From 3db9ce32faa07466fd40ab003e04a6b9553f96bf Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 19 Jul 2018 21:07:53 +0100 Subject: [PATCH 001/489] Fusee: Deployed new SDMMC driver in fusee-secondary. All stages boot now. Fusee: Fixed wrong argument in se.c function. Fusee: Improved timers. --- fusee/fusee-primary/src/gpio.c | 1 - fusee/fusee-primary/src/main.c | 14 +- fusee/fusee-primary/src/sdmmc/sdmmc.c | 37 +- fusee/fusee-primary/src/sdmmc/sdmmc.h | 1 + fusee/fusee-primary/src/sdmmc/sdmmc_core.c | 54 +- fusee/fusee-primary/src/sdmmc/sdmmc_core.h | 11 + fusee/fusee-primary/src/stage2.h | 1 - fusee/fusee-primary/src/timers.h | 38 +- fusee/fusee-secondary/Makefile | 2 +- fusee/fusee-secondary/src/apb_misc.h | 54 +- fusee/fusee-secondary/src/car.h | 236 +- fusee/fusee-secondary/src/device_partition.c | 8 +- fusee/fusee-secondary/src/fs_dev.c | 5 +- fusee/fusee-secondary/src/fs_utils.c | 2 - fusee/fusee-secondary/src/fs_utils.h | 2 +- fusee/fusee-secondary/src/fuse.c | 2 + fusee/fusee-secondary/src/fuse.h | 3 - fusee/fusee-secondary/src/gpio.c | 60 +- fusee/fusee-secondary/src/gpio.h | 149 +- fusee/fusee-secondary/src/lib/driver_utils.h | 2 +- fusee/fusee-secondary/src/lib/fatfs/diskio.c | 51 +- fusee/fusee-secondary/src/main.c | 15 +- .../src/{switch_fs.c => nxfs.c} | 180 +- fusee/fusee-secondary/src/nxfs.h | 10 + fusee/fusee-secondary/src/pad_control.h | 67 - fusee/fusee-secondary/src/panic_color.h | 4 +- fusee/fusee-secondary/src/pinmux.h | 69 +- fusee/fusee-secondary/src/pmc.h | 46 +- fusee/fusee-secondary/src/sdmmc.c | 3749 ----------------- fusee/fusee-secondary/src/sdmmc.h | 313 -- fusee/fusee-secondary/src/sdmmc/mmc.h | 448 ++ fusee/fusee-secondary/src/sdmmc/sd.h | 153 + fusee/fusee-secondary/src/sdmmc/sdmmc.c | 1528 +++++++ fusee/fusee-secondary/src/sdmmc/sdmmc.h | 161 + fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 1987 +++++++++ fusee/fusee-secondary/src/sdmmc/sdmmc_core.h | 298 ++ fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h | 154 + fusee/fusee-secondary/src/se.c | 2 +- fusee/fusee-secondary/src/se.h | 3 +- fusee/fusee-secondary/src/stage2.h | 3 +- fusee/fusee-secondary/src/supplies.c | 37 - fusee/fusee-secondary/src/supplies.h | 36 - fusee/fusee-secondary/src/switch_fs.h | 12 - fusee/fusee-secondary/src/timers.h | 41 +- 44 files changed, 5247 insertions(+), 4802 deletions(-) rename fusee/fusee-secondary/src/{switch_fs.c => nxfs.c} (68%) create mode 100644 fusee/fusee-secondary/src/nxfs.h delete mode 100644 fusee/fusee-secondary/src/pad_control.h delete mode 100644 fusee/fusee-secondary/src/sdmmc.c delete mode 100644 fusee/fusee-secondary/src/sdmmc.h create mode 100644 fusee/fusee-secondary/src/sdmmc/mmc.h create mode 100644 fusee/fusee-secondary/src/sdmmc/sd.h create mode 100644 fusee/fusee-secondary/src/sdmmc/sdmmc.c create mode 100644 fusee/fusee-secondary/src/sdmmc/sdmmc.h create mode 100644 fusee/fusee-secondary/src/sdmmc/sdmmc_core.c create mode 100644 fusee/fusee-secondary/src/sdmmc/sdmmc_core.h create mode 100644 fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h delete mode 100644 fusee/fusee-secondary/src/supplies.c delete mode 100644 fusee/fusee-secondary/src/supplies.h delete mode 100644 fusee/fusee-secondary/src/switch_fs.h diff --git a/fusee/fusee-primary/src/gpio.c b/fusee/fusee-primary/src/gpio.c index cfa2f38be..529e9fb15 100644 --- a/fusee/fusee-primary/src/gpio.c +++ b/fusee/fusee-primary/src/gpio.c @@ -4,7 +4,6 @@ #include "gpio.h" #include "utils.h" -#include "lib/printk.h" /** * Returns a GPIO bank object that corresponds to the given GPIO pin, diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 42b1c7255..c5a5a5d3c 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -4,6 +4,7 @@ #include "hwinit.h" #include "fuse.h" #include "se.h" +#include "timers.h" #include "fs_utils.h" #include "stage2.h" #include "chainloader.h" @@ -122,14 +123,7 @@ int main(void) { /* Say hello. */ printk("Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); printk("Using color linear framebuffer at 0x%p!\n", g_framebuffer); - -#ifndef I_KNOW_WHAT_I_AM_DOING -#error "Fusee is a work-in-progress bootloader, and is not ready for usage yet. If you want to play with it anyway, please #define I_KNOW_WHAT_I_AM_DOING -- and recognize that we will be unable to provide support until it is ready for general usage :)" - - printk("Warning: Fus\xe9" "e is not yet completed, and not ready for general testing!\n"); - fatal_error("Please do not seek support for it until it is done.\n"); -#endif - + /* Load the BCT0 configuration ini off of the SD. */ bct0 = load_config(); @@ -142,10 +136,12 @@ int main(void) { stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */ memcpy(&stage2_args->version, &stage2_version, 4); stage2_args->display_initialized = false; - memcpy(&stage2_args->sd_sdmmc, &g_sd_sdmmc, sizeof(g_sd_sdmmc)); strcpy(stage2_args->bct0, bct0); g_chainloader_argc = 2; + /* Wait a while. */ + mdelay(1000); + /* Deinitialize the display, console, etc. */ cleanup_env(); diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc.c b/fusee/fusee-primary/src/sdmmc/sdmmc.c index f4243d9c7..1c17988ca 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc.c @@ -189,7 +189,7 @@ static int sdmmc_device_rw(sdmmc_device_t *device, uint32_t sector, uint32_t num sdmmc_device_send_status(device); /* Wait for a while. */ - udelay(100000); + mdelay(100); } else break; @@ -504,8 +504,8 @@ static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool i /* Keep checking if timeout expired. */ is_timeout = (get_time_since(timebase) > 2000000); - /* Delay for an appropriate period. */ - udelay(10000); + /* Delay for a minimum of 10 milliseconds. */ + mdelay(10); } return 0; @@ -1161,8 +1161,8 @@ static int sdmmc_mmc_send_op_cond(sdmmc_device_t *device, SdmmcBusVoltage bus_vo /* Keep checking if timeout expired. */ is_timeout = (get_time_since(timebase) > 2000000); - /* Delay for an appropriate period. */ - udelay(10000); + /* Delay for a minimum of 10 milliseconds. */ + mdelay(10); } return 0; @@ -1357,11 +1357,23 @@ static int sdmmc_mmc_select_bkops(sdmmc_device_t *device) return sdmmc_device_send_status(device); } +int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition) +{ + uint32_t arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_PART_CONFIG) << 16) | ((partition) << 8)); + + /* Try to change the active partition. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed) { uint32_t cid[4] = {0}; uint32_t csd[4] = {0}; - uint8_t ext_csd[512] = {0}; + uint8_t *ext_csd = (uint8_t *)SDMMC_BOUNCE_BUFFER_ADDRESS; // TODO: Better way to do this. /* Initialize our device's struct. */ memset(device, 0, sizeof(sdmmc_device_t)); @@ -1376,6 +1388,9 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth /* Bind the underlying driver. */ device->sdmmc = sdmmc; + /* Set RCA. */ + device->rca = 0x01; + sdmmc_info(sdmmc, "SDMMC driver was successfully initialized for eMMC!"); /* Apply at least 74 clock cycles. eMMC should be ready afterwards. */ @@ -1408,14 +1423,14 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth sdmmc_info(sdmmc, "Got CID from eMMC!"); - /* Get the eMMC's RCA. */ + /* Set the eMMC's RCA. */ if (!sdmmc_mmc_set_relative_addr(device)) { - sdmmc_error(sdmmc, "Failed to get RCA!"); + sdmmc_error(sdmmc, "Failed to set RCA!"); return 0; } - sdmmc_info(sdmmc, "Got RCA (0x%08x) from eMMC!", device->rca); + sdmmc_info(sdmmc, "RCA is now set in eMMC!"); /* Get the eMMC card's CSD. */ if (!sdmmc_device_send_csd(device, csd)) @@ -1484,7 +1499,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth /* Decode and save the CID. */ sdmmc_mmc_decode_cid(device, cid); - + /* TODO: Handle automatic BKOPS properly. Leave it disabled for now. */ if (false && device->ext_csd.bkops && !(device->ext_csd.auto_bkops_en & EXT_CSD_AUTO_BKOPS_MASK)) { @@ -1507,4 +1522,4 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth sdmmc_adjust_sd_clock(sdmmc); return 1; -} +} \ No newline at end of file diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc.h b/fusee/fusee-primary/src/sdmmc/sdmmc.h index 6e955644b..c3a2a325b 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc.h +++ b/fusee/fusee-primary/src/sdmmc/sdmmc.h @@ -156,5 +156,6 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data); int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data); int sdmmc_device_finish(sdmmc_device_t *device); +int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition); #endif \ No newline at end of file diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c index 4637d5fc5..5b96970c9 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c @@ -14,8 +14,6 @@ #include "../lib/driver_utils.h" #include "../hwinit/max7762x.h" -#define SDMMC_BOUNCE_BUFFER_ADDRESS 0x90000000 - static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; void sdmmc_set_log_level(SdmmcLogLevel log_level) @@ -116,7 +114,7 @@ void sdmmc_dump_regs(sdmmc_t *sdmmc) sdmmc_debug(sdmmc, "max_current: 0x%08" PRIX32, sdmmc->regs->max_current); sdmmc_debug(sdmmc, "set_acmd12_error: 0x%04" PRIX16, sdmmc->regs->set_acmd12_error); sdmmc_debug(sdmmc, "set_int_error: 0x%04" PRIX16, sdmmc->regs->set_int_error); - sdmmc_debug(sdmmc, "adma_error: 0x%02" PRIX16, sdmmc->regs->adma_error); + sdmmc_debug(sdmmc, "adma_error: 0x%02" PRIX8, sdmmc->regs->adma_error); sdmmc_debug(sdmmc, "adma_address: 0x%08" PRIX32, sdmmc->regs->adma_address); sdmmc_debug(sdmmc, "upper_adma_address: 0x%08" PRIX32, sdmmc->regs->upper_adma_address); sdmmc_debug(sdmmc, "preset_for_init: 0x%04" PRIX16, sdmmc->regs->preset_for_init); @@ -700,10 +698,13 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc) /* Change to ADMA if requested. */ if (sdmmc->use_adma && (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)) { + // TODO: Setting the ADMA flags breaks ADMA... + /* if (sdmmc->regs->capabilities & SDHCI_CAN_64BIT) sdmmc->regs->host_control |= SDHCI_CTRL_ADMA64; else sdmmc->regs->host_control |= SDHCI_CTRL_ADMA32; + */ } /* Set the timeout to be the maximum value. */ @@ -1092,7 +1093,7 @@ static int sdmmc_init_controller(sdmmc_t *sdmmc, SdmmcControllerNum controller) sdmmc->is_clk_running = false; sdmmc->is_sd_clk_enabled = false; sdmmc->is_tuning_tap_val_set = false; - sdmmc->use_adma = false; + sdmmc->use_adma = true; sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; sdmmc->tap_val = 0; sdmmc->internal_divider = 0; @@ -1201,13 +1202,23 @@ void sdmmc_finish(sdmmc_t *sdmmc) /* Disable the SD clock. */ sdmmc_disable_sd_clock(sdmmc); - /* Disable SD power. */ + /* Disable SDMMC power. */ sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE); + /* Disable the SD card power. */ + if (sdmmc->controller == SDMMC_1) + { + /* Disable GPIO output. */ + gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_INPUT); + + /* Power cycle for 100ms without power. */ + mdelay(100); + } + /* Force a register read to refresh the clock control value. */ sdmmc_get_sd_clock_control(sdmmc); - /* Stop the SD clock. */ + /* Stop the SDMMC clock. */ sdmmc_clk_stop(sdmmc->controller); /* Clock is no longer running by now. */ @@ -1307,7 +1318,8 @@ static int sdmmc_wait_busy(sdmmc_t *sdmmc) static void sdmmc_intr_enable(sdmmc_t *sdmmc) { /* Set all error bits and enable the relevant interrupts. */ - sdmmc->regs->int_enable |= (0x017F0000 | (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT)); + sdmmc->regs->int_enable |= 0x017F0000; + sdmmc->regs->int_enable |= (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT); /* Refresh status. */ sdmmc->regs->int_status = sdmmc->regs->int_status; @@ -1315,11 +1327,15 @@ static void sdmmc_intr_enable(sdmmc_t *sdmmc) static void sdmmc_intr_disable(sdmmc_t *sdmmc) { - /* Clear the interrupt bits. */ - sdmmc->regs->int_enable &= ~(0x017F0000 | (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT)); + /* Clear all error bits and the interrupts. */ + sdmmc->regs->int_enable &= ~(0x017F0000); + sdmmc->regs->int_enable &= ~(TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT); + + /* Refresh status. */ + sdmmc->regs->int_status = sdmmc->regs->int_status; } -static bool sdmmc_intr_check_status(sdmmc_t *sdmmc, u16 status_mask) +static bool sdmmc_intr_check_status(sdmmc_t *sdmmc, uint16_t status_mask) { bool is_masked = (sdmmc->regs->int_status & status_mask); @@ -1353,8 +1369,8 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req) if (blkcnt >= 0xFFFF) blkcnt = 0xFFFF; - /* Point to our bounce buffer. */ - uint32_t dma_base_addr = (uint32_t)sdmmc->dma_bounce_buf; + /* Use our bounce buffer for SDMA or the request data buffer for ADMA. */ + uint32_t dma_base_addr = sdmmc->use_adma ? (uint32_t)req->data : (uint32_t)sdmmc->dma_bounce_buf; /* DMA buffer address must be aligned to 4 bytes. */ if ((4 - (dma_base_addr & 0x03)) & 0x03) @@ -1408,7 +1424,7 @@ static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req) static int sdmmc_dma_update(sdmmc_t *sdmmc) { - u16 blkcnt = 0; + uint16_t blkcnt = 0; /* Loop until all blocks have been consumed. */ do @@ -1464,7 +1480,7 @@ static int sdmmc_dma_update(sdmmc_t *sdmmc) static void sdmmc_set_cmd_flags(sdmmc_t *sdmmc, sdmmc_command_t *cmd, bool is_dma) { - u16 cmd_reg_flags = 0; + uint16_t cmd_reg_flags = 0; /* Select length flags based on response type. */ if (!(cmd->flags & SDMMC_RSP_PRESENT)) @@ -1629,8 +1645,8 @@ int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, u return 0; } - /* If this is a write operation, copy the data into our bounce buffer. */ - if (!req->is_read) + /* If this is a SDMA write operation, copy the data into our bounce buffer. */ + if (!sdmmc->use_adma && !req->is_read) memcpy((void *)sdmmc->dma_bounce_buf, (void *)req->data, req->blksz * req->num_blocks); } @@ -1659,8 +1675,8 @@ int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, u return 0; } - /* If this is a read operation, copy the data from our bounce buffer. */ - if (req->is_read) + /* If this is a SDMA read operation, copy the data from our bounce buffer. */ + if (!sdmmc->use_adma && req->is_read) { uint32_t dma_data_size = (sdmmc->regs->dma_address - (uint32_t)sdmmc->dma_bounce_buf); memcpy((void *)req->data, (void *)sdmmc->dma_bounce_buf, dma_data_size); @@ -1853,7 +1869,7 @@ static int sdmmc_send_tuning(sdmmc_t *sdmmc, uint32_t opcode) void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc) { - sdmmc->tap_val = ((sdmmc->regs->vendor_clock_cntrl & 0xFF0000) >> 16); + sdmmc->tap_val = (sdmmc->regs->vendor_clock_cntrl >> 16); sdmmc->is_tuning_tap_val_set = true; } diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.h b/fusee/fusee-primary/src/sdmmc/sdmmc_core.h index 038b80455..37dd207d1 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.h +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.h @@ -3,6 +3,9 @@ #include "sdmmc_tegra.h" +/* Bounce buffer */ +#define SDMMC_BOUNCE_BUFFER_ADDRESS 0x90000000 + /* Present state */ #define SDHCI_CMD_INHIBIT 0x00000001 #define SDHCI_DATA_INHIBIT 0x00000002 @@ -177,6 +180,14 @@ typedef enum { SDMMC_4 = 3 } SdmmcControllerNum; +typedef enum { + SDMMC_PARTITION_INVALID = -1, + SDMMC_PARTITION_USER = 0, + SDMMC_PARTITION_BOOT0 = 1, + SDMMC_PARTITION_BOOT1 = 2, + SDMMC_PARTITION_RPMB = 3 +} SdmmcPartitionNum; + typedef enum { SDMMC_VOLTAGE_NONE = 0, SDMMC_VOLTAGE_1V8 = 1, diff --git a/fusee/fusee-primary/src/stage2.h b/fusee/fusee-primary/src/stage2.h index a2a5f1dbb..7bceb7be5 100644 --- a/fusee/fusee-primary/src/stage2.h +++ b/fusee/fusee-primary/src/stage2.h @@ -21,7 +21,6 @@ typedef struct { typedef struct { uint32_t version; - sdmmc_t sd_sdmmc; bool display_initialized; char bct0[BCTO_MAX_SIZE]; } stage2_args_t; diff --git a/fusee/fusee-primary/src/timers.h b/fusee/fusee-primary/src/timers.h index c951f0427..519c0292f 100644 --- a/fusee/fusee-primary/src/timers.h +++ b/fusee/fusee-primary/src/timers.h @@ -7,6 +7,11 @@ #define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) #define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10) +#define RTC_BASE 0x7000E000 +#define RTC_SECONDS MAKE_REG32(RTC_BASE + 0x08) +#define RTC_SHADOW_SECONDS MAKE_REG32(RTC_BASE + 0x0C) +#define RTC_MILLI_SECONDS MAKE_REG32(RTC_BASE + 0x10) + typedef struct { uint32_t CONFIG; uint32_t STATUS; @@ -20,23 +25,46 @@ typedef struct { void wait(uint32_t microseconds); -static inline uint32_t get_time(void) { +static inline uint32_t get_time_s(void) { + return RTC_SECONDS; +} + +static inline uint32_t get_time_ms(void) { + return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10)); +} + +static inline uint32_t get_time_us(void) { return TIMERUS_CNTR_1US_0; } +/** + * Returns the time in microseconds. + */ +static inline uint32_t get_time(void) { + return get_time_us(); +} + /** * Returns the number of microseconds that have passed since a given get_time(). */ static inline uint32_t get_time_since(uint32_t base) { - return get_time() - base; + return get_time_us() - base; } /** * Delays for a given number of microseconds. */ -static inline void udelay(unsigned usecs) { - uint32_t start = get_time(); - while (get_time() - start < usecs); +static inline void udelay(uint32_t usecs) { + uint32_t start = get_time_us(); + while (get_time_us() - start < usecs); +} + +/** + * Delays for a given number of milliseconds. + */ +static inline void mdelay(uint32_t msecs) { + uint32_t start = get_time_ms(); + while (get_time_ms() - start < msecs); } __attribute__ ((noreturn)) void watchdog_reboot(void); diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index b200d0ae7..477dd52d0 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -21,7 +21,7 @@ include $(DEVKITARM)/base_rules #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := src src/lib src/lib/fatfs src/display src/hwinit +SOURCES := src src/sdmmc src/hwinit src/lib src/lib/fatfs src/display DATA := data INCLUDES := include diff --git a/fusee/fusee-secondary/src/apb_misc.h b/fusee/fusee-secondary/src/apb_misc.h index 278d2362f..114b7496a 100644 --- a/fusee/fusee-secondary/src/apb_misc.h +++ b/fusee/fusee-secondary/src/apb_misc.h @@ -1,15 +1,5 @@ -#ifndef __APB_MISC_H__ -#define __APB_MISC_H__ - -/* FIXME: clean up */ - -#define MISC_BASE (0x70000000UL) -#define PINMUX_BASE (MISC_BASE + 0x3000) -#define PINMUX_AUX_GPIO_PZ1_0 (*(volatile uint32_t *)(PINMUX_BASE + 0x280)) - -#define APB_MISC_GP_VGPIO_GPIO_MUX_SEL_0 MAKE_REG32(MISC_BASE + 0xb74) -#define APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL_0 MAKE_REG32(MISC_BASE + 0xa98) -#define APB_MISC_GP_EMMC4_PAD_CFGPADCTRL_0 MAKE_REG32(MISC_BASE + 0xab4) +#ifndef FUSEE_APB_MISC_H +#define FUSEE_APB_MISC_H #define SDMMC1_PAD_CAL_DRVUP_SHIFT (20) #define SDMMC1_PAD_CAL_DRVDN_SHIFT (12) @@ -21,4 +11,44 @@ #define CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT) #define CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT) +#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8) +#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4) +#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8) +#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4) +#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC1_CD_SOURCE (1 << 0) +#define PADCTL_SDMMC1_WP_SOURCE (1 << 1) +#define PADCTL_SDMMC3_CD_SOURCE (1 << 2) +#define PADCTL_SDMMC3_WP_SOURCE (1 << 3) + +typedef struct { + uint32_t asdbgreg; /* 0x810 */ + uint32_t reserved0[0x31]; + uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */ + uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */ + uint32_t emmc2_pad_cfg_control; /* 0x8DC */ + uint32_t emmc4_pad_cfg_control; /* 0x8E0 */ + uint32_t _todo0[0x6E]; + uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */ + uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */ + uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */ + uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */ + uint32_t _todo1[0x03]; + uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */ + uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */ + uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */ + uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */ + uint32_t _todo2[0x2E]; + uint32_t vgpio_gpio_mux_sel; /* 0xB74 */ + uint32_t qspi_sck_lpbk_control; /* 0xB78 */ +} tegra_padctl_t; + +static inline volatile tegra_padctl_t *padctl_get_regs(void) +{ + return (volatile tegra_padctl_t *)0x70000810; +} + #endif diff --git a/fusee/fusee-secondary/src/car.h b/fusee/fusee-secondary/src/car.h index 593c7a78a..8cc0fb139 100644 --- a/fusee/fusee-secondary/src/car.h +++ b/fusee/fusee-secondary/src/car.h @@ -1,95 +1,68 @@ +#ifndef FUSEE_CAR_H +#define FUSEE_CAR_H -#ifndef __FUSEE_CLOCK_H__ -#define __FUSEE_CLOCK_H__ +#define CLK_SOURCE_SDMMC1 20 +#define CLK_SOURCE_SDMMC2 21 +#define CLK_SOURCE_SDMMC3 47 +#define CLK_SOURCE_SDMMC4 25 +#define CLK_SOURCE_SDMMC_LEGACY 0 -#include "utils.h" +#define CLK_L_SDMMC1 (1 << 14) +#define CLK_L_SDMMC2 (1 << 9) +#define CLK_U_SDMMC3 (1 << 5) +#define CLK_L_SDMMC4 (1 << 15) -/** - * Struct definition yanked from u-boot. - */ +#define TEGRA_CLK_PLLS 6 /* Number of normal PLLs */ +#define TEGRA_CLK_SIMPLE_PLLS 3 /* Number of simple PLLs */ +#define TEGRA_CLK_SOURCES 64 /* Number of ppl clock sources L/H/U */ +#define TEGRA_CLK_SOURCES_VW 32 /* Number of ppl clock sources V/W */ +#define TEGRA_CLK_SOURCES_X 32 /* Number of ppl clock sources X */ +#define TEGRA_CLK_SOURCES_Y 18 /* Number of ppl clock sources Y */ + +#define CLK_SOURCE_MASK (0b111 << 29) +#define CLK_SOURCE_FIRST (0b000 << 29) +#define CLK_DIVIDER_MASK (0xff << 0) +#define CLK_DIVIDER_UNITY (0x00 << 0) + +#define CAR_CONTROL_SDMMC1 (1 << 14) +#define CAR_CONTROL_SDMMC4 (1 << 15) +#define CAR_CONTROL_SDMMC_LEGACY (1 << 1) /* PLL registers - there are several PLLs in the clock controller */ -struct clk_pll { +typedef struct { uint32_t pll_base; /* the control register */ + /* pll_out[0] is output A control, pll_out[1] is output B control */ uint32_t pll_out[2]; uint32_t pll_misc; /* other misc things */ -}; +} clk_pll_t; /* PLL registers - there are several PLLs in the clock controller */ -struct clk_pll_simple { +typedef struct { uint32_t pll_base; /* the control register */ uint32_t pll_misc; /* other misc things */ -}; +} clk_pll_simple_t; -struct clk_pllm { +typedef struct { uint32_t pllm_base; /* the control register */ uint32_t pllm_out; /* output control */ uint32_t pllm_misc1; /* misc1 */ uint32_t pllm_misc2; /* misc2 */ -}; - - -/* - * Most PLLs use the clk_pll structure, but some have a simpler two-member - * structure for which we use clk_pll_simple. The reason for this non- - * othogonal setup is not stated. - */ -enum { - TEGRA_CLK_PLLS = 6, /* Number of normal PLLs */ - TEGRA_CLK_SIMPLE_PLLS = 3, /* Number of simple PLLs */ - TEGRA_CLK_SOURCES = 64, /* Number of ppl clock sources L/H/U */ - TEGRA_CLK_SOURCES_VW = 32, /* Number of ppl clock sources V/W */ - TEGRA_CLK_SOURCES_X = 32, /* Number of ppl clock sources X */ - TEGRA_CLK_SOURCES_Y = 18, /* Number of ppl clock sources Y */ -}; - -/* - * Masks for TEGRA_CLK_SOURCE elements. - */ -enum { - CLK_SOURCE_MASK = (0b111 << 29), - CLK_SOURCE_SDMMC1_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */ - CLK_SOURCE_SDMMC4_PLLP_OUT0 = (0b000 << 29), /* Fixed 408 MHz */ - CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ = (0b001 << 29), /* 199.68 MHz */ - CLK_SOURCE_SDMMC_LEGACY_PLLP_OUT0 = (0b100 << 29), /* Fixed 408 MHz */ - - CLK_DIVIDER_MASK = (0xff << 0), - CLK_DIVIDER_UNITY = (0x00 << 0), -}; - - -/** - * Reset bits for relevant registers. - */ -enum { - CAR_CONTROL_SDMMC1 = (1 << 14), - CAR_CONTROL_SDMMC4 = (1 << 15), - CAR_CONTROL_SDMMC_LEGACY = (1 << 1), -}; - - -enum { - CLK_SOURCE_SDMMC1 = 20, - CLK_SOURCE_SDMMC4 = 25, /* 0x54 into the the main source block */ - - CLK_SOURCE_SDMMC_LEGACY = 0, /* first in block Y */ -}; - +} clk_pllm_t; /* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */ -struct tegra_car { +typedef struct { uint32_t rst_src; /* _RST_SOURCE_0,0x00 */ uint32_t rst_dev_l; uint32_t rst_dev_h; uint32_t rst_dev_u; - uint32_t clk_out_dev_l; - uint32_t clk_out_dev_h; - uint32_t clk_out_dev_u; + uint32_t clk_out_enb_l; + uint32_t clk_out_enb_h; + uint32_t clk_out_enb_u; - uint32_t reserved0; /* reserved_0, 0x1C */ + uint32_t reserved0; /* reserved_0, 0x1C */ uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */ uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0,0x24 */ uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */ @@ -97,21 +70,21 @@ struct tegra_car { uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */ uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */ uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0,0x38 */ - uint32_t reserved1; /* reserved_1, 0x3C */ + uint32_t reserved1; /* reserved_1, 0x3C */ uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0,0x40 */ uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */ uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */ uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4C */ - uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */ - uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */ + uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */ + uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */ uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */ uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0,0x5C */ uint32_t reserved2[8]; /* reserved_2[8], 0x60-7C */ - struct clk_pll pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */ + clk_pll_t pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */ /* PLLs from 0xe0 to 0xf4 */ - struct clk_pll_simple pll_simple[TEGRA_CLK_SIMPLE_PLLS]; + clk_pll_simple_t pll_simple[TEGRA_CLK_SIMPLE_PLLS]; uint32_t reserved10; /* _reserved_10, 0xF8 */ uint32_t reserved11; /* _reserved_11, 0xFC */ @@ -171,11 +144,11 @@ struct tegra_car { uint32_t reserved32[2]; /* _reserved_32, 0x350,0x354 */ - uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ - uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ + uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ + uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ - uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ @@ -186,8 +159,8 @@ struct tegra_car { uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ uint32_t reserved33[9]; /* _reserved_33, 0x38c-3ac */ - uint32_t clk_src_v; /* 0x3B0-0x42C */ - uint32_t clk_src_w; /* 0x3B0-0x42C */ + uint32_t clk_src_v; /* 0x3B0-0x42C */ + uint32_t clk_src_w; /* 0x3B0-0x42C */ /* _RST_DEV_V/W_SET_0 0x430 ~ 0x43c */ uint32_t rst_dev_v_set; @@ -210,18 +183,18 @@ struct tegra_car { uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */ uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */ uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46C */ - uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */ - uint32_t reserved40[1]; /* _reserved_40, 0x474 */ - uint32_t intstatus; /* __INTSTATUS_0, 0x478 */ - uint32_t intmask; /* __INTMASK_0, 0x47C */ - uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */ - uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */ - uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */ + uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */ + uint32_t reserved40[1]; /* _reserved_40, 0x474 */ + uint32_t intstatus; /* __INTSTATUS_0, 0x478 */ + uint32_t intmask; /* __INTMASK_0, 0x47C */ + uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */ + uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */ + uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */ - uint32_t plle_aux; /* _PLLE_AUX_0, 0x48C */ - uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */ - uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */ - uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */ + uint32_t plle_aux; /* _PLLE_AUX_0, 0x48C */ + uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */ + uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */ + uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */ uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49C */ uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4A0 */ @@ -231,68 +204,65 @@ struct tegra_car { uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4B0 */ uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4B4 */ - uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4B8 */ - uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4BC */ - uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4C0 */ - uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4C4 */ - uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4C8 */ + uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4B8 */ + uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4BC */ + uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4C0 */ + uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4C4 */ + uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4C8 */ uint32_t crs_reserved_50[7]; /* _reserved_50, 0x4CC-0x4E4 */ - uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4E8 */ - uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4EC */ - uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4F0 */ - uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4F4 */ - uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4F8 */ - uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4FC */ - uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */ - uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */ - uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */ - uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50C */ - uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */ - uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */ - uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */ - uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51C */ - uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */ - uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */ - uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */ + uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4E8 */ + uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4EC */ + uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4F0 */ + uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4F4 */ + uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4F8 */ + uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4FC */ + uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */ + uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */ + uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */ + uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50C */ + uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */ + uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */ + uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */ + uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51C */ + uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */ + uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */ + uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */ uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52C */ uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */ - uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */ - uint32_t reserved51[1]; /* _reserved_51, 0x538 */ - uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53C */ - uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */ - uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */ - uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */ - uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54C */ + uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */ + uint32_t reserved51[1]; /* _reserved_51, 0x538 */ + uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53C */ + uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */ + uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */ + uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */ + uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54C */ uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */ - uint32_t reserved52[1]; /* _reserved_52, 0x554 */ + uint32_t reserved52[1]; /* _reserved_52, 0x554 */ uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */ - uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55C */ - uint32_t _rsv32[4]; /* 0x560-0x56c */ - uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */ - uint32_t _rsv32_1[7]; /* 0x574-58c */ - struct clk_pll_simple plldp; /* _PLLDP_BASE, 0x590 _PLLDP_MISC */ - uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ + uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55C */ + uint32_t _rsv32[4]; /* 0x560-0x56c */ + uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */ + uint32_t _rsv32_1[7]; /* 0x574-58c */ + clk_pll_simple_t plldp; /* _PLLDP_BASE, 0x590 _PLLDP_MISC */ + uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ /* Tegra124+ - skip to 0x600 here for new CLK_SOURCE_ regs */ - uint32_t _rsrv32_2[25]; /* _0x59C - 0x5FC */ - uint32_t clk_src_x[TEGRA_CLK_SOURCES_X]; /* XUSB, etc, 0x600-0x67C */ + uint32_t _rsrv32_2[25]; /* _0x59C - 0x5FC */ + uint32_t clk_src_x[TEGRA_CLK_SOURCES_X]; /* XUSB, etc, 0x600-0x67C */ /* Tegra210 - skip to 0x694 here for new CLK_SOURCE_ regs */ - uint32_t reserved61[5]; /* _reserved_61, 0x680 - 0x690 */ + uint32_t reserved61[5]; /* _reserved_61, 0x680 - 0x690 */ + /* * NOTE: PLLA1 regs are in the middle of this Y region. Break this in * two later if PLLA1 is needed, but for now this is cleaner. */ uint32_t clk_src_y[TEGRA_CLK_SOURCES_Y]; /* SPARE1, etc, 0x694-0x6D8 */ -}; +} tegra_car_t; - -/** - * Utility function that grabs the Tegra CAR registers. - */ -static inline struct tegra_car *car_get_regs(void) +static inline volatile tegra_car_t *car_get_regs(void) { - return (struct tegra_car *)0x60006000UL; + return (volatile tegra_car_t *)0x60006000; } #endif diff --git a/fusee/fusee-secondary/src/device_partition.c b/fusee/fusee-secondary/src/device_partition.c index 5d2534bdb..b3ead91d3 100644 --- a/fusee/fusee-secondary/src/device_partition.c +++ b/fusee/fusee-secondary/src/device_partition.c @@ -1,7 +1,8 @@ #include #include "device_partition.h" -int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) { +int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) +{ int rc; if (!devpart->initialized) { rc = devpart->initializer(devpart); @@ -28,16 +29,15 @@ int device_partition_read_data(device_partition_t *devpart, void *dst, uint64_t } } -int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) { +int device_partition_write_data(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) +{ int rc; - if (!devpart->initialized) { rc = devpart->initializer(devpart); if (rc != 0) { return rc; } } - if (devpart->read_cipher != NULL && devpart->crypto_mode != DevicePartitionCryptoMode_None) { for (uint64_t i = 0; i < num_sectors; i += devpart->crypto_work_buffer_num_sectors) { uint64_t n = (i + devpart->crypto_work_buffer_num_sectors > num_sectors) ? (num_sectors - i) : devpart->crypto_work_buffer_num_sectors; diff --git a/fusee/fusee-secondary/src/fs_dev.c b/fusee/fusee-secondary/src/fs_dev.c index 39af77c98..232115510 100644 --- a/fusee/fusee-secondary/src/fs_dev.c +++ b/fusee/fusee-secondary/src/fs_dev.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -104,7 +105,7 @@ int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool fsdev_device_t *device = fsdev_find_device(name); FRESULT rc; char drname[40]; - + if (device != NULL) { errno = EEXIST; /* Device already exists */ return -1; @@ -153,7 +154,7 @@ int fsdev_mount_device(const char *name, const device_partition_t *devpart, bool VolumeStr[device - g_fsdev_devices] = FKNAM; return fsdev_convert_rc(NULL, rc); } - + device->setup = true; device->registered = false; diff --git a/fusee/fusee-secondary/src/fs_utils.c b/fusee/fusee-secondary/src/fs_utils.c index 1ea1193bb..cd188f370 100644 --- a/fusee/fusee-secondary/src/fs_utils.c +++ b/fusee/fusee-secondary/src/fs_utils.c @@ -1,8 +1,6 @@ #include #include #include "fs_utils.h" -#include "hwinit.h" -#include "sdmmc.h" size_t get_file_size(const char *filename) { struct stat st; diff --git a/fusee/fusee-secondary/src/fs_utils.h b/fusee/fusee-secondary/src/fs_utils.h index 6a100fb9d..3bf9bb92a 100644 --- a/fusee/fusee-secondary/src/fs_utils.h +++ b/fusee/fusee-secondary/src/fs_utils.h @@ -2,7 +2,7 @@ #define FUSEE_FS_UTILS_H #include "utils.h" -#include "sdmmc.h" +#include "sdmmc/sdmmc.h" size_t get_file_size(const char *filename); size_t read_from_file(void *dst, size_t dst_size, const char *filename); diff --git a/fusee/fusee-secondary/src/fuse.c b/fusee/fusee-secondary/src/fuse.c index 0999fc672..2bdfa3740 100644 --- a/fusee/fusee-secondary/src/fuse.c +++ b/fusee/fusee-secondary/src/fuse.c @@ -1,3 +1,5 @@ +#include +#include #include #include "hwinit.h" diff --git a/fusee/fusee-secondary/src/fuse.h b/fusee/fusee-secondary/src/fuse.h index 1dcbc8d60..989f564bf 100644 --- a/fusee/fusee-secondary/src/fuse.h +++ b/fusee/fusee-secondary/src/fuse.h @@ -1,9 +1,6 @@ #ifndef FUSEE_FUSE_H #define FUSEE_FUSE_H -#include -#include - typedef struct { uint32_t FUSE_CTRL; uint32_t FUSE_REG_ADDR; diff --git a/fusee/fusee-secondary/src/gpio.c b/fusee/fusee-secondary/src/gpio.c index f6572d16c..529e9fb15 100644 --- a/fusee/fusee-secondary/src/gpio.c +++ b/fusee/fusee-secondary/src/gpio.c @@ -1,19 +1,9 @@ -#include #include #include #include #include "gpio.h" - -enum tegra_gpio_shifts { - GPIO_BANK_SHIFT = 5, - GPIO_PORT_SHIFT = 3, -}; - -enum tegra_gpio_masks { - GPIO_PORT_MASK = 0x3, - GPIO_PIN_MASK = 0x7, -}; +#include "utils.h" /** * Returns a GPIO bank object that corresponds to the given GPIO pin, @@ -22,43 +12,39 @@ enum tegra_gpio_masks { * @param pin The GPIO to get the bank for. * @return The GPIO bank object to use for working with the given bank. */ -static volatile struct tegra_gpio_bank *gpio_get_bank(enum tegra_named_gpio pin) +static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin) { - volatile struct tegra_gpio *gpio = gpio_get_regs(); - int bank_number = pin >> GPIO_BANK_SHIFT; + volatile tegra_gpio_t *gpio = gpio_get_regs(); + uint32_t bank_number = pin >> GPIO_BANK_SHIFT; return &gpio->bank[bank_number]; } - /** * @return the port number for working with the given GPIO. */ -static volatile int gpio_get_port(enum tegra_named_gpio pin) +static volatile uint32_t gpio_get_port(uint32_t pin) { return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK; } - /** * @return a mask to be used to work with the given GPIO */ -static volatile uint32_t gpio_get_mask(enum tegra_named_gpio pin) +static volatile uint32_t gpio_get_mask(uint32_t pin) { uint32_t pin_number = pin & GPIO_PIN_MASK; return (1 << pin_number); } - - /** * Performs a simple GPIO configuration operation. * * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. * @param should_be_set True iff the relevant bit should be set; or false if it should be cleared. - * @param offset The offset into a gpio_bank structure + * @param offset The offset into a gpio_bank structure */ -static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_set, size_t offset) +static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset) { // Retrieve the register set that corresponds to the given pin and offset. uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset; @@ -66,10 +52,9 @@ static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_s // Figure out the offset into the cluster, // and the mask to be used. - int port = gpio_get_port(pin); + uint32_t port = gpio_get_port(pin); uint32_t mask = gpio_get_mask(pin); - // Set or clear the bit, as appropriate. if (should_be_set) cluster[port] |= mask; @@ -77,15 +62,14 @@ static void gpio_simple_register_set(enum tegra_named_gpio pin, bool should_be_s cluster[port] &= ~mask; } - /** * Performs a simple GPIO configuration operation. * * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. * @param should_be_set True iff the relevant bit should be set; or false if it should be cleared. - * @param offset The offset into a gpio_bank structure + * @param offset The offset into a gpio_bank structure */ -static bool gpio_simple_register_get(enum tegra_named_gpio pin, size_t offset) +static bool gpio_simple_register_get(uint32_t pin, uint32_t offset) { // Retrieve the register set that corresponds to the given pin and offset. uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset; @@ -93,57 +77,53 @@ static bool gpio_simple_register_get(enum tegra_named_gpio pin, size_t offset) // Figure out the offset into the cluster, // and the mask to be used. - int port = gpio_get_port(pin); + uint32_t port = gpio_get_port(pin); uint32_t mask = gpio_get_mask(pin); // Convert the given value to a boolean. return !!(cluster[port] & mask); } - /** * Configures a given pin as either GPIO or SFIO. * * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. * @param mode The relevant mode. */ -void gpio_configure_mode(enum tegra_named_gpio pin, enum tegra_gpio_mode mode) +void gpio_configure_mode(uint32_t pin, uint32_t mode) { - gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(struct tegra_gpio_bank, config)); + gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config)); } - /** * Configures a given pin as either INPUT or OUPUT. * * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. * @param direction The relevant direction. */ -void gpio_configure_direction(enum tegra_named_gpio pin, enum tegra_gpio_direction dir) +void gpio_configure_direction(uint32_t pin, uint32_t dir) { - gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(struct tegra_gpio_bank, direction)); + gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction)); } - /** * Drives a relevant GPIO pin as either HIGH or LOW. * * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. * @param mode The relevant mode. */ -void gpio_write(enum tegra_named_gpio pin, enum tegra_gpio_value value) +void gpio_write(uint32_t pin, uint32_t value) { - gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(struct tegra_gpio_bank, out)); + gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out)); } - /** * Drives a relevant GPIO pin as either HIGH or LOW. * * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. * @param mode The relevant mode. */ -enum tegra_gpio_value gpio_read(enum tegra_named_gpio pin) +uint32_t gpio_read(uint32_t pin) { - return gpio_simple_register_get(pin, offsetof(struct tegra_gpio_bank, in)); + return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in)); } diff --git a/fusee/fusee-secondary/src/gpio.h b/fusee/fusee-secondary/src/gpio.h index 581906c8b..b3da7dc56 100644 --- a/fusee/fusee-secondary/src/gpio.h +++ b/fusee/fusee-secondary/src/gpio.h @@ -1,19 +1,14 @@ -/* - * Struct defintiions lifted from NVIDIA sample code. - * (C) Copyright 2013-2015 NVIDIA Corporation - * - * adapted for Fusée by Kate Temkin -#include -#include "utils.h" - -enum tegra_gpio_port { +#define TEGRA_GPIO_PORTS 4 +#define TEGRA_GPIO_BANKS 8 +#define GPIO_BANK_SHIFT 5 +#define GPIO_PORT_SHIFT 3 +#define GPIO_PORT_MASK 0x03 +#define GPIO_PIN_MASK 0x07 + +typedef enum { TEGRA_GPIO_PORT_A = 0, TEGRA_GPIO_PORT_B = 1, TEGRA_GPIO_PORT_C = 2, @@ -46,25 +41,9 @@ enum tegra_gpio_port { TEGRA_GPIO_PORT_DD = 29, TEGRA_GPIO_PORT_EE = 30, TEGRA_GPIO_PORT_FF = 31, -}; +} tegra_gpio_port; -/** - * Convenince macro for computing a GPIO port number. - */ -#define TEGRA_GPIO(port, offset) \ - ((TEGRA_GPIO_PORT_##port * 8) + offset) - -/* - * The Tegra210 GPIO controller has 256 GPIOS in 8 banks of 4 ports, - * each with 8 GPIOs. - */ -enum { - TEGRA_GPIO_PORTS = 4, /* number of ports per bank */ - TEGRA_GPIO_BANKS = 8, /* number of banks */ -}; - -/* GPIO Controller registers for a single bank */ -struct tegra_gpio_bank { +typedef struct { uint32_t config[TEGRA_GPIO_PORTS]; uint32_t direction[TEGRA_GPIO_PORTS]; uint32_t out[TEGRA_GPIO_PORTS]; @@ -81,94 +60,40 @@ struct tegra_gpio_bank { uint32_t masked_int_enable[TEGRA_GPIO_PORTS]; uint32_t masked_int_level[TEGRA_GPIO_PORTS]; uint32_t masked_int_clear[TEGRA_GPIO_PORTS]; -}; +} tegra_gpio_bank_t; +typedef struct { + tegra_gpio_bank_t bank[TEGRA_GPIO_BANKS]; +} tegra_gpio_t; -/** - * Representation of Tegra GPIO controllers. - */ -struct tegra_gpio { - struct tegra_gpio_bank bank[TEGRA_GPIO_BANKS]; -}; - -/** - * GPIO pins that have a more detailed functional name, - * specialized for the Switch. - */ -enum tegra_named_gpio { - GPIO_MICROSD_CARD_DETECT = TEGRA_GPIO(Z, 1), - GPIO_MICROSD_WRITE_PROTECT = TEGRA_GPIO(Z, 4), - GPIO_MICROSD_SUPPLY_ENABLE = TEGRA_GPIO(E, 4), -}; - - -/** - * Mode select for GPIO or SFIO. - */ -enum tegra_gpio_mode { - GPIO_MODE_GPIO = 0, - GPIO_MODE_SFIO = 1 -}; - - -/** - * GPIO direction values - */ -enum tegra_gpio_direction { - GPIO_DIRECTION_INPUT = 0, - GPIO_DIRECTION_OUTPUT = 1 -}; - - -/** - * Active-high GPIO logic - */ -enum tegra_gpio_value { - GPIO_LEVEL_LOW = 0, - GPIO_LEVEL_HIGH = 1 -}; - - -/** - * Utility function that grabs the Tegra pinmux registers. - */ -static inline struct tegra_gpio *gpio_get_regs(void) +static inline volatile tegra_gpio_t *gpio_get_regs(void) { - return (struct tegra_gpio *)0x6000d000; + return (volatile tegra_gpio_t *)0x6000D000; } -/** - * Configures a given pin as either GPIO or SFIO. - * - * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. - * @param mode The relevant mode. - */ -void gpio_configure_mode(enum tegra_named_gpio pin, enum tegra_gpio_mode mode); +#define TEGRA_GPIO(port, offset) \ + ((TEGRA_GPIO_PORT_##port * 8) + offset) +/* Mode select */ +#define GPIO_MODE_GPIO 0 +#define GPIO_MODE_SFIO 1 -/** - * Configures a given pin as either INPUT or OUPUT. - * - * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. - * @param direction The relevant direction. - */ -void gpio_configure_direction(enum tegra_named_gpio pin, enum tegra_gpio_direction dir); +/* Direction */ +#define GPIO_DIRECTION_INPUT 0 +#define GPIO_DIRECTION_OUTPUT 1 +/* Level */ +#define GPIO_LEVEL_LOW 0 +#define GPIO_LEVEL_HIGH 1 -/** - * Drives a relevant GPIO pin as either HIGH or LOW. - * - * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. - * @param mode The relevant value. - */ -void gpio_write(enum tegra_named_gpio pin, enum tegra_gpio_value value); +/* Named GPIOs */ +#define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1) +#define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4) +#define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4) -/** - * Drives a relevant GPIO pin as either HIGH or LOW. - * - * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. - * @param mode The relevant mode. - */ -enum tegra_gpio_value gpio_read(enum tegra_named_gpio pin); +void gpio_configure_mode(uint32_t pin, uint32_t mode); +void gpio_configure_direction(uint32_t pin, uint32_t dir); +void gpio_write(uint32_t pin, uint32_t value); +uint32_t gpio_read(uint32_t pin); #endif diff --git a/fusee/fusee-secondary/src/lib/driver_utils.h b/fusee/fusee-secondary/src/lib/driver_utils.h index 8f0a22e66..2a24f67d9 100644 --- a/fusee/fusee-secondary/src/lib/driver_utils.h +++ b/fusee/fusee-secondary/src/lib/driver_utils.h @@ -5,6 +5,6 @@ #include #define vprintk vprintf -#define printk printf +#define printk printf #endif diff --git a/fusee/fusee-secondary/src/lib/fatfs/diskio.c b/fusee/fusee-secondary/src/lib/fatfs/diskio.c index 3bafa06b4..768b933b0 100644 --- a/fusee/fusee-secondary/src/lib/fatfs/diskio.c +++ b/fusee/fusee-secondary/src/lib/fatfs/diskio.c @@ -25,11 +25,10 @@ DSTATUS disk_status ( ) { device_partition_t *devpart = g_volume_to_devparts[pdrv]; - if (devpart == NULL) { - return STA_NODISK; - } else { - return devpart->initialized ? 0 : STA_NOINIT; - } + if (devpart) + return devpart->initialized ? RES_OK : STA_NOINIT; + else + return STA_NODISK; } @@ -44,14 +43,12 @@ DSTATUS disk_initialize ( { /* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */ device_partition_t *devpart = g_volume_to_devparts[pdrv]; - if (devpart == NULL) { + if (!devpart) return STA_NODISK; - } else if (devpart->initializer != NULL) { - int rc = devpart->initializer(devpart); - return rc == 0 ? 0 : STA_NOINIT; - } else { - return 0; - } + else if (devpart->initializer) + return devpart->initializer(devpart) ? STA_NOINIT : RES_OK; + else + return RES_OK; } @@ -69,14 +66,12 @@ DRESULT disk_read ( { /* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */ device_partition_t *devpart = g_volume_to_devparts[pdrv]; - if (devpart == NULL) { + if (!devpart) return RES_PARERR; - } else if (devpart->reader != NULL) { - int rc = device_partition_read_data(devpart, buff, sector, count); - return rc == 0 ? 0 : RES_ERROR; - } else { + else if (devpart->reader) + return device_partition_read_data(devpart, buff, sector, count) ? RES_ERROR : RES_OK; + else return RES_ERROR; - } } @@ -94,14 +89,12 @@ DRESULT disk_write ( { /* We aren't using FF_MULTI_PARTITION, so pdrv = volume id. */ device_partition_t *devpart = g_volume_to_devparts[pdrv]; - if (devpart == NULL) { + if (!devpart) return RES_PARERR; - } else if (devpart->writer != NULL) { - int rc = device_partition_write_data(devpart, buff, sector, count); - return rc == 0 ? 0 : RES_ERROR; - } else { + else if (devpart->writer) + return device_partition_write_data(devpart, buff, sector, count) ? RES_ERROR : RES_OK; + else return RES_ERROR; - } } @@ -118,11 +111,11 @@ DRESULT disk_ioctl ( { device_partition_t *devpart = g_volume_to_devparts[pdrv]; switch (cmd) { - case GET_SECTOR_SIZE: - *(WORD *)buff = devpart != NULL ? (WORD)devpart->sector_size : 512; - return 0; - default: - return 0; + case GET_SECTOR_SIZE: + *(WORD *)buff = devpart ? (WORD)devpart->sector_size : 512; + return RES_OK; + default: + return RES_OK; } } diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 8218c8cd7..d6aa5191a 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -12,9 +12,10 @@ #include "nxboot.h" #include "console.h" #include "fs_utils.h" -#include "switch_fs.h" +#include "nxfs.h" #include "gpt.h" #include "display/video_fb.h" +#include "sdmmc/sdmmc.h" extern void (*__program_exit_callback)(int rc); @@ -30,7 +31,7 @@ static void setup_env(void) { /* Set up exception handlers. */ setup_exception_handlers(); - if(/*switchfs_import_mmc_structs(&g_stage2_args->sd_mmc, NULL) == -1 ||*/ switchfs_mount_all() == -1) { + if (nxfs_mount_all() < 0) { fatal_error("Failed to mount at least one parition: %s\n", strerror(errno)); } @@ -39,7 +40,7 @@ static void setup_env(void) { static void cleanup_env(void) { /* Unmount everything (this causes all open files to be flushed and closed) */ - switchfs_unmount_all(); + nxfs_unmount_all(); //console_end(); } @@ -61,12 +62,16 @@ int main(int argc, void **argv) { if (argc != STAGE2_ARGC) { generic_panic(); } + g_stage2_args = (stage2_args_t *)argv[STAGE2_ARGV_ARGUMENT_STRUCT]; - if(g_stage2_args->version != 0) { + if (g_stage2_args->version != 0) { generic_panic(); } - + + /* Set the SDMMC's driver logging level. */ + sdmmc_set_log_level(SDMMC_LOG_INFO); + /* Initialize the display, console, FS, etc. */ setup_env(); diff --git a/fusee/fusee-secondary/src/switch_fs.c b/fusee/fusee-secondary/src/nxfs.c similarity index 68% rename from fusee/fusee-secondary/src/switch_fs.c rename to fusee/fusee-secondary/src/nxfs.c index 50f5a0a67..1420e73a4 100644 --- a/fusee/fusee-secondary/src/switch_fs.c +++ b/fusee/fusee-secondary/src/nxfs.c @@ -2,31 +2,40 @@ #include #include #include -#include "switch_fs.h" +#include +#include "nxfs.h" #include "gpt.h" -#include "sdmmc.h" #include "se.h" #include "hwinit.h" +#include "utils.h" +#include "sdmmc/sdmmc.h" static bool g_ahb_redirect_enabled = false; -static bool g_sd_mmc_initialized = false; -static bool g_nand_mmc_initialized = false; +static bool g_sd_device_initialized = false; +static bool g_emmc_device_initialized = false; -static bool g_sd_mmc_imported = false; -static bool g_nand_mmc_imported = false; +static sdmmc_t g_sd_sdmmc = {0}; +static sdmmc_t g_emmc_sdmmc = {0}; -static struct mmc g_sd_mmc = {0}; -static struct mmc g_nand_mmc = {0}; +static sdmmc_device_t g_sd_device = {0}; +static sdmmc_device_t g_emmc_device = {0}; typedef struct mmc_partition_info_t { - struct mmc *mmc; - enum sdmmc_controller controller; - enum sdmmc_partition mmc_partition; + sdmmc_device_t *device; + SdmmcControllerNum controller; + SdmmcPartitionNum partition; } mmc_partition_info_t; +static mmc_partition_info_t g_sd_mmcpart = {&g_sd_device, SDMMC_1, SDMMC_PARTITION_USER}; +static mmc_partition_info_t g_emmc_boot0_mmcpart = {&g_emmc_device, SDMMC_4, SDMMC_PARTITION_BOOT0}; +static mmc_partition_info_t g_emmc_boot1_mmcpart = {&g_emmc_device, SDMMC_4, SDMMC_PARTITION_BOOT1}; +static mmc_partition_info_t g_emmc_user_mmcpart = {&g_emmc_device, SDMMC_4, SDMMC_PARTITION_USER}; + +SdmmcPartitionNum g_current_emmc_partition = SDMMC_PARTITION_INVALID; + static int mmc_partition_initialize(device_partition_t *devpart) { mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct; - + if (devpart->read_cipher != NULL || devpart->write_cipher != NULL) { devpart->crypto_work_buffer = memalign(16, devpart->sector_size * 16); if (devpart->crypto_work_buffer == NULL) { @@ -44,27 +53,21 @@ static int mmc_partition_initialize(device_partition_t *devpart) { g_ahb_redirect_enabled = true; } - if (mmcpart->mmc == &g_sd_mmc) { - if (!g_sd_mmc_initialized) { - int rc = g_sd_mmc_imported ? 0 : sdmmc_init(mmcpart->mmc, mmcpart->controller, true); - if (rc == 0) { - sdmmc_set_write_enable(mmcpart->mmc, SDMMC_WRITE_ENABLED); - g_sd_mmc_initialized = true; - } - else { + if (mmcpart->device == &g_sd_device) { + if (!g_sd_device_initialized) { + int rc = sdmmc_device_sd_init(mmcpart->device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SDR104) ? 0 : EIO; + if (rc) return rc; - } + g_sd_device_initialized = true; } devpart->initialized = true; return 0; - } else if (mmcpart->mmc == &g_nand_mmc) { - if (!g_nand_mmc_initialized) { - int rc = g_nand_mmc_imported ? 0 : sdmmc_init(mmcpart->mmc, mmcpart->controller, true); - if (rc == 0) { - g_nand_mmc_initialized = true; - } else { + } else if (mmcpart->device == &g_emmc_device) { + if (!g_emmc_device_initialized) { + int rc = sdmmc_device_mmc_init(mmcpart->device, &g_emmc_sdmmc, SDMMC_BUS_WIDTH_8BIT, SDMMC_SPEED_HS400) ? 0 : EIO; + if (rc) return rc; - } + g_emmc_device_initialized = true; } devpart->initialized = true; return 0; @@ -77,34 +80,31 @@ static void mmc_partition_finalize(device_partition_t *devpart) { free(devpart->crypto_work_buffer); } -static enum sdmmc_partition g_current_emmc_partition = (enum sdmmc_partition)-1; - static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) { mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct; - if (mmcpart->mmc == &g_nand_mmc && g_current_emmc_partition != mmcpart->mmc_partition) { - int rc = sdmmc_select_partition(mmcpart->mmc, mmcpart->mmc_partition); - if (rc != 0 && rc != ENOTTY) { - return rc; - } - g_current_emmc_partition = mmcpart->mmc_partition; + + if ((mmcpart->device == &g_emmc_device) && (g_current_emmc_partition != mmcpart->partition)) { + if (!sdmmc_mmc_select_partition(mmcpart->device, mmcpart->partition)) + return EIO; + g_current_emmc_partition = mmcpart->partition; } - return sdmmc_read(mmcpart->mmc, dst, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors); + + return sdmmc_device_read(mmcpart->device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, dst) ? 0 : EIO; } static int mmc_partition_write(device_partition_t *devpart, const void *src, uint64_t sector, uint64_t num_sectors) { mmc_partition_info_t *mmcpart = (mmc_partition_info_t *)devpart->device_struct; - if (mmcpart->mmc == &g_nand_mmc && g_current_emmc_partition != mmcpart->mmc_partition) { - int rc = sdmmc_select_partition(mmcpart->mmc, mmcpart->mmc_partition); - if (rc != 0 && rc != ENOTTY) { - return rc; - } - g_current_emmc_partition = mmcpart->mmc_partition; + + if ((mmcpart->device == &g_emmc_device) && (g_current_emmc_partition != mmcpart->partition)) { + if (!sdmmc_mmc_select_partition(mmcpart->device, mmcpart->partition)) + return EIO; + g_current_emmc_partition = mmcpart->partition; } - return sdmmc_write(mmcpart->mmc, src, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors); + return sdmmc_device_write(mmcpart->device, (uint32_t)(devpart->start_sector + sector), (uint32_t)num_sectors, (void *)src) ? 0 : EIO; } -static int switchfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) { +static int nxfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) { unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */ unsigned int keyslot_b = 5; size_t size = num_sectors * devpart->sector_size; @@ -124,7 +124,7 @@ static int switchfs_bis_crypto_decrypt(device_partition_t *devpart, uint64_t sec } } -static int switchfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) { +static int nxfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sector, uint64_t num_sectors) { unsigned int keyslot_a = 4; /* These keyslots are never used by exosphere, and should be safe. */ unsigned int keyslot_b = 5; size_t size = num_sectors * devpart->sector_size; @@ -144,11 +144,6 @@ static int switchfs_bis_crypto_encrypt(device_partition_t *devpart, uint64_t sec } } -static mmc_partition_info_t g_sd_mmcpart = { &g_sd_mmc, SWITCH_MICROSD, SDMMC_PARTITION_USER }; -static mmc_partition_info_t g_nand_boot0_mmcpart = { &g_nand_mmc, SWITCH_EMMC, SDMMC_PARTITION_BOOT0 }; -static mmc_partition_info_t g_nand_boot1_mmcpart = { &g_nand_mmc, SWITCH_EMMC, SDMMC_PARTITION_BOOT1 }; -static mmc_partition_info_t g_nand_user_mmcpart = { &g_nand_mmc, SWITCH_EMMC, SDMMC_PARTITION_USER }; - static const device_partition_t g_mmc_devpart_template = { .sector_size = 512, .initializer = mmc_partition_initialize, @@ -157,7 +152,7 @@ static const device_partition_t g_mmc_devpart_template = { .writer = mmc_partition_write, }; -static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk) { +static int nxfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *param, size_t entry_offset, FILE *disk) { (void)entry_offset; (void)disk; device_partition_t *parent = (device_partition_t *)param; @@ -204,8 +199,8 @@ static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void } if (known_partitions[i].is_encrypted) { - devpart.read_cipher = switchfs_bis_crypto_decrypt; - devpart.write_cipher = switchfs_bis_crypto_encrypt; + devpart.read_cipher = nxfs_bis_crypto_decrypt; + devpart.write_cipher = nxfs_bis_crypto_encrypt; devpart.crypto_mode = DevicePartitionCryptoMode_Xts; } @@ -238,37 +233,7 @@ static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void return 0; } -int switchfs_import_mmc_structs(void *sd, void *nand) { - if (sd != NULL) { - int rc = 0; - memcpy(&g_sd_mmc, sd, sizeof(g_sd_mmc)); - rc = sdmmc_import_struct(&g_sd_mmc); - if (rc != 0) { - memset(&g_sd_mmc, 0, sizeof(g_sd_mmc)); - errno = rc; - return -1; - } else { - g_sd_mmc_imported = true; - } - } - - if (nand != NULL) { - int rc = 0; - memcpy(&g_nand_mmc, nand, sizeof(g_nand_mmc)); - rc = sdmmc_import_struct(&g_nand_mmc); - if (rc != 0) { - memset(&g_nand_mmc, 0, sizeof(g_nand_mmc)); - errno = rc; - return -1; - } else { - g_nand_mmc_imported = true; - } - } - - return 0; -} - -int switchfs_mount_all(void) { +int nxfs_mount_all(void) { device_partition_t model; int rc; FILE *rawnand; @@ -278,63 +243,80 @@ int switchfs_mount_all(void) { model.device_struct = &g_sd_mmcpart; model.start_sector = 0; model.num_sectors = 1u << 30; /* arbitrary numbers of sectors. TODO: find the size of the SD in sectors. */ + rc = fsdev_mount_device("sdmc", &model, true); + if (rc == -1) { return -1; } + rc = fsdev_register_device("sdmc"); + if (rc == -1) { return -1; } /* Boot0. */ model = g_mmc_devpart_template; - model.device_struct = &g_nand_boot0_mmcpart; + model.device_struct = &g_emmc_boot0_mmcpart; model.start_sector = 0; model.num_sectors = 0x184000 / model.sector_size; + rc = rawdev_mount_device("boot0", &model, true); + if (rc == -1) { return -1; } + rc = rawdev_register_device("boot0"); + + if (rc == -1) { + return -1; + } + + /* Boot1. */ + model = g_mmc_devpart_template; + model.device_struct = &g_emmc_boot1_mmcpart; + model.start_sector = 0; + model.num_sectors = 0x80000 / model.sector_size; + + rc = rawdev_mount_device("boot1", &model, false); + if (rc == -1) { return -1; } - /* Boot1. */ - model = g_mmc_devpart_template; - model.device_struct = &g_nand_boot1_mmcpart; - model.start_sector = 0; - model.num_sectors = 0x80000 / model.sector_size; - rc = rawdev_mount_device("boot1", &model, false); - if (rc == -1) { - return -1; - } /* Don't register boot1 for now. */ /* Raw NAND (excluding boot partitions), and its partitions. */ model = g_mmc_devpart_template; model = g_mmc_devpart_template; - model.device_struct = &g_nand_user_mmcpart; + model.device_struct = &g_emmc_user_mmcpart; model.start_sector = 0; model.num_sectors = (32ull << 30) / model.sector_size; + rc = rawdev_mount_device("rawnand", &model, false); + if (rc == -1) { return -1; } + rc = rawdev_register_device("rawnand"); if (rc == -1) { return -1; } + rawnand = fopen("rawnand:/", "rb"); - rc = gpt_iterate_through_entries(rawnand, model.sector_size, switchfs_mount_partition_gpt_callback, &model); + rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); fclose(rawnand); + if (rc == 0) { rc = fsdev_set_default_device("sdmc"); } + return rc; } -int switchfs_unmount_all(void) { - return fsdev_unmount_all() != 0 || rawdev_unmount_all() != 0 ? -1 : 0; +int nxfs_unmount_all(void) { + return ((fsdev_unmount_all() || rawdev_unmount_all()) ? -1 : 0); } diff --git a/fusee/fusee-secondary/src/nxfs.h b/fusee/fusee-secondary/src/nxfs.h new file mode 100644 index 000000000..bbb745814 --- /dev/null +++ b/fusee/fusee-secondary/src/nxfs.h @@ -0,0 +1,10 @@ +#ifndef FUSEE_NX_FS_H +#define FUSEE_NX_FS_H + +#include "fs_dev.h" +#include "raw_dev.h" + +int nxfs_mount_all(void); +int nxfs_unmount_all(void); + +#endif diff --git a/fusee/fusee-secondary/src/pad_control.h b/fusee/fusee-secondary/src/pad_control.h deleted file mode 100644 index a1ba93ae8..000000000 --- a/fusee/fusee-secondary/src/pad_control.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Fusée pad control code - * ~ktemkin - */ - -#ifndef __FUSEE_PADCTL_H__ -#define __FUSEE_PADCTL_H__ - -#include "utils.h" - -/** - * Registers in the Misc Pad control region - */ -struct tegra_padctl { - /* TODO: support registers before? */ - uint32_t sdmmc1_control; - uint32_t sdmmc3_control; - uint32_t sdmmc2_control; - uint32_t sdmmc4_control; - - /* TODO: support registers after? */ - uint8_t _todo[656]; - - uint32_t vgpio_gpio_mux_sel; -}; - -/** - * Masks for Pad Control registers - */ -enum tegra_padctl_masks { - - /* SDMMC1 */ - PADCTL_SDMMC1_DEEP_LOOPBACK = (1 << 0), - - /* SDMMC3 */ - PADCTL_SDMMC3_DEEP_LOOPBACK = (1 << 0), - - /* SDMMC2 */ - PADCTL_SDMMC2_ENABLE_DATA_IN = (0xFF << 8), - PADCTL_SDMMC2_ENABLE_CLK_IN = (0x3 << 4), - PADCTL_SDMMC2_DEEP_LOOPBACK = (1 << 0), - - /* SDMMC4 */ - PADCTL_SDMMC4_ENABLE_DATA_IN = (0xFF << 8), - PADCTL_SDMMC4_ENABLE_CLK_IN = (0x3 << 4), - PADCTL_SDMMC4_DEEP_LOOPBACK = (1 << 0), - - /* VGPIO/GPIO */ - PADCTL_SDMMC1_CD_SOURCE = (1 << 0), - PADCTL_SDMMC1_WP_SOURCE = (1 << 1), - PADCTL_SDMMC3_CD_SOURCE = (1 << 2), - PADCTL_SDMMC3_WP_SOURCE = (1 << 3), - - -}; - - -/** - * Utility function that grabs the Tegra PADCTL registers. - */ -static inline struct tegra_padctl *padctl_get_regs(void) -{ - return (struct tegra_padctl *)0x700008d4; -} - - -#endif diff --git a/fusee/fusee-secondary/src/panic_color.h b/fusee/fusee-secondary/src/panic_color.h index a310b139b..a87cfdeb6 100644 --- a/fusee/fusee-secondary/src/panic_color.h +++ b/fusee/fusee-secondary/src/panic_color.h @@ -1,5 +1,5 @@ -#ifndef EXOSPHERE_PANIC_COLOR_H -#define EXOSPHERE_PANIC_COLOR_H +#ifndef FUSEE_PANIC_COLOR_H +#define FUSEE_PANIC_COLOR_H #define COLOR_0 0x00F00003 #define COLOR_1 0x0F000003 diff --git a/fusee/fusee-secondary/src/pinmux.h b/fusee/fusee-secondary/src/pinmux.h index d583eaf9a..d7131d1d5 100644 --- a/fusee/fusee-secondary/src/pinmux.h +++ b/fusee/fusee-secondary/src/pinmux.h @@ -1,14 +1,22 @@ -#ifndef __FUSEE_PINMUX_H__ -#define __FUSEE_PINMUX_H__ +#ifndef FUSEE_PINMUX_H +#define FUSEE_PINMUX_H -#include -#include -#include "utils.h" +#define PINMUX_TRISTATE (1 << 4) +#define PINMUX_PARKED (1 << 5) +#define PINMUX_INPUT (1 << 6) +#define PINMUX_PULL_NONE (0 << 2) +#define PINMUX_PULL_DOWN (1 << 2) +#define PINMUX_PULL_UP (2 << 2) +#define PINMUX_SELECT_FUNCTION0 0 +#define PINMUX_SELECT_FUNCTION1 1 +#define PINMUX_SELECT_FUNCTION2 2 +#define PINMUX_SELECT_FUNCTION3 3 +#define PINMUX_DRIVE_1X (0 << 13) +#define PINMUX_DRIVE_2X (1 << 13) +#define PINMUX_DRIVE_3X (2 << 13) +#define PINMUX_DRIVE_4X (3 << 13) -/** - * Pinmux structures. - */ -struct tegra_pinmux { +typedef struct { uint32_t sdmmc1_clk; uint32_t sdmmc1_cmd; uint32_t sdmmc1_dat3; @@ -174,48 +182,11 @@ struct tegra_pinmux { uint32_t pz3; uint32_t pz4; uint32_t pz5; -}; +} tegra_pinmux_t; -/** - * Constants for use of the Tegra Pinmux. - */ -enum tegra_pinmux_constants { - - /* Tristate (output buffer) control */ - PINMUX_TRISTATE = (1 << 4), - - /* Park control */ - PINMUX_PARKED = (1 << 5), - - /* Input control */ - PINMUX_INPUT = (1 << 6), - - /* Pull resistors */ - PINMUX_PULL_NONE = (0 << 2), - PINMUX_PULL_DOWN = (1 << 2), - PINMUX_PULL_UP = (2 << 2), - - /* Function select */ - PINMUX_SELECT_FUNCTION0 = 0, - PINMUX_SELECT_FUNCTION1 = 1, - PINMUX_SELECT_FUNCTION2 = 2, - PINMUX_SELECT_FUNCTION3 = 3, - - /* Drive */ - PINMUX_DRIVE_1X = (0x0 << 13), - PINMUX_DRIVE_2X = (0x1 << 13), - PINMUX_DRIVE_3X = (0x2 << 13), - PINMUX_DRIVE_4X = (0x3 << 13), -}; - - -/** - * Utility function that grabs the Tegra pinmux registers. - */ -static inline struct tegra_pinmux *pinmux_get_regs(void) +static inline volatile tegra_pinmux_t *pinmux_get_regs(void) { - return (struct tegra_pinmux *)0x70003000; + return (volatile tegra_pinmux_t *)0x70003000; } - #endif diff --git a/fusee/fusee-secondary/src/pmc.h b/fusee/fusee-secondary/src/pmc.h index 1a1a8b30a..4c10d1a0e 100644 --- a/fusee/fusee-secondary/src/pmc.h +++ b/fusee/fusee-secondary/src/pmc.h @@ -1,37 +1,27 @@ -#ifndef __FUSEE_PMC_H__ -#define __FUSEE_PMC_H__ - -#include "utils.h" - -#define PMC_BASE 0x7000E400 - +#ifndef FUSEE_PMC_H +#define FUSEE_PMC_H /* TODO: get rid of these defines; use the struct instead */ +#define PMC_BASE 0x7000E400 + +#define PMC_CONTROL_SDMMC1 (1 << 12) +#define PMC_CONTROL_SDMMC3 (1 << 13) +#define PMC_CONTROL_SDMMC4 (1 << 14) + #define APBDEV_PMC_CONTROL MAKE_REG32(PMC_BASE + 0x00) - #define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24) - #define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30) #define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_REG32(PMC_BASE + 0x38) - #define APBDEV_PMC_SCRATCH0_0 MAKE_REG32(PMC_BASE + 0x50) - #define APBDEV_PMC_CRYPTO_OP_0 MAKE_REG32(PMC_BASE + 0xF4) - #define APBDEV_PM_0 MAKE_REG32(PMC_BASE + 0x14) #define APBDEV_PMC_WAKE2_STATUS_0 MAKE_REG32(PMC_BASE + 0x168) #define APBDEV_PMC_RST_STATUS_0 MAKE_REG32(PMC_BASE + 0x1B4) #define APBDEV_PMC_CNTRL2_0 MAKE_REG32(PMC_BASE + 0x440) - #define APBDEV_PMC_SCRATCH43_0 MAKE_REG32(PMC_BASE + 0x22C) - #define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840) -/** - * Definitions of the Tegra PMC. - * NOTE: Incomplete, do not use - */ -struct tegra_pmc { +typedef struct { uint32_t cntrl; uint32_t sec_disable; uint32_t pmc_swrst; @@ -297,23 +287,11 @@ struct tegra_pmc { uint32_t scratch118; uint32_t scratch119; uint32_t scratch1_eco; -}; +} tegra_pmc_t; -enum tegra_pmc_masks { - /* NO_IOPOWER, power detect, ect. */ - PMC_CONTROL_SDMMC1 = (1 << 12), - PMC_CONTROL_SDMMC3 = (1 << 13), - PMC_CONTROL_SDMMC4 = (1 << 14), -}; - - -/** - * Utility function that grabs the Tegra PMC registers. - */ -static inline volatile struct tegra_pmc *pmc_get_regs(void) +static inline volatile tegra_pmc_t *pmc_get_regs(void) { - return (volatile struct tegra_pmc *)0x7000E400; + return (volatile tegra_pmc_t *)0x7000E400; } - #endif diff --git a/fusee/fusee-secondary/src/sdmmc.c b/fusee/fusee-secondary/src/sdmmc.c deleted file mode 100644 index e34b17f60..000000000 --- a/fusee/fusee-secondary/src/sdmmc.c +++ /dev/null @@ -1,3749 +0,0 @@ -/** - * Fusée SD/MMC driver for the Switch - * ~ktemkin - */ - -#include -#include -#include -#include - -#include "lib/driver_utils.h" -#include "sdmmc.h" -#include "car.h" -#include "pinmux.h" -#include "timers.h" -#include "apb_misc.h" -#include "gpio.h" -#include "supplies.h" -#include "pmc.h" -#include "pad_control.h" -#include "apb_misc.h" -#define TEGRA_SDMMC_BASE (0x700B0000) -#define TEGRA_SDMMC_SIZE (0x200) - - -/** - * Map of tegra SDMMC registers - */ -struct tegra_sdmmc { - - /* SDHCI standard registers */ - uint32_t dma_address; - uint16_t block_size; - uint16_t block_count; - uint32_t argument; - uint16_t transfer_mode; - uint16_t command; - uint32_t response[0x4]; - uint32_t buffer; - uint32_t present_state; - uint8_t host_control; - uint8_t power_control; - uint8_t block_gap_control; - uint8_t wake_up_control; - uint16_t clock_control; - uint8_t timeout_control; - uint8_t software_reset; - uint32_t int_status; - uint32_t int_enable; - uint32_t signal_enable; - uint16_t acmd12_err; - uint16_t host_control2; - uint32_t capabilities; - uint32_t capabilities_1; - uint32_t max_current; - uint32_t _0x4c; - uint16_t set_acmd12_error; - uint16_t set_int_error; - uint16_t adma_error; - uint8_t _0x56[0x2]; - uint32_t adma_address; - uint32_t upper_adma_address; - uint16_t preset_for_init; - uint16_t preset_for_default; - uint16_t preset_for_high; - uint16_t preset_for_sdr12; - uint16_t preset_for_sdr25; - uint16_t preset_for_sdr50; - uint16_t preset_for_sdr104; - uint16_t preset_for_ddr50; - uint8_t _0x70[0x4]; - uint32_t _0x74[0x22]; - uint16_t slot_int_status; - uint16_t host_version; - - /* vendor specific registers */ - uint32_t vendor_clock_cntrl; - uint32_t vendor_sys_sw_cntrl; - uint32_t vendor_err_intr_status; - uint32_t vendor_cap_overrides; - uint32_t vendor_boot_cntrl; - uint32_t vendor_boot_ack_timeout; - uint32_t vendor_boot_dat_timeout; - uint32_t vendor_debounce_count; - uint32_t vendor_misc_cntrl; - uint32_t max_current_override; - uint32_t max_current_override_hi; - uint32_t _0x12c[0x20]; - uint32_t vendor_io_trim_cntrl; - - /* start of sdmmc2/sdmmc4 only */ - uint32_t vendor_dllcal_cfg; - uint32_t vendor_dll_ctrl0; - uint32_t vendor_dll_ctrl1; - uint32_t vendor_dllcal_cfg_sta; - /* end of sdmmc2/sdmmc4 only */ - - uint32_t vendor_tuning_cntrl0; - uint32_t vendor_tuning_cntrl1; - uint32_t vendor_tuning_status0; - uint32_t vendor_tuning_status1; - uint32_t vendor_clk_gate_hysteresis_count; - uint32_t vendor_preset_val0; - uint32_t vendor_preset_val1; - uint32_t vendor_preset_val2; - uint32_t sdmemcomppadctrl; - uint32_t auto_cal_config; - uint32_t auto_cal_interval; - uint32_t auto_cal_status; - uint32_t io_spare; - uint32_t sdmmca_mccif_fifoctrl; - uint32_t timeout_wcoal_sdmmca; - uint32_t _0x1fc; -}; - -/** - * SDMMC response lengths - */ -enum sdmmc_response_type { - MMC_RESPONSE_NONE = 0, - MMC_RESPONSE_LEN136 = 1, - MMC_RESPONSE_LEN48 = 2, - MMC_RESPONSE_LEN48_CHK_BUSY = 3, - -}; - -/** - * Lengths of SD command responses - */ -enum sdmmc_constants { - /* Bytes in a LEN136 response */ - MMC_RESPONSE_SIZE_LEN136 = 15, -}; - -/** - * SDMMC clock divider constants - */ -enum sdmmc_clock_dividers { - - /* Clock dividers: SD */ - MMC_CLOCK_DIVIDER_SDR12 = 31, // 16.5, from the TRM table - MMC_CLOCK_DIVIDER_SDR25 = 15, // 8.5, from the table - MMC_CLOCK_DIVIDER_SDR50 = 7, // 4.5, from the table - MMC_CLOCK_DIVIDER_SDR104 = 2, // 2, from the table - - /* Clock dividers: MMC */ - MMC_CLOCK_DIVIDER_HS26 = 30, // 16, from the TRM table - MMC_CLOCK_DIVIDER_HS52 = 14, // 8, from the table - -#if 0 - // TODO: Figure out why PLLC4_OUT2_LJ doesn't work, most likely need to be enabled in hwinit - MMC_CLOCK_DIVIDER_HS200 = 0, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ - MMC_CLOCK_DIVIDER_HS400 = 0, // 1 -- NOTE THIS IS WITH RESPECT TO PLLC4_OUT2_LJ -#else - MMC_CLOCK_DIVIDER_HS200 = 3, - MMC_CLOCK_DIVIDER_HS400 = 3, -#endif - - /* Clock dividers: Legacy 12 MHz timer */ - MMC_CLOCK_DIVIDER_LEGACY = 66, // 34 - to get 12 MHz out of 408 MHz -}; - -/** - * SDMMC clock divider constants - */ -enum sdmmc_clock_sources { - - /* Clock sources: SD */ - MMC_CLOCK_SOURCE_SDR12 = CLK_SOURCE_SDMMC1_PLLP_OUT0, // PLLP - MMC_CLOCK_SOURCE_SDR25 = CLK_SOURCE_SDMMC1_PLLP_OUT0, - MMC_CLOCK_SOURCE_SDR50 = CLK_SOURCE_SDMMC1_PLLP_OUT0, - MMC_CLOCK_SOURCE_SDR104 = CLK_SOURCE_SDMMC1_PLLP_OUT0, - - /* Clock sources: MMC */ - MMC_CLOCK_SOURCE_HS26 = CLK_SOURCE_SDMMC4_PLLP_OUT0, // PLLP - MMC_CLOCK_SOURCE_HS52 = CLK_SOURCE_SDMMC4_PLLP_OUT0, - -#if 0 - // TODO: Figure out why PLLC4_OUT2_LJ doesn't work, most likely need to be enabled in hwinit - MMC_CLOCK_SOURCE_HS200 = CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ, // PLLC4_OUT2_LJ - MMC_CLOCK_SOURCE_HS400 = CLK_SOURCE_SDMMC4_PLLC4_OUT2_LJ, -#else - // For the time being, use PLLP_OUT0 - MMC_CLOCK_SOURCE_HS200 = CLK_SOURCE_SDMMC4_PLLP_OUT0, - MMC_CLOCK_SOURCE_HS400 = CLK_SOURCE_SDMMC4_PLLP_OUT0, -#endif - - /* Clock sources: Legacy 12 MHz timer */ - MMC_CLOCK_SOURCE_LEGACY = CLK_SOURCE_SDMMC_LEGACY_PLLP_OUT0, -}; - -/** - * SDMMC response sanity checks - * see the standard for when these should be used - */ -enum sdmmc_response_checks { - MMC_CHECKS_NONE = 0, - MMC_CHECKS_CRC = (1 << 3), - MMC_CHECKS_INDEX = (1 << 4), - MMC_CHECKS_ALL = (1 << 4) | (1 << 3), -}; - -/** - * General masks for SDMMC registers. - */ -enum sdmmc_register_bits { - - /* Present state register */ - MMC_COMMAND_INHIBIT = (1 << 0), - MMC_DATA_INHIBIT = (1 << 1), - MMC_BUFFER_WRITE_ENABLE = (1 << 10), - MMC_BUFFER_READ_ENABLE = (1 << 11), - MMC_DAT0_LINE_STATE = (1 << 20), - MMC_READ_ACTIVE = (1 << 9), - MMC_WRITE_ACTIVE = (1 << 8), - - /* Block size register */ - MMC_DMA_BOUNDARY_MAXIMUM = (0x7 << 12), - MMC_DMA_BOUNDARY_512K = (0x7 << 12), - MMC_DMA_BOUNDARY_64K = (0x4 << 12), - MMC_DMA_BOUNDARY_32K = (0x3 << 12), - MMC_DMA_BOUNDARY_16K = (0x2 << 12), - MMC_DMA_BOUNDARY_8K = (0x1 << 12), - MMC_DMA_BOUNDARY_4K = (0x0 << 12), - MMC_TRANSFER_BLOCK_512B = (0x200 << 0), - - /* Command register */ - MMC_COMMAND_NUMBER_SHIFT = 8, - MMC_COMMAND_RESPONSE_TYPE_SHIFT = 0, - MMC_COMMAND_HAS_DATA = 1 << 5, - MMC_COMMAND_TYPE_ABORT = 3 << 6, - MMC_COMMAND_CHECK_NUMBER = 1 << 4, - - /* Transfer mode arguments */ - MMC_TRANSFER_DMA_ENABLE = (1 << 0), - MMC_TRANSFER_LIMIT_BLOCK_COUNT = (1 << 1), - MMC_TRANSFER_MULTIPLE_BLOCKS = (1 << 5), - MMC_TRANSFER_AUTO_CMD_MASK = (0x3 << 2), - MMC_TRANSFER_AUTO_CMD12 = (0x1 << 2), - MMC_TRANSFER_AUTO_CMD23 = (0x2 << 2), - MMC_TRANSFER_AUTO_CMD = (0x3 << 2), - MMC_TRANSFER_CARD_TO_HOST = (1 << 4), - - /* Interrupt status */ - MMC_STATUS_COMMAND_COMPLETE = (1 << 0), - MMC_STATUS_TRANSFER_COMPLETE = (1 << 1), - MMC_STATUS_DMA_INTERRUPT = (1 << 3), - MMC_STATUS_BUFFER_READ_READY = (1 << 5), - MMC_STATUS_COMMAND_TIMEOUT = (1 << 16), - MMC_STATUS_COMMAND_CRC_ERROR = (1 << 17), - MMC_STATUS_COMMAND_END_BIT_ERROR = (1 << 18), - MMC_STATUS_COMMAND_INDEX_ERROR = (1 << 19), - - MMC_STATUS_ERROR_MASK = (0xF << 16), - - /* Clock control */ - MMC_CLOCK_CONTROL_CARD_CLOCK_ENABLE = (1 << 2), - MMC_CLOCK_CONTROL_FREQUENCY_MASK = (0x3FF << 6), - MMC_CLOCK_CONTROL_FREQUENCY_SHIFT = 8, - MMC_CLOCK_CONTROL_FREQUENCY_INIT = 0x1F, // generates 400kHz from the TRM dividers - MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH = 0x00, // passes through the CAR clock unmodified - - /* Host control */ - MMC_DMA_SELECT_MASK = (0x3 << 3), - MMC_DMA_SELECT_SDMA = (0x0 << 3), - MMC_HOST_BUS_WIDTH_MASK = (1 << 1) | (1 << 5), - MMC_HOST_BUS_WIDTH_4BIT = (1 << 1), - MMC_HOST_BUS_WIDTH_8BIT = (1 << 5), - MMC_HOST_ENABLE_HIGH_SPEED = (1 << 2), - - /* Host control 2 */ - MMC_HOST2_DRIVE_STRENGTH_MASK = (0x3 << 4), - MMC_HOST2_DRIVE_STRENGTH_B = (0x0 << 4), - MMC_HOST2_DRIVE_STRENGTH_A = (0x1 << 4), - MMC_HOST2_DRIVE_STRENGTH_C = (0x2 << 4), - MMC_HOST2_DRIVE_STRENGTH_D = (0x3 << 4), - MMC_HOST2_USE_1V8_SIGNALING = (1 << 3), - MMC_HOST2_EXECUTE_TUNING = (1 << 6), - MMC_HOST2_SAMPLING_CLOCK_ENABLED = (1 << 7), - MMC_HOST2_UHS_MODE_MASK = (0x7 << 3), - - /* Software reset */ - MMC_SOFT_RESET_FULL = (1 << 0), - MMC_SOFT_RESET_CMD = (1 << 1), - MMC_SOFT_RESET_DAT = (1 << 2), - - /* Vendor clock control */ - MMC_CLOCK_TAP_MASK = (0xFF << 16), - MMC_CLOCK_TAP_SDMMC1 = (0x04 << 16), - MMC_CLOCK_TAP_SDMMC4 = (0x00 << 16), - - MMC_CLOCK_TRIM_MASK = (0xFF << 24), - MMC_CLOCK_TRIM_SDMMC1 = (0x02 << 24), - MMC_CLOCK_TRIM_SDMMC4 = (0x08 << 24), - - MMC_CLOCK_PADPIPE_CLKEN_OVERRIDE = (1 << 3), - - /* Autocal configuration */ - MMC_AUTOCAL_PDPU_CONFIG_MASK = 0x7f7f, - MMC_AUTOCAL_PDPU_SDMMC1_1V8 = 0x7b7b, - MMC_AUTOCAL_PDPU_SDMMC1_3V3 = 0x7d00, - MMC_AUTOCAL_PDPU_SDMMC4_1V8 = 0x0505, - MMC_AUTOCAL_START = (1 << 31), - MMC_AUTOCAL_ENABLE = (1 << 29), - - /* Autocal status */ - MMC_AUTOCAL_ACTIVE = (1 << 31), - - /* Power control */ - MMC_POWER_CONTROL_VOLTAGE_MASK = (0x3 << 1), - MMC_POWER_CONTROL_VOLTAGE_SHIFT = 1, - MMC_POWER_CONTROL_POWER_ENABLE = (1 << 0), - - /* Capabilities register high */ - MMC_SDR50_REQUIRES_TUNING = (1 << 13), - - /* Vendor tuning control 0*/ - MMC_VENDOR_TUNING_TRIES_MASK = (0x7 << 13), - MMC_VENDOR_TUNING_TRIES_SHIFT = 13, - - MMC_VENDOR_TUNING_MULTIPLIER_MASK = (0x7F << 6), - MMC_VENDOR_TUNING_MULTIPLIER_UNITY = (1 << 6), - - MMC_VENDOR_TUNING_DIVIDER_MASK = (0x7 << 3), - - MMC_VENDOR_TUNING_SET_BY_HW = (1 << 17), - - /* Vendor tuning control 1*/ - MMC_VENDOR_TUNING_STEP_SIZE_SDR50_DEFAULT = (0 << 0), - MMC_VENDOR_TUNING_STEP_SIZE_SDR104_DEFAULT = (0 << 4), - - /* Vendor capability overrides */ - MMC_VENDOR_CAPABILITY_DQS_TRIM_MASK = (0x3f << 8), - MMC_VENDOR_CAPABILITY_DQS_TRIM_HS400 = (0x11 << 8), -}; - - -/** - * Represents the possible tuning modes for the X1 SDMMC controller. - */ -enum sdmmc_tuning_attempts { - MMC_VENDOR_TUNING_TRIES_40 = 0, - MMC_VENDOR_TUNING_TRIES_64 = 1, - MMC_VENDOR_TUNING_TRIES_128 = 2, - MMC_VENDOR_TUNING_TRIES_192 = 3, - MMC_VENDOR_TUNING_TRIES_256 = 4, - - /* Helpful aliases; values are from the TRM */ - MMC_VENDOR_TUNING_TRIES_SDR50 = 4, - MMC_VENDOR_TUNING_TRIES_SDR104 = 2, - MMC_VENDOR_TUNING_TRIES_HS200 = 2, - MMC_VENDOR_TUNING_TRIES_HS400 = 2, -}; - - -/* Constant map that converts from a MMC_VENDOR_TUNING_TRIES_* value to the number of tries. */ -static const int sdmmc_tuning_iterations[] = {40, 64, 128, 192, 256}; - -/** - * SDMMC commands - */ -enum sdmmc_command { - CMD_GO_IDLE_OR_INIT = 0, - CMD_SEND_OPERATING_CONDITIONS = 1, - CMD_ALL_SEND_CID = 2, - CMD_SET_RELATIVE_ADDR = 3, - CMD_GET_RELATIVE_ADDR = 3, - CMD_SET_DSR = 4, - CMD_TOGGLE_SLEEP_AWAKE = 5, - CMD_SWITCH_MODE = 6, - CMD_APP_SWITCH_WIDTH = 6, - CMD_TOGGLE_CARD_SELECT = 7, - CMD_SEND_EXT_CSD = 8, - CMD_SEND_IF_COND = 8, - CMD_SEND_CSD = 9, - CMD_SEND_CID = 10, - CMD_SWITCH_TO_LOW_VOLTAGE = 11, - CMD_STOP_TRANSMISSION = 12, - CMD_READ_STATUS = 13, - CMD_BUS_TEST = 14, - CMD_GO_INACTIVE = 15, - CMD_SET_BLKLEN = 16, - CMD_READ_SINGLE_BLOCK = 17, - CMD_READ_MULTIPLE_BLOCK = 18, - CMD_SD_SEND_TUNING_BLOCK = 19, - CMD_MMC_SEND_TUNING_BLOCK = 21, - CMD_WRITE_SINGLE_BLOCK = 24, - CMD_WRITE_MULTIPLE_BLOCK = 25, - - CMD_APP_SEND_OP_COND = 41, - CMD_APP_SET_CARD_DETECT = 42, - CMD_APP_SEND_SCR = 51, - CMD_APP_COMMAND = 55, -}; - - -/** - * Fields that can be modified by CMD_SWITCH_MODE. - */ -enum sdmmc_switch_field { - /* Fields */ - MMC_PARTITION_CONFIG = 179, - MMC_BUS_WIDTH = 183, - MMC_HS_TIMING = 185, -}; - - - -/** - * String descriptions of each command. - */ -static const char *sdmmc_command_string[] = { - "CMD_GO_IDLE_OR_INIT", - "CMD_SEND_OPERATING_CONDITIONS", - "CMD_ALL_SEND_CID", - "CMD_SET_RELATIVE_ADDR", - "CMD_SET_DSR", - "CMD_TOGGLE_SLEEP_AWAKE", - "CMD_SWITCH_MODE", - "CMD_TOGGLE_CARD_SELECT", - "CMD_SEND_EXT_CSD/CMD_SEND_IF_COND", - "CMD_SEND_CSD", - "CMD_SEND_CID ", - "CMD_SWITCH_TO_LOW_VOLTAGE", - "CMD_STOP_TRANSMISSION", - "CMD_READ_STATUS", - "CMD_BUS_TEST", - "CMD_GO_INACTIVE", - "CMD_SET_BLKLEN", - "CMD_READ_SINGLE_BLOCK", - "CMD_READ_MULTIPLE_BLOCK", - "CMD_SD_SEND_TUNING_BLOCK", - "", - "CMD_MMC_SEND_TUNING_BLOCK", - "", - "", - "CMD_WRITE_SINGLE_BLOCK", - "CMD_WRITE_WRITE_BLOCK", -}; - - -/** - * SDMMC command argument numbers - */ -enum sdmmc_command_magic { - MMC_ENABLE_BOOT_INIT_MAGIC = 0xf0f0f0f0, - MMC_ENABLE_BOOT_ENABLE_MAGIC = 0xfffffffa, - - MMC_EMMC_OPERATING_COND_CAPACITY_MAGIC = 0x00ff8080, - - MMC_EMMC_OPERATING_COND_CAPACITY_MASK = 0x0fffffff, - MMC_EMMC_OPERATING_COND_BUSY = (0x04 << 28), - MMC_EMMC_OPERATING_COND_READY = (0x0c << 28), - MMC_EMMC_OPERATING_READINESS_MASK = (0x0f << 28), - - MMC_SD_OPERATING_COND_READY = (1 << 31), - MMC_SD_OPERATING_COND_HIGH_CAPACITY = (1 << 30), - MMC_SD_OPERATING_COND_ACCEPTS_1V8 = (1 << 24), - MMC_SD_OPERATING_COND_ACCEPTS_3V3 = (1 << 20), - - /* READ_STATUS responses */ - MMC_STATUS_MASK = (0xf << 9), - MMC_STATUS_PROGRAMMING = (0x7 << 9), - MMC_STATUS_READY_FOR_DATA = (0x1 << 8), - MMC_STATUS_CHECK_ERROR = (~0x0206BF7F), - - /* IF_COND components */ - MMC_IF_VOLTAGE_3V3 = (1 << 8), - MMC_IF_CHECK_PATTERN = 0xAA, - - /* Switch mode constants */ - SDMMC_SWITCH_MODE_MODE_SHIFT = 31, - SDMMC_SWITCH_MODE_ALL_FUNCTIONS_UNUSED = 0xFFFFFF, - SDMMC_SWITCH_MODE_FUNCTION_MASK = 0xF, - SDMMC_SWITCH_MODE_GROUP_SIZE_BITS = 4, - - SDMMC_SWITCH_MODE_MODE_QUERY = 0, - SDMMC_SWITCH_MODE_MODE_APPLY = 1, - SDMMC_SWITCH_MODE_ACCESS_MODE = 0, - SDMMC_SWITCH_MODE_NO_GROUP = -1, - - /* Misc constants */ - MMC_DEFAULT_BLOCK_ORDER = 9, - MMC_VOLTAGE_SWITCH_TIME = 5000, // 5ms - MMC_POST_CLOCK_DELAY = 1000, // 1ms - MMC_SPEED_MMC_OFFSET = 10, - - MMC_AUTOCAL_TIMEOUT = 10 * 1000, // 10ms - MMC_TUNING_TIMEOUT = 150 * 1000, // 150ms - MMC_TUNING_BLOCK_ORDER_4BIT = 6, - MMC_TUNING_BLOCK_ORDER_8BIT = 7, -}; - - -/** - * Version magic numbers for different CSD versions. - */ -enum sdmmc_csd_versions { - MMC_CSD_VERSION1 = 0, - MMC_CSD_VERSION2 = 1, -}; - - -/** - * Positions of different fields in various CSDs. - * May eventually be replaced with a bitfield struct, if we use enough of the CSDs. - */ -enum sdmmc_csd_extents { - - /* csd structure version */ - MMC_CSD_STRUCTURE_START = 126, - MMC_CSD_STRUCTURE_WIDTH = 2, - - /* read block length */ - MMC_CSD_V1_READ_BL_LENGTH_START = 80, - MMC_CSD_V1_READ_BL_LENGTH_WIDTH = 4, - -}; - - -/** - * Positions of the different fields in the Extended CSD. - */ -enum sdmmc_ext_csd_extents { - MMC_EXT_CSD_SIZE = 512, - - /* Hardware partition registers */ - MMC_EXT_CSD_PARTITION_SETTING_COMPLETE = 155, - MMC_EXT_CSD_PARTITION_SETTING_COMPLETED = (1 << 0), - - MMC_EXT_CSD_PARTITION_ATTRIBUTE = 156, - MMC_EXT_CSD_PARTITION_ENHANCED_ATTRIBUTE = 0x1f, - - MMC_EXT_CSD_PARTITION_SUPPORT = 160, - MMC_SUPPORTS_HARDWARE_PARTS = (1 << 0), - - MMC_EXT_CSD_ERASE_GROUP_DEF = 175, - MMC_EXT_CSD_ERASE_GROUP_DEF_BIT = (1 << 0), - - MMC_EXT_CSD_PARTITION_CONFIG = 179, - MMC_EXT_CSD_PARTITION_SELECT_MASK = 0x7, - - MMC_EXT_CSD_PARTITION_SWITCH_TIME = 199, - MMC_EXT_CSD_PARTITION_SWITCH_SCALE_US = 10000, - - /* Card type register; we skip entries for - * non-1V8 modes, as we're fixed to 1V8 */ - MMC_EXT_CSD_CARD_TYPE = 196, - MMC_EXT_CSD_CARD_TYPE_HS26 = (1 << 0), - MMC_EXT_CSD_CARD_TYPE_HS52 = (1 << 1), - MMC_EXT_CSD_CARD_TYPE_HS200_1V8 = (1 << 4), - MMC_EXT_CSD_CARD_TYPE_HS400_1V8 = (1 << 6), - - /* Current HS mode register */ - MMC_EXT_CSD_HS_TIMING = 185, -}; - - -/** - * Bitfield struct representing an SD SCR. - */ -struct PACKED sdmmc_scr { - uint32_t reserved1; - uint16_t reserved0; - uint8_t supports_width_1bit : 1; - uint8_t supports_width_reserved0 : 1; - uint8_t supports_width_4bit : 1; - uint8_t supports_width_reserved1 : 1; - uint8_t security_support : 3; - uint8_t data_after_erase : 1; - uint8_t spec_version : 4; - uint8_t scr_version : 4; -}; - - -/** - * Bitfield struct represneting an SD card's function status. - */ -struct PACKED sdmmc_function_status { - - /* NOTE: all of the below are reversed from CPU endianness! */ - uint16_t current_consumption; - uint16_t group6_support; - uint16_t group5_support; - uint16_t group4_support; - uint16_t group3_support; - uint16_t group2_support; - - /* support for various speed modes */ - uint16_t group1_support_reserved1 : 8; - uint16_t sdr12_support : 1; - uint16_t sdr25_support : 1; - uint16_t sdr50_support : 1; - uint16_t sdr104_support : 1; - uint16_t ddr50_support : 1; - uint16_t group1_support_reserved2 : 3; - - - uint8_t group5_selection : 4; - uint8_t group6_selection : 4; - uint8_t group3_selection : 4; - uint8_t group4_selection : 4; - uint8_t active_access_mode : 4; - uint8_t group2_selection : 4; - - uint8_t structure_version; - uint16_t group6_busy_status; - uint16_t group5_busy_status; - uint16_t group4_busy_status; - uint16_t group3_busy_status; - uint16_t group2_busy_status; - uint16_t group1_busy_status; - uint8_t reserved[34]; -}; - -/* Callback function typedefs */ -typedef int (*fault_handler_t)(struct mmc *mmc); - -/* Forward declarations */ -static int sdmmc_send_simple_command(struct mmc *mmc, enum sdmmc_command command, - enum sdmmc_response_type response_type, uint32_t argument, void *response_buffer); -static int sdmmc_wait_for_event(struct mmc *mmc, - uint32_t target_irq, uint32_t state_conditions, - uint32_t fault_conditions, fault_handler_t fault_handler); -static int sdmmc_send_command(struct mmc *mmc, enum sdmmc_command command, - enum sdmmc_response_type response_type, enum sdmmc_response_checks checks, - uint32_t argument, void *response_buffer, uint16_t blocks_to_transfer, - bool is_write, bool auto_terminate, void *data_buffer); -static int sdmmc_use_block_size(struct mmc *mmc, int block_order); -static uint8_t sdmmc_get_block_order(struct mmc *mmc, bool is_write); -static void sdmmc_prepare_command_data(struct mmc *mmc, uint16_t blocks, - bool is_write, bool auto_terminate, bool use_dma, int argument); -static void sdmmc_prepare_command_registers(struct mmc *mmc, int blocks_to_xfer, - enum sdmmc_command command, enum sdmmc_response_type response_type, - enum sdmmc_response_checks checks); -static int sdmmc_wait_for_command_readiness(struct mmc *mmc); -static int sdmmc_wait_for_data_readiness(struct mmc *mmc); - -/* SDMMC debug enable */ -static int sdmmc_loglevel = 0; - -/** - * Page-aligned bounce buffer to target with SDMMC DMA. - * If the size of this buffer is changed, the block_size - */ -static uint8_t ALIGN(4096) sdmmc_bounce_buffer[1024 * 8]; -static const uint16_t sdmmc_bounce_dma_boundary = MMC_DMA_BOUNDARY_8K; - - -/** - * Sets the current SDMMC debugging loglevel. - * - * @param loglevel Current log level. A higher value prints more logs. - * @return The loglevel prior to when this was applied, for easy restoration. - */ -int sdmmc_set_loglevel(int loglevel) -{ - int original_loglevel = sdmmc_loglevel; - sdmmc_loglevel = loglevel; - - return original_loglevel; -} - - -/** - * Internal utility function for generating debug prints at various log levels. - */ -static void mmc_vprint(struct mmc *mmc, char *fmt, int required_loglevel, va_list list) -{ - // Allow debug prints to be silenced by a negative loglevel. - //TODO: respect the log level, most likely there are still some timing problems - //which make it not working when the logging is supressed - //if (sdmmc_loglevel < required_loglevel) - // return; - - printk("%s: ", mmc->name); - vprintk(fmt, list); - printk("\n"); -} - - -/** - * Normal SDMMC print for SDMMC information. - */ -static void mmc_print(struct mmc *mmc, char *fmt, ...) -{ - va_list list; - - va_start(list, fmt); - mmc_vprint(mmc, fmt, 0, list); - va_end(list); -} - - -/** - * Normal SDMMC print for SDMMC information. - */ -static void mmc_debug(struct mmc *mmc, char *fmt, ...) -{ - va_list list; - - va_start(list, fmt); - mmc_vprint(mmc, fmt, 1, list); - va_end(list); -} - - -/** - * @return a statically allocated string that describes the given command - */ -static const char *sdmmc_get_speed_string(enum sdmmc_bus_speed speed) -{ - switch (speed) { - case SDMMC_SPEED_INIT: return "400kHz (init)"; - - // SD card speeds - case SDMMC_SPEED_SDR12: return "12.5MB/s"; - case SDMMC_SPEED_SDR25: return "25MB/s"; - case SDMMC_SPEED_SDR50: return "50MB/s"; - case SDMMC_SPEED_SDR104: return "104MB/s"; - case SDMMC_SPEED_DDR50: return "104MB/s (DDR)"; - case SDMMC_SPEED_OTHER: return ""; - - // eMMC card speeds - case SDMMC_SPEED_HS26: return "26 MHz"; - case SDMMC_SPEED_HS52: return "52 MHz"; - case SDMMC_SPEED_HS200: return "200MHz"; - case SDMMC_SPEED_HS400: return "200MHz (DDR)"; - } - - return ""; -} - - -/** - * @return a statically allocated string that describes the given command - */ -static const char *sdmmc_get_command_string(enum sdmmc_command command) -{ - switch (command) { - - // Commands that aren't in the lower block. - case CMD_APP_COMMAND: - return "CMD_APP_COMMAND"; - case CMD_APP_SEND_OP_COND: - return "CMD_APP_SEND_OP_COND"; - case CMD_APP_SET_CARD_DETECT: - return "CMD_APP_SET_CARD_DETECT"; - case CMD_APP_SEND_SCR: - return "CMD_APP_SEND_SCR"; - - // For commands with low numbers, read them string from the relevant array. - default: - return sdmmc_command_string[command]; - } -} - - -/** - * Debug: print out any errors that occurred during a command timeout - */ -void mmc_print_command_errors(struct mmc *mmc, int command_errno) -{ - if (command_errno & MMC_STATUS_COMMAND_TIMEOUT) - mmc_print(mmc, "ERROR: command timed out!"); - - if (command_errno & MMC_STATUS_COMMAND_CRC_ERROR) - mmc_print(mmc, "ERROR: command response had invalid CRC"); - - if (command_errno & MMC_STATUS_COMMAND_END_BIT_ERROR) - mmc_print(mmc, "ERROR: command response had invalid end bit"); - - if (command_errno & MMC_STATUS_COMMAND_INDEX_ERROR) - mmc_print(mmc, "ERROR: response appears not to be for the last issued command"); - -} - - -/** - * Retreives the SDMMC register range for the given controller. - */ -static struct tegra_sdmmc *sdmmc_get_regs(enum sdmmc_controller controller) -{ - // Start with the base addresss of the SDMMC_BLOCK - uintptr_t addr = TEGRA_SDMMC_BASE; - - // Offset our address by the controller number. - addr += (controller * TEGRA_SDMMC_SIZE); - - // Return the controller. - return (struct tegra_sdmmc *)addr; -} - -/** - * Performs a soft-reset of the SDMMC controller. - * - * @param mmc The MMC controller to be reset. - * @return 0 if the device successfully came out of reset; or an error code otherwise - */ -static int sdmmc_hardware_reset(struct mmc *mmc, uint32_t reset_flags) -{ - uint32_t timebase = get_time(); - - // Reset the MMC controller... - mmc->regs->software_reset |= reset_flags; - - // Wait for the SDMMC controller to come back up... - while (mmc->regs->software_reset & reset_flags) { - if (get_time_since(timebase) > mmc->timeout) { - mmc_print(mmc, "failed to bring up SDMMC controller"); - return ETIMEDOUT; - } - } - - return 0; -} - -/** - * Delays for a given amount of host clock cycles. - * - * @param mmc The MMC controller whose clock cycles should be waited upon. - * @param clocks The number of clock cycles to wait. - */ -static void sdmmc_host_clock_delay(struct mmc *mmc, unsigned int clocks) -{ - // For the time being simply wait for clocks * 50 us - // This covers clocks as slow as 20 kHz and hence should always be safe - // TODO: determine the actual wait time based on clock source and divider - udelay(50 * clocks); -} - -/** - * Performs low-level initialization for SDMMC4, used for the eMMC. - */ -static int sdmmc4_set_up_clock_and_io(struct mmc *mmc) -{ - volatile struct tegra_car *car = car_get_regs(); - volatile struct tegra_padctl *padctl = padctl_get_regs(); - - // Put SDMMC4 in reset - car->rst_dev_l_set |= 0x8000; - - // Configure the clock to place the device into the initial mode. - car->clk_src[CLK_SOURCE_SDMMC4] = MMC_CLOCK_SOURCE_SDR12 | MMC_CLOCK_DIVIDER_SDR12; - - // Set the legacy divier used for detecting timeouts. - car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = MMC_CLOCK_SOURCE_LEGACY | MMC_CLOCK_DIVIDER_LEGACY; - - // Set SDMMC4 clock enable - car->clk_enb_l_set |= 0x8000; - car->clk_enb_y_set |= CAR_CONTROL_SDMMC_LEGACY; - - // Delay 100 host clock cycles - sdmmc_host_clock_delay(mmc, 100); - - // Take SDMMC4 out of reset - car->rst_dev_l_clr |= 0x8000; - - // Enable input paths for all pins. - padctl->sdmmc4_control |= - PADCTL_SDMMC4_ENABLE_DATA_IN | PADCTL_SDMMC4_ENABLE_CLK_IN | PADCTL_SDMMC4_DEEP_LOOPBACK; - - return 0; -} - -/** - * Sets the voltage that the given SDMMC is currently working with. - * - * @param mmc The controller to affect. - * @param voltage The voltage to apply. - */ -static void sdmmc_set_working_voltage(struct mmc *mmc, enum sdmmc_bus_voltage voltage) -{ - // Apply the voltage... - mmc->operating_voltage = voltage; - - // Set up the SD card's voltage. - mmc->regs->power_control &= ~MMC_POWER_CONTROL_VOLTAGE_MASK; - mmc->regs->power_control |= voltage << MMC_POWER_CONTROL_VOLTAGE_SHIFT; - - // Switch to 1V8 signaling. - mmc->regs->host_control2 |= MMC_HOST2_USE_1V8_SIGNALING; - - // Mark the power as on. - mmc->regs->power_control |= MMC_POWER_CONTROL_POWER_ENABLE; -} - - -/** - * Enables power supplies for SDMMC4, used for eMMC. - */ -static int sdmmc4_enable_supplies(struct mmc *mmc) -{ - // As a booot device, SDMMC4's power supply is always on. - // Modify the controller to know the voltage being applied to it, - // and return success. - sdmmc_set_working_voltage(mmc, MMC_VOLTAGE_1V8); - return 0; -} - - -/** - * Enables power supplies for SDMMC1, used for the SD card slot. - */ -static int sdmmc1_enable_supplies(struct mmc *mmc) -{ - volatile struct tegra_pmc *pmc = pmc_get_regs(); - volatile struct tegra_pinmux *pinmux = pinmux_get_regs(); - - // Set PAD_E_INPUT_OR_E_PWRD (relevant for eMMC only) - mmc->regs->sdmemcomppadctrl |= 0x80000000; - - // Ensure the PMC is prepared for the SDMMC card to recieve power. - pmc->no_iopower &= ~PMC_CONTROL_SDMMC1; - pmc->pwr_det_val |= PMC_CONTROL_SDMMC1; - - // Set up SD card voltages. - udelay(1000); - supply_enable(SUPPLY_MICROSD, false); - udelay(1000); - - // Modify the controller to know the voltage being applied to it. - sdmmc_set_working_voltage(mmc, MMC_VOLTAGE_3V3); - - // Configure the enable line for the SD card power. - pinmux->dmic3_clk = PINMUX_SELECT_FUNCTION0; - gpio_configure_mode(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_MODE_GPIO); - gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_OUTPUT); - - // Bring up the SD card fixed regulator. - gpio_write(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_LEVEL_HIGH); - return 0; -} - - -/** - * Configures clocking parameters for a given controller. - * - * @param mmc The MMC controller to set up. - * @param operating_voltage The operating voltage for the bus, currently. - */ -static int sdmmc_set_up_clocking_parameters(struct mmc *mmc, enum sdmmc_bus_voltage operating_voltage) -{ - // Clear the I/O conditioning constants. - mmc->regs->vendor_clock_cntrl &= ~(MMC_CLOCK_TRIM_MASK | MMC_CLOCK_TAP_MASK); - - // Per the TRM, set the PADPIPE clock enable. - mmc->regs->vendor_clock_cntrl |= MMC_CLOCK_PADPIPE_CLKEN_OVERRIDE; - - // Set up the I/O conditioning constants used to ensure we have a reliable clock. - // Constants above and procedure below from the TRM. - switch (mmc->controller) { - case SWITCH_EMMC: - if (operating_voltage != MMC_VOLTAGE_1V8) { - mmc_print(mmc, "ERROR: eMMC can only run at 1V8, but mmc struct claims voltage %d", operating_voltage); - return EINVAL; - } - - mmc->regs->auto_cal_config &= ~MMC_AUTOCAL_PDPU_CONFIG_MASK; - mmc->regs->auto_cal_config |= MMC_AUTOCAL_PDPU_SDMMC4_1V8; - mmc->regs->vendor_clock_cntrl |= (MMC_CLOCK_TRIM_SDMMC4 | MMC_CLOCK_TAP_SDMMC4); - break; - - case SWITCH_MICROSD: - switch (operating_voltage) { - case MMC_VOLTAGE_1V8: - mmc->regs->auto_cal_config &= ~MMC_AUTOCAL_PDPU_CONFIG_MASK; - mmc->regs->auto_cal_config |= MMC_AUTOCAL_PDPU_SDMMC1_1V8; - break; - case MMC_VOLTAGE_3V3: - mmc->regs->auto_cal_config &= ~MMC_AUTOCAL_PDPU_CONFIG_MASK; - mmc->regs->auto_cal_config |= MMC_AUTOCAL_PDPU_SDMMC1_3V3; - break; - default: - mmc_print(mmc, "ERROR: microsd does not support voltage %d", operating_voltage); - return EINVAL; - } - mmc->regs->vendor_clock_cntrl |= (MMC_CLOCK_TRIM_SDMMC1 | MMC_CLOCK_TAP_SDMMC1); - break; - - default: - printk("ERROR: initialization not yet writen for SDMMC%d", mmc->controller); - return ENODEV; - } - - return 0; -} - - -/** - * Enables or disables delivering a clock to the downstream SD/MMC card. - * - * @param mmc The controller to be affected. - * @param enabled True if the clock should be enabled; false to disable. - */ -void sdmmc_clock_enable(struct mmc *mmc, bool enabled) -{ - // Set or clear the card clock enable bit according to the - // controller paramter. - if (enabled) - mmc->regs->clock_control |= MMC_CLOCK_CONTROL_CARD_CLOCK_ENABLE; - else - mmc->regs->clock_control &= ~MMC_CLOCK_CONTROL_CARD_CLOCK_ENABLE; -} - - -/** - * Runs SDMMC automatic calibration-- this tunes the parameters used for SDMMC - * signal intergrity. - * - * @param mmc The controller whose card is to be tuned. - * @param restart_sd_clock True iff the SD card should be started after calibration. - * - * @return 0 on success, or an error code on failure - */ -static int sdmmc_run_autocal(struct mmc *mmc, bool restart_sd_clock) -{ - uint32_t timebase; - int ret = 0; - - // Stop the SD card's clock, so our autocal sequence doesn't - // confuse the target card. - sdmmc_clock_enable(mmc, false); - - // Start automatic calibration... - mmc->regs->auto_cal_config |= (MMC_AUTOCAL_START | MMC_AUTOCAL_ENABLE); - udelay(1); - - // ... and wait until the autocal is complete - timebase = get_time(); - while ((mmc->regs->auto_cal_status & MMC_AUTOCAL_ACTIVE)) { - - // Ensure we haven't timed out... - if (get_time_since(timebase) > MMC_AUTOCAL_TIMEOUT) { - mmc_print(mmc, "ERROR: autocal timed out!"); - if (mmc->controller == SWITCH_MICROSD) { - // Fallback driver strengths from Tegra X1 TRM - uint32_t drvup = (mmc->operating_voltage == MMC_VOLTAGE_3V3) ? 0x12 : 0x11; - uint32_t drvdn = (mmc->operating_voltage == MMC_VOLTAGE_3V3) ? 0x12 : 0x15; - uint32_t value = APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL_0; - value &= ~(SDMMC1_PAD_CAL_DRVUP_MASK | SDMMC1_PAD_CAL_DRVDN_MASK); - value |= (drvup << SDMMC1_PAD_CAL_DRVUP_SHIFT); - value |= (drvdn << SDMMC1_PAD_CAL_DRVDN_SHIFT); - APB_MISC_GP_SDMMC1_PAD_CFGPADCTRL_0 = value; - } else if (mmc->controller == SWITCH_EMMC) { - uint32_t value = APB_MISC_GP_EMMC4_PAD_CFGPADCTRL_0; - value &= ~(CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK | CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK); - value |= (0x10 << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT); - value |= (0x10 << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT); - APB_MISC_GP_EMMC4_PAD_CFGPADCTRL_0 = value; - } - mmc->regs->auto_cal_config &= ~MMC_AUTOCAL_ENABLE; - ret = ETIMEDOUT; - break; - } - } - - // If requested, enable the SD clock. - if (restart_sd_clock) - sdmmc_clock_enable(mmc, true); - - return ret; -} - - -/** - * Switches the Switch's microSD card into low-voltage mode. - * - * @param mmc The MMC controller via which to communicate. - * @return 0 on success, or an error code on failure. - */ -static int sdmmc1_switch_to_low_voltage(struct mmc *mmc) -{ - volatile struct tegra_pmc *pmc = pmc_get_regs(); - int rc; - - // Let the SD card know we're about to switch into low-voltage mode. - // Set up the card's relative address. - rc = sdmmc_send_simple_command(mmc, CMD_SWITCH_TO_LOW_VOLTAGE, MMC_RESPONSE_LEN48, 0, NULL); - if (rc) { - mmc_print(mmc, "card was not willling to switch to low voltage! (%d)", rc); - return rc; - } - - // Switch the MicroSD card supply into its low-voltage mode. - supply_enable(SUPPLY_MICROSD, true); - pmc->pwr_det_val &= ~PMC_CONTROL_SDMMC1; - - // Apply our clocking parameters for low-voltage mode. - rc = sdmmc_set_up_clocking_parameters(mmc, MMC_VOLTAGE_1V8); - if (rc) { - mmc_print(mmc, "WARNING: could not optimize card clocking parameters. (%d)", rc); - } - - // Rerun the main clock calibration... - rc = sdmmc_run_autocal(mmc, false); - if (rc) - mmc_print(mmc, "WARNING: failed to re-calibrate after voltage switch!"); - - // ... and ensure the host is set up to apply the relevant change. - sdmmc_set_working_voltage(mmc, MMC_VOLTAGE_1V8); - udelay(MMC_VOLTAGE_SWITCH_TIME); - - // Enable the SD clock. - sdmmc_clock_enable(mmc, true); - udelay(MMC_POST_CLOCK_DELAY); - - mmc_debug(mmc, "now running from 1V8"); - return 0; -} - - -/** - * Low-voltage switching method for controllers that don't - * support a low-voltage switch. Always fails. - * - * @param mmc The MMC controller via which to communicate. - * @return ENOSYS, indicating failure, always - */ -static int sdmmc_always_fail(struct mmc *mmc) -{ - // This card is always in low voltage and should never have to switch. - return ENOSYS; -} - - -/** - * Sets up the clock for the given SDMMC controller. - * Assumes the controller's clock has been stopped with sdmmc_clock_enable before use. - * - * @param mmc The controller to work with. - * @param source The clock source, as defined by the CAR. - * @param car_divisor. The divisor for that source in the CAR. Usually one of the MMC_CLOCK_DIVIDER macros; - * a divider of N results in a clock that's (N/2) + 1 slower. - * @param sdmmc_divisor An additional divisor applied in the SDMMC controller. - */ -static void sdmmc4_configure_clock(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor) -{ - volatile struct tegra_car *car = car_get_regs(); - - // Set up the CAR aspect of the clock, and wait 2us per change per the TRM. - car->clk_enb_l_clr = CAR_CONTROL_SDMMC4; - car->clk_src[CLK_SOURCE_SDMMC4] = source | car_divisor; - udelay(2); - car->clk_enb_l_set = CAR_CONTROL_SDMMC4; - - // ... and the SDMMC section of it. - mmc->regs->clock_control &= ~MMC_CLOCK_CONTROL_FREQUENCY_MASK; - mmc->regs->clock_control |= sdmmc_divisor << MMC_CLOCK_CONTROL_FREQUENCY_SHIFT; -} - - -/** - * Sets up the clock for the given SDMMC controller. - * Assumes the controller's clock has been stopped with sdmmc_clock_enable before use. - * - * @param mmc The controller to work with. - * @param source The clock source, as defined by the CAR. - * @param car_divisor. The divisor for that source in the CAR. Usually one of the MMC_CLOCK_DIVIDER macros; - * a divider of N results in a clock that's (N/2) + 1 slower. - * @param sdmmc_divisor An additional divisor applied in the SDMMC controller. - */ -static void sdmmc1_configure_clock(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor) -{ - volatile struct tegra_car *car = car_get_regs(); - - // Set up the CAR aspect of the clock, and wait 2us per change per the TRM. - car->clk_enb_l_clr = CAR_CONTROL_SDMMC1; - car->clk_src[CLK_SOURCE_SDMMC1] = source | car_divisor; - udelay(2); - car->clk_enb_l_set = CAR_CONTROL_SDMMC1; - - // ... and the SDMMC section of it. - mmc->regs->clock_control &= ~MMC_CLOCK_CONTROL_FREQUENCY_MASK; - mmc->regs->clock_control |= sdmmc_divisor << MMC_CLOCK_CONTROL_FREQUENCY_SHIFT; -} - - -/** - * Runs a single iteration of an active SDMMC clock tune. - * You probably want sdmmc_tune_clock instead. - */ -static int sdmmc_run_tuning_iteration(struct mmc *mmc, enum sdmmc_command tuning_command) -{ - int rc; - uint32_t saved_int_enable = mmc->regs->int_enable; - - // Enable the BUFFER_READ_READY interrupt for this run, and make sure it's not set. - mmc->regs->int_enable |= MMC_STATUS_BUFFER_READ_READY; - mmc->regs->int_status = mmc->regs->int_status; - - // Wait until we can issue commands to the device. - rc = sdmmc_wait_for_command_readiness(mmc); - if (rc) { - mmc_print(mmc, "card not willing to accept commands (%d / %08x)", rc, mmc->regs->present_state); - return EBUSY; - } - - rc = sdmmc_wait_for_data_readiness(mmc); - if (rc) { - mmc_print(mmc, "card not willing to accept data-commands (%d / %08x)", rc, mmc->regs->present_state); - return EBUSY; - } - - // Disable the SD card clock. [TRM 32.7.6.2 Step 3] - // NVIDIA notes that issuing the re-tune command triggers a re-selection of clock tap, but also - // due to a hardware issue, causes a one-microsecond window in which a clock glitch can occur. - // We'll disable the SD card clock temporarily so the card itself isn't affected by the glitch. - sdmmc_clock_enable(mmc, false); - - // Issue our tuning command. [TRM 32.7.6.2 Step 4] - sdmmc_prepare_command_data(mmc, 1, false, false, false, 0); - sdmmc_prepare_command_registers(mmc, 1, tuning_command, MMC_RESPONSE_LEN48, MMC_CHECKS_ALL); - - // Wait for 1us [TRM 32.7.6.2 Step 5] - // As part of the workaround above, we'll wait one microsecond for the glitch window to pass. - udelay(1); - - // Issue a software reset for the data and command lines. [TRM 32.7.6.2 Step 6/7] - // This completes the workaround by ensuring the glitch didn't leave the sampling hardware - // for these lines in an uncertain state. This function blocks until the glitch window has - // complete, so it handles both TRM steps 7 and 8. - sdmmc_hardware_reset(mmc, MMC_SOFT_RESET_CMD | MMC_SOFT_RESET_DAT); - - // Restore the SDMMC clock, now that the workaround is complete. [TRM 32.7.6.2 Step 8] - // This enables the actual command to be issued. - sdmmc_clock_enable(mmc, true); - - // Wait for the command to be completed. [TRM 32.7.6.2 Step 9] - rc = sdmmc_wait_for_event(mmc, MMC_STATUS_BUFFER_READ_READY, 0, 0, NULL); - - // Always restore the prior interrupt settings. - mmc->regs->int_enable = saved_int_enable; - - // If we had an error waiting for the interrupt, something went wrong. - // TODO: decide if this should be a retry condition? - if (rc) { - mmc_print(mmc, "buffer ready ready didn't go high in time?"); - mmc_print(mmc, "error message: %s", strerror(rc)); - mmc_print(mmc, "interrupt reg: %08x", mmc->regs->int_status); - mmc_print(mmc, "interrupt en: %08x", mmc->regs->int_enable); - return rc; - } - - // Check the status of the "execute tuning", which indicates the success of - // this tuning step. [TRM 32.7.6.2 Step 10] - if (mmc->regs->host_control2 & MMC_HOST2_EXECUTE_TUNING) - return EAGAIN; - - return 0; -} - - -/** - * Performs an SDMMC clock tuning -- should be issued when switching up to a UHS-I - * mode, and periodically thereafter per the spec. - * - * @param mmc The controller to tune. - * @param iterations The total number of iterations to perform. - * @param tuning_command The command to be used for tuning; usually CMD19/21. - */ -static int sdmmc_tune_clock(struct mmc *mmc, enum sdmmc_tuning_attempts iterations, - enum sdmmc_command tuning_command) -{ - int rc; - - // We follow the NVIDIA-suggested tuning procedure (TRM section 32.7.6), - // including sections where it deviates from the SDMMC specifications. - // - // This seems to produce the most reliable results, and includes workarounds - // for bugs in the X1 hardware. - - // Read the current block order, so we can restore it. - int original_block_order = sdmmc_get_block_order(mmc, false); - - // Stores the current timeout; we'll restore it in a bit. - int original_timeout = mmc->timeout; - - // The SDMMC host spec suggests tuning should occur over 40 iterations, so we'll stick to that. - // Vendors seem to deviate from this, so this is a possible area to look into if something doesn't - // wind up working correctly. - int attempts_remaining = sdmmc_tuning_iterations[iterations]; - mmc_debug(mmc, "executing tuning (%d iterations)", attempts_remaining); - - // Allow the tuning hardware to control e.g. our clock taps. - mmc->regs->vendor_tuning_cntrl0 |= MMC_VENDOR_TUNING_SET_BY_HW; - - // Apply our number of tries. - mmc->regs->vendor_tuning_cntrl0 &= ~MMC_VENDOR_TUNING_TRIES_MASK; - mmc->regs->vendor_tuning_cntrl0 |= (iterations << MMC_VENDOR_TUNING_TRIES_SHIFT); - - // Don't use a multiplier or a divider. - mmc->regs->vendor_tuning_cntrl0 &= ~(MMC_VENDOR_TUNING_MULTIPLIER_MASK | MMC_VENDOR_TUNING_DIVIDER_MASK); - mmc->regs->vendor_tuning_cntrl0 |= MMC_VENDOR_TUNING_MULTIPLIER_UNITY; - - // Use zero step sizes; per TRM 32.7.6.1. - mmc->regs->vendor_tuning_cntrl1 = MMC_VENDOR_TUNING_STEP_SIZE_SDR50_DEFAULT | MMC_VENDOR_TUNING_STEP_SIZE_SDR104_DEFAULT; - - // Start the tuning process. [TRM 32.7.6.2 Step 2] - mmc->regs->host_control2 |= MMC_HOST2_EXECUTE_TUNING; - - // Momentarily step down to a smaller block size, so we don't - // have to allocate a huge buffer for this command. - mmc->read_block_order = mmc->tuning_block_order; - - // Step down to the timeout recommended in the specification. - mmc->timeout = MMC_TUNING_TIMEOUT; - - // Iterate an iteration of the tuning process. - while (attempts_remaining--) { - - // Run an iteration of our tuning process. - rc = sdmmc_run_tuning_iteration(mmc, tuning_command); - - // If we have an error other than "retry, break. - if (rc != EAGAIN) - break; - } - - // Restore the original parameters. - mmc->read_block_order = original_block_order; - mmc->timeout = original_timeout; - - // If we exceeded our attempts, set this as a timeout. - if (rc == EAGAIN) { - mmc_print(mmc, "tuning attempts exceeded!"); - rc = ETIMEDOUT; - } - - // If the tuning failed, for any reason, print and return the error. - if (rc) { - mmc_print(mmc, "ERROR: failed to tune the SDMMC clock! (%d)", rc); - mmc_print(mmc, "error message %s", strerror(rc)); - return rc; - } - - // If we've made it here, this iteration completed tuning. - // Check for a tuning failure (SAMPLE CLOCK = 0). [TRM 32.7.6.2 Step 11] - if (!(mmc->regs->host_control2 & MMC_HOST2_SAMPLING_CLOCK_ENABLED)) { - mmc_print(mmc, "ERROR: tuning failed after complete iteration!"); - mmc_print(mmc, "host_control2: %08x", mmc->regs->host_control2); - return EIO; - } - - return 0; -} - - -/** - * Configures the host controller to work at a given UHS-I mode. - * - * @param mmc The controller to work with - * @param speed The UHS or pre-UHS speed to work at. - */ -static void sdmmc_set_uhs_mode(struct mmc *mmc, enum sdmmc_bus_speed speed) -{ - // Set the UHS mode register. - mmc->regs->host_control2 &= MMC_HOST2_UHS_MODE_MASK; - mmc->regs->host_control2 |= speed; -} - - -/** - * Applies the appropriate clock dividers to the CAR and SD controller to enable use of the - * provided speed. Does not handle any requisite communications with the card. - * - * @param mmc The controller to affect. - * @param speed The speed to apply. - * @param enable_after If set, the SDMMC clock will be enabled after the change. If not, it will be left disabled. - */ -static int sdmmc_apply_clock_speed(struct mmc *mmc, enum sdmmc_bus_speed speed, bool enable_after) -{ - int rc; - - // By default, don't execute tuning after applying the clock. - bool execute_tuning = false; - enum sdmmc_tuning_attempts tuning_attempts = MMC_VENDOR_TUNING_TRIES_40; - enum sdmmc_command tuning_command = CMD_SD_SEND_TUNING_BLOCK; - - // Ensure the clocks are not currently running to avoid glitches. - sdmmc_clock_enable(mmc, false); - - // Clear the registers of any existing values, so we can apply new ones. - mmc->regs->host_control &= ~MMC_HOST_ENABLE_HIGH_SPEED; - - // Apply the dividers according to the speed provided. - switch (speed) { - - // 400kHz initialization mode. - case SDMMC_SPEED_INIT: - mmc->configure_clock(mmc, MMC_CLOCK_SOURCE_SDR12, MMC_CLOCK_DIVIDER_SDR12, MMC_CLOCK_CONTROL_FREQUENCY_INIT); - sdmmc_set_uhs_mode(mmc, SDMMC_SPEED_SDR12); - break; - - // 25MHz default speed (SD) - case SDMMC_SPEED_SDR12: - mmc->configure_clock(mmc, MMC_CLOCK_SOURCE_SDR12, MMC_CLOCK_DIVIDER_SDR12, MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH); - sdmmc_set_uhs_mode(mmc, SDMMC_SPEED_SDR12); - break; - - // 26MHz default speed (MMC) - case SDMMC_SPEED_HS26: - mmc->configure_clock(mmc, MMC_CLOCK_SOURCE_HS26, MMC_CLOCK_DIVIDER_HS26, MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH); - break; - - // 50MHz high speed (SD) - case SDMMC_SPEED_SDR25: - // Configure the host to use high-speed timing. - mmc->regs->host_control |= MMC_HOST_ENABLE_HIGH_SPEED; - mmc->configure_clock(mmc, MMC_CLOCK_SOURCE_SDR25, MMC_CLOCK_DIVIDER_SDR25, MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH); - sdmmc_set_uhs_mode(mmc, SDMMC_SPEED_SDR25); - break; - - // 52MHz high speed (MMC) - case SDMMC_SPEED_HS52: - mmc->configure_clock(mmc, MMC_CLOCK_SOURCE_HS52, MMC_CLOCK_DIVIDER_HS52, MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH); - break; - - // 100MHz UHS-I (SD) - case SDMMC_SPEED_SDR50: - mmc->regs->host_control |= MMC_HOST_ENABLE_HIGH_SPEED; - mmc->configure_clock(mmc, MMC_CLOCK_SOURCE_SDR50, MMC_CLOCK_DIVIDER_SDR50, MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH); - // Tegra X1 Series Processors Silicon Errata MMC-2 mentions setting SDR104 mode as workaround. - sdmmc_set_uhs_mode(mmc, SDMMC_SPEED_SDR104); - - execute_tuning = true; - tuning_attempts = MMC_VENDOR_TUNING_TRIES_SDR50; - break; - - // 200MHz UHS-I (SD) - case SDMMC_SPEED_SDR104: - mmc->regs->host_control |= MMC_HOST_ENABLE_HIGH_SPEED; - mmc->configure_clock(mmc, MMC_CLOCK_SOURCE_SDR104, MMC_CLOCK_DIVIDER_SDR104, MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH); - sdmmc_set_uhs_mode(mmc, SDMMC_SPEED_SDR104); - - execute_tuning = true; - tuning_attempts = MMC_VENDOR_TUNING_TRIES_SDR104; - break; - - // 200MHz single-data rate (MMC) - case SDMMC_SPEED_HS200: - case SDMMC_SPEED_HS400: - mmc->regs->host_control |= MMC_HOST_ENABLE_HIGH_SPEED; - mmc->configure_clock(mmc, MMC_CLOCK_SOURCE_HS200, MMC_CLOCK_DIVIDER_HS200, MMC_CLOCK_CONTROL_FREQUENCY_PASSTHROUGH); - sdmmc_set_uhs_mode(mmc, SDMMC_SPEED_SDR104); // Per datasheet; we set the controller in SDR104 mode. - - // Execute tuning. - execute_tuning = true; - tuning_attempts = MMC_VENDOR_TUNING_TRIES_HS200; - tuning_command = CMD_MMC_SEND_TUNING_BLOCK; - break; - - default: - mmc_print(mmc, "ERROR: switching to unsupported speed!\n"); - return ENOSYS; - } - - // If we need to execute tuning for this clock mode, do so. - if (execute_tuning) { - rc = sdmmc_tune_clock(mmc, tuning_attempts, tuning_command); - if (rc) { - mmc_print(mmc, "WARNING: clock tuning failed! speed mode can't be used. (%d)", rc); - sdmmc_clock_enable(mmc, true); - return rc; - } - } - - // Special case: HS400 mode should be applied _after_ HS200 is applied, so we apply that - // first above, and then switch up and re-tune. - if (speed == SDMMC_SPEED_HS400) { - sdmmc_set_uhs_mode(mmc, SDMMC_SPEED_OTHER); // Special value, per datasheet - - // Per the TRM, we should also use this opportunity to set up the DQS path trimmer. - // TODO: should this be used only in HS400? - mmc->regs->vendor_cap_overrides &= ~MMC_VENDOR_CAPABILITY_DQS_TRIM_MASK; - mmc->regs->vendor_cap_overrides |= MMC_VENDOR_CAPABILITY_DQS_TRIM_HS400; - - // TODO: run the DLLCAL here! - - mmc_print(mmc, "TODO: double the data rate here!"); - } - - - // Re-enable the clock, if necessary. - if (enable_after) { - sdmmc_clock_enable(mmc, true); - udelay(MMC_POST_CLOCK_DELAY); - } - - // Finally store the operating speed. - mmc->operating_speed = speed; - return 0; -} - - -/** - * Performs low-level initialization for SDMMC1, used for the SD card slot. - */ -static int sdmmc1_set_up_clock_and_io(struct mmc *mmc) -{ - volatile struct tegra_car *car = car_get_regs(); - volatile struct tegra_pinmux *pinmux = pinmux_get_regs(); - volatile struct tegra_padctl *padctl = padctl_get_regs(); - - // Set up each of the relevant pins to be connected to output drivers, - // and selected for SDMMC use. - pinmux->sdmmc1_clk = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT; - pinmux->sdmmc1_cmd = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; - pinmux->sdmmc1_dat3 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; - pinmux->sdmmc1_dat2 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; - pinmux->sdmmc1_dat1 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; - pinmux->sdmmc1_dat0 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; - - // Set up the card detect pin as a GPIO input. - pinmux->pz1 = PINMUX_TRISTATE | PINMUX_SELECT_FUNCTION1 | PINMUX_PULL_UP | PINMUX_INPUT; - gpio_configure_mode(GPIO_MICROSD_CARD_DETECT, GPIO_MODE_GPIO); - gpio_configure_direction(GPIO_MICROSD_CARD_DETECT, GPIO_DIRECTION_INPUT); - udelay(100); - - // Ensure we're using GPIO and not GPIO for the SD card's card detect. - padctl->vgpio_gpio_mux_sel &= ~PADCTL_SDMMC1_CD_SOURCE; - - // Put SDMMC1 in reset - car->rst_dev_l_set = CAR_CONTROL_SDMMC1; - - // Configure the clock to place the device into the initial mode. - car->clk_src[CLK_SOURCE_SDMMC1] = MMC_CLOCK_SOURCE_SDR12 | MMC_CLOCK_DIVIDER_SDR12; - - // Set the legacy divier used for detecting timeouts. - car->clk_src_y[CLK_SOURCE_SDMMC_LEGACY] = MMC_CLOCK_SOURCE_LEGACY | MMC_CLOCK_DIVIDER_LEGACY; - - // Set SDMMC1 clock enable - car->clk_enb_l_set = CAR_CONTROL_SDMMC1; - car->clk_enb_y_set = CAR_CONTROL_SDMMC_LEGACY; - - // Delay 100 host clock cycles - sdmmc_host_clock_delay(mmc, 100); - - // Take SDMMC1 out of reset - car->rst_dev_l_clr |= CAR_CONTROL_SDMMC1; - - // Enable clock loopback. - padctl->sdmmc1_control |= PADCTL_SDMMC1_DEEP_LOOPBACK; - - return 0; -} - - -/** - * Initialize the low-level SDMMC hardware. - * Thanks to hexkyz for this init code. - * - * FIXME: clean up the magic numbers, split into sections. - */ -static int sdmmc_hardware_init(struct mmc *mmc) -{ - volatile struct tegra_sdmmc *regs = mmc->regs; - - uint32_t timebase; - bool is_timeout; - - int rc; - - // Initialize the Tegra resources necessary to use the given piece of hardware. - rc = mmc->set_up_clock_and_io(mmc); - if (rc) { - mmc_print(mmc, "ERROR: could not set up controller for use!"); - return rc; - } - - // Software reset the SDMMC device. - rc = sdmmc_hardware_reset(mmc, MMC_SOFT_RESET_FULL); - if (rc) { - mmc_print(mmc, "failed to reset!"); - return rc; - } - - // Turn on the card's power supplies... - rc = mmc->enable_supplies(mmc); - if (rc) { - mmc_print(mmc, "ERROR: could power on the card!"); - return rc; - } - - - // Set IO_SPARE[19] (one cycle delay) - regs->io_spare |= 0x80000; - - // Clear SEL_VREG - regs->vendor_io_trim_cntrl &= ~(0x04); - - // Set SDMMC2TMC_CFG_SDMEMCOMP_VREF_SEL to 0x07 - regs->sdmemcomppadctrl &= ~(0x0F); - regs->sdmemcomppadctrl |= 0x07; - - // Set ourselves up to have a stable. - rc = sdmmc_set_up_clocking_parameters(mmc, mmc->operating_voltage); - if (rc) { - mmc_print(mmc, "WARNING: could not optimize card clocking parameters. (%d)", rc); - } - - // Set PAD_E_INPUT_OR_E_PWRD - regs->sdmemcomppadctrl |= 0x80000000; - - // Wait one milisecond - udelay(1000); - - // Run automatic calibration. - rc = sdmmc_run_autocal(mmc, false); - if (rc) { - mmc_print(mmc, "autocal failed! (%d)", rc); - return rc; - } - - // Clear PAD_E_INPUT_OR_E_PWRD (relevant for eMMC only) - regs->sdmemcomppadctrl &= ~(0x80000000); - - // Set SDHCI_CLOCK_INT_EN - regs->clock_control |= 0x01; - - // Program a timeout of 2000ms - timebase = get_time(); - is_timeout = false; - - // Wait for SDHCI_CLOCK_INT_STABLE to be set - while (!(regs->clock_control & 0x02) && !is_timeout) { - // Keep checking if timeout expired - is_timeout = get_time_since(timebase) > 2000000; - } - - // Clock failed to stabilize - if (is_timeout) { - mmc_print(mmc, "clock never stabalized!"); - return -1; - } - - // FIXME: replace this to support better clocks - regs->host_control2 = 0; - - // Clear SDHCI_PROG_CLOCK_MODE - regs->clock_control &= ~(0x20); - - // Ensure we're using Single-operation DMA (SDMA) mode for DMA. - regs->host_control &= ~MMC_DMA_SELECT_MASK; - - // Set the timeout to be the maximum value - regs->timeout_control &= ~(0x0F); - regs->timeout_control |= 0x0E; - - // Ensure we start off using a single-bit bus. - mmc->regs->host_control &= ~MMC_HOST_BUS_WIDTH_MASK; - - // TODO: move me into enable voltages, if applicable? - - // Clear TAP_VAL_UPDATED_BY_HW - regs->vendor_tuning_cntrl0 &= ~(0x20000); - - // Start off in non-high-speed mode. - regs->host_control &= ~MMC_HOST_ENABLE_HIGH_SPEED; - - // Clear SDHCI_CTRL_VDD_180 - regs->host_control2 &= ~(0x08); - - // Set up the card's initialization. - rc = sdmmc_apply_clock_speed(mmc, SDMMC_SPEED_INIT, true); - if (rc) { - mmc_print(mmc, "ERROR: could not set SDMMC card speed!"); - return rc; - } - - return 0; -} - - -/* - * Blocks until the card has reached a given physical state, - * as indicated by the present state register. - * - * @param mmc The MMC controller whose state we should wait on - * @param present_state_mask A mask that indicates when we should return. - * Returns when the mask bits are no longer set in present_state if invert is true, - * or true when the mask bits are _set_ in the present state if invert is false. - * - * @return 0 on success, or an error on failure - */ -static int sdmmc_wait_for_physical_state(struct mmc *mmc, uint32_t present_state_mask, bool invert) -{ - uint32_t timebase = get_time(); - uint32_t condition; - - // Retry until the event or an error happens - while (true) { - - // Handle timeout. - if (get_time_since(timebase) > mmc->timeout) { - mmc_print(mmc, "timed out waiting for command readiness!"); - return ETIMEDOUT; - } - - // Read the status, and invert the condition, if necessary. - condition = mmc->regs->present_state & present_state_mask; - if (invert) { - condition = !condition; - } - - // Return once our condition is met. - if (condition) - return 0; - } -} - - -/** - * Blocks until the SD driver is ready for a command, - * or the MMC controller's timeout interval is met. - * - * @param mmc The MMC controller - */ -static int sdmmc_wait_for_command_readiness(struct mmc *mmc) -{ - return sdmmc_wait_for_physical_state(mmc, MMC_COMMAND_INHIBIT, true); -} - - -/** - * Blocks until the SD driver is ready to transmit data, - * or the MMC controller's timeout interval is met. - * - * @param mmc The MMC controller whose data line we should wait for. - */ -static int sdmmc_wait_for_data_readiness(struct mmc *mmc) -{ - return sdmmc_wait_for_physical_state(mmc, MMC_DATA_INHIBIT, true); -} - - -/** - * Blocks until the SD driver's data lines are clear, - * indicating the card is no longer busy. - * - * @param mmc The MMC controller whose data line we should wait for. - */ -static int sdmmc_wait_until_no_longer_busy(struct mmc *mmc) -{ - return sdmmc_wait_for_physical_state(mmc, MMC_DAT0_LINE_STATE, false); -} - -/** - * Handles an event in which the given SDMMC controller's DMA buffers have - * become full, and must be emptied again before they can be used. - * - * @param mmc The MMC controller that has suffered a full buffer. - */ -static int sdmmc_flush_bounce_buffer(struct mmc *mmc) -{ - // Determine the total amount copied by subtracting the current pointer from - // its starting address-- effectively by figuring out how far we got in the bounce buffer. - uint32_t total_copied = mmc->regs->dma_address - (uint32_t)sdmmc_bounce_buffer; - - // If we have a DMA buffer we're copying to, empty it out. - if (mmc->active_data_buffer) { - - // Copy the data to the user buffer, and advance in the user buffer - // by the amount coppied. - memcpy((void *)mmc->active_data_buffer, sdmmc_bounce_buffer, total_copied); - mmc->active_data_buffer += total_copied; - } - - // Reset the DMA to point at the beginning of our bounce buffer for another interation. - mmc->regs->dma_address = (uint32_t)sdmmc_bounce_buffer; - return 0; -} - -/** - * Generic SDMMC waiting function. - * - * @param mmc The MMC controller on which to wait. - * @param target_irq A bitmask that specifies the interrupt bits that - * will make this function return success. - * @param state_condition A bitmask that specifies a collection of bits - * that indicate business in present_state. If zero, all of the relevant - * conditions becoming false will cause a sucessful return. - * @param fault_conditions A bitmask that specifies the bits that - * will make this function trigger its fault handler. - * @param fault_handler A function that's called to handle DMA faults. - * If it returns nonzero, this method will abort immediately; if it - * returns zero, it'll clear the error and continue. - * - * @return 0 on sucess, EFAULT if a fault condition occurs, - * or an error code if a transfer failure occurs - */ -static int sdmmc_wait_for_event(struct mmc *mmc, - uint32_t target_irq, uint32_t state_conditions, - uint32_t fault_conditions, fault_handler_t fault_handler) -{ - uint32_t timebase = get_time(); - uint32_t intstatus; - int rc; - - // Wait until we either wind up ready, or until we've timed out. - while (true) { - if (get_time_since(timebase) > mmc->timeout) - return ETIMEDOUT; - - // Read intstatus into temporary variable to make sure that the - // priorities are: fault conditions, target irq, errors - // This makes sure that if fault conditions and target irq - // comes nearly at the same time that the fault handler will - // always be called - intstatus = mmc->regs->int_status; - if (intstatus & fault_conditions) { - - // If we don't have a handler, fault. - if (!fault_handler) { - mmc_print(mmc, "ERROR: unhandled DMA fault!"); - return EFAULT; - } - - // Call the DMA fault handler. - rc = fault_handler(mmc); - if (rc) { - mmc_print(mmc, "ERROR: unhandled DMA fault! (%d)", rc); - return rc; - } - - // Finally, EOI the relevant interrupt. - mmc->regs->int_status = fault_conditions; - intstatus &= ~(fault_conditions); - - // Reset the timebase, so it applies to the next - // DMA interval. - timebase = get_time(); - } - - if (intstatus & target_irq) - return 0; - - if (state_conditions && !(mmc->regs->present_state & state_conditions)) - return 0; - - // If an error occurs, return it. - if (intstatus & MMC_STATUS_ERROR_MASK) - return (intstatus & MMC_STATUS_ERROR_MASK); - } -} - -/** - * Blocks until the SD driver has completed issuing a command. - * - * @param mmc The MMC controller - */ -static int sdmmc_wait_for_command_completion(struct mmc *mmc) -{ - return sdmmc_wait_for_event(mmc, MMC_STATUS_COMMAND_COMPLETE, 0, 0, NULL); -} - - -/** - * Blocks until the SD driver has completed issuing a command. - * - * @param mmc The MMC controller - */ -static int sdmmc_wait_for_transfer_completion(struct mmc *mmc) -{ - int rc = sdmmc_wait_for_event(mmc, MMC_STATUS_TRANSFER_COMPLETE, - MMC_WRITE_ACTIVE | MMC_READ_ACTIVE, MMC_STATUS_DMA_INTERRUPT, sdmmc_flush_bounce_buffer); - - - return rc; -} - - -/** - * Returns the block order for a given operation on the MMC controller. - * - * @param mmc The MMC controller for which we're quierying block size. - * @param is_write True iff the given operation is a write. - */ -static uint8_t sdmmc_get_block_order(struct mmc *mmc, bool is_write) -{ - if (is_write) - return mmc->write_block_order; - else - return mmc->read_block_order; -} - - -/** - * Returns the block size for a given operation on the MMC controller. - * - * @param mmc The MMC controller for which we're quierying block size. - * @param is_write True iff the given operation is a write. - */ -static uint32_t sdmmc_get_block_size(struct mmc *mmc, bool is_write) -{ - return (1 << sdmmc_get_block_order(mmc, is_write)); -} - - -/** - * Handles execution of a DATA stage using the CPU, rather than by using DMA. - * - * @param mmc The MMc controller to work with. - * @param blocks The number of blocks to work with. - * @param is_write True iff the data is being set _to_ the CARD. - * @param data_buffer The data buffer to be transmitted or populated. - * - * @return 0 on success, or an error code on failure. - */ -static int sdmmc_handle_cpu_transfer(struct mmc *mmc, uint16_t blocks, bool is_write, void *data_buffer) -{ - uint16_t blocks_remaining = blocks; - uint16_t bytes_remaining_in_block; - - uint32_t timebase = get_time(); - - // Get a window that lets us work with the data buffer in 32-bit chunks. - uint32_t *buffer = data_buffer; - - // Figure out the mask to check based on whether this is a read or a write. - uint32_t mask = is_write ? MMC_BUFFER_WRITE_ENABLE : MMC_BUFFER_READ_ENABLE; - - // While we have blocks left to read... - while (blocks_remaining) { - - // Get the number of bytes per block read. - bytes_remaining_in_block = sdmmc_get_block_size(mmc, false); - - // Wait for a block read to complete. - while (!(mmc->regs->present_state & mask)) { - - // If an error occurs, return it. - if (mmc->regs->int_status & MMC_STATUS_ERROR_MASK) { - return (mmc->regs->int_status & MMC_STATUS_ERROR_MASK); - } - - // Check for timeout. - if (get_time_since(timebase) > mmc->timeout) - return ETIMEDOUT; - } - - // While we've still bytes left to read. - while (bytes_remaining_in_block) { - - // Check for timeout. - if (get_time_since(timebase) > mmc->timeout) - return ETIMEDOUT; - - // Transfer the data to the relevant - if (is_write) { - if ((uintptr_t)buffer & 3) { - // Handle unaligned buffers - uint32_t w; - uint8_t *data = (uint8_t *)buffer; - w = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); - mmc->regs->buffer = w; - } else { - mmc->regs->buffer = *buffer; - } - } else { - if ((uintptr_t)buffer & 3) { - // Handle unaligned buffers - uint32_t w = mmc->regs->buffer; - uint8_t *data = (uint8_t *)buffer; - data[0] = w & 0xFF; - data[1] = (w >> 8) & 0xFF; - data[2] = (w >> 16) & 0xFF; - data[3] = (w >> 24) & 0xFF; - } else { - *buffer = mmc->regs->buffer; - } - } - - // Advance by a register size... - bytes_remaining_in_block -= sizeof(mmc->regs->buffer); - ++buffer; - } - - // Advice by a block... - --blocks_remaining; - } - - return 0; -} - -/** - * Prepare the data-related registers for command transmission. - * - * @param mmc The device to be used to transmit. - * @param blocks The total number of blocks to be transferred. - * @param is_write True iff we're sending data _to_ the card. - * @param auto_termiante True iff we should instruct the system - * to reclaim the data lines after a transaction. - */ -static void sdmmc_prepare_command_data(struct mmc *mmc, uint16_t blocks, - bool is_write, bool auto_terminate, bool use_dma, int argument) -{ - if (blocks) { - uint16_t block_size = sdmmc_get_block_size(mmc, is_write); - - // If we're using DMA, target our bounce buffer. - if (use_dma) - mmc->regs->dma_address = (uint32_t)sdmmc_bounce_buffer; - - // Set up the DMA block size and count. - // This is synchronized with the size of our bounce buffer. - mmc->regs->block_size = sdmmc_bounce_dma_boundary | block_size; - mmc->regs->block_count = blocks; - } - - // Populate the command argument. - mmc->regs->argument = argument; - - if (blocks) { - uint32_t to_write = MMC_TRANSFER_LIMIT_BLOCK_COUNT; - - // If this controller should use DMA, set that up. - if (use_dma) - to_write |= MMC_TRANSFER_DMA_ENABLE; - - // If this is a multi-block datagram, indicate so. - if (blocks > 1) - to_write |= MMC_TRANSFER_MULTIPLE_BLOCKS; - - // If this command should automatically terminate, set the host to - // terminate it after the block span is complete. - if (auto_terminate) { - // If we're in SDR104, use AUTO_CMD23 intead of AUTO_CMD12, - // per the host controller specification. - if (mmc->operating_speed == SDMMC_SPEED_SDR104) - to_write |= MMC_TRANSFER_AUTO_CMD23; - else - to_write |= MMC_TRANSFER_AUTO_CMD12; - } - - // If this is a read, set the READ mode. - if (!is_write) - to_write |= MMC_TRANSFER_CARD_TO_HOST; - - mmc->regs->transfer_mode = to_write; - } - -} - - -/** - * Prepare the command-related registers for command transmission. - * - * @param mmc The device to be used to transmit. - * @param blocks_to_xfer The total number of blocks to be transferred. - * @param command The command number to issue. - * @param response_type The type of response we'll expect. - */ -static void sdmmc_prepare_command_registers(struct mmc *mmc, int blocks_to_xfer, - enum sdmmc_command command, enum sdmmc_response_type response_type, enum sdmmc_response_checks checks) -{ - // Populate the command number - uint16_t to_write = (command << MMC_COMMAND_NUMBER_SHIFT) | (response_type << MMC_COMMAND_RESPONSE_TYPE_SHIFT) | checks; - - // If this is a "stop transmitting" command, set the abort flag. - if (command == CMD_STOP_TRANSMISSION) - to_write |= MMC_COMMAND_TYPE_ABORT; - - // If this command has a data stage, include it. - // Note that tuning commands are atypical, but are considered to have a data stage - // consiting of the tuning pattern. - if (blocks_to_xfer) - to_write |= MMC_COMMAND_HAS_DATA; - - // Write our command to the given register. - // This must be all done at once, as writes to this register have semantic meaning. - mmc->regs->command = to_write; -} - - -/** - * Enables or disables the SDMMC interrupts. - * We leave these masked, but checkt their status in their status register. - * - * @param mmc The eMMC device to work with. - * @param enabled True if interrupts should enabled, or false to disable them. - */ -static void sdmmc_enable_interrupts(struct mmc *mmc, bool enabled) -{ - // Get an mask that represents all interrupts. - uint32_t all_interrupts = - MMC_STATUS_COMMAND_COMPLETE | MMC_STATUS_TRANSFER_COMPLETE | - MMC_STATUS_DMA_INTERRUPT | MMC_STATUS_ERROR_MASK; - - // Clear any pending interrupts. - mmc->regs->int_status = all_interrupts; - - // And enable or disable the pseudo-interrupts. - if (enabled) { - mmc->regs->int_enable |= all_interrupts; - } else { - mmc->regs->int_enable &= ~all_interrupts; - } -} - -/** - * Handle the response to an SDMMC command, copying the data - * from the SDMMC response holding area to the user-provided response buffer. - */ -static int sdmmc_handle_command_response(struct mmc *mmc, - enum sdmmc_response_type type, void *response_buffer) -{ - uint32_t *buffer = (uint32_t *)response_buffer; - int rc; - - // If we don't have a place to put the response, - // skip copying it out. - if (!response_buffer) - return 0; - - - switch (type) { - - // Easy case: we don't have a response. We don't need to do anything. - case MMC_RESPONSE_NONE: - break; - - // If we have a response we have to wait on busy-completion for, - // wait for the DAT0 line to clear. - case MMC_RESPONSE_LEN48_CHK_BUSY: - mmc_print(mmc, "waiting for card to stop being busy..."); - rc = sdmmc_wait_until_no_longer_busy(mmc); - if (rc) { - mmc_print(mmc, "failure waiting for card to finish being busy (%d)", rc); - return rc; - } - // (fall-through) - - // If we have a 48-bit response, then we have 32 bits of response and 16 bits of CRC/command. - // The naming is a little odd, but that's thanks to the SDMMC standard. - case MMC_RESPONSE_LEN48: - *buffer = mmc->regs->response[0]; - break; - - // If we have a 136-bit response, we have 128 of response and 8 bits of CRC. - // TODO: validate that this is the right format/endianness/everything - case MMC_RESPONSE_LEN136: - - // Copy the response to the buffer manually. - // We avoid memcpy here, because this is volatile. - for(int i = 0; i < 4; ++i) - buffer[i] = mmc->regs->response[i]; - break; - - default: - mmc_print(mmc, "invalid response type; not handling response"); - } - - return 0; -} - - -/** - * Sends a command to the SD card, and awaits a response. - * - * @param mmc The SDMMC device to be used to transmit the command. - * @param response_type The type of response to expect-- mostly specifies the length. - * @param checks Determines which sanity checks the host controller should run. - * @param argument The argument to the SDMMC command. - * @param response_buffer A buffer to store the response. Should be at uint32_t for a LEN48 command, - * or 16 bytes for a LEN136 command. If this arguemnt is NULL, no response will be returned. - * @param blocks_to_transfer The number of SDMMC blocks to be transferred with the given command, - * or 0 to indicate that this command should not expect response data. - * @param is_write True iff the given command issues data _to_ the card, instead of vice versa. - * @param auto_terminate True iff the gven command needs to be terminated with e.g. CMD12 - * @param data_buffer A byte buffer that either contains the data to be sent, or which should - * receive data, depending on the is_write argument. - * - * @returns 0 on success, an error number on failure - */ -static int sdmmc_send_command(struct mmc *mmc, enum sdmmc_command command, - enum sdmmc_response_type response_type, enum sdmmc_response_checks checks, - uint32_t argument, void *response_buffer, uint16_t blocks_to_transfer, - bool is_write, bool auto_terminate, void *data_buffer) -{ - uint32_t total_data_to_xfer = sdmmc_get_block_size(mmc, is_write) * blocks_to_transfer; - int rc; - - // Store user data buffer for use by future DMA operations. - mmc->active_data_buffer = (uint32_t)data_buffer; - - // Sanity check: if this is a data transfer, make sure we have a data buffer... - if (blocks_to_transfer && !data_buffer) { - mmc_print(mmc, "WARNING: no data buffer provided, but this is a data transfer!"); - mmc_print(mmc, "this does nothing; but is supported for debug"); - } - - // Wait until we can issue commands to the device. - rc = sdmmc_wait_for_command_readiness(mmc); - if (rc) { - mmc_print(mmc, "card not willing to accept commands (%d / %08x)", rc, mmc->regs->present_state); - return -EBUSY; - } - - // If this is a data command, or a command that uses the data lines for busy-detection. - if (blocks_to_transfer || (response_type == MMC_RESPONSE_LEN48_CHK_BUSY)) { - rc = sdmmc_wait_for_data_readiness(mmc); - if (rc) { - mmc_print(mmc, "card not willing to accept data-commands (%d / %08x)", rc, mmc->regs->present_state); - return -EBUSY; - } - } - - // Periodically recalibrate the SD controller - if (mmc->controller == SWITCH_MICROSD) { - sdmmc_run_autocal(mmc, true); - } - - // If we have data to send, prepare it. - sdmmc_prepare_command_data(mmc, blocks_to_transfer, is_write, auto_terminate, mmc->use_dma, argument); - - // If this is a write and we have data, we'll need to populate the bounce buffer before - // issuing the command. - if (blocks_to_transfer && is_write && mmc->use_dma && data_buffer) - memcpy(sdmmc_bounce_buffer, (void *)mmc->active_data_buffer, total_data_to_xfer); - - // Ensure we get the status response we want. - sdmmc_enable_interrupts(mmc, true); - - // Configure the controller to send the command. - sdmmc_prepare_command_registers(mmc, blocks_to_transfer, command, response_type, checks); - - // Wait for the command to be completed. - rc = sdmmc_wait_for_command_completion(mmc); - if (rc) { - mmc_print(mmc, "failed to issue %s (arg=%x, rc=%d)", sdmmc_get_command_string(command), argument, rc); - mmc_print_command_errors(mmc, rc); - - sdmmc_enable_interrupts(mmc, false); - return rc; - } - - // Copy the response received to the output buffer, if applicable. - rc = sdmmc_handle_command_response(mmc, response_type, response_buffer); - if (rc) { - mmc_print(mmc, "failed to handle %s response! (%d)", sdmmc_get_command_string(command), rc); - return rc; - } - - // If we had a data stage, handle it. - if (blocks_to_transfer) { - - // If this is a DMA transfer, wait for its completion. - if (mmc->use_dma) { - - // Wait for the transfer to be complete... - rc = sdmmc_wait_for_transfer_completion(mmc); - if (rc) { - mmc_print(mmc, "failed to complete %s data stage via DMA (%d)", sdmmc_get_command_string(command), command, rc); - sdmmc_enable_interrupts(mmc, false); - return rc; - } - - // If this is a read, and we've just finished a transfer, copy the data from - // our bounce buffer to the target data buffer. - if (!is_write && data_buffer) - sdmmc_flush_bounce_buffer(mmc); - } - // Otherwise, perform the transfer using the CPU. - else { - rc = sdmmc_handle_cpu_transfer(mmc, blocks_to_transfer, is_write, data_buffer); - if (rc) { - mmc_print(mmc, "failed to complete CMD%d data stage via CPU (%d)", command, rc); - sdmmc_enable_interrupts(mmc, false); - return rc; - } - } - } - - // Disable resporting psuedo-interrupts. - // (This is mostly for when the GIC is brought up) - sdmmc_enable_interrupts(mmc, false); - - mmc_debug(mmc, "completed %s.", sdmmc_get_command_string(command)); - return 0; -} - - -/** - * Convenience function that sends a simple SDMMC command - * and awaits response. Wrapper around sdmmc_send_command. - * - * @param mmc The SDMMC device to be used to transmit the command. - * @param response_type The type of response to expect-- mostly specifies the length. - * @param argument The argument to the SDMMC command. - * @param response_buffer A buffer to store the response. Should be at uint32_t for a LEN48 command, - * or 16 bytes for a LEN136 command. - * - * @returns 0 on success, an error number on failure - */ -static int sdmmc_send_simple_command(struct mmc *mmc, enum sdmmc_command command, - enum sdmmc_response_type response_type, uint32_t argument, void *response_buffer) -{ - // If we don't expect a response, don't check; otherwise check everything. - enum sdmmc_response_checks checks = (response_type == MMC_RESPONSE_NONE) ? MMC_CHECKS_NONE : MMC_CHECKS_ALL; - - // Deletegate the full checks function. - return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer, 0, false, false, NULL); -} - - -/** - * Sends an SDMMC application command. - * - * @param mmc The SDMMC device to be used to transmit the command. - * @param response_type The type of response to expect-- mostly specifies the length. - * @param checks Determines which sanity checks the host controller should run. - * @param argument The argument to the SDMMC command. - * @param response_buffer A buffer to store the response. Should be at uint32_t for a LEN48 command, - * or 16 bytes for a LEN136 command. - * - * @returns 0 on success, an error number on failure - */ -static int sdmmc_send_app_command(struct mmc *mmc, enum sdmmc_command command, - enum sdmmc_response_type response_type, enum sdmmc_response_checks checks, - uint32_t argument, void *response_buffer, uint16_t blocks_to_transfer, - bool auto_terminate, void *data_buffer) -{ - int rc; - - // First, send the application command. - rc = sdmmc_send_simple_command(mmc, CMD_APP_COMMAND, MMC_RESPONSE_LEN48, mmc->relative_address << 16, NULL); - if (rc) { - mmc_print(mmc, "failed to prepare application command %s! (%d)", sdmmc_get_command_string(command), rc); - return rc; - } - - // And issue the body of the command. - return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer, - blocks_to_transfer, false, auto_terminate, data_buffer); -} - - -/** - * Sends an SDMMC application command. - * - * @param mmc The SDMMC device to be used to transmit the command. - * @param response_type The type of response to expect-- mostly specifies the length. - * @param checks Determines which sanity checks the host controller should run. - * @param argument The argument to the SDMMC command. - * @param response_buffer A buffer to store the response. Should be at uint32_t for a LEN48 command, - * or 16 bytes for a LEN136 command. - * - * @returns 0 on success, an error number on failure - */ -static int sdmmc_send_simple_app_command(struct mmc *mmc, enum sdmmc_command command, - enum sdmmc_response_type response_type, enum sdmmc_response_checks checks, - uint32_t argument, void *response_buffer) -{ - // Deletegate to the full app command function. - return sdmmc_send_app_command(mmc, command, response_type, checks, argument, response_buffer, 0, false, NULL); -} - - -/** - * Reads a collection of bits from the CSD register. - * - * @param csd An array of four uint32_ts containing the CSD. - * @param start The bit number to start at. - * @param width. The width of the relveant read. - * - * @returns the extracted bits - */ -static uint32_t sdmmc_extract_csd_bits(uint32_t *csd, int start, int width) -{ - uint32_t relevant_dword, result; - int offset_into_dword, bits_into_next_dword; - - // Sanity check our span. - if ((start + width) > 128) { - printk("MMC ERROR: invalid CSD slice!\n"); - return 0xFFFFFFFF; - } - - // Figure out where the relevant range is in our CSD. - relevant_dword = csd[start / 32]; - offset_into_dword = start % 32; - - // Grab all the bits we can from the relevant DWORD. - result = relevant_dword >> offset_into_dword; - - // Special case: if we spanned a word boundary, we'll - // need to read one word. - // - // FIXME: I'm writing this at 5AM, and this requires basic arithemtic, - // my greatest weakness. This is going to be stupid wrong. - if (offset_into_dword + width > 32) { - bits_into_next_dword = (offset_into_dword + width) - 32; - - // Grab the next dword in the CSD... - relevant_dword = csd[(start / 32) + 1]; - - // ... mask away the bits higher than the bits we want... - relevant_dword &= (1 << (bits_into_next_dword)) - 1; - - // .. and shift the relevant bits up to their position. - relevant_dword <<= (width - bits_into_next_dword); - - // Finally, combine in the new word. - result |= relevant_dword; - } - - return result; -} - - -/** - * Parses a fetched CSD per the Version 1 standard. - * - * @param mmc The MMC structure to be populated. - * @param csd A four-dword array containing the read CSD. - * - * @returns int 0 on success, or an error code if the CSD appears invalid - */ -static int sdmmc_parse_csd_version1(struct mmc *mmc, uint32_t *csd) -{ - // Get the maximum allowed read-block size. - mmc->read_block_order = sdmmc_extract_csd_bits(csd, MMC_CSD_V1_READ_BL_LENGTH_START, MMC_CSD_V1_READ_BL_LENGTH_WIDTH); - - // TODO: handle other attributes - return 0; -} - - -/** - * Decides on a block transfer sized based on the information observed, - * and applies it to the card. - * - * @param mmc The controller to use to set the order - * @param block_order The order (log-base-2) of the block size to be used. - */ -static int sdmmc_use_block_size(struct mmc *mmc, int block_order) -{ - int rc; - - // Inform the card of the block size we'll want to use. - rc = sdmmc_send_simple_command(mmc, CMD_SET_BLKLEN, MMC_RESPONSE_LEN48, 1 << block_order, NULL); - if (rc) { - mmc_print(mmc, "could not fetch the CID"); - return ENODEV; - } - - // On success, store the relevant block size. - mmc->read_block_order = block_order; - mmc->write_block_order = block_order; - return 0; -} - - -/** - * Reads the active SD card's SD Configuration Register, and updates the object's properties. - * - * @param mmc The controller with which to query and to update. - * @returns 0 on success, or an errno on failure - */ -static int sdmmc_read_and_parse_scr(struct mmc *mmc) -{ - int rc; - struct sdmmc_scr scr; - - // Read the current block order, so we can restore it. - int original_block_order = sdmmc_get_block_order(mmc, false); - - // Always request a single 8-byte block. - const int block_order = 3; - const int num_blocks = 1; - - // Momentarily step down to a smaller block size, so we don't - // have to allocate a huge buffer for this command. - mmc->read_block_order = block_order; - - // Request the CSD from the device. - rc = sdmmc_send_app_command(mmc, CMD_APP_SEND_SCR, MMC_RESPONSE_LEN48, MMC_CHECKS_ALL, 0, NULL, num_blocks, false, &scr); - if (rc) { - mmc_print(mmc, "could not get the card's SCR!"); - mmc->read_block_order = original_block_order; - return rc; - } - - // Store the SCR data. - mmc->spec_version = scr.spec_version; - - // Restore the original block order. - mmc->read_block_order = original_block_order; - - return 0; -} - - -/** - * Reads the active MMC card's Card Specific Data, and updates the MMC object's properties. - * - * @param mmc The MMC to be queired and updated. - * @returns 0 on success, or an errno on failure - */ -static int sdmmc_read_and_parse_csd(struct mmc *mmc) -{ - int rc; - uint32_t csd[4]; - uint16_t csd_version; - - // Request the CSD from the device. - rc = sdmmc_send_simple_command(mmc, CMD_SEND_CSD, MMC_RESPONSE_LEN136, mmc->relative_address << 16, csd); - if (rc) { - mmc_print(mmc, "could not get the card's CSD!"); - return ENODEV; - } - - // Figure out the CSD version. - csd_version = sdmmc_extract_csd_bits(csd, MMC_CSD_STRUCTURE_START, MMC_CSD_STRUCTURE_WIDTH); - - // Handle each CSD version. - switch (csd_version) { - - // Handle version 1 CSDs. - // (The Switch eMMC appears to always use ver1 CSDs.) - case MMC_CSD_VERSION1: - return sdmmc_parse_csd_version1(mmc, csd); - - // For now, don't support any others. - default: - mmc_print(mmc, "ERROR: we don't currently support cards with v%d CSDs!", csd_version); - return ENOTTY; - } -} - - -/** - * Reads the active MMC card's Card Specific Data, and updates the MMC object's properties. - * - * @param mmc The MMC to be queired and updated. - * @returns 0 on success, or an errno on failure - */ -static int sdmmc_read_and_parse_ext_csd(struct mmc *mmc) -{ - int rc; - uint8_t ext_csd[MMC_EXT_CSD_SIZE]; - - // Read the single EXT CSD block. - rc = sdmmc_send_command(mmc, CMD_SEND_EXT_CSD, MMC_RESPONSE_LEN48, - MMC_CHECKS_ALL, 0, NULL, 1, false, false, ext_csd); - if (rc) { - mmc_print(mmc, "ERROR: failed to read the extended CSD!"); - return rc; - } - - /** - * Parse the extended CSD: - */ - - // Hardware partition support. - mmc->partition_support = ext_csd[MMC_EXT_CSD_PARTITION_SUPPORT]; - mmc->partition_config = ext_csd[MMC_EXT_CSD_PARTITION_CONFIG] & ~MMC_EXT_CSD_PARTITION_SELECT_MASK; - mmc->partition_switch_time = ext_csd[MMC_EXT_CSD_PARTITION_SWITCH_TIME] * MMC_EXT_CSD_PARTITION_SWITCH_SCALE_US; - mmc->partitioned = ext_csd[MMC_EXT_CSD_PARTITION_SETTING_COMPLETE] & MMC_EXT_CSD_PARTITION_SETTING_COMPLETED; - mmc->partition_attribute = ext_csd[MMC_EXT_CSD_PARTITION_ATTRIBUTE]; - - // Speed support. - mmc->mmc_card_type = ext_csd[MMC_EXT_CSD_CARD_TYPE]; - - return 0; -} - - -/** - * Switches the SDMMC card and controller to the fullest bus width possible. - * - * @param mmc The MMC controller to switch up to a full bus width. - */ -static int sdmmc_mmc_switch_bus_width(struct mmc *mmc, enum sdmmc_bus_width width) -{ - // Ask the card to adjust to the wider bus width. - int rc = mmc->switch_mode(mmc, MMC_SWITCH_EXTCSD_NORMAL, - MMC_BUS_WIDTH, width, mmc->timeout, NULL); - if (rc) { - mmc_print(mmc, "could not switch mode on the card side!"); - return rc; - } - - // Apply the same changes on the host side. - mmc->regs->host_control &= ~MMC_HOST_BUS_WIDTH_MASK; - switch (width) { - case MMC_BUS_WIDTH_4BIT: - mmc->regs->host_control |= MMC_HOST_BUS_WIDTH_4BIT; - break; - case MMC_BUS_WIDTH_8BIT: - mmc->regs->host_control |= MMC_HOST_BUS_WIDTH_8BIT; - break; - default: - break; - } - return 0; -} - - -/** - * Switches the SDMMC card and controller to the fullest bus width possible. - * - * @param mmc The MMC controller to switch up to a full bus width. - */ -static int sdmmc_sd_switch_bus_width(struct mmc *mmc, enum sdmmc_bus_width width) -{ - // By default, SD DAT3 is used for card detect. We'll need to - // release it from this function by dropping its pull-up resistor - // before we can use the line for data. Do so. - int rc = sdmmc_send_simple_app_command(mmc, CMD_APP_SET_CARD_DETECT, - MMC_RESPONSE_LEN48, MMC_CHECKS_ALL, 0, NULL); - if (rc) { - mmc_print(mmc, "could not stop using DAT3 as a card detect!"); - return rc; - } - - // Ask the card to adjust to the wider bus width. - rc = sdmmc_send_simple_app_command(mmc, CMD_APP_SWITCH_WIDTH, - MMC_RESPONSE_LEN48, MMC_CHECKS_ALL, width, NULL); - if (rc) { - mmc_print(mmc, "could not switch mode on the card side!"); - return rc; - } - - // Apply the same changes on the host side. - mmc->regs->host_control &= ~MMC_HOST_BUS_WIDTH_MASK; - if (mmc->max_bus_width == SD_BUS_WIDTH_4BIT) { - mmc->regs->host_control |= MMC_HOST_BUS_WIDTH_4BIT; - } - - return 0; -} - - -/** - * Optimize our SDMMC transfer mode to fully utilize the bus. - */ -static int sdmmc_optimize_transfer_mode(struct mmc *mmc) -{ - int rc; - - // Switch the device to its maximum bus width. - rc = mmc->switch_bus_width(mmc, mmc->max_bus_width); - if (rc) { - mmc_print(mmc, "could not switch the controller's bus width!"); - return rc; - } - - // Automatically optimize speed as much as is possible. How this works depends on - // the type of card. - rc = mmc->optimize_speed(mmc); - if (rc) { - mmc_print(mmc, "could not optimize the controller's speed!"); - return rc; - } - - return 0; -} - - -/** - * Switches the active card and host controller to the given speed mode. - * - * @param mmc The MMC controller to affect. - * @param speed The speed to switch to. - * @param status_out The status result of the relevant switch operation. - */ -static int sdmmc_switch_bus_speed(struct mmc *mmc, enum sdmmc_bus_speed speed) -{ - int rc; - - // Ask the card to switch to the new speed. - rc = mmc->card_switch_bus_speed(mmc, speed); - if (rc) { - mmc_print(mmc, "WARNING: could not switch card to %s", sdmmc_get_speed_string(speed)); - return rc; - } - - // Switch the host controller so it talks the relevant speed. - rc = sdmmc_apply_clock_speed(mmc, speed, true); - if (rc) { - mmc_print(mmc, "WARNING: could not switch the host to %s", sdmmc_get_speed_string(speed)); - - // Fall back to the original speed before returning.. - sdmmc_apply_clock_speed(mmc, mmc->operating_speed, true); - return rc; - } - - mmc_debug(mmc, "now operating at %s!", sdmmc_get_speed_string(speed)); - return 0; -} - - -/** - * Switches the active SD card and host controller to the given speed mode. - * - * @param mmc The MMC controller to affect. - * @param speed The speed to switch to. - * @param status_out The status result of the relevant switch operation. - */ -static int sdmmc_sd_switch_bus_speed(struct mmc *mmc, enum sdmmc_bus_speed speed) -{ - struct sdmmc_function_status status_out; - int rc; - - // Read the supported functions from the card. - rc = mmc->switch_mode(mmc, SDMMC_SWITCH_MODE_MODE_APPLY, SDMMC_SWITCH_MODE_ACCESS_MODE, speed, 0, &status_out); - if (rc) { - mmc_print(mmc, "WARNING: could not issue the bus speed switch"); - return rc; - } - - // Check that the active operating mode has switched to the new mode. - if (status_out.active_access_mode != speed) { - mmc_print(mmc, "WARNING: device did not accept mode %s!", sdmmc_get_speed_string(speed)); - mmc_print(mmc, " reported mode is %s / %d", sdmmc_get_speed_string(status_out.active_access_mode), status_out.active_access_mode); - return EINVAL; - } - - return 0; -} - - -/** - * Switches the active MMC card and host controller to the given speed mode. - * - * @param mmc The MMC controller to affect. - * @param speed The speed to switch to. - * @param status_out The status result of the relevant switch operation. - */ -static int sdmmc_mmc_switch_bus_speed(struct mmc *mmc, enum sdmmc_bus_speed speed) -{ - int rc; - uint8_t ext_csd[MMC_EXT_CSD_SIZE]; - - // To disambiguate constants, we add ten to every MMC speed constant. - // we have to undo this before sending the constants out to the card. - uint32_t argument = speed - MMC_SPEED_MMC_OFFSET; - - // Read the supported functions from the card. - rc = mmc->switch_mode(mmc, MMC_SWITCH_MODE_WRITE_BYTE, MMC_HS_TIMING, argument, 0, NULL); - if (rc) { - mmc_print(mmc, "WARNING: could not issue the mode switch"); - return rc; - } - - // Read the single EXT-CSD block, which contains the current speed. - rc = sdmmc_send_command(mmc, CMD_SEND_EXT_CSD, MMC_RESPONSE_LEN48, - MMC_CHECKS_ALL, 0, NULL, 1, false, false, ext_csd); - if (rc) { - mmc_print(mmc, "ERROR: failed to read the extended CSD after mode-switch!"); - return rc; - } - - // Check the ext-csd to make sure the change took. - if (ext_csd[MMC_EXT_CSD_HS_TIMING] != argument) { - mmc_print(mmc, "WARNING: device did not accept mode %s!", sdmmc_get_speed_string(speed)); - mmc_print(mmc, " reported mode is %s / %d", sdmmc_get_speed_string(ext_csd[MMC_EXT_CSD_HS_TIMING]), ext_csd[MMC_EXT_CSD_HS_TIMING]); - return EINVAL; - } - - return 0; -} - - -/** - * Optimize our SDMMC transfer speed by maxing out the bus as much as is possible. - */ -static int sdmmc_sd_optimize_speed(struct mmc *mmc) -{ - int rc; - struct sdmmc_function_status function_status; - - // We started off with the controller opearting with a divided clock, - // which is meant to keep us within the pre-init operating frequency of 400kHz. - // We're now set up, so we can drop the divider. From this point forward, the - // clock is now driven by the CAR frequency. - rc = sdmmc_apply_clock_speed(mmc, SDMMC_SPEED_SDR12, true); - if (rc) { - mmc_print(mmc, "WARNING: could not step up to normal operating speeds!"); - mmc_print(mmc, " ... expect delays."); - return rc; - } - mmc_debug(mmc, "now operating at 12.5MB/s!"); - - // If we're not at a full bus width, we can't switch to a higher speed. - // We're already optimal, vacuously succeed. - if (mmc->max_bus_width != SD_BUS_WIDTH_4BIT) - return 0; - - // Read the supported functions from the card. - rc = mmc->switch_mode(mmc, SDMMC_SWITCH_MODE_MODE_QUERY, SDMMC_SWITCH_MODE_NO_GROUP, 0, 0, &function_status); - if (rc) { - mmc_print(mmc, "WARNING: could not query card mode status; speed will be limited"); - return rc; - } - - // Debug information for very vebose modes. - mmc_debug(mmc, "this card supports the following speed modes:"); - mmc_debug(mmc, "SDR12: %d SDR25: %d SDR50: %d SDR104: %d DDR50: %d\n", - function_status.sdr12_support, function_status.sdr25_support, - function_status.sdr50_support, function_status.sdr104_support, - function_status.ddr50_support); - - // If we're operating in a UHS-compatbile low-voltage mode, check for UHS-modes. - if (mmc->operating_voltage == MMC_VOLTAGE_1V8) { - - // Try each of the UHS-I modes, we support. - if (function_status.sdr104_support && !sdmmc_switch_bus_speed(mmc, SDMMC_SPEED_SDR104)) - return 0; - if (function_status.sdr50_support && !sdmmc_switch_bus_speed(mmc, SDMMC_SPEED_SDR50)) - return 0; - } - - // If we support High Speed but not a UHS-I mode, use it. - if (function_status.sdr25_support) - return sdmmc_switch_bus_speed(mmc, SDMMC_SPEED_SDR25); - - mmc_debug(mmc, "couldn't improve speed above the speed already set."); - return 0; -} - - -/** - * Optimize our MMC transfer speed by maxing out the bus as much as is possible. - */ -static int sdmmc_mmc_optimize_speed(struct mmc *mmc) -{ - int rc; - bool hs52_support, hs200_support, hs400_support; - - // XXX - sdmmc_set_loglevel(3); - - // We started off with the controller opearting with a divided clock, - // which is meant to keep us within the pre-init operating frequency of 400kHz. - // We're now set up, so we can drop the divider. From this point forward, the - // clock is now driven by the CAR frequency. - rc = sdmmc_apply_clock_speed(mmc, SDMMC_SPEED_SDR12, true); - if (rc) { - mmc_print(mmc, "WARNING: could not step up to normal operating speeds!"); - mmc_print(mmc, " ... expect delays."); - return rc; - } - mmc_debug(mmc, "now operating at 25MB/s!"); - - // Determine which high-speed modes are supported, for easy reference below. - hs200_support = mmc->mmc_card_type & MMC_EXT_CSD_CARD_TYPE_HS400_1V8; - hs400_support = mmc->mmc_card_type & MMC_EXT_CSD_CARD_TYPE_HS400_1V8; - hs52_support = mmc->mmc_card_type & MMC_EXT_CSD_CARD_TYPE_HS52; - - // First, try modes that are only supported at 1V8 and below, - // if we can. - if (mmc->operating_voltage == MMC_VOLTAGE_1V8) { - //if (hs400_support && !sdmmc_switch_bus_speed(mmc, SDMMC_SPEED_HS400)) - // return 0; - if (hs200_support && !sdmmc_switch_bus_speed(mmc, SDMMC_SPEED_HS200)) - return 0; - - (void)hs400_support; - } - - // Next, try the legacy "high speed" mode. - if (hs52_support) - return sdmmc_switch_bus_speed(mmc, SDMMC_SPEED_HS52); - - mmc_debug(mmc, "couldn't improve speed above the default"); - return 0; -} - - -/** - * Requests that an MMC target use the card's current relative address. - * - * @param mmc The SDMMC controller to work with. - * @return 0 on success, or an error code on failure. - */ -static int sdmmc_set_relative_address(struct mmc *mmc) -{ - int rc; - - // Set up the card's relative address. - rc = sdmmc_send_simple_command(mmc, CMD_SET_RELATIVE_ADDR, MMC_RESPONSE_LEN48, mmc->relative_address << 16, NULL); - if (rc) { - mmc_print(mmc, "could not set the card's relative address! (%d)", rc); - return rc; - } - - return 0; -} - - -/** - * Requests that an SD target report a relative address for us to use - * to communicate with it. - * - * @param mmc The SDMMC controller to work with. - * @return 0 on success, or an error code on failure. - */ -static int sdmmc_get_relative_address(struct mmc *mmc) -{ - int rc; - uint32_t response; - - // Set up the card's relative address. - rc = sdmmc_send_simple_command(mmc, CMD_GET_RELATIVE_ADDR, MMC_RESPONSE_LEN48, 0, &response); - if (rc) { - mmc_print(mmc, "could not get the card's relative address! (%d)", rc); - return rc; - } - - // Apply the fetched relative address. - mmc->relative_address = response >> 16; - return 0; -} - - -/** - * Shared card initialization for SD and MMC cards. - * Used to bring the card fully online and gather information about the card. - * - * @param mmc The MMC controller that will perform the initilaization. - */ -static int sdmmc_card_init(struct mmc *mmc) -{ - int rc; - uint32_t response[4]; - - // Retreive the card ID. - rc = sdmmc_send_simple_command(mmc, CMD_ALL_SEND_CID, MMC_RESPONSE_LEN136, 0, response); - if (rc) { - mmc_print(mmc, "could not fetch the CID"); - return rc; - } - - // Store the card ID for later. - memcpy(mmc->cid, response, sizeof(mmc->cid)); - - // Establish a relative address to communicate with - rc = mmc->establish_relative_address(mmc); - if (rc) { - mmc_print(mmc, "could not establish a relative address! (%d)", rc); - return rc; - } - - // Read and handle card's Card Specific Data (CSD). - rc = sdmmc_read_and_parse_csd(mmc); - if (rc) { - mmc_print(mmc, "could not populate CSD attributes! (%d)", rc); - return rc; - } - - // Select our eMMC card, so it knows we're talking to it. - rc = sdmmc_send_simple_command(mmc, CMD_TOGGLE_CARD_SELECT, MMC_RESPONSE_LEN48, mmc->relative_address << 16, response); - if (rc) { - mmc_print(mmc, "could not select the active card for use! (%d)", rc); - return rc; - } - - // Set up a block transfer size of 512B blocks. - // 1) every card supports this, and 2) we use SDMA, which only supports up to 512B - rc = sdmmc_use_block_size(mmc, MMC_DEFAULT_BLOCK_ORDER); - if (rc) { - mmc_print(mmc, "could not set up block transfer sizes! (%d)", rc); - return rc; - } - - return 0; -} - - -/** - * Blocks until the eMMC card is fully initialized. - * - * @param mmc The MMC device that should do the waiting. - */ -static int sdmmc_mmc_wait_for_card_readiness(struct mmc *mmc) -{ - int rc; - uint32_t response[4]; - - - while (true) { - - uint32_t response_masked; - - // Ask the SD card to identify its state. It will respond with readiness and a capacity magic. - int original_loglevel = sdmmc_set_loglevel(0); - rc = sdmmc_send_command(mmc, CMD_SEND_OPERATING_CONDITIONS, MMC_RESPONSE_LEN48, - MMC_CHECKS_NONE, 0x40000080, response, 0, false, false, NULL); - sdmmc_set_loglevel(original_loglevel); - - if (rc) { - mmc_print(mmc, "ERROR: could not read the card's operating conditions!"); - return rc; - } - - // Validate that this is a valid Switch eMMC. - // Per the spec, any card greater than 2GiB should respond with this magic number. - response_masked = response[0] & MMC_EMMC_OPERATING_COND_CAPACITY_MASK; - if (response_masked != MMC_EMMC_OPERATING_COND_CAPACITY_MAGIC) { - mmc_print(mmc, "ERROR: this doesn't appear to be a valid Switch eMMC!"); - return ENOTTY; - } - - // If the device has just become ready, we're done! - response_masked = response[0] & MMC_EMMC_OPERATING_READINESS_MASK; - if (response_masked == MMC_EMMC_OPERATING_COND_READY) { - return 0; - } - } -} - - -/** - * Blocks until the SD card is fully initialized. - * - * @param mmc The MMC device that should do the waiting. - * @aparam response Out argument that recieves the final, ready command response. - * Should have roon for uint32_t. - */ -static int sdmmc_sd_wait_for_card_readiness(struct mmc *mmc, uint32_t *response) -{ - int rc; - uint32_t argument = MMC_SD_OPERATING_COND_ACCEPTS_3V3; - - // If this is a SDv2 or higher card, check for an SDHC card, - // and for low-voltage support. - if (mmc->spec_version >= SD_VERSION_2_0) { - argument |= MMC_SD_OPERATING_COND_HIGH_CAPACITY; - argument |= MMC_SD_OPERATING_COND_ACCEPTS_1V8; - } - - while (true) { - - // Ask the SD card to identify its state. - int original_loglevel = sdmmc_set_loglevel(0); - rc = sdmmc_send_simple_app_command(mmc, CMD_APP_SEND_OP_COND, - MMC_RESPONSE_LEN48, MMC_CHECKS_NONE, argument, response); - sdmmc_set_loglevel(original_loglevel); - if (rc) { - mmc_print(mmc, "ERROR: could not read the card's operating conditions!"); - return rc; - } - - // If the device has just become ready, we're done! - if (response[0] & MMC_SD_OPERATING_COND_READY) - return 0; - - // Wait a delay so we're not spamming the card incessantly. - udelay(1000); - } -} - - -/** - * Handles MMC-specific card initialization. - */ -static int sdmmc_mmc_card_init(struct mmc *mmc) -{ - int rc; - - mmc_debug(mmc, "setting up card as MMC"); - - // Bring the bus out of its idle state. - rc = sdmmc_send_simple_command(mmc, CMD_GO_IDLE_OR_INIT, MMC_RESPONSE_NONE, 0, NULL); - if (rc) { - mmc_print(mmc, "could not bring bus to idle!"); - return rc; - } - - // Wait for the card to finish being busy. - rc = sdmmc_mmc_wait_for_card_readiness(mmc); - if (rc) { - mmc_print(mmc, "card failed to come up! (%d)", rc); - return rc; - } - - // Run the common core card initialization. - rc = sdmmc_card_init(mmc); - if (rc) { - mmc_print(mmc, "failed to set up card (%d)!", rc); - return rc; - } - - // Read and handle card's Extended Card Specific Data (ext-CSD). - rc = sdmmc_read_and_parse_ext_csd(mmc); - if (rc) { - mmc_print(mmc, "could not populate extended-CSD attributes! (%d)", rc); - return EPIPE; - } - - return 0; -} - - -/** - * Evalutes a check pattern response (used with interface commands) - * and validates that it contains our common check pattern. - * - * @param response The response recieved after a given command. - * @return True iff the given response has a valid check pattern. - */ -static bool sdmmc_check_pattern_present(uint32_t response) -{ - uint32_t pattern_byte = response & 0xFF; - return pattern_byte == MMC_IF_CHECK_PATTERN; -} - - -/** - * Handles SD-specific card initialization. - */ -static int sdmmc_sd_card_init(struct mmc *mmc) -{ - int rc; - uint32_t ocr, response; - - mmc_debug(mmc, "setting up card as SD"); - - // Bring the bus out of its idle state. - rc = sdmmc_send_simple_command(mmc, CMD_GO_IDLE_OR_INIT, MMC_RESPONSE_NONE, 0, NULL); - if (rc) { - mmc_print(mmc, "could not bring bus to idle!"); - return rc; - } - - // Validate that the card can handle working with the voltages we can provide. - rc = sdmmc_send_simple_command(mmc, CMD_SEND_IF_COND, MMC_RESPONSE_LEN48, MMC_IF_VOLTAGE_3V3 | MMC_IF_CHECK_PATTERN, &response); - if (rc || !sdmmc_check_pattern_present(response)) { - - // TODO: This is either a broken, SDv1 or MMC card. - // Handle the latter two cases as best we can. - - mmc_print(mmc, "ERROR: this card isn't an SDHC card!"); - mmc_print(mmc, " we don't yet support low-capacity cards. :("); - return rc; - } - // If this responded, indicate that this is a v2 card. - else { - // store that this is a v2 card - mmc->spec_version = SD_VERSION_2_0; - } - - // Wait for the card to finish being busy. - rc = sdmmc_sd_wait_for_card_readiness(mmc, &ocr); - if (rc) { - mmc_print(mmc, "card failed to come up! (%d)", rc); - return rc; - } - - // If the response indicated this was a high capacity card, - // always use block addressing. - mmc->uses_block_addressing = !!(ocr & MMC_SD_OPERATING_COND_HIGH_CAPACITY); - - // If the card supports using 1V8, drop down using lower voltages. - if (mmc->allow_voltage_switching && ocr & MMC_SD_OPERATING_COND_ACCEPTS_1V8) { - if (mmc->operating_voltage != MMC_VOLTAGE_1V8) { - rc = mmc->switch_to_low_voltage(mmc); - if (rc) - mmc_print(mmc, "WARNING: could not switch to low-voltage mode! (%d)", rc); - } - } - - // Run the common core card initialization. - rc = sdmmc_card_init(mmc); - if (rc) { - mmc_print(mmc, "failed to set up card (%d)!", rc); - return rc; - } - - // Read the card's SCR. - rc = sdmmc_read_and_parse_scr(mmc); - if (rc) { - mmc_print(mmc, "failed to read SCR! (%d)!", rc); - return rc; - } - - return 0; -} - - -/** - * @returns true iff the given READ_STATUS response indicates readiness - */ -static bool sdmmc_status_indicates_readiness(uint32_t status) -{ - // If the card is currently programming, it's not ready. - if ((status & MMC_STATUS_MASK) == MMC_STATUS_PROGRAMMING) - return false; - - // Return true iff the card is ready for data. - return status & MMC_STATUS_READY_FOR_DATA; -} - - -/** - * Waits for card readiness; should be issued after e.g. enabling partitioning. - * - * @param mmc The MMC to wait on. - * @param 0 if the wait completed with the card being ready; or an error code otherwise - */ -static int sdmmc_wait_for_card_ready(struct mmc *mmc, uint32_t timeout) -{ - int rc; - uint32_t status; - - uint32_t timebase = get_time(); - - while (true) { - // Read the card's status. - rc = sdmmc_send_simple_command(mmc, CMD_READ_STATUS, MMC_RESPONSE_LEN48, mmc->relative_address << 16, &status); - - // Ensure we haven't timed out. - if (get_time_since(timebase) > timeout) - return ETIMEDOUT; - - // If we couldn't read, try again. - if (rc) - continue; - - // Check to see if we hit a fatal error. - if (status & MMC_STATUS_CHECK_ERROR) - return EPIPE; - - // Check for ready status. - if (sdmmc_status_indicates_readiness(status)) - return 0; - } -} - - -/** - * Issues a SWITCH_MODE command, which can be used to write registers on the MMC card's controller, - * and thus to e.g. switch partitions. - * - * @param mmc The MMC device to use for comms. - * @param mode The access mode with which to access the controller. - * @param field The field to access. - * @param value The argument to the access mode. - * @param timeout The timeout, which is often longer than the normal MMC timeout. - * - * @return 0 on success, or an error code on failure - */ -static int sdmmc_mmc_switch_mode(struct mmc *mmc, int mode, int field, int value, uint32_t timeout, void *unused) -{ - // Collapse our various parameters into a single argument. - uint32_t argument = - (mode << MMC_SWITCH_ACCESS_MODE_SHIFT) | - (field << MMC_SWITCH_FIELD_SHIFT) | - (value << MMC_SWITCH_VALUE_SHIFT); - - // Issue the switch mode command. - int rc = sdmmc_send_simple_command(mmc, CMD_SWITCH_MODE, MMC_RESPONSE_LEN48_CHK_BUSY, argument, NULL); - if (rc){ - mmc_print(mmc, "failed to issue SWITCH_MODE command! (%d / %d / %d; rc=%d)", mode, field, value, rc); - return rc; - } - - // Wait until we have a sense of the card status to return. - if (timeout != 0) { - rc = sdmmc_wait_for_card_ready(mmc, timeout); - if (rc){ - mmc_print(mmc, "failed to talk to the card after SWITCH_MODE (%d)", rc); - return rc; - } - } - - return 0; -} - - -/** - * @return True iff the given MMC card supports hardare partitions. - */ -static bool sdmmc_supports_hardware_partitions(struct mmc *mmc) -{ - return mmc->partition_support & MMC_SUPPORTS_HARDWARE_PARTS; -} - - -/** - * card detect method for built-in cards. - */ -bool sdmmc_builtin_card_present(struct mmc *mmc) -{ - return true; -} - -/** - * card detect method for GPIO-based card detects - */ -bool sdmmc_external_card_present(struct mmc *mmc) -{ - return !gpio_read(mmc->card_detect_gpio); -} - -/** - * Issues an SD card mode-switch command. - * - * @param mmc The controller to use. - * @param mode The mode flag -- one to set function data, zero to query. - * @param group The SD card function group-- see the SD card Physical Layer spec. Set this negative to not apply arguments. - * @param response 64-byte buffer to store the response. - */ -static int sdmmc_sd_switch_mode(struct mmc *mmc, int mode, int group, int value, uint32_t timeout, void *response) -{ - int rc; - - // Read the current block order, so we can restore it. - int original_block_order = sdmmc_get_block_order(mmc, false); - - // Always request a single 64-byte block. - const int block_order = 6; - const int num_blocks = 1; - - // Build the argument we're going to issue. - uint32_t argument = (mode << SDMMC_SWITCH_MODE_MODE_SHIFT) | SDMMC_SWITCH_MODE_ALL_FUNCTIONS_UNUSED; - - // If we have a group argument, apply the group and value. - if(group >= 0) { - const int group_shift = group * SDMMC_SWITCH_MODE_GROUP_SIZE_BITS; - argument &= ~(SDMMC_SWITCH_MODE_FUNCTION_MASK << group_shift); - argument |= value << group_shift; - } - - // Momentarily step down to a smaller block size, so we don't - // have to allocate a huge buffer for this command. - mmc->read_block_order = block_order; - - // Issue the command itself. - rc = sdmmc_send_command(mmc, CMD_SWITCH_MODE, MMC_RESPONSE_LEN48, MMC_CHECKS_ALL, argument, NULL, num_blocks, false, false, response); - if (rc) { - mmc_print(mmc, "could not issue switch command!"); - mmc->read_block_order = original_block_order; - return rc; - } - - // Restore the original block order. - mmc->read_block_order = original_block_order; - - return 0; -} - - -/** - * Switches a given SDMMC Controller where - */ -static void sdmmc_apply_card_type(struct mmc *mmc, enum sdmmc_card_type type) -{ - // Store the card type for our own reference... - mmc->card_type = type; - - // Set up our per-protocol function pointers. - switch (type) { - - // MMC-protoco cards - case MMC_CARD_EMMC: - case MMC_CARD_MMC: - mmc->card_init = sdmmc_mmc_card_init; - mmc->establish_relative_address = sdmmc_set_relative_address; - mmc->switch_mode = sdmmc_mmc_switch_mode; - mmc->switch_bus_width = sdmmc_mmc_switch_bus_width; - mmc->card_switch_bus_speed = sdmmc_mmc_switch_bus_speed; - mmc->optimize_speed = sdmmc_mmc_optimize_speed; - - break; - - // SD-protocol cards - case MMC_CARD_SD: - mmc->card_init = sdmmc_sd_card_init; - mmc->establish_relative_address = sdmmc_get_relative_address; - mmc->switch_mode = sdmmc_sd_switch_mode; - mmc->switch_bus_width = sdmmc_sd_switch_bus_width; - mmc->optimize_speed = sdmmc_sd_optimize_speed; - mmc->card_switch_bus_speed = sdmmc_sd_switch_bus_speed; - break; - - // Switch-cart protocol cards - case MMC_CARD_CART: - printk("BUG: trying to use an impossible code path, hanging!\n"); - while(true); - } -} - - -/** - * Populates the given MMC object with defaults for its controller. - * - * @param mmc The mmc object to populate. - */ -static int sdmmc_initialize_defaults(struct mmc *mmc) -{ - // Set up based on the controller - switch (mmc->controller) { - case SWITCH_EMMC: - mmc->name = "eMMC"; - mmc->max_bus_width = MMC_BUS_WIDTH_8BIT; - mmc->tuning_block_order = MMC_TUNING_BLOCK_ORDER_8BIT; - mmc->operating_voltage = MMC_VOLTAGE_1V8; - - // Set up function pointers for each of our per-instance functions. - mmc->set_up_clock_and_io = sdmmc4_set_up_clock_and_io; - mmc->enable_supplies = sdmmc4_enable_supplies; - mmc->switch_to_low_voltage = sdmmc_always_fail; - mmc->card_present = sdmmc_builtin_card_present; - mmc->configure_clock = sdmmc4_configure_clock; - - // The EMMC controller always uses an EMMC card. - sdmmc_apply_card_type(mmc, MMC_CARD_EMMC); - - // The Switch's eMMC always uses block addressing. - mmc->uses_block_addressing = true; - break; - - case SWITCH_MICROSD: - mmc->name = "uSD"; - mmc->card_type = MMC_CARD_SD; - mmc->max_bus_width = SD_BUS_WIDTH_4BIT; - mmc->tuning_block_order = MMC_TUNING_BLOCK_ORDER_4BIT; - mmc->operating_voltage = MMC_VOLTAGE_3V3; - mmc->card_detect_gpio = GPIO_MICROSD_CARD_DETECT; - - // Per-instance functions. - mmc->set_up_clock_and_io = sdmmc1_set_up_clock_and_io; - mmc->enable_supplies = sdmmc1_enable_supplies; - mmc->switch_to_low_voltage = sdmmc1_switch_to_low_voltage; - mmc->card_present = sdmmc_external_card_present; - mmc->configure_clock = sdmmc1_configure_clock; - - // For the microSD card slot, assume we have an SD-type card. - // Negotiation has a chance to change this, later. - sdmmc_apply_card_type(mmc, MMC_CARD_SD); - - // Start off assuming byte addressing; we'll detect and correct this - // later, if necessary. - mmc->uses_block_addressing = false; - break; - - default: - printk("ERROR: initialization not yet writen for SDMMC%d", mmc->controller + 1); - return ENOSYS; - } - - return 0; -} - - -/** - * Set up a new SDMMC driver. - * - * @param mmc The SDMMC structure to be initiailized with the device state. - * @param controler The controller description to be used; usually SWITCH_EMMC - * or SWITCH_MICROSD. - * @param allow_voltage_switching True if we should allow voltage switching, - * which may not make sense if we're about to chainload to another component without - * preseving the overall structure. - */ -int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching) -{ - int rc; - - // Get a reference to the registers for the relevant SDMMC controller. - mmc->controller = controller; - mmc->regs = sdmmc_get_regs(controller); - mmc->allow_voltage_switching = allow_voltage_switching; - - // Set the defaults for the card, including the default function pointers - // for the assumed card type, and the per-controller options. - rc = sdmmc_initialize_defaults(mmc); - if (rc) { - printk("ERROR: controller SDMMC%d not currently supported!\n", controller + 1); - return rc; - } - - // Default to a timeout of 1s. - mmc->timeout = 1000000; - mmc->partition_switch_time = 1000; - - // Use DMA, by default. - mmc->use_dma = true; - - // Don't allow writing unless the caller explicitly enables it. - mmc->write_enable = SDMMC_WRITE_DISABLED; - - // Default to relative address of zero. - mmc->relative_address = 0; - - // Initialize the raw SDMMC controller. - rc = sdmmc_hardware_init(mmc); - if (rc) { - mmc_print(mmc, "failed to set up controller! (%d)", rc); - return rc; - } - - // ... and verify that the card is there. - if (!mmc->card_present(mmc)) { - mmc_print(mmc, "ERROR: no card detected!"); - return ENODEV; - } - - // Handle the initialization that's specific to the card type. - rc = mmc->card_init(mmc); - if (rc) { - mmc_print(mmc, "failed to set run card-specific initialization (%d)!", rc); - return rc; - } - - // Switch to a transfer mode that can more efficiently utilize the bus. - rc = sdmmc_optimize_transfer_mode(mmc); - if (rc) { - mmc_print(mmc, "WARNING: could not optimize bus utlization! (%d)", rc); - } - - return 0; -} - - -/** - * Imports a SDMMC driver struct from another program. This mainly intended for stage2, - * so that it can reuse stage1's SDMMC struct instance(s). - * - * @param mmc The SDMMC structure to be imported. - */ -int sdmmc_import_struct(struct mmc *mmc) -{ - int rc; - bool uses_block_addressing = mmc->uses_block_addressing; - mmc->regs = sdmmc_get_regs(mmc->controller); - - rc = sdmmc_initialize_defaults(mmc); - if (rc) { - printk("ERROR: controller SDMMC%d not currently supported!\n", mmc->controller + 1); - return rc; - } - - mmc->uses_block_addressing = uses_block_addressing; - return 0; -} - - -/** - * Selects the active MMC partition. Can be used to select - * boot partitions for access. Affects all operations going forward. - * - * @param mmc The MMC controller whose card is to be used. - * @param partition The partition number to be selected. - * - * @return 0 on success, or an error code on failure. - */ -int sdmmc_select_partition(struct mmc *mmc, enum sdmmc_partition partition) -{ - uint16_t argument = partition; - int rc; - - // If we're trying to access hardware partitions on a device that doesn't support them, - // bail out. - if (!sdmmc_supports_hardware_partitions(mmc)) - return ENOTTY; - - // Set the PARTITION_CONFIG register to select the active partition. - mmc_print(mmc, "switching to partition %d", partition); - rc = mmc->switch_mode(mmc, MMC_SWITCH_MODE_WRITE_BYTE, MMC_PARTITION_CONFIG, argument, 0, NULL); - if (rc) { - mmc_print(mmc, "failed to select partition %d (%02x, rc=%d)", partition, argument, rc); - } - - mmc_print(mmc, "waiting for %d us", mmc->partition_switch_time); - udelay(mmc->partition_switch_time); - - return rc; -} - - -/** - * Reads a sector or sectors from a given SD/MMC card. - * - * @param mmc The MMC device to work with. - * @param buffer The output buffer to target. - * @param block The sector number to read. - * @param count The number of sectors to read. - * - * @return 0 on success, or an error code on failure. - */ -int sdmmc_read(struct mmc *mmc, void *buffer, uint32_t block, unsigned int count) -{ - uint32_t command = (count == 1) ? CMD_READ_SINGLE_BLOCK : CMD_READ_MULTIPLE_BLOCK; - - // Determine the argument, which indicates which address we're reading/writing. - uint32_t extent = block; - - // If this card uses byte addressing rather than sector addressing, - // multiply by the block size. - if (!mmc->uses_block_addressing) { - extent *= sdmmc_get_block_size(mmc, false); - } - - // Execute the relevant read. - return sdmmc_send_command(mmc, command, MMC_RESPONSE_LEN48, MMC_CHECKS_ALL, extent, NULL, count, false, count > 1, buffer); -} - -/** - * Releases the SDMMC write lockout, enabling access to the card. - * Note that by default, setting this to WRITE_ENABLED will not allow access to eMMC. - * Check the source for a third constant that can be used to enable eMMC writes. - * - * @param perms The permissions to apply-- typically WRITE_DISABLED or WRITE_ENABLED. - */ -void sdmmc_set_write_enable(struct mmc *mmc, enum sdmmc_write_permission perms) -{ - mmc->write_enable = perms; -} - - -/** - * Writes a sector or sectors to a given SD/MMC card. - * - * @param mmc The MMC device to work with. - * @param buffer The input buffer to write. - * @param block The sector number to write from. - * @param count The number of sectors to write. - * - * @return 0 on success, or an error code on failure. - */ -int sdmmc_write(struct mmc *mmc, const void *buffer, uint32_t block, unsigned int count) -{ - // Sanity check variables: we're especially careful about allowing writes to the switch eMMC. - bool is_emmc = (mmc->controller == SWITCH_EMMC); - bool allow_mmc_write = (mmc->write_enable == SDMMC_WRITE_ENABLED_INCLUDING_EMMC); - - uint32_t command = (count == 1) ? CMD_WRITE_SINGLE_BLOCK : CMD_WRITE_MULTIPLE_BLOCK; - - // Determine the argument, which indicates which address we're reading/writing. - uint32_t extent = block; - - // If we don't have an explict write enable, don't allow writes. - if (mmc->write_enable == SDMMC_WRITE_DISABLED) { - mmc_print(mmc, "tried to write to an external card, but write was not enabled!"); - return EACCES; - } - - // Explicitly protect the switch's eMMC to prevent bricks. - if (is_emmc && !allow_mmc_write) { - mmc_print(mmc, "cowardly refusing to write to the switch's eMMMC"); - return EACCES; - } - - // If this card uses byte addressing rather than sector addressing, - // multiply by the block size. - if (!mmc->uses_block_addressing) { - extent *= sdmmc_get_block_size(mmc, true); - } - - // Execute the relevant read. - return sdmmc_send_command(mmc, command, MMC_RESPONSE_LEN48, MMC_CHECKS_ALL, extent, NULL, count, true, count > 1, (void *)buffer); -} - -/** - * Checks to see whether an SD card is present. - * - * @mmc mmc The controller with which to check for card presence. - * @return true iff a card is present - */ -bool sdmmc_card_present(struct mmc *mmc) -{ - return mmc->card_present(mmc); -} - -/** - * Prints out all of the tegra_mmc struct fields - * - * @mmc mmc The controller with which to dump registers. - */ -void sdmmc_dump_regs(struct mmc *mmc) { - mmc_debug(mmc, "dma_address: 0x%08" PRIX32 "\n",mmc->regs->dma_address); - mmc_debug(mmc, "block_size: 0x%04" PRIX16 "\n",mmc->regs->block_size); - mmc_debug(mmc, "block_count: 0x%04" PRIX16 "\n",mmc->regs->block_count); - mmc_debug(mmc, "argument: 0x%08" PRIX32 "\n",mmc->regs->argument); - mmc_debug(mmc, "transfer_mode: 0x%04" PRIX16 "\n",mmc->regs->transfer_mode); - mmc_debug(mmc, "command: 0x%04" PRIX16 "\n",mmc->regs->command); - mmc_debug(mmc, "response[0]: 0x%08" PRIX32 "\n",mmc->regs->response[0]); - mmc_debug(mmc, "response[1]: 0x%08" PRIX32 "\n",mmc->regs->response[1]); - mmc_debug(mmc, "response[2]: 0x%08" PRIX32 "\n",mmc->regs->response[2]); - mmc_debug(mmc, "response[3]: 0x%08" PRIX32 "\n",mmc->regs->response[3]); - mmc_debug(mmc, "buffer: 0x%08" PRIX32 "\n",mmc->regs->buffer); - mmc_debug(mmc, "present_state: 0x%08" PRIX32 "\n",mmc->regs->present_state); - mmc_debug(mmc, "host_control: 0x%02" PRIX8 "\n",mmc->regs->host_control); - mmc_debug(mmc, "power_control: 0x%02" PRIX8 "\n",mmc->regs->power_control); - mmc_debug(mmc, "block_gap_control: 0x%02" PRIX8 "\n",mmc->regs->block_gap_control); - mmc_debug(mmc, "wake_up_control: 0x%02" PRIX8 "\n",mmc->regs->wake_up_control); - mmc_debug(mmc, "clock_control: 0x%04" PRIX16 "\n",mmc->regs->clock_control); - mmc_debug(mmc, "timeout_control: 0x%02" PRIX8 "\n",mmc->regs->timeout_control); - mmc_debug(mmc, "software_reset: 0x%02" PRIX8 "\n",mmc->regs->software_reset); - mmc_debug(mmc, "int_status: 0x%08" PRIX32 "\n",mmc->regs->int_status); - mmc_debug(mmc, "int_enable: 0x%08" PRIX32 "\n",mmc->regs->int_enable); - mmc_debug(mmc, "signal_enable: 0x%08" PRIX32 "\n",mmc->regs->signal_enable); - mmc_debug(mmc, "acmd12_err: 0x%04" PRIX16 "\n",mmc->regs->acmd12_err); - mmc_debug(mmc, "host_control2: 0x%04" PRIX16 "\n",mmc->regs->host_control2); - mmc_debug(mmc, "capabilities: 0x%08" PRIX32 "\n",mmc->regs->capabilities); - mmc_debug(mmc, "capabilities_1: 0x%08" PRIX32 "\n",mmc->regs->capabilities_1); - mmc_debug(mmc, "max_current: 0x%08" PRIX32 "\n",mmc->regs->max_current); - mmc_debug(mmc, "set_acmd12_error: 0x%04" PRIX16 "\n",mmc->regs->set_acmd12_error); - mmc_debug(mmc, "set_int_error: 0x%04" PRIX16 "\n",mmc->regs->set_int_error); - mmc_debug(mmc, "adma_error: 0x%04" PRIX16 "\n",mmc->regs->adma_error); - mmc_debug(mmc, "adma_address: 0x%08" PRIX32 "\n",mmc->regs->adma_address); - mmc_debug(mmc, "upper_adma_address: 0x%08" PRIX32 "\n",mmc->regs->upper_adma_address); - mmc_debug(mmc, "preset_for_init: 0x%04" PRIX16 "\n",mmc->regs->preset_for_init); - mmc_debug(mmc, "preset_for_default: 0x%04" PRIX16 "\n",mmc->regs->preset_for_default); - mmc_debug(mmc, "preset_for_high: 0x%04" PRIX16 "\n",mmc->regs->preset_for_high); - mmc_debug(mmc, "preset_for_sdr12: 0x%04" PRIX16 "\n",mmc->regs->preset_for_sdr12); - mmc_debug(mmc, "preset_for_sdr25: 0x%04" PRIX16 "\n",mmc->regs->preset_for_sdr25); - mmc_debug(mmc, "preset_for_sdr50: 0x%04" PRIX16 "\n",mmc->regs->preset_for_sdr50); - mmc_debug(mmc, "preset_for_sdr104: 0x%04" PRIX16 "\n",mmc->regs->preset_for_sdr104); - mmc_debug(mmc, "preset_for_ddr50: 0x%04" PRIX16 "\n",mmc->regs->preset_for_ddr50); - mmc_debug(mmc, "slot_int_status: 0x%04" PRIX16 "\n",mmc->regs->slot_int_status); - mmc_debug(mmc, "host_version: 0x%04" PRIX16 "\n",mmc->regs->host_version); - mmc_debug(mmc, "vendor_clock_cntrl: 0x%08" PRIX32 "\n",mmc->regs->vendor_clock_cntrl); - mmc_debug(mmc, "vendor_sys_sw_cntrl: 0x%08" PRIX32 "\n",mmc->regs->vendor_sys_sw_cntrl); - mmc_debug(mmc, "vendor_err_intr_status: 0x%08" PRIX32 "\n",mmc->regs->vendor_err_intr_status); - mmc_debug(mmc, "vendor_cap_overrides: 0x%08" PRIX32 "\n",mmc->regs->vendor_cap_overrides); - mmc_debug(mmc, "vendor_boot_cntrl: 0x%08" PRIX32 "\n",mmc->regs->vendor_boot_cntrl); - mmc_debug(mmc, "vendor_boot_ack_timeout: 0x%08" PRIX32 "\n",mmc->regs->vendor_boot_ack_timeout); - mmc_debug(mmc, "vendor_boot_dat_timeout: 0x%08" PRIX32 "\n",mmc->regs->vendor_boot_dat_timeout); - mmc_debug(mmc, "vendor_debounce_count: 0x%08" PRIX32 "\n",mmc->regs->vendor_debounce_count); - mmc_debug(mmc, "vendor_misc_cntrl: 0x%08" PRIX32 "\n",mmc->regs->vendor_misc_cntrl); - mmc_debug(mmc, "max_current_override: 0x%08" PRIX32 "\n",mmc->regs->max_current_override); - mmc_debug(mmc, "max_current_override_hi: 0x%08" PRIX32 "\n",mmc->regs->max_current_override_hi); - mmc_debug(mmc, "vendor_io_trim_cntrl: 0x%08" PRIX32 "\n",mmc->regs->vendor_io_trim_cntrl); - mmc_debug(mmc, "vendor_dllcal_cfg: 0x%08" PRIX32 "\n",mmc->regs->vendor_dllcal_cfg); - mmc_debug(mmc, "vendor_dll_ctrl0: 0x%08" PRIX32 "\n",mmc->regs->vendor_dll_ctrl0); - mmc_debug(mmc, "vendor_dll_ctrl1: 0x%08" PRIX32 "\n",mmc->regs->vendor_dll_ctrl1); - mmc_debug(mmc, "vendor_dllcal_cfg_sta: 0x%08" PRIX32 "\n",mmc->regs->vendor_dllcal_cfg_sta); - mmc_debug(mmc, "vendor_tuning_cntrl0: 0x%08" PRIX32 "\n",mmc->regs->vendor_tuning_cntrl0); - mmc_debug(mmc, "vendor_tuning_cntrl1: 0x%08" PRIX32 "\n",mmc->regs->vendor_tuning_cntrl1); - mmc_debug(mmc, "vendor_tuning_status0: 0x%08" PRIX32 "\n",mmc->regs->vendor_tuning_status0); - mmc_debug(mmc, "vendor_tuning_status1: 0x%08" PRIX32 "\n",mmc->regs->vendor_tuning_status1); - mmc_debug(mmc, "vendor_clk_gate_hysteresis_count: 0x%08" PRIX32 "\n",mmc->regs->vendor_clk_gate_hysteresis_count); - mmc_debug(mmc, "vendor_preset_val0: 0x%08" PRIX32 "\n",mmc->regs->vendor_preset_val0); - mmc_debug(mmc, "vendor_preset_val1: 0x%08" PRIX32 "\n",mmc->regs->vendor_preset_val1); - mmc_debug(mmc, "vendor_preset_val2: 0x%08" PRIX32 "\n",mmc->regs->vendor_preset_val2); - mmc_debug(mmc, "sdmemcomppadctrl: 0x%08" PRIX32 "\n",mmc->regs->sdmemcomppadctrl); - mmc_debug(mmc, "auto_cal_config: 0x%08" PRIX32 "\n",mmc->regs->auto_cal_config); - mmc_debug(mmc, "auto_cal_interval: 0x%08" PRIX32 "\n",mmc->regs->auto_cal_interval); - mmc_debug(mmc, "auto_cal_status: 0x%08" PRIX32 "\n",mmc->regs->auto_cal_status); - mmc_debug(mmc, "io_spare: 0x%08" PRIX32 "\n",mmc->regs->io_spare); - mmc_debug(mmc, "sdmmca_mccif_fifoctrl: 0x%08" PRIX32 "\n",mmc->regs->sdmmca_mccif_fifoctrl); - mmc_debug(mmc, "timeout_wcoal_sdmmca: 0x%08" PRIX32 "\n",mmc->regs->timeout_wcoal_sdmmca); -} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/sdmmc.h b/fusee/fusee-secondary/src/sdmmc.h deleted file mode 100644 index 63538a405..000000000 --- a/fusee/fusee-secondary/src/sdmmc.h +++ /dev/null @@ -1,313 +0,0 @@ -/** - * Fusée SD/MMC driver for the Switch - * ~ktemkin - */ - -#ifndef __FUSEE_SDMMC_H__ -#define __FUSEE_SDMMC_H__ - -#include -#include -#include "utils.h" -#include "gpio.h" - -/* Opaque pointer to the Tegra SDMMC registers */ -struct tegra_sdmmc; - - -/** - * Bus widths supported by the SD/MMC cards. - */ -enum sdmmc_bus_width { - MMC_BUS_WIDTH_1BIT = 0, - MMC_BUS_WIDTH_4BIT = 1, - MMC_BUS_WIDTH_8BIT = 2, - - SD_BUS_WIDTH_1BIT = 0, - SD_BUS_WIDTH_4BIT = 2 -}; - - -/** - * Describes the voltages that the host will use to drive the SD card. - * CAUTION: getting these wrong can damage (especially embedded) cards! - */ -enum sdmmc_bus_voltage { - MMC_VOLTAGE_3V3 = 0b111, - MMC_VOLTAGE_1V8 = 0b101, -}; - - -/** - * Represents the different types of devices an MMC object - * can represent. - */ -enum sdmmc_card_type { - MMC_CARD_EMMC, - MMC_CARD_MMC, - MMC_CARD_SD, - MMC_CARD_CART, -}; - - - -/** - * Specification versions for SD/MMC cards. - */ -enum sdmmc_spec_version { - - /* MMC card versions */ - MMC_VERSION_4 = 0, - - /* SD card versions */ - SD_VERSION_1_0 = 0, - SD_VERSION_1_1 = 1, - SD_VERSION_2_0 = 2, - -}; - - -/** - * SDMMC controllers - */ -enum sdmmc_controller { - SWITCH_MICROSD = 0, - SWITCH_EMMC = 3 -}; - -/** - * Write permission modes for SD cards. - */ -enum sdmmc_write_permission { - SDMMC_WRITE_DISABLED, - SDMMC_WRITE_ENABLED, - - /* use this with the utmost caution so you don't wind up with a brick */ - SDMMC_WRITE_ENABLED_INCLUDING_EMMC, -}; - - -/** - * Methods by which we can touch registers accessed via. - * CMD_SWITCH_MODE. - */ -enum sdmmc_switch_access_mode { - - /* Normal commands */ - MMC_SWITCH_MODE_CMD_SET = 0, - MMC_SWITCH_MODE_SET_BITS = 1, - MMC_SWITCH_MODE_CLEAR_BITS = 2, - MMC_SWITCH_MODE_WRITE_BYTE = 3, - - /* EXTCSD access */ - MMC_SWITCH_EXTCSD_NORMAL = 1, -}; - - -/** - * Offsets into the SWITCH_MODE argument. - */ -enum sdmmc_switch_argument_offsets { - MMC_SWITCH_VALUE_SHIFT = 8, - MMC_SWITCH_FIELD_SHIFT = 16, - MMC_SWITCH_ACCESS_MODE_SHIFT = 24, -}; - - -/** - * Bus speeds possible for an SDMMC controller. - */ -enum sdmmc_bus_speed { - /* SD card speeds */ - SDMMC_SPEED_SDR12 = 0, - SDMMC_SPEED_SDR25 = 1, - SDMMC_SPEED_SDR50 = 2, - SDMMC_SPEED_SDR104 = 3, - SDMMC_SPEED_DDR50 = 4, - - /* Other speed: non-spec-compliant value used for e.g. HS400 */ - SDMMC_SPEED_OTHER = 5, - - /* eMMC card speeds */ - /* note: to avoid an enum clash, we add ten to these */ - SDMMC_SPEED_HS26 = 10 , - SDMMC_SPEED_HS52 = 11 , - SDMMC_SPEED_HS200 = 12 , - SDMMC_SPEED_HS400 = 13 , - - /* special speeds */ - SDMMC_SPEED_INIT = -1, -}; - - - -/** - * Primary data structure describing a Fusée MMC driver. - */ -struct mmc { - enum sdmmc_controller controller; - - /* Controller properties */ - const char *name; - bool use_dma; - bool allow_voltage_switching; - unsigned int timeout; - enum tegra_named_gpio card_detect_gpio; - enum sdmmc_write_permission write_enable; - - /* Per-controller operations. */ - int (*set_up_clock_and_io)(struct mmc *mmc); - void (*configure_clock)(struct mmc *mmc, uint32_t source, int car_divisor, int sdmmc_divisor); - int (*enable_supplies)(struct mmc *mmc); - int (*switch_to_low_voltage)(struct mmc *mmc); - bool (*card_present)(struct mmc *mmc); - - /* Per-card-type operations */ - int (*card_init)(struct mmc *mmc); - int (*establish_relative_address)(struct mmc *mmc); - int (*switch_mode)(struct mmc *mmc, int a, int b, int c, uint32_t timeout, void *response); - int (*switch_bus_width)(struct mmc *mmc, enum sdmmc_bus_width width); - int (*optimize_speed)(struct mmc *mmc); - int (*card_switch_bus_speed)(struct mmc *mmc, enum sdmmc_bus_speed speed); - - /* Card properties */ - enum sdmmc_card_type card_type; - uint32_t mmc_card_type; - - uint8_t cid[15]; - uint32_t relative_address; - uint8_t partitioned; - enum sdmmc_spec_version spec_version; - enum sdmmc_bus_width max_bus_width; - enum sdmmc_bus_voltage operating_voltage; - enum sdmmc_bus_speed operating_speed; - - uint8_t partition_support; - uint8_t partition_config; - uint8_t partition_attribute; - uint32_t partition_switch_time; - - uint8_t read_block_order; - uint8_t write_block_order; - uint8_t tuning_block_order; - bool uses_block_addressing; - - /* Current operation status flags */ - uint32_t active_data_buffer; - - /* Pointers to hardware structures */ - volatile struct tegra_sdmmc *regs; -}; - - - - -/** - * Primary data structure describing a Fusée MMC driver. - */ -struct mmc; - - -/** - * Parititions supported by the Switch eMMC. - */ -enum sdmmc_partition { - SDMMC_PARTITION_USER = 0, - SDMMC_PARTITION_BOOT0 = 1, - SDMMC_PARTITION_BOOT1 = 2, -}; - - -/** - * Sets the current SDMMC debugging loglevel. - * - * @param loglevel Current log level. A higher value prints more logs. - * @return The loglevel prior to when this was applied, for easy restoration. - */ -int sdmmc_set_loglevel(int loglevel); - - -/** - * Set up a new SDMMC driver. - * - * @param mmc The SDMMC structure to be initiailized with the device state. - * @param controler The controller description to be used; usually SWITCH_EMMC - * or SWITCH_MICROSD. - * @param allow_voltage_switching True if we should allow voltage switching, - * which may not make sense if we're about to chainload to another component without - * preseving the overall structure. - */ -int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching); - - -/** - * Imports a SDMMC driver struct from another program. This mainly intended for stage2, - * so that it can reuse stage1's SDMMC struct instance(s). - * - * @param mmc The SDMMC structure to be imported. - */ -int sdmmc_import_struct(struct mmc *mmc); - - -/** - * Selects the active MMC partition. Can be used to select - * boot partitions for access. Affects all operations going forward. - * - * @param mmc The MMC controller whose card is to be used. - * @param partition The partition number to be selected. - * - * @return 0 on success, or an error code on failure. - */ -int sdmmc_select_partition(struct mmc *mmc, enum sdmmc_partition partition); - - -/** - * Reads a sector or sectors from a given SD card. - * - * @param mmc The MMC device to work with. - * @param buffer The output buffer to target. - * @param sector The sector number to read. - * @param count The number of sectors to read. - */ -int sdmmc_read(struct mmc *mmc, void *buffer, uint32_t sector, unsigned int count); - - -/** - * Releases the SDMMC write lockout, enabling access to the card. - * Note that by default, setting this to WRITE_ENABLED will not allow access to eMMC. - * Check the source for a third constant that can be used to enable eMMC writes. - * - * @param perms The permissions to apply-- typically WRITE_DISABLED or WRITE_ENABLED. - */ -void sdmmc_set_write_enable(struct mmc *mmc, enum sdmmc_write_permission perms); - - -/** - * Writes a sector or sectors to a given SD/MMC card. - * - * @param mmc The MMC device to work with. - * @param buffer The input buffer to write. - * @param block The sector number to write from. - * @param count The number of sectors to write. - * - * @return 0 on success, or an error code on failure. - */ -int sdmmc_write(struct mmc *mmc, const void *buffer, uint32_t block, unsigned int count); - - -/** - * Checks to see whether an SD card is present. - * - * @mmc mmc The controller with which to check for card presence. - * @return true iff a card is present - */ -bool sdmmc_card_present(struct mmc *mmc); - -/** - * Prints out all of the tegra_mmc struct fields - * - * @mmc mmc The controller with which to dump registers. - */ -void sdmmc_dump_regs(struct mmc *mmc); - -#endif diff --git a/fusee/fusee-secondary/src/sdmmc/mmc.h b/fusee/fusee-secondary/src/sdmmc/mmc.h new file mode 100644 index 000000000..e357d00a4 --- /dev/null +++ b/fusee/fusee-secondary/src/sdmmc/mmc.h @@ -0,0 +1,448 @@ +/* + * Header for MultiMediaCard (MMC) + * + * Copyright 2002 Hewlett-Packard Company + * + * Use consistent with the GNU GPL is permitted, + * provided that this copyright notice is + * preserved in its entirety in all copies and derived works. + * + * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, + * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS + * FITNESS FOR ANY PARTICULAR PURPOSE. + * + * Many thanks to Alessandro Rubini and Jonathan Corbet! + * + * Based strongly on code by: + * + * Author: Yong-iL Joh + * + * Author: Andrew Christian + * 15 May 2002 + */ + +#ifndef LINUX_MMC_MMC_H +#define LINUX_MMC_MMC_H + +/* Standard MMC commands (4.1) type argument response */ + /* class 1 */ +#define MMC_GO_IDLE_STATE 0 /* bc */ +#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ +#define MMC_ALL_SEND_CID 2 /* bcr R2 */ +#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ +#define MMC_SET_DSR 4 /* bc [31:16] RCA */ +#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */ +#define MMC_SWITCH 6 /* ac [31:0] See below R1b */ +#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ +#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ +#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ +#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ +#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ +#define MMC_STOP_TRANSMISSION 12 /* ac R1b */ +#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ +#define MMC_BUS_TEST_R 14 /* adtc R1 */ +#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ +#define MMC_BUS_TEST_W 19 /* adtc R1 */ +#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */ +#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */ + + /* class 2 */ +#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ +#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ +#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ +#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */ +#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */ + + /* class 3 */ +#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ + + /* class 4 */ +#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ +#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ +#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ +#define MMC_PROGRAM_CID 26 /* adtc R1 */ +#define MMC_PROGRAM_CSD 27 /* adtc R1 */ + + /* class 6 */ +#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ +#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ +#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ + + /* class 5 */ +#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ +#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ +#define MMC_ERASE 38 /* ac R1b */ + + /* class 9 */ +#define MMC_FAST_IO 39 /* ac R4 */ +#define MMC_GO_IRQ_STATE 40 /* bcr R5 */ + + /* class 7 */ +#define MMC_LOCK_UNLOCK 42 /* adtc R1b */ + + /* class 8 */ +#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ +#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ + + /* class 11 */ +#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */ +#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */ +#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */ +#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */ +#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */ + +/* + * MMC_SWITCH argument format: + * + * [31:26] Always 0 + * [25:24] Access Mode + * [23:16] Location of target Byte in EXT_CSD + * [15:08] Value Byte + * [07:03] Always 0 + * [02:00] Command Set + */ + +/* + MMC status in R1, for native mode (SPI bits are different) + Type + e : error bit + s : status bit + r : detected and set for the actual command response + x : detected and set during command execution. the host must poll + the card by sending status command in order to read these bits. + Clear condition + a : according to the card state + b : always related to the previous command. Reception of + a valid command will clear it (with a delay of one command) + c : clear by read + */ + +#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ +#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ +#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ +#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ +#define R1_ERASE_PARAM (1 << 27) /* ex, c */ +#define R1_WP_VIOLATION (1 << 26) /* erx, c */ +#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ +#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ +#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ +#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ +#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ +#define R1_CC_ERROR (1 << 20) /* erx, c */ +#define R1_ERROR (1 << 19) /* erx, c */ +#define R1_UNDERRUN (1 << 18) /* ex, c */ +#define R1_OVERRUN (1 << 17) /* ex, c */ +#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ +#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ +#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ +#define R1_ERASE_RESET (1 << 13) /* sr, c */ +#define R1_STATUS(x) (x & 0xFFFFE000) +#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ +#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ +#define R1_SWITCH_ERROR (1 << 7) /* sx, c */ +#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ +#define R1_APP_CMD (1 << 5) /* sr, c */ + +#define R1_STATE_IDLE 0 +#define R1_STATE_READY 1 +#define R1_STATE_IDENT 2 +#define R1_STATE_STBY 3 +#define R1_STATE_TRAN 4 +#define R1_STATE_DATA 5 +#define R1_STATE_RCV 6 +#define R1_STATE_PRG 7 +#define R1_STATE_DIS 8 + +/* + * MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS + * R1 is the low order byte; R2 is the next highest byte, when present. + */ +#define R1_SPI_IDLE (1 << 0) +#define R1_SPI_ERASE_RESET (1 << 1) +#define R1_SPI_ILLEGAL_COMMAND (1 << 2) +#define R1_SPI_COM_CRC (1 << 3) +#define R1_SPI_ERASE_SEQ (1 << 4) +#define R1_SPI_ADDRESS (1 << 5) +#define R1_SPI_PARAMETER (1 << 6) +/* R1 bit 7 is always zero */ +#define R2_SPI_CARD_LOCKED (1 << 8) +#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */ +#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP +#define R2_SPI_ERROR (1 << 10) +#define R2_SPI_CC_ERROR (1 << 11) +#define R2_SPI_CARD_ECC_ERROR (1 << 12) +#define R2_SPI_WP_VIOLATION (1 << 13) +#define R2_SPI_ERASE_PARAM (1 << 14) +#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */ +#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE + +/* + * OCR bits are mostly in host.h + */ +#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ +#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ +#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ +#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ +#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */ +#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */ +#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */ +#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */ +#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */ +#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */ +#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */ +#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */ +#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */ +#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */ +#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */ +#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */ +#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ +#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ + +/* + * Card Command Classes (CCC) + */ +#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */ + /* (CMD0,1,2,3,4,7,9,10,12,13,15) */ + /* (and for SPI, CMD58,59) */ +#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */ + /* (CMD11) */ +#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */ + /* (CMD16,17,18) */ +#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */ + /* (CMD20) */ +#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */ + /* (CMD16,24,25,26,27) */ +#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */ + /* (CMD32,33,34,35,36,37,38,39) */ +#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */ + /* (CMD28,29,30) */ +#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */ + /* (CMD16,CMD42) */ +#define CCC_APP_SPEC (1<<8) /* (8) Application specific */ + /* (CMD55,56,57,ACMD*) */ +#define CCC_IO_MODE (1<<9) /* (9) I/O mode */ + /* (CMD5,39,40,52,53) */ +#define CCC_SWITCH (1<<10) /* (10) High speed switch */ + /* (CMD6,34,35,36,37,50) */ + /* (11) Reserved */ + /* (CMD?) */ + +/* + * CSD field definitions + */ + +#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ +#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ +#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */ +#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */ + +#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ +#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ +#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ +#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */ +#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */ + +/* + * EXT_CSD fields + */ + +#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */ +#define EXT_CSD_FLUSH_CACHE 32 /* W */ +#define EXT_CSD_CACHE_CTRL 33 /* R/W */ +#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ +#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */ +#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */ +#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */ +#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */ +#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ +#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ +#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ +#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ +#define EXT_CSD_HPI_MGMT 161 /* R/W */ +#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ +#define EXT_CSD_BKOPS_EN 163 /* R/W */ +#define EXT_CSD_BKOPS_START 164 /* W */ +#define EXT_CSD_SANITIZE_START 165 /* W */ +#define EXT_CSD_WR_REL_PARAM 166 /* RO */ +#define EXT_CSD_RPMB_MULT 168 /* RO */ +#define EXT_CSD_FW_CONFIG 169 /* R/W */ +#define EXT_CSD_BOOT_WP 173 /* R/W */ +#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ +#define EXT_CSD_PART_CONFIG 179 /* R/W */ +#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ +#define EXT_CSD_BUS_WIDTH 183 /* R/W */ +#define EXT_CSD_STROBE_SUPPORT 184 /* RO */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_POWER_CLASS 187 /* R/W */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_STRUCTURE 194 /* RO */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */ +#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */ +#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */ +#define EXT_CSD_PWR_CL_52_195 200 /* RO */ +#define EXT_CSD_PWR_CL_26_195 201 /* RO */ +#define EXT_CSD_PWR_CL_52_360 202 /* RO */ +#define EXT_CSD_PWR_CL_26_360 203 /* RO */ +#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ +#define EXT_CSD_S_A_TIMEOUT 217 /* RO */ +#define EXT_CSD_REL_WR_SEC_C 222 /* RO */ +#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ +#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ +#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ +#define EXT_CSD_BOOT_MULT 226 /* RO */ +#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ +#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */ +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ +#define EXT_CSD_TRIM_MULT 232 /* RO */ +#define EXT_CSD_PWR_CL_200_195 236 /* RO */ +#define EXT_CSD_PWR_CL_200_360 237 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ +#define EXT_CSD_BKOPS_STATUS 246 /* RO */ +#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ +#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ +#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ +#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ +#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */ +#define EXT_CSD_PRE_EOL_INFO 267 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */ +#define EXT_CSD_CMDQ_DEPTH 307 /* RO */ +#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */ +#define EXT_CSD_SUPPORTED_MODE 493 /* RO */ +#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ +#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ +#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ +#define EXT_CSD_MAX_PACKED_READS 501 /* RO */ +#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ +#define EXT_CSD_HPI_FEATURES 503 /* RO */ + +/* + * EXT_CSD field definitions + */ + +#define EXT_CSD_WR_REL_PARAM_EN (1<<2) + +#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40) +#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10) +#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04) +#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01) + +#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) +#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) +#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3) +#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4) + +#define EXT_CSD_PART_SETTING_COMPLETED (0x1) +#define EXT_CSD_PART_SUPPORT_PART_EN (0x1) + +#define EXT_CSD_CMD_SET_NORMAL (1<<0) +#define EXT_CSD_CMD_SET_SECURE (1<<1) +#define EXT_CSD_CMD_SET_CPSECURE (1<<2) + +#define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */ +#define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */ +#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \ + EXT_CSD_CARD_TYPE_HS_52) +#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */ + /* DDR mode @1.8V or 3V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */ + /* DDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ + | EXT_CSD_CARD_TYPE_DDR_1_2V) +#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */ +#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */ + /* SDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \ + EXT_CSD_CARD_TYPE_HS200_1_2V) +#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */ +#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */ +#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \ + EXT_CSD_CARD_TYPE_HS400_1_2V) +#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */ + +#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ +#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ +#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ +#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ +#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ +#define EXT_CSD_BUS_WIDTH_STROBE BIT(7) /* Enhanced strobe mode */ + +#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */ +#define EXT_CSD_TIMING_HS 1 /* High speed */ +#define EXT_CSD_TIMING_HS200 2 /* HS200 */ +#define EXT_CSD_TIMING_HS400 3 /* HS400 */ +#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */ + +#define EXT_CSD_SEC_ER_EN BIT(0) +#define EXT_CSD_SEC_BD_BLK_EN BIT(2) +#define EXT_CSD_SEC_GB_CL_EN BIT(4) +#define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */ + +#define EXT_CSD_RST_N_EN_MASK 0x3 +#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */ + +#define EXT_CSD_NO_POWER_NOTIFICATION 0 +#define EXT_CSD_POWER_ON 1 +#define EXT_CSD_POWER_OFF_SHORT 2 +#define EXT_CSD_POWER_OFF_LONG 3 + +#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */ +#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */ +#define EXT_CSD_PWR_CL_8BIT_SHIFT 4 +#define EXT_CSD_PWR_CL_4BIT_SHIFT 0 + +#define EXT_CSD_PACKED_EVENT_EN BIT(3) + +/* + * EXCEPTION_EVENT_STATUS field + */ +#define EXT_CSD_URGENT_BKOPS BIT(0) +#define EXT_CSD_DYNCAP_NEEDED BIT(1) +#define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2) +#define EXT_CSD_PACKED_FAILURE BIT(3) + +#define EXT_CSD_PACKED_GENERIC_ERROR BIT(0) +#define EXT_CSD_PACKED_INDEXED_ERROR BIT(1) + +/* + * BKOPS status level + */ +#define EXT_CSD_BKOPS_LEVEL_2 0x2 + +/* + * BKOPS modes + */ +#define EXT_CSD_MANUAL_BKOPS_MASK 0x01 +#define EXT_CSD_AUTO_BKOPS_MASK 0x02 + +/* + * Command Queue + */ +#define EXT_CSD_CMDQ_MODE_ENABLED BIT(0) +#define EXT_CSD_CMDQ_DEPTH_MASK GENMASK(4, 0) +#define EXT_CSD_CMDQ_SUPPORTED BIT(0) + +/* + * MMC_SWITCH access modes + */ +#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ +#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */ +#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ +#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ + +/* + * Erase/trim/discard + */ +#define MMC_ERASE_ARG 0x00000000 +#define MMC_SECURE_ERASE_ARG 0x80000000 +#define MMC_TRIM_ARG 0x00000001 +#define MMC_DISCARD_ARG 0x00000003 +#define MMC_SECURE_TRIM1_ARG 0x80000001 +#define MMC_SECURE_TRIM2_ARG 0x80008000 +#define MMC_SECURE_ARGS 0x80000000 +#define MMC_TRIM_ARGS 0x00008001 + +#endif /* LINUX_MMC_MMC_H */ diff --git a/fusee/fusee-secondary/src/sdmmc/sd.h b/fusee/fusee-secondary/src/sdmmc/sd.h new file mode 100644 index 000000000..e5707f55f --- /dev/null +++ b/fusee/fusee-secondary/src/sdmmc/sd.h @@ -0,0 +1,153 @@ +/* + * include/linux/mmc/sd.h + * + * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#ifndef LINUX_MMC_SD_H +#define LINUX_MMC_SD_H + +/* SD commands type argument response */ +/* class 0 */ +/* This is basically the same command as for MMC with some quirks. */ +#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ +#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ +#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ + +/* class 10 */ +#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ + +/* class 5 */ +#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ +#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ + +/* Application commands */ +#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ +#define SD_APP_SD_STATUS 13 /* adtc R1 */ +#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ +#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ +#define SD_APP_SET_CLR_CARD_DETECT 42 /* ac [0] set cd R1 */ +#define SD_APP_SEND_SCR 51 /* adtc R1 */ + +/* OCR bit definitions */ +#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ +#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ +#define SD_OCR_XPC (1 << 28) /* SDXC power control */ +#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ +#define SD_OCR_VDD_LOW (1 << 7) /* SD: Reserved for Low Voltage Range */ +#define SD_OCR_VDD_20_21 (1 << 8) +#define SD_OCR_VDD_21_22 (1 << 9) +#define SD_OCR_VDD_22_23 (1 << 10) +#define SD_OCR_VDD_23_24 (1 << 11) +#define SD_OCR_VDD_24_25 (1 << 12) +#define SD_OCR_VDD_25_26 (1 << 13) +#define SD_OCR_VDD_26_27 (1 << 14) +#define SD_OCR_VDD_27_28 (1 << 15) +#define SD_OCR_VDD_28_29 (1 << 16) +#define SD_OCR_VDD_29_30 (1 << 17) +#define SD_OCR_VDD_30_31 (1 << 18) +#define SD_OCR_VDD_31_32 (1 << 19) +#define SD_OCR_VDD_32_33 (1 << 20) +#define SD_OCR_VDD_33_34 (1 << 21) +#define SD_OCR_VDD_34_35 (1 << 22) +#define SD_OCR_VDD_35_36 (1 << 23) + +/* + * SD_SWITCH argument format: + * + * [31] Check (0) or switch (1) + * [30:24] Reserved (0) + * [23:20] Function group 6 + * [19:16] Function group 5 + * [15:12] Function group 4 + * [11:8] Function group 3 + * [7:4] Function group 2 + * [3:0] Function group 1 + */ + +/* + * SD_SEND_IF_COND argument format: + * + * [31:12] Reserved (0) + * [11:8] Host Voltage Supply Flags + * [7:0] Check Pattern (0xAA) + */ + +/* + * SCR field definitions + */ + +#define SD_SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ +#define SD_SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ +#define SD_SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ +#define SD_SCR_BUS_WIDTH_1 1 +#define SD_SCR_BUS_WIDTH_4 4 +#define SD_SCR_CMD20_SUPPORT 1 +#define SD_SCR_CMD23_SUPPORT 2 + +/* + * SD bus widths + */ +#define SD_BUS_WIDTH_1 0 +#define SD_BUS_WIDTH_4 2 + +/* + * SD bus speed modes + */ +#define UHS_SDR12_BUS_SPEED 0 +#define HIGH_SPEED_BUS_SPEED 1 +#define UHS_SDR25_BUS_SPEED 1 +#define UHS_SDR50_BUS_SPEED 2 +#define UHS_SDR104_BUS_SPEED 3 +#define UHS_DDR50_BUS_SPEED 4 +#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED) +#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED) +#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED) +#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED) +#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED) +#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED) + +/* + * SD bus driver types + */ +#define SD_DRIVER_TYPE_B 0x01 +#define SD_DRIVER_TYPE_A 0x02 +#define SD_DRIVER_TYPE_C 0x04 +#define SD_DRIVER_TYPE_D 0x08 + +/* + * SD bus current limits + */ +#define SD_SET_CURRENT_LIMIT_200 0 +#define SD_SET_CURRENT_LIMIT_400 1 +#define SD_SET_CURRENT_LIMIT_600 2 +#define SD_SET_CURRENT_LIMIT_800 3 +#define SD_SET_CURRENT_NO_CHANGE (-1) +#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200) +#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400) +#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600) +#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) + +/* + * SD_SWITCH mode + */ +#define SD_SWITCH_CHECK 0 +#define SD_SWITCH_SET 1 + +/* + * SD_SWITCH function groups + */ +#define SD_SWITCH_GRP_ACCESS 0 + +/* + * SD_SWITCH access modes + */ +#define SD_SWITCH_ACCESS_DEF 0 +#define SD_SWITCH_ACCESS_HS 1 + +#endif /* LINUX_MMC_SD_H */ diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc.c b/fusee/fusee-secondary/src/sdmmc/sdmmc.c new file mode 100644 index 000000000..24e5f84b2 --- /dev/null +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc.c @@ -0,0 +1,1528 @@ +#include +#include +#include +#include +#include + +#include "sdmmc.h" +#include "mmc.h" +#include "sd.h" +#include "../timers.h" +#include "../lib/driver_utils.h" + +#define UNSTUFF_BITS(resp,start,size) \ +({ \ + const int __size = size; \ + const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1; \ + const int __off = 3 - ((start) / 32); \ + const int __shft = (start) & 31; \ + uint32_t __res; \ + \ + __res = resp[__off] >> __shft; \ + if (__size + __shft > 32) \ + __res |= resp[__off-1] << ((32 - __shft) % 32); \ + __res & __mask; \ +}) + +static const unsigned int tran_exp[] = { + 10000, 100000, 1000000, 10000000, + 0, 0, 0, 0 +}; + +static const unsigned char tran_mant[] = { + 0, 10, 12, 13, 15, 20, 25, 30, + 35, 40, 45, 50, 55, 60, 70, 80, +}; + +static const unsigned int taac_exp[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, +}; + +static const unsigned int taac_mant[] = { + 0, 10, 12, 13, 15, 20, 25, 30, + 35, 40, 45, 50, 55, 60, 70, 80, +}; + +/* + Common SDMMC device functions. +*/ + +static bool is_sdmmc_device_r1_error(uint32_t status) +{ + return (status & (R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR + | R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION + | R1_LOCK_UNLOCK_FAILED | R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND + | R1_CARD_ECC_FAILED | R1_CC_ERROR | R1_ERROR | R1_CID_CSD_OVERWRITE + | R1_WP_ERASE_SKIP | R1_ERASE_RESET | R1_SWITCH_ERROR)); +} + +static int sdmmc_device_send_r1_cmd(sdmmc_device_t *device, uint32_t opcode, uint32_t arg, bool is_busy, uint32_t resp_mask, uint32_t resp_state) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = opcode; + cmd.arg = arg; + cmd.flags = (is_busy ? SDMMC_RSP_R1B : SDMMC_RSP_R1); + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Mask the response, if necessary. */ + if (resp_mask) + resp &= ~(resp_mask); + + /* We got an error state. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + + /* We need to check for the desired state. */ + if (resp_state != 0xFFFFFFFF) + { + /* We didn't get the expected state. */ + if (R1_CURRENT_STATE(resp) != resp_state) + return 0; + } + + return 1; +} + +static int sdmmc_device_go_idle(sdmmc_device_t *device) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = MMC_GO_IDLE_STATE; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_NONE; + + return sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0); +} + +static int sdmmc_device_send_cid(sdmmc_device_t *device, uint32_t *cid) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = MMC_ALL_SEND_CID; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R2; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + /* Try to load back the response. */ + return sdmmc_load_response(device->sdmmc, SDMMC_RSP_R2, cid); +} + +static int sdmmc_device_send_csd(sdmmc_device_t *device, uint32_t *csd) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = MMC_SEND_CSD; + cmd.arg = (device->rca << 16); + cmd.flags = SDMMC_RSP_R2; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + /* Try to load back the response. */ + return sdmmc_load_response(device->sdmmc, SDMMC_RSP_R2, csd); +} + +static int sdmmc_device_select_card(sdmmc_device_t *device) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SELECT_CARD, (device->rca << 16), true, 0, 0xFFFFFFFF); +} + +static int sdmmc_device_set_blocklen(sdmmc_device_t *device, uint32_t blocklen) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SET_BLOCKLEN, blocklen, false, 0, R1_STATE_TRAN); +} + +static int sdmmc_device_send_status(sdmmc_device_t *device) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SEND_STATUS, (device->rca << 16), false, 0, R1_STATE_TRAN); +} + +static int sdmmc_device_rw(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data, bool is_read) +{ + uint8_t *buf = (uint8_t *)data; + + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + while (num_sectors) + { + uint32_t num_blocks_out = 0; + uint32_t num_retries = 10; + + for (; num_retries > 0; num_retries--) + { + cmd.opcode = is_read ? MMC_READ_MULTIPLE_BLOCK : MMC_WRITE_MULTIPLE_BLOCK; + cmd.arg = sector; + cmd.flags = SDMMC_RSP_R1; + + req.data = buf; + req.blksz = 512; + req.num_blocks = num_sectors; + req.is_read = is_read; + req.is_multi_block = true; + req.is_auto_cmd12 = true; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, &req, &num_blocks_out)) + { + /* Abort the transmission. */ + sdmmc_abort(device->sdmmc, MMC_STOP_TRANSMISSION); + + /* Peek the SD card's status. */ + sdmmc_device_send_status(device); + + /* Wait for a while. */ + mdelay(100); + } + else + break; + } + + /* Failed to read/write on all attempts. */ + if (!num_retries) + return 0; + + /* Advance to next sector. */ + sector += num_blocks_out; + num_sectors -= num_blocks_out; + buf += (512 * num_blocks_out); + } + + return 1; +} + +int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data) +{ + return sdmmc_device_rw(device, sector, num_sectors, data, true); +} + +int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data) +{ + return sdmmc_device_rw(device, sector, num_sectors, data, false); +} + +int sdmmc_device_finish(sdmmc_device_t *device) +{ + /* Place the device in idle state. */ + if (!sdmmc_device_go_idle(device)) + return 0; + + /* Terminate the device. */ + sdmmc_finish(device->sdmmc); + return 1; +} + +/* + SD device functions. +*/ + +static void sdmmc_sd_decode_cid(sdmmc_device_t *device, uint32_t *cid) +{ + device->cid.manfid = UNSTUFF_BITS(cid, 120, 8); + device->cid.oemid = UNSTUFF_BITS(cid, 104, 16); + device->cid.prod_name[0] = UNSTUFF_BITS(cid, 96, 8); + device->cid.prod_name[1] = UNSTUFF_BITS(cid, 88, 8); + device->cid.prod_name[2] = UNSTUFF_BITS(cid, 80, 8); + device->cid.prod_name[3] = UNSTUFF_BITS(cid, 72, 8); + device->cid.prod_name[4] = UNSTUFF_BITS(cid, 64, 8); + device->cid.hwrev = UNSTUFF_BITS(cid, 60, 4); + device->cid.fwrev = UNSTUFF_BITS(cid, 56, 4); + device->cid.serial = UNSTUFF_BITS(cid, 24, 32); + device->cid.year = UNSTUFF_BITS(cid, 12, 8) + 2000; /* SD cards year offset */ + device->cid.month = UNSTUFF_BITS(cid, 8, 4); +} + +static int sdmmc_sd_decode_csd(sdmmc_device_t *device, uint32_t *csd) +{ + unsigned int e, m; + device->csd.structure = UNSTUFF_BITS(csd, 126, 2); + + switch (device->csd.structure) { + case 0: + m = UNSTUFF_BITS(csd, 115, 4); + e = UNSTUFF_BITS(csd, 112, 3); + device->csd.taac_ns = (taac_exp[e] * taac_mant[m] + 9) / 10; + device->csd.taac_clks = UNSTUFF_BITS(csd, 104, 8) * 100; + + m = UNSTUFF_BITS(csd, 99, 4); + e = UNSTUFF_BITS(csd, 96, 3); + device->csd.max_dtr = tran_exp[e] * tran_mant[m]; + device->csd.cmdclass = UNSTUFF_BITS(csd, 84, 12); + + e = UNSTUFF_BITS(csd, 47, 3); + m = UNSTUFF_BITS(csd, 62, 12); + device->csd.capacity = ((1 + m) << (e + 2)); + + device->csd.read_blkbits = UNSTUFF_BITS(csd, 80, 4); + device->csd.read_partial = UNSTUFF_BITS(csd, 79, 1); + device->csd.write_misalign = UNSTUFF_BITS(csd, 78, 1); + device->csd.read_misalign = UNSTUFF_BITS(csd, 77, 1); + device->csd.dsr_imp = UNSTUFF_BITS(csd, 76, 1); + device->csd.r2w_factor = UNSTUFF_BITS(csd, 26, 3); + device->csd.write_blkbits = UNSTUFF_BITS(csd, 22, 4); + device->csd.write_partial = UNSTUFF_BITS(csd, 21, 1); + + if (UNSTUFF_BITS(csd, 46, 1)) { + device->csd.erase_size = 1; + } else if (device->csd.write_blkbits >= 9) { + device->csd.erase_size = UNSTUFF_BITS(csd, 39, 7) + 1; + device->csd.erase_size <<= (device->csd.write_blkbits - 9); + } + break; + case 1: + device->csd.taac_ns = 0; /* Unused */ + device->csd.taac_clks = 0; /* Unused */ + + m = UNSTUFF_BITS(csd, 99, 4); + e = UNSTUFF_BITS(csd, 96, 3); + device->csd.max_dtr = tran_exp[e] * tran_mant[m]; + device->csd.cmdclass = UNSTUFF_BITS(csd, 84, 12); + device->csd.c_size = UNSTUFF_BITS(csd, 48, 22); + + m = UNSTUFF_BITS(csd, 48, 22); + device->csd.capacity = ((1 + m) << 10); + + device->csd.read_blkbits = 9; + device->csd.read_partial = 0; + device->csd.write_misalign = 0; + device->csd.read_misalign = 0; + device->csd.r2w_factor = 4; /* Unused */ + device->csd.write_blkbits = 9; + device->csd.write_partial = 0; + device->csd.erase_size = 1; + break; + default: + return 0; + } + + return 1; +} + +static int sdmmc_sd_decode_scr(sdmmc_device_t *device, uint8_t *scr) +{ + uint8_t tmp[8]; + uint32_t resp[4]; + + /* This must be swapped. */ + for (int i = 0; i < 8; i += 4) + { + tmp[i + 3] = scr[i]; + tmp[i + 2] = scr[i + 1]; + tmp[i + 1] = scr[i + 2]; + tmp[i] = scr[i + 3]; + } + + resp[3] = *(uint32_t *)&tmp[4]; + resp[2] = *(uint32_t *)&tmp[0]; + + device->scr.sda_vsn = UNSTUFF_BITS(resp, 56, 4); + device->scr.bus_widths = UNSTUFF_BITS(resp, 48, 4); + + /* Check if Physical Layer Spec v3.0 is supported. */ + if (device->scr.sda_vsn == SD_SCR_SPEC_VER_2) + device->scr.sda_spec3 = UNSTUFF_BITS(resp, 47, 1); + + if (device->scr.sda_spec3) + device->scr.cmds = UNSTUFF_BITS(resp, 32, 2); + + /* Unknown SCR structure version. */ + if (UNSTUFF_BITS(resp, 60, 4)) + return 0; + else + return 1; +} + +static void sdmmc_sd_decode_ssr(sdmmc_device_t *device, uint8_t *ssr) +{ + uint8_t tmp[64]; + uint32_t resp1[4]; + uint32_t resp2[4]; + + /* This must be swapped. */ + for (int i = 0; i < 64; i += 4) + { + tmp[i + 3] = ssr[i]; + tmp[i + 2] = ssr[i + 1]; + tmp[i + 1] = ssr[i + 2]; + tmp[i] = ssr[i + 3]; + } + + resp1[3] = *(uint32_t *)&tmp[12]; + resp1[2] = *(uint32_t *)&tmp[8]; + resp1[1] = *(uint32_t *)&tmp[4]; + resp1[0] = *(uint32_t *)&tmp[0]; + resp2[3] = *(uint32_t *)&tmp[28]; + resp2[2] = *(uint32_t *)&tmp[24]; + resp2[1] = *(uint32_t *)&tmp[20]; + resp2[0] = *(uint32_t *)&tmp[16]; + + device->ssr.dat_bus_width = ((UNSTUFF_BITS(resp1, 126, 2) & SD_BUS_WIDTH_4) ? 4 : 1); + device->ssr.speed_class = UNSTUFF_BITS(resp1, 56, 8); + + if (device->ssr.speed_class < 4) + device->ssr.speed_class <<= 1; + else if (device->ssr.speed_class == 4) + device->ssr.speed_class = 10; + + device->ssr.uhs_speed_grade = UNSTUFF_BITS(resp1, 12, 4); + device->ssr.video_speed_class = UNSTUFF_BITS(resp1, 0, 8); + device->ssr.app_perf_class = UNSTUFF_BITS(resp2, 80, 4); +} + +static int sdmmc_sd_send_app_cmd(sdmmc_device_t *device, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t resp_mask, uint32_t resp_state) +{ + /* Try to send the APP command. */ + if (!sdmmc_device_send_r1_cmd(device, MMC_APP_CMD, (device->rca << 16), false, resp_mask, resp_state)) + return 0; + + /* Send the actual command. */ + if (!sdmmc_send_cmd(device->sdmmc, cmd, req, 0)) + return 0; + + return 1; +} + +static int sdmmc_sd_send_if_cond(sdmmc_device_t *device, bool *is_sd_ver2) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = SD_SEND_IF_COND; + /* We set the bit if the host supports voltages between 2.7 and 3.6 V */ + cmd.arg = 0x1AA; + cmd.flags = SDMMC_RSP_R7; + + /* Command failed, this means SD Card is not version 2. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + { + *is_sd_ver2 = false; + return 1; + } + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R7, &resp)) + return 0; + + /* Check if we got a valid response. */ + if ((resp & 0xFF) == 0xAA) + { + *is_sd_ver2 = true; + return 1; + } + + return 0; +} + +static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool is_uhs_en) +{ + sdmmc_command_t cmd = {}; + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + while (!is_timeout) + { + /* Set this since most cards do not answer if some reserved bits in the OCR are set. */ + uint32_t arg = SD_OCR_VDD_32_33; + + /* Request support for SDXC power control and SDHC block mode cards. */ + if (is_sd_ver2) + { + arg |= SD_OCR_XPC; + arg |= SD_OCR_CCS; + } + + /* Request support 1.8V switching. */ + if (is_uhs_en) + arg |= SD_OCR_S18R; + + cmd.opcode = SD_APP_OP_COND; + cmd.arg = arg; + cmd.flags = SDMMC_RSP_R3; + + /* Try to send the command. */ + if (!sdmmc_sd_send_app_cmd(device, &cmd, 0, is_sd_ver2 ? 0 : 0x400000, 0xFFFFFFFF)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R3, &resp)) + return 0; + + /* Card Power up bit is set. */ + if (resp & MMC_CARD_BUSY) + { + /* We have a SDHC block mode card. */ + if (resp & SD_OCR_CCS) + device->is_block_sdhc = true; + + /* We asked for low voltage support and the card accepted. */ + if (is_uhs_en && (resp & SD_ROCR_S18A)) + { + /* Voltage switching is only valid for SDMMC1. */ + if (device->sdmmc->controller == SDMMC_1) + { + /* Failed to issue voltage switching command. */ + if (!sdmmc_device_send_r1_cmd(device, SD_SWITCH_VOLTAGE, 0, false, 0, R1_STATE_READY)) + return 0; + + /* Delay a bit before asking for the voltage switch. */ + udelay(1000); + + /* Tell the driver to switch the voltage. */ + if (!sdmmc_switch_voltage(device->sdmmc)) + return 0; + + /* We are now running at 1.8V. */ + device->is_180v = true; + } + } + + return 1; + } + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + + /* Delay for a minimum of 10 milliseconds. */ + mdelay(10); + } + + return 0; +} + +static int sdmmc_sd_send_relative_addr(sdmmc_device_t *device) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = SD_SEND_RELATIVE_ADDR; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R6; + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + while (!is_timeout) + { + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R6, &resp)) + return 0; + + /* Save the RCA. */ + if (resp >> 16) + { + device->rca = (resp >> 16); + return 1; + } + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + + /* Delay for an appropriate period. */ + udelay(1000); + } + + return 0; +} + +static int sdmmc_sd_send_scr(sdmmc_device_t *device, uint8_t *scr) +{ + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + cmd.opcode = SD_APP_SEND_SCR; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1; + + req.data = scr; + req.blksz = 8; + req.num_blocks = 1; + req.is_read = true; + req.is_multi_block = false; + req.is_auto_cmd12 = false; + + /* Try to send the APP command. */ + if (!sdmmc_sd_send_app_cmd(device, &cmd, &req, 0, R1_STATE_TRAN)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Evaluate the response. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + else + return 1; +} + +static int sdmmc_sd_set_clr_card_detect(sdmmc_device_t *device) +{ + /* Try to send the APP command. */ + if (!sdmmc_device_send_r1_cmd(device, MMC_APP_CMD, (device->rca << 16), false, 0, R1_STATE_TRAN)) + return 0; + + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, SD_APP_SET_CLR_CARD_DETECT, 0, false, 0, R1_STATE_TRAN); +} + +static int sdmmc_sd_set_bus_width(sdmmc_device_t *device) +{ + /* Try to send the APP command. */ + if (!sdmmc_device_send_r1_cmd(device, MMC_APP_CMD, (device->rca << 16), false, 0, R1_STATE_TRAN)) + return 0; + + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, false, 0, R1_STATE_TRAN); +} + +static int sdmmc_sd_switch(sdmmc_device_t *device, uint32_t mode, uint32_t group, uint8_t value, uint8_t *data) +{ + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + cmd.opcode = SD_SWITCH; + cmd.arg = ((mode << 31) | 0x00FFFFFF); + cmd.arg &= ~(0xF << (group * 4)); + cmd.arg |= (value << (group * 4)); + cmd.flags = SDMMC_RSP_R1; + + req.data = data; + req.blksz = 64; + req.num_blocks = 1; + req.is_read = true; + req.is_multi_block = false; + req.is_auto_cmd12 = false; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, &req, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Evaluate the response. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + else + return 1; +} + +static int sdmmc_sd_set_current_limit(sdmmc_device_t *device, uint8_t *status) +{ + /* Start with the highest possible limit. */ + uint32_t current_limit = SD_SET_CURRENT_LIMIT_800; + + /* Try each limit. */ + while (current_limit > SD_SET_CURRENT_NO_CHANGE) + { + /* Switch the current limit. */ + if (!sdmmc_sd_switch(device, SD_SWITCH_SET, 3, current_limit, status)) + return 0; + + /* Current limit was set successfully. */ + if (((status[15] >> 4) & 0x0F) == current_limit) + break; + + current_limit--; + } + + return 1; +} + +static int sdmmc_sd_switch_hs(sdmmc_device_t *device, uint32_t type, uint8_t *status) +{ + /* Test if the card supports high-speed mode. */ + if (!sdmmc_sd_switch(device, 0, 0, type, status)) + return 0; + + uint32_t res_type = (status[16] & 0xF); + + /* This high-speed mode type is not supported. */ + if (res_type != type) + return 0; + + if ((((uint16_t)status[0] << 8) | status[1]) < 0x320) + { + /* Try to switch to high-speed mode. */ + if (!sdmmc_sd_switch(device, 1, 0, type, status)) + return 0; + + /* Something failed when switching to high-speed mode. */ + if ((status[16] & 0xF) != res_type) + return 0; + } + + return 1; +} + +static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status) +{ + /* Adjust the current limit. */ + if (!sdmmc_sd_set_current_limit(device, status)) + return 0; + + /* Invalid bus width. */ + if (device->sdmmc->bus_width != SDMMC_BUS_WIDTH_4BIT) + return 0; + + /* Get the supported high-speed type. */ + if (!sdmmc_sd_switch(device, 0, 0, 0xF, status)) + return 0; + + /* High-speed SDR104 is supported. */ + if (status[13] & SD_MODE_UHS_SDR104) + { + /* Switch to high-speed. */ + if (!sdmmc_sd_switch_hs(device, UHS_SDR104_BUS_SPEED, status)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR104)) + return 0; + + /* Run tuning. */ + if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR104, MMC_SEND_TUNING_BLOCK)) + return 0; + } + else if (status[13] & SD_MODE_UHS_SDR50) /* High-speed SDR50 is supported. */ + { + /* Switch to high-speed. */ + if (!sdmmc_sd_switch_hs(device, UHS_SDR50_BUS_SPEED, status)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR50)) + return 0; + + /* Run tuning. */ + if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR50, MMC_SEND_TUNING_BLOCK)) + return 0; + } + else if (status[13] & SD_MODE_UHS_SDR12) /* High-speed SDR12 is supported. */ + { + /* Switch to high-speed. */ + if (!sdmmc_sd_switch_hs(device, UHS_SDR12_BUS_SPEED, status)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR12)) + return 0; + + /* Run tuning. */ + if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR12, MMC_SEND_TUNING_BLOCK)) + return 0; + } + else + return 0; + + /* Peek the SD card's status. */ + return sdmmc_device_send_status(device); +} + +static int sdmmc_sd_switch_hs_high(sdmmc_device_t *device, uint8_t *status) +{ + /* Get the supported high-speed type. */ + if (!sdmmc_sd_switch(device, 0, 0, 0xF, status)) + return 0; + + /* High-speed is supported. */ + if (status[13] & 2) + { + /* Switch to high-speed. */ + if (!sdmmc_sd_switch_hs(device, SDHCI_CTRL_UHS_SDR25, status)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR25)) + return 0; + + /* Peek the SD card's status. */ + return sdmmc_device_send_status(device); + } + + /* Nothing to do. */ + return 1; +} + +static int sdmmc_sd_status(sdmmc_device_t *device, uint8_t *ssr) +{ + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + cmd.opcode = SD_APP_SD_STATUS; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1; + + req.data = ssr; + req.blksz = 64; + req.num_blocks = 1; + req.is_read = true; + req.is_multi_block = false; + req.is_auto_cmd12 = false; + + /* Try to send the APP command. */ + if (!sdmmc_sd_send_app_cmd(device, &cmd, &req, 0, R1_STATE_TRAN)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Evaluate the response. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + else + return 1; +} + +int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed) +{ + bool is_sd_ver2 = false; + uint32_t cid[4] = {0}; + uint32_t csd[4] = {0}; + uint8_t scr[8] = {0}; + uint8_t ssr[64] = {0}; + uint8_t switch_status[512] = {0}; + + /* Initialize our device's struct. */ + memset(device, 0, sizeof(sdmmc_device_t)); + + /* Try to initialize the driver. */ + if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_VOLTAGE_3V3, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_SDR)) + { + sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!"); + return 0; + } + + /* Bind the underlying driver. */ + device->sdmmc = sdmmc; + + sdmmc_info(sdmmc, "SDMMC driver was successfully initialized for SD!"); + + /* Apply at least 74 clock cycles. The card should be ready afterwards. */ + udelay((74000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + /* Instruct the SD card to go idle. */ + if (!sdmmc_device_go_idle(device)) + { + sdmmc_error(sdmmc, "Failed to go idle!"); + return 0; + } + + sdmmc_info(sdmmc, "SD card went idle!"); + + /* Get the SD card's interface operating condition. */ + if (!sdmmc_sd_send_if_cond(device, &is_sd_ver2)) + { + sdmmc_error(sdmmc, "Failed to send if cond!"); + return 0; + } + + sdmmc_info(sdmmc, "Sent if cond to SD card!"); + + /* Get the SD card's operating conditions. */ + if (!sdmmc_sd_send_op_cond(device, is_sd_ver2, (bus_width == SDMMC_BUS_WIDTH_4BIT) && (bus_speed == SDMMC_SPEED_SDR104))) + { + sdmmc_error(sdmmc, "Failed to send op cond!"); + return 0; + } + + sdmmc_info(sdmmc, "Sent op cond to SD card!"); + + /* Get the SD card's CID. */ + if (!sdmmc_device_send_cid(device, cid)) + { + sdmmc_error(sdmmc, "Failed to get CID!"); + return 0; + } + + sdmmc_info(sdmmc, "Got CID from SD card!"); + + /* Decode and save the CID. */ + sdmmc_sd_decode_cid(device, cid); + + /* Get the SD card's RCA. */ + if (!sdmmc_sd_send_relative_addr(device)) + { + sdmmc_error(sdmmc, "Failed to get RCA!"); + return 0; + } + + sdmmc_info(sdmmc, "Got RCA (0x%08x) from SD card!", device->rca); + + /* Get the SD card's CSD. */ + if (!sdmmc_device_send_csd(device, csd)) + { + sdmmc_error(sdmmc, "Failed to get CSD!"); + return 0; + } + + sdmmc_info(sdmmc, "Got CSD from SD card!"); + + /* Decode and save the CSD. */ + if (!sdmmc_sd_decode_csd(device, csd)) + sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure); + + /* If we never switched to 1.8V, change the bus speed mode. */ + if (!device->is_180v) + { + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UNK6)) + { + sdmmc_error(sdmmc, "Failed to apply the correct bus speed!"); + return 0; + } + + sdmmc_info(sdmmc, "Speed mode has been adjusted!"); + } + + /* Select the SD card. */ + if (!sdmmc_device_select_card(device)) + { + sdmmc_error(sdmmc, "Failed to select SD card!"); + return 0; + } + + sdmmc_info(sdmmc, "SD card is now selected!"); + + /* Change the SD card's block length. */ + if (!sdmmc_device_set_blocklen(device, 512)) + { + sdmmc_error(sdmmc, "Failed to set SD card's block length!"); + return 0; + } + + sdmmc_info(sdmmc, "SD card's block length is now 512!"); + + /* It's a good practice to disconnect the pull-up resistor with ACMD42. */ + if (!sdmmc_sd_set_clr_card_detect(device)) + { + sdmmc_error(sdmmc, "Failed to disconnect the pull-up resistor!"); + return 0; + } + + sdmmc_info(sdmmc, "Pull-up resistor is now disconnected!"); + + /* Get the SD card's SCR. */ + if (!sdmmc_sd_send_scr(device, scr)) + { + sdmmc_error(sdmmc, "Failed to get SCR!"); + return 0; + } + + sdmmc_info(sdmmc, "Got SCR from SD card!"); + + /* Decode and save the SCR. */ + if (!sdmmc_sd_decode_scr(device, scr)) + { + sdmmc_error(sdmmc, "Got unknown SCR structure!"); + return 0; + } + + /* Switch to wider bus (if supported). */ + if ((bus_width == SDMMC_BUS_WIDTH_4BIT) + && (device->scr.bus_widths & SD_SCR_BUS_WIDTH_4) + && (device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2))) + { + if (!sdmmc_sd_set_bus_width(device)) + { + sdmmc_error(sdmmc, "Failed to switch to wider bus!"); + return 0; + } + + sdmmc_select_bus_width(device->sdmmc, SDMMC_BUS_WIDTH_4BIT); + sdmmc_info(sdmmc, "Switched to wider bus!"); + } + + if (device->is_180v) + { + /* Switch to high-speed from low voltage (if possible). */ + if (!sdmmc_sd_switch_hs_low(device, switch_status)) + { + sdmmc_error(sdmmc, "Failed to switch to high-speed!"); + return 0; + } + + sdmmc_info(sdmmc, "Switched to high-speed!"); + } + else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_UNK6))) + { + /* Switch to high-speed from high voltage (if possible). */ + if (!sdmmc_sd_switch_hs_high(device, switch_status)) + { + sdmmc_error(sdmmc, "Failed to switch to high-speed!"); + return 0; + } + + sdmmc_info(sdmmc, "Switched to high-speed!"); + } + + /* Correct any inconsistent states. */ + sdmmc_adjust_sd_clock(sdmmc); + + /* Get the SD card's SSR. */ + if (!sdmmc_sd_status(device, ssr)) + { + sdmmc_error(sdmmc, "Failed to get SSR!"); + return 0; + } + + sdmmc_info(sdmmc, "Got SSR from SD card!"); + + /* Decode and save the SSR. */ + sdmmc_sd_decode_ssr(device, scr); + + return 1; +} + +/* + MMC device functions. +*/ + +static void sdmmc_mmc_decode_cid(sdmmc_device_t *device, uint32_t *cid) +{ + switch (device->csd.mmca_vsn) + { + case 0: /* MMC v1.0 - v1.2 */ + case 1: /* MMC v1.4 */ + device->cid.prod_name[6] = UNSTUFF_BITS(cid, 48, 8); + device->cid.manfid = UNSTUFF_BITS(cid, 104, 24); + device->cid.hwrev = UNSTUFF_BITS(cid, 44, 4); + device->cid.fwrev = UNSTUFF_BITS(cid, 40, 4); + device->cid.serial = UNSTUFF_BITS(cid, 16, 24); + break; + case 2: /* MMC v2.0 - v2.2 */ + case 3: /* MMC v3.1 - v3.3 */ + case 4: /* MMC v4 */ + device->cid.manfid = UNSTUFF_BITS(cid, 120, 8); + device->cid.oemid = UNSTUFF_BITS(cid, 104, 8); + device->cid.prv = UNSTUFF_BITS(cid, 48, 8); + device->cid.serial = UNSTUFF_BITS(cid, 16, 32); + break; + default: + break; + } + + device->cid.prod_name[0] = UNSTUFF_BITS(cid, 96, 8); + device->cid.prod_name[1] = UNSTUFF_BITS(cid, 88, 8); + device->cid.prod_name[2] = UNSTUFF_BITS(cid, 80, 8); + device->cid.prod_name[3] = UNSTUFF_BITS(cid, 72, 8); + device->cid.prod_name[4] = UNSTUFF_BITS(cid, 64, 8); + device->cid.prod_name[5] = UNSTUFF_BITS(cid, 56, 8); + + device->cid.month = UNSTUFF_BITS(cid, 12, 4); + device->cid.year = (UNSTUFF_BITS(cid, 8, 4) + 1997); + + if ((device->ext_csd.rev >= 5) && (device->cid.year < 2010)) + device->cid.year += 16; +} + +static int sdmmc_mmc_decode_csd(sdmmc_device_t *device, uint32_t *csd) +{ + unsigned int e, m, a, b; + + device->csd.structure = UNSTUFF_BITS(csd, 126, 2); + + if (!device->csd.structure) { + return 0; + } + + device->csd.mmca_vsn = UNSTUFF_BITS(csd, 122, 4); + + m = UNSTUFF_BITS(csd, 115, 4); + e = UNSTUFF_BITS(csd, 112, 3); + device->csd.taac_ns = ((taac_exp[e] * taac_mant[m] + 9) / 10); + device->csd.taac_clks = (UNSTUFF_BITS(csd, 104, 8) * 100); + + m = UNSTUFF_BITS(csd, 99, 4); + e = UNSTUFF_BITS(csd, 96, 3); + device->csd.max_dtr = (tran_exp[e] * tran_mant[m]); + device->csd.cmdclass = UNSTUFF_BITS(csd, 84, 12); + + e = UNSTUFF_BITS(csd, 47, 3); + m = UNSTUFF_BITS(csd, 62, 12); + device->csd.capacity = ((1 + m) << (e + 2)); + + device->csd.read_blkbits = UNSTUFF_BITS(csd, 80, 4); + device->csd.read_partial = UNSTUFF_BITS(csd, 79, 1); + device->csd.write_misalign = UNSTUFF_BITS(csd, 78, 1); + device->csd.read_misalign = UNSTUFF_BITS(csd, 77, 1); + device->csd.dsr_imp = UNSTUFF_BITS(csd, 76, 1); + device->csd.r2w_factor = UNSTUFF_BITS(csd, 26, 3); + device->csd.write_blkbits = UNSTUFF_BITS(csd, 22, 4); + device->csd.write_partial = UNSTUFF_BITS(csd, 21, 1); + + if (device->csd.write_blkbits >= 9) + { + a = UNSTUFF_BITS(csd, 42, 5); + b = UNSTUFF_BITS(csd, 37, 5); + device->csd.erase_size = ((a + 1) * (b + 1)); + device->csd.erase_size <<= (device->csd.write_blkbits - 9); + } + + return 1; +} + +static void sdmmc_mmc_decode_ext_csd(sdmmc_device_t *device, uint8_t *ext_csd) +{ + device->ext_csd.rev = ext_csd[EXT_CSD_REV]; + device->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; + device->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; + device->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT]; + device->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; + device->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; + device->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; + device->ext_csd.raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3]; + device->ext_csd.bkops = ext_csd[EXT_CSD_BKOPS_SUPPORT]; + device->ext_csd.man_bkops_en = ext_csd[EXT_CSD_BKOPS_EN]; + device->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; +} + +static int sdmmc_mmc_send_op_cond(sdmmc_device_t *device, SdmmcBusVoltage bus_voltage) +{ + sdmmc_command_t cmd = {}; + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + while (!is_timeout) + { + /* Set high capacity bit. */ + uint32_t arg = SD_OCR_CCS; + + /* Set voltage bits. */ + if (bus_voltage == SDMMC_VOLTAGE_1V8) + arg |= MMC_VDD_165_195; + else if (bus_voltage == SDMMC_VOLTAGE_3V3) + arg |= (MMC_VDD_33_34 | MMC_VDD_32_33 | MMC_VDD_31_32 | MMC_VDD_30_31 | MMC_VDD_29_30 | MMC_VDD_28_29 | MMC_VDD_27_28); + else + return 0; + + cmd.opcode = MMC_SEND_OP_COND; + cmd.arg = arg; + cmd.flags = SDMMC_RSP_R3; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R3, &resp)) + return 0; + + /* Card Power up bit is set. */ + if (resp & MMC_CARD_BUSY) + { + /* We have a SDHC block mode card. */ + if (resp & SD_OCR_CCS) + device->is_block_sdhc = true; + + return 1; + } + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + + /* Delay for a minimum of 10 milliseconds. */ + mdelay(10); + } + + return 0; +} + +static int sdmmc_mmc_send_ext_csd(sdmmc_device_t *device, uint8_t *ext_csd) +{ + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + cmd.opcode = MMC_SEND_EXT_CSD; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1; + + req.data = ext_csd; + req.blksz = 512; + req.num_blocks = 1; + req.is_read = true; + req.is_multi_block = false; + req.is_auto_cmd12 = false; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, &req, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Evaluate the response. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + else + return 1; +} + +static int sdmmc_mmc_set_relative_addr(sdmmc_device_t *device) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SET_RELATIVE_ADDR, (device->rca << 16), false, 0, 0xFFFFFFFF); +} + +static int sdmmc_mmc_switch(sdmmc_device_t *device, uint32_t arg) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SWITCH, arg, true, 0, 0xFFFFFFFF); +} + +static int sdmmc_mmc_select_bus_width(sdmmc_device_t *device, SdmmcBusWidth bus_width) +{ + uint32_t arg = 0; + + /* Choose the argument for the switch command. */ + switch (bus_width) + { + case SDMMC_BUS_WIDTH_1BIT: + return 1; + case SDMMC_BUS_WIDTH_4BIT: + arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_BUS_WIDTH) << 16) | ((EXT_CSD_BUS_WIDTH_4) << 8)); + break; + case SDMMC_BUS_WIDTH_8BIT: + arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_BUS_WIDTH) << 16) | ((EXT_CSD_BUS_WIDTH_8) << 8)); + break; + default: + return 0; + } + + /* Try to switch the bus width. */ + if (sdmmc_mmc_switch(device, arg) && sdmmc_device_send_status(device)) + { + sdmmc_select_bus_width(device->sdmmc, bus_width); + return 1; + } + + return 0; +} + +static int sdmmc_mmc_select_hs(sdmmc_device_t *device, bool ignore_status) +{ + uint32_t arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_HS_TIMING) << 16) | ((EXT_CSD_TIMING_HS) << 8)); + + /* Try to switch to HS. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Check the status if necessary. */ + if (!ignore_status && !sdmmc_device_send_status(device)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS52)) + return 0; + + /* Check the status if necessary. */ + if (!ignore_status && !sdmmc_device_send_status(device)) + return 0; + + return 1; +} + +static int sdmmc_mmc_select_hs200(sdmmc_device_t *device) +{ + uint32_t arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_HS_TIMING) << 16) | ((EXT_CSD_TIMING_HS200) << 8)); + + /* Try to switch to HS200. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS200)) + return 0; + + /* Execute tuning procedure. */ + if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_HS200, MMC_SEND_TUNING_BLOCK_HS200)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + +static int sdmmc_mmc_select_hs400(sdmmc_device_t *device) +{ + uint32_t arg = 0; + + /* Switch to HS200 first. */ + if (!sdmmc_mmc_select_hs200(device)) + return 0; + + /* Fetch and set the tuning tap value. */ + sdmmc_set_tuning_tap_val(device->sdmmc); + + /* Switch to HS. */ + if (!sdmmc_mmc_select_hs(device, true)) + return 0; + + arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_BUS_WIDTH) << 16) | ((EXT_CSD_DDR_BUS_WIDTH_8) << 8)); + + /* Try to switch to 8bit bus. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_HS_TIMING) << 16) | ((EXT_CSD_TIMING_HS400) << 8)); + + /* Try to switch to HS400. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS400)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + +static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed) +{ + // FIXME: Tuning is broken. Use HS52 for now. + return sdmmc_mmc_select_hs(device, false); + + if ((bus_speed == SDMMC_SPEED_HS400) && + (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) && + (device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)) + { + /* Switch to HS400. */ + return sdmmc_mmc_select_hs400(device); + } + else if (((bus_speed == SDMMC_SPEED_HS400) || (bus_speed == SDMMC_SPEED_HS200)) && + ((device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) || (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT)) && + (device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)) + { + /* Switch to HS200. */ + return sdmmc_mmc_select_hs200(device); + } + else if (device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS_52) + { + /* Switch to HS. */ + return sdmmc_mmc_select_hs(device, false); + } + + return 0; +} + +static int sdmmc_mmc_select_bkops(sdmmc_device_t *device) +{ + uint32_t arg = (((MMC_SWITCH_MODE_SET_BITS) << 24) | ((EXT_CSD_BKOPS_EN) << 16) | ((EXT_CSD_BKOPS_LEVEL_2) << 8)); + + /* Try to enable bkops. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + +int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition) +{ + uint32_t arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_PART_CONFIG) << 16) | ((partition) << 8)); + + /* Try to change the active partition. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + +int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed) +{ + uint32_t cid[4] = {0}; + uint32_t csd[4] = {0}; + uint8_t *ext_csd = (uint8_t *)SDMMC_BOUNCE_BUFFER_ADDRESS; // TODO: Better way to do this. + + /* Initialize our device's struct. */ + memset(device, 0, sizeof(sdmmc_device_t)); + + /* Try to initialize the driver. */ + if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_VOLTAGE_1V8, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_HS)) + { + sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!"); + return 0; + } + + /* Bind the underlying driver. */ + device->sdmmc = sdmmc; + + /* Set RCA. */ + device->rca = 0x01; + + sdmmc_info(sdmmc, "SDMMC driver was successfully initialized for eMMC!"); + + /* Apply at least 74 clock cycles. eMMC should be ready afterwards. */ + udelay((74000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + /* Instruct the eMMC to go idle. */ + if (!sdmmc_device_go_idle(device)) + { + sdmmc_error(sdmmc, "Failed to go idle!"); + return 0; + } + + sdmmc_info(sdmmc, "eMMC went idle!"); + + /* Get the eMMC's operating conditions. */ + if (!sdmmc_mmc_send_op_cond(device, SDMMC_VOLTAGE_1V8)) + { + sdmmc_error(sdmmc, "Failed to send op cond!"); + return 0; + } + + sdmmc_info(sdmmc, "Sent op cond to eMMC!"); + + /* Get the eMMC's CID. */ + if (!sdmmc_device_send_cid(device, cid)) + { + sdmmc_error(sdmmc, "Failed to get CID!"); + return 0; + } + + sdmmc_info(sdmmc, "Got CID from eMMC!"); + + /* Set the eMMC's RCA. */ + if (!sdmmc_mmc_set_relative_addr(device)) + { + sdmmc_error(sdmmc, "Failed to set RCA!"); + return 0; + } + + sdmmc_info(sdmmc, "RCA is now set in eMMC!"); + + /* Get the eMMC card's CSD. */ + if (!sdmmc_device_send_csd(device, csd)) + { + sdmmc_error(sdmmc, "Failed to get CSD!"); + return 0; + } + + sdmmc_info(sdmmc, "Got CSD from eMMC!"); + + /* Decode and save the CSD. */ + if (!sdmmc_mmc_decode_csd(device, csd)) + sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure); + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS26)) + { + sdmmc_error(sdmmc, "Failed to apply the correct bus speed!"); + return 0; + } + + sdmmc_info(sdmmc, "Speed mode has been adjusted!"); + + /* Select the eMMC card. */ + if (!sdmmc_device_select_card(device)) + { + sdmmc_error(sdmmc, "Failed to select eMMC card!"); + return 0; + } + + sdmmc_info(sdmmc, "eMMC card is now selected!"); + + /* Change the eMMC's block length. */ + if (!sdmmc_device_set_blocklen(device, 512)) + { + sdmmc_error(sdmmc, "Failed to set eMMC's block length!"); + return 0; + } + + sdmmc_info(sdmmc, "eMMC's block length is now 512!"); + + /* Only specification version 4 and later support the next features. */ + if (device->csd.mmca_vsn < CSD_SPEC_VER_4) + return 1; + + /* Change the eMMC's bus width. */ + if (!sdmmc_mmc_select_bus_width(device, bus_width)) + { + sdmmc_error(sdmmc, "Failed to set eMMC's bus width!"); + return 0; + } + + sdmmc_info(sdmmc, "eMMC's bus width has been adjusted!"); + + /* Get the eMMC's extended CSD. */ + if (!sdmmc_mmc_send_ext_csd(device, ext_csd)) + { + sdmmc_error(sdmmc, "Failed to get EXT_CSD!"); + return 0; + } + + sdmmc_info(sdmmc, "Got EXT_CSD from eMMC!"); + + /* Decode and save the extended CSD. */ + sdmmc_mmc_decode_ext_csd(device, ext_csd); + + /* Decode and save the CID. */ + sdmmc_mmc_decode_cid(device, cid); + + /* TODO: Handle automatic BKOPS properly. Leave it disabled for now. */ + if (false && device->ext_csd.bkops && !(device->ext_csd.auto_bkops_en & EXT_CSD_AUTO_BKOPS_MASK)) + { + sdmmc_mmc_select_bkops(device); + sdmmc_info(sdmmc, "BKOPS is enabled!"); + } + else + sdmmc_info(sdmmc, "BKOPS is disabled!"); + + /* Switch to high speed mode. */ + if (!sdmmc_mmc_select_timing(device, bus_speed)) + { + sdmmc_error(sdmmc, "Failed to switch to high speed mode!"); + return 0; + } + + sdmmc_info(sdmmc, "Switched to high speed mode!"); + + /* Correct any inconsistent states. */ + sdmmc_adjust_sd_clock(sdmmc); + + return 1; +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc.h b/fusee/fusee-secondary/src/sdmmc/sdmmc.h new file mode 100644 index 000000000..c3a2a325b --- /dev/null +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc.h @@ -0,0 +1,161 @@ +#ifndef FUSEE_SDMMC_H +#define FUSEE_SDMMC_H + +#include "sdmmc_core.h" + +/* Structure for storing the MMC CID (adapted from Linux headers) */ +typedef struct { + uint32_t manfid; + uint8_t prod_name[8]; + uint8_t prv; + uint32_t serial; + uint16_t oemid; + uint16_t year; + uint8_t hwrev; + uint8_t fwrev; + uint8_t month; +} mmc_cid_t; + +/* Structure for storing the MMC CSD (adapted from Linux headers) */ +typedef struct { + uint8_t structure; + uint8_t mmca_vsn; + uint16_t cmdclass; + uint16_t taac_clks; + uint32_t taac_ns; + uint32_t c_size; + uint32_t r2w_factor; + uint32_t max_dtr; + uint32_t erase_size; /* In sectors */ + uint32_t read_blkbits; + uint32_t write_blkbits; + uint32_t capacity; + uint32_t read_partial:1, + read_misalign:1, + write_partial:1, + write_misalign:1, + dsr_imp:1; +} mmc_csd_t; + +/* Structure for storing the MMC extended CSD (adapted from Linux headers) */ +typedef struct { + uint8_t rev; + uint8_t erase_group_def; + uint8_t sec_feature_support; + uint8_t rel_sectors; + uint8_t rel_param; + uint8_t part_config; + uint8_t cache_ctrl; + uint8_t rst_n_function; + uint8_t max_packed_writes; + uint8_t max_packed_reads; + uint8_t packed_event_en; + uint32_t part_time; /* Units: ms */ + uint32_t sa_timeout; /* Units: 100ns */ + uint32_t generic_cmd6_time; /* Units: 10ms */ + uint32_t power_off_longtime; /* Units: ms */ + uint8_t power_off_notification; /* state */ + uint32_t hs_max_dtr; + uint32_t hs200_max_dtr; + uint32_t sectors; + uint32_t hc_erase_size; /* In sectors */ + uint32_t hc_erase_timeout; /* In milliseconds */ + uint32_t sec_trim_mult; /* Secure trim multiplier */ + uint32_t sec_erase_mult; /* Secure erase multiplier */ + uint32_t trim_timeout; /* In milliseconds */ + uint32_t partition_setting_completed; /* enable bit */ + uint64_t enhanced_area_offset; /* Units: Byte */ + uint32_t enhanced_area_size; /* Units: KB */ + uint32_t cache_size; /* Units: KB */ + uint32_t hpi_en; /* HPI enablebit */ + uint32_t hpi; /* HPI support bit */ + uint32_t hpi_cmd; /* cmd used as HPI */ + uint32_t bkops; /* background support bit */ + uint32_t man_bkops_en; /* manual bkops enable bit */ + uint32_t auto_bkops_en; /* auto bkops enable bit */ + uint32_t data_sector_size; /* 512 bytes or 4KB */ + uint32_t data_tag_unit_size; /* DATA TAG UNIT size */ + uint32_t boot_ro_lock; /* ro lock support */ + uint32_t boot_ro_lockable; + uint32_t ffu_capable; /* Firmware upgrade support */ + uint32_t cmdq_en; /* Command Queue enabled */ + uint32_t cmdq_support; /* Command Queue supported */ + uint32_t cmdq_depth; /* Command Queue depth */ + uint8_t fwrev[8]; /* FW version */ + uint8_t raw_exception_status; /* 54 */ + uint8_t raw_partition_support; /* 160 */ + uint8_t raw_rpmb_size_mult; /* 168 */ + uint8_t raw_erased_mem_count; /* 181 */ + uint8_t strobe_support; /* 184 */ + uint8_t raw_ext_csd_structure; /* 194 */ + uint8_t raw_card_type; /* 196 */ + uint8_t raw_driver_strength; /* 197 */ + uint8_t out_of_int_time; /* 198 */ + uint8_t raw_pwr_cl_52_195; /* 200 */ + uint8_t raw_pwr_cl_26_195; /* 201 */ + uint8_t raw_pwr_cl_52_360; /* 202 */ + uint8_t raw_pwr_cl_26_360; /* 203 */ + uint8_t raw_s_a_timeout; /* 217 */ + uint8_t raw_hc_erase_gap_size; /* 221 */ + uint8_t raw_erase_timeout_mult; /* 223 */ + uint8_t raw_hc_erase_grp_size; /* 224 */ + uint8_t raw_sec_trim_mult; /* 229 */ + uint8_t raw_sec_erase_mult; /* 230 */ + uint8_t raw_sec_feature_support; /* 231 */ + uint8_t raw_trim_mult; /* 232 */ + uint8_t raw_pwr_cl_200_195; /* 236 */ + uint8_t raw_pwr_cl_200_360; /* 237 */ + uint8_t raw_pwr_cl_ddr_52_195; /* 238 */ + uint8_t raw_pwr_cl_ddr_52_360; /* 239 */ + uint8_t raw_pwr_cl_ddr_200_360; /* 253 */ + uint8_t raw_bkops_status; /* 246 */ + uint8_t raw_sectors[4]; /* 212 - 4 bytes */ + uint8_t pre_eol_info; /* 267 */ + uint8_t device_life_time_est_typ_a; /* 268 */ + uint8_t device_life_time_est_typ_b; /* 269 */ + uint32_t feature_support; +} mmc_ext_csd_t; + +/* Structure for storing the SD SCR (adapted from Linux headers) */ +typedef struct { + uint8_t sda_vsn; + uint8_t sda_spec3; + uint8_t bus_widths; + uint8_t cmds; +} sd_scr_t; + +/* Structure for storing the SD SSR (adapted from Linux headers) */ +typedef struct { + uint8_t dat_bus_width; + uint8_t secured_mode; + uint16_t sd_card_type; + uint8_t speed_class; + uint8_t uhs_speed_grade; + uint8_t uhs_au_size; + uint8_t video_speed_class; + uint8_t app_perf_class; +} sd_ssr_t; + +/* Structure describing a SDMMC device's context. */ +typedef struct { + /* Underlying driver context. */ + sdmmc_t *sdmmc; + + bool is_180v; + bool is_block_sdhc; + uint32_t rca; + mmc_cid_t cid; + mmc_csd_t csd; + mmc_ext_csd_t ext_csd; + sd_scr_t scr; + sd_ssr_t ssr; +} sdmmc_device_t; + +int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed); +int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed); +int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data); +int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data); +int sdmmc_device_finish(sdmmc_device_t *device); +int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition); + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c new file mode 100644 index 000000000..5b96970c9 --- /dev/null +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -0,0 +1,1987 @@ +#include +#include +#include +#include +#include + +#include "sdmmc_core.h" +#include "../car.h" +#include "../pinmux.h" +#include "../timers.h" +#include "../apb_misc.h" +#include "../gpio.h" +#include "../pmc.h" +#include "../lib/driver_utils.h" +#include "../hwinit/max7762x.h" + +static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; + +void sdmmc_set_log_level(SdmmcLogLevel log_level) +{ + g_sdmmc_log_level = log_level; +} + +static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_list list) +{ + if (log_level > g_sdmmc_log_level) + return; + + switch (log_level) { + case SDMMC_LOG_ERROR: + printk("%s [ERROR]: ", sdmmc->name); + break; + case SDMMC_LOG_WARN: + printk("%s [WARN]: ", sdmmc->name); + break; + case SDMMC_LOG_INFO: + printk("%s [INFO]: ", sdmmc->name); + break; + case SDMMC_LOG_DEBUG: + printk("%s [DEBUG]: ", sdmmc->name); + break; + default: + break; + } + + vprintk(fmt, list); + printk("\n"); +} + +void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + sdmmc_print(sdmmc, SDMMC_LOG_ERROR, fmt, list); + va_end(list); +} + +void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + sdmmc_print(sdmmc, SDMMC_LOG_WARN, fmt, list); + va_end(list); +} + +void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + sdmmc_print(sdmmc, SDMMC_LOG_INFO, fmt, list); + va_end(list); +} + +void sdmmc_debug(sdmmc_t *sdmmc, char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + sdmmc_print(sdmmc, SDMMC_LOG_DEBUG, fmt, list); + va_end(list); +} + +void sdmmc_dump_regs(sdmmc_t *sdmmc) +{ + sdmmc_debug(sdmmc, "dma_address: 0x%08" PRIX32, sdmmc->regs->dma_address); + sdmmc_debug(sdmmc, "block_size: 0x%04" PRIX16, sdmmc->regs->block_size); + sdmmc_debug(sdmmc, "block_count: 0x%04" PRIX16, sdmmc->regs->block_count); + sdmmc_debug(sdmmc, "argument: 0x%08" PRIX32, sdmmc->regs->argument); + sdmmc_debug(sdmmc, "transfer_mode: 0x%04" PRIX16, sdmmc->regs->transfer_mode); + sdmmc_debug(sdmmc, "command: 0x%04" PRIX16, sdmmc->regs->command); + sdmmc_debug(sdmmc, "response[0]: 0x%08" PRIX32, sdmmc->regs->response[0]); + sdmmc_debug(sdmmc, "response[1]: 0x%08" PRIX32, sdmmc->regs->response[1]); + sdmmc_debug(sdmmc, "response[2]: 0x%08" PRIX32, sdmmc->regs->response[2]); + sdmmc_debug(sdmmc, "response[3]: 0x%08" PRIX32, sdmmc->regs->response[3]); + sdmmc_debug(sdmmc, "buffer: 0x%08" PRIX32, sdmmc->regs->buffer); + sdmmc_debug(sdmmc, "present_state: 0x%08" PRIX32, sdmmc->regs->present_state); + sdmmc_debug(sdmmc, "host_control: 0x%02" PRIX8, sdmmc->regs->host_control); + sdmmc_debug(sdmmc, "power_control: 0x%02" PRIX8, sdmmc->regs->power_control); + sdmmc_debug(sdmmc, "block_gap_control: 0x%02" PRIX8, sdmmc->regs->block_gap_control); + sdmmc_debug(sdmmc, "wake_up_control: 0x%02" PRIX8, sdmmc->regs->wake_up_control); + sdmmc_debug(sdmmc, "clock_control: 0x%04" PRIX16, sdmmc->regs->clock_control); + sdmmc_debug(sdmmc, "timeout_control: 0x%02" PRIX8, sdmmc->regs->timeout_control); + sdmmc_debug(sdmmc, "software_reset: 0x%02" PRIX8, sdmmc->regs->software_reset); + sdmmc_debug(sdmmc, "int_status: 0x%08" PRIX32, sdmmc->regs->int_status); + sdmmc_debug(sdmmc, "int_enable: 0x%08" PRIX32, sdmmc->regs->int_enable); + sdmmc_debug(sdmmc, "signal_enable: 0x%08" PRIX32, sdmmc->regs->signal_enable); + sdmmc_debug(sdmmc, "acmd12_err: 0x%04" PRIX16, sdmmc->regs->acmd12_err); + sdmmc_debug(sdmmc, "host_control2: 0x%04" PRIX16, sdmmc->regs->host_control2); + sdmmc_debug(sdmmc, "capabilities: 0x%08" PRIX32, sdmmc->regs->capabilities); + sdmmc_debug(sdmmc, "capabilities_1: 0x%08" PRIX32, sdmmc->regs->capabilities_1); + sdmmc_debug(sdmmc, "max_current: 0x%08" PRIX32, sdmmc->regs->max_current); + sdmmc_debug(sdmmc, "set_acmd12_error: 0x%04" PRIX16, sdmmc->regs->set_acmd12_error); + sdmmc_debug(sdmmc, "set_int_error: 0x%04" PRIX16, sdmmc->regs->set_int_error); + sdmmc_debug(sdmmc, "adma_error: 0x%02" PRIX8, sdmmc->regs->adma_error); + sdmmc_debug(sdmmc, "adma_address: 0x%08" PRIX32, sdmmc->regs->adma_address); + sdmmc_debug(sdmmc, "upper_adma_address: 0x%08" PRIX32, sdmmc->regs->upper_adma_address); + sdmmc_debug(sdmmc, "preset_for_init: 0x%04" PRIX16, sdmmc->regs->preset_for_init); + sdmmc_debug(sdmmc, "preset_for_default: 0x%04" PRIX16, sdmmc->regs->preset_for_default); + sdmmc_debug(sdmmc, "preset_for_high: 0x%04" PRIX16, sdmmc->regs->preset_for_high); + sdmmc_debug(sdmmc, "preset_for_sdr12: 0x%04" PRIX16, sdmmc->regs->preset_for_sdr12); + sdmmc_debug(sdmmc, "preset_for_sdr25: 0x%04" PRIX16, sdmmc->regs->preset_for_sdr25); + sdmmc_debug(sdmmc, "preset_for_sdr50: 0x%04" PRIX16, sdmmc->regs->preset_for_sdr50); + sdmmc_debug(sdmmc, "preset_for_sdr104: 0x%04" PRIX16, sdmmc->regs->preset_for_sdr104); + sdmmc_debug(sdmmc, "preset_for_ddr50: 0x%04" PRIX16, sdmmc->regs->preset_for_ddr50); + sdmmc_debug(sdmmc, "slot_int_status: 0x%04" PRIX16, sdmmc->regs->slot_int_status); + sdmmc_debug(sdmmc, "host_version: 0x%04" PRIX16, sdmmc->regs->host_version); + sdmmc_debug(sdmmc, "vendor_clock_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_clock_cntrl); + sdmmc_debug(sdmmc, "vendor_sys_sw_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_sys_sw_cntrl); + sdmmc_debug(sdmmc, "vendor_err_intr_status: 0x%08" PRIX32, sdmmc->regs->vendor_err_intr_status); + sdmmc_debug(sdmmc, "vendor_cap_overrides: 0x%08" PRIX32, sdmmc->regs->vendor_cap_overrides); + sdmmc_debug(sdmmc, "vendor_boot_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_boot_cntrl); + sdmmc_debug(sdmmc, "vendor_boot_ack_timeout: 0x%08" PRIX32, sdmmc->regs->vendor_boot_ack_timeout); + sdmmc_debug(sdmmc, "vendor_boot_dat_timeout: 0x%08" PRIX32, sdmmc->regs->vendor_boot_dat_timeout); + sdmmc_debug(sdmmc, "vendor_debounce_count: 0x%08" PRIX32, sdmmc->regs->vendor_debounce_count); + sdmmc_debug(sdmmc, "vendor_misc_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_misc_cntrl); + sdmmc_debug(sdmmc, "max_current_override: 0x%08" PRIX32, sdmmc->regs->max_current_override); + sdmmc_debug(sdmmc, "max_current_override_hi: 0x%08" PRIX32, sdmmc->regs->max_current_override_hi); + sdmmc_debug(sdmmc, "vendor_io_trim_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_io_trim_cntrl); + sdmmc_debug(sdmmc, "vendor_dllcal_cfg: 0x%08" PRIX32, sdmmc->regs->vendor_dllcal_cfg); + sdmmc_debug(sdmmc, "vendor_dll_ctrl0: 0x%08" PRIX32, sdmmc->regs->vendor_dll_ctrl0); + sdmmc_debug(sdmmc, "vendor_dll_ctrl1: 0x%08" PRIX32, sdmmc->regs->vendor_dll_ctrl1); + sdmmc_debug(sdmmc, "vendor_dllcal_cfg_sta: 0x%08" PRIX32, sdmmc->regs->vendor_dllcal_cfg_sta); + sdmmc_debug(sdmmc, "vendor_tuning_cntrl0: 0x%08" PRIX32, sdmmc->regs->vendor_tuning_cntrl0); + sdmmc_debug(sdmmc, "vendor_tuning_cntrl1: 0x%08" PRIX32, sdmmc->regs->vendor_tuning_cntrl1); + sdmmc_debug(sdmmc, "vendor_tuning_status0: 0x%08" PRIX32, sdmmc->regs->vendor_tuning_status0); + sdmmc_debug(sdmmc, "vendor_tuning_status1: 0x%08" PRIX32, sdmmc->regs->vendor_tuning_status1); + sdmmc_debug(sdmmc, "vendor_clk_gate_hysteresis_count: 0x%08" PRIX32, sdmmc->regs->vendor_clk_gate_hysteresis_count); + sdmmc_debug(sdmmc, "vendor_preset_val0: 0x%08" PRIX32, sdmmc->regs->vendor_preset_val0); + sdmmc_debug(sdmmc, "vendor_preset_val1: 0x%08" PRIX32, sdmmc->regs->vendor_preset_val1); + sdmmc_debug(sdmmc, "vendor_preset_val2: 0x%08" PRIX32, sdmmc->regs->vendor_preset_val2); + sdmmc_debug(sdmmc, "sdmemcomppadctrl: 0x%08" PRIX32, sdmmc->regs->sdmemcomppadctrl); + sdmmc_debug(sdmmc, "auto_cal_config: 0x%08" PRIX32, sdmmc->regs->auto_cal_config); + sdmmc_debug(sdmmc, "auto_cal_interval: 0x%08" PRIX32, sdmmc->regs->auto_cal_interval); + sdmmc_debug(sdmmc, "auto_cal_status: 0x%08" PRIX32, sdmmc->regs->auto_cal_status); + sdmmc_debug(sdmmc, "io_spare: 0x%08" PRIX32, sdmmc->regs->io_spare); + sdmmc_debug(sdmmc, "sdmmca_mccif_fifoctrl: 0x%08" PRIX32, sdmmc->regs->sdmmca_mccif_fifoctrl); + sdmmc_debug(sdmmc, "timeout_wcoal_sdmmca: 0x%08" PRIX32, sdmmc->regs->timeout_wcoal_sdmmca); +} + +typedef struct { + uint32_t clk_source_val; + uint32_t clk_div_val; +} sdmmc_clk_source_t; + +static sdmmc_clk_source_t sdmmc_clk_sources[4] = {0}; + +/* Check if the SDMMC device clock is held in reset. */ +static bool is_sdmmc_clk_rst(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + return (car->rst_dev_l & CLK_L_SDMMC1); + case SDMMC_2: + return (car->rst_dev_l & CLK_L_SDMMC2); + case SDMMC_3: + return (car->rst_dev_u & CLK_U_SDMMC3); + case SDMMC_4: + return (car->rst_dev_l & CLK_L_SDMMC4); + } + + return false; +} + +/* Put the SDMMC device clock in reset. */ +static void sdmmc_clk_set_rst(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + car->rst_dev_l_set = CLK_L_SDMMC1; + break; + case SDMMC_2: + car->rst_dev_l_set = CLK_L_SDMMC2; + break; + case SDMMC_3: + car->rst_dev_u_set = CLK_U_SDMMC3; + break; + case SDMMC_4: + car->rst_dev_l_set = CLK_L_SDMMC4; + break; + } +} + +/* Take the SDMMC device clock out of reset. */ +static void sdmmc_clk_clear_rst(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + car->rst_dev_l_clr = CLK_L_SDMMC1; + break; + case SDMMC_2: + car->rst_dev_l_clr = CLK_L_SDMMC2; + break; + case SDMMC_3: + car->rst_dev_u_clr = CLK_U_SDMMC3; + break; + case SDMMC_4: + car->rst_dev_l_clr = CLK_L_SDMMC4; + break; + } +} + +/* Check if the SDMMC device clock is enabled. */ +static bool is_sdmmc_clk_enb(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + return (car->clk_out_enb_l & CLK_L_SDMMC1); + case SDMMC_2: + return (car->clk_out_enb_l & CLK_L_SDMMC2); + case SDMMC_3: + return (car->clk_out_enb_u & CLK_U_SDMMC3); + case SDMMC_4: + return (car->clk_out_enb_l & CLK_L_SDMMC4); + } + + return false; +} + +/* Enable the SDMMC device clock. */ +static void sdmmc_clk_set_enb(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + car->clk_enb_l_set = CLK_L_SDMMC1; + break; + case SDMMC_2: + car->clk_enb_l_set = CLK_L_SDMMC2; + break; + case SDMMC_3: + car->clk_enb_u_set = CLK_U_SDMMC3; + break; + case SDMMC_4: + car->clk_enb_l_set = CLK_L_SDMMC4; + break; + } +} + +/* Disable the SDMMC device clock. */ +static void sdmmc_clk_clear_enb(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + car->clk_enb_l_clr = CLK_L_SDMMC1; + break; + case SDMMC_2: + car->clk_enb_l_clr = CLK_L_SDMMC2; + break; + case SDMMC_3: + car->clk_enb_u_clr = CLK_U_SDMMC3; + break; + case SDMMC_4: + car->clk_enb_l_clr = CLK_L_SDMMC4; + break; + } +} + +/* Get the appropriate SDMMC maximum frequency. */ +static int sdmmc_get_sdclk_freq(SdmmcBusSpeed bus_speed) +{ + switch (bus_speed) + { + case SDMMC_SPEED_INIT_HS: + case SDMMC_SPEED_HS26: + return 26000; + case SDMMC_SPEED_HS52: + return 52000; + case SDMMC_SPEED_HS200: + case SDMMC_SPEED_HS400: + case SDMMC_SPEED_SDR104: + return 200000; + case SDMMC_SPEED_INIT_SDR: + case SDMMC_SPEED_UNK6: + case SDMMC_SPEED_SDR12: + return 25000; + case SDMMC_SPEED_SDR25: + return 50000; + case SDMMC_SPEED_SDR50: + return 100000; + case SDMMC_SPEED_DDR50: + return 40800; + case SDMMC_SPEED_UNK14: + return 200000; + default: + return 0; + } +} + +/* Get the appropriate SDMMC divider for the SDCLK. */ +static int sdmmc_get_sdclk_div(SdmmcBusSpeed bus_speed) +{ + switch (bus_speed) + { + case SDMMC_SPEED_INIT_HS: + return 66; + case SDMMC_SPEED_INIT_SDR: + // TODO: TRM says return 64? + case SDMMC_SPEED_HS26: + case SDMMC_SPEED_HS52: + case SDMMC_SPEED_HS200: + case SDMMC_SPEED_HS400: + case SDMMC_SPEED_UNK6: + case SDMMC_SPEED_SDR25: + case SDMMC_SPEED_SDR12: + case SDMMC_SPEED_SDR50: + case SDMMC_SPEED_SDR104: + case SDMMC_SPEED_DDR50: + return 1; + case SDMMC_SPEED_UNK14: + return 2; + default: + return 0; + } +} + +/* Set the device clock source and CAR divider. */ +static int sdmmc_clk_set_source(SdmmcControllerNum controller, uint32_t clk_freq) +{ + volatile tegra_car_t *car = car_get_regs(); + + uint32_t car_div = 0; + uint32_t out_freq = 0; + + switch (clk_freq) + { + case 25000: + out_freq = 24728; + car_div = SDMMC_CAR_DIVIDER_SDR12; + break; + case 26000: + out_freq = 25500; + car_div = SDMMC_CAR_DIVIDER_HS26; + break; + case 40800: + out_freq = 40800; + car_div = SDMMC_CAR_DIVIDER_DDR50; + break; + case 50000: + out_freq = 48000; + car_div = SDMMC_CAR_DIVIDER_SDR25; + break; + case 52000: + out_freq = 51000; + car_div = SDMMC_CAR_DIVIDER_HS52; + break; + case 100000: + out_freq = 90667; + car_div = SDMMC_CAR_DIVIDER_SDR50; + break; + case 200000: + out_freq = 163200; + car_div = SDMMC_CAR_DIVIDER_HS200; + break; + case 208000: + out_freq = 204000; + car_div = SDMMC_CAR_DIVIDER_SDR104; + break; + default: + return 0; + } + + sdmmc_clk_sources[controller].clk_source_val = clk_freq; + sdmmc_clk_sources[controller].clk_div_val = out_freq; + + switch (controller) + { + case SDMMC_1: + car->clk_src[CLK_SOURCE_SDMMC1] = (CLK_SOURCE_FIRST | car_div); + break; + case SDMMC_2: + car->clk_src[CLK_SOURCE_SDMMC2] = (CLK_SOURCE_FIRST | car_div); + break; + case SDMMC_3: + car->clk_src[CLK_SOURCE_SDMMC3] = (CLK_SOURCE_FIRST | car_div); + break; + case SDMMC_4: + car->clk_src[CLK_SOURCE_SDMMC4] = (CLK_SOURCE_FIRST | car_div); + break; + } + + return out_freq; +} + +/* Adjust the device clock source value. */ +static int sdmmc_clk_adjust_source(SdmmcControllerNum controller, uint32_t clk_source_val) +{ + uint32_t out_val = 0; + + if (sdmmc_clk_sources[controller].clk_source_val == clk_source_val) + out_val = sdmmc_clk_sources[controller].clk_div_val; + else + { + bool was_sdmmc_clk_enb = is_sdmmc_clk_enb(controller); + + /* Clock was already enabled. Disable it. */ + if (was_sdmmc_clk_enb) + sdmmc_clk_clear_enb(controller); + + out_val = sdmmc_clk_set_source(controller, clk_source_val); + + /* Clock was already enabled. Enable it back. */ + if (was_sdmmc_clk_enb) + sdmmc_clk_set_enb(controller); + + /* Dummy read for value refreshing. */ + is_sdmmc_clk_rst(controller); + } + + return out_val; +} + +/* Enable the SD clock if possible. */ +static void sdmmc_enable_sd_clock(sdmmc_t *sdmmc) +{ + if ((sdmmc->has_sd) && !(sdmmc->regs->clock_control & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)) + sdmmc->regs->clock_control |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; + sdmmc->is_sd_clk_enabled = true; +} + +/* Disable the SD clock. */ +static void sdmmc_disable_sd_clock(sdmmc_t *sdmmc) +{ + sdmmc->is_sd_clk_enabled = false; + sdmmc->regs->clock_control &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; +} + +/* Automatically enable or disable the SD clock. */ +void sdmmc_adjust_sd_clock(sdmmc_t *sdmmc) +{ + if (!(sdmmc->has_sd) && (sdmmc->regs->clock_control & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)) + sdmmc_disable_sd_clock(sdmmc); + else if (sdmmc->is_sd_clk_enabled && !(sdmmc->regs->clock_control & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)) + sdmmc_enable_sd_clock(sdmmc); +} + +/* Return the clock control value. Used for dummy reads. */ +static int sdmmc_get_sd_clock_control(sdmmc_t *sdmmc) +{ + return sdmmc->regs->clock_control; +} + +/* Start the SDMMC clock. */ +static void sdmmc_clk_start(SdmmcControllerNum controller, uint32_t clk_source_val) +{ + /* Clock was already enabled. Disable it. */ + if (is_sdmmc_clk_enb(controller)) + sdmmc_clk_clear_enb(controller); + + /* Put the device clock in reset. */ + sdmmc_clk_set_rst(controller); + + /* Configure the device clock source. */ + uint32_t clk_div = sdmmc_clk_set_source(controller, clk_source_val); + + /* Enable the device clock. */ + sdmmc_clk_set_enb(controller); + + /* Dummy read for value refreshing. */ + is_sdmmc_clk_rst(controller); + + /* Synchronize. */ + udelay((100000 + clk_div - 1) / clk_div); + + /* Take the device clock out of reset. */ + sdmmc_clk_clear_rst(controller); + + /* Dummy read for value refreshing. */ + is_sdmmc_clk_rst(controller); +} + +/* Stop the SDMMC clock. */ +static void sdmmc_clk_stop(SdmmcControllerNum controller) +{ + /* Put the device clock in reset. */ + sdmmc_clk_set_rst(controller); + + /* Disable the device clock. */ + sdmmc_clk_clear_enb(controller); + + /* Dummy read for value refreshing. */ + is_sdmmc_clk_rst(controller); +} + +/* Configure clock trimming. */ +static void sdmmc_vendor_clock_cntrl_config(sdmmc_t *sdmmc) +{ + /* Clear the I/O conditioning constants. */ + sdmmc->regs->vendor_clock_cntrl &= ~(SDMMC_CLOCK_TRIM_MASK | SDMMC_CLOCK_TAP_MASK); + + /* Per the TRM, set the PADPIPE clock enable */ + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_PADPIPE_CLKEN_OVERRIDE; + + /* Set the appropriate trim value. */ + switch (sdmmc->controller) { + case SDMMC_1: + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_TRIM_SDMMC1; + break; + case SDMMC_2: + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_TRIM_SDMMC2; + break; + case SDMMC_3: + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_TRIM_SDMMC3; + break; + case SDMMC_4: + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_TRIM_SDMMC4; + break; + } +} + +/* Configure automatic calibration. */ +static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) +{ + switch (sdmmc->controller) { + case SDMMC_1: + case SDMMC_3: + switch (voltage) { + case SDMMC_VOLTAGE_1V8: + sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_1V8; + break; + case SDMMC_VOLTAGE_3V3: + sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_3V3; + break; + default: + sdmmc_error(sdmmc, "microsd does not support voltage %d", voltage); + return 0; + } + + break; + + case SDMMC_2: + case SDMMC_4: + if (voltage != SDMMC_VOLTAGE_1V8) { + sdmmc_error(sdmmc, "eMMC can only run at 1V8, but sdmmc struct claims voltage %d", voltage); + return 0; + } + + sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC4_1V8; + break; + } + + return 1; +} + +/* Run automatic calibration. */ +static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) +{ + bool restart_sd_clock = false; + volatile tegra_padctl_t *padctl = padctl_get_regs(); + + /* SD clock is enabled. Disable it and restart later. */ + if (sdmmc->is_sd_clk_enabled) + { + restart_sd_clock = true; + sdmmc_disable_sd_clock(sdmmc); + } + + /* Set PAD_E_INPUT_OR_E_PWRD */ + if (!(sdmmc->regs->sdmemcomppadctrl & 0x80000000)) + { + sdmmc->regs->sdmemcomppadctrl |= 0x80000000; + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Delay. */ + udelay(1); + } + + /* Start automatic calibration. */ + sdmmc->regs->auto_cal_config |= (SDMMC_AUTOCAL_START | SDMMC_AUTOCAL_ENABLE); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Delay. */ + udelay(1); + + /* Get current time. */ + uint32_t timebase = get_time(); + + /* Wait until the autocal is complete. */ + while ((sdmmc->regs->auto_cal_status & SDMMC_AUTOCAL_ACTIVE)) { + /* Ensure we haven't timed out. */ + if (get_time_since(timebase) > SDMMC_AUTOCAL_TIMEOUT) { + sdmmc_error(sdmmc, "autocal timed out!"); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Upon timeout, fall back to standard values. */ + if (sdmmc->controller == SDMMC_1) { + uint32_t drvup = (voltage == SDMMC_VOLTAGE_3V3) ? 0x12 : 0x11; + uint32_t drvdn = (voltage == SDMMC_VOLTAGE_3V3) ? 0x12 : 0x15; + uint32_t value = padctl->sdmmc1_pad_cfgpadctrl; + value &= ~(SDMMC1_PAD_CAL_DRVUP_MASK | SDMMC1_PAD_CAL_DRVDN_MASK); + value |= (drvup << SDMMC1_PAD_CAL_DRVUP_SHIFT); + value |= (drvdn << SDMMC1_PAD_CAL_DRVDN_SHIFT); + padctl->sdmmc1_pad_cfgpadctrl = value; + } else if (sdmmc->controller == SDMMC_4) { + uint32_t value = padctl->emmc4_pad_cfgpadctrl; + value &= ~(CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK | CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK); + value |= (0x10 << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT); + value |= (0x10 << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT); + padctl->emmc4_pad_cfgpadctrl = value; + } + + /* Manually clear the autocal enable bit. */ + sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_ENABLE; + break; + } + } + + /* Clear PAD_E_INPUT_OR_E_PWRD (relevant for eMMC only) */ + sdmmc->regs->sdmemcomppadctrl &= ~(0x80000000); + + /* If requested, enable the SD clock. */ + if (restart_sd_clock) + sdmmc_enable_sd_clock(sdmmc); +} + +static int sdmmc_int_clk_enable(sdmmc_t *sdmmc) +{ + /* Enable the internal clock. */ + sdmmc->regs->clock_control |= TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE; + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 2000ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait for the clock to stabilize. */ + while (!(sdmmc->regs->clock_control & TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + } + + /* Clock failed to stabilize. */ + if (is_timeout) { + sdmmc_error(sdmmc, "clock never stabilized!"); + return 0; + } + + /* Configure clock control and host control 2. */ + sdmmc->regs->host_control2 &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; + sdmmc->regs->clock_control &= ~TEGRA_MMC_CLKCON_PROG_CLOCK_MODE; + sdmmc->regs->host_control2 |= SDHCI_HOST_VERSION_4_EN; + + /* Ensure 64bit addressing is supported. */ + if (!(sdmmc->regs->capabilities & SDHCI_CAN_64BIT)) { + sdmmc_error(sdmmc, "64bit addressing is unsupported!"); + return 0; + } + + /* Enable 64bit addressing. */ + sdmmc->regs->host_control2 |= SDHCI_ADDRESSING_64BIT_EN; + + /* Use SDMA by default. */ + sdmmc->regs->host_control &= ~SDHCI_CTRL_DMA_MASK; + + /* Change to ADMA if requested. */ + if (sdmmc->use_adma && (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)) { + // TODO: Setting the ADMA flags breaks ADMA... + /* + if (sdmmc->regs->capabilities & SDHCI_CAN_64BIT) + sdmmc->regs->host_control |= SDHCI_CTRL_ADMA64; + else + sdmmc->regs->host_control |= SDHCI_CTRL_ADMA32; + */ + } + + /* Set the timeout to be the maximum value. */ + sdmmc->regs->timeout_control &= 0xF0; + sdmmc->regs->timeout_control |= 0x0E; + + return 1; +} + +void sdmmc_select_bus_width(sdmmc_t *sdmmc, SdmmcBusWidth width) +{ + if (width == SDMMC_BUS_WIDTH_1BIT) + { + sdmmc->regs->host_control &= ~(SDHCI_CTRL_4BITBUS | SDHCI_CTRL_8BITBUS); + sdmmc->bus_width = SDMMC_BUS_WIDTH_1BIT; + } + else if (width == SDMMC_BUS_WIDTH_4BIT) + { + sdmmc->regs->host_control |= SDHCI_CTRL_4BITBUS; + sdmmc->regs->host_control &= ~SDHCI_CTRL_8BITBUS; + sdmmc->bus_width = SDMMC_BUS_WIDTH_4BIT; + } + else if (width == SDMMC_BUS_WIDTH_8BIT) + { + sdmmc->regs->host_control |= SDHCI_CTRL_8BITBUS; + sdmmc->bus_width = SDMMC_BUS_WIDTH_8BIT; + } + else + sdmmc_error(sdmmc, "Invalid bus width specified!"); +} + +void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) +{ + if (voltage == SDMMC_VOLTAGE_NONE) + { + sdmmc->regs->power_control &= ~TEGRA_MMC_PWRCTL_SD_BUS_POWER; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + } + else if (voltage == SDMMC_VOLTAGE_1V8) + { + sdmmc->regs->power_control |= TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8; + sdmmc->regs->power_control |= TEGRA_MMC_PWRCTL_SD_BUS_POWER; + sdmmc->bus_voltage = SDMMC_VOLTAGE_1V8; + } + else if (voltage == SDMMC_VOLTAGE_3V3) + { + sdmmc->regs->power_control |= TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3; + sdmmc->regs->power_control |= TEGRA_MMC_PWRCTL_SD_BUS_POWER; + sdmmc->bus_voltage = SDMMC_VOLTAGE_3V3; + } + else + sdmmc_error(sdmmc, "Invalid power state specified!"); +} + +static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed) +{ + if (bus_speed == SDMMC_SPEED_HS400) + { + /* Clear and set DQS_TRIM_VAL (used in HS400) */ + sdmmc->regs->vendor_cap_overrides &= ~(0x3F00); + sdmmc->regs->vendor_cap_overrides |= 0x2800; + } + + /* Clear TAP_VAL_UPDATED_BY_HW */ + sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x20000); + + if (bus_speed == SDMMC_SPEED_HS400) + { + /* We must have obtained the tap value from the tuning procedure here. */ + if (sdmmc->is_tuning_tap_val_set) + { + /* Clear and set the tap value. */ + sdmmc->regs->vendor_clock_cntrl &= ~(0xFF0000); + sdmmc->regs->vendor_clock_cntrl |= (sdmmc->tap_val << 16); + } + } + else + { + /* Use the recommended values. */ + switch (sdmmc->controller) + { + case SDMMC_1: + sdmmc->tap_val = 4; + break; + case SDMMC_2: + case SDMMC_4: + sdmmc->tap_val = 0; + break; + case SDMMC_3: + sdmmc->tap_val = 3; + break; + } + + /* Clear and set the tap value. */ + sdmmc->regs->vendor_clock_cntrl &= ~(0xFF0000); + sdmmc->regs->vendor_clock_cntrl |= (sdmmc->tap_val << 16); + } +} + +static int sdmmc_dllcal_run(sdmmc_t *sdmmc) +{ + bool shutdown_sd_clock = false; + + /* SD clock is disabled. Enable it. */ + if (!sdmmc->is_sd_clk_enabled) + { + shutdown_sd_clock = true; + sdmmc_enable_sd_clock(sdmmc); + } + + /* Set the CALIBRATE bit. */ + sdmmc->regs->vendor_dllcal_cfg |= 0x80000000; + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 5ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait for CALIBRATE to be cleared. */ + while ((sdmmc->regs->vendor_dllcal_cfg & 0x80000000) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 5000); + } + + /* Calibration failed. */ + if (is_timeout) { + sdmmc_error(sdmmc, "DLLCAL failed!"); + return 0; + } + + /* Program a timeout of 10ms. */ + timebase = get_time(); + is_timeout = false; + + /* Wait for DLL_CAL_ACTIVE to be cleared. */ + while ((sdmmc->regs->vendor_dllcal_cfg_sta & 0x80000000) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 10000); + } + + /* Clock failed to stabilize. */ + if (is_timeout) { + sdmmc_error(sdmmc, "ERROR: DLLCAL failed!"); + return 0; + } + + /* If requested, disable the SD clock. */ + if (shutdown_sd_clock) + sdmmc_disable_sd_clock(sdmmc); + + return 1; +} + +int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed) +{ + bool restart_sd_clock = false; + + /* SD clock is enabled. Disable it and restart later. */ + if (sdmmc->is_sd_clk_enabled) + { + restart_sd_clock = true; + sdmmc_disable_sd_clock(sdmmc); + } + + /* Configure tap values as necessary. */ + sdmmc_tap_config(sdmmc, bus_speed); + + /* Set the appropriate host speed. */ + switch (bus_speed) { + /* 400kHz initialization mode and a few others. */ + case SDMMC_SPEED_INIT_HS: + case SDMMC_SPEED_HS26: + case SDMMC_SPEED_INIT_SDR: + case SDMMC_SPEED_UNK6: + sdmmc->regs->host_control &= ~(SDHCI_CTRL_HISPD); + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180); + break; + + /* 50MHz high speed (SD) and 52MHz high speed (MMC). */ + case SDMMC_SPEED_SDR25: + case SDMMC_SPEED_HS52: + sdmmc->regs->host_control |= SDHCI_CTRL_HISPD; + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180); + break; + + /* 200MHz UHS-I (SD) and other modes due to errata. */ + case SDMMC_SPEED_HS200: + case SDMMC_SPEED_SDR104: + case SDMMC_SPEED_DDR50: + case SDMMC_SPEED_SDR50: + case SDMMC_SPEED_UNK14: + sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; + sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180); + break; + + /* 200MHz single-data rate (MMC). */ + case SDMMC_SPEED_HS400: + sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; + sdmmc->regs->host_control2 |= (SDHCI_CTRL_HS400 | SDHCI_CTRL_VDD_180); + break; + + /* 25MHz default speed (SD). */ + case SDMMC_SPEED_SDR12: + sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; + sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180); + break; + + default: + sdmmc_error(sdmmc, "Switching to unsupported speed!"); + return 0; + } + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Get the clock's frequency and divider. */ + uint32_t freq_val = sdmmc_get_sdclk_freq(bus_speed); + uint32_t div_val = sdmmc_get_sdclk_div(bus_speed); + + /* Adjust the CAR side of the clock. */ + uint32_t out_freq_val = sdmmc_clk_adjust_source(sdmmc->controller, freq_val); + + /* Save the internal divider value. */ + sdmmc->internal_divider = ((out_freq_val + div_val - 1) / div_val); + + uint16_t div_val_lo = div_val >> 1; + uint16_t div_val_hi = 0; + + if (div_val_lo > 0xFF) + div_val_hi = (div_val_lo >> 8); + + /* Set the clock control divider values. */ + sdmmc->regs->clock_control &= ~((SDHCI_DIV_HI_MASK | SDHCI_DIV_MASK) << 6); + sdmmc->regs->clock_control |= ((div_val_hi << SDHCI_DIVIDER_HI_SHIFT) | (div_val_lo << SDHCI_DIVIDER_SHIFT)); + + /* If requested, enable the SD clock. */ + if (restart_sd_clock) + sdmmc_enable_sd_clock(sdmmc); + + /* Run DLLCAL for HS400 only */ + if (bus_speed == SDMMC_SPEED_HS400) + return sdmmc_dllcal_run(sdmmc); + + return 1; +} + +static int sdmmc1_config() +{ + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + volatile tegra_padctl_t *padctl = padctl_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* Set up the card detect pin as a GPIO input */ + pinmux->pz1 = PINMUX_SELECT_FUNCTION1 | PINMUX_PULL_UP | PINMUX_INPUT; + padctl->vgpio_gpio_mux_sel = 0; + gpio_configure_mode(GPIO_MICROSD_CARD_DETECT, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_MICROSD_CARD_DETECT, GPIO_DIRECTION_INPUT); + udelay(100); + + /* Check the GPIO. */ + if (gpio_read(GPIO_MICROSD_CARD_DETECT)) + return 0; + + padctl->sdmmc1_clk_lpbk_control = 1; + + /* Set up the SDMMC1 pinmux. */ + pinmux->sdmmc1_clk = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT; + pinmux->sdmmc1_cmd = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + pinmux->sdmmc1_dat3 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + pinmux->sdmmc1_dat2 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + pinmux->sdmmc1_dat1 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + pinmux->sdmmc1_dat0 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + + /* Ensure the PMC is prepared for the SDMMC1 card to receive power. */ + pmc->no_iopower &= ~PMC_CONTROL_SDMMC1; + pmc->pwr_det_val |= PMC_CONTROL_SDMMC1; + + /* Configure the enable line for the SD card power. */ + pinmux->dmic3_clk = PINMUX_SELECT_FUNCTION1 | PINMUX_PULL_DOWN | PINMUX_INPUT; + gpio_configure_mode(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_MODE_GPIO); + gpio_write(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_LEVEL_HIGH); + gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_OUTPUT); + + udelay(1000); + + /* Set up SD card voltages. */ + max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); + max77620_regulator_enable(REGULATOR_LDO2, 1); + + udelay(1000); + + padctl->sdmmc1_pad_cfgpadctrl = 0x10000000; + + udelay(1000); + + return 1; +} + +static int sdmmc2_config() +{ + return 1; +} + +static int sdmmc3_config() +{ + return 1; +} + +static int sdmmc4_config() +{ + return 1; +} + +static int sdmmc_init_controller(sdmmc_t *sdmmc, SdmmcControllerNum controller) +{ + /* Sanitize input number for the controller. */ + if ((controller < SDMMC_1) || (controller > SDMMC_4)) + return 0; + + /* Clear up memory for our struct. */ + memset(sdmmc, 0, sizeof(sdmmc_t)); + + /* Bind the appropriate controller and it's register space to our struct. */ + sdmmc->controller = controller; + sdmmc->regs = sdmmc_get_regs(controller); + + /* Set up per-device pointers and properties. */ + switch (sdmmc->controller) { + case SDMMC_1: + /* Controller properties. */ + sdmmc->name = "uSD"; + sdmmc->has_sd = true; + sdmmc->is_clk_running = false; + sdmmc->is_sd_clk_enabled = false; + sdmmc->is_tuning_tap_val_set = false; + sdmmc->use_adma = false; + sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; + sdmmc->tap_val = 0; + sdmmc->internal_divider = 0; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + + /* Function pointers. */ + sdmmc->sdmmc_config = sdmmc1_config; + break; + + case SDMMC_2: + /* Controller properties. */ + sdmmc->name = "GC"; + sdmmc->has_sd = true; + sdmmc->is_clk_running = false; + sdmmc->is_sd_clk_enabled = false; + sdmmc->is_tuning_tap_val_set = false; + sdmmc->use_adma = false; + sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; + sdmmc->tap_val = 0; + sdmmc->internal_divider = 0; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + + /* Function pointers. */ + sdmmc->sdmmc_config = sdmmc2_config; + break; + + case SDMMC_3: + /* Controller properties. */ + sdmmc->name = "UNUSED"; + sdmmc->has_sd = true; + sdmmc->is_clk_running = false; + sdmmc->is_sd_clk_enabled = false; + sdmmc->is_tuning_tap_val_set = false; + sdmmc->use_adma = false; + sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; + sdmmc->tap_val = 0; + sdmmc->internal_divider = 0; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + + /* Function pointers. */ + sdmmc->sdmmc_config = sdmmc3_config; + break; + + case SDMMC_4: + /* Controller properties. */ + sdmmc->name = "eMMC"; + sdmmc->has_sd = true; + sdmmc->is_clk_running = false; + sdmmc->is_sd_clk_enabled = false; + sdmmc->is_tuning_tap_val_set = false; + sdmmc->use_adma = true; + sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; + sdmmc->tap_val = 0; + sdmmc->internal_divider = 0; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + + /* Function pointers. */ + sdmmc->sdmmc_config = sdmmc4_config; + break; + } + + return 1; +} + +int sdmmc_init(sdmmc_t *sdmmc, SdmmcControllerNum controller, SdmmcBusVoltage bus_voltage, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed) +{ + /* Initialize our controller structure. */ + if (!sdmmc_init_controller(sdmmc, controller)) { + sdmmc_error(sdmmc, "Failed to initialize SDMMC%d", controller + 1); + return 0; + } + + /* Perform initial configuration steps if necessary. */ + if (!sdmmc->sdmmc_config()) { + sdmmc_error(sdmmc, "Failed to configure controller!"); + return 0; + } + + /* Initialize the clock status. */ + sdmmc->is_clk_running = false; + + /* Clock is enabled and out of reset. Shouldn't happen. */ + if (!is_sdmmc_clk_rst(controller) && is_sdmmc_clk_enb(controller)) { + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + } + + /* Sort out the clock's frequency. */ + uint32_t clk_freq_val = sdmmc_get_sdclk_freq(bus_speed); + + /* Start the SDMMC clock. */ + sdmmc_clk_start(controller, clk_freq_val); + + /* Update the clock status. */ + sdmmc->is_clk_running = true; + + // Set IO_SPARE[19] (one cycle delay) + sdmmc->regs->io_spare |= 0x80000; + + // Clear SEL_VREG + sdmmc->regs->vendor_io_trim_cntrl &= ~(0x04); + + /* Configure vendor clocking. */ + sdmmc_vendor_clock_cntrl_config(sdmmc); + + // Set SDMMC2TMC_CFG_SDMEMCOMP_VREF_SEL to 0x07 + sdmmc->regs->sdmemcomppadctrl &= 0x0F; + sdmmc->regs->sdmemcomppadctrl |= 0x07; + + /* Configure autocal offsets. */ + if (!sdmmc_autocal_config(sdmmc, bus_voltage)) { + sdmmc_error(sdmmc, "Failed to configure automatic calibration!"); + return 0; + } + + /* Do autocal. */ + sdmmc_autocal_run(sdmmc, bus_voltage); + + /* Enable the internal clock. */ + if (!sdmmc_int_clk_enable(sdmmc)) { + sdmmc_error(sdmmc, "Failed to enable the internal clock!"); + return 0; + } + + /* Select the desired bus width. */ + sdmmc_select_bus_width(sdmmc, bus_width); + + /* Select the desired voltage. */ + sdmmc_select_voltage(sdmmc, bus_voltage); + + /* Enable the internal clock. */ + if (!sdmmc_select_speed(sdmmc, bus_speed)) { + sdmmc_error(sdmmc, "Failed to apply the correct bus speed!"); + return 0; + } + + /* Correct any inconsistent states. */ + sdmmc_adjust_sd_clock(sdmmc); + + /* Enable the SD clock. */ + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + return 1; +} + +void sdmmc_finish(sdmmc_t *sdmmc) +{ + /* Stop everything. */ + if (sdmmc->is_clk_running) + { + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + + /* Disable SDMMC power. */ + sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE); + + /* Disable the SD card power. */ + if (sdmmc->controller == SDMMC_1) + { + /* Disable GPIO output. */ + gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_INPUT); + + /* Power cycle for 100ms without power. */ + mdelay(100); + } + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Stop the SDMMC clock. */ + sdmmc_clk_stop(sdmmc->controller); + + /* Clock is no longer running by now. */ + sdmmc->is_clk_running = false; + } +} + +static void sdmmc_do_sw_reset(sdmmc_t *sdmmc) +{ + /* Assert a software reset. */ + sdmmc->regs->software_reset |= (TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE | TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 100ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait for the register to be cleared. */ + while ((sdmmc->regs->software_reset & (TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE | TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE)) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 100000); + } +} + +static int sdmmc_wait_for_inhibit(sdmmc_t *sdmmc, bool wait_for_dat) +{ + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 10ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait on CMD inhibit to be cleared. */ + while ((sdmmc->regs->present_state & TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 10000); + } + + /* Bit was never released. Reset. */ + if (is_timeout) + { + sdmmc_do_sw_reset(sdmmc); + return 0; + } + + if (wait_for_dat) + { + /* Program a timeout of 10ms. */ + timebase = get_time(); + is_timeout = false; + + /* Wait on DAT inhibit to be cleared. */ + while ((sdmmc->regs->present_state & TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 10000); + } + + /* Bit was never released, reset. */ + if (is_timeout) + { + sdmmc_do_sw_reset(sdmmc); + return 0; + } + } + + return 1; +} + +static int sdmmc_wait_busy(sdmmc_t *sdmmc) +{ + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 10ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait on DAT0 level mask to be set. */ + while (!(sdmmc->regs->present_state & SDHCI_DATA_0_LVL_MASK) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 10000); + } + + /* Bit was never released. Reset. */ + if (is_timeout) + { + sdmmc_do_sw_reset(sdmmc); + return 0; + } + + return 1; +} + +static void sdmmc_intr_enable(sdmmc_t *sdmmc) +{ + /* Set all error bits and enable the relevant interrupts. */ + sdmmc->regs->int_enable |= 0x017F0000; + sdmmc->regs->int_enable |= (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT); + + /* Refresh status. */ + sdmmc->regs->int_status = sdmmc->regs->int_status; +} + +static void sdmmc_intr_disable(sdmmc_t *sdmmc) +{ + /* Clear all error bits and the interrupts. */ + sdmmc->regs->int_enable &= ~(0x017F0000); + sdmmc->regs->int_enable &= ~(TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT); + + /* Refresh status. */ + sdmmc->regs->int_status = sdmmc->regs->int_status; +} + +static bool sdmmc_intr_check_status(sdmmc_t *sdmmc, uint16_t status_mask) +{ + bool is_masked = (sdmmc->regs->int_status & status_mask); + + /* Mask status. */ + if (is_masked) + sdmmc->regs->int_status &= status_mask; + + return is_masked; +} + +static bool sdmmc_intr_check_error(sdmmc_t *sdmmc) +{ + bool is_error = (sdmmc->regs->int_status & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT); + + /* Refresh status. */ + if (is_error) + sdmmc->regs->int_status = sdmmc->regs->int_status; + + return is_error; +} + +static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req) +{ + /* Invalid block count or size. */ + if (!req->blksz || !req->num_blocks) + return 0; + + uint32_t blkcnt = req->num_blocks; + + /* Truncate block count. Length can't be over 65536 bytes. */ + if (blkcnt >= 0xFFFF) + blkcnt = 0xFFFF; + + /* Use our bounce buffer for SDMA or the request data buffer for ADMA. */ + uint32_t dma_base_addr = sdmmc->use_adma ? (uint32_t)req->data : (uint32_t)sdmmc->dma_bounce_buf; + + /* DMA buffer address must be aligned to 4 bytes. */ + if ((4 - (dma_base_addr & 0x03)) & 0x03) + return 0; + + /* Write our address to the registers. */ + if (sdmmc->use_adma) + { + /* Set ADMA registers. */ + sdmmc->regs->adma_address = dma_base_addr; + sdmmc->regs->upper_adma_address = 0; + } + else + { + /* Set SDMA register. */ + sdmmc->regs->dma_address = dma_base_addr; + } + + /* Store the next DMA block address for updating. */ + sdmmc->next_dma_addr = ((dma_base_addr + 0x80000) & 0xFFF80000); + + /* Set the block size ORed with the DMA boundary mask. */ + sdmmc->regs->block_size = req->blksz | 0x7000; + + /* Set the block count. */ + sdmmc->regs->block_count = blkcnt; + + /* Select basic DMA transfer mode. */ + uint32_t transfer_mode = TEGRA_MMC_TRNMOD_DMA_ENABLE; + + /* Select multi block. */ + if (req->is_multi_block) + transfer_mode |= (TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT | TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE); + + /* Select read mode. */ + if (req->is_read) + transfer_mode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ; + + /* Select AUTO_CMD12. */ + if (req->is_auto_cmd12) + { + transfer_mode &= ~(TEGRA_MMC_TRNMOD_AUTO_CMD12 & TEGRA_MMC_TRNMOD_AUTO_CMD23); + transfer_mode |= TEGRA_MMC_TRNMOD_AUTO_CMD12; + } + + /* Set the transfer mode in the register. */ + sdmmc->regs->transfer_mode = transfer_mode; + + return blkcnt; +} + +static int sdmmc_dma_update(sdmmc_t *sdmmc) +{ + uint16_t blkcnt = 0; + + /* Loop until all blocks have been consumed. */ + do + { + /* Update block count. */ + blkcnt = sdmmc->regs->block_count; + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Watch over the DMA transfer. */ + while (!is_timeout) + { + /* An error has been raised. Reset. */ + if (sdmmc_intr_check_error(sdmmc)) + { + sdmmc_do_sw_reset(sdmmc); + return 0; + } + + /* We have a DMA interrupt. Restart the transfer where it was interrupted. */ + if (sdmmc_intr_check_status(sdmmc, TEGRA_MMC_NORINTSTS_DMA_INTERRUPT)) + { + if (sdmmc->use_adma) + { + /* Update ADMA registers. */ + sdmmc->regs->adma_address = sdmmc->next_dma_addr; + sdmmc->regs->upper_adma_address = 0; + } + else + { + /* Update SDMA register. */ + sdmmc->regs->dma_address = sdmmc->next_dma_addr; + } + + sdmmc->next_dma_addr += 0x80000; + } + + /* Transfer is over. */ + if (sdmmc_intr_check_status(sdmmc, TEGRA_MMC_NORINTSTS_XFER_COMPLETE)) + return 1; + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + } + } while (sdmmc->regs->block_count < blkcnt); + + /* Should never get here. Reset. */ + sdmmc_do_sw_reset(sdmmc); + return 0; +} + +static void sdmmc_set_cmd_flags(sdmmc_t *sdmmc, sdmmc_command_t *cmd, bool is_dma) +{ + uint16_t cmd_reg_flags = 0; + + /* Select length flags based on response type. */ + if (!(cmd->flags & SDMMC_RSP_PRESENT)) + cmd_reg_flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE; + else if (cmd->flags & SDMMC_RSP_136) + cmd_reg_flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136; + else if (cmd->flags & SDMMC_RSP_BUSY) + cmd_reg_flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY; + else + cmd_reg_flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48; + + /* Select CRC flag based on response type. */ + if (cmd->flags & SDMMC_RSP_CRC) + cmd_reg_flags |= TEGRA_MMC_TRNMOD_CMD_CRC_CHECK; + + /* Select opcode flag based on response type. */ + if (cmd->flags & SDMMC_RSP_OPCODE) + cmd_reg_flags |= TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK; + + /* Select data present flag. */ + if (is_dma) + cmd_reg_flags |= TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER; + + /* Set the CMD's argument, opcode and flags. */ + sdmmc->regs->argument = cmd->arg; + sdmmc->regs->command = ((cmd->opcode << 8) | cmd_reg_flags); +} + +static int sdmmc_wait_for_cmd(sdmmc_t *sdmmc) +{ + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Set this for error checking. */ + bool is_err = false; + + /* Wait for CMD to finish. */ + while (!is_err && !is_timeout) { + /* Command is done. */ + if (sdmmc_intr_check_status(sdmmc, TEGRA_MMC_NORINTSTS_CMD_COMPLETE)) + return 1; + + /* Check for any raised errors. */ + is_err = sdmmc_intr_check_error(sdmmc); + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + } + + /* Should never get here. Reset. */ + sdmmc_do_sw_reset(sdmmc); + return 0; +} + +static int sdmmc_save_response(sdmmc_t *sdmmc, uint32_t flags) +{ + /* We have a valid response. */ + if (flags & SDMMC_RSP_PRESENT) + { + if (flags & SDMMC_RSP_136) + { + /* CRC is stripped so we need to do some shifting. */ + for (int i = 0; i < 4; i++) { + sdmmc->resp[i] = (sdmmc->regs->response[3 - i] << 0x08); + + if (i != 0) + sdmmc->resp[i - 1] |= ((sdmmc->regs->response[3 - i] >> 24) & 0xFF); + } + } + else + { + /* Card is still busy. */ + if (flags & SDMMC_RSP_BUSY) + { + /* Wait for DAT0 level mask. */ + if (!sdmmc_wait_busy(sdmmc)) + return 0; + } + + /* Save our response. */ + sdmmc->resp[0] = sdmmc->regs->response[0]; + } + + return 1; + } + + /* Invalid response. */ + return 0; +} + +int sdmmc_load_response(sdmmc_t *sdmmc, uint32_t flags, uint32_t *resp) +{ + /* Make sure our output buffer is valid. */ + if (!resp) + return 0; + + /* We have a valid response. */ + if (flags & SDMMC_RSP_PRESENT) + { + if (flags & SDMMC_RSP_136) + { + resp[0] = sdmmc->resp[0]; + resp[1] = sdmmc->resp[1]; + resp[2] = sdmmc->resp[2]; + resp[3] = sdmmc->resp[3]; + } + else + resp[0] = sdmmc->resp[0]; + + return 1; + } + + /* Invalid response. */ + return 0; +} + +int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t *num_blocks_out) +{ + uint32_t cmd_result = 0; + bool shutdown_sd_clock = false; + + /* Run automatic calibration on each command submission for SDMMC1. */ + if ((sdmmc->controller == SDMMC_1) && !(sdmmc->has_sd)) + sdmmc_autocal_run(sdmmc, sdmmc->bus_voltage); + + /* SD clock is disabled. Enable it. */ + if (!sdmmc->is_sd_clk_enabled) + { + shutdown_sd_clock = true; + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Provide 8 clock cycles after enabling the clock. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + } + + /* Determine if we should wait for data inhibit. */ + bool wait_for_dat = (req || (cmd->flags & SDMMC_RSP_BUSY)); + + /* Wait for CMD and DAT inhibit. */ + if (!sdmmc_wait_for_inhibit(sdmmc, wait_for_dat)) + return 0; + + uint32_t dma_blkcnt = 0; + bool is_dma = false; + + /* This is a data transfer. */ + if (req) + { + is_dma = true; + dma_blkcnt = sdmmc_dma_init(sdmmc, req); + + if (!dma_blkcnt) + { + sdmmc_error(sdmmc, "Failed to initialize the DMA transfer!"); + return 0; + } + + /* If this is a SDMA write operation, copy the data into our bounce buffer. */ + if (!sdmmc->use_adma && !req->is_read) + memcpy((void *)sdmmc->dma_bounce_buf, (void *)req->data, req->blksz * req->num_blocks); + } + + /* Enable interrupts. */ + sdmmc_intr_enable(sdmmc); + + /* Parse and set the CMD's flags. */ + sdmmc_set_cmd_flags(sdmmc, cmd, is_dma); + + /* Wait for the CMD to finish. */ + cmd_result = sdmmc_wait_for_cmd(sdmmc); + + sdmmc_debug(sdmmc, "CMD(%d): %08X, %08X, %08X, %08X", cmd_result, sdmmc->regs->response[0], sdmmc->regs->response[1], sdmmc->regs->response[2], sdmmc->regs->response[3]); + + if (cmd_result) + { + /* Save response, if necessary. */ + sdmmc_save_response(sdmmc, cmd->flags); + + /* Process the DMA request. */ + if (req) + { + if (!sdmmc_dma_update(sdmmc)) + { + sdmmc_error(sdmmc, "Failed to process the DMA transfer!"); + return 0; + } + + /* If this is a SDMA read operation, copy the data from our bounce buffer. */ + if (!sdmmc->use_adma && req->is_read) + { + uint32_t dma_data_size = (sdmmc->regs->dma_address - (uint32_t)sdmmc->dma_bounce_buf); + memcpy((void *)req->data, (void *)sdmmc->dma_bounce_buf, dma_data_size); + } + } + } + + /* Disable interrupts. */ + sdmmc_intr_disable(sdmmc); + + if (cmd_result) + { + if (req) + { + /* Save back the number of DMA blocks. */ + if (num_blocks_out) + *num_blocks_out = dma_blkcnt; + + /* Save the response for AUTO_CMD12. */ + if (req->is_auto_cmd12) + sdmmc->resp_auto_cmd12 = sdmmc->regs->response[3]; + } + + /* Wait for DAT0 to be 0. */ + if (req || (cmd->flags & SDMMC_RSP_BUSY)) + cmd_result = sdmmc_wait_busy(sdmmc); + } + + /* Provide 8 clock cycles before disabling the clock. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + if (shutdown_sd_clock) + sdmmc_disable_sd_clock(sdmmc); + + return cmd_result; +} + +int sdmmc_switch_voltage(sdmmc_t *sdmmc) +{ + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_SDR12)) + { + sdmmc_error(sdmmc, "Failed to apply the correct bus speed for low voltage support!"); + return 0; + } + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Reconfigure the regulator. */ + max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); + pmc->pwr_det_val &= ~(PMC_CONTROL_SDMMC1); + + /* Reconfigure autocal offsets. */ + if (!sdmmc_autocal_config(sdmmc, SDMMC_VOLTAGE_1V8)) + { + sdmmc_error(sdmmc, "Failed to configure automatic calibration for low voltage support!"); + return 0; + } + + /* Do autocal again. */ + sdmmc_autocal_run(sdmmc, SDMMC_VOLTAGE_1V8); + + /* Change the desired voltage. */ + sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_1V8); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Wait a while. */ + udelay(5000); + + /* Host control 2 flag should be set by now. */ + if (sdmmc->regs->host_control2 & SDHCI_CTRL_VDD_180) + { + /* Enable the SD clock. */ + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Wait a while. */ + udelay(1000); + + /* Data level is up. Voltage switching is done.*/ + if (sdmmc->regs->present_state & SDHCI_DATA_LVL_MASK) + return 1; + } + + return 0; +} + +static int sdmmc_send_tuning(sdmmc_t *sdmmc, uint32_t opcode) +{ + /* Nothing to do. */ + if (!sdmmc->has_sd) + return 0; + + /* Wait for CMD and DAT inhibit. */ + if (!sdmmc_wait_for_inhibit(sdmmc, true)) + return 0; + + /* Select the right size for sending the tuning block. */ + if (sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT) + sdmmc->regs->block_size = 0x40; + else if (sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) + sdmmc->regs->block_size = 0x80; + else + return 0; + + /* Select the block count and transfer mode. */ + sdmmc->regs->block_count = 1; + sdmmc->regs->transfer_mode = TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ; + + /* Manually enable the Buffer Read Ready interrupt. */ + sdmmc->regs->int_enable |= TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY; + + /* Refresh status. */ + sdmmc->regs->int_status = sdmmc->regs->int_status; + + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + + /* Prepare the tuning command. */ + sdmmc_command_t cmd = {}; + cmd.opcode = opcode; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1; + + /* Parse and set the CMD's flags. */ + sdmmc_set_cmd_flags(sdmmc, &cmd, true); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Wait a while. */ + udelay(1); + + /* Reset. */ + sdmmc_do_sw_reset(sdmmc); + + /* Enable back the SD clock. */ + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a 50ms timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait for Buffer Read Ready interrupt. */ + while (!is_timeout) + { + /* Buffer Read Ready was asserted. */ + if (sdmmc_intr_check_status(sdmmc, TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY)) + { + /* Manually disable the Buffer Read Ready interrupt. */ + sdmmc->regs->int_enable &= ~(TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Provide 8 clock cycles. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + return 1; + } + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 5000); + } + + /* Reset. */ + sdmmc_do_sw_reset(sdmmc); + + /* Manually disable the Buffer Read Ready interrupt. */ + sdmmc->regs->int_enable &= ~(TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Provide 8 clock cycles. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + return 0; +} + +void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc) +{ + sdmmc->tap_val = (sdmmc->regs->vendor_clock_cntrl >> 16); + sdmmc->is_tuning_tap_val_set = true; +} + +int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcode) +{ + uint32_t max_tuning_loop = 0; + uint32_t tuning_cntrl_flag = 0; + + sdmmc->regs->vendor_tuning_cntrl1 = 0; + + switch (bus_speed) + { + case SDMMC_SPEED_HS200: + case SDMMC_SPEED_HS400: + case SDMMC_SPEED_SDR104: + max_tuning_loop = 0x80; + tuning_cntrl_flag = 0x4000; + break; + case SDMMC_SPEED_SDR50: + case SDMMC_SPEED_DDR50: + case SDMMC_SPEED_UNK14: + max_tuning_loop = 0x100; + tuning_cntrl_flag = 0x8000; + break; + default: + return 0; + } + + sdmmc->regs->vendor_tuning_cntrl0 &= ~(0xE000); + sdmmc->regs->vendor_tuning_cntrl0 |= tuning_cntrl_flag; + + sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x1FC0); + sdmmc->regs->vendor_tuning_cntrl0 |= 0x40; + + sdmmc->regs->vendor_tuning_cntrl0 |= 0x20000; + + /* Start tuning. */ + sdmmc->regs->host_control2 |= SDHCI_CTRL_EXEC_TUNING; + + /* Repeat until Execute Tuning is set to 0 or the number of loops reaches the maximum value. */ + for (uint32_t i = 0; i < max_tuning_loop; i++) + { + sdmmc_send_tuning(sdmmc, opcode); + + /* Tuning is done. */ + if (!(sdmmc->regs->host_control2 & SDHCI_CTRL_EXEC_TUNING)) + break; + } + + /* Success! */ + if (sdmmc->regs->host_control2 & SDHCI_CTRL_TUNED_CLK) + return 1; + + return 0; +} + +int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode) +{ + uint32_t result = 0; + uint32_t cmd_result = 0; + bool shutdown_sd_clock = false; + + /* SD clock is disabled. Enable it. */ + if (!sdmmc->is_sd_clk_enabled) + { + shutdown_sd_clock = true; + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Provide 8 clock cycles after enabling the clock. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + } + + /* Wait for CMD and DAT inhibit. */ + if (sdmmc_wait_for_inhibit(sdmmc, false)) + { + /* Enable interrupts. */ + sdmmc_intr_enable(sdmmc); + + /* Prepare the command. */ + sdmmc_command_t cmd = {}; + cmd.opcode = opcode; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1B; + + /* Parse and set the CMD's flags. */ + sdmmc_set_cmd_flags(sdmmc, &cmd, false); + + /* Wait for the CMD to finish. */ + cmd_result = sdmmc_wait_for_cmd(sdmmc); + + /* Disable interrupts. */ + sdmmc_intr_disable(sdmmc); + + if (cmd_result) + { + /* Save response, if necessary. */ + sdmmc_save_response(sdmmc, cmd.flags); + + /* Wait for DAT0 to be 0. */ + result = sdmmc_wait_busy(sdmmc); + } + } + + /* Provide 8 clock cycles before disabling the clock. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + /* Disable the SD clock if requested. */ + if (shutdown_sd_clock) + sdmmc_disable_sd_clock(sdmmc); + + return result; +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h new file mode 100644 index 000000000..37dd207d1 --- /dev/null +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h @@ -0,0 +1,298 @@ +#ifndef FUSEE_SDMMC_CORE_H +#define FUSEE_SDMMC_CORE_H + +#include "sdmmc_tegra.h" + +/* Bounce buffer */ +#define SDMMC_BOUNCE_BUFFER_ADDRESS 0x90000000 + +/* Present state */ +#define SDHCI_CMD_INHIBIT 0x00000001 +#define SDHCI_DATA_INHIBIT 0x00000002 +#define SDHCI_DOING_WRITE 0x00000100 +#define SDHCI_DOING_READ 0x00000200 +#define SDHCI_SPACE_AVAILABLE 0x00000400 +#define SDHCI_DATA_AVAILABLE 0x00000800 +#define SDHCI_CARD_PRESENT 0x00010000 +#define SDHCI_WRITE_PROTECT 0x00080000 +#define SDHCI_DATA_LVL_MASK 0x00F00000 +#define SDHCI_DATA_LVL_SHIFT 20 +#define SDHCI_DATA_0_LVL_MASK 0x00100000 +#define SDHCI_CMD_LVL 0x01000000 + +/* SDHCI clock control */ +#define SDHCI_DIVIDER_SHIFT 8 +#define SDHCI_DIVIDER_HI_SHIFT 6 +#define SDHCI_DIV_MASK 0xFF +#define SDHCI_DIV_MASK_LEN 8 +#define SDHCI_DIV_HI_MASK 0x300 +#define SDHCI_PROG_CLOCK_MODE 0x0020 +#define SDHCI_CLOCK_CARD_EN 0x0004 +#define SDHCI_CLOCK_INT_STABLE 0x0002 +#define SDHCI_CLOCK_INT_EN 0x0001 + +/* SDHCI host control */ +#define SDHCI_CTRL_LED 0x01 +#define SDHCI_CTRL_4BITBUS 0x02 +#define SDHCI_CTRL_HISPD 0x04 +#define SDHCI_CTRL_DMA_MASK 0x18 +#define SDHCI_CTRL_SDMA 0x00 +#define SDHCI_CTRL_ADMA1 0x08 +#define SDHCI_CTRL_ADMA32 0x10 +#define SDHCI_CTRL_ADMA64 0x18 +#define SDHCI_CTRL_8BITBUS 0x20 +#define SDHCI_CTRL_CDTEST_INS 0x40 +#define SDHCI_CTRL_CDTEST_EN 0x80 + +/* SDHCI host control 2 */ +#define SDHCI_CTRL_UHS_MASK 0x0007 +#define SDHCI_CTRL_UHS_SDR12 0x0000 +#define SDHCI_CTRL_UHS_SDR25 0x0001 +#define SDHCI_CTRL_UHS_SDR50 0x0002 +#define SDHCI_CTRL_UHS_SDR104 0x0003 +#define SDHCI_CTRL_UHS_DDR50 0x0004 +#define SDHCI_CTRL_HS400 0x0005 +#define SDHCI_CTRL_VDD_180 0x0008 +#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 +#define SDHCI_CTRL_DRV_TYPE_B 0x0000 +#define SDHCI_CTRL_DRV_TYPE_A 0x0010 +#define SDHCI_CTRL_DRV_TYPE_C 0x0020 +#define SDHCI_CTRL_DRV_TYPE_D 0x0030 +#define SDHCI_CTRL_EXEC_TUNING 0x0040 +#define SDHCI_CTRL_TUNED_CLK 0x0080 +#define SDHCI_UHS2_IF_EN 0x0100 +#define SDHCI_HOST_VERSION_4_EN 0x1000 +#define SDHCI_ADDRESSING_64BIT_EN 0x2000 +#define SDHCI_ASYNC_INTR_EN 0x4000 +#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 + +/* SDHCI capabilities */ +#define SDHCI_CAN_DO_8BIT 0x00040000 +#define SDHCI_CAN_DO_ADMA2 0x00080000 +#define SDHCI_CAN_DO_ADMA1 0x00100000 +#define SDHCI_CAN_DO_HISPD 0x00200000 +#define SDHCI_CAN_DO_SDMA 0x00400000 +#define SDHCI_CAN_VDD_330 0x01000000 +#define SDHCI_CAN_VDD_300 0x02000000 +#define SDHCI_CAN_VDD_180 0x04000000 +#define SDHCI_CAN_64BIT 0x10000000 +#define SDHCI_ASYNC_INTR 0x20000000 + +/* Vendor clock control */ +#define SDMMC_CLOCK_TAP_MASK (0xFF << 16) +#define SDMMC_CLOCK_TAP_SDMMC1 (0x04 << 16) +#define SDMMC_CLOCK_TAP_SDMMC2 (0x00 << 16) +#define SDMMC_CLOCK_TAP_SDMMC3 (0x03 << 16) +#define SDMMC_CLOCK_TAP_SDMMC4 (0x00 << 16) +#define SDMMC_CLOCK_TRIM_MASK (0xFF << 24) +#define SDMMC_CLOCK_TRIM_SDMMC1 (0x02 << 24) +#define SDMMC_CLOCK_TRIM_SDMMC2 (0x08 << 24) +#define SDMMC_CLOCK_TRIM_SDMMC3 (0x03 << 24) +#define SDMMC_CLOCK_TRIM_SDMMC4 (0x08 << 24) +#define SDMMC_CLOCK_PADPIPE_CLKEN_OVERRIDE (1 << 3) + +/* Autocal configuration */ +#define SDMMC_AUTOCAL_PDPU_CONFIG_MASK 0x7F7F +#define SDMMC_AUTOCAL_PDPU_SDMMC1_1V8 0x7B7B +#define SDMMC_AUTOCAL_PDPU_SDMMC1_3V3 0x7D00 +#define SDMMC_AUTOCAL_PDPU_SDMMC4_1V8 0x0505 +#define SDMMC_AUTOCAL_START (1 << 31) +#define SDMMC_AUTOCAL_ENABLE (1 << 29) + +/* Autocal status */ +#define SDMMC_AUTOCAL_ACTIVE (1 << 31) + +/* Vendor tuning control 0*/ +#define SDMMC_VENDOR_TUNING_TRIES_MASK (0x7 << 13) +#define SDMMC_VENDOR_TUNING_TRIES_SHIFT 13 +#define SDMMC_VENDOR_TUNING_MULTIPLIER_MASK (0x7F << 6) +#define SDMMC_VENDOR_TUNING_MULTIPLIER_UNITY (1 << 6) +#define SDMMC_VENDOR_TUNING_DIVIDER_MASK (0x7 << 3) +#define SDMMC_VENDOR_TUNING_SET_BY_HW (1 << 17) + +/* Vendor tuning control 1*/ +#define SDMMC_VENDOR_TUNING_STEP_SIZE_SDR50_DEFAULT (0 << 0) +#define SDMMC_VENDOR_TUNING_STEP_SIZE_SDR104_DEFAULT (0 << 4) + +/* Vendor capability overrides */ +#define SDMMC_VENDOR_CAPABILITY_DQS_TRIM_MASK (0x3F << 8) +#define SDMMC_VENDOR_CAPABILITY_DQS_TRIM_HS400 (0x11 << 8) + +/* Timeouts */ +#define SDMMC_AUTOCAL_TIMEOUT (10 * 1000) +#define SDMMC_TUNING_TIMEOUT (150 * 1000) + +/* Command response flags */ +#define SDMMC_RSP_PRESENT (1 << 0) +#define SDMMC_RSP_136 (1 << 1) +#define SDMMC_RSP_CRC (1 << 2) +#define SDMMC_RSP_BUSY (1 << 3) +#define SDMMC_RSP_OPCODE (1 << 4) + +/* Command types */ +#define SDMMC_CMD_MASK (3 << 5) +#define SDMMC_CMD_AC (0 << 5) +#define SDMMC_CMD_ADTC (1 << 5) +#define SDMMC_CMD_BC (2 << 5) +#define SDMMC_CMD_BCR (3 << 5) + +/* SPI command response flags */ +#define SDMMC_RSP_SPI_S1 (1 << 7) +#define SDMMC_RSP_SPI_S2 (1 << 8) +#define SDMMC_RSP_SPI_B4 (1 << 9) +#define SDMMC_RSP_SPI_BUSY (1 << 10) + +/* Native response types for commands */ +#define SDMMC_RSP_NONE (0) +#define SDMMC_RSP_R1 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE) +#define SDMMC_RSP_R1B (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE|SDMMC_RSP_BUSY) +#define SDMMC_RSP_R2 (SDMMC_RSP_PRESENT|SDMMC_RSP_136|SDMMC_RSP_CRC) +#define SDMMC_RSP_R3 (SDMMC_RSP_PRESENT) +#define SDMMC_RSP_R4 (SDMMC_RSP_PRESENT) +#define SDMMC_RSP_R5 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE) +#define SDMMC_RSP_R6 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE) +#define SDMMC_RSP_R7 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE) +#define SDMMC_RSP_R1_NO_CRC (SDMMC_RSP_PRESENT|SDMMC_RSP_OPCODE) + +/* SPI response types for commands */ +#define SDMMC_RSP_SPI_R1 (SDMMC_RSP_SPI_S1) +#define SDMMC_RSP_SPI_R1B (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_BUSY) +#define SDMMC_RSP_SPI_R2 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2) +#define SDMMC_RSP_SPI_R3 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4) +#define SDMMC_RSP_SPI_R4 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4) +#define SDMMC_RSP_SPI_R5 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2) +#define SDMMC_RSP_SPI_R7 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4) + +/* Internal logging */ +typedef enum { + SDMMC_LOG_NONE = 0, + SDMMC_LOG_ERROR = 1, + SDMMC_LOG_WARN = 2, + SDMMC_LOG_INFO = 3, + SDMMC_LOG_DEBUG = 4 +} SdmmcLogLevel; + +/* SDMMC controllers */ +typedef enum { + SDMMC_1 = 0, + SDMMC_2 = 1, + SDMMC_3 = 2, + SDMMC_4 = 3 +} SdmmcControllerNum; + +typedef enum { + SDMMC_PARTITION_INVALID = -1, + SDMMC_PARTITION_USER = 0, + SDMMC_PARTITION_BOOT0 = 1, + SDMMC_PARTITION_BOOT1 = 2, + SDMMC_PARTITION_RPMB = 3 +} SdmmcPartitionNum; + +typedef enum { + SDMMC_VOLTAGE_NONE = 0, + SDMMC_VOLTAGE_1V8 = 1, + SDMMC_VOLTAGE_3V3 = 2 +} SdmmcBusVoltage; + +typedef enum { + SDMMC_BUS_WIDTH_1BIT = 0, + SDMMC_BUS_WIDTH_4BIT = 1, + SDMMC_BUS_WIDTH_8BIT = 2 +} SdmmcBusWidth; + +typedef enum { + SDMMC_SPEED_INIT_HS = 0, + SDMMC_SPEED_HS26 = 1, + SDMMC_SPEED_HS52 = 2, + SDMMC_SPEED_HS200 = 3, + SDMMC_SPEED_HS400 = 4, + SDMMC_SPEED_INIT_SDR = 5, + SDMMC_SPEED_UNK6 = 6, + SDMMC_SPEED_SDR25 = 7, + SDMMC_SPEED_SDR12 = 8, + SDMMC_SPEED_UNK9 = 9, + SDMMC_SPEED_SDR50 = 10, + SDMMC_SPEED_SDR104 = 11, + SDMMC_SPEED_UNK12 = 12, + SDMMC_SPEED_DDR50 = 13, + SDMMC_SPEED_UNK14 = 14, +} SdmmcBusSpeed; + +typedef enum { + SDMMC_CAR_DIVIDER_SDR12 = 31, // (16.5 * 2) - 2 + SDMMC_CAR_DIVIDER_SDR25 = 15, // (8.5 * 2) - 2 + SDMMC_CAR_DIVIDER_SDR50 = 7, // (4.5 * 2) - 2 + SDMMC_CAR_DIVIDER_SDR104 = 2, // (2 * 2) - 2 + SDMMC_CAR_DIVIDER_DDR50 = 18, // (5 * 2 * 2) - 2 + SDMMC_CAR_DIVIDER_HS26 = 30, // (16 * 2) - 2 + SDMMC_CAR_DIVIDER_HS52 = 14, // (8 * 2) - 2 + SDMMC_CAR_DIVIDER_HS200 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0) + SDMMC_CAR_DIVIDER_HS400 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0) +} SdmmcCarDivider; + +/* Structure for describing a SDMMC device. */ +typedef struct { + /* Controller number */ + SdmmcControllerNum controller; + + /* Backing register space */ + volatile tegra_sdmmc_t *regs; + + /* Controller properties */ + const char *name; + bool has_sd; + bool is_clk_running; + bool is_sd_clk_enabled; + bool is_tuning_tap_val_set; + bool use_adma; + uint32_t tap_val; + uint32_t internal_divider; + uint32_t resp[4]; + uint32_t resp_auto_cmd12; + uint32_t next_dma_addr; + uint8_t* dma_bounce_buf; + SdmmcBusVoltage bus_voltage; + SdmmcBusWidth bus_width; + + /* Per-controller operations. */ + int (*sdmmc_config)(); +} sdmmc_t; + +/* Structure for describing a SDMMC command. */ +typedef struct { + uint32_t opcode; + uint32_t arg; + uint32_t resp[4]; + uint32_t flags; /* expected response type */ +} sdmmc_command_t; + +/* Structure for describing a SDMMC request. */ +typedef struct { + void* data; + uint32_t blksz; + uint32_t num_blocks; + bool is_multi_block; + bool is_read; + bool is_auto_cmd12; +} sdmmc_request_t; + +int sdmmc_init(sdmmc_t *sdmmc, SdmmcControllerNum controller, SdmmcBusVoltage bus_voltage, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed); +void sdmmc_finish(sdmmc_t *sdmmc); +int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed); +void sdmmc_select_bus_width(sdmmc_t *sdmmc, SdmmcBusWidth width); +void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage); +void sdmmc_adjust_sd_clock(sdmmc_t *sdmmc); +int sdmmc_switch_voltage(sdmmc_t *sdmmc); +void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc); +int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcode); +int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t *num_blocks_out); +int sdmmc_load_response(sdmmc_t *sdmmc, uint32_t flags, uint32_t *resp); +int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode); +void sdmmc_set_log_level(SdmmcLogLevel log_level); +void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...); +void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...); +void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...); +void sdmmc_debug(sdmmc_t *sdmmc, char *fmt, ...); +void sdmmc_dump_regs(sdmmc_t *sdmmc); + +#endif diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h b/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h new file mode 100644 index 000000000..7a6c141f7 --- /dev/null +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h @@ -0,0 +1,154 @@ +#ifndef FUSEE_SDMMC_TEGRA_H +#define FUSEE_SDMMC_TEGRA_H + +#include +#include + +#define TEGRA_MMC_PWRCTL_SD_BUS_POWER (1 << 0) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 (5 << 1) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 (6 << 1) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 (7 << 1) + +#define TEGRA_MMC_HOSTCTL_DMASEL_MASK (3 << 3) +#define TEGRA_MMC_HOSTCTL_DMASEL_SDMA (0 << 3) +#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_32BIT (2 << 3) +#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_64BIT (3 << 3) + +#define TEGRA_MMC_TRNMOD_DMA_ENABLE (1 << 0) +#define TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE (1 << 1) +#define TEGRA_MMC_TRNMOD_AUTO_CMD12 (1 << 2) +#define TEGRA_MMC_TRNMOD_AUTO_CMD23 (1 << 3) +#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_WRITE (0 << 4) +#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ (1 << 4) +#define TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT (1 << 5) + +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_MASK (3 << 0) +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE (0 << 0) +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136 (1 << 0) +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48 (2 << 0) +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY (3 << 0) + +#define TEGRA_MMC_TRNMOD_CMD_CRC_CHECK (1 << 3) +#define TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK (1 << 4) +#define TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER (1 << 5) + +#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD (1 << 0) +#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT (1 << 1) + +#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE (1 << 0) +#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE (1 << 1) +#define TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE (1 << 2) +#define TEGRA_MMC_CLKCON_PROG_CLOCK_MODE (1 << 5) + +#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_SHIFT 8 +#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_MASK (0xff << 8) + +#define TEGRA_MMC_SWRST_SW_RESET_FOR_ALL (1 << 0) +#define TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE (1 << 1) +#define TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE (1 << 2) + +#define TEGRA_MMC_NORINTSTS_CMD_COMPLETE (1 << 0) +#define TEGRA_MMC_NORINTSTS_XFER_COMPLETE (1 << 1) +#define TEGRA_MMC_NORINTSTS_DMA_INTERRUPT (1 << 3) +#define TEGRA_MMC_NORINTSTS_ERR_INTERRUPT (1 << 15) +#define TEGRA_MMC_NORINTSTS_CMD_TIMEOUT (1 << 16) + +#define TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE (1 << 0) +#define TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE (1 << 1) +#define TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT (1 << 3) +#define TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY (1 << 4) +#define TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY (1 << 5) + +#define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE (1 << 1) + +typedef struct { + /* SDHCI standard registers */ + uint32_t dma_address; + uint16_t block_size; + uint16_t block_count; + uint32_t argument; + uint16_t transfer_mode; + uint16_t command; + uint32_t response[0x4]; + uint32_t buffer; + uint32_t present_state; + uint8_t host_control; + uint8_t power_control; + uint8_t block_gap_control; + uint8_t wake_up_control; + uint16_t clock_control; + uint8_t timeout_control; + uint8_t software_reset; + uint32_t int_status; + uint32_t int_enable; + uint32_t signal_enable; + uint16_t acmd12_err; + uint16_t host_control2; + uint32_t capabilities; + uint32_t capabilities_1; + uint32_t max_current; + uint32_t _0x4c; + uint16_t set_acmd12_error; + uint16_t set_int_error; + uint8_t adma_error; + uint8_t _0x56[0x3]; + uint32_t adma_address; + uint32_t upper_adma_address; + uint16_t preset_for_init; + uint16_t preset_for_default; + uint16_t preset_for_high; + uint16_t preset_for_sdr12; + uint16_t preset_for_sdr25; + uint16_t preset_for_sdr50; + uint16_t preset_for_sdr104; + uint16_t preset_for_ddr50; + uint32_t _0x70[0x23]; + uint16_t slot_int_status; + uint16_t host_version; + + /* vendor specific registers */ + uint32_t vendor_clock_cntrl; + uint32_t vendor_sys_sw_cntrl; + uint32_t vendor_err_intr_status; + uint32_t vendor_cap_overrides; + uint32_t vendor_boot_cntrl; + uint32_t vendor_boot_ack_timeout; + uint32_t vendor_boot_dat_timeout; + uint32_t vendor_debounce_count; + uint32_t vendor_misc_cntrl; + uint32_t max_current_override; + uint32_t max_current_override_hi; + uint32_t _0x12c[0x20]; + uint32_t vendor_io_trim_cntrl; + + /* start of sdmmc2/sdmmc4 only */ + uint32_t vendor_dllcal_cfg; + uint32_t vendor_dll_ctrl0; + uint32_t vendor_dll_ctrl1; + uint32_t vendor_dllcal_cfg_sta; + /* end of sdmmc2/sdmmc4 only */ + + uint32_t vendor_tuning_cntrl0; + uint32_t vendor_tuning_cntrl1; + uint32_t vendor_tuning_status0; + uint32_t vendor_tuning_status1; + uint32_t vendor_clk_gate_hysteresis_count; + uint32_t vendor_preset_val0; + uint32_t vendor_preset_val1; + uint32_t vendor_preset_val2; + uint32_t sdmemcomppadctrl; + uint32_t auto_cal_config; + uint32_t auto_cal_interval; + uint32_t auto_cal_status; + uint32_t io_spare; + uint32_t sdmmca_mccif_fifoctrl; + uint32_t timeout_wcoal_sdmmca; + uint32_t _0x1fc; +} tegra_sdmmc_t; + +static inline volatile tegra_sdmmc_t *sdmmc_get_regs(uint32_t idx) +{ + return (volatile tegra_sdmmc_t *)(0x700B0000 + (idx * 0x200)); +} + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/se.c b/fusee/fusee-secondary/src/se.c index bf3a7cc92..18e16bd99 100644 --- a/fusee/fusee-secondary/src/se.c +++ b/fusee/fusee-secondary/src/se.c @@ -438,7 +438,7 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys SECURITY_ENGINE->CRYPTO_REG = keyslot_1 << 24; } SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1; - trigger_se_blocking_op(OP_START, dst, size, dst, size); + trigger_se_blocking_op(OP_START, dst, size, src, size); /* XOR. */ aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size); diff --git a/fusee/fusee-secondary/src/se.h b/fusee/fusee-secondary/src/se.h index ad96a8020..a1ef7fa84 100644 --- a/fusee/fusee-secondary/src/se.h +++ b/fusee/fusee-secondary/src/se.h @@ -1,7 +1,6 @@ #ifndef FUSEE_SE_H #define FUSEE_SE_H -#include "utils.h" #include #define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2 @@ -206,4 +205,4 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v void se_initialize_rng(unsigned int keyslot); void se_generate_random(unsigned int keyslot, void *dst, size_t size); -#endif /* EXOSPHERE_SE_H */ +#endif diff --git a/fusee/fusee-secondary/src/stage2.h b/fusee/fusee-secondary/src/stage2.h index 1314e87df..020cf2c50 100644 --- a/fusee/fusee-secondary/src/stage2.h +++ b/fusee/fusee-secondary/src/stage2.h @@ -2,7 +2,7 @@ #define FUSEE_STAGE2_H #include "utils.h" -#include "sdmmc.h" +#include "sdmmc/sdmmc.h" /* TODO: Is there a more concise way to do this? */ #define STAGE2_ARGV_PROGRAM_PATH 0 @@ -13,7 +13,6 @@ typedef struct { uint32_t version; - //struct mmc sd_mmc; bool display_initialized; char bct0[BCTO_MAX_SIZE]; } stage2_args_t; diff --git a/fusee/fusee-secondary/src/supplies.c b/fusee/fusee-secondary/src/supplies.c deleted file mode 100644 index 37ccfe95e..000000000 --- a/fusee/fusee-secondary/src/supplies.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Fusée power supply control code - * ~ktemkin - */ - -#include "lib/driver_utils.h" -#include "supplies.h" - -// FIXME: replace hwinit with our own code -#include "hwinit/max7762x.h" - -/** - * Enables a given power supply. - * - * @param supply The power domain on the Switch that is to be enabled. - * @param use_low_voltage If the supply supports multiple voltages, use the lower one. - * Some devices start in a high power mode, but an can be switched to a lower one. - * Set this to false unless you know what you're doing. - */ -void supply_enable(enum switch_power_supply supply, bool use_low_voltage) -{ - uint32_t voltage = 0; - - switch(supply) { - case SUPPLY_MICROSD: - voltage = use_low_voltage ? SUPPLY_MICROSD_LOW_VOLTAGE : SUPPLY_MICROSD_VOLTAGE; - - max77620_regulator_set_voltage(SUPPLY_MICROSD_REGULATOR, voltage); - max77620_regulator_enable(SUPPLY_MICROSD_REGULATOR, true); - return; - - default: - printk("ERROR: could not enable unknown supply %d!\n", supply); - return; - } -} - diff --git a/fusee/fusee-secondary/src/supplies.h b/fusee/fusee-secondary/src/supplies.h deleted file mode 100644 index f328a67eb..000000000 --- a/fusee/fusee-secondary/src/supplies.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Fusée power supply control code - * ~ktemkin - */ - -#ifndef __FUSEE_SUPPLIES_H__ -#define __FUSEE_SUPPLIES_H__ - -#include "utils.h" - -enum switch_power_supply { - SUPPLY_MICROSD, -}; - - -enum switch_power_constants { - - /* MicroSD card */ - SUPPLY_MICROSD_REGULATOR = 6, - SUPPLY_MICROSD_VOLTAGE = 3300000, - SUPPLY_MICROSD_LOW_VOLTAGE = 1800000, - -}; - - -/** - * Enables a given power supply. - * - * @param supply The power domain on the Switch that is to be enabled. - * @param use_low_voltage If the supply supports multiple voltages, use the lower one. - * Some devices start in a high power mode, but an can be switched to a lower one. - * Set this to false unless you know what you're doing. - */ -void supply_enable(enum switch_power_supply supply, bool use_low_voltage); - -#endif diff --git a/fusee/fusee-secondary/src/switch_fs.h b/fusee/fusee-secondary/src/switch_fs.h deleted file mode 100644 index 0cc256797..000000000 --- a/fusee/fusee-secondary/src/switch_fs.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef FUSEE_SWITCH_FS_H -#define FUSEE_SWITCH_FS_H - -#include "fs_dev.h" -#include "raw_dev.h" - -int switchfs_import_mmc_structs(void *sd, void *nand); - -int switchfs_mount_all(void); -int switchfs_unmount_all(void); - -#endif diff --git a/fusee/fusee-secondary/src/timers.h b/fusee/fusee-secondary/src/timers.h index 3c314e449..519c0292f 100644 --- a/fusee/fusee-secondary/src/timers.h +++ b/fusee/fusee-secondary/src/timers.h @@ -4,11 +4,14 @@ #include "utils.h" #define TIMERS_BASE 0x60005000 - #define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) - #define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10) +#define RTC_BASE 0x7000E000 +#define RTC_SECONDS MAKE_REG32(RTC_BASE + 0x08) +#define RTC_SHADOW_SECONDS MAKE_REG32(RTC_BASE + 0x0C) +#define RTC_MILLI_SECONDS MAKE_REG32(RTC_BASE + 0x10) + typedef struct { uint32_t CONFIG; uint32_t STATUS; @@ -22,24 +25,46 @@ typedef struct { void wait(uint32_t microseconds); -static inline uint32_t get_time(void) { +static inline uint32_t get_time_s(void) { + return RTC_SECONDS; +} + +static inline uint32_t get_time_ms(void) { + return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10)); +} + +static inline uint32_t get_time_us(void) { return TIMERUS_CNTR_1US_0; } +/** + * Returns the time in microseconds. + */ +static inline uint32_t get_time(void) { + return get_time_us(); +} + /** * Returns the number of microseconds that have passed since a given get_time(). */ static inline uint32_t get_time_since(uint32_t base) { - return get_time() - base; + return get_time_us() - base; } /** * Delays for a given number of microseconds. */ -static inline void udelay(unsigned usecs) -{ - uint32_t start = get_time(); - while (get_time() - start < usecs) ; +static inline void udelay(uint32_t usecs) { + uint32_t start = get_time_us(); + while (get_time_us() - start < usecs); +} + +/** + * Delays for a given number of milliseconds. + */ +static inline void mdelay(uint32_t msecs) { + uint32_t start = get_time_ms(); + while (get_time_ms() - start < msecs); } __attribute__ ((noreturn)) void watchdog_reboot(void); From a46e796f4d464fdea35830900c26b8d6b7ba299a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 19 Jul 2018 21:17:57 -0600 Subject: [PATCH 002/489] fs.mitm: Fix UAF in every DirEntry processed. How on earth did this code ever work? --- stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index fbfa350d5..2e87a051a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -236,7 +236,7 @@ void RomFSBuildContext::Build(std::vector *out_infos) { RomFSDirectoryEntry *dir_table = (RomFSDirectoryEntry *)((uintptr_t)dir_hash_table + this->dir_hash_table_size); u32 *file_hash_table = (u32 *)((uintptr_t)dir_table + this->dir_table_size); RomFSFileEntry *file_table = (RomFSFileEntry *)((uintptr_t)file_hash_table + this->file_hash_table_size); - + /* Clear out hash tables. */ for (u32 i = 0; i < dir_hash_table_entry_count; i++) { dir_hash_table[i] = ROMFS_ENTRY_EMPTY; @@ -332,11 +332,7 @@ void RomFSBuildContext::Build(std::vector *out_infos) { default: fatalSimple(0xF601); } - - delete cur_file->path; - delete cur_file; } - this->files.clear(); /* Populate dir tables. */ for (const auto &it : this->directories) { @@ -362,6 +358,14 @@ void RomFSBuildContext::Build(std::vector *out_infos) { this->root = NULL; this->directories.clear(); + /* Delete files. */ + for (const auto &it : this->files) { + cur_file = it.second; + delete cur_file->path; + delete cur_file; + } + this->files.clear(); + /* Set header fields. */ header->header_size = sizeof(*header); header->file_hash_table_size = this->file_hash_table_size; From eaa282b9153610949bcfde12eaaa27445d6f5fe2 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 19 Jul 2018 21:21:50 -0600 Subject: [PATCH 003/489] Fix additional UAF in DirEntry building --- stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index 2e87a051a..be9c63620 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -352,6 +352,11 @@ void RomFSBuildContext::Build(std::vector *out_infos) { memset(cur_entry->name, 0, (cur_entry->name_size + 3) & ~3); memcpy(cur_entry->name, cur_dir->path + cur_dir->cur_path_ofs, name_size); + } + + /* Delete directories. */ + for (const auto &it : this->directories) { + cur_dir = it.second; delete cur_dir->path; delete cur_dir; } From e58927a8ab26c2f8958ec2ea73d4216631a37af2 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Mon, 23 Jul 2018 20:14:53 +0100 Subject: [PATCH 004/489] fusee: Fix SDMMC high speed support and other bugs. --- fusee/fusee-primary/src/sdmmc/sdmmc.c | 21 ++++--- fusee/fusee-primary/src/sdmmc/sdmmc_core.c | 62 +++++++++---------- fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h | 6 +- fusee/fusee-secondary/src/sdmmc/sdmmc.c | 24 ++++--- fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 62 +++++++++---------- fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h | 6 +- 6 files changed, 84 insertions(+), 97 deletions(-) diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc.c b/fusee/fusee-primary/src/sdmmc/sdmmc.c index 1c17988ca..0927295f3 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc.c @@ -487,12 +487,12 @@ static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool i return 0; /* Delay a bit before asking for the voltage switch. */ - udelay(1000); + mdelay(100); /* Tell the driver to switch the voltage. */ if (!sdmmc_switch_voltage(device->sdmmc)) return 0; - + /* We are now running at 1.8V. */ device->is_180v = true; } @@ -693,15 +693,15 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status) /* Adjust the current limit. */ if (!sdmmc_sd_set_current_limit(device, status)) return 0; - + /* Invalid bus width. */ if (device->sdmmc->bus_width != SDMMC_BUS_WIDTH_4BIT) return 0; - + /* Get the supported high-speed type. */ if (!sdmmc_sd_switch(device, 0, 0, 0xF, status)) return 0; - + /* High-speed SDR104 is supported. */ if (status[13] & SD_MODE_UHS_SDR104) { @@ -748,6 +748,7 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status) else return 0; + /* Peek the SD card's status. */ return sdmmc_device_send_status(device); } @@ -974,22 +975,22 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b /* Switch to high-speed from low voltage (if possible). */ if (!sdmmc_sd_switch_hs_low(device, switch_status)) { - sdmmc_error(sdmmc, "Failed to switch to high-speed!"); + sdmmc_error(sdmmc, "Failed to switch to high-speed from low voltage!"); return 0; } - sdmmc_info(sdmmc, "Switched to high-speed!"); + sdmmc_info(sdmmc, "Switched to high-speed from low voltage!"); } else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_UNK6))) { /* Switch to high-speed from high voltage (if possible). */ if (!sdmmc_sd_switch_hs_high(device, switch_status)) { - sdmmc_error(sdmmc, "Failed to switch to high-speed!"); + sdmmc_error(sdmmc, "Failed to switch to high-speed from high voltage!"); return 0; } - sdmmc_info(sdmmc, "Switched to high-speed!"); + sdmmc_info(sdmmc, "Switched to high-speed from high voltage!"); } /* Correct any inconsistent states. */ @@ -1373,7 +1374,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth { uint32_t cid[4] = {0}; uint32_t csd[4] = {0}; - uint8_t *ext_csd = (uint8_t *)SDMMC_BOUNCE_BUFFER_ADDRESS; // TODO: Better way to do this. + uint8_t ext_csd[512] = {0}; /* Initialize our device's struct. */ memset(device, 0, sizeof(sdmmc_device_t)); diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c index 5b96970c9..b99db835d 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c @@ -549,28 +549,26 @@ static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) case SDMMC_3: switch (voltage) { case SDMMC_VOLTAGE_1V8: - sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_1V8; break; case SDMMC_VOLTAGE_3V3: - sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_3V3; break; default: - sdmmc_error(sdmmc, "microsd does not support voltage %d", voltage); + sdmmc_error(sdmmc, "uSD does not support requested voltage!"); return 0; } break; - case SDMMC_2: case SDMMC_4: if (voltage != SDMMC_VOLTAGE_1V8) { - sdmmc_error(sdmmc, "eMMC can only run at 1V8, but sdmmc struct claims voltage %d", voltage); + sdmmc_error(sdmmc, "eMMC can only run at 1V8!"); return 0; } - - sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC4_1V8; break; } @@ -581,8 +579,8 @@ static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) /* Run automatic calibration. */ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) { - bool restart_sd_clock = false; volatile tegra_padctl_t *padctl = padctl_get_regs(); + bool restart_sd_clock = false; /* SD clock is enabled. Disable it and restart later. */ if (sdmmc->is_sd_clk_enabled) @@ -619,7 +617,7 @@ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) while ((sdmmc->regs->auto_cal_status & SDMMC_AUTOCAL_ACTIVE)) { /* Ensure we haven't timed out. */ if (get_time_since(timebase) > SDMMC_AUTOCAL_TIMEOUT) { - sdmmc_error(sdmmc, "autocal timed out!"); + sdmmc_error(sdmmc, "Auto-calibration timed out!"); /* Force a register read to refresh the clock control value. */ sdmmc_get_sd_clock_control(sdmmc); @@ -642,7 +640,7 @@ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) } /* Manually clear the autocal enable bit. */ - sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_ENABLE; + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_ENABLE); break; } } @@ -696,16 +694,9 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc) /* Use SDMA by default. */ sdmmc->regs->host_control &= ~SDHCI_CTRL_DMA_MASK; - /* Change to ADMA if requested. */ - if (sdmmc->use_adma && (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)) { - // TODO: Setting the ADMA flags breaks ADMA... - /* - if (sdmmc->regs->capabilities & SDHCI_CAN_64BIT) - sdmmc->regs->host_control |= SDHCI_CTRL_ADMA64; - else - sdmmc->regs->host_control |= SDHCI_CTRL_ADMA32; - */ - } + /* Change to ADMA if possible. */ + if (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2) + sdmmc->use_adma = true; /* Set the timeout to be the maximum value. */ sdmmc->regs->timeout_control &= 0xF0; @@ -847,9 +838,9 @@ static int sdmmc_dllcal_run(sdmmc_t *sdmmc) is_timeout = (get_time_since(timebase) > 10000); } - /* Clock failed to stabilize. */ + /* Calibration failed. */ if (is_timeout) { - sdmmc_error(sdmmc, "ERROR: DLLCAL failed!"); + sdmmc_error(sdmmc, "DLLCAL failed!"); return 0; } @@ -898,20 +889,23 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed) case SDMMC_SPEED_DDR50: case SDMMC_SPEED_SDR50: case SDMMC_SPEED_UNK14: - sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; - sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180); + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; break; /* 200MHz single-data rate (MMC). */ case SDMMC_SPEED_HS400: - sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; - sdmmc->regs->host_control2 |= (SDHCI_CTRL_HS400 | SDHCI_CTRL_VDD_180); + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; break; /* 25MHz default speed (SD). */ case SDMMC_SPEED_SDR12: - sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; - sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180); + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; break; default: @@ -1093,7 +1087,7 @@ static int sdmmc_init_controller(sdmmc_t *sdmmc, SdmmcControllerNum controller) sdmmc->is_clk_running = false; sdmmc->is_sd_clk_enabled = false; sdmmc->is_tuning_tap_val_set = false; - sdmmc->use_adma = true; + sdmmc->use_adma = false; sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; sdmmc->tap_val = 0; sdmmc->internal_divider = 0; @@ -1206,11 +1200,11 @@ void sdmmc_finish(sdmmc_t *sdmmc) sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE); /* Disable the SD card power. */ - if (sdmmc->controller == SDMMC_1) - { + if (sdmmc->controller == SDMMC_1) + { /* Disable GPIO output. */ gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_INPUT); - + /* Power cycle for 100ms without power. */ mdelay(100); } @@ -1749,7 +1743,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc) sdmmc_get_sd_clock_control(sdmmc); /* Wait a while. */ - udelay(5000); + mdelay(5); /* Host control 2 flag should be set by now. */ if (sdmmc->regs->host_control2 & SDHCI_CTRL_VDD_180) @@ -1761,7 +1755,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc) sdmmc_get_sd_clock_control(sdmmc); /* Wait a while. */ - udelay(1000); + mdelay(1); /* Data level is up. Voltage switching is done.*/ if (sdmmc->regs->present_state & SDHCI_DATA_LVL_MASK) diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h b/fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h index 7a6c141f7..8fbcffb6f 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h @@ -106,7 +106,7 @@ typedef struct { uint16_t slot_int_status; uint16_t host_version; - /* vendor specific registers */ + /* Vendor specific registers */ uint32_t vendor_clock_cntrl; uint32_t vendor_sys_sw_cntrl; uint32_t vendor_err_intr_status; @@ -121,12 +121,12 @@ typedef struct { uint32_t _0x12c[0x20]; uint32_t vendor_io_trim_cntrl; - /* start of sdmmc2/sdmmc4 only */ + /* Start of sdmmc2/sdmmc4 only */ uint32_t vendor_dllcal_cfg; uint32_t vendor_dll_ctrl0; uint32_t vendor_dll_ctrl1; uint32_t vendor_dllcal_cfg_sta; - /* end of sdmmc2/sdmmc4 only */ + /* End of sdmmc2/sdmmc4 only */ uint32_t vendor_tuning_cntrl0; uint32_t vendor_tuning_cntrl1; diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc.c b/fusee/fusee-secondary/src/sdmmc/sdmmc.c index 24e5f84b2..0927295f3 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc.c @@ -487,12 +487,12 @@ static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool i return 0; /* Delay a bit before asking for the voltage switch. */ - udelay(1000); + mdelay(100); /* Tell the driver to switch the voltage. */ if (!sdmmc_switch_voltage(device->sdmmc)) return 0; - + /* We are now running at 1.8V. */ device->is_180v = true; } @@ -693,15 +693,15 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status) /* Adjust the current limit. */ if (!sdmmc_sd_set_current_limit(device, status)) return 0; - + /* Invalid bus width. */ if (device->sdmmc->bus_width != SDMMC_BUS_WIDTH_4BIT) return 0; - + /* Get the supported high-speed type. */ if (!sdmmc_sd_switch(device, 0, 0, 0xF, status)) return 0; - + /* High-speed SDR104 is supported. */ if (status[13] & SD_MODE_UHS_SDR104) { @@ -748,6 +748,7 @@ static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status) else return 0; + /* Peek the SD card's status. */ return sdmmc_device_send_status(device); } @@ -974,22 +975,22 @@ int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth b /* Switch to high-speed from low voltage (if possible). */ if (!sdmmc_sd_switch_hs_low(device, switch_status)) { - sdmmc_error(sdmmc, "Failed to switch to high-speed!"); + sdmmc_error(sdmmc, "Failed to switch to high-speed from low voltage!"); return 0; } - sdmmc_info(sdmmc, "Switched to high-speed!"); + sdmmc_info(sdmmc, "Switched to high-speed from low voltage!"); } else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_UNK6))) { /* Switch to high-speed from high voltage (if possible). */ if (!sdmmc_sd_switch_hs_high(device, switch_status)) { - sdmmc_error(sdmmc, "Failed to switch to high-speed!"); + sdmmc_error(sdmmc, "Failed to switch to high-speed from high voltage!"); return 0; } - sdmmc_info(sdmmc, "Switched to high-speed!"); + sdmmc_info(sdmmc, "Switched to high-speed from high voltage!"); } /* Correct any inconsistent states. */ @@ -1322,9 +1323,6 @@ static int sdmmc_mmc_select_hs400(sdmmc_device_t *device) static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed) { - // FIXME: Tuning is broken. Use HS52 for now. - return sdmmc_mmc_select_hs(device, false); - if ((bus_speed == SDMMC_SPEED_HS400) && (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) && (device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)) @@ -1376,7 +1374,7 @@ int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth { uint32_t cid[4] = {0}; uint32_t csd[4] = {0}; - uint8_t *ext_csd = (uint8_t *)SDMMC_BOUNCE_BUFFER_ADDRESS; // TODO: Better way to do this. + uint8_t ext_csd[512] = {0}; /* Initialize our device's struct. */ memset(device, 0, sizeof(sdmmc_device_t)); diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index 5b96970c9..b99db835d 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -549,28 +549,26 @@ static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) case SDMMC_3: switch (voltage) { case SDMMC_VOLTAGE_1V8: - sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_1V8; break; case SDMMC_VOLTAGE_3V3: - sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_3V3; break; default: - sdmmc_error(sdmmc, "microsd does not support voltage %d", voltage); + sdmmc_error(sdmmc, "uSD does not support requested voltage!"); return 0; } break; - case SDMMC_2: case SDMMC_4: if (voltage != SDMMC_VOLTAGE_1V8) { - sdmmc_error(sdmmc, "eMMC can only run at 1V8, but sdmmc struct claims voltage %d", voltage); + sdmmc_error(sdmmc, "eMMC can only run at 1V8!"); return 0; } - - sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_PDPU_CONFIG_MASK; + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC4_1V8; break; } @@ -581,8 +579,8 @@ static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) /* Run automatic calibration. */ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) { - bool restart_sd_clock = false; volatile tegra_padctl_t *padctl = padctl_get_regs(); + bool restart_sd_clock = false; /* SD clock is enabled. Disable it and restart later. */ if (sdmmc->is_sd_clk_enabled) @@ -619,7 +617,7 @@ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) while ((sdmmc->regs->auto_cal_status & SDMMC_AUTOCAL_ACTIVE)) { /* Ensure we haven't timed out. */ if (get_time_since(timebase) > SDMMC_AUTOCAL_TIMEOUT) { - sdmmc_error(sdmmc, "autocal timed out!"); + sdmmc_error(sdmmc, "Auto-calibration timed out!"); /* Force a register read to refresh the clock control value. */ sdmmc_get_sd_clock_control(sdmmc); @@ -642,7 +640,7 @@ static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) } /* Manually clear the autocal enable bit. */ - sdmmc->regs->auto_cal_config &= ~SDMMC_AUTOCAL_ENABLE; + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_ENABLE); break; } } @@ -696,16 +694,9 @@ static int sdmmc_int_clk_enable(sdmmc_t *sdmmc) /* Use SDMA by default. */ sdmmc->regs->host_control &= ~SDHCI_CTRL_DMA_MASK; - /* Change to ADMA if requested. */ - if (sdmmc->use_adma && (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2)) { - // TODO: Setting the ADMA flags breaks ADMA... - /* - if (sdmmc->regs->capabilities & SDHCI_CAN_64BIT) - sdmmc->regs->host_control |= SDHCI_CTRL_ADMA64; - else - sdmmc->regs->host_control |= SDHCI_CTRL_ADMA32; - */ - } + /* Change to ADMA if possible. */ + if (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2) + sdmmc->use_adma = true; /* Set the timeout to be the maximum value. */ sdmmc->regs->timeout_control &= 0xF0; @@ -847,9 +838,9 @@ static int sdmmc_dllcal_run(sdmmc_t *sdmmc) is_timeout = (get_time_since(timebase) > 10000); } - /* Clock failed to stabilize. */ + /* Calibration failed. */ if (is_timeout) { - sdmmc_error(sdmmc, "ERROR: DLLCAL failed!"); + sdmmc_error(sdmmc, "DLLCAL failed!"); return 0; } @@ -898,20 +889,23 @@ int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed) case SDMMC_SPEED_DDR50: case SDMMC_SPEED_SDR50: case SDMMC_SPEED_UNK14: - sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; - sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180); + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; break; /* 200MHz single-data rate (MMC). */ case SDMMC_SPEED_HS400: - sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; - sdmmc->regs->host_control2 |= (SDHCI_CTRL_HS400 | SDHCI_CTRL_VDD_180); + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; break; /* 25MHz default speed (SD). */ case SDMMC_SPEED_SDR12: - sdmmc->regs->host_control2 &= SDHCI_CTRL_UHS_MASK; - sdmmc->regs->host_control2 |= (SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180); + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; break; default: @@ -1093,7 +1087,7 @@ static int sdmmc_init_controller(sdmmc_t *sdmmc, SdmmcControllerNum controller) sdmmc->is_clk_running = false; sdmmc->is_sd_clk_enabled = false; sdmmc->is_tuning_tap_val_set = false; - sdmmc->use_adma = true; + sdmmc->use_adma = false; sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; sdmmc->tap_val = 0; sdmmc->internal_divider = 0; @@ -1206,11 +1200,11 @@ void sdmmc_finish(sdmmc_t *sdmmc) sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE); /* Disable the SD card power. */ - if (sdmmc->controller == SDMMC_1) - { + if (sdmmc->controller == SDMMC_1) + { /* Disable GPIO output. */ gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_INPUT); - + /* Power cycle for 100ms without power. */ mdelay(100); } @@ -1749,7 +1743,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc) sdmmc_get_sd_clock_control(sdmmc); /* Wait a while. */ - udelay(5000); + mdelay(5); /* Host control 2 flag should be set by now. */ if (sdmmc->regs->host_control2 & SDHCI_CTRL_VDD_180) @@ -1761,7 +1755,7 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc) sdmmc_get_sd_clock_control(sdmmc); /* Wait a while. */ - udelay(1000); + mdelay(1); /* Data level is up. Voltage switching is done.*/ if (sdmmc->regs->present_state & SDHCI_DATA_LVL_MASK) diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h b/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h index 7a6c141f7..8fbcffb6f 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h @@ -106,7 +106,7 @@ typedef struct { uint16_t slot_int_status; uint16_t host_version; - /* vendor specific registers */ + /* Vendor specific registers */ uint32_t vendor_clock_cntrl; uint32_t vendor_sys_sw_cntrl; uint32_t vendor_err_intr_status; @@ -121,12 +121,12 @@ typedef struct { uint32_t _0x12c[0x20]; uint32_t vendor_io_trim_cntrl; - /* start of sdmmc2/sdmmc4 only */ + /* Start of sdmmc2/sdmmc4 only */ uint32_t vendor_dllcal_cfg; uint32_t vendor_dll_ctrl0; uint32_t vendor_dll_ctrl1; uint32_t vendor_dllcal_cfg_sta; - /* end of sdmmc2/sdmmc4 only */ + /* End of sdmmc2/sdmmc4 only */ uint32_t vendor_tuning_cntrl0; uint32_t vendor_tuning_cntrl1; From dd4993dfda662cc6c9eebc1d4533a5d92a7cfb51 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 24 Jul 2018 01:26:37 -0700 Subject: [PATCH 005/489] Loader: Use HW-acceleration for SHA256 --- stratosphere/loader/source/ldr_nro.cpp | 5 +- stratosphere/loader/source/ldr_nso.cpp | 6 +- stratosphere/loader/source/sha256.c | 227 +++++++++------------- stratosphere/loader/source/sha256.h | 57 +++--- stratosphere/loader/source/sha256_armv8.s | 163 ++++++++++++++++ 5 files changed, 287 insertions(+), 171 deletions(-) create mode 100644 stratosphere/loader/source/sha256_armv8.s diff --git a/stratosphere/loader/source/ldr_nro.cpp b/stratosphere/loader/source/ldr_nro.cpp index 52f1bdf03..127878212 100644 --- a/stratosphere/loader/source/ldr_nro.cpp +++ b/stratosphere/loader/source/ldr_nro.cpp @@ -36,7 +36,7 @@ Result NroUtils::LoadNro(Registration::Process *target_proc, Handle process_h, u unsigned int i; Result rc; u8 nro_hash[0x20]; - SHA256_CTX sha_ctx; + struct sha256_state sha_ctx; /* Ensure there is an available NRO slot. */ if (std::all_of(target_proc->nro_infos.begin(), target_proc->nro_infos.end(), std::mem_fn(&Registration::NroInfo::in_use))) { return 0x6E09; @@ -78,7 +78,8 @@ Result NroUtils::LoadNro(Registration::Process *target_proc, Handle process_h, u sha256_init(&sha_ctx); sha256_update(&sha_ctx, (u8 *)nro, nro->nro_size); - sha256_final(&sha_ctx, nro_hash); + sha256_finalize(&sha_ctx); + sha256_finish(&sha_ctx, nro_hash); if (!Registration::IsNroHashPresent(target_proc->index, nro_hash)) { rc = 0x6C09; diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index 86b696454..b01e5d25f 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -199,6 +199,7 @@ Result NsoUtils::CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLo } + Result NsoUtils::LoadNsoSegment(u64 title_id, unsigned int index, unsigned int segment, FILE *f_nso, u8 *map_base, u8 *map_end) { bool is_compressed = ((g_nso_headers[index].flags >> segment) & 1) != 0; bool check_hash = ((g_nso_headers[index].flags >> (segment + 3)) & 1) != 0; @@ -230,10 +231,11 @@ Result NsoUtils::LoadNsoSegment(u64 title_id, unsigned int index, unsigned int s if (check_hash) { u8 hash[0x20] = {0}; - SHA256_CTX sha_ctx; + struct sha256_state sha_ctx; sha256_init(&sha_ctx); sha256_update(&sha_ctx, dst_addr, out_size); - sha256_final(&sha_ctx, hash); + sha256_finalize(&sha_ctx); + sha256_finish(&sha_ctx, hash); if (std::memcmp(g_nso_headers[index].section_hashes[segment], hash, sizeof(hash))) { return 0xA09; diff --git a/stratosphere/loader/source/sha256.c b/stratosphere/loader/source/sha256.c index eb9c5c073..02d40a758 100644 --- a/stratosphere/loader/source/sha256.c +++ b/stratosphere/loader/source/sha256.c @@ -1,158 +1,113 @@ -/********************************************************************* -* Filename: sha256.c -* Author: Brad Conte (brad AT bradconte.com) -* Copyright: -* Disclaimer: This code is presented "as is" without any guarantees. -* Details: Implementation of the SHA-256 hashing algorithm. - SHA-256 is one of the three algorithms in the SHA2 - specification. The others, SHA-384 and SHA-512, are not - offered in this implementation. - Algorithm specification can be found here: - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf - This implementation uses little endian byte order. -*********************************************************************/ +/* Based on linux source code */ +/* + * sha256_base.h - core logic for SHA-256 implementations + * + * Copyright (C) 2015 Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ -/*************************** HEADER FILES ***************************/ -#include -#include +#ifdef __cplusplus +extern "C" { +#endif + +#include #include "sha256.h" -/****************************** MACROS ******************************/ -#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) -#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) +#define unlikely(x) __builtin_expect(!!(x), 0) -#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) -#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) -#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) -#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) -#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) -#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) - -/**************************** VARIABLES *****************************/ -static const WORD k[64] = { - 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, - 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, - 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, - 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, - 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, - 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, - 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, - 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 -}; - -/*********************** FUNCTION DEFINITIONS ***********************/ -void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) +void sha256_block_data_order (uint32_t *ctx, const void *in, size_t num); + +int sha256_init(struct sha256_state *sctx) { - WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + sctx->state[0] = SHA256_H0; + sctx->state[1] = SHA256_H1; + sctx->state[2] = SHA256_H2; + sctx->state[3] = SHA256_H3; + sctx->state[4] = SHA256_H4; + sctx->state[5] = SHA256_H5; + sctx->state[6] = SHA256_H6; + sctx->state[7] = SHA256_H7; + sctx->count = 0; - for (i = 0, j = 0; i < 16; ++i, j += 4) - m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); - for ( ; i < 64; ++i) - m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; - - a = ctx->state[0]; - b = ctx->state[1]; - c = ctx->state[2]; - d = ctx->state[3]; - e = ctx->state[4]; - f = ctx->state[5]; - g = ctx->state[6]; - h = ctx->state[7]; - - for (i = 0; i < 64; ++i) { - t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; - t2 = EP0(a) + MAJ(a,b,c); - h = g; - g = f; - f = e; - e = d + t1; - d = c; - c = b; - b = a; - a = t1 + t2; - } - - ctx->state[0] += a; - ctx->state[1] += b; - ctx->state[2] += c; - ctx->state[3] += d; - ctx->state[4] += e; - ctx->state[5] += f; - ctx->state[6] += g; - ctx->state[7] += h; + return 0; } -void sha256_init(SHA256_CTX *ctx) +int sha256_update(struct sha256_state *sctx, + const void *data, + size_t len) { - ctx->datalen = 0; - ctx->bitlen = 0; - ctx->state[0] = 0x6a09e667; - ctx->state[1] = 0xbb67ae85; - ctx->state[2] = 0x3c6ef372; - ctx->state[3] = 0xa54ff53a; - ctx->state[4] = 0x510e527f; - ctx->state[5] = 0x9b05688c; - ctx->state[6] = 0x1f83d9ab; - ctx->state[7] = 0x5be0cd19; -} + const u8 *data8 = (const u8 *)data; + unsigned int len32 = (unsigned int)len; + unsigned int partial = sctx->count % SHA256_BLOCK_SIZE; -void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) -{ - WORD i; + sctx->count += len32; - for (i = 0; i < len; ++i) { - ctx->data[ctx->datalen] = data[i]; - ctx->datalen++; - if (ctx->datalen == 64) { - sha256_transform(ctx, ctx->data); - ctx->bitlen += 512; - ctx->datalen = 0; + if (unlikely((partial + len32) >= SHA256_BLOCK_SIZE)) { + int blocks; + + if (partial) { + int p = SHA256_BLOCK_SIZE - partial; + + memcpy(sctx->buf + partial, data8, p); + data8 += p; + len32 -= p; + + sha256_block_data_order(sctx->state, sctx->buf, 1); } + + blocks = len32 / SHA256_BLOCK_SIZE; + len32 %= SHA256_BLOCK_SIZE; + + if (blocks) { + sha256_block_data_order(sctx->state, data8, blocks); + data8 += blocks * SHA256_BLOCK_SIZE; + } + partial = 0; } + if (len32) + memcpy(sctx->buf + partial, data8, len32); + + return 0; } -void sha256_final(SHA256_CTX *ctx, BYTE hash[]) +int sha256_finalize(struct sha256_state *sctx) { - WORD i; + const int bit_offset = SHA256_BLOCK_SIZE - sizeof(u64); + u64 *bits = (u64 *)(sctx->buf + bit_offset); + unsigned int partial = sctx->count % SHA256_BLOCK_SIZE; - i = ctx->datalen; + sctx->buf[partial++] = 0x80; + if (partial > bit_offset) { + memset(sctx->buf + partial, 0x0, SHA256_BLOCK_SIZE - partial); + partial = 0; - // Pad whatever data is left in the buffer. - if (ctx->datalen < 56) { - ctx->data[i++] = 0x80; - while (i < 56) - ctx->data[i++] = 0x00; - } - else { - ctx->data[i++] = 0x80; - while (i < 64) - ctx->data[i++] = 0x00; - sha256_transform(ctx, ctx->data); - memset(ctx->data, 0, 56); + sha256_block_data_order(sctx->state, sctx->buf, 1); } - // Append to the padding the total message's length in bits and transform. - ctx->bitlen += ctx->datalen * 8; - ctx->data[63] = ctx->bitlen; - ctx->data[62] = ctx->bitlen >> 8; - ctx->data[61] = ctx->bitlen >> 16; - ctx->data[60] = ctx->bitlen >> 24; - ctx->data[59] = ctx->bitlen >> 32; - ctx->data[58] = ctx->bitlen >> 40; - ctx->data[57] = ctx->bitlen >> 48; - ctx->data[56] = ctx->bitlen >> 56; - sha256_transform(ctx, ctx->data); + memset(sctx->buf + partial, 0x0, bit_offset - partial); + *bits = __builtin_bswap64(sctx->count << 3); + sha256_block_data_order(sctx->state, sctx->buf, 1); - // Since this implementation uses little endian byte ordering and SHA uses big endian, - // reverse all the bytes when copying the final state to the output hash. - for (i = 0; i < 4; ++i) { - hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; - hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; - hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; - hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; - hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; - hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; - hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; - hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; - } + return 0; } + +int sha256_finish(struct sha256_state *sctx, void *out) +{ + unsigned int digest_size = 32; + u32 *digest = (u32 *)out; + int i; + + // Switch: misalignment shouldn't be a problem here... + for (i = 0; digest_size > 0; i++, digest_size -= sizeof(u32)) + *digest++ = __builtin_bswap32(sctx->state[i]); + + *sctx = (struct sha256_state){}; + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/stratosphere/loader/source/sha256.h b/stratosphere/loader/source/sha256.h index 870b1dbe0..cfb09f89c 100644 --- a/stratosphere/loader/source/sha256.h +++ b/stratosphere/loader/source/sha256.h @@ -1,41 +1,36 @@ -/********************************************************************* -* Filename: sha256.h -* Author: Brad Conte (brad AT bradconte.com) -* Copyright: -* Disclaimer: This code is presented "as is" without any guarantees. -* Details: Defines the API for the corresponding SHA1 implementation. -*********************************************************************/ +#pragma once -#if defined (__cplusplus) +/* Based on linux source code */ + +#ifdef __cplusplus extern "C" { #endif -#ifndef SHA256_H -#define SHA256_H -/*************************** HEADER FILES ***************************/ -#include +#include -/****************************** MACROS ******************************/ -#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 -/**************************** DATA TYPES ****************************/ -typedef unsigned char BYTE; // 8-bit byte -typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines +#define SHA256_H0 0x6a09e667UL +#define SHA256_H1 0xbb67ae85UL +#define SHA256_H2 0x3c6ef372UL +#define SHA256_H3 0xa54ff53aUL +#define SHA256_H4 0x510e527fUL +#define SHA256_H5 0x9b05688cUL +#define SHA256_H6 0x1f83d9abUL +#define SHA256_H7 0x5be0cd19UL -typedef struct { - BYTE data[64]; - WORD datalen; - unsigned long long bitlen; - WORD state[8]; -} SHA256_CTX; +struct sha256_state { + u32 state[SHA256_DIGEST_SIZE / 4]; + u64 count; + u8 buf[SHA256_BLOCK_SIZE]; +}; -/*********************** FUNCTION DECLARATIONS **********************/ -void sha256_init(SHA256_CTX *ctx); -void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len); -void sha256_final(SHA256_CTX *ctx, BYTE hash[]); +int sha256_init(struct sha256_state *sctx); +int sha256_update(struct sha256_state *sctx, const void *data, size_t len); +int sha256_finalize(struct sha256_state *sctx); +int sha256_finish(struct sha256_state *sctx, void *out); -#endif // SHA256_H - -#if defined (__cplusplus) +#ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/stratosphere/loader/source/sha256_armv8.s b/stratosphere/loader/source/sha256_armv8.s new file mode 100644 index 000000000..0420d38be --- /dev/null +++ b/stratosphere/loader/source/sha256_armv8.s @@ -0,0 +1,163 @@ +.section .text.sha256_armv8, "ax", %progbits +.align 5 +.arch armv8-a+crypto + +# SHA256 assembly implementation for ARMv8 AArch64 (based on linux source code) + +.global sha256_block_data_order +.type sha256_block_data_order,%function +sha256_block_data_order: + +.Lsha256prolog: + + stp x29, x30, [sp,#-64]! + mov x29, sp + adr x3, .LKConstant256 + str q8, [sp, #16] + ld1 {v16.4s-v19.4s}, [x3], #64 + ld1 {v0.4s}, [x0], #16 + ld1 {v20.4s-v23.4s}, [x3], #64 + add x2, x1, x2, lsl #6 + ld1 {v1.4s}, [x0] + ld1 {v24.4s-v27.4s}, [x3], #64 + sub x0, x0, #16 + str q9, [sp, #32] + str q10, [sp, #48] + ld1 {v28.4s-v31.4s}, [x3], #64 + +.Lsha256loop: + + ld1 {v5.16b-v8.16b}, [x1], #64 + mov v2.16b, v0.16b + mov v3.16b, v1.16b + + rev32 v5.16b, v5.16b + rev32 v6.16b, v6.16b + add v9.4s, v5.4s, v16.4s + rev32 v7.16b, v7.16b + add v10.4s, v6.4s, v17.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v5.4s, v6.4s + rev32 v8.16b, v8.16b + add v9.4s, v7.4s, v18.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v6.4s, v7.4s + sha256su1 v5.4s, v7.4s, v8.4s + add v10.4s, v8.4s, v19.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v7.4s, v8.4s + sha256su1 v6.4s, v8.4s, v5.4s + add v9.4s, v5.4s, v20.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v8.4s, v5.4s + sha256su1 v7.4s, v5.4s, v6.4s + add v10.4s, v6.4s, v21.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v5.4s, v6.4s + sha256su1 v8.4s, v6.4s, v7.4s + add v9.4s, v7.4s, v22.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v6.4s, v7.4s + sha256su1 v5.4s, v7.4s, v8.4s + add v10.4s, v8.4s, v23.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v7.4s, v8.4s + sha256su1 v6.4s, v8.4s, v5.4s + add v9.4s, v5.4s, v24.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v8.4s, v5.4s + sha256su1 v7.4s, v5.4s, v6.4s + add v10.4s, v6.4s, v25.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v5.4s, v6.4s + sha256su1 v8.4s, v6.4s, v7.4s + add v9.4s, v7.4s, v26.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v6.4s, v7.4s + sha256su1 v5.4s, v7.4s, v8.4s + add v10.4s, v8.4s, v27.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v7.4s, v8.4s + sha256su1 v6.4s, v8.4s, v5.4s + add v9.4s, v5.4s, v28.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v8.4s, v5.4s + sha256su1 v7.4s, v5.4s, v6.4s + add v10.4s, v6.4s, v29.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su1 v8.4s, v6.4s, v7.4s + add v9.4s, v7.4s, v30.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + add v10.4s, v8.4s, v31.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + cmp x1, x2 + add v1.4s, v1.4s, v3.4s + add v0.4s, v0.4s, v2.4s + b.ne .Lsha256loop + +.Lsha256epilog: + + st1 {v0.4s,v1.4s}, [x0] + ldr q10, [sp, #48] + ldr q9, [sp, #32] + ldr q8, [sp, #16] + ldr x29, [sp], #64 + ret + +.align 5 +.LKConstant256: +.word 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.word 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.word 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.word 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.word 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc +.word 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.word 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.word 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 +.word 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.word 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.word 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.word 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.word 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.word 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.word 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + +.size sha256_block_data_order,.-sha256_block_data_order +.align 2 + + + From a2104b85ceb114aa104bddbad1871121305717fc Mon Sep 17 00:00:00 2001 From: hexkyz Date: Tue, 24 Jul 2018 19:05:27 +0100 Subject: [PATCH 006/489] fusee: Disable the SDCLK when switching to low voltage. --- fusee/fusee-primary/src/sdmmc/sdmmc_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c index b99db835d..85cab87ba 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c @@ -1712,6 +1712,9 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc) { volatile tegra_pmc_t *pmc = pmc_get_regs(); + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + /* Reconfigure the internal clock. */ if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_SDR12)) { @@ -1978,4 +1981,4 @@ int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode) sdmmc_disable_sd_clock(sdmmc); return result; -} \ No newline at end of file +} From fd88bd1d2c69ceded89da48f98f0ae117a56f195 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Tue, 24 Jul 2018 19:06:41 +0100 Subject: [PATCH 007/489] fusee: Disable the SDCLK when switching to low voltage. --- fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index b99db835d..85cab87ba 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -1712,6 +1712,9 @@ int sdmmc_switch_voltage(sdmmc_t *sdmmc) { volatile tegra_pmc_t *pmc = pmc_get_regs(); + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + /* Reconfigure the internal clock. */ if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_SDR12)) { @@ -1978,4 +1981,4 @@ int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode) sdmmc_disable_sd_clock(sdmmc); return result; -} \ No newline at end of file +} From 78366098393d99402c13498409785b6a771937e1 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 26 Jul 2018 18:45:18 +0100 Subject: [PATCH 008/489] Fix multiple issues reported by Coverity Scan --- exosphere/src/smc_user.c | 8 ++++++-- fusee/fusee-primary/src/sdmmc/sdmmc.c | 2 +- fusee/fusee-primary/src/stage2.c | 3 ++- fusee/fusee-secondary/src/fs_dev.c | 4 +++- fusee/fusee-secondary/src/gpt.c | 2 +- fusee/fusee-secondary/src/key_derivation.c | 4 ++-- fusee/fusee-secondary/src/nxfs.c | 7 ++++++- fusee/fusee-secondary/src/package1.c | 2 +- fusee/fusee-secondary/src/sdmmc/sdmmc.c | 2 +- stratosphere/loader/source/ldr_npdm.cpp | 10 +++++++--- 10 files changed, 30 insertions(+), 14 deletions(-) diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c index 7cc8103de..4f883655a 100644 --- a/exosphere/src/smc_user.c +++ b/exosphere/src/smc_user.c @@ -163,11 +163,15 @@ uint32_t user_generate_aes_kek(smc_args_t *args) { /* Masks 0, 3 are allowed all the time. */ - const uint8_t kek_seeds[4][0x10] = { + const uint8_t kek_seeds[7][0x10] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0xA2, 0xAB, 0xBF, 0x9C, 0x92, 0x2F, 0xBB, 0xE3, 0x78, 0x79, 0x9B, 0xC0, 0xCC, 0xEA, 0xA5, 0x74}, {0x57, 0xE2, 0xD9, 0x45, 0xE4, 0x92, 0xF4, 0xFD, 0xC3, 0xF9, 0x86, 0x38, 0x89, 0x78, 0x9F, 0x3C}, - {0xE5, 0x4D, 0x9A, 0x02, 0xF0, 0x4F, 0x5F, 0xA8, 0xAD, 0x76, 0x0A, 0xF6, 0x32, 0x95, 0x59, 0xBB} + {0xE5, 0x4D, 0x9A, 0x02, 0xF0, 0x4F, 0x5F, 0xA8, 0xAD, 0x76, 0x0A, 0xF6, 0x32, 0x95, 0x59, 0xBB}, + /* 5.0.0+ KEK seeds. */ + {0x59, 0xD9, 0x31, 0xF4, 0xA7, 0x97, 0xB8, 0x14, 0x40, 0xD6, 0xA2, 0x60, 0x2B, 0xED, 0x15, 0x31}, + {0xFD, 0x6A, 0x25, 0xE5, 0xD8, 0x38, 0x7F, 0x91, 0x49, 0xDA, 0xF8, 0x59, 0xA8, 0x28, 0xE6, 0x75}, + {0x89, 0x96, 0x43, 0x9A, 0x7C, 0xD5, 0x59, 0x55, 0x24, 0xD5, 0x24, 0x18, 0xAB, 0x6C, 0x04, 0x61} }; const uint8_t kek_masks[4][0x10] = { {0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9}, diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc.c b/fusee/fusee-primary/src/sdmmc/sdmmc.c index 0927295f3..365547ae9 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc.c @@ -643,7 +643,7 @@ static int sdmmc_sd_switch(sdmmc_device_t *device, uint32_t mode, uint32_t group static int sdmmc_sd_set_current_limit(sdmmc_device_t *device, uint8_t *status) { /* Start with the highest possible limit. */ - uint32_t current_limit = SD_SET_CURRENT_LIMIT_800; + int32_t current_limit = SD_SET_CURRENT_LIMIT_800; /* Try each limit. */ while (current_limit > SD_SET_CURRENT_NO_CHANGE) diff --git a/fusee/fusee-primary/src/stage2.c b/fusee/fusee-primary/src/stage2.c index 0d933f859..b3cffa3fa 100644 --- a/fusee/fusee-primary/src/stage2.c +++ b/fusee/fusee-primary/src/stage2.c @@ -110,5 +110,6 @@ void load_stage2(const char *bct0) { g_chainloader_entries[0].num = 0; g_chainloader_entrypoint = config.entrypoint; - strncpy(g_stage2_path, config.path, sizeof(g_stage2_path)); + strncpy(g_stage2_path, config.path, sizeof(g_stage2_path) - 1); + g_stage2_path[sizeof(g_stage2_path) - 1] = '\0'; } diff --git a/fusee/fusee-secondary/src/fs_dev.c b/fusee/fusee-secondary/src/fs_dev.c index 232115510..d6fda4a1b 100644 --- a/fusee/fusee-secondary/src/fs_dev.c +++ b/fusee/fusee-secondary/src/fs_dev.c @@ -359,6 +359,8 @@ static void fsdev_filinfo_to_st(struct stat *st, const FILINFO *info) { date.tm_sec = (info->ftime << 1) & 63; date.tm_min = (info->ftime >> 5) & 63; date.tm_hour = (info->ftime >> 11) & 31; + + date.tm_isdst = 0; st->st_atime = st->st_mtime = st->st_ctime = mktime(&date); st->st_size = (off_t)info->fsize; @@ -459,7 +461,7 @@ static off_t fsdev_seek(struct _reent *r, void *fd, off_t pos, int whence) { return -1; } - if(pos < 0 && pos + off < 0) { + if ((FSIZE_t)pos < 0 && (FSIZE_t)pos + off < 0) { /* don't allow seek to before the beginning of the file */ r->_errno = EINVAL; return -1; diff --git a/fusee/fusee-secondary/src/gpt.c b/fusee/fusee-secondary/src/gpt.c index 14db6563e..67dd5d474 100644 --- a/fusee/fusee-secondary/src/gpt.c +++ b/fusee/fusee-secondary/src/gpt.c @@ -79,7 +79,7 @@ int gpt_iterate_through_entries(FILE *disk, size_t sector_size, gpt_entry_iterat /* Iterate through the entries. */ for (uint32_t i = 0; i < hdr.entry_count; i++) { - if (fread(&entry, sizeof(efi_entry_t), 1, disk) == 0) { + if (!fread(&entry, sizeof(efi_entry_t), 1, disk)) { return -1; } diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index 39dc992d5..a216b2465 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -45,7 +45,7 @@ static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uin static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) { if (revision >= 0x20) { return -1; - generic_panic(); + /* TODO: what should we do? */ } if (keyblobs != NULL) { @@ -80,7 +80,7 @@ static int decrypt_keyblob(const nx_keyblob_t *keyblobs, uint32_t revision, uint decrypt_data_into_keyslot(0xB, keyslot, keyblob_mac_seed, 0x10); /* Validate keyblob. */ - se_compute_aes_128_cmac(0xB, work_buffer, 0x10, keyblob.mac + sizeof(keyblob.mac), sizeof(keyblob) - sizeof(keyblob.mac)); + se_compute_aes_128_cmac(0xB, work_buffer, 0x10, &keyblob + sizeof(keyblob.mac), sizeof(keyblob) - sizeof(keyblob.mac)); if (safe_memcmp(keyblob.mac, work_buffer, 0x10)) { return -1; } diff --git a/fusee/fusee-secondary/src/nxfs.c b/fusee/fusee-secondary/src/nxfs.c index 1420e73a4..521117f3d 100644 --- a/fusee/fusee-secondary/src/nxfs.c +++ b/fusee/fusee-secondary/src/nxfs.c @@ -157,7 +157,7 @@ static int nxfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *par (void)disk; device_partition_t *parent = (device_partition_t *)param; device_partition_t devpart = *parent; - char name_buffer[64]; + char name_buffer[128]; const uint16_t *utf16name = entry->name; uint32_t name_len; int rc; @@ -307,6 +307,11 @@ int nxfs_mount_all(void) { } rawnand = fopen("rawnand:/", "rb"); + + if (rawnand == NULL) { + return -1; + } + rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); fclose(rawnand); diff --git a/fusee/fusee-secondary/src/package1.c b/fusee/fusee-secondary/src/package1.c index 04291bd2f..5df01ef0b 100644 --- a/fusee/fusee-secondary/src/package1.c +++ b/fusee/fusee-secondary/src/package1.c @@ -65,7 +65,7 @@ int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_ /* Read the full keyblob area.*/ for (size_t i = 0; i < 32; i++) { - if (fread(d.sector, 0x200, 1, boot0) == 0) { + if (!fread(d.sector, 0x200, 1, boot0)) { return -1; } keyblobs[i] = d.keyblob; diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc.c b/fusee/fusee-secondary/src/sdmmc/sdmmc.c index 0927295f3..365547ae9 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc.c @@ -643,7 +643,7 @@ static int sdmmc_sd_switch(sdmmc_device_t *device, uint32_t mode, uint32_t group static int sdmmc_sd_set_current_limit(sdmmc_device_t *device, uint8_t *status) { /* Start with the highest possible limit. */ - uint32_t current_limit = SD_SET_CURRENT_LIMIT_800; + int32_t current_limit = SD_SET_CURRENT_LIMIT_800; /* Try each limit. */ while (current_limit > SD_SET_CURRENT_NO_CHANGE) diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index d06003571..f7c71727b 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -42,17 +42,21 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { g_npdm_cache.info = (const NpdmUtils::NpdmInfo){0}; FILE *f_npdm = OpenNpdm(tid); + + rc = 0x202; if (f_npdm == NULL) { /* For generic "Couldn't open the file" error, just say the file doesn't exist. */ - return 0x202; + return rc; } fseek(f_npdm, 0, SEEK_END); size_t npdm_size = ftell(f_npdm); fseek(f_npdm, 0, SEEK_SET); - if (npdm_size > sizeof(g_npdm_cache.buffer) || fread(g_npdm_cache.buffer, 1, npdm_size, f_npdm) != npdm_size) { - return 0x609; + rc = 0x609; + if ((npdm_size > sizeof(g_npdm_cache.buffer)) || (fread(g_npdm_cache.buffer, 1, npdm_size, f_npdm) != npdm_size)) { + fclose(f_npdm); + return rc; } fclose(f_npdm); From 054c65dffbd6216f3fc59e1c335bf5a975827cf5 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Thu, 26 Jul 2018 19:26:43 +0100 Subject: [PATCH 009/489] Revert unnecessary change (thanks @rajkosto) --- fusee/fusee-secondary/src/key_derivation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index a216b2465..c048cc05d 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -80,7 +80,7 @@ static int decrypt_keyblob(const nx_keyblob_t *keyblobs, uint32_t revision, uint decrypt_data_into_keyslot(0xB, keyslot, keyblob_mac_seed, 0x10); /* Validate keyblob. */ - se_compute_aes_128_cmac(0xB, work_buffer, 0x10, &keyblob + sizeof(keyblob.mac), sizeof(keyblob) - sizeof(keyblob.mac)); + se_compute_aes_128_cmac(0xB, work_buffer, 0x10, keyblob.mac + sizeof(keyblob.mac), sizeof(keyblob) - sizeof(keyblob.mac)); if (safe_memcmp(keyblob.mac, work_buffer, 0x10)) { return -1; } From 9d0d9d95e1196886412bbf29f6fd24042c3c179b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 01:44:21 -0700 Subject: [PATCH 010/489] Stratosphere: Give more memory to SYSTEM, use less memory. --- stratosphere/loader/source/ldr_main.cpp | 2 +- stratosphere/pm/source/pm_main.cpp | 2 +- stratosphere/pm/source/pm_resource_limits.cpp | 8 ++++++++ stratosphere/sm/source/sm_main.cpp | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index 5d6f5a01c..94a52fcbf 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -16,7 +16,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x200000 + #define INNER_HEAP_SIZE 0x20000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 5a65793fd..4ce175465 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -18,7 +18,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x200000 + #define INNER_HEAP_SIZE 0x20000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index f45f135e9..4149ccfac 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -3,6 +3,9 @@ #include "pm_resource_limits.hpp" +/* Give 24 MiB to SYSTEM from Applet. This allows for more custom sysmodules. */ +#define ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES 0x1800000ULL + /* Memory that system, application, applet are allowed to allocate. */ static const u64 g_memory_resource_limits_deprecated[5][3] = { {0x010D00000ULL, 0x0CD500000ULL, 0x021700000ULL}, @@ -78,6 +81,11 @@ void ResourceLimitUtils::InitializeLimits() { memcpy(&g_memory_resource_limits, &g_memory_resource_limits_deprecated, sizeof(g_memory_resource_limits)); memcpy(&g_resource_limits, &g_resource_limits_deprecated, sizeof(g_resource_limits)); } + /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */ + for (unsigned int i = 0; i < 5; i++) { + g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + } /* Get memory limits. */ u64 memory_arrangement; if (R_FAILED(splGetConfig(SplConfigItem_MemoryArrange, &memory_arrangement))) { diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index e68b6674d..410058383 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -15,7 +15,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x200000 + #define INNER_HEAP_SIZE 0x20000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; From 6adcb483e5dab08e8aab9467bfbd5c4c894e4c2f Mon Sep 17 00:00:00 2001 From: misson20000 Date: Fri, 27 Jul 2018 01:56:24 -0700 Subject: [PATCH 011/489] pm: remove magic flag/event numbers to improve readability and understandability --- stratosphere/pm/source/pm_registration.cpp | 72 +++++++------ stratosphere/pm/source/pm_registration.hpp | 119 +++++++++++++++++++++ stratosphere/pm/source/pm_shell.cpp | 2 +- 3 files changed, 159 insertions(+), 34 deletions(-) diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index 856e5dfec..e61b81a3b 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -105,16 +105,16 @@ void Registration::HandleProcessLaunch() { /* Setup process flags. */ if (program_info.application_type & 1) { - new_process.flags |= 0x40; + new_process.flags |= PROCESSFLAGS_APPLICATION; } if (kernelAbove200() && LAUNCHFLAGS_NOTIYDEBUGSPECIAL(launch_flags) && (program_info.application_type & 4)) { - new_process.flags |= 0x80; + new_process.flags |= PROCESSFLAGS_NOTIFYDEBUGSPECIAL; } if (LAUNCHFLAGS_NOTIFYWHENEXITED(launch_flags)) { - new_process.flags |= 1; + new_process.flags |= PROCESSFLAGS_NOTIFYWHENEXITED; } if (LAUNCHFLAGS_NOTIFYDEBUGEVENTS(launch_flags) && (!kernelAbove200() || (program_info.application_type & 4))) { - new_process.flags |= 0x8; + new_process.flags |= PROCESSFLAGS_NOTIFYDEBUGEVENTS; } /* Add process to the list. */ @@ -125,7 +125,7 @@ void Registration::HandleProcessLaunch() { g_debug_title_event->signal_event(); g_debug_on_launch_tid = 0; rc = 0; - } else if ((new_process.flags & 0x40) && g_debug_next_application.load()) { + } else if ((new_process.flags & PROCESSFLAGS_APPLICATION) && g_debug_next_application.load()) { g_debug_application_event->signal_event(); g_debug_next_application = false; rc = 0; @@ -226,7 +226,7 @@ Result Registration::HandleSignaledProcess(std::shared_ptrstate = (ProcessState)tmp; if (old_state == ProcessState_Crashed && process->state != ProcessState_Crashed) { - process->flags &= ~0x4; + process->flags &= ~PROCESSFLAGS_CRASH_DEBUG; } switch (process->state) { case ProcessState_Created: @@ -234,37 +234,37 @@ Result Registration::HandleSignaledProcess(std::shared_ptrflags & 8) { - process->flags &= ~0x30; - process->flags |= 0x10; + if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) { + process->flags &= ~(PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED); + process->flags |= PROCESSFLAGS_DEBUGEVENTPENDING; g_process_event->signal_event(); } - if (kernelAbove200() && process->flags & 0x80) { - process->flags &= ~0x180; - process->flags |= 0x100; + if (kernelAbove200() && process->flags & PROCESSFLAGS_NOTIFYDEBUGSPECIAL) { + process->flags &= ~(PROCESSFLAGS_NOTIFYDEBUGSPECIAL | PROCESSFLAGS_DEBUGDETACHED); + process->flags |= PROCESSFLAGS_DEBUGDETACHED; } break; case ProcessState_Crashed: - process->flags |= 6; + process->flags |= (PROCESSFLAGS_CRASHED | PROCESSFLAGS_CRASH_DEBUG); g_process_event->signal_event(); break; case ProcessState_Running: - if (process->flags & 8) { - process->flags &= ~0x30; - process->flags |= 0x10; + if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) { + process->flags &= ~(PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED); + process->flags |= PROCESSFLAGS_DEBUGEVENTPENDING; g_process_event->signal_event(); } break; case ProcessState_Exited: - if (process->flags & 1 && !kernelAbove500()) { + if (process->flags & PROCESSFLAGS_NOTIFYWHENEXITED && !kernelAbove500()) { g_process_event->signal_event(); } else { FinalizeExitedProcess(process); } return 0xF601; case ProcessState_DebugSuspended: - if (process->flags & 8) { - process->flags |= 0x30; + if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) { + process->flags |= (PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED); g_process_event->signal_event(); } break; @@ -274,7 +274,7 @@ Result Registration::HandleSignaledProcess(std::shared_ptr process) { auto auto_lock = GetProcessListUniqueLock(); - bool signal_debug_process_5x = kernelAbove500() && process->flags & 1; + bool signal_debug_process_5x = kernelAbove500() && process->flags & PROCESSFLAGS_NOTIFYWHENEXITED; /* Unregister with FS. */ if (R_FAILED(fsprUnregisterProgram(process->pid))) { /* TODO: Panic. */ @@ -344,7 +344,7 @@ bool Registration::HasApplicationProcess(std::shared_ptr auto auto_lock = GetProcessListUniqueLock(); for (auto &process : g_process_list.processes) { - if (process->flags & 0x40) { + if (process->flags & PROCESSFLAGS_APPLICATION) { if (out != nullptr) { *out = process; } @@ -386,7 +386,7 @@ Result Registration::GetDebugProcessIds(u64 *out_pids, u32 max_out, u32 *num_out for (auto &process : g_process_list.processes) { - if (process->flags & 4 && num < max_out) { + if (process->flags & PROCESSFLAGS_CRASH_DEBUG && num < max_out) { out_pids[num++] = process->pid; } } @@ -403,27 +403,33 @@ void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) { auto auto_lock = GetProcessListUniqueLock(); for (auto &p : g_process_list.processes) { - if (kernelAbove200() && p->state >= ProcessState_DebugDetached && p->flags & 0x100) { - p->flags &= ~0x100; + if (kernelAbove200() && p->state >= ProcessState_DebugDetached && p->flags & PROCESSFLAGS_DEBUGDETACHED) { + p->flags &= ~PROCESSFLAGS_DEBUGDETACHED; *out_pid = p->pid; - *out_type = kernelAbove500() ? 2 : 5; + *out_type = kernelAbove500() ? PROCESSEVENTTYPE_500_DEBUGDETACHED : PROCESSEVENTTYPE_DEBUGDETACHED; return; } - if (p->flags & 0x10) { + if (p->flags & PROCESSFLAGS_DEBUGEVENTPENDING) { u64 old_flags = p->flags; - p->flags &= ~0x10; + p->flags &= ~PROCESSFLAGS_DEBUGEVENTPENDING; *out_pid = p->pid; - *out_type = kernelAbove500() ? (((old_flags >> 5) & 1) | 4) : (((old_flags >> 5) & 1) + 3); + *out_type = kernelAbove500() ? + ((old_flags & PROCESSFLAGS_DEBUGSUSPENDED) ? + PROCESSEVENTTYPE_500_SUSPENDED : + PROCESSEVENTTYPE_500_RUNNING) : + ((old_flags & PROCESSFLAGS_DEBUGSUSPENDED) ? + PROCESSEVENTTYPE_SUSPENDED : + PROCESSEVENTTYPE_RUNNING); return; } - if (p->flags & 2) { + if (p->flags & PROCESSFLAGS_CRASHED) { *out_pid = p->pid; - *out_type = kernelAbove500() ? 3 : 1; + *out_type = kernelAbove500() ? PROCESSEVENTTYPE_500_CRASH : PROCESSEVENTTYPE_CRASH; return; } - if (!kernelAbove500() && p->flags & 1 && p->state == ProcessState_Exited) { + if (!kernelAbove500() && p->flags & PROCESSFLAGS_NOTIFYWHENEXITED && p->state == ProcessState_Exited) { *out_pid = p->pid; - *out_type = 2; + *out_type = PROCESSEVENTTYPE_EXIT; return; } } @@ -434,7 +440,7 @@ void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) { std::shared_ptr process = g_dead_process_list.processes[0]; g_dead_process_list.processes.erase(g_dead_process_list.processes.begin()); *out_pid = process->pid; - *out_type = 1; + *out_type = PROCESSEVENTTYPE_500_EXIT; return; } } diff --git a/stratosphere/pm/source/pm_registration.hpp b/stratosphere/pm/source/pm_registration.hpp index ce22b8573..89dc1d929 100644 --- a/stratosphere/pm/source/pm_registration.hpp +++ b/stratosphere/pm/source/pm_registration.hpp @@ -11,7 +11,126 @@ #define LAUNCHFLAGS_NOTIFYDEBUGEVENTS(flags) (flags & (kernelAbove500() ? 0x8 : 0x10)) #define LAUNCHFLAGS_NOTIYDEBUGSPECIAL(flags) (flags & (kernelAbove500() ? 0x2 : (kernelAbove200() ? 0x20 : 0x0))) +// none of these names are official or authoritative in any way +enum { + /* + set in HandleProcessLaunch when + - launch_flags has LAUNCHFLAGS_NOTIFYWHENEXITED set + signals g_process_event in HandleSignaledProcess when + - process enters Exited state + - we're below 5.0.0 + (finalizes dead process when not set) + adds to dead process list in FinalizeExitedProcess when + - we're 5.0.0+ + (also signals g_process_event) + [5.0.0+] causes ProcessEventType 2 + */ + PROCESSFLAGS_NOTIFYWHENEXITED = 0x001, + /* + set in HandleSignaledProcess when + - process crashes + causes ProcessEventType 1 ([5.0.0+] 3) (persistent) + */ + PROCESSFLAGS_CRASHED = 0x002, + + /* + cleared in HandleSignaledProcess when + - process goes from CRASHED to any other state + set in HandleSignaledProcess when + - process crashes + adds process to GetDebugProcessIds + */ + PROCESSFLAGS_CRASH_DEBUG = 0x004, + + /* + set in HandleProcessLaunch when + - launch_flags has LAUNCHFLAGS_NOTIFYDEBUGEVENTS set + - and (we're 1.0.0 or program_info.application_type & 4) (is this because 1.0.0 doesn't check?) + signals g_process_event in HandleSignaledProcess when + - process enters DebugDetached state + signals g_process_event in HandleSignaledProcess when + - process enters Running state + */ + PROCESSFLAGS_NOTIFYDEBUGEVENTS = 0x008, + + /* + set in HandleSignaledProcess when + - process enters DebugDetached state + - and PROCESSFLAGS_NOTIFYDEBUGEVENTS is set + set in HandleSignaledProcess when + - process enters Running state + - and PROCESSFLAGS_NOTIFYDEBUGEVENTS is set + set in HandleSignaledProcess when + - process enters DebugSuspended state + - and PROCESSFLAGS_NOTIFYDEBUGEVENTS is set + causes some complicated ProcessEvent (one-shot) + */ + PROCESSFLAGS_DEBUGEVENTPENDING = 0x010, + + /* + cleared in HandleSignaledProcess when + - process enters DebugDetached state + - and PROCESSFLAGS_NOTIFYDEBUGEVENTS is set + cleared in HandleSignaledProcess when + - process enters Running state + - and PROCESSFLAGS_NOTIFYDEBUGEVENTS is set + set in HandleSignaledProcess when + - process enters DebugSuspended state + - and PROCESSFLAGS_NOTIFYDEBUGEVENTS is set + */ + PROCESSFLAGS_DEBUGSUSPENDED = 0x020, + + /* + set in HandleProcessLaunch when + - program_info.application_type & 1 + signals g_debug_application_event in HandleProcessLaunch when + - g_debug_next_application is set (unsets g_debug_next_application) + causes HasApplicationProcess to return true + meaning? + application + */ + PROCESSFLAGS_APPLICATION = 0x040, + + /* + set in HandleProcessLaunch when + - we're above 2.0.0 (creport related?) + - and launch_flags has LAUNCHFLAGS_NOTIFYDEBUGSPECIAL set + - and program_info.application_type & 4 + tested in HandleSignaledProcess when + - process enters DebugDetached state + - and we're above 2.0.0 + causes + - clearing of PROCESSFLAGS_NOTIFYDEBUGSPECIAL (one-shot?) + - setting of PROCESSFLAGS_DEBUGDETACHED + */ + PROCESSFLAGS_NOTIFYDEBUGSPECIAL = 0x080, + + /* + set in HandleSignaledProcess when + - process enters DebugDetached state + - and we're above 2.0.0 + - and PROCESSFLAGS_NOTIFYDEBUGSPECIAL was set + causes ProcessEventType 5 ([5.0.0+] 2) (one-shot) + */ + PROCESSFLAGS_DEBUGDETACHED = 0x100, +}; + +enum { + PROCESSEVENTTYPE_CRASH = 1, + PROCESSEVENTTYPE_EXIT = 2, // only fired once, when process enters DebugDetached state (likely creport related) + PROCESSEVENTTYPE_RUNNING = 3, // debug detached or running + PROCESSEVENTTYPE_SUSPENDED = 4, // debug suspended + PROCESSEVENTTYPE_DEBUGDETACHED = 5, + + + PROCESSEVENTTYPE_500_EXIT = 1, + PROCESSEVENTTYPE_500_DEBUGDETACHED = 2, // only fired once, when process enters DebugDetached state (likely creport related) + PROCESSEVENTTYPE_500_CRASH = 3, + PROCESSEVENTTYPE_500_RUNNING = 4, // debug detached or running + PROCESSEVENTTYPE_500_SUSPENDED = 5, // debug suspended +}; + class Registration { public: struct TidSid { diff --git a/stratosphere/pm/source/pm_shell.cpp b/stratosphere/pm/source/pm_shell.cpp index d09807eb8..ffdab1bd6 100644 --- a/stratosphere/pm/source/pm_shell.cpp +++ b/stratosphere/pm/source/pm_shell.cpp @@ -140,7 +140,7 @@ std::tuple ShellService::clear_process_notification_flag(u64 pid) { std::shared_ptr proc = Registration::GetProcess(pid); if (proc != NULL) { - proc->flags &= ~2; + proc->flags &= ~PROCESSFLAGS_CRASHED; return {0x0}; } else { return {0x20F}; From 9f160627670596fb2578f29980c03145010d876f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 02:23:53 -0700 Subject: [PATCH 012/489] PM: Embed boot2 logic in PM. --- stratosphere/boot2/Makefile | 185 ------------------ .../boot2_main.cpp => pm/source/pm_boot2.cpp} | 90 ++------- stratosphere/pm/source/pm_boot2.hpp | 10 + stratosphere/pm/source/pm_shell.cpp | 4 +- 4 files changed, 30 insertions(+), 259 deletions(-) delete mode 100644 stratosphere/boot2/Makefile rename stratosphere/{boot2/source/boot2_main.cpp => pm/source/pm_boot2.cpp} (60%) create mode 100644 stratosphere/pm/source/pm_boot2.hpp diff --git a/stratosphere/boot2/Makefile b/stratosphere/boot2/Makefile deleted file mode 100644 index 74ee33781..000000000 --- a/stratosphere/boot2/Makefile +++ /dev/null @@ -1,185 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") -endif - -TOPDIR ?= $(CURDIR) -include $(DEVKITPRO)/libnx/switch_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". -# -# NO_ICON: if set to anything, do not use icon. -# NO_NACP: if set to anything, no .nacp file is generated. -# APP_TITLE is the name of the app stored in the .nacp file (Optional) -# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) -# APP_VERSION is the version of the app stored in the .nacp file (Optional) -# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) -# ICON is the filename of the icon (.jpg), relative to the project folder. -# If not set, it attempts to use one of the following (in this order): -# - .jpg -# - icon.jpg -# - /default_icon.jpg -#--------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := source -DATA := data -INCLUDES := include -EXEFS_SRC := exefs_src - -DEFINES := -DDISABLE_IPC - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE - -CFLAGS := -g -Wall -O2 -ffunction-sections \ - $(ARCH) $(DEFINES) - -CFLAGS += $(INCLUDE) -D__SWITCH__ - -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -LIBS := -lstratosphere -lnx - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(LIBNX) $(CURDIR)/../libstratosphere - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES := $(addsuffix .o,$(BINFILES)) \ - $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) - -ifeq ($(strip $(ICON)),) - icons := $(wildcard *.jpg) - ifneq (,$(findstring $(TARGET).jpg,$(icons))) - export APP_ICON := $(TOPDIR)/$(TARGET).jpg - else - ifneq (,$(findstring icon.jpg,$(icons))) - export APP_ICON := $(TOPDIR)/icon.jpg - endif - endif -else - export APP_ICON := $(TOPDIR)/$(ICON) -endif - -ifeq ($(strip $(NO_ICON)),) - export NROFLAGS += --icon=$(APP_ICON) -endif - -ifeq ($(strip $(NO_NACP)),) - export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp -endif - -ifneq ($(APP_TITLEID),) - export NACPFLAGS += --titleid=$(APP_TITLEID) -endif - -.PHONY: $(BUILD) clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf - - -#--------------------------------------------------------------------------------- -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -all : $(OUTPUT).pfs0 $(OUTPUT).nro - -$(OUTPUT).pfs0 : $(OUTPUT).nso - -$(OUTPUT).nso : $(OUTPUT).elf - -ifeq ($(strip $(NO_NACP)),) -$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp -else -$(OUTPUT).nro : $(OUTPUT).elf -endif - -$(OUTPUT).elf : $(OFILES) - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/stratosphere/boot2/source/boot2_main.cpp b/stratosphere/pm/source/pm_boot2.cpp similarity index 60% rename from stratosphere/boot2/source/boot2_main.cpp rename to stratosphere/pm/source/pm_boot2.cpp index 998a22ce8..f3995ebaa 100644 --- a/stratosphere/boot2/source/boot2_main.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -5,61 +5,13 @@ #include #include +#include "pm_boot2.hpp" +#include "pm_registration.hpp" -#define PMC_BASE 0x7000E400 - -extern "C" { - extern u32 __start__; - - u32 __nx_applet_type = AppletType_None; - - #define INNER_HEAP_SIZE 0x200000 - size_t nx_inner_heap_size = INNER_HEAP_SIZE; - char nx_inner_heap[INNER_HEAP_SIZE]; - - void __libnx_initheap(void); - void __appInit(void); - void __appExit(void); -} - -void __libnx_initheap(void) { - void* addr = nx_inner_heap; - size_t size = nx_inner_heap_size; - - /* Newlib */ - extern char* fake_heap_start; - extern char* fake_heap_end; - - fake_heap_start = (char*)addr; - fake_heap_end = (char*)addr + size; -} - -void __appInit(void) { - Result rc; - - rc = smInitialize(); - if (R_FAILED(rc)) - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); - - rc = fsInitialize(); - if (R_FAILED(rc)) - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); - - rc = pmshellInitialize(); - if (R_FAILED(rc)) - fatalSimple(0xCAFE << 4 | 1); -} - -void __appExit(void) { - /* Cleanup services. */ - pmshellExit(); - fsExit(); - smExit(); -} - -void LaunchTitle(u64 title_id, u64 storage_id, u32 launch_flags, u64 *pid) { +static void LaunchTitle(u64 title_id, FsStorageId storage_id, u32 launch_flags, u64 *pid) { u64 local_pid; - Result rc = pmshellLaunchProcess(launch_flags, title_id, storage_id, &local_pid); + + Result rc = Registration::LaunchProcessByTidSid(Registration::TidSid{title_id, storage_id}, launch_flags, &local_pid); switch (rc) { case 0xCE01: /* Out of resource! */ @@ -82,7 +34,7 @@ void LaunchTitle(u64 title_id, u64 storage_id, u32 launch_flags, u64 *pid) { } } -bool ShouldForceMaintenanceMode() { +static bool ShouldForceMaintenanceMode() { /* TODO: Contact set:sys, retrieve boot!force_maintenance, read plus/minus buttons. */ return false; } @@ -128,34 +80,28 @@ static const std::tuple g_additional_launch_programs[] = { {0x0100000000000035, true}, /* grc */ }; -int main(int argc, char **argv) -{ - consoleDebugInit(debugDevice_SVC); - - /* NOTE: Order for initial programs is modified. */ - /* This is to launch things required for Loader to mount SD card ASAP. */ +void EmbeddedBoot2::Main() { + /* TODO: Modify initial program launch order, to get SD card mounted faster. */ /* Launch psc. */ - LaunchTitle(0x0100000000000021, 3, 0, NULL); - /* Launch bus. */ - LaunchTitle(0x010000000000000A, 3, 0, NULL); - /* Launch pcv. */ - LaunchTitle(0x010000000000001A, 3, 0, NULL); + LaunchTitle(0x0100000000000021, FsStorageId_NandSystem, 0, NULL); /* Launch settings. */ - LaunchTitle(0x0100000000000009, 3, 0, NULL); + LaunchTitle(0x0100000000000009, FsStorageId_NandSystem, 0, NULL); /* Launch usb. */ - LaunchTitle(0x0100000000000006, 3, 0, NULL); + LaunchTitle(0x0100000000000006, FsStorageId_NandSystem, 0, NULL); /* Launch pcie. */ - LaunchTitle(0x010000000000001D, 3, 0, NULL); + LaunchTitle(0x010000000000001D, FsStorageId_NandSystem, 0, NULL); + /* Launch bus. */ + LaunchTitle(0x010000000000000A, FsStorageId_NandSystem, 0, NULL); /* Launch tma. */ - LaunchTitle(0x0100000000000007, 3, 0, NULL); + LaunchTitle(0x0100000000000007, FsStorageId_NandSystem, 0, NULL); + /* Launch pcv. */ + LaunchTitle(0x010000000000001A, FsStorageId_NandSystem, 0, NULL); bool maintenance = ShouldForceMaintenanceMode(); for (auto &launch_program : g_additional_launch_programs) { if (!maintenance || std::get(launch_program)) { - LaunchTitle(std::get(launch_program), 3, 0, NULL); + LaunchTitle(std::get(launch_program), FsStorageId_NandSystem, 0, NULL); } } - - return 0; } diff --git a/stratosphere/pm/source/pm_boot2.hpp b/stratosphere/pm/source/pm_boot2.hpp new file mode 100644 index 000000000..20d2a19b5 --- /dev/null +++ b/stratosphere/pm/source/pm_boot2.hpp @@ -0,0 +1,10 @@ +#pragma once + +enum class TitleId : u64 { + x = 0UL, +}; + +class EmbeddedBoot2 { + public: + static void Main(); +}; \ No newline at end of file diff --git a/stratosphere/pm/source/pm_shell.cpp b/stratosphere/pm/source/pm_shell.cpp index ffdab1bd6..78b72a86f 100644 --- a/stratosphere/pm/source/pm_shell.cpp +++ b/stratosphere/pm/source/pm_shell.cpp @@ -3,6 +3,7 @@ #include "pm_registration.hpp" #include "pm_resource_limits.hpp" #include "pm_shell.hpp" +#include "pm_boot2.hpp" static bool g_has_boot_finished = false; @@ -148,10 +149,9 @@ std::tuple ShellService::clear_process_notification_flag(u64 pid) { } std::tuple ShellService::notify_boot_finished() { - u64 boot2_pid; if (!g_has_boot_finished) { g_has_boot_finished = true; - return {Registration::LaunchProcess(BOOT2_TITLE_ID, FsStorageId_NandSystem, 0, &boot2_pid)}; + EmbeddedBoot2::Main(); } return {0}; } From c0798031896d7c2b746d1ba052af745947a6bff3 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 02:37:45 -0700 Subject: [PATCH 013/489] PM: Use enum in EmbeddedBoot2 --- stratosphere/pm/source/pm_boot2.cpp | 98 ++++++++++++++--------------- stratosphere/pm/source/pm_boot2.hpp | 62 +++++++++++++++++- 2 files changed, 109 insertions(+), 51 deletions(-) diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index f3995ebaa..b40200b14 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -8,10 +8,10 @@ #include "pm_boot2.hpp" #include "pm_registration.hpp" -static void LaunchTitle(u64 title_id, FsStorageId storage_id, u32 launch_flags, u64 *pid) { +static void LaunchTitle(Boot2KnownTitleId title_id, FsStorageId storage_id, u32 launch_flags, u64 *pid) { u64 local_pid; - Result rc = Registration::LaunchProcessByTidSid(Registration::TidSid{title_id, storage_id}, launch_flags, &local_pid); + Result rc = Registration::LaunchProcessByTidSid(Registration::TidSid{(u64)title_id, storage_id}, launch_flags, &local_pid); switch (rc) { case 0xCE01: /* Out of resource! */ @@ -39,69 +39,69 @@ static bool ShouldForceMaintenanceMode() { return false; } -static const std::tuple g_additional_launch_programs[] = { - {0x0100000000000023, true}, /* am */ - {0x0100000000000019, true}, /* nvservices */ - {0x010000000000001C, true}, /* nvnflinger */ - {0x010000000000002D, true}, /* vi */ - {0x010000000000001F, true}, /* ns */ - {0x0100000000000015, true}, /* lm */ - {0x010000000000001B, true}, /* ppc */ - {0x0100000000000010, true}, /* ptm */ - {0x0100000000000013, true}, /* hid */ - {0x0100000000000014, true}, /* audio */ - {0x0100000000000029, true}, /* lbl */ - {0x0100000000000016, true}, /* wlan */ - {0x010000000000000B, true}, /* bluetooth */ - {0x0100000000000012, true}, /* bsdsockets */ - {0x010000000000000F, true}, /* nifm */ - {0x0100000000000018, true}, /* ldn */ - {0x010000000000001E, true}, /* account */ - {0x010000000000000E, false}, /* friends */ - {0x0100000000000020, true}, /* nfc */ - {0x010000000000003C, true}, /* jpegdec */ - {0x0100000000000022, true}, /* capsrv */ - {0x0100000000000024, true}, /* ssl */ - {0x0100000000000025, true}, /* nim */ - {0x010000000000000C, false}, /* bcat */ - {0x010000000000002B, true}, /* erpt */ - {0x0100000000000033, true}, /* es */ - {0x010000000000002E, true}, /* pctl */ - {0x010000000000002A, true}, /* btm */ - {0x0100000000000030, false}, /* eupld */ - {0x0100000000000031, true}, /* glue */ - {0x0100000000000032, true}, /* eclct */ - {0x010000000000002F, false}, /* npns */ - {0x0100000000000034, true}, /* fatal */ - {0x0100000000000037, true}, /* ro */ - {0x0100000000000038, true}, /* doesn't exist on retail systems */ - {0x0100000000000039, true}, /* sdb */ - {0x010000000000003A, true}, /* migration */ - {0x0100000000000035, true}, /* grc */ +static const std::tuple g_additional_launch_programs[] = { + {Boot2KnownTitleId::am, true}, /* am */ + {Boot2KnownTitleId::nvservices, true}, /* nvservices */ + {Boot2KnownTitleId::nvnflinger, true}, /* nvnflinger */ + {Boot2KnownTitleId::vi, true}, /* vi */ + {Boot2KnownTitleId::ns, true}, /* ns */ + {Boot2KnownTitleId::lm, true}, /* lm */ + {Boot2KnownTitleId::ppc, true}, /* ppc */ + {Boot2KnownTitleId::ptm, true}, /* ptm */ + {Boot2KnownTitleId::hid, true}, /* hid */ + {Boot2KnownTitleId::audio, true}, /* audio */ + {Boot2KnownTitleId::lbl, true}, /* lbl */ + {Boot2KnownTitleId::wlan, true}, /* wlan */ + {Boot2KnownTitleId::bluetooth, true}, /* bluetooth */ + {Boot2KnownTitleId::bsdsockets, true}, /* bsdsockets */ + {Boot2KnownTitleId::nifm, true}, /* nifm */ + {Boot2KnownTitleId::ldn, true}, /* ldn */ + {Boot2KnownTitleId::account, true}, /* account */ + {Boot2KnownTitleId::friends, false}, /* friends */ + {Boot2KnownTitleId::nfc, true}, /* nfc */ + {Boot2KnownTitleId::jpegdec, true}, /* jpegdec */ + {Boot2KnownTitleId::capsrv, true}, /* capsrv */ + {Boot2KnownTitleId::ssl, true}, /* ssl */ + {Boot2KnownTitleId::nim, true}, /* nim */ + {Boot2KnownTitleId::bcat, false}, /* bcat */ + {Boot2KnownTitleId::erpt, true}, /* erpt */ + {Boot2KnownTitleId::es, true}, /* es */ + {Boot2KnownTitleId::pctl, true}, /* pctl */ + {Boot2KnownTitleId::btm, true}, /* btm */ + {Boot2KnownTitleId::eupld, false}, /* eupld */ + {Boot2KnownTitleId::glue, true}, /* glue */ + {Boot2KnownTitleId::eclct, true}, /* eclct */ + {Boot2KnownTitleId::npns, false}, /* npns */ + {Boot2KnownTitleId::fatal, true}, /* fatal */ + {Boot2KnownTitleId::ro, true}, /* ro */ + {Boot2KnownTitleId::profiler, true}, /* profiler */ + {Boot2KnownTitleId::sdb, true}, /* sdb */ + {Boot2KnownTitleId::migration, true}, /* migration */ + {Boot2KnownTitleId::grc, true}, /* grc */ }; void EmbeddedBoot2::Main() { /* TODO: Modify initial program launch order, to get SD card mounted faster. */ /* Launch psc. */ - LaunchTitle(0x0100000000000021, FsStorageId_NandSystem, 0, NULL); + LaunchTitle(Boot2KnownTitleId::psc, FsStorageId_NandSystem, 0, NULL); /* Launch settings. */ - LaunchTitle(0x0100000000000009, FsStorageId_NandSystem, 0, NULL); + LaunchTitle(Boot2KnownTitleId::settings, FsStorageId_NandSystem, 0, NULL); /* Launch usb. */ - LaunchTitle(0x0100000000000006, FsStorageId_NandSystem, 0, NULL); + LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); /* Launch pcie. */ - LaunchTitle(0x010000000000001D, FsStorageId_NandSystem, 0, NULL); + LaunchTitle(Boot2KnownTitleId::pcie, FsStorageId_NandSystem, 0, NULL); /* Launch bus. */ - LaunchTitle(0x010000000000000A, FsStorageId_NandSystem, 0, NULL); + LaunchTitle(Boot2KnownTitleId::bus, FsStorageId_NandSystem, 0, NULL); /* Launch tma. */ - LaunchTitle(0x0100000000000007, FsStorageId_NandSystem, 0, NULL); + LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_NandSystem, 0, NULL); /* Launch pcv. */ - LaunchTitle(0x010000000000001A, FsStorageId_NandSystem, 0, NULL); + LaunchTitle(Boot2KnownTitleId::pcv, FsStorageId_NandSystem, 0, NULL); bool maintenance = ShouldForceMaintenanceMode(); for (auto &launch_program : g_additional_launch_programs) { if (!maintenance || std::get(launch_program)) { - LaunchTitle(std::get(launch_program), FsStorageId_NandSystem, 0, NULL); + LaunchTitle(std::get(launch_program), FsStorageId_NandSystem, 0, NULL); } } } diff --git a/stratosphere/pm/source/pm_boot2.hpp b/stratosphere/pm/source/pm_boot2.hpp index 20d2a19b5..2aa1e593e 100644 --- a/stratosphere/pm/source/pm_boot2.hpp +++ b/stratosphere/pm/source/pm_boot2.hpp @@ -1,7 +1,65 @@ #pragma once -enum class TitleId : u64 { - x = 0UL, +enum class Boot2KnownTitleId : u64 { + fs = 0x0100000000000000UL, + loader = 0x0100000000000001UL, + ncm = 0x0100000000000002UL, + pm = 0x0100000000000003UL, + sm = 0x0100000000000004UL, + boot = 0x0100000000000005UL, + usb = 0x0100000000000006UL, + tma = 0x0100000000000007UL, + boot2 = 0x0100000000000008UL, + settings = 0x0100000000000009UL, + bus = 0x010000000000000AUL, + bluetooth = 0x010000000000000BUL, + bcat = 0x010000000000000CUL, + dmnt = 0x010000000000000DUL, + friends = 0x010000000000000EUL, + nifm = 0x010000000000000FUL, + ptm = 0x0100000000000010UL, + shell = 0x0100000000000011UL, + bsdsockets = 0x0100000000000012UL, + hid = 0x0100000000000013UL, + audio = 0x0100000000000014UL, + lm = 0x0100000000000015UL, + wlan = 0x0100000000000016UL, + cs = 0x0100000000000017UL, + ldn = 0x0100000000000018UL, + nvservices = 0x0100000000000019UL, + pcv = 0x010000000000001AUL, + ppc = 0x010000000000001BUL, + nvnflinger = 0x010000000000001CUL, + pcie = 0x010000000000001DUL, + account = 0x010000000000001EUL, + ns = 0x010000000000001FUL, + nfc = 0x0100000000000020UL, + psc = 0x0100000000000021UL, + capsrv = 0x0100000000000022UL, + am = 0x0100000000000023UL, + ssl = 0x0100000000000024UL, + nim = 0x0100000000000025UL, + spl = 0x0100000000000028UL, + lbl = 0x0100000000000029UL, + btm = 0x010000000000002AUL, + erpt = 0x010000000000002BUL, + vi = 0x010000000000002DUL, + pctl = 0x010000000000002EUL, + npns = 0x010000000000002FUL, + eupld = 0x0100000000000030UL, + glue = 0x0100000000000031UL, + eclct = 0x0100000000000032UL, + es = 0x0100000000000033UL, + fatal = 0x0100000000000034UL, + grc = 0x0100000000000035UL, + creport = 0x0100000000000036UL, + ro = 0x0100000000000037UL, + profiler = 0x0100000000000038UL, + sdb = 0x0100000000000039UL, + migration = 0x010000000000003AUL, + jit = 0x010000000000003BUL, + jpegdec = 0x010000000000003CUL, + safemode = 0x010000000000003DUL, }; class EmbeddedBoot2 { From 2667266aad09e8bd321ba99e7bdc599b2bb6e777 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 03:22:06 -0700 Subject: [PATCH 014/489] pm.boot2: Skeleton hook for SD-mandated launches --- stratosphere/pm/source/pm_boot2.cpp | 45 ++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index b40200b14..13b7eddb6 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -80,28 +80,57 @@ static const std::tuple g_additional_launch_programs[] {Boot2KnownTitleId::grc, true}, /* grc */ }; +static void MountSdCard() { + Handle tmp_hnd = 0; + static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:c"}; + for (unsigned int i = 0; i < sizeof(required_active_services) / sizeof(required_active_services[0]); i++) { + if (R_FAILED(smGetServiceOriginal(&tmp_hnd, smEncodeName(required_active_services[i])))) { + /* TODO: Panic */ + } else { + svcCloseHandle(tmp_hnd); + } + } + fsdevMountSdmc(); +} + void EmbeddedBoot2::Main() { - /* TODO: Modify initial program launch order, to get SD card mounted faster. */ - + /* psc, bus, pcv is the minimal set of required titles to get SD card. */ + /* bus depends on pcie, and pcv depends on settings. */ /* Launch psc. */ LaunchTitle(Boot2KnownTitleId::psc, FsStorageId_NandSystem, 0, NULL); - /* Launch settings. */ - LaunchTitle(Boot2KnownTitleId::settings, FsStorageId_NandSystem, 0, NULL); - /* Launch usb. */ - LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); /* Launch pcie. */ LaunchTitle(Boot2KnownTitleId::pcie, FsStorageId_NandSystem, 0, NULL); /* Launch bus. */ LaunchTitle(Boot2KnownTitleId::bus, FsStorageId_NandSystem, 0, NULL); - /* Launch tma. */ - LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_NandSystem, 0, NULL); + /* Launch settings. */ + LaunchTitle(Boot2KnownTitleId::settings, FsStorageId_NandSystem, 0, NULL); /* Launch pcv. */ LaunchTitle(Boot2KnownTitleId::pcv, FsStorageId_NandSystem, 0, NULL); + /* At this point, the SD card can be mounted. */ + MountSdCard(); + + /* Launch usb. */ + LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); + /* Launch tma. */ + LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_NandSystem, 0, NULL); + + /* Launch default programs. */ bool maintenance = ShouldForceMaintenanceMode(); for (auto &launch_program : g_additional_launch_programs) { if (!maintenance || std::get(launch_program)) { LaunchTitle(std::get(launch_program), FsStorageId_NandSystem, 0, NULL); } } + + /* Allow for user-customizable programs. */ + FILE *f_boot2 = fopen("sdmc:/atmosphere/boot2.txt", "rb"); + if (f_boot2 != NULL) { + /* TODO: Parse Title Id/Storage ID pairs, and launch them. */ + + fclose(f_boot2); + } + + /* We no longer need the SD card. */ + fsdevUnmountAll(); } From 5a63f4e30420003958e559e455f4ed45e96df4d7 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 19:34:22 -0700 Subject: [PATCH 015/489] PM: Make boot2 launch SD card content with StorageId_None --- stratosphere/pm/source/pm_boot2.cpp | 38 +++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 13b7eddb6..e1aee4c4b 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include #include @@ -8,6 +10,19 @@ #include "pm_boot2.hpp" #include "pm_registration.hpp" +static bool IsHexadecimal(const char *str) { + while (*str) { + if (('0' <= *str && *str <= '9') || + ('a' <= *str && *str <= 'f') || + ('A' <= *str && *str <= 'F')) { + str++; + } else { + return false; + } + } + return true; +} + static void LaunchTitle(Boot2KnownTitleId title_id, FsStorageId storage_id, u32 launch_flags, u64 *pid) { u64 local_pid; @@ -124,11 +139,24 @@ void EmbeddedBoot2::Main() { } /* Allow for user-customizable programs. */ - FILE *f_boot2 = fopen("sdmc:/atmosphere/boot2.txt", "rb"); - if (f_boot2 != NULL) { - /* TODO: Parse Title Id/Storage ID pairs, and launch them. */ - - fclose(f_boot2); + DIR *titles_dir = opendir("sdmc:/atmosphere/titles"); + struct dirent *ent; + if (titles_dir != NULL) { + while ((ent = readdir(titles_dir)) != NULL) { + if (strlen(ent->d_name) == 0x10 && IsHexadecimal(ent->d_name)) { + u64 title_id = strtoul(ent->d_name, NULL, 16); + char title_path[FS_MAX_PATH] = {0}; + strcpy(title_path, "sdmc:/atmosphere/titles/"); + strcat(title_path, ent->d_name); + strcat(title_path, "/boot2.flag"); + FILE *f_flag = fopen(title_path, "rb"); + if (f_flag != NULL) { + fclose(f_flag); + LaunchTitle((Boot2KnownTitleId)title_id, FsStorageId_None, 0, NULL); + } + } + } + closedir(titles_dir); } /* We no longer need the SD card. */ From b365065a2d9048eb4a3263690769bcf0ec34322d Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 19:53:20 -0700 Subject: [PATCH 016/489] Loader: Support loading FsStorageId_None content from SD. --- .../loader/source/ldr_content_management.cpp | 1 + .../loader/source/ldr_process_creation.cpp | 10 ++++--- .../loader/source/ldr_process_manager.cpp | 27 ++++++++++++------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 29487b327..4424441e1 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -44,6 +44,7 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { fsdevMountDevice("code", g_CodeFileSystem); + fsldrExit(); return rc; } diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 56ba05af2..b8f9c71c4 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -102,9 +102,11 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc } /* Mount the title's exefs. */ - rc = ContentManagement::MountCodeForTidSid(&target_process->tid_sid); - if (R_FAILED(rc)) { - return rc; + if (target_process->tid_sid.storage_id != FsStorageId_None) { + rc = ContentManagement::MountCodeForTidSid(&target_process->tid_sid); + if (R_FAILED(rc)) { + return rc; + } } /* Load the process's NPDM. */ @@ -191,7 +193,7 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc rc = 0; CREATE_PROCESS_END: - if (R_SUCCEEDED(rc)) { + if (R_SUCCEEDED(rc) && target_process->tid_sid.storage_id != FsStorageId_None) { rc = ContentManagement::UnmountCode(); } else { ContentManagement::UnmountCode(); diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index 2ea5bd03b..55511f56c 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -42,10 +42,13 @@ std::tuple ProcessManagerService::create_process(u64 flags, return {rc, MovedHandle{process_h}}; } - rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid); - if (R_FAILED(rc)) { - return {rc, MovedHandle{process_h}}; + if (tid_sid.storage_id != FsStorageId_None) { + rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid); + if (R_FAILED(rc)) { + return {rc, MovedHandle{process_h}}; + } } + launch_item = LaunchQueue::get_item(tid_sid.title_id); @@ -70,7 +73,7 @@ std::tuple ProcessManagerService::get_program_info(Registration::TidSid return {rc}; } - if (tid_sid.title_id != out_program_info.pointer->title_id) { + if (tid_sid.storage_id != FsStorageId_None && tid_sid.title_id != out_program_info.pointer->title_id) { rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid); if (R_FAILED(rc)) { return {rc}; @@ -109,17 +112,23 @@ Result ProcessManagerService::populate_program_info_buffer(ProcessManagerService NpdmUtils::NpdmInfo info; Result rc; - rc = ContentManagement::MountCodeForTidSid(tid_sid); - if (R_FAILED(rc)) { - return rc; + if (tid_sid->storage_id != FsStorageId_None) { + rc = ContentManagement::MountCodeForTidSid(tid_sid); + if (R_FAILED(rc)) { + return rc; + } } rc = NpdmUtils::LoadNpdm(tid_sid->title_id, &info); + + if (tid_sid->storage_id != FsStorageId_None) { + ContentManagement::UnmountCode(); + } + if (R_FAILED(rc)) { return rc; } - - ContentManagement::UnmountCode(); + out->main_thread_priority = info.header->main_thread_prio; out->default_cpu_id = info.header->default_cpuid; From 2a6348cd738160441c73fae49b1279551f44c991 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 19:57:32 -0700 Subject: [PATCH 017/489] creport: add fsp-srv access to npdm --- stratosphere/creport/creport.json | 1 + 1 file changed, 1 insertion(+) diff --git a/stratosphere/creport/creport.json b/stratosphere/creport/creport.json index 4ea55edbd..fc94da978 100644 --- a/stratosphere/creport/creport.json +++ b/stratosphere/creport/creport.json @@ -19,6 +19,7 @@ "erpt:c": false, "fatal:u": false, "ns:dev": false, + "fsp-srv": false, "time:s": true }, "kernel_capabilities": { From 5993614c2e570d442ecdeae6f42cfa93f56a4978 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 20:15:06 -0700 Subject: [PATCH 018/489] fs.mitm: Try to MitM titles that have override RomFS content on the SD card --- stratosphere/fs_mitm/source/fsmitm_service.hpp | 8 +++++++- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 16 ++++++++++++++++ stratosphere/fs_mitm/source/fsmitm_utils.hpp | 2 ++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 6e565f69d..8ebe9cba9 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -3,6 +3,7 @@ #include #include "imitmserviceobject.hpp" #include "fs_istorage.hpp" +#include "fsmitm_utils.hpp" enum class FspSrvCmd { SetCurrentProcess = 1, @@ -21,7 +22,12 @@ class FsMitMService : public IMitMServiceObject { } static bool should_mitm(u64 pid, u64 tid) { - return tid >= 0x0100000000010000ULL; + if (tid >= 0x0100000000010000ULL) { + return true; + } + bool has_romfs_content; + Result rc = Utils::HasSdRomfsContent(tid, &has_romfs_content); + return R_SUCCEEDED(rc) && has_romfs_content; } FsMitMService *clone() override { diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 90e310a35..720dcac4f 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -121,3 +121,19 @@ Result Utils::OpenRomFSDir(FsFileSystem *fs, u64 title_id, const char *path, FsD } return fsFsOpenDirectory(fs, safe_path, FS_DIROPEN_DIRECTORY | FS_DIROPEN_FILE, out); } + +Result Utils::HasSdRomfsContent(u64 title_id, bool *out) { + Result rc; + FsDir dir; + if (R_FAILED((rc = Utils::OpenRomFSSdDir(title_id, "", &dir)))) { + return rc; + } + + FsDirectoryEntry dir_entry; + u64 read_entries; + if (R_SUCCEEDED((rc = fsDirRead(&dir, 0, &read_entries, 1, &dir_entry)))) { + *out = (read_entries == 1); + } + fsDirClose(&dir); + return rc; +} \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index d14cbd764..a301fbcc9 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -15,4 +15,6 @@ class Utils { static Result OpenRomFSFile(FsFileSystem *fs, u64 title_id, const char *fn, int flags, FsFile *out); static Result OpenRomFSDir(FsFileSystem *fs, u64 title_id, const char *path, FsDir *out); + + static Result HasSdRomfsContent(u64 title_id, bool *out); }; \ No newline at end of file From a811b447ce84e09d951766829cc64a339df6f6c7 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Jul 2018 20:34:09 -0700 Subject: [PATCH 019/489] creport: Pretty-print addresses whenever possible. --- stratosphere/creport/source/creport_code_info.cpp | 13 +++++++++++++ stratosphere/creport/source/creport_code_info.hpp | 4 ++++ .../creport/source/creport_crash_report.cpp | 11 ++++++----- .../creport/source/creport_crash_report.hpp | 2 +- stratosphere/creport/source/creport_thread_info.cpp | 12 ++++++------ stratosphere/creport/source/creport_thread_info.hpp | 8 ++++++++ 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index ba7ceb12c..c57a44df1 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -125,4 +125,17 @@ void CodeList::GetCodeInfoBuildId(u64 debug_handle, u64 rodata_addr, u8 *build_i memcpy(build_id, last_pages + ofs + 4, 0x20); } } +} + + +const char *CodeList::GetFormattedAddressString(u64 address) { + memset(this->address_str_buf, 0, sizeof(this->address_str_buf)); + for (unsigned int i = 0; i < this->code_count; i++) { + if (this->code_infos[i].start_address <= address && address < this->code_infos[i].end_address) { + snprintf(this->address_str_buf, sizeof(this->address_str_buf) - 1, "%016lx (%s + 0x%lx)", address, this->code_infos[i].name, address - this->code_infos[i].start_address); + return this->address_str_buf; + } + } + snprintf(this->address_str_buf, sizeof(this->address_str_buf) - 1, "%016lx", address); + return this->address_str_buf; } \ No newline at end of file diff --git a/stratosphere/creport/source/creport_code_info.hpp b/stratosphere/creport/source/creport_code_info.hpp index f10834f3d..18aa17b23 100644 --- a/stratosphere/creport/source/creport_code_info.hpp +++ b/stratosphere/creport/source/creport_code_info.hpp @@ -16,8 +16,12 @@ class CodeList { static const size_t max_code_count = 0x10; u32 code_count = 0; CodeInfo code_infos[max_code_count]; + + /* For pretty-printing. */ + char address_str_buf[0x280]; public: void ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr); + const char *GetFormattedAddressString(u64 address); void SaveToFile(FILE *f_report); private: bool TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address); diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 34873bc48..cf396ecc5 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -15,6 +15,7 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR()); this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); } + this->thread_list.SetCodeList(&this->code_list); if (IsApplication()) { ProcessDyingMessage(); @@ -242,7 +243,7 @@ void CrashReport::SaveReport() { void CrashReport::SaveToFile(FILE *f_report) { char buf[0x10] = {0}; - fprintf(f_report, "Atmosphère Crash Report (v1.0):\n"); + fprintf(f_report, "Atmosphère Crash Report (v1.1):\n"); fprintf(f_report, "Result: 0x%X (2%03d-%04d)\n\n", this->result, R_MODULE(this->result), R_DESCRIPTION(this->result)); /* Process Info. */ @@ -253,12 +254,12 @@ void CrashReport::SaveToFile(FILE *f_report) { fprintf(f_report, " Process ID: %016lx\n", this->process_info.process_id); fprintf(f_report, " Process Flags: %08x\n", this->process_info.flags); if (kernelAbove500()) { - fprintf(f_report, " User Exception Address: %016lx\n", this->process_info.user_exception_context_address); + fprintf(f_report, " User Exception Address: %s\n", this->code_list.GetFormattedAddressString(this->process_info.user_exception_context_address)); } fprintf(f_report, "Exception Info:\n"); fprintf(f_report, " Type: %s\n", GetDebugExceptionTypeStr(this->exception_info.type)); - fprintf(f_report, " Address: %016lx\n", this->exception_info.address); + fprintf(f_report, " Address: %s\n", this->code_list.GetFormattedAddressString(this->exception_info.address)); switch (this->exception_info.type) { case DebugExceptionType::UndefinedInstruction: fprintf(f_report, " Opcode: %08x\n", this->exception_info.specific.undefined_instruction.insn); @@ -266,7 +267,7 @@ void CrashReport::SaveToFile(FILE *f_report) { case DebugExceptionType::DataAbort: case DebugExceptionType::AlignmentFault: if (this->exception_info.specific.raw != this->exception_info.address) { - fprintf(f_report, " Fault Address: %016lx\n", this->exception_info.specific.raw); + fprintf(f_report, " Fault Address: %s\n", this->code_list.GetFormattedAddressString(this->exception_info.specific.raw)); } break; case DebugExceptionType::BadSvc: @@ -282,7 +283,7 @@ void CrashReport::SaveToFile(FILE *f_report) { if (kernelAbove500()) { if (this->dying_message_size) { fprintf(f_report, "Dying Message Info:\n"); - fprintf(f_report, " Address: 0x%016lx\n", this->dying_message_address); + fprintf(f_report, " Address: 0x%s\n", this->code_list.GetFormattedAddressString(this->dying_message_address)); fprintf(f_report, " Size: 0x%016lx\n", this->dying_message_size); CrashReport::Memdump(f_report, " Dying Message: ", this->dying_message, this->dying_message_size); } diff --git a/stratosphere/creport/source/creport_crash_report.hpp b/stratosphere/creport/source/creport_crash_report.hpp index d93ba0bcc..76b371cdb 100644 --- a/stratosphere/creport/source/creport_crash_report.hpp +++ b/stratosphere/creport/source/creport_crash_report.hpp @@ -43,7 +43,7 @@ class CrashReport { CodeList code_list; ThreadList thread_list; - public: + public: void BuildReport(u64 pid, bool has_extra_info); void SaveReport(); diff --git a/stratosphere/creport/source/creport_thread_info.cpp b/stratosphere/creport/source/creport_thread_info.cpp index f881e1700..f310f8f14 100644 --- a/stratosphere/creport/source/creport_thread_info.cpp +++ b/stratosphere/creport/source/creport_thread_info.cpp @@ -12,16 +12,16 @@ void ThreadInfo::SaveToFile(FILE *f_report) { fprintf(f_report, " Registers:\n"); { for (unsigned int i = 0; i <= 28; i++) { - fprintf(f_report, " X[%02u]: %016lx\n", i, this->context.x[i]); + fprintf(f_report, " X[%02u]: %s\n", i, this->code_list->GetFormattedAddressString(this->context.x[i])); } - fprintf(f_report, " FP: %016lx\n", this->context.fp); - fprintf(f_report, " LR: %016lx\n", this->context.lr); - fprintf(f_report, " SP: %016lx\n", this->context.sp); - fprintf(f_report, " PC: %016lx\n", this->context.pc); + fprintf(f_report, " FP: %s\n", this->code_list->GetFormattedAddressString(this->context.fp)); + fprintf(f_report, " LR: %s\n", this->code_list->GetFormattedAddressString(this->context.lr)); + fprintf(f_report, " SP: %s\n", this->code_list->GetFormattedAddressString(this->context.sp)); + fprintf(f_report, " PC: %s\n", this->code_list->GetFormattedAddressString(this->context.pc)); } fprintf(f_report, " Stack Trace:\n"); for (unsigned int i = 0; i < this->stack_trace_size; i++) { - fprintf(f_report, " ReturnAddress[%02u]: %016lx\n", i, this->stack_trace[i]); + fprintf(f_report, " ReturnAddress[%02u]: %s\n", i, this->code_list->GetFormattedAddressString(this->stack_trace[i])); } } diff --git a/stratosphere/creport/source/creport_thread_info.hpp b/stratosphere/creport/source/creport_thread_info.hpp index 6af698d4b..af49bb779 100644 --- a/stratosphere/creport/source/creport_thread_info.hpp +++ b/stratosphere/creport/source/creport_thread_info.hpp @@ -3,6 +3,7 @@ #include #include "creport_debug_types.hpp" +#include "creport_code_info.hpp" struct FpuReg { u64 _[2]; /* TODO: uint128? */ @@ -37,6 +38,7 @@ class ThreadInfo { u64 stack_bottom = 0; u64 stack_trace[0x20]{}; u32 stack_trace_size = 0; + CodeList *code_list; public: u64 GetPC() { return context.pc; } u64 GetLR() { return context.lr; } @@ -45,6 +47,7 @@ class ThreadInfo { bool ReadFromProcess(Handle debug_handle, u64 thread_id, bool is_64_bit); void SaveToFile(FILE *f_report); void DumpBinary(FILE *f_bin); + void SetCodeList(CodeList *cl) { this->code_list = cl; } private: void TryGetStackInfo(Handle debug_handle); }; @@ -58,4 +61,9 @@ class ThreadList { void SaveToFile(FILE *f_report); void DumpBinary(FILE *f_bin, u64 crashed_id); void ReadThreadsFromProcess(Handle debug_handle, bool is_64_bit); + void SetCodeList(CodeList *cl) { + for (u32 i = 0; i < thread_count; i++) { + thread_infos[i].SetCodeList(cl); + } + } }; From cd42f6dc18347e5e5a967c298c6caf4efd1e440c Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 28 Jul 2018 12:29:54 -0700 Subject: [PATCH 020/489] fs.mitm: Allow fsmitm.flag specification for mitm --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 12 ++ .../fs_mitm/source/fsmitm_service.hpp | 7 +- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 106 ++++++++++++------ stratosphere/fs_mitm/source/fsmitm_utils.hpp | 4 + 4 files changed, 89 insertions(+), 40 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 700100bdf..c5cb5cba2 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -14,6 +14,8 @@ #include "mitm_query_service.hpp" +#include "fsmitm_utils.hpp" + extern "C" { extern u32 __start__; @@ -89,6 +91,9 @@ void __appExit(void) { int main(int argc, char **argv) { Thread worker_thread = {0}; + Thread sd_initializer_thread = {0}; + consoleDebugInit(debugDevice_SVC); + consoleDebugInit(debugDevice_SVC); if (R_FAILED(threadCreate(&worker_thread, &FsMitMWorker::Main, NULL, 0x20000, 45, 0))) { @@ -98,6 +103,13 @@ int main(int argc, char **argv) /* TODO: Panic. */ } + if (R_FAILED(threadCreate(&sd_initializer_thread, &Utils::InitializeSdThreadFunc, NULL, 0x4000, 0x15, 0))) { + /* TODO: Panic. */ + } + if (R_FAILED(threadStart(&sd_initializer_thread))) { + /* TODO: Panic. */ + } + /* TODO: What's a good timeout value to use here? */ auto server_manager = std::make_unique(1, U64_MAX, 0x20000); //auto server_manager = std::make_unique(U64_MAX); diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 8ebe9cba9..ef337d329 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -22,12 +22,7 @@ class FsMitMService : public IMitMServiceObject { } static bool should_mitm(u64 pid, u64 tid) { - if (tid >= 0x0100000000010000ULL) { - return true; - } - bool has_romfs_content; - Result rc = Utils::HasSdRomfsContent(tid, &has_romfs_content); - return R_SUCCEEDED(rc) && has_romfs_content; + return tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid); } FsMitMService *clone() override { diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 720dcac4f..ef8cc6be4 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -1,53 +1,88 @@ #include #include #include +#include #include "sm_mitm.h" #include "debug.hpp" #include "fsmitm_utils.hpp" static FsFileSystem g_sd_filesystem = {0}; -static bool g_has_initialized = false; +static std::vector g_mitm_flagged_tids; +static std::atomic_bool g_has_initialized = false; -static Result EnsureInitialized() { - if (g_has_initialized) { - return 0x0; +static bool IsHexadecimal(const char *str) { + while (*str) { + if (('0' <= *str && *str <= '9') || + ('a' <= *str && *str <= 'f') || + ('A' <= *str && *str <= 'F')) { + str++; + } else { + return false; + } } - + return true; +} + +void Utils::InitializeSdThreadFunc(void *args) { + /* Get required services. */ + Handle tmp_hnd = 0; static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:c"}; for (unsigned int i = 0; i < sizeof(required_active_services) / sizeof(required_active_services[0]); i++) { - Result rc = smMitMUninstall(required_active_services[i]); - if (rc == 0xE15) { - return rc; - } else if (R_FAILED(rc) && rc != 0x1015) { - return rc; + if (R_FAILED(smGetServiceOriginal(&tmp_hnd, smEncodeName(required_active_services[i])))) { + /* TODO: Panic */ + } else { + svcCloseHandle(tmp_hnd); } } - Result rc = fsMountSdcard(&g_sd_filesystem); - if (R_SUCCEEDED(rc)) { - g_has_initialized = true; + /* Mount SD. */ + while (R_FAILED(fsMountSdcard(&g_sd_filesystem))) { + svcSleepThread(1000ULL); } - return rc; + + /* Check for MitM flags. */ + FsDir titles_dir; + if (R_SUCCEEDED(fsFsOpenDirectory(&g_sd_filesystem, "/atmosphere/titles", FS_DIROPEN_DIRECTORY, &titles_dir))) { + FsDirectoryEntry dir_entry; + FsFile f; + u64 read_entries; + while (R_SUCCEEDED((fsDirRead(&titles_dir, 0, &read_entries, 1, &dir_entry))) && read_entries == 1) { + if (strlen(dir_entry.name) == 0x10 && IsHexadecimal(dir_entry.name)) { + u64 title_id = strtoul(dir_entry.name, NULL, 16); + char title_path[FS_MAX_PATH] = {0}; + strcpy(title_path, "sdmc:/atmosphere/titles/"); + strcat(title_path, dir_entry.name); + strcat(title_path, "/fsmitm.flag"); + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, title_path, FS_OPEN_READ, &f))) { + g_mitm_flagged_tids.push_back(title_id); + fsFileClose(&f); + } + } + } + fsDirClose(&titles_dir); + } + + g_has_initialized = true; + + svcExitThread(); } bool Utils::IsSdInitialized() { - return R_SUCCEEDED(EnsureInitialized()); + return g_has_initialized; } Result Utils::OpenSdFile(const char *fn, int flags, FsFile *out) { - Result rc; - if (R_FAILED((rc = EnsureInitialized()))) { - return rc; + if (!IsSdInitialized()) { + return 0xFA202; } return fsFsOpenFile(&g_sd_filesystem, fn, flags, out); } Result Utils::OpenSdFileForAtmosphere(u64 title_id, const char *fn, int flags, FsFile *out) { - Result rc; - if (R_FAILED((rc = EnsureInitialized()))) { - return rc; + if (!IsSdInitialized()) { + return 0xFA202; } char path[FS_MAX_PATH]; @@ -60,27 +95,24 @@ Result Utils::OpenSdFileForAtmosphere(u64 title_id, const char *fn, int flags, F } Result Utils::OpenRomFSSdFile(u64 title_id, const char *fn, int flags, FsFile *out) { - Result rc; - if (R_FAILED((rc = EnsureInitialized()))) { - return rc; + if (!IsSdInitialized()) { + return 0xFA202; } return OpenRomFSFile(&g_sd_filesystem, title_id, fn, flags, out); } Result Utils::OpenSdDir(const char *path, FsDir *out) { - Result rc; - if (R_FAILED((rc = EnsureInitialized()))) { - return rc; + if (!IsSdInitialized()) { + return 0xFA202; } return fsFsOpenDirectory(&g_sd_filesystem, path, FS_DIROPEN_DIRECTORY | FS_DIROPEN_FILE, out); } Result Utils::OpenSdDirForAtmosphere(u64 title_id, const char *path, FsDir *out) { - Result rc; - if (R_FAILED((rc = EnsureInitialized()))) { - return rc; + if (!IsSdInitialized()) { + return 0xFA202; } char safe_path[FS_MAX_PATH]; @@ -93,9 +125,8 @@ Result Utils::OpenSdDirForAtmosphere(u64 title_id, const char *path, FsDir *out) } Result Utils::OpenRomFSSdDir(u64 title_id, const char *path, FsDir *out) { - Result rc; - if (R_FAILED((rc = EnsureInitialized()))) { - return rc; + if (!IsSdInitialized()) { + return 0xFA202; } return OpenRomFSDir(&g_sd_filesystem, title_id, path, out); @@ -136,4 +167,11 @@ Result Utils::HasSdRomfsContent(u64 title_id, bool *out) { } fsDirClose(&dir); return rc; -} \ No newline at end of file +} + +bool Utils::HasSdMitMFlag(u64 tid) { + if (IsSdInitialized()) { + return std::find(g_mitm_flagged_tids.begin(), g_mitm_flagged_tids.end(), tid) != g_mitm_flagged_tids.end(); + } + return false; +} diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index a301fbcc9..794dbe34c 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -17,4 +17,8 @@ class Utils { static Result OpenRomFSDir(FsFileSystem *fs, u64 title_id, const char *path, FsDir *out); static Result HasSdRomfsContent(u64 title_id, bool *out); + + /* SD card Initialization + MitM detection. */ + static void InitializeSdThreadFunc(void *args); + static bool HasSdMitMFlag(u64 tid); }; \ No newline at end of file From c1fd2eda20a60fd449826761775656cc629a696e Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 28 Jul 2018 20:01:09 -0700 Subject: [PATCH 021/489] Loader: Skeleton IPS/IPS32 patching support. --- stratosphere/loader/source/ldr_nso.cpp | 4 + stratosphere/loader/source/ldr_patcher.cpp | 104 +++++++++++++++++++++ stratosphere/loader/source/ldr_patcher.hpp | 10 ++ 3 files changed, 118 insertions(+) create mode 100644 stratosphere/loader/source/ldr_patcher.cpp create mode 100644 stratosphere/loader/source/ldr_patcher.hpp diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index b01e5d25f..69825e06f 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -7,6 +7,7 @@ #include "ldr_nso.hpp" #include "ldr_map.hpp" #include "ldr_random.hpp" +#include "ldr_patcher.hpp" static NsoUtils::NsoHeader g_nso_headers[NSO_NUM_MAX] = {0}; static bool g_nso_present[NSO_NUM_MAX] = {0}; @@ -283,6 +284,9 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo u64 bss_base = rw_start + g_nso_headers[i].segments[2].decomp_size, bss_size = g_nso_headers[i].segments[2].align_or_total_size; std::fill(map_base + bss_base, map_base + bss_base + bss_size, 0); + /* Apply patches to loaded module. */ + PatchUtils::ApplyPatches(title_id, &g_nso_headers[i], map_base, bss_base); + nso_map.Close(); for (unsigned int seg = 0; seg < 3; seg++) { diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp new file mode 100644 index 000000000..87efe19fb --- /dev/null +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include + +#include +#include "ldr_patcher.hpp" + +#define IPS_MAGIC "PATCH" +#define IPS_TAIL "EOF" + +#define IPS32_MAGIC "IPS32" +#define IPS32_TAIL "EEOF" + +static inline u8 HexNybbleToU8(const char nybble) { + if ('0' <= nybble && nybble <= '9') { + return nybble - '0'; + } else if ('a' <= nybble && nybble <= 'f') { + return nybble - 'a'; + } else { + return nybble - 'A'; + } +} + +static bool MatchesBuildId(const char *name, size_t name_len, const u8 *build_id) { + /* Validate name is hex build id. */ + for (unsigned int i = 0; i < name_len - 4; i++) { + if (!(('0' <= name[i] && name[i] <= '9') || + ('a' <= name[i] && name[i] <= 'f') || + ('A' <= name[i] && name[i] <= 'F'))) { + return false; + } + } + + /* Read build id from name. */ + u8 build_id_from_name[0x20] = {0}; + for (unsigned int name_ofs = 0, id_ofs = 0; name_ofs < name_len - 4; id_ofs++) { + build_id_from_name[id_ofs] |= HexNybbleToU8(name[name_ofs++]) << 4; + build_id_from_name[id_ofs] |= HexNybbleToU8(name[name_ofs++]); + } + + return memcmp(build_id, build_id_from_name, sizeof(build_id_from_name)) == 0; +} + +static inline void PatchNsoByte(u8 *nso, size_t max_size, size_t offset, u8 val) { + /* TODO: Be smarter about this. */ + if (sizeof(NsoUtils::NsoHeader) <= offset && offset < max_size) { + nso[offset - sizeof(NsoUtils::NsoHeader)] = val; + } +} + +static void ApplyIpsPatch(u8 *mapped_nso, size_t mapped_size, FILE *ips) { + /* TODO */ +} + +static void ApplyIps32Patch(u8 *mapped_nso, size_t mapped_size, FILE *ips) { + /* TODO */ +} + +void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t mapped_size) { + /* Inspect all patches from //exefs/patches/<*>/<*>.ips. */ + char path[FS_MAX_PATH+1] = {0}; + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs/patches", title_id); + DIR *patches_dir = opendir(path); + struct dirent *pdir_ent; + if (patches_dir != NULL) { + /* Iterate over the patches directory to find patch subdirectories. */ + while ((pdir_ent = readdir(patches_dir)) != NULL) { + if (strcmp(pdir_ent->d_name, ".") == 0 || strcmp(pdir_ent->d_name, "..") == 0) { + continue; + } + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs/patches/%s", title_id, pdir_ent->d_name); + DIR *patch_dir = opendir(path); + struct dirent *ent; + if (patch_dir != NULL) { + /* Iterate over the patch subdirectory to find .ips patches. */ + while ((ent = readdir(patch_dir)) != NULL) { + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { + continue; + } + size_t name_len = strlen(ent->d_name); + if ((4 < name_len && name_len <= 0x44) && ((name_len & 1) == 0) && strcmp(ent->d_name + name_len - 4, ".ips") == 0 && MatchesBuildId(ent->d_name, name_len, header->build_id)) { + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs/patches/%s/%s", title_id, pdir_ent->d_name, ent->d_name); + FILE *f_ips = fopen(path, "rb"); + if (f_ips != NULL) { + u8 header[5]; + if (fread(header, 5, 1, f_ips) == 1) { + if (memcmp(header, IPS_MAGIC, 5) == 0) { + ApplyIpsPatch(mapped_nso, mapped_size, f_ips); + } else if (memcmp(header, IPS32_MAGIC, 5) == 0) { + ApplyIps32Patch(mapped_nso, mapped_size, f_ips); + } + } + fclose(f_ips); + } + } + } + closedir(patch_dir); + } + } + closedir(patches_dir); + } +} \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_patcher.hpp b/stratosphere/loader/source/ldr_patcher.hpp new file mode 100644 index 000000000..cea953a73 --- /dev/null +++ b/stratosphere/loader/source/ldr_patcher.hpp @@ -0,0 +1,10 @@ +#pragma once +#include <switch.h> +#include <cstdio> + +#include "ldr_nso.hpp" + +class PatchUtils { + public: + static void ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t size); +}; \ No newline at end of file From 0f5f3c2ad052b5303252f9f3076f2c78004ca542 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 28 Jul 2018 20:28:17 -0700 Subject: [PATCH 022/489] Loader: Implement IPS/IPS32 patching. --- stratosphere/loader/source/ldr_patcher.cpp | 94 ++++++++++++++++++---- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index 87efe19fb..7247d559d 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -7,6 +7,8 @@ #include <switch.h> #include "ldr_patcher.hpp" +/* IPS Patching adapted from Luma3DS (https://github.com/AuroraWright/Luma3DS/blob/master/sysmodules/loader/source/patcher.c) */ + #define IPS_MAGIC "PATCH" #define IPS_TAIL "EOF" @@ -43,21 +45,85 @@ static bool MatchesBuildId(const char *name, size_t name_len, const u8 *build_id return memcmp(build_id, build_id_from_name, sizeof(build_id_from_name)) == 0; } -static inline void PatchNsoByte(u8 *nso, size_t max_size, size_t offset, u8 val) { - /* TODO: Be smarter about this. */ - if (sizeof(NsoUtils::NsoHeader) <= offset && offset < max_size) { - nso[offset - sizeof(NsoUtils::NsoHeader)] = val; +static void ApplyIpsPatch(u8 *mapped_nso, size_t mapped_size, bool is_ips32, FILE *f_ips) { + u8 buffer[4]; + while (fread(buffer, is_ips32 ? 4 : 3, 1, f_ips) == 1) { + if (is_ips32 && memcmp(buffer, IPS32_TAIL, 4) == 0) { + break; + } else if (!is_ips32 && memcmp(buffer, IPS_TAIL, 3) == 0) { + break; + } + + /* Offset of patch. */ + u32 patch_offset; + if (is_ips32) { + patch_offset = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; + } else { + patch_offset = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]); + } + + /* Size of patch. */ + if (fread(buffer, 2, 1, f_ips) != 1) { + break; + } + u32 patch_size = (buffer[0] << 8) | (buffer[1]); + + /* Check for RLE encoding. */ + if (patch_size == 0) { + /* Size of RLE. */ + if (fread(buffer, 2, 1, f_ips) != 1) { + break; + } + + u32 rle_size = (buffer[0] << 8) | (buffer[1]); + + /* Value for RLE. */ + if (fread(buffer, 1, 1, f_ips) != 1) { + break; + } + + if (patch_offset < sizeof(NsoUtils::NsoHeader)) { + if (patch_offset + rle_size > sizeof(NsoUtils::NsoHeader)) { + u32 diff = sizeof(NsoUtils::NsoHeader) - patch_offset; + patch_offset += diff; + rle_size -= diff; + goto IPS_RLE_PATCH_OFFSET_WITHIN_BOUNDS; + } + } else { + IPS_RLE_PATCH_OFFSET_WITHIN_BOUNDS: + patch_offset -= sizeof(NsoUtils::NsoHeader); + if (patch_offset + rle_size > mapped_size) { + rle_size = mapped_size - patch_offset; + } + memset(mapped_nso + patch_offset, buffer[0], rle_size); + } + } else { + if (patch_offset < sizeof(NsoUtils::NsoHeader)) { + if (patch_offset + patch_size > sizeof(NsoUtils::NsoHeader)) { + u32 diff = sizeof(NsoUtils::NsoHeader) - patch_offset; + patch_offset += diff; + patch_size -= diff; + fseek(f_ips, diff, SEEK_CUR); + goto IPS_DATA_PATCH_OFFSET_WITHIN_BOUNDS; + } + } else { + IPS_DATA_PATCH_OFFSET_WITHIN_BOUNDS: + patch_offset -= sizeof(NsoUtils::NsoHeader); + u32 read_size = patch_size; + if (patch_offset + read_size > mapped_size) { + read_size = mapped_size - patch_offset; + } + if (fread(mapped_nso + patch_offset, read_size, 1, f_ips) != 1) { + break; + } + if (patch_size > read_size) { + fseek(f_ips, patch_size - read_size, SEEK_CUR); + } + } + } } } -static void ApplyIpsPatch(u8 *mapped_nso, size_t mapped_size, FILE *ips) { - /* TODO */ -} - -static void ApplyIps32Patch(u8 *mapped_nso, size_t mapped_size, FILE *ips) { - /* TODO */ -} - void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t mapped_size) { /* Inspect all patches from /<title>/exefs/patches/<*>/<*>.ips. */ char path[FS_MAX_PATH+1] = {0}; @@ -87,9 +153,9 @@ void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u u8 header[5]; if (fread(header, 5, 1, f_ips) == 1) { if (memcmp(header, IPS_MAGIC, 5) == 0) { - ApplyIpsPatch(mapped_nso, mapped_size, f_ips); + ApplyIpsPatch(mapped_nso, mapped_size, false, f_ips); } else if (memcmp(header, IPS32_MAGIC, 5) == 0) { - ApplyIps32Patch(mapped_nso, mapped_size, f_ips); + ApplyIps32Patch(mapped_nso, mapped_size, true, f_ips); } } fclose(f_ips); From 75916001a2eee3beefb61561178ed555e6e5f4d7 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 28 Jul 2018 20:36:30 -0700 Subject: [PATCH 023/489] Loader: Fix IPS edge condition, change ips location --- stratosphere/loader/source/ldr_patcher.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index 7247d559d..f7684aa2a 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -105,6 +105,8 @@ static void ApplyIpsPatch(u8 *mapped_nso, size_t mapped_size, bool is_ips32, FIL patch_size -= diff; fseek(f_ips, diff, SEEK_CUR); goto IPS_DATA_PATCH_OFFSET_WITHIN_BOUNDS; + } else { + fseek(f_ips, patch_size, SEEK_CUR); } } else { IPS_DATA_PATCH_OFFSET_WITHIN_BOUNDS: @@ -127,7 +129,7 @@ static void ApplyIpsPatch(u8 *mapped_nso, size_t mapped_size, bool is_ips32, FIL void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t mapped_size) { /* Inspect all patches from /<title>/exefs/patches/<*>/<*>.ips. */ char path[FS_MAX_PATH+1] = {0}; - snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs/patches", title_id); + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs_patches", title_id); DIR *patches_dir = opendir(path); struct dirent *pdir_ent; if (patches_dir != NULL) { @@ -136,7 +138,7 @@ void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u if (strcmp(pdir_ent->d_name, ".") == 0 || strcmp(pdir_ent->d_name, "..") == 0) { continue; } - snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs/patches/%s", title_id, pdir_ent->d_name); + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs_patches/%s", title_id, pdir_ent->d_name); DIR *patch_dir = opendir(path); struct dirent *ent; if (patch_dir != NULL) { @@ -147,7 +149,7 @@ void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u } size_t name_len = strlen(ent->d_name); if ((4 < name_len && name_len <= 0x44) && ((name_len & 1) == 0) && strcmp(ent->d_name + name_len - 4, ".ips") == 0 && MatchesBuildId(ent->d_name, name_len, header->build_id)) { - snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs/patches/%s/%s", title_id, pdir_ent->d_name, ent->d_name); + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs_patches/%s/%s", title_id, pdir_ent->d_name, ent->d_name); FILE *f_ips = fopen(path, "rb"); if (f_ips != NULL) { u8 header[5]; From 08275240c6481760596828030be3a92013306f27 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 28 Jul 2018 20:41:13 -0700 Subject: [PATCH 024/489] Loader/ips: fix compile error --- stratosphere/loader/source/ldr_patcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index f7684aa2a..e50086d8a 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -157,7 +157,7 @@ void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u if (memcmp(header, IPS_MAGIC, 5) == 0) { ApplyIpsPatch(mapped_nso, mapped_size, false, f_ips); } else if (memcmp(header, IPS32_MAGIC, 5) == 0) { - ApplyIps32Patch(mapped_nso, mapped_size, true, f_ips); + ApplyIpsPatch(mapped_nso, mapped_size, true, f_ips); } } fclose(f_ips); From 674a91db8cdacf90951f3a467bf901feb39df6d7 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 28 Jul 2018 21:06:50 -0700 Subject: [PATCH 025/489] Loader/ips: Fix more bugs, now works with simple test on hw. --- stratosphere/loader/source/ldr_patcher.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index e50086d8a..67520e425 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -19,9 +19,9 @@ static inline u8 HexNybbleToU8(const char nybble) { if ('0' <= nybble && nybble <= '9') { return nybble - '0'; } else if ('a' <= nybble && nybble <= 'f') { - return nybble - 'a'; + return nybble - 'a' + 0xa; } else { - return nybble - 'A'; + return nybble - 'A' + 0xA; } } From a3d53fbb2cc55eebed5e33f4c9969053b67b2d3f Mon Sep 17 00:00:00 2001 From: Luke Street <luke.street@encounterpc.com> Date: Sun, 29 Jul 2018 12:17:51 -0400 Subject: [PATCH 026/489] Define wait() in fusee-primary/secondary --- fusee/fusee-primary/src/utils.c | 7 +++++++ fusee/fusee-secondary/src/utils.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/fusee/fusee-primary/src/utils.c b/fusee/fusee-primary/src/utils.c index 1ffe4b249..823e4ea00 100644 --- a/fusee/fusee-primary/src/utils.c +++ b/fusee/fusee-primary/src/utils.c @@ -13,6 +13,13 @@ #include <inttypes.h> +void wait(uint32_t microseconds) { + uint32_t old_time = TIMERUS_CNTR_1US_0; + while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { + /* Spin-lock. */ + } +} + __attribute__((noreturn)) void watchdog_reboot(void) { volatile watchdog_timers_t *wdt = GET_WDT(4); wdt->PATTERN = WDT_REBOOT_PATTERN; diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index d5f6bebf2..4aee48cf6 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -12,6 +12,13 @@ #include <stdio.h> #include <inttypes.h> +void wait(uint32_t microseconds) { + uint32_t old_time = TIMERUS_CNTR_1US_0; + while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { + /* Spin-lock. */ + } +} + __attribute__((noreturn)) void watchdog_reboot(void) { volatile watchdog_timers_t *wdt = GET_WDT(4); wdt->PATTERN = WDT_REBOOT_PATTERN; From a9b20b5553661a64cb7b8e55f18383257e20a3ce Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 11:02:06 -0700 Subject: [PATCH 027/489] Exosphere: Fix CFLAGs for latest devkitA64 --- exosphere/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exosphere/Makefile b/exosphere/Makefile index 079ae7bd4..7f0340003 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -33,12 +33,14 @@ CFLAGS := \ -ffunction-sections \ -fdata-sections \ -fomit-frame-pointer \ + -fno-asynchronous-unwind-tables \ + -fno-unwind-tables \ -std=gnu11 \ -Werror \ -Wall \ $(ARCH) $(DEFINES) -CFLAGS += $(INCLUDE) +CFLAGS += $(INCLUDE) CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 From de05685e3d89d01a6c6101d18ad3be878921beeb Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 11:07:05 -0700 Subject: [PATCH 028/489] fs.mitm: Remove shim for fsStorageGetSize, which was added to libnx --- stratosphere/fs_mitm/source/fs_shim.c | 33 --------------------------- stratosphere/fs_mitm/source/fs_shim.h | 1 - 2 files changed, 34 deletions(-) diff --git a/stratosphere/fs_mitm/source/fs_shim.c b/stratosphere/fs_mitm/source/fs_shim.c index 99a79fa2b..ebfae7ed6 100644 --- a/stratosphere/fs_mitm/source/fs_shim.c +++ b/stratosphere/fs_mitm/source/fs_shim.c @@ -235,39 +235,6 @@ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *o } /* Missing FS Storage commands. */ -Result fsStorageGetSize(FsStorage* s, u64* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 size; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && out) *out = resp->size; - } - - return rc; -} - Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeInfo *out) { IpcCommand c; ipcInitialize(&c); diff --git a/stratosphere/fs_mitm/source/fs_shim.h b/stratosphere/fs_mitm/source/fs_shim.h index ce128729f..9030078e7 100644 --- a/stratosphere/fs_mitm/source/fs_shim.h +++ b/stratosphere/fs_mitm/source/fs_shim.h @@ -29,7 +29,6 @@ Result fsOpenDataStorageByDataIdFromDomain(Service* s, FsStorageId storage_id, u Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out); /* Missing FS Storage commands. */ -Result fsStorageGetSize(FsStorage* s, u64* out); Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeInfo *out); #ifdef __cplusplus From e697f6bdd053d0a79e44a61b04dcea036d064ef9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 11:21:42 -0700 Subject: [PATCH 029/489] fs.mitm: Fix flag detection. --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index ef8cc6be4..e499a5bf9 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -51,7 +51,7 @@ void Utils::InitializeSdThreadFunc(void *args) { if (strlen(dir_entry.name) == 0x10 && IsHexadecimal(dir_entry.name)) { u64 title_id = strtoul(dir_entry.name, NULL, 16); char title_path[FS_MAX_PATH] = {0}; - strcpy(title_path, "sdmc:/atmosphere/titles/"); + strcpy(title_path, "/atmosphere/titles/"); strcat(title_path, dir_entry.name); strcat(title_path, "/fsmitm.flag"); if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, title_path, FS_OPEN_READ, &f))) { From 44e2412ae6905924e9ed3fd228e3ceeda0b8d9d6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 11:27:19 -0700 Subject: [PATCH 030/489] Loader: Change ips patch location to ease patch distribution --- stratosphere/loader/source/ldr_nso.cpp | 2 +- stratosphere/loader/source/ldr_patcher.cpp | 10 +++++----- stratosphere/loader/source/ldr_patcher.hpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index 69825e06f..26e265690 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -285,7 +285,7 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo std::fill(map_base + bss_base, map_base + bss_base + bss_size, 0); /* Apply patches to loaded module. */ - PatchUtils::ApplyPatches(title_id, &g_nso_headers[i], map_base, bss_base); + PatchUtils::ApplyPatches(&g_nso_headers[i], map_base, bss_base); nso_map.Close(); diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index 67520e425..569e44fcd 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -126,10 +126,10 @@ static void ApplyIpsPatch(u8 *mapped_nso, size_t mapped_size, bool is_ips32, FIL } } -void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t mapped_size) { - /* Inspect all patches from /<title>/exefs/patches/<*>/<*>.ips. */ +void PatchUtils::ApplyPatches(const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t mapped_size) { + /* Inspect all patches from /atmosphere/exefs_patches/<*>/<*>.ips */ char path[FS_MAX_PATH+1] = {0}; - snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs_patches", title_id); + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/exefs_patches"); DIR *patches_dir = opendir(path); struct dirent *pdir_ent; if (patches_dir != NULL) { @@ -138,7 +138,7 @@ void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u if (strcmp(pdir_ent->d_name, ".") == 0 || strcmp(pdir_ent->d_name, "..") == 0) { continue; } - snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs_patches/%s", title_id, pdir_ent->d_name); + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/exefs_patches/%s", pdir_ent->d_name); DIR *patch_dir = opendir(path); struct dirent *ent; if (patch_dir != NULL) { @@ -149,7 +149,7 @@ void PatchUtils::ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u } size_t name_len = strlen(ent->d_name); if ((4 < name_len && name_len <= 0x44) && ((name_len & 1) == 0) && strcmp(ent->d_name + name_len - 4, ".ips") == 0 && MatchesBuildId(ent->d_name, name_len, header->build_id)) { - snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/titles/%016lx/exefs_patches/%s/%s", title_id, pdir_ent->d_name, ent->d_name); + snprintf(path, sizeof(path) - 1, "sdmc:/atmosphere/exefs_patches/%s/%s", pdir_ent->d_name, ent->d_name); FILE *f_ips = fopen(path, "rb"); if (f_ips != NULL) { u8 header[5]; diff --git a/stratosphere/loader/source/ldr_patcher.hpp b/stratosphere/loader/source/ldr_patcher.hpp index cea953a73..07794a3a9 100644 --- a/stratosphere/loader/source/ldr_patcher.hpp +++ b/stratosphere/loader/source/ldr_patcher.hpp @@ -6,5 +6,5 @@ class PatchUtils { public: - static void ApplyPatches(u64 title_id, const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t size); + static void ApplyPatches(const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t size); }; \ No newline at end of file From 3a2520a3b75c1c3fca8a39d35f0a154c5bb59217 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 16:35:43 -0700 Subject: [PATCH 031/489] Loader: Add support for exefs redirection to code nsp on SD. --- .../loader/source/ldr_content_management.cpp | 16 ++++++++++++++++ .../loader/source/ldr_content_management.hpp | 1 + .../loader/source/ldr_process_creation.cpp | 16 ++++++++++++---- .../loader/source/ldr_process_manager.cpp | 6 +++++- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 4424441e1..9b7a76194 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -19,6 +19,10 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { if (!g_has_initialized_fs_dev) { TryMountSdCard(); } + + if (kernelAbove200() && g_has_initialized_fs_dev && R_SUCCEEDED(MountCodeNspOnSd(tid))) { + return 0x0; + } if (R_FAILED(rc = ResolveContentPath(path, tid, sid))) { @@ -53,6 +57,18 @@ Result ContentManagement::UnmountCode() { return 0; } +Result ContentManagement::MountCodeNspOnSd(u64 tid) { + char path[FS_MAX_PATH+1] = {0}; + snprintf(path, FS_MAX_PATH, "sdmc:/atmosphere/titles/%016lx/exefs.nsp", tid); + Result rc = fsOpenFileSystemWithId(&g_CodeFileSystem, 0, FsFileSystemType_ApplicationPackage, path); + + if (R_SUCCEEDED(rc)) { + fsdevMountDevice("code", g_CodeFileSystem); + } + + return rc; +} + Result ContentManagement::MountCodeForTidSid(Registration::TidSid *tid_sid) { return MountCode(tid_sid->title_id, tid_sid->storage_id); } diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index dded7398e..8fee7b5ac 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -6,6 +6,7 @@ class ContentManagement { public: static Result MountCode(u64 tid, FsStorageId sid); + static Result MountCodeNspOnSd(u64 tid); static Result UnmountCode(); static Result MountCodeForTidSid(Registration::TidSid *tid_sid); diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index b8f9c71c4..07cd225a6 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -93,6 +93,7 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc Registration::Process *target_process; Handle process_h = 0; u64 process_id = 0; + bool mounted_code = false; Result rc; /* Get the process from the registration queue. */ @@ -107,6 +108,11 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc if (R_FAILED(rc)) { return rc; } + mounted_code = true; + } else { + if (R_SUCCEEDED(ContentManagement::MountCodeNspOnSd(target_process->tid_sid.title_id))) { + mounted_code = true; + } } /* Load the process's NPDM. */ @@ -193,10 +199,12 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc rc = 0; CREATE_PROCESS_END: - if (R_SUCCEEDED(rc) && target_process->tid_sid.storage_id != FsStorageId_None) { - rc = ContentManagement::UnmountCode(); - } else { - ContentManagement::UnmountCode(); + if (mounted_code) { + if (R_SUCCEEDED(rc) && target_process->tid_sid.storage_id != FsStorageId_None) { + rc = ContentManagement::UnmountCode(); + } else { + ContentManagement::UnmountCode(); + } } if (R_SUCCEEDED(rc)) { *out_process_h = process_h; diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index 55511f56c..66ab5308b 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -111,17 +111,21 @@ std::tuple<Result> ProcessManagerService::unregister_title(u64 index) { Result ProcessManagerService::populate_program_info_buffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid) { NpdmUtils::NpdmInfo info; Result rc; + bool mounted_code = false; if (tid_sid->storage_id != FsStorageId_None) { rc = ContentManagement::MountCodeForTidSid(tid_sid); if (R_FAILED(rc)) { return rc; } + mounted_code = true; + } else if (R_SUCCEEDED(ContentManagement::MountCodeNspOnSd(tid_sid->title_id))) { + mounted_code = true; } rc = NpdmUtils::LoadNpdm(tid_sid->title_id, &info); - if (tid_sid->storage_id != FsStorageId_None) { + if (mounted_code) { ContentManagement::UnmountCode(); } From c547ed50aa64f6229abd15589f63c4983fc44108 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 16:45:29 -0700 Subject: [PATCH 032/489] Loader: Fix exefs nsp support. Works on hardware. --- stratosphere/loader/source/ldr_content_management.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 9b7a76194..ef2dc2ef1 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -59,7 +59,7 @@ Result ContentManagement::UnmountCode() { Result ContentManagement::MountCodeNspOnSd(u64 tid) { char path[FS_MAX_PATH+1] = {0}; - snprintf(path, FS_MAX_PATH, "sdmc:/atmosphere/titles/%016lx/exefs.nsp", tid); + snprintf(path, FS_MAX_PATH, "@Sdcard:/atmosphere/titles/%016lx/exefs.nsp", tid); Result rc = fsOpenFileSystemWithId(&g_CodeFileSystem, 0, FsFileSystemType_ApplicationPackage, path); if (R_SUCCEEDED(rc)) { From 84bcaf8dc62e4bd711ef5cbfb53851d4fcf7df0a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 16:48:33 -0700 Subject: [PATCH 033/489] creport: Change report path to crash_reports --- stratosphere/creport/source/creport_crash_report.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index cf396ecc5..abf2e0233 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -206,7 +206,7 @@ void CrashReport::EnsureReportDirectories() { char path[FS_MAX_PATH]; strcpy(path, "sdmc:/atmosphere"); mkdir(path, S_IRWXU); - strcat(path, "/crash reports"); + strcat(path, "/crash_reports"); mkdir(path, S_IRWXU); strcat(path, "/dumps"); mkdir(path, S_IRWXU); From c70420d99616f1cf58210978946044be27d52c01 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 16:54:15 -0700 Subject: [PATCH 034/489] creport: Actually change report paths. --- stratosphere/creport/source/creport_crash_report.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index abf2e0233..f687b00b3 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -226,7 +226,7 @@ void CrashReport::SaveReport() { } /* Open report file. */ - snprintf(report_path, sizeof(report_path) - 1, "sdmc:/atmosphere/crash reports/%011lu_%016lx.log", timestamp, process_info.title_id); + snprintf(report_path, sizeof(report_path) - 1, "sdmc:/atmosphere/crash_reports/%011lu_%016lx.log", timestamp, process_info.title_id); FILE *f_report = fopen(report_path, "w"); if (f_report == NULL) { return; @@ -235,7 +235,7 @@ void CrashReport::SaveReport() { fclose(f_report); /* Dump threads. */ - snprintf(report_path, sizeof(report_path) - 1, "sdmc:/atmosphere/crash reports/dumps/%011lu_%016lx_thread_info.bin", timestamp, process_info.title_id); + snprintf(report_path, sizeof(report_path) - 1, "sdmc:/atmosphere/crash_reports/dumps/%011lu_%016lx_thread_info.bin", timestamp, process_info.title_id); f_report = fopen(report_path, "wb"); this->thread_list.DumpBinary(f_report, this->crashed_thread_info.GetId()); fclose(f_report); From cb4089e49c0cdf441c28804a003e54472e0b7222 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 29 Jul 2018 17:27:30 -0700 Subject: [PATCH 035/489] Stratosphere: use isxdigit to check if char is hex. --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 12 +++++------- stratosphere/loader/source/ldr_patcher.cpp | 7 +++---- stratosphere/pm/source/pm_boot2.cpp | 12 +++++------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index e499a5bf9..3542b8af8 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -13,13 +13,11 @@ static std::atomic_bool g_has_initialized = false; static bool IsHexadecimal(const char *str) { while (*str) { - if (('0' <= *str && *str <= '9') || - ('a' <= *str && *str <= 'f') || - ('A' <= *str && *str <= 'F')) { - str++; - } else { - return false; - } + if (isxdigit(*str)) { + str++; + } else { + return false; + } } return true; } diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index 569e44fcd..a0a6bdc24 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -3,6 +3,7 @@ #include <cstdio> #include <cstring> #include <dirent.h> +#include <ctype.h> #include <switch.h> #include "ldr_patcher.hpp" @@ -28,11 +29,9 @@ static inline u8 HexNybbleToU8(const char nybble) { static bool MatchesBuildId(const char *name, size_t name_len, const u8 *build_id) { /* Validate name is hex build id. */ for (unsigned int i = 0; i < name_len - 4; i++) { - if (!(('0' <= name[i] && name[i] <= '9') || - ('a' <= name[i] && name[i] <= 'f') || - ('A' <= name[i] && name[i] <= 'F'))) { + if (isxdigit(name[i]) == 0) { return false; - } + } } /* Read build id from name. */ diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index e1aee4c4b..27618124a 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -12,13 +12,11 @@ static bool IsHexadecimal(const char *str) { while (*str) { - if (('0' <= *str && *str <= '9') || - ('a' <= *str && *str <= 'f') || - ('A' <= *str && *str <= 'F')) { - str++; - } else { - return false; - } + if (isxdigit(*str)) { + str++; + } else { + return false; + } } return true; } From bbdf2868c9fb91d528123875ee95111f99d8536e Mon Sep 17 00:00:00 2001 From: Lioncash <mathew1800@gmail.com> Date: Sun, 29 Jul 2018 22:51:38 -0400 Subject: [PATCH 036/489] fusee-secondary/fs_dev: Correct uninitialized cast within fsdev_seek() Previously this was casting the same unassigned variable that was being assigned to. --- fusee/fusee-secondary/src/fs_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/fs_dev.c b/fusee/fusee-secondary/src/fs_dev.c index d6fda4a1b..dec7baa27 100644 --- a/fusee/fusee-secondary/src/fs_dev.c +++ b/fusee/fusee-secondary/src/fs_dev.c @@ -442,7 +442,7 @@ static ssize_t fsdev_read(struct _reent *r, void *fd, char *ptr, size_t len) { } static off_t fsdev_seek(struct _reent *r, void *fd, off_t pos, int whence) { - FIL *f = (FIL *)f; + FIL *f = (FIL *)fd; FSIZE_t off; int ret; From 4b8455baf91d8699a663341c135c91c34f0a7816 Mon Sep 17 00:00:00 2001 From: Lioncash <mathew1800@gmail.com> Date: Sun, 29 Jul 2018 23:21:30 -0400 Subject: [PATCH 037/489] fusee-secondary: Correct else-if condition in xmemmove() Previously both the if and else conditions were the same. --- fusee/fusee-secondary/src/chainloader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/chainloader.c b/fusee/fusee-secondary/src/chainloader.c index 6890ff4ff..b4090b103 100644 --- a/fusee/fusee-secondary/src/chainloader.c +++ b/fusee/fusee-secondary/src/chainloader.c @@ -17,7 +17,7 @@ static void *xmemmove(void *dst, const void *src, size_t len) for (size_t i = 0; i < len; i++) { dst8[i] = src8[i]; } - } else if (src8 > dst8) { + } else if (dst8 > src8) { for (size_t i = len; len > 0; len--) dst8[i - 1] = src8[i - 1]; } From 6eac78595e907da588150405ec10132f3048f653 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Wed, 1 Aug 2018 21:15:16 +0100 Subject: [PATCH 038/489] fusee-secondary: Remove restriction for loading from eMMC --- fusee/fusee-secondary/src/nxboot.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 22684241c..70c1f90f3 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -87,16 +87,12 @@ void nxboot_main(void) { fatal_error("Failed to open Package2 from %s: %s!\n", loader_ctx->package2_path, strerror(errno)); } } else { -#ifdef I_KNOW_WHAT_IM_DOING_2 pk2file = fopen("bcpkg21:/", "rb"); if (pk2file == NULL || fseek(pk2file, 0x4000, SEEK_SET) != 0) { printf("Error: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); fclose(pk2file); generic_panic(); } -#else - fatal_error("Package2 must be loaded from the SD card, unless you know what you are doing!\n"); -#endif } setvbuf(pk2file, NULL, _IONBF, 0); /* Workaround. */ @@ -193,7 +189,7 @@ void nxboot_main(void) { package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); printf(u8"Reading Exosphère...\n"); - /* Copy Exophère to a good location (or read it directly to it.) */ + /* Copy Exosphère to a good location (or read it directly to it.) */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { exosphere_memaddr = (void *)0x40020000; } else { From 441e58be5642bd429808b62b36b84f6f086549a5 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 1 Aug 2018 23:15:18 -0700 Subject: [PATCH 039/489] anti-telemetry: Do not boot Error Collection sysmodule --- stratosphere/pm/source/pm_boot2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 27618124a..6bf25ea00 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -83,7 +83,7 @@ static const std::tuple<Boot2KnownTitleId, bool> g_additional_launch_programs[] {Boot2KnownTitleId::btm, true}, /* btm */ {Boot2KnownTitleId::eupld, false}, /* eupld */ {Boot2KnownTitleId::glue, true}, /* glue */ - {Boot2KnownTitleId::eclct, true}, /* eclct */ + /* {Boot2KnownTitleId::eclct, true}, */ /* eclct */ /* Skip launching error collection in Atmosphere to lessen telemetry. */ {Boot2KnownTitleId::npns, false}, /* npns */ {Boot2KnownTitleId::fatal, true}, /* fatal */ {Boot2KnownTitleId::ro, true}, /* ro */ From adc496b6a7d109b82dab5efa9f1e5ab6853fd48a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 2 Aug 2018 21:33:55 -0700 Subject: [PATCH 040/489] Exosphere: Change physical segment maps depending on firmware version --- exosphere/src/bootup.c | 7 ++++- exosphere/src/coldboot_init.c | 48 +++++++++++++++++++++++++++-------- exosphere/src/memory_map.h | 11 ++++++++ exosphere/src/start.s | 6 ++++- exosphere/src/warmboot_init.c | 34 ++++++++++++++++++------- 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 57e18367b..90f590841 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -147,7 +147,12 @@ void bootup_misc_mmio(void) { (void)(MAKE_MC_REG(0x014)); /* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */ - uint32_t reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); + uint32_t reset_vec; + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + reset_vec = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); + } else { + reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); + } EVP_CPU_RESET_VECTOR_0 = 0; SB_AA64_RESET_LOW_0 = reset_vec | 1; SB_AA64_RESET_HIGH_0 = 0; diff --git a/exosphere/src/coldboot_init.c b/exosphere/src/coldboot_init.c index 5cc2d43e5..65952539e 100644 --- a/exosphere/src/coldboot_init.c +++ b/exosphere/src/coldboot_init.c @@ -18,7 +18,8 @@ extern const uint8_t __start_cold[]; /* warboot_init.c */ extern unsigned int g_exosphere_target_firmware_for_init; void init_dma_controllers(unsigned int target_firmware); -void set_memory_registers_enable_mmu(void); +void set_memory_registers_enable_mmu_1x_ttbr0(void); +void set_memory_registers_enable_mmu_5x_ttbr0(void); static void identity_map_all_mappings(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_tbl) { static const uintptr_t addrs[] = { TUPLE_FOLD_LEFT_0(EVAL(IDENTIY_MAPPING_ID_MAX), _MMAPID, COMMA) }; @@ -65,22 +66,34 @@ static void warmboot_map_all_ram_segments(uintptr_t *mmu_l3_tbl) { } } -static void tzram_map_all_segments(uintptr_t *mmu_l3_tbl) { +static void tzram_map_all_segments(uintptr_t *mmu_l3_tbl, unsigned int target_firmware) { static const uintptr_t offs[] = { TUPLE_FOLD_LEFT_0(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; static const size_t increments[] = { TUPLE_FOLD_LEFT_2(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; static const bool is_executable[] = { TUPLE_FOLD_LEFT_3(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; + static const uintptr_t offs_5x[] = { TUPLE_FOLD_LEFT_0(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZ5XS, COMMA) }; + for(size_t i = 0, offset = 0; i < TZRAM_SEGMENT_ID_MAX; i++) { - tzram_map_segment(mmu_l3_tbl, TZRAM_SEGMENT_BASE + offset, 0x7C010000ull + offs[i], sizes[i], is_executable[i]); + uintptr_t off = (target_firmware < EXOSPHERE_TARGET_FIRMWARE_500) ? offs[i] : offs_5x[i]; + tzram_map_segment(mmu_l3_tbl, TZRAM_SEGMENT_BASE + offset, 0x7C010000ull + off, sizes[i], is_executable[i]); offset += increments[i]; } } -static void configure_ttbls(void) { - uintptr_t *mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - uintptr_t *mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); - uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); +static void configure_ttbls(unsigned int target_firmware) { + uintptr_t *mmu_l1_tbl; + uintptr_t *mmu_l2_tbl; + uintptr_t *mmu_l3_tbl; + if (target_firmware < EXOSPHERE_TARGET_FIRMWARE_500) { + mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); + mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); + mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + } else { + mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); + mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); + mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + } mmu_init_table(mmu_l1_tbl, 64); /* 33-bit address space */ mmu_init_table(mmu_l2_tbl, 4096); @@ -101,7 +114,7 @@ static void configure_ttbls(void) { mmio_map_all_devices(mmu_l3_tbl); lp0_entry_map_all_ram_segments(mmu_l3_tbl); warmboot_map_all_ram_segments(mmu_l3_tbl); - tzram_map_all_segments(mmu_l3_tbl); + tzram_map_all_segments(mmu_l3_tbl, target_firmware); } static void do_relocation(const coldboot_crt0_reloc_list_t *reloc_list, size_t index) { @@ -117,8 +130,17 @@ static void do_relocation(const coldboot_crt0_reloc_list_t *reloc_list, size_t i } } +uintptr_t get_coldboot_crt0_temp_stack_address(void) { + return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; +} + uintptr_t get_coldboot_crt0_stack_address(void) { - return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; + if (exosphere_get_target_firmware_for_init() < EXOSPHERE_TARGET_FIRMWARE_500) { + return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; + } else { + return TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; + } + } void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold) { @@ -154,8 +176,12 @@ void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold) /* TZRAM accesses should work normally after this point. */ init_dma_controllers(g_exosphere_target_firmware_for_init); - configure_ttbls(); - set_memory_registers_enable_mmu(); + configure_ttbls(g_exosphere_target_firmware_for_init); + if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { + set_memory_registers_enable_mmu_1x_ttbr0(); + } else { + set_memory_registers_enable_mmu_5x_ttbr0(); + } /* Copy or clear the remaining sections */ for(size_t i = 0; i < reloc_list->nb_relocs_post_mmu_init; i++) { diff --git a/exosphere/src/memory_map.h b/exosphere/src/memory_map.h index 723fc758a..41a4b8f6b 100644 --- a/exosphere/src/memory_map.h +++ b/exosphere/src/memory_map.h @@ -53,6 +53,16 @@ #define _MMAPTZS6 ( 0x1000ull, 0x1000ull, 0x02000ull, false ) /* L2 translation table */ #define _MMAPTZS7 ( 0x2000ull, 0x1000ull, 0x02000ull, false ) /* L3 translation table */ +/* TZRAM segments for 5.0.0+. (offset). */ +#define _MMAPTZ5XS0 ( 0x3000ull ) /* Warmboot crt0 sections and main code segment */ +#define _MMAPTZ5XS1 ( 0ull ) /* pk2ldr segment */ +#define _MMAPTZ5XS2 ( 0ull ) /* SPL .bss buffer, NOT mapped at startup */ +#define _MMAPTZ5XS3 ( 0ull ) /* Core 0ull1,2 stack */ +#define _MMAPTZ5XS4 ( 0x1000ull ) /* Core 3 stack */ +#define _MMAPTZ5XS5 ( 0x2000ull ) /* Secure Monitor exception vectors, some init stacks */ +#define _MMAPTZ5XS6 ( 0x10000 - 0x2000ull ) /* L2 translation table */ +#define _MMAPTZ5XS7 ( 0x10000 - 0x1000ull ) /* L3 translation table */ + #define MMIO_BASE 0x1F0080000ull #define LP0_ENTRY_RAM_SEGMENT_BASE (MMIO_BASE + 0x000100000ull) #define WARMBOOT_RAM_SEGMENT_BASE (LP0_ENTRY_RAM_SEGMENT_BASE + 0x000047000ull) /* increment seems to be arbitrary ? */ @@ -129,6 +139,7 @@ #define WARMBOOT_GET_RAM_SEGMENT_ATTRIBS(segment_id) (TUPLE_ELEM_2(CAT(_MMAPWBS, EVAL(segment_id)))) #define TZRAM_GET_SEGMENT_PA(segment_id) (0x7C010000ull + (TUPLE_ELEM_0(CAT(_MMAPTZS, EVAL(segment_id))))) +#define TZRAM_GET_SEGMENT_5X_PA(segment_id) (0x7C010000ull + (TUPLE_ELEM_0(CAT(_MMAPTZ5XS, EVAL(segment_id))))) #define TZRAM_GET_SEGMENT_ADDRESS(segment_id) (TUPLE_FOLD_LEFT_2(EVAL(segment_id), _MMAPTZS, PLUS) EVAL(TZRAM_SEGMENT_BASE)) #define TZRAM_GET_SEGMENT_SIZE(segment_id) (TUPLE_ELEM_1(CAT(_MMAPTZS, EVAL(segment_id)))) #define TZRAM_IS_SEGMENT_EXECUTABLE(segment_id) (TUPLE_ELEM_3(CAT(_MMAPTZS, EVAL(segment_id)))) diff --git a/exosphere/src/start.s b/exosphere/src/start.s index 7730bda95..38eb4ce34 100644 --- a/exosphere/src/start.s +++ b/exosphere/src/start.s @@ -101,8 +101,11 @@ __start_cold: br x16 _post_cold_crt0_reloc: - + /* Setup stack for coldboot crt0. */ msr spsel, #0 + bl get_coldboot_crt0_temp_stack_address + mov sp, x0 + mov fp, #0 bl get_coldboot_crt0_stack_address mov sp, x0 mov fp, #0 @@ -128,6 +131,7 @@ _post_cold_crt0_reloc: ldr x1, =0x80010000 /* Set size in coldboot relocation list. */ str x21, [x0, #0x8] + bl coldboot_init ldr x16, =__jump_to_main_cold diff --git a/exosphere/src/warmboot_init.c b/exosphere/src/warmboot_init.c index 1dd7d1445..91897f3ca 100644 --- a/exosphere/src/warmboot_init.c +++ b/exosphere/src/warmboot_init.c @@ -8,6 +8,9 @@ #undef MC_BASE #define MC_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC)) +#define WARMBOOT_GET_TZRAM_SEGMENT_PA(x) ((g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) \ + ? TZRAM_GET_SEGMENT_PA(x) : TZRAM_GET_SEGMENT_5X_PA(x)) + /* start.s */ void __set_memory_registers(uintptr_t ttbr0, uintptr_t vbar, uint64_t cpuectlr, uint32_t scr, uint32_t tcr, uint32_t cptr, uint64_t mair, uint32_t sctlr); @@ -15,16 +18,16 @@ void __set_memory_registers(uintptr_t ttbr0, uintptr_t vbar, uint64_t cpuectlr, unsigned int g_exosphere_target_firmware_for_init = 0; uintptr_t get_warmboot_crt0_stack_address(void) { - return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE012_STACK) + 0x800; + return WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE012_STACK) + 0x800; } uintptr_t get_warmboot_crt0_stack_address_critsec_enter(void) { unsigned int core_id = get_core_id(); if (core_id) { - return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x1000; + return WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x1000; } else { - return TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x80 * (core_id + 1); + return WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x80 * (core_id + 1); } } @@ -89,9 +92,8 @@ void init_dma_controllers(unsigned int target_firmware) { } } -void set_memory_registers_enable_mmu(void) { +void _set_memory_registers_enable_mmu(const uintptr_t ttbr0) { static const uintptr_t vbar = TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800; - static const uintptr_t ttbr0 = TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64; /* - Disable table walk descriptor access prefetch. @@ -142,12 +144,22 @@ void set_memory_registers_enable_mmu(void) { __set_memory_registers(ttbr0, vbar, cpuectlr, scr, tcr, cptr, mair, sctlr); } +void set_memory_registers_enable_mmu_1x_ttbr0(void) { + static const uintptr_t ttbr0 = TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64; + _set_memory_registers_enable_mmu(ttbr0); +} + +void set_memory_registers_enable_mmu_5x_ttbr0(void) { + static const uintptr_t ttbr0 = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64; + _set_memory_registers_enable_mmu(ttbr0); +} + #if 0 /* Since we decided not to identity-unmap TZRAM */ static void identity_remap_tzram(void) { /* See also: configure_ttbls (in coldboot_init.c). */ - uintptr_t *mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - uintptr_t *mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); - uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + uintptr_t *mmu_l1_tbl = (uintptr_t *)(WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); + uintptr_t *mmu_l2_tbl = (uintptr_t *)WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); + uintptr_t *mmu_l3_tbl = (uintptr_t *)WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); mmu_map_table(1, mmu_l1_tbl, 0x40000000, mmu_l2_tbl, 0); mmu_map_table(2, mmu_l2_tbl, 0x7C000000, mmu_l3_tbl, 0); @@ -176,5 +188,9 @@ void warmboot_init(void) { /*identity_remap_tzram();*/ /* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */ - set_memory_registers_enable_mmu(); + if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { + set_memory_registers_enable_mmu_1x_ttbr0(); + } else { + set_memory_registers_enable_mmu_5x_ttbr0(); + } } From 294f05ea562b3999e303f2c968e36e4c65bda537 Mon Sep 17 00:00:00 2001 From: Pika <15848969+ThatNerdyPikachu@users.noreply.github.com> Date: Thu, 2 Aug 2018 16:32:51 -0400 Subject: [PATCH 041/489] make all (working) sysmodules compile --- stratosphere/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/Makefile b/stratosphere/Makefile index a14b69ffe..1c1e5b1e5 100644 --- a/stratosphere/Makefile +++ b/stratosphere/Makefile @@ -1,4 +1,4 @@ -KIPS := loader pm sm boot +KIPS := loader pm sm boot fs_mitm creport #TODO: boot2 ? From 761ab4fcfe128086b59ddb24adcc8ea618ee8de1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 10 Aug 2018 19:51:59 -0700 Subject: [PATCH 042/489] Creport: Update makefile to build npdm/nsp --- .gitignore | 2 ++ stratosphere/creport/Makefile | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e3c4e615c..e39d9f114 100644 --- a/.gitignore +++ b/.gitignore @@ -41,7 +41,9 @@ *.nso *.nro *.nacp +*.npdm *.pfs0 +*.nsp *.kip # Debug files diff --git a/stratosphere/creport/Makefile b/stratosphere/creport/Makefile index 9598aea90..67fd1e2f4 100644 --- a/stratosphere/creport/Makefile +++ b/stratosphere/creport/Makefile @@ -120,7 +120,7 @@ $(BUILD): #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr $(BUILD) $(TARGET).nso $(TARGET).elf + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).npdm $(TARGET).nso $(TARGET).elf #--------------------------------------------------------------------------------- @@ -132,7 +132,13 @@ DEPENDS := $(OFILES:.o=.d) #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -all : $(OUTPUT).nso +all : $(OUTPUT).nsp + +ifeq ($(strip $(APP_JSON)),) +$(OUTPUT).nsp : $(OUTPUT).nso +else +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm +endif $(OUTPUT).nso : $(OUTPUT).elf From 6c8a1a39e12fe8b71964c89f3f2acf3659be247e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 11 Aug 2018 18:46:41 -0700 Subject: [PATCH 043/489] creport: fix various issues, improve support (closes #187) -Fixes a NULL deref in thread info parsing -Heuristically uses [<buildid>] instead of rodata contents if NSO has no name segment -Adds full thread/code region dump for all firmwares, instead of just 5.x. --- .../creport/source/creport_code_info.cpp | 40 +++++++++++++++++-- .../creport/source/creport_code_info.hpp | 2 +- .../creport/source/creport_crash_report.cpp | 15 ++++--- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index c57a44df1..d7342ff62 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -36,8 +36,14 @@ void CodeList::ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr) { /* Parse CodeInfo. */ this->code_infos[this->code_count].start_address = mi.addr; this->code_infos[this->code_count].end_address = mi.addr + mi.size; - GetCodeInfoName(debug_handle, mi.addr + mi.size, this->code_infos[this->code_count].name); + GetCodeInfoName(debug_handle, mi.addr, mi.addr + mi.size, this->code_infos[this->code_count].name); GetCodeInfoBuildId(debug_handle, mi.addr + mi.size, this->code_infos[this->code_count].build_id); + if (this->code_infos[this->code_count].name[0] == '\x00') { + snprintf(this->code_infos[this->code_count].name, 0x1F, "[%02x%02x%02x%02x]", this->code_infos[this->code_count].build_id[0], + this->code_infos[this->code_count].build_id[1], + this->code_infos[this->code_count].build_id[2], + this->code_infos[this->code_count].build_id[3]); + } this->code_count++; } @@ -79,23 +85,49 @@ bool CodeList::TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address) { return false; } -void CodeList::GetCodeInfoName(u64 debug_handle, u64 rodata_addr, char *name) { +void CodeList::GetCodeInfoName(u64 debug_handle, u64 rx_address, u64 rodata_addr, char *name) { char name_in_proc[0x200]; /* Clear name. */ memset(name, 0, 0x20); + + /* Check whether this NSO *has* a name... */ + { + u64 rodata_start[0x20/sizeof(u64)]; + MemoryInfo mi; + u32 pi; + u64 rw_address; + + /* Verify .rodata is read-only. */ + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, rodata_addr)) || mi.perm != Perm_R) { + return; + } + + /* rwdata is after rodata. */ + rw_address = mi.addr + mi.size; + + /* Read start of .rodata. */ + if (R_FAILED(svcReadDebugProcessMemory(rodata_start, debug_handle, rodata_addr, sizeof(rodata_start)))) { + return; + } + + /* Check if name section is present. */ + if (rodata_start[0] == (rw_address - rx_address)) { + return; + } + } /* Read name out of .rodata. */ if (R_FAILED(svcReadDebugProcessMemory(name_in_proc, debug_handle, rodata_addr + 8, sizeof(name_in_proc)))) { return; } - + /* Start after last slash in path. */ int ofs = strnlen(name_in_proc, sizeof(name_in_proc)); while (ofs >= 0 && name_in_proc[ofs] != '/' && name_in_proc[ofs] != '\\') { ofs--; } - + strncpy(name, name_in_proc + ofs + 1, 0x20); name[0x1F] = '\x00'; } diff --git a/stratosphere/creport/source/creport_code_info.hpp b/stratosphere/creport/source/creport_code_info.hpp index 18aa17b23..45b1cd10f 100644 --- a/stratosphere/creport/source/creport_code_info.hpp +++ b/stratosphere/creport/source/creport_code_info.hpp @@ -25,6 +25,6 @@ class CodeList { void SaveToFile(FILE *f_report); private: bool TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address); - void GetCodeInfoName(u64 debug_handle, u64 ro_address, char *name); + void GetCodeInfoName(u64 debug_handle, u64 rx_address, u64 ro_address, char *name); void GetCodeInfoBuildId(u64 debug_handle, u64 ro_address, u8 *build_id); }; diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index f687b00b3..4ad39ecd4 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -11,10 +11,9 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { this->has_extra_info = has_extra_info; if (OpenProcess(pid)) { ProcessExceptions(); - if (kernelAbove500()) { - this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR()); - this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); - } + this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR()); + this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); + this->crashed_thread_info.SetCodeList(&this->code_list); this->thread_list.SetCodeList(&this->code_list); if (IsApplication()) { @@ -287,11 +286,11 @@ void CrashReport::SaveToFile(FILE *f_report) { fprintf(f_report, " Size: 0x%016lx\n", this->dying_message_size); CrashReport::Memdump(f_report, " Dying Message: ", this->dying_message, this->dying_message_size); } - fprintf(f_report, "Code Region Info:\n"); - this->code_list.SaveToFile(f_report); - fprintf(f_report, "\nThread Report:\n"); - this->thread_list.SaveToFile(f_report); } + fprintf(f_report, "Code Region Info:\n"); + this->code_list.SaveToFile(f_report); + fprintf(f_report, "\nThread Report:\n"); + this->thread_list.SaveToFile(f_report); } /* Lifted from hactool. */ From 326d58e28c6df6f8e42422fe0ffae86a78a8ab75 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 11 Aug 2018 19:02:12 -0700 Subject: [PATCH 044/489] creport: tabs -> spaces --- .../creport/source/creport_code_info.cpp | 68 +++++++++---------- .../creport/source/creport_crash_report.cpp | 14 ++-- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index d7342ff62..b9ddc7434 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -38,12 +38,12 @@ void CodeList::ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr) { this->code_infos[this->code_count].end_address = mi.addr + mi.size; GetCodeInfoName(debug_handle, mi.addr, mi.addr + mi.size, this->code_infos[this->code_count].name); GetCodeInfoBuildId(debug_handle, mi.addr + mi.size, this->code_infos[this->code_count].build_id); - if (this->code_infos[this->code_count].name[0] == '\x00') { - snprintf(this->code_infos[this->code_count].name, 0x1F, "[%02x%02x%02x%02x]", this->code_infos[this->code_count].build_id[0], - this->code_infos[this->code_count].build_id[1], - this->code_infos[this->code_count].build_id[2], - this->code_infos[this->code_count].build_id[3]); - } + if (this->code_infos[this->code_count].name[0] == '\x00') { + snprintf(this->code_infos[this->code_count].name, 0x1F, "[%02x%02x%02x%02x]", this->code_infos[this->code_count].build_id[0], + this->code_infos[this->code_count].build_id[1], + this->code_infos[this->code_count].build_id[2], + this->code_infos[this->code_count].build_id[3]); + } this->code_count++; } @@ -90,44 +90,44 @@ void CodeList::GetCodeInfoName(u64 debug_handle, u64 rx_address, u64 rodata_addr /* Clear name. */ memset(name, 0, 0x20); - - /* Check whether this NSO *has* a name... */ - { - u64 rodata_start[0x20/sizeof(u64)]; - MemoryInfo mi; - u32 pi; - u64 rw_address; - - /* Verify .rodata is read-only. */ - if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, rodata_addr)) || mi.perm != Perm_R) { - return; - } - - /* rwdata is after rodata. */ - rw_address = mi.addr + mi.size; - - /* Read start of .rodata. */ - if (R_FAILED(svcReadDebugProcessMemory(rodata_start, debug_handle, rodata_addr, sizeof(rodata_start)))) { - return; - } - - /* Check if name section is present. */ - if (rodata_start[0] == (rw_address - rx_address)) { - return; - } - } + + /* Check whether this NSO *has* a name... */ + { + u64 rodata_start[0x20/sizeof(u64)]; + MemoryInfo mi; + u32 pi; + u64 rw_address; + + /* Verify .rodata is read-only. */ + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, rodata_addr)) || mi.perm != Perm_R) { + return; + } + + /* rwdata is after rodata. */ + rw_address = mi.addr + mi.size; + + /* Read start of .rodata. */ + if (R_FAILED(svcReadDebugProcessMemory(rodata_start, debug_handle, rodata_addr, sizeof(rodata_start)))) { + return; + } + + /* Check if name section is present. */ + if (rodata_start[0] == (rw_address - rx_address)) { + return; + } + } /* Read name out of .rodata. */ if (R_FAILED(svcReadDebugProcessMemory(name_in_proc, debug_handle, rodata_addr + 8, sizeof(name_in_proc)))) { return; } - + /* Start after last slash in path. */ int ofs = strnlen(name_in_proc, sizeof(name_in_proc)); while (ofs >= 0 && name_in_proc[ofs] != '/' && name_in_proc[ofs] != '\\') { ofs--; } - + strncpy(name, name_in_proc + ofs + 1, 0x20); name[0x1F] = '\x00'; } diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 4ad39ecd4..01994e1e6 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -11,9 +11,9 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { this->has_extra_info = has_extra_info; if (OpenProcess(pid)) { ProcessExceptions(); - this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR()); - this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); - this->crashed_thread_info.SetCodeList(&this->code_list); + this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR()); + this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); + this->crashed_thread_info.SetCodeList(&this->code_list); this->thread_list.SetCodeList(&this->code_list); if (IsApplication()) { @@ -287,10 +287,10 @@ void CrashReport::SaveToFile(FILE *f_report) { CrashReport::Memdump(f_report, " Dying Message: ", this->dying_message, this->dying_message_size); } } - fprintf(f_report, "Code Region Info:\n"); - this->code_list.SaveToFile(f_report); - fprintf(f_report, "\nThread Report:\n"); - this->thread_list.SaveToFile(f_report); + fprintf(f_report, "Code Region Info:\n"); + this->code_list.SaveToFile(f_report); + fprintf(f_report, "\nThread Report:\n"); + this->thread_list.SaveToFile(f_report); } /* Lifted from hactool. */ From de49cfefac15fb83d9f30e1bcdfef9685cb95425 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 11 Aug 2018 19:16:29 -0700 Subject: [PATCH 045/489] creport: Print Break information on UserBreak --- stratosphere/creport/source/creport_crash_report.cpp | 5 +++++ stratosphere/creport/source/creport_debug_types.hpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 01994e1e6..30059d1de 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -272,6 +272,11 @@ void CrashReport::SaveToFile(FILE *f_report) { case DebugExceptionType::BadSvc: fprintf(f_report, " Svc Id: 0x%02x\n", this->exception_info.specific.bad_svc.id); break; + case DebugExceptionType::UserBreak: + fprintf(f_report, " Break Reason: 0x%lx\n", this->exception_info.specific.user_break.break_reason); + fprintf(f_report, " Break Address: %s\n", this->code_list.GetFormattedAddressString(this->exception_info.specific.user_break.address)); + fprintf(f_report, " Break Size: 0x%lx\n", this->exception_info.specific.user_break.size); + break; default: break; } diff --git a/stratosphere/creport/source/creport_debug_types.hpp b/stratosphere/creport/source/creport_debug_types.hpp index 22421dbba..44daa7f67 100644 --- a/stratosphere/creport/source/creport_debug_types.hpp +++ b/stratosphere/creport/source/creport_debug_types.hpp @@ -76,7 +76,7 @@ struct AlignmentFaultInfo { }; struct UserBreakInfo { - u64 info_0; + u64 break_reason; u64 address; u64 size; }; From f41aaccaa2bffc8468f3ec482c82063a4640b7e2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 16 Aug 2018 18:45:38 -0700 Subject: [PATCH 046/489] exosphere: commit WIP warmboot progress -15+ bugs fixed -We now receive ~0x400 SMCs from user processes (including from psm) on wake-from-sleep --- exosphere/src/bootconfig.h | 1 - exosphere/src/bootup.c | 2 +- exosphere/src/bpmpfw_debug.h | 8 ++++++++ exosphere/src/car.h | 2 ++ exosphere/src/cpu_context.c | 24 ++++++++++++++++++++---- exosphere/src/lp0.c | 32 ++++++++++++++++++++++++-------- exosphere/src/package2.c | 30 ++++++++++++++++++++++++++---- exosphere/src/smc_api.c | 7 ++++++- exosphere/src/smc_api.h | 3 +++ exosphere/src/start.s | 6 ++++-- exosphere/src/warmboot_init.c | 7 ++++--- exosphere/src/warmboot_main.c | 8 +++++++- 12 files changed, 105 insertions(+), 25 deletions(-) create mode 100644 exosphere/src/bpmpfw_debug.h diff --git a/exosphere/src/bootconfig.h b/exosphere/src/bootconfig.h index f5505f4ab..823323a03 100644 --- a/exosphere/src/bootconfig.h +++ b/exosphere/src/bootconfig.h @@ -26,7 +26,6 @@ typedef struct { bootconfig_unsigned_config_t unsigned_config; uint8_t signature[0x100]; bootconfig_signed_config_t signed_config; - uint8_t unused_space[0x240]; /* remaining space in the evt page */ } bootconfig_t; static inline bootconfig_t *get_loaded_bootconfig(void) { diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 90f590841..7a945ec8f 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -268,7 +268,7 @@ void setup_current_core_state(void) { uint64_t temp_reg; /* Setup system registers. */ - SET_SYSREG(spsr_el3, 0b1111 << 6 | 0b1001); /* use EL2h+DAIF set initially, may be overwritten later. Not in official code */ + SET_SYSREG(spsr_el3, 0b1111 << 6 | 0b0101); /* use EL2h+DAIF set initially, may be overwritten later. Not in official code */ SET_SYSREG(actlr_el3, 0x73ull); SET_SYSREG(actlr_el2, 0x73ull); diff --git a/exosphere/src/bpmpfw_debug.h b/exosphere/src/bpmpfw_debug.h new file mode 100644 index 000000000..c61d2d14c --- /dev/null +++ b/exosphere/src/bpmpfw_debug.h @@ -0,0 +1,8 @@ +#ifndef EXOSPHERE_BPMPFW_DEBUG_H +#define EXOSPHERE_BPMPFW_DEBUG_H + +static const unsigned char g_bpmpfw_for_debug[0x584] = { + /* ... */ +}; + +#endif \ No newline at end of file diff --git a/exosphere/src/car.h b/exosphere/src/car.h index 3fb511bc2..7d489d2c4 100644 --- a/exosphere/src/car.h +++ b/exosphere/src/car.h @@ -14,6 +14,8 @@ #define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 MAKE_CAR_REG(0x048) #define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) +#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) +#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454) #define NUM_CAR_BANKS 7 diff --git a/exosphere/src/cpu_context.c b/exosphere/src/cpu_context.c index d952d7879..853519236 100644 --- a/exosphere/src/cpu_context.c +++ b/exosphere/src/cpu_context.c @@ -2,6 +2,8 @@ #include <stdint.h> #include "arm.h" #include "cpu_context.h" +#include "car.h" +#include "exocfg.h" #include "flow.h" #include "pmc.h" #include "timers.h" @@ -18,7 +20,7 @@ #define RESTORE_SYSREG64(reg) do { temp_reg = g_cpu_contexts[current_core].reg; __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false) #define RESTORE_SYSREG32(reg) RESTORE_SYSREG64(reg) #define RESTORE_BP_REG(i, _) RESTORE_SYSREG64(DBGBVR##i##_EL1); RESTORE_SYSREG64(DBGBCR##i##_EL1); -#define RESTORE_WP_REG(i, _) RESTORE_SYSREG64(DBGBVR##i##_EL1); RESTORE_SYSREG64(DBGBCR##i##_EL1); +#define RESTORE_WP_REG(i, _) RESTORE_SYSREG64(DBGWVR##i##_EL1); RESTORE_SYSREG64(DBGWCR##i##_EL1); /* start.s */ void __attribute__((noreturn)) __jump_to_lower_el(uint64_t arg, uintptr_t ep, uint32_t spsr); @@ -79,8 +81,13 @@ uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) { set_core_entrypoint_and_argument(core, entrypoint_addr, argument); - const uint32_t status_masks[NUM_CPU_CORES] = {0x4000, 0x200, 0x400, 0x800}; - const uint32_t toggle_vals[NUM_CPU_CORES] = {0xE, 0x9, 0xA, 0xB}; + static const uint32_t status_masks[NUM_CPU_CORES] = {0x4000, 0x200, 0x400, 0x800}; + static const uint32_t toggle_vals[NUM_CPU_CORES] = {0xE, 0x9, 0xA, 0xB}; + + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + /* Reset the core */ + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 = (1 << (core + 0x10)) | (1 << core); + } /* Check if we're already in the correct state. */ if ((APBDEV_PMC_PWRGATE_STATUS_0 & status_masks[core]) != status_masks[core]) { @@ -91,7 +98,7 @@ uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) { wait(1); counter--; if (counter < 1) { - return 0; + goto CPU_ON_SUCCESS; } } @@ -108,6 +115,13 @@ uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) { counter--; } } + +CPU_ON_SUCCESS: + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + /* Start the core */ + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = (1 << (core + 0x10)) | (1 << core); + } + return 0; } @@ -145,6 +159,7 @@ void save_current_core_context(void) { /* Save system registers. */ SAVE_SYSREG32(OSDTRRX_EL1); + SAVE_SYSREG32(OSDTRTX_EL1); SAVE_SYSREG32(MDSCR_EL1); SAVE_SYSREG32(OSECCR_EL1); SAVE_SYSREG32(MDCCINT_EL1); @@ -168,6 +183,7 @@ void restore_current_core_context(void) { if (g_cpu_contexts[current_core].is_saved) { RESTORE_SYSREG32(OSDTRRX_EL1); + RESTORE_SYSREG32(OSDTRTX_EL1); RESTORE_SYSREG32(MDSCR_EL1); RESTORE_SYSREG32(OSECCR_EL1); RESTORE_SYSREG32(MDCCINT_EL1); diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c index 33041e9d9..e52e3ae52 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/lp0.c @@ -23,16 +23,21 @@ #define u8 uint8_t #define u32 uint32_t -#include "bpmpfw_bin.h" +#include "bpmpfw_debug.h" #undef u8 #undef u32 /* Save security engine, and go to sleep. */ void save_se_and_power_down_cpu(void) { + /* TODO: Remove set suspend call once exo warmboots fully */ + set_suspend_for_debug(); uint32_t tzram_cmac[0x4] = {0}; uint8_t *tzram_encryption_dst = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM)); uint8_t *tzram_encryption_src = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM)); + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + tzram_encryption_src += 0x2000ull; + } uint8_t *tzram_store_address = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_TZRAM)); clear_priv_smc_in_progress(); @@ -45,17 +50,20 @@ void save_se_and_power_down_cpu(void) { flush_dcache_range(tzram_encryption_dst, tzram_encryption_dst + LP0_TZRAM_SAVE_SIZE); flush_dcache_range(tzram_encryption_src, tzram_encryption_src + LP0_TZRAM_SAVE_SIZE); - /* Use the all-zero cmac buffer as an IV. */ + /* Use the all-zero cmac buffer as an IV. */ se_aes_256_cbc_encrypt(KEYSLOT_SWITCH_LP0TZRAMKEY, tzram_encryption_dst, LP0_TZRAM_SAVE_SIZE, tzram_encryption_src, LP0_TZRAM_SAVE_SIZE, tzram_cmac); flush_dcache_range(tzram_encryption_dst, tzram_encryption_dst + LP0_TZRAM_SAVE_SIZE); /* Copy encrypted TZRAM from IRAM to DRAM. */ - memcpy(tzram_store_address, tzram_encryption_dst, LP0_TZRAM_SAVE_SIZE); + for (unsigned int i = 0; i < LP0_TZRAM_SAVE_SIZE; i += 4) { + write32le(tzram_store_address, i, read32le(tzram_encryption_dst, i)); + } + flush_dcache_range(tzram_store_address, tzram_store_address + LP0_TZRAM_SAVE_SIZE); /* Compute CMAC. */ se_compute_aes_256_cmac(KEYSLOT_SWITCH_LP0TZRAMKEY, tzram_cmac, sizeof(tzram_cmac), tzram_encryption_src, LP0_TZRAM_SAVE_SIZE); - + /* Write CMAC, lock registers. */ APBDEV_PMC_SECURE_SCRATCH112_0 = tzram_cmac[0]; APBDEV_PMC_SECURE_SCRATCH113_0 = tzram_cmac[1]; @@ -76,6 +84,8 @@ void save_se_and_power_down_cpu(void) { if (!configitem_is_retail()) { /* TODO: uart_log("OYASUMI"); */ } + + __dsb_sy(); finalize_powerdown(); } @@ -85,6 +95,7 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen if ((power_state & 0x17FFF) != 0x1001B) { return 0xFFFFFFFD; } + unsigned int current_core = get_core_id(); @@ -169,14 +180,17 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen BPMP_VECTOR_UNK = 0x40003004; /* Reboot. */ BPMP_VECTOR_IRQ = 0x40003004; /* Reboot. */ BPMP_VECTOR_FIQ = 0x40003004; /* Reboot. */ - + /* Hold the BPMP in reset. */ MAKE_CAR_REG(0x300) = 2; /* Copy BPMP firmware. */ uint8_t *lp0_entry_code = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE)); - memcpy(lp0_entry_code, bpmpfw_bin, bpmpfw_bin_size); - flush_dcache_range(lp0_entry_code, lp0_entry_code + bpmpfw_bin_size); + for (unsigned int i = 0; i < sizeof(g_bpmpfw_for_debug); i += 4) { + write32le(lp0_entry_code, i, read32le(g_bpmpfw_for_debug, i)); + } + + flush_dcache_range(lp0_entry_code, lp0_entry_code + sizeof(g_bpmpfw_for_debug)); /* Take the BPMP out of reset. */ MAKE_CAR_REG(0x304) = 2; @@ -188,11 +202,13 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen flow_set_halt_events(current_core, false); FLOW_CTLR_L2FLUSH_CONTROL_0 = 0; flow_set_csr(current_core, 2); - + /* Save core context. */ set_core_entrypoint_and_argument(current_core, entrypoint, argument); save_current_core_context(); set_current_core_inactive(); + + call_with_stack_pointer(get_smc_core012_stack_address(), save_se_and_power_down_cpu); generic_panic(); diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 507acb1fa..26db12510 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -382,13 +382,32 @@ static void load_package2_sections(package2_meta_t *metadata, uint32_t master_ke memset(load_buf, 0, PACKAGE2_SIZE_MAX); } +static void copy_warmboot_bin_to_dram() { + uint8_t *warmboot_src = (uint8_t *)0x4003B000; + uint8_t *warmboot_dst = (uint8_t *)0x8000D000; + const size_t warmboot_size = 0x2000; + + /* Flush cache, to ensure warmboot is where we need it to be. */ + flush_dcache_range(warmboot_src, warmboot_src + warmboot_size); + __dsb_sy(); + + /* Copy warmboot. */ + for (size_t i = 0; i < warmboot_size; i += sizeof(uint32_t)) { + write32le(warmboot_dst, i, read32le(warmboot_src, i)); + } + + /* Flush cache, to ensure warmboot is where we need it to be. */ + flush_dcache_range(warmboot_dst, warmboot_dst + warmboot_size); + __dsb_sy(); +} + static void sync_with_nx_bootloader(int state) { while (MAILBOX_NX_BOOTLOADER_SETUP_STATE < state) { wait(100); } } -static void indentity_unmap_dram(void) { +static void identity_unmap_dram(void) { uintptr_t *mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); mmu_unmap_range(1, mmu_l1_tbl, IDENTITY_GET_MAPPING_ADDRESS(IDENTITY_MAPPING_DRAM), IDENTITY_GET_MAPPING_SIZE(IDENTITY_MAPPING_DRAM)); @@ -410,6 +429,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { /* Perform initial PMC register writes, if relevant. */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + MAKE_REG32(PMC_BASE + 0x054) = 0x8000D000; MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF; MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE; MAKE_REG32(PMC_BASE + 0x334) |= 0x10; @@ -453,7 +473,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { /* Synchronize with NX BOOTLOADER. */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { sync_with_nx_bootloader(NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X); - /* TODO: copy_warmboot_bin_to_dram(); */ + copy_warmboot_bin_to_dram(); sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X); } else { sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2); @@ -461,7 +481,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { /* Make PMC (2.x+), MC (4.x+) registers secure-only */ secure_additional_devices(); - + /* Remove the identity mapping for iRAM-C+D & TZRAM */ /* For our crt0 to work, this doesn't actually unmap TZRAM */ identity_unmap_iram_cd_tzram(); @@ -499,7 +519,9 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { set_core_entrypoint_and_argument(0, DRAM_BASE_PHYSICAL + header.metadata.entrypoint, 0); /* Remove the DRAM identity mapping. */ - indentity_unmap_dram(); + if (0) { + identity_unmap_dram(); + } /* Synchronize with NX BOOTLOADER. */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index 23c5cb728..063611a0a 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -121,6 +121,11 @@ static atomic_flag g_is_priv_smc_in_progress = ATOMIC_FLAG_INIT; /* Global for smc_configure_carveout. */ static bool g_configured_carveouts[2] = {false, false}; +static bool g_has_suspended = false; +void set_suspend_for_debug(void) { + g_has_suspended = true; +} + void set_version_specific_smcs(void) { switch (exosphere_get_target_firmware()) { case EXOSPHERE_TARGET_FIRMWARE_100: @@ -207,7 +212,7 @@ void call_smc_handler(uint32_t handler_id, smc_args_t *args) { unsigned char smc_id; unsigned int result; unsigned int (*smc_handler)(smc_args_t *args); - + /* Validate top-level handler. */ if (handler_id != SMC_HANDLER_USER && handler_id != SMC_HANDLER_PRIV) { generic_panic(); diff --git a/exosphere/src/smc_api.h b/exosphere/src/smc_api.h index 3d2a46a79..80eb5bcb3 100644 --- a/exosphere/src/smc_api.h +++ b/exosphere/src/smc_api.h @@ -22,6 +22,9 @@ uintptr_t get_exception_entry_stack_address(unsigned int core_id); void set_version_specific_smcs(void); + +void set_suspend_for_debug(void); + void call_smc_handler(unsigned int handler_id, smc_args_t *args); #endif diff --git a/exosphere/src/start.s b/exosphere/src/start.s index 38eb4ce34..185291859 100644 --- a/exosphere/src/start.s +++ b/exosphere/src/start.s @@ -223,8 +223,8 @@ __jump_to_main_warm: bl __set_exception_entry_stack_pointer mov w0, #0 /* use core0,1,2 stack bottom + 0x800 (VA of warmboot crt0 sp) temporarily */ - bl get_exception_entry_stack_address - add sp, x0, #0x800 + bl get_warmboot_main_stack_address + mov sp, x0 bl warmboot_main .section .text.__set_exception_entry_stack, "ax", %progbits @@ -248,12 +248,14 @@ __set_exception_entry_stack_pointer: .type __jump_to_lower_el, %function __jump_to_lower_el: /* x0: arg (context ID), x1: entrypoint, w2: spsr */ + mov x19, x0 mov w2, w2 msr elr_el3, x1 msr spsr_el3, x2 bl __set_exception_entry_stack_pointer + mov x0, x19 isb eret diff --git a/exosphere/src/warmboot_init.c b/exosphere/src/warmboot_init.c index 91897f3ca..d3d73374c 100644 --- a/exosphere/src/warmboot_init.c +++ b/exosphere/src/warmboot_init.c @@ -4,6 +4,7 @@ #include "arm.h" #include "synchronization.h" #include "exocfg.h" +#include "pmc.h" #undef MC_BASE #define MC_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC)) @@ -24,7 +25,7 @@ uintptr_t get_warmboot_crt0_stack_address(void) { uintptr_t get_warmboot_crt0_stack_address_critsec_enter(void) { unsigned int core_id = get_core_id(); - if (core_id) { + if (core_id == 3) { return WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x1000; } else { return WARMBOOT_GET_TZRAM_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x80 * (core_id + 1); @@ -180,12 +181,12 @@ void warmboot_init(void) { */ flush_dcache_all(); invalidate_icache_all(); - + /* On warmboot (not cpu_on) only */ if (MC_SECURITY_CFG3_0 == 0) { init_dma_controllers(g_exosphere_target_firmware_for_init); } - + /*identity_remap_tzram();*/ /* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */ if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { diff --git a/exosphere/src/warmboot_main.c b/exosphere/src/warmboot_main.c index 01e127df6..1c9a9ad9e 100644 --- a/exosphere/src/warmboot_main.c +++ b/exosphere/src/warmboot_main.c @@ -16,6 +16,12 @@ #include "misc.h" #include "interrupt.h" +#include "pmc.h" + +uintptr_t get_warmboot_main_stack_address(void) { + return TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x780; +} + void __attribute__((noreturn)) warmboot_main(void) { /* This function and its callers are reached in either of the following events, under normal conditions: @@ -53,7 +59,7 @@ void __attribute__((noreturn)) warmboot_main(void) { PINMUX_AUX_GEN1_I2C_SCL_0 = 0x40; PINMUX_AUX_GEN1_I2C_SDA_0 = 0x40; - clkrst_enable(CARDEVICE_I2C1); + clkrst_reboot(CARDEVICE_I2C1); i2c_init(0); i2c_clear_ti_charger_bit_7(); clkrst_disable(CARDEVICE_I2C1); From ee0117b59ededc829604aa01b7773b3a5b53cf60 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 16 Aug 2018 18:56:04 -0700 Subject: [PATCH 047/489] exo: tabs->spaces... --- exosphere/src/arm.s | 4 ++-- exosphere/src/bootup.c | 6 ++--- exosphere/src/coldboot_init.c | 44 +++++++++++++++++------------------ exosphere/src/lp0.c | 8 +++---- exosphere/src/start.s | 4 ++-- exosphere/src/warmboot_init.c | 16 ++++++------- 6 files changed, 41 insertions(+), 41 deletions(-) diff --git a/exosphere/src/arm.s b/exosphere/src/arm.s index 7cf4d0cda..b1dc29109 100644 --- a/exosphere/src/arm.s +++ b/exosphere/src/arm.s @@ -51,7 +51,7 @@ tlb_invalidate_page_inner_shareable: * * This file is based on sample code from ARMv8 ARM. * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0+ */ /* @@ -84,7 +84,7 @@ __asm_dcache_level: /* x5 <- bit position of #ways */ loop_set: - mov x6, x3 /* x6 <- working copy of #ways */ + mov x6, x3 /* x6 <- working copy of #ways */ loop_way: lsl x7, x6, x5 orr x9, x12, x7 /* map way and level to cisw value */ diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 7a945ec8f..a1fd2522a 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -149,10 +149,10 @@ void bootup_misc_mmio(void) { /* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */ uint32_t reset_vec; if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { - reset_vec = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); + reset_vec = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); } else { - reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); - } + reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); + } EVP_CPU_RESET_VECTOR_0 = 0; SB_AA64_RESET_LOW_0 = reset_vec | 1; SB_AA64_RESET_HIGH_0 = 0; diff --git a/exosphere/src/coldboot_init.c b/exosphere/src/coldboot_init.c index 65952539e..c88704638 100644 --- a/exosphere/src/coldboot_init.c +++ b/exosphere/src/coldboot_init.c @@ -73,9 +73,9 @@ static void tzram_map_all_segments(uintptr_t *mmu_l3_tbl, unsigned int target_fi static const bool is_executable[] = { TUPLE_FOLD_LEFT_3(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZS, COMMA) }; static const uintptr_t offs_5x[] = { TUPLE_FOLD_LEFT_0(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZ5XS, COMMA) }; - + for(size_t i = 0, offset = 0; i < TZRAM_SEGMENT_ID_MAX; i++) { - uintptr_t off = (target_firmware < EXOSPHERE_TARGET_FIRMWARE_500) ? offs[i] : offs_5x[i]; + uintptr_t off = (target_firmware < EXOSPHERE_TARGET_FIRMWARE_500) ? offs[i] : offs_5x[i]; tzram_map_segment(mmu_l3_tbl, TZRAM_SEGMENT_BASE + offset, 0x7C010000ull + off, sizes[i], is_executable[i]); offset += increments[i]; } @@ -85,15 +85,15 @@ static void configure_ttbls(unsigned int target_firmware) { uintptr_t *mmu_l1_tbl; uintptr_t *mmu_l2_tbl; uintptr_t *mmu_l3_tbl; - if (target_firmware < EXOSPHERE_TARGET_FIRMWARE_500) { - mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); - mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - } else { - mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); - mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); - mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); - } + if (target_firmware < EXOSPHERE_TARGET_FIRMWARE_500) { + mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); + mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); + mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + } else { + mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); + mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); + mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + } mmu_init_table(mmu_l1_tbl, 64); /* 33-bit address space */ mmu_init_table(mmu_l2_tbl, 4096); @@ -131,15 +131,15 @@ static void do_relocation(const coldboot_crt0_reloc_list_t *reloc_list, size_t i } uintptr_t get_coldboot_crt0_temp_stack_address(void) { - return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; + return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; } uintptr_t get_coldboot_crt0_stack_address(void) { - if (exosphere_get_target_firmware_for_init() < EXOSPHERE_TARGET_FIRMWARE_500) { - return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; - } else { - return TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; - } + if (exosphere_get_target_firmware_for_init() < EXOSPHERE_TARGET_FIRMWARE_500) { + return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; + } else { + return TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; + } } @@ -177,11 +177,11 @@ void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold) init_dma_controllers(g_exosphere_target_firmware_for_init); configure_ttbls(g_exosphere_target_firmware_for_init); - if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { - set_memory_registers_enable_mmu_1x_ttbr0(); - } else { - set_memory_registers_enable_mmu_5x_ttbr0(); - } + if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { + set_memory_registers_enable_mmu_1x_ttbr0(); + } else { + set_memory_registers_enable_mmu_5x_ttbr0(); + } /* Copy or clear the remaining sections */ for(size_t i = 0; i < reloc_list->nb_relocs_post_mmu_init; i++) { diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c index e52e3ae52..520042c5c 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/lp0.c @@ -29,15 +29,15 @@ /* Save security engine, and go to sleep. */ void save_se_and_power_down_cpu(void) { - /* TODO: Remove set suspend call once exo warmboots fully */ + /* TODO: Remove set suspend call once exo warmboots fully */ set_suspend_for_debug(); uint32_t tzram_cmac[0x4] = {0}; uint8_t *tzram_encryption_dst = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM)); uint8_t *tzram_encryption_src = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM)); - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { - tzram_encryption_src += 0x2000ull; - } + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + tzram_encryption_src += 0x2000ull; + } uint8_t *tzram_store_address = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_TZRAM)); clear_priv_smc_in_progress(); diff --git a/exosphere/src/start.s b/exosphere/src/start.s index 185291859..0374248da 100644 --- a/exosphere/src/start.s +++ b/exosphere/src/start.s @@ -101,7 +101,7 @@ __start_cold: br x16 _post_cold_crt0_reloc: - /* Setup stack for coldboot crt0. */ + /* Setup stack for coldboot crt0. */ msr spsel, #0 bl get_coldboot_crt0_temp_stack_address mov sp, x0 @@ -131,7 +131,7 @@ _post_cold_crt0_reloc: ldr x1, =0x80010000 /* Set size in coldboot relocation list. */ str x21, [x0, #0x8] - + bl coldboot_init ldr x16, =__jump_to_main_cold diff --git a/exosphere/src/warmboot_init.c b/exosphere/src/warmboot_init.c index d3d73374c..427792054 100644 --- a/exosphere/src/warmboot_init.c +++ b/exosphere/src/warmboot_init.c @@ -10,7 +10,7 @@ #define MC_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC)) #define WARMBOOT_GET_TZRAM_SEGMENT_PA(x) ((g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) \ - ? TZRAM_GET_SEGMENT_PA(x) : TZRAM_GET_SEGMENT_5X_PA(x)) + ? TZRAM_GET_SEGMENT_PA(x) : TZRAM_GET_SEGMENT_5X_PA(x)) /* start.s */ void __set_memory_registers(uintptr_t ttbr0, uintptr_t vbar, uint64_t cpuectlr, uint32_t scr, @@ -147,12 +147,12 @@ void _set_memory_registers_enable_mmu(const uintptr_t ttbr0) { void set_memory_registers_enable_mmu_1x_ttbr0(void) { static const uintptr_t ttbr0 = TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64; - _set_memory_registers_enable_mmu(ttbr0); + _set_memory_registers_enable_mmu(ttbr0); } void set_memory_registers_enable_mmu_5x_ttbr0(void) { static const uintptr_t ttbr0 = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64; - _set_memory_registers_enable_mmu(ttbr0); + _set_memory_registers_enable_mmu(ttbr0); } #if 0 /* Since we decided not to identity-unmap TZRAM */ @@ -189,9 +189,9 @@ void warmboot_init(void) { /*identity_remap_tzram();*/ /* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */ - if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { - set_memory_registers_enable_mmu_1x_ttbr0(); - } else { - set_memory_registers_enable_mmu_5x_ttbr0(); - } + if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { + set_memory_registers_enable_mmu_1x_ttbr0(); + } else { + set_memory_registers_enable_mmu_5x_ttbr0(); + } } From a0deea8ae0f91145ba8b59ea78596e4949461c04 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 16 Aug 2018 18:56:49 -0700 Subject: [PATCH 048/489] exo: fix SAVE_WP_REG definition --- exosphere/src/cpu_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exosphere/src/cpu_context.c b/exosphere/src/cpu_context.c index 853519236..f42ef9021 100644 --- a/exosphere/src/cpu_context.c +++ b/exosphere/src/cpu_context.c @@ -15,7 +15,7 @@ #define SAVE_SYSREG64(reg) do { __asm__ __volatile__ ("mrs %0, " #reg : "=r"(temp_reg) :: "memory"); g_cpu_contexts[current_core].reg = temp_reg; } while(false) #define SAVE_SYSREG32(reg) do { __asm__ __volatile__ ("mrs %0, " #reg : "=r"(temp_reg) :: "memory"); g_cpu_contexts[current_core].reg = (uint32_t)temp_reg; } while(false) #define SAVE_BP_REG(i, _) SAVE_SYSREG64(DBGBVR##i##_EL1); SAVE_SYSREG64(DBGBCR##i##_EL1); -#define SAVE_WP_REG(i, _) SAVE_SYSREG64(DBGBVR##i##_EL1); SAVE_SYSREG64(DBGBCR##i##_EL1); +#define SAVE_WP_REG(i, _) SAVE_SYSREG64(DBGWVR##i##_EL1); SAVE_SYSREG64(DBGWCR##i##_EL1); #define RESTORE_SYSREG64(reg) do { temp_reg = g_cpu_contexts[current_core].reg; __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false) #define RESTORE_SYSREG32(reg) RESTORE_SYSREG64(reg) From 46f68fcbff95bf9c7cf8a8944293d31618de02c8 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 16 Aug 2018 20:17:37 -0700 Subject: [PATCH 049/489] Exosphere: Fix carveout saving (warmboot now works on 5.1.0) --- exosphere/src/mc.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/exosphere/src/mc.c b/exosphere/src/mc.c index 74e9886ba..4a4aed9a5 100644 --- a/exosphere/src/mc.c +++ b/exosphere/src/mc.c @@ -4,6 +4,16 @@ #include "mc.h" #include "exocfg.h" +typedef struct { + uint64_t address; + uint64_t size; +} saved_carveout_info_t; + +static saved_carveout_info_t g_saved_carveouts[2] = { + {0x80060000ull, KERNEL_CARVEOUT_SIZE_MAX}, + {0x00000000ull, 0x00000000ull} +}; + volatile security_carveout_t *get_carveout_by_id(unsigned int carveout) { if (CARVEOUT_ID_MIN <= carveout && carveout <= CARVEOUT_ID_MAX) { return (volatile security_carveout_t *)(MC_BASE + 0xC08ull + 0x50 * (carveout - CARVEOUT_ID_MIN)); @@ -67,10 +77,10 @@ void configure_default_carveouts(void) { /* Configure default Kernel carveouts based on 2.0.0+. */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { /* Configure Carveout 4 (KERNEL_BUILTINS) */ - configure_kernel_carveout(4, 0x80060000, KERNEL_CARVEOUT_SIZE_MAX); + configure_kernel_carveout(4, g_saved_carveouts[0].address, g_saved_carveouts[0].size); /* Configure Carveout 5 (KERNEL_UNUSED) */ - configure_kernel_carveout(5, 0, 0); + configure_kernel_carveout(5, g_saved_carveouts[1].address, g_saved_carveouts[1].size); } else { for (unsigned int i = 4; i <= 5; i++) { carveout = get_carveout_by_id(i); @@ -96,6 +106,9 @@ void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint6 if (carveout_id != 4 && carveout_id != 5) { generic_panic(); } + + g_saved_carveouts[carveout_id-4].address = address; + g_saved_carveouts[carveout_id-4].size = size; volatile security_carveout_t *carveout = get_carveout_by_id(carveout_id); carveout->paddr_low = (uint32_t)(address & 0xFFFFFFFF); From 7346ede1e16b8834f5ff0359b08fadcd2ece39a6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 16 Aug 2018 20:46:33 -0700 Subject: [PATCH 050/489] exosphere: use our open source bpmpfw (warmboot still works) --- exosphere/src/bpmpfw_debug.h | 8 -------- exosphere/src/lp0.c | 8 ++++---- 2 files changed, 4 insertions(+), 12 deletions(-) delete mode 100644 exosphere/src/bpmpfw_debug.h diff --git a/exosphere/src/bpmpfw_debug.h b/exosphere/src/bpmpfw_debug.h deleted file mode 100644 index c61d2d14c..000000000 --- a/exosphere/src/bpmpfw_debug.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef EXOSPHERE_BPMPFW_DEBUG_H -#define EXOSPHERE_BPMPFW_DEBUG_H - -static const unsigned char g_bpmpfw_for_debug[0x584] = { - /* ... */ -}; - -#endif \ No newline at end of file diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c index 520042c5c..fd3b3b3a0 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/lp0.c @@ -23,7 +23,7 @@ #define u8 uint8_t #define u32 uint32_t -#include "bpmpfw_debug.h" +#include "bpmpfw_bin.h" #undef u8 #undef u32 @@ -186,11 +186,11 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen /* Copy BPMP firmware. */ uint8_t *lp0_entry_code = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE)); - for (unsigned int i = 0; i < sizeof(g_bpmpfw_for_debug); i += 4) { - write32le(lp0_entry_code, i, read32le(g_bpmpfw_for_debug, i)); + for (unsigned int i = 0; i < bpmpfw_bin_size; i += 4) { + write32le(lp0_entry_code, i, read32le(bpmpfw_bin, i)); } - flush_dcache_range(lp0_entry_code, lp0_entry_code + sizeof(g_bpmpfw_for_debug)); + flush_dcache_range(lp0_entry_code, lp0_entry_code + bpmpfw_bin_size); /* Take the BPMP out of reset. */ MAKE_CAR_REG(0x304) = 2; From d9f83ce368f59491affde70eafe34d9d6e0c9737 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 16 Aug 2018 22:13:29 -0700 Subject: [PATCH 051/489] exosphere: add theoretical dev unit key support --- exosphere/src/masterkey.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/exosphere/src/masterkey.c b/exosphere/src/masterkey.c index c126a4af3..4b83da88a 100644 --- a/exosphere/src/masterkey.c +++ b/exosphere/src/masterkey.c @@ -3,6 +3,7 @@ #include <string.h> #include "utils.h" +#include "configitem.h" #include "masterkey.h" #include "se.h" @@ -12,9 +13,19 @@ static bool g_determined_mkey_revision = false; static uint8_t g_old_masterkeys[MASTERKEY_REVISION_MAX][0x10]; static uint8_t g_old_devicekeys[MASTERKEY_NUM_NEW_DEVICE_KEYS - 1][0x10]; -/* TODO: Dev keys. */ /* TODO: Extend with new vectors, as needed. */ +/* Dev unit keys. */ +static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = +{ + {0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE}, /* Zeroes encrypted with Master Key 00. */ + {0x39, 0x33, 0xF9, 0x31, 0xBA, 0xE4, 0xA7, 0x21, 0x2C, 0xDD, 0xB7, 0xD8, 0xB4, 0x4E, 0x37, 0x23}, /* Master key 00 encrypted with Master key 01. */ + {0x97, 0x29, 0xB0, 0x32, 0x43, 0x14, 0x8C, 0xA6, 0x85, 0xE9, 0x5A, 0x94, 0x99, 0x39, 0xAC, 0x5D}, /* Master key 01 encrypted with Master key 02. */ + {0x2C, 0xCA, 0x9C, 0x31, 0x1E, 0x07, 0xB0, 0x02, 0x97, 0x0A, 0xD8, 0x03, 0xA2, 0x76, 0x3F, 0xA3}, /* Master key 02 encrypted with Master key 03. */ + {0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ +}; + +/* Retail unit keys. */ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = { {0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D}, /* Zeroes encrypted with Master Key 00. */ @@ -24,14 +35,14 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = {0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ }; -bool check_mkey_revision(unsigned int revision) { +bool check_mkey_revision(unsigned int revision, bool is_retail) { uint8_t final_vector[0x10]; unsigned int check_keyslot = KEYSLOT_SWITCH_MASTERKEY; if (revision > 0) { /* Generate old master key array. */ for (unsigned int i = revision; i > 0; i--) { - se_aes_ecb_decrypt_block(check_keyslot, g_old_masterkeys[i-1], 0x10, mkey_vectors[i], 0x10); + se_aes_ecb_decrypt_block(check_keyslot, g_old_masterkeys[i-1], 0x10, is_retail ? mkey_vectors[i] : mkey_vectors_dev[i], 0x10); set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_masterkeys[i-1], 0x10); check_keyslot = KEYSLOT_SWITCH_TEMPKEY; } @@ -52,7 +63,7 @@ void mkey_detect_revision(void) { } for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) { - if (check_mkey_revision(rev)) { + if (check_mkey_revision(rev, configitem_is_retail())) { g_determined_mkey_revision = true; g_mkey_revision = rev; break; From 320ec38be1f276da985f1c398335cb7fc1b34bf2 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Sat, 18 Aug 2018 17:59:33 +0100 Subject: [PATCH 052/489] fusee: Complete re-write of the hardware initialization code: - Updated code to match hekate's; - Improved nxboot (now boots firmwares 2.x successfully); - Temporarily disabled built-in boot system module support; - Fixed multiple bugs. --- fusee/fusee-primary/Makefile | 2 +- fusee/fusee-primary/src/apb_misc.h | 13 +- fusee/fusee-primary/src/btn.c | 64 + fusee/fusee-primary/src/btn.h | 12 + fusee/fusee-primary/src/car.c | 114 ++ fusee/fusee-primary/src/car.h | 582 ++++++--- fusee/fusee-primary/src/di.c | 255 ++++ fusee/fusee-primary/src/di.h | 350 +++++ fusee/fusee-primary/src/di.inl | 546 ++++++++ fusee/fusee-primary/src/{hwinit => }/emc.h | 28 +- fusee/fusee-primary/src/flow.h | 15 + fusee/fusee-primary/src/fs_utils.c | 2 +- fusee/fusee-primary/src/fuse.c | 153 +-- fusee/fusee-primary/src/fuse.h | 19 +- fusee/fusee-primary/src/gpio.h | 14 +- fusee/fusee-primary/src/hwinit.c | 245 ++++ fusee/fusee-primary/src/hwinit.h | 40 +- fusee/fusee-primary/src/hwinit/btn.c | 25 - fusee/fusee-primary/src/hwinit/btn.h | 13 - fusee/fusee-primary/src/hwinit/clock.c | 145 --- fusee/fusee-primary/src/hwinit/clock.h | 51 - fusee/fusee-primary/src/hwinit/cluster.c | 114 -- fusee/fusee-primary/src/hwinit/cluster.h | 12 - fusee/fusee-primary/src/hwinit/di.c | 209 --- fusee/fusee-primary/src/hwinit/di.h | 60 - fusee/fusee-primary/src/hwinit/di.inl | 532 -------- fusee/fusee-primary/src/hwinit/fuse.h | 28 - fusee/fusee-primary/src/hwinit/hwinit.c | 280 ---- fusee/fusee-primary/src/hwinit/hwinit.h | 9 - fusee/fusee-primary/src/hwinit/hwinit_fuse.c | 12 - fusee/fusee-primary/src/hwinit/i2c.c | 116 -- fusee/fusee-primary/src/hwinit/i2c.h | 19 - fusee/fusee-primary/src/hwinit/max77620.h | 324 ----- fusee/fusee-primary/src/hwinit/max7762x.c | 136 -- fusee/fusee-primary/src/hwinit/pinmux.c | 16 - fusee/fusee-primary/src/hwinit/pinmux.h | 23 - fusee/fusee-primary/src/hwinit/pmc.h | 26 - fusee/fusee-primary/src/hwinit/sdram.c | 488 ------- fusee/fusee-primary/src/hwinit/sdram.h | 6 - fusee/fusee-primary/src/hwinit/sdram.inl | 812 ------------ fusee/fusee-primary/src/hwinit/t210.h | 71 -- fusee/fusee-primary/src/hwinit/tsec.c | 113 -- fusee/fusee-primary/src/hwinit/tsec.h | 8 - fusee/fusee-primary/src/hwinit/types.h | 11 - fusee/fusee-primary/src/hwinit/uart.c | 62 - fusee/fusee-primary/src/hwinit/uart.h | 43 - fusee/fusee-primary/src/hwinit/util.c | 16 - fusee/fusee-primary/src/hwinit/util.h | 17 - fusee/fusee-primary/src/i2c.c | 205 +++ fusee/fusee-primary/src/i2c.h | 71 ++ fusee/fusee-primary/src/lib/lz.c | 179 +++ fusee/fusee-primary/src/lib/lz.h | 52 + fusee/fusee-primary/src/main.c | 28 +- fusee/fusee-primary/src/max77620.h | 326 +++++ fusee/fusee-primary/src/max7762x.c | 161 +++ .../fusee-primary/src/{hwinit => }/max7762x.h | 37 +- fusee/fusee-primary/src/mc.c | 146 +++ fusee/fusee-primary/src/{hwinit => }/mc.h | 30 +- fusee/fusee-primary/src/panic.c | 2 +- fusee/fusee-primary/src/pinmux.h | 5 +- fusee/fusee-primary/src/pmc.h | 374 +++++- fusee/fusee-primary/src/sdmmc/sdmmc_core.c | 10 +- fusee/fusee-primary/src/sdram.c | 561 ++++++++ fusee/fusee-primary/src/sdram.h | 8 + fusee/fusee-primary/src/sdram.inl | 1136 +++++++++++++++++ fusee/fusee-primary/src/sdram_lp0.c | 1109 ++++++++++++++++ fusee/fusee-primary/src/sdram_lz.inl | 108 ++ fusee/fusee-primary/src/sdram_param_t210.h | 933 ++++++++++++++ .../fusee-primary/src/sdram_param_t210_lp0.h | 964 ++++++++++++++ fusee/fusee-primary/src/se.c | 215 ++-- fusee/fusee-primary/src/se.h | 22 +- fusee/fusee-primary/src/sysctr0.h | 11 + fusee/fusee-primary/src/sysreg.h | 32 + fusee/fusee-primary/src/timers.h | 1 + fusee/fusee-primary/src/uart.c | 55 + fusee/fusee-primary/src/uart.h | 153 +++ fusee/fusee-primary/src/utils.c | 2 +- fusee/fusee-secondary/Makefile | 2 +- fusee/fusee-secondary/src/apb_misc.h | 13 +- fusee/fusee-secondary/src/btn.c | 64 + fusee/fusee-secondary/src/btn.h | 12 + fusee/fusee-secondary/src/car.c | 114 ++ fusee/fusee-secondary/src/car.h | 582 ++++++--- fusee/fusee-secondary/src/cluster.c | 135 ++ fusee/fusee-secondary/src/cluster.h | 6 + fusee/fusee-secondary/src/console.c | 7 +- fusee/fusee-secondary/src/di.c | 255 ++++ fusee/fusee-secondary/src/di.h | 350 +++++ fusee/fusee-secondary/src/di.inl | 546 ++++++++ fusee/fusee-secondary/src/flow.h | 37 +- fusee/fusee-secondary/src/fuse.c | 153 +-- fusee/fusee-secondary/src/fuse.h | 19 +- fusee/fusee-secondary/src/gpio.h | 14 +- fusee/fusee-secondary/src/hwinit.h | 42 - fusee/fusee-secondary/src/hwinit/btn.c | 25 - fusee/fusee-secondary/src/hwinit/btn.h | 13 - fusee/fusee-secondary/src/hwinit/clock.c | 145 --- fusee/fusee-secondary/src/hwinit/clock.h | 51 - fusee/fusee-secondary/src/hwinit/cluster.c | 117 -- fusee/fusee-secondary/src/hwinit/cluster.h | 12 - fusee/fusee-secondary/src/hwinit/di.c | 209 --- fusee/fusee-secondary/src/hwinit/di.h | 60 - fusee/fusee-secondary/src/hwinit/di.inl | 532 -------- fusee/fusee-secondary/src/hwinit/emc.h | 665 ---------- fusee/fusee-secondary/src/hwinit/fuse.h | 28 - fusee/fusee-secondary/src/hwinit/hwinit.c | 280 ---- fusee/fusee-secondary/src/hwinit/hwinit.h | 9 - .../fusee-secondary/src/hwinit/hwinit_fuse.c | 12 - fusee/fusee-secondary/src/hwinit/i2c.c | 116 -- fusee/fusee-secondary/src/hwinit/i2c.h | 19 - fusee/fusee-secondary/src/hwinit/max77620.h | 324 ----- fusee/fusee-secondary/src/hwinit/max7762x.c | 136 -- fusee/fusee-secondary/src/hwinit/pinmux.c | 16 - fusee/fusee-secondary/src/hwinit/pinmux.h | 23 - fusee/fusee-secondary/src/hwinit/pmc.h | 26 - fusee/fusee-secondary/src/hwinit/sdram.c | 488 ------- fusee/fusee-secondary/src/hwinit/sdram.h | 6 - fusee/fusee-secondary/src/hwinit/sdram.inl | 812 ------------ fusee/fusee-secondary/src/hwinit/t210.h | 71 -- fusee/fusee-secondary/src/hwinit/tsec.c | 113 -- fusee/fusee-secondary/src/hwinit/tsec.h | 8 - fusee/fusee-secondary/src/hwinit/types.h | 11 - fusee/fusee-secondary/src/hwinit/uart.c | 62 - fusee/fusee-secondary/src/hwinit/uart.h | 43 - fusee/fusee-secondary/src/hwinit/util.c | 16 - fusee/fusee-secondary/src/hwinit/util.h | 17 - fusee/fusee-secondary/src/i2c.c | 205 +++ fusee/fusee-secondary/src/i2c.h | 71 ++ fusee/fusee-secondary/src/key_derivation.c | 4 +- fusee/fusee-secondary/src/lib/driver_utils.h | 2 +- fusee/fusee-secondary/src/max77620.h | 326 +++++ fusee/fusee-secondary/src/max7762x.c | 161 +++ .../src/{hwinit => }/max7762x.h | 37 +- fusee/fusee-secondary/src/mc.c | 146 +++ fusee/fusee-secondary/src/{hwinit => }/mc.h | 30 +- fusee/fusee-secondary/src/nxboot.c | 106 +- fusee/fusee-secondary/src/nxfs.c | 2 +- fusee/fusee-secondary/src/package2.c | 4 - fusee/fusee-secondary/src/panic.c | 2 +- fusee/fusee-secondary/src/pinmux.h | 5 +- fusee/fusee-secondary/src/pmc.h | 374 +++++- fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 10 +- fusee/fusee-secondary/src/se.c | 215 ++-- fusee/fusee-secondary/src/se.h | 22 +- fusee/fusee-secondary/src/stratosphere.c | 13 +- fusee/fusee-secondary/src/sysreg.h | 32 + fusee/fusee-secondary/src/timers.h | 1 + fusee/fusee-secondary/src/tsec.c | 156 +++ fusee/fusee-secondary/src/tsec.h | 97 ++ fusee/fusee-secondary/src/utils.c | 2 +- 150 files changed, 12667 insertions(+), 9359 deletions(-) create mode 100644 fusee/fusee-primary/src/btn.c create mode 100644 fusee/fusee-primary/src/btn.h create mode 100644 fusee/fusee-primary/src/car.c create mode 100644 fusee/fusee-primary/src/di.c create mode 100644 fusee/fusee-primary/src/di.h create mode 100644 fusee/fusee-primary/src/di.inl rename fusee/fusee-primary/src/{hwinit => }/emc.h (98%) create mode 100644 fusee/fusee-primary/src/flow.h create mode 100644 fusee/fusee-primary/src/hwinit.c delete mode 100644 fusee/fusee-primary/src/hwinit/btn.c delete mode 100644 fusee/fusee-primary/src/hwinit/btn.h delete mode 100644 fusee/fusee-primary/src/hwinit/clock.c delete mode 100644 fusee/fusee-primary/src/hwinit/clock.h delete mode 100644 fusee/fusee-primary/src/hwinit/cluster.c delete mode 100644 fusee/fusee-primary/src/hwinit/cluster.h delete mode 100644 fusee/fusee-primary/src/hwinit/di.c delete mode 100644 fusee/fusee-primary/src/hwinit/di.h delete mode 100644 fusee/fusee-primary/src/hwinit/di.inl delete mode 100644 fusee/fusee-primary/src/hwinit/fuse.h delete mode 100644 fusee/fusee-primary/src/hwinit/hwinit.c delete mode 100644 fusee/fusee-primary/src/hwinit/hwinit.h delete mode 100644 fusee/fusee-primary/src/hwinit/hwinit_fuse.c delete mode 100644 fusee/fusee-primary/src/hwinit/i2c.c delete mode 100644 fusee/fusee-primary/src/hwinit/i2c.h delete mode 100644 fusee/fusee-primary/src/hwinit/max77620.h delete mode 100755 fusee/fusee-primary/src/hwinit/max7762x.c delete mode 100644 fusee/fusee-primary/src/hwinit/pinmux.c delete mode 100644 fusee/fusee-primary/src/hwinit/pinmux.h delete mode 100644 fusee/fusee-primary/src/hwinit/pmc.h delete mode 100644 fusee/fusee-primary/src/hwinit/sdram.c delete mode 100644 fusee/fusee-primary/src/hwinit/sdram.h delete mode 100644 fusee/fusee-primary/src/hwinit/sdram.inl delete mode 100644 fusee/fusee-primary/src/hwinit/t210.h delete mode 100644 fusee/fusee-primary/src/hwinit/tsec.c delete mode 100644 fusee/fusee-primary/src/hwinit/tsec.h delete mode 100644 fusee/fusee-primary/src/hwinit/types.h delete mode 100644 fusee/fusee-primary/src/hwinit/uart.c delete mode 100644 fusee/fusee-primary/src/hwinit/uart.h delete mode 100644 fusee/fusee-primary/src/hwinit/util.c delete mode 100644 fusee/fusee-primary/src/hwinit/util.h create mode 100644 fusee/fusee-primary/src/i2c.c create mode 100644 fusee/fusee-primary/src/i2c.h create mode 100644 fusee/fusee-primary/src/lib/lz.c create mode 100644 fusee/fusee-primary/src/lib/lz.h create mode 100644 fusee/fusee-primary/src/max77620.h create mode 100644 fusee/fusee-primary/src/max7762x.c rename fusee/fusee-primary/src/{hwinit => }/max7762x.h (62%) mode change 100755 => 100644 create mode 100644 fusee/fusee-primary/src/mc.c rename fusee/fusee-primary/src/{hwinit => }/mc.h (98%) create mode 100644 fusee/fusee-primary/src/sdram.c create mode 100644 fusee/fusee-primary/src/sdram.h create mode 100644 fusee/fusee-primary/src/sdram.inl create mode 100644 fusee/fusee-primary/src/sdram_lp0.c create mode 100644 fusee/fusee-primary/src/sdram_lz.inl create mode 100644 fusee/fusee-primary/src/sdram_param_t210.h create mode 100644 fusee/fusee-primary/src/sdram_param_t210_lp0.h create mode 100644 fusee/fusee-primary/src/sysctr0.h create mode 100644 fusee/fusee-primary/src/sysreg.h create mode 100644 fusee/fusee-primary/src/uart.c create mode 100644 fusee/fusee-primary/src/uart.h create mode 100644 fusee/fusee-secondary/src/btn.c create mode 100644 fusee/fusee-secondary/src/btn.h create mode 100644 fusee/fusee-secondary/src/car.c create mode 100644 fusee/fusee-secondary/src/cluster.c create mode 100644 fusee/fusee-secondary/src/cluster.h create mode 100644 fusee/fusee-secondary/src/di.c create mode 100644 fusee/fusee-secondary/src/di.h create mode 100644 fusee/fusee-secondary/src/di.inl delete mode 100644 fusee/fusee-secondary/src/hwinit.h delete mode 100644 fusee/fusee-secondary/src/hwinit/btn.c delete mode 100644 fusee/fusee-secondary/src/hwinit/btn.h delete mode 100644 fusee/fusee-secondary/src/hwinit/clock.c delete mode 100644 fusee/fusee-secondary/src/hwinit/clock.h delete mode 100644 fusee/fusee-secondary/src/hwinit/cluster.c delete mode 100644 fusee/fusee-secondary/src/hwinit/cluster.h delete mode 100644 fusee/fusee-secondary/src/hwinit/di.c delete mode 100644 fusee/fusee-secondary/src/hwinit/di.h delete mode 100644 fusee/fusee-secondary/src/hwinit/di.inl delete mode 100644 fusee/fusee-secondary/src/hwinit/emc.h delete mode 100644 fusee/fusee-secondary/src/hwinit/fuse.h delete mode 100644 fusee/fusee-secondary/src/hwinit/hwinit.c delete mode 100644 fusee/fusee-secondary/src/hwinit/hwinit.h delete mode 100644 fusee/fusee-secondary/src/hwinit/hwinit_fuse.c delete mode 100644 fusee/fusee-secondary/src/hwinit/i2c.c delete mode 100644 fusee/fusee-secondary/src/hwinit/i2c.h delete mode 100644 fusee/fusee-secondary/src/hwinit/max77620.h delete mode 100644 fusee/fusee-secondary/src/hwinit/max7762x.c delete mode 100644 fusee/fusee-secondary/src/hwinit/pinmux.c delete mode 100644 fusee/fusee-secondary/src/hwinit/pinmux.h delete mode 100644 fusee/fusee-secondary/src/hwinit/pmc.h delete mode 100644 fusee/fusee-secondary/src/hwinit/sdram.c delete mode 100644 fusee/fusee-secondary/src/hwinit/sdram.h delete mode 100644 fusee/fusee-secondary/src/hwinit/sdram.inl delete mode 100644 fusee/fusee-secondary/src/hwinit/t210.h delete mode 100644 fusee/fusee-secondary/src/hwinit/tsec.c delete mode 100644 fusee/fusee-secondary/src/hwinit/tsec.h delete mode 100644 fusee/fusee-secondary/src/hwinit/types.h delete mode 100644 fusee/fusee-secondary/src/hwinit/uart.c delete mode 100644 fusee/fusee-secondary/src/hwinit/uart.h delete mode 100644 fusee/fusee-secondary/src/hwinit/util.c delete mode 100644 fusee/fusee-secondary/src/hwinit/util.h create mode 100644 fusee/fusee-secondary/src/i2c.c create mode 100644 fusee/fusee-secondary/src/i2c.h create mode 100644 fusee/fusee-secondary/src/max77620.h create mode 100644 fusee/fusee-secondary/src/max7762x.c rename fusee/fusee-secondary/src/{hwinit => }/max7762x.h (62%) create mode 100644 fusee/fusee-secondary/src/mc.c rename fusee/fusee-secondary/src/{hwinit => }/mc.h (98%) create mode 100644 fusee/fusee-secondary/src/sysreg.h create mode 100644 fusee/fusee-secondary/src/tsec.c create mode 100644 fusee/fusee-secondary/src/tsec.h diff --git a/fusee/fusee-primary/Makefile b/fusee/fusee-primary/Makefile index 975160cb0..34307fcbe 100644 --- a/fusee/fusee-primary/Makefile +++ b/fusee/fusee-primary/Makefile @@ -18,7 +18,7 @@ include $(DEVKITARM)/base_rules #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := src src/sdmmc src/hwinit src/lib src/lib/fatfs src/display +SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display DATA := data INCLUDES := include diff --git a/fusee/fusee-primary/src/apb_misc.h b/fusee/fusee-primary/src/apb_misc.h index 114b7496a..4552a61b5 100644 --- a/fusee/fusee-primary/src/apb_misc.h +++ b/fusee/fusee-primary/src/apb_misc.h @@ -1,6 +1,17 @@ #ifndef FUSEE_APB_MISC_H #define FUSEE_APB_MISC_H +#include <stdint.h> + +#define APB_MISC_BASE 0x70000000 +#define APB_PADCTL_BASE 0x70000810 +#define MAKE_APB_MISC_REG(n) MAKE_REG32(APB_MISC_BASE + n) +#define MAKE_APB_PADCTL_REG(n) MAKE_REG32(APB_PADCTL_BASE + n) + +#define APB_MISC_PP_PINMUX_GLOBAL_0 MAKE_APB_MISC_REG(0x40) +#define APB_MISC_GP_WIFI_EN_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB64) +#define APB_MISC_GP_WIFI_RST_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB68) + #define SDMMC1_PAD_CAL_DRVUP_SHIFT (20) #define SDMMC1_PAD_CAL_DRVDN_SHIFT (12) #define SDMMC1_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVUP_SHIFT) @@ -48,7 +59,7 @@ typedef struct { static inline volatile tegra_padctl_t *padctl_get_regs(void) { - return (volatile tegra_padctl_t *)0x70000810; + return (volatile tegra_padctl_t *)APB_PADCTL_BASE; } #endif diff --git a/fusee/fusee-primary/src/btn.c b/fusee/fusee-primary/src/btn.c new file mode 100644 index 000000000..bffc8e79d --- /dev/null +++ b/fusee/fusee-primary/src/btn.c @@ -0,0 +1,64 @@ +#include <stdint.h> + +#include "btn.h" +#include "i2c.h" +#include "gpio.h" +#include "timers.h" + +uint32_t btn_read() +{ + uint32_t res = 0; + + if (!gpio_read(GPIO_BUTTON_VOL_DOWN)) + res |= BTN_VOL_DOWN; + + if (!gpio_read(GPIO_BUTTON_VOL_UP)) + res |= BTN_VOL_UP; + + uint32_t val = 0; + if (i2c_query(4, 0x3C, 0x15, &val, 1)) + { + if (val & 0x4) + res |= BTN_POWER; + } + + return res; +} + +uint32_t btn_wait() +{ + uint32_t res = 0, btn = btn_read(); + int pwr = 0; + + if (btn & BTN_POWER) + { + pwr = 1; + btn &= ~BTN_POWER; + } + + do + { + res = btn_read(); + + if (!(res & BTN_POWER) && pwr) + pwr = 0; + else if (pwr) + res &= ~BTN_POWER; + } while (btn == res); + + return res; +} + +uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask) +{ + uint32_t timeout = get_time_ms() + time_ms; + uint32_t res = btn_read() & mask; + + do + { + if (!(res & mask)) + res = btn_read() & mask; + } while (get_time_ms() < timeout); + + return res; +} \ No newline at end of file diff --git a/fusee/fusee-primary/src/btn.h b/fusee/fusee-primary/src/btn.h new file mode 100644 index 000000000..08f6f6921 --- /dev/null +++ b/fusee/fusee-primary/src/btn.h @@ -0,0 +1,12 @@ +#ifndef FUSEE_BTN_H_ +#define FUSEE_BTN_H_ + +#define BTN_POWER 0x1 +#define BTN_VOL_DOWN 0x2 +#define BTN_VOL_UP 0x4 + +uint32_t btn_read(); +uint32_t btn_wait(); +uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask); + +#endif \ No newline at end of file diff --git a/fusee/fusee-primary/src/car.c b/fusee/fusee-primary/src/car.c new file mode 100644 index 000000000..bc79be9a6 --- /dev/null +++ b/fusee/fusee-primary/src/car.c @@ -0,0 +1,114 @@ +#include "car.h" +#include "utils.h" + +static inline uint32_t get_clk_source_reg(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0x178; + case CARDEVICE_UARTB: return 0x17C; + case CARDEVICE_UARTC: return 0x1A0; + case CARDEVICE_I2C1: return 0x124; + case CARDEVICE_I2C5: return 0x128; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0x42C; + case CARDEVICE_HOST1X: return 0x180; + case CARDEVICE_TSEC: return 0x1F4; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 0x410; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_ACTMON: return 0x3E8; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static inline uint32_t get_clk_source_val(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_UARTC: return 0; + case CARDEVICE_I2C1: return 6; + case CARDEVICE_I2C5: return 6; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0; + case CARDEVICE_HOST1X: return 4; + case CARDEVICE_TSEC: return 0; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 0; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_ACTMON: return 6; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static inline uint32_t get_clk_source_div(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_UARTC: return 0; + case CARDEVICE_I2C1: return 0; + case CARDEVICE_I2C5: return 0; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0; + case CARDEVICE_HOST1X: return 3; + case CARDEVICE_TSEC: return 2; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 2; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_ACTMON: return 0; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; +static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; + +void clk_enable(CarDevice dev) { + uint32_t clk_source_reg; + if ((clk_source_reg = get_clk_source_reg(dev))) { + MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev); + } + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void clk_disable(CarDevice dev) { + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void rst_enable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void rst_disable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void clkrst_enable(CarDevice dev) { + clk_enable(dev); + rst_disable(dev); +} + +void clkrst_disable(CarDevice dev) { + rst_enable(dev); + clk_disable(dev); +} + +void clkrst_reboot(CarDevice dev) { + clkrst_disable(dev); + clkrst_enable(dev); +} + +void clkrst_enable_fuse_regs(bool enable) { + volatile tegra_car_t *car = car_get_regs(); + car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28)); +} diff --git a/fusee/fusee-primary/src/car.h b/fusee/fusee-primary/src/car.h index 8cc0fb139..6ec42e744 100644 --- a/fusee/fusee-primary/src/car.h +++ b/fusee/fusee-primary/src/car.h @@ -1,121 +1,202 @@ #ifndef FUSEE_CAR_H #define FUSEE_CAR_H -#define CLK_SOURCE_SDMMC1 20 -#define CLK_SOURCE_SDMMC2 21 -#define CLK_SOURCE_SDMMC3 47 -#define CLK_SOURCE_SDMMC4 25 -#define CLK_SOURCE_SDMMC_LEGACY 0 +#include <stdint.h> +#include <stdbool.h> + +#define CAR_BASE 0x60006000 +#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) #define CLK_L_SDMMC1 (1 << 14) #define CLK_L_SDMMC2 (1 << 9) #define CLK_U_SDMMC3 (1 << 5) #define CLK_L_SDMMC4 (1 << 15) -#define TEGRA_CLK_PLLS 6 /* Number of normal PLLs */ -#define TEGRA_CLK_SIMPLE_PLLS 3 /* Number of simple PLLs */ -#define TEGRA_CLK_SOURCES 64 /* Number of ppl clock sources L/H/U */ -#define TEGRA_CLK_SOURCES_VW 32 /* Number of ppl clock sources V/W */ -#define TEGRA_CLK_SOURCES_X 32 /* Number of ppl clock sources X */ -#define TEGRA_CLK_SOURCES_Y 18 /* Number of ppl clock sources Y */ - #define CLK_SOURCE_MASK (0b111 << 29) #define CLK_SOURCE_FIRST (0b000 << 29) #define CLK_DIVIDER_MASK (0xff << 0) #define CLK_DIVIDER_UNITY (0x00 << 0) -#define CAR_CONTROL_SDMMC1 (1 << 14) -#define CAR_CONTROL_SDMMC4 (1 << 15) -#define CAR_CONTROL_SDMMC_LEGACY (1 << 1) +#define NUM_CAR_BANKS 7 -/* PLL registers - there are several PLLs in the clock controller */ -typedef struct { - uint32_t pll_base; /* the control register */ - - /* pll_out[0] is output A control, pll_out[1] is output B control */ - uint32_t pll_out[2]; - uint32_t pll_misc; /* other misc things */ -} clk_pll_t; - -/* PLL registers - there are several PLLs in the clock controller */ -typedef struct { - uint32_t pll_base; /* the control register */ - uint32_t pll_misc; /* other misc things */ -} clk_pll_simple_t; - -typedef struct { - uint32_t pllm_base; /* the control register */ - uint32_t pllm_out; /* output control */ - uint32_t pllm_misc1; /* misc1 */ - uint32_t pllm_misc2; /* misc2 */ -} clk_pllm_t; +/* Clock and reset devices. */ +typedef enum { + CARDEVICE_UARTA = ((0 << 5) | 0x6), + CARDEVICE_UARTB = ((0 << 5) | 0x7), + CARDEVICE_UARTC = ((1 << 5) | 0x17), + CARDEVICE_I2C1 = ((0 << 5) | 0xC), + CARDEVICE_I2C5 = ((1 << 5) | 0xF), + CARDEVICE_UNK = ((3 << 5) | 0x1E), + CARDEVICE_SE = ((3 << 5) | 0x1F), + CARDEVICE_HOST1X = ((0 << 5) | 0x1C), + CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E), + CARDEVICE_SOR0 = ((5 << 5) | 0x16), + CARDEVICE_SOR1 = ((5 << 5) | 0x17), + CARDEVICE_KFUSE = ((1 << 5) | 0x8), + CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B), + CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), + CARDEVICE_ACTMON = ((3 << 5) | 0x17), + CARDEVICE_BPMP = ((0 << 5) | 0x1) +} CarDevice; /* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */ typedef struct { - uint32_t rst_src; /* _RST_SOURCE_0,0x00 */ + uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */ + /* _RST_DEVICES_L/H/U_0 0x4-0xc */ uint32_t rst_dev_l; uint32_t rst_dev_h; uint32_t rst_dev_u; + /* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */ uint32_t clk_out_enb_l; uint32_t clk_out_enb_h; uint32_t clk_out_enb_u; - uint32_t reserved0; /* reserved_0, 0x1C */ - uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */ - uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0,0x24 */ - uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */ - uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0,0x2C */ - uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */ - uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */ - uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0,0x38 */ - uint32_t reserved1; /* reserved_1, 0x3C */ - uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0,0x40 */ - uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */ - uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */ - uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4C */ - uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */ - uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */ - uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */ - uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0,0x5C */ - uint32_t reserved2[8]; /* reserved_2[8], 0x60-7C */ + uint32_t _0x1C; + uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */ + uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */ + uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */ + uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */ + uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */ + uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */ + uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */ + uint32_t _0x3C; + uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */ + uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */ + uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */ + uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */ + uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */ + uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */ + uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */ + uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */ + uint32_t _0x60[2]; + uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */ + uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */ + uint32_t _0x70[4]; - clk_pll_t pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */ + /* PLLC 0x80-0x8c */ + uint32_t pllc_base; + uint32_t pllc_out; + uint32_t pllc_misc0; + uint32_t pllc_misc1; + + /* PLLM 0x90-0x9c */ + uint32_t pllm_base; + uint32_t pllm_out; + uint32_t pllm_misc1; + uint32_t pllm_misc2; + + /* PLLP 0xa0-0xac */ + uint32_t pllp_base; + uint32_t pllp_outa; + uint32_t pllp_outb; + uint32_t pllp_misc; + + /* PLLA 0xb0-0xbc */ + uint32_t plla_base; + uint32_t plla_out; + uint32_t plla_misc0; + uint32_t plla_misc1; + + /* PLLU 0xc0-0xcc */ + uint32_t pllu_base; + uint32_t pllu_out; + uint32_t pllu_misc1; + uint32_t pllu_misc2; + + /* PLLD 0xd0-0xdc */ + uint32_t plld_base; + uint32_t plld_out; + uint32_t plld_misc1; + uint32_t plld_misc2; - /* PLLs from 0xe0 to 0xf4 */ - clk_pll_simple_t pll_simple[TEGRA_CLK_SIMPLE_PLLS]; + /* PLLX 0xe0-0xe4 */ + uint32_t pllx_base; + uint32_t pllx_misc; + + /* PLLE 0xe8-0xf4 */ + uint32_t plle_base; + uint32_t plle_misc; + uint32_t plle_ss_cntl1; + uint32_t plle_ss_cntl2; + + uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */ + uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */ - uint32_t reserved10; /* _reserved_10, 0xF8 */ - uint32_t reserved11; /* _reserved_11, 0xFC */ + uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */ + uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */ + uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */ + uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */ + uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */ + uint32_t _0x114; + uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */ + uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */ + uint32_t _0x120; + uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */ + uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */ + uint32_t _0x12c[2]; + uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */ + uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */ + uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */ + uint32_t _0x140; + uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */ + uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */ + uint32_t _0x14c; + uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */ + uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */ + uint32_t _0x158[3]; + uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */ + uint32_t _0x168[4]; + uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */ + uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */ + uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */ + uint32_t _0x184[5]; + uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */ + uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */ + uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */ + uint32_t _0x1a4; + uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */ + uint32_t _0x1ac[2]; + uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */ + uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */ + uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */ + uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */ + uint32_t _0x1c4[2]; + uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */ + uint32_t _0x1d0; + uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */ + uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */ + uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */ + uint32_t _0x1e0[5]; + uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */ + uint32_t _0x1f8; + + uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */ + uint32_t _0x200[32]; - uint32_t clk_src[TEGRA_CLK_SOURCES]; /*_I2S1_0... 0x100-1fc */ + uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ + uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ + uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ - uint32_t reserved20[32]; /* _reserved_20, 0x200-27c */ + uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */ + uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ + uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ - uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ - uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ - uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ + uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */ + uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */ + uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */ - uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */ - uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ - uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ + uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */ + uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */ + uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */ - uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */ - uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */ - uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */ + uint32_t _0x2b0[17]; + uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */ + uint32_t _0x2f8[2]; - uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */ - uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */ - uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */ - - uint32_t reserved21[17]; /* _reserved_21, 0x2b0-2f0 */ - - uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */ - - uint32_t reserved22[2]; /* _reserved_22, 0x2f8-2fc */ - - /* _RST_DEV_L/H/U_SET_0 0x300 ~ 0x314 */ + /* _RST_DEV_L/H/U_SET_0 0x300-0x314 */ uint32_t rst_dev_l_set; uint32_t rst_dev_l_clr; uint32_t rst_dev_h_set; @@ -123,9 +204,9 @@ typedef struct { uint32_t rst_dev_u_set; uint32_t rst_dev_u_clr; - uint32_t reserved30[2]; /* _reserved_30, 0x318, 0x31c */ + uint32_t _0x318[2]; - /* _CLK_ENB_L/H/U_CLR_0 0x320 ~ 0x334 */ + /* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */ uint32_t clk_enb_l_set; uint32_t clk_enb_l_clr; uint32_t clk_enb_h_set; @@ -133,136 +214,275 @@ typedef struct { uint32_t clk_enb_u_set; uint32_t clk_enb_u_clr; - uint32_t reserved31[2]; /* _reserved_31, 0x338, 0x33c */ - - uint32_t cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */ - uint32_t cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */ + uint32_t _0x338; + uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */ + uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */ + uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */ /* Additional (T30) registers */ - uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */ - uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ + uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */ + uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ - uint32_t reserved32[2]; /* _reserved_32, 0x350,0x354 */ + uint32_t _0x350[2]; + uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ + uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ + uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ + uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ + uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ + uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ + uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ + uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ + uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ + uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ + uint32_t _0x38c[5]; + uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */ + uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */ + uint32_t _0x3a8[2]; + + uint32_t _0x3b0; + uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */ + uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */ + uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */ + uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */ + uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */ + uint32_t _0x3c8[2]; + uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */ + uint32_t _0x3d4[4]; + uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */ + uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */ + uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */ + uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */ + uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */ + uint32_t _0x3f8; + uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */ + uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */ + uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */ + uint32_t _0x408[2]; + uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */ + uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */ + uint32_t _0x418[2]; + uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */ + uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */ + uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */ + uint32_t _0x42c; - uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ - uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ - - uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ - uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ - uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ - uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ - uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ - uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ - uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ - uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ - uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ - uint32_t reserved33[9]; /* _reserved_33, 0x38c-3ac */ - uint32_t clk_src_v; /* 0x3B0-0x42C */ - uint32_t clk_src_w; /* 0x3B0-0x42C */ - - /* _RST_DEV_V/W_SET_0 0x430 ~ 0x43c */ + /* _RST_DEV_V/W_SET_0 0x430-0x43c */ uint32_t rst_dev_v_set; uint32_t rst_dev_v_clr; uint32_t rst_dev_w_set; uint32_t rst_dev_w_clr; - /* _CLK_ENB_V/W_CLR_0 0x440 ~ 0x44c */ - uint32_t rst_clk_v_set; - uint32_t rst_clk_v_clr; - uint32_t rst_clk_w_set; - uint32_t rst_clk_w_clr; + /* _CLK_ENB_V/W_CLR_0 0x440-0x44c */ + uint32_t clk_enb_v_set; + uint32_t clk_enb_v_clr; + uint32_t clk_enb_w_set; + uint32_t clk_enb_w_clr; /* Additional (T114+) registers */ - uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */ - uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */ - uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */ - uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45C */ - uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */ - uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */ - uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */ - uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46C */ - uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */ - uint32_t reserved40[1]; /* _reserved_40, 0x474 */ - uint32_t intstatus; /* __INTSTATUS_0, 0x478 */ - uint32_t intmask; /* __INTMASK_0, 0x47C */ - uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */ - uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */ - uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */ + uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */ + uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */ + uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */ + uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */ + uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */ + uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */ + uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */ + uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */ + uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */ + uint32_t _0x474; + uint32_t intstatus; /* _INTSTATUS_0, 0x478 */ + uint32_t intmask; /* _INTMASK_0, 0x47c */ + uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */ + uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */ + uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */ - uint32_t plle_aux; /* _PLLE_AUX_0, 0x48C */ - uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */ - uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */ - uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */ + uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */ + uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */ + uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */ + uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */ - uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49C */ - uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4A0 */ - uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4A4 */ - uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4A8 */ - uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4AC */ - uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4B0 */ - uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4B4 */ + uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */ + uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */ + uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */ + uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */ + uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */ + uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */ + uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */ - uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4B8 */ - uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4BC */ - uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4C0 */ - uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4C4 */ - uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4C8 */ - uint32_t crs_reserved_50[7]; /* _reserved_50, 0x4CC-0x4E4 */ - uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4E8 */ - uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4EC */ - uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4F0 */ - uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4F4 */ - uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4F8 */ - uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4FC */ + uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */ + uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */ + uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */ + uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */ + uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */ + uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */ + uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */ + uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */ + uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */ + uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */ + uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */ + uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */ + uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */ + uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */ + uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */ + uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */ + uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */ + uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */ uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */ uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */ uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */ - uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50C */ + uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */ uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */ uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */ uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */ - uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51C */ + uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */ uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */ uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */ uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */ - uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52C */ + uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */ uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */ uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */ - uint32_t reserved51[1]; /* _reserved_51, 0x538 */ - uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53C */ + uint32_t _0x538; + uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */ uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */ uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */ uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */ - uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54C */ + uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */ uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */ - uint32_t reserved52[1]; /* _reserved_52, 0x554 */ + uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */ uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */ - uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55C */ - uint32_t _rsv32[4]; /* 0x560-0x56c */ - uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */ - uint32_t _rsv32_1[7]; /* 0x574-58c */ - clk_pll_simple_t plldp; /* _PLLDP_BASE, 0x590 _PLLDP_MISC */ - uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ - - /* Tegra124+ - skip to 0x600 here for new CLK_SOURCE_ regs */ - uint32_t _rsrv32_2[25]; /* _0x59C - 0x5FC */ - uint32_t clk_src_x[TEGRA_CLK_SOURCES_X]; /* XUSB, etc, 0x600-0x67C */ - - /* Tegra210 - skip to 0x694 here for new CLK_SOURCE_ regs */ - uint32_t reserved61[5]; /* _reserved_61, 0x680 - 0x690 */ + uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */ + uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */ + uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */ - /* - * NOTE: PLLA1 regs are in the middle of this Y region. Break this in - * two later if PLLA1 is needed, but for now this is cleaner. - */ - uint32_t clk_src_y[TEGRA_CLK_SOURCES_Y]; /* SPARE1, etc, 0x694-0x6D8 */ + uint32_t _0x568[2]; + uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */ + uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */ + uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */ + uint32_t _0x57c[5]; + + uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/ + uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */ + uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ + uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */ + uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */ + uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */ + uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */ + uint32_t _0x5ac[6]; + uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */ + uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */ + uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */ + uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */ + uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */ + uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */ + uint32_t _0x5dc[2]; + uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */ + uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */ + uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */ + uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */ + uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */ + uint32_t _0x5f8[2]; + + uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */ + uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */ + uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */ + uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */ + uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */ + uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */ + uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */ + uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */ + uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */ + uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */ + uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */ + uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */ + uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */ + uint32_t _0x634[3]; + uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */ + uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */ + uint32_t _0x648; + uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */ + uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */ + uint32_t _0x654; + uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */ + uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */ + uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */ + uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */ + uint32_t _0x668; + uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */ + uint32_t _0x670[2]; + uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */ + + uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */ + uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */ + uint32_t _0x684[2]; + uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */ + uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */ + + uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */ + uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */ + uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */ + uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */ + + uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */ + uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */ + uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */ + uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */ + uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */ + uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */ + + uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */ + uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */ + uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */ + uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */ + uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */ + uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */ + uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */ + uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */ + + uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */ + uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */ + uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */ + + uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */ + uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */ + uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */ + uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */ + uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */ + uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */ + uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */ + uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */ + uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */ + uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ + + uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ + uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ + uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ + uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ + uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */ + uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */ + uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */ + uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */ + uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */ + uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */ + uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */ + uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */ + uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */ } tegra_car_t; -static inline volatile tegra_car_t *car_get_regs(void) -{ - return (volatile tegra_car_t *)0x60006000; +static inline volatile tegra_car_t *car_get_regs(void) { + return (volatile tegra_car_t *)CAR_BASE; } +void clk_enable(CarDevice dev); +void clk_disable(CarDevice dev); +void rst_enable(CarDevice dev); +void rst_disable(CarDevice dev); + +void clkrst_enable(CarDevice dev); +void clkrst_disable(CarDevice dev); +void clkrst_reboot(CarDevice dev); + +void clkrst_enable_fuse_regs(bool enable); + #endif diff --git a/fusee/fusee-primary/src/di.c b/fusee/fusee-primary/src/di.c new file mode 100644 index 000000000..e22257465 --- /dev/null +++ b/fusee/fusee-primary/src/di.c @@ -0,0 +1,255 @@ +#include <string.h> + +#include "di.h" +#include "timers.h" +#include "i2c.h" +#include "pmc.h" +#include "max77620.h" +#include "gpio.h" +#include "pinmux.h" +#include "car.h" + +#include "di.inl" + +static uint32_t _display_ver = 0; + +static void exec_cfg(uint32_t *base, const cfg_op_t *ops, uint32_t num_ops) +{ + for (uint32_t i = 0; i < num_ops; i++) + base[ops[i].off] = ops[i].val; +} + +static void _display_dsi_wait(uint32_t timeout, uint32_t off, uint32_t mask) +{ + uint32_t end = get_time_us() + timeout; + while ((get_time_us() < end) && (MAKE_DSI_REG(off) & mask)) { + /* Wait. */ + } + udelay(5); +} + +void display_init() +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + + /* Power on. */ + uint8_t val = 0xD0; + i2c_send(4, 0x3C, MAX77620_REG_LDO0_CFG, &val, 1); + val = 0x09; + i2c_send(4, 0x3C, MAX77620_REG_GPIO7, &val, 1); + + /* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */ + car->rst_dev_h_clr = 0x1010000; + car->clk_enb_h_set = 0x1010000; + car->rst_dev_l_clr = 0x18000000; + car->clk_enb_l_set = 0x18000000; + car->clk_enb_x_set = 0x20000; + car->clk_source_uart_fst_mipi_cal = 0xA; + car->clk_enb_w_set = 0x80000; + car->clk_source_dsia_lp = 0xA; + + /* DPD idle. */ + pmc->io_dpd_req = 0x40000000; + pmc->io_dpd2_req = 0x40000000; + + /* Configure pins. */ + pinmux->nfc_en &= ~PINMUX_TRISTATE; + pinmux->nfc_int &= ~PINMUX_TRISTATE; + pinmux->lcd_bl_pwm &= ~PINMUX_TRISTATE; + pinmux->lcd_bl_en &= ~PINMUX_TRISTATE; + pinmux->lcd_rst &= ~PINMUX_TRISTATE; + + /* Configure Backlight +-5V GPIOs. */ + gpio_configure_mode(GPIO_LCD_BL_P5V, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_N5V, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_LCD_BL_P5V, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_N5V, GPIO_DIRECTION_OUTPUT); + + /* Enable Backlight +5V. */ + gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_HIGH); + + udelay(10000u); + + /* Enable Backlight -5V. */ + gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_HIGH); + + udelay(10000); + + /* Configure Backlight PWM, EN and RST GPIOs. */ + gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_EN, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_RST, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_LCD_BL_PWM, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_EN, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_RST, GPIO_DIRECTION_OUTPUT); + + /* Enable Backlight EN. */ + gpio_write(GPIO_LCD_BL_EN, GPIO_LEVEL_HIGH); + + /* Configure display interface and display. */ + MAKE_MIPI_CAL_REG(0x60) = 0; + + exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4); + exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94); + exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 60); + + udelay(10000); + + /* Enable Backlight RST. */ + gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_HIGH); + + udelay(60000); + + MAKE_DSI_REG(DSI_BTA_TIMING) = 0x50204; + MAKE_DSI_REG(DSI_WR_DATA) = 0x337; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + _display_dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO)); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x406; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + _display_dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO)); + + MAKE_DSI_REG(DSI_HOST_CONTROL) = (DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC); + _display_dsi_wait(150000, DSI_HOST_CONTROL, DSI_HOST_CONTROL_IMM_BTA); + + udelay(5000); + + _display_ver = MAKE_DSI_REG(DSI_RD_DATA); + + if (_display_ver == 0x10) + exec_cfg((uint32_t *)DSI_BASE, _display_config_4, 43); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x1105; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + + udelay(180000); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x2905; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + + udelay(20000); + + exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21); + exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3); + + MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4; + exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10); + + udelay(10000); + + exec_cfg((uint32_t *)MIPI_CAL_BASE, _display_config_8, 6); + exec_cfg((uint32_t *)DSI_BASE, _display_config_9, 4); + exec_cfg((uint32_t *)MIPI_CAL_BASE, _display_config_10, 16); + + udelay(10000); + + exec_cfg((uint32_t *)DI_BASE, _display_config_11, 113); +} + +void display_backlight(bool enable) +{ + /* Enable Backlight PWM. */ + gpio_write(GPIO_LCD_BL_PWM, enable ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW); +} + +void display_end() +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + + /* Disable Backlight. */ + display_backlight(false); + + MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 1; + MAKE_DSI_REG(DSI_WR_DATA) = 0x2805; + + uint32_t host1x_delay = MAKE_HOST1X_REG(0x30A4) + 5; + while (MAKE_HOST1X_REG(0x30A4) < host1x_delay) { + /* Wait. */ + } + + MAKE_DI_REG(DC_CMD_STATE_ACCESS) = 5; + MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 0; + + exec_cfg((uint32_t *)DI_BASE, _display_config_12, 17); + exec_cfg((uint32_t *)DSI_BASE, _display_config_13, 16); + + udelay(10000); + + if (_display_ver == 0x10) + exec_cfg((uint32_t *)DSI_BASE, _display_config_14, 22); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x1005; + MAKE_DSI_REG(DSI_TRIGGER) = 2; + + udelay(50000); + + /* Disable Backlight RST. */ + gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable Backlight -5V. */ + gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable Backlight +5V. */ + gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable clocks. */ + car->rst_dev_h_set = 0x1010000; + car->clk_enb_h_clr = 0x1010000; + car->rst_dev_l_set = 0x18000000; + car->clk_enb_l_clr = 0x18000000; + + MAKE_DSI_REG(DSI_PAD_CONTROL_0) = 0x10F010F; + MAKE_DSI_REG(DSI_POWER_CONTROL) = 0; + + /* Backlight PWM. */ + gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_SFIO); + + pinmux->lcd_bl_pwm = ((pinmux->lcd_bl_pwm & ~PINMUX_TRISTATE) | PINMUX_TRISTATE); + pinmux->lcd_bl_pwm = (((pinmux->lcd_bl_pwm >> 2) << 2) | 1); +} + +void display_color_screen(uint32_t color) +{ + exec_cfg((uint32_t *)DI_BASE, cfg_display_one_color, 8); + + /* Configure display to show single color. */ + MAKE_DI_REG(DC_WIN_AD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_WIN_BD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_WIN_CD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_DISP_BLEND_BACKGROUND_COLOR) = color; + MAKE_DI_REG(DC_CMD_STATE_CONTROL) = ((MAKE_DI_REG(DC_CMD_STATE_CONTROL) & 0xFFFFFFFE) | GENERAL_ACT_REQ); + + udelay(35000); + + display_backlight(true); +} + +uint32_t *display_init_framebuffer(void *address) +{ + static cfg_op_t conf[sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t)] = {0}; + if(conf[0].val == 0) { + for (uint32_t i = 0; i < sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t); i++) { + conf[i] = cfg_display_framebuffer[i]; + } + } + + uint32_t *lfb_addr = (uint32_t *)address; + + conf[19].val = (uint32_t)address; + + //This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). + exec_cfg((uint32_t *)DI_BASE, conf, 32); + + udelay(35000); + + return lfb_addr; +} diff --git a/fusee/fusee-primary/src/di.h b/fusee/fusee-primary/src/di.h new file mode 100644 index 000000000..bca4b569a --- /dev/null +++ b/fusee/fusee-primary/src/di.h @@ -0,0 +1,350 @@ +#ifndef FUSEE_DI_H_ +#define FUSEE_DI_H_ + +#include <stdint.h> +#include <stdbool.h> + +#define HOST1X_BASE 0x50000000 +#define DI_BASE 0x54200000 +#define DSI_BASE 0x54300000 +#define VIC_BASE 0x54340000 +#define MIPI_CAL_BASE 0x700E3000 +#define MAKE_HOST1X_REG(n) MAKE_REG32(HOST1X_BASE + n) +#define MAKE_DI_REG(n) MAKE_REG32(DI_BASE + n * 4) +#define MAKE_DSI_REG(n) MAKE_REG32(DSI_BASE + n * 4) +#define MAKE_MIPI_CAL_REG(n) MAKE_REG32(MIPI_CAL_BASE + n) +#define MAKE_VIC_REG(n) MAKE_REG32(VIC_BASE + n) + +/* Display registers. */ +#define DC_CMD_GENERAL_INCR_SYNCPT 0x00 + +#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01 +#define SYNCPT_CNTRL_NO_STALL (1 << 8) +#define SYNCPT_CNTRL_SOFT_RESET (1 << 0) + +#define DC_CMD_CONT_SYNCPT_VSYNC 0x28 +#define SYNCPT_VSYNC_ENABLE (1 << 8) + +#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 + +#define DC_CMD_DISPLAY_COMMAND 0x32 +#define DISP_CTRL_MODE_STOP (0 << 5) +#define DISP_CTRL_MODE_C_DISPLAY (1 << 5) +#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5) +#define DISP_CTRL_MODE_MASK (3 << 5) + +#define DC_CMD_DISPLAY_POWER_CONTROL 0x36 +#define PW0_ENABLE (1 << 0) +#define PW1_ENABLE (1 << 2) +#define PW2_ENABLE (1 << 4) +#define PW3_ENABLE (1 << 6) +#define PW4_ENABLE (1 << 8) +#define PM0_ENABLE (1 << 16) +#define PM1_ENABLE (1 << 18) + +#define DC_CMD_INT_MASK 0x38 +#define DC_CMD_INT_ENABLE 0x39 + +#define DC_CMD_STATE_ACCESS 0x40 +#define READ_MUX (1 << 0) +#define WRITE_MUX (1 << 2) + +#define DC_CMD_STATE_CONTROL 0x41 +#define GENERAL_ACT_REQ (1 << 0) +#define WIN_A_ACT_REQ (1 << 1) +#define WIN_B_ACT_REQ (1 << 2) +#define WIN_C_ACT_REQ (1 << 3) +#define CURSOR_ACT_REQ (1 << 7) +#define GENERAL_UPDATE (1 << 8) +#define WIN_A_UPDATE (1 << 9) +#define WIN_B_UPDATE (1 << 10) +#define WIN_C_UPDATE (1 << 11) +#define CURSOR_UPDATE (1 << 15) +#define NC_HOST_TRIG (1 << 24) + +#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 +#define WINDOW_A_SELECT (1 << 4) +#define WINDOW_B_SELECT (1 << 5) +#define WINDOW_C_SELECT (1 << 6) + +#define DC_CMD_REG_ACT_CONTROL 0x043 + +#define DC_COM_CRC_CONTROL 0x300 +#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) +#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) + +#define DC_COM_DSC_TOP_CTL 0x33E + +#define DC_DISP_DISP_WIN_OPTIONS 0x402 +#define HDMI_ENABLE (1 << 30) +#define DSI_ENABLE (1 << 29) +#define SOR1_TIMING_CYA (1 << 27) +#define SOR1_ENABLE (1 << 26) +#define SOR_ENABLE (1 << 25) +#define CURSOR_ENABLE (1 << 16) + +#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 +#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404 +#define DC_DISP_DISP_TIMING_OPTIONS 0x405 +#define DC_DISP_REF_TO_SYNC 0x406 +#define DC_DISP_SYNC_WIDTH 0x407 +#define DC_DISP_BACK_PORCH 0x408 +#define DC_DISP_ACTIVE 0x409 +#define DC_DISP_FRONT_PORCH 0x40A + +#define DC_DISP_DISP_CLOCK_CONTROL 0x42E +#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8) +#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8) +#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8) +#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8) +#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8) +#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8) +#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8) +#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8) +#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8) +#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8) +#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8) +#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8) +#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8) +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) + +#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F +#define DISP_DATA_FORMAT_DF1P1C (0 << 0) +#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0) +#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0) +#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0) +#define DISP_DATA_FORMAT_DF2S (4 << 0) +#define DISP_DATA_FORMAT_DF3S (5 << 0) +#define DISP_DATA_FORMAT_DFSPI (6 << 0) +#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0) +#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0) +#define DISP_ALIGNMENT_MSB (0 << 8) +#define DISP_ALIGNMENT_LSB (1 << 8) +#define DISP_ORDER_RED_BLUE (0 << 9) +#define DISP_ORDER_BLUE_RED (1 << 9) + +#define DC_DISP_DISP_COLOR_CONTROL 0x430 +#define DITHER_CONTROL_MASK (3 << 8) +#define DITHER_CONTROL_DISABLE (0 << 8) +#define DITHER_CONTROL_ORDERED (2 << 8) +#define DITHER_CONTROL_ERRDIFF (3 << 8) +#define BASE_COLOR_SIZE_MASK (0xf << 0) +#define BASE_COLOR_SIZE_666 (0 << 0) +#define BASE_COLOR_SIZE_111 (1 << 0) +#define BASE_COLOR_SIZE_222 (2 << 0) +#define BASE_COLOR_SIZE_333 (3 << 0) +#define BASE_COLOR_SIZE_444 (4 << 0) +#define BASE_COLOR_SIZE_555 (5 << 0) +#define BASE_COLOR_SIZE_565 (6 << 0) +#define BASE_COLOR_SIZE_332 (7 << 0) +#define BASE_COLOR_SIZE_888 (8 << 0) + +#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 +#define SC1_H_QUALIFIER_NONE (1 << 16) +#define SC0_H_QUALIFIER_NONE (1 << 0) + +#define DC_DISP_DATA_ENABLE_OPTIONS 0x432 +#define DE_SELECT_ACTIVE_BLANK (0 << 0) +#define DE_SELECT_ACTIVE (1 << 0) +#define DE_SELECT_ACTIVE_IS (2 << 0) +#define DE_CONTROL_ONECLK (0 << 2) +#define DE_CONTROL_NORMAL (1 << 2) +#define DE_CONTROL_EARLY_EXT (2 << 2) +#define DE_CONTROL_EARLY (3 << 2) +#define DE_CONTROL_ACTIVE_BLANK (4 << 2) + +#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480 +#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 + +#define DC_WIN_CSC_YOF 0x611 +#define DC_WIN_CSC_KYRGB 0x612 +#define DC_WIN_CSC_KUR 0x613 +#define DC_WIN_CSC_KVR 0x614 +#define DC_WIN_CSC_KUG 0x615 +#define DC_WIN_CSC_KVG 0x616 +#define DC_WIN_CSC_KUB 0x617 +#define DC_WIN_CSC_KVB 0x618 +#define DC_WIN_AD_WIN_OPTIONS 0xB80 +#define DC_WIN_BD_WIN_OPTIONS 0xD80 +#define DC_WIN_CD_WIN_OPTIONS 0xF80 + +/* The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). */ +#define DC_WIN_WIN_OPTIONS 0x700 +#define H_DIRECTION (1 << 0) +#define V_DIRECTION (1 << 2) +#define COLOR_EXPAND (1 << 6) +#define CSC_ENABLE (1 << 18) +#define WIN_ENABLE (1 << 30) + +#define DC_WIN_COLOR_DEPTH 0x703 +#define WIN_COLOR_DEPTH_P1 0x0 +#define WIN_COLOR_DEPTH_P2 0x1 +#define WIN_COLOR_DEPTH_P4 0x2 +#define WIN_COLOR_DEPTH_P8 0x3 +#define WIN_COLOR_DEPTH_B4G4R4A4 0x4 +#define WIN_COLOR_DEPTH_B5G5R5A 0x5 +#define WIN_COLOR_DEPTH_B5G6R5 0x6 +#define WIN_COLOR_DEPTH_AB5G5R5 0x7 +#define WIN_COLOR_DEPTH_B8G8R8A8 0xC +#define WIN_COLOR_DEPTH_R8G8B8A8 0xD +#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE +#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF +#define WIN_COLOR_DEPTH_YCbCr422 0x10 +#define WIN_COLOR_DEPTH_YUV422 0x11 +#define WIN_COLOR_DEPTH_YCbCr420P 0x12 +#define WIN_COLOR_DEPTH_YUV420P 0x13 +#define WIN_COLOR_DEPTH_YCbCr422P 0x14 +#define WIN_COLOR_DEPTH_YUV422P 0x15 +#define WIN_COLOR_DEPTH_YCbCr422R 0x16 +#define WIN_COLOR_DEPTH_YUV422R 0x17 +#define WIN_COLOR_DEPTH_YCbCr422RA 0x18 +#define WIN_COLOR_DEPTH_YUV422RA 0x19 + +#define DC_WIN_BUFFER_CONTROL 0x702 +#define DC_WIN_POSITION 0x704 + +#define DC_WIN_SIZE 0x705 +#define H_SIZE(x) (((x) & 0x1fff) << 0) +#define V_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_PRESCALED_SIZE 0x706 +#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0) +#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_H_INITIAL_DDA 0x707 +#define DC_WIN_V_INITIAL_DDA 0x708 + +#define DC_WIN_DDA_INC 0x709 +#define H_DDA_INC(x) (((x) & 0xffff) << 0) +#define V_DDA_INC(x) (((x) & 0xffff) << 16) + +#define DC_WIN_LINE_STRIDE 0x70A +#define DC_WIN_DV_CONTROL 0x70E + +/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */ +#define DC_WINBUF_START_ADDR 0x800 +#define DC_WINBUF_ADDR_H_OFFSET 0x806 +#define DC_WINBUF_ADDR_V_OFFSET 0x808 +#define DC_WINBUF_SURFACE_KIND 0x80B + +/* Display serial interface registers. */ +#define DSI_RD_DATA 0x9 +#define DSI_WR_DATA 0xA + +#define DSI_POWER_CONTROL 0xB +#define DSI_POWER_CONTROL_ENABLE 1 + +#define DSI_INT_ENABLE 0xC +#define DSI_INT_STATUS 0xD +#define DSI_INT_MASK 0xE + +#define DSI_HOST_CONTROL 0xF +#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21) +#define DSI_HOST_CONTROL_CRC_RESET (1 << 20) +#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) +#define DSI_HOST_CONTROL_RAW (1 << 6) +#define DSI_HOST_CONTROL_HS (1 << 5) +#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4) +#define DSI_HOST_CONTROL_IMM_BTA (1 << 3) +#define DSI_HOST_CONTROL_PKT_BTA (1 << 2) +#define DSI_HOST_CONTROL_CS (1 << 1) +#define DSI_HOST_CONTROL_ECC (1 << 0) + +#define DSI_CONTROL 0x10 +#define DSI_CONTROL_HS_CLK_CTRL (1 << 20) +#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16) +#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12) +#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8) +#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4) +#define DSI_CONTROL_DCS_ENABLE (1 << 3) +#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2) +#define DSI_CONTROL_VIDEO_ENABLE (1 << 1) +#define DSI_CONTROL_HOST_ENABLE (1 << 0) + +#define DSI_SOL_DELAY 0x11 +#define DSI_MAX_THRESHOLD 0x12 + +#define DSI_TRIGGER 0x13 +#define DSI_TRIGGER_HOST (1 << 1) +#define DSI_TRIGGER_VIDEO (1 << 0) + +#define DSI_TX_CRC 0x14 +#define DSI_STATUS 0x15 +#define DSI_INIT_SEQ_CONTROL 0x1A +#define DSI_INIT_SEQ_DATA_0 0x1B +#define DSI_INIT_SEQ_DATA_1 0x1C +#define DSI_INIT_SEQ_DATA_2 0x1D +#define DSI_INIT_SEQ_DATA_3 0x1E +#define DSI_PKT_SEQ_0_LO 0x23 +#define DSI_PKT_SEQ_0_HI 0x24 +#define DSI_PKT_SEQ_1_LO 0x25 +#define DSI_PKT_SEQ_1_HI 0x26 +#define DSI_PKT_SEQ_2_LO 0x27 +#define DSI_PKT_SEQ_2_HI 0x28 +#define DSI_PKT_SEQ_3_LO 0x29 +#define DSI_PKT_SEQ_3_HI 0x2A +#define DSI_PKT_SEQ_4_LO 0x2B +#define DSI_PKT_SEQ_4_HI 0x2C +#define DSI_PKT_SEQ_5_LO 0x2D +#define DSI_PKT_SEQ_5_HI 0x2E +#define DSI_DCS_CMDS 0x33 +#define DSI_PKT_LEN_0_1 0x34 +#define DSI_PKT_LEN_2_3 0x35 +#define DSI_PKT_LEN_4_5 0x36 +#define DSI_PKT_LEN_6_7 0x37 +#define DSI_PHY_TIMING_0 0x3C +#define DSI_PHY_TIMING_1 0x3D +#define DSI_PHY_TIMING_2 0x3E +#define DSI_BTA_TIMING 0x3F + +#define DSI_TIMEOUT_0 0x44 +#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0) + +#define DSI_TIMEOUT_1 0x45 +#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0) + +#define DSI_TO_TALLY 0x46 + +#define DSI_PAD_CONTROL_0 0x4B +#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24) +#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) +#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8) +#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0) + +#define DSI_PAD_CONTROL_CD 0x4c +#define DSI_VIDEO_MODE_CONTROL 0x4E + +#define DSI_PAD_CONTROL_1 0x4F +#define DSI_PAD_CONTROL_2 0x50 + +#define DSI_PAD_CONTROL_3 0x51 +#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12) +#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8) +#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4) +#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0) + +#define DSI_PAD_CONTROL_4 0x52 + +typedef struct _cfg_op_t +{ + uint32_t off; + uint32_t val; +} cfg_op_t; + +void display_init(); +void display_end(); + +/* Show one single color on the display. */ +void display_color_screen(uint32_t color); + +/* Switches screen backlight ON/OFF. */ +void display_backlight(bool enable); + +/* Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ +uint32_t *display_init_framebuffer(void *address); + +#endif diff --git a/fusee/fusee-primary/src/di.inl b/fusee/fusee-primary/src/di.inl new file mode 100644 index 000000000..c34fb4cf2 --- /dev/null +++ b/fusee/fusee-primary/src/di.inl @@ -0,0 +1,546 @@ +//Clock config. +static const cfg_op_t _display_config_1[4] = { + {0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 + {0x34, 0x4830A001}, //CLK_RST_CONTROLLER_PLLD_BASE + {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 + {0x37, 0x2D0AAA} //CLK_RST_CONTROLLER_PLLD_MISC +}; + +//Display A config. +static const cfg_op_t _display_config_2[94] = { + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_REG_ACT_CONTROL, 0x54}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_DISP_DC_MCCIF_FIFOCTRL, 0}, + {DC_DISP_DISP_MEM_HIGH_PRIORITY, 0}, + {DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0}, + {DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE}, + {DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL}, + {DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | 0x9}, // 9: SYNCPT + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, + {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, + {0x4E4, 0}, + {DC_COM_CRC_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ} +}; + +//DSI Init config. +static const cfg_op_t _display_config_3[60] = { + {DSI_WR_DATA, 0}, + {DSI_INT_ENABLE, 0}, + {DSI_INT_STATUS, 0}, + {DSI_INT_MASK, 0}, + {DSI_INIT_SEQ_DATA_0, 0}, + {DSI_INIT_SEQ_DATA_1, 0}, + {DSI_INIT_SEQ_DATA_2, 0}, + {DSI_INIT_SEQ_DATA_3, 0}, + {DSI_DCS_CMDS, 0}, + {DSI_PKT_SEQ_0_LO, 0}, + {DSI_PKT_SEQ_1_LO, 0}, + {DSI_PKT_SEQ_2_LO, 0}, + {DSI_PKT_SEQ_3_LO, 0}, + {DSI_PKT_SEQ_4_LO, 0}, + {DSI_PKT_SEQ_5_LO, 0}, + {DSI_PKT_SEQ_0_HI, 0}, + {DSI_PKT_SEQ_1_HI, 0}, + {DSI_PKT_SEQ_2_HI, 0}, + {DSI_PKT_SEQ_3_HI, 0}, + {DSI_PKT_SEQ_4_HI, 0}, + {DSI_PKT_SEQ_5_HI, 0}, + {DSI_CONTROL, 0}, + {DSI_PAD_CONTROL_CD, 0}, + {DSI_SOL_DELAY, 0x18}, + {DSI_MAX_THRESHOLD, 0x1E0}, + {DSI_TRIGGER, 0}, + {DSI_INIT_SEQ_CONTROL, 0}, + {DSI_PKT_LEN_0_1, 0}, + {DSI_PKT_LEN_2_3, 0}, + {DSI_PKT_LEN_4_5, 0}, + {DSI_PKT_LEN_6_7, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30109}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Enable + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, 0}, + {DSI_POWER_CONTROL, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30118}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_MAX_THRESHOLD, 0x40}, + {DSI_TRIGGER, 0}, + {DSI_TX_CRC, 0}, + {DSI_INIT_SEQ_CONTROL, 0} +}; + +//DSI config (if ver == 0x10). +static const cfg_op_t _display_config_4[43] = { + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0x9483FFB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xBD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x1939}, + {DSI_WR_DATA, 0xAAAAAAD8}, + {DSI_WR_DATA, 0xAAAAAAEB}, + {DSI_WR_DATA, 0xAAEBAAAA}, + {DSI_WR_DATA, 0xAAAAAAAA}, + {DSI_WR_DATA, 0xAAAAAAEB}, + {DSI_WR_DATA, 0xAAEBAAAA}, + {DSI_WR_DATA, 0xAA}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x1BD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2739}, + {DSI_WR_DATA, 0xFFFFFFD8}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFF}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2BD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xF39}, + {DSI_WR_DATA, 0xFFFFFFD8}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFF}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xBD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x6D915}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0xB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST} +}; + +//DSI config. +static const cfg_op_t _display_config_5[21] = { + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30172}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_PKT_SEQ_0_LO, 0x40000208}, + {DSI_PKT_SEQ_2_LO, 0x40000308}, + {DSI_PKT_SEQ_4_LO, 0x40000308}, + {DSI_PKT_SEQ_1_LO, 0x40000308}, + {DSI_PKT_SEQ_3_LO, 0x3F3B2B08}, + {DSI_PKT_SEQ_3_HI, 0x2CC}, + {DSI_PKT_SEQ_5_LO, 0x3F3B2B08}, + {DSI_PKT_SEQ_5_HI, 0x2CC}, + {DSI_PKT_LEN_0_1, 0xCE0000}, + {DSI_PKT_LEN_2_3, 0x87001A2}, + {DSI_PKT_LEN_4_5, 0x190}, + {DSI_PKT_LEN_6_7, 0x190}, + {DSI_HOST_CONTROL, 0}, +}; + +//Clock config. +static const cfg_op_t _display_config_6[3] = { + {0x34, 0x4810C001}, //CLK_RST_CONTROLLER_PLLD_BASE + {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 + {0x37, 0x2DFC00} //CLK_RST_CONTROLLER_PLLD_MISC +}; + +//DSI config. +static const cfg_op_t _display_config_7[10] = { + {DSI_TRIGGER, 0}, + {DSI_CONTROL, 0}, + {DSI_SOL_DELAY, 6}, + {DSI_MAX_THRESHOLD, 0x1E0}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL| DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC} +}; + +//MIPI CAL config. +static const cfg_op_t _display_config_8[6] = { + {0x18, 0}, + {2, 0xF3F10000}, + {0x16, 1}, + {0x18, 0}, + {0x18, 0x10010}, + {0x17, 0x300} +}; + +//DSI config. +static const cfg_op_t _display_config_9[4] = { + {DSI_PAD_CONTROL_1, 0}, + {DSI_PAD_CONTROL_2, 0}, + {DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)}, + {DSI_PAD_CONTROL_4, 0} +}; + +//MIPI CAL config. +static const cfg_op_t _display_config_10[16] = { + {0xE, 0x200200}, + {0xF, 0x200200}, + {0x19, 0x200002}, + {0x1A, 0x200002}, + {5, 0}, + {6, 0}, + {7, 0}, + {8, 0}, + {9, 0}, + {0xA, 0}, + {0x10, 0}, + {0x11, 0}, + {0x1A, 0}, + {0x1C, 0}, + {0x1D, 0}, + {0, 0x2A000001} +}; + +//Display A config. +static const cfg_op_t _display_config_11[113] = { + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, + {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, + {0x4E4, 0}, + {DC_COM_CRC_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + /* Set Display timings */ + {DC_DISP_DISP_TIMING_OPTIONS, 0}, + {DC_DISP_REF_TO_SYNC, (1 << 16)}, // h_ref_to_sync = 0, v_ref_to_sync = 1. + {DC_DISP_SYNC_WIDTH, 0x10048}, + {DC_DISP_BACK_PORCH, 0x90048}, + {DC_DISP_ACTIVE, 0x50002D0}, + {DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the DC_DISP_ACTIVE cmd. + /* End of Display timings */ + {DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE}, + {DC_COM_PIN_OUTPUT_ENABLE(1), 0}, + {DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_DISP_DISP_CLOCK_CONTROL, 0}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX}, + {DC_DISP_FRONT_PORCH, 0xA0088}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0} +}; + +////Display A config. +static const cfg_op_t _display_config_12[17] = { + {DC_DISP_FRONT_PORCH, 0xA0088}, + {DC_CMD_INT_MASK, 0}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_INT_ENABLE, 0}, + {DC_CMD_CONT_SYNCPT_VSYNC, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_DISPLAY_POWER_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, +}; + +//DSI config. +static const cfg_op_t _display_config_13[16] = { + {DSI_POWER_CONTROL, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30109}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) }, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_MAX_THRESHOLD, 0x40}, + {DSI_TRIGGER, 0}, + {DSI_TX_CRC, 0}, + {DSI_INIT_SEQ_CONTROL, 0} +}; + +//DSI config (if ver == 0x10). +static const cfg_op_t _display_config_14[22] = { + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0x9483FFB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2139}, + {DSI_WR_DATA, 0x191919D5}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xB39}, + {DSI_WR_DATA, 0x4F0F41B1}, + {DSI_WR_DATA, 0xF179A433}, + {DSI_WR_DATA, 0x2D81}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0xB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST} +}; + +//Display A config. +static const cfg_op_t cfg_display_one_color[8] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} //DISPLAY_CTRL_MODE: continuous display. +}; + +//Display A config. +static const cfg_op_t cfg_display_framebuffer[32] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //T_A8R8G8B8 //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8 + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_POSITION, 0}, //(0,0) + {DC_WIN_H_INITIAL_DDA, 0}, + {DC_WIN_V_INITIAL_DDA, 0}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes. + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels. + {DC_WIN_LINE_STRIDE, 0x6000C00}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_BUFFER_CONTROL, 0}, + {DC_WINBUF_SURFACE_KIND, 0}, //Regular surface. + {DC_WINBUF_START_ADDR, 0xC0000000}, //Framebuffer address. + {DC_WINBUF_ADDR_H_OFFSET, 0}, + {DC_WINBUF_ADDR_V_OFFSET, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, //Enable window AD. + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display. + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update. + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request. +}; diff --git a/fusee/fusee-primary/src/hwinit/emc.h b/fusee/fusee-primary/src/emc.h similarity index 98% rename from fusee/fusee-primary/src/hwinit/emc.h rename to fusee/fusee-primary/src/emc.h index ce134c2fe..a032d5c97 100644 --- a/fusee/fusee-primary/src/hwinit/emc.h +++ b/fusee/fusee-primary/src/emc.h @@ -1,27 +1,11 @@ -/* -* arch/arm/mach-tegra/tegra21_emc.h -* -* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -* -*/ +#ifndef FUSEE_EMC_H_ +#define FUSEE_EMC_H_ -#ifndef _EMC_H_ -#define _EMC_H_ +#define EMC_BASE 0x7001B000 +#define MAKE_EMC_REG(n) MAKE_REG32(EMC_BASE + n) +#define EMC_DBG 0x8 +#define EMC_CFG 0xC #define EMC_CONFIG_SAMPLE_DELAY 0x5f0 #define EMC_CFG_UPDATE 0x5f4 #define EMC_ADR_CFG 0x10 diff --git a/fusee/fusee-primary/src/flow.h b/fusee/fusee-primary/src/flow.h new file mode 100644 index 000000000..b3128d55e --- /dev/null +++ b/fusee/fusee-primary/src/flow.h @@ -0,0 +1,15 @@ +#ifndef FUSEE_FLOW_CTLR_H +#define FUSEE_FLOW_CTLR_H + +#include <stdint.h> + +#define FLOW_CTLR_BASE 0x60007000 +#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_CTLR_BASE + ofs) + +#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) +#define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040) +#define FLOW_CTLR_FLOW_DBG_QUAL_0 MAKE_FLOW_REG(0x050) +#define FLOW_CTLR_L2FLUSH_CONTROL_0 MAKE_FLOW_REG(0x094) +#define FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 MAKE_FLOW_REG(0x098) + +#endif diff --git a/fusee/fusee-primary/src/fs_utils.c b/fusee/fusee-primary/src/fs_utils.c index c3ee71d4c..1c8529f07 100644 --- a/fusee/fusee-primary/src/fs_utils.c +++ b/fusee/fusee-primary/src/fs_utils.c @@ -1,5 +1,5 @@ #include "fs_utils.h" -#include "hwinit.h" +#include "mc.h" #include "lib/printk.h" #include "lib/fatfs/ff.h" diff --git a/fusee/fusee-primary/src/fuse.c b/fusee/fusee-primary/src/fuse.c index 2bdfa3740..04780c9ce 100644 --- a/fusee/fusee-primary/src/fuse.c +++ b/fusee/fusee-primary/src/fuse.c @@ -2,7 +2,7 @@ #include <stdint.h> #include <string.h> -#include "hwinit.h" +#include "car.h" #include "fuse.h" #include "timers.h" @@ -13,154 +13,155 @@ void fuse_enable_power(void); void fuse_disable_power(void); void fuse_wait_idle(void); -/* Initialize the FUSE driver */ -void fuse_init(void) -{ - /* - Already done by hwinit, except maybe fuse_secondary_private_key_disable (?) - fuse_make_regs_visible(); - fuse_secondary_private_key_disable(); - fuse_disable_programming(); - */ +/* Initialize the fuse driver */ +void fuse_init(void) { + fuse_make_regs_visible(); + fuse_secondary_private_key_disable(); + fuse_disable_programming(); /* TODO: Overrides (iROM patches) and various reads happen here */ } /* Make all fuse registers visible */ -void fuse_make_regs_visible(void) -{ - clock_enable_fuse(1); +void fuse_make_regs_visible(void) { + clkrst_enable_fuse_regs(true); } /* Enable power to the fuse hardware array */ -void fuse_enable_power(void) -{ - FUSE_REGS->FUSE_PWR_GOOD_SW = 1; - wait(1); +void fuse_enable_power(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PWR_GOOD_SW = 1; + udelay(1); } /* Disable power to the fuse hardware array */ -void fuse_disable_power(void) -{ - FUSE_REGS->FUSE_PWR_GOOD_SW = 0; - wait(1); +void fuse_disable_power(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PWR_GOOD_SW = 0; + udelay(1); } /* Wait for the fuse driver to go idle */ -void fuse_wait_idle(void) -{ +void fuse_wait_idle(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); uint32_t ctrl_val = 0; /* Wait for STATE_IDLE */ while ((ctrl_val & (0xF0000)) != 0x40000) { - wait(1); - ctrl_val = FUSE_REGS->FUSE_CTRL; + udelay(1); + ctrl_val = fuse->FUSE_CTRL; } } /* Read a fuse from the hardware array */ -uint32_t fuse_hw_read(uint32_t addr) -{ +uint32_t fuse_hw_read(uint32_t addr) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); fuse_wait_idle(); /* Program the target address */ - FUSE_REGS->FUSE_REG_ADDR = addr; + fuse->FUSE_REG_ADDR = addr; /* Enable read operation in control register */ - uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; + uint32_t ctrl_val = fuse->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x1; /* Set FUSE_READ command */ - FUSE_REGS->FUSE_CTRL = ctrl_val; + fuse->FUSE_CTRL = ctrl_val; fuse_wait_idle(); - return FUSE_REGS->FUSE_REG_READ; + return fuse->FUSE_REG_READ; } /* Write a fuse in the hardware array */ -void fuse_hw_write(uint32_t value, uint32_t addr) -{ +void fuse_hw_write(uint32_t value, uint32_t addr) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); fuse_wait_idle(); /* Program the target address and value */ - FUSE_REGS->FUSE_REG_ADDR = addr; - FUSE_REGS->FUSE_REG_WRITE = value; + fuse->FUSE_REG_ADDR = addr; + fuse->FUSE_REG_WRITE = value; /* Enable write operation in control register */ - uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; + uint32_t ctrl_val = fuse->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x2; /* Set FUSE_WRITE command */ - FUSE_REGS->FUSE_CTRL = ctrl_val; + fuse->FUSE_CTRL = ctrl_val; fuse_wait_idle(); } /* Sense the fuse hardware array into the shadow cache */ -void fuse_hw_sense(void) -{ +void fuse_hw_sense(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); fuse_wait_idle(); /* Enable sense operation in control register */ - uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; + uint32_t ctrl_val = fuse->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x3; /* Set FUSE_SENSE command */ - FUSE_REGS->FUSE_CTRL = ctrl_val; + fuse->FUSE_CTRL = ctrl_val; fuse_wait_idle(); } /* Disables all fuse programming. */ void fuse_disable_programming(void) { - FUSE_REGS->FUSE_DIS_PGM = 1; + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_DIS_PGM = 1; } /* Unknown exactly what this does, but it alters the contents read from the fuse cache. */ void fuse_secondary_private_key_disable(void) { - FUSE_REGS->FUSE_PRIVATEKEYDISABLE = 0x10; + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PRIVATEKEYDISABLE = 0x10; } /* Read the SKU info register from the shadow cache */ -uint32_t fuse_get_sku_info(void) -{ - return FUSE_CHIP_REGS->FUSE_SKU_INFO; +uint32_t fuse_get_sku_info(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return fuse_chip->FUSE_SKU_INFO; } /* Read the bootrom patch version from a register in the shadow cache */ -uint32_t fuse_get_bootrom_patch_version(void) -{ - return FUSE_CHIP_REGS->FUSE_SOC_SPEEDO_1; +uint32_t fuse_get_bootrom_patch_version(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return fuse_chip->FUSE_SOC_SPEEDO_1; } /* Read a spare bit register from the shadow cache */ -uint32_t fuse_get_spare_bit(uint32_t idx) -{ +uint32_t fuse_get_spare_bit(uint32_t idx) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + if (idx >= 32) { return 0; } - return FUSE_CHIP_REGS->FUSE_SPARE_BIT[idx]; + return fuse_chip->FUSE_SPARE_BIT[idx]; } /* Read a reserved ODM register from the shadow cache */ -uint32_t fuse_get_reserved_odm(uint32_t idx) -{ +uint32_t fuse_get_reserved_odm(uint32_t idx) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + if (idx >= 8) { return 0; } - return FUSE_CHIP_REGS->FUSE_RESERVED_ODM[idx]; + return fuse_chip->FUSE_RESERVED_ODM[idx]; } /* Derive the Device ID using values in the shadow cache */ uint64_t fuse_get_device_id(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + uint64_t device_id = 0; - uint64_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF; - uint64_t x_coord = FUSE_CHIP_REGS->FUSE_X_COORDINATE & 0x1FF; - uint64_t wafer_id = FUSE_CHIP_REGS->FUSE_WAFER_ID & 0x3F; - uint32_t lot_code = FUSE_CHIP_REGS->FUSE_LOT_CODE_0; - uint64_t fab_code = FUSE_CHIP_REGS->FUSE_FAB_CODE & 0x3F; + uint64_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF; + uint64_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF; + uint64_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F; + uint32_t lot_code = fuse_chip->FUSE_LOT_CODE_0; + uint64_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F; uint64_t derived_lot_code = 0; for (unsigned int i = 0; i < 5; i++) { derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F); @@ -177,24 +178,27 @@ uint64_t fuse_get_device_id(void) { /* Get the DRAM ID using values in the shadow cache */ uint32_t fuse_get_dram_id(void) { - return (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 3) & 0x7; + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return (fuse_chip->FUSE_RESERVED_ODM[4] >> 3) & 0x7; } /* Derive the Hardware Type using values in the shadow cache */ uint32_t fuse_get_hardware_type(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + /* This function is very different between 4.x and < 4.x */ - uint32_t hardware_type = ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 2) & 1); + uint32_t hardware_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((fuse_chip->FUSE_RESERVED_ODM[4] >> 2) & 1); /* TODO: choose; if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT) { static const uint32_t types[] = {0,1,4,3}; - hardware_type |= (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 14) & 0x3C; + hardware_type |= (fuse_chip->FUSE_RESERVED_ODM[4] >> 14) & 0x3C; hardware_type--; return hardware_type > 3 ? 4 : types[hardware_type]; } else {*/ if (hardware_type >= 1) { return hardware_type > 2 ? 3 : hardware_type - 1; - } else if ((FUSE_CHIP_REGS->FUSE_SPARE_BIT[9] & 1) == 0) { + } else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) { return 0; } else { return 3; @@ -204,8 +208,10 @@ uint32_t fuse_get_hardware_type(void) { /* Derive the Retail Type using values in the shadow cache */ uint32_t fuse_get_retail_type(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + /* Retail type = IS_RETAIL | UNIT_TYPE */ - uint32_t retail_type = ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 7) & 4) | (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] & 3); + uint32_t retail_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 4) | (fuse_chip->FUSE_RESERVED_ODM[4] & 3); if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */ return 1; } else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */ @@ -216,16 +222,17 @@ uint32_t fuse_get_retail_type(void) { /* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */ void fuse_get_hardware_info(void *dst) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); uint32_t hw_info[0x4]; - uint32_t unk_hw_fuse = FUSE_CHIP_REGS->_0x120 & 0x3F; - uint32_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF; - uint32_t x_coord = FUSE_CHIP_REGS->FUSE_X_COORDINATE & 0x1FF; - uint32_t wafer_id = FUSE_CHIP_REGS->FUSE_WAFER_ID & 0x3F; - uint32_t lot_code_0 = FUSE_CHIP_REGS->FUSE_LOT_CODE_0; - uint32_t lot_code_1 = FUSE_CHIP_REGS->FUSE_LOT_CODE_1 & 0x0FFFFFFF; - uint32_t fab_code = FUSE_CHIP_REGS->FUSE_FAB_CODE & 0x3F; - uint32_t vendor_code = FUSE_CHIP_REGS->FUSE_VENDOR_CODE & 0xF; + uint32_t unk_hw_fuse = fuse_chip->_0x120 & 0x3F; + uint32_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF; + uint32_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF; + uint32_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F; + uint32_t lot_code_0 = fuse_chip->FUSE_LOT_CODE_0; + uint32_t lot_code_1 = fuse_chip->FUSE_LOT_CODE_1 & 0x0FFFFFFF; + uint32_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F; + uint32_t vendor_code = fuse_chip->FUSE_VENDOR_CODE & 0xF; /* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */ hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse)); diff --git a/fusee/fusee-primary/src/fuse.h b/fusee/fusee-primary/src/fuse.h index 989f564bf..63285b64f 100644 --- a/fusee/fusee-primary/src/fuse.h +++ b/fusee/fusee-primary/src/fuse.h @@ -1,6 +1,11 @@ #ifndef FUSEE_FUSE_H #define FUSEE_FUSE_H +#define FUSE_BASE 0x7000F800 +#define FUSE_CHIP_BASE (FUSE_BASE + 0x100) +#define MAKE_FUSE_REG(n) MAKE_REG32(FUSE_BASE + n) +#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n) + typedef struct { uint32_t FUSE_CTRL; uint32_t FUSE_REG_ADDR; @@ -17,7 +22,7 @@ typedef struct { uint32_t FUSE_WRITE_ACCESS; uint32_t FUSE_PWR_GOOD_SW; uint32_t _0x38[0x32]; -} fuse_registers_t; +} tegra_fuse_t; typedef struct { uint32_t FUSE_PRODUCTION_MODE; @@ -160,17 +165,15 @@ typedef struct { uint32_t _0x278; uint32_t _0x27C; uint32_t FUSE_SPARE_BIT[0x20]; -} fuse_chip_registers_t; +} tegra_fuse_chip_t; -static inline volatile fuse_registers_t *get_fuse_regs(void) { - return (volatile fuse_registers_t *)(0x7000F000 + 0x800); +static inline volatile tegra_fuse_t *fuse_get_regs(void) { + return (volatile tegra_fuse_t *)FUSE_BASE; } -static inline volatile fuse_chip_registers_t *get_fuse_chip_regs(void) { - return (volatile fuse_chip_registers_t *)(0x7000F000 + 0x900); +static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) { + return (volatile tegra_fuse_chip_t *)FUSE_CHIP_BASE; } -#define FUSE_REGS (get_fuse_regs()) -#define FUSE_CHIP_REGS (get_fuse_chip_regs()) void fuse_init(void); diff --git a/fusee/fusee-primary/src/gpio.h b/fusee/fusee-primary/src/gpio.h index b3da7dc56..a916c989c 100644 --- a/fusee/fusee-primary/src/gpio.h +++ b/fusee/fusee-primary/src/gpio.h @@ -1,6 +1,11 @@ #ifndef FUSEE_GPIO_H #define FUSEE_GPIO_H +#include <stdint.h> + +#define GPIO_BASE 0x6000D000 +#define MAKE_GPIO_REG(n) MAKE_REG32(GPIO_BASE + n) + #define TEGRA_GPIO_PORTS 4 #define TEGRA_GPIO_BANKS 8 #define GPIO_BANK_SHIFT 5 @@ -68,7 +73,7 @@ typedef struct { static inline volatile tegra_gpio_t *gpio_get_regs(void) { - return (volatile tegra_gpio_t *)0x6000D000; + return (volatile tegra_gpio_t *)GPIO_BASE; } #define TEGRA_GPIO(port, offset) \ @@ -87,9 +92,16 @@ static inline volatile tegra_gpio_t *gpio_get_regs(void) #define GPIO_LEVEL_HIGH 1 /* Named GPIOs */ +#define GPIO_BUTTON_VOL_DOWN TEGRA_GPIO(X, 7) +#define GPIO_BUTTON_VOL_UP TEGRA_GPIO(X, 6) #define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1) #define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4) #define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4) +#define GPIO_LCD_BL_P5V TEGRA_GPIO(I, 0) +#define GPIO_LCD_BL_N5V TEGRA_GPIO(I, 1) +#define GPIO_LCD_BL_PWM TEGRA_GPIO(V, 0) +#define GPIO_LCD_BL_EN TEGRA_GPIO(V, 1) +#define GPIO_LCD_BL_RST TEGRA_GPIO(V, 2) void gpio_configure_mode(uint32_t pin, uint32_t mode); void gpio_configure_direction(uint32_t pin, uint32_t dir); diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c new file mode 100644 index 000000000..903b750bd --- /dev/null +++ b/fusee/fusee-primary/src/hwinit.c @@ -0,0 +1,245 @@ +#include "hwinit.h" +#include "apb_misc.h" +#include "car.h" +#include "di.h" +#include "fuse.h" +#include "gpio.h" +#include "i2c.h" +#include "max77620.h" +#include "mc.h" +#include "pinmux.h" +#include "pmc.h" +#include "se.h" +#include "sdram.h" +#include "sysctr0.h" +#include "sysreg.h" +#include "timers.h" +#include "uart.h" + +void config_oscillators() +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + car->spare_reg0 = ((car->spare_reg0 & 0xFFFFFFF3) | 4); + + SYSCTR0_CNTFID0_0 = 19200000; + MAKE_TIMERS_REG(0x14) = 0x45F; + + car->osc_ctrl = 0x50000071; + pmc->osc_edpd_over = ((pmc->osc_edpd_over & 0xFFFFFF81) | 0xE); + pmc->osc_edpd_over = ((pmc->osc_edpd_over & 0xFFBFFFFF) | 0x400000); + pmc->cntrl2 = ((pmc->cntrl2 & 0xFFFFEFFF) | 0x1000); + pmc->scratch188 = ((pmc->scratch188 & 0xFCFFFFFF) | 0x2000000); + car->clk_sys_rate = 0x10; + car->pllmb_base &= 0xBFFFFFFF; + pmc->tsc_mult = ((pmc->tsc_mult & 0xFFFF0000) | 0x249F); /* 0x249F = 19200000 * (16 / 32.768 kHz) */ + car->sclk_brst_pol = 0x20004444; + car->super_sclk_div = 0x80000000; + car->clk_sys_rate = 2; +} + +void config_gpios() +{ + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + + pinmux->uart2_tx = 0; + pinmux->uart3_tx = 0; + pinmux->pe6 = PINMUX_INPUT; + pinmux->ph6 = PINMUX_INPUT; + + gpio_configure_mode(TEGRA_GPIO(G, 0), GPIO_MODE_GPIO); + gpio_configure_mode(TEGRA_GPIO(D, 1), GPIO_MODE_GPIO); + gpio_configure_mode(TEGRA_GPIO(E, 6), GPIO_MODE_GPIO); + gpio_configure_mode(TEGRA_GPIO(H, 6), GPIO_MODE_GPIO); + gpio_configure_direction(TEGRA_GPIO(G, 0), GPIO_DIRECTION_INPUT); + gpio_configure_direction(TEGRA_GPIO(D, 1), GPIO_DIRECTION_INPUT); + gpio_configure_direction(TEGRA_GPIO(E, 6), GPIO_DIRECTION_INPUT); + gpio_configure_direction(TEGRA_GPIO(H, 6), GPIO_DIRECTION_INPUT); + + pinmux->gen1_i2c_scl = PINMUX_INPUT; + pinmux->gen1_i2c_sda = PINMUX_INPUT; + pinmux->pwr_i2c_scl = PINMUX_INPUT; + pinmux->pwr_i2c_sda = PINMUX_INPUT; + pinmux->uart1_rx = 0; + pinmux->uart1_tx = (PINMUX_INPUT | PINMUX_PULL_UP); + pinmux->uart1_rts = 0; + pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN); + + /* Configure volume up/down as inputs. */ + gpio_configure_mode(GPIO_BUTTON_VOL_UP, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_BUTTON_VOL_DOWN, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_BUTTON_VOL_UP, GPIO_DIRECTION_INPUT); + gpio_configure_direction(GPIO_BUTTON_VOL_DOWN, GPIO_DIRECTION_INPUT); +} + +void config_pmc_scratch() +{ + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + pmc->scratch20 &= 0xFFF3FFFF; + pmc->scratch190 &= 0xFFFFFFFE; + pmc->secure_scratch21 |= 0x10; +} + +void mbist_workaround() +{ + volatile tegra_car_t *car = car_get_regs(); + + car->clk_source_sor1 = ((car->clk_source_sor1 | 0x8000) & 0xFFFFBFFF); + car->plld_base |= 0x40800000u; + car->rst_dev_y_clr = 0x40; + car->rst_dev_x_clr = 0x40000; + car->rst_dev_l_clr = 0x18000000; + udelay(2); + + /* Setup I2S. */ + MAKE_I2S_REG(0x0A0) |= 0x400; + MAKE_I2S_REG(0x088) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x1A0) |= 0x400; + MAKE_I2S_REG(0x188) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x2A0) |= 0x400; + MAKE_I2S_REG(0x288) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x3A0) |= 0x400; + MAKE_I2S_REG(0x388) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x4A0) |= 0x400; + MAKE_I2S_REG(0x488) &= 0xFFFFFFFE; + + MAKE_DI_REG(DC_COM_DSC_TOP_CTL) |= 4; + MAKE_VIC_REG(0x8C) = 0xFFFFFFFF; + udelay(2); + + /* Set devices in reset. */ + car->rst_dev_y_set = 0x40; + car->rst_dev_l_set = 0x18000000; + car->rst_dev_x_set = 0x40000; + + /* Clock out enables. */ + car->clk_out_enb_h = 0xC0; + car->clk_out_enb_l = 0x80000130; + car->clk_out_enb_u = 0x1F00200; + car->clk_out_enb_v = 0x80400808; + car->clk_out_enb_w = 0x402000FC; + car->clk_out_enb_x = 0x23000780; + car->clk_out_enb_y = 0x300; + + /* LVL2 clock gate overrides. */ + car->lvl2_clk_gate_ovra = 0; + car->lvl2_clk_gate_ovrb = 0; + car->lvl2_clk_gate_ovrc = 0; + car->lvl2_clk_gate_ovrd = 0; + car->lvl2_clk_gate_ovre = 0; + + /* Configure clock sources. */ + car->plld_base &= 0x1F7FFFFF; + car->clk_source_sor1 &= 0xFFFF3FFF; + car->clk_source_vi = ((car->clk_source_vi & 0x1FFFFFFF) | 0x80000000); + car->clk_source_host1x = ((car->clk_source_host1x & 0x1FFFFFFF) | 0x80000000); + car->clk_source_nvenc = ((car->clk_source_nvenc & 0x1FFFFFFF) | 0x80000000); +} + +void config_se_brom() +{ + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + volatile tegra_se_t *se = se_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* Bootrom part we skipped. */ + uint32_t sbk[4] = {fuse_chip->FUSE_PRIVATE_KEY[0], fuse_chip->FUSE_PRIVATE_KEY[1], fuse_chip->FUSE_PRIVATE_KEY[2], fuse_chip->FUSE_PRIVATE_KEY[3]}; + set_aes_keyslot(0xE, sbk, 0x10); + + /* Lock SBK from being read. */ + se->AES_KEYSLOT_FLAGS[0xE] = 0x7E; + + /* This memset needs to happen here, else TZRAM will behave weirdly later on. */ + memset((void *)0x7C010000, 0, 0x10000); + + pmc->crypto_op = 0; + se->INT_STATUS_REG = 0x1F; + + /* Lock SSK (although it's not set and unused anyways). */ + se->AES_KEYSLOT_FLAGS[0xF] = 0x7E; + + /* Clear the boot reason to avoid problems later */ + pmc->scratch200 = 0; + pmc->reset_status = 0; +} + +void nx_hwinit() +{ + volatile tegra_pmc_t *pmc = pmc_get_regs(); + volatile tegra_car_t *car = car_get_regs(); + + /* Bootrom stuff we skipped by going through RCM. */ + config_se_brom(); + + AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; + pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); + + mbist_workaround(); + clkrst_reboot(CARDEVICE_SE); + + /* Initialize the fuse driver. */ + fuse_init(); + + /* Initialize the memory controller. */ + mc_enable(); + + /* Configure oscillators, pinmux and GPIOs. */ + config_oscillators(); + APB_MISC_PP_PINMUX_GLOBAL_0 = 0; + config_gpios(); + + /* Uncomment for UART debugging. */ + /* + clkrst_reboot(CARDEVICE_UARTC); + uart_init(UART_C, 115200); + */ + + clkrst_reboot(CARDEVICE_CL_DVFS); + clkrst_reboot(CARDEVICE_I2C1); + clkrst_reboot(CARDEVICE_I2C5); + clkrst_reboot(CARDEVICE_SE); + clkrst_reboot(CARDEVICE_UNK); + + /* Initialize I2C1 and I2C5. */ + i2c_init(0); + i2c_init(4); + + uint8_t val = 0x40; + i2c_send(4, 0x3C, MAX77620_REG_CNFGBBC, &val, 1); + val = 0x78; + i2c_send(4, 0x3C, MAX77620_REG_ONOFFCNFG1, &val, 1); + + val = 0x38; + i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG0, &val, 1); + val = 0x3A; + i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG1, &val, 1); + val = 0x38; + i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG2, &val, 1); + val = 0xF; + i2c_send(4, 0x3C, MAX77620_REG_FPS_LDO4, &val, 1); + val = 0xC7; + i2c_send(4, 0x3C, MAX77620_REG_FPS_LDO8, &val, 1); + val = 0x4F; + i2c_send(4, 0x3C, MAX77620_REG_FPS_SD0, &val, 1); + val = 0x29; + i2c_send(4, 0x3C, MAX77620_REG_FPS_SD1, &val, 1); + val = 0x1B; + i2c_send(4, 0x3C, MAX77620_REG_FPS_SD3, &val, 1); + + val = 42; /* 42 = (1125000 - 600000) / 12500 -> 1.125V */ + i2c_send(4, 0x3C, MAX77620_REG_SD0, &val, 1); + + /* Configure and lock PMC scratch registers. */ + config_pmc_scratch(); + + car->sclk_brst_pol = ((car->sclk_brst_pol & 0xFFFF8888) | 0x3333); + + /* Configure memory controller carveouts. */ + mc_config_carveout(); + + /* Initialize and save SDRAM. */ + sdram_init(); + sdram_lp0_save_params(sdram_get_params()); +} \ No newline at end of file diff --git a/fusee/fusee-primary/src/hwinit.h b/fusee/fusee-primary/src/hwinit.h index 7b66f07b7..da197ae83 100644 --- a/fusee/fusee-primary/src/hwinit.h +++ b/fusee/fusee-primary/src/hwinit.h @@ -1,39 +1,9 @@ -#ifndef FUSEE_HWINIT_H -#define FUSEE_HWINIT_H +#ifndef FUSEE_HWINIT_H_ +#define FUSEE_HWINIT_H_ -/* Symbols from hwinit that we're using, but w/o importing macro definitions that may clash with ours */ +#define I2S_BASE 0x702D1000 +#define MAKE_I2S_REG(n) MAKE_REG32(I2S_BASE + n) -#include "hwinit/types.h" -#include "hwinit/hwinit.h" -#include "hwinit/i2c.h" +void nx_hwinit(); -#include <stdbool.h> - -#define UART_A 0 -#define UART_B 1 -#define UART_C 2 -#define BAUD_115200 115200 - -void uart_init(u32 idx, u32 baud); -void uart_wait_idle(u32 idx, u32 which); -void uart_send(u32 idx, u8 *buf, u32 len); -void uart_recv(u32 idx, u8 *buf, u32 len); - -void display_init(); -void display_end(); - -void clock_enable_fuse(u32 enable); - -/*! Show one single color on the display. */ -void display_color_screen(u32 color); - -/*! Init display in full 1280x720 resolution (32bpp, line stride 768, framebuffer size = 1280*768*4 bytes). */ -u32 *display_init_framebuffer(void *address); - -/*! Enable or disable the backlight. Should only be called when the screen is completely set up, to avoid flickering. */ -void display_enable_backlight(bool on); - -void cluster_enable_cpu0(u64 entry, u32 ns_disable); - -void mc_enable_ahb_redirect(); #endif diff --git a/fusee/fusee-primary/src/hwinit/btn.c b/fusee/fusee-primary/src/hwinit/btn.c deleted file mode 100644 index 50bf1b37d..000000000 --- a/fusee/fusee-primary/src/hwinit/btn.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "btn.h" -#include "i2c.h" -#include "t210.h" - -u32 btn_read() -{ - u32 res = 0; - if(!(GPIO_6(0x3C) & 0x80)) - res |= BTN_VOL_DOWN; - if(!(GPIO_6(0x3C) & 0x40)) - res |= BTN_VOL_UP; - if(i2c_recv_byte(4, 0x3C, 0x15) & 0x4) - res |= BTN_POWER; - return res; -} - -u32 btn_wait() -{ - u32 res = 0, btn = btn_read(); - do - { - res = btn_read(); - } while (btn == res); - return res; -} diff --git a/fusee/fusee-primary/src/hwinit/btn.h b/fusee/fusee-primary/src/hwinit/btn.h deleted file mode 100644 index 7ae7af9e7..000000000 --- a/fusee/fusee-primary/src/hwinit/btn.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _BTN_H_ -#define _BTN_H_ - -#include "types.h" - -#define BTN_POWER 0x1 -#define BTN_VOL_DOWN 0x2 -#define BTN_VOL_UP 0x4 - -u32 btn_read(); -u32 btn_wait(); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/clock.c b/fusee/fusee-primary/src/hwinit/clock.c deleted file mode 100644 index b0b4ab93b..000000000 --- a/fusee/fusee-primary/src/hwinit/clock.c +++ /dev/null @@ -1,145 +0,0 @@ -#include "clock.h" -#include "t210.h" -#include "util.h" - -static const clock_t _clock_uart[] = { - /* UART A */ { 4, 0x10, 0x178, 6, 0, 0 }, - /* UART B */ { 4, 0x10, 0x17C, 7, 0, 0 }, - /* UART C */ { 8, 0x14, 0x1A0, 0x17, 0, 0 }, - /* UART D */ { 0 }, - /* UART E */ { 0 } -}; - -static const clock_t _clock_i2c[] = { - /* I2C1 */ { 4, 0x10, 0x124, 0xC, 6, 0 }, - /* I2C2 */ { 0 }, - /* I2C3 */ { 0 }, - /* I2C4 */ { 0 }, - /* I2C5 */ { 8, 0x14, 0x128, 0xF, 6, 0 }, - /* I2C6 */ { 0 } -}; - -static clock_t _clock_se = { 0x358, 0x360, 0x42C, 0x1F, 0, 0 }; - -static clock_t _clock_host1x = { 4, 0x10, 0x180, 0x1C, 4, 3 }; -static clock_t _clock_tsec = { 0xC, 0x18, 0x1F4, 0x13, 0, 2 }; -static clock_t _clock_sor_safe = { 0x2A4, 0x298, 0, 0x1E, 0, 0 }; -static clock_t _clock_sor0 = { 0x28C, 0x280, 0, 0x16, 0, 0 }; -static clock_t _clock_sor1 = { 0x28C, 0x280, 0x410, 0x17, 0, 2 }; -static clock_t _clock_kfuse = { 8, 0x14, 0, 8, 0, 0 }; - -static clock_t _clock_coresight = { 0xC, 0x18, 0x1D4, 9, 0, 4}; - -void clock_enable(const clock_t *clk) -{ - //Put clock into reset. - CLOCK(clk->reset) = CLOCK(clk->reset) & ~(1 << clk->index) | (1 << clk->index); - //Disable. - CLOCK(clk->enable) &= ~(1 << clk->index); - //Configure clock source if required. - if (clk->source) - CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29); - //Enable. - CLOCK(clk->enable) = CLOCK(clk->enable) & ~(1 << clk->index) | (1 << clk->index); - //Take clock off reset. - CLOCK(clk->reset) &= ~(1 << clk->index); -} - -void clock_disable(const clock_t *clk) -{ - //Put clock into reset. - CLOCK(clk->reset) = CLOCK(clk->reset) & ~(1 << clk->index) | (1 << clk->index); - //Disable. - CLOCK(clk->enable) &= ~(1 << clk->index); -} - -void clock_enable_fuse(u32 enable) -{ - CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF | ((enable & 1) << 28) & 0x10000000; -} - -void clock_enable_uart(u32 idx) -{ - clock_enable(&_clock_uart[idx]); -} - -void clock_enable_i2c(u32 idx) -{ - clock_enable(&_clock_i2c[idx]); -} - -void clock_enable_se() -{ - clock_enable(&_clock_se); -} - -void clock_enable_host1x() -{ - clock_enable(&_clock_host1x); -} - -void clock_enable_tsec() -{ - clock_enable(&_clock_tsec); -} - -void clock_enable_sor_safe() -{ - clock_enable(&_clock_sor_safe); -} - -void clock_enable_sor0() -{ - clock_enable(&_clock_sor0); -} - -void clock_enable_sor1() -{ - clock_enable(&_clock_sor1); -} - -void clock_enable_kfuse() -{ - //clock_enable(&_clock_kfuse); - CLOCK(0x8) = CLOCK(0x8) & 0xFFFFFEFF | 0x100; - CLOCK(0x14) &= 0xFFFFFEFF; - CLOCK(0x14) = CLOCK(0x14) & 0xFFFFFEFF | 0x100; - sleep(10); - CLOCK(0x8) &= 0xFFFFFEFF; - sleep(20); -} - -void clock_disable_host1x() -{ - clock_disable(&_clock_host1x); -} - -void clock_disable_tsec() -{ - clock_disable(&_clock_tsec); -} - -void clock_disable_sor_safe() -{ - clock_disable(&_clock_sor_safe); -} - -void clock_disable_sor0() -{ - clock_disable(&_clock_sor0); -} - -void clock_disable_sor1() -{ - clock_disable(&_clock_sor1); -} - -void clock_disable_kfuse() -{ - clock_disable(&_clock_kfuse); -} - -void clock_enable_coresight() -{ - clock_enable(&_clock_coresight); -} diff --git a/fusee/fusee-primary/src/hwinit/clock.h b/fusee/fusee-primary/src/hwinit/clock.h deleted file mode 100644 index 027fd4b26..000000000 --- a/fusee/fusee-primary/src/hwinit/clock.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _CLOCK_H_ -#define _CLOCK_H_ - -#include "types.h" - -/*! Clock registers. */ -#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY 0x28 -#define CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2C -#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 -#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 -#define CLK_RST_CONTROLLER_OSC_CTRL 0x50 -#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19C -#define CLK_RST_CONTROLLER_CLK_ENB_X_SET 0x284 -#define CLK_RST_CONTROLLER_RST_DEV_H_SET 0x308 -#define CLK_RST_CONTROLLER_CLK_ENB_H_SET 0x328 -#define CLK_RST_CONTROLLER_RST_DEVICES_V 0x358 -#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR 0x454 -#define CLK_RST_CONTROLLER_SPARE_REG0 0x55C -#define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8 - -typedef struct _clock_t -{ - u32 reset; - u32 enable; - u32 source; - u8 index; - u8 clk_src; - u8 clk_div; -} clock_t; - -void clock_enable(const clock_t *clk); -void clock_disable(const clock_t *clk); -void clock_enable_fuse(u32 enable); -void clock_enable_uart(u32 idx); -void clock_enable_i2c(u32 idx); -void clock_enable_se(); -void clock_enable_host1x(); -void clock_enable_tsec(); -void clock_enable_sor_safe(); -void clock_enable_sor0(); -void clock_enable_sor1(); -void clock_enable_kfuse(); -void clock_disable_host1x(); -void clock_disable_tsec(); -void clock_disable_sor_safe(); -void clock_disable_sor0(); -void clock_disable_sor1(); -void clock_disable_kfuse(); -void clock_enable_coresight(); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/cluster.c b/fusee/fusee-primary/src/hwinit/cluster.c deleted file mode 100644 index 90015205f..000000000 --- a/fusee/fusee-primary/src/hwinit/cluster.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "cluster.h" -#include "i2c.h" -#include "clock.h" -#include "util.h" -#include "pmc.h" -#include "t210.h" - -void _cluster_enable_power() -{ - u8 tmp; - - if (i2c_recv_buf_small(&tmp, 1, I2C_5, 0x3C, 0x40)) - { - tmp &= 0xDFu; - i2c_send_byte(I2C_5, 0x3C, 0x40, tmp); - } - i2c_send_byte(I2C_5, 0x3C, 0x3B, 0x09); - - //Enable cores power. - i2c_send_byte(I2C_5, 0x1B, 0x02, 0x20); - i2c_send_byte(I2C_5, 0x1B, 0x03, 0x8D); - i2c_send_byte(I2C_5, 0x1B, 0x00, 0xB7); - i2c_send_byte(I2C_5, 0x1B, 0x01, 0xB7); -} - -int _cluster_pmc_enable_partition(u32 part, u32 toggle) -{ - //Check if the partition has already been turned on. - if (PMC(APBDEV_PMC_PWRGATE_STATUS) & part) - return 0; - - u32 i = 5001; - while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100) - { - sleep(1); - i--; - if (i < 1) - return 0; - } - - PMC(APBDEV_PMC_PWRGATE_TOGGLE) = toggle | 0x100; - - i = 5001; - while (i > 0) - { - if (PMC(APBDEV_PMC_PWRGATE_STATUS) & part) - break; - sleep(1); - i--; - } - - return 1; -} - -void cluster_enable_cpu0(u64 entry, u32 ns_disable) -{ - //Set ACTIVE_CLUSER to FAST. - FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE; - - _cluster_enable_power(); - - if (!(CLOCK(0xE0) & 0x40000000)) - { - CLOCK(0x518) &= 0xFFFFFFF7; - sleep(2); - CLOCK(0xE4) = CLOCK(0xE4) & 0xFFFBFFFF | 0x40000; - CLOCK(0xE0) = 0x40404E02; - } - while (!(CLOCK(0xE0) & 0x8000000)) - ; - - CLOCK(0x3B4) = CLOCK(0x3B4) & 0x1FFFFF00 | 6; - CLOCK(0x360) = CLOCK(0x360) & 0xFFFFFFF7 | 8; - CLOCK(0x20) = 0x20008888; - CLOCK(0x24) = 0x80000000; - CLOCK(0x440) = 1; - - clock_enable_coresight(); - - CLOCK(0x388) = CLOCK(0x388) & 0xFFFFE000; - - //Enable CPU rail. - _cluster_pmc_enable_partition(1, 0); - //Enable cluster 0 non-CPU. - _cluster_pmc_enable_partition(0x8000, 15); - //Enable CE0. - _cluster_pmc_enable_partition(0x4000, 14); - - //Request and wait for RAM repair. - FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; - while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & 2)) - ; - - EXCP_VEC(0x100) = 0; - - if(ns_disable) - { - //Set reset vectors. - SB(SB_AA64_RESET_LOW) = (u32)entry | 1; - SB(SB_AA64_RESET_HIGH) = (u32)(entry >> 32); - //Non-secure reset vector write disable. - SB(SB_CSR_0) = 2; - } - else - { - //Set reset vectors. - SB(SB_AA64_RESET_LOW) = (u32)entry; - SB(SB_AA64_RESET_HIGH) = (u32)(entry >> 32); - } - - //Until here the CPU was in reset, this kicks execution. - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= 0xFFFFFFF7; - CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x411F000F; -} diff --git a/fusee/fusee-primary/src/hwinit/cluster.h b/fusee/fusee-primary/src/hwinit/cluster.h deleted file mode 100644 index 41ae68f52..000000000 --- a/fusee/fusee-primary/src/hwinit/cluster.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _CLUSTER_H_ -#define _CLUSTER_H_ - -#include "types.h" - -/*! Flow controller registers. */ -#define FLOW_CTLR_RAM_REPAIR 0x40 -#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98 - -void cluster_enable_cpu0(u64 entry, u32 ns_disable); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/di.c b/fusee/fusee-primary/src/hwinit/di.c deleted file mode 100644 index a168f8dc4..000000000 --- a/fusee/fusee-primary/src/hwinit/di.c +++ /dev/null @@ -1,209 +0,0 @@ -#include "di.h" -#include "t210.h" -#include "util.h" -#include "i2c.h" -#include "pmc.h" - -#include "di.inl" - -static u32 _display_ver = 0; - -static void _display_dsi_wait(u32 timeout, u32 off, u32 mask) -{ - u32 end = TMR(0x10) + timeout; - while (TMR(0x10) < end && DSI(off) & mask) - ; - sleep(5); -} - -void display_init() -{ - //Power on. - i2c_send_byte(I2C_5, 0x3C, 0x23, 0xD0); - i2c_send_byte(I2C_5, 0x3C, 0x3D, 0x09); - - //Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. - CLOCK(0x30C) = 0x1010000; - CLOCK(0x328) = 0x1010000; - CLOCK(0x304) = 0x18000000; - CLOCK(0x320) = 0x18000000; - CLOCK(0x284) = 0x20000; - CLOCK(0x66C) = 0xA; - CLOCK(0x448) = 0x80000; - CLOCK(0x620) = 0xA; - - //DPD idle. - PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000; - PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000; - - //Config pins. - PINMUX_AUX(0x1D0) &= 0xFFFFFFEF; - PINMUX_AUX(0x1D4) &= 0xFFFFFFEF; - PINMUX_AUX(0x1FC) &= 0xFFFFFFEF; - PINMUX_AUX(0x200) &= 0xFFFFFFEF; - PINMUX_AUX(0x204) &= 0xFFFFFFEF; - - GPIO_3(0x00) = GPIO_3(0x00) & 0xFFFFFFFC | 0x3; - GPIO_3(0x10) = GPIO_3(0x10) & 0xFFFFFFFC | 0x3; - GPIO_3(0x20) = GPIO_3(0x20) & 0xFFFFFFFE | 0x1; - - sleep(10000u); - - GPIO_3(0x20) = GPIO_3(0x20) & 0xFFFFFFFD | 0x2; - - sleep(10000); - - GPIO_6(0x04) = GPIO_6(0x04) & 0xFFFFFFF8 | 0x7; - GPIO_6(0x14) = GPIO_6(0x14) & 0xFFFFFFF8 | 0x7; - GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFD | 0x2; - - //Config display interface and display. - MIPI_CAL(0x60) = 0; - - exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4); - exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94); - exec_cfg((u32 *)DSI_BASE, _display_config_3, 60); - - sleep(10000); - - GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFB | 0x4; - - sleep(60000); - - DSI(_DSIREG(DSI_DSI_BTA_TIMING)) = 0x50204; - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x337; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; - _display_dsi_wait(250000, _DSIREG(DSI_DSI_TRIGGER), 3); - - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x406; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; - _display_dsi_wait(250000, _DSIREG(DSI_DSI_TRIGGER), 3); - - DSI(_DSIREG(DSI_HOST_DSI_CONTROL)) = 0x200B; - _display_dsi_wait(150000, _DSIREG(DSI_HOST_DSI_CONTROL), 8); - - sleep(5000); - - _display_ver = DSI(_DSIREG(DSI_DSI_RD_DATA)); - if (_display_ver == 0x10) - exec_cfg((u32 *)DSI_BASE, _display_config_4, 43); - - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x1105; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; - - sleep(180000); - - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x2905; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; - - sleep(20000); - - exec_cfg((u32 *)DSI_BASE, _display_config_5, 21); - exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3); - DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; - exec_cfg((u32 *)DSI_BASE, _display_config_7, 10); - - sleep(10000); - - exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6); - exec_cfg((u32 *)DSI_BASE, _display_config_9, 4); - exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16); - - sleep(10000); - - exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113); -} - -void display_end() -{ - GPIO_6(0x24) &= 0xFFFFFFFE; - DSI(_DSIREG(DSI_DSI_VID_MODE_CONTROL)) = 1; - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x2805; - - u32 end = HOST1X(0x30A4) + 5; - while (HOST1X(0x30A4) < end) - ; - - DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = 5; - DSI(_DSIREG(DSI_DSI_VID_MODE_CONTROL)) = 0; - - exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17); - exec_cfg((u32 *)DSI_BASE, _display_config_13, 16); - - sleep(10000); - - if (_display_ver == 0x10) - exec_cfg((u32 *)DSI_BASE, _display_config_14, 22); - - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x1005; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 2; - - sleep(50000); - - GPIO_6(0x24) &= 0xFFFFFFFB; - - sleep(10000); - - GPIO_3(0x20) &= 0xFFFFFFFD; - - sleep(10000); - - GPIO_3(0x20) = (GPIO_3(0x20) >> 1) << 1; - - sleep(10000); - - //Disable clocks. - CLOCK(0x308) = 0x1010000; - CLOCK(0x32C) = 0x1010000; - CLOCK(0x300) = 0x18000000; - CLOCK(0x324) = 0x18000000; - - DSI(_DSIREG(DSI_PAD_CONTROL)) = 0x10F010F; - DSI(_DSIREG(DSI_DSI_POWER_CONTROL)) = 0; - - GPIO_6(0x04) &= 0xFFFFFFFE; - - PINMUX_AUX(0x1FC) = PINMUX_AUX(0x1FC) & 0xFFFFFFEF | 0x10; - PINMUX_AUX(0x1FC) = (PINMUX_AUX(0x1FC) >> 2) << 2 | 1; -} - -void display_color_screen(u32 color) -{ - exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8); - - //Configure display to show single color. - DISPLAY_A(_DIREG(DC_WIN_AD_WIN_OPTIONS)) = 0; - DISPLAY_A(_DIREG(DC_WIN_BD_WIN_OPTIONS)) = 0; - DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0; - DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color; - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE | 1; - - sleep(35000); - - GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFE | 1; -} - -void display_enable_backlight(bool on) { - GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFE | !!on; -} - - -u32 *display_init_framebuffer(void *address) -{ - static cfg_op_t conf[sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t)] = {0}; - if(conf[0].val == 0) { - for (u32 i = 0; i < sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t); i++) { - conf[i] = cfg_display_framebuffer[i]; - } - } - - u32 *lfb_addr = (u32 *)address; - - conf[19].val = (u32)address; - //This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). - exec_cfg((u32 *)DISPLAY_A_BASE, conf, 32); - - sleep(35000); - - return lfb_addr; -} diff --git a/fusee/fusee-primary/src/hwinit/di.h b/fusee/fusee-primary/src/hwinit/di.h deleted file mode 100644 index 9d482e072..000000000 --- a/fusee/fusee-primary/src/hwinit/di.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _DI_H_ -#define _DI_H_ - -#include "types.h" -#include <stdbool.h> - -/*! Display registers. */ -#define _DIREG(reg) ((reg) * 4) -#define DC_CMD_DISPLAY_COMMAND 0x32 -#define DC_CMD_STATE_ACCESS 0x40 -#define DC_CMD_STATE_CONTROL 0x41 -#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 -#define DC_DISP_DISP_WIN_OPTIONS 0x402 -#define DC_DISP_DISP_CLOCK_CONTROL 0x42E -#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 -#define DC_WIN_AD_WIN_OPTIONS 0xB80 -#define DC_WIN_BD_WIN_OPTIONS 0xD80 -#define DC_WIN_CD_WIN_OPTIONS 0xF80 - -//The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). -#define DC_X_WIN_XD_WIN_OPTIONS 0x700 -#define DC_X_WIN_XD_COLOR_DEPTH 0x703 -#define DC_X_WIN_XD_POSITION 0x704 -#define DC_X_WIN_XD_SIZE 0x705 -#define DC_X_WIN_XD_PRESCALED_SIZE 0x706 -#define DC_X_WIN_XD_H_INITIAL_DDA 0x707 -#define DC_X_WIN_XD_V_INITIAL_DDA 0x708 -#define DC_X_WIN_XD_DDA_INCREMENT 0x709 -#define DC_X_WIN_XD_LINE_STRIDE 0x70A - -//The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). -#define DC_X_WINBUF_XD_START_ADDR 0x800 -#define DC_X_WINBUF_XD_ADDR_H_OFFSET 0x806 -#define DC_X_WINBUF_XD_ADDR_V_OFFSET 0x808 -#define DC_X_WINBUF_XD_SURFACE_KIND 0x80B - -/*! Display serial interface registers. */ -#define _DSIREG(reg) ((reg) * 4) -#define DSI_DSI_RD_DATA 0x9 -#define DSI_DSI_WR_DATA 0xA -#define DSI_DSI_POWER_CONTROL 0xB -#define DSI_HOST_DSI_CONTROL 0xF -#define DSI_DSI_TRIGGER 0x13 -#define DSI_DSI_BTA_TIMING 0x3F -#define DSI_PAD_CONTROL 0x4B -#define DSI_DSI_VID_MODE_CONTROL 0x4E - -void display_init(); -void display_end(); - -/*! Show one single color on the display. */ -void display_color_screen(u32 color); - -/*! Init display in full 1280x720 resolution (32bpp, line stride 768, framebuffer size = 1280*768*4 bytes). */ -u32 *display_init_framebuffer(void *address); - -/*! Enable or disable the backlight. Should only be called when the screen is completely set up, to avoid flickering. */ -void display_enable_backlight(bool on); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/di.inl b/fusee/fusee-primary/src/hwinit/di.inl deleted file mode 100644 index b2e6d1533..000000000 --- a/fusee/fusee-primary/src/hwinit/di.inl +++ /dev/null @@ -1,532 +0,0 @@ -//Clock config. -static const cfg_op_t _display_config_1[4] = { - {0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 - {0x34, 0x4830A001}, //CLK_RST_CONTROLLER_PLLD_BASE - {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 - {0x37, 0x2D0AAA} //CLK_RST_CONTROLLER_PLLD_MISC -}; - -//Display A config. -static const cfg_op_t _display_config_2[94] = { - {0x40, 0}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x43, 0x54}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x42, 0x10}, - {0x42, 0x20}, - {0x42, 0x40}, - {0x480, 0}, - {0x403, 0}, - {0x404, 0}, - {0x36, 0x50155}, - {1, 0x100}, - {0x28, 0x109}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF}, - {0x40, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x10}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x10}, - {0x42, 0x10}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x20}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x20}, - {0x42, 0x20}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x42, 0x40}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x40}, - {0x42, 0x40}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x430, 8}, - {0x42F, 0}, - {0x307, 0x1000000}, - {0x309, 0}, - {0x4E4, 0}, - {0x300, 0}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF}, - {0x42, 0x10}, - {0x716, 0x10000FF}, - {0x42, 0x20}, - {0x716, 0x10000FF}, - {0x42, 0x40}, - {0x716, 0x10000FF}, - {0x31, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x402, 0}, - {0x32, 0}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF} -}; - -//DSI config. -static const cfg_op_t _display_config_3[60] = { - {0xA, 0}, - {0xC, 0}, - {0xD, 0}, - {0xE, 0}, - {0x1B, 0}, - {0x1C, 0}, - {0x1D, 0}, - {0x1E, 0}, - {0x33, 0}, - {0x23, 0}, - {0x25, 0}, - {0x27, 0}, - {0x29, 0}, - {0x2B, 0}, - {0x2D, 0}, - {0x24, 0}, - {0x26, 0}, - {0x28, 0}, - {0x2A, 0}, - {0x2C, 0}, - {0x2E, 0}, - {0x10, 0}, - {0x4C, 0}, - {0x11, 0x18}, - {0x12, 0x1E0}, - {0x13, 0}, - {0x1A, 0}, - {0x34, 0}, - {0x35, 0}, - {0x36, 0}, - {0x37, 0}, - {0x4F, 0}, - {0x3C, 0x6070601}, - {0x3D, 0x40A0E05}, - {0x3E, 0x30109}, - {0x3F, 0x190A14}, - {0x44, 0x2000FFFF}, - {0x45, 0x7652000}, - {0x46, 0}, - {0x4B, 0}, - {DSI_DSI_POWER_CONTROL, 1}, - {DSI_DSI_POWER_CONTROL, 1}, - {DSI_DSI_POWER_CONTROL, 0}, - {DSI_DSI_POWER_CONTROL, 0}, - {0x4F, 0}, - {0x3C, 0x6070601}, - {0x3D, 0x40A0E05}, - {0x3E, 0x30118}, - {0x3F, 0x190A14}, - {0x44, 0x2000FFFF}, - {0x45, 0x13432000}, - {0x46, 0}, - {0xF, 0x102003}, - {0x10, 0x31}, - {DSI_DSI_POWER_CONTROL, 1}, - {DSI_DSI_POWER_CONTROL, 1}, - {0x12, 0x40}, - {0x13, 0}, - {0x14, 0}, - {0x1A, 0} -}; - -//DSI config (if ver == 0x10). -static const cfg_op_t _display_config_4[43] = { - {DSI_DSI_WR_DATA, 0x439}, - {DSI_DSI_WR_DATA, 0x9483FFB9}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0xBD15}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x1939}, - {DSI_DSI_WR_DATA, 0xAAAAAAD8}, - {DSI_DSI_WR_DATA, 0xAAAAAAEB}, - {DSI_DSI_WR_DATA, 0xAAEBAAAA}, - {DSI_DSI_WR_DATA, 0xAAAAAAAA}, - {DSI_DSI_WR_DATA, 0xAAAAAAEB}, - {DSI_DSI_WR_DATA, 0xAAEBAAAA}, - {DSI_DSI_WR_DATA, 0xAA}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x1BD15}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x2739}, - {DSI_DSI_WR_DATA, 0xFFFFFFD8}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFF}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x2BD15}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0xF39}, - {DSI_DSI_WR_DATA, 0xFFFFFFD8}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFF}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0xBD15}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x6D915}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x439}, - {DSI_DSI_WR_DATA, 0xB9}, - {DSI_DSI_TRIGGER, 2} -}; - -//DSI config. -static const cfg_op_t _display_config_5[21] = { - {0x4F, 0}, - {0x3C, 0x6070601}, - {0x3D, 0x40A0E05}, - {0x3E, 0x30172}, - {0x3F, 0x190A14}, - {0x44, 0x20000A40}, - {0x45, 0x5A2F2000}, - {0x46, 0}, - {0x23, 0x40000208}, - {0x27, 0x40000308}, - {0x2B, 0x40000308}, - {0x25, 0x40000308}, - {0x29, 0x3F3B2B08}, - {0x2A, 0x2CC}, - {0x2D, 0x3F3B2B08}, - {0x2E, 0x2CC}, - {0x34, 0xCE0000}, - {0x35, 0x87001A2}, - {0x36, 0x190}, - {0x37, 0x190}, - {0xF, 0}, -}; - -//Clock config. -static const cfg_op_t _display_config_6[3] = { - {0x34, 0x4810C001}, //CLK_RST_CONTROLLER_PLLD_BASE - {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 - {0x37, 0x2DFC00} //CLK_RST_CONTROLLER_PLLD_MISC -}; - -//DSI config. -static const cfg_op_t _display_config_7[10] = { - {0x13, 0}, - {0x10, 0}, - {0x11, 6}, - {0x12, 0x1E0}, - {DSI_DSI_POWER_CONTROL, 1}, - {0x10, 0x103032}, - {0xF, 0x33}, - {0x10, 0x103032}, - {0xF, 3}, - {0xF, 0x23} -}; - -//MIPI CAL config. -static const cfg_op_t _display_config_8[6] = { - {0x18, 0}, - {2, 0xF3F10000}, - {0x16, 1}, - {0x18, 0}, - {0x18, 0x10010}, - {0x17, 0x300} -}; - -//DSI config. -static const cfg_op_t _display_config_9[4] = { - {0x4F, 0}, - {0x50, 0}, - {0x51, 0x3333}, - {0x52, 0} -}; - -//MIPI CAL config. -static const cfg_op_t _display_config_10[16] = { - {0xE, 0x200200}, - {0xF, 0x200200}, - {0x19, 0x200002}, - {0x1A, 0x200002}, - {5, 0}, - {6, 0}, - {7, 0}, - {8, 0}, - {9, 0}, - {0xA, 0}, - {0x10, 0}, - {0x11, 0}, - {0x1A, 0}, - {0x1C, 0}, - {0x1D, 0}, - {0, 0x2A000001} -}; - -//Display A config. -static const cfg_op_t _display_config_11[113] = { - {0x40, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x10}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x10}, - {0x42, 0x10}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x20}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x20}, - {0x42, 0x20}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x42, 0x40}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x40}, - {0x42, 0x40}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x430, 8}, - {0x42F, 0}, - {0x307, 0x1000000}, - {0x309, 0}, - {0x4E4, 0}, - {0x300, 0}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF}, - {0x42, 0x10}, - {0x716, 0x10000FF}, - {0x42, 0x20}, - {0x716, 0x10000FF}, - {0x42, 0x40}, - {0x716, 0x10000FF}, - {0x31, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x402, 0}, - {0x32, 0}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF}, - {0x40, 0}, - {0x405, 0}, - {0x406, 0x10000}, - {0x407, 0x10048}, - {0x408, 0x90048}, - {0x409, 0x50002D0}, - {0x40A, 0xA0088}, - {0x431, 0x10001}, - {0x303, 0}, - {0x432, 5}, - {0x42F, 0}, - {0x42E, 0}, - {0x31, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x402, 0}, - {0x32, 0x20}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x40, 5}, - {0x40A, 0xA0088}, - {0x40, 0}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0, 0x301}, - {0, 0x301}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x40, 0}, - {0x42E, 4}, - {0x430, 8}, - {0x31, 0} -}; - -////Display A config. -static const cfg_op_t _display_config_12[17] = { - {0x40A, 0xA0088}, - {0x38, 0}, - {0x40, 0}, - {0x39, 0}, - {0x28, 0}, - {0x32, 0}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0, 0x301}, - {0, 0x301}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x36, 0}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1} -}; - -//DSI config. -static const cfg_op_t _display_config_13[16] = { - {DSI_DSI_POWER_CONTROL, 0}, - {0x4F, 0}, - {0x3C, 0x6070601}, - {0x3D, 0x40A0E05}, - {0x3E, 0x30109}, - {0x3F, 0x190A14}, - {0x44, 0x2000FFFF}, - {0x45, 0x7652000}, - {0x46, 0}, - {0xF, 0x102003}, - {0x10, 0x31}, - {DSI_DSI_POWER_CONTROL, 1}, - {0x12, 0x40}, - {0x13, 0}, - {0x14, 0}, - {0x1A, 0} -}; - -//DSI config (if ver == 0x10). -static const cfg_op_t _display_config_14[22] = { - {DSI_DSI_WR_DATA, 0x439}, - {DSI_DSI_WR_DATA, 0x9483FFB9}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x2139}, - {DSI_DSI_WR_DATA, 0x191919D5}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0xB39}, - {DSI_DSI_WR_DATA, 0x4F0F41B1}, - {DSI_DSI_WR_DATA, 0xF179A433}, - {DSI_DSI_WR_DATA, 0x2D81}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x439}, - {DSI_DSI_WR_DATA, 0xB9}, - {DSI_DSI_TRIGGER, 2} -}; - -//Display A config. -static const cfg_op_t cfg_display_one_color[8] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x10}, //Enable window A. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x20}, //Enable window B. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x40}, //Enable window C. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_CMD_DISPLAY_COMMAND, 0x20} //DISPLAY_CTRL_MODE: continuous display. -}; - -//Display A config. -static const cfg_op_t cfg_display_framebuffer[32] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x40}, //Enable window C. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x20}, //Enable window B. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x10}, //Enable window A. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_X_WIN_XD_COLOR_DEPTH, 0xD}, //T_A8B8G8R8 - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_X_WIN_XD_POSITION, 0}, //(0,0) - {DC_X_WIN_XD_H_INITIAL_DDA, 0}, - {DC_X_WIN_XD_V_INITIAL_DDA, 0}, - {DC_X_WIN_XD_PRESCALED_SIZE, 0x5000B40}, //Pre-scaled size: 1280x2880 bytes (= 0x500 vertical lines x 0xB40 bytes). - {DC_X_WIN_XD_DDA_INCREMENT, 0x10001000}, - {DC_X_WIN_XD_SIZE, 0x50002D0}, //Window size: 1280x720 (= 0x500 vertical lines x 0x2D0 horizontal pixels). - {DC_X_WIN_XD_LINE_STRIDE, 0x6000C00}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. - {0x702, 0}, - {DC_X_WINBUF_XD_SURFACE_KIND, 0}, //Regular surface. - {DC_X_WINBUF_XD_START_ADDR, 0xC0000000}, //Framebuffer address. - {DC_X_WINBUF_XD_ADDR_H_OFFSET, 0}, - {DC_X_WINBUF_XD_ADDR_V_OFFSET, 0}, - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_X_WIN_XD_WIN_OPTIONS, 0x40000000}, //Enable window AD. - {DC_CMD_DISPLAY_COMMAND, 0x20}, //DISPLAY_CTRL_MODE: continuous display. - {DC_CMD_STATE_CONTROL, 0x300}, //General update; window A update. - {DC_CMD_STATE_CONTROL, 3} //General activation request; window A activation request. -}; diff --git a/fusee/fusee-primary/src/hwinit/fuse.h b/fusee/fusee-primary/src/hwinit/fuse.h deleted file mode 100644 index 1f19f466f..000000000 --- a/fusee/fusee-primary/src/hwinit/fuse.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _FUSE_H_ -#define _FUSE_H_ - -#include "types.h" - -/*! Fuse registers. */ -#define FUSE_CTRL 0x0 -#define FUSE_ADDR 0x4 -#define FUSE_RDATA 0x8 -#define FUSE_WDATA 0xC -#define FUSE_TIME_RD1 0x10 -#define FUSE_TIME_RD2 0x14 -#define FUSE_TIME_PGM1 0x18 -#define FUSE_TIME_PGM2 0x1C -#define FUSE_PRIV2INTFC 0x20 -#define FUSE_FUSEBYPASS 0x24 -#define FUSE_PRIVATEKEYDISABLE 0x28 -#define FUSE_DISABLEREGPROGRAM 0x2C -#define FUSE_WRITE_ACCESS_SW 0x30 -#define FUSE_PWR_GOOD_SW 0x34 - -/*! Fuse cache registers. */ -#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) - -void fuse_disable_program(); -u32 fuse_read_odm(u32 idx); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/hwinit.c b/fusee/fusee-primary/src/hwinit/hwinit.c deleted file mode 100644 index 467efdee5..000000000 --- a/fusee/fusee-primary/src/hwinit/hwinit.c +++ /dev/null @@ -1,280 +0,0 @@ -#include "clock.h" -#include "uart.h" -#include "i2c.h" -#include "sdram.h" -#include "di.h" -#include "mc.h" -#include "t210.h" -#include "pmc.h" -#include "pinmux.h" -#include "fuse.h" -#include "util.h" - -void config_oscillators() -{ - CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3 | 4; - SYSCTR0(SYSCTR0_CNTFID0) = 19200000; - TMR(0x14) = 0x45F; - CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; - PMC(APBDEV_PMC_OSC_EDPD_OVER) = PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81 | 0xE; - PMC(APBDEV_PMC_OSC_EDPD_OVER) = PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF | 0x400000; - PMC(APBDEV_PMC_CNTRL2) = PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF | 0x1000; - PMC(APBDEV_PMC_SCRATCH188) = PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF | 0x2000000; - CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; - PMC(APBDEV_PMC_TSC_MULT) = PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000 | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz) - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; - CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; - CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; -} - -void config_gpios() -{ - PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0; - PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0; - - PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = 0x40; - PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = 0x40; - - GPIO_2(0x8) = GPIO_2(0x8) & 0xFFFFFFFE | 1; - GPIO_1(0xC) = GPIO_1(0xC) & 0xFFFFFFFD | 2; - GPIO_2(0x0) = GPIO_2(0x0) & 0xFFFFFFBF | 0x40; - GPIO_2(0xC) = GPIO_2(0xC) & 0xFFFFFFBF | 0x40; - GPIO_2(0x18) &= 0xFFFFFFFE; - GPIO_1(0x1C) &= 0xFFFFFFFD; - GPIO_2(0x10) &= 0xFFFFFFBF; - GPIO_2(0x1C) &= 0xFFFFFFBF; - - pinmux_config_i2c(I2C_1); - pinmux_config_i2c(I2C_5); - pinmux_config_uart(UART_A); - - GPIO_6(0xC) = GPIO_6(0xC) & 0xFFFFFFBF | 0x40; - GPIO_6(0xC) = GPIO_6(0xC) & 0xFFFFFF7F | 0x80; - GPIO_6(0x1C) &= 0xFFFFFFBF; - GPIO_6(0x1C) &= 0xFFFFFF7F; -} - -void config_pmc_scratch() -{ - PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; - PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; - PMC(APBDEV_PMC_SECURE_SCRATCH21) |= 0x10; -} - -void mc_config_tsec_carveout(u32 bom, u32 size1mb, int lock) -{ - MC(0x670) = 0x90000000; - MC(0x674) = 1; - if (lock) - MC(0x678) = 1; -} - -void mc_config_carveout() -{ - *(vu32 *)0x8005FFFC = 0xC0EDBBCC; - MC(0x984) = 1; - MC(0x988) = 0; - MC(0x648) = 0; - MC(0x64C) = 0; - MC(0x650) = 1; - - //Official code disables and locks the carveout here. - //mc_config_tsec_carveout(0, 0, 1); - - MC(0x9A0) = 0; - MC(0x9A4) = 0; - MC(0x9A8) = 0; - MC(0x9AC) = 1; - MC(0xC0C) = 0; - MC(0xC10) = 0; - MC(0xC14) = 0; - MC(0xC18) = 0; - MC(0xC1C) = 0; - MC(0xC20) = 0; - MC(0xC24) = 0; - MC(0xC28) = 0; - MC(0xC2C) = 0; - MC(0xC30) = 0; - MC(0xC34) = 0; - MC(0xC38) = 0; - MC(0xC3C) = 0; - MC(0xC08) = 0x4000006; - MC(0xC5C) = 0x80020000; - MC(0xC60) = 0; - MC(0xC64) = 2; - MC(0xC68) = 0; - MC(0xC6C) = 0; - MC(0xC70) = 0x3000000; - MC(0xC74) = 0; - MC(0xC78) = 0x300; - MC(0xC7C) = 0; - MC(0xC80) = 0; - MC(0xC84) = 0; - MC(0xC88) = 0; - MC(0xC8C) = 0; - MC(0xC58) = 0x440167E; - MC(0xCAC) = 0; - MC(0xCB0) = 0; - MC(0xCB4) = 0; - MC(0xCB8) = 0; - MC(0xCBC) = 0; - MC(0xCC0) = 0x3000000; - MC(0xCC4) = 0; - MC(0xCC8) = 0x300; - MC(0xCCC) = 0; - MC(0xCD0) = 0; - MC(0xCD4) = 0; - MC(0xCD8) = 0; - MC(0xCDC) = 0; - MC(0xCA8) = 0x4401E7E; - MC(0xCFC) = 0; - MC(0xD00) = 0; - MC(0xD04) = 0; - MC(0xD08) = 0; - MC(0xD0C) = 0; - MC(0xD10) = 0; - MC(0xD14) = 0; - MC(0xD18) = 0; - MC(0xD1C) = 0; - MC(0xD20) = 0; - MC(0xD24) = 0; - MC(0xD28) = 0; - MC(0xD2C) = 0; - MC(0xCF8) = 0x8F; - MC(0xD4C) = 0; - MC(0xD50) = 0; - MC(0xD54) = 0; - MC(0xD58) = 0; - MC(0xD5C) = 0; - MC(0xD60) = 0; - MC(0xD64) = 0; - MC(0xD68) = 0; - MC(0xD6C) = 0; - MC(0xD70) = 0; - MC(0xD74) = 0; - MC(0xD78) = 0; - MC(0xD7C) = 0; - MC(0xD48) = 0x8F; -} - -void enable_clocks() -{ - CLOCK(0x410) = (CLOCK(0x410) | 0x8000) & 0xFFFFBFFF; - CLOCK(0xD0) |= 0x40800000u; - CLOCK(0x2AC) = 64; - CLOCK(0x294) = 0x40000; - CLOCK(0x304) = 0x18000000; - sleep(2); - - I2S(0x0A0) |= 0x400; - I2S(0x088) &= 0xFFFFFFFE; - I2S(0x1A0) |= 0x400; - I2S(0x188) &= 0xFFFFFFFE; - I2S(0x2A0) |= 0x400; - I2S(0x288) &= 0xFFFFFFFE; - I2S(0x3A0) |= 0x400; - I2S(0x388) &= 0xFFFFFFFE; - I2S(0x4A0) |= 0x400; - I2S(0x488) &= 0xFFFFFFFE; - DISPLAY_A(0xCF8) |= 4; - VIC(0x8C) = 0xFFFFFFFF; - sleep(2); - - CLOCK(0x2A8) = 0x40; - CLOCK(0x300) = 0x18000000; - CLOCK(0x290) = 0x40000; - CLOCK(0x14) = 0xC0; - CLOCK(0x10) = 0x80000130; - CLOCK(0x18) = 0x1F00200; - CLOCK(0x360) = 0x80400808; - CLOCK(0x364) = 0x402000FC; - CLOCK(0x280) = 0x23000780; - CLOCK(0x298) = 0x300; - CLOCK(0xF8) = 0; - CLOCK(0xFC) = 0; - CLOCK(0x3A0) = 0; - CLOCK(0x3A4) = 0; - CLOCK(0x554) = 0; - CLOCK(0xD0) &= 0x1F7FFFFFu; - CLOCK(0x410) &= 0xFFFF3FFF; - CLOCK(0x148) = CLOCK(0x148) & 0x1FFFFFFF | 0x80000000; - CLOCK(0x180) = CLOCK(0x180) & 0x1FFFFFFF | 0x80000000; - CLOCK(0x6A0) = CLOCK(0x6A0) & 0x1FFFFFFF | 0x80000000; -} - -void mc_enable_ahb_redirect() -{ - CLOCK(0x3A4) = CLOCK(0x3A4) & 0xFFF7FFFF | 0x80000; - //MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE; - MC(MC_IRAM_BOM) = 0x40000000; - MC(MC_IRAM_TOM) = 0x4003F000; -} - -void mc_disable_ahb_redirect() -{ - MC(MC_IRAM_BOM) = 0xFFFFF000; - MC(MC_IRAM_TOM) = 0; - //Disable IRAM_CFG_WRITE_ACCESS (sticky). - //MC(MC_IRAM_REG_CTRL) = MC(MC_IRAM_REG_CTRL) & 0xFFFFFFFE | 1; - CLOCK(0x3A4) &= 0xFFF7FFFF; -} - -void mc_enable() -{ - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF | 0x40000000; - //Enable MIPI CAL clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF | 0x2000000; - //Enable MC clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE | 1; - //Enable EMC DLL clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & 0xFFFFBFFF | 0x4000; - CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x2000001; //Clear EMC and MC reset. - sleep(5); -} - -clock_t clock_unk1 = { 0x358, 0x360, 0x42C, 0x1F, 0, 0 }; -clock_t clock_unk2 = { 0x358, 0x360, 0, 0x1E, 0, 0 }; - -void nx_hwinit() -{ - enable_clocks(); - clock_enable_se(); - clock_enable_fuse(1); - fuse_disable_program(); - - mc_enable(); - - config_oscillators(); - _REG(0x70000000, 0x40) = 0; - - config_gpios(); - - clock_enable_i2c(I2C_1); - clock_enable_i2c(I2C_5); - clock_enable(&clock_unk1); - clock_enable(&clock_unk2); - - i2c_init(I2C_1); - i2c_init(I2C_5); - - //Config PMIC (TODO: use max77620.h) - i2c_send_byte(I2C_5, 0x3C, 4, 0x40); - i2c_send_byte(I2C_5, 0x3C, 0x41, 0x78); - i2c_send_byte(I2C_5, 0x3C, 0x43, 0x38); - i2c_send_byte(I2C_5, 0x3C, 0x44, 0x3A); - i2c_send_byte(I2C_5, 0x3C, 0x45, 0x38); - i2c_send_byte(I2C_5, 0x3C, 0x4A, 0xF); - i2c_send_byte(I2C_5, 0x3C, 0x4E, 0xC7); - i2c_send_byte(I2C_5, 0x3C, 0x4F, 0x4F); - i2c_send_byte(I2C_5, 0x3C, 0x50, 0x29); - i2c_send_byte(I2C_5, 0x3C, 0x52, 0x1B); - i2c_send_byte(I2C_5, 0x3C, 0x16, 42); //42 = (1000 * 1125 - 600000) / 12500 - - config_pmc_scratch(); - - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888 | 0x3333; - - mc_config_carveout(); - - sdram_init(); -} diff --git a/fusee/fusee-primary/src/hwinit/hwinit.h b/fusee/fusee-primary/src/hwinit/hwinit.h deleted file mode 100644 index fda89d4f4..000000000 --- a/fusee/fusee-primary/src/hwinit/hwinit.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _HWINIT_H_ -#define _HWINIT_H_ - -void mc_config_tsec_carveout(u32 bom, u32 size1mb, int lock); -void mc_enable_ahb_redirect(); -void mc_disable_ahb_redirect(); -void nx_hwinit(); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/hwinit_fuse.c b/fusee/fusee-primary/src/hwinit/hwinit_fuse.c deleted file mode 100644 index 80fa85788..000000000 --- a/fusee/fusee-primary/src/hwinit/hwinit_fuse.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "fuse.h" -#include "t210.h" - -void fuse_disable_program() -{ - FUSE(FUSE_DISABLEREGPROGRAM) = 1; -} - -u32 fuse_read_odm(u32 idx) -{ - return FUSE(FUSE_RESERVED_ODMX(idx)); -} diff --git a/fusee/fusee-primary/src/hwinit/i2c.c b/fusee/fusee-primary/src/hwinit/i2c.c deleted file mode 100644 index b44b9ffa5..000000000 --- a/fusee/fusee-primary/src/hwinit/i2c.c +++ /dev/null @@ -1,116 +0,0 @@ -#include <string.h> - -#include "i2c.h" -#include "util.h" - -static u32 i2c_addrs[] = { 0x7000C000, 0x7000C400, 0x7000C500, 0x7000C700, 0x7000D000, 0x7000D100 }; - -static void _i2c_wait(vu32 *base) -{ - base[0x23] = 0x25; - for (u32 i = 0; i < 20; i++) - { - sleep(1); - if (!(base[0x23] & 1)) - break; - } -} - -static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size) -{ - if (size > 4) - return 0; - - u32 tmp = 0; - memcpy(&tmp, buf, size); - - vu32 *base = (vu32 *)i2c_addrs[idx]; - base[1] = x << 1; //Set x (send mode). - base[3] = tmp; //Set value. - base[0] = (2 * size - 2) | 0x2800; //Set size and send mode. - _i2c_wait(base); //Kick transaction. - - base[0] = base[0] & 0xFFFFFDFF | 0x200; - while (base[7] & 0x100) - ; - - if (base[7] << 28) - return 0; - - return 1; -} - -static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x) -{ - if (size > 4) - return 0; - - vu32 *base = (vu32 *)i2c_addrs[idx]; - base[1] = (x << 1) | 1; //Set x (recv mode). - base[0] = (2 * size - 2) | 0x2840; //Set size and recv mode. - _i2c_wait(base); //Kick transaction. - - base[0] = base[0] & 0xFFFFFDFF | 0x200; - while (base[7] & 0x100) - ; - - if (base[7] << 28) - return 0; - - u32 tmp = base[3]; //Get value. - memcpy(buf, &tmp, size); - - return 1; -} - -void i2c_init(u32 idx) -{ - vu32 *base = (vu32 *)i2c_addrs[idx]; - - base[0x1B] = 0x50001; - base[0x21] = 0x90003; - _i2c_wait(base); - - for (u32 i = 0; i < 10; i++) - { - sleep(20000); - if (base[0x1A] & 0x800) - break; - } - - vu32 dummy = base[0x22]; - base[0x1A] = base[0x1A]; -} - -int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size) -{ - u8 tmp[4]; - - if (size > 3) - return 0; - - tmp[0] = y; - memcpy(tmp + 1, buf, size); - - return _i2c_send_pkt(idx, x, tmp, size + 1); -} - -int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y) -{ - int res = _i2c_send_pkt(idx, x, (u8 *)&y, 1); - if (res) - res = _i2c_recv_pkt(idx, buf, size, x); - return res; -} - -void i2c_send_byte(u32 idx, u32 x, u32 y, u8 b) -{ - i2c_send_buf_small(idx, x, y, &b, 1); -} - -u8 i2c_recv_byte(u32 idx, u32 x, u32 y) -{ - u8 tmp; - i2c_recv_buf_small(&tmp, 1, idx, x, y); - return tmp; -} diff --git a/fusee/fusee-primary/src/hwinit/i2c.h b/fusee/fusee-primary/src/hwinit/i2c.h deleted file mode 100644 index 921533d6b..000000000 --- a/fusee/fusee-primary/src/hwinit/i2c.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _I2C_H_ -#define _I2C_H_ - -#include "types.h" - -#define I2C_1 0 -#define I2C_2 1 -#define I2C_3 2 -#define I2C_4 3 -#define I2C_5 4 -#define I2C_6 5 - -void i2c_init(u32 idx); -int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size); -int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y); -void i2c_send_byte(u32 idx, u32 x, u32 y, u8 b); -u8 i2c_recv_byte(u32 idx, u32 x, u32 y); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/max77620.h b/fusee/fusee-primary/src/hwinit/max77620.h deleted file mode 100644 index 7223067dc..000000000 --- a/fusee/fusee-primary/src/hwinit/max77620.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Defining registers address and its bit definitions of MAX77620 and MAX20024 - * - * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - */ - -#ifndef _MFD_MAX77620_H_ -#define _MFD_MAX77620_H_ - -/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ -#define MAX77620_REG_CNFGGLBL1 0x00 -#define MAX77620_REG_CNFGGLBL2 0x01 -#define MAX77620_REG_CNFGGLBL3 0x02 -#define MAX77620_REG_CNFG1_32K 0x03 -#define MAX77620_REG_CNFGBBC 0x04 -#define MAX77620_REG_IRQTOP 0x05 -#define MAX77620_REG_INTLBT 0x06 -#define MAX77620_REG_IRQSD 0x07 -#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 -#define MAX77620_REG_IRQ_LVL2_L8 0x09 -#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A -#define MAX77620_REG_ONOFFIRQ 0x0B -#define MAX77620_REG_NVERC 0x0C -#define MAX77620_REG_IRQTOPM 0x0D -#define MAX77620_REG_INTENLBT 0x0E -#define MAX77620_REG_IRQMASKSD 0x0F -#define MAX77620_REG_IRQ_MSK_L0_7 0x10 -#define MAX77620_REG_IRQ_MSK_L8 0x11 -#define MAX77620_REG_ONOFFIRQM 0x12 -#define MAX77620_REG_STATLBT 0x13 -#define MAX77620_REG_STATSD 0x14 -#define MAX77620_REG_ONOFFSTAT 0x15 - -/* SD and LDO Registers */ -#define MAX77620_REG_SD0 0x16 -#define MAX77620_REG_SD1 0x17 -#define MAX77620_REG_SD2 0x18 -#define MAX77620_REG_SD3 0x19 -#define MAX77620_REG_SD4 0x1A -#define MAX77620_REG_DVSSD0 0x1B -#define MAX77620_REG_DVSSD1 0x1C -#define MAX77620_REG_SD0_CFG 0x1D -#define MAX77620_REG_SD1_CFG 0x1E -#define MAX77620_REG_SD2_CFG 0x1F -#define MAX77620_REG_SD3_CFG 0x20 -#define MAX77620_REG_SD4_CFG 0x21 -#define MAX77620_REG_SD_CFG2 0x22 -#define MAX77620_REG_LDO0_CFG 0x23 -#define MAX77620_REG_LDO0_CFG2 0x24 -#define MAX77620_REG_LDO1_CFG 0x25 -#define MAX77620_REG_LDO1_CFG2 0x26 -#define MAX77620_REG_LDO2_CFG 0x27 -#define MAX77620_REG_LDO2_CFG2 0x28 -#define MAX77620_REG_LDO3_CFG 0x29 -#define MAX77620_REG_LDO3_CFG2 0x2A -#define MAX77620_REG_LDO4_CFG 0x2B -#define MAX77620_REG_LDO4_CFG2 0x2C -#define MAX77620_REG_LDO5_CFG 0x2D -#define MAX77620_REG_LDO5_CFG2 0x2E -#define MAX77620_REG_LDO6_CFG 0x2F -#define MAX77620_REG_LDO6_CFG2 0x30 -#define MAX77620_REG_LDO7_CFG 0x31 -#define MAX77620_REG_LDO7_CFG2 0x32 -#define MAX77620_REG_LDO8_CFG 0x33 -#define MAX77620_REG_LDO8_CFG2 0x34 -#define MAX77620_REG_LDO_CFG3 0x35 - -#define MAX77620_LDO_SLEW_RATE_MASK 0x1 - -/* LDO Configuration 3 */ -#define MAX77620_TRACK4_MASK (1 << 5) -#define MAX77620_TRACK4_SHIFT 5 - -/* Voltage */ -#define MAX77620_SDX_VOLT_MASK 0xFF -#define MAX77620_SD0_VOLT_MASK 0x3F -#define MAX77620_SD1_VOLT_MASK 0x7F -#define MAX77620_LDO_VOLT_MASK 0x3F - -#define MAX77620_REG_GPIO0 0x36 -#define MAX77620_REG_GPIO1 0x37 -#define MAX77620_REG_GPIO2 0x38 -#define MAX77620_REG_GPIO3 0x39 -#define MAX77620_REG_GPIO4 0x3A -#define MAX77620_REG_GPIO5 0x3B -#define MAX77620_REG_GPIO6 0x3C -#define MAX77620_REG_GPIO7 0x3D -#define MAX77620_REG_PUE_GPIO 0x3E -#define MAX77620_REG_PDE_GPIO 0x3F -#define MAX77620_REG_AME_GPIO 0x40 -#define MAX77620_REG_ONOFFCNFG1 0x41 -#define MAX77620_REG_ONOFFCNFG2 0x42 - -/* FPS Registers */ -#define MAX77620_REG_FPS_CFG0 0x43 -#define MAX77620_REG_FPS_CFG1 0x44 -#define MAX77620_REG_FPS_CFG2 0x45 -#define MAX77620_REG_FPS_LDO0 0x46 -#define MAX77620_REG_FPS_LDO1 0x47 -#define MAX77620_REG_FPS_LDO2 0x48 -#define MAX77620_REG_FPS_LDO3 0x49 -#define MAX77620_REG_FPS_LDO4 0x4A -#define MAX77620_REG_FPS_LDO5 0x4B -#define MAX77620_REG_FPS_LDO6 0x4C -#define MAX77620_REG_FPS_LDO7 0x4D -#define MAX77620_REG_FPS_LDO8 0x4E -#define MAX77620_REG_FPS_SD0 0x4F -#define MAX77620_REG_FPS_SD1 0x50 -#define MAX77620_REG_FPS_SD2 0x51 -#define MAX77620_REG_FPS_SD3 0x52 -#define MAX77620_REG_FPS_SD4 0x53 -#define MAX77620_REG_FPS_NONE 0 - -#define MAX77620_FPS_SRC_MASK 0xC0 -#define MAX77620_FPS_SRC_SHIFT 6 -#define MAX77620_FPS_PU_PERIOD_MASK 0x38 -#define MAX77620_FPS_PU_PERIOD_SHIFT 3 -#define MAX77620_FPS_PD_PERIOD_MASK 0x07 -#define MAX77620_FPS_PD_PERIOD_SHIFT 0 -#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 -#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 -#define MAX77620_FPS_EN_SRC_MASK 0x06 -#define MAX77620_FPS_EN_SRC_SHIFT 1 -#define MAX77620_FPS_ENFPS_SW_MASK 0x01 -#define MAX77620_FPS_ENFPS_SW 0x01 - -/* Minimum and maximum FPS period time (in microseconds) are - * different for MAX77620 and Max20024. - */ -#define MAX77620_FPS_PERIOD_MIN_US 40 -#define MAX20024_FPS_PERIOD_MIN_US 20 - -#define MAX77620_FPS_PERIOD_MAX_US 2560 -#define MAX20024_FPS_PERIOD_MAX_US 5120 - -#define MAX77620_REG_FPS_GPIO1 0x54 -#define MAX77620_REG_FPS_GPIO2 0x55 -#define MAX77620_REG_FPS_GPIO3 0x56 -#define MAX77620_REG_FPS_RSO 0x57 -#define MAX77620_REG_CID0 0x58 -#define MAX77620_REG_CID1 0x59 -#define MAX77620_REG_CID2 0x5A -#define MAX77620_REG_CID3 0x5B -#define MAX77620_REG_CID4 0x5C -#define MAX77620_REG_CID5 0x5D - -#define MAX77620_REG_DVSSD4 0x5E -#define MAX20024_REG_MAX_ADD 0x70 - -#define MAX77620_CID_DIDM_MASK 0xF0 -#define MAX77620_CID_DIDM_SHIFT 4 - -/* CNCG2SD */ -#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) -#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) - -/* Device Identification Metal */ -#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) -/* Device Indentification OTP */ -#define MAX77620_CID5_DIDO(n) ((n) & 0xF) - -/* SD CNFG1 */ -#define MAX77620_SD_SR_MASK 0xC0 -#define MAX77620_SD_SR_SHIFT 6 -#define MAX77620_SD_POWER_MODE_MASK 0x30 -#define MAX77620_SD_POWER_MODE_SHIFT 4 -#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) -#define MAX77620_SD_CFG1_ADE_DISABLE 0 -#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) -#define MAX77620_SD_FPWM_MASK 0x04 -#define MAX77620_SD_FPWM_SHIFT 2 -#define MAX77620_SD_FSRADE_MASK 0x01 -#define MAX77620_SD_FSRADE_SHIFT 0 -#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) -#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 -#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) -#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) -#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) -#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 -#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) - -/* LDO_CNFG2 */ -#define MAX77620_LDO_POWER_MODE_MASK 0xC0 -#define MAX77620_LDO_POWER_MODE_SHIFT 6 -#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) -#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) -#define MAX77620_LDO_CFG2_ADE_DISABLE 0 -#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) -#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) -#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) -#define MAX77620_LDO_CFG2_SS_SLOW 0 - -#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) -#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) -#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) -#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) -#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) -#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) -#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) - -#define MAX77620_IRQ_LBM_MASK (1 << 3) -#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) -#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) - -#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) -#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) -#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0 -#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) -#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) -#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0 -#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0 -#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) -#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) -#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) -#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) -#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) -#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) -#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) -#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) - -#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) -#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) -#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) -#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) -#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) -#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) -#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) -#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) - -#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) - -#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) -#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 -#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 -#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) -#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) -#define MAX20024_ONOFFCNFG1_CLRSE 0x18 - -#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) -#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) -#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) -#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) -#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) - -#define MAX77620_GLBLM_MASK (1 << 0) - -#define MAX77620_WDTC_MASK 0x3 -#define MAX77620_WDTOFFC (1 << 4) -#define MAX77620_WDTSLPC (1 << 3) -#define MAX77620_WDTEN (1 << 2) - -#define MAX77620_TWD_MASK 0x3 -#define MAX77620_TWD_2s 0x0 -#define MAX77620_TWD_16s 0x1 -#define MAX77620_TWD_64s 0x2 -#define MAX77620_TWD_128s 0x3 - -#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) -#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) -#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) -#define MAX77620_CNFGGLBL1_LBDAC 0x0E -#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) - -/* CNFG BBC registers */ -#define MAX77620_CNFGBBC_ENABLE (1 << 0) -#define MAX77620_CNFGBBC_CURRENT_MASK 0x06 -#define MAX77620_CNFGBBC_CURRENT_SHIFT 1 -#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 -#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 -#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) -#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 -#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 - -#define MAX77620_FPS_COUNT 3 - -/* Interrupts */ -enum { - MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ - MAX77620_IRQ_TOP_SD, /* SD power fail */ - MAX77620_IRQ_TOP_LDO, /* LDO power fail */ - MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ - MAX77620_IRQ_TOP_RTC, /* RTC */ - MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ - MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ - MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ - MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ - MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ -}; - -/* GPIOs */ -enum { - MAX77620_GPIO0, - MAX77620_GPIO1, - MAX77620_GPIO2, - MAX77620_GPIO3, - MAX77620_GPIO4, - MAX77620_GPIO5, - MAX77620_GPIO6, - MAX77620_GPIO7, - MAX77620_GPIO_NR, -}; - -/* FPS Source */ -enum max77620_fps_src { - MAX77620_FPS_SRC_0, - MAX77620_FPS_SRC_1, - MAX77620_FPS_SRC_2, - MAX77620_FPS_SRC_NONE, - MAX77620_FPS_SRC_DEF, -}; - -enum max77620_chip_id { - MAX77620, - MAX20024, -}; - -#endif /* _MFD_MAX77620_H_ */ diff --git a/fusee/fusee-primary/src/hwinit/max7762x.c b/fusee/fusee-primary/src/hwinit/max7762x.c deleted file mode 100755 index 67caaf230..000000000 --- a/fusee/fusee-primary/src/hwinit/max7762x.c +++ /dev/null @@ -1,136 +0,0 @@ -/* -* Copyright (c) 2018 naehrwert -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "max7762x.h" -#include "max77620.h" -#include "i2c.h" -#include "util.h" - -#define REGULATOR_SD 0 -#define REGULATOR_LDO 1 - -typedef struct _max77620_regulator_t -{ - u8 type; - const char *name; - u8 reg_sd; - u32 mv_step; - u32 mv_min; - u32 mv_default; - u32 mv_max; - u8 volt_addr; - u8 cfg_addr; - u8 volt_mask; - u8 enable_mask; - u8 enable_shift; - u8 status_mask; - - u8 fps_addr; - u8 fps_src; - u8 pd_period; - u8 pu_period; -} max77620_regulator_t; - -static const max77620_regulator_t _pmic_regulators[] = { - { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, 0x3F, 0x30, 4, 0x80, 0x4F, 1, 7, 1 }, - { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, 0x3F, 0x30, 4, 0x40, 0x50, 0, 1, 5 }, - { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, 0xFF, 0x30, 4, 0x20, 0x51, 1, 5, 2 }, - { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, 0xFF, 0x30, 4, 0x10, 0x52, 0, 3, 3 }, - { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, 0x3F, 0xC0, 6, 0x00, 0x46, 3, 7, 0 }, - { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, 0x3F, 0xC0, 6, 0x00, 0x47, 3, 7, 0 }, - { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, 0x3F, 0xC0, 6, 0x00, 0x48, 3, 7, 0 }, - { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, 0x3F, 0xC0, 6, 0x00, 0x49, 3, 7, 0 }, - { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4A, 0, 7, 1 }, - { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4B, 3, 7, 0 }, - { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4C, 3, 7, 0 }, - { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4D, 1, 4, 3 }, - { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4E, 3, 7, 0 } -}; - -int max77620_regulator_get_status(u32 id) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - if (reg->type == REGULATOR_SD) - return i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask ? 0 : 1; - return i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8 ? 1 : 0; -} - -int max77620_regulator_config_fps(u32 id) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - i2c_send_byte(I2C_5, 0x3C, reg->fps_addr, (reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); - - return 1; -} - -int max77620_regulator_set_voltage(u32 id, u32 mv) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - if (mv < reg->mv_default || mv > reg->mv_max) - return 0; - - u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; - u8 val = i2c_recv_byte(I2C_5, 0x3C, reg->volt_addr); - val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); - i2c_send_byte(I2C_5, 0x3C, reg->volt_addr, val); - sleep(1000); - - return 1; -} - -int max77620_regulator_enable(u32 id, int enable) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr; - u8 val = i2c_recv_byte(I2C_5, 0x3C, addr); - if (enable) - val = (val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask); - else - val &= ~reg->enable_mask; - i2c_send_byte(I2C_5, 0x3C, addr, val); - sleep(1000); - - return 1; -} - -void max77620_config_default() -{ - for (u32 i = 1; i <= REGULATOR_MAX; i++) - { - i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_CID4); - max77620_regulator_config_fps(i); - max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); - if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) - max77620_regulator_enable(i, 1); - } - i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_SD_CFG2, 4); -} diff --git a/fusee/fusee-primary/src/hwinit/pinmux.c b/fusee/fusee-primary/src/hwinit/pinmux.c deleted file mode 100644 index 269c91a57..000000000 --- a/fusee/fusee-primary/src/hwinit/pinmux.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "pinmux.h" -#include "t210.h" - -void pinmux_config_uart(u32 idx) -{ - PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = 0; - PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0x48; - PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0; - PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = 0x44; -} - -void pinmux_config_i2c(u32 idx) -{ - PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = 0x40; - PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = 0x40; -} diff --git a/fusee/fusee-primary/src/hwinit/pinmux.h b/fusee/fusee-primary/src/hwinit/pinmux.h deleted file mode 100644 index 59bf506d8..000000000 --- a/fusee/fusee-primary/src/hwinit/pinmux.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _PINMUX_H_ -#define _PINMUX_H_ - -#include "types.h" - -/*! Pinmux registers. */ -#define PINMUX_AUX_UART2_TX 0xF4 -#define PINMUX_AUX_UART3_TX 0x104 -#define PINMUX_AUX_GPIO_PE6 0x248 -#define PINMUX_AUX_GPIO_PH6 0x250 -/*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */ -#define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x)) -#define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x)) -#define PINMUX_AUX_UARTX_RTS(x) (0xEC + 0x10 * (x)) -#define PINMUX_AUX_UARTX_CTS(x) (0xF0 + 0x10 * (x)) -/*! 0:GEN1, 1:GEN2, 2:GEN3, 3:CAM, 4:PWR */ -#define PINMUX_AUX_X_I2C_SCL(x) (0xBC + 8 * (x)) -#define PINMUX_AUX_X_I2C_SDA(x) (0xC0 + 8 * (x)) - -void pinmux_config_uart(u32 idx); -void pinmux_config_i2c(u32 idx); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/pmc.h b/fusee/fusee-primary/src/hwinit/pmc.h deleted file mode 100644 index 4c8677239..000000000 --- a/fusee/fusee-primary/src/hwinit/pmc.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _PMC_H_ -#define _PMC_H_ - -/*! PMC registers. */ -#define APBDEV_PMC_PWRGATE_TOGGLE 0x30 -#define APBDEV_PMC_PWRGATE_STATUS 0x38 -#define APBDEV_PMC_NO_IOPOWER 0x44 -#define APBDEV_PMC_SCRATCH20 0xA0 -#define APBDEV_PMC_DDR_PWR 0xE8 -#define APBDEV_PMC_CRYPTO_OP 0xF4 -#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4 -#define APBDEV_PMC_IO_DPD_REQ 0x1B8 -#define APBDEV_PMC_IO_DPD2_REQ 0x1C0 -#define APBDEV_PMC_VDDP_SEL 0x1CC -#define APBDEV_PMC_TSC_MULT 0x2B4 -#define APBDEV_PMC_REG_SHORT 0x2CC -#define APBDEV_PMC_WEAK_BIAS 0x2C8 -#define APBDEV_PMC_SECURE_SCRATCH21 0x334 -#define APBDEV_PMC_CNTRL2 0x440 -#define APBDEV_PMC_IO_DPD4_REQ 0x464 -#define APBDEV_PMC_DDR_CNTRL 0x4E4 -#define APBDEV_PMC_SCRATCH188 0x810 -#define APBDEV_PMC_SCRATCH190 0x818 -#define APBDEV_PMC_SCRATCH200 0x840 - -#endif diff --git a/fusee/fusee-primary/src/hwinit/sdram.c b/fusee/fusee-primary/src/hwinit/sdram.c deleted file mode 100644 index a64d7b886..000000000 --- a/fusee/fusee-primary/src/hwinit/sdram.c +++ /dev/null @@ -1,488 +0,0 @@ -#include "i2c.h" -#include "t210.h" -#include "mc.h" -//#include "emc.h" -#include "pmc.h" -#include "util.h" -#include "fuse.h" - -#include "sdram.inl" - -static u32 _get_sdram_id() -{ - return (fuse_read_odm(4) & 0x38) >> 3; -} - -static void _sdram_config(const u32 *_cfg) -{ - const u32 *_cfg_120 = _cfg + 0x120; - const u32 *_cfg_100 = _cfg + 0x100; - - PMC(0x45C) = (((4 * _cfg[0x12F] >> 2) + 0x80000000) ^ 0xFFFF) & 0xC000FFFF; - sleep(_cfg[0x111]); - - u32 req = (4 * _cfg_120[0x10] >> 2) + 0x80000000; - PMC(APBDEV_PMC_IO_DPD4_REQ) = (req ^ 0x3FFF0000) >> 16 << 16; - sleep(_cfg_100[0x12]); - PMC(APBDEV_PMC_IO_DPD4_REQ) = (req ^ 0xFFFF) & 0xC000FFFF; - sleep(_cfg_100[0x12]); - PMC(APBDEV_PMC_WEAK_BIAS) = 0; - sleep(1); - - CLOCK(0x98) = _cfg[4]; - CLOCK(0x9C) = 0; - CLOCK(0x90) = (_cfg[2] << 8) | (*((u16 *)_cfg + 0xA) << 20) | _cfg[1] | 0x40000000; - - u32 wait_end = TMR(0x10) + 300; - while (!((CLOCK(0x90) >> 27) & 1)) - { - if (TMR(0x10) >= wait_end) - goto break_nosleep; - } - sleep(10); -break_nosleep: - - CLOCK(0x19C) = _cfg[0x16] & 0xFFFEFFFF | (_cfg[0x175] >> 11) & 0x10000; - if (_cfg[0x17]) - CLOCK(0x664) = _cfg[0x17]; - if (_cfg[0x1A]) - CLOCK(0x44C) = 0x40000000; - CLOCK(0x328) = 0x2000001; - CLOCK(0x284) = 0x4000; - CLOCK(0x30C) = 0x2000001; - EMC(0xC34) = _cfg_120[0x13]; - EMC(0xC38) = _cfg_120[0x14]; - EMC(0xCF0) = _cfg_120[0x15]; - EMC(0x28) = 1; - sleep(1); - EMC(0x8) = _cfg[0xA9] | 2 * _cfg[0xAA]; - if (_cfg[0xA]) - *(vu32 *)_cfg[0xA] = _cfg[0xB]; - EMC(0x584) = _cfg[0x7B]; - EMC(0x380) = _cfg[0x7D]; - EMC(0x384) = _cfg[0x7E]; - EMC(0x388) = _cfg[0x7F]; - EMC(0x38C) = _cfg[0x80]; - EMC(0x390) = _cfg[0x81]; - EMC(0x394) = _cfg[0x82]; - EMC(0x398) = _cfg[0x83]; - EMC(0x39C) = _cfg[0x84]; - EMC(0x3A0) = _cfg[0x85]; - EMC(0x3A4) = _cfg[0x86]; - EMC(0x3A8) = _cfg[0x87]; - EMC(0x3AC) = _cfg[0x88]; - EMC(0x3B0) = _cfg[0x89]; - EMC(0xC80) = _cfg[0x14A]; - EMC(0xC84) = _cfg[0x14B]; - EMC(0xC88) = _cfg[0x14C]; - EMC(0x330) = (_cfg_120[0x16] | 0xFEEDFEED) & 0x1FFF1FFF; - EMC(0x5F0) = _cfg[0x149]; - EMC(0x5C8) = _cfg[0x7C]; - EMC(0x404) = _cfg_100[0x18]; - EMC(0x408) = _cfg_100[0x19]; - EMC(0x40C) = _cfg_100[0x1A]; - EMC(0x410) = _cfg_100[0x1B]; - EMC(0x418) = _cfg_100[0x1C]; - EMC(0x41C) = _cfg_100[0x1D]; - EMC(0x420) = _cfg_100[0x1E]; - EMC(0x424) = _cfg_100[0x1F]; - if (_cfg[0xE]) - *(vu32 *)_cfg[0xE] = _cfg[0xF]; - EMC(0x30C) = _cfg[0x31]; - EMC(0x578) = _cfg[0x32]; - EMC(0x2F4) = _cfg[0x33]; - EMC(0x458) = _cfg[0x1D]; - EMC(0x45C) = _cfg[0x1E]; - EMC(0x5B0) = _cfg[0x1F]; - EMC(0x5B4) = _cfg[0x20]; - EMC(0x5CC) = _cfg[0x21]; - EMC(0x574) = _cfg[0x22]; - EMC(0x2DC) = _cfg[0x23]; - EMC(0xC48) = _cfg[0x2A]; - EMC(0xC70) = _cfg[0x2B]; - EMC(0xC74) = _cfg[0x2C]; - EMC(0xC4C) = _cfg[0x2D]; - EMC(0xC78) = _cfg[0x2E]; - EMC(0x464) = _cfg[0x26]; - EMC(0xC44) = _cfg[0x2F]; - EMC(0x5E4) = _cfg_120[0xD]; - EMC(0x5E8) = _cfg_120[0xE]; - EMC(0x2C8) = _cfg[0xB0]; - EMC(0x588) = _cfg_120[1]; - EMC(0x58C) = _cfg_120[2]; - EMC(0x594) = _cfg_120[3]; - EMC(0x598) = _cfg_120[4]; - EMC(0x59C) = _cfg_120[5]; - EMC(0x5A0) = _cfg_120[6]; - EMC(0x5A4) = _cfg_120[7]; - EMC(0x5A8) = _cfg_120[8]; - EMC(0x5AC) = _cfg_120[9]; - EMC(0x5B8) = _cfg_120[0xA]; - EMC(0x5BC) = _cfg_120[0xB]; - EMC(0x5C4) = _cfg_120[0xC]; - EMC(0x330) = (_cfg_120[0x16] | 0xFE40FE40) & 0x1FFF1FFF; - EMC(0xC40) = _cfg_120[0x12]; - EMC(0x318) = _cfg_120[0x17]; - EMC(0x334) = _cfg_120[0x18] & 0xFF7FFF7F; - EMC(0x31C) = _cfg_120[0x19]; - EMC(0xC3C) = _cfg_120[0x1A]; - EMC(0xC54) = _cfg_120[0x1B]; - EMC(0xC50) = _cfg_120[0x1C]; - EMC(0xC64) = _cfg_120[0x1F]; - EMC(0xC5C) = _cfg_120[0x1D]; - EMC(0xC58) = _cfg_120[0x1E]; - EMC(0xC60) = _cfg[0x141]; - EMC(0x49C) = _cfg[0x142]; - EMC(0x720) = _cfg[0x143]; - EMC(0x724) = _cfg[0x144]; - EMC(0x728) = _cfg[0x145]; - EMC(0x72C) = _cfg[0x146]; - EMC(0x730) = _cfg[0x147]; - EMC(0x734) = _cfg[0x148]; - EMC(0x740) = _cfg[0x14D]; - EMC(0x744) = _cfg[0x14E]; - EMC(0x748) = _cfg[0x14F]; - EMC(0x74C) = _cfg[0x150]; - EMC(0x750) = _cfg[0x151]; - EMC(0x754) = _cfg[0x152]; - EMC(0x760) = _cfg[0x153]; - EMC(0x770) = _cfg[0x154]; - EMC(0x774) = _cfg[0x155]; - EMC(0x778) = _cfg[0x156]; - EMC(0x780) = _cfg[0x157]; - EMC(0x784) = _cfg[0x158]; - EMC(0x788) = _cfg[0x159]; - EMC(0xBE0) = _cfg[0xB6]; - EMC(0xBE4) = _cfg[0xB7]; - EMC(0xBF0) = _cfg[0xB8]; - EMC(0xBF4) = _cfg[0xB9]; - EMC(0xCF4) = _cfg[0xBA]; - EMC(0x600) = _cfg[0xBD]; - EMC(0x604) = _cfg[0xBE]; - EMC(0x608) = _cfg[0xBF]; - EMC(0x60C) = _cfg[0xC0]; - EMC(0x610) = _cfg[0xC1]; - EMC(0x614) = _cfg[0xC2]; - EMC(0x620) = _cfg[0xC3]; - EMC(0x624) = _cfg[0xC4]; - EMC(0x628) = _cfg[0xC5]; - EMC(0x62C) = _cfg[0xC6]; - EMC(0x630) = _cfg[0xC7]; - EMC(0x634) = _cfg[0xC8]; - EMC(0x330) = _cfg_120[0x16]; - EMC(0x640) = _cfg[0xC9]; - EMC(0x644) = _cfg[0xCA]; - EMC(0x648) = _cfg[0xCB]; - EMC(0x64C) = _cfg[0xCC]; - EMC(0x650) = _cfg[0xCD]; - EMC(0x654) = _cfg[0xCE]; - EMC(0x660) = _cfg[0xCF]; - EMC(0x664) = _cfg[0xD0]; - EMC(0x668) = _cfg[0xD1]; - EMC(0x66C) = _cfg[0xD2]; - EMC(0x670) = _cfg[0xD3]; - EMC(0x674) = _cfg[0xD4]; - EMC(0x680) = _cfg[0xD5]; - EMC(0x684) = _cfg[0xD6]; - EMC(0x688) = _cfg[0xD7]; - EMC(0x68C) = _cfg[0xD8]; - EMC(0x690) = _cfg[0xD9]; - EMC(0x694) = _cfg[0xDA]; - EMC(0x6A0) = _cfg[0xDB]; - EMC(0x6A4) = _cfg[0xDC]; - EMC(0x6A8) = _cfg[0xDD]; - EMC(0x6AC) = _cfg[0xDE]; - EMC(0x6B0) = _cfg[0xDF]; - EMC(0x6B4) = _cfg[0xE0]; - EMC(0x6C0) = _cfg[0xE1]; - EMC(0x6C4) = _cfg[0xE2]; - EMC(0x6C8) = _cfg[0xE3]; - EMC(0x6CC) = _cfg[0xE4]; - EMC(0x6E0) = _cfg[0xE5]; - EMC(0x6E4) = _cfg[0xE6]; - EMC(0x6E8) = _cfg[0xE7]; - EMC(0x6EC) = _cfg[0xE8]; - EMC(0xC00) = _cfg[0xE9]; - EMC(0xC04) = _cfg[0xEA]; - EMC(0xC08) = _cfg[0xEB]; - EMC(0xC0C) = _cfg[0xEC]; - EMC(0xC10) = _cfg[0xED]; - EMC(0xC20) = _cfg[0xEE]; - EMC(0xC24) = _cfg[0xEF]; - EMC(0xC28) = _cfg[0xF0]; - EMC(0xC68) = (*((u8 *)_cfg + 0x500) | 0xFFFFFFFE) & 0xF; - if (_cfg[0xC]) - *(vu32 *)_cfg[0xC] = _cfg[0xD]; - EMC(0x28) = 1; - MC(0x648) = _cfg[0x180]; - MC(0x978) = _cfg[0x181]; - MC(0x64C) = _cfg[0x182]; - MC(0x418) = _cfg[0x183]; - MC(0x590) = _cfg[0x184]; - MC(0x984) = _cfg[0x185]; - MC(0x988) = _cfg[0x186]; - MC(0x54) = _cfg[0x15A]; - MC(0x58) = _cfg[0x15B]; - MC(0x5C) = _cfg[0x15C]; - MC(0x60) = _cfg[0x15D]; - MC(0x64) = _cfg[0x15E]; - MC(0x68) = _cfg[0x15F]; - MC(0x6C) = _cfg[0x160]; - MC(0x50) = _cfg[0x161]; - MC(0x670) = _cfg[0x187]; - MC(0x9D4) = _cfg[0x188]; - MC(0x674) = _cfg[0x189]; - MC(0x9A0) = _cfg[0x1D6]; - MC(0x9A8) = _cfg[0x1D7]; - MC(0x9A4) = _cfg[0x1D8]; - MC(0x90) = _cfg[0x162]; - MC(0x94) = _cfg[0x163]; - MC(0x6F0) = _cfg[0x164]; - MC(0x6F4) = _cfg[0x165]; - MC(0x98) = _cfg[0x166]; - MC(0x9C) = _cfg[0x167]; - MC(0xA0) = _cfg[0x168]; - MC(0xA4) = _cfg[0x169]; - MC(0xA8) = _cfg[0x16A]; - MC(0xAC) = _cfg[0x16B]; - MC(0xB0) = _cfg[0x16C]; - MC(0xB4) = _cfg[0x16D]; - MC(0xB8) = _cfg[0x16E]; - MC(0xBC) = _cfg[0x16F]; - MC(0x6C4) = _cfg[0x17D]; - MC(0xC0) = _cfg[0x170]; - MC(0xC4) = _cfg[0x171]; - MC(0x6C0) = _cfg[0x172]; - MC(0xD0) = _cfg[0x173]; - MC(0xD4) = _cfg[0x174]; - MC(0xD8) = _cfg[0x175]; - MC(0xDC) = _cfg[0x176]; - MC(0xC8) = _cfg[0x177]; - MC(0xE0) = _cfg[0x178]; - MC(0xE8) = _cfg[0x179]; - MC(0x968) = _cfg[0x17A]; - MC(0xEC) = _cfg[0x17B]; - MC(0x9DC) = _cfg[0x17C]; - MC(0xFC) = 1; - MC(0xF4) = _cfg[0x17E]; - MC(0x100) = _cfg[0x17F]; - EMC(0x10) = _cfg[0x34]; - EMC(0x140) = _cfg_100[7]; - EMC(0x700) = _cfg[0x27]; - EMC(0x704) = _cfg[0x28]; - EMC(0x708) = _cfg[0x29]; - EMC(0x2F8) = _cfg[0x24]; - EMC(0x300) = _cfg[0x25]; - EMC(0x2A8) = _cfg[0x1B]; - EMC(0x2A4) = _cfg[0x1C]; - sleep(_cfg[0x30]); - if (_cfg[0x10]) - *(vu32 *)_cfg[0x10] = _cfg[0x11]; - EMC(0x2B8) = _cfg[0xA4]; - EMC(0x560) = _cfg[0xA5]; - EMC(0x55C) = _cfg[0xBB]; - EMC(0x554) = _cfg[0xBC]; - EMC(0xF0) = _cfg[0xAB]; - EMC(0xF4) = _cfg[0xAC]; - EMC(0xC8) = _cfg[0xA1]; - EMC(0xC4) = _cfg[0xA2]; - EMC(0x104) = _cfg[0x7A]; - EMC(0x2C) = _cfg[0x3A]; - EMC(0x30) = _cfg[0x3B]; - EMC(0x590) = _cfg[0x3C]; - EMC(0x580) = _cfg[0x3D]; - EMC(0xC0) = _cfg[0x3E]; - EMC(0x34) = _cfg[0x3F]; - EMC(0x38) = _cfg[0x40]; - EMC(0xAC) = _cfg[0x47]; - EMC(0x144) = _cfg[0x41]; - EMC(0x148) = _cfg[0x42]; - EMC(0x3C) = _cfg[0x43]; - EMC(0x40) = _cfg[0x44]; - EMC(0x44) = _cfg[0x45]; - EMC(0x48) = _cfg[0x46]; - EMC(0x5C0) = _cfg[0x48]; - EMC(0x4C) = _cfg[0x49]; - EMC(0x50) = _cfg[0x4A]; - EMC(0x54) = _cfg[0x4B]; - EMC(0x58) = _cfg[0x4C]; - EMC(0xB8) = _cfg[0x4D]; - EMC(0x5C) = _cfg[0x4E]; - EMC(0x4E0) = _cfg[0x4F]; - EMC(0x498) = _cfg[0x50]; - EMC(0x494) = _cfg[0x51]; - EMC(0x2D0) = _cfg[0x52]; - EMC(0x490) = _cfg[0x53]; - EMC(0x48C) = _cfg[0x54]; - EMC(0x60) = _cfg[0x55]; - EMC(0x568) = _cfg[0x56]; - EMC(0x468) = _cfg[0x57]; - EMC(0x46C) = _cfg[0x58]; - EMC(0x14C) = _cfg[0x59]; - EMC(0x150) = _cfg[0x5A]; - EMC(0x154) = _cfg[0x5B]; - EMC(0x56C) = _cfg[0x5C]; - EMC(0xC68) = _cfg[0x140]; - EMC(0x8) = _cfg[0xA9]; - EMC(0x64) = _cfg[0x5D]; - EMC(0x428) = 0; - EMC(0x68) = _cfg[0x5E]; - EMC(0x6C) = _cfg[0x5F]; - EMC(0x2CC) = _cfg[0x60]; - EMC(0x2D8) = _cfg[0x61]; - EMC(0x2D4) = _cfg[0x62]; - EMC(0x564) = _cfg[0x63]; - EMC(0x70) = _cfg[0x64]; - EMC(0x74) = _cfg[0x65]; - EMC(0x3DC) = _cfg[0x66]; - EMC(0x78) = _cfg[0x67]; - EMC(0x7C) = _cfg[0x68]; - EMC(0x80) = _cfg[0x69]; - EMC(0x84) = _cfg[0x6A]; - EMC(0x88) = _cfg[0x6B]; - EMC(0x8C) = _cfg[0x6C]; - EMC(0x11C) = _cfg[0x6D]; - EMC(0x118) = _cfg[0x6E]; - EMC(0xB4) = _cfg[0x6F]; - EMC(0x90) = _cfg[0x70]; - EMC(0x3E4) = _cfg[0x71]; - EMC(0x94) = _cfg[0x72]; - EMC(0x158) = _cfg[0x73]; - EMC(0x15C) = _cfg[0x74]; - EMC(0x98) = _cfg[0x75]; - EMC(0x9C) = _cfg[0x76]; - EMC(0xA0) = _cfg[0x77]; - EMC(0xA4) = _cfg[0x78]; - EMC(0xA8) = _cfg[0x79]; - EMC(0xB0) = _cfg[0xF2]; - EMC(0x2BC) = _cfg[0xAF]; - EMC(0x2C0) = _cfg[0xB1]; - EMC(0x100) = _cfg[0x8A] & 0xFFFFFFFD; - EMC(0x120) = _cfg[0x8B]; - EMC(0x440) = _cfg_120[0xF]; - EMC(0x444) = _cfg_120[0x10]; - EMC(0x448) = _cfg_120[0x11]; - EMC(0x124) = _cfg_100[0x17]; - EMC(0x480) = *_cfg_120; - EMC(0xC) = ((_cfg[0xA3] & 4 | 0x3C00000) & 0xFFFFFFF7 | _cfg[0xA3] & 8) & 0xFFFFFFFD | _cfg[0xA3] & 2; - if ((_cfg[0x1D4] & 0x80000000) != 0) - { - *(vu32 *)(4 * _cfg[0x1D4] + 0x70000000) = _cfg[0x1D5]; - MC(0xFC) = 1; - } - PMC(0x45C) = ((4 * _cfg_120[0xF] >> 2) + 0x40000000) & 0xCFFF0000; - sleep(_cfg_100[0x11]); - if (!_cfg[0x1B]) - EMC(0x2A4) = _cfg[0x1C] | 0x200; - EMC(0x334) = _cfg_120[0x18]; - if (_cfg[0xFA] << 31) - { - if (*_cfg == 2) - EMC(0x2E4) = 8 * _cfg[0xF4]; - if (*_cfg == 3) - { - EMC(0x2E4) = _cfg[0xF4]; - EMC(0x2E8) = _cfg[0xF5]; - } - } - EMC(0x28) = 1; - sleep(_cfg[0x39]); - PMC(0x4E4) &= 0xFFF8007F; - sleep(_cfg_100[0x15]); - if (*_cfg == 2) - { - EMC(0x24) = (_cfg[0x37] << 16) | (_cfg[0x38] << 12); - sleep(_cfg[0x36] + 200); - EMC(0x24) = ((_cfg[0x37] << 16) | (_cfg[0x38] << 12)) + 0x100; - sleep(_cfg[0x36] + 500); - } - if (*_cfg == 3) - { - EMC(0x24) = (_cfg[0x37] << 16) | (_cfg[0x38] << 12); - sleep(_cfg[0x36] + 200); - EMC(0x24) = ((_cfg[0x37] << 16) | (_cfg[0x38] << 12)) + 0x100; - sleep(_cfg[0x36] + 2000); - } - EMC(0x24) = ((_cfg[0x37] << 16) | (_cfg[0x38] << 12)) + 0x101; - sleep(_cfg[0x35]); - if (*_cfg != 3) - EMC(0xDC) = (_cfg[0xB2] << 30) + 1; - if (*_cfg == 1) - sleep(_cfg[0x36] + 200); - if (*_cfg == 3) - { - if (_cfg[0x12]) - *(vu32 *)_cfg[0x12] = _cfg[0x13]; - EMC(0x134) = _cfg[0x91]; - EMC(0xE8) = _cfg[0x90]; - EMC(0x138) = _cfg[0x92]; - EMC(0x13C) = _cfg[0x93]; - EMC(0x4A4) = _cfg[0x94]; - EMC(0x4C4) = _cfg[0x9A]; - EMC(0x4AC) = _cfg[0x95]; - EMC(0x4BC) = _cfg[0x98]; - EMC(0x4B0) = _cfg[0x96]; - EMC(0x4C0) = _cfg[0x99]; - if (_cfg[0xFA] << 31) - { - EMC(0x2EC) = _cfg[0xF7]; - sleep(_cfg[0xF9]); - EMC(0x2EC) = _cfg[0xF7] ^ 3; - if (!(_cfg[0xB2] & 2)) - { - EMC(0x2EC) = _cfg[0xF8]; - sleep(_cfg[0xF9]); - EMC(0x2EC) = _cfg[0xF8] ^ 3; - } - } - } - PMC(0x1D0) = _cfg_100[0xF]; - if (_cfg[0] == 1 || _cfg[0] == 2 || _cfg[0] == 3) - { - EMC(0x2E0) = _cfg[0xF3]; - EMC(0x2E4) = _cfg[0xF4]; - EMC(0x2E8) = _cfg[0xF5]; - } - if (_cfg[0x14]) - *(vu32 *)_cfg[0x14] = _cfg[0x15]; - EMC(0x28) = 1; - if (_cfg_100[8]) - EMC(0xD4) = ((1 << _cfg_100[8] << 8) - 0xFD) | (_cfg[0x38] << 30); - EMC(0x20) = _cfg[0xB2] | 0x80000000; - EMC(0x3E0) = _cfg[0xAD]; - EMC(0x5F4) = _cfg[0xA8]; - EMC(0xC) = _cfg[0xA3]; - EMC(0x310) = _cfg[0xB4]; - EMC(0x314) = _cfg[0xB5]; - EMC(0x3D8) = _cfg[0xB3]; - EMC(0x100) = _cfg[0x8A] | 2; - EMC(0x28) = 1; - EMC(0x558) = _cfg[0xA6]; - EMC(0x4D8) = _cfg[0xA7]; - SYSREG(AHB_ARBITRATION_XBAR_CTRL) = SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF | (*((u16 *)_cfg + 0x15C) << 16); - MC(0x650) = _cfg[0x18A]; - MC(0x678) = _cfg[0x18B]; - MC(0x9AC) = _cfg[0x1D9]; - MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; //Disable write access to a bunch of MC registers. -} - -void sdram_init() -{ - u32 sdram_id = _get_sdram_id(); - const u32 *cfg = _dram_cfgs[sdram_id]; //TODO: sdram_id should be in [0,4]. - - i2c_send_byte(I2C_5, 0x3C, 0x22, 0x05); - i2c_send_byte(I2C_5, 0x3C, 0x17, 40); //40 = (1000 * 1100 - 600000) / 12500 - - PMC(APBDEV_PMC_VDDP_SEL) = cfg[0x10C]; - sleep(cfg[0x10D]); - PMC(APBDEV_PMC_DDR_PWR) = PMC(0xE8); - PMC(APBDEV_PMC_NO_IOPOWER) = cfg[0x114]; - PMC(APBDEV_PMC_REG_SHORT) = cfg[0x113]; - PMC(APBDEV_PMC_DDR_CNTRL) = cfg[0x116]; - - if (cfg[8]) - *(vu32 *)cfg[8] = cfg[9]; - - _sdram_config(cfg); -} diff --git a/fusee/fusee-primary/src/hwinit/sdram.h b/fusee/fusee-primary/src/hwinit/sdram.h deleted file mode 100644 index 19db6da9b..000000000 --- a/fusee/fusee-primary/src/hwinit/sdram.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SDRAM_H_ -#define _SDRAM_H_ - -void sdram_init(); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/sdram.inl b/fusee/fusee-primary/src/hwinit/sdram.inl deleted file mode 100644 index 788dcc8aa..000000000 --- a/fusee/fusee-primary/src/hwinit/sdram.inl +++ /dev/null @@ -1,812 +0,0 @@ -static const u8 _dram_cfg_0[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, - 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 _dram_cfg_1[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, - 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 _dram_cfg_2[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, - 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 _dram_cfg_3[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, - 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 _dram_cfg_4[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0C, 0x00, - 0x02, 0x03, 0x0C, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x18, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u32 *_dram_cfgs[5] = { - (const u32 *)_dram_cfg_0, - (const u32 *)_dram_cfg_1, - (const u32 *)_dram_cfg_2, - (const u32 *)_dram_cfg_3, - (const u32 *)_dram_cfg_4 -}; diff --git a/fusee/fusee-primary/src/hwinit/t210.h b/fusee/fusee-primary/src/hwinit/t210.h deleted file mode 100644 index 578d6282b..000000000 --- a/fusee/fusee-primary/src/hwinit/t210.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _T210_H_ -#define _T210_H_ - -#include "types.h" - -#define HOST1X_BASE 0x50000000 -#define DISPLAY_A_BASE 0x54200000 -#define DSI_BASE 0x54300000 -#define VIC_BASE 0x54340000 -#define TSEC_BASE 0x54500000 -#define SOR1_BASE 0x54580000 -#define TMR_BASE 0x60005000 -#define CLOCK_BASE 0x60006000 -#define FLOW_CTLR_BASE 0x60007000 -#define SYSREG_BASE 0x6000C000 -#define SB_BASE (SYSREG_BASE + 0x200) -#define GPIO_BASE 0x6000D000 -#define GPIO_1_BASE (GPIO_BASE) -#define GPIO_2_BASE (GPIO_BASE + 0x100) -#define GPIO_3_BASE (GPIO_BASE + 0x200) -#define GPIO_6_BASE (GPIO_BASE + 0x500) -#define EXCP_VEC_BASE 0x6000F000 -#define PINMUX_AUX_BASE 0x70003000 -#define UART_BASE 0x70006000 -#define PMC_BASE 0x7000E400 -#define SYSCTR0_BASE 0x7000F000 -#define FUSE_BASE 0x7000F800 -#define MC_BASE 0x70019000 -#define EMC_BASE 0x7001B000 -#define MIPI_CAL_BASE 0x700E3000 -#define I2S_BASE 0x702D1000 - -#define _REG(base, off) *(vu32 *)((base) + (off)) - -#define HOST1X(off) _REG(HOST1X_BASE, off) -#define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off) -#define DSI(off) _REG(DSI_BASE, off) -#define VIC(off) _REG(VIC_BASE, off) -#define TSEC(off) _REG(TSEC_BASE, off) -#define SOR1(off) _REG(SOR1_BASE, off) -#define TMR(off) _REG(TMR_BASE, off) -#define CLOCK(off) _REG(CLOCK_BASE, off) -#define FLOW_CTLR(off) _REG(FLOW_CTLR_BASE, off) -#define SYSREG(off) _REG(SYSREG_BASE, off) -#define SB(off) _REG(SB_BASE, off) -#define GPIO_1(off) _REG(GPIO_1_BASE, off) -#define GPIO_2(off) _REG(GPIO_2_BASE, off) -#define GPIO_3(off) _REG(GPIO_3_BASE, off) -#define GPIO_6(off) _REG(GPIO_6_BASE, off) -#define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off) -#define PINMUX_AUX(off) _REG(PINMUX_AUX_BASE, off) -#define PMC(off) _REG(PMC_BASE, off) -#define SYSCTR0(off) _REG(SYSCTR0_BASE, off) -#define FUSE(off) _REG(FUSE_BASE, off) -#define MC(off) _REG(MC_BASE, off) -#define EMC(off) _REG(EMC_BASE, off) -#define MIPI_CAL(off) _REG(MIPI_CAL_BASE, off) -#define I2S(off) _REG(I2S_BASE, off) - -/*! System registers. */ -#define AHB_ARBITRATION_XBAR_CTRL 0xE0 - -/*! Secure boot registers. */ -#define SB_CSR_0 0x0 -#define SB_AA64_RESET_LOW 0x30 -#define SB_AA64_RESET_HIGH 0x34 - -/*! SYSCTR0 registers. */ -#define SYSCTR0_CNTFID0 0x20 - -#endif diff --git a/fusee/fusee-primary/src/hwinit/tsec.c b/fusee/fusee-primary/src/hwinit/tsec.c deleted file mode 100644 index 3b229fc52..000000000 --- a/fusee/fusee-primary/src/hwinit/tsec.c +++ /dev/null @@ -1,113 +0,0 @@ -#include <string.h> -#include "tsec.h" -#include "clock.h" -#include "t210.h" - -static int _tsec_dma_wait_idle() -{ - u32 timeout = TMR(0x10) + 10000000; - - while (!(TSEC(0x1118) & 2)) - if (TMR(0x10) > timeout) - return 0; - - return 1; -} - -static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offset) -{ - u32 cmd; - - if (not_imem) - cmd = 0x600; // DMA 0x100 bytes - else - cmd = 0x10; // dma imem - - TSEC(0x1114) = i_offset; // tsec_dmatrfmoffs_r - TSEC(0x111C) = pa_offset; // tsec_dmatrffboffs_r - TSEC(0x1118) = cmd; // tsec_dmatrfcmd_r - - return _tsec_dma_wait_idle(); -} - -int tsec_query(u32 carveout, u8 *dst, u32 rev) -{ - int res = 0; - - //Enable clocks. - clock_enable_host1x(); - clock_enable_tsec(); - clock_enable_sor_safe(); - clock_enable_sor0(); - clock_enable_sor1(); - clock_enable_kfuse(); - - //Configure Falcon. - TSEC(0x110C) = 0; // tsec_dmactl_r - TSEC(0x1010) = 0xFFF2; // tsec_irqmset_r - TSEC(0x101C) = 0xFFF0; // tsec_irqdest_r - TSEC(0x1048) = 3; // tsec_itfen_r - if (!_tsec_dma_wait_idle()) - { - res = -1; - goto out; - } - - //Load firmware. - TSEC(0x1110) = carveout >> 8;// tsec_dmatrfbase_r - for (u32 addr = 0; addr < 0xF00; addr += 0x100) - if (!_tsec_dma_pa_to_internal_100(0, addr, addr)) - { - res = -2; - goto out; - } - - //Execute firmware. - HOST1X(0x3300) = 0x34C2E1DA; - TSEC(0x1044) = 0; - TSEC(0x1040) = rev; - TSEC(0x1104) = 0; // tsec_bootvec_r - TSEC(0x1100) = 2; // tsec_cpuctl_r - if (!_tsec_dma_wait_idle()) - { - res = -3; - goto out; - } - u32 timeout = TMR(0x10) + 2000000; - while (!TSEC(0x1044)) - if (TMR(0x10) > timeout) - { - res = -4; - goto out; - } - if (TSEC(0x1044) != 0xB0B0B0B0) - { - res = -5; - goto out; - } - - //Fetch result. - HOST1X(0x3300) = 0; - u32 buf[4]; - buf[0] = SOR1(0x1E8); - buf[1] = SOR1(0x21C); - buf[2] = SOR1(0x208); - buf[3] = SOR1(0x20C); - SOR1(0x1E8) = 0; - SOR1(0x21C) = 0; - SOR1(0x208) = 0; - SOR1(0x20C) = 0; - memcpy(dst, &buf, 0x10); - -out:; - - //Disable clocks. - clock_disable_kfuse(); - clock_disable_sor1(); - clock_disable_sor0(); - clock_disable_sor_safe(); - clock_disable_tsec(); - clock_disable_host1x(); - - return res; -} diff --git a/fusee/fusee-primary/src/hwinit/tsec.h b/fusee/fusee-primary/src/hwinit/tsec.h deleted file mode 100644 index 03fb503d2..000000000 --- a/fusee/fusee-primary/src/hwinit/tsec.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _TSEC_H_ -#define _TSEC_H_ - -#include "types.h" - -int tsec_query(u32 carveout, u8 *dst, u32 rev); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/types.h b/fusee/fusee-primary/src/hwinit/types.h deleted file mode 100644 index dff2978da..000000000 --- a/fusee/fusee-primary/src/hwinit/types.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _TYPES_H_ -#define _TYPES_H_ - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef volatile unsigned int vu32; -typedef unsigned long long int u64; -typedef volatile unsigned long long int vu64; - -#endif diff --git a/fusee/fusee-primary/src/hwinit/uart.c b/fusee/fusee-primary/src/hwinit/uart.c deleted file mode 100644 index b9b35aa8c..000000000 --- a/fusee/fusee-primary/src/hwinit/uart.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "uart.h" -#include "t210.h" -#include "util.h" - -/* UART A, B, C, D and E. */ -static const u32 uart_baseoff[5] = { 0, 0x40, 0x200, 0x300, 0x400 }; - -void uart_init(u32 idx, u32 baud) -{ - volatile uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - - //Set baud rate. - u32 rate = (8 * baud + 408000000) / (16 * baud); - uart->UART_LCR = 0x80; //Enable DLAB. - uart->UART_THR_DLAB = (u8)rate; //Divisor latch LSB. - uart->UART_IER_DLAB = (u8)(rate >> 8); //Divisor latch MSB. - uart->UART_LCR = 0; //Diable DLAB. - - //Setup UART in fifo mode. - uart->UART_IER_DLAB = 0; - uart->UART_IIR_FCR = 7; //Enable and clear TX and RX FIFOs. - volatile u32 tmp = uart->UART_LSR; - sleep(3 * ((baud + 999999) / baud)); - uart->UART_LCR = 3; //Set word length 8. - uart->UART_MCR = 0; - uart->UART_MSR = 0; - uart->UART_IRDA_CSR = 0; - uart->UART_RX_FIFO_CFG = 1; - uart->UART_MIE = 0; - uart->UART_ASR = 0; -} - -void uart_wait_idle(u32 idx, u32 which) -{ - volatile uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - while (!(uart->UART_VENDOR_STATUS & which)) - ; -} - -void uart_send(u32 idx, u8 *buf, u32 len) -{ - volatile uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - - for (u32 i = 0; i != len; i++) - { - while (uart->UART_LSR & UART_TX_FIFO_FULL) - ; - uart->UART_THR_DLAB = buf[i]; - }; -} - -void uart_recv(u32 idx, u8 *buf, u32 len) -{ - volatile uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - - for (u32 i = 0; i != len; i++) - { - while (uart->UART_LSR & UART_RX_FIFO_EMPTY) - ; - buf[i] = uart->UART_THR_DLAB; - }; -} diff --git a/fusee/fusee-primary/src/hwinit/uart.h b/fusee/fusee-primary/src/hwinit/uart.h deleted file mode 100644 index ac8222215..000000000 --- a/fusee/fusee-primary/src/hwinit/uart.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _UART_H_ -#define _UART_H_ - -#include "types.h" - -#define UART_A 0 -#define UART_B 1 -#define UART_C 2 -//TODO: define clock inits for those. -/*#define UART_D 3 -#define UART_E 4*/ - -#define BAUD_115200 115200 - -#define UART_TX_IDLE 0x00000001 -#define UART_RX_IDLE 0x00000002 -#define UART_TX_FIFO_FULL 0x100 -#define UART_RX_FIFO_EMPTY 0x200 - -typedef struct _uart_t -{ - /* 0x00 */ u32 UART_THR_DLAB; - /* 0x04 */ u32 UART_IER_DLAB; - /* 0x08 */ u32 UART_IIR_FCR; - /* 0x0C */ u32 UART_LCR; - /* 0x10 */ u32 UART_MCR; - /* 0x14 */ u32 UART_LSR; - /* 0x18 */ u32 UART_MSR; - /* 0x1C */ u32 UART_SPR; - /* 0x20 */ u32 UART_IRDA_CSR; - /* 0x24 */ u32 UART_RX_FIFO_CFG; - /* 0x28 */ u32 UART_MIE; - /* 0x2C */ u32 UART_VENDOR_STATUS; - /* 0x30 */ u8 _pad_30[0x0C]; - /* 0x3C */ u32 UART_ASR; -} uart_t; - -void uart_init(u32 idx, u32 baud); -void uart_wait_idle(u32 idx, u32 which); -void uart_send(u32 idx, u8 *buf, u32 len); -void uart_recv(u32 idx, u8 *buf, u32 len); - -#endif diff --git a/fusee/fusee-primary/src/hwinit/util.c b/fusee/fusee-primary/src/hwinit/util.c deleted file mode 100644 index 780b31177..000000000 --- a/fusee/fusee-primary/src/hwinit/util.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "util.h" -#include "t210.h" - -void sleep(u32 ticks) -{ - u32 start = TMR(0x10); - while (TMR(0x10) - start <= ticks) - ; -} - -void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) -{ - for(u32 i = 0; i < num_ops; i++) - base[ops[i].off] = ops[i].val; -} - diff --git a/fusee/fusee-primary/src/hwinit/util.h b/fusee/fusee-primary/src/hwinit/util.h deleted file mode 100644 index 13bc8024f..000000000 --- a/fusee/fusee-primary/src/hwinit/util.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _UTIL_H_ -#define _UTIL_H_ - -#include "types.h" -#pragma GCC diagnostic ignored "-Wparentheses" -#pragma GCC diagnostic ignored "-Wunused-variable" - -typedef struct _cfg_op_t -{ - u32 off; - u32 val; -} cfg_op_t; - -void sleep(u32 ticks); -void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); - -#endif diff --git a/fusee/fusee-primary/src/i2c.c b/fusee/fusee-primary/src/i2c.c new file mode 100644 index 000000000..a98d7fa6e --- /dev/null +++ b/fusee/fusee-primary/src/i2c.c @@ -0,0 +1,205 @@ +#include "i2c.h" +#include "utils.h" +#include "timers.h" + +/* Prototypes for internal commands. */ +volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id); +void i2c_load_config(volatile tegra_i2c_t *regs); + +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size); +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size); + +bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size); +bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size); + +/* Initialize I2C based on registers. */ +void i2c_init(unsigned int id) { + volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); + + /* Setup divisor, and clear the bus. */ + regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; + regs->I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; + + /* Load hardware configuration. */ + i2c_load_config(regs); + + /* Wait a while until BUS_CLEAR_DONE is set. */ + for (unsigned int i = 0; i < 10; i++) { + udelay(20000); + if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { + break; + } + } + + /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ + regs->I2C_I2C_BUS_CLEAR_STATUS_0; + + /* Read and set the Interrupt Status. */ + uint32_t int_status = regs->I2C_INTERRUPT_STATUS_REGISTER_0; + regs->I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; +} + +/* Sets a bit in a PMIC register over I2C during CPU shutdown. */ +void i2c_send_pmic_cpu_shutdown_cmd(void) { + uint32_t val = 0; + /* PMIC == Device 4:3C. */ + i2c_query(4, 0x3C, 0x41, &val, 1); + val |= 4; + i2c_send(4, 0x3C, 0x41, &val, 1); +} + +/* Queries the value of TI charger bit over I2C. */ +bool i2c_query_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(0, 0x6B, 0, &val, 1); + return (val & 0x80) != 0; +} + +/* Clears TI charger bit over I2C. */ +void i2c_clear_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(0, 0x6B, 0, &val, 1); + val &= 0x7F; + i2c_send(0, 0x6B, 0, &val, 1); +} + +/* Sets TI charger bit over I2C. */ +void i2c_set_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(0, 0x6B, 0, &val, 1); + val |= 0x80; + i2c_send(0, 0x6B, 0, &val, 1); +} + +/* Get registers pointer based on I2C ID. */ +volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { + switch (id) { + case 0: + return I2C1_REGS; + case 1: + return I2C2_REGS; + case 2: + return I2C3_REGS; + case 3: + return I2C4_REGS; + case 4: + return I2C5_REGS; + case 5: + return I2C6_REGS; + default: + generic_panic(); + } + return NULL; +} + +/* Load hardware config for I2C4. */ +void i2c_load_config(volatile tegra_i2c_t *regs) { + /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ + regs->I2C_I2C_CONFIG_LOAD_0 = 0x25; + + /* Wait a bit for master config to be loaded. */ + for (unsigned int i = 0; i < 20; i++) { + udelay(1); + if (!(regs->I2C_I2C_CONFIG_LOAD_0 & 1)) { + break; + } + } +} + +/* Reads a register from a device over I2C, writes result to output. */ +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) { + volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); + uint32_t val = r; + + /* Write single byte register ID to device. */ + if (!i2c_write(regs, device, &val, 1)) { + return false; + } + /* Limit output size to 32-bits. */ + if (dst_size > 4) { + return false; + } + + return i2c_read(regs, device, dst, dst_size); +} + +/* Writes a value to a register over I2C. */ +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) { + uint32_t val = r; + if (src_size == 0) { + return true; + } else if (src_size <= 3) { + memcpy(((uint8_t *)&val) + 1, src, src_size); + return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1); + } else { + return false; + } +} + +/* Writes bytes to device over I2C. */ +bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) { + if (src_size > 4) { + return false; + } else if (src_size == 0) { + return true; + } + + /* Set device for 7-bit write mode. */ + regs->I2C_I2C_CMD_ADDR0_0 = device << 1; + + /* Load in data to write. */ + regs->I2C_I2C_CMD_DATA1_0 = read32le(src, 0); + + /* Set config with LENGTH = src_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + regs->I2C_I2C_CNFG_0 = ((src_size << 1) - 2) | 0x2800; + + i2c_load_config(regs); + + /* Config |= SEND; */ + regs->I2C_I2C_CNFG_0 |= 0x200; + + + while (regs->I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ + return (regs->I2C_I2C_STATUS_0 & 0xF) == 0; +} + +/* Reads bytes from device over I2C. */ +bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) { + if (dst_size > 4) { + return false; + } else if (dst_size == 0) { + return true; + } + + /* Set device for 7-bit read mode. */ + regs->I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1; + + /* Set config with LENGTH = dst_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + regs->I2C_I2C_CNFG_0 = ((dst_size << 1) - 2) | 0x2840; + + i2c_load_config(regs); + + /* Config |= SEND; */ + regs->I2C_I2C_CNFG_0 |= 0x200; + + + while (regs->I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Ensure success. */ + if ((regs->I2C_I2C_STATUS_0 & 0xF) != 0) { + return false; + } + + uint32_t val = regs->I2C_I2C_CMD_DATA1_0; + memcpy(dst, &val, dst_size); + return true; +} diff --git a/fusee/fusee-primary/src/i2c.h b/fusee/fusee-primary/src/i2c.h new file mode 100644 index 000000000..e07ed3349 --- /dev/null +++ b/fusee/fusee-primary/src/i2c.h @@ -0,0 +1,71 @@ +#ifndef FUSEE_I2C_H +#define FUSEE_I2C_H + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#define I2C234_BASE 0x7000C000 +#define I2C56_BASE 0x7000D000 + +typedef struct { + uint32_t I2C_I2C_CNFG_0; + uint32_t I2C_I2C_CMD_ADDR0_0; + uint32_t I2C_I2C_CMD_ADDR1_0; + uint32_t I2C_I2C_CMD_DATA1_0; + uint32_t I2C_I2C_CMD_DATA2_0; + uint32_t _0x14; + uint32_t _0x18; + uint32_t I2C_I2C_STATUS_0; + uint32_t I2C_I2C_SL_CNFG_0; + uint32_t I2C_I2C_SL_RCVD_0; + uint32_t I2C_I2C_SL_STATUS_0; + uint32_t I2C_I2C_SL_ADDR1_0; + uint32_t I2C_I2C_SL_ADDR2_0; + uint32_t I2C_I2C_TLOW_SEXT_0; + uint32_t _0x38; + uint32_t I2C_I2C_SL_DELAY_COUNT_0; + uint32_t I2C_I2C_SL_INT_MASK_0; + uint32_t I2C_I2C_SL_INT_SOURCE_0; + uint32_t I2C_I2C_SL_INT_SET_0; + uint32_t _0x4C; + uint32_t I2C_I2C_TX_PACKET_FIFO_0; + uint32_t I2C_I2C_RX_FIFO_0; + uint32_t I2C_PACKET_TRANSFER_STATUS_0; + uint32_t I2C_FIFO_CONTROL_0; + uint32_t I2C_FIFO_STATUS_0; + uint32_t I2C_INTERRUPT_MASK_REGISTER_0; + uint32_t I2C_INTERRUPT_STATUS_REGISTER_0; + uint32_t I2C_I2C_CLK_DIVISOR_REGISTER_0; + uint32_t I2C_I2C_INTERRUPT_SOURCE_REGISTER_0; + uint32_t I2C_I2C_INTERRUPT_SET_REGISTER_0; + uint32_t I2C_I2C_SLV_TX_PACKET_FIFO_0; + uint32_t I2C_I2C_SLV_RX_FIFO_0; + uint32_t I2C_I2C_SLV_PACKET_STATUS_0; + uint32_t I2C_I2C_BUS_CLEAR_CONFIG_0; + uint32_t I2C_I2C_BUS_CLEAR_STATUS_0; + uint32_t I2C_I2C_CONFIG_LOAD_0; + uint32_t _0x90; + uint32_t I2C_I2C_INTERFACE_TIMING_0_0; + uint32_t I2C_I2C_INTERFACE_TIMING_1_0; + uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0; + uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; +} tegra_i2c_t; + +#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x000)) +#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x400)) +#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x500)) +#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x700)) +#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000)) +#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100)) + +void i2c_init(unsigned int id); +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size); +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size); + +void i2c_send_pmic_cpu_shutdown_cmd(void); +bool i2c_query_ti_charger_bit_7(void); +void i2c_clear_ti_charger_bit_7(void); +void i2c_set_ti_charger_bit_7(void); + +#endif diff --git a/fusee/fusee-primary/src/lib/lz.c b/fusee/fusee-primary/src/lib/lz.c new file mode 100644 index 000000000..a17c6e49f --- /dev/null +++ b/fusee/fusee-primary/src/lib/lz.c @@ -0,0 +1,179 @@ +/************************************************************************* +* Name: lz.c +* Author: Marcus Geelnard +* Description: LZ77 coder/decoder implementation. +* Reentrant: Yes +* +* The LZ77 compression scheme is a substitutional compression scheme +* proposed by Abraham Lempel and Jakob Ziv in 1977. It is very simple in +* its design, and uses no fancy bit level compression. +* +* This is my first attempt at an implementation of a LZ77 code/decoder. +* +* The principle of the LZ77 compression algorithm is to store repeated +* occurrences of strings as references to previous occurrences of the same +* string. The point is that the reference consumes less space than the +* string itself, provided that the string is long enough (in this +* implementation, the string has to be at least 4 bytes long, since the +* minimum coded reference is 3 bytes long). Also note that the term +* "string" refers to any kind of byte sequence (it does not have to be +* an ASCII string, for instance). +* +* The coder uses a brute force approach to finding string matches in the +* history buffer (or "sliding window", if you wish), which is very, very +* slow. I recon the complexity is somewhere between O(n^2) and O(n^3), +* depending on the input data. +* +* There is also a faster implementation that uses a large working buffer +* in which a "jump table" is stored, which is used to quickly find +* possible string matches (see the source code for LZ_CompressFast() for +* more information). The faster method is an order of magnitude faster, +* but still quite slow compared to other compression methods. +* +* The upside is that decompression is very fast, and the compression ratio +* is often very good. +* +* The reference to a string is coded as a (length,offset) pair, where the +* length indicates the length of the string, and the offset gives the +* offset from the current data position. To distinguish between string +* references and literal strings (uncompressed bytes), a string reference +* is preceded by a marker byte, which is chosen as the least common byte +* symbol in the input data stream (this marker byte is stored in the +* output stream as the first byte). +* +* Occurrences of the marker byte in the stream are encoded as the marker +* byte followed by a zero byte, which means that occurrences of the marker +* byte have to be coded with two bytes. +* +* The lengths and offsets are coded in a variable length fashion, allowing +* values of any magnitude (up to 4294967295 in this implementation). +* +* With this compression scheme, the worst case compression result is +* (257/256)*insize + 1. +* +*------------------------------------------------------------------------- +* Copyright (c) 2003-2006 Marcus Geelnard +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would +* be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not +* be misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source +* distribution. +* +* Marcus Geelnard +* marcus.geelnard at home.se +*************************************************************************/ + + +/************************************************************************* +* INTERNAL FUNCTIONS * +*************************************************************************/ + + +/************************************************************************* +* _LZ_ReadVarSize() - Read unsigned integer with variable number of +* bytes depending on value. +*************************************************************************/ + +static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf ) +{ + unsigned int y, b, num_bytes; + + /* Read complete value (stop when byte contains zero in 8:th bit) */ + y = 0; + num_bytes = 0; + do + { + b = (unsigned int) (*buf ++); + y = (y << 7) | (b & 0x0000007f); + ++ num_bytes; + } + while( b & 0x00000080 ); + + /* Store value in x */ + *x = y; + + /* Return number of bytes read */ + return num_bytes; +} + + + +/************************************************************************* +* PUBLIC FUNCTIONS * +*************************************************************************/ + + +/************************************************************************* +* LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder. +* in - Input (compressed) buffer. +* out - Output (uncompressed) buffer. This buffer must be large +* enough to hold the uncompressed data. +* insize - Number of input bytes. +*************************************************************************/ + +void LZ_Uncompress( const unsigned char *in, unsigned char *out, + unsigned int insize ) +{ + unsigned char marker, symbol; + unsigned int i, inpos, outpos, length, offset; + + /* Do we have anything to uncompress? */ + if( insize < 1 ) + { + return; + } + + /* Get marker symbol from input stream */ + marker = in[ 0 ]; + inpos = 1; + + /* Main decompression loop */ + outpos = 0; + do + { + symbol = in[ inpos ++ ]; + if( symbol == marker ) + { + /* We had a marker byte */ + if( in[ inpos ] == 0 ) + { + /* It was a single occurrence of the marker byte */ + out[ outpos ++ ] = marker; + ++ inpos; + } + else + { + /* Extract true length and offset */ + inpos += _LZ_ReadVarSize( &length, &in[ inpos ] ); + inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] ); + + /* Copy corresponding data from history window */ + for( i = 0; i < length; ++ i ) + { + out[ outpos ] = out[ outpos - offset ]; + ++ outpos; + } + } + } + else + { + /* No marker, plain copy */ + out[ outpos ++ ] = symbol; + } + } + while( inpos < insize ); +} diff --git a/fusee/fusee-primary/src/lib/lz.h b/fusee/fusee-primary/src/lib/lz.h new file mode 100644 index 000000000..6f31b4a14 --- /dev/null +++ b/fusee/fusee-primary/src/lib/lz.h @@ -0,0 +1,52 @@ +/************************************************************************* +* Name: lz.h +* Author: Marcus Geelnard +* Description: LZ77 coder/decoder interface. +* Reentrant: Yes +*------------------------------------------------------------------------- +* Copyright (c) 2003-2006 Marcus Geelnard +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would +* be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not +* be misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source +* distribution. +* +* Marcus Geelnard +* marcus.geelnard at home.se +*************************************************************************/ + +#ifndef _lz_h_ +#define _lz_h_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************* +* Function prototypes +*************************************************************************/ + +void LZ_Uncompress( const unsigned char *in, unsigned char *out, + unsigned int insize ); + + +#ifdef __cplusplus +} +#endif + +#endif /* _lz_h_ */ diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index c5a5a5d3c..b1552b7cd 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -2,8 +2,7 @@ #include "exception_handlers.h" #include "panic.h" #include "hwinit.h" -#include "fuse.h" -#include "se.h" +#include "di.h" #include "timers.h" #include "fs_utils.h" #include "stage2.h" @@ -49,32 +48,15 @@ static const char *load_config(void) { return bct0; } -static void load_sbk(void) { - uint32_t sbk[0x4]; - /* Load the SBK into the security engine, if relevant. */ - memcpy(sbk, (void *)get_fuse_chip_regs()->FUSE_PRIVATE_KEY, 0x10); - for (unsigned int i = 0; i < 4; i++) { - if (sbk[i] != 0xFFFFFFFF) { - set_aes_keyslot(0xE, sbk, 0x10); - break; - } - } -} - static void setup_env(void) { g_framebuffer = (void *)0xC0000000; - /* Initialize DRAM. */ - /* TODO: What can be stripped out to make this minimal? */ + /* Initialize hardware. */ nx_hwinit(); /* Check for panics. */ check_and_display_panic(); - /* Try to load the SBK into the security engine, if possible. */ - /* TODO: Should this be done later? */ - load_sbk(); - /* Zero-fill the framebuffer and register it as printk provider. */ video_init(g_framebuffer); @@ -86,7 +68,7 @@ static void setup_env(void) { /* Turn on the backlight after initializing the lfb */ /* to avoid flickering. */ - display_enable_backlight(true); + display_backlight(true); /* Set up the exception handlers. */ setup_exception_handlers(); @@ -99,7 +81,7 @@ static void cleanup_env(void) { /* Unmount the SD card. */ unmount_sd(); - display_enable_backlight(false); + display_backlight(false); display_end(); } @@ -123,7 +105,7 @@ int main(void) { /* Say hello. */ printk("Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); printk("Using color linear framebuffer at 0x%p!\n", g_framebuffer); - + /* Load the BCT0 configuration ini off of the SD. */ bct0 = load_config(); diff --git a/fusee/fusee-primary/src/max77620.h b/fusee/fusee-primary/src/max77620.h new file mode 100644 index 000000000..ad22a06b5 --- /dev/null +++ b/fusee/fusee-primary/src/max77620.h @@ -0,0 +1,326 @@ +/* + * Defining registers address and its bit definitions of MAX77620 and MAX20024 + * + * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#ifndef _MFD_MAX77620_H_ +#define _MFD_MAX77620_H_ + +/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ +#define MAX77620_REG_CNFGGLBL1 0x00 +#define MAX77620_REG_CNFGGLBL2 0x01 +#define MAX77620_REG_CNFGGLBL3 0x02 +#define MAX77620_REG_CNFG1_32K 0x03 +#define MAX77620_REG_CNFGBBC 0x04 +#define MAX77620_REG_IRQTOP 0x05 +#define MAX77620_REG_INTLBT 0x06 +#define MAX77620_REG_IRQSD 0x07 +#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 +#define MAX77620_REG_IRQ_LVL2_L8 0x09 +#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A +#define MAX77620_REG_ONOFFIRQ 0x0B +#define MAX77620_REG_NVERC 0x0C +#define MAX77620_REG_IRQTOPM 0x0D +#define MAX77620_REG_INTENLBT 0x0E +#define MAX77620_REG_IRQMASKSD 0x0F +#define MAX77620_REG_IRQ_MSK_L0_7 0x10 +#define MAX77620_REG_IRQ_MSK_L8 0x11 +#define MAX77620_REG_ONOFFIRQM 0x12 +#define MAX77620_REG_STATLBT 0x13 +#define MAX77620_REG_STATSD 0x14 +#define MAX77620_REG_ONOFFSTAT 0x15 + +/* SD and LDO Registers */ +#define MAX77620_REG_SD0 0x16 +#define MAX77620_REG_SD1 0x17 +#define MAX77620_REG_SD2 0x18 +#define MAX77620_REG_SD3 0x19 +#define MAX77620_REG_SD4 0x1A +#define MAX77620_REG_DVSSD0 0x1B +#define MAX77620_REG_DVSSD1 0x1C +#define MAX77620_REG_SD0_CFG 0x1D +#define MAX77620_REG_SD1_CFG 0x1E +#define MAX77620_REG_SD2_CFG 0x1F +#define MAX77620_REG_SD3_CFG 0x20 +#define MAX77620_REG_SD4_CFG 0x21 +#define MAX77620_REG_SD_CFG2 0x22 +#define MAX77620_REG_LDO0_CFG 0x23 +#define MAX77620_REG_LDO0_CFG2 0x24 +#define MAX77620_REG_LDO1_CFG 0x25 +#define MAX77620_REG_LDO1_CFG2 0x26 +#define MAX77620_REG_LDO2_CFG 0x27 +#define MAX77620_REG_LDO2_CFG2 0x28 +#define MAX77620_REG_LDO3_CFG 0x29 +#define MAX77620_REG_LDO3_CFG2 0x2A +#define MAX77620_REG_LDO4_CFG 0x2B +#define MAX77620_REG_LDO4_CFG2 0x2C +#define MAX77620_REG_LDO5_CFG 0x2D +#define MAX77620_REG_LDO5_CFG2 0x2E +#define MAX77620_REG_LDO6_CFG 0x2F +#define MAX77620_REG_LDO6_CFG2 0x30 +#define MAX77620_REG_LDO7_CFG 0x31 +#define MAX77620_REG_LDO7_CFG2 0x32 +#define MAX77620_REG_LDO8_CFG 0x33 +#define MAX77620_REG_LDO8_CFG2 0x34 +#define MAX77620_REG_LDO_CFG3 0x35 + +#define MAX77620_LDO_SLEW_RATE_MASK 0x1 + +/* LDO Configuration 3 */ +#define MAX77620_TRACK4_MASK (1 << 5) +#define MAX77620_TRACK4_SHIFT 5 + +/* Voltage */ +#define MAX77620_SDX_VOLT_MASK 0xFF +#define MAX77620_SD0_VOLT_MASK 0x3F +#define MAX77620_SD1_VOLT_MASK 0x7F +#define MAX77620_LDO_VOLT_MASK 0x3F + +#define MAX77620_REG_GPIO0 0x36 +#define MAX77620_REG_GPIO1 0x37 +#define MAX77620_REG_GPIO2 0x38 +#define MAX77620_REG_GPIO3 0x39 +#define MAX77620_REG_GPIO4 0x3A +#define MAX77620_REG_GPIO5 0x3B +#define MAX77620_REG_GPIO6 0x3C +#define MAX77620_REG_GPIO7 0x3D +#define MAX77620_REG_PUE_GPIO 0x3E +#define MAX77620_REG_PDE_GPIO 0x3F +#define MAX77620_REG_AME_GPIO 0x40 +#define MAX77620_REG_ONOFFCNFG1 0x41 +#define MAX77620_REG_ONOFFCNFG2 0x42 + +/* FPS Registers */ +#define MAX77620_REG_FPS_CFG0 0x43 +#define MAX77620_REG_FPS_CFG1 0x44 +#define MAX77620_REG_FPS_CFG2 0x45 +#define MAX77620_REG_FPS_LDO0 0x46 +#define MAX77620_REG_FPS_LDO1 0x47 +#define MAX77620_REG_FPS_LDO2 0x48 +#define MAX77620_REG_FPS_LDO3 0x49 +#define MAX77620_REG_FPS_LDO4 0x4A +#define MAX77620_REG_FPS_LDO5 0x4B +#define MAX77620_REG_FPS_LDO6 0x4C +#define MAX77620_REG_FPS_LDO7 0x4D +#define MAX77620_REG_FPS_LDO8 0x4E +#define MAX77620_REG_FPS_SD0 0x4F +#define MAX77620_REG_FPS_SD1 0x50 +#define MAX77620_REG_FPS_SD2 0x51 +#define MAX77620_REG_FPS_SD3 0x52 +#define MAX77620_REG_FPS_SD4 0x53 +#define MAX77620_REG_FPS_NONE 0 + +#define MAX77620_FPS_SRC_MASK 0xC0 +#define MAX77620_FPS_SRC_SHIFT 6 +#define MAX77620_FPS_PU_PERIOD_MASK 0x38 +#define MAX77620_FPS_PU_PERIOD_SHIFT 3 +#define MAX77620_FPS_PD_PERIOD_MASK 0x07 +#define MAX77620_FPS_PD_PERIOD_SHIFT 0 +#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 +#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 +#define MAX77620_FPS_EN_SRC_MASK 0x06 +#define MAX77620_FPS_EN_SRC_SHIFT 1 +#define MAX77620_FPS_ENFPS_SW_MASK 0x01 +#define MAX77620_FPS_ENFPS_SW 0x01 + +/* Minimum and maximum FPS period time (in microseconds) are + * different for MAX77620 and Max20024. + */ +#define MAX77620_FPS_PERIOD_MIN_US 40 +#define MAX20024_FPS_PERIOD_MIN_US 20 + +#define MAX77620_FPS_PERIOD_MAX_US 2560 +#define MAX20024_FPS_PERIOD_MAX_US 5120 + +#define MAX77620_REG_FPS_GPIO1 0x54 +#define MAX77620_REG_FPS_GPIO2 0x55 +#define MAX77620_REG_FPS_GPIO3 0x56 +#define MAX77620_REG_FPS_RSO 0x57 +#define MAX77620_REG_CID0 0x58 +#define MAX77620_REG_CID1 0x59 +#define MAX77620_REG_CID2 0x5A +#define MAX77620_REG_CID3 0x5B +#define MAX77620_REG_CID4 0x5C +#define MAX77620_REG_CID5 0x5D + +#define MAX77620_REG_DVSSD4 0x5E +#define MAX20024_REG_MAX_ADD 0x70 + +#define MAX77620_CID_DIDM_MASK 0xF0 +#define MAX77620_CID_DIDM_SHIFT 4 + +/* CNCG2SD */ +#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) +#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) + +/* Device Identification Metal */ +#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) +/* Device Indentification OTP */ +#define MAX77620_CID5_DIDO(n) ((n) & 0xF) + +/* SD CNFG1 */ +#define MAX77620_SD_SR_MASK 0xC0 +#define MAX77620_SD_SR_SHIFT 6 +#define MAX77620_SD_POWER_MODE_MASK 0x30 +#define MAX77620_SD_POWER_MODE_SHIFT 4 +#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) +#define MAX77620_SD_CFG1_ADE_DISABLE 0 +#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) +#define MAX77620_SD_FPWM_MASK 0x04 +#define MAX77620_SD_FPWM_SHIFT 2 +#define MAX77620_SD_FSRADE_MASK 0x01 +#define MAX77620_SD_FSRADE_SHIFT 0 +#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) +#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 +#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) +#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) +#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) +#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 +#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) + +/* LDO_CNFG2 */ +#define MAX77620_LDO_POWER_MODE_MASK 0xC0 +#define MAX77620_LDO_POWER_MODE_SHIFT 6 +#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) +#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) +#define MAX77620_LDO_CFG2_ADE_DISABLE 0 +#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) +#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) +#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) +#define MAX77620_LDO_CFG2_SS_SLOW 0 + +#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) +#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) +#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) +#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) +#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) +#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) +#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) + +#define MAX77620_IRQ_LBM_MASK (1 << 3) +#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) +#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) + +#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) +#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) +#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0 +#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) +#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) +#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0 +#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0 +#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) +#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) +#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) +#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) +#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) +#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) +#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) +#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) + +#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) +#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) +#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) +#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) +#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) +#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) +#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) +#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) + +#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) + +#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) +#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 +#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 +#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) +#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) +#define MAX20024_ONOFFCNFG1_CLRSE 0x18 + +#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) +#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) +#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) +#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) +#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) + +#define MAX77620_GLBLM_MASK (1 << 0) + +#define MAX77620_WDTC_MASK 0x3 +#define MAX77620_WDTOFFC (1 << 4) +#define MAX77620_WDTSLPC (1 << 3) +#define MAX77620_WDTEN (1 << 2) + +#define MAX77620_TWD_MASK 0x3 +#define MAX77620_TWD_2s 0x0 +#define MAX77620_TWD_16s 0x1 +#define MAX77620_TWD_64s 0x2 +#define MAX77620_TWD_128s 0x3 + +#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) +#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) +#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) +#define MAX77620_CNFGGLBL1_LBHYST_N (1 << 4) +#define MAX77620_CNFGGLBL1_LBDAC 0x0E +#define MAX77620_CNFGGLBL1_LBDAC_N (1 << 1) +#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) + +/* CNFG BBC registers */ +#define MAX77620_CNFGBBC_ENABLE (1 << 0) +#define MAX77620_CNFGBBC_CURRENT_MASK 0x06 +#define MAX77620_CNFGBBC_CURRENT_SHIFT 1 +#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 +#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 +#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) +#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 +#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 + +#define MAX77620_FPS_COUNT 3 + +/* Interrupts */ +enum { + MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ + MAX77620_IRQ_TOP_SD, /* SD power fail */ + MAX77620_IRQ_TOP_LDO, /* LDO power fail */ + MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ + MAX77620_IRQ_TOP_RTC, /* RTC */ + MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ + MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ + MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ + MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ + MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ +}; + +/* GPIOs */ +enum { + MAX77620_GPIO0, + MAX77620_GPIO1, + MAX77620_GPIO2, + MAX77620_GPIO3, + MAX77620_GPIO4, + MAX77620_GPIO5, + MAX77620_GPIO6, + MAX77620_GPIO7, + MAX77620_GPIO_NR, +}; + +/* FPS Source */ +enum max77620_fps_src { + MAX77620_FPS_SRC_0, + MAX77620_FPS_SRC_1, + MAX77620_FPS_SRC_2, + MAX77620_FPS_SRC_NONE, + MAX77620_FPS_SRC_DEF, +}; + +enum max77620_chip_id { + MAX77620, + MAX20024, +}; + +#endif /* _MFD_MAX77620_H_ */ diff --git a/fusee/fusee-primary/src/max7762x.c b/fusee/fusee-primary/src/max7762x.c new file mode 100644 index 000000000..419a13bce --- /dev/null +++ b/fusee/fusee-primary/src/max7762x.c @@ -0,0 +1,161 @@ +#include <stdint.h> + +#include "max7762x.h" +#include "max77620.h" +#include "i2c.h" +#include "timers.h" + +#define REGULATOR_SD 0 +#define REGULATOR_LDO 1 + +typedef struct _max77620_regulator_t +{ + uint8_t type; + const char *name; + uint8_t reg_sd; + uint32_t mv_step; + uint32_t mv_min; + uint32_t mv_default; + uint32_t mv_max; + uint8_t volt_addr; + uint8_t cfg_addr; + uint8_t volt_mask; + uint8_t enable_mask; + uint8_t enable_shift; + uint8_t status_mask; + + uint8_t fps_addr; + uint8_t fps_src; + uint8_t pd_period; + uint8_t pu_period; +} max77620_regulator_t; + +static const max77620_regulator_t _pmic_regulators[] = { + { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, 0x3F, 0x30, 4, 0x80, 0x4F, 1, 7, 1 }, + { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, 0x3F, 0x30, 4, 0x40, 0x50, 0, 1, 5 }, + { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, 0xFF, 0x30, 4, 0x20, 0x51, 1, 5, 2 }, + { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, 0xFF, 0x30, 4, 0x10, 0x52, 0, 3, 3 }, + { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, 0x3F, 0xC0, 6, 0x00, 0x46, 3, 7, 0 }, + { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, 0x3F, 0xC0, 6, 0x00, 0x47, 3, 7, 0 }, + { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, 0x3F, 0xC0, 6, 0x00, 0x48, 3, 7, 0 }, + { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, 0x3F, 0xC0, 6, 0x00, 0x49, 3, 7, 0 }, + { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4A, 0, 7, 1 }, + { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4B, 3, 7, 0 }, + { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4C, 3, 7, 0 }, + { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4D, 1, 4, 3 }, + { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4E, 3, 7, 0 } +}; + +int max77620_regulator_get_status(uint32_t id) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + uint8_t val = 0; + + if (reg->type == REGULATOR_SD) { + if (i2c_query(4, 0x3C, MAX77620_REG_STATSD, &val, 1)) + return (val & reg->status_mask) ? 0 : 1; + } + + if (i2c_query(4, 0x3C, reg->cfg_addr, &val, 1)) + return (val & 8) ? 0 : 1; + + return 0; +} + +int max77620_regulator_config_fps(uint32_t id) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); + + if (i2c_send(4, 0x3C, reg->fps_addr, &val, 1)) { + return 1; + } + + return 0; +} + +int max77620_regulator_set_voltage(uint32_t id, uint32_t mv) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + + if ((mv < reg->mv_default) || (mv > reg->mv_max)) + return 0; + + uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; + uint8_t val = 0; + + if (i2c_query(4, 0x3C, reg->volt_addr, &val, 1)) + { + val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask)); + + if (i2c_send(4, 0x3C, reg->volt_addr, &val, 1)) + { + udelay(1000); + return 1; + } + } + + return 0; +} + +int max77620_regulator_enable(uint32_t id, int enable) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + + uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr; + uint8_t val = 0; + + if (i2c_query(4, 0x3C, addr, &val, 1)) + { + if (enable) + val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); + else + val &= ~reg->enable_mask; + + if (i2c_send(4, 0x3C, addr, &val, 1)) + { + udelay(1000); + return 1; + } + } + + return 0; +} + +void max77620_config_default() +{ + for (uint32_t i = 1; i <= REGULATOR_MAX; i++) + { + uint8_t val = 0; + if (i2c_query(4, 0x3C, MAX77620_REG_CID4, &val, 1)) + { + max77620_regulator_config_fps(i); + max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); + + if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) { + max77620_regulator_enable(i, 1); + } + } + } + + uint8_t val = 4; + i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); +} + +void max77620_low_battery_monitor_config() +{ + uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N); + i2c_send(4, 0x3C, MAX77620_REG_CNFGGLBL1, &val, 1); +} diff --git a/fusee/fusee-primary/src/hwinit/max7762x.h b/fusee/fusee-primary/src/max7762x.h old mode 100755 new mode 100644 similarity index 62% rename from fusee/fusee-primary/src/hwinit/max7762x.h rename to fusee/fusee-primary/src/max7762x.h index 05434956e..c106a27d4 --- a/fusee/fusee-primary/src/hwinit/max7762x.h +++ b/fusee/fusee-primary/src/max7762x.h @@ -1,34 +1,16 @@ -/* -* Copyright (c) 2018 naehrwert -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _MAX7762X_H_ -#define _MAX7762X_H_ - -#include "types.h" +#ifndef FUSEE_MAX7762X_H_ +#define FUSEE_MAX7762X_H_ /* * Switch Power domains (max77620): * Name | Usage | uV step | uV min | uV default | uV max | Init *-------+---------------+---------+--------+------------+---------+------------------ * sd0 | core | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1) -* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1) +* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1) * sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv) * sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 | -* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1) -* ldo1 | XUSB | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) +* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1) +* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) * ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 | * ldo3 | | 50000 | 800000 | 3100000 | 3100000 | * ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | @@ -59,10 +41,11 @@ #define REGULATOR_LDO8 12 #define REGULATOR_MAX 12 -int max77620_regulator_get_status(u32 id); -int max77620_regulator_config_fps(u32 id); -int max77620_regulator_set_voltage(u32 id, u32 mv); -int max77620_regulator_enable(u32 id, int enable); +int max77620_regulator_get_status(uint32_t id); +int max77620_regulator_config_fps(uint32_t id); +int max77620_regulator_set_voltage(uint32_t id, uint32_t mv); +int max77620_regulator_enable(uint32_t id, int enable); void max77620_config_default(); +void max77620_low_battery_monitor_config(); #endif diff --git a/fusee/fusee-primary/src/mc.c b/fusee/fusee-primary/src/mc.c new file mode 100644 index 000000000..a98b6fbf7 --- /dev/null +++ b/fusee/fusee-primary/src/mc.c @@ -0,0 +1,146 @@ +#include "mc.h" +#include "car.h" +#include "timers.h" + +void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock) +{ + MAKE_MC_REG(MC_SEC_CARVEOUT_BOM) = bom; + MAKE_MC_REG(MC_SEC_CARVEOUT_SIZE_MB) = size1mb; + + if (lock) + MAKE_MC_REG(MC_SEC_CARVEOUT_REG_CTRL) = 1; +} + +void mc_config_carveout() +{ + *(volatile uint32_t *)0x8005FFFC = 0xC0EDBBCC; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1; + + mc_config_tsec_carveout(0, 0, 1); + + MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = 1; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CFG0) = 0x4000006; + + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0x3000000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0x300; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CFG0) = 0x4401E7E; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CFG0) = 0x8F; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F; +} + +void mc_config_carveout_finalize() +{ + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = 0x3000000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = 0x300; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CFG0) = 0x440167E; +} + +void mc_enable_ahb_redirect() +{ + volatile tegra_car_t *car = car_get_regs(); + car->lvl2_clk_gate_ovrd = ((car->lvl2_clk_gate_ovrd & 0xFFF7FFFF) | 0x80000); + + MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000; + MAKE_MC_REG(MC_IRAM_TOM) = 0x4003F000; +} + +void mc_disable_ahb_redirect() +{ + volatile tegra_car_t *car = car_get_regs(); + + MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; + MAKE_MC_REG(MC_IRAM_TOM) = 0; + + car->lvl2_clk_gate_ovrd &= 0xFFF7FFFF; +} + +void mc_enable() +{ + volatile tegra_car_t *car = car_get_regs(); + + /* Set EMC clock source. */ + car->clk_source_emc = ((car->clk_source_emc & 0x1FFFFFFF) | 0x40000000); + + /* Enable MIPI CAL clock. */ + car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFDFFFFFF) | 0x2000000); + + /* Enable MC clock. */ + car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFFFFFFFE) | 1); + + /* Enable EMC DLL clock. */ + car->clk_enb_x_set = ((car->clk_enb_x_set & 0xFFFFBFFF) | 0x4000); + + /* Clear EMC and MC reset. */ + car->rst_dev_h_set = 0x2000001; + udelay(5); + + mc_disable_ahb_redirect(); +} \ No newline at end of file diff --git a/fusee/fusee-primary/src/hwinit/mc.h b/fusee/fusee-primary/src/mc.h similarity index 98% rename from fusee/fusee-primary/src/hwinit/mc.h rename to fusee/fusee-primary/src/mc.h index 7eebdf4e0..e93bfc7bf 100644 --- a/fusee/fusee-primary/src/hwinit/mc.h +++ b/fusee/fusee-primary/src/mc.h @@ -1,18 +1,11 @@ -/* -* Copyright (c) 2014, NVIDIA Corporation. All rights reserved. -* -* This software is licensed under the terms of the GNU General Public -* License version 2, as published by the Free Software Foundation, and -* may be copied, distributed, and modified under those terms. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -*/ +#ifndef FUSEE_MC_H_ +#define FUSEE_MC_H_ -#ifndef _MC_H_ -#define _MC_ +#include <stdint.h> +#include <stdbool.h> + +#define MC_BASE 0x70019000 +#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) #define MC_INTSTATUS 0x0 #define MC_INTMASK 0x4 @@ -463,4 +456,11 @@ #define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 #define MC_DA_CONFIG0 0x9dc -#endif +void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock); +void mc_config_carveout(); +void mc_config_carveout_finalize(); +void mc_enable_ahb_redirect(); +void mc_disable_ahb_redirect(); +void mc_enable(); + +#endif \ No newline at end of file diff --git a/fusee/fusee-primary/src/panic.c b/fusee/fusee-primary/src/panic.c index b5c4591b6..ce0b54747 100644 --- a/fusee/fusee-primary/src/panic.c +++ b/fusee/fusee-primary/src/panic.c @@ -1,8 +1,8 @@ #include "panic.h" +#include "di.h" #include "pmc.h" #include "fuse.h" #include "utils.h" -#include "hwinit.h" static uint32_t g_panic_code = 0; diff --git a/fusee/fusee-primary/src/pinmux.h b/fusee/fusee-primary/src/pinmux.h index d7131d1d5..80fc3a37c 100644 --- a/fusee/fusee-primary/src/pinmux.h +++ b/fusee/fusee-primary/src/pinmux.h @@ -1,6 +1,9 @@ #ifndef FUSEE_PINMUX_H #define FUSEE_PINMUX_H +#define PINMUX_BASE 0x70003000 +#define MAKE_PINMUX_REG(n) MAKE_REG32(PINMUX_BASE + n) + #define PINMUX_TRISTATE (1 << 4) #define PINMUX_PARKED (1 << 5) #define PINMUX_INPUT (1 << 6) @@ -186,7 +189,7 @@ typedef struct { static inline volatile tegra_pinmux_t *pinmux_get_regs(void) { - return (volatile tegra_pinmux_t *)0x70003000; + return (volatile tegra_pinmux_t *)PINMUX_BASE; } #endif diff --git a/fusee/fusee-primary/src/pmc.h b/fusee/fusee-primary/src/pmc.h index 4c10d1a0e..0c851eb47 100644 --- a/fusee/fusee-primary/src/pmc.h +++ b/fusee/fusee-primary/src/pmc.h @@ -1,25 +1,49 @@ #ifndef FUSEE_PMC_H #define FUSEE_PMC_H -/* TODO: get rid of these defines; use the struct instead */ +#include <stdint.h> + #define PMC_BASE 0x7000E400 +#define MAKE_PMC_REG(n) MAKE_REG32(PMC_BASE + n) #define PMC_CONTROL_SDMMC1 (1 << 12) #define PMC_CONTROL_SDMMC3 (1 << 13) #define PMC_CONTROL_SDMMC4 (1 << 14) -#define APBDEV_PMC_CONTROL MAKE_REG32(PMC_BASE + 0x00) -#define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24) -#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30) -#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_REG32(PMC_BASE + 0x38) -#define APBDEV_PMC_SCRATCH0_0 MAKE_REG32(PMC_BASE + 0x50) -#define APBDEV_PMC_CRYPTO_OP_0 MAKE_REG32(PMC_BASE + 0xF4) -#define APBDEV_PM_0 MAKE_REG32(PMC_BASE + 0x14) -#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_REG32(PMC_BASE + 0x168) -#define APBDEV_PMC_RST_STATUS_0 MAKE_REG32(PMC_BASE + 0x1B4) -#define APBDEV_PMC_CNTRL2_0 MAKE_REG32(PMC_BASE + 0x440) -#define APBDEV_PMC_SCRATCH43_0 MAKE_REG32(PMC_BASE + 0x22C) -#define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840) +#define APBDEV_PMC_CONTROL MAKE_PMC_REG(0x00) +#define APBDEV_PM_0 MAKE_PMC_REG(0x14) +#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x24) +#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x30) +#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x38) +#define APBDEV_PMC_NO_IOPOWER_0 MAKE_PMC_REG(0x44) +#define APBDEV_PMC_SCRATCH0_0 MAKE_PMC_REG(0x50) +#define APBDEV_PMC_SCRATCH1_0 MAKE_PMC_REG(0x54) +#define APBDEV_PMC_SCRATCH20_0 MAKE_PMC_REG(0xA0) +#define APBDEV_PMC_PWR_DET_VAL_0 MAKE_PMC_REG(0xE4) +#define APBDEV_PMC_DDR_PWR_0 MAKE_PMC_REG(0xE8) +#define APBDEV_PMC_CRYPTO_OP_0 MAKE_PMC_REG(0xF4) +#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_PMC_REG(0x168) +#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4) +#define APBDEV_PMC_RST_STATUS_0 MAKE_PMC_REG(0x1B4) +#define APBDEV_PMC_IO_DPD_REQ_0 MAKE_PMC_REG(0x1B8) +#define APBDEV_PMC_IO_DPD2_REQ_0 MAKE_PMC_REG(0x1C0) +#define APBDEV_PMC_VDDP_SEL_0 MAKE_PMC_REG(0x1CC) +#define APBDEV_PMC_SCRATCH49_0 MAKE_PMC_REG(0x244) +#define APBDEV_PMC_TSC_MULT_0 MAKE_PMC_REG(0x2B4) +#define APBDEV_PMC_REG_SHORT_0 MAKE_PMC_REG(0x2CC) +#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) +#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334) +#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360) +#define APBDEV_PMC_SECURE_SCRATCH49_0 MAKE_PMC_REG(0x3A4) +#define APBDEV_PMC_CNTRL2_0 MAKE_PMC_REG(0x440) +#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464) +#define APBDEV_PMC_UTMIP_PAD_CFG1_0 MAKE_PMC_REG(0x4C4) +#define APBDEV_PMC_UTMIP_PAD_CFG3_0 MAKE_PMC_REG(0x4CC) +#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4) +#define APBDEV_PMC_SCRATCH43_0 MAKE_PMC_REG(0x22C) +#define APBDEV_PMC_SCRATCH188_0 MAKE_PMC_REG(0x810) +#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) +#define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840) typedef struct { uint32_t cntrl; @@ -42,7 +66,6 @@ typedef struct { uint32_t no_iopower; uint32_t pwr_det; uint32_t pwr_det_latch; - uint32_t scratch0; uint32_t scratch1; uint32_t scratch2; @@ -67,14 +90,12 @@ typedef struct { uint32_t scratch21; uint32_t scratch22; uint32_t scratch23; - uint32_t secure_scratch0; uint32_t secure_scratch1; uint32_t secure_scratch2; uint32_t secure_scratch3; uint32_t secure_scratch4; uint32_t secure_scratch5; - uint32_t cpupwrgood_timer; uint32_t cpupwroff_timer; uint32_t pg_mask; @@ -88,7 +109,6 @@ typedef struct { uint32_t usb_ao; uint32_t crypto_op; uint32_t pllp_wb0_override; - uint32_t scratch24; uint32_t scratch25; uint32_t scratch26; @@ -108,7 +128,6 @@ typedef struct { uint32_t scratch40; uint32_t scratch41; uint32_t scratch42; - uint32_t bo_mirror0; uint32_t bo_mirror1; uint32_t bo_mirror2; @@ -143,10 +162,9 @@ typedef struct { uint32_t io_dpd2_stat; uint32_t sel_dpd_tim; uint32_t vddp_sel; - uint32_t ddr_cfg; uint32_t e_no_vttgen; - uint32_t reserved0; + uint32_t _reserved0; uint32_t pllm_wb0_ovrride_frq; uint32_t test_pwrgate; uint32_t pwrgate_timer_mult; @@ -156,8 +174,12 @@ typedef struct { uint32_t utmip_pad_cfg; uint32_t utmip_term_pad_cfg; uint32_t utmip_uhsic_sleep_cfg; - - uint32_t todo_0[9]; + uint32_t utmip_uhsic_sleepwalk_cfg; + uint32_t utmip_sleepwalk_p[3]; + uint32_t uhsic_sleepwalk_p0; + uint32_t utmip_uhsic_status; + uint32_t utmip_uhsic_fake; + uint32_t bo_mirror3[2]; uint32_t secure_scratch6; uint32_t secure_scratch7; uint32_t scratch43; @@ -176,7 +198,22 @@ typedef struct { uint32_t scratch0_eco; uint32_t por_dpd_ctrl; uint32_t scratch2_eco; - uint32_t todo_1[17]; + uint32_t utmip_uhsic_line_wakeup; + uint32_t utmip_bias_master_cntrl; + uint32_t utmip_master_config; + uint32_t td_pwrgate_inter_part_timer; + uint32_t utmip_uhsic2_triggers; + uint32_t utmip_uhsic2_saved_state; + uint32_t utmip_uhsic2_sleep_cfg; + uint32_t utmip_uhsic2_sleepwalk_cfg; + uint32_t uhsic2_sleepwalk_p1; + uint32_t utmip_uhsic2_status; + uint32_t utmip_uhsic2_fake; + uint32_t utmip_uhsic2_line_wakeup; + uint32_t utmip_master2_config; + uint32_t utmip_uhsic_rpd_cfg; + uint32_t pg_mask_ce0; + uint32_t pg_mask3[2]; uint32_t pllm_wb0_override2; uint32_t tsc_mult; uint32_t cpu_vsense_override; @@ -184,7 +221,9 @@ typedef struct { uint32_t sticky_bits; uint32_t sec_disable2; uint32_t weak_bias; - uint32_t todo_3[13]; + uint32_t reg_short; + uint32_t pg_mask_andor; + uint32_t _reserved1[11]; uint32_t secure_scratch8; uint32_t secure_scratch9; uint32_t secure_scratch10; @@ -213,15 +252,64 @@ typedef struct { uint32_t secure_scratch33; uint32_t secure_scratch34; uint32_t secure_scratch35; - - uint32_t reserved1[52]; + uint32_t secure_scratch36; + uint32_t secure_scratch37; + uint32_t secure_scratch38; + uint32_t secure_scratch39; + uint32_t secure_scratch40; + uint32_t secure_scratch41; + uint32_t secure_scratch42; + uint32_t secure_scratch43; + uint32_t secure_scratch44; + uint32_t secure_scratch45; + uint32_t secure_scratch46; + uint32_t secure_scratch47; + uint32_t secure_scratch48; + uint32_t secure_scratch49; + uint32_t secure_scratch50; + uint32_t secure_scratch51; + uint32_t secure_scratch52; + uint32_t secure_scratch53; + uint32_t secure_scratch54; + uint32_t secure_scratch55; + uint32_t secure_scratch56; + uint32_t secure_scratch57; + uint32_t secure_scratch58; + uint32_t secure_scratch59; + uint32_t secure_scratch60; + uint32_t secure_scratch61; + uint32_t secure_scratch62; + uint32_t secure_scratch63; + uint32_t secure_scratch64; + uint32_t secure_scratch65; + uint32_t secure_scratch66; + uint32_t secure_scratch67; + uint32_t secure_scratch68; + uint32_t secure_scratch69; + uint32_t secure_scratch70; + uint32_t secure_scratch71; + uint32_t secure_scratch72; + uint32_t secure_scratch73; + uint32_t secure_scratch74; + uint32_t secure_scratch75; + uint32_t secure_scratch76; + uint32_t secure_scratch77; + uint32_t secure_scratch78; + uint32_t secure_scratch79; + uint32_t _reserved2[8]; uint32_t cntrl2; - uint32_t reserved2[6]; + uint32_t _reserved3[2]; + uint32_t event_counter; + uint32_t fuse_control; + uint32_t scratch1_eco; + uint32_t _reserved4; uint32_t io_dpd3_req; - uint32_t io_dpd3_stat; - uint32_t strap_opt_a; - uint32_t reserved3[102]; - + uint32_t io_dpd3_status; + uint32_t io_dpd4_req; + uint32_t io_dpd4_status; + uint32_t _reserved5[30]; + uint32_t ddr_cntrl; + uint32_t _reserved6[70]; uint32_t scratch56; uint32_t scratch57; uint32_t scratch58; @@ -286,12 +374,232 @@ typedef struct { uint32_t scratch117; uint32_t scratch118; uint32_t scratch119; - uint32_t scratch1_eco; + uint32_t scratch120; + uint32_t scratch121; + uint32_t scratch122; + uint32_t scratch123; + uint32_t scratch124; + uint32_t scratch125; + uint32_t scratch126; + uint32_t scratch127; + uint32_t scratch128; + uint32_t scratch129; + uint32_t scratch130; + uint32_t scratch131; + uint32_t scratch132; + uint32_t scratch133; + uint32_t scratch134; + uint32_t scratch135; + uint32_t scratch136; + uint32_t scratch137; + uint32_t scratch138; + uint32_t scratch139; + uint32_t scratch140; + uint32_t scratch141; + uint32_t scratch142; + uint32_t scratch143; + uint32_t scratch144; + uint32_t scratch145; + uint32_t scratch146; + uint32_t scratch147; + uint32_t scratch148; + uint32_t scratch149; + uint32_t scratch150; + uint32_t scratch151; + uint32_t scratch152; + uint32_t scratch153; + uint32_t scratch154; + uint32_t scratch155; + uint32_t scratch156; + uint32_t scratch157; + uint32_t scratch158; + uint32_t scratch159; + uint32_t scratch160; + uint32_t scratch161; + uint32_t scratch162; + uint32_t scratch163; + uint32_t scratch164; + uint32_t scratch165; + uint32_t scratch166; + uint32_t scratch167; + uint32_t scratch168; + uint32_t scratch169; + uint32_t scratch170; + uint32_t scratch171; + uint32_t scratch172; + uint32_t scratch173; + uint32_t scratch174; + uint32_t scratch175; + uint32_t scratch176; + uint32_t scratch177; + uint32_t scratch178; + uint32_t scratch179; + uint32_t scratch180; + uint32_t scratch181; + uint32_t scratch182; + uint32_t scratch183; + uint32_t scratch184; + uint32_t scratch185; + uint32_t scratch186; + uint32_t scratch187; + uint32_t scratch188; + uint32_t scratch189; + uint32_t scratch190; + uint32_t scratch191; + uint32_t scratch192; + uint32_t scratch193; + uint32_t scratch194; + uint32_t scratch195; + uint32_t scratch196; + uint32_t scratch197; + uint32_t scratch198; + uint32_t scratch199; + uint32_t scratch200; + uint32_t scratch201; + uint32_t scratch202; + uint32_t scratch203; + uint32_t scratch204; + uint32_t scratch205; + uint32_t scratch206; + uint32_t scratch207; + uint32_t scratch208; + uint32_t scratch209; + uint32_t scratch210; + uint32_t scratch211; + uint32_t scratch212; + uint32_t scratch213; + uint32_t scratch214; + uint32_t scratch215; + uint32_t scratch216; + uint32_t scratch217; + uint32_t scratch218; + uint32_t scratch219; + uint32_t scratch220; + uint32_t scratch221; + uint32_t scratch222; + uint32_t scratch223; + uint32_t scratch224; + uint32_t scratch225; + uint32_t scratch226; + uint32_t scratch227; + uint32_t scratch228; + uint32_t scratch229; + uint32_t scratch230; + uint32_t scratch231; + uint32_t scratch232; + uint32_t scratch233; + uint32_t scratch234; + uint32_t scratch235; + uint32_t scratch236; + uint32_t scratch237; + uint32_t scratch238; + uint32_t scratch239; + uint32_t scratch240; + uint32_t scratch241; + uint32_t scratch242; + uint32_t scratch243; + uint32_t scratch244; + uint32_t scratch245; + uint32_t scratch246; + uint32_t scratch247; + uint32_t scratch248; + uint32_t scratch249; + uint32_t scratch250; + uint32_t scratch251; + uint32_t scratch252; + uint32_t scratch253; + uint32_t scratch254; + uint32_t scratch255; + uint32_t scratch256; + uint32_t scratch257; + uint32_t scratch258; + uint32_t scratch259; + uint32_t scratch260; + uint32_t scratch261; + uint32_t scratch262; + uint32_t scratch263; + uint32_t scratch264; + uint32_t scratch265; + uint32_t scratch266; + uint32_t scratch267; + uint32_t scratch268; + uint32_t scratch269; + uint32_t scratch270; + uint32_t scratch271; + uint32_t scratch272; + uint32_t scratch273; + uint32_t scratch274; + uint32_t scratch275; + uint32_t scratch276; + uint32_t scratch277; + uint32_t scratch278; + uint32_t scratch279; + uint32_t scratch280; + uint32_t scratch281; + uint32_t scratch282; + uint32_t scratch283; + uint32_t scratch284; + uint32_t scratch285; + uint32_t scratch286; + uint32_t scratch287; + uint32_t scratch288; + uint32_t scratch289; + uint32_t scratch290; + uint32_t scratch291; + uint32_t scratch292; + uint32_t scratch293; + uint32_t scratch294; + uint32_t scratch295; + uint32_t scratch296; + uint32_t scratch297; + uint32_t scratch298; + uint32_t scratch299; + uint32_t _reserved7[50]; + uint32_t secure_scratch80; + uint32_t secure_scratch81; + uint32_t secure_scratch82; + uint32_t secure_scratch83; + uint32_t secure_scratch84; + uint32_t secure_scratch85; + uint32_t secure_scratch86; + uint32_t secure_scratch87; + uint32_t secure_scratch88; + uint32_t secure_scratch89; + uint32_t secure_scratch90; + uint32_t secure_scratch91; + uint32_t secure_scratch92; + uint32_t secure_scratch93; + uint32_t secure_scratch94; + uint32_t secure_scratch95; + uint32_t secure_scratch96; + uint32_t secure_scratch97; + uint32_t secure_scratch98; + uint32_t secure_scratch99; + uint32_t secure_scratch100; + uint32_t secure_scratch101; + uint32_t secure_scratch102; + uint32_t secure_scratch103; + uint32_t secure_scratch104; + uint32_t secure_scratch105; + uint32_t secure_scratch106; + uint32_t secure_scratch107; + uint32_t secure_scratch108; + uint32_t secure_scratch109; + uint32_t secure_scratch110; + uint32_t secure_scratch111; + uint32_t secure_scratch112; + uint32_t secure_scratch113; + uint32_t secure_scratch114; + uint32_t secure_scratch115; + uint32_t secure_scratch116; + uint32_t secure_scratch117; + uint32_t secure_scratch118; + uint32_t secure_scratch119; } tegra_pmc_t; static inline volatile tegra_pmc_t *pmc_get_regs(void) { - return (volatile tegra_pmc_t *)0x7000E400; + return (volatile tegra_pmc_t *)PMC_BASE; } #endif diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c index 85cab87ba..c30a1f837 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c @@ -11,8 +11,8 @@ #include "../apb_misc.h" #include "../gpio.h" #include "../pmc.h" +#include "../max7762x.h" #include "../lib/driver_utils.h" -#include "../hwinit/max7762x.h" static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; @@ -399,16 +399,16 @@ static int sdmmc_clk_set_source(SdmmcControllerNum controller, uint32_t clk_freq switch (controller) { case SDMMC_1: - car->clk_src[CLK_SOURCE_SDMMC1] = (CLK_SOURCE_FIRST | car_div); + car->clk_source_sdmmc1 = (CLK_SOURCE_FIRST | car_div); break; case SDMMC_2: - car->clk_src[CLK_SOURCE_SDMMC2] = (CLK_SOURCE_FIRST | car_div); + car->clk_source_sdmmc2 = (CLK_SOURCE_FIRST | car_div); break; case SDMMC_3: - car->clk_src[CLK_SOURCE_SDMMC3] = (CLK_SOURCE_FIRST | car_div); + car->clk_source_sdmmc3 = (CLK_SOURCE_FIRST | car_div); break; case SDMMC_4: - car->clk_src[CLK_SOURCE_SDMMC4] = (CLK_SOURCE_FIRST | car_div); + car->clk_source_sdmmc4 = (CLK_SOURCE_FIRST | car_div); break; } diff --git a/fusee/fusee-primary/src/sdram.c b/fusee/fusee-primary/src/sdram.c new file mode 100644 index 000000000..eb941f235 --- /dev/null +++ b/fusee/fusee-primary/src/sdram.c @@ -0,0 +1,561 @@ +#include "i2c.h" +#include "mc.h" +#include "emc.h" +#include "pmc.h" +#include "timers.h" +#include "sysreg.h" +#include "fuse.h" +#include "max77620.h" +#include "sdram_param_t210.h" +#include "car.h" + +#define CONFIG_SDRAM_COMPRESS_CFG + +#ifdef CONFIG_SDRAM_COMPRESS_CFG +#include "lib/lz.h" +#include "sdram_lz.inl" +#else +#include "sdram.inl" +#endif + +static uint32_t _get_sdram_id() +{ + return ((fuse_get_reserved_odm(4) & 0x38) >> 3); +} + +static void _sdram_config(const sdram_params_t *params) +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + pmc->io_dpd3_req = (((4 * params->emc_pmc_scratch1 >> 2) + 0x80000000) ^ 0xFFFF) & 0xC000FFFF; + udelay(params->pmc_io_dpd3_req_wait); + + uint32_t req = (4 * params->emc_pmc_scratch2 >> 2) + 0x80000000; + pmc->io_dpd4_req = (req >> 16 << 16) ^ 0x3FFF0000; + + udelay(params->pmc_io_dpd4_req_wait); + pmc->io_dpd4_req = (req ^ 0xFFFF) & 0xC000FFFF; + udelay(params->pmc_io_dpd4_req_wait); + + pmc->weak_bias = 0; + udelay(1); + + car->pllm_misc1 = params->pllm_setup_control; + car->pllm_misc2 = 0; + car->pllm_base = ((params->pllm_feedback_divider << 8) | params->pllm_input_divider | 0x40000000 | ((params->pllm_post_divider & 0xFFFF) << 20)); + + bool timeout = false; + uint32_t wait_end = get_time_us() + 300; + + while (!(car->pllm_base & 0x8000000) && !timeout) + { + if (get_time_us() >= wait_end) + timeout = true; + } + + if (!timeout) { + udelay(10); + } + + car->clk_source_emc = (((params->mc_emem_arb_misc0 >> 11) & 0x10000) | (params->emc_clock_source & 0xFFFEFFFF)); + + if (params->emc_clock_source_dll) + car->clk_source_emc_dll = params->emc_clock_source_dll; + + if (params->clear_clock2_mc1) + car->clk_enb_w_clr = 0x40000000; + + car->clk_enb_h_set = 0x2000001; + car->clk_enb_x_set = 0x4000; + car->rst_dev_h_clr = 0x2000001; + + MAKE_EMC_REG(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0; + MAKE_EMC_REG(EMC_PMACRO_VTTGEN_CTRL_1) = params->emc_pmacro_vttgen_ctrl1; + MAKE_EMC_REG(EMC_PMACRO_VTTGEN_CTRL_2) = params->emc_pmacro_vttgen_ctrl2; + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + udelay(1); + + MAKE_EMC_REG(EMC_DBG) = (params->emc_dbg_write_mux << 1) | params->emc_dbg; + + if (params->emc_bct_spare2) + *(volatile uint32_t *)params->emc_bct_spare2 = params->emc_bct_spare3; + + MAKE_EMC_REG(EMC_FBIO_CFG7) = params->emc_fbio_cfg7; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD0_0) = params->emc_cmd_mapping_cmd0_0; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD0_1) = params->emc_cmd_mapping_cmd0_1; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD0_2) = params->emc_cmd_mapping_cmd0_2; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD1_0) = params->emc_cmd_mapping_cmd1_0; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD1_1) = params->emc_cmd_mapping_cmd1_1; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD1_2) = params->emc_cmd_mapping_cmd1_2; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD2_0) = params->emc_cmd_mapping_cmd2_0; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD2_1) = params->emc_cmd_mapping_cmd2_1; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD2_2) = params->emc_cmd_mapping_cmd2_2; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD3_0) = params->emc_cmd_mapping_cmd3_0; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD3_1) = params->emc_cmd_mapping_cmd3_1; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD3_2) = params->emc_cmd_mapping_cmd3_2; + MAKE_EMC_REG(EMC_CMD_MAPPING_BYTE) = params->emc_cmd_mapping_byte; + MAKE_EMC_REG(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0; + MAKE_EMC_REG(EMC_PMACRO_BRICK_MAPPING_1) = params->emc_pmacro_brick_mapping1; + MAKE_EMC_REG(EMC_PMACRO_BRICK_MAPPING_2) = params->emc_pmacro_brick_mapping2; + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU1) = ((params->emc_pmacro_brick_ctrl_rfu1 & 0x1120112) | 0x1EED1EED); + MAKE_EMC_REG(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay; + MAKE_EMC_REG(EMC_FBIO_CFG8) = params->emc_fbio_cfg8; + MAKE_EMC_REG(EMC_SWIZZLE_RANK0_BYTE0) = params->emc_swizzle_rank0_byte0; + MAKE_EMC_REG(EMC_SWIZZLE_RANK0_BYTE1) = params->emc_swizzle_rank0_byte1; + MAKE_EMC_REG(EMC_SWIZZLE_RANK0_BYTE2) = params->emc_swizzle_rank0_byte2; + MAKE_EMC_REG(EMC_SWIZZLE_RANK0_BYTE3) = params->emc_swizzle_rank0_byte3; + MAKE_EMC_REG(EMC_SWIZZLE_RANK1_BYTE0) = params->emc_swizzle_rank1_byte0; + MAKE_EMC_REG(EMC_SWIZZLE_RANK1_BYTE1) = params->emc_swizzle_rank1_byte1; + MAKE_EMC_REG(EMC_SWIZZLE_RANK1_BYTE2) = params->emc_swizzle_rank1_byte2; + MAKE_EMC_REG(EMC_SWIZZLE_RANK1_BYTE3) = params->emc_swizzle_rank1_byte3; + + if (params->emc_bct_spare6) + *(volatile uint32_t *)params->emc_bct_spare6 = params->emc_bct_spare7; + + MAKE_EMC_REG(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl; + MAKE_EMC_REG(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2; + MAKE_EMC_REG(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG5) = params->emc_auto_cal_config5; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG6) = params->emc_auto_cal_config6; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8; + MAKE_EMC_REG(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term; + MAKE_EMC_REG(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive; + MAKE_EMC_REG(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive; + MAKE_EMC_REG(EMC_PMACRO_CMD_TX_DRV) = params->emc_pmacro_cmd_tx_drive; + MAKE_EMC_REG(EMC_PMACRO_AUTOCAL_CFG_COMMON) = params->emc_pmacro_auto_cal_common; + MAKE_EMC_REG(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; + MAKE_EMC_REG(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; + MAKE_EMC_REG(EMC_DLL_CFG_0) = params->emc_dll_cfg0; + MAKE_EMC_REG(EMC_DLL_CFG_1) = params->emc_dll_cfg1; + MAKE_EMC_REG(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1; + MAKE_EMC_REG(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0; + MAKE_EMC_REG(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1; + MAKE_EMC_REG(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0; + MAKE_EMC_REG(EMC_DQS_BRLSHFT_1) = params->emc_dqs_brlshft1; + MAKE_EMC_REG(EMC_CMD_BRLSHFT_0) = params->emc_cmd_brlshft0; + MAKE_EMC_REG(EMC_CMD_BRLSHFT_1) = params->emc_cmd_brlshft1; + MAKE_EMC_REG(EMC_CMD_BRLSHFT_2) = params->emc_cmd_brlshft2; + MAKE_EMC_REG(EMC_CMD_BRLSHFT_3) = params->emc_cmd_brlshft3; + MAKE_EMC_REG(EMC_QUSE_BRLSHFT_0) = params->emc_quse_brlshft0; + MAKE_EMC_REG(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1; + MAKE_EMC_REG(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2; + MAKE_EMC_REG(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3; + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU1) = ((params->emc_pmacro_brick_ctrl_rfu1 & 0x1BF01BF) | 0x1E401E40); + MAKE_EMC_REG(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; + MAKE_EMC_REG(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd; + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU2) = (params->emc_pmacro_brick_ctrl_rfu2 & 0xFF7FFF7F); + MAKE_EMC_REG(EMC_PMACRO_DATA_BRICK_CTRL_FDPD) = params->emc_pmacro_data_brick_ctrl_fdpd; + MAKE_EMC_REG(EMC_PMACRO_BG_BIAS_CTRL_0) = params->emc_pmacro_bg_bias_ctrl0; + MAKE_EMC_REG(EMC_PMACRO_DATA_PAD_RX_CTRL) = params->emc_pmacro_data_pad_rx_ctrl; + MAKE_EMC_REG(EMC_PMACRO_CMD_PAD_RX_CTRL) = params->emc_pmacro_cmd_pad_rx_ctrl; + MAKE_EMC_REG(EMC_PMACRO_DATA_PAD_TX_CTRL) = params->emc_pmacro_data_pad_tx_ctrl; + MAKE_EMC_REG(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode; + MAKE_EMC_REG(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode; + MAKE_EMC_REG(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl; + MAKE_EMC_REG(EMC_CFG_3) = params->emc_cfg3; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_2) = params->emc_pmacro_tx_pwrd2; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_3) = params->emc_pmacro_tx_pwrd3; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_4) = params->emc_pmacro_tx_pwrd4; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_5) = params->emc_pmacro_tx_pwrd5; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_0) = params->emc_pmacro_tx_sel_clk_src0; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_1) = params->emc_pmacro_tx_sel_clk_src1; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_2) = params->emc_pmacro_tx_sel_clk_src2; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_3) = params->emc_pmacro_tx_sel_clk_src3; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_4) = params->emc_pmacro_tx_sel_clk_src4; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_5) = params->emc_pmacro_tx_sel_clk_src5; + MAKE_EMC_REG(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass; + MAKE_EMC_REG(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0; + MAKE_EMC_REG(EMC_PMACRO_DDLL_PWRD_1) = params->emc_pmacro_ddll_pwrd1; + MAKE_EMC_REG(EMC_PMACRO_DDLL_PWRD_2) = params->emc_pmacro_ddll_pwrd2; + MAKE_EMC_REG(EMC_PMACRO_CMD_CTRL_0) = params->emc_pmacro_cmd_ctrl0; + MAKE_EMC_REG(EMC_PMACRO_CMD_CTRL_1) = params->emc_pmacro_cmd_ctrl1; + MAKE_EMC_REG(EMC_PMACRO_CMD_CTRL_2) = params->emc_pmacro_cmd_ctrl2; + MAKE_EMC_REG(EMC_PMACRO_IB_VREF_DQ_0) = params->emc_pmacro_ib_vref_dq_0; + MAKE_EMC_REG(EMC_PMACRO_IB_VREF_DQ_1) = params->emc_pmacro_ib_vref_dq_1; + MAKE_EMC_REG(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0; + MAKE_EMC_REG(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1; + MAKE_EMC_REG(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_3) = params->emc_pmacro_quse_ddll_rank0_3; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_4) = params->emc_pmacro_quse_ddll_rank0_4; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_5) = params->emc_pmacro_quse_ddll_rank0_5; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_0) = params->emc_pmacro_quse_ddll_rank1_0; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_1) = params->emc_pmacro_quse_ddll_rank1_1; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_2) = params->emc_pmacro_quse_ddll_rank1_2; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_3) = params->emc_pmacro_quse_ddll_rank1_3; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_4) = params->emc_pmacro_quse_ddll_rank1_4; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5; + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3) = params->emc_pmacro_ob_ddll_long_dq_rank0_3; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4) = params->emc_pmacro_ob_ddll_long_dq_rank0_4; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5) = params->emc_pmacro_ob_ddll_long_dq_rank0_5; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0) = params->emc_pmacro_ob_ddll_long_dq_rank1_0; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1) = params->emc_pmacro_ob_ddll_long_dq_rank1_1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2) = params->emc_pmacro_ob_ddll_long_dq_rank1_2; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3) = params->emc_pmacro_ob_ddll_long_dq_rank1_3; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4) = params->emc_pmacro_ob_ddll_long_dq_rank1_4; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5) = params->emc_pmacro_ob_ddll_long_dq_rank1_5; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ob_ddll_long_dqs_rank0_0; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ob_ddll_long_dqs_rank0_1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ob_ddll_long_dqs_rank0_2; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ob_ddll_long_dqs_rank0_3; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4) = params->emc_pmacro_ob_ddll_long_dqs_rank0_4; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5) = params->emc_pmacro_ob_ddll_long_dqs_rank0_5; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ob_ddll_long_dqs_rank1_0; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ob_ddll_long_dqs_rank1_1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ob_ddll_long_dqs_rank1_2; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ob_ddll_long_dqs_rank1_3; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4) = params->emc_pmacro_ob_ddll_long_dqs_rank1_4; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5) = params->emc_pmacro_ob_ddll_long_dqs_rank1_5; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ib_ddll_long_dqs_rank0_0; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ib_ddll_long_dqs_rank0_1; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ib_ddll_long_dqs_rank0_2; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ib_ddll_long_dqs_rank0_3; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ib_ddll_long_dqs_rank1_0; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ib_ddll_long_dqs_rank1_1; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_3) = params->emc_pmacro_ddll_long_cmd_3; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_4) = params->emc_pmacro_ddll_long_cmd_4; + MAKE_EMC_REG(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0; + MAKE_EMC_REG(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1; + MAKE_EMC_REG(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2; + MAKE_EMC_REG(EMC_PMACRO_COMMON_PAD_TX_CTRL) = ((params->emc_pmacro_common_pad_tx_ctrl & 1) | 0xE); + + if (params->emc_bct_spare4) + *(volatile uint32_t *)params->emc_bct_spare4 = params->emc_bct_spare5; + + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + + MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; + MAKE_MC_REG(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi; + MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb; + MAKE_MC_REG(MC_VIDEO_PROTECT_VPR_OVERRIDE) = params->mc_video_protect_vpr_override; + MAKE_MC_REG(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = params->mc_video_protect_gpu_override0; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = params->mc_video_protect_gpu_override1; + MAKE_MC_REG(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg; + MAKE_MC_REG(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0; + MAKE_MC_REG(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1; + MAKE_MC_REG(MC_EMEM_ADR_CFG_CHANNEL_MASK) = params->mc_emem_adr_cfg_channel_mask; + MAKE_MC_REG(MC_EMEM_ADR_CFG_BANK_MASK_0) = params->mc_emem_adr_cfg_bank_mask0; + MAKE_MC_REG(MC_EMEM_ADR_CFG_BANK_MASK_1) = params->mc_emem_adr_cfg_bank_mask1; + MAKE_MC_REG(MC_EMEM_ADR_CFG_BANK_MASK_2) = params->mc_emem_adr_cfg_bank_mask2; + MAKE_MC_REG(MC_EMEM_CFG) = params->mc_emem_cfg; + MAKE_MC_REG(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom; + MAKE_MC_REG(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi; + MAKE_MC_REG(MC_SEC_CARVEOUT_SIZE_MB) = params->mc_sec_carveout_size_mb; + MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom; + MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi; + MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = params->mc_mts_carveout_size_mb; + MAKE_MC_REG(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg; + MAKE_MC_REG(MC_EMEM_ARB_OUTSTANDING_REQ) = params->mc_emem_arb_outstanding_req; + MAKE_MC_REG(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl; + MAKE_MC_REG(MC_EMEM_ARB_REFPB_BANK_CTRL) = params->emc_emem_arb_refpb_bank_ctrl; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RCD) = params->mc_emem_arb_timing_rcd; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RP) = params->mc_emem_arb_timing_rp; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RC) = params->mc_emem_arb_timing_rc; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RAS) = params->mc_emem_arb_timing_ras; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_FAW) = params->mc_emem_arb_timing_faw; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RRD) = params->mc_emem_arb_timing_rrd; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RAP2PRE) = params->mc_emem_arb_timing_rap2pre; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_WAP2PRE) = params->mc_emem_arb_timing_wap2pre; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_R2R) = params->mc_emem_arb_timing_r2r; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_W2W) = params->mc_emem_arb_timing_w2w; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_CCDMW) = params->mc_emem_arb_timing_ccdmw; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_R2W) = params->mc_emem_arb_timing_r2w; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_W2R) = params->mc_emem_arb_timing_w2r; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RFCPB) = params->mc_emem_arb_timing_rfcpb; + MAKE_MC_REG(MC_EMEM_ARB_DA_TURNS) = params->mc_emem_arb_da_turns; + MAKE_MC_REG(MC_EMEM_ARB_DA_COVERS) = params->mc_emem_arb_da_covers; + MAKE_MC_REG(MC_EMEM_ARB_MISC0) = params->mc_emem_arb_misc0; + MAKE_MC_REG(MC_EMEM_ARB_MISC1) = params->mc_emem_arb_misc1; + MAKE_MC_REG(MC_EMEM_ARB_MISC2) = params->mc_emem_arb_misc2; + MAKE_MC_REG(MC_EMEM_ARB_RING1_THROTTLE) = params->mc_emem_arb_ring1_throttle; + MAKE_MC_REG(MC_EMEM_ARB_OVERRIDE) = params->mc_emem_arb_override; + MAKE_MC_REG(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1; + MAKE_MC_REG(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv; + MAKE_MC_REG(MC_DA_CONFIG0) = params->mc_da_cfg0; + MAKE_MC_REG(MC_TIMING_CONTROL) = 1; + MAKE_MC_REG(MC_CLKEN_OVERRIDE) = params->mc_clken_override; + MAKE_MC_REG(MC_STAT_CONTROL) = params->mc_stat_control; + + MAKE_EMC_REG(EMC_ADR_CFG) = params->emc_adr_cfg; + MAKE_EMC_REG(EMC_CLKEN_OVERRIDE) = params->emc_clken_override; + MAKE_EMC_REG(EMC_PMACRO_AUTOCAL_CFG_0) = params->emc_pmacro_auto_cal_cfg0; + MAKE_EMC_REG(EMC_PMACRO_AUTOCAL_CFG_1) = params->emc_pmacro_auto_cal_cfg1; + MAKE_EMC_REG(EMC_PMACRO_AUTOCAL_CFG_2) = params->emc_pmacro_auto_cal_cfg2; + MAKE_EMC_REG(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0; + MAKE_EMC_REG(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1; + MAKE_EMC_REG(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; + udelay(params->emc_auto_cal_wait); + + if (params->emc_bct_spare8) + *(volatile uint32_t *)params->emc_bct_spare8 = params->emc_bct_spare9; + + MAKE_EMC_REG(EMC_CFG_2) = params->emc_cfg2; + MAKE_EMC_REG(EMC_CFG_PIPE) = params->emc_cfg_pipe; + MAKE_EMC_REG(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1; + MAKE_EMC_REG(EMC_CFG_PIPE_2) = params->emc_cfg_pipe2; + MAKE_EMC_REG(EMC_CMDQ) = params->emc_cmd_q; + MAKE_EMC_REG(EMC_MC2EMCQ) = params->emc_mc2emc_q; + MAKE_EMC_REG(EMC_MRS_WAIT_CNT) = params->emc_mrs_wait_cnt; + MAKE_EMC_REG(EMC_MRS_WAIT_CNT2) = params->emc_mrs_wait_cnt2; + MAKE_EMC_REG(EMC_FBIO_CFG5) = params->emc_fbio_cfg5; + MAKE_EMC_REG(EMC_RC) = params->emc_rc; + MAKE_EMC_REG(EMC_RFC) = params->emc_rfc; + MAKE_EMC_REG(EMC_RFCPB) = params->emc_rfc_pb; + MAKE_EMC_REG(EMC_REFCTRL2) = params->emc_ref_ctrl2; + MAKE_EMC_REG(EMC_RFC_SLR) = params->emc_rfc_slr; + MAKE_EMC_REG(EMC_RAS) = params->emc_ras; + MAKE_EMC_REG(EMC_RP) = params->emc_rp; + MAKE_EMC_REG(EMC_TPPD) = params->emc_tppd; + MAKE_EMC_REG(EMC_R2R) = params->emc_r2r; + MAKE_EMC_REG(EMC_W2W) = params->emc_w2w; + MAKE_EMC_REG(EMC_R2W) = params->emc_r2w; + MAKE_EMC_REG(EMC_W2R) = params->emc_w2r; + MAKE_EMC_REG(EMC_R2P) = params->emc_r2p; + MAKE_EMC_REG(EMC_W2P) = params->emc_w2p; + MAKE_EMC_REG(EMC_CCDMW) = params->emc_ccdmw; + MAKE_EMC_REG(EMC_RD_RCD) = params->emc_rd_rcd; + MAKE_EMC_REG(EMC_WR_RCD) = params->emc_wr_rcd; + MAKE_EMC_REG(EMC_RRD) = params->emc_rrd; + MAKE_EMC_REG(EMC_REXT) = params->emc_rext; + MAKE_EMC_REG(EMC_WEXT) = params->emc_wext; + MAKE_EMC_REG(EMC_WDV) = params->emc_wdv; + MAKE_EMC_REG(EMC_WDV_CHK) = params->emc_wdv_chk; + MAKE_EMC_REG(EMC_WSV) = params->emc_wsv; + MAKE_EMC_REG(EMC_WEV) = params->emc_wev; + MAKE_EMC_REG(EMC_WDV_MASK) = params->emc_wdv_mask; + MAKE_EMC_REG(EMC_WS_DURATION) = params->emc_ws_duration; + MAKE_EMC_REG(EMC_WE_DURATION) = params->emc_we_duration; + MAKE_EMC_REG(EMC_QUSE) = params->emc_quse; + MAKE_EMC_REG(EMC_QUSE_WIDTH) = params->emc_quse_width; + MAKE_EMC_REG(EMC_IBDLY) = params->emc_ibdly; + MAKE_EMC_REG(EMC_OBDLY) = params->emc_obdly; + MAKE_EMC_REG(EMC_EINPUT) = params->emc_einput; + MAKE_EMC_REG(EMC_EINPUT_DURATION) = params->emc_einput_duration; + MAKE_EMC_REG(EMC_PUTERM_EXTRA) = params->emc_puterm_extra; + MAKE_EMC_REG(EMC_PUTERM_WIDTH) = params->emc_puterm_width; + MAKE_EMC_REG(EMC_PMACRO_COMMON_PAD_TX_CTRL) = params->emc_pmacro_common_pad_tx_ctrl; + MAKE_EMC_REG(EMC_DBG) = params->emc_dbg; + MAKE_EMC_REG(EMC_QRST) = params->emc_qrst; + MAKE_EMC_REG(EMC_ISSUE_QRST) = 0; + MAKE_EMC_REG(EMC_QSAFE) = params->emc_qsafe; + MAKE_EMC_REG(EMC_RDV) = params->emc_rdv; + MAKE_EMC_REG(EMC_RDV_MASK) = params->emc_rdv_mask; + MAKE_EMC_REG(EMC_RDV_EARLY) = params->emc_rdv_early; + MAKE_EMC_REG(EMC_RDV_EARLY_MASK) = params->emc_rdv_early_mask; + MAKE_EMC_REG(EMC_QPOP) = params->emc_qpop; + MAKE_EMC_REG(EMC_REFRESH) = params->emc_refresh; + MAKE_EMC_REG(EMC_BURST_REFRESH_NUM) = params->emc_burst_refresh_num; + MAKE_EMC_REG(EMC_PRE_REFRESH_REQ_CNT) = params->emc_prerefresh_req_cnt; + MAKE_EMC_REG(EMC_PDEX2WR) = params->emc_pdex2wr; + MAKE_EMC_REG(EMC_PDEX2RD) = params->emc_pdex2rd; + MAKE_EMC_REG(EMC_PCHG2PDEN) = params->emc_pchg2pden; + MAKE_EMC_REG(EMC_ACT2PDEN) = params->emc_act2pden; + MAKE_EMC_REG(EMC_AR2PDEN) = params->emc_ar2pden; + MAKE_EMC_REG(EMC_RW2PDEN) = params->emc_rw2pden; + MAKE_EMC_REG(EMC_CKE2PDEN) = params->emc_cke2pden; + MAKE_EMC_REG(EMC_PDEX2CKE) = params->emc_pdex2che; + MAKE_EMC_REG(EMC_PDEX2MRR) = params->emc_pdex2mrr; + MAKE_EMC_REG(EMC_TXSR) = params->emc_txsr; + MAKE_EMC_REG(EMC_TXSRDLL) = params->emc_txsr_dll; + MAKE_EMC_REG(EMC_TCKE) = params->emc_tcke; + MAKE_EMC_REG(EMC_TCKESR) = params->emc_tckesr; + MAKE_EMC_REG(EMC_TPD) = params->emc_tpd; + MAKE_EMC_REG(EMC_TFAW) = params->emc_tfaw; + MAKE_EMC_REG(EMC_TRPAB) = params->emc_trpab; + MAKE_EMC_REG(EMC_TCLKSTABLE) = params->emc_tclkstable; + MAKE_EMC_REG(EMC_TCLKSTOP) = params->emc_tclkstop; + MAKE_EMC_REG(EMC_TREFBW) = params->emc_trefbw; + MAKE_EMC_REG(EMC_ODT_WRITE) = params->emc_odt_write; + MAKE_EMC_REG(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll; + MAKE_EMC_REG(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period; + MAKE_EMC_REG(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD; + MAKE_EMC_REG(EMC_CFG_RSV) = params->emc_cfg_rsv; + MAKE_EMC_REG(EMC_PMC_SCRATCH1) = params->emc_pmc_scratch1; + MAKE_EMC_REG(EMC_PMC_SCRATCH2) = params->emc_pmc_scratch2; + MAKE_EMC_REG(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3; + MAKE_EMC_REG(EMC_ACPD_CONTROL) = params->emc_acpd_control; + MAKE_EMC_REG(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; + MAKE_EMC_REG(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000; + + if (params->boot_rom_patch_control & 0x80000000) + { + *(volatile uint32_t *)(4 * (params->boot_rom_patch_control + 0x1C000000)) = params->boot_rom_patch_data; + MAKE_MC_REG(MC_TIMING_CONTROL) = 1; + } + + pmc->io_dpd3_req = (((4 * params->emc_pmc_scratch1 >> 2) + 0x40000000) & 0xCFFF0000); + udelay(params->pmc_io_dpd3_req_wait); + + if (!params->emc_auto_cal_interval) + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG) = (params->emc_auto_cal_config | 0x200); + + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2; + + if (params->emc_zcal_warm_cold_boot_enables & 1) + { + if (params->memory_type == 2) + MAKE_EMC_REG(EMC_ZCAL_WAIT_CNT) = (8 * params->emc_zcal_wait_cnt); + + if (params->memory_type == 3) + { + MAKE_EMC_REG(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; + MAKE_EMC_REG(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; + } + } + + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + udelay(params->emc_timing_control_wait); + + pmc->ddr_cntrl &= 0xFFF8007F; + udelay(params->pmc_ddr_ctrl_wait); + + if (params->memory_type == 2) + { + MAKE_EMC_REG(EMC_PIN) = ((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)); + udelay(params->emc_pin_extra_wait + 200); + MAKE_EMC_REG(EMC_PIN) = (((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 256); + udelay(params->emc_pin_extra_wait + 500); + } + + if (params->memory_type == 3) + { + MAKE_EMC_REG(EMC_PIN) = ((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)); + udelay(params->emc_pin_extra_wait + 200); + MAKE_EMC_REG(EMC_PIN) = (((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 256); + udelay(params->emc_pin_extra_wait + 2000); + } + + MAKE_EMC_REG(EMC_PIN) = (((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 0x101); + udelay(params->emc_pin_program_wait); + + if (params->memory_type != 3) + MAKE_EMC_REG(EMC_NOP) = ((params->emc_dev_select << 30) + 1); + + if (params->memory_type == 1) + udelay(params->emc_pin_extra_wait + 200); + + if (params->memory_type == 3) + { + if (params->emc_bct_spare10) + *(volatile uint32_t *)params->emc_bct_spare10 = params->emc_bct_spare11; + + MAKE_EMC_REG(EMC_MRW2) = params->emc_mrw2; + MAKE_EMC_REG(EMC_MRW) = params->emc_mrw1; + MAKE_EMC_REG(EMC_MRW3) = params->emc_mrw3; + MAKE_EMC_REG(EMC_MRW4) = params->emc_mrw4; + MAKE_EMC_REG(EMC_MRW6) = params->emc_mrw6; + MAKE_EMC_REG(EMC_MRW14) = params->emc_mrw14; + MAKE_EMC_REG(EMC_MRW8) = params->emc_mrw8; + MAKE_EMC_REG(EMC_MRW12) = params->emc_mrw12; + MAKE_EMC_REG(EMC_MRW9) = params->emc_mrw9; + MAKE_EMC_REG(EMC_MRW13) = params->emc_mrw13; + + if (params->emc_zcal_warm_cold_boot_enables & 1) + { + MAKE_EMC_REG(EMC_ZQ_CAL) = params->emc_zcal_init_dev0; + udelay(params->emc_zcal_init_wait); + MAKE_EMC_REG(EMC_ZQ_CAL) = (params->emc_zcal_init_dev0 ^ 3); + + if (!(params->emc_dev_select & 2)) + { + MAKE_EMC_REG(EMC_ZQ_CAL) = params->emc_zcal_init_dev1; + udelay(params->emc_zcal_init_wait); + MAKE_EMC_REG(EMC_ZQ_CAL) = (params->emc_zcal_init_dev1 ^ 3); + } + } + } + + pmc->ddr_cfg = params->pmc_ddr_cfg; + if ((params->memory_type - 1) <= 2) + { + MAKE_EMC_REG(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval; + MAKE_EMC_REG(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; + MAKE_EMC_REG(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; + } + + if (params->emc_bct_spare12) + *(volatile uint32_t *)params->emc_bct_spare12 = params->emc_bct_spare13; + + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + + if (params->emc_extra_refresh_num) + MAKE_EMC_REG(EMC_REF) = (((1 << params->emc_extra_refresh_num << 8) - 0xFD) | (params->emc_pin_gpio << 30)); + + MAKE_EMC_REG(EMC_REFCTRL) = (params->emc_dev_select | 0x80000000); + MAKE_EMC_REG(EMC_DYN_SELF_REF_CONTROL) = params->emc_dyn_self_ref_control; + MAKE_EMC_REG(EMC_CFG_UPDATE) = params->emc_cfg_update; + MAKE_EMC_REG(EMC_CFG) = params->emc_cfg; + MAKE_EMC_REG(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq; + MAKE_EMC_REG(EMC_FDPD_CTRL_CMD) = params->emc_fdpd_ctrl_cmd; + MAKE_EMC_REG(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl; + MAKE_EMC_REG(EMC_FBIO_SPARE) = (params->emc_fbio_spare | 2); + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + MAKE_EMC_REG(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk; + MAKE_EMC_REG(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp; + + AHB_ARBITRATION_XBAR_CTRL_0 = ((AHB_ARBITRATION_XBAR_CTRL_0 & 0xFFFEFFFF) | ((params->ahb_arbitration_xbar_ctrl_meminit_done & 0xFFFF) << 16)); + + MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access; + MAKE_MC_REG(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access; + MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl; + MAKE_MC_REG(MC_EMEM_CFG_ACCESS_CTRL) = 1; /* Disable write access to a bunch of MC registers. */ +} + +const void *sdram_get_params() +{ + /* TODO: sdram_id should be in [0, 7]. */ + +#ifdef CONFIG_SDRAM_COMPRESS_CFG + uint8_t *buf = (uint8_t *)0x40030000; + LZ_Uncompress(_dram_cfg_lz, buf, sizeof(_dram_cfg_lz)); + return (const void *)&buf[sizeof(sdram_params_t) * _get_sdram_id()]; +#else + return _dram_cfgs[_get_sdram_id()]; +#endif +} + +void sdram_init() +{ + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* TODO: sdram_id should be in [0,4]. */ + const sdram_params_t *params = (const sdram_params_t *)sdram_get_params(); + + uint8_t val = 5; + i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); + val = 40; /* 40 = (1000 * 1100 - 600000) / 12500 -> 1.1V */ + i2c_send(4, 0x3C, MAX77620_REG_SD1, &val, 1); + + pmc->vddp_sel = params->pmc_vddp_sel; + udelay(params->pmc_vddp_sel_wait); + + pmc->ddr_pwr = pmc->ddr_pwr; + pmc->no_iopower = params->pmc_no_io_power; + pmc->reg_short = params->pmc_reg_short; + pmc->ddr_cntrl = params->pmc_ddr_ctrl; + + if (params->emc_bct_spare0) + *(volatile uint32_t *)params->emc_bct_spare0 = params->emc_bct_spare1; + + _sdram_config(params); +} diff --git a/fusee/fusee-primary/src/sdram.h b/fusee/fusee-primary/src/sdram.h new file mode 100644 index 000000000..1ccc07f0c --- /dev/null +++ b/fusee/fusee-primary/src/sdram.h @@ -0,0 +1,8 @@ +#ifndef FUSEE_SDRAM_H_ +#define FUSEE_SDRAM_H_ + +void sdram_init(); +const void *sdram_get_params(); +void sdram_lp0_save_params(const void *params); + +#endif diff --git a/fusee/fusee-primary/src/sdram.inl b/fusee/fusee-primary/src/sdram.inl new file mode 100644 index 000000000..187355c4c --- /dev/null +++ b/fusee/fusee-primary/src/sdram.inl @@ -0,0 +1,1136 @@ +static const uint8_t _dram_cfg_0[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_1[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_2[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_3[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_4[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0C, 0x00, + 0x02, 0x03, 0x0C, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x18, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_5[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, + 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, + 0x2F, 0x00, 0x33, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, + 0x2F, 0x00, 0x33, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x15, 0x00, 0x15, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, 0x16, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_6[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, + 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, + 0x2F, 0x00, 0x33, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, + 0x2F, 0x00, 0x33, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x15, 0x00, 0x15, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, 0x16, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xA3, 0x72, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint32_t *_dram_cfgs[7] = { + (const uint32_t *)_dram_cfg_0, + (const uint32_t *)_dram_cfg_1, + (const uint32_t *)_dram_cfg_2, + (const uint32_t *)_dram_cfg_3, + (const uint32_t *)_dram_cfg_4, + (const uint32_t *)_dram_cfg_5, + (const uint32_t *)_dram_cfg_6 +}; diff --git a/fusee/fusee-primary/src/sdram_lp0.c b/fusee/fusee-primary/src/sdram_lp0.c new file mode 100644 index 000000000..36bcc6bef --- /dev/null +++ b/fusee/fusee-primary/src/sdram_lp0.c @@ -0,0 +1,1109 @@ +#include "pmc.h" +#include "sdram_param_t210_lp0.h" + +/* + * This function reads SDRAM parameters from the common BCT format and + * writes them into PMC scratch registers (where the BootROM expects them + * on LP0 resume). + */ +void sdram_lp0_save_params(const void *params) +{ + struct sdram_params *sdram = (struct sdram_params *)params; + volatile tegra_pmc_t *pmc = pmc_get_regs(); + +#define pack(src, src_bits, dst, dst_bits) { \ + uint32_t mask = 0xffffffff >> (31 - ((1 ? src_bits) - (0 ? src_bits))); \ + dst &= ~(mask << (0 ? dst_bits)); \ + dst |= ((src >> (0 ? src_bits)) & mask) << (0 ? dst_bits); \ +} + +#define s(param, src_bits, pmcreg, dst_bits) \ + pack(sdram->param, src_bits, pmc->pmcreg, dst_bits) + +#define c(value, pmcreg, dst_bits) \ + pack(value, (1 ? dst_bits) - (0 ? dst_bits) : 0, pmc->pmcreg, dst_bits) + +/* 32 bits version of s macro */ +#define s32(param, pmcreg) pmc->pmcreg = sdram->param + +/* 32 bits version c macro */ +#define c32(value, pmcreg) pmc->pmcreg = value + + //TODO: pkg1.1 (1.X - 3.X) reads them from MC. + // Patch carveout parameters. + /*sdram->McGeneralizedCarveout1Bom = 0; + sdram->McGeneralizedCarveout1BomHi = 0; + sdram->McGeneralizedCarveout1Size128kb = 0; + sdram->McGeneralizedCarveout1Access0 = 0; + sdram->McGeneralizedCarveout1Access1 = 0; + sdram->McGeneralizedCarveout1Access2 = 0; + sdram->McGeneralizedCarveout1Access3 = 0; + sdram->McGeneralizedCarveout1Access4 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout1Cfg0 = 0; + sdram->McGeneralizedCarveout2Bom = 0x80020000; + sdram->McGeneralizedCarveout2BomHi = 0; + sdram->McGeneralizedCarveout2Size128kb = 2; + sdram->McGeneralizedCarveout2Access0 = 0; + sdram->McGeneralizedCarveout2Access1 = 0; + sdram->McGeneralizedCarveout2Access2 = 0x3000000; + sdram->McGeneralizedCarveout2Access3 = 0; + sdram->McGeneralizedCarveout2Access4 = 0x300; + sdram->McGeneralizedCarveout2ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout2ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout2ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout2ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout2ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout2Cfg0 = 0x440167E; + sdram->McGeneralizedCarveout3Bom = 0; + sdram->McGeneralizedCarveout3BomHi = 0; + sdram->McGeneralizedCarveout3Size128kb = 0; + sdram->McGeneralizedCarveout3Access0 = 0; + sdram->McGeneralizedCarveout3Access1 = 0; + sdram->McGeneralizedCarveout3Access2 = 0x3000000; + sdram->McGeneralizedCarveout3Access3 = 0; + sdram->McGeneralizedCarveout3Access4 = 0x300; + sdram->McGeneralizedCarveout3ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout3ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout3ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout3ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout3ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout3Cfg0 = 0x4401E7E; + sdram->McGeneralizedCarveout4Bom = 0; + sdram->McGeneralizedCarveout4BomHi = 0; + sdram->McGeneralizedCarveout4Size128kb = 0; + sdram->McGeneralizedCarveout4Access0 = 0; + sdram->McGeneralizedCarveout4Access1 = 0; + sdram->McGeneralizedCarveout4Access2 = 0; + sdram->McGeneralizedCarveout4Access3 = 0; + sdram->McGeneralizedCarveout4Access4 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout4Cfg0 = 0x8F; + sdram->McGeneralizedCarveout5Bom = 0; + sdram->McGeneralizedCarveout5BomHi = 0; + sdram->McGeneralizedCarveout5Size128kb = 0; + sdram->McGeneralizedCarveout5Access0 = 0; + sdram->McGeneralizedCarveout5Access1 = 0; + sdram->McGeneralizedCarveout5Access2 = 0; + sdram->McGeneralizedCarveout5Access3 = 0; + sdram->McGeneralizedCarveout5Access4 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout5Cfg0 = 0x8F;*/ + + //TODO: this is 4.X+ behaviour which seems to work fine for < 4.X. + // Patch carveout parameters. + sdram->McGeneralizedCarveout1Cfg0 = 0; + sdram->McGeneralizedCarveout2Cfg0 = 0; + sdram->McGeneralizedCarveout3Cfg0 = 0; + sdram->McGeneralizedCarveout4Cfg0 = 0; + sdram->McGeneralizedCarveout5Cfg0 = 0; + + // Patch SDRAM parameters. + uint32_t t0 = sdram->EmcSwizzleRank0Byte0 << 5 >> 29 > sdram->EmcSwizzleRank0Byte0 << 1 >> 29; + uint32_t t1 = (t0 & 0xFFFFFFEF) | ((sdram->EmcSwizzleRank1Byte0 << 5 >> 29 > sdram->EmcSwizzleRank1Byte0 << 1 >> 29) << 4); + uint32_t t2 = (t1 & 0xFFFFFFFD) | ((sdram->EmcSwizzleRank0Byte1 << 5 >> 29 > sdram->EmcSwizzleRank0Byte1 << 1 >> 29) << 1); + uint32_t t3 = (t2 & 0xFFFFFFDF) | ((sdram->EmcSwizzleRank1Byte1 << 5 >> 29 > sdram->EmcSwizzleRank1Byte1 << 1 >> 29) << 5); + uint32_t t4 = (t3 & 0xFFFFFFFB) | ((sdram->EmcSwizzleRank0Byte2 << 5 >> 29 > sdram->EmcSwizzleRank0Byte2 << 1 >> 29) << 2); + uint32_t t5 = (t4 & 0xFFFFFFBF) | ((sdram->EmcSwizzleRank1Byte2 << 5 >> 29 > sdram->EmcSwizzleRank1Byte2 << 1 >> 29) << 6); + uint32_t t6 = (t5 & 0xFFFFFFF7) | ((sdram->EmcSwizzleRank0Byte3 << 5 >> 29 > sdram->EmcSwizzleRank0Byte3 << 1 >> 29) << 3); + uint32_t t7 = (t6 & 0xFFFFFF7F) | ((sdram->EmcSwizzleRank1Byte3 << 5 >> 29 > sdram->EmcSwizzleRank1Byte3 << 1 >> 29) << 7); + sdram->SwizzleRankByteEncode = t7; + sdram->EmcBctSpare2 = 0x40000DD8; + sdram->EmcBctSpare3 = t7; + + s(EmcClockSource, 7:0, scratch6, 15:8); + s(EmcClockSourceDll, 7:0, scratch6, 23:16); + s(EmcClockSource, 31:29, scratch6, 26:24); + s(EmcClockSourceDll, 31:29, scratch6, 29:27); + s(EmcClockSourceDll, 11:10, scratch6, 31:30); + s(ClkRstControllerPllmMisc2Override, 9:8, scratch7, 1:0); + s(ClkRstControllerPllmMisc2Override, 2:1, scratch7, 3:2); + s(EmcZqCalLpDdr4WarmBoot, 31:30, scratch7, 5:4); + s(EmcClockSource, 15:15, scratch7, 6:6); + s(EmcClockSource, 26:26, scratch7, 7:7); + s(EmcClockSource, 20:20, scratch7, 8:8); + s(EmcClockSource, 19:19, scratch7, 9:9); + s(ClkRstControllerPllmMisc2Override, 13:13, scratch7, 10:10); + s(ClkRstControllerPllmMisc2Override, 12:12, scratch7, 11:11); + s(ClkRstControllerPllmMisc2Override, 11:11, scratch7, 12:12); + s(ClkRstControllerPllmMisc2Override, 10:10, scratch7, 13:13); + s(ClkRstControllerPllmMisc2Override, 5:5, scratch7, 14:14); + s(ClkRstControllerPllmMisc2Override, 4:4, scratch7, 15:15); + s(ClkRstControllerPllmMisc2Override, 3:3, scratch7, 16:16); + s(ClkRstControllerPllmMisc2Override, 0:0, scratch7, 17:17); + s(EmcZqCalLpDdr4WarmBoot, 1:0, scratch7, 19:18); + s(EmcZqCalLpDdr4WarmBoot, 4:4, scratch7, 20:20); + s(EmcOdtWrite, 5:0, scratch7, 26:21); + s(EmcOdtWrite, 11:8, scratch7, 30:27); + s(EmcOdtWrite, 31:31, scratch7, 31:31); + s(EmcFdpdCtrlCmdNoRamp, 0:0, scratch13, 30:30); + s(EmcCfgPipeClk, 0:0, scratch13, 31:31); + s(McEmemArbMisc2, 0:0, scratch14, 30:30); + s(McDaCfg0, 0:0, scratch14, 31:31); + s(EmcQRst, 6:0, scratch15, 26:20); + s(EmcQRst, 20:16, scratch15, 31:27); + s(EmcPmacroCmdTxDrv, 5:0, scratch16, 25:20); + s(EmcPmacroCmdTxDrv, 13:8, scratch16, 31:26); + s(EmcPmacroAutocalCfg0, 2:0, scratch17, 22:20); + s(EmcPmacroAutocalCfg0, 10:8, scratch17, 25:23); + s(EmcPmacroAutocalCfg0, 18:16, scratch17, 28:26); + s(EmcPmacroAutocalCfg0, 26:24, scratch17, 31:29); + s(EmcPmacroAutocalCfg1, 2:0, scratch18, 22:20); + s(EmcPmacroAutocalCfg1, 10:8, scratch18, 25:23); + s(EmcPmacroAutocalCfg1, 18:16, scratch18, 28:26); + s(EmcPmacroAutocalCfg1, 26:24, scratch18, 31:29); + s(EmcPmacroAutocalCfg2, 2:0, scratch19, 22:20); + s(EmcPmacroAutocalCfg2, 10:8, scratch19, 25:23); + s(EmcPmacroAutocalCfg2, 18:16, scratch19, 28:26); + s(EmcPmacroAutocalCfg2, 26:24, scratch19, 31:29); + s32(EmcCfgRsv,scratch22); + s32(EmcAutoCalConfig, scratch23); + s32(EmcAutoCalVrefSel0, scratch24); + s32(EmcPmacroBrickCtrlRfu1, scratch25); + s32(EmcPmacroBrickCtrlRfu2, scratch26); + s32(EmcPmcScratch1, scratch27); + s32(EmcPmcScratch2, scratch28); + s32(EmcPmcScratch3, scratch29); + s32(McEmemArbDaTurns, scratch30); + s(EmcFbioSpare, 31:24, scratch58, 7:0); + s(EmcFbioSpare, 23:16, scratch58, 15:8); + s(EmcFbioSpare, 15:8, scratch58, 23:16); + s(EmcFbioSpare, 7:2, scratch58, 29:24); + s(EmcFbioSpare, 0:0, scratch58, 30:30); + s(EmcDllCfg0, 29:0, scratch59, 29:0); + s(EmcPmacroDdllBypass, 11:0, scratch60, 11:0); + s(EmcPmacroDdllBypass, 27:13, scratch60, 26:12); + s(EmcPmacroDdllBypass, 31:29, scratch60, 29:27); + s(McEmemArbMisc0, 14:0, scratch61, 14:0); + s(McEmemArbMisc0, 30:16, scratch61, 29:15); + s(EmcFdpdCtrlCmd, 16:0, scratch62, 16:0); + s(EmcFdpdCtrlCmd, 31:20, scratch62, 28:17); + s(EmcAutoCalConfig2, 27:0, scratch63, 27:0); + s(EmcBurstRefreshNum, 3:0, scratch63, 31:28); + s(EmcPmacroZctrl, 27:0, scratch64, 27:0); + s(EmcTppd, 3:0, scratch64, 31:28); + s(EmcCfgDigDll, 10:0, scratch65, 10:0); + s(EmcCfgDigDll, 25:12, scratch65, 24:11); + s(EmcCfgDigDll, 27:27, scratch65, 25:25); + s(EmcCfgDigDll, 31:30, scratch65, 27:26); + s(EmcR2r, 3:0, scratch65, 31:28); + s(EmcFdpdCtrlDq, 16:0, scratch66, 16:0); + s(EmcFdpdCtrlDq, 28:20, scratch66, 25:17); + s(EmcFdpdCtrlDq, 31:30, scratch66, 27:26); + s(EmcW2w, 3:0, scratch66, 31:28); + s(EmcPmacroTxPwrd4, 13:0, scratch67, 13:0); + s(EmcPmacroTxPwrd4, 29:16, scratch67, 27:14); + s(EmcPmacroCommonPadTxCtrl, 3:0, scratch67, 31:28); + s(EmcPmacroTxPwrd5, 13:0, scratch68, 13:0); + s(EmcPmacroTxPwrd5, 29:16, scratch68, 27:14); + s(EmcPmacroDdllPwrd0, 4:0, scratch69, 4:0); + s(EmcPmacroDdllPwrd0, 12:6, scratch69, 11:5); + s(EmcPmacroDdllPwrd0, 20:14, scratch69, 18:12); + s(EmcPmacroDdllPwrd0, 28:22, scratch69, 25:19); + s(EmcPmacroDdllPwrd0, 31:30, scratch69, 27:26); + s(EmcCfg, 4:4, scratch69, 31:31); + s(EmcPmacroDdllPwrd1, 4:0, scratch70, 4:0); + s(EmcPmacroDdllPwrd1, 12:6, scratch70, 11:5); + s(EmcPmacroDdllPwrd1, 20:14, scratch70, 18:12); + s(EmcPmacroDdllPwrd1, 28:22, scratch70, 25:19); + s(EmcPmacroDdllPwrd1, 31:30, scratch70, 27:26); + s(EmcCfg, 5:5, scratch70, 31:31); + s(EmcPmacroDdllPwrd2, 4:0, scratch71, 4:0); + s(EmcPmacroDdllPwrd2, 12:6, scratch71, 11:5); + s(EmcPmacroDdllPwrd2, 20:14, scratch71, 18:12); + s(EmcPmacroDdllPwrd2, 28:22, scratch71, 25:19); + s(EmcPmacroDdllPwrd2, 31:30, scratch71, 27:26); + s(EmcFbioCfg5, 23:20, scratch71, 31:28); + s(EmcPmacroIbVrefDq_0, 6:0, scratch72, 6:0); + s(EmcPmacroIbVrefDq_0, 14:8, scratch72, 13:7); + s(EmcPmacroIbVrefDq_0, 22:16, scratch72, 20:14); + s(EmcPmacroIbVrefDq_0, 30:24, scratch72, 27:21); + s(EmcFbioCfg5, 15:13, scratch72, 30:28); + s(EmcCfg, 6:6, scratch72, 31:31); + s(EmcPmacroIbVrefDq_1, 6:0, scratch73, 6:0); + s(EmcPmacroIbVrefDq_1, 14:8, scratch73, 13:7); + s(EmcPmacroIbVrefDq_1, 22:16, scratch73, 20:14); + s(EmcPmacroIbVrefDq_1, 30:24, scratch73, 27:21); + s(EmcCfg2, 5:3, scratch73, 30:28); + s(EmcCfg, 7:7, scratch73, 31:31); + s(EmcPmacroIbVrefDqs_0, 6:0, scratch74, 6:0); + s(EmcPmacroIbVrefDqs_0, 14:8, scratch74, 13:7); + s(EmcPmacroIbVrefDqs_0, 22:16, scratch74, 20:14); + s(EmcPmacroIbVrefDqs_0, 30:24, scratch74, 27:21); + s(EmcCfg, 17:16, scratch74, 29:28); + s(EmcFbioCfg5, 1:0, scratch74, 31:30); + s(EmcPmacroIbVrefDqs_1, 6:0, scratch75, 6:0); + s(EmcPmacroIbVrefDqs_1, 14:8, scratch75, 13:7); + s(EmcPmacroIbVrefDqs_1, 22:16, scratch75, 20:14); + s(EmcPmacroIbVrefDqs_1, 30:24, scratch75, 27:21); + s(EmcFbioCfg5, 3:2, scratch75, 29:28); + s(EmcCfg2, 27:26, scratch75, 31:30); + s(EmcPmacroDdllShortCmd_0, 6:0, scratch76, 6:0); + s(EmcPmacroDdllShortCmd_0, 14:8, scratch76, 13:7); + s(EmcPmacroDdllShortCmd_0, 22:16, scratch76, 20:14); + s(EmcPmacroDdllShortCmd_0, 30:24, scratch76, 27:21); + s(EmcPmacroCmdPadTxCtrl, 3:2, scratch76, 29:28); + s(EmcPmacroCmdPadTxCtrl, 7:6, scratch76, 31:30); + s(EmcPmacroDdllShortCmd_1, 6:0, scratch77, 6:0); + s(EmcPmacroDdllShortCmd_1, 14:8, scratch77, 13:7); + s(EmcPmacroDdllShortCmd_1, 22:16, scratch77, 20:14); + s(EmcPmacroDdllShortCmd_1, 30:24, scratch77, 27:21); + s(EmcPmacroCmdPadTxCtrl, 11:10, scratch77, 29:28); + s(EmcPmacroCmdPadTxCtrl, 15:14, scratch77, 31:30); + s(EmcAutoCalChannel, 5:0, scratch78, 5:0); + s(EmcAutoCalChannel, 11:8, scratch78, 9:6); + s(EmcAutoCalChannel, 27:16, scratch78, 21:10); + s(EmcAutoCalChannel, 31:29, scratch78, 24:22); + s(EmcConfigSampleDelay, 6:0, scratch78, 31:25); + s(EmcPmacroRxTerm, 5:0, scratch79, 5:0); + s(EmcPmacroRxTerm, 13:8, scratch79, 11:6); + s(EmcPmacroRxTerm, 21:16, scratch79, 17:12); + s(EmcPmacroRxTerm, 29:24, scratch79, 23:18); + s(EmcRc, 7:0, scratch79, 31:24); + s(EmcPmacroDqTxDrv, 5:0, scratch80, 5:0); + s(EmcPmacroDqTxDrv, 13:8, scratch80, 11:6); + s(EmcPmacroDqTxDrv, 21:16, scratch80, 17:12); + s(EmcPmacroDqTxDrv, 29:24, scratch80, 23:18); + s(EmcSelDpdCtrl, 5:2, scratch80, 27:24); + s(EmcSelDpdCtrl, 8:8, scratch80, 28:28); + s(EmcSelDpdCtrl, 18:16, scratch80, 31:29); + s(EmcPmacroCaTxDrv, 5:0, scratch81, 5:0); + s(EmcPmacroCaTxDrv, 13:8, scratch81, 11:6); + s(EmcPmacroCaTxDrv, 21:16, scratch81, 17:12); + s(EmcPmacroCaTxDrv, 29:24, scratch81, 23:18); + s(EmcObdly, 5:0, scratch81, 29:24); + s(EmcObdly, 29:28, scratch81, 31:30); + s(EmcZcalInterval, 23:10, scratch82, 13:0); + s(EmcZcalInterval, 9:0, scratch82, 23:14); + s(EmcPmacroCmdRxTermMode, 1:0, scratch82, 25:24); + s(EmcPmacroCmdRxTermMode, 5:4, scratch82, 27:26); + s(EmcPmacroCmdRxTermMode, 9:8, scratch82, 29:28); + s(EmcPmacroCmdRxTermMode, 13:12, scratch82, 31:30); + s(EmcDataBrlshft0, 23:0, scratch83, 23:0); + s(EmcPmacroDataRxTermMode, 1:0, scratch83, 25:24); + s(EmcPmacroDataRxTermMode, 5:4, scratch83, 27:26); + s(EmcPmacroDataRxTermMode, 9:8, scratch83, 29:28); + s(EmcPmacroDataRxTermMode, 13:12, scratch83, 31:30); + s(EmcDataBrlshft1, 23:0, scratch84, 23:0); + s(McEmemArbTimingRc, 7:0, scratch84, 31:24); + s(EmcDqsBrlshft0, 23:0, scratch85, 23:0); + s(McEmemArbRsv, 7:0, scratch85, 31:24); + s(EmcDqsBrlshft1, 23:0, scratch86, 23:0); + s(EmcCfgPipe2, 11:0, scratch87, 11:0); + s(EmcCfgPipe2, 27:16, scratch87, 23:12); + s(EmcCfgPipe1, 11:0, scratch88, 11:0); + s(EmcCfgPipe1, 27:16, scratch88, 23:12); + s(EmcPmacroCmdCtrl0, 5:0, scratch89, 5:0); + s(EmcPmacroCmdCtrl0, 13:8, scratch89, 11:6); + s(EmcPmacroCmdCtrl0, 21:16, scratch89, 17:12); + s(EmcPmacroCmdCtrl0, 29:24, scratch89, 23:18); + s(EmcPmacroCmdCtrl1, 5:0, scratch90, 5:0); + s(EmcPmacroCmdCtrl1, 13:8, scratch90, 11:6); + s(EmcPmacroCmdCtrl1, 21:16, scratch90, 17:12); + s(EmcPmacroCmdCtrl1, 29:24, scratch90, 23:18); + s(EmcRas, 6:0, scratch90, 30:24); + s(EmcCfg, 8:8, scratch90, 31:31); + s(EmcPmacroVttgenCtrl2, 23:0, scratch91, 23:0); + s(EmcW2p, 6:0, scratch91, 30:24); + s(EmcCfg, 9:9, scratch91, 31:31); + s(EmcPmacroCmdPadRxCtrl, 2:0, scratch92, 2:0); + s(EmcPmacroCmdPadRxCtrl, 5:4, scratch92, 4:3); + s(EmcPmacroCmdPadRxCtrl, 10:8, scratch92, 7:5); + s(EmcPmacroCmdPadRxCtrl, 22:12, scratch92, 18:8); + s(EmcPmacroCmdPadRxCtrl, 28:24, scratch92, 23:19); + s(EmcQSafe, 6:0, scratch92, 30:24); + s(EmcCfg, 18:18, scratch92, 31:31); + s(EmcPmacroDataPadRxCtrl, 2:0, scratch93, 2:0); + s(EmcPmacroDataPadRxCtrl, 5:4, scratch93, 4:3); + s(EmcPmacroDataPadRxCtrl, 10:8, scratch93, 7:5); + s(EmcPmacroDataPadRxCtrl, 22:12, scratch93, 18:8); + s(EmcPmacroDataPadRxCtrl, 28:24, scratch93, 23:19); + s(EmcRdv, 6:0, scratch93, 30:24); + s(EmcCfg, 21:21, scratch93, 31:31); + s(McEmemArbDaCovers, 23:0, scratch94, 23:0); + s(EmcRw2Pden, 6:0, scratch94, 30:24); + s(EmcCfg, 22:22, scratch94, 31:31); + s(EmcPmacroCmdCtrl2, 5:0, scratch95, 5:0); + s(EmcPmacroCmdCtrl2, 13:9, scratch95, 10:6); + s(EmcPmacroCmdCtrl2, 21:16, scratch95, 16:11); + s(EmcPmacroCmdCtrl2, 29:24, scratch95, 22:17); + s(EmcRfcPb, 8:0, scratch95, 31:23); + s(EmcPmacroQuseDdllRank0_0, 10:0, scratch96, 10:0); + s(EmcPmacroQuseDdllRank0_0, 26:16, scratch96, 21:11); + s(EmcCfgUpdate, 2:0, scratch96, 24:22); + s(EmcCfgUpdate, 10:8, scratch96, 27:25); + s(EmcCfgUpdate, 31:28, scratch96, 31:28); + s(EmcPmacroQuseDdllRank0_1, 10:0, scratch97, 10:0); + s(EmcPmacroQuseDdllRank0_1, 26:16, scratch97, 21:11); + s(EmcRfc, 9:0, scratch97, 31:22); + s(EmcPmacroQuseDdllRank0_2, 10:0, scratch98, 10:0); + s(EmcPmacroQuseDdllRank0_2, 26:16, scratch98, 21:11); + s(EmcTxsr, 9:0, scratch98, 31:22); + s(EmcPmacroQuseDdllRank0_3, 10:0, scratch99, 10:0); + s(EmcPmacroQuseDdllRank0_3, 26:16, scratch99, 21:11); + s(EmcMc2EmcQ, 2:0, scratch99, 24:22); + s(EmcMc2EmcQ, 10:8, scratch99, 27:25); + s(EmcMc2EmcQ, 27:24, scratch99, 31:28); + s(EmcPmacroQuseDdllRank0_4, 10:0, scratch100, 10:0); + s(EmcPmacroQuseDdllRank0_4, 26:16, scratch100, 21:11); + s(McEmemArbRing1Throttle, 4:0, scratch100, 26:22); + s(McEmemArbRing1Throttle, 20:16, scratch100, 31:27); + s(EmcPmacroQuseDdllRank0_5, 10:0, scratch101, 10:0); + s(EmcPmacroQuseDdllRank0_5, 26:16, scratch101, 21:11); + s(EmcPmacroQuseDdllRank1_0, 10:0, scratch102, 10:0); + s(EmcPmacroQuseDdllRank1_0, 26:16, scratch102, 21:11); + s(EmcAr2Pden, 8:0, scratch102, 30:22); + s(EmcCfg, 23:23, scratch102, 31:31); + s(EmcPmacroQuseDdllRank1_1, 10:0, scratch103, 10:0); + s(EmcPmacroQuseDdllRank1_1, 26:16, scratch103, 21:11); + s(EmcRfcSlr, 8:0, scratch103, 30:22); + s(EmcCfg, 24:24, scratch103, 31:31); + s(EmcPmacroQuseDdllRank1_2, 10:0, scratch104, 10:0); + s(EmcPmacroQuseDdllRank1_2, 26:16, scratch104, 21:11); + s(EmcIbdly, 6:0, scratch104, 28:22); + s(EmcIbdly, 29:28, scratch104, 30:29); + s(EmcCfg, 25:25, scratch104, 31:31); + s(EmcPmacroQuseDdllRank1_3, 10:0, scratch105, 10:0); + s(EmcPmacroQuseDdllRank1_3, 26:16, scratch105, 21:11); + s(McEmemArbTimingRFCPB, 8:0, scratch105, 30:22); + s(EmcCfg, 26:26, scratch105, 31:31); + s(EmcPmacroQuseDdllRank1_4, 10:0, scratch106, 10:0); + s(EmcPmacroQuseDdllRank1_4, 26:16, scratch106, 21:11); + s(EmcTfaw, 6:0, scratch106, 28:22); + s(EmcPmacroDataPadTxCtrl, 3:2, scratch106, 30:29); + s(EmcCfg, 28:28, scratch106, 31:31); + s(EmcPmacroQuseDdllRank1_5, 10:0, scratch107, 10:0); + s(EmcPmacroQuseDdllRank1_5, 26:16, scratch107, 21:11); + s(EmcTClkStable, 6:0, scratch107, 28:22); + s(EmcPmacroDataPadTxCtrl, 7:6, scratch107, 30:29); + s(EmcCfg, 29:29, scratch107, 31:31); + s(EmcPmacroObDdllLongDqRank0_0, 10:0, scratch108, 10:0); + s(EmcPmacroObDdllLongDqRank0_0, 26:16, scratch108, 21:11); + s(EmcPdex2Mrr, 6:0, scratch108, 28:22); + s(EmcPmacroDataPadTxCtrl, 11:10, scratch108, 30:29); + s(EmcCfg, 30:30, scratch108, 31:31); + s(EmcPmacroObDdllLongDqRank0_1, 10:0, scratch109, 10:0); + s(EmcPmacroObDdllLongDqRank0_1, 26:16, scratch109, 21:11); + s(EmcRdvMask, 6:0, scratch109, 28:22); + s(EmcPmacroDataPadTxCtrl, 15:14, scratch109, 30:29); + s(EmcCfg, 31:31, scratch109, 31:31); + s(EmcPmacroObDdllLongDqRank0_2, 10:0, scratch110, 10:0); + s(EmcPmacroObDdllLongDqRank0_2, 26:16, scratch110, 21:11); + s(EmcRdvEarlyMask, 6:0, scratch110, 28:22); + s(EmcFbioCfg5, 4:4, scratch110, 29:29); + s(EmcFbioCfg5, 8:8, scratch110, 30:30); + s(EmcFbioCfg5, 10:10, scratch110, 31:31); + s(EmcPmacroObDdllLongDqRank0_3, 10:0, scratch111, 10:0); + s(EmcPmacroObDdllLongDqRank0_3, 26:16, scratch111, 21:11); + s(EmcRdvEarly, 6:0, scratch111, 28:22); + s(EmcFbioCfg5, 12:12, scratch111, 29:29); + s(EmcFbioCfg5, 25:24, scratch111, 31:30); + s(EmcPmacroObDdllLongDqRank0_4, 10:0, scratch112, 10:0); + s(EmcPmacroObDdllLongDqRank0_4, 26:16, scratch112, 21:11); + s(EmcPmacroDdllShortCmd_2, 6:0, scratch112, 28:22); + s(EmcFbioCfg5, 28:26, scratch112, 31:29); + s(EmcPmacroObDdllLongDqRank0_5, 10:0, scratch113, 10:0); + s(EmcPmacroObDdllLongDqRank0_5, 26:16, scratch113, 21:11); + s(McEmemArbTimingRp, 6:0, scratch113, 28:22); + s(EmcFbioCfg5, 31:30, scratch113, 30:29); + s(EmcCfg2, 0:0, scratch113, 31:31); + s(EmcPmacroObDdllLongDqRank1_0, 10:0, scratch114, 10:0); + s(EmcPmacroObDdllLongDqRank1_0, 26:16, scratch114, 21:11); + s(McEmemArbTimingRas, 6:0, scratch114, 28:22); + s(EmcCfg2, 2:1, scratch114, 30:29); + s(EmcCfg2, 7:7, scratch114, 31:31); + s(EmcPmacroObDdllLongDqRank1_1, 10:0, scratch115, 10:0); + s(EmcPmacroObDdllLongDqRank1_1, 26:16, scratch115, 21:11); + s(McEmemArbTimingFaw, 6:0, scratch115, 28:22); + s(EmcCfg2, 11:10, scratch115, 30:29); + s(EmcCfg2, 14:14, scratch115, 31:31); + s(EmcPmacroObDdllLongDqRank1_2, 10:0, scratch123, 10:0); + s(EmcPmacroObDdllLongDqRank1_2, 26:16, scratch123, 21:11); + s(McEmemArbTimingRap2Pre, 6:0, scratch123, 28:22); + s(EmcCfg2, 16:15, scratch123, 30:29); + s(EmcCfg2, 20:20, scratch123, 31:31); + s(EmcPmacroObDdllLongDqRank1_3, 10:0, scratch124, 10:0); + s(EmcPmacroObDdllLongDqRank1_3, 26:16, scratch124, 21:11); + s(McEmemArbTimingWap2Pre, 6:0, scratch124, 28:22); + s(EmcCfg2, 24:22, scratch124, 31:29); + s(EmcPmacroObDdllLongDqRank1_4, 10:0, scratch125, 10:0); + s(EmcPmacroObDdllLongDqRank1_4, 26:16, scratch125, 21:11); + s(McEmemArbTimingR2W, 6:0, scratch125, 28:22); + s(EmcCfg2, 25:25, scratch125, 29:29); + s(EmcCfg2, 29:28, scratch125, 31:30); + s(EmcPmacroObDdllLongDqRank1_5, 10:0, scratch126, 10:0); + s(EmcPmacroObDdllLongDqRank1_5, 26:16, scratch126, 21:11); + s(McEmemArbTimingW2R, 6:0, scratch126, 28:22); + s(EmcCfg2, 31:30, scratch126, 30:29); + s(EmcCfgPipe, 0:0, scratch126, 31:31); + s(EmcPmacroObDdllLongDqsRank0_0, 10:0, scratch127, 10:0); + s(EmcPmacroObDdllLongDqsRank0_0, 26:16, scratch127, 21:11); + s(EmcRp, 5:0, scratch127, 27:22); + s(EmcCfgPipe, 4:1, scratch127, 31:28); + s(EmcPmacroObDdllLongDqsRank0_1, 10:0, scratch128, 10:0); + s(EmcPmacroObDdllLongDqsRank0_1, 26:16, scratch128, 21:11); + s(EmcR2w, 5:0, scratch128, 27:22); + s(EmcCfgPipe, 8:5, scratch128, 31:28); + s(EmcPmacroObDdllLongDqsRank0_2, 10:0, scratch129, 10:0); + s(EmcPmacroObDdllLongDqsRank0_2, 26:16, scratch129, 21:11); + s(EmcW2r, 5:0, scratch129, 27:22); + s(EmcCfgPipe, 11:9, scratch129, 30:28); + s(EmcCfgPipe, 16:16, scratch129, 31:31); + s(EmcPmacroObDdllLongDqsRank0_3, 10:0, scratch130, 10:0); + s(EmcPmacroObDdllLongDqsRank0_3, 26:16, scratch130, 21:11); + s(EmcR2p, 5:0, scratch130, 27:22); + s(EmcCfgPipe, 20:17, scratch130, 31:28); + s(EmcPmacroObDdllLongDqsRank0_4, 10:0, scratch131, 10:0); + s(EmcPmacroObDdllLongDqsRank0_4, 26:16, scratch131, 21:11); + s(EmcCcdmw, 5:0, scratch131, 27:22); + s(EmcCfgPipe, 24:21, scratch131, 31:28); + s(EmcPmacroObDdllLongDqsRank0_5, 10:0, scratch132, 10:0); + s(EmcPmacroObDdllLongDqsRank0_5, 26:16, scratch132, 21:11); + s(EmcRdRcd, 5:0, scratch132, 27:22); + s(EmcCfgPipe, 27:25, scratch132, 30:28); + s(EmcPmacroTxPwrd0, 0:0, scratch132, 31:31); + s(EmcPmacroObDdllLongDqsRank1_0, 10:0, scratch133, 10:0); + s(EmcPmacroObDdllLongDqsRank1_0, 26:16, scratch133, 21:11); + s(EmcWrRcd, 5:0, scratch133, 27:22); + s(EmcPmacroTxPwrd0, 4:1, scratch133, 31:28); + s(EmcPmacroObDdllLongDqsRank1_1, 10:0, scratch134, 10:0); + s(EmcPmacroObDdllLongDqsRank1_1, 26:16, scratch134, 21:11); + s(EmcWdv, 5:0, scratch134, 27:22); + s(EmcPmacroTxPwrd0, 8:5, scratch134, 31:28); + s(EmcPmacroObDdllLongDqsRank1_2, 10:0, scratch135, 10:0); + s(EmcPmacroObDdllLongDqsRank1_2, 26:16, scratch135, 21:11); + s(EmcQUse, 5:0, scratch135, 27:22); + s(EmcPmacroTxPwrd0, 12:9, scratch135, 31:28); + s(EmcPmacroObDdllLongDqsRank1_3, 10:0, scratch136, 10:0); + s(EmcPmacroObDdllLongDqsRank1_3, 26:16, scratch136, 21:11); + s(EmcPdEx2Wr, 5:0, scratch136, 27:22); + s(EmcPmacroTxPwrd0, 13:13, scratch136, 28:28); + s(EmcPmacroTxPwrd0, 18:16, scratch136, 31:29); + s(EmcPmacroObDdllLongDqsRank1_4, 10:0, scratch137, 10:0); + s(EmcPmacroObDdllLongDqsRank1_4, 26:16, scratch137, 21:11); + s(EmcPdEx2Rd, 5:0, scratch137, 27:22); + s(EmcPmacroTxPwrd0, 22:19, scratch137, 31:28); + s(EmcPmacroObDdllLongDqsRank1_5, 10:0, scratch138, 10:0); + s(EmcPmacroObDdllLongDqsRank1_5, 26:16, scratch138, 21:11); + s(EmcPdex2Cke, 5:0, scratch138, 27:22); + s(EmcPmacroTxPwrd0, 26:23, scratch138, 31:28); + s(EmcPmacroIbDdllLongDqsRank0_0, 10:0, scratch139, 10:0); + s(EmcPmacroIbDdllLongDqsRank0_0, 26:16, scratch139, 21:11); + s(EmcPChg2Pden, 5:0, scratch139, 27:22); + s(EmcPmacroTxPwrd0, 29:27, scratch139, 30:28); + s(EmcPmacroTxPwrd1, 0:0, scratch139, 31:31); + s(EmcPmacroIbDdllLongDqsRank0_1, 10:0, scratch140, 10:0); + s(EmcPmacroIbDdllLongDqsRank0_1, 26:16, scratch140, 21:11); + s(EmcAct2Pden, 5:0, scratch140, 27:22); + s(EmcPmacroTxPwrd1, 4:1, scratch140, 31:28); + s(EmcPmacroIbDdllLongDqsRank0_2, 10:0, scratch141, 10:0); + s(EmcPmacroIbDdllLongDqsRank0_2, 26:16, scratch141, 21:11); + s(EmcCke2Pden, 5:0, scratch141, 27:22); + s(EmcPmacroTxPwrd1, 8:5, scratch141, 31:28); + s(EmcPmacroIbDdllLongDqsRank0_3, 10:0, scratch142, 10:0); + s(EmcPmacroIbDdllLongDqsRank0_3, 26:16, scratch142, 21:11); + s(EmcTcke, 5:0, scratch142, 27:22); + s(EmcPmacroTxPwrd1, 12:9, scratch142, 31:28); + s(EmcPmacroIbDdllLongDqsRank1_0, 10:0, scratch143, 10:0); + s(EmcPmacroIbDdllLongDqsRank1_0, 26:16, scratch143, 21:11); + s(EmcTrpab, 5:0, scratch143, 27:22); + s(EmcPmacroTxPwrd1, 13:13, scratch143, 28:28); + s(EmcPmacroTxPwrd1, 18:16, scratch143, 31:29); + s(EmcPmacroIbDdllLongDqsRank1_1, 10:0, scratch144, 10:0); + s(EmcPmacroIbDdllLongDqsRank1_1, 26:16, scratch144, 21:11); + s(EmcClkenOverride, 3:1, scratch144, 24:22); + s(EmcClkenOverride, 8:6, scratch144, 27:25); + s(EmcPmacroTxPwrd1, 22:19, scratch144, 31:28); + s(EmcPmacroIbDdllLongDqsRank1_2, 10:0, scratch145, 10:0); + s(EmcPmacroIbDdllLongDqsRank1_2, 26:16, scratch145, 21:11); + s(EmcEInput, 5:0, scratch145, 27:22); + s(EmcPmacroTxPwrd1, 26:23, scratch145, 31:28); + s(EmcPmacroIbDdllLongDqsRank1_3, 10:0, scratch146, 10:0); + s(EmcPmacroIbDdllLongDqsRank1_3, 26:16, scratch146, 21:11); + s(EmcEInputDuration, 5:0, scratch146, 27:22); + s(EmcPmacroTxPwrd1, 29:27, scratch146, 30:28); + s(EmcPmacroTxPwrd2, 0:0, scratch146, 31:31); + s(EmcPmacroDdllLongCmd_0, 10:0, scratch147, 10:0); + s(EmcPmacroDdllLongCmd_0, 26:16, scratch147, 21:11); + s(EmcPutermExtra, 5:0, scratch147, 27:22); + s(EmcPmacroTxPwrd2, 4:1, scratch147, 31:28); + s(EmcPmacroDdllLongCmd_1, 10:0, scratch148, 10:0); + s(EmcPmacroDdllLongCmd_1, 26:16, scratch148, 21:11); + s(EmcTckesr, 5:0, scratch148, 27:22); + s(EmcPmacroTxPwrd2, 8:5, scratch148, 31:28); + s(EmcPmacroDdllLongCmd_2, 10:0, scratch149, 10:0); + s(EmcPmacroDdllLongCmd_2, 26:16, scratch149, 21:11); + s(EmcTpd, 5:0, scratch149, 27:22); + s(EmcPmacroTxPwrd2, 12:9, scratch149, 31:28); + s(EmcPmacroDdllLongCmd_3, 10:0, scratch150, 10:0); + s(EmcPmacroDdllLongCmd_3, 26:16, scratch150, 21:11); + s(EmcWdvMask, 5:0, scratch150, 27:22); + s(EmcPmacroTxPwrd2, 13:13, scratch150, 28:28); + s(EmcPmacroTxPwrd2, 18:16, scratch150, 31:29); + s(McEmemArbCfg, 8:0, scratch151, 8:0); + s(McEmemArbCfg, 20:16, scratch151, 13:9); + s(McEmemArbCfg, 31:24, scratch151, 21:14); + s(EmcWdvChk, 5:0, scratch151, 27:22); + s(EmcPmacroTxPwrd2, 22:19, scratch151, 31:28); + s(McEmemArbMisc1, 12:0, scratch152, 12:0); + s(McEmemArbMisc1, 25:21, scratch152, 17:13); + s(McEmemArbMisc1, 31:28, scratch152, 21:18); + s(EmcCmdBrlshft0, 5:0, scratch152, 27:22); + s(EmcPmacroTxPwrd2, 26:23, scratch152, 31:28); + s(EmcMrsWaitCnt2, 9:0, scratch153, 9:0); + s(EmcMrsWaitCnt2, 26:16, scratch153, 20:10); + s(EmcPmacroIbRxrt, 10:0, scratch153, 31:21); + s(EmcMrsWaitCnt, 9:0, scratch154, 9:0); + s(EmcMrsWaitCnt, 26:16, scratch154, 20:10); + s(EmcPmacroDdllLongCmd_4, 10:0, scratch154, 31:21); + s(EmcAutoCalInterval, 20:0, scratch155, 20:0); + s(McEmemArbOutstandingReq, 8:0, scratch155, 29:21); + s(McEmemArbOutstandingReq, 31:30, scratch155, 31:30); + s(McEmemArbRefpbHpCtrl, 6:0, scratch156, 6:0); + s(McEmemArbRefpbHpCtrl, 14:8, scratch156, 13:7); + s(McEmemArbRefpbHpCtrl, 22:16, scratch156, 20:14); + s(EmcCmdBrlshft1, 5:0, scratch156, 26:21); + s(EmcRrd, 4:0, scratch156, 31:27); + s(EmcQuseBrlshft0, 19:0, scratch157, 19:0); + s(EmcFbioCfg8, 27:16, scratch157, 31:20); + s(EmcQuseBrlshft1, 19:0, scratch158, 19:0); + s(EmcTxsrDll, 11:0, scratch158, 31:20); + s(EmcQuseBrlshft2, 19:0, scratch159, 19:0); + s(EmcTxdsrvttgen, 11:0, scratch159, 31:20); + s(EmcQuseBrlshft3, 19:0, scratch160, 19:0); + s(EmcPmacroVttgenCtrl0, 3:0, scratch160, 23:20); + s(EmcPmacroVttgenCtrl0, 11:8, scratch160, 27:24); + s(EmcPmacroVttgenCtrl0, 19:16, scratch160, 31:28); + s(EmcPmacroVttgenCtrl1, 19:0, scratch161, 19:0); + s(EmcCmdBrlshft2, 5:0, scratch161, 25:20); + s(EmcCmdBrlshft3, 5:0, scratch161, 31:26); + s(EmcAutoCalConfig3, 5:0, scratch162, 5:0); + s(EmcAutoCalConfig3, 13:8, scratch162, 11:6); + s(EmcAutoCalConfig3, 18:16, scratch162, 14:12); + s(EmcAutoCalConfig3, 22:20, scratch162, 17:15); + s(EmcTRefBw, 13:0, scratch162, 31:18); + s(EmcAutoCalConfig4, 5:0, scratch163, 5:0); + s(EmcAutoCalConfig4, 13:8, scratch163, 11:6); + s(EmcAutoCalConfig4, 18:16, scratch163, 14:12); + s(EmcAutoCalConfig4, 22:20, scratch163, 17:15); + s(EmcQpop, 6:0, scratch163, 24:18); + s(EmcQpop, 22:16, scratch163, 31:25); + s(EmcAutoCalConfig5, 5:0, scratch164, 5:0); + s(EmcAutoCalConfig5, 13:8, scratch164, 11:6); + s(EmcAutoCalConfig5, 18:16, scratch164, 14:12); + s(EmcAutoCalConfig5, 22:20, scratch164, 17:15); + s(EmcPmacroAutocalCfgCommon, 5:0, scratch164, 23:18); + s(EmcPmacroAutocalCfgCommon, 13:8, scratch164, 29:24); + s(EmcPmacroAutocalCfgCommon, 16:16, scratch164, 30:30); + s(EmcPmacroTxPwrd2, 27:27, scratch164, 31:31); + s(EmcAutoCalConfig6, 5:0, scratch165, 5:0); + s(EmcAutoCalConfig6, 13:8, scratch165, 11:6); + s(EmcAutoCalConfig6, 18:16, scratch165, 14:12); + s(EmcAutoCalConfig6, 22:20, scratch165, 17:15); + s(EmcWev, 5:0, scratch165, 23:18); + s(EmcWsv, 5:0, scratch165, 29:24); + s(EmcPmacroTxPwrd2, 29:28, scratch165, 31:30); + s(EmcAutoCalConfig7, 5:0, scratch166, 5:0); + s(EmcAutoCalConfig7, 13:8, scratch166, 11:6); + s(EmcAutoCalConfig7, 18:16, scratch166, 14:12); + s(EmcAutoCalConfig7, 22:20, scratch166, 17:15); + s(EmcCfg3, 2:0, scratch166, 20:18); + s(EmcCfg3, 6:4, scratch166, 23:21); + s(EmcQuseWidth, 3:0, scratch166, 27:24); + s(EmcQuseWidth, 29:28, scratch166, 29:28); + s(EmcPmacroTxPwrd3, 1:0, scratch166, 31:30); + s(EmcAutoCalConfig8, 5:0, scratch167, 5:0); + s(EmcAutoCalConfig8, 13:8, scratch167, 11:6); + s(EmcAutoCalConfig8, 18:16, scratch167, 14:12); + s(EmcAutoCalConfig8, 22:20, scratch167, 17:15); + s(EmcPmacroBgBiasCtrl0, 2:0, scratch167, 20:18); + s(EmcPmacroBgBiasCtrl0, 6:4, scratch167, 23:21); + s(McEmemArbTimingRcd, 5:0, scratch167, 29:24); + s(EmcPmacroTxPwrd3, 3:2, scratch167, 31:30); + s(EmcXm2CompPadCtrl2, 17:0, scratch168, 17:0); + s(McEmemArbTimingCcdmw, 5:0, scratch168, 23:18); + s(McEmemArbOverride, 27:27, scratch168, 24:24); + s(McEmemArbOverride, 26:26, scratch168, 25:25); + s(McEmemArbOverride, 16:16, scratch168, 26:26); + s(McEmemArbOverride, 10:10, scratch168, 27:27); + s(McEmemArbOverride, 4:4, scratch168, 28:28); + s(McEmemArbOverride, 3:3, scratch168, 29:29); + s(EmcPmacroTxPwrd3, 5:4, scratch168, 31:30); + s(EmcXm2CompPadCtrl3, 17:0, scratch169, 17:0); + s(EmcRext, 4:0, scratch169, 22:18); + s(EmcTClkStop, 4:0, scratch169, 27:23); + s(EmcPmacroTxPwrd3, 9:6, scratch169, 31:28); + s(EmcZcalWaitCnt, 10:0, scratch170, 10:0); + s(EmcZcalWaitCnt, 21:16, scratch170, 16:11); + s(EmcZcalWaitCnt, 31:31, scratch170, 17:17); + s(EmcWext, 4:0, scratch170, 22:18); + s(EmcRefctrl2, 0:0, scratch170, 23:23); + s(EmcRefctrl2, 26:24, scratch170, 26:24); + s(EmcRefctrl2, 31:31, scratch170, 27:27); + s(EmcPmacroTxPwrd3, 13:10, scratch170, 31:28); + s(EmcZcalMrwCmd, 7:0, scratch171, 7:0); + s(EmcZcalMrwCmd, 23:16, scratch171, 15:8); + s(EmcZcalMrwCmd, 31:30, scratch171, 17:16); + s(EmcWeDuration, 4:0, scratch171, 22:18); + s(EmcWsDuration, 4:0, scratch171, 27:23); + s(EmcPmacroTxPwrd3, 19:16, scratch171, 31:28); + s(EmcSwizzleRank0Byte0, 2:0, scratch172, 2:0); + s(EmcSwizzleRank0Byte0, 6:4, scratch172, 5:3); + s(EmcSwizzleRank0Byte0, 10:8, scratch172, 8:6); + s(EmcSwizzleRank0Byte0, 14:12, scratch172, 11:9); + s(EmcSwizzleRank0Byte0, 18:16, scratch172, 14:12); + s(EmcSwizzleRank0Byte0, 22:20, scratch172, 17:15); + s(EmcPutermWidth, 31:31, scratch172, 18:18); + s(EmcPutermWidth, 3:0, scratch172, 22:19); + s(McEmemArbTimingRrd, 4:0, scratch172, 27:23); + s(EmcPmacroTxPwrd3, 23:20, scratch172, 31:28); + s(EmcSwizzleRank0Byte1, 2:0, scratch173, 2:0); + s(EmcSwizzleRank0Byte1, 6:4, scratch173, 5:3); + s(EmcSwizzleRank0Byte1, 10:8, scratch173, 8:6); + s(EmcSwizzleRank0Byte1, 14:12, scratch173, 11:9); + s(EmcSwizzleRank0Byte1, 18:16, scratch173, 14:12); + s(EmcSwizzleRank0Byte1, 22:20, scratch173, 17:15); + s(McEmemArbTimingR2R, 4:0, scratch173, 22:18); + s(McEmemArbTimingW2W, 4:0, scratch173, 27:23); + s(EmcPmacroTxPwrd3, 27:24, scratch173, 31:28); + s(EmcSwizzleRank0Byte2, 2:0, scratch174, 2:0); + s(EmcSwizzleRank0Byte2, 6:4, scratch174, 5:3); + s(EmcSwizzleRank0Byte2, 10:8, scratch174, 8:6); + s(EmcSwizzleRank0Byte2, 14:12, scratch174, 11:9); + s(EmcSwizzleRank0Byte2, 18:16, scratch174, 14:12); + s(EmcSwizzleRank0Byte2, 22:20, scratch174, 17:15); + s(EmcPmacroTxPwrd3, 29:28, scratch174, 19:18); + s(EmcPmacroTxSelClkSrc0, 11:0, scratch174, 31:20); + s(EmcSwizzleRank0Byte3, 2:0, scratch175, 2:0); + s(EmcSwizzleRank0Byte3, 6:4, scratch175, 5:3); + s(EmcSwizzleRank0Byte3, 10:8, scratch175, 8:6); + s(EmcSwizzleRank0Byte3, 14:12, scratch175, 11:9); + s(EmcSwizzleRank0Byte3, 18:16, scratch175, 14:12); + s(EmcSwizzleRank0Byte3, 22:20, scratch175, 17:15); + s(EmcPmacroTxSelClkSrc0, 27:16, scratch175, 29:18); + s(EmcPmacroTxSelClkSrc1, 1:0, scratch175, 31:30); + s(EmcSwizzleRank1Byte0, 2:0, scratch176, 2:0); + s(EmcSwizzleRank1Byte0, 6:4, scratch176, 5:3); + s(EmcSwizzleRank1Byte0, 10:8, scratch176, 8:6); + s(EmcSwizzleRank1Byte0, 14:12, scratch176, 11:9); + s(EmcSwizzleRank1Byte0, 18:16, scratch176, 14:12); + s(EmcSwizzleRank1Byte0, 22:20, scratch176, 17:15); + s(EmcPmacroTxSelClkSrc1, 11:2, scratch176, 27:18); + s(EmcPmacroTxSelClkSrc1, 19:16, scratch176, 31:28); + s(EmcSwizzleRank1Byte1, 2:0, scratch177, 2:0); + s(EmcSwizzleRank1Byte1, 6:4, scratch177, 5:3); + s(EmcSwizzleRank1Byte1, 10:8, scratch177, 8:6); + s(EmcSwizzleRank1Byte1, 14:12, scratch177, 11:9); + s(EmcSwizzleRank1Byte1, 18:16, scratch177, 14:12); + s(EmcSwizzleRank1Byte1, 22:20, scratch177, 17:15); + s(EmcPmacroTxSelClkSrc1, 27:20, scratch177, 25:18); + s(EmcPmacroTxSelClkSrc3, 5:0, scratch177, 31:26); + s(EmcSwizzleRank1Byte2, 2:0, scratch178, 2:0); + s(EmcSwizzleRank1Byte2, 6:4, scratch178, 5:3); + s(EmcSwizzleRank1Byte2, 10:8, scratch178, 8:6); + s(EmcSwizzleRank1Byte2, 14:12, scratch178, 11:9); + s(EmcSwizzleRank1Byte2, 18:16, scratch178, 14:12); + s(EmcSwizzleRank1Byte2, 22:20, scratch178, 17:15); + s(EmcPmacroTxSelClkSrc3, 11:6, scratch178, 23:18); + s(EmcPmacroTxSelClkSrc3, 23:16, scratch178, 31:24); + s(EmcSwizzleRank1Byte3, 2:0, scratch179, 2:0); + s(EmcSwizzleRank1Byte3, 6:4, scratch179, 5:3); + s(EmcSwizzleRank1Byte3, 10:8, scratch179, 8:6); + s(EmcSwizzleRank1Byte3, 14:12, scratch179, 11:9); + s(EmcSwizzleRank1Byte3, 18:16, scratch179, 14:12); + s(EmcSwizzleRank1Byte3, 22:20, scratch179, 17:15); + s(EmcPmacroTxSelClkSrc3, 27:24, scratch179, 21:18); + s(EmcPmacroTxSelClkSrc2, 9:0, scratch179, 31:22); + s(EmcPmacroCmdBrickCtrlFdpd, 17:0, scratch180, 17:0); + s(EmcPmacroTxSelClkSrc2, 11:10, scratch180, 19:18); + s(EmcPmacroTxSelClkSrc2, 27:16, scratch180, 31:20); + s(EmcPmacroDataBrickCtrlFdpd, 17:0, scratch181, 17:0); + s(EmcPmacroTxSelClkSrc4, 11:0, scratch181, 29:18); + s(EmcPmacroTxSelClkSrc4, 17:16, scratch181, 31:30); + s(EmcFbioCfg7, 16:0, scratch182, 16:0); + s(McEmemArbRefpbBankCtrl, 6:0, scratch182, 23:17); + s(McEmemArbRefpbBankCtrl, 14:8, scratch182, 30:24); + s(McEmemArbRefpbBankCtrl, 31:31, scratch182, 31:31); + s(EmcDynSelfRefControl, 15:0, scratch183, 15:0); + s(EmcDynSelfRefControl, 31:31, scratch183, 16:16); + s(EmcPmacroTxSelClkSrc4, 27:18, scratch183, 26:17); + s(EmcPmacroTxSelClkSrc5, 4:0, scratch183, 31:27); + s(EmcDllCfg1, 16:0, scratch184, 16:0); + s(EmcPmacroTxSelClkSrc5, 11:5, scratch184, 23:17); + s(EmcPmacroTxSelClkSrc5, 23:16, scratch184, 31:24); + s(EmcPmacroPadCfgCtrl, 1:0, scratch185, 1:0); + s(EmcPmacroPadCfgCtrl, 6:5, scratch185, 3:2); + s(EmcPmacroPadCfgCtrl, 11:9, scratch185, 6:4); + s(EmcPmacroPadCfgCtrl, 13:13, scratch185, 7:7); + s(EmcPmacroPadCfgCtrl, 17:16, scratch185, 9:8); + s(EmcPmacroPadCfgCtrl, 21:20, scratch185, 11:10); + s(EmcPmacroPadCfgCtrl, 25:24, scratch185, 13:12); + s(EmcPmacroPadCfgCtrl, 30:28, scratch185, 16:14); + s(EmcPmacroTxSelClkSrc5, 27:24, scratch185, 20:17); + s(EmcPmacroCmdPadTxCtrl, 1:0, scratch185, 22:21); + s(EmcPmacroCmdPadTxCtrl, 5:4, scratch185, 24:23); + s(EmcPmacroCmdPadTxCtrl, 9:8, scratch185, 26:25); + s(EmcPmacroCmdPadTxCtrl, 13:12, scratch185, 28:27); + s(EmcPmacroCmdPadTxCtrl, 16:16, scratch185, 29:29); + s(EmcPmacroCmdPadTxCtrl, 21:20, scratch185, 31:30); + s(EmcRefresh, 15:0, scratch186, 15:0); + s(EmcCmdQ, 4:0, scratch186, 20:16); + s(EmcCmdQ, 10:8, scratch186, 23:21); + s(EmcCmdQ, 14:12, scratch186, 26:24); + s(EmcCmdQ, 28:24, scratch186, 31:27); + s(EmcAcpdControl, 15:0, scratch187, 15:0); + s(EmcAutoCalVrefSel1, 15:0, scratch187, 31:16); + s(EmcXm2CompPadCtrl, 1:0, scratch188, 1:0); + s(EmcXm2CompPadCtrl, 6:3, scratch188, 5:2); + s(EmcXm2CompPadCtrl, 9:9, scratch188, 6:6); + s(EmcXm2CompPadCtrl, 19:11, scratch188, 15:7); + s(EmcCfgDigDllPeriod, 15:0, scratch188, 31:16); + s(EmcCfgDigDll_1, 15:0, scratch189, 15:0); + s(EmcPreRefreshReqCnt, 15:0, scratch189, 31:16); + s(EmcPmacroCmdPadTxCtrl, 27:24, scratch190, 19:16); + s(EmcPmacroDataPadTxCtrl, 1:0, scratch190, 21:20); + s(EmcPmacroDataPadTxCtrl, 5:4, scratch190, 23:22); + s(EmcPmacroDataPadTxCtrl, 9:8, scratch190, 25:24); + s(EmcPmacroDataPadTxCtrl, 13:12, scratch190, 27:26); + s(EmcPmacroDataPadTxCtrl, 16:16, scratch190, 28:28); + s(EmcPmacroDataPadTxCtrl, 21:20, scratch190, 30:29); + s(EmcPmacroDataPadTxCtrl, 24:24, scratch190, 31:31); + s(EmcPmacroDataPadTxCtrl, 27:25, scratch191, 2:0); + + s(EmcPinGpio, 1:0, scratch8, 31:30); + s(EmcPinGpioEn, 1:0, scratch9, 31:30); + s(EmcDevSelect, 1:0, scratch10, 31:30); + s(EmcZcalWarmColdBootEnables, 1:0, scratch11, 31:30); + s(EmcCfgDigDllPeriodWarmBoot, 1:0, scratch12, 31:30); + s32(EmcBctSpare13, scratch31); + s32(EmcBctSpare12, scratch32); + s32(EmcBctSpare7, scratch33); + s32(EmcBctSpare6, scratch40); + s32(EmcBctSpare5, scratch42); + s32(EmcBctSpare4, scratch44); + s32(EmcBctSpare3, scratch45); + s32(EmcBctSpare2, scratch46); + s32(EmcBctSpare1, scratch47); + s32(EmcBctSpare0, scratch48); + s32(EmcBctSpare9, scratch50); + s32(EmcBctSpare8, scratch51); + s32(BootRomPatchData, scratch56); + s32(BootRomPatchControl, scratch57); + s(McClkenOverrideAllWarmBoot, 0:0, scratch58, 31:31); + s(EmcClkenOverrideAllWarmBoot, 0:0, scratch59, 30:30); + s(EmcMrsWarmBootEnable, 0:0, scratch59, 31:31); + s(ClearClk2Mc1, 0:0, scratch60, 30:30); + s(EmcWarmBootExtraModeRegWriteEnable, 0:0, scratch60, 31:31); + s(ClkRstControllerPllmMisc2OverrideEnable, 0:0, scratch61, 30:30); + s(EmcDbgWriteMux, 0:0, scratch61, 31:31); + s(EmcExtraRefreshNum, 2:0, scratch62, 31:29); + s(PmcIoDpd3ReqWait, 2:0, scratch68, 30:28); + s(AhbArbitrationXbarCtrlMemInitDone, 0:0, scratch68, 31:31); + s(MemoryType, 2:0, scratch69, 30:28); + s(PmcIoDpd4ReqWait, 2:0, scratch70, 30:28); + s(EmcTimingControlWait, 7:0, scratch86, 31:24); + s(EmcZcalWarmBootWait, 7:0, scratch87, 31:24); + s(WarmBootWait, 7:0, scratch88, 31:24); + s(EmcPinProgramWait, 7:0, scratch89, 31:24); + s(EmcAutoCalWait, 9:0, scratch101, 31:22); + s(SwizzleRankByteEncode, 15:0, scratch190, 15:0); + + switch (sdram->MemoryType) + { + case NvBootMemoryType_LpDdr2: + case NvBootMemoryType_LpDdr4: + s(EmcMrwLpddr2ZcalWarmBoot, 23:16, scratch5, 7:0); + s(EmcMrwLpddr2ZcalWarmBoot, 7:0, scratch5, 15:8); + s(EmcWarmBootMrwExtra, 23:16, scratch5, 23:16); + s(EmcWarmBootMrwExtra, 7:0, scratch5, 31:24); + s(EmcMrwLpddr2ZcalWarmBoot, 31:30, scratch6, 1:0); + s(EmcWarmBootMrwExtra, 31:30, scratch6, 3:2); + s(EmcMrwLpddr2ZcalWarmBoot, 27:26, scratch6, 5:4); + s(EmcWarmBootMrwExtra, 27:26, scratch6, 7:6); + s(EmcMrw6, 27:0, scratch8, 27:0); + s(EmcMrw6, 31:30, scratch8, 29:28); + s(EmcMrw8, 27:0, scratch9, 27:0); + s(EmcMrw8, 31:30, scratch9, 29:28); + s(EmcMrw9, 27:0, scratch10, 27:0); + s(EmcMrw9, 31:30, scratch10, 29:28); + s(EmcMrw10, 27:0, scratch11, 27:0); + s(EmcMrw10, 31:30, scratch11, 29:28); + s(EmcMrw12, 27:0, scratch12, 27:0); + s(EmcMrw12, 31:30, scratch12, 29:28); + s(EmcMrw13, 27:0, scratch13, 27:0); + s(EmcMrw13, 31:30, scratch13, 29:28); + s(EmcMrw14, 27:0, scratch14, 27:0); + s(EmcMrw14, 31:30, scratch14, 29:28); + s(EmcMrw1, 7:0, scratch15, 7:0); + s(EmcMrw1, 23:16, scratch15, 15:8); + s(EmcMrw1, 27:26, scratch15, 17:16); + s(EmcMrw1, 31:30, scratch15, 19:18); + s(EmcWarmBootMrwExtra, 7:0, scratch16, 7:0); + s(EmcWarmBootMrwExtra, 23:16, scratch16, 15:8); + s(EmcWarmBootMrwExtra, 27:26, scratch16, 17:16); + s(EmcWarmBootMrwExtra, 31:30, scratch16, 19:18); + s(EmcMrw2, 7:0, scratch17, 7:0); + s(EmcMrw2, 23:16, scratch17, 15:8); + s(EmcMrw2, 27:26, scratch17, 17:16); + s(EmcMrw2, 31:30, scratch17, 19:18); + s(EmcMrw3, 7:0, scratch18, 7:0); + s(EmcMrw3, 23:16, scratch18, 15:8); + s(EmcMrw3, 27:26, scratch18, 17:16); + s(EmcMrw3, 31:30, scratch18, 19:18); + s(EmcMrw4, 7:0, scratch19, 7:0); + s(EmcMrw4, 23:16, scratch19, 15:8); + s(EmcMrw4, 27:26, scratch19, 17:16); + s(EmcMrw4, 31:30, scratch19, 19:18); + break; + case NvBootMemoryType_Ddr3: + s(EmcMrs, 13:0, scratch5, 13:0); + s(EmcEmrs, 13:0, scratch5, 27:14); + s(EmcMrs, 21:20, scratch5, 29:28); + s(EmcMrs, 31:30, scratch5, 31:30); + s(EmcEmrs2, 13:0, scratch8, 13:0); + s(EmcEmrs3, 13:0, scratch8, 27:14); + s(EmcEmrs, 21:20, scratch8, 29:28); + s(EmcWarmBootMrsExtra, 13:0, scratch9, 13:0); + s(EmcEmrs, 31:30, scratch9, 15:14); + s(EmcEmrs2, 21:20, scratch9, 17:16); + s(EmcEmrs2, 31:30, scratch9, 19:18); + s(EmcEmrs3, 21:20, scratch9, 21:20); + s(EmcEmrs3, 31:30, scratch9, 23:22); + s(EmcWarmBootMrsExtra, 31:30, scratch9, 25:24); + s(EmcWarmBootMrsExtra, 21:20, scratch9, 27:26); + s(EmcZqCalDdr3WarmBoot, 31:30, scratch9, 29:28); + s(EmcMrs, 27:26, scratch10, 1:0); + s(EmcEmrs, 27:26, scratch10, 3:2); + s(EmcEmrs2, 27:26, scratch10, 5:4); + s(EmcEmrs3, 27:26, scratch10, 7:6); + s(EmcWarmBootMrsExtra, 27:27, scratch10, 8:8); + s(EmcWarmBootMrsExtra, 26:26, scratch10, 9:9); + s(EmcZqCalDdr3WarmBoot, 0:0, scratch10, 10:10); + s(EmcZqCalDdr3WarmBoot, 4:4, scratch10, 11:11); + break; + } + + s32(EmcCmdMappingByte, secure_scratch8); + s32(EmcPmacroBrickMapping0, secure_scratch9); + s32(EmcPmacroBrickMapping1, secure_scratch10); + s32(EmcPmacroBrickMapping2, secure_scratch11); + s32(McVideoProtectGpuOverride0, secure_scratch12); + s(EmcCmdMappingCmd0_0, 6:0, secure_scratch13, 6:0); + s(EmcCmdMappingCmd0_0, 14:8, secure_scratch13, 13:7); + s(EmcCmdMappingCmd0_0, 22:16, secure_scratch13, 20:14); + s(EmcCmdMappingCmd0_0, 30:24, secure_scratch13, 27:21); + s(McVideoProtectBomAdrHi, 1:0, secure_scratch13, 29:28); + s(McVideoProtectWriteAccess, 1:0, secure_scratch13, 31:30); + s(EmcCmdMappingCmd0_1, 6:0, secure_scratch14, 6:0); + s(EmcCmdMappingCmd0_1, 14:8, secure_scratch14, 13:7); + s(EmcCmdMappingCmd0_1, 22:16, secure_scratch14, 20:14); + s(EmcCmdMappingCmd0_1, 30:24, secure_scratch14, 27:21); + s(McSecCarveoutAdrHi, 1:0, secure_scratch14, 29:28); + s(McMtsCarveoutAdrHi, 1:0, secure_scratch14, 31:30); + s(EmcCmdMappingCmd1_0, 6:0, secure_scratch15, 6:0); + s(EmcCmdMappingCmd1_0, 14:8, secure_scratch15, 13:7); + s(EmcCmdMappingCmd1_0, 22:16, secure_scratch15, 20:14); + s(EmcCmdMappingCmd1_0, 30:24, secure_scratch15, 27:21); + s(McGeneralizedCarveout5BomHi, 1:0, secure_scratch15, 29:28); + s(McGeneralizedCarveout3BomHi, 1:0, secure_scratch15, 31:30); + s(EmcCmdMappingCmd1_1, 6:0, secure_scratch16, 6:0); + s(EmcCmdMappingCmd1_1, 14:8, secure_scratch16, 13:7); + s(EmcCmdMappingCmd1_1, 22:16, secure_scratch16, 20:14); + s(EmcCmdMappingCmd1_1, 30:24, secure_scratch16, 27:21); + s(McGeneralizedCarveout2BomHi, 1:0, secure_scratch16, 29:28); + s(McGeneralizedCarveout4BomHi, 1:0, secure_scratch16, 31:30); + s(EmcCmdMappingCmd2_0, 6:0, secure_scratch17, 6:0); + s(EmcCmdMappingCmd2_0, 14:8, secure_scratch17, 13:7); + s(EmcCmdMappingCmd2_0, 22:16, secure_scratch17, 20:14); + s(EmcCmdMappingCmd2_0, 30:24, secure_scratch17, 27:21); + s(McGeneralizedCarveout1BomHi, 1:0, secure_scratch17, 29:28); + s(EmcAdrCfg, 0:0, secure_scratch17, 30:30); + s(EmcFbioSpare, 1:1, secure_scratch17, 31:31); + s(EmcCmdMappingCmd2_1, 6:0, secure_scratch18, 6:0); + s(EmcCmdMappingCmd2_1, 14:8, secure_scratch18, 13:7); + s(EmcCmdMappingCmd2_1, 22:16, secure_scratch18, 20:14); + s(EmcCmdMappingCmd2_1, 30:24, secure_scratch18, 27:21); + s(EmcFbioCfg8, 15:15, secure_scratch18, 28:28); + s(McEmemAdrCfg, 0:0, secure_scratch18, 29:29); + s(McSecCarveoutProtectWriteAccess, 0:0, secure_scratch18, 30:30); + s(McMtsCarveoutRegCtrl, 0:0, secure_scratch18, 31:31); + s(EmcCmdMappingCmd3_0, 6:0, secure_scratch19, 6:0); + s(EmcCmdMappingCmd3_0, 14:8, secure_scratch19, 13:7); + s(EmcCmdMappingCmd3_0, 22:16, secure_scratch19, 20:14); + s(EmcCmdMappingCmd3_0, 30:24, secure_scratch19, 27:21); + s(McGeneralizedCarveout2Cfg0, 6:3, secure_scratch19, 31:28); + s(EmcCmdMappingCmd3_1, 6:0, secure_scratch20, 6:0); + s(EmcCmdMappingCmd3_1, 14:8, secure_scratch20, 13:7); + s(EmcCmdMappingCmd3_1, 22:16, secure_scratch20, 20:14); + s(EmcCmdMappingCmd3_1, 30:24, secure_scratch20, 27:21); + s(McGeneralizedCarveout2Cfg0, 10:7, secure_scratch20, 31:28); + s(McGeneralizedCarveout4Cfg0, 26:0, secure_scratch39, 26:0); + s(McGeneralizedCarveout2Cfg0, 17:14, secure_scratch39, 30:27); + s(McVideoProtectVprOverride, 0:0, secure_scratch39, 31:31); + s(McGeneralizedCarveout5Cfg0, 26:0, secure_scratch40, 26:0); + s(McGeneralizedCarveout2Cfg0, 21:18, secure_scratch40, 30:27); + s(McVideoProtectVprOverride, 1:1, secure_scratch40, 31:31); + s(EmcCmdMappingCmd0_2, 6:0, secure_scratch41, 6:0); + s(EmcCmdMappingCmd0_2, 14:8, secure_scratch41, 13:7); + s(EmcCmdMappingCmd0_2, 22:16, secure_scratch41, 20:14); + s(EmcCmdMappingCmd0_2, 27:24, secure_scratch41, 24:21); + s(McGeneralizedCarveout1Cfg0, 6:3, secure_scratch41, 28:25); + s(McGeneralizedCarveout2Cfg0, 13:11, secure_scratch41, 31:29); + s(EmcCmdMappingCmd1_2, 6:0, secure_scratch42, 6:0); + s(EmcCmdMappingCmd1_2, 14:8, secure_scratch42, 13:7); + s(EmcCmdMappingCmd1_2, 22:16, secure_scratch42, 20:14); + s(EmcCmdMappingCmd1_2, 27:24, secure_scratch42, 24:21); + s(McGeneralizedCarveout1Cfg0, 13:7, secure_scratch42, 31:25); + s(EmcCmdMappingCmd2_2, 6:0, secure_scratch43, 6:0); + s(EmcCmdMappingCmd2_2, 14:8, secure_scratch43, 13:7); + s(EmcCmdMappingCmd2_2, 22:16, secure_scratch43, 20:14); + s(EmcCmdMappingCmd2_2, 27:24, secure_scratch43, 24:21); + s(McGeneralizedCarveout1Cfg0, 17:14, secure_scratch43, 28:25); + s(McGeneralizedCarveout3Cfg0, 13:11, secure_scratch43, 31:29); + s(EmcCmdMappingCmd3_2, 6:0, secure_scratch44, 6:0); + s(EmcCmdMappingCmd3_2, 14:8, secure_scratch44, 13:7); + s(EmcCmdMappingCmd3_2, 22:16, secure_scratch44, 20:14); + s(EmcCmdMappingCmd3_2, 27:24, secure_scratch44, 24:21); + s(McGeneralizedCarveout1Cfg0, 21:18, secure_scratch44, 28:25); + s(McVideoProtectVprOverride, 3:2, secure_scratch44, 30:29); + s(McVideoProtectVprOverride, 6:6, secure_scratch44, 31:31); + s(McEmemAdrCfgChannelMask, 31:9, secure_scratch45, 22:0); + s(McEmemAdrCfgDev0, 2:0, secure_scratch45, 25:23); + s(McEmemAdrCfgDev0, 9:8, secure_scratch45, 27:26); + s(McEmemAdrCfgDev0, 19:16, secure_scratch45, 31:28); + s(McEmemAdrCfgBankMask0, 31:10, secure_scratch46, 21:0); + s(McEmemAdrCfgDev1, 2:0, secure_scratch46, 24:22); + s(McEmemAdrCfgDev1, 9:8, secure_scratch46, 26:25); + s(McEmemAdrCfgDev1, 19:16, secure_scratch46, 30:27); + s(McVideoProtectVprOverride, 7:7, secure_scratch46, 31:31); + s(McEmemAdrCfgBankMask1, 31:10, secure_scratch47, 21:0); + s(McGeneralizedCarveout3Cfg0, 10:3, secure_scratch47, 29:22); + s(McVideoProtectVprOverride, 9:8, secure_scratch47, 31:30); + s(McEmemAdrCfgBankMask2, 31:10, secure_scratch48, 21:0); + s(McGeneralizedCarveout3Cfg0, 21:14, secure_scratch48, 29:22); + s(McVideoProtectVprOverride, 11:11, secure_scratch48, 30:30); + s(McVideoProtectVprOverride, 14:14, secure_scratch48, 31:31); + s(McVideoProtectGpuOverride1, 15:0, secure_scratch49, 15:0); + s(McEmemCfg, 13:0, secure_scratch49, 29:16); + s(McEmemCfg, 31:31, secure_scratch49, 30:30); + s(McVideoProtectVprOverride, 15:15, secure_scratch49, 31:31); + s(McGeneralizedCarveout3Bom, 31:17, secure_scratch50, 14:0); + s(McGeneralizedCarveout1Bom, 31:17, secure_scratch50, 29:15); + s(McVideoProtectVprOverride, 18:17, secure_scratch50, 31:30); + s(McGeneralizedCarveout4Bom, 31:17, secure_scratch51, 14:0); + s(McGeneralizedCarveout2Bom, 31:17, secure_scratch51, 29:15); + s(McVideoProtectVprOverride, 20:19, secure_scratch51, 31:30); + s(McGeneralizedCarveout5Bom, 31:17, secure_scratch52, 14:0); + s(McVideoProtectBom, 31:20, secure_scratch52, 26:15); + s(McVideoProtectVprOverride, 23:21, secure_scratch52, 29:27); + s(McVideoProtectVprOverride, 26:26, secure_scratch52, 30:30); + s(McVideoProtectVprOverride, 29:29, secure_scratch52, 31:31); + s(McVideoProtectSizeMb, 11:0, secure_scratch53, 11:0); + s(McSecCarveoutBom, 31:20, secure_scratch53, 23:12); + s(McVideoProtectVprOverride, 31:30, secure_scratch53, 25:24); + s(McVideoProtectVprOverride1, 1:0, secure_scratch53, 27:26); + s(McVideoProtectVprOverride1, 7:4, secure_scratch53, 31:28); + s(McSecCarveoutSizeMb, 11:0, secure_scratch54, 11:0); + s(McMtsCarveoutBom, 31:20, secure_scratch54, 23:12); + s(McVideoProtectVprOverride1, 15:8, secure_scratch54, 31:24); + s(McMtsCarveoutSizeMb, 11:0, secure_scratch55, 11:0); + s(McGeneralizedCarveout4Size128kb, 11:0, secure_scratch55, 23:12); + s(McVideoProtectVprOverride1, 16:16, secure_scratch55, 24:24); + s(McGeneralizedCarveout2Cfg0, 2:0, secure_scratch55, 27:25); + s(McGeneralizedCarveout2Cfg0, 25:22, secure_scratch55, 31:28); + s(McGeneralizedCarveout3Size128kb, 11:0, secure_scratch56, 11:0); + s(McGeneralizedCarveout2Size128kb, 11:0, secure_scratch56, 23:12); + s(McGeneralizedCarveout2Cfg0, 26:26, secure_scratch56, 24:24); + s(McGeneralizedCarveout1Cfg0, 2:0, secure_scratch56, 27:25); + s(McGeneralizedCarveout1Cfg0, 25:22, secure_scratch56, 31:28); + s(McGeneralizedCarveout1Size128kb, 11:0, secure_scratch57, 11:0); + s(McGeneralizedCarveout5Size128kb, 11:0, secure_scratch57, 23:12); + s(McGeneralizedCarveout1Cfg0, 26:26, secure_scratch57, 24:24); + s(McGeneralizedCarveout3Cfg0, 2:0, secure_scratch57, 27:25); + s(McGeneralizedCarveout3Cfg0, 25:22, secure_scratch57, 31:28); + s(McGeneralizedCarveout3Cfg0, 26:26, secure_scratch58, 0:0); + + s32(McGeneralizedCarveout1Access0, secure_scratch59); + s32(McGeneralizedCarveout1Access1, secure_scratch60); + s32(McGeneralizedCarveout1Access2, secure_scratch61); + s32(McGeneralizedCarveout1Access3, secure_scratch62); + s32(McGeneralizedCarveout1Access4, secure_scratch63); + s32(McGeneralizedCarveout2Access0, secure_scratch64); + s32(McGeneralizedCarveout2Access1, secure_scratch65); + s32(McGeneralizedCarveout2Access2, secure_scratch66); + s32(McGeneralizedCarveout2Access3, secure_scratch67); + s32(McGeneralizedCarveout2Access4, secure_scratch68); + s32(McGeneralizedCarveout3Access0, secure_scratch69); + s32(McGeneralizedCarveout3Access1, secure_scratch70); + s32(McGeneralizedCarveout3Access2, secure_scratch71); + s32(McGeneralizedCarveout3Access3, secure_scratch72); + s32(McGeneralizedCarveout3Access4, secure_scratch73); + s32(McGeneralizedCarveout4Access0, secure_scratch74); + s32(McGeneralizedCarveout4Access1, secure_scratch75); + s32(McGeneralizedCarveout4Access2, secure_scratch76); + s32(McGeneralizedCarveout4Access3, secure_scratch77); + s32(McGeneralizedCarveout4Access4, secure_scratch78); + s32(McGeneralizedCarveout5Access0, secure_scratch79); + s32(McGeneralizedCarveout5Access1, secure_scratch80); + s32(McGeneralizedCarveout5Access2, secure_scratch81); + s32(McGeneralizedCarveout5Access3, secure_scratch82); + s32(McGeneralizedCarveout1ForceInternalAccess0, secure_scratch84); + s32(McGeneralizedCarveout1ForceInternalAccess1, secure_scratch85); + s32(McGeneralizedCarveout1ForceInternalAccess2, secure_scratch86); + s32(McGeneralizedCarveout1ForceInternalAccess3, secure_scratch87); + s32(McGeneralizedCarveout1ForceInternalAccess4, secure_scratch88); + s32(McGeneralizedCarveout2ForceInternalAccess0, secure_scratch89); + s32(McGeneralizedCarveout2ForceInternalAccess1, secure_scratch90); + s32(McGeneralizedCarveout2ForceInternalAccess2, secure_scratch91); + s32(McGeneralizedCarveout2ForceInternalAccess3, secure_scratch92); + s32(McGeneralizedCarveout2ForceInternalAccess4, secure_scratch93); + s32(McGeneralizedCarveout3ForceInternalAccess0, secure_scratch94); + s32(McGeneralizedCarveout3ForceInternalAccess1, secure_scratch95); + s32(McGeneralizedCarveout3ForceInternalAccess2, secure_scratch96); + s32(McGeneralizedCarveout3ForceInternalAccess3, secure_scratch97); + s32(McGeneralizedCarveout3ForceInternalAccess4, secure_scratch98); + s32(McGeneralizedCarveout4ForceInternalAccess0, secure_scratch99); + s32(McGeneralizedCarveout4ForceInternalAccess1, secure_scratch100); + s32(McGeneralizedCarveout4ForceInternalAccess2, secure_scratch101); + s32(McGeneralizedCarveout4ForceInternalAccess3, secure_scratch102); + s32(McGeneralizedCarveout4ForceInternalAccess4, secure_scratch103); + s32(McGeneralizedCarveout5ForceInternalAccess0, secure_scratch104); + s32(McGeneralizedCarveout5ForceInternalAccess1, secure_scratch105); + s32(McGeneralizedCarveout5ForceInternalAccess2, secure_scratch106); + s32(McGeneralizedCarveout5ForceInternalAccess3, secure_scratch107); + + c32(0, scratch2); + s(PllMInputDivider, 7:0, scratch2, 7:0); + s(PllMFeedbackDivider, 7:0, scratch2, 15:8); + s(PllMPostDivider, 4:0, scratch2, 20:16); + s(PllMKVCO, 0:0, scratch2, 21:21); + s(PllMKCP, 1:0, scratch2, 23:22); + + c32(0, scratch35); + s(PllMSetupControl, 15:0, scratch35, 15:0); + + c32(0, scratch3); + s(PllMInputDivider, 7:0, scratch3, 7:0); + c(0x3e, scratch3, 15:8); + c(0, scratch3, 20:16); + s(PllMKVCO, 0:0, scratch3, 21:21); + s(PllMKCP, 1:0, scratch3, 23:22); + + c32(0, scratch36); + s(PllMSetupControl, 23:0, scratch36, 23:0); + + c32(0, scratch4); + s(PllMStableTime, 9:0, scratch4, 9:0); +} diff --git a/fusee/fusee-primary/src/sdram_lz.inl b/fusee/fusee-primary/src/sdram_lz.inl new file mode 100644 index 000000000..d16470fe6 --- /dev/null +++ b/fusee/fusee-primary/src/sdram_lz.inl @@ -0,0 +1,108 @@ +static const uint8_t _dram_cfg_lz[1262] = { + 0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x2C, 0x17, 0x04, 0x09, 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, + 0x17, 0x10, 0x10, 0x00, 0x00, 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, + 0x00, 0x04, 0xB4, 0x01, 0x70, 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, + 0x70, 0x17, 0x10, 0x24, 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x17, 0x04, 0x04, 0x17, 0x09, 0x18, 0xFF, 0xFF, 0x1F, + 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x77, + 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, 0x17, 0x08, 0x08, 0xA6, 0xA6, + 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x04, 0x04, + 0x04, 0x04, 0x17, 0x04, 0x04, 0x17, 0x04, 0x3C, 0x1F, 0x1F, 0x1F, 0x1F, + 0x17, 0x04, 0x04, 0x17, 0x06, 0x06, 0x00, 0x00, 0x04, 0x08, 0x17, 0x06, + 0x46, 0xA1, 0x01, 0x00, 0x00, 0x32, 0x17, 0x0B, 0x64, 0x01, 0x17, 0x04, + 0x7C, 0x17, 0x07, 0x0C, 0x03, 0x17, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13, + 0x17, 0x0B, 0x2C, 0x09, 0x00, 0x00, 0x00, 0x17, 0x05, 0x5D, 0x17, 0x07, + 0x10, 0x0B, 0x17, 0x07, 0x28, 0x08, 0x17, 0x07, 0x0C, 0x17, 0x04, 0x1C, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x17, 0x04, 0x04, 0x17, 0x07, 0x08, 0x17, + 0x04, 0x50, 0x17, 0x04, 0x2C, 0x17, 0x04, 0x1C, 0x17, 0x04, 0x10, 0x17, + 0x08, 0x6C, 0x17, 0x04, 0x10, 0x17, 0x04, 0x38, 0x17, 0x04, 0x40, 0x05, + 0x17, 0x07, 0x1C, 0x17, 0x08, 0x58, 0x17, 0x04, 0x24, 0x17, 0x04, 0x18, + 0x17, 0x08, 0x64, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x09, 0x0C, 0x17, 0x05, 0x82, + 0x58, 0x17, 0x07, 0x61, 0xC1, 0x17, 0x07, 0x50, 0x17, 0x04, 0x04, 0x17, + 0x08, 0x81, 0x48, 0x17, 0x04, 0x04, 0x17, 0x04, 0x28, 0x17, 0x04, 0x60, + 0x17, 0x08, 0x54, 0x27, 0x17, 0x04, 0x04, 0x17, 0x07, 0x14, 0x17, 0x04, + 0x04, 0x04, 0x17, 0x07, 0x81, 0x58, 0x17, 0x0C, 0x0C, 0x1C, 0x03, 0x00, + 0x00, 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x17, 0x04, 0x5A, 0xF3, 0x0C, + 0x04, 0x05, 0x1B, 0x06, 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, + 0x08, 0x1D, 0x09, 0x0A, 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, + 0x02, 0x1B, 0x1C, 0x23, 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, + 0x0A, 0x0B, 0x1D, 0x0D, 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, + 0x24, 0x06, 0x07, 0x9A, 0x12, 0x17, 0x05, 0x83, 0x41, 0x00, 0xFF, 0x17, + 0x10, 0x83, 0x6C, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, + 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, + 0x00, 0x0B, 0x08, 0x72, 0x72, 0x0E, 0x0C, 0x17, 0x04, 0x20, 0x08, 0x08, + 0x0D, 0x0C, 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x17, 0x06, + 0x2C, 0x11, 0x08, 0x17, 0x10, 0x84, 0x67, 0x15, 0x00, 0xCC, 0x00, 0x0A, + 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, 0xFF, + 0x0F, 0xFF, 0x0F, 0x17, 0x08, 0x83, 0x4C, 0x01, 0x03, 0x00, 0x70, 0x00, + 0x0C, 0x00, 0x01, 0x17, 0x04, 0x0C, 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, + 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, 0x17, 0x04, 0x10, 0xA0, 0x00, 0x2C, + 0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x80, 0x17, 0x06, 0x48, 0x08, 0x00, + 0x04, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, + 0x28, 0x28, 0x17, 0x04, 0x04, 0x11, 0x11, 0x11, 0x11, 0x17, 0x04, 0x04, + 0xBE, 0x00, 0x00, 0x17, 0x05, 0x58, 0x17, 0x08, 0x5C, 0x17, 0x22, 0x85, + 0x6A, 0x17, 0x1A, 0x1A, 0x14, 0x00, 0x12, 0x00, 0x10, 0x17, 0x05, 0x83, + 0x0A, 0x17, 0x16, 0x18, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x17, 0x05, 0x83, 0x0C, 0x17, + 0x04, 0x20, 0x17, 0x18, 0x18, 0x28, 0x00, 0x28, 0x17, 0x04, 0x04, 0x17, + 0x08, 0x08, 0x17, 0x10, 0x10, 0x00, 0x14, 0x17, 0x05, 0x5A, 0x17, 0x04, + 0x5C, 0x17, 0x04, 0x5E, 0x17, 0x04, 0x0E, 0x17, 0x0E, 0x78, 0x17, 0x09, + 0x82, 0x50, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, + 0x17, 0x08, 0x18, 0x80, 0x01, 0x00, 0x00, 0x40, 0x17, 0x04, 0x20, 0x03, + 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, 0x11, 0x17, 0x08, 0x82, 0x58, + 0x17, 0x0C, 0x38, 0x17, 0x1B, 0x81, 0x6C, 0x17, 0x08, 0x85, 0x60, 0x17, + 0x08, 0x86, 0x50, 0x17, 0x08, 0x86, 0x60, 0x17, 0x06, 0x83, 0x21, 0x22, + 0x04, 0xFF, 0xFF, 0xAF, 0x4F, 0x17, 0x0C, 0x86, 0x74, 0x17, 0x08, 0x2C, + 0x8B, 0xFF, 0x07, 0x17, 0x06, 0x81, 0x04, 0x32, 0x54, 0x76, 0x10, 0x47, + 0x32, 0x65, 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, + 0x64, 0x32, 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, + 0x32, 0x67, 0x17, 0x04, 0x24, 0x49, 0x92, 0x24, 0x17, 0x04, 0x04, 0x17, + 0x11, 0x7C, 0x1B, 0x17, 0x04, 0x04, 0x17, 0x13, 0x81, 0x14, 0x2F, 0x41, + 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x17, 0x04, 0x7C, 0xFF, 0xFF, 0xFF, + 0x7F, 0x0B, 0xD7, 0x06, 0x40, 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, + 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x17, 0x06, 0x86, 0x59, + 0x17, 0x0F, 0x89, 0x14, 0x37, 0x17, 0x07, 0x82, 0x72, 0x10, 0x17, 0x06, + 0x83, 0x0D, 0x00, 0x11, 0x01, 0x17, 0x05, 0x85, 0x39, 0x17, 0x04, 0x0E, + 0x0A, 0x17, 0x07, 0x89, 0x29, 0x17, 0x04, 0x1B, 0x17, 0x08, 0x86, 0x77, + 0x17, 0x09, 0x12, 0x20, 0x00, 0x00, 0x00, 0x81, 0x10, 0x09, 0x28, 0x93, + 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, 0x17, 0x18, 0x82, 0x2C, 0xFF, + 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0x17, 0x04, 0x04, 0xDC, 0xDC, + 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x17, 0x04, 0x04, 0x17, 0x04, 0x04, + 0x17, 0x05, 0x82, 0x24, 0x03, 0x07, 0x17, 0x04, 0x04, 0x00, 0x00, 0x24, + 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, + 0x9C, 0x4B, 0x17, 0x04, 0x64, 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, + 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x17, 0x06, 0x85, 0x60, 0x17, + 0x10, 0x82, 0x74, 0x17, 0x08, 0x08, 0x17, 0x08, 0x88, 0x00, 0x17, 0x04, + 0x10, 0x04, 0x17, 0x0B, 0x87, 0x6C, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, + 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x17, 0x08, 0x8B, 0x18, + 0x1F, 0x17, 0x09, 0x81, 0x73, 0x00, 0xFF, 0x00, 0xFF, 0x17, 0x05, 0x86, + 0x48, 0x17, 0x04, 0x0C, 0x17, 0x07, 0x86, 0x34, 0x00, 0x00, 0xF0, 0x17, + 0x09, 0x87, 0x54, 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x17, 0x0C, 0x81, + 0x52, 0x17, 0x0A, 0x1C, 0x17, 0x10, 0x81, 0x6C, 0x17, 0x0A, 0x82, 0x21, + 0x17, 0x07, 0x82, 0x4D, 0x17, 0x0A, 0x8A, 0x1B, 0x17, 0x11, 0x2C, 0x76, + 0x0C, 0x17, 0x0A, 0x8A, 0x67, 0x17, 0x0F, 0x84, 0x28, 0x17, 0x06, 0x34, + 0x17, 0x17, 0x3A, 0x7E, 0x16, 0x40, 0x17, 0x0C, 0x8B, 0x1F, 0x17, 0x2A, + 0x38, 0x1E, 0x17, 0x0A, 0x38, 0x17, 0x13, 0x81, 0x28, 0x00, 0xC0, 0x17, + 0x17, 0x55, 0x46, 0x24, 0x17, 0x0A, 0x81, 0x28, 0x17, 0x14, 0x38, 0x17, + 0x18, 0x81, 0x60, 0x46, 0x2C, 0x17, 0x06, 0x38, 0xEC, 0x17, 0x0D, 0x16, + 0x17, 0x0E, 0x82, 0x3C, 0x17, 0x82, 0x0C, 0x8E, 0x68, 0x17, 0x04, 0x24, + 0x17, 0x5C, 0x8E, 0x68, 0x17, 0x07, 0x82, 0x5F, 0x80, 0x17, 0x87, 0x01, + 0x8E, 0x68, 0x02, 0x17, 0x81, 0x4A, 0x8E, 0x68, 0x17, 0x0C, 0x87, 0x78, + 0x17, 0x85, 0x28, 0x8E, 0x68, 0x17, 0x8E, 0x68, 0x9D, 0x50, 0x17, 0x81, + 0x24, 0x8E, 0x68, 0x17, 0x04, 0x2C, 0x17, 0x28, 0x8E, 0x68, 0x17, 0x04, + 0x30, 0x17, 0x85, 0x3C, 0x8E, 0x68, 0x12, 0x17, 0x07, 0x85, 0x70, 0x17, + 0x88, 0x74, 0x8E, 0x68, 0x17, 0x87, 0x3E, 0x9D, 0x50, 0x0C, 0x17, 0x04, + 0x04, 0x17, 0x12, 0x8E, 0x68, 0x18, 0x17, 0x87, 0x12, 0xBB, 0x20, 0x17, + 0x83, 0x04, 0x9D, 0x50, 0x15, 0x17, 0x05, 0x8D, 0x76, 0x17, 0x0F, 0x8B, + 0x49, 0x17, 0x0B, 0x18, 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, + 0x34, 0x00, 0x36, 0x00, 0x2F, 0x00, 0x33, 0x17, 0x09, 0x84, 0x0C, 0x17, + 0x18, 0x18, 0x17, 0x20, 0x8E, 0x68, 0x15, 0x17, 0x07, 0x5A, 0x17, 0x06, + 0x5E, 0x16, 0x00, 0x15, 0x17, 0x82, 0x40, 0x9D, 0x50, 0x17, 0x86, 0x5F, + 0xBB, 0x20, 0x3A, 0x00, 0x00, 0x00, 0x1D, 0x17, 0x81, 0x4F, 0xAC, 0x38, + 0x3B, 0x17, 0x04, 0x04, 0x17, 0x86, 0x30, 0x8E, 0x68, 0x17, 0x81, 0x53, + 0xAC, 0x38, 0x07, 0x17, 0x0D, 0x8E, 0x68, 0xA3, 0x72, 0x17, 0x83, 0x10, + 0x8E, 0x68 +}; diff --git a/fusee/fusee-primary/src/sdram_param_t210.h b/fusee/fusee-primary/src/sdram_param_t210.h new file mode 100644 index 000000000..328ee5109 --- /dev/null +++ b/fusee/fusee-primary/src/sdram_param_t210.h @@ -0,0 +1,933 @@ +/* + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * See file CREDITS for list of people who contributed to this + * project. + */ + +/** + * Defines the SDRAM parameter structure. + * + * Note that PLLM is used by EMC. + */ + +#ifndef _SDRAM_PARAM_T210_H_ +#define _SDRAM_PARAM_T210_H_ + +#include <stdint.h> + +#define MEMORY_TYPE_NONE 0 +#define MEMORY_TYPE_DDR 0 +#define MEMORY_TYPE_LPDDR 0 +#define MEMORY_TYPE_DDR2 0 +#define MEMORY_TYPE_LPDDR2 1 +#define MEMORY_TYPE_DDR3 2 +#define MEMORY_TYPE_LPDDR4 3 + +/** + * Defines the SDRAM parameter structure + */ +typedef struct _sdram_params +{ + /* Specifies the type of memory device */ + uint32_t memory_type; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + uint32_t pllm_input_divider; + /* Specifies the N value for PllM */ + uint32_t pllm_feedback_divider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + uint32_t pllm_stable_time; + /* Specifies misc. control bits */ + uint32_t pllm_setup_control; + /* Specifies the P value for PLLM */ + uint32_t pllm_post_divider; + /* Specifies value for Charge Pump Gain Control */ + uint32_t pllm_kcp; + /* Specifies VCO gain */ + uint32_t pllm_kvco; + /* Spare BCT param */ + uint32_t emc_bct_spare0; + /* Spare BCT param */ + uint32_t emc_bct_spare1; + /* Spare BCT param */ + uint32_t emc_bct_spare2; + /* Spare BCT param */ + uint32_t emc_bct_spare3; + /* Spare BCT param */ + uint32_t emc_bct_spare4; + /* Spare BCT param */ + uint32_t emc_bct_spare5; + /* Spare BCT param */ + uint32_t emc_bct_spare6; + /* Spare BCT param */ + uint32_t emc_bct_spare7; + /* Spare BCT param */ + uint32_t emc_bct_spare8; + /* Spare BCT param */ + uint32_t emc_bct_spare9; + /* Spare BCT param */ + uint32_t emc_bct_spare10; + /* Spare BCT param */ + uint32_t emc_bct_spare11; + /* Spare BCT param */ + uint32_t emc_bct_spare12; + /* Spare BCT param */ + uint32_t emc_bct_spare13; + + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + uint32_t emc_clock_source; + uint32_t emc_clock_source_dll; + + /* Defines possible override for PLLLM_MISC2 */ + uint32_t clk_rst_pllm_misc20_override; + /* enables override for PLLLM_MISC2 */ + uint32_t clk_rst_pllm_misc20_override_enable; + /* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */ + uint32_t clear_clock2_mc1; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + uint32_t emc_auto_cal_interval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + uint32_t emc_auto_cal_config; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + uint32_t emc_auto_cal_config2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + uint32_t emc_auto_cal_config3; + + uint32_t emc_auto_cal_config4; + uint32_t emc_auto_cal_config5; + uint32_t emc_auto_cal_config6; + uint32_t emc_auto_cal_config7; + uint32_t emc_auto_cal_config8; + /* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */ + uint32_t emc_auto_cal_vref_sel0; + uint32_t emc_auto_cal_vref_sel1; + + /* Specifies the value for EMC_AUTO_CAL_CHANNEL */ + uint32_t emc_auto_cal_channel; + + /* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */ + uint32_t emc_pmacro_auto_cal_cfg0; + uint32_t emc_pmacro_auto_cal_cfg1; + uint32_t emc_pmacro_auto_cal_cfg2; + + uint32_t emc_pmacro_rx_term; + uint32_t emc_pmacro_dq_tx_drive; + uint32_t emc_pmacro_ca_tx_drive; + uint32_t emc_pmacro_cmd_tx_drive; + uint32_t emc_pmacro_auto_cal_common; + uint32_t emc_pmacro_zcrtl; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + uint32_t emc_auto_cal_wait; + + uint32_t emc_xm2_comp_pad_ctrl; + uint32_t emc_xm2_comp_pad_ctrl2; + uint32_t emc_xm2_comp_pad_ctrl3; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + uint32_t emc_adr_cfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + uint32_t emc_pin_program_wait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + uint32_t emc_pin_extra_wait; + + uint32_t emc_pin_gpio_enable; + uint32_t emc_pin_gpio; + + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + uint32_t emc_timing_control_wait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + uint32_t emc_rc; + /* Specifies the value for EMC_RFC */ + uint32_t emc_rfc; + + uint32_t emc_rfc_pb; + uint32_t emc_ref_ctrl2; + + /* Specifies the value for EMC_RFC_SLR */ + uint32_t emc_rfc_slr; + /* Specifies the value for EMC_RAS */ + uint32_t emc_ras; + /* Specifies the value for EMC_RP */ + uint32_t emc_rp; + /* Specifies the value for EMC_R2R */ + uint32_t emc_r2r; + /* Specifies the value for EMC_W2W */ + uint32_t emc_w2w; + /* Specifies the value for EMC_R2W */ + uint32_t emc_r2w; + /* Specifies the value for EMC_W2R */ + uint32_t emc_w2r; + /* Specifies the value for EMC_R2P */ + uint32_t emc_r2p; + /* Specifies the value for EMC_W2P */ + uint32_t emc_w2p; + /* Specifies the value for EMC_RD_RCD */ + + uint32_t emc_tppd; + uint32_t emc_ccdmw; + + uint32_t emc_rd_rcd; + /* Specifies the value for EMC_WR_RCD */ + uint32_t emc_wr_rcd; + /* Specifies the value for EMC_RRD */ + uint32_t emc_rrd; + /* Specifies the value for EMC_REXT */ + uint32_t emc_rext; + /* Specifies the value for EMC_WEXT */ + uint32_t emc_wext; + /* Specifies the value for EMC_WDV */ + uint32_t emc_wdv; + + uint32_t emc_wdv_chk; + uint32_t emc_wsv; + uint32_t emc_wev; + + /* Specifies the value for EMC_WDV_MASK */ + uint32_t emc_wdv_mask; + + uint32_t emc_ws_duration; + uint32_t emc_we_duration; + + /* Specifies the value for EMC_QUSE */ + uint32_t emc_quse; + /* Specifies the value for EMC_QUSE_WIDTH */ + uint32_t emc_quse_width; + /* Specifies the value for EMC_IBDLY */ + uint32_t emc_ibdly; + + uint32_t emc_obdly; + + /* Specifies the value for EMC_EINPUT */ + uint32_t emc_einput; + /* Specifies the value for EMC_EINPUT_DURATION */ + uint32_t emc_einput_duration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + uint32_t emc_puterm_extra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + uint32_t emc_puterm_width; + + uint32_t emc_qrst; + uint32_t emc_qsafe; + uint32_t emc_rdv; + uint32_t emc_rdv_mask; + + uint32_t emc_rdv_early; + uint32_t emc_rdv_early_mask; + + /* Specifies the value for EMC_QPOP */ + uint32_t emc_qpop; + + /* Specifies the value for EMC_REFRESH */ + uint32_t emc_refresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + uint32_t emc_burst_refresh_num; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + uint32_t emc_prerefresh_req_cnt; + /* Specifies the value for EMC_PDEX2WR */ + uint32_t emc_pdex2wr; + /* Specifies the value for EMC_PDEX2RD */ + uint32_t emc_pdex2rd; + /* Specifies the value for EMC_PCHG2PDEN */ + uint32_t emc_pchg2pden; + /* Specifies the value for EMC_ACT2PDEN */ + uint32_t emc_act2pden; + /* Specifies the value for EMC_AR2PDEN */ + uint32_t emc_ar2pden; + /* Specifies the value for EMC_RW2PDEN */ + uint32_t emc_rw2pden; + + uint32_t emc_cke2pden; + uint32_t emc_pdex2che; + uint32_t emc_pdex2mrr; + + /* Specifies the value for EMC_TXSR */ + uint32_t emc_txsr; + /* Specifies the value for EMC_TXSRDLL */ + uint32_t emc_txsr_dll; + /* Specifies the value for EMC_TCKE */ + uint32_t emc_tcke; + /* Specifies the value for EMC_TCKESR */ + uint32_t emc_tckesr; + /* Specifies the value for EMC_TPD */ + uint32_t emc_tpd; + /* Specifies the value for EMC_TFAW */ + uint32_t emc_tfaw; + /* Specifies the value for EMC_TRPAB */ + uint32_t emc_trpab; + /* Specifies the value for EMC_TCLKSTABLE */ + uint32_t emc_tclkstable; + /* Specifies the value for EMC_TCLKSTOP */ + uint32_t emc_tclkstop; + /* Specifies the value for EMC_TREFBW */ + uint32_t emc_trefbw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + uint32_t emc_fbio_cfg5; + /* Specifies the value for EMC_FBIO_CFG7 */ + uint32_t emc_fbio_cfg7; + uint32_t emc_fbio_cfg8; + + /* Command mapping for CMD brick 0 */ + uint32_t emc_cmd_mapping_cmd0_0; + uint32_t emc_cmd_mapping_cmd0_1; + uint32_t emc_cmd_mapping_cmd0_2; + uint32_t emc_cmd_mapping_cmd1_0; + uint32_t emc_cmd_mapping_cmd1_1; + uint32_t emc_cmd_mapping_cmd1_2; + uint32_t emc_cmd_mapping_cmd2_0; + uint32_t emc_cmd_mapping_cmd2_1; + uint32_t emc_cmd_mapping_cmd2_2; + uint32_t emc_cmd_mapping_cmd3_0; + uint32_t emc_cmd_mapping_cmd3_1; + uint32_t emc_cmd_mapping_cmd3_2; + uint32_t emc_cmd_mapping_byte; + + /* Specifies the value for EMC_FBIO_SPARE */ + uint32_t emc_fbio_spare; + + /* Specifies the value for EMC_CFG_RSV */ + uint32_t emc_cfg_rsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + uint32_t emc_mrs; + /* Specifies the MP0 command to initialize mode registers */ + uint32_t emc_emrs; + /* Specifies the MP2 command to initialize mode registers */ + uint32_t emc_emrs2; + /* Specifies the MP3 command to initialize mode registers */ + uint32_t emc_emrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + uint32_t emc_mrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + uint32_t emc_mrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + uint32_t emc_mrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t emc_mrw4; + + /* Specifies the programming to LPDDR4 Mode Register 3 at cold boot */ + uint32_t emc_mrw6; + /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */ + uint32_t emc_mrw8; + /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */ + uint32_t emc_mrw9; + /* Specifies the programming to LPDDR4 Mode Register 12 at cold boot */ + uint32_t emc_mrw10; + /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */ + uint32_t emc_mrw12; + /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */ + uint32_t emc_mrw13; + /* Specifies the programming to LPDDR4 Mode Register 22 at cold boot */ + uint32_t emc_mrw14; + + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + uint32_t emc_mrw_extra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + uint32_t emc_warm_boot_mrw_extra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + uint32_t emc_warm_boot_extramode_reg_write_enable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + uint32_t emc_extramode_reg_write_enable; + + /* Specifies the EMC_MRW reset command value */ + uint32_t emc_mrw_reset_command; + /* Specifies the EMC Reset wait time (in microseconds) */ + uint32_t emc_mrw_reset_ninit_wait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + uint32_t emc_mrs_wait_cnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + uint32_t emc_mrs_wait_cnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + uint32_t emc_cfg; + /* Specifies the value for EMC_CFG_2 */ + uint32_t emc_cfg2; + /* Specifies the pipe bypass controls */ + uint32_t emc_cfg_pipe; + + uint32_t emc_cfg_pipe_clk; + uint32_t emc_fdpd_ctrl_cmd_no_ramp; + uint32_t emc_cfg_update; + + /* Specifies the value for EMC_DBG */ + uint32_t emc_dbg; + + uint32_t emc_dbg_write_mux; + + /* Specifies the value for EMC_CMDQ */ + uint32_t emc_cmd_q; + /* Specifies the value for EMC_MC2EMCQ */ + uint32_t emc_mc2emc_q; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + uint32_t emc_dyn_self_ref_control; + + /* Specifies the value for MEM_INIT_DONE */ + uint32_t ahb_arbitration_xbar_ctrl_meminit_done; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + uint32_t emc_cfg_dig_dll; + uint32_t emc_cfg_dig_dll_1; + + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + uint32_t emc_cfg_dig_dll_period; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + uint32_t emc_dev_select; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + uint32_t emc_sel_dpd_ctrl; + + /* Pads trimmer delays */ + uint32_t emc_fdpd_ctrl_dq; + uint32_t emc_fdpd_ctrl_cmd; + uint32_t emc_pmacro_ib_vref_dq_0; + uint32_t emc_pmacro_ib_vref_dq_1; + uint32_t emc_pmacro_ib_vref_dqs_0; + uint32_t emc_pmacro_ib_vref_dqs_1; + uint32_t emc_pmacro_ib_rxrt; + uint32_t emc_cfg_pipe1; + uint32_t emc_cfg_pipe2; + + /* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */ + uint32_t emc_pmacro_quse_ddll_rank0_0; + uint32_t emc_pmacro_quse_ddll_rank0_1; + uint32_t emc_pmacro_quse_ddll_rank0_2; + uint32_t emc_pmacro_quse_ddll_rank0_3; + uint32_t emc_pmacro_quse_ddll_rank0_4; + uint32_t emc_pmacro_quse_ddll_rank0_5; + uint32_t emc_pmacro_quse_ddll_rank1_0; + uint32_t emc_pmacro_quse_ddll_rank1_1; + uint32_t emc_pmacro_quse_ddll_rank1_2; + uint32_t emc_pmacro_quse_ddll_rank1_3; + uint32_t emc_pmacro_quse_ddll_rank1_4; + uint32_t emc_pmacro_quse_ddll_rank1_5; + + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_0; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_1; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_2; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_3; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_4; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_5; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_0; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_1; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_2; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_3; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_4; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_5; + + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_0; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_1; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_2; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_3; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_4; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_5; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_0; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_1; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_2; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_3; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_4; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_5; + + uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_0; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_1; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_2; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_3; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_0; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_1; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_2; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_3; + + uint32_t emc_pmacro_ddll_long_cmd_0; + uint32_t emc_pmacro_ddll_long_cmd_1; + uint32_t emc_pmacro_ddll_long_cmd_2; + uint32_t emc_pmacro_ddll_long_cmd_3; + uint32_t emc_pmacro_ddll_long_cmd_4; + uint32_t emc_pmacro_ddll_short_cmd_0; + uint32_t emc_pmacro_ddll_short_cmd_1; + uint32_t emc_pmacro_ddll_short_cmd_2; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + uint32_t warm_boot_wait; + + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t emc_odt_write; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + uint32_t emc_zcal_interval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + uint32_t emc_zcal_wait_cnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + uint32_t emc_zcal_mrw_cmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + uint32_t emc_mrs_reset_dll; + /* Specifies the command for ZQ initialization of device 0 */ + uint32_t emc_zcal_init_dev0; + /* Specifies the command for ZQ initialization of device 1 */ + uint32_t emc_zcal_init_dev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + uint32_t emc_zcal_init_wait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + uint32_t emc_zcal_warm_cold_boot_enables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + uint32_t emc_mrw_lpddr2zcal_warm_boot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + uint32_t emc_zqcal_ddr3_warm_boot; + + uint32_t emc_zqcal_lpddr4_warm_boot; + + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + uint32_t emc_zcal_warm_boot_wait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + uint32_t emc_mrs_warm_boot_enable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + uint32_t emc_mrs_reset_dll_wait; + /* Specifies the extra MRS command to initialize mode registers */ + uint32_t emc_mrs_extra; + /* Specifies the extra MRS command at warm boot */ + uint32_t emc_warm_boot_mrs_extra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + uint32_t emc_emrs_ddr2_dll_enable; + /* Specifies the MRS command to reset the DDR2 DLL */ + uint32_t emc_mrs_ddr2_dll_reset; + /* Specifies the EMRS command to set OCD calibration */ + uint32_t emc_emrs_ddr2_ocd_calib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + uint32_t emc_ddr2_wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + uint32_t emc_clken_override; + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + uint32_t emc_extra_refresh_num; + /* Specifies the master override for all EMC clocks */ + uint32_t emc_clken_override_allwarm_boot; + /* Specifies the master override for all MC clocks */ + uint32_t mc_clken_override_allwarm_boot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + uint32_t emc_cfg_dig_dll_period_warm_boot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + uint32_t pmc_vddp_sel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + uint32_t pmc_vddp_sel_wait; + /* Specifies the value for PMC_DDR_PWR */ + uint32_t pmc_ddr_pwr; + /* Specifies the value for PMC_DDR_CFG */ + uint32_t pmc_ddr_cfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + uint32_t pmc_io_dpd3_req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + uint32_t pmc_io_dpd3_req_wait; + + uint32_t pmc_io_dpd4_req_wait; + + /* Specifies the value for PMC_REG_SHORT */ + uint32_t pmc_reg_short; + /* Specifies the value for PMC_NO_IOPOWER */ + uint32_t pmc_no_io_power; + + uint32_t pmc_ddr_ctrl_wait; + uint32_t pmc_ddr_ctrl; + + /* Specifies the value for EMC_ACPD_CONTROL */ + uint32_t emc_acpd_control; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + uint32_t emc_swizzle_rank0_byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + uint32_t emc_swizzle_rank0_byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + uint32_t emc_swizzle_rank0_byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + uint32_t emc_swizzle_rank0_byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + uint32_t emc_swizzle_rank1_byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + uint32_t emc_swizzle_rank1_byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + uint32_t emc_swizzle_rank1_byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + uint32_t emc_swizzle_rank1_byte3; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + uint32_t emc_txdsrvttgen; + + /* Specifies the value for EMC_DATA_BRLSHFT_0 */ + uint32_t emc_data_brlshft0; + uint32_t emc_data_brlshft1; + + uint32_t emc_dqs_brlshft0; + uint32_t emc_dqs_brlshft1; + + uint32_t emc_cmd_brlshft0; + uint32_t emc_cmd_brlshft1; + uint32_t emc_cmd_brlshft2; + uint32_t emc_cmd_brlshft3; + + uint32_t emc_quse_brlshft0; + uint32_t emc_quse_brlshft1; + uint32_t emc_quse_brlshft2; + uint32_t emc_quse_brlshft3; + + uint32_t emc_dll_cfg0; + uint32_t emc_dll_cfg1; + + uint32_t emc_pmc_scratch1; + uint32_t emc_pmc_scratch2; + uint32_t emc_pmc_scratch3; + + uint32_t emc_pmacro_pad_cfg_ctrl; + + uint32_t emc_pmacro_vttgen_ctrl0; + uint32_t emc_pmacro_vttgen_ctrl1; + uint32_t emc_pmacro_vttgen_ctrl2; + + uint32_t emc_pmacro_brick_ctrl_rfu1; + uint32_t emc_pmacro_cmd_brick_ctrl_fdpd; + uint32_t emc_pmacro_brick_ctrl_rfu2; + uint32_t emc_pmacro_data_brick_ctrl_fdpd; + uint32_t emc_pmacro_bg_bias_ctrl0; + uint32_t emc_pmacro_data_pad_rx_ctrl; + uint32_t emc_pmacro_cmd_pad_rx_ctrl; + uint32_t emc_pmacro_data_rx_term_mode; + uint32_t emc_pmacro_cmd_rx_term_mode; + uint32_t emc_pmacro_data_pad_tx_ctrl; + uint32_t emc_pmacro_common_pad_tx_ctrl; + uint32_t emc_pmacro_cmd_pad_tx_ctrl; + uint32_t emc_cfg3; + + uint32_t emc_pmacro_tx_pwrd0; + uint32_t emc_pmacro_tx_pwrd1; + uint32_t emc_pmacro_tx_pwrd2; + uint32_t emc_pmacro_tx_pwrd3; + uint32_t emc_pmacro_tx_pwrd4; + uint32_t emc_pmacro_tx_pwrd5; + + uint32_t emc_config_sample_delay; + + uint32_t emc_pmacro_brick_mapping0; + uint32_t emc_pmacro_brick_mapping1; + uint32_t emc_pmacro_brick_mapping2; + + uint32_t emc_pmacro_tx_sel_clk_src0; + uint32_t emc_pmacro_tx_sel_clk_src1; + uint32_t emc_pmacro_tx_sel_clk_src2; + uint32_t emc_pmacro_tx_sel_clk_src3; + uint32_t emc_pmacro_tx_sel_clk_src4; + uint32_t emc_pmacro_tx_sel_clk_src5; + + uint32_t emc_pmacro_ddll_bypass; + + uint32_t emc_pmacro_ddll_pwrd0; + uint32_t emc_pmacro_ddll_pwrd1; + uint32_t emc_pmacro_ddll_pwrd2; + + uint32_t emc_pmacro_cmd_ctrl0; + uint32_t emc_pmacro_cmd_ctrl1; + uint32_t emc_pmacro_cmd_ctrl2; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + uint32_t mc_emem_adr_cfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + uint32_t mc_emem_adr_cfg_dev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + uint32_t mc_emem_adr_cfg_dev1; + + uint32_t mc_emem_adr_cfg_channel_mask; + + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */ + uint32_t mc_emem_adr_cfg_bank_mask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + uint32_t mc_emem_adr_cfg_bank_mask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + uint32_t mc_emem_adr_cfg_bank_mask2; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + uint32_t mc_emem_cfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + uint32_t mc_emem_arb_cfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + uint32_t mc_emem_arb_outstanding_req; + + uint32_t emc_emem_arb_refpb_hp_ctrl; + uint32_t emc_emem_arb_refpb_bank_ctrl; + + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + uint32_t mc_emem_arb_timing_rcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + uint32_t mc_emem_arb_timing_rp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + uint32_t mc_emem_arb_timing_rc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + uint32_t mc_emem_arb_timing_ras; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + uint32_t mc_emem_arb_timing_faw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + uint32_t mc_emem_arb_timing_rrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + uint32_t mc_emem_arb_timing_rap2pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + uint32_t mc_emem_arb_timing_wap2pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + uint32_t mc_emem_arb_timing_r2r; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + uint32_t mc_emem_arb_timing_w2w; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + uint32_t mc_emem_arb_timing_r2w; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + uint32_t mc_emem_arb_timing_w2r; + + uint32_t mc_emem_arb_timing_rfcpb; + + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + uint32_t mc_emem_arb_da_turns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + uint32_t mc_emem_arb_da_covers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + uint32_t mc_emem_arb_misc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + uint32_t mc_emem_arb_misc1; + uint32_t mc_emem_arb_misc2; + + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + uint32_t mc_emem_arb_ring1_throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + uint32_t mc_emem_arb_override; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + uint32_t mc_emem_arb_override1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + uint32_t mc_emem_arb_rsv; + + uint32_t mc_da_cfg0; + uint32_t mc_emem_arb_timing_ccdmw; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + uint32_t mc_clken_override; + + /* Specifies the value for MC_STAT_CONTROL */ + uint32_t mc_stat_control; + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + uint32_t mc_video_protect_bom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + uint32_t mc_video_protect_bom_adr_hi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + uint32_t mc_video_protect_size_mb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + uint32_t mc_video_protect_vpr_override; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + uint32_t mc_video_protect_vpr_override1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + uint32_t mc_video_protect_gpu_override0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + uint32_t mc_video_protect_gpu_override1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + uint32_t mc_sec_carveout_bom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + uint32_t mc_sec_carveout_adr_hi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + uint32_t mc_sec_carveout_size_mb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */ + uint32_t mc_video_protect_write_access; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */ + uint32_t mc_sec_carveout_protect_write_access; + + uint32_t mc_generalized_carveout1_bom; + uint32_t mc_generalized_carveout1_bom_hi; + uint32_t mc_generalized_carveout1_size_128kb; + uint32_t mc_generalized_carveout1_access0; + uint32_t mc_generalized_carveout1_access1; + uint32_t mc_generalized_carveout1_access2; + uint32_t mc_generalized_carveout1_access3; + uint32_t mc_generalized_carveout1_access4; + uint32_t mc_generalized_carveout1_force_internal_access0; + uint32_t mc_generalized_carveout1_force_internal_access1; + uint32_t mc_generalized_carveout1_force_internal_access2; + uint32_t mc_generalized_carveout1_force_internal_access3; + uint32_t mc_generalized_carveout1_force_internal_access4; + uint32_t mc_generalized_carveout1_cfg0; + + uint32_t mc_generalized_carveout2_bom; + uint32_t mc_generalized_carveout2_bom_hi; + uint32_t mc_generalized_carveout2_size_128kb; + uint32_t mc_generalized_carveout2_access0; + uint32_t mc_generalized_carveout2_access1; + uint32_t mc_generalized_carveout2_access2; + uint32_t mc_generalized_carveout2_access3; + uint32_t mc_generalized_carveout2_access4; + uint32_t mc_generalized_carveout2_force_internal_access0; + uint32_t mc_generalized_carveout2_force_internal_access1; + uint32_t mc_generalized_carveout2_force_internal_access2; + uint32_t mc_generalized_carveout2_force_internal_access3; + uint32_t mc_generalized_carveout2_force_internal_access4; + uint32_t mc_generalized_carveout2_cfg0; + + uint32_t mc_generalized_carveout3_bom; + uint32_t mc_generalized_carveout3_bom_hi; + uint32_t mc_generalized_carveout3_size_128kb; + uint32_t mc_generalized_carveout3_access0; + uint32_t mc_generalized_carveout3_access1; + uint32_t mc_generalized_carveout3_access2; + uint32_t mc_generalized_carveout3_access3; + uint32_t mc_generalized_carveout3_access4; + uint32_t mc_generalized_carveout3_force_internal_access0; + uint32_t mc_generalized_carveout3_force_internal_access1; + uint32_t mc_generalized_carveout3_force_internal_access2; + uint32_t mc_generalized_carveout3_force_internal_access3; + uint32_t mc_generalized_carveout3_force_internal_access4; + uint32_t mc_generalized_carveout3_cfg0; + + uint32_t mc_generalized_carveout4_bom; + uint32_t mc_generalized_carveout4_bom_hi; + uint32_t mc_generalized_carveout4_size_128kb; + uint32_t mc_generalized_carveout4_access0; + uint32_t mc_generalized_carveout4_access1; + uint32_t mc_generalized_carveout4_access2; + uint32_t mc_generalized_carveout4_access3; + uint32_t mc_generalized_carveout4_access4; + uint32_t mc_generalized_carveout4_force_internal_access0; + uint32_t mc_generalized_carveout4_force_internal_access1; + uint32_t mc_generalized_carveout4_force_internal_access2; + uint32_t mc_generalized_carveout4_force_internal_access3; + uint32_t mc_generalized_carveout4_force_internal_access4; + uint32_t mc_generalized_carveout4_cfg0; + + uint32_t mc_generalized_carveout5_bom; + uint32_t mc_generalized_carveout5_bom_hi; + uint32_t mc_generalized_carveout5_size_128kb; + uint32_t mc_generalized_carveout5_access0; + uint32_t mc_generalized_carveout5_access1; + uint32_t mc_generalized_carveout5_access2; + uint32_t mc_generalized_carveout5_access3; + uint32_t mc_generalized_carveout5_access4; + uint32_t mc_generalized_carveout5_force_internal_access0; + uint32_t mc_generalized_carveout5_force_internal_access1; + uint32_t mc_generalized_carveout5_force_internal_access2; + uint32_t mc_generalized_carveout5_force_internal_access3; + uint32_t mc_generalized_carveout5_force_internal_access4; + uint32_t mc_generalized_carveout5_cfg0; + + /* Specifies enable for CA training */ + uint32_t emc_ca_training_enable; + /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */ + uint32_t swizzle_rank_byte_encode; + /* Specifies enable and offset for patched boot rom write */ + uint32_t boot_rom_patch_control; + /* Specifies data for patched boot rom write */ + uint32_t boot_rom_patch_data; + + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + uint32_t mc_mts_carveout_bom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + uint32_t mc_mts_carveout_adr_hi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + uint32_t mc_mts_carveout_size_mb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + uint32_t mc_mts_carveout_reg_ctrl; +} sdram_params_t; + +#endif diff --git a/fusee/fusee-primary/src/sdram_param_t210_lp0.h b/fusee/fusee-primary/src/sdram_param_t210_lp0.h new file mode 100644 index 000000000..6702ea2c9 --- /dev/null +++ b/fusee/fusee-primary/src/sdram_param_t210_lp0.h @@ -0,0 +1,964 @@ +/* + * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * Copyright (C) 2018 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/** + * Defines the SDRAM parameter structure. + * + * Note that PLLM is used by EMC. The field names are in camel case to ease + * directly converting BCT config files (*.cfg) into C structure. + */ + +#ifndef __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ +#define __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ + +#include <stdint.h> + +enum +{ + /* Specifies the memory type to be undefined */ + NvBootMemoryType_None = 0, + + /* Specifies the memory type to be DDR SDRAM */ + NvBootMemoryType_Ddr = 0, + + /* Specifies the memory type to be LPDDR SDRAM */ + NvBootMemoryType_LpDdr = 0, + + /* Specifies the memory type to be DDR2 SDRAM */ + NvBootMemoryType_Ddr2 = 0, + + /* Specifies the memory type to be LPDDR2 SDRAM */ + NvBootMemoryType_LpDdr2, + + /* Specifies the memory type to be DDR3 SDRAM */ + NvBootMemoryType_Ddr3, + + /* Specifies the memory type to be LPDDR4 SDRAM */ + NvBootMemoryType_LpDdr4, + + NvBootMemoryType_Num, + + /* Specifies an entry in the ram_code table that's not in use */ + NvBootMemoryType_Unused = 0X7FFFFFF, +}; + +/** + * Defines the SDRAM parameter structure + */ +struct sdram_params +{ + + /* Specifies the type of memory device */ + uint32_t MemoryType; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + uint32_t PllMInputDivider; + /* Specifies the N value for PllM */ + uint32_t PllMFeedbackDivider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + uint32_t PllMStableTime; + /* Specifies misc. control bits */ + uint32_t PllMSetupControl; + /* Specifies the P value for PLLM */ + uint32_t PllMPostDivider; + /* Specifies value for Charge Pump Gain Control */ + uint32_t PllMKCP; + /* Specifies VCO gain */ + uint32_t PllMKVCO; + /* Spare BCT param */ + uint32_t EmcBctSpare0; + /* Spare BCT param */ + uint32_t EmcBctSpare1; + /* Spare BCT param */ + uint32_t EmcBctSpare2; + /* Spare BCT param */ + uint32_t EmcBctSpare3; + /* Spare BCT param */ + uint32_t EmcBctSpare4; + /* Spare BCT param */ + uint32_t EmcBctSpare5; + /* Spare BCT param */ + uint32_t EmcBctSpare6; + /* Spare BCT param */ + uint32_t EmcBctSpare7; + /* Spare BCT param */ + uint32_t EmcBctSpare8; + /* Spare BCT param */ + uint32_t EmcBctSpare9; + /* Spare BCT param */ + uint32_t EmcBctSpare10; + /* Spare BCT param */ + uint32_t EmcBctSpare11; + /* Spare BCT param */ + uint32_t EmcBctSpare12; + /* Spare BCT param */ + uint32_t EmcBctSpare13; + + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + uint32_t EmcClockSource; + uint32_t EmcClockSourceDll; + + /* Defines possible override for PLLLM_MISC2 */ + uint32_t ClkRstControllerPllmMisc2Override; + /* enables override for PLLLM_MISC2 */ + uint32_t ClkRstControllerPllmMisc2OverrideEnable; + /* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */ + uint32_t ClearClk2Mc1; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + uint32_t EmcAutoCalInterval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + uint32_t EmcAutoCalConfig; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + uint32_t EmcAutoCalConfig2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + uint32_t EmcAutoCalConfig3; + + /* Specifies the values for EMC_AUTO_CAL_CONFIG4-8 */ + uint32_t EmcAutoCalConfig4; + uint32_t EmcAutoCalConfig5; + uint32_t EmcAutoCalConfig6; + uint32_t EmcAutoCalConfig7; + uint32_t EmcAutoCalConfig8; + + /* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */ + uint32_t EmcAutoCalVrefSel0; + uint32_t EmcAutoCalVrefSel1; + + /* Specifies the value for EMC_AUTO_CAL_CHANNEL */ + uint32_t EmcAutoCalChannel; + + /* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */ + uint32_t EmcPmacroAutocalCfg0; + uint32_t EmcPmacroAutocalCfg1; + uint32_t EmcPmacroAutocalCfg2; + uint32_t EmcPmacroRxTerm; + uint32_t EmcPmacroDqTxDrv; + uint32_t EmcPmacroCaTxDrv; + uint32_t EmcPmacroCmdTxDrv; + uint32_t EmcPmacroAutocalCfgCommon; + uint32_t EmcPmacroZctrl; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + uint32_t EmcAutoCalWait; + + uint32_t EmcXm2CompPadCtrl; + uint32_t EmcXm2CompPadCtrl2; + uint32_t EmcXm2CompPadCtrl3; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + uint32_t EmcAdrCfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + uint32_t EmcPinProgramWait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + uint32_t EmcPinExtraWait; + + uint32_t EmcPinGpioEn; + uint32_t EmcPinGpio; + + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + uint32_t EmcTimingControlWait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + uint32_t EmcRc; + /* Specifies the value for EMC_RFC */ + uint32_t EmcRfc; + /* Specifies the value for EMC_RFC_PB */ + uint32_t EmcRfcPb; + /* Specifies the value for EMC_RFC_CTRL2 */ + uint32_t EmcRefctrl2; + /* Specifies the value for EMC_RFC_SLR */ + uint32_t EmcRfcSlr; + /* Specifies the value for EMC_RAS */ + uint32_t EmcRas; + /* Specifies the value for EMC_RP */ + uint32_t EmcRp; + /* Specifies the value for EMC_R2R */ + uint32_t EmcR2r; + /* Specifies the value for EMC_W2W */ + uint32_t EmcW2w; + /* Specifies the value for EMC_R2W */ + uint32_t EmcR2w; + /* Specifies the value for EMC_W2R */ + uint32_t EmcW2r; + /* Specifies the value for EMC_R2P */ + uint32_t EmcR2p; + /* Specifies the value for EMC_W2P */ + uint32_t EmcW2p; + + uint32_t EmcTppd; + uint32_t EmcCcdmw; + + /* Specifies the value for EMC_RD_RCD */ + uint32_t EmcRdRcd; + /* Specifies the value for EMC_WR_RCD */ + uint32_t EmcWrRcd; + /* Specifies the value for EMC_RRD */ + uint32_t EmcRrd; + /* Specifies the value for EMC_REXT */ + uint32_t EmcRext; + /* Specifies the value for EMC_WEXT */ + uint32_t EmcWext; + /* Specifies the value for EMC_WDV */ + uint32_t EmcWdv; + + uint32_t EmcWdvChk; + uint32_t EmcWsv; + uint32_t EmcWev; + + /* Specifies the value for EMC_WDV_MASK */ + uint32_t EmcWdvMask; + + uint32_t EmcWsDuration; + uint32_t EmcWeDuration; + + /* Specifies the value for EMC_QUSE */ + uint32_t EmcQUse; + /* Specifies the value for EMC_QUSE_WIDTH */ + uint32_t EmcQuseWidth; + /* Specifies the value for EMC_IBDLY */ + uint32_t EmcIbdly; + /* Specifies the value for EMC_OBDLY */ + uint32_t EmcObdly; + /* Specifies the value for EMC_EINPUT */ + uint32_t EmcEInput; + /* Specifies the value for EMC_EINPUT_DURATION */ + uint32_t EmcEInputDuration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + uint32_t EmcPutermExtra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + uint32_t EmcPutermWidth; + /* Specifies the value for EMC_PUTERM_ADJ */ + ////uint32_t EmcPutermAdj; + + /* Specifies the value for EMC_QRST */ + uint32_t EmcQRst; + /* Specifies the value for EMC_QSAFE */ + uint32_t EmcQSafe; + /* Specifies the value for EMC_RDV */ + uint32_t EmcRdv; + /* Specifies the value for EMC_RDV_MASK */ + uint32_t EmcRdvMask; + /* Specifies the value for EMC_RDV_EARLY */ + uint32_t EmcRdvEarly; + /* Specifies the value for EMC_RDV_EARLY_MASK */ + uint32_t EmcRdvEarlyMask; + /* Specifies the value for EMC_QPOP */ + uint32_t EmcQpop; + + /* Specifies the value for EMC_REFRESH */ + uint32_t EmcRefresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + uint32_t EmcBurstRefreshNum; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + uint32_t EmcPreRefreshReqCnt; + /* Specifies the value for EMC_PDEX2WR */ + uint32_t EmcPdEx2Wr; + /* Specifies the value for EMC_PDEX2RD */ + uint32_t EmcPdEx2Rd; + /* Specifies the value for EMC_PCHG2PDEN */ + uint32_t EmcPChg2Pden; + /* Specifies the value for EMC_ACT2PDEN */ + uint32_t EmcAct2Pden; + /* Specifies the value for EMC_AR2PDEN */ + uint32_t EmcAr2Pden; + /* Specifies the value for EMC_RW2PDEN */ + uint32_t EmcRw2Pden; + /* Specifies the value for EMC_CKE2PDEN */ + uint32_t EmcCke2Pden; + /* Specifies the value for EMC_PDEX2CKE */ + uint32_t EmcPdex2Cke; + /* Specifies the value for EMC_PDEX2MRR */ + uint32_t EmcPdex2Mrr; + /* Specifies the value for EMC_TXSR */ + uint32_t EmcTxsr; + /* Specifies the value for EMC_TXSRDLL */ + uint32_t EmcTxsrDll; + /* Specifies the value for EMC_TCKE */ + uint32_t EmcTcke; + /* Specifies the value for EMC_TCKESR */ + uint32_t EmcTckesr; + /* Specifies the value for EMC_TPD */ + uint32_t EmcTpd; + /* Specifies the value for EMC_TFAW */ + uint32_t EmcTfaw; + /* Specifies the value for EMC_TRPAB */ + uint32_t EmcTrpab; + /* Specifies the value for EMC_TCLKSTABLE */ + uint32_t EmcTClkStable; + /* Specifies the value for EMC_TCLKSTOP */ + uint32_t EmcTClkStop; + /* Specifies the value for EMC_TREFBW */ + uint32_t EmcTRefBw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + uint32_t EmcFbioCfg5; + /* Specifies the value for EMC_FBIO_CFG7 */ + uint32_t EmcFbioCfg7; + /* Specifies the value for EMC_FBIO_CFG8 */ + uint32_t EmcFbioCfg8; + + /* Command mapping for CMD brick 0 */ + uint32_t EmcCmdMappingCmd0_0; + uint32_t EmcCmdMappingCmd0_1; + uint32_t EmcCmdMappingCmd0_2; + uint32_t EmcCmdMappingCmd1_0; + uint32_t EmcCmdMappingCmd1_1; + uint32_t EmcCmdMappingCmd1_2; + uint32_t EmcCmdMappingCmd2_0; + uint32_t EmcCmdMappingCmd2_1; + uint32_t EmcCmdMappingCmd2_2; + uint32_t EmcCmdMappingCmd3_0; + uint32_t EmcCmdMappingCmd3_1; + uint32_t EmcCmdMappingCmd3_2; + uint32_t EmcCmdMappingByte; + + /* Specifies the value for EMC_FBIO_SPARE */ + uint32_t EmcFbioSpare; + + /* Specifies the value for EMC_CFG_RSV */ + uint32_t EmcCfgRsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + uint32_t EmcMrs; + /* Specifies the MP0 command to initialize mode registers */ + uint32_t EmcEmrs; + /* Specifies the MP2 command to initialize mode registers */ + uint32_t EmcEmrs2; + /* Specifies the MP3 command to initialize mode registers */ + uint32_t EmcEmrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + uint32_t EmcMrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + uint32_t EmcMrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + uint32_t EmcMrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t EmcMrw4; + /* Specifies the programming to LPDDR2 Mode Register 3? at cold boot */ + uint32_t EmcMrw6; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t EmcMrw8; + /* Specifies the programming to LPDDR2 Mode Register 11? at cold boot */ + uint32_t EmcMrw9; + /* Specifies the programming to LPDDR2 Mode Register 12 at cold boot */ + uint32_t EmcMrw10; + /* Specifies the programming to LPDDR2 Mode Register 14 at cold boot */ + uint32_t EmcMrw12; + /* Specifies the programming to LPDDR2 Mode Register 14? at cold boot */ + uint32_t EmcMrw13; + /* Specifies the programming to LPDDR2 Mode Register 22 at cold boot */ + uint32_t EmcMrw14; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + uint32_t EmcMrwExtra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + uint32_t EmcWarmBootMrwExtra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + uint32_t EmcWarmBootExtraModeRegWriteEnable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + uint32_t EmcExtraModeRegWriteEnable; + + /* Specifies the EMC_MRW reset command value */ + uint32_t EmcMrwResetCommand; + /* Specifies the EMC Reset wait time (in microseconds) */ + uint32_t EmcMrwResetNInitWait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + uint32_t EmcMrsWaitCnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + uint32_t EmcMrsWaitCnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + uint32_t EmcCfg; + /* Specifies the value for EMC_CFG_2 */ + uint32_t EmcCfg2; + /* Specifies the pipe bypass controls */ + uint32_t EmcCfgPipe; + uint32_t EmcCfgPipeClk; + uint32_t EmcFdpdCtrlCmdNoRamp; + uint32_t EmcCfgUpdate; + + /* Specifies the value for EMC_DBG */ + uint32_t EmcDbg; + uint32_t EmcDbgWriteMux; + + /* Specifies the value for EMC_CMDQ */ + uint32_t EmcCmdQ; + /* Specifies the value for EMC_MC2EMCQ */ + uint32_t EmcMc2EmcQ; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + uint32_t EmcDynSelfRefControl; + + /* Specifies the value for MEM_INIT_DONE */ + uint32_t AhbArbitrationXbarCtrlMemInitDone; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + uint32_t EmcCfgDigDll; + uint32_t EmcCfgDigDll_1; + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + uint32_t EmcCfgDigDllPeriod; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + uint32_t EmcDevSelect; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + uint32_t EmcSelDpdCtrl; + + /* Pads trimmer delays */ + uint32_t EmcFdpdCtrlDq; + uint32_t EmcFdpdCtrlCmd; + uint32_t EmcPmacroIbVrefDq_0; + uint32_t EmcPmacroIbVrefDq_1; + uint32_t EmcPmacroIbVrefDqs_0; + uint32_t EmcPmacroIbVrefDqs_1; + uint32_t EmcPmacroIbRxrt; + uint32_t EmcCfgPipe1; + uint32_t EmcCfgPipe2; + + /* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */ + uint32_t EmcPmacroQuseDdllRank0_0; + uint32_t EmcPmacroQuseDdllRank0_1; + uint32_t EmcPmacroQuseDdllRank0_2; + uint32_t EmcPmacroQuseDdllRank0_3; + uint32_t EmcPmacroQuseDdllRank0_4; + uint32_t EmcPmacroQuseDdllRank0_5; + uint32_t EmcPmacroQuseDdllRank1_0; + uint32_t EmcPmacroQuseDdllRank1_1; + uint32_t EmcPmacroQuseDdllRank1_2; + uint32_t EmcPmacroQuseDdllRank1_3; + uint32_t EmcPmacroQuseDdllRank1_4; + uint32_t EmcPmacroQuseDdllRank1_5; + + uint32_t EmcPmacroObDdllLongDqRank0_0; + uint32_t EmcPmacroObDdllLongDqRank0_1; + uint32_t EmcPmacroObDdllLongDqRank0_2; + uint32_t EmcPmacroObDdllLongDqRank0_3; + uint32_t EmcPmacroObDdllLongDqRank0_4; + uint32_t EmcPmacroObDdllLongDqRank0_5; + uint32_t EmcPmacroObDdllLongDqRank1_0; + uint32_t EmcPmacroObDdllLongDqRank1_1; + uint32_t EmcPmacroObDdllLongDqRank1_2; + uint32_t EmcPmacroObDdllLongDqRank1_3; + uint32_t EmcPmacroObDdllLongDqRank1_4; + uint32_t EmcPmacroObDdllLongDqRank1_5; + + uint32_t EmcPmacroObDdllLongDqsRank0_0; + uint32_t EmcPmacroObDdllLongDqsRank0_1; + uint32_t EmcPmacroObDdllLongDqsRank0_2; + uint32_t EmcPmacroObDdllLongDqsRank0_3; + uint32_t EmcPmacroObDdllLongDqsRank0_4; + uint32_t EmcPmacroObDdllLongDqsRank0_5; + uint32_t EmcPmacroObDdllLongDqsRank1_0; + uint32_t EmcPmacroObDdllLongDqsRank1_1; + uint32_t EmcPmacroObDdllLongDqsRank1_2; + uint32_t EmcPmacroObDdllLongDqsRank1_3; + uint32_t EmcPmacroObDdllLongDqsRank1_4; + uint32_t EmcPmacroObDdllLongDqsRank1_5; + + uint32_t EmcPmacroIbDdllLongDqsRank0_0; + uint32_t EmcPmacroIbDdllLongDqsRank0_1; + uint32_t EmcPmacroIbDdllLongDqsRank0_2; + uint32_t EmcPmacroIbDdllLongDqsRank0_3; + uint32_t EmcPmacroIbDdllLongDqsRank1_0; + uint32_t EmcPmacroIbDdllLongDqsRank1_1; + uint32_t EmcPmacroIbDdllLongDqsRank1_2; + uint32_t EmcPmacroIbDdllLongDqsRank1_3; + + uint32_t EmcPmacroDdllLongCmd_0; + uint32_t EmcPmacroDdllLongCmd_1; + uint32_t EmcPmacroDdllLongCmd_2; + uint32_t EmcPmacroDdllLongCmd_3; + uint32_t EmcPmacroDdllLongCmd_4; + uint32_t EmcPmacroDdllShortCmd_0; + uint32_t EmcPmacroDdllShortCmd_1; + uint32_t EmcPmacroDdllShortCmd_2; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + uint32_t WarmBootWait; + + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t EmcOdtWrite; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + uint32_t EmcZcalInterval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + uint32_t EmcZcalWaitCnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + uint32_t EmcZcalMrwCmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + uint32_t EmcMrsResetDll; + /* Specifies the command for ZQ initialization of device 0 */ + uint32_t EmcZcalInitDev0; + /* Specifies the command for ZQ initialization of device 1 */ + uint32_t EmcZcalInitDev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + uint32_t EmcZcalInitWait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + uint32_t EmcZcalWarmColdBootEnables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + uint32_t EmcMrwLpddr2ZcalWarmBoot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + uint32_t EmcZqCalDdr3WarmBoot; + uint32_t EmcZqCalLpDdr4WarmBoot; + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + uint32_t EmcZcalWarmBootWait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + uint32_t EmcMrsWarmBootEnable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + uint32_t EmcMrsResetDllWait; + /* Specifies the extra MRS command to initialize mode registers */ + uint32_t EmcMrsExtra; + /* Specifies the extra MRS command at warm boot */ + uint32_t EmcWarmBootMrsExtra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + uint32_t EmcEmrsDdr2DllEnable; + /* Specifies the MRS command to reset the DDR2 DLL */ + uint32_t EmcMrsDdr2DllReset; + /* Specifies the EMRS command to set OCD calibration */ + uint32_t EmcEmrsDdr2OcdCalib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + uint32_t EmcDdr2Wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + uint32_t EmcClkenOverride; + + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + uint32_t EmcExtraRefreshNum; + /* Specifies the master override for all EMC clocks */ + uint32_t EmcClkenOverrideAllWarmBoot; + /* Specifies the master override for all MC clocks */ + uint32_t McClkenOverrideAllWarmBoot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + uint32_t EmcCfgDigDllPeriodWarmBoot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + uint32_t PmcVddpSel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + uint32_t PmcVddpSelWait; + /* Specifies the value for PMC_DDR_PWR */ + uint32_t PmcDdrPwr; + /* Specifies the value for PMC_DDR_CFG */ + uint32_t PmcDdrCfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3Req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3ReqWait; + uint32_t PmcIoDpd4ReqWait; + + /* Specifies the value for PMC_REG_SHORT */ + uint32_t PmcRegShort; + /* Specifies the value for PMC_NO_IOPOWER */ + uint32_t PmcNoIoPower; + + uint32_t PmcDdrCntrlWait; + uint32_t PmcDdrCntrl; + + /* Specifies the value for EMC_ACPD_CONTROL */ + uint32_t EmcAcpdControl; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE_CFG */ + ////uint32_t EmcSwizzleRank0ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + uint32_t EmcSwizzleRank0Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + uint32_t EmcSwizzleRank0Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + uint32_t EmcSwizzleRank0Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + uint32_t EmcSwizzleRank0Byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE_CFG */ + ////uint32_t EmcSwizzleRank1ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + uint32_t EmcSwizzleRank1Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + uint32_t EmcSwizzleRank1Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + uint32_t EmcSwizzleRank1Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + uint32_t EmcSwizzleRank1Byte3; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + uint32_t EmcTxdsrvttgen; + + /* Specifies the value for EMC_DATA_BRLSHFT_0 */ + uint32_t EmcDataBrlshft0; + uint32_t EmcDataBrlshft1; + + uint32_t EmcDqsBrlshft0; + uint32_t EmcDqsBrlshft1; + + uint32_t EmcCmdBrlshft0; + uint32_t EmcCmdBrlshft1; + uint32_t EmcCmdBrlshft2; + uint32_t EmcCmdBrlshft3; + + uint32_t EmcQuseBrlshft0; + uint32_t EmcQuseBrlshft1; + uint32_t EmcQuseBrlshft2; + uint32_t EmcQuseBrlshft3; + + uint32_t EmcDllCfg0; + uint32_t EmcDllCfg1; + + uint32_t EmcPmcScratch1; + uint32_t EmcPmcScratch2; + uint32_t EmcPmcScratch3; + + uint32_t EmcPmacroPadCfgCtrl; + + uint32_t EmcPmacroVttgenCtrl0; + uint32_t EmcPmacroVttgenCtrl1; + uint32_t EmcPmacroVttgenCtrl2; + + uint32_t EmcPmacroBrickCtrlRfu1; + uint32_t EmcPmacroCmdBrickCtrlFdpd; + uint32_t EmcPmacroBrickCtrlRfu2; + uint32_t EmcPmacroDataBrickCtrlFdpd; + uint32_t EmcPmacroBgBiasCtrl0; + uint32_t EmcPmacroDataPadRxCtrl; + uint32_t EmcPmacroCmdPadRxCtrl; + uint32_t EmcPmacroDataRxTermMode; + uint32_t EmcPmacroCmdRxTermMode; + uint32_t EmcPmacroDataPadTxCtrl; + uint32_t EmcPmacroCommonPadTxCtrl; + uint32_t EmcPmacroCmdPadTxCtrl; + uint32_t EmcCfg3; + + uint32_t EmcPmacroTxPwrd0; + uint32_t EmcPmacroTxPwrd1; + uint32_t EmcPmacroTxPwrd2; + uint32_t EmcPmacroTxPwrd3; + uint32_t EmcPmacroTxPwrd4; + uint32_t EmcPmacroTxPwrd5; + + uint32_t EmcConfigSampleDelay; + + uint32_t EmcPmacroBrickMapping0; + uint32_t EmcPmacroBrickMapping1; + uint32_t EmcPmacroBrickMapping2; + + uint32_t EmcPmacroTxSelClkSrc0; + uint32_t EmcPmacroTxSelClkSrc1; + uint32_t EmcPmacroTxSelClkSrc2; + uint32_t EmcPmacroTxSelClkSrc3; + uint32_t EmcPmacroTxSelClkSrc4; + uint32_t EmcPmacroTxSelClkSrc5; + + uint32_t EmcPmacroDdllBypass; + + uint32_t EmcPmacroDdllPwrd0; + uint32_t EmcPmacroDdllPwrd1; + uint32_t EmcPmacroDdllPwrd2; + + uint32_t EmcPmacroCmdCtrl0; + uint32_t EmcPmacroCmdCtrl1; + uint32_t EmcPmacroCmdCtrl2; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + uint32_t McEmemAdrCfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + uint32_t McEmemAdrCfgDev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + uint32_t McEmemAdrCfgDev1; + uint32_t McEmemAdrCfgChannelMask; + + /* Specifies the value for MC_EMEM_BANK_SWIZZLECfg0 */ + uint32_t McEmemAdrCfgBankMask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + uint32_t McEmemAdrCfgBankMask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + uint32_t McEmemAdrCfgBankMask2; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + uint32_t McEmemCfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + uint32_t McEmemArbCfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + uint32_t McEmemArbOutstandingReq; + + uint32_t McEmemArbRefpbHpCtrl; + uint32_t McEmemArbRefpbBankCtrl; + + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + uint32_t McEmemArbTimingRcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + uint32_t McEmemArbTimingRp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + uint32_t McEmemArbTimingRc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + uint32_t McEmemArbTimingRas; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + uint32_t McEmemArbTimingFaw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + uint32_t McEmemArbTimingRrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + uint32_t McEmemArbTimingRap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + uint32_t McEmemArbTimingWap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + uint32_t McEmemArbTimingR2R; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + uint32_t McEmemArbTimingW2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + uint32_t McEmemArbTimingR2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + uint32_t McEmemArbTimingW2R; + + uint32_t McEmemArbTimingRFCPB; + + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + uint32_t McEmemArbDaTurns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + uint32_t McEmemArbDaCovers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + uint32_t McEmemArbMisc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + uint32_t McEmemArbMisc1; + uint32_t McEmemArbMisc2; + + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + uint32_t McEmemArbRing1Throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + uint32_t McEmemArbOverride; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + uint32_t McEmemArbOverride1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + uint32_t McEmemArbRsv; + + uint32_t McDaCfg0; + uint32_t McEmemArbTimingCcdmw; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + uint32_t McClkenOverride; + + /* Specifies the value for MC_STAT_CONTROL */ + uint32_t McStatControl; + + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + uint32_t McVideoProtectBom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + uint32_t McVideoProtectBomAdrHi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + uint32_t McVideoProtectSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + uint32_t McVideoProtectVprOverride; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + uint32_t McVideoProtectVprOverride1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + uint32_t McVideoProtectGpuOverride0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + uint32_t McVideoProtectGpuOverride1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + uint32_t McSecCarveoutBom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + uint32_t McSecCarveoutAdrHi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + uint32_t McSecCarveoutSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL. + VIDEO_PROTECT_WRITEAccess */ + uint32_t McVideoProtectWriteAccess; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL. + SEC_CARVEOUT_WRITEAccess */ + uint32_t McSecCarveoutProtectWriteAccess; + + /* Write-Protect Regions (WPR) */ + uint32_t McGeneralizedCarveout1Bom; + uint32_t McGeneralizedCarveout1BomHi; + uint32_t McGeneralizedCarveout1Size128kb; + uint32_t McGeneralizedCarveout1Access0; + uint32_t McGeneralizedCarveout1Access1; + uint32_t McGeneralizedCarveout1Access2; + uint32_t McGeneralizedCarveout1Access3; + uint32_t McGeneralizedCarveout1Access4; + uint32_t McGeneralizedCarveout1ForceInternalAccess0; + uint32_t McGeneralizedCarveout1ForceInternalAccess1; + uint32_t McGeneralizedCarveout1ForceInternalAccess2; + uint32_t McGeneralizedCarveout1ForceInternalAccess3; + uint32_t McGeneralizedCarveout1ForceInternalAccess4; + uint32_t McGeneralizedCarveout1Cfg0; + + uint32_t McGeneralizedCarveout2Bom; + uint32_t McGeneralizedCarveout2BomHi; + uint32_t McGeneralizedCarveout2Size128kb; + uint32_t McGeneralizedCarveout2Access0; + uint32_t McGeneralizedCarveout2Access1; + uint32_t McGeneralizedCarveout2Access2; + uint32_t McGeneralizedCarveout2Access3; + uint32_t McGeneralizedCarveout2Access4; + uint32_t McGeneralizedCarveout2ForceInternalAccess0; + uint32_t McGeneralizedCarveout2ForceInternalAccess1; + uint32_t McGeneralizedCarveout2ForceInternalAccess2; + uint32_t McGeneralizedCarveout2ForceInternalAccess3; + uint32_t McGeneralizedCarveout2ForceInternalAccess4; + uint32_t McGeneralizedCarveout2Cfg0; + + uint32_t McGeneralizedCarveout3Bom; + uint32_t McGeneralizedCarveout3BomHi; + uint32_t McGeneralizedCarveout3Size128kb; + uint32_t McGeneralizedCarveout3Access0; + uint32_t McGeneralizedCarveout3Access1; + uint32_t McGeneralizedCarveout3Access2; + uint32_t McGeneralizedCarveout3Access3; + uint32_t McGeneralizedCarveout3Access4; + uint32_t McGeneralizedCarveout3ForceInternalAccess0; + uint32_t McGeneralizedCarveout3ForceInternalAccess1; + uint32_t McGeneralizedCarveout3ForceInternalAccess2; + uint32_t McGeneralizedCarveout3ForceInternalAccess3; + uint32_t McGeneralizedCarveout3ForceInternalAccess4; + uint32_t McGeneralizedCarveout3Cfg0; + + uint32_t McGeneralizedCarveout4Bom; + uint32_t McGeneralizedCarveout4BomHi; + uint32_t McGeneralizedCarveout4Size128kb; + uint32_t McGeneralizedCarveout4Access0; + uint32_t McGeneralizedCarveout4Access1; + uint32_t McGeneralizedCarveout4Access2; + uint32_t McGeneralizedCarveout4Access3; + uint32_t McGeneralizedCarveout4Access4; + uint32_t McGeneralizedCarveout4ForceInternalAccess0; + uint32_t McGeneralizedCarveout4ForceInternalAccess1; + uint32_t McGeneralizedCarveout4ForceInternalAccess2; + uint32_t McGeneralizedCarveout4ForceInternalAccess3; + uint32_t McGeneralizedCarveout4ForceInternalAccess4; + uint32_t McGeneralizedCarveout4Cfg0; + + uint32_t McGeneralizedCarveout5Bom; + uint32_t McGeneralizedCarveout5BomHi; + uint32_t McGeneralizedCarveout5Size128kb; + uint32_t McGeneralizedCarveout5Access0; + uint32_t McGeneralizedCarveout5Access1; + uint32_t McGeneralizedCarveout5Access2; + uint32_t McGeneralizedCarveout5Access3; + uint32_t McGeneralizedCarveout5Access4; + uint32_t McGeneralizedCarveout5ForceInternalAccess0; + uint32_t McGeneralizedCarveout5ForceInternalAccess1; + uint32_t McGeneralizedCarveout5ForceInternalAccess2; + uint32_t McGeneralizedCarveout5ForceInternalAccess3; + uint32_t McGeneralizedCarveout5ForceInternalAccess4; + uint32_t McGeneralizedCarveout5Cfg0; + + /* Specifies enable for CA training */ + uint32_t EmcCaTrainingEnable; + + /* Set if bit 6 select is greater than bit 7 select; uses aremc. + spec packet SWIZZLE_BIT6_GT_BIT7 */ + uint32_t SwizzleRankByteEncode; + /* Specifies enable and offset for patched boot ROM write */ + uint32_t BootRomPatchControl; + /* Specifies data for patched boot ROM write */ + uint32_t BootRomPatchData; + + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + uint32_t McMtsCarveoutBom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + uint32_t McMtsCarveoutAdrHi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + uint32_t McMtsCarveoutSizeMb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + uint32_t McMtsCarveoutRegCtrl; + + /* End */ +}; + +#endif /* __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ */ diff --git a/fusee/fusee-primary/src/se.c b/fusee/fusee-primary/src/se.c index 18e16bd99..af86980b3 100644 --- a/fusee/fusee-primary/src/se.c +++ b/fusee/fusee-primary/src/se.c @@ -1,7 +1,6 @@ #include <string.h> #include "utils.h" -/*#include "interrupt.h"*/ #include "se.h" void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size); @@ -24,42 +23,49 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { } void se_check_error_status_reg(void) { - if (SECURITY_ENGINE->ERR_STATUS_REG) { + volatile tegra_se_t *se = se_get_regs(); + if (se->ERR_STATUS_REG) { generic_panic(); } } void se_check_for_error(void) { - if (SECURITY_ENGINE->INT_STATUS_REG & 0x10000 || SECURITY_ENGINE->FLAGS_REG & 3 || SECURITY_ENGINE->ERR_STATUS_REG) { + volatile tegra_se_t *se = se_get_regs(); + if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) { generic_panic(); } } void se_verify_flags_cleared(void) { - if (SECURITY_ENGINE->FLAGS_REG & 3) { + volatile tegra_se_t *se = se_get_regs(); + if (se->FLAGS_REG & 3) { generic_panic(); } } /* Set the flags for an AES keyslot. */ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Misc flags. */ if (flags & ~0x80) { - SECURITY_ENGINE->AES_KEYSLOT_FLAGS[keyslot] = ~flags; + se->AES_KEYSLOT_FLAGS[keyslot] = ~flags; } /* Disable keyslot reads. */ if (flags & 0x80) { - SECURITY_ENGINE->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); } } /* Set the flags for an RSA keyslot. */ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX) { generic_panic(); } @@ -67,28 +73,32 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { /* Misc flags. */ if (flags & ~0x80) { /* TODO: Why are flags assigned this way? */ - SECURITY_ENGINE->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; + se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; } /* Disable keyslot reads. */ if (flags & 0x80) { - SECURITY_ENGINE->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); } } void clear_aes_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Zero out the whole keyslot and IV. */ for (unsigned int i = 0; i < 0x10; i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = 0; + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = 0; } } void clear_rsa_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX) { generic_panic(); } @@ -96,40 +106,44 @@ void clear_rsa_keyslot(unsigned int keyslot) { /* Zero out the whole keyslot. */ for (unsigned int i = 0; i < 0x40; i++) { /* Select Keyslot Modulus[i] */ - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = 0; + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; + se->RSA_KEYTABLE_DATA = 0; } for (unsigned int i = 0; i < 0x40; i++) { /* Select Keyslot Expontent[i] */ - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = 0; + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = 0; } } void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { generic_panic(); } for (size_t i = 0; i < (key_size >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = read32le(key, 4 * i); + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = read32le(key, 4 * i); } } void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { generic_panic(); } for (size_t i = 0; i < (modulus_size >> 2); i++) { - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; + se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); } for (size_t i = 0; i < (exp_size >> 2); i++) { - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); } g_se_modulus_sizes[keyslot] = modulus_size; @@ -137,47 +151,55 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_ } void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { generic_panic(); } for (size_t i = 0; i < (iv_size >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = read32le(iv, 4 * i); + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = read32le(iv, 4 * i); } } void clear_aes_keyslot_iv(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } for (size_t i = 0; i < (0x10 >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = 0; + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = 0; } } void set_se_ctr(const void *ctr) { + volatile tegra_se_t *se = se_get_regs(); for (unsigned int i = 0; i < 4; i++) { - SECURITY_ENGINE->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + se->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); } } void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); - SECURITY_ENGINE->CRYPTO_REG = keyslot_src << 24; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; - SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; + se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); + se->CRYPTO_REG = keyslot_src << 24; + se->BLOCK_COUNT_REG = 0; + se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); } void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); uint8_t ALIGN(16) stack_buf[KEYSIZE_RSA_MAX]; if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) { @@ -189,18 +211,19 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co stack_buf[i] = *((uint8_t *)src + src_size - i - 1); } - SECURITY_ENGINE->CONFIG_REG = (ALG_RSA | DST_RSAREG); - SECURITY_ENGINE->RSA_CONFIG = keyslot << 24; - SECURITY_ENGINE->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; - SECURITY_ENGINE->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; - + se->CONFIG_REG = (ALG_RSA | DST_RSAREG); + se->RSA_CONFIG = keyslot << 24; + se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; + se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size); se_get_exp_mod_output(dst, dst_size); } void se_get_exp_mod_output(void *buf, size_t size) { + volatile tegra_se_t *se = se_get_regs(); size_t num_dwords = (size >> 2); + if (num_dwords < 1) { return; } @@ -210,7 +233,7 @@ void se_get_exp_mod_output(void *buf, size_t size) { /* Copy endian swapped output. */ while (num_dwords) { - *p_out = read32be(SECURITY_ENGINE->RSA_OUTPUT, offset); + *p_out = read32be(se->RSA_OUTPUT, offset); offset += 4; p_out--; num_dwords--; @@ -271,6 +294,7 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v } void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); se_ll_t in_ll; se_ll_t out_ll; @@ -278,21 +302,22 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v ll_init(&out_ll, dst, dst_size); /* Set the LLs. */ - SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); - SECURITY_ENGINE->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll); + se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); + se->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll); /* Set registers for operation. */ - SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG; - SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG; - SECURITY_ENGINE->OPERATION_REG = op; + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = op; - while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ } + while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ } se_check_for_error(); } /* Secure AES Functionality. */ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); uint8_t block[0x10] = {0}; if (src_size > sizeof(block) || dst_size > sizeof(block)) { @@ -305,7 +330,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } /* Trigger AES operation. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); /* Copy output data into dst. */ @@ -315,21 +340,23 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) { generic_panic(); } unsigned int num_blocks = src_size >> 4; /* Unknown what this write does, but official code writes it for CTR mode. */ - SECURITY_ENGINE->_0x80C = 1; - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x91E; + se->SPARE_0 = 1; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x91E; set_se_ctr(ctr); /* Handle any aligned blocks. */ size_t aligned_size = (size_t)num_blocks << 4; if (aligned_size) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1; + se->BLOCK_COUNT_REG = num_blocks - 1; trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size); } @@ -344,15 +371,16 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo } void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } /* Set configuration high (256-bit vs 128-bit) based on parameter. */ - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); - SECURITY_ENGINE->CRYPTO_REG = keyslot << 24 | 0x100; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); + se->CRYPTO_REG = keyslot << 24 | 0x100; se_perform_aes_block_operation(dst, 0x10, src, 0x10); - } void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { @@ -365,12 +393,14 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = keyslot << 24; + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot << 24; se_perform_aes_block_operation(dst, 0x10, src, 0x10); } @@ -422,6 +452,8 @@ void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, ui } void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keyslot_2, size_t sector, bool encrypt, void *dst, const void *src, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + if ((size & 0xF) || size == 0) { generic_panic(); } @@ -431,13 +463,13 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys /* Encrypt/Decrypt. */ if (encrypt) { - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = keyslot_1 << 24 | 0x100; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = keyslot_1 << 24 | 0x100; } else { - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = keyslot_1 << 24; + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot_1 << 24; } - SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1; + se->BLOCK_COUNT_REG = (size >> 4) - 1; trigger_se_blocking_op(OP_START, dst, size, src, size); /* XOR. */ @@ -469,6 +501,8 @@ void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslo } void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -481,17 +515,17 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con shift_left_xor_rb(derived_key); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | (0x145); + se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); + se->CRYPTO_REG = (keyslot << 24) | (0x145); clear_aes_keyslot_iv(keyslot); unsigned int num_blocks = (data_size + 0xF) >> 4; /* Handle aligned blocks. */ if (num_blocks > 1) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 2; + se->BLOCK_COUNT_REG = num_blocks - 2; trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); - SECURITY_ENGINE->CRYPTO_REG |= 0x80; + se->CRYPTO_REG |= 0x80; } /* Create final block. */ @@ -508,12 +542,12 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con } /* Perform last operation. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); /* Copy output CMAC. */ for (unsigned int i = 0; i < (cmac_size >> 2); i++) { - ((uint32_t *)cmac)[i] = read32le(SECURITY_ENGINE->HASH_RESULT_REG, i << 2); + ((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2); } } @@ -525,42 +559,48 @@ void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, } void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x144; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); + se->CRYPTO_REG = (keyslot << 24) | 0x144; set_aes_keyslot_iv(keyslot, iv, 0x10); - SECURITY_ENGINE->BLOCK_COUNT_REG = (src_size >> 4) - 1; + se->BLOCK_COUNT_REG = (src_size >> 4) - 1; trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); } /* SHA256 Implementation. */ void se_calculate_sha256(void *dst, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + /* Setup config for SHA256, size = BITS(src_size) */ - SECURITY_ENGINE->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); - SECURITY_ENGINE->SHA_CONFIG_REG = 1; - SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); - SECURITY_ENGINE->_0x208 = 0; - SECURITY_ENGINE->_0x20C = 0; - SECURITY_ENGINE->_0x210 = 0; - SECURITY_ENGINE->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); - SECURITY_ENGINE->_0x218 = 0; - SECURITY_ENGINE->_0x21C = 0; - SECURITY_ENGINE->_0x220 = 0; + se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); + se->SHA_CONFIG_REG = 1; + se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); + se->_0x208 = 0; + se->_0x20C = 0; + se->_0x210 = 0; + se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); + se->_0x218 = 0; + se->_0x21C = 0; + se->_0x220 = 0; /* Trigger the operation. */ trigger_se_blocking_op(OP_START, NULL, 0, src, src_size); /* Copy output hash. */ for (unsigned int i = 0; i < (0x20 >> 2); i++) { - ((uint32_t *)dst)[i] = read32be(SECURITY_ENGINE->HASH_RESULT_REG, i << 2); + ((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2); } } /* RNG API */ void se_initialize_rng(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -569,32 +609,33 @@ void se_initialize_rng(unsigned int keyslot) { /* This will be discarded, when done. */ uint8_t ALIGN(16) output_buf[0x10]; - SECURITY_ENGINE->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ - SECURITY_ENGINE->RNG_RESEED_INTERVAL_REG = 70001; - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 5; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ + se->RNG_RESEED_INTERVAL_REG = 70001; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 5; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0); } void se_generate_random(unsigned int keyslot, void *dst, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } uint32_t num_blocks = size >> 4; size_t aligned_size = num_blocks << 4; - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 4; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 4; if (num_blocks >= 1) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1; + se->BLOCK_COUNT_REG = num_blocks - 1; trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0); } if (size > aligned_size) { se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0); } - } diff --git a/fusee/fusee-primary/src/se.h b/fusee/fusee-primary/src/se.h index a1ef7fa84..311567261 100644 --- a/fusee/fusee-primary/src/se.h +++ b/fusee/fusee-primary/src/se.h @@ -1,7 +1,8 @@ #ifndef FUSEE_SE_H #define FUSEE_SE_H -#include <assert.h> +#define SE_BASE 0x70012000 +#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n) #define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2 #define KEYSLOT_SWITCH_SRKGENKEY 0x8 @@ -98,10 +99,10 @@ typedef struct security_engine { uint32_t _0x21C; uint32_t _0x220; uint32_t _0x224; - uint8_t _0x228[0x5C]; + uint8_t _0x228[0x58]; uint32_t AES_KEY_READ_DISABLE_REG; uint32_t AES_KEYSLOT_FLAGS[0x10]; - uint8_t _0x2C8[0x38]; + uint8_t _0x2C4[0x3C]; uint32_t _0x300; uint32_t CRYPTO_REG; uint32_t CRYPTO_CTR_REG[4]; @@ -131,15 +132,13 @@ typedef struct security_engine { uint32_t FLAGS_REG; uint32_t ERR_STATUS_REG; uint32_t _0x808; - uint32_t _0x80C; + uint32_t SPARE_0; uint32_t _0x810; uint32_t _0x814; uint32_t _0x818; uint32_t _0x81C; uint8_t _0x820[0x17E0]; -} security_engine_t; - -static_assert(sizeof(security_engine_t) == 0x2000, "Mis-defined Security Engine Registers!"); +} tegra_se_t; typedef struct { uint32_t address; @@ -151,15 +150,10 @@ typedef struct { se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ } se_ll_t; - -/* WIP, API subject to change. */ - -static inline volatile security_engine_t *get_security_engine(void) { - return (volatile security_engine_t *)0x70012000; +static inline volatile tegra_se_t *se_get_regs(void) { + return (volatile tegra_se_t *)SE_BASE; } -#define SECURITY_ENGINE (get_security_engine()) - /* This function MUST be registered to fire on the appropriate interrupt. */ void se_check_error_status_reg(void); diff --git a/fusee/fusee-primary/src/sysctr0.h b/fusee/fusee-primary/src/sysctr0.h new file mode 100644 index 000000000..60c645bdd --- /dev/null +++ b/fusee/fusee-primary/src/sysctr0.h @@ -0,0 +1,11 @@ +#ifndef FUSEE_SYSCTR0_H +#define FUSEE_SYSCTR0_H + +#include <stdint.h> + +#define SYSCTR0_BASE 0x7000F000 +#define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) + +#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x00) + +#endif diff --git a/fusee/fusee-primary/src/sysreg.h b/fusee/fusee-primary/src/sysreg.h new file mode 100644 index 000000000..d69cf8897 --- /dev/null +++ b/fusee/fusee-primary/src/sysreg.h @@ -0,0 +1,32 @@ +#ifndef FUSEE_SYSREG_H +#define FUSEE_SYSREG_H + +#include <stdint.h> + +#define SYSREG_BASE 0x6000C000 +#define SB_BASE (SYSREG_BASE + 0x200) +#define EXCP_VEC_BASE 0x6000F000 + +#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n) +#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n) +#define MAKE_EXCP_VEC_REG(n) MAKE_REG32(EXCP_VEC_BASE + n) + +#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004) +#define AHB_ARBITRATION_XBAR_CTRL_0 MAKE_SYSREG(0x0E0) +#define AHB_AHB_SPARE_REG_0 MAKE_SYSREG(0x110) + +#define SB_CSR_0 MAKE_SB_REG(0x00) +#define SB_PIROM_START_0 MAKE_SB_REG(0x04) +#define SB_PFCFG_0 MAKE_SB_REG(0x08) +#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C) +#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10) +#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14) +#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18) +#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C) +#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20) +#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24) +#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28) +#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30) +#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34) + +#endif diff --git a/fusee/fusee-primary/src/timers.h b/fusee/fusee-primary/src/timers.h index 519c0292f..8c9569c19 100644 --- a/fusee/fusee-primary/src/timers.h +++ b/fusee/fusee-primary/src/timers.h @@ -8,6 +8,7 @@ #define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10) #define RTC_BASE 0x7000E000 +#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) #define RTC_SECONDS MAKE_REG32(RTC_BASE + 0x08) #define RTC_SHADOW_SECONDS MAKE_REG32(RTC_BASE + 0x0C) #define RTC_MILLI_SECONDS MAKE_REG32(RTC_BASE + 0x10) diff --git a/fusee/fusee-primary/src/uart.c b/fusee/fusee-primary/src/uart.c new file mode 100644 index 000000000..3d9865983 --- /dev/null +++ b/fusee/fusee-primary/src/uart.c @@ -0,0 +1,55 @@ +#include "uart.h" +#include "timers.h" + +void uart_init(UartDevice dev, uint32_t baud) { + volatile tegra_uart_t *uart = uart_get_regs(dev); + + /* Set baud rate. */ + uint32_t rate = (8 * baud + 408000000) / (16 * baud); + uart->UART_LCR = UART_LCR_DLAB; /* Enable DLAB. */ + uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */ + uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */ + uart->UART_LCR = 0; /* Diable DLAB. */ + + /* Setup UART in fifo mode. */ + uart->UART_IER_DLAB = 0; + uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */ + (void)uart->UART_LSR; + udelay(3 * ((baud + 999999) / baud)); + uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */ + uart->UART_MCR = 0; + uart->UART_MSR = 0; + uart->UART_IRDA_CSR = 0; + uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */ + uart->UART_MIE = 0; + uart->UART_ASR = 0; +} + +/* This function blocks until the UART device (dev) is in the desired state (status). Make sure the desired state can be reached! */ +void uart_wait_idle(UartDevice dev, UartVendorStatus status) { + while (!(uart_get_regs(dev)->UART_VENDOR_STATUS & status)) { + /* Wait */ + } +} + +void uart_send(UartDevice dev, const void *buf, size_t len) { + volatile tegra_uart_t *uart = uart_get_regs(dev); + + for (size_t i = 0; i < len; i++) { + while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL) { + /* Wait until the TX FIFO isn't full */ + } + uart->UART_THR_DLAB = *((const uint8_t *)buf + i); + } +} + +void uart_recv(UartDevice dev, void *buf, size_t len) { + volatile tegra_uart_t *uart = uart_get_regs(dev); + + for (size_t i = 0; i < len; i++) { + while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY) { + /* Wait until the RX FIFO isn't empty */ + } + *((uint8_t *)buf + i) = uart->UART_THR_DLAB; + } +} diff --git a/fusee/fusee-primary/src/uart.h b/fusee/fusee-primary/src/uart.h new file mode 100644 index 000000000..3ba2ccad2 --- /dev/null +++ b/fusee/fusee-primary/src/uart.h @@ -0,0 +1,153 @@ +#ifndef FUSEE_UART_H +#define FUSEE_UART_H + +#include <string.h> + +#define UART_BASE 0x70006000 + +#define BAUD_115200 115200 + +/* UART devices */ +typedef enum { + UART_A = 0, + UART_B = 1, + UART_C = 2, + UART_D = 3, + UART_E = 4, +} UartDevice; + +/* 36.3.12 UART_VENDOR_STATUS_0_0 */ +typedef enum { + UART_VENDOR_STATE_TX_IDLE = 1 << 0, + UART_VENDOR_STATE_RX_IDLE = 1 << 1, + + /* This bit is set to 1 when a read is issued to an empty FIFO and gets cleared on register read (sticky bit until read) + 0 = NO_UNDERRUN + 1 = UNDERRUN + */ + UART_VENDOR_STATE_RX_UNDERRUN = 1 << 2, + + /* This bit is set to 1 when write data is issued to the TX FIFO when it is already full and gets cleared on register read (sticky bit until read) + 0 = NO_OVERRUN + 1 = OVERRUN + */ + UART_VENDOR_STATE_TX_OVERRUN = 1 << 3, + + UART_VENDOR_STATE_RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ + UART_VENDOR_STATE_TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ +} UartVendorStatus; + +/* 36.3.6 UART_LSR_0 */ +typedef enum { + UART_LSR_RDR = 1 << 0, /* Receiver Data Ready */ + UART_LSR_OVRF = 1 << 1, /* Receiver Overrun Error */ + UART_LSR_PERR = 1 << 2, /* Parity Error */ + UART_LSR_FERR = 1 << 3, /* Framing Error */ + UART_LSR_BRK = 1 << 4, /* BREAK condition detected on line */ + UART_LSR_THRE = 1 << 5, /* Transmit Holding Register is Empty -- OK to write data */ + UART_LSR_TMTY = 1 << 6, /* Transmit Shift Register empty status */ + UART_LSR_FIFOE = 1 << 7, /* Receive FIFO Error */ + UART_LSR_TX_FIFO_FULL = 1 << 8, /* Transmitter FIFO full status */ + UART_LSR_RX_FIFO_EMPTY = 1 << 9, /* Receiver FIFO empty status */ +} UartLineStatus; + +/* 36.3.4 UART_LCR_0 */ +typedef enum { + UART_LCR_WD_LENGTH_5 = 0, /* word length 5 */ + UART_LCR_WD_LENGTH_6 = 1, /* word length 6 */ + UART_LCR_WD_LENGTH_7 = 2, /* word length 7 */ + UART_LCR_WD_LENGTH_8 = 3, /* word length 8 */ + + /* STOP: + 0 = Transmit 1 stop bit + 1 = Transmit 2 stop bits (receiver always checks for 1 stop bit) + */ + UART_LCR_STOP = 1 << 2, + UART_LCR_PAR = 1 << 3, /* Parity enabled */ + UART_LCR_EVEN = 1 << 4, /* Even parity format. There will always be an even number of 1s in the binary representation (PAR = 1) */ + UART_LCR_SET_P = 1 << 5, /* Set (force) parity to value in LCR[4] */ + UART_LCR_SET_B = 1 << 6, /* Set BREAK condition -- Transmitter sends all zeroes to indicate BREAK */ + UART_LCR_DLAB = 1 << 7, /* Divisor Latch Access Bit (set to allow programming of the DLH, DLM Divisors) */ +} UartLineControl; + +/* 36.3.3 UART_IIR_FCR_0 */ +typedef enum { + UART_FCR_FCR_EN_FIFO = 1 << 0, /* Enable the transmit and receive FIFOs. This bit should be enabled */ + UART_FCR_RX_CLR = 1 << 1, /* Clears the contents of the receive FIFO and resets its counter logic to 0 (the receive shift register is not cleared or altered). This bit returns to 0 after clearing the FIFOs */ + UART_FCR_TX_CLR = 1 << 2, /* Clears the contents of the transmit FIFO and resets its counter logic to 0 (the transmit shift register is not cleared or altered). This bit returns to 0 after clearing the FIFOs */ + + /* DMA: + 0 = DMA_MODE_0 + 1 = DMA_MODE_1 + */ + UART_FCR_DMA = 1 << 3, + + /* TX_TRIG + 0 = FIFO_COUNT_GREATER_16 + 1 = FIFO_COUNT_GREATER_8 + 2 = FIFO_COUNT_GREATER_4 + 3 = FIFO_COUNT_GREATER_1 + */ + UART_FCR_TX_TRIG = 3 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_16 = 0 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_8 = 1 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_4 = 2 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_1 = 3 << 4, + + /* RX_TRIG + 0 = FIFO_COUNT_GREATER_1 + 1 = FIFO_COUNT_GREATER_4 + 2 = FIFO_COUNT_GREATER_8 + 3 = FIFO_COUNT_GREATER_16 + */ + UART_FCR_RX_TRIG = 3 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_1 = 0 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_4 = 1 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_8 = 2 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_16 = 3 << 6, +} UartFifoControl; + +/* 36.3.3 UART_IIR_FCR_0 */ +typedef enum { + UART_IIR_IS_STA = 1 << 0, /* Interrupt Pending if ZERO */ + UART_IIR_IS_PRI0 = 1 << 1, /* Encoded Interrupt ID Refer to IIR[3:0] table [36.3.3] */ + UART_IIR_IS_PRI1 = 1 << 2, /* Encoded Interrupt ID Refer to IIR[3:0] table */ + UART_IIR_IS_PRI2 = 1 << 3, /* Encoded Interrupt ID Refer to IIR[3:0] table */ + + /* FIFO Mode Status + 0 = 16450 mode (no FIFO) + 1 = 16550 mode (FIFO) + */ + UART_IIR_EN_FIFO = 3 << 6, + UART_IIR_MODE_16450 = 0 << 6, + UART_IIR_MODE_16550 = 1 << 6, +} UartInterruptIdentification; + +typedef struct { + uint32_t UART_THR_DLAB; + uint32_t UART_IER_DLAB; + uint32_t UART_IIR_FCR; + uint32_t UART_LCR; + uint32_t UART_MCR; + uint32_t UART_LSR; + uint32_t UART_MSR; + uint32_t UART_SPR; + uint32_t UART_IRDA_CSR; + uint32_t UART_RX_FIFO_CFG; + uint32_t UART_MIE; + uint32_t UART_VENDOR_STATUS; + uint8_t _0x30[0x0C]; + uint32_t UART_ASR; +} tegra_uart_t; + +void uart_init(UartDevice dev, uint32_t baud); +void uart_wait_idle(UartDevice dev, UartVendorStatus status); +void uart_send(UartDevice dev, const void *buf, size_t len); +void uart_recv(UartDevice dev, void *buf, size_t len); + +static inline volatile tegra_uart_t *uart_get_regs(UartDevice dev) { + static const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400}; + return (volatile tegra_uart_t *)(UART_BASE + offsets[dev]); +} + +#endif diff --git a/fusee/fusee-primary/src/utils.c b/fusee/fusee-primary/src/utils.c index 823e4ea00..6929ec0c0 100644 --- a/fusee/fusee-primary/src/utils.c +++ b/fusee/fusee-primary/src/utils.c @@ -7,9 +7,9 @@ #include "timers.h" #include "panic.h" #include "car.h" +#include "btn.h" #include "lib/printk.h" -#include "hwinit/btn.h" #include <inttypes.h> diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 477dd52d0..bad10f017 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -21,7 +21,7 @@ include $(DEVKITARM)/base_rules #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := src src/sdmmc src/hwinit src/lib src/lib/fatfs src/display +SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display DATA := data INCLUDES := include diff --git a/fusee/fusee-secondary/src/apb_misc.h b/fusee/fusee-secondary/src/apb_misc.h index 114b7496a..4552a61b5 100644 --- a/fusee/fusee-secondary/src/apb_misc.h +++ b/fusee/fusee-secondary/src/apb_misc.h @@ -1,6 +1,17 @@ #ifndef FUSEE_APB_MISC_H #define FUSEE_APB_MISC_H +#include <stdint.h> + +#define APB_MISC_BASE 0x70000000 +#define APB_PADCTL_BASE 0x70000810 +#define MAKE_APB_MISC_REG(n) MAKE_REG32(APB_MISC_BASE + n) +#define MAKE_APB_PADCTL_REG(n) MAKE_REG32(APB_PADCTL_BASE + n) + +#define APB_MISC_PP_PINMUX_GLOBAL_0 MAKE_APB_MISC_REG(0x40) +#define APB_MISC_GP_WIFI_EN_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB64) +#define APB_MISC_GP_WIFI_RST_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB68) + #define SDMMC1_PAD_CAL_DRVUP_SHIFT (20) #define SDMMC1_PAD_CAL_DRVDN_SHIFT (12) #define SDMMC1_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVUP_SHIFT) @@ -48,7 +59,7 @@ typedef struct { static inline volatile tegra_padctl_t *padctl_get_regs(void) { - return (volatile tegra_padctl_t *)0x70000810; + return (volatile tegra_padctl_t *)APB_PADCTL_BASE; } #endif diff --git a/fusee/fusee-secondary/src/btn.c b/fusee/fusee-secondary/src/btn.c new file mode 100644 index 000000000..bffc8e79d --- /dev/null +++ b/fusee/fusee-secondary/src/btn.c @@ -0,0 +1,64 @@ +#include <stdint.h> + +#include "btn.h" +#include "i2c.h" +#include "gpio.h" +#include "timers.h" + +uint32_t btn_read() +{ + uint32_t res = 0; + + if (!gpio_read(GPIO_BUTTON_VOL_DOWN)) + res |= BTN_VOL_DOWN; + + if (!gpio_read(GPIO_BUTTON_VOL_UP)) + res |= BTN_VOL_UP; + + uint32_t val = 0; + if (i2c_query(4, 0x3C, 0x15, &val, 1)) + { + if (val & 0x4) + res |= BTN_POWER; + } + + return res; +} + +uint32_t btn_wait() +{ + uint32_t res = 0, btn = btn_read(); + int pwr = 0; + + if (btn & BTN_POWER) + { + pwr = 1; + btn &= ~BTN_POWER; + } + + do + { + res = btn_read(); + + if (!(res & BTN_POWER) && pwr) + pwr = 0; + else if (pwr) + res &= ~BTN_POWER; + } while (btn == res); + + return res; +} + +uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask) +{ + uint32_t timeout = get_time_ms() + time_ms; + uint32_t res = btn_read() & mask; + + do + { + if (!(res & mask)) + res = btn_read() & mask; + } while (get_time_ms() < timeout); + + return res; +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/btn.h b/fusee/fusee-secondary/src/btn.h new file mode 100644 index 000000000..08f6f6921 --- /dev/null +++ b/fusee/fusee-secondary/src/btn.h @@ -0,0 +1,12 @@ +#ifndef FUSEE_BTN_H_ +#define FUSEE_BTN_H_ + +#define BTN_POWER 0x1 +#define BTN_VOL_DOWN 0x2 +#define BTN_VOL_UP 0x4 + +uint32_t btn_read(); +uint32_t btn_wait(); +uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask); + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/car.c b/fusee/fusee-secondary/src/car.c new file mode 100644 index 000000000..bc79be9a6 --- /dev/null +++ b/fusee/fusee-secondary/src/car.c @@ -0,0 +1,114 @@ +#include "car.h" +#include "utils.h" + +static inline uint32_t get_clk_source_reg(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0x178; + case CARDEVICE_UARTB: return 0x17C; + case CARDEVICE_UARTC: return 0x1A0; + case CARDEVICE_I2C1: return 0x124; + case CARDEVICE_I2C5: return 0x128; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0x42C; + case CARDEVICE_HOST1X: return 0x180; + case CARDEVICE_TSEC: return 0x1F4; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 0x410; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_ACTMON: return 0x3E8; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static inline uint32_t get_clk_source_val(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_UARTC: return 0; + case CARDEVICE_I2C1: return 6; + case CARDEVICE_I2C5: return 6; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0; + case CARDEVICE_HOST1X: return 4; + case CARDEVICE_TSEC: return 0; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 0; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_ACTMON: return 6; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static inline uint32_t get_clk_source_div(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_UARTC: return 0; + case CARDEVICE_I2C1: return 0; + case CARDEVICE_I2C5: return 0; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0; + case CARDEVICE_HOST1X: return 3; + case CARDEVICE_TSEC: return 2; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 2; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_ACTMON: return 0; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; +static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; + +void clk_enable(CarDevice dev) { + uint32_t clk_source_reg; + if ((clk_source_reg = get_clk_source_reg(dev))) { + MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev); + } + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void clk_disable(CarDevice dev) { + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void rst_enable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void rst_disable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void clkrst_enable(CarDevice dev) { + clk_enable(dev); + rst_disable(dev); +} + +void clkrst_disable(CarDevice dev) { + rst_enable(dev); + clk_disable(dev); +} + +void clkrst_reboot(CarDevice dev) { + clkrst_disable(dev); + clkrst_enable(dev); +} + +void clkrst_enable_fuse_regs(bool enable) { + volatile tegra_car_t *car = car_get_regs(); + car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28)); +} diff --git a/fusee/fusee-secondary/src/car.h b/fusee/fusee-secondary/src/car.h index 8cc0fb139..6ec42e744 100644 --- a/fusee/fusee-secondary/src/car.h +++ b/fusee/fusee-secondary/src/car.h @@ -1,121 +1,202 @@ #ifndef FUSEE_CAR_H #define FUSEE_CAR_H -#define CLK_SOURCE_SDMMC1 20 -#define CLK_SOURCE_SDMMC2 21 -#define CLK_SOURCE_SDMMC3 47 -#define CLK_SOURCE_SDMMC4 25 -#define CLK_SOURCE_SDMMC_LEGACY 0 +#include <stdint.h> +#include <stdbool.h> + +#define CAR_BASE 0x60006000 +#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) #define CLK_L_SDMMC1 (1 << 14) #define CLK_L_SDMMC2 (1 << 9) #define CLK_U_SDMMC3 (1 << 5) #define CLK_L_SDMMC4 (1 << 15) -#define TEGRA_CLK_PLLS 6 /* Number of normal PLLs */ -#define TEGRA_CLK_SIMPLE_PLLS 3 /* Number of simple PLLs */ -#define TEGRA_CLK_SOURCES 64 /* Number of ppl clock sources L/H/U */ -#define TEGRA_CLK_SOURCES_VW 32 /* Number of ppl clock sources V/W */ -#define TEGRA_CLK_SOURCES_X 32 /* Number of ppl clock sources X */ -#define TEGRA_CLK_SOURCES_Y 18 /* Number of ppl clock sources Y */ - #define CLK_SOURCE_MASK (0b111 << 29) #define CLK_SOURCE_FIRST (0b000 << 29) #define CLK_DIVIDER_MASK (0xff << 0) #define CLK_DIVIDER_UNITY (0x00 << 0) -#define CAR_CONTROL_SDMMC1 (1 << 14) -#define CAR_CONTROL_SDMMC4 (1 << 15) -#define CAR_CONTROL_SDMMC_LEGACY (1 << 1) +#define NUM_CAR_BANKS 7 -/* PLL registers - there are several PLLs in the clock controller */ -typedef struct { - uint32_t pll_base; /* the control register */ - - /* pll_out[0] is output A control, pll_out[1] is output B control */ - uint32_t pll_out[2]; - uint32_t pll_misc; /* other misc things */ -} clk_pll_t; - -/* PLL registers - there are several PLLs in the clock controller */ -typedef struct { - uint32_t pll_base; /* the control register */ - uint32_t pll_misc; /* other misc things */ -} clk_pll_simple_t; - -typedef struct { - uint32_t pllm_base; /* the control register */ - uint32_t pllm_out; /* output control */ - uint32_t pllm_misc1; /* misc1 */ - uint32_t pllm_misc2; /* misc2 */ -} clk_pllm_t; +/* Clock and reset devices. */ +typedef enum { + CARDEVICE_UARTA = ((0 << 5) | 0x6), + CARDEVICE_UARTB = ((0 << 5) | 0x7), + CARDEVICE_UARTC = ((1 << 5) | 0x17), + CARDEVICE_I2C1 = ((0 << 5) | 0xC), + CARDEVICE_I2C5 = ((1 << 5) | 0xF), + CARDEVICE_UNK = ((3 << 5) | 0x1E), + CARDEVICE_SE = ((3 << 5) | 0x1F), + CARDEVICE_HOST1X = ((0 << 5) | 0x1C), + CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E), + CARDEVICE_SOR0 = ((5 << 5) | 0x16), + CARDEVICE_SOR1 = ((5 << 5) | 0x17), + CARDEVICE_KFUSE = ((1 << 5) | 0x8), + CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B), + CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), + CARDEVICE_ACTMON = ((3 << 5) | 0x17), + CARDEVICE_BPMP = ((0 << 5) | 0x1) +} CarDevice; /* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */ typedef struct { - uint32_t rst_src; /* _RST_SOURCE_0,0x00 */ + uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */ + /* _RST_DEVICES_L/H/U_0 0x4-0xc */ uint32_t rst_dev_l; uint32_t rst_dev_h; uint32_t rst_dev_u; + /* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */ uint32_t clk_out_enb_l; uint32_t clk_out_enb_h; uint32_t clk_out_enb_u; - uint32_t reserved0; /* reserved_0, 0x1C */ - uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */ - uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0,0x24 */ - uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */ - uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0,0x2C */ - uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */ - uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */ - uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0,0x38 */ - uint32_t reserved1; /* reserved_1, 0x3C */ - uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0,0x40 */ - uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */ - uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */ - uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4C */ - uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */ - uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */ - uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */ - uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0,0x5C */ - uint32_t reserved2[8]; /* reserved_2[8], 0x60-7C */ + uint32_t _0x1C; + uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */ + uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */ + uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */ + uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */ + uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */ + uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */ + uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */ + uint32_t _0x3C; + uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */ + uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */ + uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */ + uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */ + uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */ + uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */ + uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */ + uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */ + uint32_t _0x60[2]; + uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */ + uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */ + uint32_t _0x70[4]; - clk_pll_t pll[TEGRA_CLK_PLLS]; /* PLLs from 0x80 to 0xdc */ + /* PLLC 0x80-0x8c */ + uint32_t pllc_base; + uint32_t pllc_out; + uint32_t pllc_misc0; + uint32_t pllc_misc1; + + /* PLLM 0x90-0x9c */ + uint32_t pllm_base; + uint32_t pllm_out; + uint32_t pllm_misc1; + uint32_t pllm_misc2; + + /* PLLP 0xa0-0xac */ + uint32_t pllp_base; + uint32_t pllp_outa; + uint32_t pllp_outb; + uint32_t pllp_misc; + + /* PLLA 0xb0-0xbc */ + uint32_t plla_base; + uint32_t plla_out; + uint32_t plla_misc0; + uint32_t plla_misc1; + + /* PLLU 0xc0-0xcc */ + uint32_t pllu_base; + uint32_t pllu_out; + uint32_t pllu_misc1; + uint32_t pllu_misc2; + + /* PLLD 0xd0-0xdc */ + uint32_t plld_base; + uint32_t plld_out; + uint32_t plld_misc1; + uint32_t plld_misc2; - /* PLLs from 0xe0 to 0xf4 */ - clk_pll_simple_t pll_simple[TEGRA_CLK_SIMPLE_PLLS]; + /* PLLX 0xe0-0xe4 */ + uint32_t pllx_base; + uint32_t pllx_misc; + + /* PLLE 0xe8-0xf4 */ + uint32_t plle_base; + uint32_t plle_misc; + uint32_t plle_ss_cntl1; + uint32_t plle_ss_cntl2; + + uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */ + uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */ - uint32_t reserved10; /* _reserved_10, 0xF8 */ - uint32_t reserved11; /* _reserved_11, 0xFC */ + uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */ + uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */ + uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */ + uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */ + uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */ + uint32_t _0x114; + uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */ + uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */ + uint32_t _0x120; + uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */ + uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */ + uint32_t _0x12c[2]; + uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */ + uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */ + uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */ + uint32_t _0x140; + uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */ + uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */ + uint32_t _0x14c; + uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */ + uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */ + uint32_t _0x158[3]; + uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */ + uint32_t _0x168[4]; + uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */ + uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */ + uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */ + uint32_t _0x184[5]; + uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */ + uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */ + uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */ + uint32_t _0x1a4; + uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */ + uint32_t _0x1ac[2]; + uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */ + uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */ + uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */ + uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */ + uint32_t _0x1c4[2]; + uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */ + uint32_t _0x1d0; + uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */ + uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */ + uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */ + uint32_t _0x1e0[5]; + uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */ + uint32_t _0x1f8; + + uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */ + uint32_t _0x200[32]; - uint32_t clk_src[TEGRA_CLK_SOURCES]; /*_I2S1_0... 0x100-1fc */ + uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ + uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ + uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ - uint32_t reserved20[32]; /* _reserved_20, 0x200-27c */ + uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */ + uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ + uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ - uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ - uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ - uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ + uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */ + uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */ + uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */ - uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */ - uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ - uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ + uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */ + uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */ + uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */ - uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */ - uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */ - uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */ + uint32_t _0x2b0[17]; + uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */ + uint32_t _0x2f8[2]; - uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */ - uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */ - uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */ - - uint32_t reserved21[17]; /* _reserved_21, 0x2b0-2f0 */ - - uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */ - - uint32_t reserved22[2]; /* _reserved_22, 0x2f8-2fc */ - - /* _RST_DEV_L/H/U_SET_0 0x300 ~ 0x314 */ + /* _RST_DEV_L/H/U_SET_0 0x300-0x314 */ uint32_t rst_dev_l_set; uint32_t rst_dev_l_clr; uint32_t rst_dev_h_set; @@ -123,9 +204,9 @@ typedef struct { uint32_t rst_dev_u_set; uint32_t rst_dev_u_clr; - uint32_t reserved30[2]; /* _reserved_30, 0x318, 0x31c */ + uint32_t _0x318[2]; - /* _CLK_ENB_L/H/U_CLR_0 0x320 ~ 0x334 */ + /* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */ uint32_t clk_enb_l_set; uint32_t clk_enb_l_clr; uint32_t clk_enb_h_set; @@ -133,136 +214,275 @@ typedef struct { uint32_t clk_enb_u_set; uint32_t clk_enb_u_clr; - uint32_t reserved31[2]; /* _reserved_31, 0x338, 0x33c */ - - uint32_t cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */ - uint32_t cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */ + uint32_t _0x338; + uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */ + uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */ + uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */ /* Additional (T30) registers */ - uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */ - uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ + uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */ + uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ - uint32_t reserved32[2]; /* _reserved_32, 0x350,0x354 */ + uint32_t _0x350[2]; + uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ + uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ + uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ + uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ + uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ + uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ + uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ + uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ + uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ + uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ + uint32_t _0x38c[5]; + uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */ + uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */ + uint32_t _0x3a8[2]; + + uint32_t _0x3b0; + uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */ + uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */ + uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */ + uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */ + uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */ + uint32_t _0x3c8[2]; + uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */ + uint32_t _0x3d4[4]; + uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */ + uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */ + uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */ + uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */ + uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */ + uint32_t _0x3f8; + uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */ + uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */ + uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */ + uint32_t _0x408[2]; + uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */ + uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */ + uint32_t _0x418[2]; + uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */ + uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */ + uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */ + uint32_t _0x42c; - uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ - uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ - - uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ - uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ - uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ - uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ - uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ - uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ - uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ - uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ - uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ - uint32_t reserved33[9]; /* _reserved_33, 0x38c-3ac */ - uint32_t clk_src_v; /* 0x3B0-0x42C */ - uint32_t clk_src_w; /* 0x3B0-0x42C */ - - /* _RST_DEV_V/W_SET_0 0x430 ~ 0x43c */ + /* _RST_DEV_V/W_SET_0 0x430-0x43c */ uint32_t rst_dev_v_set; uint32_t rst_dev_v_clr; uint32_t rst_dev_w_set; uint32_t rst_dev_w_clr; - /* _CLK_ENB_V/W_CLR_0 0x440 ~ 0x44c */ - uint32_t rst_clk_v_set; - uint32_t rst_clk_v_clr; - uint32_t rst_clk_w_set; - uint32_t rst_clk_w_clr; + /* _CLK_ENB_V/W_CLR_0 0x440-0x44c */ + uint32_t clk_enb_v_set; + uint32_t clk_enb_v_clr; + uint32_t clk_enb_w_set; + uint32_t clk_enb_w_clr; /* Additional (T114+) registers */ - uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */ - uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */ - uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */ - uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45C */ - uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */ - uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */ - uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */ - uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46C */ - uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */ - uint32_t reserved40[1]; /* _reserved_40, 0x474 */ - uint32_t intstatus; /* __INTSTATUS_0, 0x478 */ - uint32_t intmask; /* __INTMASK_0, 0x47C */ - uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */ - uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */ - uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */ + uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */ + uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */ + uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */ + uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */ + uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */ + uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */ + uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */ + uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */ + uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */ + uint32_t _0x474; + uint32_t intstatus; /* _INTSTATUS_0, 0x478 */ + uint32_t intmask; /* _INTMASK_0, 0x47c */ + uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */ + uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */ + uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */ - uint32_t plle_aux; /* _PLLE_AUX_0, 0x48C */ - uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */ - uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */ - uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */ + uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */ + uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */ + uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */ + uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */ - uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49C */ - uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4A0 */ - uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4A4 */ - uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4A8 */ - uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4AC */ - uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4B0 */ - uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4B4 */ + uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */ + uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */ + uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */ + uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */ + uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */ + uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */ + uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */ - uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4B8 */ - uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4BC */ - uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4C0 */ - uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4C4 */ - uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4C8 */ - uint32_t crs_reserved_50[7]; /* _reserved_50, 0x4CC-0x4E4 */ - uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4E8 */ - uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4EC */ - uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4F0 */ - uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4F4 */ - uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4F8 */ - uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4FC */ + uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */ + uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */ + uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */ + uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */ + uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */ + uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */ + uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */ + uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */ + uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */ + uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */ + uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */ + uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */ + uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */ + uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */ + uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */ + uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */ + uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */ + uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */ uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */ uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */ uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */ - uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50C */ + uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */ uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */ uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */ uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */ - uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51C */ + uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */ uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */ uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */ uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */ - uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52C */ + uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */ uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */ uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */ - uint32_t reserved51[1]; /* _reserved_51, 0x538 */ - uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53C */ + uint32_t _0x538; + uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */ uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */ uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */ uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */ - uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54C */ + uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */ uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */ - uint32_t reserved52[1]; /* _reserved_52, 0x554 */ + uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */ uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */ - uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55C */ - uint32_t _rsv32[4]; /* 0x560-0x56c */ - uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG 0x570 */ - uint32_t _rsv32_1[7]; /* 0x574-58c */ - clk_pll_simple_t plldp; /* _PLLDP_BASE, 0x590 _PLLDP_MISC */ - uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ - - /* Tegra124+ - skip to 0x600 here for new CLK_SOURCE_ regs */ - uint32_t _rsrv32_2[25]; /* _0x59C - 0x5FC */ - uint32_t clk_src_x[TEGRA_CLK_SOURCES_X]; /* XUSB, etc, 0x600-0x67C */ - - /* Tegra210 - skip to 0x694 here for new CLK_SOURCE_ regs */ - uint32_t reserved61[5]; /* _reserved_61, 0x680 - 0x690 */ + uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */ + uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */ + uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */ - /* - * NOTE: PLLA1 regs are in the middle of this Y region. Break this in - * two later if PLLA1 is needed, but for now this is cleaner. - */ - uint32_t clk_src_y[TEGRA_CLK_SOURCES_Y]; /* SPARE1, etc, 0x694-0x6D8 */ + uint32_t _0x568[2]; + uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */ + uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */ + uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */ + uint32_t _0x57c[5]; + + uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/ + uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */ + uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ + uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */ + uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */ + uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */ + uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */ + uint32_t _0x5ac[6]; + uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */ + uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */ + uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */ + uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */ + uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */ + uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */ + uint32_t _0x5dc[2]; + uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */ + uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */ + uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */ + uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */ + uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */ + uint32_t _0x5f8[2]; + + uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */ + uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */ + uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */ + uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */ + uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */ + uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */ + uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */ + uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */ + uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */ + uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */ + uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */ + uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */ + uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */ + uint32_t _0x634[3]; + uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */ + uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */ + uint32_t _0x648; + uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */ + uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */ + uint32_t _0x654; + uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */ + uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */ + uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */ + uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */ + uint32_t _0x668; + uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */ + uint32_t _0x670[2]; + uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */ + + uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */ + uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */ + uint32_t _0x684[2]; + uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */ + uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */ + + uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */ + uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */ + uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */ + uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */ + + uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */ + uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */ + uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */ + uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */ + uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */ + uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */ + + uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */ + uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */ + uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */ + uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */ + uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */ + uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */ + uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */ + uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */ + + uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */ + uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */ + uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */ + + uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */ + uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */ + uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */ + uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */ + uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */ + uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */ + uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */ + uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */ + uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */ + uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ + + uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ + uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ + uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ + uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ + uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */ + uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */ + uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */ + uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */ + uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */ + uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */ + uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */ + uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */ + uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */ } tegra_car_t; -static inline volatile tegra_car_t *car_get_regs(void) -{ - return (volatile tegra_car_t *)0x60006000; +static inline volatile tegra_car_t *car_get_regs(void) { + return (volatile tegra_car_t *)CAR_BASE; } +void clk_enable(CarDevice dev); +void clk_disable(CarDevice dev); +void rst_enable(CarDevice dev); +void rst_disable(CarDevice dev); + +void clkrst_enable(CarDevice dev); +void clkrst_disable(CarDevice dev); +void clkrst_reboot(CarDevice dev); + +void clkrst_enable_fuse_regs(bool enable); + #endif diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c new file mode 100644 index 000000000..bceaf7d73 --- /dev/null +++ b/fusee/fusee-secondary/src/cluster.c @@ -0,0 +1,135 @@ +#include <stdint.h> + +#include "cluster.h" +#include "flow.h" +#include "sysreg.h" +#include "i2c.h" +#include "car.h" +#include "timers.h" +#include "pmc.h" +#include "max77620.h" + +void _cluster_enable_power() +{ + uint8_t val = 0; + i2c_query(4, 0x3C, MAX77620_REG_AME_GPIO, &val, 1); + + val &= 0xDF; + i2c_send(4, 0x3C, MAX77620_REG_AME_GPIO, &val, 1); + val = 0x09; + i2c_send(4, 0x3C, MAX77620_REG_GPIO5, &val, 1); + + /* Enable power. */ + val = 0x20; + i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL3, &val, 1); + val = 0x8D; + i2c_send(4, 0x1B, MAX77620_REG_CNFG1_32K, &val, 1); + val = 0xB7; + i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL1, &val, 1); + val = 0xB7; + i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL2, &val, 1); +} + +int _cluster_pmc_enable_partition(uint32_t part, uint32_t toggle) +{ + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* Check if the partition has already been turned on. */ + if (pmc->pwrgate_status & part) + return 1; + + uint32_t i = 5001; + while (pmc->pwrgate_toggle & 0x100) + { + udelay(1); + i--; + if (i < 1) + return 0; + } + + pmc->pwrgate_toggle = (toggle | 0x100); + + i = 5001; + while (i > 0) + { + if (pmc->pwrgate_status & part) + break; + + udelay(1); + i--; + } + + return 1; +} + +void cluster_boot_cpu0(uint32_t entry) +{ + volatile tegra_car_t *car = car_get_regs(); + + /* Set ACTIVE_CLUSER to FAST. */ + FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 &= 0xFFFFFFFE; + + _cluster_enable_power(); + + if (!(car->pllx_base & 0x40000000)) + { + car->pllx_misc3 &= 0xFFFFFFF7; + udelay(2); + car->pllx_base = 0x80404E02; + car->pllx_base = 0x404E02; + car->pllx_misc = ((car->pllx_base & 0xFFFBFFFF) | 0x40000); + car->pllx_base = 0x40404E02; + } + + while (!(car->pllx_base & 0x8000000)) { + /* Spinlock. */ + } + + /* Configure MSELECT source and enable clock. */ + car->clk_source_mselect = ((car->clk_source_mselect & 0x1FFFFF00) | 6); + car->clk_out_enb_v = ((car->clk_out_enb_v & 0xFFFFFFF7) | 8); + + /* Configure initial CPU clock frequency and enable clock. */ + car->cclk_brst_pol = 0x20008888; + car->super_cclk_div = 0x80000000; + car->clk_enb_v_set = 1; + + clkrst_reboot(CARDEVICE_CORESIGHT); + + /* CAR2PMC_CPU_ACK_WIDTH should be set to 0. */ + car->cpu_softrst_ctrl2 &= 0xFFFFF000; + + /* Enable CPU rail. */ + _cluster_pmc_enable_partition(1, 0); + + /* Enable cluster 0 non-CPU. */ + _cluster_pmc_enable_partition(0x8000, 15); + + /* Enable CE0. */ + _cluster_pmc_enable_partition(0x4000, 14); + + /* Request and wait for RAM repair. */ + FLOW_CTLR_RAM_REPAIR_0 = 1; + while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)){ + /* Spinlock. */ + } + + MAKE_EXCP_VEC_REG(0x100) = 0; + + /* Set reset vector. */ + SB_AA64_RESET_LOW_0 = entry | 1; + SB_AA64_RESET_HIGH_0 = 0; + + /* Non-secure reset vector write disable. */ + SB_CSR_0 = 2; + (void)SB_CSR_0; + + /* Clear MSELECT reset. */ + car->rst_dev_v &= 0xFFFFFFF7; + + /* Clear NONCPU reset. */ + car->rst_cpug_cmplx_clr = 0x20000000; + + /* Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.*/ + car->rst_cpug_cmplx_clr = 0x411F000F; +} diff --git a/fusee/fusee-secondary/src/cluster.h b/fusee/fusee-secondary/src/cluster.h new file mode 100644 index 000000000..e8e60c3ee --- /dev/null +++ b/fusee/fusee-secondary/src/cluster.h @@ -0,0 +1,6 @@ +#ifndef FUSEE_CLUSTER_H_ +#define FUSEE_CLUSTER_H_ + +void cluster_boot_cpu0(uint32_t entry); + +#endif diff --git a/fusee/fusee-secondary/src/console.c b/fusee/fusee-secondary/src/console.c index 4d26d9601..68532636d 100644 --- a/fusee/fusee-secondary/src/console.c +++ b/fusee/fusee-secondary/src/console.c @@ -5,7 +5,7 @@ #include <malloc.h> #include <sys/iosupport.h> #include "console.h" -#include "hwinit.h" +#include "di.h" #include "display/video_fb.h" static void *g_framebuffer = NULL; @@ -98,7 +98,7 @@ static void console_init_display(void) { /* Turn on the backlight after initializing the lfb */ /* to avoid flickering. */ if (!g_display_initialized) { - display_enable_backlight(true); + display_backlight(true); } g_display_initialized = true; @@ -144,7 +144,6 @@ static int console_create(void) { return 0; } - int console_init(bool display_initialized) { g_display_initialized = display_initialized; @@ -193,7 +192,7 @@ int console_resume(void) { int console_end(void) { /* Deinitialize the framebuffer and display */ if (g_display_initialized) { - display_enable_backlight(false); + display_backlight(false); display_end(); } free(g_framebuffer); diff --git a/fusee/fusee-secondary/src/di.c b/fusee/fusee-secondary/src/di.c new file mode 100644 index 000000000..e22257465 --- /dev/null +++ b/fusee/fusee-secondary/src/di.c @@ -0,0 +1,255 @@ +#include <string.h> + +#include "di.h" +#include "timers.h" +#include "i2c.h" +#include "pmc.h" +#include "max77620.h" +#include "gpio.h" +#include "pinmux.h" +#include "car.h" + +#include "di.inl" + +static uint32_t _display_ver = 0; + +static void exec_cfg(uint32_t *base, const cfg_op_t *ops, uint32_t num_ops) +{ + for (uint32_t i = 0; i < num_ops; i++) + base[ops[i].off] = ops[i].val; +} + +static void _display_dsi_wait(uint32_t timeout, uint32_t off, uint32_t mask) +{ + uint32_t end = get_time_us() + timeout; + while ((get_time_us() < end) && (MAKE_DSI_REG(off) & mask)) { + /* Wait. */ + } + udelay(5); +} + +void display_init() +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + + /* Power on. */ + uint8_t val = 0xD0; + i2c_send(4, 0x3C, MAX77620_REG_LDO0_CFG, &val, 1); + val = 0x09; + i2c_send(4, 0x3C, MAX77620_REG_GPIO7, &val, 1); + + /* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */ + car->rst_dev_h_clr = 0x1010000; + car->clk_enb_h_set = 0x1010000; + car->rst_dev_l_clr = 0x18000000; + car->clk_enb_l_set = 0x18000000; + car->clk_enb_x_set = 0x20000; + car->clk_source_uart_fst_mipi_cal = 0xA; + car->clk_enb_w_set = 0x80000; + car->clk_source_dsia_lp = 0xA; + + /* DPD idle. */ + pmc->io_dpd_req = 0x40000000; + pmc->io_dpd2_req = 0x40000000; + + /* Configure pins. */ + pinmux->nfc_en &= ~PINMUX_TRISTATE; + pinmux->nfc_int &= ~PINMUX_TRISTATE; + pinmux->lcd_bl_pwm &= ~PINMUX_TRISTATE; + pinmux->lcd_bl_en &= ~PINMUX_TRISTATE; + pinmux->lcd_rst &= ~PINMUX_TRISTATE; + + /* Configure Backlight +-5V GPIOs. */ + gpio_configure_mode(GPIO_LCD_BL_P5V, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_N5V, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_LCD_BL_P5V, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_N5V, GPIO_DIRECTION_OUTPUT); + + /* Enable Backlight +5V. */ + gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_HIGH); + + udelay(10000u); + + /* Enable Backlight -5V. */ + gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_HIGH); + + udelay(10000); + + /* Configure Backlight PWM, EN and RST GPIOs. */ + gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_EN, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_RST, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_LCD_BL_PWM, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_EN, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_RST, GPIO_DIRECTION_OUTPUT); + + /* Enable Backlight EN. */ + gpio_write(GPIO_LCD_BL_EN, GPIO_LEVEL_HIGH); + + /* Configure display interface and display. */ + MAKE_MIPI_CAL_REG(0x60) = 0; + + exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4); + exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94); + exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 60); + + udelay(10000); + + /* Enable Backlight RST. */ + gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_HIGH); + + udelay(60000); + + MAKE_DSI_REG(DSI_BTA_TIMING) = 0x50204; + MAKE_DSI_REG(DSI_WR_DATA) = 0x337; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + _display_dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO)); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x406; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + _display_dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO)); + + MAKE_DSI_REG(DSI_HOST_CONTROL) = (DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC); + _display_dsi_wait(150000, DSI_HOST_CONTROL, DSI_HOST_CONTROL_IMM_BTA); + + udelay(5000); + + _display_ver = MAKE_DSI_REG(DSI_RD_DATA); + + if (_display_ver == 0x10) + exec_cfg((uint32_t *)DSI_BASE, _display_config_4, 43); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x1105; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + + udelay(180000); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x2905; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + + udelay(20000); + + exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21); + exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3); + + MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4; + exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10); + + udelay(10000); + + exec_cfg((uint32_t *)MIPI_CAL_BASE, _display_config_8, 6); + exec_cfg((uint32_t *)DSI_BASE, _display_config_9, 4); + exec_cfg((uint32_t *)MIPI_CAL_BASE, _display_config_10, 16); + + udelay(10000); + + exec_cfg((uint32_t *)DI_BASE, _display_config_11, 113); +} + +void display_backlight(bool enable) +{ + /* Enable Backlight PWM. */ + gpio_write(GPIO_LCD_BL_PWM, enable ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW); +} + +void display_end() +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + + /* Disable Backlight. */ + display_backlight(false); + + MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 1; + MAKE_DSI_REG(DSI_WR_DATA) = 0x2805; + + uint32_t host1x_delay = MAKE_HOST1X_REG(0x30A4) + 5; + while (MAKE_HOST1X_REG(0x30A4) < host1x_delay) { + /* Wait. */ + } + + MAKE_DI_REG(DC_CMD_STATE_ACCESS) = 5; + MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 0; + + exec_cfg((uint32_t *)DI_BASE, _display_config_12, 17); + exec_cfg((uint32_t *)DSI_BASE, _display_config_13, 16); + + udelay(10000); + + if (_display_ver == 0x10) + exec_cfg((uint32_t *)DSI_BASE, _display_config_14, 22); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x1005; + MAKE_DSI_REG(DSI_TRIGGER) = 2; + + udelay(50000); + + /* Disable Backlight RST. */ + gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable Backlight -5V. */ + gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable Backlight +5V. */ + gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable clocks. */ + car->rst_dev_h_set = 0x1010000; + car->clk_enb_h_clr = 0x1010000; + car->rst_dev_l_set = 0x18000000; + car->clk_enb_l_clr = 0x18000000; + + MAKE_DSI_REG(DSI_PAD_CONTROL_0) = 0x10F010F; + MAKE_DSI_REG(DSI_POWER_CONTROL) = 0; + + /* Backlight PWM. */ + gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_SFIO); + + pinmux->lcd_bl_pwm = ((pinmux->lcd_bl_pwm & ~PINMUX_TRISTATE) | PINMUX_TRISTATE); + pinmux->lcd_bl_pwm = (((pinmux->lcd_bl_pwm >> 2) << 2) | 1); +} + +void display_color_screen(uint32_t color) +{ + exec_cfg((uint32_t *)DI_BASE, cfg_display_one_color, 8); + + /* Configure display to show single color. */ + MAKE_DI_REG(DC_WIN_AD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_WIN_BD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_WIN_CD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_DISP_BLEND_BACKGROUND_COLOR) = color; + MAKE_DI_REG(DC_CMD_STATE_CONTROL) = ((MAKE_DI_REG(DC_CMD_STATE_CONTROL) & 0xFFFFFFFE) | GENERAL_ACT_REQ); + + udelay(35000); + + display_backlight(true); +} + +uint32_t *display_init_framebuffer(void *address) +{ + static cfg_op_t conf[sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t)] = {0}; + if(conf[0].val == 0) { + for (uint32_t i = 0; i < sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t); i++) { + conf[i] = cfg_display_framebuffer[i]; + } + } + + uint32_t *lfb_addr = (uint32_t *)address; + + conf[19].val = (uint32_t)address; + + //This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). + exec_cfg((uint32_t *)DI_BASE, conf, 32); + + udelay(35000); + + return lfb_addr; +} diff --git a/fusee/fusee-secondary/src/di.h b/fusee/fusee-secondary/src/di.h new file mode 100644 index 000000000..bca4b569a --- /dev/null +++ b/fusee/fusee-secondary/src/di.h @@ -0,0 +1,350 @@ +#ifndef FUSEE_DI_H_ +#define FUSEE_DI_H_ + +#include <stdint.h> +#include <stdbool.h> + +#define HOST1X_BASE 0x50000000 +#define DI_BASE 0x54200000 +#define DSI_BASE 0x54300000 +#define VIC_BASE 0x54340000 +#define MIPI_CAL_BASE 0x700E3000 +#define MAKE_HOST1X_REG(n) MAKE_REG32(HOST1X_BASE + n) +#define MAKE_DI_REG(n) MAKE_REG32(DI_BASE + n * 4) +#define MAKE_DSI_REG(n) MAKE_REG32(DSI_BASE + n * 4) +#define MAKE_MIPI_CAL_REG(n) MAKE_REG32(MIPI_CAL_BASE + n) +#define MAKE_VIC_REG(n) MAKE_REG32(VIC_BASE + n) + +/* Display registers. */ +#define DC_CMD_GENERAL_INCR_SYNCPT 0x00 + +#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01 +#define SYNCPT_CNTRL_NO_STALL (1 << 8) +#define SYNCPT_CNTRL_SOFT_RESET (1 << 0) + +#define DC_CMD_CONT_SYNCPT_VSYNC 0x28 +#define SYNCPT_VSYNC_ENABLE (1 << 8) + +#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 + +#define DC_CMD_DISPLAY_COMMAND 0x32 +#define DISP_CTRL_MODE_STOP (0 << 5) +#define DISP_CTRL_MODE_C_DISPLAY (1 << 5) +#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5) +#define DISP_CTRL_MODE_MASK (3 << 5) + +#define DC_CMD_DISPLAY_POWER_CONTROL 0x36 +#define PW0_ENABLE (1 << 0) +#define PW1_ENABLE (1 << 2) +#define PW2_ENABLE (1 << 4) +#define PW3_ENABLE (1 << 6) +#define PW4_ENABLE (1 << 8) +#define PM0_ENABLE (1 << 16) +#define PM1_ENABLE (1 << 18) + +#define DC_CMD_INT_MASK 0x38 +#define DC_CMD_INT_ENABLE 0x39 + +#define DC_CMD_STATE_ACCESS 0x40 +#define READ_MUX (1 << 0) +#define WRITE_MUX (1 << 2) + +#define DC_CMD_STATE_CONTROL 0x41 +#define GENERAL_ACT_REQ (1 << 0) +#define WIN_A_ACT_REQ (1 << 1) +#define WIN_B_ACT_REQ (1 << 2) +#define WIN_C_ACT_REQ (1 << 3) +#define CURSOR_ACT_REQ (1 << 7) +#define GENERAL_UPDATE (1 << 8) +#define WIN_A_UPDATE (1 << 9) +#define WIN_B_UPDATE (1 << 10) +#define WIN_C_UPDATE (1 << 11) +#define CURSOR_UPDATE (1 << 15) +#define NC_HOST_TRIG (1 << 24) + +#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 +#define WINDOW_A_SELECT (1 << 4) +#define WINDOW_B_SELECT (1 << 5) +#define WINDOW_C_SELECT (1 << 6) + +#define DC_CMD_REG_ACT_CONTROL 0x043 + +#define DC_COM_CRC_CONTROL 0x300 +#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) +#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) + +#define DC_COM_DSC_TOP_CTL 0x33E + +#define DC_DISP_DISP_WIN_OPTIONS 0x402 +#define HDMI_ENABLE (1 << 30) +#define DSI_ENABLE (1 << 29) +#define SOR1_TIMING_CYA (1 << 27) +#define SOR1_ENABLE (1 << 26) +#define SOR_ENABLE (1 << 25) +#define CURSOR_ENABLE (1 << 16) + +#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 +#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404 +#define DC_DISP_DISP_TIMING_OPTIONS 0x405 +#define DC_DISP_REF_TO_SYNC 0x406 +#define DC_DISP_SYNC_WIDTH 0x407 +#define DC_DISP_BACK_PORCH 0x408 +#define DC_DISP_ACTIVE 0x409 +#define DC_DISP_FRONT_PORCH 0x40A + +#define DC_DISP_DISP_CLOCK_CONTROL 0x42E +#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8) +#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8) +#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8) +#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8) +#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8) +#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8) +#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8) +#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8) +#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8) +#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8) +#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8) +#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8) +#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8) +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) + +#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F +#define DISP_DATA_FORMAT_DF1P1C (0 << 0) +#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0) +#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0) +#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0) +#define DISP_DATA_FORMAT_DF2S (4 << 0) +#define DISP_DATA_FORMAT_DF3S (5 << 0) +#define DISP_DATA_FORMAT_DFSPI (6 << 0) +#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0) +#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0) +#define DISP_ALIGNMENT_MSB (0 << 8) +#define DISP_ALIGNMENT_LSB (1 << 8) +#define DISP_ORDER_RED_BLUE (0 << 9) +#define DISP_ORDER_BLUE_RED (1 << 9) + +#define DC_DISP_DISP_COLOR_CONTROL 0x430 +#define DITHER_CONTROL_MASK (3 << 8) +#define DITHER_CONTROL_DISABLE (0 << 8) +#define DITHER_CONTROL_ORDERED (2 << 8) +#define DITHER_CONTROL_ERRDIFF (3 << 8) +#define BASE_COLOR_SIZE_MASK (0xf << 0) +#define BASE_COLOR_SIZE_666 (0 << 0) +#define BASE_COLOR_SIZE_111 (1 << 0) +#define BASE_COLOR_SIZE_222 (2 << 0) +#define BASE_COLOR_SIZE_333 (3 << 0) +#define BASE_COLOR_SIZE_444 (4 << 0) +#define BASE_COLOR_SIZE_555 (5 << 0) +#define BASE_COLOR_SIZE_565 (6 << 0) +#define BASE_COLOR_SIZE_332 (7 << 0) +#define BASE_COLOR_SIZE_888 (8 << 0) + +#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 +#define SC1_H_QUALIFIER_NONE (1 << 16) +#define SC0_H_QUALIFIER_NONE (1 << 0) + +#define DC_DISP_DATA_ENABLE_OPTIONS 0x432 +#define DE_SELECT_ACTIVE_BLANK (0 << 0) +#define DE_SELECT_ACTIVE (1 << 0) +#define DE_SELECT_ACTIVE_IS (2 << 0) +#define DE_CONTROL_ONECLK (0 << 2) +#define DE_CONTROL_NORMAL (1 << 2) +#define DE_CONTROL_EARLY_EXT (2 << 2) +#define DE_CONTROL_EARLY (3 << 2) +#define DE_CONTROL_ACTIVE_BLANK (4 << 2) + +#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480 +#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 + +#define DC_WIN_CSC_YOF 0x611 +#define DC_WIN_CSC_KYRGB 0x612 +#define DC_WIN_CSC_KUR 0x613 +#define DC_WIN_CSC_KVR 0x614 +#define DC_WIN_CSC_KUG 0x615 +#define DC_WIN_CSC_KVG 0x616 +#define DC_WIN_CSC_KUB 0x617 +#define DC_WIN_CSC_KVB 0x618 +#define DC_WIN_AD_WIN_OPTIONS 0xB80 +#define DC_WIN_BD_WIN_OPTIONS 0xD80 +#define DC_WIN_CD_WIN_OPTIONS 0xF80 + +/* The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). */ +#define DC_WIN_WIN_OPTIONS 0x700 +#define H_DIRECTION (1 << 0) +#define V_DIRECTION (1 << 2) +#define COLOR_EXPAND (1 << 6) +#define CSC_ENABLE (1 << 18) +#define WIN_ENABLE (1 << 30) + +#define DC_WIN_COLOR_DEPTH 0x703 +#define WIN_COLOR_DEPTH_P1 0x0 +#define WIN_COLOR_DEPTH_P2 0x1 +#define WIN_COLOR_DEPTH_P4 0x2 +#define WIN_COLOR_DEPTH_P8 0x3 +#define WIN_COLOR_DEPTH_B4G4R4A4 0x4 +#define WIN_COLOR_DEPTH_B5G5R5A 0x5 +#define WIN_COLOR_DEPTH_B5G6R5 0x6 +#define WIN_COLOR_DEPTH_AB5G5R5 0x7 +#define WIN_COLOR_DEPTH_B8G8R8A8 0xC +#define WIN_COLOR_DEPTH_R8G8B8A8 0xD +#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE +#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF +#define WIN_COLOR_DEPTH_YCbCr422 0x10 +#define WIN_COLOR_DEPTH_YUV422 0x11 +#define WIN_COLOR_DEPTH_YCbCr420P 0x12 +#define WIN_COLOR_DEPTH_YUV420P 0x13 +#define WIN_COLOR_DEPTH_YCbCr422P 0x14 +#define WIN_COLOR_DEPTH_YUV422P 0x15 +#define WIN_COLOR_DEPTH_YCbCr422R 0x16 +#define WIN_COLOR_DEPTH_YUV422R 0x17 +#define WIN_COLOR_DEPTH_YCbCr422RA 0x18 +#define WIN_COLOR_DEPTH_YUV422RA 0x19 + +#define DC_WIN_BUFFER_CONTROL 0x702 +#define DC_WIN_POSITION 0x704 + +#define DC_WIN_SIZE 0x705 +#define H_SIZE(x) (((x) & 0x1fff) << 0) +#define V_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_PRESCALED_SIZE 0x706 +#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0) +#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_H_INITIAL_DDA 0x707 +#define DC_WIN_V_INITIAL_DDA 0x708 + +#define DC_WIN_DDA_INC 0x709 +#define H_DDA_INC(x) (((x) & 0xffff) << 0) +#define V_DDA_INC(x) (((x) & 0xffff) << 16) + +#define DC_WIN_LINE_STRIDE 0x70A +#define DC_WIN_DV_CONTROL 0x70E + +/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */ +#define DC_WINBUF_START_ADDR 0x800 +#define DC_WINBUF_ADDR_H_OFFSET 0x806 +#define DC_WINBUF_ADDR_V_OFFSET 0x808 +#define DC_WINBUF_SURFACE_KIND 0x80B + +/* Display serial interface registers. */ +#define DSI_RD_DATA 0x9 +#define DSI_WR_DATA 0xA + +#define DSI_POWER_CONTROL 0xB +#define DSI_POWER_CONTROL_ENABLE 1 + +#define DSI_INT_ENABLE 0xC +#define DSI_INT_STATUS 0xD +#define DSI_INT_MASK 0xE + +#define DSI_HOST_CONTROL 0xF +#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21) +#define DSI_HOST_CONTROL_CRC_RESET (1 << 20) +#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) +#define DSI_HOST_CONTROL_RAW (1 << 6) +#define DSI_HOST_CONTROL_HS (1 << 5) +#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4) +#define DSI_HOST_CONTROL_IMM_BTA (1 << 3) +#define DSI_HOST_CONTROL_PKT_BTA (1 << 2) +#define DSI_HOST_CONTROL_CS (1 << 1) +#define DSI_HOST_CONTROL_ECC (1 << 0) + +#define DSI_CONTROL 0x10 +#define DSI_CONTROL_HS_CLK_CTRL (1 << 20) +#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16) +#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12) +#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8) +#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4) +#define DSI_CONTROL_DCS_ENABLE (1 << 3) +#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2) +#define DSI_CONTROL_VIDEO_ENABLE (1 << 1) +#define DSI_CONTROL_HOST_ENABLE (1 << 0) + +#define DSI_SOL_DELAY 0x11 +#define DSI_MAX_THRESHOLD 0x12 + +#define DSI_TRIGGER 0x13 +#define DSI_TRIGGER_HOST (1 << 1) +#define DSI_TRIGGER_VIDEO (1 << 0) + +#define DSI_TX_CRC 0x14 +#define DSI_STATUS 0x15 +#define DSI_INIT_SEQ_CONTROL 0x1A +#define DSI_INIT_SEQ_DATA_0 0x1B +#define DSI_INIT_SEQ_DATA_1 0x1C +#define DSI_INIT_SEQ_DATA_2 0x1D +#define DSI_INIT_SEQ_DATA_3 0x1E +#define DSI_PKT_SEQ_0_LO 0x23 +#define DSI_PKT_SEQ_0_HI 0x24 +#define DSI_PKT_SEQ_1_LO 0x25 +#define DSI_PKT_SEQ_1_HI 0x26 +#define DSI_PKT_SEQ_2_LO 0x27 +#define DSI_PKT_SEQ_2_HI 0x28 +#define DSI_PKT_SEQ_3_LO 0x29 +#define DSI_PKT_SEQ_3_HI 0x2A +#define DSI_PKT_SEQ_4_LO 0x2B +#define DSI_PKT_SEQ_4_HI 0x2C +#define DSI_PKT_SEQ_5_LO 0x2D +#define DSI_PKT_SEQ_5_HI 0x2E +#define DSI_DCS_CMDS 0x33 +#define DSI_PKT_LEN_0_1 0x34 +#define DSI_PKT_LEN_2_3 0x35 +#define DSI_PKT_LEN_4_5 0x36 +#define DSI_PKT_LEN_6_7 0x37 +#define DSI_PHY_TIMING_0 0x3C +#define DSI_PHY_TIMING_1 0x3D +#define DSI_PHY_TIMING_2 0x3E +#define DSI_BTA_TIMING 0x3F + +#define DSI_TIMEOUT_0 0x44 +#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0) + +#define DSI_TIMEOUT_1 0x45 +#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0) + +#define DSI_TO_TALLY 0x46 + +#define DSI_PAD_CONTROL_0 0x4B +#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24) +#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) +#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8) +#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0) + +#define DSI_PAD_CONTROL_CD 0x4c +#define DSI_VIDEO_MODE_CONTROL 0x4E + +#define DSI_PAD_CONTROL_1 0x4F +#define DSI_PAD_CONTROL_2 0x50 + +#define DSI_PAD_CONTROL_3 0x51 +#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12) +#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8) +#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4) +#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0) + +#define DSI_PAD_CONTROL_4 0x52 + +typedef struct _cfg_op_t +{ + uint32_t off; + uint32_t val; +} cfg_op_t; + +void display_init(); +void display_end(); + +/* Show one single color on the display. */ +void display_color_screen(uint32_t color); + +/* Switches screen backlight ON/OFF. */ +void display_backlight(bool enable); + +/* Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ +uint32_t *display_init_framebuffer(void *address); + +#endif diff --git a/fusee/fusee-secondary/src/di.inl b/fusee/fusee-secondary/src/di.inl new file mode 100644 index 000000000..c34fb4cf2 --- /dev/null +++ b/fusee/fusee-secondary/src/di.inl @@ -0,0 +1,546 @@ +//Clock config. +static const cfg_op_t _display_config_1[4] = { + {0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 + {0x34, 0x4830A001}, //CLK_RST_CONTROLLER_PLLD_BASE + {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 + {0x37, 0x2D0AAA} //CLK_RST_CONTROLLER_PLLD_MISC +}; + +//Display A config. +static const cfg_op_t _display_config_2[94] = { + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_REG_ACT_CONTROL, 0x54}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_DISP_DC_MCCIF_FIFOCTRL, 0}, + {DC_DISP_DISP_MEM_HIGH_PRIORITY, 0}, + {DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0}, + {DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE}, + {DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL}, + {DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | 0x9}, // 9: SYNCPT + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, + {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, + {0x4E4, 0}, + {DC_COM_CRC_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ} +}; + +//DSI Init config. +static const cfg_op_t _display_config_3[60] = { + {DSI_WR_DATA, 0}, + {DSI_INT_ENABLE, 0}, + {DSI_INT_STATUS, 0}, + {DSI_INT_MASK, 0}, + {DSI_INIT_SEQ_DATA_0, 0}, + {DSI_INIT_SEQ_DATA_1, 0}, + {DSI_INIT_SEQ_DATA_2, 0}, + {DSI_INIT_SEQ_DATA_3, 0}, + {DSI_DCS_CMDS, 0}, + {DSI_PKT_SEQ_0_LO, 0}, + {DSI_PKT_SEQ_1_LO, 0}, + {DSI_PKT_SEQ_2_LO, 0}, + {DSI_PKT_SEQ_3_LO, 0}, + {DSI_PKT_SEQ_4_LO, 0}, + {DSI_PKT_SEQ_5_LO, 0}, + {DSI_PKT_SEQ_0_HI, 0}, + {DSI_PKT_SEQ_1_HI, 0}, + {DSI_PKT_SEQ_2_HI, 0}, + {DSI_PKT_SEQ_3_HI, 0}, + {DSI_PKT_SEQ_4_HI, 0}, + {DSI_PKT_SEQ_5_HI, 0}, + {DSI_CONTROL, 0}, + {DSI_PAD_CONTROL_CD, 0}, + {DSI_SOL_DELAY, 0x18}, + {DSI_MAX_THRESHOLD, 0x1E0}, + {DSI_TRIGGER, 0}, + {DSI_INIT_SEQ_CONTROL, 0}, + {DSI_PKT_LEN_0_1, 0}, + {DSI_PKT_LEN_2_3, 0}, + {DSI_PKT_LEN_4_5, 0}, + {DSI_PKT_LEN_6_7, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30109}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Enable + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, 0}, + {DSI_POWER_CONTROL, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30118}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_MAX_THRESHOLD, 0x40}, + {DSI_TRIGGER, 0}, + {DSI_TX_CRC, 0}, + {DSI_INIT_SEQ_CONTROL, 0} +}; + +//DSI config (if ver == 0x10). +static const cfg_op_t _display_config_4[43] = { + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0x9483FFB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xBD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x1939}, + {DSI_WR_DATA, 0xAAAAAAD8}, + {DSI_WR_DATA, 0xAAAAAAEB}, + {DSI_WR_DATA, 0xAAEBAAAA}, + {DSI_WR_DATA, 0xAAAAAAAA}, + {DSI_WR_DATA, 0xAAAAAAEB}, + {DSI_WR_DATA, 0xAAEBAAAA}, + {DSI_WR_DATA, 0xAA}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x1BD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2739}, + {DSI_WR_DATA, 0xFFFFFFD8}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFF}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2BD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xF39}, + {DSI_WR_DATA, 0xFFFFFFD8}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFF}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xBD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x6D915}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0xB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST} +}; + +//DSI config. +static const cfg_op_t _display_config_5[21] = { + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30172}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_PKT_SEQ_0_LO, 0x40000208}, + {DSI_PKT_SEQ_2_LO, 0x40000308}, + {DSI_PKT_SEQ_4_LO, 0x40000308}, + {DSI_PKT_SEQ_1_LO, 0x40000308}, + {DSI_PKT_SEQ_3_LO, 0x3F3B2B08}, + {DSI_PKT_SEQ_3_HI, 0x2CC}, + {DSI_PKT_SEQ_5_LO, 0x3F3B2B08}, + {DSI_PKT_SEQ_5_HI, 0x2CC}, + {DSI_PKT_LEN_0_1, 0xCE0000}, + {DSI_PKT_LEN_2_3, 0x87001A2}, + {DSI_PKT_LEN_4_5, 0x190}, + {DSI_PKT_LEN_6_7, 0x190}, + {DSI_HOST_CONTROL, 0}, +}; + +//Clock config. +static const cfg_op_t _display_config_6[3] = { + {0x34, 0x4810C001}, //CLK_RST_CONTROLLER_PLLD_BASE + {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 + {0x37, 0x2DFC00} //CLK_RST_CONTROLLER_PLLD_MISC +}; + +//DSI config. +static const cfg_op_t _display_config_7[10] = { + {DSI_TRIGGER, 0}, + {DSI_CONTROL, 0}, + {DSI_SOL_DELAY, 6}, + {DSI_MAX_THRESHOLD, 0x1E0}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL| DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC} +}; + +//MIPI CAL config. +static const cfg_op_t _display_config_8[6] = { + {0x18, 0}, + {2, 0xF3F10000}, + {0x16, 1}, + {0x18, 0}, + {0x18, 0x10010}, + {0x17, 0x300} +}; + +//DSI config. +static const cfg_op_t _display_config_9[4] = { + {DSI_PAD_CONTROL_1, 0}, + {DSI_PAD_CONTROL_2, 0}, + {DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)}, + {DSI_PAD_CONTROL_4, 0} +}; + +//MIPI CAL config. +static const cfg_op_t _display_config_10[16] = { + {0xE, 0x200200}, + {0xF, 0x200200}, + {0x19, 0x200002}, + {0x1A, 0x200002}, + {5, 0}, + {6, 0}, + {7, 0}, + {8, 0}, + {9, 0}, + {0xA, 0}, + {0x10, 0}, + {0x11, 0}, + {0x1A, 0}, + {0x1C, 0}, + {0x1D, 0}, + {0, 0x2A000001} +}; + +//Display A config. +static const cfg_op_t _display_config_11[113] = { + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, + {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, + {0x4E4, 0}, + {DC_COM_CRC_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + /* Set Display timings */ + {DC_DISP_DISP_TIMING_OPTIONS, 0}, + {DC_DISP_REF_TO_SYNC, (1 << 16)}, // h_ref_to_sync = 0, v_ref_to_sync = 1. + {DC_DISP_SYNC_WIDTH, 0x10048}, + {DC_DISP_BACK_PORCH, 0x90048}, + {DC_DISP_ACTIVE, 0x50002D0}, + {DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the DC_DISP_ACTIVE cmd. + /* End of Display timings */ + {DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE}, + {DC_COM_PIN_OUTPUT_ENABLE(1), 0}, + {DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_DISP_DISP_CLOCK_CONTROL, 0}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX}, + {DC_DISP_FRONT_PORCH, 0xA0088}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0} +}; + +////Display A config. +static const cfg_op_t _display_config_12[17] = { + {DC_DISP_FRONT_PORCH, 0xA0088}, + {DC_CMD_INT_MASK, 0}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_INT_ENABLE, 0}, + {DC_CMD_CONT_SYNCPT_VSYNC, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_DISPLAY_POWER_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, +}; + +//DSI config. +static const cfg_op_t _display_config_13[16] = { + {DSI_POWER_CONTROL, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30109}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) }, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_MAX_THRESHOLD, 0x40}, + {DSI_TRIGGER, 0}, + {DSI_TX_CRC, 0}, + {DSI_INIT_SEQ_CONTROL, 0} +}; + +//DSI config (if ver == 0x10). +static const cfg_op_t _display_config_14[22] = { + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0x9483FFB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2139}, + {DSI_WR_DATA, 0x191919D5}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xB39}, + {DSI_WR_DATA, 0x4F0F41B1}, + {DSI_WR_DATA, 0xF179A433}, + {DSI_WR_DATA, 0x2D81}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0xB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST} +}; + +//Display A config. +static const cfg_op_t cfg_display_one_color[8] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} //DISPLAY_CTRL_MODE: continuous display. +}; + +//Display A config. +static const cfg_op_t cfg_display_framebuffer[32] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //T_A8R8G8B8 //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8 + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_POSITION, 0}, //(0,0) + {DC_WIN_H_INITIAL_DDA, 0}, + {DC_WIN_V_INITIAL_DDA, 0}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes. + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels. + {DC_WIN_LINE_STRIDE, 0x6000C00}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_BUFFER_CONTROL, 0}, + {DC_WINBUF_SURFACE_KIND, 0}, //Regular surface. + {DC_WINBUF_START_ADDR, 0xC0000000}, //Framebuffer address. + {DC_WINBUF_ADDR_H_OFFSET, 0}, + {DC_WINBUF_ADDR_V_OFFSET, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, //Enable window AD. + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display. + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update. + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request. +}; diff --git a/fusee/fusee-secondary/src/flow.h b/fusee/fusee-secondary/src/flow.h index 65b9a2359..b3128d55e 100644 --- a/fusee/fusee-secondary/src/flow.h +++ b/fusee/fusee-secondary/src/flow.h @@ -1,44 +1,15 @@ #ifndef FUSEE_FLOW_CTLR_H #define FUSEE_FLOW_CTLR_H -#include "utils.h" +#include <stdint.h> -#define FLOW_BASE 0x60007000 - -#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_BASE + ofs) +#define FLOW_CTLR_BASE 0x60007000 +#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_CTLR_BASE + ofs) #define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) +#define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040) #define FLOW_CTLR_FLOW_DBG_QUAL_0 MAKE_FLOW_REG(0x050) #define FLOW_CTLR_L2FLUSH_CONTROL_0 MAKE_FLOW_REG(0x094) #define FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 MAKE_FLOW_REG(0x098) - -static const struct { - unsigned int CPUN_CSR_OFS; - unsigned int HALT_CPUN_EVENTS_OFS; - unsigned int CC4_COREN_CTRL_OFS; -} g_flow_core_offsets[NUM_CPU_CORES] = { - {0x008, 0x000, 0x06C}, - {0x018, 0x014, 0x070}, - {0x020, 0x01C, 0x074}, - {0x028, 0x024, 0x078}, -}; - -static inline void flow_set_cc4_ctrl(uint32_t core, uint32_t cc4_ctrl) { - MAKE_FLOW_REG(g_flow_core_offsets[core].CC4_COREN_CTRL_OFS) = cc4_ctrl; -} - -static inline void flow_set_halt_events(uint32_t core, bool halt_events) { - MAKE_FLOW_REG(g_flow_core_offsets[core].HALT_CPUN_EVENTS_OFS) = (halt_events ? 0x40000F00 : 0x40000000); -} - -static inline void flow_set_csr(uint32_t core, uint32_t csr) { - MAKE_FLOW_REG(g_flow_core_offsets[core].CPUN_CSR_OFS) = (0x100 << core) | (csr << 12) | 0xC001; -} - -static inline void flow_clear_csr0_and_events(uint32_t core) { - MAKE_FLOW_REG(g_flow_core_offsets[core].CPUN_CSR_OFS) = 0; - MAKE_FLOW_REG(g_flow_core_offsets[core].HALT_CPUN_EVENTS_OFS) = 0; -} - #endif diff --git a/fusee/fusee-secondary/src/fuse.c b/fusee/fusee-secondary/src/fuse.c index 2bdfa3740..04780c9ce 100644 --- a/fusee/fusee-secondary/src/fuse.c +++ b/fusee/fusee-secondary/src/fuse.c @@ -2,7 +2,7 @@ #include <stdint.h> #include <string.h> -#include "hwinit.h" +#include "car.h" #include "fuse.h" #include "timers.h" @@ -13,154 +13,155 @@ void fuse_enable_power(void); void fuse_disable_power(void); void fuse_wait_idle(void); -/* Initialize the FUSE driver */ -void fuse_init(void) -{ - /* - Already done by hwinit, except maybe fuse_secondary_private_key_disable (?) - fuse_make_regs_visible(); - fuse_secondary_private_key_disable(); - fuse_disable_programming(); - */ +/* Initialize the fuse driver */ +void fuse_init(void) { + fuse_make_regs_visible(); + fuse_secondary_private_key_disable(); + fuse_disable_programming(); /* TODO: Overrides (iROM patches) and various reads happen here */ } /* Make all fuse registers visible */ -void fuse_make_regs_visible(void) -{ - clock_enable_fuse(1); +void fuse_make_regs_visible(void) { + clkrst_enable_fuse_regs(true); } /* Enable power to the fuse hardware array */ -void fuse_enable_power(void) -{ - FUSE_REGS->FUSE_PWR_GOOD_SW = 1; - wait(1); +void fuse_enable_power(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PWR_GOOD_SW = 1; + udelay(1); } /* Disable power to the fuse hardware array */ -void fuse_disable_power(void) -{ - FUSE_REGS->FUSE_PWR_GOOD_SW = 0; - wait(1); +void fuse_disable_power(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PWR_GOOD_SW = 0; + udelay(1); } /* Wait for the fuse driver to go idle */ -void fuse_wait_idle(void) -{ +void fuse_wait_idle(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); uint32_t ctrl_val = 0; /* Wait for STATE_IDLE */ while ((ctrl_val & (0xF0000)) != 0x40000) { - wait(1); - ctrl_val = FUSE_REGS->FUSE_CTRL; + udelay(1); + ctrl_val = fuse->FUSE_CTRL; } } /* Read a fuse from the hardware array */ -uint32_t fuse_hw_read(uint32_t addr) -{ +uint32_t fuse_hw_read(uint32_t addr) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); fuse_wait_idle(); /* Program the target address */ - FUSE_REGS->FUSE_REG_ADDR = addr; + fuse->FUSE_REG_ADDR = addr; /* Enable read operation in control register */ - uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; + uint32_t ctrl_val = fuse->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x1; /* Set FUSE_READ command */ - FUSE_REGS->FUSE_CTRL = ctrl_val; + fuse->FUSE_CTRL = ctrl_val; fuse_wait_idle(); - return FUSE_REGS->FUSE_REG_READ; + return fuse->FUSE_REG_READ; } /* Write a fuse in the hardware array */ -void fuse_hw_write(uint32_t value, uint32_t addr) -{ +void fuse_hw_write(uint32_t value, uint32_t addr) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); fuse_wait_idle(); /* Program the target address and value */ - FUSE_REGS->FUSE_REG_ADDR = addr; - FUSE_REGS->FUSE_REG_WRITE = value; + fuse->FUSE_REG_ADDR = addr; + fuse->FUSE_REG_WRITE = value; /* Enable write operation in control register */ - uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; + uint32_t ctrl_val = fuse->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x2; /* Set FUSE_WRITE command */ - FUSE_REGS->FUSE_CTRL = ctrl_val; + fuse->FUSE_CTRL = ctrl_val; fuse_wait_idle(); } /* Sense the fuse hardware array into the shadow cache */ -void fuse_hw_sense(void) -{ +void fuse_hw_sense(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); fuse_wait_idle(); /* Enable sense operation in control register */ - uint32_t ctrl_val = FUSE_REGS->FUSE_CTRL; + uint32_t ctrl_val = fuse->FUSE_CTRL; ctrl_val &= ~0x3; ctrl_val |= 0x3; /* Set FUSE_SENSE command */ - FUSE_REGS->FUSE_CTRL = ctrl_val; + fuse->FUSE_CTRL = ctrl_val; fuse_wait_idle(); } /* Disables all fuse programming. */ void fuse_disable_programming(void) { - FUSE_REGS->FUSE_DIS_PGM = 1; + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_DIS_PGM = 1; } /* Unknown exactly what this does, but it alters the contents read from the fuse cache. */ void fuse_secondary_private_key_disable(void) { - FUSE_REGS->FUSE_PRIVATEKEYDISABLE = 0x10; + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PRIVATEKEYDISABLE = 0x10; } /* Read the SKU info register from the shadow cache */ -uint32_t fuse_get_sku_info(void) -{ - return FUSE_CHIP_REGS->FUSE_SKU_INFO; +uint32_t fuse_get_sku_info(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return fuse_chip->FUSE_SKU_INFO; } /* Read the bootrom patch version from a register in the shadow cache */ -uint32_t fuse_get_bootrom_patch_version(void) -{ - return FUSE_CHIP_REGS->FUSE_SOC_SPEEDO_1; +uint32_t fuse_get_bootrom_patch_version(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return fuse_chip->FUSE_SOC_SPEEDO_1; } /* Read a spare bit register from the shadow cache */ -uint32_t fuse_get_spare_bit(uint32_t idx) -{ +uint32_t fuse_get_spare_bit(uint32_t idx) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + if (idx >= 32) { return 0; } - return FUSE_CHIP_REGS->FUSE_SPARE_BIT[idx]; + return fuse_chip->FUSE_SPARE_BIT[idx]; } /* Read a reserved ODM register from the shadow cache */ -uint32_t fuse_get_reserved_odm(uint32_t idx) -{ +uint32_t fuse_get_reserved_odm(uint32_t idx) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + if (idx >= 8) { return 0; } - return FUSE_CHIP_REGS->FUSE_RESERVED_ODM[idx]; + return fuse_chip->FUSE_RESERVED_ODM[idx]; } /* Derive the Device ID using values in the shadow cache */ uint64_t fuse_get_device_id(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + uint64_t device_id = 0; - uint64_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF; - uint64_t x_coord = FUSE_CHIP_REGS->FUSE_X_COORDINATE & 0x1FF; - uint64_t wafer_id = FUSE_CHIP_REGS->FUSE_WAFER_ID & 0x3F; - uint32_t lot_code = FUSE_CHIP_REGS->FUSE_LOT_CODE_0; - uint64_t fab_code = FUSE_CHIP_REGS->FUSE_FAB_CODE & 0x3F; + uint64_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF; + uint64_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF; + uint64_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F; + uint32_t lot_code = fuse_chip->FUSE_LOT_CODE_0; + uint64_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F; uint64_t derived_lot_code = 0; for (unsigned int i = 0; i < 5; i++) { derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F); @@ -177,24 +178,27 @@ uint64_t fuse_get_device_id(void) { /* Get the DRAM ID using values in the shadow cache */ uint32_t fuse_get_dram_id(void) { - return (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 3) & 0x7; + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return (fuse_chip->FUSE_RESERVED_ODM[4] >> 3) & 0x7; } /* Derive the Hardware Type using values in the shadow cache */ uint32_t fuse_get_hardware_type(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + /* This function is very different between 4.x and < 4.x */ - uint32_t hardware_type = ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 2) & 1); + uint32_t hardware_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((fuse_chip->FUSE_RESERVED_ODM[4] >> 2) & 1); /* TODO: choose; if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT) { static const uint32_t types[] = {0,1,4,3}; - hardware_type |= (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 14) & 0x3C; + hardware_type |= (fuse_chip->FUSE_RESERVED_ODM[4] >> 14) & 0x3C; hardware_type--; return hardware_type > 3 ? 4 : types[hardware_type]; } else {*/ if (hardware_type >= 1) { return hardware_type > 2 ? 3 : hardware_type - 1; - } else if ((FUSE_CHIP_REGS->FUSE_SPARE_BIT[9] & 1) == 0) { + } else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) { return 0; } else { return 3; @@ -204,8 +208,10 @@ uint32_t fuse_get_hardware_type(void) { /* Derive the Retail Type using values in the shadow cache */ uint32_t fuse_get_retail_type(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + /* Retail type = IS_RETAIL | UNIT_TYPE */ - uint32_t retail_type = ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 7) & 4) | (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] & 3); + uint32_t retail_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 4) | (fuse_chip->FUSE_RESERVED_ODM[4] & 3); if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */ return 1; } else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */ @@ -216,16 +222,17 @@ uint32_t fuse_get_retail_type(void) { /* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */ void fuse_get_hardware_info(void *dst) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); uint32_t hw_info[0x4]; - uint32_t unk_hw_fuse = FUSE_CHIP_REGS->_0x120 & 0x3F; - uint32_t y_coord = FUSE_CHIP_REGS->FUSE_Y_COORDINATE & 0x1FF; - uint32_t x_coord = FUSE_CHIP_REGS->FUSE_X_COORDINATE & 0x1FF; - uint32_t wafer_id = FUSE_CHIP_REGS->FUSE_WAFER_ID & 0x3F; - uint32_t lot_code_0 = FUSE_CHIP_REGS->FUSE_LOT_CODE_0; - uint32_t lot_code_1 = FUSE_CHIP_REGS->FUSE_LOT_CODE_1 & 0x0FFFFFFF; - uint32_t fab_code = FUSE_CHIP_REGS->FUSE_FAB_CODE & 0x3F; - uint32_t vendor_code = FUSE_CHIP_REGS->FUSE_VENDOR_CODE & 0xF; + uint32_t unk_hw_fuse = fuse_chip->_0x120 & 0x3F; + uint32_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF; + uint32_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF; + uint32_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F; + uint32_t lot_code_0 = fuse_chip->FUSE_LOT_CODE_0; + uint32_t lot_code_1 = fuse_chip->FUSE_LOT_CODE_1 & 0x0FFFFFFF; + uint32_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F; + uint32_t vendor_code = fuse_chip->FUSE_VENDOR_CODE & 0xF; /* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */ hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse)); diff --git a/fusee/fusee-secondary/src/fuse.h b/fusee/fusee-secondary/src/fuse.h index 989f564bf..63285b64f 100644 --- a/fusee/fusee-secondary/src/fuse.h +++ b/fusee/fusee-secondary/src/fuse.h @@ -1,6 +1,11 @@ #ifndef FUSEE_FUSE_H #define FUSEE_FUSE_H +#define FUSE_BASE 0x7000F800 +#define FUSE_CHIP_BASE (FUSE_BASE + 0x100) +#define MAKE_FUSE_REG(n) MAKE_REG32(FUSE_BASE + n) +#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n) + typedef struct { uint32_t FUSE_CTRL; uint32_t FUSE_REG_ADDR; @@ -17,7 +22,7 @@ typedef struct { uint32_t FUSE_WRITE_ACCESS; uint32_t FUSE_PWR_GOOD_SW; uint32_t _0x38[0x32]; -} fuse_registers_t; +} tegra_fuse_t; typedef struct { uint32_t FUSE_PRODUCTION_MODE; @@ -160,17 +165,15 @@ typedef struct { uint32_t _0x278; uint32_t _0x27C; uint32_t FUSE_SPARE_BIT[0x20]; -} fuse_chip_registers_t; +} tegra_fuse_chip_t; -static inline volatile fuse_registers_t *get_fuse_regs(void) { - return (volatile fuse_registers_t *)(0x7000F000 + 0x800); +static inline volatile tegra_fuse_t *fuse_get_regs(void) { + return (volatile tegra_fuse_t *)FUSE_BASE; } -static inline volatile fuse_chip_registers_t *get_fuse_chip_regs(void) { - return (volatile fuse_chip_registers_t *)(0x7000F000 + 0x900); +static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) { + return (volatile tegra_fuse_chip_t *)FUSE_CHIP_BASE; } -#define FUSE_REGS (get_fuse_regs()) -#define FUSE_CHIP_REGS (get_fuse_chip_regs()) void fuse_init(void); diff --git a/fusee/fusee-secondary/src/gpio.h b/fusee/fusee-secondary/src/gpio.h index b3da7dc56..a916c989c 100644 --- a/fusee/fusee-secondary/src/gpio.h +++ b/fusee/fusee-secondary/src/gpio.h @@ -1,6 +1,11 @@ #ifndef FUSEE_GPIO_H #define FUSEE_GPIO_H +#include <stdint.h> + +#define GPIO_BASE 0x6000D000 +#define MAKE_GPIO_REG(n) MAKE_REG32(GPIO_BASE + n) + #define TEGRA_GPIO_PORTS 4 #define TEGRA_GPIO_BANKS 8 #define GPIO_BANK_SHIFT 5 @@ -68,7 +73,7 @@ typedef struct { static inline volatile tegra_gpio_t *gpio_get_regs(void) { - return (volatile tegra_gpio_t *)0x6000D000; + return (volatile tegra_gpio_t *)GPIO_BASE; } #define TEGRA_GPIO(port, offset) \ @@ -87,9 +92,16 @@ static inline volatile tegra_gpio_t *gpio_get_regs(void) #define GPIO_LEVEL_HIGH 1 /* Named GPIOs */ +#define GPIO_BUTTON_VOL_DOWN TEGRA_GPIO(X, 7) +#define GPIO_BUTTON_VOL_UP TEGRA_GPIO(X, 6) #define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1) #define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4) #define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4) +#define GPIO_LCD_BL_P5V TEGRA_GPIO(I, 0) +#define GPIO_LCD_BL_N5V TEGRA_GPIO(I, 1) +#define GPIO_LCD_BL_PWM TEGRA_GPIO(V, 0) +#define GPIO_LCD_BL_EN TEGRA_GPIO(V, 1) +#define GPIO_LCD_BL_RST TEGRA_GPIO(V, 2) void gpio_configure_mode(uint32_t pin, uint32_t mode); void gpio_configure_direction(uint32_t pin, uint32_t dir); diff --git a/fusee/fusee-secondary/src/hwinit.h b/fusee/fusee-secondary/src/hwinit.h deleted file mode 100644 index 1d4a47299..000000000 --- a/fusee/fusee-secondary/src/hwinit.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef FUSEE_HWINIT_H -#define FUSEE_HWINIT_H - -/* Symbols from hwinit that we're using, but w/o importing macro definitions that may clash with ours */ - -#include "hwinit/types.h" -#include "hwinit/hwinit.h" -#include "hwinit/i2c.h" - -#include <stdbool.h> - -#define UART_A 0 -#define UART_B 1 -#define UART_C 2 -#define BAUD_115200 115200 - -void uart_init(u32 idx, u32 baud); -void uart_wait_idle(u32 idx, u32 which); -void uart_send(u32 idx, u8 *buf, u32 len); -void uart_recv(u32 idx, u8 *buf, u32 len); - -void display_init(); -void display_end(); - -void clock_enable_fuse(u32 enable); - -/*! Show one single color on the display. */ -void display_color_screen(u32 color); - -/*! Init display in full 1280x720 resolution (32bpp, line stride 768, framebuffer size = 1280*768*4 bytes). */ -u32 *display_init_framebuffer(void *address); - -/*! Enable or disable the backlight. Should only be called when the screen is completely set up, to avoid flickering. */ -void display_enable_backlight(bool on); - -void cluster_enable_cpu0(u64 entry, u32 ns_disable); - -void mc_enable_ahb_redirect(); - -int tsec_query(u32 carveout, u8 *dst, u32 rev); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/btn.c b/fusee/fusee-secondary/src/hwinit/btn.c deleted file mode 100644 index 50bf1b37d..000000000 --- a/fusee/fusee-secondary/src/hwinit/btn.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "btn.h" -#include "i2c.h" -#include "t210.h" - -u32 btn_read() -{ - u32 res = 0; - if(!(GPIO_6(0x3C) & 0x80)) - res |= BTN_VOL_DOWN; - if(!(GPIO_6(0x3C) & 0x40)) - res |= BTN_VOL_UP; - if(i2c_recv_byte(4, 0x3C, 0x15) & 0x4) - res |= BTN_POWER; - return res; -} - -u32 btn_wait() -{ - u32 res = 0, btn = btn_read(); - do - { - res = btn_read(); - } while (btn == res); - return res; -} diff --git a/fusee/fusee-secondary/src/hwinit/btn.h b/fusee/fusee-secondary/src/hwinit/btn.h deleted file mode 100644 index 7ae7af9e7..000000000 --- a/fusee/fusee-secondary/src/hwinit/btn.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _BTN_H_ -#define _BTN_H_ - -#include "types.h" - -#define BTN_POWER 0x1 -#define BTN_VOL_DOWN 0x2 -#define BTN_VOL_UP 0x4 - -u32 btn_read(); -u32 btn_wait(); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/clock.c b/fusee/fusee-secondary/src/hwinit/clock.c deleted file mode 100644 index b0b4ab93b..000000000 --- a/fusee/fusee-secondary/src/hwinit/clock.c +++ /dev/null @@ -1,145 +0,0 @@ -#include "clock.h" -#include "t210.h" -#include "util.h" - -static const clock_t _clock_uart[] = { - /* UART A */ { 4, 0x10, 0x178, 6, 0, 0 }, - /* UART B */ { 4, 0x10, 0x17C, 7, 0, 0 }, - /* UART C */ { 8, 0x14, 0x1A0, 0x17, 0, 0 }, - /* UART D */ { 0 }, - /* UART E */ { 0 } -}; - -static const clock_t _clock_i2c[] = { - /* I2C1 */ { 4, 0x10, 0x124, 0xC, 6, 0 }, - /* I2C2 */ { 0 }, - /* I2C3 */ { 0 }, - /* I2C4 */ { 0 }, - /* I2C5 */ { 8, 0x14, 0x128, 0xF, 6, 0 }, - /* I2C6 */ { 0 } -}; - -static clock_t _clock_se = { 0x358, 0x360, 0x42C, 0x1F, 0, 0 }; - -static clock_t _clock_host1x = { 4, 0x10, 0x180, 0x1C, 4, 3 }; -static clock_t _clock_tsec = { 0xC, 0x18, 0x1F4, 0x13, 0, 2 }; -static clock_t _clock_sor_safe = { 0x2A4, 0x298, 0, 0x1E, 0, 0 }; -static clock_t _clock_sor0 = { 0x28C, 0x280, 0, 0x16, 0, 0 }; -static clock_t _clock_sor1 = { 0x28C, 0x280, 0x410, 0x17, 0, 2 }; -static clock_t _clock_kfuse = { 8, 0x14, 0, 8, 0, 0 }; - -static clock_t _clock_coresight = { 0xC, 0x18, 0x1D4, 9, 0, 4}; - -void clock_enable(const clock_t *clk) -{ - //Put clock into reset. - CLOCK(clk->reset) = CLOCK(clk->reset) & ~(1 << clk->index) | (1 << clk->index); - //Disable. - CLOCK(clk->enable) &= ~(1 << clk->index); - //Configure clock source if required. - if (clk->source) - CLOCK(clk->source) = clk->clk_div | (clk->clk_src << 29); - //Enable. - CLOCK(clk->enable) = CLOCK(clk->enable) & ~(1 << clk->index) | (1 << clk->index); - //Take clock off reset. - CLOCK(clk->reset) &= ~(1 << clk->index); -} - -void clock_disable(const clock_t *clk) -{ - //Put clock into reset. - CLOCK(clk->reset) = CLOCK(clk->reset) & ~(1 << clk->index) | (1 << clk->index); - //Disable. - CLOCK(clk->enable) &= ~(1 << clk->index); -} - -void clock_enable_fuse(u32 enable) -{ - CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) = CLOCK(CLK_RST_CONTROLLER_MISC_CLK_ENB) & 0xEFFFFFFF | ((enable & 1) << 28) & 0x10000000; -} - -void clock_enable_uart(u32 idx) -{ - clock_enable(&_clock_uart[idx]); -} - -void clock_enable_i2c(u32 idx) -{ - clock_enable(&_clock_i2c[idx]); -} - -void clock_enable_se() -{ - clock_enable(&_clock_se); -} - -void clock_enable_host1x() -{ - clock_enable(&_clock_host1x); -} - -void clock_enable_tsec() -{ - clock_enable(&_clock_tsec); -} - -void clock_enable_sor_safe() -{ - clock_enable(&_clock_sor_safe); -} - -void clock_enable_sor0() -{ - clock_enable(&_clock_sor0); -} - -void clock_enable_sor1() -{ - clock_enable(&_clock_sor1); -} - -void clock_enable_kfuse() -{ - //clock_enable(&_clock_kfuse); - CLOCK(0x8) = CLOCK(0x8) & 0xFFFFFEFF | 0x100; - CLOCK(0x14) &= 0xFFFFFEFF; - CLOCK(0x14) = CLOCK(0x14) & 0xFFFFFEFF | 0x100; - sleep(10); - CLOCK(0x8) &= 0xFFFFFEFF; - sleep(20); -} - -void clock_disable_host1x() -{ - clock_disable(&_clock_host1x); -} - -void clock_disable_tsec() -{ - clock_disable(&_clock_tsec); -} - -void clock_disable_sor_safe() -{ - clock_disable(&_clock_sor_safe); -} - -void clock_disable_sor0() -{ - clock_disable(&_clock_sor0); -} - -void clock_disable_sor1() -{ - clock_disable(&_clock_sor1); -} - -void clock_disable_kfuse() -{ - clock_disable(&_clock_kfuse); -} - -void clock_enable_coresight() -{ - clock_enable(&_clock_coresight); -} diff --git a/fusee/fusee-secondary/src/hwinit/clock.h b/fusee/fusee-secondary/src/hwinit/clock.h deleted file mode 100644 index 027fd4b26..000000000 --- a/fusee/fusee-secondary/src/hwinit/clock.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _CLOCK_H_ -#define _CLOCK_H_ - -#include "types.h" - -/*! Clock registers. */ -#define CLK_RST_CONTROLLER_SCLK_BURST_POLICY 0x28 -#define CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER 0x2C -#define CLK_RST_CONTROLLER_CLK_SYSTEM_RATE 0x30 -#define CLK_RST_CONTROLLER_MISC_CLK_ENB 0x48 -#define CLK_RST_CONTROLLER_OSC_CTRL 0x50 -#define CLK_RST_CONTROLLER_CLK_SOURCE_EMC 0x19C -#define CLK_RST_CONTROLLER_CLK_ENB_X_SET 0x284 -#define CLK_RST_CONTROLLER_RST_DEV_H_SET 0x308 -#define CLK_RST_CONTROLLER_CLK_ENB_H_SET 0x328 -#define CLK_RST_CONTROLLER_RST_DEVICES_V 0x358 -#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR 0x454 -#define CLK_RST_CONTROLLER_SPARE_REG0 0x55C -#define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8 - -typedef struct _clock_t -{ - u32 reset; - u32 enable; - u32 source; - u8 index; - u8 clk_src; - u8 clk_div; -} clock_t; - -void clock_enable(const clock_t *clk); -void clock_disable(const clock_t *clk); -void clock_enable_fuse(u32 enable); -void clock_enable_uart(u32 idx); -void clock_enable_i2c(u32 idx); -void clock_enable_se(); -void clock_enable_host1x(); -void clock_enable_tsec(); -void clock_enable_sor_safe(); -void clock_enable_sor0(); -void clock_enable_sor1(); -void clock_enable_kfuse(); -void clock_disable_host1x(); -void clock_disable_tsec(); -void clock_disable_sor_safe(); -void clock_disable_sor0(); -void clock_disable_sor1(); -void clock_disable_kfuse(); -void clock_enable_coresight(); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/cluster.c b/fusee/fusee-secondary/src/hwinit/cluster.c deleted file mode 100644 index 26f6e8d3e..000000000 --- a/fusee/fusee-secondary/src/hwinit/cluster.c +++ /dev/null @@ -1,117 +0,0 @@ -#include "cluster.h" -#include "i2c.h" -#include "clock.h" -#include "util.h" -#include "pmc.h" -#include "t210.h" - -void _cluster_enable_power() -{ - u8 tmp; - - if (i2c_recv_buf_small(&tmp, 1, I2C_5, 0x3C, 0x40)) - { - tmp &= 0xDFu; - i2c_send_byte(I2C_5, 0x3C, 0x40, tmp); - } - i2c_send_byte(I2C_5, 0x3C, 0x3B, 0x09); - - //Enable cores power. - i2c_send_byte(I2C_5, 0x1B, 0x02, 0x20); - i2c_send_byte(I2C_5, 0x1B, 0x03, 0x8D); - i2c_send_byte(I2C_5, 0x1B, 0x00, 0xB7); - i2c_send_byte(I2C_5, 0x1B, 0x01, 0xB7); -} - -int _cluster_pmc_enable_partition(u32 part, u32 toggle) -{ - //Check if the partition has already been turned on. - if (PMC(APBDEV_PMC_PWRGATE_STATUS) & part) - return 0; - - u32 i = 5001; - while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100) - { - sleep(1); - i--; - if (i < 1) - return 0; - } - - PMC(APBDEV_PMC_PWRGATE_TOGGLE) = toggle | 0x100; - - i = 5001; - while (i > 0) - { - if (PMC(APBDEV_PMC_PWRGATE_STATUS) & part) - break; - sleep(1); - i--; - } - - return 1; -} - -void cluster_enable_cpu0(u64 entry, u32 ns_disable) -{ - //Set ACTIVE_CLUSER to FAST. - FLOW_CTLR(FLOW_CTLR_BPMP_CLUSTER_CONTROL) &= 0xFFFFFFFE; - - _cluster_enable_power(); - - if (!(CLOCK(0xE0) & 0x40000000)) - { - CLOCK(0x518) &= 0xFFFFFFF7; - sleep(2); - CLOCK(0xE0) = 0x80404E02; - CLOCK(0xE0) = 0x404E02; - CLOCK(0xE4) = CLOCK(0xE4) & 0xFFFBFFFF | 0x40000; - CLOCK(0xE0) = 0x40404E02; - } - while (!(CLOCK(0xE0) & 0x8000000)) - ; - - CLOCK(0x3B4) = CLOCK(0x3B4) & 0x1FFFFF00 | 6; - CLOCK(0x360) = CLOCK(0x360) & 0xFFFFFFF7 | 8; - CLOCK(0x20) = 0x20008888; - CLOCK(0x24) = 0x80000000; - CLOCK(0x440) = 1; - - clock_enable_coresight(); - - CLOCK(0x388) = CLOCK(0x388) & 0xFFFFF000; - - //Enable CPU rail. - _cluster_pmc_enable_partition(1, 0); - //Enable cluster 0 non-CPU. - _cluster_pmc_enable_partition(0x8000, 15); - //Enable CE0. - _cluster_pmc_enable_partition(0x4000, 14); - - //Request and wait for RAM repair. - FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1; - while (!(FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) & 2)) - ; - - EXCP_VEC(0x100) = 0; - - if(ns_disable) - { - //Set reset vectors. - SB(SB_AA64_RESET_LOW) = (u32)entry | 1; - SB(SB_AA64_RESET_HIGH) = (u32)(entry >> 32); - //Non-secure reset vector write disable. - SB(SB_CSR_0) = 2; - } - else - { - //Set reset vectors. - SB(SB_AA64_RESET_LOW) = (u32)entry; - SB(SB_AA64_RESET_HIGH) = (u32)(entry >> 32); - } - - //Until here the CPU was in reset, this kicks execution. - CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= 0xFFFFFFF7; - CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000; - CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x411F000F; -} diff --git a/fusee/fusee-secondary/src/hwinit/cluster.h b/fusee/fusee-secondary/src/hwinit/cluster.h deleted file mode 100644 index 41ae68f52..000000000 --- a/fusee/fusee-secondary/src/hwinit/cluster.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _CLUSTER_H_ -#define _CLUSTER_H_ - -#include "types.h" - -/*! Flow controller registers. */ -#define FLOW_CTLR_RAM_REPAIR 0x40 -#define FLOW_CTLR_BPMP_CLUSTER_CONTROL 0x98 - -void cluster_enable_cpu0(u64 entry, u32 ns_disable); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/di.c b/fusee/fusee-secondary/src/hwinit/di.c deleted file mode 100644 index a168f8dc4..000000000 --- a/fusee/fusee-secondary/src/hwinit/di.c +++ /dev/null @@ -1,209 +0,0 @@ -#include "di.h" -#include "t210.h" -#include "util.h" -#include "i2c.h" -#include "pmc.h" - -#include "di.inl" - -static u32 _display_ver = 0; - -static void _display_dsi_wait(u32 timeout, u32 off, u32 mask) -{ - u32 end = TMR(0x10) + timeout; - while (TMR(0x10) < end && DSI(off) & mask) - ; - sleep(5); -} - -void display_init() -{ - //Power on. - i2c_send_byte(I2C_5, 0x3C, 0x23, 0xD0); - i2c_send_byte(I2C_5, 0x3C, 0x3D, 0x09); - - //Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. - CLOCK(0x30C) = 0x1010000; - CLOCK(0x328) = 0x1010000; - CLOCK(0x304) = 0x18000000; - CLOCK(0x320) = 0x18000000; - CLOCK(0x284) = 0x20000; - CLOCK(0x66C) = 0xA; - CLOCK(0x448) = 0x80000; - CLOCK(0x620) = 0xA; - - //DPD idle. - PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000; - PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000; - - //Config pins. - PINMUX_AUX(0x1D0) &= 0xFFFFFFEF; - PINMUX_AUX(0x1D4) &= 0xFFFFFFEF; - PINMUX_AUX(0x1FC) &= 0xFFFFFFEF; - PINMUX_AUX(0x200) &= 0xFFFFFFEF; - PINMUX_AUX(0x204) &= 0xFFFFFFEF; - - GPIO_3(0x00) = GPIO_3(0x00) & 0xFFFFFFFC | 0x3; - GPIO_3(0x10) = GPIO_3(0x10) & 0xFFFFFFFC | 0x3; - GPIO_3(0x20) = GPIO_3(0x20) & 0xFFFFFFFE | 0x1; - - sleep(10000u); - - GPIO_3(0x20) = GPIO_3(0x20) & 0xFFFFFFFD | 0x2; - - sleep(10000); - - GPIO_6(0x04) = GPIO_6(0x04) & 0xFFFFFFF8 | 0x7; - GPIO_6(0x14) = GPIO_6(0x14) & 0xFFFFFFF8 | 0x7; - GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFD | 0x2; - - //Config display interface and display. - MIPI_CAL(0x60) = 0; - - exec_cfg((u32 *)CLOCK_BASE, _display_config_1, 4); - exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_2, 94); - exec_cfg((u32 *)DSI_BASE, _display_config_3, 60); - - sleep(10000); - - GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFB | 0x4; - - sleep(60000); - - DSI(_DSIREG(DSI_DSI_BTA_TIMING)) = 0x50204; - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x337; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; - _display_dsi_wait(250000, _DSIREG(DSI_DSI_TRIGGER), 3); - - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x406; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; - _display_dsi_wait(250000, _DSIREG(DSI_DSI_TRIGGER), 3); - - DSI(_DSIREG(DSI_HOST_DSI_CONTROL)) = 0x200B; - _display_dsi_wait(150000, _DSIREG(DSI_HOST_DSI_CONTROL), 8); - - sleep(5000); - - _display_ver = DSI(_DSIREG(DSI_DSI_RD_DATA)); - if (_display_ver == 0x10) - exec_cfg((u32 *)DSI_BASE, _display_config_4, 43); - - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x1105; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; - - sleep(180000); - - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x2905; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 0x2; - - sleep(20000); - - exec_cfg((u32 *)DSI_BASE, _display_config_5, 21); - exec_cfg((u32 *)CLOCK_BASE, _display_config_6, 3); - DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; - exec_cfg((u32 *)DSI_BASE, _display_config_7, 10); - - sleep(10000); - - exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_8, 6); - exec_cfg((u32 *)DSI_BASE, _display_config_9, 4); - exec_cfg((u32 *)MIPI_CAL_BASE, _display_config_10, 16); - - sleep(10000); - - exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_11, 113); -} - -void display_end() -{ - GPIO_6(0x24) &= 0xFFFFFFFE; - DSI(_DSIREG(DSI_DSI_VID_MODE_CONTROL)) = 1; - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x2805; - - u32 end = HOST1X(0x30A4) + 5; - while (HOST1X(0x30A4) < end) - ; - - DISPLAY_A(_DIREG(DC_CMD_STATE_ACCESS)) = 5; - DSI(_DSIREG(DSI_DSI_VID_MODE_CONTROL)) = 0; - - exec_cfg((u32 *)DISPLAY_A_BASE, _display_config_12, 17); - exec_cfg((u32 *)DSI_BASE, _display_config_13, 16); - - sleep(10000); - - if (_display_ver == 0x10) - exec_cfg((u32 *)DSI_BASE, _display_config_14, 22); - - DSI(_DSIREG(DSI_DSI_WR_DATA)) = 0x1005; - DSI(_DSIREG(DSI_DSI_TRIGGER)) = 2; - - sleep(50000); - - GPIO_6(0x24) &= 0xFFFFFFFB; - - sleep(10000); - - GPIO_3(0x20) &= 0xFFFFFFFD; - - sleep(10000); - - GPIO_3(0x20) = (GPIO_3(0x20) >> 1) << 1; - - sleep(10000); - - //Disable clocks. - CLOCK(0x308) = 0x1010000; - CLOCK(0x32C) = 0x1010000; - CLOCK(0x300) = 0x18000000; - CLOCK(0x324) = 0x18000000; - - DSI(_DSIREG(DSI_PAD_CONTROL)) = 0x10F010F; - DSI(_DSIREG(DSI_DSI_POWER_CONTROL)) = 0; - - GPIO_6(0x04) &= 0xFFFFFFFE; - - PINMUX_AUX(0x1FC) = PINMUX_AUX(0x1FC) & 0xFFFFFFEF | 0x10; - PINMUX_AUX(0x1FC) = (PINMUX_AUX(0x1FC) >> 2) << 2 | 1; -} - -void display_color_screen(u32 color) -{ - exec_cfg((u32 *)DISPLAY_A_BASE, cfg_display_one_color, 8); - - //Configure display to show single color. - DISPLAY_A(_DIREG(DC_WIN_AD_WIN_OPTIONS)) = 0; - DISPLAY_A(_DIREG(DC_WIN_BD_WIN_OPTIONS)) = 0; - DISPLAY_A(_DIREG(DC_WIN_CD_WIN_OPTIONS)) = 0; - DISPLAY_A(_DIREG(DC_DISP_BLEND_BACKGROUND_COLOR)) = color; - DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) = DISPLAY_A(_DIREG(DC_CMD_STATE_CONTROL)) & 0xFFFFFFFE | 1; - - sleep(35000); - - GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFE | 1; -} - -void display_enable_backlight(bool on) { - GPIO_6(0x24) = GPIO_6(0x24) & 0xFFFFFFFE | !!on; -} - - -u32 *display_init_framebuffer(void *address) -{ - static cfg_op_t conf[sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t)] = {0}; - if(conf[0].val == 0) { - for (u32 i = 0; i < sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t); i++) { - conf[i] = cfg_display_framebuffer[i]; - } - } - - u32 *lfb_addr = (u32 *)address; - - conf[19].val = (u32)address; - //This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). - exec_cfg((u32 *)DISPLAY_A_BASE, conf, 32); - - sleep(35000); - - return lfb_addr; -} diff --git a/fusee/fusee-secondary/src/hwinit/di.h b/fusee/fusee-secondary/src/hwinit/di.h deleted file mode 100644 index 9d482e072..000000000 --- a/fusee/fusee-secondary/src/hwinit/di.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _DI_H_ -#define _DI_H_ - -#include "types.h" -#include <stdbool.h> - -/*! Display registers. */ -#define _DIREG(reg) ((reg) * 4) -#define DC_CMD_DISPLAY_COMMAND 0x32 -#define DC_CMD_STATE_ACCESS 0x40 -#define DC_CMD_STATE_CONTROL 0x41 -#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 -#define DC_DISP_DISP_WIN_OPTIONS 0x402 -#define DC_DISP_DISP_CLOCK_CONTROL 0x42E -#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 -#define DC_WIN_AD_WIN_OPTIONS 0xB80 -#define DC_WIN_BD_WIN_OPTIONS 0xD80 -#define DC_WIN_CD_WIN_OPTIONS 0xF80 - -//The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). -#define DC_X_WIN_XD_WIN_OPTIONS 0x700 -#define DC_X_WIN_XD_COLOR_DEPTH 0x703 -#define DC_X_WIN_XD_POSITION 0x704 -#define DC_X_WIN_XD_SIZE 0x705 -#define DC_X_WIN_XD_PRESCALED_SIZE 0x706 -#define DC_X_WIN_XD_H_INITIAL_DDA 0x707 -#define DC_X_WIN_XD_V_INITIAL_DDA 0x708 -#define DC_X_WIN_XD_DDA_INCREMENT 0x709 -#define DC_X_WIN_XD_LINE_STRIDE 0x70A - -//The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). -#define DC_X_WINBUF_XD_START_ADDR 0x800 -#define DC_X_WINBUF_XD_ADDR_H_OFFSET 0x806 -#define DC_X_WINBUF_XD_ADDR_V_OFFSET 0x808 -#define DC_X_WINBUF_XD_SURFACE_KIND 0x80B - -/*! Display serial interface registers. */ -#define _DSIREG(reg) ((reg) * 4) -#define DSI_DSI_RD_DATA 0x9 -#define DSI_DSI_WR_DATA 0xA -#define DSI_DSI_POWER_CONTROL 0xB -#define DSI_HOST_DSI_CONTROL 0xF -#define DSI_DSI_TRIGGER 0x13 -#define DSI_DSI_BTA_TIMING 0x3F -#define DSI_PAD_CONTROL 0x4B -#define DSI_DSI_VID_MODE_CONTROL 0x4E - -void display_init(); -void display_end(); - -/*! Show one single color on the display. */ -void display_color_screen(u32 color); - -/*! Init display in full 1280x720 resolution (32bpp, line stride 768, framebuffer size = 1280*768*4 bytes). */ -u32 *display_init_framebuffer(void *address); - -/*! Enable or disable the backlight. Should only be called when the screen is completely set up, to avoid flickering. */ -void display_enable_backlight(bool on); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/di.inl b/fusee/fusee-secondary/src/hwinit/di.inl deleted file mode 100644 index b2e6d1533..000000000 --- a/fusee/fusee-secondary/src/hwinit/di.inl +++ /dev/null @@ -1,532 +0,0 @@ -//Clock config. -static const cfg_op_t _display_config_1[4] = { - {0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 - {0x34, 0x4830A001}, //CLK_RST_CONTROLLER_PLLD_BASE - {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 - {0x37, 0x2D0AAA} //CLK_RST_CONTROLLER_PLLD_MISC -}; - -//Display A config. -static const cfg_op_t _display_config_2[94] = { - {0x40, 0}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x43, 0x54}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x42, 0x10}, - {0x42, 0x20}, - {0x42, 0x40}, - {0x480, 0}, - {0x403, 0}, - {0x404, 0}, - {0x36, 0x50155}, - {1, 0x100}, - {0x28, 0x109}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF}, - {0x40, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x10}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x10}, - {0x42, 0x10}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x20}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x20}, - {0x42, 0x20}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x42, 0x40}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x40}, - {0x42, 0x40}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x430, 8}, - {0x42F, 0}, - {0x307, 0x1000000}, - {0x309, 0}, - {0x4E4, 0}, - {0x300, 0}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF}, - {0x42, 0x10}, - {0x716, 0x10000FF}, - {0x42, 0x20}, - {0x716, 0x10000FF}, - {0x42, 0x40}, - {0x716, 0x10000FF}, - {0x31, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x402, 0}, - {0x32, 0}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF} -}; - -//DSI config. -static const cfg_op_t _display_config_3[60] = { - {0xA, 0}, - {0xC, 0}, - {0xD, 0}, - {0xE, 0}, - {0x1B, 0}, - {0x1C, 0}, - {0x1D, 0}, - {0x1E, 0}, - {0x33, 0}, - {0x23, 0}, - {0x25, 0}, - {0x27, 0}, - {0x29, 0}, - {0x2B, 0}, - {0x2D, 0}, - {0x24, 0}, - {0x26, 0}, - {0x28, 0}, - {0x2A, 0}, - {0x2C, 0}, - {0x2E, 0}, - {0x10, 0}, - {0x4C, 0}, - {0x11, 0x18}, - {0x12, 0x1E0}, - {0x13, 0}, - {0x1A, 0}, - {0x34, 0}, - {0x35, 0}, - {0x36, 0}, - {0x37, 0}, - {0x4F, 0}, - {0x3C, 0x6070601}, - {0x3D, 0x40A0E05}, - {0x3E, 0x30109}, - {0x3F, 0x190A14}, - {0x44, 0x2000FFFF}, - {0x45, 0x7652000}, - {0x46, 0}, - {0x4B, 0}, - {DSI_DSI_POWER_CONTROL, 1}, - {DSI_DSI_POWER_CONTROL, 1}, - {DSI_DSI_POWER_CONTROL, 0}, - {DSI_DSI_POWER_CONTROL, 0}, - {0x4F, 0}, - {0x3C, 0x6070601}, - {0x3D, 0x40A0E05}, - {0x3E, 0x30118}, - {0x3F, 0x190A14}, - {0x44, 0x2000FFFF}, - {0x45, 0x13432000}, - {0x46, 0}, - {0xF, 0x102003}, - {0x10, 0x31}, - {DSI_DSI_POWER_CONTROL, 1}, - {DSI_DSI_POWER_CONTROL, 1}, - {0x12, 0x40}, - {0x13, 0}, - {0x14, 0}, - {0x1A, 0} -}; - -//DSI config (if ver == 0x10). -static const cfg_op_t _display_config_4[43] = { - {DSI_DSI_WR_DATA, 0x439}, - {DSI_DSI_WR_DATA, 0x9483FFB9}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0xBD15}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x1939}, - {DSI_DSI_WR_DATA, 0xAAAAAAD8}, - {DSI_DSI_WR_DATA, 0xAAAAAAEB}, - {DSI_DSI_WR_DATA, 0xAAEBAAAA}, - {DSI_DSI_WR_DATA, 0xAAAAAAAA}, - {DSI_DSI_WR_DATA, 0xAAAAAAEB}, - {DSI_DSI_WR_DATA, 0xAAEBAAAA}, - {DSI_DSI_WR_DATA, 0xAA}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x1BD15}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x2739}, - {DSI_DSI_WR_DATA, 0xFFFFFFD8}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFF}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x2BD15}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0xF39}, - {DSI_DSI_WR_DATA, 0xFFFFFFD8}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFFFF}, - {DSI_DSI_WR_DATA, 0xFFFFFF}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0xBD15}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x6D915}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x439}, - {DSI_DSI_WR_DATA, 0xB9}, - {DSI_DSI_TRIGGER, 2} -}; - -//DSI config. -static const cfg_op_t _display_config_5[21] = { - {0x4F, 0}, - {0x3C, 0x6070601}, - {0x3D, 0x40A0E05}, - {0x3E, 0x30172}, - {0x3F, 0x190A14}, - {0x44, 0x20000A40}, - {0x45, 0x5A2F2000}, - {0x46, 0}, - {0x23, 0x40000208}, - {0x27, 0x40000308}, - {0x2B, 0x40000308}, - {0x25, 0x40000308}, - {0x29, 0x3F3B2B08}, - {0x2A, 0x2CC}, - {0x2D, 0x3F3B2B08}, - {0x2E, 0x2CC}, - {0x34, 0xCE0000}, - {0x35, 0x87001A2}, - {0x36, 0x190}, - {0x37, 0x190}, - {0xF, 0}, -}; - -//Clock config. -static const cfg_op_t _display_config_6[3] = { - {0x34, 0x4810C001}, //CLK_RST_CONTROLLER_PLLD_BASE - {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 - {0x37, 0x2DFC00} //CLK_RST_CONTROLLER_PLLD_MISC -}; - -//DSI config. -static const cfg_op_t _display_config_7[10] = { - {0x13, 0}, - {0x10, 0}, - {0x11, 6}, - {0x12, 0x1E0}, - {DSI_DSI_POWER_CONTROL, 1}, - {0x10, 0x103032}, - {0xF, 0x33}, - {0x10, 0x103032}, - {0xF, 3}, - {0xF, 0x23} -}; - -//MIPI CAL config. -static const cfg_op_t _display_config_8[6] = { - {0x18, 0}, - {2, 0xF3F10000}, - {0x16, 1}, - {0x18, 0}, - {0x18, 0x10010}, - {0x17, 0x300} -}; - -//DSI config. -static const cfg_op_t _display_config_9[4] = { - {0x4F, 0}, - {0x50, 0}, - {0x51, 0x3333}, - {0x52, 0} -}; - -//MIPI CAL config. -static const cfg_op_t _display_config_10[16] = { - {0xE, 0x200200}, - {0xF, 0x200200}, - {0x19, 0x200002}, - {0x1A, 0x200002}, - {5, 0}, - {6, 0}, - {7, 0}, - {8, 0}, - {9, 0}, - {0xA, 0}, - {0x10, 0}, - {0x11, 0}, - {0x1A, 0}, - {0x1C, 0}, - {0x1D, 0}, - {0, 0x2A000001} -}; - -//Display A config. -static const cfg_op_t _display_config_11[113] = { - {0x40, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x10}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x10}, - {0x42, 0x10}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x20}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x20}, - {0x42, 0x20}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x42, 0x40}, - {0x70E, 0}, - {0x700, 0}, - {0x42, 0x40}, - {0x42, 0x40}, - {0x611, 0xF0}, - {0x612, 0x12A}, - {0x613, 0}, - {0x614, 0x198}, - {0x615, 0x39B}, - {0x616, 0x32F}, - {0x617, 0x204}, - {0x618, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x430, 8}, - {0x42F, 0}, - {0x307, 0x1000000}, - {0x309, 0}, - {0x4E4, 0}, - {0x300, 0}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF}, - {0x42, 0x10}, - {0x716, 0x10000FF}, - {0x42, 0x20}, - {0x716, 0x10000FF}, - {0x42, 0x40}, - {0x716, 0x10000FF}, - {0x31, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x402, 0}, - {0x32, 0}, - {DC_CMD_STATE_CONTROL, 0xF00}, - {DC_CMD_STATE_CONTROL, 0xF}, - {0x40, 0}, - {0x405, 0}, - {0x406, 0x10000}, - {0x407, 0x10048}, - {0x408, 0x90048}, - {0x409, 0x50002D0}, - {0x40A, 0xA0088}, - {0x431, 0x10001}, - {0x303, 0}, - {0x432, 5}, - {0x42F, 0}, - {0x42E, 0}, - {0x31, 0}, - {0x42, 0x10}, - {0x700, 0}, - {0x42, 0x20}, - {0x700, 0}, - {0x42, 0x40}, - {0x700, 0}, - {0x402, 0}, - {0x32, 0x20}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x40, 5}, - {0x40A, 0xA0088}, - {0x40, 0}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0, 0x301}, - {0, 0x301}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x40, 0}, - {0x42E, 4}, - {0x430, 8}, - {0x31, 0} -}; - -////Display A config. -static const cfg_op_t _display_config_12[17] = { - {0x40A, 0xA0088}, - {0x38, 0}, - {0x40, 0}, - {0x39, 0}, - {0x28, 0}, - {0x32, 0}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0, 0x301}, - {0, 0x301}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1}, - {0x36, 0}, - {DC_CMD_STATE_CONTROL, 0x100}, - {DC_CMD_STATE_CONTROL, 1} -}; - -//DSI config. -static const cfg_op_t _display_config_13[16] = { - {DSI_DSI_POWER_CONTROL, 0}, - {0x4F, 0}, - {0x3C, 0x6070601}, - {0x3D, 0x40A0E05}, - {0x3E, 0x30109}, - {0x3F, 0x190A14}, - {0x44, 0x2000FFFF}, - {0x45, 0x7652000}, - {0x46, 0}, - {0xF, 0x102003}, - {0x10, 0x31}, - {DSI_DSI_POWER_CONTROL, 1}, - {0x12, 0x40}, - {0x13, 0}, - {0x14, 0}, - {0x1A, 0} -}; - -//DSI config (if ver == 0x10). -static const cfg_op_t _display_config_14[22] = { - {DSI_DSI_WR_DATA, 0x439}, - {DSI_DSI_WR_DATA, 0x9483FFB9}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x2139}, - {DSI_DSI_WR_DATA, 0x191919D5}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19191919}, - {DSI_DSI_WR_DATA, 0x19}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0xB39}, - {DSI_DSI_WR_DATA, 0x4F0F41B1}, - {DSI_DSI_WR_DATA, 0xF179A433}, - {DSI_DSI_WR_DATA, 0x2D81}, - {DSI_DSI_TRIGGER, 2}, - {DSI_DSI_WR_DATA, 0x439}, - {DSI_DSI_WR_DATA, 0xB9}, - {DSI_DSI_TRIGGER, 2} -}; - -//Display A config. -static const cfg_op_t cfg_display_one_color[8] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x10}, //Enable window A. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x20}, //Enable window B. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x40}, //Enable window C. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_CMD_DISPLAY_COMMAND, 0x20} //DISPLAY_CTRL_MODE: continuous display. -}; - -//Display A config. -static const cfg_op_t cfg_display_framebuffer[32] = { - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x40}, //Enable window C. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x20}, //Enable window B. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_CMD_DISPLAY_WINDOW_HEADER, 0x10}, //Enable window A. - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_X_WIN_XD_COLOR_DEPTH, 0xD}, //T_A8B8G8R8 - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_X_WIN_XD_POSITION, 0}, //(0,0) - {DC_X_WIN_XD_H_INITIAL_DDA, 0}, - {DC_X_WIN_XD_V_INITIAL_DDA, 0}, - {DC_X_WIN_XD_PRESCALED_SIZE, 0x5000B40}, //Pre-scaled size: 1280x2880 bytes (= 0x500 vertical lines x 0xB40 bytes). - {DC_X_WIN_XD_DDA_INCREMENT, 0x10001000}, - {DC_X_WIN_XD_SIZE, 0x50002D0}, //Window size: 1280x720 (= 0x500 vertical lines x 0x2D0 horizontal pixels). - {DC_X_WIN_XD_LINE_STRIDE, 0x6000C00}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. - {0x702, 0}, - {DC_X_WINBUF_XD_SURFACE_KIND, 0}, //Regular surface. - {DC_X_WINBUF_XD_START_ADDR, 0xC0000000}, //Framebuffer address. - {DC_X_WINBUF_XD_ADDR_H_OFFSET, 0}, - {DC_X_WINBUF_XD_ADDR_V_OFFSET, 0}, - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_X_WIN_XD_WIN_OPTIONS, 0}, - {DC_DISP_DISP_WIN_OPTIONS, 0x20000000}, //DSI_ENABLE - {DC_X_WIN_XD_WIN_OPTIONS, 0x40000000}, //Enable window AD. - {DC_CMD_DISPLAY_COMMAND, 0x20}, //DISPLAY_CTRL_MODE: continuous display. - {DC_CMD_STATE_CONTROL, 0x300}, //General update; window A update. - {DC_CMD_STATE_CONTROL, 3} //General activation request; window A activation request. -}; diff --git a/fusee/fusee-secondary/src/hwinit/emc.h b/fusee/fusee-secondary/src/hwinit/emc.h deleted file mode 100644 index ce134c2fe..000000000 --- a/fusee/fusee-secondary/src/hwinit/emc.h +++ /dev/null @@ -1,665 +0,0 @@ -/* -* arch/arm/mach-tegra/tegra21_emc.h -* -* Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -* -*/ - -#ifndef _EMC_H_ -#define _EMC_H_ - -#define EMC_CONFIG_SAMPLE_DELAY 0x5f0 -#define EMC_CFG_UPDATE 0x5f4 -#define EMC_ADR_CFG 0x10 -#define EMC_REFCTRL 0x20 -#define EMC_PIN 0x24 -#define EMC_TIMING_CONTROL 0x28 -#define EMC_RC 0x2c -#define EMC_RFC 0x30 -#define EMC_RFCPB 0x590 -#define EMC_RAS 0x34 -#define EMC_RP 0x38 -#define EMC_R2W 0x3c -#define EMC_W2R 0x40 -#define EMC_R2P 0x44 -#define EMC_W2P 0x48 -#define EMC_CCDMW 0x5c0 -#define EMC_RD_RCD 0x4c -#define EMC_WR_RCD 0x50 -#define EMC_RRD 0x54 -#define EMC_REXT 0x58 -#define EMC_WDV 0x5c -#define EMC_QUSE 0x60 -#define EMC_QRST 0x64 -#define EMC_ISSUE_QRST 0x428 -#define EMC_QSAFE 0x68 -#define EMC_RDV 0x6c -#define EMC_REFRESH 0x70 -#define EMC_BURST_REFRESH_NUM 0x74 -#define EMC_PDEX2WR 0x78 -#define EMC_PDEX2RD 0x7c -#define EMC_PDEX2CKE 0x118 -#define EMC_PCHG2PDEN 0x80 -#define EMC_ACT2PDEN 0x84 -#define EMC_AR2PDEN 0x88 -#define EMC_RW2PDEN 0x8c -#define EMC_CKE2PDEN 0x11c -#define EMC_TXSR 0x90 -#define EMC_TCKE 0x94 -#define EMC_TFAW 0x98 -#define EMC_TRPAB 0x9c -#define EMC_TCLKSTABLE 0xa0 -#define EMC_TCLKSTOP 0xa4 -#define EMC_TREFBW 0xa8 -#define EMC_TPPD 0xac -#define EMC_PDEX2MRR 0xb4 -#define EMC_ODT_WRITE 0xb0 -#define EMC_WEXT 0xb8 -#define EMC_RFC_SLR 0xc0 -#define EMC_MRS_WAIT_CNT2 0xc4 -#define EMC_MRS_WAIT_CNT 0xc8 -#define EMC_MRS 0xcc -#define EMC_EMRS 0xd0 -#define EMC_REF 0xd4 -#define EMC_PRE 0xd8 -#define EMC_NOP 0xdc -#define EMC_SELF_REF 0xe0 -#define EMC_DPD 0xe4 -#define EMC_MRW 0xe8 -#define EMC_MRR 0xec -#define EMC_CMDQ 0xf0 -#define EMC_MC2EMCQ 0xf4 -#define EMC_FBIO_SPARE 0x100 -#define EMC_FBIO_CFG5 0x104 -#define EMC_CFG_RSV 0x120 -#define EMC_ACPD_CONTROL 0x124 -#define EMC_MPC 0x128 -#define EMC_EMRS2 0x12c -#define EMC_EMRS3 0x130 -#define EMC_MRW2 0x134 -#define EMC_MRW3 0x138 -#define EMC_MRW4 0x13c -#define EMC_MRW5 0x4a0 -#define EMC_MRW6 0x4a4 -#define EMC_MRW7 0x4a8 -#define EMC_MRW8 0x4ac -#define EMC_MRW9 0x4b0 -#define EMC_MRW10 0x4b4 -#define EMC_MRW11 0x4b8 -#define EMC_MRW12 0x4bc -#define EMC_MRW13 0x4c0 -#define EMC_MRW14 0x4c4 -#define EMC_MRW15 0x4d0 -#define EMC_CFG_SYNC 0x4d4 -#define EMC_CLKEN_OVERRIDE 0x140 -#define EMC_R2R 0x144 -#define EMC_W2W 0x148 -#define EMC_EINPUT 0x14c -#define EMC_EINPUT_DURATION 0x150 -#define EMC_PUTERM_EXTRA 0x154 -#define EMC_TCKESR 0x158 -#define EMC_TPD 0x15c -#define EMC_STAT_CONTROL 0x160 -#define EMC_STAT_STATUS 0x164 -#define EMC_STAT_DRAM_CLOCK_LIMIT_LO 0x19c -#define EMC_STAT_DRAM_CLOCK_LIMIT_HI 0x1a0 -#define EMC_STAT_DRAM_CLOCKS_LO 0x1a4 -#define EMC_STAT_DRAM_CLOCKS_HI 0x1a8 -#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_LO 0x1ac -#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_HI 0x1b0 -#define EMC_STAT_DRAM_DEV0_READ_CNT_LO 0x1b4 -#define EMC_STAT_DRAM_DEV0_READ_CNT_HI 0x1b8 -#define EMC_STAT_DRAM_DEV0_READ8_CNT_LO 0x1bc -#define EMC_STAT_DRAM_DEV0_READ8_CNT_HI 0x1c0 -#define EMC_STAT_DRAM_DEV0_WRITE_CNT_LO 0x1c4 -#define EMC_STAT_DRAM_DEV0_WRITE_CNT_HI 0x1c8 -#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_LO 0x1cc -#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_HI 0x1d0 -#define EMC_STAT_DRAM_DEV0_REF_CNT_LO 0x1d4 -#define EMC_STAT_DRAM_DEV0_REF_CNT_HI 0x1d8 -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1dc -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e0 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1e4 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e8 -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1ec -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f0 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1f4 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f8 -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x1fc -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x200 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x204 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x208 -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x20c -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x210 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x214 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x218 -#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_LO 0x21c -#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_HI 0x220 -#define EMC_STAT_DRAM_DEV0_DSR 0x224 -#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_LO 0x228 -#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_HI 0x22c -#define EMC_STAT_DRAM_DEV1_READ_CNT_LO 0x230 -#define EMC_STAT_DRAM_DEV1_READ_CNT_HI 0x234 -#define EMC_STAT_DRAM_DEV1_READ8_CNT_LO 0x238 -#define EMC_STAT_DRAM_DEV1_READ8_CNT_HI 0x23c -#define EMC_STAT_DRAM_DEV1_WRITE_CNT_LO 0x240 -#define EMC_STAT_DRAM_DEV1_WRITE_CNT_HI 0x244 -#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_LO 0x248 -#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_HI 0x24c -#define EMC_STAT_DRAM_DEV1_REF_CNT_LO 0x250 -#define EMC_STAT_DRAM_DEV1_REF_CNT_HI 0x254 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x258 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x25c -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x260 -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x264 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x268 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x26c -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x270 -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x274 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x278 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x27c -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x280 -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x284 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x288 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x28c -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x290 -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x294 -#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_LO 0x298 -#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_HI 0x29c -#define EMC_STAT_DRAM_DEV1_DSR 0x2a0 -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc8c -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc90 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc94 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc98 -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xc9c -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca0 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xca4 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca8 -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcac -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb0 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcb4 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb8 -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcbc -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc0 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcc4 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc8 -#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_LO 0xccc -#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_HI 0xcd0 -#define EMC_STAT_DRAM_IO_DSR 0xcd4 -#define EMC_AUTO_CAL_CONFIG 0x2a4 -#define EMC_AUTO_CAL_CONFIG2 0x458 -#define EMC_AUTO_CAL_CONFIG3 0x45c -#define EMC_AUTO_CAL_CONFIG4 0x5b0 -#define EMC_AUTO_CAL_CONFIG5 0x5b4 -#define EMC_AUTO_CAL_CONFIG6 0x5cc -#define EMC_AUTO_CAL_CONFIG7 0x574 -#define EMC_AUTO_CAL_CONFIG8 0x2dc -#define EMC_AUTO_CAL_VREF_SEL_0 0x2f8 -#define EMC_AUTO_CAL_VREF_SEL_1 0x300 -#define EMC_AUTO_CAL_INTERVAL 0x2a8 -#define EMC_AUTO_CAL_STATUS 0x2ac -#define EMC_AUTO_CAL_STATUS2 0x3d4 -#define EMC_AUTO_CAL_CHANNEL 0x464 -#define EMC_PMACRO_RX_TERM 0xc48 -#define EMC_PMACRO_DQ_TX_DRV 0xc70 -#define EMC_PMACRO_CA_TX_DRV 0xc74 -#define EMC_PMACRO_CMD_TX_DRV 0xc4c -#define EMC_PMACRO_AUTOCAL_CFG_0 0x700 -#define EMC_PMACRO_AUTOCAL_CFG_1 0x704 -#define EMC_PMACRO_AUTOCAL_CFG_2 0x708 -#define EMC_PMACRO_AUTOCAL_CFG_COMMON 0xc78 -#define EMC_PMACRO_ZCTRL 0xc44 -#define EMC_XM2COMPPADCTRL 0x30c -#define EMC_XM2COMPPADCTRL2 0x578 -#define EMC_XM2COMPPADCTRL3 0x2f4 -#define EMC_COMP_PAD_SW_CTRL 0x57c -#define EMC_REQ_CTRL 0x2b0 -#define EMC_EMC_STATUS 0x2b4 -#define EMC_CFG_2 0x2b8 -#define EMC_CFG_DIG_DLL 0x2bc -#define EMC_CFG_DIG_DLL_PERIOD 0x2c0 -#define EMC_DIG_DLL_STATUS 0x2c4 -#define EMC_CFG_DIG_DLL_1 0x2c8 -#define EMC_RDV_MASK 0x2cc -#define EMC_WDV_MASK 0x2d0 -#define EMC_RDV_EARLY_MASK 0x2d4 -#define EMC_RDV_EARLY 0x2d8 -#define EMC_WDV_CHK 0x4e0 -#define EMC_ZCAL_INTERVAL 0x2e0 -#define EMC_ZCAL_WAIT_CNT 0x2e4 -#define EMC_ZCAL_MRW_CMD 0x2e8 -#define EMC_ZQ_CAL 0x2ec -#define EMC_SCRATCH0 0x324 -#define EMC_STALL_THEN_EXE_BEFORE_CLKCHANGE 0x3c8 -#define EMC_STALL_THEN_EXE_AFTER_CLKCHANGE 0x3cc -#define EMC_UNSTALL_RW_AFTER_CLKCHANGE 0x3d0 -#define EMC_FDPD_CTRL_CMD_NO_RAMP 0x4d8 -#define EMC_SEL_DPD_CTRL 0x3d8 -#define EMC_FDPD_CTRL_DQ 0x310 -#define EMC_FDPD_CTRL_CMD 0x314 -#define EMC_PRE_REFRESH_REQ_CNT 0x3dc -#define EMC_REFCTRL2 0x580 -#define EMC_FBIO_CFG7 0x584 -#define EMC_DATA_BRLSHFT_0 0x588 -#define EMC_DATA_BRLSHFT_1 0x58c -#define EMC_DQS_BRLSHFT_0 0x594 -#define EMC_DQS_BRLSHFT_1 0x598 -#define EMC_CMD_BRLSHFT_0 0x59c -#define EMC_CMD_BRLSHFT_1 0x5a0 -#define EMC_CMD_BRLSHFT_2 0x5a4 -#define EMC_CMD_BRLSHFT_3 0x5a8 -#define EMC_QUSE_BRLSHFT_0 0x5ac -#define EMC_QUSE_BRLSHFT_1 0x5b8 -#define EMC_QUSE_BRLSHFT_2 0x5bc -#define EMC_QUSE_BRLSHFT_3 0x5c4 -#define EMC_FBIO_CFG8 0x5c8 -#define EMC_CMD_MAPPING_CMD0_0 0x380 -#define EMC_CMD_MAPPING_CMD0_1 0x384 -#define EMC_CMD_MAPPING_CMD0_2 0x388 -#define EMC_CMD_MAPPING_CMD1_0 0x38c -#define EMC_CMD_MAPPING_CMD1_1 0x390 -#define EMC_CMD_MAPPING_CMD1_2 0x394 -#define EMC_CMD_MAPPING_CMD2_0 0x398 -#define EMC_CMD_MAPPING_CMD2_1 0x39c -#define EMC_CMD_MAPPING_CMD2_2 0x3a0 -#define EMC_CMD_MAPPING_CMD3_0 0x3a4 -#define EMC_CMD_MAPPING_CMD3_1 0x3a8 -#define EMC_CMD_MAPPING_CMD3_2 0x3ac -#define EMC_CMD_MAPPING_BYTE 0x3b0 -#define EMC_DYN_SELF_REF_CONTROL 0x3e0 -#define EMC_TXSRDLL 0x3e4 -#define EMC_CCFIFO_ADDR 0x3e8 -#define EMC_CCFIFO_DATA 0x3ec -#define EMC_CCFIFO_STATUS 0x3f0 -#define EMC_SWIZZLE_RANK0_BYTE0 0x404 -#define EMC_SWIZZLE_RANK0_BYTE1 0x408 -#define EMC_SWIZZLE_RANK0_BYTE2 0x40c -#define EMC_SWIZZLE_RANK0_BYTE3 0x410 -#define EMC_SWIZZLE_RANK1_BYTE0 0x418 -#define EMC_SWIZZLE_RANK1_BYTE1 0x41c -#define EMC_SWIZZLE_RANK1_BYTE2 0x420 -#define EMC_SWIZZLE_RANK1_BYTE3 0x424 -#define EMC_TR_TIMING_0 0x3b4 -#define EMC_TR_CTRL_0 0x3b8 -#define EMC_TR_CTRL_1 0x3bc -#define EMC_TR_DVFS 0x460 -#define EMC_SWITCH_BACK_CTRL 0x3c0 -#define EMC_TR_RDV 0x3c4 -#define EMC_TR_QPOP 0x3f4 -#define EMC_TR_RDV_MASK 0x3f8 -#define EMC_TR_QSAFE 0x3fc -#define EMC_TR_QRST 0x400 -#define EMC_IBDLY 0x468 -#define EMC_OBDLY 0x46c -#define EMC_TXDSRVTTGEN 0x480 -#define EMC_WE_DURATION 0x48c -#define EMC_WS_DURATION 0x490 -#define EMC_WEV 0x494 -#define EMC_WSV 0x498 -#define EMC_CFG_3 0x49c -#define EMC_CFG_PIPE_2 0x554 -#define EMC_CFG_PIPE_CLK 0x558 -#define EMC_CFG_PIPE_1 0x55c -#define EMC_CFG_PIPE 0x560 -#define EMC_QPOP 0x564 -#define EMC_QUSE_WIDTH 0x568 -#define EMC_PUTERM_WIDTH 0x56c -#define EMC_PROTOBIST_CONFIG_ADR_1 0x5d0 -#define EMC_PROTOBIST_CONFIG_ADR_2 0x5d4 -#define EMC_PROTOBIST_MISC 0x5d8 -#define EMC_PROTOBIST_WDATA_LOWER 0x5dc -#define EMC_PROTOBIST_WDATA_UPPER 0x5e0 -#define EMC_PROTOBIST_RDATA 0x5ec -#define EMC_DLL_CFG_0 0x5e4 -#define EMC_DLL_CFG_1 0x5e8 -#define EMC_TRAINING_CMD 0xe00 -#define EMC_TRAINING_CTRL 0xe04 -#define EMC_TRAINING_STATUS 0xe08 -#define EMC_TRAINING_QUSE_CORS_CTRL 0xe0c -#define EMC_TRAINING_QUSE_FINE_CTRL 0xe10 -#define EMC_TRAINING_QUSE_CTRL_MISC 0xe14 -#define EMC_TRAINING_WRITE_FINE_CTRL 0xe18 -#define EMC_TRAINING_WRITE_CTRL_MISC 0xe1c -#define EMC_TRAINING_WRITE_VREF_CTRL 0xe20 -#define EMC_TRAINING_READ_FINE_CTRL 0xe24 -#define EMC_TRAINING_READ_CTRL_MISC 0xe28 -#define EMC_TRAINING_READ_VREF_CTRL 0xe2c -#define EMC_TRAINING_CA_FINE_CTRL 0xe30 -#define EMC_TRAINING_CA_CTRL_MISC 0xe34 -#define EMC_TRAINING_CA_CTRL_MISC1 0xe38 -#define EMC_TRAINING_CA_VREF_CTRL 0xe3c -#define EMC_TRAINING_CA_TADR_CTRL 0xe40 -#define EMC_TRAINING_SETTLE 0xe44 -#define EMC_TRAINING_DEBUG_CTRL 0xe48 -#define EMC_TRAINING_DEBUG_DQ0 0xe4c -#define EMC_TRAINING_DEBUG_DQ1 0xe50 -#define EMC_TRAINING_DEBUG_DQ2 0xe54 -#define EMC_TRAINING_DEBUG_DQ3 0xe58 -#define EMC_TRAINING_MPC 0xe5c -#define EMC_TRAINING_PATRAM_CTRL 0xe60 -#define EMC_TRAINING_PATRAM_DQ 0xe64 -#define EMC_TRAINING_PATRAM_DMI 0xe68 -#define EMC_TRAINING_VREF_SETTLE 0xe6c -#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE0 0xe70 -#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE1 0xe74 -#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE2 0xe78 -#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE3 0xe7c -#define EMC_TRAINING_RW_EYE_CENTER_IB_MISC 0xe80 -#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE0 0xe84 -#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE1 0xe88 -#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE2 0xe8c -#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE3 0xe90 -#define EMC_TRAINING_RW_EYE_CENTER_OB_MISC 0xe94 -#define EMC_TRAINING_RW_OFFSET_IB_BYTE0 0xe98 -#define EMC_TRAINING_RW_OFFSET_IB_BYTE1 0xe9c -#define EMC_TRAINING_RW_OFFSET_IB_BYTE2 0xea0 -#define EMC_TRAINING_RW_OFFSET_IB_BYTE3 0xea4 -#define EMC_TRAINING_RW_OFFSET_IB_MISC 0xea8 -#define EMC_TRAINING_RW_OFFSET_OB_BYTE0 0xeac -#define EMC_TRAINING_RW_OFFSET_OB_BYTE1 0xeb0 -#define EMC_TRAINING_RW_OFFSET_OB_BYTE2 0xeb4 -#define EMC_TRAINING_RW_OFFSET_OB_BYTE3 0xeb8 -#define EMC_TRAINING_RW_OFFSET_OB_MISC 0xebc -#define EMC_TRAINING_OPT_CA_VREF 0xec0 -#define EMC_TRAINING_OPT_DQ_OB_VREF 0xec4 -#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK0 0xec8 -#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK1 0xecc -#define EMC_TRAINING_QUSE_VREF_CTRL 0xed0 -#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4 -#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8 -#define EMC_TRAINING_DRAMC_TIMING 0xedc -#define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600 -#define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604 -#define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608 -#define EMC_PMACRO_QUSE_DDLL_RANK0_3 0x60c -#define EMC_PMACRO_QUSE_DDLL_RANK0_4 0x610 -#define EMC_PMACRO_QUSE_DDLL_RANK0_5 0x614 -#define EMC_PMACRO_QUSE_DDLL_RANK1_0 0x620 -#define EMC_PMACRO_QUSE_DDLL_RANK1_1 0x624 -#define EMC_PMACRO_QUSE_DDLL_RANK1_2 0x628 -#define EMC_PMACRO_QUSE_DDLL_RANK1_3 0x62c -#define EMC_PMACRO_QUSE_DDLL_RANK1_4 0x630 -#define EMC_PMACRO_QUSE_DDLL_RANK1_5 0x634 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 0x640 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 0x644 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 0x648 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 0x64c -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4 0x650 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5 0x654 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 0x660 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 0x664 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 0x668 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 0x66c -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4 0x670 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5 0x674 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0 0x680 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1 0x684 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2 0x688 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3 0x68c -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4 0x690 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5 0x694 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0 0x6a0 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1 0x6a4 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2 0x6a8 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3 0x6ac -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4 0x6b0 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5 0x6b4 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0 0x6c0 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1 0x6c4 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2 0x6c8 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3 0x6cc -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_4 0x6d0 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_5 0x6d4 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0 0x6e0 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1 0x6e4 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2 0x6e8 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3 0x6ec -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_4 0x6f0 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_5 0x6f4 -#define EMC_PMACRO_TX_PWRD_0 0x720 -#define EMC_PMACRO_TX_PWRD_1 0x724 -#define EMC_PMACRO_TX_PWRD_2 0x728 -#define EMC_PMACRO_TX_PWRD_3 0x72c -#define EMC_PMACRO_TX_PWRD_4 0x730 -#define EMC_PMACRO_TX_PWRD_5 0x734 -#define EMC_PMACRO_TX_SEL_CLK_SRC_0 0x740 -#define EMC_PMACRO_TX_SEL_CLK_SRC_1 0x744 -#define EMC_PMACRO_TX_SEL_CLK_SRC_3 0x74c -#define EMC_PMACRO_TX_SEL_CLK_SRC_2 0x748 -#define EMC_PMACRO_TX_SEL_CLK_SRC_4 0x750 -#define EMC_PMACRO_TX_SEL_CLK_SRC_5 0x754 -#define EMC_PMACRO_DDLL_BYPASS 0x760 -#define EMC_PMACRO_DDLL_PWRD_0 0x770 -#define EMC_PMACRO_DDLL_PWRD_1 0x774 -#define EMC_PMACRO_DDLL_PWRD_2 0x778 -#define EMC_PMACRO_CMD_CTRL_0 0x780 -#define EMC_PMACRO_CMD_CTRL_1 0x784 -#define EMC_PMACRO_CMD_CTRL_2 0x788 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0x800 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0x804 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0x808 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3 0x80c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0x810 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0x814 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0x818 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3 0x81c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0x820 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0x824 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0x828 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3 0x82c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0x830 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0x834 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0x838 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3 0x83c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0x840 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0x844 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0x848 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3 0x84c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0x850 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0x854 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0x858 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3 0x85c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0x860 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0x864 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0x868 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3 0x86c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0x870 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0x874 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0x878 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3 0x87c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0 0x880 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1 0x884 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2 0x888 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3 0x88c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0 0x890 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1 0x894 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2 0x898 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3 0x89c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0 0x8a0 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1 0x8a4 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2 0x8a8 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3 0x8ac -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0 0x8b0 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1 0x8b4 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2 0x8b8 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3 0x8bc -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0x900 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0x904 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0x908 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3 0x90c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0x910 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0x914 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0x918 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3 0x91c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0x920 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0x924 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0x928 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3 0x92c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0x930 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0x934 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0x938 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3 0x93c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0x940 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0x944 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0x948 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3 0x94c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0x950 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0x954 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0x958 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3 0x95c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0x960 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0x964 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0x968 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3 0x96c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0x970 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0x974 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0x978 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3 0x97c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0 0x980 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1 0x984 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2 0x988 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3 0x98c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0 0x990 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1 0x994 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2 0x998 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3 0x99c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0 0x9a0 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1 0x9a4 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2 0x9a8 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3 0x9ac -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0 0x9b0 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1 0x9b4 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2 0x9b8 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3 0x9bc -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0xa00 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0xa04 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0xa08 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0xa10 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0xa14 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0xa18 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0xa20 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0xa24 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0xa28 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0xa30 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0xa34 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0xa38 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0xa40 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0xa44 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0xa48 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0xa50 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0xa54 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0xa58 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0xa60 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0xa64 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0xa68 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0xa70 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0xa74 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0xa78 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_0 0xa80 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_1 0xa84 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_2 0xa88 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_0 0xa90 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_1 0xa94 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_2 0xa98 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_0 0xaa0 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_1 0xaa4 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_2 0xaa8 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_0 0xab0 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_1 0xab4 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_2 0xab8 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0xb00 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0xb04 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0xb08 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0xb10 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0xb14 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0xb18 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0xb20 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0xb24 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0xb28 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0xb30 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0xb34 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0xb38 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0xb40 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0xb44 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0xb48 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0xb50 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0xb54 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0xb58 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0xb60 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0xb64 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0xb68 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0xb70 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0xb74 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0xb78 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_0 0xb80 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_1 0xb84 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_2 0xb88 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_0 0xb90 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_1 0xb94 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_2 0xb98 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_0 0xba0 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_1 0xba4 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_2 0xba8 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_0 0xbb0 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_1 0xbb4 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_2 0xbb8 -#define EMC_PMACRO_IB_VREF_DQ_0 0xbe0 -#define EMC_PMACRO_IB_VREF_DQ_1 0xbe4 -#define EMC_PMACRO_IB_VREF_DQ_2 0xbe8 -#define EMC_PMACRO_IB_VREF_DQS_0 0xbf0 -#define EMC_PMACRO_IB_VREF_DQS_1 0xbf4 -#define EMC_PMACRO_IB_VREF_DQS_2 0xbf8 -#define EMC_PMACRO_IB_RXRT 0xcf4 -#define EMC_PMACRO_DDLL_LONG_CMD_0 0xc00 -#define EMC_PMACRO_DDLL_LONG_CMD_1 0xc04 -#define EMC_PMACRO_DDLL_LONG_CMD_2 0xc08 -#define EMC_PMACRO_DDLL_LONG_CMD_3 0xc0c -#define EMC_PMACRO_DDLL_LONG_CMD_4 0xc10 -#define EMC_PMACRO_DDLL_LONG_CMD_5 0xc14 -#define EMC_PMACRO_DDLL_SHORT_CMD_0 0xc20 -#define EMC_PMACRO_DDLL_SHORT_CMD_1 0xc24 -#define EMC_PMACRO_DDLL_SHORT_CMD_2 0xc28 -#define EMC_PMACRO_CFG_PM_GLOBAL_0 0xc30 -#define EMC_PMACRO_VTTGEN_CTRL_0 0xc34 -#define EMC_PMACRO_VTTGEN_CTRL_1 0xc38 -#define EMC_PMACRO_VTTGEN_CTRL_2 0xcf0 -#define EMC_PMACRO_BG_BIAS_CTRL_0 0xc3c -#define EMC_PMACRO_PAD_CFG_CTRL 0xc40 -#define EMC_PMACRO_CMD_PAD_RX_CTRL 0xc50 -#define EMC_PMACRO_DATA_PAD_RX_CTRL 0xc54 -#define EMC_PMACRO_CMD_RX_TERM_MODE 0xc58 -#define EMC_PMACRO_DATA_RX_TERM_MODE 0xc5c -#define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60 -#define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64 -#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68 -#define EMC_PMACRO_BRICK_MAPPING_0 0xc80 -#define EMC_PMACRO_BRICK_MAPPING_1 0xc84 -#define EMC_PMACRO_BRICK_MAPPING_2 0xc88 -#define EMC_PMACRO_DDLLCAL_CAL 0xce0 -#define EMC_PMACRO_DDLL_OFFSET 0xce4 -#define EMC_PMACRO_DDLL_PERIODIC_OFFSET 0xce8 -#define EMC_PMACRO_BRICK_CTRL_RFU1 0x330 -#define EMC_PMACRO_BRICK_CTRL_RFU2 0x334 -#define EMC_PMACRO_CMD_BRICK_CTRL_FDPD 0x318 -#define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c -#define EMC_PMACRO_TRAINING_CTRL_0 0xcf8 -#define EMC_PMACRO_TRAINING_CTRL_1 0xcfc -#define EMC_PMC_SCRATCH1 0x440 -#define EMC_PMC_SCRATCH2 0x444 -#define EMC_PMC_SCRATCH3 0x448 - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/fuse.h b/fusee/fusee-secondary/src/hwinit/fuse.h deleted file mode 100644 index 1f19f466f..000000000 --- a/fusee/fusee-secondary/src/hwinit/fuse.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _FUSE_H_ -#define _FUSE_H_ - -#include "types.h" - -/*! Fuse registers. */ -#define FUSE_CTRL 0x0 -#define FUSE_ADDR 0x4 -#define FUSE_RDATA 0x8 -#define FUSE_WDATA 0xC -#define FUSE_TIME_RD1 0x10 -#define FUSE_TIME_RD2 0x14 -#define FUSE_TIME_PGM1 0x18 -#define FUSE_TIME_PGM2 0x1C -#define FUSE_PRIV2INTFC 0x20 -#define FUSE_FUSEBYPASS 0x24 -#define FUSE_PRIVATEKEYDISABLE 0x28 -#define FUSE_DISABLEREGPROGRAM 0x2C -#define FUSE_WRITE_ACCESS_SW 0x30 -#define FUSE_PWR_GOOD_SW 0x34 - -/*! Fuse cache registers. */ -#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) - -void fuse_disable_program(); -u32 fuse_read_odm(u32 idx); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/hwinit.c b/fusee/fusee-secondary/src/hwinit/hwinit.c deleted file mode 100644 index 467efdee5..000000000 --- a/fusee/fusee-secondary/src/hwinit/hwinit.c +++ /dev/null @@ -1,280 +0,0 @@ -#include "clock.h" -#include "uart.h" -#include "i2c.h" -#include "sdram.h" -#include "di.h" -#include "mc.h" -#include "t210.h" -#include "pmc.h" -#include "pinmux.h" -#include "fuse.h" -#include "util.h" - -void config_oscillators() -{ - CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3 | 4; - SYSCTR0(SYSCTR0_CNTFID0) = 19200000; - TMR(0x14) = 0x45F; - CLOCK(CLK_RST_CONTROLLER_OSC_CTRL) = 0x50000071; - PMC(APBDEV_PMC_OSC_EDPD_OVER) = PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFFFFF81 | 0xE; - PMC(APBDEV_PMC_OSC_EDPD_OVER) = PMC(APBDEV_PMC_OSC_EDPD_OVER) & 0xFFBFFFFF | 0x400000; - PMC(APBDEV_PMC_CNTRL2) = PMC(APBDEV_PMC_CNTRL2) & 0xFFFFEFFF | 0x1000; - PMC(APBDEV_PMC_SCRATCH188) = PMC(APBDEV_PMC_SCRATCH188) & 0xFCFFFFFF | 0x2000000; - CLOCK(CLK_RST_CONTROLLER_PLLMB_BASE) &= 0xBFFFFFFF; - PMC(APBDEV_PMC_TSC_MULT) = PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000 | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz) - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; - CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; - CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; -} - -void config_gpios() -{ - PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0; - PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0; - - PINMUX_AUX(PINMUX_AUX_GPIO_PE6) = 0x40; - PINMUX_AUX(PINMUX_AUX_GPIO_PH6) = 0x40; - - GPIO_2(0x8) = GPIO_2(0x8) & 0xFFFFFFFE | 1; - GPIO_1(0xC) = GPIO_1(0xC) & 0xFFFFFFFD | 2; - GPIO_2(0x0) = GPIO_2(0x0) & 0xFFFFFFBF | 0x40; - GPIO_2(0xC) = GPIO_2(0xC) & 0xFFFFFFBF | 0x40; - GPIO_2(0x18) &= 0xFFFFFFFE; - GPIO_1(0x1C) &= 0xFFFFFFFD; - GPIO_2(0x10) &= 0xFFFFFFBF; - GPIO_2(0x1C) &= 0xFFFFFFBF; - - pinmux_config_i2c(I2C_1); - pinmux_config_i2c(I2C_5); - pinmux_config_uart(UART_A); - - GPIO_6(0xC) = GPIO_6(0xC) & 0xFFFFFFBF | 0x40; - GPIO_6(0xC) = GPIO_6(0xC) & 0xFFFFFF7F | 0x80; - GPIO_6(0x1C) &= 0xFFFFFFBF; - GPIO_6(0x1C) &= 0xFFFFFF7F; -} - -void config_pmc_scratch() -{ - PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; - PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; - PMC(APBDEV_PMC_SECURE_SCRATCH21) |= 0x10; -} - -void mc_config_tsec_carveout(u32 bom, u32 size1mb, int lock) -{ - MC(0x670) = 0x90000000; - MC(0x674) = 1; - if (lock) - MC(0x678) = 1; -} - -void mc_config_carveout() -{ - *(vu32 *)0x8005FFFC = 0xC0EDBBCC; - MC(0x984) = 1; - MC(0x988) = 0; - MC(0x648) = 0; - MC(0x64C) = 0; - MC(0x650) = 1; - - //Official code disables and locks the carveout here. - //mc_config_tsec_carveout(0, 0, 1); - - MC(0x9A0) = 0; - MC(0x9A4) = 0; - MC(0x9A8) = 0; - MC(0x9AC) = 1; - MC(0xC0C) = 0; - MC(0xC10) = 0; - MC(0xC14) = 0; - MC(0xC18) = 0; - MC(0xC1C) = 0; - MC(0xC20) = 0; - MC(0xC24) = 0; - MC(0xC28) = 0; - MC(0xC2C) = 0; - MC(0xC30) = 0; - MC(0xC34) = 0; - MC(0xC38) = 0; - MC(0xC3C) = 0; - MC(0xC08) = 0x4000006; - MC(0xC5C) = 0x80020000; - MC(0xC60) = 0; - MC(0xC64) = 2; - MC(0xC68) = 0; - MC(0xC6C) = 0; - MC(0xC70) = 0x3000000; - MC(0xC74) = 0; - MC(0xC78) = 0x300; - MC(0xC7C) = 0; - MC(0xC80) = 0; - MC(0xC84) = 0; - MC(0xC88) = 0; - MC(0xC8C) = 0; - MC(0xC58) = 0x440167E; - MC(0xCAC) = 0; - MC(0xCB0) = 0; - MC(0xCB4) = 0; - MC(0xCB8) = 0; - MC(0xCBC) = 0; - MC(0xCC0) = 0x3000000; - MC(0xCC4) = 0; - MC(0xCC8) = 0x300; - MC(0xCCC) = 0; - MC(0xCD0) = 0; - MC(0xCD4) = 0; - MC(0xCD8) = 0; - MC(0xCDC) = 0; - MC(0xCA8) = 0x4401E7E; - MC(0xCFC) = 0; - MC(0xD00) = 0; - MC(0xD04) = 0; - MC(0xD08) = 0; - MC(0xD0C) = 0; - MC(0xD10) = 0; - MC(0xD14) = 0; - MC(0xD18) = 0; - MC(0xD1C) = 0; - MC(0xD20) = 0; - MC(0xD24) = 0; - MC(0xD28) = 0; - MC(0xD2C) = 0; - MC(0xCF8) = 0x8F; - MC(0xD4C) = 0; - MC(0xD50) = 0; - MC(0xD54) = 0; - MC(0xD58) = 0; - MC(0xD5C) = 0; - MC(0xD60) = 0; - MC(0xD64) = 0; - MC(0xD68) = 0; - MC(0xD6C) = 0; - MC(0xD70) = 0; - MC(0xD74) = 0; - MC(0xD78) = 0; - MC(0xD7C) = 0; - MC(0xD48) = 0x8F; -} - -void enable_clocks() -{ - CLOCK(0x410) = (CLOCK(0x410) | 0x8000) & 0xFFFFBFFF; - CLOCK(0xD0) |= 0x40800000u; - CLOCK(0x2AC) = 64; - CLOCK(0x294) = 0x40000; - CLOCK(0x304) = 0x18000000; - sleep(2); - - I2S(0x0A0) |= 0x400; - I2S(0x088) &= 0xFFFFFFFE; - I2S(0x1A0) |= 0x400; - I2S(0x188) &= 0xFFFFFFFE; - I2S(0x2A0) |= 0x400; - I2S(0x288) &= 0xFFFFFFFE; - I2S(0x3A0) |= 0x400; - I2S(0x388) &= 0xFFFFFFFE; - I2S(0x4A0) |= 0x400; - I2S(0x488) &= 0xFFFFFFFE; - DISPLAY_A(0xCF8) |= 4; - VIC(0x8C) = 0xFFFFFFFF; - sleep(2); - - CLOCK(0x2A8) = 0x40; - CLOCK(0x300) = 0x18000000; - CLOCK(0x290) = 0x40000; - CLOCK(0x14) = 0xC0; - CLOCK(0x10) = 0x80000130; - CLOCK(0x18) = 0x1F00200; - CLOCK(0x360) = 0x80400808; - CLOCK(0x364) = 0x402000FC; - CLOCK(0x280) = 0x23000780; - CLOCK(0x298) = 0x300; - CLOCK(0xF8) = 0; - CLOCK(0xFC) = 0; - CLOCK(0x3A0) = 0; - CLOCK(0x3A4) = 0; - CLOCK(0x554) = 0; - CLOCK(0xD0) &= 0x1F7FFFFFu; - CLOCK(0x410) &= 0xFFFF3FFF; - CLOCK(0x148) = CLOCK(0x148) & 0x1FFFFFFF | 0x80000000; - CLOCK(0x180) = CLOCK(0x180) & 0x1FFFFFFF | 0x80000000; - CLOCK(0x6A0) = CLOCK(0x6A0) & 0x1FFFFFFF | 0x80000000; -} - -void mc_enable_ahb_redirect() -{ - CLOCK(0x3A4) = CLOCK(0x3A4) & 0xFFF7FFFF | 0x80000; - //MC(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE; - MC(MC_IRAM_BOM) = 0x40000000; - MC(MC_IRAM_TOM) = 0x4003F000; -} - -void mc_disable_ahb_redirect() -{ - MC(MC_IRAM_BOM) = 0xFFFFF000; - MC(MC_IRAM_TOM) = 0; - //Disable IRAM_CFG_WRITE_ACCESS (sticky). - //MC(MC_IRAM_REG_CTRL) = MC(MC_IRAM_REG_CTRL) & 0xFFFFFFFE | 1; - CLOCK(0x3A4) &= 0xFFF7FFFF; -} - -void mc_enable() -{ - CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF | 0x40000000; - //Enable MIPI CAL clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF | 0x2000000; - //Enable MC clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE | 1; - //Enable EMC DLL clock. - CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & 0xFFFFBFFF | 0x4000; - CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x2000001; //Clear EMC and MC reset. - sleep(5); -} - -clock_t clock_unk1 = { 0x358, 0x360, 0x42C, 0x1F, 0, 0 }; -clock_t clock_unk2 = { 0x358, 0x360, 0, 0x1E, 0, 0 }; - -void nx_hwinit() -{ - enable_clocks(); - clock_enable_se(); - clock_enable_fuse(1); - fuse_disable_program(); - - mc_enable(); - - config_oscillators(); - _REG(0x70000000, 0x40) = 0; - - config_gpios(); - - clock_enable_i2c(I2C_1); - clock_enable_i2c(I2C_5); - clock_enable(&clock_unk1); - clock_enable(&clock_unk2); - - i2c_init(I2C_1); - i2c_init(I2C_5); - - //Config PMIC (TODO: use max77620.h) - i2c_send_byte(I2C_5, 0x3C, 4, 0x40); - i2c_send_byte(I2C_5, 0x3C, 0x41, 0x78); - i2c_send_byte(I2C_5, 0x3C, 0x43, 0x38); - i2c_send_byte(I2C_5, 0x3C, 0x44, 0x3A); - i2c_send_byte(I2C_5, 0x3C, 0x45, 0x38); - i2c_send_byte(I2C_5, 0x3C, 0x4A, 0xF); - i2c_send_byte(I2C_5, 0x3C, 0x4E, 0xC7); - i2c_send_byte(I2C_5, 0x3C, 0x4F, 0x4F); - i2c_send_byte(I2C_5, 0x3C, 0x50, 0x29); - i2c_send_byte(I2C_5, 0x3C, 0x52, 0x1B); - i2c_send_byte(I2C_5, 0x3C, 0x16, 42); //42 = (1000 * 1125 - 600000) / 12500 - - config_pmc_scratch(); - - CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & 0xFFFF8888 | 0x3333; - - mc_config_carveout(); - - sdram_init(); -} diff --git a/fusee/fusee-secondary/src/hwinit/hwinit.h b/fusee/fusee-secondary/src/hwinit/hwinit.h deleted file mode 100644 index fda89d4f4..000000000 --- a/fusee/fusee-secondary/src/hwinit/hwinit.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _HWINIT_H_ -#define _HWINIT_H_ - -void mc_config_tsec_carveout(u32 bom, u32 size1mb, int lock); -void mc_enable_ahb_redirect(); -void mc_disable_ahb_redirect(); -void nx_hwinit(); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/hwinit_fuse.c b/fusee/fusee-secondary/src/hwinit/hwinit_fuse.c deleted file mode 100644 index 80fa85788..000000000 --- a/fusee/fusee-secondary/src/hwinit/hwinit_fuse.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "fuse.h" -#include "t210.h" - -void fuse_disable_program() -{ - FUSE(FUSE_DISABLEREGPROGRAM) = 1; -} - -u32 fuse_read_odm(u32 idx) -{ - return FUSE(FUSE_RESERVED_ODMX(idx)); -} diff --git a/fusee/fusee-secondary/src/hwinit/i2c.c b/fusee/fusee-secondary/src/hwinit/i2c.c deleted file mode 100644 index b44b9ffa5..000000000 --- a/fusee/fusee-secondary/src/hwinit/i2c.c +++ /dev/null @@ -1,116 +0,0 @@ -#include <string.h> - -#include "i2c.h" -#include "util.h" - -static u32 i2c_addrs[] = { 0x7000C000, 0x7000C400, 0x7000C500, 0x7000C700, 0x7000D000, 0x7000D100 }; - -static void _i2c_wait(vu32 *base) -{ - base[0x23] = 0x25; - for (u32 i = 0; i < 20; i++) - { - sleep(1); - if (!(base[0x23] & 1)) - break; - } -} - -static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size) -{ - if (size > 4) - return 0; - - u32 tmp = 0; - memcpy(&tmp, buf, size); - - vu32 *base = (vu32 *)i2c_addrs[idx]; - base[1] = x << 1; //Set x (send mode). - base[3] = tmp; //Set value. - base[0] = (2 * size - 2) | 0x2800; //Set size and send mode. - _i2c_wait(base); //Kick transaction. - - base[0] = base[0] & 0xFFFFFDFF | 0x200; - while (base[7] & 0x100) - ; - - if (base[7] << 28) - return 0; - - return 1; -} - -static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x) -{ - if (size > 4) - return 0; - - vu32 *base = (vu32 *)i2c_addrs[idx]; - base[1] = (x << 1) | 1; //Set x (recv mode). - base[0] = (2 * size - 2) | 0x2840; //Set size and recv mode. - _i2c_wait(base); //Kick transaction. - - base[0] = base[0] & 0xFFFFFDFF | 0x200; - while (base[7] & 0x100) - ; - - if (base[7] << 28) - return 0; - - u32 tmp = base[3]; //Get value. - memcpy(buf, &tmp, size); - - return 1; -} - -void i2c_init(u32 idx) -{ - vu32 *base = (vu32 *)i2c_addrs[idx]; - - base[0x1B] = 0x50001; - base[0x21] = 0x90003; - _i2c_wait(base); - - for (u32 i = 0; i < 10; i++) - { - sleep(20000); - if (base[0x1A] & 0x800) - break; - } - - vu32 dummy = base[0x22]; - base[0x1A] = base[0x1A]; -} - -int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size) -{ - u8 tmp[4]; - - if (size > 3) - return 0; - - tmp[0] = y; - memcpy(tmp + 1, buf, size); - - return _i2c_send_pkt(idx, x, tmp, size + 1); -} - -int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y) -{ - int res = _i2c_send_pkt(idx, x, (u8 *)&y, 1); - if (res) - res = _i2c_recv_pkt(idx, buf, size, x); - return res; -} - -void i2c_send_byte(u32 idx, u32 x, u32 y, u8 b) -{ - i2c_send_buf_small(idx, x, y, &b, 1); -} - -u8 i2c_recv_byte(u32 idx, u32 x, u32 y) -{ - u8 tmp; - i2c_recv_buf_small(&tmp, 1, idx, x, y); - return tmp; -} diff --git a/fusee/fusee-secondary/src/hwinit/i2c.h b/fusee/fusee-secondary/src/hwinit/i2c.h deleted file mode 100644 index 921533d6b..000000000 --- a/fusee/fusee-secondary/src/hwinit/i2c.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _I2C_H_ -#define _I2C_H_ - -#include "types.h" - -#define I2C_1 0 -#define I2C_2 1 -#define I2C_3 2 -#define I2C_4 3 -#define I2C_5 4 -#define I2C_6 5 - -void i2c_init(u32 idx); -int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size); -int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y); -void i2c_send_byte(u32 idx, u32 x, u32 y, u8 b); -u8 i2c_recv_byte(u32 idx, u32 x, u32 y); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/max77620.h b/fusee/fusee-secondary/src/hwinit/max77620.h deleted file mode 100644 index 7223067dc..000000000 --- a/fusee/fusee-secondary/src/hwinit/max77620.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Defining registers address and its bit definitions of MAX77620 and MAX20024 - * - * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - */ - -#ifndef _MFD_MAX77620_H_ -#define _MFD_MAX77620_H_ - -/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ -#define MAX77620_REG_CNFGGLBL1 0x00 -#define MAX77620_REG_CNFGGLBL2 0x01 -#define MAX77620_REG_CNFGGLBL3 0x02 -#define MAX77620_REG_CNFG1_32K 0x03 -#define MAX77620_REG_CNFGBBC 0x04 -#define MAX77620_REG_IRQTOP 0x05 -#define MAX77620_REG_INTLBT 0x06 -#define MAX77620_REG_IRQSD 0x07 -#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 -#define MAX77620_REG_IRQ_LVL2_L8 0x09 -#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A -#define MAX77620_REG_ONOFFIRQ 0x0B -#define MAX77620_REG_NVERC 0x0C -#define MAX77620_REG_IRQTOPM 0x0D -#define MAX77620_REG_INTENLBT 0x0E -#define MAX77620_REG_IRQMASKSD 0x0F -#define MAX77620_REG_IRQ_MSK_L0_7 0x10 -#define MAX77620_REG_IRQ_MSK_L8 0x11 -#define MAX77620_REG_ONOFFIRQM 0x12 -#define MAX77620_REG_STATLBT 0x13 -#define MAX77620_REG_STATSD 0x14 -#define MAX77620_REG_ONOFFSTAT 0x15 - -/* SD and LDO Registers */ -#define MAX77620_REG_SD0 0x16 -#define MAX77620_REG_SD1 0x17 -#define MAX77620_REG_SD2 0x18 -#define MAX77620_REG_SD3 0x19 -#define MAX77620_REG_SD4 0x1A -#define MAX77620_REG_DVSSD0 0x1B -#define MAX77620_REG_DVSSD1 0x1C -#define MAX77620_REG_SD0_CFG 0x1D -#define MAX77620_REG_SD1_CFG 0x1E -#define MAX77620_REG_SD2_CFG 0x1F -#define MAX77620_REG_SD3_CFG 0x20 -#define MAX77620_REG_SD4_CFG 0x21 -#define MAX77620_REG_SD_CFG2 0x22 -#define MAX77620_REG_LDO0_CFG 0x23 -#define MAX77620_REG_LDO0_CFG2 0x24 -#define MAX77620_REG_LDO1_CFG 0x25 -#define MAX77620_REG_LDO1_CFG2 0x26 -#define MAX77620_REG_LDO2_CFG 0x27 -#define MAX77620_REG_LDO2_CFG2 0x28 -#define MAX77620_REG_LDO3_CFG 0x29 -#define MAX77620_REG_LDO3_CFG2 0x2A -#define MAX77620_REG_LDO4_CFG 0x2B -#define MAX77620_REG_LDO4_CFG2 0x2C -#define MAX77620_REG_LDO5_CFG 0x2D -#define MAX77620_REG_LDO5_CFG2 0x2E -#define MAX77620_REG_LDO6_CFG 0x2F -#define MAX77620_REG_LDO6_CFG2 0x30 -#define MAX77620_REG_LDO7_CFG 0x31 -#define MAX77620_REG_LDO7_CFG2 0x32 -#define MAX77620_REG_LDO8_CFG 0x33 -#define MAX77620_REG_LDO8_CFG2 0x34 -#define MAX77620_REG_LDO_CFG3 0x35 - -#define MAX77620_LDO_SLEW_RATE_MASK 0x1 - -/* LDO Configuration 3 */ -#define MAX77620_TRACK4_MASK (1 << 5) -#define MAX77620_TRACK4_SHIFT 5 - -/* Voltage */ -#define MAX77620_SDX_VOLT_MASK 0xFF -#define MAX77620_SD0_VOLT_MASK 0x3F -#define MAX77620_SD1_VOLT_MASK 0x7F -#define MAX77620_LDO_VOLT_MASK 0x3F - -#define MAX77620_REG_GPIO0 0x36 -#define MAX77620_REG_GPIO1 0x37 -#define MAX77620_REG_GPIO2 0x38 -#define MAX77620_REG_GPIO3 0x39 -#define MAX77620_REG_GPIO4 0x3A -#define MAX77620_REG_GPIO5 0x3B -#define MAX77620_REG_GPIO6 0x3C -#define MAX77620_REG_GPIO7 0x3D -#define MAX77620_REG_PUE_GPIO 0x3E -#define MAX77620_REG_PDE_GPIO 0x3F -#define MAX77620_REG_AME_GPIO 0x40 -#define MAX77620_REG_ONOFFCNFG1 0x41 -#define MAX77620_REG_ONOFFCNFG2 0x42 - -/* FPS Registers */ -#define MAX77620_REG_FPS_CFG0 0x43 -#define MAX77620_REG_FPS_CFG1 0x44 -#define MAX77620_REG_FPS_CFG2 0x45 -#define MAX77620_REG_FPS_LDO0 0x46 -#define MAX77620_REG_FPS_LDO1 0x47 -#define MAX77620_REG_FPS_LDO2 0x48 -#define MAX77620_REG_FPS_LDO3 0x49 -#define MAX77620_REG_FPS_LDO4 0x4A -#define MAX77620_REG_FPS_LDO5 0x4B -#define MAX77620_REG_FPS_LDO6 0x4C -#define MAX77620_REG_FPS_LDO7 0x4D -#define MAX77620_REG_FPS_LDO8 0x4E -#define MAX77620_REG_FPS_SD0 0x4F -#define MAX77620_REG_FPS_SD1 0x50 -#define MAX77620_REG_FPS_SD2 0x51 -#define MAX77620_REG_FPS_SD3 0x52 -#define MAX77620_REG_FPS_SD4 0x53 -#define MAX77620_REG_FPS_NONE 0 - -#define MAX77620_FPS_SRC_MASK 0xC0 -#define MAX77620_FPS_SRC_SHIFT 6 -#define MAX77620_FPS_PU_PERIOD_MASK 0x38 -#define MAX77620_FPS_PU_PERIOD_SHIFT 3 -#define MAX77620_FPS_PD_PERIOD_MASK 0x07 -#define MAX77620_FPS_PD_PERIOD_SHIFT 0 -#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 -#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 -#define MAX77620_FPS_EN_SRC_MASK 0x06 -#define MAX77620_FPS_EN_SRC_SHIFT 1 -#define MAX77620_FPS_ENFPS_SW_MASK 0x01 -#define MAX77620_FPS_ENFPS_SW 0x01 - -/* Minimum and maximum FPS period time (in microseconds) are - * different for MAX77620 and Max20024. - */ -#define MAX77620_FPS_PERIOD_MIN_US 40 -#define MAX20024_FPS_PERIOD_MIN_US 20 - -#define MAX77620_FPS_PERIOD_MAX_US 2560 -#define MAX20024_FPS_PERIOD_MAX_US 5120 - -#define MAX77620_REG_FPS_GPIO1 0x54 -#define MAX77620_REG_FPS_GPIO2 0x55 -#define MAX77620_REG_FPS_GPIO3 0x56 -#define MAX77620_REG_FPS_RSO 0x57 -#define MAX77620_REG_CID0 0x58 -#define MAX77620_REG_CID1 0x59 -#define MAX77620_REG_CID2 0x5A -#define MAX77620_REG_CID3 0x5B -#define MAX77620_REG_CID4 0x5C -#define MAX77620_REG_CID5 0x5D - -#define MAX77620_REG_DVSSD4 0x5E -#define MAX20024_REG_MAX_ADD 0x70 - -#define MAX77620_CID_DIDM_MASK 0xF0 -#define MAX77620_CID_DIDM_SHIFT 4 - -/* CNCG2SD */ -#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) -#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) - -/* Device Identification Metal */ -#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) -/* Device Indentification OTP */ -#define MAX77620_CID5_DIDO(n) ((n) & 0xF) - -/* SD CNFG1 */ -#define MAX77620_SD_SR_MASK 0xC0 -#define MAX77620_SD_SR_SHIFT 6 -#define MAX77620_SD_POWER_MODE_MASK 0x30 -#define MAX77620_SD_POWER_MODE_SHIFT 4 -#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) -#define MAX77620_SD_CFG1_ADE_DISABLE 0 -#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) -#define MAX77620_SD_FPWM_MASK 0x04 -#define MAX77620_SD_FPWM_SHIFT 2 -#define MAX77620_SD_FSRADE_MASK 0x01 -#define MAX77620_SD_FSRADE_SHIFT 0 -#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) -#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 -#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) -#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) -#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) -#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 -#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) - -/* LDO_CNFG2 */ -#define MAX77620_LDO_POWER_MODE_MASK 0xC0 -#define MAX77620_LDO_POWER_MODE_SHIFT 6 -#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) -#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) -#define MAX77620_LDO_CFG2_ADE_DISABLE 0 -#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) -#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) -#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) -#define MAX77620_LDO_CFG2_SS_SLOW 0 - -#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) -#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) -#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) -#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) -#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) -#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) -#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) - -#define MAX77620_IRQ_LBM_MASK (1 << 3) -#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) -#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) - -#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) -#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) -#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0 -#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) -#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) -#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0 -#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) -#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0 -#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) -#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) -#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) -#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) -#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) -#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) -#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) -#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) - -#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) -#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) -#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) -#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) -#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) -#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) -#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) -#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) - -#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) - -#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) -#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 -#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 -#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) -#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) -#define MAX20024_ONOFFCNFG1_CLRSE 0x18 - -#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) -#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) -#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) -#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) -#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) - -#define MAX77620_GLBLM_MASK (1 << 0) - -#define MAX77620_WDTC_MASK 0x3 -#define MAX77620_WDTOFFC (1 << 4) -#define MAX77620_WDTSLPC (1 << 3) -#define MAX77620_WDTEN (1 << 2) - -#define MAX77620_TWD_MASK 0x3 -#define MAX77620_TWD_2s 0x0 -#define MAX77620_TWD_16s 0x1 -#define MAX77620_TWD_64s 0x2 -#define MAX77620_TWD_128s 0x3 - -#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) -#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) -#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) -#define MAX77620_CNFGGLBL1_LBDAC 0x0E -#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) - -/* CNFG BBC registers */ -#define MAX77620_CNFGBBC_ENABLE (1 << 0) -#define MAX77620_CNFGBBC_CURRENT_MASK 0x06 -#define MAX77620_CNFGBBC_CURRENT_SHIFT 1 -#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 -#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 -#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) -#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 -#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 - -#define MAX77620_FPS_COUNT 3 - -/* Interrupts */ -enum { - MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ - MAX77620_IRQ_TOP_SD, /* SD power fail */ - MAX77620_IRQ_TOP_LDO, /* LDO power fail */ - MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ - MAX77620_IRQ_TOP_RTC, /* RTC */ - MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ - MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ - MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ - MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ - MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ -}; - -/* GPIOs */ -enum { - MAX77620_GPIO0, - MAX77620_GPIO1, - MAX77620_GPIO2, - MAX77620_GPIO3, - MAX77620_GPIO4, - MAX77620_GPIO5, - MAX77620_GPIO6, - MAX77620_GPIO7, - MAX77620_GPIO_NR, -}; - -/* FPS Source */ -enum max77620_fps_src { - MAX77620_FPS_SRC_0, - MAX77620_FPS_SRC_1, - MAX77620_FPS_SRC_2, - MAX77620_FPS_SRC_NONE, - MAX77620_FPS_SRC_DEF, -}; - -enum max77620_chip_id { - MAX77620, - MAX20024, -}; - -#endif /* _MFD_MAX77620_H_ */ diff --git a/fusee/fusee-secondary/src/hwinit/max7762x.c b/fusee/fusee-secondary/src/hwinit/max7762x.c deleted file mode 100644 index 67caaf230..000000000 --- a/fusee/fusee-secondary/src/hwinit/max7762x.c +++ /dev/null @@ -1,136 +0,0 @@ -/* -* Copyright (c) 2018 naehrwert -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "max7762x.h" -#include "max77620.h" -#include "i2c.h" -#include "util.h" - -#define REGULATOR_SD 0 -#define REGULATOR_LDO 1 - -typedef struct _max77620_regulator_t -{ - u8 type; - const char *name; - u8 reg_sd; - u32 mv_step; - u32 mv_min; - u32 mv_default; - u32 mv_max; - u8 volt_addr; - u8 cfg_addr; - u8 volt_mask; - u8 enable_mask; - u8 enable_shift; - u8 status_mask; - - u8 fps_addr; - u8 fps_src; - u8 pd_period; - u8 pu_period; -} max77620_regulator_t; - -static const max77620_regulator_t _pmic_regulators[] = { - { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, 0x3F, 0x30, 4, 0x80, 0x4F, 1, 7, 1 }, - { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, 0x3F, 0x30, 4, 0x40, 0x50, 0, 1, 5 }, - { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, 0xFF, 0x30, 4, 0x20, 0x51, 1, 5, 2 }, - { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, 0xFF, 0x30, 4, 0x10, 0x52, 0, 3, 3 }, - { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, 0x3F, 0xC0, 6, 0x00, 0x46, 3, 7, 0 }, - { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, 0x3F, 0xC0, 6, 0x00, 0x47, 3, 7, 0 }, - { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, 0x3F, 0xC0, 6, 0x00, 0x48, 3, 7, 0 }, - { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, 0x3F, 0xC0, 6, 0x00, 0x49, 3, 7, 0 }, - { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4A, 0, 7, 1 }, - { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4B, 3, 7, 0 }, - { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4C, 3, 7, 0 }, - { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4D, 1, 4, 3 }, - { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4E, 3, 7, 0 } -}; - -int max77620_regulator_get_status(u32 id) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - if (reg->type == REGULATOR_SD) - return i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_STATSD) & reg->status_mask ? 0 : 1; - return i2c_recv_byte(I2C_5, 0x3C, reg->cfg_addr) & 8 ? 1 : 0; -} - -int max77620_regulator_config_fps(u32 id) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - i2c_send_byte(I2C_5, 0x3C, reg->fps_addr, (reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); - - return 1; -} - -int max77620_regulator_set_voltage(u32 id, u32 mv) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - if (mv < reg->mv_default || mv > reg->mv_max) - return 0; - - u32 mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; - u8 val = i2c_recv_byte(I2C_5, 0x3C, reg->volt_addr); - val = (val & ~reg->volt_mask) | (mult & reg->volt_mask); - i2c_send_byte(I2C_5, 0x3C, reg->volt_addr, val); - sleep(1000); - - return 1; -} - -int max77620_regulator_enable(u32 id, int enable) -{ - if (id > REGULATOR_MAX) - return 0; - - const max77620_regulator_t *reg = &_pmic_regulators[id]; - - u32 addr = reg->type == REGULATOR_SD ? reg->cfg_addr : reg->volt_addr; - u8 val = i2c_recv_byte(I2C_5, 0x3C, addr); - if (enable) - val = (val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask); - else - val &= ~reg->enable_mask; - i2c_send_byte(I2C_5, 0x3C, addr, val); - sleep(1000); - - return 1; -} - -void max77620_config_default() -{ - for (u32 i = 1; i <= REGULATOR_MAX; i++) - { - i2c_recv_byte(I2C_5, 0x3C, MAX77620_REG_CID4); - max77620_regulator_config_fps(i); - max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); - if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) - max77620_regulator_enable(i, 1); - } - i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_SD_CFG2, 4); -} diff --git a/fusee/fusee-secondary/src/hwinit/pinmux.c b/fusee/fusee-secondary/src/hwinit/pinmux.c deleted file mode 100644 index 269c91a57..000000000 --- a/fusee/fusee-secondary/src/hwinit/pinmux.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "pinmux.h" -#include "t210.h" - -void pinmux_config_uart(u32 idx) -{ - PINMUX_AUX(PINMUX_AUX_UARTX_RX(idx)) = 0; - PINMUX_AUX(PINMUX_AUX_UARTX_TX(idx)) = 0x48; - PINMUX_AUX(PINMUX_AUX_UARTX_RTS(idx)) = 0; - PINMUX_AUX(PINMUX_AUX_UARTX_CTS(idx)) = 0x44; -} - -void pinmux_config_i2c(u32 idx) -{ - PINMUX_AUX(PINMUX_AUX_X_I2C_SCL(idx)) = 0x40; - PINMUX_AUX(PINMUX_AUX_X_I2C_SDA(idx)) = 0x40; -} diff --git a/fusee/fusee-secondary/src/hwinit/pinmux.h b/fusee/fusee-secondary/src/hwinit/pinmux.h deleted file mode 100644 index 59bf506d8..000000000 --- a/fusee/fusee-secondary/src/hwinit/pinmux.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _PINMUX_H_ -#define _PINMUX_H_ - -#include "types.h" - -/*! Pinmux registers. */ -#define PINMUX_AUX_UART2_TX 0xF4 -#define PINMUX_AUX_UART3_TX 0x104 -#define PINMUX_AUX_GPIO_PE6 0x248 -#define PINMUX_AUX_GPIO_PH6 0x250 -/*! 0:UART-A, 1:UART-B, 3:UART-C, 3:UART-D */ -#define PINMUX_AUX_UARTX_TX(x) (0xE4 + 0x10 * (x)) -#define PINMUX_AUX_UARTX_RX(x) (0xE8 + 0x10 * (x)) -#define PINMUX_AUX_UARTX_RTS(x) (0xEC + 0x10 * (x)) -#define PINMUX_AUX_UARTX_CTS(x) (0xF0 + 0x10 * (x)) -/*! 0:GEN1, 1:GEN2, 2:GEN3, 3:CAM, 4:PWR */ -#define PINMUX_AUX_X_I2C_SCL(x) (0xBC + 8 * (x)) -#define PINMUX_AUX_X_I2C_SDA(x) (0xC0 + 8 * (x)) - -void pinmux_config_uart(u32 idx); -void pinmux_config_i2c(u32 idx); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/pmc.h b/fusee/fusee-secondary/src/hwinit/pmc.h deleted file mode 100644 index 4c8677239..000000000 --- a/fusee/fusee-secondary/src/hwinit/pmc.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _PMC_H_ -#define _PMC_H_ - -/*! PMC registers. */ -#define APBDEV_PMC_PWRGATE_TOGGLE 0x30 -#define APBDEV_PMC_PWRGATE_STATUS 0x38 -#define APBDEV_PMC_NO_IOPOWER 0x44 -#define APBDEV_PMC_SCRATCH20 0xA0 -#define APBDEV_PMC_DDR_PWR 0xE8 -#define APBDEV_PMC_CRYPTO_OP 0xF4 -#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4 -#define APBDEV_PMC_IO_DPD_REQ 0x1B8 -#define APBDEV_PMC_IO_DPD2_REQ 0x1C0 -#define APBDEV_PMC_VDDP_SEL 0x1CC -#define APBDEV_PMC_TSC_MULT 0x2B4 -#define APBDEV_PMC_REG_SHORT 0x2CC -#define APBDEV_PMC_WEAK_BIAS 0x2C8 -#define APBDEV_PMC_SECURE_SCRATCH21 0x334 -#define APBDEV_PMC_CNTRL2 0x440 -#define APBDEV_PMC_IO_DPD4_REQ 0x464 -#define APBDEV_PMC_DDR_CNTRL 0x4E4 -#define APBDEV_PMC_SCRATCH188 0x810 -#define APBDEV_PMC_SCRATCH190 0x818 -#define APBDEV_PMC_SCRATCH200 0x840 - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/sdram.c b/fusee/fusee-secondary/src/hwinit/sdram.c deleted file mode 100644 index a64d7b886..000000000 --- a/fusee/fusee-secondary/src/hwinit/sdram.c +++ /dev/null @@ -1,488 +0,0 @@ -#include "i2c.h" -#include "t210.h" -#include "mc.h" -//#include "emc.h" -#include "pmc.h" -#include "util.h" -#include "fuse.h" - -#include "sdram.inl" - -static u32 _get_sdram_id() -{ - return (fuse_read_odm(4) & 0x38) >> 3; -} - -static void _sdram_config(const u32 *_cfg) -{ - const u32 *_cfg_120 = _cfg + 0x120; - const u32 *_cfg_100 = _cfg + 0x100; - - PMC(0x45C) = (((4 * _cfg[0x12F] >> 2) + 0x80000000) ^ 0xFFFF) & 0xC000FFFF; - sleep(_cfg[0x111]); - - u32 req = (4 * _cfg_120[0x10] >> 2) + 0x80000000; - PMC(APBDEV_PMC_IO_DPD4_REQ) = (req ^ 0x3FFF0000) >> 16 << 16; - sleep(_cfg_100[0x12]); - PMC(APBDEV_PMC_IO_DPD4_REQ) = (req ^ 0xFFFF) & 0xC000FFFF; - sleep(_cfg_100[0x12]); - PMC(APBDEV_PMC_WEAK_BIAS) = 0; - sleep(1); - - CLOCK(0x98) = _cfg[4]; - CLOCK(0x9C) = 0; - CLOCK(0x90) = (_cfg[2] << 8) | (*((u16 *)_cfg + 0xA) << 20) | _cfg[1] | 0x40000000; - - u32 wait_end = TMR(0x10) + 300; - while (!((CLOCK(0x90) >> 27) & 1)) - { - if (TMR(0x10) >= wait_end) - goto break_nosleep; - } - sleep(10); -break_nosleep: - - CLOCK(0x19C) = _cfg[0x16] & 0xFFFEFFFF | (_cfg[0x175] >> 11) & 0x10000; - if (_cfg[0x17]) - CLOCK(0x664) = _cfg[0x17]; - if (_cfg[0x1A]) - CLOCK(0x44C) = 0x40000000; - CLOCK(0x328) = 0x2000001; - CLOCK(0x284) = 0x4000; - CLOCK(0x30C) = 0x2000001; - EMC(0xC34) = _cfg_120[0x13]; - EMC(0xC38) = _cfg_120[0x14]; - EMC(0xCF0) = _cfg_120[0x15]; - EMC(0x28) = 1; - sleep(1); - EMC(0x8) = _cfg[0xA9] | 2 * _cfg[0xAA]; - if (_cfg[0xA]) - *(vu32 *)_cfg[0xA] = _cfg[0xB]; - EMC(0x584) = _cfg[0x7B]; - EMC(0x380) = _cfg[0x7D]; - EMC(0x384) = _cfg[0x7E]; - EMC(0x388) = _cfg[0x7F]; - EMC(0x38C) = _cfg[0x80]; - EMC(0x390) = _cfg[0x81]; - EMC(0x394) = _cfg[0x82]; - EMC(0x398) = _cfg[0x83]; - EMC(0x39C) = _cfg[0x84]; - EMC(0x3A0) = _cfg[0x85]; - EMC(0x3A4) = _cfg[0x86]; - EMC(0x3A8) = _cfg[0x87]; - EMC(0x3AC) = _cfg[0x88]; - EMC(0x3B0) = _cfg[0x89]; - EMC(0xC80) = _cfg[0x14A]; - EMC(0xC84) = _cfg[0x14B]; - EMC(0xC88) = _cfg[0x14C]; - EMC(0x330) = (_cfg_120[0x16] | 0xFEEDFEED) & 0x1FFF1FFF; - EMC(0x5F0) = _cfg[0x149]; - EMC(0x5C8) = _cfg[0x7C]; - EMC(0x404) = _cfg_100[0x18]; - EMC(0x408) = _cfg_100[0x19]; - EMC(0x40C) = _cfg_100[0x1A]; - EMC(0x410) = _cfg_100[0x1B]; - EMC(0x418) = _cfg_100[0x1C]; - EMC(0x41C) = _cfg_100[0x1D]; - EMC(0x420) = _cfg_100[0x1E]; - EMC(0x424) = _cfg_100[0x1F]; - if (_cfg[0xE]) - *(vu32 *)_cfg[0xE] = _cfg[0xF]; - EMC(0x30C) = _cfg[0x31]; - EMC(0x578) = _cfg[0x32]; - EMC(0x2F4) = _cfg[0x33]; - EMC(0x458) = _cfg[0x1D]; - EMC(0x45C) = _cfg[0x1E]; - EMC(0x5B0) = _cfg[0x1F]; - EMC(0x5B4) = _cfg[0x20]; - EMC(0x5CC) = _cfg[0x21]; - EMC(0x574) = _cfg[0x22]; - EMC(0x2DC) = _cfg[0x23]; - EMC(0xC48) = _cfg[0x2A]; - EMC(0xC70) = _cfg[0x2B]; - EMC(0xC74) = _cfg[0x2C]; - EMC(0xC4C) = _cfg[0x2D]; - EMC(0xC78) = _cfg[0x2E]; - EMC(0x464) = _cfg[0x26]; - EMC(0xC44) = _cfg[0x2F]; - EMC(0x5E4) = _cfg_120[0xD]; - EMC(0x5E8) = _cfg_120[0xE]; - EMC(0x2C8) = _cfg[0xB0]; - EMC(0x588) = _cfg_120[1]; - EMC(0x58C) = _cfg_120[2]; - EMC(0x594) = _cfg_120[3]; - EMC(0x598) = _cfg_120[4]; - EMC(0x59C) = _cfg_120[5]; - EMC(0x5A0) = _cfg_120[6]; - EMC(0x5A4) = _cfg_120[7]; - EMC(0x5A8) = _cfg_120[8]; - EMC(0x5AC) = _cfg_120[9]; - EMC(0x5B8) = _cfg_120[0xA]; - EMC(0x5BC) = _cfg_120[0xB]; - EMC(0x5C4) = _cfg_120[0xC]; - EMC(0x330) = (_cfg_120[0x16] | 0xFE40FE40) & 0x1FFF1FFF; - EMC(0xC40) = _cfg_120[0x12]; - EMC(0x318) = _cfg_120[0x17]; - EMC(0x334) = _cfg_120[0x18] & 0xFF7FFF7F; - EMC(0x31C) = _cfg_120[0x19]; - EMC(0xC3C) = _cfg_120[0x1A]; - EMC(0xC54) = _cfg_120[0x1B]; - EMC(0xC50) = _cfg_120[0x1C]; - EMC(0xC64) = _cfg_120[0x1F]; - EMC(0xC5C) = _cfg_120[0x1D]; - EMC(0xC58) = _cfg_120[0x1E]; - EMC(0xC60) = _cfg[0x141]; - EMC(0x49C) = _cfg[0x142]; - EMC(0x720) = _cfg[0x143]; - EMC(0x724) = _cfg[0x144]; - EMC(0x728) = _cfg[0x145]; - EMC(0x72C) = _cfg[0x146]; - EMC(0x730) = _cfg[0x147]; - EMC(0x734) = _cfg[0x148]; - EMC(0x740) = _cfg[0x14D]; - EMC(0x744) = _cfg[0x14E]; - EMC(0x748) = _cfg[0x14F]; - EMC(0x74C) = _cfg[0x150]; - EMC(0x750) = _cfg[0x151]; - EMC(0x754) = _cfg[0x152]; - EMC(0x760) = _cfg[0x153]; - EMC(0x770) = _cfg[0x154]; - EMC(0x774) = _cfg[0x155]; - EMC(0x778) = _cfg[0x156]; - EMC(0x780) = _cfg[0x157]; - EMC(0x784) = _cfg[0x158]; - EMC(0x788) = _cfg[0x159]; - EMC(0xBE0) = _cfg[0xB6]; - EMC(0xBE4) = _cfg[0xB7]; - EMC(0xBF0) = _cfg[0xB8]; - EMC(0xBF4) = _cfg[0xB9]; - EMC(0xCF4) = _cfg[0xBA]; - EMC(0x600) = _cfg[0xBD]; - EMC(0x604) = _cfg[0xBE]; - EMC(0x608) = _cfg[0xBF]; - EMC(0x60C) = _cfg[0xC0]; - EMC(0x610) = _cfg[0xC1]; - EMC(0x614) = _cfg[0xC2]; - EMC(0x620) = _cfg[0xC3]; - EMC(0x624) = _cfg[0xC4]; - EMC(0x628) = _cfg[0xC5]; - EMC(0x62C) = _cfg[0xC6]; - EMC(0x630) = _cfg[0xC7]; - EMC(0x634) = _cfg[0xC8]; - EMC(0x330) = _cfg_120[0x16]; - EMC(0x640) = _cfg[0xC9]; - EMC(0x644) = _cfg[0xCA]; - EMC(0x648) = _cfg[0xCB]; - EMC(0x64C) = _cfg[0xCC]; - EMC(0x650) = _cfg[0xCD]; - EMC(0x654) = _cfg[0xCE]; - EMC(0x660) = _cfg[0xCF]; - EMC(0x664) = _cfg[0xD0]; - EMC(0x668) = _cfg[0xD1]; - EMC(0x66C) = _cfg[0xD2]; - EMC(0x670) = _cfg[0xD3]; - EMC(0x674) = _cfg[0xD4]; - EMC(0x680) = _cfg[0xD5]; - EMC(0x684) = _cfg[0xD6]; - EMC(0x688) = _cfg[0xD7]; - EMC(0x68C) = _cfg[0xD8]; - EMC(0x690) = _cfg[0xD9]; - EMC(0x694) = _cfg[0xDA]; - EMC(0x6A0) = _cfg[0xDB]; - EMC(0x6A4) = _cfg[0xDC]; - EMC(0x6A8) = _cfg[0xDD]; - EMC(0x6AC) = _cfg[0xDE]; - EMC(0x6B0) = _cfg[0xDF]; - EMC(0x6B4) = _cfg[0xE0]; - EMC(0x6C0) = _cfg[0xE1]; - EMC(0x6C4) = _cfg[0xE2]; - EMC(0x6C8) = _cfg[0xE3]; - EMC(0x6CC) = _cfg[0xE4]; - EMC(0x6E0) = _cfg[0xE5]; - EMC(0x6E4) = _cfg[0xE6]; - EMC(0x6E8) = _cfg[0xE7]; - EMC(0x6EC) = _cfg[0xE8]; - EMC(0xC00) = _cfg[0xE9]; - EMC(0xC04) = _cfg[0xEA]; - EMC(0xC08) = _cfg[0xEB]; - EMC(0xC0C) = _cfg[0xEC]; - EMC(0xC10) = _cfg[0xED]; - EMC(0xC20) = _cfg[0xEE]; - EMC(0xC24) = _cfg[0xEF]; - EMC(0xC28) = _cfg[0xF0]; - EMC(0xC68) = (*((u8 *)_cfg + 0x500) | 0xFFFFFFFE) & 0xF; - if (_cfg[0xC]) - *(vu32 *)_cfg[0xC] = _cfg[0xD]; - EMC(0x28) = 1; - MC(0x648) = _cfg[0x180]; - MC(0x978) = _cfg[0x181]; - MC(0x64C) = _cfg[0x182]; - MC(0x418) = _cfg[0x183]; - MC(0x590) = _cfg[0x184]; - MC(0x984) = _cfg[0x185]; - MC(0x988) = _cfg[0x186]; - MC(0x54) = _cfg[0x15A]; - MC(0x58) = _cfg[0x15B]; - MC(0x5C) = _cfg[0x15C]; - MC(0x60) = _cfg[0x15D]; - MC(0x64) = _cfg[0x15E]; - MC(0x68) = _cfg[0x15F]; - MC(0x6C) = _cfg[0x160]; - MC(0x50) = _cfg[0x161]; - MC(0x670) = _cfg[0x187]; - MC(0x9D4) = _cfg[0x188]; - MC(0x674) = _cfg[0x189]; - MC(0x9A0) = _cfg[0x1D6]; - MC(0x9A8) = _cfg[0x1D7]; - MC(0x9A4) = _cfg[0x1D8]; - MC(0x90) = _cfg[0x162]; - MC(0x94) = _cfg[0x163]; - MC(0x6F0) = _cfg[0x164]; - MC(0x6F4) = _cfg[0x165]; - MC(0x98) = _cfg[0x166]; - MC(0x9C) = _cfg[0x167]; - MC(0xA0) = _cfg[0x168]; - MC(0xA4) = _cfg[0x169]; - MC(0xA8) = _cfg[0x16A]; - MC(0xAC) = _cfg[0x16B]; - MC(0xB0) = _cfg[0x16C]; - MC(0xB4) = _cfg[0x16D]; - MC(0xB8) = _cfg[0x16E]; - MC(0xBC) = _cfg[0x16F]; - MC(0x6C4) = _cfg[0x17D]; - MC(0xC0) = _cfg[0x170]; - MC(0xC4) = _cfg[0x171]; - MC(0x6C0) = _cfg[0x172]; - MC(0xD0) = _cfg[0x173]; - MC(0xD4) = _cfg[0x174]; - MC(0xD8) = _cfg[0x175]; - MC(0xDC) = _cfg[0x176]; - MC(0xC8) = _cfg[0x177]; - MC(0xE0) = _cfg[0x178]; - MC(0xE8) = _cfg[0x179]; - MC(0x968) = _cfg[0x17A]; - MC(0xEC) = _cfg[0x17B]; - MC(0x9DC) = _cfg[0x17C]; - MC(0xFC) = 1; - MC(0xF4) = _cfg[0x17E]; - MC(0x100) = _cfg[0x17F]; - EMC(0x10) = _cfg[0x34]; - EMC(0x140) = _cfg_100[7]; - EMC(0x700) = _cfg[0x27]; - EMC(0x704) = _cfg[0x28]; - EMC(0x708) = _cfg[0x29]; - EMC(0x2F8) = _cfg[0x24]; - EMC(0x300) = _cfg[0x25]; - EMC(0x2A8) = _cfg[0x1B]; - EMC(0x2A4) = _cfg[0x1C]; - sleep(_cfg[0x30]); - if (_cfg[0x10]) - *(vu32 *)_cfg[0x10] = _cfg[0x11]; - EMC(0x2B8) = _cfg[0xA4]; - EMC(0x560) = _cfg[0xA5]; - EMC(0x55C) = _cfg[0xBB]; - EMC(0x554) = _cfg[0xBC]; - EMC(0xF0) = _cfg[0xAB]; - EMC(0xF4) = _cfg[0xAC]; - EMC(0xC8) = _cfg[0xA1]; - EMC(0xC4) = _cfg[0xA2]; - EMC(0x104) = _cfg[0x7A]; - EMC(0x2C) = _cfg[0x3A]; - EMC(0x30) = _cfg[0x3B]; - EMC(0x590) = _cfg[0x3C]; - EMC(0x580) = _cfg[0x3D]; - EMC(0xC0) = _cfg[0x3E]; - EMC(0x34) = _cfg[0x3F]; - EMC(0x38) = _cfg[0x40]; - EMC(0xAC) = _cfg[0x47]; - EMC(0x144) = _cfg[0x41]; - EMC(0x148) = _cfg[0x42]; - EMC(0x3C) = _cfg[0x43]; - EMC(0x40) = _cfg[0x44]; - EMC(0x44) = _cfg[0x45]; - EMC(0x48) = _cfg[0x46]; - EMC(0x5C0) = _cfg[0x48]; - EMC(0x4C) = _cfg[0x49]; - EMC(0x50) = _cfg[0x4A]; - EMC(0x54) = _cfg[0x4B]; - EMC(0x58) = _cfg[0x4C]; - EMC(0xB8) = _cfg[0x4D]; - EMC(0x5C) = _cfg[0x4E]; - EMC(0x4E0) = _cfg[0x4F]; - EMC(0x498) = _cfg[0x50]; - EMC(0x494) = _cfg[0x51]; - EMC(0x2D0) = _cfg[0x52]; - EMC(0x490) = _cfg[0x53]; - EMC(0x48C) = _cfg[0x54]; - EMC(0x60) = _cfg[0x55]; - EMC(0x568) = _cfg[0x56]; - EMC(0x468) = _cfg[0x57]; - EMC(0x46C) = _cfg[0x58]; - EMC(0x14C) = _cfg[0x59]; - EMC(0x150) = _cfg[0x5A]; - EMC(0x154) = _cfg[0x5B]; - EMC(0x56C) = _cfg[0x5C]; - EMC(0xC68) = _cfg[0x140]; - EMC(0x8) = _cfg[0xA9]; - EMC(0x64) = _cfg[0x5D]; - EMC(0x428) = 0; - EMC(0x68) = _cfg[0x5E]; - EMC(0x6C) = _cfg[0x5F]; - EMC(0x2CC) = _cfg[0x60]; - EMC(0x2D8) = _cfg[0x61]; - EMC(0x2D4) = _cfg[0x62]; - EMC(0x564) = _cfg[0x63]; - EMC(0x70) = _cfg[0x64]; - EMC(0x74) = _cfg[0x65]; - EMC(0x3DC) = _cfg[0x66]; - EMC(0x78) = _cfg[0x67]; - EMC(0x7C) = _cfg[0x68]; - EMC(0x80) = _cfg[0x69]; - EMC(0x84) = _cfg[0x6A]; - EMC(0x88) = _cfg[0x6B]; - EMC(0x8C) = _cfg[0x6C]; - EMC(0x11C) = _cfg[0x6D]; - EMC(0x118) = _cfg[0x6E]; - EMC(0xB4) = _cfg[0x6F]; - EMC(0x90) = _cfg[0x70]; - EMC(0x3E4) = _cfg[0x71]; - EMC(0x94) = _cfg[0x72]; - EMC(0x158) = _cfg[0x73]; - EMC(0x15C) = _cfg[0x74]; - EMC(0x98) = _cfg[0x75]; - EMC(0x9C) = _cfg[0x76]; - EMC(0xA0) = _cfg[0x77]; - EMC(0xA4) = _cfg[0x78]; - EMC(0xA8) = _cfg[0x79]; - EMC(0xB0) = _cfg[0xF2]; - EMC(0x2BC) = _cfg[0xAF]; - EMC(0x2C0) = _cfg[0xB1]; - EMC(0x100) = _cfg[0x8A] & 0xFFFFFFFD; - EMC(0x120) = _cfg[0x8B]; - EMC(0x440) = _cfg_120[0xF]; - EMC(0x444) = _cfg_120[0x10]; - EMC(0x448) = _cfg_120[0x11]; - EMC(0x124) = _cfg_100[0x17]; - EMC(0x480) = *_cfg_120; - EMC(0xC) = ((_cfg[0xA3] & 4 | 0x3C00000) & 0xFFFFFFF7 | _cfg[0xA3] & 8) & 0xFFFFFFFD | _cfg[0xA3] & 2; - if ((_cfg[0x1D4] & 0x80000000) != 0) - { - *(vu32 *)(4 * _cfg[0x1D4] + 0x70000000) = _cfg[0x1D5]; - MC(0xFC) = 1; - } - PMC(0x45C) = ((4 * _cfg_120[0xF] >> 2) + 0x40000000) & 0xCFFF0000; - sleep(_cfg_100[0x11]); - if (!_cfg[0x1B]) - EMC(0x2A4) = _cfg[0x1C] | 0x200; - EMC(0x334) = _cfg_120[0x18]; - if (_cfg[0xFA] << 31) - { - if (*_cfg == 2) - EMC(0x2E4) = 8 * _cfg[0xF4]; - if (*_cfg == 3) - { - EMC(0x2E4) = _cfg[0xF4]; - EMC(0x2E8) = _cfg[0xF5]; - } - } - EMC(0x28) = 1; - sleep(_cfg[0x39]); - PMC(0x4E4) &= 0xFFF8007F; - sleep(_cfg_100[0x15]); - if (*_cfg == 2) - { - EMC(0x24) = (_cfg[0x37] << 16) | (_cfg[0x38] << 12); - sleep(_cfg[0x36] + 200); - EMC(0x24) = ((_cfg[0x37] << 16) | (_cfg[0x38] << 12)) + 0x100; - sleep(_cfg[0x36] + 500); - } - if (*_cfg == 3) - { - EMC(0x24) = (_cfg[0x37] << 16) | (_cfg[0x38] << 12); - sleep(_cfg[0x36] + 200); - EMC(0x24) = ((_cfg[0x37] << 16) | (_cfg[0x38] << 12)) + 0x100; - sleep(_cfg[0x36] + 2000); - } - EMC(0x24) = ((_cfg[0x37] << 16) | (_cfg[0x38] << 12)) + 0x101; - sleep(_cfg[0x35]); - if (*_cfg != 3) - EMC(0xDC) = (_cfg[0xB2] << 30) + 1; - if (*_cfg == 1) - sleep(_cfg[0x36] + 200); - if (*_cfg == 3) - { - if (_cfg[0x12]) - *(vu32 *)_cfg[0x12] = _cfg[0x13]; - EMC(0x134) = _cfg[0x91]; - EMC(0xE8) = _cfg[0x90]; - EMC(0x138) = _cfg[0x92]; - EMC(0x13C) = _cfg[0x93]; - EMC(0x4A4) = _cfg[0x94]; - EMC(0x4C4) = _cfg[0x9A]; - EMC(0x4AC) = _cfg[0x95]; - EMC(0x4BC) = _cfg[0x98]; - EMC(0x4B0) = _cfg[0x96]; - EMC(0x4C0) = _cfg[0x99]; - if (_cfg[0xFA] << 31) - { - EMC(0x2EC) = _cfg[0xF7]; - sleep(_cfg[0xF9]); - EMC(0x2EC) = _cfg[0xF7] ^ 3; - if (!(_cfg[0xB2] & 2)) - { - EMC(0x2EC) = _cfg[0xF8]; - sleep(_cfg[0xF9]); - EMC(0x2EC) = _cfg[0xF8] ^ 3; - } - } - } - PMC(0x1D0) = _cfg_100[0xF]; - if (_cfg[0] == 1 || _cfg[0] == 2 || _cfg[0] == 3) - { - EMC(0x2E0) = _cfg[0xF3]; - EMC(0x2E4) = _cfg[0xF4]; - EMC(0x2E8) = _cfg[0xF5]; - } - if (_cfg[0x14]) - *(vu32 *)_cfg[0x14] = _cfg[0x15]; - EMC(0x28) = 1; - if (_cfg_100[8]) - EMC(0xD4) = ((1 << _cfg_100[8] << 8) - 0xFD) | (_cfg[0x38] << 30); - EMC(0x20) = _cfg[0xB2] | 0x80000000; - EMC(0x3E0) = _cfg[0xAD]; - EMC(0x5F4) = _cfg[0xA8]; - EMC(0xC) = _cfg[0xA3]; - EMC(0x310) = _cfg[0xB4]; - EMC(0x314) = _cfg[0xB5]; - EMC(0x3D8) = _cfg[0xB3]; - EMC(0x100) = _cfg[0x8A] | 2; - EMC(0x28) = 1; - EMC(0x558) = _cfg[0xA6]; - EMC(0x4D8) = _cfg[0xA7]; - SYSREG(AHB_ARBITRATION_XBAR_CTRL) = SYSREG(AHB_ARBITRATION_XBAR_CTRL) & 0xFFFEFFFF | (*((u16 *)_cfg + 0x15C) << 16); - MC(0x650) = _cfg[0x18A]; - MC(0x678) = _cfg[0x18B]; - MC(0x9AC) = _cfg[0x1D9]; - MC(MC_EMEM_CFG_ACCESS_CTRL) = 1; //Disable write access to a bunch of MC registers. -} - -void sdram_init() -{ - u32 sdram_id = _get_sdram_id(); - const u32 *cfg = _dram_cfgs[sdram_id]; //TODO: sdram_id should be in [0,4]. - - i2c_send_byte(I2C_5, 0x3C, 0x22, 0x05); - i2c_send_byte(I2C_5, 0x3C, 0x17, 40); //40 = (1000 * 1100 - 600000) / 12500 - - PMC(APBDEV_PMC_VDDP_SEL) = cfg[0x10C]; - sleep(cfg[0x10D]); - PMC(APBDEV_PMC_DDR_PWR) = PMC(0xE8); - PMC(APBDEV_PMC_NO_IOPOWER) = cfg[0x114]; - PMC(APBDEV_PMC_REG_SHORT) = cfg[0x113]; - PMC(APBDEV_PMC_DDR_CNTRL) = cfg[0x116]; - - if (cfg[8]) - *(vu32 *)cfg[8] = cfg[9]; - - _sdram_config(cfg); -} diff --git a/fusee/fusee-secondary/src/hwinit/sdram.h b/fusee/fusee-secondary/src/hwinit/sdram.h deleted file mode 100644 index 19db6da9b..000000000 --- a/fusee/fusee-secondary/src/hwinit/sdram.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SDRAM_H_ -#define _SDRAM_H_ - -void sdram_init(); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/sdram.inl b/fusee/fusee-secondary/src/hwinit/sdram.inl deleted file mode 100644 index 788dcc8aa..000000000 --- a/fusee/fusee-secondary/src/hwinit/sdram.inl +++ /dev/null @@ -1,812 +0,0 @@ -static const u8 _dram_cfg_0[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, - 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 _dram_cfg_1[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, - 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 _dram_cfg_2[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, - 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 _dram_cfg_3[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, - 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 _dram_cfg_4[1896] = { - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, - 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, - 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, - 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, - 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, - 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, - 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, - 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, - 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, - 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, - 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, - 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, - 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, - 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, - 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, - 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, - 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, - 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, - 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, - 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, - 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, - 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, - 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, - 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, - 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, - 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, - 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, - 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, - 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, - 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, - 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0C, 0x00, - 0x02, 0x03, 0x0C, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, - 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x18, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, - 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, - 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const u32 *_dram_cfgs[5] = { - (const u32 *)_dram_cfg_0, - (const u32 *)_dram_cfg_1, - (const u32 *)_dram_cfg_2, - (const u32 *)_dram_cfg_3, - (const u32 *)_dram_cfg_4 -}; diff --git a/fusee/fusee-secondary/src/hwinit/t210.h b/fusee/fusee-secondary/src/hwinit/t210.h deleted file mode 100644 index 578d6282b..000000000 --- a/fusee/fusee-secondary/src/hwinit/t210.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _T210_H_ -#define _T210_H_ - -#include "types.h" - -#define HOST1X_BASE 0x50000000 -#define DISPLAY_A_BASE 0x54200000 -#define DSI_BASE 0x54300000 -#define VIC_BASE 0x54340000 -#define TSEC_BASE 0x54500000 -#define SOR1_BASE 0x54580000 -#define TMR_BASE 0x60005000 -#define CLOCK_BASE 0x60006000 -#define FLOW_CTLR_BASE 0x60007000 -#define SYSREG_BASE 0x6000C000 -#define SB_BASE (SYSREG_BASE + 0x200) -#define GPIO_BASE 0x6000D000 -#define GPIO_1_BASE (GPIO_BASE) -#define GPIO_2_BASE (GPIO_BASE + 0x100) -#define GPIO_3_BASE (GPIO_BASE + 0x200) -#define GPIO_6_BASE (GPIO_BASE + 0x500) -#define EXCP_VEC_BASE 0x6000F000 -#define PINMUX_AUX_BASE 0x70003000 -#define UART_BASE 0x70006000 -#define PMC_BASE 0x7000E400 -#define SYSCTR0_BASE 0x7000F000 -#define FUSE_BASE 0x7000F800 -#define MC_BASE 0x70019000 -#define EMC_BASE 0x7001B000 -#define MIPI_CAL_BASE 0x700E3000 -#define I2S_BASE 0x702D1000 - -#define _REG(base, off) *(vu32 *)((base) + (off)) - -#define HOST1X(off) _REG(HOST1X_BASE, off) -#define DISPLAY_A(off) _REG(DISPLAY_A_BASE, off) -#define DSI(off) _REG(DSI_BASE, off) -#define VIC(off) _REG(VIC_BASE, off) -#define TSEC(off) _REG(TSEC_BASE, off) -#define SOR1(off) _REG(SOR1_BASE, off) -#define TMR(off) _REG(TMR_BASE, off) -#define CLOCK(off) _REG(CLOCK_BASE, off) -#define FLOW_CTLR(off) _REG(FLOW_CTLR_BASE, off) -#define SYSREG(off) _REG(SYSREG_BASE, off) -#define SB(off) _REG(SB_BASE, off) -#define GPIO_1(off) _REG(GPIO_1_BASE, off) -#define GPIO_2(off) _REG(GPIO_2_BASE, off) -#define GPIO_3(off) _REG(GPIO_3_BASE, off) -#define GPIO_6(off) _REG(GPIO_6_BASE, off) -#define EXCP_VEC(off) _REG(EXCP_VEC_BASE, off) -#define PINMUX_AUX(off) _REG(PINMUX_AUX_BASE, off) -#define PMC(off) _REG(PMC_BASE, off) -#define SYSCTR0(off) _REG(SYSCTR0_BASE, off) -#define FUSE(off) _REG(FUSE_BASE, off) -#define MC(off) _REG(MC_BASE, off) -#define EMC(off) _REG(EMC_BASE, off) -#define MIPI_CAL(off) _REG(MIPI_CAL_BASE, off) -#define I2S(off) _REG(I2S_BASE, off) - -/*! System registers. */ -#define AHB_ARBITRATION_XBAR_CTRL 0xE0 - -/*! Secure boot registers. */ -#define SB_CSR_0 0x0 -#define SB_AA64_RESET_LOW 0x30 -#define SB_AA64_RESET_HIGH 0x34 - -/*! SYSCTR0 registers. */ -#define SYSCTR0_CNTFID0 0x20 - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/tsec.c b/fusee/fusee-secondary/src/hwinit/tsec.c deleted file mode 100644 index 3b229fc52..000000000 --- a/fusee/fusee-secondary/src/hwinit/tsec.c +++ /dev/null @@ -1,113 +0,0 @@ -#include <string.h> -#include "tsec.h" -#include "clock.h" -#include "t210.h" - -static int _tsec_dma_wait_idle() -{ - u32 timeout = TMR(0x10) + 10000000; - - while (!(TSEC(0x1118) & 2)) - if (TMR(0x10) > timeout) - return 0; - - return 1; -} - -static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offset) -{ - u32 cmd; - - if (not_imem) - cmd = 0x600; // DMA 0x100 bytes - else - cmd = 0x10; // dma imem - - TSEC(0x1114) = i_offset; // tsec_dmatrfmoffs_r - TSEC(0x111C) = pa_offset; // tsec_dmatrffboffs_r - TSEC(0x1118) = cmd; // tsec_dmatrfcmd_r - - return _tsec_dma_wait_idle(); -} - -int tsec_query(u32 carveout, u8 *dst, u32 rev) -{ - int res = 0; - - //Enable clocks. - clock_enable_host1x(); - clock_enable_tsec(); - clock_enable_sor_safe(); - clock_enable_sor0(); - clock_enable_sor1(); - clock_enable_kfuse(); - - //Configure Falcon. - TSEC(0x110C) = 0; // tsec_dmactl_r - TSEC(0x1010) = 0xFFF2; // tsec_irqmset_r - TSEC(0x101C) = 0xFFF0; // tsec_irqdest_r - TSEC(0x1048) = 3; // tsec_itfen_r - if (!_tsec_dma_wait_idle()) - { - res = -1; - goto out; - } - - //Load firmware. - TSEC(0x1110) = carveout >> 8;// tsec_dmatrfbase_r - for (u32 addr = 0; addr < 0xF00; addr += 0x100) - if (!_tsec_dma_pa_to_internal_100(0, addr, addr)) - { - res = -2; - goto out; - } - - //Execute firmware. - HOST1X(0x3300) = 0x34C2E1DA; - TSEC(0x1044) = 0; - TSEC(0x1040) = rev; - TSEC(0x1104) = 0; // tsec_bootvec_r - TSEC(0x1100) = 2; // tsec_cpuctl_r - if (!_tsec_dma_wait_idle()) - { - res = -3; - goto out; - } - u32 timeout = TMR(0x10) + 2000000; - while (!TSEC(0x1044)) - if (TMR(0x10) > timeout) - { - res = -4; - goto out; - } - if (TSEC(0x1044) != 0xB0B0B0B0) - { - res = -5; - goto out; - } - - //Fetch result. - HOST1X(0x3300) = 0; - u32 buf[4]; - buf[0] = SOR1(0x1E8); - buf[1] = SOR1(0x21C); - buf[2] = SOR1(0x208); - buf[3] = SOR1(0x20C); - SOR1(0x1E8) = 0; - SOR1(0x21C) = 0; - SOR1(0x208) = 0; - SOR1(0x20C) = 0; - memcpy(dst, &buf, 0x10); - -out:; - - //Disable clocks. - clock_disable_kfuse(); - clock_disable_sor1(); - clock_disable_sor0(); - clock_disable_sor_safe(); - clock_disable_tsec(); - clock_disable_host1x(); - - return res; -} diff --git a/fusee/fusee-secondary/src/hwinit/tsec.h b/fusee/fusee-secondary/src/hwinit/tsec.h deleted file mode 100644 index 03fb503d2..000000000 --- a/fusee/fusee-secondary/src/hwinit/tsec.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _TSEC_H_ -#define _TSEC_H_ - -#include "types.h" - -int tsec_query(u32 carveout, u8 *dst, u32 rev); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/types.h b/fusee/fusee-secondary/src/hwinit/types.h deleted file mode 100644 index dff2978da..000000000 --- a/fusee/fusee-secondary/src/hwinit/types.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _TYPES_H_ -#define _TYPES_H_ - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef volatile unsigned int vu32; -typedef unsigned long long int u64; -typedef volatile unsigned long long int vu64; - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/uart.c b/fusee/fusee-secondary/src/hwinit/uart.c deleted file mode 100644 index b9b35aa8c..000000000 --- a/fusee/fusee-secondary/src/hwinit/uart.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "uart.h" -#include "t210.h" -#include "util.h" - -/* UART A, B, C, D and E. */ -static const u32 uart_baseoff[5] = { 0, 0x40, 0x200, 0x300, 0x400 }; - -void uart_init(u32 idx, u32 baud) -{ - volatile uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - - //Set baud rate. - u32 rate = (8 * baud + 408000000) / (16 * baud); - uart->UART_LCR = 0x80; //Enable DLAB. - uart->UART_THR_DLAB = (u8)rate; //Divisor latch LSB. - uart->UART_IER_DLAB = (u8)(rate >> 8); //Divisor latch MSB. - uart->UART_LCR = 0; //Diable DLAB. - - //Setup UART in fifo mode. - uart->UART_IER_DLAB = 0; - uart->UART_IIR_FCR = 7; //Enable and clear TX and RX FIFOs. - volatile u32 tmp = uart->UART_LSR; - sleep(3 * ((baud + 999999) / baud)); - uart->UART_LCR = 3; //Set word length 8. - uart->UART_MCR = 0; - uart->UART_MSR = 0; - uart->UART_IRDA_CSR = 0; - uart->UART_RX_FIFO_CFG = 1; - uart->UART_MIE = 0; - uart->UART_ASR = 0; -} - -void uart_wait_idle(u32 idx, u32 which) -{ - volatile uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - while (!(uart->UART_VENDOR_STATUS & which)) - ; -} - -void uart_send(u32 idx, u8 *buf, u32 len) -{ - volatile uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - - for (u32 i = 0; i != len; i++) - { - while (uart->UART_LSR & UART_TX_FIFO_FULL) - ; - uart->UART_THR_DLAB = buf[i]; - }; -} - -void uart_recv(u32 idx, u8 *buf, u32 len) -{ - volatile uart_t *uart = (uart_t *)(UART_BASE + uart_baseoff[idx]); - - for (u32 i = 0; i != len; i++) - { - while (uart->UART_LSR & UART_RX_FIFO_EMPTY) - ; - buf[i] = uart->UART_THR_DLAB; - }; -} diff --git a/fusee/fusee-secondary/src/hwinit/uart.h b/fusee/fusee-secondary/src/hwinit/uart.h deleted file mode 100644 index ac8222215..000000000 --- a/fusee/fusee-secondary/src/hwinit/uart.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _UART_H_ -#define _UART_H_ - -#include "types.h" - -#define UART_A 0 -#define UART_B 1 -#define UART_C 2 -//TODO: define clock inits for those. -/*#define UART_D 3 -#define UART_E 4*/ - -#define BAUD_115200 115200 - -#define UART_TX_IDLE 0x00000001 -#define UART_RX_IDLE 0x00000002 -#define UART_TX_FIFO_FULL 0x100 -#define UART_RX_FIFO_EMPTY 0x200 - -typedef struct _uart_t -{ - /* 0x00 */ u32 UART_THR_DLAB; - /* 0x04 */ u32 UART_IER_DLAB; - /* 0x08 */ u32 UART_IIR_FCR; - /* 0x0C */ u32 UART_LCR; - /* 0x10 */ u32 UART_MCR; - /* 0x14 */ u32 UART_LSR; - /* 0x18 */ u32 UART_MSR; - /* 0x1C */ u32 UART_SPR; - /* 0x20 */ u32 UART_IRDA_CSR; - /* 0x24 */ u32 UART_RX_FIFO_CFG; - /* 0x28 */ u32 UART_MIE; - /* 0x2C */ u32 UART_VENDOR_STATUS; - /* 0x30 */ u8 _pad_30[0x0C]; - /* 0x3C */ u32 UART_ASR; -} uart_t; - -void uart_init(u32 idx, u32 baud); -void uart_wait_idle(u32 idx, u32 which); -void uart_send(u32 idx, u8 *buf, u32 len); -void uart_recv(u32 idx, u8 *buf, u32 len); - -#endif diff --git a/fusee/fusee-secondary/src/hwinit/util.c b/fusee/fusee-secondary/src/hwinit/util.c deleted file mode 100644 index 780b31177..000000000 --- a/fusee/fusee-secondary/src/hwinit/util.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "util.h" -#include "t210.h" - -void sleep(u32 ticks) -{ - u32 start = TMR(0x10); - while (TMR(0x10) - start <= ticks) - ; -} - -void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) -{ - for(u32 i = 0; i < num_ops; i++) - base[ops[i].off] = ops[i].val; -} - diff --git a/fusee/fusee-secondary/src/hwinit/util.h b/fusee/fusee-secondary/src/hwinit/util.h deleted file mode 100644 index 13bc8024f..000000000 --- a/fusee/fusee-secondary/src/hwinit/util.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _UTIL_H_ -#define _UTIL_H_ - -#include "types.h" -#pragma GCC diagnostic ignored "-Wparentheses" -#pragma GCC diagnostic ignored "-Wunused-variable" - -typedef struct _cfg_op_t -{ - u32 off; - u32 val; -} cfg_op_t; - -void sleep(u32 ticks); -void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops); - -#endif diff --git a/fusee/fusee-secondary/src/i2c.c b/fusee/fusee-secondary/src/i2c.c new file mode 100644 index 000000000..a98d7fa6e --- /dev/null +++ b/fusee/fusee-secondary/src/i2c.c @@ -0,0 +1,205 @@ +#include "i2c.h" +#include "utils.h" +#include "timers.h" + +/* Prototypes for internal commands. */ +volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id); +void i2c_load_config(volatile tegra_i2c_t *regs); + +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size); +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size); + +bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size); +bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size); + +/* Initialize I2C based on registers. */ +void i2c_init(unsigned int id) { + volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); + + /* Setup divisor, and clear the bus. */ + regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; + regs->I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; + + /* Load hardware configuration. */ + i2c_load_config(regs); + + /* Wait a while until BUS_CLEAR_DONE is set. */ + for (unsigned int i = 0; i < 10; i++) { + udelay(20000); + if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { + break; + } + } + + /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ + regs->I2C_I2C_BUS_CLEAR_STATUS_0; + + /* Read and set the Interrupt Status. */ + uint32_t int_status = regs->I2C_INTERRUPT_STATUS_REGISTER_0; + regs->I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; +} + +/* Sets a bit in a PMIC register over I2C during CPU shutdown. */ +void i2c_send_pmic_cpu_shutdown_cmd(void) { + uint32_t val = 0; + /* PMIC == Device 4:3C. */ + i2c_query(4, 0x3C, 0x41, &val, 1); + val |= 4; + i2c_send(4, 0x3C, 0x41, &val, 1); +} + +/* Queries the value of TI charger bit over I2C. */ +bool i2c_query_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(0, 0x6B, 0, &val, 1); + return (val & 0x80) != 0; +} + +/* Clears TI charger bit over I2C. */ +void i2c_clear_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(0, 0x6B, 0, &val, 1); + val &= 0x7F; + i2c_send(0, 0x6B, 0, &val, 1); +} + +/* Sets TI charger bit over I2C. */ +void i2c_set_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(0, 0x6B, 0, &val, 1); + val |= 0x80; + i2c_send(0, 0x6B, 0, &val, 1); +} + +/* Get registers pointer based on I2C ID. */ +volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { + switch (id) { + case 0: + return I2C1_REGS; + case 1: + return I2C2_REGS; + case 2: + return I2C3_REGS; + case 3: + return I2C4_REGS; + case 4: + return I2C5_REGS; + case 5: + return I2C6_REGS; + default: + generic_panic(); + } + return NULL; +} + +/* Load hardware config for I2C4. */ +void i2c_load_config(volatile tegra_i2c_t *regs) { + /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ + regs->I2C_I2C_CONFIG_LOAD_0 = 0x25; + + /* Wait a bit for master config to be loaded. */ + for (unsigned int i = 0; i < 20; i++) { + udelay(1); + if (!(regs->I2C_I2C_CONFIG_LOAD_0 & 1)) { + break; + } + } +} + +/* Reads a register from a device over I2C, writes result to output. */ +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) { + volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); + uint32_t val = r; + + /* Write single byte register ID to device. */ + if (!i2c_write(regs, device, &val, 1)) { + return false; + } + /* Limit output size to 32-bits. */ + if (dst_size > 4) { + return false; + } + + return i2c_read(regs, device, dst, dst_size); +} + +/* Writes a value to a register over I2C. */ +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) { + uint32_t val = r; + if (src_size == 0) { + return true; + } else if (src_size <= 3) { + memcpy(((uint8_t *)&val) + 1, src, src_size); + return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1); + } else { + return false; + } +} + +/* Writes bytes to device over I2C. */ +bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) { + if (src_size > 4) { + return false; + } else if (src_size == 0) { + return true; + } + + /* Set device for 7-bit write mode. */ + regs->I2C_I2C_CMD_ADDR0_0 = device << 1; + + /* Load in data to write. */ + regs->I2C_I2C_CMD_DATA1_0 = read32le(src, 0); + + /* Set config with LENGTH = src_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + regs->I2C_I2C_CNFG_0 = ((src_size << 1) - 2) | 0x2800; + + i2c_load_config(regs); + + /* Config |= SEND; */ + regs->I2C_I2C_CNFG_0 |= 0x200; + + + while (regs->I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ + return (regs->I2C_I2C_STATUS_0 & 0xF) == 0; +} + +/* Reads bytes from device over I2C. */ +bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) { + if (dst_size > 4) { + return false; + } else if (dst_size == 0) { + return true; + } + + /* Set device for 7-bit read mode. */ + regs->I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1; + + /* Set config with LENGTH = dst_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + regs->I2C_I2C_CNFG_0 = ((dst_size << 1) - 2) | 0x2840; + + i2c_load_config(regs); + + /* Config |= SEND; */ + regs->I2C_I2C_CNFG_0 |= 0x200; + + + while (regs->I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Ensure success. */ + if ((regs->I2C_I2C_STATUS_0 & 0xF) != 0) { + return false; + } + + uint32_t val = regs->I2C_I2C_CMD_DATA1_0; + memcpy(dst, &val, dst_size); + return true; +} diff --git a/fusee/fusee-secondary/src/i2c.h b/fusee/fusee-secondary/src/i2c.h new file mode 100644 index 000000000..e07ed3349 --- /dev/null +++ b/fusee/fusee-secondary/src/i2c.h @@ -0,0 +1,71 @@ +#ifndef FUSEE_I2C_H +#define FUSEE_I2C_H + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#define I2C234_BASE 0x7000C000 +#define I2C56_BASE 0x7000D000 + +typedef struct { + uint32_t I2C_I2C_CNFG_0; + uint32_t I2C_I2C_CMD_ADDR0_0; + uint32_t I2C_I2C_CMD_ADDR1_0; + uint32_t I2C_I2C_CMD_DATA1_0; + uint32_t I2C_I2C_CMD_DATA2_0; + uint32_t _0x14; + uint32_t _0x18; + uint32_t I2C_I2C_STATUS_0; + uint32_t I2C_I2C_SL_CNFG_0; + uint32_t I2C_I2C_SL_RCVD_0; + uint32_t I2C_I2C_SL_STATUS_0; + uint32_t I2C_I2C_SL_ADDR1_0; + uint32_t I2C_I2C_SL_ADDR2_0; + uint32_t I2C_I2C_TLOW_SEXT_0; + uint32_t _0x38; + uint32_t I2C_I2C_SL_DELAY_COUNT_0; + uint32_t I2C_I2C_SL_INT_MASK_0; + uint32_t I2C_I2C_SL_INT_SOURCE_0; + uint32_t I2C_I2C_SL_INT_SET_0; + uint32_t _0x4C; + uint32_t I2C_I2C_TX_PACKET_FIFO_0; + uint32_t I2C_I2C_RX_FIFO_0; + uint32_t I2C_PACKET_TRANSFER_STATUS_0; + uint32_t I2C_FIFO_CONTROL_0; + uint32_t I2C_FIFO_STATUS_0; + uint32_t I2C_INTERRUPT_MASK_REGISTER_0; + uint32_t I2C_INTERRUPT_STATUS_REGISTER_0; + uint32_t I2C_I2C_CLK_DIVISOR_REGISTER_0; + uint32_t I2C_I2C_INTERRUPT_SOURCE_REGISTER_0; + uint32_t I2C_I2C_INTERRUPT_SET_REGISTER_0; + uint32_t I2C_I2C_SLV_TX_PACKET_FIFO_0; + uint32_t I2C_I2C_SLV_RX_FIFO_0; + uint32_t I2C_I2C_SLV_PACKET_STATUS_0; + uint32_t I2C_I2C_BUS_CLEAR_CONFIG_0; + uint32_t I2C_I2C_BUS_CLEAR_STATUS_0; + uint32_t I2C_I2C_CONFIG_LOAD_0; + uint32_t _0x90; + uint32_t I2C_I2C_INTERFACE_TIMING_0_0; + uint32_t I2C_I2C_INTERFACE_TIMING_1_0; + uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0; + uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; +} tegra_i2c_t; + +#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x000)) +#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x400)) +#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x500)) +#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x700)) +#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000)) +#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100)) + +void i2c_init(unsigned int id); +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size); +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size); + +void i2c_send_pmic_cpu_shutdown_cmd(void); +bool i2c_query_ti_charger_bit_7(void); +void i2c_clear_ti_charger_bit_7(void); +void i2c_set_ti_charger_bit_7(void); + +#endif diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index c048cc05d..900b7f9df 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -3,7 +3,7 @@ #include "se.h" #include "exocfg.h" #include "fuse.h" -#include "hwinit.h" +#include "tsec.h" #include "utils.h" #define AL16 ALIGN(16) @@ -39,7 +39,7 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = { static nx_dec_keyblob_t AL16 g_dec_keyblobs[32]; static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uint32_t tsec_key_id) { - return tsec_query((u32)tsec_fw, dst, tsec_key_id); + return tsec_get_key(dst, tsec_key_id, tsec_fw); } static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) { diff --git a/fusee/fusee-secondary/src/lib/driver_utils.h b/fusee/fusee-secondary/src/lib/driver_utils.h index 2a24f67d9..eefc51215 100644 --- a/fusee/fusee-secondary/src/lib/driver_utils.h +++ b/fusee/fusee-secondary/src/lib/driver_utils.h @@ -7,4 +7,4 @@ #define vprintk vprintf #define printk printf -#endif +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/max77620.h b/fusee/fusee-secondary/src/max77620.h new file mode 100644 index 000000000..ad22a06b5 --- /dev/null +++ b/fusee/fusee-secondary/src/max77620.h @@ -0,0 +1,326 @@ +/* + * Defining registers address and its bit definitions of MAX77620 and MAX20024 + * + * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#ifndef _MFD_MAX77620_H_ +#define _MFD_MAX77620_H_ + +/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ +#define MAX77620_REG_CNFGGLBL1 0x00 +#define MAX77620_REG_CNFGGLBL2 0x01 +#define MAX77620_REG_CNFGGLBL3 0x02 +#define MAX77620_REG_CNFG1_32K 0x03 +#define MAX77620_REG_CNFGBBC 0x04 +#define MAX77620_REG_IRQTOP 0x05 +#define MAX77620_REG_INTLBT 0x06 +#define MAX77620_REG_IRQSD 0x07 +#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 +#define MAX77620_REG_IRQ_LVL2_L8 0x09 +#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A +#define MAX77620_REG_ONOFFIRQ 0x0B +#define MAX77620_REG_NVERC 0x0C +#define MAX77620_REG_IRQTOPM 0x0D +#define MAX77620_REG_INTENLBT 0x0E +#define MAX77620_REG_IRQMASKSD 0x0F +#define MAX77620_REG_IRQ_MSK_L0_7 0x10 +#define MAX77620_REG_IRQ_MSK_L8 0x11 +#define MAX77620_REG_ONOFFIRQM 0x12 +#define MAX77620_REG_STATLBT 0x13 +#define MAX77620_REG_STATSD 0x14 +#define MAX77620_REG_ONOFFSTAT 0x15 + +/* SD and LDO Registers */ +#define MAX77620_REG_SD0 0x16 +#define MAX77620_REG_SD1 0x17 +#define MAX77620_REG_SD2 0x18 +#define MAX77620_REG_SD3 0x19 +#define MAX77620_REG_SD4 0x1A +#define MAX77620_REG_DVSSD0 0x1B +#define MAX77620_REG_DVSSD1 0x1C +#define MAX77620_REG_SD0_CFG 0x1D +#define MAX77620_REG_SD1_CFG 0x1E +#define MAX77620_REG_SD2_CFG 0x1F +#define MAX77620_REG_SD3_CFG 0x20 +#define MAX77620_REG_SD4_CFG 0x21 +#define MAX77620_REG_SD_CFG2 0x22 +#define MAX77620_REG_LDO0_CFG 0x23 +#define MAX77620_REG_LDO0_CFG2 0x24 +#define MAX77620_REG_LDO1_CFG 0x25 +#define MAX77620_REG_LDO1_CFG2 0x26 +#define MAX77620_REG_LDO2_CFG 0x27 +#define MAX77620_REG_LDO2_CFG2 0x28 +#define MAX77620_REG_LDO3_CFG 0x29 +#define MAX77620_REG_LDO3_CFG2 0x2A +#define MAX77620_REG_LDO4_CFG 0x2B +#define MAX77620_REG_LDO4_CFG2 0x2C +#define MAX77620_REG_LDO5_CFG 0x2D +#define MAX77620_REG_LDO5_CFG2 0x2E +#define MAX77620_REG_LDO6_CFG 0x2F +#define MAX77620_REG_LDO6_CFG2 0x30 +#define MAX77620_REG_LDO7_CFG 0x31 +#define MAX77620_REG_LDO7_CFG2 0x32 +#define MAX77620_REG_LDO8_CFG 0x33 +#define MAX77620_REG_LDO8_CFG2 0x34 +#define MAX77620_REG_LDO_CFG3 0x35 + +#define MAX77620_LDO_SLEW_RATE_MASK 0x1 + +/* LDO Configuration 3 */ +#define MAX77620_TRACK4_MASK (1 << 5) +#define MAX77620_TRACK4_SHIFT 5 + +/* Voltage */ +#define MAX77620_SDX_VOLT_MASK 0xFF +#define MAX77620_SD0_VOLT_MASK 0x3F +#define MAX77620_SD1_VOLT_MASK 0x7F +#define MAX77620_LDO_VOLT_MASK 0x3F + +#define MAX77620_REG_GPIO0 0x36 +#define MAX77620_REG_GPIO1 0x37 +#define MAX77620_REG_GPIO2 0x38 +#define MAX77620_REG_GPIO3 0x39 +#define MAX77620_REG_GPIO4 0x3A +#define MAX77620_REG_GPIO5 0x3B +#define MAX77620_REG_GPIO6 0x3C +#define MAX77620_REG_GPIO7 0x3D +#define MAX77620_REG_PUE_GPIO 0x3E +#define MAX77620_REG_PDE_GPIO 0x3F +#define MAX77620_REG_AME_GPIO 0x40 +#define MAX77620_REG_ONOFFCNFG1 0x41 +#define MAX77620_REG_ONOFFCNFG2 0x42 + +/* FPS Registers */ +#define MAX77620_REG_FPS_CFG0 0x43 +#define MAX77620_REG_FPS_CFG1 0x44 +#define MAX77620_REG_FPS_CFG2 0x45 +#define MAX77620_REG_FPS_LDO0 0x46 +#define MAX77620_REG_FPS_LDO1 0x47 +#define MAX77620_REG_FPS_LDO2 0x48 +#define MAX77620_REG_FPS_LDO3 0x49 +#define MAX77620_REG_FPS_LDO4 0x4A +#define MAX77620_REG_FPS_LDO5 0x4B +#define MAX77620_REG_FPS_LDO6 0x4C +#define MAX77620_REG_FPS_LDO7 0x4D +#define MAX77620_REG_FPS_LDO8 0x4E +#define MAX77620_REG_FPS_SD0 0x4F +#define MAX77620_REG_FPS_SD1 0x50 +#define MAX77620_REG_FPS_SD2 0x51 +#define MAX77620_REG_FPS_SD3 0x52 +#define MAX77620_REG_FPS_SD4 0x53 +#define MAX77620_REG_FPS_NONE 0 + +#define MAX77620_FPS_SRC_MASK 0xC0 +#define MAX77620_FPS_SRC_SHIFT 6 +#define MAX77620_FPS_PU_PERIOD_MASK 0x38 +#define MAX77620_FPS_PU_PERIOD_SHIFT 3 +#define MAX77620_FPS_PD_PERIOD_MASK 0x07 +#define MAX77620_FPS_PD_PERIOD_SHIFT 0 +#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 +#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 +#define MAX77620_FPS_EN_SRC_MASK 0x06 +#define MAX77620_FPS_EN_SRC_SHIFT 1 +#define MAX77620_FPS_ENFPS_SW_MASK 0x01 +#define MAX77620_FPS_ENFPS_SW 0x01 + +/* Minimum and maximum FPS period time (in microseconds) are + * different for MAX77620 and Max20024. + */ +#define MAX77620_FPS_PERIOD_MIN_US 40 +#define MAX20024_FPS_PERIOD_MIN_US 20 + +#define MAX77620_FPS_PERIOD_MAX_US 2560 +#define MAX20024_FPS_PERIOD_MAX_US 5120 + +#define MAX77620_REG_FPS_GPIO1 0x54 +#define MAX77620_REG_FPS_GPIO2 0x55 +#define MAX77620_REG_FPS_GPIO3 0x56 +#define MAX77620_REG_FPS_RSO 0x57 +#define MAX77620_REG_CID0 0x58 +#define MAX77620_REG_CID1 0x59 +#define MAX77620_REG_CID2 0x5A +#define MAX77620_REG_CID3 0x5B +#define MAX77620_REG_CID4 0x5C +#define MAX77620_REG_CID5 0x5D + +#define MAX77620_REG_DVSSD4 0x5E +#define MAX20024_REG_MAX_ADD 0x70 + +#define MAX77620_CID_DIDM_MASK 0xF0 +#define MAX77620_CID_DIDM_SHIFT 4 + +/* CNCG2SD */ +#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) +#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) + +/* Device Identification Metal */ +#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) +/* Device Indentification OTP */ +#define MAX77620_CID5_DIDO(n) ((n) & 0xF) + +/* SD CNFG1 */ +#define MAX77620_SD_SR_MASK 0xC0 +#define MAX77620_SD_SR_SHIFT 6 +#define MAX77620_SD_POWER_MODE_MASK 0x30 +#define MAX77620_SD_POWER_MODE_SHIFT 4 +#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) +#define MAX77620_SD_CFG1_ADE_DISABLE 0 +#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) +#define MAX77620_SD_FPWM_MASK 0x04 +#define MAX77620_SD_FPWM_SHIFT 2 +#define MAX77620_SD_FSRADE_MASK 0x01 +#define MAX77620_SD_FSRADE_SHIFT 0 +#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) +#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 +#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) +#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) +#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) +#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 +#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) + +/* LDO_CNFG2 */ +#define MAX77620_LDO_POWER_MODE_MASK 0xC0 +#define MAX77620_LDO_POWER_MODE_SHIFT 6 +#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) +#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) +#define MAX77620_LDO_CFG2_ADE_DISABLE 0 +#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) +#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) +#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) +#define MAX77620_LDO_CFG2_SS_SLOW 0 + +#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) +#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) +#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) +#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) +#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) +#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) +#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) + +#define MAX77620_IRQ_LBM_MASK (1 << 3) +#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) +#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) + +#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) +#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) +#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0 +#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) +#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) +#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0 +#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0 +#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) +#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) +#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) +#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) +#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) +#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) +#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) +#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) + +#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) +#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) +#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) +#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) +#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) +#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) +#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) +#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) + +#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) + +#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) +#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 +#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 +#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) +#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) +#define MAX20024_ONOFFCNFG1_CLRSE 0x18 + +#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) +#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) +#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) +#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) +#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) + +#define MAX77620_GLBLM_MASK (1 << 0) + +#define MAX77620_WDTC_MASK 0x3 +#define MAX77620_WDTOFFC (1 << 4) +#define MAX77620_WDTSLPC (1 << 3) +#define MAX77620_WDTEN (1 << 2) + +#define MAX77620_TWD_MASK 0x3 +#define MAX77620_TWD_2s 0x0 +#define MAX77620_TWD_16s 0x1 +#define MAX77620_TWD_64s 0x2 +#define MAX77620_TWD_128s 0x3 + +#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) +#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) +#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) +#define MAX77620_CNFGGLBL1_LBHYST_N (1 << 4) +#define MAX77620_CNFGGLBL1_LBDAC 0x0E +#define MAX77620_CNFGGLBL1_LBDAC_N (1 << 1) +#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) + +/* CNFG BBC registers */ +#define MAX77620_CNFGBBC_ENABLE (1 << 0) +#define MAX77620_CNFGBBC_CURRENT_MASK 0x06 +#define MAX77620_CNFGBBC_CURRENT_SHIFT 1 +#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 +#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 +#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) +#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 +#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 + +#define MAX77620_FPS_COUNT 3 + +/* Interrupts */ +enum { + MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ + MAX77620_IRQ_TOP_SD, /* SD power fail */ + MAX77620_IRQ_TOP_LDO, /* LDO power fail */ + MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ + MAX77620_IRQ_TOP_RTC, /* RTC */ + MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ + MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ + MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ + MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ + MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ +}; + +/* GPIOs */ +enum { + MAX77620_GPIO0, + MAX77620_GPIO1, + MAX77620_GPIO2, + MAX77620_GPIO3, + MAX77620_GPIO4, + MAX77620_GPIO5, + MAX77620_GPIO6, + MAX77620_GPIO7, + MAX77620_GPIO_NR, +}; + +/* FPS Source */ +enum max77620_fps_src { + MAX77620_FPS_SRC_0, + MAX77620_FPS_SRC_1, + MAX77620_FPS_SRC_2, + MAX77620_FPS_SRC_NONE, + MAX77620_FPS_SRC_DEF, +}; + +enum max77620_chip_id { + MAX77620, + MAX20024, +}; + +#endif /* _MFD_MAX77620_H_ */ diff --git a/fusee/fusee-secondary/src/max7762x.c b/fusee/fusee-secondary/src/max7762x.c new file mode 100644 index 000000000..419a13bce --- /dev/null +++ b/fusee/fusee-secondary/src/max7762x.c @@ -0,0 +1,161 @@ +#include <stdint.h> + +#include "max7762x.h" +#include "max77620.h" +#include "i2c.h" +#include "timers.h" + +#define REGULATOR_SD 0 +#define REGULATOR_LDO 1 + +typedef struct _max77620_regulator_t +{ + uint8_t type; + const char *name; + uint8_t reg_sd; + uint32_t mv_step; + uint32_t mv_min; + uint32_t mv_default; + uint32_t mv_max; + uint8_t volt_addr; + uint8_t cfg_addr; + uint8_t volt_mask; + uint8_t enable_mask; + uint8_t enable_shift; + uint8_t status_mask; + + uint8_t fps_addr; + uint8_t fps_src; + uint8_t pd_period; + uint8_t pu_period; +} max77620_regulator_t; + +static const max77620_regulator_t _pmic_regulators[] = { + { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, 0x3F, 0x30, 4, 0x80, 0x4F, 1, 7, 1 }, + { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, 0x3F, 0x30, 4, 0x40, 0x50, 0, 1, 5 }, + { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, 0xFF, 0x30, 4, 0x20, 0x51, 1, 5, 2 }, + { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, 0xFF, 0x30, 4, 0x10, 0x52, 0, 3, 3 }, + { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, 0x3F, 0xC0, 6, 0x00, 0x46, 3, 7, 0 }, + { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, 0x3F, 0xC0, 6, 0x00, 0x47, 3, 7, 0 }, + { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, 0x3F, 0xC0, 6, 0x00, 0x48, 3, 7, 0 }, + { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, 0x3F, 0xC0, 6, 0x00, 0x49, 3, 7, 0 }, + { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4A, 0, 7, 1 }, + { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4B, 3, 7, 0 }, + { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4C, 3, 7, 0 }, + { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4D, 1, 4, 3 }, + { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4E, 3, 7, 0 } +}; + +int max77620_regulator_get_status(uint32_t id) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + uint8_t val = 0; + + if (reg->type == REGULATOR_SD) { + if (i2c_query(4, 0x3C, MAX77620_REG_STATSD, &val, 1)) + return (val & reg->status_mask) ? 0 : 1; + } + + if (i2c_query(4, 0x3C, reg->cfg_addr, &val, 1)) + return (val & 8) ? 0 : 1; + + return 0; +} + +int max77620_regulator_config_fps(uint32_t id) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); + + if (i2c_send(4, 0x3C, reg->fps_addr, &val, 1)) { + return 1; + } + + return 0; +} + +int max77620_regulator_set_voltage(uint32_t id, uint32_t mv) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + + if ((mv < reg->mv_default) || (mv > reg->mv_max)) + return 0; + + uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; + uint8_t val = 0; + + if (i2c_query(4, 0x3C, reg->volt_addr, &val, 1)) + { + val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask)); + + if (i2c_send(4, 0x3C, reg->volt_addr, &val, 1)) + { + udelay(1000); + return 1; + } + } + + return 0; +} + +int max77620_regulator_enable(uint32_t id, int enable) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + + uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr; + uint8_t val = 0; + + if (i2c_query(4, 0x3C, addr, &val, 1)) + { + if (enable) + val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); + else + val &= ~reg->enable_mask; + + if (i2c_send(4, 0x3C, addr, &val, 1)) + { + udelay(1000); + return 1; + } + } + + return 0; +} + +void max77620_config_default() +{ + for (uint32_t i = 1; i <= REGULATOR_MAX; i++) + { + uint8_t val = 0; + if (i2c_query(4, 0x3C, MAX77620_REG_CID4, &val, 1)) + { + max77620_regulator_config_fps(i); + max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); + + if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) { + max77620_regulator_enable(i, 1); + } + } + } + + uint8_t val = 4; + i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); +} + +void max77620_low_battery_monitor_config() +{ + uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N); + i2c_send(4, 0x3C, MAX77620_REG_CNFGGLBL1, &val, 1); +} diff --git a/fusee/fusee-secondary/src/hwinit/max7762x.h b/fusee/fusee-secondary/src/max7762x.h similarity index 62% rename from fusee/fusee-secondary/src/hwinit/max7762x.h rename to fusee/fusee-secondary/src/max7762x.h index 05434956e..c106a27d4 100644 --- a/fusee/fusee-secondary/src/hwinit/max7762x.h +++ b/fusee/fusee-secondary/src/max7762x.h @@ -1,34 +1,16 @@ -/* -* Copyright (c) 2018 naehrwert -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _MAX7762X_H_ -#define _MAX7762X_H_ - -#include "types.h" +#ifndef FUSEE_MAX7762X_H_ +#define FUSEE_MAX7762X_H_ /* * Switch Power domains (max77620): * Name | Usage | uV step | uV min | uV default | uV max | Init *-------+---------------+---------+--------+------------+---------+------------------ * sd0 | core | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1) -* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1) +* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1) * sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv) * sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 | -* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1) -* ldo1 | XUSB | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) +* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1) +* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) * ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 | * ldo3 | | 50000 | 800000 | 3100000 | 3100000 | * ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | @@ -59,10 +41,11 @@ #define REGULATOR_LDO8 12 #define REGULATOR_MAX 12 -int max77620_regulator_get_status(u32 id); -int max77620_regulator_config_fps(u32 id); -int max77620_regulator_set_voltage(u32 id, u32 mv); -int max77620_regulator_enable(u32 id, int enable); +int max77620_regulator_get_status(uint32_t id); +int max77620_regulator_config_fps(uint32_t id); +int max77620_regulator_set_voltage(uint32_t id, uint32_t mv); +int max77620_regulator_enable(uint32_t id, int enable); void max77620_config_default(); +void max77620_low_battery_monitor_config(); #endif diff --git a/fusee/fusee-secondary/src/mc.c b/fusee/fusee-secondary/src/mc.c new file mode 100644 index 000000000..a98b6fbf7 --- /dev/null +++ b/fusee/fusee-secondary/src/mc.c @@ -0,0 +1,146 @@ +#include "mc.h" +#include "car.h" +#include "timers.h" + +void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock) +{ + MAKE_MC_REG(MC_SEC_CARVEOUT_BOM) = bom; + MAKE_MC_REG(MC_SEC_CARVEOUT_SIZE_MB) = size1mb; + + if (lock) + MAKE_MC_REG(MC_SEC_CARVEOUT_REG_CTRL) = 1; +} + +void mc_config_carveout() +{ + *(volatile uint32_t *)0x8005FFFC = 0xC0EDBBCC; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1; + + mc_config_tsec_carveout(0, 0, 1); + + MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = 1; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CFG0) = 0x4000006; + + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0x3000000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0x300; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CFG0) = 0x4401E7E; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CFG0) = 0x8F; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F; +} + +void mc_config_carveout_finalize() +{ + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = 0x3000000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = 0x300; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CFG0) = 0x440167E; +} + +void mc_enable_ahb_redirect() +{ + volatile tegra_car_t *car = car_get_regs(); + car->lvl2_clk_gate_ovrd = ((car->lvl2_clk_gate_ovrd & 0xFFF7FFFF) | 0x80000); + + MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000; + MAKE_MC_REG(MC_IRAM_TOM) = 0x4003F000; +} + +void mc_disable_ahb_redirect() +{ + volatile tegra_car_t *car = car_get_regs(); + + MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; + MAKE_MC_REG(MC_IRAM_TOM) = 0; + + car->lvl2_clk_gate_ovrd &= 0xFFF7FFFF; +} + +void mc_enable() +{ + volatile tegra_car_t *car = car_get_regs(); + + /* Set EMC clock source. */ + car->clk_source_emc = ((car->clk_source_emc & 0x1FFFFFFF) | 0x40000000); + + /* Enable MIPI CAL clock. */ + car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFDFFFFFF) | 0x2000000); + + /* Enable MC clock. */ + car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFFFFFFFE) | 1); + + /* Enable EMC DLL clock. */ + car->clk_enb_x_set = ((car->clk_enb_x_set & 0xFFFFBFFF) | 0x4000); + + /* Clear EMC and MC reset. */ + car->rst_dev_h_set = 0x2000001; + udelay(5); + + mc_disable_ahb_redirect(); +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/hwinit/mc.h b/fusee/fusee-secondary/src/mc.h similarity index 98% rename from fusee/fusee-secondary/src/hwinit/mc.h rename to fusee/fusee-secondary/src/mc.h index 7eebdf4e0..e93bfc7bf 100644 --- a/fusee/fusee-secondary/src/hwinit/mc.h +++ b/fusee/fusee-secondary/src/mc.h @@ -1,18 +1,11 @@ -/* -* Copyright (c) 2014, NVIDIA Corporation. All rights reserved. -* -* This software is licensed under the terms of the GNU General Public -* License version 2, as published by the Free Software Foundation, and -* may be copied, distributed, and modified under those terms. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -*/ +#ifndef FUSEE_MC_H_ +#define FUSEE_MC_H_ -#ifndef _MC_H_ -#define _MC_ +#include <stdint.h> +#include <stdbool.h> + +#define MC_BASE 0x70019000 +#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) #define MC_INTSTATUS 0x0 #define MC_INTMASK 0x4 @@ -463,4 +456,11 @@ #define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 #define MC_DA_CONFIG0 0x9dc -#endif +void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock); +void mc_config_carveout(); +void mc_config_carveout_finalize(); +void mc_enable_ahb_redirect(); +void mc_disable_ahb_redirect(); +void mc_enable(); + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 70c1f90f3..9d30d1454 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -6,6 +6,13 @@ #include "utils.h" #include "fs_utils.h" #include "nxboot.h" +#include "nxfs.h" +#include "di.h" +#include "mc.h" +#include "se.h" +#include "cluster.h" +#include "flow.h" +#include "timers.h" #include "key_derivation.h" #include "package1.h" #include "package2.h" @@ -14,7 +21,6 @@ #include "exocfg.h" #include "display/video_fb.h" #include "lib/ini.h" -#include "hwinit/t210.h" #define u8 uint8_t #define u32 uint32_t @@ -22,8 +28,6 @@ #undef u8 #undef u32 -#include "hwinit/cluster.h" - static int exosphere_ini_handler(void *user, const char *section, const char *name, const char *value) { exosphere_config_t *exo_cfg = (exosphere_config_t *)user; if (strcmp(section, "exosphere") == 0) { @@ -58,6 +62,7 @@ static void nxboot_configure_exosphere(void) { /* This is the main function responsible for booting Horizon. */ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; void nxboot_main(void) { + volatile tegra_se_t *se = se_get_regs(); loader_ctx_t *loader_ctx = get_loader_ctx(); /* void *bootconfig; */ package2_header_t *package2; @@ -74,7 +79,6 @@ void nxboot_main(void) { FILE *boot0, *pk2file; void *exosphere_memaddr; - /* TODO: How should we deal with bootconfig? */ package2 = memalign(4096, PACKAGE2_SIZE_MAX); if (package2 == NULL) { fatal_error("nxboot: out of memory!\n"); @@ -185,10 +189,12 @@ void nxboot_main(void) { } printf("Rebuilding package2...\n"); + /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); printf(u8"Reading Exosphère...\n"); + /* Copy Exosphère to a good location (or read it directly to it.) */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { exosphere_memaddr = (void *)0x40020000; @@ -211,26 +217,7 @@ void nxboot_main(void) { } else { memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); } - - /* Boot up Exosphère. */ - MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; - } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X; - } - printf("Powering on the CCPLEX...\n"); - cluster_enable_cpu0((uint64_t)(uintptr_t)exosphere_memaddr, 1); - while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { - /* Wait for Exosphere to wake up. */ - } - printf(u8"Exopshère is responding!\n"); - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED; - } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; - } - + /* Clean up. */ free(package1loader); if (loader_ctx->tsecfw_path[0] != '\0') { @@ -240,12 +227,79 @@ void nxboot_main(void) { free(warmboot_fw); } free(package2); + + /* Unmount everything. */ + nxfs_unmount_all(); + + /* Clear used keyslots. */ + clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); + clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); + + /* Lock keyslots. */ + set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF); + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); + } else { + set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); + } + /* TODO: Handle bootconfig. */ + memset((void *)0x4003D000, 0, 0x3000); + + /* Finalize the GPU UCODE carveout. */ + mc_config_carveout_finalize(); + + /* Lock AES keyslots. */ + for (uint32_t i = 0; i < 16; i++) + set_aes_keyslot_flags(i, 0x15); + + /* Lock RSA keyslots. */ + for (uint32_t i = 0; i < 2; i++) + set_rsa_keyslot_flags(i, 1); + + /* Lock the Security Engine. */ + se->_0x4 = 0; + se->AES_KEY_READ_DISABLE_REG = 0; + se->RSA_KEY_READ_DISABLE_REG = 0; + se->_0x0 &= 0xFFFFFFFB; + + /* Boot up Exosphère. */ + MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; + } else { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X; + } + + printf("Powering on the CCPLEX...\n"); + /* Display splash screen. */ display_splash_screen_bmp(loader_ctx->custom_splash_path); + + /* Turn off the backlight. */ + display_backlight(false); + + /* Terminate the display if necessary. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) + display_end(); + + /* Boot CPU0. */ + cluster_boot_cpu0((uint64_t)(uintptr_t)exosphere_memaddr); + + /* Wait for Exosphère to wake up. */ + while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { + udelay(1); + } + + /* Signal Exosphère. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED; + } else { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; + } - //Halt ourselves in waitevent state. + /* Halt ourselves in waitevent state. */ while (1) { - FLOW_CTLR(0x4) = 0x50000000; + FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; } } diff --git a/fusee/fusee-secondary/src/nxfs.c b/fusee/fusee-secondary/src/nxfs.c index 521117f3d..fcb05d0f9 100644 --- a/fusee/fusee-secondary/src/nxfs.c +++ b/fusee/fusee-secondary/src/nxfs.c @@ -4,9 +4,9 @@ #include <errno.h> #include <string.h> #include "nxfs.h" +#include "mc.h" #include "gpt.h" #include "se.h" -#include "hwinit.h" #include "utils.h" #include "sdmmc/sdmmc.h" diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index b968818f2..8449b72ac 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -85,7 +85,6 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm free(rebuilt_package2); } - static void package2_crypt_ctr(unsigned int master_key_rev, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { /* Derive package2 key. */ const uint8_t __attribute__((aligned(16))) package2_key_source[0x10] = { @@ -262,9 +261,6 @@ static size_t package2_get_thermosphere(void **thermosphere) { return 0; } - - - static ini1_header_t *package2_rebuild_ini1(ini1_header_t *ini1, uint32_t target_firmware) { /* TODO: Do we want to support loading another INI from sd:/whatever/INI1.bin? */ ini1_header_t *inis_to_merge[STRATOSPHERE_INI1_MAX] = {0}; diff --git a/fusee/fusee-secondary/src/panic.c b/fusee/fusee-secondary/src/panic.c index b5c4591b6..ce0b54747 100644 --- a/fusee/fusee-secondary/src/panic.c +++ b/fusee/fusee-secondary/src/panic.c @@ -1,8 +1,8 @@ #include "panic.h" +#include "di.h" #include "pmc.h" #include "fuse.h" #include "utils.h" -#include "hwinit.h" static uint32_t g_panic_code = 0; diff --git a/fusee/fusee-secondary/src/pinmux.h b/fusee/fusee-secondary/src/pinmux.h index d7131d1d5..80fc3a37c 100644 --- a/fusee/fusee-secondary/src/pinmux.h +++ b/fusee/fusee-secondary/src/pinmux.h @@ -1,6 +1,9 @@ #ifndef FUSEE_PINMUX_H #define FUSEE_PINMUX_H +#define PINMUX_BASE 0x70003000 +#define MAKE_PINMUX_REG(n) MAKE_REG32(PINMUX_BASE + n) + #define PINMUX_TRISTATE (1 << 4) #define PINMUX_PARKED (1 << 5) #define PINMUX_INPUT (1 << 6) @@ -186,7 +189,7 @@ typedef struct { static inline volatile tegra_pinmux_t *pinmux_get_regs(void) { - return (volatile tegra_pinmux_t *)0x70003000; + return (volatile tegra_pinmux_t *)PINMUX_BASE; } #endif diff --git a/fusee/fusee-secondary/src/pmc.h b/fusee/fusee-secondary/src/pmc.h index 4c10d1a0e..0c851eb47 100644 --- a/fusee/fusee-secondary/src/pmc.h +++ b/fusee/fusee-secondary/src/pmc.h @@ -1,25 +1,49 @@ #ifndef FUSEE_PMC_H #define FUSEE_PMC_H -/* TODO: get rid of these defines; use the struct instead */ +#include <stdint.h> + #define PMC_BASE 0x7000E400 +#define MAKE_PMC_REG(n) MAKE_REG32(PMC_BASE + n) #define PMC_CONTROL_SDMMC1 (1 << 12) #define PMC_CONTROL_SDMMC3 (1 << 13) #define PMC_CONTROL_SDMMC4 (1 << 14) -#define APBDEV_PMC_CONTROL MAKE_REG32(PMC_BASE + 0x00) -#define APBDEV_PMC_DPD_ENABLE_0 MAKE_REG32(PMC_BASE + 0x24) -#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_REG32(PMC_BASE + 0x30) -#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_REG32(PMC_BASE + 0x38) -#define APBDEV_PMC_SCRATCH0_0 MAKE_REG32(PMC_BASE + 0x50) -#define APBDEV_PMC_CRYPTO_OP_0 MAKE_REG32(PMC_BASE + 0xF4) -#define APBDEV_PM_0 MAKE_REG32(PMC_BASE + 0x14) -#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_REG32(PMC_BASE + 0x168) -#define APBDEV_PMC_RST_STATUS_0 MAKE_REG32(PMC_BASE + 0x1B4) -#define APBDEV_PMC_CNTRL2_0 MAKE_REG32(PMC_BASE + 0x440) -#define APBDEV_PMC_SCRATCH43_0 MAKE_REG32(PMC_BASE + 0x22C) -#define APBDEV_PMC_SCRATCH200_0 MAKE_REG32(PMC_BASE + 0x840) +#define APBDEV_PMC_CONTROL MAKE_PMC_REG(0x00) +#define APBDEV_PM_0 MAKE_PMC_REG(0x14) +#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x24) +#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x30) +#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x38) +#define APBDEV_PMC_NO_IOPOWER_0 MAKE_PMC_REG(0x44) +#define APBDEV_PMC_SCRATCH0_0 MAKE_PMC_REG(0x50) +#define APBDEV_PMC_SCRATCH1_0 MAKE_PMC_REG(0x54) +#define APBDEV_PMC_SCRATCH20_0 MAKE_PMC_REG(0xA0) +#define APBDEV_PMC_PWR_DET_VAL_0 MAKE_PMC_REG(0xE4) +#define APBDEV_PMC_DDR_PWR_0 MAKE_PMC_REG(0xE8) +#define APBDEV_PMC_CRYPTO_OP_0 MAKE_PMC_REG(0xF4) +#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_PMC_REG(0x168) +#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4) +#define APBDEV_PMC_RST_STATUS_0 MAKE_PMC_REG(0x1B4) +#define APBDEV_PMC_IO_DPD_REQ_0 MAKE_PMC_REG(0x1B8) +#define APBDEV_PMC_IO_DPD2_REQ_0 MAKE_PMC_REG(0x1C0) +#define APBDEV_PMC_VDDP_SEL_0 MAKE_PMC_REG(0x1CC) +#define APBDEV_PMC_SCRATCH49_0 MAKE_PMC_REG(0x244) +#define APBDEV_PMC_TSC_MULT_0 MAKE_PMC_REG(0x2B4) +#define APBDEV_PMC_REG_SHORT_0 MAKE_PMC_REG(0x2CC) +#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) +#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334) +#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360) +#define APBDEV_PMC_SECURE_SCRATCH49_0 MAKE_PMC_REG(0x3A4) +#define APBDEV_PMC_CNTRL2_0 MAKE_PMC_REG(0x440) +#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464) +#define APBDEV_PMC_UTMIP_PAD_CFG1_0 MAKE_PMC_REG(0x4C4) +#define APBDEV_PMC_UTMIP_PAD_CFG3_0 MAKE_PMC_REG(0x4CC) +#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4) +#define APBDEV_PMC_SCRATCH43_0 MAKE_PMC_REG(0x22C) +#define APBDEV_PMC_SCRATCH188_0 MAKE_PMC_REG(0x810) +#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) +#define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840) typedef struct { uint32_t cntrl; @@ -42,7 +66,6 @@ typedef struct { uint32_t no_iopower; uint32_t pwr_det; uint32_t pwr_det_latch; - uint32_t scratch0; uint32_t scratch1; uint32_t scratch2; @@ -67,14 +90,12 @@ typedef struct { uint32_t scratch21; uint32_t scratch22; uint32_t scratch23; - uint32_t secure_scratch0; uint32_t secure_scratch1; uint32_t secure_scratch2; uint32_t secure_scratch3; uint32_t secure_scratch4; uint32_t secure_scratch5; - uint32_t cpupwrgood_timer; uint32_t cpupwroff_timer; uint32_t pg_mask; @@ -88,7 +109,6 @@ typedef struct { uint32_t usb_ao; uint32_t crypto_op; uint32_t pllp_wb0_override; - uint32_t scratch24; uint32_t scratch25; uint32_t scratch26; @@ -108,7 +128,6 @@ typedef struct { uint32_t scratch40; uint32_t scratch41; uint32_t scratch42; - uint32_t bo_mirror0; uint32_t bo_mirror1; uint32_t bo_mirror2; @@ -143,10 +162,9 @@ typedef struct { uint32_t io_dpd2_stat; uint32_t sel_dpd_tim; uint32_t vddp_sel; - uint32_t ddr_cfg; uint32_t e_no_vttgen; - uint32_t reserved0; + uint32_t _reserved0; uint32_t pllm_wb0_ovrride_frq; uint32_t test_pwrgate; uint32_t pwrgate_timer_mult; @@ -156,8 +174,12 @@ typedef struct { uint32_t utmip_pad_cfg; uint32_t utmip_term_pad_cfg; uint32_t utmip_uhsic_sleep_cfg; - - uint32_t todo_0[9]; + uint32_t utmip_uhsic_sleepwalk_cfg; + uint32_t utmip_sleepwalk_p[3]; + uint32_t uhsic_sleepwalk_p0; + uint32_t utmip_uhsic_status; + uint32_t utmip_uhsic_fake; + uint32_t bo_mirror3[2]; uint32_t secure_scratch6; uint32_t secure_scratch7; uint32_t scratch43; @@ -176,7 +198,22 @@ typedef struct { uint32_t scratch0_eco; uint32_t por_dpd_ctrl; uint32_t scratch2_eco; - uint32_t todo_1[17]; + uint32_t utmip_uhsic_line_wakeup; + uint32_t utmip_bias_master_cntrl; + uint32_t utmip_master_config; + uint32_t td_pwrgate_inter_part_timer; + uint32_t utmip_uhsic2_triggers; + uint32_t utmip_uhsic2_saved_state; + uint32_t utmip_uhsic2_sleep_cfg; + uint32_t utmip_uhsic2_sleepwalk_cfg; + uint32_t uhsic2_sleepwalk_p1; + uint32_t utmip_uhsic2_status; + uint32_t utmip_uhsic2_fake; + uint32_t utmip_uhsic2_line_wakeup; + uint32_t utmip_master2_config; + uint32_t utmip_uhsic_rpd_cfg; + uint32_t pg_mask_ce0; + uint32_t pg_mask3[2]; uint32_t pllm_wb0_override2; uint32_t tsc_mult; uint32_t cpu_vsense_override; @@ -184,7 +221,9 @@ typedef struct { uint32_t sticky_bits; uint32_t sec_disable2; uint32_t weak_bias; - uint32_t todo_3[13]; + uint32_t reg_short; + uint32_t pg_mask_andor; + uint32_t _reserved1[11]; uint32_t secure_scratch8; uint32_t secure_scratch9; uint32_t secure_scratch10; @@ -213,15 +252,64 @@ typedef struct { uint32_t secure_scratch33; uint32_t secure_scratch34; uint32_t secure_scratch35; - - uint32_t reserved1[52]; + uint32_t secure_scratch36; + uint32_t secure_scratch37; + uint32_t secure_scratch38; + uint32_t secure_scratch39; + uint32_t secure_scratch40; + uint32_t secure_scratch41; + uint32_t secure_scratch42; + uint32_t secure_scratch43; + uint32_t secure_scratch44; + uint32_t secure_scratch45; + uint32_t secure_scratch46; + uint32_t secure_scratch47; + uint32_t secure_scratch48; + uint32_t secure_scratch49; + uint32_t secure_scratch50; + uint32_t secure_scratch51; + uint32_t secure_scratch52; + uint32_t secure_scratch53; + uint32_t secure_scratch54; + uint32_t secure_scratch55; + uint32_t secure_scratch56; + uint32_t secure_scratch57; + uint32_t secure_scratch58; + uint32_t secure_scratch59; + uint32_t secure_scratch60; + uint32_t secure_scratch61; + uint32_t secure_scratch62; + uint32_t secure_scratch63; + uint32_t secure_scratch64; + uint32_t secure_scratch65; + uint32_t secure_scratch66; + uint32_t secure_scratch67; + uint32_t secure_scratch68; + uint32_t secure_scratch69; + uint32_t secure_scratch70; + uint32_t secure_scratch71; + uint32_t secure_scratch72; + uint32_t secure_scratch73; + uint32_t secure_scratch74; + uint32_t secure_scratch75; + uint32_t secure_scratch76; + uint32_t secure_scratch77; + uint32_t secure_scratch78; + uint32_t secure_scratch79; + uint32_t _reserved2[8]; uint32_t cntrl2; - uint32_t reserved2[6]; + uint32_t _reserved3[2]; + uint32_t event_counter; + uint32_t fuse_control; + uint32_t scratch1_eco; + uint32_t _reserved4; uint32_t io_dpd3_req; - uint32_t io_dpd3_stat; - uint32_t strap_opt_a; - uint32_t reserved3[102]; - + uint32_t io_dpd3_status; + uint32_t io_dpd4_req; + uint32_t io_dpd4_status; + uint32_t _reserved5[30]; + uint32_t ddr_cntrl; + uint32_t _reserved6[70]; uint32_t scratch56; uint32_t scratch57; uint32_t scratch58; @@ -286,12 +374,232 @@ typedef struct { uint32_t scratch117; uint32_t scratch118; uint32_t scratch119; - uint32_t scratch1_eco; + uint32_t scratch120; + uint32_t scratch121; + uint32_t scratch122; + uint32_t scratch123; + uint32_t scratch124; + uint32_t scratch125; + uint32_t scratch126; + uint32_t scratch127; + uint32_t scratch128; + uint32_t scratch129; + uint32_t scratch130; + uint32_t scratch131; + uint32_t scratch132; + uint32_t scratch133; + uint32_t scratch134; + uint32_t scratch135; + uint32_t scratch136; + uint32_t scratch137; + uint32_t scratch138; + uint32_t scratch139; + uint32_t scratch140; + uint32_t scratch141; + uint32_t scratch142; + uint32_t scratch143; + uint32_t scratch144; + uint32_t scratch145; + uint32_t scratch146; + uint32_t scratch147; + uint32_t scratch148; + uint32_t scratch149; + uint32_t scratch150; + uint32_t scratch151; + uint32_t scratch152; + uint32_t scratch153; + uint32_t scratch154; + uint32_t scratch155; + uint32_t scratch156; + uint32_t scratch157; + uint32_t scratch158; + uint32_t scratch159; + uint32_t scratch160; + uint32_t scratch161; + uint32_t scratch162; + uint32_t scratch163; + uint32_t scratch164; + uint32_t scratch165; + uint32_t scratch166; + uint32_t scratch167; + uint32_t scratch168; + uint32_t scratch169; + uint32_t scratch170; + uint32_t scratch171; + uint32_t scratch172; + uint32_t scratch173; + uint32_t scratch174; + uint32_t scratch175; + uint32_t scratch176; + uint32_t scratch177; + uint32_t scratch178; + uint32_t scratch179; + uint32_t scratch180; + uint32_t scratch181; + uint32_t scratch182; + uint32_t scratch183; + uint32_t scratch184; + uint32_t scratch185; + uint32_t scratch186; + uint32_t scratch187; + uint32_t scratch188; + uint32_t scratch189; + uint32_t scratch190; + uint32_t scratch191; + uint32_t scratch192; + uint32_t scratch193; + uint32_t scratch194; + uint32_t scratch195; + uint32_t scratch196; + uint32_t scratch197; + uint32_t scratch198; + uint32_t scratch199; + uint32_t scratch200; + uint32_t scratch201; + uint32_t scratch202; + uint32_t scratch203; + uint32_t scratch204; + uint32_t scratch205; + uint32_t scratch206; + uint32_t scratch207; + uint32_t scratch208; + uint32_t scratch209; + uint32_t scratch210; + uint32_t scratch211; + uint32_t scratch212; + uint32_t scratch213; + uint32_t scratch214; + uint32_t scratch215; + uint32_t scratch216; + uint32_t scratch217; + uint32_t scratch218; + uint32_t scratch219; + uint32_t scratch220; + uint32_t scratch221; + uint32_t scratch222; + uint32_t scratch223; + uint32_t scratch224; + uint32_t scratch225; + uint32_t scratch226; + uint32_t scratch227; + uint32_t scratch228; + uint32_t scratch229; + uint32_t scratch230; + uint32_t scratch231; + uint32_t scratch232; + uint32_t scratch233; + uint32_t scratch234; + uint32_t scratch235; + uint32_t scratch236; + uint32_t scratch237; + uint32_t scratch238; + uint32_t scratch239; + uint32_t scratch240; + uint32_t scratch241; + uint32_t scratch242; + uint32_t scratch243; + uint32_t scratch244; + uint32_t scratch245; + uint32_t scratch246; + uint32_t scratch247; + uint32_t scratch248; + uint32_t scratch249; + uint32_t scratch250; + uint32_t scratch251; + uint32_t scratch252; + uint32_t scratch253; + uint32_t scratch254; + uint32_t scratch255; + uint32_t scratch256; + uint32_t scratch257; + uint32_t scratch258; + uint32_t scratch259; + uint32_t scratch260; + uint32_t scratch261; + uint32_t scratch262; + uint32_t scratch263; + uint32_t scratch264; + uint32_t scratch265; + uint32_t scratch266; + uint32_t scratch267; + uint32_t scratch268; + uint32_t scratch269; + uint32_t scratch270; + uint32_t scratch271; + uint32_t scratch272; + uint32_t scratch273; + uint32_t scratch274; + uint32_t scratch275; + uint32_t scratch276; + uint32_t scratch277; + uint32_t scratch278; + uint32_t scratch279; + uint32_t scratch280; + uint32_t scratch281; + uint32_t scratch282; + uint32_t scratch283; + uint32_t scratch284; + uint32_t scratch285; + uint32_t scratch286; + uint32_t scratch287; + uint32_t scratch288; + uint32_t scratch289; + uint32_t scratch290; + uint32_t scratch291; + uint32_t scratch292; + uint32_t scratch293; + uint32_t scratch294; + uint32_t scratch295; + uint32_t scratch296; + uint32_t scratch297; + uint32_t scratch298; + uint32_t scratch299; + uint32_t _reserved7[50]; + uint32_t secure_scratch80; + uint32_t secure_scratch81; + uint32_t secure_scratch82; + uint32_t secure_scratch83; + uint32_t secure_scratch84; + uint32_t secure_scratch85; + uint32_t secure_scratch86; + uint32_t secure_scratch87; + uint32_t secure_scratch88; + uint32_t secure_scratch89; + uint32_t secure_scratch90; + uint32_t secure_scratch91; + uint32_t secure_scratch92; + uint32_t secure_scratch93; + uint32_t secure_scratch94; + uint32_t secure_scratch95; + uint32_t secure_scratch96; + uint32_t secure_scratch97; + uint32_t secure_scratch98; + uint32_t secure_scratch99; + uint32_t secure_scratch100; + uint32_t secure_scratch101; + uint32_t secure_scratch102; + uint32_t secure_scratch103; + uint32_t secure_scratch104; + uint32_t secure_scratch105; + uint32_t secure_scratch106; + uint32_t secure_scratch107; + uint32_t secure_scratch108; + uint32_t secure_scratch109; + uint32_t secure_scratch110; + uint32_t secure_scratch111; + uint32_t secure_scratch112; + uint32_t secure_scratch113; + uint32_t secure_scratch114; + uint32_t secure_scratch115; + uint32_t secure_scratch116; + uint32_t secure_scratch117; + uint32_t secure_scratch118; + uint32_t secure_scratch119; } tegra_pmc_t; static inline volatile tegra_pmc_t *pmc_get_regs(void) { - return (volatile tegra_pmc_t *)0x7000E400; + return (volatile tegra_pmc_t *)PMC_BASE; } #endif diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index 85cab87ba..c30a1f837 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -11,8 +11,8 @@ #include "../apb_misc.h" #include "../gpio.h" #include "../pmc.h" +#include "../max7762x.h" #include "../lib/driver_utils.h" -#include "../hwinit/max7762x.h" static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; @@ -399,16 +399,16 @@ static int sdmmc_clk_set_source(SdmmcControllerNum controller, uint32_t clk_freq switch (controller) { case SDMMC_1: - car->clk_src[CLK_SOURCE_SDMMC1] = (CLK_SOURCE_FIRST | car_div); + car->clk_source_sdmmc1 = (CLK_SOURCE_FIRST | car_div); break; case SDMMC_2: - car->clk_src[CLK_SOURCE_SDMMC2] = (CLK_SOURCE_FIRST | car_div); + car->clk_source_sdmmc2 = (CLK_SOURCE_FIRST | car_div); break; case SDMMC_3: - car->clk_src[CLK_SOURCE_SDMMC3] = (CLK_SOURCE_FIRST | car_div); + car->clk_source_sdmmc3 = (CLK_SOURCE_FIRST | car_div); break; case SDMMC_4: - car->clk_src[CLK_SOURCE_SDMMC4] = (CLK_SOURCE_FIRST | car_div); + car->clk_source_sdmmc4 = (CLK_SOURCE_FIRST | car_div); break; } diff --git a/fusee/fusee-secondary/src/se.c b/fusee/fusee-secondary/src/se.c index 18e16bd99..af86980b3 100644 --- a/fusee/fusee-secondary/src/se.c +++ b/fusee/fusee-secondary/src/se.c @@ -1,7 +1,6 @@ #include <string.h> #include "utils.h" -/*#include "interrupt.h"*/ #include "se.h" void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size); @@ -24,42 +23,49 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { } void se_check_error_status_reg(void) { - if (SECURITY_ENGINE->ERR_STATUS_REG) { + volatile tegra_se_t *se = se_get_regs(); + if (se->ERR_STATUS_REG) { generic_panic(); } } void se_check_for_error(void) { - if (SECURITY_ENGINE->INT_STATUS_REG & 0x10000 || SECURITY_ENGINE->FLAGS_REG & 3 || SECURITY_ENGINE->ERR_STATUS_REG) { + volatile tegra_se_t *se = se_get_regs(); + if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) { generic_panic(); } } void se_verify_flags_cleared(void) { - if (SECURITY_ENGINE->FLAGS_REG & 3) { + volatile tegra_se_t *se = se_get_regs(); + if (se->FLAGS_REG & 3) { generic_panic(); } } /* Set the flags for an AES keyslot. */ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Misc flags. */ if (flags & ~0x80) { - SECURITY_ENGINE->AES_KEYSLOT_FLAGS[keyslot] = ~flags; + se->AES_KEYSLOT_FLAGS[keyslot] = ~flags; } /* Disable keyslot reads. */ if (flags & 0x80) { - SECURITY_ENGINE->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); } } /* Set the flags for an RSA keyslot. */ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX) { generic_panic(); } @@ -67,28 +73,32 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { /* Misc flags. */ if (flags & ~0x80) { /* TODO: Why are flags assigned this way? */ - SECURITY_ENGINE->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; + se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; } /* Disable keyslot reads. */ if (flags & 0x80) { - SECURITY_ENGINE->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); } } void clear_aes_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Zero out the whole keyslot and IV. */ for (unsigned int i = 0; i < 0x10; i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = 0; + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = 0; } } void clear_rsa_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX) { generic_panic(); } @@ -96,40 +106,44 @@ void clear_rsa_keyslot(unsigned int keyslot) { /* Zero out the whole keyslot. */ for (unsigned int i = 0; i < 0x40; i++) { /* Select Keyslot Modulus[i] */ - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = 0; + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; + se->RSA_KEYTABLE_DATA = 0; } for (unsigned int i = 0; i < 0x40; i++) { /* Select Keyslot Expontent[i] */ - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = 0; + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = 0; } } void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { generic_panic(); } for (size_t i = 0; i < (key_size >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = read32le(key, 4 * i); + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = read32le(key, 4 * i); } } void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { generic_panic(); } for (size_t i = 0; i < (modulus_size >> 2); i++) { - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; + se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); } for (size_t i = 0; i < (exp_size >> 2); i++) { - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); } g_se_modulus_sizes[keyslot] = modulus_size; @@ -137,47 +151,55 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_ } void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { generic_panic(); } for (size_t i = 0; i < (iv_size >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = read32le(iv, 4 * i); + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = read32le(iv, 4 * i); } } void clear_aes_keyslot_iv(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } for (size_t i = 0; i < (0x10 >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = 0; + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = 0; } } void set_se_ctr(const void *ctr) { + volatile tegra_se_t *se = se_get_regs(); for (unsigned int i = 0; i < 4; i++) { - SECURITY_ENGINE->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + se->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); } } void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); - SECURITY_ENGINE->CRYPTO_REG = keyslot_src << 24; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; - SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; + se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); + se->CRYPTO_REG = keyslot_src << 24; + se->BLOCK_COUNT_REG = 0; + se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); } void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); uint8_t ALIGN(16) stack_buf[KEYSIZE_RSA_MAX]; if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) { @@ -189,18 +211,19 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co stack_buf[i] = *((uint8_t *)src + src_size - i - 1); } - SECURITY_ENGINE->CONFIG_REG = (ALG_RSA | DST_RSAREG); - SECURITY_ENGINE->RSA_CONFIG = keyslot << 24; - SECURITY_ENGINE->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; - SECURITY_ENGINE->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; - + se->CONFIG_REG = (ALG_RSA | DST_RSAREG); + se->RSA_CONFIG = keyslot << 24; + se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; + se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size); se_get_exp_mod_output(dst, dst_size); } void se_get_exp_mod_output(void *buf, size_t size) { + volatile tegra_se_t *se = se_get_regs(); size_t num_dwords = (size >> 2); + if (num_dwords < 1) { return; } @@ -210,7 +233,7 @@ void se_get_exp_mod_output(void *buf, size_t size) { /* Copy endian swapped output. */ while (num_dwords) { - *p_out = read32be(SECURITY_ENGINE->RSA_OUTPUT, offset); + *p_out = read32be(se->RSA_OUTPUT, offset); offset += 4; p_out--; num_dwords--; @@ -271,6 +294,7 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v } void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); se_ll_t in_ll; se_ll_t out_ll; @@ -278,21 +302,22 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v ll_init(&out_ll, dst, dst_size); /* Set the LLs. */ - SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); - SECURITY_ENGINE->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll); + se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); + se->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll); /* Set registers for operation. */ - SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG; - SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG; - SECURITY_ENGINE->OPERATION_REG = op; + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = op; - while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ } + while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ } se_check_for_error(); } /* Secure AES Functionality. */ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); uint8_t block[0x10] = {0}; if (src_size > sizeof(block) || dst_size > sizeof(block)) { @@ -305,7 +330,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } /* Trigger AES operation. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); /* Copy output data into dst. */ @@ -315,21 +340,23 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) { generic_panic(); } unsigned int num_blocks = src_size >> 4; /* Unknown what this write does, but official code writes it for CTR mode. */ - SECURITY_ENGINE->_0x80C = 1; - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x91E; + se->SPARE_0 = 1; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x91E; set_se_ctr(ctr); /* Handle any aligned blocks. */ size_t aligned_size = (size_t)num_blocks << 4; if (aligned_size) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1; + se->BLOCK_COUNT_REG = num_blocks - 1; trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size); } @@ -344,15 +371,16 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo } void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } /* Set configuration high (256-bit vs 128-bit) based on parameter. */ - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); - SECURITY_ENGINE->CRYPTO_REG = keyslot << 24 | 0x100; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); + se->CRYPTO_REG = keyslot << 24 | 0x100; se_perform_aes_block_operation(dst, 0x10, src, 0x10); - } void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { @@ -365,12 +393,14 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = keyslot << 24; + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot << 24; se_perform_aes_block_operation(dst, 0x10, src, 0x10); } @@ -422,6 +452,8 @@ void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, ui } void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keyslot_2, size_t sector, bool encrypt, void *dst, const void *src, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + if ((size & 0xF) || size == 0) { generic_panic(); } @@ -431,13 +463,13 @@ void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keys /* Encrypt/Decrypt. */ if (encrypt) { - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = keyslot_1 << 24 | 0x100; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = keyslot_1 << 24 | 0x100; } else { - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = keyslot_1 << 24; + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot_1 << 24; } - SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1; + se->BLOCK_COUNT_REG = (size >> 4) - 1; trigger_se_blocking_op(OP_START, dst, size, src, size); /* XOR. */ @@ -469,6 +501,8 @@ void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslo } void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -481,17 +515,17 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con shift_left_xor_rb(derived_key); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | (0x145); + se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); + se->CRYPTO_REG = (keyslot << 24) | (0x145); clear_aes_keyslot_iv(keyslot); unsigned int num_blocks = (data_size + 0xF) >> 4; /* Handle aligned blocks. */ if (num_blocks > 1) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 2; + se->BLOCK_COUNT_REG = num_blocks - 2; trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); - SECURITY_ENGINE->CRYPTO_REG |= 0x80; + se->CRYPTO_REG |= 0x80; } /* Create final block. */ @@ -508,12 +542,12 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con } /* Perform last operation. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); /* Copy output CMAC. */ for (unsigned int i = 0; i < (cmac_size >> 2); i++) { - ((uint32_t *)cmac)[i] = read32le(SECURITY_ENGINE->HASH_RESULT_REG, i << 2); + ((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2); } } @@ -525,42 +559,48 @@ void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, } void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x144; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); + se->CRYPTO_REG = (keyslot << 24) | 0x144; set_aes_keyslot_iv(keyslot, iv, 0x10); - SECURITY_ENGINE->BLOCK_COUNT_REG = (src_size >> 4) - 1; + se->BLOCK_COUNT_REG = (src_size >> 4) - 1; trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); } /* SHA256 Implementation. */ void se_calculate_sha256(void *dst, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + /* Setup config for SHA256, size = BITS(src_size) */ - SECURITY_ENGINE->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); - SECURITY_ENGINE->SHA_CONFIG_REG = 1; - SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); - SECURITY_ENGINE->_0x208 = 0; - SECURITY_ENGINE->_0x20C = 0; - SECURITY_ENGINE->_0x210 = 0; - SECURITY_ENGINE->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); - SECURITY_ENGINE->_0x218 = 0; - SECURITY_ENGINE->_0x21C = 0; - SECURITY_ENGINE->_0x220 = 0; + se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); + se->SHA_CONFIG_REG = 1; + se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); + se->_0x208 = 0; + se->_0x20C = 0; + se->_0x210 = 0; + se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); + se->_0x218 = 0; + se->_0x21C = 0; + se->_0x220 = 0; /* Trigger the operation. */ trigger_se_blocking_op(OP_START, NULL, 0, src, src_size); /* Copy output hash. */ for (unsigned int i = 0; i < (0x20 >> 2); i++) { - ((uint32_t *)dst)[i] = read32be(SECURITY_ENGINE->HASH_RESULT_REG, i << 2); + ((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2); } } /* RNG API */ void se_initialize_rng(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -569,32 +609,33 @@ void se_initialize_rng(unsigned int keyslot) { /* This will be discarded, when done. */ uint8_t ALIGN(16) output_buf[0x10]; - SECURITY_ENGINE->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ - SECURITY_ENGINE->RNG_RESEED_INTERVAL_REG = 70001; - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 5; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ + se->RNG_RESEED_INTERVAL_REG = 70001; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 5; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0); } void se_generate_random(unsigned int keyslot, void *dst, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } uint32_t num_blocks = size >> 4; size_t aligned_size = num_blocks << 4; - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 4; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 4; if (num_blocks >= 1) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1; + se->BLOCK_COUNT_REG = num_blocks - 1; trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0); } if (size > aligned_size) { se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0); } - } diff --git a/fusee/fusee-secondary/src/se.h b/fusee/fusee-secondary/src/se.h index a1ef7fa84..311567261 100644 --- a/fusee/fusee-secondary/src/se.h +++ b/fusee/fusee-secondary/src/se.h @@ -1,7 +1,8 @@ #ifndef FUSEE_SE_H #define FUSEE_SE_H -#include <assert.h> +#define SE_BASE 0x70012000 +#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n) #define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2 #define KEYSLOT_SWITCH_SRKGENKEY 0x8 @@ -98,10 +99,10 @@ typedef struct security_engine { uint32_t _0x21C; uint32_t _0x220; uint32_t _0x224; - uint8_t _0x228[0x5C]; + uint8_t _0x228[0x58]; uint32_t AES_KEY_READ_DISABLE_REG; uint32_t AES_KEYSLOT_FLAGS[0x10]; - uint8_t _0x2C8[0x38]; + uint8_t _0x2C4[0x3C]; uint32_t _0x300; uint32_t CRYPTO_REG; uint32_t CRYPTO_CTR_REG[4]; @@ -131,15 +132,13 @@ typedef struct security_engine { uint32_t FLAGS_REG; uint32_t ERR_STATUS_REG; uint32_t _0x808; - uint32_t _0x80C; + uint32_t SPARE_0; uint32_t _0x810; uint32_t _0x814; uint32_t _0x818; uint32_t _0x81C; uint8_t _0x820[0x17E0]; -} security_engine_t; - -static_assert(sizeof(security_engine_t) == 0x2000, "Mis-defined Security Engine Registers!"); +} tegra_se_t; typedef struct { uint32_t address; @@ -151,15 +150,10 @@ typedef struct { se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ } se_ll_t; - -/* WIP, API subject to change. */ - -static inline volatile security_engine_t *get_security_engine(void) { - return (volatile security_engine_t *)0x70012000; +static inline volatile tegra_se_t *se_get_regs(void) { + return (volatile tegra_se_t *)SE_BASE; } -#define SECURITY_ENGINE (get_security_engine()) - /* This function MUST be registered to fire on the appropriate interrupt. */ void se_check_error_status_reg(void); diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index e849c88bc..a0d1b5db0 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -27,7 +27,7 @@ extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size; /* GCC doesn't consider the size as const... we have to write it ourselves. */ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { - const uint8_t *boot_kip = NULL; + /* const uint8_t *boot_kip = NULL; */ uint32_t boot_kip_size = 0; uint8_t *data; @@ -36,10 +36,10 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { } if (target_firmware <= EXOSPHERE_TARGET_FIRMWARE_100) { - boot_kip = boot_100_kip; + /* boot_kip = boot_100_kip; */ boot_kip_size = boot_100_kip_size; } else { - boot_kip = boot_200_kip; + /* boot_kip = boot_200_kip; */ boot_kip_size = boot_200_kip_size; } @@ -52,7 +52,7 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { g_stratosphere_ini1->magic = MAGIC_INI1; g_stratosphere_ini1->size = size; - g_stratosphere_ini1->num_processes = 4; + g_stratosphere_ini1->num_processes = 3; /*TODO: Change to 4 when boot is supported. */ g_stratosphere_ini1->_0xC = 0; data = g_stratosphere_ini1->kip_data; @@ -67,9 +67,12 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { memcpy(data, sm_kip, sm_kip_size); data += sm_kip_size; + /* TODO: Uncomment when boot is supported. */ + /* memcpy(data, boot_kip, boot_kip_size); data += boot_kip_size; - + */ + return g_stratosphere_ini1; } diff --git a/fusee/fusee-secondary/src/sysreg.h b/fusee/fusee-secondary/src/sysreg.h new file mode 100644 index 000000000..d69cf8897 --- /dev/null +++ b/fusee/fusee-secondary/src/sysreg.h @@ -0,0 +1,32 @@ +#ifndef FUSEE_SYSREG_H +#define FUSEE_SYSREG_H + +#include <stdint.h> + +#define SYSREG_BASE 0x6000C000 +#define SB_BASE (SYSREG_BASE + 0x200) +#define EXCP_VEC_BASE 0x6000F000 + +#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n) +#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n) +#define MAKE_EXCP_VEC_REG(n) MAKE_REG32(EXCP_VEC_BASE + n) + +#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004) +#define AHB_ARBITRATION_XBAR_CTRL_0 MAKE_SYSREG(0x0E0) +#define AHB_AHB_SPARE_REG_0 MAKE_SYSREG(0x110) + +#define SB_CSR_0 MAKE_SB_REG(0x00) +#define SB_PIROM_START_0 MAKE_SB_REG(0x04) +#define SB_PFCFG_0 MAKE_SB_REG(0x08) +#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C) +#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10) +#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14) +#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18) +#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C) +#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20) +#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24) +#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28) +#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30) +#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34) + +#endif diff --git a/fusee/fusee-secondary/src/timers.h b/fusee/fusee-secondary/src/timers.h index 519c0292f..8c9569c19 100644 --- a/fusee/fusee-secondary/src/timers.h +++ b/fusee/fusee-secondary/src/timers.h @@ -8,6 +8,7 @@ #define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10) #define RTC_BASE 0x7000E000 +#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) #define RTC_SECONDS MAKE_REG32(RTC_BASE + 0x08) #define RTC_SHADOW_SECONDS MAKE_REG32(RTC_BASE + 0x0C) #define RTC_MILLI_SECONDS MAKE_REG32(RTC_BASE + 0x10) diff --git a/fusee/fusee-secondary/src/tsec.c b/fusee/fusee-secondary/src/tsec.c new file mode 100644 index 000000000..12e8613ec --- /dev/null +++ b/fusee/fusee-secondary/src/tsec.c @@ -0,0 +1,156 @@ +#include "tsec.h" +#include "di.h" +#include "timers.h" +#include "car.h" + +static int tsec_dma_wait_idle() +{ + volatile tegra_tsec_t *tsec = tsec_get_regs(); + uint32_t timeout = (get_time_ms() + 10000); + + while (!(tsec->FALCON_DMATRFCMD & 2)) + if (get_time_ms() > timeout) + return 0; + + return 1; +} + +static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t phys_offset) +{ + volatile tegra_tsec_t *tsec = tsec_get_regs(); + uint32_t cmd = 0; + + if (!is_imem) + cmd = 0x600; + else + cmd = 0x10; + + tsec->FALCON_DMATRFMOFFS = flcn_offset; + tsec->FALCON_DMATRFFBOFFS = phys_offset; + tsec->FALCON_DMATRFCMD = cmd; + + return tsec_dma_wait_idle(); +} + +int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw) +{ + volatile tegra_tsec_t *tsec = tsec_get_regs(); + + /* Enable clocks. */ + clkrst_reboot(CARDEVICE_HOST1X); + clkrst_reboot(CARDEVICE_TSEC); + clkrst_reboot(CARDEVICE_SOR_SAFE); + clkrst_reboot(CARDEVICE_SOR0); + clkrst_reboot(CARDEVICE_SOR1); + clkrst_reboot(CARDEVICE_KFUSE); + + /* Configure Falcon. */ + tsec->FALCON_DMACTL = 0; + tsec->FALCON_IRQMSET = 0xFFF2; + tsec->FALCON_IRQDEST = 0xFFF0; + tsec->FALCON_ITFEN = 3; + + if (!tsec_dma_wait_idle()) + { + /* Disable clocks. */ + clkrst_disable(CARDEVICE_KFUSE); + clkrst_disable(CARDEVICE_SOR1); + clkrst_disable(CARDEVICE_SOR0); + clkrst_disable(CARDEVICE_SOR_SAFE); + clkrst_disable(CARDEVICE_TSEC); + clkrst_disable(CARDEVICE_HOST1X); + + return -1; + } + + /* Load firmware. */ + tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8; + for (uint32_t addr = 0; addr < 0xF00; addr += 0x100) + { + if (!tsec_dma_phys_to_flcn(true, addr, addr)) + { + /* Disable clocks. */ + clkrst_disable(CARDEVICE_KFUSE); + clkrst_disable(CARDEVICE_SOR1); + clkrst_disable(CARDEVICE_SOR0); + clkrst_disable(CARDEVICE_SOR_SAFE); + clkrst_disable(CARDEVICE_TSEC); + clkrst_disable(CARDEVICE_HOST1X); + + return -2; + } + } + + /* Unknown host1x write. */ + MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA; + + /* Execute firmware. */ + tsec->FALCON_SCRATCH1 = 0; + tsec->FALCON_SCRATCH0 = rev; + tsec->FALCON_BOOTVEC = 0; + tsec->FALCON_CPUCTL = 2; + + if (!tsec_dma_wait_idle()) + { + /* Disable clocks. */ + clkrst_disable(CARDEVICE_KFUSE); + clkrst_disable(CARDEVICE_SOR1); + clkrst_disable(CARDEVICE_SOR0); + clkrst_disable(CARDEVICE_SOR_SAFE); + clkrst_disable(CARDEVICE_TSEC); + clkrst_disable(CARDEVICE_HOST1X); + + return -3; + } + + uint32_t timeout = (get_time_ms() + 2000); + while (!tsec->FALCON_SCRATCH1) + { + if (get_time_ms() > timeout) + { + /* Disable clocks. */ + clkrst_disable(CARDEVICE_KFUSE); + clkrst_disable(CARDEVICE_SOR1); + clkrst_disable(CARDEVICE_SOR0); + clkrst_disable(CARDEVICE_SOR_SAFE); + clkrst_disable(CARDEVICE_TSEC); + clkrst_disable(CARDEVICE_HOST1X); + + return -4; + } + } + + if (tsec->FALCON_SCRATCH1 != 0xB0B0B0B0) + { + /* Disable clocks. */ + clkrst_disable(CARDEVICE_KFUSE); + clkrst_disable(CARDEVICE_SOR1); + clkrst_disable(CARDEVICE_SOR0); + clkrst_disable(CARDEVICE_SOR_SAFE); + clkrst_disable(CARDEVICE_TSEC); + clkrst_disable(CARDEVICE_HOST1X); + + return -5; + } + + /* Unknown host1x write. */ + MAKE_HOST1X_REG(0x3300) = 0; + + /* Fetch result from SOR1. */ + uint32_t tmp[0x4] = {0}; + tmp[0] = SOR1_DP_HDCP_BKSV_LSB; + tmp[1] = SOR1_TMDS_HDCP_BKSV_LSB; + tmp[2] = SOR1_TMDS_HDCP_CN_MSB; + tmp[3] = SOR1_TMDS_HDCP_CN_LSB; + + /* Clear SOR1 registers. */ + SOR1_DP_HDCP_BKSV_LSB = 0; + SOR1_TMDS_HDCP_BKSV_LSB = 0; + SOR1_TMDS_HDCP_CN_MSB = 0; + SOR1_TMDS_HDCP_CN_LSB = 0; + + /* Copy back the key. */ + memcpy(key, &tmp, 0x10); + + return 0; +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/tsec.h b/fusee/fusee-secondary/src/tsec.h new file mode 100644 index 000000000..47be450bd --- /dev/null +++ b/fusee/fusee-secondary/src/tsec.h @@ -0,0 +1,97 @@ +#ifndef FUSEE_TSEC_H_ +#define FUSEE_TSEC_H_ + +#include <string.h> +#include <stdbool.h> + +#define TSEC_BASE 0x54500000 +#define SOR1_BASE 0x54580000 + +#define SOR1_DP_HDCP_BKSV_LSB MAKE_REG32(SOR1_BASE + 0x1E8) +#define SOR1_TMDS_HDCP_BKSV_LSB MAKE_REG32(SOR1_BASE + 0x21C) +#define SOR1_TMDS_HDCP_CN_MSB MAKE_REG32(SOR1_BASE + 0x208) +#define SOR1_TMDS_HDCP_CN_LSB MAKE_REG32(SOR1_BASE + 0x20C) + +typedef struct { + uint8_t _0x0[0x1000]; /* Ignore non Falcon registers. */ + uint32_t FALCON_IRQSSET; + uint32_t FALCON_IRQSCLR; + uint32_t FALCON_IRQSTAT; + uint32_t FALCON_IRQMODE; + uint32_t FALCON_IRQMSET; + uint32_t FALCON_IRQMCLR; + uint32_t FALCON_IRQMASK; + uint32_t FALCON_IRQDEST; + uint8_t _0x1020[0x20]; + uint32_t FALCON_SCRATCH0; + uint32_t FALCON_SCRATCH1; + uint32_t FALCON_ITFEN; + uint32_t FALCON_IDLESTATE; + uint32_t FALCON_CURCTX; + uint32_t FALCON_NXTCTX; + uint8_t _0x1058[0x28]; + uint32_t FALCON_SCRATCH2; + uint32_t FALCON_SCRATCH3; + uint8_t _0x1088[0x18]; + uint32_t FALCON_CGCTL; + uint32_t FALCON_ENGCTL; + uint8_t _0x10A8[0x58]; + uint32_t FALCON_CPUCTL; + uint32_t FALCON_BOOTVEC; + uint32_t FALCON_HWCFG; + uint32_t FALCON_DMACTL; + uint32_t FALCON_DMATRFBASE; + uint32_t FALCON_DMATRFMOFFS; + uint32_t FALCON_DMATRFCMD; + uint32_t FALCON_DMATRFFBOFFS; + uint8_t _0x1120[0x10]; + uint32_t FALCON_CPUCTL_ALIAS; + uint8_t _0x1134[0x20]; + uint32_t FALCON_IMFILLRNG1; + uint32_t FALCON_IMFILLCTL; + uint32_t _0x115C; + uint32_t _0x1160; + uint32_t _0x1164; + uint32_t FALCON_EXTERRADDR; + uint32_t FALCON_EXTERRSTAT; + uint32_t _0x1170; + uint32_t _0x1174; + uint32_t _0x1178; + uint32_t FALCON_CG2; + uint32_t FALCON_CODE_INDEX; + uint32_t FALCON_CODE; + uint32_t FALCON_CODE_VIRT_ADDR; + uint8_t _0x118C[0x34]; + uint32_t FALCON_DATA_INDEX0; + uint32_t FALCON_DATA0; + uint32_t FALCON_DATA_INDEX1; + uint32_t FALCON_DATA1; + uint32_t FALCON_DATA_INDEX2; + uint32_t FALCON_DATA2; + uint32_t FALCON_DATA_INDEX3; + uint32_t FALCON_DATA3; + uint32_t FALCON_DATA_INDEX4; + uint32_t FALCON_DATA4; + uint32_t FALCON_DATA_INDEX5; + uint32_t FALCON_DATA5; + uint32_t FALCON_DATA_INDEX6; + uint32_t FALCON_DATA6; + uint32_t FALCON_DATA_INDEX7; + uint32_t FALCON_DATA7; + uint32_t FALCON_ICD_CMD; + uint32_t FALCON_ICD_ADDR; + uint32_t FALCON_ICD_WDATA; + uint32_t FALCON_ICD_RDATA; + uint8_t _0x1210[0x30]; + uint32_t FALCON_SCTL; + uint8_t _0x1244[0x5F8]; /* Ignore non Falcon registers. */ +} tegra_tsec_t; + +static inline volatile tegra_tsec_t *tsec_get_regs(void) +{ + return (volatile tegra_tsec_t *)TSEC_BASE; +} + +int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw); + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index 4aee48cf6..220c49d24 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -6,7 +6,7 @@ #include "pmc.h" #include "car.h" #include "timers.h" -#include "hwinit/btn.h" +#include "btn.h" #include "panic.h" #include <stdio.h> From dcd91b5932ef20b37c139960e8e27dc371ee42fb Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Sat, 18 Aug 2018 18:15:23 +0100 Subject: [PATCH 053/489] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 73fe01895..b874c6d66 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,10 @@ In no particular order, we credit the following for their invaluable contributio * __devkitPro__ for the [devkitA64](https://devkitpro.org/) toolchain and libnx support. * __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.tech/) pertaining to the Nintendo Switch. * __ChaN__ for the [FatFs](http://elm-chan.org/fsw/ff/00index_e.html) module. +* __Marcus Geelnard__ for the [bcl-1.2.0](https://sourceforge.net/projects/bcl/files/bcl/bcl-1.2.0) library. +* __naehrwert__ and __st4rk__ for the original [hekate](https://github.com/nwert/hekate) project and its hwinit code base. +* __CTCaer__ for the continued [hekate](https://github.com/CTCaer/hekate) project's fork. * __Riley__ for suggesting "Atmosphere" as a Horizon OS reimplementation+customization project name. -* __naehrwert__ for the [hekate](https://github.com/nwert/hekate) project and its hwinit code base. * __hedgeberg__ for research and hardware testing. * __lioncash__ for code cleanup and general improvements. * __jaames__ for designing and providing Atmosphère's graphical resources. From e5bfb95c22f04a14e715ee6c6ef97d638e1d1458 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Sun, 19 Aug 2018 17:09:30 +0100 Subject: [PATCH 054/489] fusee: Add warmboot support. --- fusee/fusee-secondary/src/nxboot.c | 52 +++++++++++++++++++--------- fusee/fusee-secondary/src/package1.h | 6 ++-- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 9d30d1454..3c4776f2b 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -10,6 +10,7 @@ #include "di.h" #include "mc.h" #include "se.h" +#include "pmc.h" #include "cluster.h" #include "flow.h" #include "timers.h" @@ -62,7 +63,8 @@ static void nxboot_configure_exosphere(void) { /* This is the main function responsible for booting Horizon. */ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; void nxboot_main(void) { - volatile tegra_se_t *se = se_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + volatile tegra_se_t *se = se_get_regs(); loader_ctx_t *loader_ctx = get_loader_ctx(); /* void *bootconfig; */ package2_header_t *package2; @@ -71,6 +73,7 @@ void nxboot_main(void) { size_t tsec_fw_size; void *warmboot_fw; size_t warmboot_fw_size; + void *warmboot_memaddr; void *package1loader; size_t package1loader_size ; package1_header_t *package1; @@ -81,7 +84,7 @@ void nxboot_main(void) { package2 = memalign(4096, PACKAGE2_SIZE_MAX); if (package2 == NULL) { - fatal_error("nxboot: out of memory!\n"); + fatal_error("Out of memory!\n"); } /* Read Package2 from a file, otherwise from its partition(s). */ @@ -93,7 +96,7 @@ void nxboot_main(void) { } else { pk2file = fopen("bcpkg21:/", "rb"); if (pk2file == NULL || fseek(pk2file, 0x4000, SEEK_SET) != 0) { - printf("Error: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); + printf("Failed to open Package2 from eMMC: %s!\n", strerror(errno)); fclose(pk2file); generic_panic(); } @@ -137,7 +140,7 @@ void nxboot_main(void) { tsec_fw = memalign(0x100, tsec_fw_size); if (tsec_fw == NULL) { - fatal_error("nxboot_main: out of memory!\n"); + fatal_error("Out of memory!\n"); } if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) { fatal_error("Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); @@ -167,7 +170,7 @@ void nxboot_main(void) { warmboot_fw = malloc(warmboot_fw_size); if (warmboot_fw == NULL) { - fatal_error("nxboot_main: out of memory!\n"); + fatal_error("Out of memory!\n"); } if (read_from_file(warmboot_fw, warmboot_fw_size, loader_ctx->warmboot_path) != warmboot_fw_size) { fatal_error("Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); @@ -175,7 +178,7 @@ void nxboot_main(void) { } else { uint8_t ctr[16]; package1_size = package1_get_encrypted_package1(&package1, ctr, package1loader, package1loader_size); - if(package1_decrypt(package1, package1_size, ctr)) { + if (package1_decrypt(package1, package1_size, ctr)) { warmboot_fw = package1_get_warmboot_fw(package1); warmboot_fw_size = package1->warmboot_size; } else { @@ -187,7 +190,23 @@ void nxboot_main(void) { fatal_error("Could not read the warmboot firmware from Package1!\n"); } } - + + /* Select the right address for the warmboot firmware. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + warmboot_memaddr = (void *)0x8000D000; + } else { + warmboot_memaddr = (void *)0x4003B000; + } + + printf("Copying warmboot firmware...\n"); + + /* Copy the warmboot firmware and set the address in PMC if necessary. */ + if (warmboot_fw && (warmboot_fw_size > 0)) { + memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size); + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) + pmc->scratch1 = (uint32_t)warmboot_memaddr; + } + printf("Rebuilding package2...\n"); /* Patch package2, adding Thermosphère + custom KIPs. */ @@ -195,24 +214,25 @@ void nxboot_main(void) { printf(u8"Reading Exosphère...\n"); - /* Copy Exosphère to a good location (or read it directly to it.) */ + /* Select the right address for Exosphère. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { exosphere_memaddr = (void *)0x40020000; } else { exosphere_memaddr = (void *)0x40018000; /* 5.x has its secmon's crt0 around this region. */ } + /* Copy Exosphère to a good location or read it directly to it. */ if (loader_ctx->exosphere_path[0] != '\0') { size_t exosphere_size = get_file_size(loader_ctx->exosphere_path); if (exosphere_size == 0) { - fatal_error(u8"Error: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + fatal_error(u8"Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } else if (exosphere_size > 0x10000) { /* The maximum is actually a bit less than that. */ - fatal_error(u8"Error: Exosphère from %s is too big!\n", loader_ctx->exosphere_path); + fatal_error(u8"Exosphère from %s is too big!\n", loader_ctx->exosphere_path); } if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) { - fatal_error(u8"Error: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + fatal_error(u8"Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } } else { memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); @@ -244,18 +264,18 @@ void nxboot_main(void) { } /* TODO: Handle bootconfig. */ - memset((void *)0x4003D000, 0, 0x3000); + memset((void *)0x4003D000, 0, 0x3000); /* Finalize the GPU UCODE carveout. */ - mc_config_carveout_finalize(); + mc_config_carveout_finalize(); /* Lock AES keyslots. */ for (uint32_t i = 0; i < 16; i++) - set_aes_keyslot_flags(i, 0x15); + set_aes_keyslot_flags(i, 0x15); /* Lock RSA keyslots. */ - for (uint32_t i = 0; i < 2; i++) - set_rsa_keyslot_flags(i, 1); + for (uint32_t i = 0; i < 2; i++) + set_rsa_keyslot_flags(i, 1); /* Lock the Security Engine. */ se->_0x4 = 0; diff --git a/fusee/fusee-secondary/src/package1.h b/fusee/fusee-secondary/src/package1.h index 310d8d29c..a56f8bc6f 100644 --- a/fusee/fusee-secondary/src/package1.h +++ b/fusee/fusee-secondary/src/package1.h @@ -9,12 +9,12 @@ typedef struct package1_header_t { char magic[4]; uint32_t warmboot_size; - uint32_t _0x8; + uint32_t warmboot_offset; uint32_t _0xC; uint32_t nx_bootloader_size; - uint32_t _0x14; + uint32_t nx_bootloader_offset; uint32_t secmon_size; - uint32_t _0x1C; + uint32_t secmon_offset; uint8_t data[]; } package1_header_t; From b5234e9efb765a2d6680a9f7d107467e0690e8ad Mon Sep 17 00:00:00 2001 From: SciresM <Sciresm@gmail.com> Date: Mon, 20 Aug 2018 14:38:39 +0900 Subject: [PATCH 055/489] exo: cleanup + (theoretical) 1.0.0 support in smcCpuSuspend --- exosphere/src/lp0.c | 267 +++++++++++++++++++++++++++----------------- 1 file changed, 167 insertions(+), 100 deletions(-) diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c index fd3b3b3a0..1dc0f9c64 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/lp0.c @@ -27,8 +27,122 @@ #undef u8 #undef u32 -/* Save security engine, and go to sleep. */ -void save_se_and_power_down_cpu(void) { +static void configure_battery_hi_z_mode(void) { + clkrst_reboot(CARDEVICE_I2C1); + + if (configitem_should_profile_battery() && !i2c_query_ti_charger_bit_7()) { + /* Profile the battery. */ + i2c_set_ti_charger_bit_7(); + uint32_t start_time = get_time(); + bool should_wait = true; + /* TODO: This is GPIO-6 GPIO_IN_1 */ + while (MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_GPIO) + 0x634) & 1) { + if (get_time() - start_time > 50000) { + should_wait = false; + break; + } + } + if (should_wait) { + wait(0x100); + } + } + clkrst_disable(CARDEVICE_I2C1); +} + +static void enable_lp0_wake_events(void) { + wait(75); + APBDEV_PMC_CNTRL2_0 |= 0x200; /* Set WAKE_DET_EN. */ + wait(75); + APBDEV_PM_0 = 0xFFFFFFFF; /* Set all wake events. */ + APBDEV_PMC_WAKE2_STATUS_0 = 0xFFFFFFFF; /* Set all wake events. */ + wait(75); +} + +static void notify_pmic_shutdown(void) { + clkrst_reboot(CARDEVICE_I2C5); + if (fuse_get_bootrom_patch_version() >= 0x7F) { + i2c_send_pmic_cpu_shutdown_cmd(); + } +} + +static void mitigate_jamais_vu(void) { + /* Jamais Vu mitigation #1: Ensure all other cores are off. */ + if (APBDEV_PMC_PWRGATE_STATUS_0 & 0xE00) { + generic_panic(); + } + + /* For debugging, make this check always pass. */ + if ((exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3)) { + FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; + } else { + FLOW_CTLR_HALT_COP_EVENTS_0 = 0x40000000; + } + + /* Jamais Vu mitigation #2: Ensure the BPMP is halted. */ + if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3) { + /* BPMP should just be plainly halted, in debugging conditions. */ + if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x50000000) { + generic_panic(); + } + } else { + /* BPMP must be in never-woken-up halt mode, under normal conditions. */ + if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x40000000) { + generic_panic(); + } + } + + /* Jamais Vu mitigation #3: Ensure all relevant DMA controllers are held in reset. */ + if ((CLK_RST_CONTROLLER_RST_DEVICES_H_0 & 0x4000004) != 0x4000004) { + generic_panic(); + } +} + +static void configure_pmc_for_deep_powerdown(void) { + APBDEV_PMC_SCRATCH0_0 = 1; + APBDEV_PMC_DPD_ENABLE_0 |= 2; +} + +static void setup_bpmp_sc7_firmware(void) { + /* Mark PMC registers as not secure-world only, so BPMP can access them. */ + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 &= 0xFFFFDFFF; + + /* Setup BPMP vectors. */ + BPMP_VECTOR_RESET = 0x40003000; /* lp0_entry_firmware_crt0 */ + BPMP_VECTOR_UNDEF = 0x40003004; /* Reboot. */ + BPMP_VECTOR_SWI = 0x40003004; /* Reboot. */ + BPMP_VECTOR_PREFETCH_ABORT = 0x40003004; /* Reboot. */ + BPMP_VECTOR_DATA_ABORT = 0x40003004; /* Reboot. */ + BPMP_VECTOR_UNK = 0x40003004; /* Reboot. */ + BPMP_VECTOR_IRQ = 0x40003004; /* Reboot. */ + BPMP_VECTOR_FIQ = 0x40003004; /* Reboot. */ + + /* Hold the BPMP in reset. */ + MAKE_CAR_REG(0x300) = 2; + + /* Copy BPMP firmware. */ + uint8_t *lp0_entry_code = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE)); + for (unsigned int i = 0; i < bpmpfw_bin_size; i += 4) { + write32le(lp0_entry_code, i, read32le(bpmpfw_bin, i)); + } + + flush_dcache_range(lp0_entry_code, lp0_entry_code + bpmpfw_bin_size); + + /* Take the BPMP out of reset. */ + MAKE_CAR_REG(0x304) = 2; + + /* Start executing BPMP firmware. */ + FLOW_CTLR_HALT_COP_EVENTS_0 = 0; +} + +static void configure_flow_regs_for_sleep(void) { + unsigned int current_core = get_core_id(); + flow_set_cc4_ctrl(current_core, 0); + flow_set_halt_events(current_core, false); + FLOW_CTLR_L2FLUSH_CONTROL_0 = 0; + flow_set_csr(current_core, 2); +} + +static void save_tzram_state(void) { /* TODO: Remove set suspend call once exo warmboots fully */ set_suspend_for_debug(); uint32_t tzram_cmac[0x4] = {0}; @@ -71,6 +185,28 @@ void save_se_and_power_down_cpu(void) { APBDEV_PMC_SECURE_SCRATCH115_0 = tzram_cmac[3]; APBDEV_PMC_SEC_DISABLE8_0 = 0x550000; + /* Perform pre-2.0.0 PMC writes. */ + if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_200) { + /* TODO: Give these writes appropriate defines in pmc.h */ + + /* Save Encrypted context location + lock scratch register. */ + MAKE_REG32(PMC_BASE + 0x360) = WARMBOOT_GET_RAM_SEGMENT_PA(WARMBOOT_RAM_SEGMENT_ID_TZRAM); + MAKE_REG32(PMC_BASE + 0x2D8) = 0x10000; + + /* Save Encryption parameters (where to copy TZRAM to, source, destination, size) */ + MAKE_REG32(PMC_BASE + 0x340) = LP0_ENTRY_GET_RAM_SEGMENT_PA(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM); + MAKE_REG32(PMC_BASE + 0x344) = 0; + MAKE_REG32(PMC_BASE + 0x348) = LP0_ENTRY_GET_RAM_SEGMENT_PA(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM); + MAKE_REG32(PMC_BASE + 0x34C) = 0; + MAKE_REG32(PMC_BASE + 0x350) = LP0_ENTRY_GET_RAM_SEGMENT_PA(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM); + MAKE_REG32(PMC_BASE + 0x354) = LP0_TZRAM_SAVE_SIZE; + + /* Lock scratch registers. */ + MAKE_REG32(PMC_BASE + 0x2D8) = 0x555; + } +} + +static void save_se_state(void) { /* Save security engine state. */ uint8_t *se_state_dst = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_SE_STATE)); se_check_error_status_reg(); @@ -80,6 +216,13 @@ void save_se_and_power_down_cpu(void) { APBDEV_PMC_SCRATCH43_0 = (uint32_t)(WARMBOOT_GET_RAM_SEGMENT_PA(WARMBOOT_RAM_SEGMENT_ID_SE_STATE)); se_set_in_context_save_mode(false); se_check_error_status_reg(); +} + +/* Save security engine, and go to sleep. */ +void save_se_and_power_down_cpu(void) { + /* Save context for warmboot to restore. */ + save_tzram_state(); + save_se_state(); if (!configitem_is_retail()) { /* TODO: uart_log("OYASUMI"); */ @@ -95,121 +238,45 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen if ((power_state & 0x17FFF) != 0x1001B) { return 0xFFFFFFFD; } - - unsigned int current_core = get_core_id(); - - clkrst_reboot(CARDEVICE_I2C1); - - if (configitem_should_profile_battery() && !i2c_query_ti_charger_bit_7()) { - /* Profile the battery. */ - i2c_set_ti_charger_bit_7(); - uint32_t start_time = get_time(); - bool should_wait = true; - /* TODO: This is GPIO-6 GPIO_IN_1 */ - while (MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_GPIO) + 0x634) & 1) { - if (get_time() - start_time > 50000) { - should_wait = false; - break; - } - } - if (should_wait) { - wait(0x100); - } - } - clkrst_disable(CARDEVICE_I2C1); + /* Perform I2C comms with TI charger if required. */ + configure_battery_hi_z_mode(); /* Enable LP0 Wake Event Detection. */ - wait(75); - APBDEV_PMC_CNTRL2_0 |= 0x200; /* Set WAKE_DET_EN. */ - wait(75); - APBDEV_PM_0 = 0xFFFFFFFF; /* Set all wake events. */ - APBDEV_PMC_WAKE2_STATUS_0 = 0xFFFFFFFF; /* Set all wake events. */ - wait(75); + enable_lp0_wake_events(); - clkrst_reboot(CARDEVICE_I2C5); - if (fuse_get_bootrom_patch_version() >= 0x7F) { - i2c_send_pmic_cpu_shutdown_cmd(); - } + /* Alert the PMC of an iminent shutdown. */ + notify_pmic_shutdown(); - /* Jamais Vu mitigation #1: Ensure all other cores are off. */ - if (APBDEV_PMC_PWRGATE_STATUS_0 & 0xE00) { - generic_panic(); - } - - /* For debugging, make this check always pass. */ - if ((exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3)) { - FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; - } else { - FLOW_CTLR_HALT_COP_EVENTS_0 = 0x40000000; - } - - /* Jamais Vu mitigation #2: Ensure the BPMP is halted. */ - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3) { - /* BPMP should just be plainly halted, in debugging conditions. */ - if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x50000000) { - generic_panic(); - } - } else { - /* BPMP must be in never-woken-up halt mode, under normal conditions. */ - if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x40000000) { - generic_panic(); - } - } - - /* Jamais Vu mitigation #3: Ensure all relevant DMA controllers are held in reset. */ - if ((CLK_RST_CONTROLLER_RST_DEVICES_H_0 & 0x4000004) != 0x4000004) { - generic_panic(); + /* Validate that the shutdown has correct context. */ + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { + mitigate_jamais_vu(); } /* Signal to bootrom the next reset should be a warmboot. */ - APBDEV_PMC_SCRATCH0_0 = 1; - APBDEV_PMC_DPD_ENABLE_0 |= 2; + configure_pmc_for_deep_powerdown(); - /* Prepare to boot the BPMP running our deep sleep firmware. */ - - /* Mark PMC registers as not secure-world only, so BPMP can access them. */ - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 &= 0xFFFFDFFF; - - /* Setup BPMP vectors. */ - BPMP_VECTOR_RESET = 0x40003000; /* lp0_entry_firmware_crt0 */ - BPMP_VECTOR_UNDEF = 0x40003004; /* Reboot. */ - BPMP_VECTOR_SWI = 0x40003004; /* Reboot. */ - BPMP_VECTOR_PREFETCH_ABORT = 0x40003004; /* Reboot. */ - BPMP_VECTOR_DATA_ABORT = 0x40003004; /* Reboot. */ - BPMP_VECTOR_UNK = 0x40003004; /* Reboot. */ - BPMP_VECTOR_IRQ = 0x40003004; /* Reboot. */ - BPMP_VECTOR_FIQ = 0x40003004; /* Reboot. */ - - /* Hold the BPMP in reset. */ - MAKE_CAR_REG(0x300) = 2; - - /* Copy BPMP firmware. */ - uint8_t *lp0_entry_code = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE)); - for (unsigned int i = 0; i < bpmpfw_bin_size; i += 4) { - write32le(lp0_entry_code, i, read32le(bpmpfw_bin, i)); + /* Ensure that BPMP SC7 firmware is active. */ + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { + setup_bpmp_sc7_firmware(); } - - flush_dcache_range(lp0_entry_code, lp0_entry_code + bpmpfw_bin_size); - /* Take the BPMP out of reset. */ - MAKE_CAR_REG(0x304) = 2; - - /* Start executing BPMP firmware. */ - FLOW_CTLR_HALT_COP_EVENTS_0 = 0; /* Prepare the current core for sleep. */ - flow_set_cc4_ctrl(current_core, 0); - flow_set_halt_events(current_core, false); - FLOW_CTLR_L2FLUSH_CONTROL_0 = 0; - flow_set_csr(current_core, 2); + configure_flow_regs_for_sleep(); /* Save core context. */ - set_core_entrypoint_and_argument(current_core, entrypoint, argument); + set_core_entrypoint_and_argument(get_core_id(), entrypoint, argument); save_current_core_context(); set_current_core_inactive(); - - call_with_stack_pointer(get_smc_core012_stack_address(), save_se_and_power_down_cpu); + /* Ensure that other cores are already asleep. */ + if (!(APBDEV_PMC_PWRGATE_STATUS_0 & 0xE00)) { + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { + call_with_stack_pointer(get_smc_core012_stack_address(), save_se_and_power_down_cpu); + } else { + save_se_and_power_down_cpu(); + } + } generic_panic(); } From c40bb9b317819b85870262d4b11e8192ef731312 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 20 Aug 2018 19:31:15 -0700 Subject: [PATCH 056/489] Exosphere: Fix crash for certain games on newer firmwares --- exosphere/src/smc_api.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index 063611a0a..a0f96073b 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -25,6 +25,7 @@ #define SMC_PRIV_HANDLERS 0x9 #define DEBUG_LOG_SMCS 0 +#define DEBUG_PANIC_ON_FAILURE 0 /* User SMC prototypes */ uint32_t smc_set_config(smc_args_t *args); @@ -260,6 +261,7 @@ void call_smc_handler(uint32_t handler_id, smc_args_t *args) { } #endif +#if DEBUG_PANIC_ON_FAILURE if (args->X[0] && (!is_aes_kek || args->X[3] <= EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG)) { MAKE_REG32(get_iram_address_for_debug() + 0x4FF0) = handler_id; @@ -268,6 +270,9 @@ void call_smc_handler(uint32_t handler_id, smc_args_t *args) { *(volatile smc_args_t *)(get_iram_address_for_debug() + 0x4F00) = *args; panic(PANIC_REBOOT); } +#else + (void)(is_aes_kek); +#endif (void)result; /* FIXME: result unused */ } @@ -636,8 +641,10 @@ uint32_t smc_configure_carveout(smc_args_t *args) { } /* Configuration is one-shot, and cannot be done multiple times. */ - if (g_configured_carveouts[carveout_id]) { - return 2; + if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_300) { + if (g_configured_carveouts[carveout_id]) { + return 2; + } } configure_kernel_carveout(carveout_id + 4, address, size); From 8edec43be2b6c1831d2ebcc6277d4bee838ba6dc Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Thu, 23 Aug 2018 19:57:01 +0100 Subject: [PATCH 057/489] fusee: Add automatic firmware version detection. --- fusee/fusee-secondary/src/nxboot.c | 99 +++++++++++++++++----------- fusee/fusee-secondary/src/package1.h | 12 +++- 2 files changed, 72 insertions(+), 39 deletions(-) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 3c4776f2b..17a9b5f0c 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -43,18 +43,36 @@ static int exosphere_ini_handler(void *user, const char *section, const char *na return 1; } -static void nxboot_configure_exosphere(void) { +static uint32_t nxboot_get_target_firmware(const void *package1loader) { + const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; + switch (package1loader_header->version) { + case 0x01: /* 1.0.0 */ + return EXOSPHERE_TARGET_FIRMWARE_100; + case 0x02: /* 2.0.0 - 2.3.0 */ + return EXOSPHERE_TARGET_FIRMWARE_200; + case 0x04: /* 3.0.0 and 3.0.1 - 3.0.2 */ + return EXOSPHERE_TARGET_FIRMWARE_300; + case 0x07: /* 4.0.0 - 4.1.0 */ + return EXOSPHERE_TARGET_FIRMWARE_400; + case 0x0B: /* 5.0.0 - 5.1.0 */ + return EXOSPHERE_TARGET_FIRMWARE_500; + default: + return 0; + } +} + +static void nxboot_configure_exosphere(uint32_t target_firmware) { exosphere_config_t exo_cfg = {0}; exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG; - exo_cfg.target_firmware = EXOSPHERE_TARGET_FIRMWARE_MAX; + exo_cfg.target_firmware = target_firmware; if (ini_parse_string(get_loader_ctx()->bct0, exosphere_ini_handler, &exo_cfg) < 0) { - fatal_error("Failed to parse BCT.ini!\n"); + fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); } - if (exo_cfg.target_firmware < EXOSPHERE_TARGET_FIRMWARE_MIN || exo_cfg.target_firmware > EXOSPHERE_TARGET_FIRMWARE_MAX) { - fatal_error("Invalid Exosphere target firmware!\n"); + if ((exo_cfg.target_firmware < EXOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > EXOSPHERE_TARGET_FIRMWARE_MAX)) { + fatal_error("[NXBOOT]: Invalid Exosphere target firmware!\n"); } *(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg; @@ -75,28 +93,30 @@ void nxboot_main(void) { size_t warmboot_fw_size; void *warmboot_memaddr; void *package1loader; - size_t package1loader_size ; + size_t package1loader_size; package1_header_t *package1; size_t package1_size; uint32_t available_revision; FILE *boot0, *pk2file; void *exosphere_memaddr; + /* Allocate memory for reading Package2. */ package2 = memalign(4096, PACKAGE2_SIZE_MAX); if (package2 == NULL) { - fatal_error("Out of memory!\n"); + fatal_error("[NXBOOT]: Out of memory!\n"); } /* Read Package2 from a file, otherwise from its partition(s). */ + printf("[NXBOOT]: Reading package2...\n"); if (loader_ctx->package2_path[0] != '\0') { pk2file = fopen(loader_ctx->package2_path, "rb"); if (pk2file == NULL) { - fatal_error("Failed to open Package2 from %s: %s!\n", loader_ctx->package2_path, strerror(errno)); + fatal_error("[NXBOOT]: Failed to open Package2 from %s: %s!\n", loader_ctx->package2_path, strerror(errno)); } } else { pk2file = fopen("bcpkg21:/", "rb"); if (pk2file == NULL || fseek(pk2file, 0x4000, SEEK_SET) != 0) { - printf("Failed to open Package2 from eMMC: %s!\n", strerror(errno)); + printf("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); fclose(pk2file); generic_panic(); } @@ -104,28 +124,22 @@ void nxboot_main(void) { setvbuf(pk2file, NULL, _IONBF, 0); /* Workaround. */ if (fread(package2, sizeof(package2_header_t), 1, pk2file) < 1) { - fatal_error("Failed to read Package2!\n"); + fatal_error("[NXBOOT]: Failed to read Package2!\n"); } - package2_size = package2_meta_get_size(&package2->metadata); if (package2_size > PACKAGE2_SIZE_MAX || package2_size <= sizeof(package2_header_t)) { - fatal_error("Package2 is too big or too small!\n"); + fatal_error("[NXBOOT]: Package2 is too big or too small!\n"); } - if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) { - fatal_error("Failed to read Package2!\n"); + fatal_error("[NXBOOT]: Failed to read Package2!\n"); } - fclose(pk2file); - printf("Read package2!\n"); - - /* Setup boot configuration for Exosphère. */ - nxboot_configure_exosphere(); - - printf("Reading boot0...\n"); + + /* Read and parse boot0. */ + printf("[NXBOOT]: Reading boot0...\n"); boot0 = fopen("boot0:/", "rb"); if (boot0 == NULL || package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1) { - fatal_error("Couldn't parse boot0: %s!\n", strerror(errno)); + fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno)); } fclose(boot0); @@ -133,47 +147,57 @@ void nxboot_main(void) { if (loader_ctx->tsecfw_path[0] != '\0') { tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); if (tsec_fw_size != 0 && tsec_fw_size != 0xF00) { - fatal_error("TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); + fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); } else if (tsec_fw_size == 0) { - fatal_error("Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); + fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } tsec_fw = memalign(0x100, tsec_fw_size); if (tsec_fw == NULL) { - fatal_error("Out of memory!\n"); + fatal_error("[NXBOOT]: Out of memory!\n"); } if (read_from_file(tsec_fw, tsec_fw_size, loader_ctx->tsecfw_path) != tsec_fw_size) { - fatal_error("Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); + fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } } else { tsec_fw_size = package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size); if (tsec_fw_size == 0) { - fatal_error("Failed to read the TSEC firmware from Package1loader!\n"); + fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); } } /* TODO: Validate that we're capable of booting. */ /* TODO: Initialize Boot Reason. */ + + /* Find the system's target firmware. */ + uint32_t target_firmware = nxboot_get_target_firmware(package1loader); + if (!target_firmware) + fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); + else + printf("[NXBOOT]: Detected target firmware %ld!\n", target_firmware); + /* Setup boot configuration for Exosphère. */ + nxboot_configure_exosphere(target_firmware); + /* Derive keydata. */ if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) { - fatal_error("Key derivation failed!\n"); + fatal_error("[NXBOOT]: Key derivation failed!\n"); } /* Read the warmboot firmware from a file, otherwise from PK1. */ if (loader_ctx->warmboot_path[0] != '\0') { warmboot_fw_size = get_file_size(loader_ctx->warmboot_path); if (warmboot_fw_size == 0) { - fatal_error("Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); + fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } warmboot_fw = malloc(warmboot_fw_size); if (warmboot_fw == NULL) { - fatal_error("Out of memory!\n"); + fatal_error("[NXBOOT]: Out of memory!\n"); } if (read_from_file(warmboot_fw, warmboot_fw_size, loader_ctx->warmboot_path) != warmboot_fw_size) { - fatal_error("Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); + fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } } else { uint8_t ctr[16]; @@ -187,7 +211,7 @@ void nxboot_main(void) { } if (warmboot_fw_size == 0) { - fatal_error("Could not read the warmboot firmware from Package1!\n"); + fatal_error("[NXBOOT]: Could not read the warmboot firmware from Package1!\n"); } } @@ -198,7 +222,7 @@ void nxboot_main(void) { warmboot_memaddr = (void *)0x4003B000; } - printf("Copying warmboot firmware...\n"); + printf("[NXBOOT]: Copying warmboot firmware...\n"); /* Copy the warmboot firmware and set the address in PMC if necessary. */ if (warmboot_fw && (warmboot_fw_size > 0)) { @@ -207,7 +231,7 @@ void nxboot_main(void) { pmc->scratch1 = (uint32_t)warmboot_memaddr; } - printf("Rebuilding package2...\n"); + printf("[NXBOOT]: Rebuilding package2...\n"); /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); @@ -291,7 +315,7 @@ void nxboot_main(void) { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X; } - printf("Powering on the CCPLEX...\n"); + printf("[NXBOOT]: Powering on the CCPLEX...\n"); /* Display splash screen. */ display_splash_screen_bmp(loader_ctx->custom_splash_path); @@ -299,9 +323,8 @@ void nxboot_main(void) { /* Turn off the backlight. */ display_backlight(false); - /* Terminate the display if necessary. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) - display_end(); + /* Terminate the display. */ + display_end(); /* Boot CPU0. */ cluster_boot_cpu0((uint64_t)(uintptr_t)exosphere_memaddr); diff --git a/fusee/fusee-secondary/src/package1.h b/fusee/fusee-secondary/src/package1.h index a56f8bc6f..256fc6d66 100644 --- a/fusee/fusee-secondary/src/package1.h +++ b/fusee/fusee-secondary/src/package1.h @@ -6,7 +6,17 @@ #define PACKAGE1LOADER_SIZE_MAX 0x40000 -typedef struct package1_header_t { +typedef struct { + uint32_t package1loader_hash; + uint32_t secmon_hash; + uint32_t nx_bootloader_hash; + uint32_t _0xC; + char build_timestamp[0x0E]; + uint8_t _0x1E; + uint8_t version; +} package1loader_header_t; + +typedef struct { char magic[4]; uint32_t warmboot_size; uint32_t warmboot_offset; From 43bde3fcc9f6bf09b8b143816b7f7dd9d06aa383 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 24 Aug 2018 17:03:53 +0100 Subject: [PATCH 058/489] fusee: Fix register definition. --- fusee/fusee-primary/src/sysctr0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-primary/src/sysctr0.h b/fusee/fusee-primary/src/sysctr0.h index 60c645bdd..477063bb0 100644 --- a/fusee/fusee-primary/src/sysctr0.h +++ b/fusee/fusee-primary/src/sysctr0.h @@ -6,6 +6,6 @@ #define SYSCTR0_BASE 0x7000F000 #define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) -#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x00) +#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20) #endif From a400b109214a2987d3ba7b68da205599f81c44b9 Mon Sep 17 00:00:00 2001 From: Lioncash <mathew1800@gmail.com> Date: Fri, 24 Aug 2018 22:30:32 -0400 Subject: [PATCH 059/489] fusee-primary: Fix always false conditional in xmemmove This was corrected in 4b8455baf91d8699a663341c135c91c34f0a7816 for fusee-secondary, but I neglected to also fix it in fusee-primary (my bad!) --- fusee/fusee-primary/src/chainloader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-primary/src/chainloader.c b/fusee/fusee-primary/src/chainloader.c index 6890ff4ff..b4090b103 100644 --- a/fusee/fusee-primary/src/chainloader.c +++ b/fusee/fusee-primary/src/chainloader.c @@ -17,7 +17,7 @@ static void *xmemmove(void *dst, const void *src, size_t len) for (size_t i = 0; i < len; i++) { dst8[i] = src8[i]; } - } else if (src8 > dst8) { + } else if (dst8 > src8) { for (size_t i = len; len > 0; len--) dst8[i - 1] = src8[i - 1]; } From 611e85e6eee068cad226fdf58e9794a0cbfc4f02 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Wed, 29 Aug 2018 18:28:21 +0100 Subject: [PATCH 060/489] fusee: Implement BootConfig and Boot Reason handling. --- exosphere/src/bootconfig.c | 4 +- exosphere/src/bootconfig.h | 11 ++- fusee/fusee-primary/src/btn.c | 2 +- fusee/fusee-primary/src/di.c | 4 +- fusee/fusee-primary/src/hwinit.c | 26 ++--- fusee/fusee-primary/src/i2c.c | 26 ++--- fusee/fusee-primary/src/i2c.h | 14 +++ fusee/fusee-primary/src/max77620.h | 30 ++++++ fusee/fusee-primary/src/max7762x.c | 20 ++-- fusee/fusee-primary/src/sdram.c | 4 +- fusee/fusee-secondary/src/btn.c | 2 +- fusee/fusee-secondary/src/cluster.c | 14 +-- fusee/fusee-secondary/src/di.c | 4 +- fusee/fusee-secondary/src/i2c.c | 26 ++--- fusee/fusee-secondary/src/i2c.h | 14 +++ fusee/fusee-secondary/src/max77620.h | 30 ++++++ fusee/fusee-secondary/src/max7762x.c | 20 ++-- fusee/fusee-secondary/src/nxboot.c | 141 ++++++++++++++++++++++----- fusee/fusee-secondary/src/nxboot.h | 16 +-- 19 files changed, 299 insertions(+), 109 deletions(-) diff --git a/exosphere/src/bootconfig.c b/exosphere/src/bootconfig.c index dd2cfd870..afa1f7e20 100644 --- a/exosphere/src/bootconfig.c +++ b/exosphere/src/bootconfig.c @@ -138,9 +138,9 @@ void bootconfig_get_package2_hash_for_recovery(uint64_t *out_hash) { } bool bootconfig_is_recovery_boot(void) { - return (g_boot_reason.is_recovery_boot != 0); + return ((g_boot_reason.bootloader_attribute & 0x01) != 0); } uint64_t bootconfig_get_boot_reason(void) { - return ((uint64_t)g_boot_reason.boot_reason_high << 24) | (g_boot_reason.boot_reason_low & 0xFFFFFF); + return ((uint64_t)g_boot_reason.boot_reason_state << 24) | (g_boot_reason.boot_reason_value & 0xFFFFFF); } diff --git a/exosphere/src/bootconfig.h b/exosphere/src/bootconfig.h index 823323a03..e2e410ade 100644 --- a/exosphere/src/bootconfig.h +++ b/exosphere/src/bootconfig.h @@ -34,11 +34,12 @@ static inline bootconfig_t *get_loaded_bootconfig(void) { } typedef struct { - uint64_t _0x00; - uint32_t _0x08; - uint32_t is_recovery_boot; - uint32_t boot_reason_low; - uint32_t boot_reason_high; + uint32_t bootloader_version; + uint32_t bootloader_start_block; + uint32_t bootloader_start_page; + uint32_t bootloader_attribute; + uint32_t boot_reason_value; + uint32_t boot_reason_state; } boot_reason_t; void bootconfig_load_and_verify(const bootconfig_t *bootconfig); diff --git a/fusee/fusee-primary/src/btn.c b/fusee/fusee-primary/src/btn.c index bffc8e79d..942d27be6 100644 --- a/fusee/fusee-primary/src/btn.c +++ b/fusee/fusee-primary/src/btn.c @@ -16,7 +16,7 @@ uint32_t btn_read() res |= BTN_VOL_UP; uint32_t val = 0; - if (i2c_query(4, 0x3C, 0x15, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1)) { if (val & 0x4) res |= BTN_POWER; diff --git a/fusee/fusee-primary/src/di.c b/fusee/fusee-primary/src/di.c index e22257465..f46310eb8 100644 --- a/fusee/fusee-primary/src/di.c +++ b/fusee/fusee-primary/src/di.c @@ -36,9 +36,9 @@ void display_init() /* Power on. */ uint8_t val = 0xD0; - i2c_send(4, 0x3C, MAX77620_REG_LDO0_CFG, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1); val = 0x09; - i2c_send(4, 0x3C, MAX77620_REG_GPIO7, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO7, &val, 1); /* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */ car->rst_dev_h_clr = 0x1010000; diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index 903b750bd..929136d38 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -203,33 +203,33 @@ void nx_hwinit() clkrst_reboot(CARDEVICE_UNK); /* Initialize I2C1 and I2C5. */ - i2c_init(0); - i2c_init(4); + i2c_init(I2C_1); + i2c_init(I2C_5); uint8_t val = 0x40; - i2c_send(4, 0x3C, MAX77620_REG_CNFGBBC, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1); val = 0x78; - i2c_send(4, 0x3C, MAX77620_REG_ONOFFCNFG1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1); val = 0x38; - i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG0, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1); val = 0x3A; - i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG1, &val, 1); val = 0x38; - i2c_send(4, 0x3C, MAX77620_REG_FPS_CFG2, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG2, &val, 1); val = 0xF; - i2c_send(4, 0x3C, MAX77620_REG_FPS_LDO4, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO4, &val, 1); val = 0xC7; - i2c_send(4, 0x3C, MAX77620_REG_FPS_LDO8, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO8, &val, 1); val = 0x4F; - i2c_send(4, 0x3C, MAX77620_REG_FPS_SD0, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD0, &val, 1); val = 0x29; - i2c_send(4, 0x3C, MAX77620_REG_FPS_SD1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD1, &val, 1); val = 0x1B; - i2c_send(4, 0x3C, MAX77620_REG_FPS_SD3, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD3, &val, 1); val = 42; /* 42 = (1125000 - 600000) / 12500 -> 1.125V */ - i2c_send(4, 0x3C, MAX77620_REG_SD0, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD0, &val, 1); /* Configure and lock PMC scratch registers. */ config_pmc_scratch(); diff --git a/fusee/fusee-primary/src/i2c.c b/fusee/fusee-primary/src/i2c.c index a98d7fa6e..028ba56e8 100644 --- a/fusee/fusee-primary/src/i2c.c +++ b/fusee/fusee-primary/src/i2c.c @@ -43,16 +43,16 @@ void i2c_init(unsigned int id) { void i2c_send_pmic_cpu_shutdown_cmd(void) { uint32_t val = 0; /* PMIC == Device 4:3C. */ - i2c_query(4, 0x3C, 0x41, &val, 1); + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); val |= 4; - i2c_send(4, 0x3C, 0x41, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); } /* Queries the value of TI charger bit over I2C. */ bool i2c_query_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); return (val & 0x80) != 0; } @@ -60,34 +60,34 @@ bool i2c_query_ti_charger_bit_7(void) { void i2c_clear_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); val &= 0x7F; - i2c_send(0, 0x6B, 0, &val, 1); + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); } /* Sets TI charger bit over I2C. */ void i2c_set_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); val |= 0x80; - i2c_send(0, 0x6B, 0, &val, 1); + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); } /* Get registers pointer based on I2C ID. */ volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { switch (id) { - case 0: + case I2C_1: return I2C1_REGS; - case 1: + case I2C_2: return I2C2_REGS; - case 2: + case I2C_3: return I2C3_REGS; - case 3: + case I2C_4: return I2C4_REGS; - case 4: + case I2C_5: return I2C5_REGS; - case 5: + case I2C_6: return I2C6_REGS; default: generic_panic(); diff --git a/fusee/fusee-primary/src/i2c.h b/fusee/fusee-primary/src/i2c.h index e07ed3349..8b0acbd35 100644 --- a/fusee/fusee-primary/src/i2c.h +++ b/fusee/fusee-primary/src/i2c.h @@ -8,6 +8,20 @@ #define I2C234_BASE 0x7000C000 #define I2C56_BASE 0x7000D000 +#define I2C_1 0 +#define I2C_2 1 +#define I2C_3 2 +#define I2C_4 3 +#define I2C_5 4 +#define I2C_6 5 + +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B + typedef struct { uint32_t I2C_I2C_CNFG_0; uint32_t I2C_I2C_CMD_ADDR0_0; diff --git a/fusee/fusee-primary/src/max77620.h b/fusee/fusee-primary/src/max77620.h index ad22a06b5..ab90f2b8e 100644 --- a/fusee/fusee-primary/src/max77620.h +++ b/fusee/fusee-primary/src/max77620.h @@ -11,6 +11,36 @@ #ifndef _MFD_MAX77620_H_ #define _MFD_MAX77620_H_ +/* RTC Registers */ +#define MAX77620_REG_RTCINT 0x00 +#define MAX77620_REG_RTCINTM 0x01 +#define MAX77620_REG_RTCCNTLM 0x02 +#define MAX77620_REG_RTCCNTL 0x03 +#define MAX77620_REG_RTCUPDATE0 0x04 +#define MAX77620_REG_RTCUPDATE1 0x05 +#define MAX77620_REG_RTCSMPL 0x06 +#define MAX77620_REG_RTCSEC 0x07 +#define MAX77620_REG_RTCMIN 0x08 +#define MAX77620_REG_RTCHOUR 0x09 +#define MAX77620_REG_RTCDOW 0x0A +#define MAX77620_REG_RTCMONTH 0x0B +#define MAX77620_REG_RTCYEAR 0x0C +#define MAX77620_REG_RTCDOM 0x0D +#define MAX77620_REG_RTCSECA1 0x0E +#define MAX77620_REG_RTCMINA1 0x0F +#define MAX77620_REG_RTCHOURA1 0x10 +#define MAX77620_REG_RTCDOWA1 0x11 +#define MAX77620_REG_RTCMONTHA1 0x12 +#define MAX77620_REG_RTCYEARA1 0x13 +#define MAX77620_REG_RTCDOMA1 0x14 +#define MAX77620_REG_RTCSECA2 0x15 +#define MAX77620_REG_RTCMINA2 0x16 +#define MAX77620_REG_RTCHOURA2 0x17 +#define MAX77620_REG_RTCDOWA2 0x18 +#define MAX77620_REG_RTCMONTHA2 0x19 +#define MAX77620_REG_RTCYEARA2 0x1A +#define MAX77620_REG_RTCDOMA2 0x1B + /* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ #define MAX77620_REG_CNFGGLBL1 0x00 #define MAX77620_REG_CNFGGLBL2 0x01 diff --git a/fusee/fusee-primary/src/max7762x.c b/fusee/fusee-primary/src/max7762x.c index 419a13bce..da20eb7b9 100644 --- a/fusee/fusee-primary/src/max7762x.c +++ b/fusee/fusee-primary/src/max7762x.c @@ -55,11 +55,11 @@ int max77620_regulator_get_status(uint32_t id) uint8_t val = 0; if (reg->type == REGULATOR_SD) { - if (i2c_query(4, 0x3C, MAX77620_REG_STATSD, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_STATSD, &val, 1)) return (val & reg->status_mask) ? 0 : 1; } - if (i2c_query(4, 0x3C, reg->cfg_addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1)) return (val & 8) ? 0 : 1; return 0; @@ -73,7 +73,7 @@ int max77620_regulator_config_fps(uint32_t id) const max77620_regulator_t *reg = &_pmic_regulators[id]; uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); - if (i2c_send(4, 0x3C, reg->fps_addr, &val, 1)) { + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->fps_addr, &val, 1)) { return 1; } @@ -93,11 +93,11 @@ int max77620_regulator_set_voltage(uint32_t id, uint32_t mv) uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; uint8_t val = 0; - if (i2c_query(4, 0x3C, reg->volt_addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) { val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask)); - if (i2c_send(4, 0x3C, reg->volt_addr, &val, 1)) + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) { udelay(1000); return 1; @@ -117,14 +117,14 @@ int max77620_regulator_enable(uint32_t id, int enable) uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr; uint8_t val = 0; - if (i2c_query(4, 0x3C, addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) { if (enable) val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); else val &= ~reg->enable_mask; - if (i2c_send(4, 0x3C, addr, &val, 1)) + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) { udelay(1000); return 1; @@ -139,7 +139,7 @@ void max77620_config_default() for (uint32_t i = 1; i <= REGULATOR_MAX; i++) { uint8_t val = 0; - if (i2c_query(4, 0x3C, MAX77620_REG_CID4, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CID4, &val, 1)) { max77620_regulator_config_fps(i); max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); @@ -151,11 +151,11 @@ void max77620_config_default() } uint8_t val = 4; - i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1); } void max77620_low_battery_monitor_config() { uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N); - i2c_send(4, 0x3C, MAX77620_REG_CNFGGLBL1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); } diff --git a/fusee/fusee-primary/src/sdram.c b/fusee/fusee-primary/src/sdram.c index eb941f235..135833eea 100644 --- a/fusee/fusee-primary/src/sdram.c +++ b/fusee/fusee-primary/src/sdram.c @@ -542,9 +542,9 @@ void sdram_init() const sdram_params_t *params = (const sdram_params_t *)sdram_get_params(); uint8_t val = 5; - i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1); val = 40; /* 40 = (1000 * 1100 - 600000) / 12500 -> 1.1V */ - i2c_send(4, 0x3C, MAX77620_REG_SD1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD1, &val, 1); pmc->vddp_sel = params->pmc_vddp_sel; udelay(params->pmc_vddp_sel_wait); diff --git a/fusee/fusee-secondary/src/btn.c b/fusee/fusee-secondary/src/btn.c index bffc8e79d..942d27be6 100644 --- a/fusee/fusee-secondary/src/btn.c +++ b/fusee/fusee-secondary/src/btn.c @@ -16,7 +16,7 @@ uint32_t btn_read() res |= BTN_VOL_UP; uint32_t val = 0; - if (i2c_query(4, 0x3C, 0x15, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1)) { if (val & 0x4) res |= BTN_POWER; diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c index bceaf7d73..b0c884670 100644 --- a/fusee/fusee-secondary/src/cluster.c +++ b/fusee/fusee-secondary/src/cluster.c @@ -12,22 +12,22 @@ void _cluster_enable_power() { uint8_t val = 0; - i2c_query(4, 0x3C, MAX77620_REG_AME_GPIO, &val, 1); + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); val &= 0xDF; - i2c_send(4, 0x3C, MAX77620_REG_AME_GPIO, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_AME_GPIO, &val, 1); val = 0x09; - i2c_send(4, 0x3C, MAX77620_REG_GPIO5, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO5, &val, 1); /* Enable power. */ val = 0x20; - i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL3, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x02, &val, 1); val = 0x8D; - i2c_send(4, 0x1B, MAX77620_REG_CNFG1_32K, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x03, &val, 1); val = 0xB7; - i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL1, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x00, &val, 1); val = 0xB7; - i2c_send(4, 0x1B, MAX77620_REG_CNFGGLBL2, &val, 1); + i2c_send(I2C_5, MAX77621_CPU_I2C_ADDR, 0x01, &val, 1); } int _cluster_pmc_enable_partition(uint32_t part, uint32_t toggle) diff --git a/fusee/fusee-secondary/src/di.c b/fusee/fusee-secondary/src/di.c index e22257465..f46310eb8 100644 --- a/fusee/fusee-secondary/src/di.c +++ b/fusee/fusee-secondary/src/di.c @@ -36,9 +36,9 @@ void display_init() /* Power on. */ uint8_t val = 0xD0; - i2c_send(4, 0x3C, MAX77620_REG_LDO0_CFG, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1); val = 0x09; - i2c_send(4, 0x3C, MAX77620_REG_GPIO7, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO7, &val, 1); /* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */ car->rst_dev_h_clr = 0x1010000; diff --git a/fusee/fusee-secondary/src/i2c.c b/fusee/fusee-secondary/src/i2c.c index a98d7fa6e..028ba56e8 100644 --- a/fusee/fusee-secondary/src/i2c.c +++ b/fusee/fusee-secondary/src/i2c.c @@ -43,16 +43,16 @@ void i2c_init(unsigned int id) { void i2c_send_pmic_cpu_shutdown_cmd(void) { uint32_t val = 0; /* PMIC == Device 4:3C. */ - i2c_query(4, 0x3C, 0x41, &val, 1); + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); val |= 4; - i2c_send(4, 0x3C, 0x41, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); } /* Queries the value of TI charger bit over I2C. */ bool i2c_query_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); return (val & 0x80) != 0; } @@ -60,34 +60,34 @@ bool i2c_query_ti_charger_bit_7(void) { void i2c_clear_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); val &= 0x7F; - i2c_send(0, 0x6B, 0, &val, 1); + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); } /* Sets TI charger bit over I2C. */ void i2c_set_ti_charger_bit_7(void) { uint32_t val = 0; /* TI Charger = Device 0:6B. */ - i2c_query(0, 0x6B, 0, &val, 1); + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); val |= 0x80; - i2c_send(0, 0x6B, 0, &val, 1); + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); } /* Get registers pointer based on I2C ID. */ volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { switch (id) { - case 0: + case I2C_1: return I2C1_REGS; - case 1: + case I2C_2: return I2C2_REGS; - case 2: + case I2C_3: return I2C3_REGS; - case 3: + case I2C_4: return I2C4_REGS; - case 4: + case I2C_5: return I2C5_REGS; - case 5: + case I2C_6: return I2C6_REGS; default: generic_panic(); diff --git a/fusee/fusee-secondary/src/i2c.h b/fusee/fusee-secondary/src/i2c.h index e07ed3349..8b0acbd35 100644 --- a/fusee/fusee-secondary/src/i2c.h +++ b/fusee/fusee-secondary/src/i2c.h @@ -8,6 +8,20 @@ #define I2C234_BASE 0x7000C000 #define I2C56_BASE 0x7000D000 +#define I2C_1 0 +#define I2C_2 1 +#define I2C_3 2 +#define I2C_4 3 +#define I2C_5 4 +#define I2C_6 5 + +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B + typedef struct { uint32_t I2C_I2C_CNFG_0; uint32_t I2C_I2C_CMD_ADDR0_0; diff --git a/fusee/fusee-secondary/src/max77620.h b/fusee/fusee-secondary/src/max77620.h index ad22a06b5..ab90f2b8e 100644 --- a/fusee/fusee-secondary/src/max77620.h +++ b/fusee/fusee-secondary/src/max77620.h @@ -11,6 +11,36 @@ #ifndef _MFD_MAX77620_H_ #define _MFD_MAX77620_H_ +/* RTC Registers */ +#define MAX77620_REG_RTCINT 0x00 +#define MAX77620_REG_RTCINTM 0x01 +#define MAX77620_REG_RTCCNTLM 0x02 +#define MAX77620_REG_RTCCNTL 0x03 +#define MAX77620_REG_RTCUPDATE0 0x04 +#define MAX77620_REG_RTCUPDATE1 0x05 +#define MAX77620_REG_RTCSMPL 0x06 +#define MAX77620_REG_RTCSEC 0x07 +#define MAX77620_REG_RTCMIN 0x08 +#define MAX77620_REG_RTCHOUR 0x09 +#define MAX77620_REG_RTCDOW 0x0A +#define MAX77620_REG_RTCMONTH 0x0B +#define MAX77620_REG_RTCYEAR 0x0C +#define MAX77620_REG_RTCDOM 0x0D +#define MAX77620_REG_RTCSECA1 0x0E +#define MAX77620_REG_RTCMINA1 0x0F +#define MAX77620_REG_RTCHOURA1 0x10 +#define MAX77620_REG_RTCDOWA1 0x11 +#define MAX77620_REG_RTCMONTHA1 0x12 +#define MAX77620_REG_RTCYEARA1 0x13 +#define MAX77620_REG_RTCDOMA1 0x14 +#define MAX77620_REG_RTCSECA2 0x15 +#define MAX77620_REG_RTCMINA2 0x16 +#define MAX77620_REG_RTCHOURA2 0x17 +#define MAX77620_REG_RTCDOWA2 0x18 +#define MAX77620_REG_RTCMONTHA2 0x19 +#define MAX77620_REG_RTCYEARA2 0x1A +#define MAX77620_REG_RTCDOMA2 0x1B + /* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ #define MAX77620_REG_CNFGGLBL1 0x00 #define MAX77620_REG_CNFGGLBL2 0x01 diff --git a/fusee/fusee-secondary/src/max7762x.c b/fusee/fusee-secondary/src/max7762x.c index 419a13bce..da20eb7b9 100644 --- a/fusee/fusee-secondary/src/max7762x.c +++ b/fusee/fusee-secondary/src/max7762x.c @@ -55,11 +55,11 @@ int max77620_regulator_get_status(uint32_t id) uint8_t val = 0; if (reg->type == REGULATOR_SD) { - if (i2c_query(4, 0x3C, MAX77620_REG_STATSD, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_STATSD, &val, 1)) return (val & reg->status_mask) ? 0 : 1; } - if (i2c_query(4, 0x3C, reg->cfg_addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1)) return (val & 8) ? 0 : 1; return 0; @@ -73,7 +73,7 @@ int max77620_regulator_config_fps(uint32_t id) const max77620_regulator_t *reg = &_pmic_regulators[id]; uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); - if (i2c_send(4, 0x3C, reg->fps_addr, &val, 1)) { + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->fps_addr, &val, 1)) { return 1; } @@ -93,11 +93,11 @@ int max77620_regulator_set_voltage(uint32_t id, uint32_t mv) uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; uint8_t val = 0; - if (i2c_query(4, 0x3C, reg->volt_addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) { val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask)); - if (i2c_send(4, 0x3C, reg->volt_addr, &val, 1)) + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) { udelay(1000); return 1; @@ -117,14 +117,14 @@ int max77620_regulator_enable(uint32_t id, int enable) uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr; uint8_t val = 0; - if (i2c_query(4, 0x3C, addr, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) { if (enable) val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); else val &= ~reg->enable_mask; - if (i2c_send(4, 0x3C, addr, &val, 1)) + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) { udelay(1000); return 1; @@ -139,7 +139,7 @@ void max77620_config_default() for (uint32_t i = 1; i <= REGULATOR_MAX; i++) { uint8_t val = 0; - if (i2c_query(4, 0x3C, MAX77620_REG_CID4, &val, 1)) + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CID4, &val, 1)) { max77620_regulator_config_fps(i); max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); @@ -151,11 +151,11 @@ void max77620_config_default() } uint8_t val = 4; - i2c_send(4, 0x3C, MAX77620_REG_SD_CFG2, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1); } void max77620_low_battery_monitor_config() { uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N); - i2c_send(4, 0x3C, MAX77620_REG_CNFGGLBL1, &val, 1); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); } diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 17a9b5f0c..dbe0882b1 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -7,10 +7,13 @@ #include "fs_utils.h" #include "nxboot.h" #include "nxfs.h" +#include "bct.h" #include "di.h" #include "mc.h" #include "se.h" #include "pmc.h" +#include "i2c.h" +#include "max77620.h" #include "cluster.h" #include "flow.h" #include "timers.h" @@ -78,13 +81,98 @@ static void nxboot_configure_exosphere(uint32_t target_firmware) { *(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg; } +static void nxboot_set_bootreason() { + boot_reason_t boot_reason = {0}; + FILE *boot0; + nvboot_config_table *bct; + nv_bootloader_info *bootloader_info; + + /* Allocate memory for the BCT. */ + bct = malloc(sizeof(nvboot_config_table)); + if (bct == NULL) { + fatal_error("[NXBOOT]: Out of memory!\n"); + } + + /* Open boot0. */ + boot0 = fopen("boot0:/", "rb"); + if (boot0 == NULL) { + fatal_error("[NXBOOT]: Failed to open boot0!\n"); + } + + /* Read the BCT. */ + if (fread(bct, sizeof(nvboot_config_table), 1, boot0) == 0) { + fatal_error("[NXBOOT]: Failed to read the BCT!\n"); + } + + /* Close boot0. */ + fclose(boot0); + + /* Populate bootloader parameters. */ + bootloader_info = &bct->bootloader[0]; + boot_reason.bootloader_version = bootloader_info->version; + boot_reason.bootloader_start_block = bootloader_info->start_blk; + boot_reason.bootloader_start_page = bootloader_info->start_page; + boot_reason.bootloader_attribute = bootloader_info->attribute; + + uint8_t power_key_intr = 0; + uint8_t rtc_intr = 0; + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFIRQ, &power_key_intr, 1); + i2c_query(I2C_5, MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCINT, &rtc_intr, 1); + + /* Set PMIC value. */ + boot_reason.boot_reason_value = ((rtc_intr << 0x08) | power_key_intr); + + /* TODO: Find out what these mean. */ + if (power_key_intr & 0x80) + boot_reason.boot_reason_state = 0x01; + else if (power_key_intr & 0x08) + boot_reason.boot_reason_state = 0x02; + else if (rtc_intr & 0x02) + boot_reason.boot_reason_state = 0x03; + else if (rtc_intr & 0x04) + boot_reason.boot_reason_state = 0x04; + + /* Set in memory. */ + memcpy((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON, &boot_reason, sizeof(boot_reason)); + + /* Clean up. */ + free(bct); +} + +static void nxboot_move_bootconfig() { + FILE *bcfile; + void *bootconfig; + + /* Allocate memory for reading BootConfig. */ + bootconfig = memalign(0x1000, 0x4000); + if (bootconfig == NULL) { + fatal_error("[NXBOOT]: Out of memory!\n"); + } + + /* Get BootConfig from the Package2 partition. */ + bcfile = fopen("bcpkg21:/", "rb"); + if (bcfile == NULL) { + fatal_error("[NXBOOT]: Failed to open BootConfig from eMMC!\n"); + } + if (fread(bootconfig, 0x4000, 1, bcfile) < 1) { + fatal_error("[NXBOOT]: Failed to read BootConfig!\n"); + } + fclose(bcfile); + + /* Copy the first 0x3000 bytes into IRAM. */ + memset((void *)0x4003D000, 0, 0x3000); + memcpy((void *)0x4003D000, bootconfig, 0x3000); + + /* Clean up. */ + free(bootconfig); +} + /* This is the main function responsible for booting Horizon. */ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; void nxboot_main(void) { volatile tegra_pmc_t *pmc = pmc_get_regs(); volatile tegra_se_t *se = se_get_regs(); loader_ctx_t *loader_ctx = get_loader_ctx(); - /* void *bootconfig; */ package2_header_t *package2; size_t package2_size; void *tsec_fw; @@ -101,7 +189,7 @@ void nxboot_main(void) { void *exosphere_memaddr; /* Allocate memory for reading Package2. */ - package2 = memalign(4096, PACKAGE2_SIZE_MAX); + package2 = memalign(0x1000, PACKAGE2_SIZE_MAX); if (package2 == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -115,10 +203,12 @@ void nxboot_main(void) { } } else { pk2file = fopen("bcpkg21:/", "rb"); - if (pk2file == NULL || fseek(pk2file, 0x4000, SEEK_SET) != 0) { - printf("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); + if (pk2file == NULL) { + fatal_error("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); + } + if (fseek(pk2file, 0x4000, SEEK_SET) != 0) { + fatal_error("[NXBOOT]: Failed to seek Package2 in eMMC: %s!\n", strerror(errno)); fclose(pk2file); - generic_panic(); } } @@ -127,7 +217,7 @@ void nxboot_main(void) { fatal_error("[NXBOOT]: Failed to read Package2!\n"); } package2_size = package2_meta_get_size(&package2->metadata); - if (package2_size > PACKAGE2_SIZE_MAX || package2_size <= sizeof(package2_header_t)) { + if ((package2_size > PACKAGE2_SIZE_MAX) || (package2_size <= sizeof(package2_header_t))) { fatal_error("[NXBOOT]: Package2 is too big or too small!\n"); } if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) { @@ -138,7 +228,7 @@ void nxboot_main(void) { /* Read and parse boot0. */ printf("[NXBOOT]: Reading boot0...\n"); boot0 = fopen("boot0:/", "rb"); - if (boot0 == NULL || package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1) { + if ((boot0 == NULL) || (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1)) { fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno)); } fclose(boot0); @@ -146,13 +236,15 @@ void nxboot_main(void) { /* Read the TSEC firmware from a file, otherwise from PK1L. */ if (loader_ctx->tsecfw_path[0] != '\0') { tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); - if (tsec_fw_size != 0 && tsec_fw_size != 0xF00) { + if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00)) { fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); } else if (tsec_fw_size == 0) { fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } - + + /* Allocate memory for the TSEC firmware. */ tsec_fw = memalign(0x100, tsec_fw_size); + if (tsec_fw == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -165,10 +257,6 @@ void nxboot_main(void) { fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); } } - - /* TODO: Validate that we're capable of booting. */ - - /* TODO: Initialize Boot Reason. */ /* Find the system's target firmware. */ uint32_t target_firmware = nxboot_get_target_firmware(package1loader); @@ -180,6 +268,12 @@ void nxboot_main(void) { /* Setup boot configuration for Exosphère. */ nxboot_configure_exosphere(target_firmware); + /* Initialize Boot Reason on older firmware versions. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + printf("[NXBOOT]: Initializing Boot Reason...\n"); + nxboot_set_bootreason(); + } + /* Derive keydata. */ if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) { fatal_error("[NXBOOT]: Key derivation failed!\n"); @@ -192,7 +286,9 @@ void nxboot_main(void) { fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } + /* Allocate memory for the warmboot firmware. */ warmboot_fw = malloc(warmboot_fw_size); + if (warmboot_fw == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -236,32 +332,36 @@ void nxboot_main(void) { /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); - printf(u8"Reading Exosphère...\n"); + printf(u8"[NXBOOT]: Reading Exosphère...\n"); /* Select the right address for Exosphère. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { - exosphere_memaddr = (void *)0x40020000; + exosphere_memaddr = (void *)0x4002D000; } else { - exosphere_memaddr = (void *)0x40018000; /* 5.x has its secmon's crt0 around this region. */ + exosphere_memaddr = (void *)0x4002B000; } /* Copy Exosphère to a good location or read it directly to it. */ if (loader_ctx->exosphere_path[0] != '\0') { size_t exosphere_size = get_file_size(loader_ctx->exosphere_path); if (exosphere_size == 0) { - fatal_error(u8"Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT]: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } else if (exosphere_size > 0x10000) { /* The maximum is actually a bit less than that. */ - fatal_error(u8"Exosphère from %s is too big!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT]: Exosphère from %s is too big!\n", loader_ctx->exosphere_path); } if (read_from_file(exosphere_memaddr, exosphere_size, loader_ctx->exosphere_path) != exosphere_size) { - fatal_error(u8"Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); + fatal_error(u8"[NXBOOT]: Could not read Exosphère from %s!\n", loader_ctx->exosphere_path); } } else { memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); } + /* Move BootConfig. */ + printf("[NXBOOT]: Moving BootConfig...\n"); + nxboot_move_bootconfig(); + /* Clean up. */ free(package1loader); if (loader_ctx->tsecfw_path[0] != '\0') { @@ -287,9 +387,6 @@ void nxboot_main(void) { set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); } - /* TODO: Handle bootconfig. */ - memset((void *)0x4003D000, 0, 0x3000); - /* Finalize the GPU UCODE carveout. */ mc_config_carveout_finalize(); diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 32710d7eb..5f24266d3 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -5,22 +5,26 @@ #define MAILBOX_NX_BOOTLOADER_BASE ((void *)(0x40002000)) +#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) #define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8) +#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC) #define NX_BOOTLOADER_STATE_INIT 0 #define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1 - #define NX_BOOTLOADER_STATE_LOADED_PACKAGE2 2 #define NX_BOOTLOADER_STATE_FINISHED 3 - #define NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X 2 #define NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X 3 #define NX_BOOTLOADER_STATE_FINISHED_4X 4 -/* Physaddr 0x40002EFC */ -#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC) - -#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) +typedef struct { + uint32_t bootloader_version; + uint32_t bootloader_start_block; + uint32_t bootloader_start_page; + uint32_t bootloader_attribute; + uint32_t boot_reason_value; + uint32_t boot_reason_state; +} boot_reason_t; void nxboot_main(void); From 3cf37330ca8e61cb766c52ad1ecabb03175dbed5 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Thu, 30 Aug 2018 19:49:33 +0100 Subject: [PATCH 061/489] fusee: Disable AHB redirection when necessary. fusee: Add 3.0.0/3.0.1/3.0.2 warmboot fix. --- fusee/fusee-primary/src/fs_utils.c | 6 ++++++ fusee/fusee-secondary/src/nxboot.c | 11 ++++++++++- fusee/fusee-secondary/src/nxfs.c | 7 +++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-primary/src/fs_utils.c b/fusee/fusee-primary/src/fs_utils.c index 1c8529f07..9146ad0c2 100644 --- a/fusee/fusee-primary/src/fs_utils.c +++ b/fusee/fusee-primary/src/fs_utils.c @@ -47,6 +47,12 @@ void unmount_sd(void) sdmmc_device_finish(&g_sd_device); g_sd_mounted = false; } + + /* Disable AHB redirection if necessary. */ + if (g_ahb_redirect_enabled) { + mc_disable_ahb_redirect(); + g_ahb_redirect_enabled = false; + } } uint32_t get_file_size(const char *filename) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index dbe0882b1..0e1351251 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -362,6 +362,15 @@ void nxboot_main(void) { printf("[NXBOOT]: Moving BootConfig...\n"); nxboot_move_bootconfig(); + /* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == EXOSPHERE_TARGET_FIRMWARE_300) { + const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; + if (!strcmp(package1loader_header->build_timestamp, "20170519101410")) + pmc->secure_scratch32 = 0xE3; /* Warmboot 3.0.0 security check.*/ + else if (!strcmp(package1loader_header->build_timestamp, "20170710161758")) + pmc->secure_scratch32 = 0x104; /* Warmboot 3.0.1/3.0.2 security check. */ + } + /* Clean up. */ free(package1loader); if (loader_ctx->tsecfw_path[0] != '\0') { @@ -424,7 +433,7 @@ void nxboot_main(void) { display_end(); /* Boot CPU0. */ - cluster_boot_cpu0((uint64_t)(uintptr_t)exosphere_memaddr); + cluster_boot_cpu0((uint32_t)exosphere_memaddr); /* Wait for Exosphère to wake up. */ while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { diff --git a/fusee/fusee-secondary/src/nxfs.c b/fusee/fusee-secondary/src/nxfs.c index fcb05d0f9..81c775a30 100644 --- a/fusee/fusee-secondary/src/nxfs.c +++ b/fusee/fusee-secondary/src/nxfs.c @@ -48,6 +48,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) { devpart->crypto_work_buffer_num_sectors = 0; } + /* Enable AHB redirection if necessary. */ if (!g_ahb_redirect_enabled) { mc_enable_ahb_redirect(); g_ahb_redirect_enabled = true; @@ -78,6 +79,12 @@ static int mmc_partition_initialize(device_partition_t *devpart) { static void mmc_partition_finalize(device_partition_t *devpart) { free(devpart->crypto_work_buffer); + + /* Disable AHB redirection if necessary. */ + if (g_ahb_redirect_enabled) { + mc_disable_ahb_redirect(); + g_ahb_redirect_enabled = false; + } } static int mmc_partition_read(device_partition_t *devpart, void *dst, uint64_t sector, uint64_t num_sectors) { From 97d1ca3cc974f35046b8676fb1547772ba79f312 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 31 Aug 2018 20:10:06 +0000 Subject: [PATCH 062/489] fusee: Disable built-in PM system module. --- fusee/fusee-secondary/src/stratosphere.c | 65 ++++++++++++++++++------ 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index a0d1b5db0..4664da5d0 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -19,6 +19,11 @@ static ini1_header_t *g_stratosphere_ini1 = NULL; +static bool g_stratosphere_loader_enabled = true; +static bool g_stratosphere_sm_enabled = true; +static bool g_stratosphere_pm_enabled = false; +static bool g_stratosphere_boot_enabled = false; + extern const uint8_t boot_100_kip[], boot_200_kip[]; extern const uint8_t loader_kip[], pm_kip[], sm_kip[]; extern const uint32_t boot_100_kip_size, boot_200_kip_size; @@ -27,8 +32,9 @@ extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size; /* GCC doesn't consider the size as const... we have to write it ourselves. */ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { - /* const uint8_t *boot_kip = NULL; */ + const uint8_t *boot_kip = NULL; uint32_t boot_kip_size = 0; + uint32_t num_processes = 0; uint8_t *data; if (g_stratosphere_ini1 != NULL) { @@ -36,14 +42,36 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { } if (target_firmware <= EXOSPHERE_TARGET_FIRMWARE_100) { - /* boot_kip = boot_100_kip; */ + boot_kip = boot_100_kip; boot_kip_size = boot_100_kip_size; } else { - /* boot_kip = boot_200_kip; */ + boot_kip = boot_200_kip; boot_kip_size = boot_200_kip_size; } - size_t size = sizeof(ini1_header_t) + loader_kip_size + pm_kip_size + sm_kip_size + boot_kip_size; + size_t size = sizeof(ini1_header_t); + + /* Calculate our processes' sizes. */ + if (g_stratosphere_loader_enabled) { + size += loader_kip_size; + num_processes++; + } + + if (g_stratosphere_pm_enabled) { + size += pm_kip_size; + num_processes++; + } + + if (g_stratosphere_sm_enabled) { + size += sm_kip_size; + num_processes++; + } + + if (g_stratosphere_boot_enabled) { + size += boot_kip_size; + num_processes++; + } + g_stratosphere_ini1 = (ini1_header_t *)malloc(size); if (g_stratosphere_ini1 == NULL) { @@ -52,26 +80,31 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { g_stratosphere_ini1->magic = MAGIC_INI1; g_stratosphere_ini1->size = size; - g_stratosphere_ini1->num_processes = 3; /*TODO: Change to 4 when boot is supported. */ + g_stratosphere_ini1->num_processes = num_processes; g_stratosphere_ini1->_0xC = 0; data = g_stratosphere_ini1->kip_data; /* Copy our processes. */ - memcpy(data, loader_kip, loader_kip_size); - data += loader_kip_size; + if (g_stratosphere_loader_enabled) { + memcpy(data, loader_kip, loader_kip_size); + data += loader_kip_size; + } - memcpy(data, pm_kip, pm_kip_size); - data += pm_kip_size; + if (g_stratosphere_pm_enabled) { + memcpy(data, pm_kip, pm_kip_size); + data += pm_kip_size; + } - memcpy(data, sm_kip, sm_kip_size); - data += sm_kip_size; + if (g_stratosphere_sm_enabled) { + memcpy(data, sm_kip, sm_kip_size); + data += sm_kip_size; + } - /* TODO: Uncomment when boot is supported. */ - /* - memcpy(data, boot_kip, boot_kip_size); - data += boot_kip_size; - */ + if (g_stratosphere_boot_enabled) { + memcpy(data, boot_kip, boot_kip_size); + data += boot_kip_size; + } return g_stratosphere_ini1; } From 70c4e64d20ba509defa73c8a0454aa7d4905355b Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 31 Aug 2018 22:36:26 +0000 Subject: [PATCH 063/489] fusee: SYSCTR0 was still wrong... --- fusee/fusee-primary/src/sysctr0.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-primary/src/sysctr0.h b/fusee/fusee-primary/src/sysctr0.h index 477063bb0..d861f739b 100644 --- a/fusee/fusee-primary/src/sysctr0.h +++ b/fusee/fusee-primary/src/sysctr0.h @@ -3,9 +3,26 @@ #include <stdint.h> -#define SYSCTR0_BASE 0x7000F000 +#define SYSCTR0_BASE 0x700F0000 #define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) +#define SYSCTR0_CNTCR_0 MAKE_SYSCTR0_REG(0x00) +#define SYSCTR0_CNTSR_0 MAKE_SYSCTR0_REG(0x04) +#define SYSCTR0_CNTCV0_0 MAKE_SYSCTR0_REG(0x08) +#define SYSCTR0_CNTCV1_0 MAKE_SYSCTR0_REG(0x0C) #define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20) +#define SYSCTR0_CNTFID1_0 MAKE_SYSCTR0_REG(0x24) +#define SYSCTR0_COUNTERID4_0 MAKE_SYSCTR0_REG(0xFD0) +#define SYSCTR0_COUNTERID5_0 MAKE_SYSCTR0_REG(0xFD4) +#define SYSCTR0_COUNTERID6_0 MAKE_SYSCTR0_REG(0xFD8) +#define SYSCTR0_COUNTERID7_0 MAKE_SYSCTR0_REG(0xFDC) +#define SYSCTR0_COUNTERID0_0 MAKE_SYSCTR0_REG(0xFE0) +#define SYSCTR0_COUNTERID1_0 MAKE_SYSCTR0_REG(0xFE4) +#define SYSCTR0_COUNTERID2_0 MAKE_SYSCTR0_REG(0xFE8) +#define SYSCTR0_COUNTERID3_0 MAKE_SYSCTR0_REG(0xFEC) +#define SYSCTR0_COUNTERID8_0 MAKE_SYSCTR0_REG(0xFF0) +#define SYSCTR0_COUNTERID9_0 MAKE_SYSCTR0_REG(0xFF4) +#define SYSCTR0_COUNTERID10_0 MAKE_SYSCTR0_REG(0xFF8) +#define SYSCTR0_COUNTERID11_0 MAKE_SYSCTR0_REG(0xFFC) #endif From a8ac5c651fa0cdfe9cfc37a235cc0f5be8fd0dd2 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 31 Aug 2018 22:38:46 +0000 Subject: [PATCH 064/489] exosphere: Add SYSCTR0 register definitions. --- exosphere/src/sysctr0.h | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/exosphere/src/sysctr0.h b/exosphere/src/sysctr0.h index 9c887c48c..c29a956ea 100644 --- a/exosphere/src/sysctr0.h +++ b/exosphere/src/sysctr0.h @@ -9,9 +9,25 @@ #define SYSCTR0_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SYSCTR0)) - #define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) - +#define SYSCTR0_CNTCR_0 MAKE_SYSCTR0_REG(0x00) +#define SYSCTR0_CNTSR_0 MAKE_SYSCTR0_REG(0x04) +#define SYSCTR0_CNTCV0_0 MAKE_SYSCTR0_REG(0x08) +#define SYSCTR0_CNTCV1_0 MAKE_SYSCTR0_REG(0x0C) +#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20) +#define SYSCTR0_CNTFID1_0 MAKE_SYSCTR0_REG(0x24) +#define SYSCTR0_COUNTERID4_0 MAKE_SYSCTR0_REG(0xFD0) +#define SYSCTR0_COUNTERID5_0 MAKE_SYSCTR0_REG(0xFD4) +#define SYSCTR0_COUNTERID6_0 MAKE_SYSCTR0_REG(0xFD8) +#define SYSCTR0_COUNTERID7_0 MAKE_SYSCTR0_REG(0xFDC) +#define SYSCTR0_COUNTERID0_0 MAKE_SYSCTR0_REG(0xFE0) +#define SYSCTR0_COUNTERID1_0 MAKE_SYSCTR0_REG(0xFE4) +#define SYSCTR0_COUNTERID2_0 MAKE_SYSCTR0_REG(0xFE8) +#define SYSCTR0_COUNTERID3_0 MAKE_SYSCTR0_REG(0xFEC) +#define SYSCTR0_COUNTERID8_0 MAKE_SYSCTR0_REG(0xFF0) +#define SYSCTR0_COUNTERID9_0 MAKE_SYSCTR0_REG(0xFF4) +#define SYSCTR0_COUNTERID10_0 MAKE_SYSCTR0_REG(0xFF8) +#define SYSCTR0_COUNTERID11_0 MAKE_SYSCTR0_REG(0xFFC) #endif From 58a42be38f768d0a596d53d629b127483493e3a3 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 31 Aug 2018 22:46:08 +0000 Subject: [PATCH 065/489] fusee: Comment out splash screen delay. --- fusee/fusee-secondary/src/splash_screen.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index c317d3797..dd0591b9a 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -1,5 +1,4 @@ #include <stdio.h> -#include "utils.h" #include "timers.h" #include "splash_screen.h" #include "fs_utils.h" @@ -7,7 +6,7 @@ void display_splash_screen_bmp(const char *custom_splash_path) { uint8_t *splash_screen = g_default_splash_screen; - if (custom_splash_path != NULL && custom_splash_path[0] != '\x00') { + if ((custom_splash_path != NULL) && (custom_splash_path[0] != '\x00')) { if (!read_from_file(splash_screen, sizeof(g_default_splash_screen), custom_splash_path)) { fatal_error("Failed to read custom splash screen from %s!\n", custom_splash_path); } @@ -16,5 +15,5 @@ void display_splash_screen_bmp(const char *custom_splash_path) { /* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */ /* Display the splash screen for three seconds. */ - wait(3000000); + /* udelay(3000000); */ } From abf57d2e43e4c6f41e04103a70fc9a4f57a28fc0 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 31 Aug 2018 22:52:31 +0000 Subject: [PATCH 066/489] fusee: Unmount *after* reading the splash screen. --- fusee/fusee-secondary/src/nxboot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 0e1351251..8a44b2f8c 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -381,9 +381,6 @@ void nxboot_main(void) { } free(package2); - /* Unmount everything. */ - nxfs_unmount_all(); - /* Clear used keyslots. */ clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); @@ -426,6 +423,9 @@ void nxboot_main(void) { /* Display splash screen. */ display_splash_screen_bmp(loader_ctx->custom_splash_path); + /* Unmount everything. */ + nxfs_unmount_all(); + /* Turn off the backlight. */ display_backlight(false); From 8007480a15144684530afa4f2cdbe93708c4b986 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Mon, 3 Sep 2018 18:48:01 +0100 Subject: [PATCH 067/489] fusee: Re-enable built-in PM system module. --- fusee/fusee-secondary/src/stratosphere.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index 4664da5d0..4a1835085 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -21,7 +21,7 @@ static ini1_header_t *g_stratosphere_ini1 = NULL; static bool g_stratosphere_loader_enabled = true; static bool g_stratosphere_sm_enabled = true; -static bool g_stratosphere_pm_enabled = false; +static bool g_stratosphere_pm_enabled = true; static bool g_stratosphere_boot_enabled = false; extern const uint8_t boot_100_kip[], boot_200_kip[]; From e02bfe036c5e5092e1bb9625c939cedf1a20f8a5 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Tue, 4 Sep 2018 19:13:36 +0100 Subject: [PATCH 068/489] fusee: Fix CAR registers' definition. --- fusee/fusee-primary/src/car.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fusee/fusee-primary/src/car.h b/fusee/fusee-primary/src/car.h index 6ec42e744..572595c90 100644 --- a/fusee/fusee-primary/src/car.h +++ b/fusee/fusee-primary/src/car.h @@ -224,16 +224,16 @@ typedef struct { uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ uint32_t _0x350[2]; - uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ - uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ - uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */ + uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */ uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ - uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ + uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */ uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ - uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ + uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */ uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ @@ -456,6 +456,7 @@ typedef struct { uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ + uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */ uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ From 5542352239f409a4917b12efc5c4871f24d9847b Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Tue, 4 Sep 2018 19:14:29 +0100 Subject: [PATCH 069/489] fusee: Fix CAR registers' definition. --- fusee/fusee-secondary/src/car.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fusee/fusee-secondary/src/car.h b/fusee/fusee-secondary/src/car.h index 6ec42e744..572595c90 100644 --- a/fusee/fusee-secondary/src/car.h +++ b/fusee/fusee-secondary/src/car.h @@ -224,16 +224,16 @@ typedef struct { uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ uint32_t _0x350[2]; - uint32_t rst_dev_v; /* _RST_DEVICES_V/W_0 */ - uint32_t rst_dev_w; /* _RST_DEVICES_V/W_0 */ - uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V/W_0 */ - uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_V/W_0 */ + uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */ + uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */ uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ - uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36C */ + uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */ uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ - uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37C */ + uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */ uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ @@ -456,6 +456,7 @@ typedef struct { uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ + uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */ uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ From ad4605abdecddd95c619fec7d04f098165c4842a Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Tue, 4 Sep 2018 19:16:03 +0100 Subject: [PATCH 070/489] fusee: Fix a bug in cluster boot code. --- fusee/fusee-secondary/src/cluster.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c index b0c884670..12eebeb8b 100644 --- a/fusee/fusee-secondary/src/cluster.c +++ b/fusee/fusee-secondary/src/cluster.c @@ -77,12 +77,12 @@ void cluster_boot_cpu0(uint32_t entry) udelay(2); car->pllx_base = 0x80404E02; car->pllx_base = 0x404E02; - car->pllx_misc = ((car->pllx_base & 0xFFFBFFFF) | 0x40000); + car->pllx_misc = ((car->pllx_misc & 0xFFFBFFFF) | 0x40000); car->pllx_base = 0x40404E02; } while (!(car->pllx_base & 0x8000000)) { - /* Spinlock. */ + /* Wait. */ } /* Configure MSELECT source and enable clock. */ @@ -111,13 +111,13 @@ void cluster_boot_cpu0(uint32_t entry) /* Request and wait for RAM repair. */ FLOW_CTLR_RAM_REPAIR_0 = 1; while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)){ - /* Spinlock. */ + /* Wait. */ } MAKE_EXCP_VEC_REG(0x100) = 0; /* Set reset vector. */ - SB_AA64_RESET_LOW_0 = entry | 1; + SB_AA64_RESET_LOW_0 = (entry | 1); SB_AA64_RESET_HIGH_0 = 0; /* Non-secure reset vector write disable. */ From 1c8abb4afba783af69ae9cd8c4be0ab0e0e6a342 Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Wed, 5 Sep 2018 05:55:46 +0200 Subject: [PATCH 071/489] name some MC registers replace hex values with enum cleanup code for better readability --- exosphere/src/bootup.c | 66 +++++++++++++++++++++++------------------- exosphere/src/mc.h | 19 ++++++++++-- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index a1fd2522a..5897fd581 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -82,15 +82,12 @@ void bootup_misc_mmio(void) { MC_SECURITY_CFG1_0 = 0; MC_SECURITY_CFG3_0 = 3; configure_default_carveouts(); - - - + /* Mark registers secure world only. */ if (exosphere_get_target_firmware() == EXOSPHERE_TARGET_FIRMWARE_100) { - /* TODO: Switch these to use the enum. */ - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = 0x500244; - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 = 0xA3700000; - APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = 0x304; + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SATA | APB_SSER0_LA; + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 = APB_SSER1_SPI1 | APB_SSER1_SPI2 | APB_SSER1_SPI3 | APB_SSER1_SPI5 | APB_SSER1_SPI6 | APB_SSER1_I2C4 | APB_SSER1_I2C6; + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = 1 << 4 | 1 << 5 | APB_SSER2_DDS; /* bits 4 and 5 are not labeled in 21.1.7.3 */ } else { /* Mark SATA_AUX, DTV, QSPI, SE, SATA, LA secure only. */ APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SE | APB_SSER0_SATA | APB_SSER0_LA; @@ -114,37 +111,42 @@ void bootup_misc_mmio(void) { APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = sec_disable_2; } + /* reset Translation Enable Registers */ + MC_SMMU_TRANSLATION_ENABLE_0_0 = 0xFFFFFFFF; + MC_SMMU_TRANSLATION_ENABLE_1_0 = 0xFFFFFFFF; + MC_SMMU_TRANSLATION_ENABLE_2_0 = 0xFFFFFFFF; + MC_SMMU_TRANSLATION_ENABLE_3_0 = 0xFFFFFFFF; + MC_SMMU_TRANSLATION_ENABLE_4_0 = 0xFFFFFFFF; + /* TODO: What are these MC reg writes? */ - MAKE_MC_REG(0x228) = 0xFFFFFFFF; - MAKE_MC_REG(0x22C) = 0xFFFFFFFF; - MAKE_MC_REG(0x230) = 0xFFFFFFFF; - MAKE_MC_REG(0x234) = 0xFFFFFFFF; - MAKE_MC_REG(0xB98) = 0xFFFFFFFF; if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { MAKE_MC_REG(0x038) = 0xE; } else { MAKE_MC_REG(0x038) = 0x0; } MAKE_MC_REG(0x03C) = 0; + + /* MISC registers*/ MAKE_MC_REG(0x9E0) = 0; MAKE_MC_REG(0x9E4) = 0; MAKE_MC_REG(0x9E8) = 0; MAKE_MC_REG(0x9EC) = 0; MAKE_MC_REG(0x9F0) = 0; MAKE_MC_REG(0x9F4) = 0; + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { - MAKE_MC_REG(0x01C) = 0; + MC_SMMU_PTB_ASID_0 = 0; } - MAKE_MC_REG(0x020) = 0; - MAKE_MC_REG(0x014) = 0x30000030; - MAKE_MC_REG(0x018) = 0x2800003F; - (void)(MAKE_MC_REG(0x014)); - MAKE_MC_REG(0x034) = 0; - (void)(MAKE_MC_REG(0x014)); - MAKE_MC_REG(0x030) = 0; - (void)(MAKE_MC_REG(0x014)); - MAKE_MC_REG(0x010) = 1; - (void)(MAKE_MC_REG(0x014)); + MC_SMMU_PTB_DATA_0 = 0; + MC_SMMU_TLB_CONFIG_0 = 0x30000030; + MC_SMMU_PTC_CONFIG_0 = 0x2800003F; + (void)MC_SMMU_TLB_CONFIG_0; + MC_SMMU_PTC_FLUSH_0 = 0; + (void)MC_SMMU_TLB_CONFIG_0; + MC_SMMU_TLB_FLUSH_0 = 0; + (void)MC_SMMU_TLB_CONFIG_0; + MC_SMMU_CONFIG_0 = 1; /* enable SMMU */ + (void)MC_SMMU_TLB_CONFIG_0; /* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */ uint32_t reset_vec; @@ -206,6 +208,7 @@ void setup_4x_mmio(void) { MAKE_MC_REG(0x660) = 0; MAKE_MC_REG(0x964) |= 1; CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 &= 0xFFF7FFFF; + /* TODO: What are these PMC scratch writes? */ APBDEV_PMC_SECURE_SCRATCH51_0 = (APBDEV_PMC_SECURE_SCRATCH51_0 & 0xFFFF8000) | 0x4000; APBDEV_PMC_SECURE_SCRATCH16_0 &= 0x3FFFFFFF; @@ -221,6 +224,7 @@ void setup_4x_mmio(void) { APBDEV_PMC_SECURE_SCRATCH102_0 = 0x0; APBDEV_PMC_SECURE_SCRATCH103_0 = 0x0; APBDEV_PMC_SECURE_SCRATCH39_0 = (APBDEV_PMC_SECURE_SCRATCH39_0 & 0xF8000000) | 0x88; + /* TODO: Do we want to bother locking the secure scratch registers? */ /* 4.x Jamais Vu mitigations. */ /* Overwrite exception vectors. */ @@ -232,23 +236,27 @@ void setup_4x_mmio(void) { BPMP_VECTOR_UNK = BPMP_MITIGATION_RESET_VAL; BPMP_VECTOR_IRQ = BPMP_MITIGATION_RESET_VAL; BPMP_VECTOR_FIQ = BPMP_MITIGATION_RESET_VAL; + /* Disable AHB arbitration for the BPMP. */ AHB_ARBITRATION_DISABLE_0 |= 2; + /* Set SMMU for BPMP/APB-DMA to point to TZRAM. */ MC_SMMU_PTB_ASID_0 = 1; - (void)(MAKE_MC_REG(0x014)); + (void)MC_SMMU_TLB_CONFIG_0; MC_SMMU_PTB_DATA_0 = 0x70012; MC_SMMU_AVPC_ASID_0 = 0x80000001; MC_SMMU_PPCS1_ASID_0 = 0x80000001; - (void)(MAKE_MC_REG(0x014)); - MAKE_MC_REG(0x34) = 0; - (void)(MAKE_MC_REG(0x014)); - MAKE_MC_REG(0x30) = 0; - (void)(MAKE_MC_REG(0x014)); + (void)MC_SMMU_TLB_CONFIG_0; + MC_SMMU_PTC_FLUSH_0 = 0; + (void)MC_SMMU_TLB_CONFIG_0; + MC_SMMU_TLB_FLUSH_0 = 0; + (void)MC_SMMU_TLB_CONFIG_0; + /* Wait for the BPMP to halt. */ while ((FLOW_CTLR_HALT_COP_EVENTS_0 >> 29) != 2) { wait(1); } + /* If not in a debugging context, setup the activity monitor. */ if ((get_debug_authentication_status() & 3) != 3) { FLOW_CTLR_HALT_COP_EVENTS_0 = 0x40000000; diff --git a/exosphere/src/mc.h b/exosphere/src/mc.h index de5141700..2e071e257 100644 --- a/exosphere/src/mc.h +++ b/exosphere/src/mc.h @@ -14,9 +14,22 @@ static inline uintptr_t get_mc_base(void) { #define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) -#define MC_SMMU_PTB_ASID_0 MAKE_MC_REG(0x01C) -#define MC_SMMU_PTB_DATA_0 MAKE_MC_REG(0x020) -#define MC_SMMU_AVPC_ASID_0 MAKE_MC_REG(0x23C) +#define MC_SMMU_CONFIG_0 MAKE_MC_REG(0x010) +#define MC_SMMU_TLB_CONFIG_0 MAKE_MC_REG(0x014) +#define MC_SMMU_PTC_CONFIG_0 MAKE_MC_REG(0x018) +#define MC_SMMU_PTB_ASID_0 MAKE_MC_REG(0x01C) +#define MC_SMMU_PTB_DATA_0 MAKE_MC_REG(0x020) +#define MC_SMMU_TLB_FLUSH_0 MAKE_MC_REG(0x030) +#define MC_SMMU_PTC_FLUSH_0 MAKE_MC_REG(0x034) +#define MC_SMMU_AFI_ASID_0 MAKE_MC_REG(0x238) +#define MC_SMMU_AVPC_ASID_0 MAKE_MC_REG(0x23C) + +#define MC_SMMU_TRANSLATION_ENABLE_0_0 MAKE_MC_REG(0x228) +#define MC_SMMU_TRANSLATION_ENABLE_1_0 MAKE_MC_REG(0x22C) +#define MC_SMMU_TRANSLATION_ENABLE_2_0 MAKE_MC_REG(0x230) +#define MC_SMMU_TRANSLATION_ENABLE_3_0 MAKE_MC_REG(0x234) +#define MC_SMMU_TRANSLATION_ENABLE_4_0 MAKE_MC_REG(0xB98) + #define MC_SMMU_PPCS1_ASID_0 MAKE_MC_REG(0x298) #define MC_SECURITY_CFG0_0 MAKE_MC_REG(0x070) From 2f8edfa8e2e2cc7dd9edd89876027aaf32e59f89 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Wed, 5 Sep 2018 20:51:03 +0100 Subject: [PATCH 072/489] fusee: Minor bugfixes. --- fusee/fusee-primary/src/di.c | 18 ++++++------------ fusee/fusee-primary/src/flow.h | 2 +- fusee/fusee-primary/src/hwinit.c | 2 +- fusee/fusee-primary/src/max7762x.c | 2 +- fusee/fusee-primary/src/mc.c | 2 +- fusee/fusee-primary/src/timers.h | 11 ++++++----- fusee/fusee-secondary/src/cluster.c | 2 +- fusee/fusee-secondary/src/di.c | 18 ++++++------------ fusee/fusee-secondary/src/flow.h | 2 +- fusee/fusee-secondary/src/max7762x.c | 2 +- fusee/fusee-secondary/src/mc.c | 2 +- fusee/fusee-secondary/src/nxboot.c | 9 +++------ fusee/fusee-secondary/src/nxboot.h | 9 +++++---- fusee/fusee-secondary/src/timers.h | 11 ++++++----- 14 files changed, 40 insertions(+), 52 deletions(-) diff --git a/fusee/fusee-primary/src/di.c b/fusee/fusee-primary/src/di.c index f46310eb8..f3d00656b 100644 --- a/fusee/fusee-primary/src/di.c +++ b/fusee/fusee-primary/src/di.c @@ -70,7 +70,7 @@ void display_init() /* Enable Backlight +5V. */ gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_HIGH); - udelay(10000u); + udelay(10000); /* Enable Backlight -5V. */ gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_HIGH); @@ -165,12 +165,7 @@ void display_end() MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 1; MAKE_DSI_REG(DSI_WR_DATA) = 0x2805; - uint32_t host1x_delay = MAKE_HOST1X_REG(0x30A4) + 5; - while (MAKE_HOST1X_REG(0x30A4) < host1x_delay) { - /* Wait. */ - } - - MAKE_DI_REG(DC_CMD_STATE_ACCESS) = 5; + MAKE_DI_REG(DC_CMD_STATE_ACCESS) = (READ_MUX | WRITE_MUX); MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 0; exec_cfg((uint32_t *)DI_BASE, _display_config_12, 17); @@ -182,7 +177,7 @@ void display_end() exec_cfg((uint32_t *)DSI_BASE, _display_config_14, 22); MAKE_DSI_REG(DSI_WR_DATA) = 0x1005; - MAKE_DSI_REG(DSI_TRIGGER) = 2; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; udelay(50000); @@ -207,7 +202,7 @@ void display_end() car->rst_dev_l_set = 0x18000000; car->clk_enb_l_clr = 0x18000000; - MAKE_DSI_REG(DSI_PAD_CONTROL_0) = 0x10F010F; + MAKE_DSI_REG(DSI_PAD_CONTROL_0) = (DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF)); MAKE_DSI_REG(DSI_POWER_CONTROL) = 0; /* Backlight PWM. */ @@ -236,17 +231,16 @@ void display_color_screen(uint32_t color) uint32_t *display_init_framebuffer(void *address) { static cfg_op_t conf[sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t)] = {0}; - if(conf[0].val == 0) { + if (conf[0].val == 0) { for (uint32_t i = 0; i < sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t); i++) { conf[i] = cfg_display_framebuffer[i]; } } uint32_t *lfb_addr = (uint32_t *)address; - conf[19].val = (uint32_t)address; - //This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). + /* This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). */ exec_cfg((uint32_t *)DI_BASE, conf, 32); udelay(35000); diff --git a/fusee/fusee-primary/src/flow.h b/fusee/fusee-primary/src/flow.h index b3128d55e..13f527cac 100644 --- a/fusee/fusee-primary/src/flow.h +++ b/fusee/fusee-primary/src/flow.h @@ -4,7 +4,7 @@ #include <stdint.h> #define FLOW_CTLR_BASE 0x60007000 -#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_CTLR_BASE + ofs) +#define MAKE_FLOW_REG(n) MAKE_REG32(FLOW_CTLR_BASE + n) #define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) #define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040) diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index 929136d38..b8ed277f2 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -24,7 +24,7 @@ void config_oscillators() car->spare_reg0 = ((car->spare_reg0 & 0xFFFFFFF3) | 4); SYSCTR0_CNTFID0_0 = 19200000; - MAKE_TIMERS_REG(0x14) = 0x45F; + TIMERUS_USEC_CFG_0 = 0x45F; car->osc_ctrl = 0x50000071; pmc->osc_edpd_over = ((pmc->osc_edpd_over & 0xFFFFFF81) | 0xE); diff --git a/fusee/fusee-primary/src/max7762x.c b/fusee/fusee-primary/src/max7762x.c index da20eb7b9..136cbfeca 100644 --- a/fusee/fusee-primary/src/max7762x.c +++ b/fusee/fusee-primary/src/max7762x.c @@ -60,7 +60,7 @@ int max77620_regulator_get_status(uint32_t id) } if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1)) - return (val & 8) ? 0 : 1; + return (val & 8) ? 1 : 0; return 0; } diff --git a/fusee/fusee-primary/src/mc.c b/fusee/fusee-primary/src/mc.c index a98b6fbf7..137bea969 100644 --- a/fusee/fusee-primary/src/mc.c +++ b/fusee/fusee-primary/src/mc.c @@ -20,7 +20,7 @@ void mc_config_carveout() MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0; MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1; - mc_config_tsec_carveout(0, 0, 1); + mc_config_tsec_carveout(0, 0, true); MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = 0; MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; diff --git a/fusee/fusee-primary/src/timers.h b/fusee/fusee-primary/src/timers.h index 8c9569c19..39bf9413e 100644 --- a/fusee/fusee-primary/src/timers.h +++ b/fusee/fusee-primary/src/timers.h @@ -5,13 +5,14 @@ #define TIMERS_BASE 0x60005000 #define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) -#define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10) +#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) +#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14) #define RTC_BASE 0x7000E000 #define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) -#define RTC_SECONDS MAKE_REG32(RTC_BASE + 0x08) -#define RTC_SHADOW_SECONDS MAKE_REG32(RTC_BASE + 0x0C) -#define RTC_MILLI_SECONDS MAKE_REG32(RTC_BASE + 0x10) +#define RTC_SECONDS MAKE_RTC_REG(0x08) +#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C) +#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10) typedef struct { uint32_t CONFIG; @@ -22,7 +23,7 @@ typedef struct { #define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) #define WDT_REBOOT_PATTERN 0xC45A -#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8*n) +#define GET_WDT_REBOOT_CFG_REG(n) MAKE_TIMERS_REG(0x60 + 0x8 * n) void wait(uint32_t microseconds); diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c index 12eebeb8b..4c9e0dde1 100644 --- a/fusee/fusee-secondary/src/cluster.c +++ b/fusee/fusee-secondary/src/cluster.c @@ -110,7 +110,7 @@ void cluster_boot_cpu0(uint32_t entry) /* Request and wait for RAM repair. */ FLOW_CTLR_RAM_REPAIR_0 = 1; - while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)){ + while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)) { /* Wait. */ } diff --git a/fusee/fusee-secondary/src/di.c b/fusee/fusee-secondary/src/di.c index f46310eb8..f3d00656b 100644 --- a/fusee/fusee-secondary/src/di.c +++ b/fusee/fusee-secondary/src/di.c @@ -70,7 +70,7 @@ void display_init() /* Enable Backlight +5V. */ gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_HIGH); - udelay(10000u); + udelay(10000); /* Enable Backlight -5V. */ gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_HIGH); @@ -165,12 +165,7 @@ void display_end() MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 1; MAKE_DSI_REG(DSI_WR_DATA) = 0x2805; - uint32_t host1x_delay = MAKE_HOST1X_REG(0x30A4) + 5; - while (MAKE_HOST1X_REG(0x30A4) < host1x_delay) { - /* Wait. */ - } - - MAKE_DI_REG(DC_CMD_STATE_ACCESS) = 5; + MAKE_DI_REG(DC_CMD_STATE_ACCESS) = (READ_MUX | WRITE_MUX); MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 0; exec_cfg((uint32_t *)DI_BASE, _display_config_12, 17); @@ -182,7 +177,7 @@ void display_end() exec_cfg((uint32_t *)DSI_BASE, _display_config_14, 22); MAKE_DSI_REG(DSI_WR_DATA) = 0x1005; - MAKE_DSI_REG(DSI_TRIGGER) = 2; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; udelay(50000); @@ -207,7 +202,7 @@ void display_end() car->rst_dev_l_set = 0x18000000; car->clk_enb_l_clr = 0x18000000; - MAKE_DSI_REG(DSI_PAD_CONTROL_0) = 0x10F010F; + MAKE_DSI_REG(DSI_PAD_CONTROL_0) = (DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF)); MAKE_DSI_REG(DSI_POWER_CONTROL) = 0; /* Backlight PWM. */ @@ -236,17 +231,16 @@ void display_color_screen(uint32_t color) uint32_t *display_init_framebuffer(void *address) { static cfg_op_t conf[sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t)] = {0}; - if(conf[0].val == 0) { + if (conf[0].val == 0) { for (uint32_t i = 0; i < sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t); i++) { conf[i] = cfg_display_framebuffer[i]; } } uint32_t *lfb_addr = (uint32_t *)address; - conf[19].val = (uint32_t)address; - //This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). + /* This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). */ exec_cfg((uint32_t *)DI_BASE, conf, 32); udelay(35000); diff --git a/fusee/fusee-secondary/src/flow.h b/fusee/fusee-secondary/src/flow.h index b3128d55e..13f527cac 100644 --- a/fusee/fusee-secondary/src/flow.h +++ b/fusee/fusee-secondary/src/flow.h @@ -4,7 +4,7 @@ #include <stdint.h> #define FLOW_CTLR_BASE 0x60007000 -#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_CTLR_BASE + ofs) +#define MAKE_FLOW_REG(n) MAKE_REG32(FLOW_CTLR_BASE + n) #define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) #define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040) diff --git a/fusee/fusee-secondary/src/max7762x.c b/fusee/fusee-secondary/src/max7762x.c index da20eb7b9..136cbfeca 100644 --- a/fusee/fusee-secondary/src/max7762x.c +++ b/fusee/fusee-secondary/src/max7762x.c @@ -60,7 +60,7 @@ int max77620_regulator_get_status(uint32_t id) } if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1)) - return (val & 8) ? 0 : 1; + return (val & 8) ? 1 : 0; return 0; } diff --git a/fusee/fusee-secondary/src/mc.c b/fusee/fusee-secondary/src/mc.c index a98b6fbf7..137bea969 100644 --- a/fusee/fusee-secondary/src/mc.c +++ b/fusee/fusee-secondary/src/mc.c @@ -20,7 +20,7 @@ void mc_config_carveout() MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0; MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1; - mc_config_tsec_carveout(0, 0, 1); + mc_config_tsec_carveout(0, 0, true); MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = 0; MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 8a44b2f8c..e4acdd15e 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -133,7 +133,7 @@ static void nxboot_set_bootreason() { boot_reason.boot_reason_state = 0x04; /* Set in memory. */ - memcpy((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON, &boot_reason, sizeof(boot_reason)); + memcpy((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE, &boot_reason, sizeof(boot_reason)); /* Clean up. */ free(bct); @@ -335,7 +335,7 @@ void nxboot_main(void) { printf(u8"[NXBOOT]: Reading Exosphère...\n"); /* Select the right address for Exosphère. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware <= EXOSPHERE_TARGET_FIRMWARE_400) { + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { exosphere_memaddr = (void *)0x4002D000; } else { exosphere_memaddr = (void *)0x4002B000; @@ -415,7 +415,7 @@ void nxboot_main(void) { if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X; + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; } printf("[NXBOOT]: Powering on the CCPLEX...\n"); @@ -426,9 +426,6 @@ void nxboot_main(void) { /* Unmount everything. */ nxfs_unmount_all(); - /* Turn off the backlight. */ - display_backlight(false); - /* Terminate the display. */ display_end(); diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 5f24266d3..540f56023 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -3,11 +3,12 @@ #include "utils.h" -#define MAILBOX_NX_BOOTLOADER_BASE ((void *)(0x40002000)) +#define MAILBOX_NX_BOOTLOADER_BASE 0x40002000 +#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) +#define MAKE_MAILBOX_NX_BOOTLOADER_REG(n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + n) -#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) -#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8) -#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFC) +#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xEF8) +#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xEFC) #define NX_BOOTLOADER_STATE_INIT 0 #define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1 diff --git a/fusee/fusee-secondary/src/timers.h b/fusee/fusee-secondary/src/timers.h index 8c9569c19..39bf9413e 100644 --- a/fusee/fusee-secondary/src/timers.h +++ b/fusee/fusee-secondary/src/timers.h @@ -5,13 +5,14 @@ #define TIMERS_BASE 0x60005000 #define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) -#define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10) +#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) +#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14) #define RTC_BASE 0x7000E000 #define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) -#define RTC_SECONDS MAKE_REG32(RTC_BASE + 0x08) -#define RTC_SHADOW_SECONDS MAKE_REG32(RTC_BASE + 0x0C) -#define RTC_MILLI_SECONDS MAKE_REG32(RTC_BASE + 0x10) +#define RTC_SECONDS MAKE_RTC_REG(0x08) +#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C) +#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10) typedef struct { uint32_t CONFIG; @@ -22,7 +23,7 @@ typedef struct { #define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) #define WDT_REBOOT_PATTERN 0xC45A -#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8*n) +#define GET_WDT_REBOOT_CFG_REG(n) MAKE_TIMERS_REG(0x60 + 0x8 * n) void wait(uint32_t microseconds); From bb0f3ac024211ff995aba24d46a83f05b1a37372 Mon Sep 17 00:00:00 2001 From: SciresM <Sciresm@gmail.com> Date: Thu, 6 Sep 2018 11:57:57 +0900 Subject: [PATCH 073/489] loader: Add support for 6.0.0. --- stratosphere/loader/source/ldr_process_creation.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 07cd225a6..05fda928a 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -8,6 +8,15 @@ #include "ldr_npdm.hpp" #include "ldr_nso.hpp" +extern "C" { + + bool __attribute__((weak)) kernelAbove600(void) { + u64 tmp; + return (svcGetInfo(&tmp, 21, INVALID_HANDLE, 0) != 0xF001); + } + +} + Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle reslimit_h, u64 arg_flags, ProcessInfo *out_proc_info) { /* Initialize a ProcessInfo using an npdm. */ *out_proc_info = (const ProcessCreation::ProcessInfo){0}; @@ -48,7 +57,7 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle if ((out_proc_info->process_flags & 6) == 0) { return 0x809; } - if ((application_type & 3) != 1) { + if (!(((application_type & 3) == 1) || (kernelAbove600() && (application_type & 3) == 2))) { return 0x809; } if (npdm->header->system_resource_size > 0x1FE00000) { From 28e4d4411d0ff333932ee0bf1ea39eba66071513 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 7 Sep 2018 16:00:13 +0100 Subject: [PATCH 074/489] Add and fix copyright notices for better GPL compliance (thanks @naehrwert and @CTCaer). --- exosphere/bpmpfw/src/emc.c | 16 ++++++++++++++ exosphere/bpmpfw/src/emc.h | 16 ++++++++++++++ exosphere/bpmpfw/src/i2c.c | 16 ++++++++++++++ exosphere/bpmpfw/src/i2c.h | 16 ++++++++++++++ exosphere/bpmpfw/src/lp0.c | 16 ++++++++++++++ exosphere/bpmpfw/src/lp0.h | 16 ++++++++++++++ exosphere/bpmpfw/src/pmc.h | 16 ++++++++++++++ exosphere/bpmpfw/src/start.s | 16 ++++++++++++++ exosphere/bpmpfw/src/timer.h | 16 ++++++++++++++ exosphere/bpmpfw/src/utils.h | 16 ++++++++++++++ exosphere/src/actmon.c | 16 ++++++++++++++ exosphere/src/actmon.h | 16 ++++++++++++++ exosphere/src/arm.h | 16 ++++++++++++++ exosphere/src/arm.s | 16 ++++++++++++++ exosphere/src/bootconfig.c | 16 ++++++++++++++ exosphere/src/bootconfig.h | 16 ++++++++++++++ exosphere/src/bootup.c | 16 ++++++++++++++ exosphere/src/bootup.h | 16 ++++++++++++++ exosphere/src/bpmp.h | 16 ++++++++++++++ exosphere/src/car.c | 16 ++++++++++++++ exosphere/src/car.h | 16 ++++++++++++++ exosphere/src/coldboot_init.c | 16 ++++++++++++++ exosphere/src/coldboot_main.c | 16 ++++++++++++++ exosphere/src/configitem.c | 16 ++++++++++++++ exosphere/src/configitem.h | 16 ++++++++++++++ exosphere/src/cpu_context.c | 16 ++++++++++++++ exosphere/src/cpu_context.h | 16 ++++++++++++++ exosphere/src/dbg/fmt.h | 16 ++++++++++++++ exosphere/src/dbg/log.c | 16 ++++++++++++++ exosphere/src/dbg/log_device_null.c | 16 ++++++++++++++ exosphere/src/dbg/log_device_null.h | 16 ++++++++++++++ exosphere/src/dbg/log_device_uart.c | 16 ++++++++++++++ exosphere/src/dbg/log_device_uart.h | 16 ++++++++++++++ exosphere/src/exocfg.c | 16 ++++++++++++++ exosphere/src/exocfg.h | 16 ++++++++++++++ exosphere/src/flow.h | 16 ++++++++++++++ exosphere/src/fuse.c | 16 ++++++++++++++ exosphere/src/fuse.h | 16 ++++++++++++++ exosphere/src/gcm.c | 16 ++++++++++++++ exosphere/src/gcm.h | 16 ++++++++++++++ exosphere/src/i2c.c | 16 ++++++++++++++ exosphere/src/i2c.h | 16 ++++++++++++++ exosphere/src/interrupt.c | 16 ++++++++++++++ exosphere/src/interrupt.h | 16 ++++++++++++++ exosphere/src/lp0.c | 16 ++++++++++++++ exosphere/src/lp0.h | 16 ++++++++++++++ exosphere/src/masterkey.c | 16 ++++++++++++++ exosphere/src/masterkey.h | 16 ++++++++++++++ exosphere/src/mc.c | 16 ++++++++++++++ exosphere/src/mc.h | 16 ++++++++++++++ exosphere/src/memory_map.h | 16 ++++++++++++++ exosphere/src/misc.h | 16 ++++++++++++++ exosphere/src/mmu.h | 16 ++++++++++++++ exosphere/src/package2.c | 16 ++++++++++++++ exosphere/src/package2.h | 16 ++++++++++++++ exosphere/src/panic_color.h | 16 ++++++++++++++ exosphere/src/pmc.h | 16 ++++++++++++++ exosphere/src/randomcache.c | 16 ++++++++++++++ exosphere/src/randomcache.h | 16 ++++++++++++++ exosphere/src/se.c | 16 ++++++++++++++ exosphere/src/se.h | 16 ++++++++++++++ exosphere/src/sealedkeys.c | 16 ++++++++++++++ exosphere/src/sealedkeys.h | 16 ++++++++++++++ exosphere/src/smc_api.c | 16 ++++++++++++++ exosphere/src/smc_api.h | 16 ++++++++++++++ exosphere/src/smc_user.c | 16 ++++++++++++++ exosphere/src/smc_user.h | 16 ++++++++++++++ exosphere/src/start.s | 16 ++++++++++++++ exosphere/src/synchronization.h | 16 ++++++++++++++ exosphere/src/sysctr0.h | 16 ++++++++++++++ exosphere/src/sysreg.h | 16 ++++++++++++++ exosphere/src/timers.c | 16 ++++++++++++++ exosphere/src/timers.h | 16 ++++++++++++++ exosphere/src/titlekey.c | 16 ++++++++++++++ exosphere/src/titlekey.h | 16 ++++++++++++++ exosphere/src/uart.c | 19 ++++++++++++++-- exosphere/src/uart.h | 18 ++++++++++++++- exosphere/src/userpage.c | 16 ++++++++++++++ exosphere/src/userpage.h | 16 ++++++++++++++ exosphere/src/utils.c | 16 ++++++++++++++ exosphere/src/utils.h | 16 ++++++++++++++ exosphere/src/version.h | 16 ++++++++++++++ exosphere/src/warmboot_init.c | 16 ++++++++++++++ exosphere/src/warmboot_main.c | 16 ++++++++++++++ fusee/fusee-primary/src/apb_misc.h | 16 ++++++++++++++ fusee/fusee-primary/src/btn.c | 18 +++++++++++++++ fusee/fusee-primary/src/btn.h | 18 +++++++++++++++ fusee/fusee-primary/src/car.c | 16 ++++++++++++++ fusee/fusee-primary/src/car.h | 16 ++++++++++++++ fusee/fusee-primary/src/chainloader.c | 16 ++++++++++++++ fusee/fusee-primary/src/chainloader.h | 16 ++++++++++++++ fusee/fusee-primary/src/di.c | 18 +++++++++++++++ fusee/fusee-primary/src/di.h | 18 +++++++++++++++ fusee/fusee-primary/src/di.inl | 17 ++++++++++++++ fusee/fusee-primary/src/emc.h | 22 +++++++++++++++++++ fusee/fusee-primary/src/exception_handlers.c | 16 ++++++++++++++ fusee/fusee-primary/src/exception_handlers.h | 16 ++++++++++++++ .../src/exception_handlers_asm.s | 16 ++++++++++++++ fusee/fusee-primary/src/flow.h | 16 ++++++++++++++ fusee/fusee-primary/src/fs_utils.c | 16 ++++++++++++++ fusee/fusee-primary/src/fs_utils.h | 16 ++++++++++++++ fusee/fusee-primary/src/fuse.c | 16 ++++++++++++++ fusee/fusee-primary/src/fuse.h | 16 ++++++++++++++ fusee/fusee-primary/src/gpio.c | 16 ++++++++++++++ fusee/fusee-primary/src/gpio.h | 16 ++++++++++++++ fusee/fusee-primary/src/hwinit.c | 18 +++++++++++++++ fusee/fusee-primary/src/hwinit.h | 18 +++++++++++++++ fusee/fusee-primary/src/i2c.c | 16 ++++++++++++++ fusee/fusee-primary/src/i2c.h | 16 ++++++++++++++ fusee/fusee-primary/src/init.c | 16 ++++++++++++++ fusee/fusee-primary/src/lib/driver_utils.h | 16 ++++++++++++++ fusee/fusee-primary/src/lib/printk.c | 16 ++++++++++++-- fusee/fusee-primary/src/lib/printk.h | 16 ++++++++++++++ fusee/fusee-primary/src/main.c | 16 ++++++++++++++ fusee/fusee-primary/src/max77620.h | 1 + fusee/fusee-primary/src/max7762x.c | 17 ++++++++++++++ fusee/fusee-primary/src/max7762x.h | 17 ++++++++++++++ fusee/fusee-primary/src/mc.c | 17 ++++++++++++++ fusee/fusee-primary/src/mc.h | 18 +++++++++++++++ fusee/fusee-primary/src/panic.c | 16 ++++++++++++++ fusee/fusee-primary/src/panic.h | 16 ++++++++++++++ fusee/fusee-primary/src/panic_color.h | 16 ++++++++++++++ fusee/fusee-primary/src/pinmux.h | 16 ++++++++++++++ fusee/fusee-primary/src/pmc.h | 16 ++++++++++++++ fusee/fusee-primary/src/sdmmc/mmc.h | 1 + fusee/fusee-primary/src/sdmmc/sd.h | 2 ++ fusee/fusee-primary/src/sdmmc/sdmmc.c | 18 +++++++++++++++ fusee/fusee-primary/src/sdmmc/sdmmc.h | 18 +++++++++++++++ fusee/fusee-primary/src/sdmmc/sdmmc_core.c | 18 +++++++++++++++ fusee/fusee-primary/src/sdmmc/sdmmc_core.h | 18 +++++++++++++++ fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h | 18 +++++++++++++++ fusee/fusee-primary/src/sdram.c | 17 ++++++++++++++ fusee/fusee-primary/src/sdram.h | 17 ++++++++++++++ fusee/fusee-primary/src/sdram.inl | 16 ++++++++++++++ fusee/fusee-primary/src/sdram_lp0.c | 16 ++++++++++++++ fusee/fusee-primary/src/sdram_lz.inl | 16 ++++++++++++++ .../fusee-primary/src/sdram_param_t210_lp0.h | 2 +- fusee/fusee-primary/src/se.c | 16 ++++++++++++++ fusee/fusee-primary/src/se.h | 16 ++++++++++++++ fusee/fusee-primary/src/stage2.c | 16 ++++++++++++++ fusee/fusee-primary/src/stage2.h | 16 ++++++++++++++ fusee/fusee-primary/src/start.s | 16 ++++++++++++++ fusee/fusee-primary/src/sysctr0.h | 16 ++++++++++++++ fusee/fusee-primary/src/sysreg.h | 16 ++++++++++++++ fusee/fusee-primary/src/timers.h | 16 ++++++++++++++ fusee/fusee-primary/src/uart.c | 17 ++++++++++++++ fusee/fusee-primary/src/uart.h | 17 ++++++++++++++ fusee/fusee-primary/src/utils.c | 16 ++++++++++++++ fusee/fusee-primary/src/utils.h | 16 ++++++++++++++ fusee/fusee-secondary/src/apb_misc.h | 16 ++++++++++++++ fusee/fusee-secondary/src/btn.c | 18 +++++++++++++++ fusee/fusee-secondary/src/btn.h | 18 +++++++++++++++ fusee/fusee-secondary/src/car.c | 16 ++++++++++++++ fusee/fusee-secondary/src/car.h | 16 ++++++++++++++ fusee/fusee-secondary/src/chainloader.c | 16 ++++++++++++++ fusee/fusee-secondary/src/chainloader.h | 16 ++++++++++++++ fusee/fusee-secondary/src/cluster.c | 17 ++++++++++++++ fusee/fusee-secondary/src/cluster.h | 17 ++++++++++++++ fusee/fusee-secondary/src/console.c | 16 ++++++++++++++ fusee/fusee-secondary/src/console.h | 16 ++++++++++++++ fusee/fusee-secondary/src/device_partition.c | 16 ++++++++++++++ fusee/fusee-secondary/src/device_partition.h | 16 ++++++++++++++ fusee/fusee-secondary/src/di.c | 18 +++++++++++++++ fusee/fusee-secondary/src/di.h | 18 +++++++++++++++ fusee/fusee-secondary/src/di.inl | 17 ++++++++++++++ .../fusee-secondary/src/exception_handlers.c | 16 ++++++++++++++ .../fusee-secondary/src/exception_handlers.h | 16 ++++++++++++++ .../src/exception_handlers_asm.s | 16 ++++++++++++++ fusee/fusee-secondary/src/exocfg.h | 16 ++++++++++++++ fusee/fusee-secondary/src/flow.h | 16 ++++++++++++++ fusee/fusee-secondary/src/fs_dev.c | 16 ++++++++++++++ fusee/fusee-secondary/src/fs_dev.h | 16 ++++++++++++++ fusee/fusee-secondary/src/fs_utils.c | 16 ++++++++++++++ fusee/fusee-secondary/src/fs_utils.h | 16 ++++++++++++++ fusee/fusee-secondary/src/fuse.c | 16 ++++++++++++++ fusee/fusee-secondary/src/fuse.h | 16 ++++++++++++++ fusee/fusee-secondary/src/gpio.c | 16 ++++++++++++++ fusee/fusee-secondary/src/gpio.h | 16 ++++++++++++++ fusee/fusee-secondary/src/gpt.c | 16 ++++++++++++++ fusee/fusee-secondary/src/gpt.h | 16 ++++++++++++++ fusee/fusee-secondary/src/i2c.c | 16 ++++++++++++++ fusee/fusee-secondary/src/i2c.h | 16 ++++++++++++++ fusee/fusee-secondary/src/init.c | 16 ++++++++++++++ fusee/fusee-secondary/src/kernel_patches.c | 16 ++++++++++++++ fusee/fusee-secondary/src/kernel_patches.h | 16 ++++++++++++++ fusee/fusee-secondary/src/key_derivation.c | 16 ++++++++++++++ fusee/fusee-secondary/src/key_derivation.h | 16 ++++++++++++++ fusee/fusee-secondary/src/kip.h | 16 ++++++++++++++ fusee/fusee-secondary/src/lib/driver_utils.h | 16 ++++++++++++++ fusee/fusee-secondary/src/loader.c | 16 ++++++++++++++ fusee/fusee-secondary/src/loader.h | 16 ++++++++++++++ fusee/fusee-secondary/src/main.c | 16 ++++++++++++++ fusee/fusee-secondary/src/masterkey.c | 16 ++++++++++++++ fusee/fusee-secondary/src/masterkey.h | 16 ++++++++++++++ fusee/fusee-secondary/src/max77620.h | 1 + fusee/fusee-secondary/src/max7762x.c | 17 ++++++++++++++ fusee/fusee-secondary/src/max7762x.h | 17 ++++++++++++++ fusee/fusee-secondary/src/mc.c | 17 ++++++++++++++ fusee/fusee-secondary/src/mc.h | 18 +++++++++++++++ fusee/fusee-secondary/src/nxboot.c | 16 ++++++++++++++ fusee/fusee-secondary/src/nxboot.h | 16 ++++++++++++++ fusee/fusee-secondary/src/nxfs.c | 16 ++++++++++++++ fusee/fusee-secondary/src/nxfs.h | 16 ++++++++++++++ fusee/fusee-secondary/src/package1.c | 16 ++++++++++++++ fusee/fusee-secondary/src/package1.h | 16 ++++++++++++++ fusee/fusee-secondary/src/package2.c | 16 ++++++++++++++ fusee/fusee-secondary/src/package2.h | 16 ++++++++++++++ fusee/fusee-secondary/src/panic.c | 16 ++++++++++++++ fusee/fusee-secondary/src/panic.h | 16 ++++++++++++++ fusee/fusee-secondary/src/panic_color.h | 16 ++++++++++++++ fusee/fusee-secondary/src/pinmux.h | 16 ++++++++++++++ fusee/fusee-secondary/src/pmc.h | 16 ++++++++++++++ fusee/fusee-secondary/src/raw_dev.c | 16 ++++++++++++++ fusee/fusee-secondary/src/raw_dev.h | 16 ++++++++++++++ fusee/fusee-secondary/src/sdmmc/mmc.h | 1 + fusee/fusee-secondary/src/sdmmc/sd.h | 2 ++ fusee/fusee-secondary/src/sdmmc/sdmmc.c | 18 +++++++++++++++ fusee/fusee-secondary/src/sdmmc/sdmmc.h | 18 +++++++++++++++ fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 18 +++++++++++++++ fusee/fusee-secondary/src/sdmmc/sdmmc_core.h | 18 +++++++++++++++ fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h | 18 +++++++++++++++ fusee/fusee-secondary/src/se.c | 16 ++++++++++++++ fusee/fusee-secondary/src/se.h | 16 ++++++++++++++ fusee/fusee-secondary/src/splash_screen.c | 16 ++++++++++++++ fusee/fusee-secondary/src/splash_screen.h | 16 ++++++++++++++ .../src/splash_screen_default.c | 16 ++++++++++++++ fusee/fusee-secondary/src/stage2.h | 16 ++++++++++++++ fusee/fusee-secondary/src/start.s | 16 ++++++++++++++ fusee/fusee-secondary/src/stratosphere.c | 16 ++++++++++++++ fusee/fusee-secondary/src/stratosphere.h | 16 ++++++++++++++ fusee/fusee-secondary/src/sysreg.h | 16 ++++++++++++++ fusee/fusee-secondary/src/timers.h | 16 ++++++++++++++ fusee/fusee-secondary/src/tsec.c | 17 ++++++++++++++ fusee/fusee-secondary/src/tsec.h | 17 ++++++++++++++ fusee/fusee-secondary/src/utils.c | 16 ++++++++++++++ fusee/fusee-secondary/src/utils.h | 16 ++++++++++++++ stratosphere/boot/source/boot_main.cpp | 16 ++++++++++++++ .../creport/source/creport_code_info.cpp | 16 ++++++++++++++ .../creport/source/creport_code_info.hpp | 16 ++++++++++++++ .../creport/source/creport_crash_report.cpp | 16 ++++++++++++++ .../creport/source/creport_crash_report.hpp | 16 ++++++++++++++ .../creport/source/creport_debug_types.hpp | 16 ++++++++++++++ stratosphere/creport/source/creport_main.cpp | 16 ++++++++++++++ .../creport/source/creport_thread_info.cpp | 16 ++++++++++++++ .../creport/source/creport_thread_info.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/debug.cpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/debug.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/fs_istorage.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/fs_shim.c | 16 ++++++++++++++ .../fs_mitm/source/fsmitm_layeredrom.cpp | 16 ++++++++++++++ .../fs_mitm/source/fsmitm_layeredrom.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/fsmitm_main.cpp | 16 ++++++++++++++ .../fs_mitm/source/fsmitm_romfsbuild.cpp | 16 ++++++++++++++ .../fs_mitm/source/fsmitm_romfsbuild.hpp | 16 ++++++++++++++ .../fs_mitm/source/fsmitm_romstorage.hpp | 16 ++++++++++++++ .../fs_mitm/source/fsmitm_service.cpp | 16 ++++++++++++++ .../fs_mitm/source/fsmitm_service.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/fsmitm_utils.cpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/fsmitm_utils.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/fsmitm_worker.cpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/fsmitm_worker.hpp | 16 ++++++++++++++ .../fs_mitm/source/imitmserviceobject.hpp | 16 ++++++++++++++ .../fs_mitm/source/mitm_query_service.cpp | 16 ++++++++++++++ .../fs_mitm/source/mitm_query_service.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/mitm_server.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/mitm_session.hpp | 16 ++++++++++++++ stratosphere/fs_mitm/source/sm_mitm.c | 16 ++++++++++++++ .../libstratosphere/include/meta_tools.hpp | 16 ++++++++++++++ .../libstratosphere/include/stratosphere.hpp | 16 ++++++++++++++ .../include/stratosphere/domainowner.hpp | 16 ++++++++++++++ .../stratosphere/existingportserver.hpp | 16 ++++++++++++++ .../include/stratosphere/hossynch.hpp | 16 ++++++++++++++ .../include/stratosphere/ievent.hpp | 16 ++++++++++++++ .../include/stratosphere/ipc_templating.hpp | 16 ++++++++++++++ .../include/stratosphere/ipcsession.hpp | 16 ++++++++++++++ .../include/stratosphere/iserver.hpp | 16 ++++++++++++++ .../include/stratosphere/iserviceobject.hpp | 16 ++++++++++++++ .../include/stratosphere/isession.hpp | 16 ++++++++++++++ .../include/stratosphere/iwaitable.hpp | 16 ++++++++++++++ .../stratosphere/managedportserver.hpp | 16 ++++++++++++++ .../multithreadedwaitablemanager.hpp | 16 ++++++++++++++ .../include/stratosphere/serviceserver.hpp | 16 ++++++++++++++ .../include/stratosphere/servicesession.hpp | 16 ++++++++++++++ .../include/stratosphere/systemevent.hpp | 16 ++++++++++++++ .../include/stratosphere/waitablemanager.hpp | 16 ++++++++++++++ .../stratosphere/waitablemanagerbase.hpp | 16 ++++++++++++++ .../source/multithreadedwaitablemanager.cpp | 16 ++++++++++++++ .../source/waitablemanager.cpp | 16 ++++++++++++++ .../loader/source/ldr_content_management.cpp | 16 ++++++++++++++ .../loader/source/ldr_content_management.hpp | 16 ++++++++++++++ .../loader/source/ldr_debug_monitor.cpp | 16 ++++++++++++++ .../loader/source/ldr_debug_monitor.hpp | 16 ++++++++++++++ .../loader/source/ldr_launch_queue.cpp | 16 ++++++++++++++ .../loader/source/ldr_launch_queue.hpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_main.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_map.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_map.hpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_npdm.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_npdm.hpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_nro.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_nro.hpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_nso.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_nso.hpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_patcher.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_patcher.hpp | 16 ++++++++++++++ .../loader/source/ldr_process_creation.cpp | 16 ++++++++++++++ .../loader/source/ldr_process_creation.hpp | 16 ++++++++++++++ .../loader/source/ldr_process_manager.cpp | 16 ++++++++++++++ .../loader/source/ldr_process_manager.hpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_random.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_random.hpp | 16 ++++++++++++++ .../loader/source/ldr_registration.cpp | 16 ++++++++++++++ .../loader/source/ldr_registration.hpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_ro_service.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_ro_service.hpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_shell.cpp | 16 ++++++++++++++ stratosphere/loader/source/ldr_shell.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_boot2.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_boot2.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_boot_mode.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_boot_mode.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_debug_monitor.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_debug_monitor.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_info.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_info.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_main.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_process_track.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_process_track.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_process_wait.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_registration.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_registration.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_resource_limits.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_resource_limits.hpp | 16 ++++++++++++++ stratosphere/pm/source/pm_shell.cpp | 16 ++++++++++++++ stratosphere/pm/source/pm_shell.hpp | 16 ++++++++++++++ stratosphere/sm/source/sm_main.cpp | 16 ++++++++++++++ stratosphere/sm/source/sm_manager_service.cpp | 16 ++++++++++++++ stratosphere/sm/source/sm_manager_service.hpp | 16 ++++++++++++++ stratosphere/sm/source/sm_registration.cpp | 16 ++++++++++++++ stratosphere/sm/source/sm_registration.hpp | 16 ++++++++++++++ stratosphere/sm/source/sm_user_service.cpp | 16 ++++++++++++++ stratosphere/sm/source/sm_user_service.hpp | 16 ++++++++++++++ thermosphere/src/exceptions.c | 19 +++++++++++----- thermosphere/src/exceptions.h | 17 ++++++++++---- thermosphere/src/lib/printk.c | 19 ++++++++++++---- thermosphere/src/lib/printk.h | 17 +++++++++++++- thermosphere/src/main.c | 17 +++++++++++--- thermosphere/src/regs.h | 17 +++++++++++--- thermosphere/src/start.s | 17 ++++++++++---- 349 files changed, 5534 insertions(+), 30 deletions(-) diff --git a/exosphere/bpmpfw/src/emc.c b/exosphere/bpmpfw/src/emc.c index e8eb293cf..e77479639 100644 --- a/exosphere/bpmpfw/src/emc.c +++ b/exosphere/bpmpfw/src/emc.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "utils.h" #include "lp0.h" #include "emc.h" diff --git a/exosphere/bpmpfw/src/emc.h b/exosphere/bpmpfw/src/emc.h index d92cf7b4b..30ac6e650 100644 --- a/exosphere/bpmpfw/src/emc.h +++ b/exosphere/bpmpfw/src/emc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BPMPFW_EMC_H #define EXOSPHERE_BPMPFW_EMC_H diff --git a/exosphere/bpmpfw/src/i2c.c b/exosphere/bpmpfw/src/i2c.c index 709e78004..55225c904 100644 --- a/exosphere/bpmpfw/src/i2c.c +++ b/exosphere/bpmpfw/src/i2c.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "i2c.h" #include "timer.h" diff --git a/exosphere/bpmpfw/src/i2c.h b/exosphere/bpmpfw/src/i2c.h index f66cee1ce..b2a755adf 100644 --- a/exosphere/bpmpfw/src/i2c.h +++ b/exosphere/bpmpfw/src/i2c.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BPMPFW_I2C_H #define EXOSPHERE_BPMPFW_I2C_H diff --git a/exosphere/bpmpfw/src/lp0.c b/exosphere/bpmpfw/src/lp0.c index 3fe5586de..21de19ce6 100644 --- a/exosphere/bpmpfw/src/lp0.c +++ b/exosphere/bpmpfw/src/lp0.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "utils.h" #include "lp0.h" #include "i2c.h" diff --git a/exosphere/bpmpfw/src/lp0.h b/exosphere/bpmpfw/src/lp0.h index 81049933b..25059490f 100644 --- a/exosphere/bpmpfw/src/lp0.h +++ b/exosphere/bpmpfw/src/lp0.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BPMPFW_LP0_H #define EXOSPHERE_BPMPFW_LP0_H diff --git a/exosphere/bpmpfw/src/pmc.h b/exosphere/bpmpfw/src/pmc.h index 7af26681f..6b8120cdb 100644 --- a/exosphere/bpmpfw/src/pmc.h +++ b/exosphere/bpmpfw/src/pmc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BPMPFW_PMC_H #define EXOSPHERE_BPMPFW_PMC_H diff --git a/exosphere/bpmpfw/src/start.s b/exosphere/bpmpfw/src/start.s index c6a0ac794..a439b7d30 100644 --- a/exosphere/bpmpfw/src/start.s +++ b/exosphere/bpmpfw/src/start.s @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + .section .text.start .align 4 .global _start diff --git a/exosphere/bpmpfw/src/timer.h b/exosphere/bpmpfw/src/timer.h index c2906a3fe..62ab23cfe 100644 --- a/exosphere/bpmpfw/src/timer.h +++ b/exosphere/bpmpfw/src/timer.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BPMPFW_TIMER_H #define EXOSPHERE_BPMPFW_TIMER_H diff --git a/exosphere/bpmpfw/src/utils.h b/exosphere/bpmpfw/src/utils.h index d3eff9b4c..e0b908e28 100644 --- a/exosphere/bpmpfw/src/utils.h +++ b/exosphere/bpmpfw/src/utils.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BPMPFW_UTILS_H #define EXOSPHERE_BPMPFW_UTILS_H diff --git a/exosphere/src/actmon.c b/exosphere/src/actmon.c index bd28675b6..a6bdbecbe 100644 --- a/exosphere/src/actmon.c +++ b/exosphere/src/actmon.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "utils.h" diff --git a/exosphere/src/actmon.h b/exosphere/src/actmon.h index fdabfff5b..f9fe6832b 100644 --- a/exosphere/src/actmon.h +++ b/exosphere/src/actmon.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_ACTIVITY_MONITOR_H #define EXOSPHERE_ACTIVITY_MONITOR_H diff --git a/exosphere/src/arm.h b/exosphere/src/arm.h index 63fe6e4a3..56cdc979d 100644 --- a/exosphere/src/arm.h +++ b/exosphere/src/arm.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_ARM_H #define EXOSPHERE_ARM_H diff --git a/exosphere/src/arm.s b/exosphere/src/arm.s index b1dc29109..1a7cb9c9c 100644 --- a/exosphere/src/arm.s +++ b/exosphere/src/arm.s @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #define cpuactlr_el1 s3_1_c15_c2_0 #define cpuectlr_el1 s3_1_c15_c2_1 diff --git a/exosphere/src/bootconfig.c b/exosphere/src/bootconfig.c index afa1f7e20..5a5da0e59 100644 --- a/exosphere/src/bootconfig.c +++ b/exosphere/src/bootconfig.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stdbool.h> #include <string.h> diff --git a/exosphere/src/bootconfig.h b/exosphere/src/bootconfig.h index e2e410ade..45b38053a 100644 --- a/exosphere/src/bootconfig.h +++ b/exosphere/src/bootconfig.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BOOTCONFIG_H #define EXOSPHERE_BOOTCONFIG_H diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 5897fd581..2ea2e7077 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stdbool.h> diff --git a/exosphere/src/bootup.h b/exosphere/src/bootup.h index 2f5f0d14b..c9169e5a5 100644 --- a/exosphere/src/bootup.h +++ b/exosphere/src/bootup.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BOOTUP_H #define EXOSPHERE_BOOTUP_H diff --git a/exosphere/src/bpmp.h b/exosphere/src/bpmp.h index e7171bc91..bb4f8e95e 100644 --- a/exosphere/src/bpmp.h +++ b/exosphere/src/bpmp.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_BPMP_H #define EXOSPHERE_BPMP_H diff --git a/exosphere/src/car.c b/exosphere/src/car.c index 58aeb519d..1ddd30197 100644 --- a/exosphere/src/car.c +++ b/exosphere/src/car.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "utils.h" diff --git a/exosphere/src/car.h b/exosphere/src/car.h index 7d489d2c4..67a665dd3 100644 --- a/exosphere/src/car.h +++ b/exosphere/src/car.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_CLOCK_AND_RESET_H #define EXOSPHERE_CLOCK_AND_RESET_H diff --git a/exosphere/src/coldboot_init.c b/exosphere/src/coldboot_init.c index c88704638..aedc28277 100644 --- a/exosphere/src/coldboot_init.c +++ b/exosphere/src/coldboot_init.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "utils.h" #include "arm.h" diff --git a/exosphere/src/coldboot_main.c b/exosphere/src/coldboot_main.c index 4840dc3fc..416a018f5 100644 --- a/exosphere/src/coldboot_main.c +++ b/exosphere/src/coldboot_main.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "utils.h" #include "mmu.h" diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 7244fa692..0e40c74c6 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "bootconfig.h" diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index 8ff65af8a..bce93f6ee 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_CFG_ITEM_H #define EXOSPHERE_CFG_ITEM_H diff --git a/exosphere/src/cpu_context.c b/exosphere/src/cpu_context.c index f42ef9021..ed307dc46 100644 --- a/exosphere/src/cpu_context.c +++ b/exosphere/src/cpu_context.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <stdint.h> #include "arm.h" diff --git a/exosphere/src/cpu_context.h b/exosphere/src/cpu_context.h index 8684f8c16..e6d47b412 100644 --- a/exosphere/src/cpu_context.h +++ b/exosphere/src/cpu_context.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_CPU_CTX_H #define EXOSPHERE_CPU_CTX_H diff --git a/exosphere/src/dbg/fmt.h b/exosphere/src/dbg/fmt.h index 97391b669..ed593422e 100644 --- a/exosphere/src/dbg/fmt.h +++ b/exosphere/src/dbg/fmt.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_DBG_FMT_H #define EXOSPHERE_DBG_FMT_H diff --git a/exosphere/src/dbg/log.c b/exosphere/src/dbg/log.c index 0f33121c5..1337ff455 100644 --- a/exosphere/src/dbg/log.c +++ b/exosphere/src/dbg/log.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include <stdarg.h> #include "log.h" diff --git a/exosphere/src/dbg/log_device_null.c b/exosphere/src/dbg/log_device_null.c index 09c29fe73..41ed3aafe 100644 --- a/exosphere/src/dbg/log_device_null.c +++ b/exosphere/src/dbg/log_device_null.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "log_device_null.h" static void initialize(debug_log_device_null_t *this) { diff --git a/exosphere/src/dbg/log_device_null.h b/exosphere/src/dbg/log_device_null.h index 900316485..88b76fbb8 100644 --- a/exosphere/src/dbg/log_device_null.h +++ b/exosphere/src/dbg/log_device_null.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_DBG_LOG_DEVICE_NULL_H #define EXOSPHERE_DBG_LOG_DEVICE_NULL_H diff --git a/exosphere/src/dbg/log_device_uart.c b/exosphere/src/dbg/log_device_uart.c index 7f8d008d8..1515bbbfd 100644 --- a/exosphere/src/dbg/log_device_uart.c +++ b/exosphere/src/dbg/log_device_uart.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "log_device_uart.h" #include "../car.h" #include "../uart.h" diff --git a/exosphere/src/dbg/log_device_uart.h b/exosphere/src/dbg/log_device_uart.h index 19abc0aef..892ab553b 100644 --- a/exosphere/src/dbg/log_device_uart.h +++ b/exosphere/src/dbg/log_device_uart.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_DBG_LOG_DEVICE_UART_H #define EXOSPHERE_DBG_LOG_DEVICE_UART_H diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index 35c42a8df..82761b318 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stdbool.h> diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index f02aa24e0..786abf36b 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_EXOSPHERE_CONFIG_H #define EXOSPHERE_EXOSPHERE_CONFIG_H diff --git a/exosphere/src/flow.h b/exosphere/src/flow.h index 014b42abd..abd1dfad8 100644 --- a/exosphere/src/flow.h +++ b/exosphere/src/flow.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_FLOW_CTLR_H #define EXOSPHERE_FLOW_CTLR_H diff --git a/exosphere/src/fuse.c b/exosphere/src/fuse.c index 94654c451..3cad511ea 100644 --- a/exosphere/src/fuse.c +++ b/exosphere/src/fuse.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "car.h" diff --git a/exosphere/src/fuse.h b/exosphere/src/fuse.h index c4d1240a7..9176893df 100644 --- a/exosphere/src/fuse.h +++ b/exosphere/src/fuse.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_FUSE_H #define EXOSPHERE_FUSE_H diff --git a/exosphere/src/gcm.c b/exosphere/src/gcm.c index 7350cd5d6..5891d571d 100644 --- a/exosphere/src/gcm.c +++ b/exosphere/src/gcm.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <string.h> diff --git a/exosphere/src/gcm.h b/exosphere/src/gcm.h index bd53bc9bf..def7133bf 100644 --- a/exosphere/src/gcm.h +++ b/exosphere/src/gcm.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_GCM_H #define EXOSPHERE_GCM_H diff --git a/exosphere/src/i2c.c b/exosphere/src/i2c.c index 8dc0ee88a..b2989e7ae 100644 --- a/exosphere/src/i2c.c +++ b/exosphere/src/i2c.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "i2c.h" diff --git a/exosphere/src/i2c.h b/exosphere/src/i2c.h index 267ecd641..8ee43e0f2 100644 --- a/exosphere/src/i2c.h +++ b/exosphere/src/i2c.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_I2C_H #define EXOSPHERE_I2C_H diff --git a/exosphere/src/interrupt.c b/exosphere/src/interrupt.c index 9ab8343ff..bbf2b4261 100644 --- a/exosphere/src/interrupt.c +++ b/exosphere/src/interrupt.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stdbool.h> diff --git a/exosphere/src/interrupt.h b/exosphere/src/interrupt.h index 2968e4708..e070e6d19 100644 --- a/exosphere/src/interrupt.h +++ b/exosphere/src/interrupt.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_INTERRUPT_H #define EXOSPHERE_INTERRUPT_H diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c index 1dc0f9c64..e7de872ab 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/lp0.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stdbool.h> #include <string.h> diff --git a/exosphere/src/lp0.h b/exosphere/src/lp0.h index 5b44c804e..293789822 100644 --- a/exosphere/src/lp0.h +++ b/exosphere/src/lp0.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_LP0_H #define EXOSPHERE_LP0_H diff --git a/exosphere/src/masterkey.c b/exosphere/src/masterkey.c index 4b83da88a..d7cbaa764 100644 --- a/exosphere/src/masterkey.c +++ b/exosphere/src/masterkey.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <stdint.h> #include <string.h> diff --git a/exosphere/src/masterkey.h b/exosphere/src/masterkey.h index 5a6a523bb..8c445aaf6 100644 --- a/exosphere/src/masterkey.h +++ b/exosphere/src/masterkey.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_MASTERKEY_H #define EXOSPHERE_MASTERKEY_H diff --git a/exosphere/src/mc.c b/exosphere/src/mc.c index 4a4aed9a5..d4234e077 100644 --- a/exosphere/src/mc.c +++ b/exosphere/src/mc.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "memory_map.h" diff --git a/exosphere/src/mc.h b/exosphere/src/mc.h index 2e071e257..b399e304e 100644 --- a/exosphere/src/mc.h +++ b/exosphere/src/mc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_MC_H #define EXOSPHERE_MC_H diff --git a/exosphere/src/memory_map.h b/exosphere/src/memory_map.h index 41a4b8f6b..c40eadbab 100644 --- a/exosphere/src/memory_map.h +++ b/exosphere/src/memory_map.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_MEMORY_MAP_H #define EXOSPHERE_MEMORY_MAP_H diff --git a/exosphere/src/misc.h b/exosphere/src/misc.h index 7d667524c..1f56b5161 100644 --- a/exosphere/src/misc.h +++ b/exosphere/src/misc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_MISC_H #define EXOSPHERE_MISC_H diff --git a/exosphere/src/mmu.h b/exosphere/src/mmu.h index ed9b885bc..2b41db321 100644 --- a/exosphere/src/mmu.h +++ b/exosphere/src/mmu.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_MMU_H #define EXOSPHERE_MMU_H diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 26db12510..5d6a20add 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "utils.h" diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h index 156ab52c3..66f4494a7 100644 --- a/exosphere/src/package2.h +++ b/exosphere/src/package2.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_PACKAGE2_H #define EXOSPHERE_PACKAGE2_H diff --git a/exosphere/src/panic_color.h b/exosphere/src/panic_color.h index a310b139b..84a8a8772 100644 --- a/exosphere/src/panic_color.h +++ b/exosphere/src/panic_color.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_PANIC_COLOR_H #define EXOSPHERE_PANIC_COLOR_H diff --git a/exosphere/src/pmc.h b/exosphere/src/pmc.h index 5b274a9bc..17fd63526 100644 --- a/exosphere/src/pmc.h +++ b/exosphere/src/pmc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_PMC_H #define EXOSPHERE_PMC_H diff --git a/exosphere/src/randomcache.c b/exosphere/src/randomcache.c index 88dcbb4fc..d715782eb 100644 --- a/exosphere/src/randomcache.c +++ b/exosphere/src/randomcache.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <string.h> diff --git a/exosphere/src/randomcache.h b/exosphere/src/randomcache.h index 7d0ddc8d2..4a7b1e371 100644 --- a/exosphere/src/randomcache.h +++ b/exosphere/src/randomcache.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_RANDOM_CACHE_H #define EXOSPHERE_RANDOM_CACHE_H diff --git a/exosphere/src/se.c b/exosphere/src/se.c index fe92958c6..058a13735 100644 --- a/exosphere/src/se.c +++ b/exosphere/src/se.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "utils.h" diff --git a/exosphere/src/se.h b/exosphere/src/se.h index 5fd606a2b..326602d26 100644 --- a/exosphere/src/se.h +++ b/exosphere/src/se.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_SE_H #define EXOSPHERE_SE_H diff --git a/exosphere/src/sealedkeys.c b/exosphere/src/sealedkeys.c index 73a88bcc6..03c417d4f 100644 --- a/exosphere/src/sealedkeys.c +++ b/exosphere/src/sealedkeys.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <string.h> diff --git a/exosphere/src/sealedkeys.h b/exosphere/src/sealedkeys.h index c73f148bd..70f380527 100644 --- a/exosphere/src/sealedkeys.h +++ b/exosphere/src/sealedkeys.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_SEALED_KEYS_H #define EXOSPHERE_SEALED_KEYS_H diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index a0f96073b..ca1d49d36 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdatomic.h> #include <stdint.h> diff --git a/exosphere/src/smc_api.h b/exosphere/src/smc_api.h index 80eb5bcb3..476d2a4fe 100644 --- a/exosphere/src/smc_api.h +++ b/exosphere/src/smc_api.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_SMC_API_H #define EXOSPHERE_SMC_API_H diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c index 4f883655a..acf21ebe1 100644 --- a/exosphere/src/smc_user.c +++ b/exosphere/src/smc_user.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <stdint.h> #include <string.h> diff --git a/exosphere/src/smc_user.h b/exosphere/src/smc_user.h index a99add637..ca0adbd62 100644 --- a/exosphere/src/smc_user.h +++ b/exosphere/src/smc_user.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_SMC_USER_H #define EXOSPHERE_SMC_USER_H diff --git a/exosphere/src/start.s b/exosphere/src/start.s index 0374248da..8c89dbb70 100644 --- a/exosphere/src/start.s +++ b/exosphere/src/start.s @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + /* For some reason GAS doesn't know about it, even with .cpu cortex-a57 */ #define cpuactlr_el1 s3_1_c15_c2_0 #define cpuectlr_el1 s3_1_c15_c2_1 diff --git a/exosphere/src/synchronization.h b/exosphere/src/synchronization.h index 328186e35..10a6f21c7 100644 --- a/exosphere/src/synchronization.h +++ b/exosphere/src/synchronization.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_SYNCHRONIZATION_H #define EXOSPHERE_SYNCHRONIZATION_H diff --git a/exosphere/src/sysctr0.h b/exosphere/src/sysctr0.h index c29a956ea..fae0c1446 100644 --- a/exosphere/src/sysctr0.h +++ b/exosphere/src/sysctr0.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_SYSCTR0_H #define EXOSPHERE_SYSCTR0_H diff --git a/exosphere/src/sysreg.h b/exosphere/src/sysreg.h index 7fc362004..f8e0f7298 100644 --- a/exosphere/src/sysreg.h +++ b/exosphere/src/sysreg.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_SYSREG_H #define EXOSPHERE_SYSREG_H diff --git a/exosphere/src/timers.c b/exosphere/src/timers.c index cf16fef5f..cffc7e57b 100644 --- a/exosphere/src/timers.c +++ b/exosphere/src/timers.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stdbool.h> diff --git a/exosphere/src/timers.h b/exosphere/src/timers.h index 8c48fe6a2..6d5f9f6ae 100644 --- a/exosphere/src/timers.h +++ b/exosphere/src/timers.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_TIMERS_H #define EXOSPHERE_TIMERS_H diff --git a/exosphere/src/titlekey.c b/exosphere/src/titlekey.c index 4c46ed226..3b6d957a8 100644 --- a/exosphere/src/titlekey.c +++ b/exosphere/src/titlekey.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <string.h> diff --git a/exosphere/src/titlekey.h b/exosphere/src/titlekey.h index a74949b8b..bfcf95d44 100644 --- a/exosphere/src/titlekey.h +++ b/exosphere/src/titlekey.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_TITLEKEY_H #define EXOSPHERE_TITLEKEY_H diff --git a/exosphere/src/uart.c b/exosphere/src/uart.c index ee1379f92..ce5c6c418 100644 --- a/exosphere/src/uart.c +++ b/exosphere/src/uart.c @@ -1,9 +1,24 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "timers.h" #include "uart.h" #include "misc.h" -/* Adapted from https://github.com/nwert/hekate/blob/master/hwinit/uart.c */ - void uart_select(UartDevice dev) { unsigned int id = (unsigned int)dev; PINMUX_AUX_UARTn_TX_0(id) = 0; /* UART */ diff --git a/exosphere/src/uart.h b/exosphere/src/uart.h index e39e56948..7a46e74c8 100644 --- a/exosphere/src/uart.h +++ b/exosphere/src/uart.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_UART_H #define EXOSPHERE_UART_H @@ -5,7 +22,6 @@ #include "memory_map.h" /* Exosphere driver for the Tegra X1 UARTs. */ -/* Mostly copied from https://github.com/nwert/hekate/blob/master/hwinit/uart.h and https://github.com/nwert/hekate/blob/master/hwinit/uart.c */ static inline uintptr_t get_uart_base(void) { return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_UART); diff --git a/exosphere/src/userpage.c b/exosphere/src/userpage.c index 01ee0afe2..d026df530 100644 --- a/exosphere/src/userpage.c +++ b/exosphere/src/userpage.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "utils.h" diff --git a/exosphere/src/userpage.h b/exosphere/src/userpage.h index f14e0cd0a..7f708b0cc 100644 --- a/exosphere/src/userpage.h +++ b/exosphere/src/userpage.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_USERPAGE_H #define EXOSPHERE_USERPAGE_H diff --git a/exosphere/src/utils.c b/exosphere/src/utils.c index 2f60fbfe1..e2b421071 100644 --- a/exosphere/src/utils.c +++ b/exosphere/src/utils.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <string.h> #include "utils.h" diff --git a/exosphere/src/utils.h b/exosphere/src/utils.h index 1567c3fc5..22dd55e43 100644 --- a/exosphere/src/utils.h +++ b/exosphere/src/utils.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_UTILS_H #define EXOSPHERE_UTILS_H diff --git a/exosphere/src/version.h b/exosphere/src/version.h index a22c9027f..99200b843 100644 --- a/exosphere/src/version.h +++ b/exosphere/src/version.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef EXOSPHERE_VERSION_H #define EXOSPHERE_VERSION_H diff --git a/exosphere/src/warmboot_init.c b/exosphere/src/warmboot_init.c index 427792054..5b366aa60 100644 --- a/exosphere/src/warmboot_init.c +++ b/exosphere/src/warmboot_init.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "utils.h" #include "memory_map.h" #include "mc.h" diff --git a/exosphere/src/warmboot_main.c b/exosphere/src/warmboot_main.c index 1c9a9ad9e..95895ba80 100644 --- a/exosphere/src/warmboot_main.c +++ b/exosphere/src/warmboot_main.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "utils.h" #include "mmu.h" #include "memory_map.h" diff --git a/fusee/fusee-primary/src/apb_misc.h b/fusee/fusee-primary/src/apb_misc.h index 4552a61b5..b2e8b1dff 100644 --- a/fusee/fusee-primary/src/apb_misc.h +++ b/fusee/fusee-primary/src/apb_misc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_APB_MISC_H #define FUSEE_APB_MISC_H diff --git a/fusee/fusee-primary/src/btn.c b/fusee/fusee-primary/src/btn.c index 942d27be6..f845c350e 100644 --- a/fusee/fusee-primary/src/btn.c +++ b/fusee/fusee-primary/src/btn.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "btn.h" diff --git a/fusee/fusee-primary/src/btn.h b/fusee/fusee-primary/src/btn.h index 08f6f6921..04f569b94 100644 --- a/fusee/fusee-primary/src/btn.h +++ b/fusee/fusee-primary/src/btn.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_BTN_H_ #define FUSEE_BTN_H_ diff --git a/fusee/fusee-primary/src/car.c b/fusee/fusee-primary/src/car.c index bc79be9a6..5bf8b4331 100644 --- a/fusee/fusee-primary/src/car.c +++ b/fusee/fusee-primary/src/car.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "car.h" #include "utils.h" diff --git a/fusee/fusee-primary/src/car.h b/fusee/fusee-primary/src/car.h index 572595c90..4135a54ef 100644 --- a/fusee/fusee-primary/src/car.h +++ b/fusee/fusee-primary/src/car.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_CAR_H #define FUSEE_CAR_H diff --git a/fusee/fusee-primary/src/chainloader.c b/fusee/fusee-primary/src/chainloader.c index b4090b103..bc222604a 100644 --- a/fusee/fusee-primary/src/chainloader.c +++ b/fusee/fusee-primary/src/chainloader.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "chainloader.h" int g_chainloader_argc = 0; diff --git a/fusee/fusee-primary/src/chainloader.h b/fusee/fusee-primary/src/chainloader.h index 43fe602a2..0081530c3 100644 --- a/fusee/fusee-primary/src/chainloader.h +++ b/fusee/fusee-primary/src/chainloader.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_CHAINLOADER_H #define FUSEE_CHAINLOADER_H diff --git a/fusee/fusee-primary/src/di.c b/fusee/fusee-primary/src/di.c index f3d00656b..b6f8116c9 100644 --- a/fusee/fusee-primary/src/di.c +++ b/fusee/fusee-primary/src/di.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "di.h" diff --git a/fusee/fusee-primary/src/di.h b/fusee/fusee-primary/src/di.h index bca4b569a..4aa4f944d 100644 --- a/fusee/fusee-primary/src/di.h +++ b/fusee/fusee-primary/src/di.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_DI_H_ #define FUSEE_DI_H_ diff --git a/fusee/fusee-primary/src/di.inl b/fusee/fusee-primary/src/di.inl index c34fb4cf2..e438ca5cb 100644 --- a/fusee/fusee-primary/src/di.inl +++ b/fusee/fusee-primary/src/di.inl @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (C) 2018 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + //Clock config. static const cfg_op_t _display_config_1[4] = { {0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 diff --git a/fusee/fusee-primary/src/emc.h b/fusee/fusee-primary/src/emc.h index a032d5c97..d0bae4130 100644 --- a/fusee/fusee-primary/src/emc.h +++ b/fusee/fusee-primary/src/emc.h @@ -1,3 +1,25 @@ +/* + * arch/arm/mach-tegra/tegra21_emc.h + * + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + #ifndef FUSEE_EMC_H_ #define FUSEE_EMC_H_ diff --git a/fusee/fusee-primary/src/exception_handlers.c b/fusee/fusee-primary/src/exception_handlers.c index 0d71e9ecb..e8d34f702 100644 --- a/fusee/fusee-primary/src/exception_handlers.c +++ b/fusee/fusee-primary/src/exception_handlers.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <inttypes.h> #include "exception_handlers.h" diff --git a/fusee/fusee-primary/src/exception_handlers.h b/fusee/fusee-primary/src/exception_handlers.h index 8e79b4136..7fda29867 100644 --- a/fusee/fusee-primary/src/exception_handlers.h +++ b/fusee/fusee-primary/src/exception_handlers.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_EXCEPTION_HANDLERS_H #define FUSEE_EXCEPTION_HANDLERS_H diff --git a/fusee/fusee-primary/src/exception_handlers_asm.s b/fusee/fusee-primary/src/exception_handlers_asm.s index 3a0be6514..84b34308b 100644 --- a/fusee/fusee-primary/src/exception_handlers_asm.s +++ b/fusee/fusee-primary/src/exception_handlers_asm.s @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + .macro GEN_USUAL_HANDLER name, index, lr_arm_displ, lr_thumb_displ _exception_handler_\name: ldr sp, =_regs diff --git a/fusee/fusee-primary/src/flow.h b/fusee/fusee-primary/src/flow.h index 13f527cac..cd98d8983 100644 --- a/fusee/fusee-primary/src/flow.h +++ b/fusee/fusee-primary/src/flow.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_FLOW_CTLR_H #define FUSEE_FLOW_CTLR_H diff --git a/fusee/fusee-primary/src/fs_utils.c b/fusee/fusee-primary/src/fs_utils.c index 9146ad0c2..b81bfec6a 100644 --- a/fusee/fusee-primary/src/fs_utils.c +++ b/fusee/fusee-primary/src/fs_utils.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "fs_utils.h" #include "mc.h" #include "lib/printk.h" diff --git a/fusee/fusee-primary/src/fs_utils.h b/fusee/fusee-primary/src/fs_utils.h index 322e8b9a8..c70df83f6 100644 --- a/fusee/fusee-primary/src/fs_utils.h +++ b/fusee/fusee-primary/src/fs_utils.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_FS_UTILS_H #define FUSEE_FS_UTILS_H diff --git a/fusee/fusee-primary/src/fuse.c b/fusee/fusee-primary/src/fuse.c index 04780c9ce..cc5656cc7 100644 --- a/fusee/fusee-primary/src/fuse.c +++ b/fusee/fusee-primary/src/fuse.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <stdint.h> #include <string.h> diff --git a/fusee/fusee-primary/src/fuse.h b/fusee/fusee-primary/src/fuse.h index 63285b64f..528b0aff4 100644 --- a/fusee/fusee-primary/src/fuse.h +++ b/fusee/fusee-primary/src/fuse.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_FUSE_H #define FUSEE_FUSE_H diff --git a/fusee/fusee-primary/src/gpio.c b/fusee/fusee-primary/src/gpio.c index 529e9fb15..9cfec5c2f 100644 --- a/fusee/fusee-primary/src/gpio.c +++ b/fusee/fusee-primary/src/gpio.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include <stdint.h> #include <errno.h> diff --git a/fusee/fusee-primary/src/gpio.h b/fusee/fusee-primary/src/gpio.h index a916c989c..41781a0ca 100644 --- a/fusee/fusee-primary/src/gpio.h +++ b/fusee/fusee-primary/src/gpio.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_GPIO_H #define FUSEE_GPIO_H diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index b8ed277f2..47d5ecf27 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "hwinit.h" #include "apb_misc.h" #include "car.h" diff --git a/fusee/fusee-primary/src/hwinit.h b/fusee/fusee-primary/src/hwinit.h index da197ae83..d76512ef3 100644 --- a/fusee/fusee-primary/src/hwinit.h +++ b/fusee/fusee-primary/src/hwinit.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_HWINIT_H_ #define FUSEE_HWINIT_H_ diff --git a/fusee/fusee-primary/src/i2c.c b/fusee/fusee-primary/src/i2c.c index 028ba56e8..27063b3cd 100644 --- a/fusee/fusee-primary/src/i2c.c +++ b/fusee/fusee-primary/src/i2c.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "i2c.h" #include "utils.h" #include "timers.h" diff --git a/fusee/fusee-primary/src/i2c.h b/fusee/fusee-primary/src/i2c.h index 8b0acbd35..ec3efecc6 100644 --- a/fusee/fusee-primary/src/i2c.h +++ b/fusee/fusee-primary/src/i2c.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_I2C_H #define FUSEE_I2C_H diff --git a/fusee/fusee-primary/src/init.c b/fusee/fusee-primary/src/init.c index a121310e4..c061fc00c 100644 --- a/fusee/fusee-primary/src/init.c +++ b/fusee/fusee-primary/src/init.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stddef.h> #include <string.h> diff --git a/fusee/fusee-primary/src/lib/driver_utils.h b/fusee/fusee-primary/src/lib/driver_utils.h index b33df1686..b79611113 100644 --- a/fusee/fusee-primary/src/lib/driver_utils.h +++ b/fusee/fusee-primary/src/lib/driver_utils.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_DRIVER_UTILS_H #define FUSEE_DRIVER_UTILS_H diff --git a/fusee/fusee-primary/src/lib/printk.c b/fusee/fusee-primary/src/lib/printk.c index 33c368dee..30b36ab00 100644 --- a/fusee/fusee-primary/src/lib/printk.c +++ b/fusee/fusee-primary/src/lib/printk.c @@ -1,5 +1,17 @@ -/** - * Kernel print functions. +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "printk.h" diff --git a/fusee/fusee-primary/src/lib/printk.h b/fusee/fusee-primary/src/lib/printk.h index 9b0c3d710..4c63b9b6f 100644 --- a/fusee/fusee-primary/src/lib/printk.h +++ b/fusee/fusee-primary/src/lib/printk.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef __PRINTK_H__ #define __PRINTK_H__ diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index b1552b7cd..fca4e5f1c 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "utils.h" #include "exception_handlers.h" #include "panic.h" diff --git a/fusee/fusee-primary/src/max77620.h b/fusee/fusee-primary/src/max77620.h index ab90f2b8e..8e1e4627e 100644 --- a/fusee/fusee-primary/src/max77620.h +++ b/fusee/fusee-primary/src/max77620.h @@ -2,6 +2,7 @@ * Defining registers address and its bit definitions of MAX77620 and MAX20024 * * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/fusee/fusee-primary/src/max7762x.c b/fusee/fusee-primary/src/max7762x.c index 136cbfeca..2987917e5 100644 --- a/fusee/fusee-primary/src/max7762x.c +++ b/fusee/fusee-primary/src/max7762x.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "max7762x.h" diff --git a/fusee/fusee-primary/src/max7762x.h b/fusee/fusee-primary/src/max7762x.h index c106a27d4..8149c03f4 100644 --- a/fusee/fusee-primary/src/max7762x.h +++ b/fusee/fusee-primary/src/max7762x.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_MAX7762X_H_ #define FUSEE_MAX7762X_H_ diff --git a/fusee/fusee-primary/src/mc.c b/fusee/fusee-primary/src/mc.c index 137bea969..d89454c8f 100644 --- a/fusee/fusee-primary/src/mc.c +++ b/fusee/fusee-primary/src/mc.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "mc.h" #include "car.h" #include "timers.h" diff --git a/fusee/fusee-primary/src/mc.h b/fusee/fusee-primary/src/mc.h index e93bfc7bf..2a167299c 100644 --- a/fusee/fusee-primary/src/mc.h +++ b/fusee/fusee-primary/src/mc.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_MC_H_ #define FUSEE_MC_H_ diff --git a/fusee/fusee-primary/src/panic.c b/fusee/fusee-primary/src/panic.c index ce0b54747..d8f298470 100644 --- a/fusee/fusee-primary/src/panic.c +++ b/fusee/fusee-primary/src/panic.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "panic.h" #include "di.h" #include "pmc.h" diff --git a/fusee/fusee-primary/src/panic.h b/fusee/fusee-primary/src/panic.h index 0b29f7070..78ea67fb6 100644 --- a/fusee/fusee-primary/src/panic.h +++ b/fusee/fusee-primary/src/panic.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PANIC_H #define FUSEE_PANIC_H diff --git a/fusee/fusee-primary/src/panic_color.h b/fusee/fusee-primary/src/panic_color.h index a87cfdeb6..68b00bf19 100644 --- a/fusee/fusee-primary/src/panic_color.h +++ b/fusee/fusee-primary/src/panic_color.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PANIC_COLOR_H #define FUSEE_PANIC_COLOR_H diff --git a/fusee/fusee-primary/src/pinmux.h b/fusee/fusee-primary/src/pinmux.h index 80fc3a37c..3912143eb 100644 --- a/fusee/fusee-primary/src/pinmux.h +++ b/fusee/fusee-primary/src/pinmux.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PINMUX_H #define FUSEE_PINMUX_H diff --git a/fusee/fusee-primary/src/pmc.h b/fusee/fusee-primary/src/pmc.h index 0c851eb47..cf20474e7 100644 --- a/fusee/fusee-primary/src/pmc.h +++ b/fusee/fusee-primary/src/pmc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PMC_H #define FUSEE_PMC_H diff --git a/fusee/fusee-primary/src/sdmmc/mmc.h b/fusee/fusee-primary/src/sdmmc/mmc.h index e357d00a4..6f7126c01 100644 --- a/fusee/fusee-primary/src/sdmmc/mmc.h +++ b/fusee/fusee-primary/src/sdmmc/mmc.h @@ -2,6 +2,7 @@ * Header for MultiMediaCard (MMC) * * Copyright 2002 Hewlett-Packard Company + * Copyright (c) 2018 Atmosphère-NX * * Use consistent with the GNU GPL is permitted, * provided that this copyright notice is diff --git a/fusee/fusee-primary/src/sdmmc/sd.h b/fusee/fusee-primary/src/sdmmc/sd.h index e5707f55f..c30e8647e 100644 --- a/fusee/fusee-primary/src/sdmmc/sd.h +++ b/fusee/fusee-primary/src/sdmmc/sd.h @@ -2,6 +2,8 @@ * include/linux/mmc/sd.h * * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. + * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc.c b/fusee/fusee-primary/src/sdmmc/sdmmc.c index 365547ae9..e4a59c046 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include <stdbool.h> #include <stdint.h> diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc.h b/fusee/fusee-primary/src/sdmmc/sdmmc.h index c3a2a325b..a40fe60d1 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc.h +++ b/fusee/fusee-primary/src/sdmmc/sdmmc.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SDMMC_H #define FUSEE_SDMMC_H diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c index c30a1f837..c831493f5 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include <stdbool.h> #include <stdint.h> diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.h b/fusee/fusee-primary/src/sdmmc/sdmmc_core.h index 37dd207d1..edcd3c60f 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.h +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SDMMC_CORE_H #define FUSEE_SDMMC_CORE_H diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h b/fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h index 8fbcffb6f..3b6b4adb0 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_tegra.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SDMMC_TEGRA_H #define FUSEE_SDMMC_TEGRA_H diff --git a/fusee/fusee-primary/src/sdram.c b/fusee/fusee-primary/src/sdram.c index 135833eea..c8e5b9502 100644 --- a/fusee/fusee-primary/src/sdram.c +++ b/fusee/fusee-primary/src/sdram.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "i2c.h" #include "mc.h" #include "emc.h" diff --git a/fusee/fusee-primary/src/sdram.h b/fusee/fusee-primary/src/sdram.h index 1ccc07f0c..b63f14ba6 100644 --- a/fusee/fusee-primary/src/sdram.h +++ b/fusee/fusee-primary/src/sdram.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SDRAM_H_ #define FUSEE_SDRAM_H_ diff --git a/fusee/fusee-primary/src/sdram.inl b/fusee/fusee-primary/src/sdram.inl index 187355c4c..845ad1161 100644 --- a/fusee/fusee-primary/src/sdram.inl +++ b/fusee/fusee-primary/src/sdram.inl @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 naehrwert + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + static const uint8_t _dram_cfg_0[1896] = { 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/fusee/fusee-primary/src/sdram_lp0.c b/fusee/fusee-primary/src/sdram_lp0.c index 36bcc6bef..12864e63c 100644 --- a/fusee/fusee-primary/src/sdram_lp0.c +++ b/fusee/fusee-primary/src/sdram_lp0.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + #include "pmc.h" #include "sdram_param_t210_lp0.h" diff --git a/fusee/fusee-primary/src/sdram_lz.inl b/fusee/fusee-primary/src/sdram_lz.inl index d16470fe6..f8f46fbd4 100644 --- a/fusee/fusee-primary/src/sdram_lz.inl +++ b/fusee/fusee-primary/src/sdram_lz.inl @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 naehrwert + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + static const uint8_t _dram_cfg_lz[1262] = { 0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x2C, 0x17, 0x04, 0x09, 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, diff --git a/fusee/fusee-primary/src/sdram_param_t210_lp0.h b/fusee/fusee-primary/src/sdram_param_t210_lp0.h index 6702ea2c9..0a1d41840 100644 --- a/fusee/fusee-primary/src/sdram_param_t210_lp0.h +++ b/fusee/fusee-primary/src/sdram_param_t210_lp0.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved. * Copyright 2014 Google Inc. - * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 CTCaer * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/fusee/fusee-primary/src/se.c b/fusee/fusee-primary/src/se.c index af86980b3..b466bd80b 100644 --- a/fusee/fusee-primary/src/se.c +++ b/fusee/fusee-primary/src/se.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "utils.h" diff --git a/fusee/fusee-primary/src/se.h b/fusee/fusee-primary/src/se.h index 311567261..db692b9cf 100644 --- a/fusee/fusee-primary/src/se.h +++ b/fusee/fusee-primary/src/se.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SE_H #define FUSEE_SE_H diff --git a/fusee/fusee-primary/src/stage2.c b/fusee/fusee-primary/src/stage2.c index b3cffa3fa..c85dab3d9 100644 --- a/fusee/fusee-primary/src/stage2.c +++ b/fusee/fusee-primary/src/stage2.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "utils.h" diff --git a/fusee/fusee-primary/src/stage2.h b/fusee/fusee-primary/src/stage2.h index 7bceb7be5..72b22f6a9 100644 --- a/fusee/fusee-primary/src/stage2.h +++ b/fusee/fusee-primary/src/stage2.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_STAGE2_H #define FUSEE_STAGE2_H diff --git a/fusee/fusee-primary/src/start.s b/fusee/fusee-primary/src/start.s index d4280470f..e417cd80e 100644 --- a/fusee/fusee-primary/src/start.s +++ b/fusee/fusee-primary/src/start.s @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + .macro CLEAR_GPR_REG_ITER mov r\@, #0 .endm diff --git a/fusee/fusee-primary/src/sysctr0.h b/fusee/fusee-primary/src/sysctr0.h index d861f739b..f622e70b1 100644 --- a/fusee/fusee-primary/src/sysctr0.h +++ b/fusee/fusee-primary/src/sysctr0.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SYSCTR0_H #define FUSEE_SYSCTR0_H diff --git a/fusee/fusee-primary/src/sysreg.h b/fusee/fusee-primary/src/sysreg.h index d69cf8897..1bc1a8c43 100644 --- a/fusee/fusee-primary/src/sysreg.h +++ b/fusee/fusee-primary/src/sysreg.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SYSREG_H #define FUSEE_SYSREG_H diff --git a/fusee/fusee-primary/src/timers.h b/fusee/fusee-primary/src/timers.h index 39bf9413e..418e5928d 100644 --- a/fusee/fusee-primary/src/timers.h +++ b/fusee/fusee-primary/src/timers.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_TIMERS_H #define FUSEE_TIMERS_H diff --git a/fusee/fusee-primary/src/uart.c b/fusee/fusee-primary/src/uart.c index 3d9865983..99d3dd848 100644 --- a/fusee/fusee-primary/src/uart.c +++ b/fusee/fusee-primary/src/uart.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "uart.h" #include "timers.h" diff --git a/fusee/fusee-primary/src/uart.h b/fusee/fusee-primary/src/uart.h index 3ba2ccad2..a4402daf4 100644 --- a/fusee/fusee-primary/src/uart.h +++ b/fusee/fusee-primary/src/uart.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_UART_H #define FUSEE_UART_H diff --git a/fusee/fusee-primary/src/utils.c b/fusee/fusee-primary/src/utils.c index 6929ec0c0..4a2ec329d 100644 --- a/fusee/fusee-primary/src/utils.c +++ b/fusee/fusee-primary/src/utils.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <stdarg.h> #include "utils.h" diff --git a/fusee/fusee-primary/src/utils.h b/fusee/fusee-primary/src/utils.h index bb647f47d..7fe8e6cb8 100644 --- a/fusee/fusee-primary/src/utils.h +++ b/fusee/fusee-primary/src/utils.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_UTILS_H #define FUSEE_UTILS_H diff --git a/fusee/fusee-secondary/src/apb_misc.h b/fusee/fusee-secondary/src/apb_misc.h index 4552a61b5..b2e8b1dff 100644 --- a/fusee/fusee-secondary/src/apb_misc.h +++ b/fusee/fusee-secondary/src/apb_misc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_APB_MISC_H #define FUSEE_APB_MISC_H diff --git a/fusee/fusee-secondary/src/btn.c b/fusee/fusee-secondary/src/btn.c index 942d27be6..d3ffdd8ea 100644 --- a/fusee/fusee-secondary/src/btn.c +++ b/fusee/fusee-secondary/src/btn.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "btn.h" diff --git a/fusee/fusee-secondary/src/btn.h b/fusee/fusee-secondary/src/btn.h index 08f6f6921..04f569b94 100644 --- a/fusee/fusee-secondary/src/btn.h +++ b/fusee/fusee-secondary/src/btn.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_BTN_H_ #define FUSEE_BTN_H_ diff --git a/fusee/fusee-secondary/src/car.c b/fusee/fusee-secondary/src/car.c index bc79be9a6..5bf8b4331 100644 --- a/fusee/fusee-secondary/src/car.c +++ b/fusee/fusee-secondary/src/car.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "car.h" #include "utils.h" diff --git a/fusee/fusee-secondary/src/car.h b/fusee/fusee-secondary/src/car.h index 572595c90..4135a54ef 100644 --- a/fusee/fusee-secondary/src/car.h +++ b/fusee/fusee-secondary/src/car.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_CAR_H #define FUSEE_CAR_H diff --git a/fusee/fusee-secondary/src/chainloader.c b/fusee/fusee-secondary/src/chainloader.c index b4090b103..bc222604a 100644 --- a/fusee/fusee-secondary/src/chainloader.c +++ b/fusee/fusee-secondary/src/chainloader.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "chainloader.h" int g_chainloader_argc = 0; diff --git a/fusee/fusee-secondary/src/chainloader.h b/fusee/fusee-secondary/src/chainloader.h index 43fe602a2..0081530c3 100644 --- a/fusee/fusee-secondary/src/chainloader.h +++ b/fusee/fusee-secondary/src/chainloader.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_CHAINLOADER_H #define FUSEE_CHAINLOADER_H diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c index 4c9e0dde1..89ce71988 100644 --- a/fusee/fusee-secondary/src/cluster.c +++ b/fusee/fusee-secondary/src/cluster.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "cluster.h" diff --git a/fusee/fusee-secondary/src/cluster.h b/fusee/fusee-secondary/src/cluster.h index e8e60c3ee..192cf24a6 100644 --- a/fusee/fusee-secondary/src/cluster.h +++ b/fusee/fusee-secondary/src/cluster.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_CLUSTER_H_ #define FUSEE_CLUSTER_H_ diff --git a/fusee/fusee-secondary/src/console.c b/fusee/fusee-secondary/src/console.c index 68532636d..0eb49fb06 100644 --- a/fusee/fusee-secondary/src/console.c +++ b/fusee/fusee-secondary/src/console.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdio.h> #include <stdlib.h> #include <stdbool.h> diff --git a/fusee/fusee-secondary/src/console.h b/fusee/fusee-secondary/src/console.h index 07d26adbb..492a11299 100644 --- a/fusee/fusee-secondary/src/console.h +++ b/fusee/fusee-secondary/src/console.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_CONSOLE_H #define FUSEE_CONSOLE_H diff --git a/fusee/fusee-secondary/src/device_partition.c b/fusee/fusee-secondary/src/device_partition.c index b3ead91d3..8d99bb407 100644 --- a/fusee/fusee-secondary/src/device_partition.c +++ b/fusee/fusee-secondary/src/device_partition.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "device_partition.h" diff --git a/fusee/fusee-secondary/src/device_partition.h b/fusee/fusee-secondary/src/device_partition.h index e0198d1fc..216c0d66f 100644 --- a/fusee/fusee-secondary/src/device_partition.h +++ b/fusee/fusee-secondary/src/device_partition.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_DEVICE_PARTITION_H #define FUSEE_DEVICE_PARTITION_H diff --git a/fusee/fusee-secondary/src/di.c b/fusee/fusee-secondary/src/di.c index f3d00656b..b6f8116c9 100644 --- a/fusee/fusee-secondary/src/di.c +++ b/fusee/fusee-secondary/src/di.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "di.h" diff --git a/fusee/fusee-secondary/src/di.h b/fusee/fusee-secondary/src/di.h index bca4b569a..4aa4f944d 100644 --- a/fusee/fusee-secondary/src/di.h +++ b/fusee/fusee-secondary/src/di.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_DI_H_ #define FUSEE_DI_H_ diff --git a/fusee/fusee-secondary/src/di.inl b/fusee/fusee-secondary/src/di.inl index c34fb4cf2..d0e9894ff 100644 --- a/fusee/fusee-secondary/src/di.inl +++ b/fusee/fusee-secondary/src/di.inl @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + //Clock config. static const cfg_op_t _display_config_1[4] = { {0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 diff --git a/fusee/fusee-secondary/src/exception_handlers.c b/fusee/fusee-secondary/src/exception_handlers.c index 0d71e9ecb..e8d34f702 100644 --- a/fusee/fusee-secondary/src/exception_handlers.c +++ b/fusee/fusee-secondary/src/exception_handlers.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <inttypes.h> #include "exception_handlers.h" diff --git a/fusee/fusee-secondary/src/exception_handlers.h b/fusee/fusee-secondary/src/exception_handlers.h index 8e79b4136..7fda29867 100644 --- a/fusee/fusee-secondary/src/exception_handlers.h +++ b/fusee/fusee-secondary/src/exception_handlers.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_EXCEPTION_HANDLERS_H #define FUSEE_EXCEPTION_HANDLERS_H diff --git a/fusee/fusee-secondary/src/exception_handlers_asm.s b/fusee/fusee-secondary/src/exception_handlers_asm.s index 3a0be6514..84b34308b 100644 --- a/fusee/fusee-secondary/src/exception_handlers_asm.s +++ b/fusee/fusee-secondary/src/exception_handlers_asm.s @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + .macro GEN_USUAL_HANDLER name, index, lr_arm_displ, lr_thumb_displ _exception_handler_\name: ldr sp, =_regs diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index 37328b7b7..dedc059fe 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_EXOSPHERE_CONFIG_H #define FUSEE_EXOSPHERE_CONFIG_H diff --git a/fusee/fusee-secondary/src/flow.h b/fusee/fusee-secondary/src/flow.h index 13f527cac..cd98d8983 100644 --- a/fusee/fusee-secondary/src/flow.h +++ b/fusee/fusee-secondary/src/flow.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_FLOW_CTLR_H #define FUSEE_FLOW_CTLR_H diff --git a/fusee/fusee-secondary/src/fs_dev.c b/fusee/fusee-secondary/src/fs_dev.c index dec7baa27..37de10775 100644 --- a/fusee/fusee-secondary/src/fs_dev.c +++ b/fusee/fusee-secondary/src/fs_dev.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <errno.h> #include <limits.h> #include <stdlib.h> diff --git a/fusee/fusee-secondary/src/fs_dev.h b/fusee/fusee-secondary/src/fs_dev.h index 93a1b8deb..039365d94 100644 --- a/fusee/fusee-secondary/src/fs_dev.h +++ b/fusee/fusee-secondary/src/fs_dev.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_FS_DEV_H #define FUSEE_FS_DEV_H diff --git a/fusee/fusee-secondary/src/fs_utils.c b/fusee/fusee-secondary/src/fs_utils.c index cd188f370..4c24b4f4c 100644 --- a/fusee/fusee-secondary/src/fs_utils.c +++ b/fusee/fusee-secondary/src/fs_utils.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdio.h> #include <sys/stat.h> #include "fs_utils.h" diff --git a/fusee/fusee-secondary/src/fs_utils.h b/fusee/fusee-secondary/src/fs_utils.h index 3bf9bb92a..caa08f4cd 100644 --- a/fusee/fusee-secondary/src/fs_utils.h +++ b/fusee/fusee-secondary/src/fs_utils.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_FS_UTILS_H #define FUSEE_FS_UTILS_H diff --git a/fusee/fusee-secondary/src/fuse.c b/fusee/fusee-secondary/src/fuse.c index 04780c9ce..cc5656cc7 100644 --- a/fusee/fusee-secondary/src/fuse.c +++ b/fusee/fusee-secondary/src/fuse.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <stdint.h> #include <string.h> diff --git a/fusee/fusee-secondary/src/fuse.h b/fusee/fusee-secondary/src/fuse.h index 63285b64f..528b0aff4 100644 --- a/fusee/fusee-secondary/src/fuse.h +++ b/fusee/fusee-secondary/src/fuse.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_FUSE_H #define FUSEE_FUSE_H diff --git a/fusee/fusee-secondary/src/gpio.c b/fusee/fusee-secondary/src/gpio.c index 529e9fb15..9cfec5c2f 100644 --- a/fusee/fusee-secondary/src/gpio.c +++ b/fusee/fusee-secondary/src/gpio.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include <stdint.h> #include <errno.h> diff --git a/fusee/fusee-secondary/src/gpio.h b/fusee/fusee-secondary/src/gpio.h index a916c989c..41781a0ca 100644 --- a/fusee/fusee-secondary/src/gpio.h +++ b/fusee/fusee-secondary/src/gpio.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_GPIO_H #define FUSEE_GPIO_H diff --git a/fusee/fusee-secondary/src/gpt.c b/fusee/fusee-secondary/src/gpt.c index 67dd5d474..05be1122d 100644 --- a/fusee/fusee-secondary/src/gpt.c +++ b/fusee/fusee-secondary/src/gpt.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include <errno.h> #include "gpt.h" diff --git a/fusee/fusee-secondary/src/gpt.h b/fusee/fusee-secondary/src/gpt.h index 690897637..bac0d6a28 100644 --- a/fusee/fusee-secondary/src/gpt.h +++ b/fusee/fusee-secondary/src/gpt.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_GPT_H #define FUSEE_GPT_H diff --git a/fusee/fusee-secondary/src/i2c.c b/fusee/fusee-secondary/src/i2c.c index 028ba56e8..27063b3cd 100644 --- a/fusee/fusee-secondary/src/i2c.c +++ b/fusee/fusee-secondary/src/i2c.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "i2c.h" #include "utils.h" #include "timers.h" diff --git a/fusee/fusee-secondary/src/i2c.h b/fusee/fusee-secondary/src/i2c.h index 8b0acbd35..ec3efecc6 100644 --- a/fusee/fusee-secondary/src/i2c.h +++ b/fusee/fusee-secondary/src/i2c.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_I2C_H #define FUSEE_I2C_H diff --git a/fusee/fusee-secondary/src/init.c b/fusee/fusee-secondary/src/init.c index a121310e4..c061fc00c 100644 --- a/fusee/fusee-secondary/src/init.c +++ b/fusee/fusee-secondary/src/init.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stddef.h> #include <string.h> diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index d6949ef51..45a34d92b 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "utils.h" #include "se.h" diff --git a/fusee/fusee-secondary/src/kernel_patches.h b/fusee/fusee-secondary/src/kernel_patches.h index 239a3d953..7dc2c7795 100644 --- a/fusee/fusee-secondary/src/kernel_patches.h +++ b/fusee/fusee-secondary/src/kernel_patches.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_KERNEL_PATCHES_H #define FUSEE_KERNEL_PATCHES_H diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index 900b7f9df..bf9688423 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "key_derivation.h" #include "masterkey.h" #include "se.h" diff --git a/fusee/fusee-secondary/src/key_derivation.h b/fusee/fusee-secondary/src/key_derivation.h index c8b995fcd..f55b4c66e 100644 --- a/fusee/fusee-secondary/src/key_derivation.h +++ b/fusee/fusee-secondary/src/key_derivation.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_KEYDERIVATION_H #define FUSEE_KEYDERIVATION_H diff --git a/fusee/fusee-secondary/src/kip.h b/fusee/fusee-secondary/src/kip.h index 08e2a680f..ce4aef413 100644 --- a/fusee/fusee-secondary/src/kip.h +++ b/fusee/fusee-secondary/src/kip.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_KIP_H #define FUSEE_KIP_H #include "utils.h" diff --git a/fusee/fusee-secondary/src/lib/driver_utils.h b/fusee/fusee-secondary/src/lib/driver_utils.h index eefc51215..24cde1ed7 100644 --- a/fusee/fusee-secondary/src/lib/driver_utils.h +++ b/fusee/fusee-secondary/src/lib/driver_utils.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_DRIVER_UTILS_H #define FUSEE_DRIVER_UTILS_H diff --git a/fusee/fusee-secondary/src/loader.c b/fusee/fusee-secondary/src/loader.c index 33c81b554..b69695532 100644 --- a/fusee/fusee-secondary/src/loader.c +++ b/fusee/fusee-secondary/src/loader.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include <stdio.h> #include <stdlib.h> diff --git a/fusee/fusee-secondary/src/loader.h b/fusee/fusee-secondary/src/loader.h index b3156736e..ccfc0e2f1 100644 --- a/fusee/fusee-secondary/src/loader.h +++ b/fusee/fusee-secondary/src/loader.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_LOADER_H #define FUSEE_LOADER_H diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index d6aa5191a..5c9107cdb 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/fusee/fusee-secondary/src/masterkey.c b/fusee/fusee-secondary/src/masterkey.c index 89501711b..6d738f23d 100644 --- a/fusee/fusee-secondary/src/masterkey.c +++ b/fusee/fusee-secondary/src/masterkey.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <stdint.h> #include <string.h> diff --git a/fusee/fusee-secondary/src/masterkey.h b/fusee/fusee-secondary/src/masterkey.h index a06504042..a491b23ef 100644 --- a/fusee/fusee-secondary/src/masterkey.h +++ b/fusee/fusee-secondary/src/masterkey.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_MASTERKEY_H #define FUSEE_MASTERKEY_H diff --git a/fusee/fusee-secondary/src/max77620.h b/fusee/fusee-secondary/src/max77620.h index ab90f2b8e..8e1e4627e 100644 --- a/fusee/fusee-secondary/src/max77620.h +++ b/fusee/fusee-secondary/src/max77620.h @@ -2,6 +2,7 @@ * Defining registers address and its bit definitions of MAX77620 and MAX20024 * * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/fusee/fusee-secondary/src/max7762x.c b/fusee/fusee-secondary/src/max7762x.c index 136cbfeca..2987917e5 100644 --- a/fusee/fusee-secondary/src/max7762x.c +++ b/fusee/fusee-secondary/src/max7762x.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdint.h> #include "max7762x.h" diff --git a/fusee/fusee-secondary/src/max7762x.h b/fusee/fusee-secondary/src/max7762x.h index c106a27d4..a59511328 100644 --- a/fusee/fusee-secondary/src/max7762x.h +++ b/fusee/fusee-secondary/src/max7762x.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_MAX7762X_H_ #define FUSEE_MAX7762X_H_ diff --git a/fusee/fusee-secondary/src/mc.c b/fusee/fusee-secondary/src/mc.c index 137bea969..d89454c8f 100644 --- a/fusee/fusee-secondary/src/mc.c +++ b/fusee/fusee-secondary/src/mc.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "mc.h" #include "car.h" #include "timers.h" diff --git a/fusee/fusee-secondary/src/mc.h b/fusee/fusee-secondary/src/mc.h index e93bfc7bf..2a167299c 100644 --- a/fusee/fusee-secondary/src/mc.h +++ b/fusee/fusee-secondary/src/mc.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_MC_H_ #define FUSEE_MC_H_ diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index e4acdd15e..47cf293b8 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdio.h> #include <string.h> #include <errno.h> diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 540f56023..7559a20a9 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_NX_BOOT_H #define FUSEE_NX_BOOT_H diff --git a/fusee/fusee-secondary/src/nxfs.c b/fusee/fusee-secondary/src/nxfs.c index 81c775a30..e7e72306c 100644 --- a/fusee/fusee-secondary/src/nxfs.c +++ b/fusee/fusee-secondary/src/nxfs.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdio.h> #include <stdlib.h> #include <malloc.h> diff --git a/fusee/fusee-secondary/src/nxfs.h b/fusee/fusee-secondary/src/nxfs.h index bbb745814..20f9f9721 100644 --- a/fusee/fusee-secondary/src/nxfs.h +++ b/fusee/fusee-secondary/src/nxfs.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_NX_FS_H #define FUSEE_NX_FS_H diff --git a/fusee/fusee-secondary/src/package1.c b/fusee/fusee-secondary/src/package1.c index 5df01ef0b..46ff14787 100644 --- a/fusee/fusee-secondary/src/package1.c +++ b/fusee/fusee-secondary/src/package1.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <errno.h> #include <stdlib.h> #include <malloc.h> diff --git a/fusee/fusee-secondary/src/package1.h b/fusee/fusee-secondary/src/package1.h index 256fc6d66..79bf25fbe 100644 --- a/fusee/fusee-secondary/src/package1.h +++ b/fusee/fusee-secondary/src/package1.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PACKAGE1_H #define FUSEE_PACKAGE1_H diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 8449b72ac..28f210b25 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdio.h> #include <stdlib.h> #include "utils.h" diff --git a/fusee/fusee-secondary/src/package2.h b/fusee/fusee-secondary/src/package2.h index 4f4e49d57..e5d573c37 100644 --- a/fusee/fusee-secondary/src/package2.h +++ b/fusee/fusee-secondary/src/package2.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PACKAGE2_H #define FUSEE_PACKAGE2_H diff --git a/fusee/fusee-secondary/src/panic.c b/fusee/fusee-secondary/src/panic.c index ce0b54747..d8f298470 100644 --- a/fusee/fusee-secondary/src/panic.c +++ b/fusee/fusee-secondary/src/panic.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "panic.h" #include "di.h" #include "pmc.h" diff --git a/fusee/fusee-secondary/src/panic.h b/fusee/fusee-secondary/src/panic.h index 0b29f7070..78ea67fb6 100644 --- a/fusee/fusee-secondary/src/panic.h +++ b/fusee/fusee-secondary/src/panic.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PANIC_H #define FUSEE_PANIC_H diff --git a/fusee/fusee-secondary/src/panic_color.h b/fusee/fusee-secondary/src/panic_color.h index a87cfdeb6..644f1107c 100644 --- a/fusee/fusee-secondary/src/panic_color.h +++ b/fusee/fusee-secondary/src/panic_color.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PANIC_COLOR_H #define FUSEE_PANIC_COLOR_H diff --git a/fusee/fusee-secondary/src/pinmux.h b/fusee/fusee-secondary/src/pinmux.h index 80fc3a37c..3912143eb 100644 --- a/fusee/fusee-secondary/src/pinmux.h +++ b/fusee/fusee-secondary/src/pinmux.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PINMUX_H #define FUSEE_PINMUX_H diff --git a/fusee/fusee-secondary/src/pmc.h b/fusee/fusee-secondary/src/pmc.h index 0c851eb47..cf20474e7 100644 --- a/fusee/fusee-secondary/src/pmc.h +++ b/fusee/fusee-secondary/src/pmc.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_PMC_H #define FUSEE_PMC_H diff --git a/fusee/fusee-secondary/src/raw_dev.c b/fusee/fusee-secondary/src/raw_dev.c index 245d3bea4..797bb40e8 100644 --- a/fusee/fusee-secondary/src/raw_dev.c +++ b/fusee/fusee-secondary/src/raw_dev.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <errno.h> #include <limits.h> #include <stdlib.h> diff --git a/fusee/fusee-secondary/src/raw_dev.h b/fusee/fusee-secondary/src/raw_dev.h index 17cee846a..784f13de4 100644 --- a/fusee/fusee-secondary/src/raw_dev.h +++ b/fusee/fusee-secondary/src/raw_dev.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_RAW_DEV_H #define FUSEE_RAW_DEV_H diff --git a/fusee/fusee-secondary/src/sdmmc/mmc.h b/fusee/fusee-secondary/src/sdmmc/mmc.h index e357d00a4..6f7126c01 100644 --- a/fusee/fusee-secondary/src/sdmmc/mmc.h +++ b/fusee/fusee-secondary/src/sdmmc/mmc.h @@ -2,6 +2,7 @@ * Header for MultiMediaCard (MMC) * * Copyright 2002 Hewlett-Packard Company + * Copyright (c) 2018 Atmosphère-NX * * Use consistent with the GNU GPL is permitted, * provided that this copyright notice is diff --git a/fusee/fusee-secondary/src/sdmmc/sd.h b/fusee/fusee-secondary/src/sdmmc/sd.h index e5707f55f..c30e8647e 100644 --- a/fusee/fusee-secondary/src/sdmmc/sd.h +++ b/fusee/fusee-secondary/src/sdmmc/sd.h @@ -2,6 +2,8 @@ * include/linux/mmc/sd.h * * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. + * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc.c b/fusee/fusee-secondary/src/sdmmc/sdmmc.c index 365547ae9..e4a59c046 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include <stdbool.h> #include <stdint.h> diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc.h b/fusee/fusee-secondary/src/sdmmc/sdmmc.h index c3a2a325b..a40fe60d1 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc.h +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SDMMC_H #define FUSEE_SDMMC_H diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index c30a1f837..c831493f5 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include <stdbool.h> #include <stdint.h> diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h index 37dd207d1..edcd3c60f 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SDMMC_CORE_H #define FUSEE_SDMMC_CORE_H diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h b/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h index 8fbcffb6f..3b6b4adb0 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_tegra.h @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SDMMC_TEGRA_H #define FUSEE_SDMMC_TEGRA_H diff --git a/fusee/fusee-secondary/src/se.c b/fusee/fusee-secondary/src/se.c index af86980b3..b466bd80b 100644 --- a/fusee/fusee-secondary/src/se.c +++ b/fusee/fusee-secondary/src/se.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <string.h> #include "utils.h" diff --git a/fusee/fusee-secondary/src/se.h b/fusee/fusee-secondary/src/se.h index 311567261..db692b9cf 100644 --- a/fusee/fusee-secondary/src/se.h +++ b/fusee/fusee-secondary/src/se.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SE_H #define FUSEE_SE_H diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index dd0591b9a..dd5085d79 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdio.h> #include "timers.h" #include "splash_screen.h" diff --git a/fusee/fusee-secondary/src/splash_screen.h b/fusee/fusee-secondary/src/splash_screen.h index 7240b3235..032337744 100644 --- a/fusee/fusee-secondary/src/splash_screen.h +++ b/fusee/fusee-secondary/src/splash_screen.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SPLASH_SCREEN_H #define FUSEE_SPLASH_SCREEN_H diff --git a/fusee/fusee-secondary/src/splash_screen_default.c b/fusee/fusee-secondary/src/splash_screen_default.c index c1391a6cf..c1a955d5f 100644 --- a/fusee/fusee-secondary/src/splash_screen_default.c +++ b/fusee/fusee-secondary/src/splash_screen_default.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "splash_screen.h" uint8_t g_default_splash_screen[1] = {0}; diff --git a/fusee/fusee-secondary/src/stage2.h b/fusee/fusee-secondary/src/stage2.h index 020cf2c50..c3d18ef49 100644 --- a/fusee/fusee-secondary/src/stage2.h +++ b/fusee/fusee-secondary/src/stage2.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_STAGE2_H #define FUSEE_STAGE2_H diff --git a/fusee/fusee-secondary/src/start.s b/fusee/fusee-secondary/src/start.s index d4280470f..e417cd80e 100644 --- a/fusee/fusee-secondary/src/start.s +++ b/fusee/fusee-secondary/src/start.s @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + .macro CLEAR_GPR_REG_ITER mov r\@, #0 .endm diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index 4a1835085..22d058b92 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdio.h> #include <stdlib.h> #include <stdint.h> diff --git a/fusee/fusee-secondary/src/stratosphere.h b/fusee/fusee-secondary/src/stratosphere.h index 2c72fab85..33915555b 100644 --- a/fusee/fusee-secondary/src/stratosphere.h +++ b/fusee/fusee-secondary/src/stratosphere.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_STRATOSPHERE_H #define FUSEE_STRATOSPHERE_H diff --git a/fusee/fusee-secondary/src/sysreg.h b/fusee/fusee-secondary/src/sysreg.h index d69cf8897..1bc1a8c43 100644 --- a/fusee/fusee-secondary/src/sysreg.h +++ b/fusee/fusee-secondary/src/sysreg.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_SYSREG_H #define FUSEE_SYSREG_H diff --git a/fusee/fusee-secondary/src/timers.h b/fusee/fusee-secondary/src/timers.h index 39bf9413e..418e5928d 100644 --- a/fusee/fusee-secondary/src/timers.h +++ b/fusee/fusee-secondary/src/timers.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_TIMERS_H #define FUSEE_TIMERS_H diff --git a/fusee/fusee-secondary/src/tsec.c b/fusee/fusee-secondary/src/tsec.c index 12e8613ec..f9cfeaa04 100644 --- a/fusee/fusee-secondary/src/tsec.c +++ b/fusee/fusee-secondary/src/tsec.c @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include "tsec.h" #include "di.h" #include "timers.h" diff --git a/fusee/fusee-secondary/src/tsec.h b/fusee/fusee-secondary/src/tsec.h index 47be450bd..3ff537172 100644 --- a/fusee/fusee-secondary/src/tsec.h +++ b/fusee/fusee-secondary/src/tsec.h @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_TSEC_H_ #define FUSEE_TSEC_H_ diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index 220c49d24..7f2de0da9 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <stdbool.h> #include <stdarg.h> #include "utils.h" diff --git a/fusee/fusee-secondary/src/utils.h b/fusee/fusee-secondary/src/utils.h index e811651a3..cfc0cbdf4 100644 --- a/fusee/fusee-secondary/src/utils.h +++ b/fusee/fusee-secondary/src/utils.h @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #ifndef FUSEE_UTILS_H #define FUSEE_UTILS_H diff --git a/stratosphere/boot/source/boot_main.cpp b/stratosphere/boot/source/boot_main.cpp index 5d3368bd3..e636ff6c5 100644 --- a/stratosphere/boot/source/boot_main.cpp +++ b/stratosphere/boot/source/boot_main.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdlib> #include <cstdint> #include <cstring> diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index b9ddc7434..3bb6e1bed 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <cstring> diff --git a/stratosphere/creport/source/creport_code_info.hpp b/stratosphere/creport/source/creport_code_info.hpp index 45b1cd10f..ff1c1fb1c 100644 --- a/stratosphere/creport/source/creport_code_info.hpp +++ b/stratosphere/creport/source/creport_code_info.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <cstdio> diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 30059d1de..cd9d1f9bb 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdio> #include <cstring> #include <sys/stat.h> diff --git a/stratosphere/creport/source/creport_crash_report.hpp b/stratosphere/creport/source/creport_crash_report.hpp index 76b371cdb..049610c87 100644 --- a/stratosphere/creport/source/creport_crash_report.hpp +++ b/stratosphere/creport/source/creport_crash_report.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/creport/source/creport_debug_types.hpp b/stratosphere/creport/source/creport_debug_types.hpp index 44daa7f67..4c2544b27 100644 --- a/stratosphere/creport/source/creport_debug_types.hpp +++ b/stratosphere/creport/source/creport_debug_types.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/creport/source/creport_main.cpp b/stratosphere/creport/source/creport_main.cpp index 692197377..77fd7b400 100644 --- a/stratosphere/creport/source/creport_main.cpp +++ b/stratosphere/creport/source/creport_main.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdlib> #include <cstdint> #include <cstdio> diff --git a/stratosphere/creport/source/creport_thread_info.cpp b/stratosphere/creport/source/creport_thread_info.cpp index f310f8f14..ab8c1e397 100644 --- a/stratosphere/creport/source/creport_thread_info.cpp +++ b/stratosphere/creport/source/creport_thread_info.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <cstring> diff --git a/stratosphere/creport/source/creport_thread_info.hpp b/stratosphere/creport/source/creport_thread_info.hpp index af49bb779..491b988a8 100644 --- a/stratosphere/creport/source/creport_thread_info.hpp +++ b/stratosphere/creport/source/creport_thread_info.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <cstdio> diff --git a/stratosphere/fs_mitm/source/debug.cpp b/stratosphere/fs_mitm/source/debug.cpp index 2abeb625a..35844b65e 100644 --- a/stratosphere/fs_mitm/source/debug.cpp +++ b/stratosphere/fs_mitm/source/debug.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include <cstring> diff --git a/stratosphere/fs_mitm/source/debug.hpp b/stratosphere/fs_mitm/source/debug.hpp index b79a426eb..0c1e21ec0 100644 --- a/stratosphere/fs_mitm/source/debug.hpp +++ b/stratosphere/fs_mitm/source/debug.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once void Reboot(); diff --git a/stratosphere/fs_mitm/source/fs_istorage.hpp b/stratosphere/fs_mitm/source/fs_istorage.hpp index 4262245f6..d6827839f 100644 --- a/stratosphere/fs_mitm/source/fs_istorage.hpp +++ b/stratosphere/fs_mitm/source/fs_istorage.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/fs_shim.c b/stratosphere/fs_mitm/source/fs_shim.c index ebfae7ed6..0c510dbba 100644 --- a/stratosphere/fs_mitm/source/fs_shim.c +++ b/stratosphere/fs_mitm/source/fs_shim.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include "fs_shim.h" diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp index 0ca29eb2b..4a11580fa 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp index fea9ccecd..3e6061651 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index c5cb5cba2..e6271b10d 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdlib> #include <cstdint> #include <cstring> diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index be9c63620..3a1afb780 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <string.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp index 6cadf1b72..c4a78e681 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <map> diff --git a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp index fc608602b..cc378cd1f 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index f23794039..07f5c3156 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include "fsmitm_service.hpp" #include "fs_shim.h" diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index ef337d329..b1bd62d9c 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 3542b8af8..a98a1b739 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include <atomic> diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index 794dbe34c..e1480d0d1 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/fsmitm_worker.cpp b/stratosphere/fs_mitm/source/fsmitm_worker.cpp index a3c755272..24cba1168 100644 --- a/stratosphere/fs_mitm/source/fsmitm_worker.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_worker.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <mutex> #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/fsmitm_worker.hpp b/stratosphere/fs_mitm/source/fsmitm_worker.hpp index 0b7b6d464..68c5ea4e4 100644 --- a/stratosphere/fs_mitm/source/fsmitm_worker.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_worker.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/imitmserviceobject.hpp b/stratosphere/fs_mitm/source/imitmserviceobject.hpp index 30cdd052e..8952903e9 100644 --- a/stratosphere/fs_mitm/source/imitmserviceobject.hpp +++ b/stratosphere/fs_mitm/source/imitmserviceobject.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <atomic> diff --git a/stratosphere/fs_mitm/source/mitm_query_service.cpp b/stratosphere/fs_mitm/source/mitm_query_service.cpp index 41f78f905..e4d88d076 100644 --- a/stratosphere/fs_mitm/source/mitm_query_service.cpp +++ b/stratosphere/fs_mitm/source/mitm_query_service.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <mutex> #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/mitm_query_service.hpp b/stratosphere/fs_mitm/source/mitm_query_service.hpp index 2508e4e2d..a1153c496 100644 --- a/stratosphere/fs_mitm/source/mitm_query_service.hpp +++ b/stratosphere/fs_mitm/source/mitm_query_service.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/stratosphere/fs_mitm/source/mitm_server.hpp b/stratosphere/fs_mitm/source/mitm_server.hpp index 612b74d32..4054dd9ac 100644 --- a/stratosphere/fs_mitm/source/mitm_server.hpp +++ b/stratosphere/fs_mitm/source/mitm_server.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/mitm_session.hpp b/stratosphere/fs_mitm/source/mitm_session.hpp index bc4fe0f09..0d535b529 100644 --- a/stratosphere/fs_mitm/source/mitm_session.hpp +++ b/stratosphere/fs_mitm/source/mitm_session.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/fs_mitm/source/sm_mitm.c b/stratosphere/fs_mitm/source/sm_mitm.c index 556848440..0ab1c5d55 100644 --- a/stratosphere/fs_mitm/source/sm_mitm.c +++ b/stratosphere/fs_mitm/source/sm_mitm.c @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <switch/arm/atomics.h> #include "sm_mitm.h" diff --git a/stratosphere/libstratosphere/include/meta_tools.hpp b/stratosphere/libstratosphere/include/meta_tools.hpp index 27da96a58..f4c06e3c0 100644 --- a/stratosphere/libstratosphere/include/meta_tools.hpp +++ b/stratosphere/libstratosphere/include/meta_tools.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <functional> diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp index d37ec97f8..fdd8b9d24 100644 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include "stratosphere/ipc_templating.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp b/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp index 8f990ea43..74500eb63 100644 --- a/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <algorithm> diff --git a/stratosphere/libstratosphere/include/stratosphere/existingportserver.hpp b/stratosphere/libstratosphere/include/stratosphere/existingportserver.hpp index d026fb676..360ed286b 100644 --- a/stratosphere/libstratosphere/include/stratosphere/existingportserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/existingportserver.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include "iserver.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp index d75379aab..0d2b8e8f6 100644 --- a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/libstratosphere/include/stratosphere/ievent.hpp b/stratosphere/libstratosphere/include/stratosphere/ievent.hpp index cdff65c1c..d1c93ef63 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ievent.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ievent.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <algorithm> diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp index f0572e40b..7f9c2c89e 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <cstdlib> diff --git a/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp b/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp index 9983a1535..e95593280 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <type_traits> diff --git a/stratosphere/libstratosphere/include/stratosphere/iserver.hpp b/stratosphere/libstratosphere/include/stratosphere/iserver.hpp index 06d140408..1b32ebcd5 100644 --- a/stratosphere/libstratosphere/include/stratosphere/iserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/iserver.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <algorithm> diff --git a/stratosphere/libstratosphere/include/stratosphere/iserviceobject.hpp b/stratosphere/libstratosphere/include/stratosphere/iserviceobject.hpp index 9433d0623..2e8c13570 100644 --- a/stratosphere/libstratosphere/include/stratosphere/iserviceobject.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/iserviceobject.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/libstratosphere/include/stratosphere/isession.hpp b/stratosphere/libstratosphere/include/stratosphere/isession.hpp index c0e44d0b2..842dfd412 100644 --- a/stratosphere/libstratosphere/include/stratosphere/isession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/isession.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <type_traits> diff --git a/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp b/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp index 4a81f3c40..1fff3f874 100644 --- a/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp b/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp index 83ed7df5c..f61545f74 100644 --- a/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include "iserver.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/multithreadedwaitablemanager.hpp b/stratosphere/libstratosphere/include/stratosphere/multithreadedwaitablemanager.hpp index 448060932..d223000db 100644 --- a/stratosphere/libstratosphere/include/stratosphere/multithreadedwaitablemanager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/multithreadedwaitablemanager.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <vector> diff --git a/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp b/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp index e73388670..f796beb26 100644 --- a/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include "iserver.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp b/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp index da64e8d6b..7b452c870 100644 --- a/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <type_traits> diff --git a/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp b/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp index ccd5a5ebe..a22254f67 100644 --- a/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp index 4b42cd2cd..54f45e06d 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <algorithm> diff --git a/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp b/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp index ed4c7775a..247592a4e 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <atomic> diff --git a/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp b/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp index 4d1dbfaec..3c5ec1356 100644 --- a/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp +++ b/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> diff --git a/stratosphere/libstratosphere/source/waitablemanager.cpp b/stratosphere/libstratosphere/source/waitablemanager.cpp index 615bf861d..35706a006 100644 --- a/stratosphere/libstratosphere/source/waitablemanager.cpp +++ b/stratosphere/libstratosphere/source/waitablemanager.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index ef2dc2ef1..c7ca985b0 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <string.h> #include <vector> diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index 8fee7b5ac..f99eb1fcf 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/loader/source/ldr_debug_monitor.cpp b/stratosphere/loader/source/ldr_debug_monitor.cpp index f7d838f8f..a2e12e3f8 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.cpp +++ b/stratosphere/loader/source/ldr_debug_monitor.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <cstdio> #include <algorithm> diff --git a/stratosphere/loader/source/ldr_debug_monitor.hpp b/stratosphere/loader/source/ldr_debug_monitor.hpp index 80b4a966c..d1b1c4e8a 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.hpp +++ b/stratosphere/loader/source/ldr_debug_monitor.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/loader/source/ldr_launch_queue.cpp b/stratosphere/loader/source/ldr_launch_queue.cpp index b43e061b4..8fda8585b 100644 --- a/stratosphere/loader/source/ldr_launch_queue.cpp +++ b/stratosphere/loader/source/ldr_launch_queue.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> #include <array> diff --git a/stratosphere/loader/source/ldr_launch_queue.hpp b/stratosphere/loader/source/ldr_launch_queue.hpp index cf90f951e..74a2a03c9 100644 --- a/stratosphere/loader/source/ldr_launch_queue.hpp +++ b/stratosphere/loader/source/ldr_launch_queue.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index 94a52fcbf..a8d69bf85 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdlib> #include <cstdint> #include <cstring> diff --git a/stratosphere/loader/source/ldr_map.cpp b/stratosphere/loader/source/ldr_map.cpp index 12e3dc527..dc9393f73 100644 --- a/stratosphere/loader/source/ldr_map.cpp +++ b/stratosphere/loader/source/ldr_map.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_map.hpp b/stratosphere/loader/source/ldr_map.hpp index 1b8c0a986..7a623b5cd 100644 --- a/stratosphere/loader/source/ldr_map.hpp +++ b/stratosphere/loader/source/ldr_map.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index f7c71727b..e455fc4b4 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_npdm.hpp b/stratosphere/loader/source/ldr_npdm.hpp index cfef58595..28fc465ef 100644 --- a/stratosphere/loader/source/ldr_npdm.hpp +++ b/stratosphere/loader/source/ldr_npdm.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_nro.cpp b/stratosphere/loader/source/ldr_nro.cpp index 127878212..06d93a464 100644 --- a/stratosphere/loader/source/ldr_nro.cpp +++ b/stratosphere/loader/source/ldr_nro.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_nro.hpp b/stratosphere/loader/source/ldr_nro.hpp index 497278fad..1d0cdf587 100644 --- a/stratosphere/loader/source/ldr_nro.hpp +++ b/stratosphere/loader/source/ldr_nro.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index 26e265690..893d662c3 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_nso.hpp b/stratosphere/loader/source/ldr_nso.hpp index 242839249..94a18223a 100644 --- a/stratosphere/loader/source/ldr_nso.hpp +++ b/stratosphere/loader/source/ldr_nso.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index a0a6bdc24..5fcbd5dd4 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdlib> #include <cstdint> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_patcher.hpp b/stratosphere/loader/source/ldr_patcher.hpp index 07794a3a9..993ba277a 100644 --- a/stratosphere/loader/source/ldr_patcher.hpp +++ b/stratosphere/loader/source/ldr_patcher.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 05fda928a..3f3d38348 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> diff --git a/stratosphere/loader/source/ldr_process_creation.hpp b/stratosphere/loader/source/ldr_process_creation.hpp index 6b87e005d..40a83678e 100644 --- a/stratosphere/loader/source/ldr_process_creation.hpp +++ b/stratosphere/loader/source/ldr_process_creation.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index 66ab5308b..a1be87408 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include "ldr_process_manager.hpp" diff --git a/stratosphere/loader/source/ldr_process_manager.hpp b/stratosphere/loader/source/ldr_process_manager.hpp index 2643be565..c177a03b2 100644 --- a/stratosphere/loader/source/ldr_process_manager.hpp +++ b/stratosphere/loader/source/ldr_process_manager.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/stratosphere/loader/source/ldr_random.cpp b/stratosphere/loader/source/ldr_random.cpp index a431fd4b3..b18cb32a4 100644 --- a/stratosphere/loader/source/ldr_random.cpp +++ b/stratosphere/loader/source/ldr_random.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include "ldr_random.hpp" diff --git a/stratosphere/loader/source/ldr_random.hpp b/stratosphere/loader/source/ldr_random.hpp index 633efef0e..d5848d73a 100644 --- a/stratosphere/loader/source/ldr_random.hpp +++ b/stratosphere/loader/source/ldr_random.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 8a0d2a6ed..217cdfc68 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> #include <cstdio> diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index eda625223..c953ab7f6 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <array> diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index 402bb9cc6..4529710f9 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <cstdio> #include <algorithm> diff --git a/stratosphere/loader/source/ldr_ro_service.hpp b/stratosphere/loader/source/ldr_ro_service.hpp index aea97ba40..3e622587e 100644 --- a/stratosphere/loader/source/ldr_ro_service.hpp +++ b/stratosphere/loader/source/ldr_ro_service.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/loader/source/ldr_shell.cpp b/stratosphere/loader/source/ldr_shell.cpp index 27d3c7e9c..664388d08 100644 --- a/stratosphere/loader/source/ldr_shell.cpp +++ b/stratosphere/loader/source/ldr_shell.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include "ldr_shell.hpp" diff --git a/stratosphere/loader/source/ldr_shell.hpp b/stratosphere/loader/source/ldr_shell.hpp index c4248269f..7cc95f858 100644 --- a/stratosphere/loader/source/ldr_shell.hpp +++ b/stratosphere/loader/source/ldr_shell.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 6bf25ea00..f666abce2 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdlib> #include <cstdint> #include <cstdio> diff --git a/stratosphere/pm/source/pm_boot2.hpp b/stratosphere/pm/source/pm_boot2.hpp index 2aa1e593e..2f93ac0e8 100644 --- a/stratosphere/pm/source/pm_boot2.hpp +++ b/stratosphere/pm/source/pm_boot2.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once enum class Boot2KnownTitleId : u64 { diff --git a/stratosphere/pm/source/pm_boot_mode.cpp b/stratosphere/pm/source/pm_boot_mode.cpp index ac0f884fb..7b83ee1e8 100644 --- a/stratosphere/pm/source/pm_boot_mode.cpp +++ b/stratosphere/pm/source/pm_boot_mode.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include "pm_boot_mode.hpp" diff --git a/stratosphere/pm/source/pm_boot_mode.hpp b/stratosphere/pm/source/pm_boot_mode.hpp index 06bfcfa9e..097dace3a 100644 --- a/stratosphere/pm/source/pm_boot_mode.hpp +++ b/stratosphere/pm/source/pm_boot_mode.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/stratosphere/pm/source/pm_debug_monitor.cpp b/stratosphere/pm/source/pm_debug_monitor.cpp index cd85e1f8a..e9818911e 100644 --- a/stratosphere/pm/source/pm_debug_monitor.cpp +++ b/stratosphere/pm/source/pm_debug_monitor.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include "pm_registration.hpp" diff --git a/stratosphere/pm/source/pm_debug_monitor.hpp b/stratosphere/pm/source/pm_debug_monitor.hpp index 16c9c710e..a6ae9ca8b 100644 --- a/stratosphere/pm/source/pm_debug_monitor.hpp +++ b/stratosphere/pm/source/pm_debug_monitor.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/stratosphere/pm/source/pm_info.cpp b/stratosphere/pm/source/pm_info.cpp index fa447fb97..437c75a8c 100644 --- a/stratosphere/pm/source/pm_info.cpp +++ b/stratosphere/pm/source/pm_info.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include "pm_registration.hpp" #include "pm_info.hpp" diff --git a/stratosphere/pm/source/pm_info.hpp b/stratosphere/pm/source/pm_info.hpp index 8e2dcb938..bc7ce5cd9 100644 --- a/stratosphere/pm/source/pm_info.hpp +++ b/stratosphere/pm/source/pm_info.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 4ce175465..24ef034eb 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdlib> #include <cstdint> #include <cstring> diff --git a/stratosphere/pm/source/pm_process_track.cpp b/stratosphere/pm/source/pm_process_track.cpp index 507979126..6de7f8603 100644 --- a/stratosphere/pm/source/pm_process_track.cpp +++ b/stratosphere/pm/source/pm_process_track.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include "pm_process_track.hpp" diff --git a/stratosphere/pm/source/pm_process_track.hpp b/stratosphere/pm/source/pm_process_track.hpp index 99c1a66fd..618c063f1 100644 --- a/stratosphere/pm/source/pm_process_track.hpp +++ b/stratosphere/pm/source/pm_process_track.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/pm/source/pm_process_wait.hpp b/stratosphere/pm/source/pm_process_wait.hpp index e074c03df..49a85a594 100644 --- a/stratosphere/pm/source/pm_process_wait.hpp +++ b/stratosphere/pm/source/pm_process_wait.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <mutex> #include <switch.h> diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index e61b81a3b..63c7fbd39 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include <atomic> diff --git a/stratosphere/pm/source/pm_registration.hpp b/stratosphere/pm/source/pm_registration.hpp index 89dc1d929..6749b4c8c 100644 --- a/stratosphere/pm/source/pm_registration.hpp +++ b/stratosphere/pm/source/pm_registration.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index 4149ccfac..af338337f 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/pm/source/pm_resource_limits.hpp b/stratosphere/pm/source/pm_resource_limits.hpp index bf31b561b..36d46fcd0 100644 --- a/stratosphere/pm/source/pm_resource_limits.hpp +++ b/stratosphere/pm/source/pm_resource_limits.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere.hpp> diff --git a/stratosphere/pm/source/pm_shell.cpp b/stratosphere/pm/source/pm_shell.cpp index 78b72a86f..4a9653367 100644 --- a/stratosphere/pm/source/pm_shell.cpp +++ b/stratosphere/pm/source/pm_shell.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include "pm_registration.hpp" diff --git a/stratosphere/pm/source/pm_shell.hpp b/stratosphere/pm/source/pm_shell.hpp index 47ef8b3c8..c5b63c030 100644 --- a/stratosphere/pm/source/pm_shell.hpp +++ b/stratosphere/pm/source/pm_shell.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index 410058383..d9381b821 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <cstdlib> #include <cstdint> #include <cstring> diff --git a/stratosphere/sm/source/sm_manager_service.cpp b/stratosphere/sm/source/sm_manager_service.cpp index 0e6a46801..04190f7ed 100644 --- a/stratosphere/sm/source/sm_manager_service.cpp +++ b/stratosphere/sm/source/sm_manager_service.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere.hpp> #include "sm_manager_service.hpp" diff --git a/stratosphere/sm/source/sm_manager_service.hpp b/stratosphere/sm/source/sm_manager_service.hpp index 1022ecd0b..f64b26a03 100644 --- a/stratosphere/sm/source/sm_manager_service.hpp +++ b/stratosphere/sm/source/sm_manager_service.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index 226a7b192..63def66d9 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <algorithm> #include <stratosphere/servicesession.hpp> diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 4f9ce8ccd..630a72181 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> diff --git a/stratosphere/sm/source/sm_user_service.cpp b/stratosphere/sm/source/sm_user_service.cpp index 076d661e6..0f8927ed8 100644 --- a/stratosphere/sm/source/sm_user_service.cpp +++ b/stratosphere/sm/source/sm_user_service.cpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #include <switch.h> #include <stratosphere/servicesession.hpp> #include "sm_user_service.hpp" diff --git a/stratosphere/sm/source/sm_user_service.hpp b/stratosphere/sm/source/sm_user_service.hpp index 424fe9968..8f3250472 100644 --- a/stratosphere/sm/source/sm_user_service.hpp +++ b/stratosphere/sm/source/sm_user_service.hpp @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + #pragma once #include <switch.h> #include <stratosphere/iserviceobject.hpp> diff --git a/thermosphere/src/exceptions.c b/thermosphere/src/exceptions.c index c51a2f9e2..2bcfef9dc 100644 --- a/thermosphere/src/exceptions.c +++ b/thermosphere/src/exceptions.c @@ -1,10 +1,19 @@ -/** - * Thermosphère: exception handler - * Handles all exceptions, including a return to EL2. +/* + * Copyright (c) 2018 Atmosphère-NX * - * Copyright (c) 2018 Kate J. Temkin <k@ktemkin.com> + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - + #include <stdint.h> #include <stddef.h> #include "exceptions.h" diff --git a/thermosphere/src/exceptions.h b/thermosphere/src/exceptions.h index e8b74928e..cd70b0a24 100644 --- a/thermosphere/src/exceptions.h +++ b/thermosphere/src/exceptions.h @@ -1,8 +1,17 @@ -/** - * Thermosphère: exception handler - * Handles all exceptions, including a return to EL2. +/* + * Copyright (c) 2018 Atmosphère-NX * - * Copyright (c) 2018 Kate J. Temkin <k@ktemkin.com> + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef __EXCEPTION_H__ diff --git a/thermosphere/src/lib/printk.c b/thermosphere/src/lib/printk.c index a24958dde..2799bc016 100644 --- a/thermosphere/src/lib/printk.c +++ b/thermosphere/src/lib/printk.c @@ -1,9 +1,20 @@ -/** - * Kernel print functions. +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - + #include "printk.h" - #include "vsprintf.h" /** diff --git a/thermosphere/src/lib/printk.h b/thermosphere/src/lib/printk.h index 006985a52..21fba95b6 100644 --- a/thermosphere/src/lib/printk.h +++ b/thermosphere/src/lib/printk.h @@ -1,2 +1,17 @@ - +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + void printk(char *fmt, ...); diff --git a/thermosphere/src/main.c b/thermosphere/src/main.c index 008fce338..fed8e0f69 100644 --- a/thermosphere/src/main.c +++ b/thermosphere/src/main.c @@ -1,6 +1,17 @@ -/** - * Thermosphère hypervisor -- primary setup code - * Copyright (c) 2018 Kate J. Temkin <k@ktemkin.com> +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stdint.h> diff --git a/thermosphere/src/regs.h b/thermosphere/src/regs.h index 9ac2a3921..db8f5a713 100644 --- a/thermosphere/src/regs.h +++ b/thermosphere/src/regs.h @@ -1,6 +1,17 @@ -/** - * Thermosphère: register access primitives - * Copyright (c) Kate J. Temkin <k@ktemkin.com> +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef __REGS_H__ diff --git a/thermosphere/src/start.s b/thermosphere/src/start.s index 02a732bd4..7e62a6110 100644 --- a/thermosphere/src/start.s +++ b/thermosphere/src/start.s @@ -1,8 +1,17 @@ -/** - * Thermosphère hypervisor entry points - * This file contains all entry points (e.g. when launching or switching ELs). +/* + * Copyright (c) 2018 Atmosphère-NX * - * Copyright (c) Kate J. Temkin <k@ktemkin.com> + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ .section ".text" From 488fc0f119d2297e2a63e7d6894d76c98fb7e1a3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 8 Sep 2018 23:47:15 -0700 Subject: [PATCH 075/489] pm: Support for 6.0.0 --- .../include/stratosphere/hossynch.hpp | 40 ++---- stratosphere/pm/pm.json | 1 + stratosphere/pm/source/pm_boot2.cpp | 1 + stratosphere/pm/source/pm_boot2.hpp | 1 + stratosphere/pm/source/pm_debug_monitor.cpp | 10 ++ stratosphere/pm/source/pm_debug_monitor.hpp | 3 + stratosphere/pm/source/pm_main.cpp | 16 +-- stratosphere/pm/source/pm_registration.cpp | 10 ++ stratosphere/pm/source/pm_registration.hpp | 23 ++-- stratosphere/pm/source/pm_resource_limits.cpp | 126 ++++++++++++------ 10 files changed, 143 insertions(+), 88 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp index 0d2b8e8f6..56facd130 100644 --- a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp @@ -66,15 +66,15 @@ class HosCondVar { public: HosCondVar() { mutexInit(&m); - condvarInit(&cv, &m); + condvarInit(&cv); } Result WaitTimeout(u64 timeout) { - return condvarWaitTimeout(&cv, timeout); + return condvarWaitTimeout(&cv, &m, timeout); } Result Wait() { - return condvarWait(&cv); + return condvarWait(&cv, &m); } Result Wake(int num) { @@ -92,45 +92,25 @@ class HosCondVar { class HosSemaphore { private: - CondVar cv; - Mutex m; - u64 count; + Semaphore s; public: HosSemaphore() { - count = 0; - mutexInit(&m); - condvarInit(&cv, &m); + semaphoreInit(&s, 0); } - HosSemaphore(u64 c) : count(c) { - mutexInit(&m); - condvarInit(&cv, &m); + HosSemaphore(u64 c) { + semaphoreInit(&s, c); } void Signal() { - mutexLock(&this->m); - count++; - condvarWakeOne(&cv); - mutexUnlock(&this->m); + semaphoreSignal(&s); } void Wait() { - mutexLock(&this->m); - while (!count) { - condvarWait(&cv); - } - count--; - mutexUnlock(&this->m); + semaphoreWait(&s); } bool TryWait() { - mutexLock(&this->m); - bool success = false; - if (count) { - count--; - success = true; - } - mutexUnlock(&this->m); - return success; + return semaphoreTryWait(&s); } }; diff --git a/stratosphere/pm/pm.json b/stratosphere/pm/pm.json index 4b127d4e8..a7bd7e8a9 100644 --- a/stratosphere/pm/pm.json +++ b/stratosphere/pm/pm.json @@ -49,6 +49,7 @@ "svcOutputDebugString": "0x27", "svcReturnFromException": "0x28", "svcGetInfo": "0x29", + "svcGetResourceLimitLimitValue": "0x30", "svcGetResourceLimitCurrentValue": "0x31", "svcWaitForAddress": "0x34", "svcSignalToAddress": "0x35", diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index f666abce2..2f22c9d11 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -107,6 +107,7 @@ static const std::tuple<Boot2KnownTitleId, bool> g_additional_launch_programs[] {Boot2KnownTitleId::sdb, true}, /* sdb */ {Boot2KnownTitleId::migration, true}, /* migration */ {Boot2KnownTitleId::grc, true}, /* grc */ + {Boot2KnownTitleId::olsc, true}, /* olsc */ }; static void MountSdCard() { diff --git a/stratosphere/pm/source/pm_boot2.hpp b/stratosphere/pm/source/pm_boot2.hpp index 2f93ac0e8..44c4e1de1 100644 --- a/stratosphere/pm/source/pm_boot2.hpp +++ b/stratosphere/pm/source/pm_boot2.hpp @@ -76,6 +76,7 @@ enum class Boot2KnownTitleId : u64 { jit = 0x010000000000003BUL, jpegdec = 0x010000000000003CUL, safemode = 0x010000000000003DUL, + olsc = 0x010000000000003EUL, }; class EmbeddedBoot2 { diff --git a/stratosphere/pm/source/pm_debug_monitor.cpp b/stratosphere/pm/source/pm_debug_monitor.cpp index e9818911e..95362c1ea 100644 --- a/stratosphere/pm/source/pm_debug_monitor.cpp +++ b/stratosphere/pm/source/pm_debug_monitor.cpp @@ -41,6 +41,11 @@ Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 case Dmnt_Cmd_5X_EnableDebugForApplication: rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_application>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; + case Dmnt_Cmd_6X_DisableDebug: + if (kernelAbove600()) { + rc = WrapIpcCommandImpl<&DebugMonitorService::disable_debug>(this, r, out_c, pointer_buffer, pointer_buffer_size); + } + break; case Dmnt_Cmd_5X_AtmosphereGetProcessHandle: rc = WrapIpcCommandImpl<&DebugMonitorService::get_process_handle>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; @@ -141,6 +146,11 @@ std::tuple<Result, CopiedHandle> DebugMonitorService::enable_debug_for_applicati return {rc, h}; } + +std::tuple<Result> DebugMonitorService::disable_debug(u32 which) { + return {Registration::DisableDebug(which)}; +} + std::tuple<Result, CopiedHandle> DebugMonitorService::get_process_handle(u64 pid) { std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid); if(proc == NULL) { diff --git a/stratosphere/pm/source/pm_debug_monitor.hpp b/stratosphere/pm/source/pm_debug_monitor.hpp index a6ae9ca8b..ee6c66b12 100644 --- a/stratosphere/pm/source/pm_debug_monitor.hpp +++ b/stratosphere/pm/source/pm_debug_monitor.hpp @@ -39,6 +39,8 @@ enum DmntCmd_5X { Dmnt_Cmd_5X_EnableDebugForTitleId = 3, Dmnt_Cmd_5X_GetApplicationProcessId = 4, Dmnt_Cmd_5X_EnableDebugForApplication = 5, + + Dmnt_Cmd_6X_DisableDebug = 6, Dmnt_Cmd_5X_AtmosphereGetProcessHandle = 65000 }; @@ -61,6 +63,7 @@ class DebugMonitorService final : public IServiceObject { std::tuple<Result, CopiedHandle> enable_debug_for_tid(u64 tid); std::tuple<Result, u64> get_application_process_id(); std::tuple<Result, CopiedHandle> enable_debug_for_application(); + std::tuple<Result> disable_debug(u32 which); /* Atmosphere commands. */ std::tuple<Result, CopiedHandle> get_process_handle(u64 pid); diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 24ef034eb..04200ba15 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -45,15 +45,15 @@ extern "C" { void __libnx_initheap(void) { - void* addr = nx_inner_heap; - size_t size = nx_inner_heap_size; + void* addr = nx_inner_heap; + size_t size = nx_inner_heap_size; - /* Newlib */ - extern char* fake_heap_start; - extern char* fake_heap_end; + /* Newlib */ + extern char* fake_heap_start; + extern char* fake_heap_end; - fake_heap_start = (char*)addr; - fake_heap_end = (char*)addr + size; + fake_heap_start = (char*)addr; + fake_heap_end = (char*)addr + size; } void __appInit(void) { @@ -142,6 +142,6 @@ int main(int argc, char **argv) /* Cleanup. */ delete server_manager; - return 0; + return 0; } diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index 63c7fbd39..4e3c8cfff 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -480,3 +480,13 @@ Result Registration::EnableDebugForApplication(Handle *out) { *out = g_debug_application_event->get_handle(); return 0; } + +Result Registration::DisableDebug(u32 which) { + if (which & 1) { + g_debug_on_launch_tid = 0; + } + if (which & 2) { + g_debug_next_application = false; + } + return 0; +} diff --git a/stratosphere/pm/source/pm_registration.hpp b/stratosphere/pm/source/pm_registration.hpp index 6749b4c8c..6f0459124 100644 --- a/stratosphere/pm/source/pm_registration.hpp +++ b/stratosphere/pm/source/pm_registration.hpp @@ -133,20 +133,20 @@ enum { }; enum { - PROCESSEVENTTYPE_CRASH = 1, - PROCESSEVENTTYPE_EXIT = 2, // only fired once, when process enters DebugDetached state (likely creport related) - PROCESSEVENTTYPE_RUNNING = 3, // debug detached or running - PROCESSEVENTTYPE_SUSPENDED = 4, // debug suspended - PROCESSEVENTTYPE_DEBUGDETACHED = 5, + PROCESSEVENTTYPE_CRASH = 1, + PROCESSEVENTTYPE_EXIT = 2, // only fired once, when process enters DebugDetached state (likely creport related) + PROCESSEVENTTYPE_RUNNING = 3, // debug detached or running + PROCESSEVENTTYPE_SUSPENDED = 4, // debug suspended + PROCESSEVENTTYPE_DEBUGDETACHED = 5, - PROCESSEVENTTYPE_500_EXIT = 1, - PROCESSEVENTTYPE_500_DEBUGDETACHED = 2, // only fired once, when process enters DebugDetached state (likely creport related) - PROCESSEVENTTYPE_500_CRASH = 3, - PROCESSEVENTTYPE_500_RUNNING = 4, // debug detached or running - PROCESSEVENTTYPE_500_SUSPENDED = 5, // debug suspended + PROCESSEVENTTYPE_500_EXIT = 1, + PROCESSEVENTTYPE_500_DEBUGDETACHED = 2, // only fired once, when process enters DebugDetached state (likely creport related) + PROCESSEVENTTYPE_500_CRASH = 3, + PROCESSEVENTTYPE_500_RUNNING = 4, // debug detached or running + PROCESSEVENTTYPE_500_SUSPENDED = 5, // debug suspended }; - + class Registration { public: struct TidSid { @@ -189,6 +189,7 @@ class Registration { static void GetProcessEventType(u64 *out_pid, u64 *out_type); static Result EnableDebugForTitleId(u64 tid, Handle *out); static Result EnableDebugForApplication(Handle *out); + static Result DisableDebug(u32 which); static Handle GetDebugTitleEventHandle(); static Handle GetDebugApplicationEventHandle(); diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index af338337f..97c699221 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -55,10 +55,17 @@ static u64 g_resource_limits_4x[3][5] = { {0x0, 0x60, 0x0, 0x20, 0x5}, }; +/* 6.x boosted the number of events and sessions that system modules are allowed to make. */ +static u64 g_resource_limits_6x[3][5] = { + {0x0, 0x260, 0x2BC, 0x80, 0x37E}, + {0x0, 0x60, 0x0, 0x20, 0x1}, + {0x0, 0x60, 0x0, 0x20, 0x5}, +}; + static Handle g_resource_limit_handles[3] = {0}; -static u64 g_memory_resource_limits[5][3] = {0}; +static u64 g_memory_resource_limits[6][3] = {0}; static u64 g_resource_limits[3][5] = {0}; static int g_memory_limit_type; static u64 g_system_boost_size = 0; @@ -89,44 +96,7 @@ static Result SetNewMemoryResourceLimit(ResourceLimitUtils::ResourceLimitCategor } void ResourceLimitUtils::InitializeLimits() { - /* Set global aliases. */ - if (kernelAbove400()) { - memcpy(&g_memory_resource_limits, &g_memory_resource_limits_4x, sizeof(g_memory_resource_limits)); - memcpy(&g_resource_limits, &g_resource_limits_4x, sizeof(g_resource_limits)); - } else { - memcpy(&g_memory_resource_limits, &g_memory_resource_limits_deprecated, sizeof(g_memory_resource_limits)); - memcpy(&g_resource_limits, &g_resource_limits_deprecated, sizeof(g_resource_limits)); - } - /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */ - for (unsigned int i = 0; i < 5; i++) { - g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - } - /* Get memory limits. */ - u64 memory_arrangement; - if (R_FAILED(splGetConfig(SplConfigItem_MemoryArrange, &memory_arrangement))) { - /* TODO: panic. */ - } - memory_arrangement &= 0x3F; - switch (memory_arrangement) { - case 2: - g_memory_limit_type = 1; - break; - case 3: - g_memory_limit_type = 2; - break; - case 17: - g_memory_limit_type = 3; - break; - case 18: - g_memory_limit_type = 4; - break; - default: - g_memory_limit_type = 0; - break; - } - - /* Create resource limits. */ + /* Create Resource Limits. */ for (unsigned int i = 0; i < 3; i++) { if (i > 0) { if (R_FAILED(svcCreateResourceLimit(&g_resource_limit_handles[i]))) { @@ -139,7 +109,85 @@ void ResourceLimitUtils::InitializeLimits() { } g_resource_limit_handles[i] = (Handle)out; } + } + /* Set global aliases. */ + if (kernelAbove600()) { + /* 6.0.0 did away with hardcoded memory resource limit values. */ + memcpy(&g_resource_limits, &g_resource_limits_6x, sizeof(g_resource_limits)); + } else if (kernelAbove400()) { + memcpy(&g_memory_resource_limits, &g_memory_resource_limits_4x, sizeof(g_memory_resource_limits_4x)); + memcpy(&g_resource_limits, &g_resource_limits_4x, sizeof(g_resource_limits)); + } else { + memcpy(&g_memory_resource_limits, &g_memory_resource_limits_deprecated, sizeof(g_memory_resource_limits_deprecated)); + memcpy(&g_resource_limits, &g_resource_limits_deprecated, sizeof(g_resource_limits)); + } + + if (kernelAbove600()) { + /* NOTE: 5 is a fake type, official code does not do this. */ + /* This is done for ease of backwards compatibility. */ + g_memory_limit_type = 5; + /* Starting 6.x, 5 MB of memory is always reserved for system. */ + const u64 reserved_system_size_6x = 0x500000; + + /* Get total memory available. */ + u64 total_memory = 0; + if (R_FAILED(svcGetResourceLimitLimitValue(&total_memory, g_resource_limit_handles[0], LimitableResource_Memory))) { + /* TODO: Panic. */ + } + + /* Get and save application + applet memory. */ + if (R_FAILED(svcGetSystemInfo(&g_memory_resource_limits[g_memory_limit_type][1], 0, 0, 0)) || + R_FAILED(svcGetSystemInfo(&g_memory_resource_limits[g_memory_limit_type][2], 0, 0, 1))) { + /* TODO: Panic. */ + } + + const u64 application_size = g_memory_resource_limits[g_memory_limit_type][1]; + const u64 applet_size = g_memory_resource_limits[g_memory_limit_type][2]; + const u64 reserved_nonsys_size = (application_size + applet_size + reserved_system_size_6x); + + /* Ensure there's enough memory for system region. */ + if (reserved_nonsys_size > total_memory) { + /* TODO: Panic. */ + } + + /* Set System memory. */ + g_memory_resource_limits[g_memory_limit_type][0] = total_memory - (reserved_nonsys_size); + } else { + /* Get memory limits. */ + u64 memory_arrangement; + if (R_FAILED(splGetConfig(SplConfigItem_MemoryArrange, &memory_arrangement))) { + /* TODO: panic. */ + } + memory_arrangement &= 0x3F; + switch (memory_arrangement) { + case 2: + g_memory_limit_type = 1; + break; + case 3: + g_memory_limit_type = 2; + break; + case 17: + g_memory_limit_type = 3; + break; + case 18: + g_memory_limit_type = 4; + break; + default: + g_memory_limit_type = 0; + break; + } + } + + /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */ + for (unsigned int i = 0; i < 6; i++) { + g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + } + + /* Set resource limits. */ + for (unsigned int i = 0; i < 3; i++) { + g_resource_limits[i][LimitableResource_Memory] = g_memory_resource_limits[g_memory_limit_type][i]; if (R_FAILED(SetResourceLimits((ResourceLimitCategory)i, g_memory_resource_limits[g_memory_limit_type][i]))) { /* TODO: Panic. */ } From fa0e9061299eff22095923125ba82ca118e2b5d2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 8 Sep 2018 23:51:52 -0700 Subject: [PATCH 076/489] exosphere: Add support for 6.0.0. --- exosphere/src/bootup.c | 26 +++++++++++-- exosphere/src/bootup.h | 2 + exosphere/src/exocfg.h | 3 +- exosphere/src/lp0.c | 5 ++- exosphere/src/masterkey.c | 6 ++- exosphere/src/masterkey.h | 7 ++-- exosphere/src/mc.c | 38 +++++++++++-------- exosphere/src/mc.h | 1 + exosphere/src/package2.c | 78 ++++++++++++++++++++++++++++++--------- exosphere/src/package2.h | 1 + exosphere/src/smc_api.c | 1 + exosphere/src/smc_user.c | 41 +++++++++++++++++--- exosphere/src/titlekey.c | 26 ++++++++++--- exosphere/src/titlekey.h | 3 ++ exosphere/src/utils.c | 7 ++-- 15 files changed, 186 insertions(+), 59 deletions(-) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 2ea2e7077..8709fd03c 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -46,6 +46,23 @@ static bool g_has_booted_up = false; + +void setup_dram_magic_numbers(void) { + /* TODO: Why does these DRAM write occur? */ + unsigned int target_fw = exosphere_get_target_firmware(); + if (EXOSPHERE_TARGET_FIRMWARE_400 <= target_fw) { + (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; + flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000); + if (EXOSPHERE_TARGET_FIRMWARE_600 <= target_fw) { + (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; + (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002; + (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; + flush_dcache_range((void *)0x8005FF00, (void *)0x8005FF0C); + } + } + __dsb_sy(); +} + void bootup_misc_mmio(void) { /* Initialize Fuse registers. */ fuse_init(); @@ -66,10 +83,8 @@ void bootup_misc_mmio(void) { se_generate_random_key(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY); se_generate_srk(KEYSLOT_SWITCH_SRKGENKEY); - /* TODO: Why does this DRAM write occur? */ - if (!g_has_booted_up && exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { - /* 4.x writes this magic number into DRAM. Why? */ - (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; + if (!g_has_booted_up && EXOSPHERE_TARGET_FIRMWARE_600 > exosphere_get_target_firmware() && exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + setup_dram_magic_numbers(); } /* Todo: What? */ @@ -219,6 +234,9 @@ void bootup_misc_mmio(void) { } void setup_4x_mmio(void) { + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + configure_gpu_ucode_carveout(); + } /* TODO: What are these MC reg writes? */ MAKE_MC_REG(0x65C) = 0xFFFFF000; MAKE_MC_REG(0x660) = 0; diff --git a/exosphere/src/bootup.h b/exosphere/src/bootup.h index c9169e5a5..43f35441f 100644 --- a/exosphere/src/bootup.h +++ b/exosphere/src/bootup.h @@ -102,6 +102,8 @@ void bootup_misc_mmio(void); void setup_4x_mmio(void); +void setup_dram_magic_numbers(void); + void setup_current_core_state(void); void identity_unmap_iram_cd_tzram(void); diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 786abf36b..5ed924b48 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -32,9 +32,10 @@ #define EXOSPHERE_TARGET_FIRMWARE_300 3 #define EXOSPHERE_TARGET_FIRMWARE_400 4 #define EXOSPHERE_TARGET_FIRMWARE_500 5 +#define EXOSPHERE_TARGET_FIRMWARE_600 6 /* TODO: What should this be, for release? */ -#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_500 +#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_600 #define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1 #define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c index e7de872ab..e6e19d3bf 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/lp0.c @@ -244,12 +244,13 @@ void save_se_and_power_down_cpu(void) { /* TODO: uart_log("OYASUMI"); */ } - __dsb_sy(); - finalize_powerdown(); } uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argument) { + /* TODO: 6.0.0 introduces heavy deja vu mitigations. */ + /* Exosphere may want to implement these. */ + /* Ensure SMC call is to enter deep sleep. */ if ((power_state & 0x17FFF) != 0x1001B) { return 0xFFFFFFFD; diff --git a/exosphere/src/masterkey.c b/exosphere/src/masterkey.c index d7cbaa764..89e175267 100644 --- a/exosphere/src/masterkey.c +++ b/exosphere/src/masterkey.c @@ -39,6 +39,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = {0x97, 0x29, 0xB0, 0x32, 0x43, 0x14, 0x8C, 0xA6, 0x85, 0xE9, 0x5A, 0x94, 0x99, 0x39, 0xAC, 0x5D}, /* Master key 01 encrypted with Master key 02. */ {0x2C, 0xCA, 0x9C, 0x31, 0x1E, 0x07, 0xB0, 0x02, 0x97, 0x0A, 0xD8, 0x03, 0xA2, 0x76, 0x3F, 0xA3}, /* Master key 02 encrypted with Master key 03. */ {0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ + {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ }; /* Retail unit keys. */ @@ -49,6 +50,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = {0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72}, /* Master key 01 encrypted with Master key 02. */ {0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */ {0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ + {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ }; bool check_mkey_revision(unsigned int revision, bool is_retail) { @@ -121,7 +123,7 @@ unsigned int mkey_get_keyslot(unsigned int revision) { void set_old_devkey(unsigned int revision, const uint8_t *key) { - if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_500_CURRENT <= revision) { + if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_600_CURRENT <= revision) { generic_panic(); } @@ -138,7 +140,7 @@ unsigned int devkey_get_keyslot(unsigned int revision) { } if (revision >= 1) { - if (revision == MASTERKEY_REVISION_500_CURRENT) { + if (revision == MASTERKEY_REVISION_600_CURRENT) { return KEYSLOT_SWITCH_DEVICEKEY; } else { /* Load into a temp keyslot. */ diff --git a/exosphere/src/masterkey.h b/exosphere/src/masterkey.h index 8c445aaf6..0ca987ee0 100644 --- a/exosphere/src/masterkey.h +++ b/exosphere/src/masterkey.h @@ -19,14 +19,15 @@ /* This is glue code to enable master key support across versions. */ -/* TODO: Update to 0x6 on release of new master key. */ -#define MASTERKEY_REVISION_MAX 0x5 +/* TODO: Update to 0x7 on release of new master key. */ +#define MASTERKEY_REVISION_MAX 0x6 #define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_300 0x01 #define MASTERKEY_REVISION_301_302 0x02 #define MASTERKEY_REVISION_400_410 0x03 -#define MASTERKEY_REVISION_500_CURRENT 0x04 +#define MASTERKEY_REVISION_500_510 0x04 +#define MASTERKEY_REVISION_600_CURRENT 0x05 #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) diff --git a/exosphere/src/mc.c b/exosphere/src/mc.c index d4234e077..97c9e5e45 100644 --- a/exosphere/src/mc.c +++ b/exosphere/src/mc.c @@ -38,6 +38,26 @@ volatile security_carveout_t *get_carveout_by_id(unsigned int carveout) { return NULL; } +void configure_gpu_ucode_carveout(void) { + /* Starting in 6.0.0, Carveout 2 is configured later on. */ + /* This is a helper function to make this easier... */ + volatile security_carveout_t *carveout = get_carveout_by_id(2); + carveout->paddr_low = 0x80020000; + carveout->paddr_high = 0; + carveout->size_big_pages = 2; /* 0x40000 */ + carveout->flags_0 = 0; + carveout->flags_1 = 0; + carveout->flags_2 = 0x3000000; + carveout->flags_3 = 0; + carveout->flags_4 = 0x300; + carveout->flags_5 = 0; + carveout->flags_6 = 0; + carveout->flags_7 = 0; + carveout->flags_8 = 0; + carveout->flags_9 = 0; + carveout->allowed_clients = 0x440167E; +} + void configure_default_carveouts(void) { /* Configure Carveout 1 (UNUSED) */ volatile security_carveout_t *carveout = get_carveout_by_id(1); @@ -57,21 +77,9 @@ void configure_default_carveouts(void) { carveout->allowed_clients = 0x04000006; /* Configure Carveout 2 (GPU UCODE) */ - carveout = get_carveout_by_id(2); - carveout->paddr_low = 0x80020000; - carveout->paddr_high = 0; - carveout->size_big_pages = 2; /* 0x40000 */ - carveout->flags_0 = 0; - carveout->flags_1 = 0; - carveout->flags_2 = 0x3000000; - carveout->flags_3 = 0; - carveout->flags_4 = 0x300; - carveout->flags_5 = 0; - carveout->flags_6 = 0; - carveout->flags_7 = 0; - carveout->flags_8 = 0; - carveout->flags_9 = 0; - carveout->allowed_clients = 0x440167E; + if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600) { + configure_gpu_ucode_carveout(); + } /* Configure Carveout 3 (UNUSED GPU) */ carveout = get_carveout_by_id(3); diff --git a/exosphere/src/mc.h b/exosphere/src/mc.h index b399e304e..22d8a971a 100644 --- a/exosphere/src/mc.h +++ b/exosphere/src/mc.h @@ -79,6 +79,7 @@ typedef struct { volatile security_carveout_t *get_carveout_by_id(unsigned int carveout); void configure_default_carveouts(void); +void configure_gpu_ucode_carveout(void); void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint64_t size); diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 5d6a20add..afc35dd93 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -38,20 +38,31 @@ extern void *__start_cold_addr; extern size_t __bin_size; + +static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { + {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ + {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */ + {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4} /* 6.x New Device Key Source. */ +}; + +static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { + {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */ + {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */ + {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF} /* 6.x New Device Keygen Source. */ +}; + +static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { + {0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */ + {0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */ + {0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5} /* 6.x New Device Keygen Source. */ +}; + static void derive_new_device_keys(unsigned int keygen_keyslot) { uint8_t work_buffer[0x10]; - static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { - {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ - {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C} /* 5.x New Device Key Source. */ - }; - - static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { - {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */ - {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E} /* 5.x New Device Keygen Source. */ - }; + bool is_retail = configitem_is_retail(); for (unsigned int revision = 0; revision < MASTERKEY_NUM_NEW_DEVICE_KEYS; revision++) { se_aes_ecb_decrypt_block(keygen_keyslot, work_buffer, 0x10, new_device_key_sources[revision], 0x10); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, mkey_get_keyslot(0), new_device_keygen_sources[revision], 0x10); + decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, mkey_get_keyslot(0), is_retail ? new_device_keygen_sources[revision] : new_device_keygen_sources_dev[revision], 0x10); if (revision < MASTERKEY_NUM_NEW_DEVICE_KEYS - 1) { se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10, work_buffer, 0x10); set_old_devkey(revision + MASTERKEY_REVISION_400_410, work_buffer); @@ -110,6 +121,7 @@ static void setup_se(void) { derive_new_device_keys(KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY); break; case EXOSPHERE_TARGET_FIRMWARE_500: + case EXOSPHERE_TARGET_FIRMWARE_600: derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY); break; } @@ -136,14 +148,18 @@ static void setup_boot_config(void) { if (configitem_is_retail()) { bootconfig_clear(); } else { - flush_dcache_range((uint8_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER, (uint8_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER + sizeof(bootconfig_t)); - bootconfig_load_and_verify((bootconfig_t *)NX_BOOTLOADER_BOOTCONFIG_POINTER); + void *bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER; + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER_6X; + } + flush_dcache_range((uint8_t *)bootconfig_ptr, (uint8_t *)bootconfig_ptr + sizeof(bootconfig_t)); + bootconfig_load_and_verify((bootconfig_t *)bootconfig_ptr); } } static void package2_crypt_ctr(unsigned int master_key_rev, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { /* Derive package2 key. */ - const uint8_t package2_key_source[0x10] = {0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7}; + static const uint8_t package2_key_source[0x10] = {0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7}; flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + dst_size); flush_dcache_range((uint8_t *)src, (uint8_t *)src + src_size); unsigned int keyslot = mkey_get_keyslot(master_key_rev); @@ -399,7 +415,22 @@ static void load_package2_sections(package2_meta_t *metadata, uint32_t master_ke } static void copy_warmboot_bin_to_dram() { - uint8_t *warmboot_src = (uint8_t *)0x4003B000; + uint8_t *warmboot_src; + switch (exosphere_get_target_firmware()) { + case EXOSPHERE_TARGET_FIRMWARE_100: + case EXOSPHERE_TARGET_FIRMWARE_200: + case EXOSPHERE_TARGET_FIRMWARE_300: + default: + generic_panic(); + break; + case EXOSPHERE_TARGET_FIRMWARE_400: + case EXOSPHERE_TARGET_FIRMWARE_500: + warmboot_src = (uint8_t *)0x4003B000; + break; + case EXOSPHERE_TARGET_FIRMWARE_600: + warmboot_src = (uint8_t *)0x4003D800; + break; + } uint8_t *warmboot_dst = (uint8_t *)0x8000D000; const size_t warmboot_size = 0x2000; @@ -448,8 +479,18 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { MAKE_REG32(PMC_BASE + 0x054) = 0x8000D000; MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF; MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE; - MAKE_REG32(PMC_BASE + 0x334) |= 0x10; - MAKE_REG32(PMC_BASE + 0x360) = 6; + MAKE_REG32(PMC_BASE + 0x334) |= 0x10; + switch (exosphere_get_target_firmware()) { + case EXOSPHERE_TARGET_FIRMWARE_400: + MAKE_REG32(PMC_BASE + 0x360) = 5; + break; + case EXOSPHERE_TARGET_FIRMWARE_500: + MAKE_REG32(PMC_BASE + 0x360) = 6; + break; + case EXOSPHERE_TARGET_FIRMWARE_600: + MAKE_REG32(PMC_BASE + 0x360) = 0x87; + break; + } } wait(1000); @@ -465,7 +506,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { randomcache_init(); /* memclear the initial copy of Exosphere running in IRAM (relocated to TZRAM by earlier code). */ - memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); + //memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); /* Let NX Bootloader know that we're running. */ MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 1; @@ -490,6 +531,9 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { sync_with_nx_bootloader(NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X); copy_warmboot_bin_to_dram(); + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + setup_dram_magic_numbers(); + } sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X); } else { sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2); diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h index 66f4494a7..ec0dfba3e 100644 --- a/exosphere/src/package2.h +++ b/exosphere/src/package2.h @@ -50,6 +50,7 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) { #define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10ULL) #define NX_BOOTLOADER_BOOTCONFIG_POINTER ((void *)(0x4003D000ull)) +#define NX_BOOTLOADER_BOOTCONFIG_POINTER_6X ((void *)(0x4003F800ull)) #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index ca1d49d36..f391dc539 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -158,6 +158,7 @@ void set_version_specific_smcs(void) { /* Do nothing. */ break; case EXOSPHERE_TARGET_FIRMWARE_500: + case EXOSPHERE_TARGET_FIRMWARE_600: /* No more LoadSecureExpModKey. */ g_smc_user_table[0xE].handler = NULL; g_smc_user_table[0xC].id = 0xC300D60C; diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c index acf21ebe1..c2b1fbecb 100644 --- a/exosphere/src/smc_user.c +++ b/exosphere/src/smc_user.c @@ -40,6 +40,20 @@ static uint8_t g_imported_exponents[4][0x100]; static uint8_t g_rsausecase_to_cryptousecase[5] = {1, 2, 3, 5, 6}; +static bool is_user_keyslot_valid(unsigned int keyslot) { + switch (exosphere_get_target_firmware()) { + case EXOSPHERE_TARGET_FIRMWARE_100: + case EXOSPHERE_TARGET_FIRMWARE_200: + case EXOSPHERE_TARGET_FIRMWARE_300: + case EXOSPHERE_TARGET_FIRMWARE_400: + case EXOSPHERE_TARGET_FIRMWARE_500: + return keyslot <= 3; + case EXOSPHERE_TARGET_FIRMWARE_600: + default: + return keyslot <= 5; + } +} + void set_exp_mod_done(bool done) { g_exp_mod_done = done; } @@ -152,7 +166,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) { /* 5.0.0+ Bounds checking. */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { if (is_personalized) { - if (master_key_rev > MASTERKEY_REVISION_500_CURRENT || ((1 << (master_key_rev + 1)) & 0x33) == 0) { + if (master_key_rev > MASTERKEY_REVISION_600_CURRENT || ((1 << (master_key_rev + 1)) & 0x73) == 0) { return 2; } if (mask_id > 3 || usecase >= CRYPTOUSECASE_MAX_5X) { @@ -238,7 +252,7 @@ uint32_t user_load_aes_key(smc_args_t *args) { uint64_t wrapped_key[2]; uint32_t keyslot = (uint32_t)args->X[1]; - if (keyslot > 3) { + if (!is_user_keyslot_valid(keyslot)) { return 2; } @@ -278,6 +292,10 @@ uint32_t crypt_aes_done_handler(void) { uint32_t user_crypt_aes(smc_args_t *args) { uint32_t keyslot = args->X[1] & 3; uint32_t mode = (args->X[1] >> 4) & 3; + + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + keyslot = args->X[1] & 7; + } uint64_t iv_ctr[2]; iv_ctr[0] = args->X[2]; @@ -287,7 +305,7 @@ uint32_t user_crypt_aes(smc_args_t *args) { uint32_t out_ll_paddr = (uint32_t)(args->X[5]); size_t size = args->X[6]; - if (size & 0xF) { + if (!is_user_keyslot_valid(keyslot) || size & 0xF) { return 2; } @@ -406,7 +424,7 @@ uint32_t user_compute_cmac(smc_args_t *args) { upage_ref_t page_ref; /* Validate keyslot and size. */ - if (keyslot > 3 || args->X[3] > 0x400) { + if (!is_user_keyslot_valid(keyslot) || args->X[3] > 0x400) { return 2; } @@ -642,7 +660,16 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) { void *user_wrapped_key = (void *)args->X[1]; void *user_modulus = (void *)args->X[2]; - unsigned int master_key_rev = (unsigned int)args->X[7]; + unsigned int option = (unsigned int)args->X[7]; + unsigned int master_key_rev; + unsigned int titlekey_type; + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + master_key_rev = option & 0x3F; + titlekey_type = (option >> 6) & 1; + } else { + master_key_rev = option; + titlekey_type = 0; + } if(master_key_rev > 0) { master_key_rev -= 1; @@ -673,6 +700,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) { tkey_set_expected_label_hash(&args->X[3]); tkey_set_master_key_rev(master_key_rev); + tkey_set_type(titlekey_type); /* Hardcode RSA keyslot 0. */ set_rsa_keyslot(0, modulus, 0x100, g_imported_exponents[0], 0x100); @@ -686,7 +714,7 @@ uint32_t user_load_titlekey(smc_args_t *args) { uint64_t sealed_titlekey[2]; uint32_t keyslot = (uint32_t)args->X[1]; - if (keyslot > 3) { + if (!is_user_keyslot_valid(keyslot)) { return 2; } @@ -721,6 +749,7 @@ uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) { } tkey_set_master_key_rev(master_key_rev); + tkey_set_type(0); tkey_aes_unwrap(titlekey, 0x10, aes_wrapped_titlekey, 0x10); seal_titlekey(sealed_titlekey, 0x10, titlekey, 0x10); diff --git a/exosphere/src/titlekey.c b/exosphere/src/titlekey.c index 3b6d957a8..b5a35b6f5 100644 --- a/exosphere/src/titlekey.c +++ b/exosphere/src/titlekey.c @@ -19,6 +19,7 @@ #include "utils.h" #include "arm.h" +#include "exocfg.h" #include "titlekey.h" #include "masterkey.h" @@ -26,6 +27,7 @@ static uint64_t g_tkey_expected_label_hash[4]; static unsigned int g_tkey_master_key_rev = MASTERKEY_REVISION_MAX; +static unsigned int g_tkey_type = 0; /* Set the expected db prefix. */ void tkey_set_expected_label_hash(uint64_t *label_hash) { @@ -41,6 +43,17 @@ void tkey_set_master_key_rev(unsigned int master_key_rev) { g_tkey_master_key_rev = master_key_rev; } +static void tkey_validate_type(unsigned int type) { + if (type > TITLEKEY_TYPE_MAX || (type > 0 && exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600)) { + generic_panic(); + } +} + +void tkey_set_type(unsigned int type) { + tkey_validate_type(type); + g_tkey_type = type; +} + /* Reference for MGF1 can be found here: https://en.wikipedia.org/wiki/Mask_generation_function#MGF1 */ void calculate_mgf1_and_xor(void *masked, size_t masked_size, const void *seed, size_t seed_size) { uint8_t cur_hash[0x20]; @@ -152,18 +165,19 @@ size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_si return wrapped_titlekey_size; } +static const uint8_t titlekek_sources[TITLEKEY_TYPE_MAX+1][0x10] = { + {0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B}, + {0x3B, 0x78, 0xF2, 0x61, 0x0F, 0x9D, 0x5A, 0xE2, 0x7B, 0x4E, 0x45, 0xAF, 0xCB, 0x0B, 0x67, 0x4D} +}; + void tkey_aes_unwrap(void *dst, size_t dst_size, const void *src, size_t src_size) { if (g_tkey_master_key_rev >= MASTERKEY_REVISION_MAX || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } - - const uint8_t titlekek_source[0x10] = { - 0x1E, 0xDC, 0x7B, 0x3B, 0x60, 0xE6, 0xB4, 0xD8, 0x78, 0xB8, 0x17, 0x15, 0x98, 0x5E, 0x62, 0x9B - }; - + /* Generate the appropriate titlekek into keyslot 9. */ unsigned int master_keyslot = mkey_get_keyslot(g_tkey_master_key_rev); - decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_source, 0x10); + decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, master_keyslot, titlekek_sources[g_tkey_type], 0x10); /* Unwrap the titlekey using the titlekek. */ se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, dst, 0x10, src, 0x10); diff --git a/exosphere/src/titlekey.h b/exosphere/src/titlekey.h index bfcf95d44..8b4593911 100644 --- a/exosphere/src/titlekey.h +++ b/exosphere/src/titlekey.h @@ -19,8 +19,11 @@ #include <stdint.h> +#define TITLEKEY_TYPE_MAX 0x1 + void tkey_set_expected_label_hash(uint64_t *label_hash); void tkey_set_master_key_rev(unsigned int master_key_rev); +void tkey_set_type(unsigned int type); size_t tkey_rsa_oaep_unwrap(void *dst, size_t dst_size, void *src, size_t src_size); diff --git a/exosphere/src/utils.c b/exosphere/src/utils.c index e2b421071..a01243e8a 100644 --- a/exosphere/src/utils.c +++ b/exosphere/src/utils.c @@ -30,14 +30,15 @@ __attribute__ ((noreturn)) void panic(uint32_t code) { APBDEV_PMC_SCRATCH200_0 = code; } - /* Uncomment for Debugging. + /* // Uncomment for Debugging. uint64_t temp_reg; MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM)) = APBDEV_PMC_SCRATCH200_0; SAVE_SYSREG64(ESR_EL3, 0x10); SAVE_SYSREG64(ELR_EL3, 0x18); SAVE_SYSREG64(FAR_EL3, 0x20); MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; + */ /* TODO: Custom Panic Driver, which displays to screen without rebooting. */ /* For now, just use NX BOOTLOADER's panic. */ @@ -48,7 +49,7 @@ __attribute__ ((noreturn)) void panic(uint32_t code) { } __attribute__ ((noreturn)) void generic_panic(void) { - /* Uncomment for Debugging. + /* //Uncomment for Debugging. uint64_t temp_reg; do { __asm__ __volatile__ ("mov %0, LR" : "=r"(temp_reg) :: "memory"); } while (false); MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_DEBUG_IRAM) + 0x28) = (uint32_t)((temp_reg >> 0) & 0xFFFFFFFFULL); From 0cad1935dd6fe2178328d9412d3f3402b682c69a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 9 Sep 2018 07:04:16 -0700 Subject: [PATCH 077/489] libstratosphere: Fix condvar wrapper primitives --- .../include/stratosphere/hossynch.hpp | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp index 56facd130..b923a4ec1 100644 --- a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp @@ -20,61 +20,75 @@ class HosMutex { private: Mutex m; + Mutex *GetMutex() { + return &this->m; + } public: HosMutex() { - mutexInit(&this->m); + mutexInit(GetMutex()); } void lock() { - mutexLock(&this->m); + mutexLock(GetMutex()); } void unlock() { - mutexUnlock(&this->m); + mutexUnlock(GetMutex()); } bool try_lock() { - return mutexTryLock(&this->m); + return mutexTryLock(GetMutex()); } + + friend class HosCondVar; }; class HosRecursiveMutex { private: RMutex m; + RMutex *GetMutex() { + return &this->m; + } public: HosRecursiveMutex() { - rmutexInit(&this->m); + rmutexInit(GetMutex()); } void lock() { - rmutexLock(&this->m); + rmutexLock(GetMutex()); } void unlock() { - rmutexUnlock(&this->m); + rmutexUnlock(GetMutex()); } bool try_lock() { - return rmutexTryLock(&this->m); + return rmutexTryLock(GetMutex()); } }; class HosCondVar { private: CondVar cv; - Mutex m; public: HosCondVar() { - mutexInit(&m); condvarInit(&cv); } - Result WaitTimeout(u64 timeout) { - return condvarWaitTimeout(&cv, &m, timeout); + Result WaitTimeout(u64 timeout, HosMutex *hm) { + return WaitTimeout(timeout, hm->GetMutex()); } - Result Wait() { - return condvarWait(&cv, &m); + Result Wait(HosMutex *hm) { + return Wait(hm->GetMutex()); + } + + Result WaitTimeout(u64 timeout, Mutex *m) { + return condvarWaitTimeout(&cv, m, timeout); + } + + Result Wait(Mutex *m) { + return condvarWait(&cv, m); } Result Wake(int num) { From d61ec20679f72895bce4a54f15c7b8e729e26040 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 10 Sep 2018 15:54:14 -0700 Subject: [PATCH 078/489] fusee: add fs.mitm kernel patches for 6.0.0 --- fusee/fusee-secondary/src/kernel_patches.c | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index 45a34d92b..f0741350a 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -253,6 +253,60 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_send)[] = {0x2A170 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(500, proc_id_recv)[] = {0x08, 0x5B, 0x41, 0xF9, 0xEA, 0x6F, 0x40, 0xF9, 0xE9, 0x03, 0x15, 0x2A, 0x29, 0xF5, 0x7E, 0xD3}; static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_recv)[] = {0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA}; +/* + stp x10, x11, [sp, #-0x10]! + ldr x11, [sp, #0x68] + mov w10, w21 + lsl x10, x10, #2 + ldr x10, [x11, x10] + mov x9, #0x0000ffffffffffff + and x8, x10, x9 + mov x9, #0xffff000000000000 + and x10, x10, x9 + mov x9, #0xfffe000000000000 + cmp x10, x9 + beq #0x20 + + stp x8, x9, [sp, #-0x10]! + ldr x8, [x24] + ldr x8, [x8, #0x38] + mov x0, x24 + blr x8 + ldp x8, x9, [sp],#0x10 + mov x8, x0 + + ldp x10, x11, [sp],#0x10 + mov x0, x8 +*/ +static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_send)[] = {0x08, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x15, 0x2A, 0xB5, 0x0A, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3}; +static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_send)[] = {0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; +/* + stp x10, x11, [sp, #-0x10]! + ldr x11, [sp, #0x80] + mov w10, w21 + lsl x10, x10, #2 + ldr x10, [x11, x10] + mov x9, #0x0000ffffffffffff + and x8, x10, x9 + mov x9, #0xffff000000000000 + and x10, x10, x9 + mov x9, #0xfffe000000000000 + cmp x10, x9 + beq #0x20 + + stp x8, x9, [sp, #-0x10]! + ldr x8, [x24] + ldr x8, [x8, #0x38] + mov x0, x24 + blr x8 + ldp x8, x9, [sp],#0x10 + mov x8, x0 + + ldp x10, x11, [sp],#0x10 + mov x0, x8 +*/ +static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv)[] = {0x08, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE9, 0x6F, 0x40, 0xF9, 0xE8, 0x03, 0x15, 0x2A, 0xB5, 0x0A, 0x00, 0x11}; +static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_recv)[] = {0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; /* Hook Definitions. */ static const kernel_hook_t g_kernel_hooks_100[] = { @@ -363,6 +417,25 @@ static const kernel_hook_t g_kernel_hooks_500[] = { .payload = MAKE_KERNEL_HOOK_NAME(500, proc_id_recv) } }; +static const kernel_hook_t g_kernel_hooks_600[] = { + { /* Send Message Process ID Patch. */ + .pattern_size = 0x1C, + .pattern = MAKE_KERNEL_PATTERN_NAME(600, proc_id_send), + .pattern_hook_offset = 0x0, + .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(600, proc_id_send))/sizeof(instruction_t), + .branch_back_offset = 0x10, + .payload = MAKE_KERNEL_HOOK_NAME(600, proc_id_send) + }, + { /* Receive Message Process ID Patch. */ + .pattern_size = 0x1C, + .pattern = MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv), + .pattern_hook_offset = 0x0, + .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(600, proc_id_recv))/sizeof(instruction_t), + .branch_back_offset = 0x10, + .payload = MAKE_KERNEL_HOOK_NAME(600, proc_id_recv) + } +}; + #define KERNEL_HOOKS(vers) .num_hooks = sizeof(g_kernel_hooks_##vers)/sizeof(kernel_hook_t), .hooks = g_kernel_hooks_##vers, @@ -397,6 +470,11 @@ static const kernel_info_t g_kernel_infos[] = { .hash = {0xB2, 0x38, 0x61, 0xA8, 0xE1, 0xE2, 0xE4, 0xE4, 0x17, 0x28, 0xED, 0xA9, 0xF6, 0xF6, 0xBD, 0xD2, 0x59, 0xDB, 0x1F, 0xEF, 0x4A, 0x8B, 0x2F, 0x1C, 0x64, 0x46, 0x06, 0x40, 0xF5, 0x05, 0x9C, 0x43}, .free_code_space_offset = 0x5C020, KERNEL_HOOKS(500) + }, + { /* 6.0.0. */ + .hash = {0x85, 0x97, 0x40, 0xF6, 0xC0, 0x3E, 0x3D, 0x44, 0xDE, 0xA4, 0xA0, 0x35, 0xFD, 0x12, 0x9C, 0xD4, 0x4F, 0x9C, 0x36, 0x53, 0x74, 0x54, 0x2C, 0x9C, 0x55, 0x47, 0xC4, 0x25, 0xF1, 0x42, 0xFB, 0x97}, + .free_code_space_offset = 0x5EE00, + KERNEL_HOOKS(600) } }; From 39d812f434671e6cae9bd349b0941a28302306b5 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Sat, 15 Sep 2018 21:08:58 +0100 Subject: [PATCH 079/489] fusee: Move nxboot hand-off to IRAM. fusee/exosphere: Minor cleanup. --- exosphere/src/package2.c | 23 +- exosphere/src/se.c | 328 ++++++++++++---------- exosphere/src/se.h | 18 +- fusee/fusee-primary/src/i2c.c | 6 +- fusee/fusee-primary/src/i2c.h | 12 +- fusee/fusee-primary/src/se.c | 18 +- fusee/fusee-primary/src/se.h | 7 +- fusee/fusee-secondary/linker.ld | 31 +- fusee/fusee-secondary/src/i2c.c | 6 +- fusee/fusee-secondary/src/i2c.h | 12 +- fusee/fusee-secondary/src/init.c | 3 + fusee/fusee-secondary/src/main.c | 3 +- fusee/fusee-secondary/src/nxboot.c | 64 +---- fusee/fusee-secondary/src/nxboot.h | 3 +- fusee/fusee-secondary/src/nxboot_iram.c | 90 ++++++ fusee/fusee-secondary/src/se.c | 18 +- fusee/fusee-secondary/src/se.h | 7 +- fusee/fusee-secondary/src/splash_screen.c | 2 +- fusee/fusee-secondary/src/start.s | 9 + 19 files changed, 370 insertions(+), 290 deletions(-) create mode 100644 fusee/fusee-secondary/src/nxboot_iram.c diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index afc35dd93..6e1620bc1 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -18,7 +18,6 @@ #include "utils.h" #include "memory_map.h" - #include "bootup.h" #include "cpu_context.h" #include "package2.h" @@ -38,7 +37,6 @@ extern void *__start_cold_addr; extern size_t __bin_size; - static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */ @@ -85,15 +83,15 @@ static void setup_se(void) { intr_initialize_gic_nonsecure(); /* Perform some sanity initialization. */ - volatile security_engine_t *p_security_engine = get_security_engine(); - p_security_engine->_0x0 &= 0xFFFEFFFF; /* Clear bit 16. */ - (void)(SECURITY_ENGINE->FLAGS_REG); + volatile tegra_se_t *se = se_get_regs(); + se->_0x0 &= 0xFFFEFFFF; /* Clear bit 16. */ + (void)(se->FLAGS_REG); __dsb_sy(); - p_security_engine->_0x4 = 0; - p_security_engine->AES_KEY_READ_DISABLE_REG = 0; - p_security_engine->RSA_KEY_READ_DISABLE_REG = 0; - p_security_engine->_0x0 &= 0xFFFFFFFB; + se->_0x4 = 0; + se->AES_KEY_READ_DISABLE_REG = 0; + se->RSA_KEY_READ_DISABLE_REG = 0; + se->_0x0 &= 0xFFFFFFFB; /* Currently unknown what each flag does. */ for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { @@ -139,8 +137,7 @@ static void setup_se(void) { set_aes_keyslot_flags(KEYSLOT_SWITCH_SESSIONKEY, 0xFF); /* Generate test vector for our keys. */ - se_generate_stored_vector(); - + se_generate_stored_vector(); } static void setup_boot_config(void) { @@ -169,7 +166,6 @@ static void package2_crypt_ctr(unsigned int master_key_rev, void *dst, size_t ds se_aes_ctr_crypt(KEYSLOT_SWITCH_PACKAGE2KEY, dst, dst_size, src, src_size, ctr, ctr_size); } - static void verify_header_signature(package2_header_t *header) { const uint8_t *modulus; @@ -506,7 +502,8 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { randomcache_init(); /* memclear the initial copy of Exosphere running in IRAM (relocated to TZRAM by earlier code). */ - //memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); + /* memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); */ + /* Let NX Bootloader know that we're running. */ MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 1; diff --git a/exosphere/src/se.c b/exosphere/src/se.c index 058a13735..80cc350ec 100644 --- a/exosphere/src/se.c +++ b/exosphere/src/se.c @@ -36,9 +36,8 @@ static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX]; static bool g_se_generated_vector = false; static uint8_t g_se_stored_test_vector[0x10]; - /* Initialize a SE linked list. */ -void ll_init(se_ll_t *ll, void *buffer, size_t size) { +void ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { ll->num_entries = 0; /* 1 Entry. */ if (buffer != NULL) { @@ -62,7 +61,7 @@ void set_security_engine_callback(unsigned int (*callback)(void)) { /* Fires on Security Engine operation completion. */ void se_operation_completed(void) { - SECURITY_ENGINE->INT_ENABLE_REG = 0; + se_get_regs()->INT_ENABLE_REG = 0; if (g_se_callback != NULL) { g_se_callback(); g_se_callback = NULL; @@ -70,13 +69,14 @@ void se_operation_completed(void) { } void se_check_error_status_reg(void) { - if (SECURITY_ENGINE->ERR_STATUS_REG) { + if (se_get_regs()->ERR_STATUS_REG) { generic_panic(); } } void se_check_for_error(void) { - if (SECURITY_ENGINE->INT_STATUS_REG & 0x10000 || SECURITY_ENGINE->FLAGS_REG & 3 || SECURITY_ENGINE->ERR_STATUS_REG) { + volatile tegra_se_t *se = se_get_regs(); + if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) { generic_panic(); } } @@ -86,12 +86,11 @@ void se_trigger_interrupt(void) { } void se_verify_flags_cleared(void) { - if (SECURITY_ENGINE->FLAGS_REG & 3) { + if (se_get_regs()->FLAGS_REG & 3) { generic_panic(); } } - void se_generate_test_vector(void *vector) { /* TODO: Implement real test vector generation. */ memset(vector, 0, 0x10); @@ -122,23 +121,27 @@ void se_generate_stored_vector(void) { /* Set the flags for an AES keyslot. */ void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Misc flags. */ if (flags & ~0x80) { - SECURITY_ENGINE->AES_KEYSLOT_FLAGS[keyslot] = ~flags; + se->AES_KEYSLOT_FLAGS[keyslot] = ~flags; } /* Disable keyslot reads. */ if (flags & 0x80) { - SECURITY_ENGINE->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); } } /* Set the flags for an RSA keyslot. */ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX) { generic_panic(); } @@ -146,28 +149,32 @@ void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { /* Misc flags. */ if (flags & ~0x80) { /* TODO: Why are flags assigned this way? */ - SECURITY_ENGINE->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; + se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; } /* Disable keyslot reads. */ if (flags & 0x80) { - SECURITY_ENGINE->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); } } void clear_aes_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Zero out the whole keyslot and IV. */ for (unsigned int i = 0; i < 0x10; i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = 0; + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = 0; } } void clear_rsa_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX) { generic_panic(); } @@ -175,40 +182,44 @@ void clear_rsa_keyslot(unsigned int keyslot) { /* Zero out the whole keyslot. */ for (unsigned int i = 0; i < 0x40; i++) { /* Select Keyslot Modulus[i] */ - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = 0; + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; + se->RSA_KEYTABLE_DATA = 0; } for (unsigned int i = 0; i < 0x40; i++) { /* Select Keyslot Expontent[i] */ - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = 0; + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = 0; } } void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { generic_panic(); } for (size_t i = 0; i < (key_size >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = read32le(key, 4 * i); + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = read32le(key, 4 * i); } } void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { generic_panic(); } for (size_t i = 0; i < (modulus_size >> 2); i++) { - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; + se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); } for (size_t i = 0; i < (exp_size >> 2); i++) { - SECURITY_ENGINE->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; - SECURITY_ENGINE->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); } g_se_modulus_sizes[keyslot] = modulus_size; @@ -216,48 +227,56 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_ } void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { generic_panic(); } for (size_t i = 0; i < (iv_size >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = read32le(iv, 4 * i); + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = read32le(iv, 4 * i); } } void clear_aes_keyslot_iv(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } for (size_t i = 0; i < (0x10 >> 2); i++) { - SECURITY_ENGINE->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; - SECURITY_ENGINE->AES_KEYTABLE_DATA = 0; + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = 0; } } void set_se_ctr(const void *ctr) { for (unsigned int i = 0; i < 4; i++) { - SECURITY_ENGINE->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); } } void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSIZE_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); - SECURITY_ENGINE->CRYPTO_REG = keyslot_src << 24; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; - SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; + se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); + se->CRYPTO_REG = keyslot_src << 24; + se->BLOCK_COUNT_REG = 0; + se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; flush_dcache_range(wrapped_key, (const uint8_t *)wrapped_key + wrapped_key_size); trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); } void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, unsigned int crypt_config, bool encrypt, unsigned int (*callback)(void)) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -268,34 +287,34 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, /* Setup Config register. */ if (encrypt) { - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); } else { - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); } /* Setup Crypto register. */ - SECURITY_ENGINE->CRYPTO_REG = crypt_config | (keyslot << 24) | (encrypt << 8); + se->CRYPTO_REG = crypt_config | (keyslot << 24) | (encrypt << 8); /* Mark this encryption as insecure -- this makes the SE not a secure busmaster. */ - SECURITY_ENGINE->CRYPTO_REG |= 0x80000000; + se->CRYPTO_REG |= 0x80000000; /* Appropriate number of blocks. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = (size >> 4) - 1; + se->BLOCK_COUNT_REG = (size >> 4) - 1; /* Set the callback, for after the async operation. */ set_security_engine_callback(callback); /* Enable SE Interrupt firing for async op. */ - SECURITY_ENGINE->INT_ENABLE_REG = 0x10; + se->INT_ENABLE_REG = 0x10; /* Setup Input/Output lists */ - SECURITY_ENGINE->IN_LL_ADDR_REG = in_ll_paddr; - SECURITY_ENGINE->OUT_LL_ADDR_REG = out_ll_paddr; + se->IN_LL_ADDR_REG = in_ll_paddr; + se->OUT_LL_ADDR_REG = out_ll_paddr; /* Set registers for operation. */ - SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG; - SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG; - SECURITY_ENGINE->OPERATION_REG = 1; + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = 1; /* Ensure writes go through. */ __dsb_ish(); @@ -303,7 +322,7 @@ void se_aes_crypt_insecure_internal(unsigned int keyslot, uint32_t out_ll_paddr, void se_aes_ctr_crypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *ctr, unsigned int (*callback)(void)) { /* Unknown what this write does, but official code writes it for CTR mode. */ - SECURITY_ENGINE->_0x80C = 1; + se_get_regs()->SPARE_0 = 1; set_se_ctr(ctr); se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x81E, true, callback); } @@ -318,8 +337,8 @@ void se_aes_cbc_decrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, ui se_aes_crypt_insecure_internal(keyslot, out_ll_paddr, in_ll_paddr, size, 0x66, false, callback); } - void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*callback)(void)) { + volatile tegra_se_t *se = se_get_regs(); uint8_t stack_buf[KEYSIZE_RSA_MAX]; if (keyslot >= KEYSLOT_RSA_MAX || size > KEYSIZE_RSA_MAX) { @@ -331,24 +350,24 @@ void se_exp_mod(unsigned int keyslot, void *buf, size_t size, unsigned int (*cal stack_buf[i] = *((uint8_t *)buf + size - i - 1); } - - SECURITY_ENGINE->CONFIG_REG = (ALG_RSA | DST_RSAREG); - SECURITY_ENGINE->RSA_CONFIG = keyslot << 24; - SECURITY_ENGINE->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; - SECURITY_ENGINE->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; + se->CONFIG_REG = (ALG_RSA | DST_RSAREG); + se->RSA_CONFIG = keyslot << 24; + se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; + se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; set_security_engine_callback(callback); /* Enable SE Interrupt firing for async op. */ - SECURITY_ENGINE->INT_ENABLE_REG = 0x10; + se->INT_ENABLE_REG = 0x10; flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX); trigger_se_rsa_op(stack_buf, size); - while (!(SECURITY_ENGINE->INT_STATUS_REG & 2)) { /* Wait a while */ } + while (!(se->INT_STATUS_REG & 2)) { /* Wait a while */ } } void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); uint8_t stack_buf[KEYSIZE_RSA_MAX]; if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) { @@ -360,11 +379,10 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co stack_buf[i] = *((uint8_t *)src + src_size - i - 1); } - SECURITY_ENGINE->CONFIG_REG = (ALG_RSA | DST_RSAREG); - SECURITY_ENGINE->RSA_CONFIG = keyslot << 24; - SECURITY_ENGINE->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; - SECURITY_ENGINE->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; - + se->CONFIG_REG = (ALG_RSA | DST_RSAREG); + se->RSA_CONFIG = keyslot << 24; + se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; + se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; flush_dcache_range(stack_buf, stack_buf + KEYSIZE_RSA_MAX); trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size); @@ -382,7 +400,7 @@ void se_get_exp_mod_output(void *buf, size_t size) { /* Copy endian swapped output. */ while (num_dwords) { - *p_out = read32be(SECURITY_ENGINE->RSA_OUTPUT, offset); + *p_out = read32be(se_get_regs()->RSA_OUTPUT, offset); offset += 4; p_out--; num_dwords--; @@ -447,22 +465,25 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v void trigger_se_rsa_op(void *buf, size_t size) { + volatile tegra_se_t *se = se_get_regs(); se_ll_t in_ll; + ll_init(&in_ll, (void *)buf, size); /* Set the input LL. */ - SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); + se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); /* Set registers for operation. */ - SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG; - SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG; - SECURITY_ENGINE->OPERATION_REG = 1; + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = 1; /* Ensure writes go through. */ __dsb_ish(); } void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); se_ll_t in_ll; se_ll_t out_ll; @@ -472,20 +493,19 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v __dsb_sy(); /* Set the LLs. */ - SECURITY_ENGINE->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); - SECURITY_ENGINE->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll); + se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); + se->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll); /* Set registers for operation. */ - SECURITY_ENGINE->ERR_STATUS_REG = SECURITY_ENGINE->ERR_STATUS_REG; - SECURITY_ENGINE->INT_STATUS_REG = SECURITY_ENGINE->INT_STATUS_REG; - SECURITY_ENGINE->OPERATION_REG = op; + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = op; - while (!(SECURITY_ENGINE->INT_STATUS_REG & 0x10)) { /* Wait a while */ } + while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ } se_check_for_error(); } - /* Secure AES Functionality. */ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { uint8_t block[0x10] = {0}; @@ -501,7 +521,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, flush_dcache_range(block, block + sizeof(block)); /* Trigger AES operation. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se_get_regs()->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); /* Copy output data into dst. */ @@ -512,6 +532,8 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) { generic_panic(); } @@ -526,15 +548,15 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo unsigned int num_blocks = src_size >> 4; /* Unknown what this write does, but official code writes it for CTR mode. */ - SECURITY_ENGINE->_0x80C = 1; - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x91E; + se->SPARE_0 = 1; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x91E; set_se_ctr(ctr); /* Handle any aligned blocks. */ size_t aligned_size = (size_t)num_blocks << 4; if (aligned_size) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1; + se->BLOCK_COUNT_REG = num_blocks - 1; trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size); } @@ -553,13 +575,15 @@ void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const vo } void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } /* Set configuration high (256-bit vs 128-bit) based on parameter. */ - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); - SECURITY_ENGINE->CRYPTO_REG = keyslot << 24 | 0x100; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); + se->CRYPTO_REG = keyslot << 24 | 0x100; flush_dcache_range((uint8_t *)src, (uint8_t *)src + 0x10); se_perform_aes_block_operation(dst, 0x10, src, 0x10); flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + 0x10); @@ -576,12 +600,14 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = keyslot << 24; + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot << 24; flush_dcache_range((uint8_t *)src, (uint8_t *)src + 0x10); se_perform_aes_block_operation(dst, 0x10, src, 0x10); flush_dcache_range((uint8_t *)dst, (uint8_t *)dst + 0x10); @@ -600,6 +626,8 @@ void shift_left_xor_rb(uint8_t *key) { } void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -616,17 +644,16 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con shift_left_xor_rb(derived_key); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | (0x145); + se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); + se->CRYPTO_REG = (keyslot << 24) | (0x145); clear_aes_keyslot_iv(keyslot); - unsigned int num_blocks = (data_size + 0xF) >> 4; /* Handle aligned blocks. */ if (num_blocks > 1) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 2; + se->BLOCK_COUNT_REG = num_blocks - 2; trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); - SECURITY_ENGINE->CRYPTO_REG |= 0x80; + se->CRYPTO_REG |= 0x80; } /* Create final block. */ @@ -643,13 +670,13 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con } /* Perform last operation. */ - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->BLOCK_COUNT_REG = 0; flush_dcache_range(last_block, last_block + sizeof(last_block)); trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); /* Copy output CMAC. */ for (unsigned int i = 0; i < (cmac_size >> 2); i++) { - ((uint32_t *)cmac)[i] = read32le(SECURITY_ENGINE->HASH_RESULT_REG, i << 2); + ((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2); } } @@ -661,42 +688,48 @@ void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, } void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { generic_panic(); } - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x144; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); + se->CRYPTO_REG = (keyslot << 24) | 0x144; set_aes_keyslot_iv(keyslot, iv, 0x10); - SECURITY_ENGINE->BLOCK_COUNT_REG = (src_size >> 4) - 1; + se->BLOCK_COUNT_REG = (src_size >> 4) - 1; trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); } /* SHA256 Implementation. */ void se_calculate_sha256(void *dst, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + /* Setup config for SHA256, size = BITS(src_size) */ - SECURITY_ENGINE->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); - SECURITY_ENGINE->SHA_CONFIG_REG = 1; - SECURITY_ENGINE->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); - SECURITY_ENGINE->_0x208 = 0; - SECURITY_ENGINE->_0x20C = 0; - SECURITY_ENGINE->_0x210 = 0; - SECURITY_ENGINE->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); - SECURITY_ENGINE->_0x218 = 0; - SECURITY_ENGINE->_0x21C = 0; - SECURITY_ENGINE->_0x220 = 0; + se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); + se->SHA_CONFIG_REG = 1; + se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); + se->_0x208 = 0; + se->_0x20C = 0; + se->_0x210 = 0; + se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); + se->_0x218 = 0; + se->_0x21C = 0; + se->_0x220 = 0; /* Trigger the operation. */ trigger_se_blocking_op(OP_START, NULL, 0, src, src_size); /* Copy output hash. */ for (unsigned int i = 0; i < (0x20 >> 2); i++) { - ((uint32_t *)dst)[i] = read32be(SECURITY_ENGINE->HASH_RESULT_REG, i << 2); + ((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2); } } /* RNG API */ void se_initialize_rng(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } @@ -705,74 +738,80 @@ void se_initialize_rng(unsigned int keyslot) { /* This will be discarded, when done. */ uint8_t output_buf[0x10]; - SECURITY_ENGINE->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ - SECURITY_ENGINE->RNG_RESEED_INTERVAL_REG = 70001; - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 5; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ + se->RNG_RESEED_INTERVAL_REG = 70001; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 5; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0); } void se_generate_random(unsigned int keyslot, void *dst, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + if (keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } uint32_t num_blocks = size >> 4; size_t aligned_size = num_blocks << 4; - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_MEMORY); - SECURITY_ENGINE->CRYPTO_REG = (keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 4; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 4; if (num_blocks >= 1) { - SECURITY_ENGINE->BLOCK_COUNT_REG = num_blocks - 1; + se->BLOCK_COUNT_REG = num_blocks - 1; trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0); } if (size > aligned_size) { se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0); } - } - /* SE context save API. */ void se_set_in_context_save_mode(bool is_context_save_mode) { - uint32_t val = SECURITY_ENGINE->_0x0; + volatile tegra_se_t *se = se_get_regs(); + + uint32_t val = se->_0x0; if (is_context_save_mode) { val |= 0x10000; } else { val &= 0xFFFEFFFF; } - SECURITY_ENGINE->_0x0 = val; + se->_0x0 = val; /* Perform a useless read from flags reg. */ - (void)(SECURITY_ENGINE->FLAGS_REG); + (void)(se->FLAGS_REG); } void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) { + volatile tegra_se_t *se = se_get_regs(); + if (dst_keyslot >= KEYSLOT_AES_MAX || rng_keyslot >= KEYSLOT_AES_MAX) { generic_panic(); } /* Setup Config. */ - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_KEYTAB); - SECURITY_ENGINE->CRYPTO_REG = (rng_keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 4; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONFIG_REG = (ALG_RNG | DST_KEYTAB); + se->CRYPTO_REG = (rng_keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 4; + se->BLOCK_COUNT_REG = 0; /* Generate low part of key. */ - SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8); + se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8); trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); /* Generate high part of key. */ - SECURITY_ENGINE->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8) | 1; + se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8) | 1; trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); } void se_generate_srk(unsigned int srkgen_keyslot) { - SECURITY_ENGINE->CONFIG_REG = (ALG_RNG | DST_SRK); - SECURITY_ENGINE->CRYPTO_REG = (srkgen_keyslot << 24) | 0x108; - SECURITY_ENGINE->RNG_CONFIG_REG = 6; - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + volatile tegra_se_t *se = se_get_regs(); + + se->CONFIG_REG = (ALG_RNG | DST_SRK); + se->CRYPTO_REG = (srkgen_keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 6; + se->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); } @@ -796,6 +835,7 @@ void se_encrypt_with_srk(void *dst, size_t dst_size, const void *src, size_t src } void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void *dst) { + volatile tegra_se_t *se = se_get_regs(); uint8_t _work_buf[0x80]; uint8_t *work_buf = (uint8_t *)(((uintptr_t)_work_buf + 0x7F) & ~0x3F); @@ -808,39 +848,39 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void flush_dcache_range(work_buf, work_buf + 0x10); /* Save random initial block. */ - SECURITY_ENGINE->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(dst, 0x10, work_buf, 0x10); /* Save Sticky Bits. */ for (unsigned int i = 0; i < 0x2; i++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(dst + 0x10 + (i * 0x10), 0x10, NULL, 0); } /* Save AES Key Table. */ for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(dst + 0x30 + (i * 0x20), 0x10, NULL, 0); - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(dst + 0x40 + (i * 0x20), 0x10, NULL, 0); } /* Save AES Original IVs. */ for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(dst + 0x230 + (i * 0x10), 0x10, NULL, 0); } /* Save AES Updated IVs */ for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(dst + 0x330 + (i * 0x10), 0x10, NULL, 0); } @@ -849,8 +889,8 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void for (unsigned int rsa_key = 0; rsa_key < KEYSLOT_RSA_MAX; rsa_key++) { for (unsigned int mod_exp = 0; mod_exp < 2; mod_exp++) { for (unsigned int sub_block = 0; sub_block < 0x10; sub_block++) { - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_RSA) | ((2 * rsa_key + (1 - mod_exp)) << CTX_SAVE_RSA_KEY_INDEX_SHIFT) | (sub_block << CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_RSA) | ((2 * rsa_key + (1 - mod_exp)) << CTX_SAVE_RSA_KEY_INDEX_SHIFT) | (sub_block << CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(rsa_ctx_out, 0x10, NULL, 0); rsa_ctx_out += 0x10; } @@ -859,14 +899,14 @@ void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void /* Save "Known Pattern. " */ static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(dst + 0x830, 0x10, context_save_known_pattern, 0x10); /* Save SRK into PMC registers. */ - SECURITY_ENGINE->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_SRK); - SECURITY_ENGINE->BLOCK_COUNT_REG = 0; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_SRK); + se->BLOCK_COUNT_REG = 0; se_encrypt_with_srk(work_buf, 0, NULL, 0); - SECURITY_ENGINE->CONFIG_REG = 0; + se->CONFIG_REG = 0; se_encrypt_with_srk(work_buf, 0, NULL, 0); } diff --git a/exosphere/src/se.h b/exosphere/src/se.h index 326602d26..54768d620 100644 --- a/exosphere/src/se.h +++ b/exosphere/src/se.h @@ -97,7 +97,7 @@ #define RSA_2048_BYTES 0x100 -typedef struct security_engine { +typedef struct { uint32_t _0x0; uint32_t _0x4; uint32_t OPERATION_REG; @@ -157,15 +157,13 @@ typedef struct security_engine { uint32_t FLAGS_REG; uint32_t ERR_STATUS_REG; uint32_t _0x808; - uint32_t _0x80C; + uint32_t SPARE_0; uint32_t _0x810; uint32_t _0x814; uint32_t _0x818; uint32_t _0x81C; uint8_t _0x820[0x17E0]; -} security_engine_t; - -static_assert(sizeof(security_engine_t) == 0x2000, "Mis-defined Security Engine Registers!"); +} tegra_se_t; typedef struct { uint32_t address; @@ -177,15 +175,10 @@ typedef struct { se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ } se_ll_t; - -/* WIP, API subject to change. */ - -static inline volatile security_engine_t *get_security_engine(void) { - return (volatile security_engine_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SE)); +static inline volatile tegra_se_t *se_get_regs(void) { + return (volatile tegra_se_t *)(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_SE)); } -#define SECURITY_ENGINE (get_security_engine()) - /* This function MUST be registered to fire on the appropriate interrupt. */ void se_operation_completed(void); @@ -209,7 +202,6 @@ void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_s void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size); void set_se_ctr(const void *ctr); - /* Insecure AES API */ void se_aes_ctr_crypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *ctr, unsigned int (*callback)(void)); void se_aes_cbc_encrypt_insecure(unsigned int keyslot, uint32_t out_ll_paddr, uint32_t in_ll_paddr, size_t size, const void *iv, unsigned int (*callback)(void)); diff --git a/fusee/fusee-primary/src/i2c.c b/fusee/fusee-primary/src/i2c.c index 27063b3cd..aec946cf2 100644 --- a/fusee/fusee-primary/src/i2c.c +++ b/fusee/fusee-primary/src/i2c.c @@ -175,8 +175,7 @@ bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src i2c_load_config(regs); /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 |= 0x200; - + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); while (regs->I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ @@ -203,8 +202,7 @@ bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_ i2c_load_config(regs); /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 |= 0x200; - + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); while (regs->I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ diff --git a/fusee/fusee-primary/src/i2c.h b/fusee/fusee-primary/src/i2c.h index ec3efecc6..9399b0024 100644 --- a/fusee/fusee-primary/src/i2c.h +++ b/fusee/fusee-primary/src/i2c.h @@ -21,8 +21,8 @@ #include <stdint.h> #include <string.h> -#define I2C234_BASE 0x7000C000 -#define I2C56_BASE 0x7000D000 +#define I2C1234_BASE 0x7000C000 +#define I2C56_BASE 0x7000D000 #define I2C_1 0 #define I2C_2 1 @@ -82,10 +82,10 @@ typedef struct { uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; } tegra_i2c_t; -#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x000)) -#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x400)) -#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x500)) -#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x700)) +#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000)) +#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400)) +#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500)) +#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700)) #define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000)) #define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100)) diff --git a/fusee/fusee-primary/src/se.c b/fusee/fusee-primary/src/se.c index b466bd80b..d4dbdc498 100644 --- a/fusee/fusee-primary/src/se.c +++ b/fusee/fusee-primary/src/se.c @@ -39,8 +39,7 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { } void se_check_error_status_reg(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->ERR_STATUS_REG) { + if (se_get_regs()->ERR_STATUS_REG) { generic_panic(); } } @@ -53,8 +52,7 @@ void se_check_for_error(void) { } void se_verify_flags_cleared(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->FLAGS_REG & 3) { + if (se_get_regs()->FLAGS_REG & 3) { generic_panic(); } } @@ -193,9 +191,8 @@ void clear_aes_keyslot_iv(unsigned int keyslot) { } void set_se_ctr(const void *ctr) { - volatile tegra_se_t *se = se_get_regs(); for (unsigned int i = 0; i < 4; i++) { - se->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); } } @@ -237,7 +234,6 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co } void se_get_exp_mod_output(void *buf, size_t size) { - volatile tegra_se_t *se = se_get_regs(); size_t num_dwords = (size >> 2); if (num_dwords < 1) { @@ -249,7 +245,7 @@ void se_get_exp_mod_output(void *buf, size_t size) { /* Copy endian swapped output. */ while (num_dwords) { - *p_out = read32be(se->RSA_OUTPUT, offset); + *p_out = read32be(se_get_regs()->RSA_OUTPUT, offset); offset += 4; p_out--; num_dwords--; @@ -330,10 +326,8 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v se_check_for_error(); } - /* Secure AES Functionality. */ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); uint8_t block[0x10] = {0}; if (src_size > sizeof(block) || dst_size > sizeof(block)) { @@ -346,7 +340,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } /* Trigger AES operation. */ - se->BLOCK_COUNT_REG = 0; + se_get_regs()->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); /* Copy output data into dst. */ @@ -407,7 +401,6 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202); } - void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { volatile tegra_se_t *se = se_get_regs(); @@ -535,7 +528,6 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con se->CRYPTO_REG = (keyslot << 24) | (0x145); clear_aes_keyslot_iv(keyslot); - unsigned int num_blocks = (data_size + 0xF) >> 4; /* Handle aligned blocks. */ if (num_blocks > 1) { diff --git a/fusee/fusee-primary/src/se.h b/fusee/fusee-primary/src/se.h index db692b9cf..64998621a 100644 --- a/fusee/fusee-primary/src/se.h +++ b/fusee/fusee-primary/src/se.h @@ -34,6 +34,9 @@ #define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE #define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF +/* This keyslot was added in 5.0.0. */ +#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA + #define KEYSLOT_AES_MAX 0x10 #define KEYSLOT_RSA_MAX 0x2 @@ -88,7 +91,7 @@ #define RSA_2048_BYTES 0x100 -typedef struct security_engine { +typedef struct { uint32_t _0x0; uint32_t _0x4; uint32_t OPERATION_REG; @@ -170,8 +173,6 @@ static inline volatile tegra_se_t *se_get_regs(void) { return (volatile tegra_se_t *)SE_BASE; } -/* This function MUST be registered to fire on the appropriate interrupt. */ - void se_check_error_status_reg(void); void se_check_for_error(void); void se_trigger_interrupt(void); diff --git a/fusee/fusee-secondary/linker.ld b/fusee/fusee-secondary/linker.ld index 0d7538c12..68d127842 100644 --- a/fusee/fusee-secondary/linker.ld +++ b/fusee/fusee-secondary/linker.ld @@ -6,6 +6,7 @@ PHDRS { crt0 PT_LOAD; chainloader PT_LOAD; + nxboot PT_LOAD; main PT_LOAD; } @@ -13,16 +14,17 @@ PHDRS MEMORY { main : ORIGIN = 0xF0000000, LENGTH = 0x10000000 + high_iram : ORIGIN = 0x40010000, LENGTH = 0x20000 low_iram : ORIGIN = 0x40003000, LENGTH = 0x8000 } SECTIONS { PROVIDE(__start__ = 0xF0000000); - PROVIDE(__stack_top__ = 0x40010000); - PROVIDE(__stack_bottom__ = 0x4000C000); - PROVIDE(__heap_start__ = 0xE0000000); - PROVIDE(__heap_end__ = 0xF0000000); + PROVIDE(__stack_top__ = 0x90020000); + PROVIDE(__stack_bottom__ = 0x90010000); + PROVIDE(__heap_start__ = 0x90020000); + PROVIDE(__heap_end__ = 0xA0020000); . = __start__; @@ -53,6 +55,27 @@ SECTIONS . = ALIGN(32); PROVIDE (__chainloader_end__ = ABSOLUTE(.)); } >low_iram :NONE + + .nxboot_loadable : + { + . = ALIGN(32); + PROVIDE (__nxboot_start__ = ABSOLUTE(.)); + PROVIDE (__nxboot_lma__ = LOADADDR(.nxboot_loadable)); + KEEP(*(.nxboot.text.start)) + nxboot_iram.o(.text*) + nxboot_iram.o(.rodata*) + nxboot_iram.o(.data*) + . = ALIGN(32); + } >high_iram AT>main :nxboot + + .nxboot_bss (NOLOAD) : + { + . = ALIGN(32); + PROVIDE (__nxboot_bss_start__ = ABSOLUTE(.)); + nxboot_iram.o(.bss* COMMON) + . = ALIGN(32); + PROVIDE (__nxboot_end__ = ABSOLUTE(.)); + } >high_iram :NONE .text : { diff --git a/fusee/fusee-secondary/src/i2c.c b/fusee/fusee-secondary/src/i2c.c index 27063b3cd..aec946cf2 100644 --- a/fusee/fusee-secondary/src/i2c.c +++ b/fusee/fusee-secondary/src/i2c.c @@ -175,8 +175,7 @@ bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src i2c_load_config(regs); /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 |= 0x200; - + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); while (regs->I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ @@ -203,8 +202,7 @@ bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_ i2c_load_config(regs); /* Config |= SEND; */ - regs->I2C_I2C_CNFG_0 |= 0x200; - + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); while (regs->I2C_I2C_STATUS_0 & 0x100) { /* Wait until not busy. */ diff --git a/fusee/fusee-secondary/src/i2c.h b/fusee/fusee-secondary/src/i2c.h index ec3efecc6..9399b0024 100644 --- a/fusee/fusee-secondary/src/i2c.h +++ b/fusee/fusee-secondary/src/i2c.h @@ -21,8 +21,8 @@ #include <stdint.h> #include <string.h> -#define I2C234_BASE 0x7000C000 -#define I2C56_BASE 0x7000D000 +#define I2C1234_BASE 0x7000C000 +#define I2C56_BASE 0x7000D000 #define I2C_1 0 #define I2C_2 1 @@ -82,10 +82,10 @@ typedef struct { uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; } tegra_i2c_t; -#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x000)) -#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x400)) -#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x500)) -#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C234_BASE + 0x700)) +#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000)) +#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400)) +#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500)) +#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700)) #define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000)) #define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100)) diff --git a/fusee/fusee-secondary/src/init.c b/fusee/fusee-secondary/src/init.c index c061fc00c..3f043b77e 100644 --- a/fusee/fusee-secondary/src/init.c +++ b/fusee/fusee-secondary/src/init.c @@ -51,8 +51,11 @@ static void __program_init_newlib_hooks(void) { static void __program_move_additional_sections(void) { #if defined(FUSEE_STAGE1_SRC) || defined(FUSEE_STAGE2_SRC) extern uint8_t __chainloader_lma__[], __chainloader_start__[], __chainloader_bss_start__[], __chainloader_end__[]; + extern uint8_t __nxboot_lma__[], __nxboot_start__[], __nxboot_bss_start__[], __nxboot_end__[]; memcpy(__chainloader_start__, __chainloader_lma__, __chainloader_bss_start__ - __chainloader_start__); memset(__chainloader_bss_start__, 0, __chainloader_end__ - __chainloader_bss_start__); + memcpy(__nxboot_start__, __nxboot_lma__, __nxboot_bss_start__ - __nxboot_start__); + memset(__nxboot_bss_start__, 0, __nxboot_end__ - __nxboot_bss_start__); #endif } diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 5c9107cdb..5048bd642 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -102,7 +102,8 @@ int main(int argc, void **argv) { g_do_nxboot = loader_ctx->chainload_entrypoint == 0; if (g_do_nxboot) { printf("Now performing nxboot.\n"); - nxboot_main(); + uint32_t boot_memaddr = nxboot_main(); + nxboot_finish(boot_memaddr); } else { /* TODO: What else do we want to do in terms of argc/argv? */ const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint]; diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 47cf293b8..6f91206ab 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -185,9 +185,8 @@ static void nxboot_move_bootconfig() { /* This is the main function responsible for booting Horizon. */ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; -void nxboot_main(void) { +uint32_t nxboot_main(void) { volatile tegra_pmc_t *pmc = pmc_get_regs(); - volatile tegra_se_t *se = se_get_regs(); loader_ctx_t *loader_ctx = get_loader_ctx(); package2_header_t *package2; size_t package2_size; @@ -397,43 +396,6 @@ void nxboot_main(void) { } free(package2); - /* Clear used keyslots. */ - clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); - clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); - - /* Lock keyslots. */ - set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF); - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); - } else { - set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); - } - - /* Finalize the GPU UCODE carveout. */ - mc_config_carveout_finalize(); - - /* Lock AES keyslots. */ - for (uint32_t i = 0; i < 16; i++) - set_aes_keyslot_flags(i, 0x15); - - /* Lock RSA keyslots. */ - for (uint32_t i = 0; i < 2; i++) - set_rsa_keyslot_flags(i, 1); - - /* Lock the Security Engine. */ - se->_0x4 = 0; - se->AES_KEY_READ_DISABLE_REG = 0; - se->RSA_KEY_READ_DISABLE_REG = 0; - se->_0x0 &= 0xFFFFFFFB; - - /* Boot up Exosphère. */ - MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; - } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; - } - printf("[NXBOOT]: Powering on the CCPLEX...\n"); /* Display splash screen. */ @@ -442,26 +404,6 @@ void nxboot_main(void) { /* Unmount everything. */ nxfs_unmount_all(); - /* Terminate the display. */ - display_end(); - - /* Boot CPU0. */ - cluster_boot_cpu0((uint32_t)exosphere_memaddr); - - /* Wait for Exosphère to wake up. */ - while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { - udelay(1); - } - - /* Signal Exosphère. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED; - } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; - } - - /* Halt ourselves in waitevent state. */ - while (1) { - FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; - } + /* Return the memory address for booting CPU0. */ + return (uint32_t)exosphere_memaddr; } diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 7559a20a9..6a042ea2a 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -43,6 +43,7 @@ typedef struct { uint32_t boot_reason_state; } boot_reason_t; -void nxboot_main(void); +uint32_t nxboot_main(void); +void nxboot_finish(uint32_t boot_memaddr); #endif diff --git a/fusee/fusee-secondary/src/nxboot_iram.c b/fusee/fusee-secondary/src/nxboot_iram.c new file mode 100644 index 000000000..5e0a0ee6c --- /dev/null +++ b/fusee/fusee-secondary/src/nxboot_iram.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> + +#include "cluster.h" +#include "di.h" +#include "exocfg.h" +#include "flow.h" +#include "mc.h" +#include "nxboot.h" +#include "se.h" +#include "timers.h" + +void nxboot_finish(uint32_t boot_memaddr) { + volatile tegra_se_t *se = se_get_regs(); + + /* Clear used keyslots. */ + clear_aes_keyslot(KEYSLOT_SWITCH_PACKAGE2KEY); + clear_aes_keyslot(KEYSLOT_SWITCH_RNGKEY); + + /* Lock keyslots. */ + set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF); + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); + } else { + set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); + } + + /* Finalize the GPU UCODE carveout. */ + mc_config_carveout_finalize(); + + /* Lock AES keyslots. */ + for (uint32_t i = 0; i < 16; i++) + set_aes_keyslot_flags(i, 0x15); + + /* Lock RSA keyslots. */ + for (uint32_t i = 0; i < 2; i++) + set_rsa_keyslot_flags(i, 1); + + /* Lock the Security Engine. */ + se->_0x4 = 0; + se->AES_KEY_READ_DISABLE_REG = 0; + se->RSA_KEY_READ_DISABLE_REG = 0; + se->_0x0 &= 0xFFFFFFFB; + + /* Boot up Exosphère. */ + MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; + } else { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; + } + + /* Terminate the display. */ + display_end(); + + /* Boot CPU0. */ + cluster_boot_cpu0(boot_memaddr); + + /* Wait for Exosphère to wake up. */ + while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { + udelay(1); + } + + /* Signal Exosphère. */ + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED; + } else { + MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; + } + + /* Halt ourselves in waitevent state. */ + while (1) { + FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; + } +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/se.c b/fusee/fusee-secondary/src/se.c index b466bd80b..d4dbdc498 100644 --- a/fusee/fusee-secondary/src/se.c +++ b/fusee/fusee-secondary/src/se.c @@ -39,8 +39,7 @@ void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { } void se_check_error_status_reg(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->ERR_STATUS_REG) { + if (se_get_regs()->ERR_STATUS_REG) { generic_panic(); } } @@ -53,8 +52,7 @@ void se_check_for_error(void) { } void se_verify_flags_cleared(void) { - volatile tegra_se_t *se = se_get_regs(); - if (se->FLAGS_REG & 3) { + if (se_get_regs()->FLAGS_REG & 3) { generic_panic(); } } @@ -193,9 +191,8 @@ void clear_aes_keyslot_iv(unsigned int keyslot) { } void set_se_ctr(const void *ctr) { - volatile tegra_se_t *se = se_get_regs(); for (unsigned int i = 0; i < 4; i++) { - se->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); } } @@ -237,7 +234,6 @@ void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, co } void se_get_exp_mod_output(void *buf, size_t size) { - volatile tegra_se_t *se = se_get_regs(); size_t num_dwords = (size >> 2); if (num_dwords < 1) { @@ -249,7 +245,7 @@ void se_get_exp_mod_output(void *buf, size_t size) { /* Copy endian swapped output. */ while (num_dwords) { - *p_out = read32be(se->RSA_OUTPUT, offset); + *p_out = read32be(se_get_regs()->RSA_OUTPUT, offset); offset += 4; p_out--; num_dwords--; @@ -330,10 +326,8 @@ void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const v se_check_for_error(); } - /* Secure AES Functionality. */ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { - volatile tegra_se_t *se = se_get_regs(); uint8_t block[0x10] = {0}; if (src_size > sizeof(block) || dst_size > sizeof(block)) { @@ -346,7 +340,7 @@ void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, } /* Trigger AES operation. */ - se->BLOCK_COUNT_REG = 0; + se_get_regs()->BLOCK_COUNT_REG = 0; trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); /* Copy output data into dst. */ @@ -407,7 +401,6 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202); } - void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { volatile tegra_se_t *se = se_get_regs(); @@ -535,7 +528,6 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con se->CRYPTO_REG = (keyslot << 24) | (0x145); clear_aes_keyslot_iv(keyslot); - unsigned int num_blocks = (data_size + 0xF) >> 4; /* Handle aligned blocks. */ if (num_blocks > 1) { diff --git a/fusee/fusee-secondary/src/se.h b/fusee/fusee-secondary/src/se.h index db692b9cf..64998621a 100644 --- a/fusee/fusee-secondary/src/se.h +++ b/fusee/fusee-secondary/src/se.h @@ -34,6 +34,9 @@ #define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE #define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF +/* This keyslot was added in 5.0.0. */ +#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA + #define KEYSLOT_AES_MAX 0x10 #define KEYSLOT_RSA_MAX 0x2 @@ -88,7 +91,7 @@ #define RSA_2048_BYTES 0x100 -typedef struct security_engine { +typedef struct { uint32_t _0x0; uint32_t _0x4; uint32_t OPERATION_REG; @@ -170,8 +173,6 @@ static inline volatile tegra_se_t *se_get_regs(void) { return (volatile tegra_se_t *)SE_BASE; } -/* This function MUST be registered to fire on the appropriate interrupt. */ - void se_check_error_status_reg(void); void se_check_for_error(void); void se_trigger_interrupt(void); diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index dd5085d79..172516c90 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -31,5 +31,5 @@ void display_splash_screen_bmp(const char *custom_splash_path) { /* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */ /* Display the splash screen for three seconds. */ - /* udelay(3000000); */ + udelay(3000000); } diff --git a/fusee/fusee-secondary/src/start.s b/fusee/fusee-secondary/src/start.s index e417cd80e..fcad0f23d 100644 --- a/fusee/fusee-secondary/src/start.s +++ b/fusee/fusee-secondary/src/start.s @@ -70,3 +70,12 @@ _start: relocate_and_chainload: ldr sp, =__stack_top__ b relocate_and_chainload_main + +.section .nxboot.text.start, "ax", %progbits +.arm +.align 5 +.global nxboot +.type nxboot, %function +nxboot: + ldr sp, =__stack_top__ + b nxboot_finish \ No newline at end of file From f864b0835d539441d5aab2d55029d188a21bdeb1 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Mon, 17 Sep 2018 21:03:03 +0100 Subject: [PATCH 080/489] fusee: Add support for firmware version 6.0.0. fusee: Implement splash screen rendering. fusee: Add minor notes and update lz library. --- fusee/fusee-primary/src/hwinit.c | 49 ++++- fusee/fusee-primary/src/lib/lz.c | 204 +++++++++++++++++- fusee/fusee-primary/src/lib/lz.h | 5 +- fusee/fusee-secondary/Makefile | 7 +- fusee/fusee-secondary/src/exocfg.h | 3 +- fusee/fusee-secondary/src/nxboot.c | 20 +- fusee/fusee-secondary/src/splash_screen.bmp | Bin 0 -> 3686454 bytes fusee/fusee-secondary/src/splash_screen.c | 65 +++++- fusee/fusee-secondary/src/splash_screen.h | 9 +- .../src/splash_screen_default.c | 19 -- 10 files changed, 337 insertions(+), 44 deletions(-) create mode 100644 fusee/fusee-secondary/src/splash_screen.bmp delete mode 100644 fusee/fusee-secondary/src/splash_screen_default.c diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index 47d5ecf27..de4df1954 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -194,7 +194,10 @@ void nx_hwinit() AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); + /* Apply the memory built-in self test workaround. */ mbist_workaround(); + + /* Reboot SE. */ clkrst_reboot(CARDEVICE_SE); /* Initialize the fuse driver. */ @@ -203,9 +206,15 @@ void nx_hwinit() /* Initialize the memory controller. */ mc_enable(); - /* Configure oscillators, pinmux and GPIOs. */ + /* Configure oscillators. */ config_oscillators(); + + /* Disable pinmux tristate input clamping. */ APB_MISC_PP_PINMUX_GLOBAL_0 = 0; + + /* Configure GPIOs. */ + /* NOTE: In 3.x+ part of the GPIO configuration is skipped if the unit is SDEV. */ + /* NOTE: In 6.x+ the GPIO configuration's order was changed a bit. */ config_gpios(); /* Uncomment for UART debugging. */ @@ -214,21 +223,34 @@ void nx_hwinit() uart_init(UART_C, 115200); */ + /* Reboot CL-DVFS. */ clkrst_reboot(CARDEVICE_CL_DVFS); + + /* Reboot I2C1. */ clkrst_reboot(CARDEVICE_I2C1); + + /* Reboot I2C5. */ clkrst_reboot(CARDEVICE_I2C5); + + /* Reboot SE. */ + /* NOTE: In 4.x+ this was removed. */ clkrst_reboot(CARDEVICE_SE); + + /* Reboot unknown device. */ clkrst_reboot(CARDEVICE_UNK); - /* Initialize I2C1 and I2C5. */ + /* Initialize I2C1. */ + /* NOTE: In 6.x+ this was moved to after the PMIC is configured. */ i2c_init(I2C_1); + + /* Initialize I2C5. */ i2c_init(I2C_5); + /* Configure the PMIC. */ uint8_t val = 0x40; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1); val = 0x78; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1); - val = 0x38; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1); val = 0x3A; @@ -245,19 +267,38 @@ void nx_hwinit() i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD1, &val, 1); val = 0x1B; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD3, &val, 1); + + /* TODO: In 3.x+ this was added. */ + /* + val = 0x22; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_GPIO3, &val, 1); + */ + + /* TODO: In 3.x+, if the unit is SDEV, the MBLPD bit is set. */ + /* + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); + val |= 0x40; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); + */ + /* Configure SD0 voltage. */ val = 42; /* 42 = (1125000 - 600000) / 12500 -> 1.125V */ i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD0, &val, 1); /* Configure and lock PMC scratch registers. */ + /* NOTE: In 4.x+ this was removed. */ config_pmc_scratch(); + /* Set super clock burst policy. */ car->sclk_brst_pol = ((car->sclk_brst_pol & 0xFFFF8888) | 0x3333); /* Configure memory controller carveouts. */ + /* NOTE: In 4.x+ this was removed. */ mc_config_carveout(); - /* Initialize and save SDRAM. */ + /* Initialize SDRAM. */ sdram_init(); + + /* Save SDRAM LP0 parameters. */ sdram_lp0_save_params(sdram_get_params()); } \ No newline at end of file diff --git a/fusee/fusee-primary/src/lib/lz.c b/fusee/fusee-primary/src/lib/lz.c index a17c6e49f..564d480ad 100644 --- a/fusee/fusee-primary/src/lib/lz.c +++ b/fusee/fusee-primary/src/lib/lz.c @@ -78,11 +78,73 @@ *************************************************************************/ +/************************************************************************* +* Constants used for LZ77 coding +*************************************************************************/ + +/* Maximum offset (can be any size < 2^31). Lower values give faster + compression, while higher values gives better compression. The default + value of 100000 is quite high. Experiment to see what works best for + you. */ +#define LZ_MAX_OFFSET 100000 + + + /************************************************************************* * INTERNAL FUNCTIONS * *************************************************************************/ +/************************************************************************* +* _LZ_StringCompare() - Return maximum length string match. +*************************************************************************/ + +static unsigned int _LZ_StringCompare( unsigned char * str1, + unsigned char * str2, unsigned int minlen, unsigned int maxlen ) +{ + unsigned int len; + + for( len = minlen; (len < maxlen) && (str1[len] == str2[len]); ++ len ); + + return len; +} + + +/************************************************************************* +* _LZ_WriteVarSize() - Write unsigned integer with variable number of +* bytes depending on value. +*************************************************************************/ + +static int _LZ_WriteVarSize( unsigned int x, unsigned char * buf ) +{ + unsigned int y; + int num_bytes, i, b; + + /* Determine number of bytes needed to store the number x */ + y = x >> 3; + for( num_bytes = 5; num_bytes >= 2; -- num_bytes ) + { + if( y & 0xfe000000 ) break; + y <<= 7; + } + + /* Write all bytes, seven bits in each, with 8:th bit set for all */ + /* but the last byte. */ + for( i = num_bytes-1; i >= 0; -- i ) + { + b = (x >> (i*7)) & 0x0000007f; + if( i > 0 ) + { + b |= 0x00000080; + } + *buf ++ = (unsigned char) b; + } + + /* Return number of bytes written */ + return num_bytes; +} + + /************************************************************************* * _LZ_ReadVarSize() - Read unsigned integer with variable number of * bytes depending on value. @@ -117,6 +179,141 @@ static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf ) *************************************************************************/ +/************************************************************************* +* LZ_Compress() - Compress a block of data using an LZ77 coder. +* in - Input (uncompressed) buffer. +* out - Output (compressed) buffer. This buffer must be 0.4% larger +* than the input buffer, plus one byte. +* insize - Number of input bytes. +* The function returns the size of the compressed data. +*************************************************************************/ + +int LZ_Compress( const unsigned char *in, unsigned char *out, unsigned int insize ) +{ + unsigned char marker, symbol; + unsigned int inpos, outpos, bytesleft, i; + unsigned int maxoffset, offset, bestoffset; + unsigned int maxlength, length, bestlength; + unsigned int histogram[ 256 ]; + unsigned char *ptr1, *ptr2; + + /* Do we have anything to compress? */ + if( insize < 1 ) + { + return 0; + } + + /* Create histogram */ + for( i = 0; i < 256; ++ i ) + { + histogram[ i ] = 0; + } + for( i = 0; i < insize; ++ i ) + { + ++ histogram[ in[ i ] ]; + } + + /* Find the least common byte, and use it as the marker symbol */ + marker = 0; + for( i = 1; i < 256; ++ i ) + { + if( histogram[ i ] < histogram[ marker ] ) + { + marker = (unsigned char) i; + } + } + + /* Remember the marker symbol for the decoder */ + out[ 0 ] = marker; + + /* Start of compression */ + inpos = 0; + outpos = 1; + + /* Main compression loop */ + bytesleft = insize; + do + { + /* Determine most distant position */ + if( inpos > LZ_MAX_OFFSET ) maxoffset = LZ_MAX_OFFSET; + else maxoffset = inpos; + + /* Get pointer to current position */ + ptr1 = &in[ inpos ]; + + /* Search history window for maximum length string match */ + bestlength = 3; + bestoffset = 0; + for( offset = 3; offset <= maxoffset; ++ offset ) + { + /* Get pointer to candidate string */ + ptr2 = &ptr1[ -(int)offset ]; + + /* Quickly determine if this is a candidate (for speed) */ + if( (ptr1[ 0 ] == ptr2[ 0 ]) && + (ptr1[ bestlength ] == ptr2[ bestlength ]) ) + { + /* Determine maximum length for this offset */ + maxlength = (bytesleft < offset ? bytesleft : offset); + + /* Count maximum length match at this offset */ + length = _LZ_StringCompare( ptr1, ptr2, 0, maxlength ); + + /* Better match than any previous match? */ + if( length > bestlength ) + { + bestlength = length; + bestoffset = offset; + } + } + } + + /* Was there a good enough match? */ + if( (bestlength >= 8) || + ((bestlength == 4) && (bestoffset <= 0x0000007f)) || + ((bestlength == 5) && (bestoffset <= 0x00003fff)) || + ((bestlength == 6) && (bestoffset <= 0x001fffff)) || + ((bestlength == 7) && (bestoffset <= 0x0fffffff)) ) + { + out[ outpos ++ ] = (unsigned char) marker; + outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] ); + outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] ); + inpos += bestlength; + bytesleft -= bestlength; + } + else + { + /* Output single byte (or two bytes if marker byte) */ + symbol = in[ inpos ++ ]; + out[ outpos ++ ] = symbol; + if( symbol == marker ) + { + out[ outpos ++ ] = 0; + } + -- bytesleft; + } + } + while( bytesleft > 3 ); + + /* Dump remaining bytes, if any */ + while( inpos < insize ) + { + if( in[ inpos ] == marker ) + { + out[ outpos ++ ] = marker; + out[ outpos ++ ] = 0; + } + else + { + out[ outpos ++ ] = in[ inpos ]; + } + ++ inpos; + } + + return outpos; +} + + /************************************************************************* * LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder. * in - Input (compressed) buffer. @@ -125,8 +322,7 @@ static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf ) * insize - Number of input bytes. *************************************************************************/ -void LZ_Uncompress( const unsigned char *in, unsigned char *out, - unsigned int insize ) +int LZ_Uncompress( const unsigned char *in, unsigned char *out, unsigned int insize ) { unsigned char marker, symbol; unsigned int i, inpos, outpos, length, offset; @@ -134,7 +330,7 @@ void LZ_Uncompress( const unsigned char *in, unsigned char *out, /* Do we have anything to uncompress? */ if( insize < 1 ) { - return; + return 0; } /* Get marker symbol from input stream */ @@ -176,4 +372,6 @@ void LZ_Uncompress( const unsigned char *in, unsigned char *out, } } while( inpos < insize ); + + return outpos; } diff --git a/fusee/fusee-primary/src/lib/lz.h b/fusee/fusee-primary/src/lib/lz.h index 6f31b4a14..bc40b6c63 100644 --- a/fusee/fusee-primary/src/lib/lz.h +++ b/fusee/fusee-primary/src/lib/lz.h @@ -41,9 +41,8 @@ extern "C" { * Function prototypes *************************************************************************/ -void LZ_Uncompress( const unsigned char *in, unsigned char *out, - unsigned int insize ); - +int LZ_Compress(const unsigned char *in, unsigned char *out, unsigned int insize); +int LZ_Uncompress(const unsigned char *in, unsigned char *out, unsigned int insize); #ifdef __cplusplus } diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index bad10f017..55377889f 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -80,7 +80,7 @@ CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) KIPFILES := loader.kip pm.kip sm.kip boot_100.kip boot_200.kip -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) exosphere.bin thermosphere.bin $(KIPFILES) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) exosphere.bin thermosphere.bin splash_screen.bmp $(KIPFILES) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C @@ -166,6 +166,11 @@ $(OFILES_SRC) : $(HFILES_BIN) #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) + +%.bmp.o %_bmp.h: %.bmp +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) %.kip.o %_kip.h: %.kip #--------------------------------------------------------------------------------- diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index dedc059fe..2b3417629 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -27,9 +27,10 @@ #define EXOSPHERE_TARGET_FIRMWARE_300 3 #define EXOSPHERE_TARGET_FIRMWARE_400 4 #define EXOSPHERE_TARGET_FIRMWARE_500 5 +#define EXOSPHERE_TARGET_FIRMWARE_600 6 #define EXOSPHERE_TARGET_FIRMWARE_MIN EXOSPHERE_TARGET_FIRMWARE_100 -#define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_500 +#define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_600 typedef struct { unsigned int magic; diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 6f91206ab..68396210b 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -75,6 +75,8 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { return EXOSPHERE_TARGET_FIRMWARE_400; case 0x0B: /* 5.0.0 - 5.1.0 */ return EXOSPHERE_TARGET_FIRMWARE_500; + case 0x0E: /* 6.0.0 */ + return EXOSPHERE_TARGET_FIRMWARE_600; default: return 0; } @@ -158,6 +160,8 @@ static void nxboot_set_bootreason() { static void nxboot_move_bootconfig() { FILE *bcfile; void *bootconfig; + uint32_t bootconfig_addr; + uint32_t bootconfig_size; /* Allocate memory for reading BootConfig. */ bootconfig = memalign(0x1000, 0x4000); @@ -175,9 +179,13 @@ static void nxboot_move_bootconfig() { } fclose(bcfile); - /* Copy the first 0x3000 bytes into IRAM. */ - memset((void *)0x4003D000, 0, 0x3000); - memcpy((void *)0x4003D000, bootconfig, 0x3000); + /* Select the actual BootConfig size and destination address. */ + bootconfig_addr = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_600) ? 0x4003D000 : 0x4003F800; + bootconfig_size = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) ? 0x3000 : 0x1000; + + /* Copy the BootConfig into IRAM. */ + memset((void *)bootconfig_addr, 0, bootconfig_size); + memcpy((void *)bootconfig_addr, bootconfig, bootconfig_size); /* Clean up. */ free(bootconfig); @@ -329,8 +337,10 @@ uint32_t nxboot_main(void) { /* Select the right address for the warmboot firmware. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { warmboot_memaddr = (void *)0x8000D000; - } else { + } else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_600) { warmboot_memaddr = (void *)0x4003B000; + } else { + warmboot_memaddr = (void *)0x4003D800; } printf("[NXBOOT]: Copying warmboot firmware...\n"); @@ -399,7 +409,7 @@ uint32_t nxboot_main(void) { printf("[NXBOOT]: Powering on the CCPLEX...\n"); /* Display splash screen. */ - display_splash_screen_bmp(loader_ctx->custom_splash_path); + display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); /* Unmount everything. */ nxfs_unmount_all(); diff --git a/fusee/fusee-secondary/src/splash_screen.bmp b/fusee/fusee-secondary/src/splash_screen.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3fe43bd90f5da7a5c16a4eccc88ea4c9537494c5 GIT binary patch literal 3686454 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�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.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ç~SZCFV`<c#X_Q=jYJMS$1nR~5&-oU|O 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%0Ab=MB}-t^<1l%)OYUCZ;I7ehZUoH;H0`@ZWv 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%0D=rJyfAxfL!R|YUQFwMVo*BIz2IsMk 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%0D+gXnfC@fsQrZ&*q-(uqzA)nP)r? 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 P`75{%tA9M{zx)3IOfh{E literal 0 HcmV?d00001 diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index 172516c90..97b258ccd 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -15,20 +15,75 @@ */ #include <stdio.h> +#include "di.h" #include "timers.h" #include "splash_screen.h" #include "fs_utils.h" #include "display/video_fb.h" -void display_splash_screen_bmp(const char *custom_splash_path) { - uint8_t *splash_screen = g_default_splash_screen; +#define u8 uint8_t +#define u32 uint32_t +#include "splash_screen_bmp.h" +#undef u8 +#undef u32 + +static void render_bmp(const uint32_t *bmp_data, uint32_t *framebuffer, uint32_t bmp_width, uint32_t bmp_height, uint32_t bmp_pos_x, uint32_t bmp_pos_y) { + /* Render the BMP. */ + for (uint32_t y = bmp_pos_y; y < (bmp_pos_y + bmp_height); y++) { + for (uint32_t x = bmp_pos_x; x < (bmp_pos_x + bmp_width); x++) { + framebuffer[x + (y * SPLASH_SCREEN_STRIDE)] = bmp_data[(bmp_height + bmp_pos_y - 1 - y) * bmp_width + x - bmp_pos_x]; + } + } + + /* Re-initialize the frame buffer. */ + display_init_framebuffer(framebuffer); +} + +void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address) { + uint8_t *splash_screen = (uint8_t *)splash_screen_bmp; + + /* Try to load an external custom splash screen. */ if ((custom_splash_path != NULL) && (custom_splash_path[0] != '\x00')) { - if (!read_from_file(splash_screen, sizeof(g_default_splash_screen), custom_splash_path)) { + if (!read_from_file(splash_screen, sizeof(&splash_screen_bmp), custom_splash_path)) { fatal_error("Failed to read custom splash screen from %s!\n", custom_splash_path); } } - - /* TODO: Display the splash screen. It should be a pointer to a BMP, at this point. */ + + /* Check for 'BM' magic. */ + if ((splash_screen[0] == 'B') && (splash_screen[1] == 'M')) { + /* Extract BMP parameters. */ + uint32_t bmp_size = (splash_screen[0x02] | (splash_screen[0x03] << 8) | (splash_screen[0x04] << 16) | (splash_screen[0x05] << 24)); + uint32_t bmp_offset = (splash_screen[0x0A] | (splash_screen[0x0B] << 8) | (splash_screen[0x0C] << 16) | (splash_screen[0x0D] << 24)); + uint32_t bmp_width = (splash_screen[0x12] | (splash_screen[0x13] << 8) | (splash_screen[0x14] << 16) | (splash_screen[0x15] << 24)); + uint32_t bmp_height = (splash_screen[0x16] | (splash_screen[0x17] << 8) | (splash_screen[0x18] << 16) | (splash_screen[0x19] << 24)); + uint16_t bmp_bpp = (splash_screen[0x1C] | (splash_screen[0x1D] << 8)); + uint32_t bmp_data_size = (splash_screen[0x22] | (splash_screen[0x23] << 8) | (splash_screen[0x24] << 16) | (splash_screen[0x25] << 24)); + + /* Data size can be wrong or set to 0. In that case, we calculate it instead. */ + if (!bmp_data_size || (bmp_data_size >= bmp_size)) + bmp_data_size = (bmp_size - bmp_offset); + + /* Only accept images up to 720x1280 resolution and with 32 BPP. */ + if ((bmp_width > SPLASH_SCREEN_WIDTH_MAX) || (bmp_height > SPLASH_SCREEN_HEIGHT_MAX)) { + fatal_error("Invalid splash screen dimensions!\n"); + } else if (bmp_bpp != SPLASH_SCREEN_BPP) { + fatal_error("Invalid splash screen color depth!\n"); + } else if (bmp_data_size > SPLASH_SCREEN_SIZE_MAX) { + fatal_error("Splash screen data size is too big!\n"); + } + + /* Calculate screen positions. */ + uint32_t bmp_pos_x = ((SPLASH_SCREEN_WIDTH_MAX - bmp_width) / 2); + uint32_t bmp_pos_y = ((SPLASH_SCREEN_HEIGHT_MAX - bmp_height) / 2); + + /* Advance to data. */ + splash_screen += bmp_offset; + + /* Render the BMP. */ + render_bmp((uint32_t *)splash_screen, (uint32_t *)fb_address, bmp_width, bmp_height, bmp_pos_x, bmp_pos_y); + } else { + fatal_error("Invalid splash screen format!\n"); + } /* Display the splash screen for three seconds. */ udelay(3000000); diff --git a/fusee/fusee-secondary/src/splash_screen.h b/fusee/fusee-secondary/src/splash_screen.h index 032337744..0cca4fe52 100644 --- a/fusee/fusee-secondary/src/splash_screen.h +++ b/fusee/fusee-secondary/src/splash_screen.h @@ -19,9 +19,12 @@ #include <stdint.h> -/* TODO: Actually make this a real thing. */ -extern unsigned char g_default_splash_screen[1]; +#define SPLASH_SCREEN_WIDTH_MAX 720 +#define SPLASH_SCREEN_HEIGHT_MAX 1280 +#define SPLASH_SCREEN_BPP 32 +#define SPLASH_SCREEN_STRIDE 768 +#define SPLASH_SCREEN_SIZE_MAX (SPLASH_SCREEN_HEIGHT_MAX * SPLASH_SCREEN_STRIDE * 4) -void display_splash_screen_bmp(const char *custom_splash_path); +void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address); #endif diff --git a/fusee/fusee-secondary/src/splash_screen_default.c b/fusee/fusee-secondary/src/splash_screen_default.c deleted file mode 100644 index c1a955d5f..000000000 --- a/fusee/fusee-secondary/src/splash_screen_default.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "splash_screen.h" - -uint8_t g_default_splash_screen[1] = {0}; From 99d36c423e25326ecfb5081be856b8be5e1815c2 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Tue, 18 Sep 2018 16:39:18 +0000 Subject: [PATCH 081/489] fusee: Add missing const qualifiers (thanks @aveao) --- fusee/fusee-primary/src/lib/lz.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-primary/src/lib/lz.c b/fusee/fusee-primary/src/lib/lz.c index 564d480ad..e62e02d15 100644 --- a/fusee/fusee-primary/src/lib/lz.c +++ b/fusee/fusee-primary/src/lib/lz.c @@ -99,8 +99,8 @@ * _LZ_StringCompare() - Return maximum length string match. *************************************************************************/ -static unsigned int _LZ_StringCompare( unsigned char * str1, - unsigned char * str2, unsigned int minlen, unsigned int maxlen ) +static unsigned int _LZ_StringCompare( const unsigned char * str1, + const unsigned char * str2, unsigned int minlen, unsigned int maxlen ) { unsigned int len; @@ -195,7 +195,7 @@ int LZ_Compress( const unsigned char *in, unsigned char *out, unsigned int insiz unsigned int maxoffset, offset, bestoffset; unsigned int maxlength, length, bestlength; unsigned int histogram[ 256 ]; - unsigned char *ptr1, *ptr2; + const unsigned char *ptr1, *ptr2; /* Do we have anything to compress? */ if( insize < 1 ) From d8391078c8828e3cf852742963e4f7f7e0f4ab96 Mon Sep 17 00:00:00 2001 From: TuxSH <tuxsh@sfr.fr> Date: Wed, 19 Sep 2018 15:03:50 +0200 Subject: [PATCH 082/489] Fix creport according to latest libnx release changes --- .../creport/source/creport_thread_info.cpp | 6 ++-- .../creport/source/creport_thread_info.hpp | 29 ++----------------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/stratosphere/creport/source/creport_thread_info.cpp b/stratosphere/creport/source/creport_thread_info.cpp index ab8c1e397..fbd27a310 100644 --- a/stratosphere/creport/source/creport_thread_info.cpp +++ b/stratosphere/creport/source/creport_thread_info.cpp @@ -28,12 +28,12 @@ void ThreadInfo::SaveToFile(FILE *f_report) { fprintf(f_report, " Registers:\n"); { for (unsigned int i = 0; i <= 28; i++) { - fprintf(f_report, " X[%02u]: %s\n", i, this->code_list->GetFormattedAddressString(this->context.x[i])); + fprintf(f_report, " X[%02u]: %s\n", i, this->code_list->GetFormattedAddressString(this->context.cpu_gprs[i].x)); } fprintf(f_report, " FP: %s\n", this->code_list->GetFormattedAddressString(this->context.fp)); fprintf(f_report, " LR: %s\n", this->code_list->GetFormattedAddressString(this->context.lr)); fprintf(f_report, " SP: %s\n", this->code_list->GetFormattedAddressString(this->context.sp)); - fprintf(f_report, " PC: %s\n", this->code_list->GetFormattedAddressString(this->context.pc)); + fprintf(f_report, " PC: %s\n", this->code_list->GetFormattedAddressString(this->context.pc.x)); } fprintf(f_report, " Stack Trace:\n"); for (unsigned int i = 0; i < this->stack_trace_size; i++) { @@ -58,7 +58,7 @@ bool ThreadInfo::ReadFromProcess(Handle debug_handle, u64 thread_id, bool is_64_ } /* Get the thread context. */ - if (R_FAILED(svcGetDebugThreadContext((u8 *)&this->context, debug_handle, this->thread_id, 0xF))) { + if (R_FAILED(svcGetDebugThreadContext(&this->context, debug_handle, this->thread_id, 0xF))) { return false; } diff --git a/stratosphere/creport/source/creport_thread_info.hpp b/stratosphere/creport/source/creport_thread_info.hpp index 491b988a8..0b3d3f07f 100644 --- a/stratosphere/creport/source/creport_thread_info.hpp +++ b/stratosphere/creport/source/creport_thread_info.hpp @@ -21,34 +21,9 @@ #include "creport_debug_types.hpp" #include "creport_code_info.hpp" -struct FpuReg { - u64 _[2]; /* TODO: uint128? */ -}; - -struct DebugThreadContext { - union { - u64 x[0x20]; - struct { - u64 _x[29]; - u64 fp; - u64 lr; - u64 sp; - }; - }; - u64 pc; - u32 psr; - /* 32-bits of padding. */ - FpuReg fpu_reg[0x20]; - u32 fpcr; - u32 fpsr; - u64 tpidr; -}; - -static_assert(sizeof(DebugThreadContext) == 0x320, "Incorrect DebugThreadContext Definition!"); - class ThreadInfo { private: - DebugThreadContext context{}; + ThreadContext context{}; u64 thread_id = 0; u64 stack_top = 0; u64 stack_bottom = 0; @@ -56,7 +31,7 @@ class ThreadInfo { u32 stack_trace_size = 0; CodeList *code_list; public: - u64 GetPC() { return context.pc; } + u64 GetPC() { return context.pc.x; } u64 GetLR() { return context.lr; } u64 GetId() { return thread_id; } From 6afbcd12d965056865541e93b4f4c3d1c54b8f8d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 19 Sep 2018 16:21:46 -0700 Subject: [PATCH 083/489] Loader: Button override + first-class HBL support --- stratosphere/loader/source/ini.c | 269 ++++++++++++++++++ stratosphere/loader/source/ini.h | 130 +++++++++ .../loader/source/ldr_content_management.cpp | 145 +++++++++- .../loader/source/ldr_content_management.hpp | 5 + stratosphere/loader/source/ldr_hid.cpp | 35 +++ stratosphere/loader/source/ldr_hid.hpp | 23 ++ stratosphere/loader/source/ldr_npdm.cpp | 78 ++++- stratosphere/loader/source/ldr_npdm.hpp | 5 +- stratosphere/loader/source/ldr_nso.cpp | 25 +- stratosphere/loader/source/ldr_nso.hpp | 1 + .../loader/source/ldr_process_creation.cpp | 11 +- 11 files changed, 692 insertions(+), 35 deletions(-) create mode 100644 stratosphere/loader/source/ini.c create mode 100644 stratosphere/loader/source/ini.h create mode 100644 stratosphere/loader/source/ldr_hid.cpp create mode 100644 stratosphere/loader/source/ldr_hid.hpp diff --git a/stratosphere/loader/source/ini.c b/stratosphere/loader/source/ini.c new file mode 100644 index 000000000..63626c72d --- /dev/null +++ b/stratosphere/loader/source/ini.c @@ -0,0 +1,269 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#include "ini.h" + +#if !INI_USE_STACK +#include <stdlib.h> +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to null at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + strncpy(dest, src, size - 1); + dest[size - 1] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; +#else + char* line; + int max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC + char* new_line; + int offset; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = realloc(line, max_line); + if (!new_line) { + free(line); + return -2; + } + line = new_line; + if (reader(line + offset, max_line - offset, stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; +#endif + value = lskip(value); + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ + error = lineno; + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/stratosphere/loader/source/ini.h b/stratosphere/loader/source/ini.h new file mode 100644 index 000000000..f45ba40ba --- /dev/null +++ b/stratosphere/loader/source/ini.h @@ -0,0 +1,130 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef __INI_H__ +#define __INI_H__ + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See http://code.google.com/p/inih/issues/detail?id=21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INI_H__ */ diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index c7ca985b0..c822d3281 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -14,19 +14,32 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <cstring> #include <switch.h> -#include <string.h> +#include <strings.h> #include <vector> #include <algorithm> #include "ldr_registration.hpp" #include "ldr_content_management.hpp" +#include "ldr_hid.hpp" + + +#include "ini.h" static FsFileSystem g_CodeFileSystem = {0}; +static FsFileSystem g_HblFileSystem = {0}; static std::vector<u64> g_created_titles; static bool g_has_initialized_fs_dev = false; +/* Default to Key R, hold disables override, HBL at atmosphere/hbl.nsp. */ +static bool g_mounted_hbl_nsp = false; +static char g_hbl_sd_path[FS_MAX_PATH+1] = "@Sdcard:/atmosphere/hbl.nsp\x00"; +static u64 g_override_key_combination = KEY_R; +static bool g_override_by_default = true; +static u64 g_override_hbl_tid = 0x010000000000100D; + Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { char path[FS_MAX_PATH] = {0}; Result rc; @@ -36,10 +49,9 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { TryMountSdCard(); } - if (kernelAbove200() && g_has_initialized_fs_dev && R_SUCCEEDED(MountCodeNspOnSd(tid))) { + if (ShouldOverrideContents() && R_SUCCEEDED(MountCodeNspOnSd(tid))) { return 0x0; } - if (R_FAILED(rc = ResolveContentPath(path, tid, sid))) { return rc; @@ -63,23 +75,44 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { } fsdevMountDevice("code", g_CodeFileSystem); + TryMountHblNspOnSd(); fsldrExit(); return rc; } Result ContentManagement::UnmountCode() { + if (g_mounted_hbl_nsp) { + fsdevUnmountDevice("hbl"); + g_mounted_hbl_nsp = false; + } fsdevUnmountDevice("code"); return 0; } + +void ContentManagement::TryMountHblNspOnSd() { + char path[FS_MAX_PATH+1] = {0}; + strncpy(path, g_hbl_sd_path, FS_MAX_PATH); + for (unsigned int i = 0; i < FS_MAX_PATH && path[i] != '\x00'; i++) { + if (path[i] == '\\') { + path[i] = '/'; + } + } + if (g_has_initialized_fs_dev && !g_mounted_hbl_nsp && R_SUCCEEDED(fsOpenFileSystemWithId(&g_HblFileSystem, 0, FsFileSystemType_ApplicationPackage, path))) { + fsdevMountDevice("hbl", g_HblFileSystem); + g_mounted_hbl_nsp = true; + } +} + Result ContentManagement::MountCodeNspOnSd(u64 tid) { char path[FS_MAX_PATH+1] = {0}; snprintf(path, FS_MAX_PATH, "@Sdcard:/atmosphere/titles/%016lx/exefs.nsp", tid); Result rc = fsOpenFileSystemWithId(&g_CodeFileSystem, 0, FsFileSystemType_ApplicationPackage, path); - if (R_SUCCEEDED(rc)) { + if (R_SUCCEEDED(rc)) { fsdevMountDevice("code", g_CodeFileSystem); + TryMountHblNspOnSd(); } return rc; @@ -158,6 +191,94 @@ void ContentManagement::SetCreatedTitle(u64 tid) { } } +static int LoaderIniHandler(void *user, const char *section, const char *name, const char *value) { + /* Taken and modified, with love, from Rajkosto's implementation. */ + if (strcasecmp(section, "config") == 0) { + if (strcasecmp(name, "hbl_tid") == 0) { + u64 override_tid = strtoul(value, NULL, 16); + if (override_tid != 0) { + g_override_hbl_tid = override_tid; + } + } else if (strcasecmp(name, "hbl_path") == 0) { + while (*value == '/' || *value == '\\') { + value++; + } + snprintf(g_hbl_sd_path, FS_MAX_PATH, "@Sdcard:/%s", value); + g_hbl_sd_path[FS_MAX_PATH] = 0; + } else if (strcasecmp(name, "override_key") == 0) { + if (value[0] == '!') { + g_override_by_default = true; + value++; + } else { + g_override_by_default = false; + } + + if (strcasecmp(value, "A") == 0) { + g_override_key_combination = KEY_A; + } else if (strcasecmp(value, "B") == 0) { + g_override_key_combination = KEY_B; + } else if (strcasecmp(value, "X") == 0) { + g_override_key_combination = KEY_X; + } else if (strcasecmp(value, "Y") == 0) { + g_override_key_combination = KEY_Y; + } else if (strcasecmp(value, "LS") == 0) { + g_override_key_combination = KEY_LSTICK; + } else if (strcasecmp(value, "RS") == 0) { + g_override_key_combination = KEY_RSTICK; + } else if (strcasecmp(value, "L") == 0) { + g_override_key_combination = KEY_L; + } else if (strcasecmp(value, "R") == 0) { + g_override_key_combination = KEY_R; + } else if (strcasecmp(value, "ZL") == 0) { + g_override_key_combination = KEY_ZL; + } else if (strcasecmp(value, "ZR") == 0) { + g_override_key_combination = KEY_ZR; + } else if (strcasecmp(value, "PLUS") == 0) { + g_override_key_combination = KEY_PLUS; + } else if (strcasecmp(value, "MINUS") == 0) { + g_override_key_combination = KEY_MINUS; + } else if (strcasecmp(value, "DLEFT") == 0) { + g_override_key_combination = KEY_DLEFT; + } else if (strcasecmp(value, "DUP") == 0) { + g_override_key_combination = KEY_DUP; + } else if (strcasecmp(value, "DRIGHT") == 0) { + g_override_key_combination = KEY_DRIGHT; + } else if (strcasecmp(value, "DDOWN") == 0) { + g_override_key_combination = KEY_DDOWN; + } else if (strcasecmp(value, "SL") == 0) { + g_override_key_combination = KEY_SL; + } else if (strcasecmp(value, "SR") == 0) { + g_override_key_combination = KEY_SR; + } else { + g_override_key_combination = 0; + } + } + } else { + return 0; + } + return 1; +} + +void ContentManagement::LoadConfiguration(FILE *config) { + if (config == NULL) { + return; + } + + char *config_str = new char[0x800]; + if (config_str != NULL) { + /* Read in string. */ + std::fill(config_str, config_str + FS_MAX_PATH, 0); + fread(config_str, 1, 0x7FF, config); + config_str[strlen(config_str)] = 0x0; + + ini_parse_string(config_str, LoaderIniHandler, NULL); + + delete[] config_str; + } + + fclose(config); +} + void ContentManagement::TryMountSdCard() { /* Mount SD card, if psc, bus, and pcv have been created. */ if (!g_has_initialized_fs_dev && HasCreatedTitle(0x0100000000000021) && HasCreatedTitle(0x010000000000000A) && HasCreatedTitle(0x010000000000001A)) { @@ -172,7 +293,23 @@ void ContentManagement::TryMountSdCard() { } if (R_SUCCEEDED(fsdevMountSdmc())) { + ContentManagement::LoadConfiguration(fopen("sdmc:/atmosphere/loader.ini", "r")); g_has_initialized_fs_dev = true; } } } + +bool ContentManagement::ShouldReplaceWithHBL(u64 tid) { + return g_mounted_hbl_nsp && tid == g_override_hbl_tid; +} + +bool ContentManagement::ShouldOverrideContents() { + if (HasCreatedTitle(0x0100000000001000)) { + u64 kDown = 0; + bool keys_triggered = (R_SUCCEEDED(HidManagement::GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0)); + return g_has_initialized_fs_dev && (g_override_by_default ^ keys_triggered); + } else { + /* Always redirect before qlaunch. */ + return g_has_initialized_fs_dev; + } +} \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index f99eb1fcf..c241092a4 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -23,6 +23,7 @@ class ContentManagement { public: static Result MountCode(u64 tid, FsStorageId sid); static Result MountCodeNspOnSd(u64 tid); + static void TryMountHblNspOnSd(); static Result UnmountCode(); static Result MountCodeForTidSid(Registration::TidSid *tid_sid); @@ -33,5 +34,9 @@ class ContentManagement { static bool HasCreatedTitle(u64 tid); static void SetCreatedTitle(u64 tid); + static void LoadConfiguration(FILE *config); static void TryMountSdCard(); + + static bool ShouldReplaceWithHBL(u64 tid); + static bool ShouldOverrideContents(); }; diff --git a/stratosphere/loader/source/ldr_hid.cpp b/stratosphere/loader/source/ldr_hid.cpp new file mode 100644 index 000000000..8bad9377b --- /dev/null +++ b/stratosphere/loader/source/ldr_hid.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <string.h> + +#include "ldr_content_management.hpp" +#include "ldr_hid.hpp" + +static bool g_has_opened_hid_session = false; + +Result HidManagement::GetKeysDown(u64 *keys) { + if (!ContentManagement::HasCreatedTitle(0x0100000000000013) || R_FAILED(hidInitialize())) { + return MAKERESULT(Module_Libnx, LibnxError_InitFail_HID); + } + + hidScanInput(); + *keys = hidKeysDown(CONTROLLER_P1_AUTO); + + hidExit(); + return 0x0; +} \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_hid.hpp b/stratosphere/loader/source/ldr_hid.hpp new file mode 100644 index 000000000..b5529fd20 --- /dev/null +++ b/stratosphere/loader/source/ldr_hid.hpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> + +class HidManagement { + public: + static Result GetKeysDown(u64 *keys); +}; diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index e455fc4b4..8e882bd21 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -19,8 +19,10 @@ #include <cstdio> #include "ldr_npdm.hpp" #include "ldr_registration.hpp" +#include "ldr_content_management.hpp" static NpdmUtils::NpdmCache g_npdm_cache = {0}; +static NpdmUtils::NpdmCache g_original_npdm_cache = {0}; static char g_npdm_path[FS_MAX_PATH] = {0}; Result NpdmUtils::LoadNpdmFromCache(u64 tid, NpdmInfo *out) { @@ -31,6 +33,12 @@ Result NpdmUtils::LoadNpdmFromCache(u64 tid, NpdmInfo *out) { return 0; } +FILE *NpdmUtils::OpenNpdmFromHBL() { + std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0); + snprintf(g_npdm_path, FS_MAX_PATH, "hbl:/main.npdm"); + return fopen(g_npdm_path, "rb"); +} + FILE *NpdmUtils::OpenNpdmFromExeFS() { std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0); snprintf(g_npdm_path, FS_MAX_PATH, "code:/main.npdm"); @@ -45,20 +53,23 @@ FILE *NpdmUtils::OpenNpdmFromSdCard(u64 title_id) { FILE *NpdmUtils::OpenNpdm(u64 title_id) { - FILE *f_out = OpenNpdmFromSdCard(title_id); - if (f_out != NULL) { - return f_out; + if (ContentManagement::ShouldOverrideContents()) { + if (ContentManagement::ShouldReplaceWithHBL(title_id)) { + return OpenNpdmFromHBL(); + } + FILE *f_out = OpenNpdmFromSdCard(title_id); + if (f_out != NULL) { + return f_out; + } } return OpenNpdmFromExeFS(); } -Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { +Result NpdmUtils::LoadNpdmInternal(FILE *f_npdm, NpdmUtils::NpdmCache *cache) { Result rc; - g_npdm_cache.info = (const NpdmUtils::NpdmInfo){0}; - - FILE *f_npdm = OpenNpdm(tid); - + cache->info = (const NpdmUtils::NpdmInfo){0}; + rc = 0x202; if (f_npdm == NULL) { /* For generic "Couldn't open the file" error, just say the file doesn't exist. */ @@ -70,7 +81,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { fseek(f_npdm, 0, SEEK_SET); rc = 0x609; - if ((npdm_size > sizeof(g_npdm_cache.buffer)) || (fread(g_npdm_cache.buffer, 1, npdm_size, f_npdm) != npdm_size)) { + if ((npdm_size > sizeof(cache->buffer)) || (fread(cache->buffer, 1, npdm_size, f_npdm) != npdm_size)) { fclose(f_npdm); return rc; } @@ -83,8 +94,8 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { } /* For ease of access... */ - g_npdm_cache.info.header = (NpdmUtils::NpdmHeader *)(g_npdm_cache.buffer); - NpdmInfo *info = &g_npdm_cache.info; + cache->info.header = (NpdmUtils::NpdmHeader *)(cache->buffer); + NpdmInfo *info = &cache->info; if (info->header->magic != MAGIC_META) { return rc; @@ -98,7 +109,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { return rc; } - info->aci0 = (NpdmAci0 *)(g_npdm_cache.buffer + info->header->aci0_offset); + info->aci0 = (NpdmAci0 *)(cache->buffer + info->header->aci0_offset); if (info->aci0->magic != MAGIC_ACI0) { return rc; @@ -126,7 +137,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { return rc; } - info->acid = (NpdmAcid *)(g_npdm_cache.buffer + info->header->acid_offset); + info->acid = (NpdmAcid *)(cache->buffer + info->header->acid_offset); if (info->acid->magic != MAGIC_ACID) { return rc; @@ -152,7 +163,48 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { info->acid_kac = (void *)((uintptr_t)info->acid + info->acid->kac_offset); + rc = 0; + return rc; +} + +Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { + Result rc; + + rc = LoadNpdmInternal(OpenNpdm(tid), &g_npdm_cache); + if (R_FAILED(rc)) { + return rc; + } + + NpdmInfo *info = &g_npdm_cache.info; + /* Override the ACID/ACI0 title ID, in order to facilitate HBL takeover of any title. */ + info->acid->title_id_range_min = tid; + info->acid->title_id_range_max = tid; + info->aci0->title_id = tid; + + if (ContentManagement::ShouldOverrideContents() && ContentManagement::ShouldReplaceWithHBL(tid) + && R_SUCCEEDED(LoadNpdmInternal(OpenNpdmFromExeFS(), &g_original_npdm_cache))) { + NpdmInfo *original_info = &g_original_npdm_cache.info; + /* Fix pool partition. */ + if (kernelAbove500()) { + info->acid->flags = (info->acid->flags & 0xFFFFFFF9) | (original_info->acid->flags & 0x00000006); + } + /* Fix application type. */ + const u32 original_application_type = GetApplicationType((u32 *)original_info->aci0_kac, original_info->aci0->kac_size/sizeof(u32)) & 7; + u32 *caps = (u32 *)info->aci0_kac; + for (unsigned int i = 0; i < info->aci0->kac_size/sizeof(u32); i++) { + if ((caps[i] & 0x3FFF) == 0x1FFF) { + caps[i] = (caps[i] & 0xFFFE3FFF) | (original_application_type << 14); + } + } + caps = (u32 *)info->acid_kac; + for (unsigned int i = 0; i < info->acid->kac_size/sizeof(u32); i++) { + if ((caps[i] & 0x3FFF) == 0x1FFF) { + caps[i] = (caps[i] & 0xFFFE3FFF) | (original_application_type << 14); + } + } + } + /* We validated! */ info->title_id = tid; *out = *info; diff --git a/stratosphere/loader/source/ldr_npdm.hpp b/stratosphere/loader/source/ldr_npdm.hpp index 28fc465ef..3a7e721ee 100644 --- a/stratosphere/loader/source/ldr_npdm.hpp +++ b/stratosphere/loader/source/ldr_npdm.hpp @@ -50,7 +50,7 @@ class NpdmUtils { u32 magic; u32 size; u32 _0x208; - u32 is_retail; + u32 flags; u64 title_id_range_min; u64 title_id_range_max; u32 fac_offset; @@ -101,9 +101,12 @@ class NpdmUtils { static Result ValidateCapabilities(u32 *acid_caps, size_t num_acid_caps, u32 *aci0_caps, size_t num_aci0_caps); + static FILE *OpenNpdmFromHBL(); static FILE *OpenNpdmFromExeFS(); static FILE *OpenNpdmFromSdCard(u64 tid); static FILE *OpenNpdm(u64 tid); static Result LoadNpdm(u64 tid, NpdmInfo *out); static Result LoadNpdmFromCache(u64 tid, NpdmInfo *out); + private: + static Result LoadNpdmInternal(FILE *f_npdm, NpdmCache *cache); }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index 893d662c3..451093e7c 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -24,12 +24,19 @@ #include "ldr_map.hpp" #include "ldr_random.hpp" #include "ldr_patcher.hpp" +#include "ldr_content_management.hpp" static NsoUtils::NsoHeader g_nso_headers[NSO_NUM_MAX] = {0}; static bool g_nso_present[NSO_NUM_MAX] = {0}; static char g_nso_path[FS_MAX_PATH] = {0}; +FILE *NsoUtils::OpenNsoFromHBL(unsigned int index) { + std::fill(g_nso_path, g_nso_path + FS_MAX_PATH, 0); + snprintf(g_nso_path, FS_MAX_PATH, "hbl:/%s", NsoUtils::GetNsoFileName(index)); + return fopen(g_nso_path, "rb"); +} + FILE *NsoUtils::OpenNsoFromExeFS(unsigned int index) { std::fill(g_nso_path, g_nso_path + FS_MAX_PATH, 0); snprintf(g_nso_path, FS_MAX_PATH, "code:/%s", NsoUtils::GetNsoFileName(index)); @@ -54,14 +61,18 @@ bool NsoUtils::CheckNsoStubbed(unsigned int index, u64 title_id) { } FILE *NsoUtils::OpenNso(unsigned int index, u64 title_id) { - FILE *f_out = OpenNsoFromSdCard(index, title_id); - if (f_out != NULL) { - return f_out; - } else if (CheckNsoStubbed(index, title_id)) { - return NULL; - } else { - return OpenNsoFromExeFS(index); + if (ContentManagement::ShouldOverrideContents()) { + if (ContentManagement::ShouldReplaceWithHBL(title_id)) { + return OpenNsoFromHBL(index); + } + FILE *f_out = OpenNsoFromSdCard(index, title_id); + if (f_out != NULL) { + return f_out; + } else if (CheckNsoStubbed(index, title_id)) { + return NULL; + } } + return OpenNsoFromExeFS(index); } bool NsoUtils::IsNsoPresent(unsigned int index) { diff --git a/stratosphere/loader/source/ldr_nso.hpp b/stratosphere/loader/source/ldr_nso.hpp index 94a18223a..364943346 100644 --- a/stratosphere/loader/source/ldr_nso.hpp +++ b/stratosphere/loader/source/ldr_nso.hpp @@ -97,6 +97,7 @@ class NsoUtils { } } + static FILE *OpenNsoFromHBL(unsigned int index); static FILE *OpenNsoFromExeFS(unsigned int index); static FILE *OpenNsoFromSdCard(unsigned int index, u64 title_id); static bool CheckNsoStubbed(unsigned int index, u64 title_id); diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 3f3d38348..40d9d716d 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -24,15 +24,6 @@ #include "ldr_npdm.hpp" #include "ldr_nso.hpp" -extern "C" { - - bool __attribute__((weak)) kernelAbove600(void) { - u64 tmp; - return (svcGetInfo(&tmp, 21, INVALID_HANDLE, 0) != 0xF001); - } - -} - Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle reslimit_h, u64 arg_flags, ProcessInfo *out_proc_info) { /* Initialize a ProcessInfo using an npdm. */ *out_proc_info = (const ProcessCreation::ProcessInfo){0}; @@ -87,7 +78,7 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle /* 5.0.0+ Pool Partition. */ if (kernelAbove500()) { - u32 pool_partition_id = (npdm->acid->is_retail >> 2) & 0xF; + u32 pool_partition_id = (npdm->acid->flags >> 2) & 0xF; switch (pool_partition_id) { case 0: /* Application. */ if ((application_type & 3) == 2) { From 532b4f4de250dbfcc12577f10f678a8bd97ceff5 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 19 Sep 2018 16:30:11 -0700 Subject: [PATCH 084/489] Loader: Fix HBL pool partition ID copy --- stratosphere/loader/source/ldr_npdm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index 8e882bd21..2bb9eb669 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -187,7 +187,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { NpdmInfo *original_info = &g_original_npdm_cache.info; /* Fix pool partition. */ if (kernelAbove500()) { - info->acid->flags = (info->acid->flags & 0xFFFFFFF9) | (original_info->acid->flags & 0x00000006); + info->acid->flags = (info->acid->flags & 0xFFFFFFC3) | (original_info->acid->flags & 0x0000003C); } /* Fix application type. */ const u32 original_application_type = GetApplicationType((u32 *)original_info->aci0_kac, original_info->aci0->kac_size/sizeof(u32)) & 7; From f622eac36e9dac8460f741a92a96b1db664ac209 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Thu, 20 Sep 2018 20:02:10 +0100 Subject: [PATCH 085/489] fusee: Finish implementing support for 6.0.0 --- fusee/fusee-secondary/src/key_derivation.c | 18 ++++---- fusee/fusee-secondary/src/key_derivation.h | 3 -- fusee/fusee-secondary/src/masterkey.c | 52 ++++++++++++++++++++-- fusee/fusee-secondary/src/masterkey.h | 16 ++++--- 4 files changed, 67 insertions(+), 22 deletions(-) diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index bf9688423..e67d3dfbd 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -25,11 +25,12 @@ #define AL16 ALIGN(16) static const uint8_t AL16 keyblob_seeds[MASTERKEY_REVISION_MAX][0x10] = { - {0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3}, /* Keyblob seed 00. */ - {0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC}, /* Keyblob seed 01. */ - {0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B}, /* Keyblob seed 02. */ - {0x2D, 0x1F, 0x48, 0x80, 0xED, 0xEC, 0xED, 0x3E, 0x3C, 0xF2, 0x48, 0xB5, 0x65, 0x7D, 0xF7, 0xBE}, /* Keyblob seed 03. */ - {0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80}, /* Keyblob seed 04. */ + {0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3}, /* Keyblob seed 00. */ + {0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC}, /* Keyblob seed 01. */ + {0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B}, /* Keyblob seed 02. */ + {0x2D, 0x1F, 0x48, 0x80, 0xED, 0xEC, 0xED, 0x3E, 0x3C, 0xF2, 0x48, 0xB5, 0x65, 0x7D, 0xF7, 0xBE}, /* Keyblob seed 03. */ + {0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80}, /* Keyblob seed 04. */ + {0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0} /* Keyblob seed 05. */ }; static const uint8_t AL16 keyblob_mac_seed[0x10] = { @@ -107,7 +108,7 @@ static int decrypt_keyblob(const nx_keyblob_t *keyblobs, uint32_t revision, uint } int load_package1_key(uint32_t revision) { - if (revision > MASTERKEY_REVISION_500_CURRENT) { + if (revision > MASTERKEY_REVISION_600_CURRENT) { return -1; } @@ -141,7 +142,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui clear_aes_keyslot(0xE); /* Get needed data. */ - set_aes_keyslot(0xC, g_dec_keyblobs[MASTERKEY_REVISION_500_CURRENT].keys[0], 0x10); + set_aes_keyslot(0xC, g_dec_keyblobs[MASTERKEY_REVISION_600_CURRENT].keys[0], 0x10); /* Also set the Package1 key for the revision that is stored on the eMMC boot0 partition. */ load_package1_key(available_revision); @@ -161,6 +162,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10); break; case EXOSPHERE_TARGET_FIRMWARE_500: + case EXOSPHERE_TARGET_FIRMWARE_600: decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); @@ -171,7 +173,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui } /* Setup master key revision, derive older master keys for use. */ - return mkey_detect_revision(); + return mkey_detect_revision(fuse_get_retail_type() != 0); } /* Sets final keyslot flags, for handover to TZ/Exosphere. Setting these will prevent the BPMP from using the device key or master key. */ diff --git a/fusee/fusee-secondary/src/key_derivation.h b/fusee/fusee-secondary/src/key_derivation.h index f55b4c66e..5b64f76d1 100644 --- a/fusee/fusee-secondary/src/key_derivation.h +++ b/fusee/fusee-secondary/src/key_derivation.h @@ -20,7 +20,6 @@ #include <stddef.h> #include <stdbool.h> #include <stdint.h> -#include "masterkey.h" typedef enum BisPartition { BisPartition_Calibration = 0, @@ -41,11 +40,9 @@ typedef struct nx_keyblob_t { }; } nx_keyblob_t; -/* TSEC fw must be 0x100-byte-aligned. */ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_fw, size_t tsec_fw_size); int load_package1_key(uint32_t revision); void finalize_nx_keydata(uint32_t target_firmware); - void derive_bis_key(void *dst, BisPartition partition_id, uint32_t target_firmware); #endif diff --git a/fusee/fusee-secondary/src/masterkey.c b/fusee/fusee-secondary/src/masterkey.c index 6d738f23d..bf31ec581 100644 --- a/fusee/fusee-secondary/src/masterkey.c +++ b/fusee/fusee-secondary/src/masterkey.c @@ -26,8 +26,21 @@ static unsigned int g_mkey_revision = 0; static bool g_determined_mkey_revision = false; static uint8_t g_old_masterkeys[MASTERKEY_REVISION_MAX][0x10]; +static uint8_t g_old_devicekeys[MASTERKEY_NUM_NEW_DEVICE_KEYS - 1][0x10]; /* TODO: Extend with new vectors, as needed. */ +/* Dev unit keys. */ +static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = +{ + {0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE}, /* Zeroes encrypted with Master Key 00. */ + {0x39, 0x33, 0xF9, 0x31, 0xBA, 0xE4, 0xA7, 0x21, 0x2C, 0xDD, 0xB7, 0xD8, 0xB4, 0x4E, 0x37, 0x23}, /* Master key 00 encrypted with Master key 01. */ + {0x97, 0x29, 0xB0, 0x32, 0x43, 0x14, 0x8C, 0xA6, 0x85, 0xE9, 0x5A, 0x94, 0x99, 0x39, 0xAC, 0x5D}, /* Master key 01 encrypted with Master key 02. */ + {0x2C, 0xCA, 0x9C, 0x31, 0x1E, 0x07, 0xB0, 0x02, 0x97, 0x0A, 0xD8, 0x03, 0xA2, 0x76, 0x3F, 0xA3}, /* Master key 02 encrypted with Master key 03. */ + {0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ + {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ +}; + +/* Retail unit keys. */ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = { {0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D}, /* Zeroes encrypted with Master Key 00. */ @@ -35,16 +48,17 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = {0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72}, /* Master key 01 encrypted with Master key 02. */ {0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */ {0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ + {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ }; -bool check_mkey_revision(unsigned int revision) { +static bool check_mkey_revision(unsigned int revision, bool is_retail) { uint8_t final_vector[0x10]; unsigned int check_keyslot = KEYSLOT_SWITCH_MASTERKEY; if (revision > 0) { /* Generate old master key array. */ for (unsigned int i = revision; i > 0; i--) { - se_aes_ecb_decrypt_block(check_keyslot, g_old_masterkeys[i-1], 0x10, mkey_vectors[i], 0x10); + se_aes_ecb_decrypt_block(check_keyslot, g_old_masterkeys[i-1], 0x10, is_retail ? mkey_vectors[i] : mkey_vectors_dev[i], 0x10); set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_masterkeys[i-1], 0x10); check_keyslot = KEYSLOT_SWITCH_TEMPKEY; } @@ -59,13 +73,13 @@ bool check_mkey_revision(unsigned int revision) { return true; } -int mkey_detect_revision(void) { +int mkey_detect_revision(bool is_retail) { if (g_determined_mkey_revision) { generic_panic(); } for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) { - if (check_mkey_revision(rev)) { + if (check_mkey_revision(rev, is_retail)) { g_determined_mkey_revision = true; g_mkey_revision = rev; break; @@ -105,3 +119,33 @@ unsigned int mkey_get_keyslot(unsigned int revision) { return KEYSLOT_SWITCH_TEMPKEY; } } + +void set_old_devkey(unsigned int revision, const uint8_t *key) { + if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_600_CURRENT <= revision) { + generic_panic(); + } + + memcpy(g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], key, 0x10); +} + +unsigned int devkey_get_keyslot(unsigned int revision) { + if (!g_determined_mkey_revision || revision >= MASTERKEY_REVISION_MAX) { + generic_panic(); + } + + if (revision > g_mkey_revision) { + generic_panic(); + } + + if (revision >= 1) { + if (revision == MASTERKEY_REVISION_600_CURRENT) { + return KEYSLOT_SWITCH_DEVICEKEY; + } else { + /* Load into a temp keyslot. */ + set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], 0x10); + return KEYSLOT_SWITCH_TEMPKEY; + } + } else { + return KEYSLOT_SWITCH_4XOLDDEVICEKEY; + } +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/masterkey.h b/fusee/fusee-secondary/src/masterkey.h index a491b23ef..531eebc58 100644 --- a/fusee/fusee-secondary/src/masterkey.h +++ b/fusee/fusee-secondary/src/masterkey.h @@ -19,22 +19,24 @@ /* This is glue code to enable master key support across versions. */ -/* TODO: Update to 0x6 on release of new master key. */ -#define MASTERKEY_REVISION_MAX 0x5 +/* TODO: Update to 0x7 on release of new master key. */ +#define MASTERKEY_REVISION_MAX 0x6 #define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_300 0x01 #define MASTERKEY_REVISION_301_302 0x02 #define MASTERKEY_REVISION_400_410 0x03 -#define MASTERKEY_REVISION_500_CURRENT 0x04 +#define MASTERKEY_REVISION_500_510 0x04 +#define MASTERKEY_REVISION_600_CURRENT 0x05 #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) -/* This should be called during initialization. */ -int mkey_detect_revision(void); +/* This should be called early on in initialization. */ +int mkey_detect_revision(bool is_retail); unsigned int mkey_get_revision(void); - unsigned int mkey_get_keyslot(unsigned int revision); +void set_old_devkey(unsigned int revision, const uint8_t *key); +unsigned int devkey_get_keyslot(unsigned int revision); -#endif +#endif \ No newline at end of file From a2b4d9168d7dab91d9a5a17287bacc621f654be0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 20 Sep 2018 13:47:20 -0700 Subject: [PATCH 086/489] exosphere: ConfigItem_IsQuestUnit was added in 3.0, not 4.0 --- exosphere/src/configitem.c | 6 +++--- exosphere/src/configitem.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 0e40c74c6..577f74502 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -117,9 +117,9 @@ uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) { case CONFIGITEM_BATTERYPROFILE: *p_outvalue = (int)g_battery_profile; break; - case CONFIGITEM_ODM4BIT10_4X: - /* Added on 4.x ... where is it being used? */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + case CONFIGITEM_ISQUESTUNIT: + /* Added on 3.0, used to determine whether console is a kiosk unit. */ + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_300) { *p_outvalue = (fuse_get_reserved_odm(4) >> 10) & 1; } else { result = 2; diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index bce93f6ee..864d76030 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -34,7 +34,7 @@ typedef enum { CONFIGITEM_ISDEBUGMODE = 11, CONFIGITEM_KERNELMEMORYCONFIGURATION = 12, CONFIGITEM_BATTERYPROFILE = 13, - CONFIGITEM_ODM4BIT10_4X = 14, + CONFIGITEM_ISQUESTUNIT = 14, CONFIGITEM_NEWHARDWARETYPE_5X = 15, CONFIGITEM_NEWKEYGENERATION_5X = 16, CONFIGITEM_PACKAGE2HASH_5X = 17, From 840242b68e41ab52caa64f954ffa33c0b387bf06 Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Sat, 22 Sep 2018 05:14:43 +0200 Subject: [PATCH 087/489] =?UTF-8?q?started=20on=20centralized=20printing/l?= =?UTF-8?q?ogging=20some=20character=20problems=20with=20"atmosph=C3=A8re"?= =?UTF-8?q?=20and=20such=20strings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fusee/fusee-secondary/src/main.c | 11 +-- fusee/fusee-secondary/src/print.c | 84 ++++++++++++++++++++ fusee/fusee-secondary/src/print.h | 38 +++++++++ fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 11 +-- 4 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 fusee/fusee-secondary/src/print.c create mode 100644 fusee/fusee-secondary/src/print.h diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 5048bd642..89acf0589 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -32,6 +32,7 @@ #include "gpt.h" #include "display/video_fb.h" #include "sdmmc/sdmmc.h" +#include "print.h" extern void (*__program_exit_callback)(int rc); @@ -91,23 +92,23 @@ int main(int argc, void **argv) { /* Initialize the display, console, FS, etc. */ setup_env(); - printf(u8"Welcome to Atmosphère Fusée Stage 2!\n"); - printf("Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]); + print(PRINT_LOG_MANDATORY, u8"Welcome to Atmosphère Fusée Stage 2!\n"); + print(PRINT_LOG_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]); /* This will load all remaining binaries off of the SD. */ load_payload(g_stage2_args->bct0); - printf("Loaded payloads!\n"); + print(PRINT_LOG_INFO, "Loaded payloads!\n"); g_do_nxboot = loader_ctx->chainload_entrypoint == 0; if (g_do_nxboot) { - printf("Now performing nxboot.\n"); + print(PRINT_LOG_INFO, "Now performing nxboot.\n"); uint32_t boot_memaddr = nxboot_main(); nxboot_finish(boot_memaddr); } else { /* TODO: What else do we want to do in terms of argc/argv? */ const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint]; - printf("Now chainloading.\n"); + print(PRINT_LOG_INFO, "Now chainloading.\n"); g_chainloader_argc = 1; strcpy(g_chainloader_arg_data, path); } diff --git a/fusee/fusee-secondary/src/print.c b/fusee/fusee-secondary/src/print.c new file mode 100644 index 000000000..0cf3f2a90 --- /dev/null +++ b/fusee/fusee-secondary/src/print.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "print.h" + +#include "display/video_fb.h" + +PrintLogLevel g_print_log_level = PRINT_LOG_DEBUG; + +void vprintk(const char *fmt, va_list args) +{ + char buf[PRINT_MESSAGE_MAX_LENGTH]; + vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args); + video_puts(buf); +} + +void printk(const char *fmt, ...) +{ + va_list list; + va_start(list, fmt); + vprintk(fmt, list); + va_end(list); +} + +/** + * print - logs a message based on its message_level + * + * If the level is below g_message_level it will not be shown + * but logged to UART (UART is TO DO) + */ +void print(PrintLogLevel printLogLevel, const char * fmt, ...) +{ + char typebuf[] = "[%s] %s"; + char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; + + /* apply prefix and append message format */ + /* TODO: add coloring to the output */ + switch(printLogLevel) + { + case PRINT_LOG_DEBUG: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt); + break; + case PRINT_LOG_INFO: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt); + break; + case PRINT_LOG_MANDATORY: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt); + break; + case PRINT_LOG_WARNING: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt); + break; + case PRINT_LOG_ERROR: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt); + break; + default: + break; + } + + /* input arguments for UART logging */ + va_list args; + va_start(args, fmt); + vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, buf, args); + va_end(args); + + /* TODO: implement SD and/or UART logging */ + + /* don't print to screen if below log level */ + if (printLogLevel < g_print_log_level) return; + + printk(buf); +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/print.h b/fusee/fusee-secondary/src/print.h new file mode 100644 index 000000000..9e06eff0e --- /dev/null +++ b/fusee/fusee-secondary/src/print.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_PRINT_H +#define FUSEE_PRINT_H + +#define PRINT_MESSAGE_MAX_LENGTH 512 + +typedef enum { + PRINT_LOG_DEBUG = 0, + PRINT_LOG_INFO, + PRINT_LOG_MANDATORY, + PRINT_LOG_WARNING, + PRINT_LOG_ERROR +} PrintLogLevel; + +#include <stdint.h> +#include "../../fusee-primary/src/lib/vsprintf.h" + +extern PrintLogLevel g_print_log_level; + +//void vprintk(const char *fmt, va_list args); +void print(PrintLogLevel printLogLevel, const char* fmt, ...); + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index c831493f5..cf0adb5a2 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -31,6 +31,7 @@ #include "../pmc.h" #include "../max7762x.h" #include "../lib/driver_utils.h" +#include "../print.h" static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; @@ -46,21 +47,21 @@ static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_l switch (log_level) { case SDMMC_LOG_ERROR: - printk("%s [ERROR]: ", sdmmc->name); + print(PRINT_LOG_ERROR, "%s", sdmmc->name); break; case SDMMC_LOG_WARN: - printk("%s [WARN]: ", sdmmc->name); + print(PRINT_LOG_WARNING, "%s", sdmmc->name); break; case SDMMC_LOG_INFO: - printk("%s [INFO]: ", sdmmc->name); + print(PRINT_LOG_INFO, "%s", sdmmc->name); break; case SDMMC_LOG_DEBUG: - printk("%s [DEBUG]: ", sdmmc->name); + print(PRINT_LOG_DEBUG, "%s", sdmmc->name); break; default: break; } - + vprintk(fmt, list); printk("\n"); } From 7548c8ecfa56bcc4b5e83667e3fcf5157498154f Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Sun, 23 Sep 2018 23:18:41 +0200 Subject: [PATCH 088/489] rather call the files log.c and log.h changed LOG_LEVEL order export only externaly used functions add todos --- fusee/fusee-secondary/src/log.c | 104 +++++++++++++++++++ fusee/fusee-secondary/src/{print.h => log.h} | 28 ++--- fusee/fusee-secondary/src/print.c | 84 --------------- 3 files changed, 120 insertions(+), 96 deletions(-) create mode 100644 fusee/fusee-secondary/src/log.c rename fusee/fusee-secondary/src/{print.h => log.h} (57%) delete mode 100644 fusee/fusee-secondary/src/print.c diff --git a/fusee/fusee-secondary/src/log.c b/fusee/fusee-secondary/src/log.c new file mode 100644 index 000000000..050b2fccc --- /dev/null +++ b/fusee/fusee-secondary/src/log.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> + +#include "log.h" +#include "display/video_fb.h" + +/* default log level for screen output */ +ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_MANDATORY; + +void log_set_log_level(ScreenLogLevel log_level) { + g_screen_log_level = log_level; +} + +void log_to_uart(const char *message) { + /* TODO: add UART logging */ +} + +void print_to_screen(ScreenLogLevel screenLogLevel, char *message) { + /* don't print to screen if below log level */ + if(g_screen_log_level == SCREEN_LOG_LEVEL_NONE || screenLogLevel > g_screen_log_level) return; + + //video_puts(buf); + printf(message); +} + +/** + * vprintk - logs a message to the console + * + * This text will not be colored or prefixed but logged to UART + * UART is TODO + */ +void vprint(ScreenLogLevel screenLogLevel, const char *fmt, va_list args) +{ + char buf[PRINT_MESSAGE_MAX_LENGTH]; + vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args); + + /* log to UART */ + log_to_uart(buf); + + print_to_screen(screenLogLevel, buf); +} + +/** + * print - logs a message and prints it to screen based on its screenLogLevel + * + * If the level is below g_screen_log_level it will not be shown but logged to UART + * UART is TODO + */ +void print(ScreenLogLevel screenLogLevel, const char * fmt, ...) +{ + char typebuf[] = "[%s] %s"; + char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; + char message[PRINT_MESSAGE_MAX_LENGTH] = {}; + + /* apply prefix and append message format */ + /* TODO: add coloring to the output */ + /* TODO: make splash disappear if level > MANDATORY */ + switch(screenLogLevel) + { + case SCREEN_LOG_LEVEL_ERROR: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt); + break; + case SCREEN_LOG_LEVEL_WARNING: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt); + break; + case SCREEN_LOG_LEVEL_MANDATORY: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt); + break; + case SCREEN_LOG_LEVEL_INFO: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt); + break; + case SCREEN_LOG_LEVEL_DEBUG: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt); + break; + default: + break; + } + + /* input arguments */ + va_list args; + va_start(args, fmt); + vsnprintf(message, PRINT_MESSAGE_MAX_LENGTH, buf, args); + va_end(args); + + /* log to UART */ + log_to_uart(message); + + print_to_screen(screenLogLevel, message); +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/print.h b/fusee/fusee-secondary/src/log.h similarity index 57% rename from fusee/fusee-secondary/src/print.h rename to fusee/fusee-secondary/src/log.h index 9e06eff0e..5be2964c9 100644 --- a/fusee/fusee-secondary/src/print.h +++ b/fusee/fusee-secondary/src/log.h @@ -19,20 +19,24 @@ #define PRINT_MESSAGE_MAX_LENGTH 512 -typedef enum { - PRINT_LOG_DEBUG = 0, - PRINT_LOG_INFO, - PRINT_LOG_MANDATORY, - PRINT_LOG_WARNING, - PRINT_LOG_ERROR -} PrintLogLevel; - -#include <stdint.h> +//#include <stdint.h> #include "../../fusee-primary/src/lib/vsprintf.h" -extern PrintLogLevel g_print_log_level; +typedef enum { + SCREEN_LOG_LEVEL_NONE = 0, + SCREEN_LOG_LEVEL_ERROR = 1, + SCREEN_LOG_LEVEL_WARNING = 2, + SCREEN_LOG_LEVEL_MANDATORY = 3, /* no log prefix */ + SCREEN_LOG_LEVEL_INFO = 4, + SCREEN_LOG_LEVEL_DEBUG = 5 +} ScreenLogLevel; -//void vprintk(const char *fmt, va_list args); -void print(PrintLogLevel printLogLevel, const char* fmt, ...); +/* TODO: make this configurable by BCT.ini */ +extern ScreenLogLevel g_screen_log_level; + +void log_set_log_level(ScreenLogLevel screen_log_level); +void log_to_uart(const char *message); +void vprint(ScreenLogLevel screenLogLevel, const char *fmt, va_list args); +void print(ScreenLogLevel screenLogLevel, const char* fmt, ...); #endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/print.c b/fusee/fusee-secondary/src/print.c deleted file mode 100644 index 0cf3f2a90..000000000 --- a/fusee/fusee-secondary/src/print.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "print.h" - -#include "display/video_fb.h" - -PrintLogLevel g_print_log_level = PRINT_LOG_DEBUG; - -void vprintk(const char *fmt, va_list args) -{ - char buf[PRINT_MESSAGE_MAX_LENGTH]; - vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args); - video_puts(buf); -} - -void printk(const char *fmt, ...) -{ - va_list list; - va_start(list, fmt); - vprintk(fmt, list); - va_end(list); -} - -/** - * print - logs a message based on its message_level - * - * If the level is below g_message_level it will not be shown - * but logged to UART (UART is TO DO) - */ -void print(PrintLogLevel printLogLevel, const char * fmt, ...) -{ - char typebuf[] = "[%s] %s"; - char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; - - /* apply prefix and append message format */ - /* TODO: add coloring to the output */ - switch(printLogLevel) - { - case PRINT_LOG_DEBUG: - snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt); - break; - case PRINT_LOG_INFO: - snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt); - break; - case PRINT_LOG_MANDATORY: - snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt); - break; - case PRINT_LOG_WARNING: - snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt); - break; - case PRINT_LOG_ERROR: - snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt); - break; - default: - break; - } - - /* input arguments for UART logging */ - va_list args; - va_start(args, fmt); - vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, buf, args); - va_end(args); - - /* TODO: implement SD and/or UART logging */ - - /* don't print to screen if below log level */ - if (printLogLevel < g_print_log_level) return; - - printk(buf); -} \ No newline at end of file From 8cc266174dd1cfa49c057679784824f06d719fab Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Sun, 23 Sep 2018 23:22:25 +0200 Subject: [PATCH 089/489] change all print* calls to use the new print with a log_level --- .../fusee-secondary/src/exception_handlers.c | 19 +++---- fusee/fusee-secondary/src/lib/driver_utils.h | 4 +- fusee/fusee-secondary/src/loader.c | 3 +- fusee/fusee-secondary/src/main.c | 13 ++--- fusee/fusee-secondary/src/nxboot.c | 51 ++++++++++--------- fusee/fusee-secondary/src/package2.c | 7 +-- fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 18 ++++--- fusee/fusee-secondary/src/utils.c | 17 +++++-- fusee/fusee-secondary/src/utils.h | 1 + 9 files changed, 79 insertions(+), 54 deletions(-) diff --git a/fusee/fusee-secondary/src/exception_handlers.c b/fusee/fusee-secondary/src/exception_handlers.c index e8d34f702..e3a74a8bb 100644 --- a/fusee/fusee-secondary/src/exception_handlers.c +++ b/fusee/fusee-secondary/src/exception_handlers.c @@ -20,6 +20,7 @@ #include "lib/driver_utils.h" #include "utils.h" #include "display/video_fb.h" +#include "log.h" #define CODE_DUMP_SIZE 0x30 #define STACK_DUMP_SIZE 0x60 @@ -55,26 +56,26 @@ void exception_handler_main(uint32_t *registers, unsigned int exception_type) { uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE; - printk("\nSomething went wrong...\n"); + print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n"); code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE); stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE); - printk("\nException type: %s\n", exception_names[exception_type]); - printk("\nRegisters:\n\n"); + print(SCREEN_LOG_LEVEL_ERROR, "\nException type: %s\n", exception_names[exception_type]); + print(SCREEN_LOG_LEVEL_ERROR, "\nRegisters:\n\n"); /* Print r0 to pc. */ for (int i = 0; i < 16; i += 2) { - printk("%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]); + print(SCREEN_LOG_LEVEL_ERROR, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]); } /* Print cpsr. */ - printk("%-7s%08"PRIX32"\n", register_names[16], registers[16]); + print(SCREEN_LOG_LEVEL_ERROR, "%-7s%08"PRIX32"\n", register_names[16], registers[16]); - printk("\nCode dump:\n"); + print(SCREEN_LOG_LEVEL_ERROR, "\nCode dump:\n"); hexdump(code_dump, code_dump_size, instr_addr); - printk("\nStack dump:\n"); + print(SCREEN_LOG_LEVEL_ERROR, "\nStack dump:\n"); hexdump(stack_dump, stack_dump_size, registers[13]); - printk("\n"); - fatal_error("An exception occured!\n"); + print(SCREEN_LOG_LEVEL_ERROR, "\n"); + fatal_error("An exception occurred!\n"); } diff --git a/fusee/fusee-secondary/src/lib/driver_utils.h b/fusee/fusee-secondary/src/lib/driver_utils.h index 24cde1ed7..851e2d1d9 100644 --- a/fusee/fusee-secondary/src/lib/driver_utils.h +++ b/fusee/fusee-secondary/src/lib/driver_utils.h @@ -20,7 +20,7 @@ #include <stdio.h> #include <stdarg.h> -#define vprintk vprintf -#define printk printf +//#define vprint vprintf +//#define print printf #endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/loader.c b/fusee/fusee-secondary/src/loader.c index b69695532..1fc54206c 100644 --- a/fusee/fusee-secondary/src/loader.c +++ b/fusee/fusee-secondary/src/loader.c @@ -24,6 +24,7 @@ #include "fs_utils.h" #include "stage2.h" #include "lib/ini.h" +#include "log.h" static loader_ctx_t g_loader_ctx = {0}; @@ -103,7 +104,7 @@ static void load_list_entry(const char *key) { } static void parse_loadlist(const char *ll) { - printf("Parsing load list: %s\n", ll); + print(SCREEN_LOG_LEVEL_DEBUG, "Parsing load list: %s\n", ll); char load_list[0x200] = {0}; strncpy(load_list, ll, 0x200 - 1); diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 89acf0589..b598093f5 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -19,6 +19,7 @@ #include <string.h> #include <errno.h> #include <malloc.h> + #include "utils.h" #include "panic.h" #include "exception_handlers.h" @@ -32,7 +33,7 @@ #include "gpt.h" #include "display/video_fb.h" #include "sdmmc/sdmmc.h" -#include "print.h" +#include "log.h" extern void (*__program_exit_callback)(int rc); @@ -92,23 +93,23 @@ int main(int argc, void **argv) { /* Initialize the display, console, FS, etc. */ setup_env(); - print(PRINT_LOG_MANDATORY, u8"Welcome to Atmosphère Fusée Stage 2!\n"); - print(PRINT_LOG_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]); + print(SCREEN_LOG_LEVEL_MANDATORY, u8"Welcome to Atmosphère Fusée Stage 2!\n"); + print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]); /* This will load all remaining binaries off of the SD. */ load_payload(g_stage2_args->bct0); - print(PRINT_LOG_INFO, "Loaded payloads!\n"); + print(SCREEN_LOG_LEVEL_INFO, "Loaded payloads!\n"); g_do_nxboot = loader_ctx->chainload_entrypoint == 0; if (g_do_nxboot) { - print(PRINT_LOG_INFO, "Now performing nxboot.\n"); + print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n"); uint32_t boot_memaddr = nxboot_main(); nxboot_finish(boot_memaddr); } else { /* TODO: What else do we want to do in terms of argc/argv? */ const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint]; - print(PRINT_LOG_INFO, "Now chainloading.\n"); + print(SCREEN_LOG_LEVEL_INFO, "Now chainloading.\n"); g_chainloader_argc = 1; strcpy(g_chainloader_arg_data, path); } diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 68396210b..3c21786cf 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -45,6 +45,7 @@ #define u8 uint8_t #define u32 uint32_t #include "exosphere_bin.h" +#include "log.h" #undef u8 #undef u32 @@ -175,6 +176,7 @@ static void nxboot_move_bootconfig() { fatal_error("[NXBOOT]: Failed to open BootConfig from eMMC!\n"); } if (fread(bootconfig, 0x4000, 1, bcfile) < 1) { + fclose(bcfile); fatal_error("[NXBOOT]: Failed to read BootConfig!\n"); } fclose(bcfile); @@ -218,7 +220,7 @@ uint32_t nxboot_main(void) { } /* Read Package2 from a file, otherwise from its partition(s). */ - printf("[NXBOOT]: Reading package2...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Reading package2...\n"); if (loader_ctx->package2_path[0] != '\0') { pk2file = fopen(loader_ctx->package2_path, "rb"); if (pk2file == NULL) { @@ -230,26 +232,29 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Failed to open Package2 from eMMC: %s!\n", strerror(errno)); } if (fseek(pk2file, 0x4000, SEEK_SET) != 0) { - fatal_error("[NXBOOT]: Failed to seek Package2 in eMMC: %s!\n", strerror(errno)); fclose(pk2file); + fatal_error("[NXBOOT]: Failed to seek Package2 in eMMC: %s!\n", strerror(errno)); } } setvbuf(pk2file, NULL, _IONBF, 0); /* Workaround. */ if (fread(package2, sizeof(package2_header_t), 1, pk2file) < 1) { + fclose(pk2file); fatal_error("[NXBOOT]: Failed to read Package2!\n"); } package2_size = package2_meta_get_size(&package2->metadata); if ((package2_size > PACKAGE2_SIZE_MAX) || (package2_size <= sizeof(package2_header_t))) { + fclose(pk2file); fatal_error("[NXBOOT]: Package2 is too big or too small!\n"); } if (fread(package2->data, package2_size - sizeof(package2_header_t), 1, pk2file) < 1) { + fclose(pk2file); fatal_error("[NXBOOT]: Failed to read Package2!\n"); } fclose(pk2file); /* Read and parse boot0. */ - printf("[NXBOOT]: Reading boot0...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Reading boot0...\n"); boot0 = fopen("boot0:/", "rb"); if ((boot0 == NULL) || (package1_read_and_parse_boot0(&package1loader, &package1loader_size, g_keyblobs, &available_revision, boot0) == -1)) { fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno)); @@ -286,17 +291,17 @@ uint32_t nxboot_main(void) { if (!target_firmware) fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); else - printf("[NXBOOT]: Detected target firmware %ld!\n", target_firmware); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware); /* Setup boot configuration for Exosphère. */ nxboot_configure_exosphere(target_firmware); - + /* Initialize Boot Reason on older firmware versions. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { - printf("[NXBOOT]: Initializing Boot Reason...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Initializing Boot Reason...\n"); nxboot_set_bootreason(); } - + /* Derive keydata. */ if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) { fatal_error("[NXBOOT]: Key derivation failed!\n"); @@ -311,7 +316,7 @@ uint32_t nxboot_main(void) { /* Allocate memory for the warmboot firmware. */ warmboot_fw = malloc(warmboot_fw_size); - + if (warmboot_fw == NULL) { fatal_error("[NXBOOT]: Out of memory!\n"); } @@ -333,7 +338,7 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Could not read the warmboot firmware from Package1!\n"); } } - + /* Select the right address for the warmboot firmware. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { warmboot_memaddr = (void *)0x8000D000; @@ -342,23 +347,23 @@ uint32_t nxboot_main(void) { } else { warmboot_memaddr = (void *)0x4003D800; } - - printf("[NXBOOT]: Copying warmboot firmware...\n"); - + + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Copying warmboot firmware...\n"); + /* Copy the warmboot firmware and set the address in PMC if necessary. */ if (warmboot_fw && (warmboot_fw_size > 0)) { memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size); if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) pmc->scratch1 = (uint32_t)warmboot_memaddr; } - - printf("[NXBOOT]: Rebuilding package2...\n"); - + + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Rebuilding package2...\n"); + /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); - printf(u8"[NXBOOT]: Reading Exosphère...\n"); - + print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Reading Exosphère...\n"); + /* Select the right address for Exosphère. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { exosphere_memaddr = (void *)0x4002D000; @@ -382,11 +387,11 @@ uint32_t nxboot_main(void) { } else { memcpy(exosphere_memaddr, exosphere_bin, exosphere_bin_size); } - + /* Move BootConfig. */ - printf("[NXBOOT]: Moving BootConfig...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Moving BootConfig...\n"); nxboot_move_bootconfig(); - + /* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == EXOSPHERE_TARGET_FIRMWARE_300) { const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; @@ -395,7 +400,7 @@ uint32_t nxboot_main(void) { else if (!strcmp(package1loader_header->build_timestamp, "20170710161758")) pmc->secure_scratch32 = 0x104; /* Warmboot 3.0.1/3.0.2 security check. */ } - + /* Clean up. */ free(package1loader); if (loader_ctx->tsecfw_path[0] != '\0') { @@ -405,8 +410,8 @@ uint32_t nxboot_main(void) { free(warmboot_fw); } free(package2); - - printf("[NXBOOT]: Powering on the CCPLEX...\n"); + + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Powering on the CCPLEX...\n"); /* Display splash screen. */ display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 28f210b25..51ec914ff 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -27,6 +27,7 @@ #define u8 uint8_t #define u32 uint32_t #include "thermosphere_bin.h" +#include "log.h" #undef u8 #undef u32 @@ -52,7 +53,7 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm /* First things first: Decrypt Package2 in place. */ package2_decrypt(package2); - printf("Decrypted package2!\n"); + print(SCREEN_LOG_LEVEL_DEBUG, "Decrypted package2!\n"); kernel_size = package2_get_src_section(&kernel, package2, PACKAGE2_SECTION_KERNEL); @@ -66,11 +67,11 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm /* Perform any patches we want to the NX kernel. */ package2_patch_kernel(kernel, kernel_size); - printf("Rebuilding the INI1 section...\n"); + print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n"); package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1); /* Perform any patches to the INI1, rebuilding it (This is where our built-in sysmodules will be added.) */ rebuilt_ini1 = package2_rebuild_ini1(orig_ini1, target_firmware); - printf("Rebuilt INI1...\n"); + print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilt INI1...\n"); /* Allocate the rebuilt package2. */ rebuilt_package2_size = sizeof(package2_header_t) + kernel_size + align_to_4(thermosphere_size) + align_to_4(rebuilt_ini1->size); diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index cf0adb5a2..eebdceb93 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -31,7 +31,7 @@ #include "../pmc.h" #include "../max7762x.h" #include "../lib/driver_utils.h" -#include "../print.h" +#include "../log.h" static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; @@ -44,26 +44,30 @@ static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_l { if (log_level > g_sdmmc_log_level) return; + + char sdmmc_fmt[] = "%s: "; + ScreenLogLevel screen_log_level = SCREEN_LOG_LEVEL_ERROR; switch (log_level) { case SDMMC_LOG_ERROR: - print(PRINT_LOG_ERROR, "%s", sdmmc->name); + screen_log_level = SCREEN_LOG_LEVEL_ERROR; break; case SDMMC_LOG_WARN: - print(PRINT_LOG_WARNING, "%s", sdmmc->name); + screen_log_level = SCREEN_LOG_LEVEL_WARNING; break; case SDMMC_LOG_INFO: - print(PRINT_LOG_INFO, "%s", sdmmc->name); + screen_log_level = SCREEN_LOG_LEVEL_DEBUG; break; case SDMMC_LOG_DEBUG: - print(PRINT_LOG_DEBUG, "%s", sdmmc->name); + screen_log_level = SCREEN_LOG_LEVEL_DEBUG; break; default: break; } - vprintk(fmt, list); - printk("\n"); + print(screen_log_level, sdmmc_fmt, sdmmc->name); + vprint(screen_log_level, fmt, list); + print(screen_log_level, "\n"); } void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...) diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index 7f2de0da9..0ceacd95e 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -24,6 +24,7 @@ #include "timers.h" #include "btn.h" #include "panic.h" +#include "log.h" #include <stdio.h> #include <inttypes.h> @@ -76,17 +77,27 @@ __attribute__((noreturn)) void wait_for_button_and_reboot(void) { } } +void wait_for_button(void) { + uint32_t button; + while (true) { + button = btn_read(); + if (button) { + return; + } + } +} + __attribute__ ((noreturn)) void generic_panic(void) { panic(0xFF000006); } __attribute__((noreturn)) void fatal_error(const char *fmt, ...) { va_list args; - printf("Fatal error: "); + print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: "); va_start(args, fmt); - vprintf(fmt, args); + vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args); va_end(args); - printf("\n Press POWER to reboot.\n"); + print(SCREEN_LOG_LEVEL_ERROR, "\n Press POWER to reboot.\n"); wait_for_button_and_reboot(); } diff --git a/fusee/fusee-secondary/src/utils.h b/fusee/fusee-secondary/src/utils.h index cfc0cbdf4..3d84a563d 100644 --- a/fusee/fusee-secondary/src/utils.h +++ b/fusee/fusee-secondary/src/utils.h @@ -124,6 +124,7 @@ __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); __attribute__((noreturn)) void car_reboot(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void); +void wait_for_button(void); __attribute__((noreturn)) void generic_panic(void); From 1eb3d7969eaa3e3d38cda47f01f44b6362eb39a3 Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Mon, 24 Sep 2018 00:02:58 +0200 Subject: [PATCH 090/489] changes to fit the codestyle improved a comment removed unused code and imports --- fusee/fusee-secondary/src/lib/driver_utils.h | 5 +---- fusee/fusee-secondary/src/log.c | 21 ++++++++++---------- fusee/fusee-secondary/src/log.h | 9 ++++----- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/fusee/fusee-secondary/src/lib/driver_utils.h b/fusee/fusee-secondary/src/lib/driver_utils.h index 851e2d1d9..9ea00087b 100644 --- a/fusee/fusee-secondary/src/lib/driver_utils.h +++ b/fusee/fusee-secondary/src/lib/driver_utils.h @@ -20,7 +20,4 @@ #include <stdio.h> #include <stdarg.h> -//#define vprint vprintf -//#define print printf - -#endif \ No newline at end of file +#endif diff --git a/fusee/fusee-secondary/src/log.c b/fusee/fusee-secondary/src/log.c index 050b2fccc..9a451cf2c 100644 --- a/fusee/fusee-secondary/src/log.c +++ b/fusee/fusee-secondary/src/log.c @@ -30,21 +30,22 @@ void log_to_uart(const char *message) { /* TODO: add UART logging */ } -void print_to_screen(ScreenLogLevel screenLogLevel, char *message) { +void print_to_screen(ScreenLogLevel screen_log_level, char *message) { /* don't print to screen if below log level */ - if(g_screen_log_level == SCREEN_LOG_LEVEL_NONE || screenLogLevel > g_screen_log_level) return; + if(screen_log_level > g_screen_log_level) return; //video_puts(buf); printf(message); } /** - * vprintk - logs a message to the console + * vprintk - logs a message and prints it to screen based on its screen_log_level * - * This text will not be colored or prefixed but logged to UART + * If the level is below g_screen_log_level it will not be shown but logged to UART + * This text will not be colored or prefixed * UART is TODO */ -void vprint(ScreenLogLevel screenLogLevel, const char *fmt, va_list args) +void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args) { char buf[PRINT_MESSAGE_MAX_LENGTH]; vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args); @@ -52,16 +53,16 @@ void vprint(ScreenLogLevel screenLogLevel, const char *fmt, va_list args) /* log to UART */ log_to_uart(buf); - print_to_screen(screenLogLevel, buf); + print_to_screen(screen_log_level, buf); } /** - * print - logs a message and prints it to screen based on its screenLogLevel + * print - logs a message and prints it to screen based on its screen_log_level * * If the level is below g_screen_log_level it will not be shown but logged to UART * UART is TODO */ -void print(ScreenLogLevel screenLogLevel, const char * fmt, ...) +void print(ScreenLogLevel screen_log_level, const char * fmt, ...) { char typebuf[] = "[%s] %s"; char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; @@ -70,7 +71,7 @@ void print(ScreenLogLevel screenLogLevel, const char * fmt, ...) /* apply prefix and append message format */ /* TODO: add coloring to the output */ /* TODO: make splash disappear if level > MANDATORY */ - switch(screenLogLevel) + switch(screen_log_level) { case SCREEN_LOG_LEVEL_ERROR: snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt); @@ -100,5 +101,5 @@ void print(ScreenLogLevel screenLogLevel, const char * fmt, ...) /* log to UART */ log_to_uart(message); - print_to_screen(screenLogLevel, message); + print_to_screen(screen_log_level, message); } \ No newline at end of file diff --git a/fusee/fusee-secondary/src/log.h b/fusee/fusee-secondary/src/log.h index 5be2964c9..ee2333fb3 100644 --- a/fusee/fusee-secondary/src/log.h +++ b/fusee/fusee-secondary/src/log.h @@ -17,10 +17,9 @@ #ifndef FUSEE_PRINT_H #define FUSEE_PRINT_H -#define PRINT_MESSAGE_MAX_LENGTH 512 +#define PRINT_MESSAGE_MAX_LENGTH 512 -//#include <stdint.h> -#include "../../fusee-primary/src/lib/vsprintf.h" +#include <stdarg.h> typedef enum { SCREEN_LOG_LEVEL_NONE = 0, @@ -36,7 +35,7 @@ extern ScreenLogLevel g_screen_log_level; void log_set_log_level(ScreenLogLevel screen_log_level); void log_to_uart(const char *message); -void vprint(ScreenLogLevel screenLogLevel, const char *fmt, va_list args); -void print(ScreenLogLevel screenLogLevel, const char* fmt, ...); +void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args); +void print(ScreenLogLevel screen_log_level, const char* fmt, ...); #endif \ No newline at end of file From d2355cdc9ba5e1413cbf254c25477a27ef54080f Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Tue, 25 Sep 2018 23:43:52 +0200 Subject: [PATCH 091/489] add the ability to print without adding a prefix for multi part/line prints --- .../fusee-secondary/src/exception_handlers.c | 16 ++++---- fusee/fusee-secondary/src/log.c | 38 +++++++++++++------ fusee/fusee-secondary/src/log.h | 4 +- fusee/fusee-secondary/src/utils.c | 2 +- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/fusee/fusee-secondary/src/exception_handlers.c b/fusee/fusee-secondary/src/exception_handlers.c index e3a74a8bb..16e8c7492 100644 --- a/fusee/fusee-secondary/src/exception_handlers.c +++ b/fusee/fusee-secondary/src/exception_handlers.c @@ -61,21 +61,23 @@ void exception_handler_main(uint32_t *registers, unsigned int exception_type) { code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE); stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE); - print(SCREEN_LOG_LEVEL_ERROR, "\nException type: %s\n", exception_names[exception_type]); - print(SCREEN_LOG_LEVEL_ERROR, "\nRegisters:\n\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n", + exception_names[exception_type]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n"); /* Print r0 to pc. */ for (int i = 0; i < 16; i += 2) { - print(SCREEN_LOG_LEVEL_ERROR, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", + register_names[i], registers[i], register_names[i+1], registers[i+1]); } /* Print cpsr. */ - print(SCREEN_LOG_LEVEL_ERROR, "%-7s%08"PRIX32"\n", register_names[16], registers[16]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]); - print(SCREEN_LOG_LEVEL_ERROR, "\nCode dump:\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n"); hexdump(code_dump, code_dump_size, instr_addr); - print(SCREEN_LOG_LEVEL_ERROR, "\nStack dump:\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n"); hexdump(stack_dump, stack_dump_size, registers[13]); - print(SCREEN_LOG_LEVEL_ERROR, "\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); fatal_error("An exception occurred!\n"); } diff --git a/fusee/fusee-secondary/src/log.c b/fusee/fusee-secondary/src/log.c index 9a451cf2c..49e989508 100644 --- a/fusee/fusee-secondary/src/log.c +++ b/fusee/fusee-secondary/src/log.c @@ -56,21 +56,11 @@ void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args) print_to_screen(screen_log_level, buf); } -/** - * print - logs a message and prints it to screen based on its screen_log_level - * - * If the level is below g_screen_log_level it will not be shown but logged to UART - * UART is TODO - */ -void print(ScreenLogLevel screen_log_level, const char * fmt, ...) -{ +void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) { char typebuf[] = "[%s] %s"; - char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; - char message[PRINT_MESSAGE_MAX_LENGTH] = {}; /* apply prefix and append message format */ /* TODO: add coloring to the output */ - /* TODO: make splash disappear if level > MANDATORY */ switch(screen_log_level) { case SCREEN_LOG_LEVEL_ERROR: @@ -91,6 +81,32 @@ void print(ScreenLogLevel screen_log_level, const char * fmt, ...) default: break; } +} + +/** + * print - logs a message and prints it to screen based on its screen_log_level + * + * If the level is below g_screen_log_level it will not be shown but logged to UART + * Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added + * UART is TODO + */ +void print(ScreenLogLevel screen_log_level, const char * fmt, ...) +{ + char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; + char message[PRINT_MESSAGE_MAX_LENGTH] = {}; + + /* TODO: make splash disappear if level > MANDATORY */ + + /* make prefix free messages with log_level possible */ + if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) { + /* remove the NO_PREFIX flag so the enum can be recognized later on */ + screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX; + + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt); + } + else { + add_prefix(screen_log_level, fmt, buf); + } /* input arguments */ va_list args; diff --git a/fusee/fusee-secondary/src/log.h b/fusee/fusee-secondary/src/log.h index ee2333fb3..73b7d86dd 100644 --- a/fusee/fusee-secondary/src/log.h +++ b/fusee/fusee-secondary/src/log.h @@ -27,7 +27,9 @@ typedef enum { SCREEN_LOG_LEVEL_WARNING = 2, SCREEN_LOG_LEVEL_MANDATORY = 3, /* no log prefix */ SCREEN_LOG_LEVEL_INFO = 4, - SCREEN_LOG_LEVEL_DEBUG = 5 + SCREEN_LOG_LEVEL_DEBUG = 5, + + SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */ } ScreenLogLevel; /* TODO: make this configurable by BCT.ini */ diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index 0ceacd95e..60bf63920 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -97,7 +97,7 @@ __attribute__((noreturn)) void fatal_error(const char *fmt, ...) { va_start(args, fmt); vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args); va_end(args); - print(SCREEN_LOG_LEVEL_ERROR, "\n Press POWER to reboot.\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n Press POWER to reboot.\n"); wait_for_button_and_reboot(); } From 762383f0d24da9ae24f5a93fa22e3498e85b9594 Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Wed, 26 Sep 2018 00:25:01 +0200 Subject: [PATCH 092/489] fix stray `[DEBUG]` at the end of sdmmc log --- fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index eebdceb93..4a19dc718 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -67,7 +67,7 @@ static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_l print(screen_log_level, sdmmc_fmt, sdmmc->name); vprint(screen_log_level, fmt, list); - print(screen_log_level, "\n"); + print(screen_log_level | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); } void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...) From d67a7c0a876e9a0ee8f97900ce12d9c32dfbe6b3 Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Wed, 26 Sep 2018 02:13:20 +0200 Subject: [PATCH 093/489] moving log.c and log.h to lib/ removing lib/driver_utils.h as it have no purpose anymore now --- .../fusee-secondary/src/exception_handlers.c | 3 +-- fusee/fusee-secondary/src/lib/driver_utils.h | 23 ------------------- fusee/fusee-secondary/src/{ => lib}/log.c | 6 ++--- fusee/fusee-secondary/src/{ => lib}/log.h | 4 ++-- fusee/fusee-secondary/src/loader.c | 2 +- fusee/fusee-secondary/src/main.c | 2 +- fusee/fusee-secondary/src/nxboot.c | 2 +- fusee/fusee-secondary/src/package2.c | 2 +- fusee/fusee-secondary/src/sdmmc/sdmmc.c | 1 - fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 3 +-- fusee/fusee-secondary/src/utils.c | 2 +- 11 files changed, 11 insertions(+), 39 deletions(-) delete mode 100644 fusee/fusee-secondary/src/lib/driver_utils.h rename fusee/fusee-secondary/src/{ => lib}/log.c (98%) rename fusee/fusee-secondary/src/{ => lib}/log.h (95%) diff --git a/fusee/fusee-secondary/src/exception_handlers.c b/fusee/fusee-secondary/src/exception_handlers.c index 16e8c7492..42a46516c 100644 --- a/fusee/fusee-secondary/src/exception_handlers.c +++ b/fusee/fusee-secondary/src/exception_handlers.c @@ -17,10 +17,9 @@ #include <inttypes.h> #include "exception_handlers.h" -#include "lib/driver_utils.h" #include "utils.h" #include "display/video_fb.h" -#include "log.h" +#include "lib/log.h" #define CODE_DUMP_SIZE 0x30 #define STACK_DUMP_SIZE 0x60 diff --git a/fusee/fusee-secondary/src/lib/driver_utils.h b/fusee/fusee-secondary/src/lib/driver_utils.h deleted file mode 100644 index 9ea00087b..000000000 --- a/fusee/fusee-secondary/src/lib/driver_utils.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef FUSEE_DRIVER_UTILS_H -#define FUSEE_DRIVER_UTILS_H - -#include <stdio.h> -#include <stdarg.h> - -#endif diff --git a/fusee/fusee-secondary/src/log.c b/fusee/fusee-secondary/src/lib/log.c similarity index 98% rename from fusee/fusee-secondary/src/log.c rename to fusee/fusee-secondary/src/lib/log.c index 49e989508..b4e8782c8 100644 --- a/fusee/fusee-secondary/src/log.c +++ b/fusee/fusee-secondary/src/lib/log.c @@ -14,10 +14,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdio.h> - #include "log.h" -#include "display/video_fb.h" + +#include <stdio.h> /* default log level for screen output */ ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_MANDATORY; @@ -34,7 +33,6 @@ void print_to_screen(ScreenLogLevel screen_log_level, char *message) { /* don't print to screen if below log level */ if(screen_log_level > g_screen_log_level) return; - //video_puts(buf); printf(message); } diff --git a/fusee/fusee-secondary/src/log.h b/fusee/fusee-secondary/src/lib/log.h similarity index 95% rename from fusee/fusee-secondary/src/log.h rename to fusee/fusee-secondary/src/lib/log.h index 73b7d86dd..080f34bef 100644 --- a/fusee/fusee-secondary/src/log.h +++ b/fusee/fusee-secondary/src/lib/log.h @@ -14,8 +14,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef FUSEE_PRINT_H -#define FUSEE_PRINT_H +#ifndef FUSEE_SECONDARY_PRINT_H +#define FUSEE_SECONDARY_PRINT_H #define PRINT_MESSAGE_MAX_LENGTH 512 diff --git a/fusee/fusee-secondary/src/loader.c b/fusee/fusee-secondary/src/loader.c index 1fc54206c..f9a2a7a30 100644 --- a/fusee/fusee-secondary/src/loader.c +++ b/fusee/fusee-secondary/src/loader.c @@ -24,7 +24,7 @@ #include "fs_utils.h" #include "stage2.h" #include "lib/ini.h" -#include "log.h" +#include "lib/log.h" static loader_ctx_t g_loader_ctx = {0}; diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index b598093f5..ec2ea8bc4 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -33,7 +33,7 @@ #include "gpt.h" #include "display/video_fb.h" #include "sdmmc/sdmmc.h" -#include "log.h" +#include "lib/log.h" extern void (*__program_exit_callback)(int rc); diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 3c21786cf..83fb6ca3a 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -45,7 +45,7 @@ #define u8 uint8_t #define u32 uint32_t #include "exosphere_bin.h" -#include "log.h" +#include "lib/log.h" #undef u8 #undef u32 diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 51ec914ff..7decd9510 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -27,7 +27,7 @@ #define u8 uint8_t #define u32 uint32_t #include "thermosphere_bin.h" -#include "log.h" +#include "lib/log.h" #undef u8 #undef u32 diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc.c b/fusee/fusee-secondary/src/sdmmc/sdmmc.c index e4a59c046..3aeb59f90 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc.c @@ -26,7 +26,6 @@ #include "mmc.h" #include "sd.h" #include "../timers.h" -#include "../lib/driver_utils.h" #define UNSTUFF_BITS(resp,start,size) \ ({ \ diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index 4a19dc718..56602bc49 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -30,8 +30,7 @@ #include "../gpio.h" #include "../pmc.h" #include "../max7762x.h" -#include "../lib/driver_utils.h" -#include "../log.h" +#include "../lib/log.h" static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index 60bf63920..b74e0163d 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -24,7 +24,7 @@ #include "timers.h" #include "btn.h" #include "panic.h" -#include "log.h" +#include "lib/log.h" #include <stdio.h> #include <inttypes.h> From 81355415d0e047d417f880b60032aee91b78515d Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Wed, 26 Sep 2018 02:18:50 +0200 Subject: [PATCH 094/489] port log.c log.h for fusee-primary refactor printing remove lib/printk as it is replaced with log remove lib/driver_utils.h added log levels as they seem right, might need adjustments --- fusee/fusee-primary/src/exception_handlers.c | 21 ++-- fusee/fusee-primary/src/fs_utils.c | 6 +- fusee/fusee-primary/src/lib/driver_utils.h | 23 ---- fusee/fusee-primary/src/lib/log.c | 120 +++++++++++++++++++ fusee/fusee-primary/src/lib/log.h | 43 +++++++ fusee/fusee-primary/src/lib/printk.c | 42 ------- fusee/fusee-primary/src/lib/printk.h | 25 ---- fusee/fusee-primary/src/main.c | 10 +- fusee/fusee-primary/src/sdmmc/sdmmc.c | 1 - fusee/fusee-primary/src/sdmmc/sdmmc_core.c | 22 ++-- fusee/fusee-primary/src/stage2.c | 12 +- fusee/fusee-primary/src/utils.c | 22 ++-- 12 files changed, 212 insertions(+), 135 deletions(-) delete mode 100644 fusee/fusee-primary/src/lib/driver_utils.h create mode 100644 fusee/fusee-primary/src/lib/log.c create mode 100644 fusee/fusee-primary/src/lib/log.h delete mode 100644 fusee/fusee-primary/src/lib/printk.c delete mode 100644 fusee/fusee-primary/src/lib/printk.h diff --git a/fusee/fusee-primary/src/exception_handlers.c b/fusee/fusee-primary/src/exception_handlers.c index e8d34f702..e0e5392b0 100644 --- a/fusee/fusee-primary/src/exception_handlers.c +++ b/fusee/fusee-primary/src/exception_handlers.c @@ -17,9 +17,8 @@ #include <inttypes.h> #include "exception_handlers.h" -#include "lib/driver_utils.h" #include "utils.h" -#include "display/video_fb.h" +#include "lib/log.h" #define CODE_DUMP_SIZE 0x30 #define STACK_DUMP_SIZE 0x60 @@ -55,26 +54,28 @@ void exception_handler_main(uint32_t *registers, unsigned int exception_type) { uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE; - printk("\nSomething went wrong...\n"); + print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n"); code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE); stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE); - printk("\nException type: %s\n", exception_names[exception_type]); - printk("\nRegisters:\n\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n", + exception_names[exception_type]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n"); /* Print r0 to pc. */ for (int i = 0; i < 16; i += 2) { - printk("%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", + register_names[i], registers[i], register_names[i+1], registers[i+1]); } /* Print cpsr. */ - printk("%-7s%08"PRIX32"\n", register_names[16], registers[16]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]); - printk("\nCode dump:\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n"); hexdump(code_dump, code_dump_size, instr_addr); - printk("\nStack dump:\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n"); hexdump(stack_dump, stack_dump_size, registers[13]); - printk("\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); fatal_error("An exception occured!\n"); } diff --git a/fusee/fusee-primary/src/fs_utils.c b/fusee/fusee-primary/src/fs_utils.c index b81bfec6a..f788c1f94 100644 --- a/fusee/fusee-primary/src/fs_utils.c +++ b/fusee/fusee-primary/src/fs_utils.c @@ -13,11 +13,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - + #include "fs_utils.h" #include "mc.h" -#include "lib/printk.h" #include "lib/fatfs/ff.h" +#include "lib/log.h" FATFS sd_fs; static bool g_sd_mounted = false; @@ -44,7 +44,7 @@ bool mount_sd(void) /* Mount SD. */ if (f_mount(&sd_fs, "", 1) == FR_OK) { - printk("Mounted SD card!\n"); + print(SCREEN_LOG_LEVEL_INFO, "Mounted SD card!\n"); g_sd_mounted = true; } } diff --git a/fusee/fusee-primary/src/lib/driver_utils.h b/fusee/fusee-primary/src/lib/driver_utils.h deleted file mode 100644 index b79611113..000000000 --- a/fusee/fusee-primary/src/lib/driver_utils.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef FUSEE_DRIVER_UTILS_H -#define FUSEE_DRIVER_UTILS_H - -#include "vsprintf.h" -#include "printk.h" - -#endif diff --git a/fusee/fusee-primary/src/lib/log.c b/fusee/fusee-primary/src/lib/log.c new file mode 100644 index 000000000..0c979c050 --- /dev/null +++ b/fusee/fusee-primary/src/lib/log.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "log.h" + +#include "../display/video_fb.h" +#include "vsprintf.h" + +/* default log level for screen output */ +ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_MANDATORY; + +void log_set_log_level(ScreenLogLevel log_level) { + g_screen_log_level = log_level; +} + +void log_to_uart(const char *message) { + /* TODO: add UART logging */ +} + +void print_to_screen(ScreenLogLevel screen_log_level, char *message) { + /* don't print to screen if below log level */ + if(screen_log_level > g_screen_log_level) return; + + video_puts(message); +} + +/** + * vprintk - logs a message and prints it to screen based on its screen_log_level + * + * If the level is below g_screen_log_level it will not be shown but logged to UART + * This text will not be colored or prefixed + * UART is TODO + */ +void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args) +{ + char buf[PRINT_MESSAGE_MAX_LENGTH]; + vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args); + + /* log to UART */ + log_to_uart(buf); + + print_to_screen(screen_log_level, buf); +} + +void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) { + char typebuf[] = "[%s] %s"; + + /* apply prefix and append message format */ + /* TODO: add coloring to the output */ + switch(screen_log_level) + { + case SCREEN_LOG_LEVEL_ERROR: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt); + break; + case SCREEN_LOG_LEVEL_WARNING: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt); + break; + case SCREEN_LOG_LEVEL_MANDATORY: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt); + break; + case SCREEN_LOG_LEVEL_INFO: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt); + break; + case SCREEN_LOG_LEVEL_DEBUG: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt); + break; + default: + break; + } +} + +/** + * print - logs a message and prints it to screen based on its screen_log_level + * + * If the level is below g_screen_log_level it will not be shown but logged to UART + * Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added + * UART is TODO + */ +void print(ScreenLogLevel screen_log_level, const char * fmt, ...) +{ + char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; + char message[PRINT_MESSAGE_MAX_LENGTH] = {}; + + /* TODO: make splash disappear if level > MANDATORY */ + + /* make prefix free messages with log_level possible */ + if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) { + /* remove the NO_PREFIX flag so the enum can be recognized later on */ + screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX; + + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt); + } + else { + add_prefix(screen_log_level, fmt, buf); + } + + /* input arguments */ + va_list args; + va_start(args, fmt); + vsnprintf(message, PRINT_MESSAGE_MAX_LENGTH, buf, args); + va_end(args); + + /* log to UART */ + log_to_uart(message); + + print_to_screen(screen_log_level, message); +} \ No newline at end of file diff --git a/fusee/fusee-primary/src/lib/log.h b/fusee/fusee-primary/src/lib/log.h new file mode 100644 index 000000000..00ddfdb6e --- /dev/null +++ b/fusee/fusee-primary/src/lib/log.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_PRIMARY_PRINT_H +#define FUSEE_PRIMARY_PRINT_H + +#define PRINT_MESSAGE_MAX_LENGTH 512 + +#include <stdarg.h> + +typedef enum { + SCREEN_LOG_LEVEL_NONE = 0, + SCREEN_LOG_LEVEL_ERROR = 1, + SCREEN_LOG_LEVEL_WARNING = 2, + SCREEN_LOG_LEVEL_MANDATORY = 3, /* no log prefix */ + SCREEN_LOG_LEVEL_INFO = 4, + SCREEN_LOG_LEVEL_DEBUG = 5, + + SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */ +} ScreenLogLevel; + +/* TODO: make this configurable by BCT.ini */ +extern ScreenLogLevel g_screen_log_level; + +void log_set_log_level(ScreenLogLevel screen_log_level); +void log_to_uart(const char *message); +void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args); +void print(ScreenLogLevel screen_log_level, const char* fmt, ...); + +#endif \ No newline at end of file diff --git a/fusee/fusee-primary/src/lib/printk.c b/fusee/fusee-primary/src/lib/printk.c deleted file mode 100644 index 30b36ab00..000000000 --- a/fusee/fusee-primary/src/lib/printk.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "printk.h" - -#include "vsprintf.h" -#include "../display/video_fb.h" - -/** - * Temporary stand-in main printk. - * - * TODO: This should print via UART, console framebuffer, and to a ring for - * consumption by Horizon - */ -void printk(const char *fmt, ...) -{ - va_list list; - va_start(list, fmt); - vprintk(fmt, list); - va_end(list); -} - - -void vprintk(const char *fmt, va_list args) -{ - char buf[512]; - vsnprintf(buf, sizeof(buf), fmt, args); - video_puts(buf); -} diff --git a/fusee/fusee-primary/src/lib/printk.h b/fusee/fusee-primary/src/lib/printk.h deleted file mode 100644 index 4c63b9b6f..000000000 --- a/fusee/fusee-primary/src/lib/printk.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __PRINTK_H__ -#define __PRINTK_H__ - -#include <stdarg.h> - -void printk(const char *fmt, ...); -void vprintk(const char *fmt, va_list args); - -#endif diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index fca4e5f1c..b41149ce4 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -25,7 +25,7 @@ #include "chainloader.h" #include "sdmmc/sdmmc.h" #include "lib/fatfs/ff.h" -#include "lib/printk.h" +#include "lib/log.h" #include "display/video_fb.h" extern void (*__program_exit_callback)(int rc); @@ -42,8 +42,8 @@ static char g_bct0_buffer[BCTO_MAX_SIZE]; static const char *load_config(void) { if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "BCT.ini")) { - printk("Failed to read BCT0 from SD!\n"); - printk("[DEBUG] Using default BCT0!\n"); + print(SCREEN_LOG_LEVEL_DEBUG, "Failed to read BCT0 from SD!\n"); + print(SCREEN_LOG_LEVEL_DEBUG, "Using default BCT0!\n"); memcpy(g_bct0_buffer, DEFAULT_BCT0_FOR_DEBUG, sizeof(DEFAULT_BCT0_FOR_DEBUG)); /* TODO: Stop using default. */ /* printk("Error: Failed to load BCT.ini!\n"); @@ -119,8 +119,8 @@ int main(void) { setup_env(); /* Say hello. */ - printk("Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); - printk("Using color linear framebuffer at 0x%p!\n", g_framebuffer); + print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); + print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); /* Load the BCT0 configuration ini off of the SD. */ bct0 = load_config(); diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc.c b/fusee/fusee-primary/src/sdmmc/sdmmc.c index e4a59c046..3aeb59f90 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc.c @@ -26,7 +26,6 @@ #include "mmc.h" #include "sd.h" #include "../timers.h" -#include "../lib/driver_utils.h" #define UNSTUFF_BITS(resp,start,size) \ ({ \ diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c index c831493f5..9d353d3b9 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c @@ -30,7 +30,7 @@ #include "../gpio.h" #include "../pmc.h" #include "../max7762x.h" -#include "../lib/driver_utils.h" +#include "../lib/log.h" static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; @@ -43,26 +43,30 @@ static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_l { if (log_level > g_sdmmc_log_level) return; - + + char sdmmc_fmt[] = "%s: "; + ScreenLogLevel screen_log_level = SCREEN_LOG_LEVEL_ERROR; + switch (log_level) { case SDMMC_LOG_ERROR: - printk("%s [ERROR]: ", sdmmc->name); + screen_log_level = SCREEN_LOG_LEVEL_ERROR; break; case SDMMC_LOG_WARN: - printk("%s [WARN]: ", sdmmc->name); + screen_log_level = SCREEN_LOG_LEVEL_WARNING; break; case SDMMC_LOG_INFO: - printk("%s [INFO]: ", sdmmc->name); + screen_log_level = SCREEN_LOG_LEVEL_DEBUG; break; case SDMMC_LOG_DEBUG: - printk("%s [DEBUG]: ", sdmmc->name); + screen_log_level = SCREEN_LOG_LEVEL_DEBUG; break; default: break; } - - vprintk(fmt, list); - printk("\n"); + + print(screen_log_level, sdmmc_fmt, sdmmc->name); + vprint(screen_log_level, fmt, list); + print(screen_log_level | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); } void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...) diff --git a/fusee/fusee-primary/src/stage2.c b/fusee/fusee-primary/src/stage2.c index c85dab3d9..66b8dcd4b 100644 --- a/fusee/fusee-primary/src/stage2.c +++ b/fusee/fusee-primary/src/stage2.c @@ -21,7 +21,7 @@ #include "fs_utils.h" #include "stage2.h" #include "chainloader.h" -#include "lib/printk.h" +#include "lib/log.h" #include "lib/vsprintf.h" #include "lib/ini.h" #include "lib/fatfs/ff.h" @@ -74,7 +74,7 @@ void load_stage2(const char *bct0) { } if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) { - printk("Error: Stage2's path name is too big!\n"); + print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n"); } if (!check_32bit_address_loadable(config.entrypoint)) { @@ -85,10 +85,10 @@ void load_stage2(const char *bct0) { fatal_error("Stage2's load address is invalid!\n"); } - printk("[DEBUG] Stage 2 Config:\n"); - printk(" File Path: %s\n", config.path); - printk(" Load Address: 0x%08x\n", config.load_address); - printk(" Entrypoint: 0x%p\n", config.entrypoint); + print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n"); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Entrypoint: 0x%p\n", config.entrypoint); if (f_stat(config.path, &info) != FR_OK) { fatal_error("Failed to stat stage2 (%s)!\n", config.path); diff --git a/fusee/fusee-primary/src/utils.c b/fusee/fusee-primary/src/utils.c index 4a2ec329d..87e84e793 100644 --- a/fusee/fusee-primary/src/utils.c +++ b/fusee/fusee-primary/src/utils.c @@ -25,7 +25,7 @@ #include "car.h" #include "btn.h" -#include "lib/printk.h" +#include "lib/log.h" #include <inttypes.h> @@ -84,11 +84,11 @@ __attribute__ ((noreturn)) void generic_panic(void) { __attribute__((noreturn)) void fatal_error(const char *fmt, ...) { va_list args; - printk("Fatal error: "); + print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: "); va_start(args, fmt); - vprintk(fmt, args); + vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args); va_end(args); - printk("\nPress POWER to reboot\n"); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n"); wait_for_button_and_reboot(); } @@ -109,27 +109,27 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase) { for (size_t i = 0; i < size; i++) { if (i % 16 == 0) { - printk("%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); } - printk("%02X ", d[i]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%02X ", d[i]); if (d[i] >= ' ' && d[i] <= '~') { ascii[i % 16] = d[i]; } else { ascii[i % 16] = '.'; } if ((i+1) % 8 == 0 || i+1 == size) { - printk(" "); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); if ((i+1) % 16 == 0) { - printk("| %s \n", ascii); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii); } else if (i+1 == size) { ascii[(i+1) % 16] = '\0'; if ((i+1) % 16 <= 8) { - printk(" "); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); } for (size_t j = (i+1) % 16; j < 16; j++) { - printk(" "); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); } - printk("| %s \n", ascii); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii); } } } From 1d22bb7b8112ff689dea49a192b0866de066d079 Mon Sep 17 00:00:00 2001 From: Resaec <resaecscript@gmail.com> Date: Wed, 26 Sep 2018 02:47:24 +0200 Subject: [PATCH 095/489] we need to strip the NO_PREFIX flag so your log_level is corrected for checking against the global --- fusee/fusee-primary/src/lib/log.c | 3 +++ fusee/fusee-secondary/src/lib/log.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/fusee/fusee-primary/src/lib/log.c b/fusee/fusee-primary/src/lib/log.c index 0c979c050..4aa396d72 100644 --- a/fusee/fusee-primary/src/lib/log.c +++ b/fusee/fusee-primary/src/lib/log.c @@ -49,6 +49,9 @@ void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args) char buf[PRINT_MESSAGE_MAX_LENGTH]; vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args); + /* we don't need that flag here, but if it gets used, strip it so we print correctly */ + screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX; + /* log to UART */ log_to_uart(buf); diff --git a/fusee/fusee-secondary/src/lib/log.c b/fusee/fusee-secondary/src/lib/log.c index b4e8782c8..d4cae38b3 100644 --- a/fusee/fusee-secondary/src/lib/log.c +++ b/fusee/fusee-secondary/src/lib/log.c @@ -48,6 +48,9 @@ void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args) char buf[PRINT_MESSAGE_MAX_LENGTH]; vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args); + /* we don't need that flag here, but if it gets used, strip it so we print correctly */ + screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX; + /* log to UART */ log_to_uart(buf); From 7b0ed094a7de23f885fe2a4421de9abb5fa3eb21 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Wed, 26 Sep 2018 21:30:53 +0100 Subject: [PATCH 096/489] fusee: Fix support for firmware 6.0.0 --- fusee/fusee-secondary/src/package2.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fusee/fusee-secondary/src/package2.h b/fusee/fusee-secondary/src/package2.h index e5d573c37..c1314305b 100644 --- a/fusee/fusee-secondary/src/package2.h +++ b/fusee/fusee-secondary/src/package2.h @@ -33,14 +33,16 @@ #define PACKAGE2_MAXVER_300 0x4 #define PACKAGE2_MAXVER_302 0x5 #define PACKAGE2_MAXVER_400_410 0x6 -#define PACKAGE2_MAXVER_500_CURRENT 0x7 +#define PACKAGE2_MAXVER_500_510 0x7 +#define PACKAGE2_MAXVER_600_CURRENT 0x8 #define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_200 0x4 #define PACKAGE2_MINVER_300 0x5 #define PACKAGE2_MINVER_302 0x6 #define PACKAGE2_MINVER_400_410 0x7 -#define PACKAGE2_MINVER_500_CURRENT 0x8 +#define PACKAGE2_MINVER_500_510 0x8 +#define PACKAGE2_MINVER_600_CURRENT 0x9 #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) From b2b7bf2bb34acbc52b76e39920c70ff28ae5abaf Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Wed, 26 Sep 2018 21:31:18 +0100 Subject: [PATCH 097/489] fusee: Fix support for firmware 6.0.0 --- fusee/fusee-secondary/src/package2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 28f210b25..76f5f5704 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -192,7 +192,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[] /* Perform version checks. */ /* We will be compatible with all package2s released before current, but not newer ones. */ - if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_500_CURRENT) { + if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_600_CURRENT) { return true; } @@ -221,7 +221,7 @@ static uint32_t package2_decrypt_and_validate_header(package2_header_t *header, /* Ensure we successfully decrypted the header. */ if (mkey_rev > mkey_get_revision()) { - fatal_error("failed to decrypt the Package2 header (master key revision %u)!\n", mkey_get_revision()); + fatal_error("Failed to decrypt the Package2 header (master key revision %u)!\n", mkey_get_revision()); } } else if (!package2_validate_metadata(&header->metadata, header->data)) { fatal_error("Failed to validate the Package2 header!\n"); From 210c6425c3dcef32e951eb338b446942b7be3a85 Mon Sep 17 00:00:00 2001 From: TuxSH <tuxsh@sfr.fr> Date: Thu, 27 Sep 2018 22:54:30 +0200 Subject: [PATCH 098/489] Cull unmainted exosphere/src/dbg folder --- exosphere/src/dbg/fmt.c | 291 ---------------------------- exosphere/src/dbg/fmt.h | 25 --- exosphere/src/dbg/log.c | 63 ------ exosphere/src/dbg/log.h | 25 --- exosphere/src/dbg/log_device_null.c | 42 ---- exosphere/src/dbg/log_device_null.h | 29 --- exosphere/src/dbg/log_device_uart.c | 45 ----- exosphere/src/dbg/log_device_uart.h | 29 --- 8 files changed, 549 deletions(-) delete mode 100644 exosphere/src/dbg/fmt.c delete mode 100644 exosphere/src/dbg/fmt.h delete mode 100644 exosphere/src/dbg/log.c delete mode 100644 exosphere/src/dbg/log.h delete mode 100644 exosphere/src/dbg/log_device_null.c delete mode 100644 exosphere/src/dbg/log_device_null.h delete mode 100644 exosphere/src/dbg/log_device_uart.c delete mode 100644 exosphere/src/dbg/log_device_uart.h diff --git a/exosphere/src/dbg/fmt.c b/exosphere/src/dbg/fmt.c deleted file mode 100644 index 3c6e243b8..000000000 --- a/exosphere/src/dbg/fmt.c +++ /dev/null @@ -1,291 +0,0 @@ -/* File : barebones/ee_printf.c - This file contains an implementation of ee_printf that only requires a method to output a char to a UART without pulling in library code. -This code is based on a file that contains the following: - Copyright (C) 2002 Michael Ringgaard. All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the project nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. -*/ - -//TuxSH's changes: add support for 64-bit numbers, remove floating-point code -// (C) AuroraWright, TuxSH - -#include "../utils.h" -#include <string.h> - -#include "fmt.h" - -#define ZEROPAD (1<<0) //Pad with zero -#define SIGN (1<<1) //Unsigned/signed long -#define PLUS (1<<2) //Show plus -#define SPACE (1<<3) //Spacer -#define LEFT (1<<4) //Left justified -#define HEX_PREP (1<<5) //0x -#define UPPERCASE (1<<6) //'ABCDEF' - -#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') - -static int32_t skipAtoi(const char **s) -{ - int32_t i = 0; - - while(IS_DIGIT(**s)) i = i * 10 + *((*s)++) - '0'; - - return i; -} - -static char *processNumber(char *str, int64_t num, bool isHex, int32_t size, int32_t precision, uint32_t type) -{ - char sign = 0; - - if(type & SIGN) - { - if(num < 0) - { - sign = '-'; - num = -num; - size--; - } - else if(type & PLUS) - { - sign = '+'; - size--; - } - else if(type & SPACE) - { - sign = ' '; - size--; - } - } - - static const char *lowerDigits = "0123456789abcdef", - *upperDigits = "0123456789ABCDEF"; - - int32_t i = 0; - char tmp[20]; - const char *dig = (type & UPPERCASE) ? upperDigits : lowerDigits; - - if(num == 0) - { - if(precision != 0) tmp[i++] = '0'; - type &= ~HEX_PREP; - } - else - { - while(num != 0) - { - uint64_t base = isHex ? 16ULL : 10ULL; - tmp[i++] = dig[(uint64_t)num % base]; - num = (int64_t)((uint64_t)num / base); - } - } - - if(type & LEFT || precision != -1) type &= ~ZEROPAD; - if(type & HEX_PREP && isHex) size -= 2; - if(i > precision) precision = i; - size -= precision; - if(!(type & (ZEROPAD | LEFT))) while(size-- > 0) *str++ = ' '; - if(sign) *str++ = sign; - - if(type & HEX_PREP && isHex) - { - *str++ = '0'; - *str++ = 'x'; - } - - if(type & ZEROPAD) while(size-- > 0) *str++ = '0'; - while(i < precision--) *str++ = '0'; - while(i-- > 0) *str++ = tmp[i]; - while(size-- > 0) *str++ = ' '; - - return str; -} - -int visprintf(char *buf, const char *fmt, va_list args) -{ - char *str; - - for(str = buf; *fmt; fmt++) - { - if(*fmt != '%') - { - *str++ = *fmt; - continue; - } - - //Process flags - uint32_t flags = 0; //Flags to number() - bool loop = true; - - while(loop) - { - switch(*++fmt) - { - case '-': flags |= LEFT; break; - case '+': flags |= PLUS; break; - case ' ': flags |= SPACE; break; - case '#': flags |= HEX_PREP; break; - case '0': flags |= ZEROPAD; break; - default: loop = false; break; - } - } - - //Get field width - int32_t fieldWidth = -1; //Width of output field - if(IS_DIGIT(*fmt)) fieldWidth = skipAtoi(&fmt); - else if(*fmt == '*') - { - fmt++; - - fieldWidth = va_arg(args, int32_t); - - if(fieldWidth < 0) - { - fieldWidth = -fieldWidth; - flags |= LEFT; - } - } - - //Get the precision - int32_t precision = -1; //Min. # of digits for integers; max number of chars for from string - if(*fmt == '.') - { - fmt++; - - if(IS_DIGIT(*fmt)) precision = skipAtoi(&fmt); - else if(*fmt == '*') - { - fmt++; - precision = va_arg(args, int32_t); - } - - if(precision < 0) precision = 0; - } - - //Get the conversion qualifier - uint32_t integerType = 0; - if(*fmt == 'l') - { - if(*++fmt == 'l') - { - fmt++; - integerType = 1; - } - - } - else if(*fmt == 'h') - { - if(*++fmt == 'h') - { - fmt++; - integerType = 3; - } - else integerType = 2; - } - - bool isHex; - - switch(*fmt) - { - case 'c': - if(!(flags & LEFT)) while(--fieldWidth > 0) *str++ = ' '; - *str++ = (uint8_t)va_arg(args, int32_t); - while(--fieldWidth > 0) *str++ = ' '; - continue; - - case 's': - { - char *s = va_arg(args, char *); - if(!s) s = "<NULL>"; - uint32_t len = (precision != -1) ? strnlen(s, precision) : strlen(s); - if(!(flags & LEFT)) while((int32_t)len < fieldWidth--) *str++ = ' '; - for(uint32_t i = 0; i < len; i++) *str++ = *s++; - while((int32_t)len < fieldWidth--) *str++ = ' '; - continue; - } - - case 'p': - if(fieldWidth == -1) - { - fieldWidth = 8; - flags |= ZEROPAD; - } - str = processNumber(str, va_arg(args, uint32_t), true, fieldWidth, precision, flags); - continue; - - //Integer number formats - set up the flags and "break" - case 'X': - flags |= UPPERCASE; - //Falls through - case 'x': - isHex = true; - break; - - case 'd': - case 'i': - flags |= SIGN; - //Falls through - case 'u': - isHex = false; - break; - - default: - if(*fmt != '%') *str++ = '%'; - if(*fmt) *str++ = *fmt; - else fmt--; - continue; - } - - int64_t num; - - if(flags & SIGN) - { - if(integerType == 1) num = va_arg(args, int64_t); - else num = va_arg(args, int32_t); - - if(integerType == 2) num = (int16_t)num; - else if(integerType == 3) num = (int8_t)num; - } - else - { - if(integerType == 1) num = va_arg(args, uint64_t); - else num = va_arg(args, uint32_t); - - if(integerType == 2) num = (uint16_t)num; - else if(integerType == 3) num = (uint8_t)num; - } - - str = processNumber(str, num, isHex, fieldWidth, precision, flags); - } - - *str = 0; - return str - buf; -} - -int isprintf(char *buf, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - int res = visprintf(buf, fmt, args); - va_end(args); - return res; -} diff --git a/exosphere/src/dbg/fmt.h b/exosphere/src/dbg/fmt.h deleted file mode 100644 index ed593422e..000000000 --- a/exosphere/src/dbg/fmt.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef EXOSPHERE_DBG_FMT_H -#define EXOSPHERE_DBG_FMT_H - -#include <stdarg.h> - -int visprintf(char *buf, const char *fmt, va_list args); -int isprintf(char *buf, const char *fmt, ...); - -#endif diff --git a/exosphere/src/dbg/log.c b/exosphere/src/dbg/log.c deleted file mode 100644 index 1337ff455..000000000 --- a/exosphere/src/dbg/log.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <string.h> -#include <stdarg.h> -#include "log.h" -#include "log_device_null.h" -#include "log_device_uart.h" -#include "fmt.h" -#include "../synchronization.h" - -#ifndef NDEBUG -static atomic_flag g_log_lock = ATOMIC_FLAG_INIT; -static debug_log_device_t *dev; -#endif - -void dbg_log_initialize(DebugLogDevice device) { -#ifndef NDEBUG - static debug_log_device_t *const devs[] = {&g_debug_log_device_null.super, &g_debug_log_device_uart.super}; - dev = device >= DEBUGLOGDEVICE_MAX ? &g_debug_log_device_null.super : devs[device]; -#else - (void)device; -#endif -} - -/* NOTE: no bound checks are done */ -void dbg_log_write(const char *fmt, ...) { -#ifndef NDEBUG - char buf[DBG_LOG_BUF_SIZE]; - int len; - va_list args; - lock_acquire(&g_log_lock); - - va_start(args, fmt); - len = visprintf(buf, fmt, args); - va_end(args); - - dev->write_string(dev, buf, len); - lock_release(&g_log_lock); -#else - (void)fmt; -#endif -} - -void dbg_log_finalize(void) { -#ifndef NDEBUG - dev->finalize(dev); - dev = NULL; -#endif -} diff --git a/exosphere/src/dbg/log.h b/exosphere/src/dbg/log.h deleted file mode 100644 index 5ae4fe043..000000000 --- a/exosphere/src/dbg/log.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef EXOSPHERE_DBG_LOG_H -#define EXOSPHERE_DBG_LOG_H - -#include "../utils.h" - -#define DBG_LOG_BUF_SIZE 256 - -typedef enum { - DEBUGLOGDEVICE_NULL = 0, - DEBUGLOGDEVICE_UART = 1, - - DEBUGLOGDEVICE_MAX = 2, -} DebugLogDevice; - -typedef struct debug_log_device_t { - void (*initialize)(struct debug_log_device_t *this, ...); - void (*write_string)(struct debug_log_device_t *this, const char *str, size_t len); - void (*finalize)(struct debug_log_device_t *this); -} debug_log_device_t; - -void dbg_log_initialize(DebugLogDevice device); -void dbg_log_write(const char *fmt, ...); -void dbg_log_finalize(void); - -#endif diff --git a/exosphere/src/dbg/log_device_null.c b/exosphere/src/dbg/log_device_null.c deleted file mode 100644 index 41ed3aafe..000000000 --- a/exosphere/src/dbg/log_device_null.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "log_device_null.h" - -static void initialize(debug_log_device_null_t *this) { - (void)this; - /* Do nothing */ -} - -static void write_string(debug_log_device_null_t *this, const char *str, size_t len) { - (void)this; - (void)str; - (void)len; - /* Do nothing */ -} - -static void finalize(debug_log_device_null_t *this) { - (void)this; - /* Do nothing */ -} - -debug_log_device_null_t g_debug_log_device_null = { - .super = { - .initialize = (void (*)(debug_log_device_t *, ...))initialize, - .write_string = (void (*)(debug_log_device_t *, const char *, size_t))write_string, - .finalize = (void (*)(debug_log_device_t *))finalize, - }, -}; diff --git a/exosphere/src/dbg/log_device_null.h b/exosphere/src/dbg/log_device_null.h deleted file mode 100644 index 88b76fbb8..000000000 --- a/exosphere/src/dbg/log_device_null.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef EXOSPHERE_DBG_LOG_DEVICE_NULL_H -#define EXOSPHERE_DBG_LOG_DEVICE_NULL_H - -#include "log.h" - -typedef struct { - debug_log_device_t super; - /* Additonnal attributes go here */ -} debug_log_device_null_t; - -extern debug_log_device_null_t g_debug_log_device_null; - -#endif diff --git a/exosphere/src/dbg/log_device_uart.c b/exosphere/src/dbg/log_device_uart.c deleted file mode 100644 index 1515bbbfd..000000000 --- a/exosphere/src/dbg/log_device_uart.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "log_device_uart.h" -#include "../car.h" -#include "../uart.h" - -static void initialize(debug_log_device_uart_t *this) { - if (!this->is_initialized) { - uart_select(UART_A); - clkrst_enable(CARDEVICE_UARTA); - uart_init(UART_A, BAUD_115200); /* is this the correct baud rate for this use-case? */ - this->is_initialized = true; - } -} - -static void write_string(debug_log_device_uart_t *this, const char *str, size_t len) { - (void)this; - uart_send(UART_A, str, len); -} - -static void finalize(debug_log_device_uart_t *this) { - clkrst_disable(CARDEVICE_UARTA); -} - -debug_log_device_uart_t g_debug_log_device_uart = { - .super = { - .initialize = (void (*)(debug_log_device_t *, ...))initialize, - .write_string = (void (*)(debug_log_device_t *, const char *, size_t))write_string, - .finalize = (void (*)(debug_log_device_t *))finalize, - }, -}; diff --git a/exosphere/src/dbg/log_device_uart.h b/exosphere/src/dbg/log_device_uart.h deleted file mode 100644 index 892ab553b..000000000 --- a/exosphere/src/dbg/log_device_uart.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef EXOSPHERE_DBG_LOG_DEVICE_UART_H -#define EXOSPHERE_DBG_LOG_DEVICE_UART_H - -#include "log.h" - -typedef struct { - debug_log_device_t super; - bool is_initialized; -} debug_log_device_uart_t; - -extern debug_log_device_uart_t g_debug_log_device_uart; - -#endif From 06088d4c60f6b7dfc5f6b8cb8604f34e96cf5715 Mon Sep 17 00:00:00 2001 From: TuxSH <tuxsh@sfr.fr> Date: Thu, 27 Sep 2018 23:56:01 +0200 Subject: [PATCH 099/489] exosphere: fix neon regs being used => don't link against newlib, use -mgeneral-regs-only --- exosphere/Makefile | 4 +- exosphere/linker.specs | 3 - exosphere/src/my_libc.c | 1141 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 1143 insertions(+), 5 deletions(-) create mode 100644 exosphere/src/my_libc.c diff --git a/exosphere/Makefile b/exosphere/Makefile index 7f0340003..77e3e02da 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -25,7 +25,7 @@ INCLUDES := include #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -march=armv8-a -mtune=cortex-a57 +ARCH := -march=armv8-a -mtune=cortex-a57 -mgeneral-regs-only #<- important DEFINES := -D__CCPLEX__ CFLAGS := \ -g \ @@ -45,7 +45,7 @@ CFLAGS += $(INCLUDE) CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +LDFLAGS = -specs=$(TOPDIR)/linker.specs -nostartfiles -nostdlib -g $(ARCH) -Wl,-Map,$(notdir $*.map) LIBS := diff --git a/exosphere/linker.specs b/exosphere/linker.specs index 300990418..fb0cb34bc 100644 --- a/exosphere/linker.specs +++ b/exosphere/linker.specs @@ -2,6 +2,3 @@ *link: %(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections - -*startfile: -crti%O%s crtbegin%O%s diff --git a/exosphere/src/my_libc.c b/exosphere/src/my_libc.c new file mode 100644 index 000000000..35bd35bbb --- /dev/null +++ b/exosphere/src/my_libc.c @@ -0,0 +1,1141 @@ +/* Note: copied from newlib */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <string.h> +#include <stddef.h> +#include <limits.h> + +/* + * Copyright (C) 2004 CodeSourcery, LLC + * + * Permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies. + * + * This file is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* Handle ELF .{pre_init,init,fini}_array sections. */ +#include <sys/types.h> + +#ifndef HAVE_INITFINI_ARRAY +#define HAVE_INITFINI_ARRAY +#endif + +#undef HAVE_INIT_FINI + +#ifdef HAVE_INITFINI_ARRAY + +/* These magic symbols are provided by the linker. */ +extern void (*__preinit_array_start []) (void) __attribute__((weak)); +extern void (*__preinit_array_end []) (void) __attribute__((weak)); +extern void (*__init_array_start []) (void) __attribute__((weak)); +extern void (*__init_array_end []) (void) __attribute__((weak)); + +#ifdef HAVE_INIT_FINI +extern void _init (void); +#endif + +/* Iterate over all the init routines. */ +void +__libc_init_array (void) +{ + size_t count; + size_t i; + + count = __preinit_array_end - __preinit_array_start; + for (i = 0; i < count; i++) + __preinit_array_start[i] (); + +#ifdef HAVE_INIT_FINI + _init (); +#endif + + count = __init_array_end - __init_array_start; + for (i = 0; i < count; i++) + __init_array_start[i] (); +} +#endif + +#ifdef HAVE_INITFINI_ARRAY +extern void (*__fini_array_start []) (void) __attribute__((weak)); +extern void (*__fini_array_end []) (void) __attribute__((weak)); + +#ifdef HAVE_INIT_FINI +extern void _fini (void); +#endif + +/* Run all the cleanup routines. */ +void +__libc_fini_array (void) +{ + size_t count; + size_t i; + + count = __fini_array_end - __fini_array_start; + for (i = count; i > 0; i--) + __fini_array_start[i-1] (); + +#ifdef HAVE_INIT_FINI + _fini (); +#endif +} +#endif + +/* +FUNCTION + <<memmove>>---move possibly overlapping memory +INDEX + memmove +SYNOPSIS + #include <string.h> + void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>); +DESCRIPTION + This function moves <[length]> characters from the block of + memory starting at <<*<[src]>>> to the memory starting at + <<*<[dst]>>>. <<memmove>> reproduces the characters correctly + at <<*<[dst]>>> even if the two areas overlap. +RETURNS + The function returns <[dst]> as passed. +PORTABILITY +<<memmove>> is ANSI C. +<<memmove>> requires no supporting OS subroutines. +QUICKREF + memmove ansi pure +*/ + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) + +/* How many bytes are copied each iteration of the 4X unrolled loop. */ +#define BIGBLOCKSIZE (sizeof (long) << 2) + +/* How many bytes are copied each iteration of the word copy loop. */ +#define LITTLEBLOCKSIZE (sizeof (long)) + +/* Threshhold for punting to the byte copier. */ +#undef TOO_SMALL +#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) + +/*SUPPRESS 20*/ +void * +//__inhibit_loop_to_libcall +memmove (void *dst_void, + const void *src_void, + size_t length) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *dst = dst_void; + const char *src = src_void; + + if (src < dst && dst < src + length) + { + /* Have to copy backwards */ + src += length; + dst += length; + while (length--) + { + *--dst = *--src; + } + } + else + { + while (length--) + { + *dst++ = *src++; + } + } + + return dst_void; +#else + char *dst = dst_void; + const char *src = src_void; + long *aligned_dst; + const long *aligned_src; + + if (src < dst && dst < src + length) + { + /* Destructive overlap...have to copy backwards */ + src += length; + dst += length; + while (length--) + { + *--dst = *--src; + } + } + else + { + /* Use optimizing algorithm for a non-destructive copy to closely + match memcpy. If the size is small or either SRC or DST is unaligned, + then punt into the byte copy loop. This should be rare. */ + if (!TOO_SMALL(length) && !UNALIGNED (src, dst)) + { + aligned_dst = (long*)dst; + aligned_src = (long*)src; + + /* Copy 4X long words at a time if possible. */ + while (length >= BIGBLOCKSIZE) + { + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + length -= BIGBLOCKSIZE; + } + + /* Copy one long word at a time if possible. */ + while (length >= LITTLEBLOCKSIZE) + { + *aligned_dst++ = *aligned_src++; + length -= LITTLEBLOCKSIZE; + } + + /* Pick up any residual with a byte copier. */ + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while (length--) + { + *dst++ = *src++; + } + } + + return dst_void; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} + +/* +FUNCTION + <<memcpy>>---copy memory regions +SYNOPSIS + #include <string.h> + void* memcpy(void *restrict <[out]>, const void *restrict <[in]>, + size_t <[n]>); +DESCRIPTION + This function copies <[n]> bytes from the memory region + pointed to by <[in]> to the memory region pointed to by + <[out]>. + If the regions overlap, the behavior is undefined. +RETURNS + <<memcpy>> returns a pointer to the first byte of the <[out]> + region. +PORTABILITY +<<memcpy>> is ANSI C. +<<memcpy>> requires no supporting OS subroutines. +QUICKREF + memcpy ansi pure + */ + +void * +memcpy (void * dst0, + const void * __restrict src0, + size_t len0) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *dst = (char *) dst0; + char *src = (char *) src0; + + void *save = dst0; + + while (len0--) + { + *dst++ = *src++; + } + + return save; +#else + char *dst = dst0; + const char *src = src0; + long *aligned_dst; + const long *aligned_src; + + /* If the size is small, or either SRC or DST is unaligned, + then punt into the byte copy loop. This should be rare. */ + if (!TOO_SMALL(len0) && !UNALIGNED (src, dst)) + { + aligned_dst = (long*)dst; + aligned_src = (long*)src; + + /* Copy 4X long words at a time if possible. */ + while (len0 >= BIGBLOCKSIZE) + { + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + len0 -= BIGBLOCKSIZE; + } + + /* Copy one long word at a time if possible. */ + while (len0 >= LITTLEBLOCKSIZE) + { + *aligned_dst++ = *aligned_src++; + len0 -= LITTLEBLOCKSIZE; + } + + /* Pick up any residual with a byte copier. */ + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while (len0--) + *dst++ = *src++; + + return dst0; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} + +/* +FUNCTION + <<memset>>---set an area of memory +INDEX + memset +SYNOPSIS + #include <string.h> + void *memset(void *<[dst]>, int <[c]>, size_t <[length]>); +DESCRIPTION + This function converts the argument <[c]> into an unsigned + char and fills the first <[length]> characters of the array + pointed to by <[dst]> to the value. +RETURNS + <<memset>> returns the value of <[dst]>. +PORTABILITY +<<memset>> is ANSI C. + <<memset>> requires no supporting OS subroutines. +QUICKREF + memset ansi pure +*/ + +#include <string.h> + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + +#define LBLOCKSIZE (sizeof(long)) +#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) +#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) + +void * +memset (void *m, + int c, + size_t n) +{ + char *s = (char *) m; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned int i; + unsigned long buffer; + unsigned long *aligned_addr; + unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an + unsigned variable. */ + + while (UNALIGNED (s)) + { + if (n--) + *s++ = (char) c; + else + return m; + } + + if (!TOO_SMALL (n)) + { + /* If we get this far, we know that n is large and s is word-aligned. */ + aligned_addr = (unsigned long *) s; + + /* Store D into each char sized location in BUFFER so that + we can set large blocks quickly. */ + buffer = (d << 8) | d; + buffer |= (buffer << 16); + for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) + buffer = (buffer << i) | buffer; + + /* Unroll the loop. */ + while (n >= LBLOCKSIZE*4) + { + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + *aligned_addr++ = buffer; + n -= 4*LBLOCKSIZE; + } + + while (n >= LBLOCKSIZE) + { + *aligned_addr++ = buffer; + n -= LBLOCKSIZE; + } + /* Pick up the remainder with a bytewise loop. */ + s = (char*)aligned_addr; + } + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (n--) + *s++ = (char) c; + + return m; +} + +/* +FUNCTION + <<memchr>>---find character in memory +INDEX + memchr +SYNOPSIS + #include <string.h> + void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); +DESCRIPTION + This function searches memory starting at <<*<[src]>>> for the + character <[c]>. The search only ends with the first + occurrence of <[c]>, or after <[length]> characters; in + particular, <<NUL>> does not terminate the search. +RETURNS + If the character <[c]> is found within <[length]> characters + of <<*<[src]>>>, a pointer to the character is returned. If + <[c]> is not found, then <<NULL>> is returned. +PORTABILITY +<<memchr>> is ANSI C. +<<memchr>> requires no supporting OS subroutines. +QUICKREF + memchr ansi pure +*/ + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) + +/* How many bytes are loaded each iteration of the word copy loop. */ +#define LBLOCKSIZE (sizeof (long)) + +/* Threshhold for punting to the bytewise iterator. */ +#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) + +#if LONG_MAX == 2147483647L +#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) +#else +#if LONG_MAX == 9223372036854775807L +/* Nonzero if X (a long int) contains a NULL byte. */ +#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) +#else +#error long int is not a 32bit or 64bit type. +#endif +#endif + +#ifndef DETECTNULL +#error long int is not a 32bit or 64bit byte +#endif + +/* DETECTCHAR returns nonzero if (long)X contains the byte used + to fill (long)MASK. */ +#define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) + +void * +memchr (const void *src_void, + int c, + size_t length) +{ + const unsigned char *src = (const unsigned char *) src_void; + unsigned char d = c; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned long *asrc; + unsigned long mask; + unsigned int i; + + while (UNALIGNED (src)) + { + if (!length--) + return NULL; + if (*src == d) + return (void *) src; + src++; + } + + if (!TOO_SMALL (length)) + { + /* If we get this far, we know that length is large and src is + word-aligned. */ + /* The fast code reads the source one word at a time and only + performs the bytewise search on word-sized segments if they + contain the search character, which is detected by XORing + the word-sized segment with a word-sized block of the search + character and then detecting for the presence of NUL in the + result. */ + asrc = (unsigned long *) src; + mask = d << 8 | d; + mask = mask << 16 | mask; + for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) + mask = (mask << i) | mask; + + while (length >= LBLOCKSIZE) + { + if (DETECTCHAR (*asrc, mask)) + break; + length -= LBLOCKSIZE; + asrc++; + } + + /* If there are fewer than LBLOCKSIZE characters left, + then we resort to the bytewise loop. */ + + src = (unsigned char *) asrc; + } + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (length--) + { + if (*src == d) + return (void *) src; + src++; + } + + return NULL; +} + +/* +FUNCTION + <<memcmp>>---compare two memory areas +INDEX + memcmp +SYNOPSIS + #include <string.h> + int memcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>); +DESCRIPTION + This function compares not more than <[n]> characters of the + object pointed to by <[s1]> with the object pointed to by <[s2]>. +RETURNS + The function returns an integer greater than, equal to or + less than zero according to whether the object pointed to by + <[s1]> is greater than, equal to or less than the object + pointed to by <[s2]>. +PORTABILITY +<<memcmp>> is ANSI C. +<<memcmp>> requires no supporting OS subroutines. +QUICKREF + memcmp ansi pure +*/ + + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) + +/* How many bytes are copied each iteration of the word copy loop. */ +#define LBLOCKSIZE (sizeof (long)) + +/* Threshhold for punting to the byte copier. */ +#define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) + +int +memcmp (const void *m1, + const void *m2, + size_t n) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + unsigned char *s1 = (unsigned char *) m1; + unsigned char *s2 = (unsigned char *) m2; + + while (n--) + { + if (*s1 != *s2) + { + return *s1 - *s2; + } + s1++; + s2++; + } + return 0; +#else + unsigned char *s1 = (unsigned char *) m1; + unsigned char *s2 = (unsigned char *) m2; + unsigned long *a1; + unsigned long *a2; + + /* If the size is too small, or either pointer is unaligned, + then we punt to the byte compare loop. Hopefully this will + not turn up in inner loops. */ + if (!TOO_SMALL(n) && !UNALIGNED(s1,s2)) + { + /* Otherwise, load and compare the blocks of memory one + word at a time. */ + a1 = (unsigned long*) s1; + a2 = (unsigned long*) s2; + while (n >= LBLOCKSIZE) + { + if (*a1 != *a2) + break; + a1++; + a2++; + n -= LBLOCKSIZE; + } + + /* check m mod LBLOCKSIZE remaining characters */ + + s1 = (unsigned char*)a1; + s2 = (unsigned char*)a2; + } + + while (n--) + { + if (*s1 != *s2) + return *s1 - *s2; + s1++; + s2++; + } + + return 0; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} + +/* +FUNCTION + <<strchr>>---search for character in string +INDEX + strchr +SYNOPSIS + #include <string.h> + char * strchr(const char *<[string]>, int <[c]>); +DESCRIPTION + This function finds the first occurence of <[c]> (converted to + a char) in the string pointed to by <[string]> (including the + terminating null character). +RETURNS + Returns a pointer to the located character, or a null pointer + if <[c]> does not occur in <[string]>. +PORTABILITY +<<strchr>> is ANSI C. +<<strchr>> requires no supporting OS subroutines. +QUICKREF + strchr ansi pure +*/ + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + + +/* Nonzero if X is not aligned on a "long" boundary. */ +#define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) + +/* How many bytes are loaded each iteration of the word copy loop. */ +#define LBLOCKSIZE (sizeof (long)) + +char * +strchr (const char *s1, + int i) +{ + const unsigned char *s = (const unsigned char *)s1; + unsigned char c = i; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned long mask,j; + unsigned long *aligned_addr; + + /* Special case for finding 0. */ + if (!c) + { + while (UNALIGNED (s)) + { + if (!*s) + return (char *) s; + s++; + } + /* Operate a word at a time. */ + aligned_addr = (unsigned long *) s; + while (!DETECTNULL (*aligned_addr)) + aligned_addr++; + /* Found the end of string. */ + s = (const unsigned char *) aligned_addr; + while (*s) + s++; + return (char *) s; + } + + /* All other bytes. Align the pointer, then search a long at a time. */ + while (UNALIGNED (s)) + { + if (!*s) + return NULL; + if (*s == c) + return (char *) s; + s++; + } + + mask = c; + for (j = 8; j < LBLOCKSIZE * 8; j <<= 1) + mask = (mask << j) | mask; + + aligned_addr = (unsigned long *) s; + while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) + aligned_addr++; + + /* The block of bytes currently pointed to by aligned_addr + contains either a null or the target char, or both. We + catch it using the bytewise search. */ + + s = (unsigned char *) aligned_addr; + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (*s && *s != c) + s++; + if (*s == c) + return (char *)s; + return NULL; +} + +/* +FUNCTION + <<strcmp>>---character string compare + +INDEX + strcmp +SYNOPSIS + #include <string.h> + int strcmp(const char *<[a]>, const char *<[b]>); +DESCRIPTION + <<strcmp>> compares the string at <[a]> to + the string at <[b]>. +RETURNS + If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, + <<strcmp>> returns a number greater than zero. If the two + strings match, <<strcmp>> returns zero. If <<*<[a]>>> + sorts lexicographically before <<*<[b]>>>, <<strcmp>> returns a + number less than zero. +PORTABILITY +<<strcmp>> is ANSI C. +<<strcmp>> requires no supporting OS subroutines. +QUICKREF + strcmp ansi pure +*/ + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) + +int +strcmp (const char *s1, + const char *s2) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + while (*s1 != '\0' && *s1 == *s2) + { + s1++; + s2++; + } + + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +#else + unsigned long *a1; + unsigned long *a2; + + /* If s1 or s2 are unaligned, then compare bytes. */ + if (!UNALIGNED (s1, s2)) + { + /* If s1 and s2 are word-aligned, compare them a word at a time. */ + a1 = (unsigned long*)s1; + a2 = (unsigned long*)s2; + while (*a1 == *a2) + { + /* To get here, *a1 == *a2, thus if we find a null in *a1, + then the strings must be equal, so return zero. */ + if (DETECTNULL (*a1)) + return 0; + + a1++; + a2++; + } + + /* A difference was detected in last few bytes of s1, so search bytewise */ + s1 = (char*)a1; + s2 = (char*)a2; + } + + while (*s1 != '\0' && *s1 == *s2) + { + s1++; + s2++; + } + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +#endif /* not PREFER_SIZE_OVER_SPEED */ +} + +/* +FUNCTION + <<strcpy>>---copy string +INDEX + strcpy +SYNOPSIS + #include <string.h> + char *strcpy(char *<[dst]>, const char *<[src]>); +DESCRIPTION + <<strcpy>> copies the string pointed to by <[src]> + (including the terminating null character) to the array + pointed to by <[dst]>. +RETURNS + This function returns the initial value of <[dst]>. +PORTABILITY +<<strcpy>> is ANSI C. +<<strcpy>> requires no supporting OS subroutines. +QUICKREF + strcpy ansi pure +*/ + +/*SUPPRESS 560*/ +/*SUPPRESS 530*/ + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + +/* Nonzero if either X or Y is not aligned on a "long" boundary. */ +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) + +char* +strcpy (char *dst0, + const char *src0) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *s = dst0; + + while (*dst0++ = *src0++) + ; + + return s; +#else + char *dst = dst0; + const char *src = src0; + long *aligned_dst; + const long *aligned_src; + + /* If SRC or DEST is unaligned, then copy bytes. */ + if (!UNALIGNED (src, dst)) + { + aligned_dst = (long*)dst; + aligned_src = (long*)src; + + /* SRC and DEST are both "long int" aligned, try to do "long int" + sized copies. */ + while (!DETECTNULL(*aligned_src)) + { + *aligned_dst++ = *aligned_src++; + } + + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while ((*dst++ = *src++)) + ; + return dst0; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} + +/* +FUNCTION + <<strlen>>---character string length +INDEX + strlen +SYNOPSIS + #include <string.h> + size_t strlen(const char *<[str]>); +DESCRIPTION + The <<strlen>> function works out the length of the string + starting at <<*<[str]>>> by counting chararacters until it + reaches a <<NULL>> character. +RETURNS + <<strlen>> returns the character count. +PORTABILITY +<<strlen>> is ANSI C. +<<strlen>> requires no supporting OS subroutines. +QUICKREF + strlen ansi pure +*/ + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + +#define LBLOCKSIZE (sizeof (long)) +#define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) +size_t +strlen (const char *str) +{ + const char *start = str; + +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) + unsigned long *aligned_addr; + + /* Align the pointer, so we can search a word at a time. */ + while (UNALIGNED (str)) + { + if (!*str) + return str - start; + str++; + } + + /* If the string is word-aligned, we can check for the presence of + a null in each word-sized block. */ + aligned_addr = (unsigned long *)str; + while (!DETECTNULL (*aligned_addr)) + aligned_addr++; + + /* Once a null is detected, we check each byte in that block for a + precise position of the null. */ + str = (char *) aligned_addr; + +#endif /* not PREFER_SIZE_OVER_SPEED */ + + while (*str) + str++; + return str - start; +} + +/* +FUNCTION + <<strncmp>>---character string compare + +INDEX + strncmp +SYNOPSIS + #include <string.h> + int strncmp(const char *<[a]>, const char * <[b]>, size_t <[length]>); +DESCRIPTION + <<strncmp>> compares up to <[length]> characters + from the string at <[a]> to the string at <[b]>. +RETURNS + If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, + <<strncmp>> returns a number greater than zero. If the two + strings are equivalent, <<strncmp>> returns zero. If <<*<[a]>>> + sorts lexicographically before <<*<[b]>>>, <<strncmp>> returns a + number less than zero. +PORTABILITY +<<strncmp>> is ANSI C. +<<strncmp>> requires no supporting OS subroutines. +QUICKREF + strncmp ansi pure +*/ + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) + +int +strncmp (const char *s1, + const char *s2, + size_t n) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + if (n == 0) + return 0; + + while (n-- != 0 && *s1 == *s2) + { + if (n == 0 || *s1 == '\0') + break; + s1++; + s2++; + } + + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +#else + unsigned long *a1; + unsigned long *a2; + + if (n == 0) + return 0; + + /* If s1 or s2 are unaligned, then compare bytes. */ + if (!UNALIGNED (s1, s2)) + { + /* If s1 and s2 are word-aligned, compare them a word at a time. */ + a1 = (unsigned long*)s1; + a2 = (unsigned long*)s2; + while (n >= sizeof (long) && *a1 == *a2) + { + n -= sizeof (long); + + /* If we've run out of bytes or hit a null, return zero + since we already know *a1 == *a2. */ + if (n == 0 || DETECTNULL (*a1)) + return 0; + + a1++; + a2++; + } + + /* A difference was detected in last few bytes of s1, so search bytewise */ + s1 = (char*)a1; + s2 = (char*)a2; + } + + while (n-- > 0 && *s1 == *s2) + { + /* If we've run out of bytes or hit a null, return zero + since we already know *s1 == *s2. */ + if (n == 0 || *s1 == '\0') + return 0; + s1++; + s2++; + } + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +#endif /* not PREFER_SIZE_OVER_SPEED */ +} + +/* +FUNCTION + <<strncpy>>---counted copy string +INDEX + strncpy +SYNOPSIS + #include <string.h> + char *strncpy(char *restrict <[dst]>, const char *restrict <[src]>, + size_t <[length]>); +DESCRIPTION + <<strncpy>> copies not more than <[length]> characters from the + the string pointed to by <[src]> (including the terminating + null character) to the array pointed to by <[dst]>. If the + string pointed to by <[src]> is shorter than <[length]> + characters, null characters are appended to the destination + array until a total of <[length]> characters have been + written. +RETURNS + This function returns the initial value of <[dst]>. +PORTABILITY +<<strncpy>> is ANSI C. +<<strncpy>> requires no supporting OS subroutines. +QUICKREF + strncpy ansi pure +*/ + +/*SUPPRESS 560*/ +/*SUPPRESS 530*/ + +#undef LBLOCKSIZE +#undef UNALIGNED +#undef TOO_SMALL + +#define UNALIGNED(X, Y) \ + (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) + +#define TOO_SMALL(LEN) ((LEN) < sizeof (long)) + +char * +strncpy (char *__restrict dst0, + const char *__restrict src0, + size_t count) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *dscan; + const char *sscan; + + dscan = dst0; + sscan = src0; + while (count > 0) + { + --count; + if ((*dscan++ = *sscan++) == '\0') + break; + } + while (count-- > 0) + *dscan++ = '\0'; + + return dst0; +#else + char *dst = dst0; + const char *src = src0; + long *aligned_dst; + const long *aligned_src; + + /* If SRC and DEST is aligned and count large enough, then copy words. */ + if (!UNALIGNED (src, dst) && !TOO_SMALL (count)) + { + aligned_dst = (long*)dst; + aligned_src = (long*)src; + + /* SRC and DEST are both "long int" aligned, try to do "long int" + sized copies. */ + while (count >= sizeof (long int) && !DETECTNULL(*aligned_src)) + { + count -= sizeof (long int); + *aligned_dst++ = *aligned_src++; + } + + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while (count > 0) + { + --count; + if ((*dst++ = *src++) == '\0') + break; + } + + while (count-- > 0) + *dst++ = '\0'; + + return dst0; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} + +/* +FUNCTION + <<strnlen>>---character string length + +INDEX + strnlen +SYNOPSIS + #include <string.h> + size_t strnlen(const char *<[str]>, size_t <[n]>); +DESCRIPTION + The <<strnlen>> function works out the length of the string + starting at <<*<[str]>>> by counting chararacters until it + reaches a NUL character or the maximum: <[n]> number of + characters have been inspected. +RETURNS + <<strnlen>> returns the character count or <[n]>. +PORTABILITY +<<strnlen>> is a GNU extension. +<<strnlen>> requires no supporting OS subroutines. +*/ + +size_t +strnlen (const char *str, + size_t n) +{ + const char *start = str; + + while (n-- > 0 && *str) + str++; + + return str - start; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif From ca0e41e8a092e8ff639c1b5b8e3412674dd5cd3b Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 28 Sep 2018 21:12:59 +0100 Subject: [PATCH 100/489] fusee: Improve integration with the new logging system fusee: Implement log level configuration from BCT.ini --- fusee/fusee-primary/src/lib/log.c | 10 +++-- fusee/fusee-primary/src/lib/log.h | 6 +-- fusee/fusee-primary/src/main.c | 47 +++++++++++++++----- fusee/fusee-primary/src/sdmmc/sdmmc_core.c | 43 ++++-------------- fusee/fusee-primary/src/sdmmc/sdmmc_core.h | 10 ----- fusee/fusee-primary/src/stage2.c | 11 +---- fusee/fusee-primary/src/stage2.h | 10 ++++- fusee/fusee-secondary/src/console.c | 10 ----- fusee/fusee-secondary/src/console.h | 7 +++ fusee/fusee-secondary/src/lib/log.c | 10 +++-- fusee/fusee-secondary/src/lib/log.h | 6 +-- fusee/fusee-secondary/src/main.c | 6 +-- fusee/fusee-secondary/src/sdmmc/sdmmc_core.c | 41 +++-------------- fusee/fusee-secondary/src/sdmmc/sdmmc_core.h | 10 ----- fusee/fusee-secondary/src/splash_screen.c | 6 +-- fusee/fusee-secondary/src/stage2.h | 4 +- 16 files changed, 98 insertions(+), 139 deletions(-) diff --git a/fusee/fusee-primary/src/lib/log.c b/fusee/fusee-primary/src/lib/log.c index 4aa396d72..37006b166 100644 --- a/fusee/fusee-primary/src/lib/log.c +++ b/fusee/fusee-primary/src/lib/log.c @@ -20,17 +20,21 @@ #include "vsprintf.h" /* default log level for screen output */ -ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_MANDATORY; +ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_NONE; void log_set_log_level(ScreenLogLevel log_level) { g_screen_log_level = log_level; } +ScreenLogLevel log_get_log_level() { + return g_screen_log_level; +} + void log_to_uart(const char *message) { /* TODO: add UART logging */ } -void print_to_screen(ScreenLogLevel screen_log_level, char *message) { +static void print_to_screen(ScreenLogLevel screen_log_level, char *message) { /* don't print to screen if below log level */ if(screen_log_level > g_screen_log_level) return; @@ -58,7 +62,7 @@ void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args) print_to_screen(screen_log_level, buf); } -void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) { +static void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) { char typebuf[] = "[%s] %s"; /* apply prefix and append message format */ diff --git a/fusee/fusee-primary/src/lib/log.h b/fusee/fusee-primary/src/lib/log.h index 00ddfdb6e..32703a318 100644 --- a/fusee/fusee-primary/src/lib/log.h +++ b/fusee/fusee-primary/src/lib/log.h @@ -14,8 +14,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef FUSEE_PRIMARY_PRINT_H -#define FUSEE_PRIMARY_PRINT_H +#ifndef FUSEE_LOG_H +#define FUSEE_LOG_H #define PRINT_MESSAGE_MAX_LENGTH 512 @@ -32,10 +32,10 @@ typedef enum { SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */ } ScreenLogLevel; -/* TODO: make this configurable by BCT.ini */ extern ScreenLogLevel g_screen_log_level; void log_set_log_level(ScreenLogLevel screen_log_level); +ScreenLogLevel log_get_log_level(); void log_to_uart(const char *message); void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args); void print(ScreenLogLevel screen_log_level, const char* fmt, ...); diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index b41149ce4..130362e0a 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -26,6 +26,8 @@ #include "sdmmc/sdmmc.h" #include "lib/fatfs/ff.h" #include "lib/log.h" +#include "lib/vsprintf.h" +#include "lib/ini.h" #include "display/video_fb.h" extern void (*__program_exit_callback)(int rc); @@ -33,6 +35,8 @@ extern void (*__program_exit_callback)(int rc); static void *g_framebuffer; static char g_bct0_buffer[BCTO_MAX_SIZE]; +#define CONFIG_LOG_LEVEL_KEY "log_level" + #define DEFAULT_BCT0_FOR_DEBUG \ "BCT0\n"\ "[stage1]\n"\ @@ -45,25 +49,41 @@ static const char *load_config(void) { print(SCREEN_LOG_LEVEL_DEBUG, "Failed to read BCT0 from SD!\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Using default BCT0!\n"); memcpy(g_bct0_buffer, DEFAULT_BCT0_FOR_DEBUG, sizeof(DEFAULT_BCT0_FOR_DEBUG)); - /* TODO: Stop using default. */ - /* printk("Error: Failed to load BCT.ini!\n"); - * generic_panic(); */ } if (memcmp(g_bct0_buffer, "BCT0", 4) != 0) { fatal_error("Unexpected magic in BCT.ini!\n"); } + /* Return pointer to first line of the ini. */ const char *bct0 = g_bct0_buffer; while (*bct0 && *bct0 != '\n') { bct0++; } + if (!bct0) { fatal_error("BCT.ini has no newline!\n"); } + return bct0; } +static int config_ini_handler(void *user, const char *section, const char *name, const char *value) { + if (strcmp(section, "config") == 0) { + if (strcmp(name, CONFIG_LOG_LEVEL_KEY) == 0) { + ScreenLogLevel *config_log_level = (ScreenLogLevel *)user; + int log_level = 0; + sscanf(value, "%d", &log_level); + *config_log_level = (ScreenLogLevel)log_level; + } else { + return 0; + } + } else { + return 0; + } + return 1; +} + static void setup_env(void) { g_framebuffer = (void *)0xC0000000; @@ -111,20 +131,26 @@ int main(void) { const char *stage2_path; stage2_args_t *stage2_args; uint32_t stage2_version = 0; - - /* Set the SDMMC's driver logging level. */ - sdmmc_set_log_level(SDMMC_LOG_INFO); + ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY; /* Initialize the display, console, etc. */ setup_env(); - /* Say hello. */ - print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); - print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); - /* Load the BCT0 configuration ini off of the SD. */ bct0 = load_config(); + /* Extract the logging level from the BCT.ini file. */ + if (ini_parse_string(bct0, config_ini_handler, &log_level) < 0) { + fatal_error("Failed to parse BCT.ini!\n"); + } + + /* Override the global logging level. */ + log_set_log_level(log_level); + + /* Say hello. */ + print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); + print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); + /* Load the loader payload into DRAM. */ load_stage2(bct0); @@ -133,6 +159,7 @@ int main(void) { strcpy(g_chainloader_arg_data, stage2_path); stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */ memcpy(&stage2_args->version, &stage2_version, 4); + stage2_args->log_level = log_level; stage2_args->display_initialized = false; strcpy(stage2_args->bct0, bct0); g_chainloader_argc = 2; diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c index 9d353d3b9..ded10a7ab 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.c @@ -32,39 +32,12 @@ #include "../max7762x.h" #include "../lib/log.h" -static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; - -void sdmmc_set_log_level(SdmmcLogLevel log_level) +static void sdmmc_print(sdmmc_t *sdmmc, ScreenLogLevel screen_log_level, char *fmt, va_list list) { - g_sdmmc_log_level = log_level; -} - -static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_list list) -{ - if (log_level > g_sdmmc_log_level) + if (screen_log_level > log_get_log_level()) return; - - char sdmmc_fmt[] = "%s: "; - ScreenLogLevel screen_log_level = SCREEN_LOG_LEVEL_ERROR; - - switch (log_level) { - case SDMMC_LOG_ERROR: - screen_log_level = SCREEN_LOG_LEVEL_ERROR; - break; - case SDMMC_LOG_WARN: - screen_log_level = SCREEN_LOG_LEVEL_WARNING; - break; - case SDMMC_LOG_INFO: - screen_log_level = SCREEN_LOG_LEVEL_DEBUG; - break; - case SDMMC_LOG_DEBUG: - screen_log_level = SCREEN_LOG_LEVEL_DEBUG; - break; - default: - break; - } - - print(screen_log_level, sdmmc_fmt, sdmmc->name); + + print(screen_log_level, "%s: ", sdmmc->name); vprint(screen_log_level, fmt, list); print(screen_log_level | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); } @@ -74,7 +47,7 @@ void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...) va_list list; va_start(list, fmt); - sdmmc_print(sdmmc, SDMMC_LOG_ERROR, fmt, list); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_ERROR, fmt, list); va_end(list); } @@ -83,7 +56,7 @@ void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...) va_list list; va_start(list, fmt); - sdmmc_print(sdmmc, SDMMC_LOG_WARN, fmt, list); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_WARNING, fmt, list); va_end(list); } @@ -92,7 +65,7 @@ void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...) va_list list; va_start(list, fmt); - sdmmc_print(sdmmc, SDMMC_LOG_INFO, fmt, list); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_INFO, fmt, list); va_end(list); } @@ -101,7 +74,7 @@ void sdmmc_debug(sdmmc_t *sdmmc, char *fmt, ...) va_list list; va_start(list, fmt); - sdmmc_print(sdmmc, SDMMC_LOG_DEBUG, fmt, list); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_DEBUG, fmt, list); va_end(list); } diff --git a/fusee/fusee-primary/src/sdmmc/sdmmc_core.h b/fusee/fusee-primary/src/sdmmc/sdmmc_core.h index edcd3c60f..ccfab130b 100644 --- a/fusee/fusee-primary/src/sdmmc/sdmmc_core.h +++ b/fusee/fusee-primary/src/sdmmc/sdmmc_core.h @@ -181,15 +181,6 @@ #define SDMMC_RSP_SPI_R5 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2) #define SDMMC_RSP_SPI_R7 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4) -/* Internal logging */ -typedef enum { - SDMMC_LOG_NONE = 0, - SDMMC_LOG_ERROR = 1, - SDMMC_LOG_WARN = 2, - SDMMC_LOG_INFO = 3, - SDMMC_LOG_DEBUG = 4 -} SdmmcLogLevel; - /* SDMMC controllers */ typedef enum { SDMMC_1 = 0, @@ -306,7 +297,6 @@ int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcod int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t *num_blocks_out); int sdmmc_load_response(sdmmc_t *sdmmc, uint32_t flags, uint32_t *resp); int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode); -void sdmmc_set_log_level(SdmmcLogLevel log_level); void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...); void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...); void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...); diff --git a/fusee/fusee-primary/src/stage2.c b/fusee/fusee-primary/src/stage2.c index 66b8dcd4b..4d1e1d9da 100644 --- a/fusee/fusee-primary/src/stage2.c +++ b/fusee/fusee-primary/src/stage2.c @@ -13,18 +13,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include <stdint.h> -#include "utils.h" -#include "display/video_fb.h" -#include "fs_utils.h" #include "stage2.h" #include "chainloader.h" -#include "lib/log.h" -#include "lib/vsprintf.h" -#include "lib/ini.h" -#include "lib/fatfs/ff.h" +#include "fs_utils.h" +#include "utils.h" char g_stage2_path[0x100] = {0}; diff --git a/fusee/fusee-primary/src/stage2.h b/fusee/fusee-primary/src/stage2.h index 72b22f6a9..e453d159f 100644 --- a/fusee/fusee-primary/src/stage2.h +++ b/fusee/fusee-primary/src/stage2.h @@ -17,7 +17,14 @@ #ifndef FUSEE_STAGE2_H #define FUSEE_STAGE2_H -#include "sdmmc/sdmmc_core.h" +#include <stdbool.h> +#include <stdint.h> + +#include "display/video_fb.h" +#include "lib/log.h" +#include "lib/vsprintf.h" +#include "lib/ini.h" +#include "lib/fatfs/ff.h" /* TODO: Is there a more concise way to do this? */ #define STAGE2_ARGV_PROGRAM_PATH 0 @@ -37,6 +44,7 @@ typedef struct { typedef struct { uint32_t version; + ScreenLogLevel log_level; bool display_initialized; char bct0[BCTO_MAX_SIZE]; } stage2_args_t; diff --git a/fusee/fusee-secondary/src/console.c b/fusee/fusee-secondary/src/console.c index 0eb49fb06..3131620f3 100644 --- a/fusee/fusee-secondary/src/console.c +++ b/fusee/fusee-secondary/src/console.c @@ -14,12 +14,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <errno.h> -#include <malloc.h> -#include <sys/iosupport.h> #include "console.h" #include "di.h" #include "display/video_fb.h" @@ -181,7 +175,6 @@ void *console_get_framebuffer(bool enable_display) { if (g_framebuffer != NULL && enable_display) { console_init_display(); } - return g_framebuffer; } @@ -189,8 +182,6 @@ int console_display(const void *framebuffer) { if (!g_display_initialized) { console_init_display(); } - - /* TODO: does this work? */ display_init_framebuffer((void *)framebuffer); return 0; } @@ -199,7 +190,6 @@ int console_resume(void) { if (!g_display_initialized) { console_init_display(); } else { - /* TODO: does this work? */ display_init_framebuffer(g_framebuffer); } return 0; diff --git a/fusee/fusee-secondary/src/console.h b/fusee/fusee-secondary/src/console.h index 492a11299..29c67be5e 100644 --- a/fusee/fusee-secondary/src/console.h +++ b/fusee/fusee-secondary/src/console.h @@ -17,6 +17,13 @@ #ifndef FUSEE_CONSOLE_H #define FUSEE_CONSOLE_H +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <errno.h> +#include <malloc.h> +#include <sys/iosupport.h> + int console_init(bool display_initialized); void *console_get_framebuffer(bool enable_display); int console_display(const void *framebuffer); /* Must be page-aligned */ diff --git a/fusee/fusee-secondary/src/lib/log.c b/fusee/fusee-secondary/src/lib/log.c index d4cae38b3..402121d4d 100644 --- a/fusee/fusee-secondary/src/lib/log.c +++ b/fusee/fusee-secondary/src/lib/log.c @@ -19,17 +19,21 @@ #include <stdio.h> /* default log level for screen output */ -ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_MANDATORY; +ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_NONE; void log_set_log_level(ScreenLogLevel log_level) { g_screen_log_level = log_level; } +ScreenLogLevel log_get_log_level() { + return g_screen_log_level; +} + void log_to_uart(const char *message) { /* TODO: add UART logging */ } -void print_to_screen(ScreenLogLevel screen_log_level, char *message) { +static void print_to_screen(ScreenLogLevel screen_log_level, char *message) { /* don't print to screen if below log level */ if(screen_log_level > g_screen_log_level) return; @@ -57,7 +61,7 @@ void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args) print_to_screen(screen_log_level, buf); } -void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) { +static void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) { char typebuf[] = "[%s] %s"; /* apply prefix and append message format */ diff --git a/fusee/fusee-secondary/src/lib/log.h b/fusee/fusee-secondary/src/lib/log.h index 080f34bef..32703a318 100644 --- a/fusee/fusee-secondary/src/lib/log.h +++ b/fusee/fusee-secondary/src/lib/log.h @@ -14,8 +14,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef FUSEE_SECONDARY_PRINT_H -#define FUSEE_SECONDARY_PRINT_H +#ifndef FUSEE_LOG_H +#define FUSEE_LOG_H #define PRINT_MESSAGE_MAX_LENGTH 512 @@ -32,10 +32,10 @@ typedef enum { SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */ } ScreenLogLevel; -/* TODO: make this configurable by BCT.ini */ extern ScreenLogLevel g_screen_log_level; void log_set_log_level(ScreenLogLevel screen_log_level); +ScreenLogLevel log_get_log_level(); void log_to_uart(const char *message); void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args); void print(ScreenLogLevel screen_log_level, const char* fmt, ...); diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index ec2ea8bc4..d10e6e7cb 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -52,8 +52,6 @@ static void setup_env(void) { if (nxfs_mount_all() < 0) { fatal_error("Failed to mount at least one parition: %s\n", strerror(errno)); } - - /* TODO: What other hardware init should we do here? */ } static void cleanup_env(void) { @@ -87,8 +85,8 @@ int main(int argc, void **argv) { generic_panic(); } - /* Set the SDMMC's driver logging level. */ - sdmmc_set_log_level(SDMMC_LOG_INFO); + /* Override the global logging level. */ + log_set_log_level(g_stage2_args->log_level); /* Initialize the display, console, FS, etc. */ setup_env(); diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c index 56602bc49..ded10a7ab 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.c @@ -32,39 +32,12 @@ #include "../max7762x.h" #include "../lib/log.h" -static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE; - -void sdmmc_set_log_level(SdmmcLogLevel log_level) +static void sdmmc_print(sdmmc_t *sdmmc, ScreenLogLevel screen_log_level, char *fmt, va_list list) { - g_sdmmc_log_level = log_level; -} - -static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_list list) -{ - if (log_level > g_sdmmc_log_level) + if (screen_log_level > log_get_log_level()) return; - - char sdmmc_fmt[] = "%s: "; - ScreenLogLevel screen_log_level = SCREEN_LOG_LEVEL_ERROR; - switch (log_level) { - case SDMMC_LOG_ERROR: - screen_log_level = SCREEN_LOG_LEVEL_ERROR; - break; - case SDMMC_LOG_WARN: - screen_log_level = SCREEN_LOG_LEVEL_WARNING; - break; - case SDMMC_LOG_INFO: - screen_log_level = SCREEN_LOG_LEVEL_DEBUG; - break; - case SDMMC_LOG_DEBUG: - screen_log_level = SCREEN_LOG_LEVEL_DEBUG; - break; - default: - break; - } - - print(screen_log_level, sdmmc_fmt, sdmmc->name); + print(screen_log_level, "%s: ", sdmmc->name); vprint(screen_log_level, fmt, list); print(screen_log_level | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); } @@ -74,7 +47,7 @@ void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...) va_list list; va_start(list, fmt); - sdmmc_print(sdmmc, SDMMC_LOG_ERROR, fmt, list); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_ERROR, fmt, list); va_end(list); } @@ -83,7 +56,7 @@ void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...) va_list list; va_start(list, fmt); - sdmmc_print(sdmmc, SDMMC_LOG_WARN, fmt, list); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_WARNING, fmt, list); va_end(list); } @@ -92,7 +65,7 @@ void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...) va_list list; va_start(list, fmt); - sdmmc_print(sdmmc, SDMMC_LOG_INFO, fmt, list); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_INFO, fmt, list); va_end(list); } @@ -101,7 +74,7 @@ void sdmmc_debug(sdmmc_t *sdmmc, char *fmt, ...) va_list list; va_start(list, fmt); - sdmmc_print(sdmmc, SDMMC_LOG_DEBUG, fmt, list); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_DEBUG, fmt, list); va_end(list); } diff --git a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h index edcd3c60f..ccfab130b 100644 --- a/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h +++ b/fusee/fusee-secondary/src/sdmmc/sdmmc_core.h @@ -181,15 +181,6 @@ #define SDMMC_RSP_SPI_R5 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2) #define SDMMC_RSP_SPI_R7 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4) -/* Internal logging */ -typedef enum { - SDMMC_LOG_NONE = 0, - SDMMC_LOG_ERROR = 1, - SDMMC_LOG_WARN = 2, - SDMMC_LOG_INFO = 3, - SDMMC_LOG_DEBUG = 4 -} SdmmcLogLevel; - /* SDMMC controllers */ typedef enum { SDMMC_1 = 0, @@ -306,7 +297,6 @@ int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcod int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t *num_blocks_out); int sdmmc_load_response(sdmmc_t *sdmmc, uint32_t flags, uint32_t *resp); int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode); -void sdmmc_set_log_level(SdmmcLogLevel log_level); void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...); void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...); void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...); diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index 97b258ccd..17cc302af 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -13,8 +13,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include <stdio.h> + +#include "console.h" #include "di.h" #include "timers.h" #include "splash_screen.h" @@ -36,7 +36,7 @@ static void render_bmp(const uint32_t *bmp_data, uint32_t *framebuffer, uint32_t } /* Re-initialize the frame buffer. */ - display_init_framebuffer(framebuffer); + console_display(framebuffer); } void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address) { diff --git a/fusee/fusee-secondary/src/stage2.h b/fusee/fusee-secondary/src/stage2.h index c3d18ef49..1274efeee 100644 --- a/fusee/fusee-secondary/src/stage2.h +++ b/fusee/fusee-secondary/src/stage2.h @@ -17,8 +17,9 @@ #ifndef FUSEE_STAGE2_H #define FUSEE_STAGE2_H -#include "utils.h" +#include "lib/log.h" #include "sdmmc/sdmmc.h" +#include "utils.h" /* TODO: Is there a more concise way to do this? */ #define STAGE2_ARGV_PROGRAM_PATH 0 @@ -29,6 +30,7 @@ typedef struct { uint32_t version; + ScreenLogLevel log_level; bool display_initialized; char bct0[BCTO_MAX_SIZE]; } stage2_args_t; From 0938057d6795aac5dfffc44cf4338d78ec85eadf Mon Sep 17 00:00:00 2001 From: roblabla <unfiltered@roblab.la> Date: Sat, 29 Sep 2018 02:37:25 +0000 Subject: [PATCH 101/489] Use new npdm-json format --- stratosphere/boot/boot_100.json | 267 ++++++++++++++++++------------ stratosphere/boot/boot_200.json | 260 +++++++++++++++++------------ stratosphere/creport/creport.json | 202 +++++++++++----------- stratosphere/fs_mitm/fs_mitm.json | 142 ++++++++-------- stratosphere/loader/loader.json | 134 ++++++++------- stratosphere/pm/pm.json | 144 ++++++++-------- stratosphere/sm/sm.json | 130 ++++++++------- 7 files changed, 708 insertions(+), 571 deletions(-) diff --git a/stratosphere/boot/boot_100.json b/stratosphere/boot/boot_100.json index 81d8b3a02..194005f95 100644 --- a/stratosphere/boot/boot_100.json +++ b/stratosphere/boot/boot_100.json @@ -1,119 +1,170 @@ { - "name" : "boot", - "title_id" : "0x0100000000000005", - "main_thread_stack_size" : "0x1000", - "main_thread_priority" : 27, - "default_cpu_id" : 3, - "process_category" : 1, - "kernel_capabilities" : { - "handle_table_size" : 128, - "syscalls" : { - "svcSetHeapSize" : "0x01", - "svcSetMemoryPermission" : "0x02", - "svcSetMemoryAttribute" : "0x03", - "svcMapMemory" : "0x04", - "svcUnmapMemory" : "0x05", - "svcQueryMemory" : "0x06", - "svcExitProcess" : "0x07", - "svcCreateThread" : "0x08", - "svcStartThread" : "0x09", - "svcExitThread" : "0x0A", - "svcSleepThread" : "0x0B", - "svcGetThreadPriority" : "0x0C", - "svcSetThreadPriority" : "0x0D", - "svcGetThreadCoreMask" : "0x0E", - "svcSetThreadCoreMask" : "0x0F", - "svcGetCurrentProcessorNumber" : "0x10", - "svcSignalEvent" : "0x11", - "svcClearEvent" : "0x12", - "svcMapSharedMemory" : "0x13", - "svcUnmapSharedMemory" : "0x14", - "svcCreateTransferMemory" : "0x15", - "svcCloseHandle" : "0x16", - "svcResetSignal" : "0x17", - "svcWaitSynchronization" : "0x18", - "svcCancelSynchronization" : "0x19", - "svcArbitrateLock" : "0x1A", - "svcArbitrateUnlock" : "0x1B", - "svcWaitProcessWideKeyAtomic" : "0x1C", - "svcSignalProcessWideKey" : "0x1D", - "svcGetSystemTick" : "0x1E", - "svcConnectToNamedPort" : "0x1F", - "svcSendSyncRequestLight" : "0x20", - "svcSendSyncRequest" : "0x21", - "svcSendSyncRequestWithUserBuffer" : "0x22", - "svcSendAsyncRequestWithUserBuffer" : "0x23", - "svcGetProcessId" : "0x24", - "svcGetThreadId" : "0x25", - "svcBreak" : "0x26", - "svcOutputDebugString" : "0x27", - "svcReturnFromException" : "0x28", - "svcGetInfo" : "0x29", - "svcCreateInterruptEvent" : "0x53", - "svcQueryIoMapping" : "0x55", - "svcCreateDeviceAddressSpace" : "0x56", - "svcAttachDeviceAddressSpace" : "0x57", - "svcDetachDeviceAddressSpace" : "0x58", - "svcMapDeviceAddressSpaceAligned" : "0x5A", - "svcUnmapDeviceAddressSpace" : "0x5C", - "svcFlushProcessDataCache" : "0x5F" + "name": "boot", + "title_id": "0x0100000000000005", + "main_thread_stack_size": "0x1000", + "main_thread_priority": 27, + "default_cpu_id": 3, + "process_category": 1, + "kernel_capabilities": [ + { + "type": "handle_table_size", + "value": 128 }, - "map" : { - "address" : "0x50003000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0A", + "svcSleepThread": "0x0B", + "svcGetThreadPriority": "0x0C", + "svcSetThreadPriority": "0x0D", + "svcGetThreadCoreMask": "0x0E", + "svcSetThreadCoreMask": "0x0F", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1A", + "svcArbitrateUnlock": "0x1B", + "svcWaitProcessWideKeyAtomic": "0x1C", + "svcSignalProcessWideKey": "0x1D", + "svcGetSystemTick": "0x1E", + "svcConnectToNamedPort": "0x1F", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcCreateInterruptEvent": "0x53", + "svcQueryIoMapping": "0x55", + "svcCreateDeviceAddressSpace": "0x56", + "svcAttachDeviceAddressSpace": "0x57", + "svcDetachDeviceAddressSpace": "0x58", + "svcMapDeviceAddressSpaceAligned": "0x5A", + "svcUnmapDeviceAddressSpace": "0x5C", + "svcFlushProcessDataCache": "0x5F" + } }, - "map" : { - "address" : "0x54200000", - "size" : "0x3000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x50003000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x54300000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x54200000", + "size": "0x3000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x60006000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x54300000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x6000D000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x60006000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x70000000", - "size" : "0x4000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x6000D000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x7000C000", - "size" : "0x2000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x70000000", + "size": "0x4000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x7000E000", - "size" : "0x4000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x7000C000", + "size": "0x2000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x700E3000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x7000E000", + "size": "0x4000", + "is_ro": false, + "is_io": true + } }, - "irq_pair" : [70, 116], - "irq_pair" : [124, 152], - "irq_pair" : [85, 95] - } -} + { + "type": "map", + "value": { + "address": "0x700E3000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } + }, + { + "type": "irq_pair", + "value": [ + 70, + 116 + ] + }, + { + "type": "irq_pair", + "value": [ + 124, + 152 + ] + }, + { + "type": "irq_pair", + "value": [ + 85, + 95 + ] + } + ] +} \ No newline at end of file diff --git a/stratosphere/boot/boot_200.json b/stratosphere/boot/boot_200.json index 645d2e0b5..01a0fb41d 100644 --- a/stratosphere/boot/boot_200.json +++ b/stratosphere/boot/boot_200.json @@ -1,116 +1,164 @@ { - "name" : "boot", - "title_id" : "0x0100000000000005", - "main_thread_stack_size" : "0x1000", - "main_thread_priority" : 27, - "default_cpu_id" : 3, - "process_category" : 1, - "kernel_capabilities" : { - "handle_table_size" : 128, - "syscalls" : { - "svcSetHeapSize" : "0x01", - "svcSetMemoryPermission" : "0x02", - "svcSetMemoryAttribute" : "0x03", - "svcMapMemory" : "0x04", - "svcUnmapMemory" : "0x05", - "svcQueryMemory" : "0x06", - "svcExitProcess" : "0x07", - "svcCreateThread" : "0x08", - "svcStartThread" : "0x09", - "svcExitThread" : "0x0A", - "svcSleepThread" : "0x0B", - "svcGetThreadPriority" : "0x0C", - "svcSetThreadPriority" : "0x0D", - "svcGetThreadCoreMask" : "0x0E", - "svcSetThreadCoreMask" : "0x0F", - "svcGetCurrentProcessorNumber" : "0x10", - "svcSignalEvent" : "0x11", - "svcClearEvent" : "0x12", - "svcMapSharedMemory" : "0x13", - "svcUnmapSharedMemory" : "0x14", - "svcCreateTransferMemory" : "0x15", - "svcCloseHandle" : "0x16", - "svcResetSignal" : "0x17", - "svcWaitSynchronization" : "0x18", - "svcCancelSynchronization" : "0x19", - "svcArbitrateLock" : "0x1A", - "svcArbitrateUnlock" : "0x1B", - "svcWaitProcessWideKeyAtomic" : "0x1C", - "svcSignalProcessWideKey" : "0x1D", - "svcGetSystemTick" : "0x1E", - "svcConnectToNamedPort" : "0x1F", - "svcSendSyncRequestLight" : "0x20", - "svcSendSyncRequest" : "0x21", - "svcSendSyncRequestWithUserBuffer" : "0x22", - "svcSendAsyncRequestWithUserBuffer" : "0x23", - "svcGetProcessId" : "0x24", - "svcGetThreadId" : "0x25", - "svcBreak" : "0x26", - "svcOutputDebugString" : "0x27", - "svcReturnFromException" : "0x28", - "svcGetInfo" : "0x29", - "svcWaitForAddress" : "0x34", - "svcSignalToAddress" : "0x35", - "svcReadWriteRegister" : "0x4E", - "svcCreateInterruptEvent" : "0x53", - "svcQueryIoMapping" : "0x55", - "svcCreateDeviceAddressSpace" : "0x56", - "svcAttachDeviceAddressSpace" : "0x57", - "svcDetachDeviceAddressSpace" : "0x58", - "svcMapDeviceAddressSpaceAligned" : "0x5A", - "svcUnmapDeviceAddressSpace" : "0x5C", - "svcFlushProcessDataCache" : "0x5F" + "name": "boot", + "title_id": "0x0100000000000005", + "main_thread_stack_size": "0x1000", + "main_thread_priority": 27, + "default_cpu_id": 3, + "process_category": 1, + "kernel_capabilities": [ + { + "type": "handle_table_size", + "value": 128 }, - "map" : { - "address" : "0x50003000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0A", + "svcSleepThread": "0x0B", + "svcGetThreadPriority": "0x0C", + "svcSetThreadPriority": "0x0D", + "svcGetThreadCoreMask": "0x0E", + "svcSetThreadCoreMask": "0x0F", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1A", + "svcArbitrateUnlock": "0x1B", + "svcWaitProcessWideKeyAtomic": "0x1C", + "svcSignalProcessWideKey": "0x1D", + "svcGetSystemTick": "0x1E", + "svcConnectToNamedPort": "0x1F", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcReadWriteRegister": "0x4E", + "svcCreateInterruptEvent": "0x53", + "svcQueryIoMapping": "0x55", + "svcCreateDeviceAddressSpace": "0x56", + "svcAttachDeviceAddressSpace": "0x57", + "svcDetachDeviceAddressSpace": "0x58", + "svcMapDeviceAddressSpaceAligned": "0x5A", + "svcUnmapDeviceAddressSpace": "0x5C", + "svcFlushProcessDataCache": "0x5F" + } }, - "map" : { - "address" : "0x54200000", - "size" : "0x3000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x50003000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x54300000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x54200000", + "size": "0x3000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x60006000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x54300000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x6000D000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x60006000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x70000000", - "size" : "0x4000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x6000D000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x7000C000", - "size" : "0x2000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x70000000", + "size": "0x4000", + "is_ro": false, + "is_io": true + } }, - "map" : { - "address" : "0x700E3000", - "size" : "0x1000", - "is_ro" : false, - "is_io" : true + { + "type": "map", + "value": { + "address": "0x7000C000", + "size": "0x2000", + "is_ro": false, + "is_io": true + } }, - "irq_pair" : [70, 116], - "irq_pair" : [124, 152], - "irq_pair" : [85, 95] - } -} + { + "type": "map", + "value": { + "address": "0x700E3000", + "size": "0x1000", + "is_ro": false, + "is_io": true + } + }, + { + "type": "irq_pair", + "value": [ + 70, + 116 + ] + }, + { + "type": "irq_pair", + "value": [ + 124, + 152 + ] + }, + { + "type": "irq_pair", + "value": [ + 85, + 95 + ] + } + ] +} \ No newline at end of file diff --git a/stratosphere/creport/creport.json b/stratosphere/creport/creport.json index fc94da978..5cc6b0c15 100644 --- a/stratosphere/creport/creport.json +++ b/stratosphere/creport/creport.json @@ -1,96 +1,110 @@ { - "name": "creport", - "title_id": "0x0100000000000036", - "title_id_range_min": "0x0100000000000036", - "title_id_range_max": "0x0100000000000036", - "main_thread_stack_size": "0x00004000", - "main_thread_priority": 44, - "default_cpu_id": 3, - "process_category": 0, - "is_retail": true, - "pool_partition": 2, - "is_64_bit": true, - "address_space_type": 3, - "filesystem_access": { - "permissions": "0xFFFFFFFFFFFFFFFF" - }, - "service_access": { - "csrng": false, - "erpt:c": false, - "fatal:u": false, - "ns:dev": false, - "fsp-srv": false, - "time:s": true - }, - "kernel_capabilities": { - "kernel_flags": { - "highest_thread_priority": 63, - "lowest_thread_priority": 24, - "lowest_cpu_id": 3, - "highest_cpu_id": 3 - }, - "syscalls": { - "svcSetHeapSize": "0x01", - "svcSetMemoryPermission": "0x02", - "svcSetMemoryAttribute": "0x03", - "svcMapMemory": "0x04", - "svcUnmapMemory": "0x05", - "svcQueryMemory": "0x06", - "svcExitProcess": "0x07", - "svcCreateThread": "0x08", - "svcStartThread": "0x09", - "svcExitThread": "0x0a", - "svcSleepThread": "0x0b", - "svcGetThreadPriority": "0x0c", - "svcSetThreadPriority": "0x0d", - "svcGetThreadCoreMask": "0x0e", - "svcSetThreadCoreMask": "0x0f", - "svcGetCurrentProcessorNumber": "0x10", - "svcSignalEvent": "0x11", - "svcClearEvent": "0x12", - "svcMapSharedMemory": "0x13", - "svcUnmapSharedMemory": "0x14", - "svcCreateTransferMemory": "0x15", - "svcCloseHandle": "0x16", - "svcResetSignal": "0x17", - "svcWaitSynchronization": "0x18", - "svcCancelSynchronization": "0x19", - "svcArbitrateLock": "0x1a", - "svcArbitrateUnlock": "0x1b", - "svcWaitProcessWideKeyAtomic": "0x1c", - "svcSignalProcessWideKey": "0x1d", - "svcGetSystemTick": "0x1e", - "svcConnectToNamedPort": "0x1f", - "svcSendSyncRequestLight": "0x20", - "svcSendSyncRequest": "0x21", - "svcSendSyncRequestWithUserBuffer": "0x22", - "svcSendAsyncRequestWithUserBuffer": "0x23", - "svcGetProcessId": "0x24", - "svcGetThreadId": "0x25", - "svcBreak": "0x26", - "svcOutputDebugString": "0x27", - "svcReturnFromException": "0x28", - "svcGetInfo": "0x29", - "svcWaitForAddress": "0x34", - "svcSignalToAddress": "0x35", - "svcCreateSession": "0x40", - "svcAcceptSession": "0x41", - "svcReplyAndReceiveLight": "0x42", - "svcReplyAndReceive": "0x43", - "svcReplyAndReceiveWithUserBuffer": "0x44", - "svcCreateEvent": "0x45", - "svcDebugActiveProcess": "0x60", - "svcGetDebugEvent": "0x63", - "svcGetThreadList": "0x66", - "svcGetDebugThreadContext": "0x67", - "svcQueryDebugProcessMemory": "0x69", - "svcReadDebugProcessMemory": "0x6a", - "svcGetDebugThreadParam": "0x6d" - }, - "min_kernel_version": "0x0060", - "debug_flags": { - "allow_debug": false, - "force_debug": true - } - } + "name": "creport", + "title_id": "0x0100000000000036", + "title_id_range_min": "0x0100000000000036", + "title_id_range_max": "0x0100000000000036", + "main_thread_stack_size": "0x00004000", + "main_thread_priority": 44, + "default_cpu_id": 3, + "process_category": 0, + "is_retail": true, + "pool_partition": 2, + "is_64_bit": true, + "address_space_type": 3, + "filesystem_access": { + "permissions": "0xFFFFFFFFFFFFFFFF" + }, + "service_host": [ + "time:s" + ], + "service_access": [ + "csrng", + "erpt:c", + "fatal:u", + "ns:dev", + "fsp-srv" + ], + "kernel_capabilities": [ + { + "type": "kernel_flags", + "value": { + "highest_thread_priority": 63, + "lowest_thread_priority": 24, + "lowest_cpu_id": 3, + "highest_cpu_id": 3 + } + }, + { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0a", + "svcSleepThread": "0x0b", + "svcGetThreadPriority": "0x0c", + "svcSetThreadPriority": "0x0d", + "svcGetThreadCoreMask": "0x0e", + "svcSetThreadCoreMask": "0x0f", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1a", + "svcArbitrateUnlock": "0x1b", + "svcWaitProcessWideKeyAtomic": "0x1c", + "svcSignalProcessWideKey": "0x1d", + "svcGetSystemTick": "0x1e", + "svcConnectToNamedPort": "0x1f", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcCreateEvent": "0x45", + "svcDebugActiveProcess": "0x60", + "svcGetDebugEvent": "0x63", + "svcGetThreadList": "0x66", + "svcGetDebugThreadContext": "0x67", + "svcQueryDebugProcessMemory": "0x69", + "svcReadDebugProcessMemory": "0x6a", + "svcGetDebugThreadParam": "0x6d" + } + }, + { + "type": "min_kernel_version", + "value": "0x0060" + }, + { + "type": "debug_flags", + "value": { + "allow_debug": false, + "force_debug": true + } + } + ] } \ No newline at end of file diff --git a/stratosphere/fs_mitm/fs_mitm.json b/stratosphere/fs_mitm/fs_mitm.json index a6775155b..7733b4bbf 100644 --- a/stratosphere/fs_mitm/fs_mitm.json +++ b/stratosphere/fs_mitm/fs_mitm.json @@ -1,70 +1,76 @@ { - "name" : "fs.mitm", - "title_id" : "0x010041544D530000", - "main_thread_stack_size" : "0x20000", - "main_thread_priority": 43, - "default_cpu_id": 3, - "process_category" : 1, - "kernel_capabilities" : { - "handle_table_size" : 512, - "syscalls": { - "svcSetHeapSize": "0x01", - "svcSetMemoryPermission": "0x02", - "svcSetMemoryAttribute": "0x03", - "svcMapMemory": "0x04", - "svcUnmapMemory": "0x05", - "svcQueryMemory": "0x06", - "svcExitProcess": "0x07", - "svcCreateThread": "0x08", - "svcStartThread": "0x09", - "svcExitThread": "0x0a", - "svcSleepThread": "0x0b", - "svcGetThreadPriority": "0x0c", - "svcSetThreadPriority": "0x0d", - "svcGetThreadCoreMask": "0x0e", - "svcSetThreadCoreMask": "0x0f", - "svcGetCurrentProcessorNumber": "0x10", - "svcSignalEvent": "0x11", - "svcClearEvent": "0x12", - "svcMapSharedMemory": "0x13", - "svcUnmapSharedMemory": "0x14", - "svcCreateTransferMemory": "0x15", - "svcCloseHandle": "0x16", - "svcResetSignal": "0x17", - "svcWaitSynchronization": "0x18", - "svcCancelSynchronization": "0x19", - "svcArbitrateLock": "0x1a", - "svcArbitrateUnlock": "0x1b", - "svcWaitProcessWideKeyAtomic": "0x1c", - "svcSignalProcessWideKey": "0x1d", - "svcGetSystemTick": "0x1e", - "svcConnectToNamedPort": "0x1f", - "svcSendSyncRequestLight": "0x20", - "svcSendSyncRequest": "0x21", - "svcSendSyncRequestWithUserBuffer": "0x22", - "svcSendAsyncRequestWithUserBuffer": "0x23", - "svcGetProcessId": "0x24", - "svcGetThreadId": "0x25", - "svcBreak": "0x26", - "svcOutputDebugString": "0x27", - "svcReturnFromException": "0x28", - "svcGetInfo": "0x29", - "svcWaitForAddress": "0x34", - "svcSignalToAddress": "0x35", - "svcCreateSession": "0x40", - "svcAcceptSession": "0x41", - "svcReplyAndReceiveLight": "0x42", - "svcReplyAndReceive": "0x43", - "svcReplyAndReceiveWithUserBuffer": "0x44", - "svcCreateEvent": "0x45", - "svcCreateInterruptEvent": "0x53", - "svcQueryIoMapping": "0x55", - "svcCreateDeviceAddressSpace": "0x56", - "svcAttachDeviceAddressSpace": "0x57", - "svcDetachDeviceAddressSpace": "0x58", - "svcMapDeviceAddressSpaceAligned": "0x5a", - "svcUnmapDeviceAddressSpace": "0x5c", - "svcGetSystemInfo": "0x6f" - } - } + "name": "fs.mitm", + "title_id": "0x010041544D530000", + "main_thread_stack_size": "0x20000", + "main_thread_priority": 43, + "default_cpu_id": 3, + "process_category": 1, + "kernel_capabilities": [ + { + "type": "handle_table_size", + "value": 512 + }, + { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0a", + "svcSleepThread": "0x0b", + "svcGetThreadPriority": "0x0c", + "svcSetThreadPriority": "0x0d", + "svcGetThreadCoreMask": "0x0e", + "svcSetThreadCoreMask": "0x0f", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1a", + "svcArbitrateUnlock": "0x1b", + "svcWaitProcessWideKeyAtomic": "0x1c", + "svcSignalProcessWideKey": "0x1d", + "svcGetSystemTick": "0x1e", + "svcConnectToNamedPort": "0x1f", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcCreateEvent": "0x45", + "svcCreateInterruptEvent": "0x53", + "svcQueryIoMapping": "0x55", + "svcCreateDeviceAddressSpace": "0x56", + "svcAttachDeviceAddressSpace": "0x57", + "svcDetachDeviceAddressSpace": "0x58", + "svcMapDeviceAddressSpaceAligned": "0x5a", + "svcUnmapDeviceAddressSpace": "0x5c", + "svcGetSystemInfo": "0x6f" + } + } + ] } \ No newline at end of file diff --git a/stratosphere/loader/loader.json b/stratosphere/loader/loader.json index 27544a507..e4f16cc7c 100644 --- a/stratosphere/loader/loader.json +++ b/stratosphere/loader/loader.json @@ -1,67 +1,73 @@ { - "name" : "Loader", - "title_id" : "0x0100000000000001", - "main_thread_stack_size" : "0x4000", - "main_thread_priority" : 49, - "default_cpu_id" : 3, - "process_category" : 1, - "kernel_capabilities" : { - "handle_table_size" : 128, - "syscalls" : { - "svcSetHeapSize" : "0x01", - "svcSetMemoryPermission" : "0x02", - "svcSetMemoryAttribute" : "0x03", - "svcMapMemory" : "0x04", - "svcUnmapMemory" : "0x05", - "svcQueryMemory" : "0x06", - "svcExitProcess" : "0x07", - "svcCreateThread" : "0x08", - "svcStartThread" : "0x09", - "svcExitThread" : "0x0A", - "svcSleepThread" : "0x0B", - "svcGetThreadPriority" : "0x0C", - "svcSetThreadPriority" : "0x0D", - "svcGetThreadCoreMask" : "0x0E", - "svcSetThreadCoreMask" : "0x0F", - "svcGetCurrentProcessorNumber" : "0x10", - "svcSignalEvent" : "0x11", - "svcClearEvent" : "0x12", - "svcMapSharedMemory" : "0x13", - "svcUnmapSharedMemory" : "0x14", - "svcCreateTransferMemory" : "0x15", - "svcCloseHandle" : "0x16", - "svcResetSignal" : "0x17", - "svcWaitSynchronization" : "0x18", - "svcCancelSynchronization" : "0x19", - "svcArbitrateLock" : "0x1A", - "svcArbitrateUnlock" : "0x1B", - "svcWaitProcessWideKeyAtomic" : "0x1C", - "svcSignalProcessWideKey" : "0x1D", - "svcGetSystemTick" : "0x1E", - "svcConnectToNamedPort" : "0x1F", - "svcSendSyncRequestLight" : "0x20", - "svcSendSyncRequest" : "0x21", - "svcSendSyncRequestWithUserBuffer" : "0x22", - "svcSendAsyncRequestWithUserBuffer" : "0x23", - "svcGetProcessId" : "0x24", - "svcGetThreadId" : "0x25", - "svcBreak" : "0x26", - "svcOutputDebugString" : "0x27", - "svcReturnFromException" : "0x28", - "svcGetInfo" : "0x29", - "svcWaitForAddress" : "0x34", - "svcSignalToAddress" : "0x35", - "svcCreateSession" : "0x40", - "svcAcceptSession" : "0x41", - "svcReplyAndReceiveLight" : "0x42", - "svcReplyAndReceive" : "0x43", - "svcReplyAndReceiveWithUserBuffer" : "0x44", - "svcSetProcessMemoryPermission" : "0x73", - "svcMapProcessMemory" : "0x74", - "svcUnmapProcessMemory" : "0x75", - "svcMapProcessCodeMemory" : "0x77", - "svcUnmapProcessCodeMemory" : "0x78", - "svcCreateProcess" : "0x79" + "name": "Loader", + "title_id": "0x0100000000000001", + "main_thread_stack_size": "0x4000", + "main_thread_priority": 49, + "default_cpu_id": 3, + "process_category": 1, + "kernel_capabilities": [ + { + "type": "handle_table_size", + "value": 128 + }, + { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0A", + "svcSleepThread": "0x0B", + "svcGetThreadPriority": "0x0C", + "svcSetThreadPriority": "0x0D", + "svcGetThreadCoreMask": "0x0E", + "svcSetThreadCoreMask": "0x0F", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1A", + "svcArbitrateUnlock": "0x1B", + "svcWaitProcessWideKeyAtomic": "0x1C", + "svcSignalProcessWideKey": "0x1D", + "svcGetSystemTick": "0x1E", + "svcConnectToNamedPort": "0x1F", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcSetProcessMemoryPermission": "0x73", + "svcMapProcessMemory": "0x74", + "svcUnmapProcessMemory": "0x75", + "svcMapProcessCodeMemory": "0x77", + "svcUnmapProcessCodeMemory": "0x78", + "svcCreateProcess": "0x79" + } } - } + ] } \ No newline at end of file diff --git a/stratosphere/pm/pm.json b/stratosphere/pm/pm.json index a7bd7e8a9..4af73d589 100644 --- a/stratosphere/pm/pm.json +++ b/stratosphere/pm/pm.json @@ -1,71 +1,77 @@ { - "name": "ProcessMana", - "title_id": "0x0100000000000003", - "main_thread_stack_size": "0x00001000", - "main_thread_priority": 49, - "default_cpu_id": 3, - "process_category": 1, - "kernel_capabilities": { - "handle_table_size": 128, - "syscalls": { - "svcSetHeapSize": "0x01", - "svcSetMemoryPermission": "0x02", - "svcSetMemoryAttribute": "0x03", - "svcMapMemory": "0x04", - "svcUnmapMemory": "0x05", - "svcQueryMemory": "0x06", - "svcExitProcess": "0x07", - "svcCreateThread": "0x08", - "svcStartThread": "0x09", - "svcExitThread": "0x0a", - "svcSleepThread": "0x0b", - "svcGetThreadPriority": "0x0c", - "svcSetThreadPriority": "0x0d", - "svcGetThreadCoreMask": "0x0e", - "svcSetThreadCoreMask": "0x0f", - "svcGetCurrentProcessorNumber": "0x10", - "svcSignalEvent": "0x11", - "svcClearEvent": "0x12", - "svcMapSharedMemory": "0x13", - "svcUnmapSharedMemory": "0x14", - "svcCreateTransferMemory": "0x15", - "svcCloseHandle": "0x16", - "svcResetSignal": "0x17", - "svcWaitSynchronization": "0x18", - "svcCancelSynchronization": "0x19", - "svcArbitrateLock": "0x1a", - "svcArbitrateUnlock": "0x1b", - "svcWaitProcessWideKeyAtomic": "0x1c", - "svcSignalProcessWideKey": "0x1d", - "svcGetSystemTick": "0x1e", - "svcConnectToNamedPort": "0x1f", - "svcSendSyncRequestLight": "0x20", - "svcSendSyncRequest": "0x21", - "svcSendSyncRequestWithUserBuffer": "0x22", - "svcSendAsyncRequestWithUserBuffer": "0x23", - "svcGetProcessId": "0x24", - "svcGetThreadId": "0x25", - "svcBreak": "0x26", - "svcOutputDebugString": "0x27", - "svcReturnFromException": "0x28", - "svcGetInfo": "0x29", - "svcGetResourceLimitLimitValue": "0x30", - "svcGetResourceLimitCurrentValue": "0x31", - "svcWaitForAddress": "0x34", - "svcSignalToAddress": "0x35", - "svcCreateSession": "0x40", - "svcAcceptSession": "0x41", - "svcReplyAndReceiveLight": "0x42", - "svcReplyAndReceive": "0x43", - "svcReplyAndReceiveWithUserBuffer": "0x44", - "svcCreateEvent": "0x45", - "svcStartProcess": "0x7a", - "svcTerminateProcess": "0x7b", - "svcGetProcessInfo": "0x7c", - "svcCreateResourceLimit": "0x7d", - "svcSetResourceLimitLimitValue": "0x7e", - "svcSetUnsafeLimit": "0x4a", - "svcGetSystemInfo": "0x6f" - } - } + "name": "ProcessMana", + "title_id": "0x0100000000000003", + "main_thread_stack_size": "0x00001000", + "main_thread_priority": 49, + "default_cpu_id": 3, + "process_category": 1, + "kernel_capabilities": [ + { + "type": "handle_table_size", + "value": 128 + }, + { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0a", + "svcSleepThread": "0x0b", + "svcGetThreadPriority": "0x0c", + "svcSetThreadPriority": "0x0d", + "svcGetThreadCoreMask": "0x0e", + "svcSetThreadCoreMask": "0x0f", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1a", + "svcArbitrateUnlock": "0x1b", + "svcWaitProcessWideKeyAtomic": "0x1c", + "svcSignalProcessWideKey": "0x1d", + "svcGetSystemTick": "0x1e", + "svcConnectToNamedPort": "0x1f", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcGetResourceLimitLimitValue": "0x30", + "svcGetResourceLimitCurrentValue": "0x31", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcCreateEvent": "0x45", + "svcStartProcess": "0x7a", + "svcTerminateProcess": "0x7b", + "svcGetProcessInfo": "0x7c", + "svcCreateResourceLimit": "0x7d", + "svcSetResourceLimitLimitValue": "0x7e", + "svcSetUnsafeLimit": "0x4a", + "svcGetSystemInfo": "0x6f" + } + } + ] } \ No newline at end of file diff --git a/stratosphere/sm/sm.json b/stratosphere/sm/sm.json index 0d3074e10..101c741e1 100644 --- a/stratosphere/sm/sm.json +++ b/stratosphere/sm/sm.json @@ -1,65 +1,71 @@ { - "name" : "sm", - "title_id" : "0x0100000000000004", - "main_thread_stack_size" : "0x1000", - "main_thread_priority" : 27, - "default_cpu_id" : 3, - "process_category" : 1, - "kernel_capabilities" : { - "handle_table_size" : 512, - "syscalls" : { - "svcSetHeapSize" : "0x01", - "svcSetMemoryPermission" : "0x02", - "svcSetMemoryAttribute" : "0x03", - "svcMapMemory" : "0x04", - "svcUnmapMemory" : "0x05", - "svcQueryMemory" : "0x06", - "svcExitProcess" : "0x07", - "svcCreateThread" : "0x08", - "svcStartThread" : "0x09", - "svcExitThread" : "0x0A", - "svcSleepThread" : "0x0B", - "svcGetThreadPriority" : "0x0C", - "svcSetThreadPriority" : "0x0D", - "svcGetThreadCoreMask" : "0x0E", - "svcSetThreadCoreMask" : "0x0F", - "svcGetCurrentProcessorNumber" : "0x10", - "svcSignalEvent" : "0x11", - "svcClearEvent" : "0x12", - "svcMapSharedMemory" : "0x13", - "svcUnmapSharedMemory" : "0x14", - "svcCreateTransferMemory" : "0x15", - "svcCloseHandle" : "0x16", - "svcResetSignal" : "0x17", - "svcWaitSynchronization" : "0x18", - "svcCancelSynchronization" : "0x19", - "svcArbitrateLock" : "0x1A", - "svcArbitrateUnlock" : "0x1B", - "svcWaitProcessWideKeyAtomic" : "0x1C", - "svcSignalProcessWideKey" : "0x1D", - "svcGetSystemTick" : "0x1E", - "svcConnectToNamedPort" : "0x1F", - "svcSendSyncRequestLight" : "0x20", - "svcSendSyncRequest" : "0x21", - "svcSendSyncRequestWithUserBuffer" : "0x22", - "svcSendAsyncRequestWithUserBuffer" : "0x23", - "svcGetProcessId" : "0x24", - "svcGetThreadId" : "0x25", - "svcBreak" : "0x26", - "svcOutputDebugString" : "0x27", - "svcReturnFromException" : "0x28", - "svcGetInfo" : "0x29", - "svcWaitForAddress" : "0x34", - "svcSignalToAddress" : "0x35", - "svcCreateSession" : "0x40", - "svcAcceptSession" : "0x41", - "svcReplyAndReceiveLight" : "0x42", - "svcReplyAndReceive" : "0x43", - "svcReplyAndReceiveWithUserBuffer" : "0x44", - "svcGetMemoryInfo" : "0x6F", - "svcCreatePort" : "0x70", - "svcManageNamedPort" : "0x71", - "svcConnectToPort" : "0x72" + "name": "sm", + "title_id": "0x0100000000000004", + "main_thread_stack_size": "0x1000", + "main_thread_priority": 27, + "default_cpu_id": 3, + "process_category": 1, + "kernel_capabilities": [ + { + "type": "handle_table_size", + "value": 512 + }, + { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0A", + "svcSleepThread": "0x0B", + "svcGetThreadPriority": "0x0C", + "svcSetThreadPriority": "0x0D", + "svcGetThreadCoreMask": "0x0E", + "svcSetThreadCoreMask": "0x0F", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1A", + "svcArbitrateUnlock": "0x1B", + "svcWaitProcessWideKeyAtomic": "0x1C", + "svcSignalProcessWideKey": "0x1D", + "svcGetSystemTick": "0x1E", + "svcConnectToNamedPort": "0x1F", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcGetMemoryInfo": "0x6F", + "svcCreatePort": "0x70", + "svcManageNamedPort": "0x71", + "svcConnectToPort": "0x72" + } } - } + ] } \ No newline at end of file From c7730d31ff3752750890ab8494c989f1bb3742a3 Mon Sep 17 00:00:00 2001 From: Pika <15848969+ThatNerdyPikachu@users.noreply.github.com> Date: Sat, 29 Sep 2018 18:48:06 -0400 Subject: [PATCH 102/489] fix thermo typo --- thermosphere/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thermosphere/src/main.c b/thermosphere/src/main.c index fed8e0f69..ea4a1219c 100644 --- a/thermosphere/src/main.c +++ b/thermosphere/src/main.c @@ -141,5 +141,5 @@ void main_el1(void * fdt) } // If we've made it here, we failed to boot, and we can't recover. - panic("We should launch Horizon, here!"); + panic("We should launch Horizon here!"); } From 3c1134e3d643699aedf86f6fbebd5772e2a650f2 Mon Sep 17 00:00:00 2001 From: CyberVision <joelc608@gmail.com> Date: Sun, 23 Sep 2018 18:53:32 -0500 Subject: [PATCH 103/489] Create Documentation/Wiki Various changes suggested by misson20000 --- docs/building.md | 6 +++ docs/components/exosphere.md | 10 +++++ docs/components/fusee/BCT.md | 26 +++++++++++++ docs/components/fusee/fusee.md | 20 ++++++++++ docs/components/stratosphere.md | 10 +++++ docs/components/thermosphere.md | 6 +++ docs/components/troposphere.md | 2 + docs/main.md | 26 +++++++++++++ docs/modules/boot.md | 2 + docs/modules/creport.md | 2 + docs/modules/fs_mitm.md | 2 + docs/modules/loader.md | 64 ++++++++++++++++++++++++++++++ docs/modules/pm.md | 23 +++++++++++ docs/modules/sm.md | 69 +++++++++++++++++++++++++++++++++ docs/roadmap.md | 19 +++++++++ 15 files changed, 287 insertions(+) create mode 100644 docs/building.md create mode 100644 docs/components/exosphere.md create mode 100644 docs/components/fusee/BCT.md create mode 100644 docs/components/fusee/fusee.md create mode 100644 docs/components/stratosphere.md create mode 100644 docs/components/thermosphere.md create mode 100644 docs/components/troposphere.md create mode 100644 docs/main.md create mode 100644 docs/modules/boot.md create mode 100644 docs/modules/creport.md create mode 100644 docs/modules/fs_mitm.md create mode 100644 docs/modules/loader.md create mode 100644 docs/modules/pm.md create mode 100644 docs/modules/sm.md create mode 100644 docs/roadmap.md diff --git a/docs/building.md b/docs/building.md new file mode 100644 index 000000000..47d230b8a --- /dev/null +++ b/docs/building.md @@ -0,0 +1,6 @@ +# Building Atmosphère +The process for building Atmosphère is similar to building Fusée Gelée payloads and other Switch apps. + +In order to build Atmosphère you must have devkitARM and devkitA64 installed on your computer. You can find instructions on how to install and setup devkitARM and devkitA64 on various OSes [here](https://devkitpro.org/wiki/Getting_Started). + +Once you have finished installing devkitARM and devkitA64, simply clone the Atmosphère repo, change to it and run `make`. diff --git a/docs/components/exosphere.md b/docs/components/exosphere.md new file mode 100644 index 000000000..b8a1103c8 --- /dev/null +++ b/docs/components/exosphere.md @@ -0,0 +1,10 @@ +# Exosphère +Exosphère is a reimplementation of Arm's TrustZone (TZ), also known as Secure Monitor (Secure_Monitor.bin). It has the highest privilege mode available on the Switch’s processor, and has access to everything on the console. + +Exosphère will potentially play a big role in Jamais Vu and Déja Vu, which are upcoming software exploits for the Switch, allowing one to launch Atmosphère on a Fusée-Gélee patched (ipatched) Switch console, and will also enable one to launch into CFW directly from the Switch itself without the use of any sort of external device, such as a computer or RCM jig, provided they are on a low enough system firmware. + +## TrustZone/Secure Monitor +TrustZone is responsible for all the cryptographic operations on the Switch. The idea behind the way it operates is that all the keys stay in the TrustZone, and userspace only gets "handles" to them. This would make sure that keydata never leaks and is kept secure. It also has a few more responsibilities, such as power management, providing a source of random numbers, and providing access to various pieces of information that are stored in the fuses. + +## Extensions +Exosphère currently only contains one extension, an SMC allowing homebrew to find which version of Atmosphère is currently running, in order to find out what extensions are allowed to be used. diff --git a/docs/components/fusee/BCT.md b/docs/components/fusee/BCT.md new file mode 100644 index 000000000..35c9f8246 --- /dev/null +++ b/docs/components/fusee/BCT.md @@ -0,0 +1,26 @@ +# BCT.ini +BCT.ini is the configuration file used by fusée-primary and fusée-secondary. It is read by fusee-primary.bin to setup and boot fusee-secondary.bin and is also read by fusee-secondary.bin to configure Exosphère or to specify the environment it should boot. + +## Configuration +This file is located at the root of your SD. +``` +BCT0 +[stage1] +stage2_path = fusee-secondary.bin +stage2_addr = 0xF0000000 +stage2_entrypoint = 0xF0000000 +``` +Add the following lines and replace the `X` according to the following list if you have trouble booting past the firmware version detection. +`target_firmware` is the OFW major version. +``` +[exosphere] +target_firmware = X +``` +``` +1.0.0 = 1 +2.X.X = 2 +3.X.X = 3 +4.X.X = 4 +5.X.X = 5 +6.0.0 = 6 +``` diff --git a/docs/components/fusee/fusee.md b/docs/components/fusee/fusee.md new file mode 100644 index 000000000..64c9575bd --- /dev/null +++ b/docs/components/fusee/fusee.md @@ -0,0 +1,20 @@ +# Fusée +Fusée (not to be confused with Fusée Gelée) is a custom bootloader needed to start Atmosphère and replaces Nintendo's Package1loader/bootloader. It currently utilizes the [Tegra X1 RCM Vulnerability](https://nvidia.custhelp.com/app/answers/detail/a_id/4660/~/security-notice%3A-nvidia-tegra-rcm-vulnerability) in order to function. + +Fusée is split into two separate parts: fusée-primary and fusée-secondary. This is due to the RCM Vulnerability only allowing payloads of a limited filesize to be sent to the device. + +As of June 2018, there are new Switch systems being sold that prevent Fusée (or any payload that requires the Fusée Gelée exploit) from working due to having an ipatched bootrom. All ipatched systems share the HAC-S-JXE-C3 product code. While Fusée cannot work on these ipatched units, they still come on firmware 4.1.0, which is vulnerable to the upcoming Déja Vu software exploit. Note that if you update past 4.1.0 on one of these ipatched units, your odds of being able to install Atmosphère or run any homebrew become practically non-existent. + +Additionally, a hardware revision of the Switch known as “Mariko†is believed to be in development. No such units have been seen in stores yet, but it is expected Nintendo will roll them out silently. The Mariko units will most likely patch the bootrom vulnerability Fusée Gelée, which is currently used to access CFW, and will likely have their own proprietary bootloader. + +## Fusée-Primary +Fusée-primary is the payload file (fusee-primary.bin) sent to the Switch from an external device. Once sent, fusée-primary makes initial preparations before loading fusée-secondary from the Switch’s SD Card. + +Fusée-primary can be configured via the [BCT.ini](../fusee/BCT.md) file located on the Switch’s SD card. + +## Fusée-Secondary +Fusée-secondary is a payload file that stays on the root of the Switch’s SD Card (fusee-secondary.bin). It is automatically launched once fusée-primary has finished, and is responsible for preparing the Switch’s hardware for future running environments, such as the homebrew menu. Fusée-secondary is also responsible for validating and launching Exosphère. + +Fusée-secondary contains various [.kip modules](/docs/main.md#modules). These modules modify existing features in the OS, and can also add new ones. + +Fusée is also capable of chainloading other payloads such as Linux. diff --git a/docs/components/stratosphere.md b/docs/components/stratosphere.md new file mode 100644 index 000000000..58813ab77 --- /dev/null +++ b/docs/components/stratosphere.md @@ -0,0 +1,10 @@ +# Stratosphère +Stratosphère allows customization of the Horizon OS and Switch kernel. It includes custom sysmodules that extend the kernel and provide new features. It also includes a reimplementation of the loader sysmodules to hook important system actions. + +The sysmodules that Stratosphère includes are: ++ [boot](../modules/boot.md): This module boots the system and initalizes hardware. ++ [creport](../modules/creport.md): Reimplementation of Nintendo’s crash report system. Dumps all error logs to the SD card instead of saving them to the NAND and sending them to Nintendo. ++ [fs_mitm](../modules/fs_mitm.md): This module can log, deny, delay, replace, and redirect any request made to the File System. ++ [loader](../modules/loader.md): Enables modifying the code of binaries that are not stored inside the kernel. ++ [pm](../modules/pm.md): Reimplementation of Nintendo’s Process Manager. ++ [sm](../modules/sm.md): Reimplementation of Nintendo’s Service Manager. diff --git a/docs/components/thermosphere.md b/docs/components/thermosphere.md new file mode 100644 index 000000000..c29483598 --- /dev/null +++ b/docs/components/thermosphere.md @@ -0,0 +1,6 @@ +# Thermosphère +Thermosphère is a hypervisor based implementation of emuNAND. An emuNAND is a copy of the firmware on the Switch’s internal memory (sysNAND), and is typically installed on an external SD Card. + +An emuNAND operates completely independently of the sysNAND. This allows one to make or test various modifications and homebrew safely without needing to restore their NAND backup afterwards by testing things on the emuNAND, and switching back to the sysNAND when finished. In the case of past Nintendo systems such as the 3DS, an emuNAND could also be used to update your system to the latest firmware while keeping your sysNAND on a lower version, however this may be more difficult to do on the Switch due to Nintendo using efuse technology for major system updates. + +Thermosphère is currently planned to be included in the 1.0 release of Atmosphère. diff --git a/docs/components/troposphere.md b/docs/components/troposphere.md new file mode 100644 index 000000000..2664843d8 --- /dev/null +++ b/docs/components/troposphere.md @@ -0,0 +1,2 @@ +# Troposphère +Troposphère contains various application-level modifications to the OS, such as launching homebrew directly from the homemenu or executing cheat/gameshark codes, similar to Luma3DS. Troposphère is not yet implemented in Atmosphère. diff --git a/docs/main.md b/docs/main.md new file mode 100644 index 000000000..5a6dfad1a --- /dev/null +++ b/docs/main.md @@ -0,0 +1,26 @@ +# Atmosphère +Atmosphère is a work-in-progress customized firmware for the Nintendo Switch. Atmosphère consists of several different components, each in charge of performing different system functions of the Nintendo Switch. + +The components of Atmosphère are: ++ [Fusée](../docs/components/fusee/fusee.md), a custom bootloader. ++ [Exosphère](../docs/components/exosphere.md), a fully-featured custom secure monitor. ++ [Stratosphère](../docs/components/stratosphere.md), a set of custom system modules. ++ [Thermosphère](../docs/components/thermosphere.md), a hypervisor-based emuNAND implementation. This component has not been implemented yet. ++ [Troposphère](../docs/components/troposphere.md), Application-level patches to the Horizon OS. This component has also not been implemented yet. + +### Modules +The Stratosphère component of Atmosphère contains various modules. These have a `.kip` extension. They provide custom features, extend existing features, or replace Nintendo sysmodules. + +Stratosphère's modules include: ++ [boot](../docs/modules/boot.md) ++ [creport](../docs/modules/creport.md) ++ [fs_mitm](../docs/modules/fs_mitm.md) ++ [loader](../docs/modules/loader.md) ++ [pm](../docs/modules/pm.md) ++ [sm](../docs/modules/sm.md) + +### Building Atmosphère +A guide to building Atmosphère can be found [here](../docs/building.md). + +### Release Roadmap +A roadmap of the releases of Atmosphère can be found [here](../docs/roadmap.md). diff --git a/docs/modules/boot.md b/docs/modules/boot.md new file mode 100644 index 000000000..53013b32c --- /dev/null +++ b/docs/modules/boot.md @@ -0,0 +1,2 @@ +# boot +The boot module is responsible for booting the system and initalizing hardware. A second boot module known as boot2 is integrated with the [pm (process manager)](../modules/pm.md) sysmodule in Atmosphère, and launches other processes. diff --git a/docs/modules/creport.md b/docs/modules/creport.md new file mode 100644 index 000000000..a6a996f43 --- /dev/null +++ b/docs/modules/creport.md @@ -0,0 +1,2 @@ +# creport +creport is a reimplementation of Nintendo's crash reporter. Atmosphère's creport catches all error logs that would have been saved to the NAND and instead saves them to the SD card for debugging purposes. This is helpful because the errors no longer go to Nintendo and developers of homebrew can still see the errors to help with the debugging process. creport catches system errors, game crashes, and homebrew crashes. diff --git a/docs/modules/fs_mitm.md b/docs/modules/fs_mitm.md new file mode 100644 index 000000000..345c42275 --- /dev/null +++ b/docs/modules/fs_mitm.md @@ -0,0 +1,2 @@ +# fs_mitm +fs_mitm is a sysmodule that enables intercepting file system operations. This module can log, deny, delay, replace, or redirect any request made to the filesystem. It enables LayeredFS to function, which allows for game mods. diff --git a/docs/modules/loader.md b/docs/modules/loader.md new file mode 100644 index 000000000..954873bb4 --- /dev/null +++ b/docs/modules/loader.md @@ -0,0 +1,64 @@ +# loader + +loader is a reimplementation of the loader sysmodule. This module is responsible for creating processes from executable NSO images and registering their access control with the kernel, sm, and fs. + +## Atmosphère Extensions + +Atmosphère extends this module to allow executables to be replaced or patched by files stored on the SD card. Note that a few services are required for SD card access and therefore cannot be replaced or patched in this manner. This includes psc, bus, and pcv. + +### Exefs Replacement + +TODO: details on buttons affecting this. + +When a process is created, loader will search for several NSO filenames in the title's exefs directory. +These filenames are, in this order: + + - rtld + - main + - subsdk0 + - subsdk1 + - ... + - subsdk9 + - sdk + +Each NSO that is found will be loaded into the process contiguously. The process's entrypoint is at the first NSO to be loaded, usually `rtld` or `main`. + +Additionally, when a process is loaded, loader will search for a `main.npdm` file in the exefs directory specifying the title's permissions. + +Atmosphère extends this functionality by also searching for these files on the SD card. When searching for a file, loader will first check if it exists on the SD card. If it does, that file will be used instead. Otherwise, it will use the copy located in the exefs, if that is present. The following directory will be searched. + +``` +sdmc:/atmosphere/titles/<title id>/exefs/ +``` + +This allows the replacement of applets, sysmodules, or even games with homebrew versions. + +In order to prevent an NSO from being loaded even if it exists in the exefs, loader will also check if a stub file exists. If such a file exists, the NSO will not be loaded. The files should be named like `rtld.stub`, `main.stub`, etc. and may be empty. + +### NSO Patching + +TODO: details on buttons affecting this. + +When an NSO is loaded, the stratosphere implementatin of loader will search for IPS patch files on the SD card in the following locations. +``` +sdmc:/atmosphere/exefs_patches/<patchset name>/<nso build id>.ips +``` +This organization allows patchsets affecting multiple NSOs to be distributed as a single directory. Patches will be searched for in each patchset directory. The name of each patch file should match the hexadecimal build ID of the NSO to affect, except that trailing zero bytes may be left off. Because the NSO build ID is unique for every NSO, this means patches will only apply to the files they are meant to apply to. + +Patch files are accepted in either IPS format or IPS32 format. + +Because NSO files are compressed, patch files are not made between the original version of a compressed NSO and the modified version of such an NSO. Instead, they are made between the uncompressed version of an NSO and the modified (and still uncompressed) version of that NSO. This also means that a patch file cannot be manually applied to the compressed version of an NSO; it must be applied to the uncompressed version. The Stratosphere implementation of loader will correctly apply these patches while loading the process regardless of whether the NSO it finds is compressed or not. + +When authoring patches, [hactool](https://github.com/SciresM/hactool) can be used to find an NSO's build ID and to uncompress NSOs. Recent versions of the [ReSwitched IDA loaders](https://github.com/reswitched/loaders) can be used to load uncompressed NSOs into IDA in such a way that you can [apply patches to the input file](https://www.hex-rays.com/products/ida/support/idadoc/1618.shtml). From there, any IPS tool can be used to create the patch between the original NSO and the patched NSO. Note that if the NSO you are patching is larger than 16 MiB, you will have to use a tool that supports IPS32. + +### HBL Support + +TODO + +### Button Overrides + +TODO + +### SM MITM Integration + +When the Stratosphere implementation of loader creates a new process, it notifies [sm](sm.md) through the `AtmosphereAssociatePidTidForMitm` command to notify any MITM services of new processes' identities. diff --git a/docs/modules/pm.md b/docs/modules/pm.md new file mode 100644 index 000000000..fe00ee18a --- /dev/null +++ b/docs/modules/pm.md @@ -0,0 +1,23 @@ +# pm + +pm is a reimplementation of Nintendo's process manager. This module is responsible for tracking running processes on the system, and managing resource limits. pm is also required to create and manage processes for homebrew applications. + +## Atmosphère Extensions + +There are a few ways in which the Stratosphere implementation of pm differs intentionally from the stock pm. + +### IPC: AtmosphereGetProcessHandle + +The Stratosphere implementation of pm adds an additional command to the [`pm:dmnt`](https://reswitched.github.io/SwIPC/ifaces.html#nn::pm::detail::IDebugMonitorInterface) interface, called `AtmosphereGetProcessHandle`. Its command ID is `65000` on all system firmware versions. It takes a `u64 process_id` and returns a process handle for the specified process, if that process is known. Notable exceptions include KIPs, which are not known to pm. If the specified process cannot be found, error code 0x20F is returned. + +The SwIPC definition for this command follows. +``` +interface nn::pm::detail::IDebugMonitorInterface is pm:dmnt { + ... + [65000] AtmosphereGetProcessHandle(u64 pid) -> handle<copy, process> process_handle; +} +``` + +### Extra System Memory for Sysmodules + +The Stratosphere implementation of pm shrinks the APPLET memory pool by 24 MiB by default, giving this memory to the SYSTEM pool. This allows custom sysmodules to use more memory without hitting the SYSTEM memory limit. diff --git a/docs/modules/sm.md b/docs/modules/sm.md new file mode 100644 index 000000000..8852975f8 --- /dev/null +++ b/docs/modules/sm.md @@ -0,0 +1,69 @@ +# sm + +sm is a reimplementation of Nintendo's service manager. It allows Atmosphère to add or remove process handle limits, add new services, or intercept service calls. This allows high-level intercepting of Horizon OS functionality. + +## Atmosphère Extensions + +There are a few ways in which the Stratosphere implementation of sm differs intentionally from the stock sm. + +### IPC: MITM Commands + +The Stratosphere implementation of sm adds a few additional commands to the [`sm:`](https://reswitched.github.io/SwIPC/ifaces.html#nn::sm::detail::IUserInterface) port session. + +Their SwIPC definitions follow. +``` +interface nn::sm::detail::IUserInterface is sm: { + ... + [65000] AtmosphereInstallMitm(ServiceName service) -> handle<port, move> service, handle<server_session, move> query; + [65001] AtmosphereUninstallMitm(ServiceName service); + [65002] AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid); +} +``` + +#### AtmosphereInstallMitm + +This command alters the registration for the named service, in order to allow services to intercept communication between client processes and their intended services. It is used by [fs_mitm](fs_mitm.md). + +It takes the name of the service to install an MITM for, and returns two handles. The first is a port handle, similar to those returned from the [RegisterService](https://reswitched.github.io/SwIPC/ifaces.html#nn::sm::detail::IUserInterface(2)) command. The second is the server side of a session, called the query session. This session will used by sm to determine whether or not a new session should be intercepted, and to inform the MITM service of the identity of new processes. + +The query session is expected to implement the following interface. +``` +interface MitmQueryService { + [65000] ShouldMitm(u64 pid) -> u64 should_mitm; + [65001] AssociatePidTid(u64 pid, u64 tid); +} +``` + +The `ShouldMitm` command is invoked whenever a process attempts to make a new connection to the MITM'd service. It should return `0` if the process's connection should not be intercepted. Any other value will cause the process's connection to be intercepted. If the command returns an error code, the process's connection will not be intercepted. + +The `AssociatePidTid` command is invoked on all MITM query sessions whenever a new process is created, in order to inform those services of the identity of a newly created process before it attempts to connect to any services. + +If the process that installed the MITM attempts to connect to the service, it will always connect to the original service. + +This command requires that the session be initialized, returning error code 0x415 if it is not. +If the given service name is invalid, error code 0xC15 is returned. +If the user does not have service registration permission for the named service, error code 0x1015 is returned. +If the service has not yet been registered, error code 0xE15 is returned. +If the service already has an MITM installed, error code 0x815 is returned. + +#### AtmosphereUninstallMitm + +Removes any installed MITM for the named service. + +This command requires that the session be initialized, returning error code 0x415 if it is not. + +#### AtmosphereAssociatePidTidForMitm + +This command is used internally by the Stratosphere implementation of the [loader](loader.md) sysmodule, when a new process is created. It will call the `AssociatePidTid` command on every registered MITM query session. + +If the given process ID refers to a kernel internal process, error code 0x1015 is returned. This command requires that the session be initialized, returning error code 0x415 if it is not. + +### Minimum Session Limit + +When a service is registered, the sysmodule registering it must specify a limit on the number of sessions that are allowed to be active for that service at a time. This is used to ensure that services like `fs-pr`, `fs-ldr`, and `ldr:pm` can only be connected to once, adding an additional layer of safety over the regular service verification to ensure that those services are only connected to by the highly priveleged process they are intended to be used by. + +By default, the Stratosphere implementation of PM will raise any session limits to at least 8, meaning that for services like `fs-pr` and those mentioned above, up to 8 processes will be able to connect to those sessions, leaving 7 sessions for homebrew to use. + +### Weak Service Verification + +In system firmware versions before 3.0.1, if a process did not call the [Initialize](https://reswitched.github.io/SwIPC/ifaces.html#nn::sm::detail::IUserInterface(0)) command on its `sm:` session, normally used to inform sm of the process's identity, sm would assume that the process was a kernel internal process and skip any service registration or access checks. The Stratosphere implementation of sm reimplements this vulnerability, allowing homebrew processes to skip service registration and access checks. diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 000000000..f7507928d --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,19 @@ +# Release Roadmap +## Upcoming Releases +### 0.7 +0.7 will be Atmosphère's first official release. +This release will include: ++ Fusée + + Supports loading/customizing of arbitrary KIPs from the SD card. + + Supports compile-time defined kernel patches on a per-firmware basis. + + Configurable by editing BCT.ini on the SD card. + + Atmosphère should also be launchable by the alternative hekate bootloader, for those who prefer it. ++ Exosphère + + Exosphere is a re-implementation of Nintendo's TrustZone firmware, fully replicating all of its features. + + In addition, it has been extended to provide information on current Atmosphere API version, for homebrew wishing to make use of it. ++ Stratosphère + + loader system module + + Service Manager system module (sm) + + Process Manager system module (pm) + + fs.mitm system module + + creport system module From 2d6aba7a707ac3807f80db22c973202931ce4780 Mon Sep 17 00:00:00 2001 From: misson20000 <xenotoad@xenotoad.net> Date: Thu, 4 Oct 2018 20:05:41 -0700 Subject: [PATCH 104/489] pm: add AtmosphereGetCurrentLimitInfo command to pm:dmnt --- stratosphere/pm/source/pm_debug_monitor.cpp | 31 +++++++++++++++++++ stratosphere/pm/source/pm_debug_monitor.hpp | 7 +++-- stratosphere/pm/source/pm_resource_limits.cpp | 4 +++ stratosphere/pm/source/pm_resource_limits.hpp | 1 + 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/stratosphere/pm/source/pm_debug_monitor.cpp b/stratosphere/pm/source/pm_debug_monitor.cpp index 95362c1ea..8555fc8dd 100644 --- a/stratosphere/pm/source/pm_debug_monitor.cpp +++ b/stratosphere/pm/source/pm_debug_monitor.cpp @@ -17,6 +17,7 @@ #include <switch.h> #include <stratosphere.hpp> #include "pm_registration.hpp" +#include "pm_resource_limits.hpp" #include "pm_debug_monitor.hpp" Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { @@ -49,6 +50,9 @@ Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 case Dmnt_Cmd_5X_AtmosphereGetProcessHandle: rc = WrapIpcCommandImpl<&DebugMonitorService::get_process_handle>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; + case Dmnt_Cmd_5X_AtmosphereGetCurrentLimitInfo: + rc = WrapIpcCommandImpl<&DebugMonitorService::get_current_limit_info>(this, r, out_c, pointer_buffer, pointer_buffer_size); + break; default: break; } @@ -78,6 +82,9 @@ Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 case Dmnt_Cmd_AtmosphereGetProcessHandle: rc = WrapIpcCommandImpl<&DebugMonitorService::get_process_handle>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; + case Dmnt_Cmd_AtmosphereGetCurrentLimitInfo: + rc = WrapIpcCommandImpl<&DebugMonitorService::get_current_limit_info>(this, r, out_c, pointer_buffer, pointer_buffer_size); + break; default: break; } @@ -158,3 +165,27 @@ std::tuple<Result, CopiedHandle> DebugMonitorService::get_process_handle(u64 pid } return {0, proc->handle}; } + +std::tuple<Result, u64, u64> DebugMonitorService::get_current_limit_info(u32 category, u32 resource) { + if(category > ResourceLimitUtils::ResourceLimitCategory::ResourceLimitCategory_Applet) { + return {0xf001, 0, 0}; + } + + Handle limit_h = ResourceLimitUtils::GetResourceLimitHandleByCategory((ResourceLimitUtils::ResourceLimitCategory) category); + + uint64_t current_value, limit_value; + + Result r; + + r = svcGetResourceLimitCurrentValue(¤t_value, limit_h, (LimitableResource) resource); + if(R_FAILED(r)) { + return {r, 0, 0}; + } + + r = svcGetResourceLimitLimitValue(&limit_value, limit_h, (LimitableResource) resource); + if(R_FAILED(r)) { + return {r, 0, 0}; + } + + return {0, current_value, limit_value}; +} diff --git a/stratosphere/pm/source/pm_debug_monitor.hpp b/stratosphere/pm/source/pm_debug_monitor.hpp index ee6c66b12..24c2d7839 100644 --- a/stratosphere/pm/source/pm_debug_monitor.hpp +++ b/stratosphere/pm/source/pm_debug_monitor.hpp @@ -29,7 +29,8 @@ enum DmntCmd { Dmnt_Cmd_GetApplicationProcessId = 5, Dmnt_Cmd_EnableDebugForApplication = 6, - Dmnt_Cmd_AtmosphereGetProcessHandle = 65000 + Dmnt_Cmd_AtmosphereGetProcessHandle = 65000, + Dmnt_Cmd_AtmosphereGetCurrentLimitInfo = 65001, }; enum DmntCmd_5X { @@ -42,7 +43,8 @@ enum DmntCmd_5X { Dmnt_Cmd_6X_DisableDebug = 6, - Dmnt_Cmd_5X_AtmosphereGetProcessHandle = 65000 + Dmnt_Cmd_5X_AtmosphereGetProcessHandle = 65000, + Dmnt_Cmd_5X_AtmosphereGetCurrentLimitInfo = 65001, }; class DebugMonitorService final : public IServiceObject { @@ -67,4 +69,5 @@ class DebugMonitorService final : public IServiceObject { /* Atmosphere commands. */ std::tuple<Result, CopiedHandle> get_process_handle(u64 pid); + std::tuple<Result, u64, u64> get_current_limit_info(u32 category, u32 resource); }; diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index 97c699221..e0d729075 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -224,6 +224,10 @@ Handle ResourceLimitUtils::GetResourceLimitHandle(u16 application_type) { } } +Handle ResourceLimitUtils::GetResourceLimitHandleByCategory(ResourceLimitCategory category) { + return g_resource_limit_handles[category]; +} + Result ResourceLimitUtils::BoostSystemMemoryResourceLimit(u64 boost_size) { Result rc = 0; if (boost_size > g_memory_resource_limits[g_memory_limit_type][ResourceLimitCategory_Application]) { diff --git a/stratosphere/pm/source/pm_resource_limits.hpp b/stratosphere/pm/source/pm_resource_limits.hpp index 36d46fcd0..c06706e02 100644 --- a/stratosphere/pm/source/pm_resource_limits.hpp +++ b/stratosphere/pm/source/pm_resource_limits.hpp @@ -28,5 +28,6 @@ class ResourceLimitUtils { static void InitializeLimits(); static void EnsureApplicationResourcesAvailable(); static Handle GetResourceLimitHandle(u16 application_type); + static Handle GetResourceLimitHandleByCategory(ResourceLimitCategory category); static Result BoostSystemMemoryResourceLimit(u64 boost_size); }; \ No newline at end of file From 20faa7f00bb54a3c708e6b303d5d78ef4ee6bdcc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 5 Oct 2018 09:13:00 -0700 Subject: [PATCH 105/489] Loader: fix automatic apptype patching. --- stratosphere/loader/source/ldr_npdm.cpp | 13 ++++++++++++- stratosphere/loader/source/ldr_npdm.hpp | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index 2bb9eb669..8d7eb0f37 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -190,7 +190,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { info->acid->flags = (info->acid->flags & 0xFFFFFFC3) | (original_info->acid->flags & 0x0000003C); } /* Fix application type. */ - const u32 original_application_type = GetApplicationType((u32 *)original_info->aci0_kac, original_info->aci0->kac_size/sizeof(u32)) & 7; + const u32 original_application_type = GetApplicationTypeRaw((u32 *)original_info->aci0_kac, original_info->aci0->kac_size/sizeof(u32)) & 7; u32 *caps = (u32 *)info->aci0_kac; for (unsigned int i = 0; i < info->aci0->kac_size/sizeof(u32); i++) { if ((caps[i] & 0x3FFF) == 0x1FFF) { @@ -489,4 +489,15 @@ u32 NpdmUtils::GetApplicationType(u32 *caps, size_t num_caps) { } } return application_type; +} + +/* Like GetApplicationType, except this returns the raw kac descriptor value. */ +u32 NpdmUtils::GetApplicationTypeRaw(u32 *caps, size_t num_caps) { + u32 application_type = 0; + for (unsigned int i = 0; i < num_caps; i++) { + if ((caps[i] & 0x3FFF) == 0x1FFF) { + return (caps[i] >> 14) & 7; + } + } + return application_type; } \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_npdm.hpp b/stratosphere/loader/source/ldr_npdm.hpp index 3a7e721ee..b04606046 100644 --- a/stratosphere/loader/source/ldr_npdm.hpp +++ b/stratosphere/loader/source/ldr_npdm.hpp @@ -96,6 +96,7 @@ class NpdmUtils { static_assert(sizeof(NpdmAci0) == 0x40, "Incorrectly defined NpdmAci0!"); static u32 GetApplicationType(u32 *caps, size_t num_caps); + static u32 GetApplicationTypeRaw(u32 *caps, size_t num_caps); static Result ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size_t num_restrict_caps, u32 *&cur_cap, size_t &caps_remaining); static Result ValidateCapabilities(u32 *acid_caps, size_t num_acid_caps, u32 *aci0_caps, size_t num_aci0_caps); From 9ae62a27ddeb917c2e8591987cab00d7bfd81fb4 Mon Sep 17 00:00:00 2001 From: Pika <15848969+ThatNerdyPikachu@users.noreply.github.com> Date: Fri, 5 Oct 2018 17:46:04 -0400 Subject: [PATCH 106/489] Fix ProcesState enum field names --- stratosphere/pm/source/pm_registration.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index 4e3c8cfff..7db40e156 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -151,7 +151,7 @@ void Registration::HandleProcessLaunch() { rc = svcStartProcess(new_process.handle, program_info.main_thread_priority, program_info.default_cpu_id, program_info.main_thread_stack_size); if (R_SUCCEEDED(rc)) { - SetProcessState(new_process.pid, ProcessState_DebugDetached); + SetProcessState(new_process.pid, ProcessState_Running); } } @@ -195,7 +195,7 @@ Result Registration::LaunchDebugProcess(u64 pid) { return 0x20F; } - if (proc->state >= ProcessState_DebugDetached) { + if (proc->state >= ProcessState_Running) { return 0x40F; } @@ -205,7 +205,7 @@ Result Registration::LaunchDebugProcess(u64 pid) { } if (R_SUCCEEDED((rc = svcStartProcess(proc->handle, program_info.main_thread_priority, program_info.default_cpu_id, program_info.main_thread_stack_size)))) { - proc->state = ProcessState_DebugDetached; + proc->state = ProcessState_Running; } return rc; @@ -246,10 +246,10 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process } switch (process->state) { case ProcessState_Created: - case ProcessState_DebugAttached: + case ProcessState_CreatedAttached: case ProcessState_Exiting: break; - case ProcessState_DebugDetached: + case ProcessState_Running: if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) { process->flags &= ~(PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED); process->flags |= PROCESSFLAGS_DEBUGEVENTPENDING; @@ -264,7 +264,7 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process process->flags |= (PROCESSFLAGS_CRASHED | PROCESSFLAGS_CRASH_DEBUG); g_process_event->signal_event(); break; - case ProcessState_Running: + case ProcessState_RunningAttached: if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) { process->flags &= ~(PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED); process->flags |= PROCESSFLAGS_DEBUGEVENTPENDING; @@ -419,7 +419,7 @@ void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) { auto auto_lock = GetProcessListUniqueLock(); for (auto &p : g_process_list.processes) { - if (kernelAbove200() && p->state >= ProcessState_DebugDetached && p->flags & PROCESSFLAGS_DEBUGDETACHED) { + if (kernelAbove200() && p->state >= ProcessState_Running && p->flags & PROCESSFLAGS_DEBUGDETACHED) { p->flags &= ~PROCESSFLAGS_DEBUGDETACHED; *out_pid = p->pid; *out_type = kernelAbove500() ? PROCESSEVENTTYPE_500_DEBUGDETACHED : PROCESSEVENTTYPE_DEBUGDETACHED; From f603dbfc98245b941aa09bf09c99fb835b3cef65 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 13:33:45 -0700 Subject: [PATCH 107/489] fs.mitm: Add domain support (closes #202) --- stratosphere/fs_mitm/source/fs_shim.c | 160 +++--------------- stratosphere/fs_mitm/source/fs_shim.h | 7 +- .../fs_mitm/source/fsmitm_service.cpp | 31 ++-- stratosphere/fs_mitm/source/mitm_session.hpp | 22 +-- .../include/stratosphere/ipc_templating.hpp | 14 +- .../include/stratosphere/isession.hpp | 10 +- 6 files changed, 66 insertions(+), 178 deletions(-) diff --git a/stratosphere/fs_mitm/source/fs_shim.c b/stratosphere/fs_mitm/source/fs_shim.c index 0c510dbba..134d83498 100644 --- a/stratosphere/fs_mitm/source/fs_shim.c +++ b/stratosphere/fs_mitm/source/fs_shim.c @@ -17,47 +17,6 @@ #include <switch.h> #include "fs_shim.h" -/* Necessary evil. */ -Result ipcCopyFromDomain(Handle session, u32 object_id, Service *out) { - u32* buf = (u32*)armGetTls(); - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 object_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - buf[0] = IpcCommandType_Control; - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->object_id = object_id; - - Result rc = ipcDispatch(session); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct ipcCopyFromDomainResponse { - u64 magic; - u64 result; - } *raw = (struct ipcCopyFromDomainResponse*)r.Raw; - - rc = raw->result; - - if (R_SUCCEEDED(rc)) { - serviceCreate(out, r.Handles[0]); - } - } - - return rc; -} - - /* Missing fsp-srv commands. */ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) { IpcCommand c; @@ -68,7 +27,7 @@ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) { u64 cmd_id; } *raw; - raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 200; @@ -77,60 +36,25 @@ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) { if (R_SUCCEEDED(rc)) { IpcParsedCommand r; - ipcParse(&r); - struct { u64 magic; u64 result; - } *resp = r.Raw; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; rc = resp->result; if (R_SUCCEEDED(rc)) { - serviceCreate(&out->s, r.Handles[0]); + serviceCreateSubservice(&out->s, s, &r, 0); } } return rc; } -Result fsOpenDataStorageByCurrentProcessFromDomainFwd(Service* s, u32 *out_object_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), s->object_id); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 200; - - Result rc = serviceIpcDispatch(s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParseForDomain(&r); - - struct { - u64 magic; - u64 result; - u32 object_id; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out_object_id = resp->object_id; - } - } - - return rc; -} - -Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out) { +Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out) { IpcCommand c; ipcInitialize(&c); @@ -141,7 +65,7 @@ Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id u64 data_id; } *raw; - raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 202; @@ -152,58 +76,18 @@ Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id if (R_SUCCEEDED(rc)) { IpcParsedCommand r; - ipcParse(&r); - struct { u64 magic; u64 result; - } *resp = r.Raw; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; rc = resp->result; if (R_SUCCEEDED(rc)) { - serviceCreate(&out->s, r.Handles[0]); - } - } - - return rc; -} - - -Result fsOpenDataStorageByDataIdFromDomain(Service* s, FsStorageId storage_id, u64 data_id, u32 *out_object_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - FsStorageId storage_id; - u64 data_id; - } *raw; - - raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), s->object_id); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 202; - raw->storage_id = storage_id; - raw->data_id = data_id; - - Result rc = serviceIpcDispatch(s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParseForDomain(&r); - - struct { - u64 magic; - u64 result; - u32 object_id; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out_object_id = resp->object_id; + serviceCreateSubservice(&out->s, s, &r, 0); } } @@ -223,7 +107,7 @@ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *o u64 len; } *raw; - raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 5; @@ -235,13 +119,14 @@ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *o if (R_SUCCEEDED(rc)) { IpcParsedCommand r; - ipcParse(&r); - struct { u64 magic; u64 result; FsRangeInfo range_info; - } *resp = r.Raw; + } *resp; + + serviceIpcParse(&f->s, &r, sizeof(*resp)); + resp = r.Raw; rc = resp->result; if (R_SUCCEEDED(rc) && out) *out = resp->range_info; @@ -263,7 +148,7 @@ Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeI u64 len; } *raw; - raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 5; @@ -275,13 +160,14 @@ Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeI if (R_SUCCEEDED(rc)) { IpcParsedCommand r; - ipcParse(&r); - struct { u64 magic; u64 result; FsRangeInfo range_info; - } *resp = r.Raw; + } *resp; + + serviceIpcParse(&s->s, &r, sizeof(*resp)); + resp = r.Raw; rc = resp->result; if (R_SUCCEEDED(rc) && out) *out = resp->range_info; diff --git a/stratosphere/fs_mitm/source/fs_shim.h b/stratosphere/fs_mitm/source/fs_shim.h index 9030078e7..d73c2595b 100644 --- a/stratosphere/fs_mitm/source/fs_shim.h +++ b/stratosphere/fs_mitm/source/fs_shim.h @@ -16,14 +16,9 @@ typedef struct { u32 flags[0x40/sizeof(u32)]; } FsRangeInfo; -/* Necessary evils. */ -Result ipcCopyFromDomain(Handle session, u32 object_id, Service *out); - /* Missing fsp-srv commands. */ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out); -Result fsOpenDataStorageByCurrentProcessFromDomainFwd(Service* s, u32 *out_object_id); -Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out); -Result fsOpenDataStorageByDataIdFromDomain(Service* s, FsStorageId storage_id, u64 data_id, u32 *out_object_id); +Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out); /* Missing FS File commands. */ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out); diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 07f5c3156..d139cc328 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -91,7 +91,11 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora Result rc; if (this->romfs_storage != nullptr) { if (this->get_owner() != NULL) { - rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id); + FsStorage s = {0}; + rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &s); + if (R_SUCCEEDED(rc)) { + out_domain_id = s.s.object_id; + } } else { rc = 0; } @@ -102,15 +106,9 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora } else { FsStorage data_storage; FsFile data_file; + + rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage); - if (this->get_owner() == NULL) { - rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage); - } else { - rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id); - if (R_SUCCEEDED(rc)) { - rc = ipcCopyFromDomain(this->forward_service->handle, out_domain_id, &data_storage.s); - } - } Log(armGetTls(), 0x100); if (R_SUCCEEDED(rc)) { /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ @@ -123,6 +121,8 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora out_session = new IPCSession<IStorageInterface>(out_storage); if (this->get_owner() == NULL) { FsMitMWorker::AddWaitable(out_session); + } else { + out_domain_id = data_storage.s.object_id; } } } @@ -140,14 +140,9 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora FsFile data_file; u32 out_domain_id = 0; Result rc; - if (this->get_owner() == NULL) { - rc = fsOpenDataStorageByDataId(this->forward_service, storage_id, data_id, &data_storage); - } else { - rc = fsOpenDataStorageByDataIdFromDomain(this->forward_service, storage_id, data_id, &out_domain_id); - if (R_SUCCEEDED(rc)) { - rc = ipcCopyFromDomain(this->forward_service->handle, out_domain_id, &data_storage.s); - } - } + + rc = fsOpenDataStorageByDataIdFwd(this->forward_service, storage_id, data_id, &data_storage); + if (R_SUCCEEDED(rc)) { /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) { @@ -157,6 +152,8 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora } if (this->get_owner() == NULL) { FsMitMWorker::AddWaitable(out_session); + } else { + out_domain_id = data_storage.s.object_id; } } diff --git a/stratosphere/fs_mitm/source/mitm_session.hpp b/stratosphere/fs_mitm/source/mitm_session.hpp index 0d535b529..c49915e69 100644 --- a/stratosphere/fs_mitm/source/mitm_session.hpp +++ b/stratosphere/fs_mitm/source/mitm_session.hpp @@ -87,20 +87,20 @@ class MitMSession final : public ISession<T> { if (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext) { std::shared_ptr<IServiceObject> obj; - if (r.IsDomainMessage) { - obj = this->domain->get_domain_object(r.ThisObjectId); - if (obj != nullptr && r.MessageType == DomainMessageType_Close) { - if (r.ThisObjectId == this->mitm_domain_id) { + if (r.IsDomainRequest) { + obj = this->domain->get_domain_object(r.InThisObjectId); + if (obj != nullptr && r.InMessageType == DomainMessageType_Close) { + if (r.InThisObjectId == this->mitm_domain_id) { Reboot(); } - this->domain->delete_object(r.ThisObjectId); + this->domain->delete_object(r.InThisObjectId); struct { u64 magic; u64 result; } *o_resp; o_resp = (decltype(o_resp)) ipcPrepareHeaderForDomain(&c, sizeof(*o_resp), 0); - *(DomainMessageHeader *)((uintptr_t)o_resp - sizeof(DomainMessageHeader)) = {0}; + *(DomainResponseHeader *)((uintptr_t)o_resp - sizeof(DomainResponseHeader)) = {0}; o_resp->magic = SFCO_MAGIC; o_resp->result = 0x0; Log(armGetTls(), 0x100); @@ -112,8 +112,9 @@ class MitMSession final : public ISession<T> { if (obj != nullptr) { retval = obj->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size()); if (R_SUCCEEDED(retval)) { - if (r.IsDomainMessage) { - ipcParseForDomain(&cur_out_r); + if (r.IsDomainRequest) { + /* We never work with out object ids, so this should be fine. */ + ipcParseDomainResponse(&cur_out_r, 0); } else { ipcParse(&cur_out_r); } @@ -182,8 +183,9 @@ class MitMSession final : public ISession<T> { Log(armGetTls(), 0x100); retval = serviceIpcDispatch(&forward_service); if (R_SUCCEEDED(retval)) { - if (r.IsDomainMessage) { - ipcParseForDomain(&cur_out_r); + if (r.IsDomainRequest) { + /* We never work with out object ids, so this should be fine. */ + ipcParseDomainResponse(&cur_out_r, 0); } else { ipcParse(&cur_out_r); } diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp index 7f9c2c89e..d37857ae8 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp @@ -459,7 +459,9 @@ struct Encoder<std::tuple<Args...>> { raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value - sizeof(Result)); } else { raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value + (num_out_sessions_in_arguments<Args... >::value * sizeof(u32)) - sizeof(Result), 0); - *((DomainMessageHeader *)((uintptr_t)raw - sizeof(DomainMessageHeader))) = {0}; + auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); + *resp_header = {0}; + resp_header->NumObjectIds = num_out_sessions_in_arguments<Args... >::value; } @@ -474,7 +476,13 @@ struct Encoder<std::tuple<Args...>> { if (R_FAILED(rc)) { std::fill(tls, tls + 0x100, 0x00); ipcInitialize(&out_command); - raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(raw)); + if (domain_owner != NULL) { + raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(raw), 0); + auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); + *resp_header = {0}; + } else { + raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(raw)); + } raw->magic = SFCO_MAGIC; raw->result = rc; } @@ -526,7 +534,7 @@ Result WrapIpcCommandImpl(Class *this_ptr, IpcParsedCommand& r, IpcCommand &out_ auto args = Decoder<OutArgs, InArgsWithoutThis>::Decode(r, out_command, pointer_buffer); auto result = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args); DomainOwner *down = NULL; - if (r.IsDomainMessage) { + if (r.IsDomainRequest) { down = this_ptr->get_owner(); } diff --git a/stratosphere/libstratosphere/include/stratosphere/isession.hpp b/stratosphere/libstratosphere/include/stratosphere/isession.hpp index 842dfd412..95156a2d0 100644 --- a/stratosphere/libstratosphere/include/stratosphere/isession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/isession.hpp @@ -118,12 +118,12 @@ class ISession : public IWaitable { IpcCommand c; ipcInitialize(&c); - if (r.IsDomainMessage && this->active_object == NULL) { + if (r.IsDomainRequest && this->active_object == NULL) { return 0xF601; } - if (r.IsDomainMessage && r.MessageType == DomainMessageType_Close) { + if (r.IsDomainRequest && r.InMessageType == DomainMessageType_Close) { this->domain->delete_object(this->active_object); this->active_object = NULL; struct { @@ -198,11 +198,11 @@ class ISession : public IWaitable { Result retval = ipcParse(&r); if (R_SUCCEEDED(retval)) { if (this->is_domain && (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext)) { - retval = ipcParseForDomain(&r); - if (!r.IsDomainMessage || r.ThisObjectId >= DOMAIN_ID_MAX) { + retval = ipcParseDomainRequest(&r); + if (!r.IsDomainRequest || r.InThisObjectId >= DOMAIN_ID_MAX) { retval = 0xF601; } else { - this->active_object = this->domain->get_domain_object(r.ThisObjectId); + this->active_object = this->domain->get_domain_object(r.InThisObjectId); } } else { this->active_object = this->service_object; From 11159f5fa99e768f71b6649666a916b34d00814a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 14:10:00 -0700 Subject: [PATCH 108/489] exosphere: Add package2 support for 6.0.0 --- exosphere/src/package2.c | 4 ++-- exosphere/src/package2.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 6e1620bc1..aeafd88d3 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -304,7 +304,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) { /* Perform version checks. */ /* We will be compatible with all package2s released before current, but not newer ones. */ - if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_500_CURRENT) { + if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_600_CURRENT) { return true; } @@ -331,7 +331,7 @@ static uint32_t decrypt_and_validate_header(package2_header_t *header) { } /* Ensure we successfully decrypted the header. */ - if (mkey_rev > mkey_get_revision()) { + if (mkey_rev > mkey_get_revision()) { panic(0xFAF00003); } } else if (!validate_package2_metadata(&header->metadata)) { diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h index ec0dfba3e..9553fa8fe 100644 --- a/exosphere/src/package2.h +++ b/exosphere/src/package2.h @@ -66,14 +66,16 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) { #define PACKAGE2_MAXVER_300 0x4 #define PACKAGE2_MAXVER_302 0x5 #define PACKAGE2_MAXVER_400_410 0x6 -#define PACKAGE2_MAXVER_500_CURRENT 0x7 +#define PACKAGE2_MAXVER_500_510 0x7 +#define PACKAGE2_MAXVER_600_CURRENT 0x8 #define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_200 0x4 #define PACKAGE2_MINVER_300 0x5 #define PACKAGE2_MINVER_302 0x6 #define PACKAGE2_MINVER_400_410 0x7 -#define PACKAGE2_MINVER_500_CURRENT 0x8 +#define PACKAGE2_MINVER_500_510 0x8 +#define PACKAGE2_MINVER_600_CURRENT 0x9 typedef struct { union { From 49f627bb28103830d8682fda8b46542ba6e06abd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 14:19:55 -0700 Subject: [PATCH 109/489] fusee: Load fs.mitm by default. --- fusee/fusee-secondary/Makefile | 4 ++-- fusee/fusee-secondary/src/main.c | 4 ++-- fusee/fusee-secondary/src/nxboot.c | 4 +++- fusee/fusee-secondary/src/stratosphere.c | 15 +++++++++++++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 55377889f..d902d588b 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -69,7 +69,7 @@ ifneq ($(BUILD),$(notdir $(CURDIR))) export OUTPUT := $(CURDIR)/$(TARGET) export TOPDIR := $(CURDIR) -export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot +export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/fs_mitm export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ $(AMS)/exosphere $(AMS)/thermosphere $(KIPDIRS) @@ -79,7 +79,7 @@ export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -KIPFILES := loader.kip pm.kip sm.kip boot_100.kip boot_200.kip +KIPFILES := loader.kip pm.kip sm.kip fs_mitm.kip boot_100.kip boot_200.kip BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) exosphere.bin thermosphere.bin splash_screen.bmp $(KIPFILES) #--------------------------------------------------------------------------------- diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index d10e6e7cb..753efc0aa 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -101,13 +101,13 @@ int main(int argc, void **argv) { g_do_nxboot = loader_ctx->chainload_entrypoint == 0; if (g_do_nxboot) { - print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n"); + print(SCREEN_LOG_LEVEL_MANDATORY, "Now performing nxboot.\n"); uint32_t boot_memaddr = nxboot_main(); nxboot_finish(boot_memaddr); } else { /* TODO: What else do we want to do in terms of argc/argv? */ const char *path = get_loader_ctx()->file_paths_to_load[get_loader_ctx()->file_id_of_entrypoint]; - print(SCREEN_LOG_LEVEL_INFO, "Now chainloading.\n"); + print(SCREEN_LOG_LEVEL_MANDATORY, "Now chainloading.\n"); g_chainloader_argc = 1; strcpy(g_chainloader_arg_data, path); } diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 83fb6ca3a..9b9c73ed2 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -292,6 +292,8 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); else print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware); + + print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); /* Setup boot configuration for Exosphère. */ nxboot_configure_exosphere(target_firmware); @@ -357,7 +359,7 @@ uint32_t nxboot_main(void) { pmc->scratch1 = (uint32_t)warmboot_memaddr; } - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Rebuilding package2...\n"); + print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Rebuilding package2...\n"); /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index 22d058b92..2223a2247 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -38,12 +38,13 @@ static ini1_header_t *g_stratosphere_ini1 = NULL; static bool g_stratosphere_loader_enabled = true; static bool g_stratosphere_sm_enabled = true; static bool g_stratosphere_pm_enabled = true; +static bool g_stratosphere_fs_mitm_enabled = true; static bool g_stratosphere_boot_enabled = false; extern const uint8_t boot_100_kip[], boot_200_kip[]; -extern const uint8_t loader_kip[], pm_kip[], sm_kip[]; +extern const uint8_t loader_kip[], pm_kip[], sm_kip[], fs_mitm_kip[]; extern const uint32_t boot_100_kip_size, boot_200_kip_size; -extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size; +extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, fs_mitm_kip_size; /* GCC doesn't consider the size as const... we have to write it ourselves. */ @@ -83,6 +84,11 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { num_processes++; } + if (g_stratosphere_fs_mitm_enabled) { + size += fs_mitm_kip_size; + num_processes++; + } + if (g_stratosphere_boot_enabled) { size += boot_kip_size; num_processes++; @@ -117,6 +123,11 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { data += sm_kip_size; } + if (g_stratosphere_fs_mitm_enabled) { + memcpy(data, fs_mitm_kip, fs_mitm_kip_size); + data += fs_mitm_kip_size; + } + if (g_stratosphere_boot_enabled) { memcpy(data, boot_kip, boot_kip_size); data += boot_kip_size; From bfa5847e4852e1cb594110d4776345e9655fdcd0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 15:08:06 -0700 Subject: [PATCH 110/489] fusee: Greatly simplify and improve KIP loading --- fusee/fusee-secondary/src/package2.c | 1 + fusee/fusee-secondary/src/stratosphere.c | 141 ++++++++++++++++++----- fusee/fusee-secondary/src/stratosphere.h | 8 +- 3 files changed, 116 insertions(+), 34 deletions(-) diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 50eada5f8..f5ac7041d 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -283,6 +283,7 @@ static ini1_header_t *package2_rebuild_ini1(ini1_header_t *ini1, uint32_t target ini1_header_t *inis_to_merge[STRATOSPHERE_INI1_MAX] = {0}; ini1_header_t *merged; + inis_to_merge[STRATOSPHERE_INI1_SDFILES] = stratosphere_get_sd_files_ini1(); inis_to_merge[STRATOSPHERE_INI1_EMBEDDED] = stratosphere_get_ini1(target_firmware); inis_to_merge[STRATOSPHERE_INI1_PACKAGE2] = ini1; diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index 2223a2247..a90a966c8 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -17,11 +17,13 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <dirent.h> #include "exocfg.h" #include "utils.h" #include "package2.h" #include "stratosphere.h" #include "fs_utils.h" +#include "lib/log.h" #define u8 uint8_t #define u32 uint32_t @@ -34,6 +36,7 @@ #undef u32 static ini1_header_t *g_stratosphere_ini1 = NULL; +static ini1_header_t *g_sd_files_ini1 = NULL; static bool g_stratosphere_loader_enabled = true; static bool g_stratosphere_sm_enabled = true; @@ -137,13 +140,111 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { } void stratosphere_free_ini1(void) { - free(g_stratosphere_ini1); - g_stratosphere_ini1 = NULL; + if (g_stratosphere_ini1 != NULL) { + free(g_stratosphere_ini1); + g_stratosphere_ini1 = NULL; + } + if (g_sd_files_ini1 != NULL) { + free(g_sd_files_ini1); + g_sd_files_ini1 = NULL; + } +} + + + +static void try_add_sd_kip(ini1_header_t *ini1, const char *kip_path) { + size_t file_size = get_file_size(kip_path); + + if (ini1->size + file_size > PACKAGE2_SIZE_MAX) { + fatal_error("Failed to load %s: INI1 would be too large!\n", kip_path); + } + + kip1_header_t kip_header; + if (read_from_file(&kip_header, sizeof(kip_header), kip_path) != sizeof(kip_header) || kip_header.magic != MAGIC_KIP1) { + return; + } + + size_t kip_size = kip1_get_size_from_header(&kip_header); + if (kip_size > file_size) { + fatal_error("Failed to load %s: KIP size is corrupt!\n", kip_path); + } + + if (read_from_file(ini1->kip_data + ini1->size - sizeof(ini1_header_t), kip_size, kip_path) != kip_size) { + /* TODO: is this error fatal? */ + return; + } + + ini1->size += kip_size; + ini1->num_processes++; +} + +ini1_header_t *stratosphere_get_sd_files_ini1(void) { + if (g_sd_files_ini1 != NULL) { + return g_sd_files_ini1; + } + + /* Allocate space. */ + g_sd_files_ini1 = (ini1_header_t *)malloc(PACKAGE2_SIZE_MAX); + g_sd_files_ini1->magic = MAGIC_INI1; + g_sd_files_ini1->size = sizeof(ini1_header_t); + g_sd_files_ini1->num_processes = 0; + g_sd_files_ini1->_0xC = 0; + + /* Load all kips from /atmosphere/kips/<*>.kip or /atmosphere/kips/<*>/<*>.kip. */ + DIR *kips_dir = opendir("atmosphere/kips"); + struct dirent *ent; + if (kips_dir != NULL) { + while ((ent = readdir(kips_dir)) != NULL) { + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { + continue; + } + + char kip_path[0x301] = {0}; + snprintf(kip_path, 0x300, "atmosphere/kips/%s", ent->d_name); + + struct stat kip_stat; + if (stat(kip_path, &kip_stat) == -1) { + continue; + } + + if ((kip_stat.st_mode & S_IFMT) == S_IFREG) { + /* If file, add to ini1. */ + try_add_sd_kip(g_sd_files_ini1, kip_path); + } else if ((kip_stat.st_mode & S_IFMT) == S_IFDIR) { + /* Otherwise, allow one level of nesting. */ + DIR *sub_dir = opendir(kip_path); + struct dirent *sub_ent; + if (sub_dir != NULL) { + while ((sub_ent = readdir(sub_dir)) != NULL) { + if (strcmp(sub_ent->d_name, ".") == 0 || strcmp(sub_ent->d_name, "..") == 0) { + continue; + } + + /* Reuse kip path variable. */ + memset(kip_path, 0, sizeof(kip_path)); + snprintf(kip_path, 0x300, "atmosphere/kips/%s/%s", ent->d_name, sub_ent->d_name); + + if (stat(kip_path, &kip_stat) == -1) { + continue; + } + + if ((kip_stat.st_mode & S_IFMT) == S_IFREG) { + /* If file, add to ini1. */ + try_add_sd_kip(g_sd_files_ini1, kip_path); + } + } + closedir(sub_dir); + } + } + } + closedir(kips_dir); + } + + return g_sd_files_ini1; } /* Merges some number of INI1s into a single INI1. It's assumed that the INIs are in order of preference. */ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { - char sd_path[0x100] = {0}; uint32_t total_num_processes = 0; /* Validate all ini headers. */ @@ -170,7 +271,6 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { merged->num_processes = 0; merged->_0xC = 0; size_t remaining_size = PACKAGE2_SIZE_MAX - sizeof(ini1_header_t); - size_t read_size; unsigned char *current_dst_kip = merged->kip_data; @@ -196,34 +296,13 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { continue; } - /* TODO: What folder should these be read out of? */ - snprintf(sd_path, sizeof(sd_path), "atmosphere/titles/%016llX/%016llX.kip", current_kip->title_id, current_kip->title_id); - - /* Try to load an override KIP from SD, if possible. */ - read_size = read_from_file(current_dst_kip, remaining_size, sd_path); - if (read_size != 0) { - kip1_header_t *sd_kip = (kip1_header_t *)(current_dst_kip); - if (read_size < sizeof(kip1_header_t) || sd_kip->magic != MAGIC_KIP1) { - fatal_error("%s is not a KIP1?\n", sd_path); - } else if (sd_kip->title_id != current_kip->title_id) { - fatal_error("%s has wrong Title ID!\n", sd_path); - } - size_t expected_sd_kip_size = kip1_get_size_from_header(sd_kip); - if (expected_sd_kip_size != read_size) { - fatal_error("%s has wrong size or there is not enough space (expected 0x%zx, read 0x%zx)!\n", - sd_path, expected_sd_kip_size, read_size); - } - remaining_size -= expected_sd_kip_size; - current_dst_kip += expected_sd_kip_size; - } else { - size_t current_kip_size = kip1_get_size_from_header(current_kip); - if (current_kip_size > remaining_size) { - fatal_error("Not enough space for all the KIP1s!\n"); - } - memcpy(current_dst_kip, current_kip, current_kip_size); - remaining_size -= current_kip_size; - current_dst_kip += current_kip_size; + size_t current_kip_size = kip1_get_size_from_header(current_kip); + if (current_kip_size > remaining_size) { + fatal_error("Not enough space for all the KIP1s!\n"); } + memcpy(current_dst_kip, current_kip, current_kip_size); + remaining_size -= current_kip_size; + current_dst_kip += current_kip_size; process_list[merged->num_processes++] = current_kip->title_id; } diff --git a/fusee/fusee-secondary/src/stratosphere.h b/fusee/fusee-secondary/src/stratosphere.h index 33915555b..2ae43f1be 100644 --- a/fusee/fusee-secondary/src/stratosphere.h +++ b/fusee/fusee-secondary/src/stratosphere.h @@ -20,11 +20,13 @@ #include "utils.h" #include "kip.h" -#define STRATOSPHERE_INI1_EMBEDDED 0x0 -#define STRATOSPHERE_INI1_PACKAGE2 0x1 -#define STRATOSPHERE_INI1_MAX 0x2 +#define STRATOSPHERE_INI1_SDFILES 0x0 +#define STRATOSPHERE_INI1_EMBEDDED 0x1 +#define STRATOSPHERE_INI1_PACKAGE2 0x2 +#define STRATOSPHERE_INI1_MAX 0x3 ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware); +ini1_header_t *stratosphere_get_sd_files_ini1(void); void stratosphere_free_ini1(void); ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_inis); From d4d197a26abd803f817b123b2da6ebc415660ff8 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 15:54:42 -0700 Subject: [PATCH 111/489] fusee: add untested, not hooked up ips code --- fusee/fusee-secondary/src/ips.c | 291 ++++++++++++++++++++++++++++++++ fusee/fusee-secondary/src/ips.h | 27 +++ 2 files changed, 318 insertions(+) create mode 100644 fusee/fusee-secondary/src/ips.c create mode 100644 fusee/fusee-secondary/src/ips.h diff --git a/fusee/fusee-secondary/src/ips.c b/fusee/fusee-secondary/src/ips.c new file mode 100644 index 000000000..46747e5a0 --- /dev/null +++ b/fusee/fusee-secondary/src/ips.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <dirent.h> +#include <string.h> +#include <ctype.h> +#include "utils.h" +#include "se.h" +#include "ips.h" + +/* IPS Patching adapted from Luma3DS (https://github.com/AuroraWright/Luma3DS/blob/master/sysmodules/loader/source/patcher.c) */ + +#define IPS_MAGIC "PATCH" +#define IPS_TAIL "EOF" + +#define IPS32_MAGIC "IPS32" +#define IPS32_TAIL "EEOF" + +/* Applies an IPS/IPS32 patch to memory, disregarding writes to the first prot_size bytes. */ +static void apply_ips_patch(uint8_t *mem, size_t mem_size, size_t prot_size, bool is_ips32, FILE *f_ips) { + uint8_t buffer[4]; + while (fread(buffer, is_ips32 ? 4 : 3, 1, f_ips) == 1) { + if (is_ips32 && memcmp(buffer, IPS32_TAIL, 4) == 0) { + break; + } else if (!is_ips32 && memcmp(buffer, IPS_TAIL, 3) == 0) { + break; + } + + /* Offset of patch. */ + uint32_t patch_offset; + if (is_ips32) { + patch_offset = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; + } else { + patch_offset = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]); + } + + /* Size of patch. */ + if (fread(buffer, 2, 1, f_ips) != 1) { + break; + } + uint32_t patch_size = (buffer[0] << 8) | (buffer[1]); + + /* Check for RLE encoding. */ + if (patch_size == 0) { + /* Size of RLE. */ + if (fread(buffer, 2, 1, f_ips) != 1) { + break; + } + + uint32_t rle_size = (buffer[0] << 8) | (buffer[1]); + + /* Value for RLE. */ + if (fread(buffer, 1, 1, f_ips) != 1) { + break; + } + + if (patch_offset < prot_size) { + if (patch_offset + rle_size > prot_size) { + uint32_t diff = prot_size - patch_offset; + patch_offset += diff; + rle_size -= diff; + goto IPS_RLE_PATCH_OFFSET_WITHIN_BOUNDS; + } + } else { + IPS_RLE_PATCH_OFFSET_WITHIN_BOUNDS: + patch_offset -= prot_size; + if (patch_offset + rle_size > mem_size) { + rle_size = mem_size - patch_offset; + } + memset(mem + patch_offset, buffer[0], rle_size); + } + } else { + if (patch_offset < prot_size) { + if (patch_offset + patch_size > prot_size) { + uint32_t diff = prot_size - patch_offset; + patch_offset += diff; + patch_size -= diff; + fseek(f_ips, diff, SEEK_CUR); + goto IPS_DATA_PATCH_OFFSET_WITHIN_BOUNDS; + } else { + fseek(f_ips, patch_size, SEEK_CUR); + } + } else { + IPS_DATA_PATCH_OFFSET_WITHIN_BOUNDS: + patch_offset -= prot_size; + uint32_t read_size = patch_size; + if (patch_offset + read_size > mem_size) { + read_size = mem_size - patch_offset; + } + if (fread(mem + patch_offset, read_size, 1, f_ips) != 1) { + break; + } + if (patch_size > read_size) { + fseek(f_ips, patch_size - read_size, SEEK_CUR); + } + } + } + } +} + + +static inline uint8_t hex_nybble_to_u8(const char nybble) { + if ('0' <= nybble && nybble <= '9') { + return nybble - '0'; + } else if ('a' <= nybble && nybble <= 'f') { + return nybble - 'a' + 0xa; + } else { + return nybble - 'A' + 0xA; + } +} + +static bool name_matches_hash(const char *name, size_t name_len, const void *hash, size_t hash_size) { + /* Validate name is hex build id. */ + for (unsigned int i = 0; i < name_len - 4; i++) { + if (isxdigit(name[i]) == 0) { + return false; + } + } + + /* Read hash from name. */ + uint8_t hash_from_name[0x20] = {0}; + for (unsigned int name_ofs = 0, id_ofs = 0; name_ofs < name_len - 4; id_ofs++) { + hash_from_name[id_ofs] |= hex_nybble_to_u8(name[name_ofs++]) << 4; + hash_from_name[id_ofs] |= hex_nybble_to_u8(name[name_ofs++]); + } + + return memcmp(hash, hash_from_name, hash_size) == 0; + +} + +static bool apply_ips_patches(const char *dir, void *mem, size_t mem_size, size_t prot_size, const void *hash, size_t hash_size) { + bool any_patches = false; + char path[0x301] = {0}; + snprintf(path, sizeof(path) - 1, "%s", dir); + DIR *patches_dir = opendir(path); + struct dirent *pdir_ent; + if (patches_dir != NULL) { + /* Iterate over the patches directory to find patch subdirectories. */ + while ((pdir_ent = readdir(patches_dir)) != NULL) { + if (strcmp(pdir_ent->d_name, ".") == 0 || strcmp(pdir_ent->d_name, "..") == 0) { + continue; + } + snprintf(path, sizeof(path) - 1, "%s/%s", dir, pdir_ent->d_name); + DIR *patch_dir = opendir(path); + struct dirent *ent; + if (patch_dir != NULL) { + /* Iterate over the patch subdirectory to find .ips patches. */ + while ((ent = readdir(patch_dir)) != NULL) { + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { + continue; + } + size_t name_len = strlen(ent->d_name); + if ((4 < name_len && name_len <= 0x44) && ((name_len & 1) == 0) && strcmp(ent->d_name + name_len - 4, ".ips") == 0 && name_matches_hash(ent->d_name, name_len, hash, hash_size)) { + snprintf(path, sizeof(path) - 1, "%s/%s/%s", dir, pdir_ent->d_name, ent->d_name); + FILE *f_ips = fopen(path, "rb"); + if (f_ips != NULL) { + uint8_t header[5]; + if (fread(header, 5, 1, f_ips) == 1) { + if (memcmp(header, IPS_MAGIC, 5) == 0) { + any_patches = true; + apply_ips_patch(mem, mem_size, prot_size, false, f_ips); + } else if (memcmp(header, IPS32_MAGIC, 5) == 0) { + any_patches = true; + apply_ips_patch(mem, mem_size, prot_size, true, f_ips); + } + } + fclose(f_ips); + } + } + } + closedir(patch_dir); + } + } + closedir(patches_dir); + } + + return any_patches; +} + +void apply_kernel_ips_patches(void *kernel, size_t kernel_size) { + uint8_t hash[0x20]; + se_calculate_sha256(hash, kernel, kernel_size); + apply_ips_patches("atmosphere/kernel_patches", kernel, kernel_size, 0, hash, sizeof(hash)); +} + +static void kip1_blz_uncompress(void *hdr_end) { + uint32_t addl_size = ((uint32_t *)hdr_end)[-1]; + uint32_t header_size = ((uint32_t *)hdr_end)[-2]; + uint32_t cmp_and_hdr_size = ((uint32_t *)hdr_end)[-3]; + + unsigned char *cmp_start = (unsigned char *)(((uintptr_t)hdr_end) - cmp_and_hdr_size); + uint32_t cmp_ofs = cmp_and_hdr_size - header_size; + uint32_t out_ofs = cmp_and_hdr_size + addl_size; + + while (out_ofs) { + unsigned char control = cmp_start[--cmp_ofs]; + for (unsigned int i = 0; i < 8; i++) { + if (control & 0x80) { + if (cmp_ofs < 2) { + fatal_error("KIP1 decompression out of bounds!\n"); + } + cmp_ofs -= 2; + uint16_t seg_val = ((unsigned int)cmp_start[cmp_ofs+1] << 8) | cmp_start[cmp_ofs]; + uint32_t seg_size = ((seg_val >> 12) & 0xF) + 3; + uint32_t seg_ofs = (seg_val & 0x0FFF) + 3; + if (out_ofs < seg_size) { + /* Kernel restricts segment copy to stay in bounds. */ + seg_size = out_ofs; + } + out_ofs -= seg_size; + + for (unsigned int j = 0; j < seg_size; j++) { + cmp_start[out_ofs + j] = cmp_start[out_ofs + j + seg_ofs]; + } + } else { + /* Copy directly. */ + if (cmp_ofs < 1) { + fatal_error("KIP1 decompression out of bounds!\n"); + } + cmp_start[--out_ofs] = cmp_start[--cmp_ofs]; + } + control <<= 1; + if (out_ofs == 0) { + return; + } + } + } +} + +static kip1_header_t *kip1_uncompress(kip1_header_t *kip, size_t *size) { + kip1_header_t new_header = *kip; + for (unsigned int i = 0; i < 3; i++) { + new_header.section_headers[i].compressed_size = new_header.section_headers[i].out_size; + } + new_header.flags &= 0xF8; + + *size = kip1_get_size_from_header(&new_header); + + unsigned char *new_kip = calloc(1, *size); + if (new_kip == NULL) { + return NULL; + } + *((kip1_header_t *)new_kip) = new_header; + + size_t new_offset = 0x100; + size_t old_offset = 0x100; + for (unsigned int i = 0; i < 3; i++) { + memcpy(new_kip + new_offset, (unsigned char *)kip + old_offset, kip->section_headers[i].compressed_size); + if (kip->flags & (1 << i)) { + kip1_blz_uncompress(new_kip + new_offset + kip->section_headers[i].compressed_size); + } + new_offset += kip->section_headers[i].out_size; + old_offset += kip->section_headers[i].compressed_size; + } + + return (kip1_header_t *)new_kip; +} + +kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size) { + uint8_t hash[0x20]; + se_calculate_sha256(hash, kip, kip_size); + + size_t uncompressed_kip_size; + kip1_header_t *uncompressed_kip = kip1_uncompress(kip, &uncompressed_kip_size); + if (uncompressed_kip == NULL) { + return NULL; + } + + if (apply_ips_patches("atmosphere/kip_patches", uncompressed_kip, uncompressed_kip_size, 0x100, hash, sizeof(hash))) { + return uncompressed_kip; + } else { + free(uncompressed_kip); + return NULL; + } +} diff --git a/fusee/fusee-secondary/src/ips.h b/fusee/fusee-secondary/src/ips.h new file mode 100644 index 000000000..6db00a1f1 --- /dev/null +++ b/fusee/fusee-secondary/src/ips.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_IPS_H +#define FUSEE_IPS_H + +#include "utils.h" +#include "kip.h" +#include <stdint.h> + +void apply_kernel_ips_patches(void *kernel, size_t kernel_size); +kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size); + +#endif From b78a3f706516333d96d3c9a2f9fed6d1ee58dac5 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 16:03:23 -0700 Subject: [PATCH 112/489] fusee: Add support for loading kernel from SD --- fusee/fusee-secondary/src/package2.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index f5ac7041d..164b43058 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -63,6 +63,24 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm if (thermosphere_size != 0 && package2->metadata.section_sizes[PACKAGE2_SECTION_UNUSED] != 0) { fatal_error(u8"Error: Package2 has no unused section for Thermosphère!\n"); } + + /* Load Kernel from SD, if possible. */ + { + size_t sd_kernel_size = get_file_size("atmosphere/kernel.bin"); + if (sd_kernel_size != 0) { + if (sd_kernel_size > PACKAGE2_SIZE_MAX) { + fatal_error("Error: atmosphere/kernel.bin is too large!\n"); + } + kernel = malloc(sd_kernel_size); + if (kernel == NULL) { + fatal_error("Error: failed to allocate kernel!\n"); + } + if (read_from_file(kernel, sd_kernel_size, "atmosphere/kernel.bin") != sd_kernel_size) { + fatal_error("Error: failed to read atmosphere/kernel.bin!\n"); + } + kernel_size = sd_kernel_size; + } + } /* Perform any patches we want to the NX kernel. */ package2_patch_kernel(kernel, kernel_size); From 472059134a9f5ce0b7f099912108fe9a7645bfa8 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 16:17:30 -0700 Subject: [PATCH 113/489] fusee: Hook up kip/kernel patch support (needs testing). --- fusee/fusee-secondary/src/kernel_patches.c | 9 +++++++-- fusee/fusee-secondary/src/kernel_patches.h | 2 +- fusee/fusee-secondary/src/package2.c | 5 ++++- fusee/fusee-secondary/src/stratosphere.c | 18 +++++++++++++++--- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index f0741350a..909a066aa 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -18,6 +18,7 @@ #include "utils.h" #include "se.h" #include "kernel_patches.h" +#include "ips.h" #define MAKE_BRANCH(a, o) 0x14000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF) @@ -510,9 +511,13 @@ const kernel_info_t *get_kernel_info(void *kernel, size_t size) { return NULL; } -void package2_patch_kernel(void *_kernel, size_t size) { +void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel) { const kernel_info_t *kernel_info = get_kernel_info(_kernel, size); - if (kernel_info == NULL) { + + /* Apply IPS patches. */ + apply_kernel_ips_patches(_kernel, size); + + if (kernel_info == NULL && !is_sd_kernel) { /* Should this be fatal? */ fatal_error("kernel_patcher: unable to identify kernel!\n"); } diff --git a/fusee/fusee-secondary/src/kernel_patches.h b/fusee/fusee-secondary/src/kernel_patches.h index 7dc2c7795..1dfb21fbf 100644 --- a/fusee/fusee-secondary/src/kernel_patches.h +++ b/fusee/fusee-secondary/src/kernel_patches.h @@ -19,6 +19,6 @@ #include "utils.h" -void package2_patch_kernel(void *kernel, size_t kernel_size); +void package2_patch_kernel(void *kernel, size_t kernel_size, bool is_sd_kernel); #endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 164b43058..1d2fb3a5c 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -23,6 +23,7 @@ #include "kernel_patches.h" #include "kip.h" #include "se.h" +#include "fs_utils.h" #define u8 uint8_t #define u32 uint32_t @@ -47,6 +48,7 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm size_t rebuilt_package2_size; void *kernel; size_t kernel_size; + bool is_sd_kernel = false; void *thermosphere; size_t thermosphere_size; ini1_header_t *orig_ini1, *rebuilt_ini1; @@ -79,11 +81,12 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm fatal_error("Error: failed to read atmosphere/kernel.bin!\n"); } kernel_size = sd_kernel_size; + is_sd_kernel = true; } } /* Perform any patches we want to the NX kernel. */ - package2_patch_kernel(kernel, kernel_size); + package2_patch_kernel(kernel, kernel_size, is_sd_kernel); print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n"); package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1); diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index a90a966c8..d10e0b4b7 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -23,6 +23,7 @@ #include "package2.h" #include "stratosphere.h" #include "fs_utils.h" +#include "ips.h" #include "lib/log.h" #define u8 uint8_t @@ -300,9 +301,20 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { if (current_kip_size > remaining_size) { fatal_error("Not enough space for all the KIP1s!\n"); } - memcpy(current_dst_kip, current_kip, current_kip_size); - remaining_size -= current_kip_size; - current_dst_kip += current_kip_size; + + kip1_header_t *patched_kip = apply_kip_ips_patches(current_kip, current_kip_size); + if (patched_kip != NULL) { + size_t patched_kip_size = kip1_get_size_from_header(patched_kip); + memcpy(current_dst_kip, patched_kip, patched_kip_size); + remaining_size -= patched_kip_size; + current_dst_kip += patched_kip_size; + + free(patched_kip); + } else { + memcpy(current_dst_kip, current_kip, current_kip_size); + remaining_size -= current_kip_size; + current_dst_kip += current_kip_size; + } process_list[merged->num_processes++] = current_kip->title_id; } From 2f29bcef3a6451978bd61d342e5e4e61611ebd8d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 17:21:08 -0700 Subject: [PATCH 114/489] fusee: Fix IPS patching for KIPs. (closes #3). --- fusee/fusee-secondary/src/ips.c | 84 ++++++++++++++++++------ fusee/fusee-secondary/src/stratosphere.c | 5 ++ 2 files changed, 69 insertions(+), 20 deletions(-) diff --git a/fusee/fusee-secondary/src/ips.c b/fusee/fusee-secondary/src/ips.c index 46747e5a0..41c2840a6 100644 --- a/fusee/fusee-secondary/src/ips.c +++ b/fusee/fusee-secondary/src/ips.c @@ -22,6 +22,7 @@ #include <ctype.h> #include "utils.h" #include "se.h" +#include "lib/log.h" #include "ips.h" /* IPS Patching adapted from Luma3DS (https://github.com/AuroraWright/Luma3DS/blob/master/sysmodules/loader/source/patcher.c) */ @@ -79,13 +80,13 @@ static void apply_ips_patch(uint8_t *mem, size_t mem_size, size_t prot_size, boo } } else { IPS_RLE_PATCH_OFFSET_WITHIN_BOUNDS: - patch_offset -= prot_size; if (patch_offset + rle_size > mem_size) { rle_size = mem_size - patch_offset; } memset(mem + patch_offset, buffer[0], rle_size); } } else { + uint32_t read_size; if (patch_offset < prot_size) { if (patch_offset + patch_size > prot_size) { uint32_t diff = prot_size - patch_offset; @@ -98,8 +99,7 @@ static void apply_ips_patch(uint8_t *mem, size_t mem_size, size_t prot_size, boo } } else { IPS_DATA_PATCH_OFFSET_WITHIN_BOUNDS: - patch_offset -= prot_size; - uint32_t read_size = patch_size; + read_size = patch_size; if (patch_offset + read_size > mem_size) { read_size = mem_size - patch_offset; } @@ -144,8 +144,52 @@ static bool name_matches_hash(const char *name, size_t name_len, const void *has } -static bool apply_ips_patches(const char *dir, void *mem, size_t mem_size, size_t prot_size, const void *hash, size_t hash_size) { +static bool has_ips_patches(const char *dir, const void *hash, size_t hash_size) { bool any_patches = false; + char path[0x301] = {0}; + snprintf(path, sizeof(path) - 1, "%s", dir); + DIR *patches_dir = opendir(path); + struct dirent *pdir_ent; + if (patches_dir != NULL) { + /* Iterate over the patches directory to find patch subdirectories. */ + while ((pdir_ent = readdir(patches_dir)) != NULL && !any_patches) { + if (strcmp(pdir_ent->d_name, ".") == 0 || strcmp(pdir_ent->d_name, "..") == 0) { + continue; + } + snprintf(path, sizeof(path) - 1, "%s/%s", dir, pdir_ent->d_name); + DIR *patch_dir = opendir(path); + struct dirent *ent; + if (patch_dir != NULL) { + /* Iterate over the patch subdirectory to find .ips patches. */ + while ((ent = readdir(patch_dir)) != NULL && !any_patches) { + if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { + continue; + } + size_t name_len = strlen(ent->d_name); + if ((4 < name_len && name_len <= 0x44) && ((name_len & 1) == 0) && strcmp(ent->d_name + name_len - 4, ".ips") == 0 && name_matches_hash(ent->d_name, name_len, hash, hash_size)) { + snprintf(path, sizeof(path) - 1, "%s/%s/%s", dir, pdir_ent->d_name, ent->d_name); + FILE *f_ips = fopen(path, "rb"); + if (f_ips != NULL) { + uint8_t header[5]; + if (fread(header, 5, 1, f_ips) == 1) { + if (memcmp(header, IPS_MAGIC, 5) == 0 || memcmp(header, IPS32_MAGIC, 5) == 0) { + any_patches = true; + } + } + fclose(f_ips); + } + } + } + closedir(patch_dir); + } + } + closedir(patches_dir); + } + + return any_patches; +} + +static void apply_ips_patches(const char *dir, void *mem, size_t mem_size, size_t prot_size, const void *hash, size_t hash_size) { char path[0x301] = {0}; snprintf(path, sizeof(path) - 1, "%s", dir); DIR *patches_dir = opendir(path); @@ -173,10 +217,8 @@ static bool apply_ips_patches(const char *dir, void *mem, size_t mem_size, size_ uint8_t header[5]; if (fread(header, 5, 1, f_ips) == 1) { if (memcmp(header, IPS_MAGIC, 5) == 0) { - any_patches = true; apply_ips_patch(mem, mem_size, prot_size, false, f_ips); } else if (memcmp(header, IPS32_MAGIC, 5) == 0) { - any_patches = true; apply_ips_patch(mem, mem_size, prot_size, true, f_ips); } } @@ -189,8 +231,6 @@ static bool apply_ips_patches(const char *dir, void *mem, size_t mem_size, size_ } closedir(patches_dir); } - - return any_patches; } void apply_kernel_ips_patches(void *kernel, size_t kernel_size) { @@ -200,10 +240,11 @@ void apply_kernel_ips_patches(void *kernel, size_t kernel_size) { } static void kip1_blz_uncompress(void *hdr_end) { - uint32_t addl_size = ((uint32_t *)hdr_end)[-1]; - uint32_t header_size = ((uint32_t *)hdr_end)[-2]; - uint32_t cmp_and_hdr_size = ((uint32_t *)hdr_end)[-3]; - + uint8_t *u8_hdr_end = (uint8_t *)hdr_end; + uint32_t addl_size = ((u8_hdr_end[-4]) << 0) | ((u8_hdr_end[-3]) << 8) | ((u8_hdr_end[-2]) << 16) | ((u8_hdr_end[-1]) << 24); + uint32_t header_size = ((u8_hdr_end[-8]) << 0) | ((u8_hdr_end[-7]) << 8) | ((u8_hdr_end[-6]) << 16) | ((u8_hdr_end[-5]) << 24); + uint32_t cmp_and_hdr_size = ((u8_hdr_end[-12]) << 0) | ((u8_hdr_end[-11]) << 8) | ((u8_hdr_end[-10]) << 16) | ((u8_hdr_end[-9]) << 24); + unsigned char *cmp_start = (unsigned char *)(((uintptr_t)hdr_end) - cmp_and_hdr_size); uint32_t cmp_ofs = cmp_and_hdr_size - header_size; uint32_t out_ofs = cmp_and_hdr_size + addl_size; @@ -275,17 +316,20 @@ static kip1_header_t *kip1_uncompress(kip1_header_t *kip, size_t *size) { kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size) { uint8_t hash[0x20]; se_calculate_sha256(hash, kip, kip_size); + + if (!has_ips_patches("atmosphere/kip_patches", hash, sizeof(hash))) { + return NULL; + } + + print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Patching KIP %08x%08x...\n", (uint32_t)(kip->title_id >> 32), (uint32_t)kip->title_id); + size_t uncompressed_kip_size; kip1_header_t *uncompressed_kip = kip1_uncompress(kip, &uncompressed_kip_size); - if (uncompressed_kip == NULL) { - return NULL; - } - - if (apply_ips_patches("atmosphere/kip_patches", uncompressed_kip, uncompressed_kip_size, 0x100, hash, sizeof(hash))) { - return uncompressed_kip; - } else { - free(uncompressed_kip); + if (uncompressed_kip == NULL) { return NULL; } + + apply_ips_patches("atmosphere/kip_patches", uncompressed_kip, uncompressed_kip_size, 0x100, hash, sizeof(hash)); + return uncompressed_kip; } diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index d10e0b4b7..2a07e1ff0 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -296,6 +296,8 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { if (already_loaded) { continue; } + + print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loading KIP %08x%08x...\n", (uint32_t)(current_kip->title_id >> 32), (uint32_t)current_kip->title_id); size_t current_kip_size = kip1_get_size_from_header(current_kip); if (current_kip_size > remaining_size) { @@ -305,6 +307,9 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, size_t num_inis) { kip1_header_t *patched_kip = apply_kip_ips_patches(current_kip, current_kip_size); if (patched_kip != NULL) { size_t patched_kip_size = kip1_get_size_from_header(patched_kip); + if (patched_kip_size > remaining_size) { + fatal_error("Not enough space for all the KIP1s!\n"); + } memcpy(current_dst_kip, patched_kip, patched_kip_size); remaining_size -= patched_kip_size; current_dst_kip += patched_kip_size; From 412511f32a5cf976bc4d726f703c90bb48c90171 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 17:30:24 -0700 Subject: [PATCH 115/489] Exosphere: Bump version to 0.7.0 --- exosphere/src/configitem.c | 6 +++++- exosphere/src/version.h | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 577f74502..d228b01a9 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -151,7 +151,11 @@ uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) { break; case CONFIGITEM_EXOSPHERE_VERSION: /* UNOFFICIAL: Gets information about the current exosphere version. */ - *p_outvalue = (EXOSPHERE_RELEASE_VERSION_MAJOR << 24) | (EXOSPHERE_RELEASE_VERSION_MINOR << 16) | (exosphere_get_target_firmware() << 8) | (mkey_get_revision() << 0); + *p_outvalue = ((ATMOSPHERE_RELEASE_VERSION_MAJOR & 0xFF) << 24) | + ((ATMOSPHERE_RELEASE_VERSION_MINOR & 0xFF) << 16) | + ((ATMOSPHERE_RELEASE_VERSION_MICRO & 0x3F) << 10) | + ((exosphere_get_target_firmware() & 0x1F) << 6) | + ((mkey_get_revision() & 0x1F) << 0); break; default: result = 2; diff --git a/exosphere/src/version.h b/exosphere/src/version.h index 99200b843..8a1a4d3ed 100644 --- a/exosphere/src/version.h +++ b/exosphere/src/version.h @@ -17,7 +17,8 @@ #ifndef EXOSPHERE_VERSION_H #define EXOSPHERE_VERSION_H -#define EXOSPHERE_RELEASE_VERSION_MAJOR 0 -#define EXOSPHERE_RELEASE_VERSION_MINOR 1 +#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 +#define ATMOSPHERE_RELEASE_VERSION_MINOR 7 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 #endif \ No newline at end of file From 6711cd93a8cd7d96b0aee95e389f8ecd69541732 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 17:54:50 -0700 Subject: [PATCH 116/489] atmosphere: extract API version management to common folder --- .../include/atmosphere}/version.h | 4 +- exosphere/Makefile | 2 +- exosphere/src/configitem.c | 12 ++-- fusee/fusee-primary/Makefile | 2 +- fusee/fusee-secondary/Makefile | 2 +- stratosphere/boot/Makefile | 2 +- stratosphere/boot/source/boot_main.cpp | 2 + stratosphere/creport/Makefile | 2 +- stratosphere/fs_mitm/Makefile | 2 +- stratosphere/fs_mitm/source/fsmitm_main.cpp | 20 +----- stratosphere/libstratosphere/Makefile | 2 +- .../libstratosphere/include/stratosphere.hpp | 2 + .../include/stratosphere/version_check.hpp | 66 +++++++++++++++++++ stratosphere/loader/Makefile | 2 +- stratosphere/loader/source/ldr_main.cpp | 14 +--- stratosphere/pm/Makefile | 2 +- stratosphere/pm/source/pm_main.cpp | 7 +- stratosphere/sm/Makefile | 2 +- thermosphere/Makefile | 2 +- 19 files changed, 92 insertions(+), 57 deletions(-) rename {exosphere/src => common/include/atmosphere}/version.h (93%) create mode 100644 stratosphere/libstratosphere/include/stratosphere/version_check.hpp diff --git a/exosphere/src/version.h b/common/include/atmosphere/version.h similarity index 93% rename from exosphere/src/version.h rename to common/include/atmosphere/version.h index 8a1a4d3ed..58dd3a50c 100644 --- a/exosphere/src/version.h +++ b/common/include/atmosphere/version.h @@ -14,8 +14,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef EXOSPHERE_VERSION_H -#define EXOSPHERE_VERSION_H +#ifndef ATMOSPHERE_VERSION_H +#define ATMOSPHERE_VERSION_H #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 7 diff --git a/exosphere/Makefile b/exosphere/Makefile index 77e3e02da..efadefc58 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -20,7 +20,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := src src/dbg DATA := data -INCLUDES := include +INCLUDES := include ../common/include #--------------------------------------------------------------------------------- # options for code generation diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index d228b01a9..389bbcaec 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -15,6 +15,7 @@ */ #include <stdint.h> +#include <atmosphere/version.h> #include "bootconfig.h" #include "configitem.h" @@ -25,7 +26,6 @@ #include "utils.h" #include "masterkey.h" #include "exocfg.h" -#include "version.h" static bool g_battery_profile = false; @@ -151,11 +151,11 @@ uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) { break; case CONFIGITEM_EXOSPHERE_VERSION: /* UNOFFICIAL: Gets information about the current exosphere version. */ - *p_outvalue = ((ATMOSPHERE_RELEASE_VERSION_MAJOR & 0xFF) << 24) | - ((ATMOSPHERE_RELEASE_VERSION_MINOR & 0xFF) << 16) | - ((ATMOSPHERE_RELEASE_VERSION_MICRO & 0x3F) << 10) | - ((exosphere_get_target_firmware() & 0x1F) << 6) | - ((mkey_get_revision() & 0x1F) << 0); + *p_outvalue = ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MAJOR & 0xFF) << 32ull) | + ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MINOR & 0xFF) << 24ull) | + ((uint64_t)(ATMOSPHERE_RELEASE_VERSION_MICRO & 0xFF) << 16ull) | + ((uint64_t)(exosphere_get_target_firmware() & 0xFF) << 8ull) | + ((uint64_t)(mkey_get_revision() & 0xFF) << 0ull); break; default: result = 2; diff --git a/fusee/fusee-primary/Makefile b/fusee/fusee-primary/Makefile index 34307fcbe..8dce2efff 100644 --- a/fusee/fusee-primary/Makefile +++ b/fusee/fusee-primary/Makefile @@ -20,7 +20,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display DATA := data -INCLUDES := include +INCLUDES := include ../../common/include #--------------------------------------------------------------------------------- # options for code generation diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index d902d588b..9055bbf59 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -23,7 +23,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display DATA := data -INCLUDES := include +INCLUDES := include ../../common/include #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/boot/Makefile b/stratosphere/boot/Makefile index b4ff11df6..57b69f6e0 100644 --- a/stratosphere/boot/Makefile +++ b/stratosphere/boot/Makefile @@ -21,7 +21,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := source DATA := data -INCLUDES := include +INCLUDES := include ../../common/include EXEFS_SRC := exefs_src DEFINES := -DDISABLE_IPC diff --git a/stratosphere/boot/source/boot_main.cpp b/stratosphere/boot/source/boot_main.cpp index e636ff6c5..9eb94f170 100644 --- a/stratosphere/boot/source/boot_main.cpp +++ b/stratosphere/boot/source/boot_main.cpp @@ -83,6 +83,8 @@ void __appInit(void) { fatalSimple(0xCAFE << 4 | 2); fsdevMountSdmc(); + + CheckAtmosphereVersion(); } void __appExit(void) { diff --git a/stratosphere/creport/Makefile b/stratosphere/creport/Makefile index 67fd1e2f4..c042e968d 100644 --- a/stratosphere/creport/Makefile +++ b/stratosphere/creport/Makefile @@ -21,7 +21,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := source DATA := data -INCLUDES := include +INCLUDES := include ../../common/include EXEFS_SRC := exefs_src DEFINES := -DDISABLE_IPC diff --git a/stratosphere/fs_mitm/Makefile b/stratosphere/fs_mitm/Makefile index 41a6cf79f..e8b1f047a 100644 --- a/stratosphere/fs_mitm/Makefile +++ b/stratosphere/fs_mitm/Makefile @@ -21,7 +21,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := source DATA := data -INCLUDES := include +INCLUDES := include ../../common/include EXEFS_SRC := exefs_src DEFINES := -DDISABLE_IPC diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index e6271b10d..9caf7f303 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -76,25 +76,7 @@ void __appInit(void) { if (R_FAILED(rc)) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); } - - rc = splInitialize(); - if (R_FAILED(rc)) { - fatalSimple(0xCAFE << 4 | 3); - } - - /* Check for exosphere API compatibility. */ - u64 exosphere_cfg; - if (R_SUCCEEDED(splGetConfig((SplConfigItem)65000, &exosphere_cfg))) { - /* MitM requires Atmosphere API 0.1. */ - u16 api_version = (exosphere_cfg >> 16) & 0xFFFF; - if (api_version < 0x0001) { - fatalSimple(0xCAFE << 4 | 0xFE); - } - } else { - fatalSimple(0xCAFE << 4 | 0xFF); - } - - //splExit(); + CheckAtmosphereVersion(); } void __appExit(void) { diff --git a/stratosphere/libstratosphere/Makefile b/stratosphere/libstratosphere/Makefile index ff0e010e7..70ba1949b 100644 --- a/stratosphere/libstratosphere/Makefile +++ b/stratosphere/libstratosphere/Makefile @@ -18,7 +18,7 @@ include $(DEVKITPRO)/libnx/switch_rules TARGET := $(notdir $(CURDIR)) SOURCES := source DATA := data -INCLUDES := include +INCLUDES := include ../../common/include #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp index fdd8b9d24..041d72741 100644 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -33,3 +33,5 @@ #include "stratosphere/waitablemanager.hpp" #include "stratosphere/multithreadedwaitablemanager.hpp" + +#include "stratosphere/version_check.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/version_check.hpp b/stratosphere/libstratosphere/include/stratosphere/version_check.hpp new file mode 100644 index 000000000..336ea837c --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/version_check.hpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <atmosphere/version.h> + +static inline void GetAtmosphereApiVersion(u32 *major, u32 *minor, u32 *micro, u32 *target_fw, u32 *mkey_rev) { + if (R_FAILED(splInitialize())) { + fatalSimple(0xCAFE << 4 | 0xD); + } + + /* Check for exosphere API compatibility. */ + u64 exosphere_cfg; + if (R_FAILED(splGetConfig((SplConfigItem)65000, &exosphere_cfg))) { + fatalSimple(0xCAFE << 4 | 0xE); + } + + if (mkey_rev) { + *mkey_rev = (u32)((exosphere_cfg >> 0x00) & 0xFF); + } + + if (target_fw) { + *target_fw = (u32)((exosphere_cfg >> 0x08) & 0xFF); + } + + if (micro) { + *micro = (u32)((exosphere_cfg >> 0x10) & 0xFF); + } + + if (minor) { + *minor = (u32)((exosphere_cfg >> 0x18) & 0xFF); + } + + if (major) { + *major = (u32)((exosphere_cfg >> 0x20) & 0xFF); + } + + splExit(); +} + +static inline u32 MakeAtmosphereVersion(u32 major, u32 minor, u32 micro) { + return (major << 16) | (minor << 8) | micro; +} + +static inline void CheckAtmosphereVersion() { + u32 major, minor, micro; + GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); + + if (MakeAtmosphereVersion(major, minor, micro) < MakeAtmosphereVersion(ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO)) { + fatalSimple(0xCAFE << 4 | 0xF); + } +} \ No newline at end of file diff --git a/stratosphere/loader/Makefile b/stratosphere/loader/Makefile index 41a6cf79f..e8b1f047a 100644 --- a/stratosphere/loader/Makefile +++ b/stratosphere/loader/Makefile @@ -21,7 +21,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := source DATA := data -INCLUDES := include +INCLUDES := include ../../common/include EXEFS_SRC := exefs_src DEFINES := -DDISABLE_IPC diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index a8d69bf85..a074977be 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -80,19 +80,7 @@ void __appInit(void) { fatalSimple(0xCAFE << 4 | 2); } - rc = splInitialize(); - if (R_FAILED(rc)) { - fatalSimple(0xCAFE << 4 | 3); - } - - /* Check for exosphere API compatibility. */ - u64 exosphere_cfg; - if (R_FAILED(splGetConfig((SplConfigItem)65000, &exosphere_cfg))) { - //fatalSimple(0xCAFE << 4 | 0xFF); - /* TODO: Does Loader need to know about target firmware/master key revision? If so, extract from exosphere_cfg. */ - } - - //splExit(); + CheckAtmosphereVersion(); } void __appExit(void) { diff --git a/stratosphere/pm/Makefile b/stratosphere/pm/Makefile index c819c77fd..c3b31a855 100644 --- a/stratosphere/pm/Makefile +++ b/stratosphere/pm/Makefile @@ -21,7 +21,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := source DATA := data -INCLUDES := include +INCLUDES := include ../../common/include EXEFS_SRC := exefs_src DEFINES := -DDISABLE_IPC diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 04200ba15..2c33145fb 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -94,12 +94,7 @@ void __appInit(void) { fatalSimple(0xCAFE << 4 | 6); } - /* Check for exosphere API compatibility. */ - u64 exosphere_cfg; - if (R_FAILED(splGetConfig((SplConfigItem)65000, &exosphere_cfg))) { - fatalSimple(0xCAFE << 4 | 0xFF); - /* TODO: Does PM need to know about target firmware/master key revision? If so, extract from exosphere_cfg. */ - } + CheckAtmosphereVersion(); } void __appExit(void) { diff --git a/stratosphere/sm/Makefile b/stratosphere/sm/Makefile index a0da4da5b..3f6b0589d 100644 --- a/stratosphere/sm/Makefile +++ b/stratosphere/sm/Makefile @@ -21,7 +21,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := source DATA := data -INCLUDES := include +INCLUDES := include ../../common/include EXEFS_SRC := exefs_src DEFINES := -DDISABLE_IPC diff --git a/thermosphere/Makefile b/thermosphere/Makefile index f62bcf1f1..76f6a100b 100644 --- a/thermosphere/Makefile +++ b/thermosphere/Makefile @@ -20,7 +20,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := src src/lib DATA := data -INCLUDES := include +INCLUDES := include ../common/include #--------------------------------------------------------------------------------- # options for code generation From 55ad57a02d288e0fe659e227914608edbc49bfd0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 19:01:41 -0700 Subject: [PATCH 117/489] fs.mitm: Use same override button semantics as loader. --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 8 + .../fs_mitm/source/fsmitm_service.hpp | 2 +- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 132 +++++++++ stratosphere/fs_mitm/source/fsmitm_utils.hpp | 8 + stratosphere/fs_mitm/source/ini.c | 269 ++++++++++++++++++ stratosphere/fs_mitm/source/ini.h | 130 +++++++++ stratosphere/fs_mitm/source/sm_mitm.h | 2 + .../loader/source/ldr_content_management.cpp | 5 +- stratosphere/loader/source/ldr_hid.cpp | 2 - 9 files changed, 552 insertions(+), 6 deletions(-) create mode 100644 stratosphere/fs_mitm/source/ini.c create mode 100644 stratosphere/fs_mitm/source/ini.h diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 9caf7f303..f2601b3a2 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -90,6 +90,7 @@ int main(int argc, char **argv) { Thread worker_thread = {0}; Thread sd_initializer_thread = {0}; + Thread hid_initializer_thread = {0}; consoleDebugInit(debugDevice_SVC); consoleDebugInit(debugDevice_SVC); @@ -108,6 +109,13 @@ int main(int argc, char **argv) /* TODO: Panic. */ } + if (R_FAILED(threadCreate(&hid_initializer_thread, &Utils::InitializeHidThreadFunc, NULL, 0x4000, 0x15, 0))) { + /* TODO: Panic. */ + } + if (R_FAILED(threadStart(&hid_initializer_thread))) { + /* TODO: Panic. */ + } + /* TODO: What's a good timeout value to use here? */ auto server_manager = std::make_unique<MultiThreadedWaitableManager>(1, U64_MAX, 0x20000); //auto server_manager = std::make_unique<WaitableManager>(U64_MAX); diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index b1bd62d9c..5c6de0a97 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -38,7 +38,7 @@ class FsMitMService : public IMitMServiceObject { } static bool should_mitm(u64 pid, u64 tid) { - return tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid); + return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)) && Utils::HasOverrideButton(tid); } FsMitMService *clone() override { diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index a98a1b739..57363cfe8 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -18,14 +18,20 @@ #include <stratosphere.hpp> #include <atomic> #include <algorithm> +#include <strings.h> #include "sm_mitm.h" #include "debug.hpp" #include "fsmitm_utils.hpp" +#include "ini.h" static FsFileSystem g_sd_filesystem = {0}; static std::vector<u64> g_mitm_flagged_tids; static std::atomic_bool g_has_initialized = false; +static std::atomic_bool g_has_hid_session = false; + +static u64 g_override_key_combination = KEY_R; +static bool g_override_by_default = true; static bool IsHexadecimal(const char *str) { while (*str) { @@ -77,15 +83,36 @@ void Utils::InitializeSdThreadFunc(void *args) { fsDirClose(&titles_dir); } + FsFile config_file; + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, "/atmosphere/loader.ini", FS_OPEN_READ, &config_file))) { + Utils::LoadConfiguration(&config_file); + fsFileClose(&config_file); + } + + g_has_initialized = true; svcExitThread(); } +void Utils::InitializeHidThreadFunc(void *args) { + while (R_FAILED(hidInitialize())) { + svcSleepThread(1000ULL); + } + + g_has_hid_session = true; + + svcExitThread(); +} + bool Utils::IsSdInitialized() { return g_has_initialized; } +bool Utils::IsHidInitialized() { + return g_has_hid_session; +} + Result Utils::OpenSdFile(const char *fn, int flags, FsFile *out) { if (!IsSdInitialized()) { return 0xFA202; @@ -189,3 +216,108 @@ bool Utils::HasSdMitMFlag(u64 tid) { } return false; } + +Result Utils::GetKeysDown(u64 *keys) { + if (!Utils::IsHidInitialized()) { + return MAKERESULT(Module_Libnx, LibnxError_InitFail_HID); + } + + hidScanInput(); + *keys = hidKeysDown(CONTROLLER_P1_AUTO); + + return 0x0; +} + +bool Utils::HasOverrideButton(u64 tid) { + if (tid < 0x0100000000010000ULL) { + /* Disable button override disable for non-applications. */ + return true; + } + + u64 kDown = 0; + bool keys_triggered = (R_SUCCEEDED(GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0)); + return IsSdInitialized() && (g_override_by_default ^ keys_triggered); +} + +static int FsMitMIniHandler(void *user, const char *section, const char *name, const char *value) { + /* Taken and modified, with love, from Rajkosto's implementation. */ + if (strcasecmp(section, "config") == 0) { + if (strcasecmp(name, "override_key") == 0) { + if (value[0] == '!') { + g_override_by_default = true; + value++; + } else { + g_override_by_default = false; + } + + if (strcasecmp(value, "A") == 0) { + g_override_key_combination = KEY_A; + } else if (strcasecmp(value, "B") == 0) { + g_override_key_combination = KEY_B; + } else if (strcasecmp(value, "X") == 0) { + g_override_key_combination = KEY_X; + } else if (strcasecmp(value, "Y") == 0) { + g_override_key_combination = KEY_Y; + } else if (strcasecmp(value, "LS") == 0) { + g_override_key_combination = KEY_LSTICK; + } else if (strcasecmp(value, "RS") == 0) { + g_override_key_combination = KEY_RSTICK; + } else if (strcasecmp(value, "L") == 0) { + g_override_key_combination = KEY_L; + } else if (strcasecmp(value, "R") == 0) { + g_override_key_combination = KEY_R; + } else if (strcasecmp(value, "ZL") == 0) { + g_override_key_combination = KEY_ZL; + } else if (strcasecmp(value, "ZR") == 0) { + g_override_key_combination = KEY_ZR; + } else if (strcasecmp(value, "PLUS") == 0) { + g_override_key_combination = KEY_PLUS; + } else if (strcasecmp(value, "MINUS") == 0) { + g_override_key_combination = KEY_MINUS; + } else if (strcasecmp(value, "DLEFT") == 0) { + g_override_key_combination = KEY_DLEFT; + } else if (strcasecmp(value, "DUP") == 0) { + g_override_key_combination = KEY_DUP; + } else if (strcasecmp(value, "DRIGHT") == 0) { + g_override_key_combination = KEY_DRIGHT; + } else if (strcasecmp(value, "DDOWN") == 0) { + g_override_key_combination = KEY_DDOWN; + } else if (strcasecmp(value, "SL") == 0) { + g_override_key_combination = KEY_SL; + } else if (strcasecmp(value, "SR") == 0) { + g_override_key_combination = KEY_SR; + } else { + g_override_key_combination = 0; + } + } + } else { + return 0; + } + return 1; +} + + +void Utils::LoadConfiguration(FsFile *f) { + if (f == NULL) { + return; + } + + u64 size; + if (R_FAILED(fsFileGetSize(f, &size))) { + return; + } + + size = std::min(size, (decltype(size))0x7FF); + + char *config_str = new char[0x800]; + if (config_str != NULL) { + /* Read in string. */ + std::fill(config_str, config_str + 0x800, 0); + size_t r_s; + fsFileRead(f, 0, config_str, size, &r_s); + + ini_parse_string(config_str, FsMitMIniHandler, NULL); + + delete[] config_str; + } +} \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index e1480d0d1..54754474c 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -37,4 +37,12 @@ class Utils { /* SD card Initialization + MitM detection. */ static void InitializeSdThreadFunc(void *args); static bool HasSdMitMFlag(u64 tid); + + + static bool IsHidInitialized(); + static void InitializeHidThreadFunc(void *args); + static Result GetKeysDown(u64 *keys); + static bool HasOverrideButton(u64 tid); + private: + static void LoadConfiguration(FsFile *f); }; \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/ini.c b/stratosphere/fs_mitm/source/ini.c new file mode 100644 index 000000000..63626c72d --- /dev/null +++ b/stratosphere/fs_mitm/source/ini.c @@ -0,0 +1,269 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#include "ini.h" + +#if !INI_USE_STACK +#include <stdlib.h> +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to null at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + strncpy(dest, src, size - 1); + dest[size - 1] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; +#else + char* line; + int max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC + char* new_line; + int offset; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = realloc(line, max_line); + if (!new_line) { + free(line); + return -2; + } + line = new_line; + if (reader(line + offset, max_line - offset, stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; +#endif + value = lskip(value); + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ + error = lineno; + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/stratosphere/fs_mitm/source/ini.h b/stratosphere/fs_mitm/source/ini.h new file mode 100644 index 000000000..f45ba40ba --- /dev/null +++ b/stratosphere/fs_mitm/source/ini.h @@ -0,0 +1,130 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef __INI_H__ +#define __INI_H__ + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See http://code.google.com/p/inih/issues/detail?id=21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INI_H__ */ diff --git a/stratosphere/fs_mitm/source/sm_mitm.h b/stratosphere/fs_mitm/source/sm_mitm.h index 302153cd9..4b521c88c 100644 --- a/stratosphere/fs_mitm/source/sm_mitm.h +++ b/stratosphere/fs_mitm/source/sm_mitm.h @@ -17,6 +17,8 @@ Result smMitMGetService(Service* service_out, const char *name); Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name); Result smMitMUninstall(const char *name); +Result smMitMIsRegistered(const char *name); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index c822d3281..93ebb8812 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -92,7 +92,7 @@ Result ContentManagement::UnmountCode() { void ContentManagement::TryMountHblNspOnSd() { - char path[FS_MAX_PATH+1] = {0}; + char path[FS_MAX_PATH + 1] = {0}; strncpy(path, g_hbl_sd_path, FS_MAX_PATH); for (unsigned int i = 0; i < FS_MAX_PATH && path[i] != '\x00'; i++) { if (path[i] == '\\') { @@ -267,9 +267,8 @@ void ContentManagement::LoadConfiguration(FILE *config) { char *config_str = new char[0x800]; if (config_str != NULL) { /* Read in string. */ - std::fill(config_str, config_str + FS_MAX_PATH, 0); + std::fill(config_str, config_str + 0x800, 0); fread(config_str, 1, 0x7FF, config); - config_str[strlen(config_str)] = 0x0; ini_parse_string(config_str, LoaderIniHandler, NULL); diff --git a/stratosphere/loader/source/ldr_hid.cpp b/stratosphere/loader/source/ldr_hid.cpp index 8bad9377b..a7ca176f0 100644 --- a/stratosphere/loader/source/ldr_hid.cpp +++ b/stratosphere/loader/source/ldr_hid.cpp @@ -20,8 +20,6 @@ #include "ldr_content_management.hpp" #include "ldr_hid.hpp" -static bool g_has_opened_hid_session = false; - Result HidManagement::GetKeysDown(u64 *keys) { if (!ContentManagement::HasCreatedTitle(0x0100000000000013) || R_FAILED(hidInitialize())) { return MAKERESULT(Module_Libnx, LibnxError_InitFail_HID); From ba4d39a0caf2e7f1ed761cdd2296963133309765 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 19:41:06 -0700 Subject: [PATCH 118/489] Atmosphere: add make dist --- .gitignore | 4 ++++ Makefile | 30 +++++++++++++++++++++++++++-- common/defaults/BCT.ini | 8 ++++++++ common/defaults/loader.ini | 4 ++++ common/include/atmosphere/version.h | 6 +++--- 5 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 common/defaults/BCT.ini create mode 100644 common/defaults/loader.ini diff --git a/.gitignore b/.gitignore index e39d9f114..f55c55a62 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,10 @@ Module.symvers Mkfile.old dkms.conf +# Distribution files +*.tgz +*.zip + .**/ # NOTE: make sure to make exceptions to this pattern when needed! diff --git a/Makefile b/Makefile index 014cb646c..20b621a00 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,36 @@ -TOPTARGETS := all clean +TOPTARGETS := all clean dist -all: fusee +all: fusee creport fusee: $(MAKE) -C $@ all +creport: + $(MAKE) -C stratosphere/creport all + clean: $(MAKE) -C fusee clean + +dist: fusee creport + $(eval MAJORVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MAJOR\b' common/include/atmosphere/version.h \ + | tr -s [:blank:] \ + | cut -d' ' -f3)) + $(eval MINORVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MINOR\b' common/include/atmosphere/version.h \ + | tr -s [:blank:] \ + | cut -d' ' -f3)) + $(eval MICROVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MICRO\b' common/include/atmosphere/version.h \ + | tr -s [:blank:] \ + | cut -d' ' -f3)) + $(eval AMSVER = $(MAJORVER).$(MINORVER).$(MICROVER)) + rm -rf atmosphere-$(AMSVER) + mkdir atmosphere-$(AMSVER) + mkdir atmosphere-$(AMSVER)/atmosphere + mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 + cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/fusee-secondary.bin + cp common/defaults/BCT.ini atmosphere-$(AMSVER)/BCT.ini + cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini + cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp + cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; + rm -r atmosphere-$(AMSVER) + .PHONY: $(TOPTARGETS) fusee diff --git a/common/defaults/BCT.ini b/common/defaults/BCT.ini new file mode 100644 index 000000000..d609b740e --- /dev/null +++ b/common/defaults/BCT.ini @@ -0,0 +1,8 @@ +BCT0 +[stage1] +stage2_path = fusee-secondary.bin +stage2_addr = 0xF0000000 +stage2_entrypoint = 0xF0000000 + +[exosphere] +target_firmware = 6 \ No newline at end of file diff --git a/common/defaults/loader.ini b/common/defaults/loader.ini new file mode 100644 index 000000000..1049ef9dd --- /dev/null +++ b/common/defaults/loader.ini @@ -0,0 +1,4 @@ +[config] +hbl_tid=010000000000100D +hbl_path=atmosphere/hbl.nsp +override_key=!R \ No newline at end of file diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 58dd3a50c..6c0c59fbe 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -17,8 +17,8 @@ #ifndef ATMOSPHERE_VERSION_H #define ATMOSPHERE_VERSION_H -#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 -#define ATMOSPHERE_RELEASE_VERSION_MINOR 7 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 +#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 +#define ATMOSPHERE_RELEASE_VERSION_MINOR 7 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 #endif \ No newline at end of file From 2c6d00fd8cbd701c1a53c539614f7e6fabd6cde9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 19:43:57 -0700 Subject: [PATCH 119/489] Move dist target to out folder. --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 20b621a00..4d80cb7fc 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ creport: clean: $(MAKE) -C fusee clean + rm -rf out dist: fusee creport $(eval MAJORVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MAJOR\b' common/include/atmosphere/version.h \ @@ -22,6 +23,7 @@ dist: fusee creport | cut -d' ' -f3)) $(eval AMSVER = $(MAJORVER).$(MINORVER).$(MICROVER)) rm -rf atmosphere-$(AMSVER) + rm -rf out mkdir atmosphere-$(AMSVER) mkdir atmosphere-$(AMSVER)/atmosphere mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 @@ -31,6 +33,9 @@ dist: fusee creport cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; rm -r atmosphere-$(AMSVER) + mkdir out + mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip + cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin .PHONY: $(TOPTARGETS) fusee From f10ae4d96f23a5f2057c5ca665a7a061b1479bc3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 19:50:43 -0700 Subject: [PATCH 120/489] Fix default BCT.ini target firmware --- common/defaults/BCT.ini | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/common/defaults/BCT.ini b/common/defaults/BCT.ini index d609b740e..3a8600340 100644 --- a/common/defaults/BCT.ini +++ b/common/defaults/BCT.ini @@ -2,7 +2,4 @@ BCT0 [stage1] stage2_path = fusee-secondary.bin stage2_addr = 0xF0000000 -stage2_entrypoint = 0xF0000000 - -[exosphere] -target_firmware = 6 \ No newline at end of file +stage2_entrypoint = 0xF0000000 \ No newline at end of file From 494498681424cc8d2cc59b6bb8b90e378e27e5fd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 16 Oct 2018 20:41:19 -0700 Subject: [PATCH 121/489] fs.mitm: Allow for disabling mitm for a title via flag. --- stratosphere/fs_mitm/source/fsmitm_service.hpp | 3 +++ stratosphere/fs_mitm/source/fsmitm_utils.cpp | 17 +++++++++++++++++ stratosphere/fs_mitm/source/fsmitm_utils.hpp | 1 + 3 files changed, 21 insertions(+) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 5c6de0a97..0dfa441e3 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -38,6 +38,9 @@ class FsMitMService : public IMitMServiceObject { } static bool should_mitm(u64 pid, u64 tid) { + if (Utils::HasSdDisableMitMFlag(tid)) { + return false; + } return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)) && Utils::HasOverrideButton(tid); } diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 57363cfe8..f726357c6 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -27,6 +27,7 @@ static FsFileSystem g_sd_filesystem = {0}; static std::vector<u64> g_mitm_flagged_tids; +static std::vector<u64> g_disable_mitm_flagged_tids; static std::atomic_bool g_has_initialized = false; static std::atomic_bool g_has_hid_session = false; @@ -78,6 +79,15 @@ void Utils::InitializeSdThreadFunc(void *args) { g_mitm_flagged_tids.push_back(title_id); fsFileClose(&f); } + + memset(title_path, 0, sizeof(title_path)); + strcpy(title_path, "/atmosphere/titles/"); + strcat(title_path, dir_entry.name); + strcat(title_path, "/fsmitm_disable.flag"); + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, title_path, FS_OPEN_READ, &f))) { + g_disable_mitm_flagged_tids.push_back(title_id); + fsFileClose(&f); + } } } fsDirClose(&titles_dir); @@ -217,6 +227,13 @@ bool Utils::HasSdMitMFlag(u64 tid) { return false; } +bool Utils::HasSdDisableMitMFlag(u64 tid) { + if (IsSdInitialized()) { + return std::find(g_disable_mitm_flagged_tids.begin(), g_disable_mitm_flagged_tids.end(), tid) != g_disable_mitm_flagged_tids.end(); + } + return false; +} + Result Utils::GetKeysDown(u64 *keys) { if (!Utils::IsHidInitialized()) { return MAKERESULT(Module_Libnx, LibnxError_InitFail_HID); diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index 54754474c..77b9d20bc 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -37,6 +37,7 @@ class Utils { /* SD card Initialization + MitM detection. */ static void InitializeSdThreadFunc(void *args); static bool HasSdMitMFlag(u64 tid); + static bool HasSdDisableMitMFlag(u64 tid); static bool IsHidInitialized(); From 781f2597e56d87ca609b01ad1a7fc5c924942475 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 17 Oct 2018 03:48:30 -0700 Subject: [PATCH 122/489] libstratosphere: Fix receive for multi-static IPC buffers --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 2 +- .../libstratosphere/include/stratosphere/isession.hpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index f2601b3a2..ef351c94d 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -117,7 +117,7 @@ int main(int argc, char **argv) } /* TODO: What's a good timeout value to use here? */ - auto server_manager = std::make_unique<MultiThreadedWaitableManager>(1, U64_MAX, 0x20000); + auto server_manager = std::make_unique<MultiThreadedWaitableManager>(5, U64_MAX, 0x20000); //auto server_manager = std::make_unique<WaitableManager>(U64_MAX); /* Create fsp-srv mitm. */ diff --git a/stratosphere/libstratosphere/include/stratosphere/isession.hpp b/stratosphere/libstratosphere/include/stratosphere/isession.hpp index 95156a2d0..12fc6650b 100644 --- a/stratosphere/libstratosphere/include/stratosphere/isession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/isession.hpp @@ -187,6 +187,10 @@ class ISession : public IWaitable { ipcAddRecvStatic(&c_for_reply, this->pointer_buffer.data(), this->pointer_buffer.size(), 0); ipcPrepareHeader(&c_for_reply, 0); + /* Fix libnx bug in serverside C descriptor handling. */ + ((u32 *)armGetTls())[1] &= 0xFFFFC3FF; + ((u32 *)armGetTls())[1] |= (2) << 10; + if (R_SUCCEEDED(rc = svcReplyAndReceive(&handle_index, &this->server_handle, 1, 0, U64_MAX))) { if (handle_index != 0) { /* TODO: Panic? */ From 5dc31f001ef4a7a139f2e1d3e11aa36aac44d0cf Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 17 Oct 2018 16:26:36 -0700 Subject: [PATCH 123/489] Stratosphere: Fix FS permissions for <4.0.0 KIPs --- stratosphere/pm/source/pm_main.cpp | 46 ++++++++++--- stratosphere/pm/source/pm_resource_limits.cpp | 3 +- stratosphere/pm/source/smm_ams.c | 69 +++++++++++++++++++ stratosphere/pm/source/smm_ams.h | 21 ++++++ stratosphere/sm/Makefile | 2 +- stratosphere/sm/source/sm_manager_service.cpp | 9 +++ stratosphere/sm/source/sm_manager_service.hpp | 6 +- stratosphere/sm/source/sm_registration.cpp | 37 +++++++++- stratosphere/sm/source/sm_registration.hpp | 3 + stratosphere/sm/source/sm_user_service.cpp | 2 +- 10 files changed, 183 insertions(+), 15 deletions(-) create mode 100644 stratosphere/pm/source/smm_ams.c create mode 100644 stratosphere/pm/source/smm_ams.h diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 2c33145fb..034567ecf 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -28,6 +28,7 @@ #include "pm_process_track.hpp" #include "pm_registration.hpp" #include "pm_debug_monitor.hpp" +#include "smm_ams.h" extern "C" { extern u32 __start__; @@ -56,6 +57,20 @@ void __libnx_initheap(void) { fake_heap_end = (char*)addr + size; } +void RegisterPrivilegedProcessesWithFs() { + /* Ensures that all privileged processes are registered with full FS permissions. */ + constexpr u64 PRIVILEGED_PROCESS_MIN = 0; + constexpr u64 PRIVILEGED_PROCESS_MAX = 0x4F; + + const u32 PRIVILEGED_FAH[0x1C/sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000}; + const u32 PRIVILEGED_FAC[0x2C/sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}; + + for (u64 pid = PRIVILEGED_PROCESS_MIN; pid <= PRIVILEGED_PROCESS_MAX; pid++) { + fsprUnregisterProgram(pid); + fsprRegisterProgram(pid, pid, FsStorageId_NandSystem, PRIVILEGED_FAH, sizeof(PRIVILEGED_FAH), PRIVILEGED_FAC, sizeof(PRIVILEGED_FAC)); + } +} + void __appInit(void) { Result rc; @@ -64,27 +79,33 @@ void __appInit(void) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); } - rc = fsInitialize(); - if (R_FAILED(rc)) { - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); - } - - rc = lrInitialize(); + rc = fsprInitialize(); if (R_FAILED(rc)) { fatalSimple(0xCAFE << 4 | 1); } - rc = fsprInitialize(); - if (R_FAILED(rc)) { + /* This works around a bug with process permissions on < 4.0.0. */ + RegisterPrivilegedProcessesWithFs(); + + rc = smManagerAmsInitialize(); + if (R_SUCCEEDED(rc)) { + smManagerAmsEndInitialDefers(); + smManagerAmsExit(); + } else { fatalSimple(0xCAFE << 4 | 2); } - rc = ldrPmInitialize(); + rc = smManagerInitialize(); + if (R_FAILED(rc)) { + fatalSimple(0xCAFE << 4 | 3); + } + + rc = lrInitialize(); if (R_FAILED(rc)) { fatalSimple(0xCAFE << 4 | 4); } - rc = smManagerInitialize(); + rc = ldrPmInitialize(); if (R_FAILED(rc)) { fatalSimple(0xCAFE << 4 | 5); } @@ -94,6 +115,11 @@ void __appInit(void) { fatalSimple(0xCAFE << 4 | 6); } + rc = fsInitialize(); + if (R_FAILED(rc)) { + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); + } + CheckAtmosphereVersion(); } diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index e0d729075..3d311d713 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -182,7 +182,8 @@ void ResourceLimitUtils::InitializeLimits() { /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */ for (unsigned int i = 0; i < 6; i++) { g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + //g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; } /* Set resource limits. */ diff --git a/stratosphere/pm/source/smm_ams.c b/stratosphere/pm/source/smm_ams.c new file mode 100644 index 000000000..4437ba949 --- /dev/null +++ b/stratosphere/pm/source/smm_ams.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <switch/arm/atomics.h> +#include "smm_ams.h" + +static Service g_smManagerAmsSrv; +static u64 g_smManagerAmsRefcnt; + +Result smManagerAmsInitialize(void) { + atomicIncrement64(&g_smManagerAmsRefcnt); + + if (serviceIsActive(&g_smManagerAmsSrv)) + return 0; + + return smGetService(&g_smManagerAmsSrv, "sm:m"); +} + +void smManagerAmsExit(void) { + if (atomicDecrement64(&g_smManagerAmsRefcnt) == 0) + serviceClose(&g_smManagerAmsSrv); +} + +Result smManagerAmsEndInitialDefers(void) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65000; + + + Result rc = serviceIpcDispatch(&g_smManagerAmsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; + +} \ No newline at end of file diff --git a/stratosphere/pm/source/smm_ams.h b/stratosphere/pm/source/smm_ams.h new file mode 100644 index 000000000..6d6dd5ed0 --- /dev/null +++ b/stratosphere/pm/source/smm_ams.h @@ -0,0 +1,21 @@ +/** + * @file smm_ams.h + * @brief Service manager (sm:m) IPC wrapper for Atmosphere extensions. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include <switch.h> + +#ifdef __cplusplus +extern "C" { +#endif + +Result smManagerAmsInitialize(void); +void smManagerAmsExit(void); + +Result smManagerAmsEndInitialDefers(void); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/stratosphere/sm/Makefile b/stratosphere/sm/Makefile index 3f6b0589d..dae1cae4a 100644 --- a/stratosphere/sm/Makefile +++ b/stratosphere/sm/Makefile @@ -34,7 +34,7 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE CFLAGS := -g -Wall -O2 -ffunction-sections \ $(ARCH) $(DEFINES) -CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX -DSM_ENABLE_MITM -DSM_MINIMUM_SESSION_LIMIT=8 +CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX -DSM_ENABLE_MITM -DSM_ENABLE_INIT_DEFERS -DSM_MINIMUM_SESSION_LIMIT=8 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 diff --git a/stratosphere/sm/source/sm_manager_service.cpp b/stratosphere/sm/source/sm_manager_service.cpp index 04190f7ed..03e0e5d95 100644 --- a/stratosphere/sm/source/sm_manager_service.cpp +++ b/stratosphere/sm/source/sm_manager_service.cpp @@ -28,6 +28,9 @@ Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_ case Manager_Cmd_UnregisterProcess: rc = WrapIpcCommandImpl<&ManagerService::unregister_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; + case Manager_Cmd_AtmosphereEndInitDefers: + rc = WrapIpcCommandImpl<&ManagerService::end_init_defers>(this, r, out_c, pointer_buffer, pointer_buffer_size); + break; default: break; } @@ -47,3 +50,9 @@ std::tuple<Result> ManagerService::register_process(u64 pid, InBuffer<u8> acid_s std::tuple<Result> ManagerService::unregister_process(u64 pid) { return {Registration::UnregisterProcess(pid)}; } + +std::tuple<Result> ManagerService::end_init_defers() { + Registration::EndInitDefers(); + return {0}; +} + diff --git a/stratosphere/sm/source/sm_manager_service.hpp b/stratosphere/sm/source/sm_manager_service.hpp index f64b26a03..fd7a98647 100644 --- a/stratosphere/sm/source/sm_manager_service.hpp +++ b/stratosphere/sm/source/sm_manager_service.hpp @@ -20,7 +20,10 @@ enum ManagerServiceCmd { Manager_Cmd_RegisterProcess = 0, - Manager_Cmd_UnregisterProcess = 1 + Manager_Cmd_UnregisterProcess = 1, + + + Manager_Cmd_AtmosphereEndInitDefers = 65000, }; class ManagerService final : public IServiceObject { @@ -36,4 +39,5 @@ class ManagerService final : public IServiceObject { /* Actual commands. */ std::tuple<Result> register_process(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac); std::tuple<Result> unregister_process(u64 pid); + std::tuple<Result> end_init_defers(); }; diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index 63def66d9..46c6d62fc 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -26,6 +26,7 @@ static std::array<Registration::Service, REGISTRATION_LIST_MAX_SERVICE> g_servic static u64 g_initial_process_id_low = 0; static u64 g_initial_process_id_high = 0; static bool g_determined_initial_process_ids = false; +static bool g_end_init_defers = false; u64 GetServiceNameLength(u64 service) { u64 service_name_len = 0; @@ -36,6 +37,38 @@ u64 GetServiceNameLength(u64 service) { return service_name_len; } +/* Atmosphere extension utilities. */ +void Registration::EndInitDefers() { + g_end_init_defers = true; +} + +constexpr u64 EncodeNameConstant(const char *name) { + u64 service = 0; + for (unsigned int i = 0; i < sizeof(service); i++) { + if (name[i] == '\x00') { + break; + } + service |= ((u64)name[i]) << (8 * i); + } + return service; +} + +bool Registration::ShouldInitDefer(u64 service) { + /* Only enable if compile-time generated. */ +#ifndef SM_ENABLE_INIT_DEFERS + return false; +#endif + + if (g_end_init_defers) { + return false; + } + + /* This is a mechanism by which certain services will always be deferred until sm:m receives a special command. */ + /* This can be extended with more services as needed at a later date. */ + constexpr u64 FSP_SRV = EncodeNameConstant("fsp-srv"); + return service == FSP_SRV; +} + /* Utilities. */ Registration::Process *Registration::GetProcessForPid(u64 pid) { auto process_it = std::find_if(g_process_list.begin(), g_process_list.end(), member_equals_fn(&Process::pid, pid)); @@ -188,11 +221,13 @@ bool Registration::HasService(u64 service) { Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) { Registration::Service *target_service = GetService(service); - if (target_service == NULL) { + if (target_service == NULL || ShouldInitDefer(service)) { /* Note: This defers the result until later. */ return RESULT_DEFER_SESSION; } + /* */ + *out = 0; Result rc; if (target_service->mitm_pid == 0 || target_service->mitm_pid == pid) { diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 630a72181..9a30652bc 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -46,6 +46,9 @@ class Registration { }; /* Utilities. */ + static void EndInitDefers(); + static bool ShouldInitDefer(u64 service); + static Registration::Process *GetProcessForPid(u64 pid); static Registration::Process *GetFreeProcess(); static Registration::Service *GetService(u64 service); diff --git a/stratosphere/sm/source/sm_user_service.cpp b/stratosphere/sm/source/sm_user_service.cpp index 0f8927ed8..00cf6f971 100644 --- a/stratosphere/sm/source/sm_user_service.cpp +++ b/stratosphere/sm/source/sm_user_service.cpp @@ -53,7 +53,7 @@ Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, Result UserService::handle_deferred() { /* If we're deferred, GetService failed. */ - return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);; + return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service); } From 06accd00f9b6c2e24dc7b33dfa44fd6871518b6e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 17 Oct 2018 16:28:53 -0700 Subject: [PATCH 124/489] pm: steal memory from 4.0.0+ ? applet : application --- stratosphere/pm/source/pm_resource_limits.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index 3d311d713..67a4aa773 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -182,8 +182,12 @@ void ResourceLimitUtils::InitializeLimits() { /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */ for (unsigned int i = 0; i < 6; i++) { g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - //g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + /* On < 4.0.0, taking from application instead of applet fixes a rare hang on boot. */ + if (kernelAbove400()) { + g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + } else { + g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + } } /* Set resource limits. */ From f9f9997d3f62827b2f1d8e751b327878e818ff5a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 17 Oct 2018 16:40:57 -0700 Subject: [PATCH 125/489] Exosphere: fix warmboot constant for 4.0.0-4.1.0 --- exosphere/src/package2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index aeafd88d3..1281f9498 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -478,7 +478,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { MAKE_REG32(PMC_BASE + 0x334) |= 0x10; switch (exosphere_get_target_firmware()) { case EXOSPHERE_TARGET_FIRMWARE_400: - MAKE_REG32(PMC_BASE + 0x360) = 5; + MAKE_REG32(PMC_BASE + 0x360) = 0x105; break; case EXOSPHERE_TARGET_FIRMWARE_500: MAKE_REG32(PMC_BASE + 0x360) = 6; From d502f3fa3fba2a091783f01e15f82b29a126bebd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 17 Oct 2018 17:32:18 -0700 Subject: [PATCH 126/489] Atmosphere: Bump version to 0.7.1 --- common/include/atmosphere/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 6c0c59fbe..c791c151d 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 7 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 1 #endif \ No newline at end of file From 85540d4ad2786c8d682fc4d6237ca0f936fb68df Mon Sep 17 00:00:00 2001 From: SciresM <Sciresm@gmail.com> Date: Fri, 19 Oct 2018 12:15:18 +0900 Subject: [PATCH 127/489] fs.mitm: Fix correctness bug in LayeredRomfs::Read(). --- stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp index 4a11580fa..ed6ad63a1 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp @@ -124,12 +124,14 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { fatalSimple(0xF601); } read_so_far += cur_read_size; + offset += cur_read_size; } else { /* Handle padding explicitly. */ cur_source_ind++; /* Zero out the padding we skip, here. */ - memset((void *)((uintptr_t)buffer + read_so_far), 0, ((*this->p_source_infos)[cur_source_ind]).virtual_offset - (cur_source->virtual_offset + cur_source->size)); - read_so_far += ((*this->p_source_infos)[cur_source_ind]).virtual_offset - (cur_source->virtual_offset + cur_source->size); + memset((void *)((uintptr_t)buffer + read_so_far), 0, ((*this->p_source_infos)[cur_source_ind]).virtual_offset - offset); + read_so_far += ((*this->p_source_infos)[cur_source_ind]).virtual_offset - offset; + offset = ((*this->p_source_infos)[cur_source_ind]).virtual_offset; } } From aa761753d74bc3e53f0f83656c39d8afe9aa60e6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 21 Oct 2018 13:59:59 -0700 Subject: [PATCH 128/489] Atmosphere: Update dist zip filename to include commit hash --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4d80cb7fc..6f1bb8c77 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,8 @@ TOPTARGETS := all clean dist +AMSREV := $(shell git rev-parse --short HEAD) +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif all: fusee creport fusee: @@ -21,7 +25,7 @@ dist: fusee creport $(eval MICROVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MICRO\b' common/include/atmosphere/version.h \ | tr -s [:blank:] \ | cut -d' ' -f3)) - $(eval AMSVER = $(MAJORVER).$(MINORVER).$(MICROVER)) + $(eval AMSVER = $(MAJORVER).$(MINORVER).$(MICROVER)-$(AMSREV)) rm -rf atmosphere-$(AMSVER) rm -rf out mkdir atmosphere-$(AMSVER) From e61bb00d7a7c7ee1ad7dcace51915dced0d6053e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 22 Oct 2018 13:39:15 -0700 Subject: [PATCH 129/489] Atmosphere: bump version to 0.7.2 --- common/include/atmosphere/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index c791c151d..30fecc9e8 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 7 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 1 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 2 #endif \ No newline at end of file From f96e1d507493eccc4bb01c5f1265896ebb8ed234 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 22 Oct 2018 22:53:40 -0700 Subject: [PATCH 130/489] loader/fs.mitm: Support override config changes at runtime --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 38 +++++++++---------- stratosphere/fs_mitm/source/fsmitm_utils.hpp | 2 +- .../loader/source/ldr_content_management.cpp | 26 ++++++------- .../loader/source/ldr_content_management.hpp | 1 + 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index f726357c6..c8791607a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -34,6 +34,9 @@ static std::atomic_bool g_has_hid_session = false; static u64 g_override_key_combination = KEY_R; static bool g_override_by_default = true; +/* Static buffer for loader.ini contents at runtime. */ +static char g_config_ini_data[0x800]; + static bool IsHexadecimal(const char *str) { while (*str) { if (isxdigit(*str)) { @@ -93,12 +96,7 @@ void Utils::InitializeSdThreadFunc(void *args) { fsDirClose(&titles_dir); } - FsFile config_file; - if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, "/atmosphere/loader.ini", FS_OPEN_READ, &config_file))) { - Utils::LoadConfiguration(&config_file); - fsFileClose(&config_file); - } - + Utils::RefreshConfiguration(); g_has_initialized = true; @@ -251,6 +249,9 @@ bool Utils::HasOverrideButton(u64 tid) { return true; } + /* Unconditionally refresh loader.ini contents. */ + RefreshConfiguration(); + u64 kDown = 0; bool keys_triggered = (R_SUCCEEDED(GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0)); return IsSdInitialized() && (g_override_by_default ^ keys_triggered); @@ -314,27 +315,26 @@ static int FsMitMIniHandler(void *user, const char *section, const char *name, c } -void Utils::LoadConfiguration(FsFile *f) { - if (f == NULL) { +void Utils::RefreshConfiguration() { + FsFile config_file; + if (R_FAILED(fsFsOpenFile(&g_sd_filesystem, "/atmosphere/loader.ini", FS_OPEN_READ, &config_file))) { return; } u64 size; - if (R_FAILED(fsFileGetSize(f, &size))) { + if (R_FAILED(fsFileGetSize(&config_file, &size))) { return; } size = std::min(size, (decltype(size))0x7FF); - char *config_str = new char[0x800]; - if (config_str != NULL) { - /* Read in string. */ - std::fill(config_str, config_str + 0x800, 0); - size_t r_s; - fsFileRead(f, 0, config_str, size, &r_s); + /* Read in string. */ + std::fill(g_config_ini_data, g_config_ini_data + 0x800, 0); + size_t r_s; + fsFileRead(&config_file, 0, g_config_ini_data, size, &r_s); + + ini_parse_string(g_config_ini_data, FsMitMIniHandler, NULL); - ini_parse_string(config_str, FsMitMIniHandler, NULL); - - delete[] config_str; - } + + fsFileClose(&config_file); } \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index 77b9d20bc..42d547481 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -45,5 +45,5 @@ class Utils { static Result GetKeysDown(u64 *keys); static bool HasOverrideButton(u64 tid); private: - static void LoadConfiguration(FsFile *f); + static void RefreshConfiguration(); }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 93ebb8812..2d5850016 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -40,6 +40,9 @@ static u64 g_override_key_combination = KEY_R; static bool g_override_by_default = true; static u64 g_override_hbl_tid = 0x010000000000100D; +/* Static buffer for loader.ini contents at runtime. */ +static char g_config_ini_data[0x800]; + Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { char path[FS_MAX_PATH] = {0}; Result rc; @@ -49,6 +52,10 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { TryMountSdCard(); } + if (g_has_initialized_fs_dev) { + RefreshConfigurationData(); + } + if (ShouldOverrideContents() && R_SUCCEEDED(MountCodeNspOnSd(tid))) { return 0x0; } @@ -259,23 +266,17 @@ static int LoaderIniHandler(void *user, const char *section, const char *name, c return 1; } -void ContentManagement::LoadConfiguration(FILE *config) { +void ContentManagement::RefreshConfigurationData() { + FILE *config = fopen("sdmc:/atmosphere/loader.ini", "r"); if (config == NULL) { return; } - char *config_str = new char[0x800]; - if (config_str != NULL) { - /* Read in string. */ - std::fill(config_str, config_str + 0x800, 0); - fread(config_str, 1, 0x7FF, config); - - ini_parse_string(config_str, LoaderIniHandler, NULL); - - delete[] config_str; - } - + std::fill(g_config_ini_data, g_config_ini_data + 0x800, 0); + fread(g_config_ini_data, 1, 0x7FF, config); fclose(config); + + ini_parse_string(g_config_ini_data, LoaderIniHandler, NULL); } void ContentManagement::TryMountSdCard() { @@ -292,7 +293,6 @@ void ContentManagement::TryMountSdCard() { } if (R_SUCCEEDED(fsdevMountSdmc())) { - ContentManagement::LoadConfiguration(fopen("sdmc:/atmosphere/loader.ini", "r")); g_has_initialized_fs_dev = true; } } diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index c241092a4..92ce721e2 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -34,6 +34,7 @@ class ContentManagement { static bool HasCreatedTitle(u64 tid); static void SetCreatedTitle(u64 tid); + static void RefreshConfigurationData(); static void LoadConfiguration(FILE *config); static void TryMountSdCard(); From db97dd8d753da2008369153b1cb95b100f424009 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 22 Oct 2018 22:56:26 -0700 Subject: [PATCH 131/489] Loader: clean up orphaned function prototype --- stratosphere/loader/source/ldr_content_management.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index 92ce721e2..183415f8f 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -35,7 +35,6 @@ class ContentManagement { static bool HasCreatedTitle(u64 tid); static void SetCreatedTitle(u64 tid); static void RefreshConfigurationData(); - static void LoadConfiguration(FILE *config); static void TryMountSdCard(); static bool ShouldReplaceWithHBL(u64 tid); From e1d884960da509f2f78438120939af9609a58dbe Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 22 Oct 2018 23:00:22 -0700 Subject: [PATCH 132/489] fs.mitm: Improve configuration refresh file semantics. --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index c8791607a..127fa7a24 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -244,7 +244,7 @@ Result Utils::GetKeysDown(u64 *keys) { } bool Utils::HasOverrideButton(u64 tid) { - if (tid < 0x0100000000010000ULL) { + if (tid < 0x0100000000010000ULL || !IsSdInitialized()) { /* Disable button override disable for non-applications. */ return true; } @@ -332,9 +332,7 @@ void Utils::RefreshConfiguration() { std::fill(g_config_ini_data, g_config_ini_data + 0x800, 0); size_t r_s; fsFileRead(&config_file, 0, g_config_ini_data, size, &r_s); + fsFileClose(&config_file); ini_parse_string(g_config_ini_data, FsMitMIniHandler, NULL); - - - fsFileClose(&config_file); } \ No newline at end of file From d55a9d168e40444e98eed57a71d4fdc8dfa8c8cb Mon Sep 17 00:00:00 2001 From: Hylian <43305009+HylianMedia@users.noreply.github.com> Date: Mon, 22 Oct 2018 17:37:21 -0500 Subject: [PATCH 133/489] Replaced Release Roadmap with Upcoming Features, added Changelog and added HBL and Button Override sections to loader.md --- docs/changelog.md | 72 ++++++++++++++++++++++++++++++++++++++++++ docs/main.md | 7 ++-- docs/modules/loader.md | 8 +++-- docs/roadmap.md | 35 ++++++++++---------- 4 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 docs/changelog.md diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 000000000..fd796c1b7 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,72 @@ +# Changelog +## 0.7.2 ++ Fixed a bug in fs.mitm's LayeredFS read implementation that caused some games to crash when trying to read files. ++ Fixed a bug affecting 1.0.0 that caused games to crash with fatal error 2001-0106 on boot. ++ Improved filenames output by the make dist target. ++ General system stability improvements to enhance the user's experience. +## 0.7.1 ++ Fixed a bug preventing consoles on 4.0.0-4.1.0 from going to sleep and waking back up. ++ Fixed a bug preventing consoles on < 4.0.0 from booting without specific KIPs on the SD card. ++ An API was added to Atmosphère's Service Manager for deferring acquisition of all handles for specific services until after early initialization is completed. ++ General system stability improvements to enhance the user's experience. +## 0.7.0 ++ First official release of Atmosphère. ++ Supports the following featureset: + + Fusée, a custom bootloader. + + Supports loading/customizing of arbitrary KIPs from the SD card. + + Supports loading a custom kernel from the SD card ("/atmosphere/kernel.bin"). + + Supports compile-time defined kernel patches on a per-firmware basis. + + All patches at paths like /atmosphere/kip_patches/<user-defined patch name>/<SHA256 of KIP>.ips will be applied to the relevant KIPs, allowing for easy distribution of patches supporting multiple versions. + + Both the IPS and IPS32 formats are supported. + + All patches at paths like /atmosphere/kernel_patches/<user-defined patch name>/<SHA256 of Kernel>.ips will be applied to the kernel, allowing for easy distribution of patches supporting multiple versions. + + Both the IPS and IPS32 formats are supported. + + Configurable by editing BCT.ini on the SD card. + + Atmosphère should also be launchable by the alternative hekate bootloader, for those who prefer it. + + Exosphère, a fully-featured custom secure monitor. + + Exosphere is a re-implementation of Nintendo's TrustZone firmware, fully replicating all of its features. + + In addition, it has been extended to provide information on current Atmosphere API version, for homebrew wishing to make use of it. + + Stratosphère, a set of custom system modules. This includes: + + A loader system module. + + Reimplementation of Nintendo's loader, fully replicating all original functionality. + + Configurable by editing /atmosphere/loader.ini + + First class support for the Homebrew Loader. + + An exefs NSP (default "/atmosphere/hbl.nsp") will be used in place of the victim title's exefs. + + By default, HBL will replace the album applet, but any application should also be supported. + + Extended to support arbitrary redirection of executable content to the SD card. + + Files will be preferentially loaded from /atmosphere/titles/<titleid>/exefs/, if present. + + Files present in the original exefs a user wants to mark as not present may be "stubbed" by creating a .stub file on the SD. + + If present, a PFS0 at /atmosphere/titles/<titleid>/exefs.nsp will fully replace the original exefs. + + Redirection is optionally toggleable by holding down certain buttons (by default, holding R disables redirection). + + Full support for patching NSO content is implemented. + + All patches at paths like /atmosphere/exefs_patches/<user-defined patch name>/<Hex Build-ID for NSO to patch>.ips will be applied, allowing for easy distribution of patches supporting multiple firmware versions and/or titles. + + Both the IPS and IPS32 formats are supported. + + Extended to support launching content from loose executable files on the SD card, without requiring any official installation. + + This is done by specifying FsStorageId_None on launch. + + A service manager system module. + + Reimplementation of Nintendo's service manager, fully replicating all original functionality. + + Compile-time support for reintroduction of "smhax", allowing clients to optionally skip service access verification by skipping initialization. + + Extended to allow homebrew to acquire more handles to privileged services than Nintendo natively allows. + + Extended to add a new API for installing Man-In-The-Middle listeners for arbitrary services. + + API can additionally be used to safely detect whether a service has been registered in a non-blocking way with no side-effects. + + Full API documentation to come. + + A process manager system module. + + Reimplementation of Nintendo's process manager, fully replicating all original functionality. + + Extended to allow homebrew to acquire handles to arbitrary processes, and thus read/modify system memory without blocking execution. + + Extended to allow homebrew to retrieve information about system resource limits. + + Extended by embedding a full, extended implementation of Nintendo's boot2 system module. + + Title launch order has been optimized in order to grant access to the SD card faster. + + The error-collection system module is intentionally not launched, preventing many system telemetry error reports from being generated at all. + + Users may place their own custom sysmodules on the SD card and flag them for automatic boot2 launch by creating a /atmosphere/titles/<title ID>/boot2.flag file on their SD card. + + A custom fs.mitm system module. + + Uses Atmosphère's MitM API in order to provide an easy means for users to modify game content. + + Intercepts all FS commands sent by games, with special handling for commands used to mount RomFS/DLC content to enable easy creation and distribution of game/DLC mods. + + fs.mitm will parse the base RomFS image for a game, a RomFS image located at /atmosphere/titles/<title ID>/romfs.bin, and all loose files in /atmosphere/titles/<title ID>/romfs/, and merge them together into a single RomFS image. + + When merging, loose files are preferred to content in the SD card romfs.bin image, and files from the SD card image are preferred to those in the base image. + + Can additionally be used to intercept commands sent by arbitrary system titles (excepting those launched before SD card is active), by creating a /atmosphere/titles/<title ID>/fsmitm.flag file on the SD card. + + Can be forcibly disabled for any title, by creating a /atmosphere/titles/<title ID>/fsmitm_disable.flag file on the SD card. + + Redirection is optionally toggleable by holding down certain buttons (by default, holding R disables redirection). + + A custom crash report system module. + + Serves as a drop-in replacement for Nintendo's own creport system module. + + Generates detailed, human-readable reports on system crashes, saving to /atmosphere/crash_reports/<timestamp>_<title ID>.log. + + Because reports are not sent to the erpt sysmodule, this disables all crash report related telemetry. + + General system stability improvements to enhance the user's experience. diff --git a/docs/main.md b/docs/main.md index 5a6dfad1a..02f3efc39 100644 --- a/docs/main.md +++ b/docs/main.md @@ -22,5 +22,8 @@ Stratosphère's modules include: ### Building Atmosphère A guide to building Atmosphère can be found [here](../docs/building.md). -### Release Roadmap -A roadmap of the releases of Atmosphère can be found [here](../docs/roadmap.md). +### Upcoming Features +A list of planned features for Atmosphère can be found [here](../docs/roadmap.md). + +### Release History +A changelog of previous versions of Atmosphère can be found [here](../docs/changelog.md). diff --git a/docs/modules/loader.md b/docs/modules/loader.md index 954873bb4..6bde97faa 100644 --- a/docs/modules/loader.md +++ b/docs/modules/loader.md @@ -53,11 +53,15 @@ When authoring patches, [hactool](https://github.com/SciresM/hactool) can be use ### HBL Support -TODO +Atmosphère can use the loader module in order to turn any game on your Switch's home menu into a launchpoint for the Homebrew Menu, rather than launching it through the album applet. This allows one to launch the Homebrew Menu with access to the ~3.2GB of RAM that the Switch reserves for games and applications, as opposed to the 442MB of RAM we are limited to when launching the Homebrew Menu from the album. This also means that it is no longer necessary to install homebrew as `.nsp` files on your Switch so long as you are using this method, as the only reason to do so is to allow the homebrew to access all of the Switch's available memory. + +In order to setup this method you will need the latest release of [hbmenu](https://github.com/switchbrew/nx-hbmenu/releases), and the latest release of [hbloader](https://github.com/switchbrew/nx-hbloader/releases). Place `hbmenu.nro` on the root of your Switch's SD Card, and place `hbl.nsp` in the atmosphere folder. From there, simply configure `loader.ini` in the atmosphere folder by replacing the Title ID in the ini (hbl_tid) (it is the Title ID for the album by default) with the Title ID of whatever game you wish to use to launch the Homebrew Menu. A list of Title IDs for Switch Games can be found [here](https://switchbrew.org/wiki/Title_list/Games). Afterwards you may reinsert your SD Card into your Switch and boot into Atmosphère as you normally would. You should now be able to boot into the Homebrew Menu by launching your designated game of choice. ### Button Overrides -TODO +By default `loader.ini` is configured to launch the Homebrew Menu when launching the game normally, and launching the game when selecting the game while holding down R. If you wish to change this, you can modify the override_key section of `loader.ini`. Placing an exclamation point in front of whatever button you wish to use will make it so that you will only launch the actual game while holding down that button, otherwise you will go into the Homebrew Menu. Removing the exclamation point will reverse this, meaning that you will boot into the Homebrew Menu only while holding down the assigned button when launching the game. + +For example, `override_key=!R` will run the game only while holding down R when launching it, otherwise it will boot into the Homebrew Menu. `override_key=R` will only boot into the Homebrew Menu while holding down R when launching the game, otherwise it will launch the game as normal. ### SM MITM Integration diff --git a/docs/roadmap.md b/docs/roadmap.md index f7507928d..03367dff9 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,19 +1,16 @@ -# Release Roadmap -## Upcoming Releases -### 0.7 -0.7 will be Atmosphère's first official release. -This release will include: -+ Fusée - + Supports loading/customizing of arbitrary KIPs from the SD card. - + Supports compile-time defined kernel patches on a per-firmware basis. - + Configurable by editing BCT.ini on the SD card. - + Atmosphère should also be launchable by the alternative hekate bootloader, for those who prefer it. -+ Exosphère - + Exosphere is a re-implementation of Nintendo's TrustZone firmware, fully replicating all of its features. - + In addition, it has been extended to provide information on current Atmosphere API version, for homebrew wishing to make use of it. -+ Stratosphère - + loader system module - + Service Manager system module (sm) - + Process Manager system module (pm) - + fs.mitm system module - + creport system module +# Planned Features +The following features are planned to be added in future versions of Atmosphère: ++ Thermosphère, a hypervisor-based emunand implementation. ++ A feature-rich debugging toolset (a component of Stratosphère). + + A custom debug monitor system module, providing an API for debugging Switch's processes. This may not be a reimplementation of Nintendo's own debug monitor. + + This should include a gdbstub implementation, possibly borrowing from Luma3DS's. + + This API should be additionally usable for RAM Editing/"Cheat Engine" purposes. + + A custom shell system module, providing an means for users to perform various RPC (with support for common/interesting functionality) on their Switch remotely. This may not be a reimplementation of Nintendo's own shell. + + This should support client connections over both Wi-Fi and USB. + + A custom logging system module, providing a means for other Atmosphère components (and possibly Nintendo's own system modules) to log debug output. + + This should support logging to the SD card, over Wi-Fi, and over USB. ++ An application-level plugin system. + + This will, ideally, work somewhat like NTR-CFW's plugin system on the 3DS, allowing users to run their own code in a game's process in their own thread. ++ An AR Code/Gameshark analog implementation, allowing for easy sharing/development of cheat codes to run on device. ++ Further extensions to existing Atmosphère components. ++ General system stability improvements to enhance the user's experience. From c0fe4f7af71f035537ac85a1781321c63892469c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 24 Oct 2018 14:05:07 -0700 Subject: [PATCH 134/489] fs.mitm: Intercept qlaunch sysver request --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 36 +++++- .../fs_mitm/source/setsys_mitm_service.cpp | 104 ++++++++++++++++++ .../fs_mitm/source/setsys_mitm_service.hpp | 58 ++++++++++ .../include/stratosphere/isession.hpp | 2 +- 4 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 stratosphere/fs_mitm/source/setsys_mitm_service.cpp create mode 100644 stratosphere/fs_mitm/source/setsys_mitm_service.hpp diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index ef351c94d..12b2e75c3 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -32,6 +32,8 @@ #include "fsmitm_utils.hpp" +#include "setsys_mitm_service.hpp" + extern "C" { extern u32 __start__; @@ -86,15 +88,30 @@ void __appExit(void) { smExit(); } +void CreateSettingsMitMServer(void *arg) { + MultiThreadedWaitableManager *server_manager = (MultiThreadedWaitableManager *)arg; + + Result rc; + if (R_FAILED((rc = setsysInitialize()))) { + fatalSimple(rc); + } + + ISession<MitMQueryService<SetSysMitMService>> *setsys_query_srv = NULL; + MitMServer<SetSysMitMService> *setsys_srv = new MitMServer<SetSysMitMService>(&setsys_query_srv, "set:sys", 60); + server_manager->add_waitable(setsys_srv); + server_manager->add_waitable(setsys_query_srv); + + svcExitThread(); +} + int main(int argc, char **argv) { Thread worker_thread = {0}; Thread sd_initializer_thread = {0}; Thread hid_initializer_thread = {0}; + Thread set_mitm_setup_thread = {0}; consoleDebugInit(debugDevice_SVC); - - consoleDebugInit(debugDevice_SVC); - + if (R_FAILED(threadCreate(&worker_thread, &FsMitMWorker::Main, NULL, 0x20000, 45, 0))) { /* TODO: Panic. */ } @@ -117,17 +134,26 @@ int main(int argc, char **argv) } /* TODO: What's a good timeout value to use here? */ - auto server_manager = std::make_unique<MultiThreadedWaitableManager>(5, U64_MAX, 0x20000); - //auto server_manager = std::make_unique<WaitableManager>(U64_MAX); + MultiThreadedWaitableManager *server_manager = new MultiThreadedWaitableManager(5, U64_MAX, 0x20000); /* Create fsp-srv mitm. */ ISession<MitMQueryService<FsMitMService>> *fs_query_srv = NULL; MitMServer<FsMitMService> *fs_srv = new MitMServer<FsMitMService>(&fs_query_srv, "fsp-srv", 61); server_manager->add_waitable(fs_srv); server_manager->add_waitable(fs_query_srv); + + /* Create set:sys mitm server, delayed until set:sys is available. */ + if (R_FAILED(threadCreate(&set_mitm_setup_thread, &CreateSettingsMitMServer, server_manager, 0x4000, 0x15, 0))) { + /* TODO: Panic. */ + } + if (R_FAILED(threadStart(&set_mitm_setup_thread))) { + /* TODO: Panic. */ + } /* Loop forever, servicing our services. */ server_manager->process(); + + delete server_manager; return 0; } diff --git a/stratosphere/fs_mitm/source/setsys_mitm_service.cpp b/stratosphere/fs_mitm/source/setsys_mitm_service.cpp new file mode 100644 index 000000000..2d702f93c --- /dev/null +++ b/stratosphere/fs_mitm/source/setsys_mitm_service.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <mutex> +#include <switch.h> +#include "setsys_mitm_service.hpp" + +#include "mitm_query_service.hpp" +#include "debug.hpp" + +static HosMutex g_version_mutex; +static bool g_got_version = false; +static SetSysFirmwareVersion g_fw_version = {0}; + +static Result _GetFirmwareVersion(SetSysFirmwareVersion *out) { + std::lock_guard<HosMutex> lock(g_version_mutex); + if (!g_got_version) { + Result rc = setsysGetFirmwareVersion(&g_fw_version); + if (R_FAILED(rc)) { + return rc; + } + + /* Modify the output firmware version. */ + { + u32 major, minor, micro; + char display_version[sizeof(g_fw_version.display_version)] = {0}; + + GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); + snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro); + + memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version)); + } + + g_got_version = true; + } + + *out = g_fw_version; + return 0; +} + +Result SetSysMitMService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { + Result rc = 0xF601; + + switch (static_cast<SetSysCmd>(cmd_id)) { + case SetSysCmd::GetFirmwareVersion: + rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version>(this, r, out_c, pointer_buffer, pointer_buffer_size); + break; + case SetSysCmd::GetFirmwareVersion2: + if (kernelAbove300()) { + rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version2>(this, r, out_c, pointer_buffer, pointer_buffer_size); + } + break; + default: + break; + } + + return rc; +} + +void SetSysMitMService::postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { + /* No commands need postprocessing. */ +} + +Result SetSysMitMService::handle_deferred() { + /* This service is never deferrable. */ + return 0; +} + +std::tuple<Result> SetSysMitMService::get_firmware_version(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { + if (out.num_elements != 1) { + return {0xF601}; + } + + Result rc = _GetFirmwareVersion(out.pointer); + + /* GetFirmwareVersion sanitizes these fields. */ + out.pointer->revision_major = 0; + out.pointer->revision_minor = 0; + + return {rc}; +} + +std::tuple<Result> SetSysMitMService::get_firmware_version2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { + if (out.num_elements != 1) { + return {0xF601}; + } + + Result rc = _GetFirmwareVersion(out.pointer); + + return {rc}; +} \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/setsys_mitm_service.hpp b/stratosphere/fs_mitm/source/setsys_mitm_service.hpp new file mode 100644 index 000000000..8c8877881 --- /dev/null +++ b/stratosphere/fs_mitm/source/setsys_mitm_service.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere/iserviceobject.hpp> +#include "imitmserviceobject.hpp" +#include "fsmitm_utils.hpp" + +enum class SetSysCmd { + GetFirmwareVersion = 3, + GetFirmwareVersion2 = 4, +}; + +class SetSysMitMService : public IMitMServiceObject { + private: + public: + SetSysMitMService(Service *s) : IMitMServiceObject(s) { + /* ... */ + } + + static bool should_mitm(u64 pid, u64 tid) { + /* Only MitM qlaunch, maintenance. */ + return tid == 0x0100000000001000ULL || tid == 0x0100000000001015ULL; + } + + SetSysMitMService *clone() override { + auto new_srv = new SetSysMitMService((Service *)&this->forward_service); + this->clone_to(new_srv); + return new_srv; + } + + void clone_to(void *o) override { + /* ... */ + } + + virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); + virtual void postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); + virtual Result handle_deferred(); + + protected: + /* Overridden commands. */ + std::tuple<Result> get_firmware_version(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); + std::tuple<Result> get_firmware_version2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/isession.hpp b/stratosphere/libstratosphere/include/stratosphere/isession.hpp index 12fc6650b..a5371deeb 100644 --- a/stratosphere/libstratosphere/include/stratosphere/isession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/isession.hpp @@ -196,7 +196,7 @@ class ISession : public IWaitable { /* TODO: Panic? */ } IpcParsedCommand r; - u64 cmd_id; + u64 cmd_id = 0; Result retval = ipcParse(&r); From a6cfbae1ff291c19a42f7fb5776b2e0b22389305 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 24 Oct 2018 14:08:55 -0700 Subject: [PATCH 135/489] Bump version to 0.7.3 --- common/include/atmosphere/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 30fecc9e8..9ab1693ad 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 7 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 2 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 3 #endif \ No newline at end of file From de688ee17a0043bc1f5034d529bc1ec385d13c23 Mon Sep 17 00:00:00 2001 From: Hylian <43305009+HylianMedia@users.noreply.github.com> Date: Wed, 24 Oct 2018 16:25:59 -0500 Subject: [PATCH 136/489] Update changelog.md --- docs/changelog.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index fd796c1b7..7aefb2474 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,14 +1,21 @@ # Changelog +## 0.7.3 ++ Loader and fs.mitm now try to reload loader.ini before reading it. This allows for changing the override button combination/HBL title id at runtime. ++ Added a MitM between set:sys and qlaunch, used to override the system version string displayed in system settings. + + The displayed system version will now display `<Actual version> (AMS <x>.<y>.<z>)`. ++ General system stability improvements to enhance the user's experience. ## 0.7.2 + Fixed a bug in fs.mitm's LayeredFS read implementation that caused some games to crash when trying to read files. + Fixed a bug affecting 1.0.0 that caused games to crash with fatal error 2001-0106 on boot. + Improved filenames output by the make dist target. + General system stability improvements to enhance the user's experience. + ## 0.7.1 + Fixed a bug preventing consoles on 4.0.0-4.1.0 from going to sleep and waking back up. + Fixed a bug preventing consoles on < 4.0.0 from booting without specific KIPs on the SD card. + An API was added to Atmosphère's Service Manager for deferring acquisition of all handles for specific services until after early initialization is completed. + General system stability improvements to enhance the user's experience. + ## 0.7.0 + First official release of Atmosphère. + Supports the following featureset: From b62329bd5ba07de84f5f8d7f0e5bfe6475857bcc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 25 Oct 2018 13:42:25 -0700 Subject: [PATCH 137/489] Add bug report issue template --- .github/ISSUE_TEMPLATE/bug_report.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..4b4dfad1e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,25 @@ +--- +name: Bug Report +about: Something doesn't work correctly in Atmosphère. + +--- + +## Bug Report + +### What's the issue you encountered? + +### How can the issue be reproduced? + +### Crash report? + +(If a crash report was created under /atmosphere/crash_reports/, please upload it to +[gist](https://gist.github.com/) and paste the link here.) + +### Environment? + +- What bootloader (fusee, hekate, etc) was Atmosphère launched by: +- Official release or unofficial build: +- Do you have additional kips you're loading: +- Additional info about your environment: + +### Additional context? From afbf57c2222f10767bc5ecb90cd21623c419eccf Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 25 Oct 2018 13:47:13 -0700 Subject: [PATCH 138/489] Add Feature Request Issue Template --- .github/ISSUE_TEMPLATE/feature_request.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..3b93d9d25 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,12 @@ +--- +name: Feature Request +about: You want to suggest a new feature for Atmosphère. + +--- + +## Feature Request + +### What feature are you suggesting? + +### Why would this feature be useful? + From a502d31cd1cf946136993d853a928dee38640ebc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 25 Oct 2018 13:52:55 -0700 Subject: [PATCH 139/489] Add Question Issue Template --- .github/ISSUE_TEMPLATE/question.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/question.md diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 000000000..6cc1915b9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,12 @@ +--- +name: Question +about: Please ask questions in the ReSwitched discord, instead of making issues. + +--- + +We would like to use GitHub to keep track of problems/feature requests. + +If you have a question, please join the ReSwitched discord for help. + +- Discord link: https://discordapp.com/invite/DThbZ7z + From 376feb63bdc217f32dd1462a2ca558d963d026de Mon Sep 17 00:00:00 2001 From: misson20000 <xenotoad@xenotoad.net> Date: Wed, 10 Oct 2018 20:45:54 -0700 Subject: [PATCH 140/489] loader: make ShouldOverrideContents take a tid argument --- stratosphere/loader/source/ldr_content_management.cpp | 6 +++--- stratosphere/loader/source/ldr_content_management.hpp | 2 +- stratosphere/loader/source/ldr_npdm.cpp | 4 ++-- stratosphere/loader/source/ldr_nso.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 2d5850016..efb2129e1 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -56,7 +56,7 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { RefreshConfigurationData(); } - if (ShouldOverrideContents() && R_SUCCEEDED(MountCodeNspOnSd(tid))) { + if (ShouldOverrideContents(tid) && R_SUCCEEDED(MountCodeNspOnSd(tid))) { return 0x0; } @@ -302,7 +302,7 @@ bool ContentManagement::ShouldReplaceWithHBL(u64 tid) { return g_mounted_hbl_nsp && tid == g_override_hbl_tid; } -bool ContentManagement::ShouldOverrideContents() { +bool ContentManagement::ShouldOverrideContents(u64 tid) { if (HasCreatedTitle(0x0100000000001000)) { u64 kDown = 0; bool keys_triggered = (R_SUCCEEDED(HidManagement::GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0)); @@ -311,4 +311,4 @@ bool ContentManagement::ShouldOverrideContents() { /* Always redirect before qlaunch. */ return g_has_initialized_fs_dev; } -} \ No newline at end of file +} diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index 183415f8f..9de9c2b29 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -38,5 +38,5 @@ class ContentManagement { static void TryMountSdCard(); static bool ShouldReplaceWithHBL(u64 tid); - static bool ShouldOverrideContents(); + static bool ShouldOverrideContents(u64 tid); }; diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index 8d7eb0f37..e7a110ced 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -53,7 +53,7 @@ FILE *NpdmUtils::OpenNpdmFromSdCard(u64 title_id) { FILE *NpdmUtils::OpenNpdm(u64 title_id) { - if (ContentManagement::ShouldOverrideContents()) { + if (ContentManagement::ShouldOverrideContents(title_id)) { if (ContentManagement::ShouldReplaceWithHBL(title_id)) { return OpenNpdmFromHBL(); } @@ -182,7 +182,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { info->acid->title_id_range_max = tid; info->aci0->title_id = tid; - if (ContentManagement::ShouldOverrideContents() && ContentManagement::ShouldReplaceWithHBL(tid) + if (ContentManagement::ShouldOverrideContents(tid) && ContentManagement::ShouldReplaceWithHBL(tid) && R_SUCCEEDED(LoadNpdmInternal(OpenNpdmFromExeFS(), &g_original_npdm_cache))) { NpdmInfo *original_info = &g_original_npdm_cache.info; /* Fix pool partition. */ diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index 451093e7c..a90a03f94 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -61,7 +61,7 @@ bool NsoUtils::CheckNsoStubbed(unsigned int index, u64 title_id) { } FILE *NsoUtils::OpenNso(unsigned int index, u64 title_id) { - if (ContentManagement::ShouldOverrideContents()) { + if (ContentManagement::ShouldOverrideContents(title_id)) { if (ContentManagement::ShouldReplaceWithHBL(title_id)) { return OpenNsoFromHBL(index); } From 18f51e9b2e7db346a45c674d71e7783deb5247d4 Mon Sep 17 00:00:00 2001 From: misson20000 <xenotoad@xenotoad.net> Date: Wed, 10 Oct 2018 20:46:43 -0700 Subject: [PATCH 141/489] loader: add NpdmUtils function for invalidating the cache for a specific title --- stratosphere/loader/source/ldr_npdm.cpp | 8 +++++++- stratosphere/loader/source/ldr_npdm.hpp | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index e7a110ced..ad688f85e 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -500,4 +500,10 @@ u32 NpdmUtils::GetApplicationTypeRaw(u32 *caps, size_t num_caps) { } } return application_type; -} \ No newline at end of file +} + +void NpdmUtils::InvalidateCache(u64 tid) { + if (g_npdm_cache.info.title_id == tid) { + g_npdm_cache.info = (const NpdmUtils::NpdmInfo){0}; + } +} diff --git a/stratosphere/loader/source/ldr_npdm.hpp b/stratosphere/loader/source/ldr_npdm.hpp index b04606046..8b9c2dd1e 100644 --- a/stratosphere/loader/source/ldr_npdm.hpp +++ b/stratosphere/loader/source/ldr_npdm.hpp @@ -108,6 +108,8 @@ class NpdmUtils { static FILE *OpenNpdm(u64 tid); static Result LoadNpdm(u64 tid, NpdmInfo *out); static Result LoadNpdmFromCache(u64 tid, NpdmInfo *out); + + static void InvalidateCache(u64 tid); private: static Result LoadNpdmInternal(FILE *f_npdm, NpdmCache *cache); -}; \ No newline at end of file +}; From 5c147e51885a9f712fb6ad9f879faa8fbd2a0edf Mon Sep 17 00:00:00 2001 From: misson20000 <xenotoad@xenotoad.net> Date: Thu, 25 Oct 2018 12:52:01 -0700 Subject: [PATCH 142/489] loader: add SetExternalContentSource extension --- .../loader/source/ldr_content_management.cpp | 57 ++++++++++++++++++- .../loader/source/ldr_content_management.hpp | 20 +++++++ stratosphere/loader/source/ldr_npdm.cpp | 11 ++++ stratosphere/loader/source/ldr_npdm.hpp | 3 +- stratosphere/loader/source/ldr_nso.cpp | 11 ++++ stratosphere/loader/source/ldr_nso.hpp | 5 +- .../loader/source/ldr_process_creation.cpp | 2 + stratosphere/loader/source/ldr_shell.cpp | 20 +++++++ stratosphere/loader/source/ldr_shell.hpp | 7 ++- 9 files changed, 132 insertions(+), 4 deletions(-) diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index efb2129e1..4fa73c093 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -19,11 +19,12 @@ #include <strings.h> #include <vector> #include <algorithm> +#include <map> #include "ldr_registration.hpp" #include "ldr_content_management.hpp" #include "ldr_hid.hpp" - +#include "ldr_npdm.hpp" #include "ini.h" @@ -43,6 +44,9 @@ static u64 g_override_hbl_tid = 0x010000000000100D; /* Static buffer for loader.ini contents at runtime. */ static char g_config_ini_data[0x800]; +/* SetExternalContentSource extension */ +static std::map<u64, ContentManagement::ExternalContentSource> g_external_content_sources; + Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { char path[FS_MAX_PATH] = {0}; Result rc; @@ -312,3 +316,54 @@ bool ContentManagement::ShouldOverrideContents(u64 tid) { return g_has_initialized_fs_dev; } } + +/* SetExternalContentSource extension */ +ContentManagement::ExternalContentSource *ContentManagement::GetExternalContentSource(u64 tid) { + auto i = g_external_content_sources.find(tid); + if (i == g_external_content_sources.end()) { + return nullptr; + } else { + return &i->second; + } +} + +Result ContentManagement::SetExternalContentSource(u64 tid, FsFileSystem filesystem) { + if (g_external_content_sources.size() >= 16) { + return 0x409; /* LAUNCH_QUEUE_FULL */ + } + + /* Remove any existing ECS for this title. */ + ClearExternalContentSource(tid); + + char mountpoint[32]; + ExternalContentSource::GenerateMountpointName(tid, mountpoint, sizeof(mountpoint)); + if (fsdevMountDevice(mountpoint, filesystem) == -1) { + return 0x7802; /* specified mount name already exists */ + } + g_external_content_sources.emplace( + std::piecewise_construct, + std::make_tuple(tid), + std::make_tuple(tid, mountpoint)); + + return 0; +} + +void ContentManagement::ClearExternalContentSource(u64 tid) { + auto i = g_external_content_sources.find(tid); + if (i != g_external_content_sources.end()) { + g_external_content_sources.erase(i); + } +} + +void ContentManagement::ExternalContentSource::GenerateMountpointName(u64 tid, char *out, size_t max_length) { + snprintf(out, max_length, "ecs-%016lx", tid); +} + +ContentManagement::ExternalContentSource::ExternalContentSource(u64 tid, const char *mountpoint) : tid(tid) { + strncpy(this->mountpoint, mountpoint, sizeof(this->mountpoint)); + NpdmUtils::InvalidateCache(tid); +} + +ContentManagement::ExternalContentSource::~ExternalContentSource() { + fsdevUnmountDevice(mountpoint); +} diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index 9de9c2b29..a9974530a 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -39,4 +39,24 @@ class ContentManagement { static bool ShouldReplaceWithHBL(u64 tid); static bool ShouldOverrideContents(u64 tid); + + /* SetExternalContentSource extension */ + class ExternalContentSource { + public: + static void GenerateMountpointName(u64 tid, char *out, size_t max_length); + + ExternalContentSource(u64 tid, const char *mountpoint); + ~ExternalContentSource(); + + ExternalContentSource(const ExternalContentSource &other) = delete; + ExternalContentSource(ExternalContentSource &&other) = delete; + ExternalContentSource &operator=(const ExternalContentSource &other) = delete; + ExternalContentSource &operator=(ExternalContentSource &&other) = delete; + + const u64 tid; + char mountpoint[32]; + }; + static ExternalContentSource *GetExternalContentSource(u64 tid); /* returns nullptr if no ECS is set */ + static Result SetExternalContentSource(u64 tid, FsFileSystem filesystem); /* takes ownership of filesystem */ + static void ClearExternalContentSource(u64 tid); }; diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index ad688f85e..7eb114cfc 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -33,6 +33,12 @@ Result NpdmUtils::LoadNpdmFromCache(u64 tid, NpdmInfo *out) { return 0; } +FILE *NpdmUtils::OpenNpdmFromECS(ContentManagement::ExternalContentSource *ecs) { + std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0); + snprintf(g_npdm_path, FS_MAX_PATH, "%s:/main.npdm", ecs->mountpoint); + return fopen(g_npdm_path, "rb"); +} + FILE *NpdmUtils::OpenNpdmFromHBL() { std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0); snprintf(g_npdm_path, FS_MAX_PATH, "hbl:/main.npdm"); @@ -53,6 +59,11 @@ FILE *NpdmUtils::OpenNpdmFromSdCard(u64 title_id) { FILE *NpdmUtils::OpenNpdm(u64 title_id) { + ContentManagement::ExternalContentSource *ecs = nullptr; + if ((ecs = ContentManagement::GetExternalContentSource(title_id)) != nullptr) { + return OpenNpdmFromECS(ecs); + } + if (ContentManagement::ShouldOverrideContents(title_id)) { if (ContentManagement::ShouldReplaceWithHBL(title_id)) { return OpenNpdmFromHBL(); diff --git a/stratosphere/loader/source/ldr_npdm.hpp b/stratosphere/loader/source/ldr_npdm.hpp index 8b9c2dd1e..2d4610f58 100644 --- a/stratosphere/loader/source/ldr_npdm.hpp +++ b/stratosphere/loader/source/ldr_npdm.hpp @@ -19,6 +19,7 @@ #include <cstdio> #include "ldr_registration.hpp" +#include "ldr_content_management.hpp" /* for ExternalContentSource */ #define MAGIC_META 0x4154454D #define MAGIC_ACI0 0x30494341 @@ -101,7 +102,7 @@ class NpdmUtils { static Result ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size_t num_restrict_caps, u32 *&cur_cap, size_t &caps_remaining); static Result ValidateCapabilities(u32 *acid_caps, size_t num_acid_caps, u32 *aci0_caps, size_t num_aci0_caps); - + static FILE *OpenNpdmFromECS(ContentManagement::ExternalContentSource *ecs); static FILE *OpenNpdmFromHBL(); static FILE *OpenNpdmFromExeFS(); static FILE *OpenNpdmFromSdCard(u64 tid); diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index a90a03f94..bdc65eb3d 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -31,6 +31,12 @@ static bool g_nso_present[NSO_NUM_MAX] = {0}; static char g_nso_path[FS_MAX_PATH] = {0}; +FILE *NsoUtils::OpenNsoFromECS(unsigned int index, ContentManagement::ExternalContentSource *ecs) { + std::fill(g_nso_path, g_nso_path + FS_MAX_PATH, 0); + snprintf(g_nso_path, FS_MAX_PATH, "%s:/%s", ecs->mountpoint, NsoUtils::GetNsoFileName(index)); + return fopen(g_nso_path, "rb"); +} + FILE *NsoUtils::OpenNsoFromHBL(unsigned int index) { std::fill(g_nso_path, g_nso_path + FS_MAX_PATH, 0); snprintf(g_nso_path, FS_MAX_PATH, "hbl:/%s", NsoUtils::GetNsoFileName(index)); @@ -61,6 +67,11 @@ bool NsoUtils::CheckNsoStubbed(unsigned int index, u64 title_id) { } FILE *NsoUtils::OpenNso(unsigned int index, u64 title_id) { + ContentManagement::ExternalContentSource *ecs = nullptr; + if ((ecs = ContentManagement::GetExternalContentSource(title_id)) != nullptr) { + return OpenNsoFromECS(index, ecs); + } + if (ContentManagement::ShouldOverrideContents(title_id)) { if (ContentManagement::ShouldReplaceWithHBL(title_id)) { return OpenNsoFromHBL(index); diff --git a/stratosphere/loader/source/ldr_nso.hpp b/stratosphere/loader/source/ldr_nso.hpp index 364943346..6de7f6677 100644 --- a/stratosphere/loader/source/ldr_nso.hpp +++ b/stratosphere/loader/source/ldr_nso.hpp @@ -18,6 +18,8 @@ #include <switch.h> #include <cstdio> +#include "ldr_content_management.hpp" /* for ExternalContentSource */ + #define MAGIC_NSO0 0x304F534E #define NSO_NUM_MAX 13 @@ -96,7 +98,8 @@ class NsoUtils { return "?"; } } - + + static FILE *OpenNsoFromECS(unsigned int index, ContentManagement::ExternalContentSource *ecs); static FILE *OpenNsoFromHBL(unsigned int index); static FILE *OpenNsoFromExeFS(unsigned int index); static FILE *OpenNsoFromSdCard(unsigned int index, u64 title_id); diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 40d9d716d..74c4b095e 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -215,6 +215,8 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc rc = 0; CREATE_PROCESS_END: + /* ECS is a one-shot operation. */ + ContentManagement::ClearExternalContentSource(target_process->tid_sid.title_id); if (mounted_code) { if (R_SUCCEEDED(rc) && target_process->tid_sid.storage_id != FsStorageId_None) { rc = ContentManagement::UnmountCode(); diff --git a/stratosphere/loader/source/ldr_shell.cpp b/stratosphere/loader/source/ldr_shell.cpp index 664388d08..75b884a08 100644 --- a/stratosphere/loader/source/ldr_shell.cpp +++ b/stratosphere/loader/source/ldr_shell.cpp @@ -18,6 +18,7 @@ #include <stratosphere.hpp> #include "ldr_shell.hpp" #include "ldr_launch_queue.hpp" +#include "ldr_content_management.hpp" Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { @@ -30,6 +31,9 @@ Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id case Shell_Cmd_ClearLaunchQueue: rc = WrapIpcCommandImpl<&ShellService::clear_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; + case Shell_Cmd_AtmosphereSetExternalContentSource: + rc = WrapIpcCommandImpl<&ShellService::set_external_content_source>(this, r, out_c, pointer_buffer, pointer_buffer_size); + break; default: break; } @@ -46,3 +50,19 @@ std::tuple<Result> ShellService::clear_launch_queue(u64 dat) { LaunchQueue::clear(); return {0}; } + +/* SetExternalContentSource extension */ +std::tuple<Result, MovedHandle> ShellService::set_external_content_source(u64 tid) { + Handle server_h; + Handle client_h; + + Result rc; + if (R_FAILED(rc = svcCreateSession(&server_h, &client_h, 0, 0))) { + return {rc, 0}; + } + + Service service; + serviceCreate(&service, client_h); + ContentManagement::SetExternalContentSource(tid, FsFileSystem {service}); + return {0, server_h}; +} diff --git a/stratosphere/loader/source/ldr_shell.hpp b/stratosphere/loader/source/ldr_shell.hpp index 7cc95f858..7b1c153d2 100644 --- a/stratosphere/loader/source/ldr_shell.hpp +++ b/stratosphere/loader/source/ldr_shell.hpp @@ -20,7 +20,9 @@ enum ShellServiceCmd { Shell_Cmd_AddTitleToLaunchQueue = 0, - Shell_Cmd_ClearLaunchQueue = 1 + Shell_Cmd_ClearLaunchQueue = 1, + + Shell_Cmd_AtmosphereSetExternalContentSource = 65000, }; class ShellService final : public IServiceObject { @@ -39,4 +41,7 @@ class ShellService final : public IServiceObject { /* Actual commands. */ std::tuple<Result> add_title_to_launch_queue(u64 args_size, u64 tid, InPointer<char> args); std::tuple<Result> clear_launch_queue(u64 dat); + + /* Atmosphere commands. */ + std::tuple<Result, MovedHandle> set_external_content_source(u64 tid); }; From 058f7350311144d427b5ff33ea40c28b44f75900 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 17:25:36 -0700 Subject: [PATCH 143/489] libstratosphere: refactor everything --- .../libstratosphere/include/stratosphere.hpp | 25 +- .../include/stratosphere/domainowner.hpp | 79 --- .../include/stratosphere/event.hpp | 127 ++++ .../include/stratosphere/firmware_version.hpp | 49 ++ .../include/stratosphere/hossynch.hpp | 25 + .../include/stratosphere/ievent.hpp | 68 -- .../include/stratosphere/ipc.hpp | 22 + .../include/stratosphere/ipc/ipc_buffers.hpp | 117 ++++ .../stratosphere/ipc/ipc_domain_object.hpp | 128 ++++ .../include/stratosphere/ipc/ipc_out.hpp | 75 +++ .../ipc_response_context.hpp} | 37 +- .../stratosphere/ipc/ipc_serialization.hpp | 629 ++++++++++++++++++ .../stratosphere/ipc/ipc_service_object.hpp | 129 ++++ .../stratosphere/ipc/ipc_service_session.hpp | 358 ++++++++++ .../ipc_session_manager_base.hpp} | 27 +- .../include/stratosphere/ipc/ipc_special.hpp | 144 ++++ .../ipc_templating_old.hpp} | 2 +- .../include/stratosphere/ipcsession.hpp | 47 -- .../include/stratosphere/iserviceobject.hpp | 40 -- .../include/stratosphere/isession.hpp | 294 -------- .../include/stratosphere/iwaitable.hpp | 54 +- .../include/stratosphere/mitm.hpp | 26 + .../imitmserviceobject.hpp} | 24 +- .../stratosphere/mitm/mitm_query_service.hpp | 50 ++ .../include/stratosphere/mitm/mitm_server.hpp | 100 +++ .../stratosphere/mitm/mitm_session.hpp | 313 +++++++++ .../include/stratosphere/mitm/sm_mitm.h | 24 + .../multithreadedwaitablemanager.hpp | 58 -- .../include/stratosphere/scope_guard.hpp | 61 ++ .../stratosphere/{iserver.hpp => servers.hpp} | 60 +- .../include/stratosphere/services.hpp | 21 + .../smm_ams.h} | 27 +- .../include/stratosphere/systemevent.hpp | 42 -- .../include/stratosphere/waitable_manager.hpp | 330 +++++++++ ...agerbase.hpp => waitable_manager_base.hpp} | 12 +- .../include/stratosphere/waitablemanager.hpp | 48 -- .../source/mitm_query_service.cpp | 42 ++ .../source/multithreadedwaitablemanager.cpp | 119 ---- stratosphere/libstratosphere/source/sm_mitm.c | 190 ++++++ stratosphere/libstratosphere/source/smm_ams.c | 69 ++ .../source/waitablemanager.cpp | 105 --- 41 files changed, 3184 insertions(+), 1013 deletions(-) delete mode 100644 stratosphere/libstratosphere/include/stratosphere/domainowner.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/event.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ievent.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp rename stratosphere/libstratosphere/include/stratosphere/{managedportserver.hpp => ipc/ipc_response_context.hpp} (52%) create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp rename stratosphere/libstratosphere/include/stratosphere/{serviceserver.hpp => ipc/ipc_session_manager_base.hpp} (55%) create mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp rename stratosphere/libstratosphere/include/stratosphere/{ipc_templating.hpp => ipc/ipc_templating_old.hpp} (99%) delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/iserviceobject.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/isession.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm.hpp rename stratosphere/libstratosphere/include/stratosphere/{existingportserver.hpp => mitm/imitmserviceobject.hpp} (61%) create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/sm_mitm.h delete mode 100644 stratosphere/libstratosphere/include/stratosphere/multithreadedwaitablemanager.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp rename stratosphere/libstratosphere/include/stratosphere/{iserver.hpp => servers.hpp} (54%) create mode 100644 stratosphere/libstratosphere/include/stratosphere/services.hpp rename stratosphere/libstratosphere/include/stratosphere/{servicesession.hpp => services/smm_ams.h} (56%) delete mode 100644 stratosphere/libstratosphere/include/stratosphere/systemevent.hpp create mode 100644 stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp rename stratosphere/libstratosphere/include/stratosphere/{waitablemanagerbase.hpp => waitable_manager_base.hpp} (80%) delete mode 100644 stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp create mode 100644 stratosphere/libstratosphere/source/mitm_query_service.cpp delete mode 100644 stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp create mode 100644 stratosphere/libstratosphere/source/sm_mitm.c create mode 100644 stratosphere/libstratosphere/source/smm_ams.c delete mode 100644 stratosphere/libstratosphere/source/waitablemanager.cpp diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp index 041d72741..503f6f7f1 100644 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -16,22 +16,17 @@ #pragma once -#include "stratosphere/ipc_templating.hpp" +#include "stratosphere/version_check.hpp" +#include "stratosphere/scope_guard.hpp" -#include "stratosphere/iwaitable.hpp" -#include "stratosphere/iserviceobject.hpp" -#include "stratosphere/iserver.hpp" -#include "stratosphere/ipcsession.hpp" -#include "stratosphere/servicesession.hpp" -#include "stratosphere/serviceserver.hpp" -#include "stratosphere/managedportserver.hpp" -#include "stratosphere/existingportserver.hpp" - -#include "stratosphere/ievent.hpp" -#include "stratosphere/systemevent.hpp" #include "stratosphere/hossynch.hpp" +#include "stratosphere/iwaitable.hpp" +#include "stratosphere/event.hpp" -#include "stratosphere/waitablemanager.hpp" -#include "stratosphere/multithreadedwaitablemanager.hpp" +#include "stratosphere/waitable_manager.hpp" -#include "stratosphere/version_check.hpp" \ No newline at end of file +#include "stratosphere/ipc.hpp" + +#include "stratosphere/mitm.hpp" + +#include "stratosphere/services.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp b/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp deleted file mode 100644 index 74500eb63..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/domainowner.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <algorithm> -#include <memory> -#include <type_traits> - -#include "iserviceobject.hpp" - -#define DOMAIN_ID_MAX 0x1000 - -class IServiceObject; - -class DomainOwner { - private: - std::array<std::shared_ptr<IServiceObject>, DOMAIN_ID_MAX> domain_objects; - public: - /* Shared ptrs should auto delete here. */ - virtual ~DomainOwner() = default; - - std::shared_ptr<IServiceObject> get_domain_object(unsigned int i) { - if (i < DOMAIN_ID_MAX) { - return domain_objects[i]; - } - return nullptr; - } - - Result reserve_object(std::shared_ptr<IServiceObject> object, unsigned int *out_i) { - auto object_it = std::find(domain_objects.begin() + 4, domain_objects.end(), nullptr); - if (object_it == domain_objects.end()) { - return 0x1900B; - } - - *out_i = std::distance(domain_objects.begin(), object_it); - *object_it = object; - object->set_owner(this); - return 0; - } - - Result set_object(std::shared_ptr<IServiceObject> object, unsigned int i) { - if (domain_objects[i] == nullptr) { - domain_objects[i] = object; - object->set_owner(this); - return 0; - } - return 0x1900B; - } - - unsigned int get_object_id(std::shared_ptr<IServiceObject> object) { - auto object_it = std::find(domain_objects.begin(), domain_objects.end(), object); - return std::distance(domain_objects.begin(), object_it); - } - - void delete_object(unsigned int i) { - domain_objects[i].reset(); - } - - void delete_object(std::shared_ptr<IServiceObject> object) { - auto object_it = std::find(domain_objects.begin(), domain_objects.end(), object); - if (object_it != domain_objects.end()) { - object_it->reset(); - } - } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/event.hpp b/stratosphere/libstratosphere/include/stratosphere/event.hpp new file mode 100644 index 000000000..ba726d557 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/event.hpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <algorithm> +#include <vector> + +#include "iwaitable.hpp" + +class IEvent : public IWaitable { + public: + /* Information members. */ + Handle r_h; + Handle w_h; + bool autoclear; + public: + IEvent(bool a = false) : r_h(INVALID_HANDLE), w_h(INVALID_HANDLE), autoclear(a) { } + IEvent(Handle r, bool a = false) : r_h(r), w_h(INVALID_HANDLE), autoclear(a) { } + IEvent(Handle r, Handle w, bool a = false) : r_h(r), w_h(w), autoclear(a) { } + + ~IEvent() { + if (r_h != INVALID_HANDLE) { + svcCloseHandle(r_h); + } + if (w_h != INVALID_HANDLE) { + svcCloseHandle(w_h); + } + } + + /* Make it non-copyable */ + IEvent() = delete; + IEvent(const IEvent &) = delete; + IEvent& operator=(const IEvent&) = delete; + + + bool IsAutoClear() { + return this->autoclear; + } + + void Clear() { + std::scoped_lock<HosMutex> lock(this->sig_lock); + this->is_signaled = false; + if (this->r_h != INVALID_HANDLE) { + svcResetSignal(this->r_h); + } + } + + void Signal() { + std::scoped_lock<HosMutex> lock(this->sig_lock); + + if (this->w_h == INVALID_HANDLE && this->r_h != INVALID_HANDLE) { + /* We can't signal an event if we only have a read handle. */ + std::abort(); + } + + if (this->w_h == INVALID_HANDLE && this->is_signaled) { + return; + } + + this->is_signaled = true; + + if (this->w_h != INVALID_HANDLE) { + svcSignalEvent(this->w_h); + } else { + this->NotifyManagerSignaled(); + } + } + + virtual Result HandleSignaled(u64 timeout) = 0; + + /* IWaitable */ + virtual Handle GetHandle() override { + return this->r_h; + } +}; + +template<class F> +class HosEvent : public IEvent { + private: + F callback; + public: + HosEvent(F f, bool a = false) : IEvent(a), callback(std::move(f)) { } + HosEvent(Handle r, F f, bool a = false) : IEvent(r, a), callback(std::move(f)) { } + HosEvent(Handle r, Handle w, F f, bool a = false) : IEvent(r, w, a), callback(std::move(f)) { } + + virtual Result HandleSignaled(u64 timeout) override { + if (this->IsAutoClear()) { + this->Clear(); + } + return this->callback(timeout); + } +}; + +template <class F> +static IEvent *CreateHosEvent(F f, bool autoclear = false) { + return new HosEvent<F>(INVALID_HANDLE, INVALID_HANDLE, std::move(f), autoclear); +} + +template <class F> +static IEvent *CreateSystemEvent(F f, bool autoclear = false) { + + Handle w_h, r_h; + if (R_FAILED(svcCreateEvent(&w_h, &r_h))) { + std::abort(); + } + + return new HosEvent<F>(r_h, w_h, std::move(f), autoclear); +} + +template <bool a = false> +static IEvent *CreateWriteOnlySystemEvent() { + return CreateSystemEvent([](u64 timeout) { std::abort(); return 0; }, a); +} diff --git a/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp b/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp new file mode 100644 index 000000000..312c68c67 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +enum FirmwareVersion : u32 { + FirmwareVersion_Min = 0, + FirmwareVersion_100 = FirmwareVersion_Min, + FirmwareVersion_200 = 1, + FirmwareVersion_300 = 2, + FirmwareVersion_400 = 3, + FirmwareVersion_500 = 4, + FirmwareVersion_600 = 5, + FirmwareVersion_Current = FirmwareVersion_600, + FirmwareVersion_Max = 32, +}; + +static inline FirmwareVersion GetRuntimeFirmwareVersion() { + FirmwareVersion fw = FirmwareVersion_Min; + if (kernelAbove200()) { + fw = FirmwareVersion_200; + } + if (kernelAbove300()) { + fw = FirmwareVersion_300; + } + if (kernelAbove400()) { + fw = FirmwareVersion_400; + } + if (kernelAbove500()) { + fw = FirmwareVersion_500; + } + if (kernelAbove600()) { + fw = FirmwareVersion_600; + } + return fw; +} diff --git a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp index b923a4ec1..73ca16d76 100644 --- a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp @@ -16,6 +16,7 @@ #pragma once #include <switch.h> +#include <mutex> class HosMutex { private: @@ -40,6 +41,18 @@ class HosMutex { return mutexTryLock(GetMutex()); } + void Lock() { + lock(); + } + + void Unlock() { + unlock(); + } + + bool TryLock() { + return try_lock(); + } + friend class HosCondVar; }; @@ -65,6 +78,18 @@ class HosRecursiveMutex { bool try_lock() { return rmutexTryLock(GetMutex()); } + + void Lock() { + lock(); + } + + void Unlock() { + unlock(); + } + + bool TryLock() { + return try_lock(); + } }; class HosCondVar { diff --git a/stratosphere/libstratosphere/include/stratosphere/ievent.hpp b/stratosphere/libstratosphere/include/stratosphere/ievent.hpp deleted file mode 100644 index d1c93ef63..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ievent.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <algorithm> -#include <vector> - -#include "iwaitable.hpp" - -typedef Result (*EventCallback)(void *arg, Handle *handles, size_t num_handles, u64 timeout); - -class IEvent : public IWaitable { - protected: - std::vector<Handle> handles; - EventCallback callback; - void *arg; - - public: - IEvent(Handle wait_h, void *a, EventCallback callback) { - if (wait_h) { - this->handles.push_back(wait_h); - } - this->arg = a; - this->callback = callback; - } - - ~IEvent() { - std::for_each(handles.begin(), handles.end(), svcCloseHandle); - } - - virtual Result signal_event() = 0; - - /* IWaitable */ - virtual Handle get_handle() { - if (handles.size() > 0) { - return this->handles[0]; - } - return 0; - } - - - virtual void handle_deferred() { - /* TODO: Panic, because we can never defer an event. */ - } - - virtual Result handle_signaled(u64 timeout) { - return this->callback(this->arg, this->handles.data(), this->handles.size(), timeout); - } - - static Result PanicCallback(void *arg, Handle *handles, size_t num_handles, u64 timeout) { - /* TODO: Panic. */ - return 0xCAFE; - } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc.hpp new file mode 100644 index 000000000..e035fda52 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc.hpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "ipc/ipc_service_object.hpp" +#include "ipc/ipc_serialization.hpp" + +#include "ipc/ipc_service_session.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp new file mode 100644 index 000000000..6bf2f71c0 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <type_traits> + +enum class IpcBufferType { + InBuffer, + OutBuffer, + InPointer, + OutPointer, +}; + +/* Base for In/Out Buffers. */ +struct IpcBufferBase {}; + +struct InOutBufferBase : public IpcBufferBase {}; + +/* Represents an A descriptor. */ +struct InBufferBase : public InOutBufferBase {}; + +template <typename T, BufferType e_t = BufferType_Normal> +struct InBuffer : public InBufferBase { + T *buffer; + size_t num_elements; + BufferType type; + static const BufferType expected_type = e_t; + + /* Convenience. */ + T& operator[](size_t i) const { + return buffer[i]; + } + + InBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } +}; + +/* Represents a B descriptor. */ +struct OutBufferBase : public InOutBufferBase {}; + +template <typename T, BufferType e_t = BufferType_Normal> +struct OutBuffer : OutBufferBase { + T *buffer; + size_t num_elements; + BufferType type; + static const BufferType expected_type = e_t; + + /* Convenience. */ + T& operator[](size_t i) const { + return buffer[i]; + } + + OutBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } +}; + +/* Represents an X descriptor. */ +struct InPointerBase : public IpcBufferBase {}; + +template <typename T> +struct InPointer : public InPointerBase { + T *pointer; + size_t num_elements; + + /* Convenience. */ + T& operator[](size_t i) const { + return pointer[i]; + } + + InPointer(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } +}; + +/* Represents a C descriptor. */ +struct OutPointerWithServerSizeBase : public IpcBufferBase {}; + +template <typename T, size_t N> +struct OutPointerWithServerSize : public OutPointerWithServerSizeBase { + T *pointer; + static const size_t num_elements = N; + static const size_t element_size = sizeof(T); + + /* Convenience. */ + T& operator[](size_t i) const { + return pointer[i]; + } + + OutPointerWithServerSize(void *p) : pointer((T *)p) { } + OutPointerWithServerSize(void *p, size_t n) : pointer((T *)p) { } +}; + +struct OutPointerWithClientSizeBase : public IpcBufferBase {}; + +/* Represents a C descriptor with size in raw data. */ +template <typename T> +struct OutPointerWithClientSize : public OutPointerWithClientSizeBase { + T *pointer; + size_t num_elements; + + /* Convenience. */ + T& operator[](size_t i) const { + return pointer[i]; + } + + OutPointerWithClientSize(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp new file mode 100644 index 000000000..1394fc095 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <algorithm> +#include <memory> +#include <type_traits> + +#include "ipc_service_object.hpp" + +class IDomainObject; + +class DomainManager { + public: + virtual std::shared_ptr<IDomainObject> AllocateDomain() = 0; + virtual void FreeDomain(IDomainObject *domain) = 0; + virtual Result ReserveObject(IDomainObject *domain, u32 *out_object_id) = 0; + virtual Result ReserveSpecificObject(IDomainObject *domain, u32 object_id) = 0; + virtual void SetObject(IDomainObject *domain, u32 object_id, ServiceObjectHolder&& holder) = 0; + virtual ServiceObjectHolder *GetObject(IDomainObject *domain, u32 object_id) = 0; + virtual Result FreeObject(IDomainObject *domain, u32 object_id) = 0; + virtual Result ForceFreeObject(u32 object_id) = 0; +}; + +class IDomainObject : public IServiceObject { + private: + DomainManager *manager; + public: + IDomainObject(DomainManager *m) : manager(m) {} + + virtual ~IDomainObject() override { + this->manager->FreeDomain(this); + } + + DomainManager *GetManager() { + return this->manager; + } + + ServiceObjectHolder *GetObject(u32 object_id) { + return this->manager->GetObject(this, object_id); + } + + Result ReserveObject(u32 *out_object_id) { + return this->manager->ReserveObject(this, out_object_id); + } + + Result ReserveSpecificObject(u32 object_id) { + return this->manager->ReserveSpecificObject(this, object_id); + } + + void SetObject(u32 object_id, ServiceObjectHolder&& holder) { + this->manager->SetObject(this, object_id, std::move(holder)); + } + + Result FreeObject(u32 object_id) { + return this->manager->FreeObject(this, object_id); + } + + Result ForceFreeObject(u32 object_id) { + return this->manager->ForceFreeObject(object_id); + } + + public: + DEFINE_SERVICE_DISPATCH_TABLE { + /* IDomainObject has no callable functions. */ + }; +}; + +static constexpr bool IsDomainObject(ServiceObjectHolder &holder) { + return holder.GetServiceId() == ServiceObjectId<IDomainObject>(); +} + +static constexpr bool IsDomainObject(ServiceObjectHolder *holder) { + return holder->GetServiceId() == ServiceObjectId<IDomainObject>(); +} + +/* Out for service impl. */ +template <typename ServiceImpl> +class Out<std::shared_ptr<ServiceImpl>> : public OutSessionTag { + static_assert(std::is_base_of_v<IServiceObject, ServiceImpl>, "OutSessions must be shared_ptr<IServiceObject>!"); + + template<typename, typename> + friend class Out; + + private: + std::shared_ptr<ServiceImpl> *srv; + IDomainObject *domain = nullptr; + u32 *object_id = nullptr; + public: + Out<std::shared_ptr<ServiceImpl>>(std::shared_ptr<IServiceObject> *s, IDomainObject *dm, u32 *o) : srv(reinterpret_cast<std::shared_ptr<ServiceImpl> *>(s)), domain(dm), object_id(o) { } + + ServiceObjectHolder GetHolder() { + std::shared_ptr<ServiceImpl> clone = *srv; + return ServiceObjectHolder(std::move(clone)); + } + + bool IsDomain() { + return domain != nullptr; + } + + u32 GetObjectId() { + return *object_id; + } + + void ChangeObjectId(u32 o) { + domain->ForceFreeObject(*object_id); + domain->ReserveSpecificObject(o); + *object_id = o; + } + + void SetValue(std::shared_ptr<ServiceImpl> &&s) { + *this->srv = std::move(s); + } +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp new file mode 100644 index 000000000..fbd186d28 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <type_traits> + +/* Declare false allowed struct. */ +template <typename> +struct AllowedOut : std::false_type {}; + +struct OutDataTag{}; +struct OutHandleTag{}; +struct OutSessionTag{}; + +/* Define out struct, so that we can get errors on enable_if */ +template <typename T, typename Allowed = void> +class Out { + static_assert(std::is_pod<T>::value && !std::is_pod<T>::value, "Invalid IPC Out Type!"); +}; + +template <typename T> +class Out<T, typename std::enable_if<std::is_trivial<T>::value || AllowedOut<T>::value>::type> : public OutDataTag { +private: + T *obj; +public: + Out(T *o) : obj(o) { } + + void SetValue(const T& t) { + *obj = t; + } + + const T& GetValue() { + return *obj; + } + + T *GetPointer() { + return obj; + } + + /* Convenience operators. */ + T& operator*() { + return *obj; + } + + T* operator->() { + return obj; + } +}; + +template <typename T> +class Out<T*> { + static_assert(std::is_pod<T>::value && !std::is_pod<T>::value, "Invalid IPC Out Type (Raw Pointer)!"); +}; + +template <typename T> +struct OutHelper; + +template <typename T> +struct OutHelper<Out<T>> { + using type = T; +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp similarity index 52% rename from stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp rename to stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp index f61545f74..4e2ed8345 100644 --- a/stratosphere/libstratosphere/include/stratosphere/managedportserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp @@ -16,18 +16,29 @@ #pragma once #include <switch.h> -#include "iserver.hpp" -template <typename T> -class ManagedPortServer : public IServer<T> { - public: - ManagedPortServer(const char *service_name, unsigned int max_s, bool s_d = false) : IServer<T>(service_name, max_s, s_d) { - if (R_FAILED(svcManageNamedPort(&this->port_handle, service_name, this->max_sessions))) { - /* TODO: panic */ - } - } - - ISession<T> *get_new_session(Handle session_h) override { - return new ServiceSession<T>(this, session_h, 0); - } +#include "ipc_service_object.hpp" +#include "ipc_domain_object.hpp" + +#include "ipc_special.hpp" + +#include "ipc_session_manager_base.hpp" + +struct IpcResponseContext { + /* Request/Reply data. */ + IpcParsedCommand request; + IpcCommand reply; + u8 out_data[0x100]; + std::shared_ptr<IServiceObject> *out_objs[8]; + Handle out_object_server_handles[8]; + IpcHandle out_handles[8]; + u32 out_object_ids[8]; + IpcCommandType cmd_type; + u64 cmd_id; + Result rc; + /* Context. */ + SessionManagerBase *manager; + ServiceObjectHolder *obj_holder; + unsigned char *pb; + size_t pb_size; }; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp new file mode 100644 index 000000000..93c894af3 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp @@ -0,0 +1,629 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <cstdlib> +#include <cstring> +#include <tuple> +#include "../../boost/callable_traits.hpp" +#include <type_traits> +#include <memory> + +#include "ipc_out.hpp" +#include "ipc_buffers.hpp" +#include "ipc_special.hpp" + +#include "ipc_domain_object.hpp" + +#include "ipc_response_context.hpp" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +template<typename Tuple> +struct PopFront; + +template<typename Head, typename... Tail> +struct PopFront<std::tuple<Head, Tail...>> { + using type = std::tuple<Tail...>; +}; + +template <typename ...> struct WhichType; + +template <typename...> +struct TypeList{}; + +template <typename... T1s, typename... T2s> +constexpr auto Concatenate(TypeList<T1s...>, TypeList<T2s...>) { + return TypeList<T1s..., T2s...>{}; +} + +template <template <typename> typename Condition, typename R> +constexpr auto FilterTypes(R result, TypeList<>) { + return result; +} + +template <template <typename> typename Condition, typename R, typename T, typename... Ts> +constexpr auto FilterTypes(R result, TypeList<T, Ts...>) { + if constexpr (Condition<T>{}) + return FilterTypes<Condition>(Concatenate(result, TypeList<T>{}), TypeList<Ts...>{}); + else + return FilterTypes<Condition>(result, TypeList<Ts...>{}); +} + +template<typename Types> struct TypeListToTuple; + +template<typename... Types> +struct TypeListToTuple<TypeList<Types...>> { + using type = std::tuple<Types...>; +}; + +template <template <typename> typename Condition, typename... Types> +using FilteredTypes = typename TypeListToTuple<std::decay_t<decltype(FilterTypes<Condition>(TypeList<>{}, TypeList<Types...>{}))>>::type; + +enum class ArgType { + InData, + OutData, + InHandle, + OutHandle, + InSession, + OutSession, + PidDesc, + InBuffer, + OutBuffer, + InPointer, + OutPointerClientSize, + OutPointerServerSize, +}; + +template<typename X> +constexpr ArgType GetArgType() { + if constexpr (std::is_base_of_v<OutDataTag, X>) { + return ArgType::OutData; + } else if constexpr (std::is_base_of_v<OutSessionTag, X>) { + return ArgType::OutSession; + } else if constexpr (std::is_base_of_v<OutHandleTag, X>) { + return ArgType::OutHandle; + } else if constexpr (std::is_base_of_v<InBufferBase, X>) { + return ArgType::InBuffer; + } else if constexpr (std::is_base_of_v<OutBufferBase, X>) { + return ArgType::OutBuffer; + } else if constexpr (std::is_base_of_v<InPointerBase, X>) { + return ArgType::InPointer; + } else if constexpr (std::is_base_of_v<OutPointerWithClientSizeBase, X>) { + return ArgType::OutPointerClientSize; + } else if constexpr (std::is_base_of_v<OutPointerWithServerSizeBase, X>) { + return ArgType::OutPointerServerSize; + } else if constexpr (std::is_base_of_v<PidDescriptorTag, X>) { + return ArgType::PidDesc; + } else if constexpr (std::is_base_of_v<IpcHandleTag, X>) { + return ArgType::InHandle; + } else if constexpr (std::is_trivial_v<X> && !std::is_pointer_v<X>) { + return ArgType::InData; + } else { + static_assert(std::is_pod_v<X> && !std::is_pod_v<X>, "Unhandled InSession!"); + return ArgType::InSession; + } +} + +template<ArgType ArgT> +struct ArgTypeFilter { + template<typename X> + using type = std::conditional_t<GetArgType<X>() == ArgT, std::true_type, std::false_type>; +}; + +template<ArgType ArgT> +struct IsArgTypeBuffer { + static constexpr bool value = ArgT == ArgType::InBuffer || ArgT == ArgType::OutBuffer || ArgT == ArgType::InPointer || ArgT == ArgType::OutPointerClientSize || ArgT == ArgType::OutPointerServerSize; +}; + +struct ArgTypeBufferFilter { + template<typename X> + using type = std::conditional_t<IsArgTypeBuffer<GetArgType<X>()>::value, std::true_type, std::false_type>; +}; + +template<ArgType ArgT> +struct IsArgTypeInData { + static constexpr bool value = ArgT == ArgType::InData || ArgT == ArgType::PidDesc; +}; + +struct ArgTypeInDataFilter { + template<typename X> + using type = std::conditional_t<IsArgTypeInData<GetArgType<X>()>::value, std::true_type, std::false_type>; +}; + +template<typename T> +struct RawDataHelper { + static_assert(GetArgType<T>() == ArgType::InData || GetArgType<T>() == ArgType::PidDesc); + static constexpr size_t align = (GetArgType<T>() == ArgType::InData) ? __alignof__(T) : __alignof__(u64); + static constexpr size_t size = (GetArgType<T>() == ArgType::InData) ? sizeof(T) : sizeof(u64); +}; + +template<typename T> +struct RawDataHelper<Out<T>> { + static_assert(GetArgType<T>() == ArgType::InData); + static constexpr size_t align = __alignof(T); + static constexpr size_t size = sizeof(T); +}; + +template<typename T> +struct RawSizeElementAdder { + static constexpr size_t GetUpdateElementSize(size_t &size) { + constexpr size_t t_align = RawDataHelper<T>::align; + constexpr size_t t_size = RawDataHelper<T>::size; + if (size % t_align == 0) { + size += t_align - (size % t_align); + } + size += t_size; + return size; + } +}; + +template<typename Ts> +struct GetRawDataSize; + +template<typename... Ts> +struct GetRawDataSize<std::tuple<Ts...>> { + static constexpr size_t Size() { + if constexpr (sizeof...(Ts) == 0) { + return 0; + } else { + size_t s = 0; + size_t ends[] = { RawSizeElementAdder<Ts>::GetUpdateElementSize(s)... }; + return (ends[sizeof...(Ts)-1] + 3) & ~3; + } + } +}; + +template <typename _Args, typename _ReturnType> +struct CommandMetaInfo; + +template<typename... _Args, typename _ReturnType> +struct CommandMetaInfo<std::tuple<_Args...>, _ReturnType> { + using Args = std::tuple<_Args...>; + using ReturnType = _ReturnType; + + static constexpr bool ReturnsResult = std::is_same_v<ReturnType, Result>; + static constexpr bool ReturnsVoid = std::is_same_v<ReturnType, void>; + + using InDatas = FilteredTypes<ArgTypeInDataFilter::type, _Args...>; + using OutDatas = FilteredTypes<ArgTypeFilter<ArgType::OutData>::type, _Args...>; + using InHandles = FilteredTypes<ArgTypeFilter<ArgType::InHandle>::type, _Args...>; + using OutHandles = FilteredTypes<ArgTypeFilter<ArgType::OutHandle>::type, _Args...>; + using InSessions = FilteredTypes<ArgTypeFilter<ArgType::InSession>::type, _Args...>; + using OutSessions = FilteredTypes<ArgTypeFilter<ArgType::OutSession>::type, _Args...>; + using PidDescs = FilteredTypes<ArgTypeFilter<ArgType::PidDesc>::type, _Args...>; + + using InBuffers = FilteredTypes<ArgTypeFilter<ArgType::InBuffer>::type, _Args...>; + using OutBuffers = FilteredTypes<ArgTypeFilter<ArgType::OutBuffer>::type, _Args...>; + using InPointers = FilteredTypes<ArgTypeFilter<ArgType::InPointer>::type, _Args...>; + using ClientSizeOutPointers = FilteredTypes<ArgTypeFilter<ArgType::OutPointerClientSize>::type, _Args...>; + using ServerSizeOutPointers = FilteredTypes<ArgTypeFilter<ArgType::OutPointerServerSize>::type, _Args...>; + using Buffers = FilteredTypes<ArgTypeBufferFilter::type, _Args...>; + + static constexpr size_t NumInDatas = std::tuple_size_v<InDatas>; + static constexpr size_t NumOutDatas = std::tuple_size_v<OutDatas>; + static constexpr size_t NumInHandles = std::tuple_size_v<InHandles>; + static constexpr size_t NumOutHandles = std::tuple_size_v<OutHandles>; + static constexpr size_t NumInSessions = std::tuple_size_v<InSessions>; + static constexpr size_t NumOutSessions = std::tuple_size_v<OutSessions>; + static constexpr size_t NumPidDescs = std::tuple_size_v<PidDescs>; + + static constexpr size_t NumInBuffers = std::tuple_size_v<InBuffers>; + static constexpr size_t NumOutBuffers = std::tuple_size_v<OutBuffers>; + static constexpr size_t NumInPointers = std::tuple_size_v<InPointers>; + static constexpr size_t NumClientSizeOutPointers = std::tuple_size_v<ClientSizeOutPointers>; + static constexpr size_t NumServerSizeOutPointers = std::tuple_size_v<ServerSizeOutPointers>; + static constexpr size_t NumBuffers = std::tuple_size_v<Buffers>; + + static_assert(NumInSessions == 0, "InSessions not yet supported!"); + static_assert(NumPidDescs == 0 || NumPidDescs == 1, "Methods can only take in 0 or 1 PIDs!"); + static_assert(NumBuffers <= 8, "Methods can only take in <= 8 Buffers!"); + static_assert(NumInHandles <= 8, "Methods can take in <= 8 Handles!"); + static_assert(NumOutHandles + NumOutSessions <= 8, "Methods can only return <= 8 Handles+Sessions!"); + + static constexpr size_t InRawArgSize = GetRawDataSize<InDatas>::Size(); + static constexpr size_t InRawArgSizeWithOutPointers = ((InRawArgSize + NumClientSizeOutPointers * sizeof(u16)) + 3) & ~3; + + static constexpr size_t OutRawArgSize = GetRawDataSize<OutDatas>::Size(); +}; + + +/* ================================================================================= */ +/* Actual wrapping implementation goes here. */ + +/* Validator. */ +struct Validator { + + template <typename T> + static constexpr bool ValidateCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& h_index, size_t& cur_c_size_offset, size_t& total_c_size) { + constexpr ArgType argT = GetArgType<T>(); + if constexpr (argT == ArgType::InBuffer) { + return ctx->request.Buffers[a_index] != nullptr && ctx->request.BufferDirections[a_index] == BufferDirection_Send && ctx->request.BufferTypes[a_index++] == T::expected_type; + } else if constexpr (argT == ArgType::OutBuffer) { + return ctx->request.Buffers[b_index] != nullptr && ctx->request.BufferDirections[b_index] == BufferDirection_Recv && ctx->request.BufferTypes[b_index++] == T::expected_type; + } else if constexpr (argT == ArgType::InPointer) { + return ctx->request.Statics[x_index++] != nullptr; + } else if constexpr (argT == ArgType::InHandle) { + if constexpr (std::is_same_v<T, MovedHandle>) { + return !ctx->request.WasHandleCopied[h_index++]; + } else if constexpr (std::is_same_v<T, CopiedHandle>) { + return ctx->request.WasHandleCopied[h_index++]; + } + } else { + if constexpr (argT == ArgType::OutPointerServerSize) { + total_c_size += T::num_elements * sizeof(T); + } else if constexpr (argT == ArgType::OutPointerServerSize) { + total_c_size += *((u16 *)((uintptr_t)(ctx->request.Raw) + 0x10 + cur_c_size_offset)); + cur_c_size_offset += sizeof(u16); + } + return true; + } + } + + template <typename Ts> + struct ValidateCommandTuple; + + template <typename ...Ts> + struct ValidateCommandTuple<std::tuple<Ts...>> { + static constexpr bool IsValid(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& h_index, size_t& cur_c_size_offset, size_t& total_c_size) { + return (ValidateCommandArgument<Ts>(ctx, a_index, b_index, x_index, h_index, cur_c_size_offset, total_c_size) && ...); + } + }; + + template<typename MetaInfo> + static constexpr Result Validate(IpcResponseContext *ctx) { + if (ctx->request.RawSize < MetaInfo::InRawArgSizeWithOutPointers) { + return 0xF601; + } + + if (ctx->request.NumBuffers != MetaInfo::NumInBuffers + MetaInfo::NumOutBuffers) { + return 0xF601; + } + + if (ctx->request.NumStatics != MetaInfo::NumInPointers) { + return 0xF601; + } + + if (ctx->request.NumStaticsOut != MetaInfo::NumClientSizeOutPointers + MetaInfo::NumServerSizeOutPointers) { + return 0xF601; + } + + if (ctx->request.NumHandles != MetaInfo::NumInHandles) { + return 0xF601; + } + + + if ((ctx->request.HasPid && MetaInfo::NumPidDescs == 0) || (!ctx->request.HasPid && MetaInfo::NumPidDescs != 0)) { + return 0xF601; + } + + if (((u32 *)ctx->request.Raw)[0] != SFCI_MAGIC) { + return 0xF601; + } + + size_t a_index = 0, b_index = MetaInfo::NumInBuffers, x_index = 0, h_index = 0; + size_t cur_c_size_offset = MetaInfo::InRawArgSize + (0x10 - ((uintptr_t)ctx->request.Raw - (uintptr_t)ctx->request.RawWithoutPadding)); + size_t total_c_size = 0; + + if (!ValidateCommandTuple<typename MetaInfo::Args>::IsValid(ctx, a_index, b_index, x_index, h_index, cur_c_size_offset, total_c_size)) { + return 0xF601; + } + + if (total_c_size > ctx->pb_size) { + return 0xF601; + } + + return 0; + } +}; + +/* ================================================================================= */ + +/* Decoder. */ +struct Decoder { + + template<typename T> + static constexpr T DecodeCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_rd_offset, size_t& out_rd_offset, size_t& pb_offset, size_t& c_sz_offset) { + constexpr ArgType argT = GetArgType<T>(); + if constexpr (argT == ArgType::InBuffer) { + const T& value = T(ctx->request.Buffers[a_index], ctx->request.BufferSizes[a_index], ctx->request.BufferTypes[a_index]); + ++a_index; + return value; + } else if constexpr (argT == ArgType::OutBuffer) { + const T& value = T(ctx->request.Buffers[b_index], ctx->request.BufferSizes[b_index], ctx->request.BufferTypes[b_index]); + ++b_index; + return value; + } else if constexpr (argT == ArgType::InPointer) { + const T& value = T(ctx->request.Statics[x_index], ctx->request.StaticSizes[x_index]); + ++x_index; + return value; + } else if constexpr (argT == ArgType::InHandle) { + return T(ctx->request.Handles[in_h_index++]); + } else if constexpr (argT == ArgType::OutHandle) { + return T(&ctx->out_handles[out_h_index++]); + } else if constexpr (argT == ArgType::PidDesc) { + constexpr size_t t_align = RawDataHelper<T>::align; + constexpr size_t t_size = RawDataHelper<T>::size; + if (in_rd_offset % t_align) { + in_rd_offset += (t_align - (in_rd_offset % t_align)); + } + uintptr_t ptr = ((uintptr_t)ctx->request.Raw + 0x10 + in_rd_offset); + in_rd_offset += t_size; + *(u64 *)ptr = ctx->request.Pid; + return T(ctx->request.Pid); + } else if constexpr (argT == ArgType::InData) { + constexpr size_t t_align = RawDataHelper<T>::align; + constexpr size_t t_size = RawDataHelper<T>::size; + if (in_rd_offset % t_align) { + in_rd_offset += (t_align - (in_rd_offset % t_align)); + } + uintptr_t ptr = ((uintptr_t)ctx->request.Raw + 0x10 + in_rd_offset); + in_rd_offset += t_size; + if constexpr (std::is_same_v<bool, T>) { + return *((u8 *)ptr) & 1; + } else { + return *((T *)ptr); + } + } else if constexpr (argT == ArgType::OutData) { + constexpr size_t t_align = RawDataHelper<T>::align; + constexpr size_t t_size = RawDataHelper<T>::size; + if (out_rd_offset % t_align) { + out_rd_offset += (t_align - (out_rd_offset % t_align)); + } + uintptr_t ptr = ((uintptr_t)ctx->out_data + out_rd_offset); + out_rd_offset += t_size; + return T(reinterpret_cast<typename OutHelper<T>::type *>(ptr)); + } else if constexpr (argT == ArgType::OutPointerClientSize || argT == ArgType::OutPointerServerSize) { + u16 sz; + if constexpr(argT == ArgType::OutPointerServerSize) { + sz = T::element_size; + } else { + sz = *(const u16 *)((uintptr_t)ctx->request.Raw + 0x10 + c_sz_offset); + } + u8* buf = ctx->pb + pb_offset; + c_sz_offset += sizeof(u16); + pb_offset += sz; + ipcAddSendStatic(&ctx->reply, buf, sz, c_index++); + return T(buf, sz); + } else if constexpr (argT == ArgType::OutSession) { + if (IsDomainObject(ctx->obj_holder)) { + const T& value = T(ctx->out_objs[out_obj_index], ctx->obj_holder->GetServiceObject<IDomainObject>(), &ctx->out_object_ids[out_obj_index]); + out_obj_index++; + return value; + } else { + const T& value = T(ctx->out_objs[out_obj_index], nullptr, 0); + out_obj_index++; + return value; + } + } + } + + template <typename Ts> + struct DecodeTuple; + + template <typename ...Ts> + struct DecodeTuple<std::tuple<Ts...>> { + static constexpr std::tuple<Ts...> GetArgs(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_rd_offset, size_t& out_rd_offset, size_t& pb_offset, size_t& c_sz_offset) { + return std::tuple<Ts... > { + DecodeCommandArgument<Ts>(ctx, a_index, b_index, x_index, c_index, in_h_index, out_h_index, out_obj_index, in_rd_offset, out_rd_offset, pb_offset, c_sz_offset) + ... + }; + } + }; + + + template<typename MetaInfo> + static constexpr typename MetaInfo::Args Decode(IpcResponseContext *ctx) { + size_t a_index = 0, b_index = MetaInfo::NumInBuffers, x_index = 0, c_index = 0, in_h_index = 0, out_h_index = 0, out_obj_index = 0; + size_t in_rd_offset = 0x0, out_rd_offset = 0, pb_offset = 0; + size_t c_sz_offset = MetaInfo::InRawArgSize + (0x10 - ((uintptr_t)ctx->request.Raw - (uintptr_t)ctx->request.RawWithoutPadding)); + return DecodeTuple<typename MetaInfo::Args>::GetArgs(ctx, a_index, b_index, x_index, c_index, in_h_index, out_h_index, out_obj_index, in_rd_offset, out_rd_offset, pb_offset, c_sz_offset); + } +}; + +/* ================================================================================= */ + +template<typename MetaInfo, typename T> +static constexpr void EncodeArgument(IpcResponseContext *ctx, size_t&out_obj_index, T& arg) { + constexpr ArgType argT = GetArgType<T>(); + if constexpr (argT == ArgType::OutHandle) { + if constexpr (std::is_same_v<MovedHandle, typename OutHelper<T>::type>) { + ipcSendHandleMove(&ctx->reply, arg.GetValue().handle); + } else { + ipcSendHandleCopy(&ctx->reply, arg.GetValue().handle); + } + } else if constexpr (argT == ArgType::OutSession) { + if (IsDomainObject(ctx->obj_holder)) { + auto domain = ctx->obj_holder->GetServiceObject<IDomainObject>(); + domain->SetObject(arg.GetObjectId(), std::move(arg.GetHolder())); + } else { + ctx->manager->AddSession(ctx->out_object_server_handles[out_obj_index++], std::move(arg.GetHolder())); + } + } +} + +template<typename MetaInfo, typename ArgsTuple> +struct Encoder; + +template <typename MetaInfo, typename ...Args> +struct Encoder<MetaInfo, std::tuple<Args...>> { + + static constexpr void EncodeFailure(IpcResponseContext *ctx, Result rc) { + memset(armGetTls(), 0, 0x100); + ipcInitialize(&ctx->reply); + struct { + u64 magic; + u64 result; + } *raw; + + if (IsDomainObject(ctx->obj_holder)) { + raw = (decltype(raw))ipcPrepareHeaderForDomain(&ctx->reply, sizeof(*raw), 0); + auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); + *resp_header = {0}; + } else { + raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)); + } + raw->magic = SFCO_MAGIC; + raw->result = rc; + } + + + + static constexpr void EncodeSuccess(IpcResponseContext *ctx, Args... args) { + size_t out_obj_index = 0; + + ((EncodeArgument<MetaInfo, Args>(ctx, out_obj_index, args)), ...); + + const bool is_domain = IsDomainObject(ctx->obj_holder); + + if (!is_domain) { + for (unsigned int i = 0; i < MetaInfo::NumOutSessions; i++) { + ipcSendHandleMove(&ctx->reply, ctx->out_handles[MetaInfo::NumOutHandles + i].handle); + } + } + + struct { + u64 magic; + u64 result; + } *raw; + if (is_domain) { + raw = (decltype(raw))ipcPrepareHeaderForDomain(&ctx->reply, sizeof(*raw) + MetaInfo::OutRawArgSize, 0); + auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); + *resp_header = {0}; + resp_header->NumObjectIds = MetaInfo::NumOutSessions; + } else { + raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)+ MetaInfo::OutRawArgSize); + } + + raw->magic = SFCO_MAGIC; + raw->result = 0; + + memcpy((void *)((uintptr_t)raw + sizeof(*raw)), ctx->out_data, MetaInfo::OutRawArgSize); + if (is_domain) { + memcpy((void *)((uintptr_t)raw + sizeof(*raw) + MetaInfo::OutRawArgSize), ctx->out_object_ids, sizeof(*ctx->out_object_ids) * MetaInfo::NumOutSessions); + } + } + +}; + +/* ================================================================================= */ + +template<auto IpcCommandImpl> +constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { + using InArgs = typename PopFront<typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>>::type; + using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; + using ClassType = typename boost::callable_traits::class_of_t<decltype(IpcCommandImpl)>; + + using CommandMetaData = CommandMetaInfo<InArgs, OutArgs>; + + static_assert(CommandMetaData::ReturnsResult || CommandMetaData::ReturnsVoid, "IpcCommandImpls must return Result or void"); + + ipcInitialize(&ctx->reply); + memset(ctx->out_data, 0, CommandMetaData::OutRawArgSize); + + Result rc = Validator::Validate<CommandMetaData>(ctx); + + if (R_FAILED(rc)) { + return 0xAAEE; + } + + ClassType *this_ptr = nullptr; + if (IsDomainObject(ctx->obj_holder)) { + this_ptr = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId)->GetServiceObject<ClassType>(); + } else { + this_ptr = ctx->obj_holder->GetServiceObject<ClassType>(); + } + if (this_ptr == nullptr) { + return 0xBBEE; + } + + std::shared_ptr<IServiceObject> out_objects[CommandMetaData::NumOutSessions]; + + /* Allocate out object IDs. */ + size_t num_out_objects; + if (IsDomainObject(ctx->obj_holder)) { + for (num_out_objects = 0; num_out_objects < CommandMetaData::NumOutSessions; num_out_objects++) { + if (R_FAILED((rc = ctx->obj_holder->GetServiceObject<IDomainObject>()->ReserveObject(&ctx->out_object_ids[num_out_objects])))) { + break; + } + ctx->out_objs[num_out_objects] = &out_objects[num_out_objects]; + } + } else { + for (num_out_objects = 0; num_out_objects < CommandMetaData::NumOutSessions; num_out_objects++) { + Handle server_h, client_h; + if (R_FAILED((rc = SessionManagerBase::CreateSessionHandles(&server_h, &client_h)))) { + break; + } + ctx->out_object_server_handles[num_out_objects] = server_h; + ctx->out_handles[CommandMetaData::NumOutHandles + num_out_objects].handle = client_h; + ctx->out_objs[num_out_objects] = &out_objects[num_out_objects]; + } + } + + ON_SCOPE_EXIT { + /* Clean up objects as necessary. */ + if (IsDomainObject(ctx->obj_holder) && R_FAILED(rc)) { + for (unsigned int i = 0; i < num_out_objects; i++) { + ctx->obj_holder->GetServiceObject<IDomainObject>()->FreeObject(ctx->out_object_ids[i]); + } + } else { + for (unsigned int i = 0; i < num_out_objects; i++) { + svcCloseHandle(ctx->out_object_server_handles[i]); + svcCloseHandle(ctx->out_handles[CommandMetaData::NumOutHandles + i].handle); + } + } + + for (unsigned int i = 0; i < num_out_objects; i++) { + ctx->out_objs[i] = nullptr; + } + }; + + if (R_SUCCEEDED(rc)) { + auto args = Decoder::Decode<CommandMetaData>(ctx); + + if constexpr (CommandMetaData::ReturnsResult) { + rc = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args); + } else { + std::apply( [=](auto&&... args) { (this_ptr->*IpcCommandImpl)(args...); }, args); + } + + if (R_SUCCEEDED(rc)) { + std::apply(Encoder<CommandMetaData, decltype(args)>::EncodeSuccess, std::tuple_cat(std::make_tuple(ctx), args)); + } else { + std::apply(Encoder<CommandMetaData, decltype(args)>::EncodeFailure, std::tuple_cat(std::make_tuple(ctx), std::make_tuple(rc))); + } + } else { + std::apply(Encoder<CommandMetaData, typename CommandMetaData::Args>::EncodeFailure, std::tuple_cat(std::make_tuple(ctx), std::make_tuple(rc))); + } + + return rc; +} + + +template <u32 c, auto CommandImpl, FirmwareVersion l = FirmwareVersion_Min, FirmwareVersion h = FirmwareVersion_Max> +inline static constexpr ServiceCommandMeta MakeServiceCommandMeta() { + return { + .fw_low = l, + .fw_high = h, + .cmd_id = c, + .handler = WrapIpcCommandImpl<CommandImpl>, + }; +}; + + +#pragma GCC diagnostic pop \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp new file mode 100644 index 000000000..979cd22a1 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <memory> +#include <type_traits> + +#include "ipc_out.hpp" + +#include "../firmware_version.hpp" + +class IpcResponseContext; + +struct ServiceCommandMeta { + FirmwareVersion fw_low = FirmwareVersion_Max; + FirmwareVersion fw_high = FirmwareVersion_Max; + u32 cmd_id = 0; + Result (*handler)(IpcResponseContext *) = nullptr; +}; + +class IServiceObject { + public: + virtual ~IServiceObject() { } +}; + +#define SERVICE_DISPATCH_TABLE_NAME s_DispatchTable +#define DEFINE_SERVICE_DISPATCH_TABLE static constexpr ServiceCommandMeta SERVICE_DISPATCH_TABLE_NAME[] + +template <typename T> +static constexpr size_t DispatchTableEntryCount() { + static_assert(std::is_base_of<IServiceObject, T>::value, "DispatchTable owners must derive from IServiceObject"); + return sizeof(T::SERVICE_DISPATCH_TABLE_NAME)/sizeof(ServiceCommandMeta); +} +template <typename T> +static constexpr const ServiceCommandMeta* DispatchTable() { + static_assert(std::is_base_of<IServiceObject, T>::value, "DispatchTable owners must derive from IServiceObject"); + return reinterpret_cast<const ServiceCommandMeta*>(&T::SERVICE_DISPATCH_TABLE_NAME); +} + +template <typename T> +static constexpr uintptr_t ServiceObjectId() { + static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); + return reinterpret_cast<uintptr_t>(&T::SERVICE_DISPATCH_TABLE_NAME); +} + +class ServiceObjectHolder { + private: + std::shared_ptr<IServiceObject> srv; + const ServiceCommandMeta *dispatch_table; + size_t entry_count; + + /* Private copy constructor. */ + ServiceObjectHolder(const ServiceObjectHolder& other) : srv(other.srv), dispatch_table(other.dispatch_table), entry_count(other.entry_count) { } + ServiceObjectHolder& operator=(const ServiceObjectHolder& other); + public: + /* Templated constructor ensures correct type id at runtime. */ + template <typename ServiceImpl> + explicit ServiceObjectHolder(std::shared_ptr<ServiceImpl>&& s) : srv(std::move(s)), dispatch_table(DispatchTable<ServiceImpl>()), entry_count(DispatchTableEntryCount<ServiceImpl>()) { } + + template <typename ServiceImpl> + ServiceImpl *GetServiceObject() { + if (GetServiceId() == ServiceObjectId<ServiceImpl>()) { + return static_cast<ServiceImpl *>(this->srv.get()); + } + return nullptr; + } + + template<typename ServiceImpl> + ServiceImpl *GetServiceObjectUnsafe() { + return static_cast<ServiceImpl *>(this->srv.get()); + } + + const ServiceCommandMeta *GetDispatchTable() { + return this->dispatch_table; + } + + size_t GetDispatchTableEntryCount() { + return this->entry_count; + } + + constexpr uintptr_t GetServiceId() { + return reinterpret_cast<uintptr_t>(this->dispatch_table); + } + + /* Default constructor, move constructor, move assignment operator. */ + ServiceObjectHolder() : srv(nullptr), dispatch_table(nullptr) { } + + ServiceObjectHolder(ServiceObjectHolder&& other) : srv(std::move(other.srv)), dispatch_table(std::move(other.dispatch_table)), entry_count(std::move(other.entry_count)) { } + + ServiceObjectHolder& operator=(ServiceObjectHolder&& other) { + this->srv = other.srv; + this->dispatch_table = other.dispatch_table; + this->entry_count = other.entry_count; + other.Reset(); + return *this; + } + + explicit operator bool() { + return this->srv != nullptr; + } + + bool operator!() { + return this->srv == nullptr; + } + + void Reset() { + this->srv.reset(); + this->dispatch_table = nullptr; + this->entry_count = 0; + } + + ServiceObjectHolder Clone() { + return ServiceObjectHolder(*this); + } +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp new file mode 100644 index 000000000..3b25e8721 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> + +#include "../iwaitable.hpp" +#include "ipc_service_object.hpp" +#include "ipc_serialization.hpp" + +enum HipcControlCommand : u32 { + HipcControlCommand_ConvertCurrentObjectToDomain = 0, + HipcControlCommand_CopyFromCurrentDomain = 1, + HipcControlCommand_CloneCurrentObject = 2, + HipcControlCommand_QueryPointerBufferSize = 3, + HipcControlCommand_CloneCurrentObjectEx = 4 +}; + + +#define RESULT_DEFER_SESSION (0x6580A) + + +class ServiceSession : public IWaitable +{ + protected: + Handle session_handle; + std::vector<unsigned char> pointer_buffer; + ServiceObjectHolder obj_holder; + ServiceObjectHolder control_holder = ServiceObjectHolder(std::make_shared<IHipcControlService>(this)); + u8 backup_tls[0x100]; + + ServiceSession(Handle s_h) : session_handle(s_h) { } + public: + template<typename T> + ServiceSession(Handle s_h, size_t pbs) : session_handle(s_h), pointer_buffer(pbs), obj_holder(std::make_shared<T>()) { } + + ServiceSession(Handle s_h, size_t pbs, ServiceObjectHolder &&h) : session_handle(s_h), pointer_buffer(pbs), obj_holder(std::move(h)) { } + + virtual ~ServiceSession() override { + svcCloseHandle(this->session_handle); + } + + SessionManagerBase *GetSessionManager() { + return static_cast<SessionManagerBase *>(this->GetManager()); + } + + DomainManager *GetDomainManager() { + return static_cast<DomainManager *>(this->GetSessionManager()); + } + + Result Receive() { + int handle_index; + /* Prepare pointer buffer... */ + IpcCommand c; + ipcInitialize(&c); + if (this->pointer_buffer.size() > 0) { + ipcAddRecvStatic(&c, this->pointer_buffer.data(), this->pointer_buffer.size(), 0); + ipcPrepareHeader(&c, 0); + + /* Fix libnx bug in serverside C descriptor handling. */ + ((u32 *)armGetTls())[1] &= 0xFFFFC3FF; + ((u32 *)armGetTls())[1] |= (2) << 10; + } else { + ipcPrepareHeader(&c, 0); + } + + /* Receive. */ + Result rc = svcReplyAndReceive(&handle_index, &this->session_handle, 1, 0, U64_MAX); + if (R_SUCCEEDED(rc)) { + std::memcpy(this->backup_tls, armGetTls(), sizeof(this->backup_tls)); + } + + return rc; + } + + Result Reply() { + int handle_index; + return svcReplyAndReceive(&handle_index, &this->session_handle, 0, this->session_handle, 0); + } + + /* For preparing basic replies. */ + Result PrepareBasicResponse(IpcResponseContext *ctx, Result rc) { + ipcInitialize(&ctx->reply); + struct { + u64 magic; + u64 result; + } *raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)); + + raw->magic = SFCO_MAGIC; + raw->result = rc; + return raw->result; + } + + Result PrepareBasicDomainResponse(IpcResponseContext *ctx, Result rc) { + ipcInitialize(&ctx->reply); + struct { + DomainResponseHeader hdr; + u64 magic; + u64 result; + } *raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)); + + raw->hdr = (DomainResponseHeader){0}; + raw->magic = SFCO_MAGIC; + raw->result = rc; + return raw->result; + } + + /* For making a new response context. */ + void InitializeResponseContext(IpcResponseContext *ctx) { + std::memset(ctx, 0, sizeof(*ctx)); + ctx->manager = this->GetSessionManager(); + ctx->obj_holder = &this->obj_holder; + ctx->pb = this->pointer_buffer.data(); + ctx->pb_size = this->pointer_buffer.size(); + } + + /* IWaitable */ + virtual Handle GetHandle() { + return this->session_handle; + } + + virtual Result GetResponse(IpcResponseContext *ctx) { + Result rc = 0xF601; + FirmwareVersion fw = GetRuntimeFirmwareVersion(); + + const ServiceCommandMeta *dispatch_table = ctx->obj_holder->GetDispatchTable(); + size_t entry_count = ctx->obj_holder->GetDispatchTableEntryCount(); + + if (IsDomainObject(ctx->obj_holder)) { + switch (ctx->request.InMessageType) { + case DomainMessageType_Invalid: + return 0xF601; + case DomainMessageType_Close: + return PrepareBasicDomainResponse(ctx, ctx->obj_holder->GetServiceObject<IDomainObject>()->FreeObject(ctx->request.InThisObjectId)); + case DomainMessageType_SendMessage: + { + auto sub_obj = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId); + if (sub_obj == nullptr) { + return PrepareBasicDomainResponse(ctx, 0x3D80B); + } + dispatch_table = sub_obj->GetDispatchTable(); + entry_count = sub_obj->GetDispatchTableEntryCount(); + } + } + } + + for (size_t i = 0; i < entry_count; i++) { + if (ctx->cmd_id == dispatch_table[i].cmd_id && dispatch_table[i].fw_low <= fw && fw <= dispatch_table[i].fw_high) { + rc = dispatch_table[i].handler(ctx); + break; + } + } + + return rc; + } + + virtual Result HandleReceived() { + IpcResponseContext ctx; + this->InitializeResponseContext(&ctx); + + ctx.cmd_type = (IpcCommandType)(*(u16 *)(armGetTls())); + + ctx.rc = 0; + + /* Parse based on command type. */ + switch (ctx.cmd_type) { + case IpcCommandType_Invalid: + case IpcCommandType_LegacyRequest: + case IpcCommandType_LegacyControl: + return 0xF601; + case IpcCommandType_Close: + { + /* Clean up gracefully. */ + PrepareBasicResponse(&ctx, 0); + this->Reply(); + } + return 0xF601; + case IpcCommandType_Control: + case IpcCommandType_ControlWithContext: + ctx.rc = ipcParse(&ctx.request); + ctx.obj_holder = &this->control_holder; + break; + case IpcCommandType_Request: + case IpcCommandType_RequestWithContext: + if (IsDomainObject(&this->obj_holder)) { + ctx.rc = ipcParseDomainRequest(&ctx.request); + } else { + ctx.rc = ipcParse(&ctx.request); + } + break; + default: + return 0xF601; + } + + + if (R_SUCCEEDED(ctx.rc)) { + ctx.cmd_id = ((u32 *)ctx.request.Raw)[2]; + this->PreProcessRequest(&ctx); + ctx.rc = this->GetResponse(&ctx); + } + + if (ctx.rc == RESULT_DEFER_SESSION) { + /* Session defer. */ + this->SetDeferred(true); + } else if (ctx.rc == 0xF601) { + /* Session close, nothing to do. */ + } else { + if (R_SUCCEEDED(ctx.rc)) { + this->PostProcessResponse(&ctx); + } + + ctx.rc = this->Reply(); + + if (ctx.rc == 0xEA01) { + ctx.rc = 0x0; + } + + this->CleanupResponse(&ctx); + } + + return ctx.rc; + } + + virtual void HandleDeferred() override { + memcpy(armGetTls(), this->backup_tls, sizeof(this->backup_tls)); + Result rc = this->HandleReceived(); + + if (rc != RESULT_DEFER_SESSION) { + this->SetDeferred(false); + if (rc == 0xF601) { + svcCloseHandle(this->GetHandle()); + } + } + } + + virtual Result HandleSignaled(u64 timeout) { + Result rc; + + if (R_SUCCEEDED(rc = this->Receive())) { + rc = this->HandleReceived(); + } + + return rc; + } + + virtual void PreProcessRequest(IpcResponseContext *ctx) { + /* ... */ + (void)(ctx); + } + + virtual void PostProcessResponse(IpcResponseContext *ctx) { + /* ... */ + (void)(ctx); + } + + virtual void CleanupResponse(IpcResponseContext *ctx) { + std::memset(this->backup_tls, 0, sizeof(this->backup_tls)); + } + + + public: + class IHipcControlService : public IServiceObject { + private: + ServiceSession *session; + public: + explicit IHipcControlService(ServiceSession *s) : session(s) { + + } + + virtual ~IHipcControlService() override { } + + Result ConvertCurrentObjectToDomain(Out<u32> object_id) { + /* Allocate new domain. */ + auto new_domain = this->session->GetDomainManager()->AllocateDomain(); + if (new_domain == nullptr) { + return 0x1900B; + } + + /* Reserve an object in the domain for our session. */ + u32 reserved_id; + Result rc = new_domain->ReserveObject(&reserved_id); + if (R_FAILED(rc)) { + return rc; + } + new_domain->SetObject(reserved_id, std::move(this->session->obj_holder)); + this->session->obj_holder = std::move(ServiceObjectHolder(std::move(new_domain))); + + /* Return the object id. */ + object_id.SetValue(reserved_id); + return 0; + } + + Result CopyFromCurrentDomain(Out<MovedHandle> out_h, u32 id) { + auto domain = this->session->obj_holder.GetServiceObject<IDomainObject>(); + if (domain == nullptr) { + return 0x3D60B; + } + + + auto object = domain->GetObject(id); + if (object == nullptr) { + return 0x3D80B; + } + + Handle server_h, client_h; + if (R_FAILED(SessionManagerBase::CreateSessionHandles(&server_h, &client_h))) { + /* N aborts here. Should we error code? */ + std::abort(); + } + + this->session->GetSessionManager()->AddSession(server_h, std::move(object->Clone())); + out_h.SetValue(client_h); + return 0; + } + + void CloneCurrentObject(Out<MovedHandle> out_h) { + Handle server_h, client_h; + if (R_FAILED(SessionManagerBase::CreateSessionHandles(&server_h, &client_h))) { + /* N aborts here. Should we error code? */ + std::abort(); + } + + this->session->GetSessionManager()->AddSession(server_h, std::move(this->session->obj_holder.Clone())); + out_h.SetValue(client_h); + } + + void QueryPointerBufferSize(Out<u16> size) { + size.SetValue(this->session->pointer_buffer.size()); + } + + void CloneCurrentObjectEx(Out<MovedHandle> out_h, u32 which) { + /* TODO: Figure out what this u32 controls. */ + return CloneCurrentObject(out_h); + } + + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<HipcControlCommand_ConvertCurrentObjectToDomain, &ServiceSession::IHipcControlService::ConvertCurrentObjectToDomain>(), + MakeServiceCommandMeta<HipcControlCommand_CopyFromCurrentDomain, &ServiceSession::IHipcControlService::CopyFromCurrentDomain>(), + MakeServiceCommandMeta<HipcControlCommand_CloneCurrentObject, &ServiceSession::IHipcControlService::CloneCurrentObject>(), + MakeServiceCommandMeta<HipcControlCommand_QueryPointerBufferSize, &ServiceSession::IHipcControlService::QueryPointerBufferSize>(), + MakeServiceCommandMeta<HipcControlCommand_CloneCurrentObjectEx, &ServiceSession::IHipcControlService::CloneCurrentObjectEx>(), + }; + }; +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_session_manager_base.hpp similarity index 55% rename from stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp rename to stratosphere/libstratosphere/include/stratosphere/ipc/ipc_session_manager_base.hpp index f796beb26..3da68038d 100644 --- a/stratosphere/libstratosphere/include/stratosphere/serviceserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_session_manager_base.hpp @@ -15,19 +15,20 @@ */ #pragma once -#include <switch.h> -#include "iserver.hpp" +#include <atomic> -template <typename T> -class ServiceServer : public IServer<T> { +#include "../waitable_manager_base.hpp" +#include "ipc_service_object.hpp" + +class SessionManagerBase : public WaitableManagerBase, public DomainManager { public: - ServiceServer(const char *service_name, unsigned int max_s, bool s_d = false) : IServer<T>(service_name, max_s, s_d) { - if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) { - /* TODO: Panic. */ - } + SessionManagerBase() = default; + virtual ~SessionManagerBase() = default; + + virtual void AddSession(Handle server_h, ServiceObjectHolder &&service) = 0; + + static Result CreateSessionHandles(Handle *server_h, Handle *client_h) { + return svcCreateSession(server_h, client_h, 0, 0); } - - ISession<T> *get_new_session(Handle session_h) override { - return new ServiceSession<T>(this, session_h, 0); - } -}; \ No newline at end of file +}; + diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp new file mode 100644 index 000000000..3b613b366 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <type_traits> + +#include "ipc_out.hpp" + +/* Represents an input PID. */ +struct PidDescriptorTag{}; + +struct PidDescriptor : public PidDescriptorTag { + u64 pid; + + void operator=(u64 &p) { + pid = p; + } + + PidDescriptor(u64 p) : pid(p) { } +}; + +struct IpcHandleTag{}; + +struct IpcHandle : public IpcHandleTag { + Handle handle; +}; + +/* Represents a moved handle. */ +struct MovedHandle : public IpcHandle { + void operator=(const Handle &h) { + this->handle = h; + } + + void operator=(const IpcHandle &o) { + this->handle = o.handle; + } + + MovedHandle(Handle h) { + this->handle = h; + } +}; + +/* Represents a copied handle. */ +struct CopiedHandle : public IpcHandle { + void operator=(const Handle &h) { + handle = h; + } + + void operator=(const IpcHandle &o) { + this->handle = o.handle; + } + + CopiedHandle(Handle h) { + this->handle = h; + } +}; + +template <> +class Out<MovedHandle> : public OutHandleTag { +private: + MovedHandle *obj; +public: + Out(IpcHandle *o) : obj(static_cast<MovedHandle *>(o)) { } + + void SetValue(const Handle& h) { + *obj = h; + } + + void SetValue(const MovedHandle& o) { + *obj = o; + } + + const MovedHandle& GetValue() { + return *obj; + } + + MovedHandle* GetPointer() { + return obj; + } + + Handle* GetHandlePointer() { + return &obj->handle; + } + + /* Convenience operators. */ + MovedHandle& operator*() { + return *obj; + } + + MovedHandle* operator->() { + return obj; + } +}; + +template <> +class Out<CopiedHandle> : public OutHandleTag { +private: + CopiedHandle *obj; +public: + Out(IpcHandle *o) : obj(static_cast<CopiedHandle *>(o)) { } + + void SetValue(const Handle& h) { + *obj = h; + } + + void SetValue(const CopiedHandle& o) { + *obj = o; + } + + const CopiedHandle& GetValue() { + return *obj; + } + + CopiedHandle* GetPointer() { + return obj; + } + + Handle* GetHandlePointer() { + return &obj->handle; + } + + /* Convenience operators. */ + CopiedHandle& operator*() { + return *obj; + } + + CopiedHandle* operator->() { + return obj; + } +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp similarity index 99% rename from stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp rename to stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp index d37857ae8..68e80a347 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc_templating.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp @@ -337,7 +337,7 @@ struct Validator<std::tuple<Args...>> { } if (((u32 *)r.Raw)[0] != SFCI_MAGIC) { - //return 0xF601; + return 0xF601; } size_t a_index = 0, b_index = num_inbuffers_in_arguments<Args ...>::value, x_index = 0, c_index = 0, h_index = 0; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp b/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp deleted file mode 100644 index e95593280..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipcsession.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <type_traits> - -#include "ipc_templating.hpp" -#include "iserviceobject.hpp" -#include "iwaitable.hpp" -#include "isession.hpp" - -template <typename T> -class IPCSession final : public ISession<T> { - static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); - - public: - IPCSession<T>(size_t pbs = 0x400) : ISession<T>(NULL, 0, 0, 0) { - Result rc; - if (R_FAILED((rc = svcCreateSession(&this->server_handle, &this->client_handle, 0, 0)))) { - fatalSimple(rc); - } - this->service_object = std::make_shared<T>(); - this->pointer_buffer.resize(pbs); - } - - IPCSession<T>(std::shared_ptr<T> so, size_t pbs = 0x400) : ISession<T>(NULL, 0, 0, so, 0) { - Result rc; - if (R_FAILED((rc = svcCreateSession(&this->server_handle, &this->client_handle, 0, 0)))) { - fatalSimple(rc); - } - this->pointer_buffer.resize(pbs); - } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/iserviceobject.hpp b/stratosphere/libstratosphere/include/stratosphere/iserviceobject.hpp deleted file mode 100644 index 2e8c13570..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/iserviceobject.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> - -template <typename T> -class ISession; - -class DomainOwner; - -class IServiceObject { - private: - DomainOwner *owner = NULL; - public: - virtual ~IServiceObject() { } - - virtual IServiceObject *clone() = 0; - - bool is_domain() { return this->owner != NULL; } - DomainOwner *get_owner() { return this->owner; } - void set_owner(DomainOwner *owner) { this->owner = owner; } - virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) = 0; - virtual Result handle_deferred() = 0; -}; - -#include "domainowner.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/isession.hpp b/stratosphere/libstratosphere/include/stratosphere/isession.hpp deleted file mode 100644 index a5371deeb..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/isession.hpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <type_traits> - -#include "ipc_templating.hpp" -#include "iserviceobject.hpp" -#include "iwaitable.hpp" -#include "iserver.hpp" - -#include "domainowner.hpp" - -enum IpcControlCommand { - IpcCtrl_Cmd_ConvertCurrentObjectToDomain = 0, - IpcCtrl_Cmd_CopyFromCurrentDomain = 1, - IpcCtrl_Cmd_CloneCurrentObject = 2, - IpcCtrl_Cmd_QueryPointerBufferSize = 3, - IpcCtrl_Cmd_CloneCurrentObjectEx = 4 -}; - -#define RESULT_DEFER_SESSION (0x6580A) - - -template <typename T> -class IServer; - -class IServiceObject; - -template <typename T> -class ISession : public IWaitable { - static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); - protected: - std::shared_ptr<T> service_object; - IServer<T> *server; - Handle server_handle; - Handle client_handle; - std::vector<char> pointer_buffer; - - bool is_domain = false; - std::shared_ptr<DomainOwner> domain; - - - std::shared_ptr<IServiceObject> active_object; - - public: - ISession<T>(IServer<T> *s, Handle s_h, Handle c_h, size_t pbs = 0x400) : server(s), server_handle(s_h), client_handle(c_h), pointer_buffer(pbs) { - this->service_object = std::make_shared<T>(); - } - - ISession<T>(IServer<T> *s, Handle s_h, Handle c_h, std::shared_ptr<T> so, size_t pbs = 0x400) : service_object(so), server(s), server_handle(s_h), client_handle(c_h), pointer_buffer(pbs) { - } - - ~ISession() override { - if (server_handle) { - svcCloseHandle(server_handle); - } - if (client_handle) { - svcCloseHandle(client_handle); - } - } - - void close_handles() { - if (server_handle) { - svcCloseHandle(server_handle); - server_handle = 0; - } - if (client_handle) { - svcCloseHandle(client_handle); - client_handle = 0; - } - } - - std::shared_ptr<T> get_service_object() { return this->service_object; } - Handle get_server_handle() { return this->server_handle; } - Handle get_client_handle() { return this->client_handle; } - - - DomainOwner *get_owner() { return this->is_domain ? this->domain.get() : NULL; } - - /* IWaitable */ - Handle get_handle() override { - return this->server_handle; - } - - void handle_deferred() override { - Result rc = this->service_object->handle_deferred(); - int handle_index; - - if (rc != RESULT_DEFER_SESSION) { - this->set_deferred(false); - if (rc == 0xF601) { - svcCloseHandle(this->get_handle()); - } else { - rc = svcReplyAndReceive(&handle_index, &this->server_handle, 0, this->server_handle, 0); - } - } - } - - - virtual Result handle_message(IpcParsedCommand &r) { - Result retval = 0xF601; - - IpcCommand c; - ipcInitialize(&c); - - if (r.IsDomainRequest && this->active_object == NULL) { - return 0xF601; - } - - - if (r.IsDomainRequest && r.InMessageType == DomainMessageType_Close) { - this->domain->delete_object(this->active_object); - this->active_object = NULL; - struct { - u64 magic; - u64 result; - } *raw = (decltype(raw))ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCO_MAGIC; - raw->result = 0x0; - return 0x0; - } - - u64 cmd_id = ((u32 *)r.Raw)[2]; - switch (r.CommandType) { - case IpcCommandType_Close: - /* TODO: This should close the session and clean up its resources. */ - retval = 0xF601; - break; - case IpcCommandType_LegacyControl: - /* TODO: What does this allow one to do? */ - retval = 0xF601; - break; - case IpcCommandType_LegacyRequest: - /* TODO: What does this allow one to do? */ - retval = 0xF601; - break; - case IpcCommandType_Request: - case IpcCommandType_RequestWithContext: - retval = this->active_object->dispatch(r, c, cmd_id, (u8 *)pointer_buffer.data(), pointer_buffer.size()); - break; - case IpcCommandType_Control: - case IpcCommandType_ControlWithContext: - retval = this->dispatch_control_command(r, c, cmd_id); - break; - case IpcCommandType_Invalid: - default: - retval = 0xF601; - break; - } - - return retval; - } - - virtual void postprocess(IpcParsedCommand &r, u64 cmd_id) { - /* ... */ - (void)(r); - (void)(cmd_id); - } - - virtual void cleanup() { - /* ... */ - } - - Result handle_signaled(u64 timeout) override { - Result rc; - int handle_index; - - /* Prepare pointer buffer... */ - IpcCommand c_for_reply; - ipcInitialize(&c_for_reply); - ipcAddRecvStatic(&c_for_reply, this->pointer_buffer.data(), this->pointer_buffer.size(), 0); - ipcPrepareHeader(&c_for_reply, 0); - - /* Fix libnx bug in serverside C descriptor handling. */ - ((u32 *)armGetTls())[1] &= 0xFFFFC3FF; - ((u32 *)armGetTls())[1] |= (2) << 10; - - if (R_SUCCEEDED(rc = svcReplyAndReceive(&handle_index, &this->server_handle, 1, 0, U64_MAX))) { - if (handle_index != 0) { - /* TODO: Panic? */ - } - IpcParsedCommand r; - u64 cmd_id = 0; - - - Result retval = ipcParse(&r); - if (R_SUCCEEDED(retval)) { - if (this->is_domain && (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext)) { - retval = ipcParseDomainRequest(&r); - if (!r.IsDomainRequest || r.InThisObjectId >= DOMAIN_ID_MAX) { - retval = 0xF601; - } else { - this->active_object = this->domain->get_domain_object(r.InThisObjectId); - } - } else { - this->active_object = this->service_object; - } - } - if (R_SUCCEEDED(retval)) { - cmd_id = ((u32 *)r.Raw)[2]; - } - if (R_SUCCEEDED(retval)) { - retval = this->handle_message(r); - } - - if (retval == RESULT_DEFER_SESSION) { - /* Session defer. */ - this->active_object.reset(); - this->set_deferred(true); - rc = retval; - } else if (retval == 0xF601) { - /* Session close. */ - this->active_object.reset(); - rc = retval; - } else { - if (R_SUCCEEDED(retval)) { - this->postprocess(r, cmd_id); - } - this->active_object.reset(); - rc = svcReplyAndReceive(&handle_index, &this->server_handle, 0, this->server_handle, 0); - if (rc == 0xEA01) { - rc = 0x0; - } - this->cleanup(); - } - } - - return rc; - } - - Result dispatch_control_command(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id) { - Result rc = 0xF601; - - /* TODO: Implement. */ - switch ((IpcControlCommand)cmd_id) { - case IpcCtrl_Cmd_ConvertCurrentObjectToDomain: - rc = WrapIpcCommandImpl<&ISession::ConvertCurrentObjectToDomain>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); - break; - case IpcCtrl_Cmd_CopyFromCurrentDomain: - rc = WrapIpcCommandImpl<&ISession::CopyFromCurrentDomain>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); - break; - case IpcCtrl_Cmd_CloneCurrentObject: - rc = WrapIpcCommandImpl<&ISession::CloneCurrentObject>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); - break; - case IpcCtrl_Cmd_QueryPointerBufferSize: - rc = WrapIpcCommandImpl<&ISession::QueryPointerBufferSize>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); - break; - case IpcCtrl_Cmd_CloneCurrentObjectEx: - rc = WrapIpcCommandImpl<&ISession::CloneCurrentObjectEx>(this, r, out_c, (u8 *)this->pointer_buffer.data(), pointer_buffer.size()); - break; - default: - break; - } - - return rc; - } - - /* Control commands. */ - std::tuple<Result> ConvertCurrentObjectToDomain() { - /* TODO */ - return {0xF601}; - } - std::tuple<Result> CopyFromCurrentDomain() { - /* TODO */ - return {0xF601}; - } - std::tuple<Result> CloneCurrentObject() { - /* TODO */ - return {0xF601}; - } - std::tuple<Result, u32> QueryPointerBufferSize() { - return {0x0, (u32)this->pointer_buffer.size()}; - } - std::tuple<Result> CloneCurrentObjectEx() { - /* TODO */ - return {0xF601}; - } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp b/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp index 1fff3f874..175996067 100644 --- a/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp @@ -18,47 +18,61 @@ #include <switch.h> -#include "waitablemanagerbase.hpp" - -class WaitableManager; +#include "waitable_manager_base.hpp" +#include "hossynch.hpp" class IWaitable { private: u64 wait_priority = 0; bool is_deferred = false; - WaitableManagerBase *manager; + WaitableManagerBase *manager = nullptr; + protected: + HosMutex sig_lock; + bool is_signaled = false; public: - virtual ~IWaitable() { } + virtual ~IWaitable() = default; - virtual void handle_deferred() = 0; - virtual Handle get_handle() = 0; - virtual Result handle_signaled(u64 timeout) = 0; - - WaitableManager *get_manager() { - return (WaitableManager *)this->manager; + virtual void HandleDeferred() { + /* ... */ } - void set_manager(WaitableManagerBase *m) { + bool IsSignaled() { + std::scoped_lock<HosMutex> lock(this->sig_lock); + return this->is_signaled; + } + + virtual Handle GetHandle() = 0; + virtual Result HandleSignaled(u64 timeout) = 0; + + WaitableManagerBase *GetManager() { + return this->manager; + } + + void SetManager(WaitableManagerBase *m) { this->manager = m; } - void update_priority() { + void UpdatePriority() { if (manager) { - this->wait_priority = this->manager->get_priority(); + this->wait_priority = this->manager->GetNextPriority(); } } - bool get_deferred() { + bool IsDeferred() { return this->is_deferred; } - void set_deferred(bool d) { + void SetDeferred(bool d) { this->is_deferred = d; } - static bool compare(IWaitable *a, IWaitable *b) { - return (a->wait_priority < b->wait_priority) && !a->is_deferred; + static bool Compare(IWaitable *a, IWaitable *b) { + return (a->wait_priority < b->wait_priority) && !a->IsDeferred() && (a->GetHandle() != INVALID_HANDLE); + } + + void NotifyManagerSignaled() { + if (this->manager) { + this->manager->NotifySignaled(this); + } } }; - -#include "waitablemanager.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm.hpp new file mode 100644 index 000000000..3d1b35259 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/mitm.hpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "mitm/sm_mitm.h" + +#include "ipc.hpp" + +#include "mitm/imitmserviceobject.hpp" +#include "mitm/mitm_query_service.hpp" +#include "mitm/mitm_session.hpp" +#include "mitm/mitm_server.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/existingportserver.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp similarity index 61% rename from stratosphere/libstratosphere/include/stratosphere/existingportserver.hpp rename to stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp index 360ed286b..873487be5 100644 --- a/stratosphere/libstratosphere/include/stratosphere/existingportserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp @@ -16,16 +16,20 @@ #pragma once #include <switch.h> -#include "iserver.hpp" +#include <atomic> -template <typename T> -class ExistingPortServer : public IServer<T> { +#include <stratosphere.hpp> + +class IMitmServiceObject : public IServiceObject { + protected: + std::shared_ptr<Service> forward_service; + u64 process_id = 0; + u64 title_id = 0; public: - ExistingPortServer(Handle port_h, unsigned int max_s, bool s_d = false) : IServer<T>(NULL, max_s, s_d) { - this->port_handle = port_h; - } + IMitmServiceObject(std::shared_ptr<Service> s) : forward_service(s) {} - ISession<T> *get_new_session(Handle session_h) override { - return new ServiceSession<T>(this, session_h, 0); - } -}; \ No newline at end of file + static bool ShouldMitm(u64 pid, u64 tid); + + protected: + virtual ~IMitmServiceObject() = default; +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp new file mode 100644 index 000000000..a007cdc82 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +enum MitmQueryServiceCommand { + MQS_Cmd_ShouldMitm = 65000, + MQS_Cmd_AssociatePidTid = 65001 +}; + +namespace MitmQueryUtils { + Result GetAssociatedTidForPid(u64 pid, u64 *tid); + + void AssociatePidToTid(u64 pid, u64 tid); +} + +template <typename T> +class MitmQueryService : public IServiceObject { + protected: + void ShouldMitm(Out<bool> should_mitm, u64 pid) { + should_mitm.SetValue(false); + u64 tid = 0; + if (R_SUCCEEDED(MitmQueryUtils::GetAssociatedTidForPid(pid, &tid))) { + should_mitm.SetValue(T::ShouldMitm(pid, tid)); + } + } + void AssociatePidToTid(u64 pid, u64 tid) { + MitmQueryUtils::AssociatePidToTid(pid, tid); + } + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<MQS_Cmd_ShouldMitm, &MitmQueryService::ShouldMitm>(), + MakeServiceCommandMeta<MQS_Cmd_AssociatePidTid, &MitmQueryService::AssociatePidToTid>(), + }; +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp new file mode 100644 index 000000000..5380fae26 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> + +#include "mitm_query_service.hpp" +#include "sm_mitm.h" +#include "mitm_session.hpp" + +template <typename T> +class MitmServer : public IWaitable { + static_assert(std::is_base_of<IMitmServiceObject, T>::value, "MitM Service Objects must derive from IMitmServiceObject"); + private: + Handle port_handle; + unsigned int max_sessions; + char mitm_name[9]; + + public: + MitmServer(Handle *out_query_h, const char *service_name, unsigned int max_s) : port_handle(0), max_sessions(max_s) { + Handle tmp_hnd; + Result rc; + + if (R_SUCCEEDED((rc = smGetServiceOriginal(&tmp_hnd, smEncodeName(service_name))))) { + svcCloseHandle(tmp_hnd); + } else { + fatalSimple(rc); + } + strncpy(mitm_name, service_name, 8); + mitm_name[8] = '\x00'; + if (R_FAILED((rc = smMitMInstall(&this->port_handle, out_query_h, mitm_name)))) { + fatalSimple(rc); + } + } + + virtual ~MitmServer() override { + if (this->port_handle) { + if (R_FAILED(smMitMUninstall(this->mitm_name))) { + std::abort(); + } + svcCloseHandle(port_handle); + } + } + + SessionManagerBase *GetSessionManager() { + return static_cast<SessionManagerBase *>(this->GetManager()); + } + + /* IWaitable */ + virtual Handle GetHandle() override { + return this->port_handle; + } + + virtual Result HandleSignaled(u64 timeout) override { + /* If this server's port was signaled, accept a new session. */ + Handle session_h; + Result rc = svcAcceptSession(&session_h, this->port_handle); + if (R_FAILED(rc)) { + return rc; + } + + /* Create a forward service for this instance. */ + std::shared_ptr<Service>forward_service(new Service(), [](Service *s) { + /* Custom deleter to ensure service is open as long as necessary. */ + serviceClose(s); + delete s; + }); + + if (R_FAILED(smMitMGetService(forward_service.get(), mitm_name))) { + /* TODO: Panic. */ + } + + this->GetSessionManager()->AddWaitable(new MitmSession(session_h, forward_service, std::make_shared<T>(forward_service))); + return 0; + } + +}; + +template<typename T> +static void AddMitmServerToManager(SessionManagerBase *manager, const char *srv_name, unsigned int max_sessions) { + Handle query_h; + auto *srv = new MitmServer<T>(&query_h, srv_name, max_sessions); + manager->AddWaitable(srv); + manager->AddSession(query_h, std::move(ServiceObjectHolder(std::move(std::make_shared<MitmQueryService<T>>())))); +} + + diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp new file mode 100644 index 000000000..33deb8b03 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include "imitmserviceobject.hpp" + +#include "mitm_query_service.hpp" + +class MitmSession final : public ServiceSession { + private: + /* This will be for the actual session. */ + std::shared_ptr<Service> forward_service; + + /* Store a handler for the service. */ + void (*service_post_process_handler)(IMitmServiceObject *, IpcResponseContext *); + + /* For cleanup usage. */ + u32 num_fwd_copy_hnds; + Handle fwd_copy_hnds[8]; + public: + template<typename T> + MitmSession(Handle s_h, std::shared_ptr<Service> fs, std::shared_ptr<T> srv) : ServiceSession(s_h) { + this->forward_service = std::move(fs); + this->obj_holder = std::move(ServiceObjectHolder(std::move(srv))); + + this->service_post_process_handler = T::PostProcess; + + size_t pbs; + if (R_FAILED(ipcQueryPointerBufferSize(forward_service->handle, &pbs))) { + std::abort(); + } + this->pointer_buffer.resize(pbs); + this->control_holder.Reset(); + this->control_holder = ServiceObjectHolder(std::make_shared<IMitmHipcControlService>(this)); + } + + MitmSession(Handle s_h, std::shared_ptr<Service> fs, ServiceObjectHolder &&h, void (*pph)(IMitmServiceObject *, IpcResponseContext *)) : ServiceSession(s_h) { + this->session_handle = s_h; + this->forward_service = std::move(fs); + this->obj_holder = std::move(h); + + this->service_post_process_handler = pph; + + size_t pbs; + if (R_FAILED(ipcQueryPointerBufferSize(forward_service->handle, &pbs))) { + std::abort(); + } + this->pointer_buffer.resize(pbs); + this->control_holder.Reset(); + this->control_holder = ServiceObjectHolder(std::make_shared<IMitmHipcControlService>(this)); + } + + virtual void PreProcessRequest(IpcResponseContext *ctx) override { + u32 *cmdbuf = (u32 *)armGetTls(); + u32 *backup_cmdbuf = (u32 *)this->backup_tls; + if (ctx->request.HasPid) { + /* [ctrl 0] [ctrl 1] [handle desc 0] [pid low] [pid high] */ + cmdbuf[4] = 0xFFFE0000UL | (cmdbuf[4] & 0xFFFFUL); + backup_cmdbuf[4] = cmdbuf[4]; + } + } + + Result ForwardRequest(IpcResponseContext *ctx) { + IpcParsedCommand r; + Result rc = serviceIpcDispatch(this->forward_service.get()); + if (R_SUCCEEDED(rc)) { + if (ctx->request.IsDomainRequest) { + /* We never work with out object ids, so this should be fine. */ + ipcParseDomainResponse(&r, 0); + } else { + ipcParse(&r); + } + + struct { + u64 magic; + u64 result; + } *resp = (decltype(resp))r.Raw; + + rc = resp->result; + + for (unsigned int i = 0; i < r.NumHandles; i++) { + if (r.WasHandleCopied[i]) { + this->fwd_copy_hnds[num_fwd_copy_hnds++] = r.Handles[i]; + } + } + } + return rc; + } + + virtual Result GetResponse(IpcResponseContext *ctx) { + Result rc = 0xF601; + FirmwareVersion fw = GetRuntimeFirmwareVersion(); + + const ServiceCommandMeta *dispatch_table = ctx->obj_holder->GetDispatchTable(); + size_t entry_count = ctx->obj_holder->GetDispatchTableEntryCount(); + + if (IsDomainObject(ctx->obj_holder)) { + switch (ctx->request.InMessageType) { + case DomainMessageType_Invalid: + return 0xF601; + case DomainMessageType_Close: + rc = ForwardRequest(ctx); + if (R_SUCCEEDED(rc)) { + ctx->obj_holder->GetServiceObject<IDomainObject>()->FreeObject(ctx->request.InThisObjectId); + } + if (R_SUCCEEDED(rc) && ctx->request.InThisObjectId == serviceGetObjectId(this->forward_service.get())) { + /* If we're not longer MitMing anything, we don't need a mitm session. */ + this->Reply(); + this->GetSessionManager()->AddSession(this->session_handle, std::move(this->obj_holder)); + this->session_handle = 0; + return 0xF601; + } + return rc; + case DomainMessageType_SendMessage: + { + auto sub_obj = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId); + if (sub_obj == nullptr) { + return ForwardRequest(ctx); + } + dispatch_table = sub_obj->GetDispatchTable(); + entry_count = sub_obj->GetDispatchTableEntryCount(); + } + } + } + + bool found_entry = false; + + for (size_t i = 0; i < entry_count; i++) { + if (ctx->cmd_id == dispatch_table[i].cmd_id && dispatch_table[i].fw_low <= fw && fw <= dispatch_table[i].fw_high) { + rc = dispatch_table[i].handler(ctx); + found_entry = true; + break; + } + } + + if (!found_entry) { + memcpy(armGetTls(), this->backup_tls, sizeof(this->backup_tls)); + rc = ForwardRequest(ctx); + } + + return rc; + } + + virtual void PostProcessResponse(IpcResponseContext *ctx) override { + if ((ctx->cmd_type == IpcCommandType_Request || ctx->cmd_type == IpcCommandType_RequestWithContext) && R_SUCCEEDED(ctx->rc)) { + if (!IsDomainObject(ctx->obj_holder) || ctx->request.InThisObjectId == serviceGetObjectId(this->forward_service.get())) { + IMitmServiceObject *obj; + if (!IsDomainObject(ctx->obj_holder)) { + obj = ctx->obj_holder->GetServiceObjectUnsafe<IMitmServiceObject>(); + } else { + obj = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId)->GetServiceObjectUnsafe<IMitmServiceObject>(); + } + this->service_post_process_handler(obj, ctx); + } + } + } + + virtual void CleanupResponse(IpcResponseContext *ctx) override { + /* Cleanup tls backup. */ + std::memset(this->backup_tls, 0, sizeof(this->backup_tls)); + + /* Clean up copy handles. */ + for (unsigned int i = 0; i < ctx->request.NumHandles; i++) { + if (ctx->request.WasHandleCopied[i]) { + svcCloseHandle(ctx->request.Handles[i]); + } + } + for (unsigned int i = 0; i < this->num_fwd_copy_hnds; i++) { + svcCloseHandle(this->fwd_copy_hnds[i]); + } + this->num_fwd_copy_hnds = 0; + } + + public: + class IMitmHipcControlService : public IServiceObject { + private: + MitmSession *session; + public: + explicit IMitmHipcControlService(MitmSession *s) : session(s) { + + } + + virtual ~IMitmHipcControlService() override { } + + public: + Result ConvertCurrentObjectToDomain(Out<u32> object_id) { + if (IsDomainObject(this->session->obj_holder)) { + return 0xF601; + } + + Result rc = serviceConvertToDomain(this->session->forward_service.get()); + if (R_FAILED(rc)) { + return rc; + } + + u32 expected_id = serviceGetObjectId(this->session->forward_service.get()); + + /* Allocate new domain. */ + auto new_domain = this->session->GetDomainManager()->AllocateDomain(); + if (new_domain == nullptr) { + /* If our domains mismatch, we're in trouble. */ + return 0xF601; + } + + /* Reserve the expected object in the domain for our session. */ + if (R_FAILED(new_domain->ReserveSpecificObject(expected_id))) { + return 0xF601; + } + new_domain->SetObject(expected_id, std::move(this->session->obj_holder)); + this->session->obj_holder = std::move(ServiceObjectHolder(std::move(new_domain))); + + /* Return the object id. */ + object_id.SetValue(expected_id); + return 0; + } + + Result CopyFromCurrentDomain(Out<MovedHandle> out_h, u32 id) { + auto domain = this->session->obj_holder.GetServiceObject<IDomainObject>(); + if (domain == nullptr) { + return 0x3D60B; + } + + + auto object = domain->GetObject(id); + if (object == nullptr) { + /* Forward onwards. */ + u32 *buf = (u32 *)armGetTls(); + buf[0] = IpcCommandType_Control; + buf[1] = 0xA; + buf[4] = SFCI_MAGIC; + buf[5] = 0; + buf[6] = 1; + buf[7] = 0; + buf[8] = id; + buf[9] = 0; + Result rc = ipcDispatch(this->session->forward_service->handle); + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + struct { + u64 magic; + u64 result; + } *raw = (decltype(raw))r.Raw; + rc = raw->result; + + if (R_SUCCEEDED(rc)) { + out_h.SetValue(r.Handles[0]); + this->session->fwd_copy_hnds[this->session->num_fwd_copy_hnds++] = r.Handles[0]; + } + } + return rc; + } + + Handle server_h, client_h; + if (R_FAILED(SessionManagerBase::CreateSessionHandles(&server_h, &client_h))) { + /* N aborts here. Should we error code? */ + std::abort(); + } + out_h.SetValue(client_h); + + if (id == serviceGetObjectId(this->session->forward_service.get())) { + this->session->GetSessionManager()->AddWaitable(new MitmSession(server_h, this->session->forward_service, std::move(object->Clone()), this->session->service_post_process_handler)); + } else { + this->session->GetSessionManager()->AddSession(server_h, std::move(object->Clone())); + } + return 0; + } + + void CloneCurrentObject(Out<MovedHandle> out_h) { + Handle server_h, client_h; + if (R_FAILED(SessionManagerBase::CreateSessionHandles(&server_h, &client_h))) { + /* N aborts here. Should we error code? */ + std::abort(); + } + + this->session->GetSessionManager()->AddWaitable(new MitmSession(server_h, this->session->forward_service, std::move(this->session->obj_holder.Clone()), this->session->service_post_process_handler)); + out_h.SetValue(client_h); + } + + void QueryPointerBufferSize(Out<u16> size) { + size.SetValue(this->session->pointer_buffer.size()); + } + + void CloneCurrentObjectEx(Out<MovedHandle> out_h, u32 which) { + /* TODO: Figure out what this u32 controls. */ + return CloneCurrentObject(out_h); + } + + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<HipcControlCommand_ConvertCurrentObjectToDomain, &MitmSession::IMitmHipcControlService::ConvertCurrentObjectToDomain>(), + MakeServiceCommandMeta<HipcControlCommand_CopyFromCurrentDomain, &MitmSession::IMitmHipcControlService::CopyFromCurrentDomain>(), + MakeServiceCommandMeta<HipcControlCommand_CloneCurrentObject, &MitmSession::IMitmHipcControlService::CloneCurrentObject>(), + MakeServiceCommandMeta<HipcControlCommand_QueryPointerBufferSize, &MitmSession::IMitmHipcControlService::QueryPointerBufferSize>(), + MakeServiceCommandMeta<HipcControlCommand_CloneCurrentObjectEx, &MitmSession::IMitmHipcControlService::CloneCurrentObjectEx>(), + }; + }; +}; diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/sm_mitm.h b/stratosphere/libstratosphere/include/stratosphere/mitm/sm_mitm.h new file mode 100644 index 000000000..4b521c88c --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/sm_mitm.h @@ -0,0 +1,24 @@ +/** + * @file sm_mitm.h + * @brief Service manager (sm) IPC wrapper for Atmosphere extensions. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include <switch.h> + +#ifdef __cplusplus +extern "C" { +#endif + +Result smMitMInitialize(void); +void smMitMExit(void); +Result smMitMGetService(Service* service_out, const char *name); +Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name); +Result smMitMUninstall(const char *name); + +Result smMitMIsRegistered(const char *name); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/multithreadedwaitablemanager.hpp b/stratosphere/libstratosphere/include/stratosphere/multithreadedwaitablemanager.hpp deleted file mode 100644 index d223000db..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/multithreadedwaitablemanager.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <vector> - -#include "waitablemanager.hpp" -#include "systemevent.hpp" - -class MultiThreadedWaitableManager : public WaitableManager { - protected: - u32 num_threads; - Thread *threads; - HosMutex get_waitable_lock; - SystemEvent *new_waitable_event; - public: - MultiThreadedWaitableManager(u32 n, u64 t, u32 ss = 0x8000) : WaitableManager(t), num_threads(n-1) { - u32 prio; - u32 cpuid = svcGetCurrentProcessorNumber(); - Result rc; - threads = new Thread[num_threads]; - if (R_FAILED((rc = svcGetThreadPriority(&prio, CUR_THREAD_HANDLE)))) { - fatalSimple(rc); - } - for (unsigned int i = 0; i < num_threads; i++) { - threads[i] = {0}; - threadCreate(&threads[i], &MultiThreadedWaitableManager::thread_func, this, ss, prio, cpuid); - } - new_waitable_event = new SystemEvent(this, &MultiThreadedWaitableManager::add_waitable_callback); - this->waitables.push_back(new_waitable_event); - } - ~MultiThreadedWaitableManager() override { - /* TODO: Exit the threads? */ - } - - IWaitable *get_waitable(); - - void add_waitable(IWaitable *waitable) override; - void process() override; - void process_until_timeout() override; - - static Result add_waitable_callback(void *this_ptr, Handle *handles, size_t num_handles, u64 timeout); - static void thread_func(void *this_ptr); -}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp b/stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp new file mode 100644 index 000000000..fa611a518 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + /* Scope guard logic lovingly taken from Andrei Alexandrescu's "Systemic Error Handling in C++" */ +#pragma once + +#include <utility> + +template<class F> +class ScopeGuard { +private: + F f; + bool active; +public: + ScopeGuard(F f) : f(std::move(f)), active(true) { } + ~ScopeGuard() { if (active) { f(); } } + void Cancel() { active = false; } + + ScopeGuard() = delete; + ScopeGuard(const ScopeGuard &) = delete; + ScopeGuard& operator=(const ScopeGuard&) = delete; + ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) { + rhs.Cancel(); + } +}; + +template<class F> +ScopeGuard<F> MakeScopeGuard(F f) { + return ScopeGuard<F>(std::move(f)); +} + +enum class ScopeGuardOnExit {}; + +template <typename F> +ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) { + return ScopeGuard<F>(std::forward<F>(f)); +} + +#define CONCATENATE_IMPL(S1, s2) s1##s2 +#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2) + +#ifdef __COUNTER__ +#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__) +#else +#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __LINE__) +#endif + +#define ON_SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = ScopeGuardOnExit() + [&]() \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/iserver.hpp b/stratosphere/libstratosphere/include/stratosphere/servers.hpp similarity index 54% rename from stratosphere/libstratosphere/include/stratosphere/iserver.hpp rename to stratosphere/libstratosphere/include/stratosphere/servers.hpp index 1b32ebcd5..7771157f1 100644 --- a/stratosphere/libstratosphere/include/stratosphere/iserver.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/servers.hpp @@ -16,48 +16,36 @@ #pragma once #include <switch.h> -#include <algorithm> -#include <type_traits> -#include "iserviceobject.hpp" #include "iwaitable.hpp" -#include "isession.hpp" +#include "ipc.hpp" -template <typename T> -class ISession; - -template <typename T> +template<typename T> class IServer : public IWaitable { static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); protected: Handle port_handle; unsigned int max_sessions; - bool supports_domains; public: - IServer(const char *service_name, unsigned int max_s, bool s_d = false) : max_sessions(max_s), supports_domains(s_d) { - - } + IServer(unsigned int max_s) : port_handle(0), max_sessions(max_s) { } virtual ~IServer() { if (port_handle) { svcCloseHandle(port_handle); } } + + SessionManagerBase *GetSessionManager() { + return static_cast<SessionManagerBase *>(this->GetManager()); + } - virtual ISession<T> *get_new_session(Handle session_h) = 0; - /* IWaitable */ - virtual Handle get_handle() { + virtual Handle GetHandle() override { return this->port_handle; } - - virtual void handle_deferred() { - /* TODO: Panic, because we can never defer a server. */ - } - - virtual Result handle_signaled(u64 timeout) { + virtual Result HandleSignaled(u64 timeout) override { /* If this server's port was signaled, accept a new session. */ Handle session_h; Result rc = svcAcceptSession(&session_h, this->port_handle); @@ -65,7 +53,35 @@ class IServer : public IWaitable { return rc; } - this->get_manager()->add_waitable(this->get_new_session(session_h)); + this->GetSessionManager()->AddSession(session_h, std::move(ServiceObjectHolder(std::move(std::make_shared<T>())))); return 0; } }; + +template <typename T> +class ServiceServer : public IServer<T> { + public: + ServiceServer(const char *service_name, unsigned int max_s) : IServer<T>(max_s) { + if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) { + /* TODO: Panic. */ + } + } +}; + +template <typename T> +class ExistingPortServer : public IServer<T> { + public: + ExistingPortServer(Handle port_h, unsigned int max_s) : IServer<T>(max_s) { + this->port_handle = port_h; + } +}; + +template <typename T> +class ManagedPortServer : public IServer<T> { + public: + ManagedPortServer(const char *service_name, unsigned int max_s) : IServer<T>(max_s) { + if (R_FAILED(svcManageNamedPort(&this->port_handle, service_name, this->max_sessions))) { + /* TODO: panic */ + } + } +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/services.hpp b/stratosphere/libstratosphere/include/stratosphere/services.hpp new file mode 100644 index 000000000..7db234698 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/services.hpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "ipc.hpp" + +#include "services/smm_ams.h" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp b/stratosphere/libstratosphere/include/stratosphere/services/smm_ams.h similarity index 56% rename from stratosphere/libstratosphere/include/stratosphere/servicesession.hpp rename to stratosphere/libstratosphere/include/stratosphere/services/smm_ams.h index 7b452c870..85973929f 100644 --- a/stratosphere/libstratosphere/include/stratosphere/servicesession.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/services/smm_ams.h @@ -16,21 +16,16 @@ #pragma once #include <switch.h> -#include <type_traits> -#include "ipc_templating.hpp" -#include "iserviceobject.hpp" -#include "iwaitable.hpp" -#include "iserver.hpp" -#include "isession.hpp" +#ifdef __cplusplus +extern "C" { +#endif -template <typename T> -class ServiceSession final : public ISession<T> { - static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); - - public: - ServiceSession<T>(IServer<T> *s, Handle s_h, Handle c_h, size_t pbs = 0x400) : ISession<T>(s, s_h, c_h, pbs) { - /* ... */ - } - -}; +Result smManagerAmsInitialize(void); +void smManagerAmsExit(void); + +Result smManagerAmsEndInitialDefers(void); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp b/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp deleted file mode 100644 index a22254f67..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/systemevent.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> - -#include "iwaitable.hpp" -#include "ievent.hpp" - -#define SYSTEMEVENT_INDEX_WAITHANDLE 0 -#define SYSTEMEVENT_INDEX_SGNLHANDLE 1 - -class SystemEvent final : public IEvent { - public: - SystemEvent(void *a, EventCallback callback) : IEvent(0, a, callback) { - Handle wait_h; - Handle sig_h; - if (R_FAILED(svcCreateEvent(&sig_h, &wait_h))) { - /* TODO: Panic. */ - } - - this->handles.push_back(wait_h); - this->handles.push_back(sig_h); - } - - Result signal_event() override { - return svcSignalEvent(this->handles[SYSTEMEVENT_INDEX_SGNLHANDLE]); - } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp new file mode 100644 index 000000000..9ce75d9f0 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <switch.h> +#include <memory> + +#include "../meta_tools.hpp" + +#include "waitable_manager_base.hpp" +#include "event.hpp" +#include "ipc.hpp" +#include "servers.hpp" + +#include "scope_guard.hpp" + +static inline Handle GetCurrentThreadHandle() { + /* TODO: Wait for libnx to add a way for me to call getThreadVars() */ + return *((Handle *)((uintptr_t)armGetTls() + 0x1E4)); +} + +struct DefaultManagerOptions { + static constexpr size_t PointerBufferSize = 0; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; +}; + +struct DomainEntry { + ServiceObjectHolder obj_holder; + IDomainObject *owner = nullptr; +}; + +template<typename ManagerOptions = DefaultManagerOptions> +class WaitableManager : public SessionManagerBase { + private: + /* Domain Manager */ + HosMutex domain_lock; + std::array<std::weak_ptr<IDomainObject>, ManagerOptions::MaxDomains> domains; + std::array<bool, ManagerOptions::MaxDomains> is_domain_allocated; + std::array<DomainEntry, ManagerOptions::MaxDomainObjects> domain_objects; + + /* Waitable Manager */ + std::vector<IWaitable *> to_add_waitables; + std::vector<IWaitable *> waitables; + u32 num_threads; + Thread *threads; + HosMutex process_lock; + HosMutex signal_lock; + HosMutex add_lock; + IEvent *new_waitable_event = nullptr; + + IWaitable *next_signaled = nullptr; + Handle cur_thread_handle = INVALID_HANDLE; + public: + WaitableManager(u32 n, u32 ss = 0x8000) : num_threads(n-1) { + u32 prio; + u32 cpuid = svcGetCurrentProcessorNumber(); + Result rc; + threads = new Thread[num_threads]; + if (num_threads) { + if (R_FAILED((rc = svcGetThreadPriority(&prio, CUR_THREAD_HANDLE)))) { + fatalSimple(rc); + } + for (unsigned int i = 0; i < num_threads; i++) { + threads[i] = {0}; + threadCreate(&threads[i], &WaitableManager::ProcessLoop, this, ss, prio, cpuid); + } + } + new_waitable_event = CreateSystemEvent([](u64 timeout) { return 0; }, true); + } + + ~WaitableManager() override { + /* This should call the destructor for every waitable. */ + std::for_each(waitables.begin(), waitables.end(), std::default_delete<IWaitable>{}); + + /* TODO: Exit the threads? */ + } + + virtual void AddWaitable(IWaitable *w) override { + std::scoped_lock lk{this->add_lock}; + this->to_add_waitables.push_back(w); + w->SetManager(this); + this->new_waitable_event->Signal(); + } + + virtual void NotifySignaled(IWaitable *w) override { + std::scoped_lock lk{this->signal_lock}; + if (this->next_signaled == nullptr && w != this->new_waitable_event) { + this->next_signaled = w; + } + svcCancelSynchronization(this->cur_thread_handle); + } + + virtual void Process() override { + /* Add initial set of waitables. */ + AddWaitablesInternal(); + + Result rc; + for (unsigned int i = 0; i < num_threads; i++) { + if (R_FAILED((rc = threadStart(&threads[i])))) { + fatalSimple(rc); + } + } + + ProcessLoop(this); + } + private: + static void ProcessLoop(void *t) { + WaitableManager *this_ptr = (WaitableManager *)t; + while (true) { + IWaitable *w = this_ptr->GetWaitable(); + if (w) { + Result rc = w->HandleSignaled(0); + if (rc == 0xF601) { + /* Close! */ + delete w; + } else { + this_ptr->AddWaitable(w); + } + } + + } + } + + IWaitable *GetWaitable() { + std::scoped_lock lk{this->process_lock}; + this->next_signaled = nullptr; + IWaitable *result = nullptr; + + if (this->new_waitable_event->IsSignaled()) { + AddWaitablesInternal(); + } + + this->cur_thread_handle = GetCurrentThreadHandle(); + ON_SCOPE_EXIT { + this->cur_thread_handle = INVALID_HANDLE; + }; + + /* First, see if anything's already signaled. */ + for (auto &w : this->waitables) { + if (w->IsSignaled()) { + result = w; + } + } + + /* It's possible somebody signaled us while we were iterating. */ + { + std::scoped_lock lk{this->signal_lock}; + if (this->next_signaled != nullptr) result = this->next_signaled; + } + + if (result == nullptr) { + std::vector<Handle> handles; + + int handle_index = 0; + Result rc; + while (result == nullptr) { + /* Sort waitables by priority. */ + std::sort(this->waitables.begin(), this->waitables.end(), IWaitable::Compare); + + /* Copy out handles. */ + handles.resize(this->waitables.size() + 1); + handles[0] = this->new_waitable_event->GetHandle(); + unsigned int num_handles = 1; + for (unsigned int i = 0; i < this->waitables.size(); i++) { + Handle h = this->waitables[i]->GetHandle(); + if (h != INVALID_HANDLE) { + handles[num_handles++] = h; + } + } + + + /* Do deferred callback for each waitable. This has to happen before we wait on anything else. */ + for (auto & waitable : this->waitables) { + if (waitable->IsDeferred()) { + waitable->HandleDeferred(); + } + } + + /* Wait forever. */ + rc = svcWaitSynchronization(&handle_index, handles.data(), num_handles, U64_MAX); + + IWaitable *w = this->waitables[handle_index - 1]; + + if (R_SUCCEEDED(rc)) { + if (handle_index == 0) { + AddWaitablesInternal(); + continue; + } + std::for_each(waitables.begin(), waitables.begin() + handle_index - 1, std::mem_fn(&IWaitable::UpdatePriority)); + result = w; + } else if (rc == 0xEA01) { + /* Timeout: Just update priorities. */ + std::for_each(waitables.begin(), waitables.end(), std::mem_fn(&IWaitable::UpdatePriority)); + } else if (rc == 0xEC01) { + /* svcCancelSynchronization was called. */ + std::scoped_lock lk{this->signal_lock}; + if (this->next_signaled != nullptr) result = this->next_signaled; + } else if (rc != 0xF601 && rc != 0xE401) { + std::abort(); + } else { + if (handle_index == 0) { + std::abort(); + } + this->waitables.erase(this->waitables.begin() + handle_index - 1); + std::for_each(waitables.begin(), waitables.begin() + handle_index - 1, std::mem_fn(&IWaitable::UpdatePriority)); + delete w; + } + } + } + + this->waitables.erase(std::remove_if(this->waitables.begin(), this->waitables.end(), [&](IWaitable *w) { return w == result; }), this->waitables.end()); + + return result; + } + + void AddWaitablesInternal() { + { + std::scoped_lock lk{this->add_lock}; + this->waitables.insert(this->waitables.end(), this->to_add_waitables.begin(), this->to_add_waitables.end()); + this->to_add_waitables.clear(); + this->new_waitable_event->Clear(); + } + } + /* Session Manager */ + public: + virtual void AddSession(Handle server_h, ServiceObjectHolder &&service) override { + this->AddWaitable(new ServiceSession(server_h, ManagerOptions::PointerBufferSize, std::move(service))); + } + + /* Domain Manager */ + public: + virtual std::shared_ptr<IDomainObject> AllocateDomain() override { + std::scoped_lock lk{this->domain_lock}; + for (size_t i = 0; i < ManagerOptions::MaxDomains; i++) { + if (!this->is_domain_allocated[i]) { + auto new_domain = std::make_shared<IDomainObject>(this); + this->domains[i] = new_domain; + this->is_domain_allocated[i] = true; + return new_domain; + } + } + return nullptr; + } + + void FreeDomain(IDomainObject *domain) override { + std::scoped_lock lk{this->domain_lock}; + for (size_t i = 0; i < ManagerOptions::MaxDomainObjects; i++) { + FreeObject(domain, i+1); + } + for (size_t i = 0; i < ManagerOptions::MaxDomains; i++) { + auto observe = this->domains[i].lock(); + if (observe.get() == domain) { + this->is_domain_allocated[i] = false; + break; + } + } + } + + virtual Result ReserveObject(IDomainObject *domain, u32 *out_object_id) override { + std::scoped_lock lk{this->domain_lock}; + for (size_t i = 0; i < ManagerOptions::MaxDomainObjects; i++) { + if (this->domain_objects[i].owner == nullptr) { + this->domain_objects[i].owner = domain; + *out_object_id = i+1; + return 0; + } + } + return 0x25A0A; + } + + virtual Result ReserveSpecificObject(IDomainObject *domain, u32 object_id) override { + std::scoped_lock lk{this->domain_lock}; + if (this->domain_objects[object_id-1].owner == nullptr) { + this->domain_objects[object_id-1].owner = domain; + return 0; + } + return 0x25A0A; + } + + virtual void SetObject(IDomainObject *domain, u32 object_id, ServiceObjectHolder&& holder) override { + std::scoped_lock lk{this->domain_lock}; + if (this->domain_objects[object_id-1].owner == domain) { + this->domain_objects[object_id-1].obj_holder = std::move(holder); + } + } + + virtual ServiceObjectHolder *GetObject(IDomainObject *domain, u32 object_id) override { + std::scoped_lock lk{this->domain_lock}; + if (this->domain_objects[object_id-1].owner == domain) { + return &this->domain_objects[object_id-1].obj_holder; + } + return nullptr; + } + + virtual Result FreeObject(IDomainObject *domain, u32 object_id) override { + std::scoped_lock lk{this->domain_lock}; + if (this->domain_objects[object_id-1].owner == domain) { + this->domain_objects[object_id-1].obj_holder.Reset(); + this->domain_objects[object_id-1].owner = nullptr; + return 0x0; + } + return 0x3D80B; + } + + virtual Result ForceFreeObject(u32 object_id) override { + std::scoped_lock lk{this->domain_lock}; + if (this->domain_objects[object_id-1].owner != nullptr) { + this->domain_objects[object_id-1].obj_holder.Reset(); + this->domain_objects[object_id-1].owner = nullptr; + return 0x0; + } + return 0x3D80B; + } +}; + diff --git a/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp similarity index 80% rename from stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp rename to stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp index 247592a4e..777403b21 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitablemanagerbase.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp @@ -15,9 +15,9 @@ */ #pragma once -#include <switch.h> #include <atomic> -#include <vector> + +class IWaitable; class WaitableManagerBase { std::atomic<u64> cur_priority = 0; @@ -25,7 +25,13 @@ class WaitableManagerBase { WaitableManagerBase() = default; virtual ~WaitableManagerBase() = default; - u64 get_priority() { + u64 GetNextPriority() { return std::atomic_fetch_add(&cur_priority, (u64)1); } + + virtual void AddWaitable(IWaitable *w) = 0; + virtual void NotifySignaled(IWaitable *w) = 0; + + virtual void Process() = 0; }; + diff --git a/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp deleted file mode 100644 index 54f45e06d..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/waitablemanager.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <algorithm> -#include <memory> -#include <vector> - -#include "waitablemanagerbase.hpp" -#include "iwaitable.hpp" -#include "hossynch.hpp" - -class IWaitable; - -class WaitableManager : public WaitableManagerBase { - protected: - std::vector<IWaitable *> to_add_waitables; - std::vector<IWaitable *> waitables; - u64 timeout = 0; - HosMutex lock; - std::atomic_bool has_new_items = false; - private: - void process_internal(bool break_on_timeout); - public: - WaitableManager(u64 t) : timeout(t) { } - ~WaitableManager() override { - /* This should call the destructor for every waitable. */ - std::for_each(waitables.begin(), waitables.end(), std::default_delete<IWaitable>{}); - } - - virtual void add_waitable(IWaitable *waitable); - virtual void process(); - virtual void process_until_timeout(); -}; diff --git a/stratosphere/libstratosphere/source/mitm_query_service.cpp b/stratosphere/libstratosphere/source/mitm_query_service.cpp new file mode 100644 index 000000000..eb3654575 --- /dev/null +++ b/stratosphere/libstratosphere/source/mitm_query_service.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <mutex> +#include <switch.h> +#include <stratosphere.hpp> + +static std::vector<u64> g_known_pids; +static std::vector<u64> g_known_tids; +static HosMutex g_pid_tid_mutex; + +Result MitmQueryUtils::GetAssociatedTidForPid(u64 pid, u64 *tid) { + Result rc = 0xCAFE; + std::scoped_lock lk{g_pid_tid_mutex}; + for (unsigned int i = 0; i < g_known_pids.size(); i++) { + if (g_known_pids[i] == pid) { + *tid = g_known_tids[i]; + rc = 0x0; + break; + } + } + return rc; +} + +void MitmQueryUtils::AssociatePidToTid(u64 pid, u64 tid) { + std::scoped_lock lk{g_pid_tid_mutex}; + g_known_pids.push_back(pid); + g_known_tids.push_back(tid); +} diff --git a/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp b/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp deleted file mode 100644 index 3c5ec1356..000000000 --- a/stratosphere/libstratosphere/source/multithreadedwaitablemanager.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <switch.h> - -#include <algorithm> -#include <functional> -#include <mutex> - -#include <stratosphere/multithreadedwaitablemanager.hpp> - -void MultiThreadedWaitableManager::process() { - Result rc; - for (unsigned int i = 0; i < num_threads; i++) { - if (R_FAILED((rc = threadStart(&threads[i])))) { - fatalSimple(rc); - } - } - MultiThreadedWaitableManager::thread_func(this); -} - -void MultiThreadedWaitableManager::process_until_timeout() { - /* TODO: Panic. */ -} - -void MultiThreadedWaitableManager::add_waitable(IWaitable *waitable) { - std::scoped_lock lk{this->lock}; - this->to_add_waitables.push_back(waitable); - waitable->set_manager(this); - this->new_waitable_event->signal_event(); -} - - -IWaitable *MultiThreadedWaitableManager::get_waitable() { - std::vector<Handle> handles; - - int handle_index = 0; - Result rc; - std::scoped_lock lk{this->get_waitable_lock}; - while (1) { - /* Sort waitables by priority. */ - std::sort(this->waitables.begin(), this->waitables.end(), IWaitable::compare); - - /* Copy out handles. */ - handles.resize(this->waitables.size()); - std::transform(this->waitables.begin(), this->waitables.end(), handles.begin(), [](IWaitable *w) { return w->get_handle(); }); - - rc = svcWaitSynchronization(&handle_index, handles.data(), this->waitables.size(), this->timeout); - IWaitable *w = this->waitables[handle_index]; - if (R_SUCCEEDED(rc)) { - std::for_each(waitables.begin(), waitables.begin() + handle_index, std::mem_fn(&IWaitable::update_priority)); - this->waitables.erase(this->waitables.begin() + handle_index); - } else if (rc == 0xEA01) { - /* Timeout. */ - std::for_each(waitables.begin(), waitables.end(), std::mem_fn(&IWaitable::update_priority)); - } else if (rc != 0xF601 && rc != 0xE401) { - /* TODO: Panic. When can this happen? */ - } else { - std::for_each(waitables.begin(), waitables.begin() + handle_index, std::mem_fn(&IWaitable::update_priority)); - this->waitables.erase(this->waitables.begin() + handle_index); - delete w; - } - - /* Do deferred callback for each waitable. */ - for (auto & waitable : this->waitables) { - if (waitable->get_deferred()) { - waitable->handle_deferred(); - } - } - - /* Return waitable. */ - if (R_SUCCEEDED(rc)) { - if (w == this->new_waitable_event) { - w->handle_signaled(0); - this->waitables.push_back(w); - } else { - return w; - } - } - } -} - -Result MultiThreadedWaitableManager::add_waitable_callback(void *arg, Handle *handles, size_t num_handles, u64 timeout) { - MultiThreadedWaitableManager *this_ptr = (MultiThreadedWaitableManager *)arg; - svcClearEvent(handles[0]); - std::scoped_lock lk{this_ptr->lock}; - this_ptr->waitables.insert(this_ptr->waitables.end(), this_ptr->to_add_waitables.begin(), this_ptr->to_add_waitables.end()); - this_ptr->to_add_waitables.clear(); - return 0; -} - -void MultiThreadedWaitableManager::thread_func(void *t) { - MultiThreadedWaitableManager *this_ptr = (MultiThreadedWaitableManager *)t; - while (1) { - IWaitable *w = this_ptr->get_waitable(); - if (w) { - Result rc = w->handle_signaled(0); - if (rc == 0xF601) { - /* Close! */ - delete w; - } else { - this_ptr->add_waitable(w); - } - } - } -} diff --git a/stratosphere/libstratosphere/source/sm_mitm.c b/stratosphere/libstratosphere/source/sm_mitm.c new file mode 100644 index 000000000..0bbb284df --- /dev/null +++ b/stratosphere/libstratosphere/source/sm_mitm.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <switch/arm/atomics.h> +#include <stratosphere/mitm/sm_mitm.h> + +static Handle g_smMitmHandle = INVALID_HANDLE; +static u64 g_refCnt; + +Result smMitMInitialize(void) { + atomicIncrement64(&g_refCnt); + + if (g_smMitmHandle != INVALID_HANDLE) + return 0; + + Result rc = svcConnectToNamedPort(&g_smMitmHandle, "sm:"); + + if (R_SUCCEEDED(rc)) { + IpcCommand c; + ipcInitialize(&c); + ipcSendPid(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 zero; + u64 reserved[2]; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + raw->zero = 0; + + rc = ipcDispatch(g_smMitmHandle); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + } + + if (R_FAILED(rc)) + smExit(); + + return rc; +} + +void smMitMExit(void) { + if (atomicDecrement64(&g_refCnt) == 0) { + svcCloseHandle(g_smMitmHandle); + g_smMitmHandle = INVALID_HANDLE; + } +} + +Result smMitMGetService(Service* service_out, const char *name_str) +{ + u64 name = smEncodeName(name_str); + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + u64 reserved[2]; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 1; + raw->service_name = name; + + Result rc = ipcDispatch(g_smMitmHandle); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + service_out->type = ServiceType_Normal; + service_out->handle = r.Handles[0]; + } + } + + return rc; +} + + +Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65000; + raw->service_name = smEncodeName(name); + + Result rc = ipcDispatch(g_smMitmHandle); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *handle_out = r.Handles[0]; + *query_out = r.Handles[1]; + } + } + + return rc; +} + +Result smMitMUninstall(const char *name) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + u64 reserved; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65001; + raw->service_name = smEncodeName(name); + + Result rc = ipcDispatch(g_smMitmHandle); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} \ No newline at end of file diff --git a/stratosphere/libstratosphere/source/smm_ams.c b/stratosphere/libstratosphere/source/smm_ams.c new file mode 100644 index 000000000..2ac9e4e6e --- /dev/null +++ b/stratosphere/libstratosphere/source/smm_ams.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <switch/arm/atomics.h> +#include <stratosphere/services/smm_ams.h> + +static Service g_smManagerAmsSrv; +static u64 g_smManagerAmsRefcnt; + +Result smManagerAmsInitialize(void) { + atomicIncrement64(&g_smManagerAmsRefcnt); + + if (serviceIsActive(&g_smManagerAmsSrv)) + return 0; + + return smGetService(&g_smManagerAmsSrv, "sm:m"); +} + +void smManagerAmsExit(void) { + if (atomicDecrement64(&g_smManagerAmsRefcnt) == 0) + serviceClose(&g_smManagerAmsSrv); +} + +Result smManagerAmsEndInitialDefers(void) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65000; + + + Result rc = serviceIpcDispatch(&g_smManagerAmsSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; + +} \ No newline at end of file diff --git a/stratosphere/libstratosphere/source/waitablemanager.cpp b/stratosphere/libstratosphere/source/waitablemanager.cpp deleted file mode 100644 index 35706a006..000000000 --- a/stratosphere/libstratosphere/source/waitablemanager.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <switch.h> - -#include <algorithm> -#include <functional> -#include <mutex> - -#include <stratosphere/waitablemanager.hpp> - -void WaitableManager::add_waitable(IWaitable *waitable) { - std::scoped_lock lk{this->lock}; - this->to_add_waitables.push_back(waitable); - waitable->set_manager(this); - this->has_new_items = true; -} - -void WaitableManager::process_internal(bool break_on_timeout) { - std::vector<Handle> handles; - - int handle_index = 0; - Result rc; - - while (1) { - /* Add new items, if relevant. */ - if (this->has_new_items) { - std::scoped_lock lk{this->lock}; - this->waitables.insert(this->waitables.end(), this->to_add_waitables.begin(), this->to_add_waitables.end()); - this->to_add_waitables.clear(); - this->has_new_items = false; - } - - /* Sort waitables by priority. */ - std::sort(this->waitables.begin(), this->waitables.end(), IWaitable::compare); - - /* Copy out handles. */ - handles.resize(this->waitables.size()); - std::transform(this->waitables.begin(), this->waitables.end(), handles.begin(), [](IWaitable *w) { return w->get_handle(); }); - - - rc = svcWaitSynchronization(&handle_index, handles.data(), this->waitables.size(), this->timeout); - if (R_SUCCEEDED(rc)) { - /* Handle a signaled waitable. */ - /* TODO: What timeout should be passed here? */ - - rc = this->waitables[handle_index]->handle_signaled(0); - - std::for_each(waitables.begin(), waitables.begin() + handle_index, std::mem_fn(&IWaitable::update_priority)); - } else if (rc == 0xEA01) { - /* Timeout. */ - std::for_each(waitables.begin(), waitables.end(), std::mem_fn(&IWaitable::update_priority)); - if (break_on_timeout) { - return; - } - } else if (rc != 0xF601) { - /* TODO: Panic. When can this happen? */ - } - - if (rc == 0xF601) { - /* handles[handle_index] was closed! */ - - /* Close the handle. */ - svcCloseHandle(handles[handle_index]); - - IWaitable *to_delete = this->waitables[handle_index]; - - /* If relevant, remove from waitables. */ - this->waitables.erase(this->waitables.begin() + handle_index); - - /* Delete it. */ - delete to_delete; - - std::for_each(waitables.begin(), waitables.begin() + handle_index, std::mem_fn(&IWaitable::update_priority)); - } - - /* Do deferred callback for each waitable. */ - for (auto & waitable : this->waitables) { - if (waitable->get_deferred()) { - waitable->handle_deferred(); - } - } - } -} - -void WaitableManager::process() { - WaitableManager::process_internal(false); -} - -void WaitableManager::process_until_timeout() { - WaitableManager::process_internal(true); -} From 9a8c70ed681f48ae957fe65b833637ddea175315 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 17:28:37 -0700 Subject: [PATCH 144/489] sm: Update for libstratosphere refactor --- stratosphere/sm/sm.json | 3 +- stratosphere/sm/source/sm_main.cpp | 15 +-- stratosphere/sm/source/sm_manager_service.cpp | 35 +----- stratosphere/sm/source/sm_manager_service.hpp | 23 ++-- stratosphere/sm/source/sm_registration.cpp | 4 +- stratosphere/sm/source/sm_user_service.cpp | 102 ++++++------------ stratosphere/sm/source/sm_user_service.hpp | 49 +++++---- 7 files changed, 87 insertions(+), 144 deletions(-) diff --git a/stratosphere/sm/sm.json b/stratosphere/sm/sm.json index 0d3074e10..cce46d816 100644 --- a/stratosphere/sm/sm.json +++ b/stratosphere/sm/sm.json @@ -1,7 +1,7 @@ { "name" : "sm", "title_id" : "0x0100000000000004", - "main_thread_stack_size" : "0x1000", + "main_thread_stack_size" : "0x2000", "main_thread_priority" : 27, "default_cpu_id" : 3, "process_category" : 1, @@ -56,6 +56,7 @@ "svcReplyAndReceiveLight" : "0x42", "svcReplyAndReceive" : "0x43", "svcReplyAndReceiveWithUserBuffer" : "0x44", + "svcCreateEvent" : "0x45", "svcGetMemoryInfo" : "0x6F", "svcCreatePort" : "0x70", "svcManageNamedPort" : "0x71", diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index d9381b821..60ceb3c45 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -61,15 +61,18 @@ void __appExit(void) { /* Nothing to clean up, because we're sm. */ } + + + int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); /* TODO: What's a good timeout value to use here? */ - WaitableManager *server_manager = new WaitableManager(U64_MAX); - + auto server_manager = new WaitableManager(1); + /* Create sm:, (and thus allow things to register to it). */ - server_manager->add_waitable(new ManagedPortServer<UserService>("sm:", 0x40)); + server_manager->AddWaitable(new ManagedPortServer<UserService>("sm:", 0x40)); /* Create sm:m manually. */ Handle smm_h; @@ -78,10 +81,10 @@ int main(int argc, char **argv) while (1) { } } - server_manager->add_waitable(new ExistingPortServer<ManagerService>(smm_h, 1)); - + server_manager->AddWaitable(new ExistingPortServer<ManagerService>(smm_h, 1)); + /* Loop forever, servicing our services. */ - server_manager->process(); + server_manager->Process(); /* Cleanup. */ delete server_manager; diff --git a/stratosphere/sm/source/sm_manager_service.cpp b/stratosphere/sm/source/sm_manager_service.cpp index 03e0e5d95..1ae5ca624 100644 --- a/stratosphere/sm/source/sm_manager_service.cpp +++ b/stratosphere/sm/source/sm_manager_service.cpp @@ -19,40 +19,15 @@ #include "sm_manager_service.hpp" #include "sm_registration.hpp" -Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - switch ((ManagerServiceCmd)cmd_id) { - case Manager_Cmd_RegisterProcess: - rc = WrapIpcCommandImpl<&ManagerService::register_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Manager_Cmd_UnregisterProcess: - rc = WrapIpcCommandImpl<&ManagerService::unregister_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Manager_Cmd_AtmosphereEndInitDefers: - rc = WrapIpcCommandImpl<&ManagerService::end_init_defers>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - return rc; +Result ManagerService::RegisterProcess(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac) { + return Registration::RegisterProcess(pid, acid_sac.buffer, acid_sac.num_elements, aci0_sac.buffer, aci0_sac.num_elements); } -Result ManagerService::handle_deferred() { - /* This service is never deferrable. */ - return 0; +Result ManagerService::UnregisterProcess(u64 pid) { + return Registration::UnregisterProcess(pid); } - -std::tuple<Result> ManagerService::register_process(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac) { - return {Registration::RegisterProcess(pid, acid_sac.buffer, acid_sac.num_elements, aci0_sac.buffer, aci0_sac.num_elements)}; -} - -std::tuple<Result> ManagerService::unregister_process(u64 pid) { - return {Registration::UnregisterProcess(pid)}; -} - -std::tuple<Result> ManagerService::end_init_defers() { +void ManagerService::AtmosphereEndInitDefers() { Registration::EndInitDefers(); - return {0}; } diff --git a/stratosphere/sm/source/sm_manager_service.hpp b/stratosphere/sm/source/sm_manager_service.hpp index fd7a98647..080c4c93e 100644 --- a/stratosphere/sm/source/sm_manager_service.hpp +++ b/stratosphere/sm/source/sm_manager_service.hpp @@ -16,7 +16,7 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> enum ManagerServiceCmd { Manager_Cmd_RegisterProcess = 0, @@ -27,17 +27,16 @@ enum ManagerServiceCmd { }; class ManagerService final : public IServiceObject { - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override; - - ManagerService *clone() override { - return new ManagerService(); - } - private: /* Actual commands. */ - std::tuple<Result> register_process(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac); - std::tuple<Result> unregister_process(u64 pid); - std::tuple<Result> end_init_defers(); + virtual Result RegisterProcess(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac); + virtual Result UnregisterProcess(u64 pid); + virtual void AtmosphereEndInitDefers(); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<Manager_Cmd_RegisterProcess, &ManagerService::RegisterProcess>(), + MakeServiceCommandMeta<Manager_Cmd_UnregisterProcess, &ManagerService::UnregisterProcess>(), + + MakeServiceCommandMeta<Manager_Cmd_AtmosphereEndInitDefers, &ManagerService::AtmosphereEndInitDefers>(), + }; }; diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index 46c6d62fc..0932db1f7 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -16,7 +16,7 @@ #include <switch.h> #include <algorithm> -#include <stratosphere/servicesession.hpp> +#include <stratosphere.hpp> #include "sm_registration.hpp" #include "meta_tools.hpp" @@ -250,7 +250,7 @@ Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) { struct { u64 magic; u64 result; - u64 should_mitm; + bool should_mitm; } *resp = ((decltype(resp))r.Raw); rc = resp->result; if (R_SUCCEEDED(rc)) { diff --git a/stratosphere/sm/source/sm_user_service.cpp b/stratosphere/sm/source/sm_user_service.cpp index 00cf6f971..40079ec15 100644 --- a/stratosphere/sm/source/sm_user_service.cpp +++ b/stratosphere/sm/source/sm_user_service.cpp @@ -15,57 +15,20 @@ */ #include <switch.h> -#include <stratosphere/servicesession.hpp> +#include <stratosphere.hpp> #include "sm_user_service.hpp" #include "sm_registration.hpp" -Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - switch ((UserServiceCmd)cmd_id) { - case User_Cmd_Initialize: - rc = WrapIpcCommandImpl<&UserService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case User_Cmd_GetService: - rc = WrapIpcCommandImpl<&UserService::get_service>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case User_Cmd_RegisterService: - rc = WrapIpcCommandImpl<&UserService::register_service>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case User_Cmd_UnregisterService: - rc = WrapIpcCommandImpl<&UserService::unregister_service>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; -#ifdef SM_ENABLE_MITM - case User_Cmd_AtmosphereInstallMitm: - rc = WrapIpcCommandImpl<&UserService::install_mitm>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case User_Cmd_AtmosphereUninstallMitm: - rc = WrapIpcCommandImpl<&UserService::uninstall_mitm>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case User_Cmd_AtmosphereAssociatePidTidForMitm: - rc = WrapIpcCommandImpl<&UserService::associate_pid_tid_for_mitm>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; -#endif - default: - break; - } - return rc; -} - -Result UserService::handle_deferred() { - /* If we're deferred, GetService failed. */ - return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service); -} - - -std::tuple<Result> UserService::initialize(PidDescriptor pid) { +Result UserService::Initialize(PidDescriptor pid) { this->pid = pid.pid; this->has_initialized = true; - return {0}; + return 0; } -std::tuple<Result, MovedHandle> UserService::get_service(u64 service) { +Result UserService::GetService(Out<MovedHandle> out_h, u64 service) { Handle session_h = 0; Result rc = 0x415; + #ifdef SM_ENABLE_SMHAX if (!this->has_initialized) { rc = Registration::GetServiceForPid(Registration::GetInitialProcessId(), service, &session_h); @@ -74,20 +37,14 @@ std::tuple<Result, MovedHandle> UserService::get_service(u64 service) { if (this->has_initialized) { rc = Registration::GetServiceForPid(this->pid, service, &session_h); } - /* It's possible that this will end up deferring us...take that into account. */ - if (rc == RESULT_DEFER_SESSION) { - this->deferred_service = service; + + if (R_SUCCEEDED(rc)) { + out_h.SetValue(session_h); } - return {rc, MovedHandle{session_h}}; + return rc; } -std::tuple<Result, MovedHandle> UserService::deferred_get_service(u64 service) { - Handle session_h = 0; - Result rc = Registration::GetServiceHandle(this->pid, service, &session_h); - return {rc, MovedHandle{session_h}}; -} - -std::tuple<Result, MovedHandle> UserService::register_service(u64 service, u8 is_light, u32 max_sessions) { +Result UserService::RegisterService(Out<MovedHandle> out_h, u64 service, u8 is_light, u32 max_sessions) { Handle service_h = 0; Result rc = 0x415; #ifdef SM_ENABLE_SMHAX @@ -98,10 +55,14 @@ std::tuple<Result, MovedHandle> UserService::register_service(u64 service, u8 is if (this->has_initialized) { rc = Registration::RegisterServiceForPid(this->pid, service, max_sessions, (is_light & 1) != 0, &service_h); } - return {rc, MovedHandle{service_h}}; + + if (R_SUCCEEDED(rc)) { + out_h.SetValue(service_h); + } + return rc; } -std::tuple<Result> UserService::unregister_service(u64 service) { +Result UserService::UnregisterService(u64 service) { Result rc = 0x415; #ifdef SM_ENABLE_SMHAX if (!this->has_initialized) { @@ -111,20 +72,33 @@ std::tuple<Result> UserService::unregister_service(u64 service) { if (this->has_initialized) { rc = Registration::UnregisterServiceForPid(this->pid, service); } - return {rc}; + return rc; } -std::tuple<Result, MovedHandle, MovedHandle> UserService::install_mitm(u64 service) { +Result UserService::AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, u64 service) { Handle service_h = 0; Handle query_h = 0; Result rc = 0x415; if (this->has_initialized) { rc = Registration::InstallMitmForPid(this->pid, service, &service_h, &query_h); } - return {rc, MovedHandle{service_h}, MovedHandle{query_h}}; + + if (R_SUCCEEDED(rc)) { + srv_h.SetValue(service_h); + qry_h.SetValue(query_h); + } + return rc; } -std::tuple<Result> UserService::associate_pid_tid_for_mitm(u64 pid, u64 tid) { +Result UserService::AtmosphereUninstallMitm(u64 service) { + Result rc = 0x415; + if (this->has_initialized) { + rc = Registration::UninstallMitmForPid(this->pid, service); + } + return rc; +} + +Result UserService::AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid) { Result rc = 0x415; if (this->has_initialized) { if (Registration::IsInitialProcess(pid)) { @@ -133,13 +107,5 @@ std::tuple<Result> UserService::associate_pid_tid_for_mitm(u64 pid, u64 tid) { rc = Registration::AssociatePidTidForMitm(pid, tid); } } - return {rc}; + return rc; } - -std::tuple<Result> UserService::uninstall_mitm(u64 service) { - Result rc = 0x415; - if (this->has_initialized) { - rc = Registration::UninstallMitmForPid(this->pid, service); - } - return {rc}; -} \ No newline at end of file diff --git a/stratosphere/sm/source/sm_user_service.hpp b/stratosphere/sm/source/sm_user_service.hpp index 8f3250472..206b4f771 100644 --- a/stratosphere/sm/source/sm_user_service.hpp +++ b/stratosphere/sm/source/sm_user_service.hpp @@ -16,7 +16,7 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> enum UserServiceCmd { User_Cmd_Initialize = 0, @@ -30,32 +30,31 @@ enum UserServiceCmd { }; class UserService final : public IServiceObject { - u64 pid = U64_MAX; - bool has_initialized = false; - u64 deferred_service = 0; - - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override; - - UserService *clone() override { - auto new_srv = new UserService(); - new_srv->pid = pid; - new_srv->has_initialized = has_initialized; - new_srv->deferred_service = deferred_service; - return new_srv; - } - private: + u64 pid = U64_MAX; + bool has_initialized = false; + /* Actual commands. */ - std::tuple<Result> initialize(PidDescriptor pid); - std::tuple<Result, MovedHandle> get_service(u64 service); - std::tuple<Result, MovedHandle> deferred_get_service(u64 service); - std::tuple<Result, MovedHandle> register_service(u64 service, u8 is_light, u32 max_sessions); - std::tuple<Result> unregister_service(u64 service); + virtual Result Initialize(PidDescriptor pid); + virtual Result GetService(Out<MovedHandle> out_h, u64 service); + virtual Result RegisterService(Out<MovedHandle> out_h, u64 service, u8 is_light, u32 max_sessions); + virtual Result UnregisterService(u64 service); /* Atmosphere commands. */ - std::tuple<Result, MovedHandle, MovedHandle> install_mitm(u64 service); - std::tuple<Result> uninstall_mitm(u64 service); - std::tuple<Result> associate_pid_tid_for_mitm(u64 pid, u64 tid); + virtual Result AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, u64 service); + virtual Result AtmosphereUninstallMitm(u64 service); + virtual Result AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<User_Cmd_Initialize, &UserService::Initialize>(), + MakeServiceCommandMeta<User_Cmd_GetService, &UserService::GetService>(), + MakeServiceCommandMeta<User_Cmd_RegisterService, &UserService::RegisterService>(), + MakeServiceCommandMeta<User_Cmd_UnregisterService, &UserService::UnregisterService>(), + +#ifdef SM_ENABLE_MITM + MakeServiceCommandMeta<User_Cmd_AtmosphereInstallMitm, &UserService::AtmosphereInstallMitm>(), + MakeServiceCommandMeta<User_Cmd_AtmosphereUninstallMitm, &UserService::AtmosphereUninstallMitm>(), + MakeServiceCommandMeta<User_Cmd_AtmosphereAssociatePidTidForMitm, &UserService::AtmosphereAssociatePidTidForMitm>(), +#endif + }; }; From 887b4e027588e758b753c7993d86c1d3ef856bdd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 17:29:35 -0700 Subject: [PATCH 145/489] pm: update for libstratosphere refactor --- stratosphere/pm/pm.json | 2 +- stratosphere/pm/source/pm_boot2.cpp | 2 +- stratosphere/pm/source/pm_boot_mode.cpp | 29 +--- stratosphere/pm/source/pm_boot_mode.hpp | 21 ++- stratosphere/pm/source/pm_debug_monitor.cpp | 168 +++++--------------- stratosphere/pm/source/pm_debug_monitor.hpp | 67 ++++---- stratosphere/pm/source/pm_info.cpp | 27 +--- stratosphere/pm/source/pm_info.hpp | 15 +- stratosphere/pm/source/pm_main.cpp | 13 +- stratosphere/pm/source/pm_process_track.cpp | 7 +- stratosphere/pm/source/pm_process_wait.hpp | 23 +-- stratosphere/pm/source/pm_registration.cpp | 61 ++++--- stratosphere/pm/source/pm_registration.hpp | 3 +- stratosphere/pm/source/pm_shell.cpp | 168 +++++--------------- stratosphere/pm/source/pm_shell.hpp | 59 ++++--- stratosphere/pm/source/smm_ams.c | 69 -------- stratosphere/pm/source/smm_ams.h | 21 --- 17 files changed, 229 insertions(+), 526 deletions(-) delete mode 100644 stratosphere/pm/source/smm_ams.c delete mode 100644 stratosphere/pm/source/smm_ams.h diff --git a/stratosphere/pm/pm.json b/stratosphere/pm/pm.json index a7bd7e8a9..e9f28ad36 100644 --- a/stratosphere/pm/pm.json +++ b/stratosphere/pm/pm.json @@ -1,7 +1,7 @@ { "name": "ProcessMana", "title_id": "0x0100000000000003", - "main_thread_stack_size": "0x00001000", + "main_thread_stack_size": "0x00002000", "main_thread_priority": 49, "default_cpu_id": 3, "process_category": 1, diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 2f22c9d11..3a6844621 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -173,7 +173,7 @@ void EmbeddedBoot2::Main() { } closedir(titles_dir); } - + /* We no longer need the SD card. */ fsdevUnmountAll(); } diff --git a/stratosphere/pm/source/pm_boot_mode.cpp b/stratosphere/pm/source/pm_boot_mode.cpp index 7b83ee1e8..7268660cc 100644 --- a/stratosphere/pm/source/pm_boot_mode.cpp +++ b/stratosphere/pm/source/pm_boot_mode.cpp @@ -20,33 +20,10 @@ static bool g_is_maintenance_boot = false; -Result BootModeService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - - switch ((BootModeCmd)cmd_id) { - case BootMode_Cmd_GetBootMode: - rc = WrapIpcCommandImpl<&BootModeService::get_boot_mode>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case BootMode_Cmd_SetMaintenanceBoot: - rc = WrapIpcCommandImpl<&BootModeService::set_maintenance_boot>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - - return rc; +void BootModeService::GetBootMode(Out<bool> out) { + out.SetValue(g_is_maintenance_boot); } -Result BootModeService::handle_deferred() { - /* This service is never deferrable. */ - return 0; -} - -std::tuple<Result, bool> BootModeService::get_boot_mode() { - return {0, g_is_maintenance_boot}; -} - -std::tuple<Result> BootModeService::set_maintenance_boot() { +void BootModeService::SetMaintenanceBoot() { g_is_maintenance_boot = true; - return {0}; } diff --git a/stratosphere/pm/source/pm_boot_mode.hpp b/stratosphere/pm/source/pm_boot_mode.hpp index 097dace3a..96572797f 100644 --- a/stratosphere/pm/source/pm_boot_mode.hpp +++ b/stratosphere/pm/source/pm_boot_mode.hpp @@ -16,24 +16,21 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> enum BootModeCmd { BootMode_Cmd_GetBootMode = 0, BootMode_Cmd_SetMaintenanceBoot = 1 }; -class BootModeService final : public IServiceObject { - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override; - - BootModeService *clone() override { - return new BootModeService(*this); - } - +class BootModeService final : public IServiceObject { private: /* Actual commands. */ - std::tuple<Result, bool> get_boot_mode(); - std::tuple<Result> set_maintenance_boot(); + void GetBootMode(Out<bool> out); + void SetMaintenanceBoot(); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<BootMode_Cmd_GetBootMode, &BootModeService::GetBootMode>(), + MakeServiceCommandMeta<BootMode_Cmd_SetMaintenanceBoot, &BootModeService::SetMaintenanceBoot>(), + }; }; diff --git a/stratosphere/pm/source/pm_debug_monitor.cpp b/stratosphere/pm/source/pm_debug_monitor.cpp index 8555fc8dd..a9d4312d2 100644 --- a/stratosphere/pm/source/pm_debug_monitor.cpp +++ b/stratosphere/pm/source/pm_debug_monitor.cpp @@ -20,172 +20,88 @@ #include "pm_resource_limits.hpp" #include "pm_debug_monitor.hpp" -Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - if (kernelAbove500()) { - switch ((DmntCmd_5X)cmd_id) { - case Dmnt_Cmd_5X_GetDebugProcessIds: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_debug_process_ids>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_5X_LaunchDebugProcess: - rc = WrapIpcCommandImpl<&DebugMonitorService::launch_debug_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_5X_GetTitleProcessId: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_title_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_5X_EnableDebugForTitleId: - rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_tid>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_5X_GetApplicationProcessId: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_5X_EnableDebugForApplication: - rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_application>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_6X_DisableDebug: - if (kernelAbove600()) { - rc = WrapIpcCommandImpl<&DebugMonitorService::disable_debug>(this, r, out_c, pointer_buffer, pointer_buffer_size); - } - break; - case Dmnt_Cmd_5X_AtmosphereGetProcessHandle: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_process_handle>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_5X_AtmosphereGetCurrentLimitInfo: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_current_limit_info>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - } else { - switch ((DmntCmd)cmd_id) { - case Dmnt_Cmd_GetUnknownStub: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_unknown_stub>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_GetDebugProcessIds: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_debug_process_ids>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_LaunchDebugProcess: - rc = WrapIpcCommandImpl<&DebugMonitorService::launch_debug_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_GetTitleProcessId: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_title_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_EnableDebugForTitleId: - rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_tid>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_GetApplicationProcessId: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_EnableDebugForApplication: - rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_application>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_AtmosphereGetProcessHandle: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_process_handle>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_AtmosphereGetCurrentLimitInfo: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_current_limit_info>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } + +Result DebugMonitorService::GetUnknownStub(Out<u32> count, OutBuffer<u8> out_buf, u64 in_unk) { + /* This command seems stubbed. */ + if (out_buf.num_elements >> 31) { + return 0xC0F; } - return rc; + count.SetValue(0); + return 0x0; } -Result DebugMonitorService::handle_deferred() { - /* This service is never deferrable. */ - return 0; -} - - -std::tuple<Result, u32> DebugMonitorService::get_unknown_stub(u64 unknown, OutBuffer<u8> out_unknown) { - /* This command seem stubbed on retail. */ - if (out_unknown.num_elements >> 31) { - return {0xC0F, 0}; - } - return {0x0, 0}; -} - -std::tuple<Result, u32> DebugMonitorService::get_debug_process_ids(OutBuffer<u64> out_pids) { - u32 num_out = 0; - Result rc; +Result DebugMonitorService::GetDebugProcessIds(Out<u32> count, OutBuffer<u64> out_pids) { if (out_pids.num_elements >> 31) { - return {0xC0F, 0}; + return 0xC0F; } - rc = Registration::GetDebugProcessIds(out_pids.buffer, out_pids.num_elements, &num_out); - return {rc, num_out}; + return Registration::GetDebugProcessIds(out_pids.buffer, out_pids.num_elements, count.GetPointer()); } -std::tuple<Result> DebugMonitorService::launch_debug_process(u64 pid) { - return {Registration::LaunchDebugProcess(pid)}; +Result DebugMonitorService::LaunchDebugProcess(u64 pid) { + return Registration::LaunchDebugProcess(pid); } -std::tuple<Result, u64> DebugMonitorService::get_title_process_id(u64 tid) { +Result DebugMonitorService::GetTitleProcessId(Out<u64> pid, u64 tid) { auto auto_lock = Registration::GetProcessListUniqueLock(); std::shared_ptr<Registration::Process> proc = Registration::GetProcessByTitleId(tid); if (proc != nullptr) { - return {0, proc->pid}; - } else { - return {0x20F, 0}; + pid.SetValue(proc->pid); + return 0; } + return 0x20F; } -std::tuple<Result, CopiedHandle> DebugMonitorService::enable_debug_for_tid(u64 tid) { - Handle h = 0; - Result rc = Registration::EnableDebugForTitleId(tid, &h); - return {rc, h}; +Result DebugMonitorService::EnableDebugForTitleId(Out<CopiedHandle> event, u64 tid) { + return Registration::EnableDebugForTitleId(tid, event.GetHandlePointer()); } -std::tuple<Result, u64> DebugMonitorService::get_application_process_id() { +Result DebugMonitorService::GetApplicationProcessId(Out<u64> pid) { auto auto_lock = Registration::GetProcessListUniqueLock(); std::shared_ptr<Registration::Process> app_proc; if (Registration::HasApplicationProcess(&app_proc)) { - return {0, app_proc->pid}; + pid.SetValue(app_proc->pid); + return 0x0; } - return {0x20F, 0}; + return 0x20F; } -std::tuple<Result, CopiedHandle> DebugMonitorService::enable_debug_for_application() { - Handle h = 0; - Result rc = Registration::EnableDebugForApplication(&h); - return {rc, h}; +Result DebugMonitorService::EnableDebugForApplication(Out<CopiedHandle> event) { + return Registration::EnableDebugForApplication(event.GetHandlePointer()); } -std::tuple<Result> DebugMonitorService::disable_debug(u32 which) { - return {Registration::DisableDebug(which)}; +Result DebugMonitorService::DisableDebug(u32 which) { + return Registration::DisableDebug(which); } -std::tuple<Result, CopiedHandle> DebugMonitorService::get_process_handle(u64 pid) { - std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid); - if(proc == NULL) { - return {0x20F, 0}; +Result DebugMonitorService::AtmosphereGetProcessHandle(Out<CopiedHandle> proc_hand, u64 pid) { + auto proc = Registration::GetProcess(pid); + if(proc != nullptr) { + proc_hand.SetValue(proc->handle); + return 0; } - return {0, proc->handle}; + return 0x20F; } -std::tuple<Result, u64, u64> DebugMonitorService::get_current_limit_info(u32 category, u32 resource) { +Result DebugMonitorService::AtmosphereGetCurrentLimitInfo(Out<u64> cur_val, Out<u64> lim_val, u32 category, u32 resource) { + Result rc; if(category > ResourceLimitUtils::ResourceLimitCategory::ResourceLimitCategory_Applet) { - return {0xf001, 0, 0}; + return 0xF001; } Handle limit_h = ResourceLimitUtils::GetResourceLimitHandleByCategory((ResourceLimitUtils::ResourceLimitCategory) category); - uint64_t current_value, limit_value; - - Result r; - - r = svcGetResourceLimitCurrentValue(¤t_value, limit_h, (LimitableResource) resource); - if(R_FAILED(r)) { - return {r, 0, 0}; + rc = svcGetResourceLimitCurrentValue(cur_val.GetPointer(), limit_h, (LimitableResource) resource); + if(R_FAILED(rc)) { + return rc; } - r = svcGetResourceLimitLimitValue(&limit_value, limit_h, (LimitableResource) resource); - if(R_FAILED(r)) { - return {r, 0, 0}; + rc = svcGetResourceLimitLimitValue(lim_val.GetPointer(), limit_h, (LimitableResource) resource); + if(R_FAILED(rc)) { + return rc; } - return {0, current_value, limit_value}; + return 0; } diff --git a/stratosphere/pm/source/pm_debug_monitor.hpp b/stratosphere/pm/source/pm_debug_monitor.hpp index 24c2d7839..88445bc60 100644 --- a/stratosphere/pm/source/pm_debug_monitor.hpp +++ b/stratosphere/pm/source/pm_debug_monitor.hpp @@ -16,7 +16,7 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> #include "pm_registration.hpp" @@ -28,12 +28,7 @@ enum DmntCmd { Dmnt_Cmd_EnableDebugForTitleId = 4, Dmnt_Cmd_GetApplicationProcessId = 5, Dmnt_Cmd_EnableDebugForApplication = 6, - - Dmnt_Cmd_AtmosphereGetProcessHandle = 65000, - Dmnt_Cmd_AtmosphereGetCurrentLimitInfo = 65001, -}; - -enum DmntCmd_5X { + Dmnt_Cmd_5X_GetDebugProcessIds = 0, Dmnt_Cmd_5X_LaunchDebugProcess = 1, Dmnt_Cmd_5X_GetTitleProcessId = 2, @@ -43,31 +38,49 @@ enum DmntCmd_5X { Dmnt_Cmd_6X_DisableDebug = 6, - Dmnt_Cmd_5X_AtmosphereGetProcessHandle = 65000, - Dmnt_Cmd_5X_AtmosphereGetCurrentLimitInfo = 65001, + Dmnt_Cmd_AtmosphereGetProcessHandle = 65000, + Dmnt_Cmd_AtmosphereGetCurrentLimitInfo = 65001, }; class DebugMonitorService final : public IServiceObject { - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override; - - DebugMonitorService *clone() override { - return new DebugMonitorService(*this); - } - private: /* Actual commands. */ - std::tuple<Result, u32> get_unknown_stub(u64 unknown, OutBuffer<u8> out_unknown); - std::tuple<Result, u32> get_debug_process_ids(OutBuffer<u64> out_processes); - std::tuple<Result> launch_debug_process(u64 pid); - std::tuple<Result, u64> get_title_process_id(u64 tid); - std::tuple<Result, CopiedHandle> enable_debug_for_tid(u64 tid); - std::tuple<Result, u64> get_application_process_id(); - std::tuple<Result, CopiedHandle> enable_debug_for_application(); - std::tuple<Result> disable_debug(u32 which); + Result GetUnknownStub(Out<u32> count, OutBuffer<u8> out_buf, u64 in_unk); + Result GetDebugProcessIds(Out<u32> count, OutBuffer<u64> out_pids); + Result LaunchDebugProcess(u64 pid); + Result GetTitleProcessId(Out<u64> pid, u64 tid); + Result EnableDebugForTitleId(Out<CopiedHandle> event, u64 tid); + Result GetApplicationProcessId(Out<u64> pid); + Result EnableDebugForApplication(Out<CopiedHandle> event); + Result DisableDebug(u32 which); /* Atmosphere commands. */ - std::tuple<Result, CopiedHandle> get_process_handle(u64 pid); - std::tuple<Result, u64, u64> get_current_limit_info(u32 category, u32 resource); + Result AtmosphereGetProcessHandle(Out<CopiedHandle> proc_hand, u64 pid); + Result AtmosphereGetCurrentLimitInfo(Out<u64> cur_val, Out<u64> lim_val, u32 category, u32 resource); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + /* 1.0.0-4.1.0 */ + MakeServiceCommandMeta<Dmnt_Cmd_GetUnknownStub, &DebugMonitorService::GetUnknownStub, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Dmnt_Cmd_GetDebugProcessIds, &DebugMonitorService::GetDebugProcessIds, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Dmnt_Cmd_LaunchDebugProcess, &DebugMonitorService::LaunchDebugProcess, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Dmnt_Cmd_GetTitleProcessId, &DebugMonitorService::GetTitleProcessId, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Dmnt_Cmd_EnableDebugForTitleId, &DebugMonitorService::EnableDebugForTitleId, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Dmnt_Cmd_GetApplicationProcessId, &DebugMonitorService::GetApplicationProcessId, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Dmnt_Cmd_EnableDebugForApplication, &DebugMonitorService::EnableDebugForApplication, FirmwareVersion_Min, FirmwareVersion_400>(), + + /* 5.0.0-* */ + MakeServiceCommandMeta<Dmnt_Cmd_5X_GetDebugProcessIds, &DebugMonitorService::GetDebugProcessIds, FirmwareVersion_500>(), + MakeServiceCommandMeta<Dmnt_Cmd_5X_LaunchDebugProcess, &DebugMonitorService::LaunchDebugProcess, FirmwareVersion_500>(), + MakeServiceCommandMeta<Dmnt_Cmd_5X_GetTitleProcessId, &DebugMonitorService::GetTitleProcessId, FirmwareVersion_500>(), + MakeServiceCommandMeta<Dmnt_Cmd_5X_EnableDebugForTitleId, &DebugMonitorService::EnableDebugForTitleId, FirmwareVersion_500>(), + MakeServiceCommandMeta<Dmnt_Cmd_5X_GetApplicationProcessId, &DebugMonitorService::GetApplicationProcessId, FirmwareVersion_500>(), + MakeServiceCommandMeta<Dmnt_Cmd_5X_EnableDebugForApplication, &DebugMonitorService::EnableDebugForApplication, FirmwareVersion_500>(), + + /* 6.0.0-* */ + MakeServiceCommandMeta<Dmnt_Cmd_6X_DisableDebug, &DebugMonitorService::DisableDebug, FirmwareVersion_600>(), + + /* Atmosphere extensions. */ + MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetProcessHandle, &DebugMonitorService::AtmosphereGetProcessHandle>(), + MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetCurrentLimitInfo, &DebugMonitorService::AtmosphereGetCurrentLimitInfo>(), + }; }; diff --git a/stratosphere/pm/source/pm_info.cpp b/stratosphere/pm/source/pm_info.cpp index 437c75a8c..4498a9f1a 100644 --- a/stratosphere/pm/source/pm_info.cpp +++ b/stratosphere/pm/source/pm_info.cpp @@ -18,32 +18,13 @@ #include "pm_registration.hpp" #include "pm_info.hpp" -Result InformationService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - - switch ((InformationCmd)cmd_id) { - case Information_Cmd_GetTitleId: - rc = WrapIpcCommandImpl<&InformationService::get_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - - return rc; -} - -Result InformationService::handle_deferred() { - /* This service is never deferrable. */ - return 0; -} - -std::tuple<Result, u64> InformationService::get_title_id(u64 pid) { +Result InformationService::GetTitleId(Out<u64> tid, u64 pid) { auto auto_lock = Registration::GetProcessListUniqueLock(); std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid); if (proc != NULL) { - return {0x0, proc->tid_sid.title_id}; - } else { - return {0x20F, 0x0}; + tid.SetValue(proc->tid_sid.title_id); + return 0; } + return 0x20F; } diff --git a/stratosphere/pm/source/pm_info.hpp b/stratosphere/pm/source/pm_info.hpp index bc7ce5cd9..ea0879576 100644 --- a/stratosphere/pm/source/pm_info.hpp +++ b/stratosphere/pm/source/pm_info.hpp @@ -17,22 +17,17 @@ #pragma once #include <switch.h> #include <stratosphere.hpp> -#include <stratosphere/iserviceobject.hpp> enum InformationCmd { Information_Cmd_GetTitleId = 0, }; class InformationService final : public IServiceObject { - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override; - - InformationService *clone() override { - return new InformationService(*this); - } - private: /* Actual commands. */ - std::tuple<Result, u64> get_title_id(u64 pid); + Result GetTitleId(Out<u64> tid, u64 pid); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<Information_Cmd_GetTitleId, &InformationService::GetTitleId>(), + }; }; diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 034567ecf..2e15f12c8 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -28,7 +28,6 @@ #include "pm_process_track.hpp" #include "pm_registration.hpp" #include "pm_debug_monitor.hpp" -#include "smm_ams.h" extern "C" { extern u32 __start__; @@ -150,16 +149,16 @@ int main(int argc, char **argv) } /* TODO: What's a good timeout value to use here? */ - WaitableManager *server_manager = new WaitableManager(U64_MAX); + auto server_manager = new WaitableManager(1); /* TODO: Create services. */ - server_manager->add_waitable(new ServiceServer<ShellService>("pm:shell", 3)); - server_manager->add_waitable(new ServiceServer<DebugMonitorService>("pm:dmnt", 2)); - server_manager->add_waitable(new ServiceServer<BootModeService>("pm:bm", 5)); - server_manager->add_waitable(new ServiceServer<InformationService>("pm:info", 1)); + server_manager->AddWaitable(new ServiceServer<ShellService>("pm:shell", 3)); + server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("pm:dmnt", 2)); + server_manager->AddWaitable(new ServiceServer<BootModeService>("pm:bm", 5)); + server_manager->AddWaitable(new ServiceServer<InformationService>("pm:info", 1)); /* Loop forever, servicing our services. */ - server_manager->process(); + server_manager->Process(); /* Cleanup. */ delete server_manager; diff --git a/stratosphere/pm/source/pm_process_track.cpp b/stratosphere/pm/source/pm_process_track.cpp index 6de7f8603..bfb2aa623 100644 --- a/stratosphere/pm/source/pm_process_track.cpp +++ b/stratosphere/pm/source/pm_process_track.cpp @@ -21,12 +21,11 @@ void ProcessTracking::MainLoop(void *arg) { /* Make a new waitable manager. */ - MultiThreadedWaitableManager *process_waiter = new MultiThreadedWaitableManager(1, U64_MAX); - process_waiter->add_waitable(Registration::GetProcessLaunchStartEvent()); - Registration::SetProcessListManager(process_waiter); + auto process_waiter = new WaitableManager(1); + process_waiter->AddWaitable(Registration::GetProcessLaunchStartEvent()); /* Service processes. */ - process_waiter->process(); + process_waiter->Process(); delete process_waiter; svcExitThread(); diff --git a/stratosphere/pm/source/pm_process_wait.hpp b/stratosphere/pm/source/pm_process_wait.hpp index 49a85a594..14df0468a 100644 --- a/stratosphere/pm/source/pm_process_wait.hpp +++ b/stratosphere/pm/source/pm_process_wait.hpp @@ -28,41 +28,28 @@ class ProcessWaiter final : public IWaitable { /* ... */ } - std::shared_ptr<Registration::Process> get_process() { + std::shared_ptr<Registration::Process> GetProcess() { return this->process; } /* IWaitable */ - Handle get_handle() override { + Handle GetHandle() override { return this->process->handle; } - void handle_deferred() override { - /* TODO: Panic, because we can never be deferred. */ - } - - Result handle_signaled(u64 timeout) override { - return Registration::HandleSignaledProcess(this->get_process()); + Result HandleSignaled(u64 timeout) override { + return Registration::HandleSignaledProcess(this->GetProcess()); } }; class ProcessList final { private: HosRecursiveMutex mutex; - WaitableManager *manager; public: std::vector<std::shared_ptr<Registration::Process>> processes; - auto get_unique_lock() { + auto GetUniqueLock() { return std::unique_lock{this->mutex}; } - - void set_manager(WaitableManager *manager) { - this->manager = manager; - } - - WaitableManager *get_manager() { - return this->manager; - } }; diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index 7db40e156..529b892e8 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -25,7 +25,7 @@ static ProcessList g_process_list; static ProcessList g_dead_process_list; -static SystemEvent *g_process_launch_start_event = NULL; +static IEvent *g_process_launch_start_event = nullptr; static HosSemaphore g_sema_finish_launch; static HosMutex g_process_launch_mutex; @@ -34,29 +34,27 @@ static Registration::ProcessLaunchState g_process_launch_state; static std::atomic_bool g_debug_next_application(false); static std::atomic<u64> g_debug_on_launch_tid(0); -static SystemEvent *g_process_event = NULL; -static SystemEvent *g_debug_title_event = NULL; -static SystemEvent *g_debug_application_event = NULL; +static IEvent *g_process_event = nullptr; +static IEvent *g_debug_title_event = nullptr; +static IEvent *g_debug_application_event = nullptr; std::unique_lock<HosRecursiveMutex> Registration::GetProcessListUniqueLock() { - return g_process_list.get_unique_lock(); -} - -void Registration::SetProcessListManager(WaitableManager *m) { - g_process_list.set_manager(m); + return g_process_list.GetUniqueLock(); } void Registration::InitializeSystemResources() { - g_process_event = new SystemEvent(NULL, &IEvent::PanicCallback); - g_debug_title_event = new SystemEvent(NULL, &IEvent::PanicCallback); - g_debug_application_event = new SystemEvent(NULL, &IEvent::PanicCallback); - g_process_launch_start_event = new SystemEvent(NULL, &Registration::ProcessLaunchStartCallback); + g_process_event = CreateWriteOnlySystemEvent(); + g_debug_title_event = CreateWriteOnlySystemEvent(); + g_debug_application_event = CreateWriteOnlySystemEvent(); + + /* Auto-clear non-system event. */ + g_process_launch_start_event = CreateSystemEvent(&Registration::ProcessLaunchStartCallback); ResourceLimitUtils::InitializeLimits(); } -Result Registration::ProcessLaunchStartCallback(void *arg, Handle *handles, size_t num_handles, u64 timeout) { - svcClearEvent(handles[0]); +Result Registration::ProcessLaunchStartCallback(u64 timeout) { + g_process_launch_start_event->Clear(); Registration::HandleProcessLaunch(); return 0; } @@ -138,11 +136,11 @@ void Registration::HandleProcessLaunch() { /* Signal, if relevant. */ if (new_process.tid_sid.title_id == g_debug_on_launch_tid.load()) { - g_debug_title_event->signal_event(); + g_debug_title_event->Signal(); g_debug_on_launch_tid = 0; rc = 0; } else if ((new_process.flags & PROCESSFLAGS_APPLICATION) && g_debug_next_application.load()) { - g_debug_application_event->signal_event(); + g_debug_application_event->Signal(); g_debug_next_application = false; rc = 0; } else if (LAUNCHFLAGS_STARTSUSPENDED(launch_flags)) { @@ -181,6 +179,7 @@ HANDLE_PROCESS_LAUNCH_END: if (R_SUCCEEDED(rc)) { *out_pid = new_process.pid; } + g_sema_finish_launch.Signal(); } @@ -220,9 +219,9 @@ Result Registration::LaunchProcess(u64 title_id, FsStorageId storage_id, u64 lau g_process_launch_state.out_pid = out_pid; /* Start a launch, and wait for it to exit. */ - g_process_launch_start_event->signal_event(); + g_process_launch_start_event->Signal(); g_sema_finish_launch.Wait(); - + return g_process_launch_state.result; } @@ -253,7 +252,7 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) { process->flags &= ~(PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED); process->flags |= PROCESSFLAGS_DEBUGEVENTPENDING; - g_process_event->signal_event(); + g_process_event->Signal(); } if (kernelAbove200() && process->flags & PROCESSFLAGS_NOTIFYDEBUGSPECIAL) { process->flags &= ~(PROCESSFLAGS_NOTIFYDEBUGSPECIAL | PROCESSFLAGS_DEBUGDETACHED); @@ -262,18 +261,18 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process break; case ProcessState_Crashed: process->flags |= (PROCESSFLAGS_CRASHED | PROCESSFLAGS_CRASH_DEBUG); - g_process_event->signal_event(); + g_process_event->Signal(); break; case ProcessState_RunningAttached: if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) { process->flags &= ~(PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED); process->flags |= PROCESSFLAGS_DEBUGEVENTPENDING; - g_process_event->signal_event(); + g_process_event->Signal(); } break; case ProcessState_Exited: if (process->flags & PROCESSFLAGS_NOTIFYWHENEXITED && !kernelAbove500()) { - g_process_event->signal_event(); + g_process_event->Signal(); } else { FinalizeExitedProcess(process); } @@ -281,7 +280,7 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process case ProcessState_DebugSuspended: if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) { process->flags |= (PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED); - g_process_event->signal_event(); + g_process_event->Signal(); } break; } @@ -310,7 +309,7 @@ void Registration::FinalizeExitedProcess(std::shared_ptr<Registration::Process> /* Insert into dead process list, if relevant. */ if (signal_debug_process_5x) { - auto lk = g_dead_process_list.get_unique_lock(); + auto lk = g_dead_process_list.GetUniqueLock(); g_dead_process_list.processes.push_back(process); } @@ -319,14 +318,14 @@ void Registration::FinalizeExitedProcess(std::shared_ptr<Registration::Process> auto_lock.unlock(); if (signal_debug_process_5x) { - g_process_event->signal_event(); + g_process_event->Signal(); } } void Registration::AddProcessToList(std::shared_ptr<Registration::Process> process) { auto auto_lock = GetProcessListUniqueLock(); g_process_list.processes.push_back(process); - g_process_list.get_manager()->add_waitable(new ProcessWaiter(process)); + g_process_launch_start_event->GetManager()->AddWaitable(new ProcessWaiter(process)); } void Registration::RemoveProcessFromList(u64 pid) { @@ -412,7 +411,7 @@ Result Registration::GetDebugProcessIds(u64 *out_pids, u32 max_out, u32 *num_out } Handle Registration::GetProcessEventHandle() { - return g_process_event->get_handle(); + return g_process_event->GetHandle(); } void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) { @@ -451,7 +450,7 @@ void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) { } if (kernelAbove500()) { auto_lock.unlock(); - auto dead_process_list_lock = g_dead_process_list.get_unique_lock(); + auto dead_process_list_lock = g_dead_process_list.GetUniqueLock(); if (g_dead_process_list.processes.size()) { std::shared_ptr<Registration::Process> process = g_dead_process_list.processes[0]; g_dead_process_list.processes.erase(g_dead_process_list.processes.begin()); @@ -471,13 +470,13 @@ Result Registration::EnableDebugForTitleId(u64 tid, Handle *out) { g_debug_on_launch_tid = old; return 0x80F; } - *out = g_debug_title_event->get_handle(); + *out = g_debug_title_event->GetHandle(); return 0x0; } Result Registration::EnableDebugForApplication(Handle *out) { g_debug_next_application = true; - *out = g_debug_application_event->get_handle(); + *out = g_debug_application_event->GetHandle(); return 0; } diff --git a/stratosphere/pm/source/pm_registration.hpp b/stratosphere/pm/source/pm_registration.hpp index 6f0459124..8b440ade4 100644 --- a/stratosphere/pm/source/pm_registration.hpp +++ b/stratosphere/pm/source/pm_registration.hpp @@ -172,8 +172,7 @@ class Registration { static void InitializeSystemResources(); static IWaitable *GetProcessLaunchStartEvent(); static std::unique_lock<HosRecursiveMutex> GetProcessListUniqueLock(); - static void SetProcessListManager(WaitableManager *m); - static Result ProcessLaunchStartCallback(void *arg, Handle *handles, size_t num_handles, u64 timeout); + static Result ProcessLaunchStartCallback(u64 timeout); static Result HandleSignaledProcess(std::shared_ptr<Process> process); static void FinalizeExitedProcess(std::shared_ptr<Process> process); diff --git a/stratosphere/pm/source/pm_shell.cpp b/stratosphere/pm/source/pm_shell.cpp index 4a9653367..aa03b0c68 100644 --- a/stratosphere/pm/source/pm_shell.cpp +++ b/stratosphere/pm/source/pm_shell.cpp @@ -23,170 +23,84 @@ static bool g_has_boot_finished = false; -Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - - if (kernelAbove500()) { - switch ((ShellCmd_5X)cmd_id) { - case Shell_Cmd_5X_LaunchProcess: - rc = WrapIpcCommandImpl<&ShellService::launch_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_5X_TerminateProcessId: - rc = WrapIpcCommandImpl<&ShellService::terminate_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_5X_TerminateTitleId: - rc = WrapIpcCommandImpl<&ShellService::terminate_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_5X_GetProcessWaitEvent: - rc = WrapIpcCommandImpl<&ShellService::get_process_wait_event>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_5X_GetProcessEventType: - rc = WrapIpcCommandImpl<&ShellService::get_process_event_type>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_5X_NotifyBootFinished: - rc = WrapIpcCommandImpl<&ShellService::notify_boot_finished>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_5X_GetApplicationProcessId: - rc = WrapIpcCommandImpl<&ShellService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_5X_BoostSystemMemoryResourceLimit: - rc = WrapIpcCommandImpl<&ShellService::boost_system_memory_resource_limit>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - } else { - switch ((ShellCmd)cmd_id) { - case Shell_Cmd_LaunchProcess: - rc = WrapIpcCommandImpl<&ShellService::launch_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_TerminateProcessId: - rc = WrapIpcCommandImpl<&ShellService::terminate_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_TerminateTitleId: - rc = WrapIpcCommandImpl<&ShellService::terminate_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_GetProcessWaitEvent: - rc = WrapIpcCommandImpl<&ShellService::get_process_wait_event>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_GetProcessEventType: - rc = WrapIpcCommandImpl<&ShellService::get_process_event_type>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_FinalizeExitedProcess: - rc = WrapIpcCommandImpl<&ShellService::finalize_exited_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_ClearProcessNotificationFlag: - rc = WrapIpcCommandImpl<&ShellService::clear_process_notification_flag>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_NotifyBootFinished: - rc = WrapIpcCommandImpl<&ShellService::notify_boot_finished>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_GetApplicationProcessId: - rc = WrapIpcCommandImpl<&ShellService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_BoostSystemMemoryResourceLimit: - rc = WrapIpcCommandImpl<&ShellService::boost_system_memory_resource_limit>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - } - - return rc; +Result ShellService::LaunchProcess(Out<u64> pid, u64 launch_flags, Registration::TidSid tid_sid) { + return Registration::LaunchProcessByTidSid(tid_sid, launch_flags, pid.GetPointer()); } -Result ShellService::handle_deferred() { - /* This service is never deferrable. */ - return 0; -} - -std::tuple<Result, u64> ShellService::launch_process(u64 launch_flags, Registration::TidSid tid_sid) { - u64 pid = 0; - Result rc = Registration::LaunchProcessByTidSid(tid_sid, launch_flags, &pid); - return {rc, pid}; -} - -std::tuple<Result> ShellService::terminate_process_id(u64 pid) { +Result ShellService::TerminateProcessId(u64 pid) { auto auto_lock = Registration::GetProcessListUniqueLock(); - std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid); + auto proc = Registration::GetProcess(pid); + if (proc != nullptr) { + return svcTerminateProcess(proc->handle); + } else { + return 0x20F; + } +} + +Result ShellService::TerminateTitleId(u64 tid) { + auto auto_lock = Registration::GetProcessListUniqueLock(); + + auto proc = Registration::GetProcessByTitleId(tid); if (proc != NULL) { - return {svcTerminateProcess(proc->handle)}; + return svcTerminateProcess(proc->handle); } else { - return {0x20F}; + return 0x20F; } } -std::tuple<Result> ShellService::terminate_title_id(u64 tid) { +void ShellService::GetProcessWaitEvent(Out<CopiedHandle> event) { + event.SetValue(Registration::GetProcessEventHandle()); +} + +void ShellService::GetProcessEventType(Out<u64> type, Out<u64> pid) { + Registration::GetProcessEventType(pid.GetPointer(), type.GetPointer()); +} + +Result ShellService::FinalizeExitedProcess(u64 pid) { auto auto_lock = Registration::GetProcessListUniqueLock(); - std::shared_ptr<Registration::Process> proc = Registration::GetProcessByTitleId(tid); - if (proc != NULL) { - return {svcTerminateProcess(proc->handle)}; - } else { - return {0x20F}; - } -} - -std::tuple<Result, CopiedHandle> ShellService::get_process_wait_event() { - return {0x0, Registration::GetProcessEventHandle()}; -} - -std::tuple<Result, u64, u64> ShellService::get_process_event_type() { - u64 type, pid; - Registration::GetProcessEventType(&pid, &type); - return {0x0, type, pid}; -} - -std::tuple<Result> ShellService::finalize_exited_process(u64 pid) { - auto auto_lock = Registration::GetProcessListUniqueLock(); - - std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid); + auto proc = Registration::GetProcess(pid); if (proc == NULL) { - return {0x20F}; + return 0x20F; } else if (proc->state != ProcessState_Exited) { - return {0x60F}; + return 0x60F; } else { Registration::FinalizeExitedProcess(proc); - return {0x0}; + return 0x0; } } -std::tuple<Result> ShellService::clear_process_notification_flag(u64 pid) { +Result ShellService::ClearProcessNotificationFlag(u64 pid) { auto auto_lock = Registration::GetProcessListUniqueLock(); - std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid); + auto proc = Registration::GetProcess(pid); if (proc != NULL) { proc->flags &= ~PROCESSFLAGS_CRASHED; - return {0x0}; + return 0x0; } else { - return {0x20F}; + return 0x20F; } } -std::tuple<Result> ShellService::notify_boot_finished() { +void ShellService::NotifyBootFinished() { if (!g_has_boot_finished) { g_has_boot_finished = true; EmbeddedBoot2::Main(); } - return {0}; } -std::tuple<Result, u64> ShellService::get_application_process_id() { +Result ShellService::GetApplicationProcessId(Out<u64> pid) { auto auto_lock = Registration::GetProcessListUniqueLock(); std::shared_ptr<Registration::Process> app_proc; if (Registration::HasApplicationProcess(&app_proc)) { - return {0, app_proc->pid}; + pid.SetValue(app_proc->pid); + return 0; } - return {0x20F, 0}; + return 0x20F; } -std::tuple<Result> ShellService::boost_system_memory_resource_limit(u64 sysmem_size) { - if (!kernelAbove400()) { - return {0xF601}; - } - - /* TODO */ - return {ResourceLimitUtils::BoostSystemMemoryResourceLimit(sysmem_size)}; +Result ShellService::BoostSystemMemoryResourceLimit(u64 sysmem_size) { + return ResourceLimitUtils::BoostSystemMemoryResourceLimit(sysmem_size); } diff --git a/stratosphere/pm/source/pm_shell.hpp b/stratosphere/pm/source/pm_shell.hpp index c5b63c030..b488107fd 100644 --- a/stratosphere/pm/source/pm_shell.hpp +++ b/stratosphere/pm/source/pm_shell.hpp @@ -16,7 +16,7 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> #include "pm_registration.hpp" @@ -46,26 +46,43 @@ enum ShellCmd_5X { Shell_Cmd_5X_BoostSystemMemoryResourceLimit = 7 }; -class ShellService final : public IServiceObject { - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override; - - ShellService *clone() override { - return new ShellService(*this); - } - - +class ShellService final : public IServiceObject { private: /* Actual commands. */ - std::tuple<Result, u64> launch_process(u64 launch_flags, Registration::TidSid tid_sid); - std::tuple<Result> terminate_process_id(u64 pid); - std::tuple<Result> terminate_title_id(u64 tid); - std::tuple<Result, CopiedHandle> get_process_wait_event(); - std::tuple<Result, u64, u64> get_process_event_type(); - std::tuple<Result> finalize_exited_process(u64 pid); - std::tuple<Result> clear_process_notification_flag(u64 pid); - std::tuple<Result> notify_boot_finished(); - std::tuple<Result, u64> get_application_process_id(); - std::tuple<Result> boost_system_memory_resource_limit(u64 sysmem_size); + Result LaunchProcess(Out<u64> pid, u64 launch_flags, Registration::TidSid tid_sid); + Result TerminateProcessId(u64 pid); + Result TerminateTitleId(u64 tid); + void GetProcessWaitEvent(Out<CopiedHandle> event); + void GetProcessEventType(Out<u64> type, Out<u64> pid); + Result FinalizeExitedProcess(u64 pid); + Result ClearProcessNotificationFlag(u64 pid); + void NotifyBootFinished(); + Result GetApplicationProcessId(Out<u64> pid); + Result BoostSystemMemoryResourceLimit(u64 sysmem_size); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + /* 1.0.0-4.0.0 */ + MakeServiceCommandMeta<Shell_Cmd_LaunchProcess, &ShellService::LaunchProcess, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Shell_Cmd_TerminateProcessId, &ShellService::TerminateProcessId, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Shell_Cmd_TerminateTitleId, &ShellService::TerminateTitleId, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Shell_Cmd_GetProcessWaitEvent, &ShellService::GetProcessWaitEvent, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Shell_Cmd_GetProcessEventType, &ShellService::GetProcessEventType, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Shell_Cmd_FinalizeExitedProcess, &ShellService::FinalizeExitedProcess, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Shell_Cmd_ClearProcessNotificationFlag, &ShellService::ClearProcessNotificationFlag, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Shell_Cmd_NotifyBootFinished, &ShellService::NotifyBootFinished, FirmwareVersion_Min, FirmwareVersion_400>(), + MakeServiceCommandMeta<Shell_Cmd_GetApplicationProcessId, &ShellService::GetApplicationProcessId, FirmwareVersion_Min, FirmwareVersion_400>(), + + /* 4.0.0-4.0.0 */ + MakeServiceCommandMeta<Shell_Cmd_BoostSystemMemoryResourceLimit, &ShellService::BoostSystemMemoryResourceLimit, FirmwareVersion_400, FirmwareVersion_400>(), + + /* 5.0.0-* */ + MakeServiceCommandMeta<Shell_Cmd_5X_LaunchProcess, &ShellService::LaunchProcess, FirmwareVersion_500>(), + MakeServiceCommandMeta<Shell_Cmd_5X_TerminateProcessId, &ShellService::TerminateProcessId, FirmwareVersion_500>(), + MakeServiceCommandMeta<Shell_Cmd_5X_TerminateTitleId, &ShellService::TerminateTitleId, FirmwareVersion_500>(), + MakeServiceCommandMeta<Shell_Cmd_5X_GetProcessWaitEvent, &ShellService::GetProcessWaitEvent, FirmwareVersion_500>(), + MakeServiceCommandMeta<Shell_Cmd_5X_GetProcessEventType, &ShellService::GetProcessEventType, FirmwareVersion_500>(), + MakeServiceCommandMeta<Shell_Cmd_5X_NotifyBootFinished, &ShellService::NotifyBootFinished, FirmwareVersion_500>(), + MakeServiceCommandMeta<Shell_Cmd_5X_GetApplicationProcessId, &ShellService::GetApplicationProcessId, FirmwareVersion_500>(), + MakeServiceCommandMeta<Shell_Cmd_5X_BoostSystemMemoryResourceLimit, &ShellService::BoostSystemMemoryResourceLimit, FirmwareVersion_500>(), + }; }; diff --git a/stratosphere/pm/source/smm_ams.c b/stratosphere/pm/source/smm_ams.c deleted file mode 100644 index 4437ba949..000000000 --- a/stratosphere/pm/source/smm_ams.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <switch.h> -#include <switch/arm/atomics.h> -#include "smm_ams.h" - -static Service g_smManagerAmsSrv; -static u64 g_smManagerAmsRefcnt; - -Result smManagerAmsInitialize(void) { - atomicIncrement64(&g_smManagerAmsRefcnt); - - if (serviceIsActive(&g_smManagerAmsSrv)) - return 0; - - return smGetService(&g_smManagerAmsSrv, "sm:m"); -} - -void smManagerAmsExit(void) { - if (atomicDecrement64(&g_smManagerAmsRefcnt) == 0) - serviceClose(&g_smManagerAmsSrv); -} - -Result smManagerAmsEndInitialDefers(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65000; - - - Result rc = serviceIpcDispatch(&g_smManagerAmsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; - -} \ No newline at end of file diff --git a/stratosphere/pm/source/smm_ams.h b/stratosphere/pm/source/smm_ams.h deleted file mode 100644 index 6d6dd5ed0..000000000 --- a/stratosphere/pm/source/smm_ams.h +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @file smm_ams.h - * @brief Service manager (sm:m) IPC wrapper for Atmosphere extensions. - * @author SciresM - * @copyright libnx Authors - */ -#pragma once -#include <switch.h> - -#ifdef __cplusplus -extern "C" { -#endif - -Result smManagerAmsInitialize(void); -void smManagerAmsExit(void); - -Result smManagerAmsEndInitialDefers(void); - -#ifdef __cplusplus -} -#endif \ No newline at end of file From aef7d363005a458e995fa18d218941026e075879 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 17:30:39 -0700 Subject: [PATCH 146/489] fs.mitm: update for libstratosphere refactor --- stratosphere/fs_mitm/fs_mitm.json | 1 + stratosphere/fs_mitm/source/debug.cpp | 2 - stratosphere/fs_mitm/source/fs_istorage.hpp | 103 +++----- .../fs_mitm/source/fsmitm_layeredrom.hpp | 10 +- stratosphere/fs_mitm/source/fsmitm_main.cpp | 46 ++-- .../fs_mitm/source/fsmitm_romfsbuild.cpp | 4 +- .../fs_mitm/source/fsmitm_romstorage.hpp | 8 - .../fs_mitm/source/fsmitm_service.cpp | 140 ++++------ .../fs_mitm/source/fsmitm_service.hpp | 45 ++-- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 1 - stratosphere/fs_mitm/source/fsmitm_worker.cpp | 53 ---- stratosphere/fs_mitm/source/fsmitm_worker.hpp | 27 -- .../fs_mitm/source/imitmserviceobject.hpp | 45 ---- .../fs_mitm/source/mitm_query_service.cpp | 43 --- .../fs_mitm/source/mitm_query_service.hpp | 75 ------ stratosphere/fs_mitm/source/mitm_server.hpp | 69 ----- stratosphere/fs_mitm/source/mitm_session.hpp | 246 ------------------ .../fs_mitm/source/setsys_mitm_service.cpp | 45 +--- .../fs_mitm/source/setsys_mitm_service.hpp | 41 ++- stratosphere/fs_mitm/source/sm_mitm.c | 190 -------------- stratosphere/fs_mitm/source/sm_mitm.h | 24 -- 21 files changed, 154 insertions(+), 1064 deletions(-) delete mode 100644 stratosphere/fs_mitm/source/fsmitm_worker.cpp delete mode 100644 stratosphere/fs_mitm/source/fsmitm_worker.hpp delete mode 100644 stratosphere/fs_mitm/source/imitmserviceobject.hpp delete mode 100644 stratosphere/fs_mitm/source/mitm_query_service.cpp delete mode 100644 stratosphere/fs_mitm/source/mitm_query_service.hpp delete mode 100644 stratosphere/fs_mitm/source/mitm_server.hpp delete mode 100644 stratosphere/fs_mitm/source/mitm_session.hpp delete mode 100644 stratosphere/fs_mitm/source/sm_mitm.c delete mode 100644 stratosphere/fs_mitm/source/sm_mitm.h diff --git a/stratosphere/fs_mitm/fs_mitm.json b/stratosphere/fs_mitm/fs_mitm.json index a6775155b..aac437f20 100644 --- a/stratosphere/fs_mitm/fs_mitm.json +++ b/stratosphere/fs_mitm/fs_mitm.json @@ -58,6 +58,7 @@ "svcReplyAndReceiveWithUserBuffer": "0x44", "svcCreateEvent": "0x45", "svcCreateInterruptEvent": "0x53", + "svcReadWriteRegister": "0x4E", "svcQueryIoMapping": "0x55", "svcCreateDeviceAddressSpace": "0x56", "svcAttachDeviceAddressSpace": "0x57", diff --git a/stratosphere/fs_mitm/source/debug.cpp b/stratosphere/fs_mitm/source/debug.cpp index 35844b65e..1531eff48 100644 --- a/stratosphere/fs_mitm/source/debug.cpp +++ b/stratosphere/fs_mitm/source/debug.cpp @@ -24,7 +24,5 @@ void Reboot() { } void Log(const void *data, int size) { - (void)(data); - (void)(size); /* ... */ } \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fs_istorage.hpp b/stratosphere/fs_mitm/source/fs_istorage.hpp index d6827839f..2f21b6b7e 100644 --- a/stratosphere/fs_mitm/source/fs_istorage.hpp +++ b/stratosphere/fs_mitm/source/fs_istorage.hpp @@ -21,21 +21,19 @@ #include "debug.hpp" -enum class FsIStorageCmd { - Read = 0, - Write = 1, - Flush = 2, - SetSize = 3, - GetSize = 4, - OperateRange = 5, +enum FsIStorageCmd : u32 { + FsIStorageCmd_Read = 0, + FsIStorageCmd_Write = 1, + FsIStorageCmd_Flush = 2, + FsIStorageCmd_SetSize = 3, + FsIStorageCmd_GetSize = 4, + FsIStorageCmd_OperateRange = 5, }; class IStorage { public: virtual ~IStorage(); - - virtual IStorage *Clone() = 0; - + virtual Result Read(void *buffer, size_t size, u64 offset) = 0; virtual Result Write(void *buffer, size_t size, u64 offset) = 0; virtual Result Flush() = 0; @@ -51,88 +49,59 @@ class IStorageInterface : public IServiceObject { IStorageInterface(IStorage *s) : base_storage(s) { /* ... */ }; - - IStorageInterface *clone() override { - return new IStorageInterface(this->base_storage->Clone()); - } - + ~IStorageInterface() { delete base_storage; }; - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) final { - Result rc = 0xF601; - switch ((FsIStorageCmd)cmd_id) { - case FsIStorageCmd::Read: - rc = WrapIpcCommandImpl<&IStorageInterface::read>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case FsIStorageCmd::Write: - rc = WrapIpcCommandImpl<&IStorageInterface::write>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case FsIStorageCmd::Flush: - rc = WrapIpcCommandImpl<&IStorageInterface::flush>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case FsIStorageCmd::SetSize: - rc = WrapIpcCommandImpl<&IStorageInterface::set_size>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case FsIStorageCmd::GetSize: - rc = WrapIpcCommandImpl<&IStorageInterface::get_size>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case FsIStorageCmd::OperateRange: - if (kernelAbove400()) { - rc = WrapIpcCommandImpl<&IStorageInterface::operate_range>(this, r, out_c, pointer_buffer, pointer_buffer_size); - } - break; - default: - break; - } - return rc; - }; - - Result handle_deferred() final { - /* TODO: Panic, we can never defer. */ - return 0; - }; private: /* Actual command API. */ - virtual std::tuple<Result> read(OutBuffer<u8, BufferType_Type1> buffer, u64 offset, u64 size) final { - return {this->base_storage->Read(buffer.buffer, std::min(buffer.num_elements, size), offset)}; + virtual Result Read(OutBuffer<u8, BufferType_Type1> buffer, u64 offset, u64 size) final { + return this->base_storage->Read(buffer.buffer, std::min(buffer.num_elements, size), offset); }; - virtual std::tuple<Result> write(InBuffer<u8, BufferType_Type1> buffer, u64 offset, u64 size) final { - return {this->base_storage->Write(buffer.buffer, std::min(buffer.num_elements, size), offset)}; + virtual Result Write(InBuffer<u8, BufferType_Type1> buffer, u64 offset, u64 size) final { + return this->base_storage->Write(buffer.buffer, std::min(buffer.num_elements, size), offset); }; - virtual std::tuple<Result> flush() final { - return {this->base_storage->Flush()}; + virtual Result Flush() final { + return this->base_storage->Flush(); }; - virtual std::tuple<Result> set_size(u64 size) final { - return {this->base_storage->SetSize(size)}; + virtual Result SetSize(u64 size) final { + return this->base_storage->SetSize(size); }; - virtual std::tuple<Result, u64> get_size() final { - u64 out_size = 0; - Result rc = this->base_storage->GetSize(&out_size); - return {rc, out_size}; + virtual Result GetSize(Out<u64> size) final { + return this->base_storage->GetSize(size.GetPointer()); }; - virtual std::tuple<Result, FsRangeInfo> operate_range(u32 operation_type, u64 offset, u64 size) final { - FsRangeInfo out_range_info = {0}; - Result rc = this->base_storage->OperateRange(operation_type, offset, size, &out_range_info); - return {rc, out_range_info}; + virtual Result OperateRange(Out<FsRangeInfo> range_info, u32 operation_type, u64 offset, u64 size) final { + return this->base_storage->OperateRange(operation_type, offset, size, range_info.GetPointer()); + }; + public: + DEFINE_SERVICE_DISPATCH_TABLE { + /* 1.0.0- */ + MakeServiceCommandMeta<FsIStorageCmd_Read, &IStorageInterface::Read>(), + MakeServiceCommandMeta<FsIStorageCmd_Write, &IStorageInterface::Write>(), + MakeServiceCommandMeta<FsIStorageCmd_Flush, &IStorageInterface::Flush>(), + MakeServiceCommandMeta<FsIStorageCmd_SetSize, &IStorageInterface::SetSize>(), + MakeServiceCommandMeta<FsIStorageCmd_GetSize, &IStorageInterface::GetSize>(), + + /* 4.0.0- */ + MakeServiceCommandMeta<FsIStorageCmd_OperateRange, &IStorageInterface::OperateRange, FirmwareVersion_400>(), }; }; class IROStorage : public IStorage { public: virtual Result Read(void *buffer, size_t size, u64 offset) = 0; - Result Write(void *buffer, size_t size, u64 offset) final { + virtual Result Write(void *buffer, size_t size, u64 offset) final { (void)(buffer); (void)(offset); (void)(size); return 0x313802; }; - Result Flush() final { + virtual Result Flush() final { return 0x0; }; - Result SetSize(u64 size) final { + virtual Result SetSize(u64 size) final { (void)(size); return 0x313802; }; diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp index 3e6061651..01be3af01 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp @@ -32,16 +32,12 @@ class LayeredRomFS : public IROStorage { /* Information about the merged RomFS. */ u64 title_id; std::shared_ptr<std::vector<RomFSSourceInfo>> p_source_infos; - - LayeredRomFS *Clone() override { - return new LayeredRomFS(*this); - }; public: LayeredRomFS(std::shared_ptr<RomInterfaceStorage> s_r, std::shared_ptr<RomFileStorage> f_r, u64 tid); virtual ~LayeredRomFS() = default; - Result Read(void *buffer, size_t size, u64 offset) override; - Result GetSize(u64 *out_size) override; - Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override; + virtual Result Read(void *buffer, size_t size, u64 offset) override; + virtual Result GetSize(u64 *out_size) override; + virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override; }; diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 12b2e75c3..2d96ce78e 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -22,13 +22,7 @@ #include <switch.h> #include <stratosphere.hpp> -#include "sm_mitm.h" - -#include "mitm_server.hpp" #include "fsmitm_service.hpp" -#include "fsmitm_worker.hpp" - -#include "mitm_query_service.hpp" #include "fsmitm_utils.hpp" @@ -88,37 +82,34 @@ void __appExit(void) { smExit(); } +struct FsMitmManagerOptions { + static const size_t PointerBufferSize = 0x800; + static const size_t MaxDomains = 0x10; + static const size_t MaxDomainObjects = 0x4000; +}; + +using FsMitmManager = WaitableManager<FsMitmManagerOptions>; + void CreateSettingsMitMServer(void *arg) { - MultiThreadedWaitableManager *server_manager = (MultiThreadedWaitableManager *)arg; + auto server_manager = (FsMitmManager *)arg; Result rc; if (R_FAILED((rc = setsysInitialize()))) { fatalSimple(rc); } - ISession<MitMQueryService<SetSysMitMService>> *setsys_query_srv = NULL; - MitMServer<SetSysMitMService> *setsys_srv = new MitMServer<SetSysMitMService>(&setsys_query_srv, "set:sys", 60); - server_manager->add_waitable(setsys_srv); - server_manager->add_waitable(setsys_query_srv); + AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 5); svcExitThread(); } int main(int argc, char **argv) { - Thread worker_thread = {0}; Thread sd_initializer_thread = {0}; Thread hid_initializer_thread = {0}; Thread set_mitm_setup_thread = {0}; consoleDebugInit(debugDevice_SVC); - if (R_FAILED(threadCreate(&worker_thread, &FsMitMWorker::Main, NULL, 0x20000, 45, 0))) { - /* TODO: Panic. */ - } - if (R_FAILED(threadStart(&worker_thread))) { - /* TODO: Panic. */ - } - if (R_FAILED(threadCreate(&sd_initializer_thread, &Utils::InitializeSdThreadFunc, NULL, 0x4000, 0x15, 0))) { /* TODO: Panic. */ } @@ -134,24 +125,21 @@ int main(int argc, char **argv) } /* TODO: What's a good timeout value to use here? */ - MultiThreadedWaitableManager *server_manager = new MultiThreadedWaitableManager(5, U64_MAX, 0x20000); + auto server_manager = new FsMitmManager(1); /* Create fsp-srv mitm. */ - ISession<MitMQueryService<FsMitMService>> *fs_query_srv = NULL; - MitMServer<FsMitMService> *fs_srv = new MitMServer<FsMitMService>(&fs_query_srv, "fsp-srv", 61); - server_manager->add_waitable(fs_srv); - server_manager->add_waitable(fs_query_srv); + AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); /* Create set:sys mitm server, delayed until set:sys is available. */ - if (R_FAILED(threadCreate(&set_mitm_setup_thread, &CreateSettingsMitMServer, server_manager, 0x4000, 0x15, 0))) { + //if (R_FAILED(threadCreate(&set_mitm_setup_thread, &CreateSettingsMitMServer, server_manager, 0x4000, 0x15, 0))) { /* TODO: Panic. */ - } - if (R_FAILED(threadStart(&set_mitm_setup_thread))) { + //} + //if (R_FAILED(threadStart(&set_mitm_setup_thread))) { /* TODO: Panic. */ - } + //} /* Loop forever, servicing our services. */ - server_manager->process(); + server_manager->Process(); delete server_manager; diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index 3a1afb780..4a01bff77 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -400,7 +400,7 @@ void RomFSBuildContext::Build(std::vector<RomFSSourceInfo> *out_infos) { header->file_table_ofs = header->file_hash_table_ofs + header->file_hash_table_size; /* For debugging, uncomment this to get a log of the generated metadata tables. */ - /* + { FsFileSystem sd_fs; if (R_SUCCEEDED(fsMountSdcard(&sd_fs))) { @@ -415,7 +415,7 @@ void RomFSBuildContext::Build(std::vector<RomFSSourceInfo> *out_infos) { fsFsClose(&sd_fs); } } - */ + out_infos->emplace_back(header->dir_hash_table_ofs, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size, metadata, RomFSDataSource::Memory); } diff --git a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp index cc378cd1f..c421a2147 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp @@ -35,10 +35,6 @@ class RomFileStorage : public IROStorage { fsFileClose(base_file); delete base_file; }; - - RomFileStorage *Clone() override { - return new RomFileStorage(this->base_file); - }; public: Result Read(void *buffer, size_t size, u64 offset) override { size_t out_sz = 0; @@ -72,10 +68,6 @@ class RomInterfaceStorage : public IROStorage { fsStorageClose(base_storage); delete base_storage; }; - - RomInterfaceStorage *Clone() override { - return new RomInterfaceStorage(this->base_storage); - }; public: Result Read(void *buffer, size_t size, u64 offset) override { return fsStorageRead(this->base_storage, offset, buffer, size); diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index d139cc328..da19d5778 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -18,81 +18,41 @@ #include "fsmitm_service.hpp" #include "fs_shim.h" -#include "fsmitm_worker.hpp" #include "fsmitm_utils.hpp" #include "fsmitm_romstorage.hpp" #include "fsmitm_layeredrom.hpp" -#include "mitm_query_service.hpp" #include "debug.hpp" -Result FsMitMService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - if (this->has_initialized) { - switch (static_cast<FspSrvCmd>(cmd_id)) { - case FspSrvCmd::OpenDataStorageByCurrentProcess: - rc = WrapIpcCommandImpl<&FsMitMService::open_data_storage_by_current_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); +void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { + auto this_ptr = static_cast<FsMitmService *>(obj); + switch ((FspSrvCmd)ctx->cmd_id) { + case FspSrvCmd_SetCurrentProcess: + if (R_SUCCEEDED(ctx->rc)) { + this_ptr->has_initialized = true; + this_ptr->process_id = ctx->request.Pid; + this_ptr->title_id = this_ptr->process_id; + if (R_FAILED(MitmQueryUtils::GetAssociatedTidForPid(this_ptr->process_id, &this_ptr->title_id))) { + /* Log here, if desired. */ + } break; - case FspSrvCmd::OpenDataStorageByDataId: - rc = WrapIpcCommandImpl<&FsMitMService::open_data_storage_by_data_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - } else { - if (static_cast<FspSrvCmd>(cmd_id) == FspSrvCmd::SetCurrentProcess) { - if (r.HasPid) { - this->init_pid = r.Pid; } - } - } - return rc; -} - -void FsMitMService::postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - struct { - u64 magic; - u64 result; - } *resp = (decltype(resp))r.Raw; - - u64 *tls = (u64 *)armGetTls(); - std::array<u64, 0x100/sizeof(u64)> backup_tls; - std::copy(tls, tls + backup_tls.size(), backup_tls.begin()); - - Result rc = (Result)resp->result; - switch (static_cast<FspSrvCmd>(cmd_id)) { - case FspSrvCmd::SetCurrentProcess: - if (R_SUCCEEDED(rc)) { - this->has_initialized = true; - } - this->process_id = this->init_pid; - this->title_id = this->process_id; - if (R_FAILED(MitMQueryUtils::get_associated_tid_for_pid(this->process_id, &this->title_id))) { - /* Log here, if desired. */ - } - std::copy(backup_tls.begin(), backup_tls.end(), tls); break; default: break; } - resp->result = rc; -} - -Result FsMitMService::handle_deferred() { - /* This service is never deferrable. */ - return 0; } /* Add redirection for RomFS to the SD card. */ -std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_storage_by_current_process() { - IPCSession<IStorageInterface> *out_session = NULL; - std::shared_ptr<IStorageInterface> out_storage = nullptr; +Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out_storage) { + std::shared_ptr<IStorageInterface> storage = nullptr; u32 out_domain_id = 0; - Result rc; + Result rc = 0; + if (this->romfs_storage != nullptr) { - if (this->get_owner() != NULL) { + if (out_storage.IsDomain()) { FsStorage s = {0}; - rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &s); + rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service.get(), &s); if (R_SUCCEEDED(rc)) { out_domain_id = s.s.object_id; } @@ -100,64 +60,78 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora rc = 0; } if (R_SUCCEEDED(rc)) { - out_storage = this->romfs_storage; - out_session = new IPCSession<IStorageInterface>(out_storage); + storage = this->romfs_storage; } } else { FsStorage data_storage; FsFile data_file; - rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage); + rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service.get(), &data_storage); Log(armGetTls(), 0x100); if (R_SUCCEEDED(rc)) { /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) { - out_storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), this->title_id)); + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), this->title_id)); } else { - out_storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, this->title_id)); + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, this->title_id)); } - this->romfs_storage = out_storage; - out_session = new IPCSession<IStorageInterface>(out_storage); - if (this->get_owner() == NULL) { - FsMitMWorker::AddWaitable(out_session); - } else { + this->romfs_storage = storage; + if (out_storage.IsDomain()) { out_domain_id = data_storage.s.object_id; } } } - OutSession out_s = OutSession(out_session); - out_s.domain_id = out_domain_id; - return {rc, out_s}; + if (R_SUCCEEDED(rc)) { + out_storage.SetValue(std::move(storage)); + if (out_storage.IsDomain()) { + out_storage.ChangeObjectId(out_domain_id); + } + } + + return rc; } /* Add redirection for System Data Archives to the SD card. */ -std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_storage_by_data_id(u64 sid, u64 data_id) { +Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out_storage, u64 sid, u64 data_id) { FsStorageId storage_id = (FsStorageId)sid; - IPCSession<IStorageInterface> *out_session = NULL; FsStorage data_storage; FsFile data_file; - u32 out_domain_id = 0; - Result rc; - rc = fsOpenDataStorageByDataIdFwd(this->forward_service, storage_id, data_id, &data_storage); + std::shared_ptr<IStorageInterface> storage = nullptr; + u32 out_domain_id = 0; + Result rc = 0; + + ON_SCOPE_EXIT { + if (R_SUCCEEDED(rc)) { + out_storage.SetValue(std::move(storage)); + if (out_storage.IsDomain()) { + out_storage.ChangeObjectId(out_domain_id); + } + } + }; + + rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &data_storage); if (R_SUCCEEDED(rc)) { /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) { - out_session = new IPCSession<IStorageInterface>(std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id))); + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id)); } else { - out_session = new IPCSession<IStorageInterface>(std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id))); + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id)); } - if (this->get_owner() == NULL) { - FsMitMWorker::AddWaitable(out_session); - } else { + if (out_storage.IsDomain()) { out_domain_id = data_storage.s.object_id; } } - OutSession out_s = OutSession(out_session); - out_s.domain_id = out_domain_id; - return {rc, out_s}; + if (R_SUCCEEDED(rc)) { + out_storage.SetValue(std::move(storage)); + if (out_storage.IsDomain()) { + out_storage.ChangeObjectId(out_domain_id); + } + } + + return rc; } \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 0dfa441e3..c1bf4e9a8 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -16,52 +16,41 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> -#include "imitmserviceobject.hpp" +#include <stratosphere.hpp> #include "fs_istorage.hpp" #include "fsmitm_utils.hpp" -enum class FspSrvCmd { - SetCurrentProcess = 1, - OpenDataStorageByCurrentProcess = 200, - OpenDataStorageByDataId = 202, +enum FspSrvCmd : u32 { + FspSrvCmd_SetCurrentProcess = 1, + FspSrvCmd_OpenDataStorageByCurrentProcess = 200, + FspSrvCmd_OpenDataStorageByDataId = 202, }; -class FsMitMService : public IMitMServiceObject { +class FsMitmService : public IMitmServiceObject { private: bool has_initialized = false; - u64 init_pid = 0; std::shared_ptr<IStorageInterface> romfs_storage; public: - FsMitMService(Service *s) : IMitMServiceObject(s) { + FsMitmService(std::shared_ptr<Service> s) : IMitmServiceObject(s) { /* ... */ } - static bool should_mitm(u64 pid, u64 tid) { + static bool ShouldMitm(u64 pid, u64 tid) { if (Utils::HasSdDisableMitMFlag(tid)) { return false; } return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)) && Utils::HasOverrideButton(tid); } - FsMitMService *clone() override { - auto new_srv = new FsMitMService((Service *)&this->forward_service); - this->clone_to(new_srv); - return new_srv; - } - - void clone_to(void *o) override { - FsMitMService *other = (FsMitMService *)o; - other->has_initialized = has_initialized; - other->init_pid = init_pid; - } - - virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); - virtual void postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); - virtual Result handle_deferred(); - + static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); + protected: /* Overridden commands. */ - std::tuple<Result, OutSession<IStorageInterface>> open_data_storage_by_current_process(); - std::tuple<Result, OutSession<IStorageInterface>> open_data_storage_by_data_id(u64 storage_id, u64 data_id); + Result OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out); + Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 storage_id, u64 data_id); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByCurrentProcess, &FsMitmService::OpenDataStorageByCurrentProcess>(), + MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByDataId, &FsMitmService::OpenDataStorageByDataId>(), + }; }; diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 127fa7a24..aa22bb5c3 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -20,7 +20,6 @@ #include <algorithm> #include <strings.h> -#include "sm_mitm.h" #include "debug.hpp" #include "fsmitm_utils.hpp" #include "ini.h" diff --git a/stratosphere/fs_mitm/source/fsmitm_worker.cpp b/stratosphere/fs_mitm/source/fsmitm_worker.cpp deleted file mode 100644 index 24cba1168..000000000 --- a/stratosphere/fs_mitm/source/fsmitm_worker.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <mutex> -#include <switch.h> -#include <stratosphere.hpp> -#include "fsmitm_worker.hpp" - -static SystemEvent *g_new_waitable_event = NULL; - -static HosMutex g_new_waitable_mutex; -static HosSemaphore g_sema_new_waitable_finish; - -static std::unique_ptr<WaitableManager> g_worker_waiter; - -Result FsMitMWorker::AddWaitableCallback(void *arg, Handle *handles, size_t num_handles, u64 timeout) { - (void)arg; - svcClearEvent(handles[0]); - g_sema_new_waitable_finish.Signal(); - return 0; -} - -void FsMitMWorker::AddWaitable(IWaitable *waitable) { - g_worker_waiter->add_waitable(waitable); - std::scoped_lock lk{g_new_waitable_mutex}; - g_new_waitable_event->signal_event(); - g_sema_new_waitable_finish.Wait(); -} - -void FsMitMWorker::Main(void *arg) { - /* Initialize waitable event. */ - g_new_waitable_event = new SystemEvent(NULL, &FsMitMWorker::AddWaitableCallback); - - /* Make a new waitable manager. */ - g_worker_waiter = std::make_unique<WaitableManager>(U64_MAX); - g_worker_waiter->add_waitable(g_new_waitable_event); - - /* Service processes. */ - g_worker_waiter->process(); -} diff --git a/stratosphere/fs_mitm/source/fsmitm_worker.hpp b/stratosphere/fs_mitm/source/fsmitm_worker.hpp deleted file mode 100644 index 68c5ea4e4..000000000 --- a/stratosphere/fs_mitm/source/fsmitm_worker.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <stratosphere.hpp> - -class FsMitMWorker { - private: - static Result AddWaitableCallback(void *arg, Handle *handles, size_t num_handles, u64 timeout); - public: - static void Main(void *arg); - static void AddWaitable(IWaitable *waitable); -}; \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/imitmserviceobject.hpp b/stratosphere/fs_mitm/source/imitmserviceobject.hpp deleted file mode 100644 index 8952903e9..000000000 --- a/stratosphere/fs_mitm/source/imitmserviceobject.hpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <atomic> - -#include <stratosphere.hpp> - -#include "debug.hpp" - -class IMitMServiceObject : public IServiceObject { - protected: - Service *forward_service; - u64 process_id = 0; - u64 title_id = 0; - public: - IMitMServiceObject(Service *s) : forward_service(s) { - - } - - static bool should_mitm(u64 pid, u64 tid) { - return true; - } - - virtual void clone_to(void *o) = 0; - protected: - virtual ~IMitMServiceObject() = default; - virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) = 0; - virtual void postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) = 0; - virtual Result handle_deferred() = 0; -}; diff --git a/stratosphere/fs_mitm/source/mitm_query_service.cpp b/stratosphere/fs_mitm/source/mitm_query_service.cpp deleted file mode 100644 index e4d88d076..000000000 --- a/stratosphere/fs_mitm/source/mitm_query_service.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <mutex> -#include <switch.h> -#include <stratosphere.hpp> -#include "mitm_query_service.hpp" - -static std::vector<u64> g_known_pids; -static std::vector<u64> g_known_tids; -static HosMutex g_pid_tid_mutex; - -Result MitMQueryUtils::get_associated_tid_for_pid(u64 pid, u64 *tid) { - Result rc = 0xCAFE; - std::scoped_lock lk{g_pid_tid_mutex}; - for (unsigned int i = 0; i < g_known_pids.size(); i++) { - if (g_known_pids[i] == pid) { - *tid = g_known_tids[i]; - rc = 0x0; - break; - } - } - return rc; -} - -void MitMQueryUtils::associate_pid_to_tid(u64 pid, u64 tid) { - std::scoped_lock lk{g_pid_tid_mutex}; - g_known_pids.push_back(pid); - g_known_tids.push_back(tid); -} diff --git a/stratosphere/fs_mitm/source/mitm_query_service.hpp b/stratosphere/fs_mitm/source/mitm_query_service.hpp deleted file mode 100644 index a1153c496..000000000 --- a/stratosphere/fs_mitm/source/mitm_query_service.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <stratosphere/iserviceobject.hpp> - -#include "debug.hpp" - -enum MitMQueryServiceCommand { - MQS_Cmd_ShouldMitm = 65000, - MQS_Cmd_AssociatePidTid = 65001 -}; - -namespace MitMQueryUtils { - Result get_associated_tid_for_pid(u64 pid, u64 *tid); - - void associate_pid_to_tid(u64 pid, u64 tid); -} - - -template <typename T> -class MitMQueryService : public IServiceObject { - public: - MitMQueryService<T> *clone() override { - return new MitMQueryService<T>(); - } - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override { - Log(armGetTls(), 0x100); - switch (cmd_id) { - case MQS_Cmd_ShouldMitm: - return WrapIpcCommandImpl<&MitMQueryService::should_mitm>(this, r, out_c, pointer_buffer, pointer_buffer_size); - case MQS_Cmd_AssociatePidTid: - return WrapIpcCommandImpl<&MitMQueryService::associate_pid_tid>(this, r, out_c, pointer_buffer, pointer_buffer_size); - default: - return 0xF601; - } - if (cmd_id == 65000) { - - } else { - return 0xF601; - } - } - Result handle_deferred() override { - /* This service is never deferrable. */ - return 0; - } - - protected: - std::tuple<Result, u64> should_mitm(u64 pid) { - u64 should_mitm = 0; - u64 tid = 0; - if (R_SUCCEEDED(MitMQueryUtils::get_associated_tid_for_pid(pid, &tid))) { - should_mitm = T::should_mitm(pid, tid); - } - return {0, should_mitm}; - } - std::tuple<Result> associate_pid_tid(u64 pid, u64 tid) { - MitMQueryUtils::associate_pid_to_tid(pid, tid); - return {0x0}; - } -}; \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/mitm_server.hpp b/stratosphere/fs_mitm/source/mitm_server.hpp deleted file mode 100644 index 4054dd9ac..000000000 --- a/stratosphere/fs_mitm/source/mitm_server.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <stratosphere.hpp> - -#include "mitm_query_service.hpp" -#include "sm_mitm.h" -#include "mitm_session.hpp" - -#include "debug.hpp" - -template <typename T> -class MitMSession; - -template <typename T> -class MitMServer final : public IServer<T> { - static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); - private: - char mitm_name[9]; - - public: - MitMServer(ISession<MitMQueryService<T>> **out_query_session, const char *service_name, unsigned int max_s, bool s_d = false) : IServer<T>(service_name, max_s, s_d) { - Handle tmp_hnd; - Handle out_query_h; - Result rc; - - if (R_SUCCEEDED((rc = smGetServiceOriginal(&tmp_hnd, smEncodeName(service_name))))) { - svcCloseHandle(tmp_hnd); - } else { - fatalSimple(rc); - } - strncpy(mitm_name, service_name, 8); - mitm_name[8] = '\x00'; - if (R_FAILED((rc = smMitMInstall(&this->port_handle, &out_query_h, mitm_name)))) { - fatalSimple(rc); - } - *out_query_session = new ServiceSession<MitMQueryService<T>>(NULL, out_query_h, 0); - } - - virtual ~MitMServer() { - if (this->port_handle) { - if (R_FAILED(smMitMUninstall(this->mitm_name))) { - /* TODO: Panic. */ - } - /* svcCloseHandle(port_handle); was called by ~IServer. */ - } - } - - ISession<T> *get_new_session(Handle session_h) override { - return new MitMSession<T>(this, session_h, 0, mitm_name); - } -}; - - diff --git a/stratosphere/fs_mitm/source/mitm_session.hpp b/stratosphere/fs_mitm/source/mitm_session.hpp deleted file mode 100644 index c49915e69..000000000 --- a/stratosphere/fs_mitm/source/mitm_session.hpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <stratosphere.hpp> -#include "imitmserviceobject.hpp" - -#include "mitm_query_service.hpp" -#include "mitm_server.hpp" -#include "fsmitm_worker.hpp" - -#include "debug.hpp" - -template <typename T> -class MitMServer; - -template <typename T> -class MitMSession final : public ISession<T> { - static_assert(std::is_base_of<IMitMServiceObject, T>::value, "MitM Service Objects must derive from IMitMServiceObject"); - - /* This will be for the actual session. */ - Service forward_service; - IpcParsedCommand cur_out_r; - u32 mitm_domain_id = 0; - bool got_first_message; - - public: - MitMSession<T>(MitMServer<T> *s, Handle s_h, Handle c_h, const char *srv) : ISession<T>(s, s_h, c_h, NULL, 0), got_first_message(false) { - this->server = s; - this->server_handle = s_h; - this->client_handle = c_h; - if (R_FAILED(smMitMGetService(&forward_service, srv))) { - /* TODO: Panic. */ - } - size_t pointer_buffer_size = 0; - if (R_FAILED(ipcQueryPointerBufferSize(forward_service.handle, &pointer_buffer_size))) { - /* TODO: Panic. */ - } - this->service_object = std::make_shared<T>(&forward_service); - this->pointer_buffer.resize(pointer_buffer_size); - } - MitMSession<T>(MitMServer<T> *s, Handle s_h, Handle c_h, Handle f_h) : ISession<T>(s, s_h, c_h, NULL, 0), got_first_message(true) { - this->server = s; - this->server_handle = s_h; - this->client_handle = c_h; - serviceCreate(&this->forward_service, f_h); - size_t pointer_buffer_size = 0; - if (R_FAILED(ipcQueryPointerBufferSize(forward_service.handle, &pointer_buffer_size))) { - /* TODO: Panic. */ - } - this->service_object = std::make_shared<T>(&forward_service); - this->pointer_buffer.resize(pointer_buffer_size); - } - - virtual ~MitMSession() { - serviceClose(&forward_service); - } - - Result handle_message(IpcParsedCommand &r) override { - IpcCommand c; - ipcInitialize(&c); - u64 cmd_id = ((u32 *)r.Raw)[2]; - Result retval = 0xF601; - - cur_out_r.NumHandles = 0; - - Log(armGetTls(), 0x100); - - u32 *cmdbuf = (u32 *)armGetTls(); - if (r.CommandType == IpcCommandType_Close) { - Reboot(); - } - - if (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext) { - std::shared_ptr<IServiceObject> obj; - if (r.IsDomainRequest) { - obj = this->domain->get_domain_object(r.InThisObjectId); - if (obj != nullptr && r.InMessageType == DomainMessageType_Close) { - if (r.InThisObjectId == this->mitm_domain_id) { - Reboot(); - } - this->domain->delete_object(r.InThisObjectId); - struct { - u64 magic; - u64 result; - } *o_resp; - - o_resp = (decltype(o_resp)) ipcPrepareHeaderForDomain(&c, sizeof(*o_resp), 0); - *(DomainResponseHeader *)((uintptr_t)o_resp - sizeof(DomainResponseHeader)) = {0}; - o_resp->magic = SFCO_MAGIC; - o_resp->result = 0x0; - Log(armGetTls(), 0x100); - return o_resp->result; - } - } else { - obj = this->service_object; - } - if (obj != nullptr) { - retval = obj->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size()); - if (R_SUCCEEDED(retval)) { - if (r.IsDomainRequest) { - /* We never work with out object ids, so this should be fine. */ - ipcParseDomainResponse(&cur_out_r, 0); - } else { - ipcParse(&cur_out_r); - } - return retval; - } - } - } else if (r.CommandType == IpcCommandType_Control || r.CommandType == IpcCommandType_ControlWithContext) { - /* Ipc Clone Current Object. */ - retval = serviceIpcDispatch(&forward_service); - Log(armGetTls(), 0x100); - if (R_SUCCEEDED(retval)) { - ipcParse(&cur_out_r); - struct { - u64 magic; - u64 result; - } *resp = (decltype(resp))cur_out_r.Raw; - retval = resp->result; - if ((cmd_id == IpcCtrl_Cmd_CloneCurrentObject || cmd_id == IpcCtrl_Cmd_CloneCurrentObjectEx)) { - if (R_SUCCEEDED(retval)) { - Handle s_h; - Handle c_h; - Result rc; - if (R_FAILED((rc = svcCreateSession(&s_h, &c_h, 0, 0)))) { - fatalSimple(rc); - } - - if (cur_out_r.NumHandles != 1) { - Reboot(); - } - - MitMSession<T> *new_sess = new MitMSession<T>((MitMServer<T> *)this->server, s_h, c_h, cur_out_r.Handles[0]); - new_sess->service_object = this->service_object; - - if (this->is_domain) { - new_sess->is_domain = true; - new_sess->domain = this->domain; - new_sess->mitm_domain_id = this->mitm_domain_id; - new_sess->forward_service.type = this->forward_service.type; - new_sess->forward_service.object_id = this->forward_service.object_id; - } - this->get_manager()->add_waitable(new_sess); - ipcSendHandleMove(&c, c_h); - struct { - u64 magic; - u64 result; - } *o_resp; - - o_resp = (decltype(o_resp)) ipcPrepareHeader(&c, sizeof(*o_resp)); - o_resp->magic = SFCO_MAGIC; - o_resp->result = 0x0; - } - } - } - Log(armGetTls(), 0x100); - return retval; - } - - /* 0xF601 --> Dispatch onwards. */ - if (retval == 0xF601) { - /* Patch PID Descriptor, if relevant. */ - if (r.HasPid) { - /* [ctrl 0] [ctrl 1] [handle desc 0] [pid low] [pid high] */ - cmdbuf[4] = 0xFFFE0000UL | (cmdbuf[4] & 0xFFFFUL); - } - - Log(armGetTls(), 0x100); - retval = serviceIpcDispatch(&forward_service); - if (R_SUCCEEDED(retval)) { - if (r.IsDomainRequest) { - /* We never work with out object ids, so this should be fine. */ - ipcParseDomainResponse(&cur_out_r, 0); - } else { - ipcParse(&cur_out_r); - } - - struct { - u64 magic; - u64 result; - } *resp = (decltype(resp))cur_out_r.Raw; - - retval = resp->result; - } - } - - Log(armGetTls(), 0x100); - Log(&cmd_id, sizeof(u64)); - u64 retval_for_log = retval; - Log(&retval_for_log, sizeof(u64)); - if (R_FAILED(retval)) { - //Reboot(); - } - - return retval; - } - - void postprocess(IpcParsedCommand &r, u64 cmd_id) override { - if (this->active_object == this->service_object && (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext)) { - IpcCommand c; - ipcInitialize(&c); - this->service_object->postprocess(cur_out_r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size()); - } else if (r.CommandType == IpcCommandType_Control || r.CommandType == IpcCommandType_ControlWithContext) { - if (cmd_id == IpcCtrl_Cmd_ConvertCurrentObjectToDomain) { - this->is_domain = true; - this->domain = std::make_shared<DomainOwner>(); - struct { - u64 magic; - u64 result; - u32 domain_id; - } *resp = (decltype(resp))cur_out_r.Raw; - Result rc; - if (R_FAILED((rc = this->domain->set_object(this->service_object, resp->domain_id)))) { - fatalSimple(rc); - } - this->mitm_domain_id = resp->domain_id; - this->forward_service.type = ServiceType_Domain; - this->forward_service.object_id = resp->domain_id; - } - } - } - - void cleanup() override { - /* Clean up copy handles. */ - for (unsigned int i = 0; i < cur_out_r.NumHandles; i++) { - if (cur_out_r.WasHandleCopied[i]) { - svcCloseHandle(cur_out_r.Handles[i]); - } - } - } -}; diff --git a/stratosphere/fs_mitm/source/setsys_mitm_service.cpp b/stratosphere/fs_mitm/source/setsys_mitm_service.cpp index 2d702f93c..a8bb5624a 100644 --- a/stratosphere/fs_mitm/source/setsys_mitm_service.cpp +++ b/stratosphere/fs_mitm/source/setsys_mitm_service.cpp @@ -18,7 +18,6 @@ #include <switch.h> #include "setsys_mitm_service.hpp" -#include "mitm_query_service.hpp" #include "debug.hpp" static HosMutex g_version_mutex; @@ -51,54 +50,20 @@ static Result _GetFirmwareVersion(SetSysFirmwareVersion *out) { return 0; } -Result SetSysMitMService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - - switch (static_cast<SetSysCmd>(cmd_id)) { - case SetSysCmd::GetFirmwareVersion: - rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case SetSysCmd::GetFirmwareVersion2: - if (kernelAbove300()) { - rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version2>(this, r, out_c, pointer_buffer, pointer_buffer_size); - } - break; - default: - break; - } - - return rc; -} - -void SetSysMitMService::postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { +void SetSysMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { /* No commands need postprocessing. */ } -Result SetSysMitMService::handle_deferred() { - /* This service is never deferrable. */ - return 0; -} - -std::tuple<Result> SetSysMitMService::get_firmware_version(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { - if (out.num_elements != 1) { - return {0xF601}; - } - +Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { Result rc = _GetFirmwareVersion(out.pointer); /* GetFirmwareVersion sanitizes these fields. */ out.pointer->revision_major = 0; out.pointer->revision_minor = 0; - return {rc}; + return rc; } -std::tuple<Result> SetSysMitMService::get_firmware_version2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { - if (out.num_elements != 1) { - return {0xF601}; - } - - Result rc = _GetFirmwareVersion(out.pointer); - - return {rc}; +Result SetSysMitmService::GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { + return _GetFirmwareVersion(out.pointer); } \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/setsys_mitm_service.hpp b/stratosphere/fs_mitm/source/setsys_mitm_service.hpp index 8c8877881..b62bdcb69 100644 --- a/stratosphere/fs_mitm/source/setsys_mitm_service.hpp +++ b/stratosphere/fs_mitm/source/setsys_mitm_service.hpp @@ -16,43 +16,34 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> -#include "imitmserviceobject.hpp" +#include <stratosphere.hpp> #include "fsmitm_utils.hpp" -enum class SetSysCmd { - GetFirmwareVersion = 3, - GetFirmwareVersion2 = 4, +enum SetSysCmd : u32 { + SetSysCmd_GetFirmwareVersion = 3, + SetSysCmd_GetFirmwareVersion2 = 4, }; -class SetSysMitMService : public IMitMServiceObject { - private: +class SetSysMitmService : public IMitmServiceObject { public: - SetSysMitMService(Service *s) : IMitMServiceObject(s) { + SetSysMitmService(std::shared_ptr<Service> s) : IMitmServiceObject(s) { /* ... */ } - static bool should_mitm(u64 pid, u64 tid) { + static bool ShouldMitm(u64 pid, u64 tid) { /* Only MitM qlaunch, maintenance. */ return tid == 0x0100000000001000ULL || tid == 0x0100000000001015ULL; } - SetSysMitMService *clone() override { - auto new_srv = new SetSysMitMService((Service *)&this->forward_service); - this->clone_to(new_srv); - return new_srv; - } - - void clone_to(void *o) override { - /* ... */ - } - - virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); - virtual void postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); - virtual Result handle_deferred(); - + static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); + protected: /* Overridden commands. */ - std::tuple<Result> get_firmware_version(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); - std::tuple<Result> get_firmware_version2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); + Result GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); + Result GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion, &SetSysMitmService::GetFirmwareVersion>(), + MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion2, &SetSysMitmService::GetFirmwareVersion2>(), + }; }; diff --git a/stratosphere/fs_mitm/source/sm_mitm.c b/stratosphere/fs_mitm/source/sm_mitm.c deleted file mode 100644 index 0ab1c5d55..000000000 --- a/stratosphere/fs_mitm/source/sm_mitm.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <switch.h> -#include <switch/arm/atomics.h> -#include "sm_mitm.h" - -static Handle g_smMitmHandle = INVALID_HANDLE; -static u64 g_refCnt; - -Result smMitMInitialize(void) { - atomicIncrement64(&g_refCnt); - - if (g_smMitmHandle != INVALID_HANDLE) - return 0; - - Result rc = svcConnectToNamedPort(&g_smMitmHandle, "sm:"); - - if (R_SUCCEEDED(rc)) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 zero; - u64 reserved[2]; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->zero = 0; - - rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - } - - if (R_FAILED(rc)) - smExit(); - - return rc; -} - -void smMitMExit(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - svcCloseHandle(g_smMitmHandle); - g_smMitmHandle = INVALID_HANDLE; - } -} - -Result smMitMGetService(Service* service_out, const char *name_str) -{ - u64 name = smEncodeName(name_str); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - u64 reserved[2]; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->service_name = name; - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - service_out->type = ServiceType_Normal; - service_out->handle = r.Handles[0]; - } - } - - return rc; -} - - -Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65000; - raw->service_name = smEncodeName(name); - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - *query_out = r.Handles[1]; - } - } - - return rc; -} - -Result smMitMUninstall(const char *name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - u64 reserved; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65001; - raw->service_name = smEncodeName(name); - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; -} \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/sm_mitm.h b/stratosphere/fs_mitm/source/sm_mitm.h deleted file mode 100644 index 4b521c88c..000000000 --- a/stratosphere/fs_mitm/source/sm_mitm.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file sm_mitm.h - * @brief Service manager (sm) IPC wrapper for Atmosphere extensions. - * @author SciresM - * @copyright libnx Authors - */ -#pragma once -#include <switch.h> - -#ifdef __cplusplus -extern "C" { -#endif - -Result smMitMInitialize(void); -void smMitMExit(void); -Result smMitMGetService(Service* service_out, const char *name); -Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name); -Result smMitMUninstall(const char *name); - -Result smMitMIsRegistered(const char *name); - -#ifdef __cplusplus -} -#endif \ No newline at end of file From 3dc679215b7899514722439efbbf912a916be69d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 17:38:24 -0700 Subject: [PATCH 147/489] fs.mitm: Remove debugging options --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 2d96ce78e..c96462eaa 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -131,12 +131,12 @@ int main(int argc, char **argv) AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); /* Create set:sys mitm server, delayed until set:sys is available. */ - //if (R_FAILED(threadCreate(&set_mitm_setup_thread, &CreateSettingsMitMServer, server_manager, 0x4000, 0x15, 0))) { + if (R_FAILED(threadCreate(&set_mitm_setup_thread, &CreateSettingsMitMServer, server_manager, 0x4000, 0x15, 0))) { /* TODO: Panic. */ - //} - //if (R_FAILED(threadStart(&set_mitm_setup_thread))) { + } + if (R_FAILED(threadStart(&set_mitm_setup_thread))) { /* TODO: Panic. */ - //} + } /* Loop forever, servicing our services. */ server_manager->Process(); From 23a85a7c2452e8163866c8c39d0573f355cc6908 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 22:14:34 -0700 Subject: [PATCH 148/489] fs.mitm: split out set.mitm --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 33 +-------- .../fs_mitm/source/fsmitm_service.cpp | 23 +++---- .../fs_mitm/source/setsys_mitm_service.cpp | 69 ------------------- .../fs_mitm/source/setsys_mitm_service.hpp | 49 ------------- .../stratosphere/mitm/mitm_query_service.hpp | 4 +- .../include/stratosphere/mitm/mitm_server.hpp | 2 +- 6 files changed, 13 insertions(+), 167 deletions(-) delete mode 100644 stratosphere/fs_mitm/source/setsys_mitm_service.cpp delete mode 100644 stratosphere/fs_mitm/source/setsys_mitm_service.hpp diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index c96462eaa..28b47fbfb 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -26,8 +26,6 @@ #include "fsmitm_utils.hpp" -#include "setsys_mitm_service.hpp" - extern "C" { extern u32 __start__; @@ -63,11 +61,6 @@ void __appInit(void) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); } - rc = smMitMInitialize(); - if (R_FAILED(rc)) { - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); - } - rc = fsInitialize(); if (R_FAILED(rc)) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); @@ -78,7 +71,6 @@ void __appInit(void) { void __appExit(void) { /* Cleanup services. */ fsExit(); - smMitMExit(); smExit(); } @@ -87,27 +79,12 @@ struct FsMitmManagerOptions { static const size_t MaxDomains = 0x10; static const size_t MaxDomainObjects = 0x4000; }; - using FsMitmManager = WaitableManager<FsMitmManagerOptions>; -void CreateSettingsMitMServer(void *arg) { - auto server_manager = (FsMitmManager *)arg; - - Result rc; - if (R_FAILED((rc = setsysInitialize()))) { - fatalSimple(rc); - } - - AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 5); - - svcExitThread(); -} - int main(int argc, char **argv) { Thread sd_initializer_thread = {0}; Thread hid_initializer_thread = {0}; - Thread set_mitm_setup_thread = {0}; consoleDebugInit(debugDevice_SVC); if (R_FAILED(threadCreate(&sd_initializer_thread, &Utils::InitializeSdThreadFunc, NULL, 0x4000, 0x15, 0))) { @@ -129,15 +106,7 @@ int main(int argc, char **argv) /* Create fsp-srv mitm. */ AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); - - /* Create set:sys mitm server, delayed until set:sys is available. */ - if (R_FAILED(threadCreate(&set_mitm_setup_thread, &CreateSettingsMitMServer, server_manager, 0x4000, 0x15, 0))) { - /* TODO: Panic. */ - } - if (R_FAILED(threadStart(&set_mitm_setup_thread))) { - /* TODO: Panic. */ - } - + /* Loop forever, servicing our services. */ server_manager->Process(); diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index da19d5778..75e575067 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -48,6 +48,15 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora std::shared_ptr<IStorageInterface> storage = nullptr; u32 out_domain_id = 0; Result rc = 0; + + ON_SCOPE_EXIT { + if (R_SUCCEEDED(rc)) { + out_storage.SetValue(std::move(storage)); + if (out_storage.IsDomain()) { + out_storage.ChangeObjectId(out_domain_id); + } + } + }; if (this->romfs_storage != nullptr) { if (out_storage.IsDomain()) { @@ -83,13 +92,6 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora } } - if (R_SUCCEEDED(rc)) { - out_storage.SetValue(std::move(storage)); - if (out_storage.IsDomain()) { - out_storage.ChangeObjectId(out_domain_id); - } - } - return rc; } @@ -126,12 +128,5 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf } } - if (R_SUCCEEDED(rc)) { - out_storage.SetValue(std::move(storage)); - if (out_storage.IsDomain()) { - out_storage.ChangeObjectId(out_domain_id); - } - } - return rc; } \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/setsys_mitm_service.cpp b/stratosphere/fs_mitm/source/setsys_mitm_service.cpp deleted file mode 100644 index a8bb5624a..000000000 --- a/stratosphere/fs_mitm/source/setsys_mitm_service.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <mutex> -#include <switch.h> -#include "setsys_mitm_service.hpp" - -#include "debug.hpp" - -static HosMutex g_version_mutex; -static bool g_got_version = false; -static SetSysFirmwareVersion g_fw_version = {0}; - -static Result _GetFirmwareVersion(SetSysFirmwareVersion *out) { - std::lock_guard<HosMutex> lock(g_version_mutex); - if (!g_got_version) { - Result rc = setsysGetFirmwareVersion(&g_fw_version); - if (R_FAILED(rc)) { - return rc; - } - - /* Modify the output firmware version. */ - { - u32 major, minor, micro; - char display_version[sizeof(g_fw_version.display_version)] = {0}; - - GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); - snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro); - - memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version)); - } - - g_got_version = true; - } - - *out = g_fw_version; - return 0; -} - -void SetSysMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { - /* No commands need postprocessing. */ -} - -Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { - Result rc = _GetFirmwareVersion(out.pointer); - - /* GetFirmwareVersion sanitizes these fields. */ - out.pointer->revision_major = 0; - out.pointer->revision_minor = 0; - - return rc; -} - -Result SetSysMitmService::GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { - return _GetFirmwareVersion(out.pointer); -} \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/setsys_mitm_service.hpp b/stratosphere/fs_mitm/source/setsys_mitm_service.hpp deleted file mode 100644 index b62bdcb69..000000000 --- a/stratosphere/fs_mitm/source/setsys_mitm_service.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <stratosphere.hpp> -#include "fsmitm_utils.hpp" - -enum SetSysCmd : u32 { - SetSysCmd_GetFirmwareVersion = 3, - SetSysCmd_GetFirmwareVersion2 = 4, -}; - -class SetSysMitmService : public IMitmServiceObject { - public: - SetSysMitmService(std::shared_ptr<Service> s) : IMitmServiceObject(s) { - /* ... */ - } - - static bool ShouldMitm(u64 pid, u64 tid) { - /* Only MitM qlaunch, maintenance. */ - return tid == 0x0100000000001000ULL || tid == 0x0100000000001015ULL; - } - - static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); - - protected: - /* Overridden commands. */ - Result GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); - Result GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); - public: - DEFINE_SERVICE_DISPATCH_TABLE { - MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion, &SetSysMitmService::GetFirmwareVersion>(), - MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion2, &SetSysMitmService::GetFirmwareVersion2>(), - }; -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp index a007cdc82..621c4cfb6 100644 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp @@ -44,7 +44,7 @@ class MitmQueryService : public IServiceObject { } public: DEFINE_SERVICE_DISPATCH_TABLE { - MakeServiceCommandMeta<MQS_Cmd_ShouldMitm, &MitmQueryService::ShouldMitm>(), - MakeServiceCommandMeta<MQS_Cmd_AssociatePidTid, &MitmQueryService::AssociatePidToTid>(), + MakeServiceCommandMeta<MQS_Cmd_ShouldMitm, &MitmQueryService<T>::ShouldMitm>(), + MakeServiceCommandMeta<MQS_Cmd_AssociatePidTid, &MitmQueryService<T>::AssociatePidToTid>(), }; }; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp index 5380fae26..dc7dbac6e 100644 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp @@ -93,8 +93,8 @@ template<typename T> static void AddMitmServerToManager(SessionManagerBase *manager, const char *srv_name, unsigned int max_sessions) { Handle query_h; auto *srv = new MitmServer<T>(&query_h, srv_name, max_sessions); - manager->AddWaitable(srv); manager->AddSession(query_h, std::move(ServiceObjectHolder(std::move(std::make_shared<MitmQueryService<T>>())))); + manager->AddWaitable(srv); } From 4cdd9aa8f1a96cab769772b514b251444cf367af Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 22:17:41 -0700 Subject: [PATCH 149/489] libstratosphere: Fix uninitialized memory bug. --- .../stratosphere/ipc/ipc_service_object.hpp | 3 ++- .../stratosphere/mitm/imitmserviceobject.hpp | 8 ++++++++ .../include/stratosphere/mitm/mitm_server.hpp | 14 +++++++++++++- .../include/stratosphere/mitm/mitm_session.hpp | 13 +++++++------ .../include/stratosphere/waitable_manager.hpp | 14 ++++++++++---- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp index 979cd22a1..c2189920d 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp @@ -124,6 +124,7 @@ class ServiceObjectHolder { } ServiceObjectHolder Clone() { - return ServiceObjectHolder(*this); + ServiceObjectHolder clone(*this); + return clone; } }; diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp index 873487be5..e37ba152c 100644 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp @@ -28,6 +28,14 @@ class IMitmServiceObject : public IServiceObject { public: IMitmServiceObject(std::shared_ptr<Service> s) : forward_service(s) {} + virtual u64 GetTitleId() { + return this->title_id; + } + + virtual u64 GetProcessId() { + return this->process_id; + } + static bool ShouldMitm(u64 pid, u64 tid); protected: diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp index dc7dbac6e..113df8a55 100644 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp @@ -32,7 +32,10 @@ class MitmServer : public IWaitable { public: MitmServer(Handle *out_query_h, const char *service_name, unsigned int max_s) : port_handle(0), max_sessions(max_s) { Handle tmp_hnd; - Result rc; + Result rc = smMitMInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } if (R_SUCCEEDED((rc = smGetServiceOriginal(&tmp_hnd, smEncodeName(service_name))))) { svcCloseHandle(tmp_hnd); @@ -44,6 +47,8 @@ class MitmServer : public IWaitable { if (R_FAILED((rc = smMitMInstall(&this->port_handle, out_query_h, mitm_name)))) { fatalSimple(rc); } + + smMitMExit(); } virtual ~MitmServer() override { @@ -79,10 +84,17 @@ class MitmServer : public IWaitable { delete s; }); + rc = smMitMInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + if (R_FAILED(smMitMGetService(forward_service.get(), mitm_name))) { /* TODO: Panic. */ } + smMitMExit(); + this->GetSessionManager()->AddWaitable(new MitmSession(session_h, forward_service, std::make_shared<T>(forward_service))); return 0; } diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp index 33deb8b03..f4df504f1 100644 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp @@ -30,7 +30,7 @@ class MitmSession final : public ServiceSession { void (*service_post_process_handler)(IMitmServiceObject *, IpcResponseContext *); /* For cleanup usage. */ - u32 num_fwd_copy_hnds; + u32 num_fwd_copy_hnds = 0; Handle fwd_copy_hnds[8]; public: template<typename T> @@ -46,7 +46,7 @@ class MitmSession final : public ServiceSession { } this->pointer_buffer.resize(pbs); this->control_holder.Reset(); - this->control_holder = ServiceObjectHolder(std::make_shared<IMitmHipcControlService>(this)); + this->control_holder = std::move(ServiceObjectHolder(std::move(std::make_shared<IMitmHipcControlService>(this)))); } MitmSession(Handle s_h, std::shared_ptr<Service> fs, ServiceObjectHolder &&h, void (*pph)(IMitmServiceObject *, IpcResponseContext *)) : ServiceSession(s_h) { @@ -62,7 +62,7 @@ class MitmSession final : public ServiceSession { } this->pointer_buffer.resize(pbs); this->control_holder.Reset(); - this->control_holder = ServiceObjectHolder(std::make_shared<IMitmHipcControlService>(this)); + this->control_holder = std::move(ServiceObjectHolder(std::move(std::make_shared<IMitmHipcControlService>(this)))); } virtual void PreProcessRequest(IpcResponseContext *ctx) override { @@ -101,7 +101,7 @@ class MitmSession final : public ServiceSession { } return rc; } - + virtual Result GetResponse(IpcResponseContext *ctx) { Result rc = 0xF601; FirmwareVersion fw = GetRuntimeFirmwareVersion(); @@ -130,7 +130,8 @@ class MitmSession final : public ServiceSession { { auto sub_obj = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId); if (sub_obj == nullptr) { - return ForwardRequest(ctx); + rc = ForwardRequest(ctx); + return rc; } dispatch_table = sub_obj->GetDispatchTable(); entry_count = sub_obj->GetDispatchTableEntryCount(); @@ -152,7 +153,7 @@ class MitmSession final : public ServiceSession { memcpy(armGetTls(), this->backup_tls, sizeof(this->backup_tls)); rc = ForwardRequest(ctx); } - + return rc; } diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp index 9ce75d9f0..099c8dfbd 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -165,6 +165,7 @@ class WaitableManager : public SessionManagerBase { if (result == nullptr) { std::vector<Handle> handles; + std::vector<IWaitable *> wait_list; int handle_index = 0; Result rc; @@ -174,11 +175,14 @@ class WaitableManager : public SessionManagerBase { /* Copy out handles. */ handles.resize(this->waitables.size() + 1); + wait_list.resize(this->waitables.size() + 1); handles[0] = this->new_waitable_event->GetHandle(); + wait_list[0] = this->new_waitable_event; unsigned int num_handles = 1; for (unsigned int i = 0; i < this->waitables.size(); i++) { Handle h = this->waitables[i]->GetHandle(); if (h != INVALID_HANDLE) { + wait_list[num_handles] = this->waitables[i]; handles[num_handles++] = h; } } @@ -194,14 +198,15 @@ class WaitableManager : public SessionManagerBase { /* Wait forever. */ rc = svcWaitSynchronization(&handle_index, handles.data(), num_handles, U64_MAX); - IWaitable *w = this->waitables[handle_index - 1]; + IWaitable *w = wait_list[handle_index]; + size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); if (R_SUCCEEDED(rc)) { if (handle_index == 0) { AddWaitablesInternal(); continue; } - std::for_each(waitables.begin(), waitables.begin() + handle_index - 1, std::mem_fn(&IWaitable::UpdatePriority)); + std::for_each(waitables.begin(), waitables.begin() + w_ind, std::mem_fn(&IWaitable::UpdatePriority)); result = w; } else if (rc == 0xEA01) { /* Timeout: Just update priorities. */ @@ -216,8 +221,9 @@ class WaitableManager : public SessionManagerBase { if (handle_index == 0) { std::abort(); } - this->waitables.erase(this->waitables.begin() + handle_index - 1); - std::for_each(waitables.begin(), waitables.begin() + handle_index - 1, std::mem_fn(&IWaitable::UpdatePriority)); + + this->waitables.erase(this->waitables.begin() + w_ind); + std::for_each(waitables.begin(), waitables.begin() + w_ind - 1, std::mem_fn(&IWaitable::UpdatePriority)); delete w; } } From bbffbd654f8c4d7087a260615189f39c41e5f746 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 22:18:04 -0700 Subject: [PATCH 150/489] set.mitm: Split out from fs.mitm --- stratosphere/Makefile | 2 +- stratosphere/set_mitm/Makefile | 159 ++++++++++++++++++ stratosphere/set_mitm/set_mitm.json | 98 +++++++++++ stratosphere/set_mitm/source/setmitm_main.cpp | 101 +++++++++++ .../set_mitm/source/setsys_mitm_service.cpp | 69 ++++++++ .../set_mitm/source/setsys_mitm_service.hpp | 48 ++++++ 6 files changed, 476 insertions(+), 1 deletion(-) create mode 100644 stratosphere/set_mitm/Makefile create mode 100644 stratosphere/set_mitm/set_mitm.json create mode 100644 stratosphere/set_mitm/source/setmitm_main.cpp create mode 100644 stratosphere/set_mitm/source/setsys_mitm_service.cpp create mode 100644 stratosphere/set_mitm/source/setsys_mitm_service.hpp diff --git a/stratosphere/Makefile b/stratosphere/Makefile index 1c1e5b1e5..559327b9e 100644 --- a/stratosphere/Makefile +++ b/stratosphere/Makefile @@ -1,4 +1,4 @@ -KIPS := loader pm sm boot fs_mitm creport +KIPS := loader pm sm boot fs_mitm set_mitm creport #TODO: boot2 ? diff --git a/stratosphere/set_mitm/Makefile b/stratosphere/set_mitm/Makefile new file mode 100644 index 000000000..c042e968d --- /dev/null +++ b/stratosphere/set_mitm/Makefile @@ -0,0 +1,159 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include ../../common/include +EXEFS_SRC := exefs_src + +DEFINES := -DDISABLE_IPC + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lstratosphere -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) $(CURDIR)/../libstratosphere + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) + +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).npdm $(TARGET).nso $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).nsp + +ifeq ($(strip $(APP_JSON)),) +$(OUTPUT).nsp : $(OUTPUT).nso +else +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm +endif + +$(OUTPUT).nso : $(OUTPUT).elf + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/stratosphere/set_mitm/set_mitm.json b/stratosphere/set_mitm/set_mitm.json new file mode 100644 index 000000000..1383e7e2c --- /dev/null +++ b/stratosphere/set_mitm/set_mitm.json @@ -0,0 +1,98 @@ +{ + "name": "set.mitm", + "title_id": "0x0100000000000032", + "title_id_range_min": "0x0100000000000032", + "title_id_range_max": "0x0100000000000032", + "main_thread_stack_size": "0x00004000", + "main_thread_priority": 49, + "default_cpu_id": 3, + "process_category": 0, + "is_retail": true, + "pool_partition": 2, + "is_64_bit": true, + "address_space_type": 3, + "filesystem_access": { + "permissions": "0xFFFFFFFFFFFFFFFF" + }, + "service_access": { + "fatal:u": false, + "fsp-srv": false, + "spl:": false, + "set:sys": false, + "set:sys": true + }, + "kernel_capabilities": { + "kernel_flags": { + "highest_thread_priority": 63, + "lowest_thread_priority": 24, + "lowest_cpu_id": 3, + "highest_cpu_id": 3 + }, + "syscalls": { + + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0a", + "svcSleepThread": "0x0b", + "svcGetThreadPriority": "0x0c", + "svcSetThreadPriority": "0x0d", + "svcGetThreadCoreMask": "0x0e", + "svcSetThreadCoreMask": "0x0f", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1a", + "svcArbitrateUnlock": "0x1b", + "svcWaitProcessWideKeyAtomic": "0x1c", + "svcSignalProcessWideKey": "0x1d", + "svcGetSystemTick": "0x1e", + "svcConnectToNamedPort": "0x1f", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcCreateEvent": "0x45", + "svcCreateInterruptEvent": "0x53", + "svcReadWriteRegister": "0x4E", + "svcQueryIoMapping": "0x55", + "svcCreateDeviceAddressSpace": "0x56", + "svcAttachDeviceAddressSpace": "0x57", + "svcDetachDeviceAddressSpace": "0x58", + "svcMapDeviceAddressSpaceAligned": "0x5a", + "svcUnmapDeviceAddressSpace": "0x5c", + "svcGetSystemInfo": "0x6f" + }, + "min_kernel_version": "0x0060", + "debug_flags": { + "allow_debug": false, + "force_debug": true + } + } +} \ No newline at end of file diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/set_mitm/source/setmitm_main.cpp new file mode 100644 index 000000000..c03f5099d --- /dev/null +++ b/stratosphere/set_mitm/source/setmitm_main.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <stratosphere.hpp> + +#include "setsys_mitm_service.hpp" + +extern "C" { + extern u32 __start__; + + u32 __nx_applet_type = AppletType_None; + + #define INNER_HEAP_SIZE 0x20000 + size_t nx_inner_heap_size = INNER_HEAP_SIZE; + char nx_inner_heap[INNER_HEAP_SIZE]; + + void __libnx_initheap(void); + void __appInit(void); + void __appExit(void); +} + + +void __libnx_initheap(void) { + void* addr = nx_inner_heap; + size_t size = nx_inner_heap_size; + + /* Newlib */ + extern char* fake_heap_start; + extern char* fake_heap_end; + + fake_heap_start = (char*)addr; + fake_heap_end = (char*)addr + size; +} + +void __appInit(void) { + Result rc; + + rc = smInitialize(); + if (R_FAILED(rc)) { + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); + } + + rc = setsysInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + CheckAtmosphereVersion(); +} + +void __appExit(void) { + /* Cleanup services. */ + setsysExit(); + smExit(); +} + +struct SetSysManagerOptions { + static const size_t PointerBufferSize = 0x100; + static const size_t MaxDomains = 4; + static const size_t MaxDomainObjects = 0x100; +}; + +using SetMitmManager = WaitableManager<SetSysManagerOptions>; + +int main(int argc, char **argv) +{ + consoleDebugInit(debugDevice_SVC); + + /* TODO: What's a good timeout value to use here? */ + auto server_manager = new SetMitmManager(1); + + /* Create fsp-srv mitm. */ + AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 4); + + /* Loop forever, servicing our services. */ + server_manager->Process(); + + delete server_manager; + + return 0; +} + diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.cpp b/stratosphere/set_mitm/source/setsys_mitm_service.cpp new file mode 100644 index 000000000..60e1c5e2c --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_mitm_service.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <mutex> +#include <switch.h> +#include "setsys_mitm_service.hpp" + +static HosMutex g_version_mutex; +static bool g_got_version = false; +static SetSysFirmwareVersion g_fw_version = {0}; + +static Result _GetFirmwareVersion(SetSysFirmwareVersion *out) { + std::scoped_lock<HosMutex> lock(g_version_mutex); + if (!g_got_version) { + Result rc = setsysGetFirmwareVersion(&g_fw_version); + if (R_FAILED(rc)) { + return rc; + } + + /* Modify the output firmware version. */ + { + u32 major, minor, micro; + char display_version[sizeof(g_fw_version.display_version)] = {0}; + + GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); + snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro); + + memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version)); + } + + g_got_version = true; + } + + *out = g_fw_version; + return 0; +} + +void SetSysMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { + /* No commands need postprocessing. */ +} + +Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { + Result rc = _GetFirmwareVersion(out.pointer); + + /* GetFirmwareVersion sanitizes these fields. */ + if (R_SUCCEEDED(rc)) { + out.pointer->revision_major = 0; + out.pointer->revision_minor = 0; + } + + return rc; +} + +Result SetSysMitmService::GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { + return _GetFirmwareVersion(out.pointer); +} \ No newline at end of file diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.hpp b/stratosphere/set_mitm/source/setsys_mitm_service.hpp new file mode 100644 index 000000000..2e3da205f --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_mitm_service.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +enum SetSysCmd : u32 { + SetSysCmd_GetFirmwareVersion = 3, + SetSysCmd_GetFirmwareVersion2 = 4, +}; + +class SetSysMitmService : public IMitmServiceObject { + public: + SetSysMitmService(std::shared_ptr<Service> s) : IMitmServiceObject(s) { + /* ... */ + } + + static bool ShouldMitm(u64 pid, u64 tid) { + /* Only MitM qlaunch, maintenance. */ + return tid == 0x0100000000001000ULL || tid == 0x0100000000001015ULL; + } + + static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); + + protected: + /* Overridden commands. */ + Result GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); + Result GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion, &SetSysMitmService::GetFirmwareVersion>(), + MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion2, &SetSysMitmService::GetFirmwareVersion2>(), + }; +}; From 8b713789206d9d9f7c5417e177691ed47f88528f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 22:18:59 -0700 Subject: [PATCH 151/489] atmosphere: add set.mitm to make dist target --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 6f1bb8c77..51df7192b 100644 --- a/Makefile +++ b/Makefile @@ -31,10 +31,12 @@ dist: fusee creport mkdir atmosphere-$(AMSVER) mkdir atmosphere-$(AMSVER)/atmosphere mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 + mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032 cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/fusee-secondary.bin cp common/defaults/BCT.ini atmosphere-$(AMSVER)/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp + cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; rm -r atmosphere-$(AMSVER) mkdir out From c49cfbd6aff40afcc2e39f6e2ed03a1a1a96f958 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 22:33:56 -0700 Subject: [PATCH 152/489] loader: update for libstratosphere refactor --- stratosphere/loader/loader.json | 3 + .../loader/source/ldr_debug_monitor.cpp | 40 ++------ .../loader/source/ldr_debug_monitor.hpp | 27 +++--- .../loader/source/ldr_launch_queue.cpp | 28 +++--- .../loader/source/ldr_launch_queue.hpp | 16 ++-- stratosphere/loader/source/ldr_main.cpp | 27 ++++-- .../loader/source/ldr_process_manager.cpp | 60 +++--------- .../loader/source/ldr_process_manager.hpp | 33 +++---- stratosphere/loader/source/ldr_ro_service.cpp | 93 ++++++------------- stratosphere/loader/source/ldr_ro_service.hpp | 31 +++---- stratosphere/loader/source/ldr_shell.cpp | 37 ++------ stratosphere/loader/source/ldr_shell.hpp | 27 +++--- 12 files changed, 150 insertions(+), 272 deletions(-) diff --git a/stratosphere/loader/loader.json b/stratosphere/loader/loader.json index 27544a507..272e9f772 100644 --- a/stratosphere/loader/loader.json +++ b/stratosphere/loader/loader.json @@ -56,6 +56,9 @@ "svcReplyAndReceiveLight" : "0x42", "svcReplyAndReceive" : "0x43", "svcReplyAndReceiveWithUserBuffer" : "0x44", + "svcCreateEvent": "0x45", + "svcReadWriteRegister" : "0x4E", + "svcQueryIoMapping": "0x55", "svcSetProcessMemoryPermission" : "0x73", "svcMapProcessMemory" : "0x74", "svcUnmapProcessMemory" : "0x75", diff --git a/stratosphere/loader/source/ldr_debug_monitor.cpp b/stratosphere/loader/source/ldr_debug_monitor.cpp index a2e12e3f8..01fd0497b 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.cpp +++ b/stratosphere/loader/source/ldr_debug_monitor.cpp @@ -22,42 +22,18 @@ #include "ldr_launch_queue.hpp" #include "ldr_registration.hpp" -Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - - switch ((DebugMonitorServiceCmd)cmd_id) { - case Dmnt_Cmd_AddTitleToLaunchQueue: - rc = WrapIpcCommandImpl<&DebugMonitorService::add_title_to_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_ClearLaunchQueue: - rc = WrapIpcCommandImpl<&DebugMonitorService::clear_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Dmnt_Cmd_GetNsoInfo: - rc = WrapIpcCommandImpl<&DebugMonitorService::get_nso_info>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - return rc; -} - -std::tuple<Result> DebugMonitorService::add_title_to_launch_queue(u64 args_size, u64 tid, InPointer<char> args) { +Result DebugMonitorService::AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args) { fprintf(stderr, "Add to launch queue: %p, %zX\n", args.pointer, std::min(args_size, args.num_elements)); - return {LaunchQueue::add(tid, args.pointer, std::min(args_size, args.num_elements))}; + return LaunchQueue::Add(tid, args.pointer, std::min(args_size, args.num_elements)); } -std::tuple<Result> DebugMonitorService::clear_launch_queue(u64 dat) { - fprintf(stderr, "Clear launch queue: %lx\n", dat); - LaunchQueue::clear(); - return {0}; +void DebugMonitorService::ClearLaunchQueue() { + LaunchQueue::Clear(); } -std::tuple<Result, u32> DebugMonitorService::get_nso_info(u64 pid, OutPointerWithClientSize<Registration::NsoInfo> out) { - u32 out_num_nsos = 0; - +Result DebugMonitorService::GetNsoInfo(Out<u32> count, OutPointerWithClientSize<Registration::NsoInfo> out, u64 pid) { + /* Zero out the output memory. */ std::fill(out.pointer, out.pointer + out.num_elements, (const Registration::NsoInfo){0}); - - Result rc = Registration::GetNsoInfosForProcessId(out.pointer, out.num_elements, pid, &out_num_nsos); - - return {rc, out_num_nsos}; + /* Actually return the nso infos. */ + return Registration::GetNsoInfosForProcessId(out.pointer, out.num_elements, pid, count.GetPointer()); } diff --git a/stratosphere/loader/source/ldr_debug_monitor.hpp b/stratosphere/loader/source/ldr_debug_monitor.hpp index d1b1c4e8a..167b2872f 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.hpp +++ b/stratosphere/loader/source/ldr_debug_monitor.hpp @@ -17,7 +17,7 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> #include "ldr_registration.hpp" enum DebugMonitorServiceCmd { @@ -26,21 +26,16 @@ enum DebugMonitorServiceCmd { Dmnt_Cmd_GetNsoInfo = 2 }; -class DebugMonitorService final : public IServiceObject { - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override { - /* This service will never defer. */ - return 0; - } - - DebugMonitorService *clone() override { - return new DebugMonitorService(); - } - +class DebugMonitorService final : public IServiceObject { private: /* Actual commands. */ - std::tuple<Result> add_title_to_launch_queue(u64 args_size, u64 tid, InPointer<char> args); - std::tuple<Result> clear_launch_queue(u64 dat); - std::tuple<Result, u32> get_nso_info(u64 pid, OutPointerWithClientSize<Registration::NsoInfo> out); + Result AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args); + void ClearLaunchQueue(); + Result GetNsoInfo(Out<u32> count, OutPointerWithClientSize<Registration::NsoInfo> out, u64 pid); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<Dmnt_Cmd_AddTitleToLaunchQueue, &DebugMonitorService::AddTitleToLaunchQueue>(), + MakeServiceCommandMeta<Dmnt_Cmd_ClearLaunchQueue, &DebugMonitorService::ClearLaunchQueue>(), + MakeServiceCommandMeta<Dmnt_Cmd_GetNsoInfo, &DebugMonitorService::GetNsoInfo>(), + }; }; diff --git a/stratosphere/loader/source/ldr_launch_queue.cpp b/stratosphere/loader/source/ldr_launch_queue.cpp index 8fda8585b..8f6933e42 100644 --- a/stratosphere/loader/source/ldr_launch_queue.cpp +++ b/stratosphere/loader/source/ldr_launch_queue.cpp @@ -23,12 +23,12 @@ static std::array<LaunchQueue::LaunchItem, LAUNCH_QUEUE_SIZE> g_launch_queue = {0}; -Result LaunchQueue::add(u64 tid, const char *args, u64 arg_size) { +Result LaunchQueue::Add(u64 tid, const char *args, u64 arg_size) { if(arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { return 0x209; } - int idx = get_free_index(tid); + int idx = GetFreeIndex(tid); if(idx == LAUNCH_QUEUE_FULL) return 0x409; @@ -39,22 +39,22 @@ Result LaunchQueue::add(u64 tid, const char *args, u64 arg_size) { return 0x0; } -Result LaunchQueue::add_copy(u64 tid_base, u64 tid) { - int idx = get_index(tid_base); +Result LaunchQueue::AddCopy(u64 tid_base, u64 tid) { + int idx = GetIndex(tid_base); if (idx == LAUNCH_QUEUE_FULL) { return 0x0; } - return add(tid, g_launch_queue[idx].args, g_launch_queue[idx].arg_size); + return Add(tid, g_launch_queue[idx].args, g_launch_queue[idx].arg_size); } -Result LaunchQueue::add_item(const LaunchItem *item) { +Result LaunchQueue::AddItem(const LaunchItem *item) { if(item->arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { return 0x209; } - int idx = get_free_index(item->tid); + int idx = GetFreeIndex(item->tid); if(idx == LAUNCH_QUEUE_FULL) return 0x409; @@ -62,7 +62,7 @@ Result LaunchQueue::add_item(const LaunchItem *item) { return 0x0; } -int LaunchQueue::get_index(u64 tid) { +int LaunchQueue::GetIndex(u64 tid) { auto it = std::find_if(g_launch_queue.begin(), g_launch_queue.end(), member_equals_fn(&LaunchQueue::LaunchItem::tid, tid)); if (it == g_launch_queue.end()) { return LAUNCH_QUEUE_FULL; @@ -70,7 +70,7 @@ int LaunchQueue::get_index(u64 tid) { return std::distance(g_launch_queue.begin(), it); } -int LaunchQueue::get_free_index(u64 tid) { +int LaunchQueue::GetFreeIndex(u64 tid) { for(unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { if(g_launch_queue[i].tid == tid || g_launch_queue[i].tid == 0x0) { return i; @@ -79,19 +79,19 @@ int LaunchQueue::get_free_index(u64 tid) { return LAUNCH_QUEUE_FULL; } -bool LaunchQueue::contains(u64 tid) { - return get_index(tid) != LAUNCH_QUEUE_FULL; +bool LaunchQueue::Contains(u64 tid) { + return GetIndex(tid) != LAUNCH_QUEUE_FULL; } -void LaunchQueue::clear() { +void LaunchQueue::Clear() { for (unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { g_launch_queue[i].tid = 0; } } -LaunchQueue::LaunchItem *LaunchQueue::get_item(u64 tid) { - int idx = get_index(tid); +LaunchQueue::LaunchItem *LaunchQueue::GetItem(u64 tid) { + int idx = GetIndex(tid); if (idx == LAUNCH_QUEUE_FULL) { return NULL; } diff --git a/stratosphere/loader/source/ldr_launch_queue.hpp b/stratosphere/loader/source/ldr_launch_queue.hpp index 74a2a03c9..234cd3be5 100644 --- a/stratosphere/loader/source/ldr_launch_queue.hpp +++ b/stratosphere/loader/source/ldr_launch_queue.hpp @@ -30,13 +30,13 @@ class LaunchQueue { char args[LAUNCH_QUEUE_ARG_SIZE_MAX]; }; - static LaunchQueue::LaunchItem *get_item(u64 tid); + static LaunchQueue::LaunchItem *GetItem(u64 tid); - static Result add(u64 tid, const char *args, u64 arg_size); - static Result add_item(const LaunchItem *item); - static Result add_copy(u64 tid_base, u64 new_tid); - static int get_index(u64 tid); - static int get_free_index(u64 tid); - static bool contains(u64 tid); - static void clear(); + static Result Add(u64 tid, const char *args, u64 arg_size); + static Result AddItem(const LaunchItem *item); + static Result AddCopy(u64 tid_base, u64 new_tid); + static int GetIndex(u64 tid); + static int GetFreeIndex(u64 tid); + static bool Contains(u64 tid); + static void Clear(); }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index a074977be..8db791cd0 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -92,24 +92,31 @@ void __appExit(void) { smExit(); } +struct LoaderServerOptions { + static constexpr size_t PointerBufferSize = 0x400; + static constexpr size_t MaxDomains = 0; + static constexpr size_t MaxDomainObjects = 0; +}; + int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); + + auto server_manager = new WaitableManager<LoaderServerOptions>(1); - /* TODO: What's a good timeout value to use here? */ - auto server_manager = std::make_unique<WaitableManager>(U64_MAX); - /* Add services to manager. */ - server_manager->add_waitable(new ServiceServer<ProcessManagerService>("ldr:pm", 1)); - server_manager->add_waitable(new ServiceServer<ShellService>("ldr:shel", 3)); - server_manager->add_waitable(new ServiceServer<DebugMonitorService>("ldr:dmnt", 2)); - if (!kernelAbove300()) { + server_manager->AddWaitable(new ServiceServer<ProcessManagerService>("ldr:pm", 1)); + server_manager->AddWaitable(new ServiceServer<ShellService>("ldr:shel", 3)); + server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("ldr:dmnt", 2)); + if (GetRuntimeFirmwareVersion() < FirmwareVersion_300) { /* On 1.0.0-2.3.0, Loader services ldr:ro instead of ro. */ - server_manager->add_waitable(new ServiceServer<RelocatableObjectsService>("ldr:ro", 0x20)); + server_manager->AddWaitable(new ServiceServer<RelocatableObjectsService>("ldr:ro", 0x20)); } - + /* Loop forever, servicing our services. */ - server_manager->process(); + server_manager->Process(); + + delete server_manager; return 0; } diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index a1be87408..3f50cf8a2 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -22,68 +22,45 @@ #include "ldr_content_management.hpp" #include "ldr_npdm.hpp" -Result ProcessManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - - switch ((ProcessManagerServiceCmd)cmd_id) { - case Pm_Cmd_CreateProcess: - rc = WrapIpcCommandImpl<&ProcessManagerService::create_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Pm_Cmd_GetProgramInfo: - rc = WrapIpcCommandImpl<&ProcessManagerService::get_program_info>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Pm_Cmd_RegisterTitle: - rc = WrapIpcCommandImpl<&ProcessManagerService::register_title>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Pm_Cmd_UnregisterTitle: - rc = WrapIpcCommandImpl<&ProcessManagerService::unregister_title>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - return rc; -} - -std::tuple<Result, MovedHandle> ProcessManagerService::create_process(u64 flags, u64 index, CopiedHandle reslimit_h) { +Result ProcessManagerService::CreateProcess(Out<MovedHandle> proc_h, u64 flags, u64 index, CopiedHandle reslimit_h) { Result rc; Registration::TidSid tid_sid; LaunchQueue::LaunchItem *launch_item; char nca_path[FS_MAX_PATH] = {0}; - Handle process_h = 0; fprintf(stderr, "CreateProcess(%016lx, %016lx, %08x);\n", flags, index, reslimit_h.handle); rc = Registration::GetRegisteredTidSid(index, &tid_sid); if (R_FAILED(rc)) { - return {rc, MovedHandle{process_h}}; + return rc; } if (tid_sid.storage_id != FsStorageId_None) { rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid); if (R_FAILED(rc)) { - return {rc, MovedHandle{process_h}}; + return rc; } } - launch_item = LaunchQueue::get_item(tid_sid.title_id); + launch_item = LaunchQueue::GetItem(tid_sid.title_id); - rc = ProcessCreation::CreateProcess(&process_h, index, nca_path, launch_item, flags, reslimit_h.handle); + rc = ProcessCreation::CreateProcess(proc_h.GetHandlePointer(), index, nca_path, launch_item, flags, reslimit_h.handle); if (R_SUCCEEDED(rc)) { ContentManagement::SetCreatedTitle(tid_sid.title_id); } - return {rc, MovedHandle{process_h}}; + return rc; } -std::tuple<Result> ProcessManagerService::get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info) { +Result ProcessManagerService::GetProgramInfo(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info) { Result rc; char nca_path[FS_MAX_PATH] = {0}; /* Zero output. */ std::fill(out_program_info.pointer, out_program_info.pointer + out_program_info.num_elements, (const ProcessManagerService::ProgramInfo){0}); - rc = populate_program_info_buffer(out_program_info.pointer, &tid_sid); + rc = PopulateProgramInfoBuffer(out_program_info.pointer, &tid_sid); if (R_FAILED(rc)) { return {rc}; @@ -100,31 +77,22 @@ std::tuple<Result> ProcessManagerService::get_program_info(Registration::TidSid return {rc}; } - rc = LaunchQueue::add_copy(tid_sid.title_id, out_program_info.pointer->title_id); + rc = LaunchQueue::AddCopy(tid_sid.title_id, out_program_info.pointer->title_id); } return {rc}; } -std::tuple<Result, u64> ProcessManagerService::register_title(Registration::TidSid tid_sid) { - u64 out_index = 0; - if (Registration::RegisterTidSid(&tid_sid, &out_index)) { - return {0, out_index}; - } else { - return {0xE09, out_index}; - } +Result ProcessManagerService::RegisterTitle(Out<u64> index, Registration::TidSid tid_sid) { + return Registration::RegisterTidSid(&tid_sid, index.GetPointer()) ? 0 : 0xE09; } -std::tuple<Result> ProcessManagerService::unregister_title(u64 index) { - if (Registration::UnregisterIndex(index)) { - return {0}; - } else { - return {0x1009}; - } +Result ProcessManagerService::UnregisterTitle(u64 index) { + return Registration::UnregisterIndex(index) ? 0 : 0x1009; } -Result ProcessManagerService::populate_program_info_buffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid) { +Result ProcessManagerService::PopulateProgramInfoBuffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid) { NpdmUtils::NpdmInfo info; Result rc; bool mounted_code = false; diff --git a/stratosphere/loader/source/ldr_process_manager.hpp b/stratosphere/loader/source/ldr_process_manager.hpp index c177a03b2..65c68b3e3 100644 --- a/stratosphere/loader/source/ldr_process_manager.hpp +++ b/stratosphere/loader/source/ldr_process_manager.hpp @@ -16,7 +16,7 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> #include "ldr_registration.hpp" #include "ldr_process_creation.hpp" @@ -42,26 +42,21 @@ class ProcessManagerService final : public IServiceObject { u8 ac_buffer[0x3E0]; }; - static_assert(sizeof(ProcessManagerService::ProgramInfo) == 0x400, "Incorrect ProgramInfo definition."); - - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override { - /* This service will never defer. */ - return 0; - } - - ProcessManagerService *clone() override { - return new ProcessManagerService(); - } - + static_assert(sizeof(ProcessManagerService::ProgramInfo) == 0x400, "Incorrect ProgramInfo definition."); private: /* Actual commands. */ - std::tuple<Result, MovedHandle> create_process(u64 flags, u64 index, CopiedHandle reslimit_h); - std::tuple<Result> get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info); - std::tuple<Result, u64> register_title(Registration::TidSid tid_sid); - std::tuple<Result> unregister_title(u64 index); + Result CreateProcess(Out<MovedHandle> proc_h, u64 flags, u64 index, CopiedHandle reslimit_h); + Result GetProgramInfo(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info); + Result RegisterTitle(Out<u64> index, Registration::TidSid tid_sid); + Result UnregisterTitle(u64 index); /* Utilities */ - Result populate_program_info_buffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid); + Result PopulateProgramInfoBuffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<Pm_Cmd_CreateProcess, &ProcessManagerService::CreateProcess>(), + MakeServiceCommandMeta<Pm_Cmd_GetProgramInfo, &ProcessManagerService::GetProgramInfo>(), + MakeServiceCommandMeta<Pm_Cmd_RegisterTitle, &ProcessManagerService::RegisterTitle>(), + MakeServiceCommandMeta<Pm_Cmd_UnregisterTitle, &ProcessManagerService::UnregisterTitle>(), + }; }; diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index 4529710f9..013476499 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -24,71 +24,34 @@ #include "ldr_map.hpp" #include "ldr_nro.hpp" -Result RelocatableObjectsService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - - switch ((RoServiceCmd)cmd_id) { - case Ro_Cmd_LoadNro: - rc = WrapIpcCommandImpl<&RelocatableObjectsService::load_nro>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Ro_Cmd_UnloadNro: - rc = WrapIpcCommandImpl<&RelocatableObjectsService::unload_nro>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Ro_Cmd_LoadNrr: - rc = WrapIpcCommandImpl<&RelocatableObjectsService::load_nrr>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Ro_Cmd_UnloadNrr: - rc = WrapIpcCommandImpl<&RelocatableObjectsService::unload_nrr>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Ro_Cmd_Initialize: - rc = WrapIpcCommandImpl<&RelocatableObjectsService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - - return rc; -} - - -std::tuple<Result, u64> RelocatableObjectsService::load_nro(PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) { - Result rc; - u64 out_address = 0; +Result RelocatableObjectsService::LoadNro(Out<u64> load_address, PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) { Registration::Process *target_proc = NULL; if (!this->has_initialized || this->process_id != pid_desc.pid) { - rc = 0xAE09; - goto LOAD_NRO_END; + return 0xAE09; } if (nro_address & 0xFFF) { - rc = 0xA209; - goto LOAD_NRO_END; + return 0xA209; } if (nro_address + nro_size <= nro_address || !nro_size || (nro_size & 0xFFF)) { - rc = 0xA409; - goto LOAD_NRO_END; + return 0xA409; } if (bss_size && bss_address + bss_size <= bss_address) { - rc = 0xA409; - goto LOAD_NRO_END; + return 0xA409; } /* Ensure no overflow for combined sizes. */ if (U64_MAX - nro_size < bss_size) { - rc = 0xA409; - goto LOAD_NRO_END; + return 0xA409; } target_proc = Registration::GetProcessByProcessId(pid_desc.pid); if (target_proc == NULL || (target_proc->owner_ro_service != NULL && (RelocatableObjectsService *)(target_proc->owner_ro_service) != this)) { - rc = 0xAC09; - goto LOAD_NRO_END; + return 0xAC09; } target_proc->owner_ro_service = this; - rc = NroUtils::LoadNro(target_proc, this->process_handle, nro_address, nro_size, bss_address, bss_size, &out_address); -LOAD_NRO_END: - return {rc, out_address}; + return NroUtils::LoadNro(target_proc, this->process_handle, nro_address, nro_size, bss_address, bss_size, load_address.GetPointer()); } -std::tuple<Result> RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, u64 nro_address) { +Result RelocatableObjectsService::UnloadNro(PidDescriptor pid_desc, u64 nro_address) { Registration::Process *target_proc = NULL; if (!this->has_initialized || this->process_id != pid_desc.pid) { return 0xAE09; @@ -106,37 +69,42 @@ std::tuple<Result> RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, return Registration::RemoveNroInfo(target_proc->index, this->process_handle, nro_address); } -std::tuple<Result> RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) { - Result rc; +Result RelocatableObjectsService::LoadNrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) { + Result rc = 0; Registration::Process *target_proc = NULL; MappedCodeMemory nrr_info = {0}; + ON_SCOPE_EXIT { + if (R_FAILED(rc) && nrr_info.IsActive()) { + nrr_info.Close(); + } + }; if (!this->has_initialized || this->process_id != pid_desc.pid) { rc = 0xAE09; - goto LOAD_NRR_END; + return rc; } if (nrr_address & 0xFFF) { rc = 0xA209; - goto LOAD_NRR_END; + return rc; } if (nrr_address + nrr_size <= nrr_address || !nrr_size || (nrr_size & 0xFFF)) { rc = 0xA409; - goto LOAD_NRR_END; + return rc; } target_proc = Registration::GetProcessByProcessId(pid_desc.pid); if (target_proc == NULL || (target_proc->owner_ro_service != NULL && (RelocatableObjectsService *)(target_proc->owner_ro_service) != this)) { rc = 0xAC09; - goto LOAD_NRR_END; + return rc; } target_proc->owner_ro_service = this; if (R_FAILED((rc = nrr_info.Open(this->process_handle, target_proc->is_64_bit_addspace, nrr_address, nrr_size)))) { - goto LOAD_NRR_END; + return rc; } if (R_FAILED((rc = nrr_info.Map()))) { - goto LOAD_NRR_END; + return rc; } rc = NroUtils::ValidateNrrHeader((NroUtils::NrrHeader *)nrr_info.mapped_address, nrr_size, target_proc->title_id); @@ -144,16 +112,10 @@ std::tuple<Result> RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u Registration::AddNrrInfo(target_proc->index, &nrr_info); } -LOAD_NRR_END: - if (R_FAILED(rc)) { - if (nrr_info.IsActive()) { - nrr_info.Close(); - } - } - return {rc}; + return rc; } -std::tuple<Result> RelocatableObjectsService::unload_nrr(PidDescriptor pid_desc, u64 nrr_address) { +Result RelocatableObjectsService::UnloadNrr(PidDescriptor pid_desc, u64 nrr_address) { Registration::Process *target_proc = NULL; if (!this->has_initialized || this->process_id != pid_desc.pid) { return 0xAE09; @@ -171,9 +133,8 @@ std::tuple<Result> RelocatableObjectsService::unload_nrr(PidDescriptor pid_desc, return Registration::RemoveNrrInfo(target_proc->index, nrr_address); } -std::tuple<Result> RelocatableObjectsService::initialize(PidDescriptor pid_desc, CopiedHandle process_h) { +Result RelocatableObjectsService::Initialize(PidDescriptor pid_desc, CopiedHandle process_h) { u64 handle_pid; - Result rc = 0xAE09; if (R_SUCCEEDED(svcGetProcessId(&handle_pid, process_h.handle)) && handle_pid == pid_desc.pid) { if (this->has_initialized) { svcCloseHandle(this->process_handle); @@ -181,7 +142,7 @@ std::tuple<Result> RelocatableObjectsService::initialize(PidDescriptor pid_desc, this->process_handle = process_h.handle; this->process_id = handle_pid; this->has_initialized = true; - rc = 0; + return 0; } - return {rc}; + return 0xAE09; } diff --git a/stratosphere/loader/source/ldr_ro_service.hpp b/stratosphere/loader/source/ldr_ro_service.hpp index 3e622587e..05bd9d058 100644 --- a/stratosphere/loader/source/ldr_ro_service.hpp +++ b/stratosphere/loader/source/ldr_ro_service.hpp @@ -17,7 +17,7 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> #include "ldr_registration.hpp" enum RoServiceCmd { @@ -33,27 +33,26 @@ class RelocatableObjectsService final : public IServiceObject { u64 process_id = U64_MAX; bool has_initialized = false; public: - ~RelocatableObjectsService() { + virtual ~RelocatableObjectsService() override { Registration::CloseRoService(this, this->process_handle); if (this->has_initialized) { svcCloseHandle(this->process_handle); } } - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override { - /* This service will never defer. */ - return 0; - } - - RelocatableObjectsService *clone() override { - return new RelocatableObjectsService(*this); - } private: /* Actual commands. */ - std::tuple<Result, u64> load_nro(PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size); - std::tuple<Result> unload_nro(PidDescriptor pid_desc, u64 nro_address); - std::tuple<Result> load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size); - std::tuple<Result> unload_nrr(PidDescriptor pid_desc, u64 nrr_address); - std::tuple<Result> initialize(PidDescriptor pid_desc, CopiedHandle process_h); + Result LoadNro(Out<u64> load_address, PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size); + Result UnloadNro(PidDescriptor pid_desc, u64 nro_address); + Result LoadNrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size); + Result UnloadNrr(PidDescriptor pid_desc, u64 nrr_address); + Result Initialize(PidDescriptor pid_desc, CopiedHandle process_h); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<Ro_Cmd_LoadNro, &RelocatableObjectsService::LoadNro>(), + MakeServiceCommandMeta<Ro_Cmd_UnloadNro, &RelocatableObjectsService::UnloadNro>(), + MakeServiceCommandMeta<Ro_Cmd_LoadNrr, &RelocatableObjectsService::LoadNrr>(), + MakeServiceCommandMeta<Ro_Cmd_UnloadNrr, &RelocatableObjectsService::UnloadNrr>(), + MakeServiceCommandMeta<Ro_Cmd_Initialize, &RelocatableObjectsService::Initialize>(), + }; }; diff --git a/stratosphere/loader/source/ldr_shell.cpp b/stratosphere/loader/source/ldr_shell.cpp index 75b884a08..1a7c913eb 100644 --- a/stratosphere/loader/source/ldr_shell.cpp +++ b/stratosphere/loader/source/ldr_shell.cpp @@ -20,49 +20,28 @@ #include "ldr_launch_queue.hpp" #include "ldr_content_management.hpp" -Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - - Result rc = 0xF601; - - switch ((ShellServiceCmd)cmd_id) { - case Shell_Cmd_AddTitleToLaunchQueue: - rc = WrapIpcCommandImpl<&ShellService::add_title_to_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_ClearLaunchQueue: - rc = WrapIpcCommandImpl<&ShellService::clear_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - case Shell_Cmd_AtmosphereSetExternalContentSource: - rc = WrapIpcCommandImpl<&ShellService::set_external_content_source>(this, r, out_c, pointer_buffer, pointer_buffer_size); - break; - default: - break; - } - return rc; -} - -std::tuple<Result> ShellService::add_title_to_launch_queue(u64 args_size, u64 tid, InPointer<char> args) { +Result ShellService::AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args) { fprintf(stderr, "Add to launch queue: %p, %zX\n", args.pointer, std::min(args_size, args.num_elements)); - return {LaunchQueue::add(tid, args.pointer, std::min(args_size, args.num_elements))}; + return LaunchQueue::Add(tid, args.pointer, std::min(args_size, args.num_elements)); } -std::tuple<Result> ShellService::clear_launch_queue(u64 dat) { - fprintf(stderr, "Clear launch queue: %lx\n", dat); - LaunchQueue::clear(); - return {0}; +void ShellService::ClearLaunchQueue() { + LaunchQueue::Clear(); } /* SetExternalContentSource extension */ -std::tuple<Result, MovedHandle> ShellService::set_external_content_source(u64 tid) { +Result ShellService::SetExternalContentSource(Out<MovedHandle> out, u64 tid) { Handle server_h; Handle client_h; Result rc; if (R_FAILED(rc = svcCreateSession(&server_h, &client_h, 0, 0))) { - return {rc, 0}; + return rc; } Service service; serviceCreate(&service, client_h); ContentManagement::SetExternalContentSource(tid, FsFileSystem {service}); - return {0, server_h}; + out.SetValue(server_h); + return 0; } diff --git a/stratosphere/loader/source/ldr_shell.hpp b/stratosphere/loader/source/ldr_shell.hpp index 7b1c153d2..1094a9e08 100644 --- a/stratosphere/loader/source/ldr_shell.hpp +++ b/stratosphere/loader/source/ldr_shell.hpp @@ -16,7 +16,7 @@ #pragma once #include <switch.h> -#include <stratosphere/iserviceobject.hpp> +#include <stratosphere.hpp> enum ShellServiceCmd { Shell_Cmd_AddTitleToLaunchQueue = 0, @@ -26,22 +26,17 @@ enum ShellServiceCmd { }; class ShellService final : public IServiceObject { - public: - Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override; - Result handle_deferred() override { - /* This service will never defer. */ - return 0; - } - - ShellService *clone() override { - return new ShellService(); - } - private: /* Actual commands. */ - std::tuple<Result> add_title_to_launch_queue(u64 args_size, u64 tid, InPointer<char> args); - std::tuple<Result> clear_launch_queue(u64 dat); - + Result AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args); + void ClearLaunchQueue(); + /* Atmosphere commands. */ - std::tuple<Result, MovedHandle> set_external_content_source(u64 tid); + Result SetExternalContentSource(Out<MovedHandle> out, u64 tid); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<Shell_Cmd_AddTitleToLaunchQueue, &ShellService::AddTitleToLaunchQueue>(), + MakeServiceCommandMeta<Shell_Cmd_ClearLaunchQueue, &ShellService::ClearLaunchQueue>(), + MakeServiceCommandMeta<Shell_Cmd_AtmosphereSetExternalContentSource, &ShellService::SetExternalContentSource>(), + }; }; From 2f7224edcefb87f2cef727ae74270e4ce5ed2f9a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 29 Oct 2018 23:41:18 -0700 Subject: [PATCH 153/489] fs.mitm: increase thread count back to 5. --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 28b47fbfb..1c12d9db1 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -102,7 +102,7 @@ int main(int argc, char **argv) } /* TODO: What's a good timeout value to use here? */ - auto server_manager = new FsMitmManager(1); + auto server_manager = new FsMitmManager(5); /* Create fsp-srv mitm. */ AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); From 6ef34d80a054d6e07375dac078380f336f080d8c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 30 Oct 2018 06:29:30 -0700 Subject: [PATCH 154/489] libstrat: automatically detect+format rawdata structs correctly. --- .../fs_mitm/source/fsmitm_service.cpp | 2 +- .../fs_mitm/source/fsmitm_service.hpp | 2 +- .../stratosphere/ipc/ipc_serialization.hpp | 126 ++++++++++++------ .../loader/source/ldr_debug_monitor.cpp | 6 +- .../loader/source/ldr_debug_monitor.hpp | 2 +- .../loader/source/ldr_process_manager.cpp | 6 +- .../loader/source/ldr_process_manager.hpp | 4 +- stratosphere/loader/source/ldr_shell.cpp | 6 +- stratosphere/loader/source/ldr_shell.hpp | 2 +- stratosphere/pm/source/pm_boot_mode.cpp | 2 +- stratosphere/pm/source/pm_boot_mode.hpp | 2 +- stratosphere/pm/source/pm_shell.cpp | 2 +- stratosphere/pm/source/pm_shell.hpp | 2 +- stratosphere/sm/source/sm_types.hpp | 22 +++ stratosphere/sm/source/sm_user_service.cpp | 26 ++-- stratosphere/sm/source/sm_user_service.hpp | 11 +- 16 files changed, 147 insertions(+), 76 deletions(-) create mode 100644 stratosphere/sm/source/sm_types.hpp diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 75e575067..a9f1e30a5 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -96,7 +96,7 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora } /* Add redirection for System Data Archives to the SD card. */ -Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out_storage, u64 sid, u64 data_id) { +Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out_storage, u64 data_id, u8 sid) { FsStorageId storage_id = (FsStorageId)sid; FsStorage data_storage; FsFile data_file; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index c1bf4e9a8..75dc7b426 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -47,7 +47,7 @@ class FsMitmService : public IMitmServiceObject { protected: /* Overridden commands. */ Result OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out); - Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 storage_id, u64 data_id); + Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 data_id, u8 storage_id); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByCurrentProcess, &FsMitmService::OpenDataStorageByCurrentProcess>(), diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp index 93c894af3..2de8f6dfb 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp @@ -174,19 +174,83 @@ struct RawSizeElementAdder { }; template<typename Ts> -struct GetRawDataSize; +struct RawDataHelper; template<typename... Ts> -struct GetRawDataSize<std::tuple<Ts...>> { - static constexpr size_t Size() { - if constexpr (sizeof...(Ts) == 0) { - return 0; - } else { - size_t s = 0; - size_t ends[] = { RawSizeElementAdder<Ts>::GetUpdateElementSize(s)... }; - return (ends[sizeof...(Ts)-1] + 3) & ~3; +struct RawDataHelper<std::tuple<Ts...>> { + /* https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,2604 */ + static constexpr void QuickSort(std::array<size_t, sizeof...(Ts)> &map, std::array<size_t, sizeof...(Ts)> &values, int left, int right) { + do { + int i = left; + int j = right; + int x = map[i + ((j - i) >> 1)]; + do { + while (i < static_cast<int>(sizeof...(Ts)) && values[x] > values[map[i]]) i++; + while (j >= 0 && values[x] < values[map[j]]) j--; + if (i > j) break; + if (i < j) { + const size_t temp = map[i]; + map[i] = map[j]; + map[j] = temp; + } + i++; + j--; + } while (i <= j); + if (j - left <= right - i) { + if (left < j) QuickSort(map, values, left, j); + left = i; + } else { + if (i < right) QuickSort(map, values, i, right); + right = j; + } + } while (left < right); + } + + static constexpr void StableSort(std::array<size_t, sizeof...(Ts)> &map, std::array<size_t, sizeof...(Ts)> &values) { + /* First, quicksort a copy of the map. */ + std::array<size_t, sizeof...(Ts)> map_unstable(map); + QuickSort(map_unstable, values, 0, sizeof...(Ts)-1); + + /* Now, create stable sorted map from unstably quicksorted indices (via repeated insertion sort on element runs). */ + for (size_t i = 0; i < sizeof...(Ts); i++) { + map[i] = map_unstable[i]; + for (ssize_t j = i-1; j >= 0 && values[map[j]] == values[map[j+1]] && map[j] > map[j+1]; j--) { + const size_t temp = map[j]; + map[j] = map[j+1]; + map[j+1] = temp; + } } } + + static constexpr std::array<size_t, sizeof...(Ts)+1> GetOffsets() { + std::array<size_t, sizeof...(Ts)+1> offsets = {}; + offsets[0] = 0; + if constexpr (sizeof...(Ts) > 0) { + /* Get size, alignment for each type. */ + std::array<size_t, sizeof...(Ts)> sizes = { RawDataHelper<Ts>::size... }; + std::array<size_t, sizeof...(Ts)> aligns = { RawDataHelper<Ts>::align... }; + + /* We want to sort...by alignment. */ + std::array<size_t, sizeof...(Ts)> map = {}; + for (size_t i = 0; i < sizeof...(Ts); i++) { map[i] = i; } + StableSort(map, aligns); + + /* Iterate over sorted types. */ + size_t cur_offset = 0; + for (size_t i = 0; i < sizeof...(Ts); i++) { + const size_t align = aligns[map[i]]; + if (cur_offset % align != 0) { + cur_offset += align - (cur_offset % align); + } + offsets[map[i]] = cur_offset; + cur_offset += sizes[map[i]]; + } + offsets[sizeof...(Ts)] = cur_offset; + } + return offsets; + } + + static constexpr std::array<size_t, sizeof...(Ts)+1> offsets = GetOffsets(); }; template <typename _Args, typename _ReturnType> @@ -236,10 +300,12 @@ struct CommandMetaInfo<std::tuple<_Args...>, _ReturnType> { static_assert(NumInHandles <= 8, "Methods can take in <= 8 Handles!"); static_assert(NumOutHandles + NumOutSessions <= 8, "Methods can only return <= 8 Handles+Sessions!"); - static constexpr size_t InRawArgSize = GetRawDataSize<InDatas>::Size(); + static constexpr std::array<size_t, NumInDatas+1> InDataOffsets = RawDataHelper<InDatas>::offsets; + static constexpr size_t InRawArgSize = InDataOffsets[NumInDatas]; static constexpr size_t InRawArgSizeWithOutPointers = ((InRawArgSize + NumClientSizeOutPointers * sizeof(u16)) + 3) & ~3; - static constexpr size_t OutRawArgSize = GetRawDataSize<OutDatas>::Size(); + static constexpr std::array<size_t, NumOutDatas+1> OutDataOffsets = RawDataHelper<OutDatas>::offsets; + static constexpr size_t OutRawArgSize = OutDataOffsets[NumOutDatas]; }; @@ -335,10 +401,11 @@ struct Validator { /* ================================================================================= */ /* Decoder. */ +template<typename MetaInfo> struct Decoder { template<typename T> - static constexpr T DecodeCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_rd_offset, size_t& out_rd_offset, size_t& pb_offset, size_t& c_sz_offset) { + static constexpr T DecodeCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_data_index, size_t& out_data_index, size_t& pb_offset, size_t& c_sz_offset) { constexpr ArgType argT = GetArgType<T>(); if constexpr (argT == ArgType::InBuffer) { const T& value = T(ctx->request.Buffers[a_index], ctx->request.BufferSizes[a_index], ctx->request.BufferTypes[a_index]); @@ -357,36 +424,18 @@ struct Decoder { } else if constexpr (argT == ArgType::OutHandle) { return T(&ctx->out_handles[out_h_index++]); } else if constexpr (argT == ArgType::PidDesc) { - constexpr size_t t_align = RawDataHelper<T>::align; - constexpr size_t t_size = RawDataHelper<T>::size; - if (in_rd_offset % t_align) { - in_rd_offset += (t_align - (in_rd_offset % t_align)); - } - uintptr_t ptr = ((uintptr_t)ctx->request.Raw + 0x10 + in_rd_offset); - in_rd_offset += t_size; + uintptr_t ptr = ((uintptr_t)ctx->request.Raw + 0x10 + MetaInfo::InDataOffsets[in_data_index++]); *(u64 *)ptr = ctx->request.Pid; return T(ctx->request.Pid); } else if constexpr (argT == ArgType::InData) { - constexpr size_t t_align = RawDataHelper<T>::align; - constexpr size_t t_size = RawDataHelper<T>::size; - if (in_rd_offset % t_align) { - in_rd_offset += (t_align - (in_rd_offset % t_align)); - } - uintptr_t ptr = ((uintptr_t)ctx->request.Raw + 0x10 + in_rd_offset); - in_rd_offset += t_size; + uintptr_t ptr = ((uintptr_t)ctx->request.Raw + 0x10 + MetaInfo::InDataOffsets[in_data_index++]); if constexpr (std::is_same_v<bool, T>) { return *((u8 *)ptr) & 1; } else { return *((T *)ptr); } } else if constexpr (argT == ArgType::OutData) { - constexpr size_t t_align = RawDataHelper<T>::align; - constexpr size_t t_size = RawDataHelper<T>::size; - if (out_rd_offset % t_align) { - out_rd_offset += (t_align - (out_rd_offset % t_align)); - } - uintptr_t ptr = ((uintptr_t)ctx->out_data + out_rd_offset); - out_rd_offset += t_size; + uintptr_t ptr = ((uintptr_t)ctx->out_data + MetaInfo::OutDataOffsets[out_data_index++]); return T(reinterpret_cast<typename OutHelper<T>::type *>(ptr)); } else if constexpr (argT == ArgType::OutPointerClientSize || argT == ArgType::OutPointerServerSize) { u16 sz; @@ -418,21 +467,20 @@ struct Decoder { template <typename ...Ts> struct DecodeTuple<std::tuple<Ts...>> { - static constexpr std::tuple<Ts...> GetArgs(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_rd_offset, size_t& out_rd_offset, size_t& pb_offset, size_t& c_sz_offset) { + static constexpr std::tuple<Ts...> GetArgs(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_data_index, size_t& out_data_index, size_t& pb_offset, size_t& c_sz_offset) { return std::tuple<Ts... > { - DecodeCommandArgument<Ts>(ctx, a_index, b_index, x_index, c_index, in_h_index, out_h_index, out_obj_index, in_rd_offset, out_rd_offset, pb_offset, c_sz_offset) + DecodeCommandArgument<Ts>(ctx, a_index, b_index, x_index, c_index, in_h_index, out_h_index, out_obj_index, in_data_index, out_data_index, pb_offset, c_sz_offset) ... }; } }; - template<typename MetaInfo> static constexpr typename MetaInfo::Args Decode(IpcResponseContext *ctx) { size_t a_index = 0, b_index = MetaInfo::NumInBuffers, x_index = 0, c_index = 0, in_h_index = 0, out_h_index = 0, out_obj_index = 0; - size_t in_rd_offset = 0x0, out_rd_offset = 0, pb_offset = 0; + size_t in_data_index = 0x0, out_data_index = 0, pb_offset = 0; size_t c_sz_offset = MetaInfo::InRawArgSize + (0x10 - ((uintptr_t)ctx->request.Raw - (uintptr_t)ctx->request.RawWithoutPadding)); - return DecodeTuple<typename MetaInfo::Args>::GetArgs(ctx, a_index, b_index, x_index, c_index, in_h_index, out_h_index, out_obj_index, in_rd_offset, out_rd_offset, pb_offset, c_sz_offset); + return DecodeTuple<typename MetaInfo::Args>::GetArgs(ctx, a_index, b_index, x_index, c_index, in_h_index, out_h_index, out_obj_index, in_data_index, out_data_index, pb_offset, c_sz_offset); } }; @@ -594,7 +642,7 @@ constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { }; if (R_SUCCEEDED(rc)) { - auto args = Decoder::Decode<CommandMetaData>(ctx); + auto args = Decoder<CommandMetaData>::Decode(ctx); if constexpr (CommandMetaData::ReturnsResult) { rc = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args); diff --git a/stratosphere/loader/source/ldr_debug_monitor.cpp b/stratosphere/loader/source/ldr_debug_monitor.cpp index 01fd0497b..d7dd77489 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.cpp +++ b/stratosphere/loader/source/ldr_debug_monitor.cpp @@ -22,9 +22,9 @@ #include "ldr_launch_queue.hpp" #include "ldr_registration.hpp" -Result DebugMonitorService::AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args) { - fprintf(stderr, "Add to launch queue: %p, %zX\n", args.pointer, std::min(args_size, args.num_elements)); - return LaunchQueue::Add(tid, args.pointer, std::min(args_size, args.num_elements)); +Result DebugMonitorService::AddTitleToLaunchQueue(u64 tid, InPointer<char> args, u32 args_size) { + if (args.num_elements < args_size) args_size = args.num_elements; + return LaunchQueue::Add(tid, args.pointer, args_size); } void DebugMonitorService::ClearLaunchQueue() { diff --git a/stratosphere/loader/source/ldr_debug_monitor.hpp b/stratosphere/loader/source/ldr_debug_monitor.hpp index 167b2872f..fa466706d 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.hpp +++ b/stratosphere/loader/source/ldr_debug_monitor.hpp @@ -29,7 +29,7 @@ enum DebugMonitorServiceCmd { class DebugMonitorService final : public IServiceObject { private: /* Actual commands. */ - Result AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args); + Result AddTitleToLaunchQueue(u64 tid, InPointer<char> args, u32 args_size); void ClearLaunchQueue(); Result GetNsoInfo(Out<u32> count, OutPointerWithClientSize<Registration::NsoInfo> out, u64 pid); public: diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index 3f50cf8a2..b1cae6ac4 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -22,13 +22,13 @@ #include "ldr_content_management.hpp" #include "ldr_npdm.hpp" -Result ProcessManagerService::CreateProcess(Out<MovedHandle> proc_h, u64 flags, u64 index, CopiedHandle reslimit_h) { +Result ProcessManagerService::CreateProcess(Out<MovedHandle> proc_h, u64 index, u32 flags, CopiedHandle reslimit_h) { Result rc; Registration::TidSid tid_sid; LaunchQueue::LaunchItem *launch_item; char nca_path[FS_MAX_PATH] = {0}; - fprintf(stderr, "CreateProcess(%016lx, %016lx, %08x);\n", flags, index, reslimit_h.handle); + fprintf(stderr, "CreateProcess(%016lx, %08x, %08x);\n", index, flags, reslimit_h.handle); rc = Registration::GetRegisteredTidSid(index, &tid_sid); if (R_FAILED(rc)) { @@ -54,7 +54,7 @@ Result ProcessManagerService::CreateProcess(Out<MovedHandle> proc_h, u64 flags, return rc; } -Result ProcessManagerService::GetProgramInfo(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info) { +Result ProcessManagerService::GetProgramInfo(OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info, Registration::TidSid tid_sid) { Result rc; char nca_path[FS_MAX_PATH] = {0}; /* Zero output. */ diff --git a/stratosphere/loader/source/ldr_process_manager.hpp b/stratosphere/loader/source/ldr_process_manager.hpp index 65c68b3e3..7cb4bc85e 100644 --- a/stratosphere/loader/source/ldr_process_manager.hpp +++ b/stratosphere/loader/source/ldr_process_manager.hpp @@ -45,8 +45,8 @@ class ProcessManagerService final : public IServiceObject { static_assert(sizeof(ProcessManagerService::ProgramInfo) == 0x400, "Incorrect ProgramInfo definition."); private: /* Actual commands. */ - Result CreateProcess(Out<MovedHandle> proc_h, u64 flags, u64 index, CopiedHandle reslimit_h); - Result GetProgramInfo(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info); + Result CreateProcess(Out<MovedHandle> proc_h, u64 index, u32 flags, CopiedHandle reslimit_h); + Result GetProgramInfo(OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info, Registration::TidSid tid_sid); Result RegisterTitle(Out<u64> index, Registration::TidSid tid_sid); Result UnregisterTitle(u64 index); diff --git a/stratosphere/loader/source/ldr_shell.cpp b/stratosphere/loader/source/ldr_shell.cpp index 1a7c913eb..4574c5af4 100644 --- a/stratosphere/loader/source/ldr_shell.cpp +++ b/stratosphere/loader/source/ldr_shell.cpp @@ -20,9 +20,9 @@ #include "ldr_launch_queue.hpp" #include "ldr_content_management.hpp" -Result ShellService::AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args) { - fprintf(stderr, "Add to launch queue: %p, %zX\n", args.pointer, std::min(args_size, args.num_elements)); - return LaunchQueue::Add(tid, args.pointer, std::min(args_size, args.num_elements)); +Result ShellService::AddTitleToLaunchQueue(u64 tid, InPointer<char> args, u32 args_size) { + if (args.num_elements < args_size) args_size = args.num_elements; + return LaunchQueue::Add(tid, args.pointer, args_size); } void ShellService::ClearLaunchQueue() { diff --git a/stratosphere/loader/source/ldr_shell.hpp b/stratosphere/loader/source/ldr_shell.hpp index 1094a9e08..69d6f2107 100644 --- a/stratosphere/loader/source/ldr_shell.hpp +++ b/stratosphere/loader/source/ldr_shell.hpp @@ -28,7 +28,7 @@ enum ShellServiceCmd { class ShellService final : public IServiceObject { private: /* Actual commands. */ - Result AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args); + Result AddTitleToLaunchQueue(u64 tid, InPointer<char> args, u32 args_size); void ClearLaunchQueue(); /* Atmosphere commands. */ diff --git a/stratosphere/pm/source/pm_boot_mode.cpp b/stratosphere/pm/source/pm_boot_mode.cpp index 7268660cc..b8158acf9 100644 --- a/stratosphere/pm/source/pm_boot_mode.cpp +++ b/stratosphere/pm/source/pm_boot_mode.cpp @@ -20,7 +20,7 @@ static bool g_is_maintenance_boot = false; -void BootModeService::GetBootMode(Out<bool> out) { +void BootModeService::GetBootMode(Out<u32> out) { out.SetValue(g_is_maintenance_boot); } diff --git a/stratosphere/pm/source/pm_boot_mode.hpp b/stratosphere/pm/source/pm_boot_mode.hpp index 96572797f..1aadf8c42 100644 --- a/stratosphere/pm/source/pm_boot_mode.hpp +++ b/stratosphere/pm/source/pm_boot_mode.hpp @@ -26,7 +26,7 @@ enum BootModeCmd { class BootModeService final : public IServiceObject { private: /* Actual commands. */ - void GetBootMode(Out<bool> out); + void GetBootMode(Out<u32> out); void SetMaintenanceBoot(); public: DEFINE_SERVICE_DISPATCH_TABLE { diff --git a/stratosphere/pm/source/pm_shell.cpp b/stratosphere/pm/source/pm_shell.cpp index aa03b0c68..a1e6dbd12 100644 --- a/stratosphere/pm/source/pm_shell.cpp +++ b/stratosphere/pm/source/pm_shell.cpp @@ -23,7 +23,7 @@ static bool g_has_boot_finished = false; -Result ShellService::LaunchProcess(Out<u64> pid, u64 launch_flags, Registration::TidSid tid_sid) { +Result ShellService::LaunchProcess(Out<u64> pid, Registration::TidSid tid_sid, u32 launch_flags) { return Registration::LaunchProcessByTidSid(tid_sid, launch_flags, pid.GetPointer()); } diff --git a/stratosphere/pm/source/pm_shell.hpp b/stratosphere/pm/source/pm_shell.hpp index b488107fd..cd707a510 100644 --- a/stratosphere/pm/source/pm_shell.hpp +++ b/stratosphere/pm/source/pm_shell.hpp @@ -49,7 +49,7 @@ enum ShellCmd_5X { class ShellService final : public IServiceObject { private: /* Actual commands. */ - Result LaunchProcess(Out<u64> pid, u64 launch_flags, Registration::TidSid tid_sid); + Result LaunchProcess(Out<u64> pid, Registration::TidSid tid_sid, u32 launch_flags); Result TerminateProcessId(u64 pid); Result TerminateTitleId(u64 tid); void GetProcessWaitEvent(Out<CopiedHandle> event); diff --git a/stratosphere/sm/source/sm_types.hpp b/stratosphere/sm/source/sm_types.hpp new file mode 100644 index 000000000..6ac9bce92 --- /dev/null +++ b/stratosphere/sm/source/sm_types.hpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +struct SmServiceName { + char name[sizeof(u64)]; +}; + +static_assert(__alignof__(SmServiceName) == 1, "SmServiceName definition!"); \ No newline at end of file diff --git a/stratosphere/sm/source/sm_user_service.cpp b/stratosphere/sm/source/sm_user_service.cpp index 40079ec15..138ceac8c 100644 --- a/stratosphere/sm/source/sm_user_service.cpp +++ b/stratosphere/sm/source/sm_user_service.cpp @@ -25,17 +25,17 @@ Result UserService::Initialize(PidDescriptor pid) { return 0; } -Result UserService::GetService(Out<MovedHandle> out_h, u64 service) { +Result UserService::GetService(Out<MovedHandle> out_h, SmServiceName service) { Handle session_h = 0; Result rc = 0x415; #ifdef SM_ENABLE_SMHAX if (!this->has_initialized) { - rc = Registration::GetServiceForPid(Registration::GetInitialProcessId(), service, &session_h); + rc = Registration::GetServiceForPid(Registration::GetInitialProcessId(), smEncodeName(service.name), &session_h); } #endif if (this->has_initialized) { - rc = Registration::GetServiceForPid(this->pid, service, &session_h); + rc = Registration::GetServiceForPid(this->pid, smEncodeName(service.name), &session_h); } if (R_SUCCEEDED(rc)) { @@ -44,16 +44,16 @@ Result UserService::GetService(Out<MovedHandle> out_h, u64 service) { return rc; } -Result UserService::RegisterService(Out<MovedHandle> out_h, u64 service, u8 is_light, u32 max_sessions) { +Result UserService::RegisterService(Out<MovedHandle> out_h, SmServiceName service, u32 max_sessions, bool is_light) { Handle service_h = 0; Result rc = 0x415; #ifdef SM_ENABLE_SMHAX if (!this->has_initialized) { - rc = Registration::RegisterServiceForPid(Registration::GetInitialProcessId(), service, max_sessions, (is_light & 1) != 0, &service_h); + rc = Registration::RegisterServiceForPid(Registration::GetInitialProcessId(), smEncodeName(service.name), max_sessions, (is_light & 1) != 0, &service_h); } #endif if (this->has_initialized) { - rc = Registration::RegisterServiceForPid(this->pid, service, max_sessions, (is_light & 1) != 0, &service_h); + rc = Registration::RegisterServiceForPid(this->pid, smEncodeName(service.name), max_sessions, (is_light & 1) != 0, &service_h); } if (R_SUCCEEDED(rc)) { @@ -62,25 +62,25 @@ Result UserService::RegisterService(Out<MovedHandle> out_h, u64 service, u8 is_l return rc; } -Result UserService::UnregisterService(u64 service) { +Result UserService::UnregisterService(SmServiceName service) { Result rc = 0x415; #ifdef SM_ENABLE_SMHAX if (!this->has_initialized) { - rc = Registration::UnregisterServiceForPid(Registration::GetInitialProcessId(), service); + rc = Registration::UnregisterServiceForPid(Registration::GetInitialProcessId(), smEncodeName(service.name)); } #endif if (this->has_initialized) { - rc = Registration::UnregisterServiceForPid(this->pid, service); + rc = Registration::UnregisterServiceForPid(this->pid, smEncodeName(service.name)); } return rc; } -Result UserService::AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, u64 service) { +Result UserService::AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, SmServiceName service) { Handle service_h = 0; Handle query_h = 0; Result rc = 0x415; if (this->has_initialized) { - rc = Registration::InstallMitmForPid(this->pid, service, &service_h, &query_h); + rc = Registration::InstallMitmForPid(this->pid, smEncodeName(service.name), &service_h, &query_h); } if (R_SUCCEEDED(rc)) { @@ -90,10 +90,10 @@ Result UserService::AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandl return rc; } -Result UserService::AtmosphereUninstallMitm(u64 service) { +Result UserService::AtmosphereUninstallMitm(SmServiceName service) { Result rc = 0x415; if (this->has_initialized) { - rc = Registration::UninstallMitmForPid(this->pid, service); + rc = Registration::UninstallMitmForPid(this->pid, smEncodeName(service.name)); } return rc; } diff --git a/stratosphere/sm/source/sm_user_service.hpp b/stratosphere/sm/source/sm_user_service.hpp index 206b4f771..f99f65bc2 100644 --- a/stratosphere/sm/source/sm_user_service.hpp +++ b/stratosphere/sm/source/sm_user_service.hpp @@ -17,6 +17,7 @@ #pragma once #include <switch.h> #include <stratosphere.hpp> +#include "sm_types.hpp" enum UserServiceCmd { User_Cmd_Initialize = 0, @@ -36,13 +37,13 @@ class UserService final : public IServiceObject { /* Actual commands. */ virtual Result Initialize(PidDescriptor pid); - virtual Result GetService(Out<MovedHandle> out_h, u64 service); - virtual Result RegisterService(Out<MovedHandle> out_h, u64 service, u8 is_light, u32 max_sessions); - virtual Result UnregisterService(u64 service); + virtual Result GetService(Out<MovedHandle> out_h, SmServiceName service); + virtual Result RegisterService(Out<MovedHandle> out_h, SmServiceName service, u32 max_sessions, bool is_light); + virtual Result UnregisterService(SmServiceName service); /* Atmosphere commands. */ - virtual Result AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, u64 service); - virtual Result AtmosphereUninstallMitm(u64 service); + virtual Result AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, SmServiceName service); + virtual Result AtmosphereUninstallMitm(SmServiceName service); virtual Result AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid); public: DEFINE_SERVICE_DISPATCH_TABLE { From 6336089b63962f3c2f519fc68cb0dfc28246290e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 30 Oct 2018 06:34:10 -0700 Subject: [PATCH 155/489] libstrat: remove unused struct in serializer --- .../stratosphere/ipc/ipc_serialization.hpp | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp index 2de8f6dfb..41a669547 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp @@ -160,24 +160,11 @@ struct RawDataHelper<Out<T>> { static constexpr size_t size = sizeof(T); }; -template<typename T> -struct RawSizeElementAdder { - static constexpr size_t GetUpdateElementSize(size_t &size) { - constexpr size_t t_align = RawDataHelper<T>::align; - constexpr size_t t_size = RawDataHelper<T>::size; - if (size % t_align == 0) { - size += t_align - (size % t_align); - } - size += t_size; - return size; - } -}; - template<typename Ts> -struct RawDataHelper; +struct RawDataComputer; template<typename... Ts> -struct RawDataHelper<std::tuple<Ts...>> { +struct RawDataComputer<std::tuple<Ts...>> { /* https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,2604 */ static constexpr void QuickSort(std::array<size_t, sizeof...(Ts)> &map, std::array<size_t, sizeof...(Ts)> &values, int left, int right) { do { @@ -300,11 +287,11 @@ struct CommandMetaInfo<std::tuple<_Args...>, _ReturnType> { static_assert(NumInHandles <= 8, "Methods can take in <= 8 Handles!"); static_assert(NumOutHandles + NumOutSessions <= 8, "Methods can only return <= 8 Handles+Sessions!"); - static constexpr std::array<size_t, NumInDatas+1> InDataOffsets = RawDataHelper<InDatas>::offsets; + static constexpr std::array<size_t, NumInDatas+1> InDataOffsets = RawDataComputer<InDatas>::offsets; static constexpr size_t InRawArgSize = InDataOffsets[NumInDatas]; static constexpr size_t InRawArgSizeWithOutPointers = ((InRawArgSize + NumClientSizeOutPointers * sizeof(u16)) + 3) & ~3; - static constexpr std::array<size_t, NumOutDatas+1> OutDataOffsets = RawDataHelper<OutDatas>::offsets; + static constexpr std::array<size_t, NumOutDatas+1> OutDataOffsets = RawDataComputer<OutDatas>::offsets; static constexpr size_t OutRawArgSize = OutDataOffsets[NumOutDatas]; }; From 7309c7f358ab47a2d2d479227da8d4743bc40489 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 30 Oct 2018 11:25:21 -0700 Subject: [PATCH 156/489] atmosphere: improve makefile dependencies --- Makefile | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 51df7192b..c2a88fd4e 100644 --- a/Makefile +++ b/Makefile @@ -4,18 +4,25 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) AMSREV := $(AMSREV)-dirty endif -all: fusee creport -fusee: - $(MAKE) -C $@ all +all: fusee stratosphere exosphere thermosphere -creport: - $(MAKE) -C stratosphere/creport all +thermosphere: + $(MAKE) -C thermosphere all + +exosphere: thermosphere + $(MAKE) -C exosphere all + +stratosphere: exosphere + $(MAKE) -C stratosphere all + +fusee: exosphere stratosphere + $(MAKE) -C $@ all clean: $(MAKE) -C fusee clean rm -rf out -dist: fusee creport +dist: all $(eval MAJORVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MAJOR\b' common/include/atmosphere/version.h \ | tr -s [:blank:] \ | cut -d' ' -f3)) From 44175058f676ce16c0de93af4d32d6bd4a423f17 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 30 Oct 2018 12:23:21 -0700 Subject: [PATCH 157/489] libstrat: mark ServiceObjectHolder functions const --- .../stratosphere/ipc/ipc_service_object.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp index c2189920d..8803da33f 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp @@ -72,7 +72,7 @@ class ServiceObjectHolder { explicit ServiceObjectHolder(std::shared_ptr<ServiceImpl>&& s) : srv(std::move(s)), dispatch_table(DispatchTable<ServiceImpl>()), entry_count(DispatchTableEntryCount<ServiceImpl>()) { } template <typename ServiceImpl> - ServiceImpl *GetServiceObject() { + ServiceImpl *GetServiceObject() const { if (GetServiceId() == ServiceObjectId<ServiceImpl>()) { return static_cast<ServiceImpl *>(this->srv.get()); } @@ -80,19 +80,19 @@ class ServiceObjectHolder { } template<typename ServiceImpl> - ServiceImpl *GetServiceObjectUnsafe() { + ServiceImpl *GetServiceObjectUnsafe() const { return static_cast<ServiceImpl *>(this->srv.get()); } - const ServiceCommandMeta *GetDispatchTable() { + const ServiceCommandMeta *GetDispatchTable() const { return this->dispatch_table; } - size_t GetDispatchTableEntryCount() { + size_t GetDispatchTableEntryCount() const { return this->entry_count; } - constexpr uintptr_t GetServiceId() { + constexpr uintptr_t GetServiceId() const { return reinterpret_cast<uintptr_t>(this->dispatch_table); } @@ -109,11 +109,11 @@ class ServiceObjectHolder { return *this; } - explicit operator bool() { + explicit operator bool() const { return this->srv != nullptr; } - bool operator!() { + bool operator!() const { return this->srv == nullptr; } @@ -123,7 +123,7 @@ class ServiceObjectHolder { this->entry_count = 0; } - ServiceObjectHolder Clone() { + ServiceObjectHolder Clone() const { ServiceObjectHolder clone(*this); return clone; } From 536b89efaed6a5bbff8111494b99dbe296beabd6 Mon Sep 17 00:00:00 2001 From: TuxSH <tuxsh@sfr.fr> Date: Tue, 30 Oct 2018 23:44:52 +0100 Subject: [PATCH 158/489] Add boost as submodule --- .gitmodules | 3 + common/include/boost | 1 + .../include/boost/callable_traits.hpp | 47 ---- .../callable_traits/add_member_const.hpp | 105 ------- .../boost/callable_traits/add_member_cv.hpp | 101 ------- .../add_member_lvalue_reference.hpp | 114 -------- .../add_member_rvalue_reference.hpp | 113 -------- .../callable_traits/add_member_volatile.hpp | 100 ------- .../boost/callable_traits/add_noexcept.hpp | 108 -------- .../callable_traits/add_transaction_safe.hpp | 110 -------- .../boost/callable_traits/add_varargs.hpp | 90 ------ .../callable_traits/apply_member_pointer.hpp | 123 --------- .../boost/callable_traits/apply_return.hpp | 109 -------- .../include/boost/callable_traits/args.hpp | 97 ------- .../boost/callable_traits/class_of.hpp | 75 ----- .../boost/callable_traits/detail/config.hpp | 109 -------- .../boost/callable_traits/detail/core.hpp | 19 -- .../detail/default_callable_traits.hpp | 207 -------------- .../detail/forward_declarations.hpp | 54 ---- .../boost/callable_traits/detail/function.hpp | 192 ------------- .../detail/function_object.hpp | 107 ------- .../detail/is_invocable_impl.hpp | 148 ---------- .../detail/parameter_index_helper.hpp | 51 ---- .../boost/callable_traits/detail/pmd.hpp | 53 ---- .../boost/callable_traits/detail/pmf.hpp | 97 ------- .../detail/polyfills/disjunction.hpp | 31 --- .../detail/polyfills/make_index_sequence.hpp | 50 ---- .../detail/qualifier_flags.hpp | 123 --------- .../detail/set_function_qualifiers.hpp | 120 -------- .../callable_traits/detail/sfinae_errors.hpp | 89 ------ .../boost/callable_traits/detail/traits.hpp | 29 -- .../detail/unguarded/function.hpp | 23 -- .../detail/unguarded/function_2.hpp | 23 -- .../detail/unguarded/function_3.hpp | 260 ------------------ .../detail/unguarded/function_ptr.hpp | 25 -- .../detail/unguarded/function_ptr_2.hpp | 23 -- .../detail/unguarded/function_ptr_3.hpp | 94 ------- .../detail/unguarded/function_ptr_varargs.hpp | 23 -- .../unguarded/function_ptr_varargs_2.hpp | 23 -- .../unguarded/function_ptr_varargs_3.hpp | 98 ------- .../callable_traits/detail/unguarded/pmf.hpp | 94 ------- .../detail/unguarded/pmf_2.hpp | 74 ----- .../detail/unguarded/pmf_3.hpp | 23 -- .../detail/unguarded/pmf_4.hpp | 147 ---------- .../detail/unguarded/pmf_varargs.hpp | 89 ------ .../detail/unguarded/pmf_varargs_2.hpp | 78 ------ .../detail/unguarded/pmf_varargs_3.hpp | 23 -- .../detail/unguarded/pmf_varargs_4.hpp | 149 ---------- .../boost/callable_traits/detail/utility.hpp | 111 -------- .../boost/callable_traits/function_type.hpp | 97 ------- .../callable_traits/has_member_qualifiers.hpp | 99 ------- .../boost/callable_traits/has_varargs.hpp | 94 ------- .../boost/callable_traits/has_void_return.hpp | 93 ------- .../boost/callable_traits/is_const_member.hpp | 97 ------- .../boost/callable_traits/is_cv_member.hpp | 95 ------- .../boost/callable_traits/is_invocable.hpp | 103 ------- .../is_lvalue_reference_member.hpp | 95 ------- .../boost/callable_traits/is_noexcept.hpp | 95 ------- .../callable_traits/is_reference_member.hpp | 98 ------- .../is_rvalue_reference_member.hpp | 97 ------- .../callable_traits/is_transaction_safe.hpp | 98 ------- .../callable_traits/is_volatile_member.hpp | 100 ------- .../callable_traits/qualified_class_of.hpp | 81 ------ .../callable_traits/remove_member_const.hpp | 85 ------ .../callable_traits/remove_member_cv.hpp | 87 ------ .../remove_member_reference.hpp | 85 ------ .../remove_member_volatile.hpp | 85 ------ .../boost/callable_traits/remove_noexcept.hpp | 93 ------- .../remove_transaction_safe.hpp | 93 ------- .../boost/callable_traits/remove_varargs.hpp | 91 ------ .../boost/callable_traits/return_type.hpp | 90 ------ .../stratosphere/ipc/ipc_serialization.hpp | 120 ++++---- .../stratosphere/ipc/ipc_templating_old.hpp | 108 ++++---- 73 files changed, 118 insertions(+), 6316 deletions(-) create mode 100644 .gitmodules create mode 160000 common/include/boost delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/add_member_const.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/add_member_cv.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/add_member_lvalue_reference.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/add_member_rvalue_reference.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/add_member_volatile.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/add_noexcept.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/add_transaction_safe.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/add_varargs.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/apply_member_pointer.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/apply_return.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/args.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/class_of.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/config.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/core.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/default_callable_traits.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/forward_declarations.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/function.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/function_object.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/is_invocable_impl.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/parameter_index_helper.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/pmd.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/pmf.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/polyfills/disjunction.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/polyfills/make_index_sequence.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/qualifier_flags.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/set_function_qualifiers.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/sfinae_errors.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/traits.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_2.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_3.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_2.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_3.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_2.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_2.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_3.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_4.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_3.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/detail/utility.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/function_type.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/has_member_qualifiers.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/has_varargs.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/has_void_return.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_const_member.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_cv_member.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_invocable.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_lvalue_reference_member.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_noexcept.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_reference_member.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_rvalue_reference_member.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_transaction_safe.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/is_volatile_member.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/qualified_class_of.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/remove_member_const.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/remove_member_cv.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/remove_member_reference.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/remove_member_volatile.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/remove_noexcept.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/remove_transaction_safe.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/remove_varargs.hpp delete mode 100644 stratosphere/libstratosphere/include/boost/callable_traits/return_type.hpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..5f85b18b6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "common/include/boost"] + path = common/include/boost + url = https://github.com/Atmosphere-NX/ext-boost.git diff --git a/common/include/boost b/common/include/boost new file mode 160000 index 000000000..fc6429e46 --- /dev/null +++ b/common/include/boost @@ -0,0 +1 @@ +Subproject commit fc6429e46398e16178b828a3a20e1bee9c56443d diff --git a/stratosphere/libstratosphere/include/boost/callable_traits.hpp b/stratosphere/libstratosphere/include/boost/callable_traits.hpp deleted file mode 100644 index 87f0fa622..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_BOOST_CLBL_TRTS_HPP -#define BOOST_CLBL_TRTS_BOOST_CLBL_TRTS_HPP - -#include <boost/callable_traits/detail/core.hpp> -#include <boost/callable_traits/add_member_const.hpp> -#include <boost/callable_traits/add_member_cv.hpp> -#include <boost/callable_traits/add_member_lvalue_reference.hpp> -#include <boost/callable_traits/add_member_rvalue_reference.hpp> -#include <boost/callable_traits/add_member_volatile.hpp> -#include <boost/callable_traits/add_noexcept.hpp> -#include <boost/callable_traits/add_transaction_safe.hpp> -#include <boost/callable_traits/add_varargs.hpp> -#include <boost/callable_traits/apply_member_pointer.hpp> -#include <boost/callable_traits/apply_return.hpp> -#include <boost/callable_traits/args.hpp> -#include <boost/callable_traits/class_of.hpp> -#include <boost/callable_traits/function_type.hpp> -#include <boost/callable_traits/has_member_qualifiers.hpp> -#include <boost/callable_traits/has_varargs.hpp> -#include <boost/callable_traits/has_void_return.hpp> -#include <boost/callable_traits/is_const_member.hpp> -#include <boost/callable_traits/is_invocable.hpp> -#include <boost/callable_traits/is_lvalue_reference_member.hpp> -#include <boost/callable_traits/is_reference_member.hpp> -#include <boost/callable_traits/is_rvalue_reference_member.hpp> -#include <boost/callable_traits/is_noexcept.hpp> -#include <boost/callable_traits/is_transaction_safe.hpp> -#include <boost/callable_traits/is_volatile_member.hpp> -#include <boost/callable_traits/qualified_class_of.hpp> -#include <boost/callable_traits/remove_member_const.hpp> -#include <boost/callable_traits/remove_member_cv.hpp> -#include <boost/callable_traits/remove_member_reference.hpp> -#include <boost/callable_traits/remove_member_volatile.hpp> -#include <boost/callable_traits/remove_noexcept.hpp> -#include <boost/callable_traits/remove_transaction_safe.hpp> -#include <boost/callable_traits/remove_varargs.hpp> -#include <boost/callable_traits/return_type.hpp> - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_const.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/add_member_const.hpp deleted file mode 100644 index cd7280ef8..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_const.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ADD_MEMBER_CONST_HPP -#define BOOST_CLBL_TRTS_ADD_MEMBER_CONST_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ add_member_const_hpp -/*` -[section:ref_add_member_const add_member_const] -[heading Header] -``#include <boost/callable_traits/add_member_const.hpp>`` -[heading Definition] -*/ - -template<typename T> -using add_member_const_t = //see below -//<- -#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - detail::sfinae_try< - typename detail::traits<T>::add_member_const, - - detail::fail_when_same<typename detail::traits<T>::add_member_const, - detail::abominable_functions_not_supported_on_this_compiler, - this_compiler_doesnt_support_abominable_function_types>, - - detail::fail_if_invalid<typename detail::traits<T>::add_member_const, - member_qualifiers_are_illegal_for_this_type>>; -#else - - detail::try_but_fail_if_invalid< - typename detail::traits<T>::add_member_const, - member_qualifiers_are_illegal_for_this_type>; - -#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - -namespace detail { - - template<typename T, typename = std::false_type> - struct add_member_const_impl {}; - - template<typename T> - struct add_member_const_impl <T, typename std::is_same< - add_member_const_t<T>, detail::dummy>::type> - { - using type = add_member_const_t<T>; - }; -} - -//-> - -template<typename T> -struct add_member_const : detail::add_member_const_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Adds a member `const` qualifier to `T`, if not already present. - -[heading Input/Output Examples] -[table - [[`T`] [`add_member_const_t<T>`]] - [[`int()`] [`int() const`]] - [[`int(foo::*)()`] [`int(foo::*)() const`]] - [[`int(foo::*)() &`] [`int(foo::*)() const &`]] - [[`int(foo::*)() &&`] [`int(foo::*)() const &&`]] - [[`int(foo::*)() const`] [`int(foo::*)() const`]] - [[`int(foo::*)() volatile`] [`int(foo::*)() const volatile`]] - [[`int(foo::*)() transaction_safe`] [`int(foo::*)() const transaction_safe`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/add_member_const.cpp] -[add_member_const] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_ADD_MEMBER_CONST_HPP - - - diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_cv.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/add_member_cv.hpp deleted file mode 100644 index e11cc0754..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_cv.hpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ADD_MEMBER_CV_HPP -#define BOOST_CLBL_TRTS_ADD_MEMBER_CV_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ add_member_cv_hpp -/*` -[section:ref_add_member_cv add_member_cv] -[heading Header] -``#include <boost/callable_traits/add_member_cv.hpp>`` -[heading Definition] -*/ - -template<typename T> -using add_member_cv_t = //see below -//<- -#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - detail::sfinae_try< - typename detail::traits<T>::add_member_cv, - - detail::fail_when_same<typename detail::traits<T>::add_member_cv, - detail::abominable_functions_not_supported_on_this_compiler, - this_compiler_doesnt_support_abominable_function_types>, - - detail::fail_if_invalid<typename detail::traits<T>::add_member_cv, - member_qualifiers_are_illegal_for_this_type>>; -#else - - detail::try_but_fail_if_invalid< - typename detail::traits<T>::add_member_cv, - member_qualifiers_are_illegal_for_this_type>; - -#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - -namespace detail { - - template<typename T, typename = std::false_type> - struct add_member_cv_impl {}; - - template<typename T> - struct add_member_cv_impl <T, typename std::is_same< - add_member_cv_t<T>, detail::dummy>::type> - { - using type = add_member_cv_t<T>; - }; -} - -//-> - -template<typename T> -struct add_member_cv : detail::add_member_cv_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Adds member `const` and `volatile` qualifiers to `T`, if not already present. - -[heading Input/Output Examples] -[table - [[`T`] [`add_member_cv_t<T>`]] - [[`int()`] [`int() const volatile`]] - [[`int(foo::*)()`] [`int(foo::*)() const volatile`]] - [[`int(foo::*)() &`] [`int(foo::*)() const volatile &`]] - [[`int(foo::*)() &&`] [`int(foo::*)() const volatile &&`]] - [[`int(foo::*)() const`] [`int(foo::*)() const volatile`]] - [[`int(foo::*)() volatile`] [`int(foo::*)() const volatile`]] - [[`int(foo::*)() transaction_safe`] [`int(foo::*)() const volatile transaction_safe`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/add_member_cv.cpp] -[add_member_cv] -[endsect] -*/ -//] - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_lvalue_reference.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/add_member_lvalue_reference.hpp deleted file mode 100644 index e23d71a00..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_lvalue_reference.hpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ADD_MEMBER_LVALUE_REFERENCE_HPP -#define BOOST_CLBL_TRTS_ADD_MEMBER_LVALUE_REFERENCE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ add_member_lvalue_reference_hpp -/*` -[section:ref_add_member_lvalue_reference add_member_lvalue_reference] -[heading Header] -``#include <boost/callable_traits/add_member_lvalue_reference.hpp>`` -[heading Definition] -*/ - -#ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -template<typename T> -struct add_member_lvalue_reference_t { - static_assert(std::is_same<T, detail::dummy>::value, - "Reference member qualifiers are not supported by this configuration."); -}; - -#else - -template<typename T> -using add_member_lvalue_reference_t = //see below -//<- -#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - detail::sfinae_try< - typename detail::traits<T>::add_member_lvalue_reference, - - detail::fail_when_same<typename detail::traits<T>::add_member_lvalue_reference, - detail::abominable_functions_not_supported_on_this_compiler, - this_compiler_doesnt_support_abominable_function_types>, - - detail::fail_if_invalid< - typename detail::traits<T>::add_member_lvalue_reference, - member_qualifiers_are_illegal_for_this_type>>; -#else - - detail::try_but_fail_if_invalid< - typename detail::traits<T>::add_member_lvalue_reference, - member_qualifiers_are_illegal_for_this_type>; - -#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS -#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -namespace detail { - - template<typename T, typename = std::false_type> - struct add_member_lvalue_reference_impl {}; - - template<typename T> - struct add_member_lvalue_reference_impl <T, typename std::is_same< - add_member_lvalue_reference_t<T>, detail::dummy>::type> - { - using type = add_member_lvalue_reference_t<T>; - }; -} -//-> - -template<typename T> -struct add_member_lvalue_reference - : detail::add_member_lvalue_reference_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Adds a member lvalue reference qualifier (`&`) to `T`, if not already present. -* If an rvalue reference qualifier is present, the lvalue reference qualifier replaces it (in accordance with reference collapsing rules). - -[heading Input/Output Examples] -[table - [[`T`] [`add_member_lvalue_reference_t<T>`]] - [[`int()`] [`int() &`]] - [[`int(foo::*)()`] [`int(foo::*)() &`]] - [[`int(foo::*)() &`] [`int(foo::*)() &`]] - [[`int(foo::*)() &&`] [`int(foo::*)() &`]] - [[`int(foo::*)() const`] [`int(foo::*)() const &`]] - [[`int(foo::*)() transaction_safe`] [`int(foo::*)() & transaction_safe`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/add_member_lvalue_reference.cpp] -[add_member_lvalue_reference] -[endsect] -*/ -//] - -#endif - diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_rvalue_reference.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/add_member_rvalue_reference.hpp deleted file mode 100644 index 84e3c5eaf..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_rvalue_reference.hpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ADD_MEMBER_RVALUE_REFERENCE_HPP -#define BOOST_CLBL_TRTS_ADD_MEMBER_RVALUE_REFERENCE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ add_member_rvalue_reference_hpp -/*` -[section:ref_add_member_rvalue_reference add_member_rvalue_reference] -[heading Header] -``#include <boost/callable_traits/add_member_rvalue_reference.hpp>`` -[heading Definition] -*/ - -#ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -template<typename T> -struct add_member_rvalue_reference_t { - static_assert(std::is_same<T, detail::dummy>::value, - "Reference member qualifiers are not supported by this configuration."); -}; - -#else - -template<typename T> -using add_member_rvalue_reference_t = //see below -//<- -#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - detail::sfinae_try< - typename detail::traits<T>::add_member_rvalue_reference, - - detail::fail_when_same<typename detail::traits<T>::add_member_rvalue_reference, - detail::abominable_functions_not_supported_on_this_compiler, - this_compiler_doesnt_support_abominable_function_types>, - - detail::fail_if_invalid<typename detail::traits<T>::add_member_rvalue_reference, - member_qualifiers_are_illegal_for_this_type>>; -#else - - detail::try_but_fail_if_invalid< - typename detail::traits<T>::add_member_rvalue_reference, - member_qualifiers_are_illegal_for_this_type>; - -#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS -#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -namespace detail { - - template<typename T, typename = std::false_type> - struct add_member_rvalue_reference_impl {}; - - template<typename T> - struct add_member_rvalue_reference_impl <T, typename std::is_same< - add_member_rvalue_reference_t<T>, detail::dummy>::type> - { - using type = add_member_rvalue_reference_t<T>; - }; -} -//-> - - -template<typename T> -struct add_member_rvalue_reference - : detail::add_member_rvalue_reference_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Adds a member rvalue reference qualifier (`&&`) to `T`, if not already present. -* If an lvalue reference qualifier is present, the lvalue reference qualifier remains (in accordance with reference collapsing rules). - -[heading Input/Output Examples] -[table - [[`T`] [`add_member_rvalue_reference_t<T>`]] - [[`int()`] [`int() &&`]] - [[`int(foo::*)()`] [`int(foo::*)() &&`]] - [[`int(foo::*)() &`] [`int(foo::*)() &`]] - [[`int(foo::*)() &&`] [`int(foo::*)() &&`]] - [[`int(foo::*)() const`] [`int(foo::*)() const &&`]] - [[`int(foo::*)() transaction_safe`] [`int(foo::*)() && transaction_safe`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/add_member_rvalue_reference.cpp] -[add_member_rvalue_reference] -[endsect][/section:ref_add_member_rvalue_reference] -*/ -//] - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_volatile.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/add_member_volatile.hpp deleted file mode 100644 index cb0a508a6..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/add_member_volatile.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ADD_MEMBER_VOLATILE_HPP -#define BOOST_CLBL_TRTS_ADD_MEMBER_VOLATILE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ add_member_volatile_hpp -/*` -[section:ref_add_member_volatile add_member_volatile] -[heading Header] -``#include <boost/callable_traits/add_member_volatile.hpp>`` -[heading Definition] -*/ - -template<typename T> -using add_member_volatile_t = //see below -//<- -#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - detail::sfinae_try< - typename detail::traits<T>::add_member_volatile, - - detail::fail_when_same<typename detail::traits<T>::add_member_volatile, - detail::abominable_functions_not_supported_on_this_compiler, - this_compiler_doesnt_support_abominable_function_types>, - - detail::fail_if_invalid< - typename detail::traits<T>::add_member_volatile, - member_qualifiers_are_illegal_for_this_type>>; -#else - - detail::try_but_fail_if_invalid< - typename detail::traits<T>::add_member_volatile, - member_qualifiers_are_illegal_for_this_type>; - -#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - -namespace detail { - - template<typename T, typename = std::false_type> - struct add_member_volatile_impl {}; - - template<typename T> - struct add_member_volatile_impl <T, typename std::is_same< - add_member_volatile_t<T>, detail::dummy>::type> - { - using type = add_member_volatile_t<T>; - }; -} -//-> - -template<typename T> -struct add_member_volatile : detail::add_member_volatile_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Adds a member volatile qualifier to `T`, if not already present. - -[heading Input/Output Examples] -[table - [[`T`] [`add_member_volatile_t<T>`]] - [[`int()`] [`int() volatile`]] - [[`int(foo::*)()`] [`int(foo::*)() volatile`]] - [[`int(foo::*)() &`] [`int(foo::*)() volatile &`]] - [[`int(foo::*)() &&`] [`int(foo::*)() volatile &&`]] - [[`int(foo::*)() const`] [`int(foo::*)() const volatile`]] - [[`int(foo::*)() transaction_safe`] [`int(foo::*)() volatile transaction_safe`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/add_member_volatile.cpp] -[add_member_volatile] -[endsect][/section:ref_add_member_volatile] -*/ -//] - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/add_noexcept.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/add_noexcept.hpp deleted file mode 100644 index 92b2dc55a..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/add_noexcept.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -@file add_noexcept - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ADD_NOEXCEPT_HPP -#define BOOST_CLBL_TRTS_ADD_NOEXCEPT_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(add_noexcept) -BOOST_CLBL_TRTS_SFINAE_MSG(add_noexcept, cannot_add_noexcept_to_this_type) - -#ifndef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -template<typename T> -struct add_noexcept_t { - static_assert(std::is_same<T, detail::dummy>::value, - "noexcept types not supported by this configuration."); -}; - -template<typename T> -struct add_noexcept { - static_assert(std::is_same<T, detail::dummy>::value, - "noexcept types not supported by this configuration."); -}; - -#else - -//[ add_noexcept_hpp -/*` -[section:ref_add_noexcept add_noexcept] -[heading Header] -``#include <boost/callable_traits/add_noexcept.hpp>`` -[heading Definition] -*/ - -template<typename T> -using add_noexcept_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::add_noexcept, - cannot_add_noexcept_to_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct add_noexcept_impl {}; - - template<typename T> - struct add_noexcept_impl <T, typename std::is_same< - add_noexcept_t<T>, detail::dummy>::type> - { - using type = add_noexcept_t<T>; - }; -} -//-> - -template<typename T> -struct add_noexcept : detail::add_noexcept_impl<T> {}; - -//<- -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be one of the following: - * function type - * function pointer type - * function reference type - * member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Adds a `noexcept` specifier to `T`, if not already present. - -[heading Input/Output Examples] -[table - [[`T`] [`add_noexcept_t<T>`]] - [[`int()`] [`int() noexcept`]] - [[`int (&)()`] [`int(&)() noexcept`]] - [[`int (*)()`] [`int(*)() noexcept`]] - [[`int(foo::*)()`] [`int(foo::*)() noexcept`]] - [[`int(foo::*)() &`] [`int(foo::*)() & noexcept`]] - [[`int(foo::*)() &&`] [`int(foo::*)() && noexcept`]] - [[`int(foo::*)() const transaction_safe`] [`int(foo::*)() const transaction_safe noexcept`]] - [[`int(foo::*)() noexcept`] [`int(foo::*)() noexcept`]] - [[`int`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (*&)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/add_noexcept.cpp] -[add_noexcept] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_ADD_NOEXCEPT_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/add_transaction_safe.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/add_transaction_safe.hpp deleted file mode 100644 index 2a634ba64..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/add_transaction_safe.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/* -@file add_transaction_safe - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ADD_TRANSACTION_SAFE_HPP -#define BOOST_CLBL_TRTS_ADD_TRANSACTION_SAFE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(add_transaction_safe) -BOOST_CLBL_TRTS_SFINAE_MSG(add_transaction_safe, cannot_add_transaction_safe_to_this_type) - -#ifndef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE -template<typename T> -struct add_transaction_safe_t { - static_assert(std::is_same<T, detail::dummy>::value, - "transaction_safe not supported by this configuration."); -}; - -template<typename T> -struct add_transaction_safe { - static_assert(std::is_same<T, detail::dummy>::value, - "transaction_safe not supported by this configuration."); -}; - -#else - -//[ add_transaction_safe_hpp -/*` -[section:ref_add_transaction_safe add_transaction_safe] -[heading Header] -``#include <boost/callable_traits/add_transaction_safe.hpp>`` -[heading Definition] -*/ - - -template<typename T> -using add_transaction_safe_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::add_transaction_safe, - cannot_add_transaction_safe_to_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct add_transaction_safe_impl {}; - - template<typename T> - struct add_transaction_safe_impl <T, typename std::is_same< - add_transaction_safe_t<T>, detail::dummy>::type> - { - using type = add_transaction_safe_t<T>; - }; -} -//-> - -template<typename T> -struct add_transaction_safe - : detail::add_transaction_safe_impl<T> {}; - -//<- -#endif // #ifndef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be one of the following: - * function type - * function pointer type - * function reference type - * member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Adds the `transaction_safe` specifier to `T`, if not already present. - -[heading Input/Output Examples] -[table - [[`T`] [`add_transaction_safe_t<T>`]] - [[`int()`] [`int() transaction_safe`]] - [[`int (&)()`] [`int(&)() transaction_safe`]] - [[`int (*)()`] [`int(*)() transaction_safe`]] - [[`int(foo::*)()`] [`int(foo::*)() transaction_safe`]] - [[`int(foo::*)() &`] [`int(foo::*)() & transaction_safe`]] - [[`int(foo::*)() &&`] [`int(foo::*)() && transaction_safe`]] - [[`int(foo::*)() const`] [`int(foo::*)() const transaction_safe`]] - [[`int(foo::*)() transaction_safe`] [`int(foo::*)() transaction_safe`]] - [[`int`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (*&)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/add_transaction_safe.cpp] -[add_transaction_safe] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_ADD_TRANSACTION_SAFE_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/add_varargs.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/add_varargs.hpp deleted file mode 100644 index 9357e38ba..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/add_varargs.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ADD_VARARGS_HPP -#define BOOST_CLBL_TRTS_ADD_VARARGS_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ add_varargs_hpp -/*` -[section:ref_add_varargs add_varargs] -[heading Header] -``#include <boost/callable_traits/add_varargs.hpp>`` -[heading Definition] -*/ - -template<typename T> -using add_varargs_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::add_varargs, - varargs_are_illegal_for_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct add_varargs_impl {}; - - template<typename T> - struct add_varargs_impl <T, typename std::is_same< - add_varargs_t<T>, detail::dummy>::type> - { - using type = add_varargs_t<T>; - }; -} -//-> - -template<typename T> -struct add_varargs : detail::add_varargs_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be one of the following: - * function type - * function pointer type - * function reference type - * member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Adds C-style variadics (`...`) to the signature of `T`, if not already present. - -[heading Input/Output Examples] -[table - [[`T`] [`add_varargs_t<T>`]] - [[`int()`] [`int(...)`]] - [[`int(int)`] [`int(int, ...)`]] - [[`int (&)()`] [`int(&)(...)`]] - [[`int (*)()`] [`int(*)(...)`]] - [[`int (*)(...)`] [`int(*)(...)`]] - [[`int(foo::*)()`] [`int(foo::*)(...)`]] - [[`int(foo::*)() &`] [`int(foo::*)(...) &`]] - [[`int(foo::*)() &&`] [`int(foo::*)(...) &&`]] - [[`int(foo::*)() const`] [`int(foo::*)(...) const`]] - [[`int(foo::*)() transaction_safe`] [`int(foo::*)(...) transaction_safe`]] - [[`int`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (*&)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/add_varargs.cpp] -[add_varargs] -[endsect] -*/ -//] - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/apply_member_pointer.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/apply_member_pointer.hpp deleted file mode 100644 index efd3f9575..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/apply_member_pointer.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_APPLY_MEMBER_POINTER_HPP -#define BOOST_CLBL_TRTS_APPLY_MEMBER_POINTER_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(apply_member_pointer) -BOOST_CLBL_TRTS_SFINAE_MSG(apply_member_pointer, members_cannot_have_a_type_of_void) -BOOST_CLBL_TRTS_SFINAE_MSG(apply_member_pointer, second_template_argument_must_be_a_class_or_struct) - -namespace detail { - - template<typename T, typename C, bool = std::is_class<C>::value> - struct make_member_pointer; - - template<typename T, typename C> - struct make_member_pointer<T, C, true> { - using type = typename std::remove_reference<T>::type C::*; - }; - - template<typename C> - struct make_member_pointer<void, C, true> { - using type = invalid_type; - }; - - template<typename T, typename C> - struct make_member_pointer<T, C, false> { - using type = error_type<T>; - }; - - template<typename T, typename C> - using make_member_pointer_t = typename make_member_pointer<T, C>::type; -} - -//[ apply_member_pointer_hpp -/*` -[section:ref_apply_member_pointer apply_member_pointer] -[heading Header] -``#include <boost/callable_traits/apply_member_pointer.hpp>`` -[heading Definition] -*/ - -template<typename T, typename C> -using apply_member_pointer_t = //see below -//<- - detail::sfinae_try< - detail::fallback_if_invalid< - typename detail::traits<T>::template apply_member_pointer<C>, - typename detail::make_member_pointer<T, C>::type>, - - detail::fail_when_same<void, T, members_cannot_have_a_type_of_void>, - - detail::fail_if<!std::is_class<C>::value, - second_template_argument_must_be_a_class_or_struct> >; - -namespace detail { - - template<typename T, typename C, typename = std::false_type> - struct apply_member_pointer_impl {}; - - template<typename T, typename C> - struct apply_member_pointer_impl <T, C, typename std::is_same< - apply_member_pointer_t<T, C>, detail::dummy>::type> - { - using type = apply_member_pointer_t<T, C>; - }; -} - -//-> - -template<typename T, typename C> -struct apply_member_pointer : detail::apply_member_pointer_impl<T, C> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` may be any type except `void` -* `C` must be a user-defined type - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* When `T` is a function, function pointer (unqualified), or function reference, then the aliased type is a member function pointer of `C` with the same parameters and return type. -* When `T` is a member function pointer (unqualified) of any type, the aliased type is a member function pointer of `C` with the same parameters and return type. -* Otherwise, the aliased type is a member data pointer equivalent to `std::remove_reference_t<T> C::*`. - -[heading Input/Output Examples] -[table - [[`T`] [`apply_member_pointer_t<T, foo>`]] - [[`int()`] [`int(foo::*)()`]] - [[`int (&)()`] [`int(foo::*)()`]] - [[`int (*)()`] [`int(foo::*)()`]] - [[`int(bar::*)()`] [`int(foo::*)()`]] - [[`int(bar::*)() &`] [`int(foo::*)() &`]] - [[`int(bar::*)() &&`] [`int(foo::*)() &&`]] - [[`int(bar::*)() const`] [`int(foo::*)() const`]] - [[`int(bar::*)() transaction_safe`] [`int(foo::*)() transaction_safe`]] - [[`int bar::*`] [`int foo::*`]] - [[`int`] [`int foo::*`]] - [[`int &`] [`int foo::*`]] - [[`const int &`] [`const int foo::*`]] - [[`int (*const)()`] [`int (*const foo::*)()`]] - [[`void`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/apply_member_pointer.cpp] -[apply_member_pointer] -[endsect] -*/ -//] -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/apply_return.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/apply_return.hpp deleted file mode 100644 index 6ed5ab74e..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/apply_return.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_APPLY_RETURN_HPP -#define BOOST_CLBL_TRTS_APPLY_RETURN_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(apply_return) -BOOST_CLBL_TRTS_SFINAE_MSG(apply_return, invalid_types_for_apply_return) - -namespace detail { - - template<typename T, typename R> - struct apply_return_helper { - using type = typename detail::traits<T>::template apply_return<R>; - }; - - //special case - template<typename... Args, typename R> - struct apply_return_helper<std::tuple<Args...>, R> { - using type = R(Args...); - }; -} - -//[ apply_return_hpp -/*` -[section:ref_apply_return apply_return] -[heading Header] -``#include <boost/callable_traits/apply_return.hpp>`` -[heading Definition] -*/ - -template<typename T, typename R> -using apply_return_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::apply_return_helper<T, R>::type, - invalid_types_for_apply_return>; - -namespace detail { - - template<typename T, typename R, typename = std::false_type> - struct apply_return_impl {}; - - template<typename T, typename R> - struct apply_return_impl <T, R, typename std::is_same< - apply_return_t<T, R>, detail::dummy>::type> - { - using type = apply_return_t<T, R>; - }; -} - //-> - -template<typename T, typename R> -struct apply_return : detail::apply_return_impl<T, R> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must one of the following: - * `std::tuple` template instantiation - * function - * function pointer - * function reference - * member function pointer - * member data pointer -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* When `T` is `std::tuple<Args...>`, the aliased type is `R(Args...)`. -* When `T` is a function, function pointer, function reference, or member function pointer, the aliased type's return type is `R`, but is otherwise identical to `T`. -* When `T` is a member data pointer of class `foo` to a `U` type (such that `T` is `U foo::*`), the aliased type is `R foo::*`. - -[heading Input/Output Examples] -[table - [[`T`] [`apply_return_t<T, float>`]] - [[`std::tuple<int, int>`] [`float(int, int)`]] - [[`int()`] [`float()`]] - [[`int (&)()`] [`float(&)()`]] - [[`int (*)()`] [`float(*)()`]] - [[`int (*)(...)`] [`float(*)()`]] - [[`int(foo::*)()`] [`float(foo::*)()`]] - [[`int(foo::*)() &`] [`float(foo::*)() &`]] - [[`int(foo::*)() &&`] [`float(foo::*)() &&`]] - [[`int(foo::*)() const`] [`float(foo::*)() const`]] - [[`int(foo::*)() transaction_safe`] [`float(foo::*)() transaction_safe`]] - [[`int foo::*`] [`float foo::*`]] - [[`int`] [(substitution failure)]] - [[`int (*const)()`] [(substitution failure)]] -] - -[heading Example Program] -[/import ../example/apply_return.cpp] -[apply_return] -[endsect] -*/ -//] -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/args.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/args.hpp deleted file mode 100644 index 6dcaaccc1..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/args.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_ARGS_HPP -#define BOOST_CLBL_TRTS_ARGS_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ args_hpp -/*`[section:ref_args args] -[heading Header] -``#include <boost/callable_traits/args.hpp>`` -[heading Definition] -*/ - -template<typename T, template<class...> class Container = std::tuple> -using args_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits< - detail::shallow_decay<T>>::template expand_args<Container>, - cannot_expand_the_parameter_list_of_first_template_argument>; - -namespace detail { - - template<typename T, template<class...> class Container, - typename = std::false_type> - struct args_impl {}; - - template<typename T, template<class...> class Container> - struct args_impl <T, Container, typename std::is_same< - args_t<T, Container>, detail::dummy>::type> - { - using type = args_t<T, Container>; - }; -} - -//-> - -template<typename T, - template<class...> class Container = std::tuple> -struct args : detail::args_impl<T, Container> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be one of the following: - * function - * function pointer - * function reference - * member function pointer - * member data pointer - * user-defined type with a non-overloaded `operator()` - * type of a non-generic lambda - -[heading Behavior] -* When the constraints are violated, a substitution failure occurs. -* When `T` is a function, function pointer, or function reference, the aliased type is `Container` instantiated with the function's parameter types. -* When `T` is a function object, the aliased type is `Container` instantiated with the `T::operator()` parameter types. -* When `T` is a member function pointer, the aliased type is a `Container` instantiation, where the first type argument is a reference to the parent class of `T`, qualified according to the member qualifiers on `T`, such that the first type is equivalent to `boost::callable_traits::qualified_class_of_t<T>`. The subsequent type arguments, if any, are the parameter types of the member function. -* When `T` is a member data pointer, the aliased type is `Container` with a single element, which is a `const` reference to the parent class of `T`. - -[heading Input/Output Examples] -[table - [[`T`] [`args_t<T>`]] - [[`void(float, char, int)`] [`std::tuple<float, char, int>`]] - [[`void(*)(float, char, int)`] [`std::tuple<float, char, int`]] - [[`void(&)(float, char, int)`] [`std::tuple<float, char, int`]] - [[`void(float, char, int) const &&`][`std::tuple<float, char, int>`]] - [[`void(*)()`] [`std::tuple<>`]] - [[`void(foo::* const &)(float, char, int)`] [`std::tuple<foo&, float, char, int>`]] - [[`int(foo::*)(int) const`] [`std::tuple<const foo&, int>`]] - [[`void(foo::*)() volatile &&`] [`std::tuple<volatile foo &&>`]] - [[`int foo::*`] [`std::tuple<const foo&>`]] - [[`const int foo::*`] [`std::tuple<const foo&>`]] - [[`int`] [(substitution failure)]] - [[`int (*const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/args.cpp] -[args] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_ARGS_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/class_of.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/class_of.hpp deleted file mode 100644 index a9eee7970..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/class_of.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_class_of_HPP -#define BOOST_CLBL_TRTS_class_of_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ class_of_hpp -/*` -[section:ref_class_of class_of] -[heading Header] -``#include <boost/callable_traits/class_of.hpp>`` -[heading Definition] -*/ - -template<typename T> -using class_of_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<detail::shallow_decay<T>>::class_type, - type_is_not_a_member_pointer>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct class_of_impl {}; - - template<typename T> - struct class_of_impl <T, typename std::is_same< - class_of_t<T>, detail::dummy>::type> - { - using type = class_of_t<T>; - }; -} - -//-> - -template<typename T> -struct class_of : detail::class_of_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a member pointer - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* The aliased type is the parent class of the member. In other words, if `T` is expanded to `U C::*`, the aliased type is `C`. - -[heading Input/Output Examples] -[table - [[`T`] [`class_of_t<T>`]] - [[`int foo::*`] [`foo`]] - [[`void(foo::* const &)() const`] [`foo`]] -] - -[heading Example Program] -[import ../example/class_of.cpp] -[class_of] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_class_of_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/config.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/config.hpp deleted file mode 100644 index 946458187..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/config.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* -@Copyright Barrett Adair 2016-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_CONFIG_HPP -#define BOOST_CLBL_TRTS_DETAIL_CONFIG_HPP - -#include <type_traits> -#include <tuple> -#include <utility> -#include <cstdint> - -#define BOOST_CLBL_TRTS_EMPTY_ -#define BOOST_CLBL_TRTS_EMPTY BOOST_CLBL_TRTS_EMPTY_ - -#ifdef __cpp_transactional_memory -# define BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE -#endif - -#ifdef __cpp_inline_variables -# define BOOST_CLBL_TRAITS_INLINE_VAR inline -#else -# define BOOST_CLBL_TRAITS_INLINE_VAR -#endif - -#ifdef __cpp_noexcept_function_type -# define BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -#endif - -#ifdef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE -# define BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER transaction_safe -#else -# define BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER -#endif - -#ifndef __clang__ -# if defined(__GNUC__) -# define BOOST_CLBL_TRTS_GCC -# if __GNUC__ >= 6 -# define BOOST_CLBL_TRTS_GCC_AT_LEAST_6_0_0 -# endif -# if __GNUC__ < 5 -# define BOOST_CLBL_TRTS_GCC_OLDER_THAN_5_0_0 -# endif -# if __GNUC__ >= 5 -# define BOOST_CLBL_TRTS_GCC_AT_LEAST_4_9_2 -# elif __GNUC__ == 4 && __GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ >= 2 -# define BOOST_CLBL_TRTS_GCC_AT_LEAST_4_9_2 -# else -# define BOOST_CLBL_TRTS_GCC_OLDER_THAN_4_9_2 -# endif //#if __GNUC__ >= 5 -# endif //#if defined __GNUC__ -#endif // #ifndef __clang__ - -#ifdef _MSC_VER -# ifdef __clang__ -# define BOOST_CLBL_TRTS_CLANG_C2 -# else -# define BOOST_CLBL_TRTS_MSVC -# endif // #ifdef __clang__ -#endif // #ifdef _MSC_VER - -#define BOOST_CLBL_TRTS_IX_SEQ(...) ::std::index_sequence< __VA_ARGS__ > -#define BOOST_CLBL_TRTS_MAKE_IX_SEQ(...) ::std::make_index_sequence< __VA_ARGS__ > -#define BOOST_CLBL_TRTS_DISJUNCTION(...) ::std::disjunction< __VA_ARGS__ > - -#ifndef __cpp_variable_templates -# define BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES -#endif - -#ifndef __cpp_lib_logical_traits -# include <boost/callable_traits/detail/polyfills/disjunction.hpp> -#endif //__cpp_lib_logical_traits - -#ifndef __cpp_lib_integer_sequence -# include <boost/callable_traits/detail/polyfills/make_index_sequence.hpp> -#endif // __cpp_lib_integer_sequence - -#if defined(BOOST_CLBL_TRTS_MSVC) && !defined(BOOST_DISABLE_WIN32) -# define BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC __cdecl -# define BOOST_CLBL_TRTS_PMF_VARGARGS_CDECL_DEFAULT -#else -# define BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#endif // #if defined(BOOST_CLBL_TRTS_MSVC) && !defined(BOOST_DISABLE_WIN32)) - -#if (defined(BOOST_CLBL_TRTS_GCC) && !defined(BOOST_CLBL_TRTS_GCC_AT_LEAST_4_9_2)) || defined(__INTEL_COMPILER) -# define BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS -# define BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS -#endif // #if defined BOOST_CLBL_TRTS_GCC && !defined(BOOST_CLBL_TRTS_GCC_AT_LEAST_4_9_2) - -#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS -# define BOOST_CLBL_TRTS_ABOMINABLE_CONST BOOST_CLBL_TRTS_EMPTY -# define BOOST_CLBL_TRTS_ABOMINABLE_VOLATILE BOOST_CLBL_TRTS_EMPTY -#else -# define BOOST_CLBL_TRTS_ABOMINABLE_CONST const -# define BOOST_CLBL_TRTS_ABOMINABLE_VOLATILE volatile -#endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - -#ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -# define BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER noexcept -#else -# define BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER BOOST_CLBL_TRTS_EMPTY -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_CONFIG_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/core.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/core.hpp deleted file mode 100644 index 77560283b..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/core.hpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - -@Copyright Barrett Adair 2016-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_CORE_HPP -#define BOOST_CLBL_TRTS_DETAIL_CORE_HPP - -#include <boost/callable_traits/detail/utility.hpp> -#include <boost/callable_traits/detail/traits.hpp> -#include <boost/callable_traits/detail/function_object.hpp> -#include <boost/callable_traits/detail/function.hpp> -#include <boost/callable_traits/detail/pmf.hpp> -#include <boost/callable_traits/detail/pmd.hpp> - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_CORE_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/default_callable_traits.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/default_callable_traits.hpp deleted file mode 100644 index 84970783a..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/default_callable_traits.hpp +++ /dev/null @@ -1,207 +0,0 @@ -/* -Copyright Barrett Adair 2016-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http ://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_DEFAULT_BOOST_CLBL_TRTS_HPP -#define BOOST_CLBL_TRTS_DETAIL_DEFAULT_BOOST_CLBL_TRTS_HPP - -namespace boost { namespace callable_traits { namespace detail { - -template<typename T = void> -struct default_callable_traits { - - // value is used by all traits classes to participate - // in the <callable_traits/detail/traits.hpp> disjunction. - static constexpr bool value = false; - - // used facilitate the disjunction in - // <callable_traits/detail/traits.hpp> - using traits = default_callable_traits; - - using error_t = error_type<T>; - - // represents the type under consideration - using type = error_t; - - // std::true_type for callables with C-style variadics - using has_varargs = std::false_type; - - using return_type = error_t; - - // arg_types is a std::tuple of argument types for - // callables that are not overloaded/templated function objects. - // arg_types IS defined in terms of INVOKE, which means - // a PMF's arg_types tuple will use a reference to its - // parent class as the first argument, with qualifiers added to - // match the PMF's own qualifiers. - using arg_types = error_t; - - // arg_types without the decltype(*this) parameter for member functions - using non_invoke_arg_types = error_t; - - // An "approximation" of a callable type, in the form - // of a plain function type. Defined in terms of INVOKE. - // An identity alias for qualified/unqualified plain function - // types. - using function_type = error_t; - - // Used to smoothen the edges between PMFs and function objects - using function_object_signature = error_t; - - // An identity alias for qualified/unqualified plain function - // types. Equivalent to remove_member_pointer for PMFs. Same - // as function_type for other callable types. - using qualified_function_type = error_t; - - // Removes C-style variadics from a signature, if present. - // Aliases error_t for function objects and PMDs. - using remove_varargs = error_t; - - // Adds C-style variadics to a signature. Aliases - // error_t for function objects and PMDs. - using add_varargs = error_t; - - // std::true_type when the signature includes noexcept, when - // the feature is available - using is_noexcept = std::false_type; - - // adds noexcept to a signature if the feature is available - using add_noexcept = error_t; - - // removes noexcept from a signature if present - using remove_noexcept = error_t; - - // std::true_type when the signature includes transaction_safe, when - // the feature is available - using is_transaction_safe = std::false_type; - - // adds transaction_safe to a signature if the feature is available - using add_transaction_safe = error_t; - - // removes transaction_safe from a signature if present - using remove_transaction_safe = error_t; - - // The class of a PMD or PMF. error_t for other types - using class_type = error_t; - - // The qualified reference type of class_type. error_t - // for non-member-pointers. - using invoke_type = error_t; - - // Removes reference qualifiers from a signature. - using remove_reference = error_t; - - // Adds an lvalue qualifier to a signature, in arbitrary - // accordance with C++11 reference collapsing rules. - using add_member_lvalue_reference = error_t; - - // Adds an rvalue qualifier to a signature, in arbitrary - // accordance with C++11 reference collapsing rules. - using add_member_rvalue_reference = error_t; - - // Adds a const qualifier to a signature. - using add_member_const = error_t; - - // Adds a volatile qualifier to a signature. - using add_member_volatile = error_t; - - // Adds both const and volatile qualifiers to a signature. - using add_member_cv = error_t; - - // Removes a const qualifier from a signature, if present. - using remove_member_const = error_t; - - // Removes a volatile qualifier from a signature, if present. - using remove_member_volatile = error_t; - - // Removes both const and volatile qualifiers from a - // signature, if any. - using remove_member_cv = error_t; - - // Removes the member pointer from PMDs and PMFs. An identity - // alias for other callable types. - using remove_member_pointer = error_t; - - // Changes the parent class type for PMDs and PMFs. Turns - // function pointers, function references, and - // qualified/unqualified function types into PMFs. Turns - // everything else into member data pointers. - template<typename C, - typename U = T, - typename K = typename std::remove_reference<U>::type, - typename L = typename std::conditional< - std::is_same<void, K>::value, error_t, K>::type, - typename Class = typename std::conditional< - std::is_class<C>::value, C, error_t>::type> - using apply_member_pointer = typename std::conditional< - std::is_same<L, error_t>::value || std::is_same<Class, error_t>::value, - error_t, L Class::*>::type; - - // Changes the return type of PMFs, function pointers, function - // references, and qualified/unqualified function types. Changes - // the data type of PMDs. error_t for function objects. - template<typename> - using apply_return = error_t; - - // Expands the argument types into a template - template<template<class...> class Container> - using expand_args = error_t; - - template<template<class...> class Container, typename... RightArgs> - using expand_args_left = error_t; - - template<template<class...> class Container, typename... LeftArgs> - using expand_args_right = error_t; - - using clear_args = error_t; - - template<typename... NewArgs> - using push_front = error_t; - - template<typename... NewArgs> - using push_back = error_t; - - template<std::size_t ElementCount> - using pop_front = error_t; - - template<std::size_t ElementCount> - using pop_back = error_t; - - template<std::size_t Index, typename... NewArgs> - using insert_args = error_t; - - template<std::size_t Index, std::size_t Count> - using remove_args = error_t; - - template<std::size_t Index, typename... NewArgs> - using replace_args = error_t; - - static constexpr qualifier_flags cv_flags = cv_of<T>::value; - static constexpr qualifier_flags ref_flags = ref_of<T>::value; - static constexpr qualifier_flags q_flags = cv_flags | ref_flags; - - using has_member_qualifiers = std::integral_constant<bool, q_flags != default_>; - using is_const_member = std::integral_constant<bool, 0 < (cv_flags & const_)>; - using is_volatile_member = std::integral_constant<bool, 0 < (cv_flags & volatile_)>; - using is_cv_member = std::integral_constant<bool, cv_flags == (const_ | volatile_)>; - -#ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - using is_reference_member = std::false_type; - using is_lvalue_reference_member = std::false_type; - using is_rvalue_reference_member = std::false_type; -#else - using is_reference_member = std::integral_constant<bool, 0 < ref_flags>; - using is_lvalue_reference_member = std::integral_constant<bool, ref_flags == lref_>; - using is_rvalue_reference_member = std::integral_constant<bool, ref_flags == rref_>; -#endif //#ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -}; - -}}} // namespace boost::callable_traits::detail - -#endif // BOOST_CLBL_TRTS_DETAIL_DEFAULT_BOOST_CLBL_TRTS_HPP - diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/forward_declarations.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/forward_declarations.hpp deleted file mode 100644 index 9327759f6..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/forward_declarations.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef BOOST_CLBL_TRTS_DETAIL_FORWARD_DECLARATIONS -#define BOOST_CLBL_TRTS_DETAIL_FORWARD_DECLARATIONS -#include <boost/callable_traits/detail/config.hpp> -#include <boost/callable_traits/detail/default_callable_traits.hpp> - -namespace boost { namespace callable_traits { namespace detail { - -template<typename T> -struct function; - -template<typename T> -struct has_normal_call_operator -{ - template<typename N, N Value> - struct check { check(std::nullptr_t) {} }; - - template<typename U> - static std::int8_t test( - check<decltype(&U::operator()), &U::operator()>); - - template<typename> - static std::int16_t test(...); - - static constexpr bool value = - sizeof(test<T>(nullptr)) == sizeof(std::int8_t); -}; - -struct callable_dummy { - void operator()() {} -}; - -template<typename T> -using default_to_function_object = typename std::conditional< - has_normal_call_operator<T>::value, - T, callable_dummy>::type; - -template<typename T> -struct pmf; - -template<typename T> -struct pmd; - -template<typename F, typename T = typename std::remove_reference<F>::type> -using function_object_base = typename std::conditional< - has_normal_call_operator<T>::value, - pmf<decltype(&default_to_function_object<T>::operator())>, - default_callable_traits<T>>::type; - -template<typename T, typename Base = function_object_base<T>> -struct function_object; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_FORWARD_DECLARATIONS diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/function.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/function.hpp deleted file mode 100644 index 624c704d2..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/function.hpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_FUNCTION_HPP -#define BOOST_CLBL_TRTS_DETAIL_FUNCTION_HPP - -#include <boost/callable_traits/detail/config.hpp> -#include <boost/callable_traits/detail/qualifier_flags.hpp> -#include <boost/callable_traits/detail/forward_declarations.hpp> -#include <boost/callable_traits/detail/set_function_qualifiers.hpp> -#include <boost/callable_traits/detail/default_callable_traits.hpp> - -namespace boost { namespace callable_traits { namespace detail { - -template<typename T> -struct function : default_callable_traits<T> {}; - -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#ifndef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS & -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS && -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const & -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const && -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile & -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile && -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile & -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile && -#include <boost/callable_traits/detail/unguarded/function.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - -#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS -#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - -// function pointers - -#define BOOST_CLBL_TRTS_CC_TAG dummy -#define BOOST_CLBL_TRTS_VARARGS_CC BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#define BOOST_CLBL_TRTS_CC -#define BOOST_CLBL_TRTS_ST -#include <boost/callable_traits/detail/unguarded/function_ptr.hpp> -#include <boost/callable_traits/detail/unguarded/function_ptr_varargs.hpp> -#undef BOOST_CLBL_TRTS_ST -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC - -/* ? -#ifdef BOOST_CLBL_TRTS_ENABLE_CDECL -#define BOOST_CLBL_TRTS_CC_TAG cdecl_tag -#define BOOST_CLBL_TRTS_VARARGS_CC __cdecl -#define BOOST_CLBL_TRTS_CC __cdecl -#define BOOST_CLBL_TRTS_ST -#include <boost/callable_traits/detail/unguarded/function_ptr.hpp> -#undef BOOST_CLBL_TRTS_ST -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC -#endif*/ - -#ifdef BOOST_CLBL_TRTS_ENABLE_STDCALL -#define BOOST_CLBL_TRTS_CC_TAG stdcall_tag -#define BOOST_CLBL_TRTS_VARARGS_CC BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#define BOOST_CLBL_TRTS_CC __stdcall -#define BOOST_CLBL_TRTS_ST -#include <boost/callable_traits/detail/unguarded/function_ptr.hpp> -#undef BOOST_CLBL_TRTS_ST -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC -#endif - -#ifdef BOOST_CLBL_TRTS_ENABLE_FASTCALL -#define BOOST_CLBL_TRTS_CC_TAG fastcall_tag -#define BOOST_CLBL_TRTS_VARARGS_CC BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#define BOOST_CLBL_TRTS_CC __fastcall -#define BOOST_CLBL_TRTS_ST -#include <boost/callable_traits/detail/unguarded/function_ptr.hpp> -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_ST -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC -#endif - -#ifdef BOOST_CLBL_TRTS_ENABLE_PASCAL -#define BOOST_CLBL_TRTS_CC_TAG pascal_tag -#define BOOST_CLBL_TRTS_VARARGS_CC BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#define BOOST_CLBL_TRTS_CC -#define BOOST_CLBL_TRTS_ST pascal -#include <boost/callable_traits/detail/unguarded/function_ptr.hpp> -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_ST -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC -#endif - -template<typename T> -struct function<T&> : std::conditional<function<T>::value, - function<T>, default_callable_traits<T&>>::type { - - static constexpr const bool value = !std::is_pointer<T>::value; - - using traits = function; - using base = function<T>; - using type = T&; - using remove_varargs = typename base::remove_varargs&; - using add_varargs = typename base::add_varargs&; - - using remove_member_reference = reference_error; - using add_member_lvalue_reference = reference_error; - using add_member_rvalue_reference = reference_error; - using add_member_const = reference_error; - using add_member_volatile = reference_error; - using add_member_cv = reference_error; - using remove_member_const = reference_error; - using remove_member_volatile = reference_error; - using remove_member_cv = reference_error; - - template<typename NewReturn> - using apply_return = typename base::template apply_return<NewReturn>&; - - using clear_args = typename base::clear_args&; - - template<typename... NewArgs> - using push_front = typename base::template push_front<NewArgs...>&; - - template<typename... NewArgs> - using push_back = typename base::template push_back<NewArgs...>&; - - template<std::size_t Count> - using pop_back = typename base::template pop_back<Count>&; - - template<std::size_t Count> - using pop_front = typename base::template pop_front<Count>&; - - template<std::size_t Index, typename... NewArgs> - using insert_args = typename base::template insert_args<Index, NewArgs...>&; - - template<std::size_t Index, std::size_t Count> - using remove_args = typename base::template remove_args<Index, Count>&; - - template<std::size_t Index, typename... NewArgs> - using replace_args = typename base::template replace_args<Index, NewArgs...>&; -}; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_FUNCTION_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/function_object.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/function_object.hpp deleted file mode 100644 index d12fc00e6..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/function_object.hpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_FUNCTION_OBJECT_HPP -#define BOOST_CLBL_TRTS_DETAIL_FUNCTION_OBJECT_HPP - -#include <boost/callable_traits/detail/pmf.hpp> -#include <boost/callable_traits/detail/default_callable_traits.hpp> -#include <boost/callable_traits/detail/forward_declarations.hpp> -#include <boost/callable_traits/detail/utility.hpp> - -namespace boost { namespace callable_traits { namespace detail { - -template<typename T, typename Base> -struct function_object : Base { - - using type = T; - using error_t = error_type<T>; - using function_type = typename Base::function_object_signature; - using arg_types = typename Base::non_invoke_arg_types; - using non_invoke_arg_types = arg_types; - - static constexpr const bool value = std::is_class< - typename std::remove_reference<T>::type>::value; - - using traits = function_object; - using class_type = error_t; - using invoke_type = error_t; - using remove_varargs = error_t; - using add_varargs = error_t; - using is_noexcept = typename Base::is_noexcept; - using add_noexcept = error_t; - using remove_noexcept = error_t; - using is_transaction_safe = typename Base::is_transaction_safe; - using add_transaction_safe = error_t; - using remove_transaction_safe = error_t; - using clear_args = error_t; - - template<template<class...> class Container> - using expand_args = typename function<function_type>::template - expand_args<Container>; - - template<template<class...> class Container, typename... RightArgs> - using expand_args_left = typename function<function_type>::template - expand_args_left<Container, RightArgs...>; - - template<template<class...> class Container, typename... LeftArgs> - using expand_args_right = typename function<function_type>::template - expand_args_right<Container, LeftArgs...>; - - template<typename C, typename U = T> - using apply_member_pointer = - typename std::remove_reference<U>::type C::*; - - template<typename> - using apply_return = error_t; - - template<typename...> - using push_front = error_t; - - template<typename...> - using push_back = error_t; - - template<std::size_t ElementCount> - using pop_args_front = error_t; - - template<std::size_t ElementCount> - using pop_args_back = error_t; - - template<std::size_t Index, typename... NewArgs> - using insert_args = error_t; - - template<std::size_t Index, std::size_t Count> - using remove_args = error_t; - - template<std::size_t Index, typename... NewArgs> - using replace_args = error_t; - - template<std::size_t Count> - using pop_front = error_t; - - template<std::size_t Count> - using pop_back = error_t; - - using remove_member_reference = error_t; - using add_member_lvalue_reference = error_t; - using add_member_rvalue_reference = error_t; - using add_member_const = error_t; - using add_member_volatile = error_t; - using add_member_cv = error_t; - using remove_member_const = error_t; - using remove_member_volatile = error_t; - using remove_member_cv = error_t; -}; - -template<typename T, typename U, typename Base> -struct function_object <T U::*, Base> - : default_callable_traits<> {}; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_FUNCTION_OBJECT_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/is_invocable_impl.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/is_invocable_impl.hpp deleted file mode 100644 index 323886572..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/is_invocable_impl.hpp +++ /dev/null @@ -1,148 +0,0 @@ - /*! -@file - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP -#define BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP - -#include <boost/callable_traits/detail/config.hpp> -#include <boost/callable_traits/detail/forward_declarations.hpp> -#include <boost/callable_traits/detail/utility.hpp> -#include <type_traits> -#include <utility> - -namespace boost { namespace callable_traits { namespace detail { - - template<typename T> - struct can_dereference_t - { - template<typename> - struct check {}; - - template<typename U> - static std::int8_t test( - check<typename std::remove_reference<decltype(*std::declval<U>())>::type>* - ); - - template<typename> - static std::int16_t test(...); - - static constexpr const bool value = - sizeof(test<T>(nullptr)) == sizeof(std::int8_t); - }; - - //returns std::true_type for pointers and smart pointers - template<typename T> - using can_dereference = std::integral_constant<bool, - can_dereference_t<T>::value>; - - - template<typename T, typename = std::true_type> - struct generalize_t { - using type = T; - }; - - template<typename T> - struct generalize_t<T, std::integral_constant<bool, - can_dereference<T>::value && !is_reference_wrapper<T>::value - >>{ - using type = decltype(*std::declval<T>()); - }; - - template<typename T> - struct generalize_t<T, is_reference_wrapper<T>> { - using type = decltype(std::declval<T>().get()); - }; - - // When T is a pointer, generalize<T> is the resulting type of the - // pointer dereferenced. When T is an std::reference_wrapper, generalize<T> - // is the underlying reference type. Otherwise, generalize<T> is T. - template<typename T> - using generalize = typename generalize_t<T>::type; - - // handles the member pointer rules of INVOKE - template<typename Base, typename T, - typename IsBaseOf = std::is_base_of<Base, shallow_decay<T>>, - typename IsSame = std::is_same<Base, shallow_decay<T>>> - using generalize_if_dissimilar = typename std::conditional< - IsBaseOf::value || IsSame::value, T, generalize<T>>::type; - - template<typename Traits, bool = Traits::is_const_member::value - || Traits::is_volatile_member::value - || Traits::is_lvalue_reference_member::value - || Traits::is_rvalue_reference_member::value> - struct test_invoke { - - template<typename... Rgs, - typename U = typename Traits::type> - auto operator()(Rgs&&... rgs) const -> - success<decltype(std::declval<U>()(static_cast<Rgs&&>(rgs)...))>; - - auto operator()(...) const -> substitution_failure; - }; - - template<typename F> - struct test_invoke<function<F>, true /*abominable*/> { - auto operator()(...) const -> substitution_failure; - }; - - template<typename Pmf, bool Ignored> - struct test_invoke<pmf<Pmf>, Ignored> { - - using class_t = typename pmf<Pmf>::class_type; - - template<typename U, typename... Rgs, - typename Obj = generalize_if_dissimilar<class_t, U&&>> - auto operator()(U&& u, Rgs&&... rgs) const -> - success<decltype((std::declval<Obj>().*std::declval<Pmf>())(static_cast<Rgs&&>(rgs)...))>; - - auto operator()(...) const -> substitution_failure; - }; - - template<typename Pmd, bool Ignored> - struct test_invoke<pmd<Pmd>, Ignored> { - - using class_t = typename pmd<Pmd>::class_type; - - template<typename U, - typename Obj = generalize_if_dissimilar<class_t, U&&>> - auto operator()(U&& u) const -> - success<decltype(std::declval<Obj>().*std::declval<Pmd>())>; - - auto operator()(...) const -> substitution_failure; - }; - - template<typename T, typename... Args> - struct is_invocable_impl { - using traits = detail::traits<T>; - using test = detail::test_invoke<traits>; - using result = decltype(test{}(::std::declval<Args>()...)); - using type = std::integral_constant<bool, result::value>; - }; - - template<typename... Args> - struct is_invocable_impl<void, Args...> { - using type = std::false_type; - }; - - template<typename IsInvocable, typename Ret, typename T, typename... Args> - struct is_invocable_r_impl { - using traits = detail::traits<T>; - using test = detail::test_invoke<traits>; - using result = decltype(test{}(::std::declval<Args>()...)); - using type = typename std::is_convertible<typename result::_::type, Ret>::type; - }; - - template<typename Ret, typename T, typename... Args> - struct is_invocable_r_impl<std::false_type, Ret, T, Args...> { - using type = std::false_type; - }; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/parameter_index_helper.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/parameter_index_helper.hpp deleted file mode 100644 index 430217591..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/parameter_index_helper.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef BOOST_CLBL_TRTS_PARAMETER_INDEX_HELPER_HPP -#define BOOST_CLBL_TRTS_PARAMETER_INDEX_HELPER_HPP - -#include <boost/callable_traits/detail/config.hpp> - -namespace boost { namespace callable_traits { namespace detail { - -template<std::size_t I, typename T, bool IgnoreThisPointer = false, - bool AllowPlus1 = false, std::size_t Count = 0> -struct parameter_index_helper { - - using error_t = error_type<T>; - - using args_tuple = typename std::conditional<IgnoreThisPointer, - typename detail::traits<T>::non_invoke_arg_types, - typename detail::traits<T>::arg_types>::type; - - static constexpr bool has_parameter_list = - !std::is_same<args_tuple, invalid_type>::value - && !std::is_same<args_tuple, reference_error>::value; - - using temp_tuple = typename std::conditional<has_parameter_list, - args_tuple, std::tuple<error_t>>::type; - - static constexpr std::size_t parameter_list_size = - std::tuple_size<temp_tuple>::value; - - static constexpr bool is_out_of_range = has_parameter_list && - I >= parameter_list_size + static_cast<std::size_t>(AllowPlus1); - - static constexpr bool is_count_out_of_range = has_parameter_list && - I + Count > parameter_list_size + static_cast<std::size_t>(AllowPlus1); - - static constexpr std::size_t index = - has_parameter_list && !is_out_of_range ? I : 0; - - static constexpr std::size_t count = - has_parameter_list && !is_count_out_of_range ? Count : 0; - - using permissive_tuple = typename std::conditional< - has_parameter_list && !is_out_of_range, - args_tuple, std::tuple<error_t>>::type; - - using permissive_function = typename std::conditional< - has_parameter_list && !is_out_of_range, - T, error_t(error_t)>::type; -}; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_PARAMETER_INDEX_HELPER_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/pmd.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/pmd.hpp deleted file mode 100644 index 13a2c4463..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/pmd.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_PMD_HPP -#define BOOST_CLBL_TRTS_DETAIL_PMD_HPP - -#include <boost/callable_traits/detail/forward_declarations.hpp> -#include <boost/callable_traits/detail/function.hpp> -#include <boost/callable_traits/detail/traits.hpp> -#include <boost/callable_traits/detail/default_callable_traits.hpp> -#include <boost/callable_traits/detail/utility.hpp> - -namespace boost { namespace callable_traits { namespace detail { - -template<typename T> -struct pmd : default_callable_traits<T> {}; - -template<typename D, typename T> -struct pmd<D T::*> : default_callable_traits<> { - - static constexpr bool value = true; - - using traits = pmd; - using class_type = T; - using invoke_type = T const &; - using type = D T::*; - using function_type = typename std::add_lvalue_reference<D>::type(invoke_type); - using qualified_function_type = D(invoke_type); - using arg_types = std::tuple<invoke_type>; - using non_invoke_arg_types = std::tuple<>; - - using return_type = typename std::add_lvalue_reference<D>::type; - - template<typename C> - using apply_member_pointer = D C::*; - - template<typename R> - using apply_return = R T::*; - - template<template<class...> class Container> - using expand_args = Container<invoke_type>; - - using is_member_pointer = std::true_type; -}; - -}}} // namespace boost::callable_traits::detail - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/pmf.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/pmf.hpp deleted file mode 100644 index 5284e0d59..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/pmf.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_PMF_HPP -#define BOOST_CLBL_TRTS_DETAIL_PMF_HPP - -#include <boost/callable_traits/detail/forward_declarations.hpp> -#include <boost/callable_traits/detail/set_function_qualifiers.hpp> -#include <boost/callable_traits/detail/qualifier_flags.hpp> -#include <boost/callable_traits/detail/default_callable_traits.hpp> -#include <boost/callable_traits/detail/utility.hpp> - -namespace boost { namespace callable_traits { namespace detail { - -template<qualifier_flags Applied, bool IsTransactionSafe, bool IsNoExcept, - typename CallingConvention, typename T, typename Return, - typename... Args> -struct set_member_function_qualifiers_t; - -template<qualifier_flags Applied, bool IsTransactionSafe, bool IsNoexcept, - typename CallingConvention, typename T, typename Return, - typename... Args> -struct set_varargs_member_function_qualifiers_t; - -template<qualifier_flags Flags, bool IsTransactionSafe, bool IsNoexcept, - typename... Ts> -using set_member_function_qualifiers = - typename set_member_function_qualifiers_t<Flags, IsTransactionSafe, - IsNoexcept, Ts...>::type; - -template<qualifier_flags Flags, bool IsTransactionSafe, bool IsNoexcept, - typename... Ts> -using set_varargs_member_function_qualifiers = - typename set_varargs_member_function_qualifiers_t<Flags, - IsTransactionSafe, IsNoexcept, Ts...>::type; - -template<typename T> -struct pmf : default_callable_traits<T> {}; - -#define BOOST_CLBL_TRTS_CC_TAG dummy -#define BOOST_CLBL_TRTS_VARARGS_CC BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#define BOOST_CLBL_TRTS_CC -#include <boost/callable_traits/detail/unguarded/pmf.hpp> -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC - -#define BOOST_CLBL_TRTS_CC_TAG dummy -#define BOOST_CLBL_TRTS_VARARGS_CC BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#define BOOST_CLBL_TRTS_CC -#include <boost/callable_traits/detail/unguarded/pmf_varargs.hpp> -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC - -#ifdef BOOST_CLBL_TRTS_ENABLE_CDECL -#define BOOST_CLBL_TRTS_CC_TAG cdecl_tag -#define BOOST_CLBL_TRTS_VARARGS_CC __cdecl -#define BOOST_CLBL_TRTS_CC __cdecl -#include <boost/callable_traits/detail/unguarded/pmf.hpp> -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_CDECL - -// Defining this macro enables undocumented features, likely broken. -// Too much work to maintain, but knock yourself out -#ifdef BOOST_CLBL_TRTS_ENABLE_STDCALL -#define BOOST_CLBL_TRTS_CC_TAG stdcall_tag -#define BOOST_CLBL_TRTS_VARARGS_CC BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#define BOOST_CLBL_TRTS_CC __stdcall -#include <boost/callable_traits/detail/unguarded/pmf.hpp> -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_STDCALL - -// Defining this macro enables undocumented features, likely broken. -// Too much work to officially maintain, but knock yourself out -#ifdef BOOST_CLBL_TRTS_ENABLE_FASTCALL -#define BOOST_CLBL_TRTS_CC_TAG fastcall_tag -#define BOOST_CLBL_TRTS_VARARGS_CC BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC -#define BOOST_CLBL_TRTS_CC __fastcall -#include <boost/callable_traits/detail/unguarded/pmf.hpp> -#undef BOOST_CLBL_TRTS_CC -#undef BOOST_CLBL_TRTS_CC_TAG -#undef BOOST_CLBL_TRTS_VARARGS_CC -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_FASTCALL - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_PMF_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/polyfills/disjunction.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/polyfills/disjunction.hpp deleted file mode 100644 index dc4f65c7c..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/polyfills/disjunction.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright Barrett Adair 2015-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_POLYFILLS_DISJUNCTION_HPP -#define BOOST_CLBL_TRTS_DETAIL_POLYFILLS_DISJUNCTION_HPP - -#undef BOOST_CLBL_TRTS_DISJUNCTION -#define BOOST_CLBL_TRTS_DISJUNCTION(...) \ - ::boost::callable_traits::detail::disjunction<__VA_ARGS__> - -namespace boost { namespace callable_traits { namespace detail { - -//polyfill for C++17 std::disjunction -template<typename...> -struct disjunction : std::false_type {}; - -template<typename T> -struct disjunction<T> : T {}; - -template<typename T, typename... Ts> -struct disjunction<T, Ts...> - : std::conditional<T::value != false, T, disjunction<Ts...>>::type {}; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_POLYFILLS_DISJUNCTION_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/polyfills/make_index_sequence.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/polyfills/make_index_sequence.hpp deleted file mode 100644 index a4a6e820c..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/polyfills/make_index_sequence.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright Barrett Adair 2016-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_POLYFILLS_MAKE_INDEX_SEQUENCE_HPP -#define BOOST_CLBL_TRTS_DETAIL_POLYFILLS_MAKE_INDEX_SEQUENCE_HPP - -#undef BOOST_CLBL_TRTS_IX_SEQ -#define BOOST_CLBL_TRTS_IX_SEQ(...) \ - ::boost::callable_traits::detail::index_sequence<__VA_ARGS__> - -#undef BOOST_CLBL_TRTS_MAKE_IX_SEQ -#define BOOST_CLBL_TRTS_MAKE_IX_SEQ(...) \ - ::boost::callable_traits::detail::make_index_sequence<__VA_ARGS__> - -namespace boost { namespace callable_traits { namespace detail { - -template<std::size_t...> -struct index_sequence { using type = index_sequence; }; - -template<typename, typename> -struct concat; - -template<std::size_t... I1, std::size_t... I2> -struct concat<index_sequence<I1...>, index_sequence<I2...>> - : index_sequence<I1..., (sizeof...(I1)+I2)...> {}; - -template<std::size_t N> - struct make_index_sequence_t; - -template<std::size_t N> -struct make_index_sequence_t : concat< - typename make_index_sequence_t<N/2>::type, - typename make_index_sequence_t<N - N/2>::type >::type {}; - -template<> -struct make_index_sequence_t<0> : index_sequence<> {}; - -template<> -struct make_index_sequence_t<1> : index_sequence<0> {}; - -template<std::size_t... I> -using make_index_sequence = typename make_index_sequence_t<I...>::type; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_POLYFILLS_MAKE_INDEX_SEQUENCE_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/qualifier_flags.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/qualifier_flags.hpp deleted file mode 100644 index f69d246c4..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/qualifier_flags.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -Defines `qualifier_flags` - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_QUALIFIER_FLAGS_HPP -#define BOOST_CLBL_TRTS_QUALIFIER_FLAGS_HPP - -#include <boost/callable_traits/detail/config.hpp> - -namespace boost { namespace callable_traits { namespace detail { - -//bit qualifier_flags used to signify cv/ref qualifiers -using qualifier_flags = std::uint32_t; - -/* - | && & V C | --------------------------------------------- -0 | 0 0 0 0 | default -1 | 0 0 0 1 | const -2 | 0 0 1 0 | volatile -3 | 0 0 1 1 | const volatile --------------------------------------------- -4 | 0 1 0 0 | & -5 | 0 1 0 1 | const & -6 | 0 1 1 0 | volatile & -7 | 0 1 1 1 | const volatile & --------------------------------------------- -8 | 1 0 0 0 | && -9 | 1 0 0 1 | const && -10 | 1 0 1 0 | volatile && -11 | 1 0 1 1 | const volatile && - -*/ - -// Flag representing the default qualifiers on a type -// or member function overload. -constexpr qualifier_flags default_ = 0; - -// Flag representing a const qualifier on a type or -// member function overload. -constexpr qualifier_flags const_ = 1; - -// Flag representing a volatile qualifier on a type -// or member function overload. -constexpr qualifier_flags volatile_ = 2; - -#ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -constexpr qualifier_flags lref_ = default_; -constexpr qualifier_flags rref_ = default_; -#else - -// Flag representing an lvalue reference type, or -// an lvalue-reference-qualified member function -// overload. -constexpr qualifier_flags lref_ = 4; - -// Flag representing an lvalue reference type, or -// an rvalue-reference-qualified member function -// overload. -constexpr qualifier_flags rref_ = 8; - -#endif //#ifdef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -constexpr qualifier_flags cv_ = 3; - -template<qualifier_flags Flags> -using remove_const_flag = std::integral_constant< - qualifier_flags, Flags & ~const_>; - -template<qualifier_flags Flags> -using is_const = std::integral_constant<bool, - (Flags & const_) != 0>; - -template<qualifier_flags Flags> -using remove_volatile_flag = std::integral_constant< - qualifier_flags, Flags & ~volatile_>; - -template<typename U, typename T = typename std::remove_reference<U>::type> -using cv_of = std::integral_constant<qualifier_flags, - (std::is_const<T>::value ? const_ : default_) - | (std::is_volatile<T>::value ? volatile_ : default_)>; - -template<typename T> -using ref_of = std::integral_constant<qualifier_flags, - std::is_rvalue_reference<T>::value ? rref_ - : (std::is_lvalue_reference<T>::value ? lref_ - : default_)>; - -//bit-flag implementation of C++11 reference collapsing rules -template<qualifier_flags Existing, - qualifier_flags Other, - bool AlreadyHasRef = (Existing & (lref_ | rref_)) != 0, - bool AlreadyHasLRef = (Existing & lref_) == lref_, - bool IsAddingLRef = (Other & lref_) == lref_ -> -using collapse_flags = std::integral_constant<qualifier_flags, - !AlreadyHasRef ? (Existing | Other) - : (AlreadyHasLRef ? (Existing | (Other & ~rref_)) - : (IsAddingLRef ? ((Existing & ~rref_) | Other ) - : (Existing | Other)))>; - -template<typename T> struct flag_map { static constexpr qualifier_flags value = default_; }; -template<typename T> struct flag_map<T &> { static constexpr qualifier_flags value = lref_; }; -template<typename T> struct flag_map<T &&> { static constexpr qualifier_flags value = rref_; }; -template<typename T> struct flag_map<T const> { static constexpr qualifier_flags value = const_; }; -template<typename T> struct flag_map<T const &> { static constexpr qualifier_flags value = const_ | lref_; }; -template<typename T> struct flag_map<T const &&> { static constexpr qualifier_flags value = const_ | rref_; }; -template<typename T> struct flag_map<T volatile> { static constexpr qualifier_flags value = volatile_; }; -template<typename T> struct flag_map<T volatile &> { static constexpr qualifier_flags value = volatile_ | lref_; }; -template<typename T> struct flag_map<T volatile &&> { static constexpr qualifier_flags value = volatile_ | rref_; }; -template<typename T> struct flag_map<T const volatile> { static constexpr qualifier_flags value = const_ | volatile_; }; -template<typename T> struct flag_map<T const volatile &> { static constexpr qualifier_flags value = const_ | volatile_ | lref_; }; -template<typename T> struct flag_map<T const volatile &&> { static constexpr qualifier_flags value = const_ | volatile_ | rref_; }; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_QUALIFIER_FLAGS_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/set_function_qualifiers.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/set_function_qualifiers.hpp deleted file mode 100644 index 9dc7f405a..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/set_function_qualifiers.hpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_SET_FUNCTION_QUALIFIERS_HPP -#define BOOST_CLBL_TRTS_DETAIL_SET_FUNCTION_QUALIFIERS_HPP - -#include <boost/callable_traits/detail/qualifier_flags.hpp> - -#define BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(QUAL) \ -template<typename Return, typename... Args> \ -struct set_function_qualifiers_t < \ - flag_map<int QUAL>::value, false, false, Return, Args...> { \ - using type = Return(Args...) QUAL; \ -}; \ - \ -template<typename Return, typename... Args> \ -struct set_function_qualifiers_t < \ - flag_map<int QUAL>::value, true, false, Return, Args...> { \ - using type = Return(Args...) QUAL \ - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER; \ -}; \ - \ -template<typename Return, typename... Args> \ -struct set_function_qualifiers_t < \ - flag_map<int QUAL>::value, false, true, Return, Args...> { \ - using type = Return(Args...) QUAL \ - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; \ -}; \ - \ -template<typename Return, typename... Args> \ -struct set_function_qualifiers_t < \ - flag_map<int QUAL>::value, true, true, Return, Args...> { \ - using type = Return(Args...) QUAL \ - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER \ - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; \ -}; \ - \ -template<typename Return, typename... Args> \ -struct set_varargs_function_qualifiers_t < \ - flag_map<int QUAL>::value, false, false, Return, Args...> { \ - using type = Return(Args..., ...) QUAL; \ -}; \ - \ -template<typename Return, typename... Args> \ -struct set_varargs_function_qualifiers_t < \ - flag_map<int QUAL>::value, true, false, Return, Args...> { \ - using type = Return(Args..., ...) QUAL \ - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER; \ -}; \ - \ -template<typename Return, typename... Args> \ -struct set_varargs_function_qualifiers_t < \ - flag_map<int QUAL>::value, false, true, Return, Args...> { \ - using type = Return(Args..., ...) QUAL \ - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; \ -}; \ - \ -template<typename Return, typename... Args> \ -struct set_varargs_function_qualifiers_t < \ - flag_map<int QUAL>::value, true, true, Return, Args...> { \ - using type = Return(Args..., ...) QUAL \ - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER \ - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; \ -} \ -/**/ - -namespace boost { namespace callable_traits { namespace detail { - - template<qualifier_flags Applied, bool IsTransactionSafe, - bool IsNoexcept, typename Return, typename... Args> - struct set_function_qualifiers_t { - using type = Return(Args...); - }; - - template<qualifier_flags Applied, bool IsTransactionSafe, - bool IsNoexcept, typename Return, typename... Args> - struct set_varargs_function_qualifiers_t { - using type = Return(Args..., ...); - }; - -#ifndef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(volatile); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const volatile); - -#ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(&); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(&&); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const &); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const &&); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(volatile &); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(volatile &&); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const volatile &); - BOOST_CLBL_TRTS_SET_FUNCTION_QUALIFIERS(const volatile &&); - -#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS -#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - template<qualifier_flags Flags, bool IsTransactionSafe, bool IsNoexcept, - typename... Ts> - using set_function_qualifiers = - typename set_function_qualifiers_t<Flags, IsTransactionSafe, IsNoexcept, - Ts...>::type; - - template<qualifier_flags Flags, bool IsTransactionSafe, bool IsNoexcept, - typename... Ts> - using set_varargs_function_qualifiers = - typename set_varargs_function_qualifiers_t<Flags, IsTransactionSafe, - IsNoexcept, Ts...>::type; - -}}} // namespace boost::callable_traits::detail - -#endif //BOOST_CLBL_TRTS_DETAIL_SET_FUNCTION_QUALIFIERS_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/sfinae_errors.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/sfinae_errors.hpp deleted file mode 100644 index 485d17259..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/sfinae_errors.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* -@Copyright Barrett Adair 2016-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_SFINAE_ERRORS_HPP -#define BOOST_CLBL_TRTS_SFINAE_ERRORS_HPP - -#include <boost/callable_traits/detail/config.hpp> - -namespace boost { namespace callable_traits { namespace detail { - - struct sfinae_error{}; - - template<typename T> - struct success { - static constexpr bool value = true; - struct _ { using type = T; }; - }; - - template<bool B, typename T> - struct fail_if : T { - static_assert(std::is_base_of<sfinae_error, T>::value, - "incorrect usage of fail_if"); - - static constexpr bool value = B; - }; - - template<typename T, typename... FailIfs> - using sfinae_try = typename BOOST_CLBL_TRTS_DISJUNCTION( - FailIfs..., success<T>)::_::type; - - template<typename FailMsg, typename ForceTwoPhaseLookup> - struct fail { - using type = typename std::conditional<std::is_same<ForceTwoPhaseLookup, std::false_type>::value, - FailMsg, FailMsg>::type::_::type; - }; - -}}} // namespace boost::callable_traits::detail - -#define BOOST_CLBL_TRTS_PP_CAT_(x, y) x ## y -#define BOOST_CLBL_TRTS_PP_CAT(x, y) BOOST_CLBL_TRTS_PP_CAT_(x, y) - -#define BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(origin) \ -namespace error { \ - template<typename ErrorMessage> \ - struct origin : \ - ::boost::callable_traits::detail::sfinae_error \ - { struct _ {}; }; \ -} \ -/**/ - -#define BOOST_CLBL_TRTS_SFINAE_MSG(origin, name) \ -struct BOOST_CLBL_TRTS_PP_CAT(name, _ ){}; \ -struct name : error::origin< \ - BOOST_CLBL_TRTS_PP_CAT(name, _ )>{}; \ -/**/ - -namespace boost { namespace callable_traits { - - BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(parameters) - BOOST_CLBL_TRTS_SFINAE_MSG(parameters, index_out_of_range_for_parameter_list) - BOOST_CLBL_TRTS_SFINAE_MSG(parameters, cannot_determine_parameters_for_this_type) - - BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(varargs) - BOOST_CLBL_TRTS_SFINAE_MSG(varargs, varargs_are_illegal_for_this_type) - - BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(member_qualifiers) - BOOST_CLBL_TRTS_SFINAE_MSG(member_qualifiers, member_qualifiers_are_illegal_for_this_type) - BOOST_CLBL_TRTS_SFINAE_MSG(member_qualifiers, this_compiler_doesnt_support_abominable_function_types) - - BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(transaction_safe_) - BOOST_CLBL_TRTS_SFINAE_MSG(transaction_safe_, transaction_safe_is_not_supported_by_this_configuration) - - BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(expand_args) - BOOST_CLBL_TRTS_SFINAE_MSG(expand_args, cannot_expand_the_parameter_list_of_first_template_argument) - - BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(member_pointer_required) - BOOST_CLBL_TRTS_SFINAE_MSG(member_pointer_required, type_is_not_a_member_pointer) - - BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(reference_error) - BOOST_CLBL_TRTS_SFINAE_MSG(reference_error, reference_type_not_supported_by_this_metafunction) - -}} // namespace boost::callable_traits - -#endif // #ifndef BOOST_CLBL_TRTS_SFINAE_ERRORS_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/traits.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/traits.hpp deleted file mode 100644 index e5a587f0b..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/traits.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_TRAITS_HPP -#define BOOST_CLBL_TRTS_DETAIL_TRAITS_HPP - -#include <boost/callable_traits/detail/forward_declarations.hpp> -#include <boost/callable_traits/detail/utility.hpp> - -namespace boost { namespace callable_traits { namespace detail { - - // Here is where the magic happens - template<typename T> - using traits = typename BOOST_CLBL_TRTS_DISJUNCTION( - function_object<unwrap_reference<T>>, - function<T>, - pmf<T>, - pmd<T>, - default_callable_traits<T> - )::traits; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_TRAITS_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function.hpp deleted file mode 100644 index a1d32e90a..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY -*/ - -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::false_type -#include <boost/callable_traits/detail/unguarded/function_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - -#ifdef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::true_type -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE transaction_safe -#include <boost/callable_traits/detail/unguarded/function_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_2.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_2.hpp deleted file mode 100644 index 562b4e933..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_2.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY -*/ - -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::false_type -#include <boost/callable_traits/detail/unguarded/function_3.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT - -#ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC noexcept -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::true_type -#include <boost/callable_traits/detail/unguarded/function_3.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_3.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_3.hpp deleted file mode 100644 index 2c329c411..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_3.hpp +++ /dev/null @@ -1,260 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -macros used: - -BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - the function-level qualifiers for the - current inclusion (combinations of `const` `volatile` `&` `&&`, or nothing) - -BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - the transaction_safe specifier for - the current include (`transaction_safe` or nothing) - -BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE is `transaction_safe` - -BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - `transaction_safe` when - BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE is enabled, otherwise nothing - -BOOST_CLBL_TRTS_NOEXCEPT_SPEC - the noexcept specifier for - the current include (`noexcept` or nothing) - -BOOST_CLBL_TRTS_IS_NOEXCEPT - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_NOEXCEPT_SPEC is `noexcept` - -BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER - `noexcept` if - BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES is defined, otherwise nothing - -*/ - -template<typename Return, typename... Args> -struct function<Return(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC> - : default_callable_traits<dummy BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS> { - - static constexpr bool value = true; - - using traits = function; - - using return_type = Return; - - using arg_types = std::tuple<Args...>; - using non_invoke_arg_types = arg_types; - - using type = Return(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using function_type = Return(Args...); - - using qualified_function_type = Return(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using remove_varargs = type; - - using add_varargs = Return (Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using is_noexcept = BOOST_CLBL_TRTS_IS_NOEXCEPT; - - using remove_noexcept = Return(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE; - - using add_noexcept = Return(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; - - using is_transaction_safe = BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE; - - using remove_transaction_safe = Return(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using add_transaction_safe = Return(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using qualifiers = default_callable_traits<dummy BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>; - - template<qualifier_flags Flags> - using set_qualifiers = set_function_qualifiers<Flags, is_transaction_safe::value, - is_noexcept::value, Return, Args...>; - - #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - using add_member_lvalue_reference = abominable_functions_not_supported_on_this_compiler; - using add_member_rvalue_reference = abominable_functions_not_supported_on_this_compiler; - using add_member_const = abominable_functions_not_supported_on_this_compiler; - using add_member_volatile = abominable_functions_not_supported_on_this_compiler; - using add_member_cv = abominable_functions_not_supported_on_this_compiler; - - #else - - using add_member_lvalue_reference = set_qualifiers< - collapse_flags<qualifiers::q_flags, lref_>::value>; - - using add_member_rvalue_reference = set_qualifiers< - collapse_flags<qualifiers::q_flags, rref_>::value>; - - using add_member_const = set_qualifiers<qualifiers::q_flags | const_>; - - using add_member_volatile = set_qualifiers<qualifiers::q_flags | volatile_>; - - using add_member_cv = set_qualifiers<qualifiers::q_flags | cv_>; - - #endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - using remove_member_reference = set_qualifiers<qualifiers::cv_flags>; - - using remove_member_const = set_qualifiers< - qualifiers::ref_flags | remove_const_flag<qualifiers::cv_flags>::value>; - - using remove_member_volatile = set_qualifiers< - qualifiers::ref_flags | remove_volatile_flag<qualifiers::cv_flags>::value>; - - using remove_member_cv = set_qualifiers<qualifiers::ref_flags>; - - template<typename U> - using apply_member_pointer = add_member_pointer<type, U>; - - template<typename NewReturn> - using apply_return = NewReturn(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<template<class...> class Container> - using expand_args = Container<Args...>; - - using is_member_pointer = std::false_type; -}; - - -template<typename Return, typename... Args> -struct function<Return (Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC> - : default_callable_traits<dummy BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS> { - - static constexpr bool value = true; - - using has_varargs = std::true_type; - using traits = function; - using return_type = Return; - using arg_types = std::tuple<Args...>; - - using type = Return (Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using function_type = Return(Args..., ...); - - using qualified_function_type = Return(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using remove_varargs = Return (Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using add_varargs = type; - - using is_noexcept = BOOST_CLBL_TRTS_IS_NOEXCEPT; - - using remove_noexcept = Return(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE; - - using add_noexcept = Return(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; - - using is_transaction_safe = BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE; - - using remove_transaction_safe = Return(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using add_transaction_safe = Return(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using qualifiers = default_callable_traits<dummy BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>; - - template<qualifier_flags Flags> - using set_qualifiers = set_varargs_function_qualifiers<Flags, is_transaction_safe::value, - is_noexcept::value, Return, Args...>; - - #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - using add_member_lvalue_reference = abominable_functions_not_supported_on_this_compiler; - using add_member_rvalue_reference = abominable_functions_not_supported_on_this_compiler; - using add_member_const = abominable_functions_not_supported_on_this_compiler; - using add_member_volatile = abominable_functions_not_supported_on_this_compiler; - using add_member_cv = abominable_functions_not_supported_on_this_compiler; - - #else - - using add_member_lvalue_reference = set_qualifiers< - collapse_flags<qualifiers::q_flags, lref_>::value>; - - using add_member_rvalue_reference = set_qualifiers< - collapse_flags<qualifiers::q_flags, rref_>::value>; - - using add_member_const = set_qualifiers<qualifiers::q_flags | const_>; - - using add_member_volatile = set_qualifiers<qualifiers::q_flags | volatile_>; - - using add_member_cv = set_qualifiers<qualifiers::q_flags | cv_>; - - #endif // #ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS - - using remove_member_reference = set_qualifiers<qualifiers::cv_flags>; - - using remove_member_const = set_qualifiers< - qualifiers::ref_flags | remove_const_flag<qualifiers::cv_flags>::value>; - - using remove_member_volatile = set_qualifiers< - qualifiers::ref_flags | remove_volatile_flag<qualifiers::cv_flags>::value>; - - using remove_member_cv = set_qualifiers<qualifiers::ref_flags>; - - template<typename U> - using apply_member_pointer = - Return( BOOST_CLBL_TRTS_DEFAULT_VARARGS_CC U::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<typename NewReturn> - using apply_return = NewReturn(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<template<class...> class Container> - using expand_args = Container<Args...>; - - using is_member_pointer = std::false_type; -}; diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr.hpp deleted file mode 100644 index 4aa8ad593..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright (c) 2016 Modified Work Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY -*/ - -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::false_type -#include <boost/callable_traits/detail/unguarded/function_ptr_2.hpp> - -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - -#ifdef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::true_type -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE transaction_safe -#include <boost/callable_traits/detail/unguarded/function_ptr_2.hpp> -#endif - -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_2.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_2.hpp deleted file mode 100644 index b54f2ed80..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_2.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY -*/ - -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::false_type -#include <boost/callable_traits/detail/unguarded/function_ptr_3.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT - -#ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC noexcept -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::true_type -#include <boost/callable_traits/detail/unguarded/function_ptr_3.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_3.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_3.hpp deleted file mode 100644 index e657b57ef..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_3.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright (c) 2016 Modified Work Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -macros used: - -BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - the transaction_safe specifier for - the current include (`transaction_safe` or nothing) - -BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE is `transaction_safe` - -BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - `transaction_safe` when - BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE is enabled, otherwise nothing - -BOOST_CLBL_TRTS_NOEXCEPT_SPEC - the noexcept specifier for - the current include (`noexcept` or nothing) - -BOOST_CLBL_TRTS_IS_NOEXCEPT - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_NOEXCEPT_SPEC is `noexcept` - -BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER - `noexcept` if - BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES is defined, otherwise nothing -*/ - -template<typename Return, typename... Args> -struct function< - BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_CC *)(Args...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC> - : default_callable_traits<> { - - static constexpr bool value = true; - - using traits = function; - - using return_type = Return; - - using arg_types = std::tuple<Args...>; - using non_invoke_arg_types = arg_types; - - using type = BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_CC *)(Args...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE; - - using function_type = Return(Args...); - using qualified_function_type = function_type; - using remove_varargs = type; - - using add_varargs = - BOOST_CLBL_TRTS_ST Return (BOOST_CLBL_TRTS_VARARGS_CC *)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using is_noexcept = BOOST_CLBL_TRTS_IS_NOEXCEPT; - - using remove_noexcept = Return(BOOST_CLBL_TRTS_CC *)(Args...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE; - - using add_noexcept = Return(BOOST_CLBL_TRTS_CC *)(Args...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; - - using is_transaction_safe = BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE; - - using remove_transaction_safe = Return(BOOST_CLBL_TRTS_CC *)(Args...) - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using add_transaction_safe = Return(BOOST_CLBL_TRTS_CC *)(Args...) - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<typename U> - using apply_member_pointer = - BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_CC U::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<typename NewReturn> - using apply_return = - BOOST_CLBL_TRTS_ST NewReturn(BOOST_CLBL_TRTS_CC *)(Args...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<template<class...> class Container> - using expand_args = Container<Args...>; - - using is_member_pointer = std::false_type; -}; - diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs.hpp deleted file mode 100644 index 625f0d62e..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2016 Modified Work Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY -*/ - -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::false_type -#include <boost/callable_traits/detail/unguarded/function_ptr_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - -#ifdef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::true_type -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE transaction_safe -#include <boost/callable_traits/detail/unguarded/function_ptr_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_2.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_2.hpp deleted file mode 100644 index 9ed68fc13..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_2.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY -*/ - -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::false_type -#include <boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT - -#ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC noexcept -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::true_type -#include <boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp deleted file mode 100644 index 42e22931a..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/function_ptr_varargs_3.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright (c) 2016 Modified Work Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -macros used: - -BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - the transaction_safe specifier for - the current include (`transaction_safe` or nothing) - -BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE is `transaction_safe` - -BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - `transaction_safe` when - BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE is enabled, otherwise nothing - -BOOST_CLBL_TRTS_NOEXCEPT_SPEC - the noexcept specifier for - the current include (`noexcept` or nothing) - -BOOST_CLBL_TRTS_IS_NOEXCEPT - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_NOEXCEPT_SPEC is `noexcept` - -BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER - `noexcept` if - BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES is defined, otherwise nothing -*/ - -template<typename Return, typename... Args> -struct function<BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_VARARGS_CC *)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC> - : default_callable_traits<> { - - static constexpr bool value = true; - - using has_varargs = std::true_type; - - using traits = function; - - using return_type = Return; - - using arg_types = std::tuple<Args...>; - using non_invoke_arg_types = arg_types; - - using type = - BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_VARARGS_CC *)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using function_type = Return(Args..., ...); - - using qualified_function_type = function_type; - - using remove_varargs = - BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_CC *)(Args...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE; - - using add_varargs = type; - - using is_noexcept = BOOST_CLBL_TRTS_IS_NOEXCEPT; - - using remove_noexcept = BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_CC *)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE; - - using add_noexcept = BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_CC *)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; - - using is_transaction_safe = BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE; - - using remove_transaction_safe = Return(BOOST_CLBL_TRTS_VARARGS_CC *)(Args..., ...) - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using add_transaction_safe = Return(BOOST_CLBL_TRTS_VARARGS_CC *)(Args..., ...) - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<typename U> - using apply_member_pointer = - BOOST_CLBL_TRTS_ST Return(BOOST_CLBL_TRTS_VARARGS_CC U::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<typename NewReturn> - using apply_return = - BOOST_CLBL_TRTS_ST NewReturn(BOOST_CLBL_TRTS_VARARGS_CC *)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<template<class...> class Container> - using expand_args = Container<Args...>; - - using is_member_pointer = std::false_type; -}; - diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf.hpp deleted file mode 100644 index de9e7a34a..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright (c) 2001 Peter Dimov and Multi Media Ltd. -Copyright (c) 2016 Modified Work Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -*/ - -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \ - BOOST_CLBL_TRTS_ABOMINABLE_CONST -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \ - BOOST_CLBL_TRTS_ABOMINABLE_VOLATILE -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \ - BOOST_CLBL_TRTS_ABOMINABLE_CONST BOOST_CLBL_TRTS_ABOMINABLE_VOLATILE -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS & -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS & -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS && -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS && -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const & -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const & -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile & -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS volatile & -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile & -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const volatile & -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const && -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const && -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile && -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS volatile && -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile && -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const volatile && -#include <boost/callable_traits/detail/unguarded/pmf_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_2.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_2.hpp deleted file mode 100644 index e3568fb14..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_2.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -*/ - -template<typename Return, typename T, typename... Args> -struct set_member_function_qualifiers_t< - flag_map<int BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - false, // IsTransactionSafe - false, // IsNoexcept - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...> { - - using type = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS; -}; - -template<typename Return, typename T, typename... Args> -struct set_member_function_qualifiers_t< - flag_map<int BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - false, - true, - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...> { - - using type = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; -}; - -template<typename Return, typename T, typename... Args> -struct set_member_function_qualifiers_t< - flag_map<int BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - true, - false, - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...> { - - using type = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER; -}; - -template<typename Return, typename T, typename... Args> -struct set_member_function_qualifiers_t< - flag_map<int BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - true, - true, - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...> { - - using type = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; -}; - -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::false_type -#include <boost/callable_traits/detail/unguarded/pmf_3.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - -#ifdef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE - -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::true_type -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE transaction_safe -#include <boost/callable_traits/detail/unguarded/pmf_3.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_3.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_3.hpp deleted file mode 100644 index 62b34f2bc..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_3.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY -*/ - -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::false_type -#include <boost/callable_traits/detail/unguarded/pmf_4.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT - -#ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC noexcept -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::true_type -#include <boost/callable_traits/detail/unguarded/pmf_4.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_4.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_4.hpp deleted file mode 100644 index 5a1f48ce2..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_4.hpp +++ /dev/null @@ -1,147 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - the function-level qualifiers for the - current inclusion (combinations of `const` `volatile` `&` `&&`, or nothing) - -BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - the transaction_safe specifier for - the current include (`transaction_safe` or nothing) - -BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE is `transaction_safe` - -BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - `transaction_safe` when - BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE is defined, otherwise nothing - -BOOST_CLBL_TRTS_NOEXCEPT_SPEC - the noexcept specifier for - the current include (`noexcept` or nothing) - -BOOST_CLBL_TRTS_IS_NOEXCEPT - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_NOEXCEPT_SPEC is `noexcept` - -BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER - `noexcept` if - BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES is defined, otherwise nothing -*/ - -template<typename Return, typename T, typename... Args> -struct pmf<Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC> - : default_callable_traits<dummy BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS> { - - static constexpr bool value = true; - - using traits = pmf; - - using return_type = Return; - - using type = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using invoke_type = typename std::conditional< - std::is_rvalue_reference<T BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - T BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS, - typename std::add_lvalue_reference<T BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::type - >::type; - - using arg_types = std::tuple<invoke_type, Args...>; - using non_invoke_arg_types = std::tuple<Args...>; - - using function_object_signature = Return(Args...); - - using function_type = Return(invoke_type, Args...); - - using qualified_function_type = Return(Args...) - BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using remove_varargs = type; - - using add_varargs = - Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using is_noexcept = BOOST_CLBL_TRTS_IS_NOEXCEPT; - - using remove_noexcept = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE; - - using add_noexcept = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; - - using is_transaction_safe = BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE; - - using remove_transaction_safe = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using add_transaction_safe = Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using class_type = T; - - using qualifiers = default_callable_traits<dummy BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>; - - template<qualifier_flags Flags> - using set_qualifiers = set_member_function_qualifiers< - Flags, is_transaction_safe::value, is_noexcept::value, - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...>; - - using remove_member_reference = set_qualifiers<qualifiers::cv_flags>; - - using add_member_lvalue_reference = set_qualifiers< - collapse_flags<qualifiers::q_flags, lref_>::value>; - - using add_member_rvalue_reference = set_qualifiers< - collapse_flags<qualifiers::q_flags, rref_>::value>; - - using add_member_const = set_qualifiers<qualifiers::q_flags | const_>; - - using add_member_volatile = set_qualifiers<qualifiers::q_flags | volatile_>; - - using add_member_cv = set_qualifiers<qualifiers::q_flags | cv_>; - - using remove_member_const = set_qualifiers< - qualifiers::ref_flags | remove_const_flag<qualifiers::cv_flags>::value>; - - using remove_member_volatile = set_qualifiers< - qualifiers::ref_flags | remove_volatile_flag<qualifiers::cv_flags>::value>; - - using remove_member_cv = set_qualifiers<qualifiers::ref_flags>; - - template<typename U> - using apply_member_pointer = - Return(BOOST_CLBL_TRTS_CC U::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<typename NewReturn> - using apply_return = - NewReturn(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<template<class...> class Container> - using expand_args = Container<invoke_type, Args...>; - - using is_member_pointer = std::true_type; -}; diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs.hpp deleted file mode 100644 index bd40f2bdf..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -*/ - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \ - BOOST_CLBL_TRTS_ABOMINABLE_CONST -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \ - BOOST_CLBL_TRTS_ABOMINABLE_VOLATILE -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS \ - BOOST_CLBL_TRTS_ABOMINABLE_CONST BOOST_CLBL_TRTS_ABOMINABLE_VOLATILE -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS & -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS & -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS && -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS && -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const & -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const & -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile & -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS volatile & -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile & -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const volatile & -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const && -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const && -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS volatile && -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS volatile && -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#define BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS const volatile && -#define BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS const volatile && -#include <boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp> -#undef BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS -#undef BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - -#endif // #ifndef BOOST_CLBL_TRTS_DISABLE_REFERENCE_QUALIFIERS \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp deleted file mode 100644 index 5de066819..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_2.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -*/ - -template<typename T, typename Return, typename... Args> -struct set_varargs_member_function_qualifiers_t < - flag_map<int BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - false, // IsTransactionSafe - false, // IsNoexcept - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...> { - - using type = - Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS; -}; - -template<typename T, typename Return, typename... Args> -struct set_varargs_member_function_qualifiers_t < - flag_map<int BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - false, - true, - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...> { - - using type = - Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; -}; - -template<typename T, typename Return, typename... Args> -struct set_varargs_member_function_qualifiers_t < - flag_map<int BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - true, - false, - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...> { - - using type = - Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER; -}; - -template<typename T, typename Return, typename... Args> -struct set_varargs_member_function_qualifiers_t < - flag_map<int BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - true, - true, - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...> { - - using type = - Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; -}; - -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::false_type -#include <boost/callable_traits/detail/unguarded/pmf_varargs_3.hpp> - -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - -#ifdef BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE - -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE std::true_type -#define BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE transaction_safe -#include <boost/callable_traits/detail/unguarded/pmf_varargs_3.hpp> -#endif - -#undef BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE -#undef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_3.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_3.hpp deleted file mode 100644 index 905a5a6d9..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_3.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY -*/ - -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::false_type -#include <boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT - -#ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES -#define BOOST_CLBL_TRTS_NOEXCEPT_SPEC noexcept -#define BOOST_CLBL_TRTS_IS_NOEXCEPT std::true_type -#include <boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp> -#undef BOOST_CLBL_TRTS_NOEXCEPT_SPEC -#undef BOOST_CLBL_TRTS_IS_NOEXCEPT -#endif // #ifdef BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp deleted file mode 100644 index ca33ebf96..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/unguarded/pmf_varargs_4.hpp +++ /dev/null @@ -1,149 +0,0 @@ -/* -Copyright (c) 2016 Barrett Adair - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -HEADER GUARDS INTENTIONALLY OMITTED -DO NOT INCLUDE THIS HEADER DIRECTLY - -BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - the function-level qualifiers for the - current inclusion (combinations of `const` `volatile` `&` `&&`, or nothing) - -BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - the transaction_safe specifier for - the current include (`transaction_safe` or nothing) - -BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE is `transaction_safe` - -BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - `transaction_safe` when - BOOST_CLBL_TRTS_ENABLE_TRANSACTION_SAFE is enabled, otherwise nothing - -BOOST_CLBL_TRTS_NOEXCEPT_SPEC - the noexcept specifier for - the current include (`noexcept` or nothing) - -BOOST_CLBL_TRTS_IS_NOEXCEPT - `std::true_type` or `std::false_type`, - tied on whether BOOST_CLBL_TRTS_NOEXCEPT_SPEC is `noexcept` - -BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER - `noexcept` if - BOOST_CLBL_TRTS_ENABLE_NOEXCEPT_TYPES is defined, otherwise nothing -*/ - -template<typename Return, typename T, typename... Args> -struct pmf<Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC> - : default_callable_traits<dummy BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS> { - - static constexpr bool value = true; - - using has_varargs = std::true_type; - - using traits = pmf; - - using return_type = Return; - - using type = Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using invoke_type = typename std::conditional< - std::is_rvalue_reference<T BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::value, - T BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS, - typename std::add_lvalue_reference<T BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>::type - >::type; - - using arg_types = std::tuple<invoke_type, Args...>; - using non_invoke_arg_types = std::tuple<Args...>; - - using function_object_signature = Return(Args..., ...); - - using function_type = Return(invoke_type, Args..., ...); - - using qualified_function_type = Return(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_ABOMINABLE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using remove_varargs = - Return(BOOST_CLBL_TRTS_CC T::*)(Args...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using add_varargs = type; - - using is_noexcept = BOOST_CLBL_TRTS_IS_NOEXCEPT; - - using remove_noexcept = Return(BOOST_CLBL_TRTS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE; - - using add_noexcept = Return(BOOST_CLBL_TRTS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPECIFIER; - - using is_transaction_safe = BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE; - - using remove_transaction_safe = Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using add_transaction_safe = Return(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_TRANSACTION_SAFE_SPECIFIER - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - using class_type = T; - - using qualifiers = default_callable_traits<dummy BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS>; - - template<qualifier_flags Flags> - using set_qualifiers = set_varargs_member_function_qualifiers< - Flags, is_transaction_safe::value, is_noexcept::value, - BOOST_CLBL_TRTS_CC_TAG, T, Return, Args...>; - - using remove_member_reference = set_qualifiers<qualifiers::cv_flags>; - - using add_member_lvalue_reference = set_qualifiers< - collapse_flags<qualifiers::q_flags, lref_>::value>; - - using add_member_rvalue_reference = set_qualifiers< - collapse_flags<qualifiers::q_flags, rref_>::value>; - - using add_member_const = set_qualifiers<qualifiers::q_flags | const_>; - - using add_member_volatile = set_qualifiers<qualifiers::q_flags | volatile_>; - - using add_member_cv = set_qualifiers<qualifiers::q_flags | cv_>; - - using remove_member_const = set_qualifiers< - qualifiers::ref_flags | remove_const_flag<qualifiers::cv_flags>::value>; - - using remove_member_volatile = set_qualifiers< - qualifiers::ref_flags | remove_volatile_flag<qualifiers::cv_flags>::value>; - - using remove_member_cv = set_qualifiers<qualifiers::ref_flags>; - - template<typename U> - using apply_member_pointer = - Return(BOOST_CLBL_TRTS_VARARGS_CC U::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<typename NewReturn> - using apply_return = - NewReturn(BOOST_CLBL_TRTS_VARARGS_CC T::*)(Args..., ...) - BOOST_CLBL_TRTS_INCLUDE_QUALIFIERS - BOOST_CLBL_TRTS_INCLUDE_TRANSACTION_SAFE - BOOST_CLBL_TRTS_NOEXCEPT_SPEC; - - template<template<class...> class Container> - using expand_args = Container<invoke_type, Args...>; - - using is_member_pointer = std::true_type; -}; diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/detail/utility.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/detail/utility.hpp deleted file mode 100644 index d5a28cc3c..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/detail/utility.hpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_DETAIL_UTILITY_HPP -#define BOOST_CLBL_TRTS_DETAIL_UTILITY_HPP - -#include <boost/callable_traits/detail/config.hpp> -#include <boost/callable_traits/detail/sfinae_errors.hpp> -#include <boost/callable_traits/detail/qualifier_flags.hpp> - -namespace boost { namespace callable_traits { namespace detail { - -struct cdecl_tag{}; -struct stdcall_tag{}; -struct fastcall_tag{}; -struct pascal_tag{}; - -struct invalid_type { invalid_type() = delete; }; -struct reference_error { reference_error() = delete; }; - -template<typename T> -using error_type = typename std::conditional< - std::is_reference<T>::value, reference_error, invalid_type>::type; - -#ifdef BOOST_CLBL_TRTS_DISABLE_ABOMINABLE_FUNCTIONS -struct abominable_functions_not_supported_on_this_compiler{}; -#endif - -// used to convey "this type doesn't matter" in code -struct dummy {}; - -// used as return type in failed SFINAE tests -struct substitution_failure : std::false_type{}; - -template<bool Value> -using bool_type = std::integral_constant<bool, Value>; - -// shorthand for std::tuple_element -template<std::size_t I, typename Tup> -using at = typename std::tuple_element<I, Tup>::type; - -template<typename T, typename Class> -using add_member_pointer = T Class::*; - -template<typename L, typename R, typename ErrorType> - using fail_when_same = fail_if<std::is_same<L, R>::value, ErrorType>; - -template<typename T, typename ErrorType, - typename U = typename std::remove_reference<T>::type> -using try_but_fail_if_invalid = sfinae_try<T, - fail_when_same<U, invalid_type, ErrorType>, - fail_when_same<U, reference_error, - reference_type_not_supported_by_this_metafunction>>; - -template<typename T, typename ErrorType, - typename U = typename std::remove_reference<T>::type, - bool is_reference_error = std::is_same<reference_error, U>::value> -using fail_if_invalid = fail_if< - std::is_same<U, invalid_type>::value || is_reference_error, - typename std::conditional<is_reference_error, - reference_type_not_supported_by_this_metafunction, ErrorType>::type>; - -template<typename T, typename Fallback> -using fallback_if_invalid = typename std::conditional< - std::is_same<T, invalid_type>::value, Fallback, T>::type; - -template<typename T, template<class> class Alias, typename U = Alias<T>> -struct force_sfinae { - using type = U; -}; - -template<typename T> -using shallow_decay = typename std::remove_cv< - typename std::remove_reference<T>::type>::type; - -template<typename T> -struct is_reference_wrapper_t { - using type = std::false_type; -}; - -template<typename T> -struct is_reference_wrapper_t<std::reference_wrapper<T>> { - using type = std::true_type; -}; - -template<typename T> -using is_reference_wrapper = - typename is_reference_wrapper_t<shallow_decay<T>>::type; - -template<typename T, typename = std::true_type> -struct unwrap_reference_t { - using type = T; -}; - -template<typename T> -struct unwrap_reference_t<T, is_reference_wrapper<T>> { - using type = decltype(std::declval<T>().get()); -}; - -// removes std::reference_wrapper -template<typename T> -using unwrap_reference = typename unwrap_reference_t<T>::type; - -}}} // namespace boost::callable_traits::detail - -#endif // #ifndef BOOST_CLBL_TRTS_DETAIL_UTILITY_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/function_type.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/function_type.hpp deleted file mode 100644 index a3305f7bf..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/function_type.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_FUNCTION_TYPE_HPP -#define BOOST_CLBL_TRTS_FUNCTION_TYPE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ function_type_hpp -/*`[section:ref_function_type function_type] -[heading Header] -``#include <boost/callable_traits/function_type.hpp>`` -[heading Definition] -*/ - -template<typename T> -using function_type_t = //see below -//<- - detail::try_but_fail_if_invalid<typename detail::traits< - detail::shallow_decay<T>>::function_type, - cannot_determine_parameters_for_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct function_type_impl {}; - - template<typename T> - struct function_type_impl <T, typename std::is_same< - function_type_t<T>, detail::dummy>::type> - { - using type = function_type_t<T>; - }; -} - -//-> - -template<typename T> -struct function_type : detail::function_type_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be one of the following: - * function - * function pointer - * function reference - * member function pointer - * member data pointer - * user-defined type with a non-overloaded `operator()` - * type of a non-generic lambda - -[heading Behavior] -* When the constraints are violated, a substitution failure occurs. -* When `T` is a function, the aliased type is identical to `T`, except that the aliased function type will not have member qualifiers or the `transaction_safe` specifier. -* When `T` is a function pointer, the aliased type is equivalent to `std::remove_pointer_t<T>`. -* When `T` is a function reference, the aliased type is equivalent to `std::remove_reference_t<T>`. -* When `T` is a function object, the aliased type is a function type with the same return type and parameter list as `T`'s `operator()`. -* When `T` is a member function pointer, the aliased type is a function type with the same return type as `T`, and the first parameter is a reference to the parent class of `T`, qualified according to the member qualifiers on `T`. The subsequent parameters, if any, are the parameter types of `T`. -* When `T` is a member data pointer, the aliased type is a function type returning the underlying member type of `T`, taking a single parameter, which is a `const` reference to the parent type of `T`. -* In all cases, the aliased function type will not have member qualifiers, and will not have the `transaction_safe` specifier. - -[heading Input/Output Examples] -[table - [[`T`] [`function_type_t<T>`]] - [[`void(int)`] [`void(int)`]] - [[`void(int) const`] [`void(int)`]] - [[`void(int) transaction_safe`] [`void(int)`]] - [[`void(*const &)(int)`] [`void(int)`]] - [[`void(&)(int)`] [`void(int)`]] - [[`void(* volatile)()`] [`void()`]] - [[`int(foo::*)(int)`] [`int(foo&, int)`]] - [[`int(foo::*)(int) const`] [`int(const foo&, int)`]] - [[`void(foo::*)() volatile &&`] [`void(volatile foo&&)`]] - [[`int foo::*`] [`int(const foo&)`]] - [[`const int foo::*`] [`int(const foo&)`]] - [[`int`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/function_type.cpp] -[function_type] -[endsect] -*/ -//] - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/has_member_qualifiers.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/has_member_qualifiers.hpp deleted file mode 100644 index 3ab44d3b0..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/has_member_qualifiers.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_HAS_MEMBER_QUALIFIERS_HPP -#define BOOST_CLBL_TRTS_HAS_MEMBER_QUALIFIERS_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ has_member_qualifiers_hpp -/*`[section:ref_has_member_qualifiers has_member_qualifiers] -[heading Header] -``#include <boost/callable_traits/has_member_qualifiers.hpp>`` -[heading Definition] -*/ - -// inherits from either std::true_type or std::false_type -template<typename T> -struct has_member_qualifiers; - -//<- -template<typename T> -struct has_member_qualifiers : detail::traits< - detail::shallow_decay<T>>::has_member_qualifiers { - - using type = typename detail::traits< - detail::shallow_decay<T>>::has_member_qualifiers; -}; - -// older compilers don't support variable templates -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct has_member_qualifiers_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool has_member_qualifiers_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::has_member_qualifiers::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `std::false_type` is inherited by `has_member_qualifiers<T>` and is aliased by `typename has_member_qualifiers<T>::type`, except when one of the following criteria is met, in which case `std::true_type` would be similarly inherited and aliased: - * `T` is a function with member qualifiers - * `T` is a member function pointer with member qualifiers - * `T` is a function object with a member-qualified `operator()` -* On compilers that support variable templates, `has_member_qualifiers_v<T>` is equivalent to `has_member_qualifiers<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`has_member_qualifiers_v<T>`]] - [[`void() const`] [`true`]] - [[`void() const transaction_safe`] [`true`]] - [[`void() volatile &&`] [`true`]] - [[`int(foo::*)() &`] [`true`]] - [[`void(foo::*)() const`] [`true`]] - [[`void(foo::*&)() const`] [`true`]] - [[`void(foo::* const)() const`] [`true`]] - [[`void()`] [`false`]] - [[`void() transaction_safe`] [`false`]] - [[`void(*)()`] [`false`]] - [[`void(*&)()`] [`false`]] - [[`int`] [`false`]] - [[`const int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`const int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/has_member_qualifiers.cpp] -[has_member_qualifiers] -[endsect] -*/ -//] - -#endif //BOOST_CLBL_TRTS_HAS_MEMBER_QUALIFIERS_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/has_varargs.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/has_varargs.hpp deleted file mode 100644 index 7f7982417..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/has_varargs.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_HAS_VARARGS_HPP -#define BOOST_CLBL_TRTS_HAS_VARARGS_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ has_varargs_hpp -/*`[section:ref_has_varargs has_varargs] -[heading Header] -``#include <boost/callable_traits/has_varargs.hpp>`` -[heading Definition] -*/ - - -// inherits from either std::true_type or std::false_type -template<typename T> -struct has_varargs; - -//<- -template<typename T> -struct has_varargs : detail::traits< - detail::shallow_decay<T>>::has_varargs { - - using type = typename detail::traits< - detail::shallow_decay<T>>::has_varargs; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct has_varargs_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool has_varargs_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::has_varargs::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `std::false_type` is inherited by `has_varargs<T>` and is aliased by `typename has_varargs<T>::type`, except when one of the following criteria is met, in which case `std::true_type` would be similarly inherited and aliased: - * `T` is a function, function pointer, or function reference where the function's parameter list includes C-style variadics. - * `T` is a pointer to a member function with C-style variadics in the parameter list. - * `T` is a function object with a non-overloaded `operator()`, which has C-style variadics in the parameter list of its `operator()`. -* On compilers that support variable templates, `has_varargs_v<T>` is equivalent to `has_varargs<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`has_varargs_v<T>`]] - [[`void(...)`] [`true`]] - [[`void(int, ...) const`] [`true`]] - [[`void(* volatile)(...)`] [`true`]] - [[`void(&)(...)`] [`true`]] - [[`void(foo::*)(...) const`] [`true`]] - [[`void(*)()`] [`false`]] - [[`void(*&)()`] [`false`]] - [[`int`] [`false`]] - [[`const int`] [`false`]] - [[`int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/has_varargs.cpp] -[has_varargs] -[endsect] -*/ -//] - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/has_void_return.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/has_void_return.hpp deleted file mode 100644 index 06f80f3dd..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/has_void_return.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_HAS_VOID_RETURN_HPP -#define BOOST_CLBL_TRTS_HAS_VOID_RETURN_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ has_void_return_hpp -/*`[section:ref_has_void_return has_void_return] -[heading Header] -``#include <boost/callable_traits/has_void_return.hpp>`` -[heading Definition] -*/ - -// inherits from either std::true_type or std::false_type -template<typename T> -struct has_void_return; - -//<- -template<typename T> -struct has_void_return - : std::is_same<typename detail::traits< - detail::shallow_decay<T>>::return_type, void> {}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct has_void_return_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> - -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool has_void_return_v = //see below -//<- - std::is_same<typename detail::traits< - detail::shallow_decay<T>>::return_type, void>::value; - -#endif - -}} // namespace boost::callable_traits -//-> - - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `std::false_type` is inherited by `has_void_return<T>` and is aliased by `typename has_void_return<T>::type`, except when one of the following criteria is met, in which case `std::true_type` would be similarly inherited and aliased: - * `T` is a function, function pointer, or function reference where the function's return type is `void`. - * `T` is a pointer to a member function whose return type is `void`. - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` function returns `void`. -* On compilers that support variable templates, `has_void_return_v<T>` is equivalent to `has_void_return<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`has_void_return_v<T>`]] - [[`void()`] [`true`]] - [[`void(int) const`] [`true`]] - [[`void(* const &)()`] [`true`]] - [[`void(&)()`] [`true`]] - [[`void(foo::*)() const`] [`true`]] - [[`int(*)()`] [`false`]] - [[`int(*&)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`void* foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/has_void_return.cpp] -[has_void_return] -[endsect] -*/ -//] - -#endif diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_const_member.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_const_member.hpp deleted file mode 100644 index f0a7ad252..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_const_member.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_CONST_MEMBER_HPP -#define BOOST_CLBL_TRTS_IS_CONST_MEMBER_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ is_const_member_hpp -/*`[section:ref_is_const_member is_const_member] -[heading Header] -``#include <boost/callable_traits/is_const_member.hpp>`` -[heading Definition] -*/ - -// inherits from either std::true_type or std::false_type -template<typename T> -struct is_const_member; - -//<- -template<typename T> -struct is_const_member - : detail::traits<detail::shallow_decay<T>>::is_const_member { - using type = typename detail::traits< - detail::shallow_decay<T>>::is_const_member; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct is_const_member_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_const_member_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::is_const_member::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `is_const_member<T>::value` is `true` when either: - * `T` is a function type with a `const` member qualifier - * `T` is a pointer to a member function with a `const` member qualifier - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has a `const` member qualifier -* On compilers that support variable templates, `is_const_member_v<T>` is equivalent to `is_const_member<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`is_const_member_v<T>`]] - [[`int() const`] [`true`]] - [[`int() const volatile`] [`true`]] - [[`int() const & transaction_safe`] [`true`]] - [[`int() const &&`] [`true`]] - [[`int(foo::*&)() const`] [`true`]] - [[`int(foo::*)() const volatile`] [`true`]] - [[`int(foo::*)() const volatile &&`][`true`]] - [[`int(foo::* const)() const`] [`true`]] - [[`int()`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int() &&`] [`false`]] - [[`int(*)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`const int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/is_const_member.cpp] -[is_const_member] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_CONST_MEMBER_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_cv_member.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_cv_member.hpp deleted file mode 100644 index 6e95545ee..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_cv_member.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_CV_MEMBER_HPP -#define BOOST_CLBL_TRTS_IS_CV_MEMBER_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ is_cv_member_hpp -/*`[section:ref_is_cv_member is_cv_member] -[heading Header] -``#include <boost/callable_traits/is_cv_member.hpp>`` -[heading Definition] -*/ - -// inherits from either std::true_type or std::false_type -template<typename T> -struct is_cv_member; - -//<- -template<typename T> -struct is_cv_member - : detail::traits<detail::shallow_decay<T>>::is_cv_member { - using type = typename detail::traits< - detail::shallow_decay<T>>::is_cv_member; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct is_cv_member_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_cv_member_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::is_cv_member::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `is_cv_member<T>::value` is `true` when either: - * `T` is a function type with both `const` and `volatile` member qualifiers - * `T` is a pointer to a member function with both `const` and `volatile` member qualifiers - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has both `const` and `volatile` member qualifiers -* On compilers that support variable templates, `is_cv_member_v<T>` is equivalent to `is_cv_member<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`is_cv_member_v<T>`]] - [[`int() const volatile`] [`true`]] - [[`int() const volatile &`] [`true`]] - [[`int(foo::* const &)() const volatile`] [`true`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int(foo::*)() const`] [`false`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int() &&`] [`false`]] - [[`int(*)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`const int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/is_cv_member.cpp] -[is_cv_member] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_CV_MEMBER_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_invocable.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_invocable.hpp deleted file mode 100644 index 892d8fb71..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_invocable.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_HPP -#define BOOST_CLBL_TRTS_IS_INVOCABLE_HPP - -#include <boost/callable_traits/detail/core.hpp> -#include <boost/callable_traits/detail/is_invocable_impl.hpp> - -namespace boost { namespace callable_traits { - -//[ is_invocable_hpp -/*`[section:ref_is_invocable is_invocable] -[heading Header] -``#include <boost/callable_traits/is_invocable.hpp>`` -[heading Definition] -*/ - -// inherits from either std::true_type or std::false_type -template<typename T, typename... Args> -struct is_invocable; - -// inherits from either std::true_type or std::false_type -template<typename Ret, typename T, typename... Args> -struct is_invocable_r; - -//<- -template<typename T, typename... Args> -struct is_invocable : detail::is_invocable_impl<T, Args...>::type { - using type = typename detail::is_invocable_impl<T, Args...>::type; -}; - -template<typename Ret, typename T, typename... Args> -struct is_invocable_r - : detail::is_invocable_r_impl< - typename detail::is_invocable_impl<T, Args...>::type, Ret, T, Args...>::type -{ - using type = typename detail::is_invocable_r_impl< - typename detail::is_invocable_impl<T, Args...>::type, Ret, T, Args...>::type; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T, typename... Args> -struct is_invocable_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -template<typename Ret, typename T, typename... Args> -struct is_invocable_r_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T, typename... Args> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_invocable_v = //see below -//<- - detail::is_invocable_impl<detail::traits<T>, Args...>::type::value; -//-> - -// only available when variable templates are supported -template<typename Ret, typename T, typename... Args> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_invocable_r_v = //see below -//<- - detail::is_invocable_r_impl< - typename detail::is_invocable_impl<T, Args...>::type, - Ret, T, Args...>::type::value; -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none - -[heading Behavior] -* standalone c++11 implementation of c++17 `std::is_invocable`, `std::is_invocable_r` -[note ref-qualified overloads of `operator()` with different signatures are not handled correctly yet.] - -[heading Example Program] -[import ../example/is_invocable.cpp] -[is_invocable] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_lvalue_reference_member.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_lvalue_reference_member.hpp deleted file mode 100644 index 89500cb93..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_lvalue_reference_member.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_LVALUE_REFERENCE_MEMBER_HPP -#define BOOST_CLBL_TRTS_IS_LVALUE_REFERENCE_MEMBER_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ is_lvalue_reference_member_hpp -/*`[section:ref_is_lvalue_reference_member is_lvalue_reference_member] -[heading Header] -``#include <boost/callable_traits/is_lvalue_reference_member.hpp>`` -[heading Definition] -*/ - - -// inherits from either std::true_type or std::false_type -template<typename T> -struct is_lvalue_reference_member; - -//<- -template<typename T> -struct is_lvalue_reference_member - : detail::traits<detail::shallow_decay<T>>::is_lvalue_reference_member { - using type = typename detail::traits< - detail::shallow_decay<T>>::is_lvalue_reference_member; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct is_lvalue_reference_member_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_lvalue_reference_member_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::is_lvalue_reference_member::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `is_lvalue_reference_member<T>::value` is `true` when either: - * `T` is a function type with a '&' member qualifier - * `T` is a pointer to a member function with a '&' member qualifiers - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has a '&' member qualifier -* On compilers that support variable templates, `is_lvalue_reference_member_v<T>` is equivalent to `is_lvalue_reference_member<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`is_lvalue_reference_member_v<T>`]] - [[`int() &`] [`true`]] - [[`int(foo::* const)() const &`] [`true`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int(foo::*)() const`] [`false`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int() &&`] [`false`]] - [[`int(*)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`const int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/is_lvalue_reference_member.cpp] -[is_lvalue_reference_member] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_LVALUE_REFERENCE_MEMBER_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_noexcept.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_noexcept.hpp deleted file mode 100644 index 36320f689..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_noexcept.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -@file is_noexcept - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_NOEXCEPT_HPP -#define BOOST_CLBL_TRTS_IS_NOEXCEPT_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ is_noexcept_hpp -/*`[section:ref_is_noexcept is_noexcept] -[heading Header] -``#include <boost/callable_traits/is_noexcept.hpp>`` -[heading Definition] -*/ - -// inherits from either std::true_type or std::false_type -template<typename T> -struct is_noexcept; - -//<- -template<typename T> -struct is_noexcept : detail::traits<detail::shallow_decay<T>>::is_noexcept { - using type = typename detail::traits< - detail::shallow_decay<T>>::is_noexcept; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct is_noexcept_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_noexcept_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::is_noexcept::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none -* -[heading Behavior] -* `is_noexcept<T>::value` is `true` when either: - * `T` is a function type, function pointer type, function reference type, or member function pointer type where the function has a `noexcept` specifier - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has a `noexcept` specifier -* On compilers that support variable templates, `is_noexcept_v<T>` is equivalent to `is_noexcept<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`is_noexcept_v<T>`]] - [[`int() const noexcept`] [`true`]] - [[`int(* const &)() noexcept`] [`true`]] - [[`int(&)() noexcept`] [`true`]] - [[`int(foo::*)() noexcept`] [`true`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int(foo::*)() const`] [`false`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int() &`] [`false`]] - [[`int(*)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`const int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/is_noexcept.cpp] -[is_noexcept] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_NOEXCEPT_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_reference_member.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_reference_member.hpp deleted file mode 100644 index ef893a04d..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_reference_member.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_REFERENCE_MEMBER_HPP -#define BOOST_CLBL_TRTS_IS_REFERENCE_MEMBER_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ is_reference_member_hpp -/*`[section:ref_is_reference_member is_reference_member] -[heading Header] -``#include <boost/callable_traits/is_reference_member.hpp>`` -[heading Definition] -*/ - - -// inherits from either std::true_type or std::false_type -template<typename T> -struct is_reference_member; - -//<- -template<typename T> -struct is_reference_member : detail::traits< - detail::shallow_decay<T>>::is_reference_member { - - using type = typename detail::traits< - detail::shallow_decay<T>>::is_reference_member; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct is_reference_member_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_reference_member_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::is_reference_member::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `is_reference_member<T>::value` is `true` when either: - * `T` is a function type with a '&' or '&&' member qualifier - * `T` is a pointer to a member function with a '&' or '&&' member qualifiers - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has a '&' or '&&' member qualifier -* On compilers that support variable templates, `is_reference_member_v<T>` is equivalent to `is_reference_member<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`is_reference_member_v<T>`]] - [[`int() &`] [`true`]] - [[`int() const &&`] [`true`]] - [[`int(foo::* const)() &&`] [`true`]] - [[`int(foo::*)(...) volatile &`] [`true`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int(foo::*)() const`] [`false`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int(*)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`const int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/is_reference_member.cpp] -[is_reference_member] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_REFERENCE_MEMBER_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_rvalue_reference_member.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_rvalue_reference_member.hpp deleted file mode 100644 index a852ce6e1..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_rvalue_reference_member.hpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_RVALUE_REFERENCE_MEMBER_HPP -#define BOOST_CLBL_TRTS_IS_RVALUE_REFERENCE_MEMBER_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ is_rvalue_reference_member_hpp -/*`[section:ref_is_rvalue_reference_member is_rvalue_reference_member] -[heading Header] -``#include <boost/callable_traits/is_rvalue_reference_member.hpp>`` -[heading Definition] -*/ - - -// inherits from either std::true_type or std::false_type -template<typename T> -struct is_rvalue_reference_member; - -//<- -template<typename T> -struct is_rvalue_reference_member : detail::traits< - detail::shallow_decay<T>>::is_rvalue_reference_member { - - using type = typename detail::traits< - detail::shallow_decay<T>>::is_rvalue_reference_member; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct is_rvalue_reference_member_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_rvalue_reference_member_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::is_rvalue_reference_member::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `is_rvalue_reference_member<T>::value` is `true` when either: - * `T` is a function type with a '&&' member qualifier - * `T` is a pointer to a member function with a '&&' member qualifiers - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has a '&&' member qualifier -* On compilers that support variable templates, `is_rvalue_reference_member_v<T>` is equivalent to `is_rvalue_reference_member<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`is_rvalue_reference_member_v<T>`]] - [[`int() const &&`] [`true`]] - [[`int(foo::*)() &&`] [`true`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int(foo::* volatile)() const`] [`false`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int() &`] [`false`]] - [[`int(*)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`const int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/is_rvalue_reference_member.cpp] -[is_rvalue_reference_member] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_RVALUE_REFERENCE_MEMBER_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_transaction_safe.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_transaction_safe.hpp deleted file mode 100644 index 51c98c53e..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_transaction_safe.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -@file is_transaction_safe - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE_HPP -#define BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ is_transaction_safe_hpp -/*`[section:ref_is_transaction_safe is_transaction_safe] -[heading Header] -``#include <boost/callable_traits/is_transaction_safe.hpp>`` -[heading Definition] -*/ - - -// inherits from either std::true_type or std::false_type -template<typename T> -struct is_transaction_safe; - -//<- -template<typename T> -struct is_transaction_safe : detail::traits< - detail::shallow_decay<T>>::is_transaction_safe { - - using type = typename detail::traits< - detail::shallow_decay<T>>::is_transaction_safe; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct is_transaction_safe_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_transaction_safe_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::is_transaction_safe::value; - -#endif - -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* none -* -[heading Behavior] -* `is_transaction_safe<T>::value` is `true` when either: - * `T` is a function type, function pointer type, function reference type, or member function pointer type where the function has a `transaction_safe` specifier - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has a `transaction_safe` specifier -* On compilers that support variable templates, `is_transaction_safe_v<T>` is equivalent to `is_transaction_safe<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`is_transaction_safe_v<T>`]] - [[`int() const transaction_safe`] [`true`]] - [[`int(*)() transaction_safe`] [`true`]] - [[`int(&)() transaction_safe`] [`true`]] - [[`int(foo::* const)() transaction_safe`] [`true`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int(foo::*)() const`] [`false`]] - [[`int() const`] [`false`]] - [[`int() volatile`] [`false`]] - [[`int() &`] [`false`]] - [[`int(*)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`const int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/is_transaction_safe.cpp] -[is_transaction_safe] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_TRANSACTION_SAFE_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/is_volatile_member.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/is_volatile_member.hpp deleted file mode 100644 index 2309eec62..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/is_volatile_member.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * -@Copyright Barrett Adair 2015-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_IS_VOLATILE_MEMBER_HPP -#define BOOST_CLBL_TRTS_IS_VOLATILE_MEMBER_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ is_volatile_member_hpp -/*`[section:ref_is_volatile_member is_volatile_member] -[heading Header] -``#include <boost/callable_traits/is_volatile_member.hpp>`` -[heading Definition] -*/ - - -// inherits from either std::true_type or std::false_type -template<typename T> -struct is_volatile_member; - -//<- -template<typename T> -struct is_volatile_member : detail::traits< - detail::shallow_decay<T>>::is_volatile_member { - - using type = typename detail::traits< - detail::shallow_decay<T>>::is_volatile_member; -}; - -#ifdef BOOST_CLBL_TRTS_DISABLE_VARIABLE_TEMPLATES - -template<typename T> -struct is_volatile_member_v { - static_assert(std::is_same<T, detail::dummy>::value, - "Variable templates not supported on this compiler."); -}; - -#else -//-> -// only available when variable templates are supported -template<typename T> -//<- -BOOST_CLBL_TRAITS_INLINE_VAR -//-> -constexpr bool is_volatile_member_v = //see below -//<- - detail::traits<detail::shallow_decay<T>>::is_volatile_member::value; - -#endif - -}} // namespace boost::callable_traits -//-> - - -/*` -[heading Constraints] -* none - -[heading Behavior] -* `is_volatile_member<T>::value` is `true` when either: - * `T` is a function type with a `volatile` member qualifier - * `T` is a pointer to a member function with a `volatile` member qualifier - * `T` is a function object with a non-overloaded `operator()`, where the `operator()` has a `volatile` member qualifier -* On compilers that support variable templates, `is_volatile_member_v<T>` is equivalent to `is_volatile_member<T>::value`. - -[heading Input/Output Examples] -[table - [[`T`] [`is_volatile_member_v<T>`]] - [[`int() volatile`] [`true`]] - [[`int() const volatile`] [`true`]] - [[`int() volatile &&`] [`true`]] - [[`int(foo::*)() volatile`] [`true`]] - [[`int(foo::* const)() volatile`] [`true`]] - [[`int(foo::*)() const volatile`] [`true`]] - [[`int(foo::*)() const volatile &&`][`true`]] - [[`int()`] [`false`]] - [[`int() const`] [`false`]] - [[`int() &&`] [`false`]] - [[`int(*)()`] [`false`]] - [[`int`] [`false`]] - [[`int foo::*`] [`false`]] - [[`volatile int foo::*`] [`false`]] -] - -[heading Example Program] -[import ../example/is_volatile_member.cpp] -[is_volatile_member] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_IS_VOLATILE_MEMBER_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/qualified_class_of.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/qualified_class_of.hpp deleted file mode 100644 index 9f9e58117..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/qualified_class_of.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_QUALIFIED_class_of_HPP -#define BOOST_CLBL_TRTS_QUALIFIED_class_of_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ qualified_class_of_hpp -/*` -[section:ref_qualified_class_of qualified_class_of] -[heading Header] -``#include <boost/callable_traits/qualified_class_of.hpp>`` -[heading Definition] -*/ - -template<typename T> -using qualified_class_of_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<detail::shallow_decay<T>>::invoke_type, - type_is_not_a_member_pointer>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct qualified_class_of_impl {}; - - template<typename T> - struct qualified_class_of_impl <T, typename std::is_same< - qualified_class_of_t<T>, detail::dummy>::type> - { - using type = qualified_class_of_t<T>; - }; -} - -//-> - -template<typename T> -struct qualified_class_of : detail::qualified_class_of_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a member pointer - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* If `T` is a member function pointer, the aliased type is the parent class of the member, qualified according to the member qualifiers on `T`. If `T` does not have a member reference qualifier, then the aliased type will be an lvalue reference. -* If `T` is a member data pointer, the aliased type is equivalent to `ct::class_of<T> const &`. - -[heading Input/Output Examples] -[table - [[`T`] [`qualified_class_of_t<T>`]] - [[`void(foo::*)()`] [`foo &`]] - [[`void(foo::* volatile)() const`] [`foo const &`]] - [[`void(foo::*)() &&`] [`foo &&`]] - [[`void(foo::*&)() volatile &&`] [`foo volatile &&`]] - [[`int foo::*`] [`foo const &`]] - [[`const int foo::*`] [`foo const &`]] -] - -[heading Example Program] -[import ../example/qualified_class_of.cpp] -[qualified_class_of] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_QUALIFIED_class_of_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_const.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_const.hpp deleted file mode 100644 index 132680082..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_const.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_CONST_HPP -#define BOOST_CLBL_TRTS_REMOVE_MEMBER_CONST_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ remove_member_const_hpp -/*` -[section:ref_remove_member_const remove_member_const] -[heading Header] -``#include <boost/callable_traits/remove_member_const.hpp>`` -[heading Definition] -*/ - -template<typename T> -using remove_member_const_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::remove_member_const, - member_qualifiers_are_illegal_for_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct remove_member_const_impl {}; - - template<typename T> - struct remove_member_const_impl <T, typename std::is_same< - remove_member_const_t<T>, detail::dummy>::type> - { - using type = remove_member_const_t<T>; - }; -} - -//-> - -template<typename T> -struct remove_member_const : detail::remove_member_const_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Removes the member `const` qualifier from `T`, if present. - -[heading Input/Output Examples] -[table - [[`T`] [`remove_member_const_t<T>`]] - [[`int() const`] [`int()`]] - [[`int(foo::*)() const`] [`int(foo::*)()`]] - [[`int(foo::*)() const &`] [`int(foo::*)() &`]] - [[`int(foo::*)() const &&`] [`int(foo::*)() &&`]] - [[`int(foo::*)() const`] [`int(foo::*)()`]] - [[`int(foo::*)() const volatile`] [`int(foo::*)() volatile`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/remove_member_const.cpp] -[remove_member_const] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_CONST_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_cv.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_cv.hpp deleted file mode 100644 index 30d99a082..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_cv.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_CV_HPP -#define BOOST_CLBL_TRTS_REMOVE_MEMBER_CV_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ remove_member_cv_hpp -/*` -[section:ref_remove_member_cv remove_member_cv] -[heading Header] -``#include <boost/callable_traits/remove_member_cv.hpp>`` -[heading Definition] -*/ - -template<typename T> -using remove_member_cv_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::remove_member_cv, - member_qualifiers_are_illegal_for_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct remove_member_cv_impl {}; - - template<typename T> - struct remove_member_cv_impl <T, typename std::is_same< - remove_member_cv_t<T>, detail::dummy>::type> - { - using type = remove_member_cv_t<T>; - }; -} - -//-> - -template<typename T> -struct remove_member_cv : detail::remove_member_cv_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Removes member `const` and/or `volatile` qualifiers from `T`, if present. - -[heading Input/Output Examples] -[table - [[`T`] [`remove_member_cv_t<T>`]] - [[`int() const volatile`] [`int()`]] - [[`int(foo::*)() const volatile`] [`int(foo::*)()`]] - [[`int(foo::*)() volatile`] [`int(foo::*)()`]] - [[`int(foo::*)() const`] [`int(foo::*)()`]] - [[`int(foo::*)() const &`] [`int(foo::*)() &`]] - [[`int(foo::*)() const &&`] [`int(foo::*)() &&`]] - [[`int(foo::*)() const`] [`int(foo::*)()`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/remove_member_cv.cpp] -[remove_member_cv] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_CV_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_reference.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_reference.hpp deleted file mode 100644 index d4e4b62ce..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_reference.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_REFERENCE_HPP -#define BOOST_CLBL_TRTS_REMOVE_MEMBER_REFERENCE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ remove_member_reference_hpp -/*` -[section:ref_remove_member_reference remove_member_reference] -[heading Header] -``#include <boost/callable_traits/remove_member_reference.hpp>`` -[heading Definition] -*/ - -template<typename T> -using remove_member_reference_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::remove_member_reference, - member_qualifiers_are_illegal_for_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct remove_member_reference_impl {}; - - template<typename T> - struct remove_member_reference_impl <T, typename std::is_same< - remove_member_reference_t<T>, detail::dummy>::type> - { - using type = remove_member_reference_t<T>; - }; -} - -//-> - -template<typename T> -struct remove_member_reference - : detail::remove_member_reference_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occuers if the constraints are violated. -* Removes member `&` or `&&` qualifiers from `T`, if present. - -[heading Input/Output Examples] -[table - [[`T`] [`remove_member_const_t<T>`]] - [[`int() &`] [`int()`]] - [[`int(foo::*)() &`] [`int(foo::*)()`]] - [[`int(foo::*)() const &`] [`int(foo::*)() const`]] - [[`int(foo::*)() const &&`] [`int(foo::*)() const`]] - [[`int(foo::*)()`] [`int(foo::*)()`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/remove_member_reference.cpp] -[remove_member_reference] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_REFERENCE_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_volatile.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_volatile.hpp deleted file mode 100644 index d20c79684..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/remove_member_volatile.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_VOLATILE_HPP -#define BOOST_CLBL_TRTS_REMOVE_MEMBER_VOLATILE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ remove_member_volatile_hpp -/*` -[section:ref_remove_member_volatile remove_member_volatile] -[heading Header] -``#include <boost/callable_traits/remove_member_volatile.hpp>`` -[heading Definition] -*/ - -template<typename T> -using remove_member_volatile_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::remove_member_volatile, - member_qualifiers_are_illegal_for_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct remove_member_volatile_impl {}; - - template<typename T> - struct remove_member_volatile_impl <T, typename std::is_same< - remove_member_volatile_t<T>, detail::dummy>::type> - { - using type = remove_member_volatile_t<T>; - }; -} - -//-> - -template<typename T> -struct remove_member_volatile : detail::remove_member_volatile_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be a function type or a member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Removes the member `volatile` qualifier from `T`, if present. - -[heading Input/Output Examples] -[table - [[`T`] [`remove_member_volatile_t<T>`]] - [[`int() volatile`] [`int()`]] - [[`int(foo::*)() volatile`] [`int(foo::*)()`]] - [[`int(foo::*)() volatile &`] [`int(foo::*)() &`]] - [[`int(foo::*)() volatile &&`] [`int(foo::*)() &&`]] - [[`int(foo::*)() volatile`] [`int(foo::*)()`]] - [[`int(foo::*)() const volatile`] [`int(foo::*)() const`]] - [[`int`] [(substitution failure)]] - [[`int (&)()`] [(substitution failure)]] - [[`int (*)()`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/remove_member_volatile.cpp] -[remove_member_volatile] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_REMOVE_MEMBER_VOLATILE_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/remove_noexcept.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/remove_noexcept.hpp deleted file mode 100644 index 7b1fcb347..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/remove_noexcept.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/* -@file remove_noexcept - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_REMOVE_NOEXCEPT_HPP -#define BOOST_CLBL_TRTS_REMOVE_NOEXCEPT_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(remove_noexcept) -BOOST_CLBL_TRTS_SFINAE_MSG(remove_noexcept, cannot_remove_noexcept_from_this_type) - -//[ remove_noexcept_hpp -/*` -[section:ref_remove_noexcept remove_noexcept] -[heading Header] -``#include <boost/callable_traits/remove_noexcept.hpp>`` -[heading Definition] -*/ - -template<typename T> -using remove_noexcept_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::remove_noexcept, - cannot_remove_noexcept_from_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct remove_noexcept_impl {}; - - template<typename T> - struct remove_noexcept_impl <T, typename std::is_same< - remove_noexcept_t<T>, detail::dummy>::type> - { - using type = remove_noexcept_t<T>; - }; -} - -//-> - -template<typename T> -struct remove_noexcept : detail::remove_noexcept_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` - -[heading Constraints] -* `T` must be one of the following: - * function type - * function pointer type - * function reference type - * member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Removes the `noexcept` specifier from `T`, if present. - -[heading Input/Output Examples] -[table - [[`T`] [`remove_noexcept_t<T>`]] - [[`int() const noexcept`] [`int() const`]] - [[`int(*)() noexcept`] [`int(*)()`]] - [[`int(&)() noexcept`] [`int(&)()`]] - [[`int(foo::*)() noexcept`] [`int(foo::*)()`]] - [[`int() const`] [`int() const`]] - [[`int(*)()`] [`int(*)()`]] - [[`int(&)()`] [`int(&)()`]] - [[`int`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/remove_noexcept.cpp] -[remove_noexcept] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_REMOVE_NOEXCEPT_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/remove_transaction_safe.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/remove_transaction_safe.hpp deleted file mode 100644 index 4e37a3666..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/remove_transaction_safe.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/* -@file remove_transaction_safe - -@Copyright Barrett Adair 2015-2017 -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_REMOVE_TRANSACTION_SAFE_HPP -#define BOOST_CLBL_TRTS_REMOVE_TRANSACTION_SAFE_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(remove_transaction_safe) -BOOST_CLBL_TRTS_SFINAE_MSG(remove_transaction_safe, cannot_remove_transaction_safe_from_this_type) - -//[ remove_transaction_safe_hpp -/*` -[section:ref_remove_transaction_safe remove_transaction_safe] -[heading Header] -``#include <boost/callable_traits/remove_transaction_safe.hpp>`` -[heading Definition] -*/ - -template<typename T> -using remove_transaction_safe_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::remove_transaction_safe, - cannot_remove_transaction_safe_from_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct remove_transaction_safe_impl {}; - - template<typename T> - struct remove_transaction_safe_impl <T, typename std::is_same< - remove_transaction_safe_t<T>, detail::dummy>::type> - { - using type = remove_transaction_safe_t<T>; - }; -} - -//-> - -template<typename T> -struct remove_transaction_safe : detail::remove_transaction_safe_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` - -[heading Constraints] -* `T` must be one of the following: - * function type - * function pointer type - * function reference type - * member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Removes the member `transaction_safe` specifier from `T`, if present. - -[heading Input/Output Examples] -[table - [[`T`] [`remove_transaction_safe_t<T>`]] - [[`int() const transaction_safe`] [`int() const`]] - [[`int(*)() transaction_safe`] [`int(*)()`]] - [[`int(&)() transaction_safe`] [`int(&)()`]] - [[`int(foo::*)() transaction_safe`] [`int(foo::*)()`]] - [[`int() const`] [`int() const`]] - [[`int(*)()`] [`int(*)()`]] - [[`int(&)()`] [`int(&)()`]] - [[`int`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (foo::* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/remove_transaction_safe.cpp] -[remove_transaction_safe] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_REMOVE_TRANSACTION_SAFE_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/remove_varargs.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/remove_varargs.hpp deleted file mode 100644 index 874651c60..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/remove_varargs.hpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_REMOVE_VARARGS_HPP -#define BOOST_CLBL_TRTS_REMOVE_VARARGS_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -//[ remove_varargs_hpp -/*` -[section:ref_remove_varargs remove_varargs] -[heading Header] -``#include <boost/callable_traits/remove_varargs.hpp>`` -[heading Definition] -*/ - -template<typename T> -using remove_varargs_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<T>::remove_varargs, - varargs_are_illegal_for_this_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct remove_varargs_impl {}; - - template<typename T> - struct remove_varargs_impl <T, typename std::is_same< - remove_varargs_t<T>, detail::dummy>::type> - { - using type = remove_varargs_t<T>; - }; -} - -//-> - -template<typename T> -struct remove_varargs : detail::remove_varargs_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be one of the following: - * function type - * function pointer type - * function reference type - * member function pointer type -* If `T` is a pointer, it may not be cv/ref qualified - -[heading Behavior] -* A substitution failure occurs if the constraints are violated. -* Removes C-style variadics (`...`) from the signature of `T`, if present. - -[heading Input/Output Examples] -[table - [[`T`] [`remove_varargs_t<T>`]] - [[`int(...)`] [`int()`]] - [[`int(int, ...)`] [`int(int)`]] - [[`int (&)(...)`] [`int(&)()`]] - [[`int (*)()`] [`int(*)()`]] - [[`int(foo::*)(...)`] [`int(foo::*)()`]] - [[`int(foo::*)(...) &`] [`int(foo::*)() &`]] - [[`int(foo::*)(...) &&`] [`int(foo::*)() &&`]] - [[`int(foo::*)(...) const`] [`int(foo::*)() const`]] - [[`int(foo::*)(...) transaction_safe`] [`int(foo::*)() transaction_safe`]] - [[`int`] [(substitution failure)]] - [[`int foo::*`] [(substitution failure)]] - [[`int (* const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/remove_varargs.cpp] -[remove_varargs] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_REMOVE_VARARGS_HPP diff --git a/stratosphere/libstratosphere/include/boost/callable_traits/return_type.hpp b/stratosphere/libstratosphere/include/boost/callable_traits/return_type.hpp deleted file mode 100644 index 586b0d249..000000000 --- a/stratosphere/libstratosphere/include/boost/callable_traits/return_type.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - -@Copyright Barrett Adair 2015-2017 - -Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) - -*/ - -#ifndef BOOST_CLBL_TRTS_RESULT_OF_HPP -#define BOOST_CLBL_TRTS_RESULT_OF_HPP - -#include <boost/callable_traits/detail/core.hpp> - -namespace boost { namespace callable_traits { - -BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(return_type) -BOOST_CLBL_TRTS_SFINAE_MSG(return_type, unable_to_determine_return_type) - -//[ return_type_hpp -/*` -[section:ref_return_type return_type] -[heading Header] -``#include <boost/callable_traits/return_type.hpp>`` -[heading Definition] -*/ - -template<typename T> -using return_type_t = //see below -//<- - detail::try_but_fail_if_invalid< - typename detail::traits<detail::shallow_decay<T>>::return_type, - unable_to_determine_return_type>; - -namespace detail { - - template<typename T, typename = std::false_type> - struct return_type_impl {}; - - template<typename T> - struct return_type_impl <T, typename std::is_same< - return_type_t<T>, detail::dummy>::type> - { - using type = return_type_t<T>; - }; -} - -//-> - -template<typename T> -struct return_type : detail::return_type_impl<T> {}; - -//<- -}} // namespace boost::callable_traits -//-> - -/*` -[heading Constraints] -* `T` must be one of the following: - * function - * function pointer - * function reference - * member function pointer - * member data pointer - * user-defined type with a non-overloaded `operator()` - * type of a non-generic lambda - -[heading Behavior] -* When the constraints are violated, a substitution failure occurs. -* The aliased type is the return type of `T`. - -[heading Input/Output Examples] -[table - [[`T`] [`return_type_t<T, std::tuple>`]] - [[`void()`] [`void`]] - [[`float(*)()`] [`float`]] - [[`const char*(&)()`] [`const char *`]] - [[`int(foo::*)() const`] [`int`]] - [[`int`] [(substitution failure)]] - [[`int (*const)()`] [(substitution failure)]] -] - -[heading Example Program] -[import ../example/return_type.cpp] -[return_type] -[endsect] -*/ -//] - -#endif // #ifndef BOOST_CLBL_TRTS_RESULT_OF_HPP diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp index 41a669547..1e4e77afa 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp @@ -13,13 +13,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - + #pragma once #include <switch.h> #include <cstdlib> #include <cstring> #include <tuple> -#include "../../boost/callable_traits.hpp" +#include <boost/callable_traits.hpp> #include <type_traits> #include <memory> @@ -31,7 +31,7 @@ #include "ipc_response_context.hpp" -#pragma GCC diagnostic push +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-variable" template<typename Tuple> @@ -192,12 +192,12 @@ struct RawDataComputer<std::tuple<Ts...>> { } } while (left < right); } - + static constexpr void StableSort(std::array<size_t, sizeof...(Ts)> &map, std::array<size_t, sizeof...(Ts)> &values) { /* First, quicksort a copy of the map. */ std::array<size_t, sizeof...(Ts)> map_unstable(map); QuickSort(map_unstable, values, 0, sizeof...(Ts)-1); - + /* Now, create stable sorted map from unstably quicksorted indices (via repeated insertion sort on element runs). */ for (size_t i = 0; i < sizeof...(Ts); i++) { map[i] = map_unstable[i]; @@ -208,7 +208,7 @@ struct RawDataComputer<std::tuple<Ts...>> { } } } - + static constexpr std::array<size_t, sizeof...(Ts)+1> GetOffsets() { std::array<size_t, sizeof...(Ts)+1> offsets = {}; offsets[0] = 0; @@ -216,12 +216,12 @@ struct RawDataComputer<std::tuple<Ts...>> { /* Get size, alignment for each type. */ std::array<size_t, sizeof...(Ts)> sizes = { RawDataHelper<Ts>::size... }; std::array<size_t, sizeof...(Ts)> aligns = { RawDataHelper<Ts>::align... }; - + /* We want to sort...by alignment. */ std::array<size_t, sizeof...(Ts)> map = {}; for (size_t i = 0; i < sizeof...(Ts); i++) { map[i] = i; } StableSort(map, aligns); - + /* Iterate over sorted types. */ size_t cur_offset = 0; for (size_t i = 0; i < sizeof...(Ts); i++) { @@ -236,7 +236,7 @@ struct RawDataComputer<std::tuple<Ts...>> { } return offsets; } - + static constexpr std::array<size_t, sizeof...(Ts)+1> offsets = GetOffsets(); }; @@ -247,10 +247,10 @@ template<typename... _Args, typename _ReturnType> struct CommandMetaInfo<std::tuple<_Args...>, _ReturnType> { using Args = std::tuple<_Args...>; using ReturnType = _ReturnType; - + static constexpr bool ReturnsResult = std::is_same_v<ReturnType, Result>; static constexpr bool ReturnsVoid = std::is_same_v<ReturnType, void>; - + using InDatas = FilteredTypes<ArgTypeInDataFilter::type, _Args...>; using OutDatas = FilteredTypes<ArgTypeFilter<ArgType::OutData>::type, _Args...>; using InHandles = FilteredTypes<ArgTypeFilter<ArgType::InHandle>::type, _Args...>; @@ -258,14 +258,14 @@ struct CommandMetaInfo<std::tuple<_Args...>, _ReturnType> { using InSessions = FilteredTypes<ArgTypeFilter<ArgType::InSession>::type, _Args...>; using OutSessions = FilteredTypes<ArgTypeFilter<ArgType::OutSession>::type, _Args...>; using PidDescs = FilteredTypes<ArgTypeFilter<ArgType::PidDesc>::type, _Args...>; - + using InBuffers = FilteredTypes<ArgTypeFilter<ArgType::InBuffer>::type, _Args...>; using OutBuffers = FilteredTypes<ArgTypeFilter<ArgType::OutBuffer>::type, _Args...>; using InPointers = FilteredTypes<ArgTypeFilter<ArgType::InPointer>::type, _Args...>; using ClientSizeOutPointers = FilteredTypes<ArgTypeFilter<ArgType::OutPointerClientSize>::type, _Args...>; using ServerSizeOutPointers = FilteredTypes<ArgTypeFilter<ArgType::OutPointerServerSize>::type, _Args...>; using Buffers = FilteredTypes<ArgTypeBufferFilter::type, _Args...>; - + static constexpr size_t NumInDatas = std::tuple_size_v<InDatas>; static constexpr size_t NumOutDatas = std::tuple_size_v<OutDatas>; static constexpr size_t NumInHandles = std::tuple_size_v<InHandles>; @@ -273,24 +273,24 @@ struct CommandMetaInfo<std::tuple<_Args...>, _ReturnType> { static constexpr size_t NumInSessions = std::tuple_size_v<InSessions>; static constexpr size_t NumOutSessions = std::tuple_size_v<OutSessions>; static constexpr size_t NumPidDescs = std::tuple_size_v<PidDescs>; - + static constexpr size_t NumInBuffers = std::tuple_size_v<InBuffers>; static constexpr size_t NumOutBuffers = std::tuple_size_v<OutBuffers>; static constexpr size_t NumInPointers = std::tuple_size_v<InPointers>; static constexpr size_t NumClientSizeOutPointers = std::tuple_size_v<ClientSizeOutPointers>; static constexpr size_t NumServerSizeOutPointers = std::tuple_size_v<ServerSizeOutPointers>; static constexpr size_t NumBuffers = std::tuple_size_v<Buffers>; - + static_assert(NumInSessions == 0, "InSessions not yet supported!"); static_assert(NumPidDescs == 0 || NumPidDescs == 1, "Methods can only take in 0 or 1 PIDs!"); static_assert(NumBuffers <= 8, "Methods can only take in <= 8 Buffers!"); static_assert(NumInHandles <= 8, "Methods can take in <= 8 Handles!"); static_assert(NumOutHandles + NumOutSessions <= 8, "Methods can only return <= 8 Handles+Sessions!"); - + static constexpr std::array<size_t, NumInDatas+1> InDataOffsets = RawDataComputer<InDatas>::offsets; static constexpr size_t InRawArgSize = InDataOffsets[NumInDatas]; static constexpr size_t InRawArgSizeWithOutPointers = ((InRawArgSize + NumClientSizeOutPointers * sizeof(u16)) + 3) & ~3; - + static constexpr std::array<size_t, NumOutDatas+1> OutDataOffsets = RawDataComputer<OutDatas>::offsets; static constexpr size_t OutRawArgSize = OutDataOffsets[NumOutDatas]; }; @@ -301,7 +301,7 @@ struct CommandMetaInfo<std::tuple<_Args...>, _ReturnType> { /* Validator. */ struct Validator { - + template <typename T> static constexpr bool ValidateCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& h_index, size_t& cur_c_size_offset, size_t& total_c_size) { constexpr ArgType argT = GetArgType<T>(); @@ -327,27 +327,27 @@ struct Validator { return true; } } - + template <typename Ts> struct ValidateCommandTuple; - + template <typename ...Ts> struct ValidateCommandTuple<std::tuple<Ts...>> { static constexpr bool IsValid(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& h_index, size_t& cur_c_size_offset, size_t& total_c_size) { return (ValidateCommandArgument<Ts>(ctx, a_index, b_index, x_index, h_index, cur_c_size_offset, total_c_size) && ...); } }; - + template<typename MetaInfo> static constexpr Result Validate(IpcResponseContext *ctx) { if (ctx->request.RawSize < MetaInfo::InRawArgSizeWithOutPointers) { return 0xF601; } - + if (ctx->request.NumBuffers != MetaInfo::NumInBuffers + MetaInfo::NumOutBuffers) { return 0xF601; } - + if (ctx->request.NumStatics != MetaInfo::NumInPointers) { return 0xF601; } @@ -355,28 +355,28 @@ struct Validator { if (ctx->request.NumStaticsOut != MetaInfo::NumClientSizeOutPointers + MetaInfo::NumServerSizeOutPointers) { return 0xF601; } - + if (ctx->request.NumHandles != MetaInfo::NumInHandles) { return 0xF601; } - - + + if ((ctx->request.HasPid && MetaInfo::NumPidDescs == 0) || (!ctx->request.HasPid && MetaInfo::NumPidDescs != 0)) { return 0xF601; } - + if (((u32 *)ctx->request.Raw)[0] != SFCI_MAGIC) { return 0xF601; } - + size_t a_index = 0, b_index = MetaInfo::NumInBuffers, x_index = 0, h_index = 0; size_t cur_c_size_offset = MetaInfo::InRawArgSize + (0x10 - ((uintptr_t)ctx->request.Raw - (uintptr_t)ctx->request.RawWithoutPadding)); size_t total_c_size = 0; - + if (!ValidateCommandTuple<typename MetaInfo::Args>::IsValid(ctx, a_index, b_index, x_index, h_index, cur_c_size_offset, total_c_size)) { return 0xF601; } - + if (total_c_size > ctx->pb_size) { return 0xF601; } @@ -390,7 +390,7 @@ struct Validator { /* Decoder. */ template<typename MetaInfo> struct Decoder { - + template<typename T> static constexpr T DecodeCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_data_index, size_t& out_data_index, size_t& pb_offset, size_t& c_sz_offset) { constexpr ArgType argT = GetArgType<T>(); @@ -448,10 +448,10 @@ struct Decoder { } } } - + template <typename Ts> struct DecodeTuple; - + template <typename ...Ts> struct DecodeTuple<std::tuple<Ts...>> { static constexpr std::tuple<Ts...> GetArgs(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_data_index, size_t& out_data_index, size_t& pb_offset, size_t& c_sz_offset) { @@ -462,7 +462,7 @@ struct Decoder { } }; - + static constexpr typename MetaInfo::Args Decode(IpcResponseContext *ctx) { size_t a_index = 0, b_index = MetaInfo::NumInBuffers, x_index = 0, c_index = 0, in_h_index = 0, out_h_index = 0, out_obj_index = 0; size_t in_data_index = 0x0, out_data_index = 0, pb_offset = 0; @@ -497,7 +497,7 @@ struct Encoder; template <typename MetaInfo, typename ...Args> struct Encoder<MetaInfo, std::tuple<Args...>> { - + static constexpr void EncodeFailure(IpcResponseContext *ctx, Result rc) { memset(armGetTls(), 0, 0x100); ipcInitialize(&ctx->reply); @@ -505,7 +505,7 @@ struct Encoder<MetaInfo, std::tuple<Args...>> { u64 magic; u64 result; } *raw; - + if (IsDomainObject(ctx->obj_holder)) { raw = (decltype(raw))ipcPrepareHeaderForDomain(&ctx->reply, sizeof(*raw), 0); auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); @@ -516,22 +516,22 @@ struct Encoder<MetaInfo, std::tuple<Args...>> { raw->magic = SFCO_MAGIC; raw->result = rc; } - - - - static constexpr void EncodeSuccess(IpcResponseContext *ctx, Args... args) { + + + + static constexpr void EncodeSuccess(IpcResponseContext *ctx, Args... args) { size_t out_obj_index = 0; - + ((EncodeArgument<MetaInfo, Args>(ctx, out_obj_index, args)), ...); - + const bool is_domain = IsDomainObject(ctx->obj_holder); - + if (!is_domain) { for (unsigned int i = 0; i < MetaInfo::NumOutSessions; i++) { ipcSendHandleMove(&ctx->reply, ctx->out_handles[MetaInfo::NumOutHandles + i].handle); } } - + struct { u64 magic; u64 result; @@ -544,10 +544,10 @@ struct Encoder<MetaInfo, std::tuple<Args...>> { } else { raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)+ MetaInfo::OutRawArgSize); } - + raw->magic = SFCO_MAGIC; raw->result = 0; - + memcpy((void *)((uintptr_t)raw + sizeof(*raw)), ctx->out_data, MetaInfo::OutRawArgSize); if (is_domain) { memcpy((void *)((uintptr_t)raw + sizeof(*raw) + MetaInfo::OutRawArgSize), ctx->out_object_ids, sizeof(*ctx->out_object_ids) * MetaInfo::NumOutSessions); @@ -563,20 +563,20 @@ constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { using InArgs = typename PopFront<typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>>::type; using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; using ClassType = typename boost::callable_traits::class_of_t<decltype(IpcCommandImpl)>; - + using CommandMetaData = CommandMetaInfo<InArgs, OutArgs>; - + static_assert(CommandMetaData::ReturnsResult || CommandMetaData::ReturnsVoid, "IpcCommandImpls must return Result or void"); - + ipcInitialize(&ctx->reply); memset(ctx->out_data, 0, CommandMetaData::OutRawArgSize); Result rc = Validator::Validate<CommandMetaData>(ctx); - + if (R_FAILED(rc)) { return 0xAAEE; } - + ClassType *this_ptr = nullptr; if (IsDomainObject(ctx->obj_holder)) { this_ptr = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId)->GetServiceObject<ClassType>(); @@ -586,9 +586,9 @@ constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { if (this_ptr == nullptr) { return 0xBBEE; } - + std::shared_ptr<IServiceObject> out_objects[CommandMetaData::NumOutSessions]; - + /* Allocate out object IDs. */ size_t num_out_objects; if (IsDomainObject(ctx->obj_holder)) { @@ -609,7 +609,7 @@ constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { ctx->out_objs[num_out_objects] = &out_objects[num_out_objects]; } } - + ON_SCOPE_EXIT { /* Clean up objects as necessary. */ if (IsDomainObject(ctx->obj_holder) && R_FAILED(rc)) { @@ -622,21 +622,21 @@ constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { svcCloseHandle(ctx->out_handles[CommandMetaData::NumOutHandles + i].handle); } } - + for (unsigned int i = 0; i < num_out_objects; i++) { ctx->out_objs[i] = nullptr; } }; - + if (R_SUCCEEDED(rc)) { auto args = Decoder<CommandMetaData>::Decode(ctx); - + if constexpr (CommandMetaData::ReturnsResult) { rc = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args); } else { std::apply( [=](auto&&... args) { (this_ptr->*IpcCommandImpl)(args...); }, args); } - + if (R_SUCCEEDED(rc)) { std::apply(Encoder<CommandMetaData, decltype(args)>::EncodeSuccess, std::tuple_cat(std::make_tuple(ctx), args)); } else { @@ -645,7 +645,7 @@ constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { } else { std::apply(Encoder<CommandMetaData, typename CommandMetaData::Args>::EncodeFailure, std::tuple_cat(std::make_tuple(ctx), std::make_tuple(rc))); } - + return rc; } @@ -661,4 +661,4 @@ inline static constexpr ServiceCommandMeta MakeServiceCommandMeta() { }; -#pragma GCC diagnostic pop \ No newline at end of file +#pragma GCC diagnostic pop diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp index 68e80a347..3b9c4960d 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp @@ -13,18 +13,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - + #pragma once #include <switch.h> #include <cstdlib> #include <cstring> #include <tuple> -#include "../boost/callable_traits.hpp" +#include <boost/callable_traits.hpp> #include <type_traits> #include "domainowner.hpp" -#pragma GCC diagnostic push +#pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-variable" /* Base for In/Out Buffers. */ @@ -39,7 +39,7 @@ struct InBuffer : InBufferBase { size_t num_elements; BufferType type; static const BufferType expected_type = e_t; - + InBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } }; @@ -52,7 +52,7 @@ struct OutBuffer : OutBufferBase { size_t num_elements; BufferType type; static const BufferType expected_type = e_t; - + OutBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } }; @@ -61,18 +61,18 @@ template <typename T> struct InPointer : IpcBufferBase { T *pointer; size_t num_elements; - + InPointer(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } }; /* Represents a C descriptor. */ struct OutPointerWithServerSizeBase : IpcBufferBase {}; - + template <typename T, size_t n> struct OutPointerWithServerSize : OutPointerWithServerSizeBase { T *pointer; static const size_t num_elements = n; - + OutPointerWithServerSize(void *p) : pointer((T *)p) { } }; @@ -81,28 +81,28 @@ template <typename T> struct OutPointerWithClientSize : IpcBufferBase { T *pointer; size_t num_elements; - + OutPointerWithClientSize(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } }; /* Represents an input PID. */ struct PidDescriptor { u64 pid; - + PidDescriptor(u64 p) : pid(p) { } }; /* Represents a moved handle. */ struct MovedHandle { Handle handle; - + MovedHandle(Handle h) : handle(h) { } }; /* Represents a copied handle. */ struct CopiedHandle { Handle handle; - + CopiedHandle(Handle h) : handle(h) { } }; @@ -117,7 +117,7 @@ template <typename T> struct OutSession : OutSessionBase { ISession<T> *session; u32 domain_id; - + OutSession(ISession<T> *s) : session(s), domain_id(DOMAIN_ID_MAX) { } }; @@ -306,16 +306,16 @@ template<typename... Args> struct Validator<std::tuple<Args...>> { IpcParsedCommand &r; size_t pointer_buffer_size; - + Result operator()() { if (r.RawSize < size_in_raw_data_with_out_pointers_for_arguments<Args... >::value) { return 0xF601; } - + if (r.NumBuffers != num_inoutbuffers_in_arguments<Args... >::value) { return 0xF601; } - + if (r.NumStatics != num_inpointers_in_arguments<Args... >::value) { return 0xF601; } @@ -323,32 +323,32 @@ struct Validator<std::tuple<Args...>> { if (r.NumStaticsOut != num_outpointers_in_arguments<Args... >::value) { return 0xF601; } - + if (r.NumHandles != num_handles_in_arguments<Args... >::value) { return 0xF601; } - + constexpr size_t num_pids = num_pids_in_arguments<Args... >::value; - + static_assert(num_pids <= 1, "Number of PID descriptors in IpcCommandImpl cannot be > 1"); - + if ((r.HasPid && num_pids == 0) || (!r.HasPid && num_pids)) { return 0xF601; } - + if (((u32 *)r.Raw)[0] != SFCI_MAGIC) { return 0xF601; } - + size_t a_index = 0, b_index = num_inbuffers_in_arguments<Args ...>::value, x_index = 0, c_index = 0, h_index = 0; size_t cur_rawdata_index = 4; size_t cur_c_size_offset = 0x10 + size_in_raw_data_for_arguments<Args... >::value + (0x10 - ((uintptr_t)r.Raw - (uintptr_t)r.RawWithoutPadding)); size_t total_c_size = 0; - + if (!(ValidateIpcParsedCommandArgument<Args>(r, cur_rawdata_index, cur_c_size_offset, a_index, b_index, x_index, c_index, h_index, total_c_size) && ...)) { return 0xF601; } - + if (total_c_size > pointer_buffer_size) { return 0xF601; } @@ -383,7 +383,7 @@ struct Encoder; template<typename T> constexpr size_t GetAndUpdateOffsetIntoRawData(DomainOwner *domain_owner, size_t& offset) { auto old = offset; - + if (old == 0) { offset += sizeof(u64); } else { @@ -392,8 +392,8 @@ constexpr size_t GetAndUpdateOffsetIntoRawData(DomainOwner *domain_owner, size_t offset += sizeof(u32); } } else { - offset += size_in_raw_data<T>::value; - } + offset += size_in_raw_data<T>::value; + } } return old; @@ -439,17 +439,17 @@ void EncodeValueIntoIpcMessageAfterPrepare(DomainOwner *domain_owner, u8 *cur_ou template<typename... Args> struct Encoder<std::tuple<Args...>> { IpcCommand &out_command; - + auto operator()(DomainOwner *domain_owner, Args... args) { static_assert(sizeof...(Args) > 0, "IpcCommandImpls must return std::tuple<Result, ...>"); size_t offset = 0; - + u8 *tls = (u8 *)armGetTls(); - + std::fill(tls, tls + 0x100, 0x00); - + ((EncodeValueIntoIpcMessageBeforePrepare<Args>(domain_owner, &out_command, args)), ...); - + /* Remove the extra space resulting from first Result type. */ struct { u64 magic; @@ -463,16 +463,16 @@ struct Encoder<std::tuple<Args...>> { *resp_header = {0}; resp_header->NumObjectIds = num_out_sessions_in_arguments<Args... >::value; } - - + + raw->magic = SFCO_MAGIC; - + u8 *raw_data = (u8 *)&raw->result; - + ((EncodeValueIntoIpcMessageAfterPrepare<Args>(domain_owner, raw_data + GetAndUpdateOffsetIntoRawData<Args>(domain_owner, offset), args)), ...); - + Result rc = raw->result; - + if (R_FAILED(rc)) { std::fill(tls, tls + 0x100, 0x00); ipcInitialize(&out_command); @@ -486,7 +486,7 @@ struct Encoder<std::tuple<Args...>> { raw->magic = SFCO_MAGIC; raw->result = rc; } - + return rc; } }; @@ -497,20 +497,20 @@ Result WrapDeferredIpcCommandImpl(Class *this_ptr, Args... args) { using InArgs = typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>; using InArgsWithoutThis = typename pop_front<InArgs>::type; using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; - + static_assert(is_specialization_of<OutArgs, std::tuple>::value, "IpcCommandImpls must return std::tuple<Result, ...>"); static_assert(std::is_same_v<std::tuple_element_t<0, OutArgs>, Result>, "IpcCommandImpls must return std::tuple<Result, ...>"); static_assert(std::is_same_v<InArgsWithoutThis, std::tuple<Args...>>, "Invalid Deferred Wrapped IpcCommandImpl arguments!"); - + IpcCommand out_command; - + ipcInitialize(&out_command); auto tuple_args = std::make_tuple(args...); auto result = std::apply( [=](auto&&... a) { return (this_ptr->*IpcCommandImpl)(a...); }, tuple_args); - + DomainOwner *down = NULL; - + return std::apply(Encoder<OutArgs>{out_command}, std::tuple_cat(std::make_tuple(down), result)); } @@ -519,25 +519,25 @@ Result WrapIpcCommandImpl(Class *this_ptr, IpcParsedCommand& r, IpcCommand &out_ using InArgs = typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>; using InArgsWithoutThis = typename pop_front<InArgs>::type; using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; - + static_assert(is_specialization_of<OutArgs, std::tuple>::value, "IpcCommandImpls must return std::tuple<Result, ...>"); static_assert(std::is_same_v<std::tuple_element_t<0, OutArgs>, Result>, "IpcCommandImpls must return std::tuple<Result, ...>"); - + ipcInitialize(&out_command); Result rc = Validator<InArgsWithoutThis>{r, pointer_buffer_size}(); - + if (R_FAILED(rc)) { return 0xF601; } - auto args = Decoder<OutArgs, InArgsWithoutThis>::Decode(r, out_command, pointer_buffer); + auto args = Decoder<OutArgs, InArgsWithoutThis>::Decode(r, out_command, pointer_buffer); auto result = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args); DomainOwner *down = NULL; if (r.IsDomainRequest) { down = this_ptr->get_owner(); } - + return std::apply(Encoder<OutArgs>{out_command}, std::tuple_cat(std::make_tuple(down), result)); } @@ -545,22 +545,22 @@ template<auto IpcCommandImpl> Result WrapStaticIpcCommandImpl(IpcParsedCommand& r, IpcCommand &out_command, u8 *pointer_buffer, size_t pointer_buffer_size) { using InArgs = typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>; using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; - + static_assert(is_specialization_of<OutArgs, std::tuple>::value, "IpcCommandImpls must return std::tuple<Result, ...>"); static_assert(std::is_same_v<std::tuple_element_t<0, OutArgs>, Result>, "IpcCommandImpls must return std::tuple<Result, ...>"); - + ipcInitialize(&out_command); Result rc = Validator<InArgs>{r, pointer_buffer_size}(); - + if (R_FAILED(rc)) { return 0xF601; } - auto args = Decoder<OutArgs, InArgs>::Decode(r, out_command, pointer_buffer); + auto args = Decoder<OutArgs, InArgs>::Decode(r, out_command, pointer_buffer); auto result = std::apply(IpcCommandImpl, args); DomainOwner *down = NULL; - + return std::apply(Encoder<OutArgs>{out_command}, std::tuple_cat(std::make_tuple(down), result)); } From be044e691c10400c9b713bc75f7c032375769523 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 30 Oct 2018 15:57:15 -0700 Subject: [PATCH 159/489] libstrat: delete old ipc templating. --- .../stratosphere/ipc/ipc_templating_old.hpp | 569 ------------------ 1 file changed, 569 deletions(-) delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp deleted file mode 100644 index 3b9c4960d..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_templating_old.hpp +++ /dev/null @@ -1,569 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <cstdlib> -#include <cstring> -#include <tuple> -#include <boost/callable_traits.hpp> -#include <type_traits> - -#include "domainowner.hpp" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" - -/* Base for In/Out Buffers. */ -struct IpcBufferBase {}; - -/* Represents an A descriptor. */ -struct InBufferBase : IpcBufferBase {}; - -template <typename T, BufferType e_t = BufferType_Normal> -struct InBuffer : InBufferBase { - T *buffer; - size_t num_elements; - BufferType type; - static const BufferType expected_type = e_t; - - InBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } -}; - -/* Represents a B descriptor. */ -struct OutBufferBase : IpcBufferBase {}; - -template <typename T, BufferType e_t = BufferType_Normal> -struct OutBuffer : OutBufferBase { - T *buffer; - size_t num_elements; - BufferType type; - static const BufferType expected_type = e_t; - - OutBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } -}; - -/* Represents an X descriptor. */ -template <typename T> -struct InPointer : IpcBufferBase { - T *pointer; - size_t num_elements; - - InPointer(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } -}; - -/* Represents a C descriptor. */ -struct OutPointerWithServerSizeBase : IpcBufferBase {}; - -template <typename T, size_t n> -struct OutPointerWithServerSize : OutPointerWithServerSizeBase { - T *pointer; - static const size_t num_elements = n; - - OutPointerWithServerSize(void *p) : pointer((T *)p) { } -}; - -/* Represents a C descriptor with size in raw data. */ -template <typename T> -struct OutPointerWithClientSize : IpcBufferBase { - T *pointer; - size_t num_elements; - - OutPointerWithClientSize(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } -}; - -/* Represents an input PID. */ -struct PidDescriptor { - u64 pid; - - PidDescriptor(u64 p) : pid(p) { } -}; - -/* Represents a moved handle. */ -struct MovedHandle { - Handle handle; - - MovedHandle(Handle h) : handle(h) { } -}; - -/* Represents a copied handle. */ -struct CopiedHandle { - Handle handle; - - CopiedHandle(Handle h) : handle(h) { } -}; - -/* Forward declarations. */ -template <typename T> -class ISession; - -/* Represents an output ServiceObject. */ -struct OutSessionBase {}; - -template <typename T> -struct OutSession : OutSessionBase { - ISession<T> *session; - u32 domain_id; - - OutSession(ISession<T> *s) : session(s), domain_id(DOMAIN_ID_MAX) { } -}; - -/* Utilities. */ -template <typename T, template <typename...> class Template> -struct is_specialization_of { - static const bool value = false; -}; - -template <template <typename...> class Template, typename... Args> -struct is_specialization_of<Template<Args...>, Template> { - static const bool value = true; -}; - -template<typename Tuple> -struct pop_front; - -template<typename Head, typename... Tail> -struct pop_front<std::tuple<Head, Tail...>> { - using type = std::tuple<Tail...>; -}; - -template <typename T> -struct is_ipc_buffer { - static const bool value = std::is_base_of<IpcBufferBase, T>::value; -}; - -template <typename T> -struct is_ipc_handle { - static const size_t value = (std::is_same<T, MovedHandle>::value || std::is_same<T, CopiedHandle>::value) ? 1 : 0; -}; - -template <typename T> -struct is_out_session { - static const bool value = std::is_base_of<OutSessionBase, T>::value; -}; - -template <typename T> -struct size_in_raw_data { - static const size_t value = (is_ipc_buffer<T>::value || is_ipc_handle<T>::value || is_out_session<T>::value) ? 0 : ((sizeof(T) < sizeof(u32)) ? sizeof(u32) : (sizeof(T) + 3) & (~3)); -}; - -template <typename ...Args> -struct size_in_raw_data_for_arguments { - static const size_t value = (size_in_raw_data<Args>::value + ... + 0); -}; - -template <typename ...Args> -struct num_out_sessions_in_arguments { - static const size_t value = ((is_out_session<Args>::value ? 1 : 0) + ... + 0); -}; - -template <typename T> -struct size_in_raw_data_with_out_pointers { - static const size_t value = is_specialization_of<T, OutPointerWithClientSize>::value ? 2 : size_in_raw_data<T>::value; -}; - -template <typename ...Args> -struct size_in_raw_data_with_out_pointers_for_arguments { - static const size_t value = ((size_in_raw_data_with_out_pointers<Args>::value + ... + 0) + 3) & ~3; -}; - -template <typename T> -struct is_ipc_inbuffer { - static const size_t value = (std::is_base_of<InBufferBase, T>::value) ? 1 : 0; -}; - -template <typename ...Args> -struct num_inbuffers_in_arguments { - static const size_t value = (is_ipc_inbuffer<Args>::value + ... + 0); -}; - -template <typename T> -struct is_ipc_inpointer { - static const size_t value = (is_specialization_of<T, InPointer>::value) ? 1 : 0; -}; - -template <typename ...Args> -struct num_inpointers_in_arguments { - static const size_t value = (is_ipc_inpointer<Args>::value + ... + 0); -}; - -template <typename T> -struct is_ipc_outpointer { - static const size_t value = (is_specialization_of<T, OutPointerWithClientSize>::value || std::is_base_of<OutPointerWithServerSizeBase, T>::value) ? 1 : 0; -}; - -template <typename ...Args> -struct num_outpointers_in_arguments { - static const size_t value = (is_ipc_outpointer<Args>::value + ... + 0); -}; - -template <typename T> -struct is_ipc_inoutbuffer { - static const size_t value = (std::is_base_of<InBufferBase, T>::value || std::is_base_of<OutBufferBase, T>::value) ? 1 : 0; -}; - -template <typename ...Args> -struct num_inoutbuffers_in_arguments { - static const size_t value = (is_ipc_inoutbuffer<Args>::value + ... + 0); -}; - -template <typename ...Args> -struct num_handles_in_arguments { - static const size_t value = (is_ipc_handle<Args>::value + ... + 0); -}; - -template <typename ...Args> -struct num_pids_in_arguments { - static const size_t value = ((std::is_same<Args, PidDescriptor>::value ? 1 : 0) + ... + 0); -}; - -template<typename T> -T GetValueFromIpcParsedCommand(IpcParsedCommand& r, IpcCommand& out_c, u8 *pointer_buffer, size_t& pointer_buffer_offset, size_t& cur_rawdata_index, size_t& cur_c_size_offset, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& h_index) { - const size_t old_rawdata_index = cur_rawdata_index; - const size_t old_c_size_offset = cur_c_size_offset; - const size_t old_pointer_buffer_offset = pointer_buffer_offset; - if constexpr (std::is_base_of<InBufferBase, T>::value) { - const T& value = T(r.Buffers[a_index], r.BufferSizes[a_index], r.BufferTypes[a_index]); - ++a_index; - return value; - } else if constexpr (std::is_base_of<OutBufferBase, T>::value) { - const T& value = T(r.Buffers[b_index], r.BufferSizes[b_index], r.BufferTypes[b_index]); - ++b_index; - return value; - } else if constexpr (is_specialization_of<T, InPointer>::value) { - const T& value{r.Statics[x_index], r.StaticSizes[x_index]}; - ++x_index; - return value; - } else if constexpr (std::is_base_of<OutPointerWithServerSizeBase, T>::value) { - T t = T(pointer_buffer + old_pointer_buffer_offset); - ipcAddSendStatic(&out_c, pointer_buffer + old_pointer_buffer_offset, t.num_elements * sizeof(*t.pointer), c_index++); - return t; - } else if constexpr (is_specialization_of<T, OutPointerWithClientSize>::value) { - cur_c_size_offset += sizeof(u16); - u16 sz = *((u16 *)((u8 *)(r.Raw) + old_c_size_offset)); - pointer_buffer_offset += sz; - ipcAddSendStatic(&out_c, pointer_buffer + old_pointer_buffer_offset, sz, c_index++); - return T(pointer_buffer + old_pointer_buffer_offset, sz); - } else if constexpr (is_ipc_handle<T>::value) { - return r.Handles[h_index++]; - } else if constexpr (std::is_same<T, PidDescriptor>::value) { - cur_rawdata_index += sizeof(u64) / sizeof(u32); - return PidDescriptor(r.Pid); - } else if constexpr (std::is_same<T, bool>::value) { - /* Official bools accept non-zero values with low bit unset as false. */ - cur_rawdata_index += size_in_raw_data<T>::value / sizeof(u32); - return ((*(((u32 *)r.Raw + old_rawdata_index))) & 1) == 1; - } else { - cur_rawdata_index += size_in_raw_data<T>::value / sizeof(u32); - return *((T *)((u32 *)r.Raw + old_rawdata_index)); - } -} - -template <typename T> -bool ValidateIpcParsedCommandArgument(IpcParsedCommand& r, size_t& cur_rawdata_index, size_t& cur_c_size_offset, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& h_index, size_t& total_c_size) { - const size_t old_c_size_offset = cur_c_size_offset; - if constexpr (std::is_base_of<InBufferBase, T>::value) { - return r.Buffers[a_index] != NULL && r.BufferDirections[a_index] == BufferDirection_Send && r.BufferTypes[a_index++] == T::expected_type; - } else if constexpr (std::is_base_of<OutBufferBase, T>::value) { - return r.Buffers[b_index] != NULL && r.BufferDirections[b_index] == BufferDirection_Recv && r.BufferTypes[b_index++] == T::expected_type; - } else if constexpr (is_specialization_of<T, InPointer>::value) { - return r.Statics[x_index] != NULL; - } else if constexpr (std::is_base_of<OutPointerWithServerSizeBase, T>::value) { - total_c_size += T::num_elements; - return true; - } else if constexpr (is_specialization_of<T, OutPointerWithClientSize>::value) { - cur_c_size_offset += sizeof(u16); - u16 sz = *((u16 *)((u8 *)(r.Raw) + old_c_size_offset)); - total_c_size += sz; - return true; - } else if constexpr (std::is_same<T, MovedHandle>::value) { - return !r.WasHandleCopied[h_index++]; - } else if constexpr (std::is_same<T, CopiedHandle>::value) { - return r.WasHandleCopied[h_index++]; - } else { - return true; - } -} - -/* Validator. */ -template <typename ArgsTuple> -struct Validator; - -template<typename... Args> -struct Validator<std::tuple<Args...>> { - IpcParsedCommand &r; - size_t pointer_buffer_size; - - Result operator()() { - if (r.RawSize < size_in_raw_data_with_out_pointers_for_arguments<Args... >::value) { - return 0xF601; - } - - if (r.NumBuffers != num_inoutbuffers_in_arguments<Args... >::value) { - return 0xF601; - } - - if (r.NumStatics != num_inpointers_in_arguments<Args... >::value) { - return 0xF601; - } - - if (r.NumStaticsOut != num_outpointers_in_arguments<Args... >::value) { - return 0xF601; - } - - if (r.NumHandles != num_handles_in_arguments<Args... >::value) { - return 0xF601; - } - - constexpr size_t num_pids = num_pids_in_arguments<Args... >::value; - - static_assert(num_pids <= 1, "Number of PID descriptors in IpcCommandImpl cannot be > 1"); - - if ((r.HasPid && num_pids == 0) || (!r.HasPid && num_pids)) { - return 0xF601; - } - - if (((u32 *)r.Raw)[0] != SFCI_MAGIC) { - return 0xF601; - } - - size_t a_index = 0, b_index = num_inbuffers_in_arguments<Args ...>::value, x_index = 0, c_index = 0, h_index = 0; - size_t cur_rawdata_index = 4; - size_t cur_c_size_offset = 0x10 + size_in_raw_data_for_arguments<Args... >::value + (0x10 - ((uintptr_t)r.Raw - (uintptr_t)r.RawWithoutPadding)); - size_t total_c_size = 0; - - if (!(ValidateIpcParsedCommandArgument<Args>(r, cur_rawdata_index, cur_c_size_offset, a_index, b_index, x_index, c_index, h_index, total_c_size) && ...)) { - return 0xF601; - } - - if (total_c_size > pointer_buffer_size) { - return 0xF601; - } - - return 0; - } -}; - - -/* Decoder. */ -template<typename OutTuple, typename ArgsTuple> -struct Decoder; - -template<typename OutTuple, typename... Args> -struct Decoder<OutTuple, std::tuple<Args...>> { - static std::tuple<Args...> Decode(IpcParsedCommand& r, IpcCommand &out_c, u8 *pointer_buffer) { - size_t a_index = 0, b_index = num_inbuffers_in_arguments<Args ...>::value, x_index = 0, c_index = 0, h_index = 0; - size_t cur_rawdata_index = 4; - size_t cur_c_size_offset = 0x10 + size_in_raw_data_for_arguments<Args... >::value + (0x10 - ((uintptr_t)r.Raw - (uintptr_t)r.RawWithoutPadding)); - size_t pointer_buffer_offset = 0; - return std::tuple<Args... > { - GetValueFromIpcParsedCommand<Args>(r, out_c, pointer_buffer, pointer_buffer_offset, cur_rawdata_index, cur_c_size_offset, a_index, b_index, x_index, c_index, h_index) - ... - }; - } -}; - -/* Encoder. */ -template<typename ArgsTuple> -struct Encoder; - -template<typename T> -constexpr size_t GetAndUpdateOffsetIntoRawData(DomainOwner *domain_owner, size_t& offset) { - auto old = offset; - - if (old == 0) { - offset += sizeof(u64); - } else { - if constexpr (is_out_session<T>::value) { - if (domain_owner) { - offset += sizeof(u32); - } - } else { - offset += size_in_raw_data<T>::value; - } - } - - return old; -} - -template<typename T> -void EncodeValueIntoIpcMessageBeforePrepare(DomainOwner *domain_owner, IpcCommand *c, T &value) { - if constexpr (std::is_same<T, MovedHandle>::value) { - ipcSendHandleMove(c, value.handle); - } else if constexpr (std::is_same<T, CopiedHandle>::value) { - ipcSendHandleCopy(c, value.handle); - } else if constexpr (std::is_same<T, PidDescriptor>::value) { - ipcSendPid(c); - } else if constexpr (is_out_session<T>::value) { - if (domain_owner && value.session) { - /* TODO: Check error... */ - if (value.domain_id != DOMAIN_ID_MAX) { - domain_owner->set_object(value.session->get_service_object(), value.domain_id); - } else { - domain_owner->reserve_object(value.session->get_service_object(), &value.domain_id); - } - value.session->close_handles(); - delete value.session; - } else { - ipcSendHandleMove(c, value.session ? value.session->get_client_handle() : 0x0); - } - } -} - -template<typename T> -void EncodeValueIntoIpcMessageAfterPrepare(DomainOwner *domain_owner, u8 *cur_out, T value) { - if constexpr (is_ipc_handle<T>::value || std::is_same<T, PidDescriptor>::value) { - /* Do nothing. */ - } else if constexpr (is_out_session<T>::value) { - if (domain_owner) { - *((u32 *)cur_out) = value.domain_id; - } - } else { - *((T *)(cur_out)) = value; - } -} - -template<typename... Args> -struct Encoder<std::tuple<Args...>> { - IpcCommand &out_command; - - auto operator()(DomainOwner *domain_owner, Args... args) { - static_assert(sizeof...(Args) > 0, "IpcCommandImpls must return std::tuple<Result, ...>"); - size_t offset = 0; - - u8 *tls = (u8 *)armGetTls(); - - std::fill(tls, tls + 0x100, 0x00); - - ((EncodeValueIntoIpcMessageBeforePrepare<Args>(domain_owner, &out_command, args)), ...); - - /* Remove the extra space resulting from first Result type. */ - struct { - u64 magic; - u64 result; - } *raw; - if (domain_owner == NULL) { - raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value - sizeof(Result)); - } else { - raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value + (num_out_sessions_in_arguments<Args... >::value * sizeof(u32)) - sizeof(Result), 0); - auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); - *resp_header = {0}; - resp_header->NumObjectIds = num_out_sessions_in_arguments<Args... >::value; - } - - - raw->magic = SFCO_MAGIC; - - u8 *raw_data = (u8 *)&raw->result; - - ((EncodeValueIntoIpcMessageAfterPrepare<Args>(domain_owner, raw_data + GetAndUpdateOffsetIntoRawData<Args>(domain_owner, offset), args)), ...); - - Result rc = raw->result; - - if (R_FAILED(rc)) { - std::fill(tls, tls + 0x100, 0x00); - ipcInitialize(&out_command); - if (domain_owner != NULL) { - raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(raw), 0); - auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); - *resp_header = {0}; - } else { - raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(raw)); - } - raw->magic = SFCO_MAGIC; - raw->result = rc; - } - - return rc; - } -}; - - -template<auto IpcCommandImpl, typename Class, typename... Args> -Result WrapDeferredIpcCommandImpl(Class *this_ptr, Args... args) { - using InArgs = typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>; - using InArgsWithoutThis = typename pop_front<InArgs>::type; - using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; - - static_assert(is_specialization_of<OutArgs, std::tuple>::value, "IpcCommandImpls must return std::tuple<Result, ...>"); - static_assert(std::is_same_v<std::tuple_element_t<0, OutArgs>, Result>, "IpcCommandImpls must return std::tuple<Result, ...>"); - static_assert(std::is_same_v<InArgsWithoutThis, std::tuple<Args...>>, "Invalid Deferred Wrapped IpcCommandImpl arguments!"); - - IpcCommand out_command; - - ipcInitialize(&out_command); - - auto tuple_args = std::make_tuple(args...); - auto result = std::apply( [=](auto&&... a) { return (this_ptr->*IpcCommandImpl)(a...); }, tuple_args); - - DomainOwner *down = NULL; - - return std::apply(Encoder<OutArgs>{out_command}, std::tuple_cat(std::make_tuple(down), result)); -} - -template<auto IpcCommandImpl, typename Class> -Result WrapIpcCommandImpl(Class *this_ptr, IpcParsedCommand& r, IpcCommand &out_command, u8 *pointer_buffer, size_t pointer_buffer_size) { - using InArgs = typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>; - using InArgsWithoutThis = typename pop_front<InArgs>::type; - using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; - - static_assert(is_specialization_of<OutArgs, std::tuple>::value, "IpcCommandImpls must return std::tuple<Result, ...>"); - static_assert(std::is_same_v<std::tuple_element_t<0, OutArgs>, Result>, "IpcCommandImpls must return std::tuple<Result, ...>"); - - ipcInitialize(&out_command); - - Result rc = Validator<InArgsWithoutThis>{r, pointer_buffer_size}(); - - if (R_FAILED(rc)) { - return 0xF601; - } - - auto args = Decoder<OutArgs, InArgsWithoutThis>::Decode(r, out_command, pointer_buffer); - auto result = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args); - DomainOwner *down = NULL; - if (r.IsDomainRequest) { - down = this_ptr->get_owner(); - } - - return std::apply(Encoder<OutArgs>{out_command}, std::tuple_cat(std::make_tuple(down), result)); -} - -template<auto IpcCommandImpl> -Result WrapStaticIpcCommandImpl(IpcParsedCommand& r, IpcCommand &out_command, u8 *pointer_buffer, size_t pointer_buffer_size) { - using InArgs = typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>; - using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; - - static_assert(is_specialization_of<OutArgs, std::tuple>::value, "IpcCommandImpls must return std::tuple<Result, ...>"); - static_assert(std::is_same_v<std::tuple_element_t<0, OutArgs>, Result>, "IpcCommandImpls must return std::tuple<Result, ...>"); - - ipcInitialize(&out_command); - - Result rc = Validator<InArgs>{r, pointer_buffer_size}(); - - if (R_FAILED(rc)) { - return 0xF601; - } - - auto args = Decoder<OutArgs, InArgs>::Decode(r, out_command, pointer_buffer); - auto result = std::apply(IpcCommandImpl, args); - DomainOwner *down = NULL; - - return std::apply(Encoder<OutArgs>{out_command}, std::tuple_cat(std::make_tuple(down), result)); -} - -#pragma GCC diagnostic pop - -#include "isession.hpp" From ef5c7d6bab9c455f1ea9213828892c5e09c16bf2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 30 Oct 2018 16:39:20 -0700 Subject: [PATCH 160/489] Fix make dist zip to launch set_mitm. (Thanks @bakugo). --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index c2a88fd4e..c10b6eb7a 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,7 @@ dist: all cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp + touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/boot2.flag cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; rm -r atmosphere-$(AMSVER) mkdir out From 158f7224a7b3b02e26c1127d80d47062914c5148 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 31 Oct 2018 02:07:35 -0700 Subject: [PATCH 161/489] set.mitm: fixup NPDM json. --- stratosphere/set_mitm/set_mitm.json | 53 ++++++++++++++++------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/stratosphere/set_mitm/set_mitm.json b/stratosphere/set_mitm/set_mitm.json index 1383e7e2c..055c6af6b 100644 --- a/stratosphere/set_mitm/set_mitm.json +++ b/stratosphere/set_mitm/set_mitm.json @@ -14,22 +14,29 @@ "filesystem_access": { "permissions": "0xFFFFFFFFFFFFFFFF" }, - "service_access": { - "fatal:u": false, - "fsp-srv": false, - "spl:": false, - "set:sys": false, - "set:sys": true - }, - "kernel_capabilities": { - "kernel_flags": { - "highest_thread_priority": 63, - "lowest_thread_priority": 24, - "lowest_cpu_id": 3, - "highest_cpu_id": 3 - }, - "syscalls": { - + "service_host": [ + "set:sys" + ], + "service_access": [ + "fatal:u", + "fsp-srv", + "spl:", + "set:sys", + "fsp-srv" + ], + "kernel_capabilities": [ + { + "type": "kernel_flags", + "value": { + "highest_thread_priority": 63, + "lowest_thread_priority": 24, + "lowest_cpu_id": 3, + "highest_cpu_id": 3 + } + }, + { + "type": "syscalls", + "value": { "svcSetHeapSize": "0x01", "svcSetMemoryPermission": "0x02", "svcSetMemoryAttribute": "0x03", @@ -88,11 +95,11 @@ "svcMapDeviceAddressSpaceAligned": "0x5a", "svcUnmapDeviceAddressSpace": "0x5c", "svcGetSystemInfo": "0x6f" - }, - "min_kernel_version": "0x0060", - "debug_flags": { - "allow_debug": false, - "force_debug": true - } - } + } + }, + { + "type": "min_kernel_version", + "value": "0x0060" + } + ] } \ No newline at end of file From e786bc7e9a3c0b9b0424b12f243d5f8debd2c85d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 4 Nov 2018 12:45:29 -0800 Subject: [PATCH 162/489] fs.mitm: Only create storage interface when needed. --- .../fs_mitm/source/fsmitm_service.cpp | 42 ++++++++++++------- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 16 ++++--- stratosphere/fs_mitm/source/fsmitm_utils.hpp | 5 +-- .../stratosphere/mitm/mitm_session.hpp | 4 +- 4 files changed, 39 insertions(+), 28 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index a9f1e30a5..7cb91f1ca 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -79,15 +79,21 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora Log(armGetTls(), 0x100); if (R_SUCCEEDED(rc)) { - /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ - if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) { - storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), this->title_id)); + if (Utils::HasSdRomfsContent(this->title_id)) { + /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ + if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(this->title_id, "romfs.bin", FS_OPEN_READ, &data_file))) { + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), this->title_id)); + } else { + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, this->title_id)); + } + this->romfs_storage = storage; + if (out_storage.IsDomain()) { + out_domain_id = data_storage.s.object_id; + } } else { - storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, this->title_id)); - } - this->romfs_storage = storage; - if (out_storage.IsDomain()) { - out_domain_id = data_storage.s.object_id; + /* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */ + fsStorageClose(&data_storage); + rc = RESULT_FORWARD_TO_SESSION; } } } @@ -117,14 +123,20 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &data_storage); if (R_SUCCEEDED(rc)) { - /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ - if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) { - storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id)); + if (Utils::HasSdRomfsContent(data_id)) { + /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ + if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) { + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id)); + } else { + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id)); + } + if (out_storage.IsDomain()) { + out_domain_id = data_storage.s.object_id; + } } else { - storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id)); - } - if (out_storage.IsDomain()) { - out_domain_id = data_storage.s.object_id; + /* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */ + fsStorageClose(&data_storage); + rc = RESULT_FORWARD_TO_SESSION; } } diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index aa22bb5c3..2210f4cfe 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -201,20 +201,18 @@ Result Utils::OpenRomFSDir(FsFileSystem *fs, u64 title_id, const char *path, FsD return fsFsOpenDirectory(fs, safe_path, FS_DIROPEN_DIRECTORY | FS_DIROPEN_FILE, out); } -Result Utils::HasSdRomfsContent(u64 title_id, bool *out) { - Result rc; +bool Utils::HasSdRomfsContent(u64 title_id) { FsDir dir; - if (R_FAILED((rc = Utils::OpenRomFSSdDir(title_id, "", &dir)))) { - return rc; + if (R_FAILED(Utils::OpenRomFSSdDir(title_id, "", &dir))) { + return false; } + ON_SCOPE_EXIT { + fsDirClose(&dir); + }; FsDirectoryEntry dir_entry; u64 read_entries; - if (R_SUCCEEDED((rc = fsDirRead(&dir, 0, &read_entries, 1, &dir_entry)))) { - *out = (read_entries == 1); - } - fsDirClose(&dir); - return rc; + return R_SUCCEEDED(fsDirRead(&dir, 0, &read_entries, 1, &dir_entry)) && read_entries == 1; } bool Utils::HasSdMitMFlag(u64 tid) { diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index 42d547481..5c27b6b14 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -26,13 +26,12 @@ class Utils { static Result OpenRomFSSdFile(u64 title_id, const char *fn, int flags, FsFile *out); static Result OpenSdDir(const char *path, FsDir *out); static Result OpenSdDirForAtmosphere(u64 title_id, const char *path, FsDir *out); - static Result OpenRomFSSdDir(u64 title_id, const char *path, FsDir *out); - + static Result OpenRomFSSdDir(u64 title_id, const char *path, FsDir *out); static Result OpenRomFSFile(FsFileSystem *fs, u64 title_id, const char *fn, int flags, FsFile *out); static Result OpenRomFSDir(FsFileSystem *fs, u64 title_id, const char *path, FsDir *out); - static Result HasSdRomfsContent(u64 title_id, bool *out); + static bool HasSdRomfsContent(u64 title_id); /* SD card Initialization + MitM detection. */ static void InitializeSdThreadFunc(void *args); diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp index f4df504f1..3a4032161 100644 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp @@ -21,6 +21,8 @@ #include "mitm_query_service.hpp" +#define RESULT_FORWARD_TO_SESSION 0xCAFEFC + class MitmSession final : public ServiceSession { private: /* This will be for the actual session. */ @@ -149,7 +151,7 @@ class MitmSession final : public ServiceSession { } } - if (!found_entry) { + if (!found_entry || rc == RESULT_FORWARD_TO_SESSION) { memcpy(armGetTls(), this->backup_tls, sizeof(this->backup_tls)); rc = ForwardRequest(ctx); } From 5d0aabaa44e2fc2c40eedd36fec5fdaf3aa261cd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 4 Nov 2018 12:48:14 -0800 Subject: [PATCH 163/489] fs.mitm: Fix romfs detection on SD --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 2210f4cfe..bb7976a0e 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -202,6 +202,14 @@ Result Utils::OpenRomFSDir(FsFileSystem *fs, u64 title_id, const char *path, FsD } bool Utils::HasSdRomfsContent(u64 title_id) { + /* Check for romfs.bin. */ + FsFile data_file; + if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(title_id, "romfs.bin", FS_OPEN_READ, &data_file))) { + fsFileClose(&data_file); + return true; + } + + /* Check for romfs folder with non-zero content. */ FsDir dir; if (R_FAILED(Utils::OpenRomFSSdDir(title_id, "", &dir))) { return false; From 78a47dba6db331842493c6729686d39ab2312a69 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 4 Nov 2018 13:56:07 -0800 Subject: [PATCH 164/489] fs.mitm: Cache IStorageInterfaces, store meta on SD instead of memory. --- .../fs_mitm/source/fsmitm_layeredrom.cpp | 16 +++ .../fs_mitm/source/fsmitm_romfsbuild.cpp | 25 ++--- .../fs_mitm/source/fsmitm_romfsbuild.hpp | 24 ++++ .../fs_mitm/source/fsmitm_service.cpp | 105 ++++++++++++++---- .../fs_mitm/source/fsmitm_service.hpp | 1 - stratosphere/fs_mitm/source/fsmitm_utils.cpp | 41 +++++++ stratosphere/fs_mitm/source/fsmitm_utils.hpp | 3 + 7 files changed, 176 insertions(+), 39 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp index ed6ad63a1..2b2bbeda3 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp @@ -83,6 +83,22 @@ Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { cur_read_size = cur_source->size - (offset - cur_source->virtual_offset); } switch (cur_source->type) { + case RomFSDataSource::MetaData: + { + FsFile file; + if (R_FAILED((rc = Utils::OpenSdFileForAtmosphere(this->title_id, ROMFS_METADATA_FILE_PATH, FS_OPEN_READ, &file)))) { + fatalSimple(rc); + } + size_t out_read; + if (R_FAILED((rc = fsFileRead(&file, (offset - cur_source->virtual_offset), (void *)((uintptr_t)buffer + read_so_far), cur_read_size, &out_read)))) { + fatalSimple(rc); + } + if (out_read != cur_read_size) { + Reboot(); + } + fsFileClose(&file); + } + break; case RomFSDataSource::LooseFile: { FsFile file; diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp index 4a01bff77..7b63b2b0a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp @@ -399,23 +399,14 @@ void RomFSBuildContext::Build(std::vector<RomFSSourceInfo> *out_infos) { header->file_hash_table_ofs = header->dir_table_ofs + header->dir_table_size; header->file_table_ofs = header->file_hash_table_ofs + header->file_hash_table_size; - /* For debugging, uncomment this to get a log of the generated metadata tables. */ + const size_t metadata_size = this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size; - { - FsFileSystem sd_fs; - if (R_SUCCEEDED(fsMountSdcard(&sd_fs))) { - FsFile f; - fsFsCreateFile(&sd_fs, "/METADATALOG.bin", this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size + sizeof(*header), 0); - if (R_SUCCEEDED(fsFsOpenFile(&sd_fs, "/METADATALOG.bin", FS_OPEN_READ | FS_OPEN_WRITE, &f))) { - fsFileSetSize(&f, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size + sizeof(*header)); - fsFileWrite(&f, 0, header, sizeof(*header)); - fsFileWrite(&f, sizeof(*header), metadata, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size); - fsFileClose(&f); - } - fsFsClose(&sd_fs); - } - } + /* Try to save metadata to the SD card, to save on memory space. */ + if (R_SUCCEEDED(Utils::SaveSdFileForAtmosphere(this->title_id, ROMFS_METADATA_FILE_PATH, metadata, metadata_size))) { + out_infos->emplace_back(header->dir_hash_table_ofs, metadata_size, RomFSDataSource::MetaData); + delete metadata; + } else { + out_infos->emplace_back(header->dir_hash_table_ofs, metadata_size, metadata, RomFSDataSource::Memory); + } - - out_infos->emplace_back(header->dir_hash_table_ofs, this->dir_hash_table_size + this->dir_table_size + this->file_hash_table_size + this->file_table_size, metadata, RomFSDataSource::Memory); } diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp index c4a78e681..4da8b30e4 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp @@ -25,11 +25,14 @@ #define ROMFS_ENTRY_EMPTY 0xFFFFFFFF #define ROMFS_FILEPARTITION_OFS 0x200 +#define ROMFS_METADATA_FILE_PATH "romfs_metadata.bin" + /* Types for RomFS Meta construction. */ enum class RomFSDataSource { BaseRomFS, FileRomFS, LooseFile, + MetaData, Memory, }; @@ -49,6 +52,10 @@ struct RomFSMemorySourceInfo { const u8 *data; }; +struct RomFSMetaDataSourceInfo { + +}; + struct RomFSSourceInfo { u64 virtual_offset; u64 size; @@ -57,6 +64,7 @@ struct RomFSSourceInfo { RomFSFileSourceInfo file_source_info; RomFSLooseSourceInfo loose_source_info; RomFSMemorySourceInfo memory_source_info; + RomFSMemorySourceInfo metadata_source_info; }; RomFSDataSource type; @@ -69,6 +77,7 @@ struct RomFSSourceInfo { this->file_source_info.offset = offset; break; case RomFSDataSource::LooseFile: + case RomFSDataSource::MetaData: case RomFSDataSource::Memory: default: fatalSimple(0xF601); @@ -83,6 +92,20 @@ struct RomFSSourceInfo { case RomFSDataSource::Memory: this->memory_source_info.data = (decltype(this->memory_source_info.data))arg; break; + case RomFSDataSource::MetaData: + case RomFSDataSource::BaseRomFS: + case RomFSDataSource::FileRomFS: + default: + fatalSimple(0xF601); + } + } + + RomFSSourceInfo(u64 v_o, u64 s, RomFSDataSource t) : virtual_offset(v_o), size(s), type(t) { + switch (this->type) { + case RomFSDataSource::MetaData: + break; + case RomFSDataSource::LooseFile: + case RomFSDataSource::Memory: case RomFSDataSource::BaseRomFS: case RomFSDataSource::FileRomFS: default: @@ -94,6 +117,7 @@ struct RomFSSourceInfo { switch (this->type) { case RomFSDataSource::BaseRomFS: case RomFSDataSource::FileRomFS: + case RomFSDataSource::MetaData: break; case RomFSDataSource::LooseFile: delete this->loose_source_info.path; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 7cb91f1ca..91364ae19 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -14,7 +14,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <map> +#include <memory> +#include <mutex> + #include <switch.h> +#include <stratosphere.hpp> #include "fsmitm_service.hpp" #include "fs_shim.h" @@ -24,6 +29,37 @@ #include "debug.hpp" +static HosMutex g_StorageCacheLock; +static std::unordered_map<u64, std::weak_ptr<IStorageInterface>> g_StorageCache; + +static bool StorageCacheGetEntry(u64 title_id, std::shared_ptr<IStorageInterface> *out) { + std::scoped_lock<HosMutex> lock(g_StorageCacheLock); + if (g_StorageCache.find(title_id) == g_StorageCache.end()) { + return false; + } + + auto intf = g_StorageCache[title_id].lock(); + if (intf != nullptr) { + *out = intf; + return true; + } + return false; +} + +static void StorageCacheSetEntry(u64 title_id, std::shared_ptr<IStorageInterface> *ptr) { + std::scoped_lock<HosMutex> lock(g_StorageCacheLock); + + /* Ensure we always use the cached copy if present. */ + if (g_StorageCache.find(title_id) != g_StorageCache.end()) { + auto intf = g_StorageCache[title_id].lock(); + if (intf != nullptr) { + *ptr = intf; + } + } + + g_StorageCache[title_id] = *ptr; +} + void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { auto this_ptr = static_cast<FsMitmService *>(obj); switch ((FspSrvCmd)ctx->cmd_id) { @@ -49,16 +85,23 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora u32 out_domain_id = 0; Result rc = 0; + bool has_cache = StorageCacheGetEntry(this->title_id, &storage); + ON_SCOPE_EXIT { if (R_SUCCEEDED(rc)) { + if (!has_cache) { + StorageCacheSetEntry(this->title_id, &storage); + } + out_storage.SetValue(std::move(storage)); if (out_storage.IsDomain()) { out_storage.ChangeObjectId(out_domain_id); } } }; - - if (this->romfs_storage != nullptr) { + + + if (has_cache) { if (out_storage.IsDomain()) { FsStorage s = {0}; rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service.get(), &s); @@ -68,8 +111,8 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora } else { rc = 0; } - if (R_SUCCEEDED(rc)) { - storage = this->romfs_storage; + if (R_FAILED(rc)) { + storage.reset(); } } else { FsStorage data_storage; @@ -86,7 +129,6 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora } else { storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, this->title_id)); } - this->romfs_storage = storage; if (out_storage.IsDomain()) { out_domain_id = data_storage.s.object_id; } @@ -106,13 +148,19 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf FsStorageId storage_id = (FsStorageId)sid; FsStorage data_storage; FsFile data_file; - + std::shared_ptr<IStorageInterface> storage = nullptr; u32 out_domain_id = 0; Result rc = 0; + bool has_cache = StorageCacheGetEntry(data_id, &storage); + ON_SCOPE_EXIT { if (R_SUCCEEDED(rc)) { + if (!has_cache) { + StorageCacheSetEntry(data_id, &storage); + } + out_storage.SetValue(std::move(storage)); if (out_storage.IsDomain()) { out_storage.ChangeObjectId(out_domain_id); @@ -120,23 +168,38 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf } }; - rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &data_storage); - - if (R_SUCCEEDED(rc)) { - if (Utils::HasSdRomfsContent(data_id)) { - /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ - if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) { - storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id)); - } else { - storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id)); - } - if (out_storage.IsDomain()) { - out_domain_id = data_storage.s.object_id; + if (has_cache) { + if (out_storage.IsDomain()) { + FsStorage s = {0}; + rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &s); + if (R_SUCCEEDED(rc)) { + out_domain_id = s.s.object_id; } } else { - /* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */ - fsStorageClose(&data_storage); - rc = RESULT_FORWARD_TO_SESSION; + rc = 0; + } + if (R_FAILED(rc)) { + storage.reset(); + } + } else { + rc = fsOpenDataStorageByDataIdFwd(this->forward_service.get(), storage_id, data_id, &data_storage); + + if (R_SUCCEEDED(rc)) { + if (Utils::HasSdRomfsContent(data_id)) { + /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ + if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) { + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), std::make_shared<RomFileStorage>(data_file), data_id)); + } else { + storage = std::make_shared<IStorageInterface>(new LayeredRomFS(std::make_shared<RomInterfaceStorage>(data_storage), nullptr, data_id)); + } + if (out_storage.IsDomain()) { + out_domain_id = data_storage.s.object_id; + } + } else { + /* If we don't have anything to modify, there's no sense in maintaining a copy of the metadata tables. */ + fsStorageClose(&data_storage); + rc = RESULT_FORWARD_TO_SESSION; + } } } diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 75dc7b426..2fffacfa9 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -29,7 +29,6 @@ enum FspSrvCmd : u32 { class FsMitmService : public IMitmServiceObject { private: bool has_initialized = false; - std::shared_ptr<IStorageInterface> romfs_storage; public: FsMitmService(std::shared_ptr<Service> s) : IMitmServiceObject(s) { /* ... */ diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index bb7976a0e..32e37fad6 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -223,6 +223,47 @@ bool Utils::HasSdRomfsContent(u64 title_id) { return R_SUCCEEDED(fsDirRead(&dir, 0, &read_entries, 1, &dir_entry)) && read_entries == 1; } +Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data, size_t size) { + if (!IsSdInitialized()) { + return 0xFA202; + } + + Result rc = 0; + + char path[FS_MAX_PATH]; + if (*fn == '/') { + snprintf(path, sizeof(path), "/atmosphere/titles/%016lx%s", title_id, fn); + } else { + snprintf(path, sizeof(path), "/atmosphere/titles/%016lx/%s", title_id, fn); + } + + /* Unconditionally create. */ + FsFile f; + fsFsCreateFile(&g_sd_filesystem, path, size, 0); + + /* Try to open. */ + rc = fsFsOpenFile(&g_sd_filesystem, path, FS_OPEN_READ | FS_OPEN_WRITE, &f); + if (R_FAILED(rc)) { + return rc; + } + + /* Always close, if we opened. */ + ON_SCOPE_EXIT { + fsFileClose(&f); + }; + + /* Try to make it big enough. */ + rc = fsFileSetSize(&f, size); + if (R_FAILED(rc)) { + return rc; + } + + /* Try to write the data. */ + rc = fsFileWrite(&f, 0, data, size); + + return rc; +} + bool Utils::HasSdMitMFlag(u64 tid) { if (IsSdInitialized()) { return std::find(g_mitm_flagged_tids.begin(), g_mitm_flagged_tids.end(), tid) != g_mitm_flagged_tids.end(); diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index 5c27b6b14..ad8d176b1 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -21,6 +21,7 @@ class Utils { public: static bool IsSdInitialized(); + static Result OpenSdFile(const char *fn, int flags, FsFile *out); static Result OpenSdFileForAtmosphere(u64 title_id, const char *fn, int flags, FsFile *out); static Result OpenRomFSSdFile(u64 title_id, const char *fn, int flags, FsFile *out); @@ -31,6 +32,8 @@ class Utils { static Result OpenRomFSFile(FsFileSystem *fs, u64 title_id, const char *fn, int flags, FsFile *out); static Result OpenRomFSDir(FsFileSystem *fs, u64 title_id, const char *path, FsDir *out); + static Result SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data, size_t size); + static bool HasSdRomfsContent(u64 title_id); /* SD card Initialization + MitM detection. */ From 3ed239296a2f3ceb147d0c45dc7748aafc5fc417 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 4 Nov 2018 21:52:26 -0800 Subject: [PATCH 165/489] libstrat: Allow nullptr buffers if 0 size. (closes #255) --- stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp | 5 +++++ .../include/stratosphere/ipc/ipc_serialization.hpp | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp index 2b2bbeda3..f6a791870 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp @@ -46,6 +46,11 @@ LayeredRomFS::LayeredRomFS(std::shared_ptr<RomInterfaceStorage> s_r, std::shared Result LayeredRomFS::Read(void *buffer, size_t size, u64 offset) { + /* Size zero reads should always succeed. */ + if (size == 0) { + return 0; + } + /* Validate size. */ u64 virt_size = (*this->p_source_infos)[this->p_source_infos->size() - 1].virtual_offset + (*this->p_source_infos)[this->p_source_infos->size() - 1].size; if (offset >= virt_size) { diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp index 1e4e77afa..66225fe6e 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp @@ -306,9 +306,9 @@ struct Validator { static constexpr bool ValidateCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& h_index, size_t& cur_c_size_offset, size_t& total_c_size) { constexpr ArgType argT = GetArgType<T>(); if constexpr (argT == ArgType::InBuffer) { - return ctx->request.Buffers[a_index] != nullptr && ctx->request.BufferDirections[a_index] == BufferDirection_Send && ctx->request.BufferTypes[a_index++] == T::expected_type; + return (ctx->request.Buffers[a_index] != nullptr || ctx->request.BufferSizes[a_index] == 0) && ctx->request.BufferDirections[a_index] == BufferDirection_Send && ctx->request.BufferTypes[a_index++] == T::expected_type; } else if constexpr (argT == ArgType::OutBuffer) { - return ctx->request.Buffers[b_index] != nullptr && ctx->request.BufferDirections[b_index] == BufferDirection_Recv && ctx->request.BufferTypes[b_index++] == T::expected_type; + return (ctx->request.Buffers[b_index] != nullptr || ctx->request.BufferSizes[b_index] == 0) && ctx->request.BufferDirections[b_index] == BufferDirection_Recv && ctx->request.BufferTypes[b_index++] == T::expected_type; } else if constexpr (argT == ArgType::InPointer) { return ctx->request.Statics[x_index++] != nullptr; } else if constexpr (argT == ArgType::InHandle) { From 9142e90a048faee4dcc0cee28e0ddc531df416b3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 5 Nov 2018 18:35:21 -0800 Subject: [PATCH 166/489] libstratosphere: Use intraprocess event signaling for new waitable management --- .../include/stratosphere/waitable_manager.hpp | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp index 099c8dfbd..4f7c1a5ac 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -61,7 +61,7 @@ class WaitableManager : public SessionManagerBase { HosMutex process_lock; HosMutex signal_lock; HosMutex add_lock; - IEvent *new_waitable_event = nullptr; + bool has_new_waitables = false; IWaitable *next_signaled = nullptr; Handle cur_thread_handle = INVALID_HANDLE; @@ -80,7 +80,6 @@ class WaitableManager : public SessionManagerBase { threadCreate(&threads[i], &WaitableManager::ProcessLoop, this, ss, prio, cpuid); } } - new_waitable_event = CreateSystemEvent([](u64 timeout) { return 0; }, true); } ~WaitableManager() override { @@ -94,15 +93,20 @@ class WaitableManager : public SessionManagerBase { std::scoped_lock lk{this->add_lock}; this->to_add_waitables.push_back(w); w->SetManager(this); - this->new_waitable_event->Signal(); + this->has_new_waitables = true; + this->CancelSynchronization(); + } + + virtual void CancelSynchronization() { + svcCancelSynchronization(this->cur_thread_handle); } virtual void NotifySignaled(IWaitable *w) override { std::scoped_lock lk{this->signal_lock}; - if (this->next_signaled == nullptr && w != this->new_waitable_event) { + if (this->next_signaled == nullptr) { this->next_signaled = w; } - svcCancelSynchronization(this->cur_thread_handle); + this->CancelSynchronization(); } virtual void Process() override { @@ -141,9 +145,8 @@ class WaitableManager : public SessionManagerBase { this->next_signaled = nullptr; IWaitable *result = nullptr; - if (this->new_waitable_event->IsSignaled()) { - AddWaitablesInternal(); - } + /* Add new waitables, if any. */ + AddWaitablesInternal(); this->cur_thread_handle = GetCurrentThreadHandle(); ON_SCOPE_EXIT { @@ -174,11 +177,9 @@ class WaitableManager : public SessionManagerBase { std::sort(this->waitables.begin(), this->waitables.end(), IWaitable::Compare); /* Copy out handles. */ - handles.resize(this->waitables.size() + 1); - wait_list.resize(this->waitables.size() + 1); - handles[0] = this->new_waitable_event->GetHandle(); - wait_list[0] = this->new_waitable_event; - unsigned int num_handles = 1; + handles.resize(this->waitables.size()); + wait_list.resize(this->waitables.size()); + unsigned int num_handles = 0; for (unsigned int i = 0; i < this->waitables.size(); i++) { Handle h = this->waitables[i]->GetHandle(); if (h != INVALID_HANDLE) { @@ -202,10 +203,6 @@ class WaitableManager : public SessionManagerBase { size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); if (R_SUCCEEDED(rc)) { - if (handle_index == 0) { - AddWaitablesInternal(); - continue; - } std::for_each(waitables.begin(), waitables.begin() + w_ind, std::mem_fn(&IWaitable::UpdatePriority)); result = w; } else if (rc == 0xEA01) { @@ -213,15 +210,16 @@ class WaitableManager : public SessionManagerBase { std::for_each(waitables.begin(), waitables.end(), std::mem_fn(&IWaitable::UpdatePriority)); } else if (rc == 0xEC01) { /* svcCancelSynchronization was called. */ - std::scoped_lock lk{this->signal_lock}; - if (this->next_signaled != nullptr) result = this->next_signaled; + AddWaitablesInternal(); + { + std::scoped_lock lk{this->signal_lock}; + if (this->next_signaled != nullptr) { + result = this->next_signaled; + } + } } else if (rc != 0xF601 && rc != 0xE401) { std::abort(); - } else { - if (handle_index == 0) { - std::abort(); - } - + } else { this->waitables.erase(this->waitables.begin() + w_ind); std::for_each(waitables.begin(), waitables.begin() + w_ind - 1, std::mem_fn(&IWaitable::UpdatePriority)); delete w; @@ -235,11 +233,11 @@ class WaitableManager : public SessionManagerBase { } void AddWaitablesInternal() { - { - std::scoped_lock lk{this->add_lock}; + std::scoped_lock lk{this->add_lock}; + if (this->has_new_waitables) { this->waitables.insert(this->waitables.end(), this->to_add_waitables.begin(), this->to_add_waitables.end()); this->to_add_waitables.clear(); - this->new_waitable_event->Clear(); + this->has_new_waitables = false; } } /* Session Manager */ From 952ee4227d50bdfb5f868152506fc81b69957d66 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 5 Nov 2018 22:56:04 -0800 Subject: [PATCH 167/489] libstrat: update curthreadhandle for libnx 1.5.0 --- .../libstratosphere/include/stratosphere/waitable_manager.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp index 4f7c1a5ac..7e116a53d 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -29,8 +29,7 @@ #include "scope_guard.hpp" static inline Handle GetCurrentThreadHandle() { - /* TODO: Wait for libnx to add a way for me to call getThreadVars() */ - return *((Handle *)((uintptr_t)armGetTls() + 0x1E4)); + return threadGetCurHandle(); } struct DefaultManagerOptions { From 2894989eb78b63917b8b5ea19708c72971444fae Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 12:42:06 -0800 Subject: [PATCH 168/489] libstrat: improve waitable manager cancelsync semantics --- .../include/stratosphere/waitable_manager.hpp | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp index 7e116a53d..d1d4b171f 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -60,6 +60,7 @@ class WaitableManager : public SessionManagerBase { HosMutex process_lock; HosMutex signal_lock; HosMutex add_lock; + HosMutex cur_thread_lock; bool has_new_waitables = false; IWaitable *next_signaled = nullptr; @@ -97,7 +98,7 @@ class WaitableManager : public SessionManagerBase { } virtual void CancelSynchronization() { - svcCancelSynchronization(this->cur_thread_handle); + svcCancelSynchronization(GetProcessingThreadHandle()); } virtual void NotifySignaled(IWaitable *w) override { @@ -122,6 +123,16 @@ class WaitableManager : public SessionManagerBase { ProcessLoop(this); } private: + void SetProcessingThreadHandle(Handle h) { + std::scoped_lock<HosMutex> lk{this->cur_thread_lock}; + this->cur_thread_handle = h; + } + + Handle GetProcessingThreadHandle() { + std::scoped_lock<HosMutex> lk{this->cur_thread_lock}; + return this->cur_thread_handle; + } + static void ProcessLoop(void *t) { WaitableManager *this_ptr = (WaitableManager *)t; while (true) { @@ -141,17 +152,20 @@ class WaitableManager : public SessionManagerBase { IWaitable *GetWaitable() { std::scoped_lock lk{this->process_lock}; + + /* Set processing thread handle while in scope. */ + SetProcessingThreadHandle(GetCurrentThreadHandle()); + ON_SCOPE_EXIT { + SetProcessingThreadHandle(INVALID_HANDLE); + }; + + /* Prepare variables for result. */ this->next_signaled = nullptr; IWaitable *result = nullptr; /* Add new waitables, if any. */ AddWaitablesInternal(); - this->cur_thread_handle = GetCurrentThreadHandle(); - ON_SCOPE_EXIT { - this->cur_thread_handle = INVALID_HANDLE; - }; - /* First, see if anything's already signaled. */ for (auto &w : this->waitables) { if (w->IsSignaled()) { From bac81f4ccca90b97edf53bd2eee06cbf914947ed Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 19:09:58 -0800 Subject: [PATCH 169/489] libstrat: fix potential oob deref in WaitableManager (closes #256) --- .../include/stratosphere/waitable_manager.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp index d1d4b171f..2f48f42f1 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -211,11 +211,10 @@ class WaitableManager : public SessionManagerBase { /* Wait forever. */ rc = svcWaitSynchronization(&handle_index, handles.data(), num_handles, U64_MAX); - - IWaitable *w = wait_list[handle_index]; - size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); - + if (R_SUCCEEDED(rc)) { + IWaitable *w = wait_list[handle_index]; + size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); std::for_each(waitables.begin(), waitables.begin() + w_ind, std::mem_fn(&IWaitable::UpdatePriority)); result = w; } else if (rc == 0xEA01) { @@ -233,6 +232,8 @@ class WaitableManager : public SessionManagerBase { } else if (rc != 0xF601 && rc != 0xE401) { std::abort(); } else { + IWaitable *w = wait_list[handle_index]; + size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); this->waitables.erase(this->waitables.begin() + w_ind); std::for_each(waitables.begin(), waitables.begin() + w_ind - 1, std::mem_fn(&IWaitable::UpdatePriority)); delete w; From 147f3c690a6cce7dd89e8e91a2bf9d2dd79c9ab9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 22:40:19 -0800 Subject: [PATCH 170/489] libstrat: Significantly cleanup waitable manager result handling. --- .../stratosphere/ipc/ipc_serialization.hpp | 18 +++--- .../stratosphere/ipc/ipc_service_session.hpp | 6 +- .../include/stratosphere/iwaitable.hpp | 6 +- .../include/stratosphere/waitable_manager.hpp | 60 +++++++++++++------ 4 files changed, 58 insertions(+), 32 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp index 66225fe6e..7ce9bd39e 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp @@ -612,14 +612,16 @@ constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { ON_SCOPE_EXIT { /* Clean up objects as necessary. */ - if (IsDomainObject(ctx->obj_holder) && R_FAILED(rc)) { - for (unsigned int i = 0; i < num_out_objects; i++) { - ctx->obj_holder->GetServiceObject<IDomainObject>()->FreeObject(ctx->out_object_ids[i]); - } - } else { - for (unsigned int i = 0; i < num_out_objects; i++) { - svcCloseHandle(ctx->out_object_server_handles[i]); - svcCloseHandle(ctx->out_handles[CommandMetaData::NumOutHandles + i].handle); + if (R_FAILED(rc)) { + if (IsDomainObject(ctx->obj_holder)) { + for (unsigned int i = 0; i < num_out_objects; i++) { + ctx->obj_holder->GetServiceObject<IDomainObject>()->FreeObject(ctx->out_object_ids[i]); + } + } else { + for (unsigned int i = 0; i < num_out_objects; i++) { + svcCloseHandle(ctx->out_object_server_handles[i]); + svcCloseHandle(ctx->out_handles[CommandMetaData::NumOutHandles + i].handle); + } } } diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp index 3b25e8721..752c533e5 100644 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp @@ -234,16 +234,14 @@ class ServiceSession : public IWaitable return ctx.rc; } - virtual void HandleDeferred() override { + virtual Result HandleDeferred() override { memcpy(armGetTls(), this->backup_tls, sizeof(this->backup_tls)); Result rc = this->HandleReceived(); if (rc != RESULT_DEFER_SESSION) { this->SetDeferred(false); - if (rc == 0xF601) { - svcCloseHandle(this->GetHandle()); - } } + return rc; } virtual Result HandleSignaled(u64 timeout) { diff --git a/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp b/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp index 175996067..d5721f849 100644 --- a/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp @@ -32,8 +32,10 @@ class IWaitable { public: virtual ~IWaitable() = default; - virtual void HandleDeferred() { - /* ... */ + virtual Result HandleDeferred() { + /* By default, HandleDeferred panics, because object shouldn't be deferrable. */ + std::abort(); + return 0; } bool IsSignaled() { diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp index 2f48f42f1..569817c6b 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -55,12 +55,14 @@ class WaitableManager : public SessionManagerBase { /* Waitable Manager */ std::vector<IWaitable *> to_add_waitables; std::vector<IWaitable *> waitables; + std::vector<IWaitable *> deferred_waitables; u32 num_threads; Thread *threads; HosMutex process_lock; HosMutex signal_lock; HosMutex add_lock; HosMutex cur_thread_lock; + HosMutex deferred_lock; bool has_new_waitables = false; IWaitable *next_signaled = nullptr; @@ -84,7 +86,9 @@ class WaitableManager : public SessionManagerBase { ~WaitableManager() override { /* This should call the destructor for every waitable. */ + std::for_each(to_add_waitables.begin(), to_add_waitables.end(), std::default_delete<IWaitable>{}); std::for_each(waitables.begin(), waitables.end(), std::default_delete<IWaitable>{}); + std::for_each(deferred_waitables.begin(), deferred_waitables.end(), std::default_delete<IWaitable>{}); /* TODO: Exit the threads? */ } @@ -143,10 +147,37 @@ class WaitableManager : public SessionManagerBase { /* Close! */ delete w; } else { - this_ptr->AddWaitable(w); + if (w->IsDeferred()) { + std::scoped_lock lk{this_ptr->deferred_lock}; + this_ptr->deferred_waitables.push_back(w); + } else { + this_ptr->AddWaitable(w); + } + } + } + + /* We finished processing, and maybe that means we can stop deferring an object. */ + { + std::scoped_lock lk{this_ptr->deferred_lock}; + + for (size_t i = 0; i < this_ptr->deferred_waitables.size(); i++) { + auto w = this_ptr->deferred_waitables[i]; + Result rc = w->HandleDeferred(); + if (rc == 0xF601 || !w->IsDeferred()) { + /* Remove from the deferred list. */ + this_ptr->deferred_waitables.erase(this_ptr->deferred_waitables.begin() + i); + if (rc == 0xF601) { + /* Delete the closed waitable. */ + delete w; + } else { + /* Add to the waitables list. */ + this_ptr->AddWaitable(w); + } + /* Subtract one from i, to avoid skipping a deferred session. */ + i--; + } } } - } } @@ -193,6 +224,8 @@ class WaitableManager : public SessionManagerBase { handles.resize(this->waitables.size()); wait_list.resize(this->waitables.size()); unsigned int num_handles = 0; + + /* Try to add waitables to wait list. */ for (unsigned int i = 0; i < this->waitables.size(); i++) { Handle h = this->waitables[i]->GetHandle(); if (h != INVALID_HANDLE) { @@ -201,21 +234,13 @@ class WaitableManager : public SessionManagerBase { } } - - /* Do deferred callback for each waitable. This has to happen before we wait on anything else. */ - for (auto & waitable : this->waitables) { - if (waitable->IsDeferred()) { - waitable->HandleDeferred(); - } - } - /* Wait forever. */ rc = svcWaitSynchronization(&handle_index, handles.data(), num_handles, U64_MAX); if (R_SUCCEEDED(rc)) { IWaitable *w = wait_list[handle_index]; size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); - std::for_each(waitables.begin(), waitables.begin() + w_ind, std::mem_fn(&IWaitable::UpdatePriority)); + std::for_each(waitables.begin(), waitables.begin() + w_ind + 1, std::mem_fn(&IWaitable::UpdatePriority)); result = w; } else if (rc == 0xEA01) { /* Timeout: Just update priorities. */ @@ -229,14 +254,13 @@ class WaitableManager : public SessionManagerBase { result = this->next_signaled; } } - } else if (rc != 0xF601 && rc != 0xE401) { + } else { + /* TODO: Consider the following cases that this covers: */ + /* 7601: Thread termination requested. */ + /* E401: Handle is dead. */ + /* E601: Handle list address invalid. */ + /* EE01: Too many handles. */ std::abort(); - } else { - IWaitable *w = wait_list[handle_index]; - size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); - this->waitables.erase(this->waitables.begin() + w_ind); - std::for_each(waitables.begin(), waitables.begin() + w_ind - 1, std::mem_fn(&IWaitable::UpdatePriority)); - delete w; } } } From 8426a4dc7789d9095c9b28bdb9d0855d8e37b373 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 22:59:30 -0800 Subject: [PATCH 171/489] libstrat: Use iterators when looping deferred waitables --- .../include/stratosphere/waitable_manager.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp index 569817c6b..c47ce81e3 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -160,12 +160,12 @@ class WaitableManager : public SessionManagerBase { { std::scoped_lock lk{this_ptr->deferred_lock}; - for (size_t i = 0; i < this_ptr->deferred_waitables.size(); i++) { - auto w = this_ptr->deferred_waitables[i]; + for (auto it = this_ptr->deferred_waitables.begin(); it != this_ptr->deferred_waitables.end();) { + auto w = *it; Result rc = w->HandleDeferred(); if (rc == 0xF601 || !w->IsDeferred()) { - /* Remove from the deferred list. */ - this_ptr->deferred_waitables.erase(this_ptr->deferred_waitables.begin() + i); + /* Remove from the deferred list, set iterator. */ + it = this_ptr->deferred_waitables.erase(it); if (rc == 0xF601) { /* Delete the closed waitable. */ delete w; @@ -173,8 +173,9 @@ class WaitableManager : public SessionManagerBase { /* Add to the waitables list. */ this_ptr->AddWaitable(w); } - /* Subtract one from i, to avoid skipping a deferred session. */ - i--; + } else { + /* Move on to the next deferred waitable. */ + it++; } } } From e65bee0d6ad4b52f83802a1550c00706fe2e5aed Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 3 Nov 2018 22:05:42 -0700 Subject: [PATCH 172/489] libstratosphere: Implement message queues --- .../libstratosphere/include/stratosphere.hpp | 1 + .../include/stratosphere/hossynch.hpp | 39 ++- .../include/stratosphere/message_queue.hpp | 73 ++++++ .../libstratosphere/source/message_queue.cpp | 235 ++++++++++++++++++ 4 files changed, 345 insertions(+), 3 deletions(-) create mode 100644 stratosphere/libstratosphere/include/stratosphere/message_queue.hpp create mode 100644 stratosphere/libstratosphere/source/message_queue.cpp diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp index 503f6f7f1..209e80e7e 100644 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -20,6 +20,7 @@ #include "stratosphere/scope_guard.hpp" #include "stratosphere/hossynch.hpp" +#include "stratosphere/message_queue.hpp" #include "stratosphere/iwaitable.hpp" #include "stratosphere/event.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp index 73ca16d76..64df3eafb 100644 --- a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp @@ -16,6 +16,7 @@ #pragma once #include <switch.h> +#include <switch/arm/counter.h> #include <mutex> class HosMutex { @@ -100,15 +101,15 @@ class HosCondVar { condvarInit(&cv); } - Result WaitTimeout(u64 timeout, HosMutex *hm) { - return WaitTimeout(timeout, hm->GetMutex()); + Result TimedWait(u64 timeout, HosMutex *hm) { + return TimedWait(timeout, hm->GetMutex()); } Result Wait(HosMutex *hm) { return Wait(hm->GetMutex()); } - Result WaitTimeout(u64 timeout, Mutex *m) { + Result TimedWait(u64 timeout, Mutex *m) { return condvarWaitTimeout(&cv, m, timeout); } @@ -153,3 +154,35 @@ class HosSemaphore { return semaphoreTryWait(&s); } }; + +class TimeoutHelper { + private: + u64 end_tick; + public: + TimeoutHelper(u64 ns) { + /* Special case zero-time timeouts. */ + if (ns == 0) { + end_tick = 0; + return; + } + + u64 cur_tick = armGetSystemTick(); + this->end_tick = cur_tick + NsToTick(ns) + 1; + } + + static inline u64 NsToTick(u64 ns) { + return (ns * 12) / 625; + } + + static inline u64 TickToNs(u64 tick) { + return (tick * 625) / 12; + } + + bool TimedOut() { + if (this->end_tick == 0) { + return true; + } + + return armGetSystemTick() >= this->end_tick; + } +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp b/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp new file mode 100644 index 000000000..f8b4c6591 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include "hossynch.hpp" +#include <memory> + +class HosMessageQueue { + private: + HosMutex queue_lock; + HosCondVar cv_not_full; + HosCondVar cv_not_empty; + std::unique_ptr<uintptr_t[]> buffer; + size_t capacity; + + size_t count = 0; + size_t offset = 0; + public: + HosMessageQueue(size_t c) : capacity(c) { + this->buffer = std::make_unique<uintptr_t[]>(this->capacity); + } + + HosMessageQueue(std::unique_ptr<uintptr_t[]> buf, size_t c) : buffer(std::move(buf)), capacity(c) { } + + /* Sending (FIFO functionality) */ + void Send(uintptr_t data); + bool TrySend(uintptr_t data); + bool TimedSend(uintptr_t data, u64 timeout); + + /* Sending (LIFO functionality) */ + void SendNext(uintptr_t data); + bool TrySendNext(uintptr_t data); + bool TimedSendNext(uintptr_t data, u64 timeout); + + /* Receive functionality */ + void Receive(uintptr_t *out); + bool TryReceive(uintptr_t *out); + bool TimedReceive(uintptr_t *out, u64 timeout); + + /* Peek functionality */ + void Peek(uintptr_t *out); + bool TryPeek(uintptr_t *out); + bool TimedPeek(uintptr_t *out, u64 timeout); + private: + void SendInternal(uintptr_t data); + void SendNextInternal(uintptr_t data); + uintptr_t ReceiveInternal(); + uintptr_t PeekInternal(); + + bool IsFull() { + return this->count >= this->capacity; + } + + bool IsEmpty() { + return this->count == 0; + } + +}; + diff --git a/stratosphere/libstratosphere/source/message_queue.cpp b/stratosphere/libstratosphere/source/message_queue.cpp new file mode 100644 index 000000000..dc24cd937 --- /dev/null +++ b/stratosphere/libstratosphere/source/message_queue.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <mutex> +#include <switch.h> +#include <stratosphere.hpp> + + +void HosMessageQueue::Send(uintptr_t data) { + /* Acquire mutex, wait sendable. */ + std::scoped_lock<HosMutex> lock(this->queue_lock); + + while (this->IsFull()) { + this->cv_not_full.Wait(&this->queue_lock); + } + + /* Send, signal. */ + this->SendInternal(data); + this->cv_not_empty.WakeAll(); +} + +bool HosMessageQueue::TrySend(uintptr_t data) { + std::scoped_lock<HosMutex> lock(this->queue_lock); + if (this->IsFull()) { + return false; + } + + /* Send, signal. */ + this->SendInternal(data); + this->cv_not_empty.WakeAll(); + return true; +} + +bool HosMessageQueue::TimedSend(uintptr_t data, u64 timeout) { + std::scoped_lock<HosMutex> lock(this->queue_lock); + TimeoutHelper timeout_helper(timeout); + + while (this->IsFull()) { + if (timeout_helper.TimedOut()) { + return false; + } + + this->cv_not_full.TimedWait(timeout, &this->queue_lock); + } + + /* Send, signal. */ + this->SendInternal(data); + this->cv_not_empty.WakeAll(); + return true; +} + +void HosMessageQueue::SendNext(uintptr_t data) { + /* Acquire mutex, wait sendable. */ + std::scoped_lock<HosMutex> lock(this->queue_lock); + + while (this->IsFull()) { + this->cv_not_full.Wait(&this->queue_lock); + } + + /* Send, signal. */ + this->SendNextInternal(data); + this->cv_not_empty.WakeAll(); +} + +bool HosMessageQueue::TrySendNext(uintptr_t data) { + std::scoped_lock<HosMutex> lock(this->queue_lock); + if (this->IsFull()) { + return false; + } + + /* Send, signal. */ + this->SendNextInternal(data); + this->cv_not_empty.WakeAll(); + return true; +} + +bool HosMessageQueue::TimedSendNext(uintptr_t data, u64 timeout) { + std::scoped_lock<HosMutex> lock(this->queue_lock); + TimeoutHelper timeout_helper(timeout); + + while (this->IsFull()) { + if (timeout_helper.TimedOut()) { + return false; + } + + this->cv_not_full.TimedWait(timeout, &this->queue_lock); + } + + /* Send, signal. */ + this->SendNextInternal(data); + this->cv_not_empty.WakeAll(); + return true; +} + +void HosMessageQueue::Receive(uintptr_t *out) { + /* Acquire mutex, wait receivable. */ + std::scoped_lock<HosMutex> lock(this->queue_lock); + + while (this->IsEmpty()) { + this->cv_not_empty.Wait(&this->queue_lock); + } + + /* Receive, signal. */ + *out = this->ReceiveInternal(); + this->cv_not_full.WakeAll(); +} +bool HosMessageQueue::TryReceive(uintptr_t *out) { + /* Acquire mutex, wait receivable. */ + std::scoped_lock<HosMutex> lock(this->queue_lock); + + if (this->IsEmpty()) { + return false; + } + + /* Receive, signal. */ + *out = this->ReceiveInternal(); + this->cv_not_full.WakeAll(); + return true; +} + +bool HosMessageQueue::TimedReceive(uintptr_t *out, u64 timeout) { + std::scoped_lock<HosMutex> lock(this->queue_lock); + TimeoutHelper timeout_helper(timeout); + + while (this->IsEmpty()) { + if (timeout_helper.TimedOut()) { + return false; + } + + this->cv_not_empty.TimedWait(timeout, &this->queue_lock); + } + + /* Receive, signal. */ + *out = this->ReceiveInternal(); + this->cv_not_full.WakeAll(); + return true; +} + +void HosMessageQueue::Peek(uintptr_t *out) { + /* Acquire mutex, wait receivable. */ + std::scoped_lock<HosMutex> lock(this->queue_lock); + + while (this->IsEmpty()) { + this->cv_not_empty.Wait(&this->queue_lock); + } + + /* Peek. */ + *out = this->PeekInternal(); +} + +bool HosMessageQueue::TryPeek(uintptr_t *out) { + /* Acquire mutex, wait receivable. */ + std::scoped_lock<HosMutex> lock(this->queue_lock); + + if (this->IsEmpty()) { + return false; + } + + /* Peek. */ + *out = this->PeekInternal(); + return true; +} + +bool HosMessageQueue::TimedPeek(uintptr_t *out, u64 timeout) { + std::scoped_lock<HosMutex> lock(this->queue_lock); + TimeoutHelper timeout_helper(timeout); + + while (this->IsEmpty()) { + if (timeout_helper.TimedOut()) { + return false; + } + + this->cv_not_empty.TimedWait(timeout, &this->queue_lock); + } + + /* Peek. */ + *out = this->PeekInternal(); + return true; +} + +void HosMessageQueue::SendInternal(uintptr_t data) { + /* Ensure we don't corrupt the queue, but this should never happen. */ + if (this->count >= this->capacity) { + std::abort(); + } + + /* Write data to tail of queue. */ + this->buffer[(this->count++ + this->offset) % this->capacity] = data; +} + +void HosMessageQueue::SendNextInternal(uintptr_t data) { + /* Ensure we don't corrupt the queue, but this should never happen. */ + if (this->count >= this->capacity) { + std::abort(); + } + + /* Write data to head of queue. */ + this->offset = (this->offset + this->capacity - 1) % this->capacity; + this->buffer[this->offset] = data; + this->count++; +} + +uintptr_t HosMessageQueue::ReceiveInternal() { + /* Ensure we don't corrupt the queue, but this should never happen. */ + if (this->count == 0) { + std::abort(); + } + + uintptr_t data = this->buffer[this->offset]; + this->offset = (this->offset + 1) % this->capacity; + this->count--; + return data; +} + +uintptr_t HosMessageQueue::PeekInternal() { + /* Ensure we don't corrupt the queue, but this should never happen. */ + if (this->count == 0) { + std::abort(); + } + + return this->buffer[this->offset]; +} \ No newline at end of file From 9b1a2451b04fcdecc2a63b267b14223ea23526c0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 23:18:46 -0800 Subject: [PATCH 173/489] libstratosphere: Add thread primitive, WaitableManager->RequestStop() --- .../include/stratosphere/hossynch.hpp | 27 ++++ .../include/stratosphere/waitable_manager.hpp | 129 +++++++++++------- .../stratosphere/waitable_manager_base.hpp | 3 +- 3 files changed, 109 insertions(+), 50 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp index 64df3eafb..4f0cbd2de 100644 --- a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp @@ -185,4 +185,31 @@ class TimeoutHelper { return armGetSystemTick() >= this->end_tick; } +}; + +class HosThread { + private: + Thread thr = {0}; + public: + HosThread() {} + + Result Initialize(ThreadFunc entry, void *arg, size_t stack_sz, int prio, int cpuid = -2) { + return threadCreate(&this->thr, entry, arg, stack_sz, prio, cpuid); + } + + Handle GetHandle() const { + return this->thr.handle; + } + + Result Start() { + return threadStart(&this->thr); + } + + Result Join() { + Result rc = threadWaitForExit(&this->thr); + if (R_SUCCEEDED(rc)) { + rc = threadClose(&this->thr); + } + return rc; + } }; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp index c47ce81e3..47244e561 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - + #pragma once #include <switch.h> @@ -51,46 +51,50 @@ class WaitableManager : public SessionManagerBase { std::array<std::weak_ptr<IDomainObject>, ManagerOptions::MaxDomains> domains; std::array<bool, ManagerOptions::MaxDomains> is_domain_allocated; std::array<DomainEntry, ManagerOptions::MaxDomainObjects> domain_objects; - + /* Waitable Manager */ std::vector<IWaitable *> to_add_waitables; std::vector<IWaitable *> waitables; std::vector<IWaitable *> deferred_waitables; - u32 num_threads; - Thread *threads; + + u32 num_extra_threads = 0; + HosThread *threads = nullptr; + HosMutex process_lock; HosMutex signal_lock; HosMutex add_lock; HosMutex cur_thread_lock; HosMutex deferred_lock; bool has_new_waitables = false; - + std::atomic<bool> should_stop = false; + IWaitable *next_signaled = nullptr; + Handle main_thread_handle = INVALID_HANDLE; Handle cur_thread_handle = INVALID_HANDLE; public: - WaitableManager(u32 n, u32 ss = 0x8000) : num_threads(n-1) { + WaitableManager(u32 n, u32 ss = 0x8000) : num_extra_threads(n-1) { u32 prio; - u32 cpuid = svcGetCurrentProcessorNumber(); Result rc; - threads = new Thread[num_threads]; - if (num_threads) { + if (num_extra_threads) { + threads = new HosThread[num_extra_threads]; if (R_FAILED((rc = svcGetThreadPriority(&prio, CUR_THREAD_HANDLE)))) { fatalSimple(rc); } - for (unsigned int i = 0; i < num_threads; i++) { - threads[i] = {0}; - threadCreate(&threads[i], &WaitableManager::ProcessLoop, this, ss, prio, cpuid); + for (unsigned int i = 0; i < num_extra_threads; i++) { + if (R_FAILED(threads[i].Initialize(&WaitableManager::ProcessLoop, this, ss, prio))) { + std::abort(); + } } } } - + ~WaitableManager() override { /* This should call the destructor for every waitable. */ std::for_each(to_add_waitables.begin(), to_add_waitables.end(), std::default_delete<IWaitable>{}); std::for_each(waitables.begin(), waitables.end(), std::default_delete<IWaitable>{}); std::for_each(deferred_waitables.begin(), deferred_waitables.end(), std::default_delete<IWaitable>{}); - - /* TODO: Exit the threads? */ + + /* If we've reached here, we should already have exited the threads. */ } virtual void AddWaitable(IWaitable *w) override { @@ -101,10 +105,15 @@ class WaitableManager : public SessionManagerBase { this->CancelSynchronization(); } + virtual void RequestStop() { + this->should_stop = true; + this->CancelSynchronization(); + } + virtual void CancelSynchronization() { svcCancelSynchronization(GetProcessingThreadHandle()); } - + virtual void NotifySignaled(IWaitable *w) override { std::scoped_lock lk{this->signal_lock}; if (this->next_signaled == nullptr) { @@ -112,18 +121,21 @@ class WaitableManager : public SessionManagerBase { } this->CancelSynchronization(); } - + virtual void Process() override { /* Add initial set of waitables. */ AddWaitablesInternal(); - + + /* Set main thread handle. */ + this->main_thread_handle = GetCurrentThreadHandle(); + Result rc; - for (unsigned int i = 0; i < num_threads; i++) { - if (R_FAILED((rc = threadStart(&threads[i])))) { + for (unsigned int i = 0; i < num_extra_threads; i++) { + if (R_FAILED((rc = threads[i].Start()))) { fatalSimple(rc); } } - + ProcessLoop(this); } private: @@ -131,35 +143,46 @@ class WaitableManager : public SessionManagerBase { std::scoped_lock<HosMutex> lk{this->cur_thread_lock}; this->cur_thread_handle = h; } - + Handle GetProcessingThreadHandle() { std::scoped_lock<HosMutex> lk{this->cur_thread_lock}; return this->cur_thread_handle; } - + static void ProcessLoop(void *t) { WaitableManager *this_ptr = (WaitableManager *)t; while (true) { IWaitable *w = this_ptr->GetWaitable(); + if (this_ptr->should_stop) { + if (GetCurrentThreadHandle() == this_ptr->main_thread_handle) { + /* Join all threads but the main one. */ + for (unsigned int i = 0; i < this_ptr->num_extra_threads; i++) { + this_ptr->threads[i].Join(); + } + break; + } else { + svcExitThread(); + } + } if (w) { Result rc = w->HandleSignaled(0); if (rc == 0xF601) { /* Close! */ delete w; } else { - if (w->IsDeferred()) { + if (w->IsDeferred()) { std::scoped_lock lk{this_ptr->deferred_lock}; this_ptr->deferred_waitables.push_back(w); - } else { + } else { this_ptr->AddWaitable(w); } } } - + /* We finished processing, and maybe that means we can stop deferring an object. */ { std::scoped_lock lk{this_ptr->deferred_lock}; - + for (auto it = this_ptr->deferred_waitables.begin(); it != this_ptr->deferred_waitables.end();) { auto w = *it; Result rc = w->HandleDeferred(); @@ -181,46 +204,50 @@ class WaitableManager : public SessionManagerBase { } } } - + IWaitable *GetWaitable() { std::scoped_lock lk{this->process_lock}; - + /* Set processing thread handle while in scope. */ SetProcessingThreadHandle(GetCurrentThreadHandle()); ON_SCOPE_EXIT { SetProcessingThreadHandle(INVALID_HANDLE); }; - + /* Prepare variables for result. */ this->next_signaled = nullptr; IWaitable *result = nullptr; - + + if (this->should_stop) { + return nullptr; + } + /* Add new waitables, if any. */ AddWaitablesInternal(); - + /* First, see if anything's already signaled. */ for (auto &w : this->waitables) { if (w->IsSignaled()) { result = w; } } - + /* It's possible somebody signaled us while we were iterating. */ { std::scoped_lock lk{this->signal_lock}; if (this->next_signaled != nullptr) result = this->next_signaled; } - + if (result == nullptr) { std::vector<Handle> handles; std::vector<IWaitable *> wait_list; - + int handle_index = 0; Result rc; while (result == nullptr) { /* Sort waitables by priority. */ std::sort(this->waitables.begin(), this->waitables.end(), IWaitable::Compare); - + /* Copy out handles. */ handles.resize(this->waitables.size()); wait_list.resize(this->waitables.size()); @@ -234,10 +261,14 @@ class WaitableManager : public SessionManagerBase { handles[num_handles++] = h; } } - + /* Wait forever. */ rc = svcWaitSynchronization(&handle_index, handles.data(), num_handles, U64_MAX); - + + if (this->should_stop) { + return nullptr; + } + if (R_SUCCEEDED(rc)) { IWaitable *w = wait_list[handle_index]; size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); @@ -265,12 +296,12 @@ class WaitableManager : public SessionManagerBase { } } } - + this->waitables.erase(std::remove_if(this->waitables.begin(), this->waitables.end(), [&](IWaitable *w) { return w == result; }), this->waitables.end()); - + return result; } - + void AddWaitablesInternal() { std::scoped_lock lk{this->add_lock}; if (this->has_new_waitables) { @@ -284,7 +315,7 @@ class WaitableManager : public SessionManagerBase { virtual void AddSession(Handle server_h, ServiceObjectHolder &&service) override { this->AddWaitable(new ServiceSession(server_h, ManagerOptions::PointerBufferSize, std::move(service))); } - + /* Domain Manager */ public: virtual std::shared_ptr<IDomainObject> AllocateDomain() override { @@ -299,7 +330,7 @@ class WaitableManager : public SessionManagerBase { } return nullptr; } - + void FreeDomain(IDomainObject *domain) override { std::scoped_lock lk{this->domain_lock}; for (size_t i = 0; i < ManagerOptions::MaxDomainObjects; i++) { @@ -313,7 +344,7 @@ class WaitableManager : public SessionManagerBase { } } } - + virtual Result ReserveObject(IDomainObject *domain, u32 *out_object_id) override { std::scoped_lock lk{this->domain_lock}; for (size_t i = 0; i < ManagerOptions::MaxDomainObjects; i++) { @@ -325,7 +356,7 @@ class WaitableManager : public SessionManagerBase { } return 0x25A0A; } - + virtual Result ReserveSpecificObject(IDomainObject *domain, u32 object_id) override { std::scoped_lock lk{this->domain_lock}; if (this->domain_objects[object_id-1].owner == nullptr) { @@ -334,14 +365,14 @@ class WaitableManager : public SessionManagerBase { } return 0x25A0A; } - + virtual void SetObject(IDomainObject *domain, u32 object_id, ServiceObjectHolder&& holder) override { std::scoped_lock lk{this->domain_lock}; if (this->domain_objects[object_id-1].owner == domain) { this->domain_objects[object_id-1].obj_holder = std::move(holder); } } - + virtual ServiceObjectHolder *GetObject(IDomainObject *domain, u32 object_id) override { std::scoped_lock lk{this->domain_lock}; if (this->domain_objects[object_id-1].owner == domain) { @@ -349,7 +380,7 @@ class WaitableManager : public SessionManagerBase { } return nullptr; } - + virtual Result FreeObject(IDomainObject *domain, u32 object_id) override { std::scoped_lock lk{this->domain_lock}; if (this->domain_objects[object_id-1].owner == domain) { @@ -359,7 +390,7 @@ class WaitableManager : public SessionManagerBase { } return 0x3D80B; } - + virtual Result ForceFreeObject(u32 object_id) override { std::scoped_lock lk{this->domain_lock}; if (this->domain_objects[object_id-1].owner != nullptr) { diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp index 777403b21..35242aac2 100644 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp @@ -31,7 +31,8 @@ class WaitableManagerBase { virtual void AddWaitable(IWaitable *w) = 0; virtual void NotifySignaled(IWaitable *w) = 0; - + + virtual void RequestStop() = 0; virtual void Process() = 0; }; From 65385544858a7244313ae63717aeb8fa2c25e7e6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 23:20:48 -0800 Subject: [PATCH 174/489] libstratosphere: add ReadOnlySystemEvent helper --- .../libstratosphere/include/stratosphere/event.hpp | 5 +++++ .../include/stratosphere/message_queue.hpp | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/stratosphere/libstratosphere/include/stratosphere/event.hpp b/stratosphere/libstratosphere/include/stratosphere/event.hpp index ba726d557..153cdd0df 100644 --- a/stratosphere/libstratosphere/include/stratosphere/event.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/event.hpp @@ -125,3 +125,8 @@ template <bool a = false> static IEvent *CreateWriteOnlySystemEvent() { return CreateSystemEvent([](u64 timeout) { std::abort(); return 0; }, a); } + +template <class F> +static IEvent *LoadReadOnlySystemEvent(Handle r_h, F f, bool autoclear = false) { + return new HosEvent<F>(r_h, f, autoclear); +} diff --git a/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp b/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp index f8b4c6591..8ed2bae7f 100644 --- a/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp +++ b/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp @@ -56,11 +56,6 @@ class HosMessageQueue { bool TryPeek(uintptr_t *out); bool TimedPeek(uintptr_t *out, u64 timeout); private: - void SendInternal(uintptr_t data); - void SendNextInternal(uintptr_t data); - uintptr_t ReceiveInternal(); - uintptr_t PeekInternal(); - bool IsFull() { return this->count >= this->capacity; } @@ -68,6 +63,11 @@ class HosMessageQueue { bool IsEmpty() { return this->count == 0; } + + void SendInternal(uintptr_t data); + void SendNextInternal(uintptr_t data); + uintptr_t ReceiveInternal(); + uintptr_t PeekInternal(); }; From 3b8bb325e8138ee50b4dc188b8fbda533756eef2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 23:43:59 -0800 Subject: [PATCH 175/489] pm: Use non-system event for process tracking. --- stratosphere/pm/source/pm_registration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index 529b892e8..362c47fe5 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -48,7 +48,7 @@ void Registration::InitializeSystemResources() { g_debug_application_event = CreateWriteOnlySystemEvent(); /* Auto-clear non-system event. */ - g_process_launch_start_event = CreateSystemEvent(&Registration::ProcessLaunchStartCallback); + g_process_launch_start_event = CreateHosEvent(&Registration::ProcessLaunchStartCallback); ResourceLimitUtils::InitializeLimits(); } From 5ef01edab5035e88c935d3db6059c70a6fcded85 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 8 Nov 2018 01:12:30 -0800 Subject: [PATCH 176/489] Delete libstratosphere in prep for submodule --- stratosphere/libstratosphere/.gitignore | 4 - stratosphere/libstratosphere/Makefile | 150 ---- .../libstratosphere/include/meta_tools.hpp | 53 -- .../libstratosphere/include/stratosphere.hpp | 33 - .../include/stratosphere/event.hpp | 132 ---- .../include/stratosphere/firmware_version.hpp | 49 -- .../include/stratosphere/hossynch.hpp | 215 ------ .../include/stratosphere/ipc.hpp | 22 - .../include/stratosphere/ipc/ipc_buffers.hpp | 117 --- .../stratosphere/ipc/ipc_domain_object.hpp | 128 ---- .../include/stratosphere/ipc/ipc_out.hpp | 75 -- .../stratosphere/ipc/ipc_response_context.hpp | 44 -- .../stratosphere/ipc/ipc_serialization.hpp | 666 ------------------ .../stratosphere/ipc/ipc_service_object.hpp | 130 ---- .../stratosphere/ipc/ipc_service_session.hpp | 356 ---------- .../ipc/ipc_session_manager_base.hpp | 34 - .../include/stratosphere/ipc/ipc_special.hpp | 144 ---- .../include/stratosphere/iwaitable.hpp | 80 --- .../include/stratosphere/message_queue.hpp | 73 -- .../include/stratosphere/mitm.hpp | 26 - .../stratosphere/mitm/imitmserviceobject.hpp | 43 -- .../stratosphere/mitm/mitm_query_service.hpp | 50 -- .../include/stratosphere/mitm/mitm_server.hpp | 112 --- .../stratosphere/mitm/mitm_session.hpp | 316 --------- .../include/stratosphere/mitm/sm_mitm.h | 24 - .../include/stratosphere/scope_guard.hpp | 61 -- .../include/stratosphere/servers.hpp | 87 --- .../include/stratosphere/services.hpp | 21 - .../include/stratosphere/services/smm_ams.h | 31 - .../include/stratosphere/version_check.hpp | 66 -- .../include/stratosphere/waitable_manager.hpp | 404 ----------- .../stratosphere/waitable_manager_base.hpp | 38 - .../libstratosphere/source/message_queue.cpp | 235 ------ .../source/mitm_query_service.cpp | 42 -- stratosphere/libstratosphere/source/sm_mitm.c | 190 ----- stratosphere/libstratosphere/source/smm_ams.c | 69 -- 36 files changed, 4320 deletions(-) delete mode 100644 stratosphere/libstratosphere/.gitignore delete mode 100644 stratosphere/libstratosphere/Makefile delete mode 100644 stratosphere/libstratosphere/include/meta_tools.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/event.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/hossynch.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_session_manager_base.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/message_queue.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/mitm/sm_mitm.h delete mode 100644 stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/servers.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/services.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/services/smm_ams.h delete mode 100644 stratosphere/libstratosphere/include/stratosphere/version_check.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp delete mode 100644 stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp delete mode 100644 stratosphere/libstratosphere/source/message_queue.cpp delete mode 100644 stratosphere/libstratosphere/source/mitm_query_service.cpp delete mode 100644 stratosphere/libstratosphere/source/sm_mitm.c delete mode 100644 stratosphere/libstratosphere/source/smm_ams.c diff --git a/stratosphere/libstratosphere/.gitignore b/stratosphere/libstratosphere/.gitignore deleted file mode 100644 index 75ebfc783..000000000 --- a/stratosphere/libstratosphere/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -debug -release -lib -*.bz2 diff --git a/stratosphere/libstratosphere/Makefile b/stratosphere/libstratosphere/Makefile deleted file mode 100644 index 70ba1949b..000000000 --- a/stratosphere/libstratosphere/Makefile +++ /dev/null @@ -1,150 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro") -endif - -TOPDIR ?= $(CURDIR) -include $(DEVKITPRO)/libnx/switch_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -#--------------------------------------------------------------------------------- -TARGET := $(notdir $(CURDIR)) -SOURCES := source -DATA := data -INCLUDES := include ../../common/include - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE - -CFLAGS := -g -Wall -O2 -ffunction-sections \ - $(ARCH) $(DEFINES) - -CFLAGS += $(INCLUDE) -D__SWITCH__ - -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -LIBS := -lnx - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(LIBNX) - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I. \ - -iquote $(CURDIR)/include/switch/ - -.PHONY: clean all - -#--------------------------------------------------------------------------------- -all: lib/$(TARGET).a lib/$(TARGET)d.a - -lib: - @[ -d $@ ] || mkdir -p $@ - -release: - @[ -d $@ ] || mkdir -p $@ - -debug: - @[ -d $@ ] || mkdir -p $@ - -lib/$(TARGET).a : lib release $(SOURCES) $(INCLUDES) - @$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \ - BUILD_CFLAGS="-DNDEBUG=1 -O2" \ - DEPSDIR=$(CURDIR)/release \ - --no-print-directory -C release \ - -f $(CURDIR)/Makefile - -lib/$(TARGET)d.a : lib debug $(SOURCES) $(INCLUDES) - @$(MAKE) BUILD=debug OUTPUT=$(CURDIR)/$@ \ - BUILD_CFLAGS="-DDEBUG=1 -Og" \ - DEPSDIR=$(CURDIR)/debug \ - --no-print-directory -C debug \ - -f $(CURDIR)/Makefile - -dist-bin: all - @tar --exclude=*~ -cjf $(TARGET).tar.bz2 include lib - -dist-src: - @tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source Makefile - -dist: dist-src dist-bin - -#--------------------------------------------------------------------------------- -clean: - @echo clean ... - @rm -fr release debug lib *.bz2 - -#--------------------------------------------------------------------------------- -else - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -$(OUTPUT) : $(OFILES) - -$(OFILES_SRC) : $(HFILES) - -#--------------------------------------------------------------------------------- -%_bin.h %.bin.o : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- - diff --git a/stratosphere/libstratosphere/include/meta_tools.hpp b/stratosphere/libstratosphere/include/meta_tools.hpp deleted file mode 100644 index f4c06e3c0..000000000 --- a/stratosphere/libstratosphere/include/meta_tools.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include <functional> - -namespace detail { - -template<typename T> -struct class_of; - -template<typename Ret, typename C> -struct class_of<Ret C::*> { - using type = C; -}; - -template<typename T> -using class_of_t = typename class_of<T>::type; - -template<typename Mem, typename T, typename C = class_of_t<Mem>> -struct member_equals_fn_helper { - T ref; - Mem mem_fn; - - bool operator()(const C& val) const { - return (std::mem_fn(mem_fn)(val) == ref); - } - - bool operator()(C&& val) const { - return (std::mem_fn(mem_fn)(std::move(val)) == ref); - } -}; - -} // namespace detail - -template<typename Mem, typename T> -auto member_equals_fn(Mem mem, T ref) { - return detail::member_equals_fn_helper<Mem, T>{std::move(ref), std::move(mem)}; -} diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp deleted file mode 100644 index 209e80e7e..000000000 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include "stratosphere/version_check.hpp" -#include "stratosphere/scope_guard.hpp" - -#include "stratosphere/hossynch.hpp" -#include "stratosphere/message_queue.hpp" -#include "stratosphere/iwaitable.hpp" -#include "stratosphere/event.hpp" - -#include "stratosphere/waitable_manager.hpp" - -#include "stratosphere/ipc.hpp" - -#include "stratosphere/mitm.hpp" - -#include "stratosphere/services.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/event.hpp b/stratosphere/libstratosphere/include/stratosphere/event.hpp deleted file mode 100644 index 153cdd0df..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/event.hpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <algorithm> -#include <vector> - -#include "iwaitable.hpp" - -class IEvent : public IWaitable { - public: - /* Information members. */ - Handle r_h; - Handle w_h; - bool autoclear; - public: - IEvent(bool a = false) : r_h(INVALID_HANDLE), w_h(INVALID_HANDLE), autoclear(a) { } - IEvent(Handle r, bool a = false) : r_h(r), w_h(INVALID_HANDLE), autoclear(a) { } - IEvent(Handle r, Handle w, bool a = false) : r_h(r), w_h(w), autoclear(a) { } - - ~IEvent() { - if (r_h != INVALID_HANDLE) { - svcCloseHandle(r_h); - } - if (w_h != INVALID_HANDLE) { - svcCloseHandle(w_h); - } - } - - /* Make it non-copyable */ - IEvent() = delete; - IEvent(const IEvent &) = delete; - IEvent& operator=(const IEvent&) = delete; - - - bool IsAutoClear() { - return this->autoclear; - } - - void Clear() { - std::scoped_lock<HosMutex> lock(this->sig_lock); - this->is_signaled = false; - if (this->r_h != INVALID_HANDLE) { - svcResetSignal(this->r_h); - } - } - - void Signal() { - std::scoped_lock<HosMutex> lock(this->sig_lock); - - if (this->w_h == INVALID_HANDLE && this->r_h != INVALID_HANDLE) { - /* We can't signal an event if we only have a read handle. */ - std::abort(); - } - - if (this->w_h == INVALID_HANDLE && this->is_signaled) { - return; - } - - this->is_signaled = true; - - if (this->w_h != INVALID_HANDLE) { - svcSignalEvent(this->w_h); - } else { - this->NotifyManagerSignaled(); - } - } - - virtual Result HandleSignaled(u64 timeout) = 0; - - /* IWaitable */ - virtual Handle GetHandle() override { - return this->r_h; - } -}; - -template<class F> -class HosEvent : public IEvent { - private: - F callback; - public: - HosEvent(F f, bool a = false) : IEvent(a), callback(std::move(f)) { } - HosEvent(Handle r, F f, bool a = false) : IEvent(r, a), callback(std::move(f)) { } - HosEvent(Handle r, Handle w, F f, bool a = false) : IEvent(r, w, a), callback(std::move(f)) { } - - virtual Result HandleSignaled(u64 timeout) override { - if (this->IsAutoClear()) { - this->Clear(); - } - return this->callback(timeout); - } -}; - -template <class F> -static IEvent *CreateHosEvent(F f, bool autoclear = false) { - return new HosEvent<F>(INVALID_HANDLE, INVALID_HANDLE, std::move(f), autoclear); -} - -template <class F> -static IEvent *CreateSystemEvent(F f, bool autoclear = false) { - - Handle w_h, r_h; - if (R_FAILED(svcCreateEvent(&w_h, &r_h))) { - std::abort(); - } - - return new HosEvent<F>(r_h, w_h, std::move(f), autoclear); -} - -template <bool a = false> -static IEvent *CreateWriteOnlySystemEvent() { - return CreateSystemEvent([](u64 timeout) { std::abort(); return 0; }, a); -} - -template <class F> -static IEvent *LoadReadOnlySystemEvent(Handle r_h, F f, bool autoclear = false) { - return new HosEvent<F>(r_h, f, autoclear); -} diff --git a/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp b/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp deleted file mode 100644 index 312c68c67..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/firmware_version.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -enum FirmwareVersion : u32 { - FirmwareVersion_Min = 0, - FirmwareVersion_100 = FirmwareVersion_Min, - FirmwareVersion_200 = 1, - FirmwareVersion_300 = 2, - FirmwareVersion_400 = 3, - FirmwareVersion_500 = 4, - FirmwareVersion_600 = 5, - FirmwareVersion_Current = FirmwareVersion_600, - FirmwareVersion_Max = 32, -}; - -static inline FirmwareVersion GetRuntimeFirmwareVersion() { - FirmwareVersion fw = FirmwareVersion_Min; - if (kernelAbove200()) { - fw = FirmwareVersion_200; - } - if (kernelAbove300()) { - fw = FirmwareVersion_300; - } - if (kernelAbove400()) { - fw = FirmwareVersion_400; - } - if (kernelAbove500()) { - fw = FirmwareVersion_500; - } - if (kernelAbove600()) { - fw = FirmwareVersion_600; - } - return fw; -} diff --git a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp b/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp deleted file mode 100644 index 4f0cbd2de..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/hossynch.hpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <switch/arm/counter.h> -#include <mutex> - -class HosMutex { - private: - Mutex m; - Mutex *GetMutex() { - return &this->m; - } - public: - HosMutex() { - mutexInit(GetMutex()); - } - - void lock() { - mutexLock(GetMutex()); - } - - void unlock() { - mutexUnlock(GetMutex()); - } - - bool try_lock() { - return mutexTryLock(GetMutex()); - } - - void Lock() { - lock(); - } - - void Unlock() { - unlock(); - } - - bool TryLock() { - return try_lock(); - } - - friend class HosCondVar; -}; - -class HosRecursiveMutex { - private: - RMutex m; - RMutex *GetMutex() { - return &this->m; - } - public: - HosRecursiveMutex() { - rmutexInit(GetMutex()); - } - - void lock() { - rmutexLock(GetMutex()); - } - - void unlock() { - rmutexUnlock(GetMutex()); - } - - bool try_lock() { - return rmutexTryLock(GetMutex()); - } - - void Lock() { - lock(); - } - - void Unlock() { - unlock(); - } - - bool TryLock() { - return try_lock(); - } -}; - -class HosCondVar { - private: - CondVar cv; - public: - HosCondVar() { - condvarInit(&cv); - } - - Result TimedWait(u64 timeout, HosMutex *hm) { - return TimedWait(timeout, hm->GetMutex()); - } - - Result Wait(HosMutex *hm) { - return Wait(hm->GetMutex()); - } - - Result TimedWait(u64 timeout, Mutex *m) { - return condvarWaitTimeout(&cv, m, timeout); - } - - Result Wait(Mutex *m) { - return condvarWait(&cv, m); - } - - Result Wake(int num) { - return condvarWake(&cv, num); - } - - Result WakeOne() { - return condvarWakeOne(&cv); - } - - Result WakeAll() { - return condvarWakeAll(&cv); - } -}; - -class HosSemaphore { - private: - Semaphore s; - public: - HosSemaphore() { - semaphoreInit(&s, 0); - } - - HosSemaphore(u64 c) { - semaphoreInit(&s, c); - } - - void Signal() { - semaphoreSignal(&s); - } - - void Wait() { - semaphoreWait(&s); - } - - bool TryWait() { - return semaphoreTryWait(&s); - } -}; - -class TimeoutHelper { - private: - u64 end_tick; - public: - TimeoutHelper(u64 ns) { - /* Special case zero-time timeouts. */ - if (ns == 0) { - end_tick = 0; - return; - } - - u64 cur_tick = armGetSystemTick(); - this->end_tick = cur_tick + NsToTick(ns) + 1; - } - - static inline u64 NsToTick(u64 ns) { - return (ns * 12) / 625; - } - - static inline u64 TickToNs(u64 tick) { - return (tick * 625) / 12; - } - - bool TimedOut() { - if (this->end_tick == 0) { - return true; - } - - return armGetSystemTick() >= this->end_tick; - } -}; - -class HosThread { - private: - Thread thr = {0}; - public: - HosThread() {} - - Result Initialize(ThreadFunc entry, void *arg, size_t stack_sz, int prio, int cpuid = -2) { - return threadCreate(&this->thr, entry, arg, stack_sz, prio, cpuid); - } - - Handle GetHandle() const { - return this->thr.handle; - } - - Result Start() { - return threadStart(&this->thr); - } - - Result Join() { - Result rc = threadWaitForExit(&this->thr); - if (R_SUCCEEDED(rc)) { - rc = threadClose(&this->thr); - } - return rc; - } -}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc.hpp deleted file mode 100644 index e035fda52..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include "ipc/ipc_service_object.hpp" -#include "ipc/ipc_serialization.hpp" - -#include "ipc/ipc_service_session.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp deleted file mode 100644 index 6bf2f71c0..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_buffers.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <type_traits> - -enum class IpcBufferType { - InBuffer, - OutBuffer, - InPointer, - OutPointer, -}; - -/* Base for In/Out Buffers. */ -struct IpcBufferBase {}; - -struct InOutBufferBase : public IpcBufferBase {}; - -/* Represents an A descriptor. */ -struct InBufferBase : public InOutBufferBase {}; - -template <typename T, BufferType e_t = BufferType_Normal> -struct InBuffer : public InBufferBase { - T *buffer; - size_t num_elements; - BufferType type; - static const BufferType expected_type = e_t; - - /* Convenience. */ - T& operator[](size_t i) const { - return buffer[i]; - } - - InBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } -}; - -/* Represents a B descriptor. */ -struct OutBufferBase : public InOutBufferBase {}; - -template <typename T, BufferType e_t = BufferType_Normal> -struct OutBuffer : OutBufferBase { - T *buffer; - size_t num_elements; - BufferType type; - static const BufferType expected_type = e_t; - - /* Convenience. */ - T& operator[](size_t i) const { - return buffer[i]; - } - - OutBuffer(void *b, size_t n, BufferType t) : buffer((T *)b), num_elements(n/sizeof(T)), type(t) { } -}; - -/* Represents an X descriptor. */ -struct InPointerBase : public IpcBufferBase {}; - -template <typename T> -struct InPointer : public InPointerBase { - T *pointer; - size_t num_elements; - - /* Convenience. */ - T& operator[](size_t i) const { - return pointer[i]; - } - - InPointer(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } -}; - -/* Represents a C descriptor. */ -struct OutPointerWithServerSizeBase : public IpcBufferBase {}; - -template <typename T, size_t N> -struct OutPointerWithServerSize : public OutPointerWithServerSizeBase { - T *pointer; - static const size_t num_elements = N; - static const size_t element_size = sizeof(T); - - /* Convenience. */ - T& operator[](size_t i) const { - return pointer[i]; - } - - OutPointerWithServerSize(void *p) : pointer((T *)p) { } - OutPointerWithServerSize(void *p, size_t n) : pointer((T *)p) { } -}; - -struct OutPointerWithClientSizeBase : public IpcBufferBase {}; - -/* Represents a C descriptor with size in raw data. */ -template <typename T> -struct OutPointerWithClientSize : public OutPointerWithClientSizeBase { - T *pointer; - size_t num_elements; - - /* Convenience. */ - T& operator[](size_t i) const { - return pointer[i]; - } - - OutPointerWithClientSize(void *p, size_t n) : pointer((T *)p), num_elements(n/sizeof(T)) { } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp deleted file mode 100644 index 1394fc095..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_domain_object.hpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <algorithm> -#include <memory> -#include <type_traits> - -#include "ipc_service_object.hpp" - -class IDomainObject; - -class DomainManager { - public: - virtual std::shared_ptr<IDomainObject> AllocateDomain() = 0; - virtual void FreeDomain(IDomainObject *domain) = 0; - virtual Result ReserveObject(IDomainObject *domain, u32 *out_object_id) = 0; - virtual Result ReserveSpecificObject(IDomainObject *domain, u32 object_id) = 0; - virtual void SetObject(IDomainObject *domain, u32 object_id, ServiceObjectHolder&& holder) = 0; - virtual ServiceObjectHolder *GetObject(IDomainObject *domain, u32 object_id) = 0; - virtual Result FreeObject(IDomainObject *domain, u32 object_id) = 0; - virtual Result ForceFreeObject(u32 object_id) = 0; -}; - -class IDomainObject : public IServiceObject { - private: - DomainManager *manager; - public: - IDomainObject(DomainManager *m) : manager(m) {} - - virtual ~IDomainObject() override { - this->manager->FreeDomain(this); - } - - DomainManager *GetManager() { - return this->manager; - } - - ServiceObjectHolder *GetObject(u32 object_id) { - return this->manager->GetObject(this, object_id); - } - - Result ReserveObject(u32 *out_object_id) { - return this->manager->ReserveObject(this, out_object_id); - } - - Result ReserveSpecificObject(u32 object_id) { - return this->manager->ReserveSpecificObject(this, object_id); - } - - void SetObject(u32 object_id, ServiceObjectHolder&& holder) { - this->manager->SetObject(this, object_id, std::move(holder)); - } - - Result FreeObject(u32 object_id) { - return this->manager->FreeObject(this, object_id); - } - - Result ForceFreeObject(u32 object_id) { - return this->manager->ForceFreeObject(object_id); - } - - public: - DEFINE_SERVICE_DISPATCH_TABLE { - /* IDomainObject has no callable functions. */ - }; -}; - -static constexpr bool IsDomainObject(ServiceObjectHolder &holder) { - return holder.GetServiceId() == ServiceObjectId<IDomainObject>(); -} - -static constexpr bool IsDomainObject(ServiceObjectHolder *holder) { - return holder->GetServiceId() == ServiceObjectId<IDomainObject>(); -} - -/* Out for service impl. */ -template <typename ServiceImpl> -class Out<std::shared_ptr<ServiceImpl>> : public OutSessionTag { - static_assert(std::is_base_of_v<IServiceObject, ServiceImpl>, "OutSessions must be shared_ptr<IServiceObject>!"); - - template<typename, typename> - friend class Out; - - private: - std::shared_ptr<ServiceImpl> *srv; - IDomainObject *domain = nullptr; - u32 *object_id = nullptr; - public: - Out<std::shared_ptr<ServiceImpl>>(std::shared_ptr<IServiceObject> *s, IDomainObject *dm, u32 *o) : srv(reinterpret_cast<std::shared_ptr<ServiceImpl> *>(s)), domain(dm), object_id(o) { } - - ServiceObjectHolder GetHolder() { - std::shared_ptr<ServiceImpl> clone = *srv; - return ServiceObjectHolder(std::move(clone)); - } - - bool IsDomain() { - return domain != nullptr; - } - - u32 GetObjectId() { - return *object_id; - } - - void ChangeObjectId(u32 o) { - domain->ForceFreeObject(*object_id); - domain->ReserveSpecificObject(o); - *object_id = o; - } - - void SetValue(std::shared_ptr<ServiceImpl> &&s) { - *this->srv = std::move(s); - } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp deleted file mode 100644 index fbd186d28..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_out.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <type_traits> - -/* Declare false allowed struct. */ -template <typename> -struct AllowedOut : std::false_type {}; - -struct OutDataTag{}; -struct OutHandleTag{}; -struct OutSessionTag{}; - -/* Define out struct, so that we can get errors on enable_if */ -template <typename T, typename Allowed = void> -class Out { - static_assert(std::is_pod<T>::value && !std::is_pod<T>::value, "Invalid IPC Out Type!"); -}; - -template <typename T> -class Out<T, typename std::enable_if<std::is_trivial<T>::value || AllowedOut<T>::value>::type> : public OutDataTag { -private: - T *obj; -public: - Out(T *o) : obj(o) { } - - void SetValue(const T& t) { - *obj = t; - } - - const T& GetValue() { - return *obj; - } - - T *GetPointer() { - return obj; - } - - /* Convenience operators. */ - T& operator*() { - return *obj; - } - - T* operator->() { - return obj; - } -}; - -template <typename T> -class Out<T*> { - static_assert(std::is_pod<T>::value && !std::is_pod<T>::value, "Invalid IPC Out Type (Raw Pointer)!"); -}; - -template <typename T> -struct OutHelper; - -template <typename T> -struct OutHelper<Out<T>> { - using type = T; -}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp deleted file mode 100644 index 4e2ed8345..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_response_context.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> - -#include "ipc_service_object.hpp" -#include "ipc_domain_object.hpp" - -#include "ipc_special.hpp" - -#include "ipc_session_manager_base.hpp" - -struct IpcResponseContext { - /* Request/Reply data. */ - IpcParsedCommand request; - IpcCommand reply; - u8 out_data[0x100]; - std::shared_ptr<IServiceObject> *out_objs[8]; - Handle out_object_server_handles[8]; - IpcHandle out_handles[8]; - u32 out_object_ids[8]; - IpcCommandType cmd_type; - u64 cmd_id; - Result rc; - /* Context. */ - SessionManagerBase *manager; - ServiceObjectHolder *obj_holder; - unsigned char *pb; - size_t pb_size; -}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp deleted file mode 100644 index 7ce9bd39e..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_serialization.hpp +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <cstdlib> -#include <cstring> -#include <tuple> -#include <boost/callable_traits.hpp> -#include <type_traits> -#include <memory> - -#include "ipc_out.hpp" -#include "ipc_buffers.hpp" -#include "ipc_special.hpp" - -#include "ipc_domain_object.hpp" - -#include "ipc_response_context.hpp" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-variable" - -template<typename Tuple> -struct PopFront; - -template<typename Head, typename... Tail> -struct PopFront<std::tuple<Head, Tail...>> { - using type = std::tuple<Tail...>; -}; - -template <typename ...> struct WhichType; - -template <typename...> -struct TypeList{}; - -template <typename... T1s, typename... T2s> -constexpr auto Concatenate(TypeList<T1s...>, TypeList<T2s...>) { - return TypeList<T1s..., T2s...>{}; -} - -template <template <typename> typename Condition, typename R> -constexpr auto FilterTypes(R result, TypeList<>) { - return result; -} - -template <template <typename> typename Condition, typename R, typename T, typename... Ts> -constexpr auto FilterTypes(R result, TypeList<T, Ts...>) { - if constexpr (Condition<T>{}) - return FilterTypes<Condition>(Concatenate(result, TypeList<T>{}), TypeList<Ts...>{}); - else - return FilterTypes<Condition>(result, TypeList<Ts...>{}); -} - -template<typename Types> struct TypeListToTuple; - -template<typename... Types> -struct TypeListToTuple<TypeList<Types...>> { - using type = std::tuple<Types...>; -}; - -template <template <typename> typename Condition, typename... Types> -using FilteredTypes = typename TypeListToTuple<std::decay_t<decltype(FilterTypes<Condition>(TypeList<>{}, TypeList<Types...>{}))>>::type; - -enum class ArgType { - InData, - OutData, - InHandle, - OutHandle, - InSession, - OutSession, - PidDesc, - InBuffer, - OutBuffer, - InPointer, - OutPointerClientSize, - OutPointerServerSize, -}; - -template<typename X> -constexpr ArgType GetArgType() { - if constexpr (std::is_base_of_v<OutDataTag, X>) { - return ArgType::OutData; - } else if constexpr (std::is_base_of_v<OutSessionTag, X>) { - return ArgType::OutSession; - } else if constexpr (std::is_base_of_v<OutHandleTag, X>) { - return ArgType::OutHandle; - } else if constexpr (std::is_base_of_v<InBufferBase, X>) { - return ArgType::InBuffer; - } else if constexpr (std::is_base_of_v<OutBufferBase, X>) { - return ArgType::OutBuffer; - } else if constexpr (std::is_base_of_v<InPointerBase, X>) { - return ArgType::InPointer; - } else if constexpr (std::is_base_of_v<OutPointerWithClientSizeBase, X>) { - return ArgType::OutPointerClientSize; - } else if constexpr (std::is_base_of_v<OutPointerWithServerSizeBase, X>) { - return ArgType::OutPointerServerSize; - } else if constexpr (std::is_base_of_v<PidDescriptorTag, X>) { - return ArgType::PidDesc; - } else if constexpr (std::is_base_of_v<IpcHandleTag, X>) { - return ArgType::InHandle; - } else if constexpr (std::is_trivial_v<X> && !std::is_pointer_v<X>) { - return ArgType::InData; - } else { - static_assert(std::is_pod_v<X> && !std::is_pod_v<X>, "Unhandled InSession!"); - return ArgType::InSession; - } -} - -template<ArgType ArgT> -struct ArgTypeFilter { - template<typename X> - using type = std::conditional_t<GetArgType<X>() == ArgT, std::true_type, std::false_type>; -}; - -template<ArgType ArgT> -struct IsArgTypeBuffer { - static constexpr bool value = ArgT == ArgType::InBuffer || ArgT == ArgType::OutBuffer || ArgT == ArgType::InPointer || ArgT == ArgType::OutPointerClientSize || ArgT == ArgType::OutPointerServerSize; -}; - -struct ArgTypeBufferFilter { - template<typename X> - using type = std::conditional_t<IsArgTypeBuffer<GetArgType<X>()>::value, std::true_type, std::false_type>; -}; - -template<ArgType ArgT> -struct IsArgTypeInData { - static constexpr bool value = ArgT == ArgType::InData || ArgT == ArgType::PidDesc; -}; - -struct ArgTypeInDataFilter { - template<typename X> - using type = std::conditional_t<IsArgTypeInData<GetArgType<X>()>::value, std::true_type, std::false_type>; -}; - -template<typename T> -struct RawDataHelper { - static_assert(GetArgType<T>() == ArgType::InData || GetArgType<T>() == ArgType::PidDesc); - static constexpr size_t align = (GetArgType<T>() == ArgType::InData) ? __alignof__(T) : __alignof__(u64); - static constexpr size_t size = (GetArgType<T>() == ArgType::InData) ? sizeof(T) : sizeof(u64); -}; - -template<typename T> -struct RawDataHelper<Out<T>> { - static_assert(GetArgType<T>() == ArgType::InData); - static constexpr size_t align = __alignof(T); - static constexpr size_t size = sizeof(T); -}; - -template<typename Ts> -struct RawDataComputer; - -template<typename... Ts> -struct RawDataComputer<std::tuple<Ts...>> { - /* https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,2604 */ - static constexpr void QuickSort(std::array<size_t, sizeof...(Ts)> &map, std::array<size_t, sizeof...(Ts)> &values, int left, int right) { - do { - int i = left; - int j = right; - int x = map[i + ((j - i) >> 1)]; - do { - while (i < static_cast<int>(sizeof...(Ts)) && values[x] > values[map[i]]) i++; - while (j >= 0 && values[x] < values[map[j]]) j--; - if (i > j) break; - if (i < j) { - const size_t temp = map[i]; - map[i] = map[j]; - map[j] = temp; - } - i++; - j--; - } while (i <= j); - if (j - left <= right - i) { - if (left < j) QuickSort(map, values, left, j); - left = i; - } else { - if (i < right) QuickSort(map, values, i, right); - right = j; - } - } while (left < right); - } - - static constexpr void StableSort(std::array<size_t, sizeof...(Ts)> &map, std::array<size_t, sizeof...(Ts)> &values) { - /* First, quicksort a copy of the map. */ - std::array<size_t, sizeof...(Ts)> map_unstable(map); - QuickSort(map_unstable, values, 0, sizeof...(Ts)-1); - - /* Now, create stable sorted map from unstably quicksorted indices (via repeated insertion sort on element runs). */ - for (size_t i = 0; i < sizeof...(Ts); i++) { - map[i] = map_unstable[i]; - for (ssize_t j = i-1; j >= 0 && values[map[j]] == values[map[j+1]] && map[j] > map[j+1]; j--) { - const size_t temp = map[j]; - map[j] = map[j+1]; - map[j+1] = temp; - } - } - } - - static constexpr std::array<size_t, sizeof...(Ts)+1> GetOffsets() { - std::array<size_t, sizeof...(Ts)+1> offsets = {}; - offsets[0] = 0; - if constexpr (sizeof...(Ts) > 0) { - /* Get size, alignment for each type. */ - std::array<size_t, sizeof...(Ts)> sizes = { RawDataHelper<Ts>::size... }; - std::array<size_t, sizeof...(Ts)> aligns = { RawDataHelper<Ts>::align... }; - - /* We want to sort...by alignment. */ - std::array<size_t, sizeof...(Ts)> map = {}; - for (size_t i = 0; i < sizeof...(Ts); i++) { map[i] = i; } - StableSort(map, aligns); - - /* Iterate over sorted types. */ - size_t cur_offset = 0; - for (size_t i = 0; i < sizeof...(Ts); i++) { - const size_t align = aligns[map[i]]; - if (cur_offset % align != 0) { - cur_offset += align - (cur_offset % align); - } - offsets[map[i]] = cur_offset; - cur_offset += sizes[map[i]]; - } - offsets[sizeof...(Ts)] = cur_offset; - } - return offsets; - } - - static constexpr std::array<size_t, sizeof...(Ts)+1> offsets = GetOffsets(); -}; - -template <typename _Args, typename _ReturnType> -struct CommandMetaInfo; - -template<typename... _Args, typename _ReturnType> -struct CommandMetaInfo<std::tuple<_Args...>, _ReturnType> { - using Args = std::tuple<_Args...>; - using ReturnType = _ReturnType; - - static constexpr bool ReturnsResult = std::is_same_v<ReturnType, Result>; - static constexpr bool ReturnsVoid = std::is_same_v<ReturnType, void>; - - using InDatas = FilteredTypes<ArgTypeInDataFilter::type, _Args...>; - using OutDatas = FilteredTypes<ArgTypeFilter<ArgType::OutData>::type, _Args...>; - using InHandles = FilteredTypes<ArgTypeFilter<ArgType::InHandle>::type, _Args...>; - using OutHandles = FilteredTypes<ArgTypeFilter<ArgType::OutHandle>::type, _Args...>; - using InSessions = FilteredTypes<ArgTypeFilter<ArgType::InSession>::type, _Args...>; - using OutSessions = FilteredTypes<ArgTypeFilter<ArgType::OutSession>::type, _Args...>; - using PidDescs = FilteredTypes<ArgTypeFilter<ArgType::PidDesc>::type, _Args...>; - - using InBuffers = FilteredTypes<ArgTypeFilter<ArgType::InBuffer>::type, _Args...>; - using OutBuffers = FilteredTypes<ArgTypeFilter<ArgType::OutBuffer>::type, _Args...>; - using InPointers = FilteredTypes<ArgTypeFilter<ArgType::InPointer>::type, _Args...>; - using ClientSizeOutPointers = FilteredTypes<ArgTypeFilter<ArgType::OutPointerClientSize>::type, _Args...>; - using ServerSizeOutPointers = FilteredTypes<ArgTypeFilter<ArgType::OutPointerServerSize>::type, _Args...>; - using Buffers = FilteredTypes<ArgTypeBufferFilter::type, _Args...>; - - static constexpr size_t NumInDatas = std::tuple_size_v<InDatas>; - static constexpr size_t NumOutDatas = std::tuple_size_v<OutDatas>; - static constexpr size_t NumInHandles = std::tuple_size_v<InHandles>; - static constexpr size_t NumOutHandles = std::tuple_size_v<OutHandles>; - static constexpr size_t NumInSessions = std::tuple_size_v<InSessions>; - static constexpr size_t NumOutSessions = std::tuple_size_v<OutSessions>; - static constexpr size_t NumPidDescs = std::tuple_size_v<PidDescs>; - - static constexpr size_t NumInBuffers = std::tuple_size_v<InBuffers>; - static constexpr size_t NumOutBuffers = std::tuple_size_v<OutBuffers>; - static constexpr size_t NumInPointers = std::tuple_size_v<InPointers>; - static constexpr size_t NumClientSizeOutPointers = std::tuple_size_v<ClientSizeOutPointers>; - static constexpr size_t NumServerSizeOutPointers = std::tuple_size_v<ServerSizeOutPointers>; - static constexpr size_t NumBuffers = std::tuple_size_v<Buffers>; - - static_assert(NumInSessions == 0, "InSessions not yet supported!"); - static_assert(NumPidDescs == 0 || NumPidDescs == 1, "Methods can only take in 0 or 1 PIDs!"); - static_assert(NumBuffers <= 8, "Methods can only take in <= 8 Buffers!"); - static_assert(NumInHandles <= 8, "Methods can take in <= 8 Handles!"); - static_assert(NumOutHandles + NumOutSessions <= 8, "Methods can only return <= 8 Handles+Sessions!"); - - static constexpr std::array<size_t, NumInDatas+1> InDataOffsets = RawDataComputer<InDatas>::offsets; - static constexpr size_t InRawArgSize = InDataOffsets[NumInDatas]; - static constexpr size_t InRawArgSizeWithOutPointers = ((InRawArgSize + NumClientSizeOutPointers * sizeof(u16)) + 3) & ~3; - - static constexpr std::array<size_t, NumOutDatas+1> OutDataOffsets = RawDataComputer<OutDatas>::offsets; - static constexpr size_t OutRawArgSize = OutDataOffsets[NumOutDatas]; -}; - - -/* ================================================================================= */ -/* Actual wrapping implementation goes here. */ - -/* Validator. */ -struct Validator { - - template <typename T> - static constexpr bool ValidateCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& h_index, size_t& cur_c_size_offset, size_t& total_c_size) { - constexpr ArgType argT = GetArgType<T>(); - if constexpr (argT == ArgType::InBuffer) { - return (ctx->request.Buffers[a_index] != nullptr || ctx->request.BufferSizes[a_index] == 0) && ctx->request.BufferDirections[a_index] == BufferDirection_Send && ctx->request.BufferTypes[a_index++] == T::expected_type; - } else if constexpr (argT == ArgType::OutBuffer) { - return (ctx->request.Buffers[b_index] != nullptr || ctx->request.BufferSizes[b_index] == 0) && ctx->request.BufferDirections[b_index] == BufferDirection_Recv && ctx->request.BufferTypes[b_index++] == T::expected_type; - } else if constexpr (argT == ArgType::InPointer) { - return ctx->request.Statics[x_index++] != nullptr; - } else if constexpr (argT == ArgType::InHandle) { - if constexpr (std::is_same_v<T, MovedHandle>) { - return !ctx->request.WasHandleCopied[h_index++]; - } else if constexpr (std::is_same_v<T, CopiedHandle>) { - return ctx->request.WasHandleCopied[h_index++]; - } - } else { - if constexpr (argT == ArgType::OutPointerServerSize) { - total_c_size += T::num_elements * sizeof(T); - } else if constexpr (argT == ArgType::OutPointerServerSize) { - total_c_size += *((u16 *)((uintptr_t)(ctx->request.Raw) + 0x10 + cur_c_size_offset)); - cur_c_size_offset += sizeof(u16); - } - return true; - } - } - - template <typename Ts> - struct ValidateCommandTuple; - - template <typename ...Ts> - struct ValidateCommandTuple<std::tuple<Ts...>> { - static constexpr bool IsValid(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& h_index, size_t& cur_c_size_offset, size_t& total_c_size) { - return (ValidateCommandArgument<Ts>(ctx, a_index, b_index, x_index, h_index, cur_c_size_offset, total_c_size) && ...); - } - }; - - template<typename MetaInfo> - static constexpr Result Validate(IpcResponseContext *ctx) { - if (ctx->request.RawSize < MetaInfo::InRawArgSizeWithOutPointers) { - return 0xF601; - } - - if (ctx->request.NumBuffers != MetaInfo::NumInBuffers + MetaInfo::NumOutBuffers) { - return 0xF601; - } - - if (ctx->request.NumStatics != MetaInfo::NumInPointers) { - return 0xF601; - } - - if (ctx->request.NumStaticsOut != MetaInfo::NumClientSizeOutPointers + MetaInfo::NumServerSizeOutPointers) { - return 0xF601; - } - - if (ctx->request.NumHandles != MetaInfo::NumInHandles) { - return 0xF601; - } - - - if ((ctx->request.HasPid && MetaInfo::NumPidDescs == 0) || (!ctx->request.HasPid && MetaInfo::NumPidDescs != 0)) { - return 0xF601; - } - - if (((u32 *)ctx->request.Raw)[0] != SFCI_MAGIC) { - return 0xF601; - } - - size_t a_index = 0, b_index = MetaInfo::NumInBuffers, x_index = 0, h_index = 0; - size_t cur_c_size_offset = MetaInfo::InRawArgSize + (0x10 - ((uintptr_t)ctx->request.Raw - (uintptr_t)ctx->request.RawWithoutPadding)); - size_t total_c_size = 0; - - if (!ValidateCommandTuple<typename MetaInfo::Args>::IsValid(ctx, a_index, b_index, x_index, h_index, cur_c_size_offset, total_c_size)) { - return 0xF601; - } - - if (total_c_size > ctx->pb_size) { - return 0xF601; - } - - return 0; - } -}; - -/* ================================================================================= */ - -/* Decoder. */ -template<typename MetaInfo> -struct Decoder { - - template<typename T> - static constexpr T DecodeCommandArgument(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_data_index, size_t& out_data_index, size_t& pb_offset, size_t& c_sz_offset) { - constexpr ArgType argT = GetArgType<T>(); - if constexpr (argT == ArgType::InBuffer) { - const T& value = T(ctx->request.Buffers[a_index], ctx->request.BufferSizes[a_index], ctx->request.BufferTypes[a_index]); - ++a_index; - return value; - } else if constexpr (argT == ArgType::OutBuffer) { - const T& value = T(ctx->request.Buffers[b_index], ctx->request.BufferSizes[b_index], ctx->request.BufferTypes[b_index]); - ++b_index; - return value; - } else if constexpr (argT == ArgType::InPointer) { - const T& value = T(ctx->request.Statics[x_index], ctx->request.StaticSizes[x_index]); - ++x_index; - return value; - } else if constexpr (argT == ArgType::InHandle) { - return T(ctx->request.Handles[in_h_index++]); - } else if constexpr (argT == ArgType::OutHandle) { - return T(&ctx->out_handles[out_h_index++]); - } else if constexpr (argT == ArgType::PidDesc) { - uintptr_t ptr = ((uintptr_t)ctx->request.Raw + 0x10 + MetaInfo::InDataOffsets[in_data_index++]); - *(u64 *)ptr = ctx->request.Pid; - return T(ctx->request.Pid); - } else if constexpr (argT == ArgType::InData) { - uintptr_t ptr = ((uintptr_t)ctx->request.Raw + 0x10 + MetaInfo::InDataOffsets[in_data_index++]); - if constexpr (std::is_same_v<bool, T>) { - return *((u8 *)ptr) & 1; - } else { - return *((T *)ptr); - } - } else if constexpr (argT == ArgType::OutData) { - uintptr_t ptr = ((uintptr_t)ctx->out_data + MetaInfo::OutDataOffsets[out_data_index++]); - return T(reinterpret_cast<typename OutHelper<T>::type *>(ptr)); - } else if constexpr (argT == ArgType::OutPointerClientSize || argT == ArgType::OutPointerServerSize) { - u16 sz; - if constexpr(argT == ArgType::OutPointerServerSize) { - sz = T::element_size; - } else { - sz = *(const u16 *)((uintptr_t)ctx->request.Raw + 0x10 + c_sz_offset); - } - u8* buf = ctx->pb + pb_offset; - c_sz_offset += sizeof(u16); - pb_offset += sz; - ipcAddSendStatic(&ctx->reply, buf, sz, c_index++); - return T(buf, sz); - } else if constexpr (argT == ArgType::OutSession) { - if (IsDomainObject(ctx->obj_holder)) { - const T& value = T(ctx->out_objs[out_obj_index], ctx->obj_holder->GetServiceObject<IDomainObject>(), &ctx->out_object_ids[out_obj_index]); - out_obj_index++; - return value; - } else { - const T& value = T(ctx->out_objs[out_obj_index], nullptr, 0); - out_obj_index++; - return value; - } - } - } - - template <typename Ts> - struct DecodeTuple; - - template <typename ...Ts> - struct DecodeTuple<std::tuple<Ts...>> { - static constexpr std::tuple<Ts...> GetArgs(IpcResponseContext *ctx, size_t& a_index, size_t& b_index, size_t& x_index, size_t& c_index, size_t& in_h_index, size_t& out_h_index, size_t& out_obj_index, size_t& in_data_index, size_t& out_data_index, size_t& pb_offset, size_t& c_sz_offset) { - return std::tuple<Ts... > { - DecodeCommandArgument<Ts>(ctx, a_index, b_index, x_index, c_index, in_h_index, out_h_index, out_obj_index, in_data_index, out_data_index, pb_offset, c_sz_offset) - ... - }; - } - }; - - - static constexpr typename MetaInfo::Args Decode(IpcResponseContext *ctx) { - size_t a_index = 0, b_index = MetaInfo::NumInBuffers, x_index = 0, c_index = 0, in_h_index = 0, out_h_index = 0, out_obj_index = 0; - size_t in_data_index = 0x0, out_data_index = 0, pb_offset = 0; - size_t c_sz_offset = MetaInfo::InRawArgSize + (0x10 - ((uintptr_t)ctx->request.Raw - (uintptr_t)ctx->request.RawWithoutPadding)); - return DecodeTuple<typename MetaInfo::Args>::GetArgs(ctx, a_index, b_index, x_index, c_index, in_h_index, out_h_index, out_obj_index, in_data_index, out_data_index, pb_offset, c_sz_offset); - } -}; - -/* ================================================================================= */ - -template<typename MetaInfo, typename T> -static constexpr void EncodeArgument(IpcResponseContext *ctx, size_t&out_obj_index, T& arg) { - constexpr ArgType argT = GetArgType<T>(); - if constexpr (argT == ArgType::OutHandle) { - if constexpr (std::is_same_v<MovedHandle, typename OutHelper<T>::type>) { - ipcSendHandleMove(&ctx->reply, arg.GetValue().handle); - } else { - ipcSendHandleCopy(&ctx->reply, arg.GetValue().handle); - } - } else if constexpr (argT == ArgType::OutSession) { - if (IsDomainObject(ctx->obj_holder)) { - auto domain = ctx->obj_holder->GetServiceObject<IDomainObject>(); - domain->SetObject(arg.GetObjectId(), std::move(arg.GetHolder())); - } else { - ctx->manager->AddSession(ctx->out_object_server_handles[out_obj_index++], std::move(arg.GetHolder())); - } - } -} - -template<typename MetaInfo, typename ArgsTuple> -struct Encoder; - -template <typename MetaInfo, typename ...Args> -struct Encoder<MetaInfo, std::tuple<Args...>> { - - static constexpr void EncodeFailure(IpcResponseContext *ctx, Result rc) { - memset(armGetTls(), 0, 0x100); - ipcInitialize(&ctx->reply); - struct { - u64 magic; - u64 result; - } *raw; - - if (IsDomainObject(ctx->obj_holder)) { - raw = (decltype(raw))ipcPrepareHeaderForDomain(&ctx->reply, sizeof(*raw), 0); - auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); - *resp_header = {0}; - } else { - raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)); - } - raw->magic = SFCO_MAGIC; - raw->result = rc; - } - - - - static constexpr void EncodeSuccess(IpcResponseContext *ctx, Args... args) { - size_t out_obj_index = 0; - - ((EncodeArgument<MetaInfo, Args>(ctx, out_obj_index, args)), ...); - - const bool is_domain = IsDomainObject(ctx->obj_holder); - - if (!is_domain) { - for (unsigned int i = 0; i < MetaInfo::NumOutSessions; i++) { - ipcSendHandleMove(&ctx->reply, ctx->out_handles[MetaInfo::NumOutHandles + i].handle); - } - } - - struct { - u64 magic; - u64 result; - } *raw; - if (is_domain) { - raw = (decltype(raw))ipcPrepareHeaderForDomain(&ctx->reply, sizeof(*raw) + MetaInfo::OutRawArgSize, 0); - auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader)); - *resp_header = {0}; - resp_header->NumObjectIds = MetaInfo::NumOutSessions; - } else { - raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)+ MetaInfo::OutRawArgSize); - } - - raw->magic = SFCO_MAGIC; - raw->result = 0; - - memcpy((void *)((uintptr_t)raw + sizeof(*raw)), ctx->out_data, MetaInfo::OutRawArgSize); - if (is_domain) { - memcpy((void *)((uintptr_t)raw + sizeof(*raw) + MetaInfo::OutRawArgSize), ctx->out_object_ids, sizeof(*ctx->out_object_ids) * MetaInfo::NumOutSessions); - } - } - -}; - -/* ================================================================================= */ - -template<auto IpcCommandImpl> -constexpr Result WrapIpcCommandImpl(IpcResponseContext *ctx) { - using InArgs = typename PopFront<typename boost::callable_traits::args_t<decltype(IpcCommandImpl)>>::type; - using OutArgs = typename boost::callable_traits::return_type_t<decltype(IpcCommandImpl)>; - using ClassType = typename boost::callable_traits::class_of_t<decltype(IpcCommandImpl)>; - - using CommandMetaData = CommandMetaInfo<InArgs, OutArgs>; - - static_assert(CommandMetaData::ReturnsResult || CommandMetaData::ReturnsVoid, "IpcCommandImpls must return Result or void"); - - ipcInitialize(&ctx->reply); - memset(ctx->out_data, 0, CommandMetaData::OutRawArgSize); - - Result rc = Validator::Validate<CommandMetaData>(ctx); - - if (R_FAILED(rc)) { - return 0xAAEE; - } - - ClassType *this_ptr = nullptr; - if (IsDomainObject(ctx->obj_holder)) { - this_ptr = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId)->GetServiceObject<ClassType>(); - } else { - this_ptr = ctx->obj_holder->GetServiceObject<ClassType>(); - } - if (this_ptr == nullptr) { - return 0xBBEE; - } - - std::shared_ptr<IServiceObject> out_objects[CommandMetaData::NumOutSessions]; - - /* Allocate out object IDs. */ - size_t num_out_objects; - if (IsDomainObject(ctx->obj_holder)) { - for (num_out_objects = 0; num_out_objects < CommandMetaData::NumOutSessions; num_out_objects++) { - if (R_FAILED((rc = ctx->obj_holder->GetServiceObject<IDomainObject>()->ReserveObject(&ctx->out_object_ids[num_out_objects])))) { - break; - } - ctx->out_objs[num_out_objects] = &out_objects[num_out_objects]; - } - } else { - for (num_out_objects = 0; num_out_objects < CommandMetaData::NumOutSessions; num_out_objects++) { - Handle server_h, client_h; - if (R_FAILED((rc = SessionManagerBase::CreateSessionHandles(&server_h, &client_h)))) { - break; - } - ctx->out_object_server_handles[num_out_objects] = server_h; - ctx->out_handles[CommandMetaData::NumOutHandles + num_out_objects].handle = client_h; - ctx->out_objs[num_out_objects] = &out_objects[num_out_objects]; - } - } - - ON_SCOPE_EXIT { - /* Clean up objects as necessary. */ - if (R_FAILED(rc)) { - if (IsDomainObject(ctx->obj_holder)) { - for (unsigned int i = 0; i < num_out_objects; i++) { - ctx->obj_holder->GetServiceObject<IDomainObject>()->FreeObject(ctx->out_object_ids[i]); - } - } else { - for (unsigned int i = 0; i < num_out_objects; i++) { - svcCloseHandle(ctx->out_object_server_handles[i]); - svcCloseHandle(ctx->out_handles[CommandMetaData::NumOutHandles + i].handle); - } - } - } - - for (unsigned int i = 0; i < num_out_objects; i++) { - ctx->out_objs[i] = nullptr; - } - }; - - if (R_SUCCEEDED(rc)) { - auto args = Decoder<CommandMetaData>::Decode(ctx); - - if constexpr (CommandMetaData::ReturnsResult) { - rc = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args); - } else { - std::apply( [=](auto&&... args) { (this_ptr->*IpcCommandImpl)(args...); }, args); - } - - if (R_SUCCEEDED(rc)) { - std::apply(Encoder<CommandMetaData, decltype(args)>::EncodeSuccess, std::tuple_cat(std::make_tuple(ctx), args)); - } else { - std::apply(Encoder<CommandMetaData, decltype(args)>::EncodeFailure, std::tuple_cat(std::make_tuple(ctx), std::make_tuple(rc))); - } - } else { - std::apply(Encoder<CommandMetaData, typename CommandMetaData::Args>::EncodeFailure, std::tuple_cat(std::make_tuple(ctx), std::make_tuple(rc))); - } - - return rc; -} - - -template <u32 c, auto CommandImpl, FirmwareVersion l = FirmwareVersion_Min, FirmwareVersion h = FirmwareVersion_Max> -inline static constexpr ServiceCommandMeta MakeServiceCommandMeta() { - return { - .fw_low = l, - .fw_high = h, - .cmd_id = c, - .handler = WrapIpcCommandImpl<CommandImpl>, - }; -}; - - -#pragma GCC diagnostic pop diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp deleted file mode 100644 index 8803da33f..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_object.hpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <memory> -#include <type_traits> - -#include "ipc_out.hpp" - -#include "../firmware_version.hpp" - -class IpcResponseContext; - -struct ServiceCommandMeta { - FirmwareVersion fw_low = FirmwareVersion_Max; - FirmwareVersion fw_high = FirmwareVersion_Max; - u32 cmd_id = 0; - Result (*handler)(IpcResponseContext *) = nullptr; -}; - -class IServiceObject { - public: - virtual ~IServiceObject() { } -}; - -#define SERVICE_DISPATCH_TABLE_NAME s_DispatchTable -#define DEFINE_SERVICE_DISPATCH_TABLE static constexpr ServiceCommandMeta SERVICE_DISPATCH_TABLE_NAME[] - -template <typename T> -static constexpr size_t DispatchTableEntryCount() { - static_assert(std::is_base_of<IServiceObject, T>::value, "DispatchTable owners must derive from IServiceObject"); - return sizeof(T::SERVICE_DISPATCH_TABLE_NAME)/sizeof(ServiceCommandMeta); -} -template <typename T> -static constexpr const ServiceCommandMeta* DispatchTable() { - static_assert(std::is_base_of<IServiceObject, T>::value, "DispatchTable owners must derive from IServiceObject"); - return reinterpret_cast<const ServiceCommandMeta*>(&T::SERVICE_DISPATCH_TABLE_NAME); -} - -template <typename T> -static constexpr uintptr_t ServiceObjectId() { - static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); - return reinterpret_cast<uintptr_t>(&T::SERVICE_DISPATCH_TABLE_NAME); -} - -class ServiceObjectHolder { - private: - std::shared_ptr<IServiceObject> srv; - const ServiceCommandMeta *dispatch_table; - size_t entry_count; - - /* Private copy constructor. */ - ServiceObjectHolder(const ServiceObjectHolder& other) : srv(other.srv), dispatch_table(other.dispatch_table), entry_count(other.entry_count) { } - ServiceObjectHolder& operator=(const ServiceObjectHolder& other); - public: - /* Templated constructor ensures correct type id at runtime. */ - template <typename ServiceImpl> - explicit ServiceObjectHolder(std::shared_ptr<ServiceImpl>&& s) : srv(std::move(s)), dispatch_table(DispatchTable<ServiceImpl>()), entry_count(DispatchTableEntryCount<ServiceImpl>()) { } - - template <typename ServiceImpl> - ServiceImpl *GetServiceObject() const { - if (GetServiceId() == ServiceObjectId<ServiceImpl>()) { - return static_cast<ServiceImpl *>(this->srv.get()); - } - return nullptr; - } - - template<typename ServiceImpl> - ServiceImpl *GetServiceObjectUnsafe() const { - return static_cast<ServiceImpl *>(this->srv.get()); - } - - const ServiceCommandMeta *GetDispatchTable() const { - return this->dispatch_table; - } - - size_t GetDispatchTableEntryCount() const { - return this->entry_count; - } - - constexpr uintptr_t GetServiceId() const { - return reinterpret_cast<uintptr_t>(this->dispatch_table); - } - - /* Default constructor, move constructor, move assignment operator. */ - ServiceObjectHolder() : srv(nullptr), dispatch_table(nullptr) { } - - ServiceObjectHolder(ServiceObjectHolder&& other) : srv(std::move(other.srv)), dispatch_table(std::move(other.dispatch_table)), entry_count(std::move(other.entry_count)) { } - - ServiceObjectHolder& operator=(ServiceObjectHolder&& other) { - this->srv = other.srv; - this->dispatch_table = other.dispatch_table; - this->entry_count = other.entry_count; - other.Reset(); - return *this; - } - - explicit operator bool() const { - return this->srv != nullptr; - } - - bool operator!() const { - return this->srv == nullptr; - } - - void Reset() { - this->srv.reset(); - this->dispatch_table = nullptr; - this->entry_count = 0; - } - - ServiceObjectHolder Clone() const { - ServiceObjectHolder clone(*this); - return clone; - } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp deleted file mode 100644 index 752c533e5..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_service_session.hpp +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> - -#include "../iwaitable.hpp" -#include "ipc_service_object.hpp" -#include "ipc_serialization.hpp" - -enum HipcControlCommand : u32 { - HipcControlCommand_ConvertCurrentObjectToDomain = 0, - HipcControlCommand_CopyFromCurrentDomain = 1, - HipcControlCommand_CloneCurrentObject = 2, - HipcControlCommand_QueryPointerBufferSize = 3, - HipcControlCommand_CloneCurrentObjectEx = 4 -}; - - -#define RESULT_DEFER_SESSION (0x6580A) - - -class ServiceSession : public IWaitable -{ - protected: - Handle session_handle; - std::vector<unsigned char> pointer_buffer; - ServiceObjectHolder obj_holder; - ServiceObjectHolder control_holder = ServiceObjectHolder(std::make_shared<IHipcControlService>(this)); - u8 backup_tls[0x100]; - - ServiceSession(Handle s_h) : session_handle(s_h) { } - public: - template<typename T> - ServiceSession(Handle s_h, size_t pbs) : session_handle(s_h), pointer_buffer(pbs), obj_holder(std::make_shared<T>()) { } - - ServiceSession(Handle s_h, size_t pbs, ServiceObjectHolder &&h) : session_handle(s_h), pointer_buffer(pbs), obj_holder(std::move(h)) { } - - virtual ~ServiceSession() override { - svcCloseHandle(this->session_handle); - } - - SessionManagerBase *GetSessionManager() { - return static_cast<SessionManagerBase *>(this->GetManager()); - } - - DomainManager *GetDomainManager() { - return static_cast<DomainManager *>(this->GetSessionManager()); - } - - Result Receive() { - int handle_index; - /* Prepare pointer buffer... */ - IpcCommand c; - ipcInitialize(&c); - if (this->pointer_buffer.size() > 0) { - ipcAddRecvStatic(&c, this->pointer_buffer.data(), this->pointer_buffer.size(), 0); - ipcPrepareHeader(&c, 0); - - /* Fix libnx bug in serverside C descriptor handling. */ - ((u32 *)armGetTls())[1] &= 0xFFFFC3FF; - ((u32 *)armGetTls())[1] |= (2) << 10; - } else { - ipcPrepareHeader(&c, 0); - } - - /* Receive. */ - Result rc = svcReplyAndReceive(&handle_index, &this->session_handle, 1, 0, U64_MAX); - if (R_SUCCEEDED(rc)) { - std::memcpy(this->backup_tls, armGetTls(), sizeof(this->backup_tls)); - } - - return rc; - } - - Result Reply() { - int handle_index; - return svcReplyAndReceive(&handle_index, &this->session_handle, 0, this->session_handle, 0); - } - - /* For preparing basic replies. */ - Result PrepareBasicResponse(IpcResponseContext *ctx, Result rc) { - ipcInitialize(&ctx->reply); - struct { - u64 magic; - u64 result; - } *raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)); - - raw->magic = SFCO_MAGIC; - raw->result = rc; - return raw->result; - } - - Result PrepareBasicDomainResponse(IpcResponseContext *ctx, Result rc) { - ipcInitialize(&ctx->reply); - struct { - DomainResponseHeader hdr; - u64 magic; - u64 result; - } *raw = (decltype(raw))ipcPrepareHeader(&ctx->reply, sizeof(*raw)); - - raw->hdr = (DomainResponseHeader){0}; - raw->magic = SFCO_MAGIC; - raw->result = rc; - return raw->result; - } - - /* For making a new response context. */ - void InitializeResponseContext(IpcResponseContext *ctx) { - std::memset(ctx, 0, sizeof(*ctx)); - ctx->manager = this->GetSessionManager(); - ctx->obj_holder = &this->obj_holder; - ctx->pb = this->pointer_buffer.data(); - ctx->pb_size = this->pointer_buffer.size(); - } - - /* IWaitable */ - virtual Handle GetHandle() { - return this->session_handle; - } - - virtual Result GetResponse(IpcResponseContext *ctx) { - Result rc = 0xF601; - FirmwareVersion fw = GetRuntimeFirmwareVersion(); - - const ServiceCommandMeta *dispatch_table = ctx->obj_holder->GetDispatchTable(); - size_t entry_count = ctx->obj_holder->GetDispatchTableEntryCount(); - - if (IsDomainObject(ctx->obj_holder)) { - switch (ctx->request.InMessageType) { - case DomainMessageType_Invalid: - return 0xF601; - case DomainMessageType_Close: - return PrepareBasicDomainResponse(ctx, ctx->obj_holder->GetServiceObject<IDomainObject>()->FreeObject(ctx->request.InThisObjectId)); - case DomainMessageType_SendMessage: - { - auto sub_obj = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId); - if (sub_obj == nullptr) { - return PrepareBasicDomainResponse(ctx, 0x3D80B); - } - dispatch_table = sub_obj->GetDispatchTable(); - entry_count = sub_obj->GetDispatchTableEntryCount(); - } - } - } - - for (size_t i = 0; i < entry_count; i++) { - if (ctx->cmd_id == dispatch_table[i].cmd_id && dispatch_table[i].fw_low <= fw && fw <= dispatch_table[i].fw_high) { - rc = dispatch_table[i].handler(ctx); - break; - } - } - - return rc; - } - - virtual Result HandleReceived() { - IpcResponseContext ctx; - this->InitializeResponseContext(&ctx); - - ctx.cmd_type = (IpcCommandType)(*(u16 *)(armGetTls())); - - ctx.rc = 0; - - /* Parse based on command type. */ - switch (ctx.cmd_type) { - case IpcCommandType_Invalid: - case IpcCommandType_LegacyRequest: - case IpcCommandType_LegacyControl: - return 0xF601; - case IpcCommandType_Close: - { - /* Clean up gracefully. */ - PrepareBasicResponse(&ctx, 0); - this->Reply(); - } - return 0xF601; - case IpcCommandType_Control: - case IpcCommandType_ControlWithContext: - ctx.rc = ipcParse(&ctx.request); - ctx.obj_holder = &this->control_holder; - break; - case IpcCommandType_Request: - case IpcCommandType_RequestWithContext: - if (IsDomainObject(&this->obj_holder)) { - ctx.rc = ipcParseDomainRequest(&ctx.request); - } else { - ctx.rc = ipcParse(&ctx.request); - } - break; - default: - return 0xF601; - } - - - if (R_SUCCEEDED(ctx.rc)) { - ctx.cmd_id = ((u32 *)ctx.request.Raw)[2]; - this->PreProcessRequest(&ctx); - ctx.rc = this->GetResponse(&ctx); - } - - if (ctx.rc == RESULT_DEFER_SESSION) { - /* Session defer. */ - this->SetDeferred(true); - } else if (ctx.rc == 0xF601) { - /* Session close, nothing to do. */ - } else { - if (R_SUCCEEDED(ctx.rc)) { - this->PostProcessResponse(&ctx); - } - - ctx.rc = this->Reply(); - - if (ctx.rc == 0xEA01) { - ctx.rc = 0x0; - } - - this->CleanupResponse(&ctx); - } - - return ctx.rc; - } - - virtual Result HandleDeferred() override { - memcpy(armGetTls(), this->backup_tls, sizeof(this->backup_tls)); - Result rc = this->HandleReceived(); - - if (rc != RESULT_DEFER_SESSION) { - this->SetDeferred(false); - } - return rc; - } - - virtual Result HandleSignaled(u64 timeout) { - Result rc; - - if (R_SUCCEEDED(rc = this->Receive())) { - rc = this->HandleReceived(); - } - - return rc; - } - - virtual void PreProcessRequest(IpcResponseContext *ctx) { - /* ... */ - (void)(ctx); - } - - virtual void PostProcessResponse(IpcResponseContext *ctx) { - /* ... */ - (void)(ctx); - } - - virtual void CleanupResponse(IpcResponseContext *ctx) { - std::memset(this->backup_tls, 0, sizeof(this->backup_tls)); - } - - - public: - class IHipcControlService : public IServiceObject { - private: - ServiceSession *session; - public: - explicit IHipcControlService(ServiceSession *s) : session(s) { - - } - - virtual ~IHipcControlService() override { } - - Result ConvertCurrentObjectToDomain(Out<u32> object_id) { - /* Allocate new domain. */ - auto new_domain = this->session->GetDomainManager()->AllocateDomain(); - if (new_domain == nullptr) { - return 0x1900B; - } - - /* Reserve an object in the domain for our session. */ - u32 reserved_id; - Result rc = new_domain->ReserveObject(&reserved_id); - if (R_FAILED(rc)) { - return rc; - } - new_domain->SetObject(reserved_id, std::move(this->session->obj_holder)); - this->session->obj_holder = std::move(ServiceObjectHolder(std::move(new_domain))); - - /* Return the object id. */ - object_id.SetValue(reserved_id); - return 0; - } - - Result CopyFromCurrentDomain(Out<MovedHandle> out_h, u32 id) { - auto domain = this->session->obj_holder.GetServiceObject<IDomainObject>(); - if (domain == nullptr) { - return 0x3D60B; - } - - - auto object = domain->GetObject(id); - if (object == nullptr) { - return 0x3D80B; - } - - Handle server_h, client_h; - if (R_FAILED(SessionManagerBase::CreateSessionHandles(&server_h, &client_h))) { - /* N aborts here. Should we error code? */ - std::abort(); - } - - this->session->GetSessionManager()->AddSession(server_h, std::move(object->Clone())); - out_h.SetValue(client_h); - return 0; - } - - void CloneCurrentObject(Out<MovedHandle> out_h) { - Handle server_h, client_h; - if (R_FAILED(SessionManagerBase::CreateSessionHandles(&server_h, &client_h))) { - /* N aborts here. Should we error code? */ - std::abort(); - } - - this->session->GetSessionManager()->AddSession(server_h, std::move(this->session->obj_holder.Clone())); - out_h.SetValue(client_h); - } - - void QueryPointerBufferSize(Out<u16> size) { - size.SetValue(this->session->pointer_buffer.size()); - } - - void CloneCurrentObjectEx(Out<MovedHandle> out_h, u32 which) { - /* TODO: Figure out what this u32 controls. */ - return CloneCurrentObject(out_h); - } - - public: - DEFINE_SERVICE_DISPATCH_TABLE { - MakeServiceCommandMeta<HipcControlCommand_ConvertCurrentObjectToDomain, &ServiceSession::IHipcControlService::ConvertCurrentObjectToDomain>(), - MakeServiceCommandMeta<HipcControlCommand_CopyFromCurrentDomain, &ServiceSession::IHipcControlService::CopyFromCurrentDomain>(), - MakeServiceCommandMeta<HipcControlCommand_CloneCurrentObject, &ServiceSession::IHipcControlService::CloneCurrentObject>(), - MakeServiceCommandMeta<HipcControlCommand_QueryPointerBufferSize, &ServiceSession::IHipcControlService::QueryPointerBufferSize>(), - MakeServiceCommandMeta<HipcControlCommand_CloneCurrentObjectEx, &ServiceSession::IHipcControlService::CloneCurrentObjectEx>(), - }; - }; -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_session_manager_base.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_session_manager_base.hpp deleted file mode 100644 index 3da68038d..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_session_manager_base.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <atomic> - -#include "../waitable_manager_base.hpp" -#include "ipc_service_object.hpp" - -class SessionManagerBase : public WaitableManagerBase, public DomainManager { - public: - SessionManagerBase() = default; - virtual ~SessionManagerBase() = default; - - virtual void AddSession(Handle server_h, ServiceObjectHolder &&service) = 0; - - static Result CreateSessionHandles(Handle *server_h, Handle *client_h) { - return svcCreateSession(server_h, client_h, 0, 0); - } -}; - diff --git a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp b/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp deleted file mode 100644 index 3b613b366..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/ipc/ipc_special.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <type_traits> - -#include "ipc_out.hpp" - -/* Represents an input PID. */ -struct PidDescriptorTag{}; - -struct PidDescriptor : public PidDescriptorTag { - u64 pid; - - void operator=(u64 &p) { - pid = p; - } - - PidDescriptor(u64 p) : pid(p) { } -}; - -struct IpcHandleTag{}; - -struct IpcHandle : public IpcHandleTag { - Handle handle; -}; - -/* Represents a moved handle. */ -struct MovedHandle : public IpcHandle { - void operator=(const Handle &h) { - this->handle = h; - } - - void operator=(const IpcHandle &o) { - this->handle = o.handle; - } - - MovedHandle(Handle h) { - this->handle = h; - } -}; - -/* Represents a copied handle. */ -struct CopiedHandle : public IpcHandle { - void operator=(const Handle &h) { - handle = h; - } - - void operator=(const IpcHandle &o) { - this->handle = o.handle; - } - - CopiedHandle(Handle h) { - this->handle = h; - } -}; - -template <> -class Out<MovedHandle> : public OutHandleTag { -private: - MovedHandle *obj; -public: - Out(IpcHandle *o) : obj(static_cast<MovedHandle *>(o)) { } - - void SetValue(const Handle& h) { - *obj = h; - } - - void SetValue(const MovedHandle& o) { - *obj = o; - } - - const MovedHandle& GetValue() { - return *obj; - } - - MovedHandle* GetPointer() { - return obj; - } - - Handle* GetHandlePointer() { - return &obj->handle; - } - - /* Convenience operators. */ - MovedHandle& operator*() { - return *obj; - } - - MovedHandle* operator->() { - return obj; - } -}; - -template <> -class Out<CopiedHandle> : public OutHandleTag { -private: - CopiedHandle *obj; -public: - Out(IpcHandle *o) : obj(static_cast<CopiedHandle *>(o)) { } - - void SetValue(const Handle& h) { - *obj = h; - } - - void SetValue(const CopiedHandle& o) { - *obj = o; - } - - const CopiedHandle& GetValue() { - return *obj; - } - - CopiedHandle* GetPointer() { - return obj; - } - - Handle* GetHandlePointer() { - return &obj->handle; - } - - /* Convenience operators. */ - CopiedHandle& operator*() { - return *obj; - } - - CopiedHandle* operator->() { - return obj; - } -}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp b/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp deleted file mode 100644 index d5721f849..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/iwaitable.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include <switch.h> - -#include "waitable_manager_base.hpp" -#include "hossynch.hpp" - -class IWaitable { - private: - u64 wait_priority = 0; - bool is_deferred = false; - WaitableManagerBase *manager = nullptr; - protected: - HosMutex sig_lock; - bool is_signaled = false; - public: - virtual ~IWaitable() = default; - - virtual Result HandleDeferred() { - /* By default, HandleDeferred panics, because object shouldn't be deferrable. */ - std::abort(); - return 0; - } - - bool IsSignaled() { - std::scoped_lock<HosMutex> lock(this->sig_lock); - return this->is_signaled; - } - - virtual Handle GetHandle() = 0; - virtual Result HandleSignaled(u64 timeout) = 0; - - WaitableManagerBase *GetManager() { - return this->manager; - } - - void SetManager(WaitableManagerBase *m) { - this->manager = m; - } - - void UpdatePriority() { - if (manager) { - this->wait_priority = this->manager->GetNextPriority(); - } - } - - bool IsDeferred() { - return this->is_deferred; - } - - void SetDeferred(bool d) { - this->is_deferred = d; - } - - static bool Compare(IWaitable *a, IWaitable *b) { - return (a->wait_priority < b->wait_priority) && !a->IsDeferred() && (a->GetHandle() != INVALID_HANDLE); - } - - void NotifyManagerSignaled() { - if (this->manager) { - this->manager->NotifySignaled(this); - } - } -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp b/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp deleted file mode 100644 index 8ed2bae7f..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/message_queue.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include "hossynch.hpp" -#include <memory> - -class HosMessageQueue { - private: - HosMutex queue_lock; - HosCondVar cv_not_full; - HosCondVar cv_not_empty; - std::unique_ptr<uintptr_t[]> buffer; - size_t capacity; - - size_t count = 0; - size_t offset = 0; - public: - HosMessageQueue(size_t c) : capacity(c) { - this->buffer = std::make_unique<uintptr_t[]>(this->capacity); - } - - HosMessageQueue(std::unique_ptr<uintptr_t[]> buf, size_t c) : buffer(std::move(buf)), capacity(c) { } - - /* Sending (FIFO functionality) */ - void Send(uintptr_t data); - bool TrySend(uintptr_t data); - bool TimedSend(uintptr_t data, u64 timeout); - - /* Sending (LIFO functionality) */ - void SendNext(uintptr_t data); - bool TrySendNext(uintptr_t data); - bool TimedSendNext(uintptr_t data, u64 timeout); - - /* Receive functionality */ - void Receive(uintptr_t *out); - bool TryReceive(uintptr_t *out); - bool TimedReceive(uintptr_t *out, u64 timeout); - - /* Peek functionality */ - void Peek(uintptr_t *out); - bool TryPeek(uintptr_t *out); - bool TimedPeek(uintptr_t *out, u64 timeout); - private: - bool IsFull() { - return this->count >= this->capacity; - } - - bool IsEmpty() { - return this->count == 0; - } - - void SendInternal(uintptr_t data); - void SendNextInternal(uintptr_t data); - uintptr_t ReceiveInternal(); - uintptr_t PeekInternal(); - -}; - diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm.hpp deleted file mode 100644 index 3d1b35259..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/mitm.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include "mitm/sm_mitm.h" - -#include "ipc.hpp" - -#include "mitm/imitmserviceobject.hpp" -#include "mitm/mitm_query_service.hpp" -#include "mitm/mitm_session.hpp" -#include "mitm/mitm_server.hpp" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp deleted file mode 100644 index e37ba152c..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/imitmserviceobject.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <atomic> - -#include <stratosphere.hpp> - -class IMitmServiceObject : public IServiceObject { - protected: - std::shared_ptr<Service> forward_service; - u64 process_id = 0; - u64 title_id = 0; - public: - IMitmServiceObject(std::shared_ptr<Service> s) : forward_service(s) {} - - virtual u64 GetTitleId() { - return this->title_id; - } - - virtual u64 GetProcessId() { - return this->process_id; - } - - static bool ShouldMitm(u64 pid, u64 tid); - - protected: - virtual ~IMitmServiceObject() = default; -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp deleted file mode 100644 index 621c4cfb6..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_query_service.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <stratosphere.hpp> - -enum MitmQueryServiceCommand { - MQS_Cmd_ShouldMitm = 65000, - MQS_Cmd_AssociatePidTid = 65001 -}; - -namespace MitmQueryUtils { - Result GetAssociatedTidForPid(u64 pid, u64 *tid); - - void AssociatePidToTid(u64 pid, u64 tid); -} - -template <typename T> -class MitmQueryService : public IServiceObject { - protected: - void ShouldMitm(Out<bool> should_mitm, u64 pid) { - should_mitm.SetValue(false); - u64 tid = 0; - if (R_SUCCEEDED(MitmQueryUtils::GetAssociatedTidForPid(pid, &tid))) { - should_mitm.SetValue(T::ShouldMitm(pid, tid)); - } - } - void AssociatePidToTid(u64 pid, u64 tid) { - MitmQueryUtils::AssociatePidToTid(pid, tid); - } - public: - DEFINE_SERVICE_DISPATCH_TABLE { - MakeServiceCommandMeta<MQS_Cmd_ShouldMitm, &MitmQueryService<T>::ShouldMitm>(), - MakeServiceCommandMeta<MQS_Cmd_AssociatePidTid, &MitmQueryService<T>::AssociatePidToTid>(), - }; -}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp deleted file mode 100644 index 113df8a55..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_server.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> - -#include "mitm_query_service.hpp" -#include "sm_mitm.h" -#include "mitm_session.hpp" - -template <typename T> -class MitmServer : public IWaitable { - static_assert(std::is_base_of<IMitmServiceObject, T>::value, "MitM Service Objects must derive from IMitmServiceObject"); - private: - Handle port_handle; - unsigned int max_sessions; - char mitm_name[9]; - - public: - MitmServer(Handle *out_query_h, const char *service_name, unsigned int max_s) : port_handle(0), max_sessions(max_s) { - Handle tmp_hnd; - Result rc = smMitMInitialize(); - if (R_FAILED(rc)) { - fatalSimple(rc); - } - - if (R_SUCCEEDED((rc = smGetServiceOriginal(&tmp_hnd, smEncodeName(service_name))))) { - svcCloseHandle(tmp_hnd); - } else { - fatalSimple(rc); - } - strncpy(mitm_name, service_name, 8); - mitm_name[8] = '\x00'; - if (R_FAILED((rc = smMitMInstall(&this->port_handle, out_query_h, mitm_name)))) { - fatalSimple(rc); - } - - smMitMExit(); - } - - virtual ~MitmServer() override { - if (this->port_handle) { - if (R_FAILED(smMitMUninstall(this->mitm_name))) { - std::abort(); - } - svcCloseHandle(port_handle); - } - } - - SessionManagerBase *GetSessionManager() { - return static_cast<SessionManagerBase *>(this->GetManager()); - } - - /* IWaitable */ - virtual Handle GetHandle() override { - return this->port_handle; - } - - virtual Result HandleSignaled(u64 timeout) override { - /* If this server's port was signaled, accept a new session. */ - Handle session_h; - Result rc = svcAcceptSession(&session_h, this->port_handle); - if (R_FAILED(rc)) { - return rc; - } - - /* Create a forward service for this instance. */ - std::shared_ptr<Service>forward_service(new Service(), [](Service *s) { - /* Custom deleter to ensure service is open as long as necessary. */ - serviceClose(s); - delete s; - }); - - rc = smMitMInitialize(); - if (R_FAILED(rc)) { - fatalSimple(rc); - } - - if (R_FAILED(smMitMGetService(forward_service.get(), mitm_name))) { - /* TODO: Panic. */ - } - - smMitMExit(); - - this->GetSessionManager()->AddWaitable(new MitmSession(session_h, forward_service, std::make_shared<T>(forward_service))); - return 0; - } - -}; - -template<typename T> -static void AddMitmServerToManager(SessionManagerBase *manager, const char *srv_name, unsigned int max_sessions) { - Handle query_h; - auto *srv = new MitmServer<T>(&query_h, srv_name, max_sessions); - manager->AddSession(query_h, std::move(ServiceObjectHolder(std::move(std::make_shared<MitmQueryService<T>>())))); - manager->AddWaitable(srv); -} - - diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp b/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp deleted file mode 100644 index 3a4032161..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/mitm_session.hpp +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <stratosphere.hpp> -#include "imitmserviceobject.hpp" - -#include "mitm_query_service.hpp" - -#define RESULT_FORWARD_TO_SESSION 0xCAFEFC - -class MitmSession final : public ServiceSession { - private: - /* This will be for the actual session. */ - std::shared_ptr<Service> forward_service; - - /* Store a handler for the service. */ - void (*service_post_process_handler)(IMitmServiceObject *, IpcResponseContext *); - - /* For cleanup usage. */ - u32 num_fwd_copy_hnds = 0; - Handle fwd_copy_hnds[8]; - public: - template<typename T> - MitmSession(Handle s_h, std::shared_ptr<Service> fs, std::shared_ptr<T> srv) : ServiceSession(s_h) { - this->forward_service = std::move(fs); - this->obj_holder = std::move(ServiceObjectHolder(std::move(srv))); - - this->service_post_process_handler = T::PostProcess; - - size_t pbs; - if (R_FAILED(ipcQueryPointerBufferSize(forward_service->handle, &pbs))) { - std::abort(); - } - this->pointer_buffer.resize(pbs); - this->control_holder.Reset(); - this->control_holder = std::move(ServiceObjectHolder(std::move(std::make_shared<IMitmHipcControlService>(this)))); - } - - MitmSession(Handle s_h, std::shared_ptr<Service> fs, ServiceObjectHolder &&h, void (*pph)(IMitmServiceObject *, IpcResponseContext *)) : ServiceSession(s_h) { - this->session_handle = s_h; - this->forward_service = std::move(fs); - this->obj_holder = std::move(h); - - this->service_post_process_handler = pph; - - size_t pbs; - if (R_FAILED(ipcQueryPointerBufferSize(forward_service->handle, &pbs))) { - std::abort(); - } - this->pointer_buffer.resize(pbs); - this->control_holder.Reset(); - this->control_holder = std::move(ServiceObjectHolder(std::move(std::make_shared<IMitmHipcControlService>(this)))); - } - - virtual void PreProcessRequest(IpcResponseContext *ctx) override { - u32 *cmdbuf = (u32 *)armGetTls(); - u32 *backup_cmdbuf = (u32 *)this->backup_tls; - if (ctx->request.HasPid) { - /* [ctrl 0] [ctrl 1] [handle desc 0] [pid low] [pid high] */ - cmdbuf[4] = 0xFFFE0000UL | (cmdbuf[4] & 0xFFFFUL); - backup_cmdbuf[4] = cmdbuf[4]; - } - } - - Result ForwardRequest(IpcResponseContext *ctx) { - IpcParsedCommand r; - Result rc = serviceIpcDispatch(this->forward_service.get()); - if (R_SUCCEEDED(rc)) { - if (ctx->request.IsDomainRequest) { - /* We never work with out object ids, so this should be fine. */ - ipcParseDomainResponse(&r, 0); - } else { - ipcParse(&r); - } - - struct { - u64 magic; - u64 result; - } *resp = (decltype(resp))r.Raw; - - rc = resp->result; - - for (unsigned int i = 0; i < r.NumHandles; i++) { - if (r.WasHandleCopied[i]) { - this->fwd_copy_hnds[num_fwd_copy_hnds++] = r.Handles[i]; - } - } - } - return rc; - } - - virtual Result GetResponse(IpcResponseContext *ctx) { - Result rc = 0xF601; - FirmwareVersion fw = GetRuntimeFirmwareVersion(); - - const ServiceCommandMeta *dispatch_table = ctx->obj_holder->GetDispatchTable(); - size_t entry_count = ctx->obj_holder->GetDispatchTableEntryCount(); - - if (IsDomainObject(ctx->obj_holder)) { - switch (ctx->request.InMessageType) { - case DomainMessageType_Invalid: - return 0xF601; - case DomainMessageType_Close: - rc = ForwardRequest(ctx); - if (R_SUCCEEDED(rc)) { - ctx->obj_holder->GetServiceObject<IDomainObject>()->FreeObject(ctx->request.InThisObjectId); - } - if (R_SUCCEEDED(rc) && ctx->request.InThisObjectId == serviceGetObjectId(this->forward_service.get())) { - /* If we're not longer MitMing anything, we don't need a mitm session. */ - this->Reply(); - this->GetSessionManager()->AddSession(this->session_handle, std::move(this->obj_holder)); - this->session_handle = 0; - return 0xF601; - } - return rc; - case DomainMessageType_SendMessage: - { - auto sub_obj = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId); - if (sub_obj == nullptr) { - rc = ForwardRequest(ctx); - return rc; - } - dispatch_table = sub_obj->GetDispatchTable(); - entry_count = sub_obj->GetDispatchTableEntryCount(); - } - } - } - - bool found_entry = false; - - for (size_t i = 0; i < entry_count; i++) { - if (ctx->cmd_id == dispatch_table[i].cmd_id && dispatch_table[i].fw_low <= fw && fw <= dispatch_table[i].fw_high) { - rc = dispatch_table[i].handler(ctx); - found_entry = true; - break; - } - } - - if (!found_entry || rc == RESULT_FORWARD_TO_SESSION) { - memcpy(armGetTls(), this->backup_tls, sizeof(this->backup_tls)); - rc = ForwardRequest(ctx); - } - - return rc; - } - - virtual void PostProcessResponse(IpcResponseContext *ctx) override { - if ((ctx->cmd_type == IpcCommandType_Request || ctx->cmd_type == IpcCommandType_RequestWithContext) && R_SUCCEEDED(ctx->rc)) { - if (!IsDomainObject(ctx->obj_holder) || ctx->request.InThisObjectId == serviceGetObjectId(this->forward_service.get())) { - IMitmServiceObject *obj; - if (!IsDomainObject(ctx->obj_holder)) { - obj = ctx->obj_holder->GetServiceObjectUnsafe<IMitmServiceObject>(); - } else { - obj = ctx->obj_holder->GetServiceObject<IDomainObject>()->GetObject(ctx->request.InThisObjectId)->GetServiceObjectUnsafe<IMitmServiceObject>(); - } - this->service_post_process_handler(obj, ctx); - } - } - } - - virtual void CleanupResponse(IpcResponseContext *ctx) override { - /* Cleanup tls backup. */ - std::memset(this->backup_tls, 0, sizeof(this->backup_tls)); - - /* Clean up copy handles. */ - for (unsigned int i = 0; i < ctx->request.NumHandles; i++) { - if (ctx->request.WasHandleCopied[i]) { - svcCloseHandle(ctx->request.Handles[i]); - } - } - for (unsigned int i = 0; i < this->num_fwd_copy_hnds; i++) { - svcCloseHandle(this->fwd_copy_hnds[i]); - } - this->num_fwd_copy_hnds = 0; - } - - public: - class IMitmHipcControlService : public IServiceObject { - private: - MitmSession *session; - public: - explicit IMitmHipcControlService(MitmSession *s) : session(s) { - - } - - virtual ~IMitmHipcControlService() override { } - - public: - Result ConvertCurrentObjectToDomain(Out<u32> object_id) { - if (IsDomainObject(this->session->obj_holder)) { - return 0xF601; - } - - Result rc = serviceConvertToDomain(this->session->forward_service.get()); - if (R_FAILED(rc)) { - return rc; - } - - u32 expected_id = serviceGetObjectId(this->session->forward_service.get()); - - /* Allocate new domain. */ - auto new_domain = this->session->GetDomainManager()->AllocateDomain(); - if (new_domain == nullptr) { - /* If our domains mismatch, we're in trouble. */ - return 0xF601; - } - - /* Reserve the expected object in the domain for our session. */ - if (R_FAILED(new_domain->ReserveSpecificObject(expected_id))) { - return 0xF601; - } - new_domain->SetObject(expected_id, std::move(this->session->obj_holder)); - this->session->obj_holder = std::move(ServiceObjectHolder(std::move(new_domain))); - - /* Return the object id. */ - object_id.SetValue(expected_id); - return 0; - } - - Result CopyFromCurrentDomain(Out<MovedHandle> out_h, u32 id) { - auto domain = this->session->obj_holder.GetServiceObject<IDomainObject>(); - if (domain == nullptr) { - return 0x3D60B; - } - - - auto object = domain->GetObject(id); - if (object == nullptr) { - /* Forward onwards. */ - u32 *buf = (u32 *)armGetTls(); - buf[0] = IpcCommandType_Control; - buf[1] = 0xA; - buf[4] = SFCI_MAGIC; - buf[5] = 0; - buf[6] = 1; - buf[7] = 0; - buf[8] = id; - buf[9] = 0; - Result rc = ipcDispatch(this->session->forward_service->handle); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - struct { - u64 magic; - u64 result; - } *raw = (decltype(raw))r.Raw; - rc = raw->result; - - if (R_SUCCEEDED(rc)) { - out_h.SetValue(r.Handles[0]); - this->session->fwd_copy_hnds[this->session->num_fwd_copy_hnds++] = r.Handles[0]; - } - } - return rc; - } - - Handle server_h, client_h; - if (R_FAILED(SessionManagerBase::CreateSessionHandles(&server_h, &client_h))) { - /* N aborts here. Should we error code? */ - std::abort(); - } - out_h.SetValue(client_h); - - if (id == serviceGetObjectId(this->session->forward_service.get())) { - this->session->GetSessionManager()->AddWaitable(new MitmSession(server_h, this->session->forward_service, std::move(object->Clone()), this->session->service_post_process_handler)); - } else { - this->session->GetSessionManager()->AddSession(server_h, std::move(object->Clone())); - } - return 0; - } - - void CloneCurrentObject(Out<MovedHandle> out_h) { - Handle server_h, client_h; - if (R_FAILED(SessionManagerBase::CreateSessionHandles(&server_h, &client_h))) { - /* N aborts here. Should we error code? */ - std::abort(); - } - - this->session->GetSessionManager()->AddWaitable(new MitmSession(server_h, this->session->forward_service, std::move(this->session->obj_holder.Clone()), this->session->service_post_process_handler)); - out_h.SetValue(client_h); - } - - void QueryPointerBufferSize(Out<u16> size) { - size.SetValue(this->session->pointer_buffer.size()); - } - - void CloneCurrentObjectEx(Out<MovedHandle> out_h, u32 which) { - /* TODO: Figure out what this u32 controls. */ - return CloneCurrentObject(out_h); - } - - public: - DEFINE_SERVICE_DISPATCH_TABLE { - MakeServiceCommandMeta<HipcControlCommand_ConvertCurrentObjectToDomain, &MitmSession::IMitmHipcControlService::ConvertCurrentObjectToDomain>(), - MakeServiceCommandMeta<HipcControlCommand_CopyFromCurrentDomain, &MitmSession::IMitmHipcControlService::CopyFromCurrentDomain>(), - MakeServiceCommandMeta<HipcControlCommand_CloneCurrentObject, &MitmSession::IMitmHipcControlService::CloneCurrentObject>(), - MakeServiceCommandMeta<HipcControlCommand_QueryPointerBufferSize, &MitmSession::IMitmHipcControlService::QueryPointerBufferSize>(), - MakeServiceCommandMeta<HipcControlCommand_CloneCurrentObjectEx, &MitmSession::IMitmHipcControlService::CloneCurrentObjectEx>(), - }; - }; -}; diff --git a/stratosphere/libstratosphere/include/stratosphere/mitm/sm_mitm.h b/stratosphere/libstratosphere/include/stratosphere/mitm/sm_mitm.h deleted file mode 100644 index 4b521c88c..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/mitm/sm_mitm.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file sm_mitm.h - * @brief Service manager (sm) IPC wrapper for Atmosphere extensions. - * @author SciresM - * @copyright libnx Authors - */ -#pragma once -#include <switch.h> - -#ifdef __cplusplus -extern "C" { -#endif - -Result smMitMInitialize(void); -void smMitMExit(void); -Result smMitMGetService(Service* service_out, const char *name); -Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name); -Result smMitMUninstall(const char *name); - -Result smMitMIsRegistered(const char *name); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp b/stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp deleted file mode 100644 index fa611a518..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/scope_guard.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - /* Scope guard logic lovingly taken from Andrei Alexandrescu's "Systemic Error Handling in C++" */ -#pragma once - -#include <utility> - -template<class F> -class ScopeGuard { -private: - F f; - bool active; -public: - ScopeGuard(F f) : f(std::move(f)), active(true) { } - ~ScopeGuard() { if (active) { f(); } } - void Cancel() { active = false; } - - ScopeGuard() = delete; - ScopeGuard(const ScopeGuard &) = delete; - ScopeGuard& operator=(const ScopeGuard&) = delete; - ScopeGuard(ScopeGuard&& rhs) : f(std::move(rhs.f)), active(rhs.active) { - rhs.Cancel(); - } -}; - -template<class F> -ScopeGuard<F> MakeScopeGuard(F f) { - return ScopeGuard<F>(std::move(f)); -} - -enum class ScopeGuardOnExit {}; - -template <typename F> -ScopeGuard<F> operator+(ScopeGuardOnExit, F&& f) { - return ScopeGuard<F>(std::forward<F>(f)); -} - -#define CONCATENATE_IMPL(S1, s2) s1##s2 -#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2) - -#ifdef __COUNTER__ -#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__) -#else -#define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __LINE__) -#endif - -#define ON_SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE_) = ScopeGuardOnExit() + [&]() \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/servers.hpp b/stratosphere/libstratosphere/include/stratosphere/servers.hpp deleted file mode 100644 index 7771157f1..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/servers.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> - -#include "iwaitable.hpp" -#include "ipc.hpp" - -template<typename T> -class IServer : public IWaitable { - static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); - protected: - Handle port_handle; - unsigned int max_sessions; - - public: - IServer(unsigned int max_s) : port_handle(0), max_sessions(max_s) { } - - virtual ~IServer() { - if (port_handle) { - svcCloseHandle(port_handle); - } - } - - SessionManagerBase *GetSessionManager() { - return static_cast<SessionManagerBase *>(this->GetManager()); - } - - /* IWaitable */ - virtual Handle GetHandle() override { - return this->port_handle; - } - - virtual Result HandleSignaled(u64 timeout) override { - /* If this server's port was signaled, accept a new session. */ - Handle session_h; - Result rc = svcAcceptSession(&session_h, this->port_handle); - if (R_FAILED(rc)) { - return rc; - } - - this->GetSessionManager()->AddSession(session_h, std::move(ServiceObjectHolder(std::move(std::make_shared<T>())))); - return 0; - } -}; - -template <typename T> -class ServiceServer : public IServer<T> { - public: - ServiceServer(const char *service_name, unsigned int max_s) : IServer<T>(max_s) { - if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) { - /* TODO: Panic. */ - } - } -}; - -template <typename T> -class ExistingPortServer : public IServer<T> { - public: - ExistingPortServer(Handle port_h, unsigned int max_s) : IServer<T>(max_s) { - this->port_handle = port_h; - } -}; - -template <typename T> -class ManagedPortServer : public IServer<T> { - public: - ManagedPortServer(const char *service_name, unsigned int max_s) : IServer<T>(max_s) { - if (R_FAILED(svcManageNamedPort(&this->port_handle, service_name, this->max_sessions))) { - /* TODO: panic */ - } - } -}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/services.hpp b/stratosphere/libstratosphere/include/stratosphere/services.hpp deleted file mode 100644 index 7db234698..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/services.hpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include "ipc.hpp" - -#include "services/smm_ams.h" \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/services/smm_ams.h b/stratosphere/libstratosphere/include/stratosphere/services/smm_ams.h deleted file mode 100644 index 85973929f..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/services/smm_ams.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> - -#ifdef __cplusplus -extern "C" { -#endif - -Result smManagerAmsInitialize(void); -void smManagerAmsExit(void); - -Result smManagerAmsEndInitialDefers(void); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/version_check.hpp b/stratosphere/libstratosphere/include/stratosphere/version_check.hpp deleted file mode 100644 index 336ea837c..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/version_check.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <switch.h> -#include <atmosphere/version.h> - -static inline void GetAtmosphereApiVersion(u32 *major, u32 *minor, u32 *micro, u32 *target_fw, u32 *mkey_rev) { - if (R_FAILED(splInitialize())) { - fatalSimple(0xCAFE << 4 | 0xD); - } - - /* Check for exosphere API compatibility. */ - u64 exosphere_cfg; - if (R_FAILED(splGetConfig((SplConfigItem)65000, &exosphere_cfg))) { - fatalSimple(0xCAFE << 4 | 0xE); - } - - if (mkey_rev) { - *mkey_rev = (u32)((exosphere_cfg >> 0x00) & 0xFF); - } - - if (target_fw) { - *target_fw = (u32)((exosphere_cfg >> 0x08) & 0xFF); - } - - if (micro) { - *micro = (u32)((exosphere_cfg >> 0x10) & 0xFF); - } - - if (minor) { - *minor = (u32)((exosphere_cfg >> 0x18) & 0xFF); - } - - if (major) { - *major = (u32)((exosphere_cfg >> 0x20) & 0xFF); - } - - splExit(); -} - -static inline u32 MakeAtmosphereVersion(u32 major, u32 minor, u32 micro) { - return (major << 16) | (minor << 8) | micro; -} - -static inline void CheckAtmosphereVersion() { - u32 major, minor, micro; - GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); - - if (MakeAtmosphereVersion(major, minor, micro) < MakeAtmosphereVersion(ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO)) { - fatalSimple(0xCAFE << 4 | 0xF); - } -} \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp deleted file mode 100644 index 47244e561..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager.hpp +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include <switch.h> -#include <memory> - -#include "../meta_tools.hpp" - -#include "waitable_manager_base.hpp" -#include "event.hpp" -#include "ipc.hpp" -#include "servers.hpp" - -#include "scope_guard.hpp" - -static inline Handle GetCurrentThreadHandle() { - return threadGetCurHandle(); -} - -struct DefaultManagerOptions { - static constexpr size_t PointerBufferSize = 0; - static constexpr size_t MaxDomains = 0; - static constexpr size_t MaxDomainObjects = 0; -}; - -struct DomainEntry { - ServiceObjectHolder obj_holder; - IDomainObject *owner = nullptr; -}; - -template<typename ManagerOptions = DefaultManagerOptions> -class WaitableManager : public SessionManagerBase { - private: - /* Domain Manager */ - HosMutex domain_lock; - std::array<std::weak_ptr<IDomainObject>, ManagerOptions::MaxDomains> domains; - std::array<bool, ManagerOptions::MaxDomains> is_domain_allocated; - std::array<DomainEntry, ManagerOptions::MaxDomainObjects> domain_objects; - - /* Waitable Manager */ - std::vector<IWaitable *> to_add_waitables; - std::vector<IWaitable *> waitables; - std::vector<IWaitable *> deferred_waitables; - - u32 num_extra_threads = 0; - HosThread *threads = nullptr; - - HosMutex process_lock; - HosMutex signal_lock; - HosMutex add_lock; - HosMutex cur_thread_lock; - HosMutex deferred_lock; - bool has_new_waitables = false; - std::atomic<bool> should_stop = false; - - IWaitable *next_signaled = nullptr; - Handle main_thread_handle = INVALID_HANDLE; - Handle cur_thread_handle = INVALID_HANDLE; - public: - WaitableManager(u32 n, u32 ss = 0x8000) : num_extra_threads(n-1) { - u32 prio; - Result rc; - if (num_extra_threads) { - threads = new HosThread[num_extra_threads]; - if (R_FAILED((rc = svcGetThreadPriority(&prio, CUR_THREAD_HANDLE)))) { - fatalSimple(rc); - } - for (unsigned int i = 0; i < num_extra_threads; i++) { - if (R_FAILED(threads[i].Initialize(&WaitableManager::ProcessLoop, this, ss, prio))) { - std::abort(); - } - } - } - } - - ~WaitableManager() override { - /* This should call the destructor for every waitable. */ - std::for_each(to_add_waitables.begin(), to_add_waitables.end(), std::default_delete<IWaitable>{}); - std::for_each(waitables.begin(), waitables.end(), std::default_delete<IWaitable>{}); - std::for_each(deferred_waitables.begin(), deferred_waitables.end(), std::default_delete<IWaitable>{}); - - /* If we've reached here, we should already have exited the threads. */ - } - - virtual void AddWaitable(IWaitable *w) override { - std::scoped_lock lk{this->add_lock}; - this->to_add_waitables.push_back(w); - w->SetManager(this); - this->has_new_waitables = true; - this->CancelSynchronization(); - } - - virtual void RequestStop() { - this->should_stop = true; - this->CancelSynchronization(); - } - - virtual void CancelSynchronization() { - svcCancelSynchronization(GetProcessingThreadHandle()); - } - - virtual void NotifySignaled(IWaitable *w) override { - std::scoped_lock lk{this->signal_lock}; - if (this->next_signaled == nullptr) { - this->next_signaled = w; - } - this->CancelSynchronization(); - } - - virtual void Process() override { - /* Add initial set of waitables. */ - AddWaitablesInternal(); - - /* Set main thread handle. */ - this->main_thread_handle = GetCurrentThreadHandle(); - - Result rc; - for (unsigned int i = 0; i < num_extra_threads; i++) { - if (R_FAILED((rc = threads[i].Start()))) { - fatalSimple(rc); - } - } - - ProcessLoop(this); - } - private: - void SetProcessingThreadHandle(Handle h) { - std::scoped_lock<HosMutex> lk{this->cur_thread_lock}; - this->cur_thread_handle = h; - } - - Handle GetProcessingThreadHandle() { - std::scoped_lock<HosMutex> lk{this->cur_thread_lock}; - return this->cur_thread_handle; - } - - static void ProcessLoop(void *t) { - WaitableManager *this_ptr = (WaitableManager *)t; - while (true) { - IWaitable *w = this_ptr->GetWaitable(); - if (this_ptr->should_stop) { - if (GetCurrentThreadHandle() == this_ptr->main_thread_handle) { - /* Join all threads but the main one. */ - for (unsigned int i = 0; i < this_ptr->num_extra_threads; i++) { - this_ptr->threads[i].Join(); - } - break; - } else { - svcExitThread(); - } - } - if (w) { - Result rc = w->HandleSignaled(0); - if (rc == 0xF601) { - /* Close! */ - delete w; - } else { - if (w->IsDeferred()) { - std::scoped_lock lk{this_ptr->deferred_lock}; - this_ptr->deferred_waitables.push_back(w); - } else { - this_ptr->AddWaitable(w); - } - } - } - - /* We finished processing, and maybe that means we can stop deferring an object. */ - { - std::scoped_lock lk{this_ptr->deferred_lock}; - - for (auto it = this_ptr->deferred_waitables.begin(); it != this_ptr->deferred_waitables.end();) { - auto w = *it; - Result rc = w->HandleDeferred(); - if (rc == 0xF601 || !w->IsDeferred()) { - /* Remove from the deferred list, set iterator. */ - it = this_ptr->deferred_waitables.erase(it); - if (rc == 0xF601) { - /* Delete the closed waitable. */ - delete w; - } else { - /* Add to the waitables list. */ - this_ptr->AddWaitable(w); - } - } else { - /* Move on to the next deferred waitable. */ - it++; - } - } - } - } - } - - IWaitable *GetWaitable() { - std::scoped_lock lk{this->process_lock}; - - /* Set processing thread handle while in scope. */ - SetProcessingThreadHandle(GetCurrentThreadHandle()); - ON_SCOPE_EXIT { - SetProcessingThreadHandle(INVALID_HANDLE); - }; - - /* Prepare variables for result. */ - this->next_signaled = nullptr; - IWaitable *result = nullptr; - - if (this->should_stop) { - return nullptr; - } - - /* Add new waitables, if any. */ - AddWaitablesInternal(); - - /* First, see if anything's already signaled. */ - for (auto &w : this->waitables) { - if (w->IsSignaled()) { - result = w; - } - } - - /* It's possible somebody signaled us while we were iterating. */ - { - std::scoped_lock lk{this->signal_lock}; - if (this->next_signaled != nullptr) result = this->next_signaled; - } - - if (result == nullptr) { - std::vector<Handle> handles; - std::vector<IWaitable *> wait_list; - - int handle_index = 0; - Result rc; - while (result == nullptr) { - /* Sort waitables by priority. */ - std::sort(this->waitables.begin(), this->waitables.end(), IWaitable::Compare); - - /* Copy out handles. */ - handles.resize(this->waitables.size()); - wait_list.resize(this->waitables.size()); - unsigned int num_handles = 0; - - /* Try to add waitables to wait list. */ - for (unsigned int i = 0; i < this->waitables.size(); i++) { - Handle h = this->waitables[i]->GetHandle(); - if (h != INVALID_HANDLE) { - wait_list[num_handles] = this->waitables[i]; - handles[num_handles++] = h; - } - } - - /* Wait forever. */ - rc = svcWaitSynchronization(&handle_index, handles.data(), num_handles, U64_MAX); - - if (this->should_stop) { - return nullptr; - } - - if (R_SUCCEEDED(rc)) { - IWaitable *w = wait_list[handle_index]; - size_t w_ind = std::distance(this->waitables.begin(), std::find(this->waitables.begin(), this->waitables.end(), w)); - std::for_each(waitables.begin(), waitables.begin() + w_ind + 1, std::mem_fn(&IWaitable::UpdatePriority)); - result = w; - } else if (rc == 0xEA01) { - /* Timeout: Just update priorities. */ - std::for_each(waitables.begin(), waitables.end(), std::mem_fn(&IWaitable::UpdatePriority)); - } else if (rc == 0xEC01) { - /* svcCancelSynchronization was called. */ - AddWaitablesInternal(); - { - std::scoped_lock lk{this->signal_lock}; - if (this->next_signaled != nullptr) { - result = this->next_signaled; - } - } - } else { - /* TODO: Consider the following cases that this covers: */ - /* 7601: Thread termination requested. */ - /* E401: Handle is dead. */ - /* E601: Handle list address invalid. */ - /* EE01: Too many handles. */ - std::abort(); - } - } - } - - this->waitables.erase(std::remove_if(this->waitables.begin(), this->waitables.end(), [&](IWaitable *w) { return w == result; }), this->waitables.end()); - - return result; - } - - void AddWaitablesInternal() { - std::scoped_lock lk{this->add_lock}; - if (this->has_new_waitables) { - this->waitables.insert(this->waitables.end(), this->to_add_waitables.begin(), this->to_add_waitables.end()); - this->to_add_waitables.clear(); - this->has_new_waitables = false; - } - } - /* Session Manager */ - public: - virtual void AddSession(Handle server_h, ServiceObjectHolder &&service) override { - this->AddWaitable(new ServiceSession(server_h, ManagerOptions::PointerBufferSize, std::move(service))); - } - - /* Domain Manager */ - public: - virtual std::shared_ptr<IDomainObject> AllocateDomain() override { - std::scoped_lock lk{this->domain_lock}; - for (size_t i = 0; i < ManagerOptions::MaxDomains; i++) { - if (!this->is_domain_allocated[i]) { - auto new_domain = std::make_shared<IDomainObject>(this); - this->domains[i] = new_domain; - this->is_domain_allocated[i] = true; - return new_domain; - } - } - return nullptr; - } - - void FreeDomain(IDomainObject *domain) override { - std::scoped_lock lk{this->domain_lock}; - for (size_t i = 0; i < ManagerOptions::MaxDomainObjects; i++) { - FreeObject(domain, i+1); - } - for (size_t i = 0; i < ManagerOptions::MaxDomains; i++) { - auto observe = this->domains[i].lock(); - if (observe.get() == domain) { - this->is_domain_allocated[i] = false; - break; - } - } - } - - virtual Result ReserveObject(IDomainObject *domain, u32 *out_object_id) override { - std::scoped_lock lk{this->domain_lock}; - for (size_t i = 0; i < ManagerOptions::MaxDomainObjects; i++) { - if (this->domain_objects[i].owner == nullptr) { - this->domain_objects[i].owner = domain; - *out_object_id = i+1; - return 0; - } - } - return 0x25A0A; - } - - virtual Result ReserveSpecificObject(IDomainObject *domain, u32 object_id) override { - std::scoped_lock lk{this->domain_lock}; - if (this->domain_objects[object_id-1].owner == nullptr) { - this->domain_objects[object_id-1].owner = domain; - return 0; - } - return 0x25A0A; - } - - virtual void SetObject(IDomainObject *domain, u32 object_id, ServiceObjectHolder&& holder) override { - std::scoped_lock lk{this->domain_lock}; - if (this->domain_objects[object_id-1].owner == domain) { - this->domain_objects[object_id-1].obj_holder = std::move(holder); - } - } - - virtual ServiceObjectHolder *GetObject(IDomainObject *domain, u32 object_id) override { - std::scoped_lock lk{this->domain_lock}; - if (this->domain_objects[object_id-1].owner == domain) { - return &this->domain_objects[object_id-1].obj_holder; - } - return nullptr; - } - - virtual Result FreeObject(IDomainObject *domain, u32 object_id) override { - std::scoped_lock lk{this->domain_lock}; - if (this->domain_objects[object_id-1].owner == domain) { - this->domain_objects[object_id-1].obj_holder.Reset(); - this->domain_objects[object_id-1].owner = nullptr; - return 0x0; - } - return 0x3D80B; - } - - virtual Result ForceFreeObject(u32 object_id) override { - std::scoped_lock lk{this->domain_lock}; - if (this->domain_objects[object_id-1].owner != nullptr) { - this->domain_objects[object_id-1].obj_holder.Reset(); - this->domain_objects[object_id-1].owner = nullptr; - return 0x0; - } - return 0x3D80B; - } -}; - diff --git a/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp b/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp deleted file mode 100644 index 35242aac2..000000000 --- a/stratosphere/libstratosphere/include/stratosphere/waitable_manager_base.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#pragma once -#include <atomic> - -class IWaitable; - -class WaitableManagerBase { - std::atomic<u64> cur_priority = 0; - public: - WaitableManagerBase() = default; - virtual ~WaitableManagerBase() = default; - - u64 GetNextPriority() { - return std::atomic_fetch_add(&cur_priority, (u64)1); - } - - virtual void AddWaitable(IWaitable *w) = 0; - virtual void NotifySignaled(IWaitable *w) = 0; - - virtual void RequestStop() = 0; - virtual void Process() = 0; -}; - diff --git a/stratosphere/libstratosphere/source/message_queue.cpp b/stratosphere/libstratosphere/source/message_queue.cpp deleted file mode 100644 index dc24cd937..000000000 --- a/stratosphere/libstratosphere/source/message_queue.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <mutex> -#include <switch.h> -#include <stratosphere.hpp> - - -void HosMessageQueue::Send(uintptr_t data) { - /* Acquire mutex, wait sendable. */ - std::scoped_lock<HosMutex> lock(this->queue_lock); - - while (this->IsFull()) { - this->cv_not_full.Wait(&this->queue_lock); - } - - /* Send, signal. */ - this->SendInternal(data); - this->cv_not_empty.WakeAll(); -} - -bool HosMessageQueue::TrySend(uintptr_t data) { - std::scoped_lock<HosMutex> lock(this->queue_lock); - if (this->IsFull()) { - return false; - } - - /* Send, signal. */ - this->SendInternal(data); - this->cv_not_empty.WakeAll(); - return true; -} - -bool HosMessageQueue::TimedSend(uintptr_t data, u64 timeout) { - std::scoped_lock<HosMutex> lock(this->queue_lock); - TimeoutHelper timeout_helper(timeout); - - while (this->IsFull()) { - if (timeout_helper.TimedOut()) { - return false; - } - - this->cv_not_full.TimedWait(timeout, &this->queue_lock); - } - - /* Send, signal. */ - this->SendInternal(data); - this->cv_not_empty.WakeAll(); - return true; -} - -void HosMessageQueue::SendNext(uintptr_t data) { - /* Acquire mutex, wait sendable. */ - std::scoped_lock<HosMutex> lock(this->queue_lock); - - while (this->IsFull()) { - this->cv_not_full.Wait(&this->queue_lock); - } - - /* Send, signal. */ - this->SendNextInternal(data); - this->cv_not_empty.WakeAll(); -} - -bool HosMessageQueue::TrySendNext(uintptr_t data) { - std::scoped_lock<HosMutex> lock(this->queue_lock); - if (this->IsFull()) { - return false; - } - - /* Send, signal. */ - this->SendNextInternal(data); - this->cv_not_empty.WakeAll(); - return true; -} - -bool HosMessageQueue::TimedSendNext(uintptr_t data, u64 timeout) { - std::scoped_lock<HosMutex> lock(this->queue_lock); - TimeoutHelper timeout_helper(timeout); - - while (this->IsFull()) { - if (timeout_helper.TimedOut()) { - return false; - } - - this->cv_not_full.TimedWait(timeout, &this->queue_lock); - } - - /* Send, signal. */ - this->SendNextInternal(data); - this->cv_not_empty.WakeAll(); - return true; -} - -void HosMessageQueue::Receive(uintptr_t *out) { - /* Acquire mutex, wait receivable. */ - std::scoped_lock<HosMutex> lock(this->queue_lock); - - while (this->IsEmpty()) { - this->cv_not_empty.Wait(&this->queue_lock); - } - - /* Receive, signal. */ - *out = this->ReceiveInternal(); - this->cv_not_full.WakeAll(); -} -bool HosMessageQueue::TryReceive(uintptr_t *out) { - /* Acquire mutex, wait receivable. */ - std::scoped_lock<HosMutex> lock(this->queue_lock); - - if (this->IsEmpty()) { - return false; - } - - /* Receive, signal. */ - *out = this->ReceiveInternal(); - this->cv_not_full.WakeAll(); - return true; -} - -bool HosMessageQueue::TimedReceive(uintptr_t *out, u64 timeout) { - std::scoped_lock<HosMutex> lock(this->queue_lock); - TimeoutHelper timeout_helper(timeout); - - while (this->IsEmpty()) { - if (timeout_helper.TimedOut()) { - return false; - } - - this->cv_not_empty.TimedWait(timeout, &this->queue_lock); - } - - /* Receive, signal. */ - *out = this->ReceiveInternal(); - this->cv_not_full.WakeAll(); - return true; -} - -void HosMessageQueue::Peek(uintptr_t *out) { - /* Acquire mutex, wait receivable. */ - std::scoped_lock<HosMutex> lock(this->queue_lock); - - while (this->IsEmpty()) { - this->cv_not_empty.Wait(&this->queue_lock); - } - - /* Peek. */ - *out = this->PeekInternal(); -} - -bool HosMessageQueue::TryPeek(uintptr_t *out) { - /* Acquire mutex, wait receivable. */ - std::scoped_lock<HosMutex> lock(this->queue_lock); - - if (this->IsEmpty()) { - return false; - } - - /* Peek. */ - *out = this->PeekInternal(); - return true; -} - -bool HosMessageQueue::TimedPeek(uintptr_t *out, u64 timeout) { - std::scoped_lock<HosMutex> lock(this->queue_lock); - TimeoutHelper timeout_helper(timeout); - - while (this->IsEmpty()) { - if (timeout_helper.TimedOut()) { - return false; - } - - this->cv_not_empty.TimedWait(timeout, &this->queue_lock); - } - - /* Peek. */ - *out = this->PeekInternal(); - return true; -} - -void HosMessageQueue::SendInternal(uintptr_t data) { - /* Ensure we don't corrupt the queue, but this should never happen. */ - if (this->count >= this->capacity) { - std::abort(); - } - - /* Write data to tail of queue. */ - this->buffer[(this->count++ + this->offset) % this->capacity] = data; -} - -void HosMessageQueue::SendNextInternal(uintptr_t data) { - /* Ensure we don't corrupt the queue, but this should never happen. */ - if (this->count >= this->capacity) { - std::abort(); - } - - /* Write data to head of queue. */ - this->offset = (this->offset + this->capacity - 1) % this->capacity; - this->buffer[this->offset] = data; - this->count++; -} - -uintptr_t HosMessageQueue::ReceiveInternal() { - /* Ensure we don't corrupt the queue, but this should never happen. */ - if (this->count == 0) { - std::abort(); - } - - uintptr_t data = this->buffer[this->offset]; - this->offset = (this->offset + 1) % this->capacity; - this->count--; - return data; -} - -uintptr_t HosMessageQueue::PeekInternal() { - /* Ensure we don't corrupt the queue, but this should never happen. */ - if (this->count == 0) { - std::abort(); - } - - return this->buffer[this->offset]; -} \ No newline at end of file diff --git a/stratosphere/libstratosphere/source/mitm_query_service.cpp b/stratosphere/libstratosphere/source/mitm_query_service.cpp deleted file mode 100644 index eb3654575..000000000 --- a/stratosphere/libstratosphere/source/mitm_query_service.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <mutex> -#include <switch.h> -#include <stratosphere.hpp> - -static std::vector<u64> g_known_pids; -static std::vector<u64> g_known_tids; -static HosMutex g_pid_tid_mutex; - -Result MitmQueryUtils::GetAssociatedTidForPid(u64 pid, u64 *tid) { - Result rc = 0xCAFE; - std::scoped_lock lk{g_pid_tid_mutex}; - for (unsigned int i = 0; i < g_known_pids.size(); i++) { - if (g_known_pids[i] == pid) { - *tid = g_known_tids[i]; - rc = 0x0; - break; - } - } - return rc; -} - -void MitmQueryUtils::AssociatePidToTid(u64 pid, u64 tid) { - std::scoped_lock lk{g_pid_tid_mutex}; - g_known_pids.push_back(pid); - g_known_tids.push_back(tid); -} diff --git a/stratosphere/libstratosphere/source/sm_mitm.c b/stratosphere/libstratosphere/source/sm_mitm.c deleted file mode 100644 index 0bbb284df..000000000 --- a/stratosphere/libstratosphere/source/sm_mitm.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <switch.h> -#include <switch/arm/atomics.h> -#include <stratosphere/mitm/sm_mitm.h> - -static Handle g_smMitmHandle = INVALID_HANDLE; -static u64 g_refCnt; - -Result smMitMInitialize(void) { - atomicIncrement64(&g_refCnt); - - if (g_smMitmHandle != INVALID_HANDLE) - return 0; - - Result rc = svcConnectToNamedPort(&g_smMitmHandle, "sm:"); - - if (R_SUCCEEDED(rc)) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 zero; - u64 reserved[2]; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->zero = 0; - - rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - } - - if (R_FAILED(rc)) - smExit(); - - return rc; -} - -void smMitMExit(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - svcCloseHandle(g_smMitmHandle); - g_smMitmHandle = INVALID_HANDLE; - } -} - -Result smMitMGetService(Service* service_out, const char *name_str) -{ - u64 name = smEncodeName(name_str); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - u64 reserved[2]; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->service_name = name; - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - service_out->type = ServiceType_Normal; - service_out->handle = r.Handles[0]; - } - } - - return rc; -} - - -Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65000; - raw->service_name = smEncodeName(name); - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - *query_out = r.Handles[1]; - } - } - - return rc; -} - -Result smMitMUninstall(const char *name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - u64 reserved; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65001; - raw->service_name = smEncodeName(name); - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; -} \ No newline at end of file diff --git a/stratosphere/libstratosphere/source/smm_ams.c b/stratosphere/libstratosphere/source/smm_ams.c deleted file mode 100644 index 2ac9e4e6e..000000000 --- a/stratosphere/libstratosphere/source/smm_ams.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <switch.h> -#include <switch/arm/atomics.h> -#include <stratosphere/services/smm_ams.h> - -static Service g_smManagerAmsSrv; -static u64 g_smManagerAmsRefcnt; - -Result smManagerAmsInitialize(void) { - atomicIncrement64(&g_smManagerAmsRefcnt); - - if (serviceIsActive(&g_smManagerAmsSrv)) - return 0; - - return smGetService(&g_smManagerAmsSrv, "sm:m"); -} - -void smManagerAmsExit(void) { - if (atomicDecrement64(&g_smManagerAmsRefcnt) == 0) - serviceClose(&g_smManagerAmsSrv); -} - -Result smManagerAmsEndInitialDefers(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65000; - - - Result rc = serviceIpcDispatch(&g_smManagerAmsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; - -} \ No newline at end of file From 54a22797a758ee8b3d3a5a30207179a3e4e322ef Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 8 Nov 2018 01:24:40 -0800 Subject: [PATCH 177/489] Make libstratosphere a submodule --- .gitmodules | 3 ++ common/include/atmosphere.h | 30 +++++++++++++++++++ stratosphere/boot/source/boot_main.cpp | 3 +- stratosphere/fs_mitm/source/fsmitm_main.cpp | 4 ++- stratosphere/libstratosphere | 1 + stratosphere/loader/source/ldr_main.cpp | 3 +- stratosphere/pm/source/pm_main.cpp | 3 +- stratosphere/set_mitm/source/setmitm_main.cpp | 3 +- 8 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 common/include/atmosphere.h create mode 160000 stratosphere/libstratosphere diff --git a/.gitmodules b/.gitmodules index 5f85b18b6..771f79185 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "common/include/boost"] path = common/include/boost url = https://github.com/Atmosphere-NX/ext-boost.git +[submodule "stratosphere/libstratosphere"] + path = stratosphere/libstratosphere + url = https://github.com/Atmosphere-NX/libstratosphere.git diff --git a/common/include/atmosphere.h b/common/include/atmosphere.h new file mode 100644 index 000000000..86f2f0427 --- /dev/null +++ b/common/include/atmosphere.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ATMOSPHERE_H +#define ATMOSPHERE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "atmosphere/version.h" + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/stratosphere/boot/source/boot_main.cpp b/stratosphere/boot/source/boot_main.cpp index 9eb94f170..1709654bf 100644 --- a/stratosphere/boot/source/boot_main.cpp +++ b/stratosphere/boot/source/boot_main.cpp @@ -20,6 +20,7 @@ #include <malloc.h> #include <switch.h> +#include <atmosphere.h> #include <stratosphere.hpp> #define CAR_BASE 0x60006000 @@ -84,7 +85,7 @@ void __appInit(void) { fsdevMountSdmc(); - CheckAtmosphereVersion(); + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 1c12d9db1..95f627d7a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -20,6 +20,7 @@ #include <malloc.h> #include <switch.h> +#include <atmosphere.h> #include <stratosphere.hpp> #include "fsmitm_service.hpp" @@ -65,7 +66,8 @@ void __appInit(void) { if (R_FAILED(rc)) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); } - CheckAtmosphereVersion(); + + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere new file mode 160000 index 000000000..3e8731809 --- /dev/null +++ b/stratosphere/libstratosphere @@ -0,0 +1 @@ +Subproject commit 3e873180905d411472722783162e6e4ee8158cfb diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index 8db791cd0..f4118afc7 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -20,6 +20,7 @@ #include <malloc.h> #include <switch.h> +#include <atmosphere.h> #include <stratosphere.hpp> #include "ldr_process_manager.hpp" @@ -80,7 +81,7 @@ void __appInit(void) { fatalSimple(0xCAFE << 4 | 2); } - CheckAtmosphereVersion(); + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 2e15f12c8..07f9fc2ec 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -20,6 +20,7 @@ #include <malloc.h> #include <switch.h> +#include <atmosphere.h> #include <stratosphere.hpp> #include "pm_boot_mode.hpp" @@ -119,7 +120,7 @@ void __appInit(void) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); } - CheckAtmosphereVersion(); + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/set_mitm/source/setmitm_main.cpp index c03f5099d..0a7b0a295 100644 --- a/stratosphere/set_mitm/source/setmitm_main.cpp +++ b/stratosphere/set_mitm/source/setmitm_main.cpp @@ -20,6 +20,7 @@ #include <malloc.h> #include <switch.h> +#include <atmosphere.h> #include <stratosphere.hpp> #include "setsys_mitm_service.hpp" @@ -64,7 +65,7 @@ void __appInit(void) { fatalSimple(rc); } - CheckAtmosphereVersion(); + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { From 9898a01d3b32cbd5624e307447b97daffcf260fe Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 8 Nov 2018 01:27:36 -0800 Subject: [PATCH 178/489] Add current branch to make dist zip name --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c10b6eb7a..7eeab49b6 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ TOPTARGETS := all clean dist -AMSREV := $(shell git rev-parse --short HEAD) +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) AMSREV := $(AMSREV)-dirty endif From cf510ad9bf232865ee20d84402d43062cb46f3c3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 8 Nov 2018 05:28:52 -0800 Subject: [PATCH 179/489] pm: Only register privileged processes with FS as needed --- stratosphere/pm/pm.json | 1 + stratosphere/pm/source/pm_main.cpp | 18 +++++++++++++++--- stratosphere/pm/source/pm_registration.cpp | 6 +++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/stratosphere/pm/pm.json b/stratosphere/pm/pm.json index 0fd963c2b..af1a699c6 100644 --- a/stratosphere/pm/pm.json +++ b/stratosphere/pm/pm.json @@ -65,6 +65,7 @@ "svcReplyAndReceiveWithUserBuffer": "0x44", "svcCreateEvent": "0x45", "svcSetUnsafeLimit": "0x4a", + "svcGetProcessList": "0x65", "svcStartProcess": "0x7a", "svcTerminateProcess": "0x7b", "svcGetProcessInfo": "0x7c", diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 07f9fc2ec..ac3abde53 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -65,9 +65,21 @@ void RegisterPrivilegedProcessesWithFs() { const u32 PRIVILEGED_FAH[0x1C/sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000}; const u32 PRIVILEGED_FAC[0x2C/sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}; - for (u64 pid = PRIVILEGED_PROCESS_MIN; pid <= PRIVILEGED_PROCESS_MAX; pid++) { - fsprUnregisterProgram(pid); - fsprRegisterProgram(pid, pid, FsStorageId_NandSystem, PRIVILEGED_FAH, sizeof(PRIVILEGED_FAH), PRIVILEGED_FAC, sizeof(PRIVILEGED_FAC)); + u32 num_pids; + u64 pids[PRIVILEGED_PROCESS_MAX+1]; + if (R_SUCCEEDED(svcGetProcessList(&num_pids, pids, sizeof(pids)/sizeof(pids[0])))) { + for (u32 i = 0; i < num_pids; i++) { + const u64 pid = pids[i]; + if (PRIVILEGED_PROCESS_MIN <= pid && pid <= PRIVILEGED_PROCESS_MAX) { + fsprUnregisterProgram(pid); + fsprRegisterProgram(pid, pid, FsStorageId_NandSystem, PRIVILEGED_FAH, sizeof(PRIVILEGED_FAH), PRIVILEGED_FAC, sizeof(PRIVILEGED_FAC)); + } + } + } else { + for (u64 pid = PRIVILEGED_PROCESS_MIN; pid <= PRIVILEGED_PROCESS_MAX; pid++) { + fsprUnregisterProgram(pid); + fsprRegisterProgram(pid, pid, FsStorageId_NandSystem, PRIVILEGED_FAH, sizeof(PRIVILEGED_FAH), PRIVILEGED_FAC, sizeof(PRIVILEGED_FAC)); + } } } diff --git a/stratosphere/pm/source/pm_registration.cpp b/stratosphere/pm/source/pm_registration.cpp index 362c47fe5..bf7958dec 100644 --- a/stratosphere/pm/source/pm_registration.cpp +++ b/stratosphere/pm/source/pm_registration.cpp @@ -292,15 +292,15 @@ void Registration::FinalizeExitedProcess(std::shared_ptr<Registration::Process> bool signal_debug_process_5x = kernelAbove500() && process->flags & PROCESSFLAGS_NOTIFYWHENEXITED; /* Unregister with FS. */ if (R_FAILED(fsprUnregisterProgram(process->pid))) { - /* TODO: Panic. */ + std::abort(); } /* Unregister with SM. */ if (R_FAILED(smManagerUnregisterProcess(process->pid))) { - /* TODO: Panic. */ + std::abort(); } /* Unregister with LDR. */ if (R_FAILED(ldrPmUnregisterTitle(process->ldr_queue_index))) { - /* TODO: Panic. */ + std::abort(); } /* Close the process's handle. */ From ce1a6a68bf62ff8ec155f2906507d6f96b39ecb0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 8 Nov 2018 16:02:04 -0800 Subject: [PATCH 180/489] fs.mitm/loader: Fix crashes when launching too many processes. --- fusee/fusee-secondary/src/kernel_patches.c | 4 ++++ stratosphere/libstratosphere | 2 +- stratosphere/loader/source/ldr_process_manager.cpp | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index 909a066aa..d5ae8df7b 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -522,6 +522,10 @@ void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel) { fatal_error("kernel_patcher: unable to identify kernel!\n"); } + if (kernel_info == NULL && is_sd_kernel) { + return; + } + /* Apply hooks. */ uint8_t *kernel = (uint8_t *)_kernel; size_t free_space_offset = kernel_info->free_code_space_offset; diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 3e8731809..bcd80ab44 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 3e873180905d411472722783162e6e4ee8158cfb +Subproject commit bcd80ab445258c20d968aad1c083fd8cb0937bee diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index b1cae6ac4..9b1bdc03a 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -30,6 +30,11 @@ Result ProcessManagerService::CreateProcess(Out<MovedHandle> proc_h, u64 index, fprintf(stderr, "CreateProcess(%016lx, %08x, %08x);\n", index, flags, reslimit_h.handle); + ON_SCOPE_EXIT { + /* Loader doesn't persist the copied resource limit handle. */ + svcCloseHandle(reslimit_h.handle); + }; + rc = Registration::GetRegisteredTidSid(index, &tid_sid); if (R_FAILED(rc)) { return rc; From bb29a2458f1b586c2e09f5d00fae757fdc989b69 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 8 Nov 2018 16:36:22 -0800 Subject: [PATCH 181/489] Bump version to 0.7.4 --- common/include/atmosphere/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 9ab1693ad..151d103f8 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 7 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 3 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 4 #endif \ No newline at end of file From 8daa2da97ce94c18e96fbb8a3bfafd36ee8749ab Mon Sep 17 00:00:00 2001 From: Hylian <43305009+HylianMedia@users.noreply.github.com> Date: Fri, 9 Nov 2018 11:26:04 -0600 Subject: [PATCH 182/489] Update Changelog for 0.7.4 --- docs/changelog.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index 7aefb2474..3d38c0340 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,24 @@ # Changelog +## 0.7.4 ++ [libstratosphere](https://github.com/Atmosphere-NX/libstratosphere) has been completely refactored/rewritten, and split into its own, separate submodule. + + While this is mostly "under the hood" for end-users, the refactor is faster (improving both boot-time and runtime performance), more accurate (many of the internal IPC structures are now bug-for-bug compatible with Nintendo's implementations), and significantly more stable (it fixes a large number of bugs present in the old library). + + The refactored API is significantly cleaner and easier to write system module code for, which should improve/speed up development of stratosphere. + + Developers looking to write their own custom system modules for the Switch can now easily include libstratosphere as a submodule in their projects. ++ Loader was extended to add a new generic way to redirect content (ExternalContentSources), courtesy @misson20000: + + A new command was added to ldr:shel, taking in a tid to redirect and returning a session handle. + + When the requested TID is loading, Loader will query the handle as though it were an IFileSystem. + + This allows clients to generically define their own filesystems, and override content with them in loader. ++ fs.mitm has gotten several optimizations that should improve its performance and stability: + + RomFS redirection now only occurs when there is content to redirect, even if the title is being mitm'd elsewhere. + + A cache is now maintained of the active data storage, if any, for all opened title IDs. This means if two processes both try to open the same archive, fs.mitm won't duplicate any of its work. + + RomFS metadata is now cached to the SD card on build instead of being persisted in memory -- this greatly reduces memory footprint and allows fs.mitm to redirect more titles simultaneously than before. ++ A number of bugs were fixed, including: + + A resource leak was fixed in process creation. This fixes crashes that occur when a large number (>32) games have been launched since the last reboot. + + fs.mitm no longer errors when receiving a zero-sized buffer. This fixes crashes in some games, including The Messenger. + + Multi-threaded server semantics should no longer cause deadlocks in certain circumstances. This fixes crashes in some games, including NES Classics. + + PM now only gives full FS permissions to the active KIPs. This fixes a potential crash where new processes might be unable to be registered with FS. ++ The `make dist` target now includes the branch in the generated zip name. ++ General system stability improvements to enhance the user's experience. ## 0.7.3 + Loader and fs.mitm now try to reload loader.ini before reading it. This allows for changing the override button combination/HBL title id at runtime. + Added a MitM between set:sys and qlaunch, used to override the system version string displayed in system settings. From b9091e946635f7ae592e6a9ebe3708e2c8bdaf6b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 00:11:38 -0800 Subject: [PATCH 183/489] fatal: Implement fatal:p, fatal:u stub. --- Makefile | 2 + stratosphere/Makefile | 2 +- stratosphere/fatal/Makefile | 159 ++++++++++++++++++ stratosphere/fatal/fatal.json | 87 ++++++++++ .../fatal/source/fatal_event_manager.cpp | 45 +++++ .../fatal/source/fatal_event_manager.hpp | 32 ++++ stratosphere/fatal/source/fatal_main.cpp | 97 +++++++++++ stratosphere/fatal/source/fatal_private.cpp | 25 +++ stratosphere/fatal/source/fatal_private.hpp | 33 ++++ stratosphere/fatal/source/fatal_types.hpp | 97 +++++++++++ stratosphere/fatal/source/fatal_user.cpp | 43 +++++ stratosphere/fatal/source/fatal_user.hpp | 43 +++++ 12 files changed, 664 insertions(+), 1 deletion(-) create mode 100644 stratosphere/fatal/Makefile create mode 100644 stratosphere/fatal/fatal.json create mode 100644 stratosphere/fatal/source/fatal_event_manager.cpp create mode 100644 stratosphere/fatal/source/fatal_event_manager.hpp create mode 100644 stratosphere/fatal/source/fatal_main.cpp create mode 100644 stratosphere/fatal/source/fatal_private.cpp create mode 100644 stratosphere/fatal/source/fatal_private.hpp create mode 100644 stratosphere/fatal/source/fatal_types.hpp create mode 100644 stratosphere/fatal/source/fatal_user.cpp create mode 100644 stratosphere/fatal/source/fatal_user.hpp diff --git a/Makefile b/Makefile index 7eeab49b6..18410a3af 100644 --- a/Makefile +++ b/Makefile @@ -40,11 +40,13 @@ dist: all mkdir atmosphere-$(AMSVER) mkdir atmosphere-$(AMSVER)/atmosphere mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 + mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032 cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/fusee-secondary.bin cp common/defaults/BCT.ini atmosphere-$(AMSVER)/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp + cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034/exefs.nsp cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/boot2.flag cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; diff --git a/stratosphere/Makefile b/stratosphere/Makefile index 559327b9e..61e6a119c 100644 --- a/stratosphere/Makefile +++ b/stratosphere/Makefile @@ -1,4 +1,4 @@ -KIPS := loader pm sm boot fs_mitm set_mitm creport +KIPS := loader pm sm boot fs_mitm set_mitm creport fatal #TODO: boot2 ? diff --git a/stratosphere/fatal/Makefile b/stratosphere/fatal/Makefile new file mode 100644 index 000000000..c042e968d --- /dev/null +++ b/stratosphere/fatal/Makefile @@ -0,0 +1,159 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include ../../common/include +EXEFS_SRC := exefs_src + +DEFINES := -DDISABLE_IPC + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lstratosphere -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) $(CURDIR)/../libstratosphere + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) + +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).npdm $(TARGET).nso $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).nsp + +ifeq ($(strip $(APP_JSON)),) +$(OUTPUT).nsp : $(OUTPUT).nso +else +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm +endif + +$(OUTPUT).nso : $(OUTPUT).elf + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/stratosphere/fatal/fatal.json b/stratosphere/fatal/fatal.json new file mode 100644 index 000000000..2d4388785 --- /dev/null +++ b/stratosphere/fatal/fatal.json @@ -0,0 +1,87 @@ +{ + "name": "fatal", + "title_id": "0x0100000000000034", + "title_id_range_min": "0x0100000000000034", + "title_id_range_max": "0x0100000000000034", + "main_thread_stack_size": "0x00010000", + "main_thread_priority": 15, + "default_cpu_id": 3, + "process_category": 0, + "is_retail": true, + "pool_partition": 2, + "is_64_bit": true, + "address_space_type": 3, + "filesystem_access": { + "permissions": "0x0000000000100000" + }, + "service_access": ["bpc", "erpt:c", "fsp-srv", "gpio", "i2c", "lbl", "lm", "nvdrv:s", "pcv", "pl:u", "pm:info", "psm", "set", "set:sys", "spsm", "vi:m", "vi:s"], + "service_host": ["fatal:p", "fatal:u"], + "kernel_capabilities": [{ + "type": "kernel_flags", + "value": { + "highest_thread_priority": 63, + "lowest_thread_priority": 12, + "lowest_cpu_id": 0, + "highest_cpu_id": 3 + } + }, { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0a", + "svcSleepThread": "0x0b", + "svcGetThreadPriority": "0x0c", + "svcSetThreadPriority": "0x0d", + "svcGetThreadCoreMask": "0x0e", + "svcSetThreadCoreMask": "0x0f", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1a", + "svcArbitrateUnlock": "0x1b", + "svcWaitProcessWideKeyAtomic": "0x1c", + "svcSignalProcessWideKey": "0x1d", + "svcGetSystemTick": "0x1e", + "svcConnectToNamedPort": "0x1f", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcCreateEvent": "0x45" + } + }, { + "type": "min_kernel_version", + "value": "0x0060" + }, { + "type": "handle_table_size", + "value": 128 + }] +} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_event_manager.cpp b/stratosphere/fatal/source/fatal_event_manager.cpp new file mode 100644 index 000000000..faed8969b --- /dev/null +++ b/stratosphere/fatal/source/fatal_event_manager.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_event_manager.hpp" + +FatalEventManager::FatalEventManager() { + /* Just create all the events. */ + for (size_t i = 0; i < FatalEventManager::NumFatalEvents; i++) { + if (R_FAILED(eventCreate(&this->events[i], true))) { + std::abort(); + } + } +} + +Result FatalEventManager::GetEvent(Handle *out) { + std::scoped_lock<HosMutex> lk{this->lock}; + + /* Only allow GetEvent to succeed NumFatalEvents times. */ + if (this->events_gotten >= FatalEventManager::NumFatalEvents) { + return 0x8A3; + } + + *out = this->events[this->events_gotten++].revent; + return 0; +} + +void FatalEventManager::SignalEvents() { + for (size_t i = 0; i < FatalEventManager::NumFatalEvents; i++) { + eventFire(&this->events[i]); + } +} diff --git a/stratosphere/fatal/source/fatal_event_manager.hpp b/stratosphere/fatal/source/fatal_event_manager.hpp new file mode 100644 index 000000000..83e4e46dd --- /dev/null +++ b/stratosphere/fatal/source/fatal_event_manager.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +class FatalEventManager { + private: + static constexpr size_t NumFatalEvents = 3; + + HosMutex lock; + size_t events_gotten = 0; + Event events[3]; + public: + FatalEventManager(); + Result GetEvent(Handle *out); + void SignalEvents(); +}; diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp new file mode 100644 index 000000000..2573eb7ad --- /dev/null +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +#include "fatal_types.hpp" +#include "fatal_private.hpp" +#include "fatal_user.hpp" + +extern "C" { + extern u32 __start__; + + u32 __nx_applet_type = AppletType_None; + + #define INNER_HEAP_SIZE 0x20000 + size_t nx_inner_heap_size = INNER_HEAP_SIZE; + char nx_inner_heap[INNER_HEAP_SIZE]; + + void __libnx_initheap(void); + void __appInit(void); + void __appExit(void); +} + + +void __libnx_initheap(void) { + void* addr = nx_inner_heap; + size_t size = nx_inner_heap_size; + + /* Newlib */ + extern char* fake_heap_start; + extern char* fake_heap_end; + + fake_heap_start = (char*)addr; + fake_heap_end = (char*)addr + size; +} + +void __appInit(void) { + Result rc; + + rc = smInitialize(); + if (R_FAILED(rc)) { + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); + } + + rc = setsysInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); +} + +void __appExit(void) { + /* Cleanup services. */ + setsysExit(); + smExit(); +} + +int main(int argc, char **argv) +{ + consoleDebugInit(debugDevice_SVC); + + /* TODO: What's a good timeout value to use here? */ + auto server_manager = new WaitableManager(1); + + /* TODO: Create services. */ + server_manager->AddWaitable(new ServiceServer<PrivateService>("fatal:p", 4)); + server_manager->AddWaitable(new ServiceServer<UserService>("fatal:u", 4)); + + /* Loop forever, servicing our services. */ + server_manager->Process(); + + delete server_manager; + + return 0; +} + diff --git a/stratosphere/fatal/source/fatal_private.cpp b/stratosphere/fatal/source/fatal_private.cpp new file mode 100644 index 000000000..b1e57322a --- /dev/null +++ b/stratosphere/fatal/source/fatal_private.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_private.hpp" +#include "fatal_event_manager.hpp" + +static FatalEventManager g_EventManager; + +Result PrivateService::GetFatalEvent(Out<CopiedHandle> out_h) { + return g_EventManager.GetEvent(out_h.GetHandlePointer()); +} diff --git a/stratosphere/fatal/source/fatal_private.hpp b/stratosphere/fatal/source/fatal_private.hpp new file mode 100644 index 000000000..22e247eae --- /dev/null +++ b/stratosphere/fatal/source/fatal_private.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +enum PrivateCmd { + Private_Cmd_GetFatalEvent = 0, +}; + +class PrivateService final : public IServiceObject { + private: + /* Actual commands. */ + Result GetFatalEvent(Out<CopiedHandle> out_h); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<Private_Cmd_GetFatalEvent, &PrivateService::GetFatalEvent>(), + }; +}; diff --git a/stratosphere/fatal/source/fatal_types.hpp b/stratosphere/fatal/source/fatal_types.hpp new file mode 100644 index 000000000..3ca5b85fc --- /dev/null +++ b/stratosphere/fatal/source/fatal_types.hpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +enum FatalResult : Result { + FatalResult_TooManyEvents = 0x8A3, + FatalResult_InRepairWithoutVolHeld = 0xAA3, + FatalResult_InRepairWithoutTimeReviserCartridge = 0xCA3, +}; + +struct Aarch64CpuContext { + using RegisterType = u64; + static constexpr size_t MaxStackTraceDepth = 0x20; + + /* Registers, exception context. N left names for these fields in fatal .rodata. */ + union { + RegisterType x[31]; + struct { + RegisterType _x[29]; + RegisterType fp; + RegisterType lr; + RegisterType sp; + RegisterType pc; + }; + }; + RegisterType pstate; + RegisterType afsr0; + RegisterType afsr1; + RegisterType esr; + RegisterType far; + + /* Misc. */ + RegisterType stack_trace[MaxStackTraceDepth]; + RegisterType start_address; + RegisterType register_set_flags; + u32 stack_trace_size; +}; + +struct Aarch32CpuContext { + using RegisterType = u32; + static constexpr size_t MaxStackTraceDepth = 0x20; + + /* Registers, exception context. N left names for these fields in fatal .rodata. */ + union { + RegisterType r[16]; + struct { + RegisterType _x[11]; + RegisterType fp; + RegisterType ip; + RegisterType sp; + RegisterType lr; + RegisterType pc; + }; + }; + RegisterType pstate; + RegisterType afsr0; + RegisterType afsr1; + RegisterType esr; + RegisterType far; + + /* Misc. Yes, stack_trace_size is really laid out differently than aarch64... */ + RegisterType stack_trace[MaxStackTraceDepth]; + u32 stack_trace_size; + RegisterType start_address; + RegisterType register_set_flags; +}; + +struct FatalCpuContext { + union { + Aarch64CpuContext aarch64_ctx; + Aarch64CpuContext aarch32_ctx; + }; + + bool is_aarch32; + u32 type; +}; + +static_assert(sizeof(Aarch64CpuContext) == 0x248, "Aarch64CpuContext definition!"); +static_assert(sizeof(Aarch32CpuContext) == 0xE0, "Aarch32CpuContext definition!"); +static_assert(sizeof(FatalCpuContext) == 0x250, "FatalCpuContext definition!"); +static_assert(std::is_pod_v<FatalCpuContext>, "FatalCpuContext definition!"); diff --git a/stratosphere/fatal/source/fatal_user.cpp b/stratosphere/fatal/source/fatal_user.cpp new file mode 100644 index 000000000..b97e2bb25 --- /dev/null +++ b/stratosphere/fatal/source/fatal_user.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_user.hpp" + +Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *context) { + /* TODO */ + return 0; +} + + +Result UserService::ThrowFatal(u32 error, PidDescriptor pid_desc) { + FatalCpuContext ctx = {0}; + return ThrowFatalImpl(error, pid_desc.pid, FatalType_ErrorReportAndErrorScreen, &ctx); +} + +Result UserService::ThrowFatalWithPolicy(u32 error, PidDescriptor pid_desc, FatalType policy) { + FatalCpuContext ctx = {0}; + return ThrowFatalImpl(error, pid_desc.pid, policy, &ctx); +} + +Result UserService::ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<FatalCpuContext> _ctx) { + /* Require exactly one context passed in. */ + if (_ctx.num_elements != 1) { + return 0xF601; + } + + return ThrowFatalImpl(error, pid_desc.pid, policy, _ctx.buffer); +} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_user.hpp b/stratosphere/fatal/source/fatal_user.hpp new file mode 100644 index 000000000..48e4f9591 --- /dev/null +++ b/stratosphere/fatal/source/fatal_user.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "fatal_types.hpp" + +enum UserCmd { + User_Cmd_ThrowFatal = 0, + User_Cmd_ThrowFatalWithPolicy = 1, + User_Cmd_ThrowFatalWithCpuContext = 2, +}; + +class UserService final : public IServiceObject { + private: + Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *context); + + /* Actual commands. */ + Result ThrowFatal(u32 error, PidDescriptor pid_desc); + Result ThrowFatalWithPolicy(u32 error, PidDescriptor pid_desc, FatalType policy); + Result ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<FatalCpuContext> _ctx); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<User_Cmd_ThrowFatal, &UserService::ThrowFatal>(), + MakeServiceCommandMeta<User_Cmd_ThrowFatalWithPolicy, &UserService::ThrowFatalWithPolicy>(), + MakeServiceCommandMeta<User_Cmd_ThrowFatalWithCpuContext, &UserService::ThrowFatalWithCpuContext>(), + }; +}; From 21b0f228b6ba81fbce9a2a9302b3098e2e061864 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 00:54:12 -0800 Subject: [PATCH 184/489] fatal: Skeleton tasks, write ThrowFatalImpl. --- stratosphere/fatal/fatal.json | 2 +- .../fatal/source/fatal_event_manager.cpp | 9 ++- .../fatal/source/fatal_event_manager.hpp | 2 + stratosphere/fatal/source/fatal_main.cpp | 6 ++ stratosphere/fatal/source/fatal_private.cpp | 4 +- stratosphere/fatal/source/fatal_task.cpp | 55 ++++++++++++++++++ stratosphere/fatal/source/fatal_task.hpp | 31 ++++++++++ stratosphere/fatal/source/fatal_types.hpp | 6 ++ stratosphere/fatal/source/fatal_user.cpp | 56 ++++++++++++++++++- 9 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 stratosphere/fatal/source/fatal_task.cpp create mode 100644 stratosphere/fatal/source/fatal_task.hpp diff --git a/stratosphere/fatal/fatal.json b/stratosphere/fatal/fatal.json index 2d4388785..9dc17d9a9 100644 --- a/stratosphere/fatal/fatal.json +++ b/stratosphere/fatal/fatal.json @@ -4,7 +4,7 @@ "title_id_range_min": "0x0100000000000034", "title_id_range_max": "0x0100000000000034", "main_thread_stack_size": "0x00010000", - "main_thread_priority": 15, + "main_thread_priority": 37, "default_cpu_id": 3, "process_category": 0, "is_retail": true, diff --git a/stratosphere/fatal/source/fatal_event_manager.cpp b/stratosphere/fatal/source/fatal_event_manager.cpp index faed8969b..4414941ce 100644 --- a/stratosphere/fatal/source/fatal_event_manager.cpp +++ b/stratosphere/fatal/source/fatal_event_manager.cpp @@ -15,8 +15,15 @@ */ #include <switch.h> +#include "fatal_types.hpp" #include "fatal_event_manager.hpp" +static FatalEventManager g_event_manager; + +FatalEventManager *GetEventManager() { + return &g_event_manager; +} + FatalEventManager::FatalEventManager() { /* Just create all the events. */ for (size_t i = 0; i < FatalEventManager::NumFatalEvents; i++) { @@ -31,7 +38,7 @@ Result FatalEventManager::GetEvent(Handle *out) { /* Only allow GetEvent to succeed NumFatalEvents times. */ if (this->events_gotten >= FatalEventManager::NumFatalEvents) { - return 0x8A3; + return FatalResult_TooManyEvents; } *out = this->events[this->events_gotten++].revent; diff --git a/stratosphere/fatal/source/fatal_event_manager.hpp b/stratosphere/fatal/source/fatal_event_manager.hpp index 83e4e46dd..e96ab0f63 100644 --- a/stratosphere/fatal/source/fatal_event_manager.hpp +++ b/stratosphere/fatal/source/fatal_event_manager.hpp @@ -30,3 +30,5 @@ class FatalEventManager { Result GetEvent(Handle *out); void SignalEvents(); }; + +FatalEventManager *GetEventManager(); \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 2573eb7ad..72b006d31 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -67,11 +67,17 @@ void __appInit(void) { fatalSimple(rc); } + rc = pminfoInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { /* Cleanup services. */ + pminfoExit(); setsysExit(); smExit(); } diff --git a/stratosphere/fatal/source/fatal_private.cpp b/stratosphere/fatal/source/fatal_private.cpp index b1e57322a..afa384662 100644 --- a/stratosphere/fatal/source/fatal_private.cpp +++ b/stratosphere/fatal/source/fatal_private.cpp @@ -18,8 +18,6 @@ #include "fatal_private.hpp" #include "fatal_event_manager.hpp" -static FatalEventManager g_EventManager; - Result PrivateService::GetFatalEvent(Out<CopiedHandle> out_h) { - return g_EventManager.GetEvent(out_h.GetHandlePointer()); + return GetEventManager()->GetEvent(out_h.GetHandlePointer()); } diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp new file mode 100644 index 000000000..eb10add15 --- /dev/null +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_types.hpp" +#include "fatal_task.hpp" + +static constexpr size_t MaxTasks = 8; +static HosThread g_task_threads[MaxTasks]; +static size_t g_num_threads = 0; + + +static void RunTaskThreadFunc(void *arg) { + IFatalTask *task = reinterpret_cast<IFatalTask *>(arg); + + Result rc = task->Run(); + if (R_FAILED(rc)) { + /* TODO: Log task failure, somehow? */ + } +} + +static void RunTask(IFatalTask *task) { + if (g_num_threads >= MaxTasks) { + std::abort(); + } + + HosThread *cur_thread = &g_task_threads[g_num_threads++]; + + cur_thread->Initialize(&RunTaskThreadFunc, task, 0x4000, 15); + cur_thread->Start(); +} + +void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) { + /* TODO: RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event); */ + /* TODO: RunTask(new PowerControlTask(ctx, title_id, battery_event); */ + /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event); */ + /* TODO: RunTask(new StopSoundTask(); */ + /* TODO: RunTask(new BacklightControlTask(); */ + /* TODO: RunTask(new AdjustClockTask(); */ + /* TODO: RunTask(new PowerButtonTask(erpt_event); */ + /* TODO: RunTask(new StateTransitionStop(); */ +} diff --git a/stratosphere/fatal/source/fatal_task.hpp b/stratosphere/fatal/source/fatal_task.hpp new file mode 100644 index 000000000..63d1ca43e --- /dev/null +++ b/stratosphere/fatal/source/fatal_task.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include "fatal_types.hpp" + +class IFatalTask { + protected: + FatalContext *ctx; + u64 title_id; + public: + virtual Result Run() = 0; + virtual const char *GetName() const = 0; +}; + +void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event); diff --git a/stratosphere/fatal/source/fatal_types.hpp b/stratosphere/fatal/source/fatal_types.hpp index 3ca5b85fc..46fafeec4 100644 --- a/stratosphere/fatal/source/fatal_types.hpp +++ b/stratosphere/fatal/source/fatal_types.hpp @@ -19,6 +19,7 @@ #include <stratosphere.hpp> enum FatalResult : Result { + FatalResult_AlreadyThrown = 0x6A3, FatalResult_TooManyEvents = 0x8A3, FatalResult_InRepairWithoutVolHeld = 0xAA3, FatalResult_InRepairWithoutTimeReviserCartridge = 0xCA3, @@ -91,6 +92,11 @@ struct FatalCpuContext { u32 type; }; +struct FatalContext { + u32 error_code; + FatalCpuContext cpu_ctx; +}; + static_assert(sizeof(Aarch64CpuContext) == 0x248, "Aarch64CpuContext definition!"); static_assert(sizeof(Aarch32CpuContext) == 0xE0, "Aarch32CpuContext definition!"); static_assert(sizeof(FatalCpuContext) == 0x250, "FatalCpuContext definition!"); diff --git a/stratosphere/fatal/source/fatal_user.cpp b/stratosphere/fatal/source/fatal_user.cpp index b97e2bb25..f683de4cc 100644 --- a/stratosphere/fatal/source/fatal_user.cpp +++ b/stratosphere/fatal/source/fatal_user.cpp @@ -16,9 +16,61 @@ #include <switch.h> #include "fatal_user.hpp" +#include "fatal_event_manager.hpp" +#include "fatal_task.hpp" -Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *context) { - /* TODO */ +static bool g_thrown = false; + +static Result SetThrown() { + /* This should be fine, since fatal only has a single IPC thread. */ + if (g_thrown) { + return FatalResult_AlreadyThrown; + } + + g_thrown = true; + return 0; +} + +Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx) { + Result rc = 0; + FatalContext ctx; + ctx.error_code = error; + ctx.cpu_ctx = *cpu_ctx; + + /* Get title id. On failure, it'll be zero. */ + u64 title_id = 0; + pminfoGetTitleId(&title_id, pid); + + switch (policy) { + case FatalType_ErrorReport: + /* TODO: Don't write an error report. */ + case FatalType_ErrorReportAndErrorScreen: + case FatalType_ErrorScreen: + { + /* Ensure we only throw once. */ + if (R_FAILED((rc = SetThrown()))) { + return rc; + } + + /* Signal that fatal is about to happen. */ + GetEventManager()->SignalEvents(); + + /* Create events. */ + Event erpt_event; + Event battery_event; + if (R_FAILED(eventCreate(&erpt_event, true)) || R_FAILED(eventCreate(&battery_event, true))) { + std::abort(); + } + + /* Run tasks. */ + RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event); + } + break; + default: + /* N aborts here. Should we just return an error code? */ + std::abort(); + } + return 0; } From 4d1481e2eb269a8e66420371c16418f4c5355bac Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 01:04:40 -0800 Subject: [PATCH 185/489] fatal: Write ErrorReportTask --- stratosphere/fatal/source/fatal_main.cpp | 2 +- stratosphere/fatal/source/fatal_task.cpp | 19 ++++++----- stratosphere/fatal/source/fatal_task.hpp | 1 + .../fatal/source/fatal_task_error_report.cpp | 28 ++++++++++++++++ .../fatal/source/fatal_task_error_report.hpp | 32 +++++++++++++++++++ 5 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 stratosphere/fatal/source/fatal_task_error_report.cpp create mode 100644 stratosphere/fatal/source/fatal_task_error_report.hpp diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 72b006d31..ae8f0ce19 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -32,7 +32,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x20000 + #define INNER_HEAP_SIZE 0x380000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index eb10add15..a01ac6244 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -18,6 +18,9 @@ #include "fatal_types.hpp" #include "fatal_task.hpp" +#include "fatal_task_error_report.hpp" + + static constexpr size_t MaxTasks = 8; static HosThread g_task_threads[MaxTasks]; static size_t g_num_threads = 0; @@ -44,12 +47,12 @@ static void RunTask(IFatalTask *task) { } void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) { - /* TODO: RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event); */ - /* TODO: RunTask(new PowerControlTask(ctx, title_id, battery_event); */ - /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event); */ - /* TODO: RunTask(new StopSoundTask(); */ - /* TODO: RunTask(new BacklightControlTask(); */ - /* TODO: RunTask(new AdjustClockTask(); */ - /* TODO: RunTask(new PowerButtonTask(erpt_event); */ - /* TODO: RunTask(new StateTransitionStop(); */ + RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event)); + /* TODO: RunTask(new PowerControlTask(ctx, title_id, battery_event)); */ + /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event)); */ + /* TODO: RunTask(new StopSoundTask()); */ + /* TODO: RunTask(new BacklightControlTask()); */ + /* TODO: RunTask(new AdjustClockTask()); */ + /* TODO: RunTask(new PowerButtonTask(erpt_event)); */ + /* TODO: RunTask(new StateTransitionStop()); */ } diff --git a/stratosphere/fatal/source/fatal_task.hpp b/stratosphere/fatal/source/fatal_task.hpp index 63d1ca43e..ef19fbbc1 100644 --- a/stratosphere/fatal/source/fatal_task.hpp +++ b/stratosphere/fatal/source/fatal_task.hpp @@ -24,6 +24,7 @@ class IFatalTask { FatalContext *ctx; u64 title_id; public: + IFatalTask(FatalContext *ctx, u64 tid) : ctx(ctx), title_id(tid) { } virtual Result Run() = 0; virtual const char *GetName() const = 0; }; diff --git a/stratosphere/fatal/source/fatal_task_error_report.cpp b/stratosphere/fatal/source/fatal_task_error_report.cpp new file mode 100644 index 000000000..72decd371 --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_error_report.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_task_error_report.hpp" + +Result ErrorReportTask::Run() { + if (this->create_report) { + /* Here, Nintendo creates an error report with erpt. AMS will not do that. */ + /* TODO: Should atmosphere log reports to to the SD card? */ + } + + /* Signal we're done with our job. */ + eventFire(this->erpt_event); +} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_error_report.hpp b/stratosphere/fatal/source/fatal_task_error_report.hpp new file mode 100644 index 000000000..7ade00bcf --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_error_report.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include "fatal_task.hpp" + +class ErrorReportTask : public IFatalTask { + private: + bool create_report; + Event *erpt_event; + public: + ErrorReportTask(FatalContext *ctx, u64 title_id, bool error_report, Event *evt) : IFatalTask(ctx, title_id), create_report(error_report), erpt_event(evt) { } + virtual Result Run() override; + virtual const char *GetName() const override { + return "WriteErrorReport"; + } +}; \ No newline at end of file From b771c42f7ffea0c2d0217c7c360f979a96adab0d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 01:19:52 -0800 Subject: [PATCH 186/489] fatal: Implement StateTransitionStopTask --- stratosphere/fatal/source/fatal_main.cpp | 14 ++++++--- stratosphere/fatal/source/fatal_task.cpp | 11 +++---- .../fatal/source/fatal_task_power.cpp | 24 +++++++++++++++ .../fatal/source/fatal_task_power.hpp | 29 +++++++++++++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 stratosphere/fatal/source/fatal_task_power.cpp create mode 100644 stratosphere/fatal/source/fatal_task_power.hpp diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index ae8f0ce19..211c22374 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -59,24 +59,30 @@ void __appInit(void) { rc = smInitialize(); if (R_FAILED(rc)) { - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); + std::abort(); } rc = setsysInitialize(); if (R_FAILED(rc)) { - fatalSimple(rc); + std::abort(); } rc = pminfoInitialize(); if (R_FAILED(rc)) { - fatalSimple(rc); + std::abort(); } - CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); + rc = spsmInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + + /* fatal cannot throw fatal, so don't do: CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); */ } void __appExit(void) { /* Cleanup services. */ + spsmExit(); pminfoExit(); setsysExit(); smExit(); diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index a01ac6244..9725d02f8 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -19,6 +19,7 @@ #include "fatal_task.hpp" #include "fatal_task_error_report.hpp" +#include "fatal_task_power.hpp" static constexpr size_t MaxTasks = 8; @@ -50,9 +51,9 @@ void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *er RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event)); /* TODO: RunTask(new PowerControlTask(ctx, title_id, battery_event)); */ /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event)); */ - /* TODO: RunTask(new StopSoundTask()); */ - /* TODO: RunTask(new BacklightControlTask()); */ - /* TODO: RunTask(new AdjustClockTask()); */ - /* TODO: RunTask(new PowerButtonTask(erpt_event)); */ - /* TODO: RunTask(new StateTransitionStop()); */ + /* TODO: RunTask(new StopSoundTask(ctx, title_id)); */ + /* TODO: RunTask(new BacklightControlTask(ctx, title_id)); */ + /* TODO: RunTask(new AdjustClockTask(ctx, title_id)); */ + /* TODO: RunTask(new PowerButtonTask(ctx, title_id, erpt_event)); */ + RunTask(new StateTransitionStopTask(ctx, title_id)); } diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp new file mode 100644 index 000000000..59ffb062b --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_task_power.hpp" + +Result StateTransitionStopTask::Run() { + /* Nintendo ignores the output of this call... */ + spsmPutErrorState(); + return 0; +} diff --git a/stratosphere/fatal/source/fatal_task_power.hpp b/stratosphere/fatal/source/fatal_task_power.hpp new file mode 100644 index 000000000..e97f71978 --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_power.hpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include "fatal_task.hpp" + +class StateTransitionStopTask : public IFatalTask { + public: + StateTransitionStopTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } + virtual Result Run() override; + virtual const char *GetName() const override { + return "StateTransitionStopTask"; + } +}; \ No newline at end of file From 13e5043d6406da4e53a88350636819116af72cb4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 01:41:47 -0800 Subject: [PATCH 187/489] fatal: Implement PowerButtonObserveTask --- stratosphere/fatal/source/fatal_task.cpp | 4 +-- .../fatal/source/fatal_task_power.cpp | 24 ++++++++++++++++++ .../fatal/source/fatal_task_power.hpp | 25 +++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 9725d02f8..381d3c176 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -49,11 +49,11 @@ static void RunTask(IFatalTask *task) { void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) { RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event)); - /* TODO: RunTask(new PowerControlTask(ctx, title_id, battery_event)); */ + /* TODO: RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event)); */ /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event)); */ /* TODO: RunTask(new StopSoundTask(ctx, title_id)); */ /* TODO: RunTask(new BacklightControlTask(ctx, title_id)); */ /* TODO: RunTask(new AdjustClockTask(ctx, title_id)); */ - /* TODO: RunTask(new PowerButtonTask(ctx, title_id, erpt_event)); */ + RunTask(new PowerButtonObserveTask(ctx, title_id, erpt_event)); RunTask(new StateTransitionStopTask(ctx, title_id)); } diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index 59ffb062b..410fc158a 100644 --- a/stratosphere/fatal/source/fatal_task_power.cpp +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -17,6 +17,30 @@ #include <switch.h> #include "fatal_task_power.hpp" +void PowerButtonObserveTask::WaitForPowerButton() { + /* Wait up to a second for error report generation to finish. */ + eventWait(this->erpt_event, TimeoutHelper::NsToTick(1000000000UL)); + + /* TODO: Force a reboot after some time if kiosk unit. */ + + BpcSleepButtonState state; + while (true) { + Result rc = bpcGetSleepButtonState(&state); + if (R_SUCCEEDED(rc) && state == BpcSleepButtonState_Held) { + bpcRebootSystem(); + return; + } + + /* Wait 100 ms between button checks. */ + svcSleepThread(TimeoutHelper::NsToTick(100000000UL)); + } +} + +Result PowerButtonObserveTask::Run() { + WaitForPowerButton(); + return 0; +} + Result StateTransitionStopTask::Run() { /* Nintendo ignores the output of this call... */ spsmPutErrorState(); diff --git a/stratosphere/fatal/source/fatal_task_power.hpp b/stratosphere/fatal/source/fatal_task_power.hpp index e97f71978..bdd5b7155 100644 --- a/stratosphere/fatal/source/fatal_task_power.hpp +++ b/stratosphere/fatal/source/fatal_task_power.hpp @@ -19,6 +19,31 @@ #include <stratosphere.hpp> #include "fatal_task.hpp" +class PowerControlTask : public IFatalTask { + private: + Event *erpt_event; + Event *battery_event; + public: + PowerControlTask(FatalContext *ctx, u64 title_id, Event *er_evt, Event *bt_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt), battery_event(bt_evt) { } + virtual Result Run() override; + virtual const char *GetName() const override { + return "PowerControlTask"; + } +}; + +class PowerButtonObserveTask : public IFatalTask { + private: + Event *erpt_event; + private: + void WaitForPowerButton(); + public: + PowerButtonObserveTask(FatalContext *ctx, u64 title_id, Event *er_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt) { } + virtual Result Run() override; + virtual const char *GetName() const override { + return "PowerButtonObserveTask"; + } +}; + class StateTransitionStopTask : public IFatalTask { public: StateTransitionStopTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } From 6f240b16656c855f8566a2ee2f14199452e85840 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 01:47:02 -0800 Subject: [PATCH 188/489] fatal: Add missing bpcInitialize() call. --- stratosphere/fatal/source/fatal_main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 211c22374..e9fb47c44 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -72,6 +72,11 @@ void __appInit(void) { std::abort(); } + rc = bpcInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + rc = spsmInitialize(); if (R_FAILED(rc)) { std::abort(); @@ -83,6 +88,7 @@ void __appInit(void) { void __appExit(void) { /* Cleanup services. */ spsmExit(); + bpcExit(); pminfoExit(); setsysExit(); smExit(); From 1228cd6903e5d5f5572fd431f18b12d0ada145f6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 02:21:29 -0800 Subject: [PATCH 189/489] fatal: misc cleanup, verified to reboot on hardware --- stratosphere/fatal/fatal.json | 5 +++-- stratosphere/fatal/source/fatal_event_manager.hpp | 2 +- stratosphere/fatal/source/fatal_task.cpp | 3 +++ .../fatal/source/fatal_task_error_report.cpp | 2 ++ stratosphere/fatal/source/fatal_user.cpp | 14 +++++++------- stratosphere/fatal/source/fatal_user.hpp | 2 +- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/stratosphere/fatal/fatal.json b/stratosphere/fatal/fatal.json index 9dc17d9a9..380b2b85f 100644 --- a/stratosphere/fatal/fatal.json +++ b/stratosphere/fatal/fatal.json @@ -14,7 +14,7 @@ "filesystem_access": { "permissions": "0x0000000000100000" }, - "service_access": ["bpc", "erpt:c", "fsp-srv", "gpio", "i2c", "lbl", "lm", "nvdrv:s", "pcv", "pl:u", "pm:info", "psm", "set", "set:sys", "spsm", "vi:m", "vi:s"], + "service_access": ["bpc", "bpc:c", "erpt:c", "fsp-srv", "gpio", "i2c", "lbl", "lm", "nvdrv:s", "pcv", "pl:u", "pm:info", "psm", "set", "set:sys", "spsm", "vi:m", "vi:s"], "service_host": ["fatal:p", "fatal:u"], "kernel_capabilities": [{ "type": "kernel_flags", @@ -75,7 +75,8 @@ "svcReplyAndReceiveLight": "0x42", "svcReplyAndReceive": "0x43", "svcReplyAndReceiveWithUserBuffer": "0x44", - "svcCreateEvent": "0x45" + "svcCreateEvent": "0x45", + "svcReadWriteRegister": "0x4E" } }, { "type": "min_kernel_version", diff --git a/stratosphere/fatal/source/fatal_event_manager.hpp b/stratosphere/fatal/source/fatal_event_manager.hpp index e96ab0f63..6b0bd5f69 100644 --- a/stratosphere/fatal/source/fatal_event_manager.hpp +++ b/stratosphere/fatal/source/fatal_event_manager.hpp @@ -24,7 +24,7 @@ class FatalEventManager { HosMutex lock; size_t events_gotten = 0; - Event events[3]; + Event events[NumFatalEvents]; public: FatalEventManager(); Result GetEvent(Handle *out); diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 381d3c176..407b78e8c 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -34,6 +34,9 @@ static void RunTaskThreadFunc(void *arg) { if (R_FAILED(rc)) { /* TODO: Log task failure, somehow? */ } + + /* Finish. */ + svcExitThread(); } static void RunTask(IFatalTask *task) { diff --git a/stratosphere/fatal/source/fatal_task_error_report.cpp b/stratosphere/fatal/source/fatal_task_error_report.cpp index 72decd371..111c4ce38 100644 --- a/stratosphere/fatal/source/fatal_task_error_report.cpp +++ b/stratosphere/fatal/source/fatal_task_error_report.cpp @@ -25,4 +25,6 @@ Result ErrorReportTask::Run() { /* Signal we're done with our job. */ eventFire(this->erpt_event); + + return 0; } \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_user.cpp b/stratosphere/fatal/source/fatal_user.cpp index f683de4cc..b21aefc29 100644 --- a/stratosphere/fatal/source/fatal_user.cpp +++ b/stratosphere/fatal/source/fatal_user.cpp @@ -58,7 +58,7 @@ Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCp /* Create events. */ Event erpt_event; Event battery_event; - if (R_FAILED(eventCreate(&erpt_event, true)) || R_FAILED(eventCreate(&battery_event, true))) { + if (R_FAILED(eventCreate(&erpt_event, false)) || R_FAILED(eventCreate(&battery_event, false))) { std::abort(); } @@ -85,11 +85,11 @@ Result UserService::ThrowFatalWithPolicy(u32 error, PidDescriptor pid_desc, Fata return ThrowFatalImpl(error, pid_desc.pid, policy, &ctx); } -Result UserService::ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<FatalCpuContext> _ctx) { - /* Require exactly one context passed in. */ - if (_ctx.num_elements != 1) { - return 0xF601; +Result UserService::ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<u8> _ctx) { + if (_ctx.num_elements < sizeof(FatalCpuContext)) { + FatalCpuContext ctx = {0}; + return ThrowFatalImpl(error, pid_desc.pid, policy, &ctx); + } else { + return ThrowFatalImpl(error, pid_desc.pid, policy, reinterpret_cast<FatalCpuContext *>(_ctx.buffer)); } - - return ThrowFatalImpl(error, pid_desc.pid, policy, _ctx.buffer); } \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_user.hpp b/stratosphere/fatal/source/fatal_user.hpp index 48e4f9591..ab46a4a9e 100644 --- a/stratosphere/fatal/source/fatal_user.hpp +++ b/stratosphere/fatal/source/fatal_user.hpp @@ -33,7 +33,7 @@ class UserService final : public IServiceObject { /* Actual commands. */ Result ThrowFatal(u32 error, PidDescriptor pid_desc); Result ThrowFatalWithPolicy(u32 error, PidDescriptor pid_desc, FatalType policy); - Result ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<FatalCpuContext> _ctx); + Result ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<u8> _ctx); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<User_Cmd_ThrowFatal, &UserService::ThrowFatal>(), From aa86d1abfa7144fee538f3ffae638ad1004182ee Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 02:42:07 -0800 Subject: [PATCH 190/489] fatal: Implement PowerControlTask --- stratosphere/fatal/source/fatal_main.cpp | 6 ++ stratosphere/fatal/source/fatal_task.cpp | 2 +- .../fatal/source/fatal_task_power.cpp | 75 +++++++++++++++++++ .../fatal/source/fatal_task_power.hpp | 3 + 4 files changed, 85 insertions(+), 1 deletion(-) diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index e9fb47c44..e01cbd7e8 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -77,6 +77,11 @@ void __appInit(void) { std::abort(); } + rc = psmInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + rc = spsmInitialize(); if (R_FAILED(rc)) { std::abort(); @@ -88,6 +93,7 @@ void __appInit(void) { void __appExit(void) { /* Cleanup services. */ spsmExit(); + psmExit(); bpcExit(); pminfoExit(); setsysExit(); diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 407b78e8c..43108e88b 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -52,7 +52,7 @@ static void RunTask(IFatalTask *task) { void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) { RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event)); - /* TODO: RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event)); */ + RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event)); /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event)); */ /* TODO: RunTask(new StopSoundTask(ctx, title_id)); */ /* TODO: RunTask(new BacklightControlTask(ctx, title_id)); */ diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index 410fc158a..2ebd2489e 100644 --- a/stratosphere/fatal/source/fatal_task_power.cpp +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -17,6 +17,76 @@ #include <switch.h> #include "fatal_task_power.hpp" +bool PowerControlTask::TryShutdown() { + /* Set a timeout of 30 seconds. */ + TimeoutHelper timeout_helper(30000000000UL); + bool cancel_shutdown = false; + PsmBatteryVoltageState bv_state = PsmBatteryVoltageState_Normal; + + while (true) { + if (timeout_helper.TimedOut()) { + break; + } + + if (R_FAILED(psmGetBatteryVoltageState(&bv_state)) || bv_state == PsmBatteryVoltageState_NeedsShutdown) { + break; + } + + if (bv_state == PsmBatteryVoltageState_Normal) { + cancel_shutdown = true; + break; + } + + /* Query voltage state every 5 seconds, for 30 seconds. */ + svcSleepThread(5000000000UL); + } + + if (!cancel_shutdown) { + bpcShutdownSystem(); + return true; + } else { + return false; + } +} + +void PowerControlTask::MonitorBatteryState() { + PsmBatteryVoltageState bv_state = PsmBatteryVoltageState_Normal; + + /* Check the battery state, and shutdown on low voltage. */ + if (R_FAILED(psmGetBatteryVoltageState(&bv_state)) || bv_state == PsmBatteryVoltageState_NeedsShutdown) { + /* Wait a second for the error report task to finish. */ + eventWait(this->erpt_event, TimeoutHelper::NsToTick(1000000000UL)); + this->TryShutdown(); + return; + } + + /* Signal we've checked the battery at least once. */ + eventFire(this->battery_event); + + while (true) { + if (R_FAILED(psmGetBatteryVoltageState(&bv_state))) { + bv_state = PsmBatteryVoltageState_NeedsShutdown; + } + + switch (bv_state) { + case PsmBatteryVoltageState_NeedsShutdown: + case PsmBatteryVoltageState_NeedsSleep: + { + bool shutdown = this->TryShutdown(); + if (shutdown) { + return; + } + } + break; + default: + break; + } + + /* Query voltage state every 5 seconds. */ + svcSleepThread(5000000000UL); + } +} + void PowerButtonObserveTask::WaitForPowerButton() { /* Wait up to a second for error report generation to finish. */ eventWait(this->erpt_event, TimeoutHelper::NsToTick(1000000000UL)); @@ -36,6 +106,11 @@ void PowerButtonObserveTask::WaitForPowerButton() { } } +Result PowerControlTask::Run() { + MonitorBatteryState(); + return 0; +} + Result PowerButtonObserveTask::Run() { WaitForPowerButton(); return 0; diff --git a/stratosphere/fatal/source/fatal_task_power.hpp b/stratosphere/fatal/source/fatal_task_power.hpp index bdd5b7155..d31e78752 100644 --- a/stratosphere/fatal/source/fatal_task_power.hpp +++ b/stratosphere/fatal/source/fatal_task_power.hpp @@ -23,6 +23,9 @@ class PowerControlTask : public IFatalTask { private: Event *erpt_event; Event *battery_event; + private: + bool TryShutdown(); + void MonitorBatteryState(); public: PowerControlTask(FatalContext *ctx, u64 title_id, Event *er_evt, Event *bt_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt), battery_event(bt_evt) { } virtual Result Run() override; From e96eaa3d7cfe9f2ac056be3ccad2a5e1e22ad9ae Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 03:05:14 -0800 Subject: [PATCH 191/489] fatal: Implement AdjustClockTask --- stratosphere/fatal/source/fatal_main.cpp | 6 +++ stratosphere/fatal/source/fatal_task.cpp | 3 +- .../fatal/source/fatal_task_clock.cpp | 45 +++++++++++++++++++ .../fatal/source/fatal_task_clock.hpp | 31 +++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 stratosphere/fatal/source/fatal_task_clock.cpp create mode 100644 stratosphere/fatal/source/fatal_task_clock.hpp diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index e01cbd7e8..d537eff42 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -77,6 +77,11 @@ void __appInit(void) { std::abort(); } + rc = pcvInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + rc = psmInitialize(); if (R_FAILED(rc)) { std::abort(); @@ -94,6 +99,7 @@ void __appExit(void) { /* Cleanup services. */ spsmExit(); psmExit(); + pcvExit(); bpcExit(); pminfoExit(); setsysExit(); diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 43108e88b..1c474fa0f 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -19,6 +19,7 @@ #include "fatal_task.hpp" #include "fatal_task_error_report.hpp" +#include "fatal_task_clock.hpp" #include "fatal_task_power.hpp" @@ -56,7 +57,7 @@ void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *er /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event)); */ /* TODO: RunTask(new StopSoundTask(ctx, title_id)); */ /* TODO: RunTask(new BacklightControlTask(ctx, title_id)); */ - /* TODO: RunTask(new AdjustClockTask(ctx, title_id)); */ + RunTask(new AdjustClockTask(ctx, title_id)); RunTask(new PowerButtonObserveTask(ctx, title_id, erpt_event)); RunTask(new StateTransitionStopTask(ctx, title_id)); } diff --git a/stratosphere/fatal/source/fatal_task_clock.cpp b/stratosphere/fatal/source/fatal_task_clock.cpp new file mode 100644 index 000000000..fe1bf93d7 --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_clock.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_task_clock.hpp" + + +Result AdjustClockTask::AdjustClock() { + /* Fatal sets the CPU to 1020MHz, the GPU to 307 MHz, and the EMC to 1331MHz. */ + constexpr u32 CPU_CLOCK_1020MHZ = 0x3CCBF700L; + constexpr u32 GPU_CLOCK_307MHZ = 0x124F8000L; + constexpr u32 EMC_CLOCK_1331MHZ = 0x4F588000L; + Result rc = 0; + + if (R_FAILED((rc = pcvSetClockRate(PcvModule_Cpu, CPU_CLOCK_1020MHZ)))) { + return rc; + } + + if (R_FAILED((rc = pcvSetClockRate(PcvModule_Gpu, GPU_CLOCK_307MHZ)))) { + return rc; + } + + if (R_FAILED((rc = pcvSetClockRate(PcvModule_Emc, EMC_CLOCK_1331MHZ)))) { + return rc; + } + + return rc; +} + +Result AdjustClockTask::Run() { + return AdjustClock(); +} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_clock.hpp b/stratosphere/fatal/source/fatal_task_clock.hpp new file mode 100644 index 000000000..8ceba6945 --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_clock.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include "fatal_task.hpp" + +class AdjustClockTask : public IFatalTask { + private: + Result AdjustClock(); + public: + AdjustClockTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } + virtual Result Run() override; + virtual const char *GetName() const override { + return "AdjustClockTask"; + } +}; \ No newline at end of file From 5649b6d63f5373bf27825386d5553a913413ba8c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 03:16:13 -0800 Subject: [PATCH 192/489] fatal: Implement BacklightControlTask --- stratosphere/fatal/source/fatal_main.cpp | 6 ++++ stratosphere/fatal/source/fatal_task.cpp | 3 +- .../fatal/source/fatal_task_screen.cpp | 28 +++++++++++++++++ .../fatal/source/fatal_task_screen.hpp | 31 +++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 stratosphere/fatal/source/fatal_task_screen.cpp create mode 100644 stratosphere/fatal/source/fatal_task_screen.hpp diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index d537eff42..e5f1065ce 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -82,6 +82,11 @@ void __appInit(void) { std::abort(); } + rc = lblInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + rc = psmInitialize(); if (R_FAILED(rc)) { std::abort(); @@ -99,6 +104,7 @@ void __appExit(void) { /* Cleanup services. */ spsmExit(); psmExit(); + lblExit(); pcvExit(); bpcExit(); pminfoExit(); diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 1c474fa0f..51beefd7e 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -19,6 +19,7 @@ #include "fatal_task.hpp" #include "fatal_task_error_report.hpp" +#include "fatal_task_screen.hpp" #include "fatal_task_clock.hpp" #include "fatal_task_power.hpp" @@ -56,7 +57,7 @@ void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *er RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event)); /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event)); */ /* TODO: RunTask(new StopSoundTask(ctx, title_id)); */ - /* TODO: RunTask(new BacklightControlTask(ctx, title_id)); */ + RunTask(new BacklightControlTask(ctx, title_id)); RunTask(new AdjustClockTask(ctx, title_id)); RunTask(new PowerButtonObserveTask(ctx, title_id, erpt_event)); RunTask(new StateTransitionStopTask(ctx, title_id)); diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp new file mode 100644 index 000000000..98e42859e --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_task_screen.hpp" + + +void BacklightControlTask::TurnOnBacklight() { + lblSwitchBacklightOn(0); +} + +Result BacklightControlTask::Run() { + TurnOnBacklight(); + return 0; +} diff --git a/stratosphere/fatal/source/fatal_task_screen.hpp b/stratosphere/fatal/source/fatal_task_screen.hpp new file mode 100644 index 000000000..3ea9151ee --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_screen.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include "fatal_task.hpp" + +class BacklightControlTask : public IFatalTask { + private: + void TurnOnBacklight(); + public: + BacklightControlTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } + virtual Result Run() override; + virtual const char *GetName() const override { + return "BacklightControlTask"; + } +}; \ No newline at end of file From 6335d21901a7cad7d11b545fe7398855af449174 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 03:22:21 -0800 Subject: [PATCH 193/489] fatal: SleepThread takes ns, not ticks --- stratosphere/fatal/source/fatal_task_power.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index 2ebd2489e..88e934f53 100644 --- a/stratosphere/fatal/source/fatal_task_power.cpp +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -102,7 +102,7 @@ void PowerButtonObserveTask::WaitForPowerButton() { } /* Wait 100 ms between button checks. */ - svcSleepThread(TimeoutHelper::NsToTick(100000000UL)); + svcSleepThread(100000000UL); } } From f8abd2b402ae4bebf6fea42490fe9c0b7934d771 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 03:51:19 -0800 Subject: [PATCH 194/489] fatal: Implement the first half of StopSoundTask --- stratosphere/fatal/source/fatal_main.cpp | 6 ++ stratosphere/fatal/source/fatal_task.cpp | 3 +- .../fatal/source/fatal_task_sound.cpp | 58 +++++++++++++++++++ .../fatal/source/fatal_task_sound.hpp | 31 ++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 stratosphere/fatal/source/fatal_task_sound.cpp create mode 100644 stratosphere/fatal/source/fatal_task_sound.hpp diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index e5f1065ce..9ed72b2e6 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -72,6 +72,11 @@ void __appInit(void) { std::abort(); } + rc = i2cInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + rc = bpcInitialize(); if (R_FAILED(rc)) { std::abort(); @@ -107,6 +112,7 @@ void __appExit(void) { lblExit(); pcvExit(); bpcExit(); + i2cExit(); pminfoExit(); setsysExit(); smExit(); diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 51beefd7e..53c3c2853 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -20,6 +20,7 @@ #include "fatal_task_error_report.hpp" #include "fatal_task_screen.hpp" +#include "fatal_task_sound.hpp" #include "fatal_task_clock.hpp" #include "fatal_task_power.hpp" @@ -56,7 +57,7 @@ void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *er RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event)); RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event)); /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event)); */ - /* TODO: RunTask(new StopSoundTask(ctx, title_id)); */ + RunTask(new StopSoundTask(ctx, title_id)); RunTask(new BacklightControlTask(ctx, title_id)); RunTask(new AdjustClockTask(ctx, title_id)); RunTask(new PowerButtonObserveTask(ctx, title_id, erpt_event)); diff --git a/stratosphere/fatal/source/fatal_task_sound.cpp b/stratosphere/fatal/source/fatal_task_sound.cpp new file mode 100644 index 000000000..9a08f331e --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_sound.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_task_sound.hpp" + + +void StopSoundTask::StopSound() { + /* Talk to the ALC5639 over I2C, and disable audio output. */ + I2cSession audio; + if (R_SUCCEEDED(i2cOpenSession(&audio, I2cDevice_AudioCodec))) { + struct { + u16 dev; + u8 val; + } __attribute__((packed)) cmd; + static_assert(sizeof(cmd) == 3, "I2C command definition!"); + + cmd.dev = 0xC801; + cmd.val = 200; + i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); + + cmd.dev = 0xC802; + cmd.val = 200; + i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); + + cmd.dev = 0xC802; + cmd.val = 200; + i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); + + for (u16 dev = 97; dev <= 102; dev++) { + cmd.dev = dev; + cmd.val = 0; + i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); + } + + i2csessionClose(&audio); + } + + /* TODO: Talk to the ALC5639 over GPIO */ +} + +Result StopSoundTask::Run() { + StopSound(); + return 0; +} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_sound.hpp b/stratosphere/fatal/source/fatal_task_sound.hpp new file mode 100644 index 000000000..bbce20d4c --- /dev/null +++ b/stratosphere/fatal/source/fatal_task_sound.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include "fatal_task.hpp" + +class StopSoundTask : public IFatalTask { + private: + void StopSound(); + public: + StopSoundTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } + virtual Result Run() override; + virtual const char *GetName() const override { + return "SoundTask"; + } +}; \ No newline at end of file From 5d5f8ad3d5749c8f4b07e016439da1b60b1c4de1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 04:07:26 -0800 Subject: [PATCH 195/489] fatal: Finish StopSoundTask --- .../fatal/source/fatal_task_sound.cpp | 67 ++++++++++++------- .../fatal/source/fatal_task_sound.hpp | 2 +- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/stratosphere/fatal/source/fatal_task_sound.cpp b/stratosphere/fatal/source/fatal_task_sound.cpp index 9a08f331e..2588b0ade 100644 --- a/stratosphere/fatal/source/fatal_task_sound.cpp +++ b/stratosphere/fatal/source/fatal_task_sound.cpp @@ -20,39 +20,54 @@ void StopSoundTask::StopSound() { /* Talk to the ALC5639 over I2C, and disable audio output. */ - I2cSession audio; - if (R_SUCCEEDED(i2cOpenSession(&audio, I2cDevice_AudioCodec))) { - struct { - u16 dev; - u8 val; - } __attribute__((packed)) cmd; - static_assert(sizeof(cmd) == 3, "I2C command definition!"); + { + I2cSession audio; + if (R_SUCCEEDED(i2cOpenSession(&audio, I2cDevice_AudioCodec))) { + struct { + u16 dev; + u8 val; + } __attribute__((packed)) cmd; + static_assert(sizeof(cmd) == 3, "I2C command definition!"); - cmd.dev = 0xC801; - cmd.val = 200; - i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); - - cmd.dev = 0xC802; - cmd.val = 200; - i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); - - cmd.dev = 0xC802; - cmd.val = 200; - i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); - - for (u16 dev = 97; dev <= 102; dev++) { - cmd.dev = dev; - cmd.val = 0; + cmd.dev = 0xC801; + cmd.val = 200; i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); + + cmd.dev = 0xC802; + cmd.val = 200; + i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); + + cmd.dev = 0xC802; + cmd.val = 200; + i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); + + for (u16 dev = 97; dev <= 102; dev++) { + cmd.dev = dev; + cmd.val = 0; + i2csessionSendAuto(&audio, &cmd, sizeof(cmd), I2cTransactionOption_All); + } + + i2csessionClose(&audio); } - - i2csessionClose(&audio); } - /* TODO: Talk to the ALC5639 over GPIO */ + /* Talk to the ALC5639 over GPIO, and disable audio output */ + { + GpioPadSession audio; + if (R_SUCCEEDED(gpioOpenSession(&audio, GpioPadName_AudioCodec))) { + /* Set direction output, sleep 200 ms so it can take effect. */ + gpioPadSetDirection(&audio, GpioDirection_Output); + svcSleepThread(200000000UL); + + /* Pull audio codec low. */ + gpioPadSetValue(&audio, GpioValue_Low); + + gpioPadClose(&audio); + } + } } Result StopSoundTask::Run() { StopSound(); return 0; -} \ No newline at end of file +} diff --git a/stratosphere/fatal/source/fatal_task_sound.hpp b/stratosphere/fatal/source/fatal_task_sound.hpp index bbce20d4c..a6feea049 100644 --- a/stratosphere/fatal/source/fatal_task_sound.hpp +++ b/stratosphere/fatal/source/fatal_task_sound.hpp @@ -28,4 +28,4 @@ class StopSoundTask : public IFatalTask { virtual const char *GetName() const override { return "SoundTask"; } -}; \ No newline at end of file +}; From 5f3187300dd440079a612ebf08be8c519af3fe8c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 11:59:55 -0800 Subject: [PATCH 196/489] fatal: Skeleton ScreenDrawing code --- stratosphere/fatal/source/fatal_main.cpp | 17 ++++++++++++----- stratosphere/fatal/source/fatal_task.cpp | 2 +- stratosphere/fatal/source/fatal_task_screen.cpp | 14 ++++++++++++++ stratosphere/fatal/source/fatal_task_screen.hpp | 13 +++++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 9ed72b2e6..31cb4a798 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -32,10 +32,13 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x380000 + #define INNER_HEAP_SIZE 0x3C0000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; + u32 __nx_nv_transfermem_size = 0x40000; + ViServiceType __nx_gfx_vi_service_type = ViServiceType_Manager; + void __libnx_initheap(void); void __appInit(void); void __appExit(void); @@ -120,18 +123,22 @@ void __appExit(void) { int main(int argc, char **argv) { - consoleDebugInit(debugDevice_SVC); - + /* TODO: Load settings from set:sys. */ + + /* TODO: Load shared font. */ + + /* TODO: Check whether we should throw fatal due to repair process... */ + /* TODO: What's a good timeout value to use here? */ auto server_manager = new WaitableManager(1); - + /* TODO: Create services. */ server_manager->AddWaitable(new ServiceServer<PrivateService>("fatal:p", 4)); server_manager->AddWaitable(new ServiceServer<UserService>("fatal:u", 4)); /* Loop forever, servicing our services. */ server_manager->Process(); - + delete server_manager; return 0; diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 53c3c2853..39a1c82d1 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -56,7 +56,7 @@ static void RunTask(IFatalTask *task) { void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) { RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event)); RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event)); - /* TODO: RunTask(new ShowFatalTask(ctx, title_id, battery_event)); */ + RunTask(new ShowFatalTask(ctx, title_id, battery_event)); RunTask(new StopSoundTask(ctx, title_id)); RunTask(new BacklightControlTask(ctx, title_id)); RunTask(new AdjustClockTask(ctx, title_id)); diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 98e42859e..a28be3fa3 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -17,6 +17,20 @@ #include <switch.h> #include "fatal_task_screen.hpp" +Result ShowFatalTask::ShowFatal() { + Result rc = 0; + + /* TODO: Get graphics to work, draw fatal screen. */ + + return rc; +} + +Result ShowFatalTask::Run() { + /* Don't show the fatal error screen until we've verified the battery is okay. */ + eventWait(this->battery_event, U64_MAX); + + return ShowFatal(); +} void BacklightControlTask::TurnOnBacklight() { lblSwitchBacklightOn(0); diff --git a/stratosphere/fatal/source/fatal_task_screen.hpp b/stratosphere/fatal/source/fatal_task_screen.hpp index 3ea9151ee..a456a9860 100644 --- a/stratosphere/fatal/source/fatal_task_screen.hpp +++ b/stratosphere/fatal/source/fatal_task_screen.hpp @@ -19,6 +19,19 @@ #include <stratosphere.hpp> #include "fatal_task.hpp" +class ShowFatalTask : public IFatalTask { + private: + Event *battery_event; + private: + Result ShowFatal(); + public: + ShowFatalTask(FatalContext *ctx, u64 title_id, Event *evt) : IFatalTask(ctx, title_id), battery_event(evt) { } + virtual Result Run() override; + virtual const char *GetName() const override { + return "ShowFatal"; + } +}; + class BacklightControlTask : public IFatalTask { private: void TurnOnBacklight(); From f914edeebdf14bc01a62343a13a8c1058b81eff7 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 12:38:24 -0800 Subject: [PATCH 197/489] fatal: Implement configuration based on settings --- stratosphere/fatal/source/fatal_config.cpp | 64 +++++++++++++++++++ stratosphere/fatal/source/fatal_config.hpp | 34 ++++++++++ stratosphere/fatal/source/fatal_main.cpp | 13 +++- .../fatal/source/fatal_task_power.cpp | 9 ++- .../fatal/source/fatal_task_screen.cpp | 1 + stratosphere/fatal/source/fatal_user.cpp | 12 +++- 6 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 stratosphere/fatal/source/fatal_config.cpp create mode 100644 stratosphere/fatal/source/fatal_config.hpp diff --git a/stratosphere/fatal/source/fatal_config.cpp b/stratosphere/fatal/source/fatal_config.cpp new file mode 100644 index 000000000..5583e7a0b --- /dev/null +++ b/stratosphere/fatal/source/fatal_config.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_types.hpp" +#include "fatal_config.hpp" + +static FatalConfig g_fatal_config; + +static IEvent *g_fatal_settings_event = nullptr; + +FatalConfig *GetFatalConfig() { + return &g_fatal_config; +} + +static void UpdateLanguageCode() { + setGetLanguageCode(&GetFatalConfig()->language_code); +} + +IEvent *GetFatalSettingsEvent() { + if (g_fatal_settings_event == nullptr) { + Event evt; + if (R_FAILED(setsysBindFatalDirtyFlagEvent(&evt))) { + std::abort(); + } + g_fatal_settings_event = LoadReadOnlySystemEvent(evt.revent, [](u64 timeout) { + u64 flags_0, flags_1; + if (R_SUCCEEDED(setsysGetFatalDirtyFlags(&flags_0, &flags_1)) && (flags_0 & 1)) { + UpdateLanguageCode(); + } + return 0; + }, true); + } + + return g_fatal_settings_event; +} + +void InitializeFatalConfig() { + FatalConfig *config = GetFatalConfig(); + + memset(config, 0, sizeof(*config)); + setsysGetSerialNumber(config->serial_number); + setsysGetFirmwareVersion(&config->firmware_version); + UpdateLanguageCode(); + + setsysGetSettingsItemValue("fatal", "transition_to_fatal", &config->transition_to_fatal, sizeof(config->transition_to_fatal)); + setsysGetSettingsItemValue("fatal", "show_extra_info", &config->show_extra_info, sizeof(config->show_extra_info)); + setsysGetSettingsItemValue("fatal", "quest_reboot_interval_second", &config->quest_reboot_interval_second, sizeof(config->quest_reboot_interval_second)); + + setsysGetFlag(SetSysFlag_Quest, &config->quest_flag); +} diff --git a/stratosphere/fatal/source/fatal_config.hpp b/stratosphere/fatal/source/fatal_config.hpp new file mode 100644 index 000000000..105534bfc --- /dev/null +++ b/stratosphere/fatal/source/fatal_config.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +struct FatalConfig { + char serial_number[0x18]; + SetSysFirmwareVersion firmware_version; + u64 language_code; + u64 quest_reboot_interval_second; + bool transition_to_fatal; + bool show_extra_info; + bool quest_flag; +}; + +IEvent *GetFatalSettingsEvent(); +FatalConfig *GetFatalConfig(); + +void InitializeFatalConfig(); \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 31cb4a798..62324f6f1 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -26,6 +26,7 @@ #include "fatal_types.hpp" #include "fatal_private.hpp" #include "fatal_user.hpp" +#include "fatal_config.hpp" extern "C" { extern u32 __start__; @@ -65,6 +66,11 @@ void __appInit(void) { std::abort(); } + rc = setInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + rc = setsysInitialize(); if (R_FAILED(rc)) { std::abort(); @@ -118,13 +124,15 @@ void __appExit(void) { i2cExit(); pminfoExit(); setsysExit(); + setExit(); smExit(); } int main(int argc, char **argv) { - /* TODO: Load settings from set:sys. */ - + /* Load settings from set:sys. */ + InitializeFatalConfig(); + /* TODO: Load shared font. */ /* TODO: Check whether we should throw fatal due to repair process... */ @@ -135,6 +143,7 @@ int main(int argc, char **argv) /* TODO: Create services. */ server_manager->AddWaitable(new ServiceServer<PrivateService>("fatal:p", 4)); server_manager->AddWaitable(new ServiceServer<UserService>("fatal:u", 4)); + server_manager->AddWaitable(GetFatalSettingsEvent()); /* Loop forever, servicing our services. */ server_manager->Process(); diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index 88e934f53..a804d6ff5 100644 --- a/stratosphere/fatal/source/fatal_task_power.cpp +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -16,6 +16,7 @@ #include <switch.h> #include "fatal_task_power.hpp" +#include "fatal_config.hpp" bool PowerControlTask::TryShutdown() { /* Set a timeout of 30 seconds. */ @@ -91,12 +92,16 @@ void PowerButtonObserveTask::WaitForPowerButton() { /* Wait up to a second for error report generation to finish. */ eventWait(this->erpt_event, TimeoutHelper::NsToTick(1000000000UL)); - /* TODO: Force a reboot after some time if kiosk unit. */ + /* Force a reboot after some time if kiosk unit. */ + const FatalConfig *config = GetFatalConfig(); + TimeoutHelper reboot_helper(config->quest_reboot_interval_second * 1000000000UL); BpcSleepButtonState state; while (true) { + + Result rc = bpcGetSleepButtonState(&state); - if (R_SUCCEEDED(rc) && state == BpcSleepButtonState_Held) { + if ((R_SUCCEEDED(rc) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) { bpcRebootSystem(); return; } diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index a28be3fa3..5dcf40b04 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -16,6 +16,7 @@ #include <switch.h> #include "fatal_task_screen.hpp" +#include "fatal_config.hpp" Result ShowFatalTask::ShowFatal() { Result rc = 0; diff --git a/stratosphere/fatal/source/fatal_user.cpp b/stratosphere/fatal/source/fatal_user.cpp index b21aefc29..f5405267c 100644 --- a/stratosphere/fatal/source/fatal_user.cpp +++ b/stratosphere/fatal/source/fatal_user.cpp @@ -18,6 +18,7 @@ #include "fatal_user.hpp" #include "fatal_event_manager.hpp" #include "fatal_task.hpp" +#include "fatal_config.hpp" static bool g_thrown = false; @@ -37,6 +38,9 @@ Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCp ctx.error_code = error; ctx.cpu_ctx = *cpu_ctx; + /* Get config. */ + const FatalConfig *config = GetFatalConfig(); + /* Get title id. On failure, it'll be zero. */ u64 title_id = 0; pminfoGetTitleId(&title_id, pid); @@ -63,7 +67,13 @@ Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCp } /* Run tasks. */ - RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event); + if (config->transition_to_fatal) { + RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event); + } else { + /* If flag is not set, don't show the fatal screen. */ + return 0; + } + } break; default: From 29833539bbc7295c4162df66c3340bcfc5c428af Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 12:56:43 -0800 Subject: [PATCH 198/489] fatal: Split out fatal from User, stub CheckRepairStatus --- stratosphere/fatal/source/fatal_repair.cpp | 24 ++++++ stratosphere/fatal/source/fatal_repair.hpp | 21 +++++ stratosphere/fatal/source/fatal_throw.cpp | 93 ++++++++++++++++++++++ stratosphere/fatal/source/fatal_throw.hpp | 24 ++++++ stratosphere/fatal/source/fatal_user.cpp | 67 +--------------- stratosphere/fatal/source/fatal_user.hpp | 4 +- 6 files changed, 164 insertions(+), 69 deletions(-) create mode 100644 stratosphere/fatal/source/fatal_repair.cpp create mode 100644 stratosphere/fatal/source/fatal_repair.hpp create mode 100644 stratosphere/fatal/source/fatal_throw.cpp create mode 100644 stratosphere/fatal/source/fatal_throw.hpp diff --git a/stratosphere/fatal/source/fatal_repair.cpp b/stratosphere/fatal/source/fatal_repair.cpp new file mode 100644 index 000000000..b9fdefef8 --- /dev/null +++ b/stratosphere/fatal/source/fatal_repair.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_types.hpp" +#include "fatal_repair.hpp" +#include "fatal_throw.hpp" + +void CheckRepairStatus() { + /* TODO */ +} diff --git a/stratosphere/fatal/source/fatal_repair.hpp b/stratosphere/fatal/source/fatal_repair.hpp new file mode 100644 index 000000000..a06d78c8f --- /dev/null +++ b/stratosphere/fatal/source/fatal_repair.hpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +void CheckRepairStatus(); \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_throw.cpp b/stratosphere/fatal/source/fatal_throw.cpp new file mode 100644 index 000000000..9650acb3d --- /dev/null +++ b/stratosphere/fatal/source/fatal_throw.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "fatal_throw.hpp" +#include "fatal_event_manager.hpp" +#include "fatal_task.hpp" +#include "fatal_config.hpp" + +static bool g_thrown = false; + +static Result SetThrown() { + /* This should be fine, since fatal only has a single IPC thread. */ + if (g_thrown) { + return FatalResult_AlreadyThrown; + } + + g_thrown = true; + return 0; +} + +Result ThrowFatalForSelf(u32 error) { + u64 pid = 0; + FatalCpuContext ctx = {0}; + + svcGetProcessId(&pid, CUR_PROCESS_HANDLE); + return ThrowFatalImpl(error, pid, FatalType_ErrorScreen, &ctx); +} + +Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx) { + Result rc = 0; + FatalContext ctx; + ctx.error_code = error; + ctx.cpu_ctx = *cpu_ctx; + + /* Get config. */ + const FatalConfig *config = GetFatalConfig(); + + /* Get title id. On failure, it'll be zero. */ + u64 title_id = 0; + pminfoGetTitleId(&title_id, pid); + + switch (policy) { + case FatalType_ErrorReport: + /* TODO: Don't write an error report. */ + case FatalType_ErrorReportAndErrorScreen: + case FatalType_ErrorScreen: + { + /* Ensure we only throw once. */ + if (R_FAILED((rc = SetThrown()))) { + return rc; + } + + /* Signal that fatal is about to happen. */ + GetEventManager()->SignalEvents(); + + /* Create events. */ + Event erpt_event; + Event battery_event; + if (R_FAILED(eventCreate(&erpt_event, false)) || R_FAILED(eventCreate(&battery_event, false))) { + std::abort(); + } + + /* Run tasks. */ + if (config->transition_to_fatal) { + RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event); + } else { + /* If flag is not set, don't show the fatal screen. */ + return 0; + } + + } + break; + default: + /* N aborts here. Should we just return an error code? */ + std::abort(); + } + + return 0; +} diff --git a/stratosphere/fatal/source/fatal_throw.hpp b/stratosphere/fatal/source/fatal_throw.hpp new file mode 100644 index 000000000..1723f7b63 --- /dev/null +++ b/stratosphere/fatal/source/fatal_throw.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "fatal_types.hpp" + +Result ThrowFatalForSelf(u32 error); +Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx); diff --git a/stratosphere/fatal/source/fatal_user.cpp b/stratosphere/fatal/source/fatal_user.cpp index f5405267c..98b081494 100644 --- a/stratosphere/fatal/source/fatal_user.cpp +++ b/stratosphere/fatal/source/fatal_user.cpp @@ -16,74 +16,9 @@ #include <switch.h> #include "fatal_user.hpp" +#include "fatal_throw.hpp" #include "fatal_event_manager.hpp" #include "fatal_task.hpp" -#include "fatal_config.hpp" - -static bool g_thrown = false; - -static Result SetThrown() { - /* This should be fine, since fatal only has a single IPC thread. */ - if (g_thrown) { - return FatalResult_AlreadyThrown; - } - - g_thrown = true; - return 0; -} - -Result UserService::ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx) { - Result rc = 0; - FatalContext ctx; - ctx.error_code = error; - ctx.cpu_ctx = *cpu_ctx; - - /* Get config. */ - const FatalConfig *config = GetFatalConfig(); - - /* Get title id. On failure, it'll be zero. */ - u64 title_id = 0; - pminfoGetTitleId(&title_id, pid); - - switch (policy) { - case FatalType_ErrorReport: - /* TODO: Don't write an error report. */ - case FatalType_ErrorReportAndErrorScreen: - case FatalType_ErrorScreen: - { - /* Ensure we only throw once. */ - if (R_FAILED((rc = SetThrown()))) { - return rc; - } - - /* Signal that fatal is about to happen. */ - GetEventManager()->SignalEvents(); - - /* Create events. */ - Event erpt_event; - Event battery_event; - if (R_FAILED(eventCreate(&erpt_event, false)) || R_FAILED(eventCreate(&battery_event, false))) { - std::abort(); - } - - /* Run tasks. */ - if (config->transition_to_fatal) { - RunFatalTasks(&ctx, title_id, policy == FatalType_ErrorReportAndErrorScreen, &erpt_event, &battery_event); - } else { - /* If flag is not set, don't show the fatal screen. */ - return 0; - } - - } - break; - default: - /* N aborts here. Should we just return an error code? */ - std::abort(); - } - - return 0; -} - Result UserService::ThrowFatal(u32 error, PidDescriptor pid_desc) { FatalCpuContext ctx = {0}; diff --git a/stratosphere/fatal/source/fatal_user.hpp b/stratosphere/fatal/source/fatal_user.hpp index ab46a4a9e..186a831d7 100644 --- a/stratosphere/fatal/source/fatal_user.hpp +++ b/stratosphere/fatal/source/fatal_user.hpp @@ -27,9 +27,7 @@ enum UserCmd { }; class UserService final : public IServiceObject { - private: - Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *context); - + private: /* Actual commands. */ Result ThrowFatal(u32 error, PidDescriptor pid_desc); Result ThrowFatalWithPolicy(u32 error, PidDescriptor pid_desc, FatalType policy); From 893bad0db292588a0814f4c31206f04f4ed59b74 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 13:15:48 -0800 Subject: [PATCH 199/489] fatal: Mostly implement CheckRepairStatus --- stratosphere/fatal/source/fatal_main.cpp | 6 +- stratosphere/fatal/source/fatal_repair.cpp | 64 +++++++++++++++++++++- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 62324f6f1..130255c1b 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -27,6 +27,7 @@ #include "fatal_private.hpp" #include "fatal_user.hpp" #include "fatal_config.hpp" +#include "fatal_repair.hpp" extern "C" { extern u32 __start__; @@ -135,12 +136,13 @@ int main(int argc, char **argv) /* TODO: Load shared font. */ - /* TODO: Check whether we should throw fatal due to repair process... */ + /* Check whether we should throw fatal due to repair process. */ + CheckRepairStatus(); /* TODO: What's a good timeout value to use here? */ auto server_manager = new WaitableManager(1); - /* TODO: Create services. */ + /* Create services. */ server_manager->AddWaitable(new ServiceServer<PrivateService>("fatal:p", 4)); server_manager->AddWaitable(new ServiceServer<UserService>("fatal:u", 4)); server_manager->AddWaitable(GetFatalSettingsEvent()); diff --git a/stratosphere/fatal/source/fatal_repair.cpp b/stratosphere/fatal/source/fatal_repair.cpp index b9fdefef8..d4ff000f2 100644 --- a/stratosphere/fatal/source/fatal_repair.cpp +++ b/stratosphere/fatal/source/fatal_repair.cpp @@ -15,10 +15,70 @@ */ #include <switch.h> +#include <stratosphere.hpp> #include "fatal_types.hpp" #include "fatal_repair.hpp" #include "fatal_throw.hpp" -void CheckRepairStatus() { - /* TODO */ +static bool InRepairWithoutVolHeld() { + if (GetRuntimeFirmwareVersion() < FirmwareVersion_300) { + return false; + } + + bool in_repair; + if (R_FAILED(setsysGetFlag(SetSysFlag_InRepairProcessEnable, &in_repair)) || !in_repair) { + return false; + } + + { + GpioPadSession vol_btn; + if (R_SUCCEEDED(gpioOpenSession(&vol_btn, GpioPadName_ButtonVolUp))) { + /* Ensure we close even on early return. */ + ON_SCOPE_EXIT { gpioPadClose(&vol_btn); }; + + /* Set direction input. */ + gpioPadSetDirection(&vol_btn, GpioDirection_Input); + + /* Ensure that we're holding the volume button for a full second. */ + TimeoutHelper timeout_helper(1000000000UL); + while (!timeout_helper.TimedOut()) { + GpioValue val; + if (R_FAILED(gpioPadGetValue(&vol_btn, &val)) || val != GpioValue_Low) { + return true; + } + + /* Sleep for 100 ms. */ + svcSleepThread(100000000UL); + } + } + } + + return false; +} + +static bool InRepairWithoutTimeReviserCartridge() { + if (GetRuntimeFirmwareVersion() < FirmwareVersion_500) { + return false; + } + + bool requires_time_reviser; + if (R_FAILED(setsysGetFlag(SetSysFlag_RequiresRunRepairTimeReviser, &requires_time_reviser)) || !requires_time_reviser) { + return false; + } + + /* TODO: if (!IsGamecardInserted()) { return true; } */ + + /* TODO: return GetGameCardAttribute(GetGameCardHandle()) & GameCardAttribute_Repair == GameCardAttribute_Repair; */ + + return false; +} + +void CheckRepairStatus() { + if (InRepairWithoutVolHeld()) { + ThrowFatalForSelf(FatalResult_InRepairWithoutVolHeld); + } + + if (InRepairWithoutTimeReviserCartridge()) { + ThrowFatalForSelf(FatalResult_InRepairWithoutTimeReviserCartridge); + } } From f7a7ce18476ddbdea51d392f61d3f6555c6a2c11 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 13:17:13 -0800 Subject: [PATCH 200/489] fatal: Fix FatalType_ErrorReport fallthrough --- stratosphere/fatal/source/fatal_throw.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stratosphere/fatal/source/fatal_throw.cpp b/stratosphere/fatal/source/fatal_throw.cpp index 9650acb3d..2eb617593 100644 --- a/stratosphere/fatal/source/fatal_throw.cpp +++ b/stratosphere/fatal/source/fatal_throw.cpp @@ -56,6 +56,7 @@ Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu switch (policy) { case FatalType_ErrorReport: /* TODO: Don't write an error report. */ + break; case FatalType_ErrorReportAndErrorScreen: case FatalType_ErrorScreen: { From caf9d11c8cc0e545f3c31ffcd81993f71592a4de Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 10 Nov 2018 13:38:17 -0800 Subject: [PATCH 201/489] fatal: Finish CheckRepairStatus --- stratosphere/fatal/source/fatal_repair.cpp | 68 ++++++++++++++-------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/stratosphere/fatal/source/fatal_repair.cpp b/stratosphere/fatal/source/fatal_repair.cpp index d4ff000f2..432384cf7 100644 --- a/stratosphere/fatal/source/fatal_repair.cpp +++ b/stratosphere/fatal/source/fatal_repair.cpp @@ -32,25 +32,27 @@ static bool InRepairWithoutVolHeld() { { GpioPadSession vol_btn; - if (R_SUCCEEDED(gpioOpenSession(&vol_btn, GpioPadName_ButtonVolUp))) { - /* Ensure we close even on early return. */ - ON_SCOPE_EXIT { gpioPadClose(&vol_btn); }; - - /* Set direction input. */ - gpioPadSetDirection(&vol_btn, GpioDirection_Input); - - /* Ensure that we're holding the volume button for a full second. */ - TimeoutHelper timeout_helper(1000000000UL); - while (!timeout_helper.TimedOut()) { - GpioValue val; - if (R_FAILED(gpioPadGetValue(&vol_btn, &val)) || val != GpioValue_Low) { - return true; - } - - /* Sleep for 100 ms. */ - svcSleepThread(100000000UL); - } + if (R_FAILED(gpioOpenSession(&vol_btn, GpioPadName_ButtonVolUp))) { + return true; } + + /* Ensure we close even on early return. */ + ON_SCOPE_EXIT { gpioPadClose(&vol_btn); }; + + /* Set direction input. */ + gpioPadSetDirection(&vol_btn, GpioDirection_Input); + + /* Ensure that we're holding the volume button for a full second. */ + TimeoutHelper timeout_helper(1000000000UL); + while (!timeout_helper.TimedOut()) { + GpioValue val; + if (R_FAILED(gpioPadGetValue(&vol_btn, &val)) || val != GpioValue_Low) { + return true; + } + + /* Sleep for 100 ms. */ + svcSleepThread(100000000UL); + } } return false; @@ -66,11 +68,31 @@ static bool InRepairWithoutTimeReviserCartridge() { return false; } - /* TODO: if (!IsGamecardInserted()) { return true; } */ - - /* TODO: return GetGameCardAttribute(GetGameCardHandle()) & GameCardAttribute_Repair == GameCardAttribute_Repair; */ - - return false; + FsGameCardHandle gc_hnd; + u8 gc_attr; + { + FsDeviceOperator devop; + if (R_FAILED(fsOpenDeviceOperator(&devop))) { + return true; + } + + /* Ensure we close even on early return. */ + ON_SCOPE_EXIT { fsDeviceOperatorClose(&devop); }; + + /* Check that a gamecard is inserted. */ + bool inserted; + if (R_FAILED(fsDeviceOperatorIsGameCardInserted(&devop, &inserted)) || !inserted) { + return true; + } + + /* Check that we can retrieve the gamecard's attributes. */ + if (R_FAILED(fsDeviceOperatorGetGameCardHandle(&devop, &gc_hnd)) || R_FAILED(fsDeviceOperatorGetGameCardAttribute(&devop, &gc_hnd, &gc_attr))) { + return true; + } + } + + /* Check that the gamecard is a repair tool. */ + return (gc_attr & FsGameCardAttribute_Repair) == FsGameCardAttribute_Repair; } void CheckRepairStatus() { From b19e50e720b4385ce30e7a6d66a53e4757b1875e Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Mon, 12 Nov 2018 01:55:16 +0000 Subject: [PATCH 202/489] fusee: Implement DRAM training: - Based on reverse engineered code and Peter De Schrijver's patches; - Complemented with CTCaer's minerva_tc project. --- fusee/fusee-primary/src/emc.h | 1760 ++++--- fusee/fusee-secondary/src/emc.h | 1089 +++++ fusee/fusee-secondary/src/main.c | 4 + fusee/fusee-secondary/src/mtc.c | 3750 ++++++++++++++ fusee/fusee-secondary/src/mtc.h | 759 +++ fusee/fusee-secondary/src/mtc_tables.h | 6189 ++++++++++++++++++++++++ 6 files changed, 12880 insertions(+), 671 deletions(-) create mode 100644 fusee/fusee-secondary/src/emc.h create mode 100644 fusee/fusee-secondary/src/mtc.c create mode 100644 fusee/fusee-secondary/src/mtc.h create mode 100644 fusee/fusee-secondary/src/mtc_tables.h diff --git a/fusee/fusee-primary/src/emc.h b/fusee/fusee-primary/src/emc.h index d0bae4130..007559a85 100644 --- a/fusee/fusee-primary/src/emc.h +++ b/fusee/fusee-primary/src/emc.h @@ -1,671 +1,1089 @@ -/* - * arch/arm/mach-tegra/tegra21_emc.h - * - * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef FUSEE_EMC_H_ -#define FUSEE_EMC_H_ - -#define EMC_BASE 0x7001B000 -#define MAKE_EMC_REG(n) MAKE_REG32(EMC_BASE + n) - -#define EMC_DBG 0x8 -#define EMC_CFG 0xC -#define EMC_CONFIG_SAMPLE_DELAY 0x5f0 -#define EMC_CFG_UPDATE 0x5f4 -#define EMC_ADR_CFG 0x10 -#define EMC_REFCTRL 0x20 -#define EMC_PIN 0x24 -#define EMC_TIMING_CONTROL 0x28 -#define EMC_RC 0x2c -#define EMC_RFC 0x30 -#define EMC_RFCPB 0x590 -#define EMC_RAS 0x34 -#define EMC_RP 0x38 -#define EMC_R2W 0x3c -#define EMC_W2R 0x40 -#define EMC_R2P 0x44 -#define EMC_W2P 0x48 -#define EMC_CCDMW 0x5c0 -#define EMC_RD_RCD 0x4c -#define EMC_WR_RCD 0x50 -#define EMC_RRD 0x54 -#define EMC_REXT 0x58 -#define EMC_WDV 0x5c -#define EMC_QUSE 0x60 -#define EMC_QRST 0x64 -#define EMC_ISSUE_QRST 0x428 -#define EMC_QSAFE 0x68 -#define EMC_RDV 0x6c -#define EMC_REFRESH 0x70 -#define EMC_BURST_REFRESH_NUM 0x74 -#define EMC_PDEX2WR 0x78 -#define EMC_PDEX2RD 0x7c -#define EMC_PDEX2CKE 0x118 -#define EMC_PCHG2PDEN 0x80 -#define EMC_ACT2PDEN 0x84 -#define EMC_AR2PDEN 0x88 -#define EMC_RW2PDEN 0x8c -#define EMC_CKE2PDEN 0x11c -#define EMC_TXSR 0x90 -#define EMC_TCKE 0x94 -#define EMC_TFAW 0x98 -#define EMC_TRPAB 0x9c -#define EMC_TCLKSTABLE 0xa0 -#define EMC_TCLKSTOP 0xa4 -#define EMC_TREFBW 0xa8 -#define EMC_TPPD 0xac -#define EMC_PDEX2MRR 0xb4 -#define EMC_ODT_WRITE 0xb0 -#define EMC_WEXT 0xb8 -#define EMC_RFC_SLR 0xc0 -#define EMC_MRS_WAIT_CNT2 0xc4 -#define EMC_MRS_WAIT_CNT 0xc8 -#define EMC_MRS 0xcc -#define EMC_EMRS 0xd0 -#define EMC_REF 0xd4 -#define EMC_PRE 0xd8 -#define EMC_NOP 0xdc -#define EMC_SELF_REF 0xe0 -#define EMC_DPD 0xe4 -#define EMC_MRW 0xe8 -#define EMC_MRR 0xec -#define EMC_CMDQ 0xf0 -#define EMC_MC2EMCQ 0xf4 -#define EMC_FBIO_SPARE 0x100 -#define EMC_FBIO_CFG5 0x104 -#define EMC_CFG_RSV 0x120 -#define EMC_ACPD_CONTROL 0x124 -#define EMC_MPC 0x128 -#define EMC_EMRS2 0x12c -#define EMC_EMRS3 0x130 -#define EMC_MRW2 0x134 -#define EMC_MRW3 0x138 -#define EMC_MRW4 0x13c -#define EMC_MRW5 0x4a0 -#define EMC_MRW6 0x4a4 -#define EMC_MRW7 0x4a8 -#define EMC_MRW8 0x4ac -#define EMC_MRW9 0x4b0 -#define EMC_MRW10 0x4b4 -#define EMC_MRW11 0x4b8 -#define EMC_MRW12 0x4bc -#define EMC_MRW13 0x4c0 -#define EMC_MRW14 0x4c4 -#define EMC_MRW15 0x4d0 -#define EMC_CFG_SYNC 0x4d4 -#define EMC_CLKEN_OVERRIDE 0x140 -#define EMC_R2R 0x144 -#define EMC_W2W 0x148 -#define EMC_EINPUT 0x14c -#define EMC_EINPUT_DURATION 0x150 -#define EMC_PUTERM_EXTRA 0x154 -#define EMC_TCKESR 0x158 -#define EMC_TPD 0x15c -#define EMC_STAT_CONTROL 0x160 -#define EMC_STAT_STATUS 0x164 -#define EMC_STAT_DRAM_CLOCK_LIMIT_LO 0x19c -#define EMC_STAT_DRAM_CLOCK_LIMIT_HI 0x1a0 -#define EMC_STAT_DRAM_CLOCKS_LO 0x1a4 -#define EMC_STAT_DRAM_CLOCKS_HI 0x1a8 -#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_LO 0x1ac -#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_HI 0x1b0 -#define EMC_STAT_DRAM_DEV0_READ_CNT_LO 0x1b4 -#define EMC_STAT_DRAM_DEV0_READ_CNT_HI 0x1b8 -#define EMC_STAT_DRAM_DEV0_READ8_CNT_LO 0x1bc -#define EMC_STAT_DRAM_DEV0_READ8_CNT_HI 0x1c0 -#define EMC_STAT_DRAM_DEV0_WRITE_CNT_LO 0x1c4 -#define EMC_STAT_DRAM_DEV0_WRITE_CNT_HI 0x1c8 -#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_LO 0x1cc -#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_HI 0x1d0 -#define EMC_STAT_DRAM_DEV0_REF_CNT_LO 0x1d4 -#define EMC_STAT_DRAM_DEV0_REF_CNT_HI 0x1d8 -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1dc -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e0 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1e4 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e8 -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1ec -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f0 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1f4 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f8 -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x1fc -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x200 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x204 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x208 -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x20c -#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x210 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x214 -#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x218 -#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_LO 0x21c -#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_HI 0x220 -#define EMC_STAT_DRAM_DEV0_DSR 0x224 -#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_LO 0x228 -#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_HI 0x22c -#define EMC_STAT_DRAM_DEV1_READ_CNT_LO 0x230 -#define EMC_STAT_DRAM_DEV1_READ_CNT_HI 0x234 -#define EMC_STAT_DRAM_DEV1_READ8_CNT_LO 0x238 -#define EMC_STAT_DRAM_DEV1_READ8_CNT_HI 0x23c -#define EMC_STAT_DRAM_DEV1_WRITE_CNT_LO 0x240 -#define EMC_STAT_DRAM_DEV1_WRITE_CNT_HI 0x244 -#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_LO 0x248 -#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_HI 0x24c -#define EMC_STAT_DRAM_DEV1_REF_CNT_LO 0x250 -#define EMC_STAT_DRAM_DEV1_REF_CNT_HI 0x254 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x258 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x25c -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x260 -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x264 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x268 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x26c -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x270 -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x274 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x278 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x27c -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x280 -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x284 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x288 -#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x28c -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x290 -#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x294 -#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_LO 0x298 -#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_HI 0x29c -#define EMC_STAT_DRAM_DEV1_DSR 0x2a0 -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc8c -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc90 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc94 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc98 -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xc9c -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca0 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xca4 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca8 -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcac -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb0 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcb4 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb8 -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcbc -#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc0 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcc4 -#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc8 -#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_LO 0xccc -#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_HI 0xcd0 -#define EMC_STAT_DRAM_IO_DSR 0xcd4 -#define EMC_AUTO_CAL_CONFIG 0x2a4 -#define EMC_AUTO_CAL_CONFIG2 0x458 -#define EMC_AUTO_CAL_CONFIG3 0x45c -#define EMC_AUTO_CAL_CONFIG4 0x5b0 -#define EMC_AUTO_CAL_CONFIG5 0x5b4 -#define EMC_AUTO_CAL_CONFIG6 0x5cc -#define EMC_AUTO_CAL_CONFIG7 0x574 -#define EMC_AUTO_CAL_CONFIG8 0x2dc -#define EMC_AUTO_CAL_VREF_SEL_0 0x2f8 -#define EMC_AUTO_CAL_VREF_SEL_1 0x300 -#define EMC_AUTO_CAL_INTERVAL 0x2a8 -#define EMC_AUTO_CAL_STATUS 0x2ac -#define EMC_AUTO_CAL_STATUS2 0x3d4 -#define EMC_AUTO_CAL_CHANNEL 0x464 -#define EMC_PMACRO_RX_TERM 0xc48 -#define EMC_PMACRO_DQ_TX_DRV 0xc70 -#define EMC_PMACRO_CA_TX_DRV 0xc74 -#define EMC_PMACRO_CMD_TX_DRV 0xc4c -#define EMC_PMACRO_AUTOCAL_CFG_0 0x700 -#define EMC_PMACRO_AUTOCAL_CFG_1 0x704 -#define EMC_PMACRO_AUTOCAL_CFG_2 0x708 -#define EMC_PMACRO_AUTOCAL_CFG_COMMON 0xc78 -#define EMC_PMACRO_ZCTRL 0xc44 -#define EMC_XM2COMPPADCTRL 0x30c -#define EMC_XM2COMPPADCTRL2 0x578 -#define EMC_XM2COMPPADCTRL3 0x2f4 -#define EMC_COMP_PAD_SW_CTRL 0x57c -#define EMC_REQ_CTRL 0x2b0 -#define EMC_EMC_STATUS 0x2b4 -#define EMC_CFG_2 0x2b8 -#define EMC_CFG_DIG_DLL 0x2bc -#define EMC_CFG_DIG_DLL_PERIOD 0x2c0 -#define EMC_DIG_DLL_STATUS 0x2c4 -#define EMC_CFG_DIG_DLL_1 0x2c8 -#define EMC_RDV_MASK 0x2cc -#define EMC_WDV_MASK 0x2d0 -#define EMC_RDV_EARLY_MASK 0x2d4 -#define EMC_RDV_EARLY 0x2d8 -#define EMC_WDV_CHK 0x4e0 -#define EMC_ZCAL_INTERVAL 0x2e0 -#define EMC_ZCAL_WAIT_CNT 0x2e4 -#define EMC_ZCAL_MRW_CMD 0x2e8 -#define EMC_ZQ_CAL 0x2ec -#define EMC_SCRATCH0 0x324 -#define EMC_STALL_THEN_EXE_BEFORE_CLKCHANGE 0x3c8 -#define EMC_STALL_THEN_EXE_AFTER_CLKCHANGE 0x3cc -#define EMC_UNSTALL_RW_AFTER_CLKCHANGE 0x3d0 -#define EMC_FDPD_CTRL_CMD_NO_RAMP 0x4d8 -#define EMC_SEL_DPD_CTRL 0x3d8 -#define EMC_FDPD_CTRL_DQ 0x310 -#define EMC_FDPD_CTRL_CMD 0x314 -#define EMC_PRE_REFRESH_REQ_CNT 0x3dc -#define EMC_REFCTRL2 0x580 -#define EMC_FBIO_CFG7 0x584 -#define EMC_DATA_BRLSHFT_0 0x588 -#define EMC_DATA_BRLSHFT_1 0x58c -#define EMC_DQS_BRLSHFT_0 0x594 -#define EMC_DQS_BRLSHFT_1 0x598 -#define EMC_CMD_BRLSHFT_0 0x59c -#define EMC_CMD_BRLSHFT_1 0x5a0 -#define EMC_CMD_BRLSHFT_2 0x5a4 -#define EMC_CMD_BRLSHFT_3 0x5a8 -#define EMC_QUSE_BRLSHFT_0 0x5ac -#define EMC_QUSE_BRLSHFT_1 0x5b8 -#define EMC_QUSE_BRLSHFT_2 0x5bc -#define EMC_QUSE_BRLSHFT_3 0x5c4 -#define EMC_FBIO_CFG8 0x5c8 -#define EMC_CMD_MAPPING_CMD0_0 0x380 -#define EMC_CMD_MAPPING_CMD0_1 0x384 -#define EMC_CMD_MAPPING_CMD0_2 0x388 -#define EMC_CMD_MAPPING_CMD1_0 0x38c -#define EMC_CMD_MAPPING_CMD1_1 0x390 -#define EMC_CMD_MAPPING_CMD1_2 0x394 -#define EMC_CMD_MAPPING_CMD2_0 0x398 -#define EMC_CMD_MAPPING_CMD2_1 0x39c -#define EMC_CMD_MAPPING_CMD2_2 0x3a0 -#define EMC_CMD_MAPPING_CMD3_0 0x3a4 -#define EMC_CMD_MAPPING_CMD3_1 0x3a8 -#define EMC_CMD_MAPPING_CMD3_2 0x3ac -#define EMC_CMD_MAPPING_BYTE 0x3b0 -#define EMC_DYN_SELF_REF_CONTROL 0x3e0 -#define EMC_TXSRDLL 0x3e4 -#define EMC_CCFIFO_ADDR 0x3e8 -#define EMC_CCFIFO_DATA 0x3ec -#define EMC_CCFIFO_STATUS 0x3f0 -#define EMC_SWIZZLE_RANK0_BYTE0 0x404 -#define EMC_SWIZZLE_RANK0_BYTE1 0x408 -#define EMC_SWIZZLE_RANK0_BYTE2 0x40c -#define EMC_SWIZZLE_RANK0_BYTE3 0x410 -#define EMC_SWIZZLE_RANK1_BYTE0 0x418 -#define EMC_SWIZZLE_RANK1_BYTE1 0x41c -#define EMC_SWIZZLE_RANK1_BYTE2 0x420 -#define EMC_SWIZZLE_RANK1_BYTE3 0x424 -#define EMC_TR_TIMING_0 0x3b4 -#define EMC_TR_CTRL_0 0x3b8 -#define EMC_TR_CTRL_1 0x3bc -#define EMC_TR_DVFS 0x460 -#define EMC_SWITCH_BACK_CTRL 0x3c0 -#define EMC_TR_RDV 0x3c4 -#define EMC_TR_QPOP 0x3f4 -#define EMC_TR_RDV_MASK 0x3f8 -#define EMC_TR_QSAFE 0x3fc -#define EMC_TR_QRST 0x400 -#define EMC_IBDLY 0x468 -#define EMC_OBDLY 0x46c -#define EMC_TXDSRVTTGEN 0x480 -#define EMC_WE_DURATION 0x48c -#define EMC_WS_DURATION 0x490 -#define EMC_WEV 0x494 -#define EMC_WSV 0x498 -#define EMC_CFG_3 0x49c -#define EMC_CFG_PIPE_2 0x554 -#define EMC_CFG_PIPE_CLK 0x558 -#define EMC_CFG_PIPE_1 0x55c -#define EMC_CFG_PIPE 0x560 -#define EMC_QPOP 0x564 -#define EMC_QUSE_WIDTH 0x568 -#define EMC_PUTERM_WIDTH 0x56c -#define EMC_PROTOBIST_CONFIG_ADR_1 0x5d0 -#define EMC_PROTOBIST_CONFIG_ADR_2 0x5d4 -#define EMC_PROTOBIST_MISC 0x5d8 -#define EMC_PROTOBIST_WDATA_LOWER 0x5dc -#define EMC_PROTOBIST_WDATA_UPPER 0x5e0 -#define EMC_PROTOBIST_RDATA 0x5ec -#define EMC_DLL_CFG_0 0x5e4 -#define EMC_DLL_CFG_1 0x5e8 -#define EMC_TRAINING_CMD 0xe00 -#define EMC_TRAINING_CTRL 0xe04 -#define EMC_TRAINING_STATUS 0xe08 -#define EMC_TRAINING_QUSE_CORS_CTRL 0xe0c -#define EMC_TRAINING_QUSE_FINE_CTRL 0xe10 -#define EMC_TRAINING_QUSE_CTRL_MISC 0xe14 -#define EMC_TRAINING_WRITE_FINE_CTRL 0xe18 -#define EMC_TRAINING_WRITE_CTRL_MISC 0xe1c -#define EMC_TRAINING_WRITE_VREF_CTRL 0xe20 -#define EMC_TRAINING_READ_FINE_CTRL 0xe24 -#define EMC_TRAINING_READ_CTRL_MISC 0xe28 -#define EMC_TRAINING_READ_VREF_CTRL 0xe2c -#define EMC_TRAINING_CA_FINE_CTRL 0xe30 -#define EMC_TRAINING_CA_CTRL_MISC 0xe34 -#define EMC_TRAINING_CA_CTRL_MISC1 0xe38 -#define EMC_TRAINING_CA_VREF_CTRL 0xe3c -#define EMC_TRAINING_CA_TADR_CTRL 0xe40 -#define EMC_TRAINING_SETTLE 0xe44 -#define EMC_TRAINING_DEBUG_CTRL 0xe48 -#define EMC_TRAINING_DEBUG_DQ0 0xe4c -#define EMC_TRAINING_DEBUG_DQ1 0xe50 -#define EMC_TRAINING_DEBUG_DQ2 0xe54 -#define EMC_TRAINING_DEBUG_DQ3 0xe58 -#define EMC_TRAINING_MPC 0xe5c -#define EMC_TRAINING_PATRAM_CTRL 0xe60 -#define EMC_TRAINING_PATRAM_DQ 0xe64 -#define EMC_TRAINING_PATRAM_DMI 0xe68 -#define EMC_TRAINING_VREF_SETTLE 0xe6c -#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE0 0xe70 -#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE1 0xe74 -#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE2 0xe78 -#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE3 0xe7c -#define EMC_TRAINING_RW_EYE_CENTER_IB_MISC 0xe80 -#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE0 0xe84 -#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE1 0xe88 -#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE2 0xe8c -#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE3 0xe90 -#define EMC_TRAINING_RW_EYE_CENTER_OB_MISC 0xe94 -#define EMC_TRAINING_RW_OFFSET_IB_BYTE0 0xe98 -#define EMC_TRAINING_RW_OFFSET_IB_BYTE1 0xe9c -#define EMC_TRAINING_RW_OFFSET_IB_BYTE2 0xea0 -#define EMC_TRAINING_RW_OFFSET_IB_BYTE3 0xea4 -#define EMC_TRAINING_RW_OFFSET_IB_MISC 0xea8 -#define EMC_TRAINING_RW_OFFSET_OB_BYTE0 0xeac -#define EMC_TRAINING_RW_OFFSET_OB_BYTE1 0xeb0 -#define EMC_TRAINING_RW_OFFSET_OB_BYTE2 0xeb4 -#define EMC_TRAINING_RW_OFFSET_OB_BYTE3 0xeb8 -#define EMC_TRAINING_RW_OFFSET_OB_MISC 0xebc -#define EMC_TRAINING_OPT_CA_VREF 0xec0 -#define EMC_TRAINING_OPT_DQ_OB_VREF 0xec4 -#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK0 0xec8 -#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK1 0xecc -#define EMC_TRAINING_QUSE_VREF_CTRL 0xed0 -#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4 -#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8 -#define EMC_TRAINING_DRAMC_TIMING 0xedc -#define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600 -#define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604 -#define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608 -#define EMC_PMACRO_QUSE_DDLL_RANK0_3 0x60c -#define EMC_PMACRO_QUSE_DDLL_RANK0_4 0x610 -#define EMC_PMACRO_QUSE_DDLL_RANK0_5 0x614 -#define EMC_PMACRO_QUSE_DDLL_RANK1_0 0x620 -#define EMC_PMACRO_QUSE_DDLL_RANK1_1 0x624 -#define EMC_PMACRO_QUSE_DDLL_RANK1_2 0x628 -#define EMC_PMACRO_QUSE_DDLL_RANK1_3 0x62c -#define EMC_PMACRO_QUSE_DDLL_RANK1_4 0x630 -#define EMC_PMACRO_QUSE_DDLL_RANK1_5 0x634 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 0x640 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 0x644 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 0x648 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 0x64c -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4 0x650 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5 0x654 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 0x660 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 0x664 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 0x668 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 0x66c -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4 0x670 -#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5 0x674 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0 0x680 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1 0x684 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2 0x688 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3 0x68c -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4 0x690 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5 0x694 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0 0x6a0 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1 0x6a4 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2 0x6a8 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3 0x6ac -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4 0x6b0 -#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5 0x6b4 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0 0x6c0 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1 0x6c4 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2 0x6c8 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3 0x6cc -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_4 0x6d0 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_5 0x6d4 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0 0x6e0 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1 0x6e4 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2 0x6e8 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3 0x6ec -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_4 0x6f0 -#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_5 0x6f4 -#define EMC_PMACRO_TX_PWRD_0 0x720 -#define EMC_PMACRO_TX_PWRD_1 0x724 -#define EMC_PMACRO_TX_PWRD_2 0x728 -#define EMC_PMACRO_TX_PWRD_3 0x72c -#define EMC_PMACRO_TX_PWRD_4 0x730 -#define EMC_PMACRO_TX_PWRD_5 0x734 -#define EMC_PMACRO_TX_SEL_CLK_SRC_0 0x740 -#define EMC_PMACRO_TX_SEL_CLK_SRC_1 0x744 -#define EMC_PMACRO_TX_SEL_CLK_SRC_3 0x74c -#define EMC_PMACRO_TX_SEL_CLK_SRC_2 0x748 -#define EMC_PMACRO_TX_SEL_CLK_SRC_4 0x750 -#define EMC_PMACRO_TX_SEL_CLK_SRC_5 0x754 -#define EMC_PMACRO_DDLL_BYPASS 0x760 -#define EMC_PMACRO_DDLL_PWRD_0 0x770 -#define EMC_PMACRO_DDLL_PWRD_1 0x774 -#define EMC_PMACRO_DDLL_PWRD_2 0x778 -#define EMC_PMACRO_CMD_CTRL_0 0x780 -#define EMC_PMACRO_CMD_CTRL_1 0x784 -#define EMC_PMACRO_CMD_CTRL_2 0x788 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0x800 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0x804 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0x808 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3 0x80c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0x810 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0x814 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0x818 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3 0x81c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0x820 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0x824 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0x828 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3 0x82c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0x830 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0x834 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0x838 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3 0x83c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0x840 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0x844 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0x848 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3 0x84c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0x850 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0x854 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0x858 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3 0x85c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0x860 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0x864 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0x868 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3 0x86c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0x870 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0x874 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0x878 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3 0x87c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0 0x880 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1 0x884 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2 0x888 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3 0x88c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0 0x890 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1 0x894 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2 0x898 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3 0x89c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0 0x8a0 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1 0x8a4 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2 0x8a8 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3 0x8ac -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0 0x8b0 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1 0x8b4 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2 0x8b8 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3 0x8bc -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0x900 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0x904 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0x908 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3 0x90c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0x910 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0x914 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0x918 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3 0x91c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0x920 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0x924 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0x928 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3 0x92c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0x930 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0x934 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0x938 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3 0x93c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0x940 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0x944 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0x948 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3 0x94c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0x950 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0x954 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0x958 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3 0x95c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0x960 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0x964 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0x968 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3 0x96c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0x970 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0x974 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0x978 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3 0x97c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0 0x980 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1 0x984 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2 0x988 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3 0x98c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0 0x990 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1 0x994 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2 0x998 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3 0x99c -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0 0x9a0 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1 0x9a4 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2 0x9a8 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3 0x9ac -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0 0x9b0 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1 0x9b4 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2 0x9b8 -#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3 0x9bc -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0xa00 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0xa04 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0xa08 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0xa10 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0xa14 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0xa18 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0xa20 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0xa24 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0xa28 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0xa30 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0xa34 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0xa38 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0xa40 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0xa44 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0xa48 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0xa50 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0xa54 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0xa58 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0xa60 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0xa64 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0xa68 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0xa70 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0xa74 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0xa78 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_0 0xa80 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_1 0xa84 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_2 0xa88 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_0 0xa90 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_1 0xa94 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_2 0xa98 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_0 0xaa0 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_1 0xaa4 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_2 0xaa8 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_0 0xab0 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_1 0xab4 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_2 0xab8 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0xb00 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0xb04 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0xb08 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0xb10 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0xb14 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0xb18 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0xb20 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0xb24 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0xb28 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0xb30 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0xb34 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0xb38 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0xb40 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0xb44 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0xb48 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0xb50 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0xb54 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0xb58 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0xb60 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0xb64 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0xb68 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0xb70 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0xb74 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0xb78 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_0 0xb80 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_1 0xb84 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_2 0xb88 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_0 0xb90 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_1 0xb94 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_2 0xb98 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_0 0xba0 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_1 0xba4 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_2 0xba8 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_0 0xbb0 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_1 0xbb4 -#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_2 0xbb8 -#define EMC_PMACRO_IB_VREF_DQ_0 0xbe0 -#define EMC_PMACRO_IB_VREF_DQ_1 0xbe4 -#define EMC_PMACRO_IB_VREF_DQ_2 0xbe8 -#define EMC_PMACRO_IB_VREF_DQS_0 0xbf0 -#define EMC_PMACRO_IB_VREF_DQS_1 0xbf4 -#define EMC_PMACRO_IB_VREF_DQS_2 0xbf8 -#define EMC_PMACRO_IB_RXRT 0xcf4 -#define EMC_PMACRO_DDLL_LONG_CMD_0 0xc00 -#define EMC_PMACRO_DDLL_LONG_CMD_1 0xc04 -#define EMC_PMACRO_DDLL_LONG_CMD_2 0xc08 -#define EMC_PMACRO_DDLL_LONG_CMD_3 0xc0c -#define EMC_PMACRO_DDLL_LONG_CMD_4 0xc10 -#define EMC_PMACRO_DDLL_LONG_CMD_5 0xc14 -#define EMC_PMACRO_DDLL_SHORT_CMD_0 0xc20 -#define EMC_PMACRO_DDLL_SHORT_CMD_1 0xc24 -#define EMC_PMACRO_DDLL_SHORT_CMD_2 0xc28 -#define EMC_PMACRO_CFG_PM_GLOBAL_0 0xc30 -#define EMC_PMACRO_VTTGEN_CTRL_0 0xc34 -#define EMC_PMACRO_VTTGEN_CTRL_1 0xc38 -#define EMC_PMACRO_VTTGEN_CTRL_2 0xcf0 -#define EMC_PMACRO_BG_BIAS_CTRL_0 0xc3c -#define EMC_PMACRO_PAD_CFG_CTRL 0xc40 -#define EMC_PMACRO_CMD_PAD_RX_CTRL 0xc50 -#define EMC_PMACRO_DATA_PAD_RX_CTRL 0xc54 -#define EMC_PMACRO_CMD_RX_TERM_MODE 0xc58 -#define EMC_PMACRO_DATA_RX_TERM_MODE 0xc5c -#define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60 -#define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64 -#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68 -#define EMC_PMACRO_BRICK_MAPPING_0 0xc80 -#define EMC_PMACRO_BRICK_MAPPING_1 0xc84 -#define EMC_PMACRO_BRICK_MAPPING_2 0xc88 -#define EMC_PMACRO_DDLLCAL_CAL 0xce0 -#define EMC_PMACRO_DDLL_OFFSET 0xce4 -#define EMC_PMACRO_DDLL_PERIODIC_OFFSET 0xce8 -#define EMC_PMACRO_BRICK_CTRL_RFU1 0x330 -#define EMC_PMACRO_BRICK_CTRL_RFU2 0x334 -#define EMC_PMACRO_CMD_BRICK_CTRL_FDPD 0x318 -#define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c -#define EMC_PMACRO_TRAINING_CTRL_0 0xcf8 -#define EMC_PMACRO_TRAINING_CTRL_1 0xcfc -#define EMC_PMC_SCRATCH1 0x440 -#define EMC_PMC_SCRATCH2 0x444 -#define EMC_PMC_SCRATCH3 0x448 - -#endif +/* + * arch/arm/mach-tegra/tegra21_emc.h + * + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef FUSEE_EMC_H_ +#define FUSEE_EMC_H_ + +#define EMC_BASE 0x7001B000 +#define EMC0_BASE 0x7001E000 +#define EMC1_BASE 0x7001F000 +#define MAKE_EMC_REG(n) MAKE_REG32(EMC_BASE + n) +#define MAKE_EMC0_REG(n) MAKE_REG32(EMC0_BASE + n) +#define MAKE_EMC1_REG(n) MAKE_REG32(EMC1_BASE + n) + +#define EMC_INTSTATUS 0x0 +#define EMC_INTSTATUS_MRR_DIVLD (0x1 << 5) +#define EMC_INTSTATUS_CLKCHANGE_COMPLETE (0x1 << 4) + +#define EMC_INTMASK 0x4 +#define EMC_DBG 0x8 +#define EMC_DBG_WRITE_MUX_ACTIVE (1 << 1) +#define EMC_DBG_CFG_SWAP_SHIFT 26 +#define EMC_DBG_CFG_SWAP_MASK \ + (0x3 << EMC_DBG_CFG_SWAP_SHIFT) +#define EMC_DBG_WRITE_ACTIVE_ONLY (1 << 30) + +#define EMC_CONFIG_SAMPLE_DELAY 0x5f0 +#define EMC_CFG_UPDATE 0x5f4 +#define EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_SHIFT 9 +#define EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_MASK \ + (0x3 << EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_SHIFT) +#define EMC_CFG 0xc +#define EMC_CFG_DRAM_CLKSTOP_PD (1 << 31) +#define EMC_CFG_DRAM_CLKSTOP_SR (1 << 30) +#define EMC_CFG_DRAM_ACPD (1 << 29) +#define EMC_CFG_DYN_SELF_REF (1 << 28) +#define EMC_CFG_REQACT_ASYNC (1 << 26) +#define EMC_CFG_AUTO_PRE_WR (1 << 25) +#define EMC_CFG_AUTO_PRE_RD (1 << 24) +#define EMC_CFG_MAM_PRE_WR (1 << 23) +#define EMC_CFG_MAN_PRE_RD (1 << 22) +#define EMC_CFG_PERIODIC_QRST (1 << 21) +#define EMC_CFG_PERIODIC_QRST_SHIFT (21) +#define EMC_CFG_EN_DYNAMIC_PUTERM (1 << 20) +#define EMC_CFG_DLY_WR_DQ_HALF_CLOCK (1 << 19) +#define EMC_CFG_DSR_VTTGEN_DRV_EN (1 << 18) +#define EMC_CFG_EMC2MC_CLK_RATIO (3 << 16) +#define EMC_CFG_WAIT_FOR_ISP2B_READY_B4_CC (1 << 9) +#define EMC_CFG_WAIT_FOR_VI2_READY_B4_CC (1 << 8) +#define EMC_CFG_WAIT_FOR_ISP2_READY_B4_CC (1 << 7) +#define EMC_CFG_INVERT_DQM (1 << 6) +#define EMC_CFG_WAIT_FOR_DISPLAYB_READY_B4_CC (1 << 5) +#define EMC_CFG_WAIT_FOR_DISPLAY_READY_B4_CC (1 << 4) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2 (1 << 3) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1 (1 << 2) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE (1 << 1) + +#define EMC_ADR_CFG 0x10 +#define EMC_REFCTRL 0x20 +#define EMC_REFCTRL_DEV_SEL_SHIFT 0 +#define EMC_REFCTRL_DEV_SEL_MASK \ + (0x3 << EMC_REFCTRL_DEV_SEL_SHIFT) +#define EMC_REFCTRL_ENABLE (0x1 << 31) +#define EMC_REFCTRL_ENABLE_ALL(num) \ + (((((num) > 1) ? 0 : 2) << EMC_REFCTRL_DEV_SEL_SHIFT) \ + | EMC_REFCTRL_ENABLE) +#define EMC_REFCTRL_DISABLE_ALL(num) \ + ((((num) > 1) ? 0 : 2) << EMC_REFCTRL_DEV_SEL_SHIFT) + +#define EMC_PIN 0x24 +#define EMC_PIN_PIN_CKE_PER_DEV (1 << 2) +#define EMC_PIN_PIN_CKEB (1 << 1) +#define EMC_PIN_PIN_CKE (1 << 0) + +#define EMC_CLK_FORCE_CC_TRIGGER (1 << 27) + +#define EMC_TIMING_CONTROL 0x28 +#define EMC_RC 0x2c +#define EMC_RFC 0x30 +#define EMC_RFCPB 0x590 +#define EMC_RAS 0x34 +#define EMC_RP 0x38 +#define EMC_R2W 0x3c +#define EMC_W2R 0x40 +#define EMC_R2P 0x44 +#define EMC_W2P 0x48 +#define EMC_CCDMW 0x5c0 +#define EMC_RD_RCD 0x4c +#define EMC_WR_RCD 0x50 +#define EMC_RRD 0x54 +#define EMC_REXT 0x58 +#define EMC_WDV 0x5c +#define EMC_QUSE 0x60 +#define EMC_QRST 0x64 +#define EMC_ISSUE_QRST 0x428 +#define EMC_QSAFE 0x68 +#define EMC_RDV 0x6c +#define EMC_REFRESH 0x70 +#define EMC_BURST_REFRESH_NUM 0x74 +#define EMC_PDEX2WR 0x78 +#define EMC_PDEX2RD 0x7c +#define EMC_PDEX2CKE 0x118 +#define EMC_PCHG2PDEN 0x80 +#define EMC_ACT2PDEN 0x84 +#define EMC_AR2PDEN 0x88 +#define EMC_RW2PDEN 0x8c +#define EMC_CKE2PDEN 0x11c +#define EMC_TXSR 0x90 +#define EMC_TCKE 0x94 +#define EMC_TFAW 0x98 +#define EMC_TRPAB 0x9c +#define EMC_TCLKSTABLE 0xa0 +#define EMC_TCLKSTOP 0xa4 +#define EMC_TREFBW 0xa8 +#define EMC_TPPD 0xac +#define EMC_PDEX2MRR 0xb4 +#define EMC_ODT_WRITE 0xb0 +#define EMC_WEXT 0xb8 +#define EMC_RFC_SLR 0xc0 +#define EMC_MRS_WAIT_CNT2 0xc4 +#define EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_SHIFT 16 +#define EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_MASK \ + (0x7ff << EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_SHIFT) +#define EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_SHIFT 0 +#define EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_MASK \ + (0x3ff << EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_SHIFT) + +#define EMC_MRS_WAIT_CNT 0xc8 +#define EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT 0 +#define EMC_MRS_WAIT_CNT_SHORT_WAIT_MASK \ + (0x3FF << EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT) +#define EMC_MRS_WAIT_CNT_LONG_WAIT_SHIFT 16 +#define EMC_MRS_WAIT_CNT_LONG_WAIT_MASK \ + (0x3FF << EMC_MRS_WAIT_CNT_LONG_WAIT_SHIFT) + +#define EMC_MRS 0xcc +#define EMC_MODE_SET_DLL_RESET (1 << 8) +#define EMC_MRS_USE_MRS_LONG_CNT (1 << 26) + +#define EMC_EMRS 0xd0 +#define EMC_EMRS_USE_EMRS_LONG_CNT (1 << 26) + +#define EMC_REF 0xd4 +#define EMC_REF_FORCE_CMD 1 + +#define EMC_PRE 0xd8 +#define EMC_NOP 0xdc +#define EMC_SELF_REF 0xe0 +#define EMC_SELF_REF_CMD_ENABLED (1 << 0) +#define EMC_SELF_REF_ACTIVE_SELF_REF (1 << 8) +#define EMC_SELF_REF_DEV_SEL_SHIFT 30 +#define EMC_SELF_REF_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) + +#define EMC_DPD 0xe4 +#define EMC_MRW 0xe8 +#define EMC_MRW_MRW_OP_SHIFT 0 +#define EMC_MRW_MRW_OP_MASK \ + (0xff << EMC_MRW_MRW_OP_SHIFT) +#define EMC_MRW_MRW_MA_SHIFT 16 +#define EMC_MRW_MRW_MA_MASK \ + (0xff << EMC_MRW_MRW_MA_SHIFT) +#define EMC_MRW_USE_MRW_LONG_CNT 26 +#define EMC_MRW_USE_MRW_EXT_CNT 27 +#define EMC_MRW_MRW_DEV_SELECTN_SHIFT 30 +#define EMC_MRW_MRW_DEV_SELECTN_MASK \ + (0x3 << EMC_MRW_MRW_DEV_SELECTN_SHIFT) + +#define EMC_MRR 0xec +#define EMC_MRR_DEV_SEL_SHIFT 30 +#define EMC_MRR_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) +#define EMC_MRR_MA_SHIFT 16 +#define EMC_MRR_MA_MASK \ + (0xff << EMC_MRR_MA_SHIFT) +#define EMC_MRR_DATA_SHIFT 0 +#define EMC_MRR_DATA_MASK \ + (0xffff << EMC_MRR_DATA_SHIFT) +#define LPDDR2_MR4_TEMP_SHIFT 0 +#define LPDDR2_MR4_TEMP_MASK \ + (0x7 << LPDDR2_MR4_TEMP_SHIFT) + +#define EMC_CMDQ 0xf0 +#define EMC_MC2EMCQ 0xf4 +#define EMC_FBIO_SPARE 0x100 +#define EMC_FBIO_CFG5 0x104 +#define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT 0 +#define EMC_FBIO_CFG5_DRAM_TYPE_MASK \ + (0x3 << EMC_FBIO_CFG5_DRAM_TYPE_SHIFT) +#define EMC_FBIO_CFG5_CMD_TX_DIS (1 << 8) +#define EMC_FBIO_CFG5_CMD_BUS_RETURN_TO_ZERO (1 << 27) + +#define EMC_CFG5_QUSE_MODE_SHIFT 13 +#define EMC_CFG5_QUSE_MODE_MASK \ + (0x7 << EMC_CFG5_QUSE_MODE_SHIFT) + +#define EMC_CFG_RSV 0x120 +#define EMC_ACPD_CONTROL 0x124 +#define EMC_MPC 0x128 +#define EMC_EMRS2 0x12c +#define EMC_EMRS2_USE_EMRS2_LONG_CNT (1 << 26) + +#define EMC_EMRS3 0x130 +#define EMC_MRW2 0x134 +#define EMC_MRW3 0x138 +#define EMC_MRW4 0x13c +#define EMC_MRW5 0x4a0 +#define EMC_MRW6 0x4a4 +#define EMC_MRW7 0x4a8 +#define EMC_MRW8 0x4ac +#define EMC_MRW9 0x4b0 +#define EMC_MRW10 0x4b4 +#define EMC_MRW11 0x4b8 +#define EMC_MRW12 0x4bc +#define EMC_MRW13 0x4c0 +#define EMC_MRW14 0x4c4 +#define EMC_MRW15 0x4d0 +#define EMC_CFG_SYNC 0x4d4 +#define EMC_CLKEN_OVERRIDE 0x140 +#define EMC_R2R 0x144 +#define EMC_W2W 0x148 +#define EMC_EINPUT 0x14c +#define EMC_EINPUT_DURATION 0x150 +#define EMC_PUTERM_EXTRA 0x154 +#define EMC_TCKESR 0x158 +#define EMC_TPD 0x15c +#define EMC_STAT_CONTROL 0x160 +#define EMC_STAT_STATUS 0x164 +#define EMC_STAT_DRAM_CLOCK_LIMIT_LO 0x19c +#define EMC_STAT_DRAM_CLOCK_LIMIT_HI 0x1a0 +#define EMC_STAT_DRAM_CLOCKS_LO 0x1a4 +#define EMC_STAT_DRAM_CLOCKS_HI 0x1a8 +#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_LO 0x1ac +#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_HI 0x1b0 +#define EMC_STAT_DRAM_DEV0_READ_CNT_LO 0x1b4 +#define EMC_STAT_DRAM_DEV0_READ_CNT_HI 0x1b8 +#define EMC_STAT_DRAM_DEV0_READ8_CNT_LO 0x1bc +#define EMC_STAT_DRAM_DEV0_READ8_CNT_HI 0x1c0 +#define EMC_STAT_DRAM_DEV0_WRITE_CNT_LO 0x1c4 +#define EMC_STAT_DRAM_DEV0_WRITE_CNT_HI 0x1c8 +#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_LO 0x1cc +#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_HI 0x1d0 +#define EMC_STAT_DRAM_DEV0_REF_CNT_LO 0x1d4 +#define EMC_STAT_DRAM_DEV0_REF_CNT_HI 0x1d8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1dc +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e0 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1e4 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1ec +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f0 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1f4 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x1fc +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x200 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x204 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x208 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x20c +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x210 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x214 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x218 +#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_LO 0x21c +#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_HI 0x220 +#define EMC_STAT_DRAM_DEV0_DSR 0x224 +#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_LO 0x228 +#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_HI 0x22c +#define EMC_STAT_DRAM_DEV1_READ_CNT_LO 0x230 +#define EMC_STAT_DRAM_DEV1_READ_CNT_HI 0x234 +#define EMC_STAT_DRAM_DEV1_READ8_CNT_LO 0x238 +#define EMC_STAT_DRAM_DEV1_READ8_CNT_HI 0x23c +#define EMC_STAT_DRAM_DEV1_WRITE_CNT_LO 0x240 +#define EMC_STAT_DRAM_DEV1_WRITE_CNT_HI 0x244 +#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_LO 0x248 +#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_HI 0x24c +#define EMC_STAT_DRAM_DEV1_REF_CNT_LO 0x250 +#define EMC_STAT_DRAM_DEV1_REF_CNT_HI 0x254 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x258 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x25c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x260 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x264 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x268 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x26c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x270 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x274 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x278 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x27c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x280 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x284 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x288 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x28c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x290 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x294 +#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_LO 0x298 +#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_HI 0x29c +#define EMC_STAT_DRAM_DEV1_DSR 0x2a0 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc8c +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc90 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc94 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc98 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xc9c +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xca4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca8 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcac +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcb4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb8 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcbc +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcc4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc8 +#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_LO 0xccc +#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_HI 0xcd0 +#define EMC_STAT_DRAM_IO_DSR 0xcd4 +#define EMC_AUTO_CAL_CONFIG 0x2a4 +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_COMPUTE_START (1 << 0) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_MEASURE_STALL (1 << 9) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_UPDATE_STALL (1 << 10) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_ENABLE (1 << 29) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_START (1 << 31) + +#define EMC_AUTO_CAL_CONFIG2 0x458 +#define EMC_AUTO_CAL_CONFIG3 0x45c +#define EMC_AUTO_CAL_CONFIG4 0x5b0 +#define EMC_AUTO_CAL_CONFIG5 0x5b4 +#define EMC_AUTO_CAL_CONFIG6 0x5cc +#define EMC_AUTO_CAL_CONFIG7 0x574 +#define EMC_AUTO_CAL_CONFIG8 0x2dc +#define EMC_AUTO_CAL_VREF_SEL_0 0x2f8 +#define EMC_AUTO_CAL_VREF_SEL_1 0x300 +#define EMC_AUTO_CAL_INTERVAL 0x2a8 +#define EMC_AUTO_CAL_STATUS 0x2ac +#define EMC_AUTO_CAL_STATUS2 0x3d4 +#define EMC_AUTO_CAL_CHANNEL 0x464 +#define EMC_PMACRO_RX_TERM 0xc48 +#define EMC_PMACRO_DQ_TX_DRV 0xc70 +#define EMC_PMACRO_CA_TX_DRV 0xc74 +#define EMC_PMACRO_CMD_TX_DRV 0xc4c +#define EMC_PMACRO_AUTOCAL_CFG_0 0x700 +#define EMC_PMACRO_AUTOCAL_CFG_1 0x704 +#define EMC_PMACRO_AUTOCAL_CFG_2 0x708 +#define EMC_PMACRO_AUTOCAL_CFG_COMMON 0xc78 +#define EMC_PMACRO_AUTOCAL_CFG_COMMON_E_CAL_BYPASS_DVFS (1 << 16) + +#define EMC_PMACRO_ZCTRL 0xc44 +#define EMC_XM2COMPPADCTRL 0x30c +#define EMC_XM2COMPPADCTRL_VREF_CAL_ENABLE (1 << 10) + +#define EMC_XM2COMPPADCTRL2 0x578 +#define EMC_XM2COMPPADCTRL3 0x2f4 +#define EMC_COMP_PAD_SW_CTRL 0x57c +#define EMC_REQ_CTRL 0x2b0 +#define EMC_EMC_STATUS 0x2b4 +#define EMC_EMC_STATUS_MRR_DIVLD (1 << 20) +#define EMC_EMC_STATUS_TIMING_UPDATE_STALLED (1 << 23) +#define EMC_EMC_STATUS_DRAM_IN_POWERDOWN_SHIFT 4 +#define EMC_EMC_STATUS_DRAM_IN_POWERDOWN_MASK \ + (0x3 << EMC_EMC_STATUS_DRAM_IN_POWERDOWN_SHIFT) +#define EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_SHIFT 8 +#define EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK \ + (0x3 << EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_SHIFT) + +#define EMC_CFG_2 0x2b8 +#define EMC_CFG_DIG_DLL 0x2bc +#define EMC_CFG_DIG_DLL_CFG_DLL_EN (1 << 0) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_UNTIL_LOCK (1 << 1) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_TRAFFIC (1 << 3) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_RW_UNTIL_LOCK (1 << 4) +#define EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT 6 +#define EMC_CFG_DIG_DLL_CFG_DLL_MODE_MASK \ + (0x3 << EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT) +#define EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT 8 +#define EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_MASK \ + (0x7 << EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT) + +#define EMC_CFG_DIG_DLL_PERIOD 0x2c0 +#define EMC_DIG_DLL_STATUS 0x2c4 +#define EMC_DIG_DLL_STATUS_DLL_LOCK (1 << 15) +#define EMC_DIG_DLL_STATUS_DLL_PRIV_UPDATED (1 << 17) +#define EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT 0 +#define EMC_DIG_DLL_STATUS_DLL_OUT_MASK \ + (0x7ff << EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT) + +#define EMC_CFG_DIG_DLL_1 0x2c8 +#define EMC_RDV_MASK 0x2cc +#define EMC_WDV_MASK 0x2d0 +#define EMC_RDV_EARLY_MASK 0x2d4 +#define EMC_RDV_EARLY 0x2d8 +#define EMC_WDV_CHK 0x4e0 +#define EMC_ZCAL_INTERVAL 0x2e0 +#define EMC_ZCAL_WAIT_CNT 0x2e4 +#define EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK 0x7ff +#define EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_SHIFT 0 + +#define EMC_ZCAL_MRW_CMD 0x2e8 +#define EMC_ZQ_CAL 0x2ec +#define EMC_ZQ_CAL_DEV_SEL_SHIFT 30 +#define EMC_ZQ_CAL_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) +#define EMC_ZQ_CAL_LONG (1 << 4) +#define EMC_ZQ_CAL_ZQ_LATCH_CMD (1 << 1) +#define EMC_ZQ_CAL_ZQ_CAL_CMD (1 << 0) +#define EMC_ZQ_CAL_LONG_CMD_DEV0 \ + (DRAM_DEV_SEL_0 | EMC_ZQ_CAL_LONG | EMC_ZQ_CAL_CMD) +#define EMC_ZQ_CAL_LONG_CMD_DEV1 \ + (DRAM_DEV_SEL_1 | EMC_ZQ_CAL_LONG | EMC_ZQ_CAL_CMD) + +#define EMC_SCRATCH0 0x324 +#define EMC_STALL_THEN_EXE_BEFORE_CLKCHANGE 0x3c8 +#define EMC_STALL_THEN_EXE_AFTER_CLKCHANGE 0x3cc +#define EMC_UNSTALL_RW_AFTER_CLKCHANGE 0x3d0 +#define EMC_FDPD_CTRL_CMD_NO_RAMP 0x4d8 +#define EMC_FDPD_CTRL_CMD_NO_RAMP_CMD_DPD_NO_RAMP_ENABLE (1 << 0) + +#define EMC_SEL_DPD_CTRL 0x3d8 +#define EMC_SEL_DPD_CTRL_DATA_SEL_DPD_EN (1 << 8) +#define EMC_SEL_DPD_CTRL_ODT_SEL_DPD_EN (1 << 5) +#define EMC_SEL_DPD_CTRL_RESET_SEL_DPD_EN (1 << 4) +#define EMC_SEL_DPD_CTRL_CA_SEL_DPD_EN (1 << 3) +#define EMC_SEL_DPD_CTRL_CLK_SEL_DPD_EN (1 << 2) +#define EMC_SEL_DPD_CTRL_DDR3_MASK \ + ((0xf << 2) | (0x1 << 8)) +#define EMC_SEL_DPD_CTRL_MAS \ + ((0x3 << 2) | (0x1 << 5) | (0x1 << 8)) + +#define EMC_FDPD_CTRL_DQ 0x310 +#define EMC_FDPD_CTRL_CMD 0x314 +#define EMC_PRE_REFRESH_REQ_CNT 0x3dc +#define EMC_REFCTRL2 0x580 +#define EMC_FBIO_CFG7 0x584 +#define EMC_FBIO_CFG7_CH0_ENABLE (1 << 1) +#define EMC_FBIO_CFG7_CH1_ENABLE (1 << 2) + +#define EMC_DATA_BRLSHFT_0 0x588 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT 21 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT 18 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT 15 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT 12 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT 9 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT 6 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT 3 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT 0 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT) + +#define EMC_DATA_BRLSHFT_1 0x58c +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT 21 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT 18 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT 15 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT 12 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT 9 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT 6 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT 3 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT 0 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT) + +#define EMC_DQS_BRLSHFT_0 0x594 +#define EMC_DQS_BRLSHFT_1 0x598 +#define EMC_CMD_BRLSHFT_0 0x59c +#define EMC_CMD_BRLSHFT_1 0x5a0 +#define EMC_CMD_BRLSHFT_2 0x5a4 +#define EMC_CMD_BRLSHFT_3 0x5a8 +#define EMC_QUSE_BRLSHFT_0 0x5ac +#define EMC_QUSE_BRLSHFT_1 0x5b8 +#define EMC_QUSE_BRLSHFT_2 0x5bc +#define EMC_QUSE_BRLSHFT_3 0x5c4 +#define EMC_FBIO_CFG8 0x5c8 +#define EMC_CMD_MAPPING_CMD0_0 0x380 +#define EMC_CMD_MAPPING_CMD0_1 0x384 +#define EMC_CMD_MAPPING_CMD0_2 0x388 +#define EMC_CMD_MAPPING_CMD1_0 0x38c +#define EMC_CMD_MAPPING_CMD1_1 0x390 +#define EMC_CMD_MAPPING_CMD1_2 0x394 +#define EMC_CMD_MAPPING_CMD2_0 0x398 +#define EMC_CMD_MAPPING_CMD2_1 0x39c +#define EMC_CMD_MAPPING_CMD2_2 0x3a0 +#define EMC_CMD_MAPPING_CMD3_0 0x3a4 +#define EMC_CMD_MAPPING_CMD3_1 0x3a8 +#define EMC_CMD_MAPPING_CMD3_2 0x3ac +#define EMC_CMD_MAPPING_BYTE 0x3b0 +#define EMC_DYN_SELF_REF_CONTROL 0x3e0 +#define EMC_TXSRDLL 0x3e4 +#define EMC_CCFIFO_ADDR 0x3e8 +#define EMC_CCFIFO_DATA 0x3ec +#define EMC_CCFIFO_STATUS 0x3f0 +#define EMC_SWIZZLE_RANK0_BYTE0 0x404 +#define EMC_SWIZZLE_RANK0_BYTE1 0x408 +#define EMC_SWIZZLE_RANK0_BYTE2 0x40c +#define EMC_SWIZZLE_RANK0_BYTE3 0x410 +#define EMC_SWIZZLE_RANK1_BYTE0 0x418 +#define EMC_SWIZZLE_RANK1_BYTE1 0x41c +#define EMC_SWIZZLE_RANK1_BYTE2 0x420 +#define EMC_SWIZZLE_RANK1_BYTE3 0x424 +#define EMC_TR_TIMING_0 0x3b4 +#define EMC_TR_CTRL_0 0x3b8 +#define EMC_TR_CTRL_1 0x3bc +#define EMC_TR_DVFS 0x460 +#define EMC_TR_DVFS_TRAINING_DVFS (1 << 0) + +#define EMC_SWITCH_BACK_CTRL 0x3c0 +#define EMC_TR_RDV 0x3c4 +#define EMC_TR_QPOP 0x3f4 +#define EMC_TR_RDV_MASK 0x3f8 +#define EMC_TR_QSAFE 0x3fc +#define EMC_TR_QRST 0x400 +#define EMC_IBDLY 0x468 +#define EMC_OBDLY 0x46c +#define EMC_TXDSRVTTGEN 0x480 +#define EMC_WE_DURATION 0x48c +#define EMC_WS_DURATION 0x490 +#define EMC_WEV 0x494 +#define EMC_WSV 0x498 +#define EMC_CFG_3 0x49c +#define EMC_CFG_PIPE_2 0x554 +#define EMC_CFG_PIPE_CLK 0x558 +#define EMC_CFG_PIPE_CLK_CLK_ALWAYS_ON (1 << 0) + +#define EMC_CFG_PIPE_1 0x55c +#define EMC_CFG_PIPE 0x560 +#define EMC_QPOP 0x564 +#define EMC_QUSE_WIDTH 0x568 +#define EMC_PUTERM_WIDTH 0x56c +#define EMC_PROTOBIST_CONFIG_ADR_1 0x5d0 +#define EMC_PROTOBIST_CONFIG_ADR_2 0x5d4 +#define EMC_PROTOBIST_MISC 0x5d8 +#define EMC_PROTOBIST_WDATA_LOWER 0x5dc +#define EMC_PROTOBIST_WDATA_UPPER 0x5e0 +#define EMC_PROTOBIST_RDATA 0x5ec +#define EMC_DLL_CFG_0 0x5e4 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_IGNORE_START (1 << 29) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_DUAL_PASS_LOCK (1 << 28) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_SHIFT 24 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_SHIFT 20 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_SHIFT 16 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_SHIFT 12 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_SHIFT 4 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_MASK \ + (0xff << EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_SHIFT 0 +#define EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_SHIFT) + +#define EMC_DLL_CFG_1 0x5e8 +#define EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_SHIFT 10 +#define EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_MASK \ + (0x7ff << EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_SHIFT) + +#define EMC_TRAINING_CMD 0xe00 +#define EMC_TRAINING_CMD_PRIME (1 << 0) +#define EMC_TRAINING_CMD_CA (1 << 1) +#define EMC_TRAINING_CMD_RD (1 << 2) +#define EMC_TRAINING_CMD_WR (1 << 3) +#define EMC_TRAINING_CMD_QUSE (1 << 4) +#define EMC_TRAINING_CMD_CA_VREF (1 << 5) +#define EMC_TRAINING_CMD_RD_VREF (1 << 6) +#define EMC_TRAINING_CMD_WR_VREF (1 << 7) +#define EMC_TRAINING_CMD_QUSE_VREF (1 << 8) +#define EMC_TRAINING_CMD_GO (1 << 31) + +#define EMC_TRAINING_CTRL 0xe04 +#define EMC_TRAINING_CTRL_SWAP_RANK (1 << 14) + +#define EMC_TRAINING_STATUS 0xe08 +#define EMC_TRAINING_QUSE_CORS_CTRL 0xe0c +#define EMC_TRAINING_QUSE_FINE_CTRL 0xe10 +#define EMC_TRAINING_QUSE_CTRL_MISC 0xe14 +#define EMC_TRAINING_WRITE_FINE_CTRL 0xe18 +#define EMC_TRAINING_WRITE_CTRL_MISC 0xe1c +#define EMC_TRAINING_WRITE_VREF_CTRL 0xe20 +#define EMC_TRAINING_READ_FINE_CTRL 0xe24 +#define EMC_TRAINING_READ_CTRL_MISC 0xe28 +#define EMC_TRAINING_READ_VREF_CTRL 0xe2c +#define EMC_TRAINING_CA_FINE_CTRL 0xe30 +#define EMC_TRAINING_CA_CTRL_MISC 0xe34 +#define EMC_TRAINING_CA_CTRL_MISC1 0xe38 +#define EMC_TRAINING_CA_VREF_CTRL 0xe3c +#define EMC_TRAINING_CA_TADR_CTRL 0xe40 +#define EMC_TRAINING_SETTLE 0xe44 +#define EMC_TRAINING_DEBUG_CTRL 0xe48 +#define EMC_TRAINING_DEBUG_DQ0 0xe4c +#define EMC_TRAINING_DEBUG_DQ1 0xe50 +#define EMC_TRAINING_DEBUG_DQ2 0xe54 +#define EMC_TRAINING_DEBUG_DQ3 0xe58 +#define EMC_TRAINING_MPC 0xe5c +#define EMC_TRAINING_PATRAM_CTRL 0xe60 +#define EMC_TRAINING_PATRAM_DQ 0xe64 +#define EMC_TRAINING_PATRAM_DMI 0xe68 +#define EMC_TRAINING_VREF_SETTLE 0xe6c +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE0 0xe70 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE1 0xe74 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE2 0xe78 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE3 0xe7c +#define EMC_TRAINING_RW_EYE_CENTER_IB_MISC 0xe80 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE0 0xe84 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE1 0xe88 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE2 0xe8c +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE3 0xe90 +#define EMC_TRAINING_RW_EYE_CENTER_OB_MISC 0xe94 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE0 0xe98 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE1 0xe9c +#define EMC_TRAINING_RW_OFFSET_IB_BYTE2 0xea0 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE3 0xea4 +#define EMC_TRAINING_RW_OFFSET_IB_MISC 0xea8 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE0 0xeac +#define EMC_TRAINING_RW_OFFSET_OB_BYTE1 0xeb0 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE2 0xeb4 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE3 0xeb8 +#define EMC_TRAINING_RW_OFFSET_OB_MISC 0xebc +#define EMC_TRAINING_OPT_CA_VREF 0xec0 +#define EMC_TRAINING_OPT_DQ_OB_VREF 0xec4 +#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK0 0xec8 +#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK1 0xecc +#define EMC_TRAINING_QUSE_VREF_CTRL 0xed0 +#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4 +#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8 +#define EMC_TRAINING_DRAMC_TIMING 0xedc +#define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600 +#define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604 +#define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608 +#define EMC_PMACRO_QUSE_DDLL_RANK0_3 0x60c +#define EMC_PMACRO_QUSE_DDLL_RANK0_4 0x610 +#define EMC_PMACRO_QUSE_DDLL_RANK0_5 0x614 +#define EMC_PMACRO_QUSE_DDLL_RANK1_0 0x620 +#define EMC_PMACRO_QUSE_DDLL_RANK1_1 0x624 +#define EMC_PMACRO_QUSE_DDLL_RANK1_2 0x628 +#define EMC_PMACRO_QUSE_DDLL_RANK1_3 0x62c +#define EMC_PMACRO_QUSE_DDLL_RANK1_4 0x630 +#define EMC_PMACRO_QUSE_DDLL_RANK1_5 0x634 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 0x640 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 0x644 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 0x648 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 0x64c +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4 0x650 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5 0x654 + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 0x660 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 0x664 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 0x668 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 0x66c +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4 0x670 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5 0x674 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0 0x680 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1 0x684 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2 0x688 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3 0x68c +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4 0x690 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5 0x694 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0 0x6a0 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1 0x6a4 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2 0x6a8 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3 0x6ac +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4 0x6b0 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5 0x6b4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0 0x6c0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1 0x6c4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2 0x6c8 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3 0x6cc +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_4 0x6d0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_5 0x6d4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0 0x6e0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1 0x6e4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2 0x6e8 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3 0x6ec +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_4 0x6f0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_5 0x6f4 +#define EMC_PMACRO_TX_PWRD_0 0x720 +#define EMC_PMACRO_TX_PWRD_1 0x724 +#define EMC_PMACRO_TX_PWRD_2 0x728 +#define EMC_PMACRO_TX_PWRD_3 0x72c +#define EMC_PMACRO_TX_PWRD_4 0x730 +#define EMC_PMACRO_TX_PWRD_5 0x734 +#define EMC_PMACRO_TX_SEL_CLK_SRC_0 0x740 +#define EMC_PMACRO_TX_SEL_CLK_SRC_1 0x744 +#define EMC_PMACRO_TX_SEL_CLK_SRC_3 0x74c +#define EMC_PMACRO_TX_SEL_CLK_SRC_2 0x748 +#define EMC_PMACRO_TX_SEL_CLK_SRC_4 0x750 +#define EMC_PMACRO_TX_SEL_CLK_SRC_5 0x754 +#define EMC_PMACRO_DDLL_BYPASS 0x760 +#define EMC_PMACRO_DDLL_PWRD_0 0x770 +#define EMC_PMACRO_DDLL_PWRD_1 0x774 +#define EMC_PMACRO_DDLL_PWRD_2 0x778 +#define EMC_PMACRO_CMD_CTRL_0 0x780 +#define EMC_PMACRO_CMD_CTRL_1 0x784 +#define EMC_PMACRO_CMD_CTRL_2 0x788 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0x800 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0x804 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0x808 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3 0x80c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0x810 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0x814 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0x818 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3 0x81c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0x820 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0x824 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0x828 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3 0x82c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0x830 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0x834 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0x838 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3 0x83c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0x840 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0x844 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0x848 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3 0x84c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0x850 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0x854 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0x858 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3 0x85c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0x860 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0x864 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0x868 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3 0x86c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0x870 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0x874 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0x878 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3 0x87c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0 0x880 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1 0x884 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2 0x888 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3 0x88c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0 0x890 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1 0x894 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2 0x898 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3 0x89c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0 0x8a0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1 0x8a4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2 0x8a8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3 0x8ac +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0 0x8b0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1 0x8b4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2 0x8b8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3 0x8bc +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0x900 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0x904 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0x908 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3 0x90c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0x910 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0x914 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0x918 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3 0x91c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0x920 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0x924 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0x928 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3 0x92c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0x930 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0x934 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0x938 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3 0x93c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0x940 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0x944 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0x948 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3 0x94c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0x950 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0x954 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0x958 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3 0x95c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0x960 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0x964 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0x968 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3 0x96c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0x970 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0x974 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0x978 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3 0x97c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0 0x980 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1 0x984 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2 0x988 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3 0x98c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0 0x990 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1 0x994 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2 0x998 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3 0x99c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0 0x9a0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1 0x9a4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2 0x9a8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3 0x9ac +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0 0x9b0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1 0x9b4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2 0x9b8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3 0x9bc +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0xa00 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0xa04 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0xa08 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0xa10 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0xa14 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0xa18 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0xa20 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0xa24 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0xa28 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0xa30 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0xa34 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0xa38 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0xa40 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0xa44 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0xa48 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0xa50 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0xa54 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0xa58 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0xa60 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0xa64 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0xa68 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0xa70 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0xa74 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0xa78 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_0 0xa80 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_1 0xa84 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_2 0xa88 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_0 0xa90 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_1 0xa94 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_2 0xa98 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_0 0xaa0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_1 0xaa4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_2 0xaa8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_0 0xab0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_1 0xab4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_2 0xab8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0xb00 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0xb04 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0xb08 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0xb10 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0xb14 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0xb18 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0xb20 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0xb24 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0xb28 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0xb30 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0xb34 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0xb38 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0xb40 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0xb44 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0xb48 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0xb50 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0xb54 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0xb58 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0xb60 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0xb64 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0xb68 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0xb70 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0xb74 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0xb78 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_0 0xb80 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_1 0xb84 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_2 0xb88 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_0 0xb90 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_1 0xb94 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_2 0xb98 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_0 0xba0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_1 0xba4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_2 0xba8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_0 0xbb0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_1 0xbb4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_2 0xbb8 +#define EMC_PMACRO_IB_VREF_DQ_0 0xbe0 +#define EMC_PMACRO_IB_VREF_DQ_1 0xbe4 +#define EMC_PMACRO_IB_VREF_DQ_2 0xbe8 +#define EMC_PMACRO_IB_VREF_DQS_0 0xbf0 +#define EMC_PMACRO_IB_VREF_DQS_1 0xbf4 +#define EMC_PMACRO_IB_VREF_DQS_2 0xbf8 +#define EMC_PMACRO_IB_RXRT 0xcf4 +#define EMC_PMACRO_DDLL_LONG_CMD_0 0xc00 +#define EMC_PMACRO_DDLL_LONG_CMD_1 0xc04 +#define EMC_PMACRO_DDLL_LONG_CMD_2 0xc08 +#define EMC_PMACRO_DDLL_LONG_CMD_3 0xc0c +#define EMC_PMACRO_DDLL_LONG_CMD_4 0xc10 +#define EMC_PMACRO_DDLL_LONG_CMD_5 0xc14 +#define EMC_PMACRO_DDLL_SHORT_CMD_0 0xc20 +#define EMC_PMACRO_DDLL_SHORT_CMD_1 0xc24 +#define EMC_PMACRO_DDLL_SHORT_CMD_2 0xc28 +#define EMC_PMACRO_CFG_PM_GLOBAL_0 0xc30 +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE0 (1 << 16) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE1 (1 << 17) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE2 (1 << 18) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE3 (1 << 19) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE4 (1 << 20) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE5 (1 << 21) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE6 (1 << 22) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE7 (1 << 23) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD0 (1 << 24) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD1 (1 << 25) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD2 (1 << 26) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD3 (1 << 27) + +#define EMC_PMACRO_VTTGEN_CTRL_0 0xc34 +#define EMC_PMACRO_VTTGEN_CTRL_1 0xc38 +#define EMC_PMACRO_VTTGEN_CTRL_2 0xcf0 +#define EMC_PMACRO_BG_BIAS_CTRL_0 0xc3c +#define EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD (1 << 0) +#define EMC_PMACRO_BG_BIAS_CTRL_0_BG_MODE (1 << 1) +#define EMC_PMACRO_BG_BIAS_CTRL_0_BGLP_E_PWRD (1 << 2) + +#define EMC_PMACRO_PAD_CFG_CTRL 0xc40 +#define EMC_PMACRO_CMD_PAD_RX_CTRL 0xc50 +#define EMC_PMACRO_DATA_PAD_RX_CTRL 0xc54 +#define EMC_PMACRO_CMD_RX_TERM_MODE 0xc58 +#define EMC_PMACRO_DATA_RX_TERM_MODE 0xc5c +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_SHIFT 8 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_SHIFT) +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_SHIFT 4 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_SHIFT) +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_SHIFT 0 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_SHIFT) + +#define RX_TERM_MODE \ + ~(EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_MASK | \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_MASK | \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_MASK) + +#define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60 +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC (1 << 1) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC (1 << 9) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC (1 << 16) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC (1 << 24) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_DRVFORCEON (1 << 26) + +#define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64 +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_E_IVREF (1 << 0) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC (1 << 1) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQS_E_IVREF (1 << 8) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC (1 << 9) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC (1 << 16) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC (1 << 24) + +#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68 +#define EMC_PMACRO_BRICK_MAPPING_0 0xc80 +#define EMC_PMACRO_BRICK_MAPPING_1 0xc84 +#define EMC_PMACRO_BRICK_MAPPING_2 0xc88 +#define EMC_PMACRO_DDLLCAL_CAL 0xce0 +#define EMC_PMACRO_DDLL_OFFSET 0xce4 +#define EMC_PMACRO_DDLL_PERIODIC_OFFSET 0xce8 +#define EMC_PMACRO_BRICK_CTRL_RFU1 0x330 +#define EMC_PMACRO_BRICK_CTRL_RFU2 0x334 +#define EMC_PMACRO_CMD_BRICK_CTRL_FDPD 0x318 +#define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c +#define EMC_PMACRO_TRAINING_CTRL_0 0xcf8 +#define EMC_PMACRO_TRAINING_CTRL_0_CH0_TRAINING_E_WRPTR (1 << 3) + +#define EMC_PMACRO_TRAINING_CTRL_1 0xcfc +#define EMC_PMACRO_TRAINING_CTRL_1_CH1_TRAINING_E_WRPTR (1 << 3) + +#define EMC_PMC_SCRATCH1 0x440 +#define EMC_PMC_SCRATCH2 0x444 +#define EMC_PMC_SCRATCH3 0x448 + +#endif diff --git a/fusee/fusee-secondary/src/emc.h b/fusee/fusee-secondary/src/emc.h new file mode 100644 index 000000000..007559a85 --- /dev/null +++ b/fusee/fusee-secondary/src/emc.h @@ -0,0 +1,1089 @@ +/* + * arch/arm/mach-tegra/tegra21_emc.h + * + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef FUSEE_EMC_H_ +#define FUSEE_EMC_H_ + +#define EMC_BASE 0x7001B000 +#define EMC0_BASE 0x7001E000 +#define EMC1_BASE 0x7001F000 +#define MAKE_EMC_REG(n) MAKE_REG32(EMC_BASE + n) +#define MAKE_EMC0_REG(n) MAKE_REG32(EMC0_BASE + n) +#define MAKE_EMC1_REG(n) MAKE_REG32(EMC1_BASE + n) + +#define EMC_INTSTATUS 0x0 +#define EMC_INTSTATUS_MRR_DIVLD (0x1 << 5) +#define EMC_INTSTATUS_CLKCHANGE_COMPLETE (0x1 << 4) + +#define EMC_INTMASK 0x4 +#define EMC_DBG 0x8 +#define EMC_DBG_WRITE_MUX_ACTIVE (1 << 1) +#define EMC_DBG_CFG_SWAP_SHIFT 26 +#define EMC_DBG_CFG_SWAP_MASK \ + (0x3 << EMC_DBG_CFG_SWAP_SHIFT) +#define EMC_DBG_WRITE_ACTIVE_ONLY (1 << 30) + +#define EMC_CONFIG_SAMPLE_DELAY 0x5f0 +#define EMC_CFG_UPDATE 0x5f4 +#define EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_SHIFT 9 +#define EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_MASK \ + (0x3 << EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_SHIFT) +#define EMC_CFG 0xc +#define EMC_CFG_DRAM_CLKSTOP_PD (1 << 31) +#define EMC_CFG_DRAM_CLKSTOP_SR (1 << 30) +#define EMC_CFG_DRAM_ACPD (1 << 29) +#define EMC_CFG_DYN_SELF_REF (1 << 28) +#define EMC_CFG_REQACT_ASYNC (1 << 26) +#define EMC_CFG_AUTO_PRE_WR (1 << 25) +#define EMC_CFG_AUTO_PRE_RD (1 << 24) +#define EMC_CFG_MAM_PRE_WR (1 << 23) +#define EMC_CFG_MAN_PRE_RD (1 << 22) +#define EMC_CFG_PERIODIC_QRST (1 << 21) +#define EMC_CFG_PERIODIC_QRST_SHIFT (21) +#define EMC_CFG_EN_DYNAMIC_PUTERM (1 << 20) +#define EMC_CFG_DLY_WR_DQ_HALF_CLOCK (1 << 19) +#define EMC_CFG_DSR_VTTGEN_DRV_EN (1 << 18) +#define EMC_CFG_EMC2MC_CLK_RATIO (3 << 16) +#define EMC_CFG_WAIT_FOR_ISP2B_READY_B4_CC (1 << 9) +#define EMC_CFG_WAIT_FOR_VI2_READY_B4_CC (1 << 8) +#define EMC_CFG_WAIT_FOR_ISP2_READY_B4_CC (1 << 7) +#define EMC_CFG_INVERT_DQM (1 << 6) +#define EMC_CFG_WAIT_FOR_DISPLAYB_READY_B4_CC (1 << 5) +#define EMC_CFG_WAIT_FOR_DISPLAY_READY_B4_CC (1 << 4) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2 (1 << 3) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1 (1 << 2) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE (1 << 1) + +#define EMC_ADR_CFG 0x10 +#define EMC_REFCTRL 0x20 +#define EMC_REFCTRL_DEV_SEL_SHIFT 0 +#define EMC_REFCTRL_DEV_SEL_MASK \ + (0x3 << EMC_REFCTRL_DEV_SEL_SHIFT) +#define EMC_REFCTRL_ENABLE (0x1 << 31) +#define EMC_REFCTRL_ENABLE_ALL(num) \ + (((((num) > 1) ? 0 : 2) << EMC_REFCTRL_DEV_SEL_SHIFT) \ + | EMC_REFCTRL_ENABLE) +#define EMC_REFCTRL_DISABLE_ALL(num) \ + ((((num) > 1) ? 0 : 2) << EMC_REFCTRL_DEV_SEL_SHIFT) + +#define EMC_PIN 0x24 +#define EMC_PIN_PIN_CKE_PER_DEV (1 << 2) +#define EMC_PIN_PIN_CKEB (1 << 1) +#define EMC_PIN_PIN_CKE (1 << 0) + +#define EMC_CLK_FORCE_CC_TRIGGER (1 << 27) + +#define EMC_TIMING_CONTROL 0x28 +#define EMC_RC 0x2c +#define EMC_RFC 0x30 +#define EMC_RFCPB 0x590 +#define EMC_RAS 0x34 +#define EMC_RP 0x38 +#define EMC_R2W 0x3c +#define EMC_W2R 0x40 +#define EMC_R2P 0x44 +#define EMC_W2P 0x48 +#define EMC_CCDMW 0x5c0 +#define EMC_RD_RCD 0x4c +#define EMC_WR_RCD 0x50 +#define EMC_RRD 0x54 +#define EMC_REXT 0x58 +#define EMC_WDV 0x5c +#define EMC_QUSE 0x60 +#define EMC_QRST 0x64 +#define EMC_ISSUE_QRST 0x428 +#define EMC_QSAFE 0x68 +#define EMC_RDV 0x6c +#define EMC_REFRESH 0x70 +#define EMC_BURST_REFRESH_NUM 0x74 +#define EMC_PDEX2WR 0x78 +#define EMC_PDEX2RD 0x7c +#define EMC_PDEX2CKE 0x118 +#define EMC_PCHG2PDEN 0x80 +#define EMC_ACT2PDEN 0x84 +#define EMC_AR2PDEN 0x88 +#define EMC_RW2PDEN 0x8c +#define EMC_CKE2PDEN 0x11c +#define EMC_TXSR 0x90 +#define EMC_TCKE 0x94 +#define EMC_TFAW 0x98 +#define EMC_TRPAB 0x9c +#define EMC_TCLKSTABLE 0xa0 +#define EMC_TCLKSTOP 0xa4 +#define EMC_TREFBW 0xa8 +#define EMC_TPPD 0xac +#define EMC_PDEX2MRR 0xb4 +#define EMC_ODT_WRITE 0xb0 +#define EMC_WEXT 0xb8 +#define EMC_RFC_SLR 0xc0 +#define EMC_MRS_WAIT_CNT2 0xc4 +#define EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_SHIFT 16 +#define EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_MASK \ + (0x7ff << EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_SHIFT) +#define EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_SHIFT 0 +#define EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_MASK \ + (0x3ff << EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_SHIFT) + +#define EMC_MRS_WAIT_CNT 0xc8 +#define EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT 0 +#define EMC_MRS_WAIT_CNT_SHORT_WAIT_MASK \ + (0x3FF << EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT) +#define EMC_MRS_WAIT_CNT_LONG_WAIT_SHIFT 16 +#define EMC_MRS_WAIT_CNT_LONG_WAIT_MASK \ + (0x3FF << EMC_MRS_WAIT_CNT_LONG_WAIT_SHIFT) + +#define EMC_MRS 0xcc +#define EMC_MODE_SET_DLL_RESET (1 << 8) +#define EMC_MRS_USE_MRS_LONG_CNT (1 << 26) + +#define EMC_EMRS 0xd0 +#define EMC_EMRS_USE_EMRS_LONG_CNT (1 << 26) + +#define EMC_REF 0xd4 +#define EMC_REF_FORCE_CMD 1 + +#define EMC_PRE 0xd8 +#define EMC_NOP 0xdc +#define EMC_SELF_REF 0xe0 +#define EMC_SELF_REF_CMD_ENABLED (1 << 0) +#define EMC_SELF_REF_ACTIVE_SELF_REF (1 << 8) +#define EMC_SELF_REF_DEV_SEL_SHIFT 30 +#define EMC_SELF_REF_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) + +#define EMC_DPD 0xe4 +#define EMC_MRW 0xe8 +#define EMC_MRW_MRW_OP_SHIFT 0 +#define EMC_MRW_MRW_OP_MASK \ + (0xff << EMC_MRW_MRW_OP_SHIFT) +#define EMC_MRW_MRW_MA_SHIFT 16 +#define EMC_MRW_MRW_MA_MASK \ + (0xff << EMC_MRW_MRW_MA_SHIFT) +#define EMC_MRW_USE_MRW_LONG_CNT 26 +#define EMC_MRW_USE_MRW_EXT_CNT 27 +#define EMC_MRW_MRW_DEV_SELECTN_SHIFT 30 +#define EMC_MRW_MRW_DEV_SELECTN_MASK \ + (0x3 << EMC_MRW_MRW_DEV_SELECTN_SHIFT) + +#define EMC_MRR 0xec +#define EMC_MRR_DEV_SEL_SHIFT 30 +#define EMC_MRR_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) +#define EMC_MRR_MA_SHIFT 16 +#define EMC_MRR_MA_MASK \ + (0xff << EMC_MRR_MA_SHIFT) +#define EMC_MRR_DATA_SHIFT 0 +#define EMC_MRR_DATA_MASK \ + (0xffff << EMC_MRR_DATA_SHIFT) +#define LPDDR2_MR4_TEMP_SHIFT 0 +#define LPDDR2_MR4_TEMP_MASK \ + (0x7 << LPDDR2_MR4_TEMP_SHIFT) + +#define EMC_CMDQ 0xf0 +#define EMC_MC2EMCQ 0xf4 +#define EMC_FBIO_SPARE 0x100 +#define EMC_FBIO_CFG5 0x104 +#define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT 0 +#define EMC_FBIO_CFG5_DRAM_TYPE_MASK \ + (0x3 << EMC_FBIO_CFG5_DRAM_TYPE_SHIFT) +#define EMC_FBIO_CFG5_CMD_TX_DIS (1 << 8) +#define EMC_FBIO_CFG5_CMD_BUS_RETURN_TO_ZERO (1 << 27) + +#define EMC_CFG5_QUSE_MODE_SHIFT 13 +#define EMC_CFG5_QUSE_MODE_MASK \ + (0x7 << EMC_CFG5_QUSE_MODE_SHIFT) + +#define EMC_CFG_RSV 0x120 +#define EMC_ACPD_CONTROL 0x124 +#define EMC_MPC 0x128 +#define EMC_EMRS2 0x12c +#define EMC_EMRS2_USE_EMRS2_LONG_CNT (1 << 26) + +#define EMC_EMRS3 0x130 +#define EMC_MRW2 0x134 +#define EMC_MRW3 0x138 +#define EMC_MRW4 0x13c +#define EMC_MRW5 0x4a0 +#define EMC_MRW6 0x4a4 +#define EMC_MRW7 0x4a8 +#define EMC_MRW8 0x4ac +#define EMC_MRW9 0x4b0 +#define EMC_MRW10 0x4b4 +#define EMC_MRW11 0x4b8 +#define EMC_MRW12 0x4bc +#define EMC_MRW13 0x4c0 +#define EMC_MRW14 0x4c4 +#define EMC_MRW15 0x4d0 +#define EMC_CFG_SYNC 0x4d4 +#define EMC_CLKEN_OVERRIDE 0x140 +#define EMC_R2R 0x144 +#define EMC_W2W 0x148 +#define EMC_EINPUT 0x14c +#define EMC_EINPUT_DURATION 0x150 +#define EMC_PUTERM_EXTRA 0x154 +#define EMC_TCKESR 0x158 +#define EMC_TPD 0x15c +#define EMC_STAT_CONTROL 0x160 +#define EMC_STAT_STATUS 0x164 +#define EMC_STAT_DRAM_CLOCK_LIMIT_LO 0x19c +#define EMC_STAT_DRAM_CLOCK_LIMIT_HI 0x1a0 +#define EMC_STAT_DRAM_CLOCKS_LO 0x1a4 +#define EMC_STAT_DRAM_CLOCKS_HI 0x1a8 +#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_LO 0x1ac +#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_HI 0x1b0 +#define EMC_STAT_DRAM_DEV0_READ_CNT_LO 0x1b4 +#define EMC_STAT_DRAM_DEV0_READ_CNT_HI 0x1b8 +#define EMC_STAT_DRAM_DEV0_READ8_CNT_LO 0x1bc +#define EMC_STAT_DRAM_DEV0_READ8_CNT_HI 0x1c0 +#define EMC_STAT_DRAM_DEV0_WRITE_CNT_LO 0x1c4 +#define EMC_STAT_DRAM_DEV0_WRITE_CNT_HI 0x1c8 +#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_LO 0x1cc +#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_HI 0x1d0 +#define EMC_STAT_DRAM_DEV0_REF_CNT_LO 0x1d4 +#define EMC_STAT_DRAM_DEV0_REF_CNT_HI 0x1d8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1dc +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e0 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1e4 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1ec +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f0 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1f4 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x1fc +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x200 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x204 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x208 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x20c +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x210 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x214 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x218 +#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_LO 0x21c +#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_HI 0x220 +#define EMC_STAT_DRAM_DEV0_DSR 0x224 +#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_LO 0x228 +#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_HI 0x22c +#define EMC_STAT_DRAM_DEV1_READ_CNT_LO 0x230 +#define EMC_STAT_DRAM_DEV1_READ_CNT_HI 0x234 +#define EMC_STAT_DRAM_DEV1_READ8_CNT_LO 0x238 +#define EMC_STAT_DRAM_DEV1_READ8_CNT_HI 0x23c +#define EMC_STAT_DRAM_DEV1_WRITE_CNT_LO 0x240 +#define EMC_STAT_DRAM_DEV1_WRITE_CNT_HI 0x244 +#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_LO 0x248 +#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_HI 0x24c +#define EMC_STAT_DRAM_DEV1_REF_CNT_LO 0x250 +#define EMC_STAT_DRAM_DEV1_REF_CNT_HI 0x254 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x258 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x25c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x260 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x264 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x268 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x26c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x270 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x274 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x278 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x27c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x280 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x284 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x288 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x28c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x290 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x294 +#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_LO 0x298 +#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_HI 0x29c +#define EMC_STAT_DRAM_DEV1_DSR 0x2a0 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc8c +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc90 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc94 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc98 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xc9c +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xca4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca8 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcac +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcb4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb8 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcbc +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcc4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc8 +#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_LO 0xccc +#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_HI 0xcd0 +#define EMC_STAT_DRAM_IO_DSR 0xcd4 +#define EMC_AUTO_CAL_CONFIG 0x2a4 +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_COMPUTE_START (1 << 0) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_MEASURE_STALL (1 << 9) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_UPDATE_STALL (1 << 10) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_ENABLE (1 << 29) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_START (1 << 31) + +#define EMC_AUTO_CAL_CONFIG2 0x458 +#define EMC_AUTO_CAL_CONFIG3 0x45c +#define EMC_AUTO_CAL_CONFIG4 0x5b0 +#define EMC_AUTO_CAL_CONFIG5 0x5b4 +#define EMC_AUTO_CAL_CONFIG6 0x5cc +#define EMC_AUTO_CAL_CONFIG7 0x574 +#define EMC_AUTO_CAL_CONFIG8 0x2dc +#define EMC_AUTO_CAL_VREF_SEL_0 0x2f8 +#define EMC_AUTO_CAL_VREF_SEL_1 0x300 +#define EMC_AUTO_CAL_INTERVAL 0x2a8 +#define EMC_AUTO_CAL_STATUS 0x2ac +#define EMC_AUTO_CAL_STATUS2 0x3d4 +#define EMC_AUTO_CAL_CHANNEL 0x464 +#define EMC_PMACRO_RX_TERM 0xc48 +#define EMC_PMACRO_DQ_TX_DRV 0xc70 +#define EMC_PMACRO_CA_TX_DRV 0xc74 +#define EMC_PMACRO_CMD_TX_DRV 0xc4c +#define EMC_PMACRO_AUTOCAL_CFG_0 0x700 +#define EMC_PMACRO_AUTOCAL_CFG_1 0x704 +#define EMC_PMACRO_AUTOCAL_CFG_2 0x708 +#define EMC_PMACRO_AUTOCAL_CFG_COMMON 0xc78 +#define EMC_PMACRO_AUTOCAL_CFG_COMMON_E_CAL_BYPASS_DVFS (1 << 16) + +#define EMC_PMACRO_ZCTRL 0xc44 +#define EMC_XM2COMPPADCTRL 0x30c +#define EMC_XM2COMPPADCTRL_VREF_CAL_ENABLE (1 << 10) + +#define EMC_XM2COMPPADCTRL2 0x578 +#define EMC_XM2COMPPADCTRL3 0x2f4 +#define EMC_COMP_PAD_SW_CTRL 0x57c +#define EMC_REQ_CTRL 0x2b0 +#define EMC_EMC_STATUS 0x2b4 +#define EMC_EMC_STATUS_MRR_DIVLD (1 << 20) +#define EMC_EMC_STATUS_TIMING_UPDATE_STALLED (1 << 23) +#define EMC_EMC_STATUS_DRAM_IN_POWERDOWN_SHIFT 4 +#define EMC_EMC_STATUS_DRAM_IN_POWERDOWN_MASK \ + (0x3 << EMC_EMC_STATUS_DRAM_IN_POWERDOWN_SHIFT) +#define EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_SHIFT 8 +#define EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK \ + (0x3 << EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_SHIFT) + +#define EMC_CFG_2 0x2b8 +#define EMC_CFG_DIG_DLL 0x2bc +#define EMC_CFG_DIG_DLL_CFG_DLL_EN (1 << 0) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_UNTIL_LOCK (1 << 1) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_TRAFFIC (1 << 3) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_RW_UNTIL_LOCK (1 << 4) +#define EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT 6 +#define EMC_CFG_DIG_DLL_CFG_DLL_MODE_MASK \ + (0x3 << EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT) +#define EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT 8 +#define EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_MASK \ + (0x7 << EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT) + +#define EMC_CFG_DIG_DLL_PERIOD 0x2c0 +#define EMC_DIG_DLL_STATUS 0x2c4 +#define EMC_DIG_DLL_STATUS_DLL_LOCK (1 << 15) +#define EMC_DIG_DLL_STATUS_DLL_PRIV_UPDATED (1 << 17) +#define EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT 0 +#define EMC_DIG_DLL_STATUS_DLL_OUT_MASK \ + (0x7ff << EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT) + +#define EMC_CFG_DIG_DLL_1 0x2c8 +#define EMC_RDV_MASK 0x2cc +#define EMC_WDV_MASK 0x2d0 +#define EMC_RDV_EARLY_MASK 0x2d4 +#define EMC_RDV_EARLY 0x2d8 +#define EMC_WDV_CHK 0x4e0 +#define EMC_ZCAL_INTERVAL 0x2e0 +#define EMC_ZCAL_WAIT_CNT 0x2e4 +#define EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK 0x7ff +#define EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_SHIFT 0 + +#define EMC_ZCAL_MRW_CMD 0x2e8 +#define EMC_ZQ_CAL 0x2ec +#define EMC_ZQ_CAL_DEV_SEL_SHIFT 30 +#define EMC_ZQ_CAL_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) +#define EMC_ZQ_CAL_LONG (1 << 4) +#define EMC_ZQ_CAL_ZQ_LATCH_CMD (1 << 1) +#define EMC_ZQ_CAL_ZQ_CAL_CMD (1 << 0) +#define EMC_ZQ_CAL_LONG_CMD_DEV0 \ + (DRAM_DEV_SEL_0 | EMC_ZQ_CAL_LONG | EMC_ZQ_CAL_CMD) +#define EMC_ZQ_CAL_LONG_CMD_DEV1 \ + (DRAM_DEV_SEL_1 | EMC_ZQ_CAL_LONG | EMC_ZQ_CAL_CMD) + +#define EMC_SCRATCH0 0x324 +#define EMC_STALL_THEN_EXE_BEFORE_CLKCHANGE 0x3c8 +#define EMC_STALL_THEN_EXE_AFTER_CLKCHANGE 0x3cc +#define EMC_UNSTALL_RW_AFTER_CLKCHANGE 0x3d0 +#define EMC_FDPD_CTRL_CMD_NO_RAMP 0x4d8 +#define EMC_FDPD_CTRL_CMD_NO_RAMP_CMD_DPD_NO_RAMP_ENABLE (1 << 0) + +#define EMC_SEL_DPD_CTRL 0x3d8 +#define EMC_SEL_DPD_CTRL_DATA_SEL_DPD_EN (1 << 8) +#define EMC_SEL_DPD_CTRL_ODT_SEL_DPD_EN (1 << 5) +#define EMC_SEL_DPD_CTRL_RESET_SEL_DPD_EN (1 << 4) +#define EMC_SEL_DPD_CTRL_CA_SEL_DPD_EN (1 << 3) +#define EMC_SEL_DPD_CTRL_CLK_SEL_DPD_EN (1 << 2) +#define EMC_SEL_DPD_CTRL_DDR3_MASK \ + ((0xf << 2) | (0x1 << 8)) +#define EMC_SEL_DPD_CTRL_MAS \ + ((0x3 << 2) | (0x1 << 5) | (0x1 << 8)) + +#define EMC_FDPD_CTRL_DQ 0x310 +#define EMC_FDPD_CTRL_CMD 0x314 +#define EMC_PRE_REFRESH_REQ_CNT 0x3dc +#define EMC_REFCTRL2 0x580 +#define EMC_FBIO_CFG7 0x584 +#define EMC_FBIO_CFG7_CH0_ENABLE (1 << 1) +#define EMC_FBIO_CFG7_CH1_ENABLE (1 << 2) + +#define EMC_DATA_BRLSHFT_0 0x588 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT 21 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT 18 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT 15 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT 12 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT 9 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT 6 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT 3 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT 0 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT) + +#define EMC_DATA_BRLSHFT_1 0x58c +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT 21 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT 18 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT 15 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT 12 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT 9 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT 6 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT 3 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT 0 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT) + +#define EMC_DQS_BRLSHFT_0 0x594 +#define EMC_DQS_BRLSHFT_1 0x598 +#define EMC_CMD_BRLSHFT_0 0x59c +#define EMC_CMD_BRLSHFT_1 0x5a0 +#define EMC_CMD_BRLSHFT_2 0x5a4 +#define EMC_CMD_BRLSHFT_3 0x5a8 +#define EMC_QUSE_BRLSHFT_0 0x5ac +#define EMC_QUSE_BRLSHFT_1 0x5b8 +#define EMC_QUSE_BRLSHFT_2 0x5bc +#define EMC_QUSE_BRLSHFT_3 0x5c4 +#define EMC_FBIO_CFG8 0x5c8 +#define EMC_CMD_MAPPING_CMD0_0 0x380 +#define EMC_CMD_MAPPING_CMD0_1 0x384 +#define EMC_CMD_MAPPING_CMD0_2 0x388 +#define EMC_CMD_MAPPING_CMD1_0 0x38c +#define EMC_CMD_MAPPING_CMD1_1 0x390 +#define EMC_CMD_MAPPING_CMD1_2 0x394 +#define EMC_CMD_MAPPING_CMD2_0 0x398 +#define EMC_CMD_MAPPING_CMD2_1 0x39c +#define EMC_CMD_MAPPING_CMD2_2 0x3a0 +#define EMC_CMD_MAPPING_CMD3_0 0x3a4 +#define EMC_CMD_MAPPING_CMD3_1 0x3a8 +#define EMC_CMD_MAPPING_CMD3_2 0x3ac +#define EMC_CMD_MAPPING_BYTE 0x3b0 +#define EMC_DYN_SELF_REF_CONTROL 0x3e0 +#define EMC_TXSRDLL 0x3e4 +#define EMC_CCFIFO_ADDR 0x3e8 +#define EMC_CCFIFO_DATA 0x3ec +#define EMC_CCFIFO_STATUS 0x3f0 +#define EMC_SWIZZLE_RANK0_BYTE0 0x404 +#define EMC_SWIZZLE_RANK0_BYTE1 0x408 +#define EMC_SWIZZLE_RANK0_BYTE2 0x40c +#define EMC_SWIZZLE_RANK0_BYTE3 0x410 +#define EMC_SWIZZLE_RANK1_BYTE0 0x418 +#define EMC_SWIZZLE_RANK1_BYTE1 0x41c +#define EMC_SWIZZLE_RANK1_BYTE2 0x420 +#define EMC_SWIZZLE_RANK1_BYTE3 0x424 +#define EMC_TR_TIMING_0 0x3b4 +#define EMC_TR_CTRL_0 0x3b8 +#define EMC_TR_CTRL_1 0x3bc +#define EMC_TR_DVFS 0x460 +#define EMC_TR_DVFS_TRAINING_DVFS (1 << 0) + +#define EMC_SWITCH_BACK_CTRL 0x3c0 +#define EMC_TR_RDV 0x3c4 +#define EMC_TR_QPOP 0x3f4 +#define EMC_TR_RDV_MASK 0x3f8 +#define EMC_TR_QSAFE 0x3fc +#define EMC_TR_QRST 0x400 +#define EMC_IBDLY 0x468 +#define EMC_OBDLY 0x46c +#define EMC_TXDSRVTTGEN 0x480 +#define EMC_WE_DURATION 0x48c +#define EMC_WS_DURATION 0x490 +#define EMC_WEV 0x494 +#define EMC_WSV 0x498 +#define EMC_CFG_3 0x49c +#define EMC_CFG_PIPE_2 0x554 +#define EMC_CFG_PIPE_CLK 0x558 +#define EMC_CFG_PIPE_CLK_CLK_ALWAYS_ON (1 << 0) + +#define EMC_CFG_PIPE_1 0x55c +#define EMC_CFG_PIPE 0x560 +#define EMC_QPOP 0x564 +#define EMC_QUSE_WIDTH 0x568 +#define EMC_PUTERM_WIDTH 0x56c +#define EMC_PROTOBIST_CONFIG_ADR_1 0x5d0 +#define EMC_PROTOBIST_CONFIG_ADR_2 0x5d4 +#define EMC_PROTOBIST_MISC 0x5d8 +#define EMC_PROTOBIST_WDATA_LOWER 0x5dc +#define EMC_PROTOBIST_WDATA_UPPER 0x5e0 +#define EMC_PROTOBIST_RDATA 0x5ec +#define EMC_DLL_CFG_0 0x5e4 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_IGNORE_START (1 << 29) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_DUAL_PASS_LOCK (1 << 28) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_SHIFT 24 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_SHIFT 20 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_SHIFT 16 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_SHIFT 12 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_SHIFT 4 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_MASK \ + (0xff << EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_SHIFT 0 +#define EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_SHIFT) + +#define EMC_DLL_CFG_1 0x5e8 +#define EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_SHIFT 10 +#define EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_MASK \ + (0x7ff << EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_SHIFT) + +#define EMC_TRAINING_CMD 0xe00 +#define EMC_TRAINING_CMD_PRIME (1 << 0) +#define EMC_TRAINING_CMD_CA (1 << 1) +#define EMC_TRAINING_CMD_RD (1 << 2) +#define EMC_TRAINING_CMD_WR (1 << 3) +#define EMC_TRAINING_CMD_QUSE (1 << 4) +#define EMC_TRAINING_CMD_CA_VREF (1 << 5) +#define EMC_TRAINING_CMD_RD_VREF (1 << 6) +#define EMC_TRAINING_CMD_WR_VREF (1 << 7) +#define EMC_TRAINING_CMD_QUSE_VREF (1 << 8) +#define EMC_TRAINING_CMD_GO (1 << 31) + +#define EMC_TRAINING_CTRL 0xe04 +#define EMC_TRAINING_CTRL_SWAP_RANK (1 << 14) + +#define EMC_TRAINING_STATUS 0xe08 +#define EMC_TRAINING_QUSE_CORS_CTRL 0xe0c +#define EMC_TRAINING_QUSE_FINE_CTRL 0xe10 +#define EMC_TRAINING_QUSE_CTRL_MISC 0xe14 +#define EMC_TRAINING_WRITE_FINE_CTRL 0xe18 +#define EMC_TRAINING_WRITE_CTRL_MISC 0xe1c +#define EMC_TRAINING_WRITE_VREF_CTRL 0xe20 +#define EMC_TRAINING_READ_FINE_CTRL 0xe24 +#define EMC_TRAINING_READ_CTRL_MISC 0xe28 +#define EMC_TRAINING_READ_VREF_CTRL 0xe2c +#define EMC_TRAINING_CA_FINE_CTRL 0xe30 +#define EMC_TRAINING_CA_CTRL_MISC 0xe34 +#define EMC_TRAINING_CA_CTRL_MISC1 0xe38 +#define EMC_TRAINING_CA_VREF_CTRL 0xe3c +#define EMC_TRAINING_CA_TADR_CTRL 0xe40 +#define EMC_TRAINING_SETTLE 0xe44 +#define EMC_TRAINING_DEBUG_CTRL 0xe48 +#define EMC_TRAINING_DEBUG_DQ0 0xe4c +#define EMC_TRAINING_DEBUG_DQ1 0xe50 +#define EMC_TRAINING_DEBUG_DQ2 0xe54 +#define EMC_TRAINING_DEBUG_DQ3 0xe58 +#define EMC_TRAINING_MPC 0xe5c +#define EMC_TRAINING_PATRAM_CTRL 0xe60 +#define EMC_TRAINING_PATRAM_DQ 0xe64 +#define EMC_TRAINING_PATRAM_DMI 0xe68 +#define EMC_TRAINING_VREF_SETTLE 0xe6c +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE0 0xe70 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE1 0xe74 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE2 0xe78 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE3 0xe7c +#define EMC_TRAINING_RW_EYE_CENTER_IB_MISC 0xe80 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE0 0xe84 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE1 0xe88 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE2 0xe8c +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE3 0xe90 +#define EMC_TRAINING_RW_EYE_CENTER_OB_MISC 0xe94 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE0 0xe98 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE1 0xe9c +#define EMC_TRAINING_RW_OFFSET_IB_BYTE2 0xea0 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE3 0xea4 +#define EMC_TRAINING_RW_OFFSET_IB_MISC 0xea8 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE0 0xeac +#define EMC_TRAINING_RW_OFFSET_OB_BYTE1 0xeb0 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE2 0xeb4 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE3 0xeb8 +#define EMC_TRAINING_RW_OFFSET_OB_MISC 0xebc +#define EMC_TRAINING_OPT_CA_VREF 0xec0 +#define EMC_TRAINING_OPT_DQ_OB_VREF 0xec4 +#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK0 0xec8 +#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK1 0xecc +#define EMC_TRAINING_QUSE_VREF_CTRL 0xed0 +#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4 +#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8 +#define EMC_TRAINING_DRAMC_TIMING 0xedc +#define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600 +#define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604 +#define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608 +#define EMC_PMACRO_QUSE_DDLL_RANK0_3 0x60c +#define EMC_PMACRO_QUSE_DDLL_RANK0_4 0x610 +#define EMC_PMACRO_QUSE_DDLL_RANK0_5 0x614 +#define EMC_PMACRO_QUSE_DDLL_RANK1_0 0x620 +#define EMC_PMACRO_QUSE_DDLL_RANK1_1 0x624 +#define EMC_PMACRO_QUSE_DDLL_RANK1_2 0x628 +#define EMC_PMACRO_QUSE_DDLL_RANK1_3 0x62c +#define EMC_PMACRO_QUSE_DDLL_RANK1_4 0x630 +#define EMC_PMACRO_QUSE_DDLL_RANK1_5 0x634 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 0x640 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 0x644 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 0x648 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 0x64c +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4 0x650 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5 0x654 + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 0x660 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 0x664 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 0x668 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 0x66c +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4 0x670 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5 0x674 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0 0x680 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1 0x684 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2 0x688 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3 0x68c +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4 0x690 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5 0x694 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0 0x6a0 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1 0x6a4 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2 0x6a8 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3 0x6ac +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4 0x6b0 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5 0x6b4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0 0x6c0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1 0x6c4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2 0x6c8 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3 0x6cc +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_4 0x6d0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_5 0x6d4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0 0x6e0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1 0x6e4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2 0x6e8 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3 0x6ec +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_4 0x6f0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_5 0x6f4 +#define EMC_PMACRO_TX_PWRD_0 0x720 +#define EMC_PMACRO_TX_PWRD_1 0x724 +#define EMC_PMACRO_TX_PWRD_2 0x728 +#define EMC_PMACRO_TX_PWRD_3 0x72c +#define EMC_PMACRO_TX_PWRD_4 0x730 +#define EMC_PMACRO_TX_PWRD_5 0x734 +#define EMC_PMACRO_TX_SEL_CLK_SRC_0 0x740 +#define EMC_PMACRO_TX_SEL_CLK_SRC_1 0x744 +#define EMC_PMACRO_TX_SEL_CLK_SRC_3 0x74c +#define EMC_PMACRO_TX_SEL_CLK_SRC_2 0x748 +#define EMC_PMACRO_TX_SEL_CLK_SRC_4 0x750 +#define EMC_PMACRO_TX_SEL_CLK_SRC_5 0x754 +#define EMC_PMACRO_DDLL_BYPASS 0x760 +#define EMC_PMACRO_DDLL_PWRD_0 0x770 +#define EMC_PMACRO_DDLL_PWRD_1 0x774 +#define EMC_PMACRO_DDLL_PWRD_2 0x778 +#define EMC_PMACRO_CMD_CTRL_0 0x780 +#define EMC_PMACRO_CMD_CTRL_1 0x784 +#define EMC_PMACRO_CMD_CTRL_2 0x788 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0x800 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0x804 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0x808 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3 0x80c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0x810 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0x814 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0x818 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3 0x81c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0x820 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0x824 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0x828 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3 0x82c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0x830 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0x834 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0x838 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3 0x83c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0x840 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0x844 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0x848 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3 0x84c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0x850 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0x854 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0x858 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3 0x85c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0x860 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0x864 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0x868 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3 0x86c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0x870 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0x874 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0x878 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3 0x87c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0 0x880 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1 0x884 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2 0x888 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3 0x88c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0 0x890 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1 0x894 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2 0x898 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3 0x89c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0 0x8a0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1 0x8a4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2 0x8a8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3 0x8ac +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0 0x8b0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1 0x8b4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2 0x8b8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3 0x8bc +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0x900 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0x904 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0x908 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3 0x90c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0x910 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0x914 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0x918 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3 0x91c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0x920 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0x924 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0x928 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3 0x92c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0x930 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0x934 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0x938 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3 0x93c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0x940 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0x944 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0x948 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3 0x94c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0x950 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0x954 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0x958 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3 0x95c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0x960 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0x964 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0x968 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3 0x96c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0x970 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0x974 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0x978 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3 0x97c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0 0x980 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1 0x984 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2 0x988 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3 0x98c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0 0x990 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1 0x994 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2 0x998 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3 0x99c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0 0x9a0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1 0x9a4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2 0x9a8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3 0x9ac +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0 0x9b0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1 0x9b4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2 0x9b8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3 0x9bc +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0xa00 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0xa04 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0xa08 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0xa10 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0xa14 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0xa18 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0xa20 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0xa24 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0xa28 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0xa30 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0xa34 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0xa38 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0xa40 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0xa44 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0xa48 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0xa50 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0xa54 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0xa58 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0xa60 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0xa64 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0xa68 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0xa70 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0xa74 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0xa78 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_0 0xa80 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_1 0xa84 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_2 0xa88 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_0 0xa90 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_1 0xa94 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_2 0xa98 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_0 0xaa0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_1 0xaa4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_2 0xaa8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_0 0xab0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_1 0xab4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_2 0xab8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0xb00 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0xb04 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0xb08 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0xb10 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0xb14 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0xb18 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0xb20 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0xb24 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0xb28 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0xb30 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0xb34 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0xb38 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0xb40 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0xb44 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0xb48 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0xb50 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0xb54 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0xb58 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0xb60 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0xb64 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0xb68 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0xb70 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0xb74 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0xb78 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_0 0xb80 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_1 0xb84 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_2 0xb88 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_0 0xb90 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_1 0xb94 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_2 0xb98 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_0 0xba0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_1 0xba4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_2 0xba8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_0 0xbb0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_1 0xbb4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_2 0xbb8 +#define EMC_PMACRO_IB_VREF_DQ_0 0xbe0 +#define EMC_PMACRO_IB_VREF_DQ_1 0xbe4 +#define EMC_PMACRO_IB_VREF_DQ_2 0xbe8 +#define EMC_PMACRO_IB_VREF_DQS_0 0xbf0 +#define EMC_PMACRO_IB_VREF_DQS_1 0xbf4 +#define EMC_PMACRO_IB_VREF_DQS_2 0xbf8 +#define EMC_PMACRO_IB_RXRT 0xcf4 +#define EMC_PMACRO_DDLL_LONG_CMD_0 0xc00 +#define EMC_PMACRO_DDLL_LONG_CMD_1 0xc04 +#define EMC_PMACRO_DDLL_LONG_CMD_2 0xc08 +#define EMC_PMACRO_DDLL_LONG_CMD_3 0xc0c +#define EMC_PMACRO_DDLL_LONG_CMD_4 0xc10 +#define EMC_PMACRO_DDLL_LONG_CMD_5 0xc14 +#define EMC_PMACRO_DDLL_SHORT_CMD_0 0xc20 +#define EMC_PMACRO_DDLL_SHORT_CMD_1 0xc24 +#define EMC_PMACRO_DDLL_SHORT_CMD_2 0xc28 +#define EMC_PMACRO_CFG_PM_GLOBAL_0 0xc30 +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE0 (1 << 16) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE1 (1 << 17) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE2 (1 << 18) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE3 (1 << 19) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE4 (1 << 20) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE5 (1 << 21) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE6 (1 << 22) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE7 (1 << 23) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD0 (1 << 24) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD1 (1 << 25) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD2 (1 << 26) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD3 (1 << 27) + +#define EMC_PMACRO_VTTGEN_CTRL_0 0xc34 +#define EMC_PMACRO_VTTGEN_CTRL_1 0xc38 +#define EMC_PMACRO_VTTGEN_CTRL_2 0xcf0 +#define EMC_PMACRO_BG_BIAS_CTRL_0 0xc3c +#define EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD (1 << 0) +#define EMC_PMACRO_BG_BIAS_CTRL_0_BG_MODE (1 << 1) +#define EMC_PMACRO_BG_BIAS_CTRL_0_BGLP_E_PWRD (1 << 2) + +#define EMC_PMACRO_PAD_CFG_CTRL 0xc40 +#define EMC_PMACRO_CMD_PAD_RX_CTRL 0xc50 +#define EMC_PMACRO_DATA_PAD_RX_CTRL 0xc54 +#define EMC_PMACRO_CMD_RX_TERM_MODE 0xc58 +#define EMC_PMACRO_DATA_RX_TERM_MODE 0xc5c +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_SHIFT 8 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_SHIFT) +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_SHIFT 4 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_SHIFT) +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_SHIFT 0 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_SHIFT) + +#define RX_TERM_MODE \ + ~(EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_MASK | \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_MASK | \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_MASK) + +#define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60 +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC (1 << 1) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC (1 << 9) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC (1 << 16) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC (1 << 24) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_DRVFORCEON (1 << 26) + +#define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64 +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_E_IVREF (1 << 0) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC (1 << 1) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQS_E_IVREF (1 << 8) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC (1 << 9) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC (1 << 16) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC (1 << 24) + +#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68 +#define EMC_PMACRO_BRICK_MAPPING_0 0xc80 +#define EMC_PMACRO_BRICK_MAPPING_1 0xc84 +#define EMC_PMACRO_BRICK_MAPPING_2 0xc88 +#define EMC_PMACRO_DDLLCAL_CAL 0xce0 +#define EMC_PMACRO_DDLL_OFFSET 0xce4 +#define EMC_PMACRO_DDLL_PERIODIC_OFFSET 0xce8 +#define EMC_PMACRO_BRICK_CTRL_RFU1 0x330 +#define EMC_PMACRO_BRICK_CTRL_RFU2 0x334 +#define EMC_PMACRO_CMD_BRICK_CTRL_FDPD 0x318 +#define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c +#define EMC_PMACRO_TRAINING_CTRL_0 0xcf8 +#define EMC_PMACRO_TRAINING_CTRL_0_CH0_TRAINING_E_WRPTR (1 << 3) + +#define EMC_PMACRO_TRAINING_CTRL_1 0xcfc +#define EMC_PMACRO_TRAINING_CTRL_1_CH1_TRAINING_E_WRPTR (1 << 3) + +#define EMC_PMC_SCRATCH1 0x440 +#define EMC_PMC_SCRATCH2 0x444 +#define EMC_PMC_SCRATCH3 0x448 + +#endif diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 753efc0aa..20654509d 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -26,6 +26,7 @@ #include "loader.h" #include "chainloader.h" #include "stage2.h" +#include "mtc.h" #include "nxboot.h" #include "console.h" #include "fs_utils.h" @@ -52,6 +53,9 @@ static void setup_env(void) { if (nxfs_mount_all() < 0) { fatal_error("Failed to mount at least one parition: %s\n", strerror(errno)); } + + /* Train DRAM. */ + train_dram(); } static void cleanup_env(void) { diff --git a/fusee/fusee-secondary/src/mtc.c b/fusee/fusee-secondary/src/mtc.c new file mode 100644 index 000000000..65fee468c --- /dev/null +++ b/fusee/fusee-secondary/src/mtc.c @@ -0,0 +1,3750 @@ +/* + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 CTCaer <ctcaer@gmail.com> + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "mtc.h" +#include "mtc_tables.h" +#include "car.h" +#include "fuse.h" +#include "timers.h" +#include "lib/log.h" + +/* + * Macros. + */ +#define max(x, y) ({ \ + typeof(x) _max1 = (x); \ + typeof(y) _max2 = (y); \ + (void) (&_max1 == &_max2); \ + _max1 > _max2 ? _max1 : _max2; }) + +#define max_t(type, x, y) ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1: __max2; }) + +#define TRIM_REG(chan, rank, reg, byte) \ + ((EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## reg ## \ + _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte ## _MASK & \ + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## \ + rank ## _ ## reg ## _INDEX]) >> \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## reg ## \ + _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte ## _SHIFT) \ + + \ + (((EMC_DATA_BRLSHFT_ ## rank ## _RANK ## rank ## _BYTE ## \ + byte ## _DATA_BRLSHFT_MASK & \ + next_timing->trim_perch_regs[REG_EMC ## chan ## \ + _EMC_DATA_BRLSHFT_ ## rank ## _INDEX]) >> \ + EMC_DATA_BRLSHFT_ ## rank ## _RANK ## rank ## _BYTE ## \ + byte ## _DATA_BRLSHFT_SHIFT) * 64) + +#define CALC_TEMP(rank, reg, byte1, byte2, n) \ + ((new[n] << EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## \ + reg ## _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte1 ## _SHIFT) & \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## reg ## \ + _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte1 ## _MASK) \ + | \ + ((new[n + 1] << EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## \ + reg ## _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte2 ## _SHIFT) & \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK ## rank ## _ ## reg ## \ + _OB_DDLL_LONG_DQ_RANK ## rank ## _BYTE ## byte2 ## _MASK) \ + +/* + * PTFV defines - basically just indexes into the per table PTFV array. + */ +#define PTFV_DQSOSC_MOVAVG_C0D0U0_INDEX 0 +#define PTFV_DQSOSC_MOVAVG_C0D0U1_INDEX 1 +#define PTFV_DQSOSC_MOVAVG_C0D1U0_INDEX 2 +#define PTFV_DQSOSC_MOVAVG_C0D1U1_INDEX 3 +#define PTFV_DQSOSC_MOVAVG_C1D0U0_INDEX 4 +#define PTFV_DQSOSC_MOVAVG_C1D0U1_INDEX 5 +#define PTFV_DQSOSC_MOVAVG_C1D1U0_INDEX 6 +#define PTFV_DQSOSC_MOVAVG_C1D1U1_INDEX 7 +#define PTFV_WRITE_SAMPLES_INDEX 8 +#define PTFV_DVFS_SAMPLES_INDEX 9 +#define PTFV_MOVAVG_WEIGHT_INDEX 10 +#define PTFV_CONFIG_CTRL_INDEX 11 + +#define PTFV_CONFIG_CTRL_USE_PREVIOUS_EMA (1 << 0) + +/* + * Do arithmetic in fixed point. + */ +#define MOVAVG_PRECISION_FACTOR 100 + +/* + * The division portion of the average operation. + */ +#define __AVERAGE_PTFV(dev) \ + ({ next_timing->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] = \ + next_timing->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] / \ + next_timing->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; }) + +/* + * The division portion of the average write operation. + */ +#define __AVERAGE_WRITE_PTFV(dev) \ + ({ next_timing->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] = \ + next_timing->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] / \ + next_timing->ptfv_list[PTFV_WRITE_SAMPLES_INDEX]; }) + +/* + * Convert val to fixed point and add it to the temporary average. + */ +#define __INCREMENT_PTFV(dev, val) \ + ({ next_timing->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] += \ + ((val) * MOVAVG_PRECISION_FACTOR); }) + +/* + * Convert a moving average back to integral form and return the value. + */ +#define __MOVAVG_AC(timing, dev) \ + ((timing)->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX] / \ + MOVAVG_PRECISION_FACTOR) + +/* Weighted update. */ +#define __WEIGHTED_UPDATE_PTFV(dev, nval) \ + do { \ + int w = PTFV_MOVAVG_WEIGHT_INDEX; \ + int dqs = PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX; \ + \ + next_timing->ptfv_list[dqs] = \ + ((nval * MOVAVG_PRECISION_FACTOR) + \ + (next_timing->ptfv_list[dqs] * \ + next_timing->ptfv_list[w])) / \ + (next_timing->ptfv_list[w] + 1); \ + } while (0) + +/* Access a particular average. */ +#define __MOVAVG(timing, dev) \ + ((timing)->ptfv_list[PTFV_DQSOSC_MOVAVG_ ## dev ## _INDEX]) + +static int g_active_timing_table_idx = -1; +static bool g_is_pllmb = false; +static bool g_fsp_for_next_freq = false; +static bool g_write_training_pattern = true; + +#define DEFINE_REG(type, reg) (reg) +static const uint32_t burst_regs_per_ch_off[] = BURST_REGS_PER_CH_LIST; +static const uint32_t burst_regs_off[] = BURST_REGS_LIST; +static const uint32_t trim_regs_per_ch_off[] = TRIM_REGS_PER_CH_LIST; +static const uint32_t trim_regs_off[] = TRIM_REGS_LIST; +static const uint32_t vref_regs_per_ch_off[] = VREF_REGS_PER_CH_LIST; +static const uint32_t training_mod_regs_per_ch_off[] = TRAINING_MOD_REGS_PER_CH_LIST; +static const uint32_t burst_mc_regs_off[] = BURST_MC_REGS_LIST; +static const uint32_t la_scale_regs_off[] = BURST_UP_DOWN_REGS_LIST; +#undef DEFINE_REG + +#define DEFINE_REG(type, reg) (type) +static const uint32_t burst_regs_per_ch_type[] = BURST_REGS_PER_CH_LIST; +static const uint32_t trim_regs_per_ch_type[] = TRIM_REGS_PER_CH_LIST; +static const uint32_t vref_regs_per_ch_type[] = VREF_REGS_PER_CH_LIST; +static const uint32_t training_mod_regs_per_ch_type[] = TRAINING_MOD_REGS_PER_CH_LIST; +#undef DEFINE_REG + +static const uint32_t g_ram_pattern_dq[0x500] = { + 0x18181818, 0x61616161, 0x85858585, 0x14141414, 0x51515151, + 0x47474747, 0x1E1E1E1E, 0x79797979, 0xE5E5E5E5, 0x94949494, + 0x51515151, 0x46464646, 0x19191919, 0x67676767, 0x9C9C9C9C, + 0x71717171, 0xC5C5C5C5, 0x17171717, 0x5F5F5F5F, 0x7E7E7E7E, + 0xFBFBFBFB, 0xEDEDEDED, 0xB4B4B4B4, 0xD2D2D2D2, 0x48484848, + 0x21212121, 0x85858585, 0x16161616, 0x59595959, 0x66666666, + 0x9A9A9A9A, 0x69696969, 0xA4A4A4A4, 0x93939393, 0x4F4F4F4F, + 0x3F3F3F3F, 0xFCFCFCFC, 0xF3F3F3F3, 0xCDCDCDCD, 0x37373737, + 0xDCDCDCDC, 0x70707070, 0xC3C3C3C3, 0x0F0F0F0F, 0x3E3E3E3E, + 0xFAFAFAFA, 0xEBEBEBEB, 0xACACACAC, 0xB3B3B3B3, 0xCCCCCCCC, + 0x31313131, 0xC5C5C5C5, 0x15151515, 0x57575757, 0x5F5F5F5F, + 0x7F7F7F7F, 0xFDFDFDFD, 0xF4F4F4F4, 0xD0D0D0D0, 0x42424242, + 0x08080808, 0x23232323, 0x8F8F8F8F, 0x3F3F3F3F, 0x18181818, + 0x61616161, 0x85858585, 0x14141414, 0x51515151, 0x47474747, + 0x1E1E1E1E, 0x79797979, 0xE5E5E5E5, 0x94949494, 0x51515151, + 0x46464646, 0x19191919, 0x67676767, 0x9C9C9C9C, 0x71717171, + 0xC5C5C5C5, 0x17171717, 0x5F5F5F5F, 0x7E7E7E7E, 0xFBFBFBFB, + 0xEDEDEDED, 0xB4B4B4B4, 0xD2D2D2D2, 0x48484848, 0x21212121, + 0x85858585, 0x16161616, 0x59595959, 0x66666666, 0x9A9A9A9A, + 0x69696969, 0xA4A4A4A4, 0x93939393, 0x4F4F4F4F, 0x3F3F3F3F, + 0xFCFCFCFC, 0xF3F3F3F3, 0xCDCDCDCD, 0x37373737, 0xDCDCDCDC, + 0x70707070, 0xC3C3C3C3, 0x0F0F0F0F, 0x3E3E3E3E, 0xFAFAFAFA, + 0xEBEBEBEB, 0xACACACAC, 0xB3B3B3B3, 0xCCCCCCCC, 0x31313131, + 0xC5C5C5C5, 0x15151515, 0x57575757, 0x5F5F5F5F, 0x7F7F7F7F, + 0xFDFDFDFD, 0xF4F4F4F4, 0xD0D0D0D0, 0x42424242, 0x08080808, + 0x23232323, 0x8F8F8F8F, 0x3F3F3F3F, 0x06060606, 0x18181818, + 0x21212121, 0x05050505, 0x14141414, 0x11111111, 0x07070707, + 0x1E1E1E1E, 0x39393939, 0x25252525, 0x14141414, 0x11111111, + 0x06060606, 0x19191919, 0x27272727, 0x1C1C1C1C, 0x31313131, + 0x05050505, 0x17171717, 0x1F1F1F1F, 0x3E3E3E3E, 0x3B3B3B3B, + 0x2D2D2D2D, 0x34343434, 0x12121212, 0x08080808, 0x21212121, + 0x05050505, 0x16161616, 0x19191919, 0x26262626, 0x1A1A1A1A, + 0x29292929, 0x24242424, 0x13131313, 0x0F0F0F0F, 0x3F3F3F3F, + 0x3C3C3C3C, 0x33333333, 0x0D0D0D0D, 0x37373737, 0x1C1C1C1C, + 0x30303030, 0x03030303, 0x0F0F0F0F, 0x3E3E3E3E, 0x3A3A3A3A, + 0x2B2B2B2B, 0x2C2C2C2C, 0x33333333, 0x0C0C0C0C, 0x31313131, + 0x05050505, 0x15151515, 0x17171717, 0x1F1F1F1F, 0x3F3F3F3F, + 0x3D3D3D3D, 0x34343434, 0x10101010, 0x02020202, 0x08080808, + 0x23232323, 0x0F0F0F0F, 0x06060606, 0x18181818, 0x21212121, + 0x05050505, 0x14141414, 0x11111111, 0x07070707, 0x1E1E1E1E, + 0x39393939, 0x25252525, 0x14141414, 0x11111111, 0x06060606, + 0x19191919, 0x27272727, 0x1C1C1C1C, 0x31313131, 0x05050505, + 0x17171717, 0x1F1F1F1F, 0x3E3E3E3E, 0x3B3B3B3B, 0x2D2D2D2D, + 0x34343434, 0x12121212, 0x08080808, 0x21212121, 0x05050505, + 0x16161616, 0x19191919, 0x26262626, 0x1A1A1A1A, 0x29292929, + 0x24242424, 0x13131313, 0x0F0F0F0F, 0x3F3F3F3F, 0x3C3C3C3C, + 0x33333333, 0x0D0D0D0D, 0x37373737, 0x1C1C1C1C, 0x30303030, + 0x03030303, 0x0F0F0F0F, 0x3E3E3E3E, 0x3A3A3A3A, 0x2B2B2B2B, + 0x2C2C2C2C, 0x33333333, 0x0C0C0C0C, 0x31313131, 0x05050505, + 0x15151515, 0x17171717, 0x1F1F1F1F, 0x3F3F3F3F, 0x3D3D3D3D, + 0x34343434, 0x10101010, 0x02020202, 0x08080808, 0x23232323, + 0x0F0F0F0F, + + 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x3F3F3F3F, 0x3F3F3F3F, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x00000000, 0x00000000, 0x3F3F3F3F, 0x3F3F3F3F, + 0x3F3F3F3F, 0x3F3F3F3F, 0x00000000, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x00000000, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x3F3F3F3F, 0x00000000, 0x00000000, 0x3F3F3F3F, + 0x3F3F3F3F, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x00000000, 0x3F3F3F3F, 0x3F3F3F3F, + 0x3F3F3F3F, 0x3F3F3F3F, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3F3F3F3F, + 0x3F3F3F3F, 0x3F3F3F3F, 0x00000000, 0x00000000, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x00000000, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3F3F3F3F, 0x3F3F3F3F, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x00000000, 0x00000000, 0x3F3F3F3F, 0x3F3F3F3F, 0x3F3F3F3F, + 0x3F3F3F3F, 0x00000000, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x00000000, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x3F3F3F3F, 0x00000000, 0x00000000, 0x3F3F3F3F, 0x3F3F3F3F, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x00000000, 0x3F3F3F3F, 0x3F3F3F3F, 0x3F3F3F3F, + 0x3F3F3F3F, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x3F3F3F3F, 0x3F3F3F3F, + 0x3F3F3F3F, 0x00000000, 0x00000000, 0x00000000, 0x3F3F3F3F, + 0x00000000, + + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, + 0x00000000, 0x3F3F3F3F, 0x00000000, 0x3F3F3F3F, 0x00000000, + 0x3F3F3F3F, + + 0x80808080, 0x00000000, 0x80808080, 0x00000000, 0x80808080, + 0x00000000, 0x80808080, 0x40404040, 0x00000000, 0x40404040, + 0x00000000, 0x40404040, 0x00000000, 0x40404040, 0x20202020, + 0x00000000, 0x20202020, 0x00000000, 0x20202020, 0x00000000, + 0x20202020, 0x10101010, 0x00000000, 0x10101010, 0x00000000, + 0x10101010, 0x00000000, 0x10101010, 0x08080808, 0x00000000, + 0x08080808, 0x00000000, 0x08080808, 0x00000000, 0x08080808, + 0x04040404, 0x00000000, 0x04040404, 0x00000000, 0x04040404, + 0x00000000, 0x04040404, 0x02020202, 0x00000000, 0x02020202, + 0x00000000, 0x02020202, 0x00000000, 0x02020202, 0x01010101, + 0x00000000, 0x01010101, 0x00000000, 0x01010101, 0x00000000, + 0x01010101, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80808080, + 0x00000000, 0x80808080, 0x00000000, 0x80808080, 0x00000000, + 0x80808080, 0x40404040, 0x00000000, 0x40404040, 0x00000000, + 0x40404040, 0x00000000, 0x40404040, 0x20202020, 0x00000000, + 0x20202020, 0x00000000, 0x20202020, 0x00000000, 0x20202020, + 0x10101010, 0x00000000, 0x10101010, 0x00000000, 0x10101010, + 0x00000000, 0x10101010, 0x08080808, 0x00000000, 0x08080808, + 0x00000000, 0x08080808, 0x00000000, 0x08080808, 0x04040404, + 0x00000000, 0x04040404, 0x00000000, 0x04040404, 0x00000000, + 0x04040404, 0x02020202, 0x00000000, 0x02020202, 0x00000000, + 0x02020202, 0x00000000, 0x02020202, 0x01010101, 0x00000000, + 0x01010101, 0x00000000, 0x01010101, 0x00000000, 0x01010101, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x20202020, + 0x00000000, 0x20202020, 0x00000000, 0x20202020, 0x00000000, + 0x20202020, 0x00000000, 0x20202020, 0x00000000, 0x10101010, + 0x00000000, 0x10101010, 0x00000000, 0x10101010, 0x00000000, + 0x10101010, 0x00000000, 0x10101010, 0x00000000, 0x08080808, + 0x00000000, 0x08080808, 0x00000000, 0x08080808, 0x00000000, + 0x08080808, 0x00000000, 0x08080808, 0x00000000, 0x04040404, + 0x00000000, 0x04040404, 0x00000000, 0x04040404, 0x00000000, + 0x04040404, 0x00000000, 0x04040404, 0x00000000, 0x02020202, + 0x00000000, 0x02020202, 0x00000000, 0x02020202, 0x00000000, + 0x02020202, 0x00000000, 0x02020202, 0x00000000, 0x01010101, + 0x00000000, 0x01010101, 0x00000000, 0x01010101, 0x00000000, + 0x01010101, 0x00000000, 0x01010101, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x20202020, 0x00000000, + 0x20202020, 0x00000000, 0x20202020, 0x00000000, 0x20202020, + 0x00000000, 0x20202020, 0x00000000, 0x10101010, 0x00000000, + 0x10101010, 0x00000000, 0x10101010, 0x00000000, 0x10101010, + 0x00000000, 0x10101010, 0x00000000, 0x08080808, 0x00000000, + 0x08080808, 0x00000000, 0x08080808, 0x00000000, 0x08080808, + 0x00000000, 0x08080808, 0x00000000, 0x04040404, 0x00000000, + 0x04040404, 0x00000000, 0x04040404, 0x00000000, 0x04040404, + 0x00000000, 0x04040404, 0x00000000, 0x02020202, 0x00000000, + 0x02020202, 0x00000000, 0x02020202, 0x00000000, 0x02020202, + 0x00000000, 0x02020202, 0x00000000, 0x01010101, 0x00000000, + 0x01010101, 0x00000000, 0x01010101, 0x00000000, 0x01010101, + 0x00000000, 0x01010101, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, + + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, + 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, + 0x55555555, 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, + 0xCCCCCCCC, 0x33333333, 0xAAAAAAAA, 0x55555555, 0xCCCCCCCC, + 0x33333333 +}; + +static const uint32_t g_ram_pattern_dmi[0x500] = { + 0xF, 0xF, 0x0, 0xF, 0xF, 0x0, 0xF, 0xF, + 0x0, 0xF, 0x0, 0xF, 0xF, 0x0, 0xF, 0xF, + 0xF, 0xF, 0x0, 0xF, 0xF, 0x0, 0x0, 0x0, + 0xF, 0xF, 0x0, 0xF, 0x0, 0x0, 0xF, 0x0, + 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0x0, + 0x0, 0xF, 0xF, 0x0, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, + 0x0, 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, 0x0, + 0xF, 0xF, 0x0, 0xF, 0xF, 0x0, 0xF, 0xF, + 0x0, 0xF, 0x0, 0xF, 0xF, 0x0, 0xF, 0xF, + 0xF, 0xF, 0x0, 0xF, 0xF, 0x0, 0x0, 0x0, + 0xF, 0xF, 0x0, 0xF, 0x0, 0x0, 0xF, 0x0, + 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0x0, + 0x0, 0xF, 0xF, 0x0, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, + 0x0, 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + + 0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xF, 0xF, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, + 0xF, 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, 0xF, + 0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0xF, 0x0, + 0xF, 0xF, 0x0, 0x0, 0xF, 0xF, 0xF, 0x0, + 0xF, 0x0, 0xF, 0x0, 0x0, 0xF, 0xF, 0xF, + 0xF, 0xF, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, + 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0xF, 0x0, + 0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xF, 0xF, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, + 0xF, 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, 0xF, + 0x0, 0x0, 0xF, 0x0, 0x0, 0x0, 0xF, 0x0, + 0xF, 0xF, 0x0, 0x0, 0xF, 0xF, 0xF, 0x0, + 0xF, 0x0, 0xF, 0x0, 0x0, 0xF, 0xF, 0xF, + 0xF, 0xF, 0x0, 0xF, 0x0, 0x0, 0x0, 0x0, + 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0xF, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, 0xF, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3, + 0xA, 0x5, 0xC, 0x3, 0xA, 0x5, 0xC, 0x3 +}; + +/* + * Register read/write helpers. + */ +static inline void emc_write(uint32_t val, uint32_t offset) { + MAKE_EMC_REG(offset) = val; +} + +static inline uint32_t emc_read(uint32_t offset) { + return MAKE_EMC_REG(offset); +} + +static inline void emc0_write(uint32_t val, uint32_t offset) { + MAKE_EMC0_REG(offset) = val; +} + +static inline uint32_t emc0_read(uint32_t offset) { + return MAKE_EMC0_REG(offset); +} + +static inline void emc1_write(uint32_t val, uint32_t offset) { + MAKE_EMC1_REG(offset) = val; +} + +static inline uint32_t emc1_read(uint32_t offset) { + return MAKE_EMC1_REG(offset); +} + +static inline void emc_write_per_ch(uint32_t val, int type, uint32_t offset) { + switch (type) { + case REG_EMC: + emc_write(val, offset); + break; + case REG_EMC0: + emc0_write(val, offset); + break; + case REG_EMC1: + emc1_write(val, offset); + break; + } +} + +static inline uint32_t emc_read_per_ch(int type, uint32_t offset) { + uint32_t val = 0; + switch (type) { + case REG_EMC: + val = emc_read(offset); + break; + case REG_EMC0: + val = emc0_read(offset); + break; + case REG_EMC1: + val = emc1_read(offset); + break; + } + return val; +} + +static inline void mc_write(uint32_t val, uint32_t offset) { + MAKE_MC_REG(offset) = val; +} + +static inline uint32_t mc_read(uint32_t offset) { + return MAKE_MC_REG(offset); +} + +/* Configure clock change sequence FIFO */ +static void ccfifo_write(uint32_t ccfifo_addr, uint32_t ccfifo_data, uint32_t ccfifo_stall_cnt) { + MAKE_EMC_REG(EMC_CCFIFO_DATA) = ccfifo_data; + MAKE_EMC_REG(EMC_CCFIFO_ADDR) = ((ccfifo_addr & 0xFFFF) | ((ccfifo_stall_cnt & 0x7FFF) << 16) | 0x80000000); +} + +static void start_periodic_compensation() { + uint32_t mpc_req = 0x4B; + + // Write to EMC_MPC_0 + emc_write(mpc_req, EMC_MPC); + + // Dummy read + mpc_req = emc_read(EMC_MPC); +} + +static uint32_t actual_osc_clocks(uint32_t in) { + if (in < 0x40) + return in * 16; + else if (in < 0x80) + return 2048; + else if (in < 0xc0) + return 4096; + else + return 8192; +} + +static void emc_set_shadow_bypass(int set) { + uint32_t emc_dbg = emc_read(EMC_DBG); + + if (set) + emc_write(emc_dbg | EMC_DBG_WRITE_MUX_ACTIVE, EMC_DBG); + else + emc_write(emc_dbg & ~EMC_DBG_WRITE_MUX_ACTIVE, EMC_DBG); +} + +static uint32_t wait_for_update(uint32_t status_reg, uint32_t bit_mask, bool updated_state, int chan) { + for (int i = 0; i < EMC_STATUS_UPDATE_TIMEOUT; i++) { + if (chan == REG_EMC) { + if (((emc_read_per_ch(REG_EMC, status_reg) & bit_mask) != 0) == updated_state) + return 0; + } else { + if (((emc_read_per_ch(REG_EMC1, status_reg) & bit_mask) != 0) == updated_state) + return 0; + } + + udelay(1); + } + + // Timeout + return 4; +} + +static void emc_timing_update(bool dual_chan) { + /* Trigger the timing update event. */ + emc_write(0x1, EMC_TIMING_CONTROL); + + /* Wait for the update to finish. */ + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_TIMING_UPDATE_STALLED, false, REG_EMC); + if (dual_chan) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_TIMING_UPDATE_STALLED, false, REG_EMC1); +} + +static uint32_t get_dll_state(tegra_emc_timing_t *next_timing) { + bool next_dll_enabled = !(next_timing->emc_emrs & 0x1); + if (next_dll_enabled) + return DLL_ON; + else + return DLL_OFF; +} + +static uint32_t div_o3(uint32_t a, uint32_t b) { + uint32_t result = a / b; + + if ((b * result) < a) + return result + 1; + else + return result; +} + +static uint32_t dvfs_power_ramp_down(bool flip_backward, tegra_emc_timing_t* current_timing, tegra_emc_timing_t* next_timing, uint32_t clk) { + uint32_t ramp_down_wait = 0; + uint32_t seq_wait = 0; + uint32_t pmacro_cmd_pad = 0; + uint32_t pmacro_dq_pad = 0; + uint32_t pmacro_cfg5 = 0; + uint32_t pmacro_rfu1 = 0; + uint32_t pmacro_common_tx = 0; + + if (flip_backward) { + pmacro_cmd_pad = next_timing->burst_regs[EMC_PMACRO_CMD_PAD_TX_CTRL_INDEX]; + pmacro_dq_pad = next_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]; + pmacro_rfu1 = next_timing->burst_regs[EMC_PMACRO_BRICK_CTRL_RFU1_INDEX]; + pmacro_cfg5 = next_timing->burst_regs[EMC_FBIO_CFG5_INDEX]; + pmacro_common_tx = next_timing->burst_regs[EMC_PMACRO_COMMON_PAD_TX_CTRL_INDEX]; + } else { + pmacro_cmd_pad = current_timing->burst_regs[EMC_PMACRO_CMD_PAD_TX_CTRL_INDEX]; + pmacro_dq_pad = ((next_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX] & 0x101) | current_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]); + pmacro_rfu1 = current_timing->burst_regs[EMC_PMACRO_BRICK_CTRL_RFU1_INDEX]; + pmacro_cfg5 = current_timing->burst_regs[EMC_FBIO_CFG5_INDEX]; + pmacro_common_tx = current_timing->burst_regs[EMC_PMACRO_COMMON_PAD_TX_CTRL_INDEX]; + } + + pmacro_cmd_pad |= EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_DRVFORCEON; + + ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad, 0); + ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 | EMC_FBIO_CFG5_CMD_TX_DIS, 12); + + ramp_down_wait = clk * 12; + seq_wait = (100000 / clk) + 1; + + if (clk < (1000000 / DVFS_FGCG_HIGH_SPEED_THRESHOLD)) { + if (clk < (1000000 / IOBRICK_DCC_THRESHOLD)) { + pmacro_cmd_pad &= ~(EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC); + pmacro_cmd_pad |= EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC; + + ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad, seq_wait); + ramp_down_wait += 100000; + + pmacro_dq_pad &= ~(EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC); + pmacro_dq_pad |= EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC; + + ccfifo_write(EMC_PMACRO_DATA_PAD_TX_CTRL, pmacro_dq_pad, 0); + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & ~0x01120112, 0); + } else { + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & ~0x01120112, seq_wait); + ramp_down_wait += 100000; + } + + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & ~0x01bf01bf, seq_wait); + ramp_down_wait += 100000; + + if (clk < (1000000 / IOBRICK_DCC_THRESHOLD)) { + pmacro_cmd_pad &= ~(EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC); + + ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad, seq_wait); + ramp_down_wait += 100000; + + pmacro_dq_pad &= ~(EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC); + + ccfifo_write(EMC_PMACRO_DATA_PAD_TX_CTRL, pmacro_dq_pad, 0); + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & ~0x07ff07ff, 0); + } else { + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & ~0x07ff07ff, seq_wait); + ramp_down_wait += 100000; + } + } else { + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & ~0x07ff07ff, seq_wait + 19); + ramp_down_wait += (100000 + (20 * clk)); + } + + if (clk < (1000000 / DVFS_FGCG_MID_SPEED_THRESHOLD)) { + ramp_down_wait += 100000; + ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & ~0x5, seq_wait); + ramp_down_wait += 100000; + ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & ~0xf, seq_wait); + ramp_down_wait += 100000; + ccfifo_write(0, 0, seq_wait); + ramp_down_wait += 100000; + } else { + ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & ~0xf, seq_wait); + } + + return ramp_down_wait; +} + +static uint32_t dvfs_power_ramp_up(bool flip_backward, tegra_emc_timing_t* current_timing, tegra_emc_timing_t* next_timing, uint32_t training, uint32_t clk) { + uint32_t ramp_up_wait = 0; + uint32_t pmacro_cmd_pad = 0; + uint32_t pmacro_dq_pad = 0; + uint32_t pmacro_cfg5 = 0; + uint32_t pmacro_rfu1 = 0; + uint32_t pmacro_common_tx = 0; + + if (flip_backward) { + pmacro_cmd_pad = current_timing->burst_regs[EMC_PMACRO_CMD_PAD_TX_CTRL_INDEX]; + pmacro_dq_pad = current_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]; + pmacro_rfu1 = current_timing->burst_regs[EMC_PMACRO_BRICK_CTRL_RFU1_INDEX]; + pmacro_cfg5 = current_timing->burst_regs[EMC_FBIO_CFG5_INDEX]; + pmacro_common_tx = current_timing->burst_regs[EMC_PMACRO_COMMON_PAD_TX_CTRL_INDEX]; + } else if (training & 3) { + pmacro_cmd_pad = next_timing->shadow_regs_ca_train[EMC_PMACRO_CMD_PAD_TX_CTRL_INDEX]; + pmacro_dq_pad = next_timing->shadow_regs_ca_train[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]; + pmacro_rfu1 = next_timing->shadow_regs_ca_train[EMC_PMACRO_BRICK_CTRL_RFU1_INDEX]; + pmacro_cfg5 = next_timing->shadow_regs_ca_train[EMC_FBIO_CFG5_INDEX]; + pmacro_common_tx = next_timing->shadow_regs_ca_train[EMC_PMACRO_COMMON_PAD_TX_CTRL_INDEX]; + } else if (training & 0xC) { + pmacro_cmd_pad = next_timing->shadow_regs_quse_train[EMC_PMACRO_CMD_PAD_TX_CTRL_INDEX]; + pmacro_dq_pad = next_timing->shadow_regs_quse_train[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]; + pmacro_rfu1 = next_timing->shadow_regs_quse_train[EMC_PMACRO_BRICK_CTRL_RFU1_INDEX]; + pmacro_cfg5 = next_timing->shadow_regs_quse_train[EMC_FBIO_CFG5_INDEX]; + pmacro_common_tx = next_timing->shadow_regs_quse_train[EMC_PMACRO_COMMON_PAD_TX_CTRL_INDEX]; + } else if (training & 0xF0) { + pmacro_cmd_pad = next_timing->shadow_regs_rdwr_train[EMC_PMACRO_CMD_PAD_TX_CTRL_INDEX]; + pmacro_dq_pad = next_timing->shadow_regs_rdwr_train[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]; + pmacro_rfu1 = next_timing->shadow_regs_rdwr_train[EMC_PMACRO_BRICK_CTRL_RFU1_INDEX]; + pmacro_cfg5 = next_timing->shadow_regs_rdwr_train[EMC_FBIO_CFG5_INDEX]; + pmacro_common_tx = next_timing->shadow_regs_rdwr_train[EMC_PMACRO_COMMON_PAD_TX_CTRL_INDEX]; + } else { + pmacro_cmd_pad = next_timing->burst_regs[EMC_PMACRO_CMD_PAD_TX_CTRL_INDEX]; + pmacro_dq_pad = next_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]; + pmacro_rfu1 = next_timing->burst_regs[EMC_PMACRO_BRICK_CTRL_RFU1_INDEX]; + pmacro_cfg5 = next_timing->burst_regs[EMC_FBIO_CFG5_INDEX]; + pmacro_common_tx = next_timing->burst_regs[EMC_PMACRO_COMMON_PAD_TX_CTRL_INDEX]; + } + + pmacro_cmd_pad |= EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_DRVFORCEON; + + if (clk < 1000000 / DVFS_FGCG_MID_SPEED_THRESHOLD) { + ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & 0xa, 0); + ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx & 0xf, (100000 / clk) + 1); + ramp_up_wait += 100000; + } else { + ccfifo_write(EMC_PMACRO_COMMON_PAD_TX_CTRL, pmacro_common_tx | 0x8, 0); + } + + if (clk < 1000000 / DVFS_FGCG_HIGH_SPEED_THRESHOLD) { + if (clk < 1000000 / IOBRICK_DCC_THRESHOLD) { + pmacro_cmd_pad |= (EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC); + pmacro_cmd_pad &= ~(EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC); + + ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad, (100000 / clk) + 1); + ramp_up_wait += 100000; + + pmacro_dq_pad |= (EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC); + pmacro_dq_pad &= ~(EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC); + + ccfifo_write(EMC_PMACRO_DATA_PAD_TX_CTRL, pmacro_dq_pad, 0); + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xfe40fe40, 0); + } else { + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xfe40fe40, (100000 / clk) + 1); + ramp_up_wait += 100000; + } + + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 & 0xfeedfeed, (100000 / clk) + 1); + ramp_up_wait += 100000; + + if (clk < 1000000 / IOBRICK_DCC_THRESHOLD) { + pmacro_cmd_pad |= (EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC | EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC); + + ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad, (100000 / clk) + 1); + ramp_up_wait += 100000; + + pmacro_dq_pad |= (EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC | EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC); + + ccfifo_write(EMC_PMACRO_DATA_PAD_TX_CTRL, pmacro_dq_pad, 0); + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1, 0); + } else { + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1, (100000 / clk) + 1); + ramp_up_wait += 100000; + } + + ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 & ~EMC_FBIO_CFG5_CMD_TX_DIS, (100000 / clk) + 10); + ramp_up_wait += (100000 + (10 * clk)); + } else if (clk < 1000000 / DVFS_FGCG_MID_SPEED_THRESHOLD) { + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 | 0x06000600, (100000 / clk) + 1); + ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 & ~EMC_FBIO_CFG5_CMD_TX_DIS, (100000 / clk) + 10); + ramp_up_wait += (100000 + 10 * clk); + } else { + ccfifo_write(EMC_PMACRO_BRICK_CTRL_RFU1, pmacro_rfu1 | 0x00000600, 0); + ccfifo_write(EMC_FBIO_CFG5, pmacro_cfg5 & ~EMC_FBIO_CFG5_CMD_TX_DIS, 12); + ramp_up_wait += (12 * clk); + } + + pmacro_cmd_pad &= ~EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_DRVFORCEON; + ccfifo_write(EMC_PMACRO_CMD_PAD_TX_CTRL, pmacro_cmd_pad, 5); + + return ramp_up_wait; +} + +static uint32_t apply_periodic_compensation_trimmer(tegra_emc_timing_t* next_timing, uint32_t offset) { + uint32_t temp = 0; + uint32_t next_timing_rate_mhz = next_timing->rate / 1000; + int tree_delta[4] = {0}; + int tree_delta_taps[4] = {0}; + int new[] = { + TRIM_REG(0, 0, 0, 0), + TRIM_REG(0, 0, 0, 1), + TRIM_REG(0, 0, 1, 2), + TRIM_REG(0, 0, 1, 3), + + TRIM_REG(1, 0, 2, 4), + TRIM_REG(1, 0, 2, 5), + TRIM_REG(1, 0, 3, 6), + TRIM_REG(1, 0, 3, 7), + + TRIM_REG(0, 1, 0, 0), + TRIM_REG(0, 1, 0, 1), + TRIM_REG(0, 1, 1, 2), + TRIM_REG(0, 1, 1, 3), + + TRIM_REG(1, 1, 2, 4), + TRIM_REG(1, 1, 2, 5), + TRIM_REG(1, 1, 3, 6), + TRIM_REG(1, 1, 3, 7) + }; + + switch (offset) { + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0: + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1: + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2: + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3: + case EMC_DATA_BRLSHFT_0: + tree_delta[0] = 128 * (next_timing->current_dram_clktree_c0d0u0 - next_timing->trained_dram_clktree_c0d0u0); + tree_delta[1] = 128 * (next_timing->current_dram_clktree_c0d0u1 - next_timing->trained_dram_clktree_c0d0u1); + tree_delta[2] = 128 * (next_timing->current_dram_clktree_c1d0u0 - next_timing->trained_dram_clktree_c1d0u0); + tree_delta[3] = 128 * (next_timing->current_dram_clktree_c1d0u1 - next_timing->trained_dram_clktree_c1d0u1); + tree_delta_taps[0] = (tree_delta[0] * (int)next_timing_rate_mhz) / 1000000; + tree_delta_taps[1] = (tree_delta[1] * (int)next_timing_rate_mhz) / 1000000; + tree_delta_taps[2] = (tree_delta[2] * (int)next_timing_rate_mhz) / 1000000; + tree_delta_taps[3] = (tree_delta[3] * (int)next_timing_rate_mhz) / 1000000; + + for (int i = 0; i < 4; i++) { + if ((tree_delta_taps[i] > next_timing->tree_margin) || + (tree_delta_taps[i] < + (-1 * next_timing->tree_margin))) { + new[i * 2] = new[i * 2] + tree_delta_taps[i]; + new[i * 2 + 1] = new[i * 2 + 1] + + tree_delta_taps[i]; + } + } + + if (offset == EMC_DATA_BRLSHFT_0) { + for (int i = 0; i < 8; i++) + new[i] = new[i] / 64; + } else { + for (int i = 0; i < 8; i++) + new[i] = new[i] % 64; + } + break; + + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0: + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1: + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2: + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3: + case EMC_DATA_BRLSHFT_1: + tree_delta[0] = 128 * (next_timing->current_dram_clktree_c0d1u0 - next_timing->trained_dram_clktree_c0d1u0); + tree_delta[1] = 128 * (next_timing->current_dram_clktree_c0d1u1 - next_timing->trained_dram_clktree_c0d1u1); + tree_delta[2] = 128 * (next_timing->current_dram_clktree_c1d1u0 - next_timing->trained_dram_clktree_c1d1u0); + tree_delta[3] = 128 * (next_timing->current_dram_clktree_c1d1u1 - next_timing->trained_dram_clktree_c1d1u1); + tree_delta_taps[0] = (tree_delta[0] * (int)next_timing_rate_mhz) / 1000000; + tree_delta_taps[1] = (tree_delta[1] * (int)next_timing_rate_mhz) / 1000000; + tree_delta_taps[2] = (tree_delta[2] * (int)next_timing_rate_mhz) / 1000000; + tree_delta_taps[3] = (tree_delta[3] * (int)next_timing_rate_mhz) / 1000000; + + for (int i = 0; i < 4; i++) { + if ((tree_delta_taps[i] > next_timing->tree_margin) || (tree_delta_taps[i] < (-1 * next_timing->tree_margin))) { + new[8 + i * 2] = new[8 + i * 2] + tree_delta_taps[i]; + new[8 + i * 2 + 1] = new[8 + i * 2 + 1] + tree_delta_taps[i]; + } + } + + if (offset == EMC_DATA_BRLSHFT_1) { + for (int i = 0; i < 8; i++) + new[i + 8] = new[i + 8] / 64; + } else { + for (int i = 0; i < 8; i++) + new[i + 8] = new[i + 8] % 64; + } + break; + } + + switch (offset) { + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0: + temp = CALC_TEMP(0, 0, 0, 1, 0); + break; + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1: + temp = CALC_TEMP(0, 1, 2, 3, 2); + break; + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2: + temp = CALC_TEMP(0, 2, 4, 5, 4); + break; + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3: + temp = CALC_TEMP(0, 3, 6, 7, 6); + break; + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0: + temp = CALC_TEMP(1, 0, 0, 1, 8); + break; + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1: + temp = CALC_TEMP(1, 1, 2, 3, 10); + break; + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2: + temp = CALC_TEMP(1, 2, 4, 5, 12); + break; + case EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3: + temp = CALC_TEMP(1, 3, 6, 7, 14); + break; + case EMC_DATA_BRLSHFT_0: + temp = ((new[0] << + EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_MASK) | + ((new[1] << + EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_MASK) | + ((new[2] << + EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_MASK) | + ((new[3] << + EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_MASK) | + ((new[4] << + EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_MASK) | + ((new[5] << + EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_MASK) | + ((new[6] << + EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_MASK) | + ((new[7] << + EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_MASK); + break; + case EMC_DATA_BRLSHFT_1: + temp = ((new[8] << + EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_MASK) | + ((new[9] << + EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_MASK) | + ((new[10] << + EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_MASK) | + ((new[11] << + EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_MASK) | + ((new[12] << + EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_MASK) | + ((new[13] << + EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_MASK) | + ((new[14] << + EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_MASK) | + ((new[15] << + EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT) & + EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_MASK); + break; + default: + break; + } + + return temp; +} + +static uint32_t update_clock_tree_delay(tegra_emc_timing_t* current_timing, tegra_emc_timing_t* next_timing, uint32_t dram_dev_num, uint32_t channel_mode, int type) { + uint32_t mrr_req = 0, mrr_data = 0; + uint32_t temp0_0 = 0, temp0_1 = 0, temp1_0 = 0, temp1_1 = 0; + int tdel = 0, tmdel = 0, adel = 0; + uint32_t cval; + uint32_t current_timing_rate_mhz = (current_timing->rate / 1000); + uint32_t next_timing_rate_mhz = (next_timing->rate / 1000); + bool dvfs_pt1 = (type == DVFS_PT1); + bool training_pt1 = (type == TRAINING_PT1); + bool dvfs_update = (type == DVFS_UPDATE); + bool training_update = (type == TRAINING_UPDATE); + bool periodic_training_update = (type == PERIODIC_TRAINING_UPDATE); + + /* + * Dev0 MSB. + */ + if (dvfs_pt1 || training_pt1 || periodic_training_update) { + mrr_req = ((2 << EMC_MRR_DEV_SEL_SHIFT) | (19 << EMC_MRR_MA_SHIFT)); + emc_write(mrr_req, EMC_MRR); + + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_MRR_DIVLD, true, REG_EMC); + if (channel_mode == DUAL_CHANNEL) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_MRR_DIVLD, true, REG_EMC1); + + mrr_data = ((emc_read(EMC_MRR) & EMC_MRR_DATA_MASK) << EMC_MRR_DATA_SHIFT); + + temp0_0 = ((mrr_data & 0xff) << 8); + temp0_1 = (mrr_data & 0xff00); + + if (channel_mode == DUAL_CHANNEL) { + mrr_data = ((emc1_read(EMC_MRR) & EMC_MRR_DATA_MASK) << EMC_MRR_DATA_SHIFT); + temp1_0 = ((mrr_data & 0xff) << 8); + temp1_1 = (mrr_data & 0xff00); + } + + /* + * Dev0 LSB. + */ + mrr_req = ((mrr_req & ~EMC_MRR_MA_MASK) | (18 << EMC_MRR_MA_SHIFT)); + emc_write(mrr_req, EMC_MRR); + + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_MRR_DIVLD, true, REG_EMC); + if (channel_mode == DUAL_CHANNEL) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_MRR_DIVLD, true, REG_EMC1); + + mrr_data = ((emc_read(EMC_MRR) & EMC_MRR_DATA_MASK) << EMC_MRR_DATA_SHIFT); + + temp0_0 |= (mrr_data & 0xff); + temp0_1 |= ((mrr_data & 0xff00) >> 8); + + if (channel_mode == DUAL_CHANNEL) { + mrr_data = ((emc1_read(EMC_MRR) & EMC_MRR_DATA_MASK) << EMC_MRR_DATA_SHIFT); + temp1_0 |= (mrr_data & 0xff); + temp1_1 |= ((mrr_data & 0xff00) >> 8); + } + } + + cval = ((1000000 * actual_osc_clocks(current_timing->run_clocks)) / (current_timing_rate_mhz * 2 * temp0_0)); + + if (dvfs_pt1 || training_pt1) + __INCREMENT_PTFV(C0D0U0, cval); + else if (dvfs_update) + __AVERAGE_PTFV(C0D0U0); + else if (training_update) + __AVERAGE_WRITE_PTFV(C0D0U0); + else if (periodic_training_update) + __WEIGHTED_UPDATE_PTFV(C0D0U0, cval); + + if (dvfs_update || training_update || periodic_training_update) { + tdel = (next_timing->current_dram_clktree_c0d0u0 - __MOVAVG_AC(next_timing, C0D0U0)); + tmdel = (tdel < 0) ? -1 * tdel : tdel; + adel = tmdel; + if ((tmdel * 128 * next_timing_rate_mhz / 1000000) > next_timing->tree_margin) + next_timing->current_dram_clktree_c0d0u0 = __MOVAVG_AC(next_timing, C0D0U0); + } + + cval = ((1000000 * actual_osc_clocks(current_timing->run_clocks)) / + (current_timing_rate_mhz * 2 * temp0_1)); + + if (dvfs_pt1 || training_pt1) + __INCREMENT_PTFV(C0D0U1, cval); + else if (dvfs_update) + __AVERAGE_PTFV(C0D0U1); + else if (training_update) + __AVERAGE_WRITE_PTFV(C0D0U1); + else if (periodic_training_update) + __WEIGHTED_UPDATE_PTFV(C0D0U1, cval); + + if (dvfs_update || training_update || periodic_training_update) { + tdel = next_timing->current_dram_clktree_c0d0u1 - __MOVAVG_AC(next_timing, C0D0U1); + tmdel = (tdel < 0) ? -1 * tdel : tdel; + + if (tmdel > adel) + adel = tmdel; + + if ((tmdel * 128 * next_timing_rate_mhz / 1000000) > next_timing->tree_margin) + next_timing->current_dram_clktree_c0d0u1 = __MOVAVG_AC(next_timing, C0D0U1); + } + + if (channel_mode == DUAL_CHANNEL) { + cval = ((1000000 * actual_osc_clocks(current_timing->run_clocks)) / (current_timing_rate_mhz * 2 * temp1_0)); + + if (dvfs_pt1 || training_pt1) + __INCREMENT_PTFV(C1D0U0, cval); + else if (dvfs_update) + __AVERAGE_PTFV(C1D0U0); + else if (training_update) + __AVERAGE_WRITE_PTFV(C1D0U0); + else if (periodic_training_update) + __WEIGHTED_UPDATE_PTFV(C1D0U0, cval); + + if (dvfs_update || training_update || periodic_training_update) { + tdel = next_timing->current_dram_clktree_c1d0u0 - __MOVAVG_AC(next_timing, C1D0U0); + tmdel = (tdel < 0) ? -1 * tdel : tdel; + + if (tmdel > adel) + adel = tmdel; + + if ((tmdel * 128 * next_timing_rate_mhz / 1000000) > next_timing->tree_margin) + next_timing->current_dram_clktree_c1d0u0 = __MOVAVG_AC(next_timing, C1D0U0); + } + + cval = ((1000000 * actual_osc_clocks(current_timing->run_clocks)) / (current_timing_rate_mhz * 2 * temp1_1)); + + if (dvfs_pt1 || training_pt1) + __INCREMENT_PTFV(C1D0U1, cval); + else if (dvfs_update) + __AVERAGE_PTFV(C1D0U1); + else if (training_update) + __AVERAGE_WRITE_PTFV(C1D0U1); + else if (periodic_training_update) + __WEIGHTED_UPDATE_PTFV(C1D0U1, cval); + + if (dvfs_update || training_update || periodic_training_update) { + tdel = next_timing->current_dram_clktree_c1d0u1 - __MOVAVG_AC(next_timing, C1D0U1); + tmdel = (tdel < 0) ? -1 * tdel : tdel; + + if (tmdel > adel) + adel = tmdel; + + if ((tmdel * 128 * next_timing_rate_mhz / 1000000) > next_timing->tree_margin) + next_timing->current_dram_clktree_c1d0u1 = __MOVAVG_AC(next_timing, C1D0U1); + } + } + + if (dram_dev_num != TWO_RANK) + return adel; + + /* + * Dev1 MSB. + */ + if (dvfs_pt1 || training_pt1 || periodic_training_update) { + mrr_req = ((1 << EMC_MRR_DEV_SEL_SHIFT) | (19 << EMC_MRR_MA_SHIFT)); + emc_write(mrr_req, EMC_MRR); + + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_MRR_DIVLD, true, REG_EMC); + if (channel_mode == DUAL_CHANNEL) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_MRR_DIVLD, true, REG_EMC1); + + mrr_data = ((emc_read(EMC_MRR) & EMC_MRR_DATA_MASK) << EMC_MRR_DATA_SHIFT); + + temp0_0 = ((mrr_data & 0xff) << 8); + temp0_1 = (mrr_data & 0xff00); + + if (channel_mode == DUAL_CHANNEL) { + mrr_data = ((emc1_read(EMC_MRR) & EMC_MRR_DATA_MASK) << EMC_MRR_DATA_SHIFT); + temp1_0 = ((mrr_data & 0xff) << 8); + temp1_1 = (mrr_data & 0xff00); + } + + /* + * Dev1 LSB. + */ + mrr_req = ((mrr_req & ~EMC_MRR_MA_MASK) | (18 << EMC_MRR_MA_SHIFT)); + emc_write(mrr_req, EMC_MRR); + + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_MRR_DIVLD, true, REG_EMC); + if (channel_mode == DUAL_CHANNEL) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_MRR_DIVLD, true, REG_EMC1); + + mrr_data = ((emc_read(EMC_MRR) & EMC_MRR_DATA_MASK) << EMC_MRR_DATA_SHIFT); + + temp0_0 |= (mrr_data & 0xff); + temp0_1 |= ((mrr_data & 0xff00) >> 8); + + if (channel_mode == DUAL_CHANNEL) { + mrr_data = ((emc1_read(EMC_MRR) & EMC_MRR_DATA_MASK) << EMC_MRR_DATA_SHIFT); + temp1_0 |= (mrr_data & 0xff); + temp1_1 |= ((mrr_data & 0xff00) >> 8); + } + } + + cval = ((1000000 * actual_osc_clocks(current_timing->run_clocks)) / (current_timing_rate_mhz * 2 * temp0_0)); + + if (dvfs_pt1 || training_pt1) + __INCREMENT_PTFV(C0D1U0, cval); + else if (dvfs_update) + __AVERAGE_PTFV(C0D1U0); + else if (training_update) + __AVERAGE_WRITE_PTFV(C0D1U0); + else if (periodic_training_update) + __WEIGHTED_UPDATE_PTFV(C0D1U0, cval); + + if (dvfs_update || training_update || periodic_training_update) { + tdel = next_timing->current_dram_clktree_c0d1u0 - __MOVAVG_AC(next_timing, C0D1U0); + tmdel = (tdel < 0) ? -1 * tdel : tdel; + + if (tmdel > adel) + adel = tmdel; + + if ((tmdel * 128 * next_timing_rate_mhz / 1000000) > next_timing->tree_margin) + next_timing->current_dram_clktree_c0d1u0 = __MOVAVG_AC(next_timing, C0D1U0); + } + + cval = ((1000000 * actual_osc_clocks(current_timing->run_clocks)) / (current_timing_rate_mhz * 2 * temp0_1)); + + if (dvfs_pt1 || training_pt1) + __INCREMENT_PTFV(C0D1U1, cval); + else if (dvfs_update) + __AVERAGE_PTFV(C0D1U1); + else if (training_update) + __AVERAGE_WRITE_PTFV(C0D1U1); + else if (periodic_training_update) + __WEIGHTED_UPDATE_PTFV(C0D1U1, cval); + + if (dvfs_update || training_update || periodic_training_update) { + tdel = next_timing->current_dram_clktree_c0d1u1 - __MOVAVG_AC(next_timing, C0D1U1); + tmdel = (tdel < 0) ? -1 * tdel : tdel; + + if (tmdel > adel) + adel = tmdel; + + if ((tmdel * 128 * next_timing_rate_mhz / 1000000) > next_timing->tree_margin) + next_timing->current_dram_clktree_c0d1u1 = __MOVAVG_AC(next_timing, C0D1U1); + } + + if (channel_mode == DUAL_CHANNEL) { + cval = ((1000000 * actual_osc_clocks(current_timing->run_clocks)) / (current_timing_rate_mhz * 2 * temp1_0)); + + if (dvfs_pt1 || training_pt1) + __INCREMENT_PTFV(C1D1U0, cval); + else if (dvfs_update) + __AVERAGE_PTFV(C1D1U0); + else if (training_update) + __AVERAGE_WRITE_PTFV(C1D1U0); + else if (periodic_training_update) + __WEIGHTED_UPDATE_PTFV(C1D1U0, cval); + + if (dvfs_update || training_update || periodic_training_update) { + tdel = next_timing->current_dram_clktree_c1d1u0 - __MOVAVG_AC(next_timing, C1D1U0); + + tmdel = (tdel < 0) ? -1 * tdel : tdel; + + if (tmdel > adel) + adel = tmdel; + + if ((tmdel * 128 * next_timing_rate_mhz / 1000000) > next_timing->tree_margin) + next_timing->current_dram_clktree_c1d1u0 = __MOVAVG_AC(next_timing, C1D1U0); + } + + cval = ((1000000 * actual_osc_clocks(current_timing->run_clocks)) / (current_timing_rate_mhz * 2 * temp1_1)); + + if (dvfs_pt1 || training_pt1) + __INCREMENT_PTFV(C1D1U1, cval); + else if (dvfs_update) + __AVERAGE_PTFV(C1D1U1); + else if (training_update) + __AVERAGE_WRITE_PTFV(C1D1U1); + else if (periodic_training_update) + __WEIGHTED_UPDATE_PTFV(C1D1U1, cval); + + if (dvfs_update || training_update || periodic_training_update) { + tdel = next_timing->current_dram_clktree_c1d1u1 - __MOVAVG_AC(next_timing, C1D1U1); + tmdel = (tdel < 0) ? -1 * tdel : tdel; + + if (tmdel > adel) + adel = tmdel; + + if ((tmdel * 128 * next_timing_rate_mhz / 1000000) > next_timing->tree_margin) + next_timing->current_dram_clktree_c1d1u1 = __MOVAVG_AC(next_timing, C1D1U1); + } + } + + if (training_update) { + next_timing->trained_dram_clktree_c0d0u0 = next_timing->current_dram_clktree_c0d0u0; + next_timing->trained_dram_clktree_c0d0u1 = next_timing->current_dram_clktree_c0d0u1; + next_timing->trained_dram_clktree_c0d1u0 = next_timing->current_dram_clktree_c0d1u0; + next_timing->trained_dram_clktree_c0d1u1 = next_timing->current_dram_clktree_c0d1u1; + next_timing->trained_dram_clktree_c1d0u0 = next_timing->current_dram_clktree_c1d0u0; + next_timing->trained_dram_clktree_c1d0u1 = next_timing->current_dram_clktree_c1d0u1; + next_timing->trained_dram_clktree_c1d1u0 = next_timing->current_dram_clktree_c1d1u0; + next_timing->trained_dram_clktree_c1d1u1 = next_timing->current_dram_clktree_c1d1u1; + } + + return adel; +} + +static void reset_dram_clktree_values(tegra_emc_timing_t *table) { + #define __RESET_CLKTREE(TBL, C, D, U) \ + TBL->current_dram_clktree_c ## C ## d ## D ## u ## U = \ + TBL->trained_dram_clktree_c ## C ## d ## D ## u ## U + + __RESET_CLKTREE(table, 0, 0, 0); + __RESET_CLKTREE(table, 0, 0, 1); + __RESET_CLKTREE(table, 1, 0, 0); + __RESET_CLKTREE(table, 1, 0, 1); + __RESET_CLKTREE(table, 1, 1, 0); + __RESET_CLKTREE(table, 1, 1, 1); +} + +static uint32_t periodic_compensation_handler(tegra_emc_timing_t *current_timing, tegra_emc_timing_t *next_timing, uint32_t dram_dev_num, uint32_t channel_mode, int type) { +#define __COPY_EMA(nt, lt, dev) \ + ({ __MOVAVG(nt, dev) = __MOVAVG(lt, dev) * \ + (nt)->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; }) + + uint32_t adel = 0; + uint32_t samples = next_timing->ptfv_list[PTFV_DVFS_SAMPLES_INDEX]; + uint32_t samples_write = next_timing->ptfv_list[PTFV_WRITE_SAMPLES_INDEX]; + uint32_t delay = 2 + (1000 * actual_osc_clocks(current_timing->run_clocks) / current_timing->rate); + + if (!next_timing->periodic_training) + return 0; + + if (type == DVFS_SEQUENCE) { + if (current_timing->periodic_training && (next_timing->ptfv_list[PTFV_CONFIG_CTRL_INDEX] & PTFV_CONFIG_CTRL_USE_PREVIOUS_EMA)) { + /* + * If the previous frequency was using periodic + * calibration then we can reuse the previous + * frequencies EMA data. + */ + __COPY_EMA(next_timing, current_timing, C0D0U0); + __COPY_EMA(next_timing, current_timing, C0D0U1); + __COPY_EMA(next_timing, current_timing, C1D0U0); + __COPY_EMA(next_timing, current_timing, C1D0U1); + __COPY_EMA(next_timing, current_timing, C0D1U0); + __COPY_EMA(next_timing, current_timing, C0D1U1); + __COPY_EMA(next_timing, current_timing, C1D1U0); + __COPY_EMA(next_timing, current_timing, C1D1U1); + } else { + /* Reset the EMA.*/ + __MOVAVG(next_timing, C0D0U0) = 0; + __MOVAVG(next_timing, C0D0U1) = 0; + __MOVAVG(next_timing, C1D0U0) = 0; + __MOVAVG(next_timing, C1D0U1) = 0; + __MOVAVG(next_timing, C0D1U0) = 0; + __MOVAVG(next_timing, C0D1U1) = 0; + __MOVAVG(next_timing, C1D1U0) = 0; + __MOVAVG(next_timing, C1D1U1) = 0; + + for (int i = 0; i < samples; i++) { + start_periodic_compensation(); + udelay(delay); + + /* + * Generate next sample of data. + */ + adel = update_clock_tree_delay(current_timing, next_timing, dram_dev_num, channel_mode, DVFS_PT1); + } + } + + adel = update_clock_tree_delay(current_timing, next_timing, dram_dev_num, channel_mode, DVFS_UPDATE); + } else if (type == WRITE_TRAINING_SEQUENCE) { + /* Reset the EMA.*/ + __MOVAVG(next_timing, C0D0U0) = 0; + __MOVAVG(next_timing, C0D0U1) = 0; + __MOVAVG(next_timing, C1D0U0) = 0; + __MOVAVG(next_timing, C1D0U1) = 0; + __MOVAVG(next_timing, C0D1U0) = 0; + __MOVAVG(next_timing, C0D1U1) = 0; + __MOVAVG(next_timing, C1D1U0) = 0; + __MOVAVG(next_timing, C1D1U1) = 0; + + for (int i = 0; i < samples_write; i++) { + start_periodic_compensation(); + udelay(delay); + + /* + * Generate next sample of data. + */ + update_clock_tree_delay(current_timing, next_timing, dram_dev_num, channel_mode, TRAINING_PT1); + } + + adel = update_clock_tree_delay(current_timing, next_timing, dram_dev_num, channel_mode, TRAINING_UPDATE); + } else if (type == PERIODIC_TRAINING_SEQUENCE) { + start_periodic_compensation(); + udelay(delay); + + adel = update_clock_tree_delay(current_timing, next_timing, dram_dev_num, channel_mode, PERIODIC_TRAINING_UPDATE); + } + + return adel; +} + +static void set_over_temp_timing(tegra_emc_timing_t *next_timing, unsigned long state) { +#define REFRESH_X2 1 +#define REFRESH_X4 2 +#define REFRESH_SPEEDUP(val, speedup) \ + (val = ((val) & 0xFFFF0000) | (((val) & 0xFFFF) >> (speedup))) + + uint32_t ref = next_timing->burst_regs[EMC_REFRESH_INDEX]; + uint32_t pre_ref = next_timing->burst_regs[EMC_PRE_REFRESH_REQ_CNT_INDEX]; + uint32_t dsr_cntrl = next_timing->burst_regs[EMC_DYN_SELF_REF_CONTROL_INDEX]; + + switch (state) { + case TEGRA_DRAM_OVER_TEMP_NONE: + case TEGRA_DRAM_OVER_TEMP_THROTTLE: + break; + case TEGRA_DRAM_OVER_TEMP_REFRESH_X2: + REFRESH_SPEEDUP(ref, REFRESH_X2); + REFRESH_SPEEDUP(pre_ref, REFRESH_X2); + REFRESH_SPEEDUP(dsr_cntrl, REFRESH_X2); + break; + case TEGRA_DRAM_OVER_TEMP_REFRESH_X4: + REFRESH_SPEEDUP(ref, REFRESH_X4); + REFRESH_SPEEDUP(pre_ref, REFRESH_X4); + REFRESH_SPEEDUP(dsr_cntrl, REFRESH_X4); + break; + default: + return; + } + + emc_write(ref, burst_regs_off[EMC_REFRESH_INDEX]); + emc_write(pre_ref, burst_regs_off[EMC_PRE_REFRESH_REQ_CNT_INDEX]); + emc_write(dsr_cntrl, burst_regs_off[EMC_DYN_SELF_REF_CONTROL_INDEX]); +} + +static void change_dll_src(tegra_emc_timing_t* next_timing, uint32_t clk_src_emc_to) { + volatile tegra_car_t *car = car_get_regs(); + + uint32_t emc_2x_clk_src_to = (clk_src_emc_to >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT); + uint32_t val = (((((next_timing->dll_clk_src & 0x1FFFFFFF) | (emc_2x_clk_src_to << EMC_CLK_EMC_2X_CLK_SRC_SHIFT)) & 0xFFFFFF00) | (clk_src_emc_to & 0xFF)) & 0xFFFFF3FF); + + /* Clock source is PLLMB_UD */ + if (emc_2x_clk_src_to == TEGRA_EMC_SRC_PLLMB_UD) + val |= 0x400; + else if (emc_2x_clk_src_to != TEGRA_EMC_SRC_PLLM_UD) /* Clock source is not PLLM_UD */ + val |= 0x800; + + /* Set EMC_DLL_CLK_SRC, DDLL_CLK_SEL and EMC_DLL_CLK_DIVISOR */ + car->clk_source_emc_dll = val; + + /* Clear and set CLK_ENB_EMC_DLL */ + uint32_t clk_enb_emc_dll = ((car->clk_out_enb_x & 0xFFFFBFFF) | ((next_timing->clk_out_enb_x_0_clk_enb_emc_dll & 1) << 14)); + car->clk_out_enb_x = clk_enb_emc_dll; +} + +static uint32_t dll_prelock(tegra_emc_timing_t* next_timing, bool dvfs_with_training, uint32_t clk_src_emc_to) { + /* Check for dual channel LPDDR4 */ + bool dual_channel_lpddr4_case = ((emc_read(EMC_FBIO_CFG7) & EMC_FBIO_CFG7_CH0_ENABLE) & (emc_read(EMC_FBIO_CFG7) & EMC_FBIO_CFG7_CH1_ENABLE)); + + uint32_t emc_dig_dll_status = 0; + uint32_t emc_cfg_dig_dll = (emc_read(EMC_CFG_DIG_DLL) & ~EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_MASK); + + emc_cfg_dig_dll |= (3 << EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT); + emc_cfg_dig_dll &= ~EMC_CFG_DIG_DLL_CFG_DLL_EN; + emc_cfg_dig_dll &= ~EMC_CFG_DIG_DLL_CFG_DLL_MODE_MASK; + emc_cfg_dig_dll |= (3 << EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT); + emc_cfg_dig_dll |= EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_TRAFFIC; + emc_cfg_dig_dll &= ~EMC_CFG_DIG_DLL_CFG_DLL_STALL_RW_UNTIL_LOCK; + emc_cfg_dig_dll &= ~EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_UNTIL_LOCK; + + /* Update EMC_CFG_DIG_DLL_0 */ + emc_write(emc_cfg_dig_dll, EMC_CFG_DIG_DLL); + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + + /* Wait until CFG_DLL_EN is cleared for EMC */ + do { + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + } while (emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN); + + /* Wait until CFG_DLL_EN is cleared for EMC1 */ + if (dual_channel_lpddr4_case) { + do { + emc_cfg_dig_dll = emc1_read(EMC_CFG_DIG_DLL); + } while (emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN); + } + + /* Manual configuration (superseded). */ + /* + uint32_t emc_dll_cfg_0 = emc_read(EMC_DLL_CFG_0); + emc_dll_cfg_0 &= 0xDF00000F; + emc_dll_cfg_0 |= 0x1FA340AF; + emc_write(emc_dll_cfg_0, EMC_DLL_CFG_0); + */ + + emc_write(next_timing->burst_regs[EMC_DLL_CFG_0_INDEX], EMC_DLL_CFG_0); + emc_write(next_timing->burst_regs[EMC_DLL_CFG_1_INDEX], EMC_DLL_CFG_1); + + /* Manual configuration (superseded). */ + /* + uint32_t ddllcal_ctrl_start_trim_val = 0; + + if ((next_timing->rate >= 400000) && (next_timing->rate < 600000)) + ddllcal_ctrl_start_trim_val = 150; + else if ((next_timing->rate >= 600000) && (next_timing->rate < 800000)) + ddllcal_ctrl_start_trim_val = 100; + else if ((next_timing->rate >= 800000) && (next_timing->rate < 1000000)) + ddllcal_ctrl_start_trim_val = 70; + else if ((next_timing->rate >= 1000000) && (next_timing->rate < 1200000)) + ddllcal_ctrl_start_trim_val = 30; + else + ddllcal_ctrl_start_trim_val = 20; + + uint32_t emc_dll_cfg_1 = emc_read(EMC_DLL_CFG_1); + emc_dll_cfg_1 &= EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_MASK; + emc_dll_cfg_1 |= ddllcal_ctrl_start_trim_val; + emc_write(emc_dll_cfg_1, EMC_DLL_CFG_1); + */ + + /* Configure the clock and reset controller for EMC DLL */ + change_dll_src(next_timing, clk_src_emc_to); + + /* Enable DLL */ + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + emc_cfg_dig_dll |= EMC_CFG_DIG_DLL_CFG_DLL_EN; + emc_write(emc_cfg_dig_dll, EMC_CFG_DIG_DLL); + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + + /* Wait until CFG_DLL_EN is set for EMC */ + do { + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + } while (!(emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN)); + + /* Wait until CFG_DLL_EN is set for EMC1 */ + if (dual_channel_lpddr4_case) { + do { + emc_cfg_dig_dll = emc1_read(EMC_CFG_DIG_DLL); + } while (!(emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN)); + } + + /* Wait until DLL_PRIV_UPDATED or DLL_LOCK have been cleared */ + do { + emc_dig_dll_status = emc_read(EMC_DIG_DLL_STATUS); + } while (!(emc_dig_dll_status & EMC_DIG_DLL_STATUS_DLL_LOCK) || !(emc_dig_dll_status & EMC_DIG_DLL_STATUS_DLL_PRIV_UPDATED)); + + if (dvfs_with_training) { + /* Set WRITE_MUX to ACTIVE */ + emc_set_shadow_bypass(ACTIVE); + + /* Disable DLL */ + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + emc_cfg_dig_dll &= ~EMC_CFG_DIG_DLL_CFG_DLL_EN; + emc_write(emc_cfg_dig_dll, EMC_CFG_DIG_DLL); + + /* Set WRITE_MUX to ASSEMBLY */ + emc_set_shadow_bypass(ASSEMBLY); + + /* Wait until CFG_DLL_EN is cleared for EMC */ + do { + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + } while (emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN); + + /* Wait until CFG_DLL_EN is cleared for EMC1 */ + if (dual_channel_lpddr4_case) { + do { + emc_cfg_dig_dll = emc1_read(EMC_CFG_DIG_DLL); + } while (emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN); + } + } + + /* Return the DLL_OUT value */ + return (emc_read(EMC_DIG_DLL_STATUS) & EMC_DIG_DLL_STATUS_DLL_OUT_MASK); +} + +static void dll_disable(bool dual_channel_lpddr4_case) { + /* Disable DLL */ + uint32_t emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + emc_cfg_dig_dll &= ~EMC_CFG_DIG_DLL_CFG_DLL_EN; + emc_write(emc_cfg_dig_dll, EMC_CFG_DIG_DLL); + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + + /* Wait until CFG_DLL_EN is cleared for EMC */ + do { + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + } while (emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN); + + /* Wait until CFG_DLL_EN is cleared for EMC1 */ + if (dual_channel_lpddr4_case) { + do { + emc_cfg_dig_dll = emc1_read(EMC_CFG_DIG_DLL); + } while (emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN); + } +} + +static void dll_enable(bool dual_channel_lpddr4_case) { + /* Enable DLL */ + uint32_t emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + emc_cfg_dig_dll |= EMC_CFG_DIG_DLL_CFG_DLL_EN; + emc_write(emc_cfg_dig_dll, EMC_CFG_DIG_DLL); + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + + /* Wait until CFG_DLL_EN is set for EMC */ + do { + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + } while (!(emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN)); + + /* Wait until CFG_DLL_EN is set for EMC1 */ + if (dual_channel_lpddr4_case) { + do { + emc_cfg_dig_dll = emc1_read(EMC_CFG_DIG_DLL); + } while (!(emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN)); + } +} + +static void dll_enable_stall(bool dual_channel_lpddr4_case) { + /* Enable DLL */ + uint32_t emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + emc_cfg_dig_dll |= EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_TRAFFIC; + emc_cfg_dig_dll |= EMC_CFG_DIG_DLL_CFG_DLL_EN; + emc_cfg_dig_dll &= ~EMC_CFG_DIG_DLL_CFG_DLL_STALL_RW_UNTIL_LOCK; + emc_cfg_dig_dll &= ~EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_UNTIL_LOCK; + emc_cfg_dig_dll = (emc_cfg_dig_dll & ~EMC_CFG_DIG_DLL_CFG_DLL_MODE_MASK) | (2 << EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT); + emc_write(emc_cfg_dig_dll, EMC_CFG_DIG_DLL); + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + + /* Wait until CFG_DLL_EN is set for EMC */ + do { + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + } while (!(emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN)); + + /* Wait until CFG_DLL_EN is set for EMC1 */ + if (dual_channel_lpddr4_case) { + do { + emc_cfg_dig_dll = emc1_read(EMC_CFG_DIG_DLL); + } while (!(emc_cfg_dig_dll & EMC_CFG_DIG_DLL_CFG_DLL_EN)); + } +} + +static bool test_clk_ratio(uint32_t rate_to, uint32_t clk_src_emc_to, uint32_t rate_from, uint32_t clk_src_emc_from) { + volatile tegra_car_t *car = car_get_regs(); + + uint32_t emc_2x_clk_src = (car->clk_source_emc >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT); + uint32_t post_div = 0; + + if ((emc_2x_clk_src == TEGRA_EMC_SRC_PLLM) || (emc_2x_clk_src == TEGRA_EMC_SRC_PLLM_UD)) { + post_div = ((car->pllm_base >> 0x14) & 0x1F); + } else if ((emc_2x_clk_src == TEGRA_EMC_SRC_PLLMB_UD) || (emc_2x_clk_src == TEGRA_EMC_SRC_PLLMB)) { + post_div = ((car->pllmb_base >> 0x14) & 0x1F); + } + + /* Bad post divider value */ + if (post_div > 0x05) + return false; + + uint32_t emc_2x_clk_src_from = (clk_src_emc_from >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT); + uint32_t emc_2x_clk_src_to = (clk_src_emc_to >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT); + uint8_t emc_2x_clk_div_from = (clk_src_emc_from & 0xFF); + uint8_t emc_2x_clk_div_to = (clk_src_emc_to & 0xFF); + + if (emc_2x_clk_src_from <= TEGRA_EMC_SRC_PLLMB_UD) + emc_2x_clk_div_from = 0; + if (emc_2x_clk_src_to <= TEGRA_EMC_SRC_PLLMB_UD) + emc_2x_clk_div_to = 0; + + /* Clock sources are different and one of them is CLK_M */ + if ((emc_2x_clk_src_to != emc_2x_clk_src_from) + && ((emc_2x_clk_src_to & 0xFFFFFFFB) + || (emc_2x_clk_src_from & 0xFFFFFFFB))) + return true; + + float val_to = (double)rate_to * ((double)((emc_2x_clk_div_to >> 1) + 1) + (double)(emc_2x_clk_div_to & 1) * 0.5) * (double)(post_div + 1); + float val_from = (double)rate_from * ((double)((emc_2x_clk_div_from >> 1) + 1) + (double)(emc_2x_clk_div_from & 1) * 0.5) * (double)(post_div + 1); + float ratio = (val_from / val_to); + + if ((ratio > 1.01f) || (ratio < 0.99f)) + return true; + + return false; +} + +static uint32_t set_pll(uint32_t rate_to, uint32_t rate_osc, uint32_t clk_src_emc_to, bool is_pllmb) { + volatile tegra_car_t *car = car_get_regs(); + + static const pll_cfg_t pll_vals[] = { + {0xB71B00, 0x2FAF0800, 0x42, 0x01, 0x00}, /* 800Mhz rate with 12Mhz oscillator (unsupported). */ + {0xC65D40, 0x2FAF0800, 0x3D, 0x01, 0x00}, /* 800Mhz rate with 13Mhz oscillator (unsupported). */ + {0x249F000, 0x11BD0400, 0x5D, 0x04, 0x02}, /* 297.6Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x17D78400, 0x7D, 0x04, 0x02}, /* 400Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x18519600, 0x55, 0x04, 0x01}, /* 408Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x1FC1E200, 0x6F, 0x04, 0x01}, /* 532.8Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x27AC4000, 0x68, 0x03, 0x01}, /* 665.6Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x2FAF0800, 0x7D, 0x03, 0x01}, /* 800Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x3780FC00, 0x61, 0x04, 0x00}, /* 931.2Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x3F83C400, 0x6F, 0x04, 0x00}, /* 1065.6Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x47868C00, 0x7D, 0x04, 0x00}, /* 1200Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x4F588000, 0x68, 0x03, 0x00}, /* 1331.2Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x56F9A000, 0x4C, 0x02, 0x00}, /* 1459.2Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x5F5E1000, 0x7D, 0x03, 0x00}, /* 1600Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x6F01F800, 0x61, 0x02, 0x00}, /* 1862.4Mhz rate with 38.4Mhz oscillator. */ + {0x249F000, 0x7F078800, 0x6F, 0x02, 0x00}, /* 2131.2Mhz rate with 38.4Mhz oscillator. */ + {0x00, 0x00, 0x00, 0x00, 0x00} /* Dummy entry. */ + }; + + uint32_t rate_to_hz = (rate_to * 1000); + uint32_t rate_osc_hz = (rate_osc * 1000); + + int freq_idx = 0; + for (int i = 0; pll_vals[i].osc_freq; i++) { + if ((rate_osc_hz == pll_vals[i].osc_freq) && (rate_to_hz == pll_vals[i].out_freq)) { + freq_idx = i; + break; + } + } + + uint32_t res = clk_src_emc_to; + + /* Failed to find the PLL values */ + if (!pll_vals[freq_idx].osc_freq) + return res; + + uint32_t feedback_div = pll_vals[freq_idx].feedback_div; + uint32_t input_div = pll_vals[freq_idx].input_div; + uint32_t post_div = pll_vals[freq_idx].post_div; + + if (is_pllmb) { + /* Set PLLMB_DIVM, PLLMB_DIVN and PLLMB_DIVP */ + car->pllmb_base = (input_div | (feedback_div << 0x08) | ((post_div & 0x1F) << 0x14)); + + /* Set PLLMB_ENABLE */ + car->pllmb_base |= 0x40000000; + + /* Clock source is PLLM_UD */ + if ((clk_src_emc_to >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT) == TEGRA_EMC_SRC_PLLM_UD) + res = ((clk_src_emc_to & 0x1FFFFFFF) | (TEGRA_EMC_SRC_PLLMB_UD << EMC_CLK_EMC_2X_CLK_SRC_SHIFT)); + else if ((clk_src_emc_to >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT) == TEGRA_EMC_SRC_PLLM) /* Clock source is PLLM_OUT0 */ + res = (clk_src_emc_to | (TEGRA_EMC_SRC_PLLMB << EMC_CLK_EMC_2X_CLK_SRC_SHIFT)); + + while (!(car->pllmb_base & 0x8000000)) { + /* Wait for PLLMB_LOCK to be set */ + } + } else { + /* Set PLLM_DIVM, PLLM_DIVN and PLLM_DIVP */ + car->pllm_base = (input_div | (feedback_div << 0x08) | ((post_div & 0x1F) << 0x14)); + + /* Set PLLM_EN_LCKDET */ + car->pllm_misc2 |= 0x10; + + /* Set PLLM_ENABLE */ + car->pllm_base |= 0x40000000; + + /* Clock source is PLLM_UD */ + if ((clk_src_emc_to >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT) == TEGRA_EMC_SRC_PLLM_UD) + res = ((clk_src_emc_to & 0x1FFFFFFF) | (TEGRA_EMC_SRC_PLLM_UD << EMC_CLK_EMC_2X_CLK_SRC_SHIFT)); + + while (!(car->pllm_base & 0x8000000)) { + /* Wait for PLLM_LOCK to be set */ + } + } + + return res; +} + +static void set_clock(tegra_emc_timing_t* current_timing, tegra_emc_timing_t* next_timing, uint32_t training, uint32_t next_clk_src) { + volatile tegra_car_t *car = car_get_regs(); + + /* Extract training values */ + bool train_ca = (training & 0x01); + bool train_ca_vref = (training & 0x02); + bool train_quse = (training & 0x04); + bool train_quse_vref = (training & 0x08); + bool train_wr = (training & 0x10); + bool train_wr_vref = (training & 0x20); + bool train_rd = (training & 0x40); + bool train_rd_vref = (training & 0x80); + bool train_swap_rank = (training & 0x100); + bool train_self_refresh = (training & 0x200); + + /* Check if we should do training. */ + bool dvfs_with_training = (training & 0xF7); + + bool skip_zqcal = false; + bool compensate_trimmer_applicable = false; + uint32_t zqcal_before_cc_cutoff = 2400; /* In picoseconds */ + int zq_latch_dvfs_wait_time; + + uint32_t mr13_catr_enable; + uint32_t mr13_flip_fspwr; + uint32_t mr13_flip_fspop; + + int next_push, next_dq_e_ivref, next_dqs_e_ivref; + + uint32_t zq_wait_long; + uint32_t zq_wait_short; + + uint32_t tRTM; + uint32_t RP_war; + uint32_t R2P_war; + uint32_t TRPab_war; + int nRTP; + uint32_t deltaTWATM; + uint32_t W2P_war; + uint32_t tRPST; + + uint32_t mrw_req; + uint32_t adel = 0; + uint32_t next_timing_rate_mhz = next_timing->rate / 1000; + + /* Set some common values needed. */ + int dram_type = emc_read(EMC_FBIO_CFG5) & EMC_FBIO_CFG5_DRAM_TYPE_MASK >> EMC_FBIO_CFG5_DRAM_TYPE_SHIFT; + int dram_dev_num = ((mc_read(MC_EMEM_ADR_CFG) & 1) + 1); + bool shared_zq_resistor = ((current_timing->burst_regs[EMC_ZCAL_WAIT_CNT_INDEX] >> 31) & 1); + bool channel_mode = ((current_timing->burst_regs[EMC_FBIO_CFG7_INDEX] >> 2) & 1); + bool is_lpddr3 = (dram_type == DRAM_TYPE_LPDDR2) && ((next_timing->burst_regs[EMC_FBIO_CFG5_INDEX] >> 25) & 1); + bool opt_zcal_en_cc = ((next_timing->burst_regs[EMC_ZCAL_INTERVAL_INDEX] && !current_timing->burst_regs[EMC_ZCAL_INTERVAL_INDEX]) || (dram_type == DRAM_TYPE_LPDDR4)); + bool opt_war_200024907 = (dram_type == DRAM_TYPE_LPDDR4); + bool opt_do_sw_qrst = false; + bool opt_cc_short_zcal = true; + bool opt_short_zcal = true; + bool save_restore_clkstop_pd = true; + uint32_t opt_dll_mode = (dram_type == DRAM_TYPE_DDR3) ? get_dll_state(next_timing) : DLL_OFF; + uint32_t opt_dvfs_mode = MAN_SR; + uint32_t emc_auto_cal_config = emc_read(EMC_AUTO_CAL_CONFIG); + + /* In picoseconds. */ + uint32_t source_clock_period = 1000000000 / current_timing->rate; + uint32_t destination_clock_period = 1000000000 / next_timing->rate; + + uint32_t tFC_lpddr4 = 1000 * next_timing->dram_timings[T_FC_LPDDR4]; + uint32_t tZQCAL_lpddr4 = 1000000; + int tZQCAL_lpddr4_fc_adj = (source_clock_period > zqcal_before_cc_cutoff) ? tZQCAL_lpddr4 / destination_clock_period : (tZQCAL_lpddr4 - tFC_lpddr4) / destination_clock_period; + + g_fsp_for_next_freq = !g_fsp_for_next_freq; + + uint32_t emc_dbg_o = emc_read(EMC_DBG); + uint32_t emc_pin_o = emc_read(EMC_PIN); + uint32_t emc_cfg_pipe_clk_o = emc_read(EMC_CFG_PIPE_CLK); + uint32_t emc_dbg = emc_dbg_o; + + uint32_t emc_cfg = next_timing->burst_regs[EMC_CFG_INDEX]; + uint32_t emc_sel_dpd_ctrl = next_timing->emc_sel_dpd_ctrl; + + emc_cfg &= ~(EMC_CFG_DYN_SELF_REF | EMC_CFG_DRAM_ACPD | EMC_CFG_DRAM_CLKSTOP_SR | EMC_CFG_DRAM_CLKSTOP_PD); + emc_sel_dpd_ctrl &= ~(EMC_SEL_DPD_CTRL_CLK_SEL_DPD_EN | EMC_SEL_DPD_CTRL_CA_SEL_DPD_EN | EMC_SEL_DPD_CTRL_RESET_SEL_DPD_EN | EMC_SEL_DPD_CTRL_ODT_SEL_DPD_EN | EMC_SEL_DPD_CTRL_DATA_SEL_DPD_EN); + + /* Step 1: + * Pre DVFS SW sequence. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 1\n"); + + /* Step 1.1: Disable DLL. */ + uint32_t tmp = emc_read(EMC_CFG_DIG_DLL); + tmp &= ~EMC_CFG_DIG_DLL_CFG_DLL_EN; + emc_write(tmp, EMC_CFG_DIG_DLL); + + /* Request a timing update. */ + emc_timing_update(channel_mode); + + /* Wait for DLL to be disabled. */ + wait_for_update(EMC_CFG_DIG_DLL, EMC_CFG_DIG_DLL_CFG_DLL_EN, false, REG_EMC); + if (channel_mode) + wait_for_update(EMC_CFG_DIG_DLL, EMC_CFG_DIG_DLL_CFG_DLL_EN, false, REG_EMC1); + + /* Step 1.2: Disable AUTOCAL. */ + emc_auto_cal_config = next_timing->emc_auto_cal_config; + uint32_t auto_cal_en = emc_auto_cal_config & EMC_AUTO_CAL_CONFIG_AUTO_CAL_ENABLE; + emc_auto_cal_config &= ~EMC_AUTO_CAL_CONFIG_AUTO_CAL_START; + emc_auto_cal_config |= EMC_AUTO_CAL_CONFIG_AUTO_CAL_MEASURE_STALL; + emc_auto_cal_config |= EMC_AUTO_CAL_CONFIG_AUTO_CAL_UPDATE_STALL; + emc_auto_cal_config |= auto_cal_en; + emc_write(emc_auto_cal_config, EMC_AUTO_CAL_CONFIG); + + /* Step 1.3: Disable other power features. */ + emc_set_shadow_bypass(ACTIVE); + emc_write(emc_cfg, EMC_CFG); + emc_write(emc_sel_dpd_ctrl, EMC_SEL_DPD_CTRL); + emc_set_shadow_bypass(ASSEMBLY); + + /* Skip this if dvfs_with_training is set. */ + if (!dvfs_with_training && next_timing->periodic_training) { + if (dram_dev_num == TWO_RANK) { + /* Wait for DRAM to get out of power down. */ + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_DRAM_IN_POWERDOWN_MASK, false, REG_EMC); + if (channel_mode) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_DRAM_IN_POWERDOWN_MASK, false, REG_EMC1); + } else { + wait_for_update(EMC_EMC_STATUS, 0x10, false, REG_EMC); + if (channel_mode) + wait_for_update(EMC_EMC_STATUS, 0x10, false, REG_EMC1); + } + + /* Wait for DRAM to get out of self refresh. */ + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK, false, REG_EMC); + if (channel_mode) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK, false, REG_EMC1); + + /* Reset all clock tree values. */ + reset_dram_clktree_values(next_timing); + + /* Do DVFS_SEQUENCE. */ + adel = periodic_compensation_handler(current_timing, next_timing, dram_dev_num, channel_mode, DVFS_SEQUENCE); + + /* Check if we should use compensate trimmer. */ + compensate_trimmer_applicable = next_timing->periodic_training && ((adel * 128 * next_timing_rate_mhz) / 1000000) > next_timing->tree_margin; + } + + emc_write(EMC_INTSTATUS_CLKCHANGE_COMPLETE, EMC_INTSTATUS); + emc_set_shadow_bypass(ACTIVE); + emc_write(emc_cfg, EMC_CFG); + emc_write(emc_sel_dpd_ctrl, EMC_SEL_DPD_CTRL); + emc_write(emc_cfg_pipe_clk_o | EMC_CFG_PIPE_CLK_CLK_ALWAYS_ON, EMC_CFG_PIPE_CLK); + emc_write(next_timing->emc_fdpd_ctrl_cmd_no_ramp & ~EMC_FDPD_CTRL_CMD_NO_RAMP_CMD_DPD_NO_RAMP_ENABLE, EMC_FDPD_CTRL_CMD_NO_RAMP); + + uint32_t bg_regulator_mode_change = ((next_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & EMC_PMACRO_BG_BIAS_CTRL_0_BGLP_E_PWRD) ^ (current_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & EMC_PMACRO_BG_BIAS_CTRL_0_BGLP_E_PWRD)) || ((next_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & + EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD) ^ (current_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD)); + + uint32_t enable_bg_regulator = (next_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD) == 0; + + /* Check if we need to change BG the regulator. */ + if (bg_regulator_mode_change) { + if (enable_bg_regulator) + emc_write(current_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & ~EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD, EMC_PMACRO_BG_BIAS_CTRL_0); + else + emc_write(current_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & ~EMC_PMACRO_BG_BIAS_CTRL_0_BGLP_E_PWRD, EMC_PMACRO_BG_BIAS_CTRL_0); + } + + /* Check if we need to turn on VREF generator. */ + if ((((!current_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX] & + EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_E_IVREF)) && + ((next_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX] & + EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_E_IVREF))) || + ((!(current_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX] & + EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQS_E_IVREF)) && + ((next_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX] & + EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQS_E_IVREF)))) + { + uint32_t pad_tx_ctrl = next_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]; + uint32_t last_pad_tx_ctrl = current_timing->burst_regs[EMC_PMACRO_DATA_PAD_TX_CTRL_INDEX]; + + next_dqs_e_ivref = pad_tx_ctrl & EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQS_E_IVREF; + next_dq_e_ivref = pad_tx_ctrl & EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_E_IVREF; + next_push = (last_pad_tx_ctrl & ~EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_E_IVREF & ~EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQS_E_IVREF) | next_dq_e_ivref | next_dqs_e_ivref; + emc_write(next_push, EMC_PMACRO_DATA_PAD_TX_CTRL); + udelay(1); + } else if (bg_regulator_mode_change) { + udelay(1); + } + + emc_set_shadow_bypass(ASSEMBLY); + + /* Step 2: + * Prelock the DLL. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 2\n"); + + if (next_timing->burst_regs[EMC_CFG_DIG_DLL_INDEX] & EMC_CFG_DIG_DLL_CFG_DLL_EN) { + dll_prelock(next_timing, dvfs_with_training, next_clk_src); + } else { + change_dll_src(next_timing, next_clk_src); + dll_disable(channel_mode); + } + + /* Step 3: + * Prepare autocal for the clock change. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 3\n"); + + emc_set_shadow_bypass(ACTIVE); + emc_write(next_timing->emc_auto_cal_config2, EMC_AUTO_CAL_CONFIG2); + emc_write(next_timing->emc_auto_cal_config3, EMC_AUTO_CAL_CONFIG3); + emc_write(next_timing->emc_auto_cal_config4, EMC_AUTO_CAL_CONFIG4); + emc_write(next_timing->emc_auto_cal_config5, EMC_AUTO_CAL_CONFIG5); + emc_write(next_timing->emc_auto_cal_config6, EMC_AUTO_CAL_CONFIG6); + emc_write(next_timing->emc_auto_cal_config7, EMC_AUTO_CAL_CONFIG7); + emc_write(next_timing->emc_auto_cal_config8, EMC_AUTO_CAL_CONFIG8); + emc_set_shadow_bypass(ASSEMBLY); + + emc_auto_cal_config |= (EMC_AUTO_CAL_CONFIG_AUTO_CAL_COMPUTE_START | auto_cal_en); + emc_write(emc_auto_cal_config, EMC_AUTO_CAL_CONFIG); + + /* Step 4: + * Update EMC_CFG. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 4\n"); + + if ((source_clock_period > 50000) && (dram_type == DRAM_TYPE_LPDDR4)) + ccfifo_write(EMC_SELF_REF, 1, 0); + else + emc_write(next_timing->emc_cfg_2, EMC_CFG_2); + + /* Step 5: + * Prepare reference variables for ZQCAL regs. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 5\n"); + + uint32_t emc_zcal_interval = current_timing->burst_regs[EMC_ZCAL_INTERVAL_INDEX]; + emc_zcal_interval &= 0xFF000000; + uint32_t emc_zcal_wait_cnt_old = current_timing->burst_regs[EMC_ZCAL_WAIT_CNT_INDEX]; + uint32_t emc_zcal_wait_cnt_new = next_timing->burst_regs[EMC_ZCAL_WAIT_CNT_INDEX]; + emc_zcal_wait_cnt_old &= ~EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK; + emc_zcal_wait_cnt_new &= ~EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK; + + if (dram_type == DRAM_TYPE_LPDDR4) + zq_wait_long = max((uint32_t)1, div_o3(1000000, destination_clock_period)); + else if (dram_type == DRAM_TYPE_LPDDR2 || is_lpddr3) + zq_wait_long = max(next_timing->min_mrs_wait, div_o3(360000, destination_clock_period)) + 4; + else if (dram_type == DRAM_TYPE_DDR3) + zq_wait_long = max((uint32_t)256, div_o3(320000, destination_clock_period) + 2); + else + zq_wait_long = 0; + + if (dram_type == DRAM_TYPE_LPDDR2 || is_lpddr3) + zq_wait_short = max(max(next_timing->min_mrs_wait, (uint32_t)6), div_o3(90000, destination_clock_period)) + 4; + else if (dram_type == DRAM_TYPE_DDR3) + zq_wait_short = max((uint32_t)64, div_o3(80000, destination_clock_period)) + 2; + else + zq_wait_short = 0; + + /* TODO: Actually use the reference variables. */ + (void)zq_wait_long; + (void)zq_wait_short; + + /* Step 6: + * Training code. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 6\n"); + + if ((train_ca || train_ca_vref) && (dram_dev_num == TWO_RANK)) { + emc_write(0x107, EMC_PIN); + } + + /* Step 7: + * Program FSP reference registers and send MRWs to new FSPWR. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 7\n"); + + /* Step 7.1: Bug 200024907 - Patch RP R2P */ + if (opt_war_200024907) { + nRTP = 16; + if (source_clock_period >= 1000000/1866) /* 535.91 ps */ + nRTP = 14; + if (source_clock_period >= 1000000/1600) /* 625.00 ps */ + nRTP = 12; + if (source_clock_period >= 1000000/1333) /* 750.19 ps */ + nRTP = 10; + if (source_clock_period >= 1000000/1066) /* 938.09 ps */ + nRTP = 8; + + deltaTWATM = max_t(uint32_t, div_o3(7500, source_clock_period), 8); + + /* + * Originally there was a + .5 in the tRPST calculation. + * However since we can't do FP in the kernel and the tRTM + * computation was in a floating point ceiling function, adding + * one to tRTP should be ok. There is no other source of non + * integer values, so the result was always going to be + * something for the form: f_ceil(N + .5) = N + 1; + */ + tRPST = ((current_timing->emc_mrw & 0x80) >> 7); + tRTM = current_timing->dram_timings[RL] + div_o3(3600, source_clock_period) + max_t(uint32_t, div_o3(7500, source_clock_period), 8) + tRPST + 1 + nRTP; + + if (current_timing->burst_regs[EMC_RP_INDEX] < tRTM) { + if (tRTM > (current_timing->burst_regs[EMC_R2P_INDEX] + current_timing->burst_regs[EMC_RP_INDEX])) { + R2P_war = tRTM - current_timing->burst_regs[EMC_RP_INDEX]; + RP_war = current_timing->burst_regs[EMC_RP_INDEX]; + TRPab_war = current_timing->burst_regs[EMC_TRPAB_INDEX]; + if (R2P_war > 63) { + RP_war = R2P_war + current_timing->burst_regs[EMC_RP_INDEX] - 63; + if (TRPab_war < RP_war) + TRPab_war = RP_war; + R2P_war = 63; + } + } else { + R2P_war = current_timing-> burst_regs[EMC_R2P_INDEX]; + RP_war = current_timing->burst_regs[EMC_RP_INDEX]; + TRPab_war = current_timing->burst_regs[EMC_TRPAB_INDEX]; + } + + if (RP_war < deltaTWATM) { + W2P_war = current_timing->burst_regs[EMC_W2P_INDEX] + deltaTWATM - RP_war; + if (W2P_war > 63) { + RP_war = RP_war + W2P_war - 63; + if (TRPab_war < RP_war) + TRPab_war = RP_war; + W2P_war = 63; + } + } else { + W2P_war = current_timing->burst_regs[EMC_W2P_INDEX]; + } + + if ((current_timing->burst_regs[EMC_W2P_INDEX] != W2P_war) + || (current_timing->burst_regs[EMC_R2P_INDEX] != R2P_war) + || (current_timing->burst_regs[EMC_RP_INDEX] != RP_war) + || (current_timing->burst_regs[EMC_TRPAB_INDEX] != TRPab_war)) + { + emc_set_shadow_bypass(ACTIVE); + emc_write(RP_war, EMC_RP); + emc_write(R2P_war, EMC_R2P); + emc_write(W2P_war, EMC_W2P); + emc_write(TRPab_war, EMC_TRPAB); + emc_set_shadow_bypass(ASSEMBLY); + udelay(1); + } + } + } + + if (!g_fsp_for_next_freq) { + mr13_flip_fspwr = (next_timing->emc_mrw3 & 0xffffff3f) | 0x80; + mr13_flip_fspop = (next_timing->emc_mrw3 & 0xffffff3f) | 0x00; + } else { + mr13_flip_fspwr = (next_timing->emc_mrw3 & 0xffffff3f) | 0x40; + mr13_flip_fspop = (next_timing->emc_mrw3 & 0xffffff3f) | 0xc0; + } + + mr13_catr_enable = (mr13_flip_fspwr & 0xFFFFFFFE) | 0x01; + + if (dram_dev_num == TWO_RANK) { + if (train_ca || train_ca_vref) { + if (train_swap_rank) { + mr13_flip_fspop = (mr13_flip_fspop & 0x3FFFFFFF) | 0x80000000; + mr13_catr_enable = (mr13_catr_enable & 0x3FFFFFFF)| 0x40000000; + } else { + mr13_flip_fspop = (mr13_flip_fspop & 0x3FFFFFFF) | 0x40000000; + mr13_catr_enable = (mr13_catr_enable & 0x3FFFFFFF) | 0x80000000; + } + } else { + if (train_swap_rank) + mr13_catr_enable = (mr13_catr_enable & 0x3FFFFFFF) | 0x40000000; + else + mr13_catr_enable = (mr13_catr_enable & 0x3FFFFFFF) | 0x80000000; + } + } + + if (dram_type == DRAM_TYPE_LPDDR4) { + emc_write(mr13_flip_fspwr, EMC_MRW3); + emc_write(next_timing->emc_mrw, EMC_MRW); + emc_write(next_timing->emc_mrw2, EMC_MRW2); + } + + /* Step 8: + * Program the shadow registers. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 8\n"); + + /* Set burst registers. */ + for (int i = 0; i < next_timing->num_burst; i++) { + uint32_t var = 0; + uint32_t wval = 0; + + if (!burst_regs_off[i]) + continue; + + var = burst_regs_off[i]; + + if (dvfs_with_training) { + if (train_ca || train_ca_vref) + wval = next_timing->shadow_regs_ca_train[i]; + else if (train_quse || train_quse_vref) + wval = next_timing->shadow_regs_quse_train[i]; + else if (train_wr || train_wr_vref || train_rd || train_rd_vref) + wval = next_timing->shadow_regs_rdwr_train[i]; + } + else + wval = next_timing->burst_regs[i]; + + if (dram_type != DRAM_TYPE_LPDDR4 && + (var == EMC_MRW6 || var == EMC_MRW7 || + var == EMC_MRW8 || var == EMC_MRW9 || + var == EMC_MRW10 || var == EMC_MRW11 || + var == EMC_MRW12 || var == EMC_MRW13 || + var == EMC_MRW14 || var == EMC_MRW15 || + var == EMC_TRAINING_CTRL)) + continue; + + if (var == EMC_CFG) { + wval &= ~EMC_CFG_DRAM_ACPD; + wval &= ~EMC_CFG_DYN_SELF_REF; + if (dram_type == DRAM_TYPE_LPDDR4) { + wval &= ~EMC_CFG_DRAM_CLKSTOP_SR; + wval &= ~EMC_CFG_DRAM_CLKSTOP_PD; + } + } else if ((var == EMC_MRS_WAIT_CNT) + && (dram_type == DRAM_TYPE_LPDDR2) + && opt_zcal_en_cc && !opt_cc_short_zcal && opt_short_zcal) { + wval = (wval & ~(EMC_MRS_WAIT_CNT_SHORT_WAIT_MASK << + EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT)) | + ((zq_wait_long & EMC_MRS_WAIT_CNT_SHORT_WAIT_MASK) << + EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT); + } else if ((var == EMC_ZCAL_WAIT_CNT) + && (dram_type == DRAM_TYPE_DDR3) + && opt_zcal_en_cc && !opt_cc_short_zcal && opt_short_zcal) { + wval = (wval & ~(EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK << + EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_SHIFT)) | + ((zq_wait_long & + EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK) << + EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT); + } else if ((var == EMC_ZCAL_INTERVAL) && opt_zcal_en_cc) { + wval = 0; /* EMC_ZCAL_INTERVAL reset value. */ + } else if (var == EMC_PMACRO_AUTOCAL_CFG_COMMON) { + wval |= EMC_PMACRO_AUTOCAL_CFG_COMMON_E_CAL_BYPASS_DVFS; + } else if (var == EMC_PMACRO_DATA_PAD_TX_CTRL) { + wval &= + ~(EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC | + EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC | + EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC | + EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC); + } else if (var == EMC_PMACRO_CMD_PAD_TX_CTRL) { + wval |= EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_DRVFORCEON; + wval &= ~(EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC | + EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC | + EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC | + EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC); + } else if (var == EMC_PMACRO_BRICK_CTRL_RFU1) { + wval &= 0xf800f800; + } else if (var == EMC_PMACRO_COMMON_PAD_TX_CTRL) { + wval &= 0xfffffff0; + } else if (var == EMC_TRAINING_CTRL) { + wval |= (train_swap_rank << 14); /* Training only. */ + } + + emc_write(wval, var); + } + + /* Do EMC refresh adjustment here (disabled). */ + set_over_temp_timing(next_timing, TEGRA_DRAM_OVER_TEMP_NONE); + + if (dram_type == DRAM_TYPE_LPDDR4) { + /* Use the current timing when training. */ + if (dvfs_with_training) + mrw_req = (23 << EMC_MRW_MRW_MA_SHIFT) | (current_timing->run_clocks & EMC_MRW_MRW_OP_MASK); + else + mrw_req = (23 << EMC_MRW_MRW_MA_SHIFT) | (next_timing->run_clocks & EMC_MRW_MRW_OP_MASK); + + emc_write(mrw_req, EMC_MRW); + } + + /* Per channel burst registers. */ + for (int i = 0; i < next_timing->num_burst_per_ch; i++) { + if (!burst_regs_per_ch_off[i]) + continue; + + if (dram_type != DRAM_TYPE_LPDDR4 && + (burst_regs_per_ch_off[i] == EMC_MRW6 || + burst_regs_per_ch_off[i] == EMC_MRW7 || + burst_regs_per_ch_off[i] == EMC_MRW8 || + burst_regs_per_ch_off[i] == EMC_MRW9 || + burst_regs_per_ch_off[i] == EMC_MRW10 || + burst_regs_per_ch_off[i] == EMC_MRW11 || + burst_regs_per_ch_off[i] == EMC_MRW12 || + burst_regs_per_ch_off[i] == EMC_MRW13 || + burst_regs_per_ch_off[i] == EMC_MRW14 || + burst_regs_per_ch_off[i] == EMC_MRW15)) + continue; + + /* Filter out second channel if not in DUAL_CHANNEL mode. */ + if ((channel_mode != DUAL_CHANNEL) && (burst_regs_per_ch_type[i] >= REG_EMC1)) + continue; + + emc_write_per_ch(next_timing->burst_reg_per_ch[i], burst_regs_per_ch_type[i], burst_regs_per_ch_off[i]); + } + + /* Vref regs. */ + for (int i = 0; i < next_timing->vref_num; i++) { + if (!vref_regs_per_ch_off[i]) + continue; + + if ((channel_mode != DUAL_CHANNEL) && (vref_regs_per_ch_type[i] >= REG_EMC1)) + continue; + + emc_write_per_ch(next_timing->vref_perch_regs[i], vref_regs_per_ch_type[i], vref_regs_per_ch_off[i]); + } + + /* Training regs. */ + if (dvfs_with_training) { + for (int i = 0; i < next_timing->training_mod_num; i++) { + if (!training_mod_regs_per_ch_off[i]) + continue; + + if ((channel_mode != DUAL_CHANNEL) && (training_mod_regs_per_ch_type[i] >= REG_EMC1)) + continue; + + emc_write_per_ch(next_timing->training_mod_regs[i], training_mod_regs_per_ch_type[i], training_mod_regs_per_ch_off[i]); + } + } + + /* Trimmers. */ + for (int i = 0; i < next_timing->num_trim; i++) { + uint32_t trim_reg; + + if (!trim_regs_off[i]) + continue; + + trim_reg = trim_regs_off[i]; + + if (compensate_trimmer_applicable && + (trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 || + trim_reg == EMC_DATA_BRLSHFT_0 || + trim_reg == EMC_DATA_BRLSHFT_1)) { + uint32_t reg = apply_periodic_compensation_trimmer(next_timing, trim_reg); + emc_write(reg, trim_regs_off[i]); + } else { + emc_write(next_timing->trim_regs[i], trim_regs_off[i]); + } + } + + /* Per channel trimmers. */ + for (int i = 0; i < next_timing->num_trim_per_ch; i++) { + uint32_t trim_reg; + + if (!trim_regs_per_ch_off[i]) + continue; + + if ((channel_mode != DUAL_CHANNEL) && (trim_regs_per_ch_type[i] >= REG_EMC1)) + continue; + + trim_reg = trim_regs_per_ch_off[i]; + + if (compensate_trimmer_applicable && + (trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 || + trim_reg == EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 || + trim_reg == EMC_DATA_BRLSHFT_0 || + trim_reg == EMC_DATA_BRLSHFT_1)) { + uint32_t reg = apply_periodic_compensation_trimmer(next_timing, trim_reg); + emc_write_per_ch(reg, trim_regs_per_ch_type[i], trim_regs_per_ch_off[i]); + } else { + emc_write_per_ch(next_timing->trim_perch_regs[i], trim_regs_per_ch_type[i], trim_regs_per_ch_off[i]); + } + } + + if (dvfs_with_training) { + if (train_wr && next_timing->periodic_training && (dram_type == DRAM_TYPE_LPDDR4)) { + periodic_compensation_handler(current_timing, next_timing, dram_dev_num, channel_mode, WRITE_TRAINING_SEQUENCE); + } + } else { + /* Write burst_mc_regs. */ + for (int i = 0; i < next_timing->num_mc_regs; i++) { + mc_write(next_timing->burst_mc_regs[i], burst_mc_regs_off[i]); + } + } + + /* Registers to be programmed on the faster clock. */ + if (!dvfs_with_training && (next_timing->rate < current_timing->rate)) { + for (int i = 0; i < next_timing->num_up_down; i++) { + mc_write(next_timing->la_scale_regs[i], la_scale_regs_off[i]); + } + } + + /* Step 9: + * LPDDR4 section A. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 9\n"); + + if (dram_type == DRAM_TYPE_LPDDR4) { + emc_write(emc_zcal_interval, EMC_ZCAL_INTERVAL); + emc_write(emc_zcal_wait_cnt_new, EMC_ZCAL_WAIT_CNT); + emc_write(emc_dbg_o | (EMC_DBG_WRITE_MUX_ACTIVE | EMC_DBG_WRITE_ACTIVE_ONLY), EMC_DBG); + emc_write(emc_zcal_interval, EMC_ZCAL_INTERVAL); + emc_write(emc_dbg_o, EMC_DBG); + + if (dvfs_with_training) { + emc_set_shadow_bypass(ACTIVE); + + emc_write(next_timing->burst_regs[EMC_PMACRO_AUTOCAL_CFG_COMMON_INDEX] | EMC_PMACRO_AUTOCAL_CFG_COMMON_E_CAL_BYPASS_DVFS, EMC_PMACRO_AUTOCAL_CFG_COMMON); + + if (train_ca || train_ca_vref) + emc_write(current_timing->burst_regs[EMC_FBIO_CFG5_INDEX] | EMC_FBIO_CFG5_CMD_BUS_RETURN_TO_ZERO, EMC_FBIO_CFG5); + + emc_set_shadow_bypass(ASSEMBLY); + + if (channel_mode) + ccfifo_write(EMC_CFG_SYNC, 0, 0); + + /* Change CFG_SWAP. */ + ccfifo_write(EMC_DBG, ((emc_dbg_o & 0xF3FFFFFF) | 0x4000000), 0); + } + } + + /* Step 10: + * LPDDR4 and DDR3 common section. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 10\n"); + + if (opt_dvfs_mode == MAN_SR || dram_type == DRAM_TYPE_LPDDR4) { + if (dram_type == DRAM_TYPE_LPDDR4) + ccfifo_write(EMC_SELF_REF, 0x101, 0); + else + ccfifo_write(EMC_SELF_REF, 0x1, 0); + + if (!(train_ca || train_ca_vref) && (dram_type == DRAM_TYPE_LPDDR4) && (source_clock_period <= zqcal_before_cc_cutoff)) { + ccfifo_write(EMC_MRW3, mr13_flip_fspwr ^ 0x40, 0); + ccfifo_write(EMC_MRW6, (next_timing->burst_regs[EMC_MRW6_INDEX] & 0xFFFF3F3F) | (current_timing->burst_regs[EMC_MRW6_INDEX] & 0x0000C0C0), 0); + ccfifo_write(EMC_MRW14, (next_timing->burst_regs[EMC_MRW14_INDEX] & 0xFFFF0707) | (current_timing->burst_regs[EMC_MRW14_INDEX] & 0x00003838), 0); + + if (dram_dev_num == TWO_RANK) { + ccfifo_write(EMC_MRW7, (next_timing->burst_regs[EMC_MRW7_INDEX] & 0xFFFF3F3F) | (current_timing->burst_regs[EMC_MRW7_INDEX] & 0x0000C0C0), 0); + ccfifo_write(EMC_MRW15, (next_timing->burst_regs[EMC_MRW15_INDEX] & 0xFFFF0707) | (current_timing->burst_regs[EMC_MRW15_INDEX] & 0x00003838), 0); + } + + if (opt_zcal_en_cc) { + if ((dram_dev_num == ONE_RANK) || shared_zq_resistor) + ccfifo_write(EMC_ZQ_CAL, 2 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_CAL_CMD, 0); + else + ccfifo_write(EMC_ZQ_CAL, EMC_ZQ_CAL_ZQ_CAL_CMD, 0); + } + } + } + + emc_dbg = emc_dbg_o; + if (dram_type == DRAM_TYPE_LPDDR4) { + if (dvfs_with_training) { + /* Change CFG_SWAP. */ + emc_dbg = ((emc_dbg_o & 0xF3FFFFFF) | 0x4000000 | EMC_DBG_WRITE_ACTIVE_ONLY); + ccfifo_write(EMC_DBG, emc_dbg, 0); + } + if (train_ca || train_ca_vref) { + ccfifo_write(EMC_PMACRO_DATA_RX_TERM_MODE, current_timing->burst_regs[EMC_PMACRO_DATA_RX_TERM_MODE_INDEX] & 0xFFFFFCCC, 0); + + if ((dram_dev_num == TWO_RANK) && train_swap_rank) { + ccfifo_write(EMC_MRW3, mr13_flip_fspop | 0x8, (1000 * current_timing->dram_timings[T_RP]) / source_clock_period); + ccfifo_write(EMC_MRW3, mr13_catr_enable | 0x8, 0); + } else { + ccfifo_write(EMC_MRW3, mr13_catr_enable | 0x8, (1000 * current_timing->dram_timings[T_RP]) / source_clock_period); + } + + ccfifo_write(EMC_TR_CTRL_0, 0x15A, 0); + ccfifo_write(EMC_INTSTATUS, 0, 1000000 / source_clock_period); + } else { + ccfifo_write(EMC_MRW3, mr13_flip_fspop | 0x8, (1000 * current_timing->dram_timings[T_RP]) / source_clock_period); + ccfifo_write(EMC_INTSTATUS, 0, tFC_lpddr4 / source_clock_period); + } + } + + bool ref_b4_sref_en = false; + bool cya_issue_pc_ref = false; + bool cya_allow_ref_cc = false; + + if ((dram_type == DRAM_TYPE_LPDDR4) || (opt_dvfs_mode != MAN_SR)) { + uint32_t t = 30 + (cya_allow_ref_cc ? (4000 * current_timing->dram_timings[T_RFC]) + ((1000 * current_timing->dram_timings[T_RP]) / source_clock_period) : 0); + ccfifo_write(EMC_PIN, emc_pin_o & ~(EMC_PIN_PIN_CKE_PER_DEV | EMC_PIN_PIN_CKEB | EMC_PIN_PIN_CKE), t); + } + + uint32_t ref_delay_mult = 1; + ref_delay_mult += ref_b4_sref_en ? 1 : 0; + ref_delay_mult += cya_allow_ref_cc ? 1 : 0; + ref_delay_mult += cya_issue_pc_ref ? 1 : 0; + uint32_t ref_delay = ref_delay_mult * ((1000 * current_timing->dram_timings[T_RP] / source_clock_period) + (1000 * current_timing->dram_timings[T_RFC] / source_clock_period)) + 20; + + /* Step 11: + * Ramp down. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 11\n"); + + ccfifo_write(EMC_CFG_SYNC, 0, (dram_type == DRAM_TYPE_LPDDR4) ? 0 : ref_delay); + ccfifo_write(EMC_DBG, emc_dbg | (EMC_DBG_WRITE_MUX_ACTIVE | EMC_DBG_WRITE_ACTIVE_ONLY), 0); + uint32_t ramp_down_wait = dvfs_power_ramp_down(false, current_timing, next_timing, source_clock_period); + + /* Step 12: + * Trigger the clock change. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 12\n"); + + ccfifo_write(EMC_STALL_THEN_EXE_AFTER_CLKCHANGE, 1, 0); + if (!dvfs_with_training) { + ccfifo_write(EMC_DBG, (emc_dbg & ~EMC_DBG_WRITE_ACTIVE_ONLY) | EMC_DBG_WRITE_MUX_ACTIVE, 0); + } + + /* Step 13: + * Ramp up. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 13\n"); + + uint32_t ramp_up_wait = dvfs_power_ramp_up(false, current_timing, next_timing, training, destination_clock_period); + ccfifo_write(EMC_DBG, emc_dbg, 0); + + /* Step 14: + * Bringup CKE pins. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 14\n"); + + if ((dram_type == DRAM_TYPE_LPDDR4)) { + uint32_t r = emc_pin_o | EMC_PIN_PIN_CKE; + if (train_ca || train_ca_vref) { + r = emc_pin_o & ~(EMC_PIN_PIN_CKE_PER_DEV | EMC_PIN_PIN_CKEB | EMC_PIN_PIN_CKE); + if (dram_dev_num == TWO_RANK) { + if (train_swap_rank) + ccfifo_write(EMC_PIN, r | EMC_PIN_PIN_CKE_PER_DEV | EMC_PIN_PIN_CKE, 0); + else + ccfifo_write(EMC_PIN, r | EMC_PIN_PIN_CKE_PER_DEV | EMC_PIN_PIN_CKEB, 0); + } + else + ccfifo_write(EMC_PIN, r, 0); + } else if (dram_dev_num == TWO_RANK) { + ccfifo_write(EMC_PIN, r | EMC_PIN_PIN_CKEB | EMC_PIN_PIN_CKE_PER_DEV, 0); + } else { + ccfifo_write(EMC_PIN, r & ~(EMC_PIN_PIN_CKEB | EMC_PIN_PIN_CKE_PER_DEV), 0); + } + } + + /* Step 15: + * Calculate zqlatch wait time; has dependency on ramping times. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 15\n"); + + if (source_clock_period <= zqcal_before_cc_cutoff) { + int t = (int)(ramp_up_wait + ramp_down_wait) / (int)destination_clock_period; + zq_latch_dvfs_wait_time = (int)tZQCAL_lpddr4_fc_adj - t; + } else { + zq_latch_dvfs_wait_time = tZQCAL_lpddr4_fc_adj - div_o3(1000 * next_timing->dram_timings[T_PDEX], destination_clock_period); + } + + if (!(train_ca || train_ca_vref) && (dram_type == DRAM_TYPE_LPDDR4) && opt_zcal_en_cc) { + if (dram_dev_num == ONE_RANK) { + if (source_clock_period > zqcal_before_cc_cutoff) { + ccfifo_write(EMC_ZQ_CAL, 2 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_CAL_CMD, div_o3(1000 * next_timing->dram_timings[T_PDEX], destination_clock_period)); + } + + if (!dvfs_with_training) { + ccfifo_write(EMC_MRW3, (mr13_flip_fspop & 0xF3FFFFF7) | 0xC000000, div_o3(1000 * next_timing->dram_timings[T_PDEX], destination_clock_period)); + ccfifo_write(EMC_SELF_REF, 0x100, 0); + ccfifo_write(EMC_REF, 0, 0); + } + + ccfifo_write(EMC_ZQ_CAL, 2 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_LATCH_CMD, max_t(int, 0, zq_latch_dvfs_wait_time)); + } else if (shared_zq_resistor) { + if (source_clock_period > zqcal_before_cc_cutoff) { + ccfifo_write(EMC_ZQ_CAL, 2 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_CAL_CMD, div_o3(1000 * next_timing->dram_timings[T_PDEX], destination_clock_period)); + } + + ccfifo_write(EMC_ZQ_CAL, 2 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_LATCH_CMD, max_t(int, 0, zq_latch_dvfs_wait_time) + div_o3(1000 * next_timing->dram_timings[T_PDEX], destination_clock_period)); + ccfifo_write(EMC_ZQ_CAL, 1 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_LATCH_CMD, 0); + + if (!dvfs_with_training) { + ccfifo_write(EMC_MRW3, (mr13_flip_fspop & 0xF3FFFFF7) | 0xC000000, 0); + ccfifo_write(EMC_SELF_REF, 0x100, 0); + ccfifo_write(EMC_REF, 0, 0); + } + + ccfifo_write(EMC_ZQ_CAL, 1 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_LATCH_CMD, tZQCAL_lpddr4 / destination_clock_period); + } else { + if (source_clock_period > zqcal_before_cc_cutoff) { + ccfifo_write(EMC_ZQ_CAL, EMC_ZQ_CAL_ZQ_CAL_CMD, div_o3(1000 * next_timing->dram_timings[T_PDEX], destination_clock_period)); + } + + if (!dvfs_with_training) { + ccfifo_write(EMC_MRW3, (mr13_flip_fspop & 0xF3FFFFF7) | 0xC000000, div_o3(1000 * next_timing->dram_timings[T_PDEX], destination_clock_period)); + ccfifo_write(EMC_SELF_REF, 0x100, 0); + ccfifo_write(EMC_REF, 0, 0); + } + + ccfifo_write(EMC_ZQ_CAL, EMC_ZQ_CAL_ZQ_LATCH_CMD, max_t(int, 0, zq_latch_dvfs_wait_time)); + } + } + + /* WAR: delay for zqlatch */ + ccfifo_write(EMC_INTSTATUS, 0, 10); + + /* Step 16: + * LPDDR4 Conditional Training Kickoff. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 16\n"); + + if (dvfs_with_training && (dram_type == DRAM_TYPE_LPDDR4)) { + ccfifo_write(EMC_INTSTATUS, 0, (1020000 / destination_clock_period)); + + uint32_t train_cmd = 0; + + if (train_ca) + train_cmd |= (1 << 1); /* CA */ + if (train_ca_vref) + train_cmd |= (1 << 5); /* CA_VREF */ + if (train_quse) + train_cmd |= (1 << 4); /* QUSE */ + if (train_quse_vref) + train_cmd |= (1 << 8); /* QUSE_VREF */ + if (train_wr) + train_cmd |= (1 << 3); /* WR */ + if (train_wr_vref) + train_cmd |= (1 << 6); /* WR_VREF */ + if (train_rd) + train_cmd |= (1 << 2); /* RD */ + if (train_rd_vref) + train_cmd |= (1 << 7); /* RD_VREF */ + + train_cmd |= (1 << 31); /* GO */ + + ccfifo_write(EMC_TRAINING_CMD, train_cmd, 0); + + if (bg_regulator_mode_change) { + if (enable_bg_regulator) + ccfifo_write(EMC_PMACRO_BG_BIAS_CTRL_0, current_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & ~EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD, 0); + else + ccfifo_write(EMC_PMACRO_BG_BIAS_CTRL_0, current_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & ~EMC_PMACRO_BG_BIAS_CTRL_0_BGLP_E_PWRD, 0); + } + + ccfifo_write(EMC_SWITCH_BACK_CTRL, 1, 0); + + if (!(train_ca || train_ca_vref) || train_swap_rank) { + ccfifo_write(EMC_MRW3, mr13_flip_fspop ^ 0xC0, 0); + ccfifo_write(EMC_INTSTATUS, 0, (1000000 / destination_clock_period)); + } + + ccfifo_write(EMC_PIN, emc_pin_o & ~(EMC_PIN_PIN_CKE_PER_DEV | EMC_PIN_PIN_CKEB | EMC_PIN_PIN_CKE), 0); + ccfifo_write(EMC_CFG_SYNC, 0, 0); + ccfifo_write(EMC_DBG, emc_dbg | (EMC_DBG_WRITE_ACTIVE_ONLY | EMC_DBG_WRITE_MUX_ACTIVE), 0); + + dvfs_power_ramp_down(true, current_timing, next_timing, destination_clock_period); + + ccfifo_write(EMC_STALL_THEN_EXE_AFTER_CLKCHANGE, 1, 0); + ccfifo_write(EMC_DBG, (emc_dbg & ~EMC_DBG_WRITE_ACTIVE_ONLY) | EMC_DBG_WRITE_MUX_ACTIVE, 0); + + dvfs_power_ramp_up(true, current_timing, next_timing, training, source_clock_period); + + ccfifo_write(EMC_DBG, emc_dbg, 0); + + if (dram_dev_num == TWO_RANK) + ccfifo_write(EMC_PIN, emc_pin_o | (EMC_PIN_PIN_CKE_PER_DEV | EMC_PIN_PIN_CKEB | EMC_PIN_PIN_CKE), 0); + else + ccfifo_write(EMC_PIN, (emc_pin_o & ~(EMC_PIN_PIN_CKE_PER_DEV | EMC_PIN_PIN_CKEB | EMC_PIN_PIN_CKE)) | EMC_PIN_PIN_CKE, 0); + + if (train_ca || train_ca_vref) { + ccfifo_write(EMC_TR_CTRL_0, 0x4A, (200000 / source_clock_period)); + ccfifo_write(EMC_TR_CTRL_0, 0x40, (1000000 / source_clock_period)); + ccfifo_write(EMC_MRW3, mr13_catr_enable & 0xFFFFFFFE, 0); + ccfifo_write(EMC_INTSTATUS, 0, (1000000 / source_clock_period)); + ccfifo_write(EMC_PMACRO_DATA_RX_TERM_MODE, current_timing->burst_regs[EMC_PMACRO_DATA_RX_TERM_MODE_INDEX], 0); + } + + ccfifo_write(EMC_DBG, emc_dbg_o, 0); + + if (opt_zcal_en_cc) { + ccfifo_write(EMC_ZQ_CAL, 2 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_CAL_CMD, 0); + ccfifo_write(EMC_ZQ_CAL, 2 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_LATCH_CMD, (1000000 / source_clock_period)); + + if (dram_dev_num == TWO_RANK) { + if (shared_zq_resistor) { + if (!(train_ca || train_ca_vref) || train_swap_rank) { + ccfifo_write(EMC_ZQ_CAL, 1 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_CAL_CMD, 0); + ccfifo_write(EMC_ZQ_CAL, 1 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_LATCH_CMD, (1000000 / source_clock_period)); + + if (!(train_ca || train_ca_vref)) + ccfifo_write(EMC_MRW3, ((mr13_flip_fspop ^ 0xC0) & 0xF3FFFFF7) | 0xC000000, 0); + } + + ccfifo_write(EMC_SELF_REF, 0x100, 0); + skip_zqcal = true; + } else { + if ((train_ca || train_ca_vref) && !train_swap_rank) { + ccfifo_write(EMC_SELF_REF, 0x100, 0); + skip_zqcal = true; + } else { + ccfifo_write(EMC_ZQ_CAL, 1 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_CAL_CMD, 0); + ccfifo_write(EMC_ZQ_CAL, 1 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_LATCH_CMD, (1000000 / source_clock_period)); + } + } + } + } + + if (!skip_zqcal) { + if (!(train_ca || train_ca_vref)) + ccfifo_write(EMC_MRW3, ((mr13_flip_fspop ^ 0xC0) & 0xF3FFFFF7) | 0xC000000, 0); + + ccfifo_write(EMC_SELF_REF, 0x100, 0); + } + } + + if (!skip_zqcal) { + /* Step 17: + * MANSR exit self refresh. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 17\n"); + + if ((opt_dvfs_mode == MAN_SR) && (dram_type != DRAM_TYPE_LPDDR4)) + ccfifo_write(EMC_SELF_REF, 0, 0); + + /* Step 18: + * Send MRWs to LPDDR3/DDR3. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 18\n"); + + if (dram_type == DRAM_TYPE_LPDDR2) { + ccfifo_write(EMC_MRW2, next_timing->emc_mrw2, 0); + ccfifo_write(EMC_MRW, next_timing->emc_mrw, 0); + + if (is_lpddr3) { + ccfifo_write(EMC_MRW4, next_timing->emc_mrw4, 0); + } + } else if (dram_type == DRAM_TYPE_DDR3) { + if (opt_dll_mode == DLL_ON) { + ccfifo_write(EMC_EMRS, next_timing->emc_emrs & ~EMC_EMRS_USE_EMRS_LONG_CNT, 0); + } + ccfifo_write(EMC_EMRS2, next_timing->emc_emrs2 & ~EMC_EMRS2_USE_EMRS2_LONG_CNT, 0); + ccfifo_write(EMC_MRS, next_timing->emc_mrs | EMC_EMRS_USE_EMRS_LONG_CNT, 0); + } + + /* Step 19: + * ZQCAL for LPDDR3/DDR3 + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 19\n"); + + if (opt_zcal_en_cc) { + if (dram_type == DRAM_TYPE_LPDDR2) { + uint32_t r; + uint32_t zq_op = opt_cc_short_zcal ? 0x56 : 0xAB; + uint32_t zcal_wait_time_ps = opt_cc_short_zcal ? 90000 : 360000; + uint32_t zcal_wait_time_clocks = div_o3(zcal_wait_time_ps, destination_clock_period); + r = zcal_wait_time_clocks << EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_SHIFT | zcal_wait_time_clocks << EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_SHIFT; + + ccfifo_write(EMC_MRS_WAIT_CNT2, r, 0); + ccfifo_write(EMC_MRW, 2 << EMC_MRW_MRW_DEV_SELECTN_SHIFT | EMC_MRW_USE_MRW_EXT_CNT | 10 << EMC_MRW_MRW_MA_SHIFT | zq_op << EMC_MRW_MRW_OP_SHIFT, 0); + + if (dram_dev_num == TWO_RANK) { + r = 1 << EMC_MRW_MRW_DEV_SELECTN_SHIFT | EMC_MRW_USE_MRW_EXT_CNT | 10 << EMC_MRW_MRW_MA_SHIFT | zq_op << EMC_MRW_MRW_OP_SHIFT; + ccfifo_write(EMC_MRW, r, 0); + } + } else if (dram_type == DRAM_TYPE_DDR3) { + uint32_t zq_op = opt_cc_short_zcal ? 0 : EMC_ZQ_CAL_LONG; + ccfifo_write(EMC_ZQ_CAL, zq_op | 2 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_CAL_CMD, 0); + + if (dram_dev_num == TWO_RANK) { + ccfifo_write(EMC_ZQ_CAL, zq_op | 1 << EMC_ZQ_CAL_DEV_SEL_SHIFT | EMC_ZQ_CAL_ZQ_CAL_CMD, 0); + } + } + } + } + + if (bg_regulator_mode_change) { + emc_set_shadow_bypass(ACTIVE); + + uint32_t bg_regulator_switch_complete_wait_clks = ramp_up_wait > 1250000 ? 0 : (1250000 - ramp_up_wait) / destination_clock_period; + + if (dvfs_with_training) { + bg_regulator_switch_complete_wait_clks = (1250000 / source_clock_period); + ccfifo_write(EMC_PMACRO_BG_BIAS_CTRL_0, current_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX], bg_regulator_switch_complete_wait_clks); + } else { + ccfifo_write(EMC_PMACRO_BG_BIAS_CTRL_0, next_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX], bg_regulator_switch_complete_wait_clks); + } + + emc_set_shadow_bypass(ASSEMBLY); + } + + /* Step 20: + * Issue ref and optional QRST. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 20\n"); + + if (dvfs_with_training || (dram_type != DRAM_TYPE_LPDDR4)) + ccfifo_write(EMC_REF, 0, 0); + + if (opt_do_sw_qrst) { + ccfifo_write(EMC_ISSUE_QRST, 1, 0); + ccfifo_write(EMC_ISSUE_QRST, 0, 2); + } + + /* Step 21: + * Restore ZCAL and ZCAL interval. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 21\n"); + + if (save_restore_clkstop_pd || opt_zcal_en_cc) { + emc_set_shadow_bypass(ACTIVE); + + if (opt_zcal_en_cc) { + if (dvfs_with_training) { + ccfifo_write(EMC_ZCAL_INTERVAL, current_timing->burst_regs[EMC_ZCAL_INTERVAL_INDEX], 0); + } else if (dram_type != DRAM_TYPE_LPDDR4) { + ccfifo_write(EMC_ZCAL_INTERVAL, next_timing->burst_regs[EMC_ZCAL_INTERVAL_INDEX], 0); + } + } + + if (save_restore_clkstop_pd) { + ccfifo_write(EMC_CFG, next_timing->burst_regs[EMC_CFG_INDEX] & ~EMC_CFG_DYN_SELF_REF, 0); + } + + if (dvfs_with_training && (dram_type == DRAM_TYPE_LPDDR4)) { + ccfifo_write(EMC_SEL_DPD_CTRL, current_timing->emc_sel_dpd_ctrl, 0); + } + + emc_set_shadow_bypass(ASSEMBLY); + } + + /* Step 22: + * Restore EMC_CFG_PIPE_CLK. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 22\n"); + + ccfifo_write(EMC_CFG_PIPE_CLK, emc_cfg_pipe_clk_o, 0); + + if (bg_regulator_mode_change) { + if (enable_bg_regulator) { + emc_write(next_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & ~EMC_PMACRO_BG_BIAS_CTRL_0_BGLP_E_PWRD, EMC_PMACRO_BG_BIAS_CTRL_0); + } else { + emc_write(next_timing->burst_regs[EMC_PMACRO_BG_BIAS_CTRL_0_INDEX] & ~EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD, EMC_PMACRO_BG_BIAS_CTRL_0); + } + } + + /* Step 23: + * Do clock change. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 23\n"); + + if (dvfs_with_training) { + car->clk_source_emc_safe = car->clk_source_emc; + change_dll_src(current_timing, car->clk_source_emc); + } + + uint32_t cfg_dig_dll_tmp = emc_read(EMC_CFG_DIG_DLL); + cfg_dig_dll_tmp |= EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_TRAFFIC; + cfg_dig_dll_tmp &= ~EMC_CFG_DIG_DLL_CFG_DLL_STALL_RW_UNTIL_LOCK; + cfg_dig_dll_tmp &= ~EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_UNTIL_LOCK; + cfg_dig_dll_tmp &= ~EMC_CFG_DIG_DLL_CFG_DLL_EN; + cfg_dig_dll_tmp = (cfg_dig_dll_tmp & ~EMC_CFG_DIG_DLL_CFG_DLL_MODE_MASK) | (2 << EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT); + emc_write(cfg_dig_dll_tmp, EMC_CFG_DIG_DLL); + + car->clk_source_emc = next_clk_src; + wait_for_update(EMC_INTSTATUS, EMC_INTSTATUS_CLKCHANGE_COMPLETE, true, REG_EMC); + + /* Step 24: + * Save training results. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 24\n"); + + if (dvfs_with_training) { + uint32_t emc_dbg_tmp = emc_read(EMC_DBG); + emc_write(emc_dbg_tmp | 1, EMC_DBG); /* Set READ_MUX to ASSEMBLY. */ + + /* Save CA results. */ + if (train_ca) { + next_timing->trim_perch_regs[REG_EMC0_EMC_CMD_BRLSHFT_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_CMD_BRLSHFT_0); + next_timing->trim_perch_regs[REG_EMC1_EMC_CMD_BRLSHFT_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_CMD_BRLSHFT_1): 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1,EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5) : 0; + + if (train_self_refresh) { + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2_INDEX] = emc_read(EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2); + } + } + + /* Save CA_VREF results. */ + if (train_ca_vref) { + next_timing->burst_reg_per_ch[REG_EMC0_EMC_MRW10_INDEX] = (emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_CA_VREF) & 0xFFFF) | 0x880C0000; + next_timing->burst_reg_per_ch[REG_EMC1_EMC_MRW10_INDEX] = (channel_mode ? emc_read_per_ch(REG_EMC1, EMC_TRAINING_OPT_CA_VREF) & 0xFFFF : 0) | 0x880C0000; + + if (dram_dev_num == TWO_RANK) { + next_timing->burst_reg_per_ch[REG_EMC0_EMC_MRW11_INDEX] = ((emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_CA_VREF) >> 16) & 0xFF) | (emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_CA_VREF) >> 24 << 8) | (0x480C0000 & 0xFFFFFF00); + next_timing->burst_reg_per_ch[REG_EMC1_EMC_MRW11_INDEX] = (((channel_mode ? emc_read_per_ch(REG_EMC1, EMC_TRAINING_OPT_CA_VREF) : 0) >> 16) & 0xFF) | ((channel_mode ? emc_read_per_ch(REG_EMC1, EMC_TRAINING_OPT_CA_VREF) : 0) >> 24 << 8) | (0x480C0000 & 0xFFFFFF00); + } else { + next_timing->burst_reg_per_ch[REG_EMC0_EMC_MRW11_INDEX] = ((emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_CA_VREF) >> 16) & 0xFF) | (emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_CA_VREF) >> 24 << 8) | (0xC80C0000 & 0xFFFFFF00); + + next_timing->burst_reg_per_ch[REG_EMC1_EMC_MRW11_INDEX] = (((channel_mode ? emc_read_per_ch(REG_EMC1, EMC_TRAINING_OPT_CA_VREF) : 0) >> 16) & 0xFF) | ((channel_mode ? emc_read_per_ch(REG_EMC1, EMC_TRAINING_OPT_CA_VREF) : 0) >> 24 << 8) | (0xC80C0000 & 0xFFFFFF00); + } + } + + /* Save QUSE results. */ + if (train_quse || train_rd) { + next_timing->trim_perch_regs[REG_EMC0_EMC_QUSE_BRLSHFT_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_QUSE_BRLSHFT_0); + next_timing->trim_perch_regs[REG_EMC1_EMC_QUSE_BRLSHFT_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_QUSE_BRLSHFT_1) : 0; + + next_timing->trim_regs[EMC_PMACRO_QUSE_DDLL_RANK0_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_QUSE_DDLL_RANK0_0); + next_timing->trim_regs[EMC_PMACRO_QUSE_DDLL_RANK0_1_INDEX]= emc_read_per_ch(REG_EMC0, EMC_PMACRO_QUSE_DDLL_RANK0_1); + next_timing->trim_regs[EMC_PMACRO_QUSE_DDLL_RANK0_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_QUSE_DDLL_RANK0_2) : 0; + next_timing->trim_regs[EMC_PMACRO_QUSE_DDLL_RANK0_3_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_QUSE_DDLL_RANK0_3) : 0; + + if (dram_dev_num == TWO_RANK) { + next_timing->trim_perch_regs[REG_EMC0_EMC_QUSE_BRLSHFT_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_QUSE_BRLSHFT_2); + next_timing->trim_perch_regs[REG_EMC1_EMC_QUSE_BRLSHFT_3_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_QUSE_BRLSHFT_3) : 0; + + next_timing->trim_regs[EMC_PMACRO_QUSE_DDLL_RANK1_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_QUSE_DDLL_RANK1_0); + next_timing->trim_regs[EMC_PMACRO_QUSE_DDLL_RANK1_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_QUSE_DDLL_RANK1_1); + next_timing->trim_regs[EMC_PMACRO_QUSE_DDLL_RANK1_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_QUSE_DDLL_RANK1_2) : 0; + next_timing->trim_regs[EMC_PMACRO_QUSE_DDLL_RANK1_3_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_QUSE_DDLL_RANK1_3) : 0; + } + } + + /* Save QUSE_VREF results. */ + if (train_quse_vref) { + if (dram_dev_num == TWO_RANK) { + uint32_t emc0_opt_dqs_array[4] = {0}; + uint32_t emc1_opt_dqs_array[4] = {0}; + uint32_t emc1_training_opt_dqs_ib_vref_rank0_val = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_TRAINING_OPT_DQS_IB_VREF_RANK0) : 0; + uint32_t emc1_training_opt_dqs_ib_vref_rank1_val = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_TRAINING_OPT_DQS_IB_VREF_RANK1) : 0; + + for (int i = 0; i < 4; i++) { + emc0_opt_dqs_array[i] = (emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQS_IB_VREF_RANK0) >> (8 * i)) & 0xFF; + emc1_opt_dqs_array[i] = (emc1_training_opt_dqs_ib_vref_rank0_val >> (8 * i)) & 0xFF; + } + + uint32_t ib_vref_dqs_0 = 0; + uint32_t ib_vref_dqs_1 = 0; + for (int i = 0; i < 4; i++) + { + ib_vref_dqs_0 |= (emc0_opt_dqs_array[i] + ((emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQS_IB_VREF_RANK1) >> (8 * i)) & 0xFF)) >> 1 << (8 * i); + ib_vref_dqs_1 |= (emc1_opt_dqs_array[i] + ((emc1_training_opt_dqs_ib_vref_rank1_val >> (8 * i)) & 0xFF)) >> 1 << (8 * i); + } + + next_timing->trim_regs[EMC_PMACRO_IB_VREF_DQS_0_INDEX] = ib_vref_dqs_0; + next_timing->trim_regs[EMC_PMACRO_IB_VREF_DQS_1_INDEX] = ib_vref_dqs_1; + } + else + { + next_timing->trim_regs[EMC_PMACRO_IB_VREF_DQS_0_INDEX] = emc_read(EMC_PMACRO_IB_VREF_DQS_0); + next_timing->trim_regs[EMC_PMACRO_IB_VREF_DQS_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_VREF_DQS_1) : 0; + } + } + + /* Save RD results. */ + if (train_rd) { + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2_INDEX]= channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3) : 0; + + if (dram_dev_num == TWO_RANK) { + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) : 0; + } + + if (train_self_refresh) { + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2) : 0; + + if (dram_dev_num == TWO_RANK) { + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2); + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1) : 0; + next_timing->trim_regs[EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2) : 0; + } + } + + /* Save RD_VREF results. */ + if (train_rd_vref) { + uint8_t ib_vref_dq_byte0_icr = (emc_read(EMC_PMACRO_IB_VREF_DQ_0) & 0x7F) + (next_timing->save_restore_mod_regs[0] & 0x7F); + if (next_timing->save_restore_mod_regs[0] & 0x80000000) + ib_vref_dq_byte0_icr = (emc_read(EMC_PMACRO_IB_VREF_DQ_0) & 0x7F) - (next_timing->save_restore_mod_regs[0] & 0x7F); + + uint8_t ib_vref_dq_byte1_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_0) >> 8) & 0x7F) + (next_timing->save_restore_mod_regs[1] & 0x7F); + if (next_timing->save_restore_mod_regs[1] & 0x80000000) + ib_vref_dq_byte1_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_0) >> 8) & 0x7F) - (next_timing->save_restore_mod_regs[1] & 0x7F); + + uint8_t ib_vref_dq_byte2_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_0) >> 16) & 0x7F) + (next_timing->save_restore_mod_regs[2] & 0x7F); + if (next_timing->save_restore_mod_regs[2] & 0x80000000) + ib_vref_dq_byte2_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_0) >> 16) & 0x7F) - (next_timing->save_restore_mod_regs[2] & 0x7F); + + uint8_t ib_vref_dq_byte3_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_0) >> 24) & 0x7F) + (next_timing->save_restore_mod_regs[3] & 0x7F); + if (next_timing->save_restore_mod_regs[3] & 0x80000000) + ib_vref_dq_byte3_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_0) >> 24) & 0x7F) - (next_timing->save_restore_mod_regs[3] & 0x7F); + + next_timing->trim_regs[EMC_PMACRO_IB_VREF_DQ_0_INDEX] = ((ib_vref_dq_byte0_icr & 0x7F) | (ib_vref_dq_byte1_icr & 0x7F) << 8) | ((ib_vref_dq_byte2_icr & 0x7F) << 16) | ((ib_vref_dq_byte3_icr & 0x7F) << 24); + + uint8_t ib_vref_dq_byte4_icr = (emc_read(EMC_PMACRO_IB_VREF_DQ_1) & 0x7F) + (next_timing->save_restore_mod_regs[4] & 0x7F); + if (next_timing->save_restore_mod_regs[4] & 0x80000000) + ib_vref_dq_byte4_icr = (emc_read(EMC_PMACRO_IB_VREF_DQ_1) & 0x7F) - (next_timing->save_restore_mod_regs[4] & 0x7F); + + uint8_t ib_vref_dq_byte5_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_1) >> 8) & 0x7F) + (next_timing->save_restore_mod_regs[5] & 0x7F); + if (next_timing->save_restore_mod_regs[5] & 0x80000000) + ib_vref_dq_byte5_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_1) >> 8) & 0x7F) - (next_timing->save_restore_mod_regs[5] & 0x7F); + + uint8_t ib_vref_dq_byte6_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_1) >> 16) & 0x7F) + (next_timing->save_restore_mod_regs[6] & 0x7F); + if (next_timing->save_restore_mod_regs[6] & 0x80000000) + ib_vref_dq_byte6_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_1) >> 16) & 0x7F) - (next_timing->save_restore_mod_regs[6] & 0x7F); + + uint8_t ib_vref_dq_byte7_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_1) >> 24) & 0x7F) + (next_timing->save_restore_mod_regs[7] & 0x7F); + if (next_timing->save_restore_mod_regs[7] & 0x80000000) + ib_vref_dq_byte7_icr = ((emc_read(EMC_PMACRO_IB_VREF_DQ_1) >> 24) & 0x7F) - (next_timing->save_restore_mod_regs[7] & 0x7F); + + next_timing->trim_regs[EMC_PMACRO_IB_VREF_DQ_1_INDEX] = ((ib_vref_dq_byte4_icr & 0x7F) | (ib_vref_dq_byte5_icr & 0x7F) << 8) | ((ib_vref_dq_byte6_icr & 0x7F) << 16) | ((ib_vref_dq_byte7_icr & 0x7F) << 24); + } + } + + /* Save WR results. */ + if (train_wr) { + next_timing->trim_perch_regs[REG_EMC0_EMC_DATA_BRLSHFT_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_DATA_BRLSHFT_0); + next_timing->trim_perch_regs[REG_EMC1_EMC_DATA_BRLSHFT_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_DATA_BRLSHFT_0) : 0; + + if (dram_dev_num == TWO_RANK) { + next_timing->trim_perch_regs[REG_EMC0_EMC_DATA_BRLSHFT_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_DATA_BRLSHFT_1); + next_timing->trim_perch_regs[REG_EMC1_EMC_DATA_BRLSHFT_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_DATA_BRLSHFT_1) : 0; + } + + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3) : 0; + + if (dram_dev_num == TWO_RANK) { + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3) : 0; + } + + if (train_self_refresh) { + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2) : 0; + + if (dram_dev_num == TWO_RANK) { + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2_INDEX] = emc_read_per_ch(REG_EMC0, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2); + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1) : 0; + next_timing->trim_regs[EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2_INDEX] = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2) : 0; + } + } + + /* Save WR_VREF results. */ + if (train_wr_vref) { + uint32_t emc1_ranks_sub_partitions = channel_mode ? emc_read_per_ch(REG_EMC1, EMC_TRAINING_OPT_DQ_OB_VREF) : 0; + + uint8_t emc0_ib_vref_dq_byte8_modded_plus = next_timing->save_restore_mod_regs[8] + emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQ_OB_VREF); + if (next_timing->save_restore_mod_regs[8] & 0x80000000) + emc0_ib_vref_dq_byte8_modded_plus = emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQ_OB_VREF) - next_timing->save_restore_mod_regs[8]; + + uint8_t emc0_mrw12_op_sp1 = ((emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQ_OB_VREF) & 0xFFFF) >> 8) + next_timing->save_restore_mod_regs[9]; + if (next_timing->save_restore_mod_regs[9] & 0x80000000) + emc0_mrw12_op_sp1 = ((emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQ_OB_VREF) & 0xFFFF) >> 8) - next_timing->save_restore_mod_regs[9]; + + uint8_t emc0_mrw13_op_sp0 = ((emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQ_OB_VREF) >> 16) & 0xFF) + next_timing->save_restore_mod_regs[8]; + if (next_timing->save_restore_mod_regs[8] & 0x80000000) + emc0_mrw13_op_sp0 = ((emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQ_OB_VREF) >> 16) & 0xFF) - next_timing->save_restore_mod_regs[8]; + + uint8_t emc0_ib_vref_dq_byte9_modded_a_plus = next_timing->save_restore_mod_regs[9] + (emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQ_OB_VREF) >> 24); + if (next_timing->save_restore_mod_regs[9] & 0x80000000) + emc0_ib_vref_dq_byte9_modded_a_plus = (emc_read_per_ch(REG_EMC0, EMC_TRAINING_OPT_DQ_OB_VREF) >> 24) - (uint8_t)next_timing->save_restore_mod_regs[9]; + + uint8_t emc0_ib_vref_dq_byte10_modded_plus = emc1_ranks_sub_partitions + next_timing->save_restore_mod_regs[10]; + if (next_timing->save_restore_mod_regs[10] & 0x80000000) + emc0_ib_vref_dq_byte10_modded_plus = emc1_ranks_sub_partitions - next_timing->save_restore_mod_regs[10]; + + uint8_t emc0_ib_vref_dq_byte11_modded_plus = ((emc1_ranks_sub_partitions & 0xFFFF) >> 8) + next_timing->save_restore_mod_regs[11]; + if (next_timing->save_restore_mod_regs[11] & 0x80000000) + emc0_ib_vref_dq_byte11_modded_plus = ((emc1_ranks_sub_partitions & 0xFFFF) >> 8) - next_timing->save_restore_mod_regs[11]; + + uint8_t emc1_mrw13_op_sp0 = ((emc1_ranks_sub_partitions >> 16) & 0xFF) + next_timing->save_restore_mod_regs[10]; + if (next_timing->save_restore_mod_regs[10] & 0x80000000) + emc1_mrw13_op_sp0 = ((emc1_ranks_sub_partitions >> 16) & 0xFF) - next_timing->save_restore_mod_regs[10]; + + uint8_t emc1_mrw13_op_sp1 = (emc1_ranks_sub_partitions >> 24) + next_timing->save_restore_mod_regs[11]; + if (next_timing->save_restore_mod_regs[11] & 0x80000000) + emc1_mrw13_op_sp1 = (emc1_ranks_sub_partitions >> 24) - next_timing->save_restore_mod_regs[11]; + + next_timing->burst_reg_per_ch[REG_EMC1_EMC_MRW12_INDEX] = (uint8_t)emc0_ib_vref_dq_byte10_modded_plus | 0x880E0000 | (emc0_ib_vref_dq_byte11_modded_plus << 8); + next_timing->burst_reg_per_ch[REG_EMC0_EMC_MRW12_INDEX] = emc0_ib_vref_dq_byte8_modded_plus | 0x880E0000 | (emc0_mrw12_op_sp1 << 8); + + if (dram_dev_num == TWO_RANK) { + next_timing->burst_reg_per_ch[REG_EMC0_EMC_MRW13_INDEX] = emc0_ib_vref_dq_byte9_modded_a_plus << 8 | emc0_mrw13_op_sp0 | 0x480E0000; + next_timing->burst_reg_per_ch[REG_EMC1_EMC_MRW13_INDEX] = (emc1_mrw13_op_sp1 << 8) | emc1_mrw13_op_sp0 | 0x480E0000; + } else { + next_timing->burst_reg_per_ch[REG_EMC0_EMC_MRW13_INDEX] = emc0_ib_vref_dq_byte9_modded_a_plus << 8 | emc0_mrw13_op_sp0 | 0xC80E0000; + next_timing->burst_reg_per_ch[REG_EMC1_EMC_MRW13_INDEX] = (emc1_mrw13_op_sp1 << 8) | emc1_mrw13_op_sp0 | 0xC80E0000; + } + } + } + + emc_write(emc_dbg_tmp, EMC_DBG); + } + + /* Step 25: + * Program MC updown registers. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 25\n"); + + if ((next_timing->rate > current_timing->rate) && !dvfs_with_training) { + for (int i = 0; i < next_timing->num_up_down; i++) { + mc_write(next_timing->la_scale_regs[i], la_scale_regs_off[i]); + } + + /* Request a timing update. */ + emc_timing_update(channel_mode); + } + + /* Step 26: + * Restore ZCAL registers. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 26\n"); + + if (dram_type == DRAM_TYPE_LPDDR4) { + emc_set_shadow_bypass(ACTIVE); + emc_write(next_timing->burst_regs[EMC_ZCAL_WAIT_CNT_INDEX], EMC_ZCAL_WAIT_CNT); + emc_write(next_timing->burst_regs[EMC_ZCAL_INTERVAL_INDEX], EMC_ZCAL_INTERVAL); + emc_set_shadow_bypass(ASSEMBLY); + } + + if ((dram_type != DRAM_TYPE_LPDDR4) + && opt_zcal_en_cc + && !opt_short_zcal + && opt_cc_short_zcal) + { + udelay(2); + + emc_set_shadow_bypass(ACTIVE); + if (dram_type == DRAM_TYPE_LPDDR2) { + emc_write(next_timing->burst_regs[EMC_MRS_WAIT_CNT_INDEX], EMC_MRS_WAIT_CNT); + } else if (dram_type == DRAM_TYPE_DDR3) { + emc_write(next_timing->burst_regs[EMC_ZCAL_WAIT_CNT_INDEX], EMC_ZCAL_WAIT_CNT); + } + emc_set_shadow_bypass(ASSEMBLY); + } + + /* Step 27: + * Restore EMC_CFG, FDPD registers. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 27\n"); + + emc_set_shadow_bypass(ACTIVE); + emc_write(next_timing->burst_regs[EMC_CFG_INDEX], EMC_CFG); + emc_set_shadow_bypass(ASSEMBLY); + emc_write(next_timing->emc_fdpd_ctrl_cmd_no_ramp, EMC_FDPD_CTRL_CMD_NO_RAMP); + emc_write(next_timing->emc_sel_dpd_ctrl, EMC_SEL_DPD_CTRL); + + /* Step 28: + * Training recover. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 28\n"); + + if (dvfs_with_training && (dram_type == DRAM_TYPE_LPDDR4)) { + emc_set_shadow_bypass(ACTIVE); + emc_write(next_timing->burst_regs[EMC_CFG_INDEX], EMC_CFG); + emc_write(next_timing->emc_sel_dpd_ctrl, EMC_SEL_DPD_CTRL); + emc_write(current_timing->burst_regs[EMC_ZCAL_WAIT_CNT_INDEX], EMC_ZCAL_WAIT_CNT); + emc_write(current_timing->burst_regs[EMC_ZCAL_INTERVAL_INDEX], EMC_ZCAL_INTERVAL); + emc_write(current_timing->emc_auto_cal_config2, EMC_AUTO_CAL_CONFIG2); + emc_write(current_timing->emc_auto_cal_config3, EMC_AUTO_CAL_CONFIG3); + emc_write(current_timing->emc_auto_cal_config4, EMC_AUTO_CAL_CONFIG4); + emc_write(current_timing->emc_auto_cal_config5, EMC_AUTO_CAL_CONFIG5); + emc_write(current_timing->emc_auto_cal_config6, EMC_AUTO_CAL_CONFIG6); + emc_write(current_timing->emc_auto_cal_config7, EMC_AUTO_CAL_CONFIG7); + emc_write(current_timing->emc_auto_cal_config8, EMC_AUTO_CAL_CONFIG8); + emc_set_shadow_bypass(ASSEMBLY); + emc_write(next_timing->burst_regs[EMC_TR_DVFS_INDEX] & ~EMC_TR_DVFS_TRAINING_DVFS, EMC_TR_DVFS); + } + + emc_set_shadow_bypass(ACTIVE); + emc_write(next_timing->burst_regs[EMC_PMACRO_AUTOCAL_CFG_COMMON_INDEX], EMC_PMACRO_AUTOCAL_CFG_COMMON); + emc_set_shadow_bypass(ASSEMBLY); + + /* Step 29: + * Power fix WAR. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 29\n"); + + emc_write(EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE0 | + EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE1 | + EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE2 | + EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE3 | + EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE4 | + EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE5 | + EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE6 | + EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE7, + EMC_PMACRO_CFG_PM_GLOBAL_0); + emc_write(EMC_PMACRO_TRAINING_CTRL_0_CH0_TRAINING_E_WRPTR, EMC_PMACRO_TRAINING_CTRL_0); + emc_write(EMC_PMACRO_TRAINING_CTRL_1_CH1_TRAINING_E_WRPTR, EMC_PMACRO_TRAINING_CTRL_1); + emc_write(0, EMC_PMACRO_CFG_PM_GLOBAL_0); + + /* Step 30: + * Re-enable autocal. + */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - step 30\n"); + + if (dvfs_with_training) { + emc_auto_cal_config = current_timing->emc_auto_cal_config; + + /* Restore FSP to account for switch back. Only needed in training. */ + g_fsp_for_next_freq = !g_fsp_for_next_freq; + } else { + emc_auto_cal_config = next_timing->emc_auto_cal_config; + + if (next_timing->burst_regs[EMC_CFG_DIG_DLL_INDEX] & EMC_CFG_DIG_DLL_CFG_DLL_EN) { + dll_enable_stall(channel_mode); + } + } + emc_write(emc_auto_cal_config, EMC_AUTO_CAL_CONFIG); + + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Clock set - done!\n"); +} + +static void do_periodic_emc_compensation(tegra_emc_timing_t* current_timing) { + uint32_t reg_count = 10; + uint32_t reg_list[] = { + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0, + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1, + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2, + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3, + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0, + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1, + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2, + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3, + EMC_DATA_BRLSHFT_0, + EMC_DATA_BRLSHFT_1 + }; + + if (current_timing->periodic_training) { + int dram_dev_num = ((mc_read(MC_EMEM_ADR_CFG) & 1) + 1); + bool channel_mode = ((current_timing->burst_regs[EMC_FBIO_CFG7_INDEX] >> 2) & 1); + + uint32_t emc_cfg_o = emc_read(EMC_CFG); + uint32_t emc_cfg = emc_cfg_o & ~(EMC_CFG_DYN_SELF_REF | EMC_CFG_DRAM_ACPD | EMC_CFG_DRAM_CLKSTOP_PD | EMC_CFG_DRAM_CLKSTOP_PD); + + /* + * 1. Power optimizations should be off. + */ + emc_write(emc_cfg, EMC_CFG); + + /* Does emc_timing_update() for above changes. */ + dll_disable(channel_mode); + + if (dram_dev_num == TWO_RANK) { + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_DRAM_IN_POWERDOWN_MASK, false, REG_EMC); + if (channel_mode) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_DRAM_IN_POWERDOWN_MASK, false, REG_EMC1); + } else { + wait_for_update(EMC_EMC_STATUS, 0x10, false, REG_EMC); + if (channel_mode) + wait_for_update(EMC_EMC_STATUS, 0x10, false, REG_EMC1); + } + + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK, false, REG_EMC); + if (channel_mode) + wait_for_update(EMC_EMC_STATUS, EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK, false, REG_EMC1); + + wait_for_update(EMC_EMC_STATUS, 0x01, false, REG_EMC); + if (channel_mode) + wait_for_update(EMC_EMC_STATUS, 0x01, false, REG_EMC1); + + uint32_t emc_cfg_update = emc_read(EMC_CFG_UPDATE); + emc_write((emc_cfg_update & ~EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_MASK) | (2 << EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_SHIFT), EMC_CFG_UPDATE); + + /* + * 2. osc kick off - this assumes training and dvfs have set + * correct MR23. + */ + start_periodic_compensation(); + + /* + * 3. Let dram capture its clock tree delays. + */ + udelay((actual_osc_clocks(current_timing->run_clocks) * 1000) / current_timing->rate + 1); + + /* + * 4. Check delta wrt previous values (save value if margin + * exceeds what is set in table). + */ + uint32_t del = periodic_compensation_handler(current_timing, current_timing, dram_dev_num, channel_mode, PERIODIC_TRAINING_SEQUENCE); + + /* + * 5. Apply compensation w.r.t. trained values (if clock tree + * has drifted more than the set margin). + */ + if (current_timing->tree_margin < ((del * 128 * (current_timing->rate / 1000)) / 1000000)) { + for (int i = 0; i < reg_count; i++) { + uint32_t tmp = apply_periodic_compensation_trimmer(current_timing, reg_list[i]); + emc_write(tmp, reg_list[i]); + } + } + + emc_write(emc_cfg_o, EMC_CFG); + + /* + * 6. Timing update actually applies the new trimmers. + */ + emc_timing_update(channel_mode); + + /* 6.1. Restore the UPDATE_DLL_IN_UPDATE field. */ + emc_write(emc_cfg_update, EMC_CFG_UPDATE); + + /* 6.2. Restore the DLL. */ + dll_enable(channel_mode); + } +} + +static void train_set_clock(tegra_emc_timing_t* current_timing, tegra_emc_timing_t* next_timing, bool update_clk, uint32_t next_clk_src) { + /* Check for dual channel LPDDR4 */ + bool dual_channel_lpddr4_case = ((emc_read(EMC_FBIO_CFG7) & EMC_FBIO_CFG7_CH0_ENABLE) & (emc_read(EMC_FBIO_CFG7) & EMC_FBIO_CFG7_CH1_ENABLE)); + + /* Get the DRAM type */ + uint32_t dram_type = (next_timing->burst_regs[EMC_FBIO_CFG5_INDEX] & 0x03); + + if (g_write_training_pattern) { + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Writing training patterns...\n"); + + /* Write the training data into pattern RAM */ + for (int i = 0; i < 0x100; i++) { + uint32_t training_pattern_val = g_ram_pattern_dq[i + (next_timing->training_pattern * 0x100)]; + + /* Write the DQ data into pattern RAM */ + emc_write(training_pattern_val, EMC_TRAINING_PATRAM_DQ); + + training_pattern_val = g_ram_pattern_dmi[i + (next_timing->training_pattern * 0x100)]; + + /* Write the DMI data into pattern RAM */ + emc_write(training_pattern_val & 0x0F, EMC_TRAINING_PATRAM_DMI); + + /* Enable writing into pattern RAM and select the offset */ + emc_write(0x80000000 + i, EMC_TRAINING_PATRAM_CTRL); + } + } + + /* Only write the training pattern once */ + g_write_training_pattern = false; + + if (next_timing->needs_training && !next_timing->trained) { + uint32_t training_flags = next_timing->needs_training; + + /* Read from MC_EMEM_ADR_CFG */ + uint32_t dram_dev_num = mc_read(MC_EMEM_ADR_CFG); + + int training_params_idx = 0; + int training_params[8] = {}; + + if (training_flags & 0x03) { + training_params_idx = 1; + training_params[0] = (training_flags & 0x203); + + if (dram_dev_num & 0x01) { + training_params_idx = 2; + training_params[1] = (training_flags & 0x303); + } + } + + if ((dram_dev_num & 0x01) && (training_flags & 0x0C)) { + training_params[training_params_idx] = (training_flags & 0x20C); + training_params[training_params_idx + 1] = (training_flags & 0x204); + training_params_idx += 2; + } else if (training_flags & 0x0C) { + training_params[training_params_idx++] = (training_flags & 0x20C); + } + + if (training_flags & 0xF0) + training_params[training_params_idx++] = (training_flags & 0x2F0); + + for (int i = 0; i < training_params_idx; i++) { + /* Adjust the clock */ + set_clock(current_timing, next_timing, training_params[i], next_clk_src); + + /* Change CFG_SWAP to ASSEMBLY_ONLY */ + uint32_t emc_dbg = emc_read(EMC_DBG); + emc_dbg = ((emc_dbg & 0xF3FFFFFF) | 0x8000000); + emc_write(emc_dbg, EMC_DBG); + + /* Change UPDATE_AUTO_CAL_IN_UPDATE to ALWAYS */ + uint32_t emc_cfg_update = emc_read(EMC_CFG_UPDATE); + emc_cfg_update = ((emc_cfg_update & 0xFFFFFFF9) | 0x04); + emc_write(emc_cfg_update, EMC_CFG_UPDATE); + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + + /* Change UPDATE_AUTO_CAL_IN_UPDATE to NEVER */ + emc_cfg_update = emc_read(EMC_CFG_UPDATE); + emc_cfg_update &= 0xFFFFFFF9; + emc_write(emc_cfg_update, EMC_CFG_UPDATE); + + /* Change CFG_SWAP to ACTIVE_ONLY */ + emc_dbg = emc_read(EMC_DBG); + emc_dbg &= 0xF3FFFFFF; + emc_write(emc_dbg, EMC_DBG); + + /* Disable DLL and change CFG_DLL_MODE to RUN_PERIODIC */ + uint32_t emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + emc_cfg_dig_dll = ((emc_cfg_dig_dll & 0xFFFFFF3E) | 0x80); + emc_write(emc_cfg_dig_dll, EMC_CFG_DIG_DLL); + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + + /* Disable or enable DLL */ + emc_cfg_dig_dll = emc_read(EMC_CFG_DIG_DLL); + if (next_timing->burst_regs[EMC_CFG_DIG_DLL_INDEX] == 0x01) + emc_cfg_dig_dll |= 0x01; + else + emc_cfg_dig_dll &= 0xFFFFFFFE; + + /* Change CFG_DLL_MODE to RUN_PERIODIC */ + emc_cfg_dig_dll = ((emc_cfg_dig_dll & 0xFFFFFF3F) | 0x80); + emc_write(emc_cfg_dig_dll, EMC_CFG_DIG_DLL); + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + + /* Wait for DLL_LOCK to be set */ + uint32_t emc_dig_dll_status = 0; + do { + emc_dig_dll_status = emc_read(EMC_DIG_DLL_STATUS); + } while (!(emc_dig_dll_status & EMC_DIG_DLL_STATUS_DLL_LOCK)); + + /* Check if DRAM is LPDDR4 */ + if (dram_type == DRAM_TYPE_LPDDR4) { + emc_write(current_timing->burst_regs[EMC_RP_INDEX], EMC_RP); + emc_write(current_timing->burst_regs[EMC_R2P_INDEX], EMC_R2P); + emc_write(current_timing->burst_regs[EMC_W2P_INDEX], EMC_W2P); + emc_write(current_timing->burst_regs[EMC_TRPAB_INDEX], EMC_TRPAB); + } + + /* Request a timing update event */ + emc_timing_update(dual_channel_lpddr4_case); + } + + /* We've finished training */ + next_timing->trained = 1; + + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Memory is trained!\n"); + } + + /* Change the clock if requested */ + if (update_clk) + set_clock(current_timing, next_timing, 0, next_clk_src); +} + +static int train_one(int z_val, uint32_t next_rate, uint32_t current_rate, tegra_emc_timing_t* timing_tables, int timing_tables_count, TrainMode mode) { + int current_timing_table_idx = -1; + int next_timing_table_idx = -1; + tegra_emc_timing_t* current_timing_table; + tegra_emc_timing_t* next_timing_table; + uint32_t next_clk_src = 0; + + /* Too many table entries */ + if (timing_tables_count > 0x384) + return 4; + + /* Locate the right tables for the transition */ + for (int i = 0; i < timing_tables_count; i++) { + uint32_t rate = timing_tables[i].rate; + + if (rate == current_rate) + current_timing_table_idx = i; + else if (rate == next_rate) + next_timing_table_idx = i; + } + + /* Failed to find the tables. */ + if ((current_timing_table_idx < 0) || (next_timing_table_idx < 0)) + return 4; + + current_timing_table = (tegra_emc_timing_t*)&timing_tables[current_timing_table_idx]; + next_timing_table = (tegra_emc_timing_t*)&timing_tables[next_timing_table_idx]; + + uint32_t clk_src_emc_from = current_timing_table->clk_src_emc; + uint32_t clk_src_emc_to = next_timing_table->clk_src_emc; + uint32_t rate_from = current_timing_table->rate; + uint32_t rate_to = next_timing_table->rate; + + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Changing rate from %d to %d!\n", rate_from, rate_to); + + bool diff_freq = test_clk_ratio(rate_to, clk_src_emc_to, rate_from, clk_src_emc_from); + + if (diff_freq) { + uint32_t emc_2x_clk_src = (clk_src_emc_from >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT); + + if (emc_2x_clk_src & 0x03) { + if ((emc_2x_clk_src - TEGRA_EMC_SRC_PLLMB_UD) <= 1) { + g_is_pllmb = false; + } + } else { + g_is_pllmb = !g_is_pllmb; + } + + /* Configure the PLL values */ + next_clk_src = set_pll(rate_to, 0x9600, clk_src_emc_to, g_is_pllmb); + } else { + uint32_t emc_2x_clk_src = (clk_src_emc_to >> EMC_CLK_EMC_2X_CLK_SRC_SHIFT); + + if ((emc_2x_clk_src != TEGRA_EMC_SRC_PLLMB) && emc_2x_clk_src) { + if (((emc_2x_clk_src - TEGRA_EMC_SRC_PLLM_UD) <= TEGRA_EMC_SRC_PLLC) && g_is_pllmb) { + next_clk_src = ((clk_src_emc_to & 0x1FFFFFFF) | (TEGRA_EMC_SRC_PLLMB_UD << EMC_CLK_EMC_2X_CLK_SRC_SHIFT)); + } + } else if (g_is_pllmb) { + next_clk_src = ((clk_src_emc_to & 0x1FFFFFFF) | (TEGRA_EMC_SRC_PLLMB << EMC_CLK_EMC_2X_CLK_SRC_SHIFT)); + } else { + next_clk_src = clk_src_emc_to; + } + } + + if (mode == OP_SWITCH) { + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Train mode is OP_SWITCH!\n"); + set_clock(current_timing_table, next_timing_table, false, next_clk_src); + g_active_timing_table_idx = next_timing_table_idx; + if (next_timing_table->periodic_training) { + do_periodic_emc_compensation(next_timing_table); + } + } else if (mode == OP_TRAIN) { + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Train mode is OP_TRAIN!\n"); + train_set_clock(current_timing_table, next_timing_table, false, next_clk_src); + g_active_timing_table_idx = next_timing_table_idx; + if (diff_freq) { + g_is_pllmb = !g_is_pllmb; + } + } else if (mode == OP_TRAIN_SWITCH) { + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Train mode is OP_TRAIN_SWITCH!\n"); + train_set_clock(current_timing_table, next_timing_table, true, next_clk_src); + g_active_timing_table_idx = next_timing_table_idx; + if (next_timing_table->periodic_training) { + do_periodic_emc_compensation(next_timing_table); + } + } else + return 4; + + return 0; +} + +void train_dram() { + volatile tegra_car_t *car = car_get_regs(); + + tegra_emc_timing_t *timing_tables; + uint32_t dram_id = fuse_get_dram_id(); + + /* Find the right timing table set. */ + if (dram_id == 0x01) + timing_tables = (tegra_emc_timing_t *)nx_abca2_dram_1; + else if ((dram_id == 0x00) || (dram_id == 0x02) || (dram_id == 0x03) || (dram_id == 0x04)) + timing_tables = (tegra_emc_timing_t *)nx_abca2_dram_0234; + else + fatal_error("[MTC]: Missing tables for DRAM id %d!\n", dram_id); + + /* Locate the right timing table. */ + int boot_index = 0; + for (boot_index = 0; boot_index < MTC_TABLES_MAX_ENTRIES; boot_index++) { + print(SCREEN_LOG_LEVEL_DEBUG, "%d (%d kHz): %s\n", boot_index, timing_tables[boot_index].rate, timing_tables[boot_index].dvfs_ver); + if (car->clk_source_emc == timing_tables[boot_index].clk_src_emc) + break; + } + + if (boot_index >= MTC_TABLES_MAX_ENTRIES) { + fatal_error("[MTC]: Failed to find timing table!\n"); + } + + /* Switch to 800Mhz. */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Switching from %dMhz to 800Mhz\n", timing_tables[boot_index].rate / 1000); + train_one(0, 800000, timing_tables[boot_index].rate, timing_tables, MTC_TABLES_MAX_ENTRIES, OP_TRAIN_SWITCH); + + /* Switch to 1600Mhz. */ + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Switching from %dMhz to 1600Mhz\n", timing_tables[g_active_timing_table_idx].rate / 1000); + train_one(0, 1600000, timing_tables[g_active_timing_table_idx].rate, timing_tables, MTC_TABLES_MAX_ENTRIES, OP_TRAIN_SWITCH); + + /* Wait a while. */ + mdelay(100); + + /* Do periodic compensation. */ + do_periodic_emc_compensation((tegra_emc_timing_t*)&timing_tables[g_active_timing_table_idx]); + + print(SCREEN_LOG_LEVEL_DEBUG, "[MTC]: Done!\n"); +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/mtc.h b/fusee/fusee-secondary/src/mtc.h new file mode 100644 index 000000000..45a043dc9 --- /dev/null +++ b/fusee/fusee-secondary/src/mtc.h @@ -0,0 +1,759 @@ +/* + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 CTCaer <ctcaer@gmail.com> + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_MTC_H_ +#define FUSEE_MTC_H_ + +#include <stdint.h> +#include <stdbool.h> + +#include "emc.h" +#include "mc.h" + +#define MTC_TABLES_MAX_ENTRIES 10 +#define MAX_PLL_CFGS 14 + +#define DVFS_FGCG_HIGH_SPEED_THRESHOLD 1000 +#define IOBRICK_DCC_THRESHOLD 2400 +#define DVFS_FGCG_MID_SPEED_THRESHOLD 600 + +#define TEGRA21_MAX_TABLE_ID_LEN 50 +#define TEGRA_EMC_ISO_USE_FREQ_MAX_NUM 12 +#define PLL_C_DIRECT_FLOOR 333500000 +#define EMC_STATUS_UPDATE_TIMEOUT 1000 +#define TEGRA_EMC_DEFAULT_CLK_LATENCY_US 2000 + +#define TEGRA_EMC_MODE_REG_17 0x00110000 +#define TEGRA_EMC_MRW_DEV_SHIFT 30 +#define TEGRA_EMC_MRW_DEV1 2 +#define TEGRA_EMC_MRW_DEV2 1 + +#define EMC_CLK_EMC_2X_CLK_SRC_SHIFT 29 +#define EMC_CLK_EMC_2X_CLK_SRC_MASK \ + (0x7 << EMC_CLK_EMC_2X_CLK_SRC_SHIFT) +#define EMC_CLK_EMC_2X_CLK_DIVISOR_SHIFT 0 +#define EMC_CLK_EMC_2X_CLK_DIVISOR_MASK \ + (0xff << EMC_CLK_EMC_2X_CLK_DIVISOR_SHIFT) + +enum { + REG_MC, + REG_EMC, + REG_EMC0, + REG_EMC1, +}; + +#define BURST_REGS_PER_CH_LIST \ +{ \ + DEFINE_REG(REG_EMC0, EMC_MRW10), \ + DEFINE_REG(REG_EMC1, EMC_MRW10), \ + DEFINE_REG(REG_EMC0, EMC_MRW11), \ + DEFINE_REG(REG_EMC1, EMC_MRW11), \ + DEFINE_REG(REG_EMC0, EMC_MRW12), \ + DEFINE_REG(REG_EMC1, EMC_MRW12), \ + DEFINE_REG(REG_EMC0, EMC_MRW13), \ + DEFINE_REG(REG_EMC1, EMC_MRW13), \ +} + +#define BURST_REGS_LIST \ +{ \ + DEFINE_REG(REG_EMC, EMC_RC), \ + DEFINE_REG(REG_EMC, EMC_RFC), \ + DEFINE_REG(REG_EMC, EMC_RFCPB), \ + DEFINE_REG(REG_EMC, EMC_REFCTRL2), \ + DEFINE_REG(REG_EMC, EMC_RFC_SLR), \ + DEFINE_REG(REG_EMC, EMC_RAS), \ + DEFINE_REG(REG_EMC, EMC_RP), \ + DEFINE_REG(REG_EMC, EMC_R2W), \ + DEFINE_REG(REG_EMC, EMC_W2R), \ + DEFINE_REG(REG_EMC, EMC_R2P), \ + DEFINE_REG(REG_EMC, EMC_W2P), \ + DEFINE_REG(REG_EMC, EMC_R2R), \ + DEFINE_REG(REG_EMC, EMC_TPPD), \ + DEFINE_REG(REG_EMC, EMC_CCDMW), \ + DEFINE_REG(REG_EMC, EMC_RD_RCD), \ + DEFINE_REG(REG_EMC, EMC_WR_RCD), \ + DEFINE_REG(REG_EMC, EMC_RRD), \ + DEFINE_REG(REG_EMC, EMC_REXT), \ + DEFINE_REG(REG_EMC, EMC_WEXT), \ + DEFINE_REG(REG_EMC, EMC_WDV_CHK), \ + DEFINE_REG(REG_EMC, EMC_WDV), \ + DEFINE_REG(REG_EMC, EMC_WSV), \ + DEFINE_REG(REG_EMC, EMC_WEV), \ + DEFINE_REG(REG_EMC, EMC_WDV_MASK), \ + DEFINE_REG(REG_EMC, EMC_WS_DURATION), \ + DEFINE_REG(REG_EMC, EMC_WE_DURATION), \ + DEFINE_REG(REG_EMC, EMC_QUSE), \ + DEFINE_REG(REG_EMC, EMC_QUSE_WIDTH), \ + DEFINE_REG(REG_EMC, EMC_IBDLY), \ + DEFINE_REG(REG_EMC, EMC_OBDLY), \ + DEFINE_REG(REG_EMC, EMC_EINPUT), \ + DEFINE_REG(REG_EMC, EMC_MRW6), \ + DEFINE_REG(REG_EMC, EMC_EINPUT_DURATION), \ + DEFINE_REG(REG_EMC, EMC_PUTERM_EXTRA), \ + DEFINE_REG(REG_EMC, EMC_PUTERM_WIDTH), \ + DEFINE_REG(REG_EMC, EMC_QRST), \ + DEFINE_REG(REG_EMC, EMC_QSAFE), \ + DEFINE_REG(REG_EMC, EMC_RDV), \ + DEFINE_REG(REG_EMC, EMC_RDV_MASK), \ + DEFINE_REG(REG_EMC, EMC_RDV_EARLY), \ + DEFINE_REG(REG_EMC, EMC_RDV_EARLY_MASK), \ + DEFINE_REG(REG_EMC, EMC_REFRESH), \ + DEFINE_REG(REG_EMC, EMC_BURST_REFRESH_NUM), \ + DEFINE_REG(REG_EMC, EMC_PRE_REFRESH_REQ_CNT), \ + DEFINE_REG(REG_EMC, EMC_PDEX2WR), \ + DEFINE_REG(REG_EMC, EMC_PDEX2RD), \ + DEFINE_REG(REG_EMC, EMC_PCHG2PDEN), \ + DEFINE_REG(REG_EMC, EMC_ACT2PDEN), \ + DEFINE_REG(REG_EMC, EMC_AR2PDEN), \ + DEFINE_REG(REG_EMC, EMC_RW2PDEN), \ + DEFINE_REG(REG_EMC, EMC_CKE2PDEN), \ + DEFINE_REG(REG_EMC, EMC_PDEX2CKE), \ + DEFINE_REG(REG_EMC, EMC_PDEX2MRR), \ + DEFINE_REG(REG_EMC, EMC_TXSR), \ + DEFINE_REG(REG_EMC, EMC_TXSRDLL), \ + DEFINE_REG(REG_EMC, EMC_TCKE), \ + DEFINE_REG(REG_EMC, EMC_TCKESR), \ + DEFINE_REG(REG_EMC, EMC_TPD), \ + DEFINE_REG(REG_EMC, EMC_TFAW), \ + DEFINE_REG(REG_EMC, EMC_TRPAB), \ + DEFINE_REG(REG_EMC, EMC_TCLKSTABLE), \ + DEFINE_REG(REG_EMC, EMC_TCLKSTOP), \ + DEFINE_REG(REG_EMC, EMC_MRW7), \ + DEFINE_REG(REG_EMC, EMC_TREFBW), \ + DEFINE_REG(REG_EMC, EMC_ODT_WRITE), \ + DEFINE_REG(REG_EMC, EMC_FBIO_CFG5), \ + DEFINE_REG(REG_EMC, EMC_FBIO_CFG7), \ + DEFINE_REG(REG_EMC, EMC_CFG_DIG_DLL), \ + DEFINE_REG(REG_EMC, EMC_CFG_DIG_DLL_PERIOD), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_RXRT), \ + DEFINE_REG(REG_EMC, EMC_CFG_PIPE_1), \ + DEFINE_REG(REG_EMC, EMC_CFG_PIPE_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_5), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_5), \ + DEFINE_REG(REG_EMC, EMC_MRW8), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_LONG_CMD_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_SHORT_CMD_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_SHORT_CMD_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_SHORT_CMD_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3), \ + DEFINE_REG(REG_EMC, EMC_TXDSRVTTGEN), \ + DEFINE_REG(REG_EMC, EMC_FDPD_CTRL_DQ), \ + DEFINE_REG(REG_EMC, EMC_FDPD_CTRL_CMD), \ + DEFINE_REG(REG_EMC, EMC_FBIO_SPARE), \ + DEFINE_REG(REG_EMC, EMC_ZCAL_INTERVAL), \ + DEFINE_REG(REG_EMC, EMC_ZCAL_WAIT_CNT), \ + DEFINE_REG(REG_EMC, EMC_MRS_WAIT_CNT), \ + DEFINE_REG(REG_EMC, EMC_MRS_WAIT_CNT2), \ + DEFINE_REG(REG_EMC, EMC_AUTO_CAL_CHANNEL), \ + DEFINE_REG(REG_EMC, EMC_DLL_CFG_0), \ + DEFINE_REG(REG_EMC, EMC_DLL_CFG_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_AUTOCAL_CFG_COMMON), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_ZCTRL), \ + DEFINE_REG(REG_EMC, EMC_CFG), \ + DEFINE_REG(REG_EMC, EMC_CFG_PIPE), \ + DEFINE_REG(REG_EMC, EMC_DYN_SELF_REF_CONTROL), \ + DEFINE_REG(REG_EMC, EMC_QPOP), \ + DEFINE_REG(REG_EMC, EMC_DQS_BRLSHFT_0), \ + DEFINE_REG(REG_EMC, EMC_DQS_BRLSHFT_1), \ + DEFINE_REG(REG_EMC, EMC_CMD_BRLSHFT_2), \ + DEFINE_REG(REG_EMC, EMC_CMD_BRLSHFT_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_PAD_CFG_CTRL), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DATA_PAD_RX_CTRL), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_PAD_RX_CTRL), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DATA_RX_TERM_MODE), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_RX_TERM_MODE), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_PAD_TX_CTRL), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DATA_PAD_TX_CTRL), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_COMMON_PAD_TX_CTRL), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_VTTGEN_CTRL_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_VTTGEN_CTRL_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_VTTGEN_CTRL_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_BRICK_CTRL_RFU1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_BRICK_CTRL_FDPD), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_BRICK_CTRL_RFU2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DATA_BRICK_CTRL_FDPD), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_BG_BIAS_CTRL_0), \ + DEFINE_REG(REG_EMC, EMC_CFG_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_PWRD_5), \ + DEFINE_REG(REG_EMC, EMC_CONFIG_SAMPLE_DELAY), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_TX_SEL_CLK_SRC_5), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_BYPASS), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_PWRD_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_PWRD_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_DDLL_PWRD_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_CTRL_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_CTRL_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_CMD_CTRL_2), \ + DEFINE_REG(REG_EMC, EMC_TR_TIMING_0), \ + DEFINE_REG(REG_EMC, EMC_TR_DVFS), \ + DEFINE_REG(REG_EMC, EMC_TR_CTRL_1), \ + DEFINE_REG(REG_EMC, EMC_TR_RDV), \ + DEFINE_REG(REG_EMC, EMC_TR_QPOP), \ + DEFINE_REG(REG_EMC, EMC_TR_RDV_MASK), \ + DEFINE_REG(REG_EMC, EMC_MRW14), \ + DEFINE_REG(REG_EMC, EMC_TR_QSAFE), \ + DEFINE_REG(REG_EMC, EMC_TR_QRST), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_SETTLE), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_VREF_SETTLE), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_CA_FINE_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_CA_CTRL_MISC), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_CA_CTRL_MISC1), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_CA_VREF_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_QUSE_CORS_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_QUSE_FINE_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_QUSE_CTRL_MISC), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_QUSE_VREF_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_READ_FINE_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_READ_CTRL_MISC), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_READ_VREF_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_WRITE_FINE_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_WRITE_CTRL_MISC), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_WRITE_VREF_CTRL), \ + DEFINE_REG(REG_EMC, EMC_TRAINING_MPC), \ + DEFINE_REG(REG_EMC, EMC_MRW15), \ +} + +#define TRIM_REGS_PER_CH_LIST \ +{ \ + DEFINE_REG(REG_EMC0, EMC_CMD_BRLSHFT_0), \ + DEFINE_REG(REG_EMC1, EMC_CMD_BRLSHFT_1), \ + DEFINE_REG(REG_EMC0, EMC_DATA_BRLSHFT_0), \ + DEFINE_REG(REG_EMC1, EMC_DATA_BRLSHFT_0), \ + DEFINE_REG(REG_EMC0, EMC_DATA_BRLSHFT_1), \ + DEFINE_REG(REG_EMC1, EMC_DATA_BRLSHFT_1), \ + DEFINE_REG(REG_EMC0, EMC_QUSE_BRLSHFT_0), \ + DEFINE_REG(REG_EMC1, EMC_QUSE_BRLSHFT_1), \ + DEFINE_REG(REG_EMC0, EMC_QUSE_BRLSHFT_2), \ + DEFINE_REG(REG_EMC1, EMC_QUSE_BRLSHFT_3), \ +} + +#define TRIM_REGS_LIST \ +{ \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_VREF_DQS_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_VREF_DQS_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_VREF_DQ_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_IB_VREF_DQ_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK0_3), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_0), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_1), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_2), \ + DEFINE_REG(REG_EMC, EMC_PMACRO_QUSE_DDLL_RANK1_3), \ +} + +#define VREF_REGS_PER_CH_LIST \ +{ \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_OPT_DQS_IB_VREF_RANK0), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_OPT_DQS_IB_VREF_RANK0), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_OPT_DQS_IB_VREF_RANK1), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_OPT_DQS_IB_VREF_RANK1), \ +} + +#define TRAINING_MOD_REGS_PER_CH_LIST \ +{ \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_IB_BYTE0), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_IB_BYTE0), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_IB_BYTE1), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_IB_BYTE1), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_IB_BYTE2), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_IB_BYTE2), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_IB_BYTE3), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_IB_BYTE3), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_IB_MISC), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_IB_MISC), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_OB_BYTE0), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_OB_BYTE0), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_OB_BYTE1), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_OB_BYTE1), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_OB_BYTE2), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_OB_BYTE2), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_OB_BYTE3), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_OB_BYTE3), \ + DEFINE_REG(REG_EMC0, EMC_TRAINING_RW_OFFSET_OB_MISC), \ + DEFINE_REG(REG_EMC1, EMC_TRAINING_RW_OFFSET_OB_MISC), \ +} + +#define BURST_MC_REGS_LIST \ +{ \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_CFG), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_OUTSTANDING_REQ), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_REFPB_HP_CTRL), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_REFPB_BANK_CTRL), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RCD), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RP), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RC), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RAS), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_FAW), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RRD), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RAP2PRE), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_WAP2PRE), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_R2R), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_W2W), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_R2W), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_CCDMW), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_W2R), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_TIMING_RFCPB), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DA_TURNS), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DA_COVERS), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_MISC0), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_MISC1), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_MISC2), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_RING1_THROTTLE), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_CTRL), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6), \ + DEFINE_REG(REG_MC, MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7), \ +} + +#define BURST_UP_DOWN_REGS_LIST \ +{ \ + DEFINE_REG(REG_MC, MC_MLL_MPCORER_PTSA_RATE), \ + DEFINE_REG(REG_MC, MC_FTOP_PTSA_RATE), \ + DEFINE_REG(REG_MC, MC_PTSA_GRANT_DECREMENT), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_XUSB_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_XUSB_1), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_TSEC_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_SDMMCA_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_SDMMCAA_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_SDMMC_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_SDMMCAB_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_PPCS_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_PPCS_1), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_MPCORE_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_HC_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_HC_1), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_AVPC_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_GPU_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_GPU2_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_NVENC_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_NVDEC_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_VIC_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_VI2_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_ISP2_0), \ + DEFINE_REG(REG_MC, MC_LATENCY_ALLOWANCE_ISP2_1), \ +} + +#define DEFINE_REG(type, reg) reg##_INDEX +enum BURST_REGS_LIST; +enum TRIM_REGS_LIST; +enum BURST_MC_REGS_LIST; +enum BURST_UP_DOWN_REGS_LIST; +#undef DEFINE_REG + +#define DEFINE_REG(type, reg) type##_##reg##_INDEX +enum BURST_REGS_PER_CH_LIST; +enum TRIM_REGS_PER_CH_LIST; +enum VREF_REGS_PER_CH_LIST; +enum TRAINING_MOD_REGS_PER_CH_LIST; +#undef DEFINE_REG + +typedef struct { + uint32_t rev; + char dvfs_ver[60]; + uint32_t rate; + uint32_t min_volt; + uint32_t gpu_min_volt; + char clock_src[32]; + uint32_t clk_src_emc; + uint32_t needs_training; + uint32_t training_pattern; + uint32_t trained; + + uint32_t periodic_training; + uint32_t trained_dram_clktree_c0d0u0; + uint32_t trained_dram_clktree_c0d0u1; + uint32_t trained_dram_clktree_c0d1u0; + uint32_t trained_dram_clktree_c0d1u1; + uint32_t trained_dram_clktree_c1d0u0; + uint32_t trained_dram_clktree_c1d0u1; + uint32_t trained_dram_clktree_c1d1u0; + uint32_t trained_dram_clktree_c1d1u1; + uint32_t current_dram_clktree_c0d0u0; + uint32_t current_dram_clktree_c0d0u1; + uint32_t current_dram_clktree_c0d1u0; + uint32_t current_dram_clktree_c0d1u1; + uint32_t current_dram_clktree_c1d0u0; + uint32_t current_dram_clktree_c1d0u1; + uint32_t current_dram_clktree_c1d1u0; + uint32_t current_dram_clktree_c1d1u1; + uint32_t run_clocks; + uint32_t tree_margin; + + uint32_t num_burst; + uint32_t num_burst_per_ch; + uint32_t num_trim; + uint32_t num_trim_per_ch; + uint32_t num_mc_regs; + uint32_t num_up_down; + uint32_t vref_num; + uint32_t training_mod_num; + uint32_t dram_timing_num; + + uint32_t ptfv_list[12]; + + uint32_t burst_regs[221]; + uint32_t burst_reg_per_ch[8]; + uint32_t shadow_regs_ca_train[221]; + uint32_t shadow_regs_quse_train[221]; + uint32_t shadow_regs_rdwr_train[221]; + + uint32_t trim_regs[138]; + uint32_t trim_perch_regs[10]; + + uint32_t vref_perch_regs[4]; + + uint32_t dram_timings[5]; + uint32_t training_mod_regs[20]; + uint32_t save_restore_mod_regs[12]; + uint32_t burst_mc_regs[33]; + uint32_t la_scale_regs[24]; + + uint32_t min_mrs_wait; + uint32_t emc_mrw; + uint32_t emc_mrw2; + uint32_t emc_mrw3; + uint32_t emc_mrw4; + uint32_t emc_mrw9; + uint32_t emc_mrs; + uint32_t emc_emrs; + uint32_t emc_emrs2; + uint32_t emc_auto_cal_config; + uint32_t emc_auto_cal_config2; + uint32_t emc_auto_cal_config3; + uint32_t emc_auto_cal_config4; + uint32_t emc_auto_cal_config5; + uint32_t emc_auto_cal_config6; + uint32_t emc_auto_cal_config7; + uint32_t emc_auto_cal_config8; + uint32_t emc_cfg_2; + uint32_t emc_sel_dpd_ctrl; + uint32_t emc_fdpd_ctrl_cmd_no_ramp; + uint32_t dll_clk_src; + uint32_t clk_out_enb_x_0_clk_enb_emc_dll; + uint32_t latency; +} tegra_emc_timing_t; + +typedef struct { + uint32_t osc_freq; + uint32_t out_freq; + uint32_t feedback_div; + uint32_t input_div; + uint32_t post_div; +} pll_cfg_t; + +typedef enum { + OP_SWITCH = 0, + OP_TRAIN = 1, + OP_TRAIN_SWITCH = 2 +} TrainMode; + +typedef enum { + TEGRA_EMC_SRC_PLLM, + TEGRA_EMC_SRC_PLLC, + TEGRA_EMC_SRC_PLLP, + TEGRA_EMC_SRC_CLKM, + TEGRA_EMC_SRC_PLLM_UD, + TEGRA_EMC_SRC_PLLMB_UD, + TEGRA_EMC_SRC_PLLMB, + TEGRA_EMC_SRC_PLLP_UD, + TEGRA_EMC_SRC_COUNT, +} EmcSource; + +enum { + DRAM_TYPE_DDR3 = 0, + DRAM_TYPE_LPDDR4 = 1, + DRAM_TYPE_LPDDR2 = 2, + DRAM_TYPE_DDR2 = 3, +}; + +enum { + DLL_CHANGE_NONE = 0, + DLL_CHANGE_ON, + DLL_CHANGE_OFF, +}; + +enum { + DLL_OFF, + DLL_ON +}; + +enum { + AUTO_PD = 0, + MAN_SR = 2 +}; + +enum { + ASSEMBLY = 0, + ACTIVE +}; + +enum { + T_RP = 0, + T_FC_LPDDR4, + T_RFC, + T_PDEX, + RL +}; + +enum { + ONE_RANK = 1, + TWO_RANK = 2 +}; + +enum { + SINGLE_CHANNEL = 0, + DUAL_CHANNEL +}; + +enum { + DRAM_DEV_SEL_ALL = 0, + DRAM_DEV_SEL_0 = (2 << 30), + DRAM_DEV_SEL_1 = (1 << 30), +}; + +enum { + EMC_CFG5_QUSE_MODE_NORMAL = 0, + EMC_CFG5_QUSE_MODE_ALWAYS_ON, + EMC_CFG5_QUSE_MODE_INTERNAL_LPBK, + EMC_CFG5_QUSE_MODE_PULSE_INTERN, + EMC_CFG5_QUSE_MODE_PULSE_EXTERN, + EMC_CFG5_QUSE_MODE_DIRECT_QUSE, +}; + +enum { + DVFS_SEQUENCE = 1, + WRITE_TRAINING_SEQUENCE = 2, + PERIODIC_TRAINING_SEQUENCE = 3, + DVFS_PT1 = 10, + DVFS_UPDATE = 11, + TRAINING_PT1 = 12, + TRAINING_UPDATE = 13, + PERIODIC_TRAINING_UPDATE = 14 +}; + +enum { + TEGRA_DRAM_OVER_TEMP_NONE = 0, + TEGRA_DRAM_OVER_TEMP_REFRESH_X2, + TEGRA_DRAM_OVER_TEMP_REFRESH_X4, + TEGRA_DRAM_OVER_TEMP_THROTTLE, + TEGRA_DRAM_OVER_TEMP_MAX, +}; + +/* Train all possible DRAM sequences. */ +void train_dram(); + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/mtc_tables.h b/fusee/fusee-secondary/src/mtc_tables.h new file mode 100644 index 000000000..eb20fdaef --- /dev/null +++ b/fusee/fusee-secondary/src/mtc_tables.h @@ -0,0 +1,6189 @@ +/* + * Copyright (c) 2018 CTCaer <ctcaer@gmail.com> + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_MTC_TABLES_H_ +#define FUSEE_MTC_TABLES_H_ + +unsigned char nx_abca2_dram_0234[0xC080] = +{ + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x34, 0x30, 0x38, 0x30, 0x30, 0x5F, 0x4E, 0x6F, 0x43, + 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, 0x37, + 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x9F, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x6F, 0x75, 0x74, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x29, 0x00, 0x09, 0x00, + 0x15, 0x00, 0x29, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0xFF, 0x0F, 0xFF, 0x0F, 0x3A, 0x02, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x14, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0xA0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x29, 0x00, 0x09, 0x00, 0x15, 0x00, 0x29, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x02, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x3A, 0x02, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x14, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x29, 0x00, 0x09, 0x00, 0x15, 0x00, 0x29, 0x00, 0x0A, 0x00, 0x0B, 0x00, + 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x3A, 0x02, 0x00, 0x80, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x37, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x14, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x30, + 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x29, 0x00, 0x09, 0x00, 0x15, 0x00, 0x29, 0x00, + 0x0A, 0x00, 0x0B, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, + 0x3A, 0x02, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x14, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x40, 0x13, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x03, 0x00, + 0x03, 0x03, 0xC3, 0x72, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x76, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x3D, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x3D, 0x00, 0xFF, 0x00, 0x49, 0x00, 0xFF, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x12, 0x80, 0x18, 0x40, 0x01, 0x00, 0x00, 0x00, 0x72, 0x51, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x36, 0x38, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, 0x43, + 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, 0x37, + 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xA0, 0x09, 0x01, 0x00, 0x20, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x6F, 0x75, 0x74, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x44, 0x00, 0x09, 0x00, + 0x15, 0x00, 0x44, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0xFF, 0x0F, 0xFF, 0x0F, 0x09, 0x03, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x11, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x22, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x0A, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x44, 0x00, 0x09, 0x00, 0x15, 0x00, 0x44, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x02, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x09, 0x03, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x11, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x22, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x44, 0x00, 0x09, 0x00, 0x15, 0x00, 0x44, 0x00, 0x0A, 0x00, 0x11, 0x00, + 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x09, 0x03, 0x00, 0x80, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x37, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x11, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x22, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x30, + 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x44, 0x00, 0x09, 0x00, 0x15, 0x00, 0x44, 0x00, + 0x0A, 0x00, 0x11, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, + 0x09, 0x03, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x11, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x22, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0xF0, 0x24, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x03, 0x00, + 0x03, 0x03, 0x63, 0x72, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0xC4, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x25, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x25, 0x00, 0xFF, 0x00, 0x49, 0x00, 0xFF, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x18, 0x40, 0x01, 0x00, 0x00, 0x00, 0xE0, 0x29, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x31, 0x30, 0x32, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x8E, 0x01, 0x00, 0x20, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x6F, 0x75, 0x74, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x8E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x66, 0x00, 0x09, 0x00, + 0x15, 0x00, 0x66, 0x00, 0x0A, 0x00, 0x1A, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0xFF, 0x0F, 0xFF, 0x0F, 0x0B, 0x04, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x1A, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x32, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x0C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x8E, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x66, 0x00, 0x09, 0x00, 0x15, 0x00, 0x66, 0x00, 0x0A, 0x00, 0x1A, 0x00, 0x02, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x0B, 0x04, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x32, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x8E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x66, 0x00, 0x09, 0x00, 0x15, 0x00, 0x66, 0x00, 0x0A, 0x00, 0x1A, 0x00, + 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x0B, 0x04, 0x00, 0x80, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x37, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x32, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x30, + 0x03, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x8E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x66, 0x00, 0x09, 0x00, 0x15, 0x00, 0x66, 0x00, + 0x0A, 0x00, 0x1A, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, + 0x0B, 0x04, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x32, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x50, 0x33, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x03, 0x00, + 0x03, 0x03, 0x03, 0x72, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x26, 0x01, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x18, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x18, 0x00, 0xFF, 0x00, 0x49, 0x00, 0xFE, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xDA, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x80, 0x18, 0x40, 0x01, 0x00, 0x00, 0x00, 0xEA, 0x1A, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x32, 0x30, 0x34, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE0, 0x1C, 0x03, 0x00, 0x20, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x6F, 0x75, 0x74, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, + 0x15, 0x00, 0xCC, 0x00, 0x0A, 0x00, 0x33, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0xFF, 0x0F, 0xFF, 0x0F, 0x13, 0x07, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x33, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x65, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x1C, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0xCC, 0x00, 0x09, 0x00, 0x15, 0x00, 0xCC, 0x00, 0x0A, 0x00, 0x33, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x13, 0x07, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x33, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x65, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x15, 0x00, 0xCC, 0x00, 0x0A, 0x00, 0x33, 0x00, + 0x03, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x13, 0x07, 0x00, 0x80, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x37, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x33, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x65, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x30, + 0x02, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, + 0x13, 0x07, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x33, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x65, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x03, 0x00, + 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x4C, 0x02, 0x00, 0x00, + 0xB2, 0x00, 0xFF, 0x00, 0xDA, 0x00, 0xFF, 0x00, 0x9D, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x0C, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x0C, 0x00, 0xFF, 0x00, 0x49, 0x00, 0x7F, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0xAD, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0xC6, 0x00, 0xFF, 0x00, 0xC6, 0x00, 0xFF, 0x00, 0x6D, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xE2, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x01, 0x00, 0x00, 0x00, 0x5C, 0x0D, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x34, 0x30, 0x38, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC0, 0x39, 0x06, 0x00, 0x2C, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0xE0, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x4A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0F, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x4D, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x03, 0x1C, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x98, 0x01, 0x0E, 0x00, + 0x1B, 0x00, 0x98, 0x01, 0x0A, 0x00, 0x66, 0x00, 0x04, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x35, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x66, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x19, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0xCB, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x19, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x38, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x03, 0x1C, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x98, 0x01, 0x0E, 0x00, 0x1B, 0x00, 0x98, 0x01, 0x0A, 0x00, 0x66, 0x00, 0x04, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x66, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0xCB, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x19, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x81, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xBB, 0x03, 0x1C, 0xC0, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x98, 0x01, 0x0E, 0x00, 0x1B, 0x00, 0x98, 0x01, 0x0A, 0x00, 0x66, 0x00, + 0x04, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x80, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x35, 0x80, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x66, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0xCB, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x19, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, + 0x07, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x07, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, + 0x4D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x03, 0x1C, 0xC0, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x03, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x98, 0x01, 0x0E, 0x00, 0x1B, 0x00, 0x98, 0x01, + 0x0A, 0x00, 0x66, 0x00, 0x04, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x0D, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x35, 0x00, 0x05, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x66, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0xCB, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x21, 0x00, 0x20, 0x00, + 0x22, 0x00, 0x21, 0x00, 0x22, 0x00, 0x21, 0x00, 0x21, 0x00, 0x20, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x21, 0x00, 0x20, 0x00, 0x22, 0x00, 0x21, 0x00, 0x22, 0x00, 0x21, 0x00, + 0x21, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x01, 0x7F, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x02, 0x03, 0x02, 0x04, 0x00, + 0x07, 0x0A, 0xA4, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x35, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x98, 0x04, 0x00, 0x00, + 0x59, 0x00, 0xFF, 0x00, 0x6D, 0x00, 0xFF, 0x00, 0x4F, 0x00, 0xFF, 0x00, 0xAF, 0x00, 0xFF, 0x00, + 0x06, 0x00, 0xFF, 0x00, 0xAF, 0x00, 0xFF, 0x00, 0x06, 0x00, 0xFF, 0x00, 0x49, 0x00, 0x40, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0x57, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0x63, 0x00, 0xFF, 0x00, 0x63, 0x00, 0xFF, 0x00, 0x36, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x71, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x08, 0x09, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x35, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0xE0, 0x01, 0x00, 0x00, 0x00, 0xD6, 0x06, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x36, 0x36, 0x35, 0x36, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x0A, 0x00, 0x39, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x11, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0xE4, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x7D, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x24, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x0B, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x9A, 0x02, 0x15, 0x00, + 0x1F, 0x00, 0x9A, 0x02, 0x0A, 0x00, 0xA7, 0x00, 0x05, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x06, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0xC9, 0x14, 0x00, 0x80, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0xA7, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x1E, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x4C, 0x01, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x28, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x11, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x24, 0x0A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x0B, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x9A, 0x02, 0x15, 0x00, 0x1F, 0x00, 0x9A, 0x02, 0x0A, 0x00, 0xA7, 0x00, 0x05, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x06, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x14, 0x00, 0x80, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0xA7, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x1B, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x4C, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x0B, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x00, 0x05, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x24, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xBB, 0x02, 0x0B, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x9A, 0x02, 0x15, 0x00, 0x1F, 0x00, 0x9A, 0x02, 0x0A, 0x00, 0xA7, 0x00, + 0x05, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x06, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x14, 0x00, 0x80, + 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xA7, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x4C, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, + 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x11, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, + 0x7D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x24, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x0B, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x9A, 0x02, 0x15, 0x00, 0x1F, 0x00, 0x9A, 0x02, + 0x0A, 0x00, 0xA7, 0x00, 0x05, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x06, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0xC9, 0x14, 0x00, 0x80, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x05, 0x05, + 0x00, 0x00, 0x05, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xA7, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x1E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x4C, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x22, 0x00, 0x20, 0x00, + 0x24, 0x00, 0x21, 0x00, 0x24, 0x00, 0x21, 0x00, 0x22, 0x00, 0x20, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x05, 0x00, 0x22, 0x00, 0x20, 0x00, 0x24, 0x00, 0x21, 0x00, 0x24, 0x00, 0x21, 0x00, + 0x22, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x04, 0x03, 0x06, 0x00, + 0x0A, 0x0F, 0xA5, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x57, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x7E, 0x07, 0x00, 0x00, + 0x3D, 0x00, 0xFF, 0x00, 0x43, 0x00, 0xFF, 0x00, 0x41, 0x00, 0xFF, 0x00, 0x90, 0x00, 0xFF, 0x00, + 0x05, 0x00, 0xFF, 0x00, 0x90, 0x00, 0xFF, 0x00, 0x05, 0x00, 0xFF, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0x35, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0x3D, 0x00, 0xFF, 0x00, 0x3D, 0x00, 0xFF, 0x00, 0x29, 0x00, 0xFF, 0x00, + 0xD8, 0x00, 0xFF, 0x00, 0x45, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x08, 0x12, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x35, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x04, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x35, 0x0C, 0x00, 0x39, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x13, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0xF0, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x07, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x20, 0x03, 0x19, 0x00, + 0x1F, 0x00, 0x20, 0x03, 0x0C, 0x00, 0xC8, 0x00, 0x06, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0xC8, 0x18, 0x00, 0x80, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0xC8, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x20, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x90, 0x01, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x30, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x13, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0xF0, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x30, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x07, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x20, 0x03, 0x19, 0x00, 0x1F, 0x00, 0x20, 0x03, 0x0C, 0x00, 0xC8, 0x00, 0x06, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x18, 0x00, 0x80, 0x17, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x90, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x30, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x0A, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x03, 0x00, 0x05, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xF0, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xBB, 0x02, 0x07, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x20, 0x03, 0x19, 0x00, 0x1F, 0x00, 0x20, 0x03, 0x0C, 0x00, 0xC8, 0x00, + 0x06, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x18, 0x00, 0x80, + 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x29, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x90, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x30, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x13, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xF0, 0x0B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x96, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x07, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x06, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x20, 0x03, 0x19, 0x00, 0x1F, 0x00, 0x20, 0x03, + 0x0C, 0x00, 0xC8, 0x00, 0x06, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x07, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0xC8, 0x18, 0x00, 0x80, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x90, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x23, 0x00, 0x1F, 0x00, + 0x24, 0x00, 0x22, 0x00, 0x24, 0x00, 0x22, 0x00, 0x23, 0x00, 0x20, 0x00, 0x06, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x24, 0x00, 0x22, 0x00, 0x24, 0x00, 0x22, 0x00, + 0x23, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x06, 0x04, 0x07, 0x00, + 0x0D, 0x12, 0x86, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x68, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x02, 0x09, 0x00, 0x00, + 0x3D, 0x00, 0xFF, 0x00, 0x38, 0x00, 0xFF, 0x00, 0x41, 0x00, 0xFF, 0x00, 0x90, 0x00, 0xFF, 0x00, + 0x05, 0x00, 0xFF, 0x00, 0x90, 0x00, 0xFF, 0x00, 0x05, 0x00, 0xFF, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0x2C, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0x32, 0x00, 0xFF, 0x00, 0x32, 0x00, 0xFF, 0x00, 0x22, 0x00, 0xFF, 0x00, + 0xB4, 0x00, 0xFF, 0x00, 0x3A, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x08, 0x12, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x35, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x31, 0x30, 0x36, 0x35, 0x36, 0x30, 0x30, 0x5F, 0x4E, + 0x6F, 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, + 0x2E, 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x42, 0x10, 0x00, 0x45, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x17, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x01, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, + 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, + 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x2A, 0x04, 0x21, 0x00, + 0x25, 0x00, 0x2A, 0x04, 0x0F, 0x00, 0x0B, 0x01, 0x07, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0xAB, 0x20, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x61, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x27, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x14, 0x02, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x4C, 0x48, 0x48, 0x0E, 0x4C, + 0x40, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, + 0x17, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x3C, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x01, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x06, 0x0B, 0x08, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x2A, 0x04, 0x21, 0x00, 0x25, 0x00, 0x2A, 0x04, 0x0F, 0x00, 0x0B, 0x01, 0x07, 0x03, 0xE0, 0xC1, + 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x20, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x26, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x14, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x40, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x08, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x07, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x03, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, + 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xFF, 0x3B, 0x00, 0x00, + 0xBB, 0x01, 0x01, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, + 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x2A, 0x04, 0x21, 0x00, 0x25, 0x00, 0x2A, 0x04, 0x0F, 0x00, 0x0B, 0x01, + 0x07, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x20, 0x00, 0x80, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x14, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x40, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x17, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x48, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x01, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, 0x08, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x2A, 0x04, 0x21, 0x00, 0x25, 0x00, 0x2A, 0x04, + 0x0F, 0x00, 0x0B, 0x01, 0x07, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x09, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0xAB, 0x20, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x61, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x27, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x14, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x24, 0x00, 0x1F, 0x00, + 0x26, 0x00, 0x23, 0x00, 0x26, 0x00, 0x23, 0x00, 0x24, 0x00, 0x20, 0x00, 0x08, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x08, 0x00, 0x24, 0x00, 0x1F, 0x00, 0x26, 0x00, 0x23, 0x00, 0x26, 0x00, 0x23, 0x00, + 0x24, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x03, 0x03, 0x04, 0x03, 0x08, 0x05, 0x09, 0x00, + 0x11, 0x18, 0x88, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x8B, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0xFF, 0x0B, 0x00, 0x00, + 0x3D, 0x00, 0xC0, 0x00, 0x38, 0x00, 0xC0, 0x00, 0x41, 0x00, 0xC0, 0x00, 0x90, 0x00, 0xC0, 0x00, + 0x05, 0x00, 0xC0, 0x00, 0x90, 0x00, 0xC0, 0x00, 0x05, 0x00, 0xC0, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0xC0, 0x00, 0x04, 0x00, 0xC0, 0x00, 0x21, 0x00, 0x08, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xC0, 0x00, 0x26, 0x00, 0xC0, 0x00, 0x26, 0x00, 0xC0, 0x00, 0x19, 0x00, 0xC0, 0x00, + 0x95, 0x00, 0xC0, 0x00, 0x2B, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0xC0, 0x00, 0x25, 0x00, 0x00, 0x00, 0x34, 0x00, 0x01, 0x08, 0x1B, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x48, 0x48, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x25, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x04, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x31, 0x33, 0x33, 0x31, 0x32, 0x30, 0x30, 0x5F, 0x4E, + 0x6F, 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, + 0x2E, 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x50, 0x14, 0x00, 0x52, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x1A, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, + 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x34, 0x05, 0x29, 0x00, + 0x2B, 0x00, 0x34, 0x05, 0x13, 0x00, 0x4D, 0x01, 0x08, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x8F, 0x28, 0x00, 0x80, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x4D, 0x61, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x2E, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x06, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x99, 0x02, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x4C, 0x48, 0x48, 0x0E, 0x4C, + 0x50, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, + 0x1A, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x48, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x06, 0x0B, 0x08, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x34, 0x05, 0x29, 0x00, 0x2B, 0x00, 0x34, 0x05, 0x13, 0x00, 0x4D, 0x01, 0x08, 0x03, 0xE0, 0xC1, + 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x28, 0x00, 0x80, 0x26, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x4D, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x2C, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x99, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x50, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x08, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0A, 0x00, 0x06, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, + 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xFF, 0x3B, 0x00, 0x00, + 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x0A, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x0A, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x34, 0x05, 0x29, 0x00, 0x2B, 0x00, 0x34, 0x05, 0x13, 0x00, 0x4D, 0x01, + 0x08, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x28, 0x00, 0x80, + 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, + 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x4D, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x38, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x99, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x50, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x48, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, 0x0A, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x34, 0x05, 0x29, 0x00, 0x2B, 0x00, 0x34, 0x05, + 0x13, 0x00, 0x4D, 0x01, 0x08, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x0B, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0x8F, 0x28, 0x00, 0x80, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x4D, 0x61, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x2E, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x99, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, + 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x25, 0x00, 0x1F, 0x00, + 0x28, 0x00, 0x23, 0x00, 0x28, 0x00, 0x23, 0x00, 0x25, 0x00, 0x20, 0x00, 0x0A, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x0A, 0x00, 0x25, 0x00, 0x1F, 0x00, 0x28, 0x00, 0x23, 0x00, 0x28, 0x00, 0x23, 0x00, + 0x25, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x03, 0x03, 0x05, 0x04, 0x09, 0x07, 0x0B, 0x00, + 0x14, 0x1E, 0x8A, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0xAD, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0xFC, 0x0E, 0x00, 0x00, + 0x3D, 0x00, 0x99, 0x00, 0x38, 0x00, 0x99, 0x00, 0x41, 0x00, 0x99, 0x00, 0x90, 0x00, 0x99, 0x00, + 0x05, 0x00, 0x99, 0x00, 0x90, 0x00, 0x99, 0x00, 0x05, 0x00, 0x99, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0x99, 0x00, 0x04, 0x00, 0x99, 0x00, 0x1B, 0x00, 0x08, 0x00, 0x99, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x99, 0x00, 0x1E, 0x00, 0x99, 0x00, 0x1E, 0x00, 0x99, 0x00, 0x18, 0x00, 0x99, 0x00, + 0x95, 0x00, 0x99, 0x00, 0x23, 0x00, 0x99, 0x00, 0x99, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x99, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x44, 0x00, 0x01, 0x08, 0x24, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x48, 0x48, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x2D, 0x08, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5F, 0x4E, + 0x6F, 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, + 0x2E, 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6A, 0x18, 0x00, 0x77, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x10, + 0x02, 0x00, 0x00, 0x10, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x1D, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x20, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x0B, 0x08, + 0x0C, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0B, 0x00, 0x0B, 0x00, + 0x0A, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x40, 0x06, 0x31, 0x00, + 0x2F, 0x00, 0x40, 0x06, 0x17, 0x00, 0x90, 0x01, 0x0A, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x8C, 0x30, 0x00, 0x80, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x90, 0x61, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x34, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x20, 0x03, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x48, 0x48, 0x0C, 0x88, 0x48, 0x48, 0x0C, 0x88, 0x48, 0x48, 0x0C, 0x48, 0x48, 0x48, 0x0C, 0x48, + 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x4C, 0x48, 0x48, 0x0E, 0x4C, + 0x60, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, + 0x1D, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x60, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x0B, 0x08, 0x0C, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x40, 0x06, 0x31, 0x00, 0x2F, 0x00, 0x40, 0x06, 0x17, 0x00, 0x90, 0x01, 0x0A, 0x03, 0xE0, 0xC1, + 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x30, 0x00, 0x80, 0x2C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x90, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x42, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x34, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x20, 0x03, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x32, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x60, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, 0x16, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x08, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0E, 0x00, 0x06, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, + 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, + 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x0B, 0x08, 0x0C, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0C, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x40, 0x06, 0x31, 0x00, 0x2F, 0x00, 0x40, 0x06, 0x17, 0x00, 0x90, 0x01, + 0x0A, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x30, 0x00, 0x80, + 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, + 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x90, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x20, 0x03, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x60, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, + 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x1D, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x48, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, + 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x0B, 0x08, 0x0C, 0x00, 0x0B, 0x00, + 0x0A, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0A, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x40, 0x06, 0x31, 0x00, 0x2F, 0x00, 0x40, 0x06, + 0x17, 0x00, 0x90, 0x01, 0x0A, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x0D, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0x8C, 0x30, 0x00, 0x80, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x90, 0x61, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x34, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x20, 0x03, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, + 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x26, 0x00, 0x1E, 0x00, + 0x29, 0x00, 0x24, 0x00, 0x29, 0x00, 0x24, 0x00, 0x26, 0x00, 0x20, 0x00, 0x0C, 0x00, 0x0B, 0x00, + 0x0A, 0x00, 0x0C, 0x00, 0x26, 0x00, 0x1E, 0x00, 0x29, 0x00, 0x24, 0x00, 0x29, 0x00, 0x24, 0x00, + 0x26, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x03, 0x03, 0x06, 0x05, 0x0C, 0x08, 0x0D, 0x00, + 0x19, 0x24, 0x8C, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x03, 0x12, 0x00, 0x00, + 0x3D, 0x00, 0x80, 0x00, 0x38, 0x00, 0x80, 0x00, 0x41, 0x00, 0x80, 0x00, 0x90, 0x00, 0x80, 0x00, + 0x05, 0x00, 0x80, 0x00, 0x90, 0x00, 0x80, 0x00, 0x05, 0x00, 0x80, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x04, 0x00, 0x80, 0x00, 0x16, 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x80, 0x00, 0x19, 0x00, 0x80, 0x00, 0x19, 0x00, 0x80, 0x00, 0x18, 0x00, 0x80, 0x00, + 0x95, 0x00, 0x80, 0x00, 0x1D, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x54, 0x00, 0x01, 0x08, 0x2D, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x48, 0x48, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x35, 0x08, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x04, 0x00, 0x00 +}; + +unsigned char nx_abca2_dram_1[0xC080] = +{ + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x34, 0x30, 0x38, 0x30, 0x30, 0x5F, 0x4E, 0x6F, 0x43, + 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, 0x37, + 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x9F, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x6F, 0x75, 0x74, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x29, 0x00, 0x09, 0x00, + 0x15, 0x00, 0x29, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0xFF, 0x0F, 0xFF, 0x0F, 0x3A, 0x02, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x14, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0xA0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x29, 0x00, 0x09, 0x00, 0x15, 0x00, 0x29, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x02, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x3A, 0x02, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x14, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x29, 0x00, 0x09, 0x00, 0x15, 0x00, 0x29, 0x00, 0x0A, 0x00, 0x0B, 0x00, + 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x3A, 0x02, 0x00, 0x80, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x37, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x14, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x30, + 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x9A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x29, 0x00, 0x09, 0x00, 0x15, 0x00, 0x29, 0x00, + 0x0A, 0x00, 0x0B, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, + 0x3A, 0x02, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x14, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x02, 0x40, 0x13, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x03, 0x00, + 0x03, 0x03, 0xC3, 0x72, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x76, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x3D, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x3D, 0x00, 0xFF, 0x00, 0x49, 0x00, 0xFF, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x12, 0x80, 0x18, 0x40, 0x01, 0x00, 0x00, 0x00, 0x72, 0x51, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x36, 0x38, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, 0x43, + 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, 0x37, + 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xA0, 0x09, 0x01, 0x00, 0x20, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x6F, 0x75, 0x74, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x44, 0x00, 0x09, 0x00, + 0x15, 0x00, 0x44, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0xFF, 0x0F, 0xFF, 0x0F, 0x09, 0x03, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x11, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x22, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x0A, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x44, 0x00, 0x09, 0x00, 0x15, 0x00, 0x44, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x02, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x09, 0x03, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x11, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x22, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x02, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x44, 0x00, 0x09, 0x00, 0x15, 0x00, 0x44, 0x00, 0x0A, 0x00, 0x11, 0x00, + 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x09, 0x03, 0x00, 0x80, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x37, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x11, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x22, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x30, + 0x04, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x44, 0x00, 0x09, 0x00, 0x15, 0x00, 0x44, 0x00, + 0x0A, 0x00, 0x11, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, + 0x09, 0x03, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x11, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x22, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0xF0, 0x24, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x03, 0x00, + 0x03, 0x03, 0x63, 0x72, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0xC4, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x25, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x25, 0x00, 0xFF, 0x00, 0x49, 0x00, 0xFF, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x18, 0x40, 0x01, 0x00, 0x00, 0x00, 0xE0, 0x29, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x31, 0x30, 0x32, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x70, 0x8E, 0x01, 0x00, 0x20, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x6F, 0x75, 0x74, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0B, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x8E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x66, 0x00, 0x09, 0x00, + 0x15, 0x00, 0x66, 0x00, 0x0A, 0x00, 0x1A, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0xFF, 0x0F, 0xFF, 0x0F, 0x0B, 0x04, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x1A, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x32, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x0C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x8E, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x66, 0x00, 0x09, 0x00, 0x15, 0x00, 0x66, 0x00, 0x0A, 0x00, 0x1A, 0x00, 0x02, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x0B, 0x04, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x32, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x8E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x66, 0x00, 0x09, 0x00, 0x15, 0x00, 0x66, 0x00, 0x0A, 0x00, 0x1A, 0x00, + 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x0B, 0x04, 0x00, 0x80, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x37, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x04, 0x04, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x32, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x0C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x30, + 0x03, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x82, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x8E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x66, 0x00, 0x09, 0x00, 0x15, 0x00, 0x66, 0x00, + 0x0A, 0x00, 0x1A, 0x00, 0x02, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, + 0x0B, 0x04, 0x00, 0x80, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x04, 0x04, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x1A, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x32, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x50, 0x33, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x03, 0x00, + 0x03, 0x03, 0x03, 0x72, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x26, 0x01, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x18, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x18, 0x00, 0xFF, 0x00, 0x49, 0x00, 0xFE, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xDA, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x80, 0x18, 0x40, 0x01, 0x00, 0x00, 0x00, 0xEA, 0x1A, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x32, 0x30, 0x34, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE0, 0x1C, 0x03, 0x00, 0x20, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x6F, 0x75, 0x74, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0D, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, + 0x15, 0x00, 0xCC, 0x00, 0x0A, 0x00, 0x33, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0xFF, 0x0F, 0xFF, 0x0F, 0x13, 0x07, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x33, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x65, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x1C, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0xCC, 0x00, 0x09, 0x00, 0x15, 0x00, 0xCC, 0x00, 0x0A, 0x00, 0x33, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x13, 0x07, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x33, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x65, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x15, 0x00, 0xCC, 0x00, 0x0A, 0x00, 0x33, 0x00, + 0x03, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, 0x13, 0x07, 0x00, 0x80, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x37, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x33, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x65, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x30, + 0x02, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0xFF, 0x0F, 0xFF, 0x0F, + 0x13, 0x07, 0x00, 0x80, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x37, 0x00, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x33, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x65, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x03, 0x00, + 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x4C, 0x02, 0x00, 0x00, + 0xB2, 0x00, 0xFF, 0x00, 0xDA, 0x00, 0xFF, 0x00, 0x9D, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x0C, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x0C, 0x00, 0xFF, 0x00, 0x49, 0x00, 0x7F, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0xAD, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0xC6, 0x00, 0xFF, 0x00, 0xC6, 0x00, 0xFF, 0x00, 0x6D, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xE2, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x01, 0x00, 0x00, 0x00, 0x5C, 0x0D, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x34, 0x30, 0x38, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC0, 0x39, 0x06, 0x00, 0x2C, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x70, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0xE0, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x4A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0F, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x01, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x4D, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x03, 0x1C, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x98, 0x01, 0x0E, 0x00, + 0x1B, 0x00, 0x98, 0x01, 0x0A, 0x00, 0x66, 0x00, 0x04, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x35, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x66, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x19, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0xCB, 0x00, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x19, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x07, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x01, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x38, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x03, 0x1C, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x98, 0x01, 0x0E, 0x00, 0x1B, 0x00, 0x98, 0x01, 0x0A, 0x00, 0x66, 0x00, 0x04, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x66, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x15, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0xCB, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x19, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x05, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x81, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xBB, 0x03, 0x1C, 0xC0, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x98, 0x01, 0x0E, 0x00, 0x1B, 0x00, 0x98, 0x01, 0x0A, 0x00, 0x66, 0x00, + 0x04, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x04, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x22, 0x0D, 0x00, 0x80, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x35, 0x80, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x66, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0xCB, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x19, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, + 0x07, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, 0x19, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x07, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x81, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, + 0x4D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x38, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x03, 0x1C, 0xC0, 0x00, 0x80, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x03, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x98, 0x01, 0x0E, 0x00, 0x1B, 0x00, 0x98, 0x01, + 0x0A, 0x00, 0x66, 0x00, 0x04, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x0D, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x35, 0x00, 0x05, 0x05, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x66, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0xCB, 0x00, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x21, 0x00, 0x20, 0x00, + 0x22, 0x00, 0x21, 0x00, 0x22, 0x00, 0x21, 0x00, 0x21, 0x00, 0x20, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x03, 0x00, 0x21, 0x00, 0x20, 0x00, 0x22, 0x00, 0x21, 0x00, 0x22, 0x00, 0x21, 0x00, + 0x21, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x01, 0x7F, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x02, 0x03, 0x02, 0x04, 0x00, + 0x07, 0x0A, 0xA4, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x35, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x98, 0x04, 0x00, 0x00, + 0x59, 0x00, 0xFF, 0x00, 0x6D, 0x00, 0xFF, 0x00, 0x4F, 0x00, 0xFF, 0x00, 0xAF, 0x00, 0xFF, 0x00, + 0x06, 0x00, 0xFF, 0x00, 0xAF, 0x00, 0xFF, 0x00, 0x06, 0x00, 0xFF, 0x00, 0x49, 0x00, 0x40, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0x57, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0x63, 0x00, 0xFF, 0x00, 0x63, 0x00, 0xFF, 0x00, 0x36, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x71, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x08, 0x09, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x35, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0xE0, 0x01, 0x00, 0x00, 0x00, 0xD6, 0x06, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x36, 0x36, 0x35, 0x36, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x28, 0x0A, 0x00, 0x39, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x11, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x01, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0xE4, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x7D, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x24, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x0B, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x9A, 0x02, 0x15, 0x00, + 0x1F, 0x00, 0x9A, 0x02, 0x0A, 0x00, 0xA7, 0x00, 0x05, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x01, 0x00, 0x06, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0xC9, 0x14, 0x00, 0x80, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0xA7, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x1E, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x01, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x4C, 0x01, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x28, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x01, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x24, 0x0A, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x0B, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x9A, 0x02, 0x15, 0x00, 0x1F, 0x00, 0x9A, 0x02, 0x0A, 0x00, 0xA7, 0x00, 0x05, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x06, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x14, 0x00, 0x80, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0xA7, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x1B, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x4C, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x0B, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x04, 0x00, 0x05, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x24, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xBB, 0x02, 0x0B, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x9A, 0x02, 0x15, 0x00, 0x1F, 0x00, 0x9A, 0x02, 0x0A, 0x00, 0xA7, 0x00, + 0x05, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x06, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xC9, 0x14, 0x00, 0x80, + 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, + 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x01, 0x00, 0x02, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE2, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xA7, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x4C, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x28, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, + 0x0A, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x05, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x79, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, + 0x7D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x24, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x0B, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x9A, 0x02, 0x15, 0x00, 0x1F, 0x00, 0x9A, 0x02, + 0x0A, 0x00, 0xA7, 0x00, 0x05, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0x06, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0xC9, 0x14, 0x00, 0x80, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x05, 0x05, + 0x00, 0x00, 0x05, 0x05, 0x10, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x11, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xA7, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x1E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x4C, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x22, 0x00, 0x20, 0x00, + 0x24, 0x00, 0x21, 0x00, 0x24, 0x00, 0x21, 0x00, 0x22, 0x00, 0x20, 0x00, 0x05, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x05, 0x00, 0x22, 0x00, 0x20, 0x00, 0x24, 0x00, 0x21, 0x00, 0x24, 0x00, 0x21, 0x00, + 0x22, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x03, 0x04, 0x03, 0x04, 0x03, 0x06, 0x00, + 0x0A, 0x0F, 0xA5, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x57, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x7E, 0x07, 0x00, 0x00, + 0x3D, 0x00, 0xFF, 0x00, 0x43, 0x00, 0xFF, 0x00, 0x41, 0x00, 0xFF, 0x00, 0x90, 0x00, 0xFF, 0x00, + 0x05, 0x00, 0xFF, 0x00, 0x90, 0x00, 0xFF, 0x00, 0x05, 0x00, 0xFF, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0x35, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0x3D, 0x00, 0xFF, 0x00, 0x3D, 0x00, 0xFF, 0x00, 0x29, 0x00, 0xFF, 0x00, + 0xD8, 0x00, 0xFF, 0x00, 0x45, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x08, 0x12, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x35, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0xCE, 0x04, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5F, 0x4E, 0x6F, + 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, 0x2E, + 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x35, 0x0C, 0x00, 0x39, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x13, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0xF0, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x07, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, + 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x20, 0x03, 0x19, 0x00, + 0x1F, 0x00, 0x20, 0x03, 0x0C, 0x00, 0xC8, 0x00, 0x06, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0xC8, 0x18, 0x00, 0x80, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0xC8, 0x60, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x20, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x90, 0x01, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x8C, 0x72, 0x72, 0x0E, 0x4C, 0x72, 0x72, 0x0E, 0x4C, + 0x30, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, + 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x05, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0xF0, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, 0x30, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x07, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0B, 0x08, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x20, 0x03, 0x19, 0x00, 0x1F, 0x00, 0x20, 0x03, 0x0C, 0x00, 0xC8, 0x00, 0x06, 0x03, 0xE0, 0xC1, + 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x18, 0x00, 0x80, 0x17, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x90, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x30, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x0A, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x08, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x03, 0x00, 0x05, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xF0, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x48, + 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xBF, 0x3B, 0x00, 0x00, + 0xBB, 0x02, 0x07, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, + 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x20, 0x03, 0x19, 0x00, 0x1F, 0x00, 0x20, 0x03, 0x0C, 0x00, 0xC8, 0x00, + 0x06, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x07, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xC8, 0x18, 0x00, 0x80, + 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0x60, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x29, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x90, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x40, 0x72, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x30, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, + 0x09, 0x00, 0x00, 0x00, 0x71, 0x71, 0x03, 0x08, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xF0, 0x0B, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x96, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x03, 0x48, 0x30, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0xBB, 0x02, 0x07, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x06, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x20, 0x03, 0x19, 0x00, 0x1F, 0x00, 0x20, 0x03, + 0x0C, 0x00, 0xC8, 0x00, 0x06, 0x03, 0xE0, 0xC1, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x07, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0xC8, 0x18, 0x00, 0x80, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0xC8, 0x60, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x90, 0x01, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x40, 0x72, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x23, 0x00, 0x1F, 0x00, + 0x24, 0x00, 0x22, 0x00, 0x24, 0x00, 0x22, 0x00, 0x23, 0x00, 0x20, 0x00, 0x06, 0x00, 0x05, 0x00, + 0x05, 0x00, 0x06, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x24, 0x00, 0x22, 0x00, 0x24, 0x00, 0x22, 0x00, + 0x23, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x03, 0x04, 0x03, 0x06, 0x04, 0x07, 0x00, + 0x0D, 0x12, 0x86, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x68, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x02, 0x09, 0x00, 0x00, + 0x3D, 0x00, 0xFF, 0x00, 0x38, 0x00, 0xFF, 0x00, 0x41, 0x00, 0xFF, 0x00, 0x90, 0x00, 0xFF, 0x00, + 0x05, 0x00, 0xFF, 0x00, 0x90, 0x00, 0xFF, 0x00, 0x05, 0x00, 0xFF, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0xFF, 0x00, 0x04, 0x00, 0xFF, 0x00, 0x2C, 0x00, 0x08, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xFF, 0x00, 0x32, 0x00, 0xFF, 0x00, 0x32, 0x00, 0xFF, 0x00, 0x22, 0x00, 0xFF, 0x00, + 0xB4, 0x00, 0xFF, 0x00, 0x3A, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x08, 0x12, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x35, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x31, 0x30, 0x36, 0x35, 0x36, 0x30, 0x30, 0x5F, 0x4E, + 0x6F, 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, + 0x2E, 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x42, 0x10, 0x00, 0x45, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x17, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x06, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x29, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x01, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, + 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, + 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x2A, 0x04, 0x21, 0x00, + 0x25, 0x00, 0x2A, 0x04, 0x0F, 0x00, 0x0B, 0x01, 0x07, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0xAB, 0x20, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x61, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x27, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x14, 0x02, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x03, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x4C, 0x48, 0x48, 0x0E, 0x4C, + 0x40, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, + 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x06, 0x00, 0x05, 0x00, + 0x27, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x2F, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x3C, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x01, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x06, 0x0B, 0x08, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x2A, 0x04, 0x21, 0x00, 0x25, 0x00, 0x2A, 0x04, 0x0F, 0x00, 0x0B, 0x01, 0x07, 0x03, 0xE0, 0xC1, + 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x20, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x26, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x14, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x40, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x08, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x07, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x03, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, + 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xFF, 0x3B, 0x00, 0x00, + 0xBB, 0x01, 0x01, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, + 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x2A, 0x04, 0x21, 0x00, 0x25, 0x00, 0x2A, 0x04, 0x0F, 0x00, 0x0B, 0x01, + 0x07, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x20, 0x00, 0x80, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x01, 0x00, 0x02, + 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xE2, 0xFF, 0xEF, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x05, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x14, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x13, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x40, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x0D, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x06, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, + 0xC8, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x48, 0x3C, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x01, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, 0x08, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x03, 0x00, 0x05, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x2A, 0x04, 0x21, 0x00, 0x25, 0x00, 0x2A, 0x04, + 0x0F, 0x00, 0x0B, 0x01, 0x07, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x09, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0xAB, 0x20, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, + 0x01, 0x01, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0x00, 0x16, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0xE2, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x61, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x31, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x27, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x14, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x13, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x03, 0x00, 0x07, + 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x24, 0x00, 0x1F, 0x00, + 0x26, 0x00, 0x23, 0x00, 0x26, 0x00, 0x23, 0x00, 0x24, 0x00, 0x20, 0x00, 0x08, 0x00, 0x07, 0x00, + 0x06, 0x00, 0x08, 0x00, 0x24, 0x00, 0x1F, 0x00, 0x26, 0x00, 0x23, 0x00, 0x26, 0x00, 0x23, 0x00, + 0x24, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x03, 0x03, 0x05, 0x03, 0x08, 0x05, 0x09, 0x00, + 0x11, 0x18, 0x88, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x8B, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0xFF, 0x0B, 0x00, 0x00, + 0x3D, 0x00, 0xC0, 0x00, 0x38, 0x00, 0xC0, 0x00, 0x41, 0x00, 0xC0, 0x00, 0x90, 0x00, 0xC0, 0x00, + 0x05, 0x00, 0xC0, 0x00, 0x90, 0x00, 0xC0, 0x00, 0x05, 0x00, 0xC0, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0xC0, 0x00, 0x04, 0x00, 0xC0, 0x00, 0x21, 0x00, 0x08, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x04, 0x00, 0xC0, 0x00, 0x26, 0x00, 0xC0, 0x00, 0x26, 0x00, 0xC0, 0x00, 0x19, 0x00, 0xC0, 0x00, + 0x95, 0x00, 0xC0, 0x00, 0x2B, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0xC0, 0x00, 0x25, 0x00, 0x00, 0x00, 0x34, 0x00, 0x01, 0x08, 0x1B, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x48, 0x48, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x25, 0x08, 0x11, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x04, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x31, 0x33, 0x33, 0x31, 0x32, 0x30, 0x30, 0x5F, 0x4E, + 0x6F, 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, + 0x2E, 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x50, 0x14, 0x00, 0x52, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0xF0, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x1A, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x09, 0x00, 0x06, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x91, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, + 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x34, 0x05, 0x29, 0x00, + 0x2B, 0x00, 0x34, 0x05, 0x13, 0x00, 0x4D, 0x01, 0x08, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x8F, 0x28, 0x00, 0x80, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x4D, 0x61, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x2E, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x06, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x99, 0x02, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x88, 0x72, 0x72, 0x0C, 0x48, 0x72, 0x72, 0x0C, 0x48, + 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x4C, 0x48, 0x48, 0x0E, 0x4C, + 0x50, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, + 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x09, 0x00, 0x06, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x27, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x48, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x06, 0x0B, 0x08, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x34, 0x05, 0x29, 0x00, 0x2B, 0x00, 0x34, 0x05, 0x13, 0x00, 0x4D, 0x01, 0x08, 0x03, 0xE0, 0xC1, + 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x28, 0x00, 0x80, 0x26, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x4D, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x2C, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x99, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x50, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x08, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0A, 0x00, 0x06, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, + 0x0B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, + 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x91, 0xFF, 0x3B, 0x00, 0x00, + 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x0A, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, + 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x0A, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x34, 0x05, 0x29, 0x00, 0x2B, 0x00, 0x34, 0x05, 0x13, 0x00, 0x4D, 0x01, + 0x08, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x0B, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x28, 0x00, 0x80, + 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, + 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x4D, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x38, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x99, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x50, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x11, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x09, 0x00, 0x06, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x08, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x00, + 0xFA, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x48, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x0B, 0x08, 0x0A, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x0A, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x0A, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x34, 0x05, 0x29, 0x00, 0x2B, 0x00, 0x34, 0x05, + 0x13, 0x00, 0x4D, 0x01, 0x08, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x0B, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0x8F, 0x28, 0x00, 0x80, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x4D, 0x61, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x2E, 0x00, 0x00, 0x00, 0x09, 0x00, 0x06, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x99, 0x02, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x40, 0x72, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, + 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x25, 0x00, 0x1F, 0x00, + 0x28, 0x00, 0x23, 0x00, 0x28, 0x00, 0x23, 0x00, 0x25, 0x00, 0x20, 0x00, 0x0A, 0x00, 0x09, 0x00, + 0x08, 0x00, 0x0A, 0x00, 0x25, 0x00, 0x1F, 0x00, 0x28, 0x00, 0x23, 0x00, 0x28, 0x00, 0x23, 0x00, + 0x25, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x03, 0x03, 0x06, 0x04, 0x09, 0x07, 0x0B, 0x00, + 0x14, 0x1E, 0x8A, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0xAD, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0xFC, 0x0E, 0x00, 0x00, + 0x3D, 0x00, 0x99, 0x00, 0x38, 0x00, 0x99, 0x00, 0x41, 0x00, 0x99, 0x00, 0x90, 0x00, 0x99, 0x00, + 0x05, 0x00, 0x99, 0x00, 0x90, 0x00, 0x99, 0x00, 0x05, 0x00, 0x99, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0x99, 0x00, 0x04, 0x00, 0x99, 0x00, 0x1B, 0x00, 0x08, 0x00, 0x99, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x99, 0x00, 0x1E, 0x00, 0x99, 0x00, 0x1E, 0x00, 0x99, 0x00, 0x18, 0x00, 0x99, 0x00, + 0x95, 0x00, 0x99, 0x00, 0x23, 0x00, 0x99, 0x00, 0x99, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x99, 0x00, 0x99, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x44, 0x00, 0x01, 0x08, 0x24, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x48, 0x48, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x2D, 0x08, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x31, 0x30, 0x5F, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5F, 0x4E, + 0x6F, 0x43, 0x66, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x56, 0x39, 0x2E, 0x38, + 0x2E, 0x37, 0x5F, 0x56, 0x31, 0x2E, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x6A, 0x18, 0x00, 0x77, 0x03, 0x00, 0x00, 0x4C, 0x04, 0x00, 0x00, 0x70, 0x6C, 0x6C, 0x6D, + 0x5F, 0x75, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, + 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xDD, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x8A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x20, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x10, + 0x02, 0x00, 0x00, 0x10, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x1D, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x06, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x20, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0D, 0xA0, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x0B, 0x08, + 0x0C, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0B, 0x00, 0x0B, 0x00, + 0x0A, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, + 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x40, 0x06, 0x31, 0x00, + 0x2F, 0x00, 0x40, 0x06, 0x17, 0x00, 0x90, 0x01, 0x0A, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, + 0x00, 0x00, 0x00, 0x00, 0x8C, 0x30, 0x00, 0x80, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, + 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x90, 0x61, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x2C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x34, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x06, 0x00, 0x80, 0x90, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x20, 0x03, 0x04, 0x00, + 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x10, 0x00, + 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, + 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, + 0x48, 0x48, 0x0C, 0x88, 0x48, 0x48, 0x0C, 0x88, 0x48, 0x48, 0x0C, 0x48, 0x48, 0x48, 0x0C, 0x48, + 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x8C, 0x48, 0x48, 0x0E, 0x4C, 0x48, 0x48, 0x0E, 0x4C, + 0x60, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, + 0x1D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x06, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, 0x60, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, + 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x66, 0x0B, 0x08, 0x0C, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, + 0x40, 0x06, 0x31, 0x00, 0x2F, 0x00, 0x40, 0x06, 0x17, 0x00, 0x90, 0x01, 0x0A, 0x03, 0xE0, 0xC1, + 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x30, 0x00, 0x80, 0x2C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, + 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x90, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x42, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, + 0x34, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x80, 0x90, 0x01, 0x00, 0x04, 0x04, 0x07, 0x07, + 0x20, 0x03, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x32, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, + 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, + 0x14, 0x14, 0x16, 0x48, 0x60, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x2B, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, 0x16, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x08, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0E, 0x00, 0x06, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x3A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x48, + 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x40, 0x60, 0x99, 0xFF, 0x3B, 0x00, 0x00, + 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x0B, 0x08, 0x0C, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0C, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0A, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0x40, 0x06, 0x31, 0x00, 0x2F, 0x00, 0x40, 0x06, 0x17, 0x00, 0x90, 0x01, + 0x0A, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, + 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x30, 0x00, 0x80, + 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x33, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x02, + 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, 0x20, 0x20, 0x10, 0x00, + 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x22, 0xFF, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x90, 0x61, 0x18, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, + 0x14, 0x14, 0x16, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x06, 0x00, 0x80, 0x90, 0x00, 0x00, + 0x04, 0x04, 0x07, 0x07, 0x20, 0x03, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, 0x00, 0x11, 0x10, 0x1F, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, 0x6A, 0x5B, 0x12, 0x01, + 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, 0x00, 0x53, 0x08, 0x0F, + 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, 0x00, 0x32, 0x10, 0x00, + 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x60, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, + 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, + 0x14, 0x00, 0x00, 0x00, 0xF1, 0xF1, 0x03, 0x08, 0x1D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x06, 0x00, 0x34, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x20, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0xF1, 0xF1, 0x03, 0x48, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x99, + 0xFF, 0x3B, 0x00, 0x00, 0xBB, 0x01, 0x00, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x0B, 0x08, 0x0C, 0x00, 0x0B, 0x00, + 0x0A, 0x00, 0x0C, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x05, 0x00, 0x08, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x0A, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, + 0x12, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x40, 0x06, 0x31, 0x00, 0x2F, 0x00, 0x40, 0x06, + 0x17, 0x00, 0x90, 0x01, 0x0A, 0x03, 0xE0, 0xC1, 0x2F, 0x61, 0x13, 0x1F, 0x14, 0x00, 0x00, 0x00, + 0x0D, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x00, 0x00, 0x00, 0x00, + 0x8C, 0x30, 0x00, 0x80, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x01, 0x01, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x20, 0x20, 0x10, 0x00, 0xFF, 0x1F, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x22, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0xDC, 0xDC, 0xDC, + 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x90, 0x61, 0x18, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x3E, 0x00, 0x00, 0x00, 0x14, 0x14, 0x16, 0x08, 0x34, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x00, + 0x80, 0xB0, 0x00, 0x00, 0x04, 0x04, 0x07, 0x07, 0x20, 0x03, 0x04, 0x00, 0x1F, 0x80, 0x13, 0x05, + 0x00, 0x11, 0x10, 0x1F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, 0x40, 0x12, 0x01, + 0x6A, 0x5B, 0x12, 0x01, 0x00, 0x10, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x10, 0x11, + 0x00, 0x53, 0x08, 0x0F, 0x00, 0x58, 0x10, 0x00, 0x00, 0xFC, 0x14, 0x11, 0x00, 0x43, 0x00, 0x07, + 0x00, 0x32, 0x10, 0x00, 0x5A, 0x3C, 0x55, 0x55, 0x14, 0x14, 0x16, 0x48, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x26, 0x00, 0x1E, 0x00, + 0x29, 0x00, 0x24, 0x00, 0x29, 0x00, 0x24, 0x00, 0x26, 0x00, 0x20, 0x00, 0x0C, 0x00, 0x0B, 0x00, + 0x0A, 0x00, 0x0C, 0x00, 0x26, 0x00, 0x1E, 0x00, 0x29, 0x00, 0x24, 0x00, 0x29, 0x00, 0x24, 0x00, + 0x26, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x04, 0x01, 0x00, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x00, 0x80, + 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x03, 0x03, 0x06, 0x05, 0x0C, 0x08, 0x0D, 0x00, + 0x19, 0x24, 0x8C, 0x71, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x1A, 0x00, 0x80, 0x00, + 0x1A, 0x00, 0x80, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x80, 0x00, 0x03, 0x12, 0x00, 0x00, + 0x3D, 0x00, 0x80, 0x00, 0x38, 0x00, 0x80, 0x00, 0x41, 0x00, 0x80, 0x00, 0x90, 0x00, 0x80, 0x00, + 0x05, 0x00, 0x80, 0x00, 0x90, 0x00, 0x80, 0x00, 0x05, 0x00, 0x80, 0x00, 0x49, 0x00, 0x34, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x04, 0x00, 0x80, 0x00, 0x16, 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x80, 0x00, 0x19, 0x00, 0x80, 0x00, 0x19, 0x00, 0x80, 0x00, 0x18, 0x00, 0x80, 0x00, + 0x95, 0x00, 0x80, 0x00, 0x1D, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x54, 0x00, 0x01, 0x08, 0x2D, 0x00, 0x02, 0x08, + 0x00, 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x48, 0x48, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x35, 0x08, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x04, 0x00, 0x00 +}; + +#endif \ No newline at end of file From 1aba87ef76b77bf918f6d3a1a322e43689fa6e7f Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Mon, 12 Nov 2018 01:56:33 +0000 Subject: [PATCH 203/489] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b874c6d66..b72ebf098 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ In no particular order, we credit the following for their invaluable contributio * __ChaN__ for the [FatFs](http://elm-chan.org/fsw/ff/00index_e.html) module. * __Marcus Geelnard__ for the [bcl-1.2.0](https://sourceforge.net/projects/bcl/files/bcl/bcl-1.2.0) library. * __naehrwert__ and __st4rk__ for the original [hekate](https://github.com/nwert/hekate) project and its hwinit code base. -* __CTCaer__ for the continued [hekate](https://github.com/CTCaer/hekate) project's fork. +* __CTCaer__ for the continued [hekate](https://github.com/CTCaer/hekate) project's fork and the [minerva_tc](https://github.com/CTCaer/minerva_tc) project. * __Riley__ for suggesting "Atmosphere" as a Horizon OS reimplementation+customization project name. * __hedgeberg__ for research and hardware testing. * __lioncash__ for code cleanup and general improvements. From 36530a5501ed036d80dec118ad6591f48862d0e4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 11 Nov 2018 19:52:19 -0800 Subject: [PATCH 204/489] creport: Improve code region list (as N did in 6.1.0) --- .../creport/source/creport_code_info.cpp | 32 ++++++++++++++++--- .../creport/source/creport_code_info.hpp | 6 ++-- .../creport/source/creport_crash_report.cpp | 9 ++++-- .../creport/source/creport_thread_info.hpp | 16 +++++++--- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index 3bb6e1bed..95e6af722 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -32,15 +32,37 @@ void CodeList::SaveToFile(FILE *f_report) { } } -void CodeList::ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr) { +void CodeList::ReadCodeRegionsFromThreadInfo(Handle debug_handle, const ThreadInfo *thread) { u64 code_base; - /* Guess that either PC or LR will point to a code region. This could be false. */ - if (!TryFindCodeRegion(debug_handle, pc, &code_base) && !TryFindCodeRegion(debug_handle, lr, &code_base)) { - return; + /* Try to add the thread's PC. */ + if (TryFindCodeRegion(debug_handle, thread->GetPC(), &code_base)) { + AddCodeRegion(debug_handle, code_base); } - u64 cur_ptr = code_base; + /* Try to add the thread's LR. */ + if (TryFindCodeRegion(debug_handle, thread->GetLR(), &code_base)) { + AddCodeRegion(debug_handle, code_base); + } + + /* Try to add all the addresses in the thread's stacktrace. */ + for (u32 i = 0; i < thread->GetStackTraceSize(); i++) { + if (TryFindCodeRegion(debug_handle, thread->GetStackTrace(i), &code_base)) { + AddCodeRegion(debug_handle, code_base); + } + } +} + +void CodeList::AddCodeRegion(u64 debug_handle, u64 code_address) { + /* Check whether we already have this code region. */ + for (size_t i = 0; i < this->code_count; i++) { + if (this->code_infos[i].start_address <= code_address && code_address < this->code_infos[i].end_address) { + return; + } + } + + /* Add all contiguous code regions. */ + u64 cur_ptr = code_address; while (this->code_count < max_code_count) { MemoryInfo mi; u32 pi; diff --git a/stratosphere/creport/source/creport_code_info.hpp b/stratosphere/creport/source/creport_code_info.hpp index ff1c1fb1c..23f8922e4 100644 --- a/stratosphere/creport/source/creport_code_info.hpp +++ b/stratosphere/creport/source/creport_code_info.hpp @@ -19,6 +19,7 @@ #include <cstdio> #include "creport_debug_types.hpp" +#include "creport_thread_info.hpp" struct CodeInfo { char name[0x20]; @@ -29,18 +30,19 @@ struct CodeInfo { class CodeList { private: - static const size_t max_code_count = 0x10; + static const size_t max_code_count = 0x60; u32 code_count = 0; CodeInfo code_infos[max_code_count]; /* For pretty-printing. */ char address_str_buf[0x280]; public: - void ReadCodeRegionsFromProcess(Handle debug_handle, u64 pc, u64 lr); + void ReadCodeRegionsFromThreadInfo(Handle debug_handle, const ThreadInfo *thread); const char *GetFormattedAddressString(u64 address); void SaveToFile(FILE *f_report); private: bool TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address); + void AddCodeRegion(u64 debug_handle, u64 code_address); void GetCodeInfoName(u64 debug_handle, u64 rx_address, u64 ro_address, char *name); void GetCodeInfoBuildId(u64 debug_handle, u64 ro_address, u8 *build_id); }; diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index cd9d1f9bb..6bcab5443 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -27,7 +27,7 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { this->has_extra_info = has_extra_info; if (OpenProcess(pid)) { ProcessExceptions(); - this->code_list.ReadCodeRegionsFromProcess(this->debug_handle, this->crashed_thread_info.GetPC(), this->crashed_thread_info.GetLR()); + this->code_list.ReadCodeRegionsFromThreadInfo(this->debug_handle, &this->crashed_thread_info); this->thread_list.ReadThreadsFromProcess(this->debug_handle, Is64Bit()); this->crashed_thread_info.SetCodeList(&this->code_list); this->thread_list.SetCodeList(&this->code_list); @@ -36,6 +36,11 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { ProcessDyingMessage(); } + /* Real creport only does this if application, but there's no reason not to do it all the time. */ + for (u32 i = 0; i < this->thread_list.GetThreadCount(); i++) { + this->code_list.ReadCodeRegionsFromThreadInfo(this->debug_handle, this->thread_list.GetThreadInfo(i)); + } + /* Real creport builds the report here. We do it later. */ Close(); @@ -258,7 +263,7 @@ void CrashReport::SaveReport() { void CrashReport::SaveToFile(FILE *f_report) { char buf[0x10] = {0}; - fprintf(f_report, "Atmosphère Crash Report (v1.1):\n"); + fprintf(f_report, "Atmosphère Crash Report (v1.2):\n"); fprintf(f_report, "Result: 0x%X (2%03d-%04d)\n\n", this->result, R_MODULE(this->result), R_DESCRIPTION(this->result)); /* Process Info. */ diff --git a/stratosphere/creport/source/creport_thread_info.hpp b/stratosphere/creport/source/creport_thread_info.hpp index 0b3d3f07f..e3f2ed606 100644 --- a/stratosphere/creport/source/creport_thread_info.hpp +++ b/stratosphere/creport/source/creport_thread_info.hpp @@ -19,7 +19,8 @@ #include <cstdio> #include "creport_debug_types.hpp" -#include "creport_code_info.hpp" + +class CodeList; class ThreadInfo { private: @@ -31,9 +32,11 @@ class ThreadInfo { u32 stack_trace_size = 0; CodeList *code_list; public: - u64 GetPC() { return context.pc.x; } - u64 GetLR() { return context.lr; } - u64 GetId() { return thread_id; } + u64 GetPC() const { return context.pc.x; } + u64 GetLR() const { return context.lr; } + u64 GetId() const { return thread_id; } + u32 GetStackTraceSize() const { return stack_trace_size; } + u64 GetStackTrace(u32 i) const { return stack_trace[i]; } bool ReadFromProcess(Handle debug_handle, u64 thread_id, bool is_64_bit); void SaveToFile(FILE *f_report); @@ -48,7 +51,10 @@ class ThreadList { static const size_t max_thread_count = 0x60; u32 thread_count = 0; ThreadInfo thread_infos[max_thread_count]; - public: + public: + u32 GetThreadCount() const { return thread_count; } + const ThreadInfo *GetThreadInfo(u32 i) const { return &thread_infos[i]; } + void SaveToFile(FILE *f_report); void DumpBinary(FILE *f_bin, u64 crashed_id); void ReadThreadsFromProcess(Handle debug_handle, bool is_64_bit); From 7d729e183699cd1c3b1ffd8f08850622d31b395a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 11 Nov 2018 20:00:04 -0800 Subject: [PATCH 205/489] creport: Add another code region locating improvement. --- .../creport/source/creport_code_info.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/stratosphere/creport/source/creport_code_info.cpp b/stratosphere/creport/source/creport_code_info.cpp index 95e6af722..5d8ef4285 100644 --- a/stratosphere/creport/source/creport_code_info.cpp +++ b/stratosphere/creport/source/creport_code_info.cpp @@ -102,7 +102,25 @@ void CodeList::AddCodeRegion(u64 debug_handle, u64 code_address) { bool CodeList::TryFindCodeRegion(Handle debug_handle, u64 guess, u64 *address) { MemoryInfo mi; u32 pi; - if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess)) || mi.perm != Perm_Rx) { + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess))) { + return false; + } + + if (mi.perm == Perm_Rw) { + guess = mi.addr - 4; + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess))) { + return false; + } + } + + if (mi.perm == Perm_R) { + guess = mi.addr - 4; + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess))) { + return false; + } + } + + if (mi.perm != Perm_Rx) { return false; } From 31c1338dba31e6aef4e20a40c7332c45a1a0aedb Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 11 Nov 2018 20:04:18 -0800 Subject: [PATCH 206/489] Bump version number to 0.7.5 --- common/include/atmosphere/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 151d103f8..3b3834f34 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 7 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 4 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 5 #endif \ No newline at end of file From 164fb96da01429a7676e5abd260debf19ef200bf Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 11 Nov 2018 20:14:20 -0800 Subject: [PATCH 207/489] Update changelog.md for 0.7.5 --- docs/changelog.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index 3d38c0340..7e3004468 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,12 @@ # Changelog +## 0.7.5 ++ DRAM training was added to fusee-secondary, courtesy @hexkyz. + + This greatly improves the speed of memory accesses during boot, resulting in a boot time that is ~200-400% faster. ++ creport has had its code region detection improved. + + Instead of only checking one of the crashing thread's PC/LR for code region presence, creport now checks both + every address in the stacktrace. This is also now done for every thread. + + This matches the improvement Nintendo added to official creport in 6.1.0. + + The code region detection heuristic was further improved by checking whether an address points to .rodata or .rwdata, instead of just .text. + + This means that a crash appears in a loaded NRO (or otherwise discontiguous) code region, creport will be able to detect all active code regions, and not just that one. ## 0.7.4 + [libstratosphere](https://github.com/Atmosphere-NX/libstratosphere) has been completely refactored/rewritten, and split into its own, separate submodule. + While this is mostly "under the hood" for end-users, the refactor is faster (improving both boot-time and runtime performance), more accurate (many of the internal IPC structures are now bug-for-bug compatible with Nintendo's implementations), and significantly more stable (it fixes a large number of bugs present in the old library). From 9f6ff2ed6ee4a023317bec1b8614621cdc34731c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 12 Nov 2018 22:26:13 -0800 Subject: [PATCH 208/489] Fatal: Implement basic background drawing. --- stratosphere/fatal/source/fatal_main.cpp | 4 +- .../fatal/source/fatal_task_screen.cpp | 151 +++++++++++++++++- .../fatal/source/fatal_task_screen.hpp | 7 + stratosphere/fatal/source/fatal_types.hpp | 1 + 4 files changed, 159 insertions(+), 4 deletions(-) diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 130255c1b..58a270b49 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -39,8 +39,8 @@ extern "C" { char nx_inner_heap[INNER_HEAP_SIZE]; u32 __nx_nv_transfermem_size = 0x40000; - ViServiceType __nx_gfx_vi_service_type = ViServiceType_Manager; - + ViLayerFlags __nx_vi_stray_layer_flags = (ViLayerFlags)0; + void __libnx_initheap(void); void __appInit(void); void __appExit(void); diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 5dcf40b04..7351e6022 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -18,11 +18,158 @@ #include "fatal_task_screen.hpp" #include "fatal_config.hpp" +Result ShowFatalTask::SetupDisplayInternal() { + Result rc; + ViDisplay display; + /* Try to open the display. */ + if (R_FAILED((rc = viOpenDisplay("Internal", &display)))) { + if (rc == 0xE72) { + return 0; + } else { + return rc; + } + } + /* Guarantee we close the display. */ + ON_SCOPE_EXIT { viCloseDisplay(&display); }; + + /* Turn on the screen. */ + if (R_FAILED((rc = viSetDisplayPowerState(&display, ViPowerState_On)))) { + return rc; + } + + /* Set alpha to 1.0f. */ + if (R_FAILED((rc = viSetDisplayAlpha(&display, 1.0f)))) { + return rc; + } + + return rc; +} + +Result ShowFatalTask::SetupDisplayExternal() { + Result rc; + ViDisplay display; + /* Try to open the display. */ + if (R_FAILED((rc = viOpenDisplay("External", &display)))) { + if (rc == 0xE72) { + return 0; + } else { + return rc; + } + } + /* Guarantee we close the display. */ + ON_SCOPE_EXIT { viCloseDisplay(&display); }; + + /* Set alpha to 1.0f. */ + if (R_FAILED((rc = viSetDisplayAlpha(&display, 1.0f)))) { + return rc; + } + + return rc; +} + +Result ShowFatalTask::PrepareScreenForDrawing() { + Result rc = 0; + + /* Connect to vi. */ + if (R_FAILED((rc = viInitialize(ViServiceType_Manager)))) { + return rc; + } + + /* Close other content. */ + viSetContentVisibility(false); + + /* Setup the two displays. */ + if (R_FAILED((rc = SetupDisplayInternal())) || R_FAILED((rc = SetupDisplayExternal()))) { + return rc; + } + + /* Open the default display. */ + if (R_FAILED((rc = viOpenDefaultDisplay(&this->display)))) { + return rc; + } + + /* Reset the display magnification to its default value. */ + u32 display_width, display_height; + if (R_FAILED((rc = viGetDisplayLogicalResolution(&this->display, &display_width, &display_height)))) { + return rc; + } + if (R_FAILED((rc = viSetDisplayMagnification(&this->display, 0, 0, display_width, display_height)))) { + return rc; + } + + /* Create layer to draw to. */ + if (R_FAILED((rc = viCreateLayer(&this->display, &this->layer)))) { + return rc; + } + + /* Setup the layer. */ + { + /* Display a layer of 1280 x 720 at 1.5x magnification */ + /* NOTE: N uses 2 (770x400) RGBA4444 buffers (tiled buffer + linear). */ + /* We use a single 1280x720 tiled RGB565 buffer. */ + constexpr u32 raw_width = 1280; + constexpr u32 raw_height = 720; + constexpr u32 layer_width = ((raw_width) * 3) / 2; + constexpr u32 layer_height = ((raw_height) * 3) / 2; + + const float layer_x = static_cast<float>((display_width - layer_width) / 2); + const float layer_y = static_cast<float>((display_height - layer_height) / 2); + u64 layer_z; + + if (R_FAILED((rc = viSetLayerSize(&this->layer, layer_width, layer_height)))) { + return rc; + } + + /* Set the layer's Z at display maximum, to be above everything else .*/ + /* NOTE: Fatal hardcodes 100 here. */ + if (R_SUCCEEDED((rc = viGetDisplayMaximumZ(&this->display, &layer_z)))) { + if (R_FAILED((rc = viSetLayerZ(&this->layer, layer_z)))) { + return rc; + } + } + + /* Center the layer in the screen. */ + if (R_FAILED((rc = viSetLayerPosition(&this->layer, layer_x, layer_y)))) { + return rc; + } + + /* Create framebuffer. */ + if (R_FAILED(rc = nwindowCreateFromLayer(&this->win, &this->layer))) { + return rc; + } + if (R_FAILED(rc = framebufferCreate(&this->fb, &this->win, raw_width, raw_height, PIXEL_FORMAT_RGB_565, 1))) { + return rc; + } + } + + + return rc; +} + Result ShowFatalTask::ShowFatal() { Result rc = 0; - /* TODO: Get graphics to work, draw fatal screen. */ - + if (R_FAILED((rc = PrepareScreenForDrawing()))) { + *(volatile u32 *)(0xCAFEBABE) = rc; + return rc; + } + + /* Dequeue a buffer. */ + u16 *tiled_buf = reinterpret_cast<u16 *>(framebufferBegin(&this->fb, NULL)); + if (tiled_buf == nullptr) { + return FatalResult_NullGfxBuffer; + } + + /* Draw a background. */ + for (size_t i = 0; i < this->fb.fb_size / sizeof(*tiled_buf); i++) { + tiled_buf[i] = 0x39C9; + } + + /* TODO: Actually draw meaningful shit here. */ + + /* Enqueue the buffer. */ + framebufferEnd(&fb); + return rc; } diff --git a/stratosphere/fatal/source/fatal_task_screen.hpp b/stratosphere/fatal/source/fatal_task_screen.hpp index a456a9860..bfaed2cea 100644 --- a/stratosphere/fatal/source/fatal_task_screen.hpp +++ b/stratosphere/fatal/source/fatal_task_screen.hpp @@ -22,7 +22,14 @@ class ShowFatalTask : public IFatalTask { private: Event *battery_event; + ViDisplay display; + ViLayer layer; + NWindow win; + Framebuffer fb; private: + Result SetupDisplayInternal(); + Result SetupDisplayExternal(); + Result PrepareScreenForDrawing(); Result ShowFatal(); public: ShowFatalTask(FatalContext *ctx, u64 title_id, Event *evt) : IFatalTask(ctx, title_id), battery_event(evt) { } diff --git a/stratosphere/fatal/source/fatal_types.hpp b/stratosphere/fatal/source/fatal_types.hpp index 46fafeec4..83abe9d0e 100644 --- a/stratosphere/fatal/source/fatal_types.hpp +++ b/stratosphere/fatal/source/fatal_types.hpp @@ -19,6 +19,7 @@ #include <stratosphere.hpp> enum FatalResult : Result { + FatalResult_NullGfxBuffer = 0x4A3, FatalResult_AlreadyThrown = 0x6A3, FatalResult_TooManyEvents = 0x8A3, FatalResult_InRepairWithoutVolHeld = 0xAA3, From 8550f722ca6cec1d1ea040319b0cd35aab96680b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 06:03:30 -0800 Subject: [PATCH 209/489] fatal: Implement basic text rendering. --- stratosphere/fatal/Makefile | 4 +- stratosphere/fatal/source/ams_logo.hpp | 1304 +++++++++++++++++ stratosphere/fatal/source/fatal_font.cpp | 149 ++ stratosphere/fatal/source/fatal_font.hpp | 35 + stratosphere/fatal/source/fatal_main.cpp | 14 +- stratosphere/fatal/source/fatal_task.cpp | 6 +- .../fatal/source/fatal_task_screen.cpp | 39 +- 7 files changed, 1541 insertions(+), 10 deletions(-) create mode 100644 stratosphere/fatal/source/ams_logo.hpp create mode 100644 stratosphere/fatal/source/fatal_font.cpp create mode 100644 stratosphere/fatal/source/fatal_font.hpp diff --git a/stratosphere/fatal/Makefile b/stratosphere/fatal/Makefile index c042e968d..4fba60450 100644 --- a/stratosphere/fatal/Makefile +++ b/stratosphere/fatal/Makefile @@ -34,14 +34,14 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE CFLAGS := -g -Wall -O2 -ffunction-sections \ $(ARCH) $(DEFINES) -CFLAGS += $(INCLUDE) -D__SWITCH__ +CFLAGS += $(INCLUDE) -D__SWITCH__ `freetype-config --cflags` CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := -lstratosphere -lnx +LIBS := `freetype-config --libs` -lstratosphere -lnx #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/stratosphere/fatal/source/ams_logo.hpp b/stratosphere/fatal/source/ams_logo.hpp new file mode 100644 index 000000000..6d64bc5c3 --- /dev/null +++ b/stratosphere/fatal/source/ams_logo.hpp @@ -0,0 +1,1304 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#define AMS_LOGO_WIDTH 0xA0 +#define AMS_LOGO_HEIGHT 0x80 + +static constexpr u16 AMS_LOGO_BIN[] = { + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0x6B4F, 0x9494, 0xB597, 0xC619, 0xD69B, + 0xDEDB, 0xCE7A, 0xBDB8, 0x9CD4, 0x6B4F, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x6B6F, 0xBDD8, 0xFFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0xB577, 0x5AED, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x630E, 0xD67A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC639, 0x5ACD, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x420A, 0xAD76, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x9CD4, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x528C, 0xDEDC, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE5A, 0x422B, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x5ACD, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFC, 0x4A6C, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x528C, 0xEF7E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE6FC, 0x422B, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x420A, 0xDEDB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE5A, 0x39EA, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0xBDD8, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD36, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x8C73, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0x7BF1, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x6B4F, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFBF, 0x5ACD, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A6C, 0xEF7E, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xE71C, 0x422B, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0xD69B, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xC619, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0xAD56, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0x94B4, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x8412, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7390, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x5AED, 0xFFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x528C, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x422B, 0xE71D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEBB, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0xC619, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB577, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x9CD4, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8432, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x7390, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x630E, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x52AC, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x4A4B, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x420A, 0xDEDC, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE5A, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0xB597, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x9CF5, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x8C32, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BD1, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x630E, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BE, 0x52AD, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x4A4B, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFC, 0x420A, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39EA, 0xCE7A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDD8, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0xA515, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8C73, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x7BD1, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x6B4F, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x5ACD, + 0xFFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF7E, + 0x4A6C, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x420A, 0xDEFC, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xD69B, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0xBDF8, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xAD36, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x9493, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0x7BF1, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x6B4F, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFBF, 0x5ACD, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A6C, 0xF77E, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xE71D, 0x422B, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0xD6BB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC619, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0xAD56, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x9CB4, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x8412, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7390, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x5AED, 0xFFBF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x52AC, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x422B, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDC, 0x420A, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0xC639, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB597, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x9CD4, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8C32, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x7390, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x630E, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x52AC, 0xF79E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xEF5D, 0x4A4B, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x420A, 0xDEDC, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE7A, 0x39EA, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0xBDD8, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA515, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x8C52, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7BD1, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x630E, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFBF, 0x5ACD, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x4A4B, 0xEF5D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEFC, 0x420A, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, + 0xCE7A, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDD8, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0xA515, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0x9473, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x7BD1, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0x6B4F, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x5ACD, 0xFFBF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xF77E, 0x4A6C, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x422B, 0xE71C, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xD6BB, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0xBDF8, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xAD56, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x9493, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8412, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x6B4F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFBF, 0x5AED, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A6C, 0xF77E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE71D, 0x422B, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0xD6BB, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC639, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0xAD56, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x9CD4, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x8432, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7390, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x630E, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, 0x52AC, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x422B, 0xE73D, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xDEDC, 0x420A, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0xB5FA, 0xD71E, 0xD71E, 0xDF3E, 0xDF3E, 0xE75E, 0xE77E, 0xE77F, 0xEF9F, 0xEF9F, 0xF7DF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xB597, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x6BD2, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, + 0x95BB, 0x9DFB, 0xAE3C, 0xB67C, 0xC6BD, 0xD6FE, 0xDF3E, 0xEF7F, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8412, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x52EE, 0x8D7B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, + 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x95DB, 0xA61C, 0xBE9D, 0xCEFD, 0xE75E, 0xF7BF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFDF, 0x5AEE, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x424B, 0x8539, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, + 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x9DDB, + 0xB65C, 0xCEFE, 0xEF9F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE73D, 0x422B, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39EA, 0x7CD7, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, + 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, + 0x8D9B, 0x8D9B, 0x8D9B, 0x95BB, 0xA61C, 0xC6BD, 0xDF5E, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC639, 0x39EA, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x6BF4, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, + 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D9B, 0x8D9B, + 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x8D9B, 0x95BB, 0xAE3C, 0xD71E, 0xF7DF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xA515, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x5B30, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D7B, 0x8D7B, + 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, + 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D9B, 0x8D9B, 0x8D9B, 0xA5FC, 0xCEDD, 0xEF9F, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7390, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A6D, + 0x853A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5B, 0x8D5B, + 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, + 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0xA5FC, 0xC6BD, + 0xEF9F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF79E, + 0x52AC, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x420B, 0x7CD8, + 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, + 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, + 0x8D5B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, + 0x8D7B, 0xA5DC, 0xCEDD, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xDEDC, 0x420A, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0x7456, 0x8D3A, + 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, + 0x8D3A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, + 0x8D5A, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, + 0x8D7B, 0x8D7B, 0x8D7B, 0x8D7B, 0xAE3C, 0xDF3E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xBDF8, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x6372, 0x851A, 0x851A, + 0x851A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, + 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, + 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, + 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D7B, 0x8D7B, 0x9DDB, 0xCEDD, 0xFFDF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0x8C73, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x52EF, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, + 0x853A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, + 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, + 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D5B, 0x8D7B, 0xB65C, 0xEF9F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFDF, 0x632E, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x424C, 0x84F9, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, + 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D5A, 0x8D5A, 0x8D5A, + 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0xAE1C, 0xDF3E, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xF77E, 0x4A6C, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x3A0A, 0x7C78, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x853A, 0x853A, 0x853A, + 0x853A, 0x853A, 0x853A, 0x853A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, + 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0x8D5A, 0xA5DB, 0xD71E, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xCE7A, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x6BD4, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x8D3A, 0x8D3A, 0x8D3A, + 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0xA5DB, + 0xE73E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xAD56, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x5B31, 0x84DA, 0x84DA, 0x84DA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, 0x8D3A, + 0x8D3A, 0xA5DC, 0xE75E, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x8412, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A8D, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, 0x853A, + 0x8D3A, 0x8D3A, 0x8D3A, 0xB61C, 0xEF9F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xF7BF, 0x5ACD, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x422B, 0x7C78, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x853A, 0x853A, 0x8D3A, 0xB65C, 0xF7BF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xE71C, 0x422B, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0x6BF6, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x955B, 0xD6DE, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBDF8, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x6373, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x84BA, 0x84BA, + 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x851A, 0x851A, 0x851A, 0x851A, + 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0xA5BB, 0xEF7F, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0x94D4, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x52F0, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, + 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, + 0x84BA, 0x84BA, 0x84BA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x851A, 0x851A, 0x851A, 0x851A, 0x851A, 0xBE5D, 0xF7BF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xF7DF, 0x7390, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x424D, 0x7C79, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, + 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x957B, 0xDF1E, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, + 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xFFDF, 0xEF5D, 0x4A6C, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0x7417, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, + 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, + 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84FA, + 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0xB63C, 0xF7BF, 0xF7DF, + 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, + 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, + 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, + 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xD6BB, 0x420A, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39CA, 0x63B5, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, + 0x7CBA, 0x7CBA, 0x7CBA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x84FA, 0x955B, 0xE73E, + 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, + 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, + 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, + 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xF7DF, 0xB597, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x5B11, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, + 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, + 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, + 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84FA, + 0xC69D, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0x7C11, 0x39C9, 0x39C9, + 0x39C9, 0x424D, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, + 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, + 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, + 0x84BA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0xA5BB, 0xEF7F, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xEF7E, 0x528C, 0x39C9, + 0x39C9, 0x6B95, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, + 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, + 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x84BA, + 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, 0x84DA, + 0x84DA, 0x84DA, 0x953B, 0xDF1E, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xAD77, 0x39C9, + 0x422C, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, + 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, + 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, + 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, 0x84BA, + 0x84BA, 0x84BA, 0x84BA, 0x84DA, 0xBE7D, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xEF9E, 0x422B, + 0x52D0, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, + 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, + 0x7CBA, 0x7CBA, 0x84BA, 0x84BA, 0x84BA, 0xA5BC, 0xEF9F, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, + 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0xF7BF, 0x73B0, + 0x5B33, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, + 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, + 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, + 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7CBA, 0x7CBA, 0x7CBA, + 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x7CBA, 0x9D5B, 0xE75F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0x94B4, + 0x6354, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, + 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x8D1A, 0xDF1E, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0x9CF5, + 0x5B33, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, + 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, + 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x84BA, 0xC69D, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0x94B4, + 0x52D0, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, + 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, + 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0x7C9A, 0xBE3C, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0x73D1, + 0x422C, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, + 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C9A, 0x7C9A, 0xADFC, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, + 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xEF9F, 0xE77E, 0x4A4B, + 0x39C9, 0x6375, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C39, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, + 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0x7C7A, 0xADBC, 0xE77F, 0xEF7F, 0xEF7F, + 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, + 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, + 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xEF7F, 0xAD97, 0x39C9, + 0x39C9, 0x422D, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x7C79, 0x9D5B, 0xE77E, 0xE77F, + 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, + 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, + 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xE77F, 0xDF3E, 0x4A8C, 0x39C9, + 0x39C9, 0x39C9, 0x5AF2, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, + 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C79, 0x7C79, 0x9D5B, 0xE75E, + 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, + 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, + 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0x8C73, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39CA, 0x6355, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x94FB, + 0xDF3E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, + 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, + 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xAD97, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x420B, 0x6B97, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, 0x7C59, + 0x8CFA, 0xDF3E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, + 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, + 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xE77E, 0xC67B, 0x420A, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x422D, 0x6BB8, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C39, 0x7C59, + 0x7C59, 0x8CFA, 0xDF3E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, + 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, + 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xDF1D, 0x52AD, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A90, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, + 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x951B, 0xDF5E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, + 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, + 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0x6B90, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x5AF3, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, 0x7439, + 0x7439, 0x7439, 0x7439, 0x9D3B, 0xDF5E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, + 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, + 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0xE75E, 0x94B4, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0x6355, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7439, 0x7439, 0x9D5B, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, + 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, + 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xB5B8, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x420B, 0x6B77, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, + 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0xA57B, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, + 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, + 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xDF5E, 0xCE9B, 0x422B, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A4E, 0x6B78, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, + 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, + 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0x7419, 0xB5FC, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, + 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, + 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xD71D, 0x5ACD, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x5291, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7419, 0x7419, 0x7419, 0xBE5C, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, + 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, + 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0x7C12, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0x5AF3, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, + 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x7C39, 0xCEBD, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, + 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, + 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0x9D16, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0x6336, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, + 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x73F9, 0x847A, 0xD6FE, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, + 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, + 0xDF3E, 0xDF3E, 0xDF3E, 0xDF3E, 0xB619, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x420C, 0x6358, 0x6B58, 0x6B58, 0x6B58, + 0x6B58, 0x6B58, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, + 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73F9, 0x73F9, 0x8CDA, 0xD71E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, + 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, 0xD73E, + 0xD73E, 0xD73E, 0xD73E, 0xCEBC, 0x4A6C, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A4F, 0x6B58, 0x6B58, 0x6B58, + 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, + 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, + 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0xA57B, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, + 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, + 0xD71E, 0xD71E, 0xD71D, 0x632F, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x52B2, 0x6358, 0x6358, + 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, + 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B98, 0x6B98, + 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BD9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0x73D9, 0xB61C, 0xD71E, 0xD71E, 0xD71E, 0xD71E, + 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, + 0xD71E, 0xD71E, 0x8453, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0x5AD4, 0x6338, + 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6B58, 0x6B58, + 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, + 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BD9, 0x73F9, 0xC69D, 0xD71E, 0xD71E, 0xD71E, + 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, + 0xD71E, 0xA557, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EB, 0x6317, + 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6358, 0x6358, + 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, + 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, + 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x847A, 0xD6FD, 0xD71E, 0xD71E, + 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, + 0xBE5B, 0x422B, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x422D, + 0x6318, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, + 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, + 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, + 0x6B58, 0x6B58, 0x6336, 0x5AF4, 0x52D3, 0x52B1, 0x4A70, 0x4A4E, 0x424E, 0x422D, 0x420C, 0x39EB, 0x39EA, 0x39EA, 0x39EA, 0x39EA, + 0x39EA, 0x39EB, 0x420B, 0x420C, 0x422C, 0x422D, 0x424D, 0x4A4E, 0x4A6F, 0x52B1, 0x52D2, 0x5AF4, 0x6315, 0x6356, 0x6B78, 0x6B98, + 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0x6BB9, 0xA55B, 0xD71E, 0xD71E, + 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xD71E, 0xCEBC, + 0x528C, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x4A70, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, + 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, + 0x6338, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6358, 0x6B58, 0x6337, 0x5AF4, 0x52B2, 0x4A6F, 0x422D, + 0x41EB, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EB, + 0x422D, 0x4A90, 0x52D2, 0x6315, 0x6378, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, + 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6BB9, 0xBE3C, 0xD6FD, + 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xD6FD, 0xCEFD, 0x6B70, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39CA, 0x52B3, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, + 0x6318, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, + 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x5AD4, 0x5291, 0x422D, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x3A0B, 0x424E, 0x52B1, 0x6315, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B98, 0x6B98, 0x6B98, + 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x6B99, 0x7C19, 0xCEDD, + 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0x8C94, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39CA, 0x5AD6, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, + 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, 0x6338, + 0x6338, 0x6338, 0x6317, 0x5AD4, 0x4A70, 0x420D, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0x424D, 0x52B1, 0x5B15, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x6B98, 0x8CBA, + 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xA598, 0x39EA, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x41EC, 0x62F7, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, + 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x5AF6, + 0x5291, 0x422D, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0x4A4E, 0x52D2, + 0x6337, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B98, + 0xADBC, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xBE5B, 0x424B, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x422E, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, + 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x6318, 0x5AD5, 0x4A70, 0x420C, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x420C, 0x5291, 0x6316, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x73B9, 0xC6BD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEFD, 0xCEDD, 0x5B0E, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x4A51, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, + 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x5AD6, 0x4A50, 0x39EB, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x3A0B, 0x5290, 0x6316, 0x6B58, 0x6B58, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, 0x6B78, + 0x6B78, 0x8CBA, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0x73D1, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0x5294, 0x62D8, 0x62D8, 0x62D8, 0x62D8, 0x62D8, 0x62D8, 0x62D8, 0x62F8, 0x62F8, 0x62F8, + 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x62F8, 0x5AD7, 0x5292, 0x420D, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0x422D, 0x5AD3, 0x6358, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, 0x6B58, + 0x6B58, 0x6B78, 0xB61C, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0xCEDD, 0x9516, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EA, 0x5AB5, 0x5AD8, 0x5AD8, 0x5AD8, 0x5AD8, 0x5AD8, 0x5AD8, 0x62D8, 0x62D8, 0x62D8, + 0x62D8, 0x62D8, 0x62D8, 0x62D8, 0x5AB5, 0x4A2F, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EB, 0x4A90, 0x6316, 0x6B58, 0x6B58, 0x6B58, 0x6B58, + 0x6B58, 0x6B58, 0x73F9, 0xC6BD, 0xC6DD, 0xC6DD, 0xC6DD, 0xC6DD, 0xC6DD, 0xA598, 0x39EA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39EB, 0x5274, 0x5AD8, 0x5AD8, 0x5AD8, 0x5AD8, 0x5AD8, 0x5AD8, 0x5AD8, 0x5AD8, + 0x5AD8, 0x5AD8, 0x5294, 0x420E, 0x39CA, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0x422E, 0x5AF5, 0x6358, 0x6358, + 0x6358, 0x6358, 0x6358, 0x951B, 0xC6DD, 0xC6DD, 0xC6DD, 0xC6DD, 0x9D37, 0x420A, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0x4A2F, 0x5A95, 0x5AB8, 0x5AB8, 0x5AB8, 0x5AB8, 0x5AB8, 0x5AB7, + 0x5273, 0x420C, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x422D, 0x5AD3, + 0x6338, 0x6338, 0x6338, 0x6B58, 0xB63C, 0xC6DD, 0xADD9, 0x6350, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39CA, 0x41EC, 0x420E, 0x4A30, 0x4A30, 0x422E, 0x39EB, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x420C, 0x4A70, 0x5291, 0x73B5, 0x6BB3, 0x52AD, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, + 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9, 0x39C9 +}; + +static_assert(sizeof(AMS_LOGO_BIN) == AMS_LOGO_WIDTH * AMS_LOGO_HEIGHT * sizeof(*AMS_LOGO_BIN), "Logo definition!"); \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_font.cpp b/stratosphere/fatal/source/fatal_font.cpp new file mode 100644 index 000000000..b81c65126 --- /dev/null +++ b/stratosphere/fatal/source/fatal_font.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include <switch.h> +#include "fatal_types.hpp" + +#include <cstring> +#include <cstdlib> +#include <cstdio> + +#include <ft2build.h> +#include FT_FREETYPE_H + +#include "fatal_config.hpp" +#include "fatal_font.hpp" + +static u16 *g_fb = nullptr; +static u32 (*g_unswizzle_func)(u32, u32) = nullptr; +static u16 g_font_color = 0xFFFF; + +static PlFontData g_font; +static PlFontData g_fonts[PlSharedFontType_Total]; +static FT_Library g_library; +static FT_Face g_face; +static FT_Error g_ft_err = 0; + +static u16 Blend(u16 color, u16 bg, u8 alpha) { + const u32 c_r = RGB565_GET_R8(color); + const u32 c_g = RGB565_GET_G8(color); + const u32 c_b = RGB565_GET_B8(color); + const u32 b_r = RGB565_GET_R8(bg); + const u32 b_g = RGB565_GET_G8(bg); + const u32 b_b = RGB565_GET_B8(bg); + + const u32 r = ((alpha * c_r) + ((0xFF - alpha) * b_r)) / 0xFF; + const u32 g = ((alpha * c_g) + ((0xFF - alpha) * b_g)) / 0xFF; + const u32 b = ((alpha * c_b) + ((0xFF - alpha) * b_b)) / 0xFF; + + return RGB888_TO_RGB565(r, g, b); +} + +static void DrawGlyph(FT_Bitmap *bitmap, u32 x, u32 y) { + u8* imageptr = bitmap->buffer; + + if (bitmap->pixel_mode!=FT_PIXEL_MODE_GRAY) return; + + for (u32 tmpy = 0; tmpy < bitmap->rows; tmpy++) { + for (u32 tmpx = 0; tmpx < bitmap->width; tmpx++) { + /* Implement very simple blending, as the bitmap value is an alpha value. */ + u16 *ptr = &g_fb[g_unswizzle_func(x + tmpx, y + tmpy)]; + *ptr = Blend(g_font_color, *ptr, imageptr[tmpx]); + } + imageptr += bitmap->pitch; + } +} + +void FontManager::DrawString(u32 x, u32 y, const char *str) { + FT_UInt glyph_index; + FT_GlyphSlot slot = g_face->glyph; + + const size_t len = strlen(str); + + u32 cur_x = x, cur_y = y; + + for (u32 i = 0; i < len; ) { + u32 cur_char; + ssize_t unit_count = decode_utf8(&cur_char, reinterpret_cast<const u8 *>(&str[i])); + if (unit_count <= 0) break; + i += unit_count; + + if (cur_char == '\n') { + cur_x = x; + cur_y += g_face->size->metrics.height >> 6; + continue; + } + + glyph_index = FT_Get_Char_Index(g_face, cur_char); + + g_ft_err = FT_Load_Glyph(g_face, glyph_index, FT_LOAD_DEFAULT); + + if (g_ft_err == 0) { + g_ft_err = FT_Render_Glyph(g_face->glyph, FT_RENDER_MODE_NORMAL); + } + + if (g_ft_err) { + return; + } + + DrawGlyph(&slot->bitmap, cur_x + slot->bitmap_left, cur_y - slot->bitmap_top); + + cur_x += slot->advance.x >> 6; + cur_y += slot->advance.y >> 6; + } +} + +void FontManager::DrawFormat(u32 x, u32 y, const char *format, ...) { + va_list va_arg; + va_start(va_arg, format); + + char char_buf[0x400]; + vsnprintf(char_buf, sizeof(char_buf), format, va_arg); + + DrawString(x, y, char_buf); +} + +void FontManager::SetFontColor(u16 color) { + g_font_color = color; +} + +void FontManager::ConfigureFontFramebuffer(u16 *fb, u32 (*unswizzle_func)(u32, u32)) { + g_fb = fb; + g_unswizzle_func = unswizzle_func; +} + +Result FontManager::InitializeSharedFont() { + Result rc; + size_t total_fonts = 0; + + if (R_FAILED((rc = plGetSharedFont(GetFatalConfig()->language_code, g_fonts, PlSharedFontType_Total, &total_fonts)))) { + return rc; + } + + if (R_FAILED((rc = plGetSharedFontByType(&g_font, PlSharedFontType_Standard)))) { + return rc; + } + + g_ft_err = FT_Init_FreeType(&g_library); + if (g_ft_err) return g_ft_err; + + g_ft_err = FT_New_Memory_Face(g_library, reinterpret_cast<const FT_Byte *>(g_font.address), g_font.size, 0, &g_face); + if (g_ft_err) return g_ft_err; + + g_ft_err = FT_Set_Char_Size(g_face, 0, 8*64, 300, 300); + return g_ft_err; +} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_font.hpp b/stratosphere/fatal/source/fatal_font.hpp new file mode 100644 index 000000000..ab553a28a --- /dev/null +++ b/stratosphere/fatal/source/fatal_font.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <cstdarg> +#include <switch.h> +#include <stratosphere.hpp> + +#define RGB888_TO_RGB565(r, g, b) ((((r >> 3) << 11) & 0xF800) | (((g >> 2) << 5) & 0x7E0) | ((b >> 3) & 0x1F)) +#define RGB565_GET_R8(c) (((c >> 11) & 0x1F) << 3) +#define RGB565_GET_G8(c) (((c >> 5) & 0x3F) << 2) +#define RGB565_GET_B8(c) (((c >> 0) & 0x1F) << 3) + +class FontManager { + public: + static Result InitializeSharedFont(); + static void ConfigureFontFramebuffer(u16 *fb, u32 (*unswizzle_func)(u32, u32)); + + static void SetFontColor(u16 color); + static void DrawString(u32 x, u32 y, const char *str); + static void DrawFormat(u32 x, u32 y, const char *format, ...); +}; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 58a270b49..292258a73 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -28,13 +28,14 @@ #include "fatal_user.hpp" #include "fatal_config.hpp" #include "fatal_repair.hpp" +#include "fatal_font.hpp" extern "C" { extern u32 __start__; u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x3C0000 + #define INNER_HEAP_SIZE 0x280000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -112,11 +113,17 @@ void __appInit(void) { std::abort(); } + rc = plInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + /* fatal cannot throw fatal, so don't do: CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); */ } void __appExit(void) { /* Cleanup services. */ + plExit(); spsmExit(); psmExit(); lblExit(); @@ -134,7 +141,10 @@ int main(int argc, char **argv) /* Load settings from set:sys. */ InitializeFatalConfig(); - /* TODO: Load shared font. */ + /* Load shared font. */ + if (R_FAILED(FontManager::InitializeSharedFont())) { + std::abort(); + } /* Check whether we should throw fatal due to repair process. */ CheckRepairStatus(); diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 39a1c82d1..62b39cdbb 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -42,21 +42,21 @@ static void RunTaskThreadFunc(void *arg) { svcExitThread(); } -static void RunTask(IFatalTask *task) { +static void RunTask(IFatalTask *task, u32 stack_size = 0x4000) { if (g_num_threads >= MaxTasks) { std::abort(); } HosThread *cur_thread = &g_task_threads[g_num_threads++]; - cur_thread->Initialize(&RunTaskThreadFunc, task, 0x4000, 15); + cur_thread->Initialize(&RunTaskThreadFunc, task, stack_size, 15); cur_thread->Start(); } void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) { RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event)); RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event)); - RunTask(new ShowFatalTask(ctx, title_id, battery_event)); + RunTask(new ShowFatalTask(ctx, title_id, battery_event), 0x10000); RunTask(new StopSoundTask(ctx, title_id)); RunTask(new BacklightControlTask(ctx, title_id)); RunTask(new AdjustClockTask(ctx, title_id)); diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 7351e6022..b651c7ef9 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -17,6 +17,27 @@ #include <switch.h> #include "fatal_task_screen.hpp" #include "fatal_config.hpp" +#include "fatal_font.hpp" +#include "ams_logo.hpp" + +static constexpr u32 FatalScreenWidth = 1280; +static constexpr u32 FatalScreenHeight = 720; +static constexpr u32 FatalScreenBpp = 2; + +static constexpr u32 FatalScreenWidthAlignedBytes = (FatalScreenWidth * FatalScreenBpp + 63) & ~63; +static constexpr u32 FatalScreenWidthAligned = FatalScreenWidthAlignedBytes / FatalScreenBpp; + +u32 GetPixelOffset(uint32_t x, uint32_t y) +{ + u32 tmp_pos; + + tmp_pos = ((y & 127) / 16) + (x/32*8) + ((y/16/8)*(((FatalScreenWidthAligned/2)/16*8))); + tmp_pos *= 16*16 * 4; + + tmp_pos += ((y%16)/8)*512 + ((x%32)/16)*256 + ((y%8)/2)*64 + ((x%16)/8)*32 + (y%2)*16 + (x%8)*2;//This line is a modified version of code from the Tegra X1 datasheet. + + return tmp_pos / 2; +} Result ShowFatalTask::SetupDisplayInternal() { Result rc; @@ -107,8 +128,8 @@ Result ShowFatalTask::PrepareScreenForDrawing() { /* Display a layer of 1280 x 720 at 1.5x magnification */ /* NOTE: N uses 2 (770x400) RGBA4444 buffers (tiled buffer + linear). */ /* We use a single 1280x720 tiled RGB565 buffer. */ - constexpr u32 raw_width = 1280; - constexpr u32 raw_height = 720; + constexpr u32 raw_width = FatalScreenWidth; + constexpr u32 raw_height = FatalScreenHeight; constexpr u32 layer_width = ((raw_width) * 3) / 2; constexpr u32 layer_height = ((raw_height) * 3) / 2; @@ -160,13 +181,25 @@ Result ShowFatalTask::ShowFatal() { return FatalResult_NullGfxBuffer; } + /* Let the font manager know about our framebuffer. */ + FontManager::ConfigureFontFramebuffer(tiled_buf, GetPixelOffset); + FontManager::SetFontColor(0xFFFF); + /* Draw a background. */ for (size_t i = 0; i < this->fb.fb_size / sizeof(*tiled_buf); i++) { tiled_buf[i] = 0x39C9; } - /* TODO: Actually draw meaningful shit here. */ + /* Draw the atmosphere logo in the bottom right corner. */ + for (size_t y = 0; y < AMS_LOGO_HEIGHT; y++) { + for (size_t x = 0; x < AMS_LOGO_WIDTH; x++) { + tiled_buf[GetPixelOffset(FatalScreenWidth - AMS_LOGO_WIDTH - 32 + x, FatalScreenHeight - AMS_LOGO_HEIGHT - 32 + y)] = AMS_LOGO_BIN[y * AMS_LOGO_WIDTH + x]; + } + } + /* TODO: Actually draw meaningful shit here. */ + FontManager::DrawFormat(32, 64, u8"A fatal error occurred: 2%03d-%04d\n", R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code)); + /* Enqueue the buffer. */ framebufferEnd(&fb); From 2838e418196885490b0ef659b70f75ce3e53038f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 12:42:35 -0800 Subject: [PATCH 210/489] Add defines for atmosphere git revision. --- exosphere/Makefile | 9 ++++++++- fusee/fusee-primary/Makefile | 9 ++++++++- fusee/fusee-secondary/Makefile | 9 ++++++++- stratosphere/boot/Makefile | 10 +++++++++- stratosphere/creport/Makefile | 9 ++++++++- stratosphere/fatal/Makefile | 9 ++++++++- stratosphere/fs_mitm/Makefile | 9 ++++++++- stratosphere/libstratosphere | 2 +- stratosphere/loader/Makefile | 9 ++++++++- stratosphere/pm/Makefile | 9 ++++++++- stratosphere/set_mitm/Makefile | 9 ++++++++- stratosphere/sm/Makefile | 9 ++++++++- thermosphere/Makefile | 8 ++++++++ 13 files changed, 98 insertions(+), 12 deletions(-) diff --git a/exosphere/Makefile b/exosphere/Makefile index efadefc58..11339bb05 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/devkitA64/base_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -26,7 +33,7 @@ INCLUDES := include ../common/include # options for code generation #--------------------------------------------------------------------------------- ARCH := -march=armv8-a -mtune=cortex-a57 -mgeneral-regs-only #<- important -DEFINES := -D__CCPLEX__ +DEFINES := -D__CCPLEX__ -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" CFLAGS := \ -g \ -O2 \ diff --git a/fusee/fusee-primary/Makefile b/fusee/fusee-primary/Makefile index 8dce2efff..cf79835f8 100644 --- a/fusee/fusee-primary/Makefile +++ b/fusee/fusee-primary/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITARM)/base_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -26,7 +33,7 @@ INCLUDES := include ../../common/include # options for code generation #--------------------------------------------------------------------------------- ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork -DEFINES := -D__BPMP__ -DFUSEE_STAGE1_SRC +DEFINES := -D__BPMP__ -DFUSEE_STAGE1_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" CFLAGS := \ -g \ diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 9055bbf59..c2c849f4d 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -12,6 +12,13 @@ AMS := $(TOPDIR)/../../ include $(DEVKITARM)/base_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -29,7 +36,7 @@ INCLUDES := include ../../common/include # options for code generation #--------------------------------------------------------------------------------- ARCH := -march=armv4t -mtune=arm7tdmi -marm -DEFINES := -D__BPMP__ -DFUSEE_STAGE2_SRC +DEFINES := -D__BPMP__ -DFUSEE_STAGE2_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" CFLAGS := \ -g \ diff --git a/stratosphere/boot/Makefile b/stratosphere/boot/Makefile index 57b69f6e0..7ea2668f3 100644 --- a/stratosphere/boot/Makefile +++ b/stratosphere/boot/Makefile @@ -9,6 +9,14 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -24,7 +32,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/creport/Makefile b/stratosphere/creport/Makefile index c042e968d..71c014dc5 100644 --- a/stratosphere/creport/Makefile +++ b/stratosphere/creport/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -24,7 +31,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/fatal/Makefile b/stratosphere/fatal/Makefile index 4fba60450..fbbe7ae9c 100644 --- a/stratosphere/fatal/Makefile +++ b/stratosphere/fatal/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -24,7 +31,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/fs_mitm/Makefile b/stratosphere/fs_mitm/Makefile index e8b1f047a..4ebc8f6d9 100644 --- a/stratosphere/fs_mitm/Makefile +++ b/stratosphere/fs_mitm/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -24,7 +31,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index bcd80ab44..6a6eedeac 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit bcd80ab445258c20d968aad1c083fd8cb0937bee +Subproject commit 6a6eedeacd69a4bddb1e43e31a642a1249a8eb88 diff --git a/stratosphere/loader/Makefile b/stratosphere/loader/Makefile index e8b1f047a..4ebc8f6d9 100644 --- a/stratosphere/loader/Makefile +++ b/stratosphere/loader/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -24,7 +31,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/pm/Makefile b/stratosphere/pm/Makefile index c3b31a855..766f33dd4 100644 --- a/stratosphere/pm/Makefile +++ b/stratosphere/pm/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -24,7 +31,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/set_mitm/Makefile b/stratosphere/set_mitm/Makefile index c042e968d..71c014dc5 100644 --- a/stratosphere/set_mitm/Makefile +++ b/stratosphere/set_mitm/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -24,7 +31,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/sm/Makefile b/stratosphere/sm/Makefile index dae1cae4a..a54a5a0d6 100644 --- a/stratosphere/sm/Makefile +++ b/stratosphere/sm/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/libnx/switch_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -24,7 +31,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" #--------------------------------------------------------------------------------- # options for code generation diff --git a/thermosphere/Makefile b/thermosphere/Makefile index 76f6a100b..7f2634bbe 100644 --- a/thermosphere/Makefile +++ b/thermosphere/Makefile @@ -9,6 +9,13 @@ endif TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/devkitA64/base_rules +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -26,6 +33,7 @@ INCLUDES := include ../common/include # options for code generation #--------------------------------------------------------------------------------- ARCH := -march=armv8-a -mtune=cortex-a57 +DEFINES := -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" CFLAGS := \ -g \ From 560d899a9b57641970c47a08ac7ad9ecdcf84204 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 13:11:41 -0800 Subject: [PATCH 211/489] Improve text rendering API, add ams version. --- stratosphere/fatal/source/fatal_font.cpp | 21 ++++++++++++++----- stratosphere/fatal/source/fatal_font.hpp | 5 +++-- .../fatal/source/fatal_task_screen.cpp | 9 +++++++- stratosphere/libstratosphere | 2 +- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/stratosphere/fatal/source/fatal_font.cpp b/stratosphere/fatal/source/fatal_font.cpp index b81c65126..e2fd4b3b2 100644 --- a/stratosphere/fatal/source/fatal_font.cpp +++ b/stratosphere/fatal/source/fatal_font.cpp @@ -31,6 +31,7 @@ static u16 *g_fb = nullptr; static u32 (*g_unswizzle_func)(u32, u32) = nullptr; static u16 g_font_color = 0xFFFF; +static u32 g_cur_x = 0, g_cur_y = 0; static PlFontData g_font; static PlFontData g_fonts[PlSharedFontType_Total]; @@ -68,13 +69,18 @@ static void DrawGlyph(FT_Bitmap *bitmap, u32 x, u32 y) { } } -void FontManager::DrawString(u32 x, u32 y, const char *str) { +void FontManager::PrintLine(const char *str) { FT_UInt glyph_index; FT_GlyphSlot slot = g_face->glyph; const size_t len = strlen(str); - u32 cur_x = x, cur_y = y; + u32 cur_x = g_cur_x, cur_y = g_cur_y; + ON_SCOPE_EXIT { + /* Advance to next line. */ + /* g_cur_x = g_cur_x; */ + g_cur_y = cur_y + (g_face->size->metrics.height >> 6); + }; for (u32 i = 0; i < len; ) { u32 cur_char; @@ -83,7 +89,7 @@ void FontManager::DrawString(u32 x, u32 y, const char *str) { i += unit_count; if (cur_char == '\n') { - cur_x = x; + cur_x = g_cur_x; cur_y += g_face->size->metrics.height >> 6; continue; } @@ -107,20 +113,25 @@ void FontManager::DrawString(u32 x, u32 y, const char *str) { } } -void FontManager::DrawFormat(u32 x, u32 y, const char *format, ...) { +void FontManager::PrintFormatLine(const char *format, ...) { va_list va_arg; va_start(va_arg, format); char char_buf[0x400]; vsnprintf(char_buf, sizeof(char_buf), format, va_arg); - DrawString(x, y, char_buf); + PrintLine(char_buf); } void FontManager::SetFontColor(u16 color) { g_font_color = color; } +void FontManager::SetPosition(u32 x, u32 y) { + g_cur_x = x; + g_cur_y = y; +} + void FontManager::ConfigureFontFramebuffer(u16 *fb, u32 (*unswizzle_func)(u32, u32)) { g_fb = fb; g_unswizzle_func = unswizzle_func; diff --git a/stratosphere/fatal/source/fatal_font.hpp b/stratosphere/fatal/source/fatal_font.hpp index ab553a28a..c72921065 100644 --- a/stratosphere/fatal/source/fatal_font.hpp +++ b/stratosphere/fatal/source/fatal_font.hpp @@ -30,6 +30,7 @@ class FontManager { static void ConfigureFontFramebuffer(u16 *fb, u32 (*unswizzle_func)(u32, u32)); static void SetFontColor(u16 color); - static void DrawString(u32 x, u32 y, const char *str); - static void DrawFormat(u32 x, u32 y, const char *format, ...); + static void SetPosition(u32 x, u32 y); + static void PrintLine(const char *str); + static void PrintFormatLine(const char *format, ...); }; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index b651c7ef9..81d4b143b 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -15,6 +15,9 @@ */ #include <switch.h> + +#include <atmosphere/version.h> + #include "fatal_task_screen.hpp" #include "fatal_config.hpp" #include "fatal_font.hpp" @@ -198,7 +201,11 @@ Result ShowFatalTask::ShowFatal() { } /* TODO: Actually draw meaningful shit here. */ - FontManager::DrawFormat(32, 64, u8"A fatal error occurred: 2%03d-%04d\n", R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code)); + FontManager::SetPosition(32, 64); + FontManager::PrintFormatLine(u8"A fatal error occurred: 2%03d-%04d", R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code)); + FontManager::PrintFormatLine(u8"Firmware: %s (AMS %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, + CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); + /* Enqueue the buffer. */ framebufferEnd(&fb); diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 6a6eedeac..0fb33e9c0 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 6a6eedeacd69a4bddb1e43e31a642a1249a8eb88 +Subproject commit 0fb33e9c094bffde737c7a73cd5ccce4d7cbae33 From 1bface09d5412a368f0907503cd9f8126e7977ff Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 13:28:05 -0800 Subject: [PATCH 212/489] fatal: add line spacing func, improve 565->888 for blending --- stratosphere/fatal/source/fatal_font.cpp | 4 ++++ stratosphere/fatal/source/fatal_font.hpp | 7 ++++--- stratosphere/fatal/source/fatal_task_screen.cpp | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/stratosphere/fatal/source/fatal_font.cpp b/stratosphere/fatal/source/fatal_font.cpp index e2fd4b3b2..a832f3238 100644 --- a/stratosphere/fatal/source/fatal_font.cpp +++ b/stratosphere/fatal/source/fatal_font.cpp @@ -132,6 +132,10 @@ void FontManager::SetPosition(u32 x, u32 y) { g_cur_y = y; } +void FontManager::AddSpacingLines(float num_lines) { + g_cur_y += static_cast<u32>((static_cast<float>(g_face->size->metrics.height) * num_lines) / 64.0f); +} + void FontManager::ConfigureFontFramebuffer(u16 *fb, u32 (*unswizzle_func)(u32, u32)) { g_fb = fb; g_unswizzle_func = unswizzle_func; diff --git a/stratosphere/fatal/source/fatal_font.hpp b/stratosphere/fatal/source/fatal_font.hpp index c72921065..a7622dc56 100644 --- a/stratosphere/fatal/source/fatal_font.hpp +++ b/stratosphere/fatal/source/fatal_font.hpp @@ -20,9 +20,9 @@ #include <stratosphere.hpp> #define RGB888_TO_RGB565(r, g, b) ((((r >> 3) << 11) & 0xF800) | (((g >> 2) << 5) & 0x7E0) | ((b >> 3) & 0x1F)) -#define RGB565_GET_R8(c) (((c >> 11) & 0x1F) << 3) -#define RGB565_GET_G8(c) (((c >> 5) & 0x3F) << 2) -#define RGB565_GET_B8(c) (((c >> 0) & 0x1F) << 3) +#define RGB565_GET_R8(c) ((((c >> 11) & 0x1F) << 3) | ((c >> 13) & 7)) +#define RGB565_GET_G8(c) ((((c >> 5) & 0x3F) << 2) | ((c >> 9) & 3)) +#define RGB565_GET_B8(c) ((((c >> 0) & 0x1F) << 3) | ((c >> 2) & 7)) class FontManager { public: @@ -31,6 +31,7 @@ class FontManager { static void SetFontColor(u16 color); static void SetPosition(u32 x, u32 y); + static void AddSpacingLines(float num_lines); static void PrintLine(const char *str); static void PrintFormatLine(const char *format, ...); }; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 81d4b143b..1872a7222 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -203,7 +203,8 @@ Result ShowFatalTask::ShowFatal() { /* TODO: Actually draw meaningful shit here. */ FontManager::SetPosition(32, 64); FontManager::PrintFormatLine(u8"A fatal error occurred: 2%03d-%04d", R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code)); - FontManager::PrintFormatLine(u8"Firmware: %s (AMS %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, + FontManager::AddSpacingLines(0.5f); + FontManager::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); From f16423c41355c7a6c7bb8c200b7866bb8fdff82f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 14:32:50 -0800 Subject: [PATCH 213/489] fatal: Add font scaling support --- stratosphere/fatal/source/fatal_font.cpp | 8 +++++++- stratosphere/fatal/source/fatal_font.hpp | 1 + stratosphere/fatal/source/fatal_task_screen.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/stratosphere/fatal/source/fatal_font.cpp b/stratosphere/fatal/source/fatal_font.cpp index a832f3238..31b45833a 100644 --- a/stratosphere/fatal/source/fatal_font.cpp +++ b/stratosphere/fatal/source/fatal_font.cpp @@ -31,6 +31,7 @@ static u16 *g_fb = nullptr; static u32 (*g_unswizzle_func)(u32, u32) = nullptr; static u16 g_font_color = 0xFFFF; +static float g_font_sz = 16.0f; static u32 g_cur_x = 0, g_cur_y = 0; static PlFontData g_font; @@ -132,6 +133,11 @@ void FontManager::SetPosition(u32 x, u32 y) { g_cur_y = y; } +void FontManager::SetFontSize(float fsz) { + g_font_sz = fsz; + g_ft_err = FT_Set_Char_Size(g_face, 0, static_cast<u32>(g_font_sz * 64.0f), 96, 96); +} + void FontManager::AddSpacingLines(float num_lines) { g_cur_y += static_cast<u32>((static_cast<float>(g_face->size->metrics.height) * num_lines) / 64.0f); } @@ -159,6 +165,6 @@ Result FontManager::InitializeSharedFont() { g_ft_err = FT_New_Memory_Face(g_library, reinterpret_cast<const FT_Byte *>(g_font.address), g_font.size, 0, &g_face); if (g_ft_err) return g_ft_err; - g_ft_err = FT_Set_Char_Size(g_face, 0, 8*64, 300, 300); + g_ft_err = FT_Set_Char_Size(g_face, 0, static_cast<u32>(g_font_sz * 64.0f), 96, 96); return g_ft_err; } \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_font.hpp b/stratosphere/fatal/source/fatal_font.hpp index a7622dc56..c0cb35456 100644 --- a/stratosphere/fatal/source/fatal_font.hpp +++ b/stratosphere/fatal/source/fatal_font.hpp @@ -31,6 +31,7 @@ class FontManager { static void SetFontColor(u16 color); static void SetPosition(u32 x, u32 y); + static void SetFontSize(float fsz); static void AddSpacingLines(float num_lines); static void PrintLine(const char *str); static void PrintFormatLine(const char *format, ...); diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 1872a7222..1fffada4d 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -207,7 +207,7 @@ Result ShowFatalTask::ShowFatal() { FontManager::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); - + /* Enqueue the buffer. */ framebufferEnd(&fb); From 20026587fd2835972b81e75a06c98bce45c5835c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 17:53:26 -0800 Subject: [PATCH 214/489] fatal: Draw GPRs + Backtrace to screen. --- stratosphere/fatal/source/fatal_config.cpp | 24 ++++ stratosphere/fatal/source/fatal_config.hpp | 3 + stratosphere/fatal/source/fatal_font.cpp | 46 ++++++- stratosphere/fatal/source/fatal_font.hpp | 4 + .../fatal/source/fatal_task_screen.cpp | 124 +++++++++++++++++- stratosphere/fatal/source/fatal_types.hpp | 66 +++++++++- 6 files changed, 253 insertions(+), 14 deletions(-) diff --git a/stratosphere/fatal/source/fatal_config.cpp b/stratosphere/fatal/source/fatal_config.cpp index 5583e7a0b..f2adae661 100644 --- a/stratosphere/fatal/source/fatal_config.cpp +++ b/stratosphere/fatal/source/fatal_config.cpp @@ -48,6 +48,28 @@ IEvent *GetFatalSettingsEvent() { return g_fatal_settings_event; } +static void SetupConfigLanguages() { + FatalConfig *config = GetFatalConfig(); + + /* Defaults. */ + config->error_msg = u8"Error Code: 2%03d-%04d (0x%x)\n"; + + if (config->quest_flag) { + config->error_desc = u8"Please call 1-800-875-1852 for service.\n"; + } else { + config->error_desc = u8"An error has occured.\n\n" + u8"Please press the POWER Button to restart the console. If you are\n" + u8"unable to restart the console, hold the POWER Button for 12 seconds\n" + u8"to turn the console off.\n\n" + u8"If the problem persists, refer to the Nintendo Support Website.\n" + u8"nintendo.com/switch/error\n"; + } + + /* TODO: Try to load dynamically. */ + /* FsStorage message_storage; */ + /* TODO: if (R_SUCCEEDED(fsOpenDataStorageByDataId(0x010000000000081D, "fatal_msg"))) { ... } */ +} + void InitializeFatalConfig() { FatalConfig *config = GetFatalConfig(); @@ -61,4 +83,6 @@ void InitializeFatalConfig() { setsysGetSettingsItemValue("fatal", "quest_reboot_interval_second", &config->quest_reboot_interval_second, sizeof(config->quest_reboot_interval_second)); setsysGetFlag(SetSysFlag_Quest, &config->quest_flag); + + SetupConfigLanguages(); } diff --git a/stratosphere/fatal/source/fatal_config.hpp b/stratosphere/fatal/source/fatal_config.hpp index 105534bfc..5656feda0 100644 --- a/stratosphere/fatal/source/fatal_config.hpp +++ b/stratosphere/fatal/source/fatal_config.hpp @@ -26,6 +26,9 @@ struct FatalConfig { bool transition_to_fatal; bool show_extra_info; bool quest_flag; + const char *error_msg; + const char *error_desc; + const char *quest_desc; }; IEvent *GetFatalSettingsEvent(); diff --git a/stratosphere/fatal/source/fatal_font.cpp b/stratosphere/fatal/source/fatal_font.cpp index 31b45833a..92712f39d 100644 --- a/stratosphere/fatal/source/fatal_font.cpp +++ b/stratosphere/fatal/source/fatal_font.cpp @@ -32,7 +32,7 @@ static u16 *g_fb = nullptr; static u32 (*g_unswizzle_func)(u32, u32) = nullptr; static u16 g_font_color = 0xFFFF; static float g_font_sz = 16.0f; -static u32 g_cur_x = 0, g_cur_y = 0; +static u32 g_line_x = 0, g_cur_x = 0, g_cur_y = 0; static PlFontData g_font; static PlFontData g_fonts[PlSharedFontType_Total]; @@ -70,7 +70,7 @@ static void DrawGlyph(FT_Bitmap *bitmap, u32 x, u32 y) { } } -void FontManager::PrintLine(const char *str) { +static void DrawString(const char *str, bool add_line) { FT_UInt glyph_index; FT_GlyphSlot slot = g_face->glyph; @@ -78,9 +78,14 @@ void FontManager::PrintLine(const char *str) { u32 cur_x = g_cur_x, cur_y = g_cur_y; ON_SCOPE_EXIT { - /* Advance to next line. */ - /* g_cur_x = g_cur_x; */ - g_cur_y = cur_y + (g_face->size->metrics.height >> 6); + if (add_line) { + /* Advance to next line. */ + g_cur_x = g_line_x; + g_cur_y = cur_y + (g_face->size->metrics.height >> 6); + } else { + g_cur_x = cur_x; + g_cur_y = cur_y; + } }; for (u32 i = 0; i < len; ) { @@ -90,7 +95,7 @@ void FontManager::PrintLine(const char *str) { i += unit_count; if (cur_char == '\n') { - cur_x = g_cur_x; + cur_x = g_line_x; cur_y += g_face->size->metrics.height >> 6; continue; } @@ -114,6 +119,10 @@ void FontManager::PrintLine(const char *str) { } } +void FontManager::PrintLine(const char *str) { + return DrawString(str, true); +} + void FontManager::PrintFormatLine(const char *format, ...) { va_list va_arg; va_start(va_arg, format); @@ -124,21 +133,46 @@ void FontManager::PrintFormatLine(const char *format, ...) { PrintLine(char_buf); } +void FontManager::Print(const char *str) { + return DrawString(str, false); +} + +void FontManager::PrintFormat(const char *format, ...) { + va_list va_arg; + va_start(va_arg, format); + + char char_buf[0x400]; + vsnprintf(char_buf, sizeof(char_buf), format, va_arg); + + Print(char_buf); +} + + void FontManager::SetFontColor(u16 color) { g_font_color = color; } void FontManager::SetPosition(u32 x, u32 y) { + g_line_x = x; g_cur_x = x; g_cur_y = y; } +u32 FontManager::GetX() { + return g_cur_x; +} + +u32 FontManager::GetY() { + return g_cur_y; +} + void FontManager::SetFontSize(float fsz) { g_font_sz = fsz; g_ft_err = FT_Set_Char_Size(g_face, 0, static_cast<u32>(g_font_sz * 64.0f), 96, 96); } void FontManager::AddSpacingLines(float num_lines) { + g_cur_x = g_line_x; g_cur_y += static_cast<u32>((static_cast<float>(g_face->size->metrics.height) * num_lines) / 64.0f); } diff --git a/stratosphere/fatal/source/fatal_font.hpp b/stratosphere/fatal/source/fatal_font.hpp index c0cb35456..e98d4e4cd 100644 --- a/stratosphere/fatal/source/fatal_font.hpp +++ b/stratosphere/fatal/source/fatal_font.hpp @@ -31,8 +31,12 @@ class FontManager { static void SetFontColor(u16 color); static void SetPosition(u32 x, u32 y); + static u32 GetX(); + static u32 GetY(); static void SetFontSize(float fsz); static void AddSpacingLines(float num_lines); static void PrintLine(const char *str); static void PrintFormatLine(const char *format, ...); + static void Print(const char *str); + static void PrintFormat(const char *format, ...); }; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 1fffada4d..90132aa1a 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -172,6 +172,7 @@ Result ShowFatalTask::PrepareScreenForDrawing() { Result ShowFatalTask::ShowFatal() { Result rc = 0; + const FatalConfig *config = GetFatalConfig(); if (R_FAILED((rc = PrepareScreenForDrawing()))) { *(volatile u32 *)(0xCAFEBABE) = rc; @@ -196,17 +197,132 @@ Result ShowFatalTask::ShowFatal() { /* Draw the atmosphere logo in the bottom right corner. */ for (size_t y = 0; y < AMS_LOGO_HEIGHT; y++) { for (size_t x = 0; x < AMS_LOGO_WIDTH; x++) { - tiled_buf[GetPixelOffset(FatalScreenWidth - AMS_LOGO_WIDTH - 32 + x, FatalScreenHeight - AMS_LOGO_HEIGHT - 32 + y)] = AMS_LOGO_BIN[y * AMS_LOGO_WIDTH + x]; + tiled_buf[GetPixelOffset(FatalScreenWidth - AMS_LOGO_WIDTH - 32 + x, 32 + y)] = AMS_LOGO_BIN[y * AMS_LOGO_WIDTH + x]; } } /* TODO: Actually draw meaningful shit here. */ FontManager::SetPosition(32, 64); - FontManager::PrintFormatLine(u8"A fatal error occurred: 2%03d-%04d", R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code)); + FontManager::SetFontSize(16.0f); + FontManager::PrintFormatLine("Title: %016lx", this->title_id); FontManager::AddSpacingLines(0.5f); - FontManager::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, - CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); + FontManager::PrintFormatLine(config->error_msg, R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code), this->ctx->error_code); + FontManager::PrintLine(config->error_desc); + FontManager::AddSpacingLines(0.5f); + FontManager::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); + /* Add a line. */ + for (size_t x = 32; x < FatalScreenWidth - 32; x++) { + tiled_buf[GetPixelOffset(x, FontManager::GetY())] = 0xFFFF; + } + + + FontManager::AddSpacingLines(1.5f); + + u32 backtrace_y = FontManager::GetY(); + u32 backtrace_x = 0; + + /* Print GPRs. */ + FontManager::SetFontSize(14.0f); + FontManager::PrintLine("General Purpose Registers"); + FontManager::AddSpacingLines(0.5f); + if (this->ctx->cpu_ctx.is_aarch32) { + for (size_t i = 0; i < (NumAarch32Gprs / 2); i++) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("%s:", Aarch32GprNames[i]); + FontManager::SetPosition(x + 47, FontManager::GetY()); + FontManager::PrintFormat("0x%08x ", this->ctx->cpu_ctx.aarch32_ctx.r[i]); + x = FontManager::GetX(); + FontManager::PrintFormat("%s:", Aarch32GprNames[i + (NumAarch32Gprs / 2)]); + FontManager::SetPosition(x + 47, FontManager::GetY()); + FontManager::PrintFormat("0x%08x ", this->ctx->cpu_ctx.aarch32_ctx.r[i]); + + + FontManager::PrintLine(""); + FontManager::SetPosition(32, FontManager::GetY()); + } + } else { + for (size_t i = 0; i < NumAarch64Gprs / 2; i++) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("%s:", Aarch64GprNames[i]); + FontManager::SetPosition(x + 47, FontManager::GetY()); + FontManager::PrintFormat("0x%016lx ", this->ctx->cpu_ctx.aarch64_ctx.x[i]); + x = FontManager::GetX(); + FontManager::PrintFormat("%s:", Aarch64GprNames[i + (NumAarch64Gprs / 2)]); + FontManager::SetPosition(x + 47, FontManager::GetY()); + FontManager::PrintFormat("0x%016lx ", this->ctx->cpu_ctx.aarch64_ctx.x[i]); + + if (i == (NumAarch64Gprs / 2) - 1) { + FontManager::Print(" "); + backtrace_x = FontManager::GetX(); + } + + FontManager::PrintLine(""); + FontManager::SetPosition(32, FontManager::GetY()); + } + } + + /* Print Backtrace. */ + FontManager::SetPosition(backtrace_x, backtrace_y); + if (this->ctx->cpu_ctx.is_aarch32) { + FontManager::PrintFormatLine("Backtrace (Start Address = 0x%08x)", this->ctx->cpu_ctx.aarch32_ctx.start_address); + FontManager::AddSpacingLines(0.5f); + for (u32 i = 0; i < Aarch32CpuContext::MaxStackTraceDepth / 2; i++) { + u32 bt_cur = 0, bt_next = 0; + if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { + bt_cur = this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i]; + } + if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { + bt_next = this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i + Aarch32CpuContext::MaxStackTraceDepth / 2]; + } + + if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("BT[%02X]: ", i); + FontManager::SetPosition(x + 76, FontManager::GetY()); + FontManager::PrintFormat("0x%08x ", bt_cur); + } + + if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("BT[%02X]: ", i + Aarch32CpuContext::MaxStackTraceDepth / 2); + FontManager::SetPosition(x + 76, FontManager::GetY()); + FontManager::PrintFormat("0x%08x ", bt_next); + } + + FontManager::PrintLine(""); + FontManager::SetPosition(backtrace_x, FontManager::GetY()); + } + } else { + FontManager::PrintFormatLine("Backtrace (Start Address = 0x%016lx)", this->ctx->cpu_ctx.aarch64_ctx.start_address); + FontManager::AddSpacingLines(0.5f); + for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) { + u64 bt_cur = 0, bt_next = 0; + if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { + bt_cur = this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i]; + } + if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { + bt_next = this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i + Aarch64CpuContext::MaxStackTraceDepth / 2]; + } + + if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("BT[%02X]: ", i); + FontManager::SetPosition(x + 76, FontManager::GetY()); + FontManager::PrintFormat("0x%016lx ", bt_cur); + } + + if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("BT[%02X]: ", i + Aarch64CpuContext::MaxStackTraceDepth / 2); + FontManager::SetPosition(x + 76, FontManager::GetY()); + FontManager::PrintFormat("0x%016lx ", bt_next); + } + + FontManager::PrintLine(""); + FontManager::SetPosition(backtrace_x, FontManager::GetY()); + } + } /* Enqueue the buffer. */ framebufferEnd(&fb); diff --git a/stratosphere/fatal/source/fatal_types.hpp b/stratosphere/fatal/source/fatal_types.hpp index 83abe9d0e..06c435364 100644 --- a/stratosphere/fatal/source/fatal_types.hpp +++ b/stratosphere/fatal/source/fatal_types.hpp @@ -26,13 +26,16 @@ enum FatalResult : Result { FatalResult_InRepairWithoutTimeReviserCartridge = 0xCA3, }; +static constexpr size_t NumAarch64Gprs = 32; +static constexpr size_t NumAarch32Gprs = 16; + struct Aarch64CpuContext { using RegisterType = u64; static constexpr size_t MaxStackTraceDepth = 0x20; /* Registers, exception context. N left names for these fields in fatal .rodata. */ union { - RegisterType x[31]; + RegisterType x[NumAarch64Gprs]; struct { RegisterType _x[29]; RegisterType fp; @@ -60,9 +63,9 @@ struct Aarch32CpuContext { /* Registers, exception context. N left names for these fields in fatal .rodata. */ union { - RegisterType r[16]; + RegisterType r[NumAarch32Gprs]; struct { - RegisterType _x[11]; + RegisterType _r[11]; RegisterType fp; RegisterType ip; RegisterType sp; @@ -86,7 +89,7 @@ struct Aarch32CpuContext { struct FatalCpuContext { union { Aarch64CpuContext aarch64_ctx; - Aarch64CpuContext aarch32_ctx; + Aarch32CpuContext aarch32_ctx; }; bool is_aarch32; @@ -102,3 +105,58 @@ static_assert(sizeof(Aarch64CpuContext) == 0x248, "Aarch64CpuContext definition! static_assert(sizeof(Aarch32CpuContext) == 0xE0, "Aarch32CpuContext definition!"); static_assert(sizeof(FatalCpuContext) == 0x250, "FatalCpuContext definition!"); static_assert(std::is_pod_v<FatalCpuContext>, "FatalCpuContext definition!"); + +static constexpr const char *Aarch64GprNames[NumAarch64Gprs] = { + u8"X0", + u8"X1", + u8"X2", + u8"X3", + u8"X4", + u8"X5", + u8"X6", + u8"X7", + u8"X8", + u8"X9", + u8"X10", + u8"X11", + u8"X12", + u8"X13", + u8"X14", + u8"X15", + u8"X16", + u8"X17", + u8"X18", + u8"X19", + u8"X20", + u8"X22", + u8"X23", + u8"X24", + u8"X25", + u8"X26", + u8"X27", + u8"X28", + u8"FP", + u8"LR", + u8"SP", + u8"PC", +}; + +static constexpr const char *Aarch32GprNames[NumAarch32Gprs] = { + u8"R0", + u8"R1", + u8"R2", + u8"R3", + u8"R4", + u8"R5", + u8"R6", + u8"R7", + u8"R8", + u8"R9", + u8"R10", + u8"FP", + u8"IP", + u8"LR", + u8"SP", + u8"PC", +}; + From fa9d7f40fc09dfae14f6c06fe3bff4152bee57e2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 18:07:27 -0800 Subject: [PATCH 215/489] fatal: Reorder error message lines. --- stratosphere/fatal/source/fatal_task_screen.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 90132aa1a..4b79cd4ef 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -204,12 +204,13 @@ Result ShowFatalTask::ShowFatal() { /* TODO: Actually draw meaningful shit here. */ FontManager::SetPosition(32, 64); FontManager::SetFontSize(16.0f); + FontManager::PrintFormat(config->error_msg, R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code), this->ctx->error_code); + FontManager::AddSpacingLines(0.5f); FontManager::PrintFormatLine("Title: %016lx", this->title_id); FontManager::AddSpacingLines(0.5f); - FontManager::PrintFormatLine(config->error_msg, R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code), this->ctx->error_code); - FontManager::PrintLine(config->error_desc); - FontManager::AddSpacingLines(0.5f); FontManager::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); + FontManager::AddSpacingLines(1.5f); + FontManager::Print(config->error_desc); /* Add a line. */ for (size_t x = 32; x < FatalScreenWidth - 32; x++) { From d4ee772714dfe1374c31460a0443aabc36dce218 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 18:11:08 -0800 Subject: [PATCH 216/489] fatal: Display start instead of bt if size = 0 --- .../fatal/source/fatal_task_screen.cpp | 126 ++++++++++-------- 1 file changed, 71 insertions(+), 55 deletions(-) diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 4b79cd4ef..4acd3fdc6 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -264,66 +264,82 @@ Result ShowFatalTask::ShowFatal() { } /* Print Backtrace. */ - FontManager::SetPosition(backtrace_x, backtrace_y); + u32 bt_size; if (this->ctx->cpu_ctx.is_aarch32) { - FontManager::PrintFormatLine("Backtrace (Start Address = 0x%08x)", this->ctx->cpu_ctx.aarch32_ctx.start_address); - FontManager::AddSpacingLines(0.5f); - for (u32 i = 0; i < Aarch32CpuContext::MaxStackTraceDepth / 2; i++) { - u32 bt_cur = 0, bt_next = 0; - if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { - bt_cur = this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i]; - } - if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { - bt_next = this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i + Aarch32CpuContext::MaxStackTraceDepth / 2]; - } - - if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { - u32 x = FontManager::GetX(); - FontManager::PrintFormat("BT[%02X]: ", i); - FontManager::SetPosition(x + 76, FontManager::GetY()); - FontManager::PrintFormat("0x%08x ", bt_cur); - } - - if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { - u32 x = FontManager::GetX(); - FontManager::PrintFormat("BT[%02X]: ", i + Aarch32CpuContext::MaxStackTraceDepth / 2); - FontManager::SetPosition(x + 76, FontManager::GetY()); - FontManager::PrintFormat("0x%08x ", bt_next); - } - - FontManager::PrintLine(""); - FontManager::SetPosition(backtrace_x, FontManager::GetY()); + bt_size = this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size; + } else { + bt_size = this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size; + } + + if (bt_size == 0) { + if (this->ctx->cpu_ctx.is_aarch32) { + FontManager::PrintFormatLine("Start Address: 0x%08x", this->ctx->cpu_ctx.aarch32_ctx.start_address); + } else { + FontManager::PrintFormatLine("Start Address: 0x%016lx", this->ctx->cpu_ctx.aarch64_ctx.start_address); } - } else { - FontManager::PrintFormatLine("Backtrace (Start Address = 0x%016lx)", this->ctx->cpu_ctx.aarch64_ctx.start_address); - FontManager::AddSpacingLines(0.5f); - for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) { - u64 bt_cur = 0, bt_next = 0; - if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { - bt_cur = this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i]; + } else { + FontManager::SetPosition(backtrace_x, backtrace_y); + if (this->ctx->cpu_ctx.is_aarch32) { + FontManager::PrintFormatLine("Backtrace (Start Address = 0x%08x)", this->ctx->cpu_ctx.aarch32_ctx.start_address); + FontManager::AddSpacingLines(0.5f); + for (u32 i = 0; i < Aarch32CpuContext::MaxStackTraceDepth / 2; i++) { + u32 bt_cur = 0, bt_next = 0; + if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { + bt_cur = this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i]; + } + if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { + bt_next = this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i + Aarch32CpuContext::MaxStackTraceDepth / 2]; + } + + if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("BT[%02X]: ", i); + FontManager::SetPosition(x + 76, FontManager::GetY()); + FontManager::PrintFormat("0x%08x ", bt_cur); + } + + if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("BT[%02X]: ", i + Aarch32CpuContext::MaxStackTraceDepth / 2); + FontManager::SetPosition(x + 76, FontManager::GetY()); + FontManager::PrintFormat("0x%08x ", bt_next); + } + + FontManager::PrintLine(""); + FontManager::SetPosition(backtrace_x, FontManager::GetY()); } - if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { - bt_next = this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i + Aarch64CpuContext::MaxStackTraceDepth / 2]; + } else { + FontManager::PrintFormatLine("Backtrace (Start Address = 0x%016lx)", this->ctx->cpu_ctx.aarch64_ctx.start_address); + FontManager::AddSpacingLines(0.5f); + for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) { + u64 bt_cur = 0, bt_next = 0; + if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { + bt_cur = this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i]; + } + if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { + bt_next = this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i + Aarch64CpuContext::MaxStackTraceDepth / 2]; + } + + if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("BT[%02X]: ", i); + FontManager::SetPosition(x + 76, FontManager::GetY()); + FontManager::PrintFormat("0x%016lx ", bt_cur); + } + + if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { + u32 x = FontManager::GetX(); + FontManager::PrintFormat("BT[%02X]: ", i + Aarch64CpuContext::MaxStackTraceDepth / 2); + FontManager::SetPosition(x + 76, FontManager::GetY()); + FontManager::PrintFormat("0x%016lx ", bt_next); + } + + FontManager::PrintLine(""); + FontManager::SetPosition(backtrace_x, FontManager::GetY()); } - - if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { - u32 x = FontManager::GetX(); - FontManager::PrintFormat("BT[%02X]: ", i); - FontManager::SetPosition(x + 76, FontManager::GetY()); - FontManager::PrintFormat("0x%016lx ", bt_cur); - } - - if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { - u32 x = FontManager::GetX(); - FontManager::PrintFormat("BT[%02X]: ", i + Aarch64CpuContext::MaxStackTraceDepth / 2); - FontManager::SetPosition(x + 76, FontManager::GetY()); - FontManager::PrintFormat("0x%016lx ", bt_next); - } - - FontManager::PrintLine(""); - FontManager::SetPosition(backtrace_x, FontManager::GetY()); } - } + } + /* Enqueue the buffer. */ framebufferEnd(&fb); From 98bdb2a7a394d2a88f29d62b5f9a70d42c2670a6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 19:30:40 -0800 Subject: [PATCH 217/489] fatal: Add fake monospace for hex output --- stratosphere/fatal/source/fatal_config.cpp | 2 +- stratosphere/fatal/source/fatal_font.cpp | 33 +++++++++-- stratosphere/fatal/source/fatal_font.hpp | 2 + .../fatal/source/fatal_task_screen.cpp | 58 +++++++++++-------- 4 files changed, 67 insertions(+), 28 deletions(-) diff --git a/stratosphere/fatal/source/fatal_config.cpp b/stratosphere/fatal/source/fatal_config.cpp index f2adae661..fd1703137 100644 --- a/stratosphere/fatal/source/fatal_config.cpp +++ b/stratosphere/fatal/source/fatal_config.cpp @@ -62,7 +62,7 @@ static void SetupConfigLanguages() { u8"unable to restart the console, hold the POWER Button for 12 seconds\n" u8"to turn the console off.\n\n" u8"If the problem persists, refer to the Nintendo Support Website.\n" - u8"nintendo.com/switch/error\n"; + u8"support.nintendo.com/switch/error\n"; } /* TODO: Try to load dynamically. */ diff --git a/stratosphere/fatal/source/fatal_font.cpp b/stratosphere/fatal/source/fatal_font.cpp index 92712f39d..b86cf4edf 100644 --- a/stratosphere/fatal/source/fatal_font.cpp +++ b/stratosphere/fatal/source/fatal_font.cpp @@ -34,6 +34,8 @@ static u16 g_font_color = 0xFFFF; static float g_font_sz = 16.0f; static u32 g_line_x = 0, g_cur_x = 0, g_cur_y = 0; +static u32 g_mono_adv = 0; + static PlFontData g_font; static PlFontData g_fonts[PlSharedFontType_Total]; static FT_Library g_library; @@ -70,7 +72,7 @@ static void DrawGlyph(FT_Bitmap *bitmap, u32 x, u32 y) { } } -static void DrawString(const char *str, bool add_line) { +static void DrawString(const char *str, bool add_line, bool mono = false) { FT_UInt glyph_index; FT_GlyphSlot slot = g_face->glyph; @@ -112,9 +114,9 @@ static void DrawString(const char *str, bool add_line) { return; } - DrawGlyph(&slot->bitmap, cur_x + slot->bitmap_left, cur_y - slot->bitmap_top); + DrawGlyph(&slot->bitmap, cur_x + slot->bitmap_left + ((mono && g_mono_adv > slot->advance.x) ? ((g_mono_adv - slot->advance.x) >> 7) : 0), cur_y - slot->bitmap_top); - cur_x += slot->advance.x >> 6; + cur_x += (mono ? g_mono_adv : slot->advance.x) >> 6; cur_y += slot->advance.y >> 6; } } @@ -147,6 +149,20 @@ void FontManager::PrintFormat(const char *format, ...) { Print(char_buf); } +void FontManager::PrintMonospaceU64(u64 x) { + char char_buf[0x400]; + snprintf(char_buf, sizeof(char_buf), "%016lX", x); + + DrawString(char_buf, false, true); +} + +void FontManager::PrintMonospaceU32(u32 x) { + char char_buf[0x400]; + snprintf(char_buf, sizeof(char_buf), "%08X", x); + + DrawString(char_buf, false, true); +} + void FontManager::SetFontColor(u16 color) { g_font_color = color; @@ -169,6 +185,15 @@ u32 FontManager::GetY() { void FontManager::SetFontSize(float fsz) { g_font_sz = fsz; g_ft_err = FT_Set_Char_Size(g_face, 0, static_cast<u32>(g_font_sz * 64.0f), 96, 96); + + g_ft_err = FT_Load_Glyph(g_face, FT_Get_Char_Index(g_face, 'A'), FT_LOAD_DEFAULT); + + if (g_ft_err == 0) { + g_ft_err = FT_Render_Glyph(g_face->glyph, FT_RENDER_MODE_NORMAL); + } + if (g_ft_err == 0) { + g_mono_adv = g_face->glyph->advance.x; + } } void FontManager::AddSpacingLines(float num_lines) { @@ -199,6 +224,6 @@ Result FontManager::InitializeSharedFont() { g_ft_err = FT_New_Memory_Face(g_library, reinterpret_cast<const FT_Byte *>(g_font.address), g_font.size, 0, &g_face); if (g_ft_err) return g_ft_err; - g_ft_err = FT_Set_Char_Size(g_face, 0, static_cast<u32>(g_font_sz * 64.0f), 96, 96); + SetFontSize(g_font_sz); return g_ft_err; } \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_font.hpp b/stratosphere/fatal/source/fatal_font.hpp index e98d4e4cd..5bd79dc14 100644 --- a/stratosphere/fatal/source/fatal_font.hpp +++ b/stratosphere/fatal/source/fatal_font.hpp @@ -39,4 +39,6 @@ class FontManager { static void PrintFormatLine(const char *format, ...); static void Print(const char *str); static void PrintFormat(const char *format, ...); + static void PrintMonospaceU64(u64 x); + static void PrintMonospaceU32(u32 x); }; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 4acd3fdc6..e4b25d1ba 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -206,7 +206,7 @@ Result ShowFatalTask::ShowFatal() { FontManager::SetFontSize(16.0f); FontManager::PrintFormat(config->error_msg, R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code), this->ctx->error_code); FontManager::AddSpacingLines(0.5f); - FontManager::PrintFormatLine("Title: %016lx", this->title_id); + FontManager::PrintFormatLine("Title: %016lX", this->title_id); FontManager::AddSpacingLines(0.5f); FontManager::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); FontManager::AddSpacingLines(1.5f); @@ -232,12 +232,19 @@ Result ShowFatalTask::ShowFatal() { u32 x = FontManager::GetX(); FontManager::PrintFormat("%s:", Aarch32GprNames[i]); FontManager::SetPosition(x + 47, FontManager::GetY()); - FontManager::PrintFormat("0x%08x ", this->ctx->cpu_ctx.aarch32_ctx.r[i]); + FontManager::Print("0x"); + FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.r[i]); + FontManager::Print(" "); x = FontManager::GetX(); FontManager::PrintFormat("%s:", Aarch32GprNames[i + (NumAarch32Gprs / 2)]); FontManager::SetPosition(x + 47, FontManager::GetY()); - FontManager::PrintFormat("0x%08x ", this->ctx->cpu_ctx.aarch32_ctx.r[i]); + FontManager::Print("0x"); + FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.r[i + (NumAarch32Gprs / 2)]); + if (i == (NumAarch32Gprs / 2) - 1) { + FontManager::Print(" "); + backtrace_x = FontManager::GetX(); + } FontManager::PrintLine(""); FontManager::SetPosition(32, FontManager::GetY()); @@ -247,11 +254,12 @@ Result ShowFatalTask::ShowFatal() { u32 x = FontManager::GetX(); FontManager::PrintFormat("%s:", Aarch64GprNames[i]); FontManager::SetPosition(x + 47, FontManager::GetY()); - FontManager::PrintFormat("0x%016lx ", this->ctx->cpu_ctx.aarch64_ctx.x[i]); + FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.x[i]); + FontManager::Print(" "); x = FontManager::GetX(); FontManager::PrintFormat("%s:", Aarch64GprNames[i + (NumAarch64Gprs / 2)]); FontManager::SetPosition(x + 47, FontManager::GetY()); - FontManager::PrintFormat("0x%016lx ", this->ctx->cpu_ctx.aarch64_ctx.x[i]); + FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.x[i + (NumAarch64Gprs / 2)]); if (i == (NumAarch64Gprs / 2) - 1) { FontManager::Print(" "); @@ -271,16 +279,17 @@ Result ShowFatalTask::ShowFatal() { bt_size = this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size; } + + FontManager::SetPosition(backtrace_x, backtrace_y); if (bt_size == 0) { if (this->ctx->cpu_ctx.is_aarch32) { - FontManager::PrintFormatLine("Start Address: 0x%08x", this->ctx->cpu_ctx.aarch32_ctx.start_address); + FontManager::PrintFormatLine("Start Address: 0x%08X", this->ctx->cpu_ctx.aarch32_ctx.start_address); } else { - FontManager::PrintFormatLine("Start Address: 0x%016lx", this->ctx->cpu_ctx.aarch64_ctx.start_address); + FontManager::PrintFormatLine("Start Address: 0x%016lX", this->ctx->cpu_ctx.aarch64_ctx.start_address); } } else { - FontManager::SetPosition(backtrace_x, backtrace_y); if (this->ctx->cpu_ctx.is_aarch32) { - FontManager::PrintFormatLine("Backtrace (Start Address = 0x%08x)", this->ctx->cpu_ctx.aarch32_ctx.start_address); + FontManager::PrintFormatLine("Backtrace - Start Address: 0x%08X", this->ctx->cpu_ctx.aarch32_ctx.start_address); FontManager::AddSpacingLines(0.5f); for (u32 i = 0; i < Aarch32CpuContext::MaxStackTraceDepth / 2; i++) { u32 bt_cur = 0, bt_next = 0; @@ -293,23 +302,25 @@ Result ShowFatalTask::ShowFatal() { if (i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { u32 x = FontManager::GetX(); - FontManager::PrintFormat("BT[%02X]: ", i); - FontManager::SetPosition(x + 76, FontManager::GetY()); - FontManager::PrintFormat("0x%08x ", bt_cur); + FontManager::PrintFormat("BT[%02d]: ", i); + FontManager::SetPosition(x + 72, FontManager::GetY()); + FontManager::PrintMonospaceU32(bt_cur); + FontManager::Print(" "); } if (i + Aarch32CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size) { u32 x = FontManager::GetX(); - FontManager::PrintFormat("BT[%02X]: ", i + Aarch32CpuContext::MaxStackTraceDepth / 2); - FontManager::SetPosition(x + 76, FontManager::GetY()); - FontManager::PrintFormat("0x%08x ", bt_next); + FontManager::PrintFormat("BT[%02d]: ", i + Aarch32CpuContext::MaxStackTraceDepth / 2); + FontManager::SetPosition(x + 72, FontManager::GetY()); + FontManager::PrintMonospaceU32(bt_next); } FontManager::PrintLine(""); FontManager::SetPosition(backtrace_x, FontManager::GetY()); } - } else { - FontManager::PrintFormatLine("Backtrace (Start Address = 0x%016lx)", this->ctx->cpu_ctx.aarch64_ctx.start_address); + } else { + + FontManager::PrintFormatLine("Backtrace - Start Address: 0x%016lX", this->ctx->cpu_ctx.aarch64_ctx.start_address); FontManager::AddSpacingLines(0.5f); for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) { u64 bt_cur = 0, bt_next = 0; @@ -322,16 +333,17 @@ Result ShowFatalTask::ShowFatal() { if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { u32 x = FontManager::GetX(); - FontManager::PrintFormat("BT[%02X]: ", i); - FontManager::SetPosition(x + 76, FontManager::GetY()); - FontManager::PrintFormat("0x%016lx ", bt_cur); + FontManager::PrintFormat("BT[%02d]: ", i); + FontManager::SetPosition(x + 72, FontManager::GetY()); + FontManager::PrintMonospaceU64(bt_cur); + FontManager::Print(" "); } if (i + Aarch64CpuContext::MaxStackTraceDepth / 2 < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { u32 x = FontManager::GetX(); - FontManager::PrintFormat("BT[%02X]: ", i + Aarch64CpuContext::MaxStackTraceDepth / 2); - FontManager::SetPosition(x + 76, FontManager::GetY()); - FontManager::PrintFormat("0x%016lx ", bt_next); + FontManager::PrintFormat("BT[%02d]: ", i + Aarch64CpuContext::MaxStackTraceDepth / 2); + FontManager::SetPosition(x + 72, FontManager::GetY()); + FontManager::PrintMonospaceU64(bt_next); } FontManager::PrintLine(""); From 50c65ea7e137a31321b772e1c4c6cc659a8f7125 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 19:33:21 -0800 Subject: [PATCH 218/489] fatal: monospace start address --- .../fatal/source/fatal_task_screen.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index e4b25d1ba..c20b14d7a 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -283,13 +283,19 @@ Result ShowFatalTask::ShowFatal() { FontManager::SetPosition(backtrace_x, backtrace_y); if (bt_size == 0) { if (this->ctx->cpu_ctx.is_aarch32) { - FontManager::PrintFormatLine("Start Address: 0x%08X", this->ctx->cpu_ctx.aarch32_ctx.start_address); + FontManager::Print("Start Address: "); + FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.start_address); + FontManager::PrintLine(""); } else { - FontManager::PrintFormatLine("Start Address: 0x%016lX", this->ctx->cpu_ctx.aarch64_ctx.start_address); + FontManager::Print("Start Address: "); + FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.start_address); + FontManager::PrintLine(""); } } else { if (this->ctx->cpu_ctx.is_aarch32) { - FontManager::PrintFormatLine("Backtrace - Start Address: 0x%08X", this->ctx->cpu_ctx.aarch32_ctx.start_address); + FontManager::PrintFormatLine("Backtrace - Start Address: "); + FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.start_address); + FontManager::PrintLine(""); FontManager::AddSpacingLines(0.5f); for (u32 i = 0; i < Aarch32CpuContext::MaxStackTraceDepth / 2; i++) { u32 bt_cur = 0, bt_next = 0; @@ -319,9 +325,9 @@ Result ShowFatalTask::ShowFatal() { FontManager::SetPosition(backtrace_x, FontManager::GetY()); } } else { - - FontManager::PrintFormatLine("Backtrace - Start Address: 0x%016lX", this->ctx->cpu_ctx.aarch64_ctx.start_address); - FontManager::AddSpacingLines(0.5f); + FontManager::PrintFormatLine("Backtrace - Start Address: "); + FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.start_address); + FontManager::PrintLine(""); for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) { u64 bt_cur = 0, bt_next = 0; if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { From 9714db14d2a296b9e37dd258a0b87d25d19b2f0e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 13 Nov 2018 20:22:54 -0800 Subject: [PATCH 219/489] fatal/creport: Add cpu context. --- .../creport/source/creport_code_info.hpp | 2 +- .../creport/source/creport_crash_report.cpp | 29 +++++++++++++++++++ .../creport/source/creport_crash_report.hpp | 1 + stratosphere/creport/source/creport_main.cpp | 4 ++- .../creport/source/creport_thread_info.hpp | 2 +- stratosphere/fatal/source/fatal_task.cpp | 2 +- stratosphere/fatal/source/fatal_task.hpp | 6 ++-- .../fatal/source/fatal_task_clock.hpp | 2 +- .../fatal/source/fatal_task_error_report.hpp | 2 +- .../fatal/source/fatal_task_power.hpp | 6 ++-- .../fatal/source/fatal_task_screen.cpp | 5 ++-- .../fatal/source/fatal_task_screen.hpp | 4 +-- .../fatal/source/fatal_task_sound.hpp | 2 +- stratosphere/fatal/source/fatal_throw.cpp | 10 +++++-- stratosphere/fatal/source/fatal_types.hpp | 3 +- 15 files changed, 60 insertions(+), 20 deletions(-) diff --git a/stratosphere/creport/source/creport_code_info.hpp b/stratosphere/creport/source/creport_code_info.hpp index ff1c1fb1c..6f1baca95 100644 --- a/stratosphere/creport/source/creport_code_info.hpp +++ b/stratosphere/creport/source/creport_code_info.hpp @@ -28,7 +28,7 @@ struct CodeInfo { }; class CodeList { - private: + public: static const size_t max_code_count = 0x10; u32 code_count = 0; CodeInfo code_infos[max_code_count]; diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index cd9d1f9bb..6f2a2e62f 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -42,6 +42,35 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { } } +FatalContext *CrashReport::GetFatalContext() { + FatalContext *ctx = new FatalContext; + *ctx = (FatalContext){0}; + + ctx->is_aarch32 = false; + ctx->type = static_cast<u32>(this->exception_info.type); + + for (size_t i = 0; i < 29; i++) { + ctx->aarch64_ctx.x[i] = this->crashed_thread_info.context.cpu_gprs[i].x; + } + ctx->aarch64_ctx.fp = this->crashed_thread_info.context.fp; + ctx->aarch64_ctx.lr = this->crashed_thread_info.context.lr; + ctx->aarch64_ctx.pc = this->crashed_thread_info.context.pc.x; + + ctx->aarch64_ctx.stack_trace_size = this->crashed_thread_info.stack_trace_size; + for (size_t i = 0; i < ctx->aarch64_ctx.stack_trace_size; i++) { + ctx->aarch64_ctx.stack_trace[i] = this->crashed_thread_info.stack_trace[i]; + } + + if (this->code_list.code_count) { + ctx->aarch64_ctx.start_address = this->code_list.code_infos[0].start_address; + } + + /* For ams fatal... */ + ctx->aarch64_ctx.afsr0 = this->process_info.title_id; + + return ctx; +} + void CrashReport::ProcessExceptions() { if (!IsOpen()) { return; diff --git a/stratosphere/creport/source/creport_crash_report.hpp b/stratosphere/creport/source/creport_crash_report.hpp index 049610c87..38aa28568 100644 --- a/stratosphere/creport/source/creport_crash_report.hpp +++ b/stratosphere/creport/source/creport_crash_report.hpp @@ -61,6 +61,7 @@ class CrashReport { public: void BuildReport(u64 pid, bool has_extra_info); + FatalContext *GetFatalContext(); void SaveReport(); bool IsAddressReadable(u64 address, u64 size, MemoryInfo *mi = NULL); diff --git a/stratosphere/creport/source/creport_main.cpp b/stratosphere/creport/source/creport_main.cpp index 77fd7b400..d106268e8 100644 --- a/stratosphere/creport/source/creport_main.cpp +++ b/stratosphere/creport/source/creport_main.cpp @@ -132,7 +132,9 @@ int main(int argc, char **argv) { return 0; } - fatalWithType(g_Creport.GetResult(), FatalType_ErrorScreen); + FatalContext *ctx = g_Creport.GetFatalContext(); + + fatalWithContext(g_Creport.GetResult(), FatalType_ErrorScreen, ctx); } } \ No newline at end of file diff --git a/stratosphere/creport/source/creport_thread_info.hpp b/stratosphere/creport/source/creport_thread_info.hpp index 0b3d3f07f..2995342cf 100644 --- a/stratosphere/creport/source/creport_thread_info.hpp +++ b/stratosphere/creport/source/creport_thread_info.hpp @@ -22,7 +22,7 @@ #include "creport_code_info.hpp" class ThreadInfo { - private: + public: ThreadContext context{}; u64 thread_id = 0; u64 stack_top = 0; diff --git a/stratosphere/fatal/source/fatal_task.cpp b/stratosphere/fatal/source/fatal_task.cpp index 62b39cdbb..6cf13428f 100644 --- a/stratosphere/fatal/source/fatal_task.cpp +++ b/stratosphere/fatal/source/fatal_task.cpp @@ -53,7 +53,7 @@ static void RunTask(IFatalTask *task, u32 stack_size = 0x4000) { cur_thread->Start(); } -void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) { +void RunFatalTasks(FatalThrowContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event) { RunTask(new ErrorReportTask(ctx, title_id, error_report, erpt_event)); RunTask(new PowerControlTask(ctx, title_id, erpt_event, battery_event)); RunTask(new ShowFatalTask(ctx, title_id, battery_event), 0x10000); diff --git a/stratosphere/fatal/source/fatal_task.hpp b/stratosphere/fatal/source/fatal_task.hpp index ef19fbbc1..6926f96f2 100644 --- a/stratosphere/fatal/source/fatal_task.hpp +++ b/stratosphere/fatal/source/fatal_task.hpp @@ -21,12 +21,12 @@ class IFatalTask { protected: - FatalContext *ctx; + FatalThrowContext *ctx; u64 title_id; public: - IFatalTask(FatalContext *ctx, u64 tid) : ctx(ctx), title_id(tid) { } + IFatalTask(FatalThrowContext *ctx, u64 tid) : ctx(ctx), title_id(tid) { } virtual Result Run() = 0; virtual const char *GetName() const = 0; }; -void RunFatalTasks(FatalContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event); +void RunFatalTasks(FatalThrowContext *ctx, u64 title_id, bool error_report, Event *erpt_event, Event *battery_event); diff --git a/stratosphere/fatal/source/fatal_task_clock.hpp b/stratosphere/fatal/source/fatal_task_clock.hpp index 8ceba6945..65aa609d3 100644 --- a/stratosphere/fatal/source/fatal_task_clock.hpp +++ b/stratosphere/fatal/source/fatal_task_clock.hpp @@ -23,7 +23,7 @@ class AdjustClockTask : public IFatalTask { private: Result AdjustClock(); public: - AdjustClockTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } + AdjustClockTask(FatalThrowContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } virtual Result Run() override; virtual const char *GetName() const override { return "AdjustClockTask"; diff --git a/stratosphere/fatal/source/fatal_task_error_report.hpp b/stratosphere/fatal/source/fatal_task_error_report.hpp index 7ade00bcf..71b220f4d 100644 --- a/stratosphere/fatal/source/fatal_task_error_report.hpp +++ b/stratosphere/fatal/source/fatal_task_error_report.hpp @@ -24,7 +24,7 @@ class ErrorReportTask : public IFatalTask { bool create_report; Event *erpt_event; public: - ErrorReportTask(FatalContext *ctx, u64 title_id, bool error_report, Event *evt) : IFatalTask(ctx, title_id), create_report(error_report), erpt_event(evt) { } + ErrorReportTask(FatalThrowContext *ctx, u64 title_id, bool error_report, Event *evt) : IFatalTask(ctx, title_id), create_report(error_report), erpt_event(evt) { } virtual Result Run() override; virtual const char *GetName() const override { return "WriteErrorReport"; diff --git a/stratosphere/fatal/source/fatal_task_power.hpp b/stratosphere/fatal/source/fatal_task_power.hpp index d31e78752..a4aedc155 100644 --- a/stratosphere/fatal/source/fatal_task_power.hpp +++ b/stratosphere/fatal/source/fatal_task_power.hpp @@ -27,7 +27,7 @@ class PowerControlTask : public IFatalTask { bool TryShutdown(); void MonitorBatteryState(); public: - PowerControlTask(FatalContext *ctx, u64 title_id, Event *er_evt, Event *bt_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt), battery_event(bt_evt) { } + PowerControlTask(FatalThrowContext *ctx, u64 title_id, Event *er_evt, Event *bt_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt), battery_event(bt_evt) { } virtual Result Run() override; virtual const char *GetName() const override { return "PowerControlTask"; @@ -40,7 +40,7 @@ class PowerButtonObserveTask : public IFatalTask { private: void WaitForPowerButton(); public: - PowerButtonObserveTask(FatalContext *ctx, u64 title_id, Event *er_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt) { } + PowerButtonObserveTask(FatalThrowContext *ctx, u64 title_id, Event *er_evt) : IFatalTask(ctx, title_id), erpt_event(er_evt) { } virtual Result Run() override; virtual const char *GetName() const override { return "PowerButtonObserveTask"; @@ -49,7 +49,7 @@ class PowerButtonObserveTask : public IFatalTask { class StateTransitionStopTask : public IFatalTask { public: - StateTransitionStopTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } + StateTransitionStopTask(FatalThrowContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } virtual Result Run() override; virtual const char *GetName() const override { return "StateTransitionStopTask"; diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index c20b14d7a..94fa1bacb 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -293,7 +293,7 @@ Result ShowFatalTask::ShowFatal() { } } else { if (this->ctx->cpu_ctx.is_aarch32) { - FontManager::PrintFormatLine("Backtrace - Start Address: "); + FontManager::Print("Backtrace - Start Address: "); FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.start_address); FontManager::PrintLine(""); FontManager::AddSpacingLines(0.5f); @@ -325,9 +325,10 @@ Result ShowFatalTask::ShowFatal() { FontManager::SetPosition(backtrace_x, FontManager::GetY()); } } else { - FontManager::PrintFormatLine("Backtrace - Start Address: "); + FontManager::Print("Backtrace - Start Address: "); FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.start_address); FontManager::PrintLine(""); + FontManager::AddSpacingLines(0.5f); for (u32 i = 0; i < Aarch64CpuContext::MaxStackTraceDepth / 2; i++) { u64 bt_cur = 0, bt_next = 0; if (i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size) { diff --git a/stratosphere/fatal/source/fatal_task_screen.hpp b/stratosphere/fatal/source/fatal_task_screen.hpp index bfaed2cea..9a2f7188c 100644 --- a/stratosphere/fatal/source/fatal_task_screen.hpp +++ b/stratosphere/fatal/source/fatal_task_screen.hpp @@ -32,7 +32,7 @@ class ShowFatalTask : public IFatalTask { Result PrepareScreenForDrawing(); Result ShowFatal(); public: - ShowFatalTask(FatalContext *ctx, u64 title_id, Event *evt) : IFatalTask(ctx, title_id), battery_event(evt) { } + ShowFatalTask(FatalThrowContext *ctx, u64 title_id, Event *evt) : IFatalTask(ctx, title_id), battery_event(evt) { } virtual Result Run() override; virtual const char *GetName() const override { return "ShowFatal"; @@ -43,7 +43,7 @@ class BacklightControlTask : public IFatalTask { private: void TurnOnBacklight(); public: - BacklightControlTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } + BacklightControlTask(FatalThrowContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } virtual Result Run() override; virtual const char *GetName() const override { return "BacklightControlTask"; diff --git a/stratosphere/fatal/source/fatal_task_sound.hpp b/stratosphere/fatal/source/fatal_task_sound.hpp index a6feea049..67954088b 100644 --- a/stratosphere/fatal/source/fatal_task_sound.hpp +++ b/stratosphere/fatal/source/fatal_task_sound.hpp @@ -23,7 +23,7 @@ class StopSoundTask : public IFatalTask { private: void StopSound(); public: - StopSoundTask(FatalContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } + StopSoundTask(FatalThrowContext *ctx, u64 title_id) : IFatalTask(ctx, title_id) { } virtual Result Run() override; virtual const char *GetName() const override { return "SoundTask"; diff --git a/stratosphere/fatal/source/fatal_throw.cpp b/stratosphere/fatal/source/fatal_throw.cpp index 2eb617593..dbd6eba3b 100644 --- a/stratosphere/fatal/source/fatal_throw.cpp +++ b/stratosphere/fatal/source/fatal_throw.cpp @@ -42,7 +42,7 @@ Result ThrowFatalForSelf(u32 error) { Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx) { Result rc = 0; - FatalContext ctx; + FatalThrowContext ctx; ctx.error_code = error; ctx.cpu_ctx = *cpu_ctx; @@ -51,7 +51,13 @@ Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu /* Get title id. On failure, it'll be zero. */ u64 title_id = 0; - pminfoGetTitleId(&title_id, pid); + pminfoGetTitleId(&title_id, pid); + ctx.is_creport = title_id == 0x0100000000000036; + + /* Support for ams creport. TODO: Make this its own command? */ + if (ctx.is_creport && !cpu_ctx->is_aarch32 && cpu_ctx->aarch64_ctx.afsr0 != 0) { + title_id = cpu_ctx->aarch64_ctx.afsr0; + } switch (policy) { case FatalType_ErrorReport: diff --git a/stratosphere/fatal/source/fatal_types.hpp b/stratosphere/fatal/source/fatal_types.hpp index 06c435364..99be9c524 100644 --- a/stratosphere/fatal/source/fatal_types.hpp +++ b/stratosphere/fatal/source/fatal_types.hpp @@ -96,8 +96,9 @@ struct FatalCpuContext { u32 type; }; -struct FatalContext { +struct FatalThrowContext { u32 error_code; + bool is_creport; FatalCpuContext cpu_ctx; }; From 962fa0a69020004f8e827200249a4edb2d201a9a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 14 Nov 2018 03:23:28 -0800 Subject: [PATCH 220/489] fatal: automatically collect backtrace for callers. --- stratosphere/fatal/fatal.json | 11 +- stratosphere/fatal/source/fatal_debug.cpp | 256 ++++++++++++++++++ stratosphere/fatal/source/fatal_debug.hpp | 149 ++++++++++ stratosphere/fatal/source/fatal_font.cpp | 8 + stratosphere/fatal/source/fatal_font.hpp | 1 + .../fatal/source/fatal_task_screen.cpp | 41 ++- stratosphere/fatal/source/fatal_throw.cpp | 22 +- stratosphere/fatal/source/fatal_types.hpp | 3 +- stratosphere/fatal/source/fatal_user.cpp | 9 +- 9 files changed, 481 insertions(+), 19 deletions(-) create mode 100644 stratosphere/fatal/source/fatal_debug.cpp create mode 100644 stratosphere/fatal/source/fatal_debug.hpp diff --git a/stratosphere/fatal/fatal.json b/stratosphere/fatal/fatal.json index 380b2b85f..61f6ca88f 100644 --- a/stratosphere/fatal/fatal.json +++ b/stratosphere/fatal/fatal.json @@ -12,7 +12,7 @@ "is_64_bit": true, "address_space_type": 3, "filesystem_access": { - "permissions": "0x0000000000100000" + "permissions": "0xFFFFFFFFFFFFFFFF" }, "service_access": ["bpc", "bpc:c", "erpt:c", "fsp-srv", "gpio", "i2c", "lbl", "lm", "nvdrv:s", "pcv", "pl:u", "pm:info", "psm", "set", "set:sys", "spsm", "vi:m", "vi:s"], "service_host": ["fatal:p", "fatal:u"], @@ -76,7 +76,14 @@ "svcReplyAndReceive": "0x43", "svcReplyAndReceiveWithUserBuffer": "0x44", "svcCreateEvent": "0x45", - "svcReadWriteRegister": "0x4E" + "svcReadWriteRegister": "0x4E", + "svcDebugActiveProcess": "0x60", + "svcGetDebugEvent": "0x63", + "svcGetThreadList": "0x66", + "svcGetDebugThreadContext": "0x67", + "svcQueryDebugProcessMemory": "0x69", + "svcReadDebugProcessMemory": "0x6a", + "svcGetDebugThreadParam": "0x6d" } }, { "type": "min_kernel_version", diff --git a/stratosphere/fatal/source/fatal_debug.cpp b/stratosphere/fatal/source/fatal_debug.cpp new file mode 100644 index 000000000..46ed8df13 --- /dev/null +++ b/stratosphere/fatal/source/fatal_debug.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <map> +#include <switch.h> +#include "fatal_debug.hpp" +#include "fatal_config.hpp" + +static bool IsAddressReadable(Handle debug_handle, u64 address, u64 size, MemoryInfo *o_mi) { + MemoryInfo mi; + u32 pi; + + if (o_mi == NULL) { + o_mi = &mi; + } + + if (R_FAILED(svcQueryDebugProcessMemory(o_mi, &pi, debug_handle, address))) { + return false; + } + + /* Must be readable */ + if ((o_mi->perm & Perm_R) != Perm_R) { + return false; + } + + /* Must have space for both userdata address and userdata size. */ + if (address < o_mi->addr || o_mi->addr + o_mi->size < address + size) { + return false; + } + + return true; +} + +static bool CheckThreadIsFatalCaller(FatalThrowContext *ctx, u64 debug_handle, u64 thread_id, u64 thread_tls_addr, ThreadContext *thread_ctx) { + /* Verify that the thread is running or waiting. */ + { + u64 _; + u32 thread_state; + if (R_FAILED(svcGetDebugThreadParam(&_, &thread_state, debug_handle, thread_id, DebugThreadParam_State))) { + return false; + } + + if (thread_state > 1) { + return false; + } + } + + /* Get the thread context. */ + if (R_FAILED(svcGetDebugThreadContext(thread_ctx, debug_handle, thread_id, 0xF))) { + return false; + } + + /* Check if PC is readable. */ + if (!IsAddressReadable(debug_handle, thread_ctx->pc.x, sizeof(u32), NULL)) { + return false; + } + + /* Try to read the current instruction. */ + u32 insn; + if (R_FAILED(svcReadDebugProcessMemory(&insn, debug_handle, thread_ctx->pc.x, sizeof(insn)))) { + return false; + } + + /* If the instruction isn't svcSendSyncRequest, it's not the fatal caller. */ + if (insn != 0xD4000421) { + return false; + } + + /* The fatal caller will have readable tls. */ + if (!IsAddressReadable(debug_handle, thread_tls_addr, 0x100, NULL)) { + return false; + } + + /* Read in the fatal caller's tls. */ + u8 thread_tls[0x100]; + if (R_FAILED(svcReadDebugProcessMemory(thread_tls, debug_handle, thread_tls_addr, sizeof(thread_tls)))) { + return false; + } + + /* Replace our tls with the fatal caller's. */ + std::memcpy(armGetTls(), thread_tls, sizeof(thread_tls)); + + /* Parse the command that the thread sent. */ + { + IpcParsedCommand r; + if (R_FAILED(ipcParse(&r))) { + return false; + } + + /* Fatal command takes in a PID, only one buffer max. */ + if (!r.HasPid || r.NumStatics || r.NumStaticsOut || r.NumHandles) { + return false; + } + + struct { + u32 magic; + u32 version; + u64 cmd_id; + u32 err_code; + } *raw = (decltype(raw))(r.Raw); + + if (raw->magic != SFCI_MAGIC) { + return false; + } + + if (raw->cmd_id > 2) { + return false; + } + + if (raw->cmd_id != 2 && r.NumBuffers) { + return false; + } + + if (raw->err_code != ctx->error_code) { + return false; + } + } + + /* We found our caller. */ + return true; +} + +void TryCollectDebugInformation(FatalThrowContext *ctx, u64 pid) { + Handle debug_handle; + if (R_SUCCEEDED(svcDebugActiveProcess(&debug_handle, pid))) { + /* Ensure we close the debugged process. */ + ON_SCOPE_EXIT { svcCloseHandle(debug_handle); }; + + /* First things first, check if process is 64 bits, and get list of thread infos. */ + std::unordered_map<u64, u64> thread_id_to_tls; + { + bool got_attach_process = false; + DebugEventInfo d; + while (R_SUCCEEDED(svcGetDebugEvent((u8 *)&d, debug_handle))) { + if (d.type == DebugEventType::AttachProcess) { + ctx->cpu_ctx.is_aarch32 = (d.info.attach_process.flags & 1) == 0; + got_attach_process = true; + } else if (d.type == DebugEventType::AttachThread) { + thread_id_to_tls[d.info.attach_thread.thread_id] = d.info.attach_thread.tls_address; + } + } + + if (!got_attach_process) { + return; + } + } + + /* TODO: Try to collect information on 32-bit fatals. This shouldn't really matter for any real use case. */ + if (ctx->cpu_ctx.is_aarch32) { + return; + } + + /* Welcome to hell. */ + bool found_fatal_caller = false; + u64 thread_id = 0; + ThreadContext thread_ctx; + { + /* We start by trying to get a list of threads. */ + u32 thread_count; + u64 thread_ids[0x60]; + if (R_FAILED(svcGetThreadList(&thread_count, thread_ids, 0x60, debug_handle))) { + return; + } + + /* We need to locate the thread that's called fatal. */ + for (u32 i = 0; i < thread_count; i++) { + const u64 cur_thread_id = thread_ids[i]; + if (thread_id_to_tls.find(cur_thread_id) == thread_id_to_tls.end()) { + continue; + } + + if (CheckThreadIsFatalCaller(ctx, debug_handle, cur_thread_id, thread_id_to_tls[cur_thread_id], &thread_ctx)) { + thread_id = cur_thread_id; + found_fatal_caller = true; + break; + } + } + if (!found_fatal_caller) { + return; + } + } + if (R_FAILED(svcGetDebugThreadContext(&thread_ctx, debug_handle, thread_id, 0xF))) { + return; + } + + /* So we found our caller. */ + for (u32 i = 0; i < 29; i++) { + /* GetDebugThreadContext won't give us any of these registers, because thread is in SVC :( */ + ctx->has_gprs[i] = false; + } + for (u32 i = 29; i < NumAarch64Gprs; i++) { + ctx->has_gprs[i] = true; + } + ctx->cpu_ctx.aarch64_ctx.fp = thread_ctx.fp; + ctx->cpu_ctx.aarch64_ctx.lr = thread_ctx.lr; + ctx->cpu_ctx.aarch64_ctx.sp = thread_ctx.sp; + ctx->cpu_ctx.aarch64_ctx.pc = thread_ctx.pc.x; + + + /* Parse a stack trace. */ + u64 cur_fp = thread_ctx.fp; + for (unsigned int i = 0; i < sizeof(ctx->cpu_ctx.aarch64_ctx.stack_trace)/sizeof(u64); i++) { + /* Validate the current frame. */ + if (cur_fp == 0 || (cur_fp & 0xF)) { + break; + } + + /* Read a new frame. */ + StackFrame cur_frame; + if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(StackFrame)))) { + break; + } + + /* Advance to the next frame. */ + ctx->cpu_ctx.aarch64_ctx.stack_trace[ctx->cpu_ctx.aarch64_ctx.stack_trace_size++] = cur_frame.lr; + cur_fp = cur_frame.fp; + } + + /* Parse the starting address. */ + { + u64 guess = thread_ctx.pc.x; + MemoryInfo mi; + u32 pi; + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess)) || mi.perm != Perm_Rx) { + return; + } + + /* Iterate backwards until we find the memory before the code region. */ + while (mi.addr > 0) { + if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess))) { + return; + } + + if (mi.type == MemType_Unmapped) { + /* Code region will be at the end of the unmapped region preceding it. */ + ctx->cpu_ctx.aarch64_ctx.start_address = mi.addr + mi.size; + break; + } + + guess -= 4; + } + } + } +} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_debug.hpp b/stratosphere/fatal/source/fatal_debug.hpp new file mode 100644 index 000000000..8a7c4ec3d --- /dev/null +++ b/stratosphere/fatal/source/fatal_debug.hpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "fatal_types.hpp" + +void TryCollectDebugInformation(FatalThrowContext *ctx, u64 pid); + +struct StackFrame { + u64 fp; + u64 lr; +}; + +struct AttachProcessInfo { + u64 title_id; + u64 process_id; + char name[0xC]; + u32 flags; + u64 user_exception_context_address; /* 5.0.0+ */ +}; + +struct AttachThreadInfo { + u64 thread_id; + u64 tls_address; + u64 entrypoint; +}; + +/* TODO: ExitProcessInfo */ +/* TODO: ExitThreadInfo */ + +enum class DebugExceptionType : u32 { + UndefinedInstruction = 0, + InstructionAbort = 1, + DataAbort = 2, + AlignmentFault = 3, + DebuggerAttached = 4, + BreakPoint = 5, + UserBreak = 6, + DebuggerBreak = 7, + BadSvc = 8, + UnknownNine = 9, +}; + +static inline const char *GetDebugExceptionTypeStr(DebugExceptionType type) { + switch (type) { + case DebugExceptionType::UndefinedInstruction: + return "Undefined Instruction"; + case DebugExceptionType::InstructionAbort: + return "Instruction Abort"; + case DebugExceptionType::DataAbort: + return "Data Abort"; + case DebugExceptionType::AlignmentFault: + return "Alignment Fault"; + case DebugExceptionType::DebuggerAttached: + return "Debugger Attached"; + case DebugExceptionType::BreakPoint: + return "Break Point"; + case DebugExceptionType::UserBreak: + return "User Break"; + case DebugExceptionType::DebuggerBreak: + return "Debugger Break"; + case DebugExceptionType::BadSvc: + return "Bad Svc"; + case DebugExceptionType::UnknownNine: + return "Unknown Nine"; + default: + return "Unknown"; + } +} + +struct UndefinedInstructionInfo { + u32 insn; +}; + +struct DataAbortInfo { + u64 address; +}; + +struct AlignmentFaultInfo { + u64 address; +}; + +struct UserBreakInfo { + u64 break_reason; + u64 address; + u64 size; +}; + +struct BadSvcInfo { + u32 id; +}; + +union SpecificExceptionInfo { + UndefinedInstructionInfo undefined_instruction; + DataAbortInfo data_abort; + AlignmentFaultInfo alignment_fault; + UserBreakInfo user_break; + BadSvcInfo bad_svc; + u64 raw; +}; + +struct ExceptionInfo { + DebugExceptionType type; + u64 address; + SpecificExceptionInfo specific; +}; + + +enum class DebugEventType : u32 { + AttachProcess = 0, + AttachThread = 1, + ExitProcess = 2, + ExitThread = 3, + Exception = 4 +}; + +union DebugInfo { + AttachProcessInfo attach_process; + AttachThreadInfo attach_thread; + ExceptionInfo exception; +}; + +struct DebugEventInfo { + DebugEventType type; + u32 flags; + u64 thread_id; + union { + DebugInfo info; + u64 _[0x40/sizeof(u64)]; + }; +}; + +static_assert(sizeof(DebugEventInfo) >= 0x50, "Incorrect DebugEventInfo definition!"); \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_font.cpp b/stratosphere/fatal/source/fatal_font.cpp index b86cf4edf..452bff06d 100644 --- a/stratosphere/fatal/source/fatal_font.cpp +++ b/stratosphere/fatal/source/fatal_font.cpp @@ -163,6 +163,14 @@ void FontManager::PrintMonospaceU32(u32 x) { DrawString(char_buf, false, true); } +void FontManager::PrintMonospaceBlank(u32 width) { + char char_buf[0x400] = {0}; + for (size_t i = 0; i < width && i < sizeof(char_buf); i++) { + char_buf[i] = ' '; + } + + DrawString(char_buf, false, true); +} void FontManager::SetFontColor(u16 color) { g_font_color = color; diff --git a/stratosphere/fatal/source/fatal_font.hpp b/stratosphere/fatal/source/fatal_font.hpp index 5bd79dc14..acd1bca63 100644 --- a/stratosphere/fatal/source/fatal_font.hpp +++ b/stratosphere/fatal/source/fatal_font.hpp @@ -41,4 +41,5 @@ class FontManager { static void PrintFormat(const char *format, ...); static void PrintMonospaceU64(u64 x); static void PrintMonospaceU32(u32 x); + static void PrintMonospaceBlank(u32 width); }; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 94fa1bacb..66e39b69c 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -225,21 +225,40 @@ Result ShowFatalTask::ShowFatal() { /* Print GPRs. */ FontManager::SetFontSize(14.0f); - FontManager::PrintLine("General Purpose Registers"); + FontManager::Print("General Purpose Registers "); + { + FontManager::SetPosition(FontManager::GetX() + 2, FontManager::GetY()); + u32 x = FontManager::GetX(); + FontManager::Print("PC: "); + FontManager::SetPosition(x + 47, FontManager::GetY()); + } + if (this->ctx->cpu_ctx.is_aarch32) { + FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.pc); + } else { + FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.pc); + } + FontManager::PrintLine(""); + FontManager::SetPosition(32, FontManager::GetY()); FontManager::AddSpacingLines(0.5f); if (this->ctx->cpu_ctx.is_aarch32) { for (size_t i = 0; i < (NumAarch32Gprs / 2); i++) { u32 x = FontManager::GetX(); FontManager::PrintFormat("%s:", Aarch32GprNames[i]); FontManager::SetPosition(x + 47, FontManager::GetY()); - FontManager::Print("0x"); - FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.r[i]); + if (this->ctx->has_gprs[i]) { + FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.r[i]); + } else { + FontManager::PrintMonospaceBlank(8); + } FontManager::Print(" "); x = FontManager::GetX(); FontManager::PrintFormat("%s:", Aarch32GprNames[i + (NumAarch32Gprs / 2)]); FontManager::SetPosition(x + 47, FontManager::GetY()); - FontManager::Print("0x"); - FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.r[i + (NumAarch32Gprs / 2)]); + if (this->ctx->has_gprs[i + (NumAarch32Gprs / 2)]) { + FontManager::PrintMonospaceU32(this->ctx->cpu_ctx.aarch32_ctx.r[i + (NumAarch32Gprs / 2)]); + } else { + FontManager::PrintMonospaceBlank(8); + } if (i == (NumAarch32Gprs / 2) - 1) { FontManager::Print(" "); @@ -254,12 +273,20 @@ Result ShowFatalTask::ShowFatal() { u32 x = FontManager::GetX(); FontManager::PrintFormat("%s:", Aarch64GprNames[i]); FontManager::SetPosition(x + 47, FontManager::GetY()); - FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.x[i]); + if (this->ctx->has_gprs[i]) { + FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.x[i]); + } else { + FontManager::PrintMonospaceBlank(16); + } FontManager::Print(" "); x = FontManager::GetX(); FontManager::PrintFormat("%s:", Aarch64GprNames[i + (NumAarch64Gprs / 2)]); FontManager::SetPosition(x + 47, FontManager::GetY()); - FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.x[i + (NumAarch64Gprs / 2)]); + if (this->ctx->has_gprs[i + (NumAarch64Gprs / 2)]) { + FontManager::PrintMonospaceU64(this->ctx->cpu_ctx.aarch64_ctx.x[i + (NumAarch64Gprs / 2)]); + } else { + FontManager::PrintMonospaceBlank(16); + } if (i == (NumAarch64Gprs / 2) - 1) { FontManager::Print(" "); diff --git a/stratosphere/fatal/source/fatal_throw.cpp b/stratosphere/fatal/source/fatal_throw.cpp index dbd6eba3b..8dbd15e0e 100644 --- a/stratosphere/fatal/source/fatal_throw.cpp +++ b/stratosphere/fatal/source/fatal_throw.cpp @@ -19,6 +19,7 @@ #include "fatal_event_manager.hpp" #include "fatal_task.hpp" #include "fatal_config.hpp" +#include "fatal_debug.hpp" static bool g_thrown = false; @@ -34,17 +35,25 @@ static Result SetThrown() { Result ThrowFatalForSelf(u32 error) { u64 pid = 0; - FatalCpuContext ctx = {0}; svcGetProcessId(&pid, CUR_PROCESS_HANDLE); - return ThrowFatalImpl(error, pid, FatalType_ErrorScreen, &ctx); + return ThrowFatalImpl(error, pid, FatalType_ErrorScreen, nullptr); } Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx) { Result rc = 0; FatalThrowContext ctx; ctx.error_code = error; - ctx.cpu_ctx = *cpu_ctx; + if (cpu_ctx != nullptr) { + ctx.cpu_ctx = *cpu_ctx; + /* Assume if we're provided a context that it's complete. */ + for (u32 i = 0; i < NumAarch64Gprs; i++) { + ctx.has_gprs[i] = true; + } + } else { + std::memset(&ctx.cpu_ctx, 0, sizeof(ctx.cpu_ctx)); + cpu_ctx = &ctx.cpu_ctx; + } /* Get config. */ const FatalConfig *config = GetFatalConfig(); @@ -59,6 +68,13 @@ Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu title_id = cpu_ctx->aarch64_ctx.afsr0; } + /* Atmosphere extension: automatic debug info collection. */ + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200 && !ctx.is_creport) { + if ((cpu_ctx->is_aarch32 && cpu_ctx->aarch32_ctx.stack_trace_size == 0) || (!cpu_ctx->is_aarch32 && cpu_ctx->aarch32_ctx.stack_trace_size == 0)) { + TryCollectDebugInformation(&ctx, pid); + } + } + switch (policy) { case FatalType_ErrorReport: /* TODO: Don't write an error report. */ diff --git a/stratosphere/fatal/source/fatal_types.hpp b/stratosphere/fatal/source/fatal_types.hpp index 99be9c524..b0635ec9f 100644 --- a/stratosphere/fatal/source/fatal_types.hpp +++ b/stratosphere/fatal/source/fatal_types.hpp @@ -99,6 +99,7 @@ struct FatalCpuContext { struct FatalThrowContext { u32 error_code; bool is_creport; + bool has_gprs[NumAarch64Gprs]; FatalCpuContext cpu_ctx; }; @@ -129,6 +130,7 @@ static constexpr const char *Aarch64GprNames[NumAarch64Gprs] = { u8"X18", u8"X19", u8"X20", + u8"X21", u8"X22", u8"X23", u8"X24", @@ -139,7 +141,6 @@ static constexpr const char *Aarch64GprNames[NumAarch64Gprs] = { u8"FP", u8"LR", u8"SP", - u8"PC", }; static constexpr const char *Aarch32GprNames[NumAarch32Gprs] = { diff --git a/stratosphere/fatal/source/fatal_user.cpp b/stratosphere/fatal/source/fatal_user.cpp index 98b081494..520971bf5 100644 --- a/stratosphere/fatal/source/fatal_user.cpp +++ b/stratosphere/fatal/source/fatal_user.cpp @@ -21,19 +21,16 @@ #include "fatal_task.hpp" Result UserService::ThrowFatal(u32 error, PidDescriptor pid_desc) { - FatalCpuContext ctx = {0}; - return ThrowFatalImpl(error, pid_desc.pid, FatalType_ErrorReportAndErrorScreen, &ctx); + return ThrowFatalImpl(error, pid_desc.pid, FatalType_ErrorReportAndErrorScreen, nullptr); } Result UserService::ThrowFatalWithPolicy(u32 error, PidDescriptor pid_desc, FatalType policy) { - FatalCpuContext ctx = {0}; - return ThrowFatalImpl(error, pid_desc.pid, policy, &ctx); + return ThrowFatalImpl(error, pid_desc.pid, policy, nullptr); } Result UserService::ThrowFatalWithCpuContext(u32 error, PidDescriptor pid_desc, FatalType policy, InBuffer<u8> _ctx) { if (_ctx.num_elements < sizeof(FatalCpuContext)) { - FatalCpuContext ctx = {0}; - return ThrowFatalImpl(error, pid_desc.pid, policy, &ctx); + return ThrowFatalImpl(error, pid_desc.pid, policy, nullptr); } else { return ThrowFatalImpl(error, pid_desc.pid, policy, reinterpret_cast<FatalCpuContext *>(_ctx.buffer)); } From e5e9968d226c333b916ffecd37e52f85173cc7c1 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Wed, 14 Nov 2018 20:14:41 +0000 Subject: [PATCH 221/489] fusee: Remove obsolete MC carveout configuration. exosphere: Fix client access for MC carveout 2. --- exosphere/src/bootup.c | 125 +++-- exosphere/src/mc.c | 114 ++--- exosphere/src/mc.h | 610 ++++++++++++++++++++++-- exosphere/src/timers.h | 7 +- exosphere/src/warmboot_init.c | 2 +- exosphere/src/warmboot_main.c | 2 +- fusee/fusee-primary/src/hwinit.c | 18 +- fusee/fusee-primary/src/mc.c | 12 +- fusee/fusee-primary/src/mc.h | 112 +++++ fusee/fusee-primary/src/timers.h | 6 +- fusee/fusee-secondary/src/mc.c | 12 +- fusee/fusee-secondary/src/mc.h | 112 +++++ fusee/fusee-secondary/src/nxboot_iram.c | 3 +- fusee/fusee-secondary/src/timers.h | 6 +- 14 files changed, 957 insertions(+), 184 deletions(-) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 8709fd03c..82c009837 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -46,17 +46,16 @@ static bool g_has_booted_up = false; - void setup_dram_magic_numbers(void) { - /* TODO: Why does these DRAM write occur? */ + /* These DRAM writes test and set values for the GPU UCODE carveout. */ unsigned int target_fw = exosphere_get_target_firmware(); if (EXOSPHERE_TARGET_FIRMWARE_400 <= target_fw) { - (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; + (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; /* Access test value. */ flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000); if (EXOSPHERE_TARGET_FIRMWARE_600 <= target_fw) { - (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; + (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; /* SKU code. */ (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002; - (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; + (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; /* Tegra210 code. */ flush_dcache_range((void *)0x8005FF00, (void *)0x8005FF0C); } } @@ -87,31 +86,30 @@ void bootup_misc_mmio(void) { setup_dram_magic_numbers(); } - /* Todo: What? */ - MAKE_TIMERS_REG(0x1A4) = 0xF1E0; + /* Mark TMR5, TMR6, TMR7, TMR8, WDT0, WDT1, WDT2 and WDT3 as secure. */ + SHARED_TIMER_SECURE_CFG_0 = 0xF1E0; - FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 = 4; /* ACTIVE_CLUSTER_LOCK. */ - FLOW_CTLR_FLOW_DBG_QUAL_0 = 0x10000000; /* Enable FIQ2CCPLEX */ + FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 = 4; /* ACTIVE_CLUSTER_LOCK. */ + FLOW_CTLR_FLOW_DBG_QUAL_0 = 0x10000000; /* Enable FIQ2CCPLEX */ /* Disable Deep Power Down. */ APBDEV_PMC_DPD_ENABLE_0 = 0; - /* Setup MC. */ - /* TODO: What are these MC reg writes? */ - MAKE_MC_REG(0x984) = 1; - MAKE_MC_REG(0x648) = 0; - MAKE_MC_REG(0x64C) = 0; - MAKE_MC_REG(0x650) = 1; - MAKE_MC_REG(0x670) = 0; - MAKE_MC_REG(0x674) = 0; - MAKE_MC_REG(0x678) = 1; - MAKE_MC_REG(0x9A0) = 0; - MAKE_MC_REG(0x9A4) = 0; - MAKE_MC_REG(0x9A8) = 0; - MAKE_MC_REG(0x9AC) = 1; - MC_SECURITY_CFG0_0 = 0; - MC_SECURITY_CFG1_0 = 0; - MC_SECURITY_CFG3_0 = 3; + /* Setup MC carveouts. */ + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; + MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1; + MAKE_MC_REG(MC_SEC_CARVEOUT_BOM) = 0; + MAKE_MC_REG(MC_SEC_CARVEOUT_SIZE_MB) = 0; + MAKE_MC_REG(MC_SEC_CARVEOUT_REG_CTRL) = 1; + MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = 1; + MAKE_MC_REG(MC_SECURITY_CFG0) = 0; + MAKE_MC_REG(MC_SECURITY_CFG1) = 0; + MAKE_MC_REG(MC_SECURITY_CFG3) = 3; configure_default_carveouts(); /* Mark registers secure world only. */ @@ -142,12 +140,12 @@ void bootup_misc_mmio(void) { APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = sec_disable_2; } - /* reset Translation Enable Registers */ - MC_SMMU_TRANSLATION_ENABLE_0_0 = 0xFFFFFFFF; - MC_SMMU_TRANSLATION_ENABLE_1_0 = 0xFFFFFFFF; - MC_SMMU_TRANSLATION_ENABLE_2_0 = 0xFFFFFFFF; - MC_SMMU_TRANSLATION_ENABLE_3_0 = 0xFFFFFFFF; - MC_SMMU_TRANSLATION_ENABLE_4_0 = 0xFFFFFFFF; + /* Reset Translation Enable Registers. */ + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_0) = 0xFFFFFFFF; + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_1) = 0xFFFFFFFF; + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_2) = 0xFFFFFFFF; + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_3) = 0xFFFFFFFF; + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF; /* TODO: What are these MC reg writes? */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { @@ -157,7 +155,7 @@ void bootup_misc_mmio(void) { } MAKE_MC_REG(0x03C) = 0; - /* MISC registers*/ + /* MISC registers. */ MAKE_MC_REG(0x9E0) = 0; MAKE_MC_REG(0x9E4) = 0; MAKE_MC_REG(0x9E8) = 0; @@ -166,18 +164,18 @@ void bootup_misc_mmio(void) { MAKE_MC_REG(0x9F4) = 0; if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { - MC_SMMU_PTB_ASID_0 = 0; + MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0; } - MC_SMMU_PTB_DATA_0 = 0; - MC_SMMU_TLB_CONFIG_0 = 0x30000030; - MC_SMMU_PTC_CONFIG_0 = 0x2800003F; - (void)MC_SMMU_TLB_CONFIG_0; - MC_SMMU_PTC_FLUSH_0 = 0; - (void)MC_SMMU_TLB_CONFIG_0; - MC_SMMU_TLB_FLUSH_0 = 0; - (void)MC_SMMU_TLB_CONFIG_0; - MC_SMMU_CONFIG_0 = 1; /* enable SMMU */ - (void)MC_SMMU_TLB_CONFIG_0; + MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0; + MAKE_MC_REG(MC_SMMU_TLB_CONFIG) = 0x30000030; + MAKE_MC_REG(MC_SMMU_PTC_CONFIG) = 0x2800003F; + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); + MAKE_MC_REG(MC_SMMU_PTC_FLUSH) = 0; + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); + MAKE_MC_REG(MC_SMMU_TLB_FLUSH) = 0; + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); + MAKE_MC_REG(MC_SMMU_CONFIG) = 1; /* Enable SMMU. */ + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); /* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */ uint32_t reset_vec; @@ -200,13 +198,13 @@ void bootup_misc_mmio(void) { /* Setup FIQs. */ - /* And assign "se_operation_completed" to Interrupt 0x5A. */ intr_set_priority(INTERRUPT_ID_SECURITY_ENGINE, 0); intr_set_group(INTERRUPT_ID_SECURITY_ENGINE, 0); intr_set_enabled(INTERRUPT_ID_SECURITY_ENGINE, 1); intr_set_cpu_mask(INTERRUPT_ID_SECURITY_ENGINE, 8); intr_set_edge_level(INTERRUPT_ID_SECURITY_ENGINE, 0); + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { intr_set_priority(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); intr_set_group(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); @@ -225,10 +223,10 @@ void bootup_misc_mmio(void) { } g_has_booted_up = true; } else if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400) { - /* TODO: What are these MC reg writes? */ - MAKE_MC_REG(0x65C) = 0xFFFFF000; - MAKE_MC_REG(0x660) = 0; - MAKE_MC_REG(0x964) |= 1; + /* Disable AHB redirect. */ + MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; + MAKE_MC_REG(MC_IRAM_TOM) = 0; + MAKE_MC_REG(MC_IRAM_REG_CTRL) |= 1; CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 &= 0xFFF7FFFF; } } @@ -237,10 +235,11 @@ void setup_4x_mmio(void) { if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { configure_gpu_ucode_carveout(); } - /* TODO: What are these MC reg writes? */ - MAKE_MC_REG(0x65C) = 0xFFFFF000; - MAKE_MC_REG(0x660) = 0; - MAKE_MC_REG(0x964) |= 1; + + /* Disable AHB redirect. */ + MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; + MAKE_MC_REG(MC_IRAM_TOM) = 0; + MAKE_MC_REG(MC_IRAM_REG_CTRL) |= 1; CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 &= 0xFFF7FFFF; /* TODO: What are these PMC scratch writes? */ @@ -275,16 +274,16 @@ void setup_4x_mmio(void) { AHB_ARBITRATION_DISABLE_0 |= 2; /* Set SMMU for BPMP/APB-DMA to point to TZRAM. */ - MC_SMMU_PTB_ASID_0 = 1; - (void)MC_SMMU_TLB_CONFIG_0; - MC_SMMU_PTB_DATA_0 = 0x70012; - MC_SMMU_AVPC_ASID_0 = 0x80000001; - MC_SMMU_PPCS1_ASID_0 = 0x80000001; - (void)MC_SMMU_TLB_CONFIG_0; - MC_SMMU_PTC_FLUSH_0 = 0; - (void)MC_SMMU_TLB_CONFIG_0; - MC_SMMU_TLB_FLUSH_0 = 0; - (void)MC_SMMU_TLB_CONFIG_0; + MAKE_MC_REG(MC_SMMU_PTB_ASID) = 1; + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); + MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0x70012; + MAKE_MC_REG(MC_SMMU_AVPC_ASID) = 0x80000001; + MAKE_MC_REG(MC_SMMU_PPCS1_ASID) = 0x80000001; + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); + MAKE_MC_REG(MC_SMMU_PTC_FLUSH) = 0; + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); + MAKE_MC_REG(MC_SMMU_TLB_FLUSH) = 0; + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); /* Wait for the BPMP to halt. */ while ((FLOW_CTLR_HALT_COP_EVENTS_0 >> 29) != 2) { @@ -321,7 +320,7 @@ void setup_current_core_state(void) { __isb(); - SET_SYSREG(cntfrq_el0, MAKE_SYSCTR0_REG(0x20)); /* TODO: Reg name. */ + SET_SYSREG(cntfrq_el0, SYSCTR0_CNTFID0_0); SET_SYSREG(cnthctl_el2, 3ull); __isb(); diff --git a/exosphere/src/mc.c b/exosphere/src/mc.c index 97c9e5e45..332614c4a 100644 --- a/exosphere/src/mc.c +++ b/exosphere/src/mc.c @@ -39,23 +39,23 @@ volatile security_carveout_t *get_carveout_by_id(unsigned int carveout) { } void configure_gpu_ucode_carveout(void) { - /* Starting in 6.0.0, Carveout 2 is configured later on. */ + /* Starting in 6.0.0, Carveout 2 is configured later on and adds read permission to TSEC. */ /* This is a helper function to make this easier... */ volatile security_carveout_t *carveout = get_carveout_by_id(2); carveout->paddr_low = 0x80020000; carveout->paddr_high = 0; - carveout->size_big_pages = 2; /* 0x40000 */ - carveout->flags_0 = 0; - carveout->flags_1 = 0; - carveout->flags_2 = 0x3000000; - carveout->flags_3 = 0; - carveout->flags_4 = 0x300; - carveout->flags_5 = 0; - carveout->flags_6 = 0; - carveout->flags_7 = 0; - carveout->flags_8 = 0; - carveout->flags_9 = 0; - carveout->allowed_clients = 0x440167E; + carveout->size_big_pages = 2; /* 0x40000 */ + carveout->client_access_0 = 0; + carveout->client_access_1 = 0; + carveout->client_access_2 = (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) ? (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR) | BIT(CSR_TSECSRD)) : (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); + carveout->client_access_3 = 0; + carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); + carveout->client_force_internal_access_0 = 0; + carveout->client_force_internal_access_1 = 0; + carveout->client_force_internal_access_2 = 0; + carveout->client_force_internal_access_3 = 0; + carveout->client_force_internal_access_4 = 0; + carveout->config = 0x440167E; } void configure_default_carveouts(void) { @@ -64,17 +64,17 @@ void configure_default_carveouts(void) { carveout->paddr_low = 0; carveout->paddr_high = 0; carveout->size_big_pages = 0; - carveout->flags_0 = 0; - carveout->flags_1 = 0; - carveout->flags_2 = 0; - carveout->flags_3 = 0; - carveout->flags_4 = 0; - carveout->flags_5 = 0; - carveout->flags_6 = 0; - carveout->flags_7 = 0; - carveout->flags_8 = 0; - carveout->flags_9 = 0; - carveout->allowed_clients = 0x04000006; + carveout->client_access_0 = 0; + carveout->client_access_1 = 0; + carveout->client_access_2 = 0; + carveout->client_access_3 = 0; + carveout->client_access_4 = 0; + carveout->client_force_internal_access_0 = 0; + carveout->client_force_internal_access_1 = 0; + carveout->client_force_internal_access_2 = 0; + carveout->client_force_internal_access_3 = 0; + carveout->client_force_internal_access_4 = 0; + carveout->config = 0x4000006; /* Configure Carveout 2 (GPU UCODE) */ if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600) { @@ -86,17 +86,17 @@ void configure_default_carveouts(void) { carveout->paddr_low = 0; carveout->paddr_high = 0; carveout->size_big_pages = 0; - carveout->flags_0 = 0; - carveout->flags_1 = 0; - carveout->flags_2 = 0x3000000; - carveout->flags_3 = 0; - carveout->flags_4 = 0x300; - carveout->flags_5 = 0; - carveout->flags_6 = 0; - carveout->flags_7 = 0; - carveout->flags_8 = 0; - carveout->flags_9 = 0; - carveout->allowed_clients = 0x4401E7E; + carveout->client_access_0 = 0; + carveout->client_access_1 = 0; + carveout->client_access_2 = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); + carveout->client_access_3 = 0; + carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); + carveout->client_force_internal_access_0 = 0; + carveout->client_force_internal_access_1 = 0; + carveout->client_force_internal_access_2 = 0; + carveout->client_force_internal_access_3 = 0; + carveout->client_force_internal_access_4 = 0; + carveout->config = 0x4401E7E; /* Configure default Kernel carveouts based on 2.0.0+. */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { @@ -111,17 +111,17 @@ void configure_default_carveouts(void) { carveout->paddr_low = 0; carveout->paddr_high = 0; carveout->size_big_pages = 0; - carveout->flags_0 = 0; - carveout->flags_1 = 0; - carveout->flags_2 = 0; - carveout->flags_3 = 0; - carveout->flags_4 = 0; - carveout->flags_5 = 0; - carveout->flags_6 = 0; - carveout->flags_7 = 0; - carveout->flags_8 = 0; - carveout->flags_9 = 0; - carveout->allowed_clients = 0x4000006; + carveout->client_access_0 = 0; + carveout->client_access_1 = 0; + carveout->client_access_2 = 0; + carveout->client_access_3 = 0; + carveout->client_access_4 = 0; + carveout->client_force_internal_access_0 = 0; + carveout->client_force_internal_access_1 = 0; + carveout->client_force_internal_access_2 = 0; + carveout->client_force_internal_access_3 = 0; + carveout->client_force_internal_access_4 = 0; + carveout->config = 0x4000006; } } } @@ -138,15 +138,15 @@ void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint6 carveout->paddr_low = (uint32_t)(address & 0xFFFFFFFF); carveout->paddr_high = (uint32_t)(address >> 32); carveout->size_big_pages = (uint32_t)(size >> 17); - carveout->flags_0 = 0x70E3407F; - carveout->flags_1 = 0x1A620880; - carveout->flags_2 = 0x303C00; - carveout->flags_3 = 0xCF0830BB; - carveout->flags_4 = 0x3; - carveout->flags_5 = exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400 && carveout_id == 4 ? 0x8000 : 0; - carveout->flags_6 = exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400 && carveout_id == 4 ? 0x40000 : 0; - carveout->flags_7 = 0; - carveout->flags_8 = 0; - carveout->flags_9 = 0; - carveout->allowed_clients = 0x8B; + carveout->client_access_0 = (BIT(CSR_PTCR) | BIT(CSR_DISPLAY0A) | BIT(CSR_DISPLAY0AB) | BIT(CSR_DISPLAY0B) | BIT(CSR_DISPLAY0BB) | BIT(CSR_DISPLAY0C) | BIT(CSR_DISPLAY0CB) | BIT(CSR_AFIR) | BIT(CSR_DISPLAYHC) | BIT(CSR_DISPLAYHCB) | BIT(CSR_HDAR) | BIT(CSR_HOST1XDMAR) | BIT(CSR_HOST1XR) | BIT(CSR_NVENCSRD) | BIT(CSR_PPCSAHBDMAR) | BIT(CSR_PPCSAHBSLVR)); + carveout->client_access_1 = (BIT(CSR_MPCORER) | BIT(CSW_NVENCSWR) | BIT(CSW_AFIW) | BIT(CSW_HDAW) | BIT(CSW_HOST1XW) | BIT(CSW_MPCOREW) | BIT(CSW_PPCSAHBDMAW) | BIT(CSW_PPCSAHBSLVW)); + carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW) | BIT(CSR_TSECSRD) | BIT(CSW_TSECSWR)); + carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); + carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR)); + carveout->client_force_internal_access_0 = ((exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSR_AVPCARM7R) : 0; + carveout->client_force_internal_access_1 = ((exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSW_AVPCARM7W) : 0; + carveout->client_force_internal_access_2 = 0; + carveout->client_force_internal_access_3 = 0; + carveout->client_force_internal_access_4 = 0; + carveout->config = 0x8B; } diff --git a/exosphere/src/mc.h b/exosphere/src/mc.h index 22d8a971a..04e199e8d 100644 --- a/exosphere/src/mc.h +++ b/exosphere/src/mc.h @@ -27,60 +27,594 @@ static inline uintptr_t get_mc_base(void) { } #define MC_BASE (get_mc_base()) - #define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) -#define MC_SMMU_CONFIG_0 MAKE_MC_REG(0x010) -#define MC_SMMU_TLB_CONFIG_0 MAKE_MC_REG(0x014) -#define MC_SMMU_PTC_CONFIG_0 MAKE_MC_REG(0x018) -#define MC_SMMU_PTB_ASID_0 MAKE_MC_REG(0x01C) -#define MC_SMMU_PTB_DATA_0 MAKE_MC_REG(0x020) -#define MC_SMMU_TLB_FLUSH_0 MAKE_MC_REG(0x030) -#define MC_SMMU_PTC_FLUSH_0 MAKE_MC_REG(0x034) -#define MC_SMMU_AFI_ASID_0 MAKE_MC_REG(0x238) -#define MC_SMMU_AVPC_ASID_0 MAKE_MC_REG(0x23C) - -#define MC_SMMU_TRANSLATION_ENABLE_0_0 MAKE_MC_REG(0x228) -#define MC_SMMU_TRANSLATION_ENABLE_1_0 MAKE_MC_REG(0x22C) -#define MC_SMMU_TRANSLATION_ENABLE_2_0 MAKE_MC_REG(0x230) -#define MC_SMMU_TRANSLATION_ENABLE_3_0 MAKE_MC_REG(0x234) -#define MC_SMMU_TRANSLATION_ENABLE_4_0 MAKE_MC_REG(0xB98) - -#define MC_SMMU_PPCS1_ASID_0 MAKE_MC_REG(0x298) - -#define MC_SECURITY_CFG0_0 MAKE_MC_REG(0x070) -#define MC_SECURITY_CFG1_0 MAKE_MC_REG(0x074) -#define MC_SECURITY_CFG3_0 MAKE_MC_REG(0x9BC) +#define MC_INTSTATUS 0x0 +#define MC_INTMASK 0x4 +#define MC_ERR_STATUS 0x8 +#define MC_ERR_ADR 0xc +#define MC_SMMU_CONFIG 0x10 +#define MC_SMMU_TLB_CONFIG 0x14 +#define MC_SMMU_PTC_CONFIG 0x18 +#define MC_SMMU_PTB_ASID 0x1c +#define MC_SMMU_PTB_DATA 0x20 +#define MC_SMMU_TLB_FLUSH 0x30 +#define MC_SMMU_PTC_FLUSH 0x34 +#define MC_SMMU_AFI_ASID 0x238 +#define MC_SMMU_AVPC_ASID 0x23c +#define MC_SMMU_PPCS1_ASID 0x298 +#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 +#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c +#define MC_SMMU_TRANSLATION_ENABLE_2 0x230 +#define MC_SMMU_TRANSLATION_ENABLE_3 0x234 +#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98 +#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0 +#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4 +#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8 +#define MC_PCFIFO_CLIENT_CONFIG3 0xddc +#define MC_PCFIFO_CLIENT_CONFIG4 0xde0 +#define MC_EMEM_CFG 0x50 +#define MC_EMEM_ADR_CFG 0x54 +#define MC_EMEM_ADR_CFG_DEV0 0x58 +#define MC_EMEM_ADR_CFG_DEV1 0x5c +#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60 +#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64 +#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68 +#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c +#define MC_SECURITY_CFG0 0x70 +#define MC_SECURITY_CFG1 0x74 +#define MC_SECURITY_CFG3 0x9bc +#define MC_SECURITY_RSV 0x7c +#define MC_EMEM_ARB_CFG 0x90 +#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 +#define MC_EMEM_ARB_TIMING_RCD 0x98 +#define MC_EMEM_ARB_TIMING_RP 0x9c +#define MC_EMEM_ARB_TIMING_RC 0xa0 +#define MC_EMEM_ARB_TIMING_RAS 0xa4 +#define MC_EMEM_ARB_TIMING_FAW 0xa8 +#define MC_EMEM_ARB_TIMING_RRD 0xac +#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 +#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 +#define MC_EMEM_ARB_TIMING_R2R 0xb8 +#define MC_EMEM_ARB_TIMING_W2W 0xbc +#define MC_EMEM_ARB_TIMING_R2W 0xc0 +#define MC_EMEM_ARB_TIMING_W2R 0xc4 +#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0 +#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4 +#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0 +#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4 +#define MC_EMEM_ARB_DA_TURNS 0xd0 +#define MC_EMEM_ARB_DA_COVERS 0xd4 +#define MC_EMEM_ARB_MISC0 0xd8 +#define MC_EMEM_ARB_MISC1 0xdc +#define MC_EMEM_ARB_MISC2 0xc8 +#define MC_EMEM_ARB_RING1_THROTTLE 0xe0 +#define MC_EMEM_ARB_RING3_THROTTLE 0xe4 +#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0 +#define MC_EMEM_ARB_OVERRIDE 0xe8 +#define MC_EMEM_ARB_RSV 0xec +#define MC_CLKEN_OVERRIDE 0xf4 +#define MC_TIMING_CONTROL_DBG 0xf8 +#define MC_TIMING_CONTROL 0xfc +#define MC_STAT_CONTROL 0x100 +#define MC_STAT_STATUS 0x104 +#define MC_STAT_EMC_CLOCK_LIMIT 0x108 +#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c +#define MC_STAT_EMC_CLOCKS 0x110 +#define MC_STAT_EMC_CLOCKS_MSBS 0x114 +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118 +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158 +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20 +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24 +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198 +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8 +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28 +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c +#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0 +#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0 +#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120 +#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c +#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c +#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c +#define MC_STAT_EMC_SET0_COUNT 0x138 +#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c +#define MC_STAT_EMC_SET1_COUNT 0x178 +#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c +#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140 +#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144 +#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180 +#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184 +#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148 +#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c +#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188 +#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c +#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150 +#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190 +#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8 +#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc +#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8 +#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc +#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0 +#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0 +#define MC_CLIENT_HOTRESET_CTRL 0x200 +#define MC_CLIENT_HOTRESET_CTRL_1 0x970 +#define MC_CLIENT_HOTRESET_STATUS 0x204 +#define MC_CLIENT_HOTRESET_STATUS_1 0x974 +#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208 +#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c +#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210 +#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214 +#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94 +#define MC_EMEM_ARB_HYSTERESIS_0 0x218 +#define MC_EMEM_ARB_HYSTERESIS_1 0x21c +#define MC_EMEM_ARB_HYSTERESIS_2 0x220 +#define MC_EMEM_ARB_HYSTERESIS_3 0x224 +#define MC_EMEM_ARB_HYSTERESIS_4 0xb84 +#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0 +#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4 +#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8 +#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc +#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0 +#define MC_EMEM_ARB_DHYST_CTRL 0xbcc +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec +#define MC_RESERVED_RSV 0x3fc +#define MC_DISB_EXTRA_SNAP_LEVELS 0x408 +#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4 +#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0 +#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18 +#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08 +#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10 +#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c +#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40 +#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414 +#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc +#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c +#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14 +#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0 +#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac +#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c +#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48 +#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8 +#define MC_USBX_EXTRA_SNAP_LEVELS 0x404 +#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8 +#define MC_SD_EXTRA_SNAP_LEVELS 0xa04 +#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c +#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8 +#define MC_GK_EXTRA_SNAP_LEVELS 0xa00 +#define MC_VE2_EXTRA_SNAP_LEVELS 0x410 +#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44 +#define MC_VIDEO_PROTECT_BOM 0x648 +#define MC_VIDEO_PROTECT_SIZE_MB 0x64c +#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978 +#define MC_VIDEO_PROTECT_REG_CTRL 0x650 +#define MC_ERR_VPR_STATUS 0x654 +#define MC_ERR_VPR_ADR 0x658 +#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418 +#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590 +#define MC_IRAM_BOM 0x65c +#define MC_IRAM_TOM 0x660 +#define MC_IRAM_ADR_HI 0x980 +#define MC_IRAM_REG_CTRL 0x964 +#define MC_EMEM_CFG_ACCESS_CTRL 0x664 +#define MC_TZ_SECURITY_CTRL 0x668 +#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c +#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4 +#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc +#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8 +#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80 +#define MC_SEC_CARVEOUT_BOM 0x670 +#define MC_SEC_CARVEOUT_SIZE_MB 0x674 +#define MC_SEC_CARVEOUT_ADR_HI 0x9d4 +#define MC_SEC_CARVEOUT_REG_CTRL 0x678 +#define MC_ERR_SEC_STATUS 0x67c +#define MC_ERR_SEC_ADR 0x680 +#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684 +#define MC_STUTTER_CONTROL 0x688 +#define MC_RESERVED_RSV_1 0x958 +#define MC_DVFS_PIPE_SELECT 0x95c +#define MC_AHB_PTSA_MIN 0x4e0 +#define MC_AUD_PTSA_MIN 0x54c +#define MC_MLL_MPCORER_PTSA_RATE 0x44c +#define MC_RING2_PTSA_RATE 0x440 +#define MC_USBD_PTSA_RATE 0x530 +#define MC_USBX_PTSA_MIN 0x528 +#define MC_USBD_PTSA_MIN 0x534 +#define MC_APB_PTSA_MAX 0x4f0 +#define MC_JPG_PTSA_RATE 0x584 +#define MC_DIS_PTSA_MIN 0x420 +#define MC_AVP_PTSA_MAX 0x4fc +#define MC_AVP_PTSA_RATE 0x4f4 +#define MC_RING1_PTSA_MIN 0x480 +#define MC_DIS_PTSA_MAX 0x424 +#define MC_SD_PTSA_MAX 0x4d8 +#define MC_MSE_PTSA_RATE 0x4c4 +#define MC_VICPC_PTSA_MIN 0x558 +#define MC_PCX_PTSA_MAX 0x4b4 +#define MC_ISP_PTSA_RATE 0x4a0 +#define MC_A9AVPPC_PTSA_MIN 0x48c +#define MC_RING2_PTSA_MAX 0x448 +#define MC_AUD_PTSA_RATE 0x548 +#define MC_HOST_PTSA_MIN 0x51c +#define MC_MLL_MPCORER_PTSA_MAX 0x454 +#define MC_SD_PTSA_MIN 0x4d4 +#define MC_RING1_PTSA_RATE 0x47c +#define MC_JPG_PTSA_MIN 0x588 +#define MC_HDAPC_PTSA_MIN 0x62c +#define MC_AVP_PTSA_MIN 0x4f8 +#define MC_JPG_PTSA_MAX 0x58c +#define MC_VE_PTSA_MAX 0x43c +#define MC_DFD_PTSA_MAX 0x63c +#define MC_VICPC_PTSA_RATE 0x554 +#define MC_GK_PTSA_MAX 0x544 +#define MC_VICPC_PTSA_MAX 0x55c +#define MC_SDM_PTSA_MAX 0x624 +#define MC_SAX_PTSA_RATE 0x4b8 +#define MC_PCX_PTSA_MIN 0x4b0 +#define MC_APB_PTSA_MIN 0x4ec +#define MC_GK2_PTSA_MIN 0x614 +#define MC_PCX_PTSA_RATE 0x4ac +#define MC_RING1_PTSA_MAX 0x484 +#define MC_HDAPC_PTSA_RATE 0x628 +#define MC_MLL_MPCORER_PTSA_MIN 0x450 +#define MC_GK2_PTSA_MAX 0x618 +#define MC_AUD_PTSA_MAX 0x550 +#define MC_GK2_PTSA_RATE 0x610 +#define MC_ISP_PTSA_MAX 0x4a8 +#define MC_DISB_PTSA_RATE 0x428 +#define MC_VE2_PTSA_MAX 0x49c +#define MC_DFD_PTSA_MIN 0x638 +#define MC_FTOP_PTSA_RATE 0x50c +#define MC_A9AVPPC_PTSA_RATE 0x488 +#define MC_VE2_PTSA_MIN 0x498 +#define MC_USBX_PTSA_MAX 0x52c +#define MC_DIS_PTSA_RATE 0x41c +#define MC_USBD_PTSA_MAX 0x538 +#define MC_A9AVPPC_PTSA_MAX 0x490 +#define MC_USBX_PTSA_RATE 0x524 +#define MC_FTOP_PTSA_MAX 0x514 +#define MC_HDAPC_PTSA_MAX 0x630 +#define MC_SD_PTSA_RATE 0x4d0 +#define MC_DFD_PTSA_RATE 0x634 +#define MC_FTOP_PTSA_MIN 0x510 +#define MC_SDM_PTSA_RATE 0x61c +#define MC_AHB_PTSA_RATE 0x4dc +#define MC_SMMU_SMMU_PTSA_MAX 0x460 +#define MC_RING2_PTSA_MIN 0x444 +#define MC_SDM_PTSA_MIN 0x620 +#define MC_APB_PTSA_RATE 0x4e8 +#define MC_MSE_PTSA_MIN 0x4c8 +#define MC_HOST_PTSA_RATE 0x518 +#define MC_VE_PTSA_RATE 0x434 +#define MC_AHB_PTSA_MAX 0x4e4 +#define MC_SAX_PTSA_MIN 0x4bc +#define MC_SMMU_SMMU_PTSA_MIN 0x45c +#define MC_ISP_PTSA_MIN 0x4a4 +#define MC_HOST_PTSA_MAX 0x520 +#define MC_SAX_PTSA_MAX 0x4c0 +#define MC_VE_PTSA_MIN 0x438 +#define MC_GK_PTSA_MIN 0x540 +#define MC_MSE_PTSA_MAX 0x4cc +#define MC_DISB_PTSA_MAX 0x430 +#define MC_DISB_PTSA_MIN 0x42c +#define MC_SMMU_SMMU_PTSA_RATE 0x458 +#define MC_VE2_PTSA_RATE 0x494 +#define MC_GK_PTSA_RATE 0x53c +#define MC_PTSA_GRANT_DECREMENT 0x960 +#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4 +#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0 +#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380 +#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384 +#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc +#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8 +#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370 +#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0 +#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374 +#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8 +#define MC_LATENCY_ALLOWANCE_VIC_0 0x394 +#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8 +#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8 +#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc +#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390 +#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694 +#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348 +#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c +#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344 +#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0 +#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698 +#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec +#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0 +#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4 +#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8 +#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4 +#define MC_LATENCY_ALLOWANCE_HC_1 0x314 +#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0 +#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4 +#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c +#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec +#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320 +#define MC_LATENCY_ALLOWANCE_VI2_0 0x398 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4 +#define MC_LATENCY_ALLOWANCE_SATA_0 0x350 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690 +#define MC_LATENCY_ALLOWANCE_HC_0 0x310 +#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8 +#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac +#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4 +#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388 +#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328 +#define MC_LATENCY_ALLOWANCE_HDA_0 0x318 +#define MC_MIN_LENGTH_APE_0 0xb34 +#define MC_MIN_LENGTH_DCB_2 0x8a8 +#define MC_MIN_LENGTH_A9AVP_0 0x950 +#define MC_MIN_LENGTH_TSEC_0 0x93c +#define MC_MIN_LENGTH_DC_1 0x898 +#define MC_MIN_LENGTH_AXIAP_0 0x94c +#define MC_MIN_LENGTH_ISP2B_0 0x930 +#define MC_MIN_LENGTH_VI2_0 0x944 +#define MC_MIN_LENGTH_DCB_0 0x8a0 +#define MC_MIN_LENGTH_DCB_1 0x8a4 +#define MC_MIN_LENGTH_PPCS_1 0x8f4 +#define MC_MIN_LENGTH_NVJPG_0 0xb3c +#define MC_MIN_LENGTH_HDA_0 0x8c4 +#define MC_MIN_LENGTH_NVENC_0 0x8d4 +#define MC_MIN_LENGTH_SDMMC_0 0xb18 +#define MC_MIN_LENGTH_ISP2B_1 0x934 +#define MC_MIN_LENGTH_HC_1 0x8c0 +#define MC_MIN_LENGTH_DC_3 0xb20 +#define MC_MIN_LENGTH_AVPC_0 0x890 +#define MC_MIN_LENGTH_VIC_0 0x940 +#define MC_MIN_LENGTH_ISP2_0 0x91c +#define MC_MIN_LENGTH_HC_0 0x8bc +#define MC_MIN_LENGTH_SE_0 0xb38 +#define MC_MIN_LENGTH_NVDEC_0 0xb30 +#define MC_MIN_LENGTH_SATA_0 0x8fc +#define MC_MIN_LENGTH_DC_0 0x894 +#define MC_MIN_LENGTH_XUSB_1 0x92c +#define MC_MIN_LENGTH_DC_2 0x89c +#define MC_MIN_LENGTH_SDMMCAA_0 0xb14 +#define MC_MIN_LENGTH_GPU_0 0xb04 +#define MC_MIN_LENGTH_ETR_0 0xb44 +#define MC_MIN_LENGTH_AFI_0 0x88c +#define MC_MIN_LENGTH_PPCS_0 0x8f0 +#define MC_MIN_LENGTH_ISP2_1 0x920 +#define MC_MIN_LENGTH_XUSB_0 0x928 +#define MC_MIN_LENGTH_MPCORE_0 0x8cc +#define MC_MIN_LENGTH_TSECB_0 0xb48 +#define MC_MIN_LENGTH_SDMMCA_0 0xb10 +#define MC_MIN_LENGTH_GPU2_0 0xb40 +#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c +#define MC_MIN_LENGTH_PTC_0 0x8f8 +#define MC_EMEM_ARB_OVERRIDE_1 0x968 +#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984 +#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988 +#define MC_EMEM_ARB_STATS_0 0x990 +#define MC_EMEM_ARB_STATS_1 0x994 +#define MC_MTS_CARVEOUT_BOM 0x9a0 +#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4 +#define MC_MTS_CARVEOUT_ADR_HI 0x9a8 +#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac +#define MC_ERR_MTS_STATUS 0x9b0 +#define MC_ERR_MTS_ADR 0x9b4 +#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 +#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74 +#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10 +#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c +#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4 +#define MC_SECURITY_CARVEOUT2_CFG0 0xc58 +#define MC_SECURITY_CARVEOUT1_CFG0 0xc08 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84 +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68 +#define MC_SECURITY_CARVEOUT3_BOM 0xcac +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60 +#define MC_SECURITY_CARVEOUT3_CFG0 0xca8 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88 +#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64 +#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50 +#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14 +#define MC_SECURITY_CARVEOUT1_BOM 0xc0c +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4 +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c +#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8 +#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60 +#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80 +#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc +#define MC_SECURITY_CARVEOUT4_BOM 0xcfc +#define MC_SECURITY_CARVEOUT5_CFG0 0xd48 +#define MC_SECURITY_CARVEOUT2_BOM 0xc5c +#define MC_SECURITY_CARVEOUT5_BOM 0xd4c +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0 +#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08 +#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 +#define MC_DA_CONFIG0 0x9dc +/* Memory Controller clients */ +#define CLIENT_ACCESS_NUM_CLIENTS 32 +typedef enum { + /* _ACCESS0 */ + CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + + /* _ACCESS1 */ + CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + + /* _ACCESS2 */ + CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + + /* _ACCESS3 */ + CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + + /* _ACCESS4 */ + CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4)) +} McClient; +/* Memory Controller carveouts */ #define CARVEOUT_ID_MIN 1 #define CARVEOUT_ID_MAX 5 - #define KERNEL_CARVEOUT_SIZE_MAX 0x1FFE0000 - typedef struct { - uint32_t allowed_clients; + uint32_t config; uint32_t paddr_low; uint32_t paddr_high; uint32_t size_big_pages; - uint32_t flags_0; - uint32_t flags_1; - uint32_t flags_2; - uint32_t flags_3; - uint32_t flags_4; - uint32_t flags_5; - uint32_t flags_6; - uint32_t flags_7; - uint32_t flags_8; - uint32_t flags_9; + uint32_t client_access_0; + uint32_t client_access_1; + uint32_t client_access_2; + uint32_t client_access_3; + uint32_t client_access_4; + uint32_t client_force_internal_access_0; + uint32_t client_force_internal_access_1; + uint32_t client_force_internal_access_2; + uint32_t client_force_internal_access_3; + uint32_t client_force_internal_access_4; uint8_t padding[0x18]; } security_carveout_t; - volatile security_carveout_t *get_carveout_by_id(unsigned int carveout); void configure_default_carveouts(void); void configure_gpu_ucode_carveout(void); void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint64_t size); - -#endif +#endif \ No newline at end of file diff --git a/exosphere/src/timers.h b/exosphere/src/timers.h index 6d5f9f6ae..0cc88c050 100644 --- a/exosphere/src/timers.h +++ b/exosphere/src/timers.h @@ -27,10 +27,11 @@ static inline uintptr_t get_timers_base(void) { } #define TIMERS_BASE (get_timers_base()) - #define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) -#define TIMERUS_CNTR_1US_0 MAKE_REG32(TIMERS_BASE + 0x10) +#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) +#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0) +#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4) typedef struct { uint32_t CONFIG; @@ -41,7 +42,7 @@ typedef struct { #define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) #define WDT_REBOOT_PATTERN 0xC45A -#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8*n) +#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n) void wait(uint32_t microseconds); diff --git a/exosphere/src/warmboot_init.c b/exosphere/src/warmboot_init.c index 5b366aa60..678879aba 100644 --- a/exosphere/src/warmboot_init.c +++ b/exosphere/src/warmboot_init.c @@ -199,7 +199,7 @@ void warmboot_init(void) { invalidate_icache_all(); /* On warmboot (not cpu_on) only */ - if (MC_SECURITY_CFG3_0 == 0) { + if (MC_SECURITY_CFG3 == 0) { init_dma_controllers(g_exosphere_target_firmware_for_init); } diff --git a/exosphere/src/warmboot_main.c b/exosphere/src/warmboot_main.c index 95895ba80..04f1afb03 100644 --- a/exosphere/src/warmboot_main.c +++ b/exosphere/src/warmboot_main.c @@ -54,7 +54,7 @@ void __attribute__((noreturn)) warmboot_main(void) { identity_unmap_iram_cd_tzram(); /* On warmboot (not cpu_on) only */ - if (MC_SECURITY_CFG3_0 == 0) { + if (MC_SECURITY_CFG3 == 0) { if (!configitem_is_retail()) { /* TODO: uart_log("OHAYO"); */ } diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index de4df1954..ef01ec23c 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -213,8 +213,8 @@ void nx_hwinit() APB_MISC_PP_PINMUX_GLOBAL_0 = 0; /* Configure GPIOs. */ - /* NOTE: In 3.x+ part of the GPIO configuration is skipped if the unit is SDEV. */ - /* NOTE: In 6.x+ the GPIO configuration's order was changed a bit. */ + /* NOTE: [3.0.0+] Part of the GPIO configuration is skipped if the unit is SDEV. */ + /* NOTE: [6.0.0+] The GPIO configuration's order was changed a bit. */ config_gpios(); /* Uncomment for UART debugging. */ @@ -233,14 +233,14 @@ void nx_hwinit() clkrst_reboot(CARDEVICE_I2C5); /* Reboot SE. */ - /* NOTE: In 4.x+ this was removed. */ + /* NOTE: [4.0.0+] This was removed. */ clkrst_reboot(CARDEVICE_SE); /* Reboot unknown device. */ clkrst_reboot(CARDEVICE_UNK); /* Initialize I2C1. */ - /* NOTE: In 6.x+ this was moved to after the PMIC is configured. */ + /* NOTE: [6.0.0+] This was moved to after the PMIC is configured. */ i2c_init(I2C_1); /* Initialize I2C5. */ @@ -268,11 +268,9 @@ void nx_hwinit() val = 0x1B; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD3, &val, 1); - /* TODO: In 3.x+ this was added. */ - /* + /* NOTE: [3.0.0+] This was added. */ val = 0x22; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_GPIO3, &val, 1); - */ /* TODO: In 3.x+, if the unit is SDEV, the MBLPD bit is set. */ /* @@ -286,15 +284,15 @@ void nx_hwinit() i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD0, &val, 1); /* Configure and lock PMC scratch registers. */ - /* NOTE: In 4.x+ this was removed. */ + /* NOTE: [4.0.0+] This was removed. */ config_pmc_scratch(); /* Set super clock burst policy. */ car->sclk_brst_pol = ((car->sclk_brst_pol & 0xFFFF8888) | 0x3333); /* Configure memory controller carveouts. */ - /* NOTE: In 4.x+ this was removed. */ - mc_config_carveout(); + /* NOTE: [4.0.0+] This is now done in the Secure Monitor. */ + /* mc_config_carveout(); */ /* Initialize SDRAM. */ sdram_init(); diff --git a/fusee/fusee-primary/src/mc.c b/fusee/fusee-primary/src/mc.c index d89454c8f..4cacac363 100644 --- a/fusee/fusee-primary/src/mc.c +++ b/fusee/fusee-primary/src/mc.c @@ -31,6 +31,7 @@ void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock) void mc_config_carveout() { *(volatile uint32_t *)0x8005FFFC = 0xC0EDBBCC; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0; @@ -43,6 +44,7 @@ void mc_config_carveout() MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = 0; MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = 1; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM_HI) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0; @@ -63,15 +65,16 @@ void mc_config_carveout() MAKE_MC_REG(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0; - MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0x3000000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0; - MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0x300; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CFG0) = 0x4401E7E; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM_HI) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0; @@ -86,6 +89,7 @@ void mc_config_carveout() MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CFG0) = 0x8F; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM_HI) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0; @@ -109,9 +113,9 @@ void mc_config_carveout_finalize() MAKE_MC_REG(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2; MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0; - MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = 0x3000000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0; - MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = 0x300; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; diff --git a/fusee/fusee-primary/src/mc.h b/fusee/fusee-primary/src/mc.h index 2a167299c..53ecd9c67 100644 --- a/fusee/fusee-primary/src/mc.h +++ b/fusee/fusee-primary/src/mc.h @@ -29,6 +29,21 @@ #define MC_INTMASK 0x4 #define MC_ERR_STATUS 0x8 #define MC_ERR_ADR 0xc +#define MC_SMMU_CONFIG 0x10 +#define MC_SMMU_TLB_CONFIG 0x14 +#define MC_SMMU_PTC_CONFIG 0x18 +#define MC_SMMU_PTB_ASID 0x1c +#define MC_SMMU_PTB_DATA 0x20 +#define MC_SMMU_TLB_FLUSH 0x30 +#define MC_SMMU_PTC_FLUSH 0x34 +#define MC_SMMU_AFI_ASID 0x238 +#define MC_SMMU_AVPC_ASID 0x23c +#define MC_SMMU_PPCS1_ASID 0x298 +#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 +#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c +#define MC_SMMU_TRANSLATION_ENABLE_2 0x230 +#define MC_SMMU_TRANSLATION_ENABLE_3 0x234 +#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98 #define MC_PCFIFO_CLIENT_CONFIG0 0xdd0 #define MC_PCFIFO_CLIENT_CONFIG1 0xdd4 #define MC_PCFIFO_CLIENT_CONFIG2 0xdd8 @@ -474,6 +489,103 @@ #define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 #define MC_DA_CONFIG0 0x9dc +/* Memory Controller clients */ +#define CLIENT_ACCESS_NUM_CLIENTS 32 +typedef enum { + /* _ACCESS0 */ + CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + + /* _ACCESS1 */ + CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + + /* _ACCESS2 */ + CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + + /* _ACCESS3 */ + CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + + /* _ACCESS4 */ + CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4)) +} McClient; + void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock); void mc_config_carveout(); void mc_config_carveout_finalize(); diff --git a/fusee/fusee-primary/src/timers.h b/fusee/fusee-primary/src/timers.h index 418e5928d..1c2be85d7 100644 --- a/fusee/fusee-primary/src/timers.h +++ b/fusee/fusee-primary/src/timers.h @@ -21,11 +21,15 @@ #define TIMERS_BASE 0x60005000 #define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) + #define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) #define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14) +#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0) +#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4) #define RTC_BASE 0x7000E000 #define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) + #define RTC_SECONDS MAKE_RTC_REG(0x08) #define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C) #define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10) @@ -39,7 +43,7 @@ typedef struct { #define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) #define WDT_REBOOT_PATTERN 0xC45A -#define GET_WDT_REBOOT_CFG_REG(n) MAKE_TIMERS_REG(0x60 + 0x8 * n) +#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n) void wait(uint32_t microseconds); diff --git a/fusee/fusee-secondary/src/mc.c b/fusee/fusee-secondary/src/mc.c index d89454c8f..4cacac363 100644 --- a/fusee/fusee-secondary/src/mc.c +++ b/fusee/fusee-secondary/src/mc.c @@ -31,6 +31,7 @@ void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock) void mc_config_carveout() { *(volatile uint32_t *)0x8005FFFC = 0xC0EDBBCC; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0; @@ -43,6 +44,7 @@ void mc_config_carveout() MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = 0; MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = 1; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM_HI) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0; @@ -63,15 +65,16 @@ void mc_config_carveout() MAKE_MC_REG(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0; - MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0x3000000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0; - MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0x300; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CFG0) = 0x4401E7E; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM_HI) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0; @@ -86,6 +89,7 @@ void mc_config_carveout() MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CFG0) = 0x8F; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM_HI) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0; @@ -109,9 +113,9 @@ void mc_config_carveout_finalize() MAKE_MC_REG(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2; MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0; - MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = 0x3000000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0; - MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = 0x300; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; diff --git a/fusee/fusee-secondary/src/mc.h b/fusee/fusee-secondary/src/mc.h index 2a167299c..53ecd9c67 100644 --- a/fusee/fusee-secondary/src/mc.h +++ b/fusee/fusee-secondary/src/mc.h @@ -29,6 +29,21 @@ #define MC_INTMASK 0x4 #define MC_ERR_STATUS 0x8 #define MC_ERR_ADR 0xc +#define MC_SMMU_CONFIG 0x10 +#define MC_SMMU_TLB_CONFIG 0x14 +#define MC_SMMU_PTC_CONFIG 0x18 +#define MC_SMMU_PTB_ASID 0x1c +#define MC_SMMU_PTB_DATA 0x20 +#define MC_SMMU_TLB_FLUSH 0x30 +#define MC_SMMU_PTC_FLUSH 0x34 +#define MC_SMMU_AFI_ASID 0x238 +#define MC_SMMU_AVPC_ASID 0x23c +#define MC_SMMU_PPCS1_ASID 0x298 +#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 +#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c +#define MC_SMMU_TRANSLATION_ENABLE_2 0x230 +#define MC_SMMU_TRANSLATION_ENABLE_3 0x234 +#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98 #define MC_PCFIFO_CLIENT_CONFIG0 0xdd0 #define MC_PCFIFO_CLIENT_CONFIG1 0xdd4 #define MC_PCFIFO_CLIENT_CONFIG2 0xdd8 @@ -474,6 +489,103 @@ #define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 #define MC_DA_CONFIG0 0x9dc +/* Memory Controller clients */ +#define CLIENT_ACCESS_NUM_CLIENTS 32 +typedef enum { + /* _ACCESS0 */ + CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + + /* _ACCESS1 */ + CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + + /* _ACCESS2 */ + CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + + /* _ACCESS3 */ + CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + + /* _ACCESS4 */ + CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4)) +} McClient; + void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock); void mc_config_carveout(); void mc_config_carveout_finalize(); diff --git a/fusee/fusee-secondary/src/nxboot_iram.c b/fusee/fusee-secondary/src/nxboot_iram.c index 5e0a0ee6c..18745ba45 100644 --- a/fusee/fusee-secondary/src/nxboot_iram.c +++ b/fusee/fusee-secondary/src/nxboot_iram.c @@ -41,7 +41,8 @@ void nxboot_finish(uint32_t boot_memaddr) { } /* Finalize the GPU UCODE carveout. */ - mc_config_carveout_finalize(); + /* NOTE: [4.0.0+] This is now done in the Secure Monitor. */ + /* mc_config_carveout_finalize(); */ /* Lock AES keyslots. */ for (uint32_t i = 0; i < 16; i++) diff --git a/fusee/fusee-secondary/src/timers.h b/fusee/fusee-secondary/src/timers.h index 418e5928d..1c2be85d7 100644 --- a/fusee/fusee-secondary/src/timers.h +++ b/fusee/fusee-secondary/src/timers.h @@ -21,11 +21,15 @@ #define TIMERS_BASE 0x60005000 #define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) + #define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) #define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14) +#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0) +#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4) #define RTC_BASE 0x7000E000 #define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) + #define RTC_SECONDS MAKE_RTC_REG(0x08) #define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C) #define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10) @@ -39,7 +43,7 @@ typedef struct { #define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) #define WDT_REBOOT_PATTERN 0xC45A -#define GET_WDT_REBOOT_CFG_REG(n) MAKE_TIMERS_REG(0x60 + 0x8 * n) +#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n) void wait(uint32_t microseconds); From 7c61e935ee2139667f1338ca1e216a665801ca31 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Wed, 14 Nov 2018 21:12:36 +0000 Subject: [PATCH 222/489] exosphere: Fix virtual mapping of MC_SECURITY_CFG3. Allow DRAM magic test value to be written on < 4.0.0. --- exosphere/src/bootup.c | 18 ++++++++---------- exosphere/src/mc.h | 3 +++ exosphere/src/warmboot_init.c | 2 +- exosphere/src/warmboot_main.c | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 82c009837..e2bbbbee3 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -49,15 +49,13 @@ static bool g_has_booted_up = false; void setup_dram_magic_numbers(void) { /* These DRAM writes test and set values for the GPU UCODE carveout. */ unsigned int target_fw = exosphere_get_target_firmware(); - if (EXOSPHERE_TARGET_FIRMWARE_400 <= target_fw) { - (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; /* Access test value. */ - flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000); - if (EXOSPHERE_TARGET_FIRMWARE_600 <= target_fw) { - (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; /* SKU code. */ - (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002; - (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; /* Tegra210 code. */ - flush_dcache_range((void *)0x8005FF00, (void *)0x8005FF0C); - } + (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; /* Access test value. */ + flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000); + if (EXOSPHERE_TARGET_FIRMWARE_600 <= target_fw) { + (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; /* SKU code. */ + (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002; + (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; /* Tegra210 code. */ + flush_dcache_range((void *)0x8005FF00, (void *)0x8005FF0C); } __dsb_sy(); } @@ -82,7 +80,7 @@ void bootup_misc_mmio(void) { se_generate_random_key(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY); se_generate_srk(KEYSLOT_SWITCH_SRKGENKEY); - if (!g_has_booted_up && EXOSPHERE_TARGET_FIRMWARE_600 > exosphere_get_target_firmware() && exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (!g_has_booted_up && (EXOSPHERE_TARGET_FIRMWARE_600 > exosphere_get_target_firmware())) { setup_dram_magic_numbers(); } diff --git a/exosphere/src/mc.h b/exosphere/src/mc.h index 04e199e8d..6d467d655 100644 --- a/exosphere/src/mc.h +++ b/exosphere/src/mc.h @@ -493,6 +493,9 @@ static inline uintptr_t get_mc_base(void) { #define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 #define MC_DA_CONFIG0 0x9dc +/* Virtual aliases */ +#define VIRT_MC_SECURITY_CFG3 MAKE_MC_REG(MC_SECURITY_CFG3) + /* Memory Controller clients */ #define CLIENT_ACCESS_NUM_CLIENTS 32 typedef enum { diff --git a/exosphere/src/warmboot_init.c b/exosphere/src/warmboot_init.c index 678879aba..6a22294a4 100644 --- a/exosphere/src/warmboot_init.c +++ b/exosphere/src/warmboot_init.c @@ -199,7 +199,7 @@ void warmboot_init(void) { invalidate_icache_all(); /* On warmboot (not cpu_on) only */ - if (MC_SECURITY_CFG3 == 0) { + if (VIRT_MC_SECURITY_CFG3 == 0) { init_dma_controllers(g_exosphere_target_firmware_for_init); } diff --git a/exosphere/src/warmboot_main.c b/exosphere/src/warmboot_main.c index 04f1afb03..8ee15c4fd 100644 --- a/exosphere/src/warmboot_main.c +++ b/exosphere/src/warmboot_main.c @@ -54,7 +54,7 @@ void __attribute__((noreturn)) warmboot_main(void) { identity_unmap_iram_cd_tzram(); /* On warmboot (not cpu_on) only */ - if (MC_SECURITY_CFG3 == 0) { + if (VIRT_MC_SECURITY_CFG3 == 0) { if (!configitem_is_retail()) { /* TODO: uart_log("OHAYO"); */ } From 8054b2d219bbaedb1dc4aa941455e8e09c106313 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 14 Nov 2018 14:13:31 -0800 Subject: [PATCH 223/489] Fatal: save auto-debug info to SD card. --- .../creport/source/creport_crash_report.cpp | 2 +- stratosphere/fatal/fatal.json | 2 +- stratosphere/fatal/source/fatal_debug.cpp | 11 ++ stratosphere/fatal/source/fatal_main.cpp | 19 ++- .../fatal/source/fatal_task_error_report.cpp | 112 +++++++++++++++++- .../fatal/source/fatal_task_error_report.hpp | 4 + stratosphere/fatal/source/fatal_throw.cpp | 4 +- stratosphere/fatal/source/fatal_types.hpp | 3 + 8 files changed, 151 insertions(+), 6 deletions(-) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 6f2a2e62f..819655d11 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -257,7 +257,7 @@ void CrashReport::EnsureReportDirectories() { } void CrashReport::SaveReport() { - /* TODO: Save the report to the SD card. */ + /* Save the report to the SD card. */ char report_path[FS_MAX_PATH]; /* Ensure path exists. */ diff --git a/stratosphere/fatal/fatal.json b/stratosphere/fatal/fatal.json index 61f6ca88f..76bce7e4f 100644 --- a/stratosphere/fatal/fatal.json +++ b/stratosphere/fatal/fatal.json @@ -15,7 +15,7 @@ "permissions": "0xFFFFFFFFFFFFFFFF" }, "service_access": ["bpc", "bpc:c", "erpt:c", "fsp-srv", "gpio", "i2c", "lbl", "lm", "nvdrv:s", "pcv", "pl:u", "pm:info", "psm", "set", "set:sys", "spsm", "vi:m", "vi:s"], - "service_host": ["fatal:p", "fatal:u"], + "service_host": ["fatal:p", "fatal:u", "time:s"], "kernel_capabilities": [{ "type": "kernel_flags", "value": { diff --git a/stratosphere/fatal/source/fatal_debug.cpp b/stratosphere/fatal/source/fatal_debug.cpp index 46ed8df13..320f1a277 100644 --- a/stratosphere/fatal/source/fatal_debug.cpp +++ b/stratosphere/fatal/source/fatal_debug.cpp @@ -146,6 +146,7 @@ void TryCollectDebugInformation(FatalThrowContext *ctx, u64 pid) { while (R_SUCCEEDED(svcGetDebugEvent((u8 *)&d, debug_handle))) { if (d.type == DebugEventType::AttachProcess) { ctx->cpu_ctx.is_aarch32 = (d.info.attach_process.flags & 1) == 0; + memcpy(ctx->proc_name, d.info.attach_process.name, sizeof(d.info.attach_process.name)); got_attach_process = true; } else if (d.type == DebugEventType::AttachThread) { thread_id_to_tls[d.info.attach_thread.thread_id] = d.info.attach_thread.tls_address; @@ -228,6 +229,16 @@ void TryCollectDebugInformation(FatalThrowContext *ctx, u64 pid) { cur_fp = cur_frame.fp; } + /* Try to read up to 0x100 of stack. */ + for (size_t sz = 0x100; sz > 0; sz -= 0x10) { + if (IsAddressReadable(debug_handle, ctx->cpu_ctx.aarch64_ctx.sp, sz, nullptr)) { + if (R_SUCCEEDED(svcReadDebugProcessMemory(ctx->stack_dump, debug_handle, ctx->cpu_ctx.aarch64_ctx.sp, sz))) { + ctx->stack_dump_size = sz; + } + break; + } + } + /* Parse the starting address. */ { u64 guess = thread_ctx.pc.x; diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 292258a73..7790e85b7 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -35,7 +35,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x280000 + #define INNER_HEAP_SIZE 0x2A0000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -118,11 +118,28 @@ void __appInit(void) { std::abort(); } + rc = fsInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + + rc = fsInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + + rc = fsdevMountSdmc(); + if (R_FAILED(rc)) { + std::abort(); + } + /* fatal cannot throw fatal, so don't do: CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); */ } void __appExit(void) { /* Cleanup services. */ + fsdevUnmountAll(); + fsExit(); plExit(); spsmExit(); psmExit(); diff --git a/stratosphere/fatal/source/fatal_task_error_report.cpp b/stratosphere/fatal/source/fatal_task_error_report.cpp index 111c4ce38..bd75e641c 100644 --- a/stratosphere/fatal/source/fatal_task_error_report.cpp +++ b/stratosphere/fatal/source/fatal_task_error_report.cpp @@ -14,17 +14,127 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <cstdio> +#include <sys/stat.h> +#include <sys/types.h> #include <switch.h> +#include <atmosphere/version.h> + #include "fatal_task_error_report.hpp" +#include "fatal_config.hpp" + +void ErrorReportTask::EnsureReportDirectories() { + char path[FS_MAX_PATH]; + strcpy(path, "sdmc:/atmosphere"); + mkdir(path, S_IRWXU); + strcat(path, "/fatal_reports"); + mkdir(path, S_IRWXU); + strcat(path, "/dumps"); + mkdir(path, S_IRWXU); +} + +bool ErrorReportTask::GetCurrentTime(u64 *out) { + *out = 0; + + /* Verify that pcv isn't dead. */ + { + Handle dummy; + if (R_SUCCEEDED(smRegisterService(&dummy, "time:s", false, 0x20))) { + svcCloseHandle(dummy); + return false; + } + } + + /* Try to get the current time. */ + bool success = false; + if (R_SUCCEEDED(timeInitialize())) { + if (R_SUCCEEDED(timeGetCurrentTime(TimeType_LocalSystemClock, out))) { + success = true; + } + timeExit(); + } + return success; +} + +void ErrorReportTask::SaveReportToSdCard() { + char file_path[FS_MAX_PATH]; + + /* Ensure path exists. */ + EnsureReportDirectories(); + + /* Get a timestamp. */ + u64 timestamp; + if (!GetCurrentTime(×tamp)) { + timestamp = svcGetSystemTick(); + } + + /* Open report file. */ + snprintf(file_path, sizeof(file_path) - 1, "sdmc:/atmosphere/fatal_reports/%011lu_%016lx.log", timestamp, this->title_id); + FILE *f_report = fopen(file_path, "w"); + if (f_report != NULL) { + ON_SCOPE_EXIT { fclose(f_report); }; + + fprintf(f_report, "Atmosphère Fatal Report (v1.0):\n"); + fprintf(f_report, "Result: 0x%X (2%03d-%04d)\n\n", this->ctx->error_code, R_MODULE(this->ctx->error_code), R_DESCRIPTION(this->ctx->error_code)); + fprintf(f_report, "Title ID: %016lx\n", this->title_id); + if (strlen(this->ctx->proc_name)) { + fprintf(f_report, "Process Name: %s\n", this->ctx->proc_name); + } + fprintf(f_report, u8"Firmware: %s (Atmosphère %u.%u.%u-%s)\n", GetFatalConfig()->firmware_version.display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); + + if (this->ctx->cpu_ctx.is_aarch32) { + fprintf(f_report, "General Purpose Registers:\n"); + for (size_t i = 0; i < NumAarch32Gprs; i++) { + if (this->ctx->has_gprs[i]) { + fprintf(f_report, " %3s: %08x\n", Aarch32GprNames[i], this->ctx->cpu_ctx.aarch32_ctx.r[i]); + } + } + fprintf(f_report, " PC: %08x\n", this->ctx->cpu_ctx.aarch32_ctx.pc); + fprintf(f_report, "Start Address: %08x\n", this->ctx->cpu_ctx.aarch32_ctx.start_address); + fprintf(f_report, "Stack Trace:\n"); + for (unsigned int i = 0; i < this->ctx->cpu_ctx.aarch32_ctx.stack_trace_size; i++) { + fprintf(f_report, " ReturnAddress[%02u]: %08x\n", i, this->ctx->cpu_ctx.aarch32_ctx.stack_trace[i]); + } + } else { + fprintf(f_report, "General Purpose Registers:\n"); + for (size_t i = 0; i < NumAarch64Gprs; i++) { + if (this->ctx->has_gprs[i]) { + fprintf(f_report, " %3s: %016lx\n", Aarch64GprNames[i], this->ctx->cpu_ctx.aarch64_ctx.x[i]); + } + } + fprintf(f_report, " PC: %016lx\n", this->ctx->cpu_ctx.aarch64_ctx.pc); + fprintf(f_report, "Start Address: %016lx\n", this->ctx->cpu_ctx.aarch64_ctx.start_address); + fprintf(f_report, "Stack Trace:\n"); + for (unsigned int i = 0; i < this->ctx->cpu_ctx.aarch64_ctx.stack_trace_size; i++) { + fprintf(f_report, " ReturnAddress[%02u]: %016lx\n", i, this->ctx->cpu_ctx.aarch64_ctx.stack_trace[i]); + } + } + + } + + if (this->ctx->stack_dump_size) { + snprintf(file_path, sizeof(file_path) - 1, "sdmc:/atmosphere/fatal_reports/dumps/%011lu_%016lx.bin", timestamp, this->title_id); + FILE *f_stackdump = fopen(file_path, "wb"); + if (f_stackdump == NULL) { return; } + ON_SCOPE_EXIT { fclose(f_stackdump); }; + + fwrite(this->ctx->stack_dump, this->ctx->stack_dump_size, 1, f_stackdump); + } +} Result ErrorReportTask::Run() { if (this->create_report) { /* Here, Nintendo creates an error report with erpt. AMS will not do that. */ - /* TODO: Should atmosphere log reports to to the SD card? */ + } + + /* Save report to SD card. */ + if (!this->ctx->is_creport) { + SaveReportToSdCard(); } /* Signal we're done with our job. */ eventFire(this->erpt_event); + return 0; } \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_error_report.hpp b/stratosphere/fatal/source/fatal_task_error_report.hpp index 71b220f4d..464828dfb 100644 --- a/stratosphere/fatal/source/fatal_task_error_report.hpp +++ b/stratosphere/fatal/source/fatal_task_error_report.hpp @@ -23,6 +23,10 @@ class ErrorReportTask : public IFatalTask { private: bool create_report; Event *erpt_event; + private: + void EnsureReportDirectories(); + bool GetCurrentTime(u64 *out); + void SaveReportToSdCard(); public: ErrorReportTask(FatalThrowContext *ctx, u64 title_id, bool error_report, Event *evt) : IFatalTask(ctx, title_id), create_report(error_report), erpt_event(evt) { } virtual Result Run() override; diff --git a/stratosphere/fatal/source/fatal_throw.cpp b/stratosphere/fatal/source/fatal_throw.cpp index 8dbd15e0e..5cbcfa9dc 100644 --- a/stratosphere/fatal/source/fatal_throw.cpp +++ b/stratosphere/fatal/source/fatal_throw.cpp @@ -42,7 +42,7 @@ Result ThrowFatalForSelf(u32 error) { Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu_ctx) { Result rc = 0; - FatalThrowContext ctx; + FatalThrowContext ctx = {0}; ctx.error_code = error; if (cpu_ctx != nullptr) { ctx.cpu_ctx = *cpu_ctx; @@ -86,7 +86,7 @@ Result ThrowFatalImpl(u32 error, u64 pid, FatalType policy, FatalCpuContext *cpu if (R_FAILED((rc = SetThrown()))) { return rc; } - + /* Signal that fatal is about to happen. */ GetEventManager()->SignalEvents(); diff --git a/stratosphere/fatal/source/fatal_types.hpp b/stratosphere/fatal/source/fatal_types.hpp index b0635ec9f..f9ce5fb0e 100644 --- a/stratosphere/fatal/source/fatal_types.hpp +++ b/stratosphere/fatal/source/fatal_types.hpp @@ -100,6 +100,9 @@ struct FatalThrowContext { u32 error_code; bool is_creport; bool has_gprs[NumAarch64Gprs]; + size_t stack_dump_size; + u8 stack_dump[0x100]; + char proc_name[0xD]; FatalCpuContext cpu_ctx; }; From 66da896347dedb97bfd5112553c2cba39a1e6368 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 14 Nov 2018 18:39:11 -0800 Subject: [PATCH 224/489] sm: Disable smhax, it interferes with functionality. --- stratosphere/sm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/sm/Makefile b/stratosphere/sm/Makefile index dae1cae4a..a73c7e7f4 100644 --- a/stratosphere/sm/Makefile +++ b/stratosphere/sm/Makefile @@ -34,7 +34,7 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE CFLAGS := -g -Wall -O2 -ffunction-sections \ $(ARCH) $(DEFINES) -CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX -DSM_ENABLE_MITM -DSM_ENABLE_INIT_DEFERS -DSM_MINIMUM_SESSION_LIMIT=8 +CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_MITM -DSM_ENABLE_INIT_DEFERS -DSM_MINIMUM_SESSION_LIMIT=8 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 From d95fc102dbddf7861e0c515e307024f8bb809e23 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 14 Nov 2018 18:39:48 -0800 Subject: [PATCH 225/489] fs.mitm: Intercept OpenBisStorage calls. --- stratosphere/fs_mitm/source/fs_istorage.hpp | 62 +++++++++++++++++++ stratosphere/fs_mitm/source/fs_shim.c | 38 ++++++++++++ stratosphere/fs_mitm/source/fs_shim.h | 1 + .../fs_mitm/source/fsmitm_romstorage.hpp | 28 +-------- .../fs_mitm/source/fsmitm_service.cpp | 34 ++++++++++ .../fs_mitm/source/fsmitm_service.hpp | 30 ++++++++- 6 files changed, 165 insertions(+), 28 deletions(-) diff --git a/stratosphere/fs_mitm/source/fs_istorage.hpp b/stratosphere/fs_mitm/source/fs_istorage.hpp index 2f21b6b7e..23233e27f 100644 --- a/stratosphere/fs_mitm/source/fs_istorage.hpp +++ b/stratosphere/fs_mitm/source/fs_istorage.hpp @@ -108,3 +108,65 @@ class IROStorage : public IStorage { virtual Result GetSize(u64 *out_size) = 0; virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0; }; + + +class ProxyStorage : public IStorage { + private: + FsStorage *base_storage; + public: + ProxyStorage(FsStorage *s) : base_storage(s) { + /* ... */ + }; + ProxyStorage(FsStorage s) { + this->base_storage = new FsStorage(s); + }; + ~ProxyStorage() { + fsStorageClose(base_storage); + delete base_storage; + }; + public: + virtual Result Read(void *buffer, size_t size, u64 offset) override { + return fsStorageRead(this->base_storage, offset, buffer, size); + }; + virtual Result Write(void *buffer, size_t size, u64 offset) override { + return fsStorageWrite(this->base_storage, offset, buffer, size); + }; + virtual Result Flush() override { + return fsStorageFlush(this->base_storage); + }; + virtual Result GetSize(u64 *out_size) override { + return fsStorageGetSize(this->base_storage, out_size); + }; + virtual Result SetSize(u64 size) override { + return fsStorageSetSize(this->base_storage, size); + }; + virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { + return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info); + }; +}; + +class ROProxyStorage : public IROStorage { + private: + FsStorage *base_storage; + public: + ROProxyStorage(FsStorage *s) : base_storage(s) { + /* ... */ + }; + ROProxyStorage(FsStorage s) { + this->base_storage = new FsStorage(s); + }; + ~ROProxyStorage() { + fsStorageClose(base_storage); + delete base_storage; + }; + public: + virtual Result Read(void *buffer, size_t size, u64 offset) override { + return fsStorageRead(this->base_storage, offset, buffer, size); + }; + virtual Result GetSize(u64 *out_size) override { + return fsStorageGetSize(this->base_storage, out_size); + }; + virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { + return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info); + }; +}; \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fs_shim.c b/stratosphere/fs_mitm/source/fs_shim.c index 134d83498..915366bb8 100644 --- a/stratosphere/fs_mitm/source/fs_shim.c +++ b/stratosphere/fs_mitm/source/fs_shim.c @@ -18,6 +18,44 @@ #include "fs_shim.h" /* Missing fsp-srv commands. */ +Result fsOpenBisStorageFwd(Service* s, FsStorage* out, u32 PartitionId) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 PartitionId; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 12; + raw->PartitionId = PartitionId; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreateSubservice(&out->s, s, &r, 0); + } + } + + return rc; +} + Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) { IpcCommand c; ipcInitialize(&c); diff --git a/stratosphere/fs_mitm/source/fs_shim.h b/stratosphere/fs_mitm/source/fs_shim.h index d73c2595b..730a2bfb5 100644 --- a/stratosphere/fs_mitm/source/fs_shim.h +++ b/stratosphere/fs_mitm/source/fs_shim.h @@ -17,6 +17,7 @@ typedef struct { } FsRangeInfo; /* Missing fsp-srv commands. */ +Result fsOpenBisStorageFwd(Service* s, FsStorage* out, u32 PartitionId); Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out); Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out); diff --git a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp index c421a2147..04d0cf8d6 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp @@ -54,30 +54,4 @@ class RomFileStorage : public IROStorage { }; /* Represents a RomFS accessed via some IStorage. */ -class RomInterfaceStorage : public IROStorage { - private: - FsStorage *base_storage; - public: - RomInterfaceStorage(FsStorage *s) : base_storage(s) { - /* ... */ - }; - RomInterfaceStorage(FsStorage s) { - this->base_storage = new FsStorage(s); - }; - ~RomInterfaceStorage() { - fsStorageClose(base_storage); - delete base_storage; - }; - public: - Result Read(void *buffer, size_t size, u64 offset) override { - return fsStorageRead(this->base_storage, offset, buffer, size); - }; - Result GetSize(u64 *out_size) override { - /* TODO: Merge into libnx? */ - return fsStorageGetSize(this->base_storage, out_size); - }; - Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { - /* TODO: Merge into libnx? */ - return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info); - }; -}; +using RomInterfaceStorage = ROProxyStorage; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 91364ae19..505af638b 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -79,6 +79,40 @@ void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx } } +/* Gate access to the BIS partitions. */ +Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out_storage, u32 bis_partition_id) { + std::shared_ptr<IStorageInterface> storage = nullptr; + u32 out_domain_id = 0; + Result rc = 0; + + ON_SCOPE_EXIT { + if (R_SUCCEEDED(rc)) { + out_storage.SetValue(std::move(storage)); + if (out_storage.IsDomain()) { + out_storage.ChangeObjectId(out_domain_id); + } + } + }; + + { + FsStorage bis_storage; + rc = fsOpenBisStorageFwd(this->forward_service.get(), &bis_storage, bis_partition_id); + if (R_SUCCEEDED(rc)) { + if (this->title_id >= 0x0100000000001000) { + storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); + } else { + /* Sysmodules should still be allowed to read and write. */ + storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)); + } + if (out_storage.IsDomain()) { + out_domain_id = bis_storage.s.object_id; + } + } + } + + return rc; +} + /* Add redirection for RomFS to the SD card. */ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out_storage) { std::shared_ptr<IStorageInterface> storage = nullptr; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 2fffacfa9..07fb38398 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -22,11 +22,31 @@ enum FspSrvCmd : u32 { FspSrvCmd_SetCurrentProcess = 1, + FspSrvCmd_OpenBisStorage = 12, FspSrvCmd_OpenDataStorageByCurrentProcess = 200, FspSrvCmd_OpenDataStorageByDataId = 202, }; -class FsMitmService : public IMitmServiceObject { +enum BisStorageId : u32 { + BisStorageId_Boot0 = 0, + BisStorageId_Boot1 = 10, + BisStorageId_RawNand = 20, + BisStorageId_BcPkg2_1 = 21, + BisStorageId_BcPkg2_2 = 22, + BisStorageId_BcPkg2_3 = 23, + BisStorageId_BcPkg2_4 = 24, + BisStorageId_BcPkg2_5 = 25, + BisStorageId_BcPkg2_6 = 26, + BisStorageId_Prodinfo = 27, + BisStorageId_ProdinfoF = 28, + BisStorageId_Safe = 29, + BisStorageId_User = 30, + BisStorageId_System = 31, + BisStorageId_SystemProperEncryption = 32, + BisStorageId_SystemProperPartition = 33, +}; + +class FsMitmService : public IMitmServiceObject { private: bool has_initialized = false; public: @@ -35,9 +55,15 @@ class FsMitmService : public IMitmServiceObject { } static bool ShouldMitm(u64 pid, u64 tid) { + /* Always intercept NS, so that we can protect the boot partition. */ + if (tid == 0x010000000000001FULL) { + return true; + } + if (Utils::HasSdDisableMitMFlag(tid)) { return false; } + return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)) && Utils::HasOverrideButton(tid); } @@ -45,10 +71,12 @@ class FsMitmService : public IMitmServiceObject { protected: /* Overridden commands. */ + Result OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out, u32 bis_partition_id); Result OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out); Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 data_id, u8 storage_id); public: DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<FspSrvCmd_OpenBisStorage, &FsMitmService::OpenBisStorage>(), MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByCurrentProcess, &FsMitmService::OpenDataStorageByCurrentProcess>(), MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByDataId, &FsMitmService::OpenDataStorageByDataId>(), }; From e1cc1b8d2940d90d4a5f8e509f3da99277f33835 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 14 Nov 2018 19:40:46 -0800 Subject: [PATCH 226/489] fs.mitm: Make accesses to Boot0 sectored --- stratosphere/fs_mitm/source/fs_istorage.hpp | 4 +- .../fs_mitm/source/fsmitm_boot0storage.hpp | 156 ++++++++++++++++++ .../fs_mitm/source/fsmitm_romstorage.hpp | 2 +- .../fs_mitm/source/fsmitm_service.cpp | 14 +- 4 files changed, 169 insertions(+), 7 deletions(-) create mode 100644 stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp diff --git a/stratosphere/fs_mitm/source/fs_istorage.hpp b/stratosphere/fs_mitm/source/fs_istorage.hpp index 23233e27f..8bd44cdd2 100644 --- a/stratosphere/fs_mitm/source/fs_istorage.hpp +++ b/stratosphere/fs_mitm/source/fs_istorage.hpp @@ -120,7 +120,7 @@ class ProxyStorage : public IStorage { ProxyStorage(FsStorage s) { this->base_storage = new FsStorage(s); }; - ~ProxyStorage() { + virtual ~ProxyStorage() { fsStorageClose(base_storage); delete base_storage; }; @@ -155,7 +155,7 @@ class ROProxyStorage : public IROStorage { ROProxyStorage(FsStorage s) { this->base_storage = new FsStorage(s); }; - ~ROProxyStorage() { + virtual ~ROProxyStorage() { fsStorageClose(base_storage); delete base_storage; }; diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp new file mode 100644 index 000000000..d06351175 --- /dev/null +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "fs_istorage.hpp" + +/* Represents a sectored storage. */ +template<u64 SectorSize> +class SectoredProxyStorage : public ProxyStorage { + private: + u64 cur_seek = 0; + u64 cur_sector = 0; + u64 cur_sector_ofs = 0; + u8 sector_buf[SectorSize]; + private: + void Seek(u64 offset) { + this->cur_sector_ofs = offset % SectorSize; + this->cur_seek = offset - this->cur_sector_ofs; + } + public: + SectoredProxyStorage(FsStorage *s) : ProxyStorage(s) { } + SectoredProxyStorage(FsStorage s) : ProxyStorage(s) { } + public: + virtual Result Read(void *_buffer, size_t size, u64 offset) override { + Result rc = 0; + u8 *buffer = static_cast<u8 *>(_buffer); + this->Seek(offset); + + if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, this->cur_seek)))) { + return rc; + } + + if (size + this->cur_sector_ofs <= SectorSize) { + memcpy(buffer, sector_buf + this->cur_sector_ofs, size); + } else { + /* Leaving the sector... */ + size_t ofs = SectorSize - this->cur_sector_ofs; + memcpy(buffer, sector_buf + this->cur_sector_ofs, ofs); + size -= ofs; + + /* We're guaranteed alignment, here. */ + const size_t aligned_remaining_size = size - (size % SectorSize); + if (aligned_remaining_size) { + if (R_FAILED((rc = ProxyStorage::Read(buffer + ofs, aligned_remaining_size, offset + ofs)))) { + return rc; + } + ofs += aligned_remaining_size; + size -= aligned_remaining_size; + } + + /* Read any leftover data. */ + if (size) { + if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, offset + ofs)))) { + return rc; + } + memcpy(buffer + ofs, sector_buf, size); + } + } + + return rc; + }; + virtual Result Write(void *_buffer, size_t size, u64 offset) override { + Result rc = 0; + u8 *buffer = static_cast<u8 *>(_buffer); + this->Seek(offset); + + if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, this->cur_seek)))) { + return rc; + } + + + if (size + this->cur_sector_ofs <= SectorSize) { + memcpy(this->sector_buf + this->cur_sector_ofs, buffer, size); + rc = ProxyStorage::Write(this->sector_buf, SectorSize, this->cur_seek); + } else { + /* Leaving the sector... */ + size_t ofs = SectorSize - this->cur_sector_ofs; + memcpy(this->sector_buf + this->cur_sector_ofs, buffer, ofs); + if (R_FAILED((rc = ProxyStorage::Write(this->sector_buf, ofs, this->cur_seek)))) { + return rc; + } + size -= ofs; + + /* We're guaranteed alignment, here. */ + const size_t aligned_remaining_size = size - (size % SectorSize); + if (aligned_remaining_size) { + if (R_FAILED((rc = ProxyStorage::Write(buffer + ofs, aligned_remaining_size, offset + ofs)))) { + return rc; + } + ofs += aligned_remaining_size; + size -= aligned_remaining_size; + } + + /* Write any leftover data. */ + if (size) { + if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, offset + ofs)))) { + return rc; + } + memcpy(this->sector_buf, buffer + ofs, size); + rc = ProxyStorage::Write(this->sector_buf, SectorSize, this->cur_seek); + } + } + + return rc; + }; +}; + +/* Represents an RCM-preserving BOOT0 partition. */ +class Boot0Storage : public SectoredProxyStorage<0x200> { + using Base = SectoredProxyStorage<0x200>; + private: + bool allow_writes; + private: + HosMutex *GetMutex() { + static HosMutex s_boot0_mutex; + return &s_boot0_mutex; + } + public: + Boot0Storage(FsStorage *s, bool w) : Base(s), allow_writes(w) { } + Boot0Storage(FsStorage s, bool w) : Base(s), allow_writes(w) { } + + public: + virtual Result Read(void *_buffer, size_t size, u64 offset) override { + GetMutex()->Lock(); + ON_SCOPE_EXIT { GetMutex()->Unlock(); }; + + return Base::Read(_buffer, size, offset); + } + + virtual Result Write(void *_buffer, size_t size, u64 offset) override { + GetMutex()->Lock(); + ON_SCOPE_EXIT { GetMutex()->Unlock(); }; + + if (!this->allow_writes) { + return 0x313802; + } + + return Base::Write(_buffer, size, offset); + } +}; \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp index 04d0cf8d6..1a186ec4c 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp @@ -31,7 +31,7 @@ class RomFileStorage : public IROStorage { RomFileStorage(FsFile f) { this->base_file = new FsFile(f); }; - ~RomFileStorage() { + virtual ~RomFileStorage() { fsFileClose(base_file); delete base_file; }; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 505af638b..ccf29db94 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -24,6 +24,7 @@ #include "fs_shim.h" #include "fsmitm_utils.hpp" +#include "fsmitm_boot0storage.hpp" #include "fsmitm_romstorage.hpp" #include "fsmitm_layeredrom.hpp" @@ -98,11 +99,16 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out FsStorage bis_storage; rc = fsOpenBisStorageFwd(this->forward_service.get(), &bis_storage, bis_partition_id); if (R_SUCCEEDED(rc)) { - if (this->title_id >= 0x0100000000001000) { - storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); + const bool allow_writes = this->title_id < 0x0100000000001000; + if (bis_partition_id == BisStorageId_Boot0) { + storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, allow_writes)); } else { - /* Sysmodules should still be allowed to read and write. */ - storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)); + if (allow_writes) { + storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); + } else { + /* Sysmodules should still be allowed to read and write. */ + storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)); + } } if (out_storage.IsDomain()) { out_domain_id = bis_storage.s.object_id; From 878ac59aae64227ab019d3d57de5cad4396eb61c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 14 Nov 2018 19:49:12 -0800 Subject: [PATCH 227/489] fs.mitm: skeleton logic for protecting autorcm. --- .../fs_mitm/source/fsmitm_boot0storage.hpp | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp index d06351175..a21365ca1 100644 --- a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp @@ -125,16 +125,21 @@ class SectoredProxyStorage : public ProxyStorage { class Boot0Storage : public SectoredProxyStorage<0x200> { using Base = SectoredProxyStorage<0x200>; private: - bool allow_writes; + u64 title_id; private: HosMutex *GetMutex() { static HosMutex s_boot0_mutex; return &s_boot0_mutex; } + bool AllowWrites() { + return title_id < 0x0100000000001000ULL; + } + bool CanModifyBctPubks() { + return title_id != 0x010000000000001FULL; + } public: - Boot0Storage(FsStorage *s, bool w) : Base(s), allow_writes(w) { } - Boot0Storage(FsStorage s, bool w) : Base(s), allow_writes(w) { } - + Boot0Storage(FsStorage *s, u64 t) : Base(s), title_id(t) { } + Boot0Storage(FsStorage s, u64 t) : Base(s), title_id(t) { } public: virtual Result Read(void *_buffer, size_t size, u64 offset) override { GetMutex()->Lock(); @@ -147,10 +152,16 @@ class Boot0Storage : public SectoredProxyStorage<0x200> { GetMutex()->Lock(); ON_SCOPE_EXIT { GetMutex()->Unlock(); }; - if (!this->allow_writes) { + if (!AllowWrites()) { return 0x313802; } - return Base::Write(_buffer, size, offset); + /* We care about protecting autorcm from NS. */ + if (CanModifyBctPubks()) { + return Base::Write(_buffer, size, offset); + } + + /* TODO */ + return 0x313802; } }; \ No newline at end of file From 05187502b31fb924489055028138ed50a3dd16d3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 03:57:55 -0800 Subject: [PATCH 228/489] fs.mitm: Implement basic boot0 protection against writes/pubk writes. --- stratosphere/fs_mitm/source/fs_istorage.hpp | 1 - .../fs_mitm/source/fsmitm_boot0storage.cpp | 78 +++++++++++++++++++ .../fs_mitm/source/fsmitm_boot0storage.hpp | 55 ++++++------- .../fs_mitm/source/fsmitm_service.cpp | 2 +- 4 files changed, 101 insertions(+), 35 deletions(-) create mode 100644 stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp diff --git a/stratosphere/fs_mitm/source/fs_istorage.hpp b/stratosphere/fs_mitm/source/fs_istorage.hpp index 8bd44cdd2..82a75619e 100644 --- a/stratosphere/fs_mitm/source/fs_istorage.hpp +++ b/stratosphere/fs_mitm/source/fs_istorage.hpp @@ -61,7 +61,6 @@ class IStorageInterface : public IServiceObject { }; virtual Result Write(InBuffer<u8, BufferType_Type1> buffer, u64 offset, u64 size) final { return this->base_storage->Write(buffer.buffer, std::min(buffer.num_elements, size), offset); - }; virtual Result Flush() final { return this->base_storage->Flush(); diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp new file mode 100644 index 000000000..e2b25ad40 --- /dev/null +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <cstring> +#include <stratosphere.hpp> + +#include "fsmitm_boot0storage.hpp" + +static HosMutex g_boot0_mutex; +static u8 g_boot0_bct_buffer[Boot0Storage::BctEndOffset]; + +bool Boot0Storage::AllowWrites() { + return this->title_id < 0x0100000000001000ULL; +} + +bool Boot0Storage::CanModifyBctPubks() { + return this->title_id != 0x010000000000001FULL; +} + +Result Boot0Storage::Read(void *_buffer, size_t size, u64 offset) { + std::scoped_lock<HosMutex> lk{g_boot0_mutex}; + + return Base::Read(_buffer, size, offset); +} + +Result Boot0Storage::Write(void *_buffer, size_t size, u64 offset) { + std::scoped_lock<HosMutex> lk{g_boot0_mutex}; + + if (!AllowWrites()) { + return 0x313802; + } + + /* We care about protecting autorcm from NS. */ + if (CanModifyBctPubks() || offset >= BctEndOffset || (offset + BctSize >= BctEndOffset && offset % BctSize >= BctPubkEnd)) { + return Base::Write(_buffer, size, offset); + } + + Result rc = 0; + u8 *buffer = static_cast<u8 *>(_buffer); + + /* First, let's deal with the data past the end. */ + if (offset + size >= BctEndOffset) { + const u64 diff = BctEndOffset - offset; + if (R_FAILED((rc = ProxyStorage::Write(buffer + diff, size - diff, BctEndOffset)))) { + return rc; + } + size -= diff; + } + + /* Read in the current BCT region. */ + if (R_FAILED((rc = ProxyStorage::Read(g_boot0_bct_buffer, BctEndOffset, 0)))) { + return rc; + } + + /* Update the bct buffer. */ + for (u64 cur_ofs = offset; cur_ofs < BctEndOffset && cur_ofs < offset + size; cur_ofs++) { + const u64 cur_bct_rel_ofs = cur_ofs % BctSize; + if (cur_bct_rel_ofs < BctPubkStart || BctPubkEnd <= cur_bct_rel_ofs) { + g_boot0_bct_buffer[cur_ofs] = buffer[cur_ofs - offset]; + } + } + + return ProxyStorage::Write(g_boot0_bct_buffer, BctEndOffset, 0); +} diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp index a21365ca1..cf53948f4 100644 --- a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp @@ -16,6 +16,7 @@ #pragma once #include <switch.h> +#include <cstring> #include <stratosphere.hpp> #include "fs_istorage.hpp" @@ -42,6 +43,11 @@ class SectoredProxyStorage : public ProxyStorage { u8 *buffer = static_cast<u8 *>(_buffer); this->Seek(offset); + if (this->cur_sector_ofs == 0 && size % SectorSize == 0) { + /* Fast case. */ + return ProxyStorage::Read(buffer, size, offset); + } + if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, this->cur_seek)))) { return rc; } @@ -80,6 +86,11 @@ class SectoredProxyStorage : public ProxyStorage { u8 *buffer = static_cast<u8 *>(_buffer); this->Seek(offset); + if (this->cur_sector_ofs == 0 && size % SectorSize == 0) { + /* Fast case. */ + return ProxyStorage::Write(buffer, size, offset); + } + if (R_FAILED((rc = ProxyStorage::Read(this->sector_buf, SectorSize, this->cur_seek)))) { return rc; } @@ -124,44 +135,22 @@ class SectoredProxyStorage : public ProxyStorage { /* Represents an RCM-preserving BOOT0 partition. */ class Boot0Storage : public SectoredProxyStorage<0x200> { using Base = SectoredProxyStorage<0x200>; + + public: + static constexpr u64 BctEndOffset = 0xFC000; + static constexpr u64 BctSize = 0x4000; + static constexpr u64 BctPubkStart = 0x210; + static constexpr u64 BctPubkSize = 0x100; + static constexpr u64 BctPubkEnd = BctPubkStart + BctPubkSize; private: u64 title_id; private: - HosMutex *GetMutex() { - static HosMutex s_boot0_mutex; - return &s_boot0_mutex; - } - bool AllowWrites() { - return title_id < 0x0100000000001000ULL; - } - bool CanModifyBctPubks() { - return title_id != 0x010000000000001FULL; - } + bool AllowWrites(); + bool CanModifyBctPubks(); public: Boot0Storage(FsStorage *s, u64 t) : Base(s), title_id(t) { } Boot0Storage(FsStorage s, u64 t) : Base(s), title_id(t) { } public: - virtual Result Read(void *_buffer, size_t size, u64 offset) override { - GetMutex()->Lock(); - ON_SCOPE_EXIT { GetMutex()->Unlock(); }; - - return Base::Read(_buffer, size, offset); - } - - virtual Result Write(void *_buffer, size_t size, u64 offset) override { - GetMutex()->Lock(); - ON_SCOPE_EXIT { GetMutex()->Unlock(); }; - - if (!AllowWrites()) { - return 0x313802; - } - - /* We care about protecting autorcm from NS. */ - if (CanModifyBctPubks()) { - return Base::Write(_buffer, size, offset); - } - - /* TODO */ - return 0x313802; - } + virtual Result Read(void *_buffer, size_t size, u64 offset) override; + virtual Result Write(void *_buffer, size_t size, u64 offset) override; }; \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index ccf29db94..6fb27f846 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -101,7 +101,7 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out if (R_SUCCEEDED(rc)) { const bool allow_writes = this->title_id < 0x0100000000001000; if (bis_partition_id == BisStorageId_Boot0) { - storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, allow_writes)); + storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id)); } else { if (allow_writes) { storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); From 420361597ec60c0fc6f584c9ad37ae456555ea0a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 04:26:40 -0800 Subject: [PATCH 229/489] all: Change flagging location. Support (but deprecate) old location. --- Makefile | 3 +- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 71 +++++++++++++++++++- stratosphere/fs_mitm/source/fsmitm_utils.hpp | 4 ++ stratosphere/pm/source/pm_boot2.cpp | 13 +++- 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 7eeab49b6..dd524d27e 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,8 @@ dist: all cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp - touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/boot2.flag + mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags + touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags/boot2.flag cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; rm -r atmosphere-$(AMSVER) mkdir out diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 32e37fad6..9ebffae0b 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -31,6 +31,7 @@ static std::atomic_bool g_has_initialized = false; static std::atomic_bool g_has_hid_session = false; static u64 g_override_key_combination = KEY_R; +static u64 g_override_hbl_tid = 0x010000000000100DULL; static bool g_override_by_default = true; /* Static buffer for loader.ini contents at runtime. */ @@ -76,19 +77,39 @@ void Utils::InitializeSdThreadFunc(void *args) { char title_path[FS_MAX_PATH] = {0}; strcpy(title_path, "/atmosphere/titles/"); strcat(title_path, dir_entry.name); - strcat(title_path, "/fsmitm.flag"); + strcat(title_path, "/flags/fsmitm.flag"); if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, title_path, FS_OPEN_READ, &f))) { g_mitm_flagged_tids.push_back(title_id); fsFileClose(&f); + } else { + /* TODO: Deprecate. */ + memset(title_path, 0, sizeof(title_path)); + strcpy(title_path, "/atmosphere/titles/"); + strcat(title_path, dir_entry.name); + strcat(title_path, "/fsmitm.flag"); + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, title_path, FS_OPEN_READ, &f))) { + g_mitm_flagged_tids.push_back(title_id); + fsFileClose(&f); + } } memset(title_path, 0, sizeof(title_path)); strcpy(title_path, "/atmosphere/titles/"); strcat(title_path, dir_entry.name); - strcat(title_path, "/fsmitm_disable.flag"); + strcat(title_path, "/flags/fsmitm_disable.flag"); if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, title_path, FS_OPEN_READ, &f))) { g_disable_mitm_flagged_tids.push_back(title_id); fsFileClose(&f); + } else { + /* TODO: Deprecate. */ + memset(title_path, 0, sizeof(title_path)); + strcpy(title_path, "/atmosphere/titles/"); + strcat(title_path, dir_entry.name); + strcat(title_path, "/fsmitm_disable.flag"); + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, title_path, FS_OPEN_READ, &f))) { + g_disable_mitm_flagged_tids.push_back(title_id); + fsFileClose(&f); + } } } } @@ -264,7 +285,46 @@ Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data, return rc; } +bool Utils::HasFlag(u64 tid, const char *flag) { + if (IsSdInitialized()) { + FsFile f; + char flag_path[FS_MAX_PATH]; + + memset(flag_path, 0, sizeof(flag_path)); + snprintf(flag_path, sizeof(flag_path) - 1, "flags/%s.flag", flag); + if (OpenSdFileForAtmosphere(tid, flag_path, FS_OPEN_READ, &f)) { + fsFileClose(&f); + return true; + } + + /* TODO: Deprecate. */ + snprintf(flag_path, sizeof(flag_path) - 1, "%s.flag", flag); + if (OpenSdFileForAtmosphere(tid, flag_path, FS_OPEN_READ, &f)) { + fsFileClose(&f); + return true; + } + } + return false; +} + +bool Utils::HasGlobalFlag(u64 tid, const char *flag) { + if (IsSdInitialized()) { + FsFile f; + char flag_path[FS_MAX_PATH] = {0}; + snprintf(flag_path, sizeof(flag_path), "/atmosphere/flags/%s.flag", flag); + if (fsFsOpenFile(&g_sd_filesystem, flag_path, FS_OPEN_READ, &f)) { + fsFileClose(&f); + return true; + } + } + return false; +} + bool Utils::HasSdMitMFlag(u64 tid) { + if (tid == g_override_hbl_tid) { + return true; + } + if (IsSdInitialized()) { return std::find(g_mitm_flagged_tids.begin(), g_mitm_flagged_tids.end(), tid) != g_mitm_flagged_tids.end(); } @@ -306,7 +366,12 @@ bool Utils::HasOverrideButton(u64 tid) { static int FsMitMIniHandler(void *user, const char *section, const char *name, const char *value) { /* Taken and modified, with love, from Rajkosto's implementation. */ if (strcasecmp(section, "config") == 0) { - if (strcasecmp(name, "override_key") == 0) { + if (strcasecmp(name, "hbl_tid") == 0) { + u64 override_tid = strtoul(value, NULL, 16); + if (override_tid != 0) { + g_override_hbl_tid = override_tid; + } + } else if (strcasecmp(name, "override_key") == 0) { if (value[0] == '!') { g_override_by_default = true; value++; diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index ad8d176b1..a730d44d6 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -38,6 +38,10 @@ class Utils { /* SD card Initialization + MitM detection. */ static void InitializeSdThreadFunc(void *args); + + static bool HasFlag(u64 tid, const char *flag); + static bool HasGlobalFlag(const char *flag); + static bool HasSdMitMFlag(u64 tid); static bool HasSdDisableMitMFlag(u64 tid); diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 3a6844621..78eddd963 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -163,11 +163,22 @@ void EmbeddedBoot2::Main() { char title_path[FS_MAX_PATH] = {0}; strcpy(title_path, "sdmc:/atmosphere/titles/"); strcat(title_path, ent->d_name); - strcat(title_path, "/boot2.flag"); + strcat(title_path, "/flags/boot2.flag"); FILE *f_flag = fopen(title_path, "rb"); if (f_flag != NULL) { fclose(f_flag); LaunchTitle((Boot2KnownTitleId)title_id, FsStorageId_None, 0, NULL); + } else { + /* TODO: Deprecate this in the future. */ + memset(title_path, 0, FS_MAX_PATH); + strcpy(title_path, "sdmc:/atmosphere/titles/"); + strcat(title_path, ent->d_name); + strcat(title_path, "/boot2.flag"); + f_flag = fopen(title_path, "rb"); + if (f_flag != NULL) { + fclose(f_flag); + LaunchTitle((Boot2KnownTitleId)title_id, FsStorageId_None, 0, NULL); + } } } } From 83644692fe6e89da5c99d6ddae9671f9cc5035bb Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 04:44:13 -0800 Subject: [PATCH 230/489] fs.mitm: Automatically backup PRODINFO on boot. --- .../fs_mitm/source/fsmitm_service.hpp | 19 ---------- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 38 ++++++++++++++++++- stratosphere/fs_mitm/source/fsmitm_utils.hpp | 19 ++++++++++ 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 07fb38398..33516ccba 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -27,25 +27,6 @@ enum FspSrvCmd : u32 { FspSrvCmd_OpenDataStorageByDataId = 202, }; -enum BisStorageId : u32 { - BisStorageId_Boot0 = 0, - BisStorageId_Boot1 = 10, - BisStorageId_RawNand = 20, - BisStorageId_BcPkg2_1 = 21, - BisStorageId_BcPkg2_2 = 22, - BisStorageId_BcPkg2_3 = 23, - BisStorageId_BcPkg2_4 = 24, - BisStorageId_BcPkg2_5 = 25, - BisStorageId_BcPkg2_6 = 26, - BisStorageId_Prodinfo = 27, - BisStorageId_ProdinfoF = 28, - BisStorageId_Safe = 29, - BisStorageId_User = 30, - BisStorageId_System = 31, - BisStorageId_SystemProperEncryption = 32, - BisStorageId_SystemProperPartition = 33, -}; - class FsMitmService : public IMitmServiceObject { private: bool has_initialized = false; diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 9ebffae0b..46ed6c39b 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -65,6 +65,42 @@ void Utils::InitializeSdThreadFunc(void *args) { svcSleepThread(1000ULL); } + /* Back up CAL0, if it's not backed up already. */ + fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups"); + { + FsStorage cal0_storage; + FsFile cal0_file; + bool has_auto_backup = false; + + static const char * const PRODINFO_BACKUP_PATH = "/atmosphere/automatic_backups/PRODINFO.bin"; + constexpr size_t PRODINFO_SIZE = 0x4000; + + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, PRODINFO_BACKUP_PATH, FS_OPEN_READ, &cal0_file))) { + char magic[4]; + size_t read; + if (R_SUCCEEDED(fsFileRead(&cal0_file, 0, magic, sizeof(magic), &read)) && read == sizeof(magic) && memcmp(magic, "CAL0", sizeof(magic)) == 0) { + has_auto_backup = true; + } + fsFileClose(&cal0_file); + } + + if (!has_auto_backup && R_SUCCEEDED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo))) { + u8 *cal0 = new u8[PRODINFO_SIZE]; + if (R_SUCCEEDED(fsStorageRead(&cal0_storage, 0, cal0, PRODINFO_SIZE)) ) { + fsFsCreateFile(&g_sd_filesystem, PRODINFO_BACKUP_PATH, PRODINFO_SIZE, 0); + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, PRODINFO_BACKUP_PATH, FS_OPEN_READ | FS_OPEN_WRITE, &cal0_file))) { + fsFileSetSize(&cal0_file, PRODINFO_SIZE); + fsFileWrite(&cal0_file, 0, cal0, PRODINFO_SIZE); + fsFileFlush(&cal0_file); + fsFileClose(&cal0_file); + } + } + + delete cal0; + fsStorageClose(&cal0_storage); + } + } + /* Check for MitM flags. */ FsDir titles_dir; if (R_SUCCEEDED(fsFsOpenDirectory(&g_sd_filesystem, "/atmosphere/titles", FS_DIROPEN_DIRECTORY, &titles_dir))) { @@ -307,7 +343,7 @@ bool Utils::HasFlag(u64 tid, const char *flag) { return false; } -bool Utils::HasGlobalFlag(u64 tid, const char *flag) { +bool Utils::HasGlobalFlag(const char *flag) { if (IsSdInitialized()) { FsFile f; char flag_path[FS_MAX_PATH] = {0}; diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index a730d44d6..71efe768b 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -18,6 +18,25 @@ #include <switch.h> #include <stratosphere.hpp> +enum BisStorageId : u32 { + BisStorageId_Boot0 = 0, + BisStorageId_Boot1 = 10, + BisStorageId_RawNand = 20, + BisStorageId_BcPkg2_1 = 21, + BisStorageId_BcPkg2_2 = 22, + BisStorageId_BcPkg2_3 = 23, + BisStorageId_BcPkg2_4 = 24, + BisStorageId_BcPkg2_5 = 25, + BisStorageId_BcPkg2_6 = 26, + BisStorageId_Prodinfo = 27, + BisStorageId_ProdinfoF = 28, + BisStorageId_Safe = 29, + BisStorageId_User = 30, + BisStorageId_System = 31, + BisStorageId_SystemProperEncryption = 32, + BisStorageId_SystemProperPartition = 33, +}; + class Utils { public: static bool IsSdInitialized(); From b4781b8a4faf31153f37677b0f646d6d4ebd4354 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 04:52:55 -0800 Subject: [PATCH 231/489] fs.mitm: improve backup path name --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 46ed6c39b..2a425b9e1 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -71,11 +71,23 @@ void Utils::InitializeSdThreadFunc(void *args) { FsStorage cal0_storage; FsFile cal0_file; bool has_auto_backup = false; + char serial_number[0x40] = {0}; + + if (R_SUCCEEDED(setsysInitialize())) { + setsysGetSerialNumber(serial_number); + setsysExit(); + } + + char prodinfo_backup_path[FS_MAX_PATH] = {0}; + if (strlen(serial_number) > 0) { + snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/PRODINFO_%s.bin", serial_number); + } else { + snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/PRODINFO.bin"); + } - static const char * const PRODINFO_BACKUP_PATH = "/atmosphere/automatic_backups/PRODINFO.bin"; constexpr size_t PRODINFO_SIZE = 0x4000; - if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, PRODINFO_BACKUP_PATH, FS_OPEN_READ, &cal0_file))) { + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ, &cal0_file))) { char magic[4]; size_t read; if (R_SUCCEEDED(fsFileRead(&cal0_file, 0, magic, sizeof(magic), &read)) && read == sizeof(magic) && memcmp(magic, "CAL0", sizeof(magic)) == 0) { @@ -87,8 +99,8 @@ void Utils::InitializeSdThreadFunc(void *args) { if (!has_auto_backup && R_SUCCEEDED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo))) { u8 *cal0 = new u8[PRODINFO_SIZE]; if (R_SUCCEEDED(fsStorageRead(&cal0_storage, 0, cal0, PRODINFO_SIZE)) ) { - fsFsCreateFile(&g_sd_filesystem, PRODINFO_BACKUP_PATH, PRODINFO_SIZE, 0); - if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, PRODINFO_BACKUP_PATH, FS_OPEN_READ | FS_OPEN_WRITE, &cal0_file))) { + fsFsCreateFile(&g_sd_filesystem, prodinfo_backup_path, PRODINFO_SIZE, 0); + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &cal0_file))) { fsFileSetSize(&cal0_file, PRODINFO_SIZE); fsFileWrite(&cal0_file, 0, cal0, PRODINFO_SIZE); fsFileFlush(&cal0_file); From 1932662b4ca548d4c1ed16d937db53b81c034680 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 04:54:07 -0800 Subject: [PATCH 232/489] fs.mitm: improve backup path name again --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 2a425b9e1..e2f39bb9c 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -80,7 +80,7 @@ void Utils::InitializeSdThreadFunc(void *args) { char prodinfo_backup_path[FS_MAX_PATH] = {0}; if (strlen(serial_number) > 0) { - snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/PRODINFO_%s.bin", serial_number); + snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/%s_PRODINFO.bin", serial_number); } else { snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/PRODINFO.bin"); } From a00e120bf7be1a1407db89d6e184ad35fcf53adf Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 06:23:44 -0800 Subject: [PATCH 233/489] fs.mitm: Make PRODINFO always read-only. --- stratosphere/fs_mitm/source/fsmitm_service.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 6fb27f846..b8384d26c 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -102,6 +102,9 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out const bool allow_writes = this->title_id < 0x0100000000001000; if (bis_partition_id == BisStorageId_Boot0) { storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id)); + } else if (bis_partition_id == BisStorageId_Prodinfo) { + /* PRODINFO should *never* be writable. */ + storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); } else { if (allow_writes) { storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); From 7e3b5c37d02b7ece2d4d733b64d573a8ed45b15e Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Thu, 15 Nov 2018 21:38:32 +0000 Subject: [PATCH 234/489] exosphere: Add missing register write. --- exosphere/src/bootup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index e2bbbbee3..962ef8e75 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -95,6 +95,7 @@ void bootup_misc_mmio(void) { /* Setup MC carveouts. */ MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0; MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0; MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1; From 46cc08160d86eef9a63dc0eb1994871b1f770f62 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 14:19:34 -0800 Subject: [PATCH 235/489] mitm: Improve session acquire semantics. --- stratosphere/libstratosphere | 2 +- stratosphere/sm/source/sm_registration.cpp | 45 ++++++++++++++++++++-- stratosphere/sm/source/sm_registration.hpp | 5 +++ stratosphere/sm/source/sm_user_service.cpp | 14 +++++++ stratosphere/sm/source/sm_user_service.hpp | 5 ++- 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index bcd80ab44..8fcac73ab 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit bcd80ab445258c20d968aad1c083fd8cb0937bee +Subproject commit 8fcac73ab2b91afe184abe48c887ea1cb9bf2076 diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index 0932db1f7..e5fc77c12 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -221,13 +221,11 @@ bool Registration::HasService(u64 service) { Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) { Registration::Service *target_service = GetService(service); - if (target_service == NULL || ShouldInitDefer(service)) { + if (target_service == NULL || ShouldInitDefer(service) || target_service->mitm_waiting_ack) { /* Note: This defers the result until later. */ return RESULT_DEFER_SESSION; } - /* */ - *out = 0; Result rc; if (target_service->mitm_pid == 0 || target_service->mitm_pid == pid) { @@ -255,7 +253,17 @@ Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) { rc = resp->result; if (R_SUCCEEDED(rc)) { if (resp->should_mitm) { - rc = svcConnectToPort(out, target_service->mitm_port_h); + rc = svcConnectToPort(&target_service->mitm_fwd_sess_h, target_service->port_h); + if (R_SUCCEEDED(rc)) { + rc = svcConnectToPort(out, target_service->mitm_port_h); + if (R_SUCCEEDED(rc)) { + target_service->mitm_waiting_ack_pid = pid; + target_service->mitm_waiting_ack = true; + } else { + svcCloseHandle(target_service->mitm_fwd_sess_h); + target_service->mitm_fwd_sess_h = 0; + } + } } else { rc = svcConnectToPort(out, target_service->port_h); } @@ -497,6 +505,35 @@ Result Registration::UninstallMitmForPid(u64 pid, u64 service) { return 0; } +Result Registration::AcknowledgeMitmSessionForPid(u64 pid, u64 service, Handle *out, u64 *out_pid) { + if (!service) { + return 0xC15; + } + + u64 service_name_len = GetServiceNameLength(service); + + /* If the service has bytes after a null terminator, that's no good. */ + if (service_name_len != 8 && (service >> (8 * service_name_len))) { + return 0xC15; + } + + Registration::Service *target_service = GetService(service); + if (target_service == NULL) { + return 0xE15; + } + + if ((!IsInitialProcess(pid) && target_service->mitm_pid != pid) || !target_service->mitm_waiting_ack) { + return 0x1015; + } + + *out = target_service->mitm_fwd_sess_h; + *out_pid = target_service->mitm_waiting_ack_pid; + target_service->mitm_fwd_sess_h = 0; + target_service->mitm_waiting_ack_pid = 0; + target_service->mitm_waiting_ack = false; + return 0; +} + Result Registration::AssociatePidTidForMitm(u64 pid, u64 tid) { for (auto &service : g_service_list) { if (service.mitm_pid) { diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 9a30652bc..657483822 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -43,6 +43,10 @@ class Registration { u64 mitm_pid; Handle mitm_port_h; Handle mitm_query_h; + + bool mitm_waiting_ack; + u64 mitm_waiting_ack_pid; + Handle mitm_fwd_sess_h; }; /* Utilities. */ @@ -74,5 +78,6 @@ class Registration { /* Extension. */ static Result InstallMitmForPid(u64 pid, u64 service, Handle *out, Handle *query_out); static Result UninstallMitmForPid(u64 pid, u64 service); + static Result AcknowledgeMitmSessionForPid(u64 pid, u64 service, Handle *out, u64 *out_pid); static Result AssociatePidTidForMitm(u64 pid, u64 tid); }; diff --git a/stratosphere/sm/source/sm_user_service.cpp b/stratosphere/sm/source/sm_user_service.cpp index 138ceac8c..02c3b8a61 100644 --- a/stratosphere/sm/source/sm_user_service.cpp +++ b/stratosphere/sm/source/sm_user_service.cpp @@ -98,6 +98,20 @@ Result UserService::AtmosphereUninstallMitm(SmServiceName service) { return rc; } +Result UserService::AtmosphereAcknowledgeMitmSession(Out<u64> client_pid, Out<MovedHandle> fwd_h, SmServiceName service) { + Result rc = 0x415; + Handle out_fwd_h = 0; + if (this->has_initialized) { + rc = Registration::AcknowledgeMitmSessionForPid(this->pid, smEncodeName(service.name), &out_fwd_h, client_pid.GetPointer()); + } + + if (R_SUCCEEDED(rc)) { + fwd_h.SetValue(out_fwd_h); + } + + return rc; +} + Result UserService::AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid) { Result rc = 0x415; if (this->has_initialized) { diff --git a/stratosphere/sm/source/sm_user_service.hpp b/stratosphere/sm/source/sm_user_service.hpp index f99f65bc2..3fedda58c 100644 --- a/stratosphere/sm/source/sm_user_service.hpp +++ b/stratosphere/sm/source/sm_user_service.hpp @@ -27,7 +27,8 @@ enum UserServiceCmd { User_Cmd_AtmosphereInstallMitm = 65000, User_Cmd_AtmosphereUninstallMitm = 65001, - User_Cmd_AtmosphereAssociatePidTidForMitm = 65002 + User_Cmd_AtmosphereAssociatePidTidForMitm = 65002, + User_Cmd_AtmosphereAcknowledgeMitmSession = 65003, }; class UserService final : public IServiceObject { @@ -45,6 +46,7 @@ class UserService final : public IServiceObject { virtual Result AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, SmServiceName service); virtual Result AtmosphereUninstallMitm(SmServiceName service); virtual Result AtmosphereAssociatePidTidForMitm(u64 pid, u64 tid); + virtual Result AtmosphereAcknowledgeMitmSession(Out<u64> client_pid, Out<MovedHandle> fwd_h, SmServiceName service); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<User_Cmd_Initialize, &UserService::Initialize>(), @@ -56,6 +58,7 @@ class UserService final : public IServiceObject { MakeServiceCommandMeta<User_Cmd_AtmosphereInstallMitm, &UserService::AtmosphereInstallMitm>(), MakeServiceCommandMeta<User_Cmd_AtmosphereUninstallMitm, &UserService::AtmosphereUninstallMitm>(), MakeServiceCommandMeta<User_Cmd_AtmosphereAssociatePidTidForMitm, &UserService::AtmosphereAssociatePidTidForMitm>(), + MakeServiceCommandMeta<User_Cmd_AtmosphereAcknowledgeMitmSession, &UserService::AtmosphereAcknowledgeMitmSession>(), #endif }; }; From ac391d9c5eeb03a46a936fa06fcc248ded997645 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 14:48:07 -0800 Subject: [PATCH 236/489] Loader: always redirect sysmodules. --- stratosphere/loader/source/ldr_content_management.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 4fa73c093..d63b242d7 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -307,7 +307,7 @@ bool ContentManagement::ShouldReplaceWithHBL(u64 tid) { } bool ContentManagement::ShouldOverrideContents(u64 tid) { - if (HasCreatedTitle(0x0100000000001000)) { + if (tid >= 0x0100000000001000 && HasCreatedTitle(0x0100000000001000)) { u64 kDown = 0; bool keys_triggered = (R_SUCCEEDED(HidManagement::GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0)); return g_has_initialized_fs_dev && (g_override_by_default ^ keys_triggered); From e0c7bfc93dac643d8e3604c9f221f56ea5c7dc3d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 14:59:47 -0800 Subject: [PATCH 237/489] fs.mitm: Always mitm non-sysmodules. --- stratosphere/fs_mitm/source/fsmitm_service.cpp | 10 +++++++++- stratosphere/fs_mitm/source/fsmitm_service.hpp | 13 +++++-------- stratosphere/libstratosphere | 2 +- .../set_mitm/source/setsys_mitm_service.hpp | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index b8384d26c..ebb485c88 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -106,7 +106,7 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out /* PRODINFO should *never* be writable. */ storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); } else { - if (allow_writes) { + if (!allow_writes) { storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); } else { /* Sysmodules should still be allowed to read and write. */ @@ -128,6 +128,10 @@ Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStora u32 out_domain_id = 0; Result rc = 0; + if (!this->should_override_contents) { + return RESULT_FORWARD_TO_SESSION; + } + bool has_cache = StorageCacheGetEntry(this->title_id, &storage); ON_SCOPE_EXIT { @@ -191,6 +195,10 @@ Result FsMitmService::OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterf FsStorageId storage_id = (FsStorageId)sid; FsStorage data_storage; FsFile data_file; + + if (!this->should_override_contents) { + return RESULT_FORWARD_TO_SESSION; + } std::shared_ptr<IStorageInterface> storage = nullptr; u32 out_domain_id = 0; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 33516ccba..3d4c6e3f1 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -30,9 +30,10 @@ enum FspSrvCmd : u32 { class FsMitmService : public IMitmServiceObject { private: bool has_initialized = false; + bool should_override_contents; public: - FsMitmService(std::shared_ptr<Service> s) : IMitmServiceObject(s) { - /* ... */ + FsMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) { + this->should_override_contents = !Utils::HasSdDisableMitMFlag(this->title_id) && Utils::HasOverrideButton(this->title_id); } static bool ShouldMitm(u64 pid, u64 tid) { @@ -40,12 +41,8 @@ class FsMitmService : public IMitmServiceObject { if (tid == 0x010000000000001FULL) { return true; } - - if (Utils::HasSdDisableMitMFlag(tid)) { - return false; - } - - return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)) && Utils::HasOverrideButton(tid); + + return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)); } static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 8fcac73ab..0bec72ca3 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 8fcac73ab2b91afe184abe48c887ea1cb9bf2076 +Subproject commit 0bec72ca36084e9780a8c28abd4a0b24c03c18af diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.hpp b/stratosphere/set_mitm/source/setsys_mitm_service.hpp index 2e3da205f..65a172175 100644 --- a/stratosphere/set_mitm/source/setsys_mitm_service.hpp +++ b/stratosphere/set_mitm/source/setsys_mitm_service.hpp @@ -25,7 +25,7 @@ enum SetSysCmd : u32 { class SetSysMitmService : public IMitmServiceObject { public: - SetSysMitmService(std::shared_ptr<Service> s) : IMitmServiceObject(s) { + SetSysMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) { /* ... */ } From cff283f77dcf22af95374de6eb4e6a2fe0000240 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 15:27:01 -0800 Subject: [PATCH 238/489] fs.mitm: Protect the CAL0 backup from being read. --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 58 ++++--- stratosphere/fs_mitm/source/sha256.c | 113 +++++++++++++ stratosphere/fs_mitm/source/sha256.h | 36 ++++ stratosphere/fs_mitm/source/sha256_armv8.s | 163 +++++++++++++++++++ 4 files changed, 346 insertions(+), 24 deletions(-) create mode 100644 stratosphere/fs_mitm/source/sha256.c create mode 100644 stratosphere/fs_mitm/source/sha256.h create mode 100644 stratosphere/fs_mitm/source/sha256_armv8.s diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index e2f39bb9c..c80c8fe9c 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -23,6 +23,7 @@ #include "debug.hpp" #include "fsmitm_utils.hpp" #include "ini.h" +#include "sha256.h" static FsFileSystem g_sd_filesystem = {0}; static std::vector<u64> g_mitm_flagged_tids; @@ -37,6 +38,11 @@ static bool g_override_by_default = true; /* Static buffer for loader.ini contents at runtime. */ static char g_config_ini_data[0x800]; +/* Backup file for CAL0 partition. */ +static constexpr size_t ProdinfoSize = 0x8000; +static FsFile g_cal0_file; +static u8 g_cal0_backup[ProdinfoSize]; + static bool IsHexadecimal(const char *str) { while (*str) { if (isxdigit(*str)) { @@ -69,8 +75,7 @@ void Utils::InitializeSdThreadFunc(void *args) { fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups"); { FsStorage cal0_storage; - FsFile cal0_file; - bool has_auto_backup = false; + char serial_number[0x40] = {0}; if (R_SUCCEEDED(setsysInitialize())) { @@ -84,32 +89,37 @@ void Utils::InitializeSdThreadFunc(void *args) { } else { snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/PRODINFO.bin"); } - - constexpr size_t PRODINFO_SIZE = 0x4000; - - if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ, &cal0_file))) { - char magic[4]; - size_t read; - if (R_SUCCEEDED(fsFileRead(&cal0_file, 0, magic, sizeof(magic), &read)) && read == sizeof(magic) && memcmp(magic, "CAL0", sizeof(magic)) == 0) { - has_auto_backup = true; + + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &g_cal0_file))) { + bool has_auto_backup = false; + size_t read = 0; + if (R_SUCCEEDED(fsFileRead(&g_cal0_file, 0, g_cal0_backup, sizeof(g_cal0_backup), &read)) && read == sizeof(g_cal0_backup)) { + bool is_cal0_valid = true; + is_cal0_valid &= memcmp(g_cal0_backup, "CAL0", 4) == 0; + is_cal0_valid &= memcmp(g_cal0_backup + 0x250, serial_number, 0x18) == 0; + u32 cal0_size = ((u32 *)g_cal0_backup)[2]; + is_cal0_valid &= cal0_size + 0x40 <= ProdinfoSize; + if (is_cal0_valid) { + struct sha256_state sha_ctx; + u8 calc_hash[0x20]; + sha256_init(&sha_ctx); + sha256_update(&sha_ctx, g_cal0_backup + 0x40, cal0_size); + sha256_finalize(&sha_ctx); + sha256_finish(&sha_ctx, calc_hash); + is_cal0_valid &= memcmp(calc_hash, g_cal0_backup + 0x20, sizeof(calc_hash)) == 0; + } + has_auto_backup = is_cal0_valid; } - fsFileClose(&cal0_file); - } - - if (!has_auto_backup && R_SUCCEEDED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo))) { - u8 *cal0 = new u8[PRODINFO_SIZE]; - if (R_SUCCEEDED(fsStorageRead(&cal0_storage, 0, cal0, PRODINFO_SIZE)) ) { - fsFsCreateFile(&g_sd_filesystem, prodinfo_backup_path, PRODINFO_SIZE, 0); - if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &cal0_file))) { - fsFileSetSize(&cal0_file, PRODINFO_SIZE); - fsFileWrite(&cal0_file, 0, cal0, PRODINFO_SIZE); - fsFileFlush(&cal0_file); - fsFileClose(&cal0_file); + + if (!has_auto_backup && R_SUCCEEDED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo))) { + if (R_SUCCEEDED(fsStorageRead(&cal0_storage, 0, g_cal0_backup, ProdinfoSize)) ) { + fsFileSetSize(&g_cal0_file, ProdinfoSize); + fsFileWrite(&g_cal0_file, 0, g_cal0_backup, ProdinfoSize); + fsFileFlush(&g_cal0_file); } } - delete cal0; - fsStorageClose(&cal0_storage); + /* NOTE: g_cal0_file is intentionally not closed here. This prevents any other process from opening it. */ } } diff --git a/stratosphere/fs_mitm/source/sha256.c b/stratosphere/fs_mitm/source/sha256.c new file mode 100644 index 000000000..02d40a758 --- /dev/null +++ b/stratosphere/fs_mitm/source/sha256.c @@ -0,0 +1,113 @@ +/* Based on linux source code */ +/* + * sha256_base.h - core logic for SHA-256 implementations + * + * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <string.h> +#include "sha256.h" + +#define unlikely(x) __builtin_expect(!!(x), 0) + +void sha256_block_data_order (uint32_t *ctx, const void *in, size_t num); + +int sha256_init(struct sha256_state *sctx) +{ + sctx->state[0] = SHA256_H0; + sctx->state[1] = SHA256_H1; + sctx->state[2] = SHA256_H2; + sctx->state[3] = SHA256_H3; + sctx->state[4] = SHA256_H4; + sctx->state[5] = SHA256_H5; + sctx->state[6] = SHA256_H6; + sctx->state[7] = SHA256_H7; + sctx->count = 0; + + return 0; +} + +int sha256_update(struct sha256_state *sctx, + const void *data, + size_t len) +{ + const u8 *data8 = (const u8 *)data; + unsigned int len32 = (unsigned int)len; + unsigned int partial = sctx->count % SHA256_BLOCK_SIZE; + + sctx->count += len32; + + if (unlikely((partial + len32) >= SHA256_BLOCK_SIZE)) { + int blocks; + + if (partial) { + int p = SHA256_BLOCK_SIZE - partial; + + memcpy(sctx->buf + partial, data8, p); + data8 += p; + len32 -= p; + + sha256_block_data_order(sctx->state, sctx->buf, 1); + } + + blocks = len32 / SHA256_BLOCK_SIZE; + len32 %= SHA256_BLOCK_SIZE; + + if (blocks) { + sha256_block_data_order(sctx->state, data8, blocks); + data8 += blocks * SHA256_BLOCK_SIZE; + } + partial = 0; + } + if (len32) + memcpy(sctx->buf + partial, data8, len32); + + return 0; +} + +int sha256_finalize(struct sha256_state *sctx) +{ + const int bit_offset = SHA256_BLOCK_SIZE - sizeof(u64); + u64 *bits = (u64 *)(sctx->buf + bit_offset); + unsigned int partial = sctx->count % SHA256_BLOCK_SIZE; + + sctx->buf[partial++] = 0x80; + if (partial > bit_offset) { + memset(sctx->buf + partial, 0x0, SHA256_BLOCK_SIZE - partial); + partial = 0; + + sha256_block_data_order(sctx->state, sctx->buf, 1); + } + + memset(sctx->buf + partial, 0x0, bit_offset - partial); + *bits = __builtin_bswap64(sctx->count << 3); + sha256_block_data_order(sctx->state, sctx->buf, 1); + + return 0; +} + +int sha256_finish(struct sha256_state *sctx, void *out) +{ + unsigned int digest_size = 32; + u32 *digest = (u32 *)out; + int i; + + // Switch: misalignment shouldn't be a problem here... + for (i = 0; digest_size > 0; i++, digest_size -= sizeof(u32)) + *digest++ = __builtin_bswap32(sctx->state[i]); + + *sctx = (struct sha256_state){}; + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/stratosphere/fs_mitm/source/sha256.h b/stratosphere/fs_mitm/source/sha256.h new file mode 100644 index 000000000..cfb09f89c --- /dev/null +++ b/stratosphere/fs_mitm/source/sha256.h @@ -0,0 +1,36 @@ +#pragma once + +/* Based on linux source code */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <switch/types.h> + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +#define SHA256_H0 0x6a09e667UL +#define SHA256_H1 0xbb67ae85UL +#define SHA256_H2 0x3c6ef372UL +#define SHA256_H3 0xa54ff53aUL +#define SHA256_H4 0x510e527fUL +#define SHA256_H5 0x9b05688cUL +#define SHA256_H6 0x1f83d9abUL +#define SHA256_H7 0x5be0cd19UL + +struct sha256_state { + u32 state[SHA256_DIGEST_SIZE / 4]; + u64 count; + u8 buf[SHA256_BLOCK_SIZE]; +}; + +int sha256_init(struct sha256_state *sctx); +int sha256_update(struct sha256_state *sctx, const void *data, size_t len); +int sha256_finalize(struct sha256_state *sctx); +int sha256_finish(struct sha256_state *sctx, void *out); + +#ifdef __cplusplus +} +#endif diff --git a/stratosphere/fs_mitm/source/sha256_armv8.s b/stratosphere/fs_mitm/source/sha256_armv8.s new file mode 100644 index 000000000..0420d38be --- /dev/null +++ b/stratosphere/fs_mitm/source/sha256_armv8.s @@ -0,0 +1,163 @@ +.section .text.sha256_armv8, "ax", %progbits +.align 5 +.arch armv8-a+crypto + +# SHA256 assembly implementation for ARMv8 AArch64 (based on linux source code) + +.global sha256_block_data_order +.type sha256_block_data_order,%function +sha256_block_data_order: + +.Lsha256prolog: + + stp x29, x30, [sp,#-64]! + mov x29, sp + adr x3, .LKConstant256 + str q8, [sp, #16] + ld1 {v16.4s-v19.4s}, [x3], #64 + ld1 {v0.4s}, [x0], #16 + ld1 {v20.4s-v23.4s}, [x3], #64 + add x2, x1, x2, lsl #6 + ld1 {v1.4s}, [x0] + ld1 {v24.4s-v27.4s}, [x3], #64 + sub x0, x0, #16 + str q9, [sp, #32] + str q10, [sp, #48] + ld1 {v28.4s-v31.4s}, [x3], #64 + +.Lsha256loop: + + ld1 {v5.16b-v8.16b}, [x1], #64 + mov v2.16b, v0.16b + mov v3.16b, v1.16b + + rev32 v5.16b, v5.16b + rev32 v6.16b, v6.16b + add v9.4s, v5.4s, v16.4s + rev32 v7.16b, v7.16b + add v10.4s, v6.4s, v17.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v5.4s, v6.4s + rev32 v8.16b, v8.16b + add v9.4s, v7.4s, v18.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v6.4s, v7.4s + sha256su1 v5.4s, v7.4s, v8.4s + add v10.4s, v8.4s, v19.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v7.4s, v8.4s + sha256su1 v6.4s, v8.4s, v5.4s + add v9.4s, v5.4s, v20.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v8.4s, v5.4s + sha256su1 v7.4s, v5.4s, v6.4s + add v10.4s, v6.4s, v21.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v5.4s, v6.4s + sha256su1 v8.4s, v6.4s, v7.4s + add v9.4s, v7.4s, v22.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v6.4s, v7.4s + sha256su1 v5.4s, v7.4s, v8.4s + add v10.4s, v8.4s, v23.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v7.4s, v8.4s + sha256su1 v6.4s, v8.4s, v5.4s + add v9.4s, v5.4s, v24.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v8.4s, v5.4s + sha256su1 v7.4s, v5.4s, v6.4s + add v10.4s, v6.4s, v25.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v5.4s, v6.4s + sha256su1 v8.4s, v6.4s, v7.4s + add v9.4s, v7.4s, v26.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v6.4s, v7.4s + sha256su1 v5.4s, v7.4s, v8.4s + add v10.4s, v8.4s, v27.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su0 v7.4s, v8.4s + sha256su1 v6.4s, v8.4s, v5.4s + add v9.4s, v5.4s, v28.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + sha256su0 v8.4s, v5.4s + sha256su1 v7.4s, v5.4s, v6.4s + add v10.4s, v6.4s, v29.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + sha256su1 v8.4s, v6.4s, v7.4s + add v9.4s, v7.4s, v30.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + add v10.4s, v8.4s, v31.4s + mov v4.16b, v2.16b + sha256h q2, q3, v9.4s + sha256h2 q3, q4, v9.4s + mov v4.16b, v2.16b + sha256h q2, q3, v10.4s + sha256h2 q3, q4, v10.4s + cmp x1, x2 + add v1.4s, v1.4s, v3.4s + add v0.4s, v0.4s, v2.4s + b.ne .Lsha256loop + +.Lsha256epilog: + + st1 {v0.4s,v1.4s}, [x0] + ldr q10, [sp, #48] + ldr q9, [sp, #32] + ldr q8, [sp, #16] + ldr x29, [sp], #64 + ret + +.align 5 +.LKConstant256: +.word 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.word 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.word 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.word 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.word 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc +.word 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.word 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.word 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 +.word 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.word 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.word 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.word 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.word 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.word 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.word 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 + +.size sha256_block_data_order,.-sha256_block_data_order +.align 2 + + + From ff09efb1bf07fc8e00e48cd02e96e939808fa69a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 15:29:02 -0800 Subject: [PATCH 239/489] fs.mitm: Prevent non-sysmodules from reading CAL0. --- stratosphere/fs_mitm/source/fsmitm_service.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index ebb485c88..9897edf6f 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -99,14 +99,21 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out FsStorage bis_storage; rc = fsOpenBisStorageFwd(this->forward_service.get(), &bis_storage, bis_partition_id); if (R_SUCCEEDED(rc)) { - const bool allow_writes = this->title_id < 0x0100000000001000; + const bool is_sysmodule = this->title_id < 0x0100000000001000; if (bis_partition_id == BisStorageId_Boot0) { storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id)); } else if (bis_partition_id == BisStorageId_Prodinfo) { /* PRODINFO should *never* be writable. */ - storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); + if (is_sysmodule) { + storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); + } else { + /* Do not allow non-sysmodules to read *or* write CAL0. */ + fsStorageClose(&bis_storage); + return 0x320002; + } } else { - if (!allow_writes) { + if (!is_sysmodule) { + /* Non-sysmodules should be allowed to read. */ storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); } else { /* Sysmodules should still be allowed to read and write. */ From 2b4e6bf25d08b95f652cec789c0c8970121371ae Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 15:46:05 -0800 Subject: [PATCH 240/489] fs.mitm: just intercept literally everything --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 2 +- stratosphere/fs_mitm/source/fsmitm_service.hpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 95f627d7a..d7dcf136b 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -78,7 +78,7 @@ void __appExit(void) { struct FsMitmManagerOptions { static const size_t PointerBufferSize = 0x800; - static const size_t MaxDomains = 0x10; + static const size_t MaxDomains = 0x40; static const size_t MaxDomainObjects = 0x4000; }; using FsMitmManager = WaitableManager<FsMitmManagerOptions>; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 3d4c6e3f1..777782b46 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -33,16 +33,16 @@ class FsMitmService : public IMitmServiceObject { bool should_override_contents; public: FsMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) { - this->should_override_contents = !Utils::HasSdDisableMitMFlag(this->title_id) && Utils::HasOverrideButton(this->title_id); + if (Utils::HasSdDisableMitMFlag(this->title_id)) { + this->should_override_contents = false; + } else { + this->should_override_contents = (this->title_id >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(this->title_id)) && Utils::HasOverrideButton(this->title_id); + } } static bool ShouldMitm(u64 pid, u64 tid) { - /* Always intercept NS, so that we can protect the boot partition. */ - if (tid == 0x010000000000001FULL) { - return true; - } - - return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)); + /* fs.mitm should always mitm everything. */ + return true; } static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); From abde50f16205f8c24a59530c310a845421f14ca9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 15:58:31 -0800 Subject: [PATCH 241/489] fs.mitm: wipe CAL0 backup from memory when done. --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index c80c8fe9c..7e47f0d60 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -120,6 +120,7 @@ void Utils::InitializeSdThreadFunc(void *args) { } /* NOTE: g_cal0_file is intentionally not closed here. This prevents any other process from opening it. */ + memset(g_cal0_backup, 0, sizeof(g_cal0_backup)); } } From d88fd04c73a83f42a3b49b0c41b6b7ad7ee64928 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 17:23:05 -0800 Subject: [PATCH 242/489] fs.mitm: fix set:sys race condition. --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 2 +- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 26 +++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index d7dcf136b..9d477261d 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -88,7 +88,7 @@ int main(int argc, char **argv) Thread sd_initializer_thread = {0}; Thread hid_initializer_thread = {0}; consoleDebugInit(debugDevice_SVC); - + if (R_FAILED(threadCreate(&sd_initializer_thread, &Utils::InitializeSdThreadFunc, NULL, 0x4000, 0x15, 0))) { /* TODO: Panic. */ } diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 7e47f0d60..e692bdc5b 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -40,7 +40,8 @@ static char g_config_ini_data[0x800]; /* Backup file for CAL0 partition. */ static constexpr size_t ProdinfoSize = 0x8000; -static FsFile g_cal0_file; +static FsFile g_cal0_file = {0}; +static u8 g_cal0_storage_backup[ProdinfoSize]; static u8 g_cal0_backup[ProdinfoSize]; static bool IsHexadecimal(const char *str) { @@ -75,13 +76,14 @@ void Utils::InitializeSdThreadFunc(void *args) { fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups"); { FsStorage cal0_storage; + if (R_FAILED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo)) || R_FAILED(fsStorageRead(&cal0_storage, 0, g_cal0_storage_backup, ProdinfoSize))) { + std::abort(); + } + fsStorageClose(&cal0_storage); char serial_number[0x40] = {0}; + memcpy(serial_number, g_cal0_storage_backup + 0x250, 0x18); - if (R_SUCCEEDED(setsysInitialize())) { - setsysGetSerialNumber(serial_number); - setsysExit(); - } char prodinfo_backup_path[FS_MAX_PATH] = {0}; if (strlen(serial_number) > 0) { @@ -89,7 +91,8 @@ void Utils::InitializeSdThreadFunc(void *args) { } else { snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/PRODINFO.bin"); } - + + fsFsCreateFile(&g_sd_filesystem, prodinfo_backup_path, ProdinfoSize, 0); if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &g_cal0_file))) { bool has_auto_backup = false; size_t read = 0; @@ -111,15 +114,14 @@ void Utils::InitializeSdThreadFunc(void *args) { has_auto_backup = is_cal0_valid; } - if (!has_auto_backup && R_SUCCEEDED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo))) { - if (R_SUCCEEDED(fsStorageRead(&cal0_storage, 0, g_cal0_backup, ProdinfoSize)) ) { - fsFileSetSize(&g_cal0_file, ProdinfoSize); - fsFileWrite(&g_cal0_file, 0, g_cal0_backup, ProdinfoSize); - fsFileFlush(&g_cal0_file); - } + if (!has_auto_backup) { + fsFileSetSize(&g_cal0_file, ProdinfoSize); + fsFileWrite(&g_cal0_file, 0, g_cal0_backup, ProdinfoSize); + fsFileFlush(&g_cal0_file); } /* NOTE: g_cal0_file is intentionally not closed here. This prevents any other process from opening it. */ + memset(g_cal0_storage_backup, 0, sizeof(g_cal0_storage_backup)); memset(g_cal0_backup, 0, sizeof(g_cal0_backup)); } } From a07e37121dafd1c2027e7bda1db03bba1d059927 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 15 Nov 2018 18:25:11 -0800 Subject: [PATCH 243/489] fs.mitm: loosen boot0 write restrictions, protect keyblobs. --- .../fs_mitm/source/fsmitm_boot0storage.cpp | 50 +++++++++++++++---- .../fs_mitm/source/fsmitm_boot0storage.hpp | 5 +- .../fs_mitm/source/fsmitm_service.hpp | 4 +- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp index e2b25ad40..1554496bd 100644 --- a/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp @@ -23,10 +23,6 @@ static HosMutex g_boot0_mutex; static u8 g_boot0_bct_buffer[Boot0Storage::BctEndOffset]; -bool Boot0Storage::AllowWrites() { - return this->title_id < 0x0100000000001000ULL; -} - bool Boot0Storage::CanModifyBctPubks() { return this->title_id != 0x010000000000001FULL; } @@ -40,18 +36,52 @@ Result Boot0Storage::Read(void *_buffer, size_t size, u64 offset) { Result Boot0Storage::Write(void *_buffer, size_t size, u64 offset) { std::scoped_lock<HosMutex> lk{g_boot0_mutex}; - if (!AllowWrites()) { - return 0x313802; + Result rc = 0; + u8 *buffer = static_cast<u8 *>(_buffer); + + /* Protect the keyblob region from writes. */ + if (offset <= EksStart) { + if (offset + size < EksStart) { + /* Fall through, no need to do anything here. */ + } else { + if (offset + size < EksEnd) { + /* Adjust size to avoid writing end of data. */ + size = EksStart - offset; + } else { + /* Perform portion of write falling past end of keyblobs. */ + const u64 diff = EksEnd - offset; + if (R_FAILED((rc = Base::Write(buffer + diff, size - diff, EksEnd)))) { + return rc; + } + /* Adjust size to avoid writing end of data. */ + size = EksStart - offset; + } + } + } else { + if (offset < EksEnd) { + if (offset + size < EksEnd) { + /* Ignore writes falling strictly within the region. */ + return 0; + } else { + /* Only write past the end of the keyblob region. */ + buffer = buffer + (EksEnd - offset); + size -= (EksEnd - offset); + offset = EksEnd; + } + } else { + /* Fall through, no need to do anything here. */ + } + } + + if (size == 0) { + return 0; } /* We care about protecting autorcm from NS. */ if (CanModifyBctPubks() || offset >= BctEndOffset || (offset + BctSize >= BctEndOffset && offset % BctSize >= BctPubkEnd)) { - return Base::Write(_buffer, size, offset); + return Base::Write(buffer, size, offset); } - Result rc = 0; - u8 *buffer = static_cast<u8 *>(_buffer); - /* First, let's deal with the data past the end. */ if (offset + size >= BctEndOffset) { const u64 diff = BctEndOffset - offset; diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp index cf53948f4..b86791ff8 100644 --- a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp @@ -142,10 +142,13 @@ class Boot0Storage : public SectoredProxyStorage<0x200> { static constexpr u64 BctPubkStart = 0x210; static constexpr u64 BctPubkSize = 0x100; static constexpr u64 BctPubkEnd = BctPubkStart + BctPubkSize; + + static constexpr u64 EksStart = 0x180000; + static constexpr u64 EksSize = 0x4000; + static constexpr u64 EksEnd = EksStart + EksSize; private: u64 title_id; private: - bool AllowWrites(); bool CanModifyBctPubks(); public: Boot0Storage(FsStorage *s, u64 t) : Base(s), title_id(t) { } diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 777782b46..fd69bc85a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -41,8 +41,8 @@ class FsMitmService : public IMitmServiceObject { } static bool ShouldMitm(u64 pid, u64 tid) { - /* fs.mitm should always mitm everything. */ - return true; + /* fs.mitm should always mitm everything that's not a kip. */ + return pid >= 0x50; } static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); From 6e7eb47d33704b3c2fe4056d7a867eb8979b6f4f Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Sat, 17 Nov 2018 21:50:31 +0000 Subject: [PATCH 244/489] fusee: Minor hardware configuration fixes. --- fusee/fusee-primary/src/hwinit.c | 2 +- fusee/fusee-primary/src/mc.c | 4 +++- fusee/fusee-secondary/src/cluster.c | 9 ++++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index ef01ec23c..d5f68d82b 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -234,7 +234,7 @@ void nx_hwinit() /* Reboot SE. */ /* NOTE: [4.0.0+] This was removed. */ - clkrst_reboot(CARDEVICE_SE); + /* clkrst_reboot(CARDEVICE_SE); */ /* Reboot unknown device. */ clkrst_reboot(CARDEVICE_UNK); diff --git a/fusee/fusee-primary/src/mc.c b/fusee/fusee-primary/src/mc.c index 4cacac363..e803d7a7c 100644 --- a/fusee/fusee-primary/src/mc.c +++ b/fusee/fusee-primary/src/mc.c @@ -160,7 +160,9 @@ void mc_enable() car->clk_enb_x_set = ((car->clk_enb_x_set & 0xFFFFBFFF) | 0x4000); /* Clear EMC and MC reset. */ - car->rst_dev_h_set = 0x2000001; + /* NOTE: [4.0.0+] This was changed to use the right register. */ + /* car->rst_dev_h_set = 0x2000001; */ + car->rst_dev_h_clr = 0x2000001; udelay(5); mc_disable_ahb_redirect(); diff --git a/fusee/fusee-secondary/src/cluster.c b/fusee/fusee-secondary/src/cluster.c index 89ce71988..747d53884 100644 --- a/fusee/fusee-secondary/src/cluster.c +++ b/fusee/fusee-secondary/src/cluster.c @@ -22,6 +22,7 @@ #include "sysreg.h" #include "i2c.h" #include "car.h" +#include "mc.h" #include "timers.h" #include "pmc.h" #include "max77620.h" @@ -141,6 +142,10 @@ void cluster_boot_cpu0(uint32_t entry) SB_CSR_0 = 2; (void)SB_CSR_0; + /* Set CPU_STRICT_TZ_APERTURE_CHECK. */ + /* NOTE: [4.0.0+] This was added, but it breaks Exosphère. */ + /* MAKE_MC_REG(MC_TZ_SECURITY_CTRL) = 1; */ + /* Clear MSELECT reset. */ car->rst_dev_v &= 0xFFFFFFF7; @@ -148,5 +153,7 @@ void cluster_boot_cpu0(uint32_t entry) car->rst_cpug_cmplx_clr = 0x20000000; /* Clear CPU{0,1,2,3} POR and CORE, CX0, L2, and DBG reset.*/ - car->rst_cpug_cmplx_clr = 0x411F000F; + /* NOTE: [5.0.0+] This was changed so only CPU0 reset is cleared. */ + /* car->rst_cpug_cmplx_clr = 0x411F000F; */ + car->rst_cpug_cmplx_clr = 0x41010001; } From 13aa774d7a42a652e2f16ee9d85570bfdd302f5f Mon Sep 17 00:00:00 2001 From: misson20000 <xenotoad@xenotoad.net> Date: Sun, 18 Nov 2018 17:01:24 -0800 Subject: [PATCH 245/489] add docs for SetExternalContentSource --- docs/modules/loader.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/modules/loader.md b/docs/modules/loader.md index 6bde97faa..5ed0f5162 100644 --- a/docs/modules/loader.md +++ b/docs/modules/loader.md @@ -66,3 +66,17 @@ For example, `override_key=!R` will run the game only while holding down R when ### SM MITM Integration When the Stratosphere implementation of loader creates a new process, it notifies [sm](sm.md) through the `AtmosphereAssociatePidTidForMitm` command to notify any MITM services of new processes' identities. + +### IPC: AtmosphereSetExternalContentSource + +An additional command is added to the [`ldr:shel`](https://reswitched.github.io/SwIPC/ifaces.html#nn::ro::detail::ILdrShellInterface) interface, called `AtmosphereSetExternalContentSource`. It's command ID is `65000` on all system firmware versions. It takes a `u64 tid` and returns a server-side session handle. The client is expected to implement the `IFileSystem` interface on the returned handle. The next time the title specified by the given title ID is launched, its ExeFS contents will be loaded from the custom `IFileSystem` instead of from SD card or original ExeFS. NSOs loaded from external content source may still be subject to exefs IPS patches. After the title is launched, the `IFileSystem` is closed and the external content source override is removed. If `AtmosphereSetExternalContentSource` is called on a title that already has an external content source set for it, the existing one will be removed and replaced with the new one. It is illegal to call `AtmosphereSetExternalContentSource` while the title is being launched. + +The `IFileSystem` only needs to implement `OpenFile`. The paths received by the `IFileSystem`'s `OpenFile` command begin with slashes, as in `/main`, `/rtld`, and `/main.npdm`. A result code of 0x202 should be returned if the file does not exist. The `IFile`s returned from `OpenFile` only need to implement `Read` and `GetSize`. + +The SwIPC definition for the `AtmosphereSetExternalContentSource` command follows. +``` +interface nn::ldr::detail::IShellInterface is ldr:shel { + ... + [65000] AtmosphereSetExternalContentSource(u64 tid) -> handle<copy, session_server> ifilesystem_handle; +} +``` From 982797df313c813e0bb69cffc31545fadcd2cc58 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Mon, 19 Nov 2018 20:05:47 +0000 Subject: [PATCH 246/489] fusee: Fix custom splash screen loading. --- fusee/fusee-secondary/src/splash_screen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index 17cc302af..37cc63d9d 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -44,7 +44,7 @@ void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address) /* Try to load an external custom splash screen. */ if ((custom_splash_path != NULL) && (custom_splash_path[0] != '\x00')) { - if (!read_from_file(splash_screen, sizeof(&splash_screen_bmp), custom_splash_path)) { + if (!read_from_file(splash_screen, splash_screen_bmp_size, custom_splash_path)) { fatal_error("Failed to read custom splash screen from %s!\n", custom_splash_path); } } From e214f4d32561224d91f4d33d7ffc11ecd2ee1cd3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 25 Nov 2018 15:51:04 -0800 Subject: [PATCH 247/489] exosphere: update for new master key --- exosphere/src/masterkey.c | 6 ++++-- exosphere/src/masterkey.h | 7 ++++--- exosphere/src/smc_user.c | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/exosphere/src/masterkey.c b/exosphere/src/masterkey.c index 89e175267..30299a24d 100644 --- a/exosphere/src/masterkey.c +++ b/exosphere/src/masterkey.c @@ -40,6 +40,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = {0x2C, 0xCA, 0x9C, 0x31, 0x1E, 0x07, 0xB0, 0x02, 0x97, 0x0A, 0xD8, 0x03, 0xA2, 0x76, 0x3F, 0xA3}, /* Master key 02 encrypted with Master key 03. */ {0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ + {0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */ }; /* Retail unit keys. */ @@ -51,6 +52,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = {0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */ {0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ + {0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */ }; bool check_mkey_revision(unsigned int revision, bool is_retail) { @@ -123,7 +125,7 @@ unsigned int mkey_get_keyslot(unsigned int revision) { void set_old_devkey(unsigned int revision, const uint8_t *key) { - if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_600_CURRENT <= revision) { + if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_MAX <= revision) { generic_panic(); } @@ -140,7 +142,7 @@ unsigned int devkey_get_keyslot(unsigned int revision) { } if (revision >= 1) { - if (revision == MASTERKEY_REVISION_600_CURRENT) { + if (revision == MASTERKEY_REVISION_MAX) { return KEYSLOT_SWITCH_DEVICEKEY; } else { /* Load into a temp keyslot. */ diff --git a/exosphere/src/masterkey.h b/exosphere/src/masterkey.h index 0ca987ee0..9341e2cd6 100644 --- a/exosphere/src/masterkey.h +++ b/exosphere/src/masterkey.h @@ -19,15 +19,16 @@ /* This is glue code to enable master key support across versions. */ -/* TODO: Update to 0x7 on release of new master key. */ -#define MASTERKEY_REVISION_MAX 0x6 +/* TODO: Update to 0x8 on release of new master key. */ +#define MASTERKEY_REVISION_MAX 0x7 #define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_300 0x01 #define MASTERKEY_REVISION_301_302 0x02 #define MASTERKEY_REVISION_400_410 0x03 #define MASTERKEY_REVISION_500_510 0x04 -#define MASTERKEY_REVISION_600_CURRENT 0x05 +#define MASTERKEY_REVISION_600_610 0x05 +#define MASTERKEY_REVISION_620_CURRENT 0x06 #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c index c2b1fbecb..5c2b9c2b6 100644 --- a/exosphere/src/smc_user.c +++ b/exosphere/src/smc_user.c @@ -166,7 +166,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) { /* 5.0.0+ Bounds checking. */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { if (is_personalized) { - if (master_key_rev > MASTERKEY_REVISION_600_CURRENT || ((1 << (master_key_rev + 1)) & 0x73) == 0) { + if (master_key_rev > MASTERKEY_REVISION_MAX || (MASTERKEY_REVISION_300 <= master_key_rev + 1 && master_key_rev + 1 < MASTERKEY_REVISION_400_410)) { return 2; } if (mask_id > 3 || usecase >= CRYPTOUSECASE_MAX_5X) { From eab5e0df9bbd4dbc0258f384807c1013df0ee6b0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 25 Nov 2018 16:06:46 -0800 Subject: [PATCH 248/489] exosphere: add EXOSPHERE_TARGET_FIRMWARE_620 --- exosphere/src/exocfg.c | 22 +++++++++++++++++++--- exosphere/src/exocfg.h | 20 +++++++++++++++++--- exosphere/src/package2.c | 3 +++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index 82761b318..4fbe8996e 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -27,9 +27,12 @@ /* TODO: Should this be at a non-static location? */ #define MAILBOX_EXOSPHERE_CONFIG (*((volatile exosphere_config_t *)(MAILBOX_BASE + 0xE40ULL))) -static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_BOOTCONFIG, EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG}; +static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_BOOTCONFIG, EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG, EXOSPHERE_FLAGS_DEFAULT}; static bool g_has_loaded_config = false; +#define EXOSPHERE_CHECK_FLAG(flag) ((g_exosphere_cfg.flags & flag) != 0) + + /* Read config out of IRAM, return target firmware version. */ unsigned int exosphere_load_config(void) { if (g_has_loaded_config) { @@ -37,8 +40,13 @@ unsigned int exosphere_load_config(void) { } g_has_loaded_config = true; - if (MAILBOX_EXOSPHERE_CONFIG.magic == MAGIC_EXOSPHERE_BOOTCONFIG) { + const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG.magic; + + if (magic == MAGIC_EXOSPHERE_BOOTCONFIG) { g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG; + } else if (magic == MAGIC_EXOSPHERE_BOOTCONFIG_0) { + g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG; + g_exosphere_cfg.flags = EXOSPHERE_FLAGS_DEFAULT; } return g_exosphere_cfg.target_firmware; @@ -50,4 +58,12 @@ unsigned int exosphere_get_target_firmware(void) { } return g_exosphere_cfg.target_firmware; -} \ No newline at end of file +} + +unsigned int exosphere_get_should_perform_620_keygen(void) { + if (!g_has_loaded_config) { + generic_panic(); + } + + return g_exosphere_cfg.target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620 && EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_PERFORM_620_KEYGEN); +} diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 5ed924b48..2a1dc810d 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -25,7 +25,9 @@ /* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */ /* "XBC0" */ -#define MAGIC_EXOSPHERE_BOOTCONFIG (0x30434258) +#define MAGIC_EXOSPHERE_BOOTCONFIG_0 (0x30434258) +/* "XBC1" */ +#define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258) #define EXOSPHERE_TARGET_FIRMWARE_100 1 #define EXOSPHERE_TARGET_FIRMWARE_200 2 @@ -33,9 +35,12 @@ #define EXOSPHERE_TARGET_FIRMWARE_400 4 #define EXOSPHERE_TARGET_FIRMWARE_500 5 #define EXOSPHERE_TARGET_FIRMWARE_600 6 +#define EXOSPHERE_TARGET_FIRMWARE_620 7 + +#define EXOSPHERE_TARGET_FIRMWARE_CURRENT EXOSPHERE_TARGET_FIRMWARE_620 /* TODO: What should this be, for release? */ -#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_600 +#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_CURRENT #define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1 #define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) @@ -43,17 +48,26 @@ /* TODO: Should this be at a non-static location? */ #define MAILBOX_EXOSPHERE_CONFIG_PHYS (*((volatile exosphere_config_t *)(MAILBOX_BASE_PHYS + 0xE40ULL))) +#define EXOSPHERE_FLAGS_DEFAULT 0x00000000 +#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) typedef struct { unsigned int magic; unsigned int target_firmware; + unsigned int flags; } exosphere_config_t; unsigned int exosphere_load_config(void); unsigned int exosphere_get_target_firmware(void); +unsigned int exosphere_get_should_perform_620_keygen(void); static inline unsigned int exosphere_get_target_firmware_for_init(void) { - return MAILBOX_EXOSPHERE_CONFIG_PHYS.magic == MAGIC_EXOSPHERE_BOOTCONFIG ? MAILBOX_EXOSPHERE_CONFIG_PHYS.target_firmware : EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG; + const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic; + if (magic == MAGIC_EXOSPHERE_BOOTCONFIG || magic == MAGIC_EXOSPHERE_BOOTCONFIG_0) { + return MAILBOX_EXOSPHERE_CONFIG_PHYS.target_firmware; + } else { + return EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG; + } } #endif diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 1281f9498..94fa821d5 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -486,6 +486,9 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { case EXOSPHERE_TARGET_FIRMWARE_600: MAKE_REG32(PMC_BASE + 0x360) = 0x87; break; + case EXOSPHERE_TARGET_FIRMWARE_620: + MAKE_REG32(PMC_BASE + 0x360) = 0xA8; + break; } } From c3569ec5e2a725843bc9dd5073e8e7891fc3a356 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 25 Nov 2018 16:22:47 -0800 Subject: [PATCH 249/489] fusee: support getting old tsec key from new tsec fw. --- fusee/fusee-secondary/src/exocfg.h | 11 +++++-- fusee/fusee-secondary/src/key_derivation.c | 5 +-- fusee/fusee-secondary/src/nxboot.c | 36 ++++++++++++++-------- fusee/fusee-secondary/src/package1.c | 16 ++++++---- fusee/fusee-secondary/src/package1.h | 2 +- fusee/fusee-secondary/src/tsec.c | 4 +-- fusee/fusee-secondary/src/tsec.h | 2 +- 7 files changed, 50 insertions(+), 26 deletions(-) diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index 2b3417629..d62775834 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -20,7 +20,9 @@ /* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */ /* "XBC0" */ -#define MAGIC_EXOSPHERE_BOOTCONFIG (0x30434258) +#define MAGIC_EXOSPHERE_BOOTCONFIG_0 (0x30434258) +/* "XBC1" */ +#define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258) #define EXOSPHERE_TARGET_FIRMWARE_100 1 #define EXOSPHERE_TARGET_FIRMWARE_200 2 @@ -28,13 +30,18 @@ #define EXOSPHERE_TARGET_FIRMWARE_400 4 #define EXOSPHERE_TARGET_FIRMWARE_500 5 #define EXOSPHERE_TARGET_FIRMWARE_600 6 +#define EXOSPHERE_TARGET_FIRMWARE_620 7 #define EXOSPHERE_TARGET_FIRMWARE_MIN EXOSPHERE_TARGET_FIRMWARE_100 -#define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_600 +#define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_620 + +#define EXOSPHERE_FLAGS_DEFAULT 0x00000000 +#define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) typedef struct { unsigned int magic; unsigned int target_firmware; + unsigned int flags; } exosphere_config_t; #define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40)) diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index e67d3dfbd..825bc9d3e 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -56,7 +56,7 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = { static nx_dec_keyblob_t AL16 g_dec_keyblobs[32]; static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uint32_t tsec_key_id) { - return tsec_get_key(dst, tsec_key_id, tsec_fw); + return tsec_get_key(dst, tsec_key_id, tsec_fw, tsec_fw_size); } static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) { @@ -125,9 +125,10 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui set_aes_keyslot_flags(0xD, 0x15); /* Set TSEC key. */ - if (get_tsec_key(work_buffer, tsec_fw, tsec_fw_size, 1) != 0) { + if (get_tsec_key(work_buffer, tsec_fw, tsec_fw_size, 1) != 0) { return -1; } + set_aes_keyslot(0xD, work_buffer, 0x10); /* Decrypt all keyblobs, setting keyslot 0xF correctly. */ diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 9b9c73ed2..0380b3544 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -76,8 +76,15 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { return EXOSPHERE_TARGET_FIRMWARE_400; case 0x0B: /* 5.0.0 - 5.1.0 */ return EXOSPHERE_TARGET_FIRMWARE_500; - case 0x0E: /* 6.0.0 */ - return EXOSPHERE_TARGET_FIRMWARE_600; + case 0x0E: { /* 6.0.0 - 6.2.0 */ + if (memcmp(package1loader_header->build_timestamp, "20180802", 8) == 0) { + return EXOSPHERE_TARGET_FIRMWARE_600; + } else if (memcmp(package1loader_header->build_timestamp, "20181107", 8) == 0) { + return EXOSPHERE_TARGET_FIRMWARE_620; + } else { + fatal_error("[NXBOOT]: Unable to identify package1!\n"); + } + } default: return 0; } @@ -88,6 +95,7 @@ static void nxboot_configure_exosphere(uint32_t target_firmware) { exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG; exo_cfg.target_firmware = target_firmware; + exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT; if (ini_parse_string(get_loader_ctx()->bct0, exosphere_ini_handler, &exo_cfg) < 0) { fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); @@ -260,11 +268,18 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Couldn't parse boot0: %s!\n", strerror(errno)); } fclose(boot0); + + /* Find the system's target firmware. */ + uint32_t target_firmware = nxboot_get_target_firmware(package1loader); + if (!target_firmware) + fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); + else + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware); /* Read the TSEC firmware from a file, otherwise from PK1L. */ if (loader_ctx->tsecfw_path[0] != '\0') { tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); - if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00)) { + if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900)) { fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); } else if (tsec_fw_size == 0) { fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); @@ -280,19 +295,16 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); } } else { - tsec_fw_size = package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size); - if (tsec_fw_size == 0) { + if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); } + if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + tsec_fw_size = 0x2900; + } else { + tsec_fw_size = 0xF00; + } } - /* Find the system's target firmware. */ - uint32_t target_firmware = nxboot_get_target_firmware(package1loader); - if (!target_firmware) - fatal_error("[NXBOOT]: Failed to detect target firmware!\n"); - else - print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Detected target firmware %ld!\n", target_firmware); - print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); /* Setup boot configuration for Exosphère. */ diff --git a/fusee/fusee-secondary/src/package1.c b/fusee/fusee-secondary/src/package1.c index 46ff14787..4f62310b6 100644 --- a/fusee/fusee-secondary/src/package1.c +++ b/fusee/fusee-secondary/src/package1.c @@ -90,15 +90,19 @@ int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_ return 0; } -size_t package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size) { +bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size) { /* The TSEC firmware is always located at a 256-byte aligned address. */ - /* We're looking for its 4 first bytes. We assume its size is always 0xF00 bytes. */ + /* We're looking for its 4 first bytes. */ const uint32_t *pos; uintptr_t pk1l = (uintptr_t)package1loader; - for (pos = (const uint32_t *)pk1l; (uintptr_t)pos < pk1l + package1loader_size && *pos != 0xCF42004D; pos += 0x40); - - (*tsec_fw) = (void *)pos; - return 0xF00; + for (pos = (const uint32_t *)pk1l; (uintptr_t)pos < pk1l + package1loader_size; pos += 0x40) { + if (*pos == 0xCF42004D) { + (*tsec_fw) = (void *)pos; + return true; + } + } + + return false; } size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size) { diff --git a/fusee/fusee-secondary/src/package1.h b/fusee/fusee-secondary/src/package1.h index 79bf25fbe..c20c88db4 100644 --- a/fusee/fusee-secondary/src/package1.h +++ b/fusee/fusee-secondary/src/package1.h @@ -46,7 +46,7 @@ typedef struct { int package1_read_and_parse_boot0(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0); -size_t package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size); +bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t package1loader_size); size_t package1_get_encrypted_package1(package1_header_t **package1, uint8_t *ctr, const void *package1loader, size_t package1loader_size); /* Must be aligned to 16 bytes. */ diff --git a/fusee/fusee-secondary/src/tsec.c b/fusee/fusee-secondary/src/tsec.c index f9cfeaa04..b864df405 100644 --- a/fusee/fusee-secondary/src/tsec.c +++ b/fusee/fusee-secondary/src/tsec.c @@ -49,7 +49,7 @@ static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t ph return tsec_dma_wait_idle(); } -int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw) +int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size) { volatile tegra_tsec_t *tsec = tsec_get_regs(); @@ -82,7 +82,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw) /* Load firmware. */ tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8; - for (uint32_t addr = 0; addr < 0xF00; addr += 0x100) + for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100) { if (!tsec_dma_phys_to_flcn(true, addr, addr)) { diff --git a/fusee/fusee-secondary/src/tsec.h b/fusee/fusee-secondary/src/tsec.h index 3ff537172..c16c2f9a3 100644 --- a/fusee/fusee-secondary/src/tsec.h +++ b/fusee/fusee-secondary/src/tsec.h @@ -109,6 +109,6 @@ static inline volatile tegra_tsec_t *tsec_get_regs(void) return (volatile tegra_tsec_t *)TSEC_BASE; } -int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw); +int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size); #endif \ No newline at end of file From a71d98d78b48b0e2e328218bcddfef581bfbcdd5 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 25 Nov 2018 17:11:21 -0800 Subject: [PATCH 250/489] exosphere: Implement optional 6.2.0+ keygen --- exosphere/src/exocfg.c | 2 +- exosphere/src/exocfg.h | 2 +- exosphere/src/package2.c | 60 ++++++++++++++++++++++++++++++++++------ exosphere/src/se.h | 5 ++++ 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index 4fbe8996e..10bc3ae64 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -60,7 +60,7 @@ unsigned int exosphere_get_target_firmware(void) { return g_exosphere_cfg.target_firmware; } -unsigned int exosphere_get_should_perform_620_keygen(void) { +unsigned int exosphere_should_perform_620_keygen(void) { if (!g_has_loaded_config) { generic_panic(); } diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 2a1dc810d..286825965 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -59,7 +59,7 @@ typedef struct { unsigned int exosphere_load_config(void); unsigned int exosphere_get_target_firmware(void); -unsigned int exosphere_get_should_perform_620_keygen(void); +unsigned int exosphere_should_perform_620_keygen(void); static inline unsigned int exosphere_get_target_firmware_for_init(void) { const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic; diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 94fa821d5..c6ef81dc2 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -38,21 +38,48 @@ extern void *__start_cold_addr; extern size_t __bin_size; static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { - {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ - {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */ - {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4} /* 6.x New Device Key Source. */ + {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ + {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */ + {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.x New Device Key Source. */ + {0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17} /* 6.2.0 New Device Key Source. */ }; static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { - {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */ - {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */ - {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF} /* 6.x New Device Keygen Source. */ + {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */ + {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */ + {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.x New Device Keygen Source. */ + {0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB} /* 6.2.0 New Device Keygen Source. */ }; static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { - {0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */ - {0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */ - {0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5} /* 6.x New Device Keygen Source. */ + {0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */ + {0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */ + {0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5}, /* 6.x New Device Keygen Source. */ + {0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38} /* 6.2.0 New Device Keygen Source. */ +}; + +static const uint8_t new_master_kek_sources[1][0x10] = { + {0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* 6.2.0 Master Kek Source. */ +}; + +static const uint8_t keyblob_key_seed_00[0x10] = { + 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 +}; + +static const uint8_t devicekey_seed[0x10] = { + 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 +}; + +static const uint8_t devicekey_4x_seed[0x10] = { + 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 +}; + +static const uint8_t masterkey_seed[0x10] = { + 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C +}; + +static const uint8_t devicekek_4x_seed[0x10] = { + 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 }; static void derive_new_device_keys(unsigned int keygen_keyslot) { @@ -105,6 +132,20 @@ static void setup_se(void) { for (unsigned int i = 0; i < KEYSLOT_RSA_MAX; i++) { set_rsa_keyslot_flags(i, 0x41); } + + if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_620 && exosphere_should_perform_620_keygen()) { + /* Start by generating device keys. */ + se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_6XTSECKEY, work_buffer, 0x10, keyblob_key_seed_00, 0x10); + decrypt_data_into_keyslot(KEYSLOT_SWITCH_4XOLDDEVICEKEY, KEYSLOT_SWITCH_6XSBK, work_buffer, 0x10); + decrypt_data_into_keyslot(KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY, KEYSLOT_SWITCH_4XOLDDEVICEKEY, devicekey_4x_seed, 0x10); + decrypt_data_into_keyslot(KEYSLOT_SWITCH_4XOLDDEVICEKEY, KEYSLOT_SWITCH_4XOLDDEVICEKEY, devicekey_seed, 0x10); + + /* Next, generate the master kek, and from there master key/device kek. We use different keyslots than Nintendo, here. */ + decrypt_data_into_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, new_master_kek_sources[0], 0x10); + decrypt_data_into_keyslot(KEYSLOT_SWITCH_MASTERKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, masterkey_seed, 0x10); + decrypt_data_into_keyslot(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, devicekek_4x_seed, 0x10); + clear_aes_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY); + } /* Detect Master Key revision. */ mkey_detect_revision(); @@ -120,6 +161,7 @@ static void setup_se(void) { break; case EXOSPHERE_TARGET_FIRMWARE_500: case EXOSPHERE_TARGET_FIRMWARE_600: + case EXOSPHERE_TARGET_FIRMWARE_620: derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY); break; } diff --git a/exosphere/src/se.h b/exosphere/src/se.h index 54768d620..61c8973fa 100644 --- a/exosphere/src/se.h +++ b/exosphere/src/se.h @@ -43,6 +43,11 @@ /* This keyslot was added in 5.0.0. */ #define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA +/* This keyslot was added in 6.00. */ +#define KEYSLOT_SWITCH_6XTSECKEY 0xC +#define KEYSLOT_SWITCH_6XTSECROOTKEY 0xD +#define KEYSLOT_SWITCH_6XSBK 0xE + #define KEYSLOT_AES_MAX 0x10 #define KEYSLOT_RSA_MAX 0x2 From 767a4b3606dbde51aa9089c96dce1635d2bab6fb Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 25 Nov 2018 22:37:24 -0800 Subject: [PATCH 251/489] fusee/exo: BYOK support for 6.2.0. Proper support TODO. --- exosphere/src/package2.c | 5 +- exosphere/src/package2.h | 6 +- exosphere/src/smc_api.c | 1 + exosphere/src/smc_user.c | 3 +- fusee/fusee-secondary/src/extkeys.c | 216 +++++++++++++++++++++ fusee/fusee-secondary/src/extkeys.h | 32 +++ fusee/fusee-secondary/src/key_derivation.c | 63 ++++-- fusee/fusee-secondary/src/key_derivation.h | 11 +- fusee/fusee-secondary/src/masterkey.c | 33 +--- fusee/fusee-secondary/src/masterkey.h | 7 +- fusee/fusee-secondary/src/nxboot.c | 21 +- fusee/fusee-secondary/src/package2.c | 2 +- fusee/fusee-secondary/src/package2.h | 6 +- 13 files changed, 343 insertions(+), 63 deletions(-) create mode 100644 fusee/fusee-secondary/src/extkeys.c create mode 100644 fusee/fusee-secondary/src/extkeys.h diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index c6ef81dc2..706386de3 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -144,7 +144,7 @@ static void setup_se(void) { decrypt_data_into_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, new_master_kek_sources[0], 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_MASTERKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, masterkey_seed, 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, devicekek_4x_seed, 0x10); - clear_aes_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY); + clear_aes_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY); } /* Detect Master Key revision. */ @@ -346,7 +346,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) { /* Perform version checks. */ /* We will be compatible with all package2s released before current, but not newer ones. */ - if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_600_CURRENT) { + if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_620_CURRENT) { return true; } @@ -466,6 +466,7 @@ static void copy_warmboot_bin_to_dram() { warmboot_src = (uint8_t *)0x4003B000; break; case EXOSPHERE_TARGET_FIRMWARE_600: + case EXOSPHERE_TARGET_FIRMWARE_620: warmboot_src = (uint8_t *)0x4003D800; break; } diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h index 9553fa8fe..97ac7638c 100644 --- a/exosphere/src/package2.h +++ b/exosphere/src/package2.h @@ -67,7 +67,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) { #define PACKAGE2_MAXVER_302 0x5 #define PACKAGE2_MAXVER_400_410 0x6 #define PACKAGE2_MAXVER_500_510 0x7 -#define PACKAGE2_MAXVER_600_CURRENT 0x8 +#define PACKAGE2_MAXVER_600_610 0x8 +#define PACKAGE2_MAXVER_620_CURRENT 0x9 #define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_200 0x4 @@ -75,7 +76,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) { #define PACKAGE2_MINVER_302 0x6 #define PACKAGE2_MINVER_400_410 0x7 #define PACKAGE2_MINVER_500_510 0x8 -#define PACKAGE2_MINVER_600_CURRENT 0x9 +#define PACKAGE2_MINVER_600_610 0x9 +#define PACKAGE2_MINVER_620_CURRENT 0xA typedef struct { union { diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index f391dc539..f39645e47 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -159,6 +159,7 @@ void set_version_specific_smcs(void) { break; case EXOSPHERE_TARGET_FIRMWARE_500: case EXOSPHERE_TARGET_FIRMWARE_600: + case EXOSPHERE_TARGET_FIRMWARE_620: /* No more LoadSecureExpModKey. */ g_smc_user_table[0xE].handler = NULL; g_smc_user_table[0xC].id = 0xC300D60C; diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c index 5c2b9c2b6..4ebf6369f 100644 --- a/exosphere/src/smc_user.c +++ b/exosphere/src/smc_user.c @@ -49,6 +49,7 @@ static bool is_user_keyslot_valid(unsigned int keyslot) { case EXOSPHERE_TARGET_FIRMWARE_500: return keyslot <= 3; case EXOSPHERE_TARGET_FIRMWARE_600: + case EXOSPHERE_TARGET_FIRMWARE_620: default: return keyslot <= 5; } @@ -166,7 +167,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) { /* 5.0.0+ Bounds checking. */ if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { if (is_personalized) { - if (master_key_rev > MASTERKEY_REVISION_MAX || (MASTERKEY_REVISION_300 <= master_key_rev + 1 && master_key_rev + 1 < MASTERKEY_REVISION_400_410)) { + if (master_key_rev >= MASTERKEY_REVISION_MAX || (MASTERKEY_REVISION_300 <= master_key_rev && master_key_rev < MASTERKEY_REVISION_400_410)) { return 2; } if (mask_id > 3 || usecase >= CRYPTOUSECASE_MAX_5X) { diff --git a/fusee/fusee-secondary/src/extkeys.c b/fusee/fusee-secondary/src/extkeys.c new file mode 100644 index 000000000..7315d4c5d --- /dev/null +++ b/fusee/fusee-secondary/src/extkeys.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include "extkeys.h" + +/** + * Reads a line from file f and parses out the key and value from it. + * The format of a line must match /^ *[A-Za-z0-9_] *[,=] *.+$/. + * If a line ends in \r, the final \r is stripped. + * The input file is assumed to have been opened with the 'b' flag. + * The input file is assumed to contain only ASCII. + * + * A line cannot exceed 512 bytes in length. + * Lines that are excessively long will be silently truncated. + * + * On success, *key and *value will be set to point to the key and value in + * the input line, respectively. + * *key and *value may also be NULL in case of empty lines. + * On failure, *key and *value will be set to NULL. + * End of file is considered failure. + * + * Because *key and *value will point to a static buffer, their contents must be + * copied before calling this function again. + * For the same reason, this function is not thread-safe. + * + * The key will be converted to lowercase. + * An empty key is considered a parse error, but an empty value is returned as + * success. + * + * This function assumes that the file can be trusted not to contain any NUL in + * the contents. + * + * Whitespace (' ', ASCII 0x20, as well as '\t', ASCII 0x09) at the beginning of + * the line, at the end of the line as well as around = (or ,) will be ignored. + * + * @param f the file to read + * @param key pointer to change to point to the key + * @param value pointer to change to point to the value + * @return 0 on success, + * 1 on end of file, + * -1 on parse error (line too long, line malformed) + * -2 on I/O error + */ +static int get_kv(FILE *f, char **key, char **value) { +#define SKIP_SPACE(p) do {\ + for (; *p == ' ' || *p == '\t'; ++p)\ + ;\ +} while(0); + static char line[1024]; + char *k, *v, *p, *end; + + *key = *value = NULL; + + errno = 0; + if (fgets(line, (int)sizeof(line), f) == NULL) { + if (feof(f)) + return 1; + else + return -2; + } + if (errno != 0) + return -2; + + if (*line == '\n' || *line == '\r' || *line == '\0') + return 0; + + /* Not finding \r or \n is not a problem. + * The line might just be exactly 512 characters long, we have no way to + * tell. + * Additionally, it's possible that the last line of a file is not actually + * a line (i.e., does not end in '\n'); we do want to handle those. + */ + if ((p = strchr(line, '\r')) != NULL || (p = strchr(line, '\n')) != NULL) { + end = p; + *p = '\0'; + } else { + end = line + strlen(line) + 1; + } + + p = line; + SKIP_SPACE(p); + k = p; + + /* Validate key and convert to lower case. */ + for (; *p != ' ' && *p != ',' && *p != '\t' && *p != '='; ++p) { + if (*p == '\0') + return -1; + + if (*p >= 'A' && *p <= 'Z') { + *p = 'a' + (*p - 'A'); + continue; + } + + if (*p != '_' && + (*p < '0' || *p > '9') && + (*p < 'a' || *p > 'z')) { + return -1; + } + } + + /* Bail if the final ++p put us at the end of string */ + if (*p == '\0') + return -1; + + /* We should be at the end of key now and either whitespace or [,=] + * follows. + */ + if (*p == '=' || *p == ',') { + *p++ = '\0'; + } else { + *p++ = '\0'; + SKIP_SPACE(p); + if (*p != '=' && *p != ',') + return -1; + *p++ = '\0'; + } + + /* Empty key is an error. */ + if (*k == '\0') + return -1; + + SKIP_SPACE(p); + v = p; + + /* Skip trailing whitespace */ + for (p = end - 1; *p == '\t' || *p == ' '; --p) + ; + + *(p + 1) = '\0'; + + *key = k; + *value = v; + + return 0; +#undef SKIP_SPACE +} + +static int ishex(char c) { + if ('a' <= c && c <= 'f') return 1; + if ('A' <= c && c <= 'F') return 1; + if ('0' <= c && c <= '9') return 1; + return 0; +} + +static char hextoi(char c) { + if ('a' <= c && c <= 'f') return c - 'a' + 0xA; + if ('A' <= c && c <= 'F') return c - 'A' + 0xA; + if ('0' <= c && c <= '9') return c - '0'; + return 0; +} + +void parse_hex_key(unsigned char *key, const char *hex, unsigned int len) { + if (strlen(hex) != 2 * len) { + fatal_error("Key (%s) must be %x hex digits!\n", hex, 2 * len); + } + + for (unsigned int i = 0; i < 2 * len; i++) { + if (!ishex(hex[i])) { + fatal_error("Key (%s) must be %x hex digits!\n", hex, 2 * len); + } + } + + memset(key, 0, len); + + for (unsigned int i = 0; i < 2 * len; i++) { + char val = hextoi(hex[i]); + if ((i & 1) == 0) { + val <<= 4; + } + key[i >> 1] |= val; + } +} + +void extkeys_initialize_keyset(fusee_extkeys_t *keyset, FILE *f) { + char *key, *value; + int ret; + + while ((ret = get_kv(f, &key, &value)) != 1 && ret != -2) { + if (ret == 0) { + if (key == NULL || value == NULL) { + continue; + } + int matched_key = 0; + if (strcmp(key, "tsec_root_key") == 0 || strcmp(key, "tsec_root_key_00") == 0) { + parse_hex_key(keyset->tsec_root_key, value, sizeof(keyset->tsec_root_key)); + matched_key = 1; + } else { + char test_name[0x100] = {0}; + for (unsigned int i = 0; i < 0x20 && !matched_key; i++) { + snprintf(test_name, sizeof(test_name), "master_kek_%02x", i); + if (strcmp(key, test_name) == 0) { + parse_hex_key(keyset->master_keks[i], value, sizeof(keyset->master_keks[i])); + matched_key = 1; + break; + } + } + } + } + } +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/extkeys.h b/fusee/fusee-secondary/src/extkeys.h new file mode 100644 index 000000000..651868995 --- /dev/null +++ b/fusee/fusee-secondary/src/extkeys.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_EXTKEYS_H +#define FUSEE_EXTKEYS_H + +#include <string.h> +#include "utils.h" +#include "masterkey.h" + +typedef struct { + unsigned char tsec_root_key[0x10]; + unsigned char master_keks[0x20][0x10]; +} fusee_extkeys_t; + +void parse_hex_key(unsigned char *key, const char *hex, unsigned int len); +void extkeys_initialize_keyset(fusee_extkeys_t *keyset, FILE *f); + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index 825bc9d3e..b997e32a7 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -13,13 +13,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - + +#include <stdio.h> #include "key_derivation.h" #include "masterkey.h" #include "se.h" #include "exocfg.h" #include "fuse.h" #include "tsec.h" +#include "extkeys.h" #include "utils.h" #define AL16 ALIGN(16) @@ -53,6 +55,10 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 }; +static const uint8_t AL16 new_master_kek_seeds[1][0x10] = { + {0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* MasterKek seed 06. */ +}; + static nx_dec_keyblob_t AL16 g_dec_keyblobs[32]; static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uint32_t tsec_key_id) { @@ -108,45 +114,79 @@ static int decrypt_keyblob(const nx_keyblob_t *keyblobs, uint32_t revision, uint } int load_package1_key(uint32_t revision) { - if (revision > MASTERKEY_REVISION_600_CURRENT) { + if (revision > MASTERKEY_REVISION_600_610) { return -1; } - set_aes_keyslot(0xB, g_dec_keyblobs[revision].keys[8], 0x10); + set_aes_keyslot(0xB, g_dec_keyblobs[revision].package1_key, 0x10); return 0; } /* Derive all Switch keys. */ -int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_fw, size_t tsec_fw_size) { +int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_fw, size_t tsec_fw_size, unsigned int *out_keygen_type) { + uint8_t AL16 tsec_key[0x10]; uint8_t AL16 work_buffer[0x10]; + uint8_t AL16 zeroes[0x10] = {0}; /* TODO: Set keyslot flags properly in preparation of derivation. */ set_aes_keyslot_flags(0xE, 0x15); set_aes_keyslot_flags(0xD, 0x15); /* Set TSEC key. */ - if (get_tsec_key(work_buffer, tsec_fw, tsec_fw_size, 1) != 0) { + if (get_tsec_key(tsec_key, tsec_fw, tsec_fw_size, 1) != 0) { return -1; } - set_aes_keyslot(0xD, work_buffer, 0x10); - + set_aes_keyslot(0xD, tsec_key, 0x10); + /* Decrypt all keyblobs, setting keyslot 0xF correctly. */ - for (unsigned int rev = 0; rev < MASTERKEY_REVISION_MAX; rev++) { + for (unsigned int rev = 0; rev <= MASTERKEY_REVISION_600_610; rev++) { int ret = decrypt_keyblob(keyblobs, rev, available_revision); if (ret) { return ret; } } - + + + /* TODO: Eventually do 6.2.0+ keygen properly? */ + *out_keygen_type = 0; + if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + const char *keyfile = fuse_get_retail_type() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys"; + FILE *extkey_file = fopen(keyfile, "r"); + AL16 fusee_extkeys_t extkeys = {0}; + if (extkey_file == NULL) { + fatal_error("Error: failed to read %s, needed for 6.2.0+ key derivation!", keyfile); + } + extkeys_initialize_keyset(&extkeys, extkey_file); + fclose(extkey_file); + + if (memcmp(extkeys.tsec_root_key, zeroes, 0x10) != 0) { + set_aes_keyslot(0xC, extkeys.tsec_root_key, 0x10); + for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { + se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10); + memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10); + } + } else { + for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { + memcpy(g_dec_keyblobs[rev].master_kek, extkeys.master_keks[rev], 0x10); + } + } + + if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) { + fatal_error("Error: failed to derive master_kek_%02x!", available_revision); + } + } + /* Clear the SBK. */ clear_aes_keyslot(0xE); /* Get needed data. */ - set_aes_keyslot(0xC, g_dec_keyblobs[MASTERKEY_REVISION_600_CURRENT].keys[0], 0x10); + set_aes_keyslot(0xC, g_dec_keyblobs[available_revision].master_kek, 0x10); /* Also set the Package1 key for the revision that is stored on the eMMC boot0 partition. */ - load_package1_key(available_revision); + if (target_firmware < EXOSPHERE_TARGET_FIRMWARE_620) { + load_package1_key(available_revision); + } /* Derive keys for Exosphere, lock critical keyslots. */ switch (target_firmware) { @@ -164,6 +204,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui break; case EXOSPHERE_TARGET_FIRMWARE_500: case EXOSPHERE_TARGET_FIRMWARE_600: + case EXOSPHERE_TARGET_FIRMWARE_620: decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); diff --git a/fusee/fusee-secondary/src/key_derivation.h b/fusee/fusee-secondary/src/key_derivation.h index 5b64f76d1..0cc475037 100644 --- a/fusee/fusee-secondary/src/key_derivation.h +++ b/fusee/fusee-secondary/src/key_derivation.h @@ -28,7 +28,14 @@ typedef enum BisPartition { } BisPartition; typedef struct { - uint8_t keys[9][0x10]; + union { + uint8_t keys[9][0x10]; + struct { + uint8_t master_kek[0x10]; + uint8_t _keys[7][0x10]; + uint8_t package1_key[0x10]; + }; + }; } nx_dec_keyblob_t; typedef struct nx_keyblob_t { @@ -40,7 +47,7 @@ typedef struct nx_keyblob_t { }; } nx_keyblob_t; -int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_fw, size_t tsec_fw_size); +int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_fw, size_t tsec_fw_size, unsigned int *out_keygen_type); int load_package1_key(uint32_t revision); void finalize_nx_keydata(uint32_t target_firmware); void derive_bis_key(void *dst, BisPartition partition_id, uint32_t target_firmware); diff --git a/fusee/fusee-secondary/src/masterkey.c b/fusee/fusee-secondary/src/masterkey.c index bf31ec581..3a4f6ae71 100644 --- a/fusee/fusee-secondary/src/masterkey.c +++ b/fusee/fusee-secondary/src/masterkey.c @@ -26,7 +26,6 @@ static unsigned int g_mkey_revision = 0; static bool g_determined_mkey_revision = false; static uint8_t g_old_masterkeys[MASTERKEY_REVISION_MAX][0x10]; -static uint8_t g_old_devicekeys[MASTERKEY_NUM_NEW_DEVICE_KEYS - 1][0x10]; /* TODO: Extend with new vectors, as needed. */ /* Dev unit keys. */ @@ -38,6 +37,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = {0x2C, 0xCA, 0x9C, 0x31, 0x1E, 0x07, 0xB0, 0x02, 0x97, 0x0A, 0xD8, 0x03, 0xA2, 0x76, 0x3F, 0xA3}, /* Master key 02 encrypted with Master key 03. */ {0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ + {0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */ }; /* Retail unit keys. */ @@ -49,6 +49,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = {0x0A, 0x0D, 0xDF, 0x34, 0x22, 0x06, 0x6C, 0xA4, 0xE6, 0xB1, 0xEC, 0x71, 0x85, 0xCA, 0x4E, 0x07}, /* Master key 02 encrypted with Master key 03. */ {0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ + {0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */ }; static bool check_mkey_revision(unsigned int revision, bool is_retail) { @@ -119,33 +120,3 @@ unsigned int mkey_get_keyslot(unsigned int revision) { return KEYSLOT_SWITCH_TEMPKEY; } } - -void set_old_devkey(unsigned int revision, const uint8_t *key) { - if (revision < MASTERKEY_REVISION_400_410 || MASTERKEY_REVISION_600_CURRENT <= revision) { - generic_panic(); - } - - memcpy(g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], key, 0x10); -} - -unsigned int devkey_get_keyslot(unsigned int revision) { - if (!g_determined_mkey_revision || revision >= MASTERKEY_REVISION_MAX) { - generic_panic(); - } - - if (revision > g_mkey_revision) { - generic_panic(); - } - - if (revision >= 1) { - if (revision == MASTERKEY_REVISION_600_CURRENT) { - return KEYSLOT_SWITCH_DEVICEKEY; - } else { - /* Load into a temp keyslot. */ - set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], 0x10); - return KEYSLOT_SWITCH_TEMPKEY; - } - } else { - return KEYSLOT_SWITCH_4XOLDDEVICEKEY; - } -} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/masterkey.h b/fusee/fusee-secondary/src/masterkey.h index 531eebc58..0f1c20a0b 100644 --- a/fusee/fusee-secondary/src/masterkey.h +++ b/fusee/fusee-secondary/src/masterkey.h @@ -19,15 +19,16 @@ /* This is glue code to enable master key support across versions. */ -/* TODO: Update to 0x7 on release of new master key. */ -#define MASTERKEY_REVISION_MAX 0x6 +/* TODO: Update to 0x8 on release of new master key. */ +#define MASTERKEY_REVISION_MAX 0x7 #define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_300 0x01 #define MASTERKEY_REVISION_301_302 0x02 #define MASTERKEY_REVISION_400_410 0x03 #define MASTERKEY_REVISION_500_510 0x04 -#define MASTERKEY_REVISION_600_CURRENT 0x05 +#define MASTERKEY_REVISION_600_610 0x05 +#define MASTERKEY_REVISION_620_CURRENT 0x06 #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 0380b3544..4851d3e3b 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -90,12 +90,16 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { } } -static void nxboot_configure_exosphere(uint32_t target_firmware) { +static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int keygen_type) { exosphere_config_t exo_cfg = {0}; exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG; exo_cfg.target_firmware = target_firmware; - exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT; + if (keygen_type) { + exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT | EXOSPHERE_FLAG_PERFORM_620_KEYGEN; + } else { + exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT; + } if (ini_parse_string(get_loader_ctx()->bct0, exosphere_ini_handler, &exo_cfg) < 0) { fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); @@ -307,8 +311,14 @@ uint32_t nxboot_main(void) { print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); + /* Derive keydata. */ + unsigned int keygen_type = 0; + if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size, &keygen_type) != 0) { + fatal_error("[NXBOOT]: Key derivation failed!\n"); + } + /* Setup boot configuration for Exosphère. */ - nxboot_configure_exosphere(target_firmware); + nxboot_configure_exosphere(target_firmware, keygen_type); /* Initialize Boot Reason on older firmware versions. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { @@ -316,11 +326,6 @@ uint32_t nxboot_main(void) { nxboot_set_bootreason(); } - /* Derive keydata. */ - if (derive_nx_keydata(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size) != 0) { - fatal_error("[NXBOOT]: Key derivation failed!\n"); - } - /* Read the warmboot firmware from a file, otherwise from PK1. */ if (loader_ctx->warmboot_path[0] != '\0') { warmboot_fw_size = get_file_size(loader_ctx->warmboot_path); diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 1d2fb3a5c..1f9cdad9b 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -214,7 +214,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[] /* Perform version checks. */ /* We will be compatible with all package2s released before current, but not newer ones. */ - if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_600_CURRENT) { + if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_620_CURRENT) { return true; } diff --git a/fusee/fusee-secondary/src/package2.h b/fusee/fusee-secondary/src/package2.h index c1314305b..b537f670d 100644 --- a/fusee/fusee-secondary/src/package2.h +++ b/fusee/fusee-secondary/src/package2.h @@ -34,7 +34,8 @@ #define PACKAGE2_MAXVER_302 0x5 #define PACKAGE2_MAXVER_400_410 0x6 #define PACKAGE2_MAXVER_500_510 0x7 -#define PACKAGE2_MAXVER_600_CURRENT 0x8 +#define PACKAGE2_MAXVER_600_610 0x8 +#define PACKAGE2_MAXVER_620_CURRENT 0x9 #define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_200 0x4 @@ -42,7 +43,8 @@ #define PACKAGE2_MINVER_302 0x6 #define PACKAGE2_MINVER_400_410 0x7 #define PACKAGE2_MINVER_500_510 0x8 -#define PACKAGE2_MINVER_600_CURRENT 0x9 +#define PACKAGE2_MINVER_600_610 0x9 +#define PACKAGE2_MINVER_620_CURRENT 0xA #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) From dd255df90db53de991407e8b9019c696b1ee9832 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 29 Nov 2018 12:13:57 -0800 Subject: [PATCH 252/489] Change mitm conditions due to sleep mode issue --- stratosphere/fs_mitm/source/fsmitm_service.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index fd69bc85a..483bf8c33 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -41,8 +41,15 @@ class FsMitmService : public IMitmServiceObject { } static bool ShouldMitm(u64 pid, u64 tid) { - /* fs.mitm should always mitm everything that's not a kip. */ - return pid >= 0x50; + static std::atomic_bool has_launched_qlaunch = false; + + /* TODO: intercepting everything seems to cause issues with sleep mode, for some reason. */ + /* Figure out why, and address it. */ + if (tid == 0x0100000000001000ULL) { + has_launched_qlaunch = true; + } + + return has_launched_qlaunch || tid == 0x010000000000001FULL || tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid); } static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); From 67ff4fe913eaa469f78e151cccb8b240298263b7 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 29 Nov 2018 12:20:08 -0800 Subject: [PATCH 253/489] fs.mitm: tweak conditions a little more. --- stratosphere/fs_mitm/source/fsmitm_service.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 483bf8c33..e7d2ad571 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -41,6 +41,11 @@ class FsMitmService : public IMitmServiceObject { } static bool ShouldMitm(u64 pid, u64 tid) { + /* Don't Mitm KIPs */ + if (pid < 0x50) { + return false; + } + static std::atomic_bool has_launched_qlaunch = false; /* TODO: intercepting everything seems to cause issues with sleep mode, for some reason. */ From ae4d29a49ffbec767609fe8e1cc10a38e952fa27 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 29 Nov 2018 12:30:32 -0800 Subject: [PATCH 254/489] fs.mitm: add flag support for writing bis/reading cal0 --- stratosphere/fs_mitm/source/fsmitm_service.cpp | 12 +++++++----- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 12 +++++++++++- stratosphere/fs_mitm/source/fsmitm_utils.hpp | 4 +++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 9897edf6f..0b1e1cf18 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -100,11 +100,13 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out rc = fsOpenBisStorageFwd(this->forward_service.get(), &bis_storage, bis_partition_id); if (R_SUCCEEDED(rc)) { const bool is_sysmodule = this->title_id < 0x0100000000001000; + const bool has_bis_write_flag = Utils::HasFlag(this->title_id, "bis_write"); + const bool has_cal0_read_flag = Utils::HasFlag(this->title_id, "cal_read"); if (bis_partition_id == BisStorageId_Boot0) { storage = std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->title_id)); } else if (bis_partition_id == BisStorageId_Prodinfo) { /* PRODINFO should *never* be writable. */ - if (is_sysmodule) { + if (is_sysmodule || has_cal0_read_flag) { storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); } else { /* Do not allow non-sysmodules to read *or* write CAL0. */ @@ -112,12 +114,12 @@ Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out return 0x320002; } } else { - if (!is_sysmodule) { - /* Non-sysmodules should be allowed to read. */ - storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); - } else { + if (is_sysmodule || has_bis_write_flag) { /* Sysmodules should still be allowed to read and write. */ storage = std::make_shared<IStorageInterface>(new ProxyStorage(bis_storage)); + } else { + /* Non-sysmodules should be allowed to read. */ + storage = std::make_shared<IStorageInterface>(new ROProxyStorage(bis_storage)); } } if (out_storage.IsDomain()) { diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index e692bdc5b..c1683eda9 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -346,7 +346,7 @@ Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data, return rc; } -bool Utils::HasFlag(u64 tid, const char *flag) { +bool Utils::HasTitleFlag(u64 tid, const char *flag) { if (IsSdInitialized()) { FsFile f; char flag_path[FS_MAX_PATH]; @@ -381,6 +381,16 @@ bool Utils::HasGlobalFlag(const char *flag) { return false; } +bool Utils::HasHblFlag(const char *flag) { + char hbl_flag[FS_MAX_PATH] = {0}; + snprintf(hbl_flag, sizeof(hbl_flag), "hbl_%s", flag); + return HasGlobalFlag(hbl_flag); +} + +bool Utils::HasFlag(u64 tid, const char *flag) { + return HasTitleFlag(tid, flag) || (tid == g_override_hbl_tid && HasHblFlag(flag)); +} + bool Utils::HasSdMitMFlag(u64 tid) { if (tid == g_override_hbl_tid) { return true; diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index 71efe768b..0811c1f7e 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -58,8 +58,10 @@ class Utils { /* SD card Initialization + MitM detection. */ static void InitializeSdThreadFunc(void *args); - static bool HasFlag(u64 tid, const char *flag); + static bool HasTitleFlag(u64 tid, const char *flag); + static bool HasHblFlag(const char *flag); static bool HasGlobalFlag(const char *flag); + static bool HasFlag(u64 tid, const char *flag); static bool HasSdMitMFlag(u64 tid); static bool HasSdDisableMitMFlag(u64 tid); From 87c0c8b83ec4db7ebfd97553e8cbff2bd0111d20 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 29 Nov 2018 12:48:40 -0800 Subject: [PATCH 255/489] Update libstratosphere --- stratosphere/libstratosphere | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 0bec72ca3..0fb33e9c0 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 0bec72ca36084e9780a8c28abd4a0b24c03c18af +Subproject commit 0fb33e9c094bffde737c7a73cd5ccce4d7cbae33 From e321f0ac0483c8c444218ebd0e5f50a2ec48005b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 29 Nov 2018 12:51:22 -0800 Subject: [PATCH 256/489] Fix libstratosphere update --- stratosphere/libstratosphere | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 0fb33e9c0..0bec72ca3 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 0fb33e9c094bffde737c7a73cd5ccce4d7cbae33 +Subproject commit 0bec72ca36084e9780a8c28abd4a0b24c03c18af From ed3770691519f025b5e7ebe353afa0fd3b224fd6 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Thu, 29 Nov 2018 23:32:31 +0000 Subject: [PATCH 257/489] fusee: Add full 6.2.0 support via SMMU virtualization. --- fusee/fusee-primary/src/mc.h | 2 + fusee/fusee-secondary/src/key_derivation.c | 59 ++--- fusee/fusee-secondary/src/key_derivation.h | 2 +- fusee/fusee-secondary/src/mc.h | 2 + fusee/fusee-secondary/src/nxboot.c | 45 +++- fusee/fusee-secondary/src/nxboot_iram.c | 19 +- fusee/fusee-secondary/src/package1.c | 3 +- fusee/fusee-secondary/src/smmu.c | 259 +++++++++++++++++++++ fusee/fusee-secondary/src/smmu.h | 63 +++++ fusee/fusee-secondary/src/tsec.c | 111 ++++++--- fusee/fusee-secondary/src/tsec.h | 4 + 11 files changed, 495 insertions(+), 74 deletions(-) create mode 100644 fusee/fusee-secondary/src/smmu.c create mode 100644 fusee/fusee-secondary/src/smmu.h diff --git a/fusee/fusee-primary/src/mc.h b/fusee/fusee-primary/src/mc.h index 53ecd9c67..dfba6052c 100644 --- a/fusee/fusee-primary/src/mc.h +++ b/fusee/fusee-primary/src/mc.h @@ -36,8 +36,10 @@ #define MC_SMMU_PTB_DATA 0x20 #define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_PTC_FLUSH 0x34 +#define MC_SMMU_ASID_SECURITY 0x38 #define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AVPC_ASID 0x23c +#define MC_SMMU_TSEC_ASID 0x294 #define MC_SMMU_PPCS1_ASID 0x298 #define MC_SMMU_TRANSLATION_ENABLE_0 0x228 #define MC_SMMU_TRANSLATION_ENABLE_1 0x22c diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index b997e32a7..0daab0f38 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -20,7 +20,6 @@ #include "se.h" #include "exocfg.h" #include "fuse.h" -#include "tsec.h" #include "extkeys.h" #include "utils.h" @@ -61,10 +60,6 @@ static const uint8_t AL16 new_master_kek_seeds[1][0x10] = { static nx_dec_keyblob_t AL16 g_dec_keyblobs[32]; -static int get_tsec_key(void *dst, const void *tsec_fw, size_t tsec_fw_size, uint32_t tsec_key_id) { - return tsec_get_key(dst, tsec_key_id, tsec_fw, tsec_fw_size); -} - static int get_keyblob(nx_keyblob_t *dst, uint32_t revision, const nx_keyblob_t *keyblobs, uint32_t available_revision) { if (revision >= 0x20) { return -1; @@ -123,20 +118,18 @@ int load_package1_key(uint32_t revision) { } /* Derive all Switch keys. */ -int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_fw, size_t tsec_fw_size, unsigned int *out_keygen_type) { - uint8_t AL16 tsec_key[0x10]; +int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_key, unsigned int *out_keygen_type) { uint8_t AL16 work_buffer[0x10]; uint8_t AL16 zeroes[0x10] = {0}; + + /* Initialize keygen type. */ + *out_keygen_type = 0; /* TODO: Set keyslot flags properly in preparation of derivation. */ set_aes_keyslot_flags(0xE, 0x15); set_aes_keyslot_flags(0xD, 0x15); - - /* Set TSEC key. */ - if (get_tsec_key(tsec_key, tsec_fw, tsec_fw_size, 1) != 0) { - return -1; - } + /* Set the TSEC key. */ set_aes_keyslot(0xD, tsec_key, 0x10); /* Decrypt all keyblobs, setting keyslot 0xF correctly. */ @@ -146,29 +139,37 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui return ret; } } - - - /* TODO: Eventually do 6.2.0+ keygen properly? */ - *out_keygen_type = 0; + + /* Do 6.2.0+ keygen. */ if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { - const char *keyfile = fuse_get_retail_type() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys"; - FILE *extkey_file = fopen(keyfile, "r"); - AL16 fusee_extkeys_t extkeys = {0}; - if (extkey_file == NULL) { - fatal_error("Error: failed to read %s, needed for 6.2.0+ key derivation!", keyfile); - } - extkeys_initialize_keyset(&extkeys, extkey_file); - fclose(extkey_file); - - if (memcmp(extkeys.tsec_root_key, zeroes, 0x10) != 0) { - set_aes_keyslot(0xC, extkeys.tsec_root_key, 0x10); + if (memcmp(tsec_root_key, zeroes, 0x10) != 0) { + /* We got a valid key from emulation. */ + set_aes_keyslot(0xC, tsec_root_key, 0x10); for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10); memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10); } } else { - for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { - memcpy(g_dec_keyblobs[rev].master_kek, extkeys.master_keks[rev], 0x10); + /* Try reading the keys from a file. */ + const char *keyfile = fuse_get_retail_type() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys"; + FILE *extkey_file = fopen(keyfile, "r"); + AL16 fusee_extkeys_t extkeys = {0}; + if (extkey_file == NULL) { + fatal_error("Error: failed to read %s, needed for 6.2.0+ key derivation!", keyfile); + } + extkeys_initialize_keyset(&extkeys, extkey_file); + fclose(extkey_file); + + if (memcmp(extkeys.tsec_root_key, zeroes, 0x10) != 0) { + set_aes_keyslot(0xC, extkeys.tsec_root_key, 0x10); + for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { + se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10); + memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10); + } + } else { + for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { + memcpy(g_dec_keyblobs[rev].master_kek, extkeys.master_keks[rev], 0x10); + } } } diff --git a/fusee/fusee-secondary/src/key_derivation.h b/fusee/fusee-secondary/src/key_derivation.h index 0cc475037..33e645cca 100644 --- a/fusee/fusee-secondary/src/key_derivation.h +++ b/fusee/fusee-secondary/src/key_derivation.h @@ -47,7 +47,7 @@ typedef struct nx_keyblob_t { }; } nx_keyblob_t; -int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_fw, size_t tsec_fw_size, unsigned int *out_keygen_type); +int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_key, unsigned int *out_keygen_type); int load_package1_key(uint32_t revision); void finalize_nx_keydata(uint32_t target_firmware); void derive_bis_key(void *dst, BisPartition partition_id, uint32_t target_firmware); diff --git a/fusee/fusee-secondary/src/mc.h b/fusee/fusee-secondary/src/mc.h index 53ecd9c67..dfba6052c 100644 --- a/fusee/fusee-secondary/src/mc.h +++ b/fusee/fusee-secondary/src/mc.h @@ -36,8 +36,10 @@ #define MC_SMMU_PTB_DATA 0x20 #define MC_SMMU_TLB_FLUSH 0x30 #define MC_SMMU_PTC_FLUSH 0x34 +#define MC_SMMU_ASID_SECURITY 0x38 #define MC_SMMU_AFI_ASID 0x238 #define MC_SMMU_AVPC_ASID 0x23c +#define MC_SMMU_TSEC_ASID 0x294 #define MC_SMMU_PPCS1_ASID 0x298 #define MC_SMMU_TRANSLATION_ENABLE_0 0x228 #define MC_SMMU_TRANSLATION_ENABLE_1 0x22c diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 4851d3e3b..eec1fd2f9 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -36,6 +36,8 @@ #include "key_derivation.h" #include "package1.h" #include "package2.h" +#include "smmu.h" +#include "tsec.h" #include "loader.h" #include "splash_screen.h" #include "exocfg.h" @@ -311,9 +313,28 @@ uint32_t nxboot_main(void) { print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); + /* Get the TSEC keys. */ + uint8_t tsec_key[0x10] = {0}; + uint8_t tsec_root_key[0x10] = {0}; + if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + uint8_t tsec_keys[0x20] = {0}; + + /* Emulate the TSEC payload on 6.2.0+. */ + smmu_emulate_tsec((void *)tsec_keys, package1loader, package1loader_size, package1loader); + + /* Copy back the keys. */ + memcpy((void *)tsec_key, (void *)tsec_keys, 0x10); + memcpy((void *)tsec_root_key, (void *)tsec_keys + 0x10, 0x10); + } else { + /* Run the TSEC payload and get the key. */ + if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { + fatal_error("[NXBOOT]: Failed to get TSEC key!\n"); + } + } + /* Derive keydata. */ unsigned int keygen_type = 0; - if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_fw, tsec_fw_size, &keygen_type) != 0) { + if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_key, &keygen_type) != 0) { fatal_error("[NXBOOT]: Key derivation failed!\n"); } @@ -343,16 +364,26 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } } else { - uint8_t ctr[16]; - package1_size = package1_get_encrypted_package1(&package1, ctr, package1loader, package1loader_size); - if (package1_decrypt(package1, package1_size, ctr)) { + if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + /* Package1 was decrypted during TSEC emulation. */ + const uint8_t *package1_hdr = (const uint8_t *)package1loader + 0x7000 - 0x20; + package1 = (package1_header_t *)(package1_hdr + 0x20); + package1_size = *(uint32_t *)package1_hdr; warmboot_fw = package1_get_warmboot_fw(package1); warmboot_fw_size = package1->warmboot_size; } else { - warmboot_fw = NULL; - warmboot_fw_size = 0; + /* Decrypt package1 and extract the warmboot firmware. */ + uint8_t ctr[16]; + package1_size = package1_get_encrypted_package1(&package1, ctr, package1loader, package1loader_size); + if (package1_decrypt(package1, package1_size, ctr)) { + warmboot_fw = package1_get_warmboot_fw(package1); + warmboot_fw_size = package1->warmboot_size; + } else { + warmboot_fw = NULL; + warmboot_fw_size = 0; + } } - + if (warmboot_fw_size == 0) { fatal_error("[NXBOOT]: Could not read the warmboot firmware from Package1!\n"); } diff --git a/fusee/fusee-secondary/src/nxboot_iram.c b/fusee/fusee-secondary/src/nxboot_iram.c index 18745ba45..86466a072 100644 --- a/fusee/fusee-secondary/src/nxboot_iram.c +++ b/fusee/fusee-secondary/src/nxboot_iram.c @@ -23,7 +23,9 @@ #include "mc.h" #include "nxboot.h" #include "se.h" +#include "smmu.h" #include "timers.h" +#include "sysreg.h" void nxboot_finish(uint32_t boot_memaddr) { volatile tegra_se_t *se = se_get_regs(); @@ -69,8 +71,21 @@ void nxboot_finish(uint32_t boot_memaddr) { /* Terminate the display. */ display_end(); - /* Boot CPU0. */ - cluster_boot_cpu0(boot_memaddr); + /* Check if SMMU emulation has been used. */ + uint32_t smmu_magic = *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC); + if (smmu_magic == 0xDEADC0DE) { + /* Clear the magic. */ + *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0; + + /* Pass the boot address to the already running payload. */ + *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xF0) = boot_memaddr; + + /* Wait a while. */ + mdelay(500); + } else { + /* Boot CPU0. */ + cluster_boot_cpu0(boot_memaddr); + } /* Wait for Exosphère to wake up. */ while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { diff --git a/fusee/fusee-secondary/src/package1.c b/fusee/fusee-secondary/src/package1.c index 4f62310b6..a0f016352 100644 --- a/fusee/fusee-secondary/src/package1.c +++ b/fusee/fusee-secondary/src/package1.c @@ -131,7 +131,7 @@ void *package1_get_warmboot_fw(const package1_header_t *package1) { https://github.com/ARM-software/arm-trusted-firmware/blob/master/plat/nvidia/tegra/common/aarch64/tegra_helpers.S#L312 and thus by 0xD5034FDF. - Nx-bootloader seems to always start by 0xE328F0C0 (msr cpsr_f, 0xc0). + Nx-bootloader starts by 0xE328F0C0 (msr cpsr_f, 0xc0) before 6.2.0 and by 0xF0C0A7F0 afterwards. */ const uint32_t *data = (const uint32_t *)package1->data; for (size_t i = 0; i < 3; i++) { @@ -140,6 +140,7 @@ void *package1_get_warmboot_fw(const package1_header_t *package1) { data += package1->secmon_size / 4; break; case 0xE328F0C0: + case 0xF0C0A7F0: data += package1->nx_bootloader_size / 4; break; default: diff --git a/fusee/fusee-secondary/src/smmu.c b/fusee/fusee-secondary/src/smmu.c new file mode 100644 index 000000000..23bd3d37d --- /dev/null +++ b/fusee/fusee-secondary/src/smmu.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "smmu.h" +#include "cluster.h" +#include "mc.h" +#include "timers.h" +#include "tsec.h" + +void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR; + +static void safe_memcpy(void *dst, void *src, uint32_t sz) { + /* Aligned memcpy to read MMIO correctly. */ + for (size_t i = 0; i < (sz/4); i++) { + ((volatile uint32_t *)dst)[i] = ((volatile uint32_t *)src)[i]; + } +} + +static void smmu_flush_ppsb() { + /* Read-back barrier for interactions between the PPSB and the APB/AHB. */ + (void)MAKE_MC_REG(MC_SMMU_TLB_CONFIG); +} + +static void smmu_flush_regs() { + /* Flush all TLB and PTC entries. */ + MAKE_MC_REG(MC_SMMU_PTC_FLUSH) = 0; + smmu_flush_ppsb(); + MAKE_MC_REG(MC_SMMU_TLB_FLUSH) = 0; + smmu_flush_ppsb(); +} + +static void *smmu_alloc_page(uint32_t page_count) { + void *cur_page = smmu_heap; + smmu_heap += (page_count * SMMU_PAGE_SIZE); + memset(cur_page, 0, (page_count * SMMU_PAGE_SIZE)); + return cur_page; +} + +static uint32_t *smmu_alloc_pdir() { + uint32_t *pdir = (uint32_t *)smmu_alloc_page(1); + for (int pdn = 0; pdn < SMMU_PDIR_COUNT; pdn++) { + pdir[pdn] = _PDE_VACANT(pdn); + } + return pdir; +} + +static uint32_t *smmu_locate_pte(uint32_t *pdir_page, uint32_t iova) { + uint32_t ptn = SMMU_ADDR_TO_PFN(iova); + uint32_t pdn = SMMU_ADDR_TO_PDN(iova); + uint32_t *pdir = pdir_page; + uint32_t *ptbl; + + if (pdir[pdn] != _PDE_VACANT(pdn)) { + /* Mapped entry table already exists. */ + ptbl = (uint32_t *)SMMU_EX_PTBL_PAGE(pdir[pdn]); + } else { + /* Allocate page table. */ + ptbl = (uint32_t *)smmu_alloc_page(1); + uint32_t addr = SMMU_PDN_TO_ADDR(pdn); + for (int pn = 0; pn < SMMU_PTBL_COUNT; pn++, addr += SMMU_PAGE_SIZE) { + ptbl[pn] = _PTE_VACANT(addr); + } + pdir[pdn] = SMMU_MK_PDE((uint32_t)ptbl, _PDE_ATTR | _PDE_NEXT); + smmu_flush_regs(); + } + + return &ptbl[ptn % SMMU_PTBL_COUNT]; +} + +static void smmu_map(uint32_t *pdir, uint32_t addr, uint32_t ptpage, int pcount, uint32_t pte_attr) { + for (int i = 0; i < pcount; i++) { + uint32_t *pte = smmu_locate_pte(pdir, addr); + *pte = SMMU_PFN_TO_PTE(SMMU_ADDR_TO_PFN(ptpage), pte_attr); + addr += SMMU_PAGE_SIZE; + ptpage += SMMU_PAGE_SIZE; + } + smmu_flush_regs(); +} + +static uint32_t *smmu_setup_tsec_as(uint32_t asid) { + /* Allocate the page directory. */ + uint32_t *pdir_page = smmu_alloc_pdir(); + + /* Set the PTB ASID and point it to the PDIR. */ + MAKE_MC_REG(MC_SMMU_PTB_ASID) = asid; + MAKE_MC_REG(MC_SMMU_PTB_DATA) = SMMU_MK_PDIR((uint32_t)pdir_page, _PDIR_ATTR); + smmu_flush_ppsb(); + + /* Assign the ASID to TSEC. */ + MAKE_MC_REG(MC_SMMU_TSEC_ASID) = SMMU_ASID_ENABLE((asid << 24) | (asid << 16) | (asid << 8) | asid); + smmu_flush_ppsb(); + + return pdir_page; +} + +static void smmu_clear_tsec_as(uint32_t asid) { + /* Set the PTB ASID and clear it's data. */ + MAKE_MC_REG(MC_SMMU_PTB_ASID) = asid; + MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0; + + /* Clear the ASID from TSEC. */ + MAKE_MC_REG(MC_SMMU_TSEC_ASID) = SMMU_ASID_DISABLE; + smmu_flush_ppsb(); +} + +static void smmu_enable() { + /* AARCH64 payload for enabling the SMMU. */ + /* Write 1 to MC_SMMU_CONFIG, read back and write the result to 0x40003F80. */ + /* This will leave the CPU waiting until 0x40003FF0 is set to Exosphère's address. */ + static const uint32_t aarch64_payload[20] = { + 0x52800020, 0x58000162, 0x58000183, 0xB9000040, + 0xB9400041, 0xB9000061, 0x58000142, 0xF9400040, + 0xF100001F, 0x54FFFFA0, 0xD61F0000, 0x00000000, + 0x70019010, 0x00000000, 0x40003F80, 0x00000000, + 0x40003FF0, 0x00000000, 0x00000000, 0x00000000 + }; + + /* Reset Translation Enable Registers. */ + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_0) = 0xFFFFFFFF; + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_1) = 0xFFFFFFFF; + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_2) = 0xFFFFFFFF; + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_3) = 0xFFFFFFFF; + MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF; + + /* Setup initial TLB and PTC configuration. */ + MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0; + MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0; + MAKE_MC_REG(MC_SMMU_TLB_CONFIG) = 0x30000030; + MAKE_MC_REG(MC_SMMU_PTC_CONFIG) = 0x2800003F; + smmu_flush_regs(); + + /* Power on the CCPLEX to enable the SMMU globally (requires a secure write). */ + volatile uint32_t *aarch64_payload_res = (volatile uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0x80); + memset((void *)SMMU_AARCH64_PAYLOAD_ADDR, 0, 0x100); + memcpy((void *)SMMU_AARCH64_PAYLOAD_ADDR, aarch64_payload, 20 * 4); + cluster_boot_cpu0(SMMU_AARCH64_PAYLOAD_ADDR); + mdelay(500); + if (*aarch64_payload_res != 1) { + fatal_error("[SMMU]: Failed to enable SMMU!\n"); + } + + /* Write magic for nxboot. */ + *(uint32_t *)(SMMU_AARCH64_PAYLOAD_ADDR + 0xFC) = 0xDEADC0DE; + + /* Flush TLB and PTC entries. */ + smmu_flush_regs(); +} + +void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_size, void *package1_dec) { + volatile tegra_tsec_t *tsec = tsec_get_regs(); + + /* Backup IRAM to DRAM. */ + memcpy((void *)SMMU_IRAM_BACKUP_ADDR, (void *)0x40010000, 0x30000); + + /* Copy package1 into IRAM. */ + memcpy((void *)0x40010000, package1, package1_size); + + /* Load the TSEC firmware from IRAM. */ + if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) { + fatal_error("[SMMU]: Failed to load TSEC firmware!\n"); + } + + /* Disable the aperture since it has precedence over the SMMU. */ + mc_disable_ahb_redirect(); + + /* Setup TSEC's address space. */ + uint32_t *pdir = smmu_setup_tsec_as(1); + + /* Allocate pages for MMIO and IRAM. */ + volatile uint32_t *car_page = smmu_alloc_page(1); + volatile uint32_t *fuse_page = smmu_alloc_page(1); + volatile uint32_t *pmc_page = smmu_alloc_page(1); + volatile uint32_t *flow_page = smmu_alloc_page(1); + volatile uint32_t *se_page = smmu_alloc_page(1); + volatile uint32_t *mc_page = smmu_alloc_page(1); + volatile uint32_t *iram_pages = smmu_alloc_page(48); + volatile uint32_t *expv_page = smmu_alloc_page(1); + + /* Copy CAR, MC and FUSE. */ + safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000); + safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000); + safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400); + + /* Copy IRAM. */ + memcpy((void *)iram_pages, (void *)0x40010000, 0x30000); + + /* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */ + car_page[0x1F4/4] = 2; + + /* TSEC wants the aperture fully open. */ + mc_page[0x65C/4] = 0; + mc_page[0x660/4] = 0x80000000; + + /* Map all necessary pages. */ + smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE); + smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE); + smmu_map(pdir, 0x7000E000, (uint32_t)pmc_page, 1, _READABLE | _NONSECURE); + smmu_map(pdir, 0x60007000, (uint32_t)flow_page, 1, _WRITABLE | _NONSECURE); + smmu_map(pdir, 0x70012000, (uint32_t)se_page, 1, _READABLE | _WRITABLE | _NONSECURE); + smmu_map(pdir, 0x70019000, (uint32_t)mc_page, 1, _READABLE | _NONSECURE); + smmu_map(pdir, 0x40010000, (uint32_t)iram_pages, 48, _READABLE | _WRITABLE | _NONSECURE); + smmu_map(pdir, 0x6000F000, (uint32_t)expv_page, 1, _READABLE | _WRITABLE | _NONSECURE); + + /* Enable the SMMU. */ + smmu_enable(); + + /* Run the TSEC firmware. */ + tsec_run_fw(); + + /* Extract the keys from SE. */ + uint32_t key_buf[0x20/4] = {0}; + volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320); + uint32_t old_key_data = *key_data; + uint32_t buf_counter = 0; + while (!(tsec->FALCON_CPUCTL & 0x10)) { + if (*key_data != old_key_data) { + old_key_data = *key_data; + key_buf[buf_counter] = *key_data; + buf_counter++; + } + } + + /* Check if the TSEC firmware wrote over the exception vectors. */ + volatile uint32_t *tsec_done_check = (volatile uint32_t *)((void *)expv_page + 0x200); + if (!(*tsec_done_check)) { + fatal_error("[SMMU]: Failed to emulate the TSEC firmware!\n"); + } + + /* Copy back the extracted keys. */ + memcpy((void *)tsec_keys, (void *)key_buf, 0x20); + + /* Manually disable TSEC clocks. */ + tsec_disable_clkrst(); + + /* Clear TSEC's address space. */ + smmu_clear_tsec_as(1); + + /* Enable back the aperture. */ + mc_enable_ahb_redirect(); + + /* Return the decrypted package1 from emulated IRAM. */ + memcpy(package1_dec, (void *)iram_pages, package1_size); + + /* Restore IRAM from DRAM. */ + memcpy((void *)0x40010000, (void *)SMMU_IRAM_BACKUP_ADDR, 0x30000); +} \ No newline at end of file diff --git a/fusee/fusee-secondary/src/smmu.h b/fusee/fusee-secondary/src/smmu.h new file mode 100644 index 000000000..ba6a01684 --- /dev/null +++ b/fusee/fusee-secondary/src/smmu.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SMMU_H_ +#define FUSEE_SMMU_H_ + +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> + +#define SMMU_HEAP_BASE_ADDR 0x81000000 +#define SMMU_IRAM_BACKUP_ADDR 0x82000000 +#define SMMU_AARCH64_PAYLOAD_ADDR 0x40003F00 + +#define SMMU_PAGE_SHIFT 12 +#define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT) +#define SMMU_PDIR_COUNT 1024 +#define SMMU_PDIR_SIZE (sizeof(uint32_t) * SMMU_PDIR_COUNT) +#define SMMU_PTBL_COUNT 1024 +#define SMMU_PTBL_SIZE (sizeof(uint32_t) * SMMU_PTBL_COUNT) +#define SMMU_PDIR_SHIFT 12 +#define SMMU_PDE_SHIFT 12 +#define SMMU_PTE_SHIFT 12 +#define SMMU_PFN_MASK 0x000fffff +#define SMMU_PDE_NEXT_SHIFT 28 +#define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12) +#define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22) +#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << 22) +#define _READABLE (1 << 31) +#define _WRITABLE (1 << 30) +#define _NONSECURE (1 << 29) +#define _PDE_NEXT (1 << SMMU_PDE_NEXT_SHIFT) +#define _MASK_ATTR (_READABLE | _WRITABLE | _NONSECURE) +#define _PDIR_ATTR (_READABLE | _WRITABLE | _NONSECURE) +#define _PDE_ATTR (_READABLE | _WRITABLE | _NONSECURE) +#define _PDE_ATTR_N (_PDE_ATTR | _PDE_NEXT) +#define _PDE_VACANT(pdn) (((pdn) << 10) | _PDE_ATTR) +#define _PTE_ATTR (_READABLE | _WRITABLE | _NONSECURE) +#define _PTE_VACANT(addr) (((addr) >> SMMU_PAGE_SHIFT) | _PTE_ATTR) +#define SMMU_MK_PDIR(page, attr) (((page) >> SMMU_PDIR_SHIFT) | (attr)) +#define SMMU_MK_PDE(page, attr) (((page) >> SMMU_PDE_SHIFT) | (attr)) +#define SMMU_EX_PTBL_PAGE(pde) (((pde) & SMMU_PFN_MASK) << SMMU_PDIR_SHIFT) +#define SMMU_PFN_TO_PTE(pfn, attr) ((pfn) | (attr)) +#define SMMU_ASID_ENABLE(asid) ((asid) | (1 << 31)) +#define SMMU_ASID_DISABLE 0 +#define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0)) + +void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_size, void *package1_dec); + +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/tsec.c b/fusee/fusee-secondary/src/tsec.c index b864df405..75ec724a3 100644 --- a/fusee/fusee-secondary/src/tsec.c +++ b/fusee/fusee-secondary/src/tsec.c @@ -49,17 +49,34 @@ static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t ph return tsec_dma_wait_idle(); } -int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size) +void tsec_enable_clkrst() { - volatile tegra_tsec_t *tsec = tsec_get_regs(); - - /* Enable clocks. */ + /* Enable all devices used by TSEC. */ clkrst_reboot(CARDEVICE_HOST1X); clkrst_reboot(CARDEVICE_TSEC); clkrst_reboot(CARDEVICE_SOR_SAFE); clkrst_reboot(CARDEVICE_SOR0); clkrst_reboot(CARDEVICE_SOR1); clkrst_reboot(CARDEVICE_KFUSE); +} + +void tsec_disable_clkrst() +{ + /* Disable all devices used by TSEC. */ + clkrst_disable(CARDEVICE_KFUSE); + clkrst_disable(CARDEVICE_SOR1); + clkrst_disable(CARDEVICE_SOR0); + clkrst_disable(CARDEVICE_SOR_SAFE); + clkrst_disable(CARDEVICE_TSEC); + clkrst_disable(CARDEVICE_HOST1X); +} + +int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size) +{ + volatile tegra_tsec_t *tsec = tsec_get_regs(); + + /* Enable clocks. */ + tsec_enable_clkrst(); /* Configure Falcon. */ tsec->FALCON_DMACTL = 0; @@ -70,12 +87,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw if (!tsec_dma_wait_idle()) { /* Disable clocks. */ - clkrst_disable(CARDEVICE_KFUSE); - clkrst_disable(CARDEVICE_SOR1); - clkrst_disable(CARDEVICE_SOR0); - clkrst_disable(CARDEVICE_SOR_SAFE); - clkrst_disable(CARDEVICE_TSEC); - clkrst_disable(CARDEVICE_HOST1X); + tsec_disable_clkrst(); return -1; } @@ -87,12 +99,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw if (!tsec_dma_phys_to_flcn(true, addr, addr)) { /* Disable clocks. */ - clkrst_disable(CARDEVICE_KFUSE); - clkrst_disable(CARDEVICE_SOR1); - clkrst_disable(CARDEVICE_SOR0); - clkrst_disable(CARDEVICE_SOR_SAFE); - clkrst_disable(CARDEVICE_TSEC); - clkrst_disable(CARDEVICE_HOST1X); + tsec_disable_clkrst(); return -2; } @@ -110,12 +117,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw if (!tsec_dma_wait_idle()) { /* Disable clocks. */ - clkrst_disable(CARDEVICE_KFUSE); - clkrst_disable(CARDEVICE_SOR1); - clkrst_disable(CARDEVICE_SOR0); - clkrst_disable(CARDEVICE_SOR_SAFE); - clkrst_disable(CARDEVICE_TSEC); - clkrst_disable(CARDEVICE_HOST1X); + tsec_disable_clkrst(); return -3; } @@ -126,12 +128,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw if (get_time_ms() > timeout) { /* Disable clocks. */ - clkrst_disable(CARDEVICE_KFUSE); - clkrst_disable(CARDEVICE_SOR1); - clkrst_disable(CARDEVICE_SOR0); - clkrst_disable(CARDEVICE_SOR_SAFE); - clkrst_disable(CARDEVICE_TSEC); - clkrst_disable(CARDEVICE_HOST1X); + tsec_disable_clkrst(); return -4; } @@ -140,12 +137,7 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw if (tsec->FALCON_SCRATCH1 != 0xB0B0B0B0) { /* Disable clocks. */ - clkrst_disable(CARDEVICE_KFUSE); - clkrst_disable(CARDEVICE_SOR1); - clkrst_disable(CARDEVICE_SOR0); - clkrst_disable(CARDEVICE_SOR_SAFE); - clkrst_disable(CARDEVICE_TSEC); - clkrst_disable(CARDEVICE_HOST1X); + tsec_disable_clkrst(); return -5; } @@ -170,4 +162,55 @@ int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw memcpy(key, &tmp, 0x10); return 0; +} + +int tsec_load_fw(const void *tsec_fw, size_t tsec_fw_size) +{ + volatile tegra_tsec_t *tsec = tsec_get_regs(); + + /* Enable clocks. */ + tsec_enable_clkrst(); + + /* Configure Falcon. */ + tsec->FALCON_DMACTL = 0; + tsec->FALCON_IRQMSET = 0xFFF2; + tsec->FALCON_IRQDEST = 0xFFF0; + tsec->FALCON_ITFEN = 3; + + if (!tsec_dma_wait_idle()) + { + /* Disable clocks. */ + tsec_disable_clkrst(); + + return -1; + } + + /* Load firmware. */ + tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8; + for (uint32_t addr = 0; addr < tsec_fw_size; addr += 0x100) + { + if (!tsec_dma_phys_to_flcn(true, addr, addr)) + { + /* Disable clocks. */ + tsec_disable_clkrst(); + + return -2; + } + } + + return 0; +} + +void tsec_run_fw() +{ + volatile tegra_tsec_t *tsec = tsec_get_regs(); + + /* Unknown host1x write. */ + MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA; + + /* Execute firmware. */ + tsec->FALCON_SCRATCH1 = 0; + tsec->FALCON_SCRATCH0 = 1; + tsec->FALCON_BOOTVEC = 0; + tsec->FALCON_CPUCTL = 2; } \ No newline at end of file diff --git a/fusee/fusee-secondary/src/tsec.h b/fusee/fusee-secondary/src/tsec.h index c16c2f9a3..54842bdfb 100644 --- a/fusee/fusee-secondary/src/tsec.h +++ b/fusee/fusee-secondary/src/tsec.h @@ -109,6 +109,10 @@ static inline volatile tegra_tsec_t *tsec_get_regs(void) return (volatile tegra_tsec_t *)TSEC_BASE; } +void tsec_enable_clkrst(); +void tsec_disable_clkrst(); int tsec_get_key(uint8_t *key, uint32_t rev, const void *tsec_fw, size_t tsec_fw_size); +int tsec_load_fw(const void *tsec_fw, size_t tsec_fw_size); +void tsec_run_fw(); #endif \ No newline at end of file From bcdfc53d7dbd39fb46d54e7f58cce2bbd1a1f178 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 29 Nov 2018 15:22:53 -0800 Subject: [PATCH 258/489] Bump version to 0.8.0 --- common/include/atmosphere/version.h | 4 ++-- docs/changelog.md | 32 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 3b3834f34..b629c78ce 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -18,7 +18,7 @@ #define ATMOSPHERE_VERSION_H #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 -#define ATMOSPHERE_RELEASE_VERSION_MINOR 7 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 5 +#define ATMOSPHERE_RELEASE_VERSION_MINOR 8 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 #endif \ No newline at end of file diff --git a/docs/changelog.md b/docs/changelog.md index 7e3004468..65a66001f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,36 @@ # Changelog +## 0.8.0 ++ A custom `fatal` system module was added. + + This re-implements and extends Nintendo's fatal module, with the following features: + + Atmosphère's `fatal` does not create error reports. + + Atmosphère's `fatal` draws a custom error screen, showing registers and a backtrace. + + Atmosphère's `fatal` attempts to gather debugging info for all crashes, and not just ones that include info. + + Atmosphère's `fatal` will attempt saving reports to the SD, if a crash report was not generated by `creport`. ++ Title flag handling was changed to prevent folder clutter. + + Instead of living in `atmosphere/titles/<tid>/%s.flag`, flags are now located in `atmosphere/titles/<tid>/flags/%s.flag` + + The old format will continue to be supported for some time, but is deprecated. + + Flags can now be applied to HBL by placing them at `atmosphere/flags/hbl_%s.flag`. ++ Changes were made to the mitm API, greatly improving caller semantics. + + `sm` now informs mitm services of a new session's process id, enabling custom handling based on title id/process id. ++ smhax is no longer enabled, because it is no longer needed and breaks significant functionality. + + Users with updated HBL/homebrew should see no observable differences due to this change. ++ Functionality was added implementing basic protections for NAND from userland homebrew: + + BOOT0 now has write protection for the BCT public key and keyblob regions. + + The `ns` sysmodule is no longer allowed to write the BCT public keys; all other processes can. + + This should prevent system updates from removing AutoRCM. + + No processes should be allowed to write to the keyblob region. + + By default, BIS partitions other than BOOT0 are now read-only, and CAL0 is neither readable nor writable. + + Adding a `bis_write` flag for a title will allow it to write to BIS. + + Adding a `cal_read` flag for a title will allow it to read CAL0. + + An automatic backup is now made of CAL0 on boot. + + `fs.mitm` maintains a file handle to this backup, so userland software cannot read it. + + To facilitate this, `fs.mitm` now mitms all sessions for non-system modules; content overriding has been made separate from service interception. + + Please note: these protections are basic, and sufficiently malicious homebrew ++can defeat them++. + + Please be careful to only run homebrew software from sources that you trust. ++ Support was added for system version 6.2.0; our thanks to @motezazer for his invaluable help. + + By default, new keys will automatically be derived without user input. + + Support is also present for loading new keys from `atmosphere/prod.keys` or `atmosphere/dev.keys` ++ General system stability improvements to enhance the user's experience. ## 0.7.5 + DRAM training was added to fusee-secondary, courtesy @hexkyz. + This greatly improves the speed of memory accesses during boot, resulting in a boot time that is ~200-400% faster. From 49ad66e47890b62ed59422983c8f3c20b763aa82 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 02:42:48 -0800 Subject: [PATCH 259/489] stratosphere: Fix fs.mitm bis_protect race condition. --- .../fs_mitm/source/fsmitm_boot0storage.cpp | 2 +- stratosphere/fs_mitm/source/fsmitm_main.cpp | 12 ++++++------ stratosphere/libstratosphere | 2 +- stratosphere/pm/source/pm_boot2.cpp | 17 ++++++++++++++++- stratosphere/pm/source/pm_main.cpp | 1 - stratosphere/sm/source/sm_manager_service.cpp | 4 ++++ stratosphere/sm/source/sm_manager_service.hpp | 4 ++++ stratosphere/sm/source/sm_registration.cpp | 8 ++++++++ stratosphere/sm/source/sm_registration.hpp | 1 + 9 files changed, 41 insertions(+), 10 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp index 1554496bd..749eae8ff 100644 --- a/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp @@ -88,7 +88,7 @@ Result Boot0Storage::Write(void *_buffer, size_t size, u64 offset) { if (R_FAILED((rc = ProxyStorage::Write(buffer + diff, size - diff, BctEndOffset)))) { return rc; } - size -= diff; + size = diff; } /* Read in the current BCT region. */ diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 9d477261d..24fa8b647 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -89,6 +89,12 @@ int main(int argc, char **argv) Thread hid_initializer_thread = {0}; consoleDebugInit(debugDevice_SVC); + /* TODO: What's a good timeout value to use here? */ + auto server_manager = new FsMitmManager(5); + + /* Create fsp-srv mitm. */ + AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); + if (R_FAILED(threadCreate(&sd_initializer_thread, &Utils::InitializeSdThreadFunc, NULL, 0x4000, 0x15, 0))) { /* TODO: Panic. */ } @@ -102,12 +108,6 @@ int main(int argc, char **argv) if (R_FAILED(threadStart(&hid_initializer_thread))) { /* TODO: Panic. */ } - - /* TODO: What's a good timeout value to use here? */ - auto server_manager = new FsMitmManager(5); - - /* Create fsp-srv mitm. */ - AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); /* Loop forever, servicing our services. */ server_manager->Process(); diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 0bec72ca3..dd31b3d2e 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 0bec72ca36084e9780a8c28abd4a0b24c03c18af +Subproject commit dd31b3d2e2450a458ef9c0d6268f3780fe70e083 diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 78eddd963..864f2d9ff 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -123,7 +123,22 @@ static void MountSdCard() { fsdevMountSdmc(); } -void EmbeddedBoot2::Main() { +void EmbeddedBoot2::Main() { + /* Wait until fs.mitm has installed itself. We want this to happen as early as possible. */ + bool fs_mitm_installed = false; + + Result rc = smManagerAmsInitialize(); + if (R_FAILED(rc)) { + std::abort(); + } + while (R_FAILED((rc = smManagerAmsHasMitm(&fs_mitm_installed, "fsp-srv"))) || !fs_mitm_installed) { + if (R_FAILED(rc)) { + std::abort(); + } + svcSleepThread(1000ull); + } + smManagerAmsExit(); + /* psc, bus, pcv is the minimal set of required titles to get SD card. */ /* bus depends on pcie, and pcv depends on settings. */ /* Launch psc. */ diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index ac3abde53..c38e7ec1b 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -102,7 +102,6 @@ void __appInit(void) { rc = smManagerAmsInitialize(); if (R_SUCCEEDED(rc)) { smManagerAmsEndInitialDefers(); - smManagerAmsExit(); } else { fatalSimple(0xCAFE << 4 | 2); } diff --git a/stratosphere/sm/source/sm_manager_service.cpp b/stratosphere/sm/source/sm_manager_service.cpp index 1ae5ca624..16b7c3820 100644 --- a/stratosphere/sm/source/sm_manager_service.cpp +++ b/stratosphere/sm/source/sm_manager_service.cpp @@ -31,3 +31,7 @@ void ManagerService::AtmosphereEndInitDefers() { Registration::EndInitDefers(); } +void ManagerService::AtmosphereHasMitm(Out<bool> out, SmServiceName service) { + out.SetValue(Registration::HasMitm(smEncodeName(service.name))); +} + diff --git a/stratosphere/sm/source/sm_manager_service.hpp b/stratosphere/sm/source/sm_manager_service.hpp index 080c4c93e..454be7edb 100644 --- a/stratosphere/sm/source/sm_manager_service.hpp +++ b/stratosphere/sm/source/sm_manager_service.hpp @@ -17,6 +17,7 @@ #pragma once #include <switch.h> #include <stratosphere.hpp> +#include "sm_types.hpp" enum ManagerServiceCmd { Manager_Cmd_RegisterProcess = 0, @@ -24,6 +25,7 @@ enum ManagerServiceCmd { Manager_Cmd_AtmosphereEndInitDefers = 65000, + Manager_Cmd_AtmosphereHasMitm = 65001, }; class ManagerService final : public IServiceObject { @@ -32,11 +34,13 @@ class ManagerService final : public IServiceObject { virtual Result RegisterProcess(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac); virtual Result UnregisterProcess(u64 pid); virtual void AtmosphereEndInitDefers(); + virtual void AtmosphereHasMitm(Out<bool> out, SmServiceName service); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<Manager_Cmd_RegisterProcess, &ManagerService::RegisterProcess>(), MakeServiceCommandMeta<Manager_Cmd_UnregisterProcess, &ManagerService::UnregisterProcess>(), MakeServiceCommandMeta<Manager_Cmd_AtmosphereEndInitDefers, &ManagerService::AtmosphereEndInitDefers>(), + MakeServiceCommandMeta<Manager_Cmd_AtmosphereHasMitm, &ManagerService::AtmosphereHasMitm>(), }; }; diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index e5fc77c12..3401f800f 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -180,6 +180,9 @@ bool Registration::IsInitialProcess(u64 pid) { u64 Registration::GetInitialProcessId() { CacheInitialProcessIdLimits(); + if (IsInitialProcess(1)) { + return 1; + } return g_initial_process_id_low; } @@ -219,6 +222,11 @@ bool Registration::HasService(u64 service) { return std::any_of(g_service_list.begin(), g_service_list.end(), member_equals_fn(&Service::service_name, service)); } +bool Registration::HasMitm(u64 service) { + Registration::Service *target_service = GetService(service); + return target_service != NULL && target_service->mitm_pid != 0; +} + Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) { Registration::Service *target_service = GetService(service); if (target_service == NULL || ShouldInitDefer(service) || target_service->mitm_waiting_ack) { diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 657483822..8c4d72660 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -69,6 +69,7 @@ class Registration { /* Service management. */ static bool HasService(u64 service); + static bool HasMitm(u64 service); static Result GetServiceHandle(u64 pid, u64 service, Handle *out); static Result GetServiceForPid(u64 pid, u64 service, Handle *out); static Result RegisterServiceForPid(u64 pid, u64 service, u64 max_sessions, bool is_light, Handle *out); From 72a2c1089619e1cadfcf6a3e290610963bf2893b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 03:10:27 -0800 Subject: [PATCH 260/489] exosphere: Add support for enabling debugmode via BCT.ini --- exosphere/src/configitem.c | 22 ++++++++++++++++------ exosphere/src/configitem.h | 6 ++++-- exosphere/src/exocfg.c | 16 ++++++++++++++++ exosphere/src/exocfg.h | 4 ++++ exosphere/src/package2.c | 1 + exosphere/src/smc_api.c | 28 ++++++++++++++++++---------- fusee/fusee-secondary/src/exocfg.h | 4 ++++ fusee/fusee-secondary/src/nxboot.c | 17 +++++++++++++++++ 8 files changed, 80 insertions(+), 18 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 389bbcaec..f03fee2bf 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -28,8 +28,9 @@ #include "exocfg.h" static bool g_battery_profile = false; +static bool g_debugmode_override_user = false, g_debugmode_override_priv = false; -uint32_t configitem_set(ConfigItem item, uint64_t value) { +uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { if (item != CONFIGITEM_BATTERYPROFILE) { return 2; } @@ -40,7 +41,7 @@ uint32_t configitem_set(ConfigItem item, uint64_t value) { bool configitem_is_recovery_boot(void) { uint64_t is_recovery_boot; - if (configitem_get(CONFIGITEM_ISRECOVERYBOOT, &is_recovery_boot) != 0) { + if (configitem_get(true, CONFIGITEM_ISRECOVERYBOOT, &is_recovery_boot) != 0) { generic_panic(); } @@ -49,7 +50,7 @@ bool configitem_is_recovery_boot(void) { bool configitem_is_retail(void) { uint64_t is_retail; - if (configitem_get(CONFIGITEM_ISRETAIL, &is_retail) != 0) { + if (configitem_get(true, CONFIGITEM_ISRETAIL, &is_retail) != 0) { generic_panic(); } @@ -62,13 +63,18 @@ bool configitem_should_profile_battery(void) { uint64_t configitem_get_hardware_type(void) { uint64_t hardware_type; - if (configitem_get(CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) { + if (configitem_get(true, CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) { generic_panic(); } return hardware_type; } -uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) { +void configitem_set_debugmode_override(bool user, bool priv) { + g_debugmode_override_user = user; + g_debugmode_override_priv = priv; +} + +uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) { uint32_t result = 0; switch (item) { case CONFIGITEM_DISABLEPROGRAMVERIFICATION: @@ -109,7 +115,11 @@ uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) { *p_outvalue = bootconfig_get_memory_arrangement(); break; case CONFIGITEM_ISDEBUGMODE: - *p_outvalue = (int)(bootconfig_is_debug_mode()); + if ((privileged && g_debugmode_override_priv) || (!privileged && g_debugmode_override_user)) { + *p_outvalue = 1; + } else { + *p_outvalue = (int)(bootconfig_is_debug_mode()); + } break; case CONFIGITEM_KERNELMEMORYCONFIGURATION: *p_outvalue = bootconfig_get_kernel_memory_configuration(); diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index 864d76030..f73c5469b 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -43,13 +43,15 @@ typedef enum { CONFIGITEM_EXOSPHERE_VERSION = 65000 } ConfigItem; -uint32_t configitem_set(ConfigItem item, uint64_t value); -uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue); +uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value); +uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue); bool configitem_is_recovery_boot(void); bool configitem_is_retail(void); bool configitem_should_profile_battery(void); +void configitem_set_debugmode_override(bool user, bool priv); + uint64_t configitem_get_hardware_type(void); #endif diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index 10bc3ae64..77d655dd2 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -67,3 +67,19 @@ unsigned int exosphere_should_perform_620_keygen(void) { return g_exosphere_cfg.target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620 && EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_PERFORM_620_KEYGEN); } + +unsigned int exosphere_should_override_debugmode_priv(void) { + if (!g_has_loaded_config) { + generic_panic(); + } + + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV); +} + +unsigned int exosphere_should_override_debugmode_user(void) { + if (!g_has_loaded_config) { + generic_panic(); + } + + return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_IS_DEBUGMODE_USER); +} diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 286825965..56ff82fdf 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -50,6 +50,8 @@ #define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) +#define EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV (1 << 1u) +#define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) typedef struct { unsigned int magic; @@ -60,6 +62,8 @@ typedef struct { unsigned int exosphere_load_config(void); unsigned int exosphere_get_target_firmware(void); unsigned int exosphere_should_perform_620_keygen(void); +unsigned int exosphere_should_override_debugmode_priv(void); +unsigned int exosphere_should_override_debugmode_user(void); static inline unsigned int exosphere_get_target_firmware_for_init(void) { const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic; diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 706386de3..c4bed0142 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -509,6 +509,7 @@ uintptr_t get_pk2ldr_stack_address(void) { void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { /* Load Exosphere-specific config. */ exosphere_load_config(); + configitem_set_debugmode_override(exosphere_should_override_debugmode_user() != 0, exosphere_should_override_debugmode_priv() != 0); /* Setup the Security Engine. */ setup_se(); diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index f39645e47..902dd20a3 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -44,8 +44,8 @@ #define DEBUG_PANIC_ON_FAILURE 0 /* User SMC prototypes */ -uint32_t smc_set_config(smc_args_t *args); -uint32_t smc_get_config(smc_args_t *args); +uint32_t smc_set_config_user(smc_args_t *args); +uint32_t smc_get_config_user(smc_args_t *args); uint32_t smc_check_status(smc_args_t *args); uint32_t smc_get_result(smc_args_t *args); uint32_t smc_exp_mod(smc_args_t *args); @@ -71,7 +71,7 @@ uint32_t smc_decrypt_or_import_rsa_key(smc_args_t *args); uint32_t smc_cpu_suspend(smc_args_t *args); uint32_t smc_cpu_off(smc_args_t *args); uint32_t smc_cpu_on(smc_args_t *args); -/* uint32_t smc_get_config(smc_args_t *args); */ +uint32_t smc_get_config_priv(smc_args_t *args); uint32_t smc_get_random_bytes_for_priv(smc_args_t *args); uint32_t smc_panic(smc_args_t *args); uint32_t smc_configure_carveout(smc_args_t *args); @@ -89,8 +89,8 @@ typedef struct { static smc_table_entry_t g_smc_user_table[SMC_USER_HANDLERS] = { {0, NULL}, - {0xC3000401, smc_set_config}, - {0xC3000002, smc_get_config}, + {0xC3000401, smc_set_config_user}, + {0xC3000002, smc_get_config_user}, {0xC3000003, smc_check_status}, {0xC3000404, smc_get_result}, {0xC3000E05, smc_exp_mod}, @@ -114,7 +114,7 @@ static smc_table_entry_t g_smc_priv_table[SMC_PRIV_HANDLERS] = { {0xC4000001, smc_cpu_suspend}, {0x84000002, smc_cpu_off}, {0xC4000003, smc_cpu_on}, - {0xC3000004, smc_get_config}, /* NOTE: Same function as for USER */ + {0xC3000004, smc_get_config_priv}, {0xC3000005, smc_get_random_bytes_for_priv}, {0xC3000006, smc_panic}, {0xC3000007, smc_configure_carveout}, @@ -329,15 +329,15 @@ uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *), return result; } -uint32_t smc_set_config(smc_args_t *args) { +uint32_t smc_set_config_user(smc_args_t *args) { /* Actual value presumed in X3 on hardware. */ - return configitem_set((ConfigItem)args->X[1], args->X[3]); + return configitem_set(false, (ConfigItem)args->X[1], args->X[3]); } -uint32_t smc_get_config(smc_args_t *args) { +uint32_t smc_get_config_user(smc_args_t *args) { uint64_t out_item = 0; uint32_t result; - result = configitem_get((ConfigItem)args->X[1], &out_item); + result = configitem_get(false, (ConfigItem)args->X[1], &out_item); args->X[1] = out_item; return result; } @@ -534,6 +534,14 @@ uint32_t smc_cpu_suspend(smc_args_t *args) { return smc_wrapper_sync(args, cpu_suspend_wrapper); } +uint32_t smc_get_config_priv(smc_args_t *args) { + uint64_t out_item = 0; + uint32_t result; + result = configitem_get(true, (ConfigItem)args->X[1], &out_item); + args->X[1] = out_item; + return result; +} + uint32_t smc_get_random_bytes_for_priv(smc_args_t *args) { /* This is an interesting SMC. */ /* The kernel must NEVER be unable to get random bytes, if it needs them */ diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index d62775834..133ebffd3 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -37,6 +37,8 @@ #define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) +#define EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV (1 << 1u) +#define EXOSPHERE_FLAG_IS_DEBUGMODE_USER (1 << 2u) typedef struct { unsigned int magic; @@ -47,5 +49,7 @@ typedef struct { #define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40)) #define EXOSPHERE_TARGETFW_KEY "target_firmware" +#define EXOSPHERE_DEBUGMODE_PRIV_KEY "debug_mode" +#define EXOSPHERE_DEBUGMODE_USER_KEY "debug_mode_user" #endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index eec1fd2f9..eca9181c9 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -53,9 +53,26 @@ static int exosphere_ini_handler(void *user, const char *section, const char *name, const char *value) { exosphere_config_t *exo_cfg = (exosphere_config_t *)user; + int tmp = 0; if (strcmp(section, "exosphere") == 0) { if (strcmp(name, EXOSPHERE_TARGETFW_KEY) == 0) { sscanf(value, "%d", &exo_cfg->target_firmware); + } + if (strcmp(name, EXOSPHERE_DEBUGMODE_PRIV_KEY) == 0) { + sscanf(value, "%d", &tmp); + if (tmp) { + exo_cfg->flags |= EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV; + } else { + exo_cfg->flags &= ~(EXOSPHERE_FLAG_IS_DEBUGMODE_PRIV); + } + } + if (strcmp(name, EXOSPHERE_DEBUGMODE_USER_KEY) == 0) { + sscanf(value, "%d", &tmp); + if (tmp) { + exo_cfg->flags |= EXOSPHERE_FLAG_IS_DEBUGMODE_USER; + } else { + exo_cfg->flags &= ~(EXOSPHERE_FLAG_IS_DEBUGMODE_USER); + } } else { return 0; } From 72f028efaef75b4d1fac5eb484d3042d91374bc0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 04:10:23 -0800 Subject: [PATCH 261/489] fusee: Implement built-in support for togglable nogc patches --- Makefile | 1 + ...E0377EF526CE6AD2AC6F2CAD7180CE69E74311.ips | Bin 0 -> 27 bytes ...6F10FB367A00BBD8B7D8D1F25CCE0B458D7E89.ips | Bin 0 -> 27 bytes ...AC2DF1E2BCAB3BC19DC5CD63DB6FAEC0947097.ips | Bin 0 -> 27 bytes ...0276B3EAD664DA79826FA936F99803B6C28F3B.ips | Bin 0 -> 27 bytes ...076B11737132EBB1484CF906B6A8EB3B1BF459.ips | Bin 0 -> 27 bytes ...CE4A5A1DA2D5C393F74224F8BC09DE4AAA4217.ips | Bin 0 -> 27 bytes ...CEBB93E3E9695C7CFD390F00509B1204101C24.ips | Bin 0 -> 27 bytes ...413B0B64CE03BD9BBFEB26F2B3E01C5427C69E.ips | Bin 0 -> 27 bytes ...785A0CD7AA9DC1A63C57D10049423DE7B77E2C.ips | Bin 0 -> 27 bytes ...2B32B432340DD2C7590CDEFC03E51B844AE805.ips | Bin 0 -> 27 bytes fusee/fusee-secondary/src/ips.c | 65 +++++++++++++++++- fusee/fusee-secondary/src/ips.h | 2 + fusee/fusee-secondary/src/nxboot.c | 22 ++++++ fusee/fusee-secondary/src/stratosphere.h | 3 + 15 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 common/defaults/kip_patches/default_nogc/02D5ABAAFD20C8B0633AA0DBAEE0377EF526CE6AD2AC6F2CAD7180CE69E74311.ips create mode 100644 common/defaults/kip_patches/default_nogc/06E90719595A010C6246FF70946F10FB367A00BBD8B7D8D1F25CCE0B458D7E89.ips create mode 100644 common/defaults/kip_patches/default_nogc/10B2D81605488599DF2242CB6BAC2DF1E2BCAB3BC19DC5CD63DB6FAEC0947097.ips create mode 100644 common/defaults/kip_patches/default_nogc/330553F6B5FB55C4C2D7B736240276B3EAD664DA79826FA936F99803B6C28F3B.ips create mode 100644 common/defaults/kip_patches/default_nogc/3A574D436186191D1788EB2C0F076B11737132EBB1484CF906B6A8EB3B1BF459.ips create mode 100644 common/defaults/kip_patches/default_nogc/549B0F8D6F72C4E9F3FD1F19EACE4A5A1DA2D5C393F74224F8BC09DE4AAA4217.ips create mode 100644 common/defaults/kip_patches/default_nogc/76F87402C9387C0F0A2FAB1B45CEBB93E3E9695C7CFD390F00509B1204101C24.ips create mode 100644 common/defaults/kip_patches/default_nogc/8096AF7C6A35AA8271F3916995413B0B64CE03BD9BBFEB26F2B3E01C5427C69E.ips create mode 100644 common/defaults/kip_patches/default_nogc/A6F27AD9AC7C73AD419B63B23E785A0CD7AA9DC1A63C57D10049423DE7B77E2C.ips create mode 100644 common/defaults/kip_patches/default_nogc/CE3ECBA2F2F062F575F8F360842B32B432340DD2C7590CDEFC03E51B844AE805.ips diff --git a/Makefile b/Makefile index 6bcecf67f..9d8364e89 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,7 @@ dist: all cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/fusee-secondary.bin cp common/defaults/BCT.ini atmosphere-$(AMSVER)/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini + cp -r common/defaults/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034/exefs.nsp cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp diff --git a/common/defaults/kip_patches/default_nogc/02D5ABAAFD20C8B0633AA0DBAEE0377EF526CE6AD2AC6F2CAD7180CE69E74311.ips b/common/defaults/kip_patches/default_nogc/02D5ABAAFD20C8B0633AA0DBAEE0377EF526CE6AD2AC6F2CAD7180CE69E74311.ips new file mode 100644 index 0000000000000000000000000000000000000000..62f99241b1fc0d676880aabf6c3e4d8057b4b823 GIT binary patch literal 27 icmWG=3~~10GTqC-*ub@B1p~(eW_hgx%<<P;{oMd<MF>&= literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/06E90719595A010C6246FF70946F10FB367A00BBD8B7D8D1F25CCE0B458D7E89.ips b/common/defaults/kip_patches/default_nogc/06E90719595A010C6246FF70946F10FB367A00BBD8B7D8D1F25CCE0B458D7E89.ips new file mode 100644 index 0000000000000000000000000000000000000000..7f1adb6e1a2fc09f477f590c1a133caa40ebbca2 GIT binary patch literal 27 icmWG=3~~10GL2+lY~Whs!ocx>SzhY^bNn?|e>VVM{RfHw literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/10B2D81605488599DF2242CB6BAC2DF1E2BCAB3BC19DC5CD63DB6FAEC0947097.ips b/common/defaults/kip_patches/default_nogc/10B2D81605488599DF2242CB6BAC2DF1E2BCAB3BC19DC5CD63DB6FAEC0947097.ips new file mode 100644 index 0000000000000000000000000000000000000000..d8f050ed0da131200dc0e941dfda20dcd2c68dca GIT binary patch literal 27 icmWG=3~~10`7xD&v4OXufPv!yv%J;;=J;!_{%!ztWC(@; literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/330553F6B5FB55C4C2D7B736240276B3EAD664DA79826FA936F99803B6C28F3B.ips b/common/defaults/kip_patches/default_nogc/330553F6B5FB55C4C2D7B736240276B3EAD664DA79826FA936F99803B6C28F3B.ips new file mode 100644 index 0000000000000000000000000000000000000000..26f1345d9fb6734b27a04e41387eaf77758f5dd4 GIT binary patch literal 27 icmWG=3~}}l{qU86u|c>+fq~-zv%J;;=J;!_{%!zxwg{;J literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/3A574D436186191D1788EB2C0F076B11737132EBB1484CF906B6A8EB3B1BF459.ips b/common/defaults/kip_patches/default_nogc/3A574D436186191D1788EB2C0F076B11737132EBB1484CF906B6A8EB3B1BF459.ips new file mode 100644 index 0000000000000000000000000000000000000000..da978a82a58cd22218ac20bcbad99a2b0a66bf5a GIT binary patch literal 27 icmWG=3~}}lwfxG!*dTOPfq~-zv%J;;=J;!_{%!zm>Igaj literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/549B0F8D6F72C4E9F3FD1F19EACE4A5A1DA2D5C393F74224F8BC09DE4AAA4217.ips b/common/defaults/kip_patches/default_nogc/549B0F8D6F72C4E9F3FD1F19EACE4A5A1DA2D5C393F74224F8BC09DE4AAA4217.ips new file mode 100644 index 0000000000000000000000000000000000000000..7f1adb6e1a2fc09f477f590c1a133caa40ebbca2 GIT binary patch literal 27 icmWG=3~~10GL2+lY~Whs!ocx>SzhY^bNn?|e>VVM{RfHw literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/76F87402C9387C0F0A2FAB1B45CEBB93E3E9695C7CFD390F00509B1204101C24.ips b/common/defaults/kip_patches/default_nogc/76F87402C9387C0F0A2FAB1B45CEBB93E3E9695C7CFD390F00509B1204101C24.ips new file mode 100644 index 0000000000000000000000000000000000000000..d8f050ed0da131200dc0e941dfda20dcd2c68dca GIT binary patch literal 27 icmWG=3~~10`7xD&v4OXufPv!yv%J;;=J;!_{%!ztWC(@; literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/8096AF7C6A35AA8271F3916995413B0B64CE03BD9BBFEB26F2B3E01C5427C69E.ips b/common/defaults/kip_patches/default_nogc/8096AF7C6A35AA8271F3916995413B0B64CE03BD9BBFEB26F2B3E01C5427C69E.ips new file mode 100644 index 0000000000000000000000000000000000000000..62f99241b1fc0d676880aabf6c3e4d8057b4b823 GIT binary patch literal 27 icmWG=3~~10GTqC-*ub@B1p~(eW_hgx%<<P;{oMd<MF>&= literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/A6F27AD9AC7C73AD419B63B23E785A0CD7AA9DC1A63C57D10049423DE7B77E2C.ips b/common/defaults/kip_patches/default_nogc/A6F27AD9AC7C73AD419B63B23E785A0CD7AA9DC1A63C57D10049423DE7B77E2C.ips new file mode 100644 index 0000000000000000000000000000000000000000..dd546f608b612e41343718cd381f60d203935bb8 GIT binary patch literal 27 icmWG=3~~10`Erzjv4OW_0RzVaW_hgx%<<P;{oMe1Gzi`R literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/CE3ECBA2F2F062F575F8F360842B32B432340DD2C7590CDEFC03E51B844AE805.ips b/common/defaults/kip_patches/default_nogc/CE3ECBA2F2F062F575F8F360842B32B432340DD2C7590CDEFC03E51B844AE805.ips new file mode 100644 index 0000000000000000000000000000000000000000..dd546f608b612e41343718cd381f60d203935bb8 GIT binary patch literal 27 icmWG=3~~10`Erzjv4OW_0RzVaW_hgx%<<P;{oMe1Gzi`R literal 0 HcmV?d00001 diff --git a/fusee/fusee-secondary/src/ips.c b/fusee/fusee-secondary/src/ips.c index 41c2840a6..036789789 100644 --- a/fusee/fusee-secondary/src/ips.c +++ b/fusee/fusee-secondary/src/ips.c @@ -33,6 +33,53 @@ #define IPS32_MAGIC "IPS32" #define IPS32_TAIL "EEOF" +#define NOGC_PATCH_DIR "default_nogc" +static bool g_enable_nogc_patches = false; + +void kip_patches_set_enable_nogc(void) { + g_enable_nogc_patches = true; +} + +static bool should_ignore_default_patch(const char *patch_dir) { + /* This function will ensure that select default patches only get loaded if enabled. */ + if (!g_enable_nogc_patches && strcmp(patch_dir, NOGC_PATCH_DIR) == 0) { + return true; + } + + return false; +} + +static bool has_patch(const char *dir, const char *subdir, const void *hash, size_t hash_size) { + char path[0x301] = {0}; + int cur_len = 0; + cur_len += snprintf(path + cur_len, sizeof(path) - cur_len, "%s/", dir); + if (subdir != NULL) { + cur_len += snprintf(path + cur_len, sizeof(path) - cur_len, "%s/", subdir); + } + for (size_t i = 0; i < hash_size; i++) { + cur_len += snprintf(path + cur_len, sizeof(path) - cur_len, "%02X", ((const uint8_t *)hash)[i]); + } + cur_len += snprintf(path + cur_len, sizeof(path) - cur_len, ".ips"); + if (cur_len >= sizeof(path)) { + return false; + } + + FILE *f = fopen(path, "rb"); + if (f != NULL) { + fclose(f); + return true; + } + return false; +} + +static bool has_needed_default_kip_patches(uint64_t title_id, const void *hash, size_t hash_size) { + if (title_id == 0x0100000000000000ULL && g_enable_nogc_patches) { + return has_patch("atmosphere/kip_patches", NOGC_PATCH_DIR, hash, hash_size); + } + + return true; +} + /* Applies an IPS/IPS32 patch to memory, disregarding writes to the first prot_size bytes. */ static void apply_ips_patch(uint8_t *mem, size_t mem_size, size_t prot_size, bool is_ips32, FILE *f_ips) { uint8_t buffer[4]; @@ -156,6 +203,11 @@ static bool has_ips_patches(const char *dir, const void *hash, size_t hash_size) if (strcmp(pdir_ent->d_name, ".") == 0 || strcmp(pdir_ent->d_name, "..") == 0) { continue; } + + if (should_ignore_default_patch(pdir_ent->d_name)) { + continue; + } + snprintf(path, sizeof(path) - 1, "%s/%s", dir, pdir_ent->d_name); DIR *patch_dir = opendir(path); struct dirent *ent; @@ -165,6 +217,7 @@ static bool has_ips_patches(const char *dir, const void *hash, size_t hash_size) if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { continue; } + size_t name_len = strlen(ent->d_name); if ((4 < name_len && name_len <= 0x44) && ((name_len & 1) == 0) && strcmp(ent->d_name + name_len - 4, ".ips") == 0 && name_matches_hash(ent->d_name, name_len, hash, hash_size)) { snprintf(path, sizeof(path) - 1, "%s/%s/%s", dir, pdir_ent->d_name, ent->d_name); @@ -200,6 +253,11 @@ static void apply_ips_patches(const char *dir, void *mem, size_t mem_size, size_ if (strcmp(pdir_ent->d_name, ".") == 0 || strcmp(pdir_ent->d_name, "..") == 0) { continue; } + + if (should_ignore_default_patch(pdir_ent->d_name)) { + continue; + } + snprintf(path, sizeof(path) - 1, "%s/%s", dir, pdir_ent->d_name); DIR *patch_dir = opendir(path); struct dirent *ent; @@ -209,6 +267,7 @@ static void apply_ips_patches(const char *dir, void *mem, size_t mem_size, size_ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { continue; } + size_t name_len = strlen(ent->d_name); if ((4 < name_len && name_len <= 0x44) && ((name_len & 1) == 0) && strcmp(ent->d_name + name_len - 4, ".ips") == 0 && name_matches_hash(ent->d_name, name_len, hash, hash_size)) { snprintf(path, sizeof(path) - 1, "%s/%s/%s", dir, pdir_ent->d_name, ent->d_name); @@ -316,7 +375,11 @@ static kip1_header_t *kip1_uncompress(kip1_header_t *kip, size_t *size) { kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size) { uint8_t hash[0x20]; se_calculate_sha256(hash, kip, kip_size); - + + if (!has_needed_default_kip_patches(kip->title_id, hash, sizeof(hash))) { + fatal_error("[NXBOOT]: Missing default patch for KIP %08x%08x...\n", (uint32_t)(kip->title_id >> 32), (uint32_t)kip->title_id); + } + if (!has_ips_patches("atmosphere/kip_patches", hash, sizeof(hash))) { return NULL; } diff --git a/fusee/fusee-secondary/src/ips.h b/fusee/fusee-secondary/src/ips.h index 6db00a1f1..f39e8b89c 100644 --- a/fusee/fusee-secondary/src/ips.h +++ b/fusee/fusee-secondary/src/ips.h @@ -24,4 +24,6 @@ void apply_kernel_ips_patches(void *kernel, size_t kernel_size); kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size); +void kip_patches_set_enable_nogc(void); + #endif diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index eca9181c9..87703c90b 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -29,6 +29,8 @@ #include "se.h" #include "pmc.h" #include "i2c.h" +#include "ips.h" +#include "stratosphere.h" #include "max77620.h" #include "cluster.h" #include "flow.h" @@ -82,6 +84,23 @@ static int exosphere_ini_handler(void *user, const char *section, const char *na return 1; } +static int stratosphere_ini_handler(void *user, const char *section, const char *name, const char *value) { + int tmp = 0; + if (strcmp(section, "stratosphere") == 0) { + if (strcmp(name, STRATOSPHERE_NOGC_KEY) == 0) { + sscanf(value, "%d", &tmp); + if (tmp) { + kip_patches_set_enable_nogc(); + } + } else { + return 0; + } + } else { + return 0; + } + return 1; +} + static uint32_t nxboot_get_target_firmware(const void *package1loader) { const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; switch (package1loader_header->version) { @@ -427,6 +446,9 @@ uint32_t nxboot_main(void) { print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Rebuilding package2...\n"); /* Patch package2, adding Thermosphère + custom KIPs. */ + if (ini_parse_string(get_loader_ctx()->bct0, stratosphere_ini_handler, NULL) < 0) { + fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); + } package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Reading Exosphère...\n"); diff --git a/fusee/fusee-secondary/src/stratosphere.h b/fusee/fusee-secondary/src/stratosphere.h index 2ae43f1be..58caae31f 100644 --- a/fusee/fusee-secondary/src/stratosphere.h +++ b/fusee/fusee-secondary/src/stratosphere.h @@ -31,4 +31,7 @@ void stratosphere_free_ini1(void); ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_inis); + +#define STRATOSPHERE_NOGC_KEY "nogc" + #endif From c6003ff530c9e86b9d8052f0775769c7f19734f4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 04:13:06 -0800 Subject: [PATCH 262/489] ams: update default BCT.ini --- common/defaults/BCT.ini | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/defaults/BCT.ini b/common/defaults/BCT.ini index 3a8600340..f98177b90 100644 --- a/common/defaults/BCT.ini +++ b/common/defaults/BCT.ini @@ -2,4 +2,11 @@ BCT0 [stage1] stage2_path = fusee-secondary.bin stage2_addr = 0xF0000000 -stage2_entrypoint = 0xF0000000 \ No newline at end of file +stage2_entrypoint = 0xF0000000 + +[exosphere] +debugmode = 0 +debugmode_user = 0 + +[stratosphere] +nogc = 0 From 52018036854919f27ead08daf7d408d60485111f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 04:36:29 -0800 Subject: [PATCH 263/489] fusee: auto-apply nogc if fuses say we should. --- common/defaults/BCT.ini | 3 ++- fusee/fusee-secondary/src/nxboot.c | 32 +++++++++++++++++++----- fusee/fusee-secondary/src/stratosphere.h | 4 +++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/common/defaults/BCT.ini b/common/defaults/BCT.ini index f98177b90..81d69e48e 100644 --- a/common/defaults/BCT.ini +++ b/common/defaults/BCT.ini @@ -9,4 +9,5 @@ debugmode = 0 debugmode_user = 0 [stratosphere] -nogc = 0 +; To force-enable nogc, add nogc = 1 +; To force-disable nogc, add nogc = 0 diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 87703c90b..e023e23fa 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -28,6 +28,7 @@ #include "mc.h" #include "se.h" #include "pmc.h" +#include "fuse.h" #include "i2c.h" #include "ips.h" #include "stratosphere.h" @@ -85,13 +86,13 @@ static int exosphere_ini_handler(void *user, const char *section, const char *na } static int stratosphere_ini_handler(void *user, const char *section, const char *name, const char *value) { + stratosphere_cfg_t *strat_cfg = (stratosphere_cfg_t *)user; int tmp = 0; if (strcmp(section, "stratosphere") == 0) { if (strcmp(name, STRATOSPHERE_NOGC_KEY) == 0) { + strat_cfg->has_nogc_config = true; sscanf(value, "%d", &tmp); - if (tmp) { - kip_patches_set_enable_nogc(); - } + strat_cfg->enable_nogc = tmp != 0; } else { return 0; } @@ -150,6 +151,25 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke *(MAILBOX_EXOSPHERE_CONFIGURATION) = exo_cfg; } +static void nxboot_configure_stratosphere(uint32_t target_firmware) { + stratosphere_cfg_t strat_cfg = {0}; + if (ini_parse_string(get_loader_ctx()->bct0, stratosphere_ini_handler, &strat_cfg) < 0) { + fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); + } + + /* Enable NOGC patches if the user requested it, or if the user is booting into 4.0.0+ with 3.0.2- fuses. */ + if (strat_cfg.has_nogc_config) { + if (strat_cfg.enable_nogc) { + kip_patches_set_enable_nogc(); + } + } else { + /* Check if fuses are < 4.0.0, but firmware is >= 4.0.0 */ + if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_400 && !(fuse_get_reserved_odm(7) & ~0x0000000F)) { + kip_patches_set_enable_nogc(); + } + } +} + static void nxboot_set_bootreason() { boot_reason_t boot_reason = {0}; FILE *boot0; @@ -444,11 +464,11 @@ uint32_t nxboot_main(void) { } print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Rebuilding package2...\n"); + + /* Parse stratosphere config. */ + nxboot_configure_stratosphere(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); /* Patch package2, adding Thermosphère + custom KIPs. */ - if (ini_parse_string(get_loader_ctx()->bct0, stratosphere_ini_handler, NULL) < 0) { - fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); - } package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Reading Exosphère...\n"); diff --git a/fusee/fusee-secondary/src/stratosphere.h b/fusee/fusee-secondary/src/stratosphere.h index 58caae31f..127e62ad9 100644 --- a/fusee/fusee-secondary/src/stratosphere.h +++ b/fusee/fusee-secondary/src/stratosphere.h @@ -31,6 +31,10 @@ void stratosphere_free_ini1(void); ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_inis); +typedef struct { + bool has_nogc_config; + bool enable_nogc; +} stratosphere_cfg_t; #define STRATOSPHERE_NOGC_KEY "nogc" From 25956c4fa170107ee6e7b362f6542c5e5a238dc2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 04:51:27 -0800 Subject: [PATCH 264/489] fatal: Print special message for version mistmatch. --- stratosphere/fatal/source/fatal_task_screen.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 66e39b69c..4ca01cee9 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -210,7 +210,17 @@ Result ShowFatalTask::ShowFatal() { FontManager::AddSpacingLines(0.5f); FontManager::PrintFormatLine(u8"Firmware: %s (Atmosphère %u.%u.%u-%s)", GetFatalConfig()->firmware_version.display_version, CURRENT_ATMOSPHERE_VERSION, GetAtmosphereGitRevision()); FontManager::AddSpacingLines(1.5f); - FontManager::Print(config->error_desc); + if (this->ctx->error_code != 0xCAFEF) { + FontManager::Print(config->error_desc); + } else { + /* Print a special message for atmosphere version mismatch. */ + FontManager::Print(u8"Atmosphère version mismatch detected.\n\n" + u8"Please press the POWER Button to restart the console. If you are\n" + u8"unable to restart the console, hold the POWER Button for 12 seconds\n" + u8"to turn the console off.\n\n" + u8"Please ensure that all Atmosphère components are updated.\n" + u8"github.com/Atmosphere-NX/Atmosphere/releases\n"); + } /* Add a line. */ for (size_t x = 32; x < FatalScreenWidth - 32; x++) { From 8d3b8354c30480625862da5f24a4c10d9bd19673 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 04:57:17 -0800 Subject: [PATCH 265/489] Exosphere: Add extension to perform a reboot to rcm. --- exosphere/src/configitem.c | 21 ++++++++++++++++++--- exosphere/src/configitem.h | 3 ++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index f03fee2bf..1f70343bb 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -31,11 +31,22 @@ static bool g_battery_profile = false; static bool g_debugmode_override_user = false, g_debugmode_override_priv = false; uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { - if (item != CONFIGITEM_BATTERYPROFILE) { - return 2; + switch (item) { + case CONFIGITEM_BATTERYPROFILE: + g_battery_profile = (value != 0); + break; + case CONFIGITEM_NEEDS_REBOOT_TO_RCM: + /* Force a reboot to RCM. */ + { + MAKE_REG32(0x7000E450) = 0x2; + MAKE_REG32(0x7000E400) = 0x10; + while (1) { } + } + break; + default: + return 2; } - g_battery_profile = (value != 0); return 0; } @@ -167,6 +178,10 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) ((uint64_t)(exosphere_get_target_firmware() & 0xFF) << 8ull) | ((uint64_t)(mkey_get_revision() & 0xFF) << 0ull); break; + case CONFIGITEM_NEEDS_REBOOT_TO_RCM: + /* UNOFFICIAL: The fact that we are executing means we aren't in the process of rebooting to rcm. */ + *p_outvalue = 0; + break; default: result = 2; break; diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index f73c5469b..8aef4e975 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -40,7 +40,8 @@ typedef enum { CONFIGITEM_PACKAGE2HASH_5X = 17, /* These are unofficial, for usage by Exosphere. */ - CONFIGITEM_EXOSPHERE_VERSION = 65000 + CONFIGITEM_EXOSPHERE_VERSION = 65000, + CONFIGITEM_NEEDS_REBOOT_TO_RCM = 65001, } ConfigItem; uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value); From be5b58d033aa53c7798fb8830bc6255deeadbf61 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 05:33:35 -0800 Subject: [PATCH 266/489] fatal: Reboot to RCM if VOL is pressed instead of PWR. --- exosphere/src/configitem.c | 4 +- stratosphere/fatal/fatal.json | 3 +- stratosphere/fatal/source/fatal_config.cpp | 6 +-- stratosphere/fatal/source/fatal_main.cpp | 3 +- stratosphere/fatal/source/fatal_repair.cpp | 2 +- .../fatal/source/fatal_task_power.cpp | 37 +++++++++++++++++-- .../fatal/source/fatal_task_screen.cpp | 6 +-- stratosphere/libstratosphere | 2 +- 8 files changed, 48 insertions(+), 15 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 1f70343bb..9aa1e6fa8 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -36,8 +36,8 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { g_battery_profile = (value != 0); break; case CONFIGITEM_NEEDS_REBOOT_TO_RCM: - /* Force a reboot to RCM. */ - { + /* Force a reboot to RCM, if requested. */ + if (value != 0) { MAKE_REG32(0x7000E450) = 0x2; MAKE_REG32(0x7000E400) = 0x10; while (1) { } diff --git a/stratosphere/fatal/fatal.json b/stratosphere/fatal/fatal.json index 76bce7e4f..201875895 100644 --- a/stratosphere/fatal/fatal.json +++ b/stratosphere/fatal/fatal.json @@ -83,7 +83,8 @@ "svcGetDebugThreadContext": "0x67", "svcQueryDebugProcessMemory": "0x69", "svcReadDebugProcessMemory": "0x6a", - "svcGetDebugThreadParam": "0x6d" + "svcGetDebugThreadParam": "0x6d", + "svcCallSecureMonitor": "0x7f" } }, { "type": "min_kernel_version", diff --git a/stratosphere/fatal/source/fatal_config.cpp b/stratosphere/fatal/source/fatal_config.cpp index fd1703137..11cc32420 100644 --- a/stratosphere/fatal/source/fatal_config.cpp +++ b/stratosphere/fatal/source/fatal_config.cpp @@ -58,9 +58,9 @@ static void SetupConfigLanguages() { config->error_desc = u8"Please call 1-800-875-1852 for service.\n"; } else { config->error_desc = u8"An error has occured.\n\n" - u8"Please press the POWER Button to restart the console. If you are\n" - u8"unable to restart the console, hold the POWER Button for 12 seconds\n" - u8"to turn the console off.\n\n" + u8"Please press the POWER Button to restart the console, or a VOL button\n" + u8"to restart the console in RCM mode. If you are unable to restart the\n" + u8"console, hold the POWER Button for 12 seconds to turn the console off.\n\n" u8"If the problem persists, refer to the Nintendo Support Website.\n" u8"support.nintendo.com/switch/error\n"; } diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 7790e85b7..733dc6eff 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -118,7 +118,7 @@ void __appInit(void) { std::abort(); } - rc = fsInitialize(); + rc = gpioInitialize(); if (R_FAILED(rc)) { std::abort(); } @@ -141,6 +141,7 @@ void __appExit(void) { fsdevUnmountAll(); fsExit(); plExit(); + gpioExit(); spsmExit(); psmExit(); lblExit(); diff --git a/stratosphere/fatal/source/fatal_repair.cpp b/stratosphere/fatal/source/fatal_repair.cpp index 432384cf7..b884c1aef 100644 --- a/stratosphere/fatal/source/fatal_repair.cpp +++ b/stratosphere/fatal/source/fatal_repair.cpp @@ -52,7 +52,7 @@ static bool InRepairWithoutVolHeld() { /* Sleep for 100 ms. */ svcSleepThread(100000000UL); - } + } } return false; diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index a804d6ff5..41954a0f5 100644 --- a/stratosphere/fatal/source/fatal_task_power.cpp +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -94,14 +94,45 @@ void PowerButtonObserveTask::WaitForPowerButton() { /* Force a reboot after some time if kiosk unit. */ const FatalConfig *config = GetFatalConfig(); - TimeoutHelper reboot_helper(config->quest_reboot_interval_second * 1000000000UL); + TimeoutHelper reboot_helper(config->quest_reboot_interval_second * 1000000000UL); + + bool check_vol_up = true, check_vol_down = true; + GpioPadSession vol_up_btn, vol_down_btn; + if (R_FAILED(gpioOpenSession(&vol_up_btn, GpioPadName_ButtonVolUp))) { + check_vol_up = false; + } + if (R_FAILED(gpioOpenSession(&vol_down_btn, GpioPadName_ButtonVolDown))) { + check_vol_down = false; + } + + /* Ensure we close on early return. */ + ON_SCOPE_EXIT { if (check_vol_up) { gpioPadClose(&vol_up_btn); } }; + ON_SCOPE_EXIT { if (check_vol_down) { gpioPadClose(&vol_down_btn); } }; + + /* Set direction input. */ + if (check_vol_up) { + gpioPadSetDirection(&vol_up_btn, GpioDirection_Input); + } + if (check_vol_down) { + gpioPadSetDirection(&vol_down_btn, GpioDirection_Input); + } BpcSleepButtonState state; + GpioValue val; while (true) { + Result rc = 0; + if (check_vol_up && R_SUCCEEDED((rc = gpioPadGetValue(&vol_up_btn, &val))) && val == GpioValue_Low) { + /* Tell exosphere to reboot to RCM. */ + RebootToRcm(); + } - Result rc = bpcGetSleepButtonState(&state); - if ((R_SUCCEEDED(rc) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) { + if (check_vol_down && R_SUCCEEDED((rc = gpioPadGetValue(&vol_down_btn, &val))) && val == GpioValue_Low) { + /* Tell exosphere to reboot to RCM. */ + RebootToRcm(); + } + + if ((R_SUCCEEDED(rc = bpcGetSleepButtonState(&state)) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) { bpcRebootSystem(); return; } diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 4ca01cee9..144935406 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -215,9 +215,9 @@ Result ShowFatalTask::ShowFatal() { } else { /* Print a special message for atmosphere version mismatch. */ FontManager::Print(u8"Atmosphère version mismatch detected.\n\n" - u8"Please press the POWER Button to restart the console. If you are\n" - u8"unable to restart the console, hold the POWER Button for 12 seconds\n" - u8"to turn the console off.\n\n" + u8"Please press the POWER Button to restart the console, or a VOL button\n" + u8"to restart the console in RCM mode. If you are unable to restart the\n" + u8"console, hold the POWER Button for 12 seconds to turn the console off.\n\n" u8"Please ensure that all Atmosphère components are updated.\n" u8"github.com/Atmosphere-NX/Atmosphere/releases\n"); } diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index dd31b3d2e..05015b935 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit dd31b3d2e2450a458ef9c0d6268f3780fe70e083 +Subproject commit 05015b9354d3df80e0836aa95d1d4dcfc2aef4b7 From 33b7e227d48323056205bfc77c048274f73e722f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 06:34:20 -0800 Subject: [PATCH 267/489] fusee: do PMC reboots, not CAR reboots. --- fusee/fusee-primary/src/utils.c | 11 +---------- fusee/fusee-primary/src/utils.h | 1 - fusee/fusee-secondary/src/utils.c | 11 +---------- fusee/fusee-secondary/src/utils.h | 1 - 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/fusee/fusee-primary/src/utils.c b/fusee/fusee-primary/src/utils.c index 87e84e793..26e838130 100644 --- a/fusee/fusee-primary/src/utils.c +++ b/fusee/fusee-primary/src/utils.c @@ -59,21 +59,12 @@ __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) { } } -__attribute__((noreturn)) void car_reboot(void) { - /* Reset the processor. */ - car_get_regs()->rst_dev_l |= 1<<2; - - while (true) { - /* Wait for reboot. */ - } -} - __attribute__((noreturn)) void wait_for_button_and_reboot(void) { uint32_t button; while (true) { button = btn_read(); if (button & BTN_POWER) { - car_reboot(); + pmc_reboot(1 << 1); } } } diff --git a/fusee/fusee-primary/src/utils.h b/fusee/fusee-primary/src/utils.h index 7fe8e6cb8..23893e930 100644 --- a/fusee/fusee-primary/src/utils.h +++ b/fusee/fusee-primary/src/utils.h @@ -121,7 +121,6 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase); __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); -__attribute__((noreturn)) void car_reboot(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void); __attribute__((noreturn)) void generic_panic(void); diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index b74e0163d..ed7636a89 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -58,21 +58,12 @@ __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) { } } -__attribute__((noreturn)) void car_reboot(void) { - /* Reset the processor. */ - car_get_regs()->rst_dev_l |= 1<<2; - - while (true) { - /* Wait for reboot. */ - } -} - __attribute__((noreturn)) void wait_for_button_and_reboot(void) { uint32_t button; while (true) { button = btn_read(); if (button & BTN_POWER) { - car_reboot(); + pmc_reboot(1 << 1); } } } diff --git a/fusee/fusee-secondary/src/utils.h b/fusee/fusee-secondary/src/utils.h index 3d84a563d..6b26428ce 100644 --- a/fusee/fusee-secondary/src/utils.h +++ b/fusee/fusee-secondary/src/utils.h @@ -122,7 +122,6 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase); __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); -__attribute__((noreturn)) void car_reboot(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void); void wait_for_button(void); From 6b3662d0477973b57e999e9f5af87be228eadde2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 13:23:53 -0800 Subject: [PATCH 268/489] Add documentation for supported flags. --- docs/flags.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 docs/flags.md diff --git a/docs/flags.md b/docs/flags.md new file mode 100644 index 000000000..74ba8cc81 --- /dev/null +++ b/docs/flags.md @@ -0,0 +1,12 @@ +# Flags +Atmosphère supports customizing CFW behavior based on the presence of `flags` on the SD card. + +The following flags are supported on a per-title basis, by placing `<flag_name>.flag` inside `/atmosphere/titles/<title_id>/flags/`: ++ `boot2`, which indicates to PM that the title should be launched during the `boot2` process. ++ `fsmitm`, which indicates that `fs.mitm` should override contents for the title even if it otherwise wouldn't. ++ `fsmitm_disable`, which indicates that `fs.mitm` should not override contents for the title, even it it otherwise would. ++ `bis_write`, which indicates that `fs.mitm` should allow the title to write to BIS partitions. ++ `cal_read`, which indicates that `fs.mitm` should allow the title to read the CAL0/PRODINFO partition. + +The following global flags are supported, by placing `<flag name>` inside `/atmosphere/flags/`: ++ `hbl_bis_write` and `hbl_cal_read` enable the BIS write and CAL0 read functionality for HBL, without needing to specify its title id. \ No newline at end of file From ed4a999caa3d9716be371bc012f7634f090af1e1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 13:24:39 -0800 Subject: [PATCH 269/489] fix flag docs typo --- docs/flags.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/flags.md b/docs/flags.md index 74ba8cc81..5ee403b28 100644 --- a/docs/flags.md +++ b/docs/flags.md @@ -8,5 +8,5 @@ The following flags are supported on a per-title basis, by placing `<flag_name>. + `bis_write`, which indicates that `fs.mitm` should allow the title to write to BIS partitions. + `cal_read`, which indicates that `fs.mitm` should allow the title to read the CAL0/PRODINFO partition. -The following global flags are supported, by placing `<flag name>` inside `/atmosphere/flags/`: +The following global flags are supported, by placing `<flag name>.flag` inside `/atmosphere/flags/`: + `hbl_bis_write` and `hbl_cal_read` enable the BIS write and CAL0 read functionality for HBL, without needing to specify its title id. \ No newline at end of file From ef17dc16faa16ec389edfd8957d0cdb73d005f1d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 30 Nov 2018 13:39:07 -0800 Subject: [PATCH 270/489] Bump version to 0.8.1 --- common/include/atmosphere/version.h | 2 +- docs/changelog.md | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index b629c78ce..a112d9352 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 8 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 1 #endif \ No newline at end of file diff --git a/docs/changelog.md b/docs/changelog.md index 65a66001f..f6d1c656d 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,25 @@ # Changelog +## 0.8.1 ++ A bug was fixed causing users to see `Failed to enable SMMU!` if fusee had previously rebooted. + + This message will still occur sporadically if fusee is not launched from coldboot, but it can never happen twice in a row. ++ A race condition was fixed in Atmosphere `bis_protect` functionality that could cause NS to be able to overwrite BCT public keys. + + This sometimes broke AutoRCM protection, the current fix has been tested on hardware and verified to work. ++ Support was added for enabling `debugmode` based on the `exosphere` section of `BCT.ini`: + + Setting `debugmode = 1` will cause exosphere to tell the kernel that debugmode is active. + + Setting `debugmode_user = 1` will cause exosphere to tell userland that debugmode is active. + + These are completely independent of one another, allowing fine control of system behavior. ++ Support was added for `nogc` functionality; thanks to @rajkosto for the patches. + + By default, `nogc` patches will automatically apply if the user is booting into 4.0.0+ with fuses from <= 3.0.2. + + Users can override this functionality via the `nogc` entry in the `stratosphere` section of `BCT.ini`: + + Setting `nogc = 1` will force enable `nogc` patches. + + Setting `nogc = 0` will force disable `nogc` patches. + + If patches are enabled but not found for the booting system, a fatal error will be thrown. + + This should prevent running FS without `nogc` patches after updating to an unsupported system version. ++ An extension was added to `exosphere` allowing userland applications to cause the system to reboot into RCM: + + This is done by calling smcSetConfig(id=65001, value=<nonzero>); user homebrew can use splSetConfig for this. ++ On fatal error, the user can now choose to perform a standard reboot via the power button, or a reboot into RCM via either volume button. ++ A custom message was added to `fatal` for when an Atmosphère API version mismatch is detected (2495-1623). ++ General system stability improvements to enhance the user's experience. ## 0.8.0 + A custom `fatal` system module was added. + This re-implements and extends Nintendo's fatal module, with the following features: @@ -27,6 +48,7 @@ + To facilitate this, `fs.mitm` now mitms all sessions for non-system modules; content overriding has been made separate from service interception. + Please note: these protections are basic, and sufficiently malicious homebrew ++can defeat them++. + Please be careful to only run homebrew software from sources that you trust. ++ A bug involving HDCP titles crashing on newer firmwares was fixed. + Support was added for system version 6.2.0; our thanks to @motezazer for his invaluable help. + By default, new keys will automatically be derived without user input. + Support is also present for loading new keys from `atmosphere/prod.keys` or `atmosphere/dev.keys` From 2708de387679556d092e0c7b1758f791658322e9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 3 Nov 2018 11:52:04 -0700 Subject: [PATCH 271/489] debug-kit: Implement tma.stub --- stratosphere/pm/source/pm_boot2.cpp | 5 +- stratosphere/tma/Makefile | 153 +++++++++++++++++++++++++++ stratosphere/tma/source/tma_main.cpp | 105 ++++++++++++++++++ stratosphere/tma/tma.json | 104 ++++++++++++++++++ 4 files changed, 365 insertions(+), 2 deletions(-) create mode 100644 stratosphere/tma/Makefile create mode 100644 stratosphere/tma/source/tma_main.cpp create mode 100644 stratosphere/tma/tma.json diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 864f2d9ff..16811b6ec 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -157,8 +157,9 @@ void EmbeddedBoot2::Main() { /* Launch usb. */ LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); - /* Launch tma. */ - LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_NandSystem, 0, NULL); + + /* Don't launch tma, because atmosphere replaces it with a KIP. */ + /* LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_NandSystem, 0, NULL); */ /* Launch default programs. */ bool maintenance = ShouldForceMaintenanceMode(); diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile new file mode 100644 index 000000000..6f361d647 --- /dev/null +++ b/stratosphere/tma/Makefile @@ -0,0 +1,153 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include ../../common/include +EXEFS_SRC := exefs_src + +DEFINES := -DDISABLE_IPC + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lstratosphere -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) $(CURDIR)/../libstratosphere + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) + +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).npdm $(TARGET).nso $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).kip + +$(OUTPUT).kip : $(OUTPUT).elf + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp new file mode 100644 index 000000000..a1b291e1d --- /dev/null +++ b/stratosphere/tma/source/tma_main.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <stratosphere.hpp> + +extern "C" { + extern u32 __start__; + + u32 __nx_applet_type = AppletType_None; + + #define INNER_HEAP_SIZE 0x20000 + size_t nx_inner_heap_size = INNER_HEAP_SIZE; + char nx_inner_heap[INNER_HEAP_SIZE]; + + void __libnx_initheap(void); + void __appInit(void); + void __appExit(void); +} + + +void __libnx_initheap(void) { + void* addr = nx_inner_heap; + size_t size = nx_inner_heap_size; + + /* Newlib */ + extern char* fake_heap_start; + extern char* fake_heap_end; + + fake_heap_start = (char*)addr; + fake_heap_end = (char*)addr + size; +} + +void __appInit(void) { + Result rc; + + rc = smInitialize(); + if (R_FAILED(rc)) { + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); + } + + rc = pscInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + CheckAtmosphereVersion(); +} + +void __appExit(void) { + /* Cleanup services. */ + pscExit(); + smExit(); +} + +int main(int argc, char **argv) +{ + consoleDebugInit(debugDevice_SVC); + + /* Setup psc module. */ + Result rc; + PscPmModule tma_module = {0}; + if (R_FAILED((rc = pscGetPmModule(&tma_module, 0x1E, nullptr, 0, true)))) { + fatalSimple(rc); + } + + /* For now, just do what dummy tma does -- loop forever, acknowledging everything. */ + while (true) { + if (R_FAILED((rc = eventWait(&tma_module.event, U64_MAX)))) { + fatalSimple(rc); + } + + PscPmState state; + u32 flags; + if (R_FAILED((rc = pscPmModuleGetRequest(&tma_module, &state, &flags)))) { + fatalSimple(rc); + } + + + if (R_FAILED((rc = pscPmModuleAcknowledge(&tma_module, state)))) { + fatalSimple(rc); + } + } + + return 0; +} + diff --git a/stratosphere/tma/tma.json b/stratosphere/tma/tma.json new file mode 100644 index 000000000..7cbfbf3fc --- /dev/null +++ b/stratosphere/tma/tma.json @@ -0,0 +1,104 @@ +{ + "name": "tma", + "title_id": "0x0100000000000007", + "main_thread_stack_size": "0x00004000", + "main_thread_priority": 38, + "default_cpu_id": 3, + "process_category": 1, + "kernel_capabilities": [ + { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0a", + "svcSleepThread": "0x0b", + "svcGetThreadPriority": "0x0c", + "svcSetThreadPriority": "0x0d", + "svcGetThreadCoreMask": "0x0e", + "svcSetThreadCoreMask": "0x0f", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1a", + "svcArbitrateUnlock": "0x1b", + "svcWaitProcessWideKeyAtomic": "0x1c", + "svcSignalProcessWideKey": "0x1d", + "svcGetSystemTick": "0x1e", + "svcConnectToNamedPort": "0x1f", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcCreateEvent": "0x45", + "svcReadWriteRegister": "0x4E", + "svcCreateSharedMemory": "0x50", + "svcMapTransferMemory": "0x51", + "svcUnmapTransferMemory": "0x52", + "svcCreateInterruptEvent": "0x53", + "svcQueryIoMapping": "0x55", + "svcCreateDeviceAddressSpace": "0x56", + "svcAttachDeviceAddressSpace": "0x57", + "svcDetachDeviceAddressSpace": "0x58", + "svcMapDeviceAddressSpaceByForce": "0x59", + "svcMapDeviceAddressSpaceAligned": "0x5a", + "svcMapDeviceAddressSpace": "0x5b", + "svcUnmapDeviceAddressSpace": "0x5c", + "svcInvalidateProcessDataCache": "0x5d", + "svcStoreProcessDataCache": "0x5e", + "svcFlushProcessDataCache": "0x5f" + } + }, { + "type": "map", + "value": { + "address": "0x02000000", + "is_ro": false, + "size": "0x05000000", + "is_io": true + } + }, { + "type": "map", + "value": { + "address": "0x10000000", + "is_ro": false, + "size": "0x04000000", + "is_io": true + } + }, { + "type": "irq_pair", + "value": [130, null] + }, { + "type": "irq_pair", + "value": [131, 132] + }, { + "type": "handle_table_size", + "value": 256 + }] +} \ No newline at end of file From ec8523af7cb00018d8104ffddae09214c1d7e62f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 23:19:11 -0800 Subject: [PATCH 272/489] tma: Implement USB packet rw. --- stratosphere/tma/Makefile | 2 +- stratosphere/tma/source/crc.h | 93 ++++ stratosphere/tma/source/tma_conn_packet.hpp | 262 ++++++++++ stratosphere/tma/source/tma_conn_result.hpp | 40 ++ .../tma/source/tma_conn_service_ids.hpp | 38 ++ stratosphere/tma/source/tma_main.cpp | 35 +- stratosphere/tma/source/tma_usb_comms.cpp | 460 ++++++++++++++++++ stratosphere/tma/source/tma_usb_comms.hpp | 35 ++ 8 files changed, 959 insertions(+), 6 deletions(-) create mode 100644 stratosphere/tma/source/crc.h create mode 100644 stratosphere/tma/source/tma_conn_packet.hpp create mode 100644 stratosphere/tma/source/tma_conn_result.hpp create mode 100644 stratosphere/tma/source/tma_conn_service_ids.hpp create mode 100644 stratosphere/tma/source/tma_usb_comms.cpp create mode 100644 stratosphere/tma/source/tma_usb_comms.hpp diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile index 6f361d647..7dc12f262 100644 --- a/stratosphere/tma/Makefile +++ b/stratosphere/tma/Makefile @@ -29,7 +29,7 @@ DEFINES := -DDISABLE_IPC #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE +ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE CFLAGS := -g -Wall -O2 -ffunction-sections \ $(ARCH) $(DEFINES) diff --git a/stratosphere/tma/source/crc.h b/stratosphere/tma/source/crc.h new file mode 100644 index 000000000..1fc37cffb --- /dev/null +++ b/stratosphere/tma/source/crc.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Code taken from Yazen Ghannam <yazen.ghannam@linaro.org>, licensed GPLv2. */ + +#define CRC32X(crc, value) __asm__("crc32x %w[c], %w[c], %x[v]":[c]"+r"(crc):[v]"r"(value)) +#define CRC32W(crc, value) __asm__("crc32w %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) +#define CRC32H(crc, value) __asm__("crc32h %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) +#define CRC32B(crc, value) __asm__("crc32b %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) +#define CRC32CX(crc, value) __asm__("crc32cx %w[c], %w[c], %x[v]":[c]"+r"(crc):[v]"r"(value)) +#define CRC32CW(crc, value) __asm__("crc32cw %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) +#define CRC32CH(crc, value) __asm__("crc32ch %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) +#define CRC32CB(crc, value) __asm__("crc32cb %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value)) + +static inline uint16_t __get_unaligned_le16(const uint8_t *p) +{ + return p[0] | p[1] << 8; +} + +static inline uint32_t __get_unaligned_le32(const uint8_t *p) +{ + return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; +} + +static inline uint64_t __get_unaligned_le64(const uint8_t *p) +{ + return (uint64_t)__get_unaligned_le32(p + 4) << 32 | + __get_unaligned_le32(p); +} + +static inline uint16_t get_unaligned_le16(const void *p) +{ + return __get_unaligned_le16((const uint8_t *)p); +} + +static inline uint32_t get_unaligned_le32(const void *p) +{ + return __get_unaligned_le32((const uint8_t *)p); +} + +static inline uint64_t get_unaligned_le64(const void *p) +{ + return __get_unaligned_le64((const uint8_t *)p); +} + + +static u32 crc32_arm64_le_hw(const u8 *p, unsigned int len) { + u32 crc = 0xFFFFFFFF; + + s64 length = len; + + while ((length -= sizeof(u64)) >= 0) { + CRC32X(crc, get_unaligned_le64(p)); + p += sizeof(u64); + } + + /* The following is more efficient than the straight loop */ + if (length & sizeof(u32)) { + CRC32W(crc, get_unaligned_le32(p)); + p += sizeof(u32); + } + if (length & sizeof(u16)) { + CRC32H(crc, get_unaligned_le16(p)); + p += sizeof(u16); + } + if (length & sizeof(u8)) + CRC32B(crc, *p); + + return crc ^ 0xFFFFFFFF; +} + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/stratosphere/tma/source/tma_conn_packet.hpp b/stratosphere/tma/source/tma_conn_packet.hpp new file mode 100644 index 000000000..03aaffc5a --- /dev/null +++ b/stratosphere/tma/source/tma_conn_packet.hpp @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <cstdarg> +#include "tma_conn_result.hpp" +#include "tma_conn_service_ids.hpp" +#include "crc.h" + +class TmaPacket { + public: + struct Header { + u32 service_id; + u32 task_id; + u16 command; + u8 is_continuation; + u8 version; + u32 body_len; + u32 reserved[4]; /* This is where N's header ends. */ + u32 body_checksum; + u32 header_checksum; + }; + + static_assert(sizeof(Header) == 0x28, "Packet::Header definition!"); + + static constexpr u32 MaxBodySize = 0xE000; + static constexpr u32 MaxPacketSize = MaxBodySize + sizeof(Header); + + private: + std::unique_ptr<u8[]> buffer = std::make_unique<u8[]>(MaxPacketSize); + u32 offset = 0; + + Header *GetHeader() const { + return reinterpret_cast<Header *>(buffer.get()); + } + + u8 *GetBody(u32 ofs) const { + return reinterpret_cast<u8 *>(buffer.get() + sizeof(Header) + ofs); + } + public: + TmaPacket() { + memset(buffer.get(), 0, MaxPacketSize); + } + + /* Implicit ~TmaPacket() */ + + /* These allow reading a packet in. */ + void CopyHeaderFrom(Header *hdr) { + *GetHeader() = *hdr; + } + + TmaConnResult CopyBodyFrom(void *body, size_t size) { + if (size >= MaxBodySize) { + return TmaConnResult::PacketOverflow; + } + + memcpy(GetBody(0), body, size); + + return TmaConnResult::Success; + } + + void CopyHeaderTo(void *out) { + memcpy(out, buffer.get(), sizeof(Header)); + } + + void CopyBodyTo(void *out) const { + memcpy(out, buffer.get() + sizeof(Header), GetBodyLength()); + } + + bool IsHeaderValid() { + Header *hdr = GetHeader(); + return crc32_arm64_le_hw(reinterpret_cast<const u8 *>(hdr), sizeof(*hdr) - sizeof(hdr->header_checksum)) == hdr->header_checksum; + } + + bool IsBodyValid() const { + const u32 body_len = GetHeader()->body_len; + if (body_len == 0) { + return GetHeader()->body_checksum == 0; + } else { + return crc32_arm64_le_hw(GetBody(0), body_len) == GetHeader()->body_checksum; + } + } + + void SetChecksums() { + Header *hdr = GetHeader(); + if (hdr->body_len) { + hdr->body_checksum = crc32_arm64_le_hw(GetBody(0), hdr->body_len); + } else { + hdr->body_checksum = 0; + } + hdr->header_checksum = crc32_arm64_le_hw(reinterpret_cast<const u8 *>(hdr), sizeof(*hdr) - sizeof(hdr->header_checksum)); + } + + u32 GetBodyLength() const { + return GetHeader()->body_len; + } + + u32 GetLength() const { + return GetBodyLength() + sizeof(Header); + } + + u32 GetBodyAvailableLength() const { + return MaxPacketSize - this->offset; + } + + void SetServiceId(TmaService srv) { + GetHeader()->service_id = static_cast<u32>(srv); + } + + TmaService GetServiceId() const { + return static_cast<TmaService>(GetHeader()->service_id); + } + + void SetTaskId(u32 id) { + GetHeader()->task_id = id; + } + + u32 GetTaskId() const { + return GetHeader()->task_id; + } + + void SetCommand(u16 cmd) { + GetHeader()->command = cmd; + } + + u16 GetCommand() const { + return GetHeader()->command; + } + + void SetContinuation(bool c) { + GetHeader()->is_continuation = c ? 1 : 0; + } + + bool GetContinuation() const { + return GetHeader()->is_continuation == 1; + } + + void SetVersion(u8 v) { + GetHeader()->version = v; + } + + u8 GetVersion() const { + return GetHeader()->version; + } + + void ClearOffset() { + this->offset = 0; + } + + TmaConnResult Write(const void *data, size_t size) { + if (size > GetBodyAvailableLength()) { + return TmaConnResult::PacketOverflow; + } + + memcpy(GetBody(this->offset), data, size); + this->offset += size; + GetHeader()->body_len = this->offset; + + return TmaConnResult::Success; + } + + TmaConnResult Read(void *data, size_t size) { + if (size > GetBodyAvailableLength()) { + return TmaConnResult::PacketOverflow; + } + + memcpy(data, GetBody(this->offset), size); + this->offset += size; + + return TmaConnResult::Success; + } + + template<typename T> + TmaConnResult Write(const T &t) { + return Write(&t, sizeof(T)); + } + + template<typename T> + TmaConnResult Read(const T &t) { + return Read(&t, sizeof(T)); + } + + TmaConnResult WriteString(const char *s) { + return Write(s, strlen(s) + 1); + } + + size_t WriteFormat(const char *format, ...) { + va_list va_arg; + va_start(va_arg, format); + const size_t available = GetBodyAvailableLength(); + const int written = vsnprintf(reinterpret_cast<char *>(GetBody(this->offset)), available, format, va_arg); + + size_t total_written; + if (static_cast<size_t>(written) < available) { + this->offset += written; + *GetBody(this->offset++) = 0; + total_written = written + 1; + } else { + this->offset += available; + total_written = available; + } + + GetHeader()->body_len = this->offset; + return total_written; + } + + TmaConnResult ReadString(char *buf, size_t buf_size, size_t *out_size) { + TmaConnResult res = TmaConnResult::Success; + + size_t available = GetBodyAvailableLength(); + size_t ofs = 0; + while (ofs < buf_size) { + if (ofs >= available) { + res = TmaConnResult::PacketOverflow; + break; + } + if (ofs == buf_size) { + res = TmaConnResult::BufferOverflow; + break; + } + + buf[ofs] = static_cast<char>(*GetBody(this->offset++)); + + if (buf[ofs++] == '\x00') { + break; + } + } + + /* Finish reading the string if the user buffer is too small. */ + if (res == TmaConnResult::BufferOverflow) { + u8 cur = *GetBody(this->offset); + while (cur != 0) { + if (ofs >= available) { + res = TmaConnResult::PacketOverflow; + break; + } + cur = *GetBody(this->offset++); + ofs++; + } + } + + if (out_size != nullptr) { + *out_size = ofs; + } + + return res; + } +}; diff --git a/stratosphere/tma/source/tma_conn_result.hpp b/stratosphere/tma/source/tma_conn_result.hpp new file mode 100644 index 000000000..7d91923af --- /dev/null +++ b/stratosphere/tma/source/tma_conn_result.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> +#include <switch.h> +#include <stratosphere.hpp> + +enum class TmaConnResult : u32 { + Success = 0, + NotImplemented, + GeneralFailure, + ConnectionFailure, + AlreadyConnected, + WrongConnectionVersion, + PacketOverflow, + BufferOverflow, + Disconnected, + ServiceAlreadyRegistered, + ServiceUnknown, + Timeout, + NotInitialized, +}; diff --git a/stratosphere/tma/source/tma_conn_service_ids.hpp b/stratosphere/tma/source/tma_conn_service_ids.hpp new file mode 100644 index 000000000..7dc8ee331 --- /dev/null +++ b/stratosphere/tma/source/tma_conn_service_ids.hpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "tma_conn_result.hpp" + +/* This is just python's hash function, but official TMA code uses it. */ +static constexpr u32 HashServiceName(const char *name) { + u32 h = *name; + u32 len = 0; + + while (*name) { + h = (1000003 * h) ^ *name; + name++; + len++; + } + + return h ^ len; +} + +enum class TmaService : u32 { + Invalid = 0, + TestService = HashServiceName("AtmosphereTestService"), /* Temporary service, will be used to debug communications. */ +}; diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp index a1b291e1d..e4c23777b 100644 --- a/stratosphere/tma/source/tma_main.cpp +++ b/stratosphere/tma/source/tma_main.cpp @@ -22,12 +22,14 @@ #include <switch.h> #include <stratosphere.hpp> +#include "tma_usb_comms.hpp" + extern "C" { extern u32 __start__; u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x20000 + #define INNER_HEAP_SIZE 0x100000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -71,10 +73,7 @@ void __appExit(void) { smExit(); } -int main(int argc, char **argv) -{ - consoleDebugInit(debugDevice_SVC); - +void PmThread(void *arg) { /* Setup psc module. */ Result rc; PscPmModule tma_module = {0}; @@ -99,6 +98,32 @@ int main(int argc, char **argv) fatalSimple(rc); } } +} + +int main(int argc, char **argv) +{ + consoleDebugInit(debugDevice_SVC); + Thread pm_thread = {0}; + if (R_FAILED(threadCreate(&pm_thread, &PmThread, NULL, 0x4000, 0x15, 0))) { + /* TODO: Panic. */ + } + if (R_FAILED(threadStart(&pm_thread))) { + /* TODO: Panic. */ + } + + TmaUsbComms::Initialize(); + TmaPacket *packet = new TmaPacket(); + usbDsWaitReady(U64_MAX); + packet->Write<u64>(0xCAFEBABEDEADCAFEUL); + packet->Write<u64>(0xCCCCCCCCCCCCCCCCUL); + TmaUsbComms::SendPacket(packet); + packet->ClearOffset(); + while (true) { + if (TmaUsbComms::ReceivePacket(packet) == TmaConnResult::Success) { + TmaUsbComms::SendPacket(packet); + } + } + return 0; } diff --git a/stratosphere/tma/source/tma_usb_comms.cpp b/stratosphere/tma/source/tma_usb_comms.cpp new file mode 100644 index 000000000..440218bef --- /dev/null +++ b/stratosphere/tma/source/tma_usb_comms.cpp @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "tma_usb_comms.hpp" + +/* TODO: Is this actually allowed? */ +#define ATMOSPHERE_INTERFACE_PROTOCOL 0xFC + +static std::atomic<bool> g_initialized = false; +static UsbDsInterface *g_interface; +static UsbDsEndpoint *g_endpoint_in, *g_endpoint_out; + +/* USB State Change Tracking. */ +static HosThread g_state_change_thread; +static WaitableManagerBase *g_state_change_manager = nullptr; +static void (*g_state_change_callback)(void *arg, u32 state); +static void *g_state_change_arg; + +/* USB Send/Receive mutexes. */ +static HosMutex g_send_mutex; +static HosMutex g_recv_mutex; + +/* Static arrays to do USB DMA into. */ +static constexpr size_t DmaBufferAlign = 0x1000; +static constexpr size_t HeaderBufferSize = DmaBufferAlign; +static constexpr size_t DataBufferSize = 0x18000; +static __attribute__((aligned(DmaBufferAlign))) u8 g_header_buffer[HeaderBufferSize]; +static __attribute__((aligned(DmaBufferAlign))) u8 g_recv_data_buf[DataBufferSize]; +static __attribute__((aligned(DmaBufferAlign))) u8 g_send_data_buf[DataBufferSize]; + +/* Taken from libnx usb comms. */ +static Result _usbCommsInterfaceInit1x() +{ + Result rc = 0; + + struct usb_interface_descriptor interface_descriptor = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 4, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceProtocol = ATMOSPHERE_INTERFACE_PROTOCOL, + }; + + struct usb_endpoint_descriptor endpoint_descriptor_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_ENDPOINT_IN, + .bmAttributes = USB_TRANSFER_TYPE_BULK, + .wMaxPacketSize = 0x200, + }; + + struct usb_endpoint_descriptor endpoint_descriptor_out = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_ENDPOINT_OUT, + .bmAttributes = USB_TRANSFER_TYPE_BULK, + .wMaxPacketSize = 0x200, + }; + + if (R_FAILED(rc)) return rc; + + //Setup interface. + rc = usbDsGetDsInterface(&g_interface, &interface_descriptor, "usb"); + if (R_FAILED(rc)) return rc; + + //Setup endpoints. + rc = usbDsInterface_GetDsEndpoint(g_interface, &g_endpoint_in, &endpoint_descriptor_in);//device->host + if (R_FAILED(rc)) return rc; + + rc = usbDsInterface_GetDsEndpoint(g_interface, &g_endpoint_out, &endpoint_descriptor_out);//host->device + if (R_FAILED(rc)) return rc; + + return rc; +} + +static Result _usbCommsInterfaceInit5x() { + Result rc = 0; + + u8 iManufacturer, iProduct, iSerialNumber; + static const u16 supported_langs[1] = {0x0409}; + // Send language descriptor + rc = usbDsAddUsbLanguageStringDescriptor(NULL, supported_langs, sizeof(supported_langs)/sizeof(u16)); + // Send manufacturer + if (R_SUCCEEDED(rc)) rc = usbDsAddUsbStringDescriptor(&iManufacturer, "Nintendo"); + // Send product + if (R_SUCCEEDED(rc)) rc = usbDsAddUsbStringDescriptor(&iProduct, "Nintendo Switch"); + // Send serial number + if (R_SUCCEEDED(rc)) rc = usbDsAddUsbStringDescriptor(&iSerialNumber, "SerialNumber"); + + // Send device descriptors + struct usb_device_descriptor device_descriptor = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0110, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = 0x40, + .idVendor = 0x057e, + .idProduct = 0x3000, + .bcdDevice = 0x0100, + .iManufacturer = iManufacturer, + .iProduct = iProduct, + .iSerialNumber = iSerialNumber, + .bNumConfigurations = 0x01 + }; + // Full Speed is USB 1.1 + if (R_SUCCEEDED(rc)) rc = usbDsSetUsbDeviceDescriptor(UsbDeviceSpeed_Full, &device_descriptor); + + // High Speed is USB 2.0 + device_descriptor.bcdUSB = 0x0200; + if (R_SUCCEEDED(rc)) rc = usbDsSetUsbDeviceDescriptor(UsbDeviceSpeed_High, &device_descriptor); + + // Super Speed is USB 3.0 + device_descriptor.bcdUSB = 0x0300; + // Upgrade packet size to 512 + device_descriptor.bMaxPacketSize0 = 0x09; + if (R_SUCCEEDED(rc)) rc = usbDsSetUsbDeviceDescriptor(UsbDeviceSpeed_Super, &device_descriptor); + + // Define Binary Object Store + u8 bos[0x16] = { + 0x05, // .bLength + USB_DT_BOS, // .bDescriptorType + 0x16, 0x00, // .wTotalLength + 0x02, // .bNumDeviceCaps + + // USB 2.0 + 0x07, // .bLength + USB_DT_DEVICE_CAPABILITY, // .bDescriptorType + 0x02, // .bDevCapabilityType + 0x02, 0x00, 0x00, 0x00, // dev_capability_data + + // USB 3.0 + 0x0A, // .bLength + USB_DT_DEVICE_CAPABILITY, // .bDescriptorType + 0x03, // .bDevCapabilityType + 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00 + }; + if (R_SUCCEEDED(rc)) rc = usbDsSetBinaryObjectStore(bos, sizeof(bos)); + + if (R_FAILED(rc)) return rc; + + struct usb_interface_descriptor interface_descriptor = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 4, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceProtocol = ATMOSPHERE_INTERFACE_PROTOCOL, + }; + + struct usb_endpoint_descriptor endpoint_descriptor_in = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_ENDPOINT_IN, + .bmAttributes = USB_TRANSFER_TYPE_BULK, + .wMaxPacketSize = 0x40, + }; + + struct usb_endpoint_descriptor endpoint_descriptor_out = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_ENDPOINT_OUT, + .bmAttributes = USB_TRANSFER_TYPE_BULK, + .wMaxPacketSize = 0x40, + }; + + struct usb_ss_endpoint_companion_descriptor endpoint_companion = { + .bLength = sizeof(struct usb_ss_endpoint_companion_descriptor), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMPANION, + .bMaxBurst = 0x0F, + .bmAttributes = 0x00, + .wBytesPerInterval = 0x00, + }; + + rc = usbDsRegisterInterface(&g_interface); + if (R_FAILED(rc)) return rc; + + interface_descriptor.bInterfaceNumber = g_interface->interface_index; + endpoint_descriptor_in.bEndpointAddress += interface_descriptor.bInterfaceNumber + 1; + endpoint_descriptor_out.bEndpointAddress += interface_descriptor.bInterfaceNumber + 1; + + // Full Speed Config + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_Full, &interface_descriptor, USB_DT_INTERFACE_SIZE); + if (R_FAILED(rc)) return rc; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_Full, &endpoint_descriptor_in, USB_DT_ENDPOINT_SIZE); + if (R_FAILED(rc)) return rc; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_Full, &endpoint_descriptor_out, USB_DT_ENDPOINT_SIZE); + if (R_FAILED(rc)) return rc; + + // High Speed Config + endpoint_descriptor_in.wMaxPacketSize = 0x200; + endpoint_descriptor_out.wMaxPacketSize = 0x200; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_High, &interface_descriptor, USB_DT_INTERFACE_SIZE); + if (R_FAILED(rc)) return rc; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_High, &endpoint_descriptor_in, USB_DT_ENDPOINT_SIZE); + if (R_FAILED(rc)) return rc; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_High, &endpoint_descriptor_out, USB_DT_ENDPOINT_SIZE); + if (R_FAILED(rc)) return rc; + + // Super Speed Config + endpoint_descriptor_in.wMaxPacketSize = 0x400; + endpoint_descriptor_out.wMaxPacketSize = 0x400; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_Super, &interface_descriptor, USB_DT_INTERFACE_SIZE); + if (R_FAILED(rc)) return rc; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_Super, &endpoint_descriptor_in, USB_DT_ENDPOINT_SIZE); + if (R_FAILED(rc)) return rc; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_Super, &endpoint_companion, USB_DT_SS_ENDPOINT_COMPANION_SIZE); + if (R_FAILED(rc)) return rc; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_Super, &endpoint_descriptor_out, USB_DT_ENDPOINT_SIZE); + if (R_FAILED(rc)) return rc; + rc = usbDsInterface_AppendConfigurationData(g_interface, UsbDeviceSpeed_Super, &endpoint_companion, USB_DT_SS_ENDPOINT_COMPANION_SIZE); + if (R_FAILED(rc)) return rc; + + //Setup endpoints. + rc = usbDsInterface_RegisterEndpoint(g_interface, &g_endpoint_in, endpoint_descriptor_in.bEndpointAddress); + if (R_FAILED(rc)) return rc; + + rc = usbDsInterface_RegisterEndpoint(g_interface, &g_endpoint_out, endpoint_descriptor_out.bEndpointAddress); + if (R_FAILED(rc)) return rc; + + return rc; +} + + +/* Actual function implementations. */ +TmaConnResult TmaUsbComms::Initialize() { + TmaConnResult res = TmaConnResult::Success; + + if (g_initialized) { + std::abort(); + } + + Result rc = usbDsInitialize(); + + /* Perform interface setup. */ + if (R_SUCCEEDED(rc)) { + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) { + rc = _usbCommsInterfaceInit5x(); + } else { + rc = _usbCommsInterfaceInit1x(); + } + } + + /* Start the state change thread. */ + /*if (R_SUCCEEDED(rc)) { + rc = g_state_change_thread.Initialize(&TmaUsbComms::UsbStateChangeThreadFunc, nullptr, 0x4000, 38); + if (R_SUCCEEDED(rc)) { + rc = g_state_change_thread.Start(); + } + }*/ + + /* Enable USB communication. */ + if (R_SUCCEEDED(rc)) { + rc = usbDsInterface_EnableInterface(g_interface); + } + if (R_SUCCEEDED(rc) && GetRuntimeFirmwareVersion() >= FirmwareVersion_500) { + rc = usbDsEnable(); + } + + + if (R_FAILED(rc)) { + /* TODO: Should I not abort here? */ + std::abort(); + + // /* Cleanup, just in case. */ + // TmaUsbComms::Finalize(); + // res = TmaConnResult::Failure; + } + + g_initialized = true; + + return res; +} + +TmaConnResult TmaUsbComms::Finalize() { + Result rc = 0; + /* We must have initialized before calling finalize. */ + if (!g_initialized) { + std::abort(); + } + + /* Kill the state change thread. */ + g_state_change_manager->RequestStop(); + if (R_FAILED(g_state_change_thread.Join())) { + std::abort(); + } + + CancelComms(); + if (R_SUCCEEDED(rc)) { + usbDsExit(); + } + + g_initialized = false; + + return R_SUCCEEDED(rc) ? TmaConnResult::Success : TmaConnResult::ConnectionFailure; +} + +void TmaUsbComms::CancelComms() { + if (!g_initialized) { + return; + } + + usbDsEndpoint_Cancel(g_endpoint_in); + usbDsEndpoint_Cancel(g_endpoint_out); +} + +void TmaUsbComms::SetStateChangeCallback(void (*callback)(void *, u32), void *arg) { + g_state_change_callback = callback; + g_state_change_arg = arg; +} + +Result TmaUsbComms::UsbXfer(UsbDsEndpoint *ep, size_t *out_xferd, void *buf, size_t size) { + Result rc = 0; + u32 urbId = 0; + u32 total_xferd = 0; + UsbDsReportData reportdata; + + if (size) { + /* Start transfer. */ + rc = usbDsEndpoint_PostBufferAsync(ep, buf, size, &urbId); + if (R_FAILED(rc)) return rc; + + /* Wait for transfer to complete. */ + eventWait(&ep->CompletionEvent, U64_MAX); + eventClear(&ep->CompletionEvent); + + rc = usbDsEndpoint_GetReportData(ep, &reportdata); + if (R_FAILED(rc)) return rc; + + rc = usbDsParseReportData(&reportdata, urbId, NULL, &total_xferd); + if (R_FAILED(rc)) return rc; + } + + if (out_xferd) *out_xferd = total_xferd; + + return rc; +} + +TmaConnResult TmaUsbComms::ReceivePacket(TmaPacket *packet) { + std::scoped_lock<HosMutex> lk{g_recv_mutex}; + TmaConnResult res = TmaConnResult::Success; + + if (!g_initialized || packet == nullptr) { + return TmaConnResult::GeneralFailure; + } + + /* Read the header. */ + size_t read = 0; + if (R_SUCCEEDED(UsbXfer(g_endpoint_out, &read, g_header_buffer, sizeof(TmaPacket::Header)))) { + packet->CopyHeaderFrom(reinterpret_cast<TmaPacket::Header *>(g_header_buffer)); + } else { + res = TmaConnResult::GeneralFailure; + } + + /* Validate the read header data. */ + if (res == TmaConnResult::Success) { + if (read != sizeof(TmaPacket::Header) || !packet->IsHeaderValid()) { + res = TmaConnResult::GeneralFailure; + } + } + + /* Read the body! */ + if (res == TmaConnResult::Success) { + const u32 body_len = packet->GetBodyLength(); + if (0 < body_len) { + if (body_len <= sizeof(g_recv_data_buf)) { + if (R_SUCCEEDED(UsbXfer(g_endpoint_out, &read, g_recv_data_buf, body_len))) { + if (read == body_len) { + res = packet->CopyBodyFrom(g_recv_data_buf, body_len); + } else { + res = TmaConnResult::GeneralFailure; + } + } + } else { + res = TmaConnResult::GeneralFailure; + } + } + } + + /* Validate the body. */ + if (res == TmaConnResult::Success) { + if (!packet->IsBodyValid()) { + res = TmaConnResult::GeneralFailure; + } + } + + if (res == TmaConnResult::Success) { + packet->ClearOffset(); + } + + return res; +} + +TmaConnResult TmaUsbComms::SendPacket(TmaPacket *packet) { + std::scoped_lock<HosMutex> lk{g_send_mutex}; + TmaConnResult res = TmaConnResult::Success; + + if (!g_initialized || packet == nullptr) { + return TmaConnResult::GeneralFailure; + } + + /* Ensure our packets have the correct checksums. */ + packet->SetChecksums(); + + /* Send the packet. */ + size_t written = 0; + const u32 body_len = packet->GetBodyLength(); + if (body_len <= sizeof(g_send_data_buf)) { + /* Copy header to send buffer. */ + packet->CopyHeaderTo(g_send_data_buf); + + /* Send the packet header. */ + if (R_SUCCEEDED(UsbXfer(g_endpoint_in, &written, g_send_data_buf, sizeof(TmaPacket::Header)))) { + if (written == sizeof(TmaPacket::Header)) { + res = TmaConnResult::Success; + } else { + res = TmaConnResult::GeneralFailure; + } + } else { + res = TmaConnResult::GeneralFailure; + } + + if (res == TmaConnResult::Success) { + /* Copy body to send buffer. */ + packet->CopyBodyTo(g_send_data_buf); + + + /* Send the packet body. */ + if (R_SUCCEEDED(UsbXfer(g_endpoint_in, &written, g_send_data_buf, body_len))) { + if (written == body_len) { + res = TmaConnResult::Success; + } else { + res = TmaConnResult::GeneralFailure; + } + } else { + res = TmaConnResult::GeneralFailure; + } + } + } else { + res = TmaConnResult::GeneralFailure; + } + + return res; +} diff --git a/stratosphere/tma/source/tma_usb_comms.hpp b/stratosphere/tma/source/tma_usb_comms.hpp new file mode 100644 index 000000000..9815e7634 --- /dev/null +++ b/stratosphere/tma/source/tma_usb_comms.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> + +#include "tma_conn_result.hpp" +#include "tma_conn_packet.hpp" + +class TmaUsbComms { + private: + static void UsbStateChangeThreadFunc(void *arg); + static Result UsbXfer(UsbDsEndpoint *ep, size_t *out_xferd, void *buf, size_t size); + public: + static TmaConnResult Initialize(); + static TmaConnResult Finalize(); + static void CancelComms(); + static TmaConnResult ReceivePacket(TmaPacket *packet); + static TmaConnResult SendPacket(TmaPacket *packet); + + static void SetStateChangeCallback(void (*callback)(void *, u32), void *arg); +}; \ No newline at end of file From 46001263f890d0dc2efa6d421670e4c5a312b0e0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 7 Nov 2018 23:21:05 -0800 Subject: [PATCH 273/489] tma: impl helper services, cleanup hostside packets --- .gitignore | 3 + stratosphere/tma/client/Main.py | 26 +++ stratosphere/tma/client/UsbConnection.py | 117 +++++++++++++ stratosphere/tma/client/UsbInterface.py | 69 ++++++++ .../tma/source/tma_conn_connection.cpp | 64 ++++++++ .../tma/source/tma_conn_connection.hpp | 80 +++++++++ .../tma/source/tma_conn_usb_connection.cpp | 155 ++++++++++++++++++ .../tma/source/tma_conn_usb_connection.hpp | 51 ++++++ stratosphere/tma/source/tma_main.cpp | 19 +-- stratosphere/tma/source/tma_usb_comms.cpp | 36 +++- stratosphere/tma/source/tma_usb_comms.hpp | 1 + 11 files changed, 603 insertions(+), 18 deletions(-) create mode 100644 stratosphere/tma/client/Main.py create mode 100644 stratosphere/tma/client/UsbConnection.py create mode 100644 stratosphere/tma/client/UsbInterface.py create mode 100644 stratosphere/tma/source/tma_conn_connection.cpp create mode 100644 stratosphere/tma/source/tma_conn_connection.hpp create mode 100644 stratosphere/tma/source/tma_conn_usb_connection.cpp create mode 100644 stratosphere/tma/source/tma_conn_usb_connection.hpp diff --git a/.gitignore b/.gitignore index f55c55a62..a89a9ec84 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,9 @@ dkms.conf *.tgz *.zip +# Python modules +*.pyc + .**/ # NOTE: make sure to make exceptions to this pattern when needed! diff --git a/stratosphere/tma/client/Main.py b/stratosphere/tma/client/Main.py new file mode 100644 index 000000000..580e0ae52 --- /dev/null +++ b/stratosphere/tma/client/Main.py @@ -0,0 +1,26 @@ +# Copyright (c) 2018 Atmosphere-NX +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +from UsbConnection import UsbConnection +import sys, time + +def main(argc, argv): + with UsbConnection(None) as c: + print 'Waiting for connection...' + c.wait_connected() + print 'Connected!' + while True: + c.send_packet('AAAAAAAA') + return 0 + +if __name__ == '__main__': + sys.exit(main(len(sys.argv), sys.argv)) \ No newline at end of file diff --git a/stratosphere/tma/client/UsbConnection.py b/stratosphere/tma/client/UsbConnection.py new file mode 100644 index 000000000..0f7d2cf8f --- /dev/null +++ b/stratosphere/tma/client/UsbConnection.py @@ -0,0 +1,117 @@ +# Copyright (c) 2018 Atmosphere-NX +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +from UsbInterface import UsbInterface +from threading import Thread, Condition +from collections import deque +import time + +class UsbConnection(UsbInterface): + # Auto connect thread func. + def auto_connect(connection): + while not connection.is_connected(): + try: + connection.connect(UsbInterface()) + except ValueError as e: + continue + def recv_thread(connection): + if connection.is_connected(): + try: + # If we've previously been connected, PyUSB will read garbage... + connection.recv_packet() + except ValueError: + pass + while connection.is_connected(): + try: + connection.recv_packet() + except Exception as e: + print 'An exception occurred:' + print 'Type: '+e.__class__.__name__ + print 'Msg: '+str(e) + connection.disconnect() + connection.send_packet(None) + def send_thread(connection): + while connection.is_connected(): + try: + next_packet = connection.get_next_send_packet() + if next_packet is not None: + connection.intf.send_packet(next_packet) + else: + connection.disconnect() + except Exception as e: + print 'An exception occurred:' + print 'Type: '+e.__class__.__name__ + print 'Msg: '+str(e) + connection.disconnect() + def __init__(self, manager): + self.manager = manager + self.connected = False + self.intf = None + self.conn_lock, self.send_lock = Condition(), Condition() + self.send_queue = deque() + def __enter__(self): + self.conn_thrd = Thread(target=UsbConnection.auto_connect, args=(self,)) + self.conn_thrd.daemon = True + self.conn_thrd.start() + return self + def __exit__(self, type, value, traceback): + time.sleep(1) + print 'Closing!' + time.sleep(1) + def wait_connected(self): + self.conn_lock.acquire() + if not self.is_connected(): + self.conn_lock.wait() + self.conn_lock.release() + def is_connected(self): + return self.connected + def connect(self, intf): + # This indicates we have a connection. + self.conn_lock.acquire() + assert not self.connected + self.intf = intf + self.connected = True + self.conn_lock.notify() + self.conn_lock.release() + self.recv_thrd = Thread(target=UsbConnection.recv_thread, args=(self,)) + self.send_thrd = Thread(target=UsbConnection.send_thread, args=(self,)) + self.recv_thrd.daemon = True + self.send_thrd.daemon = True + self.recv_thrd.start() + self.send_thrd.start() + def disconnect(self): + self.conn_lock.acquire() + if self.connected: + self.connected = False + self.conn_lock.release() + def recv_packet(self): + hdr, body = self.intf.read_packet() + print('Got Packet: %s' % body.encode('hex')) + def send_packet(self, packet): + self.send_lock.acquire() + if len(self.send_queue) == 0x40: + self.send_lock.wait() + self.send_queue.append(packet) + if len(self.send_queue) == 1: + self.send_lock.notify() + self.send_lock.release() + def get_next_send_packet(self): + self.send_lock.acquire() + if len(self.send_queue) == 0: + self.send_lock.wait() + packet = self.send_queue.popleft() + if len(self.send_queue) == 0x3F: + self.send_lock.notify() + self.send_lock.release() + return packet + diff --git a/stratosphere/tma/client/UsbInterface.py b/stratosphere/tma/client/UsbInterface.py new file mode 100644 index 000000000..90d91cab9 --- /dev/null +++ b/stratosphere/tma/client/UsbInterface.py @@ -0,0 +1,69 @@ +# Copyright (c) 2018 Atmosphere-NX +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import usb, zlib +from struct import unpack as up, pack as pk + +def crc32(s): + return zlib.crc32(s) & 0xFFFFFFFF + +class UsbInterface(): + def __init__(self): + self.dev = usb.core.find(idVendor=0x057e, idProduct=0x3000) + if self.dev is None: + raise ValueError('Device not found') + + self.dev.set_configuration() + self.cfg = self.dev.get_active_configuration() + self.intf = usb.util.find_descriptor(self.cfg, bInterfaceClass=0xff, bInterfaceSubClass=0xff, bInterfaceProtocol=0xfc) + assert self.intf is not None + + self.ep_in = usb.util.find_descriptor( + self.intf, + custom_match = \ + lambda e: \ + usb.util.endpoint_direction(e.bEndpointAddress) == \ + usb.util.ENDPOINT_IN) + assert self.ep_in is not None + + self.ep_out = usb.util.find_descriptor( + self.intf, + custom_match = \ + lambda e: \ + usb.util.endpoint_direction(e.bEndpointAddress) == \ + usb.util.ENDPOINT_OUT) + assert self.ep_out is not None + def close(self): + usb.util.dispose_resources(self.dev) + def blocking_read(self, size): + return ''.join(chr(x) for x in self.ep_in.read(size, 0xFFFFFFFFFFFFFFFF)) + def blocking_write(self, data): + self.ep_out.write(data, 0xFFFFFFFFFFFFFFFF) + def read_packet(self): + hdr = self.blocking_read(0x28) + _, _, _, body_size, _, _, _, _, body_chk, hdr_chk = up('<IIIIIIIIII', hdr) + if crc32(hdr[:-4]) != hdr_chk: + raise ValueError('Invalid header checksum in received packet!') + body = self.blocking_read(body_size) + if len(body) != body_size: + raise ValueError('Failed to receive packet body!') + elif crc32(body) != body_chk: + raise ValueError('Invalid body checksum in received packet!') + return (hdr, body) + def send_packet(self, body): + hdr = pk('<IIIIIIIII', 0, 0, 0, len(body), 0, 0, 0, 0, crc32(body)) + hdr += pk('<I', crc32(hdr)) + self.blocking_write(hdr) + self.blocking_write(body) + + diff --git a/stratosphere/tma/source/tma_conn_connection.cpp b/stratosphere/tma/source/tma_conn_connection.cpp new file mode 100644 index 000000000..23337b2b2 --- /dev/null +++ b/stratosphere/tma/source/tma_conn_connection.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include "tma_conn_connection.hpp" + +/* Packet management. */ +TmaPacket *TmaConnection::AllocateSendPacket() { + /* TODO: Service Manager. */ + return new TmaPacket(); +} + +TmaPacket *TmaConnection::AllocateRecvPacket() { + /* TODO: Service Manager. */ + return new TmaPacket(); +} + +void TmaConnection::FreePacket(TmaPacket *packet) { + /* TODO: Service Manager. */ + delete packet; +} + +void TmaConnection::OnReceivePacket(TmaPacket *packet) { + /* TODO: Service Manager. */ +} + +void TmaConnection::OnDisconnected() { + if (!this->is_initialized) { + std::abort(); + } + + /* TODO: Service Manager. */ + + this->has_woken_up = false; + this->OnConnectionEvent(ConnectionEvent::Disconnected); +} + +void TmaConnection::OnConnectionEvent(ConnectionEvent event) { + if (this->connection_event_callback != nullptr) { + this->connection_event_callback(this->connection_event_arg, event); + } +} + +void TmaConnection::CancelTasks() { + /* TODO: Service Manager. */ +} + +void TmaConnection::Tick() { + /* TODO: Service Manager. */ +} diff --git a/stratosphere/tma/source/tma_conn_connection.hpp b/stratosphere/tma/source/tma_conn_connection.hpp new file mode 100644 index 000000000..4cf3cabe3 --- /dev/null +++ b/stratosphere/tma/source/tma_conn_connection.hpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "tma_conn_result.hpp" +#include "tma_conn_packet.hpp" + +enum class ConnectionEvent : u32 { + Connected, + Disconnected +}; + +class TmaConnection { + protected: + HosMutex lock; + void (*connection_event_callback)(void *, ConnectionEvent) = nullptr; + void *connection_event_arg = nullptr; + bool has_woken_up = false; + bool is_initialized = false; + protected: + void OnReceivePacket(TmaPacket *packet); + void OnDisconnected(); + void OnConnectionEvent(ConnectionEvent event); + void CancelTasks(); + void Tick(); + public: + /* Setup */ + TmaConnection() { } + virtual ~TmaConnection() { } + + void Initialize() { + if (this->is_initialized) { + std::abort(); + } + this->is_initialized = true; + } + + void SetConnectionEventCallback(void (*callback)(void *, ConnectionEvent), void *arg) { + this->connection_event_callback = callback; + this->connection_event_arg = arg; + } + + void Finalize() { + if (this->is_initialized) { + this->StopListening(); + if (this->IsConnected()) { + this->Disconnect(); + } + this->is_initialized = false; + } + } + + /* Packet management. */ + TmaPacket *AllocateSendPacket(); + TmaPacket *AllocateRecvPacket(); + void FreePacket(TmaPacket *packet); + + /* For sub-interfaces to implement, connection management. */ + virtual void StartListening() { } + virtual void StopListening() { } + virtual bool IsConnected() = 0; + virtual TmaConnResult Disconnect() = 0; + virtual TmaConnResult SendPacket(TmaPacket *packet) = 0; +}; \ No newline at end of file diff --git a/stratosphere/tma/source/tma_conn_usb_connection.cpp b/stratosphere/tma/source/tma_conn_usb_connection.cpp new file mode 100644 index 000000000..d9d40a214 --- /dev/null +++ b/stratosphere/tma/source/tma_conn_usb_connection.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include "tma_conn_usb_connection.hpp" +#include "tma_usb_comms.hpp" + +static HosThread g_SendThread, g_RecvThread; + +TmaConnResult TmaUsbConnection::InitializeComms() { + return TmaUsbComms::Initialize(); +} + +TmaConnResult TmaUsbConnection::FinalizeComms() { + return TmaUsbComms::Finalize(); +} + +void TmaUsbConnection::ClearSendQueue() { + uintptr_t _packet; + while (this->send_queue.TryReceive(&_packet)) { + TmaPacket *packet = reinterpret_cast<TmaPacket *>(_packet); + if (packet != nullptr) { + this->FreePacket(packet); + } + } +} + +void TmaUsbConnection::SendThreadFunc(void *arg) { + TmaUsbConnection *this_ptr = reinterpret_cast<TmaUsbConnection *>(arg); + TmaConnResult res = TmaConnResult::Success; + TmaPacket *packet = nullptr; + + while (res == TmaConnResult::Success) { + /* Receive a packet from the send queue. */ + { + uintptr_t _packet; + this_ptr->send_queue.Receive(&_packet); + packet = reinterpret_cast<TmaPacket *>(_packet); + } + + if (packet != nullptr) { + /* Send the packet if we're connected. */ + if (this_ptr->IsConnected()) { + res = TmaUsbComms::SendPacket(packet); + } + + this_ptr->FreePacket(packet); + this_ptr->Tick(); + } else { + res = TmaConnResult::Disconnected; + } + } + + this_ptr->SetConnected(false); + this_ptr->OnDisconnected(); +} + +void TmaUsbConnection::RecvThreadFunc(void *arg) { + TmaUsbConnection *this_ptr = reinterpret_cast<TmaUsbConnection *>(arg); + TmaConnResult res = TmaConnResult::Success; + u64 i = 0; + this_ptr->SetConnected(true); + + while (res == TmaConnResult::Success) { + if (!this_ptr->IsConnected()) { + break; + } + TmaPacket *packet = this_ptr->AllocateRecvPacket(); + if (packet == nullptr) { std::abort(); } + + res = TmaUsbComms::ReceivePacket(packet); + + if (res == TmaConnResult::Success) { + TmaPacket *send_packet = this_ptr->AllocateSendPacket(); + send_packet->Write<u64>(i++); + this_ptr->send_queue.Send(reinterpret_cast<uintptr_t>(send_packet)); + this_ptr->FreePacket(packet); + } else { + this_ptr->FreePacket(packet); + } + } + + this_ptr->SetConnected(false); + this_ptr->send_queue.Send(reinterpret_cast<uintptr_t>(nullptr)); +} + +void TmaUsbConnection::OnUsbStateChange(void *arg, u32 state) { + TmaUsbConnection *this_ptr = reinterpret_cast<TmaUsbConnection *>(arg); + switch (state) { + case 0: + case 6: + this_ptr->StopThreads(); + break; + case 5: + this_ptr->StartThreads(); + break; + } +} + +void TmaUsbConnection::StartThreads() { + g_SendThread.Join(); + g_RecvThread.Join(); + + g_SendThread.Initialize(&TmaUsbConnection::SendThreadFunc, this, 0x4000, 38); + g_RecvThread.Initialize(&TmaUsbConnection::RecvThreadFunc, this, 0x4000, 38); + + this->ClearSendQueue(); + g_SendThread.Start(); + g_RecvThread.Start(); +} + +void TmaUsbConnection::StopThreads() { + TmaUsbComms::CancelComms(); + g_SendThread.Join(); + g_RecvThread.Join(); +} + +bool TmaUsbConnection::IsConnected() { + return this->is_connected; +} + +TmaConnResult TmaUsbConnection::Disconnect() { + TmaUsbComms::SetStateChangeCallback(nullptr, nullptr); + + this->StopThreads(); + + return TmaConnResult::Success; +} + +TmaConnResult TmaUsbConnection::SendPacket(TmaPacket *packet) { + std::scoped_lock<HosMutex> lk(this->lock); + + if (this->IsConnected()) { + this->send_queue.Send(reinterpret_cast<uintptr_t>(packet)); + return TmaConnResult::Success; + } else { + this->FreePacket(packet); + this->Tick(); + return TmaConnResult::Disconnected; + } +} diff --git a/stratosphere/tma/source/tma_conn_usb_connection.hpp b/stratosphere/tma/source/tma_conn_usb_connection.hpp new file mode 100644 index 000000000..15876ef3b --- /dev/null +++ b/stratosphere/tma/source/tma_conn_usb_connection.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "tma_conn_connection.hpp" +#include "tma_usb_comms.hpp" + +class TmaUsbConnection : public TmaConnection { + private: + HosMessageQueue send_queue = HosMessageQueue(64); + std::atomic<bool> is_connected = false; + private: + static void SendThreadFunc(void *arg); + static void RecvThreadFunc(void *arg); + static void OnUsbStateChange(void *this_ptr, u32 state); + void ClearSendQueue(); + void StartThreads(); + void StopThreads(); + void SetConnected(bool c) { this->is_connected = c; } + public: + static TmaConnResult InitializeComms(); + static TmaConnResult FinalizeComms(); + + TmaUsbConnection() { + TmaUsbComms::SetStateChangeCallback(&TmaUsbConnection::OnUsbStateChange, this); + } + + virtual ~TmaUsbConnection() { + this->Disconnect(); + } + + virtual bool IsConnected() override; + virtual TmaConnResult Disconnect() override; + virtual TmaConnResult SendPacket(TmaPacket *packet) override; +}; \ No newline at end of file diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp index e4c23777b..8fc308444 100644 --- a/stratosphere/tma/source/tma_main.cpp +++ b/stratosphere/tma/source/tma_main.cpp @@ -22,14 +22,14 @@ #include <switch.h> #include <stratosphere.hpp> -#include "tma_usb_comms.hpp" +#include "tma_conn_usb_connection.hpp" extern "C" { extern u32 __start__; u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x100000 + #define INNER_HEAP_SIZE 0x400000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -111,17 +111,12 @@ int main(int argc, char **argv) /* TODO: Panic. */ } - TmaUsbComms::Initialize(); - TmaPacket *packet = new TmaPacket(); - usbDsWaitReady(U64_MAX); - packet->Write<u64>(0xCAFEBABEDEADCAFEUL); - packet->Write<u64>(0xCCCCCCCCCCCCCCCCUL); - TmaUsbComms::SendPacket(packet); - packet->ClearOffset(); + TmaUsbConnection::InitializeComms(); + auto conn = new TmaUsbConnection(); + conn->Initialize(); + while (true) { - if (TmaUsbComms::ReceivePacket(packet) == TmaConnResult::Success) { - TmaUsbComms::SendPacket(packet); - } + svcSleepThread(10000000UL); } diff --git a/stratosphere/tma/source/tma_usb_comms.cpp b/stratosphere/tma/source/tma_usb_comms.cpp index 440218bef..f2cd014c8 100644 --- a/stratosphere/tma/source/tma_usb_comms.cpp +++ b/stratosphere/tma/source/tma_usb_comms.cpp @@ -258,12 +258,12 @@ TmaConnResult TmaUsbComms::Initialize() { } /* Start the state change thread. */ - /*if (R_SUCCEEDED(rc)) { + if (R_SUCCEEDED(rc)) { rc = g_state_change_thread.Initialize(&TmaUsbComms::UsbStateChangeThreadFunc, nullptr, 0x4000, 38); if (R_SUCCEEDED(rc)) { rc = g_state_change_thread.Start(); } - }*/ + } /* Enable USB communication. */ if (R_SUCCEEDED(rc)) { @@ -277,10 +277,6 @@ TmaConnResult TmaUsbComms::Initialize() { if (R_FAILED(rc)) { /* TODO: Should I not abort here? */ std::abort(); - - // /* Cleanup, just in case. */ - // TmaUsbComms::Finalize(); - // res = TmaConnResult::Failure; } g_initialized = true; @@ -306,6 +302,10 @@ TmaConnResult TmaUsbComms::Finalize() { usbDsExit(); } + g_state_change_callback = nullptr; + g_interface = nullptr; + g_endpoint_in = nullptr; + g_endpoint_out = nullptr; g_initialized = false; return R_SUCCEEDED(rc) ? TmaConnResult::Success : TmaConnResult::ConnectionFailure; @@ -458,3 +458,27 @@ TmaConnResult TmaUsbComms::SendPacket(TmaPacket *packet) { return res; } + +void TmaUsbComms::UsbStateChangeThreadFunc(void *arg) { + u32 state; + g_state_change_manager = new WaitableManager(1); + + auto state_change_event = LoadReadOnlySystemEvent(usbDsGetStateChangeEvent()->revent, [&](u64 timeout) { + if (R_SUCCEEDED(usbDsGetState(&state))) { + if (g_state_change_callback != nullptr) { + g_state_change_callback(g_state_change_arg, state); + } + } + return 0; + }, true); + + g_state_change_manager->AddWaitable(state_change_event); + g_state_change_manager->Process(); + + /* If we get here, we're exiting. */ + state_change_event->r_h = 0; + delete g_state_change_manager; + g_state_change_manager = nullptr; + + svcExitThread(); +} \ No newline at end of file diff --git a/stratosphere/tma/source/tma_usb_comms.hpp b/stratosphere/tma/source/tma_usb_comms.hpp index 9815e7634..52f119140 100644 --- a/stratosphere/tma/source/tma_usb_comms.hpp +++ b/stratosphere/tma/source/tma_usb_comms.hpp @@ -14,6 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#pragma once #include <switch.h> #include <stratosphere.hpp> From 2572ae8378d28226af88af657979fde86f41e75a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 6 Nov 2018 20:20:07 -0800 Subject: [PATCH 274/489] tma: impl helper services, cleanup hostside packets --- stratosphere/tma/client/Main.py | 2 - stratosphere/tma/client/Packet.py | 116 ++++++++++++++++++ stratosphere/tma/client/ServiceId.py | 27 ++++ stratosphere/tma/client/UsbConnection.py | 50 +++++--- stratosphere/tma/client/UsbInterface.py | 33 ++--- stratosphere/tma/source/tma_conn_packet.hpp | 2 +- .../tma/source/tma_conn_service_ids.hpp | 8 ++ .../tma/source/tma_conn_usb_connection.cpp | 58 ++++++++- .../tma/source/tma_conn_usb_connection.hpp | 1 + stratosphere/tma/source/tma_usb_comms.cpp | 2 +- 10 files changed, 252 insertions(+), 47 deletions(-) create mode 100644 stratosphere/tma/client/Packet.py create mode 100644 stratosphere/tma/client/ServiceId.py diff --git a/stratosphere/tma/client/Main.py b/stratosphere/tma/client/Main.py index 580e0ae52..b1469a1e1 100644 --- a/stratosphere/tma/client/Main.py +++ b/stratosphere/tma/client/Main.py @@ -18,8 +18,6 @@ def main(argc, argv): print 'Waiting for connection...' c.wait_connected() print 'Connected!' - while True: - c.send_packet('AAAAAAAA') return 0 if __name__ == '__main__': diff --git a/stratosphere/tma/client/Packet.py b/stratosphere/tma/client/Packet.py new file mode 100644 index 000000000..465be93e8 --- /dev/null +++ b/stratosphere/tma/client/Packet.py @@ -0,0 +1,116 @@ +# Copyright (c) 2018 Atmosphere-NX +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +import zlib +import ServiceId +from struct import unpack as up, pack as pk + +HEADER_SIZE = 0x28 + +def crc32(s): + return zlib.crc32(s) & 0xFFFFFFFF + +class Packet(): + def __init__(self): + self.service = 0 + self.task = 0 + self.cmd = 0 + self.continuation = 0 + self.version = 0 + self.body_len = 0 + self.body = '' + self.offset = 0 + def load_header(self, header): + assert len(header) == HEADER_SIZE + self.service, self.task, self.cmd, self.continuation, self.version, self.body_len, \ + _, self.body_chk, self.hdr_chk = up('<IIHBBI16sII', header) + if crc32(header[:-4]) != self.hdr_chk: + raise ValueError('Invalid header checksum in received packet!') + def load_body(self, body): + assert len(body) == self.body_len + if crc32(body) != self.body_chk: + raise ValueError('Invalid body checksum in received packet!') + self.body = body + def get_data(self): + assert len(self.body) == self.body_len and self.body_len <= 0xE000 + self.body_chk = crc32(self.body) + hdr = pk('<IIHBBIIIIII', self.service, self.task, self.cmd, self.continuation, self.version, self.body_len, 0, 0, 0, 0, self.body_chk) + self.hdr_chk = crc32(hdr) + hdr += pk('<I', self.hdr_chk) + return hdr + self.body + def set_service(self, srv): + if type(srv) is str: + self.service = ServiceId.hash(srv) + else: + self.service = srv + return self + def set_task(self, t): + self.task = t + return self + def set_cmd(self, x): + self.cmd = x + return self + def set_continuation(self, c): + self.continuation = c + return self + def set_version(self, v): + self.version = v + return self + def reset_offset(self): + self.offset = 0 + return self + def write_str(self, s): + self.body += s + self.body_len += len(s) + return self + def write_u8(self, x): + self.body += pk('<B', x & 0xFF) + self.body_len += 1 + return self + def write_u16(self, x): + self.body += pk('<H', x & 0xFFFF) + self.body_len += 2 + return self + def write_u32(self, x): + self.body += pk('<I', x & 0xFFFFFFFF) + self.body_len += 4 + return self + def write_u64(self, x): + self.body += pk('<Q', x & 0xFFFFFFFFFFFFFFFF) + self.body_len += 8 + return self + def read_str(self): + s = '' + while self.body[self.offset] != '\x00' and self.offset < self.body_len: + s += self.body[self.offset] + self.offset += 1 + def read_u8(self): + x, = up('<B', self.body[self.offset:self.offset+1]) + self.offset += 1 + return x + def read_u16(self): + x, = up('<H', self.body[self.offset:self.offset+2]) + self.offset += 2 + return x + def read_u32(self): + x, = up('<I', self.body[self.offset:self.offset+4]) + self.offset += 4 + return x + def read_u64(self): + x, = up('<Q', self.body[self.offset:self.offset+8]) + self.offset += 8 + return x + def read_struct(self, format, sz): + x = up(format, self.body[self.offset:self.offset+sz]) + self.offset += sz + return x diff --git a/stratosphere/tma/client/ServiceId.py b/stratosphere/tma/client/ServiceId.py new file mode 100644 index 000000000..5207d2ae3 --- /dev/null +++ b/stratosphere/tma/client/ServiceId.py @@ -0,0 +1,27 @@ +# Copyright (c) 2018 Atmosphere-NX +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +def hash(s): + h = ord(s[0]) & 0xFFFFFFFF + for c in s: + h = ((1000003 * h) ^ ord(c)) & 0xFFFFFFFF + h ^= len(s) + return h + +USB_QUERY_TARGET = hash("USBQueryTarget") +USB_SEND_HOST_INFO = hash("USBSendHostInfo") +USB_CONNECT = hash("USBConnect") +USB_DISCONNECT = hash("USBDisconnect") + + \ No newline at end of file diff --git a/stratosphere/tma/client/UsbConnection.py b/stratosphere/tma/client/UsbConnection.py index 0f7d2cf8f..a7b009ad6 100644 --- a/stratosphere/tma/client/UsbConnection.py +++ b/stratosphere/tma/client/UsbConnection.py @@ -15,6 +15,8 @@ from UsbInterface import UsbInterface from threading import Thread, Condition from collections import deque import time +import ServiceId +from Packet import Packet class UsbConnection(UsbInterface): # Auto connect thread func. @@ -25,12 +27,6 @@ class UsbConnection(UsbInterface): except ValueError as e: continue def recv_thread(connection): - if connection.is_connected(): - try: - # If we've previously been connected, PyUSB will read garbage... - connection.recv_packet() - except ValueError: - pass while connection.is_connected(): try: connection.recv_packet() @@ -65,6 +61,7 @@ class UsbConnection(UsbInterface): self.conn_thrd.start() return self def __exit__(self, type, value, traceback): + self.disconnect() time.sleep(1) print 'Closing!' time.sleep(1) @@ -80,24 +77,43 @@ class UsbConnection(UsbInterface): self.conn_lock.acquire() assert not self.connected self.intf = intf - self.connected = True - self.conn_lock.notify() - self.conn_lock.release() - self.recv_thrd = Thread(target=UsbConnection.recv_thread, args=(self,)) - self.send_thrd = Thread(target=UsbConnection.send_thread, args=(self,)) - self.recv_thrd.daemon = True - self.send_thrd.daemon = True - self.recv_thrd.start() - self.send_thrd.start() + + try: + # Perform Query + Connection handshake + self.intf.send_packet(Packet().set_service(ServiceId.USB_QUERY_TARGET)) + query_resp = self.intf.read_packet() + print 'Found Switch, Protocol version 0x%x' % query_resp.read_u32() + + self.intf.send_packet(Packet().set_service(ServiceId.USB_SEND_HOST_INFO).write_u32(0).write_u32(0)) + + self.intf.send_packet(Packet().set_service(ServiceId.USB_CONNECT)) + resp = self.intf.read_packet() + + # Spawn threads + self.recv_thrd = Thread(target=UsbConnection.recv_thread, args=(self,)) + self.send_thrd = Thread(target=UsbConnection.send_thread, args=(self,)) + self.recv_thrd.daemon = True + self.send_thrd.daemon = True + self.recv_thrd.start() + self.send_thrd.start() + self.connected = True + finally: + # Finish connection. + self.conn_lock.notify() + self.conn_lock.release() def disconnect(self): self.conn_lock.acquire() if self.connected: self.connected = False + self.intf.send_packet(Packet().set_service(ServiceId.USB_DISCONNECT)) self.conn_lock.release() def recv_packet(self): - hdr, body = self.intf.read_packet() - print('Got Packet: %s' % body.encode('hex')) + packet = self.intf.read_packet() + assert type(packet) is Packet + dat = packet.read_u64() + print('Got Packet: %08x' % dat) def send_packet(self, packet): + assert type(packet) is Packet self.send_lock.acquire() if len(self.send_queue) == 0x40: self.send_lock.wait() diff --git a/stratosphere/tma/client/UsbInterface.py b/stratosphere/tma/client/UsbInterface.py index 90d91cab9..69169cf6e 100644 --- a/stratosphere/tma/client/UsbInterface.py +++ b/stratosphere/tma/client/UsbInterface.py @@ -11,11 +11,8 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import usb, zlib -from struct import unpack as up, pack as pk - -def crc32(s): - return zlib.crc32(s) & 0xFFFFFFFF +import usb +import Packet class UsbInterface(): def __init__(self): @@ -50,20 +47,16 @@ class UsbInterface(): def blocking_write(self, data): self.ep_out.write(data, 0xFFFFFFFFFFFFFFFF) def read_packet(self): - hdr = self.blocking_read(0x28) - _, _, _, body_size, _, _, _, _, body_chk, hdr_chk = up('<IIIIIIIIII', hdr) - if crc32(hdr[:-4]) != hdr_chk: - raise ValueError('Invalid header checksum in received packet!') - body = self.blocking_read(body_size) - if len(body) != body_size: - raise ValueError('Failed to receive packet body!') - elif crc32(body) != body_chk: - raise ValueError('Invalid body checksum in received packet!') - return (hdr, body) - def send_packet(self, body): - hdr = pk('<IIIIIIIII', 0, 0, 0, len(body), 0, 0, 0, 0, crc32(body)) - hdr += pk('<I', crc32(hdr)) - self.blocking_write(hdr) - self.blocking_write(body) + packet = Packet.Packet() + hdr = self.blocking_read(Packet.HEADER_SIZE) + packet.load_header(hdr) + if packet.body_len: + packet.load_body(self.blocking_read(packet.body_len)) + return packet + def send_packet(self, packet): + data = packet.get_data() + self.blocking_write(data[:Packet.HEADER_SIZE]) + if (len(data) > Packet.HEADER_SIZE): + self.blocking_write(data[Packet.HEADER_SIZE:]) diff --git a/stratosphere/tma/source/tma_conn_packet.hpp b/stratosphere/tma/source/tma_conn_packet.hpp index 03aaffc5a..18537c119 100644 --- a/stratosphere/tma/source/tma_conn_packet.hpp +++ b/stratosphere/tma/source/tma_conn_packet.hpp @@ -190,7 +190,7 @@ class TmaPacket { } template<typename T> - TmaConnResult Read(const T &t) { + TmaConnResult Read(T &t) { return Read(&t, sizeof(T)); } diff --git a/stratosphere/tma/source/tma_conn_service_ids.hpp b/stratosphere/tma/source/tma_conn_service_ids.hpp index 7dc8ee331..1120d81ec 100644 --- a/stratosphere/tma/source/tma_conn_service_ids.hpp +++ b/stratosphere/tma/source/tma_conn_service_ids.hpp @@ -34,5 +34,13 @@ static constexpr u32 HashServiceName(const char *name) { enum class TmaService : u32 { Invalid = 0, + + /* Special nodes, for facilitating connection over USB. */ + UsbQueryTarget = HashServiceName("USBQueryTarget"), + UsbSendHostInfo = HashServiceName("USBSendHostInfo"), + UsbConnect = HashServiceName("USBConnect"), + UsbDisconnect = HashServiceName("USBDisconnect"), + + TestService = HashServiceName("AtmosphereTestService"), /* Temporary service, will be used to debug communications. */ }; diff --git a/stratosphere/tma/source/tma_conn_usb_connection.cpp b/stratosphere/tma/source/tma_conn_usb_connection.cpp index d9d40a214..75bf1a2a4 100644 --- a/stratosphere/tma/source/tma_conn_usb_connection.cpp +++ b/stratosphere/tma/source/tma_conn_usb_connection.cpp @@ -76,18 +76,54 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { this_ptr->SetConnected(true); while (res == TmaConnResult::Success) { - if (!this_ptr->IsConnected()) { - break; - } TmaPacket *packet = this_ptr->AllocateRecvPacket(); if (packet == nullptr) { std::abort(); } res = TmaUsbComms::ReceivePacket(packet); if (res == TmaConnResult::Success) { - TmaPacket *send_packet = this_ptr->AllocateSendPacket(); - send_packet->Write<u64>(i++); - this_ptr->send_queue.Send(reinterpret_cast<uintptr_t>(send_packet)); + switch (packet->GetServiceId()) { + case TmaService::UsbQueryTarget: { + this_ptr->SetConnected(false); + + res = this_ptr->SendQueryReply(packet); + + if (!this_ptr->has_woken_up) { + /* TODO: Cancel background work. */ + } + } + break; + case TmaService::UsbSendHostInfo: { + struct { + u32 version; + u32 sleeping; + } host_info; + packet->Read<decltype(host_info)>(host_info); + + if (!this_ptr->has_woken_up || !host_info.sleeping) { + /* TODO: Cancel background work. */ + } + } + break; + case TmaService::UsbConnect: { + res = this_ptr->SendQueryReply(packet); + + if (res == TmaConnResult::Success) { + this_ptr->SetConnected(true); + this_ptr->OnConnectionEvent(ConnectionEvent::Connected); + } + } + break; + case TmaService::UsbDisconnect: { + this_ptr->SetConnected(false); + this_ptr->OnDisconnected(); + + /* TODO: Cancel background work. */ + } + break; + default: + break; + } this_ptr->FreePacket(packet); } else { this_ptr->FreePacket(packet); @@ -153,3 +189,13 @@ TmaConnResult TmaUsbConnection::SendPacket(TmaPacket *packet) { return TmaConnResult::Disconnected; } } + +TmaConnResult TmaUsbConnection::SendQueryReply(TmaPacket *packet) { + packet->ClearOffset(); + struct { + u32 version; + } target_info; + target_info.version = 0; + packet->Write<decltype(target_info)>(target_info); + return TmaUsbComms::SendPacket(packet); +} diff --git a/stratosphere/tma/source/tma_conn_usb_connection.hpp b/stratosphere/tma/source/tma_conn_usb_connection.hpp index 15876ef3b..2927e6e3f 100644 --- a/stratosphere/tma/source/tma_conn_usb_connection.hpp +++ b/stratosphere/tma/source/tma_conn_usb_connection.hpp @@ -29,6 +29,7 @@ class TmaUsbConnection : public TmaConnection { static void SendThreadFunc(void *arg); static void RecvThreadFunc(void *arg); static void OnUsbStateChange(void *this_ptr, u32 state); + TmaConnResult SendQueryReply(TmaPacket *packet); void ClearSendQueue(); void StartThreads(); void StopThreads(); diff --git a/stratosphere/tma/source/tma_usb_comms.cpp b/stratosphere/tma/source/tma_usb_comms.cpp index f2cd014c8..32390c327 100644 --- a/stratosphere/tma/source/tma_usb_comms.cpp +++ b/stratosphere/tma/source/tma_usb_comms.cpp @@ -436,7 +436,7 @@ TmaConnResult TmaUsbComms::SendPacket(TmaPacket *packet) { res = TmaConnResult::GeneralFailure; } - if (res == TmaConnResult::Success) { + if (res == TmaConnResult::Success && 0 < body_len) { /* Copy body to send buffer. */ packet->CopyBodyTo(g_send_data_buf); From fc426a06b229f08327e26dbb9956d4b74d4285b1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 1 Dec 2018 13:56:13 -0800 Subject: [PATCH 275/489] exo: fix vaddr/paddr confusion in rcm reboot code --- exosphere/src/configitem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 9aa1e6fa8..a0309ec2b 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -38,8 +38,8 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { case CONFIGITEM_NEEDS_REBOOT_TO_RCM: /* Force a reboot to RCM, if requested. */ if (value != 0) { - MAKE_REG32(0x7000E450) = 0x2; - MAKE_REG32(0x7000E400) = 0x10; + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; while (1) { } } break; From bd76e73b253fa14327425e3952815e720dbf8343 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 1 Dec 2018 13:58:09 -0800 Subject: [PATCH 276/489] fusee: fix configuration typo --- fusee/fusee-secondary/src/exocfg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index 133ebffd3..d21abb4f9 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -49,7 +49,7 @@ typedef struct { #define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40)) #define EXOSPHERE_TARGETFW_KEY "target_firmware" -#define EXOSPHERE_DEBUGMODE_PRIV_KEY "debug_mode" -#define EXOSPHERE_DEBUGMODE_USER_KEY "debug_mode_user" +#define EXOSPHERE_DEBUGMODE_PRIV_KEY "debugmode" +#define EXOSPHERE_DEBUGMODE_USER_KEY "debugmode_user" #endif \ No newline at end of file From 3fa973f430196c36756be8f533b34cd2eaeaf767 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 1 Dec 2018 19:07:05 -0800 Subject: [PATCH 277/489] fatal/set_mitm: Support 1.0.0 kernel. --- stratosphere/fatal/fatal.json | 6 +++--- stratosphere/set_mitm/set_mitm.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stratosphere/fatal/fatal.json b/stratosphere/fatal/fatal.json index 201875895..0bdbeeeb2 100644 --- a/stratosphere/fatal/fatal.json +++ b/stratosphere/fatal/fatal.json @@ -4,13 +4,13 @@ "title_id_range_min": "0x0100000000000034", "title_id_range_max": "0x0100000000000034", "main_thread_stack_size": "0x00010000", - "main_thread_priority": 37, + "main_thread_priority": 15, "default_cpu_id": 3, "process_category": 0, "is_retail": true, "pool_partition": 2, "is_64_bit": true, - "address_space_type": 3, + "address_space_type": 1, "filesystem_access": { "permissions": "0xFFFFFFFFFFFFFFFF" }, @@ -88,7 +88,7 @@ } }, { "type": "min_kernel_version", - "value": "0x0060" + "value": "0x0030" }, { "type": "handle_table_size", "value": 128 diff --git a/stratosphere/set_mitm/set_mitm.json b/stratosphere/set_mitm/set_mitm.json index 055c6af6b..1f71cf7c1 100644 --- a/stratosphere/set_mitm/set_mitm.json +++ b/stratosphere/set_mitm/set_mitm.json @@ -10,7 +10,7 @@ "is_retail": true, "pool_partition": 2, "is_64_bit": true, - "address_space_type": 3, + "address_space_type": 1, "filesystem_access": { "permissions": "0xFFFFFFFFFFFFFFFF" }, @@ -99,7 +99,7 @@ }, { "type": "min_kernel_version", - "value": "0x0060" + "value": "0x0030" } ] } \ No newline at end of file From bbed78149c7a176a3687dc081f6a34063a603f8e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 1 Dec 2018 19:07:25 -0800 Subject: [PATCH 278/489] fs.mitm: Hog less CPU time if SD card not inserted --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index c1683eda9..2151e22ff 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -69,7 +69,7 @@ void Utils::InitializeSdThreadFunc(void *args) { /* Mount SD. */ while (R_FAILED(fsMountSdcard(&g_sd_filesystem))) { - svcSleepThread(1000ULL); + svcSleepThread(1000000ULL); } /* Back up CAL0, if it's not backed up already. */ From 8ecf68cb655f3e102c42e9d08d361f668f74bc02 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 1 Dec 2018 21:38:28 -0800 Subject: [PATCH 279/489] fusee: Add support for 1.0.0-7. --- fusee/fusee-secondary/src/kernel_patches.c | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index d5ae8df7b..03c5bbf4d 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -310,6 +310,24 @@ static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv)[] = {0x08, 0x03 static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_recv)[] = {0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; /* Hook Definitions. */ +static const kernel_hook_t g_kernel_hooks_100_7[] = { + { /* Send Message Process ID Patch. */ + .pattern_size = 0x10, + .pattern = MAKE_KERNEL_PATTERN_NAME(100, proc_id_send), + .pattern_hook_offset = 0x0, + .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(100, proc_id_send))/sizeof(instruction_t), + .branch_back_offset = 0x4, + .payload = MAKE_KERNEL_HOOK_NAME(100, proc_id_send) + }, + { /* Receive Message Process ID Patch. */ + .pattern_size = 0x10, + .pattern = MAKE_KERNEL_PATTERN_NAME(100, proc_id_recv), + .pattern_hook_offset = 0x0, + .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(100, proc_id_recv))/sizeof(instruction_t), + .branch_back_offset = 0x4, + .payload = MAKE_KERNEL_HOOK_NAME(100, proc_id_recv) + } +}; static const kernel_hook_t g_kernel_hooks_100[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x10, @@ -442,6 +460,11 @@ static const kernel_hook_t g_kernel_hooks_600[] = { /* Kernel Infos. */ static const kernel_info_t g_kernel_infos[] = { + { /* 1.0.0-7. */ + .hash = {0x64, 0x44, 0x07, 0x2F, 0x56, 0x44, 0x73, 0xDD, 0xD5, 0x46, 0x1B, 0x8C, 0xDC, 0xEF, 0x54, 0x98, 0x16, 0xDA, 0x81, 0xDE, 0x5B, 0x1C, 0x9D, 0xD7, 0x5A, 0x13, 0x91, 0xD9, 0x53, 0xAB, 0x8D, 0x8D}, + .free_code_space_offset = 0x4797C, + KERNEL_HOOKS(100_7) + }, { /* 1.0.0. */ .hash = {0xB8, 0xC5, 0x0C, 0x68, 0x25, 0xA9, 0xB9, 0x5B, 0xD2, 0x4D, 0x2C, 0x7C, 0x81, 0x7F, 0xE6, 0x96, 0xF2, 0x42, 0x4E, 0x1D, 0x78, 0xDF, 0x3B, 0xCA, 0x3D, 0x6B, 0x68, 0x12, 0xDD, 0xA9, 0xCB, 0x9C}, .free_code_space_offset = 0x4797C, From 021d84ff04d35ec905f733b505b94f9e8fe0bec6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 1 Dec 2018 21:39:29 -0800 Subject: [PATCH 280/489] fusee: remove duplicate hook --- fusee/fusee-secondary/src/kernel_patches.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index 03c5bbf4d..5b83d8ef9 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -310,24 +310,6 @@ static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv)[] = {0x08, 0x03 static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_recv)[] = {0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; /* Hook Definitions. */ -static const kernel_hook_t g_kernel_hooks_100_7[] = { - { /* Send Message Process ID Patch. */ - .pattern_size = 0x10, - .pattern = MAKE_KERNEL_PATTERN_NAME(100, proc_id_send), - .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(100, proc_id_send))/sizeof(instruction_t), - .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(100, proc_id_send) - }, - { /* Receive Message Process ID Patch. */ - .pattern_size = 0x10, - .pattern = MAKE_KERNEL_PATTERN_NAME(100, proc_id_recv), - .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(100, proc_id_recv))/sizeof(instruction_t), - .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(100, proc_id_recv) - } -}; static const kernel_hook_t g_kernel_hooks_100[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x10, @@ -463,7 +445,7 @@ static const kernel_info_t g_kernel_infos[] = { { /* 1.0.0-7. */ .hash = {0x64, 0x44, 0x07, 0x2F, 0x56, 0x44, 0x73, 0xDD, 0xD5, 0x46, 0x1B, 0x8C, 0xDC, 0xEF, 0x54, 0x98, 0x16, 0xDA, 0x81, 0xDE, 0x5B, 0x1C, 0x9D, 0xD7, 0x5A, 0x13, 0x91, 0xD9, 0x53, 0xAB, 0x8D, 0x8D}, .free_code_space_offset = 0x4797C, - KERNEL_HOOKS(100_7) + KERNEL_HOOKS(100) }, { /* 1.0.0. */ .hash = {0xB8, 0xC5, 0x0C, 0x68, 0x25, 0xA9, 0xB9, 0x5B, 0xD2, 0x4D, 0x2C, 0x7C, 0x81, 0x7F, 0xE6, 0x96, 0xF2, 0x42, 0x4E, 0x1D, 0x78, 0xDF, 0x3B, 0xCA, 0x3D, 0x6B, 0x68, 0x12, 0xDD, 0xA9, 0xCB, 0x9C}, From 49ba3a86e2f574234030130c9c3564f4c5d57b76 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 4 Dec 2018 03:54:25 -0800 Subject: [PATCH 281/489] fusee: move BCT.ini/secondary into atmosphere/ --- Makefile | 4 ++-- common/defaults/BCT.ini | 2 +- fusee/fusee-primary/src/main.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 9d8364e89..62fdd0f64 100644 --- a/Makefile +++ b/Makefile @@ -42,8 +42,8 @@ dist: all mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032 - cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/fusee-secondary.bin - cp common/defaults/BCT.ini atmosphere-$(AMSVER)/BCT.ini + cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin + cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini cp -r common/defaults/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp diff --git a/common/defaults/BCT.ini b/common/defaults/BCT.ini index 81d69e48e..660b456b7 100644 --- a/common/defaults/BCT.ini +++ b/common/defaults/BCT.ini @@ -1,6 +1,6 @@ BCT0 [stage1] -stage2_path = fusee-secondary.bin +stage2_path = atmosphere/fusee-secondary.bin stage2_addr = 0xF0000000 stage2_entrypoint = 0xF0000000 diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 130362e0a..9c5e81def 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -40,12 +40,12 @@ static char g_bct0_buffer[BCTO_MAX_SIZE]; #define DEFAULT_BCT0_FOR_DEBUG \ "BCT0\n"\ "[stage1]\n"\ -"stage2_path = fusee-secondary.bin\n"\ +"stage2_path = atmosphere/fusee-secondary.bin\n"\ "stage2_addr = 0xF0000000\n"\ "stage2_entrypoint = 0xF0000000\n" static const char *load_config(void) { - if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "BCT.ini")) { + if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "atmosphere/BCT.ini")) { print(SCREEN_LOG_LEVEL_DEBUG, "Failed to read BCT0 from SD!\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Using default BCT0!\n"); memcpy(g_bct0_buffer, DEFAULT_BCT0_FOR_DEBUG, sizeof(DEFAULT_BCT0_FOR_DEBUG)); @@ -159,7 +159,7 @@ int main(void) { strcpy(g_chainloader_arg_data, stage2_path); stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */ memcpy(&stage2_args->version, &stage2_version, 4); - stage2_args->log_level = log_level; + memcpy(&stage2_args->log_level, &log_level, sizeof(log_level)); stage2_args->display_initialized = false; strcpy(stage2_args->bct0, bct0); g_chainloader_argc = 2; From 903789cf6e4c3b5b0e2eab9540ce0854ef679b44 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 4 Dec 2018 04:01:22 -0800 Subject: [PATCH 282/489] fusee: fix error printing pre-SD card init (closes #289). --- fusee/fusee-primary/src/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 9c5e81def..c54862ba8 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -108,7 +108,7 @@ static void setup_env(void) { /* Set up the exception handlers. */ setup_exception_handlers(); - + /* Mount the SD card. */ mount_sd(); } @@ -133,6 +133,9 @@ int main(void) { uint32_t stage2_version = 0; ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY; + /* Override the global logging level. */ + log_set_log_level(log_level); + /* Initialize the display, console, etc. */ setup_env(); @@ -144,9 +147,6 @@ int main(void) { fatal_error("Failed to parse BCT.ini!\n"); } - /* Override the global logging level. */ - log_set_log_level(log_level); - /* Say hello. */ print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); From a79f4cf6f6ecef2f17da43ca9cca2225e0949e7f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 4 Dec 2018 15:59:30 -0800 Subject: [PATCH 283/489] exosphere: fix sleep mode when debugmode is enabled --- exosphere/src/bootup.c | 8 ++++++++ exosphere/src/configitem.c | 9 +++++++++ exosphere/src/configitem.h | 1 + exosphere/src/lp0.c | 3 ++- exosphere/src/warmboot_main.c | 11 ++++++++++- 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 962ef8e75..4836f4610 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -31,6 +31,7 @@ #include "configitem.h" #include "timers.h" #include "misc.h" +#include "uart.h" #include "bpmp.h" #include "sysreg.h" #include "interrupt.h" @@ -213,6 +214,13 @@ void bootup_misc_mmio(void) { } if (!g_has_booted_up) { + /* N doesn't do this, but we should for compatibility. */ + if (configitem_is_debugmode_priv()) { + uart_select(UART_A); + clkrst_reboot(CARDEVICE_UARTA); + uart_init(UART_A, 115200); + } + intr_register_handler(INTERRUPT_ID_SECURITY_ENGINE, se_operation_completed); if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { intr_register_handler(INTERRUPT_ID_ACTIVITY_MONITOR_4X, actmon_interrupt_handler); diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index a0309ec2b..cac02b835 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -72,6 +72,15 @@ bool configitem_should_profile_battery(void) { return g_battery_profile; } +bool configitem_is_debugmode_priv(void) { + uint64_t debugmode = 0; + if (configitem_get(true, CONFIGITEM_ISDEBUGMODE, &debugmode) != 0) { + generic_panic(); + } + + return debugmode != 0; +} + uint64_t configitem_get_hardware_type(void) { uint64_t hardware_type; if (configitem_get(true, CONFIGITEM_HARDWARETYPE, &hardware_type) != 0) { diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index 8aef4e975..df54c5740 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -50,6 +50,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue); bool configitem_is_recovery_boot(void); bool configitem_is_retail(void); bool configitem_should_profile_battery(void); +bool configitem_is_debugmode_priv(void); void configitem_set_debugmode_override(bool user, bool priv); diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c index e6e19d3bf..e38693cf0 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/lp0.c @@ -35,6 +35,7 @@ #include "smc_api.h" #include "timers.h" #include "misc.h" +#include "uart.h" #include "exocfg.h" #define u8 uint8_t @@ -241,7 +242,7 @@ void save_se_and_power_down_cpu(void) { save_se_state(); if (!configitem_is_retail()) { - /* TODO: uart_log("OYASUMI"); */ + uart_send(UART_A, "OYASUMI", 8); } finalize_powerdown(); diff --git a/exosphere/src/warmboot_main.c b/exosphere/src/warmboot_main.c index 8ee15c4fd..d6f66aeb3 100644 --- a/exosphere/src/warmboot_main.c +++ b/exosphere/src/warmboot_main.c @@ -30,6 +30,7 @@ #include "car.h" #include "i2c.h" #include "misc.h" +#include "uart.h" #include "interrupt.h" #include "pmc.h" @@ -55,8 +56,16 @@ void __attribute__((noreturn)) warmboot_main(void) { /* On warmboot (not cpu_on) only */ if (VIRT_MC_SECURITY_CFG3 == 0) { + /* N only does this on dev units, but we will do it unconditionally. */ + { + uart_select(UART_A); + clkrst_reboot(CARDEVICE_UARTA); + uart_init(UART_A, 115200); + } + if (!configitem_is_retail()) { - /* TODO: uart_log("OHAYO"); */ + uart_send(UART_A, "OHAYO", 6); + uart_wait_idle(UART_A, UART_VENDOR_STATE_TX_IDLE); } /* Sanity check the Security Engine. */ From a51d355707cb70f90021fde9226a64ad3e9e2f16 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 4 Dec 2018 16:01:26 -0800 Subject: [PATCH 284/489] exo: there's no reason to not always init uart to be safe, actually --- exosphere/src/bootup.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 4836f4610..9d01ae08a 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -215,11 +215,9 @@ void bootup_misc_mmio(void) { if (!g_has_booted_up) { /* N doesn't do this, but we should for compatibility. */ - if (configitem_is_debugmode_priv()) { - uart_select(UART_A); - clkrst_reboot(CARDEVICE_UARTA); - uart_init(UART_A, 115200); - } + uart_select(UART_A); + clkrst_reboot(CARDEVICE_UARTA); + uart_init(UART_A, 115200); intr_register_handler(INTERRUPT_ID_SECURITY_ENGINE, se_operation_completed); if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { From bb48e33074577825c609d71a9ad49e7587f2c05b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 02:11:20 -0800 Subject: [PATCH 285/489] tma: Skeleton Service/Task/TaskList classes. --- stratosphere/libstratosphere | 2 +- stratosphere/tma/source/tma_conn_packet.hpp | 6 +- .../tma/source/tma_conn_service_ids.hpp | 9 +- .../tma/source/tma_conn_usb_connection.cpp | 9 +- stratosphere/tma/source/tma_main.cpp | 3 +- stratosphere/tma/source/tma_service.cpp | 32 +++ stratosphere/tma/source/tma_service.hpp | 43 ++++ stratosphere/tma/source/tma_task.cpp | 29 +++ stratosphere/tma/source/tma_task.hpp | 74 +++++++ stratosphere/tma/source/tma_task_list.cpp | 183 ++++++++++++++++++ stratosphere/tma/source/tma_task_list.hpp | 49 +++++ 11 files changed, 428 insertions(+), 11 deletions(-) create mode 100644 stratosphere/tma/source/tma_service.cpp create mode 100644 stratosphere/tma/source/tma_service.hpp create mode 100644 stratosphere/tma/source/tma_task.cpp create mode 100644 stratosphere/tma/source/tma_task.hpp create mode 100644 stratosphere/tma/source/tma_task_list.cpp create mode 100644 stratosphere/tma/source/tma_task_list.hpp diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 05015b935..fa37b70b0 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 05015b9354d3df80e0836aa95d1d4dcfc2aef4b7 +Subproject commit fa37b70b0eca93be04e18636db25c9443e00d03b diff --git a/stratosphere/tma/source/tma_conn_packet.hpp b/stratosphere/tma/source/tma_conn_packet.hpp index 18537c119..0b2593876 100644 --- a/stratosphere/tma/source/tma_conn_packet.hpp +++ b/stratosphere/tma/source/tma_conn_packet.hpp @@ -117,12 +117,12 @@ class TmaPacket { return MaxPacketSize - this->offset; } - void SetServiceId(TmaService srv) { + void SetServiceId(TmaServiceId srv) { GetHeader()->service_id = static_cast<u32>(srv); } - TmaService GetServiceId() const { - return static_cast<TmaService>(GetHeader()->service_id); + TmaServiceId GetServiceId() const { + return static_cast<TmaServiceId>(GetHeader()->service_id); } void SetTaskId(u32 id) { diff --git a/stratosphere/tma/source/tma_conn_service_ids.hpp b/stratosphere/tma/source/tma_conn_service_ids.hpp index 1120d81ec..eb0543d3d 100644 --- a/stratosphere/tma/source/tma_conn_service_ids.hpp +++ b/stratosphere/tma/source/tma_conn_service_ids.hpp @@ -32,7 +32,7 @@ static constexpr u32 HashServiceName(const char *name) { return h ^ len; } -enum class TmaService : u32 { +enum class TmaServiceId : u32 { Invalid = 0, /* Special nodes, for facilitating connection over USB. */ @@ -44,3 +44,10 @@ enum class TmaService : u32 { TestService = HashServiceName("AtmosphereTestService"), /* Temporary service, will be used to debug communications. */ }; + +static constexpr bool IsMetaService(TmaServiceId id) { + return id == TmaServiceId::UsbQueryTarget || + id == TmaServiceId::UsbSendHostInfo || + id == TmaServiceId::UsbConnect || + id == TmaServiceId::UsbDisconnect; +} diff --git a/stratosphere/tma/source/tma_conn_usb_connection.cpp b/stratosphere/tma/source/tma_conn_usb_connection.cpp index 75bf1a2a4..ba6ecd349 100644 --- a/stratosphere/tma/source/tma_conn_usb_connection.cpp +++ b/stratosphere/tma/source/tma_conn_usb_connection.cpp @@ -72,7 +72,6 @@ void TmaUsbConnection::SendThreadFunc(void *arg) { void TmaUsbConnection::RecvThreadFunc(void *arg) { TmaUsbConnection *this_ptr = reinterpret_cast<TmaUsbConnection *>(arg); TmaConnResult res = TmaConnResult::Success; - u64 i = 0; this_ptr->SetConnected(true); while (res == TmaConnResult::Success) { @@ -83,7 +82,7 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { if (res == TmaConnResult::Success) { switch (packet->GetServiceId()) { - case TmaService::UsbQueryTarget: { + case TmaServiceId::UsbQueryTarget: { this_ptr->SetConnected(false); res = this_ptr->SendQueryReply(packet); @@ -93,7 +92,7 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { } } break; - case TmaService::UsbSendHostInfo: { + case TmaServiceId::UsbSendHostInfo: { struct { u32 version; u32 sleeping; @@ -105,7 +104,7 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { } } break; - case TmaService::UsbConnect: { + case TmaServiceId::UsbConnect: { res = this_ptr->SendQueryReply(packet); if (res == TmaConnResult::Success) { @@ -114,7 +113,7 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { } } break; - case TmaService::UsbDisconnect: { + case TmaServiceId::UsbDisconnect: { this_ptr->SetConnected(false); this_ptr->OnDisconnected(); diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp index 8fc308444..d1b179d4c 100644 --- a/stratosphere/tma/source/tma_main.cpp +++ b/stratosphere/tma/source/tma_main.cpp @@ -20,6 +20,7 @@ #include <malloc.h> #include <switch.h> +#include <atmosphere.h> #include <stratosphere.hpp> #include "tma_conn_usb_connection.hpp" @@ -64,7 +65,7 @@ void __appInit(void) { fatalSimple(rc); } - CheckAtmosphereVersion(); + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { diff --git a/stratosphere/tma/source/tma_service.cpp b/stratosphere/tma/source/tma_service.cpp new file mode 100644 index 000000000..963d6e6d5 --- /dev/null +++ b/stratosphere/tma/source/tma_service.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include "tma_service.hpp" + +u32 TmaService::GetNextTaskId() { + /* TODO: Service Manager */ + return 0; +} + +void TmaService::OnSleep() { + /* Default service does nothing here. */ +} + +void TmaService::OnWake() { + /* Default service does nothing here. */ +} \ No newline at end of file diff --git a/stratosphere/tma/source/tma_service.hpp b/stratosphere/tma/source/tma_service.hpp new file mode 100644 index 000000000..17ab8215b --- /dev/null +++ b/stratosphere/tma/source/tma_service.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "tma_conn_service_ids.hpp" +#include "tma_conn_packet.hpp" +#include "tma_task.hpp" + +class TmaServiceManager; + +class TmaService { + protected: + TmaServiceManager *manager; + const char *service_name; + const TmaServiceId id; + protected: + u32 GetNextTaskId(); + virtual TmaTask *NewTask(TmaPacket *packet) = 0; + + virtual void OnSleep(); + virtual void OnWake(); + public: + TmaService(TmaServiceManager *m, const char *n) : manager(m), service_name(n), id(static_cast<TmaServiceId>(HashServiceName(this->service_name))) { } + virtual ~TmaService() { } + + TmaServiceId GetServiceId() const { return this->id; } +}; diff --git a/stratosphere/tma/source/tma_task.cpp b/stratosphere/tma/source/tma_task.cpp new file mode 100644 index 000000000..5c9c863b6 --- /dev/null +++ b/stratosphere/tma/source/tma_task.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include "tma_task.hpp" + +void TmaTask::Complete() { + /* TODO: Service manager */ + this->state = TmaTaskState::Complete; +} + +void TmaTask::Cancel() { + /* TODO: Service manager */ + this->state = TmaTaskState::Canceled; +} \ No newline at end of file diff --git a/stratosphere/tma/source/tma_task.hpp b/stratosphere/tma/source/tma_task.hpp new file mode 100644 index 000000000..9e115893f --- /dev/null +++ b/stratosphere/tma/source/tma_task.hpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "tma_conn_service_ids.hpp" +#include "tma_conn_packet.hpp" + +enum class TmaTaskState : u32 { + InProgress, + Complete, + Canceled, +}; + +class TmaServiceManager; + +class TmaTask { + public: + static constexpr u32 MaxPriority = 15; + static constexpr u32 NumPriorities = MaxPriority + 1; + protected: + TmaServiceManager *manager; + u32 priority = 0; + TmaServiceId service_id = TmaServiceId::Invalid; + u32 task_id = 0; + u32 command = 0; + TmaTaskState state = TmaTaskState::InProgress; + HosSignal signal; + bool owned_by_task_list = true; + bool sleep_allowed = true; + public: + TmaTask(TmaServiceManager *m) : manager(m) { } + virtual ~TmaTask() { } + + u32 GetPriority() const { return this->priority; } + TmaServiceId GetServiceId() const { return this->service_id; } + u32 GetTaskId() const { return this->task_id; } + u32 GetCommand() const { return this->command; } + TmaTaskState GetState() const { return this->state; } + bool GetOwnedByTaskList() const { return this->owned_by_task_list; } + bool GetSleepAllowed() const { return this->sleep_allowed; } + + void SetPriority(u32 p) { this->priority = p; } + void SetServiceId(TmaServiceId s) { this->service_id = s; } + void SetTaskId(u32 i) { this->task_id = i; } + void SetCommand(u32 c) { this->command = c; } + void SetOwnedByTaskList(bool o) { this->owned_by_task_list = o; } + void SetSleepAllowed(bool a) { this->sleep_allowed = a; } + + void Signal() { this->signal.Signal(); } + void ResetSignal() { this->signal.Reset(); } + + void Complete(); + void Cancel(); + + virtual void OnStart(TmaPacket *packet) = 0; + virtual void OnReceivePacket(TmaPacket *packet) = 0; + virtual void OnSendPacket(TmaPacket *packet) = 0; +}; diff --git a/stratosphere/tma/source/tma_task_list.cpp b/stratosphere/tma/source/tma_task_list.cpp new file mode 100644 index 000000000..2c8ac5b48 --- /dev/null +++ b/stratosphere/tma/source/tma_task_list.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include <algorithm> + +#include <switch.h> +#include <stratosphere.hpp> +#include "tma_task_list.hpp" + +TmaTask *TmaTaskList::GetById(u32 task_id) const { + for (u32 i = 0 ; i < TmaTask::NumPriorities; i++) { + for (auto task : this->tasks[i]) { + if (task->GetTaskId() == task_id) { + return task; + } + } + } + return nullptr; +} + +u32 TmaTaskList::GetNumTasks() const { + std::scoped_lock<HosMutex> lk(this->lock); + u32 count = 0; + + for (u32 i = 0 ; i < TmaTask::NumPriorities; i++) { + count += this->tasks[i].size(); + } + + return count; +} + +u32 TmaTaskList::GetNumSleepingTasks() const { + std::scoped_lock<HosMutex> lk(this->lock); + u32 count = 0; + + for (u32 i = 0 ; i < TmaTask::NumPriorities; i++) { + count += this->sleeping_tasks[i].size(); + } + + return count; +} + +bool TmaTaskList::SendPacket(bool connected, TmaPacket *packet) { + std::scoped_lock<HosMutex> lk(this->lock); + + TmaTask *target_task = nullptr; + + /* This loop both finds a target task, and cleans up finished tasks. */ + for (u32 i = 0; i < TmaTask::NumPriorities; i++) { + auto it = this->tasks[i].begin(); + while (it != this->tasks[i].end()) { + auto task = *it; + switch (task->GetState()) { + case TmaTaskState::InProgress: + it++; + if (target_task == nullptr) { + if (connected || IsMetaService(task->GetServiceId())) { + target_task = nullptr; + } + } + break; + case TmaTaskState::Complete: + case TmaTaskState::Canceled: + it = this->tasks[i].erase(it); + if (task->GetOwnedByTaskList()) { + delete task; + } else { + task->Signal(); + } + break; + default: + /* TODO: Panic to fatal? */ + std::abort(); + } + } + } + + if (target_task) { + /* Setup packet. */ + packet->SetContinuation(true); + packet->SetServiceId(target_task->GetServiceId()); + packet->SetTaskId(target_task->GetTaskId()); + packet->SetCommand(target_task->GetCommand()); + packet->ClearOffset(); + + /* Actually handle packet send. */ + target_task->OnSendPacket(packet); + } + + return target_task != nullptr; +} + +bool TmaTaskList::ReceivePacket(TmaPacket *packet) { + std::scoped_lock<HosMutex> lk(this->lock); + + auto task = this->GetById(packet->GetTaskId()); + if (task != nullptr) { + task->OnReceivePacket(packet); + } + return task != nullptr; +} + +void TmaTaskList::Add(TmaTask *task) { + std::scoped_lock<HosMutex> lk(this->lock); + + this->tasks[task->GetPriority()].push_back(task); +} + +void TmaTaskList::Remove(TmaTask *task) { + const auto priority = task->GetPriority(); + + /* Nintendo iterates over all lists instead of just the correct one. */ + /* TODO: Is there actually any reason to do that? */ + auto ind = std::find(this->tasks[priority].begin(), this->tasks[priority].end(), task); + if (ind != this->tasks[priority].end()) { + this->tasks[priority].erase(ind); + return; + } + + /* TODO: Panic to fatal? */ + std::abort(); +} + +void TmaTaskList::Cancel(u32 task_id) { + std::scoped_lock<HosMutex> lk(this->lock); + + auto task = this->GetById(task_id); + if (task != nullptr) { + task->Cancel(); + } +} + +void TmaTaskList::CancelAll() { + std::scoped_lock<HosMutex> lk(this->lock); + + for (u32 i = 0 ; i < TmaTask::NumPriorities; i++) { + for (auto task : this->tasks[i]) { + task->Cancel(); + } + } +} + +void TmaTaskList::Sleep() { + std::scoped_lock<HosMutex> lk(this->lock); + + for (u32 i = 0; i < TmaTask::NumPriorities; i++) { + auto it = this->tasks[i].begin(); + while (it != this->tasks[i].end()) { + auto task = *it; + if (task->GetSleepAllowed()) { + it = this->tasks[i].erase(it); + this->sleeping_tasks[i].push_back(task); + } else { + it++; + } + } + } +} + +void TmaTaskList::Wake() { + std::scoped_lock<HosMutex> lk(this->lock); + + for (u32 i = 0; i < TmaTask::NumPriorities; i++) { + auto it = this->sleeping_tasks[i].begin(); + while (it != this->sleeping_tasks[i].end()) { + auto task = *it; + it = this->sleeping_tasks[i].erase(it); + this->tasks[i].push_back(task); + } + } +} diff --git a/stratosphere/tma/source/tma_task_list.hpp b/stratosphere/tma/source/tma_task_list.hpp new file mode 100644 index 000000000..bfad0e6ca --- /dev/null +++ b/stratosphere/tma/source/tma_task_list.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include <vector> + +#include "tma_conn_service_ids.hpp" +#include "tma_task.hpp" + +class TmaTaskList { + private: + mutable HosMutex lock; + std::vector<TmaTask *> tasks[TmaTask::NumPriorities]; + std::vector<TmaTask *> sleeping_tasks[TmaTask::NumPriorities]; + private: + void Remove(TmaTask *task); + TmaTask *GetById(u32 task_id) const; + public: + TmaTaskList() { } + virtual ~TmaTaskList() { } + + u32 GetNumTasks() const; + u32 GetNumSleepingTasks() const; + + bool SendPacket(bool connected, TmaPacket *packet); + bool ReceivePacket(TmaPacket *packet); + + void Add(TmaTask *task); + void Cancel(u32 task_id); + void CancelAll(); + + void Sleep(); + void Wake(); +}; \ No newline at end of file From bf7dc84893023bd34250c6bb619d8b2508d35746 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 04:16:48 -0800 Subject: [PATCH 286/489] tma: first pass at TmaServiceManager --- .../tma/source/tma_conn_connection.cpp | 20 +- .../tma/source/tma_conn_connection.hpp | 10 + stratosphere/tma/source/tma_conn_packet.hpp | 13 + .../tma/source/tma_conn_usb_connection.cpp | 6 +- stratosphere/tma/source/tma_service.cpp | 4 +- stratosphere/tma/source/tma_service.hpp | 8 +- .../tma/source/tma_service_manager.cpp | 402 ++++++++++++++++++ .../tma/source/tma_service_manager.hpp | 109 +++++ stratosphere/tma/source/tma_task.cpp | 7 +- stratosphere/tma/source/tma_task_list.cpp | 35 ++ stratosphere/tma/source/tma_task_list.hpp | 3 +- 11 files changed, 595 insertions(+), 22 deletions(-) create mode 100644 stratosphere/tma/source/tma_service_manager.cpp create mode 100644 stratosphere/tma/source/tma_service_manager.hpp diff --git a/stratosphere/tma/source/tma_conn_connection.cpp b/stratosphere/tma/source/tma_conn_connection.cpp index 23337b2b2..3cc571365 100644 --- a/stratosphere/tma/source/tma_conn_connection.cpp +++ b/stratosphere/tma/source/tma_conn_connection.cpp @@ -17,25 +17,23 @@ #include <switch.h> #include <stratosphere.hpp> #include "tma_conn_connection.hpp" +#include "tma_service_manager.hpp" /* Packet management. */ TmaPacket *TmaConnection::AllocateSendPacket() { - /* TODO: Service Manager. */ - return new TmaPacket(); + return this->service_manager->AllocateSendPacket(); } TmaPacket *TmaConnection::AllocateRecvPacket() { - /* TODO: Service Manager. */ - return new TmaPacket(); + return this->service_manager->AllocateRecvPacket(); } void TmaConnection::FreePacket(TmaPacket *packet) { - /* TODO: Service Manager. */ - delete packet; + this->service_manager->FreePacket(packet); } void TmaConnection::OnReceivePacket(TmaPacket *packet) { - /* TODO: Service Manager. */ + this->service_manager->OnReceivePacket(packet); } void TmaConnection::OnDisconnected() { @@ -43,7 +41,9 @@ void TmaConnection::OnDisconnected() { std::abort(); } - /* TODO: Service Manager. */ + if (this->service_manager != nullptr) { + this->service_manager->OnDisconnect(); + } this->has_woken_up = false; this->OnConnectionEvent(ConnectionEvent::Disconnected); @@ -56,9 +56,9 @@ void TmaConnection::OnConnectionEvent(ConnectionEvent event) { } void TmaConnection::CancelTasks() { - /* TODO: Service Manager. */ + this->service_manager->CancelTasks(); } void TmaConnection::Tick() { - /* TODO: Service Manager. */ + this->service_manager->Tick(); } diff --git a/stratosphere/tma/source/tma_conn_connection.hpp b/stratosphere/tma/source/tma_conn_connection.hpp index 4cf3cabe3..3c5f39bcd 100644 --- a/stratosphere/tma/source/tma_conn_connection.hpp +++ b/stratosphere/tma/source/tma_conn_connection.hpp @@ -26,6 +26,9 @@ enum class ConnectionEvent : u32 { Disconnected }; + +class TmaServiceManager; + class TmaConnection { protected: HosMutex lock; @@ -33,6 +36,7 @@ class TmaConnection { void *connection_event_arg = nullptr; bool has_woken_up = false; bool is_initialized = false; + TmaServiceManager *service_manager = nullptr; protected: void OnReceivePacket(TmaPacket *packet); void OnDisconnected(); @@ -66,10 +70,16 @@ class TmaConnection { } } + void SetServiceManager(TmaServiceManager *manager) { this->service_manager = manager; } + /* Packet management. */ TmaPacket *AllocateSendPacket(); TmaPacket *AllocateRecvPacket(); void FreePacket(TmaPacket *packet); + + /* Sleep management. */ + bool HasWokenUp() const { return this->has_woken_up; } + void SetWokenUp(bool woke) { this->has_woken_up = woke; } /* For sub-interfaces to implement, connection management. */ virtual void StartListening() { } diff --git a/stratosphere/tma/source/tma_conn_packet.hpp b/stratosphere/tma/source/tma_conn_packet.hpp index 0b2593876..a3df7a3f3 100644 --- a/stratosphere/tma/source/tma_conn_packet.hpp +++ b/stratosphere/tma/source/tma_conn_packet.hpp @@ -43,6 +43,7 @@ class TmaPacket { private: std::unique_ptr<u8[]> buffer = std::make_unique<u8[]>(MaxPacketSize); u32 offset = 0; + HosMessageQueue *free_queue = nullptr; Header *GetHeader() const { return reinterpret_cast<Header *>(buffer.get()); @@ -95,6 +96,14 @@ class TmaPacket { } } + HosMessageQueue *GetFreeQueue() const { + return this->free_queue; + } + + void SetFreeQueue(HosMessageQueue *queue) { + this->free_queue = queue; + } + void SetChecksums() { Header *hdr = GetHeader(); if (hdr->body_len) { @@ -161,6 +170,10 @@ class TmaPacket { this->offset = 0; } + void SetBodyLength() { + GetHeader()->body_len = this->offset; + } + TmaConnResult Write(const void *data, size_t size) { if (size > GetBodyAvailableLength()) { return TmaConnResult::PacketOverflow; diff --git a/stratosphere/tma/source/tma_conn_usb_connection.cpp b/stratosphere/tma/source/tma_conn_usb_connection.cpp index ba6ecd349..ed7c2f707 100644 --- a/stratosphere/tma/source/tma_conn_usb_connection.cpp +++ b/stratosphere/tma/source/tma_conn_usb_connection.cpp @@ -88,7 +88,7 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { res = this_ptr->SendQueryReply(packet); if (!this_ptr->has_woken_up) { - /* TODO: Cancel background work. */ + this_ptr->CancelTasks(); } } break; @@ -100,7 +100,7 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { packet->Read<decltype(host_info)>(host_info); if (!this_ptr->has_woken_up || !host_info.sleeping) { - /* TODO: Cancel background work. */ + this_ptr->CancelTasks(); } } break; @@ -117,7 +117,7 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { this_ptr->SetConnected(false); this_ptr->OnDisconnected(); - /* TODO: Cancel background work. */ + this_ptr->CancelTasks(); } break; default: diff --git a/stratosphere/tma/source/tma_service.cpp b/stratosphere/tma/source/tma_service.cpp index 963d6e6d5..8a70701c8 100644 --- a/stratosphere/tma/source/tma_service.cpp +++ b/stratosphere/tma/source/tma_service.cpp @@ -17,10 +17,10 @@ #include <switch.h> #include <stratosphere.hpp> #include "tma_service.hpp" +#include "tma_service_manager.hpp" u32 TmaService::GetNextTaskId() { - /* TODO: Service Manager */ - return 0; + return this->manager->GetNextTaskId(); } void TmaService::OnSleep() { diff --git a/stratosphere/tma/source/tma_service.hpp b/stratosphere/tma/source/tma_service.hpp index 17ab8215b..e9b0d53e3 100644 --- a/stratosphere/tma/source/tma_service.hpp +++ b/stratosphere/tma/source/tma_service.hpp @@ -31,13 +31,13 @@ class TmaService { const TmaServiceId id; protected: u32 GetNextTaskId(); - virtual TmaTask *NewTask(TmaPacket *packet) = 0; - - virtual void OnSleep(); - virtual void OnWake(); public: TmaService(TmaServiceManager *m, const char *n) : manager(m), service_name(n), id(static_cast<TmaServiceId>(HashServiceName(this->service_name))) { } virtual ~TmaService() { } TmaServiceId GetServiceId() const { return this->id; } + + virtual TmaTask *NewTask(TmaPacket *packet) = 0; + virtual void OnSleep(); + virtual void OnWake(); }; diff --git a/stratosphere/tma/source/tma_service_manager.cpp b/stratosphere/tma/source/tma_service_manager.cpp new file mode 100644 index 000000000..0012944d8 --- /dev/null +++ b/stratosphere/tma/source/tma_service_manager.cpp @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include "tma_service_manager.hpp" + +TmaServiceManager::TmaServiceManager() { + /* Set up queues */ + for (size_t i = 0; i < TmaServiceManager::PacketQueueDepth; i++) { + TmaPacket *packet = nullptr; + + packet = new TmaPacket(); + packet->SetFreeQueue(&this->free_send_packet_queue); + this->free_send_packet_queue.Send(reinterpret_cast<uintptr_t>(packet)); + packet = nullptr; + + packet = new TmaPacket(); + packet->SetFreeQueue(&this->free_recv_packet_queue); + this->free_recv_packet_queue.Send(reinterpret_cast<uintptr_t>(packet)); + packet = nullptr; + } + for (size_t i = 0; i < TmaServiceManager::WorkQueueDepth; i++) { + this->free_work_queue.Send(reinterpret_cast<uintptr_t>(new TmaWorkItem())); + } +} + +TmaServiceManager::~TmaServiceManager() { + /* Destroy queues. */ + TmaPacket *packet = nullptr; + while (this->free_send_packet_queue.TryReceive(reinterpret_cast<uintptr_t *>(&packet))) { + delete packet; + packet = nullptr; + } + while (this->free_recv_packet_queue.TryReceive(reinterpret_cast<uintptr_t *>(&packet))) { + delete packet; + packet = nullptr; + } + + TmaWorkItem *work_item = nullptr; + while (this->free_work_queue.TryReceive(reinterpret_cast<uintptr_t *>(&work_item))) { + delete work_item; + work_item = nullptr; + } + while (this->work_queue.TryReceive(reinterpret_cast<uintptr_t *>(&work_item))) { + delete work_item; + work_item = nullptr; + } +} + +void TmaServiceManager::Initialize() { + this->initialized = true; + this->work_thread.Initialize(TmaServiceManager::WorkThread, this, 0x4000, 0x26); + this->work_thread.Start(); +} + +void TmaServiceManager::Finalize() { + if (this->initialized) { + this->initialized = false; + if (this->connection && this->connection->IsConnected()) { + this->connection->Disconnect(); + } + + /* Signal to work thread to end. */ + this->work_queue.Send(reinterpret_cast<uintptr_t>(nullptr)); + this->work_thread.Join(); + + /* TODO: N tells services that they have no manager here. Do we want to do that? */ + } +} + +void TmaServiceManager::AddWork(TmaWorkType type, TmaTask *task, TmaPacket *packet) { + if (!this->initialized) { + std::abort(); + } + + TmaWorkItem *work_item = nullptr; + this->free_work_queue.Receive(reinterpret_cast<uintptr_t *>(&work_item)); + + work_item->task = task; + work_item->packet = packet; + work_item->work_type = type; +} + +/* Packet management. */ +TmaConnResult TmaServiceManager::SendPacket(TmaPacket *packet) { + TmaConnResult res = TmaConnResult::Disconnected; + + if (this->connection != nullptr) { + res = this->connection->SendPacket(packet); + } + + return res; +} + + +void TmaServiceManager::OnReceivePacket(TmaPacket *packet) { + this->AddWork(TmaWorkType::ReceivePacket, nullptr, packet); +} + +TmaPacket *TmaServiceManager::AllocateSendPacket() { + if (!this->initialized) { + std::abort(); + } + + TmaPacket *packet = nullptr; + this->free_send_packet_queue.Receive(reinterpret_cast<uintptr_t *>(&packet)); + + packet->ClearOffset(); + packet->SetBodyLength(); + + return packet; +} + +TmaPacket *TmaServiceManager::AllocateRecvPacket() { + if (!this->initialized) { + std::abort(); + } + + TmaPacket *packet = nullptr; + this->free_recv_packet_queue.Receive(reinterpret_cast<uintptr_t *>(&packet)); + + packet->ClearOffset(); + + return packet; +} + +void TmaServiceManager::FreePacket(TmaPacket *packet) { + if (!this->initialized) { + std::abort(); + } + + if (packet != nullptr) { + packet->GetFreeQueue()->Send(reinterpret_cast<uintptr_t>(packet)); + } +} + + +/* Service/task management. */ +TmaService *TmaServiceManager::GetServiceById(TmaServiceId id) { + std::scoped_lock<HosMutex> lk(this->lock); + + for (auto srv : this->services) { + if (srv->GetServiceId() == id) { + return srv; + } + } + + return nullptr; +} + +void TmaServiceManager::AddService(TmaService *service) { + std::scoped_lock<HosMutex> lk(this->lock); + + this->services.push_back(service); +} + +void TmaServiceManager::AddTask(TmaTask *task, TmaPacket *packet) { + this->AddWork(TmaWorkType::NewTask, task, packet); +} + +void TmaServiceManager::FreeTask(TmaTask *task) { + this->AddWork(TmaWorkType::FreeTask, task, nullptr); +} + +void TmaServiceManager::CancelTask(u32 task_id) { + if (this->initialized) { + this->task_list.Cancel(task_id); + } +} + +void TmaServiceManager::CancelTasks() { + if (this->initialized) { + this->task_list.CancelAll(); + } +} + +u32 TmaServiceManager::GetNextTaskId() { + while (true) { + u32 id; + { + /* N only uses 16 bits for the task id. We'll use 24. */ + std::scoped_lock<HosMutex> lk(this->lock); + id = (this->next_task_id++) & 0xFFFFFF; + } + + if (this->task_list.IsIdFree(id)) { + return id; + } + } +} + +/* Connection management. */ +void TmaServiceManager::Tick() { + this->AddWork(TmaWorkType::Tick, nullptr, nullptr); +} + +void TmaServiceManager::SetConnection(TmaConnection *conn) { + this->connection = conn; +} + +void TmaServiceManager::OnDisconnect() { + if (!this->initialized) { + std::abort(); + } + + if (!this->GetAsleep()) { + this->disconnect_signal.Reset(); + + this->AddWork(TmaWorkType::Disconnect, nullptr, nullptr); + + /* TODO: why does N wait with a timeout of zero here? */ + this->disconnect_signal.Wait(); + } +} + +void TmaServiceManager::Sleep() { + if (!this->initialized) { + std::abort(); + } + + if (!this->GetAsleep()) { + this->wake_signal.Reset(); + this->sleep_signal.Reset(); + + /* Tell the work thread to stall, wait for ACK. */ + this->AddWork(TmaWorkType::Sleep, nullptr, nullptr); + this->sleep_signal.Wait(); + + this->SetAsleep(true); + } +} + +void TmaServiceManager::Wake(TmaConnection *conn) { + if (this->connection != nullptr) { + std::abort(); + } + if (this->GetAsleep()) { + this->connection = conn; + this->connection->SetWokenUp(true); + this->connection->SetServiceManager(this); + /* Tell the work thread to resume. */ + this->wake_signal.Signal(); + } +} + +bool TmaServiceManager::GetConnected() const { + return this->connection != nullptr && this->connection->IsConnected(); +} + +/* Work thread. */ +void TmaServiceManager::WorkThread(void *_this) { + TmaServiceManager *this_ptr = reinterpret_cast<TmaServiceManager *>(_this); + if (!this_ptr->initialized) { + std::abort(); + } + + while (true) { + /* Receive a work item. */ + TmaWorkItem *work_item = nullptr; + this_ptr->work_queue.Receive(reinterpret_cast<uintptr_t *>(&work_item)); + + if (work_item == nullptr) { + /* We're done. */ + this_ptr->task_list.CancelAll(); + break; + } + + switch (work_item->work_type) { + case TmaWorkType::Tick: + /* HandleTickWork called unconditionally. */ + break; + case TmaWorkType::NewTask: + this_ptr->HandleNewTaskWork(work_item); + break; + case TmaWorkType::FreeTask: + this_ptr->HandleFreeTaskWork(work_item); + break; + case TmaWorkType::ReceivePacket: + this_ptr->HandleReceivePacketWork(work_item); + break; + case TmaWorkType::Disconnect: + this_ptr->HandleDisconnectWork(); + break; + case TmaWorkType::Sleep: + this_ptr->HandleSleepWork(); + break; + case TmaWorkType::None: + default: + std::abort(); + break; + } + + this_ptr->free_work_queue.Send(reinterpret_cast<uintptr_t>(work_item)); + this_ptr->HandleTickWork(); + } +} + +void TmaServiceManager::HandleNewTaskWork(TmaWorkItem *work_item) { + this->task_list.Add(work_item->task); + if (this->GetConnected()) { + if (work_item->packet != nullptr) { + this->SendPacket(work_item->packet); + } + } else { + work_item->task->Cancel(); + this->FreePacket(work_item->packet); + } +} + +void TmaServiceManager::HandleFreeTaskWork(TmaWorkItem *work_item) { + delete work_item->task; +} + +void TmaServiceManager::HandleReceivePacketWork(TmaWorkItem *work_item) { + /* Handle continuation packets. */ + if (work_item->packet->GetContinuation()) { + this->task_list.ReceivePacket(work_item->packet); + return; + } + + /* Make a new task for the packet. */ + TmaService *srv = this->GetServiceById(work_item->packet->GetServiceId()); + if (srv != nullptr) { + TmaTask *task = srv->NewTask(work_item->packet); + if (task != nullptr) { + this->task_list.Add(task); + } + } +} + +void TmaServiceManager::HandleTickWork() { + if (this->connection == nullptr) { + std::abort(); + } + + /* N does this kind of manual cleanup if send isn't called. */ + /* It's pretty gross, but in lieu of a better idea... */ + bool needs_manual_cleanup = true; + + TmaPacket *packet = nullptr; + + while (this->connection != nullptr && this->free_send_packet_queue.TryReceive(reinterpret_cast<uintptr_t *>(&packet))) { + needs_manual_cleanup = false; + + if (this->task_list.SendPacket(this->GetConnected(), packet)) { + if (this->SendPacket(packet) != TmaConnResult::Success) { + break; + } + } else { + this->FreePacket(packet); + break; + } + } + + if (needs_manual_cleanup) { + this->task_list.CleanupDoneTasks(); + } +} + +void TmaServiceManager::HandleDisconnectWork() { + this->task_list.CancelAll(); + this->disconnect_signal.Signal(); +} + +void TmaServiceManager::HandleSleepWork() { + /* Put the task list to sleep. */ + this->task_list.Sleep(); + + /* Put services to sleep. */ + for (auto srv : this->services) { + srv->OnSleep(); + } + + /* Signal to main thread that we're sleeping. */ + this->sleep_signal.Signal(); + /* Wait for us to wake up. */ + this->wake_signal.Wait(); + + /* We're awake now... */ + + /* Wake up services. */ + for (auto srv : this->services) { + srv->OnWake(); + } + + /* Wake up the task list. */ + this->task_list.Wake(); +} diff --git a/stratosphere/tma/source/tma_service_manager.hpp b/stratosphere/tma/source/tma_service_manager.hpp new file mode 100644 index 000000000..ac6ccc5e3 --- /dev/null +++ b/stratosphere/tma/source/tma_service_manager.hpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "tma_conn_service_ids.hpp" +#include "tma_conn_packet.hpp" +#include "tma_task.hpp" +#include "tma_service.hpp" +#include "tma_task_list.hpp" +#include "tma_conn_connection.hpp" + +enum class TmaWorkType : u32 { + None, + NewTask, + FreeTask, + ReceivePacket, + Tick, + Disconnect, + Sleep, +}; + +struct TmaWorkItem { + TmaTask *task; + TmaPacket *packet; + TmaWorkType work_type; +}; + +class TmaServiceManager { + public: + static constexpr size_t PacketQueueDepth = 0x8; + static constexpr size_t WorkQueueDepth = 0x80; + private: + HosMutex lock; + bool initialized = false; + TmaTaskList task_list; + HosThread work_thread; + std::vector<TmaService *> services; + TmaConnection *connection = nullptr; + u32 next_task_id = 0; + + /* Work queues. */ + HosMessageQueue free_send_packet_queue = HosMessageQueue(PacketQueueDepth); + HosMessageQueue free_recv_packet_queue = HosMessageQueue(PacketQueueDepth); + HosMessageQueue work_queue = HosMessageQueue(WorkQueueDepth); + HosMessageQueue free_work_queue = HosMessageQueue(WorkQueueDepth); + + /* Sleep management. */ + HosSignal disconnect_signal; + HosSignal wake_signal; + HosSignal sleep_signal; + bool asleep = false; + private: + static void WorkThread(void *arg); + void AddWork(TmaWorkType type, TmaTask *task, TmaPacket *packet); + void HandleNewTaskWork(TmaWorkItem *work_item); + void HandleFreeTaskWork(TmaWorkItem *work_item); + void HandleReceivePacketWork(TmaWorkItem *work_item); + void HandleTickWork(); + void HandleDisconnectWork(); + void HandleSleepWork(); + + void SetAsleep(bool s) { this->asleep = s; } + public: + TmaServiceManager(); + virtual ~TmaServiceManager(); + void Initialize(); + void Finalize(); + + /* Packet management. */ + TmaConnResult SendPacket(TmaPacket *packet); + void OnReceivePacket(TmaPacket *packet); + TmaPacket *AllocateSendPacket(); + TmaPacket *AllocateRecvPacket(); + void FreePacket(TmaPacket *packet); + + /* Service/task management. */ + TmaService *GetServiceById(TmaServiceId id); + void AddService(TmaService *service); + void AddTask(TmaTask *task, TmaPacket *packet); + void FreeTask(TmaTask *task); + void CancelTask(u32 task_id); + void CancelTasks(); + u32 GetNextTaskId(); + + /* Connection management. */ + void Tick(); + void SetConnection(TmaConnection *conn); + void OnDisconnect(); + void Sleep(); + void Wake(TmaConnection *conn); + bool GetAsleep() const { return this->asleep; } + bool GetConnected() const; +}; diff --git a/stratosphere/tma/source/tma_task.cpp b/stratosphere/tma/source/tma_task.cpp index 5c9c863b6..a9450be76 100644 --- a/stratosphere/tma/source/tma_task.cpp +++ b/stratosphere/tma/source/tma_task.cpp @@ -17,13 +17,16 @@ #include <switch.h> #include <stratosphere.hpp> #include "tma_task.hpp" +#include "tma_service_manager.hpp" void TmaTask::Complete() { - /* TODO: Service manager */ + /* TODO: Set packet state */ this->state = TmaTaskState::Complete; + this->manager->Tick(); } void TmaTask::Cancel() { - /* TODO: Service manager */ + /* TODO: Set packet state */ this->state = TmaTaskState::Canceled; + this->manager->Tick(); } \ No newline at end of file diff --git a/stratosphere/tma/source/tma_task_list.cpp b/stratosphere/tma/source/tma_task_list.cpp index 2c8ac5b48..2cb28b487 100644 --- a/stratosphere/tma/source/tma_task_list.cpp +++ b/stratosphere/tma/source/tma_task_list.cpp @@ -52,6 +52,11 @@ u32 TmaTaskList::GetNumSleepingTasks() const { return count; } +bool TmaTaskList::IsIdFree(u32 task_id) const { + std::scoped_lock<HosMutex> lk(this->lock); + return GetById(task_id) == nullptr; +} + bool TmaTaskList::SendPacket(bool connected, TmaPacket *packet) { std::scoped_lock<HosMutex> lk(this->lock); @@ -112,6 +117,36 @@ bool TmaTaskList::ReceivePacket(TmaPacket *packet) { return task != nullptr; } + +void TmaTaskList::CleanupDoneTasks() { + std::scoped_lock<HosMutex> lk(this->lock); + + /* Clean up all tasks in Complete/Canceled state. */ + for (u32 i = 0; i < TmaTask::NumPriorities; i++) { + auto it = this->tasks[i].begin(); + while (it != this->tasks[i].end()) { + auto task = *it; + switch (task->GetState()) { + case TmaTaskState::InProgress: + it++; + break; + case TmaTaskState::Complete: + case TmaTaskState::Canceled: + it = this->tasks[i].erase(it); + if (task->GetOwnedByTaskList()) { + delete task; + } else { + task->Signal(); + } + break; + default: + /* TODO: Panic to fatal? */ + std::abort(); + } + } + } +} + void TmaTaskList::Add(TmaTask *task) { std::scoped_lock<HosMutex> lk(this->lock); diff --git a/stratosphere/tma/source/tma_task_list.hpp b/stratosphere/tma/source/tma_task_list.hpp index bfad0e6ca..e29ddb274 100644 --- a/stratosphere/tma/source/tma_task_list.hpp +++ b/stratosphere/tma/source/tma_task_list.hpp @@ -36,10 +36,11 @@ class TmaTaskList { u32 GetNumTasks() const; u32 GetNumSleepingTasks() const; + bool IsIdFree(u32 task_id) const; bool SendPacket(bool connected, TmaPacket *packet); bool ReceivePacket(TmaPacket *packet); - + void CleanupDoneTasks(); void Add(TmaTask *task); void Cancel(u32 task_id); void CancelAll(); From 37e5a8544bea9486965f66f8750c9046944ae697 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 05:31:45 -0800 Subject: [PATCH 287/489] tma: Add target initialization/power management logic --- stratosphere/tma/source/tma_main.cpp | 46 +--- stratosphere/tma/source/tma_power_manager.cpp | 69 ++++++ stratosphere/tma/source/tma_power_manager.hpp | 25 ++ stratosphere/tma/source/tma_target.cpp | 219 ++++++++++++++++++ stratosphere/tma/source/tma_target.hpp | 25 ++ 5 files changed, 344 insertions(+), 40 deletions(-) create mode 100644 stratosphere/tma/source/tma_power_manager.cpp create mode 100644 stratosphere/tma/source/tma_power_manager.hpp create mode 100644 stratosphere/tma/source/tma_target.cpp create mode 100644 stratosphere/tma/source/tma_target.hpp diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp index d1b179d4c..fb1491cc3 100644 --- a/stratosphere/tma/source/tma_main.cpp +++ b/stratosphere/tma/source/tma_main.cpp @@ -23,7 +23,7 @@ #include <atmosphere.h> #include <stratosphere.hpp> -#include "tma_conn_usb_connection.hpp" +#include "tma_target.hpp" extern "C" { extern u32 __start__; @@ -74,52 +74,18 @@ void __appExit(void) { smExit(); } -void PmThread(void *arg) { - /* Setup psc module. */ - Result rc; - PscPmModule tma_module = {0}; - if (R_FAILED((rc = pscGetPmModule(&tma_module, 0x1E, nullptr, 0, true)))) { - fatalSimple(rc); - } - - /* For now, just do what dummy tma does -- loop forever, acknowledging everything. */ - while (true) { - if (R_FAILED((rc = eventWait(&tma_module.event, U64_MAX)))) { - fatalSimple(rc); - } - - PscPmState state; - u32 flags; - if (R_FAILED((rc = pscPmModuleGetRequest(&tma_module, &state, &flags)))) { - fatalSimple(rc); - } - - - if (R_FAILED((rc = pscPmModuleAcknowledge(&tma_module, state)))) { - fatalSimple(rc); - } - } -} - int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); - Thread pm_thread = {0}; - if (R_FAILED(threadCreate(&pm_thread, &PmThread, NULL, 0x4000, 0x15, 0))) { - /* TODO: Panic. */ - } - if (R_FAILED(threadStart(&pm_thread))) { - /* TODO: Panic. */ - } - - TmaUsbConnection::InitializeComms(); - auto conn = new TmaUsbConnection(); - conn->Initialize(); + + /* This will initialize the target. */ + TmaTarget::Initialize(); while (true) { svcSleepThread(10000000UL); } - + + TmaTarget::Finalize(); return 0; } diff --git a/stratosphere/tma/source/tma_power_manager.cpp b/stratosphere/tma/source/tma_power_manager.cpp new file mode 100644 index 000000000..f7c04a475 --- /dev/null +++ b/stratosphere/tma/source/tma_power_manager.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include "tma_power_manager.hpp" + +static constexpr u16 PscPmModuleId_Usb = 0x04; +static constexpr u16 PscPmModuleId_Pcie = 0x13; +static constexpr u16 PscPmModuleId_Tma = 0x1E; + +static const u16 g_tma_pm_dependencies[] = { + PscPmModuleId_Pcie, + PscPmModuleId_Usb, +}; + +static void (*g_pm_callback)(PscPmState, u32) = nullptr; +static HosThread g_pm_thread; + +static void PowerManagerThread(void *arg) { + /* Setup psc module. */ + Result rc; + PscPmModule tma_module = {0}; + if (R_FAILED((rc = pscGetPmModule(&tma_module, PscPmModuleId_Tma, g_tma_pm_dependencies, sizeof(g_tma_pm_dependencies)/sizeof(u16), true)))) { + fatalSimple(rc); + } + + /* For now, just do what dummy tma does -- loop forever, acknowledging everything. */ + while (true) { + if (R_FAILED((rc = eventWait(&tma_module.event, U64_MAX)))) { + fatalSimple(rc); + } + + PscPmState state; + u32 flags; + if (R_FAILED((rc = pscPmModuleGetRequest(&tma_module, &state, &flags)))) { + fatalSimple(rc); + } + + g_pm_callback(state, flags); + + if (R_FAILED((rc = pscPmModuleAcknowledge(&tma_module, state)))) { + fatalSimple(rc); + } + } +} + +void TmaPowerManager::Initialize(void (*callback)(PscPmState, u32)) { + g_pm_callback = callback; + g_pm_thread.Initialize(PowerManagerThread, nullptr, 0x4000, 0x15); + g_pm_thread.Start(); +} + +void TmaPowerManager::Finalize() { + /* TODO */ +} \ No newline at end of file diff --git a/stratosphere/tma/source/tma_power_manager.hpp b/stratosphere/tma/source/tma_power_manager.hpp new file mode 100644 index 000000000..6ca0e4ad8 --- /dev/null +++ b/stratosphere/tma/source/tma_power_manager.hpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +class TmaPowerManager { + public: + static void Initialize(void (*callback)(PscPmState, u32)); + static void Finalize(); +}; diff --git a/stratosphere/tma/source/tma_target.cpp b/stratosphere/tma/source/tma_target.cpp new file mode 100644 index 000000000..234345da1 --- /dev/null +++ b/stratosphere/tma/source/tma_target.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> + +#include "tma_conn_connection.hpp" +#include "tma_conn_usb_connection.hpp" + +#include "tma_service_manager.hpp" +#include "tma_power_manager.hpp" + +#include "tma_target.hpp" + +struct TmaTargetConfig { + char configuration_id1[0x80]; + char serial_number[0x80]; +}; + +static TmaConnection *g_active_connection = nullptr; +static TmaServiceManager *g_service_manager = nullptr; +static HosMutex g_connection_event_mutex; +static bool g_has_woken_up = false; +static bool g_signal_on_disconnect = false; + +static TmaUsbConnection *g_usb_connection = nullptr; + +static TmaTargetConfig g_target_config = { + "Unknown", + "SerialNumber", +}; + +static void RefreshTargetConfig() { + setsysInitialize(); + + /* TODO: setsysGetConfigurationId1(&g_target_config.configuration_id1); */ + + g_target_config.serial_number[0] = 0; + setsysGetSerialNumber(g_target_config.serial_number); + + setsysExit(); +} + +static void InitializeServices() { + g_service_manager->Initialize(); +} + +static void FinalizeServices() { + g_service_manager->Finalize(); +} + +static void SetActiveConnection(TmaConnection *connection) { + if (g_active_connection != connection) { + if (g_active_connection != nullptr) { + FinalizeServices(); + g_service_manager->SetConnection(nullptr); + g_active_connection->Disconnect(); + g_active_connection = nullptr; + } + + if (connection != nullptr) { + g_active_connection = connection; + InitializeServices(); + g_service_manager->SetConnection(g_active_connection); + g_active_connection->SetServiceManager(g_service_manager); + } + } +} + +static void OnConnectionEvent(void *arg, ConnectionEvent evt) { + std::scoped_lock<HosMutex> lk(g_connection_event_mutex); + + switch (evt) { + case ConnectionEvent::Connected: + { + bool has_active_connection = false; + g_has_woken_up = false; + + if (arg == g_usb_connection) { + SetActiveConnection(g_usb_connection); + has_active_connection = true; + } + + if (has_active_connection) { + /* TODO: Signal connected */ + } + } + break; + case ConnectionEvent::Disconnected: + if (g_signal_on_disconnect) { + /* TODO: Signal disconnected */ + } + break; + default: + std::abort(); + break; + } +} + +static void Wake() { + if (g_service_manager->GetAsleep()) { + g_has_woken_up = true; + + /* N checks what kind of connection to use here. For now, we only use USB. */ + TmaUsbConnection::InitializeComms(); + g_usb_connection = new TmaUsbConnection(); + g_usb_connection->SetConnectionEventCallback(OnConnectionEvent, g_usb_connection); + g_usb_connection->Initialize(); + SetActiveConnection(g_usb_connection); + + g_service_manager->Wake(g_active_connection); + } +} + +static void Sleep() { + if (!g_service_manager->GetAsleep()) { + if (g_active_connection->IsConnected()) { + /* TODO: Send a packet saying we're going to sleep. */ + } + + g_service_manager->Sleep(); + g_service_manager->SetConnection(nullptr); + g_active_connection->Disconnect(); + g_active_connection = nullptr; + g_service_manager->CancelTasks(); + + if (g_usb_connection != nullptr) { + g_usb_connection->Finalize(); + delete g_usb_connection; + g_usb_connection = nullptr; + TmaUsbConnection::FinalizeComms(); + } + } +} + +static void OnPowerManagementEvent(PscPmState state, u32 flags) { + switch (state) { + case PscPmState_Awake: + { + Wake(); + } + break; + case PscPmState_ReadyAwaken: + { + if (g_service_manager->GetAsleep()) { + Wake(); + { + /* Try to restore a connection. */ + bool connected = g_service_manager->GetConnected(); + + /* N uses a seven-second timeout, here. */ + TimeoutHelper timeout_helper(7000000000ULL); + while (!connected && !timeout_helper.TimedOut()) { + connected = g_service_manager->GetConnected(); + if (!connected) { + /* Sleep for 1ms. */ + svcSleepThread(1000000ULL); + } + } + if (!connected) { + /* TODO: Signal disconnected */ + } + } + } + } + break; + case PscPmState_ReadySleep: + { + Sleep(); + } + break; + default: + /* Don't handle ReadySleepCritical/ReadyAwakenCritical/ReadyShutdown */ + break; + } +} + +void TmaTarget::Initialize() { + /* Get current thread priority. */ + u32 cur_prio; + if (R_FAILED(svcGetThreadPriority(&cur_prio, CUR_THREAD_HANDLE))) { + std::abort(); + } + + g_active_connection = nullptr; + g_service_manager = new TmaServiceManager(); + + RefreshTargetConfig(); + + /* N checks what kind of connection to use here. For now, we only use USB. */ + TmaUsbConnection::InitializeComms(); + g_usb_connection = new TmaUsbConnection(); + g_usb_connection->SetConnectionEventCallback(OnConnectionEvent, g_usb_connection); + g_usb_connection->Initialize(); + SetActiveConnection(g_usb_connection); + + /* TODO: Initialize connection events */ + + /* TODO: Initialize IPC services */ + + TmaPowerManager::Initialize(OnPowerManagementEvent); +} + +void TmaTarget::Finalize() { + /* TODO: Is implementing this actually worthwhile? It will never be called in practice... */ +} diff --git a/stratosphere/tma/source/tma_target.hpp b/stratosphere/tma/source/tma_target.hpp new file mode 100644 index 000000000..73b81e857 --- /dev/null +++ b/stratosphere/tma/source/tma_target.hpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +class TmaTarget { + public: + static void Initialize(); + static void Finalize(); +}; From d875d84d2d53a717b68d8d4852ccaf8dac896de8 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 07:11:06 -0800 Subject: [PATCH 288/489] tma: Fix sleep/wake semantics, now tested on hardware. --- stratosphere/tma/client/UsbConnection.py | 1 + stratosphere/tma/source/tma_power_manager.cpp | 1 - stratosphere/tma/source/tma_service_manager.cpp | 2 ++ stratosphere/tma/source/tma_target.cpp | 9 ++++++++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/stratosphere/tma/client/UsbConnection.py b/stratosphere/tma/client/UsbConnection.py index a7b009ad6..a0ec84e38 100644 --- a/stratosphere/tma/client/UsbConnection.py +++ b/stratosphere/tma/client/UsbConnection.py @@ -80,6 +80,7 @@ class UsbConnection(UsbInterface): try: # Perform Query + Connection handshake + print 'Performing handshake...' self.intf.send_packet(Packet().set_service(ServiceId.USB_QUERY_TARGET)) query_resp = self.intf.read_packet() print 'Found Switch, Protocol version 0x%x' % query_resp.read_u32() diff --git a/stratosphere/tma/source/tma_power_manager.cpp b/stratosphere/tma/source/tma_power_manager.cpp index f7c04a475..423b7cb90 100644 --- a/stratosphere/tma/source/tma_power_manager.cpp +++ b/stratosphere/tma/source/tma_power_manager.cpp @@ -23,7 +23,6 @@ static constexpr u16 PscPmModuleId_Pcie = 0x13; static constexpr u16 PscPmModuleId_Tma = 0x1E; static const u16 g_tma_pm_dependencies[] = { - PscPmModuleId_Pcie, PscPmModuleId_Usb, }; diff --git a/stratosphere/tma/source/tma_service_manager.cpp b/stratosphere/tma/source/tma_service_manager.cpp index 0012944d8..2d2b18cec 100644 --- a/stratosphere/tma/source/tma_service_manager.cpp +++ b/stratosphere/tma/source/tma_service_manager.cpp @@ -93,6 +93,7 @@ void TmaServiceManager::AddWork(TmaWorkType type, TmaTask *task, TmaPacket *pack work_item->task = task; work_item->packet = packet; work_item->work_type = type; + this->work_queue.Send(reinterpret_cast<uintptr_t>(work_item)); } /* Packet management. */ @@ -391,6 +392,7 @@ void TmaServiceManager::HandleSleepWork() { this->wake_signal.Wait(); /* We're awake now... */ + this->SetAsleep(false); /* Wake up services. */ for (auto srv : this->services) { diff --git a/stratosphere/tma/source/tma_target.cpp b/stratosphere/tma/source/tma_target.cpp index 234345da1..227975c70 100644 --- a/stratosphere/tma/source/tma_target.cpp +++ b/stratosphere/tma/source/tma_target.cpp @@ -34,6 +34,7 @@ static TmaConnection *g_active_connection = nullptr; static TmaServiceManager *g_service_manager = nullptr; static HosMutex g_connection_event_mutex; static bool g_has_woken_up = false; +static bool g_connected_before_sleep = false; static bool g_signal_on_disconnect = false; static TmaUsbConnection *g_usb_connection = nullptr; @@ -119,7 +120,7 @@ static void Wake() { g_usb_connection = new TmaUsbConnection(); g_usb_connection->SetConnectionEventCallback(OnConnectionEvent, g_usb_connection); g_usb_connection->Initialize(); - SetActiveConnection(g_usb_connection); + g_active_connection = g_usb_connection; g_service_manager->Wake(g_active_connection); } @@ -128,7 +129,11 @@ static void Wake() { static void Sleep() { if (!g_service_manager->GetAsleep()) { if (g_active_connection->IsConnected()) { + g_connected_before_sleep = true; + /* TODO: Send a packet saying we're going to sleep. */ + } else { + g_connected_before_sleep = false; } g_service_manager->Sleep(); @@ -157,6 +162,7 @@ static void OnPowerManagementEvent(PscPmState state, u32 flags) { { if (g_service_manager->GetAsleep()) { Wake(); + if (g_connected_before_sleep) { /* Try to restore a connection. */ bool connected = g_service_manager->GetConnected(); @@ -170,6 +176,7 @@ static void OnPowerManagementEvent(PscPmState state, u32 flags) { svcSleepThread(1000000ULL); } } + if (!connected) { /* TODO: Signal disconnected */ } From 24be9ffc57de237962f85e7846eb71976d1bf12a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 08:33:56 -0800 Subject: [PATCH 289/489] tma: Add working AtmosphereTestService (echoes As) --- stratosphere/tma/Makefile | 2 +- stratosphere/tma/client/Main.py | 5 ++ stratosphere/tma/client/ServiceId.py | 2 + .../source/test/atmosphere_test_service.cpp | 31 +++++++ .../source/test/atmosphere_test_service.hpp | 30 +++++++ .../tma/source/test/atmosphere_test_task.cpp | 36 ++++++++ .../tma/source/test/atmosphere_test_task.hpp | 33 ++++++++ .../tma/source/tma_conn_usb_connection.cpp | 84 ++++++++++--------- .../tma/source/tma_service_manager.cpp | 2 + stratosphere/tma/source/tma_target.cpp | 4 + stratosphere/tma/source/tma_task.cpp | 9 +- stratosphere/tma/source/tma_task.hpp | 3 + stratosphere/tma/source/tma_task_list.cpp | 4 +- 13 files changed, 200 insertions(+), 45 deletions(-) create mode 100644 stratosphere/tma/source/test/atmosphere_test_service.cpp create mode 100644 stratosphere/tma/source/test/atmosphere_test_service.hpp create mode 100644 stratosphere/tma/source/test/atmosphere_test_task.cpp create mode 100644 stratosphere/tma/source/test/atmosphere_test_task.hpp diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile index 7dc12f262..9d0408a23 100644 --- a/stratosphere/tma/Makefile +++ b/stratosphere/tma/Makefile @@ -19,7 +19,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := source +SOURCES := source source/test DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src diff --git a/stratosphere/tma/client/Main.py b/stratosphere/tma/client/Main.py index b1469a1e1..3ea150608 100644 --- a/stratosphere/tma/client/Main.py +++ b/stratosphere/tma/client/Main.py @@ -12,12 +12,17 @@ # You should have received a copy of the GNU General Public License from UsbConnection import UsbConnection import sys, time +from Packet import Packet +import ServiceId def main(argc, argv): with UsbConnection(None) as c: print 'Waiting for connection...' c.wait_connected() print 'Connected!' + c.intf.send_packet(Packet().set_service(ServiceId.ATMOSPHERE_TEST_SERVICE).set_task(0x01000000).write_u32(0x40)) + resp = c.intf.read_packet() + print resp.body return 0 if __name__ == '__main__': diff --git a/stratosphere/tma/client/ServiceId.py b/stratosphere/tma/client/ServiceId.py index 5207d2ae3..27b314f93 100644 --- a/stratosphere/tma/client/ServiceId.py +++ b/stratosphere/tma/client/ServiceId.py @@ -24,4 +24,6 @@ USB_SEND_HOST_INFO = hash("USBSendHostInfo") USB_CONNECT = hash("USBConnect") USB_DISCONNECT = hash("USBDisconnect") +ATMOSPHERE_TEST_SERVICE = hash("AtmosphereTestService") + \ No newline at end of file diff --git a/stratosphere/tma/source/test/atmosphere_test_service.cpp b/stratosphere/tma/source/test/atmosphere_test_service.cpp new file mode 100644 index 000000000..7433882fa --- /dev/null +++ b/stratosphere/tma/source/test/atmosphere_test_service.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> + +#include "atmosphere_test_service.hpp" +#include "atmosphere_test_task.hpp" + +TmaTask *AtmosphereTestService::NewTask(TmaPacket *packet) { + auto new_task = new AtmosphereTestTask(this->manager); + new_task->SetServiceId(this->GetServiceId()); + new_task->SetTaskId(packet->GetTaskId()); + new_task->OnStart(packet); + new_task->SetNeedsPackets(true); + + return new_task; +} diff --git a/stratosphere/tma/source/test/atmosphere_test_service.hpp b/stratosphere/tma/source/test/atmosphere_test_service.hpp new file mode 100644 index 000000000..c01e7e5cb --- /dev/null +++ b/stratosphere/tma/source/test/atmosphere_test_service.hpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "../tma_conn_service_ids.hpp" +#include "../tma_service.hpp" + +class AtmosphereTestService : public TmaService { + public: + AtmosphereTestService(TmaServiceManager *m) : TmaService(m, "AtmosphereTestService") { } + virtual ~AtmosphereTestService() { } + + virtual TmaTask *NewTask(TmaPacket *packet) override; +}; \ No newline at end of file diff --git a/stratosphere/tma/source/test/atmosphere_test_task.cpp b/stratosphere/tma/source/test/atmosphere_test_task.cpp new file mode 100644 index 000000000..57cb6078b --- /dev/null +++ b/stratosphere/tma/source/test/atmosphere_test_task.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> + +#include "atmosphere_test_task.hpp" + +void AtmosphereTestTask::OnStart(TmaPacket *packet) { + packet->Read<u32>(this->arg); +} + +void AtmosphereTestTask::OnReceivePacket(TmaPacket *packet) { + std::abort(); +} + +void AtmosphereTestTask::OnSendPacket(TmaPacket *packet) { + for (size_t i = 0; i < this->arg && i < 0x100; i++) { + packet->Write<u8>('A'); + } + + this->Complete(); +} \ No newline at end of file diff --git a/stratosphere/tma/source/test/atmosphere_test_task.hpp b/stratosphere/tma/source/test/atmosphere_test_task.hpp new file mode 100644 index 000000000..ebbb62b03 --- /dev/null +++ b/stratosphere/tma/source/test/atmosphere_test_task.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "../tma_task.hpp" + +class AtmosphereTestTask : public TmaTask { + private: + u32 arg; + public: + AtmosphereTestTask(TmaServiceManager *m) : TmaTask(m) { } + virtual ~AtmosphereTestTask() { } + + virtual void OnStart(TmaPacket *packet) override; + virtual void OnReceivePacket(TmaPacket *packet) override; + virtual void OnSendPacket(TmaPacket *packet) override; +}; diff --git a/stratosphere/tma/source/tma_conn_usb_connection.cpp b/stratosphere/tma/source/tma_conn_usb_connection.cpp index ed7c2f707..d7c89199f 100644 --- a/stratosphere/tma/source/tma_conn_usb_connection.cpp +++ b/stratosphere/tma/source/tma_conn_usb_connection.cpp @@ -81,49 +81,53 @@ void TmaUsbConnection::RecvThreadFunc(void *arg) { res = TmaUsbComms::ReceivePacket(packet); if (res == TmaConnResult::Success) { - switch (packet->GetServiceId()) { - case TmaServiceId::UsbQueryTarget: { - this_ptr->SetConnected(false); - - res = this_ptr->SendQueryReply(packet); - - if (!this_ptr->has_woken_up) { - this_ptr->CancelTasks(); + if (!IsMetaService(packet->GetServiceId())) { + this_ptr->OnReceivePacket(packet); + } else { + switch (packet->GetServiceId()) { + case TmaServiceId::UsbQueryTarget: { + this_ptr->SetConnected(false); + + res = this_ptr->SendQueryReply(packet); + + if (!this_ptr->has_woken_up) { + this_ptr->CancelTasks(); + } } - } - break; - case TmaServiceId::UsbSendHostInfo: { - struct { - u32 version; - u32 sleeping; - } host_info; - packet->Read<decltype(host_info)>(host_info); - - if (!this_ptr->has_woken_up || !host_info.sleeping) { - this_ptr->CancelTasks(); - } - } - break; - case TmaServiceId::UsbConnect: { - res = this_ptr->SendQueryReply(packet); - - if (res == TmaConnResult::Success) { - this_ptr->SetConnected(true); - this_ptr->OnConnectionEvent(ConnectionEvent::Connected); - } - } - break; - case TmaServiceId::UsbDisconnect: { - this_ptr->SetConnected(false); - this_ptr->OnDisconnected(); - - this_ptr->CancelTasks(); - } - break; - default: break; + case TmaServiceId::UsbSendHostInfo: { + struct { + u32 version; + u32 sleeping; + } host_info; + packet->Read<decltype(host_info)>(host_info); + + if (!this_ptr->has_woken_up || !host_info.sleeping) { + this_ptr->CancelTasks(); + } + } + break; + case TmaServiceId::UsbConnect: { + res = this_ptr->SendQueryReply(packet); + + if (res == TmaConnResult::Success) { + this_ptr->SetConnected(true); + this_ptr->OnConnectionEvent(ConnectionEvent::Connected); + } + } + break; + case TmaServiceId::UsbDisconnect: { + this_ptr->SetConnected(false); + this_ptr->OnDisconnected(); + + this_ptr->CancelTasks(); + } + break; + default: + break; + } + this_ptr->FreePacket(packet); } - this_ptr->FreePacket(packet); } else { this_ptr->FreePacket(packet); } diff --git a/stratosphere/tma/source/tma_service_manager.cpp b/stratosphere/tma/source/tma_service_manager.cpp index 2d2b18cec..e684f7e0c 100644 --- a/stratosphere/tma/source/tma_service_manager.cpp +++ b/stratosphere/tma/source/tma_service_manager.cpp @@ -327,6 +327,8 @@ void TmaServiceManager::HandleFreeTaskWork(TmaWorkItem *work_item) { } void TmaServiceManager::HandleReceivePacketWork(TmaWorkItem *work_item) { + ON_SCOPE_EXIT { this->FreePacket(work_item->packet); }; + /* Handle continuation packets. */ if (work_item->packet->GetContinuation()) { this->task_list.ReceivePacket(work_item->packet); diff --git a/stratosphere/tma/source/tma_target.cpp b/stratosphere/tma/source/tma_target.cpp index 227975c70..9873d952d 100644 --- a/stratosphere/tma/source/tma_target.cpp +++ b/stratosphere/tma/source/tma_target.cpp @@ -25,6 +25,8 @@ #include "tma_target.hpp" +#include "test/atmosphere_test_service.hpp" + struct TmaTargetConfig { char configuration_id1[0x80]; char serial_number[0x80]; @@ -204,6 +206,8 @@ void TmaTarget::Initialize() { g_active_connection = nullptr; g_service_manager = new TmaServiceManager(); + /* TODO: Make this better. */ + g_service_manager->AddService(new AtmosphereTestService(g_service_manager)); RefreshTargetConfig(); diff --git a/stratosphere/tma/source/tma_task.cpp b/stratosphere/tma/source/tma_task.cpp index a9450be76..6133b5c5e 100644 --- a/stratosphere/tma/source/tma_task.cpp +++ b/stratosphere/tma/source/tma_task.cpp @@ -19,14 +19,19 @@ #include "tma_task.hpp" #include "tma_service_manager.hpp" +void TmaTask::SetNeedsPackets(bool n) { + this->needs_packets = n; + this->manager->Tick(); +} + void TmaTask::Complete() { - /* TODO: Set packet state */ + SetNeedsPackets(false); this->state = TmaTaskState::Complete; this->manager->Tick(); } void TmaTask::Cancel() { - /* TODO: Set packet state */ + SetNeedsPackets(false); this->state = TmaTaskState::Canceled; this->manager->Tick(); } \ No newline at end of file diff --git a/stratosphere/tma/source/tma_task.hpp b/stratosphere/tma/source/tma_task.hpp index 9e115893f..686a7a50d 100644 --- a/stratosphere/tma/source/tma_task.hpp +++ b/stratosphere/tma/source/tma_task.hpp @@ -43,6 +43,7 @@ class TmaTask { HosSignal signal; bool owned_by_task_list = true; bool sleep_allowed = true; + bool needs_packets = false; public: TmaTask(TmaServiceManager *m) : manager(m) { } virtual ~TmaTask() { } @@ -54,6 +55,7 @@ class TmaTask { TmaTaskState GetState() const { return this->state; } bool GetOwnedByTaskList() const { return this->owned_by_task_list; } bool GetSleepAllowed() const { return this->sleep_allowed; } + bool GetNeedsPackets() const { return this->needs_packets; } void SetPriority(u32 p) { this->priority = p; } void SetServiceId(TmaServiceId s) { this->service_id = s; } @@ -61,6 +63,7 @@ class TmaTask { void SetCommand(u32 c) { this->command = c; } void SetOwnedByTaskList(bool o) { this->owned_by_task_list = o; } void SetSleepAllowed(bool a) { this->sleep_allowed = a; } + void SetNeedsPackets(bool n); void Signal() { this->signal.Signal(); } void ResetSignal() { this->signal.Reset(); } diff --git a/stratosphere/tma/source/tma_task_list.cpp b/stratosphere/tma/source/tma_task_list.cpp index 2cb28b487..36f54bef9 100644 --- a/stratosphere/tma/source/tma_task_list.cpp +++ b/stratosphere/tma/source/tma_task_list.cpp @@ -70,9 +70,9 @@ bool TmaTaskList::SendPacket(bool connected, TmaPacket *packet) { switch (task->GetState()) { case TmaTaskState::InProgress: it++; - if (target_task == nullptr) { + if (target_task == nullptr && task->GetNeedsPackets()) { if (connected || IsMetaService(task->GetServiceId())) { - target_task = nullptr; + target_task = task; } } break; From 61ad4e09919a724b6732e637fc2eb040e3f4cb6d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 13:18:31 -0800 Subject: [PATCH 290/489] tma: Implement example set:sys getter service --- stratosphere/tma/Makefile | 2 +- stratosphere/tma/client/Main.py | 11 ++++- stratosphere/tma/client/Packet.py | 4 ++ stratosphere/tma/client/ServiceId.py | 2 +- .../tma/source/settings/settings_service.cpp | 43 +++++++++++++++++ .../tma/source/settings/settings_service.hpp | 34 ++++++++++++++ .../tma/source/settings/settings_task.cpp | 46 +++++++++++++++++++ .../tma/source/settings/settings_task.hpp | 38 +++++++++++++++ stratosphere/tma/source/tma_main.cpp | 6 +++ stratosphere/tma/source/tma_target.cpp | 2 + 10 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 stratosphere/tma/source/settings/settings_service.cpp create mode 100644 stratosphere/tma/source/settings/settings_service.hpp create mode 100644 stratosphere/tma/source/settings/settings_task.cpp create mode 100644 stratosphere/tma/source/settings/settings_task.hpp diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile index 9d0408a23..161caed02 100644 --- a/stratosphere/tma/Makefile +++ b/stratosphere/tma/Makefile @@ -19,7 +19,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := source source/test +SOURCES := source source/test source/settings DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src diff --git a/stratosphere/tma/client/Main.py b/stratosphere/tma/client/Main.py index 3ea150608..0a81509c6 100644 --- a/stratosphere/tma/client/Main.py +++ b/stratosphere/tma/client/Main.py @@ -20,9 +20,16 @@ def main(argc, argv): print 'Waiting for connection...' c.wait_connected() print 'Connected!' - c.intf.send_packet(Packet().set_service(ServiceId.ATMOSPHERE_TEST_SERVICE).set_task(0x01000000).write_u32(0x40)) + c.intf.send_packet(Packet().set_service(ServiceId.SETTINGS_SERVICE).set_task(0x01000000).set_cmd(0).write_str('lm').write_str('sd_card_log_output_directory')) resp = c.intf.read_packet() - print resp.body + success = resp.read_u8() != 0 + print 'Succeeded: %s' % str(success) + if success: + size = resp.read_u32() + value = resp.body[resp.offset:resp.offset+size] + print 'Value Size: 0x%x' % size + print 'Value: %s' % repr(value) + return 0 if __name__ == '__main__': diff --git a/stratosphere/tma/client/Packet.py b/stratosphere/tma/client/Packet.py index 465be93e8..9f623b28d 100644 --- a/stratosphere/tma/client/Packet.py +++ b/stratosphere/tma/client/Packet.py @@ -70,6 +70,8 @@ class Packet(): self.offset = 0 return self def write_str(self, s): + if s[-1] != '\x00': + s += '\x00' self.body += s self.body_len += len(s) return self @@ -94,6 +96,8 @@ class Packet(): while self.body[self.offset] != '\x00' and self.offset < self.body_len: s += self.body[self.offset] self.offset += 1 + if self.offset < self.body_len and self.body[self.offset] == '\x00': + self.offset += 1 def read_u8(self): x, = up('<B', self.body[self.offset:self.offset+1]) self.offset += 1 diff --git a/stratosphere/tma/client/ServiceId.py b/stratosphere/tma/client/ServiceId.py index 27b314f93..e943313a6 100644 --- a/stratosphere/tma/client/ServiceId.py +++ b/stratosphere/tma/client/ServiceId.py @@ -25,5 +25,5 @@ USB_CONNECT = hash("USBConnect") USB_DISCONNECT = hash("USBDisconnect") ATMOSPHERE_TEST_SERVICE = hash("AtmosphereTestService") - +SETTINGS_SERVICE = hash ("SettingsService") \ No newline at end of file diff --git a/stratosphere/tma/source/settings/settings_service.cpp b/stratosphere/tma/source/settings/settings_service.cpp new file mode 100644 index 000000000..8dc5dfa52 --- /dev/null +++ b/stratosphere/tma/source/settings/settings_service.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> + +#include "settings_service.hpp" +#include "settings_task.hpp" + +TmaTask *SettingsService::NewTask(TmaPacket *packet) { + TmaTask *new_task = nullptr; + switch (packet->GetCommand()) { + case SettingsServiceCmd_GetSetting: + { + new_task = new GetSettingTask(this->manager); + } + break; + default: + new_task = nullptr; + break; + } + if (new_task != nullptr) { + new_task->SetServiceId(this->GetServiceId()); + new_task->SetTaskId(packet->GetTaskId()); + new_task->OnStart(packet); + new_task->SetNeedsPackets(true); + } + + return new_task; +} diff --git a/stratosphere/tma/source/settings/settings_service.hpp b/stratosphere/tma/source/settings/settings_service.hpp new file mode 100644 index 000000000..3b21c891b --- /dev/null +++ b/stratosphere/tma/source/settings/settings_service.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "../tma_conn_service_ids.hpp" +#include "../tma_service.hpp" + +enum SettingsServiceCmd : u32 { + SettingsServiceCmd_GetSetting = 0, +}; + +class SettingsService : public TmaService { + public: + SettingsService(TmaServiceManager *m) : TmaService(m, "SettingsService") { } + virtual ~SettingsService() { } + + virtual TmaTask *NewTask(TmaPacket *packet) override; +}; \ No newline at end of file diff --git a/stratosphere/tma/source/settings/settings_task.cpp b/stratosphere/tma/source/settings/settings_task.cpp new file mode 100644 index 000000000..650cc6c15 --- /dev/null +++ b/stratosphere/tma/source/settings/settings_task.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> + +#include "settings_task.hpp" + +void GetSettingTask::OnStart(TmaPacket *packet) { + size_t length; + packet->ReadString(this->name, sizeof(this->name), &length); + packet->ReadString(this->item_key, sizeof(this->item_key), &length); + + if (R_SUCCEEDED(setsysGetSettingsItemValueSize(this->name, this->item_key, &this->value_size))) { + if (this->value_size <= sizeof(this->value)) { + if (R_SUCCEEDED(setsysGetSettingsItemValue(this->name, this->item_key, this->value, this->value_size))) { + this->succeeded = true; + } + } + } +} + +void GetSettingTask::OnReceivePacket(TmaPacket *packet) { + std::abort(); +} + +void GetSettingTask::OnSendPacket(TmaPacket *packet) { + packet->Write<u8>((u8)this->succeeded); + packet->Write<u32>((u32)this->value_size); + packet->Write(this->value, this->value_size); + + this->Complete(); +} \ No newline at end of file diff --git a/stratosphere/tma/source/settings/settings_task.hpp b/stratosphere/tma/source/settings/settings_task.hpp new file mode 100644 index 000000000..5d2bd13be --- /dev/null +++ b/stratosphere/tma/source/settings/settings_task.hpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "../tma_task.hpp" + +class GetSettingTask : public TmaTask { + private: + char name[0x40] = {0}; + char item_key[0x40] = {0}; + u8 value[0x40] = {0}; + u64 value_size = 0; + bool succeeded = false; + + public: + GetSettingTask(TmaServiceManager *m) : TmaTask(m) { } + virtual ~GetSettingTask() { } + + virtual void OnStart(TmaPacket *packet) override; + virtual void OnReceivePacket(TmaPacket *packet) override; + virtual void OnSendPacket(TmaPacket *packet) override; +}; diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp index fb1491cc3..d314ed16a 100644 --- a/stratosphere/tma/source/tma_main.cpp +++ b/stratosphere/tma/source/tma_main.cpp @@ -65,11 +65,17 @@ void __appInit(void) { fatalSimple(rc); } + rc = setsysInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { /* Cleanup services. */ + setsysExit(); pscExit(); smExit(); } diff --git a/stratosphere/tma/source/tma_target.cpp b/stratosphere/tma/source/tma_target.cpp index 9873d952d..9cfcb335f 100644 --- a/stratosphere/tma/source/tma_target.cpp +++ b/stratosphere/tma/source/tma_target.cpp @@ -26,6 +26,7 @@ #include "tma_target.hpp" #include "test/atmosphere_test_service.hpp" +#include "settings/settings_service.hpp" struct TmaTargetConfig { char configuration_id1[0x80]; @@ -208,6 +209,7 @@ void TmaTarget::Initialize() { g_service_manager = new TmaServiceManager(); /* TODO: Make this better. */ g_service_manager->AddService(new AtmosphereTestService(g_service_manager)); + g_service_manager->AddService(new SettingsService(g_service_manager)); RefreshTargetConfig(); From d1985fe77e85b27392277024640c30c4d3c4c66b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 13:21:21 -0800 Subject: [PATCH 291/489] tma: better GetSettingsTask output --- stratosphere/tma/source/settings/settings_task.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/stratosphere/tma/source/settings/settings_task.cpp b/stratosphere/tma/source/settings/settings_task.cpp index 650cc6c15..52540e623 100644 --- a/stratosphere/tma/source/settings/settings_task.cpp +++ b/stratosphere/tma/source/settings/settings_task.cpp @@ -39,8 +39,10 @@ void GetSettingTask::OnReceivePacket(TmaPacket *packet) { void GetSettingTask::OnSendPacket(TmaPacket *packet) { packet->Write<u8>((u8)this->succeeded); - packet->Write<u32>((u32)this->value_size); - packet->Write(this->value, this->value_size); + if (this->succeeded) { + packet->Write<u32>((u32)this->value_size); + packet->Write(this->value, this->value_size); + } this->Complete(); } \ No newline at end of file From 588315f877c7f5aa7a0f56ac0c9ef2f762723f75 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 21:08:04 -0800 Subject: [PATCH 292/489] dmnt: Create Makefile/Process folder. --- stratosphere/dmnt/Makefile | 166 +++++++++++++++++++++++++ stratosphere/dmnt/dmnt.json | 117 +++++++++++++++++ stratosphere/dmnt/source/dmnt_main.cpp | 129 +++++++++++++++++++ 3 files changed, 412 insertions(+) create mode 100644 stratosphere/dmnt/Makefile create mode 100644 stratosphere/dmnt/dmnt.json create mode 100644 stratosphere/dmnt/source/dmnt_main.cpp diff --git a/stratosphere/dmnt/Makefile b/stratosphere/dmnt/Makefile new file mode 100644 index 000000000..71c014dc5 --- /dev/null +++ b/stratosphere/dmnt/Makefile @@ -0,0 +1,166 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include ../../common/include +EXEFS_SRC := exefs_src + +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lstratosphere -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) $(CURDIR)/../libstratosphere + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) + +ifeq ($(strip $(CONFIG_JSON)),) + jsons := $(wildcard *.json) + ifneq (,$(findstring $(TARGET).json,$(jsons))) + export APP_JSON := $(TOPDIR)/$(TARGET).json + else + ifneq (,$(findstring config.json,$(jsons))) + export APP_JSON := $(TOPDIR)/config.json + endif + endif +else + export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).npdm $(TARGET).nso $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).nsp + +ifeq ($(strip $(APP_JSON)),) +$(OUTPUT).nsp : $(OUTPUT).nso +else +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm +endif + +$(OUTPUT).nso : $(OUTPUT).elf + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/stratosphere/dmnt/dmnt.json b/stratosphere/dmnt/dmnt.json new file mode 100644 index 000000000..0be7e94ed --- /dev/null +++ b/stratosphere/dmnt/dmnt.json @@ -0,0 +1,117 @@ +{ + "name": "dmnt", + "title_id": "0x010000000000000d", + "title_id_range_min": "0x010000000000000d", + "title_id_range_max": "0x010000000000000d", + "main_thread_stack_size": "0x00004000", + "main_thread_priority": 39, + "default_cpu_id": 3, + "process_category": 0, + "is_retail": true, + "pool_partition": 2, + "is_64_bit": true, + "address_space_type": 1, + "filesystem_access": { + "permissions": "0xFFFFFFFFFFFFFFFF" + }, + "service_access": [ + "pm:dmnt", + "ldr:dmnt", + "ro:dmnt", + "ns:dev", + "spl:", + "lr", + "htc", + "bsd:s", + "sfdnsres", + "bsdcfg", + "set", + "fsp-srv", + "fatal:u" + ], + "service_host": [ + "dmnt:-" + ], + "kernel_capabilities": [{ + "type": "kernel_flags", + "value": { + "highest_thread_priority": 63, + "lowest_thread_priority": 24, + "lowest_cpu_id": 0, + "highest_cpu_id": 3 + } + }, { + "type": "syscalls", + "value": { + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0a", + "svcSleepThread": "0x0b", + "svcGetThreadPriority": "0x0c", + "svcSetThreadPriority": "0x0d", + "svcGetThreadCoreMask": "0x0e", + "svcSetThreadCoreMask": "0x0f", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1a", + "svcArbitrateUnlock": "0x1b", + "svcWaitProcessWideKeyAtomic": "0x1c", + "svcSignalProcessWideKey": "0x1d", + "svcGetSystemTick": "0x1e", + "svcConnectToNamedPort": "0x1f", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcCreateEvent": "0x45", + "svcDebugActiveProcess": "0x60", + "svcBreakDebugProcess": "0x61", + "svcTerminateDebugProcess": "0x62", + "svcGetDebugEvent": "0x63", + "svcContinueDebugEvent": "0x64", + "svcGetProcessList": "0x65", + "svcGetThreadList": "0x66", + "svcGetDebugThreadContext": "0x67", + "svcSetDebugThreadContext": "0x68", + "svcQueryDebugProcessMemory": "0x69", + "svcReadDebugProcessMemory": "0x6a", + "svcWriteDebugProcessMemory": "0x6b", + "svcSetHardwareBreakPoint": "0x6c", + "svcGetDebugThreadParam": "0x6d" + } + }, { + "type": "min_kernel_version", + "value": "0x0030" + }, { + "type": "handle_table_size", + "value": 0 + }] +} \ No newline at end of file diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp new file mode 100644 index 000000000..73adbbcaf --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +extern "C" { + extern u32 __start__; + + u32 __nx_applet_type = AppletType_None; + + #define INNER_HEAP_SIZE 0x80000 + size_t nx_inner_heap_size = INNER_HEAP_SIZE; + char nx_inner_heap[INNER_HEAP_SIZE]; + + void __libnx_initheap(void); + void __appInit(void); + void __appExit(void); +} + + +void __libnx_initheap(void) { + void* addr = nx_inner_heap; + size_t size = nx_inner_heap_size; + + /* Newlib */ + extern char* fake_heap_start; + extern char* fake_heap_end; + + fake_heap_start = (char*)addr; + fake_heap_end = (char*)addr + size; +} + +void __appInit(void) { + Result rc; + + rc = smInitialize(); + if (R_FAILED(rc)) { + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); + } + + rc = pmdmntInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + rc = ldrDmntInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + /* + if (kernelAbove300()) { + rc = roDmntInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + } + */ + + rc = nsdevInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + rc = lrInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + rc = setInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + rc = fsInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + rc = fsdevMountSdmc(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); +} + +void __appExit(void) { + /* Cleanup services. */ + fsdevUnmountAll(); + fsExit(); + setExit(); + lrExit(); + nsdevExit(); + /* if (kernelAbove300()) { roDmntExit(); } */ + ldrDmntExit(); + pmdmntExit(); + smExit(); +} + +int main(int argc, char **argv) +{ + consoleDebugInit(debugDevice_SVC); + + /* TODO: Make a server manager, and process on it. */ + + return 0; +} + From 94e527e7632787726ae07ee60eb07212201fe98a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 23:35:09 -0800 Subject: [PATCH 293/489] dmnt: Skeleton real process implementation. --- .../dmnt/source/dmnt_debug_monitor.cpp | 34 +++++ .../dmnt/source/dmnt_debug_monitor.hpp | 136 ++++++++++++++++++ stratosphere/dmnt/source/dmnt_main.cpp | 15 +- 3 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 stratosphere/dmnt/source/dmnt_debug_monitor.cpp create mode 100644 stratosphere/dmnt/source/dmnt_debug_monitor.hpp diff --git a/stratosphere/dmnt/source/dmnt_debug_monitor.cpp b/stratosphere/dmnt/source/dmnt_debug_monitor.cpp new file mode 100644 index 000000000..30c4e19a4 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_debug_monitor.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "dmnt_debug_monitor.hpp" + +Result DebugMonitorService::BreakDebugProcess(Handle debug_hnd) { + /* Nintendo discards the output of this command, but we will return it. */ + return svcBreakDebugProcess(debug_hnd); +} + +Result DebugMonitorService::TerminateDebugProcess(Handle debug_hnd) { + /* Nintendo discards the output of this command, but we will return it. */ + return svcTerminateDebugProcess(debug_hnd); +} + +Result DebugMonitorService::CloseHandle(Handle debug_hnd) { + /* Nintendo discards the output of this command, but we will return it. */ + /* This command is, entertainingly, also pretty unsafe in general... */ + return svcCloseHandle(debug_hnd); +} diff --git a/stratosphere/dmnt/source/dmnt_debug_monitor.hpp b/stratosphere/dmnt/source/dmnt_debug_monitor.hpp new file mode 100644 index 000000000..028e5173d --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_debug_monitor.hpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +enum DmntCmd { + DebugMonitor_Cmd_BreakDebugProcess = 0, + DebugMonitor_Cmd_TerminateDebugProcess = 1, + DebugMonitor_Cmd_CloseHandle = 2, + DebugMonitor_Cmd_LoadImage = 3, + DebugMonitor_Cmd_GetProcessId = 4, + DebugMonitor_Cmd_GetProcessHandle = 5, + DebugMonitor_Cmd_WaitSynchronization = 6, + DebugMonitor_Cmd_GetDebugEvent = 7, + DebugMonitor_Cmd_GetProcessModuleInfo = 8, + DebugMonitor_Cmd_GetProcessList = 9, + DebugMonitor_Cmd_GetThreadList = 10, + DebugMonitor_Cmd_GetDebugThreadContext = 11, + DebugMonitor_Cmd_ContinueDebugEvent = 12, + DebugMonitor_Cmd_ReadDebugProcessMemory = 13, + DebugMonitor_Cmd_WriteDebugProcessMemory = 14, + DebugMonitor_Cmd_SetDebugThreadContext = 15, + DebugMonitor_Cmd_GetDebugThreadParam = 16, + DebugMonitor_Cmd_InitializeThreadInfo = 17, + DebugMonitor_Cmd_SetHardwareBreakPoint = 18, + DebugMonitor_Cmd_QueryDebugProcessMemory = 19, + DebugMonitor_Cmd_GetProcessMemoryDetails = 20, + DebugMonitor_Cmd_AttachByProgramId = 21, + DebugMonitor_Cmd_AttachOnLaunch = 22, + DebugMonitor_Cmd_GetDebugMonitorProcessId = 23, + DebugMonitor_Cmd_GetJitDebugProcessList = 25, + DebugMonitor_Cmd_CreateCoreDump = 26, + DebugMonitor_Cmd_GetAllDebugThreadInfo = 27, + DebugMonitor_Cmd_TargetIO_FileOpen = 29, + DebugMonitor_Cmd_TargetIO_FileClose = 30, + DebugMonitor_Cmd_TargetIO_FileRead = 31, + DebugMonitor_Cmd_TargetIO_FileWrite = 32, + DebugMonitor_Cmd_TargetIO_FileSetAttributes = 33, + DebugMonitor_Cmd_TargetIO_FileGetInformation = 34, + DebugMonitor_Cmd_TargetIO_FileSetTime = 35, + DebugMonitor_Cmd_TargetIO_FileSetSize = 36, + DebugMonitor_Cmd_TargetIO_FileDelete = 37, + DebugMonitor_Cmd_TargetIO_FileMove = 38, + DebugMonitor_Cmd_TargetIO_DirectoryCreate = 39, + DebugMonitor_Cmd_TargetIO_DirectoryDelete = 40, + DebugMonitor_Cmd_TargetIO_DirectoryRename = 41, + DebugMonitor_Cmd_TargetIO_DirectoryGetCount = 42, + DebugMonitor_Cmd_TargetIO_DirectoryOpen = 43, + DebugMonitor_Cmd_TargetIO_DirectoryGetNext = 44, + DebugMonitor_Cmd_TargetIO_DirectoryClose = 45, + DebugMonitor_Cmd_TargetIO_GetFreeSpace = 46, + DebugMonitor_Cmd_TargetIO_GetVolumeInformation = 47, + DebugMonitor_Cmd_InitiateCoreDump = 48, + DebugMonitor_Cmd_ContinueCoreDump = 49, + DebugMonitor_Cmd_AddTTYToCoreDump = 50, + DebugMonitor_Cmd_AddImageToCoreDump = 51, + DebugMonitor_Cmd_CloseCoreDump = 52, + DebugMonitor_Cmd_CancelAttach = 53, +}; + +class DebugMonitorService final : public IServiceObject { + private: + Result BreakDebugProcess(Handle debug_hnd); + Result TerminateDebugProcess(Handle debug_hnd); + Result CloseHandle(Handle debug_hnd); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<DebugMonitor_Cmd_BreakDebugProcess, &DebugMonitorService::BreakDebugProcess>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TerminateDebugProcess, &DebugMonitorService::TerminateDebugProcess>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_CloseHandle, &DebugMonitorService::CloseHandle>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_LoadImage, &DebugMonitorService::LoadImage>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessId, &DebugMonitorService::GetProcessId>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessHandle, &DebugMonitorService::GetProcessHandle>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_WaitSynchronization, &DebugMonitorService::WaitSynchronization>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetDebugEvent, &DebugMonitorService::GetDebugEvent>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessModuleInfo, &DebugMonitorService::GetProcessModuleInfo>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessList, &DebugMonitorService::GetProcessList>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetThreadList, &DebugMonitorService::GetThreadList>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetDebugThreadContext, &DebugMonitorService::GetDebugThreadContext>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_ContinueDebugEvent, &DebugMonitorService::ContinueDebugEvent>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_ReadDebugProcessMemory, &DebugMonitorService::ReadDebugProcessMemory>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_WriteDebugProcessMemory, &DebugMonitorService::WriteDebugProcessMemory>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_SetDebugThreadContext, &DebugMonitorService::SetDebugThreadContext>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetDebugThreadParam, &DebugMonitorService::GetDebugThreadParam>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_InitializeThreadInfo, &DebugMonitorService::InitializeThreadInfo>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_SetHardwareBreakPoint, &DebugMonitorService::SetHardwareBreakPoint>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_QueryDebugProcessMemory, &DebugMonitorService::QueryDebugProcessMemory>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessMemoryDetails, &DebugMonitorService::GetProcessMemoryDetails>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_AttachByProgramId, &DebugMonitorService::AttachByProgramId>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_AttachOnLaunch, &DebugMonitorService::AttachOnLaunch>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetDebugMonitorProcessId, &DebugMonitorService::GetDebugMonitorProcessId>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetJitDebugProcessList, &DebugMonitorService::GetJitDebugProcessList>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_CreateCoreDump, &DebugMonitorService::CreateCoreDump>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_GetAllDebugThreadInfo, &DebugMonitorService::GetAllDebugThreadInfo>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileOpen, &DebugMonitorService::TargetIO_FileOpen>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileClose, &DebugMonitorService::TargetIO_FileClose>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileRead, &DebugMonitorService::TargetIO_FileRead>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileWrite, &DebugMonitorService::TargetIO_FileWrite>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetAttributes, &DebugMonitorService::TargetIO_FileSetAttributes>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileGetInformation, &DebugMonitorService::TargetIO_FileGetInformation>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetTime, &DebugMonitorService::TargetIO_FileSetTime>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetSize, &DebugMonitorService::TargetIO_FileSetSize>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileDelete, &DebugMonitorService::TargetIO_FileDelete>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileMove, &DebugMonitorService::TargetIO_FileMove>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryCreate, &DebugMonitorService::TargetIO_DirectoryCreate>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryDelete, &DebugMonitorService::TargetIO_DirectoryDelete>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryRename, &DebugMonitorService::TargetIO_DirectoryRename>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryGetCount, &DebugMonitorService::TargetIO_DirectoryGetCount>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryOpen, &DebugMonitorService::TargetIO_DirectoryOpen>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryGetNext, &DebugMonitorService::TargetIO_DirectoryGetNext>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryClose, &DebugMonitorService::TargetIO_DirectoryClose>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_GetFreeSpace, &DebugMonitorService::TargetIO_GetFreeSpace>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_GetVolumeInformation, &DebugMonitorService::TargetIO_GetVolumeInformation>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_InitiateCoreDump, &DebugMonitorService::InitiateCoreDump>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_ContinueCoreDump, &DebugMonitorService::ContinueCoreDump>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_AddTTYToCoreDump, &DebugMonitorService::AddTTYToCoreDump>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_AddImageToCoreDump, &DebugMonitorService::AddImageToCoreDump>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_CloseCoreDump, &DebugMonitorService::CloseCoreDump>(), + // MakeServiceCommandMeta<DebugMonitor_Cmd_CancelAttach, &DebugMonitorService::CancelAttach>(), + }; +}; diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index 73adbbcaf..dbf936635 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -23,6 +23,8 @@ #include <atmosphere.h> #include <stratosphere.hpp> +#include "dmnt_debug_monitor.hpp" + extern "C" { extern u32 __start__; @@ -121,8 +123,17 @@ void __appExit(void) { int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); - - /* TODO: Make a server manager, and process on it. */ + + /* Nintendo uses four threads. */ + auto server_manager = new WaitableManager(4); + + /* Create services. */ + server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("dmnt:-", 4)); + + /* Loop forever, servicing our services. */ + server_manager->Process(); + + delete server_manager; return 0; } From 907f6fa72db5b7b0c04b6e7afa40758a92133059 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 23:36:12 -0800 Subject: [PATCH 294/489] stratosphere: make tma non-kip, add to build system --- Makefile | 2 ++ stratosphere/Makefile | 2 +- stratosphere/pm/source/pm_boot2.cpp | 7 ++++-- stratosphere/tma/Makefile | 10 +++++++-- stratosphere/tma/client/Main.py | 2 +- stratosphere/tma/tma.json | 34 +++++++++++++++++++++++++++++ 6 files changed, 51 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 62fdd0f64..37d2613a7 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,8 @@ dist: all cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags/boot2.flag + cp stratosphere/tma/tma.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000007/exefs.nsp + cp stratosphere/dmnt/dmnt.nsp atmosphere-$(AMSVER)/atmosphere/titles/010000000000000D/exefs.nsp cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; rm -r atmosphere-$(AMSVER) mkdir out diff --git a/stratosphere/Makefile b/stratosphere/Makefile index 61e6a119c..fa1c68b67 100644 --- a/stratosphere/Makefile +++ b/stratosphere/Makefile @@ -1,4 +1,4 @@ -KIPS := loader pm sm boot fs_mitm set_mitm creport fatal +KIPS := loader pm sm boot fs_mitm set_mitm creport fatal tma dmnt #TODO: boot2 ? diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 16811b6ec..6f3fa2c9f 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -158,8 +158,11 @@ void EmbeddedBoot2::Main() { /* Launch usb. */ LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); - /* Don't launch tma, because atmosphere replaces it with a KIP. */ - /* LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_NandSystem, 0, NULL); */ + /* Launch Atmosphere tma, using FsStorageId_None to force SD card boot. */ + LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_None, 0, NULL); + + /* Launch Atmosphere dmnt, using FsStorageId_None to force SD card boot. */ + LaunchTitle(Boot2KnownTitleId::dmnt, FsStorageId_None, 0, NULL); /* Launch default programs. */ bool maintenance = ShouldForceMaintenanceMode(); diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile index 161caed02..6b5faa89c 100644 --- a/stratosphere/tma/Makefile +++ b/stratosphere/tma/Makefile @@ -132,9 +132,15 @@ DEPENDS := $(OFILES:.o=.d) #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -all : $(OUTPUT).kip +all : $(OUTPUT).nsp -$(OUTPUT).kip : $(OUTPUT).elf +ifeq ($(strip $(APP_JSON)),) +$(OUTPUT).nsp : $(OUTPUT).nso +else +$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm +endif + +$(OUTPUT).nso : $(OUTPUT).elf $(OUTPUT).elf : $(OFILES) diff --git a/stratosphere/tma/client/Main.py b/stratosphere/tma/client/Main.py index 0a81509c6..4fabfc7b5 100644 --- a/stratosphere/tma/client/Main.py +++ b/stratosphere/tma/client/Main.py @@ -20,7 +20,7 @@ def main(argc, argv): print 'Waiting for connection...' c.wait_connected() print 'Connected!' - c.intf.send_packet(Packet().set_service(ServiceId.SETTINGS_SERVICE).set_task(0x01000000).set_cmd(0).write_str('lm').write_str('sd_card_log_output_directory')) + c.intf.send_packet(Packet().set_service(ServiceId.SETTINGS_SERVICE).set_task(0x01000000).set_cmd(0).write_str('platformconfig').write_str('platformtype')) resp = c.intf.read_packet() success = resp.read_u8() != 0 print 'Succeeded: %s' % str(success) diff --git a/stratosphere/tma/tma.json b/stratosphere/tma/tma.json index 7cbfbf3fc..e67d99b1f 100644 --- a/stratosphere/tma/tma.json +++ b/stratosphere/tma/tma.json @@ -1,10 +1,44 @@ { "name": "tma", "title_id": "0x0100000000000007", + "title_id_range_min": "0x0100000000000007", + "title_id_range_max": "0x0100000000000007", "main_thread_stack_size": "0x00004000", "main_thread_priority": 38, "default_cpu_id": 3, "process_category": 1, + "default_cpu_id": 3, + "process_category": 0, + "is_retail": true, + "pool_partition": 2, + "is_64_bit": true, + "address_space_type": 1, + "filesystem_access": { + "permissions": "0xFFFFFFFFFFFFFFFF" + }, + "service_access": [ + "bsd:s", + "bsdcfg", + "dmnt:-", + "fatal:u", + "i2c", + "pcie", + "psc:m", + "set:cal", + "set:fd", + "set:sys", + "sfdnsres", + "spl:", + "usb:ds" + ], + "service_host": [ + "file_io", + "gds", + "htc", + "htcs", + "tma_log", + "tmagent" + ], "kernel_capabilities": [ { "type": "syscalls", From 8a92a63a6430875e7d351bd7e0230425f676e3f3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 23:44:11 -0800 Subject: [PATCH 295/489] pm: Don't launch titles twice due to boot2.flag --- Makefile | 2 ++ stratosphere/pm/source/pm_boot2.cpp | 36 +++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 37d2613a7..9319c39a5 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,8 @@ dist: all mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032 + mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/010000000000000D + mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000007 cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 6f3fa2c9f..3ce877f1d 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -26,6 +26,8 @@ #include "pm_boot2.hpp" #include "pm_registration.hpp" +static std::vector<Boot2KnownTitleId> g_launched_titles; + static bool IsHexadecimal(const char *str) { while (*str) { if (isxdigit(*str)) { @@ -37,22 +39,34 @@ static bool IsHexadecimal(const char *str) { return true; } +static bool HasLaunchedTitle(Boot2KnownTitleId title_id) { + return std::find(g_launched_titles.begin(), g_launched_titles.end(), title_id) != g_launched_titles.end(); +} + +static void SetLaunchedTitle(Boot2KnownTitleId title_id) { + g_launched_titles.push_back(title_id); +} + +static void ClearLaunchedTitles() { + g_launched_titles.clear(); +} + static void LaunchTitle(Boot2KnownTitleId title_id, FsStorageId storage_id, u32 launch_flags, u64 *pid) { - u64 local_pid; + u64 local_pid = 0; Result rc = Registration::LaunchProcessByTidSid(Registration::TidSid{(u64)title_id, storage_id}, launch_flags, &local_pid); switch (rc) { case 0xCE01: /* Out of resource! */ - /* TODO: Panic(). */ + std::abort(); break; case 0xDE01: /* Out of memory! */ - /* TODO: Panic(). */ + std::abort(); break; case 0xD001: /* Limit Reached! */ - /* TODO: Panic(). */ + std::abort(); break; default: /* We don't care about other issues. */ @@ -61,6 +75,8 @@ static void LaunchTitle(Boot2KnownTitleId title_id, FsStorageId storage_id, u32 if (pid) { *pid = local_pid; } + + SetLaunchedTitle(title_id); } static bool ShouldForceMaintenanceMode() { @@ -178,7 +194,10 @@ void EmbeddedBoot2::Main() { if (titles_dir != NULL) { while ((ent = readdir(titles_dir)) != NULL) { if (strlen(ent->d_name) == 0x10 && IsHexadecimal(ent->d_name)) { - u64 title_id = strtoul(ent->d_name, NULL, 16); + Boot2KnownTitleId title_id = (Boot2KnownTitleId)strtoul(ent->d_name, NULL, 16); + if (HasLaunchedTitle(title_id)) { + continue; + } char title_path[FS_MAX_PATH] = {0}; strcpy(title_path, "sdmc:/atmosphere/titles/"); strcat(title_path, ent->d_name); @@ -186,7 +205,7 @@ void EmbeddedBoot2::Main() { FILE *f_flag = fopen(title_path, "rb"); if (f_flag != NULL) { fclose(f_flag); - LaunchTitle((Boot2KnownTitleId)title_id, FsStorageId_None, 0, NULL); + LaunchTitle(title_id, FsStorageId_None, 0, NULL); } else { /* TODO: Deprecate this in the future. */ memset(title_path, 0, FS_MAX_PATH); @@ -196,13 +215,16 @@ void EmbeddedBoot2::Main() { f_flag = fopen(title_path, "rb"); if (f_flag != NULL) { fclose(f_flag); - LaunchTitle((Boot2KnownTitleId)title_id, FsStorageId_None, 0, NULL); + LaunchTitle(title_id, FsStorageId_None, 0, NULL); } } } } closedir(titles_dir); } + + /* Free the memory used to track what boot2 launches. */ + ClearLaunchedTitles(); /* We no longer need the SD card. */ fsdevUnmountAll(); From eb6ab2ba62e80a007435eeeeac87fc931fd1fc53 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 5 Dec 2018 23:57:35 -0800 Subject: [PATCH 296/489] dmnt: Implement three more easy commands --- .../dmnt/source/dmnt_debug_monitor.cpp | 18 ++++++++++++++++++ .../dmnt/source/dmnt_debug_monitor.hpp | 11 +++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_debug_monitor.cpp b/stratosphere/dmnt/source/dmnt_debug_monitor.cpp index 30c4e19a4..2e287e6eb 100644 --- a/stratosphere/dmnt/source/dmnt_debug_monitor.cpp +++ b/stratosphere/dmnt/source/dmnt_debug_monitor.cpp @@ -32,3 +32,21 @@ Result DebugMonitorService::CloseHandle(Handle debug_hnd) { /* This command is, entertainingly, also pretty unsafe in general... */ return svcCloseHandle(debug_hnd); } + +Result DebugMonitorService::GetProcessId(Out<u64> out_pid, Handle hnd) { + /* Nintendo discards the output of this command, but we will return it. */ + return svcGetProcessId(out_pid.GetPointer(), hnd); +} + +Result DebugMonitorService::GetProcessHandle(Out<Handle> out_hnd, u64 pid) { + Result rc = svcDebugActiveProcess(out_hnd.GetPointer(), pid); + if (rc == 0xF401) { + rc = 0x4B7; + } + return rc; +} + +Result DebugMonitorService::WaitSynchronization(Handle hnd, u64 ns) { + /* Nintendo discards the output of this command, but we will return it. */ + return svcWaitSynchronizationSingle(hnd, ns); +} diff --git a/stratosphere/dmnt/source/dmnt_debug_monitor.hpp b/stratosphere/dmnt/source/dmnt_debug_monitor.hpp index 028e5173d..bd73d4a88 100644 --- a/stratosphere/dmnt/source/dmnt_debug_monitor.hpp +++ b/stratosphere/dmnt/source/dmnt_debug_monitor.hpp @@ -78,16 +78,19 @@ class DebugMonitorService final : public IServiceObject { Result BreakDebugProcess(Handle debug_hnd); Result TerminateDebugProcess(Handle debug_hnd); Result CloseHandle(Handle debug_hnd); + Result GetProcessId(Out<u64> out_pid, Handle hnd); + Result GetProcessHandle(Out<Handle> out_hnd, u64 pid); + Result WaitSynchronization(Handle hnd, u64 ns); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<DebugMonitor_Cmd_BreakDebugProcess, &DebugMonitorService::BreakDebugProcess>(), MakeServiceCommandMeta<DebugMonitor_Cmd_TerminateDebugProcess, &DebugMonitorService::TerminateDebugProcess>(), MakeServiceCommandMeta<DebugMonitor_Cmd_CloseHandle, &DebugMonitorService::CloseHandle>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_LoadImage, &DebugMonitorService::LoadImage>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessId, &DebugMonitorService::GetProcessId>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessHandle, &DebugMonitorService::GetProcessHandle>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_WaitSynchronization, &DebugMonitorService::WaitSynchronization>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_GetDebugEvent, &DebugMonitorService::GetDebugEvent>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessId, &DebugMonitorService::GetProcessId>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessHandle, &DebugMonitorService::GetProcessHandle>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_WaitSynchronization, &DebugMonitorService::WaitSynchronization>(), + //MakeServiceCommandMeta<DebugMonitor_Cmd_GetDebugEvent, &DebugMonitorService::GetDebugEvent>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessModuleInfo, &DebugMonitorService::GetProcessModuleInfo>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_GetProcessList, &DebugMonitorService::GetProcessList>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_GetThreadList, &DebugMonitorService::GetThreadList>(), From d452d6f89dc46378336a389a60ea8d772927fb3f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 6 Dec 2018 09:29:09 -0800 Subject: [PATCH 297/489] exo: Correct seal key source --- exosphere/src/sealedkeys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exosphere/src/sealedkeys.c b/exosphere/src/sealedkeys.c index 03c417d4f..14142b274 100644 --- a/exosphere/src/sealedkeys.c +++ b/exosphere/src/sealedkeys.c @@ -33,7 +33,7 @@ static const uint8_t g_seal_key_sources[CRYPTOUSECASE_MAX_5X][0x10] = { {0x0E, 0xE0, 0xC4, 0x33, 0x82, 0x66, 0xE8, 0x08, 0x39, 0x13, 0x41, 0x7D, 0x04, 0x64, 0x2B, 0x6D}, {0xE1, 0xA8, 0xAA, 0x6A, 0x2D, 0x9C, 0xDE, 0x43, 0x0C, 0xDE, 0xC6, 0x17, 0xF6, 0xC7, 0xF1, 0xDE}, {0x74, 0x20, 0xF6, 0x46, 0x77, 0xB0, 0x59, 0x2C, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9}, - {0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE8, 0x1B, 0x58, 0x64, 0x47, 0x41, 0x37, 0xD9} + {0xAA, 0x19, 0x0F, 0xFA, 0x4C, 0x30, 0x3B, 0x2E, 0xE6, 0xD8, 0x9A, 0xCF, 0xE5, 0x3F, 0xB3, 0x4B} }; bool usecase_is_invalid(unsigned int usecase) { From 46c50f2cbe4e1e3b341354468518114f3cbc16ac Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 6 Dec 2018 13:16:33 -0800 Subject: [PATCH 298/489] dmnt: Add TargetIO_Open/Close/Read/Write funcs. --- stratosphere/dmnt/source/dmnt_main.cpp | 2 +- ...mnt_debug_monitor.hpp => dmnt_service.hpp} | 13 +- ...bug_monitor.cpp => dmnt_service_debug.cpp} | 2 +- .../dmnt/source/dmnt_service_target_io.cpp | 195 ++++++++++++++++++ 4 files changed, 206 insertions(+), 6 deletions(-) rename stratosphere/dmnt/source/{dmnt_debug_monitor.hpp => dmnt_service.hpp} (91%) rename stratosphere/dmnt/source/{dmnt_debug_monitor.cpp => dmnt_service_debug.cpp} (98%) create mode 100644 stratosphere/dmnt/source/dmnt_service_target_io.cpp diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index dbf936635..fc4917faa 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -23,7 +23,7 @@ #include <atmosphere.h> #include <stratosphere.hpp> -#include "dmnt_debug_monitor.hpp" +#include "dmnt_service.hpp" extern "C" { extern u32 __start__; diff --git a/stratosphere/dmnt/source/dmnt_debug_monitor.hpp b/stratosphere/dmnt/source/dmnt_service.hpp similarity index 91% rename from stratosphere/dmnt/source/dmnt_debug_monitor.hpp rename to stratosphere/dmnt/source/dmnt_service.hpp index bd73d4a88..4959657fa 100644 --- a/stratosphere/dmnt/source/dmnt_debug_monitor.hpp +++ b/stratosphere/dmnt/source/dmnt_service.hpp @@ -81,6 +81,11 @@ class DebugMonitorService final : public IServiceObject { Result GetProcessId(Out<u64> out_pid, Handle hnd); Result GetProcessHandle(Out<Handle> out_hnd, u64 pid); Result WaitSynchronization(Handle hnd, u64 ns); + + Result TargetIO_FileOpen(OutBuffer<u64> out_hnd, InBuffer<char> path, int open_mode, u32 create_mode); + Result TargetIO_FileClose(InBuffer<u64> hnd); + Result TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8> out_data, Out<u32> out_read, u64 offset); + Result TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8> data, Out<u32> out_written, u64 offset); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<DebugMonitor_Cmd_BreakDebugProcess, &DebugMonitorService::BreakDebugProcess>(), @@ -110,10 +115,10 @@ class DebugMonitorService final : public IServiceObject { // MakeServiceCommandMeta<DebugMonitor_Cmd_GetJitDebugProcessList, &DebugMonitorService::GetJitDebugProcessList>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_CreateCoreDump, &DebugMonitorService::CreateCoreDump>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_GetAllDebugThreadInfo, &DebugMonitorService::GetAllDebugThreadInfo>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileOpen, &DebugMonitorService::TargetIO_FileOpen>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileClose, &DebugMonitorService::TargetIO_FileClose>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileRead, &DebugMonitorService::TargetIO_FileRead>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileWrite, &DebugMonitorService::TargetIO_FileWrite>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileOpen, &DebugMonitorService::TargetIO_FileOpen>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileClose, &DebugMonitorService::TargetIO_FileClose>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileRead, &DebugMonitorService::TargetIO_FileRead>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileWrite, &DebugMonitorService::TargetIO_FileWrite>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetAttributes, &DebugMonitorService::TargetIO_FileSetAttributes>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileGetInformation, &DebugMonitorService::TargetIO_FileGetInformation>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetTime, &DebugMonitorService::TargetIO_FileSetTime>(), diff --git a/stratosphere/dmnt/source/dmnt_debug_monitor.cpp b/stratosphere/dmnt/source/dmnt_service_debug.cpp similarity index 98% rename from stratosphere/dmnt/source/dmnt_debug_monitor.cpp rename to stratosphere/dmnt/source/dmnt_service_debug.cpp index 2e287e6eb..2c384a910 100644 --- a/stratosphere/dmnt/source/dmnt_debug_monitor.cpp +++ b/stratosphere/dmnt/source/dmnt_service_debug.cpp @@ -15,7 +15,7 @@ */ #include <switch.h> -#include "dmnt_debug_monitor.hpp" +#include "dmnt_service.hpp" Result DebugMonitorService::BreakDebugProcess(Handle debug_hnd) { /* Nintendo discards the output of this command, but we will return it. */ diff --git a/stratosphere/dmnt/source/dmnt_service_target_io.cpp b/stratosphere/dmnt/source/dmnt_service_target_io.cpp new file mode 100644 index 000000000..15f8e0889 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_service_target_io.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <unordered_map> +#include <switch.h> +#include "dmnt_service.hpp" + +enum TIOCreateOption : u32 { + TIOCreateOption_CreateNew = 1, + TIOCreateOption_CreateAlways = 2, + TIOCreateOption_OpenExisting = 3, + TIOCreateOption_OpenAlways = 4, + TIOCreateOption_ResetSize = 5, +}; + +/* Nintendo uses actual pointers as file handles. We'll add a layer of indirection... */ +static bool g_sd_initialized = false; +static HosMutex g_sd_lock; +static FsFileSystem g_sd_fs; + +static HosMutex g_file_handle_lock; +static u64 g_cur_fd = 0; +static std::unordered_map<u64, FsFile> g_file_handles; + +static Result EnsureSdInitialized() { + std::scoped_lock<HosMutex> lk(g_sd_lock); + if (g_sd_initialized) { + return 0; + } + + Result rc = fsMountSdcard(&g_sd_fs); + if (R_SUCCEEDED(rc)) { + g_sd_initialized = true; + } + return rc; +} + +static u64 GetFileHandle(FsFile f) { + std::scoped_lock<HosMutex> lk(g_file_handle_lock); + + u64 fd = g_cur_fd++; + g_file_handles[fd] = f; + return fd; +} + +static Result GetFileByHandle(FsFile *out, u64 handle) { + std::scoped_lock<HosMutex> lk(g_file_handle_lock); + if (g_file_handles.find(handle) != g_file_handles.end()) { + *out = g_file_handles[handle]; + return 0; + } + return 0x2EE202; +} + +static Result CloseFileByHandle(u64 handle) { + std::scoped_lock<HosMutex> lk(g_file_handle_lock); + if (g_file_handles.find(handle) != g_file_handles.end()) { + fsFileClose(&g_file_handles[handle]); + g_file_handles.erase(handle); + return 0; + } + return 0x2EE202; +} + +static void FixPath(char *dst, size_t dst_size, InBuffer<char> &path) { + dst[dst_size - 1] = 0; + strncpy(dst, "/", dst_size - 1); + + const char *src = path.buffer; + size_t src_idx = 0; + size_t dst_idx = 1; + while (src_idx < path.num_elements && (src[src_idx] == '/' || src[src_idx] == '\\')) { + src_idx++; + } + + while (src_idx < path.num_elements && dst_idx < dst_size - 1 && src[src_idx] != 0) { + if (src[src_idx] == '\\') { + dst[dst_idx] = '/'; + } else { + dst[dst_idx] = src[src_idx]; + } + + src_idx++; + dst_idx++; + } + + if (dst_idx < dst_size) { + dst[dst_idx] = 0; + } +} + +Result DebugMonitorService::TargetIO_FileOpen(OutBuffer<u64> out_hnd, InBuffer<char> path, int open_mode, u32 create_mode) { + if (out_hnd.num_elements != 1) { + return 0xF601; + } + + Result rc = EnsureSdInitialized(); + if (R_FAILED(rc)) { + return rc; + } + + char fs_path[FS_MAX_PATH]; + + FixPath(fs_path, sizeof(fs_path), path); + + if (create_mode == TIOCreateOption_CreateAlways) { + fsFsDeleteFile(&g_sd_fs, fs_path); + rc = fsFsCreateFile(&g_sd_fs, fs_path, 0, 0); + } else if (create_mode == TIOCreateOption_CreateNew) { + rc = fsFsCreateFile(&g_sd_fs, fs_path, 0, 0); + } + + if (R_FAILED(rc)) { + return rc; + } + + FsFile f; + rc = fsFsOpenFile(&g_sd_fs, fs_path, open_mode, &f); + if (R_FAILED(rc)) { + if (create_mode == TIOCreateOption_OpenAlways) { + fsFsCreateFile(&g_sd_fs, fs_path, 0, 0); + rc = fsFsOpenFile(&g_sd_fs, fs_path, open_mode, &f); + } + } + + if (R_SUCCEEDED(rc)) { + if (create_mode == TIOCreateOption_ResetSize) { + rc = fsFileSetSize(&f, 0); + } + if (R_SUCCEEDED(rc)) { + out_hnd[0] = GetFileHandle(f); + } else { + fsFileClose(&f); + } + } + + return rc; +} + +Result DebugMonitorService::TargetIO_FileClose(InBuffer<u64> hnd) { + if (hnd.num_elements != 1) { + return 0xF601; + } + + return CloseFileByHandle(hnd[0]); +} + +Result DebugMonitorService::TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8> out_data, Out<u32> out_read, u64 offset) { + if (hnd.num_elements != 1) { + return 0xF601; + } + + FsFile f; + Result rc = GetFileByHandle(&f, hnd[0]); + if (R_FAILED(rc)) { + return rc; + } + + size_t read = 0; + rc = fsFileRead(&f, offset, out_data.buffer, out_data.num_elements, &read); + out_read.SetValue(static_cast<u32>(read)); + return rc; +} + +Result DebugMonitorService::TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8> data, Out<u32> out_written, u64 offset) { + if (hnd.num_elements != 1) { + return 0xF601; + } + + FsFile f; + Result rc = GetFileByHandle(&f, hnd[0]); + if (R_FAILED(rc)) { + return rc; + } + + rc = fsFileWrite(&f, offset, data.buffer, data.num_elements); + if (R_SUCCEEDED(rc)) { + out_written.SetValue(data.num_elements); + } + + return rc; +} From 6b04c937e6c40e72602a3856c778f63f4b267c8f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 6 Dec 2018 13:39:27 -0800 Subject: [PATCH 299/489] dmnt: Add remaining TargetIO_File* funcs --- stratosphere/dmnt/source/dmnt_service.hpp | 18 ++- .../dmnt/source/dmnt_service_target_io.cpp | 106 +++++++++++++++++- 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_service.hpp b/stratosphere/dmnt/source/dmnt_service.hpp index 4959657fa..c35801680 100644 --- a/stratosphere/dmnt/source/dmnt_service.hpp +++ b/stratosphere/dmnt/source/dmnt_service.hpp @@ -86,6 +86,12 @@ class DebugMonitorService final : public IServiceObject { Result TargetIO_FileClose(InBuffer<u64> hnd); Result TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8> out_data, Out<u32> out_read, u64 offset); Result TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8> data, Out<u32> out_written, u64 offset); + Result TargetIO_FileSetAttributes(InBuffer<char> path, InBuffer<u8> attributes); + Result TargetIO_FileGetInformation(InBuffer<char> path, OutBuffer<u64> out_info, Out<int> is_directory); + Result TargetIO_FileSetTime(InBuffer<char> path, u64 create, u64 access, u64 modify); + Result TargetIO_FileSetSize(InBuffer<char> path, u64 size); + Result TargetIO_FileDelete(InBuffer<char> path); + Result TargetIO_FileMove(InBuffer<char> path0, InBuffer<char> path1); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<DebugMonitor_Cmd_BreakDebugProcess, &DebugMonitorService::BreakDebugProcess>(), @@ -119,12 +125,12 @@ class DebugMonitorService final : public IServiceObject { MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileClose, &DebugMonitorService::TargetIO_FileClose>(), MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileRead, &DebugMonitorService::TargetIO_FileRead>(), MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileWrite, &DebugMonitorService::TargetIO_FileWrite>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetAttributes, &DebugMonitorService::TargetIO_FileSetAttributes>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileGetInformation, &DebugMonitorService::TargetIO_FileGetInformation>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetTime, &DebugMonitorService::TargetIO_FileSetTime>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetSize, &DebugMonitorService::TargetIO_FileSetSize>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileDelete, &DebugMonitorService::TargetIO_FileDelete>(), - // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileMove, &DebugMonitorService::TargetIO_FileMove>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetAttributes, &DebugMonitorService::TargetIO_FileSetAttributes>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileGetInformation, &DebugMonitorService::TargetIO_FileGetInformation>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetTime, &DebugMonitorService::TargetIO_FileSetTime>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileSetSize, &DebugMonitorService::TargetIO_FileSetSize>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileDelete, &DebugMonitorService::TargetIO_FileDelete>(), + MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_FileMove, &DebugMonitorService::TargetIO_FileMove>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryCreate, &DebugMonitorService::TargetIO_DirectoryCreate>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryDelete, &DebugMonitorService::TargetIO_DirectoryDelete>(), // MakeServiceCommandMeta<DebugMonitor_Cmd_TargetIO_DirectoryRename, &DebugMonitorService::TargetIO_DirectoryRename>(), diff --git a/stratosphere/dmnt/source/dmnt_service_target_io.cpp b/stratosphere/dmnt/source/dmnt_service_target_io.cpp index 15f8e0889..6699ff3d0 100644 --- a/stratosphere/dmnt/source/dmnt_service_target_io.cpp +++ b/stratosphere/dmnt/source/dmnt_service_target_io.cpp @@ -113,7 +113,6 @@ Result DebugMonitorService::TargetIO_FileOpen(OutBuffer<u64> out_hnd, InBuffer<c } char fs_path[FS_MAX_PATH]; - FixPath(fs_path, sizeof(fs_path), path); if (create_mode == TIOCreateOption_CreateAlways) { @@ -193,3 +192,108 @@ Result DebugMonitorService::TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8> d return rc; } + +Result DebugMonitorService::TargetIO_FileSetAttributes(InBuffer<char> path, InBuffer<u8> attributes) { + /* I don't really know why this command exists, Horizon doesn't allow you to set any attributes. */ + /* N just returns 0x0 unconditionally here. */ + return 0x0; +} + +Result DebugMonitorService::TargetIO_FileGetInformation(InBuffer<char> path, OutBuffer<u64> out_info, Out<int> is_directory) { + if (out_info.num_elements != 4) { + return 0xF601; + } + + Result rc = EnsureSdInitialized(); + if (R_FAILED(rc)) { + return rc; + } + + char fs_path[FS_MAX_PATH]; + FixPath(fs_path, sizeof(fs_path), path); + + for (size_t i = 0; i < out_info.num_elements; i++) { + out_info[i] = 0; + } + is_directory.SetValue(0); + + FsFile f; + rc = fsFsOpenFile(&g_sd_fs, fs_path, FS_OPEN_READ, &f); + if (R_SUCCEEDED(rc)) { + ON_SCOPE_EXIT { fsFileClose(&f); }; + + /* N doesn't check this return code. */ + fsFileGetSize(&f, &out_info[0]); + + /* TODO: N does not call fsFsGetFileTimestampRaw here, but we possibly could. */ + } else { + FsDir dir; + rc = fsFsOpenDirectory(&g_sd_fs, fs_path, FS_DIROPEN_FILE | FS_DIROPEN_DIRECTORY, &dir); + if (R_SUCCEEDED(rc)) { + fsDirClose(&dir); + is_directory.SetValue(1); + } + } + + return rc; +} + +Result DebugMonitorService::TargetIO_FileSetTime(InBuffer<char> path, u64 create, u64 access, u64 modify) { + /* This is another function that doesn't really need to exist, because Horizon doesn't let you set anything. */ + return 0x0; +} + +Result DebugMonitorService::TargetIO_FileSetSize(InBuffer<char> input, u64 size) { + /* Why does this function take in a path and not a file handle? */ + + /* We will try to be better than N, here. N only treats input as a path. */ + if (input.num_elements == sizeof(u64)) { + FsFile f; + if (R_SUCCEEDED(GetFileByHandle(&f, reinterpret_cast<u64 *>(input.buffer)[0]))) { + return fsFileSetSize(&f, size); + } + } + + Result rc = EnsureSdInitialized(); + if (R_FAILED(rc)) { + return rc; + } + + char fs_path[FS_MAX_PATH]; + FixPath(fs_path, sizeof(fs_path), input); + + FsFile f; + rc = fsFsOpenFile(&g_sd_fs, fs_path, FS_OPEN_WRITE, &f); + if (R_SUCCEEDED(rc)) { + rc = fsFileSetSize(&f, size); + fsFileClose(&f); + } + + return rc; +} + +Result DebugMonitorService::TargetIO_FileDelete(InBuffer<char> path) { + Result rc = EnsureSdInitialized(); + if (R_FAILED(rc)) { + return rc; + } + + char fs_path[FS_MAX_PATH]; + FixPath(fs_path, sizeof(fs_path), path); + + return fsFsDeleteFile(&g_sd_fs, fs_path); +} + +Result DebugMonitorService::TargetIO_FileMove(InBuffer<char> path0, InBuffer<char> path1) { + Result rc = EnsureSdInitialized(); + if (R_FAILED(rc)) { + return rc; + } + + char fs_path0[FS_MAX_PATH]; + char fs_path1[FS_MAX_PATH]; + FixPath(fs_path0, sizeof(fs_path0), path0); + FixPath(fs_path1, sizeof(fs_path1), path1); + + return fsFsRenameFile(&g_sd_fs, fs_path0, fs_path1); +} From efcce68a5677ddea27adedbb21721197c6efd52b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 6 Dec 2018 13:55:02 -0800 Subject: [PATCH 300/489] tma: Correct JSON to work as non-kip --- stratosphere/tma/tma.json | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/stratosphere/tma/tma.json b/stratosphere/tma/tma.json index e67d99b1f..b1f3d99e3 100644 --- a/stratosphere/tma/tma.json +++ b/stratosphere/tma/tma.json @@ -6,8 +6,6 @@ "main_thread_stack_size": "0x00004000", "main_thread_priority": 38, "default_cpu_id": 3, - "process_category": 1, - "default_cpu_id": 3, "process_category": 0, "is_retail": true, "pool_partition": 2, @@ -39,8 +37,15 @@ "tma_log", "tmagent" ], - "kernel_capabilities": [ - { + "kernel_capabilities": [{ + "type": "kernel_flags", + "value": { + "highest_thread_priority": 63, + "lowest_thread_priority": 24, + "lowest_cpu_id": 0, + "highest_cpu_id": 3 + } + }, { "type": "syscalls", "value": { "svcSetHeapSize": "0x01", @@ -131,6 +136,9 @@ }, { "type": "irq_pair", "value": [131, 132] + }, { + "type": "min_kernel_version", + "value": "0x0030" }, { "type": "handle_table_size", "value": 256 From 600ad660a680df9e895dbbadd53e12a7f17fc678 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 6 Dec 2018 15:32:27 -0800 Subject: [PATCH 301/489] tma: First pass at tio file read/write --- stratosphere/dmnt/source/dmnt_service.hpp | 4 +- .../dmnt/source/dmnt_service_target_io.cpp | 4 +- stratosphere/tma/Makefile | 2 +- stratosphere/tma/client/Main.py | 17 +- stratosphere/tma/client/ServiceId.py | 3 +- stratosphere/tma/source/dmnt.c | 188 ++++++++++++++++++ stratosphere/tma/source/dmnt.h | 46 +++++ .../tma/source/target_io/tio_service.cpp | 47 +++++ .../tma/source/target_io/tio_service.hpp | 35 ++++ .../tma/source/target_io/tio_task.cpp | 152 ++++++++++++++ .../tma/source/target_io/tio_task.hpp | 85 ++++++++ stratosphere/tma/source/tma_conn_packet.hpp | 4 + stratosphere/tma/source/tma_main.cpp | 8 + stratosphere/tma/source/tma_target.cpp | 2 + stratosphere/tma/source/tma_task.cpp | 15 ++ stratosphere/tma/source/tma_task.hpp | 3 + 16 files changed, 600 insertions(+), 15 deletions(-) create mode 100644 stratosphere/tma/source/dmnt.c create mode 100644 stratosphere/tma/source/dmnt.h create mode 100644 stratosphere/tma/source/target_io/tio_service.cpp create mode 100644 stratosphere/tma/source/target_io/tio_service.hpp create mode 100644 stratosphere/tma/source/target_io/tio_task.cpp create mode 100644 stratosphere/tma/source/target_io/tio_task.hpp diff --git a/stratosphere/dmnt/source/dmnt_service.hpp b/stratosphere/dmnt/source/dmnt_service.hpp index c35801680..ecb2f8f50 100644 --- a/stratosphere/dmnt/source/dmnt_service.hpp +++ b/stratosphere/dmnt/source/dmnt_service.hpp @@ -84,8 +84,8 @@ class DebugMonitorService final : public IServiceObject { Result TargetIO_FileOpen(OutBuffer<u64> out_hnd, InBuffer<char> path, int open_mode, u32 create_mode); Result TargetIO_FileClose(InBuffer<u64> hnd); - Result TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8> out_data, Out<u32> out_read, u64 offset); - Result TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8> data, Out<u32> out_written, u64 offset); + Result TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8, BufferType_Type1> out_data, Out<u32> out_read, u64 offset); + Result TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8, BufferType_Type1> data, Out<u32> out_written, u64 offset); Result TargetIO_FileSetAttributes(InBuffer<char> path, InBuffer<u8> attributes); Result TargetIO_FileGetInformation(InBuffer<char> path, OutBuffer<u64> out_info, Out<int> is_directory); Result TargetIO_FileSetTime(InBuffer<char> path, u64 create, u64 access, u64 modify); diff --git a/stratosphere/dmnt/source/dmnt_service_target_io.cpp b/stratosphere/dmnt/source/dmnt_service_target_io.cpp index 6699ff3d0..ef56cfdbd 100644 --- a/stratosphere/dmnt/source/dmnt_service_target_io.cpp +++ b/stratosphere/dmnt/source/dmnt_service_target_io.cpp @@ -157,7 +157,7 @@ Result DebugMonitorService::TargetIO_FileClose(InBuffer<u64> hnd) { return CloseFileByHandle(hnd[0]); } -Result DebugMonitorService::TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8> out_data, Out<u32> out_read, u64 offset) { +Result DebugMonitorService::TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8, BufferType_Type1> out_data, Out<u32> out_read, u64 offset) { if (hnd.num_elements != 1) { return 0xF601; } @@ -174,7 +174,7 @@ Result DebugMonitorService::TargetIO_FileRead(InBuffer<u64> hnd, OutBuffer<u8> o return rc; } -Result DebugMonitorService::TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8> data, Out<u32> out_written, u64 offset) { +Result DebugMonitorService::TargetIO_FileWrite(InBuffer<u64> hnd, InBuffer<u8, BufferType_Type1> data, Out<u32> out_written, u64 offset) { if (hnd.num_elements != 1) { return 0xF601; } diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile index 6b5faa89c..085537f4a 100644 --- a/stratosphere/tma/Makefile +++ b/stratosphere/tma/Makefile @@ -19,7 +19,7 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := source source/test source/settings +SOURCES := source source/test source/settings source/target_io DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src diff --git a/stratosphere/tma/client/Main.py b/stratosphere/tma/client/Main.py index 4fabfc7b5..fe4687856 100644 --- a/stratosphere/tma/client/Main.py +++ b/stratosphere/tma/client/Main.py @@ -20,16 +20,15 @@ def main(argc, argv): print 'Waiting for connection...' c.wait_connected() print 'Connected!' - c.intf.send_packet(Packet().set_service(ServiceId.SETTINGS_SERVICE).set_task(0x01000000).set_cmd(0).write_str('platformconfig').write_str('platformtype')) + print 'Reading atmosphere/BCT.ini...' + c.intf.send_packet(Packet().set_service(ServiceId.TARGETIO_SERVICE).set_task(0x01000000).set_cmd(2).write_str('atmosphere/BCT.ini').write_u64(0x109).write_u64(0)) resp = c.intf.read_packet() - success = resp.read_u8() != 0 - print 'Succeeded: %s' % str(success) - if success: - size = resp.read_u32() - value = resp.body[resp.offset:resp.offset+size] - print 'Value Size: 0x%x' % size - print 'Value: %s' % repr(value) - + res_packet = c.intf.read_packet() + read_res, size_read = resp.read_u32(), resp.read_u32() + print 'Final Result: 0x%x' % res_packet.read_u32() + print 'Size Read: 0x%x' % size_read + print 'Data:\n%s' % resp.body[resp.offset:] + return 0 if __name__ == '__main__': diff --git a/stratosphere/tma/client/ServiceId.py b/stratosphere/tma/client/ServiceId.py index e943313a6..4e4327f91 100644 --- a/stratosphere/tma/client/ServiceId.py +++ b/stratosphere/tma/client/ServiceId.py @@ -25,5 +25,6 @@ USB_CONNECT = hash("USBConnect") USB_DISCONNECT = hash("USBDisconnect") ATMOSPHERE_TEST_SERVICE = hash("AtmosphereTestService") -SETTINGS_SERVICE = hash ("SettingsService") +SETTINGS_SERVICE = hash("SettingsService") +TARGETIO_SERVICE = hash("TIOService") \ No newline at end of file diff --git a/stratosphere/tma/source/dmnt.c b/stratosphere/tma/source/dmnt.c new file mode 100644 index 000000000..c79f7765c --- /dev/null +++ b/stratosphere/tma/source/dmnt.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "dmnt.h" + +static Service g_dmntSrv; +static u64 g_refCnt; + +Result dmntInitialize(void) { + atomicIncrement64(&g_refCnt); + + if (serviceIsActive(&g_dmntSrv)) + return 0; + + return smGetService(&g_dmntSrv, "dmnt:-"); +} + +void dmntExit(void) { + if (atomicDecrement64(&g_refCnt) == 0) + serviceClose(&g_dmntSrv); +} + +Result dmntTargetIOFileOpen(DmntFile *out, const char *path, int flags, DmntTIOCreateOption create_option) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, path, FS_MAX_PATH, BufferType_Normal); + ipcAddRecvBuffer(&c, out, sizeof(*out), BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + int flags; + u32 create_option; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 29; + raw->flags = flags; + raw->create_option = create_option; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result dmntTargetIOFileClose(DmntFile *f) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, f, sizeof(*f), BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 30; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result dmntTargetIOFileRead(DmntFile *f, u64 off, void* buf, size_t len, size_t *out_read) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, f, sizeof(*f), BufferType_Normal); + ipcAddRecvBuffer(&c, buf, len, BufferType_Type1); + + struct { + u64 magic; + u64 cmd_id; + u64 offset; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 31; + raw->offset = off; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u32 out_read; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out_read) { + *out_read = resp->out_read; + } + } + + return rc; +} + +Result dmntTargetIOFileWrite(DmntFile *f, u64 off, const void* buf, size_t len, size_t *out_written) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, f, sizeof(*f), BufferType_Normal); + ipcAddSendBuffer(&c, buf, len, BufferType_Type1); + + struct { + u64 magic; + u64 cmd_id; + u64 offset; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 32; + raw->offset = off; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u32 out_written; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out_written) { + *out_written = resp->out_written; + } + } + + return rc; +} diff --git a/stratosphere/tma/source/dmnt.h b/stratosphere/tma/source/dmnt.h new file mode 100644 index 000000000..15382fb53 --- /dev/null +++ b/stratosphere/tma/source/dmnt.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + u64 handle; +} DmntFile; + +typedef enum { + DmntTIOCreateOption_CreateNew = 1, + DmntTIOCreateOption_CreateAlways = 2, + DmntTIOCreateOption_OpenExisting = 3, + DmntTIOCreateOption_OpenAlways = 4, + DmntTIOCreateOption_ResetSize = 5, +} DmntTIOCreateOption; + +Result dmntInitialize(void); +void dmntExit(void); + +Result dmntTargetIOFileOpen(DmntFile *out, const char *path, int flags, DmntTIOCreateOption create_option); +Result dmntTargetIOFileClose(DmntFile *f); +Result dmntTargetIOFileRead(DmntFile *f, u64 off, void* buf, size_t len, size_t* out_read); +Result dmntTargetIOFileWrite(DmntFile *f, u64 off, const void* buf, size_t len, size_t* out_written); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/stratosphere/tma/source/target_io/tio_service.cpp b/stratosphere/tma/source/target_io/tio_service.cpp new file mode 100644 index 000000000..84edaba83 --- /dev/null +++ b/stratosphere/tma/source/target_io/tio_service.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> + +#include "tio_service.hpp" +#include "tio_task.hpp" + +TmaTask *TIOService::NewTask(TmaPacket *packet) { + TmaTask *new_task = nullptr; + switch (packet->GetCommand()) { + case TIOServiceCmd_FileRead: + { + new_task = new TIOFileReadTask(this->manager); + } + break; + case TIOServiceCmd_FileWrite: + { + new_task = new TIOFileWriteTask(this->manager); + } + break; + default: + new_task = nullptr; + break; + } + if (new_task != nullptr) { + new_task->SetServiceId(this->GetServiceId()); + new_task->SetTaskId(packet->GetTaskId()); + new_task->OnStart(packet); + } + + return new_task; +} diff --git a/stratosphere/tma/source/target_io/tio_service.hpp b/stratosphere/tma/source/target_io/tio_service.hpp new file mode 100644 index 000000000..110439468 --- /dev/null +++ b/stratosphere/tma/source/target_io/tio_service.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "../tma_conn_service_ids.hpp" +#include "../tma_service.hpp" + +enum TIOServiceCmd : u32 { + TIOServiceCmd_FileRead = 2, + TIOServiceCmd_FileWrite = 3, +}; + +class TIOService : public TmaService { + public: + TIOService(TmaServiceManager *m) : TmaService(m, "TIOService") { } + virtual ~TIOService() { } + + virtual TmaTask *NewTask(TmaPacket *packet) override; +}; \ No newline at end of file diff --git a/stratosphere/tma/source/target_io/tio_task.cpp b/stratosphere/tma/source/target_io/tio_task.cpp new file mode 100644 index 000000000..528efeb99 --- /dev/null +++ b/stratosphere/tma/source/target_io/tio_task.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> + +#include "tio_task.hpp" + + +void TIOFileReadTask::OnStart(TmaPacket *packet) { + char path[FS_MAX_PATH]; + + packet->ReadString(path, sizeof(path), nullptr); + packet->Read<u64>(this->size_remaining); + packet->Read<u64>(this->cur_offset); + + if (strlen(path) == 0) { + this->SendResult(0x202); + return; + } + + Result rc = dmntTargetIOFileOpen(&this->handle, path, FS_OPEN_READ, DmntTIOCreateOption_OpenExisting); + if (R_FAILED(rc)) { + this->SendResult(rc); + return; + } else { + auto packet = this->AllocateSendPacket(); + rc = this->ProcessPacket(packet); + if (R_SUCCEEDED(rc)) { + this->manager->SendPacket(packet); + if (this->size_remaining) { + this->SetNeedsPackets(true); + } else { + this->SendResult(rc); + } + } else { + this->manager->FreePacket(packet); + this->SendResult(rc); + } + } +} + +void TIOFileReadTask::OnSendPacket(TmaPacket *packet) { + Result rc = this->ProcessPacket(packet); + + if (this->size_remaining == 0 || R_FAILED(rc)) { + this->SendResult(rc); + } +} + +void TIOFileReadTask::SendResult(Result rc) { + dmntTargetIOFileClose(&this->handle); + this->SetNeedsPackets(false); + + auto packet = this->AllocateSendPacket(); + packet->Write<Result>(rc); + this->manager->SendPacket(packet); + Complete(); +} + +Result TIOFileReadTask::ProcessPacket(TmaPacket *packet) { + Result rc = 0x196002; + + size_t cur_read = static_cast<u32>((this->size_remaining > MaxDataSize) ? MaxDataSize : this->size_remaining); + + u8 *buf = new u8[cur_read]; + if (buf != nullptr) { + size_t actual_read = 0; + rc = dmntTargetIOFileRead(&this->handle, this->cur_offset, buf, cur_read, &actual_read); + if (R_SUCCEEDED(rc)) { + packet->Write<Result>(rc); + packet->Write<u32>(actual_read); + packet->Write(buf, actual_read); + this->cur_offset += actual_read; + this->size_remaining -= actual_read; + } + + delete buf; + } + + return rc; +} + +void TIOFileWriteTask::OnStart(TmaPacket *packet) { + char path[FS_MAX_PATH]; + + packet->ReadString(path, sizeof(path), nullptr); + packet->Read<u64>(this->size_remaining); + packet->Read<u64>(this->cur_offset); + + if (strlen(path) == 0) { + this->SendResult(0x202); + return; + } + + Result rc = dmntTargetIOFileOpen(&this->handle, path, FS_OPEN_READ, DmntTIOCreateOption_OpenExisting); + if (R_FAILED(rc)) { + this->SendResult(rc); + } +} + +void TIOFileWriteTask::OnReceivePacket(TmaPacket *packet) { + Result rc = this->ProcessPacket(packet); + + if (this->size_remaining == 0 || R_FAILED(rc)) { + this->SendResult(rc); + } +} + +void TIOFileWriteTask::SendResult(Result rc) { + dmntTargetIOFileClose(&this->handle); + + auto packet = this->AllocateSendPacket(); + packet->Write<Result>(rc); + this->manager->SendPacket(packet); + Complete(); +} + +Result TIOFileWriteTask::ProcessPacket(TmaPacket *packet) { + Result rc = 0x196002; + + /* Note: N does not bounds check this. We do. */ + u32 cur_write = 0; + packet->Read<u32>(cur_write); + + size_t actual_written = 0; + if (cur_write < MaxDataSize) { + if (cur_write > this->size_remaining) { + cur_write = this->size_remaining; + } + rc = dmntTargetIOFileWrite(&this->handle, this->cur_offset, packet->GetCurrentBodyPtr(), cur_write, &actual_written); + if (R_SUCCEEDED(rc)) { + this->size_remaining -= actual_written; + this->cur_offset += actual_written; + } + } + + return rc; +} \ No newline at end of file diff --git a/stratosphere/tma/source/target_io/tio_task.hpp b/stratosphere/tma/source/target_io/tio_task.hpp new file mode 100644 index 000000000..7a3307fd3 --- /dev/null +++ b/stratosphere/tma/source/target_io/tio_task.hpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "../tma_task.hpp" +#include "../tma_service_manager.hpp" +#include "../dmnt.h" + +class TIOTask : public TmaTask { + public: + TIOTask(TmaServiceManager *m) : TmaTask(m) { } + virtual ~TIOTask() { } + + virtual void SendResult(Result rc) { + TmaPacket *packet = this->AllocateSendPacket(); + packet->Write<Result>(rc); + this->manager->SendPacket(packet); + this->Complete(); + } + + virtual void OnStart(TmaPacket *packet) = 0; + + virtual void OnReceivePacket(TmaPacket *packet) override { + this->Complete(); + } + + virtual void OnSendPacket(TmaPacket *packet) override { + this->Complete(); + } +}; + +class TIOFileReadTask : public TIOTask { + private: + static constexpr size_t HeaderSize = sizeof(Result) + sizeof(u32); + static constexpr size_t MaxDataSize = TmaPacket::MaxBodySize - HeaderSize; + private: + DmntFile handle = {0}; + u64 size_remaining = 0; + u64 cur_offset = 0; + public: + TIOFileReadTask(TmaServiceManager *m) : TIOTask(m) { } + virtual ~TIOFileReadTask() { } + + virtual void OnStart(TmaPacket *packet) override; + virtual void OnSendPacket(TmaPacket *packet) override; + virtual void SendResult(Result rc) override; + + Result ProcessPacket(TmaPacket *packet); +}; + +class TIOFileWriteTask : public TIOTask { + private: + static constexpr size_t HeaderSize = sizeof(u32); + static constexpr size_t MaxDataSize = TmaPacket::MaxBodySize - HeaderSize; + private: + DmntFile handle = {0}; + u64 size_remaining = 0; + u64 cur_offset = 0; + public: + TIOFileWriteTask(TmaServiceManager *m) : TIOTask(m) { } + virtual ~TIOFileWriteTask() { } + + virtual void OnStart(TmaPacket *packet) override; + virtual void OnReceivePacket(TmaPacket *packet) override; + virtual void SendResult(Result rc) override; + + Result ProcessPacket(TmaPacket *packet); +}; + diff --git a/stratosphere/tma/source/tma_conn_packet.hpp b/stratosphere/tma/source/tma_conn_packet.hpp index a3df7a3f3..20ccce265 100644 --- a/stratosphere/tma/source/tma_conn_packet.hpp +++ b/stratosphere/tma/source/tma_conn_packet.hpp @@ -166,6 +166,10 @@ class TmaPacket { return GetHeader()->version; } + u8 *GetCurrentBodyPtr() { + return GetBody(this->offset); + } + void ClearOffset() { this->offset = 0; } diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp index d314ed16a..e0d16571e 100644 --- a/stratosphere/tma/source/tma_main.cpp +++ b/stratosphere/tma/source/tma_main.cpp @@ -25,6 +25,8 @@ #include "tma_target.hpp" +#include "dmnt.h" + extern "C" { extern u32 __start__; @@ -70,11 +72,17 @@ void __appInit(void) { fatalSimple(rc); } + rc = dmntInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { /* Cleanup services. */ + dmntExit(); setsysExit(); pscExit(); smExit(); diff --git a/stratosphere/tma/source/tma_target.cpp b/stratosphere/tma/source/tma_target.cpp index 9cfcb335f..2659c2636 100644 --- a/stratosphere/tma/source/tma_target.cpp +++ b/stratosphere/tma/source/tma_target.cpp @@ -27,6 +27,7 @@ #include "test/atmosphere_test_service.hpp" #include "settings/settings_service.hpp" +#include "target_io/tio_service.hpp" struct TmaTargetConfig { char configuration_id1[0x80]; @@ -210,6 +211,7 @@ void TmaTarget::Initialize() { /* TODO: Make this better. */ g_service_manager->AddService(new AtmosphereTestService(g_service_manager)); g_service_manager->AddService(new SettingsService(g_service_manager)); + g_service_manager->AddService(new TIOService(g_service_manager)); RefreshTargetConfig(); diff --git a/stratosphere/tma/source/tma_task.cpp b/stratosphere/tma/source/tma_task.cpp index 6133b5c5e..4fb10ad2d 100644 --- a/stratosphere/tma/source/tma_task.cpp +++ b/stratosphere/tma/source/tma_task.cpp @@ -24,6 +24,21 @@ void TmaTask::SetNeedsPackets(bool n) { this->manager->Tick(); } +TmaPacket *TmaTask::AllocateSendPacket(bool continuation) { + auto packet = this->manager->AllocateSendPacket(); + packet->SetServiceId(this->service_id); + packet->SetTaskId(this->task_id); + packet->SetCommand(this->command); + packet->SetContinuation(continuation); + + return packet; +} + + +void TmaTask::FreePacket(TmaPacket *packet) { + this->manager->FreePacket(packet); +} + void TmaTask::Complete() { SetNeedsPackets(false); this->state = TmaTaskState::Complete; diff --git a/stratosphere/tma/source/tma_task.hpp b/stratosphere/tma/source/tma_task.hpp index 686a7a50d..7f17ffc7b 100644 --- a/stratosphere/tma/source/tma_task.hpp +++ b/stratosphere/tma/source/tma_task.hpp @@ -68,6 +68,9 @@ class TmaTask { void Signal() { this->signal.Signal(); } void ResetSignal() { this->signal.Reset(); } + TmaPacket *AllocateSendPacket(bool continuation = true); + void FreePacket(TmaPacket *packet); + void Complete(); void Cancel(); From f79f4d175bd4ffad041e3e32820f484653d8ff98 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 6 Dec 2018 20:21:15 -0800 Subject: [PATCH 302/489] tma: add more dmnt wrapper commands --- stratosphere/tma/source/dmnt.c | 98 ++++++++++++++++++++++++++++++++++ stratosphere/tma/source/dmnt.h | 11 ++++ 2 files changed, 109 insertions(+) diff --git a/stratosphere/tma/source/dmnt.c b/stratosphere/tma/source/dmnt.c index c79f7765c..d8124520a 100644 --- a/stratosphere/tma/source/dmnt.c +++ b/stratosphere/tma/source/dmnt.c @@ -186,3 +186,101 @@ Result dmntTargetIOFileWrite(DmntFile *f, u64 off, const void* buf, size_t len, return rc; } + +Result dmntTargetIOFileGetInformation(const char *path, bool *out_is_dir, DmntFileInformation *out_info) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, path, FS_MAX_PATH, BufferType_Normal); + ipcAddRecvBuffer(&c, out_info, sizeof(*out_info), BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 34; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + int is_dir; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *out_is_dir = resp->is_dir != 0; + } + } + + return rc; +} + +Result dmntTargetIOFileGetSize(const char *path, u64 *out_size) { + DmntFileInformation info; + bool is_dir; + Result rc = dmntTargetIOFileGetInformation(path, &is_dir, &info); + if (R_SUCCEEDED(rc)) { + if (is_dir) { + /* TODO: error code? */ + rc = 0x202; + } else { + *out_size = info.size; + } + } + return rc; +} + +static Result _dmntTargetIOFileSetSize(const void *arg, size_t arg_size, u64 size) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, arg, arg_size, BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + u64 size; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 36; + raw->size = size; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result dmntTargetIOFileSetSize(const char *path, u64 size) { + return _dmntTargetIOFileSetSize(path, FS_MAX_PATH, size); +} + +Result dmntTargetIOFileSetOpenFileSize(DmntFile *f, u64 size) { + /* Atmosphere extension */ + return _dmntTargetIOFileSetSize(f, sizeof(*f), size); +} diff --git a/stratosphere/tma/source/dmnt.h b/stratosphere/tma/source/dmnt.h index 15382fb53..2858cd96f 100644 --- a/stratosphere/tma/source/dmnt.h +++ b/stratosphere/tma/source/dmnt.h @@ -33,6 +33,13 @@ typedef enum { DmntTIOCreateOption_ResetSize = 5, } DmntTIOCreateOption; +typedef struct { + u64 size; + u64 create_time; + u64 access_time; + u64 modify_time; +} DmntFileInformation; + Result dmntInitialize(void); void dmntExit(void); @@ -40,6 +47,10 @@ Result dmntTargetIOFileOpen(DmntFile *out, const char *path, int flags, DmntTIOC Result dmntTargetIOFileClose(DmntFile *f); Result dmntTargetIOFileRead(DmntFile *f, u64 off, void* buf, size_t len, size_t* out_read); Result dmntTargetIOFileWrite(DmntFile *f, u64 off, const void* buf, size_t len, size_t* out_written); +Result dmntTargetIOFileGetInformation(const char *path, bool *out_is_dir, DmntFileInformation *out_info); +Result dmntTargetIOFileGetSize(const char *path, u64 *out_size); +Result dmntTargetIOFileSetSize(const char *path, u64 size); +Result dmntTargetIOFileSetOpenFileSize(DmntFile *f, u64 size); /* Atmosphere extension */ #ifdef __cplusplus } From 29153af2bcea395ddc1ebf60b88655bfd8630529 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 6 Dec 2018 23:25:16 -0800 Subject: [PATCH 303/489] tma.tio: Improve read/write bounding. --- .../tma/source/target_io/tio_task.cpp | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/stratosphere/tma/source/target_io/tio_task.cpp b/stratosphere/tma/source/target_io/tio_task.cpp index 528efeb99..a8090bd0a 100644 --- a/stratosphere/tma/source/target_io/tio_task.cpp +++ b/stratosphere/tma/source/target_io/tio_task.cpp @@ -27,12 +27,22 @@ void TIOFileReadTask::OnStart(TmaPacket *packet) { packet->Read<u64>(this->size_remaining); packet->Read<u64>(this->cur_offset); + Result rc = 0; if (strlen(path) == 0) { - this->SendResult(0x202); - return; + rc = 0x202; } - Result rc = dmntTargetIOFileOpen(&this->handle, path, FS_OPEN_READ, DmntTIOCreateOption_OpenExisting); + if (R_SUCCEEDED(rc)) { + u64 file_size; + rc = dmntTargetIOFileGetSize(path, &file_size); + if (R_SUCCEEDED(rc)) { + if (file_size < this->cur_offset + this->size_remaining) { + this->size_remaining = file_size - this->cur_offset; + } + } + } + + rc = dmntTargetIOFileOpen(&this->handle, path, FS_OPEN_READ, DmntTIOCreateOption_OpenExisting); if (R_FAILED(rc)) { this->SendResult(rc); return; @@ -101,12 +111,23 @@ void TIOFileWriteTask::OnStart(TmaPacket *packet) { packet->Read<u64>(this->size_remaining); packet->Read<u64>(this->cur_offset); + Result rc = 0; if (strlen(path) == 0) { - this->SendResult(0x202); - return; + rc = 0x202; } - Result rc = dmntTargetIOFileOpen(&this->handle, path, FS_OPEN_READ, DmntTIOCreateOption_OpenExisting); + if (R_SUCCEEDED(rc)) { + u64 file_size; + rc = dmntTargetIOFileGetSize(path, &file_size); + if (R_SUCCEEDED(rc)) { + if (file_size < this->cur_offset + this->size_remaining) { + this->size_remaining = file_size - this->cur_offset; + } + } + } + + rc = dmntTargetIOFileOpen(&this->handle, path, FS_OPEN_READ, DmntTIOCreateOption_OpenExisting); + if (R_FAILED(rc)) { this->SendResult(rc); } From 49d1e65496b7b3c44dbf321d9cbf7771d092d081 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 7 Dec 2018 03:26:06 -0800 Subject: [PATCH 304/489] tma: Fix nn.tma.PmModuleThread priority --- stratosphere/tma/source/tma_power_manager.cpp | 2 +- stratosphere/tma/tma.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/stratosphere/tma/source/tma_power_manager.cpp b/stratosphere/tma/source/tma_power_manager.cpp index 423b7cb90..d71de8592 100644 --- a/stratosphere/tma/source/tma_power_manager.cpp +++ b/stratosphere/tma/source/tma_power_manager.cpp @@ -59,7 +59,7 @@ static void PowerManagerThread(void *arg) { void TmaPowerManager::Initialize(void (*callback)(PscPmState, u32)) { g_pm_callback = callback; - g_pm_thread.Initialize(PowerManagerThread, nullptr, 0x4000, 0x15); + g_pm_thread.Initialize(PowerManagerThread, nullptr, 0x4000, 0x26); g_pm_thread.Start(); } diff --git a/stratosphere/tma/tma.json b/stratosphere/tma/tma.json index b1f3d99e3..81cbac6c6 100644 --- a/stratosphere/tma/tma.json +++ b/stratosphere/tma/tma.json @@ -112,7 +112,8 @@ "svcUnmapDeviceAddressSpace": "0x5c", "svcInvalidateProcessDataCache": "0x5d", "svcStoreProcessDataCache": "0x5e", - "svcFlushProcessDataCache": "0x5f" + "svcFlushProcessDataCache": "0x5f", + "svcCallSecureMonitor": "0x7f" } }, { "type": "map", From cdb7ce3decd2adb2dab86578c2232dd80e74269e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 7 Dec 2018 03:32:24 -0800 Subject: [PATCH 305/489] ams: turn on debugmode by default. --- common/defaults/BCT.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/defaults/BCT.ini b/common/defaults/BCT.ini index 660b456b7..9e34aedc8 100644 --- a/common/defaults/BCT.ini +++ b/common/defaults/BCT.ini @@ -5,7 +5,8 @@ stage2_addr = 0xF0000000 stage2_entrypoint = 0xF0000000 [exosphere] -debugmode = 0 +; Note: Disabling debugmode will cause parts of ams.tma to not work. +debugmode = 1 debugmode_user = 0 [stratosphere] From ef373d954f6adac5b3ffae749294e9c14adf4c15 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 7 Dec 2018 22:17:06 +0000 Subject: [PATCH 306/489] fusee: Fix KFUSE clock. --- fusee/fusee-primary/src/car.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-primary/src/car.c b/fusee/fusee-primary/src/car.c index 5bf8b4331..935dea922 100644 --- a/fusee/fusee-primary/src/car.c +++ b/fusee/fusee-primary/src/car.c @@ -15,6 +15,7 @@ */ #include "car.h" +#include "timers.h" #include "utils.h" static inline uint32_t get_clk_source_reg(CarDevice dev) { @@ -121,7 +122,15 @@ void clkrst_disable(CarDevice dev) { void clkrst_reboot(CarDevice dev) { clkrst_disable(dev); - clkrst_enable(dev); + if (dev == CARDEVICE_KFUSE) { + /* Workaround for KFUSE clock. */ + clk_enable(dev); + udelay(100); + rst_disable(dev); + udelay(200); + } else { + clkrst_enable(dev); + } } void clkrst_enable_fuse_regs(bool enable) { From 00aa283a54d7ace981fe9baebe8126b437d3d5ab Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Fri, 7 Dec 2018 22:18:01 +0000 Subject: [PATCH 307/489] fusee: Fix KFUSE clock. --- fusee/fusee-secondary/src/car.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/car.c b/fusee/fusee-secondary/src/car.c index 5bf8b4331..935dea922 100644 --- a/fusee/fusee-secondary/src/car.c +++ b/fusee/fusee-secondary/src/car.c @@ -15,6 +15,7 @@ */ #include "car.h" +#include "timers.h" #include "utils.h" static inline uint32_t get_clk_source_reg(CarDevice dev) { @@ -121,7 +122,15 @@ void clkrst_disable(CarDevice dev) { void clkrst_reboot(CarDevice dev) { clkrst_disable(dev); - clkrst_enable(dev); + if (dev == CARDEVICE_KFUSE) { + /* Workaround for KFUSE clock. */ + clk_enable(dev); + udelay(100); + rst_disable(dev); + udelay(200); + } else { + clkrst_enable(dev); + } } void clkrst_enable_fuse_regs(bool enable) { From 4827fd71b4fbaec9df9529a468d815eee306a12a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 7 Dec 2018 14:27:46 -0800 Subject: [PATCH 308/489] fusee: Fix race condition involving volatile reads --- fusee/fusee-secondary/src/smmu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-secondary/src/smmu.c b/fusee/fusee-secondary/src/smmu.c index 23bd3d37d..db54e5d9d 100644 --- a/fusee/fusee-secondary/src/smmu.c +++ b/fusee/fusee-secondary/src/smmu.c @@ -226,9 +226,10 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si uint32_t old_key_data = *key_data; uint32_t buf_counter = 0; while (!(tsec->FALCON_CPUCTL & 0x10)) { - if (*key_data != old_key_data) { - old_key_data = *key_data; - key_buf[buf_counter] = *key_data; + const uint32_t new_key_data = *key_data; + if (new_key_data != old_key_data) { + old_key_data = new_key_data; + key_buf[buf_counter] = new_key_data; buf_counter++; } } From 0ef336889388efaeab32f91528fde4dc1e318749 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 7 Dec 2018 14:54:06 -0800 Subject: [PATCH 309/489] fusee: retry tsec key generation on failure. --- fusee/fusee-secondary/src/smmu.c | 103 +++++++++++++++++++------------ 1 file changed, 64 insertions(+), 39 deletions(-) diff --git a/fusee/fusee-secondary/src/smmu.c b/fusee/fusee-secondary/src/smmu.c index db54e5d9d..23e394837 100644 --- a/fusee/fusee-secondary/src/smmu.c +++ b/fusee/fusee-secondary/src/smmu.c @@ -20,6 +20,8 @@ #include "timers.h" #include "tsec.h" +#define TSEC_KEYGEN_MAX_RETRIES 25 + void *smmu_heap = (void *)SMMU_HEAP_BASE_ADDR; static void safe_memcpy(void *dst, void *src, uint32_t sz) { @@ -168,14 +170,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si /* Copy package1 into IRAM. */ memcpy((void *)0x40010000, package1, package1_size); - /* Load the TSEC firmware from IRAM. */ - if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) { - fatal_error("[SMMU]: Failed to load TSEC firmware!\n"); - } - - /* Disable the aperture since it has precedence over the SMMU. */ - mc_disable_ahb_redirect(); - /* Setup TSEC's address space. */ uint32_t *pdir = smmu_setup_tsec_as(1); @@ -189,21 +183,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si volatile uint32_t *iram_pages = smmu_alloc_page(48); volatile uint32_t *expv_page = smmu_alloc_page(1); - /* Copy CAR, MC and FUSE. */ - safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000); - safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000); - safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400); - - /* Copy IRAM. */ - memcpy((void *)iram_pages, (void *)0x40010000, 0x30000); - - /* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */ - car_page[0x1F4/4] = 2; - - /* TSEC wants the aperture fully open. */ - mc_page[0x65C/4] = 0; - mc_page[0x660/4] = 0x80000000; - /* Map all necessary pages. */ smmu_map(pdir, 0x60006000, (uint32_t)car_page, 1, _READABLE | _WRITABLE | _NONSECURE); smmu_map(pdir, 0x7000F000, (uint32_t)fuse_page, 1, _READABLE | _NONSECURE); @@ -217,20 +196,69 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si /* Enable the SMMU. */ smmu_enable(); - /* Run the TSEC firmware. */ - tsec_run_fw(); - - /* Extract the keys from SE. */ + /* Loop retrying TSEC firmware execution, in case we lose the SE keydata race. */ uint32_t key_buf[0x20/4] = {0}; - volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320); - uint32_t old_key_data = *key_data; - uint32_t buf_counter = 0; - while (!(tsec->FALCON_CPUCTL & 0x10)) { - const uint32_t new_key_data = *key_data; - if (new_key_data != old_key_data) { - old_key_data = new_key_data; - key_buf[buf_counter] = new_key_data; - buf_counter++; + unsigned int retries = 0; + while (true) { + if (retries++ > TSEC_KEYGEN_MAX_RETRIES) { + fatal_error("[SMMU] TSEC key generation race was lost too many times!"); + } + + /* Load the TSEC firmware from IRAM. */ + if (tsec_load_fw((void *)(0x40010000 + 0xE00), 0x2900) < 0) { + fatal_error("[SMMU]: Failed to load TSEC firmware!\n"); + } + + /* Disable the aperture since it has precedence over the SMMU. */ + mc_disable_ahb_redirect(); + + /* Clear all pages. */ + memset((void *)car_page, 0, SMMU_PAGE_SIZE); + memset((void *)fuse_page, 0, SMMU_PAGE_SIZE); + memset((void *)pmc_page, 0, SMMU_PAGE_SIZE); + memset((void *)flow_page, 0, SMMU_PAGE_SIZE); + memset((void *)se_page, 0, SMMU_PAGE_SIZE); + memset((void *)mc_page, 0, SMMU_PAGE_SIZE); + memset((void *)iram_pages, 0, 48 * SMMU_PAGE_SIZE); + memset((void *)expv_page, 0, SMMU_PAGE_SIZE); + + /* Copy CAR, MC and FUSE. */ + safe_memcpy((void *)car_page, (void *)0x60006000, 0x1000); + safe_memcpy((void *)mc_page, (void *)0x70019000, 0x1000); + safe_memcpy((void *)&fuse_page[0x800/4], (void *)0x7000F800, 0x400); + + /* Copy IRAM. */ + memcpy((void *)iram_pages, (void *)0x40010000, 0x30000); + + /* TSEC wants CLK_RST_CONTROLLER_CLK_SOURCE_TSEC_0 to be equal to 2. */ + car_page[0x1F4/4] = 2; + + /* TSEC wants the aperture fully open. */ + mc_page[0x65C/4] = 0; + mc_page[0x660/4] = 0x80000000; + + + /* Run the TSEC firmware. */ + tsec_run_fw(); + + /* Extract the keys from SE. */ + volatile uint32_t *key_data = (volatile uint32_t *)((void *)se_page + 0x320); + uint32_t old_key_data = *key_data; + uint32_t buf_counter = 0; + while (!(tsec->FALCON_CPUCTL & 0x10)) { + const uint32_t new_key_data = *key_data; + if (new_key_data != old_key_data) { + old_key_data = new_key_data; + key_buf[buf_counter] = new_key_data; + buf_counter++; + } + } + + /* Enable back the aperture. */ + mc_enable_ahb_redirect(); + + if (buf_counter == 8) { + break; } } @@ -249,9 +277,6 @@ void smmu_emulate_tsec(void *tsec_keys, const void *package1, size_t package1_si /* Clear TSEC's address space. */ smmu_clear_tsec_as(1); - /* Enable back the aperture. */ - mc_enable_ahb_redirect(); - /* Return the decrypted package1 from emulated IRAM. */ memcpy(package1_dec, (void *)iram_pages, package1_size); From a21b5d453a11e862021bdd47d928eeba101875dc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 7 Dec 2018 03:32:24 -0800 Subject: [PATCH 310/489] ams: turn on debugmode by default. --- common/defaults/BCT.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/defaults/BCT.ini b/common/defaults/BCT.ini index 660b456b7..9e34aedc8 100644 --- a/common/defaults/BCT.ini +++ b/common/defaults/BCT.ini @@ -5,7 +5,8 @@ stage2_addr = 0xF0000000 stage2_entrypoint = 0xF0000000 [exosphere] -debugmode = 0 +; Note: Disabling debugmode will cause parts of ams.tma to not work. +debugmode = 1 debugmode_user = 0 [stratosphere] From 84c776fa6b0d950c67a37803da1a49764bc33106 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 7 Dec 2018 17:30:07 -0800 Subject: [PATCH 311/489] Bump version to 0.8.2 --- common/defaults/BCT.ini | 2 +- common/include/atmosphere/version.h | 2 +- docs/changelog.md | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/common/defaults/BCT.ini b/common/defaults/BCT.ini index 9e34aedc8..b74c19725 100644 --- a/common/defaults/BCT.ini +++ b/common/defaults/BCT.ini @@ -5,7 +5,7 @@ stage2_addr = 0xF0000000 stage2_entrypoint = 0xF0000000 [exosphere] -; Note: Disabling debugmode will cause parts of ams.tma to not work. +; Note: Disabling debugmode will cause parts of ams.tma to not work, in the future. debugmode = 1 debugmode_user = 0 diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index a112d9352..9a529c942 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 8 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 1 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 2 #endif \ No newline at end of file diff --git a/docs/changelog.md b/docs/changelog.md index f6d1c656d..e9891d279 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,13 @@ # Changelog +## 0.8.2 ++ A number of bugs were fixed causing users to sometimes see `Key Derivation Failed!`. + + KFUSE clock enable timings have been adjusted to allow time to stabilize before TSEC is granted access. + + A race condition was fixed that could cause wrong key data to be used on 6.2.0 + + The TSEC firmware is now retried on failure, fixing a failure affecting ~1/50 boots on 6.2.0. ++ A bug was fixed causing some modules to not work on firmware 1.0.0. ++ A bug was fixed causing sleep mode to not work with debugmode enabled. + + As a result, debugmode is now enabled in the default BCT.ini. ++ General system stability improvements to enhance the user's experience. ## 0.8.1 + A bug was fixed causing users to see `Failed to enable SMMU!` if fusee had previously rebooted. + This message will still occur sporadically if fusee is not launched from coldboot, but it can never happen twice in a row. From a9a71fbeedeb2a98c1a0e8c612b5c73d8bd894d6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 10 Dec 2018 19:30:59 -0800 Subject: [PATCH 312/489] fs.mitm: Fix HID usage (closes #292) --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 7 +++++-- stratosphere/fs_mitm/source/fsmitm_utils.hpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 2151e22ff..39d8ce1f4 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -191,6 +191,8 @@ void Utils::InitializeHidThreadFunc(void *args) { g_has_hid_session = true; + hidExit(); + svcExitThread(); } @@ -198,7 +200,7 @@ bool Utils::IsSdInitialized() { return g_has_initialized; } -bool Utils::IsHidInitialized() { +bool Utils::IsHidAvailable() { return g_has_hid_session; } @@ -410,13 +412,14 @@ bool Utils::HasSdDisableMitMFlag(u64 tid) { } Result Utils::GetKeysDown(u64 *keys) { - if (!Utils::IsHidInitialized()) { + if (!Utils::IsHidAvailable() || R_FAILED(hidInitialize())) { return MAKERESULT(Module_Libnx, LibnxError_InitFail_HID); } hidScanInput(); *keys = hidKeysDown(CONTROLLER_P1_AUTO); + hidExit(); return 0x0; } diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index 0811c1f7e..856748c4d 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -67,7 +67,7 @@ class Utils { static bool HasSdDisableMitMFlag(u64 tid); - static bool IsHidInitialized(); + static bool IsHidAvailable(); static void InitializeHidThreadFunc(void *args); static Result GetKeysDown(u64 *keys); static bool HasOverrideButton(u64 tid); From b72a68f62255f034afee5880ee4c7414975cdbdb Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 16 Dec 2018 17:38:10 -0800 Subject: [PATCH 313/489] exo: follow hekate's example, disable warmboot signature checks via bootrom arbwrite. (rip mariko) --- exosphere/src/lp0.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/exosphere/src/lp0.c b/exosphere/src/lp0.c index e38693cf0..effb2dc13 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/lp0.c @@ -240,6 +240,10 @@ void save_se_and_power_down_cpu(void) { /* Save context for warmboot to restore. */ save_tzram_state(); save_se_state(); + + /* Patch the bootrom to disable warmboot signature checks. */ + MAKE_REG32(PMC_BASE + 0x118) = 0x2202E012; + MAKE_REG32(PMC_BASE + 0x11C) = 0x6001DC28; if (!configitem_is_retail()) { uart_send(UART_A, "OYASUMI", 8); From dca51291aacfb166d7651e984e2f3f32d21c4947 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 11:30:59 -0800 Subject: [PATCH 314/489] Exo: bpmpfw -> sc7fw, lp0 -> sc7 --- exosphere/Makefile | 14 +++++++------- exosphere/{bpmpfw => sc7fw}/Makefile | 0 exosphere/{bpmpfw => sc7fw}/linker.ld | 0 exosphere/{bpmpfw => sc7fw}/linker.specs | 0 exosphere/{bpmpfw => sc7fw}/src/emc.c | 2 +- exosphere/{bpmpfw => sc7fw}/src/emc.h | 0 exosphere/{bpmpfw => sc7fw}/src/i2c.c | 0 exosphere/{bpmpfw => sc7fw}/src/i2c.h | 0 exosphere/{bpmpfw => sc7fw}/src/pmc.h | 0 exosphere/{bpmpfw/src/lp0.c => sc7fw/src/sc7.c} | 4 ++-- exosphere/{bpmpfw/src/lp0.h => sc7fw/src/sc7.h} | 6 +++--- exosphere/{bpmpfw => sc7fw}/src/start.s | 4 ++-- exosphere/{bpmpfw => sc7fw}/src/timer.h | 0 exosphere/{bpmpfw => sc7fw}/src/utils.h | 0 exosphere/src/{lp0.c => sc7.c} | 10 +++++----- exosphere/src/{lp0.h => sc7.h} | 4 ++-- exosphere/src/smc_api.c | 2 +- 17 files changed, 23 insertions(+), 23 deletions(-) rename exosphere/{bpmpfw => sc7fw}/Makefile (100%) rename exosphere/{bpmpfw => sc7fw}/linker.ld (100%) rename exosphere/{bpmpfw => sc7fw}/linker.specs (100%) rename exosphere/{bpmpfw => sc7fw}/src/emc.c (99%) rename exosphere/{bpmpfw => sc7fw}/src/emc.h (100%) rename exosphere/{bpmpfw => sc7fw}/src/i2c.c (100%) rename exosphere/{bpmpfw => sc7fw}/src/i2c.h (100%) rename exosphere/{bpmpfw => sc7fw}/src/pmc.h (100%) rename exosphere/{bpmpfw/src/lp0.c => sc7fw/src/sc7.c} (98%) rename exosphere/{bpmpfw/src/lp0.h => sc7fw/src/sc7.h} (88%) rename exosphere/{bpmpfw => sc7fw}/src/start.s (94%) rename exosphere/{bpmpfw => sc7fw}/src/timer.h (100%) rename exosphere/{bpmpfw => sc7fw}/src/utils.h (100%) rename exosphere/src/{lp0.c => sc7.c} (97%) rename exosphere/src/{lp0.h => sc7.h} (94%) diff --git a/exosphere/Makefile b/exosphere/Makefile index 11339bb05..4eb2d4491 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -75,14 +75,14 @@ export TOPDIR := $(CURDIR) export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ - $(TOPDIR)/bpmpfw + $(TOPDIR)/sc7fw export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) bpmpfw.bin +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C @@ -109,22 +109,22 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -.PHONY: $(BUILD) build_bpmpfw clean all +.PHONY: $(BUILD) build_sc7fw clean all #--------------------------------------------------------------------------------- all: $(BUILD) -check_bpmpfw: - @$(MAKE) -C bpmpfw all +check_sc7fw: + @$(MAKE) -C sc7fw all -$(BUILD): check_bpmpfw +$(BUILD): check_sc7fw @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile #--------------------------------------------------------------------------------- clean: @echo clean ... - @$(MAKE) -C $(TOPDIR)/bpmpfw clean + @$(MAKE) -C $(TOPDIR)/sc7fw clean @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf diff --git a/exosphere/bpmpfw/Makefile b/exosphere/sc7fw/Makefile similarity index 100% rename from exosphere/bpmpfw/Makefile rename to exosphere/sc7fw/Makefile diff --git a/exosphere/bpmpfw/linker.ld b/exosphere/sc7fw/linker.ld similarity index 100% rename from exosphere/bpmpfw/linker.ld rename to exosphere/sc7fw/linker.ld diff --git a/exosphere/bpmpfw/linker.specs b/exosphere/sc7fw/linker.specs similarity index 100% rename from exosphere/bpmpfw/linker.specs rename to exosphere/sc7fw/linker.specs diff --git a/exosphere/bpmpfw/src/emc.c b/exosphere/sc7fw/src/emc.c similarity index 99% rename from exosphere/bpmpfw/src/emc.c rename to exosphere/sc7fw/src/emc.c index e77479639..6b6e16635 100644 --- a/exosphere/bpmpfw/src/emc.c +++ b/exosphere/sc7fw/src/emc.c @@ -15,7 +15,7 @@ */ #include "utils.h" -#include "lp0.h" +#include "sc7.h" #include "emc.h" #include "pmc.h" #include "timer.h" diff --git a/exosphere/bpmpfw/src/emc.h b/exosphere/sc7fw/src/emc.h similarity index 100% rename from exosphere/bpmpfw/src/emc.h rename to exosphere/sc7fw/src/emc.h diff --git a/exosphere/bpmpfw/src/i2c.c b/exosphere/sc7fw/src/i2c.c similarity index 100% rename from exosphere/bpmpfw/src/i2c.c rename to exosphere/sc7fw/src/i2c.c diff --git a/exosphere/bpmpfw/src/i2c.h b/exosphere/sc7fw/src/i2c.h similarity index 100% rename from exosphere/bpmpfw/src/i2c.h rename to exosphere/sc7fw/src/i2c.h diff --git a/exosphere/bpmpfw/src/pmc.h b/exosphere/sc7fw/src/pmc.h similarity index 100% rename from exosphere/bpmpfw/src/pmc.h rename to exosphere/sc7fw/src/pmc.h diff --git a/exosphere/bpmpfw/src/lp0.c b/exosphere/sc7fw/src/sc7.c similarity index 98% rename from exosphere/bpmpfw/src/lp0.c rename to exosphere/sc7fw/src/sc7.c index 21de19ce6..4ae84b11c 100644 --- a/exosphere/bpmpfw/src/lp0.c +++ b/exosphere/sc7fw/src/sc7.c @@ -15,7 +15,7 @@ */ #include "utils.h" -#include "lp0.h" +#include "sc7.h" #include "i2c.h" #include "pmc.h" #include "emc.h" @@ -55,7 +55,7 @@ static void set_pmc_dpd_io_pads(void) { spinlock_wait(32); } -void lp0_entry_main(void) { +void sc7_entry_main(void) { /* Disable the BPMP Cache. */ CACHE_CTRL |= 0xC00; diff --git a/exosphere/bpmpfw/src/lp0.h b/exosphere/sc7fw/src/sc7.h similarity index 88% rename from exosphere/bpmpfw/src/lp0.h rename to exosphere/sc7fw/src/sc7.h index 25059490f..37f95cb33 100644 --- a/exosphere/bpmpfw/src/lp0.h +++ b/exosphere/sc7fw/src/sc7.h @@ -14,12 +14,12 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef EXOSPHERE_BPMPFW_LP0_H -#define EXOSPHERE_BPMPFW_LP0_H +#ifndef EXOSPHERE_BPMPFW_SC7_H +#define EXOSPHERE_BPMPFW_SC7_H #include "utils.h" -void lp0_entry_main(void); +void sc7_entry_main(void); void reboot(void); diff --git a/exosphere/bpmpfw/src/start.s b/exosphere/sc7fw/src/start.s similarity index 94% rename from exosphere/bpmpfw/src/start.s rename to exosphere/sc7fw/src/start.s index a439b7d30..c648a10d4 100644 --- a/exosphere/bpmpfw/src/start.s +++ b/exosphere/sc7fw/src/start.s @@ -25,11 +25,11 @@ _start: .global crt0 .type crt0, %function crt0: - @ setup to call lp0_entry_main + @ setup to call sc7_entry_main msr cpsr_cxsf, #0xD3 ldr sp, =__stack_top__ ldr lr, =reboot - b lp0_entry_main + b sc7_entry_main .global spinlock_wait diff --git a/exosphere/bpmpfw/src/timer.h b/exosphere/sc7fw/src/timer.h similarity index 100% rename from exosphere/bpmpfw/src/timer.h rename to exosphere/sc7fw/src/timer.h diff --git a/exosphere/bpmpfw/src/utils.h b/exosphere/sc7fw/src/utils.h similarity index 100% rename from exosphere/bpmpfw/src/utils.h rename to exosphere/sc7fw/src/utils.h diff --git a/exosphere/src/lp0.c b/exosphere/src/sc7.c similarity index 97% rename from exosphere/src/lp0.c rename to exosphere/src/sc7.c index effb2dc13..f168a895f 100644 --- a/exosphere/src/lp0.c +++ b/exosphere/src/sc7.c @@ -28,7 +28,7 @@ #include "flow.h" #include "fuse.h" #include "i2c.h" -#include "lp0.h" +#include "sc7.h" #include "masterkey.h" #include "pmc.h" #include "se.h" @@ -40,7 +40,7 @@ #define u8 uint8_t #define u32 uint32_t -#include "bpmpfw_bin.h" +#include "sc7fw_bin.h" #undef u8 #undef u32 @@ -138,11 +138,11 @@ static void setup_bpmp_sc7_firmware(void) { /* Copy BPMP firmware. */ uint8_t *lp0_entry_code = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE)); - for (unsigned int i = 0; i < bpmpfw_bin_size; i += 4) { - write32le(lp0_entry_code, i, read32le(bpmpfw_bin, i)); + for (unsigned int i = 0; i < sc7fw_bin_size; i += 4) { + write32le(lp0_entry_code, i, read32le(sc7fw_bin, i)); } - flush_dcache_range(lp0_entry_code, lp0_entry_code + bpmpfw_bin_size); + flush_dcache_range(lp0_entry_code, lp0_entry_code + sc7fw_bin_size); /* Take the BPMP out of reset. */ MAKE_CAR_REG(0x304) = 2; diff --git a/exosphere/src/lp0.h b/exosphere/src/sc7.h similarity index 94% rename from exosphere/src/lp0.h rename to exosphere/src/sc7.h index 293789822..c5612da92 100644 --- a/exosphere/src/lp0.h +++ b/exosphere/src/sc7.h @@ -14,8 +14,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef EXOSPHERE_LP0_H -#define EXOSPHERE_LP0_H +#ifndef EXOSPHERE_SC7_H +#define EXOSPHERE_SC7_H #include <stdint.h> diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index 902dd20a3..336f593cb 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -34,7 +34,7 @@ #include "se.h" #include "userpage.h" #include "titlekey.h" -#include "lp0.h" +#include "sc7.h" #include "exocfg.h" #define SMC_USER_HANDLERS 0x13 From fc4912ef54b0142b7abc265090b9895265d28d1f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 12:01:10 -0800 Subject: [PATCH 315/489] exo: add stub warmboot.bin --- exosphere/lp0fw/Makefile | 154 +++++++++++++++++++++++++++++++++++ exosphere/lp0fw/linker.ld | 24 ++++++ exosphere/lp0fw/linker.specs | 7 ++ exosphere/lp0fw/src/lp0.c | 41 ++++++++++ exosphere/lp0fw/src/lp0.h | 35 ++++++++ exosphere/lp0fw/src/pmc.h | 53 ++++++++++++ exosphere/lp0fw/src/start.s | 68 ++++++++++++++++ exosphere/lp0fw/src/timer.h | 33 ++++++++ exosphere/lp0fw/src/utils.h | 38 +++++++++ 9 files changed, 453 insertions(+) create mode 100644 exosphere/lp0fw/Makefile create mode 100644 exosphere/lp0fw/linker.ld create mode 100644 exosphere/lp0fw/linker.specs create mode 100644 exosphere/lp0fw/src/lp0.c create mode 100644 exosphere/lp0fw/src/lp0.h create mode 100644 exosphere/lp0fw/src/pmc.h create mode 100644 exosphere/lp0fw/src/start.s create mode 100644 exosphere/lp0fw/src/timer.h create mode 100644 exosphere/lp0fw/src/utils.h diff --git a/exosphere/lp0fw/Makefile b/exosphere/lp0fw/Makefile new file mode 100644 index 000000000..0eadd1314 --- /dev/null +++ b/exosphere/lp0fw/Makefile @@ -0,0 +1,154 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITARM)/base_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := src +DATA := data +INCLUDES := include + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork + +CFLAGS := \ + -g \ + -O2 \ + -ffunction-sections \ + -fdata-sections \ + -fomit-frame-pointer \ + -fno-inline \ + -std=gnu11 \ + -Werror \ + -Wall \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__BPMP__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).bin + +$(OUTPUT).bin : $(OUTPUT).elf + $(OBJCOPY) -S -O binary $< $@ + @echo built ... $(notdir $@) + +$(OUTPUT).elf : $(OFILES) + +%.elf: $(OFILES) + @echo linking $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + @$(NM) -CSn $@ > $(notdir $*.lst) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/exosphere/lp0fw/linker.ld b/exosphere/lp0fw/linker.ld new file mode 100644 index 000000000..165608360 --- /dev/null +++ b/exosphere/lp0fw/linker.ld @@ -0,0 +1,24 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +ENTRY(_start) +SECTIONS +{ + . = 0x40010000; + + __start__ = ABSOLUTE(.); + + .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } + .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } + .bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; } + + . = ALIGN(4); + + __end__ = ABSOLUTE(.); + + __total_size__ = (__end__ - __start__); + __executable_size__ = (__end__ - _start); + + __stack_top__ = 0x40013000; + __stack_bottom__ = 0x40012000; +} \ No newline at end of file diff --git a/exosphere/lp0fw/linker.specs b/exosphere/lp0fw/linker.specs new file mode 100644 index 000000000..300990418 --- /dev/null +++ b/exosphere/lp0fw/linker.specs @@ -0,0 +1,7 @@ +%rename link old_link + +*link: +%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections + +*startfile: +crti%O%s crtbegin%O%s diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c new file mode 100644 index 000000000..b363748e8 --- /dev/null +++ b/exosphere/lp0fw/src/lp0.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils.h" +#include "lp0.h" +#include "pmc.h" +#include "timer.h" + +void reboot(void) { + /* Write MAIN_RST */ + APBDEV_PMC_CNTRL_0 = 0x10; + while (true) { + /* Wait for reboot. */ + } +} + +void lp0_entry_main(warmboot_metadata_t *meta) { + /* Before doing anything else, ensure some sanity. */ + if (meta->magic != WARMBOOT_MAGIC || meta->tz_relative_offset > 0x2000) { + reboot(); + } + + /* TODO: stuff */ + + while (true) { /* TODO: Halt BPMP */ } +} + + diff --git a/exosphere/lp0fw/src/lp0.h b/exosphere/lp0fw/src/lp0.h new file mode 100644 index 000000000..189813d9b --- /dev/null +++ b/exosphere/lp0fw/src/lp0.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_LP0_H +#define EXOSPHERE_WARMBOOT_BIN_LP0_H + +#include "utils.h" + +/* WBT0 */ +#define WARMBOOT_MAGIC 0x30544257 + +typedef struct { + uint32_t magic; + uint32_t tz_relative_offset; + uint32_t padding[2]; +} warmboot_metadata_t; + +void lp0_entry_main(warmboot_metadata_t *meta); + +void reboot(void); + +#endif diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h new file mode 100644 index 000000000..dd32e9c2e --- /dev/null +++ b/exosphere/lp0fw/src/pmc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_PMC_H +#define EXOSPHERE_WARMBOOT_BIN_PMC_H + +#include "utils.h" + +#define PMC_BASE (0x7000E400) + +#define MAKE_PMC_REG(ofs) (MAKE_REG32(PMC_BASE + ofs)) + +#define APBDEV_PMC_CNTRL_0 MAKE_PMC_REG(0x000) + +#define APBDEV_PMC_DPD_SAMPLE_0 MAKE_PMC_REG(0x020) + +#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x024) + +#define APBDEV_PMC_CLAMP_STATUS_0 MAKE_PMC_REG(0x02C) + +#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038) + +#define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080) +#define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084) +#define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098) + + +#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) + +#define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C) +#define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460) + +#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464) +#define APBDEV_PMC_IO_DPD4_STATUS_0 MAKE_PMC_REG(0x468) + +#define APBDEV_PMC_SET_SW_CLAMP_0 MAKE_PMC_REG(0x47C) + +#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4) + +#endif diff --git a/exosphere/lp0fw/src/start.s b/exosphere/lp0fw/src/start.s new file mode 100644 index 000000000..9abe6a391 --- /dev/null +++ b/exosphere/lp0fw/src/start.s @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +.section .text.start + +/* Warmboot header. */ +/* Binary size */ +.word __total_size__ +.rept 3 +.word 0x00000000 +.endr +/* RSA modulus */ +.rept 0x40 +.word 0xFFFFFFFF +.endr +/* Padding */ +.rept 4 +.word 0x00000000 +.endr +/* RSA signature */ +.rept 0x40 +.word 0xFFFFFFFF +.endr +/* Padding */ +.rept 4 +.word 0x00000000 +.endr +/* Relocation meta */ +.word __total_size__ +.word _start +.word _start +.word __executable_size__ + +.global _start +_start: + b crt0 +.rept 0x7C + .word 0x00000000 /* Padding */ +.endr + +.global _metadata +_metadata: + .ascii "WBT0" /* Magic number */ + .word 0x00000000 /* TrustZone relative base. */ + .word 0x00000000 /* Reserved */ + .word 0x00000000 /* Reserved */ + +.global crt0 +.type crt0, %function +crt0: + @ setup to call lp0_entry_main + ldr sp, =__stack_top__ + ldr lr, =reboot + ldr r0, =_metadata + b lp0_entry_main diff --git a/exosphere/lp0fw/src/timer.h b/exosphere/lp0fw/src/timer.h new file mode 100644 index 000000000..74f4a6360 --- /dev/null +++ b/exosphere/lp0fw/src/timer.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_TIMER_H +#define EXOSPHERE_WARMBOOT_BIN_TIMER_H + +#include "utils.h" + +#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010) + +static inline void timer_wait(uint32_t microseconds) { + uint32_t old_time = TIMERUS_CNTR_1US_0; + while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { + /* Spin-lock. */ + } +} + +void spinlock_wait(uint32_t count); + +#endif diff --git a/exosphere/lp0fw/src/utils.h b/exosphere/lp0fw/src/utils.h new file mode 100644 index 000000000..60a48d6b6 --- /dev/null +++ b/exosphere/lp0fw/src/utils.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_UTILS_H +#define EXOSPHERE_WARMBOOT_BIN_UTILS_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define BIT(n) (1u << (n)) +#define BITL(n) (1ull << (n)) +#define MASK(n) (BIT(n) - 1) +#define MASKL(n) (BITL(n) - 1) +#define MASK2(a,b) (MASK(a) & ~MASK(b)) +#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) + +#define MAKE_REG32(a) (*(volatile uint32_t *)(a)) + +#define ALIGN(m) __attribute__((aligned(m))) +#define PACKED __attribute__((packed)) + +#define ALINLINE __attribute__((always_inline)) + +#endif From e0f1e637f79a6eae88178a6576a3a74a953d1929 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 12:39:35 -0800 Subject: [PATCH 316/489] Add single source of truth for target firmwares. --- .gitignore | 8 + common/include/atmosphere.h | 1 + common/include/atmosphere/target_fw.h | 36 ++ exosphere/lp0fw/Makefile | 2 +- exosphere/lp0fw/src/lp0.c | 8 +- exosphere/lp0fw/src/lp0.h | 2 +- exosphere/lp0fw/src/mc.c | 40 ++ exosphere/lp0fw/src/mc.h | 614 +++++++++++++++++++++ exosphere/lp0fw/src/start.s | 5 +- exosphere/lp0fw/src/utils.h | 1 + exosphere/src/bootup.c | 26 +- exosphere/src/coldboot_init.c | 8 +- exosphere/src/configitem.c | 10 +- exosphere/src/cpu_context.c | 4 +- exosphere/src/exocfg.c | 4 +- exosphere/src/exocfg.h | 15 +- exosphere/src/fuse.c | 2 +- exosphere/src/mc.c | 10 +- exosphere/src/package2.c | 50 +- exosphere/src/sc7.c | 14 +- exosphere/src/sealedkeys.c | 2 +- exosphere/src/smc_api.c | 20 +- exosphere/src/smc_user.c | 48 +- exosphere/src/titlekey.c | 2 +- exosphere/src/warmboot_init.c | 6 +- exosphere/src/warmboot_main.c | 4 +- fusee/fusee-secondary/src/exocfg.h | 12 +- fusee/fusee-secondary/src/key_derivation.c | 24 +- fusee/fusee-secondary/src/nxboot.c | 40 +- fusee/fusee-secondary/src/nxboot_iram.c | 6 +- fusee/fusee-secondary/src/stratosphere.c | 2 +- 31 files changed, 855 insertions(+), 171 deletions(-) create mode 100644 common/include/atmosphere/target_fw.h create mode 100644 exosphere/lp0fw/src/mc.c create mode 100644 exosphere/lp0fw/src/mc.h diff --git a/.gitignore b/.gitignore index f55c55a62..d759ff7f0 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,14 @@ dkms.conf *.tgz *.zip +# IDA binaries +*.id0 +*.id1 +*.id2 +*.idb +*.nam +*.til + .**/ # NOTE: make sure to make exceptions to this pattern when needed! diff --git a/common/include/atmosphere.h b/common/include/atmosphere.h index 86f2f0427..09f2faccf 100644 --- a/common/include/atmosphere.h +++ b/common/include/atmosphere.h @@ -22,6 +22,7 @@ extern "C" { #endif #include "atmosphere/version.h" +#include "atmosphere/target_fw.h" #ifdef __cplusplus } diff --git a/common/include/atmosphere/target_fw.h b/common/include/atmosphere/target_fw.h new file mode 100644 index 000000000..03f689e94 --- /dev/null +++ b/common/include/atmosphere/target_fw.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef ATMOSPHERE_TARGET_FIRMWARE_H +#define ATMOSPHERE_TARGET_FIRMWARE_H + +#define ATMOSPHERE_TARGET_FIRMWARE_100 1 +#define ATMOSPHERE_TARGET_FIRMWARE_200 2 +#define ATMOSPHERE_TARGET_FIRMWARE_300 3 +#define ATMOSPHERE_TARGET_FIRMWARE_400 4 +#define ATMOSPHERE_TARGET_FIRMWARE_500 5 +#define ATMOSPHERE_TARGET_FIRMWARE_600 6 +#define ATMOSPHERE_TARGET_FIRMWARE_620 7 + +#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_620 + +#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100 +#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_620 + +/* TODO: What should this be, for release? */ +#define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT + +#endif \ No newline at end of file diff --git a/exosphere/lp0fw/Makefile b/exosphere/lp0fw/Makefile index 0eadd1314..e8afccfd1 100644 --- a/exosphere/lp0fw/Makefile +++ b/exosphere/lp0fw/Makefile @@ -20,7 +20,7 @@ TARGET := $(notdir $(CURDIR)) BUILD := build SOURCES := src DATA := data -INCLUDES := include +INCLUDES := include ../../common/include #--------------------------------------------------------------------------------- # options for code generation diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c index b363748e8..7f1c77ec4 100644 --- a/exosphere/lp0fw/src/lp0.c +++ b/exosphere/lp0fw/src/lp0.c @@ -16,6 +16,7 @@ #include "utils.h" #include "lp0.h" +#include "mc.h" #include "pmc.h" #include "timer.h" @@ -29,10 +30,15 @@ void reboot(void) { void lp0_entry_main(warmboot_metadata_t *meta) { /* Before doing anything else, ensure some sanity. */ - if (meta->magic != WARMBOOT_MAGIC || meta->tz_relative_offset > 0x2000) { + if (meta->magic != WARMBOOT_MAGIC || meta->target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX) { reboot(); } + /* [4.0.0+] First thing warmboot does is disable BPMP access to memory. */ + if (meta->target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) { + disable_bpmp_access_to_dram(); + } + /* TODO: stuff */ while (true) { /* TODO: Halt BPMP */ } diff --git a/exosphere/lp0fw/src/lp0.h b/exosphere/lp0fw/src/lp0.h index 189813d9b..90cdb6850 100644 --- a/exosphere/lp0fw/src/lp0.h +++ b/exosphere/lp0fw/src/lp0.h @@ -24,7 +24,7 @@ typedef struct { uint32_t magic; - uint32_t tz_relative_offset; + uint32_t target_firmware; uint32_t padding[2]; } warmboot_metadata_t; diff --git a/exosphere/lp0fw/src/mc.c b/exosphere/lp0fw/src/mc.c new file mode 100644 index 000000000..a26ef285b --- /dev/null +++ b/exosphere/lp0fw/src/mc.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "mc.h" +#include "utils.h" + +void disable_bpmp_access_to_dram(void) { + /* Modify carveout 4 to prevent BPMP access to dram (TZ will fix it). */ + volatile security_carveout_t *carveout = (volatile security_carveout_t *)(MC_BASE + 0xC08 + 0x50 * (4 - CARVEOUT_ID_MIN)); + carveout->paddr_low = 0; + carveout->paddr_high = 0; + carveout->size_big_pages = 1; /* 128 KiB */ + carveout->client_access_0 = 0; + carveout->client_access_1 = 0; + carveout->client_access_2 = 0; + carveout->client_access_3 = 0; + carveout->client_access_4 = 0; + carveout->client_force_internal_access_0 = BIT(CSR_AVPCARM7R); + carveout->client_force_internal_access_1 = BIT(CSW_AVPCARM7W); + carveout->client_force_internal_access_2 = 0; + carveout->client_force_internal_access_3 = 0; + carveout->client_force_internal_access_4 = 0; + /* Set config to LOCKED, TZ-SECURE, untranslated addresses only. */ + carveout->config = 0x8F; +} diff --git a/exosphere/lp0fw/src/mc.h b/exosphere/lp0fw/src/mc.h new file mode 100644 index 000000000..647a826c4 --- /dev/null +++ b/exosphere/lp0fw/src/mc.h @@ -0,0 +1,614 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_MC_H +#define EXOSPHERE_WARMBOOT_BIN_MC_H + +#include <stdint.h> + +#define MC_BASE_PHYS 0x70019000 + +#define MC_BASE (MC_BASE_PHYS) +#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) + +#define MC_INTSTATUS 0x0 +#define MC_INTMASK 0x4 +#define MC_ERR_STATUS 0x8 +#define MC_ERR_ADR 0xc +#define MC_SMMU_CONFIG 0x10 +#define MC_SMMU_TLB_CONFIG 0x14 +#define MC_SMMU_PTC_CONFIG 0x18 +#define MC_SMMU_PTB_ASID 0x1c +#define MC_SMMU_PTB_DATA 0x20 +#define MC_SMMU_TLB_FLUSH 0x30 +#define MC_SMMU_PTC_FLUSH 0x34 +#define MC_SMMU_AFI_ASID 0x238 +#define MC_SMMU_AVPC_ASID 0x23c +#define MC_SMMU_PPCS1_ASID 0x298 +#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 +#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c +#define MC_SMMU_TRANSLATION_ENABLE_2 0x230 +#define MC_SMMU_TRANSLATION_ENABLE_3 0x234 +#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98 +#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0 +#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4 +#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8 +#define MC_PCFIFO_CLIENT_CONFIG3 0xddc +#define MC_PCFIFO_CLIENT_CONFIG4 0xde0 +#define MC_EMEM_CFG 0x50 +#define MC_EMEM_ADR_CFG 0x54 +#define MC_EMEM_ADR_CFG_DEV0 0x58 +#define MC_EMEM_ADR_CFG_DEV1 0x5c +#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60 +#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64 +#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68 +#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c +#define MC_SECURITY_CFG0 0x70 +#define MC_SECURITY_CFG1 0x74 +#define MC_SECURITY_CFG3 0x9bc +#define MC_SECURITY_RSV 0x7c +#define MC_EMEM_ARB_CFG 0x90 +#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 +#define MC_EMEM_ARB_TIMING_RCD 0x98 +#define MC_EMEM_ARB_TIMING_RP 0x9c +#define MC_EMEM_ARB_TIMING_RC 0xa0 +#define MC_EMEM_ARB_TIMING_RAS 0xa4 +#define MC_EMEM_ARB_TIMING_FAW 0xa8 +#define MC_EMEM_ARB_TIMING_RRD 0xac +#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 +#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 +#define MC_EMEM_ARB_TIMING_R2R 0xb8 +#define MC_EMEM_ARB_TIMING_W2W 0xbc +#define MC_EMEM_ARB_TIMING_R2W 0xc0 +#define MC_EMEM_ARB_TIMING_W2R 0xc4 +#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0 +#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4 +#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0 +#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4 +#define MC_EMEM_ARB_DA_TURNS 0xd0 +#define MC_EMEM_ARB_DA_COVERS 0xd4 +#define MC_EMEM_ARB_MISC0 0xd8 +#define MC_EMEM_ARB_MISC1 0xdc +#define MC_EMEM_ARB_MISC2 0xc8 +#define MC_EMEM_ARB_RING1_THROTTLE 0xe0 +#define MC_EMEM_ARB_RING3_THROTTLE 0xe4 +#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0 +#define MC_EMEM_ARB_OVERRIDE 0xe8 +#define MC_EMEM_ARB_RSV 0xec +#define MC_CLKEN_OVERRIDE 0xf4 +#define MC_TIMING_CONTROL_DBG 0xf8 +#define MC_TIMING_CONTROL 0xfc +#define MC_STAT_CONTROL 0x100 +#define MC_STAT_STATUS 0x104 +#define MC_STAT_EMC_CLOCK_LIMIT 0x108 +#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c +#define MC_STAT_EMC_CLOCKS 0x110 +#define MC_STAT_EMC_CLOCKS_MSBS 0x114 +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118 +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158 +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20 +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24 +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198 +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8 +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28 +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c +#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0 +#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0 +#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120 +#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c +#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c +#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c +#define MC_STAT_EMC_SET0_COUNT 0x138 +#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c +#define MC_STAT_EMC_SET1_COUNT 0x178 +#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c +#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140 +#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144 +#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180 +#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184 +#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148 +#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c +#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188 +#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c +#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150 +#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190 +#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8 +#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc +#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8 +#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc +#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0 +#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0 +#define MC_CLIENT_HOTRESET_CTRL 0x200 +#define MC_CLIENT_HOTRESET_CTRL_1 0x970 +#define MC_CLIENT_HOTRESET_STATUS 0x204 +#define MC_CLIENT_HOTRESET_STATUS_1 0x974 +#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208 +#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c +#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210 +#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214 +#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94 +#define MC_EMEM_ARB_HYSTERESIS_0 0x218 +#define MC_EMEM_ARB_HYSTERESIS_1 0x21c +#define MC_EMEM_ARB_HYSTERESIS_2 0x220 +#define MC_EMEM_ARB_HYSTERESIS_3 0x224 +#define MC_EMEM_ARB_HYSTERESIS_4 0xb84 +#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0 +#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4 +#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8 +#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc +#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0 +#define MC_EMEM_ARB_DHYST_CTRL 0xbcc +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec +#define MC_RESERVED_RSV 0x3fc +#define MC_DISB_EXTRA_SNAP_LEVELS 0x408 +#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4 +#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0 +#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18 +#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08 +#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10 +#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c +#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40 +#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414 +#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc +#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c +#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14 +#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0 +#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac +#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c +#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48 +#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8 +#define MC_USBX_EXTRA_SNAP_LEVELS 0x404 +#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8 +#define MC_SD_EXTRA_SNAP_LEVELS 0xa04 +#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c +#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8 +#define MC_GK_EXTRA_SNAP_LEVELS 0xa00 +#define MC_VE2_EXTRA_SNAP_LEVELS 0x410 +#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44 +#define MC_VIDEO_PROTECT_BOM 0x648 +#define MC_VIDEO_PROTECT_SIZE_MB 0x64c +#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978 +#define MC_VIDEO_PROTECT_REG_CTRL 0x650 +#define MC_ERR_VPR_STATUS 0x654 +#define MC_ERR_VPR_ADR 0x658 +#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418 +#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590 +#define MC_IRAM_BOM 0x65c +#define MC_IRAM_TOM 0x660 +#define MC_IRAM_ADR_HI 0x980 +#define MC_IRAM_REG_CTRL 0x964 +#define MC_EMEM_CFG_ACCESS_CTRL 0x664 +#define MC_TZ_SECURITY_CTRL 0x668 +#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c +#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4 +#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc +#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8 +#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80 +#define MC_SEC_CARVEOUT_BOM 0x670 +#define MC_SEC_CARVEOUT_SIZE_MB 0x674 +#define MC_SEC_CARVEOUT_ADR_HI 0x9d4 +#define MC_SEC_CARVEOUT_REG_CTRL 0x678 +#define MC_ERR_SEC_STATUS 0x67c +#define MC_ERR_SEC_ADR 0x680 +#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684 +#define MC_STUTTER_CONTROL 0x688 +#define MC_RESERVED_RSV_1 0x958 +#define MC_DVFS_PIPE_SELECT 0x95c +#define MC_AHB_PTSA_MIN 0x4e0 +#define MC_AUD_PTSA_MIN 0x54c +#define MC_MLL_MPCORER_PTSA_RATE 0x44c +#define MC_RING2_PTSA_RATE 0x440 +#define MC_USBD_PTSA_RATE 0x530 +#define MC_USBX_PTSA_MIN 0x528 +#define MC_USBD_PTSA_MIN 0x534 +#define MC_APB_PTSA_MAX 0x4f0 +#define MC_JPG_PTSA_RATE 0x584 +#define MC_DIS_PTSA_MIN 0x420 +#define MC_AVP_PTSA_MAX 0x4fc +#define MC_AVP_PTSA_RATE 0x4f4 +#define MC_RING1_PTSA_MIN 0x480 +#define MC_DIS_PTSA_MAX 0x424 +#define MC_SD_PTSA_MAX 0x4d8 +#define MC_MSE_PTSA_RATE 0x4c4 +#define MC_VICPC_PTSA_MIN 0x558 +#define MC_PCX_PTSA_MAX 0x4b4 +#define MC_ISP_PTSA_RATE 0x4a0 +#define MC_A9AVPPC_PTSA_MIN 0x48c +#define MC_RING2_PTSA_MAX 0x448 +#define MC_AUD_PTSA_RATE 0x548 +#define MC_HOST_PTSA_MIN 0x51c +#define MC_MLL_MPCORER_PTSA_MAX 0x454 +#define MC_SD_PTSA_MIN 0x4d4 +#define MC_RING1_PTSA_RATE 0x47c +#define MC_JPG_PTSA_MIN 0x588 +#define MC_HDAPC_PTSA_MIN 0x62c +#define MC_AVP_PTSA_MIN 0x4f8 +#define MC_JPG_PTSA_MAX 0x58c +#define MC_VE_PTSA_MAX 0x43c +#define MC_DFD_PTSA_MAX 0x63c +#define MC_VICPC_PTSA_RATE 0x554 +#define MC_GK_PTSA_MAX 0x544 +#define MC_VICPC_PTSA_MAX 0x55c +#define MC_SDM_PTSA_MAX 0x624 +#define MC_SAX_PTSA_RATE 0x4b8 +#define MC_PCX_PTSA_MIN 0x4b0 +#define MC_APB_PTSA_MIN 0x4ec +#define MC_GK2_PTSA_MIN 0x614 +#define MC_PCX_PTSA_RATE 0x4ac +#define MC_RING1_PTSA_MAX 0x484 +#define MC_HDAPC_PTSA_RATE 0x628 +#define MC_MLL_MPCORER_PTSA_MIN 0x450 +#define MC_GK2_PTSA_MAX 0x618 +#define MC_AUD_PTSA_MAX 0x550 +#define MC_GK2_PTSA_RATE 0x610 +#define MC_ISP_PTSA_MAX 0x4a8 +#define MC_DISB_PTSA_RATE 0x428 +#define MC_VE2_PTSA_MAX 0x49c +#define MC_DFD_PTSA_MIN 0x638 +#define MC_FTOP_PTSA_RATE 0x50c +#define MC_A9AVPPC_PTSA_RATE 0x488 +#define MC_VE2_PTSA_MIN 0x498 +#define MC_USBX_PTSA_MAX 0x52c +#define MC_DIS_PTSA_RATE 0x41c +#define MC_USBD_PTSA_MAX 0x538 +#define MC_A9AVPPC_PTSA_MAX 0x490 +#define MC_USBX_PTSA_RATE 0x524 +#define MC_FTOP_PTSA_MAX 0x514 +#define MC_HDAPC_PTSA_MAX 0x630 +#define MC_SD_PTSA_RATE 0x4d0 +#define MC_DFD_PTSA_RATE 0x634 +#define MC_FTOP_PTSA_MIN 0x510 +#define MC_SDM_PTSA_RATE 0x61c +#define MC_AHB_PTSA_RATE 0x4dc +#define MC_SMMU_SMMU_PTSA_MAX 0x460 +#define MC_RING2_PTSA_MIN 0x444 +#define MC_SDM_PTSA_MIN 0x620 +#define MC_APB_PTSA_RATE 0x4e8 +#define MC_MSE_PTSA_MIN 0x4c8 +#define MC_HOST_PTSA_RATE 0x518 +#define MC_VE_PTSA_RATE 0x434 +#define MC_AHB_PTSA_MAX 0x4e4 +#define MC_SAX_PTSA_MIN 0x4bc +#define MC_SMMU_SMMU_PTSA_MIN 0x45c +#define MC_ISP_PTSA_MIN 0x4a4 +#define MC_HOST_PTSA_MAX 0x520 +#define MC_SAX_PTSA_MAX 0x4c0 +#define MC_VE_PTSA_MIN 0x438 +#define MC_GK_PTSA_MIN 0x540 +#define MC_MSE_PTSA_MAX 0x4cc +#define MC_DISB_PTSA_MAX 0x430 +#define MC_DISB_PTSA_MIN 0x42c +#define MC_SMMU_SMMU_PTSA_RATE 0x458 +#define MC_VE2_PTSA_RATE 0x494 +#define MC_GK_PTSA_RATE 0x53c +#define MC_PTSA_GRANT_DECREMENT 0x960 +#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4 +#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0 +#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380 +#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384 +#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc +#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8 +#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370 +#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0 +#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374 +#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8 +#define MC_LATENCY_ALLOWANCE_VIC_0 0x394 +#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8 +#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8 +#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc +#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390 +#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694 +#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348 +#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c +#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344 +#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0 +#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698 +#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec +#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0 +#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4 +#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8 +#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4 +#define MC_LATENCY_ALLOWANCE_HC_1 0x314 +#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0 +#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4 +#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c +#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec +#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320 +#define MC_LATENCY_ALLOWANCE_VI2_0 0x398 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4 +#define MC_LATENCY_ALLOWANCE_SATA_0 0x350 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690 +#define MC_LATENCY_ALLOWANCE_HC_0 0x310 +#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8 +#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac +#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4 +#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388 +#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328 +#define MC_LATENCY_ALLOWANCE_HDA_0 0x318 +#define MC_MIN_LENGTH_APE_0 0xb34 +#define MC_MIN_LENGTH_DCB_2 0x8a8 +#define MC_MIN_LENGTH_A9AVP_0 0x950 +#define MC_MIN_LENGTH_TSEC_0 0x93c +#define MC_MIN_LENGTH_DC_1 0x898 +#define MC_MIN_LENGTH_AXIAP_0 0x94c +#define MC_MIN_LENGTH_ISP2B_0 0x930 +#define MC_MIN_LENGTH_VI2_0 0x944 +#define MC_MIN_LENGTH_DCB_0 0x8a0 +#define MC_MIN_LENGTH_DCB_1 0x8a4 +#define MC_MIN_LENGTH_PPCS_1 0x8f4 +#define MC_MIN_LENGTH_NVJPG_0 0xb3c +#define MC_MIN_LENGTH_HDA_0 0x8c4 +#define MC_MIN_LENGTH_NVENC_0 0x8d4 +#define MC_MIN_LENGTH_SDMMC_0 0xb18 +#define MC_MIN_LENGTH_ISP2B_1 0x934 +#define MC_MIN_LENGTH_HC_1 0x8c0 +#define MC_MIN_LENGTH_DC_3 0xb20 +#define MC_MIN_LENGTH_AVPC_0 0x890 +#define MC_MIN_LENGTH_VIC_0 0x940 +#define MC_MIN_LENGTH_ISP2_0 0x91c +#define MC_MIN_LENGTH_HC_0 0x8bc +#define MC_MIN_LENGTH_SE_0 0xb38 +#define MC_MIN_LENGTH_NVDEC_0 0xb30 +#define MC_MIN_LENGTH_SATA_0 0x8fc +#define MC_MIN_LENGTH_DC_0 0x894 +#define MC_MIN_LENGTH_XUSB_1 0x92c +#define MC_MIN_LENGTH_DC_2 0x89c +#define MC_MIN_LENGTH_SDMMCAA_0 0xb14 +#define MC_MIN_LENGTH_GPU_0 0xb04 +#define MC_MIN_LENGTH_ETR_0 0xb44 +#define MC_MIN_LENGTH_AFI_0 0x88c +#define MC_MIN_LENGTH_PPCS_0 0x8f0 +#define MC_MIN_LENGTH_ISP2_1 0x920 +#define MC_MIN_LENGTH_XUSB_0 0x928 +#define MC_MIN_LENGTH_MPCORE_0 0x8cc +#define MC_MIN_LENGTH_TSECB_0 0xb48 +#define MC_MIN_LENGTH_SDMMCA_0 0xb10 +#define MC_MIN_LENGTH_GPU2_0 0xb40 +#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c +#define MC_MIN_LENGTH_PTC_0 0x8f8 +#define MC_EMEM_ARB_OVERRIDE_1 0x968 +#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984 +#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988 +#define MC_EMEM_ARB_STATS_0 0x990 +#define MC_EMEM_ARB_STATS_1 0x994 +#define MC_MTS_CARVEOUT_BOM 0x9a0 +#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4 +#define MC_MTS_CARVEOUT_ADR_HI 0x9a8 +#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac +#define MC_ERR_MTS_STATUS 0x9b0 +#define MC_ERR_MTS_ADR 0x9b4 +#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 +#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74 +#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10 +#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c +#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4 +#define MC_SECURITY_CARVEOUT2_CFG0 0xc58 +#define MC_SECURITY_CARVEOUT1_CFG0 0xc08 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84 +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68 +#define MC_SECURITY_CARVEOUT3_BOM 0xcac +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60 +#define MC_SECURITY_CARVEOUT3_CFG0 0xca8 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88 +#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64 +#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50 +#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14 +#define MC_SECURITY_CARVEOUT1_BOM 0xc0c +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4 +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c +#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8 +#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60 +#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80 +#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc +#define MC_SECURITY_CARVEOUT4_BOM 0xcfc +#define MC_SECURITY_CARVEOUT5_CFG0 0xd48 +#define MC_SECURITY_CARVEOUT2_BOM 0xc5c +#define MC_SECURITY_CARVEOUT5_BOM 0xd4c +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0 +#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08 +#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 +#define MC_DA_CONFIG0 0x9dc + +/* Virtual aliases */ +#define VIRT_MC_SECURITY_CFG3 MAKE_MC_REG(MC_SECURITY_CFG3) + +/* Memory Controller clients */ +#define CLIENT_ACCESS_NUM_CLIENTS 32 +typedef enum { + /* _ACCESS0 */ + CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + + /* _ACCESS1 */ + CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + + /* _ACCESS2 */ + CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + + /* _ACCESS3 */ + CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + + /* _ACCESS4 */ + CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4)) +} McClient; + +/* Memory Controller carveouts */ +#define CARVEOUT_ID_MIN 1 +#define CARVEOUT_ID_MAX 5 +typedef struct { + uint32_t config; + uint32_t paddr_low; + uint32_t paddr_high; + uint32_t size_big_pages; + uint32_t client_access_0; + uint32_t client_access_1; + uint32_t client_access_2; + uint32_t client_access_3; + uint32_t client_access_4; + uint32_t client_force_internal_access_0; + uint32_t client_force_internal_access_1; + uint32_t client_force_internal_access_2; + uint32_t client_force_internal_access_3; + uint32_t client_force_internal_access_4; + uint8_t padding[0x18]; +} security_carveout_t; + +void disable_bpmp_access_to_dram(void); + +#endif \ No newline at end of file diff --git a/exosphere/lp0fw/src/start.s b/exosphere/lp0fw/src/start.s index 9abe6a391..17aab0bfc 100644 --- a/exosphere/lp0fw/src/start.s +++ b/exosphere/lp0fw/src/start.s @@ -47,14 +47,11 @@ .global _start _start: b crt0 -.rept 0x7C - .word 0x00000000 /* Padding */ -.endr .global _metadata _metadata: .ascii "WBT0" /* Magic number */ - .word 0x00000000 /* TrustZone relative base. */ + .word 0x00000000 /* Target firmware. */ .word 0x00000000 /* Reserved */ .word 0x00000000 /* Reserved */ diff --git a/exosphere/lp0fw/src/utils.h b/exosphere/lp0fw/src/utils.h index 60a48d6b6..f1e43cec6 100644 --- a/exosphere/lp0fw/src/utils.h +++ b/exosphere/lp0fw/src/utils.h @@ -20,6 +20,7 @@ #include <stdbool.h> #include <stddef.h> #include <stdint.h> +#include <atmosphere.h> #define BIT(n) (1u << (n)) #define BITL(n) (1ull << (n)) diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 9d01ae08a..fbaf2bb27 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -52,7 +52,7 @@ void setup_dram_magic_numbers(void) { unsigned int target_fw = exosphere_get_target_firmware(); (*(volatile uint32_t *)(0x8005FFFC)) = 0xC0EDBBCC; /* Access test value. */ flush_dcache_range((void *)0x8005FFFC, (void *)0x80060000); - if (EXOSPHERE_TARGET_FIRMWARE_600 <= target_fw) { + if (ATMOSPHERE_TARGET_FIRMWARE_600 <= target_fw) { (*(volatile uint32_t *)(0x8005FF00)) = 0x00000083; /* SKU code. */ (*(volatile uint32_t *)(0x8005FF04)) = 0x00000002; (*(volatile uint32_t *)(0x8005FF08)) = 0x00000210; /* Tegra210 code. */ @@ -81,7 +81,7 @@ void bootup_misc_mmio(void) { se_generate_random_key(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY); se_generate_srk(KEYSLOT_SWITCH_SRKGENKEY); - if (!g_has_booted_up && (EXOSPHERE_TARGET_FIRMWARE_600 > exosphere_get_target_firmware())) { + if (!g_has_booted_up && (ATMOSPHERE_TARGET_FIRMWARE_600 > exosphere_get_target_firmware())) { setup_dram_magic_numbers(); } @@ -113,7 +113,7 @@ void bootup_misc_mmio(void) { configure_default_carveouts(); /* Mark registers secure world only. */ - if (exosphere_get_target_firmware() == EXOSPHERE_TARGET_FIRMWARE_100) { + if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_100) { APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 = APB_SSER0_SATA_AUX | APB_SSER0_DTV | APB_SSER0_QSPI | APB_SSER0_SATA | APB_SSER0_LA; APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 = APB_SSER1_SPI1 | APB_SSER1_SPI2 | APB_SSER1_SPI3 | APB_SSER1_SPI5 | APB_SSER1_SPI6 | APB_SSER1_I2C4 | APB_SSER1_I2C6; APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0 = 1 << 4 | 1 << 5 | APB_SSER2_DDS; /* bits 4 and 5 are not labeled in 21.1.7.3 */ @@ -130,7 +130,7 @@ void bootup_misc_mmio(void) { /* Also mark I2C4 secure only, */ sec_disable_1 |= APB_SSER1_I2C4; } - if (hardware_type != 0 && exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (hardware_type != 0 && exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { /* Starting on 4.x on non-dev units, mark UARTB, UARTC, SPI4, I2C3 secure only. */ sec_disable_1 |= APB_SSER1_UART_B | APB_SSER1_UART_C | APB_SSER1_SPI4 | APB_SSER1_I2C3; /* Starting on 4.x on non-dev units, mark SDMMC1 secure only. */ @@ -148,7 +148,7 @@ void bootup_misc_mmio(void) { MAKE_MC_REG(MC_SMMU_TRANSLATION_ENABLE_4) = 0xFFFFFFFF; /* TODO: What are these MC reg writes? */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { MAKE_MC_REG(0x038) = 0xE; } else { MAKE_MC_REG(0x038) = 0x0; @@ -163,7 +163,7 @@ void bootup_misc_mmio(void) { MAKE_MC_REG(0x9F0) = 0; MAKE_MC_REG(0x9F4) = 0; - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { MAKE_MC_REG(MC_SMMU_PTB_ASID) = 0; } MAKE_MC_REG(MC_SMMU_PTB_DATA) = 0; @@ -179,7 +179,7 @@ void bootup_misc_mmio(void) { /* Clear RESET Vector, setup CPU Secure Boot RESET Vectors. */ uint32_t reset_vec; - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { reset_vec = TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); } else { reset_vec = TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_WARMBOOT_CRT0_AND_MAIN); @@ -205,7 +205,7 @@ void bootup_misc_mmio(void) { intr_set_cpu_mask(INTERRUPT_ID_SECURITY_ENGINE, 8); intr_set_edge_level(INTERRUPT_ID_SECURITY_ENGINE, 0); - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { intr_set_priority(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); intr_set_group(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 0); intr_set_enabled(INTERRUPT_ID_ACTIVITY_MONITOR_4X, 1); @@ -220,14 +220,14 @@ void bootup_misc_mmio(void) { uart_init(UART_A, 115200); intr_register_handler(INTERRUPT_ID_SECURITY_ENGINE, se_operation_completed); - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { intr_register_handler(INTERRUPT_ID_ACTIVITY_MONITOR_4X, actmon_interrupt_handler); } for (unsigned int core = 1; core < NUM_CPU_CORES; core++) { set_core_is_active(core, false); } g_has_booted_up = true; - } else if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400) { + } else if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) { /* Disable AHB redirect. */ MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; MAKE_MC_REG(MC_IRAM_TOM) = 0; @@ -237,7 +237,7 @@ void bootup_misc_mmio(void) { } void setup_4x_mmio(void) { - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { configure_gpu_ucode_carveout(); } @@ -360,9 +360,9 @@ void identity_unmap_iram_cd_tzram(void) { } void secure_additional_devices(void) { - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0 |= APB_SSER0_PMC; /* make PMC secure-only (2.x+) */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0 |= APB_SSER1_MC0 | APB_SSER1_MC1 | APB_SSER1_MCB; /* make MC0, MC1, MCB secure-only (4.x+) */ } } diff --git a/exosphere/src/coldboot_init.c b/exosphere/src/coldboot_init.c index aedc28277..1ea3ebb9c 100644 --- a/exosphere/src/coldboot_init.c +++ b/exosphere/src/coldboot_init.c @@ -91,7 +91,7 @@ static void tzram_map_all_segments(uintptr_t *mmu_l3_tbl, unsigned int target_fi static const uintptr_t offs_5x[] = { TUPLE_FOLD_LEFT_0(EVAL(TZRAM_SEGMENT_ID_MAX), _MMAPTZ5XS, COMMA) }; for(size_t i = 0, offset = 0; i < TZRAM_SEGMENT_ID_MAX; i++) { - uintptr_t off = (target_firmware < EXOSPHERE_TARGET_FIRMWARE_500) ? offs[i] : offs_5x[i]; + uintptr_t off = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_500) ? offs[i] : offs_5x[i]; tzram_map_segment(mmu_l3_tbl, TZRAM_SEGMENT_BASE + offset, 0x7C010000ull + off, sizes[i], is_executable[i]); offset += increments[i]; } @@ -101,7 +101,7 @@ static void configure_ttbls(unsigned int target_firmware) { uintptr_t *mmu_l1_tbl; uintptr_t *mmu_l2_tbl; uintptr_t *mmu_l3_tbl; - if (target_firmware < EXOSPHERE_TARGET_FIRMWARE_500) { + if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_500) { mmu_l1_tbl = (uintptr_t *)(TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800 - 64); mmu_l2_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L2_TRANSLATION_TABLE); mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); @@ -151,7 +151,7 @@ uintptr_t get_coldboot_crt0_temp_stack_address(void) { } uintptr_t get_coldboot_crt0_stack_address(void) { - if (exosphere_get_target_firmware_for_init() < EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware_for_init() < ATMOSPHERE_TARGET_FIRMWARE_500) { return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; } else { return TZRAM_GET_SEGMENT_5X_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x800; @@ -193,7 +193,7 @@ void coldboot_init(coldboot_crt0_reloc_list_t *reloc_list, uintptr_t start_cold) init_dma_controllers(g_exosphere_target_firmware_for_init); configure_ttbls(g_exosphere_target_firmware_for_init); - if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { + if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) { set_memory_registers_enable_mmu_1x_ttbr0(); } else { set_memory_registers_enable_mmu_5x_ttbr0(); diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index cac02b835..66a98730a 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -125,7 +125,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) break; case CONFIGITEM_BOOTREASON: /* For some reason, Nintendo removed it on 4.0 */ - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) { *p_outvalue = bootconfig_get_boot_reason(); } else { result = 2; @@ -149,7 +149,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) break; case CONFIGITEM_ISQUESTUNIT: /* Added on 3.0, used to determine whether console is a kiosk unit. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_300) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_300) { *p_outvalue = (fuse_get_reserved_odm(4) >> 10) & 1; } else { result = 2; @@ -157,7 +157,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) break; case CONFIGITEM_NEWHARDWARETYPE_5X: /* Added in 5.x, currently hardcoded to 0. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { *p_outvalue = 0; } else { result = 2; @@ -165,7 +165,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) break; case CONFIGITEM_NEWKEYGENERATION_5X: /* Added in 5.x. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { *p_outvalue = fuse_get_5x_key_generation(); } else { result = 2; @@ -173,7 +173,7 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) break; case CONFIGITEM_PACKAGE2HASH_5X: /* Added in 5.x. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500 && bootconfig_is_recovery_boot()) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500 && bootconfig_is_recovery_boot()) { bootconfig_get_package2_hash_for_recovery(p_outvalue); } else { result = 2; diff --git a/exosphere/src/cpu_context.c b/exosphere/src/cpu_context.c index ed307dc46..13fb03aab 100644 --- a/exosphere/src/cpu_context.c +++ b/exosphere/src/cpu_context.c @@ -100,7 +100,7 @@ uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) { static const uint32_t status_masks[NUM_CPU_CORES] = {0x4000, 0x200, 0x400, 0x800}; static const uint32_t toggle_vals[NUM_CPU_CORES] = {0xE, 0x9, 0xA, 0xB}; - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { /* Reset the core */ CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 = (1 << (core + 0x10)) | (1 << core); } @@ -133,7 +133,7 @@ uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) { } CPU_ON_SUCCESS: - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { /* Start the core */ CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = (1 << (core + 0x10)) | (1 << core); } diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index 77d655dd2..08a929d7f 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -27,7 +27,7 @@ /* TODO: Should this be at a non-static location? */ #define MAILBOX_EXOSPHERE_CONFIG (*((volatile exosphere_config_t *)(MAILBOX_BASE + 0xE40ULL))) -static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_BOOTCONFIG, EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG, EXOSPHERE_FLAGS_DEFAULT}; +static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_BOOTCONFIG, ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG, EXOSPHERE_FLAGS_DEFAULT}; static bool g_has_loaded_config = false; #define EXOSPHERE_CHECK_FLAG(flag) ((g_exosphere_cfg.flags & flag) != 0) @@ -65,7 +65,7 @@ unsigned int exosphere_should_perform_620_keygen(void) { generic_panic(); } - return g_exosphere_cfg.target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620 && EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_PERFORM_620_KEYGEN); + return g_exosphere_cfg.target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620 && EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_PERFORM_620_KEYGEN); } unsigned int exosphere_should_override_debugmode_priv(void) { diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 56ff82fdf..2f41c6cf1 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -18,6 +18,7 @@ #define EXOSPHERE_EXOSPHERE_CONFIG_H #include <stdint.h> +#include <atmosphere.h> #include "utils.h" #include "memory_map.h" @@ -29,18 +30,6 @@ /* "XBC1" */ #define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258) -#define EXOSPHERE_TARGET_FIRMWARE_100 1 -#define EXOSPHERE_TARGET_FIRMWARE_200 2 -#define EXOSPHERE_TARGET_FIRMWARE_300 3 -#define EXOSPHERE_TARGET_FIRMWARE_400 4 -#define EXOSPHERE_TARGET_FIRMWARE_500 5 -#define EXOSPHERE_TARGET_FIRMWARE_600 6 -#define EXOSPHERE_TARGET_FIRMWARE_620 7 - -#define EXOSPHERE_TARGET_FIRMWARE_CURRENT EXOSPHERE_TARGET_FIRMWARE_620 - -/* TODO: What should this be, for release? */ -#define EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG EXOSPHERE_TARGET_FIRMWARE_CURRENT #define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1 #define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) @@ -70,7 +59,7 @@ static inline unsigned int exosphere_get_target_firmware_for_init(void) { if (magic == MAGIC_EXOSPHERE_BOOTCONFIG || magic == MAGIC_EXOSPHERE_BOOTCONFIG_0) { return MAILBOX_EXOSPHERE_CONFIG_PHYS.target_firmware; } else { - return EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG; + return ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG; } } diff --git a/exosphere/src/fuse.c b/exosphere/src/fuse.c index 3cad511ea..b33459f42 100644 --- a/exosphere/src/fuse.c +++ b/exosphere/src/fuse.c @@ -207,7 +207,7 @@ uint32_t fuse_get_hardware_type(void) { /* This function is very different between 4.x and < 4.x */ uint32_t hardware_type = ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 2) & 1); - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { static const uint32_t types[] = {0,1,4,3}; hardware_type |= (FUSE_CHIP_REGS->FUSE_RESERVED_ODM[4] >> 14) & 0x3C; diff --git a/exosphere/src/mc.c b/exosphere/src/mc.c index 332614c4a..c1979eea3 100644 --- a/exosphere/src/mc.c +++ b/exosphere/src/mc.c @@ -47,7 +47,7 @@ void configure_gpu_ucode_carveout(void) { carveout->size_big_pages = 2; /* 0x40000 */ carveout->client_access_0 = 0; carveout->client_access_1 = 0; - carveout->client_access_2 = (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) ? (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR) | BIT(CSR_TSECSRD)) : (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); + carveout->client_access_2 = (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) ? (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR) | BIT(CSR_TSECSRD)) : (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); carveout->client_access_3 = 0; carveout->client_access_4 = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); carveout->client_force_internal_access_0 = 0; @@ -77,7 +77,7 @@ void configure_default_carveouts(void) { carveout->config = 0x4000006; /* Configure Carveout 2 (GPU UCODE) */ - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600) { + if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_600) { configure_gpu_ucode_carveout(); } @@ -99,7 +99,7 @@ void configure_default_carveouts(void) { carveout->config = 0x4401E7E; /* Configure default Kernel carveouts based on 2.0.0+. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { /* Configure Carveout 4 (KERNEL_BUILTINS) */ configure_kernel_carveout(4, g_saved_carveouts[0].address, g_saved_carveouts[0].size); @@ -143,8 +143,8 @@ void configure_kernel_carveout(unsigned int carveout_id, uint64_t address, uint6 carveout->client_access_2 = (BIT(CSR_XUSB_HOSTR) | BIT(CSW_XUSB_HOSTW) | BIT(CSR_XUSB_DEVR) | BIT(CSW_XUSB_DEVW) | BIT(CSR_TSECSRD) | BIT(CSW_TSECSWR)); carveout->client_access_3 = (BIT(CSR_SDMMCRA) | BIT(CSR_SDMMCRAA) | BIT(CSR_SDMMCRAB) | BIT(CSW_SDMMCWA) | BIT(CSW_SDMMCWAA) | BIT(CSW_SDMMCWAB) | BIT(CSR_VICSRD) | BIT(CSW_VICSWR) | BIT(CSR_DISPLAYD) | BIT(CSR_NVDECSRD) | BIT(CSW_NVDECSWR) | BIT(CSR_APER) | BIT(CSW_APEW) | BIT(CSR_NVJPGSRD) | BIT(CSW_NVJPGSWR)); carveout->client_access_4 = (BIT(CSR_SESRD) | BIT(CSW_SESWR)); - carveout->client_force_internal_access_0 = ((exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSR_AVPCARM7R) : 0; - carveout->client_force_internal_access_1 = ((exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSW_AVPCARM7W) : 0; + carveout->client_force_internal_access_0 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSR_AVPCARM7R) : 0; + carveout->client_force_internal_access_1 = ((exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) && (carveout_id == 4)) ? BIT(CSW_AVPCARM7W) : 0; carveout->client_force_internal_access_2 = 0; carveout->client_force_internal_access_3 = 0; carveout->client_force_internal_access_4 = 0; diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index c4bed0142..80d3c1180 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -133,7 +133,7 @@ static void setup_se(void) { set_rsa_keyslot_flags(i, 0x41); } - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_620 && exosphere_should_perform_620_keygen()) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_620 && exosphere_should_perform_620_keygen()) { /* Start by generating device keys. */ se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_6XTSECKEY, work_buffer, 0x10, keyblob_key_seed_00, 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_4XOLDDEVICEKEY, KEYSLOT_SWITCH_6XSBK, work_buffer, 0x10); @@ -152,16 +152,16 @@ static void setup_se(void) { /* Derive new device keys. */ switch (exosphere_get_target_firmware()) { - case EXOSPHERE_TARGET_FIRMWARE_100: - case EXOSPHERE_TARGET_FIRMWARE_200: - case EXOSPHERE_TARGET_FIRMWARE_300: + case ATMOSPHERE_TARGET_FIRMWARE_100: + case ATMOSPHERE_TARGET_FIRMWARE_200: + case ATMOSPHERE_TARGET_FIRMWARE_300: break; - case EXOSPHERE_TARGET_FIRMWARE_400: + case ATMOSPHERE_TARGET_FIRMWARE_400: derive_new_device_keys(KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY); break; - case EXOSPHERE_TARGET_FIRMWARE_500: - case EXOSPHERE_TARGET_FIRMWARE_600: - case EXOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_500: + case ATMOSPHERE_TARGET_FIRMWARE_600: + case ATMOSPHERE_TARGET_FIRMWARE_620: derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY); break; } @@ -188,7 +188,7 @@ static void setup_boot_config(void) { bootconfig_clear(); } else { void *bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER; - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { bootconfig_ptr = NX_BOOTLOADER_BOOTCONFIG_POINTER_6X; } flush_dcache_range((uint8_t *)bootconfig_ptr, (uint8_t *)bootconfig_ptr + sizeof(bootconfig_t)); @@ -455,18 +455,18 @@ static void load_package2_sections(package2_meta_t *metadata, uint32_t master_ke static void copy_warmboot_bin_to_dram() { uint8_t *warmboot_src; switch (exosphere_get_target_firmware()) { - case EXOSPHERE_TARGET_FIRMWARE_100: - case EXOSPHERE_TARGET_FIRMWARE_200: - case EXOSPHERE_TARGET_FIRMWARE_300: + case ATMOSPHERE_TARGET_FIRMWARE_100: + case ATMOSPHERE_TARGET_FIRMWARE_200: + case ATMOSPHERE_TARGET_FIRMWARE_300: default: generic_panic(); break; - case EXOSPHERE_TARGET_FIRMWARE_400: - case EXOSPHERE_TARGET_FIRMWARE_500: + case ATMOSPHERE_TARGET_FIRMWARE_400: + case ATMOSPHERE_TARGET_FIRMWARE_500: warmboot_src = (uint8_t *)0x4003B000; break; - case EXOSPHERE_TARGET_FIRMWARE_600: - case EXOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_600: + case ATMOSPHERE_TARGET_FIRMWARE_620: warmboot_src = (uint8_t *)0x4003D800; break; } @@ -515,22 +515,22 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { setup_se(); /* Perform initial PMC register writes, if relevant. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { MAKE_REG32(PMC_BASE + 0x054) = 0x8000D000; MAKE_REG32(PMC_BASE + 0x0A0) &= 0xFFF3FFFF; MAKE_REG32(PMC_BASE + 0x818) &= 0xFFFFFFFE; MAKE_REG32(PMC_BASE + 0x334) |= 0x10; switch (exosphere_get_target_firmware()) { - case EXOSPHERE_TARGET_FIRMWARE_400: + case ATMOSPHERE_TARGET_FIRMWARE_400: MAKE_REG32(PMC_BASE + 0x360) = 0x105; break; - case EXOSPHERE_TARGET_FIRMWARE_500: + case ATMOSPHERE_TARGET_FIRMWARE_500: MAKE_REG32(PMC_BASE + 0x360) = 6; break; - case EXOSPHERE_TARGET_FIRMWARE_600: + case ATMOSPHERE_TARGET_FIRMWARE_600: MAKE_REG32(PMC_BASE + 0x360) = 0x87; break; - case EXOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_620: MAKE_REG32(PMC_BASE + 0x360) = 0xA8; break; } @@ -564,7 +564,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { setup_boot_config(); /* Set sysctr0 registers based on bootconfig. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { uint64_t sysctr0_val = bootconfig_get_value_for_sysctr0(); MAKE_SYSCTR0_REG(0x8) = (uint32_t)((sysctr0_val >> 0) & 0xFFFFFFFFULL); MAKE_SYSCTR0_REG(0xC) = (uint32_t)((sysctr0_val >> 32) & 0xFFFFFFFFULL); @@ -572,10 +572,10 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { } /* Synchronize with NX BOOTLOADER. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { sync_with_nx_bootloader(NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X); copy_warmboot_bin_to_dram(); - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { setup_dram_magic_numbers(); } sync_with_nx_bootloader(NX_BOOTLOADER_STATE_LOADED_PACKAGE2_4X); @@ -628,7 +628,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { } /* Synchronize with NX BOOTLOADER. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { sync_with_nx_bootloader(NX_BOOTLOADER_STATE_FINISHED_4X); setup_4x_mmio(); } else { diff --git a/exosphere/src/sc7.c b/exosphere/src/sc7.c index f168a895f..a7908c6f6 100644 --- a/exosphere/src/sc7.c +++ b/exosphere/src/sc7.c @@ -89,14 +89,14 @@ static void mitigate_jamais_vu(void) { } /* For debugging, make this check always pass. */ - if ((exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3)) { + if ((exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3)) { FLOW_CTLR_HALT_COP_EVENTS_0 = 0x50000000; } else { FLOW_CTLR_HALT_COP_EVENTS_0 = 0x40000000; } /* Jamais Vu mitigation #2: Ensure the BPMP is halted. */ - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3) { + if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400 || (get_debug_authentication_status() & 3) == 3) { /* BPMP should just be plainly halted, in debugging conditions. */ if (FLOW_CTLR_HALT_COP_EVENTS_0 != 0x50000000) { generic_panic(); @@ -166,7 +166,7 @@ static void save_tzram_state(void) { uint8_t *tzram_encryption_dst = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM)); uint8_t *tzram_encryption_src = (uint8_t *)(LP0_ENTRY_GET_RAM_SEGMENT_ADDRESS(LP0_ENTRY_RAM_SEGMENT_ID_CURRENT_TZRAM)); - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { tzram_encryption_src += 0x2000ull; } uint8_t *tzram_store_address = (uint8_t *)(WARMBOOT_GET_RAM_SEGMENT_ADDRESS(WARMBOOT_RAM_SEGMENT_ID_TZRAM)); @@ -203,7 +203,7 @@ static void save_tzram_state(void) { APBDEV_PMC_SEC_DISABLE8_0 = 0x550000; /* Perform pre-2.0.0 PMC writes. */ - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_200) { + if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_200) { /* TODO: Give these writes appropriate defines in pmc.h */ /* Save Encrypted context location + lock scratch register. */ @@ -271,7 +271,7 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen notify_pmic_shutdown(); /* Validate that the shutdown has correct context. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { mitigate_jamais_vu(); } @@ -279,7 +279,7 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen configure_pmc_for_deep_powerdown(); /* Ensure that BPMP SC7 firmware is active. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { setup_bpmp_sc7_firmware(); } @@ -293,7 +293,7 @@ uint32_t cpu_suspend(uint64_t power_state, uint64_t entrypoint, uint64_t argumen /* Ensure that other cores are already asleep. */ if (!(APBDEV_PMC_PWRGATE_STATUS_0 & 0xE00)) { - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_200) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_200) { call_with_stack_pointer(get_smc_core012_stack_address(), save_se_and_power_down_cpu); } else { save_se_and_power_down_cpu(); diff --git a/exosphere/src/sealedkeys.c b/exosphere/src/sealedkeys.c index 14142b274..0d6e9ad48 100644 --- a/exosphere/src/sealedkeys.c +++ b/exosphere/src/sealedkeys.c @@ -37,7 +37,7 @@ static const uint8_t g_seal_key_sources[CRYPTOUSECASE_MAX_5X][0x10] = { }; bool usecase_is_invalid(unsigned int usecase) { - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { return usecase >= CRYPTOUSECASE_MAX_5X; } else { return usecase >= CRYPTOUSECASE_MAX; diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index 336f593cb..2cb028589 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -145,21 +145,21 @@ void set_suspend_for_debug(void) { void set_version_specific_smcs(void) { switch (exosphere_get_target_firmware()) { - case EXOSPHERE_TARGET_FIRMWARE_100: + case ATMOSPHERE_TARGET_FIRMWARE_100: /* 1.0.0 doesn't have ConfigureCarveout or ReadWriteRegister. */ g_smc_priv_table[7].handler = NULL; g_smc_priv_table[8].handler = NULL; /* 1.0.0 doesn't have UnwrapAesWrappedTitlekey. */ g_smc_user_table[0x12].handler = NULL; break; - case EXOSPHERE_TARGET_FIRMWARE_200: - case EXOSPHERE_TARGET_FIRMWARE_300: - case EXOSPHERE_TARGET_FIRMWARE_400: + case ATMOSPHERE_TARGET_FIRMWARE_200: + case ATMOSPHERE_TARGET_FIRMWARE_300: + case ATMOSPHERE_TARGET_FIRMWARE_400: /* Do nothing. */ break; - case EXOSPHERE_TARGET_FIRMWARE_500: - case EXOSPHERE_TARGET_FIRMWARE_600: - case EXOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_500: + case ATMOSPHERE_TARGET_FIRMWARE_600: + case ATMOSPHERE_TARGET_FIRMWARE_620: /* No more LoadSecureExpModKey. */ g_smc_user_table[0xE].handler = NULL; g_smc_user_table[0xC].id = 0xC300D60C; @@ -280,7 +280,7 @@ void call_smc_handler(uint32_t handler_id, smc_args_t *args) { #endif #if DEBUG_PANIC_ON_FAILURE - if (args->X[0] && (!is_aes_kek || args->X[3] <= EXOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG)) + if (args->X[0] && (!is_aes_kek || args->X[3] <= ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG)) { MAKE_REG32(get_iram_address_for_debug() + 0x4FF0) = handler_id; MAKE_REG32(get_iram_address_for_debug() + 0x4FF4) = smc_id; @@ -594,7 +594,7 @@ uint32_t smc_read_write_register(smc_args_t *args) { } else { return 2; } - } else if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400 && MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address && + } else if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400 && MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) <= address && address < MMIO_GET_DEVICE_PA(MMIO_DEVID_MC) + MMIO_GET_DEVICE_SIZE(MMIO_DEVID_MC)) { /* Memory Controller RW supported only on 4.0.0+ */ const uint8_t mc_whitelist[0x68] = { @@ -667,7 +667,7 @@ uint32_t smc_configure_carveout(smc_args_t *args) { } /* Configuration is one-shot, and cannot be done multiple times. */ - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_300) { + if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_300) { if (g_configured_carveouts[carveout_id]) { return 2; } diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c index 4ebf6369f..e042f179f 100644 --- a/exosphere/src/smc_user.c +++ b/exosphere/src/smc_user.c @@ -42,14 +42,14 @@ static uint8_t g_rsausecase_to_cryptousecase[5] = {1, 2, 3, 5, 6}; static bool is_user_keyslot_valid(unsigned int keyslot) { switch (exosphere_get_target_firmware()) { - case EXOSPHERE_TARGET_FIRMWARE_100: - case EXOSPHERE_TARGET_FIRMWARE_200: - case EXOSPHERE_TARGET_FIRMWARE_300: - case EXOSPHERE_TARGET_FIRMWARE_400: - case EXOSPHERE_TARGET_FIRMWARE_500: + case ATMOSPHERE_TARGET_FIRMWARE_100: + case ATMOSPHERE_TARGET_FIRMWARE_200: + case ATMOSPHERE_TARGET_FIRMWARE_300: + case ATMOSPHERE_TARGET_FIRMWARE_400: + case ATMOSPHERE_TARGET_FIRMWARE_500: return keyslot <= 3; - case EXOSPHERE_TARGET_FIRMWARE_600: - case EXOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_600: + case ATMOSPHERE_TARGET_FIRMWARE_620: default: return keyslot <= 5; } @@ -157,7 +157,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) { uint8_t mask_id = (uint8_t)((packed_options >> 1) & 3); /* Switches the output based on how it will be used. */ - uint8_t usecase = (uint8_t)((packed_options >> 5) & (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500 ? 7 : 3)); + uint8_t usecase = (uint8_t)((packed_options >> 5) & (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500 ? 7 : 3)); /* Switched the output based on whether it should be console unique. */ bool is_personalized = (int)(packed_options & 1); @@ -165,7 +165,7 @@ uint32_t user_generate_aes_kek(smc_args_t *args) { bool is_recovery_boot = configitem_is_recovery_boot(); /* 5.0.0+ Bounds checking. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { if (is_personalized) { if (master_key_rev >= MASTERKEY_REVISION_MAX || (MASTERKEY_REVISION_300 <= master_key_rev && master_key_rev < MASTERKEY_REVISION_400_410)) { return 2; @@ -219,9 +219,9 @@ uint32_t user_generate_aes_kek(smc_args_t *args) { unsigned int keyslot; if (is_personalized) { /* Behavior changed in 4.0.0, and in 5.0.0. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { keyslot = devkey_get_keyslot(master_key_rev); - } else if (exosphere_get_target_firmware() == EXOSPHERE_TARGET_FIRMWARE_400) { + } else if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_400) { if (master_key_rev >= 1) { keyslot = KEYSLOT_SWITCH_DEVICEKEY; /* New device key, 4.x. */ } else { @@ -294,7 +294,7 @@ uint32_t user_crypt_aes(smc_args_t *args) { uint32_t keyslot = args->X[1] & 3; uint32_t mode = (args->X[1] >> 4) & 3; - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { keyslot = args->X[1] & 7; } @@ -310,7 +310,7 @@ uint32_t user_crypt_aes(smc_args_t *args) { return 2; } - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { /* Disallow dma lists outside of safe range. */ if (in_ll_paddr - 0x80000000 >= 0x3FF7F5) { return 2; @@ -358,7 +358,7 @@ uint32_t user_generate_specific_aes_key(smc_args_t *args) { if (master_key_rev > 0) { master_key_rev -= 1; } - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400) { master_key_rev = 0; } @@ -374,9 +374,9 @@ uint32_t user_generate_specific_aes_key(smc_args_t *args) { unsigned int keyslot; /* Behavior changed in 5.0.0. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { keyslot = devkey_get_keyslot(master_key_rev); - } else if (exosphere_get_target_firmware() == EXOSPHERE_TARGET_FIRMWARE_400) { + } else if (exosphere_get_target_firmware() == ATMOSPHERE_TARGET_FIRMWARE_400) { if (master_key_rev >= 1) { keyslot = KEYSLOT_SWITCH_DEVICEKEY; /* New device key, 4.x. */ } else { @@ -455,7 +455,7 @@ uint32_t user_load_rsa_oaep_key(smc_args_t *args) { upage_ref_t page_ref; /* This function no longer exists in 5.x+. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { generic_panic(); } @@ -504,7 +504,7 @@ uint32_t user_decrypt_rsa_private_key(smc_args_t *args) { upage_ref_t page_ref; /* This function no longer exists in 5.x+. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { generic_panic(); } @@ -562,7 +562,7 @@ uint32_t user_load_secure_exp_mod_key(smc_args_t *args) { upage_ref_t page_ref; /* This function no longer exists in 5.x+. */ - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { generic_panic(); } @@ -618,7 +618,7 @@ uint32_t user_secure_exp_mod(smc_args_t *args) { void *user_modulus = (void *)args->X[2]; unsigned int exponent_id = 1; - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_500) { switch (args->X[3]) { case 0: exponent_id = 1; @@ -664,7 +664,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) { unsigned int option = (unsigned int)args->X[7]; unsigned int master_key_rev; unsigned int titlekey_type; - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_600) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_600) { master_key_rev = option & 0x3F; titlekey_type = (option >> 6) & 1; } else { @@ -676,7 +676,7 @@ uint32_t user_unwrap_rsa_oaep_wrapped_titlekey(smc_args_t *args) { master_key_rev -= 1; } - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_300) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_300) { if (master_key_rev >= MASTERKEY_REVISION_MAX) { return 2; } @@ -741,7 +741,7 @@ uint32_t user_unwrap_aes_wrapped_titlekey(smc_args_t *args) { if (master_key_rev > 0) { master_key_rev -= 1; } - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_300) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_300) { if (master_key_rev >= MASTERKEY_REVISION_MAX) { return 2; } @@ -837,7 +837,7 @@ uint32_t user_decrypt_or_import_rsa_key(smc_args_t *args) { upage_ref_t page_ref; /* This function only exists in 5.x+. */ - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_500) { + if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_500) { generic_panic(); } diff --git a/exosphere/src/titlekey.c b/exosphere/src/titlekey.c index b5a35b6f5..3e0e5907a 100644 --- a/exosphere/src/titlekey.c +++ b/exosphere/src/titlekey.c @@ -44,7 +44,7 @@ void tkey_set_master_key_rev(unsigned int master_key_rev) { } static void tkey_validate_type(unsigned int type) { - if (type > TITLEKEY_TYPE_MAX || (type > 0 && exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_600)) { + if (type > TITLEKEY_TYPE_MAX || (type > 0 && exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_600)) { generic_panic(); } } diff --git a/exosphere/src/warmboot_init.c b/exosphere/src/warmboot_init.c index 6a22294a4..2422b03ba 100644 --- a/exosphere/src/warmboot_init.c +++ b/exosphere/src/warmboot_init.c @@ -25,7 +25,7 @@ #undef MC_BASE #define MC_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_MC)) -#define WARMBOOT_GET_TZRAM_SEGMENT_PA(x) ((g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) \ +#define WARMBOOT_GET_TZRAM_SEGMENT_PA(x) ((g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) \ ? TZRAM_GET_SEGMENT_PA(x) : TZRAM_GET_SEGMENT_5X_PA(x)) /* start.s */ @@ -53,7 +53,7 @@ void warmboot_crt0_critical_section_enter(volatile critical_section_t *critical_ } void init_dma_controllers(unsigned int target_firmware) { - if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) { /* Set some unknown registers in HOST1X. */ MAKE_REG32(0x500038F8) &= 0xFFFFFFFE; MAKE_REG32(0x50003300) = 0; @@ -205,7 +205,7 @@ void warmboot_init(void) { /*identity_remap_tzram();*/ /* Nintendo pointlessly fully invalidate the TLB & invalidate the data cache on the modified ranges here */ - if (g_exosphere_target_firmware_for_init < EXOSPHERE_TARGET_FIRMWARE_500) { + if (g_exosphere_target_firmware_for_init < ATMOSPHERE_TARGET_FIRMWARE_500) { set_memory_registers_enable_mmu_1x_ttbr0(); } else { set_memory_registers_enable_mmu_5x_ttbr0(); diff --git a/exosphere/src/warmboot_main.c b/exosphere/src/warmboot_main.c index d6f66aeb3..b782a61e9 100644 --- a/exosphere/src/warmboot_main.c +++ b/exosphere/src/warmboot_main.c @@ -79,7 +79,7 @@ void __attribute__((noreturn)) warmboot_main(void) { /* Make PMC (2.x+), MC (4.x+) registers secure-only */ secure_additional_devices(); - if (exosphere_get_target_firmware() < EXOSPHERE_TARGET_FIRMWARE_400 || configitem_get_hardware_type() == 0) { + if (exosphere_get_target_firmware() < ATMOSPHERE_TARGET_FIRMWARE_400 || configitem_get_hardware_type() == 0) { /* Enable input to I2C1 */ PINMUX_AUX_GEN1_I2C_SCL_0 = 0x40; PINMUX_AUX_GEN1_I2C_SDA_0 = 0x40; @@ -92,7 +92,7 @@ void __attribute__((noreturn)) warmboot_main(void) { clear_user_smc_in_progress(); - if (exosphere_get_target_firmware() >= EXOSPHERE_TARGET_FIRMWARE_400) { + if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_400) { setup_4x_mmio(); } } diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index d21abb4f9..55c8d12c5 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -17,6 +17,8 @@ #ifndef FUSEE_EXOSPHERE_CONFIG_H #define FUSEE_EXOSPHERE_CONFIG_H +#include <atmosphere.h> + /* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */ /* "XBC0" */ @@ -24,16 +26,6 @@ /* "XBC1" */ #define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258) -#define EXOSPHERE_TARGET_FIRMWARE_100 1 -#define EXOSPHERE_TARGET_FIRMWARE_200 2 -#define EXOSPHERE_TARGET_FIRMWARE_300 3 -#define EXOSPHERE_TARGET_FIRMWARE_400 4 -#define EXOSPHERE_TARGET_FIRMWARE_500 5 -#define EXOSPHERE_TARGET_FIRMWARE_600 6 -#define EXOSPHERE_TARGET_FIRMWARE_620 7 - -#define EXOSPHERE_TARGET_FIRMWARE_MIN EXOSPHERE_TARGET_FIRMWARE_100 -#define EXOSPHERE_TARGET_FIRMWARE_MAX EXOSPHERE_TARGET_FIRMWARE_620 #define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index 0daab0f38..3b934f59c 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -141,7 +141,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui } /* Do 6.2.0+ keygen. */ - if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { if (memcmp(tsec_root_key, zeroes, 0x10) != 0) { /* We got a valid key from emulation. */ set_aes_keyslot(0xC, tsec_root_key, 0x10); @@ -185,27 +185,27 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui set_aes_keyslot(0xC, g_dec_keyblobs[available_revision].master_kek, 0x10); /* Also set the Package1 key for the revision that is stored on the eMMC boot0 partition. */ - if (target_firmware < EXOSPHERE_TARGET_FIRMWARE_620) { + if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_620) { load_package1_key(available_revision); } /* Derive keys for Exosphere, lock critical keyslots. */ switch (target_firmware) { - case EXOSPHERE_TARGET_FIRMWARE_100: - case EXOSPHERE_TARGET_FIRMWARE_200: - case EXOSPHERE_TARGET_FIRMWARE_300: + case ATMOSPHERE_TARGET_FIRMWARE_100: + case ATMOSPHERE_TARGET_FIRMWARE_200: + case ATMOSPHERE_TARGET_FIRMWARE_300: decrypt_data_into_keyslot(0xD, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10); break; - case EXOSPHERE_TARGET_FIRMWARE_400: + case ATMOSPHERE_TARGET_FIRMWARE_400: decrypt_data_into_keyslot(0xD, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10); break; - case EXOSPHERE_TARGET_FIRMWARE_500: - case EXOSPHERE_TARGET_FIRMWARE_600: - case EXOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_500: + case ATMOSPHERE_TARGET_FIRMWARE_600: + case ATMOSPHERE_TARGET_FIRMWARE_620: decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); @@ -222,11 +222,11 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui /* Sets final keyslot flags, for handover to TZ/Exosphere. Setting these will prevent the BPMP from using the device key or master key. */ void finalize_nx_keydata(uint32_t target_firmware) { set_aes_keyslot_flags(0xC, 0xFF); - set_aes_keyslot_flags((target_firmware >= EXOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY), 0xFF); + set_aes_keyslot_flags((target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY), 0xFF); } static void generate_specific_aes_key(void *dst, const void *wrapped_key, bool should_mask, uint32_t target_firmware) { - unsigned int keyslot = (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY); + unsigned int keyslot = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY); if (fuse_get_bootrom_patch_version() < 0x7F) { /* On dev units, use a fixed "all-zeroes" seed. */ /* Yes, this data really is all-zero in actual TrustZone .rodata. */ @@ -257,7 +257,7 @@ static void generate_personalized_aes_key_for_bis(void *dst, const void *wrapped 0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8 }; - unsigned int keyslot = (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY); + unsigned int keyslot = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? (KEYSLOT_SWITCH_4XOLDDEVICEKEY) : (KEYSLOT_SWITCH_DEVICEKEY); /* Derive kek. */ decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, keyslot, kek_source, 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_TEMPKEY, KEYSLOT_SWITCH_TEMPKEY, wrapped_kek, 0x10); diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index e023e23fa..37e4d293c 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -106,20 +106,20 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; switch (package1loader_header->version) { case 0x01: /* 1.0.0 */ - return EXOSPHERE_TARGET_FIRMWARE_100; + return ATMOSPHERE_TARGET_FIRMWARE_100; case 0x02: /* 2.0.0 - 2.3.0 */ - return EXOSPHERE_TARGET_FIRMWARE_200; + return ATMOSPHERE_TARGET_FIRMWARE_200; case 0x04: /* 3.0.0 and 3.0.1 - 3.0.2 */ - return EXOSPHERE_TARGET_FIRMWARE_300; + return ATMOSPHERE_TARGET_FIRMWARE_300; case 0x07: /* 4.0.0 - 4.1.0 */ - return EXOSPHERE_TARGET_FIRMWARE_400; + return ATMOSPHERE_TARGET_FIRMWARE_400; case 0x0B: /* 5.0.0 - 5.1.0 */ - return EXOSPHERE_TARGET_FIRMWARE_500; + return ATMOSPHERE_TARGET_FIRMWARE_500; case 0x0E: { /* 6.0.0 - 6.2.0 */ if (memcmp(package1loader_header->build_timestamp, "20180802", 8) == 0) { - return EXOSPHERE_TARGET_FIRMWARE_600; + return ATMOSPHERE_TARGET_FIRMWARE_600; } else if (memcmp(package1loader_header->build_timestamp, "20181107", 8) == 0) { - return EXOSPHERE_TARGET_FIRMWARE_620; + return ATMOSPHERE_TARGET_FIRMWARE_620; } else { fatal_error("[NXBOOT]: Unable to identify package1!\n"); } @@ -144,7 +144,7 @@ static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int ke fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); } - if ((exo_cfg.target_firmware < EXOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > EXOSPHERE_TARGET_FIRMWARE_MAX)) { + if ((exo_cfg.target_firmware < ATMOSPHERE_TARGET_FIRMWARE_MIN) || (exo_cfg.target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX)) { fatal_error("[NXBOOT]: Invalid Exosphere target firmware!\n"); } @@ -164,7 +164,7 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) { } } else { /* Check if fuses are < 4.0.0, but firmware is >= 4.0.0 */ - if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_400 && !(fuse_get_reserved_odm(7) & ~0x0000000F)) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400 && !(fuse_get_reserved_odm(7) & ~0x0000000F)) { kip_patches_set_enable_nogc(); } } @@ -252,8 +252,8 @@ static void nxboot_move_bootconfig() { fclose(bcfile); /* Select the actual BootConfig size and destination address. */ - bootconfig_addr = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_600) ? 0x4003D000 : 0x4003F800; - bootconfig_size = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) ? 0x3000 : 0x1000; + bootconfig_addr = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_600) ? 0x4003D000 : 0x4003F800; + bootconfig_size = (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) ? 0x3000 : 0x1000; /* Copy the BootConfig into IRAM. */ memset((void *)bootconfig_addr, 0, bootconfig_size); @@ -360,7 +360,7 @@ uint32_t nxboot_main(void) { if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); } - if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { tsec_fw_size = 0x2900; } else { tsec_fw_size = 0xF00; @@ -372,7 +372,7 @@ uint32_t nxboot_main(void) { /* Get the TSEC keys. */ uint8_t tsec_key[0x10] = {0}; uint8_t tsec_root_key[0x10] = {0}; - if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { uint8_t tsec_keys[0x20] = {0}; /* Emulate the TSEC payload on 6.2.0+. */ @@ -398,7 +398,7 @@ uint32_t nxboot_main(void) { nxboot_configure_exosphere(target_firmware, keygen_type); /* Initialize Boot Reason on older firmware versions. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Initializing Boot Reason...\n"); nxboot_set_bootreason(); } @@ -420,7 +420,7 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } } else { - if (target_firmware >= EXOSPHERE_TARGET_FIRMWARE_620) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { /* Package1 was decrypted during TSEC emulation. */ const uint8_t *package1_hdr = (const uint8_t *)package1loader + 0x7000 - 0x20; package1 = (package1_header_t *)(package1_hdr + 0x20); @@ -446,9 +446,9 @@ uint32_t nxboot_main(void) { } /* Select the right address for the warmboot firmware. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { warmboot_memaddr = (void *)0x8000D000; - } else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_600) { + } else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_600) { warmboot_memaddr = (void *)0x4003B000; } else { warmboot_memaddr = (void *)0x4003D800; @@ -459,7 +459,7 @@ uint32_t nxboot_main(void) { /* Copy the warmboot firmware and set the address in PMC if necessary. */ if (warmboot_fw && (warmboot_fw_size > 0)) { memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size); - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) pmc->scratch1 = (uint32_t)warmboot_memaddr; } @@ -474,7 +474,7 @@ uint32_t nxboot_main(void) { print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Reading Exosphère...\n"); /* Select the right address for Exosphère. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { exosphere_memaddr = (void *)0x4002D000; } else { exosphere_memaddr = (void *)0x4002B000; @@ -502,7 +502,7 @@ uint32_t nxboot_main(void) { nxboot_move_bootconfig(); /* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == EXOSPHERE_TARGET_FIRMWARE_300) { + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == ATMOSPHERE_TARGET_FIRMWARE_300) { const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader; if (!strcmp(package1loader_header->build_timestamp, "20170519101410")) pmc->secure_scratch32 = 0xE3; /* Warmboot 3.0.0 security check.*/ diff --git a/fusee/fusee-secondary/src/nxboot_iram.c b/fusee/fusee-secondary/src/nxboot_iram.c index 86466a072..0705af10d 100644 --- a/fusee/fusee-secondary/src/nxboot_iram.c +++ b/fusee/fusee-secondary/src/nxboot_iram.c @@ -36,7 +36,7 @@ void nxboot_finish(uint32_t boot_memaddr) { /* Lock keyslots. */ set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF); - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); } else { set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); @@ -62,7 +62,7 @@ void nxboot_finish(uint32_t boot_memaddr) { /* Boot up Exosphère. */ MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; } else { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; @@ -93,7 +93,7 @@ void nxboot_finish(uint32_t boot_memaddr) { } /* Signal Exosphère. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < EXOSPHERE_TARGET_FIRMWARE_400) { + if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED; } else { MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index 2a07e1ff0..acdaa7e89 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -62,7 +62,7 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { return g_stratosphere_ini1; } - if (target_firmware <= EXOSPHERE_TARGET_FIRMWARE_100) { + if (target_firmware <= ATMOSPHERE_TARGET_FIRMWARE_100) { boot_kip = boot_100_kip; boot_kip_size = boot_100_kip_size; } else { From 5f905c6b42acc19dcee167421131f3af201ee8e9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 13:22:08 -0800 Subject: [PATCH 317/489] warmboot: Add device debug configuration --- exosphere/lp0fw/src/fuse.h | 189 +++++++++++++++++++++++++++++++++++ exosphere/lp0fw/src/lp0.c | 4 + exosphere/lp0fw/src/misc.c | 47 +++++++++ exosphere/lp0fw/src/misc.h | 33 ++++++ exosphere/lp0fw/src/pmc.h | 2 +- exosphere/lp0fw/src/sysreg.h | 46 +++++++++ 6 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 exosphere/lp0fw/src/fuse.h create mode 100644 exosphere/lp0fw/src/misc.c create mode 100644 exosphere/lp0fw/src/misc.h create mode 100644 exosphere/lp0fw/src/sysreg.h diff --git a/exosphere/lp0fw/src/fuse.h b/exosphere/lp0fw/src/fuse.h new file mode 100644 index 000000000..b07e8b9d5 --- /dev/null +++ b/exosphere/lp0fw/src/fuse.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_FUSE_H +#define EXOSPHERE_WARMBOOT_BIN_FUSE_H + +#include <stdbool.h> +#include <stdint.h> + +#include "utils.h" + +typedef struct { + uint32_t FUSE_CTRL; + uint32_t FUSE_REG_ADDR; + uint32_t FUSE_REG_READ; + uint32_t FUSE_REG_WRITE; + uint32_t FUSE_TIME_RD1; + uint32_t FUSE_TIME_RD2; + uint32_t FUSE_TIME_PGM1; + uint32_t FUSE_TIME_PGM2; + uint32_t FUSE_PRIV2INTFC; + uint32_t FUSE_FUSEBYPASS; + uint32_t FUSE_PRIVATEKEYDISABLE; + uint32_t FUSE_DIS_PGM; + uint32_t FUSE_WRITE_ACCESS; + uint32_t FUSE_PWR_GOOD_SW; + uint32_t _0x38[0x32]; +} fuse_registers_t; + +typedef struct { + uint32_t FUSE_PRODUCTION_MODE; + uint32_t _0x4; + uint32_t _0x8; + uint32_t _0xC; + uint32_t FUSE_SKU_INFO; + uint32_t FUSE_CPU_SPEEDO_0; + uint32_t FUSE_CPU_IDDQ; + uint32_t _0x1C; + uint32_t _0x20; + uint32_t _0x24; + uint32_t FUSE_FT_REV; + uint32_t FUSE_CPU_SPEEDO_1; + uint32_t FUSE_CPU_SPEEDO_2; + uint32_t FUSE_SOC_SPEEDO_0; + uint32_t FUSE_SOC_SPEEDO_1; + uint32_t FUSE_SOC_SPEEDO_2; + uint32_t FUSE_SOC_IDDQ; + uint32_t _0x44; + uint32_t FUSE_FA; + uint32_t _0x4C; + uint32_t _0x50; + uint32_t _0x54; + uint32_t _0x58; + uint32_t _0x5C; + uint32_t _0x60; + uint32_t FUSE_PUBLIC_KEY[0x8]; + uint32_t FUSE_TSENSOR_1; + uint32_t FUSE_TSENSOR_2; + uint32_t _0x8C; + uint32_t FUSE_CP_REV; + uint32_t _0x94; + uint32_t FUSE_TSENSOR_0; + uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG; + uint32_t FUSE_SECURITY_MODE; + uint32_t FUSE_PRIVATE_KEY[0x4]; + uint32_t FUSE_DEVICE_KEY; + uint32_t _0xB8; + uint32_t _0xBC; + uint32_t FUSE_RESERVED_SW; + uint32_t FUSE_VP8_ENABLE; + uint32_t FUSE_RESERVED_ODM[0x8]; + uint32_t _0xE8; + uint32_t _0xEC; + uint32_t FUSE_SKU_USB_CALIB; + uint32_t FUSE_SKU_DIRECT_CONFIG; + uint32_t _0xF8; + uint32_t _0xFC; + uint32_t FUSE_VENDOR_CODE; + uint32_t FUSE_FAB_CODE; + uint32_t FUSE_LOT_CODE_0; + uint32_t FUSE_LOT_CODE_1; + uint32_t FUSE_WAFER_ID; + uint32_t FUSE_X_COORDINATE; + uint32_t FUSE_Y_COORDINATE; + uint32_t _0x11C; + uint32_t _0x120; + uint32_t FUSE_SATA_CALIB; + uint32_t FUSE_GPU_IDDQ; + uint32_t FUSE_TSENSOR_3; + uint32_t _0x130; + uint32_t _0x134; + uint32_t _0x138; + uint32_t _0x13C; + uint32_t _0x140; + uint32_t _0x144; + uint32_t FUSE_OPT_SUBREVISION; + uint32_t _0x14C; + uint32_t _0x150; + uint32_t FUSE_TSENSOR_4; + uint32_t FUSE_TSENSOR_5; + uint32_t FUSE_TSENSOR_6; + uint32_t FUSE_TSENSOR_7; + uint32_t FUSE_OPT_PRIV_SEC_DIS; + uint32_t FUSE_PKC_DISABLE; + uint32_t _0x16C; + uint32_t _0x170; + uint32_t _0x174; + uint32_t _0x178; + uint32_t _0x17C; + uint32_t FUSE_TSENSOR_COMMON; + uint32_t _0x184; + uint32_t _0x188; + uint32_t _0x18C; + uint32_t _0x190; + uint32_t _0x194; + uint32_t _0x198; + uint32_t FUSE_DEBUG_AUTH_OVERRIDE; + uint32_t _0x1A0; + uint32_t _0x1A4; + uint32_t _0x1A8; + uint32_t _0x1AC; + uint32_t _0x1B0; + uint32_t _0x1B4; + uint32_t _0x1B8; + uint32_t _0x1BC; + uint32_t _0x1D0; + uint32_t FUSE_TSENSOR_8; + uint32_t _0x1D8; + uint32_t _0x1DC; + uint32_t _0x1E0; + uint32_t _0x1E4; + uint32_t _0x1E8; + uint32_t _0x1EC; + uint32_t _0x1F0; + uint32_t _0x1F4; + uint32_t _0x1F8; + uint32_t _0x1FC; + uint32_t _0x200; + uint32_t FUSE_RESERVED_CALIB; + uint32_t _0x208; + uint32_t _0x20C; + uint32_t _0x210; + uint32_t _0x214; + uint32_t _0x218; + uint32_t FUSE_TSENSOR_9; + uint32_t _0x220; + uint32_t _0x224; + uint32_t _0x228; + uint32_t _0x22C; + uint32_t _0x230; + uint32_t _0x234; + uint32_t _0x238; + uint32_t _0x23C; + uint32_t _0x240; + uint32_t _0x244; + uint32_t _0x248; + uint32_t _0x24C; + uint32_t FUSE_USB_CALIB_EXT; + uint32_t _0x254; + uint32_t _0x258; + uint32_t _0x25C; + uint32_t _0x260; + uint32_t _0x264; + uint32_t _0x268; + uint32_t _0x26C; + uint32_t _0x270; + uint32_t _0x274; + uint32_t _0x278; + uint32_t _0x27C; + uint32_t FUSE_SPARE_BIT[0x20]; +} fuse_chip_registers_t; + +#define FUSE_REGS ((volatile fuse_registers_t *)(0x7000F800)) +#define FUSE_CHIP_REGS ((volatile fuse_chip_registers_t *)(0x7000F900)) + +#endif diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c index 7f1c77ec4..fd6525a41 100644 --- a/exosphere/lp0fw/src/lp0.c +++ b/exosphere/lp0fw/src/lp0.c @@ -18,6 +18,7 @@ #include "lp0.h" #include "mc.h" #include "pmc.h" +#include "misc.h" #include "timer.h" void reboot(void) { @@ -39,6 +40,9 @@ void lp0_entry_main(warmboot_metadata_t *meta) { disable_bpmp_access_to_dram(); } + /* Configure debugging depending on FUSE_PRODUCTION_MODE */ + configure_device_dbg_settings(); + /* TODO: stuff */ while (true) { /* TODO: Halt BPMP */ } diff --git a/exosphere/lp0fw/src/misc.c b/exosphere/lp0fw/src/misc.c new file mode 100644 index 000000000..3310f0e86 --- /dev/null +++ b/exosphere/lp0fw/src/misc.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "utils.h" +#include "misc.h" +#include "fuse.h" +#include "sysreg.h" +#include "pmc.h" + +void configure_device_dbg_settings(void) { + /* Enable RTCK daisychaining by setting TBE bit. */ + APB_MISC_PP_CONFIG_CTL_0 = 0x80; + + /* Literally none of this is documented in the TRM, lol. */ + if (FUSE_CHIP_REGS->FUSE_SECURITY_MODE == 1) { + uint32_t secure_boot_val = 0b0100; /* Sets NIDEN for aarch64. */ + uint32_t misc_val = 0x40; + if (APBDEV_PMC_STICKY_BITS_0 & 0x40) { + misc_val = 0x0; + } else { + secure_boot_val = 0b1101; /* Sets SPNIDEN, NIDEN, DBGEN for aarch64. */ + } + SB_PFCFG_0 = (SB_PFCFG_0 & ~0b1111) | secure_boot_val; /* Configures debug bits. */ + APB_MISC_PP_CONFIG_CTL_0 |= misc_val; /* Undocumented, seems to control invasive debugging/JTAG. */ + } + + /* Set sticky bits based SECURITY_MODE. */ + APBDEV_PMC_STICKY_BITS_0 |= FUSE_CHIP_REGS->FUSE_SECURITY_MODE; + + /* Set E_INPUT in PINMUX_AUX_GPIO_PA6_0 */ + PINMUX_AUX_GPIO_PA6_0 |= 0x40; +} diff --git a/exosphere/lp0fw/src/misc.h b/exosphere/lp0fw/src/misc.h new file mode 100644 index 000000000..6d34e075f --- /dev/null +++ b/exosphere/lp0fw/src/misc.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_MISC_H +#define EXOSPHERE_WARMBOOT_BIN_MISC_H + +#include <stdint.h> + +#define MISC_BASE (0x70000000) + +#define MAKE_MISC_REG(n) MAKE_REG32(MISC_BASE + n) + +#define APB_MISC_PP_CONFIG_CTL_0 MAKE_MISC_REG(0x024) + + +#define PINMUX_AUX_GPIO_PA6_0 MAKE_MISC_REG(0x3244) + +void configure_device_dbg_settings(void); + +#endif diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h index dd32e9c2e..9025fbd33 100644 --- a/exosphere/lp0fw/src/pmc.h +++ b/exosphere/lp0fw/src/pmc.h @@ -37,7 +37,7 @@ #define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084) #define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098) - +#define APBDEV_PMC_STICKY_BITS_0 MAKE_PMC_REG(0x2C0) #define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) #define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C) diff --git a/exosphere/lp0fw/src/sysreg.h b/exosphere/lp0fw/src/sysreg.h new file mode 100644 index 000000000..87e0fc0fa --- /dev/null +++ b/exosphere/lp0fw/src/sysreg.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_SYSREG_H +#define EXOSPHERE_WARMBOOT_BIN_SYSREG_H + +#include <stdint.h> + + +#define SYSREG_BASE (0x6000C000) + +#define SB_BASE (SYSREG_BASE + 0x200) + +#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n) +#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n) + +#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004) + +#define SB_CSR_0 MAKE_SB_REG(0x00) +#define SB_PIROM_START_0 MAKE_SB_REG(0x04) +#define SB_PFCFG_0 MAKE_SB_REG(0x08) +#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C) +#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10) +#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14) +#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18) +#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C) +#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20) +#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24) +#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28) +#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30) +#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34) + +#endif From a94bee71d214000049daa07802be7c550b796894 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 13:58:28 -0800 Subject: [PATCH 318/489] warmboot: add fuse bypass init --- exosphere/lp0fw/src/car.c | 84 ++++++++++++++++++++++++++++++++++++++ exosphere/lp0fw/src/car.h | 53 ++++++++++++++++++++++++ exosphere/lp0fw/src/fuse.c | 71 ++++++++++++++++++++++++++++++++ exosphere/lp0fw/src/fuse.h | 11 +++++ exosphere/lp0fw/src/lp0.c | 26 +++++++++++- exosphere/lp0fw/src/lp0.h | 2 +- exosphere/lp0fw/src/misc.h | 2 + exosphere/lp0fw/src/pmc.h | 4 ++ 8 files changed, 250 insertions(+), 3 deletions(-) create mode 100644 exosphere/lp0fw/src/car.c create mode 100644 exosphere/lp0fw/src/car.h create mode 100644 exosphere/lp0fw/src/fuse.c diff --git a/exosphere/lp0fw/src/car.c b/exosphere/lp0fw/src/car.c new file mode 100644 index 000000000..bf0a5b780 --- /dev/null +++ b/exosphere/lp0fw/src/car.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "utils.h" +#include "car.h" +#include "timer.h" +#include "lp0.h" + +static inline uint32_t get_special_clk_reg(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0x178; + case CARDEVICE_UARTB: return 0x17C; + case CARDEVICE_I2C1: return 0x124; + case CARDEVICE_I2C5: return 0x128; + case CARDEVICE_ACTMON: return 0x3E8; + case CARDEVICE_BPMP: return 0; + default: reboot(); + } +} + +static inline uint32_t get_special_clk_val(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_I2C1: return (6 << 29); + case CARDEVICE_I2C5: return (6 << 29); + case CARDEVICE_ACTMON: return (6 << 29); + case CARDEVICE_BPMP: return 0; + default: reboot(); + } +} + +static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; +static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; + +void clk_enable(CarDevice dev) { + uint32_t special_reg; + if ((special_reg = get_special_clk_reg(dev))) { + MAKE_CAR_REG(special_reg) = get_special_clk_val(dev); + } + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void clk_disable(CarDevice dev) { + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void rst_enable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void rst_disable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void clkrst_enable(CarDevice dev) { + clk_enable(dev); + rst_disable(dev); +} + +void clkrst_disable(CarDevice dev) { + rst_enable(dev); + clk_disable(dev); +} + +void clkrst_reboot(CarDevice dev) { + clkrst_disable(dev); + clkrst_enable(dev); +} diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h new file mode 100644 index 000000000..c2596b848 --- /dev/null +++ b/exosphere/lp0fw/src/car.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_CLOCK_AND_RESET_H +#define EXOSPHERE_WARMBOOT_BIN_CLOCK_AND_RESET_H + +#include <stdint.h> + +#define CAR_BASE 0x60006000 + +#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) + +#define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 MAKE_CAR_REG(0x048) +#define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) +#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) +#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) +#define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454) + +#define NUM_CAR_BANKS 7 + +typedef enum { + CARDEVICE_UARTA = 6, + CARDEVICE_UARTB = 7, + CARDEVICE_I2C1 = 12, + CARDEVICE_I2C5 = 47, + CARDEVICE_ACTMON = 119, + CARDEVICE_BPMP = 1 +} CarDevice; + +void clk_enable(CarDevice dev); +void clk_disable(CarDevice dev); +void rst_enable(CarDevice dev); +void rst_disable(CarDevice dev); + +void clkrst_enable(CarDevice dev); +void clkrst_disable(CarDevice dev); + +void clkrst_reboot(CarDevice dev); + +#endif diff --git a/exosphere/lp0fw/src/fuse.c b/exosphere/lp0fw/src/fuse.c new file mode 100644 index 000000000..84a64cfa6 --- /dev/null +++ b/exosphere/lp0fw/src/fuse.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "utils.h" +#include "fuse.h" +#include "car.h" +#include "pmc.h" + +#define NUM_FUSE_BYPASS_ENTRIES 0 + +bool fuse_check_downgrade_status(void) { + /* We aren't going to implement anti-downgrade. */ + return false; +} + +static fuse_bypass_data_t g_fuse_bypass_entries[NUM_FUSE_BYPASS_ENTRIES] = { + /* No entries here. */ +}; + +void fuse_configure_fuse_bypass(void) { + /* Enable fuses in CAR? This seems to affect fuse data visibility. */ + CLK_RST_CONTROLLER_MISC_CLK_ENB_0 |= 0x10000000; + + /* Configure bypass/override, only if programming is allowed. */ + if (!(FUSE_REGS->FUSE_DIS_PGM & 1)) { + /* Enable write access. */ + FUSE_REGS->FUSE_WRITE_ACCESS = (FUSE_REGS->FUSE_WRITE_ACCESS & ~0x1) | 0x10000; + /* Enable fuse bypass config. */ + FUSE_REGS->FUSE_FUSEBYPASS = 1; + + /* Override fuses. */ + for (size_t i = 0; i < NUM_FUSE_BYPASS_ENTRIES; i++) { + MAKE_FUSE_REG(g_fuse_bypass_entries[i].offset) = g_fuse_bypass_entries[i].value; + } + + /* Disable fuse write access. */ + FUSE_REGS->FUSE_WRITE_ACCESS |= 1; + + /* Enable fuse bypass config. */ + /* I think this is a bug, and Nintendo meant to write 0 here? */ + FUSE_REGS->FUSE_FUSEBYPASS = 1; + + /* This...clears the disable programming bit(?). */ + /* I have no idea why this happens. What? */ + /* This is probably also either a bug or does nothing. */ + /* Is this bit even clearable? */ + FUSE_REGS->FUSE_DIS_PGM &= 0xFFFFFFFE; + + /* Restore saved private key disable bit. */ + FUSE_REGS->FUSE_PRIVATEKEYDISABLE |= (APBDEV_PMC_SECURE_SCRATCH21_0 & 0x10); + + /* Lock private key disable secure scratch. */ + APBDEV_PMC_SEC_DISABLE2_0 |= 0x4000000; + } + +} diff --git a/exosphere/lp0fw/src/fuse.h b/exosphere/lp0fw/src/fuse.h index b07e8b9d5..39706bd89 100644 --- a/exosphere/lp0fw/src/fuse.h +++ b/exosphere/lp0fw/src/fuse.h @@ -186,4 +186,15 @@ typedef struct { #define FUSE_REGS ((volatile fuse_registers_t *)(0x7000F800)) #define FUSE_CHIP_REGS ((volatile fuse_chip_registers_t *)(0x7000F900)) +#define MAKE_FUSE_REG(n) MAKE_REG32(0x7000F800 + n) + +typedef struct { + uint32_t offset; + uint32_t value; +} fuse_bypass_data_t; + +bool fuse_check_downgrade_status(void); + +void fuse_configure_fuse_bypass(void); + #endif diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c index fd6525a41..dcb68aa4d 100644 --- a/exosphere/lp0fw/src/lp0.c +++ b/exosphere/lp0fw/src/lp0.c @@ -19,6 +19,7 @@ #include "mc.h" #include "pmc.h" #include "misc.h" +#include "fuse.h" #include "timer.h" void reboot(void) { @@ -30,19 +31,40 @@ void reboot(void) { } void lp0_entry_main(warmboot_metadata_t *meta) { + const uint32_t target_firmware = meta->target_firmware; /* Before doing anything else, ensure some sanity. */ - if (meta->magic != WARMBOOT_MAGIC || meta->target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX) { + if (meta->magic != WARMBOOT_MAGIC || target_firmware > ATMOSPHERE_TARGET_FIRMWARE_MAX) { reboot(); } /* [4.0.0+] First thing warmboot does is disable BPMP access to memory. */ - if (meta->target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) { disable_bpmp_access_to_dram(); } /* Configure debugging depending on FUSE_PRODUCTION_MODE */ configure_device_dbg_settings(); + /* Check for downgrade. */ + /* NOTE: We implemented this as "return false" */ + if (fuse_check_downgrade_status()) { + reboot(); + } + + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_300) { + /* Nintendo's firmware checks APBDEV_PMC_SECURE_SCRATCH32_0 against a per-warmboot binary value here. */ + /* We won't bother with that. */ + if (false /* APBDEV_PMC_SECURE_SCRATCH32_0 == WARMBOOT_MAGIC_NUMBER */) { + reboot(); + } + } + + /* TODO: Check that we're running at the correct physical address. */ + + /* Setup fuses, disable bypass. */ + fuse_configure_fuse_bypass(); + + /* TODO: stuff */ while (true) { /* TODO: Halt BPMP */ } diff --git a/exosphere/lp0fw/src/lp0.h b/exosphere/lp0fw/src/lp0.h index 90cdb6850..04787f0ed 100644 --- a/exosphere/lp0fw/src/lp0.h +++ b/exosphere/lp0fw/src/lp0.h @@ -30,6 +30,6 @@ typedef struct { void lp0_entry_main(warmboot_metadata_t *meta); -void reboot(void); +void __attribute__((noreturn)) reboot(void); #endif diff --git a/exosphere/lp0fw/src/misc.h b/exosphere/lp0fw/src/misc.h index 6d34e075f..4c94002c2 100644 --- a/exosphere/lp0fw/src/misc.h +++ b/exosphere/lp0fw/src/misc.h @@ -19,6 +19,8 @@ #include <stdint.h> +#include "utils.h" + #define MISC_BASE (0x70000000) #define MAKE_MISC_REG(n) MAKE_REG32(MISC_BASE + n) diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h index 9025fbd33..982caf444 100644 --- a/exosphere/lp0fw/src/pmc.h +++ b/exosphere/lp0fw/src/pmc.h @@ -38,8 +38,12 @@ #define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098) #define APBDEV_PMC_STICKY_BITS_0 MAKE_PMC_REG(0x2C0) +#define APBDEV_PMC_SEC_DISABLE2_0 MAKE_PMC_REG(0x2C4) #define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) +#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334) +#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360) + #define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C) #define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460) From 0b15539479b97142b5ac78019f1e7ff08edc1530 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 14:18:04 -0800 Subject: [PATCH 319/489] warmboot: add car_configure_oscillators --- exosphere/lp0fw/src/car.c | 15 +++++++++++++++ exosphere/lp0fw/src/car.h | 5 +++++ exosphere/lp0fw/src/pmc.h | 2 ++ exosphere/lp0fw/src/timer.h | 1 + 4 files changed, 23 insertions(+) diff --git a/exosphere/lp0fw/src/car.c b/exosphere/lp0fw/src/car.c index bf0a5b780..93e36da8a 100644 --- a/exosphere/lp0fw/src/car.c +++ b/exosphere/lp0fw/src/car.c @@ -19,6 +19,7 @@ #include "utils.h" #include "car.h" #include "timer.h" +#include "pmc.h" #include "lp0.h" static inline uint32_t get_special_clk_reg(CarDevice dev) { @@ -48,6 +49,20 @@ static inline uint32_t get_special_clk_val(CarDevice dev) { static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; +void car_configure_oscillators(void) { + /* Enable the crystal oscillator, setting drive strength to the saved value in PMC. */ + CLK_RST_CONTROLLER_OSC_CTRL_0 = (CLK_RST_CONTROLLER_OSC_CTRL_0 & 0xFFFFFC0E) | 1 | (((APBDEV_PMC_OSC_EDPD_OVER_0 >> 1) & 0x3F) << 4); + + /* Set CLK_M_DIVISOR to 1 (causes actual division by 2.) */ + CLK_RST_CONTROLLER_SPARE_REG0_0 = (1 << 2); + /* Reading the register after writing it is required to ensure value takes. */ + (void)(CLK_RST_CONTROLLER_SPARE_REG0_0); + + /* Set TIMERUS_USEC_CFG to cycle at 0x60 / 0x5 = 19.2 MHz. */ + /* Value is (dividend << 8) | (divisor). */ + TIMERUS_USEC_CFG_0 = 0x45F; +} + void clk_enable(CarDevice dev) { uint32_t special_reg; if ((special_reg = get_special_clk_reg(dev))) { diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h index c2596b848..32659a2d0 100644 --- a/exosphere/lp0fw/src/car.h +++ b/exosphere/lp0fw/src/car.h @@ -24,11 +24,14 @@ #define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) #define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 MAKE_CAR_REG(0x048) +#define CLK_RST_CONTROLLER_OSC_CTRL_0 MAKE_CAR_REG(0x050) #define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454) +#define CLK_RST_CONTROLLER_SPARE_REG0_0 MAKE_CAR_REG(0x55C) + #define NUM_CAR_BANKS 7 typedef enum { @@ -40,6 +43,8 @@ typedef enum { CARDEVICE_BPMP = 1 } CarDevice; +void car_configure_oscillators(void); + void clk_enable(CarDevice dev); void clk_disable(CarDevice dev); void rst_enable(CarDevice dev); diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h index 982caf444..22ce2d94d 100644 --- a/exosphere/lp0fw/src/pmc.h +++ b/exosphere/lp0fw/src/pmc.h @@ -37,6 +37,8 @@ #define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084) #define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098) +#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4) + #define APBDEV_PMC_STICKY_BITS_0 MAKE_PMC_REG(0x2C0) #define APBDEV_PMC_SEC_DISABLE2_0 MAKE_PMC_REG(0x2C4) #define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) diff --git a/exosphere/lp0fw/src/timer.h b/exosphere/lp0fw/src/timer.h index 74f4a6360..3a4911856 100644 --- a/exosphere/lp0fw/src/timer.h +++ b/exosphere/lp0fw/src/timer.h @@ -20,6 +20,7 @@ #include "utils.h" #define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010) +#define TIMERUS_USEC_CFG_0 MAKE_REG32(0x60005014) static inline void timer_wait(uint32_t microseconds) { uint32_t old_time = TIMERUS_CNTR_1US_0; From 8d08e609164bc18a02ec151b656c66a3e63fcea4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 14:40:30 -0800 Subject: [PATCH 320/489] warmboot: add ram config --- exosphere/lp0fw/src/emc.c | 33 ++++++++++++++++++ exosphere/lp0fw/src/emc.h | 71 ++++++++++++++++++++++++++++++++++++++ exosphere/lp0fw/src/lp0.c | 10 +++++- exosphere/lp0fw/src/misc.c | 7 +++- exosphere/lp0fw/src/misc.h | 5 ++- 5 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 exosphere/lp0fw/src/emc.c create mode 100644 exosphere/lp0fw/src/emc.h diff --git a/exosphere/lp0fw/src/emc.c b/exosphere/lp0fw/src/emc.c new file mode 100644 index 000000000..a2ffc57c9 --- /dev/null +++ b/exosphere/lp0fw/src/emc.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils.h" +#include "lp0.h" +#include "emc.h" +#include "pmc.h" +#include "timer.h" + +void emc_configure_pmacro_training(void) { + /* Set DISABLE_CFG_BYTEN for all N. */ + EMC_PMACRO_CFG_PM_GLOBAL_0_0 = 0xFF0000; + + /* Set CHN_TRAINING_E_WRPTR for channel 0 + channel 1. */ + EMC_PMACRO_TRAINING_CTRL_0_0 = 8; + EMC_PMACRO_TRAINING_CTRL_1_0 = 8; + + /* Clear DISABLE_CFG_BYTEN for all N. */ + EMC_PMACRO_CFG_PM_GLOBAL_0_0 = 0x0; +} \ No newline at end of file diff --git a/exosphere/lp0fw/src/emc.h b/exosphere/lp0fw/src/emc.h new file mode 100644 index 000000000..d9c54d041 --- /dev/null +++ b/exosphere/lp0fw/src/emc.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_EMC_H +#define EXOSPHERE_WARMBOOT_BIN_EMC_H + +#include "utils.h" + +#define EMC_BASE (0x7001B000) + +#define EMC0_BASE (0x7001E000) +#define EMC1_BASE (0x7001F000) + + +#define MAKE_EMC_REG(ofs) (MAKE_REG32(EMC_BASE + ofs)) + +#define MAKE_EMC0_REG(ofs) (MAKE_REG32(EMC0_BASE + ofs)) +#define MAKE_EMC1_REG(ofs) (MAKE_REG32(EMC1_BASE + ofs)) + +#define EMC_CFG_0 MAKE_EMC_REG(0x00C) + +#define EMC_ADR_CFG_0 MAKE_EMC_REG(0x10) + +#define EMC_TIMING_CONTROL_0 MAKE_EMC_REG(0x028) + +#define EMC_SELF_REF_0 MAKE_EMC_REG(0x0E0) + +#define EMC_MRW_0 MAKE_EMC_REG(0x0E8) + +#define EMC_FBIO_CFG5_0 MAKE_EMC_REG(0x104) + +#define EMC_MRW3_0 MAKE_EMC_REG(0x138) + +#define EMC_AUTO_CAL_CONFIG_0 MAKE_EMC_REG(0x2A4) + +#define EMC_REQ_CTRL_0 MAKE_EMC_REG(0x2B0) + +#define EMC_EMC_STATUS_0 MAKE_EMC_REG(0x2B4) +#define EMC0_EMC_STATUS_0 MAKE_EMC0_REG(0x2B4) +#define EMC1_EMC_STATUS_0 MAKE_EMC1_REG(0x2B4) + +#define EMC_CFG_DIG_DLL_0 MAKE_EMC_REG(0x2BC) +#define EMC0_CFG_DIG_DLL_0 MAKE_EMC0_REG(0x2BC) +#define EMC1_CFG_DIG_DLL_0 MAKE_EMC1_REG(0x2BC) + +#define EMC_ZCAL_INTERVAL_0 MAKE_EMC_REG(0x2E0) + +#define EMC_PMC_SCRATCH3_0 MAKE_EMC_REG(0x448) + +#define EMC_FBIO_CFG7_0 MAKE_EMC_REG(0x584) + +#define EMC_PMACRO_CFG_PM_GLOBAL_0_0 MAKE_EMC_REG(0xC30) +#define EMC_PMACRO_TRAINING_CTRL_0_0 MAKE_EMC_REG(0xCF8) +#define EMC_PMACRO_TRAINING_CTRL_1_0 MAKE_EMC_REG(0xCFC) + +void emc_configure_pmacro_training(void); + +#endif diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c index dcb68aa4d..9ca6e2b6a 100644 --- a/exosphere/lp0fw/src/lp0.c +++ b/exosphere/lp0fw/src/lp0.c @@ -20,6 +20,8 @@ #include "pmc.h" #include "misc.h" #include "fuse.h" +#include "car.h" +#include "emc.h" #include "timer.h" void reboot(void) { @@ -43,7 +45,7 @@ void lp0_entry_main(warmboot_metadata_t *meta) { } /* Configure debugging depending on FUSE_PRODUCTION_MODE */ - configure_device_dbg_settings(); + misc_configure_device_dbg_settings(); /* Check for downgrade. */ /* NOTE: We implemented this as "return false" */ @@ -64,6 +66,12 @@ void lp0_entry_main(warmboot_metadata_t *meta) { /* Setup fuses, disable bypass. */ fuse_configure_fuse_bypass(); + /* Configure oscillators/timing in CAR. */ + car_configure_oscillators(); + + /* Restore RAM configuration. */ + misc_restore_ram_svop(); + emc_configure_pmacro_training(); /* TODO: stuff */ diff --git a/exosphere/lp0fw/src/misc.c b/exosphere/lp0fw/src/misc.c index 3310f0e86..941f50981 100644 --- a/exosphere/lp0fw/src/misc.c +++ b/exosphere/lp0fw/src/misc.c @@ -22,7 +22,7 @@ #include "sysreg.h" #include "pmc.h" -void configure_device_dbg_settings(void) { +void misc_configure_device_dbg_settings(void) { /* Enable RTCK daisychaining by setting TBE bit. */ APB_MISC_PP_CONFIG_CTL_0 = 0x80; @@ -45,3 +45,8 @@ void configure_device_dbg_settings(void) { /* Set E_INPUT in PINMUX_AUX_GPIO_PA6_0 */ PINMUX_AUX_GPIO_PA6_0 |= 0x40; } + +void misc_restore_ram_svop(void) { + /* This sets CFG2TMC_RAM_SVOP_PDP to 0x2. */ + APB_MISC_GP_ASDBGREG_0 |= 0x02000000; +} \ No newline at end of file diff --git a/exosphere/lp0fw/src/misc.h b/exosphere/lp0fw/src/misc.h index 4c94002c2..a4f7c2b66 100644 --- a/exosphere/lp0fw/src/misc.h +++ b/exosphere/lp0fw/src/misc.h @@ -27,9 +27,12 @@ #define APB_MISC_PP_CONFIG_CTL_0 MAKE_MISC_REG(0x024) +#define APB_MISC_GP_ASDBGREG_0 MAKE_MISC_REG(0x810) #define PINMUX_AUX_GPIO_PA6_0 MAKE_MISC_REG(0x3244) -void configure_device_dbg_settings(void); +void misc_configure_device_dbg_settings(void); + +void misc_restore_ram_svop(void); #endif From 83941f864783190c1123db3a8b3c2923c65e75ed Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 15:35:07 -0800 Subject: [PATCH 321/489] warmboot: add car_mbist_workaround --- exosphere/lp0fw/src/car.c | 35 +++++++++++++++++++++++++++++++++++ exosphere/lp0fw/src/car.h | 9 +++++++++ exosphere/lp0fw/src/lp0.c | 3 +++ 3 files changed, 47 insertions(+) diff --git a/exosphere/lp0fw/src/car.c b/exosphere/lp0fw/src/car.c index 93e36da8a..12f3b7c3c 100644 --- a/exosphere/lp0fw/src/car.c +++ b/exosphere/lp0fw/src/car.c @@ -20,6 +20,7 @@ #include "car.h" #include "timer.h" #include "pmc.h" +#include "emc.h" #include "lp0.h" static inline uint32_t get_special_clk_reg(CarDevice dev) { @@ -49,6 +50,8 @@ static inline uint32_t get_special_clk_val(CarDevice dev) { static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; +static uint32_t g_clk_clr_reg_offsets[NUM_CAR_BANKS] = {0x324, 0x32C, 0x334, 0x444, 0x44C, 0x228, 0x2A0}; + void car_configure_oscillators(void) { /* Enable the crystal oscillator, setting drive strength to the saved value in PMC. */ CLK_RST_CONTROLLER_OSC_CTRL_0 = (CLK_RST_CONTROLLER_OSC_CTRL_0 & 0xFFFFFC0E) | 1 | (((APBDEV_PMC_OSC_EDPD_OVER_0 >> 1) & 0x3F) << 4); @@ -63,6 +66,38 @@ void car_configure_oscillators(void) { TIMERUS_USEC_CFG_0 = 0x45F; } +void car_mbist_workaround(void) { + /* This code works around MBIST bug. */ + + /* Clear LVL2_CLK_GATE_OVR* registers. */ + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA_0 = 0; + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0 = 0; + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC_0 = 0; + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 = 0; + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 = 0; + + /* Clear bit patterns in CAR. */ + /* L: Reset all but RTC, TMR, GPIO, BPMP Cache (CACHE2). */ + MAKE_CAR_REG(g_clk_clr_reg_offsets[0]) = MAKE_CAR_REG(g_clk_reg_offsets[0]) & 0x7FFFFECF; + /* H: Reset all but MC, PMC, FUSE, EMC. */ + MAKE_CAR_REG(g_clk_clr_reg_offsets[1]) = MAKE_CAR_REG(g_clk_reg_offsets[1]) & 0xFDFFFF3E; + /* U: Reset all but CSITE, IRAM[A-D], BPMP Cache RAM (CRAM2). */ + MAKE_CAR_REG(g_clk_clr_reg_offsets[2]) = MAKE_CAR_REG(g_clk_reg_offsets[2]) & 0xFE0FFDFF; + /* V: Reset all but MSELECT, S/PDIF audio doubler, TZRAM, SE. */ + MAKE_CAR_REG(g_clk_clr_reg_offsets[3]) = MAKE_CAR_REG(g_clk_reg_offsets[3]) & 0x3FBFFFF7; + /* W: Reset all but PCIERX[0-5], ENTROPY. */ + MAKE_CAR_REG(g_clk_clr_reg_offsets[4]) = MAKE_CAR_REG(g_clk_reg_offsets[4]) & 0xFFDFFF03; + /* X: Reset all but ETC, MCLK, MCLK2, I2C6, EMC_DLL, GPU, DBGAPB, PLLG_REF, . */ + MAKE_CAR_REG(g_clk_clr_reg_offsets[5]) = MAKE_CAR_REG(g_clk_reg_offsets[5]) & 0xDCFFB87F; + /* Y: Reset all but MC_CDPA, MC_CCPA. */ + MAKE_CAR_REG(g_clk_clr_reg_offsets[6]) = MAKE_CAR_REG(g_clk_reg_offsets[6]) & 0xFFFFFCFF; + + /* Enable clock to MC1, if CH1 is enabled in EMC. */ + if (EMC_FBIO_CFG7_0 & 4) { /* CH1_ENABLE */ + CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 |= 0x40000000; /* SET_CLK_ENB_MC1 */ + } +} + void clk_enable(CarDevice dev) { uint32_t special_reg; if ((special_reg = get_special_clk_reg(dev))) { diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h index 32659a2d0..f10c2e518 100644 --- a/exosphere/lp0fw/src/car.h +++ b/exosphere/lp0fw/src/car.h @@ -30,8 +30,16 @@ #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454) +#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA_0 MAKE_CAR_REG(0x0F8) +#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0 MAKE_CAR_REG(0x0FC) +#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC_0 MAKE_CAR_REG(0x3A0) +#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) +#define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 MAKE_CAR_REG(0x554) + #define CLK_RST_CONTROLLER_SPARE_REG0_0 MAKE_CAR_REG(0x55C) +#define CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 MAKE_CAR_REG(0x448) + #define NUM_CAR_BANKS 7 typedef enum { @@ -44,6 +52,7 @@ typedef enum { } CarDevice; void car_configure_oscillators(void); +void car_mbist_workaround(void); void clk_enable(CarDevice dev); void clk_disable(CarDevice dev); diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c index 9ca6e2b6a..a0ebd3985 100644 --- a/exosphere/lp0fw/src/lp0.c +++ b/exosphere/lp0fw/src/lp0.c @@ -73,6 +73,9 @@ void lp0_entry_main(warmboot_metadata_t *meta) { misc_restore_ram_svop(); emc_configure_pmacro_training(); + /* Setup clock output for all devices, working around mbist bug. */ + car_mbist_workaround(); + /* TODO: stuff */ while (true) { /* TODO: Halt BPMP */ } From 802830d8d40cf87da8843e23bb868b1bef61ede0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 16:04:50 -0800 Subject: [PATCH 322/489] warmboot: start cluster_init, skeleton all remaining code --- exosphere/lp0fw/src/car.h | 36 ++++++++++++++++++---- exosphere/lp0fw/src/cluster.c | 58 +++++++++++++++++++++++++++++++++++ exosphere/lp0fw/src/cluster.h | 24 +++++++++++++++ exosphere/lp0fw/src/flow.h | 31 +++++++++++++++++++ exosphere/lp0fw/src/lp0.c | 21 +++++++++++-- exosphere/lp0fw/src/pmc.h | 2 ++ exosphere/lp0fw/src/timer.h | 2 +- 7 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 exosphere/lp0fw/src/cluster.c create mode 100644 exosphere/lp0fw/src/cluster.h create mode 100644 exosphere/lp0fw/src/flow.h diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h index f10c2e518..bc08731d7 100644 --- a/exosphere/lp0fw/src/car.h +++ b/exosphere/lp0fw/src/car.h @@ -30,6 +30,12 @@ #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454) +#define CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER_0 MAKE_CAR_REG(0x36C) +#define CLK_RST_CONTROLLER_SUPER_CCLKP_DIVIDER_0 MAKE_CAR_REG(0x374) + +#define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0 MAKE_CAR_REG(0x388) +#define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT_0 MAKE_CAR_REG(0x3B4) + #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA_0 MAKE_CAR_REG(0x0F8) #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRB_0 MAKE_CAR_REG(0x0FC) #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRC_0 MAKE_CAR_REG(0x3A0) @@ -38,17 +44,35 @@ #define CLK_RST_CONTROLLER_SPARE_REG0_0 MAKE_CAR_REG(0x55C) +#define CLK_RST_CONTROLLER_RST_DEV_U_SET_0 MAKE_CAR_REG(0x310) + +#define CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 MAKE_CAR_REG(0x314) +#define CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 MAKE_CAR_REG(0x434) + +#define CLK_RST_CONTROLLER_CLK_ENB_U_SET_0 MAKE_CAR_REG(0x330) +#define CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 MAKE_CAR_REG(0x440) #define CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 MAKE_CAR_REG(0x448) #define NUM_CAR_BANKS 7 typedef enum { - CARDEVICE_UARTA = 6, - CARDEVICE_UARTB = 7, - CARDEVICE_I2C1 = 12, - CARDEVICE_I2C5 = 47, - CARDEVICE_ACTMON = 119, - CARDEVICE_BPMP = 1 + CARDEVICE_UARTA = ((0 << 5) | 0x6), + CARDEVICE_UARTB = ((0 << 5) | 0x7), + CARDEVICE_UARTC = ((1 << 5) | 0x17), + CARDEVICE_I2C1 = ((0 << 5) | 0xC), + CARDEVICE_I2C5 = ((1 << 5) | 0xF), + CARDEVICE_UNK = ((3 << 5) | 0x1E), + CARDEVICE_SE = ((3 << 5) | 0x1F), + CARDEVICE_HOST1X = ((0 << 5) | 0x1C), + CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E), + CARDEVICE_SOR0 = ((5 << 5) | 0x16), + CARDEVICE_SOR1 = ((5 << 5) | 0x17), + CARDEVICE_KFUSE = ((1 << 5) | 0x8), + CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B), + CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), + CARDEVICE_ACTMON = ((3 << 5) | 0x17), + CARDEVICE_BPMP = ((0 << 5) | 0x1) } CarDevice; void car_configure_oscillators(void); diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c new file mode 100644 index 000000000..daa5c6d84 --- /dev/null +++ b/exosphere/lp0fw/src/cluster.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "utils.h" +#include "cluster.h" +#include "car.h" +#include "timer.h" +#include "pmc.h" +#include "sysreg.h" + +void cluster_initialize_cpu(void) { + /* Hold CoreSight in reset. */ + CLK_RST_CONTROLLER_RST_DEV_U_SET_0 = 0x200; + + /* CAR2PMC_CPU_ACK_WIDTH should be set to 0. */ + CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0 &= 0xFFFFF000; + + /* Restore SB_AA64_RESET values from PMC scratch. */ + SB_AA64_RESET_LOW_0 = APBDEV_PMC_SECURE_SCRATCH34_0 | 1; + SB_AA64_RESET_HIGH_0 = APBDEV_PMC_SECURE_SCRATCH35_0; + + /* Set CDIV_ENB for CCLKG/CCLKP. */ + CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER_0 = 0x80000000; + CLK_RST_CONTROLLER_SUPER_CCLKP_DIVIDER_0 = 0x80000000; + + /* Enable CoreSight clock, take CoreSight out of reset. */ + CLK_RST_CONTROLLER_CLK_ENB_U_SET_0 = 0x200; + CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 = 0x200; + + /* Configure MSELECT to divide by 4, enable MSELECT clock. */ + CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT_0 = 6; /* (6/2) + 1 = 4. */ + CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 = 0x8; + + /* Wait 2 us, then take MSELECT out of reset. */ + timer_wait(2); + CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 = 0x8; + + /* TODO: This function is enormous */ +} + +void cluster_power_on_cpu(void) { + /* TODO */ +} \ No newline at end of file diff --git a/exosphere/lp0fw/src/cluster.h b/exosphere/lp0fw/src/cluster.h new file mode 100644 index 000000000..0551deb3f --- /dev/null +++ b/exosphere/lp0fw/src/cluster.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_CLUSTER_H +#define EXOSPHERE_WARMBOOT_BIN_CLUSTER_H + +void cluster_initialize_cpu(void); +void cluster_power_on_cpu(void); + +#endif diff --git a/exosphere/lp0fw/src/flow.h b/exosphere/lp0fw/src/flow.h new file mode 100644 index 000000000..559c79716 --- /dev/null +++ b/exosphere/lp0fw/src/flow.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_FLOW_CTLR_H +#define EXOSPHERE_WARMBOOT_BIN_FLOW_CTLR_H + +#include <stdint.h> +#include <stdbool.h> + +#include "utils.h" + +#define FLOW_BASE (0x60007000) + +#define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_BASE + ofs) + +#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) + +#endif diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c index a0ebd3985..565af3b79 100644 --- a/exosphere/lp0fw/src/lp0.c +++ b/exosphere/lp0fw/src/lp0.c @@ -22,6 +22,8 @@ #include "fuse.h" #include "car.h" #include "emc.h" +#include "cluster.h" +#include "flow.h" #include "timer.h" void reboot(void) { @@ -76,9 +78,22 @@ void lp0_entry_main(warmboot_metadata_t *meta) { /* Setup clock output for all devices, working around mbist bug. */ car_mbist_workaround(); - /* TODO: stuff */ - - while (true) { /* TODO: Halt BPMP */ } + /* Initialize the CPU cluster. */ + cluster_initialize_cpu(); + + /* TODO: decrypt_restore_secmon_to_tzram(); */ + + /* Power on the CPU cluster. */ + cluster_power_on_cpu(); + + /* Nintendo clears most of warmboot.bin out of IRAM here. We're not gonna bother. */ + /* memset( ... ); */ + + const uint32_t halt_val = (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_400) ? 0x40000000 : 0x50000000; + while (true) { + /* Halt the BPMP. */ + FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val; + } } diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h index 22ce2d94d..17a821903 100644 --- a/exosphere/lp0fw/src/pmc.h +++ b/exosphere/lp0fw/src/pmc.h @@ -45,6 +45,8 @@ #define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334) #define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360) +#define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_PMC_REG(0x368) +#define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_PMC_REG(0x36C) #define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C) #define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460) diff --git a/exosphere/lp0fw/src/timer.h b/exosphere/lp0fw/src/timer.h index 3a4911856..14d3b9afd 100644 --- a/exosphere/lp0fw/src/timer.h +++ b/exosphere/lp0fw/src/timer.h @@ -23,7 +23,7 @@ #define TIMERUS_USEC_CFG_0 MAKE_REG32(0x60005014) static inline void timer_wait(uint32_t microseconds) { - uint32_t old_time = TIMERUS_CNTR_1US_0; + const uint32_t old_time = TIMERUS_CNTR_1US_0; while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { /* Spin-lock. */ } From a4ce50ffd52173d2f521d410e67f0a1b4e940098 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 16:18:27 -0800 Subject: [PATCH 323/489] warmboot: add through dpd disable --- exosphere/lp0fw/src/car.h | 4 +++- exosphere/lp0fw/src/cluster.c | 11 +++++++++++ exosphere/lp0fw/src/cluster.h | 6 ++++++ exosphere/lp0fw/src/pmc.h | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h index bc08731d7..9174b4598 100644 --- a/exosphere/lp0fw/src/car.h +++ b/exosphere/lp0fw/src/car.h @@ -25,7 +25,7 @@ #define CLK_RST_CONTROLLER_MISC_CLK_ENB_0 MAKE_CAR_REG(0x048) #define CLK_RST_CONTROLLER_OSC_CTRL_0 MAKE_CAR_REG(0x050) -#define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) +#define CLK_RST_CONTROLLER_PLLX_BASE_0 MAKE_CAR_REG(0x0E0) #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET_0 MAKE_CAR_REG(0x450) #define CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 MAKE_CAR_REG(0x454) @@ -42,6 +42,8 @@ #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 MAKE_CAR_REG(0x554) +#define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) + #define CLK_RST_CONTROLLER_SPARE_REG0_0 MAKE_CAR_REG(0x55C) #define CLK_RST_CONTROLLER_RST_DEV_U_SET_0 MAKE_CAR_REG(0x310) diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c index daa5c6d84..26b1bda0b 100644 --- a/exosphere/lp0fw/src/cluster.c +++ b/exosphere/lp0fw/src/cluster.c @@ -50,6 +50,17 @@ void cluster_initialize_cpu(void) { timer_wait(2); CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 = 0x8; + /* Set MSELECT WRAP_TO_SLAVE_INCR[0-2], clear ERR_RESP_EN_SLAVE[1-2]. */ + MSELECT_CONFIG_0 = (MSELECT_CONFIG_0 & 0xFCFFFFFF) | 0x38000000; + + /* Clear PLLX_ENABLE. */ + CLK_RST_CONTROLLER_PLLX_BASE_0 &= 0xBFFFFFFF; + + /* Clear PMC scratch 190, disable PMC DPD then wait 10 us. */ + APBDEV_PMC_SCRATCH190_0 &= 0xFFFFFFFE; + APBDEV_PMC_DPD_SAMPLE_0 = 0; + timer_wait(10); + /* TODO: This function is enormous */ } diff --git a/exosphere/lp0fw/src/cluster.h b/exosphere/lp0fw/src/cluster.h index 0551deb3f..5daf26f09 100644 --- a/exosphere/lp0fw/src/cluster.h +++ b/exosphere/lp0fw/src/cluster.h @@ -18,6 +18,12 @@ #ifndef EXOSPHERE_WARMBOOT_BIN_CLUSTER_H #define EXOSPHERE_WARMBOOT_BIN_CLUSTER_H +#include <stdint.h> + +#include "utils.h" + +#define MSELECT_CONFIG_0 MAKE_REG32(0x50060000) + void cluster_initialize_cpu(void); void cluster_power_on_cpu(void); diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h index 17a821903..08cd1f3b8 100644 --- a/exosphere/lp0fw/src/pmc.h +++ b/exosphere/lp0fw/src/pmc.h @@ -36,6 +36,7 @@ #define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080) #define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084) #define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098) +#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) #define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4) From b419c0df290a99d3ee65fedb18f7b059ff2f39bd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 16:34:41 -0800 Subject: [PATCH 324/489] warmboot: more code, through power on i2c5 --- exosphere/lp0fw/src/car.h | 5 +++++ exosphere/lp0fw/src/cluster.c | 23 +++++++++++++++++++++++ exosphere/lp0fw/src/misc.h | 4 ++++ 3 files changed, 32 insertions(+) diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h index 9174b4598..31b73ef80 100644 --- a/exosphere/lp0fw/src/car.h +++ b/exosphere/lp0fw/src/car.h @@ -33,6 +33,9 @@ #define CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER_0 MAKE_CAR_REG(0x36C) #define CLK_RST_CONTROLLER_SUPER_CCLKP_DIVIDER_0 MAKE_CAR_REG(0x374) +#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF_0 MAKE_CAR_REG(0x62C) +#define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC_0 MAKE_CAR_REG(0x630) + #define CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2_0 MAKE_CAR_REG(0x388) #define CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT_0 MAKE_CAR_REG(0x3B4) @@ -46,11 +49,13 @@ #define CLK_RST_CONTROLLER_SPARE_REG0_0 MAKE_CAR_REG(0x55C) +#define CLK_RST_CONTROLLER_RST_DEV_H_SET_0 MAKE_CAR_REG(0x308) #define CLK_RST_CONTROLLER_RST_DEV_U_SET_0 MAKE_CAR_REG(0x310) #define CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 MAKE_CAR_REG(0x314) #define CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 MAKE_CAR_REG(0x434) +#define CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 MAKE_CAR_REG(0x328) #define CLK_RST_CONTROLLER_CLK_ENB_U_SET_0 MAKE_CAR_REG(0x330) #define CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 MAKE_CAR_REG(0x440) #define CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 MAKE_CAR_REG(0x448) diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c index 26b1bda0b..4fd6ea039 100644 --- a/exosphere/lp0fw/src/cluster.c +++ b/exosphere/lp0fw/src/cluster.c @@ -61,6 +61,29 @@ void cluster_initialize_cpu(void) { APBDEV_PMC_DPD_SAMPLE_0 = 0; timer_wait(10); + /* Configure UART2 via GPIO controller 2 G. */ + MAKE_REG32(0x6000D108) |= 4; /* GPIO_CNF */ + MAKE_REG32(0x6000D118) |= 4; /* GPIO_OE */ + MAKE_REG32(0x6000D128) &= ~4; /* GPIO_OUT */ + + /* Set CL_DVFS RSVD0 + TRISTATE, read register to make it stick. */ + PINMUX_AUX_DVFS_PWM_0 = 0x11; + (void)PINMUX_AUX_DVFS_PWM_0; + + /* Configure I2C. */ + PINMUX_AUX_PWR_I2C_SCL_0 = 0x40; + PINMUX_AUX_PWR_I2C_SDA_0 = 0x40; + + /* Enable clock to CL_DVFS, and set its source/divider. */ + CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 = 0x08000000; + CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF_0 = 0xE; + CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC_0 = 0xE; + + /* Power on I2C5, wait 5 us. */ + CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 = 0x8000; + CLK_RST_CONTROLLER_RST_DEV_H_SET_0 = 0x8000; + timer_wait(5); + /* TODO: This function is enormous */ } diff --git a/exosphere/lp0fw/src/misc.h b/exosphere/lp0fw/src/misc.h index a4f7c2b66..6fe93d520 100644 --- a/exosphere/lp0fw/src/misc.h +++ b/exosphere/lp0fw/src/misc.h @@ -29,6 +29,10 @@ #define APB_MISC_GP_ASDBGREG_0 MAKE_MISC_REG(0x810) +#define PINMUX_AUX_PWR_I2C_SCL_0 MAKE_MISC_REG(0x30DC) +#define PINMUX_AUX_PWR_I2C_SDA_0 MAKE_MISC_REG(0x30E0) +#define PINMUX_AUX_DVFS_PWM_0 MAKE_MISC_REG(0x3184) + #define PINMUX_AUX_GPIO_PA6_0 MAKE_MISC_REG(0x3244) void misc_configure_device_dbg_settings(void); From 754aaecc18eb93fdee4b9c09a47d15607398abdd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 16:48:14 -0800 Subject: [PATCH 325/489] warmboot: add i2c code to enable PMIC --- exosphere/lp0fw/src/car.h | 3 ++ exosphere/lp0fw/src/cluster.c | 9 ++++- exosphere/lp0fw/src/i2c.c | 76 +++++++++++++++++++++++++++++++++++ exosphere/lp0fw/src/i2c.h | 48 ++++++++++++++++++++++ 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 exosphere/lp0fw/src/i2c.c create mode 100644 exosphere/lp0fw/src/i2c.h diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h index 31b73ef80..6716ef219 100644 --- a/exosphere/lp0fw/src/car.h +++ b/exosphere/lp0fw/src/car.h @@ -33,6 +33,8 @@ #define CLK_RST_CONTROLLER_SUPER_CCLKG_DIVIDER_0 MAKE_CAR_REG(0x36C) #define CLK_RST_CONTROLLER_SUPER_CCLKP_DIVIDER_0 MAKE_CAR_REG(0x374) +#define CLK_RST_CONTROLLER_CLK_SOURCE_I2C5_0 MAKE_CAR_REG(0x128) + #define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF_0 MAKE_CAR_REG(0x62C) #define CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC_0 MAKE_CAR_REG(0x630) @@ -52,6 +54,7 @@ #define CLK_RST_CONTROLLER_RST_DEV_H_SET_0 MAKE_CAR_REG(0x308) #define CLK_RST_CONTROLLER_RST_DEV_U_SET_0 MAKE_CAR_REG(0x310) +#define CLK_RST_CONTROLLER_RST_DEV_H_CLR_0 MAKE_CAR_REG(0x30C) #define CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 MAKE_CAR_REG(0x314) #define CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 MAKE_CAR_REG(0x434) diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c index 4fd6ea039..05cacf2ea 100644 --- a/exosphere/lp0fw/src/cluster.c +++ b/exosphere/lp0fw/src/cluster.c @@ -21,6 +21,8 @@ #include "car.h" #include "timer.h" #include "pmc.h" +#include "misc.h" +#include "i2c.h" #include "sysreg.h" void cluster_initialize_cpu(void) { @@ -79,10 +81,15 @@ void cluster_initialize_cpu(void) { CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_REF_0 = 0xE; CLK_RST_CONTROLLER_CLK_SOURCE_DVFS_SOC_0 = 0xE; - /* Power on I2C5, wait 5 us. */ + /* Power on I2C5, wait 5 us, set source + take out of reset. */ CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 = 0x8000; CLK_RST_CONTROLLER_RST_DEV_H_SET_0 = 0x8000; timer_wait(5); + CLK_RST_CONTROLLER_CLK_SOURCE_I2C5_0 = 0x4; + CLK_RST_CONTROLLER_RST_DEV_H_CLR_0 = 0x8000; + + /* Enable the PMIC. */ + i2c_enable_pmic(); /* TODO: This function is enormous */ } diff --git a/exosphere/lp0fw/src/i2c.c b/exosphere/lp0fw/src/i2c.c new file mode 100644 index 000000000..68382b0c2 --- /dev/null +++ b/exosphere/lp0fw/src/i2c.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "i2c.h" +#include "timer.h" + +/* Prototypes for internal commands. */ +void i2c_set_test_master_config_load(void); +void i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes); +void i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b); + +/* Load hardware config for I2C5. */ +void i2c_set_test_master_config_load(void) { + /* Set MSTR_CONFIG_LOAD. */ + I2C_I2C_CONFIG_LOAD_0 = 0x1; + + while (!(I2C_I2C_CONFIG_LOAD_0 & 1)) { + /* Wait forever until it's set. */ + } +} + +/* Writes a value to an i2c device. */ +void i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) { + if (num_bytes > 4) { + return; + } + + /* Set device for 7-bit mode. */ + I2C_I2C_CMD_ADDR0_0 = device << 1; + + /* Load in data to write. */ + I2C_I2C_CMD_DATA1_0 = val; + + /* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800; + + i2c_set_test_master_config_load(); + + /* Config |= SEND; */ + I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800 | 0x200; + + + while (I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + while (I2C_I2C_STATUS_0 & 0xF) { + /* Wait until write successful. */ + } +} + +/* Writes a byte val to reg for given device. */ +void i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) { + uint32_t val = (reg) | (b << 8); + /* Write 1 byte (reg) + 1 byte (value) */ + i2c_write(device, val, 2); +} + +/* Enable the PMIC. */ +void i2c_enable_pmic(void) { + /* Write 00 to Device 27 Reg 00. */ + i2c_send_byte_command(27, 0, 0x80); +} diff --git a/exosphere/lp0fw/src/i2c.h b/exosphere/lp0fw/src/i2c.h new file mode 100644 index 000000000..90c05215b --- /dev/null +++ b/exosphere/lp0fw/src/i2c.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_I2C_H +#define EXOSPHERE_WARMBOOT_BIN_I2C_H + +#include "utils.h" + +/* I2C_BASE = I2C5. */ +#define I2C_BASE (0x7000D000) + +#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs)) + +#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000) + +#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004) + +#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C) + +#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C) + +#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068) + +#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C) + +#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084) + +#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088) + + +#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C) + +void i2c_enable_pmic(void); + +#endif From 72594c6783027fff5698161190d7651856f5d27e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 17:03:39 -0800 Subject: [PATCH 326/489] warmboot: add crail power on code --- exosphere/lp0fw/src/car.h | 3 +++ exosphere/lp0fw/src/cluster.c | 40 ++++++++++++++++++++++++++++++++++- exosphere/lp0fw/src/pmc.h | 6 ++++-- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h index 6716ef219..5cc0b5d90 100644 --- a/exosphere/lp0fw/src/car.h +++ b/exosphere/lp0fw/src/car.h @@ -63,6 +63,9 @@ #define CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 MAKE_CAR_REG(0x440) #define CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 MAKE_CAR_REG(0x448) +#define CLK_RST_CONTROLLER_CLK_ENB_H_CLR_0 MAKE_CAR_REG(0x32C) +#define CLK_RST_CONTROLLER_CLK_ENB_W_CLR_0 MAKE_CAR_REG(0x44C) + #define NUM_CAR_BANKS 7 typedef enum { diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c index 05cacf2ea..0ffd20940 100644 --- a/exosphere/lp0fw/src/cluster.c +++ b/exosphere/lp0fw/src/cluster.c @@ -25,6 +25,20 @@ #include "i2c.h" #include "sysreg.h" +static void cluster_pmc_enable_partition(uint32_t mask, uint32_t toggle) { + /* Set toggle if unset. */ + if (!(APBDEV_PMC_PWRGATE_STATUS_0 & mask)) { + APBDEV_PMC_PWRGATE_TOGGLE_0 = toggle; + } + + /* Wait until toggle set. */ + while (!(APBDEV_PMC_PWRGATE_STATUS_0 & mask)) { } + + /* Remove clamping. */ + APBDEV_PMC_REMOVE_CLAMPING_CMD_0 = mask; + while (!(APBDEV_PMC_CLAMP_STATUS_0 & mask)) { } +} + void cluster_initialize_cpu(void) { /* Hold CoreSight in reset. */ CLK_RST_CONTROLLER_RST_DEV_U_SET_0 = 0x200; @@ -88,8 +102,32 @@ void cluster_initialize_cpu(void) { CLK_RST_CONTROLLER_CLK_SOURCE_I2C5_0 = 0x4; CLK_RST_CONTROLLER_RST_DEV_H_CLR_0 = 0x8000; - /* Enable the PMIC. */ + /* Enable the PMIC, wait 2ms. */ i2c_enable_pmic(); + timer_wait(2000); + + /* Enable power to the CRAIL partition. */ + cluster_pmc_enable_partition(1, 0x100); + + /* Remove SW clamp to CRAIL. */ + APBDEV_PMC_SET_SW_CLAMP_0 = 0; + APBDEV_PMC_REMOVE_CLAMPING_CMD_0 = 1; + while (!(APBDEV_PMC_CLAMP_STATUS_0 & 1)) { } + + /* Nintendo manually counts down from 8. I am not sure why this happens. */ + { + volatile int32_t counter = 8; + while (counter >= 0) { + counter--; + } + } + + /* Power off I2C5. */ + CLK_RST_CONTROLLER_RST_DEV_H_SET_0 = 0x8000; + CLK_RST_CONTROLLER_CLK_ENB_H_CLR_0 = 0x8000; + + /* Disable clock to CL_DVFS */ + CLK_RST_CONTROLLER_CLK_ENB_W_CLR_0 = 0x08000000; /* TODO: This function is enormous */ } diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h index 08cd1f3b8..d4528e80c 100644 --- a/exosphere/lp0fw/src/pmc.h +++ b/exosphere/lp0fw/src/pmc.h @@ -31,12 +31,14 @@ #define APBDEV_PMC_CLAMP_STATUS_0 MAKE_PMC_REG(0x02C) -#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038) +#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x030) +#define APBDEV_PMC_REMOVE_CLAMPING_CMD_0 MAKE_PMC_REG(0x034) +#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x038) #define APBDEV_PMC_SCRATCH12_0 MAKE_PMC_REG(0x080) #define APBDEV_PMC_SCRATCH13_0 MAKE_PMC_REG(0x084) #define APBDEV_PMC_SCRATCH18_0 MAKE_PMC_REG(0x098) -#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) +#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) #define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4) From 7a704827f1db2163695460e7abffa95a7cabc320 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 17:13:24 -0800 Subject: [PATCH 327/489] warmboot: add flow_perform_ram_repair --- exosphere/lp0fw/src/cluster.c | 4 ++++ exosphere/lp0fw/src/flow.c | 31 +++++++++++++++++++++++++++++++ exosphere/lp0fw/src/flow.h | 6 +++++- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 exosphere/lp0fw/src/flow.c diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c index 0ffd20940..f29239502 100644 --- a/exosphere/lp0fw/src/cluster.c +++ b/exosphere/lp0fw/src/cluster.c @@ -23,6 +23,7 @@ #include "pmc.h" #include "misc.h" #include "i2c.h" +#include "flow.h" #include "sysreg.h" static void cluster_pmc_enable_partition(uint32_t mask, uint32_t toggle) { @@ -129,6 +130,9 @@ void cluster_initialize_cpu(void) { /* Disable clock to CL_DVFS */ CLK_RST_CONTROLLER_CLK_ENB_W_CLR_0 = 0x08000000; + /* Perform RAM repair if necessary. */ + flow_perform_ram_repair(); + /* TODO: This function is enormous */ } diff --git a/exosphere/lp0fw/src/flow.c b/exosphere/lp0fw/src/flow.c new file mode 100644 index 000000000..9fa847936 --- /dev/null +++ b/exosphere/lp0fw/src/flow.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "utils.h" +#include "flow.h" + +void flow_perform_ram_repair(void) { + /* Perform repair only if not active cluster. */ + if (!(FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 & 1)) { + /* Set REQ, to begin RAM repair. */ + FLOW_CTLR_RAM_REPAIR_0 = 1; + + /* Wait for STS to say RAM repair has completed. */ + while (!(FLOW_CTLR_RAM_REPAIR_0 & 2)) { } + } +} \ No newline at end of file diff --git a/exosphere/lp0fw/src/flow.h b/exosphere/lp0fw/src/flow.h index 559c79716..e0bd86ccd 100644 --- a/exosphere/lp0fw/src/flow.h +++ b/exosphere/lp0fw/src/flow.h @@ -26,6 +26,10 @@ #define MAKE_FLOW_REG(ofs) MAKE_REG32(FLOW_BASE + ofs) -#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) +#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) +#define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040) +#define FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 MAKE_FLOW_REG(0x098) + +void flow_perform_ram_repair(void); #endif From f6bc4abfd0950ea116fcdc5603d32fddf4f0e946 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 17:17:19 -0800 Subject: [PATCH 328/489] warmboot: implement cluster_power_on_cpu --- exosphere/lp0fw/src/cluster.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c index f29239502..a3040216b 100644 --- a/exosphere/lp0fw/src/cluster.c +++ b/exosphere/lp0fw/src/cluster.c @@ -133,9 +133,16 @@ void cluster_initialize_cpu(void) { /* Perform RAM repair if necessary. */ flow_perform_ram_repair(); - /* TODO: This function is enormous */ + /* Enable power to the C0NC partition. */ + cluster_pmc_enable_partition(0x8000, 0x10F); + + /* TODO: other shit */ } void cluster_power_on_cpu(void) { - /* TODO */ + /* Enable power to CE0 partition. */ + cluster_pmc_enable_partition(0x4000, 0x10E); + + /* Clear CPU reset. */ + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = 0x10001; } \ No newline at end of file From 4f9ecc9d508e0197e555a839937fefe759138573 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 17 Dec 2018 17:32:44 -0800 Subject: [PATCH 329/489] warmboot: finish cluster_initialize_cpu --- exosphere/lp0fw/src/car.h | 5 +++++ exosphere/lp0fw/src/cluster.c | 19 +++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/exosphere/lp0fw/src/car.h b/exosphere/lp0fw/src/car.h index 5cc0b5d90..c762f434f 100644 --- a/exosphere/lp0fw/src/car.h +++ b/exosphere/lp0fw/src/car.h @@ -47,6 +47,9 @@ #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD_0 MAKE_CAR_REG(0x3A4) #define CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE_0 MAKE_CAR_REG(0x554) +#define CLK_RST_CONTROLLER_CCLKG_BURST_POLICY_0 MAKE_CAR_REG(0x368) +#define CLK_RST_CONTROLLER_CCLKP_BURST_POLICY_0 MAKE_CAR_REG(0x370) + #define CLK_RST_CONTROLLER_RST_DEVICES_H_0 MAKE_CAR_REG(0x008) #define CLK_RST_CONTROLLER_SPARE_REG0_0 MAKE_CAR_REG(0x55C) @@ -58,10 +61,12 @@ #define CLK_RST_CONTROLLER_RST_DEV_U_CLR_0 MAKE_CAR_REG(0x314) #define CLK_RST_CONTROLLER_RST_DEV_V_CLR_0 MAKE_CAR_REG(0x434) +#define CLK_RST_CONTROLLER_CLK_ENB_L_SET_0 MAKE_CAR_REG(0x320) #define CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 MAKE_CAR_REG(0x328) #define CLK_RST_CONTROLLER_CLK_ENB_U_SET_0 MAKE_CAR_REG(0x330) #define CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 MAKE_CAR_REG(0x440) #define CLK_RST_CONTROLLER_CLK_ENB_W_SET_0 MAKE_CAR_REG(0x448) +#define CLK_RST_CONTROLLER_CLK_ENB_Y_SET_0 MAKE_CAR_REG(0x29C) #define CLK_RST_CONTROLLER_CLK_ENB_H_CLR_0 MAKE_CAR_REG(0x32C) #define CLK_RST_CONTROLLER_CLK_ENB_W_CLR_0 MAKE_CAR_REG(0x44C) diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c index a3040216b..d05de9082 100644 --- a/exosphere/lp0fw/src/cluster.c +++ b/exosphere/lp0fw/src/cluster.c @@ -133,10 +133,25 @@ void cluster_initialize_cpu(void) { /* Perform RAM repair if necessary. */ flow_perform_ram_repair(); - /* Enable power to the C0NC partition. */ + /* Enable power to the non-CPU partition. */ cluster_pmc_enable_partition(0x8000, 0x10F); - /* TODO: other shit */ + /* Enable clock to PLLP_OUT_CPU, wait 2 us. */ + CLK_RST_CONTROLLER_CLK_ENB_Y_SET_0 = 0x80000000; + timer_wait(2); + + /* Enable clock to CPU, CPUG, wait 10 us. */ + CLK_RST_CONTROLLER_CLK_ENB_L_SET_0 = 1; + CLK_RST_CONTROLLER_CLK_ENB_V_SET_0 = 1; + timer_wait(10); + + /* Set CPU clock sources to PLLP_OUT_0 + state to RUN, wait 10 us. */ + CLK_RST_CONTROLLER_CCLKG_BURST_POLICY_0 = 0x20004444; + CLK_RST_CONTROLLER_CCLKP_BURST_POLICY_0 = 0x20004444; + timer_wait(10); + + /* Take non-CPU out of reset (write CLR_NONCPURESET). */ + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR_0 = 0x20000000; } void cluster_power_on_cpu(void) { From 3924a2ef76ad06be19e0b3702301e9a07d833ec7 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 18 Dec 2018 15:31:34 -0800 Subject: [PATCH 330/489] warmboot: start secmon_restore_to_tzram --- exosphere/lp0fw/src/lp0.c | 5 +- exosphere/lp0fw/src/se.c | 238 +++++++++++++++++++++++++++++++++++ exosphere/lp0fw/src/se.h | 187 +++++++++++++++++++++++++++ exosphere/lp0fw/src/secmon.c | 67 ++++++++++ exosphere/lp0fw/src/secmon.h | 26 ++++ 5 files changed, 520 insertions(+), 3 deletions(-) create mode 100644 exosphere/lp0fw/src/se.c create mode 100644 exosphere/lp0fw/src/se.h create mode 100644 exosphere/lp0fw/src/secmon.c create mode 100644 exosphere/lp0fw/src/secmon.h diff --git a/exosphere/lp0fw/src/lp0.c b/exosphere/lp0fw/src/lp0.c index 565af3b79..5aaf46987 100644 --- a/exosphere/lp0fw/src/lp0.c +++ b/exosphere/lp0fw/src/lp0.c @@ -25,6 +25,7 @@ #include "cluster.h" #include "flow.h" #include "timer.h" +#include "secmon.h" void reboot(void) { /* Write MAIN_RST */ @@ -81,7 +82,7 @@ void lp0_entry_main(warmboot_metadata_t *meta) { /* Initialize the CPU cluster. */ cluster_initialize_cpu(); - /* TODO: decrypt_restore_secmon_to_tzram(); */ + secmon_restore_to_tzram(target_firmware); /* Power on the CPU cluster. */ cluster_power_on_cpu(); @@ -95,5 +96,3 @@ void lp0_entry_main(warmboot_metadata_t *meta) { FLOW_CTLR_HALT_COP_EVENTS_0 = halt_val; } } - - diff --git a/exosphere/lp0fw/src/se.c b/exosphere/lp0fw/src/se.c new file mode 100644 index 000000000..cb4f1ab98 --- /dev/null +++ b/exosphere/lp0fw/src/se.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> + +#include "utils.h" +#include "lp0.h" +#include "se.h" + +static void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size); + +/* Initialize a SE linked list. */ +static void __attribute__((__noinline__)) ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { + ll->num_entries = 0; /* 1 Entry. */ + + if (buffer != NULL) { + ll->addr_info.address = (uint32_t) buffer; + ll->addr_info.size = (uint32_t) size; + } else { + ll->addr_info.address = 0; + ll->addr_info.size = 0; + } +} + +void se_check_error_status_reg(void) { + if (se_get_regs()->ERR_STATUS_REG) { + reboot(); + } +} + +void se_check_for_error(void) { + volatile tegra_se_t *se = se_get_regs(); + if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) { + reboot(); + } +} + +void se_verify_flags_cleared(void) { + if (se_get_regs()->FLAGS_REG & 3) { + reboot(); + } +} + +void clear_aes_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + reboot(); + } + + /* Zero out the whole keyslot and IV. */ + for (unsigned int i = 0; i < 0x10; i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = 0; + } +} + +void clear_rsa_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_RSA_MAX) { + reboot(); + } + + /* Zero out the whole keyslot. */ + for (unsigned int i = 0; i < 0x40; i++) { + /* Select Keyslot Modulus[i] */ + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; + se->RSA_KEYTABLE_DATA = 0; + } + for (unsigned int i = 0; i < 0x40; i++) { + /* Select Keyslot Expontent[i] */ + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = 0; + } +} + +void clear_aes_keyslot_iv(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + reboot(); + } + + for (size_t i = 0; i < (0x10 >> 2); i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = 0; + } +} + + +void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + se_ll_t in_ll; + se_ll_t out_ll; + + ll_init(&in_ll, (void *)src, src_size); + ll_init(&out_ll, dst, dst_size); + + /* Set the LLs. */ + se->IN_LL_ADDR_REG = (uint32_t)(&in_ll); + se->OUT_LL_ADDR_REG = (uint32_t) (&out_ll); + + /* Set registers for operation. */ + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = op; + + while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ } + se_check_for_error(); +} + +/* Secure AES Functionality. */ +void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { + uint8_t block[0x10] = {0}; + + if (src_size > sizeof(block) || dst_size > sizeof(block)) { + reboot(); + } + + /* Load src data into block. */ + if (src_size != 0) { + memcpy(block, src, src_size); + } + + /* Trigger AES operation. */ + se_get_regs()->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); + + /* Copy output data into dst. */ + if (dst_size != 0) { + memcpy(dst, block, dst_size); + } +} + +void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { + reboot(); + } + + /* Set configuration high (256-bit vs 128-bit) based on parameter. */ + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); + se->CRYPTO_REG = keyslot << 24 | 0x100; + se_perform_aes_block_operation(dst, 0x10, src, 0x10); +} + +void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { + reboot(); + } + + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot << 24; + se_perform_aes_block_operation(dst, 0x10, src, 0x10); +} + +void shift_left_xor_rb(uint8_t *key) { + uint8_t prev_high_bit = 0; + for (unsigned int i = 0; i < 0x10; i++) { + uint8_t cur_byte = key[0xF - i]; + key[0xF - i] = (cur_byte << 1) | (prev_high_bit); + prev_high_bit = cur_byte >> 7; + } + if (prev_high_bit) { + key[0xF] ^= 0x87; + } +} + +void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + reboot(); + } + + /* Generate the derived key, to be XOR'd with final output block. */ + uint8_t ALIGN(16) derived_key[0x10] = {0}; + se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high); + shift_left_xor_rb(derived_key); + if (data_size & 0xF) { + shift_left_xor_rb(derived_key); + } + + se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); + se->CRYPTO_REG = (keyslot << 24) | (0x145); + clear_aes_keyslot_iv(keyslot); + + unsigned int num_blocks = (data_size + 0xF) >> 4; + /* Handle aligned blocks. */ + if (num_blocks > 1) { + se->BLOCK_COUNT_REG = num_blocks - 2; + trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); + se->CRYPTO_REG |= 0x80; + } + + /* Create final block. */ + uint8_t ALIGN(16) last_block[0x10] = {0}; + if (data_size & 0xF) { + memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF); + last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */ + } else if (data_size >= 0x10) { + memcpy(last_block, data + data_size - 0x10, 0x10); + } + + for (unsigned int i = 0; i < 0x10; i++) { + last_block[i] ^= derived_key[i]; + } + + /* Perform last operation. */ + se->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); + + /* Copy output CMAC. */ + for (unsigned int i = 0; i < (cmac_size >> 2); i++) { + ((uint32_t *)cmac)[i] = ((volatile uint32_t *)se->HASH_RESULT_REG)[i]; + } +} + +void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { + se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202); +} diff --git a/exosphere/lp0fw/src/se.h b/exosphere/lp0fw/src/se.h new file mode 100644 index 000000000..b3e79f6e5 --- /dev/null +++ b/exosphere/lp0fw/src/se.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_SE_H +#define EXOSPHERE_WARMBOOT_BIN_SE_H + +#define SE_BASE 0x70012000 +#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n) + +#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2 +#define KEYSLOT_SWITCH_SRKGENKEY 0x8 +#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8 +#define KEYSLOT_SWITCH_TEMPKEY 0x9 +#define KEYSLOT_SWITCH_SESSIONKEY 0xA +#define KEYSLOT_SWITCH_RNGKEY 0xB +#define KEYSLOT_SWITCH_MASTERKEY 0xC +#define KEYSLOT_SWITCH_DEVICEKEY 0xD + +/* This keyslot was added in 4.0.0. */ +#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD +#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE +#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF + +/* This keyslot was added in 5.0.0. */ +#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA + +#define KEYSLOT_AES_MAX 0x10 +#define KEYSLOT_RSA_MAX 0x2 + +#define KEYSIZE_AES_MAX 0x20 +#define KEYSIZE_RSA_MAX 0x100 + +#define ALG_SHIFT (12) +#define ALG_DEC_SHIFT (8) +#define ALG_NOP (0 << ALG_SHIFT) +#define ALG_AES_ENC (1 << ALG_SHIFT) +#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP) +#define ALG_RNG (2 << ALG_SHIFT) +#define ALG_SHA (3 << ALG_SHIFT) +#define ALG_RSA (4 << ALG_SHIFT) + +#define DST_SHIFT (2) +#define DST_MEMORY (0 << DST_SHIFT) +#define DST_HASHREG (1 << DST_SHIFT) +#define DST_KEYTAB (2 << DST_SHIFT) +#define DST_SRK (3 << DST_SHIFT) +#define DST_RSAREG (4 << DST_SHIFT) + +#define ENCMODE_SHIFT (24) +#define DECMODE_SHIFT (16) +#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT) + +#define HASH_DISABLE (0x0) +#define HASH_ENABLE (0x1) + +#define OP_ABORT 0 +#define OP_START 1 +#define OP_RESTART 2 +#define OP_CTX_SAVE 3 +#define OP_RESTART_IN 4 + +#define CTX_SAVE_SRC_SHIFT 29 +#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT) + +#define CTX_SAVE_KEY_LOW_BITS 0 +#define CTX_SAVE_KEY_HIGH_BITS 1 +#define CTX_SAVE_KEY_ORIGINAL_IV 2 +#define CTX_SAVE_KEY_UPDATED_IV 3 + +#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24 +#define CTX_SAVE_KEY_INDEX_SHIFT 8 +#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16 +#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12 + +#define RSA_2048_BYTES 0x100 + +typedef struct { + uint32_t _0x0; + uint32_t _0x4; + uint32_t OPERATION_REG; + uint32_t INT_ENABLE_REG; + uint32_t INT_STATUS_REG; + uint32_t CONFIG_REG; + uint32_t IN_LL_ADDR_REG; + uint32_t _0x1C; + uint32_t _0x20; + uint32_t OUT_LL_ADDR_REG; + uint32_t _0x28; + uint32_t _0x2C; + uint8_t HASH_RESULT_REG[0x20]; + uint8_t _0x50[0x20]; + uint32_t CONTEXT_SAVE_CONFIG_REG; + uint8_t _0x74[0x18C]; + uint32_t SHA_CONFIG_REG; + uint32_t SHA_MSG_LENGTH_REG; + uint32_t _0x208; + uint32_t _0x20C; + uint32_t _0x210; + uint32_t SHA_MSG_LEFT_REG; + uint32_t _0x218; + uint32_t _0x21C; + uint32_t _0x220; + uint32_t _0x224; + uint8_t _0x228[0x58]; + uint32_t AES_KEY_READ_DISABLE_REG; + uint32_t AES_KEYSLOT_FLAGS[0x10]; + uint8_t _0x2C4[0x3C]; + uint32_t _0x300; + uint32_t CRYPTO_REG; + uint32_t CRYPTO_CTR_REG[4]; + uint32_t BLOCK_COUNT_REG; + uint32_t AES_KEYTABLE_ADDR; + uint32_t AES_KEYTABLE_DATA; + uint32_t _0x324; + uint32_t _0x328; + uint32_t _0x32C; + uint32_t CRYPTO_KEYTABLE_DST_REG; + uint8_t _0x334[0xC]; + uint32_t RNG_CONFIG_REG; + uint32_t RNG_SRC_CONFIG_REG; + uint32_t RNG_RESEED_INTERVAL_REG; + uint8_t _0x34C[0xB4]; + uint32_t RSA_CONFIG; + uint32_t RSA_KEY_SIZE_REG; + uint32_t RSA_EXP_SIZE_REG; + uint32_t RSA_KEY_READ_DISABLE_REG; + uint32_t RSA_KEYSLOT_FLAGS[2]; + uint32_t _0x418; + uint32_t _0x41C; + uint32_t RSA_KEYTABLE_ADDR; + uint32_t RSA_KEYTABLE_DATA; + uint8_t RSA_OUTPUT[0x100]; + uint8_t _0x528[0x2D8]; + uint32_t FLAGS_REG; + uint32_t ERR_STATUS_REG; + uint32_t _0x808; + uint32_t SPARE_0; + uint32_t _0x810; + uint32_t _0x814; + uint32_t _0x818; + uint32_t _0x81C; + uint8_t _0x820[0x17E0]; +} tegra_se_t; + +typedef struct { + uint32_t address; + uint32_t size; +} se_addr_info_t; + +typedef struct { + uint32_t num_entries; /* Set to total entries - 1 */ + se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ +} se_ll_t; + +static inline volatile tegra_se_t *se_get_regs(void) { + return (volatile tegra_se_t *)SE_BASE; +} + +void se_check_error_status_reg(void); +void se_check_for_error(void); + +void se_verify_flags_cleared(void); + +void clear_aes_keyslot(unsigned int keyslot); +void clear_rsa_keyslot(unsigned int keyslot); +void clear_aes_keyslot_iv(unsigned int keyslot); + +void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); + +#endif diff --git a/exosphere/lp0fw/src/secmon.c b/exosphere/lp0fw/src/secmon.c new file mode 100644 index 000000000..1fe3ea78a --- /dev/null +++ b/exosphere/lp0fw/src/secmon.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "utils.h" +#include "lp0.h" +#include "secmon.h" +#include "se.h" +#include "pmc.h" + +/* "private" functions. */ +static bool secmon_should_clear_aes_keyslot(unsigned int keyslot); +static void secmon_clear_unused_keyslots(void); + +void secmon_restore_to_tzram(const uint32_t target_firmware) { + /* Newer warmboot binaries clear the untouched keyslots for safety. */ + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500) { + secmon_clear_unused_keyslots(); + } + + /* TODO: stuff */ +} + +bool secmon_should_clear_aes_keyslot(unsigned int keyslot) { + static const uint8_t saved_keyslots[6] = { + KEYSLOT_SWITCH_LP0TZRAMKEY, + KEYSLOT_SWITCH_SESSIONKEY, + KEYSLOT_SWITCH_RNGKEY, + KEYSLOT_SWITCH_MASTERKEY, + KEYSLOT_SWITCH_DEVICEKEY, + KEYSLOT_SWITCH_4XOLDDEVICEKEY + }; + + for (unsigned int i = 0; i < sizeof(saved_keyslots)/sizeof(saved_keyslots[0]); i++) { + if (keyslot == saved_keyslots[i]) { + return false; + } + } + return true; +} + +void secmon_clear_unused_keyslots(void) { + /* Clear unused keyslots. */ + for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { + if (secmon_should_clear_aes_keyslot(i)) { + clear_aes_keyslot(i); + } + clear_aes_keyslot_iv(i); + } + for (unsigned int i = 0; i < KEYSLOT_RSA_MAX; i++) { + clear_rsa_keyslot(i); + } +} \ No newline at end of file diff --git a/exosphere/lp0fw/src/secmon.h b/exosphere/lp0fw/src/secmon.h new file mode 100644 index 000000000..71daac914 --- /dev/null +++ b/exosphere/lp0fw/src/secmon.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_WARMBOOT_BIN_SECMON_H +#define EXOSPHERE_WARMBOOT_BIN_SECMON_H + +#include <stdint.h> + +#include "utils.h" + +void secmon_restore_to_tzram(const uint32_t target_firmware); + +#endif From 95a9e1e215832b36d398993a60dbc07f86f8bc4b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 18 Dec 2018 15:55:16 -0800 Subject: [PATCH 331/489] warmboot: add code for decrypting/restoring tzram. --- exosphere/lp0fw/src/pmc.h | 5 ++++ exosphere/lp0fw/src/se.c | 14 ++++++++++++ exosphere/lp0fw/src/se.h | 1 + exosphere/lp0fw/src/secmon.c | 44 +++++++++++++++++++++++++++++++++++- 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h index d4528e80c..2bee565a3 100644 --- a/exosphere/lp0fw/src/pmc.h +++ b/exosphere/lp0fw/src/pmc.h @@ -51,6 +51,11 @@ #define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_PMC_REG(0x368) #define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_PMC_REG(0x36C) +#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_PMC_REG(0x718) +#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_PMC_REG(0x71C) +#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_PMC_REG(0x720) +#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_PMC_REG(0x724) + #define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C) #define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460) diff --git a/exosphere/lp0fw/src/se.c b/exosphere/lp0fw/src/se.c index cb4f1ab98..f6ae15816 100644 --- a/exosphere/lp0fw/src/se.c +++ b/exosphere/lp0fw/src/se.c @@ -236,3 +236,17 @@ void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, con void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202); } + +void se_aes_256_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { + reboot(); + } + + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY) | (0x202 << 16); + se->CRYPTO_REG = (keyslot << 24) | 0x66; + clear_aes_keyslot_iv(keyslot); + se->BLOCK_COUNT_REG = (src_size >> 4) - 1; + trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); +} \ No newline at end of file diff --git a/exosphere/lp0fw/src/se.h b/exosphere/lp0fw/src/se.h index b3e79f6e5..c9de02a99 100644 --- a/exosphere/lp0fw/src/se.h +++ b/exosphere/lp0fw/src/se.h @@ -183,5 +183,6 @@ void clear_rsa_keyslot(unsigned int keyslot); void clear_aes_keyslot_iv(unsigned int keyslot); void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); +void se_aes_256_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); #endif diff --git a/exosphere/lp0fw/src/secmon.c b/exosphere/lp0fw/src/secmon.c index 1fe3ea78a..d6ec9b1b8 100644 --- a/exosphere/lp0fw/src/secmon.c +++ b/exosphere/lp0fw/src/secmon.c @@ -25,6 +25,7 @@ /* "private" functions. */ static bool secmon_should_clear_aes_keyslot(unsigned int keyslot); static void secmon_clear_unused_keyslots(void); +static void secmon_decrypt_saved_image(void *dst, const void *src, size_t size); void secmon_restore_to_tzram(const uint32_t target_firmware) { /* Newer warmboot binaries clear the untouched keyslots for safety. */ @@ -32,10 +33,51 @@ void secmon_restore_to_tzram(const uint32_t target_firmware) { secmon_clear_unused_keyslots(); } + /* Decrypt Secure Monitor from DRAM into TZRAM. */ + void *tzram_src = (void *)(0x80010000); + void *tzram_dst = (void *)(target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_500 ? 0x7C012000 : 0x7C010000); + const size_t tzram_size = 0xE000; + secmon_decrypt_saved_image(tzram_dst, tzram_src, tzram_size); + + /* Nintendo clears DRAM, but I'm not sure why, given they lock out BPMP access to DRAM. */ + for (size_t i = 0; i < tzram_size/sizeof(uint32_t); i++) { + ((volatile uint32_t *)tzram_src)[i] = 0; + } + + /* Make security engine require secure busmaster. */ + se_get_regs()->_0x4 = 0; + /* TODO: stuff */ } +void secmon_decrypt_saved_image(void *dst, const void *src, size_t size) { + /* First, AES-256-CBC decrypt the image into TZRAM. */ + se_aes_256_cbc_decrypt(KEYSLOT_SWITCH_LP0TZRAMKEY, dst, size, src, size); + + /* Next, calculate CMAC. */ + uint32_t tzram_cmac[4] = {0, 0, 0, 0}; + se_compute_aes_256_cmac(KEYSLOT_SWITCH_LP0TZRAMKEY, tzram_cmac, sizeof(tzram_cmac), dst, size); + + /* Validate the MAC against saved one in PMC scratch. */ + if (tzram_cmac[0] != APBDEV_PMC_SECURE_SCRATCH112_0 || + tzram_cmac[1] != APBDEV_PMC_SECURE_SCRATCH113_0 || + tzram_cmac[2] != APBDEV_PMC_SECURE_SCRATCH114_0 || + tzram_cmac[3] != APBDEV_PMC_SECURE_SCRATCH115_0) { + reboot(); + } + + /* Clear the PMC scratch registers that hold the CMAC. */ + APBDEV_PMC_SECURE_SCRATCH112_0 = 0; + APBDEV_PMC_SECURE_SCRATCH113_0 = 0; + APBDEV_PMC_SECURE_SCRATCH114_0 = 0; + APBDEV_PMC_SECURE_SCRATCH115_0 = 0; + + /* Clear keyslot now that we're done with it. */ + clear_aes_keyslot(KEYSLOT_SWITCH_LP0TZRAMKEY); +} + bool secmon_should_clear_aes_keyslot(unsigned int keyslot) { + /* We'll just compare keyslot against a hardcoded list of keys. */ static const uint8_t saved_keyslots[6] = { KEYSLOT_SWITCH_LP0TZRAMKEY, KEYSLOT_SWITCH_SESSIONKEY, @@ -64,4 +106,4 @@ void secmon_clear_unused_keyslots(void) { for (unsigned int i = 0; i < KEYSLOT_RSA_MAX; i++) { clear_rsa_keyslot(i); } -} \ No newline at end of file +} From 34c16e211f6135e8dfff58dd1155e240be010b4e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 18 Dec 2018 16:02:49 -0800 Subject: [PATCH 332/489] warmboot: make remaining TODOs explicit --- exosphere/lp0fw/src/fuse.c | 4 ++++ exosphere/lp0fw/src/fuse.h | 2 ++ exosphere/lp0fw/src/secmon.c | 8 +++++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/exosphere/lp0fw/src/fuse.c b/exosphere/lp0fw/src/fuse.c index 84a64cfa6..cad33c8f3 100644 --- a/exosphere/lp0fw/src/fuse.c +++ b/exosphere/lp0fw/src/fuse.c @@ -28,6 +28,10 @@ bool fuse_check_downgrade_status(void) { return false; } +void fuse_disable_programming(void) { + FUSE_REGS->FUSE_DIS_PGM = 1; +} + static fuse_bypass_data_t g_fuse_bypass_entries[NUM_FUSE_BYPASS_ENTRIES] = { /* No entries here. */ }; diff --git a/exosphere/lp0fw/src/fuse.h b/exosphere/lp0fw/src/fuse.h index 39706bd89..6c3059680 100644 --- a/exosphere/lp0fw/src/fuse.h +++ b/exosphere/lp0fw/src/fuse.h @@ -197,4 +197,6 @@ bool fuse_check_downgrade_status(void); void fuse_configure_fuse_bypass(void); +void fuse_disable_programming(void); + #endif diff --git a/exosphere/lp0fw/src/secmon.c b/exosphere/lp0fw/src/secmon.c index d6ec9b1b8..142e7b447 100644 --- a/exosphere/lp0fw/src/secmon.c +++ b/exosphere/lp0fw/src/secmon.c @@ -20,6 +20,7 @@ #include "lp0.h" #include "secmon.h" #include "se.h" +#include "fuse.h" #include "pmc.h" /* "private" functions. */ @@ -47,7 +48,12 @@ void secmon_restore_to_tzram(const uint32_t target_firmware) { /* Make security engine require secure busmaster. */ se_get_regs()->_0x4 = 0; - /* TODO: stuff */ + /* TODO: se_verify_keys_unreadable(); */ + + /* TODO: pmc_lockout_wb_scratch_registers(); */ + + /* Disable fuse programming. */ + fuse_disable_programming(); } void secmon_decrypt_saved_image(void *dst, const void *src, size_t size) { From a01d0e94f8da69bceffbcbca875b5c092be7955a Mon Sep 17 00:00:00 2001 From: misson20000 <xenotoad@xenotoad.net> Date: Fri, 21 Dec 2018 00:27:43 -0800 Subject: [PATCH 333/489] stratosphere/Makefile: change KIPS to MODULES --- stratosphere/Makefile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/stratosphere/Makefile b/stratosphere/Makefile index 61e6a119c..5369af9e4 100644 --- a/stratosphere/Makefile +++ b/stratosphere/Makefile @@ -1,8 +1,6 @@ -KIPS := loader pm sm boot fs_mitm set_mitm creport fatal +MODULES := loader pm sm boot fs_mitm set_mitm creport fatal -#TODO: boot2 ? - -SUBFOLDERS := libstratosphere $(KIPS) +SUBFOLDERS := libstratosphere $(MODULES) TOPTARGETS := all clean @@ -11,6 +9,6 @@ $(TOPTARGETS): $(SUBFOLDERS) $(SUBFOLDERS): $(MAKE) -C $@ $(MAKECMDGOALS) -$(KIPS): libstratosphere +$(MODULES): libstratosphere .PHONY: $(TOPTARGETS) $(SUBFOLDERS) From 3ce32d2014956a42357e42ec05ca1012c3ad003a Mon Sep 17 00:00:00 2001 From: The Dax <thedax@users.noreply.github.com> Date: Fri, 21 Dec 2018 16:56:07 -0500 Subject: [PATCH 334/489] DevkitARM r50-2 buildfix. --- fusee/fusee-secondary/src/stratosphere.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index acdaa7e89..9deaa8720 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -18,6 +18,7 @@ #include <stdlib.h> #include <stdint.h> #include <dirent.h> +#include <sys/stat.h> #include "exocfg.h" #include "utils.h" #include "package2.h" From 36a727ef8124cd8c9f11a494d224550b7db7399d Mon Sep 17 00:00:00 2001 From: SciresM <Sciresm@gmail.com> Date: Wed, 26 Dec 2018 12:56:20 -0800 Subject: [PATCH 335/489] fincs has write-access to the ams repo + deserves credit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b72ebf098..8059286e6 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Atmosphère consists of multiple components, each of which replaces/modifies a d Credits ===== -Atmosphère is currently being developed and maintained by __SciresM__, __TuxSH__ and __hexkyz__.<br> +Atmosphère is currently being developed and maintained by __SciresM__, __TuxSH__, __hexkyz__, and __fincs__.<br> In no particular order, we credit the following for their invaluable contributions: * __switchbrew__ for the [libnx](https://github.com/switchbrew/libnx) project and the extensive [documentation, research and tool development](http://switchbrew.org) pertaining to the Nintendo Switch. From d1abc53d3318cfe94a6008b4baf344f728e72d1d Mon Sep 17 00:00:00 2001 From: jul2003 <julien.appelle@wanadoo.fr> Date: Fri, 28 Dec 2018 18:56:03 +0100 Subject: [PATCH 336/489] devkitARM r50-3 buildfix --- fusee/fusee-secondary/src/lib/fatfs/ff.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fusee/fusee-secondary/src/lib/fatfs/ff.h b/fusee/fusee-secondary/src/lib/fatfs/ff.h index cd90d6d6d..e00f5f79d 100644 --- a/fusee/fusee-secondary/src/lib/fatfs/ff.h +++ b/fusee/fusee-secondary/src/lib/fatfs/ff.h @@ -187,6 +187,7 @@ typedef struct { /* Directory object structure (DIR) */ +#ifndef _dirent_h_ typedef struct { FFOBJID obj; /* Object identifier */ DWORD dptr; /* Current read/write offset */ @@ -201,7 +202,7 @@ typedef struct { const TCHAR* pat; /* Pointer to the name matching pattern */ #endif } DIR; - +#endif /* File information structure (FILINFO) */ From d0505d3c11f86589524a89bddf4dc00d8f8a6abb Mon Sep 17 00:00:00 2001 From: TuxSH <tuxsh@sfr.fr> Date: Fri, 28 Dec 2018 23:50:40 +0100 Subject: [PATCH 337/489] Revert "Merge pull request #313 from jul2003/master" This reverts commit dad67de8af3aa890bff2631cb15f5e2369523ee5, reversing changes made to af55d5872ccf86a5ae64eaa9eb8056fbd4487ae6. --- fusee/fusee-secondary/src/lib/fatfs/ff.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fusee/fusee-secondary/src/lib/fatfs/ff.h b/fusee/fusee-secondary/src/lib/fatfs/ff.h index e00f5f79d..cd90d6d6d 100644 --- a/fusee/fusee-secondary/src/lib/fatfs/ff.h +++ b/fusee/fusee-secondary/src/lib/fatfs/ff.h @@ -187,7 +187,6 @@ typedef struct { /* Directory object structure (DIR) */ -#ifndef _dirent_h_ typedef struct { FFOBJID obj; /* Object identifier */ DWORD dptr; /* Current read/write offset */ @@ -202,7 +201,7 @@ typedef struct { const TCHAR* pat; /* Pointer to the name matching pattern */ #endif } DIR; -#endif + /* File information structure (FILINFO) */ From 35cf3b65a37cd1d28f87413980a3a52418bd8e29 Mon Sep 17 00:00:00 2001 From: misson20000 <xenotoad@xenotoad.net> Date: Sun, 6 Jan 2019 16:30:05 -0800 Subject: [PATCH 338/489] loader/ECS: don't clear ECS on failure, add ClearExternalContentSource command --- docs/modules/loader.md | 27 ++++++++++++++++--- .../loader/source/ldr_process_creation.cpp | 6 +++-- stratosphere/loader/source/ldr_shell.cpp | 4 +++ stratosphere/loader/source/ldr_shell.hpp | 3 +++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/docs/modules/loader.md b/docs/modules/loader.md index 5ed0f5162..ca388178c 100644 --- a/docs/modules/loader.md +++ b/docs/modules/loader.md @@ -67,16 +67,35 @@ For example, `override_key=!R` will run the game only while holding down R when When the Stratosphere implementation of loader creates a new process, it notifies [sm](sm.md) through the `AtmosphereAssociatePidTidForMitm` command to notify any MITM services of new processes' identities. -### IPC: AtmosphereSetExternalContentSource +### IPC: AtmosphereSetExternalContentSource and AtmosphereClearExternalContentSource -An additional command is added to the [`ldr:shel`](https://reswitched.github.io/SwIPC/ifaces.html#nn::ro::detail::ILdrShellInterface) interface, called `AtmosphereSetExternalContentSource`. It's command ID is `65000` on all system firmware versions. It takes a `u64 tid` and returns a server-side session handle. The client is expected to implement the `IFileSystem` interface on the returned handle. The next time the title specified by the given title ID is launched, its ExeFS contents will be loaded from the custom `IFileSystem` instead of from SD card or original ExeFS. NSOs loaded from external content source may still be subject to exefs IPS patches. After the title is launched, the `IFileSystem` is closed and the external content source override is removed. If `AtmosphereSetExternalContentSource` is called on a title that already has an external content source set for it, the existing one will be removed and replaced with the new one. It is illegal to call `AtmosphereSetExternalContentSource` while the title is being launched. +Two additional commands are added to the [`ldr:shel`](https://reswitched.github.io/SwIPC/ifaces.html#nn::ro::detail::ILdrShellInterface) interface, called `AtmosphereSetExternalContentSource` and `AtmosphereClearExternalContentSource`. +Their command IDs are `65000` and `65001` on all system firmware versions. -The `IFileSystem` only needs to implement `OpenFile`. The paths received by the `IFileSystem`'s `OpenFile` command begin with slashes, as in `/main`, `/rtld`, and `/main.npdm`. A result code of 0x202 should be returned if the file does not exist. The `IFile`s returned from `OpenFile` only need to implement `Read` and `GetSize`. +`AtmosphereSetExternalContentSource` takes a `u64 tid` and returns a server-side session handle. +The client is expected to implement the `IFileSystem` interface on the returned handle. The next +time the title specified by the given title ID is launched, its ExeFS contents will be loaded from +the custom `IFileSystem` instead of from SD card or original ExeFS. NSOs loaded from external +content source may still be subject to exefs IPS patches. After the title is launched successfuly, +the `IFileSystem` is closed and the external content source override is removed. If +`AtmosphereSetExternalContentSource` is called on a title that already has an external content +source set for it, the existing one will be removed and replaced with the new one. It is illegal to +call `AtmosphereSetExternalContentSource` while the title is being launched. -The SwIPC definition for the `AtmosphereSetExternalContentSource` command follows. +If title launching fails, the external content source remains registered. The +`AtmosphereClearExternalContentSource` command can be used to clear an external content source if +title launch fails. + +The `IFileSystem` only needs to implement `OpenFile` and `GetFileTimeStampRaw`. The paths received +by the `IFileSystem`'s `OpenFile` command begin with slashes, as in `/main`, `/rtld`, and `/main.npdm`. +A result code of 0x202 should be returned if the file does not exist. `GetFileTimeStampRaw` can just +be a stub. The `IFile`s returned from `OpenFile` only need to implement `Read` and `GetSize`. + +The SwIPC definitions for the extension commands follow. ``` interface nn::ldr::detail::IShellInterface is ldr:shel { ... [65000] AtmosphereSetExternalContentSource(u64 tid) -> handle<copy, session_server> ifilesystem_handle; + [65001] AtmosphereClearExternalContentSource(u64 tid); } ``` diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 74c4b095e..6253b9bfc 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -214,8 +214,8 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc Registration::AssociatePidTidForMitM(index); rc = 0; -CREATE_PROCESS_END: - /* ECS is a one-shot operation. */ + + /* ECS is a one-shot operation, but we don't clear on failure. */ ContentManagement::ClearExternalContentSource(target_process->tid_sid.title_id); if (mounted_code) { if (R_SUCCEEDED(rc) && target_process->tid_sid.storage_id != FsStorageId_None) { @@ -224,6 +224,8 @@ CREATE_PROCESS_END: ContentManagement::UnmountCode(); } } + +CREATE_PROCESS_END: if (R_SUCCEEDED(rc)) { *out_process_h = process_h; } else { diff --git a/stratosphere/loader/source/ldr_shell.cpp b/stratosphere/loader/source/ldr_shell.cpp index 4574c5af4..a359db5b2 100644 --- a/stratosphere/loader/source/ldr_shell.cpp +++ b/stratosphere/loader/source/ldr_shell.cpp @@ -45,3 +45,7 @@ Result ShellService::SetExternalContentSource(Out<MovedHandle> out, u64 tid) { out.SetValue(server_h); return 0; } + +void ShellService::ClearExternalContentSource(u64 tid) { + ContentManagement::ClearExternalContentSource(tid); +} diff --git a/stratosphere/loader/source/ldr_shell.hpp b/stratosphere/loader/source/ldr_shell.hpp index 69d6f2107..f51361f5d 100644 --- a/stratosphere/loader/source/ldr_shell.hpp +++ b/stratosphere/loader/source/ldr_shell.hpp @@ -23,6 +23,7 @@ enum ShellServiceCmd { Shell_Cmd_ClearLaunchQueue = 1, Shell_Cmd_AtmosphereSetExternalContentSource = 65000, + Shell_Cmd_AtmosphereClearExternalContentSource = 65001, }; class ShellService final : public IServiceObject { @@ -33,10 +34,12 @@ class ShellService final : public IServiceObject { /* Atmosphere commands. */ Result SetExternalContentSource(Out<MovedHandle> out, u64 tid); + void ClearExternalContentSource(u64 tid); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<Shell_Cmd_AddTitleToLaunchQueue, &ShellService::AddTitleToLaunchQueue>(), MakeServiceCommandMeta<Shell_Cmd_ClearLaunchQueue, &ShellService::ClearLaunchQueue>(), MakeServiceCommandMeta<Shell_Cmd_AtmosphereSetExternalContentSource, &ShellService::SetExternalContentSource>(), + MakeServiceCommandMeta<Shell_Cmd_AtmosphereClearExternalContentSource, &ShellService::ClearExternalContentSource>(), }; }; From da0d22f05ae4758e54b70cfe4c289a6263e60ba0 Mon Sep 17 00:00:00 2001 From: natinusala <natinusala@gmail.com> Date: Sun, 6 Jan 2019 21:56:36 +0100 Subject: [PATCH 339/489] loader: add 'override any app' feature --- = | 0 .../loader/source/ldr_content_management.cpp | 14 ++++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 = diff --git a/= b/= new file mode 100644 index 000000000..e69de29bb diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index d63b242d7..77a17bb5d 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -40,6 +40,7 @@ static char g_hbl_sd_path[FS_MAX_PATH+1] = "@Sdcard:/atmosphere/hbl.nsp\x00"; static u64 g_override_key_combination = KEY_R; static bool g_override_by_default = true; static u64 g_override_hbl_tid = 0x010000000000100D; +static bool g_override_any_app = false; /* Static buffer for loader.ini contents at runtime. */ static char g_config_ini_data[0x800]; @@ -206,9 +207,14 @@ static int LoaderIniHandler(void *user, const char *section, const char *name, c /* Taken and modified, with love, from Rajkosto's implementation. */ if (strcasecmp(section, "config") == 0) { if (strcasecmp(name, "hbl_tid") == 0) { - u64 override_tid = strtoul(value, NULL, 16); - if (override_tid != 0) { - g_override_hbl_tid = override_tid; + if (strcasecmp(value, "app") == 0) { + g_override_any_app = true; + } + else { + u64 override_tid = strtoul(value, NULL, 16); + if (override_tid != 0) { + g_override_hbl_tid = override_tid; + } } } else if (strcasecmp(name, "hbl_path") == 0) { while (*value == '/' || *value == '\\') { @@ -303,7 +309,7 @@ void ContentManagement::TryMountSdCard() { } bool ContentManagement::ShouldReplaceWithHBL(u64 tid) { - return g_mounted_hbl_nsp && tid == g_override_hbl_tid; + return g_mounted_hbl_nsp && ((g_override_any_app && tid >= 0x0100000000010000) || (!g_override_any_app && tid == g_override_hbl_tid)); } bool ContentManagement::ShouldOverrideContents(u64 tid) { From a899a61f80d14a130c9236b090c64e25590f6ad1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 9 Jan 2019 12:50:01 -0800 Subject: [PATCH 340/489] fs.mitm: match any_app override semantics --- stratosphere/fs_mitm/source/fsmitm_utils.cpp | 20 +++++++++++++++----- stratosphere/fs_mitm/source/fsmitm_utils.hpp | 2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/fs_mitm/source/fsmitm_utils.cpp index 39d8ce1f4..a16d9aa2b 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.cpp @@ -33,6 +33,7 @@ static std::atomic_bool g_has_hid_session = false; static u64 g_override_key_combination = KEY_R; static u64 g_override_hbl_tid = 0x010000000000100DULL; +static bool g_override_any_app = false; static bool g_override_by_default = true; /* Static buffer for loader.ini contents at runtime. */ @@ -348,6 +349,10 @@ Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data, return rc; } +bool Utils::IsHblTid(u64 tid) { + return (g_override_any_app && tid >= 0x0100000000010000ULL) || (!g_override_any_app && tid == g_override_hbl_tid); +} + bool Utils::HasTitleFlag(u64 tid, const char *flag) { if (IsSdInitialized()) { FsFile f; @@ -390,11 +395,11 @@ bool Utils::HasHblFlag(const char *flag) { } bool Utils::HasFlag(u64 tid, const char *flag) { - return HasTitleFlag(tid, flag) || (tid == g_override_hbl_tid && HasHblFlag(flag)); + return HasTitleFlag(tid, flag) || (IsHblTid(tid) && HasHblFlag(flag)); } bool Utils::HasSdMitMFlag(u64 tid) { - if (tid == g_override_hbl_tid) { + if (IsHblTid(tid)) { return true; } @@ -441,9 +446,14 @@ static int FsMitMIniHandler(void *user, const char *section, const char *name, c /* Taken and modified, with love, from Rajkosto's implementation. */ if (strcasecmp(section, "config") == 0) { if (strcasecmp(name, "hbl_tid") == 0) { - u64 override_tid = strtoul(value, NULL, 16); - if (override_tid != 0) { - g_override_hbl_tid = override_tid; + if (strcasecmp(value, "app") == 0) { + g_override_any_app = true; + } + else { + u64 override_tid = strtoul(value, NULL, 16); + if (override_tid != 0) { + g_override_hbl_tid = override_tid; + } } } else if (strcasecmp(name, "override_key") == 0) { if (value[0] == '!') { diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/fs_mitm/source/fsmitm_utils.hpp index 856748c4d..6aa8535b7 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_utils.hpp @@ -58,6 +58,8 @@ class Utils { /* SD card Initialization + MitM detection. */ static void InitializeSdThreadFunc(void *args); + static bool IsHblTid(u64 tid); + static bool HasTitleFlag(u64 tid, const char *flag); static bool HasHblFlag(const char *flag); static bool HasGlobalFlag(const char *flag); From d0285fb57c44227c602c14cb034664255e801845 Mon Sep 17 00:00:00 2001 From: jakibaki <jakibaki@live.com> Date: Sat, 12 Jan 2019 15:27:12 +0100 Subject: [PATCH 341/489] Remove '=' file from the root of the repo --- = | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 = diff --git a/= b/= deleted file mode 100644 index e69de29bb..000000000 From 50db68527455034caf449aaf5189937f9ff9c6bf Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 19 Jan 2019 16:23:23 -0800 Subject: [PATCH 342/489] creport: attempt to improve userbreak errcode output --- .../creport/source/creport_crash_report.cpp | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 08e15c301..0c48af675 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -19,10 +19,8 @@ #include <sys/stat.h> #include <sys/types.h> #include <switch.h> - #include "creport_crash_report.hpp" #include "creport_debug_types.hpp" - void CrashReport::BuildReport(u64 pid, bool has_extra_info) { this->has_extra_info = has_extra_info; if (OpenProcess(pid)) { @@ -46,7 +44,6 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { Close(); } } - FatalContext *CrashReport::GetFatalContext() { FatalContext *ctx = new FatalContext; *ctx = (FatalContext){0}; @@ -75,7 +72,6 @@ FatalContext *CrashReport::GetFatalContext() { return ctx; } - void CrashReport::ProcessExceptions() { if (!IsOpen()) { return; @@ -98,7 +94,6 @@ void CrashReport::ProcessExceptions() { } } } - void CrashReport::HandleAttachProcess(DebugEventInfo &d) { this->process_info = d.info.attach_process; if (kernelAbove500() && IsApplication()) { @@ -136,7 +131,6 @@ void CrashReport::HandleAttachProcess(DebugEventInfo &d) { this->dying_message_size = userdata_size; } } - void CrashReport::HandleException(DebugEventInfo &d) { switch (d.info.exception.type) { case DebugExceptionType::UndefinedInstruction: @@ -155,8 +149,15 @@ void CrashReport::HandleException(DebugEventInfo &d) { case DebugExceptionType::UserBreak: this->result = (Result)CrashReportResult::UserBreak; /* Try to parse out the user break result. */ - if (kernelAbove500() && IsAddressReadable(d.info.exception.specific.user_break.address, sizeof(this->result))) { - svcReadDebugProcessMemory(&this->result, this->debug_handle, d.info.exception.specific.user_break.address, sizeof(this->result)); + if (kernelAbove500()) { + Result user_result = RESULT_SUCCESS; + if (IsAddressReadable(d.info.exception.specific.user_break.address, sizeof(user_result))) { + svcReadDebugProcessMemory(&user_result, this->debug_handle, d.info.exception.specific.user_break.address, sizeof(user_result)); + } + /* Only copy over the user result if it gives us information (as by default nnSdk uses the success code, which is confusing). */ + if (R_FAILED(user_result)) { + this->result = user_result; + } } break; case DebugExceptionType::BadSvc: @@ -176,7 +177,6 @@ void CrashReport::HandleException(DebugEventInfo &d) { /* Parse crashing thread info. */ this->crashed_thread_info.ReadFromProcess(this->debug_handle, d.thread_id, Is64Bit()); } - void CrashReport::ProcessDyingMessage() { /* Dying message is only stored starting in 5.0.0. */ if (!kernelAbove500()) { @@ -202,7 +202,6 @@ void CrashReport::ProcessDyingMessage() { svcReadDebugProcessMemory(this->dying_message, this->debug_handle, this->dying_message_address, this->dying_message_size); } - bool CrashReport::IsAddressReadable(u64 address, u64 size, MemoryInfo *o_mi) { MemoryInfo mi; u32 pi; @@ -224,10 +223,8 @@ bool CrashReport::IsAddressReadable(u64 address, u64 size, MemoryInfo *o_mi) { if (address < o_mi->addr || o_mi->addr + o_mi->size < address + size) { return false; } - return true; } - bool CrashReport::GetCurrentTime(u64 *out) { *out = 0; @@ -250,7 +247,6 @@ bool CrashReport::GetCurrentTime(u64 *out) { } return success; } - void CrashReport::EnsureReportDirectories() { char path[FS_MAX_PATH]; strcpy(path, "sdmc:/atmosphere"); @@ -260,7 +256,6 @@ void CrashReport::EnsureReportDirectories() { strcat(path, "/dumps"); mkdir(path, S_IRWXU); } - void CrashReport::SaveReport() { /* Save the report to the SD card. */ char report_path[FS_MAX_PATH]; @@ -289,7 +284,6 @@ void CrashReport::SaveReport() { this->thread_list.DumpBinary(f_report, this->crashed_thread_info.GetId()); fclose(f_report); } - void CrashReport::SaveToFile(FILE *f_report) { char buf[0x10] = {0}; fprintf(f_report, "Atmosphère Crash Report (v1.2):\n"); @@ -347,35 +341,27 @@ void CrashReport::SaveToFile(FILE *f_report) { fprintf(f_report, "\nThread Report:\n"); this->thread_list.SaveToFile(f_report); } - /* Lifted from hactool. */ void CrashReport::Memdump(FILE *f, const char *prefix, const void *data, size_t size) { uint8_t *p = (uint8_t *)data; - unsigned int prefix_len = strlen(prefix); size_t offset = 0; int first = 1; - while (size) { unsigned int max = 32; - if (max > size) { max = size; } - if (first) { fprintf(f, "%s", prefix); first = 0; } else { fprintf(f, "%*s", prefix_len, ""); } - for (unsigned int i = 0; i < max; i++) { fprintf(f, "%02X", p[offset++]); } - fprintf(f, "\n"); - size -= max; } } From 2a2d1bc78bd1169d5bb48a682a5b820c66707e6a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 19 Jan 2019 16:32:33 -0800 Subject: [PATCH 343/489] creport: Fix formatting error. --- .../creport/source/creport_crash_report.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 0c48af675..7d130e34a 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -19,8 +19,10 @@ #include <sys/stat.h> #include <sys/types.h> #include <switch.h> + #include "creport_crash_report.hpp" #include "creport_debug_types.hpp" + void CrashReport::BuildReport(u64 pid, bool has_extra_info) { this->has_extra_info = has_extra_info; if (OpenProcess(pid)) { @@ -44,6 +46,7 @@ void CrashReport::BuildReport(u64 pid, bool has_extra_info) { Close(); } } + FatalContext *CrashReport::GetFatalContext() { FatalContext *ctx = new FatalContext; *ctx = (FatalContext){0}; @@ -72,6 +75,7 @@ FatalContext *CrashReport::GetFatalContext() { return ctx; } + void CrashReport::ProcessExceptions() { if (!IsOpen()) { return; @@ -94,6 +98,7 @@ void CrashReport::ProcessExceptions() { } } } + void CrashReport::HandleAttachProcess(DebugEventInfo &d) { this->process_info = d.info.attach_process; if (kernelAbove500() && IsApplication()) { @@ -131,6 +136,7 @@ void CrashReport::HandleAttachProcess(DebugEventInfo &d) { this->dying_message_size = userdata_size; } } + void CrashReport::HandleException(DebugEventInfo &d) { switch (d.info.exception.type) { case DebugExceptionType::UndefinedInstruction: @@ -177,6 +183,7 @@ void CrashReport::HandleException(DebugEventInfo &d) { /* Parse crashing thread info. */ this->crashed_thread_info.ReadFromProcess(this->debug_handle, d.thread_id, Is64Bit()); } + void CrashReport::ProcessDyingMessage() { /* Dying message is only stored starting in 5.0.0. */ if (!kernelAbove500()) { @@ -202,6 +209,7 @@ void CrashReport::ProcessDyingMessage() { svcReadDebugProcessMemory(this->dying_message, this->debug_handle, this->dying_message_address, this->dying_message_size); } + bool CrashReport::IsAddressReadable(u64 address, u64 size, MemoryInfo *o_mi) { MemoryInfo mi; u32 pi; @@ -225,6 +233,7 @@ bool CrashReport::IsAddressReadable(u64 address, u64 size, MemoryInfo *o_mi) { } return true; } + bool CrashReport::GetCurrentTime(u64 *out) { *out = 0; @@ -247,6 +256,7 @@ bool CrashReport::GetCurrentTime(u64 *out) { } return success; } + void CrashReport::EnsureReportDirectories() { char path[FS_MAX_PATH]; strcpy(path, "sdmc:/atmosphere"); @@ -256,6 +266,7 @@ void CrashReport::EnsureReportDirectories() { strcat(path, "/dumps"); mkdir(path, S_IRWXU); } + void CrashReport::SaveReport() { /* Save the report to the SD card. */ char report_path[FS_MAX_PATH]; @@ -284,6 +295,7 @@ void CrashReport::SaveReport() { this->thread_list.DumpBinary(f_report, this->crashed_thread_info.GetId()); fclose(f_report); } + void CrashReport::SaveToFile(FILE *f_report) { char buf[0x10] = {0}; fprintf(f_report, "Atmosphère Crash Report (v1.2):\n"); @@ -341,6 +353,7 @@ void CrashReport::SaveToFile(FILE *f_report) { fprintf(f_report, "\nThread Report:\n"); this->thread_list.SaveToFile(f_report); } + /* Lifted from hactool. */ void CrashReport::Memdump(FILE *f, const char *prefix, const void *data, size_t size) { uint8_t *p = (uint8_t *)data; From a09137c00803e4e5ec8b24b4c838b64e99e99d1b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 19 Jan 2019 16:35:40 -0800 Subject: [PATCH 344/489] creport: Okay, maybe actually fix formatting. --- stratosphere/creport/source/creport_crash_report.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 7d130e34a..8a6dc786e 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -231,6 +231,7 @@ bool CrashReport::IsAddressReadable(u64 address, u64 size, MemoryInfo *o_mi) { if (address < o_mi->addr || o_mi->addr + o_mi->size < address + size) { return false; } + return true; } @@ -357,24 +358,31 @@ void CrashReport::SaveToFile(FILE *f_report) { /* Lifted from hactool. */ void CrashReport::Memdump(FILE *f, const char *prefix, const void *data, size_t size) { uint8_t *p = (uint8_t *)data; + unsigned int prefix_len = strlen(prefix); size_t offset = 0; int first = 1; + while (size) { unsigned int max = 32; + if (max > size) { max = size; } + if (first) { fprintf(f, "%s", prefix); first = 0; } else { fprintf(f, "%*s", prefix_len, ""); } + for (unsigned int i = 0; i < max; i++) { fprintf(f, "%02X", p[offset++]); } + fprintf(f, "\n"); + size -= max; } } From c42fc16d8e179d46323acc6343533b616cbf5b79 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 19 Jan 2019 17:28:26 -0800 Subject: [PATCH 345/489] creport: RESULT_SUCCESS is not a defined value by libnx. --- stratosphere/creport/source/creport_crash_report.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/creport/source/creport_crash_report.cpp b/stratosphere/creport/source/creport_crash_report.cpp index 8a6dc786e..d202dff08 100644 --- a/stratosphere/creport/source/creport_crash_report.cpp +++ b/stratosphere/creport/source/creport_crash_report.cpp @@ -156,7 +156,7 @@ void CrashReport::HandleException(DebugEventInfo &d) { this->result = (Result)CrashReportResult::UserBreak; /* Try to parse out the user break result. */ if (kernelAbove500()) { - Result user_result = RESULT_SUCCESS; + Result user_result = 0; if (IsAddressReadable(d.info.exception.specific.user_break.address, sizeof(user_result))) { svcReadDebugProcessMemory(&user_result, this->debug_handle, d.info.exception.specific.user_break.address, sizeof(user_result)); } From add52b90c9c1f8a71be1c577b5e5045c3d1f3bfd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 19 Jan 2019 17:31:35 -0800 Subject: [PATCH 346/489] exosphere: Add support for AMS SMC extensions --- exosphere/src/smc_ams.c | 33 +++++++++++++++++++++++++++++++++ exosphere/src/smc_ams.h | 24 ++++++++++++++++++++++++ exosphere/src/smc_api.c | 40 +++++++++++++++++++++++++++++++++------- exosphere/src/smc_api.h | 15 +++++++++++++-- 4 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 exosphere/src/smc_ams.c create mode 100644 exosphere/src/smc_ams.h diff --git a/exosphere/src/smc_ams.c b/exosphere/src/smc_ams.c new file mode 100644 index 000000000..98e10146b --- /dev/null +++ b/exosphere/src/smc_ams.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#include "utils.h" +#include "smc_api.h" +#include "smc_ams.h" + +uint32_t ams_iram_copy(smc_args_t *args) { + /* TODO: Implement a DRAM <-> IRAM copy of up to one page here. */ + /* This operation is necessary to implement reboot-to-payload. */ + /* args->X[1] = DRAM address (translated by kernel). */ + /* args->X[2] = IRAM address. */ + /* args->X[3] = size (must be <= 0x1000). */ + /* args->X[4] = 0 for read, 1 for write. */ + return 2; +} diff --git a/exosphere/src/smc_ams.h b/exosphere/src/smc_ams.h new file mode 100644 index 000000000..ed1cee156 --- /dev/null +++ b/exosphere/src/smc_ams.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_SMC_AMS_H +#define EXOSPHERE_SMC_AMS_H + +#include "smc_api.h" + +uint32_t ams_iram_copy(smc_args_t *args); + +#endif \ No newline at end of file diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index 2cb028589..373919162 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -31,6 +31,7 @@ #include "sealedkeys.h" #include "smc_api.h" #include "smc_user.h" +#include "smc_ams.h" #include "se.h" #include "userpage.h" #include "titlekey.h" @@ -40,6 +41,8 @@ #define SMC_USER_HANDLERS 0x13 #define SMC_PRIV_HANDLERS 0x9 +#define SMC_AMS_HANDLERS 0x2 + #define DEBUG_LOG_SMCS 0 #define DEBUG_PANIC_ON_FAILURE 0 @@ -77,6 +80,9 @@ uint32_t smc_panic(smc_args_t *args); uint32_t smc_configure_carveout(smc_args_t *args); uint32_t smc_read_write_register(smc_args_t *args); +/* Atmosphere SMC prototypes */ +uint32_t smc_ams_iram_copy(smc_args_t *args); + typedef struct { uint32_t id; uint32_t (*handler)(smc_args_t *args); @@ -121,7 +127,13 @@ static smc_table_entry_t g_smc_priv_table[SMC_PRIV_HANDLERS] = { {0xC3000008, smc_read_write_register} }; -static smc_table_t g_smc_tables[2] = { +/* This is a table used for atmosphere-specific SMCs. */ +static smc_table_entry_t g_smc_ams_table[SMC_AMS_HANDLERS] = { + {0, NULL}, + {0xF0000201, smc_ams_iram_copy}, +}; + +static smc_table_t g_smc_tables[SMC_HANDLER_COUNT + 1] = { { /* SMC_HANDLER_USER */ g_smc_user_table, SMC_USER_HANDLERS @@ -129,6 +141,10 @@ static smc_table_t g_smc_tables[2] = { { /* SMC_HANDLER_PRIV */ g_smc_priv_table, SMC_PRIV_HANDLERS + }, + { /* SMC_HANDLER_AMS */ + g_smc_ams_table, + SMC_AMS_HANDLERS } }; @@ -228,19 +244,25 @@ void clear_smc_callback(uint64_t key) { _Atomic uint64_t num_smcs_called = 0; void call_smc_handler(uint32_t handler_id, smc_args_t *args) { - unsigned char smc_id; + unsigned char smc_id, call_range; unsigned int result; unsigned int (*smc_handler)(smc_args_t *args); /* Validate top-level handler. */ - if (handler_id != SMC_HANDLER_USER && handler_id != SMC_HANDLER_PRIV) { + if (handler_id >= SMC_HANDLER_COUNT) { generic_panic(); } - /* Validate core is appropriate for handler. */ - if (handler_id == SMC_HANDLER_USER && get_core_id() != 3) { - /* USER SMCs must be called via svcCallSecureMonitor on core 3 (where spl runs) */ - generic_panic(); + /* If user-handler, detect if talking to Atmosphere/validate calling core. */ + if (handler_id == SMC_HANDLER_USER) { + if ((call_range = (unsigned char)((args->X[0] >> 24) & 0x3F)) == SMC_CALL_RANGE_TRUSTED_APP) { + /* Nintendo's SMCs are all OEM-specific. */ + /* Pending a reason not to, we will treat Trusted Application SMCs as intended to talk to Atmosphere. */ + handler_id = SMC_HANDLER_AMS; + } else if (get_core_id() != 3) { + /* USER SMCs must be called via svcCallSecureMonitor on core 3 (where spl runs) */ + generic_panic(); + } } /* Validate sub-handler index */ @@ -683,3 +705,7 @@ uint32_t smc_panic(smc_args_t *args) { uint32_t color = ((args->X[1] & 0xF) << 8) | ((args->X[1] & 0xF0)) | ((args->X[1] & 0xF00) >> 8); panic((color << 20) | 0x40); } + +uint32_t smc_ams_iram_copy(smc_args_t *args) { + return smc_wrapper_sync(args, ams_iram_copy); +} diff --git a/exosphere/src/smc_api.h b/exosphere/src/smc_api.h index 476d2a4fe..5f95444fc 100644 --- a/exosphere/src/smc_api.h +++ b/exosphere/src/smc_api.h @@ -19,8 +19,19 @@ #include <stdint.h> -#define SMC_HANDLER_USER 0 -#define SMC_HANDLER_PRIV 1 +#define SMC_HANDLER_USER 0 +#define SMC_HANDLER_PRIV 1 +#define SMC_HANDLER_COUNT 2 + +#define SMC_HANDLER_AMS (SMC_HANDLER_COUNT) + +#define SMC_CALL_RANGE_ARM_ARCH 0 +#define SMC_CALL_RANGE_CPU 1 +#define SMC_CALL_RANGE_SIP 2 +#define SMC_CALL_RANGE_OEM 3 +#define SMC_CALL_RANGE_STANDARD 4 + +#define SMC_CALL_RANGE_TRUSTED_APP 0x30 typedef struct { uint64_t X[8]; From caba025e978778363ffee4107523f905458d00e9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 02:37:04 -0800 Subject: [PATCH 347/489] warmboot: fix bugs in firmware --- exosphere/lp0fw/src/cluster.c | 4 ++-- exosphere/lp0fw/src/i2c.c | 4 ++-- exosphere/lp0fw/src/misc.c | 2 +- exosphere/lp0fw/src/pmc.h | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/exosphere/lp0fw/src/cluster.c b/exosphere/lp0fw/src/cluster.c index d05de9082..bbbc4fd2f 100644 --- a/exosphere/lp0fw/src/cluster.c +++ b/exosphere/lp0fw/src/cluster.c @@ -37,7 +37,7 @@ static void cluster_pmc_enable_partition(uint32_t mask, uint32_t toggle) { /* Remove clamping. */ APBDEV_PMC_REMOVE_CLAMPING_CMD_0 = mask; - while (!(APBDEV_PMC_CLAMP_STATUS_0 & mask)) { } + while (APBDEV_PMC_CLAMP_STATUS_0 & mask) { } } void cluster_initialize_cpu(void) { @@ -113,7 +113,7 @@ void cluster_initialize_cpu(void) { /* Remove SW clamp to CRAIL. */ APBDEV_PMC_SET_SW_CLAMP_0 = 0; APBDEV_PMC_REMOVE_CLAMPING_CMD_0 = 1; - while (!(APBDEV_PMC_CLAMP_STATUS_0 & 1)) { } + while (APBDEV_PMC_CLAMP_STATUS_0 & 1) { } /* Nintendo manually counts down from 8. I am not sure why this happens. */ { diff --git a/exosphere/lp0fw/src/i2c.c b/exosphere/lp0fw/src/i2c.c index 68382b0c2..b7fafd932 100644 --- a/exosphere/lp0fw/src/i2c.c +++ b/exosphere/lp0fw/src/i2c.c @@ -27,8 +27,8 @@ void i2c_set_test_master_config_load(void) { /* Set MSTR_CONFIG_LOAD. */ I2C_I2C_CONFIG_LOAD_0 = 0x1; - while (!(I2C_I2C_CONFIG_LOAD_0 & 1)) { - /* Wait forever until it's set. */ + while (I2C_I2C_CONFIG_LOAD_0 & 1) { + /* Wait forever until it's unset. */ } } diff --git a/exosphere/lp0fw/src/misc.c b/exosphere/lp0fw/src/misc.c index 941f50981..9a795d37c 100644 --- a/exosphere/lp0fw/src/misc.c +++ b/exosphere/lp0fw/src/misc.c @@ -48,5 +48,5 @@ void misc_configure_device_dbg_settings(void) { void misc_restore_ram_svop(void) { /* This sets CFG2TMC_RAM_SVOP_PDP to 0x2. */ - APB_MISC_GP_ASDBGREG_0 |= 0x02000000; + APB_MISC_GP_ASDBGREG_0 = (APB_MISC_GP_ASDBGREG_0 & 0xFCFFFFFF) | 0x02000000; } \ No newline at end of file diff --git a/exosphere/lp0fw/src/pmc.h b/exosphere/lp0fw/src/pmc.h index 2bee565a3..908a55e8f 100644 --- a/exosphere/lp0fw/src/pmc.h +++ b/exosphere/lp0fw/src/pmc.h @@ -51,10 +51,10 @@ #define APBDEV_PMC_SECURE_SCRATCH34_0 MAKE_PMC_REG(0x368) #define APBDEV_PMC_SECURE_SCRATCH35_0 MAKE_PMC_REG(0x36C) -#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_PMC_REG(0x718) -#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_PMC_REG(0x71C) -#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_PMC_REG(0x720) -#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_PMC_REG(0x724) +#define APBDEV_PMC_SECURE_SCRATCH112_0 MAKE_PMC_REG(0xB18) +#define APBDEV_PMC_SECURE_SCRATCH113_0 MAKE_PMC_REG(0xB1C) +#define APBDEV_PMC_SECURE_SCRATCH114_0 MAKE_PMC_REG(0xB20) +#define APBDEV_PMC_SECURE_SCRATCH115_0 MAKE_PMC_REG(0xB24) #define APBDEV_PMC_IO_DPD3_REQ_0 MAKE_PMC_REG(0x45C) #define APBDEV_PMC_IO_DPD3_STATUS_0 MAKE_PMC_REG(0x460) From d349bdb1f848d30fdd28ae485ea8b0fac261ffa3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 02:38:45 -0800 Subject: [PATCH 348/489] fusee/exo: build warmboot, use instead of Nintendo's. --- exosphere/Makefile | 11 ++-- fusee/fusee-secondary/Makefile | 4 +- fusee/fusee-secondary/src/lp0.h | 52 ++++++++++++++++++ fusee/fusee-secondary/src/nxboot.c | 87 ++++++++++++++++++++++-------- 4 files changed, 128 insertions(+), 26 deletions(-) create mode 100644 fusee/fusee-secondary/src/lp0.h diff --git a/exosphere/Makefile b/exosphere/Makefile index 4eb2d4491..cb06f6f5f 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -75,6 +75,7 @@ export TOPDIR := $(CURDIR) export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(TOPDIR)/lp0fw \ $(TOPDIR)/sc7fw export DEPSDIR := $(CURDIR)/$(BUILD) @@ -82,7 +83,7 @@ export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin lp0fw.bin #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C @@ -109,7 +110,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -.PHONY: $(BUILD) build_sc7fw clean all +.PHONY: $(BUILD) build_sc7fw build_lp0fw clean all #--------------------------------------------------------------------------------- all: $(BUILD) @@ -117,7 +118,10 @@ all: $(BUILD) check_sc7fw: @$(MAKE) -C sc7fw all -$(BUILD): check_sc7fw +check_lp0fw: + @$(MAKE) -C lp0fw all + +$(BUILD): check_sc7fw check_lp0fw @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile @@ -125,6 +129,7 @@ $(BUILD): check_sc7fw clean: @echo clean ... @$(MAKE) -C $(TOPDIR)/sc7fw clean + @$(MAKE) -C $(TOPDIR)/lp0fw clean @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index c2c849f4d..90e963b63 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -79,7 +79,7 @@ export TOPDIR := $(CURDIR) export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/fs_mitm export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ - $(AMS)/exosphere $(AMS)/thermosphere $(KIPDIRS) + $(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/thermosphere $(KIPDIRS) export DEPSDIR := $(CURDIR)/$(BUILD) @@ -87,7 +87,7 @@ CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) KIPFILES := loader.kip pm.kip sm.kip fs_mitm.kip boot_100.kip boot_200.kip -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) exosphere.bin thermosphere.bin splash_screen.bmp $(KIPFILES) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) exosphere.bin lp0fw.bin thermosphere.bin splash_screen.bmp $(KIPFILES) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C diff --git a/fusee/fusee-secondary/src/lp0.h b/fusee/fusee-secondary/src/lp0.h new file mode 100644 index 000000000..bcb09fa63 --- /dev/null +++ b/fusee/fusee-secondary/src/lp0.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_WARMBOOT_BIN_LP0_H +#define FUSEE_WARMBOOT_BIN_LP0_H + +#include "utils.h" + +/* WBT0 */ +#define WARMBOOT_MAGIC 0x30544257 + +typedef struct { + uint32_t entrypoint_insn; + uint32_t magic; + uint32_t target_firmware; + uint32_t padding[2]; +} warmboot_metadata_t; + +typedef struct { + uint32_t warmboot_fw_size; + uint32_t dst_address; + uint32_t entrypoint; + uint32_t code_size; +} warmboot_nv_header_t; + +typedef struct { + uint32_t warmboot_fw_size; + uint32_t _0x4[3]; + uint8_t rsa_modulus[0x100]; + uint8_t _0x110[0x10]; + uint8_t rsa_signature[0x100]; + uint8_t _0x220[0x10]; + warmboot_nv_header_t nv_header; + warmboot_metadata_t ams_metadata; +} warmboot_ams_header_t; + +_Static_assert(sizeof(warmboot_ams_header_t) == 0x254, "Warmboot header definition!"); + +#endif diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 37e4d293c..6879d4ec8 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -41,6 +41,7 @@ #include "package2.h" #include "smmu.h" #include "tsec.h" +#include "lp0.h" #include "loader.h" #include "splash_screen.h" #include "exocfg.h" @@ -50,10 +51,52 @@ #define u8 uint8_t #define u32 uint32_t #include "exosphere_bin.h" +#include "lp0fw_bin.h" #include "lib/log.h" #undef u8 #undef u32 +extern const uint8_t lp0fw_bin[]; +extern const uint32_t lp0fw_bin_size; + +static const uint8_t retail_pkc_modulus[0x100] = { + 0xF7, 0x86, 0x47, 0xAB, 0x71, 0x89, 0x81, 0xB5, 0xCF, 0x0C, 0xB0, 0xE8, 0x48, 0xA7, 0xFD, 0xAD, + 0xCB, 0x4E, 0x4A, 0x52, 0x0B, 0x1A, 0x8E, 0xDE, 0x41, 0x87, 0x6F, 0xB7, 0x31, 0x05, 0x5F, 0xAA, + 0xEA, 0x97, 0x76, 0x21, 0x20, 0x2B, 0x40, 0x48, 0x76, 0x55, 0x35, 0x03, 0xFE, 0x7F, 0x67, 0x62, + 0xFD, 0x4E, 0xE1, 0x22, 0xF8, 0xF0, 0x97, 0x39, 0xEF, 0xEA, 0x47, 0x89, 0x3C, 0xDB, 0xF0, 0x02, + 0xAD, 0x0C, 0x96, 0xCA, 0x82, 0xAB, 0xB3, 0xCB, 0x98, 0xC8, 0xDC, 0xC6, 0xAC, 0x5C, 0x93, 0x3B, + 0x84, 0x3D, 0x51, 0x91, 0x9E, 0xC1, 0x29, 0x22, 0x95, 0xF0, 0xA1, 0x51, 0xBA, 0xAF, 0x5D, 0xC3, + 0xAB, 0x04, 0x1B, 0x43, 0x61, 0x7D, 0xEA, 0x65, 0x95, 0x24, 0x3C, 0x51, 0x3E, 0x8F, 0xDB, 0xDB, + 0xC1, 0xC4, 0x2D, 0x04, 0x29, 0x5A, 0xD7, 0x34, 0x6B, 0xCC, 0xF1, 0x06, 0xF9, 0xC9, 0xE1, 0xF9, + 0x61, 0x52, 0xE2, 0x05, 0x51, 0xB1, 0x3D, 0x88, 0xF9, 0xA9, 0x27, 0xA5, 0x6F, 0x4D, 0xE7, 0x22, + 0x48, 0xA5, 0xF8, 0x12, 0xA2, 0xC2, 0x5A, 0xA0, 0xBF, 0xC8, 0x76, 0x4B, 0x66, 0xFE, 0x1C, 0x73, + 0x00, 0x29, 0x26, 0xCD, 0x18, 0x4F, 0xC2, 0xB0, 0x51, 0x77, 0x2E, 0x91, 0x09, 0x1B, 0x41, 0x5D, + 0x89, 0x5E, 0xEE, 0x24, 0x22, 0x47, 0xE5, 0xE5, 0xF1, 0x86, 0x99, 0x67, 0x08, 0x28, 0x42, 0xF0, + 0x58, 0x62, 0x54, 0xC6, 0x5B, 0xDC, 0xE6, 0x80, 0x85, 0x6F, 0xE2, 0x72, 0xB9, 0x7E, 0x36, 0x64, + 0x48, 0x85, 0x10, 0xA4, 0x75, 0x38, 0x79, 0x76, 0x8B, 0x51, 0xD5, 0x87, 0xC3, 0x02, 0xC9, 0x1B, + 0x93, 0x22, 0x49, 0xEA, 0xAB, 0xA0, 0xB5, 0xB1, 0x3C, 0x10, 0xC4, 0x71, 0xF0, 0xF1, 0x81, 0x1A, + 0x3A, 0x9C, 0xFC, 0x51, 0x61, 0xB1, 0x4B, 0x18, 0xB2, 0x3D, 0xAA, 0xD6, 0xAC, 0x72, 0x26, 0xB7 +}; + +static const uint8_t dev_pkc_modulus[0x100] = { + 0x37, 0x84, 0x14, 0xB3, 0x78, 0xA4, 0x7F, 0xD8, 0x71, 0x45, 0xCD, 0x90, 0x51, 0x51, 0xBF, 0x2C, + 0x27, 0x03, 0x30, 0x46, 0xBE, 0x8F, 0x99, 0x3E, 0x9F, 0x36, 0x4D, 0xEB, 0xF7, 0x0E, 0x81, 0x7F, + 0xE4, 0x6B, 0xA8, 0x42, 0x8A, 0xA5, 0x4F, 0x76, 0xCC, 0xCB, 0xC5, 0x31, 0xA8, 0x5A, 0x70, 0x51, + 0x34, 0xBF, 0x1E, 0x8D, 0x6E, 0xCF, 0x05, 0x84, 0xCF, 0x8B, 0xE5, 0x9C, 0x3A, 0xA5, 0xCD, 0x1A, + 0x9C, 0xAC, 0x59, 0x30, 0x09, 0x21, 0x3C, 0xBE, 0x07, 0x5C, 0x8D, 0x1C, 0xD1, 0xA3, 0xC9, 0x8F, + 0x26, 0xE2, 0x99, 0xB2, 0x3C, 0x28, 0xAD, 0x63, 0x0F, 0xF5, 0xA0, 0x1C, 0xA2, 0x34, 0xC4, 0x0E, + 0xDB, 0xD7, 0xE1, 0xA9, 0x5E, 0xE9, 0xA5, 0xA8, 0x64, 0x3A, 0xFC, 0x48, 0xB5, 0x97, 0xDF, 0x55, + 0x7C, 0x9A, 0xD2, 0x8C, 0x32, 0x36, 0x1D, 0xC5, 0xA0, 0xC5, 0x66, 0xDF, 0x8A, 0xAD, 0x76, 0x18, + 0x46, 0x3E, 0xDF, 0xD8, 0xEF, 0xB9, 0xE5, 0xDC, 0xCD, 0x08, 0x59, 0xBC, 0x36, 0x68, 0xD6, 0xFC, + 0x3F, 0xFA, 0x11, 0x00, 0x0D, 0x50, 0xE0, 0x69, 0x0F, 0x70, 0x78, 0x7E, 0xD1, 0xA5, 0x85, 0xCD, + 0x13, 0xBC, 0x42, 0x74, 0x33, 0x0C, 0x11, 0x24, 0x1E, 0x33, 0xD5, 0x31, 0xB7, 0x3E, 0x48, 0x94, + 0xCC, 0x81, 0x29, 0x1E, 0xB1, 0xCF, 0x4C, 0x36, 0x7F, 0xE1, 0x1C, 0x15, 0xD4, 0x3F, 0xFB, 0x12, + 0xC2, 0x73, 0x22, 0x16, 0x52, 0xE0, 0x5C, 0x4C, 0x94, 0xE0, 0x87, 0x47, 0xEA, 0xD0, 0x9F, 0x42, + 0x9B, 0xAC, 0xB6, 0xB5, 0xB6, 0x34, 0xE4, 0x55, 0x49, 0xD7, 0xC0, 0xAE, 0xD4, 0x22, 0xB3, 0x5C, + 0x87, 0x64, 0x42, 0xEC, 0x11, 0x6D, 0xBC, 0x09, 0xC0, 0x80, 0x07, 0xD0, 0xBD, 0xBA, 0x45, 0xFE, + 0xD5, 0x52, 0xDA, 0xEC, 0x41, 0xA4, 0xAD, 0x7B, 0x36, 0x86, 0x18, 0xB4, 0x5B, 0xD1, 0x30, 0xBB +}; + static int exosphere_ini_handler(void *user, const char *section, const char *name, const char *value) { exosphere_config_t *exo_cfg = (exosphere_config_t *)user; int tmp = 0; @@ -277,8 +320,6 @@ uint32_t nxboot_main(void) { void *warmboot_memaddr; void *package1loader; size_t package1loader_size; - package1_header_t *package1; - size_t package1_size; uint32_t available_revision; FILE *boot0, *pk2file; void *exosphere_memaddr; @@ -403,7 +444,7 @@ uint32_t nxboot_main(void) { nxboot_set_bootreason(); } - /* Read the warmboot firmware from a file, otherwise from PK1. */ + /* Read the warmboot firmware from a file, otherwise from Atmosphere's implementation. */ if (loader_ctx->warmboot_path[0] != '\0') { warmboot_fw_size = get_file_size(loader_ctx->warmboot_path); if (warmboot_fw_size == 0) { @@ -420,30 +461,34 @@ uint32_t nxboot_main(void) { fatal_error("[NXBOOT]: Could not read the warmboot firmware from %s!\n", loader_ctx->warmboot_path); } } else { - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { - /* Package1 was decrypted during TSEC emulation. */ - const uint8_t *package1_hdr = (const uint8_t *)package1loader + 0x7000 - 0x20; - package1 = (package1_header_t *)(package1_hdr + 0x20); - package1_size = *(uint32_t *)package1_hdr; - warmboot_fw = package1_get_warmboot_fw(package1); - warmboot_fw_size = package1->warmboot_size; - } else { - /* Decrypt package1 and extract the warmboot firmware. */ - uint8_t ctr[16]; - package1_size = package1_get_encrypted_package1(&package1, ctr, package1loader, package1loader_size); - if (package1_decrypt(package1, package1_size, ctr)) { - warmboot_fw = package1_get_warmboot_fw(package1); - warmboot_fw_size = package1->warmboot_size; - } else { - warmboot_fw = NULL; - warmboot_fw_size = 0; - } + /* Use Atmosphere's warmboot firmware implementation. */ + warmboot_fw_size = lp0fw_bin_size; + warmboot_fw = malloc(warmboot_fw_size); + + if (warmboot_fw == NULL) { + fatal_error("[NXBOOT]: Out of memory!\n"); } + memcpy(warmboot_fw, lp0fw_bin, warmboot_fw_size); + if (warmboot_fw_size == 0) { fatal_error("[NXBOOT]: Could not read the warmboot firmware from Package1!\n"); } } + + /* Patch warmboot firmware for atmosphere. */ + if (warmboot_fw != NULL && warmboot_fw_size >= sizeof(warmboot_ams_header_t)) { + warmboot_ams_header_t *ams_header = (warmboot_ams_header_t *)warmboot_fw; + if (ams_header->ams_metadata.magic == WARMBOOT_MAGIC) { + /* Set target firmware */ + ams_header->ams_metadata.target_firmware = target_firmware; + + /* Set RSA modulus */ + const uint8_t *pkc_modulus = fuse_get_retail_type() != 0 ? retail_pkc_modulus : dev_pkc_modulus; + memcpy(ams_header->rsa_modulus, pkc_modulus, sizeof(ams_header->rsa_modulus)); + } + } + /* Select the right address for the warmboot firmware. */ if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { From a52e601f2e99023e852d4910f6114264b02308b2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 02:50:13 -0800 Subject: [PATCH 349/489] exosphere: Add support for rebooting to a payload in IRAM. --- exosphere/src/configitem.c | 27 ++++++++++++++++++++------- exosphere/src/configitem.h | 6 +++++- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 66a98730a..2ccd56b06 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -35,13 +35,26 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { case CONFIGITEM_BATTERYPROFILE: g_battery_profile = (value != 0); break; - case CONFIGITEM_NEEDS_REBOOT_TO_RCM: + case CONFIGITEM_NEEDS_REBOOT: /* Force a reboot to RCM, if requested. */ - if (value != 0) { - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; - while (1) { } + switch (value) { + case REBOOT_KIND_NO_REBOOT: + return 0; + case REBOOT_KIND_TO_RCM: + /* Set reboot kind = rcm. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; + break; + case REBOOT_KIND_TO_WB_PAYLOAD: + /* Set reboot kind = warmboot. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1; + /* Patch bootrom to jump to payload. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x118) = 0x40010000; /* Return to start of payload. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x11C) = 0x4000FFA4; /* Overwrite bootrom return address on stack. */ + break; + default: + return 2; } + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; break; default: return 2; @@ -187,8 +200,8 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) ((uint64_t)(exosphere_get_target_firmware() & 0xFF) << 8ull) | ((uint64_t)(mkey_get_revision() & 0xFF) << 0ull); break; - case CONFIGITEM_NEEDS_REBOOT_TO_RCM: - /* UNOFFICIAL: The fact that we are executing means we aren't in the process of rebooting to rcm. */ + case CONFIGITEM_NEEDS_REBOOT: + /* UNOFFICIAL: The fact that we are executing means we aren't in the process of rebooting. */ *p_outvalue = 0; break; default: diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index df54c5740..26b54c67f 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -41,9 +41,13 @@ typedef enum { /* These are unofficial, for usage by Exosphere. */ CONFIGITEM_EXOSPHERE_VERSION = 65000, - CONFIGITEM_NEEDS_REBOOT_TO_RCM = 65001, + CONFIGITEM_NEEDS_REBOOT = 65001, } ConfigItem; +#define REBOOT_KIND_NO_REBOOT 0 +#define REBOOT_KIND_TO_RCM 1 +#define REBOOT_KIND_TO_WB_PAYLOAD 2 + uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value); uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue); From 295574740d8c3b362bfba9865b7bee8c1dbc3fb2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 02:51:27 -0800 Subject: [PATCH 350/489] exosphere: improve nested switch format --- exosphere/src/configitem.c | 39 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 2ccd56b06..3065bc6f4 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -36,25 +36,28 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { g_battery_profile = (value != 0); break; case CONFIGITEM_NEEDS_REBOOT: - /* Force a reboot to RCM, if requested. */ - switch (value) { - case REBOOT_KIND_NO_REBOOT: - return 0; - case REBOOT_KIND_TO_RCM: - /* Set reboot kind = rcm. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; - break; - case REBOOT_KIND_TO_WB_PAYLOAD: - /* Set reboot kind = warmboot. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1; - /* Patch bootrom to jump to payload. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x118) = 0x40010000; /* Return to start of payload. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x11C) = 0x4000FFA4; /* Overwrite bootrom return address on stack. */ - break; - default: - return 2; + /* Force a reboot, if requested. */ + { + switch (value) { + case REBOOT_KIND_NO_REBOOT: + return 0; + case REBOOT_KIND_TO_RCM: + /* Set reboot kind = rcm. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x2; + break; + case REBOOT_KIND_TO_WB_PAYLOAD: + /* Set reboot kind = warmboot. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1; + /* Patch bootrom to jump to payload. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x118) = 0x40010000; /* Return to start of payload. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x11C) = 0x4000FFA4; /* Overwrite bootrom return address on stack. */ + break; + default: + return 2; + } + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; + while (1) { } } - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; break; default: return 2; From eeef08e58e24d2ca37c6d54c954ab35fe9f78ca6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 03:10:45 -0800 Subject: [PATCH 351/489] exo: ensure IRAM initialization. --- exosphere/src/configitem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 3065bc6f4..eb080ede2 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -49,8 +49,10 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { /* Set reboot kind = warmboot. */ MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1; /* Patch bootrom to jump to payload. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x118) = 0x40010000; /* Return to start of payload. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x11C) = 0x4000FFA4; /* Overwrite bootrom return address on stack. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x630ull) = 0x0010171B; /* Return to bootrom IRAM initialization func. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x4000FFA4; /* Overwrite bootrom return address on stack. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x40010000; /* Return to start of payload. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x63Cull) = 0x4000FFB4; /* Overwrite bootrom return address on stack. */ break; default: return 2; From deb124138b64041b9daef9a52decacc5c973cb84 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 05:05:24 -0800 Subject: [PATCH 352/489] exosphere: Implement smc_ams_iram_copy --- exosphere/src/memory_map.h | 10 ++- exosphere/src/mmu.h | 4 ++ exosphere/src/smc_ams.c | 136 +++++++++++++++++++++++++++++++++++-- 3 files changed, 141 insertions(+), 9 deletions(-) diff --git a/exosphere/src/memory_map.h b/exosphere/src/memory_map.h index c40eadbab..50bd32c7b 100644 --- a/exosphere/src/memory_map.h +++ b/exosphere/src/memory_map.h @@ -48,7 +48,9 @@ #define _MMAPDEV15 ( 0x6000D000ull, 0x1000ull, true ) /* GPIO-1 - GPIO-8 */ #define _MMAPDEV16 ( 0x7000C000ull, 0x1000ull, true ) /* I2C-I2C4 */ #define _MMAPDEV17 ( 0x6000F000ull, 0x1000ull, true ) /* Exception vectors */ -#define _MMAPDEV18 ( 0x40038000ull, 0x8000ull, true ) /* DEBUG: IRAM */ +#define _MMAPDEV18 ( 0x00000000ull, 0x1000ull, true ) /* AMS irampage, NOT mapped at startup */ +#define _MMAPDEV19 ( 0x00000000ull, 0x1000ull, true ) /* AMS userpage, NOT mapped at startup */ +#define _MMAPDEV20 ( 0x40038000ull, 0x5000ull, true ) /* DEBUG: IRAM */ /* LP0 entry ram segments (addr, size, additional attributes) */ #define _MMAPLP0ES0 ( 0x40020000ull, 0x10000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted TZRAM */ @@ -108,8 +110,10 @@ #define MMIO_DEVID_GPIO 15 #define MMIO_DEVID_DTV_I2C234 16 #define MMIO_DEVID_EXCEPTION_VECTORS 17 -#define MMIO_DEVID_DEBUG_IRAM 18 -#define MMIO_DEVID_MAX 19 +#define MMIO_DEVID_AMS_IRAM_PAGE 18 +#define MMIO_DEVID_AMS_USER_PAGE 19 +#define MMIO_DEVID_DEBUG_IRAM 20 +#define MMIO_DEVID_MAX 21 #define LP0_ENTRY_RAM_SEGMENT_ID_ENCRYPTED_TZRAM 0 #define LP0_ENTRY_RAM_SEGMENT_ID_LP0_ENTRY_CODE 1 diff --git a/exosphere/src/mmu.h b/exosphere/src/mmu.h index 2b41db321..a85569308 100644 --- a/exosphere/src/mmu.h +++ b/exosphere/src/mmu.h @@ -165,6 +165,10 @@ static inline void mmu_unmap(unsigned int level, uintptr_t *tbl, uintptr_t base_ tbl[mmu_compute_index(level, base_addr)] = MMU_PTE_TYPE_FAULT; } +static inline void mmu_unmap_page(uintptr_t *tbl, uintptr_t base_addr) { + tbl[mmu_compute_index(3, base_addr)] = MMU_PTE_TYPE_FAULT; +} + static inline void mmu_map_block_range(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, size_t size, uint64_t attrs) { size = ((size + (BITL(MMU_Lx_SHIFT(level)) - 1)) >> MMU_Lx_SHIFT(level)) << MMU_Lx_SHIFT(level); for(size_t offset = 0; offset < size; offset += BITL(MMU_Lx_SHIFT(level))) { diff --git a/exosphere/src/smc_ams.c b/exosphere/src/smc_ams.c index 98e10146b..08e220f3d 100644 --- a/exosphere/src/smc_ams.c +++ b/exosphere/src/smc_ams.c @@ -14,20 +14,144 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stdatomic.h> #include <stdbool.h> #include <stdint.h> #include <string.h> #include "utils.h" -#include "smc_api.h" #include "smc_ams.h" +#include "arm.h" +#include "synchronization.h" +#include "memory_map.h" +#include "mmu.h" + +static atomic_flag g_ams_userpage_mapped = ATOMIC_FLAG_INIT; +static atomic_flag g_ams_iram_page_mapped = ATOMIC_FLAG_INIT; + +static inline uintptr_t get_ams_user_page_secure_monitor_addr(void) { + return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_USER_PAGE); +} + +static inline uintptr_t get_ams_iram_page_secure_monitor_addr(void) { + return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE); +} + +#define AMS_USER_PAGE_SECURE_MONITOR_ADDR (get_ams_user_page_secure_monitor_addr()) +#define AMS_IRAM_PAGE_SECURE_MONITOR_ADDR (get_ams_iram_page_secure_monitor_addr()) + + +static inline uintptr_t get_page_for_address(void *address) { + return ((uintptr_t)(address)) & ~0xFFFULL; +} + +static bool ams_is_user_addr_valid(uintptr_t user_address) { + /* Check that the address is in dram. */ + uintptr_t page_address = get_page_for_address((void *)user_address); + return (page_address - 0x80000000ull) < (6ull << 30); +} + +static bool ams_is_iram_addr_valid(uintptr_t iram_address) { + /* Check that the address is in iram. */ + return 0x40000000ULL <= iram_address && iram_address <= 0x4003FFFFULL; +} + +static void ams_map_userpage(uintptr_t user_address) { + lock_acquire(&g_ams_userpage_mapped); + static const uint64_t userpage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_NORMAL; + uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + mmu_map_page(mmu_l3_tbl, AMS_USER_PAGE_SECURE_MONITOR_ADDR, get_page_for_address((void *)user_address), userpage_attributes); + tlb_invalidate_page_inner_shareable((void *)AMS_USER_PAGE_SECURE_MONITOR_ADDR); +} + +static void ams_unmap_userpage(void) { + uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + mmu_unmap_page(mmu_l3_tbl, AMS_USER_PAGE_SECURE_MONITOR_ADDR); + tlb_invalidate_page_inner_shareable((void *)AMS_USER_PAGE_SECURE_MONITOR_ADDR); + lock_release(&g_ams_userpage_mapped); +} + +static void ams_map_irampage(uintptr_t iram_address) { + lock_acquire(&g_ams_iram_page_mapped); + static const uint64_t irampage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_DEVICE; + uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + mmu_map_page(mmu_l3_tbl, AMS_IRAM_PAGE_SECURE_MONITOR_ADDR, get_page_for_address((void *)iram_address), irampage_attributes); + tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); +} + +static void ams_unmap_irampage(void) { + uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); + mmu_unmap_page(mmu_l3_tbl, AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); + tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); + lock_release(&g_ams_iram_page_mapped); +} uint32_t ams_iram_copy(smc_args_t *args) { - /* TODO: Implement a DRAM <-> IRAM copy of up to one page here. */ + /* Implements a DRAM <-> IRAM copy of up to one page. */ /* This operation is necessary to implement reboot-to-payload. */ - /* args->X[1] = DRAM address (translated by kernel). */ - /* args->X[2] = IRAM address. */ - /* args->X[3] = size (must be <= 0x1000). */ + /* args->X[1] = DRAM address (translated by kernel), must be 4-byte aligned. */ + /* args->X[2] = IRAM address, must be 4-byte aligned. */ + /* args->X[3] = size (must be <= 0x1000 and 4-byte aligned). */ /* args->X[4] = 0 for read, 1 for write. */ - return 2; + + const uintptr_t dram_address = (uintptr_t)args->X[1]; + const uintptr_t iram_address = (uintptr_t)args->X[2]; + const uintptr_t dram_page_offset = (dram_address & 0xFFFULL); + const uintptr_t iram_page_offset = (iram_address & 0xFFFULL); + const size_t size = args->X[3]; + const uint32_t option = (uint32_t)args->X[4]; + + /* Validate addresses. */ + if (!ams_is_user_addr_valid(dram_address) || !ams_is_iram_addr_valid(iram_address)) { + return 2; + } + + /* Validate size. */ + if (size > 0x1000 || (size + dram_page_offset) > 0x1000 || (size + iram_page_offset) > 0x1000) { + return 2; + } + + /* Validate alignment. */ + if (size % sizeof(uint32_t) || dram_page_offset % sizeof(uint32_t) || iram_page_offset % sizeof(uint32_t)) { + return 2; + } + + /* Validate argument. */ + if (option != 0 && option != 1) { + return 2; + } + + /* Map pages. */ + ams_map_userpage(dram_address); + ams_map_irampage(iram_address); + + /* Set source/destination for copy. */ + volatile uint32_t *dram_ptr = (volatile uint32_t *)(AMS_USER_PAGE_SECURE_MONITOR_ADDR + dram_page_offset); + volatile uint32_t *iram_ptr = (volatile uint32_t *)(AMS_IRAM_PAGE_SECURE_MONITOR_ADDR + iram_page_offset); + + volatile uint32_t *dst; + volatile uint32_t *src; + const size_t num_dwords = size / sizeof(uint32_t); + if (option == 0) { + dst = dram_ptr; + src = iram_ptr; + } else { + dst = iram_ptr; + src = dram_ptr; + } + + /* Actually copy data. */ + for (size_t i = 0; i < num_dwords; i++) { + dst[i] = src[i]; + } + + /* Flush! */ + flush_dcache_range((void *)dst, (void *)(dst + num_dwords)); + + /* Unmap pages. */ + ams_unmap_irampage(); + ams_unmap_userpage(); + + return 0; } From b6684ff84519bb95c34f68ccaf68134964547a18 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 15:59:09 -0800 Subject: [PATCH 353/489] sm: Add sm:dmnt query extension --- docs/modules/sm.md | 56 +++++++++++++++++++ stratosphere/sm/source/sm_dmnt_service.cpp | 33 +++++++++++ stratosphere/sm/source/sm_dmnt_service.hpp | 40 +++++++++++++ stratosphere/sm/source/sm_main.cpp | 12 ++++ stratosphere/sm/source/sm_manager_service.hpp | 1 - stratosphere/sm/source/sm_registration.cpp | 48 ++++++++++++++++ stratosphere/sm/source/sm_registration.hpp | 6 ++ stratosphere/sm/source/sm_types.hpp | 15 ++++- 8 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 stratosphere/sm/source/sm_dmnt_service.cpp create mode 100644 stratosphere/sm/source/sm_dmnt_service.hpp diff --git a/docs/modules/sm.md b/docs/modules/sm.md index 8852975f8..4d04fe3cf 100644 --- a/docs/modules/sm.md +++ b/docs/modules/sm.md @@ -20,6 +20,18 @@ interface nn::sm::detail::IUserInterface is sm: { } ``` +Additionally, an interface `sm:dmnt` has been created to allow a debug monitor to query sm's state. + +Its SwIPC definition follows. +``` +interface nn::sm::detail::IDebugMonitorInterface is sm:dmnt { + [65000] AtmosphereGetServiceRecord(ServiceName name) -> SmServiceRecord; + [65001] AtmosphereListServiceRecords(u64 offset) -> buffer<SmServiceRecord, 6>, u64 count; + [65002] AtmosphereGetServiceRecordSize() -> u64 record_size; +} +``` + + #### AtmosphereInstallMitm This command alters the registration for the named service, in order to allow services to intercept communication between client processes and their intended services. It is used by [fs_mitm](fs_mitm.md). @@ -58,6 +70,50 @@ This command is used internally by the Stratosphere implementation of the [loade If the given process ID refers to a kernel internal process, error code 0x1015 is returned. This command requires that the session be initialized, returning error code 0x415 if it is not. +#### AtmosphereGetServiceRecordSize + +Retrieves `sizeof(SmServiceRecord)` for a service. The current format of `SmServiceRecord` structure follows. + +``` +struct SmServiceRecord { + uint64_t service_name; + uint64_t owner_pid; + uint64_t max_sessions; + uint64_t mitm_pid; + uint64_t mitm_waiting_ack_pid; + bool is_light; + bool mitm_waiting_ack; +}; +``` + +#### AtmosphereGetServiceRecord + +Retrieves a service registration record for a service. + +#### AtmosphereListServiceRecords + +Provides a list of service registrations records. + +The command will return an array of `SmServiceRecord`s, skipping `offset` records. The number of records returned is indicated by `count`. +If `count` is less than the size of the buffer divided by `sizeof(SmServiceRecord)` (the buffer was not completely filled), the end of the service registration list has been reached. Otherwise, client code +should increment `offset` by `count` and call again. Client code should retrieve a record size using `AtmosphereGetServiceRecordSize`, and either make sure that the size of a record matches what it expects, +or should make sure to use the correct size as the stride while iterating over the array of returned records. Example pseudocode is shown below. + +``` +offset = 0; +record_size = AtmosphereGetServiceRecordSize(); +do { + SmServiceRecord records[16]; + count = AtmosphereListServiceRecords(offset, buffer(records)); + for (i = 0; i < count; i++) { + SmServiceRecord record = {0}; + memcpy(&record, &records[i], min(record_size, sizeof(SmServiceRecord)); + /* process record */ + offset++; + } +} while(count == sizeof(records) / record_size); +``` + ### Minimum Session Limit When a service is registered, the sysmodule registering it must specify a limit on the number of sessions that are allowed to be active for that service at a time. This is used to ensure that services like `fs-pr`, `fs-ldr`, and `ldr:pm` can only be connected to once, adding an additional layer of safety over the regular service verification to ensure that those services are only connected to by the highly priveleged process they are intended to be used by. diff --git a/stratosphere/sm/source/sm_dmnt_service.cpp b/stratosphere/sm/source/sm_dmnt_service.cpp new file mode 100644 index 000000000..5428ab7a7 --- /dev/null +++ b/stratosphere/sm/source/sm_dmnt_service.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include "sm_dmnt_service.hpp" +#include "sm_registration.hpp" + +Result DmntService::AtmosphereGetRecord(Out<SmServiceRecord> record, SmServiceName service) { + return Registration::GetServiceRecord(smEncodeName(service.name), record.GetPointer()); +} + +void DmntService::AtmosphereListRecords(OutBuffer<SmServiceRecord> records, Out<u64> out_count, u64 offset) { + Registration::ListServiceRecords(offset, records.num_elements, records.buffer, out_count.GetPointer()); +} + +void DmntService::AtmosphereGetRecordSize(Out<u64> record_size) { + record_size.SetValue(sizeof(SmServiceRecord)); +} + diff --git a/stratosphere/sm/source/sm_dmnt_service.hpp b/stratosphere/sm/source/sm_dmnt_service.hpp new file mode 100644 index 000000000..66a71d728 --- /dev/null +++ b/stratosphere/sm/source/sm_dmnt_service.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> +#include "sm_types.hpp" + +enum DmntServiceCmd { + Dmnt_Cmd_AtmosphereGetRecord = 65000, + Dmnt_Cmd_AtmosphereListRecords = 65001, + Dmnt_Cmd_AtmosphereGetRecordSize = 65002, +}; + +class DmntService final : public IServiceObject { + private: + /* Actual commands. */ + virtual Result AtmosphereGetRecord(Out<SmServiceRecord> record, SmServiceName service); + virtual void AtmosphereListRecords(OutBuffer<SmServiceRecord> records, Out<u64> out_count, u64 offset); + virtual void AtmosphereGetRecordSize(Out<u64> record_size); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetRecord, &DmntService::AtmosphereGetRecord>(), + MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereListRecords, &DmntService::AtmosphereListRecords>(), + MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetRecordSize, &DmntService::AtmosphereGetRecordSize>(), + }; +}; diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index 60ceb3c45..f97c34283 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -24,6 +24,7 @@ #include "sm_manager_service.hpp" #include "sm_user_service.hpp" +#include "sm_dmnt_service.hpp" #include "sm_registration.hpp" extern "C" { @@ -82,6 +83,17 @@ int main(int argc, char **argv) } server_manager->AddWaitable(new ExistingPortServer<ManagerService>(smm_h, 1)); + + /*===== ATMOSPHERE EXTENSION =====*/ + /* Create sm:dmnt manually. */ + Handle smdmnt_h; + if (R_FAILED(Registration::RegisterServiceForSelf(smEncodeName("sm:dmnt"), 1, false, &smdmnt_h))) { + /* TODO: Panic. */ + while (1) { } + } + + server_manager->AddWaitable(new ExistingPortServer<DmntService>(smm_h, 1));; + /*================================*/ /* Loop forever, servicing our services. */ server_manager->Process(); diff --git a/stratosphere/sm/source/sm_manager_service.hpp b/stratosphere/sm/source/sm_manager_service.hpp index 454be7edb..bb71e58b6 100644 --- a/stratosphere/sm/source/sm_manager_service.hpp +++ b/stratosphere/sm/source/sm_manager_service.hpp @@ -23,7 +23,6 @@ enum ManagerServiceCmd { Manager_Cmd_RegisterProcess = 0, Manager_Cmd_UnregisterProcess = 1, - Manager_Cmd_AtmosphereEndInitDefers = 65000, Manager_Cmd_AtmosphereHasMitm = 65001, }; diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index 3401f800f..c9957e315 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -562,3 +562,51 @@ Result Registration::AssociatePidTidForMitm(u64 pid, u64 tid) { } return 0x0; } + +void Registration::ConvertServiceToRecord(Registration::Service *service, SmServiceRecord *record) { + record->service_name = service->service_name; + record->owner_pid = service->owner_pid; + record->max_sessions = service->max_sessions; + record->mitm_pid = service->mitm_pid; + record->mitm_waiting_ack_pid = service->mitm_waiting_ack_pid; + record->is_light = service->is_light; + record->mitm_waiting_ack = service->mitm_waiting_ack; +} + +Result Registration::GetServiceRecord(u64 service, SmServiceRecord *out) { + if (!service) { + return 0xC15; + } + + u64 service_name_len = GetServiceNameLength(service); + + /* If the service has bytes after a null terminator, that's no good. */ + if (service_name_len != 8 && (service >> (8 * service_name_len))) { + return 0xC15; + } + + Registration::Service *target_service = GetService(service); + if (target_service == NULL) { + return 0xE15; + } + + ConvertServiceToRecord(target_service, out); + return 0x0; +} + +void Registration::ListServiceRecords(u64 offset, u64 max_out, SmServiceRecord *out, u64 *out_count) { + u64 count = 0; + + for (auto it = g_service_list.begin(); it != g_service_list.end() && count < max_out; it++) { + if (it->service_name != 0) { + if (offset > 0) { + offset--; + } else { + ConvertServiceToRecord(it, out++); + count++; + } + } + } + + *out_count = count; +} diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 8c4d72660..7d7ef5961 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -17,6 +17,8 @@ #pragma once #include <switch.h> +#include "sm_types.hpp" + #define REGISTRATION_LIST_MAX_PROCESS (0x40) #define REGISTRATION_LIST_MAX_SERVICE (0x100) #define REGISTRATION_MAX_SAC_SIZE (0x200) @@ -81,4 +83,8 @@ class Registration { static Result UninstallMitmForPid(u64 pid, u64 service); static Result AcknowledgeMitmSessionForPid(u64 pid, u64 service, Handle *out, u64 *out_pid); static Result AssociatePidTidForMitm(u64 pid, u64 tid); + + static void ConvertServiceToRecord(Registration::Service *service, SmServiceRecord *record); + static Result GetServiceRecord(u64 service, SmServiceRecord *out); + static void ListServiceRecords(u64 offset, u64 max_out, SmServiceRecord *out, u64 *out_count); }; diff --git a/stratosphere/sm/source/sm_types.hpp b/stratosphere/sm/source/sm_types.hpp index 6ac9bce92..a8e0453a1 100644 --- a/stratosphere/sm/source/sm_types.hpp +++ b/stratosphere/sm/source/sm_types.hpp @@ -19,4 +19,17 @@ struct SmServiceName { char name[sizeof(u64)]; }; -static_assert(__alignof__(SmServiceName) == 1, "SmServiceName definition!"); \ No newline at end of file +static_assert(__alignof__(SmServiceName) == 1, "SmServiceName definition!"); + +/* For Debug Monitor extensions. */ +struct SmServiceRecord { + u64 service_name; + u64 owner_pid; + u64 max_sessions; + u64 mitm_pid; + u64 mitm_waiting_ack_pid; + bool is_light; + bool mitm_waiting_ack; +}; + +static_assert(sizeof(SmServiceRecord) == 0x30, "SmServiceRecord definition!"); \ No newline at end of file From 83025080c89deb575d0e72d55a0e335ab7c00f1c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 17:00:35 -0800 Subject: [PATCH 354/489] sm: change InstallMitM to wait for registration instead of 0xE15 --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 13 ++++++++----- stratosphere/libstratosphere | 2 +- stratosphere/pm/source/pm_boot2.cpp | 8 ++++++-- stratosphere/set_mitm/source/setmitm_main.cpp | 15 +++++++++------ stratosphere/sm/source/sm_registration.cpp | 2 +- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 24fa8b647..40808a34c 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -62,11 +62,6 @@ void __appInit(void) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); } - rc = fsInitialize(); - if (R_FAILED(rc)) { - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); - } - CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } @@ -94,6 +89,14 @@ int main(int argc, char **argv) /* Create fsp-srv mitm. */ AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); + + /* Connect to FS */ + { + Result rc = fsInitialize(); + if (R_FAILED(rc)) { + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); + } + } if (R_FAILED(threadCreate(&sd_initializer_thread, &Utils::InitializeSdThreadFunc, NULL, 0x4000, 0x15, 0))) { /* TODO: Panic. */ diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 05015b935..f9d38856f 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 05015b9354d3df80e0836aa95d1d4dcfc2aef4b7 +Subproject commit f9d38856f335c4cb0ed3c7253d9319a965815af2 diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 864f2d9ff..5a88f10bb 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -123,8 +123,7 @@ static void MountSdCard() { fsdevMountSdmc(); } -void EmbeddedBoot2::Main() { - /* Wait until fs.mitm has installed itself. We want this to happen as early as possible. */ +static void WaitForFsMitm() { bool fs_mitm_installed = false; Result rc = smManagerAmsInitialize(); @@ -138,6 +137,11 @@ void EmbeddedBoot2::Main() { svcSleepThread(1000ull); } smManagerAmsExit(); +} + +void EmbeddedBoot2::Main() { + /* Wait until fs.mitm has installed itself. We want this to happen as early as possible. */ + WaitForFsMitm(); /* psc, bus, pcv is the minimal set of required titles to get SD card. */ /* bus depends on pcie, and pcv depends on settings. */ diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/set_mitm/source/setmitm_main.cpp index 0a7b0a295..3fea764dd 100644 --- a/stratosphere/set_mitm/source/setmitm_main.cpp +++ b/stratosphere/set_mitm/source/setmitm_main.cpp @@ -60,11 +60,6 @@ void __appInit(void) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); } - rc = setsysInitialize(); - if (R_FAILED(rc)) { - fatalSimple(rc); - } - CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } @@ -89,8 +84,16 @@ int main(int argc, char **argv) /* TODO: What's a good timeout value to use here? */ auto server_manager = new SetMitmManager(1); - /* Create fsp-srv mitm. */ + /* Create set:sys mitm. */ AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 4); + + /* Connect to set:sys. */ + { + Result rc = setsysInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + } /* Loop forever, servicing our services. */ server_manager->Process(); diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index c9957e315..33fcc6eec 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -467,7 +467,7 @@ Result Registration::InstallMitmForPid(u64 pid, u64 service, Handle *out, Handle /* Verify the service exists. */ Registration::Service *target_service = GetService(service); if (target_service == NULL) { - return 0xE15; + return RESULT_DEFER_SESSION; } /* Verify the service isn't already being mitm'd. */ From 260a819fd28d675a451eeede4839a9ae6a1fdfb5 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 17:04:44 -0800 Subject: [PATCH 355/489] sm: update mitm api docs for change --- docs/modules/sm.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/modules/sm.md b/docs/modules/sm.md index 4d04fe3cf..a71b7f107 100644 --- a/docs/modules/sm.md +++ b/docs/modules/sm.md @@ -52,11 +52,11 @@ The `AssociatePidTid` command is invoked on all MITM query sessions whenever a n If the process that installed the MITM attempts to connect to the service, it will always connect to the original service. -This command requires that the session be initialized, returning error code 0x415 if it is not. -If the given service name is invalid, error code 0xC15 is returned. -If the user does not have service registration permission for the named service, error code 0x1015 is returned. -If the service has not yet been registered, error code 0xE15 is returned. -If the service already has an MITM installed, error code 0x815 is returned. +This command requires that the session be initialized, returning error code 0x415 if it is not.\ +If the given service name is invalid, error code 0xC15 is returned.\ +If the user does not have service registration permission for the named service, error code 0x1015 is returned.\ +If the service already has an MITM installed, error code 0x815 is returned.\ +If the service has not yet been registered, the request will be deferred until the service is registered in the same manner as IUserInterface::GetService.\ #### AtmosphereUninstallMitm From 216555517066ccd9958ee5b07c1954eeea7d9d68 Mon Sep 17 00:00:00 2001 From: SciresM <Sciresm@gmail.com> Date: Sun, 20 Jan 2019 17:05:49 -0800 Subject: [PATCH 356/489] smdocs: remove extraneous \ --- docs/modules/sm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/sm.md b/docs/modules/sm.md index a71b7f107..79d5e800f 100644 --- a/docs/modules/sm.md +++ b/docs/modules/sm.md @@ -56,7 +56,7 @@ This command requires that the session be initialized, returning error code 0x41 If the given service name is invalid, error code 0xC15 is returned.\ If the user does not have service registration permission for the named service, error code 0x1015 is returned.\ If the service already has an MITM installed, error code 0x815 is returned.\ -If the service has not yet been registered, the request will be deferred until the service is registered in the same manner as IUserInterface::GetService.\ +If the service has not yet been registered, the request will be deferred until the service is registered in the same manner as IUserInterface::GetService. #### AtmosphereUninstallMitm From f61f5feaf4b2cdcc69fa5cd125186be25bd29982 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 22:21:49 -0800 Subject: [PATCH 357/489] pm: Launch set.mitm earlier in boot. --- stratosphere/pm/source/pm_boot2.cpp | 43 +++++++++++++++++++++++++---- stratosphere/pm/source/pm_boot2.hpp | 4 +++ stratosphere/pm/source/pm_main.cpp | 6 ++-- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 5a88f10bb..181fbb44d 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -26,6 +26,20 @@ #include "pm_boot2.hpp" #include "pm_registration.hpp" +static std::vector<Boot2KnownTitleId> g_boot2_titles; + +static void ClearLaunchedTitles() { + g_boot2_titles.clear(); +} + +static void SetLaunchedTitle(Boot2KnownTitleId title_id) { + g_boot2_titles.push_back(title_id); +} + +static bool HasLaunchedTitle(Boot2KnownTitleId title_id) { + return std::find(g_boot2_titles.begin(), g_boot2_titles.end(), title_id) != g_boot2_titles.end(); +} + static bool IsHexadecimal(const char *str) { while (*str) { if (isxdigit(*str)) { @@ -40,6 +54,11 @@ static bool IsHexadecimal(const char *str) { static void LaunchTitle(Boot2KnownTitleId title_id, FsStorageId storage_id, u32 launch_flags, u64 *pid) { u64 local_pid; + /* Don't launch a title twice during boot2. */ + if (HasLaunchedTitle(title_id)) { + return; + } + Result rc = Registration::LaunchProcessByTidSid(Registration::TidSid{(u64)title_id, storage_id}, launch_flags, &local_pid); switch (rc) { case 0xCE01: @@ -61,6 +80,10 @@ static void LaunchTitle(Boot2KnownTitleId title_id, FsStorageId storage_id, u32 if (pid) { *pid = local_pid; } + + if (R_SUCCEEDED(rc)) { + SetLaunchedTitle(title_id); + } } static bool ShouldForceMaintenanceMode() { @@ -123,25 +146,28 @@ static void MountSdCard() { fsdevMountSdmc(); } -static void WaitForFsMitm() { - bool fs_mitm_installed = false; +static void WaitForMitm(const char *service) { + bool mitm_installed = false; Result rc = smManagerAmsInitialize(); if (R_FAILED(rc)) { std::abort(); } - while (R_FAILED((rc = smManagerAmsHasMitm(&fs_mitm_installed, "fsp-srv"))) || !fs_mitm_installed) { + while (R_FAILED((rc = smManagerAmsHasMitm(&mitm_installed, service))) || !mitm_installed) { if (R_FAILED(rc)) { std::abort(); } - svcSleepThread(1000ull); + svcSleepThread(1000000ull); } smManagerAmsExit(); } void EmbeddedBoot2::Main() { /* Wait until fs.mitm has installed itself. We want this to happen as early as possible. */ - WaitForFsMitm(); + WaitForMitm("fsp-srv"); + + /* Clear titles. */ + ClearLaunchedTitles(); /* psc, bus, pcv is the minimal set of required titles to get SD card. */ /* bus depends on pcie, and pcv depends on settings. */ @@ -159,6 +185,10 @@ void EmbeddedBoot2::Main() { /* At this point, the SD card can be mounted. */ MountSdCard(); + /* Launch set:mitm, wait for it. */ + LaunchTitle(Boot2KnownTitleId::ams_set_mitm, FsStorageId_None, 0, NULL); + WaitForMitm("set:sys"); + /* Launch usb. */ LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); /* Launch tma. */ @@ -206,4 +236,7 @@ void EmbeddedBoot2::Main() { /* We no longer need the SD card. */ fsdevUnmountAll(); + + /* Clear titles. */ + ClearLaunchedTitles(); } diff --git a/stratosphere/pm/source/pm_boot2.hpp b/stratosphere/pm/source/pm_boot2.hpp index 44c4e1de1..7a0cd5dec 100644 --- a/stratosphere/pm/source/pm_boot2.hpp +++ b/stratosphere/pm/source/pm_boot2.hpp @@ -77,6 +77,10 @@ enum class Boot2KnownTitleId : u64 { jpegdec = 0x010000000000003CUL, safemode = 0x010000000000003DUL, olsc = 0x010000000000003EUL, + + + /* atmosphere extensions */ + ams_set_mitm = 0x0100000000000032UL, }; class EmbeddedBoot2 { diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index c38e7ec1b..42f72fdd4 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -148,15 +148,15 @@ void __appExit(void) { int main(int argc, char **argv) { - Thread process_track_thread = {0}; + HosThread process_track_thread; consoleDebugInit(debugDevice_SVC); /* Initialize and spawn the Process Tracking thread. */ Registration::InitializeSystemResources(); - if (R_FAILED(threadCreate(&process_track_thread, &ProcessTracking::MainLoop, NULL, 0x4000, 0x15, 0))) { + if (R_FAILED(process_track_thread.Initialize(&ProcessTracking::MainLoop, NULL, 0x4000, 0x15))) { /* TODO: Panic. */ } - if (R_FAILED(threadStart(&process_track_thread))) { + if (R_FAILED(process_track_thread.Start())) { /* TODO: Panic. */ } From 4711d0565d67d71a08d88ddc2208106640573ffc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 20 Jan 2019 23:13:16 -0800 Subject: [PATCH 358/489] set.mitm: mitm everything We still only lie about firmware version to qlaunch/maintenance. This is to prepare for loading settings off of the SD card. --- stratosphere/set_mitm/source/setmitm_main.cpp | 2 +- .../source/setsys_firmware_version.cpp | 55 +++++++++++++ .../source/setsys_firmware_version.hpp | 24 ++++++ .../set_mitm/source/setsys_mitm_service.cpp | 82 +++++++++++-------- .../set_mitm/source/setsys_mitm_service.hpp | 21 ++++- stratosphere/set_mitm/source/setsys_shim.c | 52 ++++++++++++ stratosphere/set_mitm/source/setsys_shim.h | 23 ++++++ 7 files changed, 222 insertions(+), 37 deletions(-) create mode 100644 stratosphere/set_mitm/source/setsys_firmware_version.cpp create mode 100644 stratosphere/set_mitm/source/setsys_firmware_version.hpp create mode 100644 stratosphere/set_mitm/source/setsys_shim.c create mode 100644 stratosphere/set_mitm/source/setsys_shim.h diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/set_mitm/source/setmitm_main.cpp index 3fea764dd..bfba144e4 100644 --- a/stratosphere/set_mitm/source/setmitm_main.cpp +++ b/stratosphere/set_mitm/source/setmitm_main.cpp @@ -85,7 +85,7 @@ int main(int argc, char **argv) auto server_manager = new SetMitmManager(1); /* Create set:sys mitm. */ - AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 4); + AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 60); /* Connect to set:sys. */ { diff --git a/stratosphere/set_mitm/source/setsys_firmware_version.cpp b/stratosphere/set_mitm/source/setsys_firmware_version.cpp new file mode 100644 index 000000000..b37c1726f --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_firmware_version.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <mutex> +#include <switch.h> + +#include "setsys_firmware_version.hpp" + +static HosMutex g_version_mutex; +static bool g_got_version = false; +static SetSysFirmwareVersion g_fw_version = {0}; + +Result VersionManager::GetFirmwareVersion(u64 title_id, SetSysFirmwareVersion *out) { + std::scoped_lock<HosMutex> lock(g_version_mutex); + if (!g_got_version) { + Result rc = setsysGetFirmwareVersion(&g_fw_version); + if (R_FAILED(rc)) { + return rc; + } + + /* Modify the output firmware version. */ + { + u32 major, minor, micro; + char display_version[sizeof(g_fw_version.display_version)] = {0}; + + GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); + snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro); + + memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version)); + } + + g_got_version = true; + } + + /* Report atmosphere string to qlaunch, maintenance and nothing else. */ + if (title_id == 0x0100000000001000ULL || title_id == 0x0100000000001015ULL) { + *out = g_fw_version; + return 0; + } else { + return setsysGetFirmwareVersion(out); + } +} \ No newline at end of file diff --git a/stratosphere/set_mitm/source/setsys_firmware_version.hpp b/stratosphere/set_mitm/source/setsys_firmware_version.hpp new file mode 100644 index 000000000..de035ed92 --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_firmware_version.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +class VersionManager { + public: + static Result GetFirmwareVersion(u64 title_id, SetSysFirmwareVersion *out); +}; diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.cpp b/stratosphere/set_mitm/source/setsys_mitm_service.cpp index 60e1c5e2c..33db6bef0 100644 --- a/stratosphere/set_mitm/source/setsys_mitm_service.cpp +++ b/stratosphere/set_mitm/source/setsys_mitm_service.cpp @@ -15,45 +15,17 @@ */ #include <mutex> +#include <algorithm> #include <switch.h> #include "setsys_mitm_service.hpp" - -static HosMutex g_version_mutex; -static bool g_got_version = false; -static SetSysFirmwareVersion g_fw_version = {0}; - -static Result _GetFirmwareVersion(SetSysFirmwareVersion *out) { - std::scoped_lock<HosMutex> lock(g_version_mutex); - if (!g_got_version) { - Result rc = setsysGetFirmwareVersion(&g_fw_version); - if (R_FAILED(rc)) { - return rc; - } - - /* Modify the output firmware version. */ - { - u32 major, minor, micro; - char display_version[sizeof(g_fw_version.display_version)] = {0}; - - GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); - snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro); - - memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version)); - } - - g_got_version = true; - } - - *out = g_fw_version; - return 0; -} +#include "setsys_firmware_version.hpp" void SetSysMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { /* No commands need postprocessing. */ } -Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { - Result rc = _GetFirmwareVersion(out.pointer); +Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { + Result rc = VersionManager::GetFirmwareVersion(this->title_id, out.pointer); /* GetFirmwareVersion sanitizes these fields. */ if (R_SUCCEEDED(rc)) { @@ -64,6 +36,48 @@ Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize<SetSysFirm return rc; } -Result SetSysMitmService::GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { - return _GetFirmwareVersion(out.pointer); +Result SetSysMitmService::GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out) { + return VersionManager::GetFirmwareVersion(this->title_id, out.pointer); +} + +Result SetSysMitmService::GetSettingsItemValueSize(Out<u64> out_size, InPointer<char> in_name, InPointer<char> in_key) { + char name[SET_MAX_NAME_SIZE] = {0}; + char key[SET_MAX_NAME_SIZE] = {0}; + + if (in_name.num_elements < SET_MAX_NAME_SIZE) { + strncpy(name, in_name.pointer, in_name.num_elements); + } else { + strncpy(name, in_name.pointer, SET_MAX_NAME_SIZE-1); + } + + if (in_key.num_elements < SET_MAX_NAME_SIZE) { + strncpy(key, in_key.pointer, in_key.num_elements); + } else { + strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1); + } + + return setsysGetSettingsItemValueSize(name, key, out_size.GetPointer()); +} + +Result SetSysMitmService::GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8> out_value, InPointer<char> in_name, InPointer<char> in_key) { + char name[SET_MAX_NAME_SIZE] = {0}; + char key[SET_MAX_NAME_SIZE] = {0}; + + if (in_name.num_elements < SET_MAX_NAME_SIZE) { + strncpy(name, in_name.pointer, in_name.num_elements); + } else { + strncpy(name, in_name.pointer, SET_MAX_NAME_SIZE-1); + } + + if (in_key.num_elements < SET_MAX_NAME_SIZE) { + strncpy(key, in_key.pointer, in_key.num_elements); + } else { + strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1); + } + + return setsysGetSettingsItemValue(name, key, out_value.buffer, out_value.num_elements); +} + +Result SetSysMitmService::GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out) { + return setsysGetEdidFwd(this->forward_service.get(), out.pointer); } \ No newline at end of file diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.hpp b/stratosphere/set_mitm/source/setsys_mitm_service.hpp index 65a172175..36d12e064 100644 --- a/stratosphere/set_mitm/source/setsys_mitm_service.hpp +++ b/stratosphere/set_mitm/source/setsys_mitm_service.hpp @@ -18,9 +18,17 @@ #include <switch.h> #include <stratosphere.hpp> +#include "setsys_shim.h" + enum SetSysCmd : u32 { SetSysCmd_GetFirmwareVersion = 3, SetSysCmd_GetFirmwareVersion2 = 4, + SetSysCmd_GetSettingsItemValueSize = 37, + SetSysCmd_GetSettingsItemValue = 38, + + /* Commands for which set:sys *must* act as a passthrough. */ + /* TODO: Solve the relevant IPC detection problem. */ + SetSysCmd_GetEdid = 41, }; class SetSysMitmService : public IMitmServiceObject { @@ -30,8 +38,8 @@ class SetSysMitmService : public IMitmServiceObject { } static bool ShouldMitm(u64 pid, u64 tid) { - /* Only MitM qlaunch, maintenance. */ - return tid == 0x0100000000001000ULL || tid == 0x0100000000001015ULL; + /* Mitm everything. */ + return true; } static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); @@ -40,9 +48,18 @@ class SetSysMitmService : public IMitmServiceObject { /* Overridden commands. */ Result GetFirmwareVersion(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); Result GetFirmwareVersion2(OutPointerWithServerSize<SetSysFirmwareVersion, 0x1> out); + Result GetSettingsItemValueSize(Out<u64> out_size, InPointer<char> name, InPointer<char> key); + Result GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8> out_value, InPointer<char> name, InPointer<char> key); + + /* Forced passthrough commands. */ + Result GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion, &SetSysMitmService::GetFirmwareVersion>(), MakeServiceCommandMeta<SetSysCmd_GetFirmwareVersion2, &SetSysMitmService::GetFirmwareVersion2>(), + MakeServiceCommandMeta<SetSysCmd_GetSettingsItemValueSize, &SetSysMitmService::GetSettingsItemValueSize>(), + MakeServiceCommandMeta<SetSysCmd_GetSettingsItemValue, &SetSysMitmService::GetSettingsItemValue>(), + + MakeServiceCommandMeta<SetSysCmd_GetEdid, &SetSysMitmService::GetEdid>(), }; }; diff --git a/stratosphere/set_mitm/source/setsys_shim.c b/stratosphere/set_mitm/source/setsys_shim.c new file mode 100644 index 000000000..4edae7004 --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_shim.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "setsys_shim.h" + +/* Command forwarders. */ +Result setsysGetEdidFwd(Service* s, SetSysEdid* out) { + IpcCommand c; + ipcInitialize(&c); + ipcAddRecvStatic(&c, out, sizeof(*out), 0); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 41; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} diff --git a/stratosphere/set_mitm/source/setsys_shim.h b/stratosphere/set_mitm/source/setsys_shim.h new file mode 100644 index 000000000..6f475ea46 --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_shim.h @@ -0,0 +1,23 @@ +/** + * @file setsys_shim.h + * @brief System Settings Services (set:sys) IPC wrapper. To be merged into libnx, eventually. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include <switch.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char edid[0x100]; +} SetSysEdid; + +/* Command forwarders. */ +Result setsysGetEdidFwd(Service* s, SetSysEdid* out); + +#ifdef __cplusplus +} +#endif \ No newline at end of file From 18ee6eb2e6356bcd4ba6762cc438afa0df5a7adc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 21 Jan 2019 01:09:06 -0800 Subject: [PATCH 359/489] set.mitm: Parse settings from SD card (closes #268) --- stratosphere/set_mitm/Makefile | 2 +- stratosphere/set_mitm/source/ini.c | 269 +++++++++++++++ stratosphere/set_mitm/source/ini.h | 130 ++++++++ stratosphere/set_mitm/source/setmitm_main.cpp | 6 +- .../set_mitm/source/setsys_mitm_service.cpp | 40 ++- .../set_mitm/source/setsys_settings_items.cpp | 305 ++++++++++++++++++ .../set_mitm/source/setsys_settings_items.hpp | 36 +++ stratosphere/set_mitm/source/setsys_shim.c | 50 ++- stratosphere/set_mitm/source/setsys_shim.h | 1 + 9 files changed, 834 insertions(+), 5 deletions(-) create mode 100644 stratosphere/set_mitm/source/ini.c create mode 100644 stratosphere/set_mitm/source/ini.h create mode 100644 stratosphere/set_mitm/source/setsys_settings_items.cpp create mode 100644 stratosphere/set_mitm/source/setsys_settings_items.hpp diff --git a/stratosphere/set_mitm/Makefile b/stratosphere/set_mitm/Makefile index 71c014dc5..2d3bf2862 100644 --- a/stratosphere/set_mitm/Makefile +++ b/stratosphere/set_mitm/Makefile @@ -31,7 +31,7 @@ DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src -DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" +DEFINES := -DDISABLE_IPC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" -DINI_MAX_LINE=768 #--------------------------------------------------------------------------------- # options for code generation diff --git a/stratosphere/set_mitm/source/ini.c b/stratosphere/set_mitm/source/ini.c new file mode 100644 index 000000000..426430c9b --- /dev/null +++ b/stratosphere/set_mitm/source/ini.c @@ -0,0 +1,269 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#include "ini.h" + +#if !INI_USE_STACK +#include <stdlib.h> +#endif + +#define MAX_SECTION 72 +#define MAX_NAME 72 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to null at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + strncpy(dest, src, size - 1); + dest[size - 1] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; +#else + char* line; + int max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC + char* new_line; + int offset; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = realloc(line, max_line); + if (!new_line) { + free(line); + return -2; + } + line = new_line; + if (reader(line + offset, max_line - offset, stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; +#endif + value = lskip(value); + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ + error = lineno; + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/stratosphere/set_mitm/source/ini.h b/stratosphere/set_mitm/source/ini.h new file mode 100644 index 000000000..f45ba40ba --- /dev/null +++ b/stratosphere/set_mitm/source/ini.h @@ -0,0 +1,130 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef __INI_H__ +#define __INI_H__ + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See http://code.google.com/p/inih/issues/detail?id=21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INI_H__ */ diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/set_mitm/source/setmitm_main.cpp index bfba144e4..e2f821e64 100644 --- a/stratosphere/set_mitm/source/setmitm_main.cpp +++ b/stratosphere/set_mitm/source/setmitm_main.cpp @@ -24,13 +24,14 @@ #include <stratosphere.hpp> #include "setsys_mitm_service.hpp" +#include "setsys_settings_items.hpp" extern "C" { extern u32 __start__; u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x20000 + #define INNER_HEAP_SIZE 0x40000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -80,6 +81,9 @@ using SetMitmManager = WaitableManager<SetSysManagerOptions>; int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); + + /* Load settings from SD card. */ + SettingsItemManager::RefreshConfiguration(); /* TODO: What's a good timeout value to use here? */ auto server_manager = new SetMitmManager(1); diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.cpp b/stratosphere/set_mitm/source/setsys_mitm_service.cpp index 33db6bef0..e12e3d5a0 100644 --- a/stratosphere/set_mitm/source/setsys_mitm_service.cpp +++ b/stratosphere/set_mitm/source/setsys_mitm_service.cpp @@ -19,6 +19,7 @@ #include <switch.h> #include "setsys_mitm_service.hpp" #include "setsys_firmware_version.hpp" +#include "setsys_settings_items.hpp" void SetSysMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { /* No commands need postprocessing. */ @@ -44,6 +45,16 @@ Result SetSysMitmService::GetSettingsItemValueSize(Out<u64> out_size, InPointer< char name[SET_MAX_NAME_SIZE] = {0}; char key[SET_MAX_NAME_SIZE] = {0}; + Result rc = SettingsItemManager::ValidateName(in_name.pointer); + if (R_FAILED(rc)) { + return rc; + } + + rc = SettingsItemManager::ValidateKey(in_key.pointer); + if (R_FAILED(rc)) { + return rc; + } + if (in_name.num_elements < SET_MAX_NAME_SIZE) { strncpy(name, in_name.pointer, in_name.num_elements); } else { @@ -55,14 +66,33 @@ Result SetSysMitmService::GetSettingsItemValueSize(Out<u64> out_size, InPointer< } else { strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1); } + + rc = SettingsItemManager::GetValueSize(name, key, out_size.GetPointer()); + if (R_FAILED(rc)) { + rc = setsysGetSettingsItemValueSize(name, key, out_size.GetPointer()); + } - return setsysGetSettingsItemValueSize(name, key, out_size.GetPointer()); + return rc; } Result SetSysMitmService::GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8> out_value, InPointer<char> in_name, InPointer<char> in_key) { char name[SET_MAX_NAME_SIZE] = {0}; char key[SET_MAX_NAME_SIZE] = {0}; + Result rc = SettingsItemManager::ValidateName(in_name.pointer); + if (R_FAILED(rc)) { + return rc; + } + + rc = SettingsItemManager::ValidateKey(in_key.pointer); + if (R_FAILED(rc)) { + return rc; + } + + if (out_value.buffer == nullptr) { + return 0x19A69; + } + if (in_name.num_elements < SET_MAX_NAME_SIZE) { strncpy(name, in_name.pointer, in_name.num_elements); } else { @@ -74,8 +104,14 @@ Result SetSysMitmService::GetSettingsItemValue(Out<u64> out_size, OutBuffer<u8> } else { strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1); } + + rc = SettingsItemManager::GetValue(name, key, out_value.buffer, out_value.num_elements, out_size.GetPointer()); + + if (R_FAILED(rc)) { + rc = setsysGetSettingsItemValueFwd(this->forward_service.get(), name, key, out_value.buffer, out_value.num_elements, out_size.GetPointer()); + } - return setsysGetSettingsItemValue(name, key, out_value.buffer, out_value.num_elements); + return rc; } Result SetSysMitmService::GetEdid(OutPointerWithServerSize<SetSysEdid, 0x1> out) { diff --git a/stratosphere/set_mitm/source/setsys_settings_items.cpp b/stratosphere/set_mitm/source/setsys_settings_items.cpp new file mode 100644 index 000000000..9f56ceb4d --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_settings_items.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <mutex> +#include <algorithm> +#include <map> +#include <string> +#include <utility> +#include <switch.h> +#include <strings.h> +#include <ctype.h> + +#include "setsys_settings_items.hpp" +#include "ini.h" + +struct SettingsItemValue { + size_t size; + u8 *data; +}; + +std::map<std::string, SettingsItemValue> g_settings_items; + +static bool g_threw_fatal = false; +static HosThread g_fatal_thread; + +static void FatalThreadFunc(void *arg) { + Result rc = (Result)((uintptr_t)arg); + fatalSimple(rc); +} + +static bool IsCorrectFormat(const char *str, size_t len) { + if (len > 0 && str[len - 1] == '.') { + return false; + } + + for (size_t i = 0; i < len; i++) { + const char c = *(str++); + + if ('a' <= c && c <= 'z') { + continue; + } + + if ('0' <= c && c <= '9') { + continue; + } + + if (c == '-' || c == '.' || c == '_') { + continue; + } + + return false; + } + + return true; +} + +Result SettingsItemManager::ValidateName(const char *name, size_t max_size) { + if (name == nullptr) { + return 0x19269; + } + + const size_t name_len = strnlen(name, std::min(max_size, MaxNameLength + 1)); + if (name_len == 0) { + return 0x1BA69; + } else if (name_len > MaxNameLength) { + return 0x1E269; + } + + if (!IsCorrectFormat(name, name_len)) { + return 0x20A69; + } + + return 0x0; +} + +Result SettingsItemManager::ValidateName(const char *name) { + return ValidateName(name, MaxNameLength + 1); +} + +Result SettingsItemManager::ValidateKey(const char *key, size_t max_size) { + if (key == nullptr) { + return 0x19469; + } + + const size_t key_len = strnlen(key, std::min(max_size, MaxKeyLength + 1)); + if (key_len == 0) { + return 0x1BC69; + } else if (key_len > MaxKeyLength) { + return 0x1E469; + } + + if (!IsCorrectFormat(key, key_len)) { + return 0x20C69; + } + + return 0x0; +} + +Result SettingsItemManager::ValidateKey(const char *key) { + return ValidateKey(key, MaxKeyLength + 1); +} + +static bool IsHexadecimal(const char *str) { + while (*str) { + if (isxdigit(*str)) { + str++; + } else { + return false; + } + } + return true; +} + +static char hextoi(char c) { + if ('a' <= c && c <= 'f') return c - 'a' + 0xA; + if ('A' <= c && c <= 'F') return c - 'A' + 0xA; + if ('0' <= c && c <= '9') return c - '0'; + return 0; +} + +static Result ParseValue(const char *name, const char *key, const char *val_tup) { + const char *delimiter = strchr(val_tup, '!'); + const char *value_str = delimiter + 1; + const char *type = val_tup; + + if (delimiter == NULL) { + return 0x20E69; + } + + while (isspace(*type) && type != delimiter) { + type++; + } + + size_t type_len = delimiter - type; + size_t value_len = strlen(value_str); + if (delimiter == NULL || value_len == 0 || type_len == 0) { + return 0x20E69; + } + + std::string kv = std::string(name) + "!" + std::string(key); + SettingsItemValue value; + + if (strncasecmp(type, "str", type_len) == 0 || strncasecmp(type, "string", type_len) == 0) { + /* String */ + value.size = value_len + 1; + value.data = reinterpret_cast<u8 *>(strdup(value_str)); + if (value.data == nullptr) { + return 0xCC69; + } + } else if (strncasecmp(type, "hex", type_len) == 0 || strncasecmp(type, "bytes", type_len) == 0) { + /* hex */ + if (value_len % 2 || !IsHexadecimal(value_str)) { + return 0x20E69; + } + value.size = value_len / 2; + u8 *data = reinterpret_cast<u8 *>(malloc(value.size)); + if (data == nullptr) { + return 0xCC69; + } + + memset(data, 0, value.size); + for (size_t i = 0; i < value_len; i++) { + data[i >> 1] |= hextoi(value_str[i]) << (4 * (i & 1)); + } + + value.data = data; + } else if (strncasecmp(type, "u8", type_len) == 0) { + /* u8 */ + value.size = sizeof(u8); + u8 *data = reinterpret_cast<u8 *>(malloc(value.size)); + if (data == nullptr) { + return 0xCC69; + } + *data = (u8)(strtoul(value_str, nullptr, 0)); + value.data = reinterpret_cast<u8 *>(data); + } else if (strncasecmp(type, "u16", type_len) == 0) { + /* u16 */ + value.size = sizeof(u16); + u16 *data = reinterpret_cast<u16 *>(malloc(value.size)); + if (data == nullptr) { + return 0xCC69; + } + *data = (u16)(strtoul(value_str, nullptr, 0)); + value.data = reinterpret_cast<u8 *>(data); + } else if (strncasecmp(type, "u32", type_len) == 0) { + /* u32 */ + value.size = sizeof(u32); + u32 *data = reinterpret_cast<u32 *>(malloc(value.size)); + if (data == nullptr) { + return 0xCC69; + } + *data = (u32)(strtoul(value_str, nullptr, 0)); + value.data = reinterpret_cast<u8 *>(data); + } else if (strncasecmp(type, "u64", type_len) == 0) { + /* u64 */ + value.size = sizeof(u64); + u64 *data = reinterpret_cast<u64 *>(malloc(value.size)); + if (data == nullptr) { + return 0xCC69; + } + *data = (u64)(strtoul(value_str, nullptr, 0)); + value.data = reinterpret_cast<u8 *>(data); + } else { + return 0x20E69; + } + + g_settings_items[kv] = value; + return 0x0; +} + +static int SettingsItemIniHandler(void *user, const char *name, const char *key, const char *value) { + Result rc = *(reinterpret_cast<Result *>(user)); + ON_SCOPE_EXIT { *(reinterpret_cast<Result *>(user)) = rc; }; + + if (R_SUCCEEDED(rc)) { + rc = SettingsItemManager::ValidateName(name); + } + if (R_SUCCEEDED(rc)) { + rc = SettingsItemManager::ValidateKey(name); + } + if (R_SUCCEEDED(rc)) { + rc = ParseValue(name, key, value); + } + + return R_SUCCEEDED(rc) ? 1 : 0; +} + +void SettingsItemManager::RefreshConfiguration() { + /* Mount the SD Card. */ + Result rc = fsInitialize(); + if (R_SUCCEEDED(rc)) { + rc = fsdevMountSdmc(); + } + if (R_FAILED(rc)) { + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); + } + + /* When we're done, we should stop talking to FS. */ + ON_SCOPE_EXIT { + fsdevUnmountAll(); + fsExit(); + }; + + /* Open, parse config file. */ + { + FILE *config = fopen("sdmc:/atmosphere/system_settings.ini", "r"); + if (config == NULL) { + return; + } + ON_SCOPE_EXIT { fclose(config); }; + + Result rc = 0; + ini_parse_file(config, SettingsItemIniHandler, &rc); + + /* Report error if we encountered one. */ + if (R_FAILED(rc) && !g_threw_fatal) { + g_threw_fatal = true; + g_fatal_thread.Initialize(&FatalThreadFunc, reinterpret_cast<void *>(rc), 0x1000, 49); + g_fatal_thread.Start(); + } + } +} + +Result SettingsItemManager::GetValueSize(const char *name, const char *key, u64 *out_size) { + std::string kv = std::string(name) + "!" + std::string(key); + + auto it = g_settings_items.find(kv); + if (it == g_settings_items.end()) { + return 0x1669; + } + + *out_size = it->second.size; + return 0x0; +} + +Result SettingsItemManager::GetValue(const char *name, const char *key, void *out, size_t max_size, u64 *out_size) { + std::string kv = std::string(name) + "!" + std::string(key); + + auto it = g_settings_items.find(kv); + if (it == g_settings_items.end()) { + return 0x1669; + } + + size_t copy_size = it->second.size; + if (max_size < copy_size) { + copy_size = max_size; + } + *out_size = copy_size; + + memcpy(out, it->second.data, copy_size); + return 0x0; +} diff --git a/stratosphere/set_mitm/source/setsys_settings_items.hpp b/stratosphere/set_mitm/source/setsys_settings_items.hpp new file mode 100644 index 000000000..47abe11b2 --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_settings_items.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + + +class SettingsItemManager { + public: + static constexpr size_t MaxNameLength = 64; + static constexpr size_t MaxKeyLength = 64; + public: + static Result ValidateName(const char *name, size_t max_size); + static Result ValidateName(const char *name); + + static Result ValidateKey(const char *key, size_t max_size); + static Result ValidateKey(const char *key); + + static void RefreshConfiguration(); + static Result GetValueSize(const char *name, const char *key, u64 *out_size); + static Result GetValue(const char *name, const char *key, void *out, size_t max_size, u64 *out_size); +}; diff --git a/stratosphere/set_mitm/source/setsys_shim.c b/stratosphere/set_mitm/source/setsys_shim.c index 4edae7004..652649405 100644 --- a/stratosphere/set_mitm/source/setsys_shim.c +++ b/stratosphere/set_mitm/source/setsys_shim.c @@ -13,7 +13,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - + +#include <string.h> #include <switch.h> #include "setsys_shim.h" @@ -50,3 +51,50 @@ Result setsysGetEdidFwd(Service* s, SetSysEdid* out) { return rc; } + +Result setsysGetSettingsItemValueFwd(Service *s, const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out) { + char send_name[SET_MAX_NAME_SIZE]; + char send_item_key[SET_MAX_NAME_SIZE]; + + memset(send_name, 0, SET_MAX_NAME_SIZE); + memset(send_item_key, 0, SET_MAX_NAME_SIZE); + strncpy(send_name, name, SET_MAX_NAME_SIZE-1); + strncpy(send_item_key, item_key, SET_MAX_NAME_SIZE-1); + + IpcCommand c; + ipcInitialize(&c); + ipcAddSendStatic(&c, send_name, SET_MAX_NAME_SIZE, 0); + ipcAddSendStatic(&c, send_item_key, SET_MAX_NAME_SIZE, 0); + ipcAddRecvBuffer(&c, value_out, value_out_size, 0); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 38; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u64 size_out; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + if (R_SUCCEEDED(rc)) { + *size_out = resp->size_out; + } + } + + return rc; +} diff --git a/stratosphere/set_mitm/source/setsys_shim.h b/stratosphere/set_mitm/source/setsys_shim.h index 6f475ea46..c2b5f73da 100644 --- a/stratosphere/set_mitm/source/setsys_shim.h +++ b/stratosphere/set_mitm/source/setsys_shim.h @@ -17,6 +17,7 @@ typedef struct { /* Command forwarders. */ Result setsysGetEdidFwd(Service* s, SetSysEdid* out); +Result setsysGetSettingsItemValueFwd(Service* s, const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out); #ifdef __cplusplus } From 2711702e29be2e7712bb0d24da7b68f452de41ba Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 21 Jan 2019 01:13:41 -0800 Subject: [PATCH 360/489] set.mitm: Add delay to allow fatal to work when thrown --- stratosphere/set_mitm/source/setsys_settings_items.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stratosphere/set_mitm/source/setsys_settings_items.cpp b/stratosphere/set_mitm/source/setsys_settings_items.cpp index 9f56ceb4d..6fbec5f50 100644 --- a/stratosphere/set_mitm/source/setsys_settings_items.cpp +++ b/stratosphere/set_mitm/source/setsys_settings_items.cpp @@ -38,6 +38,9 @@ static HosThread g_fatal_thread; static void FatalThreadFunc(void *arg) { Result rc = (Result)((uintptr_t)arg); + + svcSleepThread(5000000000ULL); + fatalSimple(rc); } From 254ac590164301602e947bc9ca75c0da86462848 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 21 Jan 2019 02:20:55 -0800 Subject: [PATCH 361/489] set.mitm: revise down memory usage --- stratosphere/set_mitm/source/setmitm_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/set_mitm/source/setmitm_main.cpp index e2f821e64..9df353cbe 100644 --- a/stratosphere/set_mitm/source/setmitm_main.cpp +++ b/stratosphere/set_mitm/source/setmitm_main.cpp @@ -31,7 +31,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x40000 + #define INNER_HEAP_SIZE 0x28000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; From 5f179cf19ff3f4edad3e062b55724bd41cf7ba47 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 21 Jan 2019 22:24:19 -0800 Subject: [PATCH 362/489] set.mitm: increase memory, fix race condition that could cause hang during boot --- stratosphere/set_mitm/source/setmitm_main.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/set_mitm/source/setmitm_main.cpp index 9df353cbe..44a5b3172 100644 --- a/stratosphere/set_mitm/source/setmitm_main.cpp +++ b/stratosphere/set_mitm/source/setmitm_main.cpp @@ -31,7 +31,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x28000 + #define INNER_HEAP_SIZE 0x50000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -61,6 +61,11 @@ void __appInit(void) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); } + rc = setsysInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } @@ -86,19 +91,11 @@ int main(int argc, char **argv) SettingsItemManager::RefreshConfiguration(); /* TODO: What's a good timeout value to use here? */ - auto server_manager = new SetMitmManager(1); + auto server_manager = new SetMitmManager(3); /* Create set:sys mitm. */ AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 60); - /* Connect to set:sys. */ - { - Result rc = setsysInitialize(); - if (R_FAILED(rc)) { - fatalSimple(rc); - } - } - /* Loop forever, servicing our services. */ server_manager->Process(); From 24f74312f2cf6f430966810ae4ae2b740edbefb4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 21 Jan 2019 22:30:16 -0800 Subject: [PATCH 363/489] Update libstrat for bugfix --- stratosphere/libstratosphere | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index f9d38856f..de4c2ddae 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit f9d38856f335c4cb0ed3c7253d9319a965815af2 +Subproject commit de4c2ddae12207e8ebe5f2f8d40335f0ebd9858d From 8a73ad996a608f52fd4a46468435456cde27f4e0 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 21 Jan 2019 23:31:59 -0800 Subject: [PATCH 364/489] pm: add support for maintenance mode --- stratosphere/pm/source/pm_boot2.cpp | 45 +++++++++++++++++++++++-- stratosphere/pm/source/pm_boot_mode.cpp | 4 +++ stratosphere/pm/source/pm_boot_mode.hpp | 2 ++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 181fbb44d..b3059f0c9 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -25,6 +25,7 @@ #include <stratosphere.hpp> #include "pm_boot2.hpp" #include "pm_registration.hpp" +#include "pm_boot_mode.hpp" static std::vector<Boot2KnownTitleId> g_boot2_titles; @@ -86,8 +87,41 @@ static void LaunchTitle(Boot2KnownTitleId title_id, FsStorageId storage_id, u32 } } -static bool ShouldForceMaintenanceMode() { - /* TODO: Contact set:sys, retrieve boot!force_maintenance, read plus/minus buttons. */ +static bool GetGpioPadLow(GpioPadName pad) { + GpioPadSession button; + if (R_FAILED(gpioOpenSession(&button, pad))) { + return false; + } + + /* Ensure we close even on early return. */ + ON_SCOPE_EXIT { gpioPadClose(&button); }; + + /* Set direction input. */ + gpioPadSetDirection(&button, GpioDirection_Input); + + GpioValue val; + return R_SUCCEEDED(gpioPadGetValue(&button, &val)) && val == GpioValue_Low; +} + +static bool IsMaintenanceMode() { + /* Contact set:sys, retrieve boot!force_maintenance. */ + if (R_SUCCEEDED(setsysInitialize())) { + ON_SCOPE_EXIT { setsysExit(); }; + + u8 force_maintenance = 1; + setsysGetSettingsItemValue("boot", "force_maintenance", &force_maintenance, sizeof(force_maintenance)); + if (force_maintenance != 0) { + return true; + } + } + + /* Contact GPIO, read plus/minus buttons. */ + if (R_SUCCEEDED(gpioInitialize())) { + ON_SCOPE_EXIT { gpioExit(); }; + + return GetGpioPadLow(GpioPadName_ButtonVolUp) && GetGpioPadLow(GpioPadName_ButtonVolDown); + } + return false; } @@ -185,6 +219,12 @@ void EmbeddedBoot2::Main() { /* At this point, the SD card can be mounted. */ MountSdCard(); + /* Find out whether we are maintenance mode. */ + bool maintenance = IsMaintenanceMode(); + if (maintenance) { + BootModeService::SetMaintenanceBootForEmbeddedBoot2(); + } + /* Launch set:mitm, wait for it. */ LaunchTitle(Boot2KnownTitleId::ams_set_mitm, FsStorageId_None, 0, NULL); WaitForMitm("set:sys"); @@ -195,7 +235,6 @@ void EmbeddedBoot2::Main() { LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_NandSystem, 0, NULL); /* Launch default programs. */ - bool maintenance = ShouldForceMaintenanceMode(); for (auto &launch_program : g_additional_launch_programs) { if (!maintenance || std::get<bool>(launch_program)) { LaunchTitle(std::get<Boot2KnownTitleId>(launch_program), FsStorageId_NandSystem, 0, NULL); diff --git a/stratosphere/pm/source/pm_boot_mode.cpp b/stratosphere/pm/source/pm_boot_mode.cpp index b8158acf9..0ed7dd18a 100644 --- a/stratosphere/pm/source/pm_boot_mode.cpp +++ b/stratosphere/pm/source/pm_boot_mode.cpp @@ -27,3 +27,7 @@ void BootModeService::GetBootMode(Out<u32> out) { void BootModeService::SetMaintenanceBoot() { g_is_maintenance_boot = true; } + +void BootModeService::SetMaintenanceBootForEmbeddedBoot2() { + g_is_maintenance_boot = true; +} diff --git a/stratosphere/pm/source/pm_boot_mode.hpp b/stratosphere/pm/source/pm_boot_mode.hpp index 1aadf8c42..48a608796 100644 --- a/stratosphere/pm/source/pm_boot_mode.hpp +++ b/stratosphere/pm/source/pm_boot_mode.hpp @@ -28,6 +28,8 @@ class BootModeService final : public IServiceObject { /* Actual commands. */ void GetBootMode(Out<u32> out); void SetMaintenanceBoot(); + public: + static void SetMaintenanceBootForEmbeddedBoot2(); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<BootMode_Cmd_GetBootMode, &BootModeService::GetBootMode>(), From 8bf8503fcd350732148856d92853a73a430d33dc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 22 Jan 2019 03:58:20 -0800 Subject: [PATCH 365/489] docs: Add set.mitm documentation --- docs/modules/set_mitm.md | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 docs/modules/set_mitm.md diff --git a/docs/modules/set_mitm.md b/docs/modules/set_mitm.md new file mode 100644 index 000000000..3c4728c36 --- /dev/null +++ b/docs/modules/set_mitm.md @@ -0,0 +1,54 @@ +# set_mitm +set_mitm is a sysmodule that enables intercepting requests to the system settings service. + +## Atmosphère Extensions + +set_mitm intercepts the `GetFirmwareVersion` command, if the requester is `qlaunch` or `maintenance`.\ +It modifies the `display_version` field of the returned system version, causing the version to display\ +in settings as `#.#.# (AMS #.#.#)`. This allows users to easily verify what version of Atmosphère they are running. + +set_mitm also intercepts the `GetSettingsItemValueSize` and `GetSettingsItemValue` commands for all requesters.\ +It does so in order to enable user configuration of system settings, which are parsed from `atmosphere/system_settings.ini` on boot.\ +The format for settings is described below. + +### Atmosphère Settings Format + +Settings are parsed from the `atmosphere/system_settings.ini` file during the boot process. This file is a normal ini file,\ +with some specific interpretations. + +The standard representation of a system setting's identifier takes the form `name!key`. This is represented within\ +`system_settings.ini` as a section `name`, with an entry `key`. For example: + +``` +[name] +key = ... +``` + +System settings can have variable types (strings, integral values, byte arrays, etc). To accommodate this, `system_settings.ini`\ +must store values as a `type_identifier!value_store` pair. A number of different types are supported, with identifiers detailed below.\ +Please note that a malformed value string will cause a fatal error to occur on boot. A full example of a custom setting is given below\ +(setting `eupld!upload_enabled = 0`), for posterity: + +``` +[eupld] +upload_enabled = u8!0x0 +``` + +### Supported Types + +* Strings + * Type identifiers: `str`, `string` + * The value string is used directly as the setting, with null terminator appended. +* Integral types + * Type identifiers: `u8`, `u16`, `u32`, `u64` + * The value string is parsed via a call to `strtoul(value, NULL, 0)`. + * Setting bitwidth is determined by the identifier (8 for 1 byte, 16 for 2 bytes, and so on). +* Raw bytes + * Type identifiers: `hex`, `bytes` + * The value string is parsed as a hexadecimal string. + * The value string must be of even length, or a fatal error will be thrown on parse. + +### Atmosphère Custom Settings + +At present, Atmosphère implements no custom settings. However, this is subject to change in the future, and any\ +custom settings will be documented here as they are added. From 9bc45475f4cde34ed1d1086980edc78906c2d5f4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 22 Jan 2019 03:59:35 -0800 Subject: [PATCH 366/489] docs: fix formatting for github --- docs/modules/set_mitm.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/modules/set_mitm.md b/docs/modules/set_mitm.md index 3c4728c36..586f1e840 100644 --- a/docs/modules/set_mitm.md +++ b/docs/modules/set_mitm.md @@ -37,16 +37,16 @@ upload_enabled = u8!0x0 ### Supported Types * Strings - * Type identifiers: `str`, `string` - * The value string is used directly as the setting, with null terminator appended. + * Type identifiers: `str`, `string` + * The value string is used directly as the setting, with null terminator appended. * Integral types - * Type identifiers: `u8`, `u16`, `u32`, `u64` - * The value string is parsed via a call to `strtoul(value, NULL, 0)`. - * Setting bitwidth is determined by the identifier (8 for 1 byte, 16 for 2 bytes, and so on). + * Type identifiers: `u8`, `u16`, `u32`, `u64` + * The value string is parsed via a call to `strtoul(value, NULL, 0)`. + * Setting bitwidth is determined by the identifier (8 for 1 byte, 16 for 2 bytes, and so on). * Raw bytes - * Type identifiers: `hex`, `bytes` - * The value string is parsed as a hexadecimal string. - * The value string must be of even length, or a fatal error will be thrown on parse. + * Type identifiers: `hex`, `bytes` + * The value string is parsed as a hexadecimal string. + * The value string must be of even length, or a fatal error will be thrown on parse. ### Atmosphère Custom Settings From c9c8f64f09ccfcf478b919f9e4601b764573410a Mon Sep 17 00:00:00 2001 From: TrainDoctor <alexgwilson15@gmail.com> Date: Thu, 17 Jan 2019 19:47:24 -0800 Subject: [PATCH 367/489] Better issue templates! --- .github/ISSUE_TEMPLATE/bug_report.md | 47 +++++++++++++++++++---- .github/ISSUE_TEMPLATE/feature_request.md | 42 ++++++++++++++++++-- .github/ISSUE_TEMPLATE/question.md | 15 +++----- README.md | 1 + 4 files changed, 84 insertions(+), 21 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 4b4dfad1e..50084ce85 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,25 +1,56 @@ --- name: Bug Report about: Something doesn't work correctly in Atmosphère. - +#assignees: --- ## Bug Report +[ If any section does not apply, replace its contents with "N/A". ]</br> +[ Lines between [ ] (square brackets) should be removed before posting. ]</br> + +[ * ]</br> +[ Note: If the bug or crash you encountered is related to; ]</br> +[ - software used to make "backups", ]</br> +[ - software explicitly distributed for piracy, etc ]</br> +[ then contributors will not provide support for your issue and your issue will be closed. ]</br> + ### What's the issue you encountered? +[ Describe the issue in detail and what you were doing beforehand. ]</br> +[ Did you make any changes related to Atmosphère itself? ]</br> +[ If so, make sure to include details relating to what exactly you changed. ]</br> + ### How can the issue be reproduced? -### Crash report? +[ * ]</br> +[ Include a detailed step by step process for recreating your issue. ]</br> -(If a crash report was created under /atmosphere/crash_reports/, please upload it to -[gist](https://gist.github.com/) and paste the link here.) +### Crash Report + +[ Crash reports can be found under ``/atmosphere/crash_reports``. ]</br> +[ If your issue caused Atmosphère to crash, include the crash report(s) by creating a [gist](https://gist.github.com/) and pasting the link here. ]</br> +[ If you don't include a crash report in instances of crash related issues, we will ask you one to provide one. ]</br> + +### System Firmware Version + +X.X.X</br> +[ Replace X's with system firmware version at time of crash. ]</br> +[ You can find your firmware version in the Settings -> System, under "System Update". ]</br> +[ If it says "Update Pending", you can clear the pending update by rebooting to Maintenance Mode. ]</br> ### Environment? -- What bootloader (fusee, hekate, etc) was Atmosphère launched by: -- Official release or unofficial build: -- Do you have additional kips you're loading: -- Additional info about your environment: +- What bootloader (fusèe, hekate, etc) was Atmosphère launched by: +- Official release or unofficial build: + - [ Offical release version x.x.x (or) unofficial build ] + - [ If using an unofficial build, include details on where/how you acquired the build. ] + - [ Ex: Self-compilation ] + - [ Ex: Kosmos' distribution of Atmosphère ] +- Do you have additional kips or sysmodules you're loading: +- Homebrew software installed: [ * ] ### Additional context? + +- Additional info about your environment: +- [ Any other information relevant to your issue. ] diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 3b93d9d25..61a25494c 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,12 +1,48 @@ --- name: Feature Request -about: You want to suggest a new feature for Atmosphère. - +about: Suggest a new feature for Atmosphère. +#assignees: --- ## Feature Request +[ If any section does not apply, replace its contents with "N/A". ]</br> +[ If you do not have the information needed for a section, replace its contents with "Unknown". ]</br> +[ Lines between [ ] (square brackets) are to be removed before posting. ] + +[ Please search for existing [feature requests](https://github.com/Atmosphere-NX/Atmosphere/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22features%2Ffeature-request%22) before you make your own request. ]</br> +[ Duplicate requests will be marked as such and you will be referred to the original request. ] + ### What feature are you suggesting? +#### Overview: +- [ Include the basic, high-level concepts for this feature here. ]</br> + +#### Smaller Details: +- [ These may include specific methods of implementation etc. ]</br> + +#### Nature of Request: +[ Remove all that do not apply to your request. ] +- Addition + - [ Ex: Addition of certain original features or features from other community projects. ] + - [ If you are suggesting porting features or including features from other projects, include what license they are distributed under and what, if any libraries those project use. ] +- Change +- Removal + - [Ex: Removal of certain features or implementation due to a specific issue/bug or because of low quality code, etc.] + +### What component do you feel this would best fit within? +- [Fusée](https://github.com/Atmosphere-NX/Atmosphere#components)</br> + - Atmosphère's custom bootloader.</br> +- [Exosphère](https://github.com/Atmosphere-NX/Atmosphere#components)</br> + - Fully-featured custom secure monitor.</br> +- [Stratosphère](https://github.com/Atmosphere-NX/Atmosphere#components)</br> + - Custom system modules.</br> +- [**Thermosphère**](https://github.com/Atmosphere-NX/Atmosphere#components)</br> + - Atmosphère's emuNAND implementation.</br> +- [**Troposphère**](https://github.com/Atmosphere-NX/Atmosphere#components)</br> + - Application-level patches to the Horizon OS.</br> + +[ Note: **Bolded components are not implemented** or are still at the prototyping phase. ] ### Why would this feature be useful? - +[ If this is a feature for an end-user, how does it benefit the end-user? ]</br> +[ If this feature is for developers, what does it add to Atmosphère that did not already exist? ]</br> diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 6cc1915b9..21e69bd4e 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -1,12 +1,7 @@ --- name: Question -about: Please ask questions in the ReSwitched discord, instead of making issues. - ---- - -We would like to use GitHub to keep track of problems/feature requests. - -If you have a question, please join the ReSwitched discord for help. - -- Discord link: https://discordapp.com/invite/DThbZ7z - +about: Please ask questions in the ReSwitched discord, instead of making issues. +--- +We would like to use GitHub to keep track of problems/feature requests. +If you have a question, please join the ReSwitched discord for help. +- Discord link: https://discordapp.com/invite/DThbZ7z diff --git a/README.md b/README.md index 8059286e6..85f15e3de 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ ===== ![License](https://img.shields.io/badge/License-GPLv2-blue.svg) +[![Chat on Discord](https://camo.githubusercontent.com/b4175720ede4f2621aa066ffbabb70ae30044679/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636861742d446973636f72642d627269676874677265656e2e737667)](https://discordapp.com/invite/ZdqEhed) Atmosphère is a work-in-progress customized firmware for the Nintendo Switch. From c6f06e2c4065c41c509d0d9f43c0b4a8e12509d1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 08:12:10 -0800 Subject: [PATCH 368/489] exosphere: properly implement reboot-to-payload --- exosphere/Makefile | 13 ++- exosphere/rebootstub/Makefile | 154 ++++++++++++++++++++++++++++++ exosphere/rebootstub/linker.ld | 18 ++++ exosphere/rebootstub/linker.specs | 7 ++ exosphere/rebootstub/src/start.s | 45 +++++++++ exosphere/src/configitem.c | 29 +++++- exosphere/src/smc_ams.c | 4 +- exosphere/src/smc_ams.h | 3 + 8 files changed, 262 insertions(+), 11 deletions(-) create mode 100644 exosphere/rebootstub/Makefile create mode 100644 exosphere/rebootstub/linker.ld create mode 100644 exosphere/rebootstub/linker.specs create mode 100644 exosphere/rebootstub/src/start.s diff --git a/exosphere/Makefile b/exosphere/Makefile index cb06f6f5f..727e71791 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -76,14 +76,15 @@ export TOPDIR := $(CURDIR) export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ $(TOPDIR)/lp0fw \ - $(TOPDIR)/sc7fw + $(TOPDIR)/sc7fw \ + $(TOPDIR)/rebootstub export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin lp0fw.bin +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin lp0fw.bin rebootstub.bin #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C @@ -110,7 +111,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -.PHONY: $(BUILD) build_sc7fw build_lp0fw clean all +.PHONY: $(BUILD) build_sc7fw build_lp0fw build_rebootstub clean all #--------------------------------------------------------------------------------- all: $(BUILD) @@ -121,7 +122,10 @@ check_sc7fw: check_lp0fw: @$(MAKE) -C lp0fw all -$(BUILD): check_sc7fw check_lp0fw +check_rebootstub: + @$(MAKE) -C lp0fw all + +$(BUILD): check_sc7fw check_lp0fw check_rebootstub @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile @@ -130,6 +134,7 @@ clean: @echo clean ... @$(MAKE) -C $(TOPDIR)/sc7fw clean @$(MAKE) -C $(TOPDIR)/lp0fw clean + @$(MAKE) -C $(TOPDIR)/rebootstub clean @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf diff --git a/exosphere/rebootstub/Makefile b/exosphere/rebootstub/Makefile new file mode 100644 index 000000000..0eadd1314 --- /dev/null +++ b/exosphere/rebootstub/Makefile @@ -0,0 +1,154 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITARM)/base_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := src +DATA := data +INCLUDES := include + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork + +CFLAGS := \ + -g \ + -O2 \ + -ffunction-sections \ + -fdata-sections \ + -fomit-frame-pointer \ + -fno-inline \ + -std=gnu11 \ + -Werror \ + -Wall \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__BPMP__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).bin + +$(OUTPUT).bin : $(OUTPUT).elf + $(OBJCOPY) -S -O binary $< $@ + @echo built ... $(notdir $@) + +$(OUTPUT).elf : $(OFILES) + +%.elf: $(OFILES) + @echo linking $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + @$(NM) -CSn $@ > $(notdir $*.lst) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/exosphere/rebootstub/linker.ld b/exosphere/rebootstub/linker.ld new file mode 100644 index 000000000..d2e018d4d --- /dev/null +++ b/exosphere/rebootstub/linker.ld @@ -0,0 +1,18 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +ENTRY(_start) +SECTIONS +{ + . = 0x4003F000; + + __start__ = ABSOLUTE(.); + + .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } + .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } + .bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; } + + . = ALIGN(4); + + __end__ = ABSOLUTE(.); +} \ No newline at end of file diff --git a/exosphere/rebootstub/linker.specs b/exosphere/rebootstub/linker.specs new file mode 100644 index 000000000..300990418 --- /dev/null +++ b/exosphere/rebootstub/linker.specs @@ -0,0 +1,7 @@ +%rename link old_link + +*link: +%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections + +*startfile: +crti%O%s crtbegin%O%s diff --git a/exosphere/rebootstub/src/start.s b/exosphere/rebootstub/src/start.s new file mode 100644 index 000000000..155ab382a --- /dev/null +++ b/exosphere/rebootstub/src/start.s @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +.section .text.start +.align 4 +.global _start +_start: + b crt0 + +.global crt0 +.type crt0, %function +crt0: + @ clear all registers + ldr r0, =0x52425430 @ RBT0 + mov r1, #0x0 + mov r2, #0x0 + mov r3, #0x0 + mov r4, #0x0 + mov r5, #0x0 + mov r6, #0x0 + mov r7, #0x0 + mov r8, #0x0 + mov r9, #0x0 + mov r10, #0x0 + mov r11, #0x0 + mov r12, #0x0 + mov lr, #0x0 + ldr sp, =0x40010000 + ldr pc, =0x40010000 + + + diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index eb080ede2..e332311c8 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -26,6 +26,14 @@ #include "utils.h" #include "masterkey.h" #include "exocfg.h" +#include "smc_ams.h" +#include "arm.h" + +#define u8 uint8_t +#define u32 uint32_t +#include "rebootstub_bin.h" +#undef u8 +#undef u32 static bool g_battery_profile = false; static bool g_debugmode_override_user = false, g_debugmode_override_priv = false; @@ -48,11 +56,22 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { case REBOOT_KIND_TO_WB_PAYLOAD: /* Set reboot kind = warmboot. */ MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1; - /* Patch bootrom to jump to payload. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x630ull) = 0x0010171B; /* Return to bootrom IRAM initialization func. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x4000FFA4; /* Overwrite bootrom return address on stack. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x40010000; /* Return to start of payload. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x63Cull) = 0x4000FFB4; /* Overwrite bootrom return address on stack. */ + /* Patch SDRAM init to perform an SVC immediately after second write */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x2E38DFFF; + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x6001DC28; + /* Set SVC handler to jump to reboot stub in IRAM. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x520ull) = 0x4003F000; + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x53Cull) = 0x6000F208; + + /* Copy reboot stub payload. */ + ams_map_irampage(0x4003F000); + for (unsigned int i = 0; i < rebootstub_bin_size; i += 4) { + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + i) = read32le(rebootstub_bin, i); + } + ams_unmap_irampage(); + + /* Ensure stub is flushed. */ + flush_dcache_all(); break; default: return 2; diff --git a/exosphere/src/smc_ams.c b/exosphere/src/smc_ams.c index 08e220f3d..5c58cbda3 100644 --- a/exosphere/src/smc_ams.c +++ b/exosphere/src/smc_ams.c @@ -72,7 +72,7 @@ static void ams_unmap_userpage(void) { lock_release(&g_ams_userpage_mapped); } -static void ams_map_irampage(uintptr_t iram_address) { +void ams_map_irampage(uintptr_t iram_address) { lock_acquire(&g_ams_iram_page_mapped); static const uint64_t irampage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_DEVICE; uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); @@ -80,7 +80,7 @@ static void ams_map_irampage(uintptr_t iram_address) { tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); } -static void ams_unmap_irampage(void) { +void ams_unmap_irampage(void) { uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE); mmu_unmap_page(mmu_l3_tbl, AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR); diff --git a/exosphere/src/smc_ams.h b/exosphere/src/smc_ams.h index ed1cee156..8b74d3bd5 100644 --- a/exosphere/src/smc_ams.h +++ b/exosphere/src/smc_ams.h @@ -21,4 +21,7 @@ uint32_t ams_iram_copy(smc_args_t *args); +void ams_map_irampage(uintptr_t iram_address); +void ams_unmap_irampage(void); + #endif \ No newline at end of file From 031c9e545b56c705dab76b4d95dd3feaf34ffb97 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 08:20:27 -0800 Subject: [PATCH 369/489] fatal: reboot to sdmc:/atmosphere/reboot_payload.bin --- stratosphere/fatal/source/fatal_config.cpp | 6 +- stratosphere/fatal/source/fatal_main.cpp | 4 ++ .../fatal/source/fatal_payload_manager.cpp | 65 +++++++++++++++++++ .../fatal/source/fatal_payload_manager.hpp | 28 ++++++++ .../fatal/source/fatal_task_power.cpp | 9 +-- .../fatal/source/fatal_task_screen.cpp | 6 +- stratosphere/libstratosphere | 2 +- 7 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 stratosphere/fatal/source/fatal_payload_manager.cpp create mode 100644 stratosphere/fatal/source/fatal_payload_manager.hpp diff --git a/stratosphere/fatal/source/fatal_config.cpp b/stratosphere/fatal/source/fatal_config.cpp index 11cc32420..9cc7d91fc 100644 --- a/stratosphere/fatal/source/fatal_config.cpp +++ b/stratosphere/fatal/source/fatal_config.cpp @@ -58,9 +58,9 @@ static void SetupConfigLanguages() { config->error_desc = u8"Please call 1-800-875-1852 for service.\n"; } else { config->error_desc = u8"An error has occured.\n\n" - u8"Please press the POWER Button to restart the console, or a VOL button\n" - u8"to restart the console in RCM mode. If you are unable to restart the\n" - u8"console, hold the POWER Button for 12 seconds to turn the console off.\n\n" + u8"Please press the POWER Button to restart the console normally, or a VOL button\n" + u8"to reboot to a payload (or RCM, if none is present). If you are unable to\n" + u8"restart the console, hold the POWER Button for 12 seconds to turn the console off.\n\n" u8"If the problem persists, refer to the Nintendo Support Website.\n" u8"support.nintendo.com/switch/error\n"; } diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 733dc6eff..39e5ae088 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -29,6 +29,7 @@ #include "fatal_config.hpp" #include "fatal_repair.hpp" #include "fatal_font.hpp" +#include "fatal_payload_manager.hpp" extern "C" { extern u32 __start__; @@ -159,6 +160,9 @@ int main(int argc, char **argv) /* Load settings from set:sys. */ InitializeFatalConfig(); + /* Load a payload from the SD card. */ + FatalPayloadManager::LoadPayloadFromSdCard(); + /* Load shared font. */ if (R_FAILED(FontManager::InitializeSharedFont())) { std::abort(); diff --git a/stratosphere/fatal/source/fatal_payload_manager.cpp b/stratosphere/fatal/source/fatal_payload_manager.cpp new file mode 100644 index 000000000..52a72d7d6 --- /dev/null +++ b/stratosphere/fatal/source/fatal_payload_manager.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include <string.h> +#include "fatal_types.hpp" +#include "fatal_payload_manager.hpp" + +/* TODO: Find a way to pre-populate this with the contents of fusee-primary. */ +static u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE] __attribute__ ((aligned (0x1000))); +static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000))); +static bool g_payload_loaded = false; + +void FatalPayloadManager::LoadPayloadFromSdCard() { + FILE *f = fopen("sdmc:/atmosphere/reboot_payload.bin", "rb"); + if (f == NULL) { + return; + } + ON_SCOPE_EXIT { fclose(f); }; + + memset(g_reboot_payload, 0xFF, sizeof(g_reboot_payload)); + fread(g_reboot_payload, 1, IRAM_PAYLOAD_MAX_SIZE, f); + g_payload_loaded = true; +} + +static void ClearIram() { + /* Make page FFs. */ + memset(g_work_page, 0xFF, sizeof(g_work_page)); + + /* Overwrite all of IRAM with FFs. */ + for (size_t ofs = 0; ofs < IRAM_PAYLOAD_MAX_SIZE; ofs += sizeof(g_work_page)) { + CopyToIram(IRAM_PAYLOAD_BASE + ofs, g_work_page, sizeof(g_work_page)); + } +} + +void FatalPayloadManager::RebootToPayload() { + /* If we don't actually have a payload loaded, just go to RCM. */ + if (!g_payload_loaded) { + RebootToRcm(); + } + + /* Ensure clean IRAM state. */ + ClearIram(); + + /* Copy in payload. */ + for (size_t ofs = 0; ofs < sizeof(g_reboot_payload); ofs += 0x1000) { + CopyToIram(IRAM_PAYLOAD_BASE + ofs, &g_reboot_payload[ofs], 0x1000); + } + + RebootToIramPayload(); +} \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_payload_manager.hpp b/stratosphere/fatal/source/fatal_payload_manager.hpp new file mode 100644 index 000000000..cb052b37f --- /dev/null +++ b/stratosphere/fatal/source/fatal_payload_manager.hpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#define IRAM_PAYLOAD_MAX_SIZE 0x30000 +#define IRAM_PAYLOAD_BASE 0x40010000ull + +class FatalPayloadManager { + public: + static void LoadPayloadFromSdCard(); + static void RebootToPayload(); +}; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index 41954a0f5..4883b78f7 100644 --- a/stratosphere/fatal/source/fatal_task_power.cpp +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -16,6 +16,7 @@ #include <switch.h> #include "fatal_task_power.hpp" +#include "fatal_payload_manager.hpp" #include "fatal_config.hpp" bool PowerControlTask::TryShutdown() { @@ -123,13 +124,13 @@ void PowerButtonObserveTask::WaitForPowerButton() { Result rc = 0; if (check_vol_up && R_SUCCEEDED((rc = gpioPadGetValue(&vol_up_btn, &val))) && val == GpioValue_Low) { - /* Tell exosphere to reboot to RCM. */ - RebootToRcm(); + /* Tell exosphere to reboot to payload. */ + FatalPayloadManager::RebootToPayload(); } if (check_vol_down && R_SUCCEEDED((rc = gpioPadGetValue(&vol_down_btn, &val))) && val == GpioValue_Low) { - /* Tell exosphere to reboot to RCM. */ - RebootToRcm(); + /* Tell exosphere to reboot to payload. */ + FatalPayloadManager::RebootToPayload(); } if ((R_SUCCEEDED(rc = bpcGetSleepButtonState(&state)) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) { diff --git a/stratosphere/fatal/source/fatal_task_screen.cpp b/stratosphere/fatal/source/fatal_task_screen.cpp index 144935406..a67cf71ce 100644 --- a/stratosphere/fatal/source/fatal_task_screen.cpp +++ b/stratosphere/fatal/source/fatal_task_screen.cpp @@ -215,9 +215,9 @@ Result ShowFatalTask::ShowFatal() { } else { /* Print a special message for atmosphere version mismatch. */ FontManager::Print(u8"Atmosphère version mismatch detected.\n\n" - u8"Please press the POWER Button to restart the console, or a VOL button\n" - u8"to restart the console in RCM mode. If you are unable to restart the\n" - u8"console, hold the POWER Button for 12 seconds to turn the console off.\n\n" + u8"Please press the POWER Button to restart the console normally, or a VOL button\n" + u8"to reboot to a payload (or RCM, if none is present). If you are unable to\n" + u8"restart the console, hold the POWER Button for 12 seconds to turn the console off.\n\n" u8"Please ensure that all Atmosphère components are updated.\n" u8"github.com/Atmosphere-NX/Atmosphere/releases\n"); } diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index de4c2ddae..9bf228de3 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit de4c2ddae12207e8ebe5f2f8d40335f0ebd9858d +Subproject commit 9bf228de3e1e33ea62ed18b51853e5de6b4c4b41 From 776ab2164184ff9d5b2458c034e11be6b56b03aa Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 08:21:52 -0800 Subject: [PATCH 370/489] dist: copy fusee-primary as default reboot payload --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 62fdd0f64..8a72d0043 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,7 @@ dist: all mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032 + cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini From b2fb42e39d3ca6f4cd3f6f86286be02cf94ee197 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 08:24:22 -0800 Subject: [PATCH 371/489] dist: add default system settings --- Makefile | 1 + common/defaults/system_settings.ini | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 common/defaults/system_settings.ini diff --git a/Makefile b/Makefile index 8a72d0043..c9ac55b28 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ dist: all cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini + cp common/defaults/system_settings.ini atmosphere-$(AMSVER)/atmosphere/system_settings.ini cp -r common/defaults/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034/exefs.nsp diff --git a/common/defaults/system_settings.ini b/common/defaults/system_settings.ini new file mode 100644 index 000000000..9a10dcd7c --- /dev/null +++ b/common/defaults/system_settings.ini @@ -0,0 +1,6 @@ +; Disable uploading error reports to Nintendo +[eupld] +upload_enabled = u8!0x0 +; Enable USB 3.0 superspeed for homebrew +[usb] +usb30_force_enabled = u8!0x1 \ No newline at end of file From 08d1e9b88050f7e271cd8d42666d5ed0e9bec1f2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 08:33:06 -0800 Subject: [PATCH 372/489] fatal: fix payload size, pm: take from application instead of applet --- stratosphere/fatal/source/fatal_payload_manager.hpp | 2 +- stratosphere/pm/source/pm_resource_limits.cpp | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/stratosphere/fatal/source/fatal_payload_manager.hpp b/stratosphere/fatal/source/fatal_payload_manager.hpp index cb052b37f..7aed9cdce 100644 --- a/stratosphere/fatal/source/fatal_payload_manager.hpp +++ b/stratosphere/fatal/source/fatal_payload_manager.hpp @@ -18,7 +18,7 @@ #include <switch.h> #include <stratosphere.hpp> -#define IRAM_PAYLOAD_MAX_SIZE 0x30000 +#define IRAM_PAYLOAD_MAX_SIZE 0x2F000 #define IRAM_PAYLOAD_BASE 0x40010000ull class FatalPayloadManager { diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index 67a4aa773..4dcdfa5a8 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -179,15 +179,11 @@ void ResourceLimitUtils::InitializeLimits() { } } - /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */ + /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Application. */ for (unsigned int i = 0; i < 6; i++) { g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - /* On < 4.0.0, taking from application instead of applet fixes a rare hang on boot. */ - if (kernelAbove400()) { - g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - } else { - g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - } + /* Taking from application instead of applet fixes a rare hang on boot on < 4.0.0. */ + g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; } /* Set resource limits. */ From e75f4e9f5ad4f8985d64cc1cc3cb5346c4577343 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:05:06 -0800 Subject: [PATCH 373/489] troposphere: add reboot_to_payload example homebrew --- Makefile | 7 +- troposphere/Makefile | 12 ++ troposphere/reboot_to_payload/Makefile | 192 ++++++++++++++++++++ troposphere/reboot_to_payload/source/main.c | 103 +++++++++++ 4 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 troposphere/Makefile create mode 100644 troposphere/reboot_to_payload/Makefile create mode 100644 troposphere/reboot_to_payload/source/main.c diff --git a/Makefile b/Makefile index c9ac55b28..8b85264f5 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) AMSREV := $(AMSREV)-dirty endif -all: fusee stratosphere exosphere thermosphere +all: fusee stratosphere exosphere thermosphere troposphere thermosphere: $(MAKE) -C thermosphere all @@ -17,6 +17,9 @@ exosphere: thermosphere stratosphere: exosphere $(MAKE) -C stratosphere all +troposphere: stratosphere + $(MAKE) -C troposphere all + fusee: exosphere stratosphere $(MAKE) -C $@ all @@ -39,6 +42,7 @@ dist: all rm -rf out mkdir atmosphere-$(AMSVER) mkdir atmosphere-$(AMSVER)/atmosphere + mkdir atmosphere-$(AMSVER)/switch mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032 @@ -51,6 +55,7 @@ dist: all cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034/exefs.nsp cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp + cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags/boot2.flag cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../; diff --git a/troposphere/Makefile b/troposphere/Makefile new file mode 100644 index 000000000..2be61ea0a --- /dev/null +++ b/troposphere/Makefile @@ -0,0 +1,12 @@ +APPLICATIONS := reboot_to_payload + +SUBFOLDERS := $(APPLICATIONS) + +TOPTARGETS := all clean + +$(TOPTARGETS): $(SUBFOLDERS) + +$(SUBFOLDERS): + $(MAKE) -C $@ $(MAKECMDGOALS) + +.PHONY: $(TOPTARGETS) $(SUBFOLDERS) diff --git a/troposphere/reboot_to_payload/Makefile b/troposphere/reboot_to_payload/Makefile new file mode 100644 index 000000000..be4c825e2 --- /dev/null +++ b/troposphere/reboot_to_payload/Makefile @@ -0,0 +1,192 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". +# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - <Project name>.jpg +# - icon.jpg +# - <libnx folder>/default_icon.jpg +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include +EXEFS_SRC := exefs_src +APP_TITLE := Reboot to Payload +APP_AUTHOR := Atmosphère-NX +APP_VERSION := 1.0.0 +#ROMFS := romfs + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) + +ifeq ($(strip $(ICON)),) + icons := $(wildcard *.jpg) + ifneq (,$(findstring $(TARGET).jpg,$(icons))) + export APP_ICON := $(TOPDIR)/$(TARGET).jpg + else + ifneq (,$(findstring icon.jpg,$(icons))) + export APP_ICON := $(TOPDIR)/icon.jpg + endif + endif +else + export APP_ICON := $(TOPDIR)/$(ICON) +endif + +ifeq ($(strip $(NO_ICON)),) + export NROFLAGS += --icon=$(APP_ICON) +endif + +ifeq ($(strip $(NO_NACP)),) + export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp +endif + +ifneq ($(APP_TITLEID),) + export NACPFLAGS += --titleid=$(APP_TITLEID) +endif + +ifneq ($(ROMFS),) + export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) +endif + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).nro + +ifeq ($(strip $(NO_NACP)),) +$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp +else +$(OUTPUT).nro : $(OUTPUT).elf +endif + +$(OUTPUT).elf : $(OFILES) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/troposphere/reboot_to_payload/source/main.c b/troposphere/reboot_to_payload/source/main.c new file mode 100644 index 000000000..297f5fa86 --- /dev/null +++ b/troposphere/reboot_to_payload/source/main.c @@ -0,0 +1,103 @@ +#include <string.h> +#include <stdio.h> +#include <stdbool.h> + +#include <switch.h> + +#define IRAM_PAYLOAD_MAX_SIZE 0x2F000 +#define IRAM_PAYLOAD_BASE 0x40010000 + +static u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE] __attribute__ ((aligned (0x1000))); +static u8 g_ff_page[0x1000] __attribute__ ((aligned (0x1000))); +static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000))); + +void do_iram_dram_copy(void *buf, uintptr_t iram_addr, size_t size, int option) { + memcpy(g_work_page, buf, size); + + SecmonArgs args = {0}; + args.X[0] = 0xF0000201; /* smcAmsIramCopy */ + args.X[1] = (uintptr_t)g_work_page; /* DRAM Address */ + args.X[2] = iram_addr; /* IRAM Address */ + args.X[3] = size; /* Copy size */ + args.X[4] = option; /* 0 = Read, 1 = Write */ + svcCallSecureMonitor(&args); + + memcpy(buf, g_work_page, size); +} + +void copy_to_iram(uintptr_t iram_addr, void *buf, size_t size) { + do_iram_dram_copy(buf, iram_addr, size, 1); +} + +void copy_from_iram(void *buf, uintptr_t iram_addr, size_t size) { + do_iram_dram_copy(buf, iram_addr, size, 0); +} + +static void clear_iram(void) { + memset(g_ff_page, 0xFF, sizeof(g_ff_page)); + for (size_t i = 0; i < IRAM_PAYLOAD_MAX_SIZE; i += sizeof(g_ff_page)) { + copy_to_iram(IRAM_PAYLOAD_BASE + i, g_ff_page, sizeof(g_ff_page)); + } +} + +static void reboot_to_payload(void) { + clear_iram(); + + for (size_t i = 0; i < IRAM_PAYLOAD_MAX_SIZE; i += 0x1000) { + copy_to_iram(IRAM_PAYLOAD_BASE + i, &g_reboot_payload[i], 0x1000); + } + + splSetConfig((SplConfigItem)65001, 2); +} + +int main(int argc, char **argv) +{ + gfxInitDefault(); + fsdevMountSdmc(); + consoleInit(NULL); + + bool can_reboot = true; + Result rc = splInitialize(); + if (R_FAILED(rc)) { + printf("Failed to initialize spl: 0x%x\n", rc); + can_reboot = false; + } else { + FILE *f = fopen("sdmc:/atmosphere/reboot_payload.bin", "rb"); + if (f == NULL) { + printf("Failed to open atmosphere/reboot_payload.bin!\n"); + can_reboot = false; + } else { + fread(g_reboot_payload, 1, sizeof(g_reboot_payload), f); + fclose(f); + printf("Press [-] to reboot to payload\n"); + } + } + + printf("Press [L] to exit\n"); + + // Main loop + while(appletMainLoop()) + { + //Scan all the inputs. This should be done once for each frame + hidScanInput(); + + //hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame) + u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); + + if (can_reboot && kDown & KEY_MINUS) { + reboot_to_payload(); + } + if (kDown & KEY_L) { break; } // break in order to return to hbmenu + + gfxFlushBuffers(); + gfxSwapBuffers(); + } + + if (can_reboot) { + splExit(); + } + fsdevUnmountAll(); + gfxExit(); + return 0; +} + From 5b4e81aa8b515b0ca6cd323b14c6e15b8c8880bc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:09:17 -0800 Subject: [PATCH 374/489] rip fancy e in nacp 2019-2019 --- troposphere/reboot_to_payload/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/troposphere/reboot_to_payload/Makefile b/troposphere/reboot_to_payload/Makefile index be4c825e2..410dae264 100644 --- a/troposphere/reboot_to_payload/Makefile +++ b/troposphere/reboot_to_payload/Makefile @@ -37,7 +37,7 @@ DATA := data INCLUDES := include EXEFS_SRC := exefs_src APP_TITLE := Reboot to Payload -APP_AUTHOR := Atmosphère-NX +APP_AUTHOR := Atmosphere-NX APP_VERSION := 1.0.0 #ROMFS := romfs From c56db864eb641c333200e996ce5f12eddbee8ef5 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:10:51 -0800 Subject: [PATCH 375/489] rtp: update to new libnx console API --- troposphere/reboot_to_payload/source/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/troposphere/reboot_to_payload/source/main.c b/troposphere/reboot_to_payload/source/main.c index 297f5fa86..db2ab4056 100644 --- a/troposphere/reboot_to_payload/source/main.c +++ b/troposphere/reboot_to_payload/source/main.c @@ -52,7 +52,6 @@ static void reboot_to_payload(void) { int main(int argc, char **argv) { - gfxInitDefault(); fsdevMountSdmc(); consoleInit(NULL); @@ -97,7 +96,7 @@ int main(int argc, char **argv) splExit(); } fsdevUnmountAll(); - gfxExit(); + consoleExit(NULL); return 0; } From f15fc6645e253b57543a1d583bc82a8d01bdb64e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:11:46 -0800 Subject: [PATCH 376/489] rtp: more libnx api updates --- troposphere/reboot_to_payload/source/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/troposphere/reboot_to_payload/source/main.c b/troposphere/reboot_to_payload/source/main.c index db2ab4056..896c52991 100644 --- a/troposphere/reboot_to_payload/source/main.c +++ b/troposphere/reboot_to_payload/source/main.c @@ -52,7 +52,6 @@ static void reboot_to_payload(void) { int main(int argc, char **argv) { - fsdevMountSdmc(); consoleInit(NULL); bool can_reboot = true; @@ -88,14 +87,13 @@ int main(int argc, char **argv) } if (kDown & KEY_L) { break; } // break in order to return to hbmenu - gfxFlushBuffers(); - gfxSwapBuffers(); + consoleUpdate(NULL); } if (can_reboot) { splExit(); } - fsdevUnmountAll(); + consoleExit(NULL); return 0; } From f99dea798a6bdfc3e812b8feb689ded58925b4cd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:13:24 -0800 Subject: [PATCH 377/489] alignas preferred to __attribute__((aligned)) --- stratosphere/fatal/source/fatal_payload_manager.cpp | 4 ++-- troposphere/reboot_to_payload/source/main.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stratosphere/fatal/source/fatal_payload_manager.cpp b/stratosphere/fatal/source/fatal_payload_manager.cpp index 52a72d7d6..22ede3638 100644 --- a/stratosphere/fatal/source/fatal_payload_manager.cpp +++ b/stratosphere/fatal/source/fatal_payload_manager.cpp @@ -21,8 +21,8 @@ #include "fatal_payload_manager.hpp" /* TODO: Find a way to pre-populate this with the contents of fusee-primary. */ -static u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE] __attribute__ ((aligned (0x1000))); -static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000))); +static alignas(0x1000) u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE]; +static alignas(0x1000) u8 g_work_page[0x1000]; static bool g_payload_loaded = false; void FatalPayloadManager::LoadPayloadFromSdCard() { diff --git a/troposphere/reboot_to_payload/source/main.c b/troposphere/reboot_to_payload/source/main.c index 896c52991..89f0e6258 100644 --- a/troposphere/reboot_to_payload/source/main.c +++ b/troposphere/reboot_to_payload/source/main.c @@ -7,9 +7,9 @@ #define IRAM_PAYLOAD_MAX_SIZE 0x2F000 #define IRAM_PAYLOAD_BASE 0x40010000 -static u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE] __attribute__ ((aligned (0x1000))); -static u8 g_ff_page[0x1000] __attribute__ ((aligned (0x1000))); -static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000))); +static alignas(0x1000) u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE]; +static alignas(0x1000) u8 g_ff_page[0x1000]; +static alignas(0x1000) u8 g_work_page[0x1000]; void do_iram_dram_copy(void *buf, uintptr_t iram_addr, size_t size, int option) { memcpy(g_work_page, buf, size); From 0e4c3007453df7787c25c9bc4d63d0858c658cdb Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:18:18 -0800 Subject: [PATCH 378/489] exo: fix rebootstub makefile --- exosphere/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exosphere/Makefile b/exosphere/Makefile index 727e71791..4603f7e4a 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -123,7 +123,7 @@ check_lp0fw: @$(MAKE) -C lp0fw all check_rebootstub: - @$(MAKE) -C lp0fw all + @$(MAKE) -C rebootstub all $(BUILD): check_sc7fw check_lp0fw check_rebootstub @[ -d $@ ] || mkdir -p $@ From 051789c430d67ed916226d16108be5aade3579da Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:31:54 -0800 Subject: [PATCH 379/489] fatal: alignas doesn't actually work --- stratosphere/fatal/source/fatal_payload_manager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stratosphere/fatal/source/fatal_payload_manager.cpp b/stratosphere/fatal/source/fatal_payload_manager.cpp index 22ede3638..52a72d7d6 100644 --- a/stratosphere/fatal/source/fatal_payload_manager.cpp +++ b/stratosphere/fatal/source/fatal_payload_manager.cpp @@ -21,8 +21,8 @@ #include "fatal_payload_manager.hpp" /* TODO: Find a way to pre-populate this with the contents of fusee-primary. */ -static alignas(0x1000) u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE]; -static alignas(0x1000) u8 g_work_page[0x1000]; +static u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE] __attribute__ ((aligned (0x1000))); +static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000))); static bool g_payload_loaded = false; void FatalPayloadManager::LoadPayloadFromSdCard() { From 7d4a257d571c7b15b9695a81dd98d80e96a7fae3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:44:03 -0800 Subject: [PATCH 380/489] Bump version to 0.8.3 --- common/include/atmosphere/version.h | 2 +- docs/changelog.md | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 9a529c942..2396eb595 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 8 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 2 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 3 #endif \ No newline at end of file diff --git a/docs/changelog.md b/docs/changelog.md index e9891d279..cb4bc8a61 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,22 @@ # Changelog +## 0.8.3 ++ A custom warmboot firmware was implemented, which does not perform anti-downgrade fuse checks. + + This fixes sleep mode when using a downgraded NAND. + + This also removes Atmosphère's final dependency on Nintendo's encrypted PK11 binary; all components are now re-implemented. ++ The ExternalContentSource API was changed to not clear on failure. ++ Content override now supports an "app" setting, that causes all applications to be overridden with HBL instead of a specific title. + + Note: because override keys are system-wide, using this setting will prevent using mods in games (as every game will be HBL). ++ A bug was fixed causing incorrect fatal-error output when svcBreak was called on 5.0.0+. ++ An extension was added to set.mitm to support customization of system settings. + + These are controlled by `atmosphere/system_settings.ini`, see [here](https://github.com/Atmosphere-NX/Atmosphere/blob/master/docs/modules/set_mitm.md) for documentation. ++ A bug was fixed in the MitM API that could sometimes cause a system hang during boot. ++ A change was made to the MitM API: in cases where sm would have returned 0xE15 when installing a mitm service, it now defers the result (following GetService semantics). ++ Support for booting into maintenance mode by holding +/- was added to PM. ++ An extension was added to exosphere, adding a custom SMC that allows for DMA to IRAM. ++ In addition, smcGetConfig was extended to reboot to a payload in IRAM at 0x40010000 when ConfigItem 65001 is set to 2. + + Fatal will now use this to reboot to sdmc:/atmosphere/reboot_payload.bin if present, when a vol button is pressed. + + An example homebrew ("reboot_to_payload") was also written and is now included with Atmosphère. ++ General system stability improvements to enhance the user's experience. ## 0.8.2 + A number of bugs were fixed causing users to sometimes see `Key Derivation Failed!`. + KFUSE clock enable timings have been adjusted to allow time to stabilize before TSEC is granted access. From 5b1bb71787ec83b11027e7985192cb57815fdbc1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 09:45:57 -0800 Subject: [PATCH 381/489] docs: add sm extension I forgot to mention --- docs/changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index cb4bc8a61..cd4548e51 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -9,6 +9,8 @@ + A bug was fixed causing incorrect fatal-error output when svcBreak was called on 5.0.0+. + An extension was added to set.mitm to support customization of system settings. + These are controlled by `atmosphere/system_settings.ini`, see [here](https://github.com/Atmosphere-NX/Atmosphere/blob/master/docs/modules/set_mitm.md) for documentation. ++ An extension was added to sm, adding a new `sm:dmnt` service. + + This can be used by a debug monitor in order to debug the registration state of various other services. + A bug was fixed in the MitM API that could sometimes cause a system hang during boot. + A change was made to the MitM API: in cases where sm would have returned 0xE15 when installing a mitm service, it now defers the result (following GetService semantics). + Support for booting into maintenance mode by holding +/- was added to PM. From cedbcba3e32c0995b5eb5555cfcbdb3d65b2e931 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 11:41:32 -0800 Subject: [PATCH 382/489] 0.8.3: fix some memory/deadlock issues --- stratosphere/fs_mitm/source/fsmitm_main.cpp | 13 +++++-------- stratosphere/pm/source/pm_resource_limits.cpp | 12 +++++++++--- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index 40808a34c..24fa8b647 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -62,6 +62,11 @@ void __appInit(void) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); } + rc = fsInitialize(); + if (R_FAILED(rc)) { + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); + } + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } @@ -89,14 +94,6 @@ int main(int argc, char **argv) /* Create fsp-srv mitm. */ AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); - - /* Connect to FS */ - { - Result rc = fsInitialize(); - if (R_FAILED(rc)) { - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); - } - } if (R_FAILED(threadCreate(&sd_initializer_thread, &Utils::InitializeSdThreadFunc, NULL, 0x4000, 0x15, 0))) { /* TODO: Panic. */ diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index 4dcdfa5a8..99763cbf4 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -179,11 +179,17 @@ void ResourceLimitUtils::InitializeLimits() { } } - /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Application. */ + /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */ for (unsigned int i = 0; i < 6; i++) { g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - /* Taking from application instead of applet fixes a rare hang on boot on < 4.0.0. */ - g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + /* On < 4.0.0, taking from application instead of applet fixes a rare hang on boot. */ + if (kernelAbove600()) { + g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + } else if (kernelAbove400()) { + g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + } else { + g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; + } } /* Set resource limits. */ From 2677cf68d4f176c09d58b25baa502572feb574e4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 24 Jan 2019 12:09:41 -0800 Subject: [PATCH 383/489] pm/0.8.3: remove memory profile adjustment entirely --- stratosphere/pm/source/pm_resource_limits.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index 99763cbf4..67a4aa773 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -183,9 +183,7 @@ void ResourceLimitUtils::InitializeLimits() { for (unsigned int i = 0; i < 6; i++) { g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; /* On < 4.0.0, taking from application instead of applet fixes a rare hang on boot. */ - if (kernelAbove600()) { - g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - } else if (kernelAbove400()) { + if (kernelAbove400()) { g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; } else { g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; From da68d02c7712092386c9153d9ac590d199da0bae Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 25 Jan 2019 00:03:54 -0800 Subject: [PATCH 384/489] pm: fix memory profiles *again* (required for botw video update on 3.0) --- stratosphere/pm/source/pm_resource_limits.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index 67a4aa773..d4649bf07 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -182,8 +182,8 @@ void ResourceLimitUtils::InitializeLimits() { /* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */ for (unsigned int i = 0; i < 6; i++) { g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; - /* On < 4.0.0, taking from application instead of applet fixes a rare hang on boot. */ - if (kernelAbove400()) { + /* On < 3.0.0, taking from application instead of applet fixes a rare hang on boot. */ + if (kernelAbove300()) { g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; } else { g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES; From e55a7bef2619846a15617de684dc2d658caf0954 Mon Sep 17 00:00:00 2001 From: Nico Elayda <nico@elayda.com> Date: Sat, 26 Jan 2019 01:33:35 +0800 Subject: [PATCH 385/489] Add component subdirectories to root Makefile's .PHONY --- Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 8b85264f5..af0c8ac6b 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,9 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) AMSREV := $(AMSREV)-dirty endif -all: fusee stratosphere exosphere thermosphere troposphere +COMPONENTS := fusee stratosphere exosphere thermosphere troposphere + +all: $(COMPONENTS) thermosphere: $(MAKE) -C thermosphere all @@ -26,7 +28,7 @@ fusee: exosphere stratosphere clean: $(MAKE) -C fusee clean rm -rf out - + dist: all $(eval MAJORVER = $(shell grep '\ATMOSPHERE_RELEASE_VERSION_MAJOR\b' common/include/atmosphere/version.h \ | tr -s [:blank:] \ @@ -63,6 +65,6 @@ dist: all mkdir out mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin - -.PHONY: $(TOPTARGETS) fusee + +.PHONY: $(TOPTARGETS) $(COMPONENTS) From ea02f389ac85006e494ba7f72bdb7c5114408833 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Fri, 25 Jan 2019 23:50:50 -0800 Subject: [PATCH 386/489] fusee-primary: reboot to self, instead of to RCM --- fusee/fusee-primary/Makefile | 16 +++++++++++----- fusee/fusee-primary/src/main.c | 2 +- fusee/fusee-primary/src/pmc.h | 5 +++++ fusee/fusee-primary/src/utils.c | 25 ++++++++++++++++++++++++- fusee/fusee-primary/src/utils.h | 1 + 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/fusee/fusee-primary/Makefile b/fusee/fusee-primary/Makefile index cf79835f8..724c4083f 100644 --- a/fusee/fusee-primary/Makefile +++ b/fusee/fusee-primary/Makefile @@ -7,6 +7,8 @@ $(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>dev endif TOPDIR ?= $(CURDIR) + +AMS := $(TOPDIR)/../../ include $(DEVKITARM)/base_rules AMSBRANCH := $(shell git symbolic-ref --short HEAD) @@ -74,14 +76,15 @@ export OUTPUT := $(CURDIR)/$(TARGET) export TOPDIR := $(CURDIR) export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(AMS)/exosphere/rebootstub export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) rebootstub.bin #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C @@ -108,10 +111,13 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) -.PHONY: $(BUILD) clean all +.PHONY: $(BUILD) clean all check_rebootstub #--------------------------------------------------------------------------------- -all: $(BUILD) +all: check_rebootstub $(BUILD) + +check_rebootstub: + @$(MAKE) -C $(AMS)/exosphere/rebootstub all $(BUILD): @[ -d $@ ] || mkdir -p $@ @@ -150,7 +156,7 @@ $(OFILES_SRC) : $(HFILES_BIN) #--------------------------------------------------------------------------------- # you need a rule like this for each extension you use as binary data #--------------------------------------------------------------------------------- -%.bin.o : %.bin +%.bin.o %_bin.h: %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @$(bin2o) diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index c54862ba8..718130467 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -163,7 +163,7 @@ int main(void) { stage2_args->display_initialized = false; strcpy(stage2_args->bct0, bct0); g_chainloader_argc = 2; - + /* Wait a while. */ mdelay(1000); diff --git a/fusee/fusee-primary/src/pmc.h b/fusee/fusee-primary/src/pmc.h index cf20474e7..80c36da7f 100644 --- a/fusee/fusee-primary/src/pmc.h +++ b/fusee/fusee-primary/src/pmc.h @@ -61,6 +61,11 @@ #define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) #define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840) +#define APBDEV_PMC_SCRATCH45_0 MAKE_PMC_REG(0x234) +#define APBDEV_PMC_SCRATCH46_0 MAKE_PMC_REG(0x238) +#define APBDEV_PMC_SCRATCH33_0 MAKE_PMC_REG(0x120) +#define APBDEV_PMC_SCRATCH40_0 MAKE_PMC_REG(0x13C) + typedef struct { uint32_t cntrl; uint32_t sec_disable; diff --git a/fusee/fusee-primary/src/utils.c b/fusee/fusee-primary/src/utils.c index 26e838130..ac3d7b61f 100644 --- a/fusee/fusee-primary/src/utils.c +++ b/fusee/fusee-primary/src/utils.c @@ -29,6 +29,12 @@ #include <inttypes.h> +#define u8 uint8_t +#define u32 uint32_t +#include "rebootstub_bin.h" +#undef u8 +#undef u32 + void wait(uint32_t microseconds) { uint32_t old_time = TIMERUS_CNTR_1US_0; while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { @@ -59,12 +65,29 @@ __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) { } } +__attribute__((noreturn)) void reboot_to_self(void) { + /* Patch SDRAM init to perform an SVC immediately after second write */ + APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF; + APBDEV_PMC_SCRATCH46_0 = 0x6001DC28; + /* Set SVC handler to jump to reboot stub in IRAM. */ + APBDEV_PMC_SCRATCH33_0 = 0x4003F000; + APBDEV_PMC_SCRATCH40_0 = 0x6000F208; + + /* Copy reboot stub into IRAM high. */ + for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) { + write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i)); + } + + /* Trigger warm reboot. */ + pmc_reboot(1 << 0); +} + __attribute__((noreturn)) void wait_for_button_and_reboot(void) { uint32_t button; while (true) { button = btn_read(); if (button & BTN_POWER) { - pmc_reboot(1 << 1); + reboot_to_self(); } } } diff --git a/fusee/fusee-primary/src/utils.h b/fusee/fusee-primary/src/utils.h index 23893e930..58e53bffe 100644 --- a/fusee/fusee-primary/src/utils.h +++ b/fusee/fusee-primary/src/utils.h @@ -121,6 +121,7 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase); __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); +__attribute__((noreturn)) void reboot_to_self(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void); __attribute__((noreturn)) void generic_panic(void); From 3f6325c358586bad489ba652e9cd8920b35779cd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 26 Jan 2019 00:21:34 -0800 Subject: [PATCH 387/489] fusee-secondary: reboot to fusee-primary, instead of rcm --- fusee/fusee-primary/Makefile | 1 + fusee/fusee-secondary/Makefile | 29 +++++++++++++++++++++++------ fusee/fusee-secondary/src/pmc.h | 5 +++++ fusee/fusee-secondary/src/utils.c | 31 ++++++++++++++++++++++++++++++- fusee/fusee-secondary/src/utils.h | 1 + 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/fusee/fusee-primary/Makefile b/fusee/fusee-primary/Makefile index 724c4083f..107b32f55 100644 --- a/fusee/fusee-primary/Makefile +++ b/fusee/fusee-primary/Makefile @@ -126,6 +126,7 @@ $(BUILD): #--------------------------------------------------------------------------------- clean: @echo clean ... + @$(MAKE) -C $(AMS)/exosphere/rebootstub clean @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 90e963b63..8a964e2d3 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -19,6 +19,13 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) AMSREV := $(AMSREV)-dirty endif +define _bin2o + bin2s $< | $(AS) -o $(@) + echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`"_end[];" > `(echo $(<F) | tr . _ | tr - _)`.h + echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`"[];" >> `(echo $(<F) | tr . _ | tr - _)`.h + echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`_size";" >> `(echo $(<F) | tr . _ | tr - _)`.h +endef + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -79,7 +86,8 @@ export TOPDIR := $(CURDIR) export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/fs_mitm export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ - $(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/thermosphere $(KIPDIRS) + $(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/exosphere/rebootstub \ + $(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(KIPDIRS) export DEPSDIR := $(CURDIR)/$(BUILD) @@ -87,7 +95,7 @@ CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) KIPFILES := loader.kip pm.kip sm.kip fs_mitm.kip boot_100.kip boot_200.kip -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) exosphere.bin lp0fw.bin thermosphere.bin splash_screen.bmp $(KIPFILES) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp $(KIPFILES) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C @@ -103,10 +111,10 @@ else endif #--------------------------------------------------------------------------------- -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_BIN := $(addsuffix .o,$(subst -,_,$(BINFILES))) export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES)))) export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ @@ -115,11 +123,14 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) .PHONY: $(BUILD) clean all -.PHONY: check_exosphere check_thermosphere check_stratosphere +.PHONY: check_fusee_primary check_exosphere check_thermosphere check_stratosphere #--------------------------------------------------------------------------------- all: $(BUILD) +check_fusee_primary: + @$(MAKE) -C $(AMS)/fusee/fusee-primary all + check_exosphere: @$(MAKE) -C $(AMS)/exosphere all @@ -130,13 +141,14 @@ check_stratosphere: @$(MAKE) -C $(AMS)/stratosphere all -$(BUILD): check_exosphere check_thermosphere check_stratosphere +$(BUILD): check_fusee_primary check_exosphere check_thermosphere check_stratosphere @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile #--------------------------------------------------------------------------------- clean: @echo clean ... + @$(MAKE) -C $(AMS)/fusee/fusee-primary clean @$(MAKE) -C $(AMS)/exosphere clean @$(MAKE) -C $(AMS)/thermosphere clean @$(MAKE) -C $(AMS)/stratosphere clean @@ -169,6 +181,11 @@ $(OFILES_SRC) : $(HFILES_BIN) #--------------------------------------------------------------------------------- # you need a rule like this for each extension you use as binary data #--------------------------------------------------------------------------------- +fusee_primary.bin.o fusee_primary_bin.h: fusee-primary.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(_bin2o) + %.bin.o %_bin.h: %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) diff --git a/fusee/fusee-secondary/src/pmc.h b/fusee/fusee-secondary/src/pmc.h index cf20474e7..80c36da7f 100644 --- a/fusee/fusee-secondary/src/pmc.h +++ b/fusee/fusee-secondary/src/pmc.h @@ -61,6 +61,11 @@ #define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) #define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840) +#define APBDEV_PMC_SCRATCH45_0 MAKE_PMC_REG(0x234) +#define APBDEV_PMC_SCRATCH46_0 MAKE_PMC_REG(0x238) +#define APBDEV_PMC_SCRATCH33_0 MAKE_PMC_REG(0x120) +#define APBDEV_PMC_SCRATCH40_0 MAKE_PMC_REG(0x13C) + typedef struct { uint32_t cntrl; uint32_t sec_disable; diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index ed7636a89..e09fc6e37 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -29,6 +29,13 @@ #include <stdio.h> #include <inttypes.h> +#define u8 uint8_t +#define u32 uint32_t +#include "fusee_primary_bin.h" +#include "rebootstub_bin.h" +#undef u8 +#undef u32 + void wait(uint32_t microseconds) { uint32_t old_time = TIMERUS_CNTR_1US_0; while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { @@ -58,12 +65,34 @@ __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) { } } +__attribute__((noreturn)) void reboot_to_fusee_primary(void) { + /* Patch SDRAM init to perform an SVC immediately after second write */ + APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF; + APBDEV_PMC_SCRATCH46_0 = 0x6001DC28; + /* Set SVC handler to jump to reboot stub in IRAM. */ + APBDEV_PMC_SCRATCH33_0 = 0x4003F000; + APBDEV_PMC_SCRATCH40_0 = 0x6000F208; + + /* Copy fusee-primary into IRAM low. */ + for (size_t i = 0; i < fusee_primary_bin_size; i += sizeof(uint32_t)) { + write32le((void *)0x40010000, i, read32le(fusee_primary_bin, i)); + } + + /* Copy reboot stub into IRAM high. */ + for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) { + write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i)); + } + + /* Trigger warm reboot. */ + pmc_reboot(1 << 0); +} + __attribute__((noreturn)) void wait_for_button_and_reboot(void) { uint32_t button; while (true) { button = btn_read(); if (button & BTN_POWER) { - pmc_reboot(1 << 1); + reboot_to_fusee_primary(); } } } diff --git a/fusee/fusee-secondary/src/utils.h b/fusee/fusee-secondary/src/utils.h index 6b26428ce..8cc3e6814 100644 --- a/fusee/fusee-secondary/src/utils.h +++ b/fusee/fusee-secondary/src/utils.h @@ -122,6 +122,7 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase); __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); +__attribute__((noreturn)) void reboot_to_fusee_primary(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void); void wait_for_button(void); From 901723621c3683cf81b5d79a36be5cd6067ca98d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 26 Jan 2019 00:50:38 -0800 Subject: [PATCH 388/489] fusee: hide non-error logs behind splash screen (closes #328) --- fusee/fusee-secondary/src/lib/log.c | 6 +++++- fusee/fusee-secondary/src/main.c | 6 +++++- fusee/fusee-secondary/src/nxboot.c | 4 ---- fusee/fusee-secondary/src/splash_screen.c | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/fusee/fusee-secondary/src/lib/log.c b/fusee/fusee-secondary/src/lib/log.c index 402121d4d..1bf37d275 100644 --- a/fusee/fusee-secondary/src/lib/log.c +++ b/fusee/fusee-secondary/src/lib/log.c @@ -15,6 +15,7 @@ */ #include "log.h" +#include "../console.h" #include <stdio.h> @@ -100,7 +101,10 @@ void print(ScreenLogLevel screen_log_level, const char * fmt, ...) char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; char message[PRINT_MESSAGE_MAX_LENGTH] = {}; - /* TODO: make splash disappear if level > MANDATORY */ + /* Make splash disappear if level is ERROR or WARNING */ + if (screen_log_level < SCREEN_LOG_LEVEL_MANDATORY) { + console_resume(); + } /* make prefix free messages with log_level possible */ if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) { diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 20654509d..97983819e 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -32,6 +32,7 @@ #include "fs_utils.h" #include "nxfs.h" #include "gpt.h" +#include "splash_screen.h" #include "display/video_fb.h" #include "sdmmc/sdmmc.h" #include "lib/log.h" @@ -95,7 +96,7 @@ int main(int argc, void **argv) { /* Initialize the display, console, FS, etc. */ setup_env(); - print(SCREEN_LOG_LEVEL_MANDATORY, u8"Welcome to Atmosphère Fusée Stage 2!\n"); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, u8"Welcome to Atmosphère Fusée Stage 2!\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]); /* This will load all remaining binaries off of the SD. */ @@ -105,6 +106,9 @@ int main(int argc, void **argv) { g_do_nxboot = loader_ctx->chainload_entrypoint == 0; if (g_do_nxboot) { + /* Display splash screen. */ + display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); + print(SCREEN_LOG_LEVEL_MANDATORY, "Now performing nxboot.\n"); uint32_t boot_memaddr = nxboot_main(); nxboot_finish(boot_memaddr); diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 6879d4ec8..18697e75a 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -43,7 +43,6 @@ #include "tsec.h" #include "lp0.h" #include "loader.h" -#include "splash_screen.h" #include "exocfg.h" #include "display/video_fb.h" #include "lib/ini.h" @@ -567,9 +566,6 @@ uint32_t nxboot_main(void) { print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Powering on the CCPLEX...\n"); - /* Display splash screen. */ - display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); - /* Unmount everything. */ nxfs_unmount_all(); diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index 37cc63d9d..1e21f252c 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -85,6 +85,6 @@ void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address) fatal_error("Invalid splash screen format!\n"); } - /* Display the splash screen for three seconds. */ - udelay(3000000); + /* Display the splash screen for two and a half seconds. */ + udelay(2500000); } From dc2b8ebab9a97347528df16bf2fc490356cd8310 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 26 Jan 2019 00:59:27 -0800 Subject: [PATCH 389/489] fusee: remove unnecessary delay. --- fusee/fusee-secondary/src/main.c | 3 +++ fusee/fusee-secondary/src/splash_screen.c | 13 ++++++++++--- fusee/fusee-secondary/src/splash_screen.h | 1 + fusee/fusee-secondary/src/timers.h | 7 +++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 97983819e..bf2474fc3 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -111,6 +111,9 @@ int main(int argc, void **argv) { print(SCREEN_LOG_LEVEL_MANDATORY, "Now performing nxboot.\n"); uint32_t boot_memaddr = nxboot_main(); + /* Wait for the splash screen to have been displayed as long as it should be. */ + splash_screen_wait_delay(); + /* Finish boot. */ nxboot_finish(boot_memaddr); } else { /* TODO: What else do we want to do in terms of argc/argv? */ diff --git a/fusee/fusee-secondary/src/splash_screen.c b/fusee/fusee-secondary/src/splash_screen.c index 1e21f252c..38908f439 100644 --- a/fusee/fusee-secondary/src/splash_screen.c +++ b/fusee/fusee-secondary/src/splash_screen.c @@ -27,6 +27,8 @@ #undef u8 #undef u32 +static uint32_t g_splash_start_time = 0; + static void render_bmp(const uint32_t *bmp_data, uint32_t *framebuffer, uint32_t bmp_width, uint32_t bmp_height, uint32_t bmp_pos_x, uint32_t bmp_pos_y) { /* Render the BMP. */ for (uint32_t y = bmp_pos_y; y < (bmp_pos_y + bmp_height); y++) { @@ -39,6 +41,11 @@ static void render_bmp(const uint32_t *bmp_data, uint32_t *framebuffer, uint32_t console_display(framebuffer); } +void splash_screen_wait_delay(void) { + /* Ensure the splash screen is displayed for at least three seconds. */ + udelay_absolute(g_splash_start_time, 3000000); +} + void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address) { uint8_t *splash_screen = (uint8_t *)splash_screen_bmp; @@ -84,7 +91,7 @@ void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address) } else { fatal_error("Invalid splash screen format!\n"); } - - /* Display the splash screen for two and a half seconds. */ - udelay(2500000); + + /* Note the time we started displaying the splash. */ + g_splash_start_time = get_time_us(); } diff --git a/fusee/fusee-secondary/src/splash_screen.h b/fusee/fusee-secondary/src/splash_screen.h index 0cca4fe52..7bd665e6d 100644 --- a/fusee/fusee-secondary/src/splash_screen.h +++ b/fusee/fusee-secondary/src/splash_screen.h @@ -26,5 +26,6 @@ #define SPLASH_SCREEN_SIZE_MAX (SPLASH_SCREEN_HEIGHT_MAX * SPLASH_SCREEN_STRIDE * 4) void display_splash_screen_bmp(const char *custom_splash_path, void *fb_address); +void splash_screen_wait_delay(void); #endif diff --git a/fusee/fusee-secondary/src/timers.h b/fusee/fusee-secondary/src/timers.h index 1c2be85d7..547dbe844 100644 --- a/fusee/fusee-secondary/src/timers.h +++ b/fusee/fusee-secondary/src/timers.h @@ -81,6 +81,13 @@ static inline void udelay(uint32_t usecs) { while (get_time_us() - start < usecs); } +/** + * Delays until a number of usecs have passed since an absolute start time. + */ +static inline void udelay_absolute(uint32_t start, uint32_t usecs) { + while (get_time_us() - start < usecs); +} + /** * Delays for a given number of milliseconds. */ From 891b865da8a82cfbd35b279f65cf059079afa949 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 26 Jan 2019 05:58:02 -0800 Subject: [PATCH 390/489] fusee: change default power-off-time to 6 seconds. --- fusee/fusee-primary/src/hwinit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusee/fusee-primary/src/hwinit.c b/fusee/fusee-primary/src/hwinit.c index d5f68d82b..d3c7b82a2 100644 --- a/fusee/fusee-primary/src/hwinit.c +++ b/fusee/fusee-primary/src/hwinit.c @@ -249,7 +249,7 @@ void nx_hwinit() /* Configure the PMIC. */ uint8_t val = 0x40; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1); - val = 0x78; + val = 0x60; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1); val = 0x38; i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1); From 7bdb2ae8975a68f9fcb845e12a3b6352c387b14b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 26 Jan 2019 06:24:49 -0800 Subject: [PATCH 391/489] libstrat: update for deadlock fix --- stratosphere/libstratosphere | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 9bf228de3..236190f8a 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 9bf228de3e1e33ea62ed18b51853e5de6b4c4b41 +Subproject commit 236190f8a34f68586e04169ab7d16418e9519c45 From 3d6405be85bb3e97940a1b2e0723af491022de3c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 30 Jan 2019 13:53:16 -0800 Subject: [PATCH 392/489] exo: change config to its own static page This is necessary to support both pre-7.0.0 and 7.0.0... --- exosphere/src/exocfg.c | 12 ++---------- exosphere/src/exocfg.h | 15 +++++++-------- fusee/fusee-secondary/src/exocfg.h | 10 ++++------ fusee/fusee-secondary/src/nxboot.c | 2 +- 4 files changed, 14 insertions(+), 25 deletions(-) diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c index 08a929d7f..71b9cd3be 100644 --- a/exosphere/src/exocfg.c +++ b/exosphere/src/exocfg.c @@ -22,12 +22,7 @@ #include "mmu.h" #include "memory_map.h" -#define MAILBOX_BASE (MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) - -/* TODO: Should this be at a non-static location? */ -#define MAILBOX_EXOSPHERE_CONFIG (*((volatile exosphere_config_t *)(MAILBOX_BASE + 0xE40ULL))) - -static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_BOOTCONFIG, ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG, EXOSPHERE_FLAGS_DEFAULT}; +static exosphere_config_t g_exosphere_cfg = {MAGIC_EXOSPHERE_CONFIG, ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG, EXOSPHERE_FLAGS_DEFAULT}; static bool g_has_loaded_config = false; #define EXOSPHERE_CHECK_FLAG(flag) ((g_exosphere_cfg.flags & flag) != 0) @@ -42,11 +37,8 @@ unsigned int exosphere_load_config(void) { const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG.magic; - if (magic == MAGIC_EXOSPHERE_BOOTCONFIG) { + if (magic == MAGIC_EXOSPHERE_CONFIG) { g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG; - } else if (magic == MAGIC_EXOSPHERE_BOOTCONFIG_0) { - g_exosphere_cfg = MAILBOX_EXOSPHERE_CONFIG; - g_exosphere_cfg.flags = EXOSPHERE_FLAGS_DEFAULT; } return g_exosphere_cfg.target_firmware; diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h index 2f41c6cf1..a2c2580e7 100644 --- a/exosphere/src/exocfg.h +++ b/exosphere/src/exocfg.h @@ -25,17 +25,15 @@ /* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */ -/* "XBC0" */ -#define MAGIC_EXOSPHERE_BOOTCONFIG_0 (0x30434258) -/* "XBC1" */ -#define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258) +/* "EXO0" */ +#define MAGIC_EXOSPHERE_CONFIG (0x304F5845) #define EXOSPHERE_LOOSEN_PACKAGE2_RESTRICTIONS_FOR_DEBUG 1 -#define MAILBOX_BASE_PHYS (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) +#define MAILBOX_EXOSPHERE_CONFIG (*((volatile exosphere_config_t *)(0x8000F000ull))) -/* TODO: Should this be at a non-static location? */ -#define MAILBOX_EXOSPHERE_CONFIG_PHYS (*((volatile exosphere_config_t *)(MAILBOX_BASE_PHYS + 0xE40ULL))) +/* Exosphere config in DRAM shares physical/virtual mapping. */ +#define MAILBOX_EXOSPHERE_CONFIG_PHYS MAILBOX_EXOSPHERE_CONFIG #define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) @@ -46,6 +44,7 @@ typedef struct { unsigned int magic; unsigned int target_firmware; unsigned int flags; + unsigned int reserved; } exosphere_config_t; unsigned int exosphere_load_config(void); @@ -56,7 +55,7 @@ unsigned int exosphere_should_override_debugmode_user(void); static inline unsigned int exosphere_get_target_firmware_for_init(void) { const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic; - if (magic == MAGIC_EXOSPHERE_BOOTCONFIG || magic == MAGIC_EXOSPHERE_BOOTCONFIG_0) { + if (magic == MAGIC_EXOSPHERE_CONFIG) { return MAILBOX_EXOSPHERE_CONFIG_PHYS.target_firmware; } else { return ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG; diff --git a/fusee/fusee-secondary/src/exocfg.h b/fusee/fusee-secondary/src/exocfg.h index 55c8d12c5..72c9e89dd 100644 --- a/fusee/fusee-secondary/src/exocfg.h +++ b/fusee/fusee-secondary/src/exocfg.h @@ -21,11 +21,8 @@ /* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */ -/* "XBC0" */ -#define MAGIC_EXOSPHERE_BOOTCONFIG_0 (0x30434258) -/* "XBC1" */ -#define MAGIC_EXOSPHERE_BOOTCONFIG (0x31434258) - +/* "EXO0" */ +#define MAGIC_EXOSPHERE_CONFIG (0x304F5845) #define EXOSPHERE_FLAGS_DEFAULT 0x00000000 #define EXOSPHERE_FLAG_PERFORM_620_KEYGEN (1 << 0u) @@ -36,9 +33,10 @@ typedef struct { unsigned int magic; unsigned int target_firmware; unsigned int flags; + unsigned int reserved; } exosphere_config_t; -#define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x40002E40)) +#define MAILBOX_EXOSPHERE_CONFIGURATION ((volatile exosphere_config_t *)(0x8000F000ull)) #define EXOSPHERE_TARGETFW_KEY "target_firmware" #define EXOSPHERE_DEBUGMODE_PRIV_KEY "debugmode" diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 18697e75a..6a64c38c1 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -174,7 +174,7 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int keygen_type) { exosphere_config_t exo_cfg = {0}; - exo_cfg.magic = MAGIC_EXOSPHERE_BOOTCONFIG; + exo_cfg.magic = MAGIC_EXOSPHERE_CONFIG; exo_cfg.target_firmware = target_firmware; if (keygen_type) { exo_cfg.flags = EXOSPHERE_FLAGS_DEFAULT | EXOSPHERE_FLAG_PERFORM_620_KEYGEN; From f78fd29e38c6b924c144b098552549f99a79b4e8 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 30 Jan 2019 04:14:00 -0800 Subject: [PATCH 393/489] Add basic support to fusee for multiple tsec_root_keys. --- common/include/atmosphere/target_fw.h | 5 +- fusee/fusee-secondary/src/extkeys.c | 25 +++++----- fusee/fusee-secondary/src/extkeys.h | 2 +- fusee/fusee-secondary/src/key_derivation.c | 48 ++++++++++++------- fusee/fusee-secondary/src/masterkey.h | 5 +- fusee/fusee-secondary/src/nxboot.c | 15 ++++-- fusee/fusee-secondary/src/nxboot.h | 12 +++-- fusee/fusee-secondary/src/nxboot_iram.c | 19 ++++---- stratosphere/loader/source/ldr_ro_service.hpp | 2 + 9 files changed, 81 insertions(+), 52 deletions(-) diff --git a/common/include/atmosphere/target_fw.h b/common/include/atmosphere/target_fw.h index 03f689e94..8cbdb6112 100644 --- a/common/include/atmosphere/target_fw.h +++ b/common/include/atmosphere/target_fw.h @@ -24,11 +24,12 @@ #define ATMOSPHERE_TARGET_FIRMWARE_500 5 #define ATMOSPHERE_TARGET_FIRMWARE_600 6 #define ATMOSPHERE_TARGET_FIRMWARE_620 7 +#define ATMOSPHERE_TARGET_FIRMWARE_700 8 -#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_620 +#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_700 #define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE_100 -#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_620 +#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_700 /* TODO: What should this be, for release? */ #define ATMOSPHERE_TARGET_FIRMWARE_DEFAULT_FOR_DEBUG ATMOSPHERE_TARGET_FIRMWARE_CURRENT diff --git a/fusee/fusee-secondary/src/extkeys.c b/fusee/fusee-secondary/src/extkeys.c index 7315d4c5d..b64bdf232 100644 --- a/fusee/fusee-secondary/src/extkeys.c +++ b/fusee/fusee-secondary/src/extkeys.c @@ -197,18 +197,19 @@ void extkeys_initialize_keyset(fusee_extkeys_t *keyset, FILE *f) { continue; } int matched_key = 0; - if (strcmp(key, "tsec_root_key") == 0 || strcmp(key, "tsec_root_key_00") == 0) { - parse_hex_key(keyset->tsec_root_key, value, sizeof(keyset->tsec_root_key)); - matched_key = 1; - } else { - char test_name[0x100] = {0}; - for (unsigned int i = 0; i < 0x20 && !matched_key; i++) { - snprintf(test_name, sizeof(test_name), "master_kek_%02x", i); - if (strcmp(key, test_name) == 0) { - parse_hex_key(keyset->master_keks[i], value, sizeof(keyset->master_keks[i])); - matched_key = 1; - break; - } + char test_name[0x100] = {0}; + for (unsigned int i = 0; i < 0x20 && !matched_key; i++) { + snprintf(test_name, sizeof(test_name), "tsec_root_key_%02x", i); + if (strcmp(key, test_name) == 0) { + parse_hex_key(keyset->tsec_root_keys[i], value, sizeof(keyset->tsec_root_keys[i])); + matched_key = 1; + break; + } + snprintf(test_name, sizeof(test_name), "master_kek_%02x", i); + if (strcmp(key, test_name) == 0) { + parse_hex_key(keyset->master_keks[i], value, sizeof(keyset->master_keks[i])); + matched_key = 1; + break; } } } diff --git a/fusee/fusee-secondary/src/extkeys.h b/fusee/fusee-secondary/src/extkeys.h index 651868995..7a64aab9d 100644 --- a/fusee/fusee-secondary/src/extkeys.h +++ b/fusee/fusee-secondary/src/extkeys.h @@ -22,7 +22,7 @@ #include "masterkey.h" typedef struct { - unsigned char tsec_root_key[0x10]; + unsigned char tsec_root_keys[0x20][0x10]; unsigned char master_keks[0x20][0x10]; } fusee_extkeys_t; diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index 3b934f59c..05cb084e1 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -54,8 +54,9 @@ static const uint8_t AL16 masterkey_4x_seed[0x10] = { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 }; -static const uint8_t AL16 new_master_kek_seeds[1][0x10] = { +static const uint8_t AL16 new_master_kek_seeds[MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_600_610][0x10] = { {0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* MasterKek seed 06. */ + {0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* MasterKek seed 07. */ }; static nx_dec_keyblob_t AL16 g_dec_keyblobs[32]; @@ -118,7 +119,7 @@ int load_package1_key(uint32_t revision) { } /* Derive all Switch keys. */ -int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_key, unsigned int *out_keygen_type) { +int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, uint32_t available_revision, const void *tsec_key, void *tsec_root_keys, unsigned int *out_keygen_type) { uint8_t AL16 work_buffer[0x10]; uint8_t AL16 zeroes[0x10] = {0}; @@ -142,14 +143,31 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui /* Do 6.2.0+ keygen. */ if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { - if (memcmp(tsec_root_key, zeroes, 0x10) != 0) { - /* We got a valid key from emulation. */ - set_aes_keyslot(0xC, tsec_root_key, 0x10); - for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { - se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10); + uint32_t desired_keyblob; + switch (target_firmware) { + case ATMOSPHERE_TARGET_FIRMWARE_620: + desired_keyblob = MASTERKEY_REVISION_620; + break; + case ATMOSPHERE_TARGET_FIRMWARE_700: + desired_keyblob = MASTERKEY_REVISION_700_CURRENT; + break; + default: + fatal_error("Unknown target firmware: %02x!", target_firmware); + break; + } + + /* Try emulation result. */ + for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) { + void *tsec_root_key = (void *)((uintptr_t)tsec_root_keys + 0x10 * (rev - MASTERKEY_REVISION_620)); + if (memcmp(tsec_root_key, zeroes, 0x10) != 0) { + /* We got a valid key from emulation. */ + set_aes_keyslot(0xC, tsec_root_key, 0x10); + se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10); memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10); } - } else { + } + + if (memcmp(g_dec_keyblobs[desired_keyblob].master_kek, zeroes, 0x10) == 0) { /* Try reading the keys from a file. */ const char *keyfile = fuse_get_retail_type() != 0 ? "atmosphere/prod.keys" : "atmosphere/dev.keys"; FILE *extkey_file = fopen(keyfile, "r"); @@ -159,20 +177,18 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui } extkeys_initialize_keyset(&extkeys, extkey_file); fclose(extkey_file); - - if (memcmp(extkeys.tsec_root_key, zeroes, 0x10) != 0) { - set_aes_keyslot(0xC, extkeys.tsec_root_key, 0x10); - for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { - se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620_CURRENT], 0x10); + for (unsigned int rev = MASTERKEY_REVISION_620; rev < MASTERKEY_REVISION_MAX; rev++) { + if (memcmp(extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], zeroes, 0x10) != 0) { + set_aes_keyslot(0xC, extkeys.tsec_root_keys[rev - MASTERKEY_REVISION_620], 0x10); + se_aes_ecb_decrypt_block(0xC, work_buffer, 0x10, new_master_kek_seeds[rev - MASTERKEY_REVISION_620], 0x10); memcpy(g_dec_keyblobs[rev].master_kek, work_buffer, 0x10); - } - } else { - for (unsigned int rev = MASTERKEY_REVISION_620_CURRENT; rev < MASTERKEY_REVISION_MAX; rev++) { + } else { memcpy(g_dec_keyblobs[rev].master_kek, extkeys.master_keks[rev], 0x10); } } } + if (memcmp(g_dec_keyblobs[available_revision].master_kek, zeroes, 0x10) == 0) { fatal_error("Error: failed to derive master_kek_%02x!", available_revision); } diff --git a/fusee/fusee-secondary/src/masterkey.h b/fusee/fusee-secondary/src/masterkey.h index 0f1c20a0b..d116f5401 100644 --- a/fusee/fusee-secondary/src/masterkey.h +++ b/fusee/fusee-secondary/src/masterkey.h @@ -20,7 +20,7 @@ /* This is glue code to enable master key support across versions. */ /* TODO: Update to 0x8 on release of new master key. */ -#define MASTERKEY_REVISION_MAX 0x7 +#define MASTERKEY_REVISION_MAX 0x8 #define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_300 0x01 @@ -28,7 +28,8 @@ #define MASTERKEY_REVISION_400_410 0x03 #define MASTERKEY_REVISION_500_510 0x04 #define MASTERKEY_REVISION_600_610 0x05 -#define MASTERKEY_REVISION_620_CURRENT 0x06 +#define MASTERKEY_REVISION_620 0x06 +#define MASTERKEY_REVISION_700_CURRENT 0x07 #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 6a64c38c1..6693401ab 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -212,7 +212,7 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) { } } -static void nxboot_set_bootreason() { +static void nxboot_set_bootreason(void *bootreason_base) { boot_reason_t boot_reason = {0}; FILE *boot0; nvboot_config_table *bct; @@ -264,7 +264,7 @@ static void nxboot_set_bootreason() { boot_reason.boot_reason_state = 0x04; /* Set in memory. */ - memcpy((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE, &boot_reason, sizeof(boot_reason)); + memcpy(bootreason_base, &boot_reason, sizeof(boot_reason)); /* Clean up. */ free(bct); @@ -412,7 +412,12 @@ uint32_t nxboot_main(void) { /* Get the TSEC keys. */ uint8_t tsec_key[0x10] = {0}; uint8_t tsec_root_key[0x10] = {0}; - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { + if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) { + /* TODO: what to do here? */ + if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { + fatal_error("[NXBOOT]: Failed to get TSEC key!\n"); + } + } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { uint8_t tsec_keys[0x20] = {0}; /* Emulate the TSEC payload on 6.2.0+. */ @@ -438,9 +443,9 @@ uint32_t nxboot_main(void) { nxboot_configure_exosphere(target_firmware, keygen_type); /* Initialize Boot Reason on older firmware versions. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { + if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Initializing Boot Reason...\n"); - nxboot_set_bootreason(); + nxboot_set_bootreason((void *)MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(target_firmware)); } /* Read the warmboot firmware from a file, otherwise from Atmosphere's implementation. */ diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 6a042ea2a..15d31d88a 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -19,12 +19,14 @@ #include "utils.h" -#define MAILBOX_NX_BOOTLOADER_BASE 0x40002000 -#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE (MAILBOX_NX_BOOTLOADER_BASE + 0xE10) -#define MAKE_MAILBOX_NX_BOOTLOADER_REG(n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + n) +#define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00 +#define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000 +#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620)) +#define MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, n) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + n) -#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xEF8) -#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_MAILBOX_NX_BOOTLOADER_REG(0xEFC) +#define MAILBOX_NX_BOOTLOADER_BOOT_REASON_BASE(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10) +#define MAILBOX_NX_BOOTLOADER_SETUP_STATE(targetfw) MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, 0xF8) +#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(targetfw) MAKE_MAILBOX_NX_BOOTLOADER_REG(targetfw, 0xFC) #define NX_BOOTLOADER_STATE_INIT 0 #define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1 diff --git a/fusee/fusee-secondary/src/nxboot_iram.c b/fusee/fusee-secondary/src/nxboot_iram.c index 0705af10d..41156973d 100644 --- a/fusee/fusee-secondary/src/nxboot_iram.c +++ b/fusee/fusee-secondary/src/nxboot_iram.c @@ -28,6 +28,7 @@ #include "sysreg.h" void nxboot_finish(uint32_t boot_memaddr) { + uint32_t target_firmware = MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware; volatile tegra_se_t *se = se_get_regs(); /* Clear used keyslots. */ @@ -36,7 +37,7 @@ void nxboot_finish(uint32_t boot_memaddr) { /* Lock keyslots. */ set_aes_keyslot_flags(KEYSLOT_SWITCH_MASTERKEY, 0xFF); - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { + if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { set_aes_keyslot_flags(KEYSLOT_SWITCH_DEVICEKEY, 0xFF); } else { set_aes_keyslot_flags(KEYSLOT_SWITCH_4XOLDDEVICEKEY, 0xFF); @@ -61,11 +62,11 @@ void nxboot_finish(uint32_t boot_memaddr) { se->_0x0 &= 0xFFFFFFFB; /* Boot up Exosphère. */ - MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 0; - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; + MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) = 0; + if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { + MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_LOADED_PACKAGE2; } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; + MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_DRAM_INITIALIZED_4X; } /* Terminate the display. */ @@ -88,15 +89,15 @@ void nxboot_finish(uint32_t boot_memaddr) { } /* Wait for Exosphère to wake up. */ - while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE == 0) { + while (MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(target_firmware) == 0) { udelay(1); } /* Signal Exosphère. */ - if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED; + if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_400) { + MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED; } else { - MAILBOX_NX_BOOTLOADER_SETUP_STATE = NX_BOOTLOADER_STATE_FINISHED_4X; + MAILBOX_NX_BOOTLOADER_SETUP_STATE(target_firmware) = NX_BOOTLOADER_STATE_FINISHED_4X; } /* Halt ourselves in waitevent state. */ diff --git a/stratosphere/loader/source/ldr_ro_service.hpp b/stratosphere/loader/source/ldr_ro_service.hpp index 05bd9d058..2a12d5f1d 100644 --- a/stratosphere/loader/source/ldr_ro_service.hpp +++ b/stratosphere/loader/source/ldr_ro_service.hpp @@ -26,6 +26,7 @@ enum RoServiceCmd { Ro_Cmd_LoadNrr = 2, Ro_Cmd_UnloadNrr = 3, Ro_Cmd_Initialize = 4, + Ro_Cmd_LoadNrrEx = 10, }; class RelocatableObjectsService final : public IServiceObject { @@ -47,6 +48,7 @@ class RelocatableObjectsService final : public IServiceObject { Result LoadNrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size); Result UnloadNrr(PidDescriptor pid_desc, u64 nrr_address); Result Initialize(PidDescriptor pid_desc, CopiedHandle process_h); + Result LoadNrrEx(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<Ro_Cmd_LoadNro, &RelocatableObjectsService::LoadNro>(), From bdfd7946e3b30275872566e4f7dbc6ee56826e1d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 30 Jan 2019 21:55:04 -0800 Subject: [PATCH 394/489] ldr:ro: Correct LoadNrrEx definition, unimpl'd for now --- stratosphere/loader/source/ldr_ro_service.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/loader/source/ldr_ro_service.hpp b/stratosphere/loader/source/ldr_ro_service.hpp index 2a12d5f1d..e6169b530 100644 --- a/stratosphere/loader/source/ldr_ro_service.hpp +++ b/stratosphere/loader/source/ldr_ro_service.hpp @@ -48,7 +48,7 @@ class RelocatableObjectsService final : public IServiceObject { Result LoadNrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size); Result UnloadNrr(PidDescriptor pid_desc, u64 nrr_address); Result Initialize(PidDescriptor pid_desc, CopiedHandle process_h); - Result LoadNrrEx(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size); + Result LoadNrrEx(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size, CopiedHandle process_h); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta<Ro_Cmd_LoadNro, &RelocatableObjectsService::LoadNro>(), From 6c41e105c4c0940f7fa8bed8c58fa40426c04e90 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 30 Jan 2019 21:56:33 -0800 Subject: [PATCH 395/489] fusee: fix stack oob read --- fusee/fusee-secondary/src/nxboot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 6693401ab..e4b5e14a6 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -411,7 +411,7 @@ uint32_t nxboot_main(void) { /* Get the TSEC keys. */ uint8_t tsec_key[0x10] = {0}; - uint8_t tsec_root_key[0x10] = {0}; + uint8_t tsec_root_keys[0x20][0x10] = {0}; if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) { /* TODO: what to do here? */ if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { @@ -425,7 +425,7 @@ uint32_t nxboot_main(void) { /* Copy back the keys. */ memcpy((void *)tsec_key, (void *)tsec_keys, 0x10); - memcpy((void *)tsec_root_key, (void *)tsec_keys + 0x10, 0x10); + memcpy((void *)tsec_root_keys, (void *)tsec_keys + 0x10, 0x10); } else { /* Run the TSEC payload and get the key. */ if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { @@ -435,7 +435,7 @@ uint32_t nxboot_main(void) { /* Derive keydata. */ unsigned int keygen_type = 0; - if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_key, &keygen_type) != 0) { + if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) { fatal_error("[NXBOOT]: Key derivation failed!\n"); } From 46f4896992f08828ca964f94985e8e1b623e2133 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 30 Jan 2019 22:37:26 -0800 Subject: [PATCH 396/489] exo/fusee: add support for new master key --- exosphere/src/masterkey.c | 2 ++ exosphere/src/masterkey.h | 7 +++--- exosphere/src/package2.c | 33 +++++++++++++++++++++++---- exosphere/src/smc_api.c | 1 + exosphere/src/smc_user.c | 1 + fusee/fusee-secondary/src/masterkey.c | 2 ++ 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/exosphere/src/masterkey.c b/exosphere/src/masterkey.c index 30299a24d..547323b44 100644 --- a/exosphere/src/masterkey.c +++ b/exosphere/src/masterkey.c @@ -41,6 +41,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = {0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ {0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */ + {0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */ }; /* Retail unit keys. */ @@ -53,6 +54,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = {0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ {0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */ + {0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */ }; bool check_mkey_revision(unsigned int revision, bool is_retail) { diff --git a/exosphere/src/masterkey.h b/exosphere/src/masterkey.h index 9341e2cd6..5da7cd4c5 100644 --- a/exosphere/src/masterkey.h +++ b/exosphere/src/masterkey.h @@ -19,8 +19,8 @@ /* This is glue code to enable master key support across versions. */ -/* TODO: Update to 0x8 on release of new master key. */ -#define MASTERKEY_REVISION_MAX 0x7 +/* TODO: Update to 0x9 on release of new master key. */ +#define MASTERKEY_REVISION_MAX 0x8 #define MASTERKEY_REVISION_100_230 0x00 #define MASTERKEY_REVISION_300 0x01 @@ -28,7 +28,8 @@ #define MASTERKEY_REVISION_400_410 0x03 #define MASTERKEY_REVISION_500_510 0x04 #define MASTERKEY_REVISION_600_610 0x05 -#define MASTERKEY_REVISION_620_CURRENT 0x06 +#define MASTERKEY_REVISION_620 0x06 +#define MASTERKEY_REVISION_700_CURRENT 0x07 #define MASTERKEY_NUM_NEW_DEVICE_KEYS (MASTERKEY_REVISION_MAX - MASTERKEY_REVISION_400_410) diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 80d3c1180..62e982e61 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -41,25 +41,29 @@ static const uint8_t new_device_key_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] {0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D}, /* 4.x New Device Key Source. */ {0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C}, /* 5.x New Device Key Source. */ {0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4}, /* 6.x New Device Key Source. */ - {0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17} /* 6.2.0 New Device Key Source. */ + {0x8E, 0x09, 0x1F, 0x7A, 0xBB, 0xCA, 0x6A, 0xFB, 0xB8, 0x9B, 0xD5, 0xC1, 0x25, 0x9C, 0xA9, 0x17}, /* 6.2.0 New Device Key Source. */ + {0x8F, 0x77, 0x5A, 0x96, 0xB0, 0x94, 0xFD, 0x8D, 0x28, 0xE4, 0x19, 0xC8, 0x16, 0x1C, 0xDB, 0x3D}, /* 7.0.0 New Device Key Source. */ }; static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { {0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D}, /* 4.x New Device Keygen Source. */ {0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E}, /* 5.x New Device Keygen Source. */ {0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF}, /* 6.x New Device Keygen Source. */ - {0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB} /* 6.2.0 New Device Keygen Source. */ + {0x81, 0x3C, 0x6C, 0xBF, 0x5D, 0x21, 0xDE, 0x77, 0x20, 0xD9, 0x6C, 0xE3, 0x22, 0x06, 0xAE, 0xBB}, /* 6.2.0 New Device Keygen Source. */ + {0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E}, /* 7.0.0 New Device Keygen Source. */ }; static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = { {0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34}, /* 4.x New Device Keygen Source. */ {0x59, 0x2D, 0x20, 0x69, 0x33, 0xB5, 0x17, 0xBA, 0xCF, 0xB1, 0x4E, 0xFD, 0xE4, 0xC2, 0x7B, 0xA8}, /* 5.x New Device Keygen Source. */ {0xF6, 0xD8, 0x59, 0x63, 0x8F, 0x47, 0xCB, 0x4A, 0xD8, 0x74, 0x05, 0x7F, 0x88, 0x92, 0x33, 0xA5}, /* 6.x New Device Keygen Source. */ - {0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38} /* 6.2.0 New Device Keygen Source. */ + {0x20, 0xAB, 0xF2, 0x0F, 0x05, 0xE3, 0xDE, 0x2E, 0xA1, 0xFB, 0x37, 0x5E, 0x8B, 0x22, 0x1A, 0x38}, /* 6.2.0 New Device Keygen Source. */ + {0x60, 0xAE, 0x56, 0x68, 0x11, 0xE2, 0x0C, 0x99, 0xDE, 0x05, 0xAE, 0x68, 0x78, 0x85, 0x04, 0xAE}, /* 6.2.0 New Device Keygen Source. */ }; -static const uint8_t new_master_kek_sources[1][0x10] = { +static const uint8_t new_master_kek_sources[MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_600_610][0x10] = { {0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A}, /* 6.2.0 Master Kek Source. */ + {0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* 7.0.0 Master Kek Source. */ }; static const uint8_t keyblob_key_seed_00[0x10] = { @@ -134,6 +138,18 @@ static void setup_se(void) { } if (exosphere_get_target_firmware() >= ATMOSPHERE_TARGET_FIRMWARE_620 && exosphere_should_perform_620_keygen()) { + unsigned int master_kek_source_ind; + switch (exosphere_get_target_firmware()) { + case ATMOSPHERE_TARGET_FIRMWARE_620: + master_kek_source_ind = MASTERKEY_REVISION_620 - MASTERKEY_REVISION_600_610; + break; + case ATMOSPHERE_TARGET_FIRMWARE_700: + master_kek_source_ind = MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_600_610; + break; + default: + generic_panic(); + break; + } /* Start by generating device keys. */ se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_6XTSECKEY, work_buffer, 0x10, keyblob_key_seed_00, 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_4XOLDDEVICEKEY, KEYSLOT_SWITCH_6XSBK, work_buffer, 0x10); @@ -141,7 +157,7 @@ static void setup_se(void) { decrypt_data_into_keyslot(KEYSLOT_SWITCH_4XOLDDEVICEKEY, KEYSLOT_SWITCH_4XOLDDEVICEKEY, devicekey_seed, 0x10); /* Next, generate the master kek, and from there master key/device kek. We use different keyslots than Nintendo, here. */ - decrypt_data_into_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, new_master_kek_sources[0], 0x10); + decrypt_data_into_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, new_master_kek_sources[master_kek_source_ind], 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_MASTERKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, masterkey_seed, 0x10); decrypt_data_into_keyslot(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, KEYSLOT_SWITCH_6XTSECROOTKEY, devicekek_4x_seed, 0x10); clear_aes_keyslot(KEYSLOT_SWITCH_6XTSECROOTKEY); @@ -162,6 +178,7 @@ static void setup_se(void) { case ATMOSPHERE_TARGET_FIRMWARE_500: case ATMOSPHERE_TARGET_FIRMWARE_600: case ATMOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_700: derive_new_device_keys(KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY); break; } @@ -469,6 +486,9 @@ static void copy_warmboot_bin_to_dram() { case ATMOSPHERE_TARGET_FIRMWARE_620: warmboot_src = (uint8_t *)0x4003D800; break; + case ATMOSPHERE_TARGET_FIRMWARE_700: + warmboot_src = (uint8_t *)0x4003E000; + break; } uint8_t *warmboot_dst = (uint8_t *)0x8000D000; const size_t warmboot_size = 0x2000; @@ -533,6 +553,9 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { case ATMOSPHERE_TARGET_FIRMWARE_620: MAKE_REG32(PMC_BASE + 0x360) = 0xA8; break; + case ATMOSPHERE_TARGET_FIRMWARE_700: + MAKE_REG32(PMC_BASE + 0x360) = 0x129; + break; } } diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c index 373919162..39e0a7d52 100644 --- a/exosphere/src/smc_api.c +++ b/exosphere/src/smc_api.c @@ -176,6 +176,7 @@ void set_version_specific_smcs(void) { case ATMOSPHERE_TARGET_FIRMWARE_500: case ATMOSPHERE_TARGET_FIRMWARE_600: case ATMOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_700: /* No more LoadSecureExpModKey. */ g_smc_user_table[0xE].handler = NULL; g_smc_user_table[0xC].id = 0xC300D60C; diff --git a/exosphere/src/smc_user.c b/exosphere/src/smc_user.c index e042f179f..13a7ed367 100644 --- a/exosphere/src/smc_user.c +++ b/exosphere/src/smc_user.c @@ -50,6 +50,7 @@ static bool is_user_keyslot_valid(unsigned int keyslot) { return keyslot <= 3; case ATMOSPHERE_TARGET_FIRMWARE_600: case ATMOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_700: default: return keyslot <= 5; } diff --git a/fusee/fusee-secondary/src/masterkey.c b/fusee/fusee-secondary/src/masterkey.c index 3a4f6ae71..8e09c8a86 100644 --- a/fusee/fusee-secondary/src/masterkey.c +++ b/fusee/fusee-secondary/src/masterkey.c @@ -38,6 +38,7 @@ static const uint8_t mkey_vectors_dev[MASTERKEY_REVISION_MAX][0x10] = {0x9B, 0x84, 0x76, 0x14, 0x72, 0x94, 0x52, 0xCB, 0x54, 0x92, 0x9B, 0xC4, 0x8C, 0x5B, 0x0F, 0xBA}, /* Master key 03 encrypted with Master key 04. */ {0x78, 0xD5, 0xF1, 0x20, 0x3D, 0x16, 0xE9, 0x30, 0x32, 0x27, 0x34, 0x6F, 0xCF, 0xE0, 0x27, 0xDC}, /* Master key 04 encrypted with Master key 05. */ {0x6F, 0xD2, 0x84, 0x1D, 0x05, 0xEC, 0x40, 0x94, 0x5F, 0x18, 0xB3, 0x81, 0x09, 0x98, 0x8D, 0x4E}, /* Master key 05 encrypted with Master key 06. */ + {0x37, 0xAF, 0xAB, 0x35, 0x79, 0x09, 0xD9, 0x48, 0x29, 0xD2, 0xDB, 0xA5, 0xA5, 0xF5, 0x30, 0x19}, /* Master key 06 encrypted with Master key 07. */ }; /* Retail unit keys. */ @@ -50,6 +51,7 @@ static const uint8_t mkey_vectors[MASTERKEY_REVISION_MAX][0x10] = {0x6E, 0x7D, 0x2D, 0xC3, 0x0F, 0x59, 0xC8, 0xFA, 0x87, 0xA8, 0x2E, 0xD5, 0x89, 0x5E, 0xF3, 0xE9}, /* Master key 03 encrypted with Master key 04. */ {0xEB, 0xF5, 0x6F, 0x83, 0x61, 0x9E, 0xF8, 0xFA, 0xE0, 0x87, 0xD7, 0xA1, 0x4E, 0x25, 0x36, 0xEE}, /* Master key 04 encrypted with Master key 05. */ {0x1E, 0x1E, 0x22, 0xC0, 0x5A, 0x33, 0x3C, 0xB9, 0x0B, 0xA9, 0x03, 0x04, 0xBA, 0xDB, 0x07, 0x57}, /* Master key 05 encrypted with Master key 06. */ + {0xA4, 0xD4, 0x52, 0x6F, 0xD1, 0xE4, 0x36, 0xAA, 0x9F, 0xCB, 0x61, 0x27, 0x1C, 0x67, 0x65, 0x1F}, /* Master key 06 encrypted with Master key 07. */ }; static bool check_mkey_revision(unsigned int revision, bool is_retail) { From 506ac3f16792d09fb5cb8b9563ba1b66762c644b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 30 Jan 2019 23:13:27 -0800 Subject: [PATCH 397/489] exo: theoretical support for moved MAILBOX page --- exosphere/src/coldboot_init.c | 11 +++++++---- exosphere/src/memory_map.h | 24 ++++++++++++++++++++++++ exosphere/src/package2.c | 6 +++--- exosphere/src/package2.h | 15 ++++++++------- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/exosphere/src/coldboot_init.c b/exosphere/src/coldboot_init.c index 1ea3ebb9c..275f12f6f 100644 --- a/exosphere/src/coldboot_init.c +++ b/exosphere/src/coldboot_init.c @@ -26,7 +26,7 @@ #undef MAILBOX_NX_BOOTLOADER_BASE #undef TIMERS_BASE -#define MAILBOX_NX_BOOTLOADER_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) +#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MMIO_GET_DEVICE_7X_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) : (MMIO_GET_DEVICE_PA(MMIO_DEVID_NXBOOTLOADER_MAILBOX)) #define TIMERS_BASE (MMIO_GET_DEVICE_PA(MMIO_DEVID_TMRs_WDTs)) extern const uint8_t __start_cold[]; @@ -48,13 +48,16 @@ static void identity_map_all_mappings(uintptr_t *mmu_l1_tbl, uintptr_t *mmu_l3_t } } -static void mmio_map_all_devices(uintptr_t *mmu_l3_tbl) { +static void mmio_map_all_devices(uintptr_t *mmu_l3_tbl, unsigned int target_firmware) { static const uintptr_t pas[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; static const size_t sizes[] = { TUPLE_FOLD_LEFT_1(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; static const bool is_secure[] = { TUPLE_FOLD_LEFT_2(EVAL(MMIO_DEVID_MAX), _MMAPDEV, COMMA) }; + + static const uintptr_t pas_7x[] = { TUPLE_FOLD_LEFT_0(EVAL(MMIO_DEVID_MAX), _MMAPDEV7X, COMMA) }; for(size_t i = 0, offset = 0; i < MMIO_DEVID_MAX; i++) { - mmio_map_device(mmu_l3_tbl, MMIO_BASE + offset, pas[i], sizes[i], is_secure[i]); + uintptr_t pa = (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) ? pas[i] : pas_7x[i]; + mmio_map_device(mmu_l3_tbl, MMIO_BASE + offset, pa, sizes[i], is_secure[i]); offset += sizes[i]; offset += 0x1000; } @@ -127,7 +130,7 @@ static void configure_ttbls(unsigned int target_firmware) { mmu_map_table(2, mmu_l2_tbl, 0x1F0000000ull, mmu_l3_tbl, 0); identity_map_all_mappings(mmu_l1_tbl, mmu_l3_tbl); - mmio_map_all_devices(mmu_l3_tbl); + mmio_map_all_devices(mmu_l3_tbl, target_firmware); lp0_entry_map_all_ram_segments(mmu_l3_tbl); warmboot_map_all_ram_segments(mmu_l3_tbl); tzram_map_all_segments(mmu_l3_tbl, target_firmware); diff --git a/exosphere/src/memory_map.h b/exosphere/src/memory_map.h index 50bd32c7b..83ceca4e9 100644 --- a/exosphere/src/memory_map.h +++ b/exosphere/src/memory_map.h @@ -52,6 +52,29 @@ #define _MMAPDEV19 ( 0x00000000ull, 0x1000ull, true ) /* AMS userpage, NOT mapped at startup */ #define _MMAPDEV20 ( 0x40038000ull, 0x5000ull, true ) /* DEBUG: IRAM */ +/* MMIO 7.0.0+. (addr). */ +#define _MMAPDEV7X0 ( 0x50041000ull ) /* ARM Interrupt Distributor */ +#define _MMAPDEV7X1 ( 0x50042000ull ) /* Interrupt Controller Physical CPU interface */ +#define _MMAPDEV7X2 ( 0x70006000ull ) /* UART */ +#define _MMAPDEV7X3 ( 0x60006000ull ) /* Clock and Reset */ +#define _MMAPDEV7X4 ( 0x7000E000ull ) /* RTC, PMC */ +#define _MMAPDEV7X5 ( 0x60005000ull ) /* TMRs, WDTs */ +#define _MMAPDEV7X6 ( 0x6000C000ull ) /* System Registers */ +#define _MMAPDEV7X7 ( 0x70012000ull ) /* SE */ +#define _MMAPDEV7X8 ( 0x700F0000ull ) /* SYSCTR0 */ +#define _MMAPDEV7X9 ( 0x70019000ull ) /* MC */ +#define _MMAPDEV7X10 ( 0x7000F000ull ) /* FUSE (0x7000F800) */ +#define _MMAPDEV7X11 ( 0x70000000ull ) /* MISC */ +#define _MMAPDEV7X12 ( 0x60007000ull ) /* Flow Controller */ +#define _MMAPDEV7X13 ( 0x40000000ull ) /* NX bootloader mailbox page */ +#define _MMAPDEV7X14 ( 0x7000D000ull ) /* I2C-5,6 - SPI 2B-1 to 4 */ +#define _MMAPDEV7X15 ( 0x6000D000ull ) /* GPIO-1 - GPIO-8 */ +#define _MMAPDEV7X16 ( 0x7000C000ull ) /* I2C-I2C4 */ +#define _MMAPDEV7X17 ( 0x6000F000ull ) /* Exception vectors */ +#define _MMAPDEV7X18 ( 0x00000000ull ) /* AMS irampage, NOT mapped at startup */ +#define _MMAPDEV7X19 ( 0x00000000ull ) /* AMS userpage, NOT mapped at startup */ +#define _MMAPDEV7X20 ( 0x40038000ull ) /* DEBUG: IRAM */ + /* LP0 entry ram segments (addr, size, additional attributes) */ #define _MMAPLP0ES0 ( 0x40020000ull, 0x10000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* Encrypted TZRAM */ #define _MMAPLP0ES1 ( 0x40003000ull, 0x01000ull, MMU_PTE_BLOCK_NS | ATTRIB_MEMTYPE_DEVICE ) /* LP0 entry code */ @@ -140,6 +163,7 @@ #define IDENTITY_IS_MAPPING_BLOCK_RANGE(mapping_id) (TUPLE_ELEM_3(CAT(_MMAPID, EVAL(mapping_id)))) #define MMIO_GET_DEVICE_PA(device_id) (TUPLE_ELEM_0(CAT(_MMAPDEV, EVAL(device_id)))) +#define MMIO_GET_DEVICE_7X_PA(device_id) (TUPLE_ELEM_0(CAT(_MMAPDEV, EVAL(device_id)))) #define MMIO_GET_DEVICE_ADDRESS(device_id)\ (\ (TUPLE_FOLD_LEFT_1(EVAL(device_id), _MMAPDEV, PLUS) EVAL(MMIO_BASE)) +\ diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 62e982e61..e43b852c0 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -508,7 +508,7 @@ static void copy_warmboot_bin_to_dram() { } static void sync_with_nx_bootloader(int state) { - while (MAILBOX_NX_BOOTLOADER_SETUP_STATE < state) { + while (MAILBOX_NX_BOOTLOADER_SETUP_STATE(exosphere_get_target_firmware()) < state) { wait(100); } } @@ -566,7 +566,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { setup_current_core_state(); /* Save boot reason to global. */ - bootconfig_load_boot_reason((volatile boot_reason_t *)(MAILBOX_NX_BOOTLOADER_BOOT_REASON)); + bootconfig_load_boot_reason((volatile boot_reason_t *)(MAILBOX_NX_BOOTLOADER_BOOT_REASON(exosphere_get_target_firmware()))); /* Initialize cache'd random bytes for kernel. */ randomcache_init(); @@ -575,7 +575,7 @@ void load_package2(coldboot_crt0_reloc_list_t *reloc_list) { /* memset((void *)reloc_list->reloc_base, 0, reloc_list->loaded_bin_size); */ /* Let NX Bootloader know that we're running. */ - MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE = 1; + MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(exosphere_get_target_firmware()) = 1; /* Wait for 1 second, to allow time for NX_BOOTLOADER to draw to the screen. This is useful for debugging. */ /* wait(1000000); */ diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h index 97ac7638c..ed563a0d9 100644 --- a/exosphere/src/package2.h +++ b/exosphere/src/package2.h @@ -21,18 +21,19 @@ #include "utils.h" #include "bootconfig.h" +#include "exocfg.h" #include "memory_map.h" /* Physaddr 0x40002EF8 */ -static inline uintptr_t get_nx_bootloader_mailbox_base(void) { - return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX); +static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) { + return MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_NXBOOTLOADER_MAILBOX) + ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (0x000ull) : (0xE00ull)); } -#define MAILBOX_NX_BOOTLOADER_BASE (get_nx_bootloader_mailbox_base()) +#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) (get_nx_bootloader_mailbox_base(targetfw)) -#define MAILBOX_NX_SECMON_BOOT_TIME MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xE08ull) +#define MAILBOX_NX_SECMON_BOOT_TIME(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x08ull) -#define MAILBOX_NX_BOOTLOADER_SETUP_STATE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEF8ull) +#define MAILBOX_NX_BOOTLOADER_SETUP_STATE(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0xF8ull) #define NX_BOOTLOADER_STATE_INIT 0 #define NX_BOOTLOADER_STATE_MOVED_BOOTCONFIG 1 @@ -45,9 +46,9 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(void) { #define NX_BOOTLOADER_STATE_FINISHED_4X 4 /* Physaddr 0x40002EFC */ -#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE + 0xEFCULL) +#define MAILBOX_NX_BOOTLOADER_IS_SECMON_AWAKE(targetfw) MAKE_REG32(MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0xFCULL) -#define MAILBOX_NX_BOOTLOADER_BOOT_REASON (MAILBOX_NX_BOOTLOADER_BASE + 0xE10ULL) +#define MAILBOX_NX_BOOTLOADER_BOOT_REASON(targetfw) (MAILBOX_NX_BOOTLOADER_BASE(targetfw) + 0x10ULL) #define NX_BOOTLOADER_BOOTCONFIG_POINTER ((void *)(0x4003D000ull)) #define NX_BOOTLOADER_BOOTCONFIG_POINTER_6X ((void *)(0x4003F800ull)) From a71b2d9329055b1ac1948eece74bd76feebcea8a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 31 Jan 2019 01:39:53 -0800 Subject: [PATCH 398/489] Exo: update package2 constants --- exosphere/src/package2.c | 2 +- exosphere/src/package2.h | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index e43b852c0..3d2842085 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -363,7 +363,7 @@ static bool validate_package2_metadata(package2_meta_t *metadata) { /* Perform version checks. */ /* We will be compatible with all package2s released before current, but not newer ones. */ - if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_620_CURRENT) { + if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_700_CURRENT) { return true; } diff --git a/exosphere/src/package2.h b/exosphere/src/package2.h index ed563a0d9..05212f20a 100644 --- a/exosphere/src/package2.h +++ b/exosphere/src/package2.h @@ -69,7 +69,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) { #define PACKAGE2_MAXVER_400_410 0x6 #define PACKAGE2_MAXVER_500_510 0x7 #define PACKAGE2_MAXVER_600_610 0x8 -#define PACKAGE2_MAXVER_620_CURRENT 0x9 +#define PACKAGE2_MAXVER_620 0x9 +#define PACKAGE2_MAXVER_700_CURRENT 0xA #define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_200 0x4 @@ -78,7 +79,8 @@ static inline uintptr_t get_nx_bootloader_mailbox_base(unsigned int targetfw) { #define PACKAGE2_MINVER_400_410 0x7 #define PACKAGE2_MINVER_500_510 0x8 #define PACKAGE2_MINVER_600_610 0x9 -#define PACKAGE2_MINVER_620_CURRENT 0xA +#define PACKAGE2_MINVER_620 0xA +#define PACKAGE2_MINVER_700_CURRENT 0xB typedef struct { union { From 752e0757d9b0b134d1c0c53192b104ff4109b23a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 31 Jan 2019 02:23:43 -0800 Subject: [PATCH 399/489] fusee: basic byok support for 7.0.0 --- fusee/fusee-secondary/src/kernel_patches.c | 77 ++++++++++++++++++++++ fusee/fusee-secondary/src/key_derivation.c | 1 + fusee/fusee-secondary/src/nxboot.c | 19 ++++-- fusee/fusee-secondary/src/package2.c | 2 +- fusee/fusee-secondary/src/package2.h | 6 +- 5 files changed, 97 insertions(+), 8 deletions(-) diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index 5b83d8ef9..cd00da4a9 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -308,6 +308,60 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_send)[] = {0xA9BF2 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv)[] = {0x08, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE9, 0x6F, 0x40, 0xF9, 0xE8, 0x03, 0x15, 0x2A, 0xB5, 0x0A, 0x00, 0x11}; static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_recv)[] = {0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; +/* + stp x10, x11, [sp, #-0x10]! + ldr x11, [sp, #0x70] + mov w10, w25 + lsl x10, x10, #2 + ldr x10, [x11, x10] + mov x9, #0x0000ffffffffffff + and x8, x10, x9 + mov x9, #0xffff000000000000 + and x10, x10, x9 + mov x9, #0xfffe000000000000 + cmp x10, x9 + beq #0x20 + + stp x8, x9, [sp, #-0x10]! + ldr x8, [x21] + ldr x8, [x8, #0x38] + mov x0, x21 + blr x8 + ldp x8, x9, [sp],#0x10 + mov x8, x0 + + ldp x10, x11, [sp],#0x10 + mov x0, x8 +*/ +static const uint8_t MAKE_KERNEL_PATTERN_NAME(700, proc_id_send)[] = {0xA8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x15, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x19, 0x2A, 0x39, 0x0B, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3}; +static const instruction_t MAKE_KERNEL_HOOK_NAME(700, proc_id_send)[] = {0xA9BF2FEA, 0xF9403BEB, 0x2A1903EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; +/* + stp x10, x11, [sp, #-0x10]! + ldr x11, [sp, #0x98] + mov w10, w22 + lsl x10, x10, #2 + ldr x10, [x11, x10] + mov x9, #0x0000ffffffffffff + and x8, x10, x9 + mov x9, #0xffff000000000000 + and x10, x10, x9 + mov x9, #0xfffe000000000000 + cmp x10, x9 + beq #0x20 + + stp x8, x9, [sp, #-0x10]! + ldr x8, [x27] + ldr x8, [x8, #0x38] + mov x0, x27 + blr x8 + ldp x8, x9, [sp],#0x10 + mov x8, x0 + + ldp x10, x11, [sp],#0x10 + mov x0, x8 +*/ +static const uint8_t MAKE_KERNEL_PATTERN_NAME(700, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xA9, 0x83, 0x50, 0xF8, 0xE8, 0x03, 0x16, 0x2A, 0xD6, 0x0A, 0x00, 0x11}; +static const instruction_t MAKE_KERNEL_HOOK_NAME(700, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; /* Hook Definitions. */ static const kernel_hook_t g_kernel_hooks_100[] = { @@ -436,6 +490,24 @@ static const kernel_hook_t g_kernel_hooks_600[] = { .payload = MAKE_KERNEL_HOOK_NAME(600, proc_id_recv) } }; +static const kernel_hook_t g_kernel_hooks_700[] = { + { /* Send Message Process ID Patch. */ + .pattern_size = 0x1C, + .pattern = MAKE_KERNEL_PATTERN_NAME(700, proc_id_send), + .pattern_hook_offset = 0x0, + .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(700, proc_id_send))/sizeof(instruction_t), + .branch_back_offset = 0x10, + .payload = MAKE_KERNEL_HOOK_NAME(700, proc_id_send) + }, + { /* Receive Message Process ID Patch. */ + .pattern_size = 0x1C, + .pattern = MAKE_KERNEL_PATTERN_NAME(700, proc_id_recv), + .pattern_hook_offset = 0x0, + .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(700, proc_id_recv))/sizeof(instruction_t), + .branch_back_offset = 0x10, + .payload = MAKE_KERNEL_HOOK_NAME(700, proc_id_recv) + } +}; #define KERNEL_HOOKS(vers) .num_hooks = sizeof(g_kernel_hooks_##vers)/sizeof(kernel_hook_t), .hooks = g_kernel_hooks_##vers, @@ -481,6 +553,11 @@ static const kernel_info_t g_kernel_infos[] = { .hash = {0x85, 0x97, 0x40, 0xF6, 0xC0, 0x3E, 0x3D, 0x44, 0xDE, 0xA4, 0xA0, 0x35, 0xFD, 0x12, 0x9C, 0xD4, 0x4F, 0x9C, 0x36, 0x53, 0x74, 0x54, 0x2C, 0x9C, 0x55, 0x47, 0xC4, 0x25, 0xF1, 0x42, 0xFB, 0x97}, .free_code_space_offset = 0x5EE00, KERNEL_HOOKS(600) + }, + { /* 7.0.0. */ + .hash = {0xA2, 0x5E, 0x47, 0x0C, 0x8E, 0x6D, 0x2F, 0xD7, 0x5D, 0xAD, 0x24, 0xD7, 0xD8, 0x24, 0x34, 0xFB, 0xCD, 0x77, 0xBB, 0xE6, 0x66, 0x03, 0xCB, 0xAF, 0xAB, 0x85, 0x45, 0xA0, 0x91, 0xAF, 0x34, 0x25}, + .free_code_space_offset = 0x5FE80, + KERNEL_HOOKS(700) } }; diff --git a/fusee/fusee-secondary/src/key_derivation.c b/fusee/fusee-secondary/src/key_derivation.c index 05cb084e1..00afec437 100644 --- a/fusee/fusee-secondary/src/key_derivation.c +++ b/fusee/fusee-secondary/src/key_derivation.c @@ -222,6 +222,7 @@ int derive_nx_keydata(uint32_t target_firmware, const nx_keyblob_t *keyblobs, ui case ATMOSPHERE_TARGET_FIRMWARE_500: case ATMOSPHERE_TARGET_FIRMWARE_600: case ATMOSPHERE_TARGET_FIRMWARE_620: + case ATMOSPHERE_TARGET_FIRMWARE_700: decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index e4b5e14a6..92eef7440 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -166,8 +166,10 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { fatal_error("[NXBOOT]: Unable to identify package1!\n"); } } + case 0x0F: + return ATMOSPHERE_TARGET_FIRMWARE_700; default: - return 0; + fatal_error("[NXBOOT]: Unable to identify package1!\n"); } } @@ -381,7 +383,7 @@ uint32_t nxboot_main(void) { /* Read the TSEC firmware from a file, otherwise from PK1L. */ if (loader_ctx->tsecfw_path[0] != '\0') { tsec_fw_size = get_file_size(loader_ctx->tsecfw_path); - if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900)) { + if ((tsec_fw_size != 0) && (tsec_fw_size != 0xF00 && tsec_fw_size != 0x2900 && tsec_fw_size != 0x3000)) { fatal_error("[NXBOOT]: TSEC firmware from %s has a wrong size!\n", loader_ctx->tsecfw_path); } else if (tsec_fw_size == 0) { fatal_error("[NXBOOT]: Could not read the TSEC firmware from %s!\n", loader_ctx->tsecfw_path); @@ -400,7 +402,9 @@ uint32_t nxboot_main(void) { if (!package1_get_tsec_fw(&tsec_fw, package1loader, package1loader_size)) { fatal_error("[NXBOOT]: Failed to read the TSEC firmware from Package1loader!\n"); } - if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_620) { + if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_700) { + tsec_fw_size = 0x3000; + } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { tsec_fw_size = 0x2900; } else { tsec_fw_size = 0xF00; @@ -413,7 +417,10 @@ uint32_t nxboot_main(void) { uint8_t tsec_key[0x10] = {0}; uint8_t tsec_root_keys[0x20][0x10] = {0}; if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) { - /* TODO: what to do here? */ + /* TODO: what else to do here? */ + + /* Patch TSEC firmware to exit after generating TSEC key. */ + *((volatile uint16_t *)((uintptr_t)tsec_fw + 0x2DB5)) = 0x02F8; if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { fatal_error("[NXBOOT]: Failed to get TSEC key!\n"); } @@ -499,8 +506,10 @@ uint32_t nxboot_main(void) { warmboot_memaddr = (void *)0x8000D000; } else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_600) { warmboot_memaddr = (void *)0x4003B000; - } else { + } else if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { warmboot_memaddr = (void *)0x4003D800; + } else { + warmboot_memaddr = (void *)0x4003E000; } print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Copying warmboot firmware...\n"); diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 1f9cdad9b..e6672708b 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -214,7 +214,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[] /* Perform version checks. */ /* We will be compatible with all package2s released before current, but not newer ones. */ - if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_620_CURRENT) { + if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_700_CURRENT) { return true; } diff --git a/fusee/fusee-secondary/src/package2.h b/fusee/fusee-secondary/src/package2.h index b537f670d..e0bcefc6c 100644 --- a/fusee/fusee-secondary/src/package2.h +++ b/fusee/fusee-secondary/src/package2.h @@ -35,7 +35,8 @@ #define PACKAGE2_MAXVER_400_410 0x6 #define PACKAGE2_MAXVER_500_510 0x7 #define PACKAGE2_MAXVER_600_610 0x8 -#define PACKAGE2_MAXVER_620_CURRENT 0x9 +#define PACKAGE2_MAXVER_620 0x9 +#define PACKAGE2_MAXVER_700_CURRENT 0xA #define PACKAGE2_MINVER_100 0x3 #define PACKAGE2_MINVER_200 0x4 @@ -44,7 +45,8 @@ #define PACKAGE2_MINVER_400_410 0x7 #define PACKAGE2_MINVER_500_510 0x8 #define PACKAGE2_MINVER_600_610 0x9 -#define PACKAGE2_MINVER_620_CURRENT 0xA +#define PACKAGE2_MINVER_620 0xA +#define PACKAGE2_MINVER_700_CURRENT 0xB #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) From 53488eb8e5e712d402e21d37be72d82ac770ab51 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 31 Jan 2019 02:55:10 -0800 Subject: [PATCH 400/489] Add nogc patches for 7.0.0 --- ...FFE2699C93305D6A69D465CF597D67465CD69BACCE8.ips | Bin 0 -> 27 bytes ...3BE4B74BED302613F1E442581FD863708E39112DB50.ips | Bin 0 -> 27 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 common/defaults/kip_patches/default_nogc/2ADBE97E9B5F41779EC95FFE2699C93305D6A69D465CF597D67465CD69BACCE8.ips create mode 100644 common/defaults/kip_patches/default_nogc/2CCE659CEC536A8E4D91F3BE4B74BED302613F1E442581FD863708E39112DB50.ips diff --git a/common/defaults/kip_patches/default_nogc/2ADBE97E9B5F41779EC95FFE2699C93305D6A69D465CF597D67465CD69BACCE8.ips b/common/defaults/kip_patches/default_nogc/2ADBE97E9B5F41779EC95FFE2699C93305D6A69D465CF597D67465CD69BACCE8.ips new file mode 100644 index 0000000000000000000000000000000000000000..0b7bc228e70adc81f00b9a0cd72572f4ddf2a8ac GIT binary patch literal 27 icmWG=3~}}lJ;2Jq*dXkbz`*f<SzhY^bNn?|e>VVOs0W7t literal 0 HcmV?d00001 diff --git a/common/defaults/kip_patches/default_nogc/2CCE659CEC536A8E4D91F3BE4B74BED302613F1E442581FD863708E39112DB50.ips b/common/defaults/kip_patches/default_nogc/2CCE659CEC536A8E4D91F3BE4B74BED302613F1E442581FD863708E39112DB50.ips new file mode 100644 index 0000000000000000000000000000000000000000..3ee63f4f30b75644fc38c945799ea6be4937f5df GIT binary patch literal 27 icmWG=3~}}lE8WV#*dY8vfPv!yv%J;;=J;!_{%!zop$Jm| literal 0 HcmV?d00001 From de07ed42bb3e71f2bd3c016aa75514d4cf9a7262 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 31 Jan 2019 03:08:14 -0800 Subject: [PATCH 401/489] update libstratosphere for new GetRuntimeFirmwareVersion() impl --- stratosphere/libstratosphere | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 236190f8a..2f1fa654f 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 236190f8a34f68586e04169ab7d16418e9519c45 +Subproject commit 2f1fa654f29b6bdab4daacb6e4b5fadd22429c86 From a3adb70a04def3608c34f18f1b4e21bdf8e29539 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 31 Jan 2019 03:24:19 -0800 Subject: [PATCH 402/489] stratosphere: version detect via svcCallSecureMonitor --- stratosphere/boot/boot_100.json | 3 ++- stratosphere/boot/boot_200.json | 3 ++- stratosphere/creport/creport.json | 4 +++- stratosphere/fatal/fatal.json | 2 +- stratosphere/fs_mitm/fs_mitm.json | 3 ++- stratosphere/libstratosphere | 2 +- stratosphere/loader/loader.json | 3 ++- stratosphere/pm/pm.json | 3 ++- stratosphere/set_mitm/set_mitm.json | 3 ++- stratosphere/sm/sm.json | 3 ++- 10 files changed, 19 insertions(+), 10 deletions(-) diff --git a/stratosphere/boot/boot_100.json b/stratosphere/boot/boot_100.json index 194005f95..88121c0d0 100644 --- a/stratosphere/boot/boot_100.json +++ b/stratosphere/boot/boot_100.json @@ -61,7 +61,8 @@ "svcDetachDeviceAddressSpace": "0x58", "svcMapDeviceAddressSpaceAligned": "0x5A", "svcUnmapDeviceAddressSpace": "0x5C", - "svcFlushProcessDataCache": "0x5F" + "svcFlushProcessDataCache": "0x5F", + "svcCallSecureMonitor": "0x7F" } }, { diff --git a/stratosphere/boot/boot_200.json b/stratosphere/boot/boot_200.json index 01a0fb41d..e9419b6bb 100644 --- a/stratosphere/boot/boot_200.json +++ b/stratosphere/boot/boot_200.json @@ -64,7 +64,8 @@ "svcDetachDeviceAddressSpace": "0x58", "svcMapDeviceAddressSpaceAligned": "0x5A", "svcUnmapDeviceAddressSpace": "0x5C", - "svcFlushProcessDataCache": "0x5F" + "svcFlushProcessDataCache": "0x5F", + "svcCallSecureMonitor": "0x7F" } }, { diff --git a/stratosphere/creport/creport.json b/stratosphere/creport/creport.json index 5cc6b0c15..fc21c3b61 100644 --- a/stratosphere/creport/creport.json +++ b/stratosphere/creport/creport.json @@ -19,6 +19,7 @@ ], "service_access": [ "csrng", + "spl:", "erpt:c", "fatal:u", "ns:dev", @@ -92,7 +93,8 @@ "svcGetDebugThreadContext": "0x67", "svcQueryDebugProcessMemory": "0x69", "svcReadDebugProcessMemory": "0x6a", - "svcGetDebugThreadParam": "0x6d" + "svcGetDebugThreadParam": "0x6d", + "svcCallSecureMonitor": "0x7F" } }, { diff --git a/stratosphere/fatal/fatal.json b/stratosphere/fatal/fatal.json index 0bdbeeeb2..5e9a17fd3 100644 --- a/stratosphere/fatal/fatal.json +++ b/stratosphere/fatal/fatal.json @@ -14,7 +14,7 @@ "filesystem_access": { "permissions": "0xFFFFFFFFFFFFFFFF" }, - "service_access": ["bpc", "bpc:c", "erpt:c", "fsp-srv", "gpio", "i2c", "lbl", "lm", "nvdrv:s", "pcv", "pl:u", "pm:info", "psm", "set", "set:sys", "spsm", "vi:m", "vi:s"], + "service_access": ["bpc", "bpc:c", "erpt:c", "fsp-srv", "gpio", "i2c", "lbl", "lm", "nvdrv:s", "pcv", "pl:u", "pm:info", "psm", "set", "set:sys", "spsm", "spl:", "vi:m", "vi:s"], "service_host": ["fatal:p", "fatal:u", "time:s"], "kernel_capabilities": [{ "type": "kernel_flags", diff --git a/stratosphere/fs_mitm/fs_mitm.json b/stratosphere/fs_mitm/fs_mitm.json index d90a68b96..5171ce029 100644 --- a/stratosphere/fs_mitm/fs_mitm.json +++ b/stratosphere/fs_mitm/fs_mitm.json @@ -70,7 +70,8 @@ "svcDetachDeviceAddressSpace": "0x58", "svcMapDeviceAddressSpaceAligned": "0x5a", "svcUnmapDeviceAddressSpace": "0x5c", - "svcGetSystemInfo": "0x6f" + "svcGetSystemInfo": "0x6f", + "svcCallSecureMonitor": "0x7F" } } ] diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 2f1fa654f..fb12edcbb 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 2f1fa654f29b6bdab4daacb6e4b5fadd22429c86 +Subproject commit fb12edcbbaa5ef7a08fbb44d4aa13f0f37136537 diff --git a/stratosphere/loader/loader.json b/stratosphere/loader/loader.json index 76ab67e85..b79900517 100644 --- a/stratosphere/loader/loader.json +++ b/stratosphere/loader/loader.json @@ -69,7 +69,8 @@ "svcUnmapProcessMemory" : "0x75", "svcMapProcessCodeMemory" : "0x77", "svcUnmapProcessCodeMemory" : "0x78", - "svcCreateProcess" : "0x79" + "svcCreateProcess" : "0x79", + "svcCallSecureMonitor": "0x7F" } } ] diff --git a/stratosphere/pm/pm.json b/stratosphere/pm/pm.json index af1a699c6..3e74d3ed8 100644 --- a/stratosphere/pm/pm.json +++ b/stratosphere/pm/pm.json @@ -71,7 +71,8 @@ "svcGetProcessInfo": "0x7c", "svcCreateResourceLimit": "0x7d", "svcSetResourceLimitLimitValue": "0x7e", - "svcGetSystemInfo": "0x6f" + "svcGetSystemInfo": "0x6f", + "svcCallSecureMonitor": "0x7F" } } ] diff --git a/stratosphere/set_mitm/set_mitm.json b/stratosphere/set_mitm/set_mitm.json index 1f71cf7c1..634ac777c 100644 --- a/stratosphere/set_mitm/set_mitm.json +++ b/stratosphere/set_mitm/set_mitm.json @@ -94,7 +94,8 @@ "svcDetachDeviceAddressSpace": "0x58", "svcMapDeviceAddressSpaceAligned": "0x5a", "svcUnmapDeviceAddressSpace": "0x5c", - "svcGetSystemInfo": "0x6f" + "svcGetSystemInfo": "0x6f", + "svcCallSecureMonitor": "0x7F" } }, { diff --git a/stratosphere/sm/sm.json b/stratosphere/sm/sm.json index cff1006d0..0734e82b7 100644 --- a/stratosphere/sm/sm.json +++ b/stratosphere/sm/sm.json @@ -65,7 +65,8 @@ "svcGetMemoryInfo" : "0x6F", "svcCreatePort" : "0x70", "svcManageNamedPort" : "0x71", - "svcConnectToPort" : "0x72" + "svcConnectToPort" : "0x72", + "svcCallSecureMonitor": "0x7F" } } ] From 4e99eaa5904e6a49bcf8201e06bfb184641f1ec5 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 31 Jan 2019 03:32:47 -0800 Subject: [PATCH 403/489] pm: Update for 7.0.0 --- stratosphere/pm/source/pm_resource_limits.cpp | 3 +++ stratosphere/pm/source/pm_shell.cpp | 7 +++++++ stratosphere/pm/source/pm_shell.hpp | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/stratosphere/pm/source/pm_resource_limits.cpp b/stratosphere/pm/source/pm_resource_limits.cpp index d4649bf07..d6d5b70f3 100644 --- a/stratosphere/pm/source/pm_resource_limits.cpp +++ b/stratosphere/pm/source/pm_resource_limits.cpp @@ -122,6 +122,9 @@ void ResourceLimitUtils::InitializeLimits() { memcpy(&g_resource_limits, &g_resource_limits_deprecated, sizeof(g_resource_limits)); } + /* 7.0.0+: Nintendo restricts the number of system threads here, from 0x260 -> 0x60. */ + /* We will not do this. */ + if (kernelAbove600()) { /* NOTE: 5 is a fake type, official code does not do this. */ /* This is done for ease of backwards compatibility. */ diff --git a/stratosphere/pm/source/pm_shell.cpp b/stratosphere/pm/source/pm_shell.cpp index a1e6dbd12..0dc429a95 100644 --- a/stratosphere/pm/source/pm_shell.cpp +++ b/stratosphere/pm/source/pm_shell.cpp @@ -104,3 +104,10 @@ Result ShellService::GetApplicationProcessId(Out<u64> pid) { Result ShellService::BoostSystemMemoryResourceLimit(u64 sysmem_size) { return ResourceLimitUtils::BoostSystemMemoryResourceLimit(sysmem_size); } + +Result ShellService::BoostSystemThreadsResourceLimit() { + /* Starting in 7.0.0, Nintendo reduces the number of system threads from 0x260 to 0x60, */ + /* Until this command is called to double that amount to 0xC0. */ + /* We will simply not reduce the number of system threads available for no reason. */ + return 0x0; +} diff --git a/stratosphere/pm/source/pm_shell.hpp b/stratosphere/pm/source/pm_shell.hpp index cd707a510..3316e168c 100644 --- a/stratosphere/pm/source/pm_shell.hpp +++ b/stratosphere/pm/source/pm_shell.hpp @@ -43,7 +43,9 @@ enum ShellCmd_5X { Shell_Cmd_5X_GetProcessEventType = 4, Shell_Cmd_5X_NotifyBootFinished = 5, Shell_Cmd_5X_GetApplicationProcessId = 6, - Shell_Cmd_5X_BoostSystemMemoryResourceLimit = 7 + Shell_Cmd_5X_BoostSystemMemoryResourceLimit = 7, + + Shell_Cmd_BoostSystemThreadsResourceLimit = 8 }; class ShellService final : public IServiceObject { @@ -59,6 +61,7 @@ class ShellService final : public IServiceObject { void NotifyBootFinished(); Result GetApplicationProcessId(Out<u64> pid); Result BoostSystemMemoryResourceLimit(u64 sysmem_size); + Result BoostSystemThreadsResourceLimit(); public: DEFINE_SERVICE_DISPATCH_TABLE { /* 1.0.0-4.0.0 */ @@ -84,5 +87,8 @@ class ShellService final : public IServiceObject { MakeServiceCommandMeta<Shell_Cmd_5X_NotifyBootFinished, &ShellService::NotifyBootFinished, FirmwareVersion_500>(), MakeServiceCommandMeta<Shell_Cmd_5X_GetApplicationProcessId, &ShellService::GetApplicationProcessId, FirmwareVersion_500>(), MakeServiceCommandMeta<Shell_Cmd_5X_BoostSystemMemoryResourceLimit, &ShellService::BoostSystemMemoryResourceLimit, FirmwareVersion_500>(), + + /* 7.0.0-* */ + MakeServiceCommandMeta<Shell_Cmd_BoostSystemThreadsResourceLimit, &ShellService::BoostSystemThreadsResourceLimit, FirmwareVersion_700>(), }; }; From 5f836aca6da839e57e5d887a0c0b7eb7c137e43f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 31 Jan 2019 04:46:20 -0800 Subject: [PATCH 404/489] Loader: set 7.0.0+ process bit when relevant --- stratosphere/loader/source/ldr_process_creation.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 6253b9bfc..76f9c85e2 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -16,6 +16,7 @@ #include <switch.h> #include <algorithm> +#include <stratosphere.hpp> #include "ldr_process_creation.hpp" #include "ldr_registration.hpp" @@ -47,12 +48,19 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle return 0x809; } out_proc_info->process_flags = (npdm->header->mmu_flags & 0xF); + /* Set Bit 4 (?) and EnableAslr based on argument flags. */ out_proc_info->process_flags |= ((arg_flags & 3) << 4) ^ 0x20; /* Set UseSystemMemBlocks if application type is 1. */ u32 application_type = NpdmUtils::GetApplicationType((u32 *)npdm->aci0_kac, npdm->aci0->kac_size / sizeof(u32)); if ((application_type & 3) == 1) { out_proc_info->process_flags |= 0x40; + /* 7.0.0+: Set unknown bit related to system resource heap if relevant. */ + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_700) { + if ((npdm->header->mmu_flags & 0x10)) { + out_proc_info->process_flags |= 0x800; + } + } } /* 3.0.0+ System Resource Size. */ From e715197290127f60c2feaf046845571bdff0d75e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 29 Jan 2019 02:29:29 -0800 Subject: [PATCH 405/489] Merge fs.mitm and set.mitm. --- Makefile | 2 +- fusee/fusee-secondary/Makefile | 4 +- fusee/fusee-secondary/src/kernel_patches.c | 2 +- fusee/fusee-secondary/src/stratosphere.c | 17 +- stratosphere/Makefile | 2 +- stratosphere/{fs_mitm => ams_mitm}/Makefile | 2 +- .../fs_mitm.json => ams_mitm/ams_mitm.json} | 2 +- .../source/amsmitm_main.cpp} | 45 ++- .../ams_mitm/source/amsmitm_modules.cpp | 60 ++++ .../ams_mitm/source/amsmitm_modules.hpp | 28 ++ .../{fs_mitm => ams_mitm}/source/debug.cpp | 0 .../{fs_mitm => ams_mitm}/source/debug.hpp | 0 .../source/fs_mitm}/fs_istorage.hpp | 2 +- .../source/fs_mitm}/fs_shim.c | 0 .../source/fs_mitm}/fs_shim.h | 0 .../source/fs_mitm}/fsmitm_boot0storage.cpp | 0 .../source/fs_mitm}/fsmitm_boot0storage.hpp | 0 .../source/fs_mitm}/fsmitm_layeredrom.cpp | 4 +- .../source/fs_mitm}/fsmitm_layeredrom.hpp | 2 +- .../ams_mitm/source/fs_mitm/fsmitm_main.cpp | 50 ++++ .../ams_mitm/source/fs_mitm/fsmitm_main.hpp | 29 ++ .../source/fs_mitm}/fsmitm_romfsbuild.cpp | 5 +- .../source/fs_mitm}/fsmitm_romfsbuild.hpp | 2 +- .../source/fs_mitm}/fsmitm_romstorage.hpp | 0 .../source/fs_mitm}/fsmitm_service.cpp | 4 +- .../source/fs_mitm}/fsmitm_service.hpp | 2 +- .../{set_mitm => ams_mitm}/source/ini.c | 0 .../{fs_mitm => ams_mitm}/source/ini.h | 0 .../ams_mitm/source/set_mitm/setmitm_main.cpp | 59 ++++ .../ams_mitm/source/set_mitm/setmitm_main.hpp | 29 ++ .../set_mitm}/setsys_firmware_version.cpp | 0 .../set_mitm}/setsys_firmware_version.hpp | 0 .../source/set_mitm}/setsys_mitm_service.cpp | 0 .../source/set_mitm}/setsys_mitm_service.hpp | 0 .../set_mitm}/setsys_settings_items.cpp | 59 ++-- .../set_mitm}/setsys_settings_items.hpp | 2 +- .../source/set_mitm}/setsys_shim.c | 0 .../source/set_mitm}/setsys_shim.h | 0 .../{fs_mitm => ams_mitm}/source/sha256.c | 0 .../{fs_mitm => ams_mitm}/source/sha256.h | 0 .../source/sha256_armv8.s | 0 .../source/utils.cpp} | 35 ++- .../source/utils.hpp} | 6 +- .../{set_mitm => eclct.stub}/Makefile | 0 .../eclct.stub.json} | 16 +- stratosphere/eclct.stub/source/eclct_stub.cpp | 65 +++++ stratosphere/fs_mitm/source/fsmitm_main.cpp | 119 -------- stratosphere/fs_mitm/source/ini.c | 269 ------------------ stratosphere/pm/source/pm_boot2.cpp | 3 +- stratosphere/set_mitm/source/ini.h | 130 --------- 50 files changed, 426 insertions(+), 630 deletions(-) rename stratosphere/{fs_mitm => ams_mitm}/Makefile (99%) rename stratosphere/{fs_mitm/fs_mitm.json => ams_mitm/ams_mitm.json} (99%) rename stratosphere/{set_mitm/source/setmitm_main.cpp => ams_mitm/source/amsmitm_main.cpp} (67%) create mode 100644 stratosphere/ams_mitm/source/amsmitm_modules.cpp create mode 100644 stratosphere/ams_mitm/source/amsmitm_modules.hpp rename stratosphere/{fs_mitm => ams_mitm}/source/debug.cpp (100%) rename stratosphere/{fs_mitm => ams_mitm}/source/debug.hpp (100%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fs_istorage.hpp (99%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fs_shim.c (100%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fs_shim.h (100%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_boot0storage.cpp (100%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_boot0storage.hpp (100%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_layeredrom.cpp (99%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_layeredrom.hpp (98%) create mode 100644 stratosphere/ams_mitm/source/fs_mitm/fsmitm_main.cpp create mode 100644 stratosphere/ams_mitm/source/fs_mitm/fsmitm_main.hpp rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_romfsbuild.cpp (99%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_romfsbuild.hpp (99%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_romstorage.hpp (100%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_service.cpp (99%) rename stratosphere/{fs_mitm/source => ams_mitm/source/fs_mitm}/fsmitm_service.hpp (99%) rename stratosphere/{set_mitm => ams_mitm}/source/ini.c (100%) rename stratosphere/{fs_mitm => ams_mitm}/source/ini.h (100%) create mode 100644 stratosphere/ams_mitm/source/set_mitm/setmitm_main.cpp create mode 100644 stratosphere/ams_mitm/source/set_mitm/setmitm_main.hpp rename stratosphere/{set_mitm/source => ams_mitm/source/set_mitm}/setsys_firmware_version.cpp (100%) rename stratosphere/{set_mitm/source => ams_mitm/source/set_mitm}/setsys_firmware_version.hpp (100%) rename stratosphere/{set_mitm/source => ams_mitm/source/set_mitm}/setsys_mitm_service.cpp (100%) rename stratosphere/{set_mitm/source => ams_mitm/source/set_mitm}/setsys_mitm_service.hpp (100%) rename stratosphere/{set_mitm/source => ams_mitm/source/set_mitm}/setsys_settings_items.cpp (89%) rename stratosphere/{set_mitm/source => ams_mitm/source/set_mitm}/setsys_settings_items.hpp (96%) rename stratosphere/{set_mitm/source => ams_mitm/source/set_mitm}/setsys_shim.c (100%) rename stratosphere/{set_mitm/source => ams_mitm/source/set_mitm}/setsys_shim.h (100%) rename stratosphere/{fs_mitm => ams_mitm}/source/sha256.c (100%) rename stratosphere/{fs_mitm => ams_mitm}/source/sha256.h (100%) rename stratosphere/{fs_mitm => ams_mitm}/source/sha256_armv8.s (100%) rename stratosphere/{fs_mitm/source/fsmitm_utils.cpp => ams_mitm/source/utils.cpp} (97%) rename stratosphere/{fs_mitm/source/fsmitm_utils.hpp => ams_mitm/source/utils.hpp} (94%) rename stratosphere/{set_mitm => eclct.stub}/Makefile (100%) rename stratosphere/{set_mitm/set_mitm.json => eclct.stub/eclct.stub.json} (92%) create mode 100644 stratosphere/eclct.stub/source/eclct_stub.cpp delete mode 100644 stratosphere/fs_mitm/source/fsmitm_main.cpp delete mode 100644 stratosphere/fs_mitm/source/ini.c delete mode 100644 stratosphere/set_mitm/source/ini.h diff --git a/Makefile b/Makefile index af0c8ac6b..cdc0d4dd0 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ dist: all cp -r common/defaults/kip_patches atmosphere-$(AMSVER)/atmosphere/kip_patches cp stratosphere/creport/creport.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036/exefs.nsp cp stratosphere/fatal/fatal.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034/exefs.nsp - cp stratosphere/set_mitm/set_mitm.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp + cp stratosphere/eclct.stub/eclct.stub.nsp atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/exefs.nsp cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags touch atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032/flags/boot2.flag diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 8a964e2d3..ed51bffb8 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -83,7 +83,7 @@ ifneq ($(BUILD),$(notdir $(CURDIR))) export OUTPUT := $(CURDIR)/$(TARGET) export TOPDIR := $(CURDIR) -export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/fs_mitm +export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/stratosphere/sm $(AMS)/stratosphere/boot $(AMS)/stratosphere/ams_mitm export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ $(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/exosphere/rebootstub \ @@ -94,7 +94,7 @@ export DEPSDIR := $(CURDIR)/$(BUILD) CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -KIPFILES := loader.kip pm.kip sm.kip fs_mitm.kip boot_100.kip boot_200.kip +KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip boot_100.kip boot_200.kip BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp $(KIPFILES) #--------------------------------------------------------------------------------- diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index cd00da4a9..54561b4ed 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -556,7 +556,7 @@ static const kernel_info_t g_kernel_infos[] = { }, { /* 7.0.0. */ .hash = {0xA2, 0x5E, 0x47, 0x0C, 0x8E, 0x6D, 0x2F, 0xD7, 0x5D, 0xAD, 0x24, 0xD7, 0xD8, 0x24, 0x34, 0xFB, 0xCD, 0x77, 0xBB, 0xE6, 0x66, 0x03, 0xCB, 0xAF, 0xAB, 0x85, 0x45, 0xA0, 0x91, 0xAF, 0x34, 0x25}, - .free_code_space_offset = 0x5FE80, + .free_code_space_offset = 0x5FEC0, KERNEL_HOOKS(700) } }; diff --git a/fusee/fusee-secondary/src/stratosphere.c b/fusee/fusee-secondary/src/stratosphere.c index 9deaa8720..53d402bf1 100644 --- a/fusee/fusee-secondary/src/stratosphere.c +++ b/fusee/fusee-secondary/src/stratosphere.c @@ -32,6 +32,7 @@ #include "loader_kip.h" #include "pm_kip.h" #include "sm_kip.h" +#include "ams_mitm_kip.h" #include "boot_100_kip.h" #include "boot_200_kip.h" #undef u8 @@ -43,13 +44,13 @@ static ini1_header_t *g_sd_files_ini1 = NULL; static bool g_stratosphere_loader_enabled = true; static bool g_stratosphere_sm_enabled = true; static bool g_stratosphere_pm_enabled = true; -static bool g_stratosphere_fs_mitm_enabled = true; +static bool g_stratosphere_ams_mitm_enabled = true; static bool g_stratosphere_boot_enabled = false; extern const uint8_t boot_100_kip[], boot_200_kip[]; -extern const uint8_t loader_kip[], pm_kip[], sm_kip[], fs_mitm_kip[]; +extern const uint8_t loader_kip[], pm_kip[], sm_kip[], ams_mitm_kip[]; extern const uint32_t boot_100_kip_size, boot_200_kip_size; -extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, fs_mitm_kip_size; +extern const uint32_t loader_kip_size, pm_kip_size, sm_kip_size, ams_mitm_kip_size; /* GCC doesn't consider the size as const... we have to write it ourselves. */ @@ -89,8 +90,8 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { num_processes++; } - if (g_stratosphere_fs_mitm_enabled) { - size += fs_mitm_kip_size; + if (g_stratosphere_ams_mitm_enabled) { + size += ams_mitm_kip_size; num_processes++; } @@ -128,9 +129,9 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware) { data += sm_kip_size; } - if (g_stratosphere_fs_mitm_enabled) { - memcpy(data, fs_mitm_kip, fs_mitm_kip_size); - data += fs_mitm_kip_size; + if (g_stratosphere_ams_mitm_enabled) { + memcpy(data, ams_mitm_kip, ams_mitm_kip_size); + data += ams_mitm_kip_size; } if (g_stratosphere_boot_enabled) { diff --git a/stratosphere/Makefile b/stratosphere/Makefile index 5369af9e4..2e718b3ab 100644 --- a/stratosphere/Makefile +++ b/stratosphere/Makefile @@ -1,4 +1,4 @@ -MODULES := loader pm sm boot fs_mitm set_mitm creport fatal +MODULES := loader pm sm boot ams_mitm eclct.stub creport fatal SUBFOLDERS := libstratosphere $(MODULES) diff --git a/stratosphere/fs_mitm/Makefile b/stratosphere/ams_mitm/Makefile similarity index 99% rename from stratosphere/fs_mitm/Makefile rename to stratosphere/ams_mitm/Makefile index 4ebc8f6d9..404225ba3 100644 --- a/stratosphere/fs_mitm/Makefile +++ b/stratosphere/ams_mitm/Makefile @@ -26,7 +26,7 @@ endif #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := source +SOURCES := source source/fs_mitm source/set_mitm DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src diff --git a/stratosphere/fs_mitm/fs_mitm.json b/stratosphere/ams_mitm/ams_mitm.json similarity index 99% rename from stratosphere/fs_mitm/fs_mitm.json rename to stratosphere/ams_mitm/ams_mitm.json index 5171ce029..e2efc65e9 100644 --- a/stratosphere/fs_mitm/fs_mitm.json +++ b/stratosphere/ams_mitm/ams_mitm.json @@ -1,5 +1,5 @@ { - "name": "fs.mitm", + "name": "ams.mitm", "title_id": "0x010041544D530000", "main_thread_stack_size": "0x20000", "main_thread_priority": 43, diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/ams_mitm/source/amsmitm_main.cpp similarity index 67% rename from stratosphere/set_mitm/source/setmitm_main.cpp rename to stratosphere/ams_mitm/source/amsmitm_main.cpp index 44a5b3172..8f1a5f84b 100644 --- a/stratosphere/set_mitm/source/setmitm_main.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_main.cpp @@ -23,15 +23,15 @@ #include <atmosphere.h> #include <stratosphere.hpp> -#include "setsys_mitm_service.hpp" -#include "setsys_settings_items.hpp" +#include "amsmitm_modules.hpp" +#include "utils.hpp" extern "C" { extern u32 __start__; u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x50000 + #define INNER_HEAP_SIZE 0x1000000 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -61,9 +61,9 @@ void __appInit(void) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); } - rc = setsysInitialize(); + rc = fsInitialize(); if (R_FAILED(rc)) { - fatalSimple(rc); + fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); } CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); @@ -71,36 +71,27 @@ void __appInit(void) { void __appExit(void) { /* Cleanup services. */ - setsysExit(); + fsExit(); smExit(); } -struct SetSysManagerOptions { - static const size_t PointerBufferSize = 0x100; - static const size_t MaxDomains = 4; - static const size_t MaxDomainObjects = 0x100; -}; - -using SetMitmManager = WaitableManager<SetSysManagerOptions>; - int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); + HosThread initializer_thread; - /* Load settings from SD card. */ - SettingsItemManager::RefreshConfiguration(); - - /* TODO: What's a good timeout value to use here? */ - auto server_manager = new SetMitmManager(3); - - /* Create set:sys mitm. */ - AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 60); - - /* Loop forever, servicing our services. */ - server_manager->Process(); - - delete server_manager; + LaunchAllMitmModules(); + if (R_FAILED(initializer_thread.Initialize(&Utils::InitializeThreadFunc, NULL, 0x4000, 0x15))) { + /* TODO: Panic. */ + } + if (R_FAILED(initializer_thread.Start())) { + /* TODO: Panic. */ + } + + /* Wait for all mitm modules to end. */ + WaitAllMitmModules(); + return 0; } diff --git a/stratosphere/ams_mitm/source/amsmitm_modules.cpp b/stratosphere/ams_mitm/source/amsmitm_modules.cpp new file mode 100644 index 000000000..d2446b77a --- /dev/null +++ b/stratosphere/ams_mitm/source/amsmitm_modules.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <stratosphere.hpp> +#include <cstring> +#include "debug.hpp" + +#include "amsmitm_modules.hpp" + +#include "fs_mitm/fsmitm_main.hpp" +#include "set_mitm/setmitm_main.hpp" + +static HosThread g_module_threads[MitmModuleId_Count]; + +static const struct { + ThreadFunc main; + u32 priority; + u32 stack_size; +} g_module_definitions[MitmModuleId_Count] = { + { &FsMitmMain, FsMitmPriority, FsMitmStackSize }, /* FsMitm */ + { &SetMitmMain, SetMitmPriority, SetMitmStackSize }, /* SetMitm */ +}; + +void LaunchAllMitmModules() { + /* Create thread for each module. */ + for (u32 i = 0; i < static_cast<u32>(MitmModuleId_Count); i++) { + const auto cur_module = &g_module_definitions[i]; + if (R_FAILED(g_module_threads[i].Initialize(cur_module->main, nullptr, cur_module->stack_size, cur_module->priority))) { + std::abort(); + } + } + + /* Start thread for each module. */ + for (u32 i = 0; i < static_cast<u32>(MitmModuleId_Count); i++) { + if (R_FAILED(g_module_threads[i].Start())) { + std::abort(); + } + } +} + +void WaitAllMitmModules() { + /* Wait on thread for each module. */ + for (u32 i = 0; i < static_cast<u32>(MitmModuleId_Count); i++) { + g_module_threads[i].Join(); + } +} \ No newline at end of file diff --git a/stratosphere/ams_mitm/source/amsmitm_modules.hpp b/stratosphere/ams_mitm/source/amsmitm_modules.hpp new file mode 100644 index 000000000..eac0cb6fe --- /dev/null +++ b/stratosphere/ams_mitm/source/amsmitm_modules.hpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +enum MitmModuleId : u32 { + MitmModuleId_FsMitm = 0, + MitmModuleId_SetMitm = 1, + + MitmModuleId_Count = 2, +}; + +void LaunchAllMitmModules(); + +void WaitAllMitmModules(); \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/debug.cpp b/stratosphere/ams_mitm/source/debug.cpp similarity index 100% rename from stratosphere/fs_mitm/source/debug.cpp rename to stratosphere/ams_mitm/source/debug.cpp diff --git a/stratosphere/fs_mitm/source/debug.hpp b/stratosphere/ams_mitm/source/debug.hpp similarity index 100% rename from stratosphere/fs_mitm/source/debug.hpp rename to stratosphere/ams_mitm/source/debug.hpp diff --git a/stratosphere/fs_mitm/source/fs_istorage.hpp b/stratosphere/ams_mitm/source/fs_mitm/fs_istorage.hpp similarity index 99% rename from stratosphere/fs_mitm/source/fs_istorage.hpp rename to stratosphere/ams_mitm/source/fs_mitm/fs_istorage.hpp index 82a75619e..77e58302d 100644 --- a/stratosphere/fs_mitm/source/fs_istorage.hpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fs_istorage.hpp @@ -19,7 +19,7 @@ #include <stratosphere.hpp> #include "fs_shim.h" -#include "debug.hpp" +#include "../debug.hpp" enum FsIStorageCmd : u32 { FsIStorageCmd_Read = 0, diff --git a/stratosphere/fs_mitm/source/fs_shim.c b/stratosphere/ams_mitm/source/fs_mitm/fs_shim.c similarity index 100% rename from stratosphere/fs_mitm/source/fs_shim.c rename to stratosphere/ams_mitm/source/fs_mitm/fs_shim.c diff --git a/stratosphere/fs_mitm/source/fs_shim.h b/stratosphere/ams_mitm/source/fs_mitm/fs_shim.h similarity index 100% rename from stratosphere/fs_mitm/source/fs_shim.h rename to stratosphere/ams_mitm/source/fs_mitm/fs_shim.h diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_boot0storage.cpp similarity index 100% rename from stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_boot0storage.cpp diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_boot0storage.hpp similarity index 100% rename from stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_boot0storage.hpp diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_layeredrom.cpp similarity index 99% rename from stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_layeredrom.cpp index f6a791870..fe81b7eeb 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_layeredrom.cpp @@ -18,8 +18,8 @@ #include <stratosphere.hpp> #include "fsmitm_layeredrom.hpp" -#include "fsmitm_utils.hpp" -#include "debug.hpp" +#include "../utils.hpp" +#include "../debug.hpp" IStorage::~IStorage() = default; diff --git a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_layeredrom.hpp similarity index 98% rename from stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_layeredrom.hpp index 01be3af01..b2970390a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_layeredrom.hpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_layeredrom.hpp @@ -20,7 +20,7 @@ #include "fsmitm_romstorage.hpp" #include "fsmitm_romfsbuild.hpp" -#include "fsmitm_utils.hpp" +#include "../utils.hpp" /* Represents a merged RomFS. */ diff --git a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_main.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_main.cpp new file mode 100644 index 000000000..bf66ed5d9 --- /dev/null +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_main.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +#include "fsmitm_main.hpp" +#include "fsmitm_service.hpp" + +#include "../utils.hpp" + +struct FsMitmManagerOptions { + static const size_t PointerBufferSize = 0x800; + static const size_t MaxDomains = 0x40; + static const size_t MaxDomainObjects = 0x4000; +}; +using FsMitmManager = WaitableManager<FsMitmManagerOptions>; + +void FsMitmMain(void *arg) { + /* Create server manager. */ + auto server_manager = new FsMitmManager(5); + + /* Create fsp-srv mitm. */ + AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); + + /* Loop forever, servicing our services. */ + server_manager->Process(); + + delete server_manager; +} + diff --git a/stratosphere/ams_mitm/source/fs_mitm/fsmitm_main.hpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_main.hpp new file mode 100644 index 000000000..400ada6c8 --- /dev/null +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_main.hpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +constexpr u32 FsMitmPriority = 43; +constexpr u32 FsMitmStackSize = 0x8000; + +void FsMitmMain(void *arg); \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfsbuild.cpp similarity index 99% rename from stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfsbuild.cpp index 7b63b2b0a..611b949da 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfsbuild.cpp @@ -17,10 +17,10 @@ #include <switch.h> #include <string.h> #include <stratosphere.hpp> -#include "fsmitm_utils.hpp" +#include "../utils.hpp" #include "fsmitm_romfsbuild.hpp" -#include "debug.hpp" +#include "../debug.hpp" void RomFSBuildContext::VisitDirectory(FsFileSystem *filesys, RomFSBuildDirectoryContext *parent) { FsDir dir; @@ -367,7 +367,6 @@ void RomFSBuildContext::Build(std::vector<RomFSSourceInfo> *out_infos) { cur_entry->name_size = name_size; memset(cur_entry->name, 0, (cur_entry->name_size + 3) & ~3); memcpy(cur_entry->name, cur_dir->path + cur_dir->cur_path_ofs, name_size); - } /* Delete directories. */ diff --git a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfsbuild.hpp similarity index 99% rename from stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfsbuild.hpp index 4da8b30e4..e76b7e7c0 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romfsbuild.hpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romfsbuild.hpp @@ -20,7 +20,7 @@ #include "fsmitm_romstorage.hpp" -#include "debug.hpp" +#include "../debug.hpp" #define ROMFS_ENTRY_EMPTY 0xFFFFFFFF #define ROMFS_FILEPARTITION_OFS 0x200 diff --git a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_romstorage.hpp similarity index 100% rename from stratosphere/fs_mitm/source/fsmitm_romstorage.hpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_romstorage.hpp diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.cpp similarity index 99% rename from stratosphere/fs_mitm/source/fsmitm_service.cpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.cpp index 0b1e1cf18..5804a6bfe 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.cpp @@ -23,12 +23,12 @@ #include "fsmitm_service.hpp" #include "fs_shim.h" -#include "fsmitm_utils.hpp" +#include "../utils.hpp" #include "fsmitm_boot0storage.hpp" #include "fsmitm_romstorage.hpp" #include "fsmitm_layeredrom.hpp" -#include "debug.hpp" +#include "../debug.hpp" static HosMutex g_StorageCacheLock; static std::unordered_map<u64, std::weak_ptr<IStorageInterface>> g_StorageCache; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.hpp similarity index 99% rename from stratosphere/fs_mitm/source/fsmitm_service.hpp rename to stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.hpp index e7d2ad571..c7cd6ed54 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/ams_mitm/source/fs_mitm/fsmitm_service.hpp @@ -18,7 +18,7 @@ #include <switch.h> #include <stratosphere.hpp> #include "fs_istorage.hpp" -#include "fsmitm_utils.hpp" +#include "../utils.hpp" enum FspSrvCmd : u32 { FspSrvCmd_SetCurrentProcess = 1, diff --git a/stratosphere/set_mitm/source/ini.c b/stratosphere/ams_mitm/source/ini.c similarity index 100% rename from stratosphere/set_mitm/source/ini.c rename to stratosphere/ams_mitm/source/ini.c diff --git a/stratosphere/fs_mitm/source/ini.h b/stratosphere/ams_mitm/source/ini.h similarity index 100% rename from stratosphere/fs_mitm/source/ini.h rename to stratosphere/ams_mitm/source/ini.h diff --git a/stratosphere/ams_mitm/source/set_mitm/setmitm_main.cpp b/stratosphere/ams_mitm/source/set_mitm/setmitm_main.cpp new file mode 100644 index 000000000..b2ca562f9 --- /dev/null +++ b/stratosphere/ams_mitm/source/set_mitm/setmitm_main.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +#include "setmitm_main.hpp" +#include "setsys_mitm_service.hpp" +#include "setsys_settings_items.hpp" + +#include "../utils.hpp" + +struct SetSysManagerOptions { + static const size_t PointerBufferSize = 0x100; + static const size_t MaxDomains = 4; + static const size_t MaxDomainObjects = 0x100; +}; + +using SetMitmManager = WaitableManager<SetSysManagerOptions>; + +void SetMitmMain(void *arg) { + /* Wait for SD to initialize. */ + Utils::WaitSdInitialized(); + + /* Load settings */ + SettingsItemManager::LoadConfiguration(); + + /* Create server manager */ + auto server_manager = new SetMitmManager(3); + + /* Create set:sys mitm. */ + AddMitmServerToManager<SetSysMitmService>(server_manager, "set:sys", 60); + + /* Loop forever, servicing our services. */ + server_manager->Process(); + + delete server_manager; + +} + diff --git a/stratosphere/ams_mitm/source/set_mitm/setmitm_main.hpp b/stratosphere/ams_mitm/source/set_mitm/setmitm_main.hpp new file mode 100644 index 000000000..5c09004b1 --- /dev/null +++ b/stratosphere/ams_mitm/source/set_mitm/setmitm_main.hpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +constexpr u32 SetMitmPriority = 43; +constexpr u32 SetMitmStackSize = 0x8000; + +void SetMitmMain(void *arg); \ No newline at end of file diff --git a/stratosphere/set_mitm/source/setsys_firmware_version.cpp b/stratosphere/ams_mitm/source/set_mitm/setsys_firmware_version.cpp similarity index 100% rename from stratosphere/set_mitm/source/setsys_firmware_version.cpp rename to stratosphere/ams_mitm/source/set_mitm/setsys_firmware_version.cpp diff --git a/stratosphere/set_mitm/source/setsys_firmware_version.hpp b/stratosphere/ams_mitm/source/set_mitm/setsys_firmware_version.hpp similarity index 100% rename from stratosphere/set_mitm/source/setsys_firmware_version.hpp rename to stratosphere/ams_mitm/source/set_mitm/setsys_firmware_version.hpp diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.cpp b/stratosphere/ams_mitm/source/set_mitm/setsys_mitm_service.cpp similarity index 100% rename from stratosphere/set_mitm/source/setsys_mitm_service.cpp rename to stratosphere/ams_mitm/source/set_mitm/setsys_mitm_service.cpp diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.hpp b/stratosphere/ams_mitm/source/set_mitm/setsys_mitm_service.hpp similarity index 100% rename from stratosphere/set_mitm/source/setsys_mitm_service.hpp rename to stratosphere/ams_mitm/source/set_mitm/setsys_mitm_service.hpp diff --git a/stratosphere/set_mitm/source/setsys_settings_items.cpp b/stratosphere/ams_mitm/source/set_mitm/setsys_settings_items.cpp similarity index 89% rename from stratosphere/set_mitm/source/setsys_settings_items.cpp rename to stratosphere/ams_mitm/source/set_mitm/setsys_settings_items.cpp index 6fbec5f50..cd845c492 100644 --- a/stratosphere/set_mitm/source/setsys_settings_items.cpp +++ b/stratosphere/ams_mitm/source/set_mitm/setsys_settings_items.cpp @@ -24,7 +24,8 @@ #include <ctype.h> #include "setsys_settings_items.hpp" -#include "ini.h" +#include "../utils.hpp" +#include "../ini.h" struct SettingsItemValue { size_t size; @@ -241,39 +242,39 @@ static int SettingsItemIniHandler(void *user, const char *name, const char *key, return R_SUCCEEDED(rc) ? 1 : 0; } -void SettingsItemManager::RefreshConfiguration() { - /* Mount the SD Card. */ - Result rc = fsInitialize(); - if (R_SUCCEEDED(rc)) { - rc = fsdevMountSdmc(); - } +void SettingsItemManager::LoadConfiguration() { + /* Open file. */ + FsFile config_file; + Result rc = Utils::OpenSdFile("/atmosphere/system_settings.ini", FS_OPEN_READ, &config_file); if (R_FAILED(rc)) { - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); + return; } - - /* When we're done, we should stop talking to FS. */ ON_SCOPE_EXIT { - fsdevUnmountAll(); - fsExit(); + fsFileClose(&config_file); }; - /* Open, parse config file. */ - { - FILE *config = fopen("sdmc:/atmosphere/system_settings.ini", "r"); - if (config == NULL) { - return; - } - ON_SCOPE_EXIT { fclose(config); }; - - Result rc = 0; - ini_parse_file(config, SettingsItemIniHandler, &rc); - - /* Report error if we encountered one. */ - if (R_FAILED(rc) && !g_threw_fatal) { - g_threw_fatal = true; - g_fatal_thread.Initialize(&FatalThreadFunc, reinterpret_cast<void *>(rc), 0x1000, 49); - g_fatal_thread.Start(); - } + /* Allocate buffer. */ + char *config_buf = new char[0x10000]; + std::memset(config_buf, 0, 0x10000); + ON_SCOPE_EXIT { + delete config_buf; + }; + + /* Read from file. */ + if (R_SUCCEEDED(rc)) { + size_t actual_size; + rc = fsFileRead(&config_file, 0, config_buf, 0xFFFF, &actual_size); + } + + if (R_SUCCEEDED(rc)) { + ini_parse_string(config_buf, SettingsItemIniHandler, &rc); + } + + /* Report error if we encountered one. */ + if (R_FAILED(rc) && !g_threw_fatal) { + g_threw_fatal = true; + g_fatal_thread.Initialize(&FatalThreadFunc, reinterpret_cast<void *>(rc), 0x1000, 49); + g_fatal_thread.Start(); } } diff --git a/stratosphere/set_mitm/source/setsys_settings_items.hpp b/stratosphere/ams_mitm/source/set_mitm/setsys_settings_items.hpp similarity index 96% rename from stratosphere/set_mitm/source/setsys_settings_items.hpp rename to stratosphere/ams_mitm/source/set_mitm/setsys_settings_items.hpp index 47abe11b2..8e2a81c69 100644 --- a/stratosphere/set_mitm/source/setsys_settings_items.hpp +++ b/stratosphere/ams_mitm/source/set_mitm/setsys_settings_items.hpp @@ -30,7 +30,7 @@ class SettingsItemManager { static Result ValidateKey(const char *key, size_t max_size); static Result ValidateKey(const char *key); - static void RefreshConfiguration(); + static void LoadConfiguration(); static Result GetValueSize(const char *name, const char *key, u64 *out_size); static Result GetValue(const char *name, const char *key, void *out, size_t max_size, u64 *out_size); }; diff --git a/stratosphere/set_mitm/source/setsys_shim.c b/stratosphere/ams_mitm/source/set_mitm/setsys_shim.c similarity index 100% rename from stratosphere/set_mitm/source/setsys_shim.c rename to stratosphere/ams_mitm/source/set_mitm/setsys_shim.c diff --git a/stratosphere/set_mitm/source/setsys_shim.h b/stratosphere/ams_mitm/source/set_mitm/setsys_shim.h similarity index 100% rename from stratosphere/set_mitm/source/setsys_shim.h rename to stratosphere/ams_mitm/source/set_mitm/setsys_shim.h diff --git a/stratosphere/fs_mitm/source/sha256.c b/stratosphere/ams_mitm/source/sha256.c similarity index 100% rename from stratosphere/fs_mitm/source/sha256.c rename to stratosphere/ams_mitm/source/sha256.c diff --git a/stratosphere/fs_mitm/source/sha256.h b/stratosphere/ams_mitm/source/sha256.h similarity index 100% rename from stratosphere/fs_mitm/source/sha256.h rename to stratosphere/ams_mitm/source/sha256.h diff --git a/stratosphere/fs_mitm/source/sha256_armv8.s b/stratosphere/ams_mitm/source/sha256_armv8.s similarity index 100% rename from stratosphere/fs_mitm/source/sha256_armv8.s rename to stratosphere/ams_mitm/source/sha256_armv8.s diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.cpp b/stratosphere/ams_mitm/source/utils.cpp similarity index 97% rename from stratosphere/fs_mitm/source/fsmitm_utils.cpp rename to stratosphere/ams_mitm/source/utils.cpp index a16d9aa2b..8f3947d9e 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.cpp +++ b/stratosphere/ams_mitm/source/utils.cpp @@ -21,11 +21,13 @@ #include <strings.h> #include "debug.hpp" -#include "fsmitm_utils.hpp" +#include "utils.hpp" #include "ini.h" #include "sha256.h" static FsFileSystem g_sd_filesystem = {0}; +static HosSignal g_sd_signal; + static std::vector<u64> g_mitm_flagged_tids; static std::vector<u64> g_disable_mitm_flagged_tids; static std::atomic_bool g_has_initialized = false; @@ -56,7 +58,7 @@ static bool IsHexadecimal(const char *str) { return true; } -void Utils::InitializeSdThreadFunc(void *args) { +void Utils::InitializeThreadFunc(void *args) { /* Get required services. */ Handle tmp_hnd = 0; static const char * const required_active_services[] = {"pcv", "gpio", "pinmux", "psc:c"}; @@ -180,20 +182,25 @@ void Utils::InitializeSdThreadFunc(void *args) { Utils::RefreshConfiguration(); + /* Initialize set:sys. */ + setsysInitialize(); + + /* Signal SD is initialized. */ g_has_initialized = true; + g_sd_signal.Signal(); - svcExitThread(); -} - -void Utils::InitializeHidThreadFunc(void *args) { - while (R_FAILED(hidInitialize())) { - svcSleepThread(1000ULL); + /* Initialize HID. */ + { + + while (R_FAILED(hidInitialize())) { + svcSleepThread(1000000ULL); + } + + g_has_hid_session = true; + + hidExit(); } - g_has_hid_session = true; - - hidExit(); - svcExitThread(); } @@ -201,6 +208,10 @@ bool Utils::IsSdInitialized() { return g_has_initialized; } +void Utils::WaitSdInitialized() { + g_sd_signal.Wait(); +} + bool Utils::IsHidAvailable() { return g_has_hid_session; } diff --git a/stratosphere/fs_mitm/source/fsmitm_utils.hpp b/stratosphere/ams_mitm/source/utils.hpp similarity index 94% rename from stratosphere/fs_mitm/source/fsmitm_utils.hpp rename to stratosphere/ams_mitm/source/utils.hpp index 6aa8535b7..e929bb10a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_utils.hpp +++ b/stratosphere/ams_mitm/source/utils.hpp @@ -40,6 +40,7 @@ enum BisStorageId : u32 { class Utils { public: static bool IsSdInitialized(); + static void WaitSdInitialized(); static Result OpenSdFile(const char *fn, int flags, FsFile *out); static Result OpenSdFileForAtmosphere(u64 title_id, const char *fn, int flags, FsFile *out); @@ -55,8 +56,8 @@ class Utils { static bool HasSdRomfsContent(u64 title_id); - /* SD card Initialization + MitM detection. */ - static void InitializeSdThreadFunc(void *args); + /* Delayed Initialization + MitM detection. */ + static void InitializeThreadFunc(void *args); static bool IsHblTid(u64 tid); @@ -70,7 +71,6 @@ class Utils { static bool IsHidAvailable(); - static void InitializeHidThreadFunc(void *args); static Result GetKeysDown(u64 *keys); static bool HasOverrideButton(u64 tid); private: diff --git a/stratosphere/set_mitm/Makefile b/stratosphere/eclct.stub/Makefile similarity index 100% rename from stratosphere/set_mitm/Makefile rename to stratosphere/eclct.stub/Makefile diff --git a/stratosphere/set_mitm/set_mitm.json b/stratosphere/eclct.stub/eclct.stub.json similarity index 92% rename from stratosphere/set_mitm/set_mitm.json rename to stratosphere/eclct.stub/eclct.stub.json index 634ac777c..120ab2e22 100644 --- a/stratosphere/set_mitm/set_mitm.json +++ b/stratosphere/eclct.stub/eclct.stub.json @@ -1,5 +1,5 @@ { - "name": "set.mitm", + "name": "eclct.stun", "title_id": "0x0100000000000032", "title_id_range_min": "0x0100000000000032", "title_id_range_max": "0x0100000000000032", @@ -14,16 +14,8 @@ "filesystem_access": { "permissions": "0xFFFFFFFFFFFFFFFF" }, - "service_host": [ - "set:sys" - ], - "service_access": [ - "fatal:u", - "fsp-srv", - "spl:", - "set:sys", - "fsp-srv" - ], + "service_host": [], + "service_access": [], "kernel_capabilities": [ { "type": "kernel_flags", @@ -95,7 +87,7 @@ "svcMapDeviceAddressSpaceAligned": "0x5a", "svcUnmapDeviceAddressSpace": "0x5c", "svcGetSystemInfo": "0x6f", - "svcCallSecureMonitor": "0x7F" + "svcCallSecureMonitor": "0x7F" } }, { diff --git a/stratosphere/eclct.stub/source/eclct_stub.cpp b/stratosphere/eclct.stub/source/eclct_stub.cpp new file mode 100644 index 000000000..1324557cc --- /dev/null +++ b/stratosphere/eclct.stub/source/eclct_stub.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +extern "C" { + extern u32 __start__; + + u32 __nx_applet_type = AppletType_None; + + #define INNER_HEAP_SIZE 0x8000 + size_t nx_inner_heap_size = INNER_HEAP_SIZE; + char nx_inner_heap[INNER_HEAP_SIZE]; + + void __libnx_initheap(void); + void __appInit(void); + void __appExit(void); +} + + +void __libnx_initheap(void) { + void* addr = nx_inner_heap; + size_t size = nx_inner_heap_size; + + /* Newlib */ + extern char* fake_heap_start; + extern char* fake_heap_end; + + fake_heap_start = (char*)addr; + fake_heap_end = (char*)addr + size; +} + +void __appInit(void) { + /* nothing to do */ +} + +void __appExit(void) { + /* nothing to do */ +} + +int main(int argc, char **argv) +{ + return 0; +} + diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp deleted file mode 100644 index 24fa8b647..000000000 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2018 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <cstdlib> -#include <cstdint> -#include <cstring> -#include <malloc.h> - -#include <switch.h> -#include <atmosphere.h> -#include <stratosphere.hpp> - -#include "fsmitm_service.hpp" - -#include "fsmitm_utils.hpp" - -extern "C" { - extern u32 __start__; - - u32 __nx_applet_type = AppletType_None; - - #define INNER_HEAP_SIZE 0x1000000 - size_t nx_inner_heap_size = INNER_HEAP_SIZE; - char nx_inner_heap[INNER_HEAP_SIZE]; - - void __libnx_initheap(void); - void __appInit(void); - void __appExit(void); -} - - -void __libnx_initheap(void) { - void* addr = nx_inner_heap; - size_t size = nx_inner_heap_size; - - /* Newlib */ - extern char* fake_heap_start; - extern char* fake_heap_end; - - fake_heap_start = (char*)addr; - fake_heap_end = (char*)addr + size; -} - -void __appInit(void) { - Result rc; - - rc = smInitialize(); - if (R_FAILED(rc)) { - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); - } - - rc = fsInitialize(); - if (R_FAILED(rc)) { - fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS)); - } - - CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); -} - -void __appExit(void) { - /* Cleanup services. */ - fsExit(); - smExit(); -} - -struct FsMitmManagerOptions { - static const size_t PointerBufferSize = 0x800; - static const size_t MaxDomains = 0x40; - static const size_t MaxDomainObjects = 0x4000; -}; -using FsMitmManager = WaitableManager<FsMitmManagerOptions>; - -int main(int argc, char **argv) -{ - Thread sd_initializer_thread = {0}; - Thread hid_initializer_thread = {0}; - consoleDebugInit(debugDevice_SVC); - - /* TODO: What's a good timeout value to use here? */ - auto server_manager = new FsMitmManager(5); - - /* Create fsp-srv mitm. */ - AddMitmServerToManager<FsMitmService>(server_manager, "fsp-srv", 61); - - if (R_FAILED(threadCreate(&sd_initializer_thread, &Utils::InitializeSdThreadFunc, NULL, 0x4000, 0x15, 0))) { - /* TODO: Panic. */ - } - if (R_FAILED(threadStart(&sd_initializer_thread))) { - /* TODO: Panic. */ - } - - if (R_FAILED(threadCreate(&hid_initializer_thread, &Utils::InitializeHidThreadFunc, NULL, 0x4000, 0x15, 0))) { - /* TODO: Panic. */ - } - if (R_FAILED(threadStart(&hid_initializer_thread))) { - /* TODO: Panic. */ - } - - /* Loop forever, servicing our services. */ - server_manager->Process(); - - delete server_manager; - - return 0; -} - diff --git a/stratosphere/fs_mitm/source/ini.c b/stratosphere/fs_mitm/source/ini.c deleted file mode 100644 index 63626c72d..000000000 --- a/stratosphere/fs_mitm/source/ini.c +++ /dev/null @@ -1,269 +0,0 @@ -/* inih -- simple .INI file parser - -inih is released under the New BSD license (see LICENSE.txt). Go to the project -home page for more info: - -https://github.com/benhoyt/inih - -*/ - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include <stdio.h> -#include <ctype.h> -#include <string.h> - -#include "ini.h" - -#if !INI_USE_STACK -#include <stdlib.h> -#endif - -#define MAX_SECTION 50 -#define MAX_NAME 50 - -/* Used by ini_parse_string() to keep track of string parsing state. */ -typedef struct { - const char* ptr; - size_t num_left; -} ini_parse_string_ctx; - -/* Strip whitespace chars off end of given string, in place. Return s. */ -static char* rstrip(char* s) -{ - char* p = s + strlen(s); - while (p > s && isspace((unsigned char)(*--p))) - *p = '\0'; - return s; -} - -/* Return pointer to first non-whitespace char in given string. */ -static char* lskip(const char* s) -{ - while (*s && isspace((unsigned char)(*s))) - s++; - return (char*)s; -} - -/* Return pointer to first char (of chars) or inline comment in given string, - or pointer to null at end of string if neither found. Inline comment must - be prefixed by a whitespace character to register as a comment. */ -static char* find_chars_or_comment(const char* s, const char* chars) -{ -#if INI_ALLOW_INLINE_COMMENTS - int was_space = 0; - while (*s && (!chars || !strchr(chars, *s)) && - !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { - was_space = isspace((unsigned char)(*s)); - s++; - } -#else - while (*s && (!chars || !strchr(chars, *s))) { - s++; - } -#endif - return (char*)s; -} - -/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ -static char* strncpy0(char* dest, const char* src, size_t size) -{ - strncpy(dest, src, size - 1); - dest[size - 1] = '\0'; - return dest; -} - -/* See documentation in header file. */ -int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, - void* user) -{ - /* Uses a fair bit of stack (use heap instead if you need to) */ -#if INI_USE_STACK - char line[INI_MAX_LINE]; - int max_line = INI_MAX_LINE; -#else - char* line; - int max_line = INI_INITIAL_ALLOC; -#endif -#if INI_ALLOW_REALLOC - char* new_line; - int offset; -#endif - char section[MAX_SECTION] = ""; - char prev_name[MAX_NAME] = ""; - - char* start; - char* end; - char* name; - char* value; - int lineno = 0; - int error = 0; - -#if !INI_USE_STACK - line = (char*)malloc(INI_INITIAL_ALLOC); - if (!line) { - return -2; - } -#endif - -#if INI_HANDLER_LINENO -#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) -#else -#define HANDLER(u, s, n, v) handler(u, s, n, v) -#endif - - /* Scan through stream line by line */ - while (reader(line, max_line, stream) != NULL) { -#if INI_ALLOW_REALLOC - offset = strlen(line); - while (offset == max_line - 1 && line[offset - 1] != '\n') { - max_line *= 2; - if (max_line > INI_MAX_LINE) - max_line = INI_MAX_LINE; - new_line = realloc(line, max_line); - if (!new_line) { - free(line); - return -2; - } - line = new_line; - if (reader(line + offset, max_line - offset, stream) == NULL) - break; - if (max_line >= INI_MAX_LINE) - break; - offset += strlen(line + offset); - } -#endif - - lineno++; - - start = line; -#if INI_ALLOW_BOM - if (lineno == 1 && (unsigned char)start[0] == 0xEF && - (unsigned char)start[1] == 0xBB && - (unsigned char)start[2] == 0xBF) { - start += 3; - } -#endif - start = lskip(rstrip(start)); - - if (strchr(INI_START_COMMENT_PREFIXES, *start)) { - /* Start-of-line comment */ - } -#if INI_ALLOW_MULTILINE - else if (*prev_name && *start && start > line) { - /* Non-blank line with leading whitespace, treat as continuation - of previous name's value (as per Python configparser). */ - if (!HANDLER(user, section, prev_name, start) && !error) - error = lineno; - } -#endif - else if (*start == '[') { - /* A "[section]" line */ - end = find_chars_or_comment(start + 1, "]"); - if (*end == ']') { - *end = '\0'; - strncpy0(section, start + 1, sizeof(section)); - *prev_name = '\0'; - } - else if (!error) { - /* No ']' found on section line */ - error = lineno; - } - } - else if (*start) { - /* Not a comment, must be a name[=:]value pair */ - end = find_chars_or_comment(start, "=:"); - if (*end == '=' || *end == ':') { - *end = '\0'; - name = rstrip(start); - value = end + 1; -#if INI_ALLOW_INLINE_COMMENTS - end = find_chars_or_comment(value, NULL); - if (*end) - *end = '\0'; -#endif - value = lskip(value); - rstrip(value); - - /* Valid name[=:]value pair found, call handler */ - strncpy0(prev_name, name, sizeof(prev_name)); - if (!HANDLER(user, section, name, value) && !error) - error = lineno; - } - else if (!error) { - /* No '=' or ':' found on name[=:]value line */ - error = lineno; - } - } - -#if INI_STOP_ON_FIRST_ERROR - if (error) - break; -#endif - } - -#if !INI_USE_STACK - free(line); -#endif - - return error; -} - -/* See documentation in header file. */ -int ini_parse_file(FILE* file, ini_handler handler, void* user) -{ - return ini_parse_stream((ini_reader)fgets, file, handler, user); -} - -/* See documentation in header file. */ -int ini_parse(const char* filename, ini_handler handler, void* user) -{ - FILE* file; - int error; - - file = fopen(filename, "r"); - if (!file) - return -1; - error = ini_parse_file(file, handler, user); - fclose(file); - return error; -} - -/* An ini_reader function to read the next line from a string buffer. This - is the fgets() equivalent used by ini_parse_string(). */ -static char* ini_reader_string(char* str, int num, void* stream) { - ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; - const char* ctx_ptr = ctx->ptr; - size_t ctx_num_left = ctx->num_left; - char* strp = str; - char c; - - if (ctx_num_left == 0 || num < 2) - return NULL; - - while (num > 1 && ctx_num_left != 0) { - c = *ctx_ptr++; - ctx_num_left--; - *strp++ = c; - if (c == '\n') - break; - num--; - } - - *strp = '\0'; - ctx->ptr = ctx_ptr; - ctx->num_left = ctx_num_left; - return str; -} - -/* See documentation in header file. */ -int ini_parse_string(const char* string, ini_handler handler, void* user) { - ini_parse_string_ctx ctx; - - ctx.ptr = string; - ctx.num_left = strlen(string); - return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, - user); -} diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index b3059f0c9..6321a42f7 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -224,9 +224,8 @@ void EmbeddedBoot2::Main() { if (maintenance) { BootModeService::SetMaintenanceBootForEmbeddedBoot2(); } - + /* Launch set:mitm, wait for it. */ - LaunchTitle(Boot2KnownTitleId::ams_set_mitm, FsStorageId_None, 0, NULL); WaitForMitm("set:sys"); /* Launch usb. */ diff --git a/stratosphere/set_mitm/source/ini.h b/stratosphere/set_mitm/source/ini.h deleted file mode 100644 index f45ba40ba..000000000 --- a/stratosphere/set_mitm/source/ini.h +++ /dev/null @@ -1,130 +0,0 @@ -/* inih -- simple .INI file parser - -inih is released under the New BSD license (see LICENSE.txt). Go to the project -home page for more info: - -https://github.com/benhoyt/inih - -*/ - -#ifndef __INI_H__ -#define __INI_H__ - -/* Make this header file easier to include in C++ code */ -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdio.h> - -/* Nonzero if ini_handler callback should accept lineno parameter. */ -#ifndef INI_HANDLER_LINENO -#define INI_HANDLER_LINENO 0 -#endif - -/* Typedef for prototype of handler function. */ -#if INI_HANDLER_LINENO -typedef int (*ini_handler)(void* user, const char* section, - const char* name, const char* value, - int lineno); -#else -typedef int (*ini_handler)(void* user, const char* section, - const char* name, const char* value); -#endif - -/* Typedef for prototype of fgets-style reader function. */ -typedef char* (*ini_reader)(char* str, int num, void* stream); - -/* Parse given INI-style file. May have [section]s, name=value pairs - (whitespace stripped), and comments starting with ';' (semicolon). Section - is "" if name=value pair parsed before any section heading. name:value - pairs are also supported as a concession to Python's configparser. - - For each name=value pair parsed, call handler function with given user - pointer as well as section, name, and value (data only valid for duration - of handler call). Handler should return nonzero on success, zero on error. - - Returns 0 on success, line number of first error on parse error (doesn't - stop on first error), -1 on file open error, or -2 on memory allocation - error (only when INI_USE_STACK is zero). -*/ -int ini_parse(const char* filename, ini_handler handler, void* user); - -/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't - close the file when it's finished -- the caller must do that. */ -int ini_parse_file(FILE* file, ini_handler handler, void* user); - -/* Same as ini_parse(), but takes an ini_reader function pointer instead of - filename. Used for implementing custom or string-based I/O (see also - ini_parse_string). */ -int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, - void* user); - -/* Same as ini_parse(), but takes a zero-terminated string with the INI data -instead of a file. Useful for parsing INI data from a network socket or -already in memory. */ -int ini_parse_string(const char* string, ini_handler handler, void* user); - -/* Nonzero to allow multi-line value parsing, in the style of Python's - configparser. If allowed, ini_parse() will call the handler with the same - name for each subsequent line parsed. */ -#ifndef INI_ALLOW_MULTILINE -#define INI_ALLOW_MULTILINE 1 -#endif - -/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of - the file. See http://code.google.com/p/inih/issues/detail?id=21 */ -#ifndef INI_ALLOW_BOM -#define INI_ALLOW_BOM 1 -#endif - -/* Chars that begin a start-of-line comment. Per Python configparser, allow - both ; and # comments at the start of a line by default. */ -#ifndef INI_START_COMMENT_PREFIXES -#define INI_START_COMMENT_PREFIXES ";#" -#endif - -/* Nonzero to allow inline comments (with valid inline comment characters - specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match - Python 3.2+ configparser behaviour. */ -#ifndef INI_ALLOW_INLINE_COMMENTS -#define INI_ALLOW_INLINE_COMMENTS 1 -#endif -#ifndef INI_INLINE_COMMENT_PREFIXES -#define INI_INLINE_COMMENT_PREFIXES ";" -#endif - -/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ -#ifndef INI_USE_STACK -#define INI_USE_STACK 1 -#endif - -/* Maximum line length for any line in INI file (stack or heap). Note that - this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ -#ifndef INI_MAX_LINE -#define INI_MAX_LINE 200 -#endif - -/* Nonzero to allow heap line buffer to grow via realloc(), zero for a - fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is - zero. */ -#ifndef INI_ALLOW_REALLOC -#define INI_ALLOW_REALLOC 0 -#endif - -/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK - is zero. */ -#ifndef INI_INITIAL_ALLOC -#define INI_INITIAL_ALLOC 200 -#endif - -/* Stop parsing on first error (default is to keep parsing). */ -#ifndef INI_STOP_ON_FIRST_ERROR -#define INI_STOP_ON_FIRST_ERROR 0 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __INI_H__ */ From 784964d49dc0990128562416d4d5b7f64b916b64 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Feb 2019 21:17:05 -0800 Subject: [PATCH 406/489] ams.mitm: add bpc handler, for reboot power button stuff --- stratosphere/ams_mitm/Makefile | 2 +- .../ams_mitm/source/amsmitm_modules.cpp | 2 + .../ams_mitm/source/amsmitm_modules.hpp | 3 +- .../source/bpc_mitm/bpc_mitm_service.cpp | 34 ++++++++++++ .../source/bpc_mitm/bpc_mitm_service.hpp | 52 ++++++++++++++++++ .../ams_mitm/source/bpc_mitm/bpcmitm_main.cpp | 55 +++++++++++++++++++ .../ams_mitm/source/bpc_mitm/bpcmitm_main.hpp | 29 ++++++++++ .../bpc_mitm/bpcmitm_reboot_manager.cpp} | 43 +++++++++++---- .../bpc_mitm/bpcmitm_reboot_manager.hpp} | 12 +++- stratosphere/fatal/source/fatal_main.cpp | 6 +- .../fatal/source/fatal_task_power.cpp | 7 +-- stratosphere/pm/source/pm_boot2.cpp | 7 ++- 12 files changed, 226 insertions(+), 26 deletions(-) create mode 100644 stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp create mode 100644 stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp create mode 100644 stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp create mode 100644 stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.hpp rename stratosphere/{fatal/source/fatal_payload_manager.cpp => ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp} (61%) rename stratosphere/{fatal/source/fatal_payload_manager.hpp => ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp} (81%) diff --git a/stratosphere/ams_mitm/Makefile b/stratosphere/ams_mitm/Makefile index 404225ba3..6aa64f2af 100644 --- a/stratosphere/ams_mitm/Makefile +++ b/stratosphere/ams_mitm/Makefile @@ -26,7 +26,7 @@ endif #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) BUILD := build -SOURCES := source source/fs_mitm source/set_mitm +SOURCES := source source/fs_mitm source/set_mitm source/bpc_mitm DATA := data INCLUDES := include ../../common/include EXEFS_SRC := exefs_src diff --git a/stratosphere/ams_mitm/source/amsmitm_modules.cpp b/stratosphere/ams_mitm/source/amsmitm_modules.cpp index d2446b77a..9d90f02b7 100644 --- a/stratosphere/ams_mitm/source/amsmitm_modules.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_modules.cpp @@ -23,6 +23,7 @@ #include "fs_mitm/fsmitm_main.hpp" #include "set_mitm/setmitm_main.hpp" +#include "bpc_mitm/bpcmitm_main.hpp" static HosThread g_module_threads[MitmModuleId_Count]; @@ -33,6 +34,7 @@ static const struct { } g_module_definitions[MitmModuleId_Count] = { { &FsMitmMain, FsMitmPriority, FsMitmStackSize }, /* FsMitm */ { &SetMitmMain, SetMitmPriority, SetMitmStackSize }, /* SetMitm */ + { &BpcMitmMain, BpcMitmPriority, BpcMitmStackSize }, /* BpcMitm */ }; void LaunchAllMitmModules() { diff --git a/stratosphere/ams_mitm/source/amsmitm_modules.hpp b/stratosphere/ams_mitm/source/amsmitm_modules.hpp index eac0cb6fe..3f9d6b830 100644 --- a/stratosphere/ams_mitm/source/amsmitm_modules.hpp +++ b/stratosphere/ams_mitm/source/amsmitm_modules.hpp @@ -19,8 +19,9 @@ enum MitmModuleId : u32 { MitmModuleId_FsMitm = 0, MitmModuleId_SetMitm = 1, + MitmModuleId_BpcMitm = 2, - MitmModuleId_Count = 2, + MitmModuleId_Count = 3, }; void LaunchAllMitmModules(); diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp new file mode 100644 index 000000000..4860301e4 --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <mutex> +#include <switch.h> +#include <stratosphere.hpp> +#include "bpc_mitm_service.hpp" +#include "bpcmitm_reboot_manager.hpp" + +void BpcMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { + /* Nothing to do here */ +} + +Result BpcMitmService::ShutdownSystem() { + /* TODO: Use exosphere + reboot to perform real shutdown, instead of fake shutdown. */ + return RESULT_FORWARD_TO_SESSION; +} + +Result BpcMitmService::RebootSystem() { + return BpcRebootManager::PerformReboot(); +} diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp new file mode 100644 index 000000000..ac51abe8f --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +enum BpcCmd : u32 { + BpcCmd_ShutdownSystem = 0, + BpcCmd_RebootSystem = 1, +}; + +class BpcMitmService : public IMitmServiceObject { + public: + BpcMitmService(std::shared_ptr<Service> s, u64 pid) : IMitmServiceObject(s, pid) { + /* ... */ + } + + static bool ShouldMitm(u64 pid, u64 tid) { + /* We will mitm: + * - am, to intercept the Reboot/Power buttons in the overlay menu. + * - fatal, to simplify payload reboot logic significantly + * - applications, to allow homebrew to take advantage of the feature. + */ + return tid == 0x0100000000000023ull || tid == 0x0100000000000034ull || tid >= 0x0100000000010000ull; + } + + static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); + + protected: + /* Overridden commands. */ + Result ShutdownSystem(); + Result RebootSystem(); + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<BpcCmd_ShutdownSystem, &BpcMitmService::ShutdownSystem>(), + MakeServiceCommandMeta<BpcCmd_RebootSystem, &BpcMitmService::RebootSystem>(), + }; +}; diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp new file mode 100644 index 000000000..8d9c63530 --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +#include "bpcmitm_main.hpp" +#include "bpc_mitm_service.hpp" +#include "bpcmitm_reboot_manager.hpp" + +#include "../utils.hpp" + +void BpcMitmMain(void *arg) { + /* Wait for initialization to occur */ + Utils::WaitSdInitialized(); + + /* Load a payload off of the SD */ + BpcRebootManager::Initialize(); + + /* Create server manager */ + auto server_manager = new WaitableManager(2); + + /* Create bpc mitm. */ + const char *service_name = "bpc"; + if (GetRuntimeFirmwareVersion() < FirmwareVersion_200) { + service_name = "bpc:c"; + } + AddMitmServerToManager<BpcMitmService>(server_manager, service_name, 13); + + /* Loop forever, servicing our services. */ + server_manager->Process(); + + delete server_manager; + +} + diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.hpp new file mode 100644 index 000000000..7fd1061a0 --- /dev/null +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_main.hpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <cstdlib> +#include <cstdint> +#include <cstring> +#include <malloc.h> + +#include <switch.h> +#include <atmosphere.h> +#include <stratosphere.hpp> + +constexpr u32 BpcMitmPriority = 32; +constexpr u32 BpcMitmStackSize = 0x8000; + +void BpcMitmMain(void *arg); \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_payload_manager.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp similarity index 61% rename from stratosphere/fatal/source/fatal_payload_manager.cpp rename to stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp index 52a72d7d6..12c52def9 100644 --- a/stratosphere/fatal/source/fatal_payload_manager.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp @@ -17,24 +17,33 @@ #include <switch.h> #include <stratosphere.hpp> #include <string.h> -#include "fatal_types.hpp" -#include "fatal_payload_manager.hpp" +#include "bpcmitm_reboot_manager.hpp" +#include "../utils.hpp" /* TODO: Find a way to pre-populate this with the contents of fusee-primary. */ static u8 g_reboot_payload[IRAM_PAYLOAD_MAX_SIZE] __attribute__ ((aligned (0x1000))); static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000))); static bool g_payload_loaded = false; +static BpcRebootType g_reboot_type = BpcRebootType::ToPayload; -void FatalPayloadManager::LoadPayloadFromSdCard() { - FILE *f = fopen("sdmc:/atmosphere/reboot_payload.bin", "rb"); - if (f == NULL) { +void BpcRebootManager::Initialize() { + /* Open payload file. */ + FsFile payload_file; + if (R_FAILED(Utils::OpenSdFile("/atmosphere/reboot_payload.bin", FS_OPEN_READ, &payload_file))) { return; } - ON_SCOPE_EXIT { fclose(f); }; + ON_SCOPE_EXIT { fsFileClose(&payload_file); }; + + /* Clear payload buffer */ + std::memset(g_reboot_payload, 0xFF, sizeof(g_reboot_payload)); + + /* Read payload file. */ + size_t actual_size; + fsFileRead(&payload_file, 0, g_reboot_payload, IRAM_PAYLOAD_MAX_SIZE, &actual_size); - memset(g_reboot_payload, 0xFF, sizeof(g_reboot_payload)); - fread(g_reboot_payload, 1, IRAM_PAYLOAD_MAX_SIZE, f); g_payload_loaded = true; + + /* TODO: Figure out what kind of reboot we're gonna be doing. */ } static void ClearIram() { @@ -47,7 +56,7 @@ static void ClearIram() { } } -void FatalPayloadManager::RebootToPayload() { +static void DoRebootToPayload() { /* If we don't actually have a payload loaded, just go to RCM. */ if (!g_payload_loaded) { RebootToRcm(); @@ -62,4 +71,18 @@ void FatalPayloadManager::RebootToPayload() { } RebootToIramPayload(); -} \ No newline at end of file +} + +Result BpcRebootManager::PerformReboot() { + switch (g_reboot_type) { + case BpcRebootType::Standard: + return RESULT_FORWARD_TO_SESSION; + case BpcRebootType::ToRcm: + RebootToRcm(); + return 0; + case BpcRebootType::ToPayload: + default: + DoRebootToPayload(); + return 0; + } +} diff --git a/stratosphere/fatal/source/fatal_payload_manager.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp similarity index 81% rename from stratosphere/fatal/source/fatal_payload_manager.hpp rename to stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp index 7aed9cdce..d7b6c575c 100644 --- a/stratosphere/fatal/source/fatal_payload_manager.hpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.hpp @@ -21,8 +21,14 @@ #define IRAM_PAYLOAD_MAX_SIZE 0x2F000 #define IRAM_PAYLOAD_BASE 0x40010000ull -class FatalPayloadManager { +enum class BpcRebootType : u32 { + Standard, + ToRcm, + ToPayload, +}; + +class BpcRebootManager { public: - static void LoadPayloadFromSdCard(); - static void RebootToPayload(); + static void Initialize(); + static Result PerformReboot(); }; \ No newline at end of file diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 39e5ae088..3c26538c2 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -29,7 +29,6 @@ #include "fatal_config.hpp" #include "fatal_repair.hpp" #include "fatal_font.hpp" -#include "fatal_payload_manager.hpp" extern "C" { extern u32 __start__; @@ -159,10 +158,7 @@ int main(int argc, char **argv) { /* Load settings from set:sys. */ InitializeFatalConfig(); - - /* Load a payload from the SD card. */ - FatalPayloadManager::LoadPayloadFromSdCard(); - + /* Load shared font. */ if (R_FAILED(FontManager::InitializeSharedFont())) { std::abort(); diff --git a/stratosphere/fatal/source/fatal_task_power.cpp b/stratosphere/fatal/source/fatal_task_power.cpp index 4883b78f7..44e5b9f2e 100644 --- a/stratosphere/fatal/source/fatal_task_power.cpp +++ b/stratosphere/fatal/source/fatal_task_power.cpp @@ -16,7 +16,6 @@ #include <switch.h> #include "fatal_task_power.hpp" -#include "fatal_payload_manager.hpp" #include "fatal_config.hpp" bool PowerControlTask::TryShutdown() { @@ -124,13 +123,11 @@ void PowerButtonObserveTask::WaitForPowerButton() { Result rc = 0; if (check_vol_up && R_SUCCEEDED((rc = gpioPadGetValue(&vol_up_btn, &val))) && val == GpioValue_Low) { - /* Tell exosphere to reboot to payload. */ - FatalPayloadManager::RebootToPayload(); + bpcRebootSystem(); } if (check_vol_down && R_SUCCEEDED((rc = gpioPadGetValue(&vol_down_btn, &val))) && val == GpioValue_Low) { - /* Tell exosphere to reboot to payload. */ - FatalPayloadManager::RebootToPayload(); + bpcRebootSystem(); } if ((R_SUCCEEDED(rc = bpcGetSleepButtonState(&state)) && state == BpcSleepButtonState_Held) || (config->quest_flag && reboot_helper.TimedOut())) { diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 6321a42f7..cb13a42ac 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -225,8 +225,13 @@ void EmbeddedBoot2::Main() { BootModeService::SetMaintenanceBootForEmbeddedBoot2(); } - /* Launch set:mitm, wait for it. */ + /* Wait for other atmosphere mitm modules to initialize. */ WaitForMitm("set:sys"); + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) { + WaitForMitm("bpc"); + } else { + WaitForMitm("bpc:c"); + } /* Launch usb. */ LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); From e2a7f23214d97eeddec1fc74f3a82f606fdc457d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Feb 2019 21:47:55 -0800 Subject: [PATCH 407/489] ams.mitm: simplify bpc ShouldMitm logic, fix enum problem --- stratosphere/ams_mitm/source/amsmitm_modules.hpp | 3 ++- stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/stratosphere/ams_mitm/source/amsmitm_modules.hpp b/stratosphere/ams_mitm/source/amsmitm_modules.hpp index 3f9d6b830..fb03657cd 100644 --- a/stratosphere/ams_mitm/source/amsmitm_modules.hpp +++ b/stratosphere/ams_mitm/source/amsmitm_modules.hpp @@ -21,7 +21,8 @@ enum MitmModuleId : u32 { MitmModuleId_SetMitm = 1, MitmModuleId_BpcMitm = 2, - MitmModuleId_Count = 3, + /* Always keep this at the end. */ + MitmModuleId_Count, }; void LaunchAllMitmModules(); diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp index ac51abe8f..03e933c06 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.hpp @@ -18,6 +18,8 @@ #include <switch.h> #include <stratosphere.hpp> +#include "../utils.hpp" + enum BpcCmd : u32 { BpcCmd_ShutdownSystem = 0, BpcCmd_RebootSystem = 1, @@ -35,7 +37,7 @@ class BpcMitmService : public IMitmServiceObject { * - fatal, to simplify payload reboot logic significantly * - applications, to allow homebrew to take advantage of the feature. */ - return tid == 0x0100000000000023ull || tid == 0x0100000000000034ull || tid >= 0x0100000000010000ull; + return tid == 0x0100000000000023ull || tid == 0x0100000000000034ull || Utils::IsHblTid(tid); } static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); From 67c7ef69f4d986ea132e4a7434cd95bc3e5e3a8e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 5 Feb 2019 01:51:05 -0800 Subject: [PATCH 408/489] bpc.mitm: Make reboot type configurable --- common/defaults/system_settings.ini | 7 ++++++- .../source/bpc_mitm/bpcmitm_reboot_manager.cpp | 17 +++++++++++++++-- .../ams_mitm/source/set_mitm/setmitm_main.cpp | 5 +---- stratosphere/ams_mitm/source/utils.cpp | 17 ++++++++++++++++- stratosphere/ams_mitm/source/utils.hpp | 4 ++++ 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/common/defaults/system_settings.ini b/common/defaults/system_settings.ini index 9a10dcd7c..91c7f7cfb 100644 --- a/common/defaults/system_settings.ini +++ b/common/defaults/system_settings.ini @@ -3,4 +3,9 @@ upload_enabled = u8!0x0 ; Enable USB 3.0 superspeed for homebrew [usb] -usb30_force_enabled = u8!0x1 \ No newline at end of file +usb30_force_enabled = u8!0x1 +; Atmosphere custom settings +[atmosphere] +; Make the power menu's "reboot" button reboot to payload. +; Set to "normal" for normal reboot, "rcm" for rcm reboot. +power_menu_reboot_function = str!payload \ No newline at end of file diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp index 12c52def9..248f2964e 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpcmitm_reboot_manager.cpp @@ -16,7 +16,7 @@ #include <switch.h> #include <stratosphere.hpp> -#include <string.h> +#include <strings.h> #include "bpcmitm_reboot_manager.hpp" #include "../utils.hpp" @@ -43,7 +43,20 @@ void BpcRebootManager::Initialize() { g_payload_loaded = true; - /* TODO: Figure out what kind of reboot we're gonna be doing. */ + /* Figure out what kind of reboot we're gonna be doing. */ + { + char reboot_type[0x40] = {0}; + u64 reboot_type_size = 0; + if (R_SUCCEEDED(Utils::GetSettingsItemValue("atmosphere", "power_menu_reboot_function", reboot_type, sizeof(reboot_type)-1, &reboot_type_size))) { + if (strcasecmp(reboot_type, "stock") == 0 || strcasecmp(reboot_type, "normal") == 0 || strcasecmp(reboot_type, "standard") == 0) { + g_reboot_type = BpcRebootType::Standard; + } else if (strcasecmp(reboot_type, "rcm") == 0) { + g_reboot_type = BpcRebootType::ToRcm; + } else if (strcasecmp(reboot_type, "payload") == 0) { + g_reboot_type = BpcRebootType::ToPayload; + } + } + } } static void ClearIram() { diff --git a/stratosphere/ams_mitm/source/set_mitm/setmitm_main.cpp b/stratosphere/ams_mitm/source/set_mitm/setmitm_main.cpp index b2ca562f9..f694588ae 100644 --- a/stratosphere/ams_mitm/source/set_mitm/setmitm_main.cpp +++ b/stratosphere/ams_mitm/source/set_mitm/setmitm_main.cpp @@ -40,10 +40,7 @@ using SetMitmManager = WaitableManager<SetSysManagerOptions>; void SetMitmMain(void *arg) { /* Wait for SD to initialize. */ Utils::WaitSdInitialized(); - - /* Load settings */ - SettingsItemManager::LoadConfiguration(); - + /* Create server manager */ auto server_manager = new SetMitmManager(3); diff --git a/stratosphere/ams_mitm/source/utils.cpp b/stratosphere/ams_mitm/source/utils.cpp index 8f3947d9e..81c5db99b 100644 --- a/stratosphere/ams_mitm/source/utils.cpp +++ b/stratosphere/ams_mitm/source/utils.cpp @@ -25,6 +25,8 @@ #include "ini.h" #include "sha256.h" +#include "set_mitm/setsys_settings_items.hpp" + static FsFileSystem g_sd_filesystem = {0}; static HosSignal g_sd_signal; @@ -187,6 +189,11 @@ void Utils::InitializeThreadFunc(void *args) { /* Signal SD is initialized. */ g_has_initialized = true; + + /* Load custom settings configuration. */ + SettingsItemManager::LoadConfiguration(); + + /* Signal to waiters that we are ready. */ g_sd_signal.Signal(); /* Initialize HID. */ @@ -541,4 +548,12 @@ void Utils::RefreshConfiguration() { fsFileClose(&config_file); ini_parse_string(g_config_ini_data, FsMitMIniHandler, NULL); -} \ No newline at end of file +} + +Result Utils::GetSettingsItemValueSize(const char *name, const char *key, u64 *out_size) { + return SettingsItemManager::GetValueSize(name, key, out_size); +} + +Result Utils::GetSettingsItemValue(const char *name, const char *key, void *out, size_t max_size, u64 *out_size) { + return SettingsItemManager::GetValue(name, key, out, max_size, out_size); +} diff --git a/stratosphere/ams_mitm/source/utils.hpp b/stratosphere/ams_mitm/source/utils.hpp index e929bb10a..2c15ec13e 100644 --- a/stratosphere/ams_mitm/source/utils.hpp +++ b/stratosphere/ams_mitm/source/utils.hpp @@ -73,6 +73,10 @@ class Utils { static bool IsHidAvailable(); static Result GetKeysDown(u64 *keys); static bool HasOverrideButton(u64 tid); + + /* Settings! */ + static Result GetSettingsItemValueSize(const char *name, const char *key, u64 *out_size); + static Result GetSettingsItemValue(const char *name, const char *key, void *out, size_t max_size, u64 *out_size); private: static void RefreshConfiguration(); }; \ No newline at end of file From 1d0efbf456ab78be2b35adf1287876ac66a74dda Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 5 Feb 2019 10:58:52 -0800 Subject: [PATCH 409/489] fix json typo --- stratosphere/eclct.stub/eclct.stub.json | 152 ++++++++++++------------ 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/stratosphere/eclct.stub/eclct.stub.json b/stratosphere/eclct.stub/eclct.stub.json index 120ab2e22..5c86a71a8 100644 --- a/stratosphere/eclct.stub/eclct.stub.json +++ b/stratosphere/eclct.stub/eclct.stub.json @@ -1,22 +1,22 @@ { - "name": "eclct.stun", - "title_id": "0x0100000000000032", - "title_id_range_min": "0x0100000000000032", - "title_id_range_max": "0x0100000000000032", - "main_thread_stack_size": "0x00004000", - "main_thread_priority": 49, - "default_cpu_id": 3, - "process_category": 0, - "is_retail": true, - "pool_partition": 2, - "is_64_bit": true, - "address_space_type": 1, - "filesystem_access": { - "permissions": "0xFFFFFFFFFFFFFFFF" - }, + "name": "eclct.stub", + "title_id": "0x0100000000000032", + "title_id_range_min": "0x0100000000000032", + "title_id_range_max": "0x0100000000000032", + "main_thread_stack_size": "0x00004000", + "main_thread_priority": 49, + "default_cpu_id": 3, + "process_category": 0, + "is_retail": true, + "pool_partition": 2, + "is_64_bit": true, + "address_space_type": 1, + "filesystem_access": { + "permissions": "0xFFFFFFFFFFFFFFFF" + }, "service_host": [], "service_access": [], - "kernel_capabilities": [ + "kernel_capabilities": [ { "type": "kernel_flags", "value": { @@ -26,67 +26,67 @@ "highest_cpu_id": 3 } }, - { + { "type": "syscalls", "value": { - "svcSetHeapSize": "0x01", - "svcSetMemoryPermission": "0x02", - "svcSetMemoryAttribute": "0x03", - "svcMapMemory": "0x04", - "svcUnmapMemory": "0x05", - "svcQueryMemory": "0x06", - "svcExitProcess": "0x07", - "svcCreateThread": "0x08", - "svcStartThread": "0x09", - "svcExitThread": "0x0a", - "svcSleepThread": "0x0b", - "svcGetThreadPriority": "0x0c", - "svcSetThreadPriority": "0x0d", - "svcGetThreadCoreMask": "0x0e", - "svcSetThreadCoreMask": "0x0f", - "svcGetCurrentProcessorNumber": "0x10", - "svcSignalEvent": "0x11", - "svcClearEvent": "0x12", - "svcMapSharedMemory": "0x13", - "svcUnmapSharedMemory": "0x14", - "svcCreateTransferMemory": "0x15", - "svcCloseHandle": "0x16", - "svcResetSignal": "0x17", - "svcWaitSynchronization": "0x18", - "svcCancelSynchronization": "0x19", - "svcArbitrateLock": "0x1a", - "svcArbitrateUnlock": "0x1b", - "svcWaitProcessWideKeyAtomic": "0x1c", - "svcSignalProcessWideKey": "0x1d", - "svcGetSystemTick": "0x1e", - "svcConnectToNamedPort": "0x1f", - "svcSendSyncRequestLight": "0x20", - "svcSendSyncRequest": "0x21", - "svcSendSyncRequestWithUserBuffer": "0x22", - "svcSendAsyncRequestWithUserBuffer": "0x23", - "svcGetProcessId": "0x24", - "svcGetThreadId": "0x25", - "svcBreak": "0x26", - "svcOutputDebugString": "0x27", - "svcReturnFromException": "0x28", - "svcGetInfo": "0x29", - "svcWaitForAddress": "0x34", - "svcSignalToAddress": "0x35", - "svcCreateSession": "0x40", - "svcAcceptSession": "0x41", - "svcReplyAndReceiveLight": "0x42", - "svcReplyAndReceive": "0x43", - "svcReplyAndReceiveWithUserBuffer": "0x44", - "svcCreateEvent": "0x45", - "svcCreateInterruptEvent": "0x53", - "svcReadWriteRegister": "0x4E", - "svcQueryIoMapping": "0x55", - "svcCreateDeviceAddressSpace": "0x56", - "svcAttachDeviceAddressSpace": "0x57", - "svcDetachDeviceAddressSpace": "0x58", - "svcMapDeviceAddressSpaceAligned": "0x5a", - "svcUnmapDeviceAddressSpace": "0x5c", - "svcGetSystemInfo": "0x6f", + "svcSetHeapSize": "0x01", + "svcSetMemoryPermission": "0x02", + "svcSetMemoryAttribute": "0x03", + "svcMapMemory": "0x04", + "svcUnmapMemory": "0x05", + "svcQueryMemory": "0x06", + "svcExitProcess": "0x07", + "svcCreateThread": "0x08", + "svcStartThread": "0x09", + "svcExitThread": "0x0a", + "svcSleepThread": "0x0b", + "svcGetThreadPriority": "0x0c", + "svcSetThreadPriority": "0x0d", + "svcGetThreadCoreMask": "0x0e", + "svcSetThreadCoreMask": "0x0f", + "svcGetCurrentProcessorNumber": "0x10", + "svcSignalEvent": "0x11", + "svcClearEvent": "0x12", + "svcMapSharedMemory": "0x13", + "svcUnmapSharedMemory": "0x14", + "svcCreateTransferMemory": "0x15", + "svcCloseHandle": "0x16", + "svcResetSignal": "0x17", + "svcWaitSynchronization": "0x18", + "svcCancelSynchronization": "0x19", + "svcArbitrateLock": "0x1a", + "svcArbitrateUnlock": "0x1b", + "svcWaitProcessWideKeyAtomic": "0x1c", + "svcSignalProcessWideKey": "0x1d", + "svcGetSystemTick": "0x1e", + "svcConnectToNamedPort": "0x1f", + "svcSendSyncRequestLight": "0x20", + "svcSendSyncRequest": "0x21", + "svcSendSyncRequestWithUserBuffer": "0x22", + "svcSendAsyncRequestWithUserBuffer": "0x23", + "svcGetProcessId": "0x24", + "svcGetThreadId": "0x25", + "svcBreak": "0x26", + "svcOutputDebugString": "0x27", + "svcReturnFromException": "0x28", + "svcGetInfo": "0x29", + "svcWaitForAddress": "0x34", + "svcSignalToAddress": "0x35", + "svcCreateSession": "0x40", + "svcAcceptSession": "0x41", + "svcReplyAndReceiveLight": "0x42", + "svcReplyAndReceive": "0x43", + "svcReplyAndReceiveWithUserBuffer": "0x44", + "svcCreateEvent": "0x45", + "svcCreateInterruptEvent": "0x53", + "svcReadWriteRegister": "0x4E", + "svcQueryIoMapping": "0x55", + "svcCreateDeviceAddressSpace": "0x56", + "svcAttachDeviceAddressSpace": "0x57", + "svcDetachDeviceAddressSpace": "0x58", + "svcMapDeviceAddressSpaceAligned": "0x5a", + "svcUnmapDeviceAddressSpace": "0x5c", + "svcGetSystemInfo": "0x6f", "svcCallSecureMonitor": "0x7F" } }, @@ -94,5 +94,5 @@ "type": "min_kernel_version", "value": "0x0030" } - ] + ] } \ No newline at end of file From 6027ff243d0741e096df085bebee647feb2b286f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 12 Feb 2019 02:53:31 -0800 Subject: [PATCH 410/489] Enforce upper bound on application tid range --- stratosphere/ams_mitm/source/utils.cpp | 4 ++-- stratosphere/libstratosphere | 2 +- stratosphere/loader/source/ldr_content_management.cpp | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stratosphere/ams_mitm/source/utils.cpp b/stratosphere/ams_mitm/source/utils.cpp index 81c5db99b..637113fdc 100644 --- a/stratosphere/ams_mitm/source/utils.cpp +++ b/stratosphere/ams_mitm/source/utils.cpp @@ -368,7 +368,7 @@ Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data, } bool Utils::IsHblTid(u64 tid) { - return (g_override_any_app && tid >= 0x0100000000010000ULL) || (!g_override_any_app && tid == g_override_hbl_tid); + return (g_override_any_app && IsApplicationTid(tid)) || (!g_override_any_app && tid == g_override_hbl_tid); } bool Utils::HasTitleFlag(u64 tid, const char *flag) { @@ -447,7 +447,7 @@ Result Utils::GetKeysDown(u64 *keys) { } bool Utils::HasOverrideButton(u64 tid) { - if (tid < 0x0100000000010000ULL || !IsSdInitialized()) { + if ((!IsApplicationTid(tid)) || (!IsSdInitialized())) { /* Disable button override disable for non-applications. */ return true; } diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index fb12edcbb..a2c74f8cd 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit fb12edcbbaa5ef7a08fbb44d4aa13f0f37136537 +Subproject commit a2c74f8cd5311f8050bcc5ea7d07b1ba4b697558 diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 77a17bb5d..b5fbbb491 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -16,6 +16,7 @@ #include <cstring> #include <switch.h> +#include <stratosphere.hpp> #include <strings.h> #include <vector> #include <algorithm> @@ -309,7 +310,7 @@ void ContentManagement::TryMountSdCard() { } bool ContentManagement::ShouldReplaceWithHBL(u64 tid) { - return g_mounted_hbl_nsp && ((g_override_any_app && tid >= 0x0100000000010000) || (!g_override_any_app && tid == g_override_hbl_tid)); + return g_mounted_hbl_nsp && ((g_override_any_app && IsApplicationTid(tid)) || (!g_override_any_app && tid == g_override_hbl_tid)); } bool ContentManagement::ShouldOverrideContents(u64 tid) { From 56246551e6cbd100f5c57a738d393345404d64c4 Mon Sep 17 00:00:00 2001 From: m4xw <m4x@m4xw.net> Date: Wed, 13 Feb 2019 18:20:07 +0100 Subject: [PATCH 411/489] [Fusee] Refactor Kernel patching (#343) * [Fusee] Refactor Kernel patching Add offset based patching Add svcControlCodeMemory patches for ver. 5, 6, 7 --- fusee/fusee-secondary/src/kernel_patches.c | 197 ++++++++++++--------- 1 file changed, 114 insertions(+), 83 deletions(-) diff --git a/fusee/fusee-secondary/src/kernel_patches.c b/fusee/fusee-secondary/src/kernel_patches.c index 54561b4ed..b01891de0 100644 --- a/fusee/fusee-secondary/src/kernel_patches.c +++ b/fusee/fusee-secondary/src/kernel_patches.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Atmosphère-NX + * Copyright (c) 2019 m4xw <m4x@m4xw.net> * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -21,9 +22,10 @@ #include "ips.h" #define MAKE_BRANCH(a, o) 0x14000000 | ((((o) - (a)) >> 2) & 0x3FFFFFF) +#define MAKE_NOP 0xD503201F -#define MAKE_KERNEL_PATTERN_NAME(vers, name) g_kernel_patch_##vers##_##name -#define MAKE_KERNEL_HOOK_NAME(vers, name) g_kernel_hook_##vers##_##name +#define MAKE_KERNEL_PATTERN_NAME(vers, name) g_kernel_pattern_##vers##_##name +#define MAKE_KERNEL_PATCH_NAME(vers, name) g_kernel_patch_##vers##_##name typedef uint32_t instruction_t; @@ -33,14 +35,15 @@ typedef struct { size_t pattern_hook_offset; size_t payload_num_instructions; size_t branch_back_offset; + size_t patch_offset; const instruction_t *payload; -} kernel_hook_t; +} kernel_patch_t; typedef struct { uint8_t hash[0x20]; /* TODO: Come up with a better way to identify kernels, that doesn't rely on hashing them. */ size_t free_code_space_offset; - unsigned int num_hooks; - const kernel_hook_t *hooks; + unsigned int num_patches; + const kernel_patch_t *patches; } kernel_info_t; /* Patch definitions. */ @@ -60,7 +63,7 @@ typedef struct { ldp x10, x11, [sp],#0x10 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(100, proc_id_send)[] = {0x48, 0x29, 0x41, 0xF9, 0xC9, 0xF5, 0x7E, 0xD3, 0xCE, 0x09, 0x00, 0x11, 0x48, 0x6A, 0x29, 0xF8}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(100, proc_id_send)[] = {0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(100, proc_id_send)[] = {0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA}; /* stp x10, x11, [sp, #-0x10]! mov w10, w28 @@ -77,7 +80,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(100, proc_id_send)[] = {0xA9BF2 ldp x10, x11, [sp],#0x10 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(100, proc_id_recv)[] = {0x68, 0x29, 0x41, 0xF9, 0x89, 0xF7, 0x7E, 0xD3, 0x9C, 0x0B, 0x00, 0x11, 0x48, 0x69, 0x29, 0xF8}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(100, proc_id_recv)[] = {0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(100, proc_id_recv)[] = {0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA}; /* stp x10, x11, [sp, #-0x10]! mov w11, w24 @@ -94,7 +97,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(100, proc_id_recv)[] = {0xA9BF2 ldp x10, x11, [sp],#0x10 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(200, proc_id_send)[] = {0x48, 0x31, 0x41, 0xF9, 0xE9, 0x03, 0x18, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0xC8, 0x6A, 0x29, 0xF8}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(200, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(200, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA}; /* stp x10, x11, [sp, #-0x10]! mov w10, w15 @@ -113,7 +116,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(200, proc_id_send)[] = {0xA9BF2 ldp x10, x11, [sp],#0x10 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(200, proc_id_recv)[] = {0x08, 0x31, 0x41, 0xF9, 0xE9, 0x03, 0x0F, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0x48, 0x6B, 0x29, 0xF8}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(200, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(200, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA}; /* stp x10, x11, [sp, #-0x10]! mov w11, w24 @@ -130,7 +133,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(200, proc_id_recv)[] = {0xA9BF2 ldp x10, x11, [sp],#0x10 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(300, proc_id_send)[] = {0x48, 0x55, 0x41, 0xF9, 0xE9, 0x03, 0x18, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0xC8, 0x6A, 0x29, 0xF8}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(300, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(300, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA}; /* stp x10, x11, [sp, #-0x10]! mov w10, w15 @@ -149,7 +152,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(300, proc_id_send)[] = {0xA9BF2 ldp x10, x11, [sp],#0x10 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(300, proc_id_recv)[] = {0x08, 0x55, 0x41, 0xF9, 0xE9, 0x03, 0x0F, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0x48, 0x6B, 0x29, 0xF8}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(300, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(300, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA}; /* stp x10, x11, [sp, #-0x10]! mov w11, w24 @@ -166,7 +169,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(300, proc_id_recv)[] = {0xA9BF2 ldp x10, x11, [sp],#0x10 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(302, proc_id_send)[] = {0x48, 0x55, 0x41, 0xF9, 0xE9, 0x03, 0x18, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0xC8, 0x6A, 0x29, 0xF8}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(302, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(302, proc_id_send)[] = {0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA}; /* stp x10, x11, [sp, #-0x10]! mov w10, w15 @@ -185,7 +188,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(302, proc_id_send)[] = {0xA9BF2 ldp x10, x11, [sp],#0x10 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(302, proc_id_recv)[] = {0x08, 0x55, 0x41, 0xF9, 0xE9, 0x03, 0x0F, 0x2A, 0x29, 0xF5, 0x7E, 0xD3, 0x48, 0x6B, 0x29, 0xF8}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(302, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(302, proc_id_recv)[] = {0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA}; /* mov w10, w23 lsl x10, x10, #2 @@ -202,7 +205,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(302, proc_id_recv)[] = {0xA9BF2 ldr x10, [sp,#0xa0] */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(400, proc_id_send)[] = {0xEA, 0x53, 0x40, 0xF9, 0x48, 0x59, 0x41, 0xF9, 0xE9, 0x03, 0x17, 0x2A, 0x29, 0xF5, 0x7E, 0xD3}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(400, proc_id_send)[] = {0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(400, proc_id_send)[] = {0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA}; /* ldr x13, [sp,#0x70] mov w10, w14 @@ -219,7 +222,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(400, proc_id_send)[] = {0x2A170 nop */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(400, proc_id_recv)[] = {0x28, 0x5B, 0x41, 0xF9, 0xE9, 0x03, 0x0E, 0x2A, 0xCE, 0x09, 0x00, 0x11, 0x29, 0xF5, 0x7E, 0xD3}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(400, proc_id_recv)[] = {0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(400, proc_id_recv)[] = {0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F}; /* mov w10, w23 lsl x10, x10, #2 @@ -236,7 +239,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(400, proc_id_recv)[] = {0xF9403 ldr x10, [sp,#0x80] */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(500, proc_id_send)[] = {0xEA, 0x43, 0x40, 0xF9, 0x48, 0x59, 0x41, 0xF9, 0xE9, 0x03, 0x17, 0x2A, 0x29, 0xF5, 0x7E, 0xD3}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_send)[] = {0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(500, proc_id_send)[] = {0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA}; /* ldr x13, [sp, #0x70] mov w10, w21 @@ -253,7 +256,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_send)[] = {0x2A170 ldr x10, [sp,#0xd8] */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(500, proc_id_recv)[] = {0x08, 0x5B, 0x41, 0xF9, 0xEA, 0x6F, 0x40, 0xF9, 0xE9, 0x03, 0x15, 0x2A, 0x29, 0xF5, 0x7E, 0xD3}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_recv)[] = {0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(500, proc_id_recv)[] = {0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA}; /* stp x10, x11, [sp, #-0x10]! ldr x11, [sp, #0x68] @@ -280,7 +283,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(500, proc_id_recv)[] = {0xF9403 mov x0, x8 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_send)[] = {0x08, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x15, 0x2A, 0xB5, 0x0A, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_send)[] = {0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(600, proc_id_send)[] = {0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; /* stp x10, x11, [sp, #-0x10]! ldr x11, [sp, #0x80] @@ -307,7 +310,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_send)[] = {0xA9BF2 mov x0, x8 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv)[] = {0x08, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE9, 0x6F, 0x40, 0xF9, 0xE8, 0x03, 0x15, 0x2A, 0xB5, 0x0A, 0x00, 0x11}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_recv)[] = {0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(600, proc_id_recv)[] = {0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; /* stp x10, x11, [sp, #-0x10]! ldr x11, [sp, #0x70] @@ -334,7 +337,7 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(600, proc_id_recv)[] = {0xA9BF2 mov x0, x8 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(700, proc_id_send)[] = {0xA8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x15, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x03, 0x19, 0x2A, 0x39, 0x0B, 0x00, 0x11, 0x08, 0xF5, 0x7E, 0xD3}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(700, proc_id_send)[] = {0xA9BF2FEA, 0xF9403BEB, 0x2A1903EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(700, proc_id_send)[] = {0xA9BF2FEA, 0xF9403BEB, 0x2A1903EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; /* stp x10, x11, [sp, #-0x10]! ldr x11, [sp, #0x98] @@ -361,203 +364,223 @@ static const instruction_t MAKE_KERNEL_HOOK_NAME(700, proc_id_send)[] = {0xA9BF2 mov x0, x8 */ static const uint8_t MAKE_KERNEL_PATTERN_NAME(700, proc_id_recv)[] = {0x68, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1B, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xA9, 0x83, 0x50, 0xF8, 0xE8, 0x03, 0x16, 0x2A, 0xD6, 0x0A, 0x00, 0x11}; -static const instruction_t MAKE_KERNEL_HOOK_NAME(700, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(700, proc_id_recv)[] = {0xA9BF2FEA, 0xF9404FEB, 0x2A1603EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400368, 0xF9401D08, 0xAA1B03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0}; + +/* svcControlCodeMemory Patches */ +/* b.eq -> nop */ +static const instruction_t MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory)[] = {MAKE_NOP}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory)[] = {MAKE_NOP}; +static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[] = {MAKE_NOP}; /* Hook Definitions. */ -static const kernel_hook_t g_kernel_hooks_100[] = { +static const kernel_patch_t g_kernel_patches_100[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(100, proc_id_send), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(100, proc_id_send))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(100, proc_id_send))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(100, proc_id_send) + .payload = MAKE_KERNEL_PATCH_NAME(100, proc_id_send) }, { /* Receive Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(100, proc_id_recv), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(100, proc_id_recv))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(100, proc_id_recv))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(100, proc_id_recv) + .payload = MAKE_KERNEL_PATCH_NAME(100, proc_id_recv) } }; -static const kernel_hook_t g_kernel_hooks_200[] = { +static const kernel_patch_t g_kernel_patches_200[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(200, proc_id_send), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(200, proc_id_send))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(200, proc_id_send))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(200, proc_id_send) + .payload = MAKE_KERNEL_PATCH_NAME(200, proc_id_send) }, { /* Receive Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(200, proc_id_recv), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(200, proc_id_recv))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(200, proc_id_recv))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(200, proc_id_recv) + .payload = MAKE_KERNEL_PATCH_NAME(200, proc_id_recv) } }; -static const kernel_hook_t g_kernel_hooks_300[] = { +static const kernel_patch_t g_kernel_patches_300[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(300, proc_id_send), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(300, proc_id_send))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(300, proc_id_send))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(300, proc_id_send) + .payload = MAKE_KERNEL_PATCH_NAME(300, proc_id_send) }, { /* Receive Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(300, proc_id_recv), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(300, proc_id_recv))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(300, proc_id_recv))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(300, proc_id_recv) + .payload = MAKE_KERNEL_PATCH_NAME(300, proc_id_recv) } }; -static const kernel_hook_t g_kernel_hooks_302[] = { +static const kernel_patch_t g_kernel_patches_302[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(302, proc_id_send), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(302, proc_id_send))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(302, proc_id_send))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(302, proc_id_send) + .payload = MAKE_KERNEL_PATCH_NAME(302, proc_id_send) }, { /* Receive Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(302, proc_id_recv), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(302, proc_id_recv))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(302, proc_id_recv))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(302, proc_id_recv) + .payload = MAKE_KERNEL_PATCH_NAME(302, proc_id_recv) } }; -static const kernel_hook_t g_kernel_hooks_400[] = { +static const kernel_patch_t g_kernel_patches_400[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(400, proc_id_send), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(400, proc_id_send))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(400, proc_id_send))/sizeof(instruction_t), .branch_back_offset = 0x8, - .payload = MAKE_KERNEL_HOOK_NAME(400, proc_id_send) + .payload = MAKE_KERNEL_PATCH_NAME(400, proc_id_send) }, { /* Receive Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(400, proc_id_recv), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(400, proc_id_recv))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(400, proc_id_recv))/sizeof(instruction_t), .branch_back_offset = 0x4, - .payload = MAKE_KERNEL_HOOK_NAME(400, proc_id_recv) + .payload = MAKE_KERNEL_PATCH_NAME(400, proc_id_recv) } }; -static const kernel_hook_t g_kernel_hooks_500[] = { +static const kernel_patch_t g_kernel_patches_500[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(500, proc_id_send), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(500, proc_id_send))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(500, proc_id_send))/sizeof(instruction_t), .branch_back_offset = 0x8, - .payload = MAKE_KERNEL_HOOK_NAME(500, proc_id_send) + .payload = MAKE_KERNEL_PATCH_NAME(500, proc_id_send) }, { /* Receive Message Process ID Patch. */ .pattern_size = 0x10, .pattern = MAKE_KERNEL_PATTERN_NAME(500, proc_id_recv), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(500, proc_id_recv))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(500, proc_id_recv))/sizeof(instruction_t), .branch_back_offset = 0x8, - .payload = MAKE_KERNEL_HOOK_NAME(500, proc_id_recv) + .payload = MAKE_KERNEL_PATCH_NAME(500, proc_id_recv) + }, + { /* svcControlCodeMemory Patch. */ + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory))/sizeof(instruction_t), + .payload = MAKE_KERNEL_PATCH_NAME(500, svc_control_codememory), + .patch_offset = 0x38C2C, } }; -static const kernel_hook_t g_kernel_hooks_600[] = { +static const kernel_patch_t g_kernel_patches_600[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x1C, .pattern = MAKE_KERNEL_PATTERN_NAME(600, proc_id_send), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(600, proc_id_send))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(600, proc_id_send))/sizeof(instruction_t), .branch_back_offset = 0x10, - .payload = MAKE_KERNEL_HOOK_NAME(600, proc_id_send) + .payload = MAKE_KERNEL_PATCH_NAME(600, proc_id_send) }, { /* Receive Message Process ID Patch. */ .pattern_size = 0x1C, .pattern = MAKE_KERNEL_PATTERN_NAME(600, proc_id_recv), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(600, proc_id_recv))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(600, proc_id_recv))/sizeof(instruction_t), .branch_back_offset = 0x10, - .payload = MAKE_KERNEL_HOOK_NAME(600, proc_id_recv) + .payload = MAKE_KERNEL_PATCH_NAME(600, proc_id_recv) + }, + { /* svcControlCodeMemory Patch. */ + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory))/sizeof(instruction_t), + .payload = MAKE_KERNEL_PATCH_NAME(600, svc_control_codememory), + .patch_offset = 0x3A8CC, } }; -static const kernel_hook_t g_kernel_hooks_700[] = { +static const kernel_patch_t g_kernel_patches_700[] = { { /* Send Message Process ID Patch. */ .pattern_size = 0x1C, .pattern = MAKE_KERNEL_PATTERN_NAME(700, proc_id_send), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(700, proc_id_send))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(700, proc_id_send))/sizeof(instruction_t), .branch_back_offset = 0x10, - .payload = MAKE_KERNEL_HOOK_NAME(700, proc_id_send) + .payload = MAKE_KERNEL_PATCH_NAME(700, proc_id_send) }, { /* Receive Message Process ID Patch. */ .pattern_size = 0x1C, .pattern = MAKE_KERNEL_PATTERN_NAME(700, proc_id_recv), .pattern_hook_offset = 0x0, - .payload_num_instructions = sizeof(MAKE_KERNEL_HOOK_NAME(700, proc_id_recv))/sizeof(instruction_t), + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(700, proc_id_recv))/sizeof(instruction_t), .branch_back_offset = 0x10, - .payload = MAKE_KERNEL_HOOK_NAME(700, proc_id_recv) + .payload = MAKE_KERNEL_PATCH_NAME(700, proc_id_recv) + }, + { /* svcControlCodeMemory Patch. */ + .payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory))/sizeof(instruction_t), + .payload = MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory), + .patch_offset = 0x3C6E0, } }; - -#define KERNEL_HOOKS(vers) .num_hooks = sizeof(g_kernel_hooks_##vers)/sizeof(kernel_hook_t), .hooks = g_kernel_hooks_##vers, +#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers, /* Kernel Infos. */ static const kernel_info_t g_kernel_infos[] = { { /* 1.0.0-7. */ .hash = {0x64, 0x44, 0x07, 0x2F, 0x56, 0x44, 0x73, 0xDD, 0xD5, 0x46, 0x1B, 0x8C, 0xDC, 0xEF, 0x54, 0x98, 0x16, 0xDA, 0x81, 0xDE, 0x5B, 0x1C, 0x9D, 0xD7, 0x5A, 0x13, 0x91, 0xD9, 0x53, 0xAB, 0x8D, 0x8D}, .free_code_space_offset = 0x4797C, - KERNEL_HOOKS(100) + KERNEL_PATCHES(100) }, { /* 1.0.0. */ .hash = {0xB8, 0xC5, 0x0C, 0x68, 0x25, 0xA9, 0xB9, 0x5B, 0xD2, 0x4D, 0x2C, 0x7C, 0x81, 0x7F, 0xE6, 0x96, 0xF2, 0x42, 0x4E, 0x1D, 0x78, 0xDF, 0x3B, 0xCA, 0x3D, 0x6B, 0x68, 0x12, 0xDD, 0xA9, 0xCB, 0x9C}, .free_code_space_offset = 0x4797C, - KERNEL_HOOKS(100) + KERNEL_PATCHES(100) }, { /* 2.0.0. */ .hash = {0x64, 0x0B, 0x51, 0xFF, 0x28, 0x01, 0xB8, 0x30, 0xA7, 0xA3, 0x60, 0x47, 0x86, 0x0D, 0x68, 0xAA, 0x9A, 0x92, 0x10, 0x0D, 0xB9, 0xCC, 0xEC, 0x8B, 0x05, 0x80, 0x73, 0xBD, 0x33, 0xB4, 0x2C, 0x6C}, .free_code_space_offset = 0x6486C, - KERNEL_HOOKS(200) + KERNEL_PATCHES(200) }, { /* 3.0.0. */ .hash = {0x50, 0x84, 0x23, 0xAC, 0x6F, 0xA1, 0x5D, 0x3B, 0x56, 0xC2, 0xFC, 0x95, 0x22, 0xCC, 0xD5, 0xA8, 0x15, 0xD3, 0xB4, 0x6B, 0xA1, 0x2C, 0xF2, 0x93, 0xD3, 0x02, 0x05, 0xAB, 0x52, 0xEF, 0x73, 0xC5}, .free_code_space_offset = 0x494A4, - KERNEL_HOOKS(300) + KERNEL_PATCHES(300) }, { /* 3.0.2. */ .hash = {0x81, 0x9D, 0x08, 0xBE, 0xE4, 0x5E, 0x1F, 0xBB, 0x45, 0x5A, 0x6D, 0x70, 0x4B, 0xB2, 0x17, 0xA6, 0x12, 0x69, 0xF8, 0xB8, 0x75, 0x1C, 0x71, 0x16, 0xF0, 0xE9, 0x79, 0x7F, 0xB0, 0xD1, 0x78, 0xB2}, .free_code_space_offset = 0x494BC, - KERNEL_HOOKS(302) + KERNEL_PATCHES(302) }, { /* 4.0.0. */ .hash = {0xE6, 0xC0, 0xB7, 0xE3, 0x2F, 0xF9, 0x44, 0x51, 0xEC, 0xD5, 0x95, 0x79, 0xE3, 0x46, 0xB1, 0xDA, 0x2E, 0xD9, 0x28, 0xC6, 0xF2, 0x31, 0x4F, 0x95, 0xD8, 0xC7, 0xD5, 0xBD, 0x15, 0xD5, 0xE2, 0x5A}, .free_code_space_offset = 0x52890, - KERNEL_HOOKS(400) + KERNEL_PATCHES(400) }, { /* 5.0.0. */ .hash = {0xB2, 0x38, 0x61, 0xA8, 0xE1, 0xE2, 0xE4, 0xE4, 0x17, 0x28, 0xED, 0xA9, 0xF6, 0xF6, 0xBD, 0xD2, 0x59, 0xDB, 0x1F, 0xEF, 0x4A, 0x8B, 0x2F, 0x1C, 0x64, 0x46, 0x06, 0x40, 0xF5, 0x05, 0x9C, 0x43}, .free_code_space_offset = 0x5C020, - KERNEL_HOOKS(500) + KERNEL_PATCHES(500) }, { /* 6.0.0. */ .hash = {0x85, 0x97, 0x40, 0xF6, 0xC0, 0x3E, 0x3D, 0x44, 0xDE, 0xA4, 0xA0, 0x35, 0xFD, 0x12, 0x9C, 0xD4, 0x4F, 0x9C, 0x36, 0x53, 0x74, 0x54, 0x2C, 0x9C, 0x55, 0x47, 0xC4, 0x25, 0xF1, 0x42, 0xFB, 0x97}, .free_code_space_offset = 0x5EE00, - KERNEL_HOOKS(600) + KERNEL_PATCHES(600) }, { /* 7.0.0. */ .hash = {0xA2, 0x5E, 0x47, 0x0C, 0x8E, 0x6D, 0x2F, 0xD7, 0x5D, 0xAD, 0x24, 0xD7, 0xD8, 0x24, 0x34, 0xFB, 0xCD, 0x77, 0xBB, 0xE6, 0x66, 0x03, 0xCB, 0xAF, 0xAB, 0x85, 0x45, 0xA0, 0x91, 0xAF, 0x34, 0x25}, .free_code_space_offset = 0x5FEC0, - KERNEL_HOOKS(700) + KERNEL_PATCHES(700) } }; @@ -608,13 +631,21 @@ void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel) { return; } - /* Apply hooks. */ + /* Apply hooks and patches. */ uint8_t *kernel = (uint8_t *)_kernel; size_t free_space_offset = kernel_info->free_code_space_offset; size_t free_space_size = ((free_space_offset + 0xFFFULL) & ~0xFFFULL) - free_space_offset; - for (unsigned int i = 0; i < kernel_info->num_hooks; i++) { - size_t hook_size = sizeof(instruction_t) * kernel_info->hooks[i].payload_num_instructions; - if (kernel_info->hooks[i].branch_back_offset) { + for (unsigned int i = 0; i < kernel_info->num_patches; i++) { + if (kernel_info->patches[i].patch_offset) { + for (unsigned int p = 0; p < kernel_info->patches[i].payload_num_instructions; p++) { + *(volatile instruction_t*)(_kernel + kernel_info->patches[i].patch_offset) = kernel_info->patches[i].payload[p]; + } + continue; + } + + size_t hook_size = sizeof(instruction_t) * kernel_info->patches[i].payload_num_instructions; + + if (kernel_info->patches[i].branch_back_offset) { hook_size += sizeof(instruction_t); } if (free_space_size < hook_size) { @@ -622,22 +653,22 @@ void package2_patch_kernel(void *_kernel, size_t size, bool is_sd_kernel) { fatal_error("kernel_patcher: insufficient space to apply patches!\n"); } - uint8_t *pattern_loc = search_pattern(kernel, size, kernel_info->hooks[i].pattern, kernel_info->hooks[i].pattern_size); + uint8_t *pattern_loc = search_pattern(kernel, size, kernel_info->patches[i].pattern, kernel_info->patches[i].pattern_size); if (pattern_loc == NULL) { /* TODO: Should we print an error/abort here? */ continue; } /* Patch kernel to branch to our hook at the desired place. */ - instruction_t *hook_start = (instruction_t *)(pattern_loc + kernel_info->hooks[i].pattern_hook_offset); + volatile instruction_t *hook_start = (instruction_t *)(pattern_loc + kernel_info->patches[i].pattern_hook_offset); *hook_start = MAKE_BRANCH((uint32_t)((uintptr_t)hook_start - (uintptr_t)kernel), free_space_offset); /* Insert hook into free space. */ - instruction_t *payload = (instruction_t *)(kernel + free_space_offset); - for (unsigned int p = 0; p < kernel_info->hooks[i].payload_num_instructions; p++) { - payload[p] = kernel_info->hooks[i].payload[p]; + volatile instruction_t *payload = (instruction_t *)(kernel + free_space_offset); + for (unsigned int p = 0; p < kernel_info->patches[i].payload_num_instructions; p++) { + payload[p] = kernel_info->patches[i].payload[p]; } - if (kernel_info->hooks[i].branch_back_offset) { - payload[kernel_info->hooks[i].payload_num_instructions] = MAKE_BRANCH(free_space_offset + sizeof(instruction_t) * kernel_info->hooks[i].payload_num_instructions, (uint32_t)(kernel_info->hooks[i].branch_back_offset + (uintptr_t)hook_start - (uintptr_t)kernel)); + if (kernel_info->patches[i].branch_back_offset) { + payload[kernel_info->patches[i].payload_num_instructions] = MAKE_BRANCH(free_space_offset + sizeof(instruction_t) * kernel_info->patches[i].payload_num_instructions, (uint32_t)(kernel_info->patches[i].branch_back_offset + (uintptr_t)hook_start - (uintptr_t)kernel)); } free_space_offset += hook_size; From 85669ef491dad824dad49f732612a4dd1bbee22a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 14 Feb 2019 04:29:12 -0800 Subject: [PATCH 412/489] Fix off-by-one (thanks @CtCaer) --- exosphere/src/package2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exosphere/src/package2.c b/exosphere/src/package2.c index 3d2842085..eccec5df7 100644 --- a/exosphere/src/package2.c +++ b/exosphere/src/package2.c @@ -141,10 +141,10 @@ static void setup_se(void) { unsigned int master_kek_source_ind; switch (exosphere_get_target_firmware()) { case ATMOSPHERE_TARGET_FIRMWARE_620: - master_kek_source_ind = MASTERKEY_REVISION_620 - MASTERKEY_REVISION_600_610; + master_kek_source_ind = MASTERKEY_REVISION_620 - MASTERKEY_REVISION_620; break; case ATMOSPHERE_TARGET_FIRMWARE_700: - master_kek_source_ind = MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_600_610; + master_kek_source_ind = MASTERKEY_REVISION_700_CURRENT - MASTERKEY_REVISION_620; break; default: generic_panic(); From 26f45fab19c5055cffe9626dc04c399eed62c908 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 04:52:11 -0800 Subject: [PATCH 413/489] sept: commit working primary. --- fusee/fusee-secondary/Makefile | 20 +- fusee/fusee-secondary/src/nxboot.c | 6 + fusee/fusee-secondary/src/utils.c | 57 ++- fusee/fusee-secondary/src/utils.h | 2 + sept/Makefile | 10 + sept/sept-primary/Makefile | 169 ++++++++ sept/sept-primary/linker.ld | 168 ++++++++ sept/sept-primary/linker.specs | 7 + sept/sept-primary/src/apb_misc.h | 81 ++++ sept/sept-primary/src/btn.c | 82 ++++ sept/sept-primary/src/btn.h | 30 ++ sept/sept-primary/src/car.c | 139 ++++++ sept/sept-primary/src/car.h | 505 ++++++++++++++++++++++ sept/sept-primary/src/di.h | 350 ++++++++++++++++ sept/sept-primary/src/fuse.c | 256 ++++++++++++ sept/sept-primary/src/fuse.h | 213 ++++++++++ sept/sept-primary/src/gpio.c | 145 +++++++ sept/sept-primary/src/gpio.h | 127 ++++++ sept/sept-primary/src/i2c.c | 219 ++++++++++ sept/sept-primary/src/i2c.h | 101 +++++ sept/sept-primary/src/main.c | 224 ++++++++++ sept/sept-primary/src/mc.c | 50 +++ sept/sept-primary/src/mc.h | 593 ++++++++++++++++++++++++++ sept/sept-primary/src/panic.c | 93 +++++ sept/sept-primary/src/panic.h | 34 ++ sept/sept-primary/src/pmc.h | 626 ++++++++++++++++++++++++++++ sept/sept-primary/src/se.c | 649 +++++++++++++++++++++++++++++ sept/sept-primary/src/se.h | 219 ++++++++++ sept/sept-primary/src/start.s | 100 +++++ sept/sept-primary/src/sysreg.h | 48 +++ sept/sept-primary/src/timers.h | 78 ++++ sept/sept-primary/src/tsec.h | 119 ++++++ sept/sept-primary/src/utils.c | 105 +++++ sept/sept-primary/src/utils.h | 129 ++++++ 34 files changed, 5744 insertions(+), 10 deletions(-) create mode 100644 sept/Makefile create mode 100644 sept/sept-primary/Makefile create mode 100644 sept/sept-primary/linker.ld create mode 100644 sept/sept-primary/linker.specs create mode 100644 sept/sept-primary/src/apb_misc.h create mode 100644 sept/sept-primary/src/btn.c create mode 100644 sept/sept-primary/src/btn.h create mode 100644 sept/sept-primary/src/car.c create mode 100644 sept/sept-primary/src/car.h create mode 100644 sept/sept-primary/src/di.h create mode 100644 sept/sept-primary/src/fuse.c create mode 100644 sept/sept-primary/src/fuse.h create mode 100644 sept/sept-primary/src/gpio.c create mode 100644 sept/sept-primary/src/gpio.h create mode 100644 sept/sept-primary/src/i2c.c create mode 100644 sept/sept-primary/src/i2c.h create mode 100644 sept/sept-primary/src/main.c create mode 100644 sept/sept-primary/src/mc.c create mode 100644 sept/sept-primary/src/mc.h create mode 100644 sept/sept-primary/src/panic.c create mode 100644 sept/sept-primary/src/panic.h create mode 100644 sept/sept-primary/src/pmc.h create mode 100644 sept/sept-primary/src/se.c create mode 100644 sept/sept-primary/src/se.h create mode 100644 sept/sept-primary/src/start.s create mode 100644 sept/sept-primary/src/sysreg.h create mode 100644 sept/sept-primary/src/timers.h create mode 100644 sept/sept-primary/src/tsec.h create mode 100644 sept/sept-primary/src/utils.c create mode 100644 sept/sept-primary/src/utils.h diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index ed51bffb8..930abf2b0 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -87,7 +87,8 @@ export KIPDIRS := $(AMS)/stratosphere/loader $(AMS)/stratosphere/pm $(AMS)/strat export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ $(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/exosphere/rebootstub \ - $(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(KIPDIRS) + $(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \ + $(KIPDIRS) export DEPSDIR := $(CURDIR)/$(BUILD) @@ -95,7 +96,10 @@ CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip boot_100.kip boot_200.kip -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp $(KIPFILES) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \ + exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp \ + sept-primary.bin \ + $(KIPFILES) #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C @@ -123,7 +127,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) .PHONY: $(BUILD) clean all -.PHONY: check_fusee_primary check_exosphere check_thermosphere check_stratosphere +.PHONY: check_fusee_primary check_exosphere check_sept check_thermosphere check_stratosphere #--------------------------------------------------------------------------------- all: $(BUILD) @@ -134,6 +138,9 @@ check_fusee_primary: check_exosphere: @$(MAKE) -C $(AMS)/exosphere all +check_sept: + @$(MAKE) -C $(AMS)/sept all + check_thermosphere: @$(MAKE) -C $(AMS)/thermosphere all @@ -141,7 +148,7 @@ check_stratosphere: @$(MAKE) -C $(AMS)/stratosphere all -$(BUILD): check_fusee_primary check_exosphere check_thermosphere check_stratosphere +$(BUILD): check_fusee_primary check_exosphere check_sept check_thermosphere check_stratosphere @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile @@ -186,6 +193,11 @@ fusee_primary.bin.o fusee_primary_bin.h: fusee-primary.bin @echo $(notdir $<) @$(_bin2o) +sept_primary.bin.o sept_primary_bin.h: sept-primary.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(_bin2o) + %.bin.o %_bin.h: %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 92eef7440..0ca6e42a6 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -411,6 +411,12 @@ uint32_t nxboot_main(void) { } } + if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_700) { + /* TODO: Detect when we have been loaded by sept-secondary, and thus have keys provided for us. */ + static const uint8_t sept_secondary[0x0] = { /* TODO: link-time magic */ }; + reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary, sizeof(sept_secondary)); + } + print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); /* Get the TSEC keys. */ diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index e09fc6e37..a847320a6 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -32,6 +32,7 @@ #define u8 uint8_t #define u32 uint32_t #include "fusee_primary_bin.h" +#include "sept_primary_bin.h" #include "rebootstub_bin.h" #undef u8 #undef u32 @@ -65,7 +66,7 @@ __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) { } } -__attribute__((noreturn)) void reboot_to_fusee_primary(void) { +__attribute__((noreturn)) static void reboot_to_payload(void) { /* Patch SDRAM init to perform an SVC immediately after second write */ APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF; APBDEV_PMC_SCRATCH46_0 = 0x6001DC28; @@ -73,11 +74,6 @@ __attribute__((noreturn)) void reboot_to_fusee_primary(void) { APBDEV_PMC_SCRATCH33_0 = 0x4003F000; APBDEV_PMC_SCRATCH40_0 = 0x6000F208; - /* Copy fusee-primary into IRAM low. */ - for (size_t i = 0; i < fusee_primary_bin_size; i += sizeof(uint32_t)) { - write32le((void *)0x40010000, i, read32le(fusee_primary_bin, i)); - } - /* Copy reboot stub into IRAM high. */ for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) { write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i)); @@ -85,6 +81,55 @@ __attribute__((noreturn)) void reboot_to_fusee_primary(void) { /* Trigger warm reboot. */ pmc_reboot(1 << 0); + while (true) { } +} + +__attribute__((noreturn)) void reboot_to_fusee_primary(void) { + /* Copy fusee-primary into IRAM low. */ + for (size_t i = 0; i < fusee_primary_bin_size; i += sizeof(uint32_t)) { + write32le((void *)0x40010000, i, read32le(fusee_primary_bin, i)); + } + + reboot_to_payload(); +} + +__attribute__((noreturn)) void reboot_to_sept(const void *tsec_fw, size_t tsec_fw_length, const void *stage2, size_t stage2_size) { + + /* Copy tsec firmware. */ + for (size_t i = 0; i < tsec_fw_length; i += sizeof(uint32_t)) { + write32le((void *)0x40010F00, i, read32le(tsec_fw, i)); + } + MAKE_REG32(0x40010EFC) = tsec_fw_length; + + /* Copy stage 2. */ + for (size_t i = 0; i < stage2_size; i += sizeof(uint32_t)) { + write32le((void *)0x40016FE0, i, read32le(stage2, i)); + } + + /* Copy sept into IRAM low. */ + for (size_t i = 0; i < sept_primary_bin_size; i += sizeof(uint32_t)) { + write32le((void *)0x4003F000, i, read32le(sept_primary_bin, i)); + } + + /* Patch SDRAM init to perform an SVC immediately after second write */ + APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF; + APBDEV_PMC_SCRATCH46_0 = 0x6001DC28; + /* Set SVC handler to jump to reboot stub in IRAM. */ + APBDEV_PMC_SCRATCH33_0 = 0x4003F000; + APBDEV_PMC_SCRATCH40_0 = 0x6000F208; + + /* Trigger warm reboot. */ + pmc_reboot(1 << 0); + while (true) { } +} + +__attribute__((noreturn)) void reboot_to_iram_payload(void *payload, size_t payload_size) { + /* Copy sept into IRAM low. */ + for (size_t i = 0; i < payload_size; i += sizeof(uint32_t)) { + write32le((void *)0x40010000, i, read32le(payload, i)); + } + + reboot_to_payload(); } __attribute__((noreturn)) void wait_for_button_and_reboot(void) { diff --git a/fusee/fusee-secondary/src/utils.h b/fusee/fusee-secondary/src/utils.h index 8cc3e6814..605bd6ed3 100644 --- a/fusee/fusee-secondary/src/utils.h +++ b/fusee/fusee-secondary/src/utils.h @@ -123,6 +123,8 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase); __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); __attribute__((noreturn)) void reboot_to_fusee_primary(void); +__attribute__((noreturn)) void reboot_to_sept(const void *tsec_fw, size_t tsec_fw_length, const void *stage2, size_t stage2_size); +__attribute__((noreturn)) void reboot_to_iram_payload(void *payload, size_t payload_size); __attribute__((noreturn)) void wait_for_button_and_reboot(void); void wait_for_button(void); diff --git a/sept/Makefile b/sept/Makefile new file mode 100644 index 000000000..632a5cd13 --- /dev/null +++ b/sept/Makefile @@ -0,0 +1,10 @@ +SUBFOLDERS := sept-primary + +TOPTARGETS := all clean + +$(TOPTARGETS): $(SUBFOLDERS) + +$(SUBFOLDERS): + $(MAKE) -C $@ $(MAKECMDGOALS) + +.PHONY: $(TOPTARGETS) $(SUBFOLDERS) diff --git a/sept/sept-primary/Makefile b/sept/sept-primary/Makefile new file mode 100644 index 000000000..107b32f55 --- /dev/null +++ b/sept/sept-primary/Makefile @@ -0,0 +1,169 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM") +endif + +TOPDIR ?= $(CURDIR) + +AMS := $(TOPDIR)/../../ +include $(DEVKITARM)/base_rules + +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display +DATA := data +INCLUDES := include ../../common/include + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork +DEFINES := -D__BPMP__ -DFUSEE_STAGE1_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" + +CFLAGS := \ + -g \ + -O2 \ + -fomit-frame-pointer \ + -ffunction-sections \ + -fdata-sections \ + -std=gnu11 \ + -Werror \ + -Wall \ + -fstrict-volatile-bitfields \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(AMS)/exosphere/rebootstub + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) rebootstub.bin + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean all check_rebootstub + +#--------------------------------------------------------------------------------- +all: check_rebootstub $(BUILD) + +check_rebootstub: + @$(MAKE) -C $(AMS)/exosphere/rebootstub all + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @$(MAKE) -C $(AMS)/exosphere/rebootstub clean + @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).bin + +$(OUTPUT).bin : $(OUTPUT).elf + $(OBJCOPY) -S -O binary $< $@ + @echo built ... $(notdir $@) + +$(OUTPUT).elf : $(OFILES) + +%.elf: $(OFILES) + @echo linking $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + @$(NM) -CSn $@ > $(notdir $*.lst) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h: %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/sept/sept-primary/linker.ld b/sept/sept-primary/linker.ld new file mode 100644 index 000000000..7d135168c --- /dev/null +++ b/sept/sept-primary/linker.ld @@ -0,0 +1,168 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +PHDRS +{ + crt0 PT_LOAD; + main PT_LOAD; +} + +/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */ +MEMORY +{ + NULL : ORIGIN = 0x00000000, LENGTH = 0x1000 + main : ORIGIN = 0x40010040, LENGTH = 0x1000 + high_iram : ORIGIN = 0x4003F000, LENGTH = 0x1000 + low_iram : ORIGIN = 0x40003000, LENGTH = 0x8000 +} + +SECTIONS +{ + PROVIDE(__crt0_start__ = 0x4003F000); + PROVIDE(__main_start__ = 0x40010040); + PROVIDE(__stack_top__ = 0x40010000); + PROVIDE(__stack_bottom__ = 0x4000C000); + PROVIDE(__heap_start__ = 0); + PROVIDE(__heap_end__ = 0); + + . = __crt0_start__; + + .crt0 : + { + KEEP( *(.text.start) ) + KEEP( *(.text.ipatch_word) ) + KEEP( *(.init) ) + . = ALIGN(32); + } >high_iram AT>high_iram :crt0 + + __main_phys_start__ = ABSOLUTE(.) ; + + .text : + { + /* .text */ + KEEP( *(.text.jump_to_main) ) + *(.text) + *(.text.*) + *(.glue_7) + *(.glue_7t) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.t*) + + /* .fini */ + KEEP( *(.fini) ) + . = ALIGN(8); + } >main AT>high_iram :main + + .rodata : + { + *(.rodata) + *(.roda) + *(.rodata.*) + *all.rodata*(*) + *(.gnu.linkonce.r*) + SORT(CONSTRUCTORS) + . = ALIGN(8); + } >main AT>high_iram + + .preinit_array : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } >main AT>high_iram + + .init_array ALIGN(4) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } >main AT>high_iram + + .fini_array ALIGN(4) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } >main AT>high_iram + + .ctors ALIGN(4) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >main AT>high_iram + + .dtors ALIGN(4) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >main AT>high_iram + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main AT>high_iram + ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main AT>high_iram + + .bss (NOLOAD) : + { + . = ALIGN(32); + PROVIDE (__bss_start__ = ABSOLUTE(.)); + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(32); + PROVIDE (__bss_end__ = ABSOLUTE(.)); + } >main AT>high_iram :NONE + __main_end__ = ABSOLUTE(.) ; + + PROVIDE(__main_size__ = (__main_end__ - __main_start__)); + + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note) } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } +} diff --git a/sept/sept-primary/linker.specs b/sept/sept-primary/linker.specs new file mode 100644 index 000000000..300990418 --- /dev/null +++ b/sept/sept-primary/linker.specs @@ -0,0 +1,7 @@ +%rename link old_link + +*link: +%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections + +*startfile: +crti%O%s crtbegin%O%s diff --git a/sept/sept-primary/src/apb_misc.h b/sept/sept-primary/src/apb_misc.h new file mode 100644 index 000000000..b2e8b1dff --- /dev/null +++ b/sept/sept-primary/src/apb_misc.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_APB_MISC_H +#define FUSEE_APB_MISC_H + +#include <stdint.h> + +#define APB_MISC_BASE 0x70000000 +#define APB_PADCTL_BASE 0x70000810 +#define MAKE_APB_MISC_REG(n) MAKE_REG32(APB_MISC_BASE + n) +#define MAKE_APB_PADCTL_REG(n) MAKE_REG32(APB_PADCTL_BASE + n) + +#define APB_MISC_PP_PINMUX_GLOBAL_0 MAKE_APB_MISC_REG(0x40) +#define APB_MISC_GP_WIFI_EN_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB64) +#define APB_MISC_GP_WIFI_RST_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB68) + +#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20) +#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12) +#define SDMMC1_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVUP_SHIFT) +#define SDMMC1_PAD_CAL_DRVDN_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVDN_SHIFT) + +#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT (8) +#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT (2) +#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT) +#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT) + +#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8) +#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4) +#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8) +#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4) +#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC1_CD_SOURCE (1 << 0) +#define PADCTL_SDMMC1_WP_SOURCE (1 << 1) +#define PADCTL_SDMMC3_CD_SOURCE (1 << 2) +#define PADCTL_SDMMC3_WP_SOURCE (1 << 3) + +typedef struct { + uint32_t asdbgreg; /* 0x810 */ + uint32_t reserved0[0x31]; + uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */ + uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */ + uint32_t emmc2_pad_cfg_control; /* 0x8DC */ + uint32_t emmc4_pad_cfg_control; /* 0x8E0 */ + uint32_t _todo0[0x6E]; + uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */ + uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */ + uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */ + uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */ + uint32_t _todo1[0x03]; + uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */ + uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */ + uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */ + uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */ + uint32_t _todo2[0x2E]; + uint32_t vgpio_gpio_mux_sel; /* 0xB74 */ + uint32_t qspi_sck_lpbk_control; /* 0xB78 */ +} tegra_padctl_t; + +static inline volatile tegra_padctl_t *padctl_get_regs(void) +{ + return (volatile tegra_padctl_t *)APB_PADCTL_BASE; +} + +#endif diff --git a/sept/sept-primary/src/btn.c b/sept/sept-primary/src/btn.c new file mode 100644 index 000000000..87a57c7bd --- /dev/null +++ b/sept/sept-primary/src/btn.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "btn.h" +#include "i2c.h" +#include "gpio.h" +#include "timers.h" + +uint32_t btn_read() +{ + uint32_t res = 0; + + if (!gpio_read(GPIO_BUTTON_VOL_DOWN)) + res |= BTN_VOL_DOWN; + + if (!gpio_read(GPIO_BUTTON_VOL_UP)) + res |= BTN_VOL_UP; + + uint32_t val = 0; + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1)) + { + if (val & 0x4) + res |= BTN_POWER; + } + + return res; +} + +uint32_t btn_wait() +{ + uint32_t res = 0, btn = btn_read(); + int pwr = 0; + + if (btn & BTN_POWER) + { + pwr = 1; + btn &= ~BTN_POWER; + } + + do + { + res = btn_read(); + + if (!(res & BTN_POWER) && pwr) + pwr = 0; + else if (pwr) + res &= ~BTN_POWER; + } while (btn == res); + + return res; +} + +uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask) +{ + uint32_t timeout = get_time_us() + time_ms * 1000; + uint32_t res = btn_read() & mask; + + do + { + if (!(res & mask)) + res = btn_read() & mask; + } while (get_time_us() < timeout); + + return res; +} \ No newline at end of file diff --git a/sept/sept-primary/src/btn.h b/sept/sept-primary/src/btn.h new file mode 100644 index 000000000..04f569b94 --- /dev/null +++ b/sept/sept-primary/src/btn.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_BTN_H_ +#define FUSEE_BTN_H_ + +#define BTN_POWER 0x1 +#define BTN_VOL_DOWN 0x2 +#define BTN_VOL_UP 0x4 + +uint32_t btn_read(); +uint32_t btn_wait(); +uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask); + +#endif \ No newline at end of file diff --git a/sept/sept-primary/src/car.c b/sept/sept-primary/src/car.c new file mode 100644 index 000000000..75c1f6854 --- /dev/null +++ b/sept/sept-primary/src/car.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "car.h" +#include "utils.h" +#include "timers.h" + +static inline uint32_t get_clk_source_reg(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0x178; + case CARDEVICE_UARTB: return 0x17C; + case CARDEVICE_UARTC: return 0x1A0; + case CARDEVICE_I2C1: return 0x124; + case CARDEVICE_I2C5: return 0x128; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0x42C; + case CARDEVICE_HOST1X: return 0x180; + case CARDEVICE_TSEC: return 0x1F4; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 0x410; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_ACTMON: return 0x3E8; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static inline uint32_t get_clk_source_val(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_UARTC: return 0; + case CARDEVICE_I2C1: return 6; + case CARDEVICE_I2C5: return 6; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0; + case CARDEVICE_HOST1X: return 4; + case CARDEVICE_TSEC: return 0; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 0; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_ACTMON: return 6; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static inline uint32_t get_clk_source_div(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_UARTC: return 0; + case CARDEVICE_I2C1: return 0; + case CARDEVICE_I2C5: return 0; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0; + case CARDEVICE_HOST1X: return 3; + case CARDEVICE_TSEC: return 2; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 2; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_ACTMON: return 0; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; +static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; + +void clk_enable(CarDevice dev) { + uint32_t clk_source_reg; + if ((clk_source_reg = get_clk_source_reg(dev))) { + MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev); + } + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void clk_disable(CarDevice dev) { + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void rst_enable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void rst_disable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void clkrst_enable(CarDevice dev) { + clk_enable(dev); + rst_disable(dev); +} + +void clkrst_disable(CarDevice dev) { + rst_enable(dev); + clk_disable(dev); +} + +void clkrst_reboot(CarDevice dev) { + clkrst_disable(dev); + if (dev == CARDEVICE_KFUSE) { + /* Workaround for KFUSE clock. */ + clk_enable(dev); + udelay(100); + rst_disable(dev); + udelay(200); + } else { + clkrst_enable(dev); + } +} + +void clkrst_enable_fuse_regs(bool enable) { + volatile tegra_car_t *car = car_get_regs(); + car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28)); +} diff --git a/sept/sept-primary/src/car.h b/sept/sept-primary/src/car.h new file mode 100644 index 000000000..4135a54ef --- /dev/null +++ b/sept/sept-primary/src/car.h @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_CAR_H +#define FUSEE_CAR_H + +#include <stdint.h> +#include <stdbool.h> + +#define CAR_BASE 0x60006000 +#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) + +#define CLK_L_SDMMC1 (1 << 14) +#define CLK_L_SDMMC2 (1 << 9) +#define CLK_U_SDMMC3 (1 << 5) +#define CLK_L_SDMMC4 (1 << 15) + +#define CLK_SOURCE_MASK (0b111 << 29) +#define CLK_SOURCE_FIRST (0b000 << 29) +#define CLK_DIVIDER_MASK (0xff << 0) +#define CLK_DIVIDER_UNITY (0x00 << 0) + +#define NUM_CAR_BANKS 7 + +/* Clock and reset devices. */ +typedef enum { + CARDEVICE_UARTA = ((0 << 5) | 0x6), + CARDEVICE_UARTB = ((0 << 5) | 0x7), + CARDEVICE_UARTC = ((1 << 5) | 0x17), + CARDEVICE_I2C1 = ((0 << 5) | 0xC), + CARDEVICE_I2C5 = ((1 << 5) | 0xF), + CARDEVICE_UNK = ((3 << 5) | 0x1E), + CARDEVICE_SE = ((3 << 5) | 0x1F), + CARDEVICE_HOST1X = ((0 << 5) | 0x1C), + CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E), + CARDEVICE_SOR0 = ((5 << 5) | 0x16), + CARDEVICE_SOR1 = ((5 << 5) | 0x17), + CARDEVICE_KFUSE = ((1 << 5) | 0x8), + CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B), + CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), + CARDEVICE_ACTMON = ((3 << 5) | 0x17), + CARDEVICE_BPMP = ((0 << 5) | 0x1) +} CarDevice; + +/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */ +typedef struct { + uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */ + + /* _RST_DEVICES_L/H/U_0 0x4-0xc */ + uint32_t rst_dev_l; + uint32_t rst_dev_h; + uint32_t rst_dev_u; + + /* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */ + uint32_t clk_out_enb_l; + uint32_t clk_out_enb_h; + uint32_t clk_out_enb_u; + + uint32_t _0x1C; + uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */ + uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */ + uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */ + uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */ + uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */ + uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */ + uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */ + uint32_t _0x3C; + uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */ + uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */ + uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */ + uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */ + uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */ + uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */ + uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */ + uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */ + uint32_t _0x60[2]; + uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */ + uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */ + uint32_t _0x70[4]; + + /* PLLC 0x80-0x8c */ + uint32_t pllc_base; + uint32_t pllc_out; + uint32_t pllc_misc0; + uint32_t pllc_misc1; + + /* PLLM 0x90-0x9c */ + uint32_t pllm_base; + uint32_t pllm_out; + uint32_t pllm_misc1; + uint32_t pllm_misc2; + + /* PLLP 0xa0-0xac */ + uint32_t pllp_base; + uint32_t pllp_outa; + uint32_t pllp_outb; + uint32_t pllp_misc; + + /* PLLA 0xb0-0xbc */ + uint32_t plla_base; + uint32_t plla_out; + uint32_t plla_misc0; + uint32_t plla_misc1; + + /* PLLU 0xc0-0xcc */ + uint32_t pllu_base; + uint32_t pllu_out; + uint32_t pllu_misc1; + uint32_t pllu_misc2; + + /* PLLD 0xd0-0xdc */ + uint32_t plld_base; + uint32_t plld_out; + uint32_t plld_misc1; + uint32_t plld_misc2; + + /* PLLX 0xe0-0xe4 */ + uint32_t pllx_base; + uint32_t pllx_misc; + + /* PLLE 0xe8-0xf4 */ + uint32_t plle_base; + uint32_t plle_misc; + uint32_t plle_ss_cntl1; + uint32_t plle_ss_cntl2; + + uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */ + uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */ + + uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */ + uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */ + uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */ + uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */ + uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */ + uint32_t _0x114; + uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */ + uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */ + uint32_t _0x120; + uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */ + uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */ + uint32_t _0x12c[2]; + uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */ + uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */ + uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */ + uint32_t _0x140; + uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */ + uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */ + uint32_t _0x14c; + uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */ + uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */ + uint32_t _0x158[3]; + uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */ + uint32_t _0x168[4]; + uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */ + uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */ + uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */ + uint32_t _0x184[5]; + uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */ + uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */ + uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */ + uint32_t _0x1a4; + uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */ + uint32_t _0x1ac[2]; + uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */ + uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */ + uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */ + uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */ + uint32_t _0x1c4[2]; + uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */ + uint32_t _0x1d0; + uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */ + uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */ + uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */ + uint32_t _0x1e0[5]; + uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */ + uint32_t _0x1f8; + + uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */ + uint32_t _0x200[32]; + + uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ + uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ + uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ + + uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */ + uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ + uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ + + uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */ + uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */ + uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */ + + uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */ + uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */ + uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */ + + uint32_t _0x2b0[17]; + uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */ + uint32_t _0x2f8[2]; + + /* _RST_DEV_L/H/U_SET_0 0x300-0x314 */ + uint32_t rst_dev_l_set; + uint32_t rst_dev_l_clr; + uint32_t rst_dev_h_set; + uint32_t rst_dev_h_clr; + uint32_t rst_dev_u_set; + uint32_t rst_dev_u_clr; + + uint32_t _0x318[2]; + + /* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */ + uint32_t clk_enb_l_set; + uint32_t clk_enb_l_clr; + uint32_t clk_enb_h_set; + uint32_t clk_enb_h_clr; + uint32_t clk_enb_u_set; + uint32_t clk_enb_u_clr; + + uint32_t _0x338; + uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */ + uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */ + uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */ + + /* Additional (T30) registers */ + uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */ + uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ + + uint32_t _0x350[2]; + uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */ + uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */ + uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ + uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */ + uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ + uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ + uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ + uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */ + uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ + uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ + uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ + uint32_t _0x38c[5]; + uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */ + uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */ + uint32_t _0x3a8[2]; + + uint32_t _0x3b0; + uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */ + uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */ + uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */ + uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */ + uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */ + uint32_t _0x3c8[2]; + uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */ + uint32_t _0x3d4[4]; + uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */ + uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */ + uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */ + uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */ + uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */ + uint32_t _0x3f8; + uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */ + uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */ + uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */ + uint32_t _0x408[2]; + uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */ + uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */ + uint32_t _0x418[2]; + uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */ + uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */ + uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */ + uint32_t _0x42c; + + /* _RST_DEV_V/W_SET_0 0x430-0x43c */ + uint32_t rst_dev_v_set; + uint32_t rst_dev_v_clr; + uint32_t rst_dev_w_set; + uint32_t rst_dev_w_clr; + + /* _CLK_ENB_V/W_CLR_0 0x440-0x44c */ + uint32_t clk_enb_v_set; + uint32_t clk_enb_v_clr; + uint32_t clk_enb_w_set; + uint32_t clk_enb_w_clr; + + /* Additional (T114+) registers */ + uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */ + uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */ + uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */ + uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */ + uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */ + uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */ + uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */ + uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */ + uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */ + uint32_t _0x474; + uint32_t intstatus; /* _INTSTATUS_0, 0x478 */ + uint32_t intmask; /* _INTMASK_0, 0x47c */ + uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */ + uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */ + uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */ + + uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */ + uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */ + uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */ + uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */ + + uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */ + uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */ + uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */ + uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */ + uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */ + uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */ + uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */ + + uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */ + uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */ + uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */ + uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */ + uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */ + uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */ + uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */ + uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */ + uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */ + uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */ + uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */ + uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */ + uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */ + uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */ + uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */ + uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */ + uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */ + uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */ + uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */ + uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */ + uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */ + uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */ + uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */ + uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */ + uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */ + uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */ + uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */ + uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */ + uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */ + uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */ + uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */ + uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */ + uint32_t _0x538; + uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */ + uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */ + uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */ + uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */ + uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */ + uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */ + uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */ + uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */ + uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */ + uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */ + uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */ + + uint32_t _0x568[2]; + uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */ + uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */ + uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */ + uint32_t _0x57c[5]; + + uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/ + uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */ + uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ + uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */ + uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */ + uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */ + uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */ + uint32_t _0x5ac[6]; + uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */ + uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */ + uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */ + uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */ + uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */ + uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */ + uint32_t _0x5dc[2]; + uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */ + uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */ + uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */ + uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */ + uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */ + uint32_t _0x5f8[2]; + + uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */ + uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */ + uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */ + uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */ + uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */ + uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */ + uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */ + uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */ + uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */ + uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */ + uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */ + uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */ + uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */ + uint32_t _0x634[3]; + uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */ + uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */ + uint32_t _0x648; + uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */ + uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */ + uint32_t _0x654; + uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */ + uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */ + uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */ + uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */ + uint32_t _0x668; + uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */ + uint32_t _0x670[2]; + uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */ + + uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */ + uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */ + uint32_t _0x684[2]; + uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */ + uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */ + + uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */ + uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */ + uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */ + uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */ + + uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */ + uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */ + uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */ + uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */ + uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */ + uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */ + + uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */ + uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */ + uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */ + uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */ + uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */ + uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */ + uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */ + uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */ + + uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */ + uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */ + uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */ + + uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */ + uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */ + uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */ + uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */ + uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */ + uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */ + uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */ + uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */ + uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */ + uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ + + uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ + uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */ + uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ + uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ + uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ + uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */ + uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */ + uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */ + uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */ + uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */ + uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */ + uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */ + uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */ + uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */ +} tegra_car_t; + +static inline volatile tegra_car_t *car_get_regs(void) { + return (volatile tegra_car_t *)CAR_BASE; +} + +void clk_enable(CarDevice dev); +void clk_disable(CarDevice dev); +void rst_enable(CarDevice dev); +void rst_disable(CarDevice dev); + +void clkrst_enable(CarDevice dev); +void clkrst_disable(CarDevice dev); +void clkrst_reboot(CarDevice dev); + +void clkrst_enable_fuse_regs(bool enable); + +#endif diff --git a/sept/sept-primary/src/di.h b/sept/sept-primary/src/di.h new file mode 100644 index 000000000..cf48dcc66 --- /dev/null +++ b/sept/sept-primary/src/di.h @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_DI_H_ +#define FUSEE_DI_H_ + +#include <stdint.h> +#include <stdbool.h> + +#define HOST1X_BASE 0x50000000 +#define DI_BASE 0x54200000 +#define DSI_BASE 0x54300000 +#define VIC_BASE 0x54340000 +#define MIPI_CAL_BASE 0x700E3000 +#define MAKE_HOST1X_REG(n) MAKE_REG32(HOST1X_BASE + n) +#define MAKE_DI_REG(n) MAKE_REG32(DI_BASE + n * 4) +#define MAKE_DSI_REG(n) MAKE_REG32(DSI_BASE + n * 4) +#define MAKE_MIPI_CAL_REG(n) MAKE_REG32(MIPI_CAL_BASE + n) +#define MAKE_VIC_REG(n) MAKE_REG32(VIC_BASE + n) + +/* Display registers. */ +#define DC_CMD_GENERAL_INCR_SYNCPT 0x00 + +#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01 +#define SYNCPT_CNTRL_NO_STALL (1 << 8) +#define SYNCPT_CNTRL_SOFT_RESET (1 << 0) + +#define DC_CMD_CONT_SYNCPT_VSYNC 0x28 +#define SYNCPT_VSYNC_ENABLE (1 << 8) + +#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 + +#define DC_CMD_DISPLAY_COMMAND 0x32 +#define DISP_CTRL_MODE_STOP (0 << 5) +#define DISP_CTRL_MODE_C_DISPLAY (1 << 5) +#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5) +#define DISP_CTRL_MODE_MASK (3 << 5) + +#define DC_CMD_DISPLAY_POWER_CONTROL 0x36 +#define PW0_ENABLE (1 << 0) +#define PW1_ENABLE (1 << 2) +#define PW2_ENABLE (1 << 4) +#define PW3_ENABLE (1 << 6) +#define PW4_ENABLE (1 << 8) +#define PM0_ENABLE (1 << 16) +#define PM1_ENABLE (1 << 18) + +#define DC_CMD_INT_MASK 0x38 +#define DC_CMD_INT_ENABLE 0x39 + +#define DC_CMD_STATE_ACCESS 0x40 +#define READ_MUX (1 << 0) +#define WRITE_MUX (1 << 2) + +#define DC_CMD_STATE_CONTROL 0x41 +#define GENERAL_ACT_REQ (1 << 0) +#define WIN_A_ACT_REQ (1 << 1) +#define WIN_B_ACT_REQ (1 << 2) +#define WIN_C_ACT_REQ (1 << 3) +#define CURSOR_ACT_REQ (1 << 7) +#define GENERAL_UPDATE (1 << 8) +#define WIN_A_UPDATE (1 << 9) +#define WIN_B_UPDATE (1 << 10) +#define WIN_C_UPDATE (1 << 11) +#define CURSOR_UPDATE (1 << 15) +#define NC_HOST_TRIG (1 << 24) + +#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 +#define WINDOW_A_SELECT (1 << 4) +#define WINDOW_B_SELECT (1 << 5) +#define WINDOW_C_SELECT (1 << 6) + +#define DC_CMD_REG_ACT_CONTROL 0x043 + +#define DC_COM_CRC_CONTROL 0x300 +#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) +#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) + +#define DC_COM_DSC_TOP_CTL 0x33E + +#define DC_DISP_DISP_WIN_OPTIONS 0x402 +#define HDMI_ENABLE (1 << 30) +#define DSI_ENABLE (1 << 29) +#define SOR1_TIMING_CYA (1 << 27) +#define SOR1_ENABLE (1 << 26) +#define SOR_ENABLE (1 << 25) +#define CURSOR_ENABLE (1 << 16) + +#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 +#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404 +#define DC_DISP_DISP_TIMING_OPTIONS 0x405 +#define DC_DISP_REF_TO_SYNC 0x406 +#define DC_DISP_SYNC_WIDTH 0x407 +#define DC_DISP_BACK_PORCH 0x408 +#define DC_DISP_ACTIVE 0x409 +#define DC_DISP_FRONT_PORCH 0x40A + +#define DC_DISP_DISP_CLOCK_CONTROL 0x42E +#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8) +#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8) +#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8) +#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8) +#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8) +#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8) +#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8) +#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8) +#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8) +#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8) +#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8) +#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8) +#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8) +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) + +#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F +#define DISP_DATA_FORMAT_DF1P1C (0 << 0) +#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0) +#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0) +#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0) +#define DISP_DATA_FORMAT_DF2S (4 << 0) +#define DISP_DATA_FORMAT_DF3S (5 << 0) +#define DISP_DATA_FORMAT_DFSPI (6 << 0) +#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0) +#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0) +#define DISP_ALIGNMENT_MSB (0 << 8) +#define DISP_ALIGNMENT_LSB (1 << 8) +#define DISP_ORDER_RED_BLUE (0 << 9) +#define DISP_ORDER_BLUE_RED (1 << 9) + +#define DC_DISP_DISP_COLOR_CONTROL 0x430 +#define DITHER_CONTROL_MASK (3 << 8) +#define DITHER_CONTROL_DISABLE (0 << 8) +#define DITHER_CONTROL_ORDERED (2 << 8) +#define DITHER_CONTROL_ERRDIFF (3 << 8) +#define BASE_COLOR_SIZE_MASK (0xf << 0) +#define BASE_COLOR_SIZE_666 (0 << 0) +#define BASE_COLOR_SIZE_111 (1 << 0) +#define BASE_COLOR_SIZE_222 (2 << 0) +#define BASE_COLOR_SIZE_333 (3 << 0) +#define BASE_COLOR_SIZE_444 (4 << 0) +#define BASE_COLOR_SIZE_555 (5 << 0) +#define BASE_COLOR_SIZE_565 (6 << 0) +#define BASE_COLOR_SIZE_332 (7 << 0) +#define BASE_COLOR_SIZE_888 (8 << 0) + +#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 +#define SC1_H_QUALIFIER_NONE (1 << 16) +#define SC0_H_QUALIFIER_NONE (1 << 0) + +#define DC_DISP_DATA_ENABLE_OPTIONS 0x432 +#define DE_SELECT_ACTIVE_BLANK (0 << 0) +#define DE_SELECT_ACTIVE (1 << 0) +#define DE_SELECT_ACTIVE_IS (2 << 0) +#define DE_CONTROL_ONECLK (0 << 2) +#define DE_CONTROL_NORMAL (1 << 2) +#define DE_CONTROL_EARLY_EXT (2 << 2) +#define DE_CONTROL_EARLY (3 << 2) +#define DE_CONTROL_ACTIVE_BLANK (4 << 2) + +#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480 +#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 + +#define DC_WIN_CSC_YOF 0x611 +#define DC_WIN_CSC_KYRGB 0x612 +#define DC_WIN_CSC_KUR 0x613 +#define DC_WIN_CSC_KVR 0x614 +#define DC_WIN_CSC_KUG 0x615 +#define DC_WIN_CSC_KVG 0x616 +#define DC_WIN_CSC_KUB 0x617 +#define DC_WIN_CSC_KVB 0x618 +#define DC_WIN_AD_WIN_OPTIONS 0xB80 +#define DC_WIN_BD_WIN_OPTIONS 0xD80 +#define DC_WIN_CD_WIN_OPTIONS 0xF80 + +/* The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). */ +#define DC_WIN_WIN_OPTIONS 0x700 +#define H_DIRECTION (1 << 0) +#define V_DIRECTION (1 << 2) +#define COLOR_EXPAND (1 << 6) +#define CSC_ENABLE (1 << 18) +#define WIN_ENABLE (1 << 30) + +#define DC_WIN_COLOR_DEPTH 0x703 +#define WIN_COLOR_DEPTH_P1 0x0 +#define WIN_COLOR_DEPTH_P2 0x1 +#define WIN_COLOR_DEPTH_P4 0x2 +#define WIN_COLOR_DEPTH_P8 0x3 +#define WIN_COLOR_DEPTH_B4G4R4A4 0x4 +#define WIN_COLOR_DEPTH_B5G5R5A 0x5 +#define WIN_COLOR_DEPTH_B5G6R5 0x6 +#define WIN_COLOR_DEPTH_AB5G5R5 0x7 +#define WIN_COLOR_DEPTH_B8G8R8A8 0xC +#define WIN_COLOR_DEPTH_R8G8B8A8 0xD +#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE +#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF +#define WIN_COLOR_DEPTH_YCbCr422 0x10 +#define WIN_COLOR_DEPTH_YUV422 0x11 +#define WIN_COLOR_DEPTH_YCbCr420P 0x12 +#define WIN_COLOR_DEPTH_YUV420P 0x13 +#define WIN_COLOR_DEPTH_YCbCr422P 0x14 +#define WIN_COLOR_DEPTH_YUV422P 0x15 +#define WIN_COLOR_DEPTH_YCbCr422R 0x16 +#define WIN_COLOR_DEPTH_YUV422R 0x17 +#define WIN_COLOR_DEPTH_YCbCr422RA 0x18 +#define WIN_COLOR_DEPTH_YUV422RA 0x19 + +#define DC_WIN_BUFFER_CONTROL 0x702 +#define DC_WIN_POSITION 0x704 + +#define DC_WIN_SIZE 0x705 +#define H_SIZE(x) (((x) & 0x1fff) << 0) +#define V_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_PRESCALED_SIZE 0x706 +#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0) +#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_H_INITIAL_DDA 0x707 +#define DC_WIN_V_INITIAL_DDA 0x708 + +#define DC_WIN_DDA_INC 0x709 +#define H_DDA_INC(x) (((x) & 0xffff) << 0) +#define V_DDA_INC(x) (((x) & 0xffff) << 16) + +#define DC_WIN_LINE_STRIDE 0x70A +#define DC_WIN_DV_CONTROL 0x70E + +/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */ +#define DC_WINBUF_START_ADDR 0x800 +#define DC_WINBUF_ADDR_H_OFFSET 0x806 +#define DC_WINBUF_ADDR_V_OFFSET 0x808 +#define DC_WINBUF_SURFACE_KIND 0x80B + +/* Display serial interface registers. */ +#define DSI_RD_DATA 0x9 +#define DSI_WR_DATA 0xA + +#define DSI_POWER_CONTROL 0xB +#define DSI_POWER_CONTROL_ENABLE 1 + +#define DSI_INT_ENABLE 0xC +#define DSI_INT_STATUS 0xD +#define DSI_INT_MASK 0xE + +#define DSI_HOST_CONTROL 0xF +#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21) +#define DSI_HOST_CONTROL_CRC_RESET (1 << 20) +#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) +#define DSI_HOST_CONTROL_RAW (1 << 6) +#define DSI_HOST_CONTROL_HS (1 << 5) +#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4) +#define DSI_HOST_CONTROL_IMM_BTA (1 << 3) +#define DSI_HOST_CONTROL_PKT_BTA (1 << 2) +#define DSI_HOST_CONTROL_CS (1 << 1) +#define DSI_HOST_CONTROL_ECC (1 << 0) + +#define DSI_CONTROL 0x10 +#define DSI_CONTROL_HS_CLK_CTRL (1 << 20) +#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16) +#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12) +#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8) +#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4) +#define DSI_CONTROL_DCS_ENABLE (1 << 3) +#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2) +#define DSI_CONTROL_VIDEO_ENABLE (1 << 1) +#define DSI_CONTROL_HOST_ENABLE (1 << 0) + +#define DSI_SOL_DELAY 0x11 +#define DSI_MAX_THRESHOLD 0x12 + +#define DSI_TRIGGER 0x13 +#define DSI_TRIGGER_HOST (1 << 1) +#define DSI_TRIGGER_VIDEO (1 << 0) + +#define DSI_TX_CRC 0x14 +#define DSI_STATUS 0x15 +#define DSI_INIT_SEQ_CONTROL 0x1A +#define DSI_INIT_SEQ_DATA_0 0x1B +#define DSI_INIT_SEQ_DATA_1 0x1C +#define DSI_INIT_SEQ_DATA_2 0x1D +#define DSI_INIT_SEQ_DATA_3 0x1E +#define DSI_PKT_SEQ_0_LO 0x23 +#define DSI_PKT_SEQ_0_HI 0x24 +#define DSI_PKT_SEQ_1_LO 0x25 +#define DSI_PKT_SEQ_1_HI 0x26 +#define DSI_PKT_SEQ_2_LO 0x27 +#define DSI_PKT_SEQ_2_HI 0x28 +#define DSI_PKT_SEQ_3_LO 0x29 +#define DSI_PKT_SEQ_3_HI 0x2A +#define DSI_PKT_SEQ_4_LO 0x2B +#define DSI_PKT_SEQ_4_HI 0x2C +#define DSI_PKT_SEQ_5_LO 0x2D +#define DSI_PKT_SEQ_5_HI 0x2E +#define DSI_DCS_CMDS 0x33 +#define DSI_PKT_LEN_0_1 0x34 +#define DSI_PKT_LEN_2_3 0x35 +#define DSI_PKT_LEN_4_5 0x36 +#define DSI_PKT_LEN_6_7 0x37 +#define DSI_PHY_TIMING_0 0x3C +#define DSI_PHY_TIMING_1 0x3D +#define DSI_PHY_TIMING_2 0x3E +#define DSI_BTA_TIMING 0x3F + +#define DSI_TIMEOUT_0 0x44 +#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0) + +#define DSI_TIMEOUT_1 0x45 +#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0) + +#define DSI_TO_TALLY 0x46 + +#define DSI_PAD_CONTROL_0 0x4B +#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24) +#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) +#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8) +#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0) + +#define DSI_PAD_CONTROL_CD 0x4c +#define DSI_VIDEO_MODE_CONTROL 0x4E + +#define DSI_PAD_CONTROL_1 0x4F +#define DSI_PAD_CONTROL_2 0x50 + +#define DSI_PAD_CONTROL_3 0x51 +#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12) +#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8) +#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4) +#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0) + +#define DSI_PAD_CONTROL_4 0x52 + +#endif diff --git a/sept/sept-primary/src/fuse.c b/sept/sept-primary/src/fuse.c new file mode 100644 index 000000000..8e80fd402 --- /dev/null +++ b/sept/sept-primary/src/fuse.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#include "car.h" +#include "fuse.h" +#include "timers.h" + +/* Prototypes for internal commands. */ +void fuse_make_regs_visible(void); + +void fuse_enable_power(void); +void fuse_disable_power(void); +void fuse_wait_idle(void); + +/* Initialize the fuse driver */ +void fuse_init(void) { + fuse_make_regs_visible(); +} + +/* Make all fuse registers visible */ +void fuse_make_regs_visible(void) { + clkrst_enable_fuse_regs(true); +} + +/* Enable power to the fuse hardware array */ +void fuse_enable_power(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PWR_GOOD_SW = 1; + udelay(1); +} + +/* Disable power to the fuse hardware array */ +void fuse_disable_power(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PWR_GOOD_SW = 0; + udelay(1); +} + +/* Wait for the fuse driver to go idle */ +void fuse_wait_idle(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + uint32_t ctrl_val = 0; + + /* Wait for STATE_IDLE */ + while ((ctrl_val & (0xF0000)) != 0x40000) + { + udelay(1); + ctrl_val = fuse->FUSE_CTRL; + } +} + +/* Read a fuse from the hardware array */ +uint32_t fuse_hw_read(uint32_t addr) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse_wait_idle(); + + /* Program the target address */ + fuse->FUSE_REG_ADDR = addr; + + /* Enable read operation in control register */ + uint32_t ctrl_val = fuse->FUSE_CTRL; + ctrl_val &= ~0x3; + ctrl_val |= 0x1; /* Set FUSE_READ command */ + fuse->FUSE_CTRL = ctrl_val; + + fuse_wait_idle(); + + return fuse->FUSE_REG_READ; +} + +/* Write a fuse in the hardware array */ +void fuse_hw_write(uint32_t value, uint32_t addr) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse_wait_idle(); + + /* Program the target address and value */ + fuse->FUSE_REG_ADDR = addr; + fuse->FUSE_REG_WRITE = value; + + /* Enable write operation in control register */ + uint32_t ctrl_val = fuse->FUSE_CTRL; + ctrl_val &= ~0x3; + ctrl_val |= 0x2; /* Set FUSE_WRITE command */ + fuse->FUSE_CTRL = ctrl_val; + + fuse_wait_idle(); +} + +/* Sense the fuse hardware array into the shadow cache */ +void fuse_hw_sense(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse_wait_idle(); + + /* Enable sense operation in control register */ + uint32_t ctrl_val = fuse->FUSE_CTRL; + ctrl_val &= ~0x3; + ctrl_val |= 0x3; /* Set FUSE_SENSE command */ + fuse->FUSE_CTRL = ctrl_val; + + fuse_wait_idle(); +} + +/* Disables all fuse programming. */ +void fuse_disable_programming(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_DIS_PGM = 1; +} + +/* Unknown exactly what this does, but it alters the contents read from the fuse cache. */ +void fuse_secondary_private_key_disable(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PRIVATEKEYDISABLE = 0x10; +} + + +/* Read the SKU info register from the shadow cache */ +uint32_t fuse_get_sku_info(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return fuse_chip->FUSE_SKU_INFO; +} + +/* Read the bootrom patch version from a register in the shadow cache */ +uint32_t fuse_get_bootrom_patch_version(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return fuse_chip->FUSE_SOC_SPEEDO_1; +} + +/* Read a spare bit register from the shadow cache */ +uint32_t fuse_get_spare_bit(uint32_t idx) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + if (idx >= 32) { + return 0; + } + + return fuse_chip->FUSE_SPARE_BIT[idx]; +} + +/* Read a reserved ODM register from the shadow cache */ +uint32_t fuse_get_reserved_odm(uint32_t idx) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + if (idx >= 8) { + return 0; + } + + return fuse_chip->FUSE_RESERVED_ODM[idx]; +} + +/* Derive the Device ID using values in the shadow cache */ +uint64_t fuse_get_device_id(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + uint64_t device_id = 0; + uint64_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF; + uint64_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF; + uint64_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F; + uint32_t lot_code = fuse_chip->FUSE_LOT_CODE_0; + uint64_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F; + uint64_t derived_lot_code = 0; + for (unsigned int i = 0; i < 5; i++) { + derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F); + } + derived_lot_code &= 0x03FFFFFF; + + device_id |= y_coord << 0; + device_id |= x_coord << 9; + device_id |= wafer_id << 18; + device_id |= derived_lot_code << 24; + device_id |= fab_code << 50; + return device_id; +} + +/* Get the DRAM ID using values in the shadow cache */ +uint32_t fuse_get_dram_id(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return (fuse_chip->FUSE_RESERVED_ODM[4] >> 3) & 0x7; +} + +/* Derive the Hardware Type using values in the shadow cache */ +uint32_t fuse_get_hardware_type(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + /* This function is very different between 4.x and < 4.x */ + uint32_t hardware_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((fuse_chip->FUSE_RESERVED_ODM[4] >> 2) & 1); + + /* TODO: choose; if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT) { + static const uint32_t types[] = {0,1,4,3}; + + hardware_type |= (fuse_chip->FUSE_RESERVED_ODM[4] >> 14) & 0x3C; + hardware_type--; + return hardware_type > 3 ? 4 : types[hardware_type]; + } else {*/ + if (hardware_type >= 1) { + return hardware_type > 2 ? 3 : hardware_type - 1; + } else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) { + return 0; + } else { + return 3; + } +// } +} + +/* Derive the Retail Type using values in the shadow cache */ +uint32_t fuse_get_retail_type(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + /* Retail type = IS_RETAIL | UNIT_TYPE */ + uint32_t retail_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 4) | (fuse_chip->FUSE_RESERVED_ODM[4] & 3); + if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */ + return 1; + } else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */ + return 0; + } + return 2; /* IS_RETAIL | DEV_UNIT */ +} + +/* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */ +void fuse_get_hardware_info(void *dst) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + uint32_t hw_info[0x4]; + + uint32_t unk_hw_fuse = fuse_chip->_0x120 & 0x3F; + uint32_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF; + uint32_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF; + uint32_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F; + uint32_t lot_code_0 = fuse_chip->FUSE_LOT_CODE_0; + uint32_t lot_code_1 = fuse_chip->FUSE_LOT_CODE_1 & 0x0FFFFFFF; + uint32_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F; + uint32_t vendor_code = fuse_chip->FUSE_VENDOR_CODE & 0xF; + + /* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */ + hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse)); + hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2)); + hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6)); + hw_info[3] = (uint32_t)(vendor_code); + + memcpy(dst, hw_info, 0x10); +} diff --git a/sept/sept-primary/src/fuse.h b/sept/sept-primary/src/fuse.h new file mode 100644 index 000000000..528b0aff4 --- /dev/null +++ b/sept/sept-primary/src/fuse.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_FUSE_H +#define FUSEE_FUSE_H + +#define FUSE_BASE 0x7000F800 +#define FUSE_CHIP_BASE (FUSE_BASE + 0x100) +#define MAKE_FUSE_REG(n) MAKE_REG32(FUSE_BASE + n) +#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n) + +typedef struct { + uint32_t FUSE_CTRL; + uint32_t FUSE_REG_ADDR; + uint32_t FUSE_REG_READ; + uint32_t FUSE_REG_WRITE; + uint32_t FUSE_TIME_RD1; + uint32_t FUSE_TIME_RD2; + uint32_t FUSE_TIME_PGM1; + uint32_t FUSE_TIME_PGM2; + uint32_t FUSE_PRIV2INTFC; + uint32_t FUSE_FUSEBYPASS; + uint32_t FUSE_PRIVATEKEYDISABLE; + uint32_t FUSE_DIS_PGM; + uint32_t FUSE_WRITE_ACCESS; + uint32_t FUSE_PWR_GOOD_SW; + uint32_t _0x38[0x32]; +} tegra_fuse_t; + +typedef struct { + uint32_t FUSE_PRODUCTION_MODE; + uint32_t _0x4; + uint32_t _0x8; + uint32_t _0xC; + uint32_t FUSE_SKU_INFO; + uint32_t FUSE_CPU_SPEEDO_0; + uint32_t FUSE_CPU_IDDQ; + uint32_t _0x1C; + uint32_t _0x20; + uint32_t _0x24; + uint32_t FUSE_FT_REV; + uint32_t FUSE_CPU_SPEEDO_1; + uint32_t FUSE_CPU_SPEEDO_2; + uint32_t FUSE_SOC_SPEEDO_0; + uint32_t FUSE_SOC_SPEEDO_1; + uint32_t FUSE_SOC_SPEEDO_2; + uint32_t FUSE_SOC_IDDQ; + uint32_t _0x44; + uint32_t FUSE_FA; + uint32_t _0x4C; + uint32_t _0x50; + uint32_t _0x54; + uint32_t _0x58; + uint32_t _0x5C; + uint32_t _0x60; + uint32_t FUSE_PUBLIC_KEY[0x8]; + uint32_t FUSE_TSENSOR_1; + uint32_t FUSE_TSENSOR_2; + uint32_t _0x8C; + uint32_t FUSE_CP_REV; + uint32_t _0x94; + uint32_t FUSE_TSENSOR_0; + uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG; + uint32_t FUSE_SECURITY_MODE; + uint32_t FUSE_PRIVATE_KEY[0x4]; + uint32_t FUSE_DEVICE_KEY; + uint32_t _0xB8; + uint32_t _0xBC; + uint32_t FUSE_RESERVED_SW; + uint32_t FUSE_VP8_ENABLE; + uint32_t FUSE_RESERVED_ODM[0x8]; + uint32_t _0xE8; + uint32_t _0xEC; + uint32_t FUSE_SKU_USB_CALIB; + uint32_t FUSE_SKU_DIRECT_CONFIG; + uint32_t _0xF8; + uint32_t _0xFC; + uint32_t FUSE_VENDOR_CODE; + uint32_t FUSE_FAB_CODE; + uint32_t FUSE_LOT_CODE_0; + uint32_t FUSE_LOT_CODE_1; + uint32_t FUSE_WAFER_ID; + uint32_t FUSE_X_COORDINATE; + uint32_t FUSE_Y_COORDINATE; + uint32_t _0x11C; + uint32_t _0x120; + uint32_t FUSE_SATA_CALIB; + uint32_t FUSE_GPU_IDDQ; + uint32_t FUSE_TSENSOR_3; + uint32_t _0x130; + uint32_t _0x134; + uint32_t _0x138; + uint32_t _0x13C; + uint32_t _0x140; + uint32_t _0x144; + uint32_t FUSE_OPT_SUBREVISION; + uint32_t _0x14C; + uint32_t _0x150; + uint32_t FUSE_TSENSOR_4; + uint32_t FUSE_TSENSOR_5; + uint32_t FUSE_TSENSOR_6; + uint32_t FUSE_TSENSOR_7; + uint32_t FUSE_OPT_PRIV_SEC_DIS; + uint32_t FUSE_PKC_DISABLE; + uint32_t _0x16C; + uint32_t _0x170; + uint32_t _0x174; + uint32_t _0x178; + uint32_t _0x17C; + uint32_t FUSE_TSENSOR_COMMON; + uint32_t _0x184; + uint32_t _0x188; + uint32_t _0x18C; + uint32_t _0x190; + uint32_t _0x194; + uint32_t _0x198; + uint32_t FUSE_DEBUG_AUTH_OVERRIDE; + uint32_t _0x1A0; + uint32_t _0x1A4; + uint32_t _0x1A8; + uint32_t _0x1AC; + uint32_t _0x1B0; + uint32_t _0x1B4; + uint32_t _0x1B8; + uint32_t _0x1BC; + uint32_t _0x1D0; + uint32_t FUSE_TSENSOR_8; + uint32_t _0x1D8; + uint32_t _0x1DC; + uint32_t _0x1E0; + uint32_t _0x1E4; + uint32_t _0x1E8; + uint32_t _0x1EC; + uint32_t _0x1F0; + uint32_t _0x1F4; + uint32_t _0x1F8; + uint32_t _0x1FC; + uint32_t _0x200; + uint32_t FUSE_RESERVED_CALIB; + uint32_t _0x208; + uint32_t _0x20C; + uint32_t _0x210; + uint32_t _0x214; + uint32_t _0x218; + uint32_t FUSE_TSENSOR_9; + uint32_t _0x220; + uint32_t _0x224; + uint32_t _0x228; + uint32_t _0x22C; + uint32_t _0x230; + uint32_t _0x234; + uint32_t _0x238; + uint32_t _0x23C; + uint32_t _0x240; + uint32_t _0x244; + uint32_t _0x248; + uint32_t _0x24C; + uint32_t FUSE_USB_CALIB_EXT; + uint32_t _0x254; + uint32_t _0x258; + uint32_t _0x25C; + uint32_t _0x260; + uint32_t _0x264; + uint32_t _0x268; + uint32_t _0x26C; + uint32_t _0x270; + uint32_t _0x274; + uint32_t _0x278; + uint32_t _0x27C; + uint32_t FUSE_SPARE_BIT[0x20]; +} tegra_fuse_chip_t; + +static inline volatile tegra_fuse_t *fuse_get_regs(void) { + return (volatile tegra_fuse_t *)FUSE_BASE; +} + +static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) { + return (volatile tegra_fuse_chip_t *)FUSE_CHIP_BASE; +} + +void fuse_init(void); + +uint32_t fuse_hw_read(uint32_t addr); +void fuse_hw_write(uint32_t value, uint32_t addr); +void fuse_hw_sense(void); +void fuse_disable_programming(void); +void fuse_secondary_private_key_disable(void); + +uint32_t fuse_get_sku_info(void); +uint32_t fuse_get_spare_bit(uint32_t idx); +uint32_t fuse_get_reserved_odm(uint32_t idx); + +uint32_t fuse_get_bootrom_patch_version(void); +uint64_t fuse_get_device_id(void); +uint32_t fuse_get_dram_id(void); +uint32_t fuse_get_hardware_type(void); +uint32_t fuse_get_retail_type(void); +void fuse_get_hardware_info(void *dst); + +#endif diff --git a/sept/sept-primary/src/gpio.c b/sept/sept-primary/src/gpio.c new file mode 100644 index 000000000..9cfec5c2f --- /dev/null +++ b/sept/sept-primary/src/gpio.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stdint.h> +#include <errno.h> + +#include "gpio.h" +#include "utils.h" + +/** + * Returns a GPIO bank object that corresponds to the given GPIO pin, + * which can be created using the TEGRA_GPIO macro or passed from the name macro. + * + * @param pin The GPIO to get the bank for. + * @return The GPIO bank object to use for working with the given bank. + */ +static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin) +{ + volatile tegra_gpio_t *gpio = gpio_get_regs(); + uint32_t bank_number = pin >> GPIO_BANK_SHIFT; + + return &gpio->bank[bank_number]; +} + +/** + * @return the port number for working with the given GPIO. + */ +static volatile uint32_t gpio_get_port(uint32_t pin) +{ + return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK; +} + +/** + * @return a mask to be used to work with the given GPIO + */ +static volatile uint32_t gpio_get_mask(uint32_t pin) +{ + uint32_t pin_number = pin & GPIO_PIN_MASK; + return (1 << pin_number); +} + +/** + * Performs a simple GPIO configuration operation. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param should_be_set True iff the relevant bit should be set; or false if it should be cleared. + * @param offset The offset into a gpio_bank structure + */ +static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset) +{ + // Retrieve the register set that corresponds to the given pin and offset. + uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset; + uint32_t *cluster = (uint32_t *)cluster_addr; + + // Figure out the offset into the cluster, + // and the mask to be used. + uint32_t port = gpio_get_port(pin); + uint32_t mask = gpio_get_mask(pin); + + // Set or clear the bit, as appropriate. + if (should_be_set) + cluster[port] |= mask; + else + cluster[port] &= ~mask; +} + +/** + * Performs a simple GPIO configuration operation. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param should_be_set True iff the relevant bit should be set; or false if it should be cleared. + * @param offset The offset into a gpio_bank structure + */ +static bool gpio_simple_register_get(uint32_t pin, uint32_t offset) +{ + // Retrieve the register set that corresponds to the given pin and offset. + uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset; + uint32_t *cluster = (uint32_t *)cluster_addr; + + // Figure out the offset into the cluster, + // and the mask to be used. + uint32_t port = gpio_get_port(pin); + uint32_t mask = gpio_get_mask(pin); + + // Convert the given value to a boolean. + return !!(cluster[port] & mask); +} + +/** + * Configures a given pin as either GPIO or SFIO. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param mode The relevant mode. + */ +void gpio_configure_mode(uint32_t pin, uint32_t mode) +{ + gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config)); +} + +/** + * Configures a given pin as either INPUT or OUPUT. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param direction The relevant direction. + */ +void gpio_configure_direction(uint32_t pin, uint32_t dir) +{ + gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction)); +} + +/** + * Drives a relevant GPIO pin as either HIGH or LOW. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param mode The relevant mode. + */ +void gpio_write(uint32_t pin, uint32_t value) +{ + gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out)); +} + +/** + * Drives a relevant GPIO pin as either HIGH or LOW. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param mode The relevant mode. + */ +uint32_t gpio_read(uint32_t pin) +{ + return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in)); +} diff --git a/sept/sept-primary/src/gpio.h b/sept/sept-primary/src/gpio.h new file mode 100644 index 000000000..41781a0ca --- /dev/null +++ b/sept/sept-primary/src/gpio.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_GPIO_H +#define FUSEE_GPIO_H + +#include <stdint.h> + +#define GPIO_BASE 0x6000D000 +#define MAKE_GPIO_REG(n) MAKE_REG32(GPIO_BASE + n) + +#define TEGRA_GPIO_PORTS 4 +#define TEGRA_GPIO_BANKS 8 +#define GPIO_BANK_SHIFT 5 +#define GPIO_PORT_SHIFT 3 +#define GPIO_PORT_MASK 0x03 +#define GPIO_PIN_MASK 0x07 + +typedef enum { + TEGRA_GPIO_PORT_A = 0, + TEGRA_GPIO_PORT_B = 1, + TEGRA_GPIO_PORT_C = 2, + TEGRA_GPIO_PORT_D = 3, + TEGRA_GPIO_PORT_E = 4, + TEGRA_GPIO_PORT_F = 5, + TEGRA_GPIO_PORT_G = 6, + TEGRA_GPIO_PORT_H = 7, + TEGRA_GPIO_PORT_I = 8, + TEGRA_GPIO_PORT_J = 9, + TEGRA_GPIO_PORT_K = 10, + TEGRA_GPIO_PORT_L = 11, + TEGRA_GPIO_PORT_M = 12, + TEGRA_GPIO_PORT_N = 13, + TEGRA_GPIO_PORT_O = 14, + TEGRA_GPIO_PORT_P = 15, + TEGRA_GPIO_PORT_Q = 16, + TEGRA_GPIO_PORT_R = 17, + TEGRA_GPIO_PORT_S = 18, + TEGRA_GPIO_PORT_T = 19, + TEGRA_GPIO_PORT_U = 20, + TEGRA_GPIO_PORT_V = 21, + TEGRA_GPIO_PORT_W = 22, + TEGRA_GPIO_PORT_X = 23, + TEGRA_GPIO_PORT_Y = 24, + TEGRA_GPIO_PORT_Z = 25, + TEGRA_GPIO_PORT_AA = 26, + TEGRA_GPIO_PORT_BB = 27, + TEGRA_GPIO_PORT_CC = 28, + TEGRA_GPIO_PORT_DD = 29, + TEGRA_GPIO_PORT_EE = 30, + TEGRA_GPIO_PORT_FF = 31, +} tegra_gpio_port; + +typedef struct { + uint32_t config[TEGRA_GPIO_PORTS]; + uint32_t direction[TEGRA_GPIO_PORTS]; + uint32_t out[TEGRA_GPIO_PORTS]; + uint32_t in[TEGRA_GPIO_PORTS]; + uint32_t int_status[TEGRA_GPIO_PORTS]; + uint32_t int_enable[TEGRA_GPIO_PORTS]; + uint32_t int_level[TEGRA_GPIO_PORTS]; + uint32_t int_clear[TEGRA_GPIO_PORTS]; + uint32_t masked_config[TEGRA_GPIO_PORTS]; + uint32_t masked_dir_out[TEGRA_GPIO_PORTS]; + uint32_t masked_out[TEGRA_GPIO_PORTS]; + uint32_t masked_in[TEGRA_GPIO_PORTS]; + uint32_t masked_int_status[TEGRA_GPIO_PORTS]; + uint32_t masked_int_enable[TEGRA_GPIO_PORTS]; + uint32_t masked_int_level[TEGRA_GPIO_PORTS]; + uint32_t masked_int_clear[TEGRA_GPIO_PORTS]; +} tegra_gpio_bank_t; + +typedef struct { + tegra_gpio_bank_t bank[TEGRA_GPIO_BANKS]; +} tegra_gpio_t; + +static inline volatile tegra_gpio_t *gpio_get_regs(void) +{ + return (volatile tegra_gpio_t *)GPIO_BASE; +} + +#define TEGRA_GPIO(port, offset) \ + ((TEGRA_GPIO_PORT_##port * 8) + offset) + +/* Mode select */ +#define GPIO_MODE_GPIO 0 +#define GPIO_MODE_SFIO 1 + +/* Direction */ +#define GPIO_DIRECTION_INPUT 0 +#define GPIO_DIRECTION_OUTPUT 1 + +/* Level */ +#define GPIO_LEVEL_LOW 0 +#define GPIO_LEVEL_HIGH 1 + +/* Named GPIOs */ +#define GPIO_BUTTON_VOL_DOWN TEGRA_GPIO(X, 7) +#define GPIO_BUTTON_VOL_UP TEGRA_GPIO(X, 6) +#define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1) +#define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4) +#define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4) +#define GPIO_LCD_BL_P5V TEGRA_GPIO(I, 0) +#define GPIO_LCD_BL_N5V TEGRA_GPIO(I, 1) +#define GPIO_LCD_BL_PWM TEGRA_GPIO(V, 0) +#define GPIO_LCD_BL_EN TEGRA_GPIO(V, 1) +#define GPIO_LCD_BL_RST TEGRA_GPIO(V, 2) + +void gpio_configure_mode(uint32_t pin, uint32_t mode); +void gpio_configure_direction(uint32_t pin, uint32_t dir); +void gpio_write(uint32_t pin, uint32_t value); +uint32_t gpio_read(uint32_t pin); + +#endif diff --git a/sept/sept-primary/src/i2c.c b/sept/sept-primary/src/i2c.c new file mode 100644 index 000000000..aec946cf2 --- /dev/null +++ b/sept/sept-primary/src/i2c.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "i2c.h" +#include "utils.h" +#include "timers.h" + +/* Prototypes for internal commands. */ +volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id); +void i2c_load_config(volatile tegra_i2c_t *regs); + +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size); +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size); + +bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size); +bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size); + +/* Initialize I2C based on registers. */ +void i2c_init(unsigned int id) { + volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); + + /* Setup divisor, and clear the bus. */ + regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; + regs->I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; + + /* Load hardware configuration. */ + i2c_load_config(regs); + + /* Wait a while until BUS_CLEAR_DONE is set. */ + for (unsigned int i = 0; i < 10; i++) { + udelay(20000); + if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { + break; + } + } + + /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ + regs->I2C_I2C_BUS_CLEAR_STATUS_0; + + /* Read and set the Interrupt Status. */ + uint32_t int_status = regs->I2C_INTERRUPT_STATUS_REGISTER_0; + regs->I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; +} + +/* Sets a bit in a PMIC register over I2C during CPU shutdown. */ +void i2c_send_pmic_cpu_shutdown_cmd(void) { + uint32_t val = 0; + /* PMIC == Device 4:3C. */ + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); + val |= 4; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); +} + +/* Queries the value of TI charger bit over I2C. */ +bool i2c_query_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); + return (val & 0x80) != 0; +} + +/* Clears TI charger bit over I2C. */ +void i2c_clear_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); + val &= 0x7F; + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); +} + +/* Sets TI charger bit over I2C. */ +void i2c_set_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); + val |= 0x80; + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); +} + +/* Get registers pointer based on I2C ID. */ +volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { + switch (id) { + case I2C_1: + return I2C1_REGS; + case I2C_2: + return I2C2_REGS; + case I2C_3: + return I2C3_REGS; + case I2C_4: + return I2C4_REGS; + case I2C_5: + return I2C5_REGS; + case I2C_6: + return I2C6_REGS; + default: + generic_panic(); + } + return NULL; +} + +/* Load hardware config for I2C4. */ +void i2c_load_config(volatile tegra_i2c_t *regs) { + /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ + regs->I2C_I2C_CONFIG_LOAD_0 = 0x25; + + /* Wait a bit for master config to be loaded. */ + for (unsigned int i = 0; i < 20; i++) { + udelay(1); + if (!(regs->I2C_I2C_CONFIG_LOAD_0 & 1)) { + break; + } + } +} + +/* Reads a register from a device over I2C, writes result to output. */ +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) { + volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); + uint32_t val = r; + + /* Write single byte register ID to device. */ + if (!i2c_write(regs, device, &val, 1)) { + return false; + } + /* Limit output size to 32-bits. */ + if (dst_size > 4) { + return false; + } + + return i2c_read(regs, device, dst, dst_size); +} + +/* Writes a value to a register over I2C. */ +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) { + uint32_t val = r; + if (src_size == 0) { + return true; + } else if (src_size <= 3) { + memcpy(((uint8_t *)&val) + 1, src, src_size); + return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1); + } else { + return false; + } +} + +/* Writes bytes to device over I2C. */ +bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) { + if (src_size > 4) { + return false; + } else if (src_size == 0) { + return true; + } + + /* Set device for 7-bit write mode. */ + regs->I2C_I2C_CMD_ADDR0_0 = device << 1; + + /* Load in data to write. */ + regs->I2C_I2C_CMD_DATA1_0 = read32le(src, 0); + + /* Set config with LENGTH = src_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + regs->I2C_I2C_CNFG_0 = ((src_size << 1) - 2) | 0x2800; + + i2c_load_config(regs); + + /* Config |= SEND; */ + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); + + while (regs->I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ + return (regs->I2C_I2C_STATUS_0 & 0xF) == 0; +} + +/* Reads bytes from device over I2C. */ +bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) { + if (dst_size > 4) { + return false; + } else if (dst_size == 0) { + return true; + } + + /* Set device for 7-bit read mode. */ + regs->I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1; + + /* Set config with LENGTH = dst_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + regs->I2C_I2C_CNFG_0 = ((dst_size << 1) - 2) | 0x2840; + + i2c_load_config(regs); + + /* Config |= SEND; */ + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); + + while (regs->I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Ensure success. */ + if ((regs->I2C_I2C_STATUS_0 & 0xF) != 0) { + return false; + } + + uint32_t val = regs->I2C_I2C_CMD_DATA1_0; + memcpy(dst, &val, dst_size); + return true; +} diff --git a/sept/sept-primary/src/i2c.h b/sept/sept-primary/src/i2c.h new file mode 100644 index 000000000..9399b0024 --- /dev/null +++ b/sept/sept-primary/src/i2c.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_I2C_H +#define FUSEE_I2C_H + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#define I2C1234_BASE 0x7000C000 +#define I2C56_BASE 0x7000D000 + +#define I2C_1 0 +#define I2C_2 1 +#define I2C_3 2 +#define I2C_4 3 +#define I2C_5 4 +#define I2C_6 5 + +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B + +typedef struct { + uint32_t I2C_I2C_CNFG_0; + uint32_t I2C_I2C_CMD_ADDR0_0; + uint32_t I2C_I2C_CMD_ADDR1_0; + uint32_t I2C_I2C_CMD_DATA1_0; + uint32_t I2C_I2C_CMD_DATA2_0; + uint32_t _0x14; + uint32_t _0x18; + uint32_t I2C_I2C_STATUS_0; + uint32_t I2C_I2C_SL_CNFG_0; + uint32_t I2C_I2C_SL_RCVD_0; + uint32_t I2C_I2C_SL_STATUS_0; + uint32_t I2C_I2C_SL_ADDR1_0; + uint32_t I2C_I2C_SL_ADDR2_0; + uint32_t I2C_I2C_TLOW_SEXT_0; + uint32_t _0x38; + uint32_t I2C_I2C_SL_DELAY_COUNT_0; + uint32_t I2C_I2C_SL_INT_MASK_0; + uint32_t I2C_I2C_SL_INT_SOURCE_0; + uint32_t I2C_I2C_SL_INT_SET_0; + uint32_t _0x4C; + uint32_t I2C_I2C_TX_PACKET_FIFO_0; + uint32_t I2C_I2C_RX_FIFO_0; + uint32_t I2C_PACKET_TRANSFER_STATUS_0; + uint32_t I2C_FIFO_CONTROL_0; + uint32_t I2C_FIFO_STATUS_0; + uint32_t I2C_INTERRUPT_MASK_REGISTER_0; + uint32_t I2C_INTERRUPT_STATUS_REGISTER_0; + uint32_t I2C_I2C_CLK_DIVISOR_REGISTER_0; + uint32_t I2C_I2C_INTERRUPT_SOURCE_REGISTER_0; + uint32_t I2C_I2C_INTERRUPT_SET_REGISTER_0; + uint32_t I2C_I2C_SLV_TX_PACKET_FIFO_0; + uint32_t I2C_I2C_SLV_RX_FIFO_0; + uint32_t I2C_I2C_SLV_PACKET_STATUS_0; + uint32_t I2C_I2C_BUS_CLEAR_CONFIG_0; + uint32_t I2C_I2C_BUS_CLEAR_STATUS_0; + uint32_t I2C_I2C_CONFIG_LOAD_0; + uint32_t _0x90; + uint32_t I2C_I2C_INTERFACE_TIMING_0_0; + uint32_t I2C_I2C_INTERFACE_TIMING_1_0; + uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0; + uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; +} tegra_i2c_t; + +#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000)) +#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400)) +#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500)) +#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700)) +#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000)) +#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100)) + +void i2c_init(unsigned int id); +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size); +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size); + +void i2c_send_pmic_cpu_shutdown_cmd(void); +bool i2c_query_ti_charger_bit_7(void); +void i2c_clear_ti_charger_bit_7(void); +void i2c_set_ti_charger_bit_7(void); + +#endif diff --git a/sept/sept-primary/src/main.c b/sept/sept-primary/src/main.c new file mode 100644 index 000000000..6154995f4 --- /dev/null +++ b/sept/sept-primary/src/main.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include "utils.h" +#include "car.h" +#include "timers.h" +#include "di.h" +#include "se.h" +#include "fuse.h" +#include "pmc.h" +#include "mc.h" +#include "sysreg.h" +#include "tsec.h" + +#define I2S_BASE 0x702D1000 +#define MAKE_I2S_REG(n) MAKE_REG32(I2S_BASE + n) + +static void setup_exception_vectors(void) { + for (unsigned int i = 0; i < 0x20; i += 4) { + MAKE_REG32(0x6000F200u + i) = (uint32_t)generic_panic; + } +} + +static void mbist_workaround(void) +{ + volatile tegra_car_t *car = car_get_regs(); + + car->clk_source_sor1 = ((car->clk_source_sor1 | 0x8000) & 0xFFFFBFFF); + car->plld_base |= 0x40800000u; + car->rst_dev_y_clr = 0x40; + car->rst_dev_x_clr = 0x40000; + car->rst_dev_l_clr = 0x18000000; + udelay(3); + + /* Setup I2S. */ + MAKE_I2S_REG(0x0A0) |= 0x400; + MAKE_I2S_REG(0x088) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x1A0) |= 0x400; + MAKE_I2S_REG(0x188) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x2A0) |= 0x400; + MAKE_I2S_REG(0x288) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x3A0) |= 0x400; + MAKE_I2S_REG(0x388) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x4A0) |= 0x400; + MAKE_I2S_REG(0x488) &= 0xFFFFFFFE; + + MAKE_DI_REG(DC_COM_DSC_TOP_CTL) |= 4; + MAKE_VIC_REG(0x8C) = 0xFFFFFFFF; + udelay(3); + + /* Set devices in reset. */ + car->rst_dev_y_set = 0x40; + car->rst_dev_l_set = 0x18000000; + car->rst_dev_x_set = 0x40000; + + /* Clock out enables. */ + car->clk_out_enb_h = 0xC0; + car->clk_out_enb_l = 0x80000130; + car->clk_out_enb_u = 0x1F00200; + car->clk_out_enb_v = 0x80400808; + car->clk_out_enb_w = 0x402000FC; + car->clk_out_enb_x = 0x23000780; + car->clk_out_enb_y = 0x300; + + /* LVL2 clock gate overrides. */ + car->lvl2_clk_gate_ovra = 0; + car->lvl2_clk_gate_ovrb = 0; + car->lvl2_clk_gate_ovrc = 0; + car->lvl2_clk_gate_ovrd = 0; + car->lvl2_clk_gate_ovre = 0; + + /* Configure clock sources. */ + car->plld_base &= 0x1F7FFFFF; + car->clk_source_sor1 &= 0xFFFF3FFF; + car->clk_source_vi = ((car->clk_source_vi & 0x1FFFFFFF) | 0x80000000); + car->clk_source_host1x = ((car->clk_source_host1x & 0x1FFFFFFF) | 0x80000000); + car->clk_source_nvenc = ((car->clk_source_nvenc & 0x1FFFFFFF) | 0x80000000); +} + +static int tsec_dma_wait_idle() +{ + volatile tegra_tsec_t *tsec = tsec_get_regs(); + uint32_t timeout = (get_time_us() + 10000000); + + while (!(tsec->FALCON_DMATRFCMD & 2)) + if (get_time_us() > timeout) + return 0; + + return 1; +} + +static int tsec_dma_phys_to_flcn(bool is_imem, uint32_t flcn_offset, uint32_t phys_offset) +{ + volatile tegra_tsec_t *tsec = tsec_get_regs(); + uint32_t cmd = 0; + + if (!is_imem) + cmd = 0x600; + else + cmd = 0x10; + + tsec->FALCON_DMATRFMOFFS = flcn_offset; + tsec->FALCON_DMATRFFBOFFS = phys_offset; + tsec->FALCON_DMATRFCMD = cmd; + + return tsec_dma_wait_idle(); +} + +int load_tsec_fw(void) { + volatile uint32_t* tsec_fw = (volatile uint32_t*)0x40010F00; + const uint32_t tsec_fw_length = MAKE_REG32(0x40010EFC); + + volatile tegra_tsec_t *tsec = tsec_get_regs(); + + /* Enable clocks. */ + clkrst_reboot(CARDEVICE_HOST1X); + clkrst_reboot(CARDEVICE_TSEC); + clkrst_reboot(CARDEVICE_SOR_SAFE); + clkrst_reboot(CARDEVICE_SOR0); + clkrst_reboot(CARDEVICE_SOR1); + clkrst_reboot(CARDEVICE_KFUSE); + + /* Configure Falcon. */ + tsec->FALCON_DMACTL = 0; + tsec->FALCON_IRQMSET = 0xFFF2; + tsec->FALCON_IRQDEST = 0xFFF0; + tsec->FALCON_ITFEN = 3; + + if (!tsec_dma_wait_idle()) + { + /* Disable clocks. */ + clkrst_disable(CARDEVICE_KFUSE); + clkrst_disable(CARDEVICE_SOR1); + clkrst_disable(CARDEVICE_SOR0); + clkrst_disable(CARDEVICE_SOR_SAFE); + clkrst_disable(CARDEVICE_TSEC); + clkrst_disable(CARDEVICE_HOST1X); + + return -1; + } + + /* Load firmware. */ + tsec->FALCON_DMATRFBASE = (uint32_t)tsec_fw >> 8; + for (uint32_t addr = 0; addr < tsec_fw_length; addr += 0x100) + { + if (!tsec_dma_phys_to_flcn(true, addr, addr)) + { + /* Disable clocks. */ + clkrst_disable(CARDEVICE_KFUSE); + clkrst_disable(CARDEVICE_SOR1); + clkrst_disable(CARDEVICE_SOR0); + clkrst_disable(CARDEVICE_SOR_SAFE); + clkrst_disable(CARDEVICE_TSEC); + clkrst_disable(CARDEVICE_HOST1X); + + return -2; + } + } + + /* Unknown host1x write. */ + MAKE_HOST1X_REG(0x3300) = 0x34C2E1DA; + + + /* Execute firmware. */ + tsec->FALCON_SCRATCH1 = 0; + tsec->FALCON_SCRATCH0 = 1; + tsec->FALCON_BOOTVEC = 0; + tsec->FALCON_CPUCTL = 2; + + while (true) { + /* Yield to Nintendo's TSEC firmware. */ + } +} + + +int main(void) { + /* Setup vectors */ + setup_exception_vectors(); + + volatile tegra_pmc_t *pmc = pmc_get_regs(); + volatile tegra_car_t *car = car_get_regs(); + + /* Clear the boot reason to avoid problems later */ + pmc->scratch200 = 0; + pmc->reset_status = 0; + + //AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; + //pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); + + /* Apply the memory built-in self test workaround. */ + mbist_workaround(); + + /* Reboot SE. */ + clkrst_reboot(CARDEVICE_SE); + + /* Initialize the fuse driver. */ + fuse_init(); + + /* Don't bother checking SKU, fuses, or bootloader version. */ + mc_enable_for_tsec(); + + /* 7.0.0 package1ldr holds I2C5 in reset, clears SYS clock. */ + car->clk_source_sys = 0; + rst_enable(CARDEVICE_I2C5); + + load_tsec_fw(); + + while (true) { } + return 0; +} diff --git a/sept/sept-primary/src/mc.c b/sept/sept-primary/src/mc.c new file mode 100644 index 000000000..6ee9f5b74 --- /dev/null +++ b/sept/sept-primary/src/mc.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "mc.h" +#include "car.h" +#include "timers.h" + +void mc_enable_for_tsec() +{ + volatile tegra_car_t *car = car_get_regs(); + + /* Set EMC clock source. */ + car->clk_source_emc = ((car->clk_source_emc & 0x1FFFFFFF) | 0x40000000); + + /* Enable MIPI CAL clock. */ + car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFDFFFFFF) | 0x2000000); + + /* Enable MC clock. */ + car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFFFFFFFE) | 1); + + /* Enable EMC DLL clock. */ + car->clk_enb_x_set = ((car->clk_enb_x_set & 0xFFFFBFFF) | 0x4000); + + /* Clear EMC and MC reset. */ + /* NOTE: [4.0.0+] This was changed to use the right register. */ + /* car->rst_dev_h_set = 0x2000001; */ + car->rst_dev_h_clr = 0x2000001; + udelay(5); + + /* Enable AHB redirect, weird boundaries for new TSEC firmware. */ + car->lvl2_clk_gate_ovrd = ((car->lvl2_clk_gate_ovrd & 0xFFF7FFFF) | 0x80000); + + MAKE_MC_REG(MC_IRAM_REG_CTRL) &= 0xFFFFFFFE; + MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000; + MAKE_MC_REG(MC_IRAM_TOM) = 0x80000000; +} \ No newline at end of file diff --git a/sept/sept-primary/src/mc.h b/sept/sept-primary/src/mc.h new file mode 100644 index 000000000..bbdafa15c --- /dev/null +++ b/sept/sept-primary/src/mc.h @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_MC_H_ +#define FUSEE_MC_H_ + +#include <stdint.h> +#include <stdbool.h> + +#define MC_BASE 0x70019000 +#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) + +#define MC_INTSTATUS 0x0 +#define MC_INTMASK 0x4 +#define MC_ERR_STATUS 0x8 +#define MC_ERR_ADR 0xc +#define MC_SMMU_CONFIG 0x10 +#define MC_SMMU_TLB_CONFIG 0x14 +#define MC_SMMU_PTC_CONFIG 0x18 +#define MC_SMMU_PTB_ASID 0x1c +#define MC_SMMU_PTB_DATA 0x20 +#define MC_SMMU_TLB_FLUSH 0x30 +#define MC_SMMU_PTC_FLUSH 0x34 +#define MC_SMMU_ASID_SECURITY 0x38 +#define MC_SMMU_AFI_ASID 0x238 +#define MC_SMMU_AVPC_ASID 0x23c +#define MC_SMMU_TSEC_ASID 0x294 +#define MC_SMMU_PPCS1_ASID 0x298 +#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 +#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c +#define MC_SMMU_TRANSLATION_ENABLE_2 0x230 +#define MC_SMMU_TRANSLATION_ENABLE_3 0x234 +#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98 +#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0 +#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4 +#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8 +#define MC_PCFIFO_CLIENT_CONFIG3 0xddc +#define MC_PCFIFO_CLIENT_CONFIG4 0xde0 +#define MC_EMEM_CFG 0x50 +#define MC_EMEM_ADR_CFG 0x54 +#define MC_EMEM_ADR_CFG_DEV0 0x58 +#define MC_EMEM_ADR_CFG_DEV1 0x5c +#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60 +#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64 +#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68 +#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c +#define MC_SECURITY_CFG0 0x70 +#define MC_SECURITY_CFG1 0x74 +#define MC_SECURITY_CFG3 0x9bc +#define MC_SECURITY_RSV 0x7c +#define MC_EMEM_ARB_CFG 0x90 +#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 +#define MC_EMEM_ARB_TIMING_RCD 0x98 +#define MC_EMEM_ARB_TIMING_RP 0x9c +#define MC_EMEM_ARB_TIMING_RC 0xa0 +#define MC_EMEM_ARB_TIMING_RAS 0xa4 +#define MC_EMEM_ARB_TIMING_FAW 0xa8 +#define MC_EMEM_ARB_TIMING_RRD 0xac +#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 +#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 +#define MC_EMEM_ARB_TIMING_R2R 0xb8 +#define MC_EMEM_ARB_TIMING_W2W 0xbc +#define MC_EMEM_ARB_TIMING_R2W 0xc0 +#define MC_EMEM_ARB_TIMING_W2R 0xc4 +#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0 +#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4 +#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0 +#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4 +#define MC_EMEM_ARB_DA_TURNS 0xd0 +#define MC_EMEM_ARB_DA_COVERS 0xd4 +#define MC_EMEM_ARB_MISC0 0xd8 +#define MC_EMEM_ARB_MISC1 0xdc +#define MC_EMEM_ARB_MISC2 0xc8 +#define MC_EMEM_ARB_RING1_THROTTLE 0xe0 +#define MC_EMEM_ARB_RING3_THROTTLE 0xe4 +#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0 +#define MC_EMEM_ARB_OVERRIDE 0xe8 +#define MC_EMEM_ARB_RSV 0xec +#define MC_CLKEN_OVERRIDE 0xf4 +#define MC_TIMING_CONTROL_DBG 0xf8 +#define MC_TIMING_CONTROL 0xfc +#define MC_STAT_CONTROL 0x100 +#define MC_STAT_STATUS 0x104 +#define MC_STAT_EMC_CLOCK_LIMIT 0x108 +#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c +#define MC_STAT_EMC_CLOCKS 0x110 +#define MC_STAT_EMC_CLOCKS_MSBS 0x114 +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118 +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158 +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20 +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24 +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198 +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8 +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28 +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c +#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0 +#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0 +#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120 +#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c +#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c +#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c +#define MC_STAT_EMC_SET0_COUNT 0x138 +#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c +#define MC_STAT_EMC_SET1_COUNT 0x178 +#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c +#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140 +#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144 +#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180 +#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184 +#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148 +#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c +#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188 +#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c +#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150 +#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190 +#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8 +#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc +#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8 +#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc +#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0 +#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0 +#define MC_CLIENT_HOTRESET_CTRL 0x200 +#define MC_CLIENT_HOTRESET_CTRL_1 0x970 +#define MC_CLIENT_HOTRESET_STATUS 0x204 +#define MC_CLIENT_HOTRESET_STATUS_1 0x974 +#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208 +#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c +#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210 +#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214 +#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94 +#define MC_EMEM_ARB_HYSTERESIS_0 0x218 +#define MC_EMEM_ARB_HYSTERESIS_1 0x21c +#define MC_EMEM_ARB_HYSTERESIS_2 0x220 +#define MC_EMEM_ARB_HYSTERESIS_3 0x224 +#define MC_EMEM_ARB_HYSTERESIS_4 0xb84 +#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0 +#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4 +#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8 +#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc +#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0 +#define MC_EMEM_ARB_DHYST_CTRL 0xbcc +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec +#define MC_RESERVED_RSV 0x3fc +#define MC_DISB_EXTRA_SNAP_LEVELS 0x408 +#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4 +#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0 +#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18 +#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08 +#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10 +#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c +#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40 +#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414 +#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc +#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c +#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14 +#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0 +#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac +#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c +#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48 +#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8 +#define MC_USBX_EXTRA_SNAP_LEVELS 0x404 +#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8 +#define MC_SD_EXTRA_SNAP_LEVELS 0xa04 +#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c +#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8 +#define MC_GK_EXTRA_SNAP_LEVELS 0xa00 +#define MC_VE2_EXTRA_SNAP_LEVELS 0x410 +#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44 +#define MC_VIDEO_PROTECT_BOM 0x648 +#define MC_VIDEO_PROTECT_SIZE_MB 0x64c +#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978 +#define MC_VIDEO_PROTECT_REG_CTRL 0x650 +#define MC_ERR_VPR_STATUS 0x654 +#define MC_ERR_VPR_ADR 0x658 +#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418 +#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590 +#define MC_IRAM_BOM 0x65c +#define MC_IRAM_TOM 0x660 +#define MC_IRAM_ADR_HI 0x980 +#define MC_IRAM_REG_CTRL 0x964 +#define MC_EMEM_CFG_ACCESS_CTRL 0x664 +#define MC_TZ_SECURITY_CTRL 0x668 +#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c +#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4 +#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc +#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8 +#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80 +#define MC_SEC_CARVEOUT_BOM 0x670 +#define MC_SEC_CARVEOUT_SIZE_MB 0x674 +#define MC_SEC_CARVEOUT_ADR_HI 0x9d4 +#define MC_SEC_CARVEOUT_REG_CTRL 0x678 +#define MC_ERR_SEC_STATUS 0x67c +#define MC_ERR_SEC_ADR 0x680 +#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684 +#define MC_STUTTER_CONTROL 0x688 +#define MC_RESERVED_RSV_1 0x958 +#define MC_DVFS_PIPE_SELECT 0x95c +#define MC_AHB_PTSA_MIN 0x4e0 +#define MC_AUD_PTSA_MIN 0x54c +#define MC_MLL_MPCORER_PTSA_RATE 0x44c +#define MC_RING2_PTSA_RATE 0x440 +#define MC_USBD_PTSA_RATE 0x530 +#define MC_USBX_PTSA_MIN 0x528 +#define MC_USBD_PTSA_MIN 0x534 +#define MC_APB_PTSA_MAX 0x4f0 +#define MC_JPG_PTSA_RATE 0x584 +#define MC_DIS_PTSA_MIN 0x420 +#define MC_AVP_PTSA_MAX 0x4fc +#define MC_AVP_PTSA_RATE 0x4f4 +#define MC_RING1_PTSA_MIN 0x480 +#define MC_DIS_PTSA_MAX 0x424 +#define MC_SD_PTSA_MAX 0x4d8 +#define MC_MSE_PTSA_RATE 0x4c4 +#define MC_VICPC_PTSA_MIN 0x558 +#define MC_PCX_PTSA_MAX 0x4b4 +#define MC_ISP_PTSA_RATE 0x4a0 +#define MC_A9AVPPC_PTSA_MIN 0x48c +#define MC_RING2_PTSA_MAX 0x448 +#define MC_AUD_PTSA_RATE 0x548 +#define MC_HOST_PTSA_MIN 0x51c +#define MC_MLL_MPCORER_PTSA_MAX 0x454 +#define MC_SD_PTSA_MIN 0x4d4 +#define MC_RING1_PTSA_RATE 0x47c +#define MC_JPG_PTSA_MIN 0x588 +#define MC_HDAPC_PTSA_MIN 0x62c +#define MC_AVP_PTSA_MIN 0x4f8 +#define MC_JPG_PTSA_MAX 0x58c +#define MC_VE_PTSA_MAX 0x43c +#define MC_DFD_PTSA_MAX 0x63c +#define MC_VICPC_PTSA_RATE 0x554 +#define MC_GK_PTSA_MAX 0x544 +#define MC_VICPC_PTSA_MAX 0x55c +#define MC_SDM_PTSA_MAX 0x624 +#define MC_SAX_PTSA_RATE 0x4b8 +#define MC_PCX_PTSA_MIN 0x4b0 +#define MC_APB_PTSA_MIN 0x4ec +#define MC_GK2_PTSA_MIN 0x614 +#define MC_PCX_PTSA_RATE 0x4ac +#define MC_RING1_PTSA_MAX 0x484 +#define MC_HDAPC_PTSA_RATE 0x628 +#define MC_MLL_MPCORER_PTSA_MIN 0x450 +#define MC_GK2_PTSA_MAX 0x618 +#define MC_AUD_PTSA_MAX 0x550 +#define MC_GK2_PTSA_RATE 0x610 +#define MC_ISP_PTSA_MAX 0x4a8 +#define MC_DISB_PTSA_RATE 0x428 +#define MC_VE2_PTSA_MAX 0x49c +#define MC_DFD_PTSA_MIN 0x638 +#define MC_FTOP_PTSA_RATE 0x50c +#define MC_A9AVPPC_PTSA_RATE 0x488 +#define MC_VE2_PTSA_MIN 0x498 +#define MC_USBX_PTSA_MAX 0x52c +#define MC_DIS_PTSA_RATE 0x41c +#define MC_USBD_PTSA_MAX 0x538 +#define MC_A9AVPPC_PTSA_MAX 0x490 +#define MC_USBX_PTSA_RATE 0x524 +#define MC_FTOP_PTSA_MAX 0x514 +#define MC_HDAPC_PTSA_MAX 0x630 +#define MC_SD_PTSA_RATE 0x4d0 +#define MC_DFD_PTSA_RATE 0x634 +#define MC_FTOP_PTSA_MIN 0x510 +#define MC_SDM_PTSA_RATE 0x61c +#define MC_AHB_PTSA_RATE 0x4dc +#define MC_SMMU_SMMU_PTSA_MAX 0x460 +#define MC_RING2_PTSA_MIN 0x444 +#define MC_SDM_PTSA_MIN 0x620 +#define MC_APB_PTSA_RATE 0x4e8 +#define MC_MSE_PTSA_MIN 0x4c8 +#define MC_HOST_PTSA_RATE 0x518 +#define MC_VE_PTSA_RATE 0x434 +#define MC_AHB_PTSA_MAX 0x4e4 +#define MC_SAX_PTSA_MIN 0x4bc +#define MC_SMMU_SMMU_PTSA_MIN 0x45c +#define MC_ISP_PTSA_MIN 0x4a4 +#define MC_HOST_PTSA_MAX 0x520 +#define MC_SAX_PTSA_MAX 0x4c0 +#define MC_VE_PTSA_MIN 0x438 +#define MC_GK_PTSA_MIN 0x540 +#define MC_MSE_PTSA_MAX 0x4cc +#define MC_DISB_PTSA_MAX 0x430 +#define MC_DISB_PTSA_MIN 0x42c +#define MC_SMMU_SMMU_PTSA_RATE 0x458 +#define MC_VE2_PTSA_RATE 0x494 +#define MC_GK_PTSA_RATE 0x53c +#define MC_PTSA_GRANT_DECREMENT 0x960 +#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4 +#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0 +#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380 +#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384 +#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc +#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8 +#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370 +#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0 +#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374 +#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8 +#define MC_LATENCY_ALLOWANCE_VIC_0 0x394 +#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8 +#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8 +#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc +#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390 +#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694 +#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348 +#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c +#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344 +#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0 +#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698 +#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec +#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0 +#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4 +#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8 +#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4 +#define MC_LATENCY_ALLOWANCE_HC_1 0x314 +#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0 +#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4 +#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c +#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec +#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320 +#define MC_LATENCY_ALLOWANCE_VI2_0 0x398 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4 +#define MC_LATENCY_ALLOWANCE_SATA_0 0x350 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690 +#define MC_LATENCY_ALLOWANCE_HC_0 0x310 +#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8 +#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac +#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4 +#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388 +#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328 +#define MC_LATENCY_ALLOWANCE_HDA_0 0x318 +#define MC_MIN_LENGTH_APE_0 0xb34 +#define MC_MIN_LENGTH_DCB_2 0x8a8 +#define MC_MIN_LENGTH_A9AVP_0 0x950 +#define MC_MIN_LENGTH_TSEC_0 0x93c +#define MC_MIN_LENGTH_DC_1 0x898 +#define MC_MIN_LENGTH_AXIAP_0 0x94c +#define MC_MIN_LENGTH_ISP2B_0 0x930 +#define MC_MIN_LENGTH_VI2_0 0x944 +#define MC_MIN_LENGTH_DCB_0 0x8a0 +#define MC_MIN_LENGTH_DCB_1 0x8a4 +#define MC_MIN_LENGTH_PPCS_1 0x8f4 +#define MC_MIN_LENGTH_NVJPG_0 0xb3c +#define MC_MIN_LENGTH_HDA_0 0x8c4 +#define MC_MIN_LENGTH_NVENC_0 0x8d4 +#define MC_MIN_LENGTH_SDMMC_0 0xb18 +#define MC_MIN_LENGTH_ISP2B_1 0x934 +#define MC_MIN_LENGTH_HC_1 0x8c0 +#define MC_MIN_LENGTH_DC_3 0xb20 +#define MC_MIN_LENGTH_AVPC_0 0x890 +#define MC_MIN_LENGTH_VIC_0 0x940 +#define MC_MIN_LENGTH_ISP2_0 0x91c +#define MC_MIN_LENGTH_HC_0 0x8bc +#define MC_MIN_LENGTH_SE_0 0xb38 +#define MC_MIN_LENGTH_NVDEC_0 0xb30 +#define MC_MIN_LENGTH_SATA_0 0x8fc +#define MC_MIN_LENGTH_DC_0 0x894 +#define MC_MIN_LENGTH_XUSB_1 0x92c +#define MC_MIN_LENGTH_DC_2 0x89c +#define MC_MIN_LENGTH_SDMMCAA_0 0xb14 +#define MC_MIN_LENGTH_GPU_0 0xb04 +#define MC_MIN_LENGTH_ETR_0 0xb44 +#define MC_MIN_LENGTH_AFI_0 0x88c +#define MC_MIN_LENGTH_PPCS_0 0x8f0 +#define MC_MIN_LENGTH_ISP2_1 0x920 +#define MC_MIN_LENGTH_XUSB_0 0x928 +#define MC_MIN_LENGTH_MPCORE_0 0x8cc +#define MC_MIN_LENGTH_TSECB_0 0xb48 +#define MC_MIN_LENGTH_SDMMCA_0 0xb10 +#define MC_MIN_LENGTH_GPU2_0 0xb40 +#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c +#define MC_MIN_LENGTH_PTC_0 0x8f8 +#define MC_EMEM_ARB_OVERRIDE_1 0x968 +#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984 +#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988 +#define MC_EMEM_ARB_STATS_0 0x990 +#define MC_EMEM_ARB_STATS_1 0x994 +#define MC_MTS_CARVEOUT_BOM 0x9a0 +#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4 +#define MC_MTS_CARVEOUT_ADR_HI 0x9a8 +#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac +#define MC_ERR_MTS_STATUS 0x9b0 +#define MC_ERR_MTS_ADR 0x9b4 +#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 +#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74 +#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10 +#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c +#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4 +#define MC_SECURITY_CARVEOUT2_CFG0 0xc58 +#define MC_SECURITY_CARVEOUT1_CFG0 0xc08 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84 +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68 +#define MC_SECURITY_CARVEOUT3_BOM 0xcac +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60 +#define MC_SECURITY_CARVEOUT3_CFG0 0xca8 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88 +#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64 +#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50 +#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14 +#define MC_SECURITY_CARVEOUT1_BOM 0xc0c +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4 +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c +#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8 +#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60 +#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80 +#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc +#define MC_SECURITY_CARVEOUT4_BOM 0xcfc +#define MC_SECURITY_CARVEOUT5_CFG0 0xd48 +#define MC_SECURITY_CARVEOUT2_BOM 0xc5c +#define MC_SECURITY_CARVEOUT5_BOM 0xd4c +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0 +#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08 +#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 +#define MC_DA_CONFIG0 0x9dc + +/* Memory Controller clients */ +#define CLIENT_ACCESS_NUM_CLIENTS 32 +typedef enum { + /* _ACCESS0 */ + CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + + /* _ACCESS1 */ + CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + + /* _ACCESS2 */ + CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + + /* _ACCESS3 */ + CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + + /* _ACCESS4 */ + CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4)) +} McClient; + +void mc_enable_for_tsec(); + +#endif \ No newline at end of file diff --git a/sept/sept-primary/src/panic.c b/sept/sept-primary/src/panic.c new file mode 100644 index 000000000..910e785f5 --- /dev/null +++ b/sept/sept-primary/src/panic.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "panic.h" +#include "di.h" +#include "pmc.h" +#include "fuse.h" +#include "utils.h" + +static uint32_t g_panic_code = 0; + +void check_panic(void) { + /* We also handle our own panics. */ + /* In the case of our own panics, we assume that the display has already been initialized. */ + bool has_panic = APBDEV_PMC_RST_STATUS_0 != 0 || g_panic_code != 0; + uint32_t code = g_panic_code == 0 ? APBDEV_PMC_SCRATCH200_0 : g_panic_code; + + has_panic = has_panic && !(APBDEV_PMC_RST_STATUS_0 != 1 && code == PANIC_CODE_SAFEMODE); + + if (has_panic) { + uint32_t color; + + /* Check for predefined codes: */ + switch (code & MASK(20)) { + case 0x01: /* Package2 signature verification failed. */ + case 0x02: /* Package2 meta verification failed. */ + case 0x03: /* Package2 version check failed. */ + case 0x04: /* Package2 payload verification failed. */ + color = PANIC_COLOR_KERNEL; + break; + case 0x05: /* Unknown SMC. */ + case 0x06: /* Unknown Abort. */ + color = PANIC_COLOR_SECMON_GENERIC; + break; + case 0x07: /* Invalid CPU context. */ + case 0x08: /* Invalid SE state. */ + case 0x09: /* CPU is already awake (2.0.0+). */ + color = PANIC_COLOR_SECMON_DEEPSLEEP; + break; + case 0x10: /* Unknown exception. */ + color = PANIC_COLOR_SECMON_EXCEPTION; + break; + case 0x30: /* General bootloader error. */ + case 0x31: /* Invalid DRAM ID. */ + case 0x32: /* Invalid size. */ + case 0x33: /* Invalid arguement. */ + case 0x34: /* Bad GPT. */ + case 0x35: /* Failed to boot SafeMode. */ + case 0x36: /* Activity monitor fired (4.0.0+). */ + color = PANIC_COLOR_BOOTLOADER_GENERIC; + break; + case 0x40: /* Kernel panic. */ + color = PANIC_COLOR_KERNEL; + break; + default: + color = code >> 20; + color |= color << 4; + break; + } + + wait_for_button_and_reboot(); + } else { + g_panic_code = 0; + APBDEV_PMC_SCRATCH200_0 = 0; + } +} + +__attribute__ ((noreturn)) void panic(uint32_t code) { + /* Set panic code. */ + if (g_panic_code == 0) { + g_panic_code = code; + APBDEV_PMC_SCRATCH200_0 = code; + } + + fuse_disable_programming(); + APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */ + + check_panic(); + while(true); +} diff --git a/sept/sept-primary/src/panic.h b/sept/sept-primary/src/panic.h new file mode 100644 index 000000000..78ea67fb6 --- /dev/null +++ b/sept/sept-primary/src/panic.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_PANIC_H +#define FUSEE_PANIC_H + +#include <stdint.h> + +#define PANIC_COLOR_KERNEL 0x0000FF +#define PANIC_COLOR_SECMON_EXCEPTION 0xFF7700 +#define PANIC_COLOR_SECMON_GENERIC 0x00FFFF +#define PANIC_COLOR_SECMON_DEEPSLEEP 0xFF77FF /* 4.0+ color */ +#define PANIC_COLOR_BOOTLOADER_GENERIC 0xAA00FF +#define PANIC_COLOR_BOOTLOADER_SAFEMODE 0xFFFFAA /* Removed */ + +#define PANIC_CODE_SAFEMODE 0x00000020 + +void check_and_display_panic(void); +__attribute__ ((noreturn)) void panic(uint32_t code); + +#endif diff --git a/sept/sept-primary/src/pmc.h b/sept/sept-primary/src/pmc.h new file mode 100644 index 000000000..80c36da7f --- /dev/null +++ b/sept/sept-primary/src/pmc.h @@ -0,0 +1,626 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_PMC_H +#define FUSEE_PMC_H + +#include <stdint.h> + +#define PMC_BASE 0x7000E400 +#define MAKE_PMC_REG(n) MAKE_REG32(PMC_BASE + n) + +#define PMC_CONTROL_SDMMC1 (1 << 12) +#define PMC_CONTROL_SDMMC3 (1 << 13) +#define PMC_CONTROL_SDMMC4 (1 << 14) + +#define APBDEV_PMC_CONTROL MAKE_PMC_REG(0x00) +#define APBDEV_PM_0 MAKE_PMC_REG(0x14) +#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x24) +#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x30) +#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x38) +#define APBDEV_PMC_NO_IOPOWER_0 MAKE_PMC_REG(0x44) +#define APBDEV_PMC_SCRATCH0_0 MAKE_PMC_REG(0x50) +#define APBDEV_PMC_SCRATCH1_0 MAKE_PMC_REG(0x54) +#define APBDEV_PMC_SCRATCH20_0 MAKE_PMC_REG(0xA0) +#define APBDEV_PMC_PWR_DET_VAL_0 MAKE_PMC_REG(0xE4) +#define APBDEV_PMC_DDR_PWR_0 MAKE_PMC_REG(0xE8) +#define APBDEV_PMC_CRYPTO_OP_0 MAKE_PMC_REG(0xF4) +#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_PMC_REG(0x168) +#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4) +#define APBDEV_PMC_RST_STATUS_0 MAKE_PMC_REG(0x1B4) +#define APBDEV_PMC_IO_DPD_REQ_0 MAKE_PMC_REG(0x1B8) +#define APBDEV_PMC_IO_DPD2_REQ_0 MAKE_PMC_REG(0x1C0) +#define APBDEV_PMC_VDDP_SEL_0 MAKE_PMC_REG(0x1CC) +#define APBDEV_PMC_SCRATCH49_0 MAKE_PMC_REG(0x244) +#define APBDEV_PMC_TSC_MULT_0 MAKE_PMC_REG(0x2B4) +#define APBDEV_PMC_REG_SHORT_0 MAKE_PMC_REG(0x2CC) +#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) +#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334) +#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360) +#define APBDEV_PMC_SECURE_SCRATCH49_0 MAKE_PMC_REG(0x3A4) +#define APBDEV_PMC_CNTRL2_0 MAKE_PMC_REG(0x440) +#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464) +#define APBDEV_PMC_UTMIP_PAD_CFG1_0 MAKE_PMC_REG(0x4C4) +#define APBDEV_PMC_UTMIP_PAD_CFG3_0 MAKE_PMC_REG(0x4CC) +#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4) +#define APBDEV_PMC_SCRATCH43_0 MAKE_PMC_REG(0x22C) +#define APBDEV_PMC_SCRATCH188_0 MAKE_PMC_REG(0x810) +#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) +#define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840) + +#define APBDEV_PMC_SCRATCH45_0 MAKE_PMC_REG(0x234) +#define APBDEV_PMC_SCRATCH46_0 MAKE_PMC_REG(0x238) +#define APBDEV_PMC_SCRATCH33_0 MAKE_PMC_REG(0x120) +#define APBDEV_PMC_SCRATCH40_0 MAKE_PMC_REG(0x13C) + +typedef struct { + uint32_t cntrl; + uint32_t sec_disable; + uint32_t pmc_swrst; + uint32_t wake_mask; + uint32_t wake_lvl; + uint32_t wake_status; + uint32_t sw_wake_status; + uint32_t dpd_pads_oride; + uint32_t dpd_sample; + uint32_t dpd_enable; + uint32_t pwrgate_timer_off; + uint32_t clamp_status; + uint32_t pwrgate_toggle; + uint32_t remove_clamping; + uint32_t pwrgate_status; + uint32_t pwrgood_timer; + uint32_t blink_timer; + uint32_t no_iopower; + uint32_t pwr_det; + uint32_t pwr_det_latch; + uint32_t scratch0; + uint32_t scratch1; + uint32_t scratch2; + uint32_t scratch3; + uint32_t scratch4; + uint32_t scratch5; + uint32_t scratch6; + uint32_t scratch7; + uint32_t scratch8; + uint32_t scratch9; + uint32_t scratch10; + uint32_t scratch11; + uint32_t scratch12; + uint32_t scratch13; + uint32_t scratch14; + uint32_t scratch15; + uint32_t scratch16; + uint32_t scratch17; + uint32_t scratch18; + uint32_t scratch19; + uint32_t scratch20; + uint32_t scratch21; + uint32_t scratch22; + uint32_t scratch23; + uint32_t secure_scratch0; + uint32_t secure_scratch1; + uint32_t secure_scratch2; + uint32_t secure_scratch3; + uint32_t secure_scratch4; + uint32_t secure_scratch5; + uint32_t cpupwrgood_timer; + uint32_t cpupwroff_timer; + uint32_t pg_mask; + uint32_t pg_mask_1; + uint32_t auto_wake_lvl; + uint32_t auto_wake_lvl_mask; + uint32_t wake_delay; + uint32_t pwr_det_val; + uint32_t ddr_pwr; + uint32_t usb_debounce_del; + uint32_t usb_ao; + uint32_t crypto_op; + uint32_t pllp_wb0_override; + uint32_t scratch24; + uint32_t scratch25; + uint32_t scratch26; + uint32_t scratch27; + uint32_t scratch28; + uint32_t scratch29; + uint32_t scratch30; + uint32_t scratch31; + uint32_t scratch32; + uint32_t scratch33; + uint32_t scratch34; + uint32_t scratch35; + uint32_t scratch36; + uint32_t scratch37; + uint32_t scratch38; + uint32_t scratch39; + uint32_t scratch40; + uint32_t scratch41; + uint32_t scratch42; + uint32_t bo_mirror0; + uint32_t bo_mirror1; + uint32_t bo_mirror2; + uint32_t sys_33v_en; + uint32_t bo_mirror_access; + uint32_t gate; + uint32_t wake2_mask; + uint32_t wake2_lvl; + uint32_t wake2_stat; + uint32_t sw_wake2_stat; + uint32_t auto_wake2_lvl_mask; + uint32_t pg_mask2; + uint32_t pg_mask_ce1; + uint32_t pg_mask_ce2; + uint32_t pg_mask_ce3; + uint32_t pwrgate_timer_ce0; + uint32_t pwrgate_timer_ce1; + uint32_t pwrgate_timer_ce2; + uint32_t pwrgate_timer_ce3; + uint32_t pwrgate_timer_ce4; + uint32_t pwrgate_timer_ce5; + uint32_t pwrgate_timer_ce6; + uint32_t pcx_edpd_cntrl; + uint32_t osc_edpd_over; + uint32_t clk_out_cntrl; + uint32_t sata_pwrgate; + uint32_t sensor_ctrl; + uint32_t reset_status; + uint32_t io_dpd_req; + uint32_t io_dpd_stat; + uint32_t io_dpd2_req; + uint32_t io_dpd2_stat; + uint32_t sel_dpd_tim; + uint32_t vddp_sel; + uint32_t ddr_cfg; + uint32_t e_no_vttgen; + uint32_t _reserved0; + uint32_t pllm_wb0_ovrride_frq; + uint32_t test_pwrgate; + uint32_t pwrgate_timer_mult; + uint32_t dsi_sel_dpd; + uint32_t utmip_uhsic_triggers; + uint32_t utmip_uhsic_saved_st; + uint32_t utmip_pad_cfg; + uint32_t utmip_term_pad_cfg; + uint32_t utmip_uhsic_sleep_cfg; + uint32_t utmip_uhsic_sleepwalk_cfg; + uint32_t utmip_sleepwalk_p[3]; + uint32_t uhsic_sleepwalk_p0; + uint32_t utmip_uhsic_status; + uint32_t utmip_uhsic_fake; + uint32_t bo_mirror3[2]; + uint32_t secure_scratch6; + uint32_t secure_scratch7; + uint32_t scratch43; + uint32_t scratch44; + uint32_t scratch45; + uint32_t scratch46; + uint32_t scratch47; + uint32_t scratch48; + uint32_t scratch49; + uint32_t scratch50; + uint32_t scratch51; + uint32_t scratch52; + uint32_t scratch53; + uint32_t scratch54; + uint32_t scratch55; + uint32_t scratch0_eco; + uint32_t por_dpd_ctrl; + uint32_t scratch2_eco; + uint32_t utmip_uhsic_line_wakeup; + uint32_t utmip_bias_master_cntrl; + uint32_t utmip_master_config; + uint32_t td_pwrgate_inter_part_timer; + uint32_t utmip_uhsic2_triggers; + uint32_t utmip_uhsic2_saved_state; + uint32_t utmip_uhsic2_sleep_cfg; + uint32_t utmip_uhsic2_sleepwalk_cfg; + uint32_t uhsic2_sleepwalk_p1; + uint32_t utmip_uhsic2_status; + uint32_t utmip_uhsic2_fake; + uint32_t utmip_uhsic2_line_wakeup; + uint32_t utmip_master2_config; + uint32_t utmip_uhsic_rpd_cfg; + uint32_t pg_mask_ce0; + uint32_t pg_mask3[2]; + uint32_t pllm_wb0_override2; + uint32_t tsc_mult; + uint32_t cpu_vsense_override; + uint32_t glb_amap_cfg; + uint32_t sticky_bits; + uint32_t sec_disable2; + uint32_t weak_bias; + uint32_t reg_short; + uint32_t pg_mask_andor; + uint32_t _reserved1[11]; + uint32_t secure_scratch8; + uint32_t secure_scratch9; + uint32_t secure_scratch10; + uint32_t secure_scratch11; + uint32_t secure_scratch12; + uint32_t secure_scratch13; + uint32_t secure_scratch14; + uint32_t secure_scratch15; + uint32_t secure_scratch16; + uint32_t secure_scratch17; + uint32_t secure_scratch18; + uint32_t secure_scratch19; + uint32_t secure_scratch20; + uint32_t secure_scratch21; + uint32_t secure_scratch22; + uint32_t secure_scratch23; + uint32_t secure_scratch24; + uint32_t secure_scratch25; + uint32_t secure_scratch26; + uint32_t secure_scratch27; + uint32_t secure_scratch28; + uint32_t secure_scratch29; + uint32_t secure_scratch30; + uint32_t secure_scratch31; + uint32_t secure_scratch32; + uint32_t secure_scratch33; + uint32_t secure_scratch34; + uint32_t secure_scratch35; + uint32_t secure_scratch36; + uint32_t secure_scratch37; + uint32_t secure_scratch38; + uint32_t secure_scratch39; + uint32_t secure_scratch40; + uint32_t secure_scratch41; + uint32_t secure_scratch42; + uint32_t secure_scratch43; + uint32_t secure_scratch44; + uint32_t secure_scratch45; + uint32_t secure_scratch46; + uint32_t secure_scratch47; + uint32_t secure_scratch48; + uint32_t secure_scratch49; + uint32_t secure_scratch50; + uint32_t secure_scratch51; + uint32_t secure_scratch52; + uint32_t secure_scratch53; + uint32_t secure_scratch54; + uint32_t secure_scratch55; + uint32_t secure_scratch56; + uint32_t secure_scratch57; + uint32_t secure_scratch58; + uint32_t secure_scratch59; + uint32_t secure_scratch60; + uint32_t secure_scratch61; + uint32_t secure_scratch62; + uint32_t secure_scratch63; + uint32_t secure_scratch64; + uint32_t secure_scratch65; + uint32_t secure_scratch66; + uint32_t secure_scratch67; + uint32_t secure_scratch68; + uint32_t secure_scratch69; + uint32_t secure_scratch70; + uint32_t secure_scratch71; + uint32_t secure_scratch72; + uint32_t secure_scratch73; + uint32_t secure_scratch74; + uint32_t secure_scratch75; + uint32_t secure_scratch76; + uint32_t secure_scratch77; + uint32_t secure_scratch78; + uint32_t secure_scratch79; + uint32_t _reserved2[8]; + uint32_t cntrl2; + uint32_t _reserved3[2]; + uint32_t event_counter; + uint32_t fuse_control; + uint32_t scratch1_eco; + uint32_t _reserved4; + uint32_t io_dpd3_req; + uint32_t io_dpd3_status; + uint32_t io_dpd4_req; + uint32_t io_dpd4_status; + uint32_t _reserved5[30]; + uint32_t ddr_cntrl; + uint32_t _reserved6[70]; + uint32_t scratch56; + uint32_t scratch57; + uint32_t scratch58; + uint32_t scratch59; + uint32_t scratch60; + uint32_t scratch61; + uint32_t scratch62; + uint32_t scratch63; + uint32_t scratch64; + uint32_t scratch65; + uint32_t scratch66; + uint32_t scratch67; + uint32_t scratch68; + uint32_t scratch69; + uint32_t scratch70; + uint32_t scratch71; + uint32_t scratch72; + uint32_t scratch73; + uint32_t scratch74; + uint32_t scratch75; + uint32_t scratch76; + uint32_t scratch77; + uint32_t scratch78; + uint32_t scratch79; + uint32_t scratch80; + uint32_t scratch81; + uint32_t scratch82; + uint32_t scratch83; + uint32_t scratch84; + uint32_t scratch85; + uint32_t scratch86; + uint32_t scratch87; + uint32_t scratch88; + uint32_t scratch89; + uint32_t scratch90; + uint32_t scratch91; + uint32_t scratch92; + uint32_t scratch93; + uint32_t scratch94; + uint32_t scratch95; + uint32_t scratch96; + uint32_t scratch97; + uint32_t scratch98; + uint32_t scratch99; + uint32_t scratch100; + uint32_t scratch101; + uint32_t scratch102; + uint32_t scratch103; + uint32_t scratch104; + uint32_t scratch105; + uint32_t scratch106; + uint32_t scratch107; + uint32_t scratch108; + uint32_t scratch109; + uint32_t scratch110; + uint32_t scratch111; + uint32_t scratch112; + uint32_t scratch113; + uint32_t scratch114; + uint32_t scratch115; + uint32_t scratch116; + uint32_t scratch117; + uint32_t scratch118; + uint32_t scratch119; + uint32_t scratch120; + uint32_t scratch121; + uint32_t scratch122; + uint32_t scratch123; + uint32_t scratch124; + uint32_t scratch125; + uint32_t scratch126; + uint32_t scratch127; + uint32_t scratch128; + uint32_t scratch129; + uint32_t scratch130; + uint32_t scratch131; + uint32_t scratch132; + uint32_t scratch133; + uint32_t scratch134; + uint32_t scratch135; + uint32_t scratch136; + uint32_t scratch137; + uint32_t scratch138; + uint32_t scratch139; + uint32_t scratch140; + uint32_t scratch141; + uint32_t scratch142; + uint32_t scratch143; + uint32_t scratch144; + uint32_t scratch145; + uint32_t scratch146; + uint32_t scratch147; + uint32_t scratch148; + uint32_t scratch149; + uint32_t scratch150; + uint32_t scratch151; + uint32_t scratch152; + uint32_t scratch153; + uint32_t scratch154; + uint32_t scratch155; + uint32_t scratch156; + uint32_t scratch157; + uint32_t scratch158; + uint32_t scratch159; + uint32_t scratch160; + uint32_t scratch161; + uint32_t scratch162; + uint32_t scratch163; + uint32_t scratch164; + uint32_t scratch165; + uint32_t scratch166; + uint32_t scratch167; + uint32_t scratch168; + uint32_t scratch169; + uint32_t scratch170; + uint32_t scratch171; + uint32_t scratch172; + uint32_t scratch173; + uint32_t scratch174; + uint32_t scratch175; + uint32_t scratch176; + uint32_t scratch177; + uint32_t scratch178; + uint32_t scratch179; + uint32_t scratch180; + uint32_t scratch181; + uint32_t scratch182; + uint32_t scratch183; + uint32_t scratch184; + uint32_t scratch185; + uint32_t scratch186; + uint32_t scratch187; + uint32_t scratch188; + uint32_t scratch189; + uint32_t scratch190; + uint32_t scratch191; + uint32_t scratch192; + uint32_t scratch193; + uint32_t scratch194; + uint32_t scratch195; + uint32_t scratch196; + uint32_t scratch197; + uint32_t scratch198; + uint32_t scratch199; + uint32_t scratch200; + uint32_t scratch201; + uint32_t scratch202; + uint32_t scratch203; + uint32_t scratch204; + uint32_t scratch205; + uint32_t scratch206; + uint32_t scratch207; + uint32_t scratch208; + uint32_t scratch209; + uint32_t scratch210; + uint32_t scratch211; + uint32_t scratch212; + uint32_t scratch213; + uint32_t scratch214; + uint32_t scratch215; + uint32_t scratch216; + uint32_t scratch217; + uint32_t scratch218; + uint32_t scratch219; + uint32_t scratch220; + uint32_t scratch221; + uint32_t scratch222; + uint32_t scratch223; + uint32_t scratch224; + uint32_t scratch225; + uint32_t scratch226; + uint32_t scratch227; + uint32_t scratch228; + uint32_t scratch229; + uint32_t scratch230; + uint32_t scratch231; + uint32_t scratch232; + uint32_t scratch233; + uint32_t scratch234; + uint32_t scratch235; + uint32_t scratch236; + uint32_t scratch237; + uint32_t scratch238; + uint32_t scratch239; + uint32_t scratch240; + uint32_t scratch241; + uint32_t scratch242; + uint32_t scratch243; + uint32_t scratch244; + uint32_t scratch245; + uint32_t scratch246; + uint32_t scratch247; + uint32_t scratch248; + uint32_t scratch249; + uint32_t scratch250; + uint32_t scratch251; + uint32_t scratch252; + uint32_t scratch253; + uint32_t scratch254; + uint32_t scratch255; + uint32_t scratch256; + uint32_t scratch257; + uint32_t scratch258; + uint32_t scratch259; + uint32_t scratch260; + uint32_t scratch261; + uint32_t scratch262; + uint32_t scratch263; + uint32_t scratch264; + uint32_t scratch265; + uint32_t scratch266; + uint32_t scratch267; + uint32_t scratch268; + uint32_t scratch269; + uint32_t scratch270; + uint32_t scratch271; + uint32_t scratch272; + uint32_t scratch273; + uint32_t scratch274; + uint32_t scratch275; + uint32_t scratch276; + uint32_t scratch277; + uint32_t scratch278; + uint32_t scratch279; + uint32_t scratch280; + uint32_t scratch281; + uint32_t scratch282; + uint32_t scratch283; + uint32_t scratch284; + uint32_t scratch285; + uint32_t scratch286; + uint32_t scratch287; + uint32_t scratch288; + uint32_t scratch289; + uint32_t scratch290; + uint32_t scratch291; + uint32_t scratch292; + uint32_t scratch293; + uint32_t scratch294; + uint32_t scratch295; + uint32_t scratch296; + uint32_t scratch297; + uint32_t scratch298; + uint32_t scratch299; + uint32_t _reserved7[50]; + uint32_t secure_scratch80; + uint32_t secure_scratch81; + uint32_t secure_scratch82; + uint32_t secure_scratch83; + uint32_t secure_scratch84; + uint32_t secure_scratch85; + uint32_t secure_scratch86; + uint32_t secure_scratch87; + uint32_t secure_scratch88; + uint32_t secure_scratch89; + uint32_t secure_scratch90; + uint32_t secure_scratch91; + uint32_t secure_scratch92; + uint32_t secure_scratch93; + uint32_t secure_scratch94; + uint32_t secure_scratch95; + uint32_t secure_scratch96; + uint32_t secure_scratch97; + uint32_t secure_scratch98; + uint32_t secure_scratch99; + uint32_t secure_scratch100; + uint32_t secure_scratch101; + uint32_t secure_scratch102; + uint32_t secure_scratch103; + uint32_t secure_scratch104; + uint32_t secure_scratch105; + uint32_t secure_scratch106; + uint32_t secure_scratch107; + uint32_t secure_scratch108; + uint32_t secure_scratch109; + uint32_t secure_scratch110; + uint32_t secure_scratch111; + uint32_t secure_scratch112; + uint32_t secure_scratch113; + uint32_t secure_scratch114; + uint32_t secure_scratch115; + uint32_t secure_scratch116; + uint32_t secure_scratch117; + uint32_t secure_scratch118; + uint32_t secure_scratch119; +} tegra_pmc_t; + +static inline volatile tegra_pmc_t *pmc_get_regs(void) +{ + return (volatile tegra_pmc_t *)PMC_BASE; +} + +#endif diff --git a/sept/sept-primary/src/se.c b/sept/sept-primary/src/se.c new file mode 100644 index 000000000..d4dbdc498 --- /dev/null +++ b/sept/sept-primary/src/se.c @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> + +#include "utils.h" +#include "se.h" + +void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size); + +/* Globals for driver. */ +static unsigned int g_se_modulus_sizes[KEYSLOT_RSA_MAX]; +static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX]; + +/* Initialize a SE linked list. */ +void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { + ll->num_entries = 0; /* 1 Entry. */ + + if (buffer != NULL) { + ll->addr_info.address = (uint32_t) get_physical_address(buffer); + ll->addr_info.size = (uint32_t) size; + } else { + ll->addr_info.address = 0; + ll->addr_info.size = 0; + } +} + +void se_check_error_status_reg(void) { + if (se_get_regs()->ERR_STATUS_REG) { + generic_panic(); + } +} + +void se_check_for_error(void) { + volatile tegra_se_t *se = se_get_regs(); + if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) { + generic_panic(); + } +} + +void se_verify_flags_cleared(void) { + if (se_get_regs()->FLAGS_REG & 3) { + generic_panic(); + } +} + +/* Set the flags for an AES keyslot. */ +void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* Misc flags. */ + if (flags & ~0x80) { + se->AES_KEYSLOT_FLAGS[keyslot] = ~flags; + } + + /* Disable keyslot reads. */ + if (flags & 0x80) { + se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + } +} + +/* Set the flags for an RSA keyslot. */ +void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_RSA_MAX) { + generic_panic(); + } + + /* Misc flags. */ + if (flags & ~0x80) { + /* TODO: Why are flags assigned this way? */ + se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; + } + + /* Disable keyslot reads. */ + if (flags & 0x80) { + se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + } +} + +void clear_aes_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* Zero out the whole keyslot and IV. */ + for (unsigned int i = 0; i < 0x10; i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = 0; + } +} + +void clear_rsa_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_RSA_MAX) { + generic_panic(); + } + + /* Zero out the whole keyslot. */ + for (unsigned int i = 0; i < 0x40; i++) { + /* Select Keyslot Modulus[i] */ + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; + se->RSA_KEYTABLE_DATA = 0; + } + for (unsigned int i = 0; i < 0x40; i++) { + /* Select Keyslot Expontent[i] */ + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = 0; + } +} + +void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { + generic_panic(); + } + + for (size_t i = 0; i < (key_size >> 2); i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = read32le(key, 4 * i); + } +} + +void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { + generic_panic(); + } + + for (size_t i = 0; i < (modulus_size >> 2); i++) { + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; + se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); + } + + for (size_t i = 0; i < (exp_size >> 2); i++) { + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); + } + + g_se_modulus_sizes[keyslot] = modulus_size; + g_se_exp_sizes[keyslot] = exp_size; +} + +void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { + generic_panic(); + } + + for (size_t i = 0; i < (iv_size >> 2); i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = read32le(iv, 4 * i); + } +} + +void clear_aes_keyslot_iv(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + for (size_t i = 0; i < (0x10 >> 2); i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = 0; + } +} + +void set_se_ctr(const void *ctr) { + for (unsigned int i = 0; i < 4; i++) { + se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + } +} + +void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { + generic_panic(); + } + + se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); + se->CRYPTO_REG = keyslot_src << 24; + se->BLOCK_COUNT_REG = 0; + se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; + + trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); +} + +void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + uint8_t ALIGN(16) stack_buf[KEYSIZE_RSA_MAX]; + + if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) { + generic_panic(); + } + + /* Endian swap the input. */ + for (size_t i = 0; i < src_size; i++) { + stack_buf[i] = *((uint8_t *)src + src_size - i - 1); + } + + se->CONFIG_REG = (ALG_RSA | DST_RSAREG); + se->RSA_CONFIG = keyslot << 24; + se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; + se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; + + trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size); + se_get_exp_mod_output(dst, dst_size); +} + +void se_get_exp_mod_output(void *buf, size_t size) { + size_t num_dwords = (size >> 2); + + if (num_dwords < 1) { + return; + } + + uint32_t *p_out = ((uint32_t *)buf) + num_dwords - 1; + uint32_t offset = 0; + + /* Copy endian swapped output. */ + while (num_dwords) { + *p_out = read32be(se_get_regs()->RSA_OUTPUT, offset); + offset += 4; + p_out--; + num_dwords--; + } +} + +bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size) { + uint8_t message[RSA_2048_BYTES]; + uint8_t h_buf[0x24]; + + /* Hardcode RSA with keyslot 0. */ + const uint8_t public_exponent[4] = {0x00, 0x01, 0x00, 0x01}; + set_rsa_keyslot(0, modulus, modulus_size, public_exponent, sizeof(public_exponent)); + se_synchronous_exp_mod(0, message, sizeof(message), signature, signature_size); + + /* Validate sanity byte. */ + if (message[RSA_2048_BYTES - 1] != 0xBC) { + return false; + } + + /* Copy Salt into MGF1 Hash Buffer. */ + memset(h_buf, 0, sizeof(h_buf)); + memcpy(h_buf, message + RSA_2048_BYTES - 0x20 - 0x1, 0x20); + + /* Decrypt maskedDB (via inline MGF1). */ + uint8_t seed = 0; + uint8_t mgf1_buf[0x20]; + for (unsigned int ofs = 0; ofs < RSA_2048_BYTES - 0x20 - 1; ofs += 0x20) { + h_buf[sizeof(h_buf) - 1] = seed++; + se_calculate_sha256(mgf1_buf, h_buf, sizeof(h_buf)); + for (unsigned int i = ofs; i < ofs + 0x20 && i < RSA_2048_BYTES - 0x20 - 1; i++) { + message[i] ^= mgf1_buf[i - ofs]; + } + } + + /* Constant lmask for rsa-2048-pss. */ + message[0] &= 0x7F; + + /* Validate DB is of the form 0000...0001. */ + for (unsigned int i = 0; i < RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1; i++) { + if (message[i] != 0) { + return false; + } + } + if (message[RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1] != 1) { + return false; + } + + /* Check hash correctness. */ + uint8_t validate_buf[8 + 0x20 + 0x20]; + uint8_t validate_hash[0x20]; + + memset(validate_buf, 0, sizeof(validate_buf)); + se_calculate_sha256(&validate_buf[8], data, data_size); + memcpy(&validate_buf[0x28], &message[RSA_2048_BYTES - 0x20 - 0x20 - 1], 0x20); + se_calculate_sha256(validate_hash, validate_buf, sizeof(validate_buf)); + return memcmp(h_buf, validate_hash, 0x20) == 0; +} + +void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + se_ll_t in_ll; + se_ll_t out_ll; + + ll_init(&in_ll, (void *)src, src_size); + ll_init(&out_ll, dst, dst_size); + + /* Set the LLs. */ + se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); + se->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll); + + /* Set registers for operation. */ + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = op; + + while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ } + se_check_for_error(); +} + +/* Secure AES Functionality. */ +void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { + uint8_t block[0x10] = {0}; + + if (src_size > sizeof(block) || dst_size > sizeof(block)) { + generic_panic(); + } + + /* Load src data into block. */ + if (src_size != 0) { + memcpy(block, src, src_size); + } + + /* Trigger AES operation. */ + se_get_regs()->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); + + /* Copy output data into dst. */ + if (dst_size != 0) { + memcpy(dst, block, dst_size); + } +} + +void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) { + generic_panic(); + } + unsigned int num_blocks = src_size >> 4; + + /* Unknown what this write does, but official code writes it for CTR mode. */ + se->SPARE_0 = 1; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x91E; + set_se_ctr(ctr); + + /* Handle any aligned blocks. */ + size_t aligned_size = (size_t)num_blocks << 4; + if (aligned_size) { + se->BLOCK_COUNT_REG = num_blocks - 1; + trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size); + } + + /* Handle final, unaligned block. */ + if (aligned_size < dst_size && aligned_size < src_size) { + size_t last_block_size = dst_size - aligned_size; + if (src_size < dst_size) { + last_block_size = src_size - aligned_size; + } + se_perform_aes_block_operation(dst + aligned_size, last_block_size, (uint8_t *)src + aligned_size, src_size - aligned_size); + } +} + +void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { + generic_panic(); + } + + /* Set configuration high (256-bit vs 128-bit) based on parameter. */ + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); + se->CRYPTO_REG = keyslot << 24 | 0x100; + se_perform_aes_block_operation(dst, 0x10, src, 0x10); +} + +void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0); +} + +void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202); +} + +void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { + generic_panic(); + } + + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot << 24; + se_perform_aes_block_operation(dst, 0x10, src, 0x10); +} + +void shift_left_xor_rb(uint8_t *key) { + uint8_t prev_high_bit = 0; + for (unsigned int i = 0; i < 0x10; i++) { + uint8_t cur_byte = key[0xF - i]; + key[0xF - i] = (cur_byte << 1) | (prev_high_bit); + prev_high_bit = cur_byte >> 7; + } + if (prev_high_bit) { + key[0xF] ^= 0x87; + } +} + +void shift_left_xor_rb_le(uint8_t *key) { + uint8_t prev_high_bit = 0; + for (unsigned int i = 0; i < 0x10; i++) { + uint8_t cur_byte = key[i]; + key[i] = (cur_byte << 1) | (prev_high_bit); + prev_high_bit = cur_byte >> 7; + } + if (prev_high_bit) { + key[0x0] ^= 0x87; + } +} + +void aes_128_xts_nintendo_get_tweak(uint8_t *tweak, size_t sector) { + for (int i = 0xF; i >= 0; i--) { /* Nintendo LE custom tweak... */ + tweak[i] = (unsigned char)(sector & 0xFF); + sector >>= 8; + } +} + +void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, uint8_t *dst, const uint8_t *src, size_t size) { + if ((size & 0xF) || size == 0) { + generic_panic(); + } + uint8_t tweak[0x10]; + aes_128_xts_nintendo_get_tweak(tweak, sector); + se_aes_128_ecb_encrypt_block(keyslot, tweak, sizeof(tweak), tweak, sizeof(tweak)); + + for (unsigned int block = 0; block < (size >> 4); block++) { + for (unsigned int i = 0; i < 0x10; i++) { + dst[(block << 4) | i] = src[(block << 4) | i] ^ tweak[i]; + } + shift_left_xor_rb_le(tweak); + } +} + +void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keyslot_2, size_t sector, bool encrypt, void *dst, const void *src, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + + if ((size & 0xF) || size == 0) { + generic_panic(); + } + + /* XOR. */ + aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, src, size); + + /* Encrypt/Decrypt. */ + if (encrypt) { + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = keyslot_1 << 24 | 0x100; + } else { + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot_1 << 24; + } + se->BLOCK_COUNT_REG = (size >> 4) - 1; + trigger_se_blocking_op(OP_START, dst, size, src, size); + + /* XOR. */ + aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size); +} + +/* Encrypt with AES-XTS (Nintendo's custom tweak). */ +void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) { + if ((size & 0xF) || size == 0) { + generic_panic(); + } + size_t sector = base_sector; + for (size_t ofs = 0; ofs < size; ofs += sector_size) { + aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, true, dst + ofs, src + ofs, sector_size); + sector++; + } +} + +/* Decrypt with AES-XTS (Nintendo's custom tweak). */ +void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) { + if ((size & 0xF) || size == 0) { + generic_panic(); + } + size_t sector = base_sector; + for (size_t ofs = 0; ofs < size; ofs += sector_size) { + aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, false, dst + ofs, src + ofs, sector_size); + sector++; + } +} + +void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* Generate the derived key, to be XOR'd with final output block. */ + uint8_t ALIGN(16) derived_key[0x10] = {0}; + se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high); + shift_left_xor_rb(derived_key); + if (data_size & 0xF) { + shift_left_xor_rb(derived_key); + } + + se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); + se->CRYPTO_REG = (keyslot << 24) | (0x145); + clear_aes_keyslot_iv(keyslot); + + unsigned int num_blocks = (data_size + 0xF) >> 4; + /* Handle aligned blocks. */ + if (num_blocks > 1) { + se->BLOCK_COUNT_REG = num_blocks - 2; + trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); + se->CRYPTO_REG |= 0x80; + } + + /* Create final block. */ + uint8_t ALIGN(16) last_block[0x10] = {0}; + if (data_size & 0xF) { + memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF); + last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */ + } else if (data_size >= 0x10) { + memcpy(last_block, data + data_size - 0x10, 0x10); + } + + for (unsigned int i = 0; i < 0x10; i++) { + last_block[i] ^= derived_key[i]; + } + + /* Perform last operation. */ + se->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); + + /* Copy output CMAC. */ + for (unsigned int i = 0; i < (cmac_size >> 2); i++) { + ((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2); + } +} + +void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { + se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0); +} +void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { + se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202); +} + +void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { + generic_panic(); + } + + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); + se->CRYPTO_REG = (keyslot << 24) | 0x144; + set_aes_keyslot_iv(keyslot, iv, 0x10); + se->BLOCK_COUNT_REG = (src_size >> 4) - 1; + trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); +} + +/* SHA256 Implementation. */ +void se_calculate_sha256(void *dst, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + + /* Setup config for SHA256, size = BITS(src_size) */ + se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); + se->SHA_CONFIG_REG = 1; + se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); + se->_0x208 = 0; + se->_0x20C = 0; + se->_0x210 = 0; + se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); + se->_0x218 = 0; + se->_0x21C = 0; + se->_0x220 = 0; + + /* Trigger the operation. */ + trigger_se_blocking_op(OP_START, NULL, 0, src, src_size); + + /* Copy output hash. */ + for (unsigned int i = 0; i < (0x20 >> 2); i++) { + ((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2); + } +} + +/* RNG API */ +void se_initialize_rng(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* To initialize the RNG, we'll perform an RNG operation into an output buffer. */ + /* This will be discarded, when done. */ + uint8_t ALIGN(16) output_buf[0x10]; + + se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ + se->RNG_RESEED_INTERVAL_REG = 70001; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 5; + se->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0); +} + +void se_generate_random(unsigned int keyslot, void *dst, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + uint32_t num_blocks = size >> 4; + size_t aligned_size = num_blocks << 4; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 4; + + if (num_blocks >= 1) { + se->BLOCK_COUNT_REG = num_blocks - 1; + trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0); + } + if (size > aligned_size) { + se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0); + } +} diff --git a/sept/sept-primary/src/se.h b/sept/sept-primary/src/se.h new file mode 100644 index 000000000..64998621a --- /dev/null +++ b/sept/sept-primary/src/se.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SE_H +#define FUSEE_SE_H + +#define SE_BASE 0x70012000 +#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n) + +#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2 +#define KEYSLOT_SWITCH_SRKGENKEY 0x8 +#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8 +#define KEYSLOT_SWITCH_TEMPKEY 0x9 +#define KEYSLOT_SWITCH_SESSIONKEY 0xA +#define KEYSLOT_SWITCH_RNGKEY 0xB +#define KEYSLOT_SWITCH_MASTERKEY 0xC +#define KEYSLOT_SWITCH_DEVICEKEY 0xD + +/* This keyslot was added in 4.0.0. */ +#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD +#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE +#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF + +/* This keyslot was added in 5.0.0. */ +#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA + +#define KEYSLOT_AES_MAX 0x10 +#define KEYSLOT_RSA_MAX 0x2 + +#define KEYSIZE_AES_MAX 0x20 +#define KEYSIZE_RSA_MAX 0x100 + +#define ALG_SHIFT (12) +#define ALG_DEC_SHIFT (8) +#define ALG_NOP (0 << ALG_SHIFT) +#define ALG_AES_ENC (1 << ALG_SHIFT) +#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP) +#define ALG_RNG (2 << ALG_SHIFT) +#define ALG_SHA (3 << ALG_SHIFT) +#define ALG_RSA (4 << ALG_SHIFT) + +#define DST_SHIFT (2) +#define DST_MEMORY (0 << DST_SHIFT) +#define DST_HASHREG (1 << DST_SHIFT) +#define DST_KEYTAB (2 << DST_SHIFT) +#define DST_SRK (3 << DST_SHIFT) +#define DST_RSAREG (4 << DST_SHIFT) + +#define ENCMODE_SHIFT (24) +#define DECMODE_SHIFT (16) +#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT) + +#define HASH_DISABLE (0x0) +#define HASH_ENABLE (0x1) + +#define OP_ABORT 0 +#define OP_START 1 +#define OP_RESTART 2 +#define OP_CTX_SAVE 3 +#define OP_RESTART_IN 4 + +#define CTX_SAVE_SRC_SHIFT 29 +#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT) + +#define CTX_SAVE_KEY_LOW_BITS 0 +#define CTX_SAVE_KEY_HIGH_BITS 1 +#define CTX_SAVE_KEY_ORIGINAL_IV 2 +#define CTX_SAVE_KEY_UPDATED_IV 3 + +#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24 +#define CTX_SAVE_KEY_INDEX_SHIFT 8 +#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16 +#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12 + +#define RSA_2048_BYTES 0x100 + +typedef struct { + uint32_t _0x0; + uint32_t _0x4; + uint32_t OPERATION_REG; + uint32_t INT_ENABLE_REG; + uint32_t INT_STATUS_REG; + uint32_t CONFIG_REG; + uint32_t IN_LL_ADDR_REG; + uint32_t _0x1C; + uint32_t _0x20; + uint32_t OUT_LL_ADDR_REG; + uint32_t _0x28; + uint32_t _0x2C; + uint8_t HASH_RESULT_REG[0x20]; + uint8_t _0x50[0x20]; + uint32_t CONTEXT_SAVE_CONFIG_REG; + uint8_t _0x74[0x18C]; + uint32_t SHA_CONFIG_REG; + uint32_t SHA_MSG_LENGTH_REG; + uint32_t _0x208; + uint32_t _0x20C; + uint32_t _0x210; + uint32_t SHA_MSG_LEFT_REG; + uint32_t _0x218; + uint32_t _0x21C; + uint32_t _0x220; + uint32_t _0x224; + uint8_t _0x228[0x58]; + uint32_t AES_KEY_READ_DISABLE_REG; + uint32_t AES_KEYSLOT_FLAGS[0x10]; + uint8_t _0x2C4[0x3C]; + uint32_t _0x300; + uint32_t CRYPTO_REG; + uint32_t CRYPTO_CTR_REG[4]; + uint32_t BLOCK_COUNT_REG; + uint32_t AES_KEYTABLE_ADDR; + uint32_t AES_KEYTABLE_DATA; + uint32_t _0x324; + uint32_t _0x328; + uint32_t _0x32C; + uint32_t CRYPTO_KEYTABLE_DST_REG; + uint8_t _0x334[0xC]; + uint32_t RNG_CONFIG_REG; + uint32_t RNG_SRC_CONFIG_REG; + uint32_t RNG_RESEED_INTERVAL_REG; + uint8_t _0x34C[0xB4]; + uint32_t RSA_CONFIG; + uint32_t RSA_KEY_SIZE_REG; + uint32_t RSA_EXP_SIZE_REG; + uint32_t RSA_KEY_READ_DISABLE_REG; + uint32_t RSA_KEYSLOT_FLAGS[2]; + uint32_t _0x418; + uint32_t _0x41C; + uint32_t RSA_KEYTABLE_ADDR; + uint32_t RSA_KEYTABLE_DATA; + uint8_t RSA_OUTPUT[0x100]; + uint8_t _0x528[0x2D8]; + uint32_t FLAGS_REG; + uint32_t ERR_STATUS_REG; + uint32_t _0x808; + uint32_t SPARE_0; + uint32_t _0x810; + uint32_t _0x814; + uint32_t _0x818; + uint32_t _0x81C; + uint8_t _0x820[0x17E0]; +} tegra_se_t; + +typedef struct { + uint32_t address; + uint32_t size; +} se_addr_info_t; + +typedef struct { + uint32_t num_entries; /* Set to total entries - 1 */ + se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ +} se_ll_t; + +static inline volatile tegra_se_t *se_get_regs(void) { + return (volatile tegra_se_t *)SE_BASE; +} + +void se_check_error_status_reg(void); +void se_check_for_error(void); +void se_trigger_interrupt(void); + +void se_validate_stored_vector(void); +void se_generate_stored_vector(void); + +void se_verify_flags_cleared(void); + +void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags); +void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags); +void clear_aes_keyslot(unsigned int keyslot); +void clear_rsa_keyslot(unsigned int keyslot); + +void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size); +void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size); +void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size); +void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size); +void set_se_ctr(const void *ctr); + +/* Secure AES API */ +void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size); +void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size); +void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); +void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); +void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); +void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); +void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size); +void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); +void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv); + +/* Hash API */ +void se_calculate_sha256(void *dst, const void *src, size_t src_size); + +/* RSA API */ +void se_get_exp_mod_output(void *buf, size_t size); +void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); +bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size); + +/* RNG API */ +void se_initialize_rng(unsigned int keyslot); +void se_generate_random(unsigned int keyslot, void *dst, size_t size); + +#endif diff --git a/sept/sept-primary/src/start.s b/sept/sept-primary/src/start.s new file mode 100644 index 000000000..50e8faf74 --- /dev/null +++ b/sept/sept-primary/src/start.s @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +.section .text.start, "ax", %progbits +.arm +.align 5 +.global _start +.type _start, %function +_start: + /* Set coldboot */ + mov r0, #0x0 + ldr r1, =0x7000E400 + str r0, [r1, #0x50] + + /* Tell pk1ldr normal reboot, no error */ + str r0, [r1, #0x1B4] + str r0, [r1, #0x840] + + /* Cleanup SVC handler address. */ + ldr r0, =0x40004C30 + ldr r1, =0x6000F208 + str r0, [r1] + + /* Disable RCM forcefully */ + mov r0, #0x4 + ldr r1, =0x15DC + ldr r2, =0xE020 + bl ipatch_word + + /* Patch BCT signature check */ + mov r0, #0x5 + ldr r1, =0x4AEE + ldr r2, =0xE05B + bl ipatch_word + + /* Patch bootloader read */ + mov r0, #0x6 + ldr r1, =0x4E88 + ldr r2, =0xE018 + bl ipatch_word + + ldr r0, =__main_phys_start__ + ldr r1, =__main_start__ + mov r2, #0x0 + ldr r3, =(__main_size__) + copy_panic_payload: + ldr r4, [r0, r2] + str r4, [r1, r2] + add r2, r2, #0x4 + cmp r2, r3 + bne copy_panic_payload + + + + /* Jump back to bootrom start. */ + ldr r0, =0x101010 + bx r0 + + /* Unused, but forces inclusion in binary. */ + b main + + +.section .text.ipatch_word, "ax", %progbits +.arm +.align 5 +.global ipatch_word +.type ipatch_word, %function +ipatch_word: + ldr r3, =0x6001dc00 + lsl r0, r0, #0x2 + lsr r1, r1, #0x1 + lsl r1, r1, #0x10 + orr r1, r1, r2 + str r1, [r3, r0] + bx lr + +.section .text.jump_to_main, "ax", %progbits +.arm +.align 5 +.global jump_to_main +.type jump_to_main, %function +jump_to_main: + /* Just jump to main */ + ldr sp, =__stack_top__ + b main + + diff --git a/sept/sept-primary/src/sysreg.h b/sept/sept-primary/src/sysreg.h new file mode 100644 index 000000000..1bc1a8c43 --- /dev/null +++ b/sept/sept-primary/src/sysreg.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SYSREG_H +#define FUSEE_SYSREG_H + +#include <stdint.h> + +#define SYSREG_BASE 0x6000C000 +#define SB_BASE (SYSREG_BASE + 0x200) +#define EXCP_VEC_BASE 0x6000F000 + +#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n) +#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n) +#define MAKE_EXCP_VEC_REG(n) MAKE_REG32(EXCP_VEC_BASE + n) + +#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004) +#define AHB_ARBITRATION_XBAR_CTRL_0 MAKE_SYSREG(0x0E0) +#define AHB_AHB_SPARE_REG_0 MAKE_SYSREG(0x110) + +#define SB_CSR_0 MAKE_SB_REG(0x00) +#define SB_PIROM_START_0 MAKE_SB_REG(0x04) +#define SB_PFCFG_0 MAKE_SB_REG(0x08) +#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C) +#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10) +#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14) +#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18) +#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C) +#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20) +#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24) +#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28) +#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30) +#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34) + +#endif diff --git a/sept/sept-primary/src/timers.h b/sept/sept-primary/src/timers.h new file mode 100644 index 000000000..d1f89d33c --- /dev/null +++ b/sept/sept-primary/src/timers.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_TIMERS_H +#define FUSEE_TIMERS_H + +#include "utils.h" + +#define TIMERS_BASE 0x60005000 +#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) + +#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) +#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14) +#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0) +#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4) + +#define RTC_BASE 0x7000E000 +#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) + +#define RTC_SECONDS MAKE_RTC_REG(0x08) +#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C) +#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10) + +typedef struct { + uint32_t CONFIG; + uint32_t STATUS; + uint32_t COMMAND; + uint32_t PATTERN; +} watchdog_timers_t; + +#define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) +#define WDT_REBOOT_PATTERN 0xC45A +#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n) + +void wait(uint32_t microseconds); + +static inline uint32_t get_time_us(void) { + return TIMERUS_CNTR_1US_0; +} + +/** + * Returns the time in microseconds. + */ +static inline uint32_t get_time(void) { + return get_time_us(); +} + +/** + * Returns the number of microseconds that have passed since a given get_time(). + */ +static inline uint32_t get_time_since(uint32_t base) { + return get_time_us() - base; +} + +/** + * Delays for a given number of microseconds. + */ +static inline void udelay(uint32_t usecs) { + uint32_t start = get_time_us(); + while (get_time_us() - start < usecs); +} + +__attribute__ ((noreturn)) void watchdog_reboot(void); + +#endif diff --git a/sept/sept-primary/src/tsec.h b/sept/sept-primary/src/tsec.h new file mode 100644 index 000000000..e90296210 --- /dev/null +++ b/sept/sept-primary/src/tsec.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_TSEC_H_ +#define FUSEE_TSEC_H_ + +#include <string.h> +#include <stdbool.h> + +#define TSEC_BASE 0x54500000 +#define SOR1_BASE 0x54580000 + +#define SOR1_DP_HDCP_BKSV_LSB MAKE_REG32(SOR1_BASE + 0x1E8) +#define SOR1_TMDS_HDCP_BKSV_LSB MAKE_REG32(SOR1_BASE + 0x21C) +#define SOR1_TMDS_HDCP_CN_MSB MAKE_REG32(SOR1_BASE + 0x208) +#define SOR1_TMDS_HDCP_CN_LSB MAKE_REG32(SOR1_BASE + 0x20C) + +typedef struct { + uint8_t _0x0[0x1000]; /* Ignore non Falcon registers. */ + uint32_t FALCON_IRQSSET; + uint32_t FALCON_IRQSCLR; + uint32_t FALCON_IRQSTAT; + uint32_t FALCON_IRQMODE; + uint32_t FALCON_IRQMSET; + uint32_t FALCON_IRQMCLR; + uint32_t FALCON_IRQMASK; + uint32_t FALCON_IRQDEST; + uint8_t _0x1020[0x20]; + uint32_t FALCON_SCRATCH0; + uint32_t FALCON_SCRATCH1; + uint32_t FALCON_ITFEN; + uint32_t FALCON_IDLESTATE; + uint32_t FALCON_CURCTX; + uint32_t FALCON_NXTCTX; + uint8_t _0x1058[0x28]; + uint32_t FALCON_SCRATCH2; + uint32_t FALCON_SCRATCH3; + uint32_t FALCON_PM_SIGNAL; + uint32_t FALCON_PM_MODE; + uint32_t FALCON_DEBUG1; + uint32_t FALCON_DEBUGINFO; + uint32_t FALCON_BREAKPOINT0; + uint32_t FALCON_BREAKPOINT1; + uint32_t FALCON_CGCTL; + uint32_t FALCON_ENGCTL; + uint8_t _0x10A8[0x58]; + uint32_t FALCON_CPUCTL; + uint32_t FALCON_BOOTVEC; + uint32_t FALCON_HWCFG; + uint32_t FALCON_DMACTL; + uint32_t FALCON_DMATRFBASE; + uint32_t FALCON_DMATRFMOFFS; + uint32_t FALCON_DMATRFCMD; + uint32_t FALCON_DMATRFFBOFFS; + uint8_t _0x1120[0x10]; + uint32_t FALCON_CPUCTL_ALIAS; + uint8_t _0x1134[0x20]; + uint32_t FALCON_IMFILLRNG1; + uint32_t FALCON_IMFILLCTL; + uint32_t _0x115C; + uint32_t _0x1160; + uint32_t _0x1164; + uint32_t FALCON_EXTERRADDR; + uint32_t FALCON_EXTERRSTAT; + uint32_t _0x1170; + uint32_t _0x1174; + uint32_t _0x1178; + uint32_t FALCON_CG2; + uint32_t FALCON_CODE_INDEX; + uint32_t FALCON_CODE; + uint32_t FALCON_CODE_VIRT_ADDR; + uint8_t _0x118C[0x34]; + uint32_t FALCON_DATA_INDEX0; + uint32_t FALCON_DATA0; + uint32_t FALCON_DATA_INDEX1; + uint32_t FALCON_DATA1; + uint32_t FALCON_DATA_INDEX2; + uint32_t FALCON_DATA2; + uint32_t FALCON_DATA_INDEX3; + uint32_t FALCON_DATA3; + uint32_t FALCON_DATA_INDEX4; + uint32_t FALCON_DATA4; + uint32_t FALCON_DATA_INDEX5; + uint32_t FALCON_DATA5; + uint32_t FALCON_DATA_INDEX6; + uint32_t FALCON_DATA6; + uint32_t FALCON_DATA_INDEX7; + uint32_t FALCON_DATA7; + uint32_t FALCON_ICD_CMD; + uint32_t FALCON_ICD_ADDR; + uint32_t FALCON_ICD_WDATA; + uint32_t FALCON_ICD_RDATA; + uint8_t _0x1210[0x30]; + uint32_t FALCON_SCTL; + uint8_t _0x1244[0x1430-0x1244]; /* Ignore non Falcon registers. */ + uint32_t TSEC_SCP_INSN_STAT; + uint8_t _0x1434[0x1244+0x5F8-0x1434]; /* Ignore non Falcon registers. */ +} tegra_tsec_t; + +static inline volatile tegra_tsec_t *tsec_get_regs(void) +{ + return (volatile tegra_tsec_t *)TSEC_BASE; +} + +#endif \ No newline at end of file diff --git a/sept/sept-primary/src/utils.c b/sept/sept-primary/src/utils.c new file mode 100644 index 000000000..5cf1e0e73 --- /dev/null +++ b/sept/sept-primary/src/utils.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stdarg.h> +#include "utils.h" +#include "se.h" +#include "fuse.h" +#include "pmc.h" +#include "timers.h" +#include "panic.h" +#include "car.h" +#include "btn.h" + +#include <inttypes.h> + +#define u8 uint8_t +#define u32 uint32_t +#include "rebootstub_bin.h" +#undef u8 +#undef u32 + +void wait(uint32_t microseconds) { + uint32_t old_time = TIMERUS_CNTR_1US_0; + while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { + /* Spin-lock. */ + } +} + +__attribute__((noreturn)) void watchdog_reboot(void) { + volatile watchdog_timers_t *wdt = GET_WDT(4); + wdt->PATTERN = WDT_REBOOT_PATTERN; + wdt->COMMAND = 2; /* Disable Counter. */ + GET_WDT_REBOOT_CFG_REG(4) = 0xC0000000; + wdt->CONFIG = 0x8019; /* Full System Reset after Fourth Counter expires, using TIMER(9). */ + wdt->COMMAND = 1; /* Enable Counter. */ + while (true) { + /* Wait for reboot. */ + } +} + +__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) { + APBDEV_PMC_SCRATCH0_0 = scratch0; + + /* Reset the processor. */ + APBDEV_PMC_CONTROL = BIT(4); + + while (true) { + /* Wait for reboot. */ + } +} + +__attribute__((noreturn)) void reboot_to_self(void) { + /* Patch SDRAM init to perform an SVC immediately after second write */ + APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF; + APBDEV_PMC_SCRATCH46_0 = 0x6001DC28; + /* Set SVC handler to jump to reboot stub in IRAM. */ + APBDEV_PMC_SCRATCH33_0 = 0x4003F000; + APBDEV_PMC_SCRATCH40_0 = 0x6000F208; + + /* Copy reboot stub into IRAM high. */ + for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) { + write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i)); + } + + /* Trigger warm reboot. */ + pmc_reboot(1 << 0); +} + +__attribute__((noreturn)) void wait_for_button_and_reboot(void) { + uint32_t button; + while (true) { + button = btn_read(); + if (button & BTN_POWER) { + reboot_to_self(); + } + } +} + +__attribute__ ((noreturn)) void generic_panic(void) { + panic(0xFF000006); +} + +__attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be) +{ + if(as <= bs && bs <= ae) + return true; + if(bs <= as && as <= be) + return true; + return false; +} + diff --git a/sept/sept-primary/src/utils.h b/sept/sept-primary/src/utils.h new file mode 100644 index 000000000..03388c631 --- /dev/null +++ b/sept/sept-primary/src/utils.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_UTILS_H +#define FUSEE_UTILS_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#define BIT(n) (1u << (n)) +#define BITL(n) (1ull << (n)) +#define MASK(n) (BIT(n) - 1) +#define MASKL(n) (BITL(n) - 1) +#define MASK2(a,b) (MASK(a) & ~MASK(b)) +#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) + +#define MAKE_REG32(a) (*(volatile uint32_t *)(a)) + +#define ALIGN(m) __attribute__((aligned(m))) +#define PACKED __attribute__((packed)) + +#define ALINLINE __attribute__((always_inline)) +#define NOINLINE __attribute__((noinline)) + +#define SET_SYSREG(reg, val) do { temp_reg = (val); __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false) + +static inline uintptr_t get_physical_address(const void *addr) { + return (uintptr_t)addr; +} + +static inline uint32_t read32le(const volatile void *dword, size_t offset) { + uintptr_t addr = (uintptr_t)dword + offset; + volatile uint32_t *target = (uint32_t *)addr; + return *target; +} + +static inline uint32_t read32be(const volatile void *dword, size_t offset) { + return __builtin_bswap32(read32le(dword, offset)); +} + +static inline uint64_t read64le(const volatile void *qword, size_t offset) { + uintptr_t addr = (uintptr_t)qword + offset; + volatile uint64_t *target = (uint64_t *)addr; + return *target; +} + +static inline uint64_t read64be(const volatile void *qword, size_t offset) { + return __builtin_bswap64(read64le(qword, offset)); +} + +static inline void write32le(volatile void *dword, size_t offset, uint32_t value) { + uintptr_t addr = (uintptr_t)dword + offset; + volatile uint32_t *target = (uint32_t *)addr; + *target = value; +} + +static inline void write32be(volatile void *dword, size_t offset, uint32_t value) { + write32le(dword, offset, __builtin_bswap32(value)); +} + +static inline void write64le(volatile void *qword, size_t offset, uint64_t value) { + uintptr_t addr = (uintptr_t)qword + offset; + volatile uint64_t *target = (uint64_t *)addr; + *target = value; +} + +static inline void write64be(volatile void *qword, size_t offset, uint64_t value) { + write64le(qword, offset, __builtin_bswap64(value)); +} + +static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) { + return __builtin_add_overflow_p(a, b, (uint32_t)0); +} + +static inline bool check_32bit_address_loadable(uintptr_t addr) { + /* FWIW the bootROM forbids loading anything between 0x40000000 and 0x40010000, using it for itself... */ + return (addr >= 0x40010000u && addr < 0x40040000u) || addr >= 0x80000000u; +} + +static inline bool check_32bit_address_range_loadable(uintptr_t addr, size_t size) { + return + !__builtin_add_overflow_p(addr, size, (uintptr_t)0) && /* the range doesn't overflow */ + check_32bit_address_loadable(addr) && check_32bit_address_loadable(addr + size) && /* bounds are valid */ + !(addr >= 0x40010000u && addr < 0x40040000u && addr + size >= 0x40040000u) /* the range doesn't cross MMIO */ + ; +} + +bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be); +static inline bool overlaps_a(const void *as, const void *ae, const void *bs, const void *be) { + return overlaps((uint64_t)(uintptr_t)as, (uint64_t)(uintptr_t)ae, (uint64_t)(uintptr_t)bs, (uint64_t)(uintptr_t)be); +} + +static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t size) { + extern uint8_t __chainloader_start__[], __chainloader_end__[]; + extern uint8_t __stack_bottom__[], __stack_top__[]; + extern uint8_t __start__[], __end__[]; + uint8_t *start = (uint8_t *)addr, *end = start + size; + + return overlaps_a(start, end, __chainloader_start__, __chainloader_end__) || + overlaps_a(start, end, __stack_bottom__, __stack_top__) || + overlaps_a(start, end, (void *)0xC0000000, (void *)0xC03C0000) || /* framebuffer */ + overlaps_a(start, end, __start__, __end__); +} + +void hexdump(const void* data, size_t size, uintptr_t addrbase); + +__attribute__((noreturn)) void watchdog_reboot(void); +__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); +__attribute__((noreturn)) void reboot_to_self(void); +__attribute__((noreturn)) void wait_for_button_and_reboot(void); + +__attribute__((noreturn)) void generic_panic(void); + +#endif From 5fe24b620d7b0e29b526918c0eb507efcbf89913 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 06:31:46 -0800 Subject: [PATCH 414/489] sept: add secondary skeleton + buildscript --- .gitignore | 5 + fusee/fusee-secondary/Makefile | 9 +- fusee/fusee-secondary/src/nxboot.c | 4 +- sept/Makefile | 2 +- sept/sept-secondary/Makefile | 173 + sept/sept-secondary/linker.ld | 192 + sept/sept-secondary/linker.specs | 7 + sept/sept-secondary/sept_sign.py | 38 + sept/sept-secondary/src/apb_misc.h | 81 + sept/sept-secondary/src/btn.c | 82 + sept/sept-secondary/src/btn.h | 30 + sept/sept-secondary/src/car.c | 139 + sept/sept-secondary/src/car.h | 505 + sept/sept-secondary/src/chainloader.c | 51 + sept/sept-secondary/src/chainloader.h | 42 + sept/sept-secondary/src/di.c | 267 + sept/sept-secondary/src/di.h | 368 + sept/sept-secondary/src/di.inl | 563 + sept/sept-secondary/src/display/cfb_console.c | 1619 ++ sept/sept-secondary/src/display/video_fb.h | 57 + .../src/display/video_font_large.h | 6181 ++++++ .../src/display/video_font_small.h | 4630 +++++ sept/sept-secondary/src/emc.h | 1089 ++ sept/sept-secondary/src/exception_handlers.c | 81 + sept/sept-secondary/src/exception_handlers.h | 28 + .../src/exception_handlers_asm.s | 125 + sept/sept-secondary/src/flow.h | 31 + sept/sept-secondary/src/fs_utils.c | 136 + sept/sept-secondary/src/fs_utils.h | 35 + sept/sept-secondary/src/fuse.c | 260 + sept/sept-secondary/src/fuse.h | 213 + sept/sept-secondary/src/gpio.c | 145 + sept/sept-secondary/src/gpio.h | 127 + sept/sept-secondary/src/hwinit.c | 298 + sept/sept-secondary/src/hwinit.h | 27 + sept/sept-secondary/src/i2c.c | 219 + sept/sept-secondary/src/i2c.h | 101 + sept/sept-secondary/src/init.c | 146 + .../src/lib/fatfs/00history.txt | 324 + .../sept-secondary/src/lib/fatfs/00readme.txt | 22 + sept/sept-secondary/src/lib/fatfs/diskio.c | 95 + sept/sept-secondary/src/lib/fatfs/diskio.h | 80 + sept/sept-secondary/src/lib/fatfs/ff.c | 6535 +++++++ sept/sept-secondary/src/lib/fatfs/ff.h | 376 + sept/sept-secondary/src/lib/fatfs/ffconf.h | 289 + sept/sept-secondary/src/lib/fatfs/ffsystem.c | 171 + sept/sept-secondary/src/lib/fatfs/ffunicode.c | 15597 ++++++++++++++++ sept/sept-secondary/src/lib/fatfs/integer.h | 36 + sept/sept-secondary/src/lib/ini.c | 269 + sept/sept-secondary/src/lib/ini.h | 130 + sept/sept-secondary/src/lib/log.c | 127 + sept/sept-secondary/src/lib/log.h | 43 + sept/sept-secondary/src/lib/lz.c | 377 + sept/sept-secondary/src/lib/lz.h | 51 + sept/sept-secondary/src/lib/vsprintf.c | 1676 ++ sept/sept-secondary/src/lib/vsprintf.h | 28 + sept/sept-secondary/src/main.c | 105 + sept/sept-secondary/src/max77620.h | 357 + sept/sept-secondary/src/max7762x.c | 178 + sept/sept-secondary/src/max7762x.h | 68 + sept/sept-secondary/src/mc.c | 169 + sept/sept-secondary/src/mc.h | 598 + sept/sept-secondary/src/panic.c | 98 + sept/sept-secondary/src/panic.h | 34 + sept/sept-secondary/src/panic_color.h | 39 + sept/sept-secondary/src/pinmux.h | 211 + sept/sept-secondary/src/pmc.h | 626 + sept/sept-secondary/src/preprocessor.h | 207 + sept/sept-secondary/src/sdmmc/mmc.h | 449 + sept/sept-secondary/src/sdmmc/sd.h | 155 + sept/sept-secondary/src/sdmmc/sdmmc.c | 1543 ++ sept/sept-secondary/src/sdmmc/sdmmc.h | 179 + sept/sept-secondary/src/sdmmc/sdmmc_core.c | 1979 ++ sept/sept-secondary/src/sdmmc/sdmmc_core.h | 306 + sept/sept-secondary/src/sdmmc/sdmmc_tegra.h | 172 + sept/sept-secondary/src/sdram.c | 578 + sept/sept-secondary/src/sdram.h | 25 + sept/sept-secondary/src/sdram.inl | 1152 ++ sept/sept-secondary/src/sdram_lp0.c | 1125 ++ sept/sept-secondary/src/sdram_lz.inl | 124 + sept/sept-secondary/src/sdram_param_t210.h | 933 + .../sept-secondary/src/sdram_param_t210_lp0.h | 964 + sept/sept-secondary/src/se.c | 649 + sept/sept-secondary/src/se.h | 219 + sept/sept-secondary/src/stage2.c | 124 + sept/sept-secondary/src/stage2.h | 55 + sept/sept-secondary/src/start.s | 86 + sept/sept-secondary/src/sysctr0.h | 44 + sept/sept-secondary/src/sysreg.h | 48 + sept/sept-secondary/src/timers.h | 94 + sept/sept-secondary/src/uart.c | 72 + sept/sept-secondary/src/uart.h | 170 + sept/sept-secondary/src/utils.c | 150 + sept/sept-secondary/src/utils.h | 131 + 94 files changed, 58543 insertions(+), 5 deletions(-) create mode 100644 sept/sept-secondary/Makefile create mode 100644 sept/sept-secondary/linker.ld create mode 100644 sept/sept-secondary/linker.specs create mode 100644 sept/sept-secondary/sept_sign.py create mode 100644 sept/sept-secondary/src/apb_misc.h create mode 100644 sept/sept-secondary/src/btn.c create mode 100644 sept/sept-secondary/src/btn.h create mode 100644 sept/sept-secondary/src/car.c create mode 100644 sept/sept-secondary/src/car.h create mode 100644 sept/sept-secondary/src/chainloader.c create mode 100644 sept/sept-secondary/src/chainloader.h create mode 100644 sept/sept-secondary/src/di.c create mode 100644 sept/sept-secondary/src/di.h create mode 100644 sept/sept-secondary/src/di.inl create mode 100644 sept/sept-secondary/src/display/cfb_console.c create mode 100644 sept/sept-secondary/src/display/video_fb.h create mode 100644 sept/sept-secondary/src/display/video_font_large.h create mode 100644 sept/sept-secondary/src/display/video_font_small.h create mode 100644 sept/sept-secondary/src/emc.h create mode 100644 sept/sept-secondary/src/exception_handlers.c create mode 100644 sept/sept-secondary/src/exception_handlers.h create mode 100644 sept/sept-secondary/src/exception_handlers_asm.s create mode 100644 sept/sept-secondary/src/flow.h create mode 100644 sept/sept-secondary/src/fs_utils.c create mode 100644 sept/sept-secondary/src/fs_utils.h create mode 100644 sept/sept-secondary/src/fuse.c create mode 100644 sept/sept-secondary/src/fuse.h create mode 100644 sept/sept-secondary/src/gpio.c create mode 100644 sept/sept-secondary/src/gpio.h create mode 100644 sept/sept-secondary/src/hwinit.c create mode 100644 sept/sept-secondary/src/hwinit.h create mode 100644 sept/sept-secondary/src/i2c.c create mode 100644 sept/sept-secondary/src/i2c.h create mode 100644 sept/sept-secondary/src/init.c create mode 100644 sept/sept-secondary/src/lib/fatfs/00history.txt create mode 100644 sept/sept-secondary/src/lib/fatfs/00readme.txt create mode 100644 sept/sept-secondary/src/lib/fatfs/diskio.c create mode 100644 sept/sept-secondary/src/lib/fatfs/diskio.h create mode 100644 sept/sept-secondary/src/lib/fatfs/ff.c create mode 100644 sept/sept-secondary/src/lib/fatfs/ff.h create mode 100644 sept/sept-secondary/src/lib/fatfs/ffconf.h create mode 100644 sept/sept-secondary/src/lib/fatfs/ffsystem.c create mode 100644 sept/sept-secondary/src/lib/fatfs/ffunicode.c create mode 100644 sept/sept-secondary/src/lib/fatfs/integer.h create mode 100644 sept/sept-secondary/src/lib/ini.c create mode 100644 sept/sept-secondary/src/lib/ini.h create mode 100644 sept/sept-secondary/src/lib/log.c create mode 100644 sept/sept-secondary/src/lib/log.h create mode 100644 sept/sept-secondary/src/lib/lz.c create mode 100644 sept/sept-secondary/src/lib/lz.h create mode 100644 sept/sept-secondary/src/lib/vsprintf.c create mode 100644 sept/sept-secondary/src/lib/vsprintf.h create mode 100644 sept/sept-secondary/src/main.c create mode 100644 sept/sept-secondary/src/max77620.h create mode 100644 sept/sept-secondary/src/max7762x.c create mode 100644 sept/sept-secondary/src/max7762x.h create mode 100644 sept/sept-secondary/src/mc.c create mode 100644 sept/sept-secondary/src/mc.h create mode 100644 sept/sept-secondary/src/panic.c create mode 100644 sept/sept-secondary/src/panic.h create mode 100644 sept/sept-secondary/src/panic_color.h create mode 100644 sept/sept-secondary/src/pinmux.h create mode 100644 sept/sept-secondary/src/pmc.h create mode 100644 sept/sept-secondary/src/preprocessor.h create mode 100644 sept/sept-secondary/src/sdmmc/mmc.h create mode 100644 sept/sept-secondary/src/sdmmc/sd.h create mode 100644 sept/sept-secondary/src/sdmmc/sdmmc.c create mode 100644 sept/sept-secondary/src/sdmmc/sdmmc.h create mode 100644 sept/sept-secondary/src/sdmmc/sdmmc_core.c create mode 100644 sept/sept-secondary/src/sdmmc/sdmmc_core.h create mode 100644 sept/sept-secondary/src/sdmmc/sdmmc_tegra.h create mode 100644 sept/sept-secondary/src/sdram.c create mode 100644 sept/sept-secondary/src/sdram.h create mode 100644 sept/sept-secondary/src/sdram.inl create mode 100644 sept/sept-secondary/src/sdram_lp0.c create mode 100644 sept/sept-secondary/src/sdram_lz.inl create mode 100644 sept/sept-secondary/src/sdram_param_t210.h create mode 100644 sept/sept-secondary/src/sdram_param_t210_lp0.h create mode 100644 sept/sept-secondary/src/se.c create mode 100644 sept/sept-secondary/src/se.h create mode 100644 sept/sept-secondary/src/stage2.c create mode 100644 sept/sept-secondary/src/stage2.h create mode 100644 sept/sept-secondary/src/start.s create mode 100644 sept/sept-secondary/src/sysctr0.h create mode 100644 sept/sept-secondary/src/sysreg.h create mode 100644 sept/sept-secondary/src/timers.h create mode 100644 sept/sept-secondary/src/uart.c create mode 100644 sept/sept-secondary/src/uart.h create mode 100644 sept/sept-secondary/src/utils.c create mode 100644 sept/sept-secondary/src/utils.h diff --git a/.gitignore b/.gitignore index d759ff7f0..20467a117 100644 --- a/.gitignore +++ b/.gitignore @@ -73,10 +73,15 @@ dkms.conf *.nam *.til +# KEYS file for sept-secondary. +*.pyc +sept/sept-secondary/KEYS.py + .**/ # NOTE: make sure to make exceptions to this pattern when needed! *.bin +*.enc **/out **/build diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 930abf2b0..7273cc10d 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -88,7 +88,7 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ $(AMS)/exosphere $(AMS)/exosphere/lp0fw $(AMS)/exosphere/rebootstub \ $(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \ - $(KIPDIRS) + $(AMS)/sept/sept-secondary $(KIPDIRS) export DEPSDIR := $(CURDIR)/$(BUILD) @@ -98,7 +98,7 @@ SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) KIPFILES := loader.kip pm.kip sm.kip ams_mitm.kip boot_100.kip boot_200.kip BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \ exosphere.bin lp0fw.bin rebootstub.bin thermosphere.bin splash_screen.bmp \ - sept-primary.bin \ + sept-primary.bin sept-secondary.enc \ $(KIPFILES) #--------------------------------------------------------------------------------- @@ -198,6 +198,11 @@ sept_primary.bin.o sept_primary_bin.h: sept-primary.bin @echo $(notdir $<) @$(_bin2o) +sept_secondary.enc.o sept_secondary_enc.h: sept-secondary.enc +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(_bin2o) + %.bin.o %_bin.h: %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 0ca6e42a6..71968dd16 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -50,6 +50,7 @@ #define u8 uint8_t #define u32 uint32_t #include "exosphere_bin.h" +#include "sept_secondary_enc.h" #include "lp0fw_bin.h" #include "lib/log.h" #undef u8 @@ -413,8 +414,7 @@ uint32_t nxboot_main(void) { if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_700) { /* TODO: Detect when we have been loaded by sept-secondary, and thus have keys provided for us. */ - static const uint8_t sept_secondary[0x0] = { /* TODO: link-time magic */ }; - reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary, sizeof(sept_secondary)); + reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size); } print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); diff --git a/sept/Makefile b/sept/Makefile index 632a5cd13..2c9cafa66 100644 --- a/sept/Makefile +++ b/sept/Makefile @@ -1,4 +1,4 @@ -SUBFOLDERS := sept-primary +SUBFOLDERS := sept-primary sept-secondary TOPTARGETS := all clean diff --git a/sept/sept-secondary/Makefile b/sept/sept-secondary/Makefile new file mode 100644 index 000000000..015822d91 --- /dev/null +++ b/sept/sept-secondary/Makefile @@ -0,0 +1,173 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM") +endif + +TOPDIR ?= $(CURDIR) + +AMS := $(TOPDIR)/../../ +include $(DEVKITARM)/base_rules + +AMSBRANCH := $(shell git symbolic-ref --short HEAD) +AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) + +ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) + AMSREV := $(AMSREV)-dirty +endif + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := src src/sdmmc src/lib src/lib/fatfs src/display +DATA := data +INCLUDES := include ../../common/include + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork +DEFINES := -D__BPMP__ -DFUSEE_STAGE1_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" + +CFLAGS := \ + -g \ + -O2 \ + -fomit-frame-pointer \ + -ffunction-sections \ + -fdata-sections \ + -std=gnu11 \ + -Werror \ + -Wall \ + -fstrict-volatile-bitfields \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(AMS)/exosphere/rebootstub + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) rebootstub.bin + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +.PHONY: $(BUILD) clean all check_rebootstub + +#--------------------------------------------------------------------------------- +all: check_rebootstub $(BUILD) + +check_rebootstub: + @$(MAKE) -C $(AMS)/exosphere/rebootstub all + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @$(MAKE) -C $(AMS)/exosphere/rebootstub clean + @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).enc + +$(OUTPUT).enc : $(OUTPUT).bin + @python $(TOPDIR)/sept_sign.py $< $@ + @echo built ... $(notdir $@) + +$(OUTPUT).bin : $(OUTPUT).elf + $(OBJCOPY) -S -O binary $< $@ + @echo built ... $(notdir $@) + +$(OUTPUT).elf : $(OFILES) + +%.elf: $(OFILES) + @echo linking $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + @$(NM) -CSn $@ > $(notdir $*.lst) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h: %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/sept/sept-secondary/linker.ld b/sept/sept-secondary/linker.ld new file mode 100644 index 000000000..b442fd3b6 --- /dev/null +++ b/sept/sept-secondary/linker.ld @@ -0,0 +1,192 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +PHDRS +{ + crt0 PT_LOAD; + chainloader PT_LOAD; + main PT_LOAD; +} + +/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */ +MEMORY +{ + NULL : ORIGIN = 0x00000000, LENGTH = 0x1000 + main : ORIGIN = 0x40010000, LENGTH = 0x20000 + low_iram : ORIGIN = 0x40003000, LENGTH = 0x8000 +} + +SECTIONS +{ + PROVIDE(__start__ = 0x40010000); + PROVIDE(__stack_top__ = 0x40010000); + PROVIDE(__stack_bottom__ = 0x4000C000); + PROVIDE(__heap_start__ = 0); + PROVIDE(__heap_end__ = 0); + + . = __start__; + + .crt0 : + { + KEEP( *(.text.start) ) + KEEP( *(.init) ) + . = ALIGN(32); + } >main :crt0 + + .chainloader_loadable : + { + . = ALIGN(32); + PROVIDE (__chainloader_start__ = ABSOLUTE(.)); + PROVIDE (__chainloader_lma__ = LOADADDR(.chainloader_loadable)); + KEEP(*(.chainloader.text.start)) + chainloader.o(.text*) + chainloader.o(.rodata*) + chainloader.o(.data*) + . = ALIGN(32); + } >low_iram AT>main :chainloader + + .chainloader_bss (NOLOAD) : + { + . = ALIGN(32); + PROVIDE (__chainloader_bss_start__ = ABSOLUTE(.)); + chainloader.o(.bss* COMMON) + . = ALIGN(32); + PROVIDE (__chainloader_end__ = ABSOLUTE(.)); + } >low_iram :NONE + + .text : + { + . = ALIGN(32); + /* .text */ + *(.text) + *(.text.*) + *(.glue_7) + *(.glue_7t) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.t*) + + /* .fini */ + KEEP( *(.fini) ) + . = ALIGN(8); + } >main :main + + .rodata : + { + *(.rodata) + *(.roda) + *(.rodata.*) + *all.rodata*(*) + *(.gnu.linkonce.r*) + SORT(CONSTRUCTORS) + . = ALIGN(8); + } >main + + .preinit_array : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } >main + + .init_array ALIGN(4) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } >main + + .fini_array ALIGN(4) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } >main + + .ctors ALIGN(4) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >main + + .dtors ALIGN(4) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >main + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main + ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main + + .data : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + . = ALIGN(32); + } >main + + .bss (NOLOAD) : + { + . = ALIGN(32); + PROVIDE (__bss_start__ = ABSOLUTE(.)); + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(32); + PROVIDE (__bss_end__ = ABSOLUTE(.)); + } >main :NONE + __end__ = ABSOLUTE(.) ; + + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note) } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } +} diff --git a/sept/sept-secondary/linker.specs b/sept/sept-secondary/linker.specs new file mode 100644 index 000000000..300990418 --- /dev/null +++ b/sept/sept-secondary/linker.specs @@ -0,0 +1,7 @@ +%rename link old_link + +*link: +%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections + +*startfile: +crti%O%s crtbegin%O%s diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py new file mode 100644 index 000000000..91d966d11 --- /dev/null +++ b/sept/sept-secondary/sept_sign.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +import sys +from struct import pack as pk, unpack as up +from Crypto.Cipher import AES +from Crypto.Hash import CMAC +import KEYS + +def sign_encrypt_code(code, sig_key, enc_key, iv): + # Pad with 0x20 of zeroes. + code += '\x00' * 0x20 + code_len = len(code) + code_len += 0xFFF + code_len &= ~0xFFF + code += '\x00' * (code_len - len(code)) + + # Add empty trustzone, warmboot segments. + code += '\x00'*0x1FE0 + pk11_hdr = 'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0) + pk11 = pk11_hdr + code + enc_pk11 = AES.new(enc_key, AES.MODE_CBC, iv).encrypt(pk11) + enc_pk11 = pk('<IIII', len(pk11), 0, 0, 0) + iv + enc_pk11 + enc_pk11 += CMAC.new(sig_key, enc_pk11, AES).digest() + return enc_pk11 + +def main(argc, argv): + if argc != 3: + print('Usage: %s input output' % argv[0]) + return 1 + with open(argv[1], 'rb') as f: + code = f.read() + assert (len(code) & 0xF) == 0 + # TODO: Support dev unit crypto + with open(argv[2], 'wb') as f: + f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV)) + return 0 + +if __name__ == '__main__': + sys.exit(main(len(sys.argv), sys.argv)) \ No newline at end of file diff --git a/sept/sept-secondary/src/apb_misc.h b/sept/sept-secondary/src/apb_misc.h new file mode 100644 index 000000000..b2e8b1dff --- /dev/null +++ b/sept/sept-secondary/src/apb_misc.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_APB_MISC_H +#define FUSEE_APB_MISC_H + +#include <stdint.h> + +#define APB_MISC_BASE 0x70000000 +#define APB_PADCTL_BASE 0x70000810 +#define MAKE_APB_MISC_REG(n) MAKE_REG32(APB_MISC_BASE + n) +#define MAKE_APB_PADCTL_REG(n) MAKE_REG32(APB_PADCTL_BASE + n) + +#define APB_MISC_PP_PINMUX_GLOBAL_0 MAKE_APB_MISC_REG(0x40) +#define APB_MISC_GP_WIFI_EN_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB64) +#define APB_MISC_GP_WIFI_RST_CFGPADCTRL_0 MAKE_APB_MISC_REG(0xB68) + +#define SDMMC1_PAD_CAL_DRVUP_SHIFT (20) +#define SDMMC1_PAD_CAL_DRVDN_SHIFT (12) +#define SDMMC1_PAD_CAL_DRVUP_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVUP_SHIFT) +#define SDMMC1_PAD_CAL_DRVDN_MASK (0x7Fu << SDMMC1_PAD_CAL_DRVDN_SHIFT) + +#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT (8) +#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT (2) +#define CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT) +#define CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK (0x3Fu << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT) + +#define PADCTL_SDMMC1_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC3_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC2_ENABLE_DATA_IN (0xFF << 8) +#define PADCTL_SDMMC2_ENABLE_CLK_IN (0x3 << 4) +#define PADCTL_SDMMC2_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC4_ENABLE_DATA_IN (0xFF << 8) +#define PADCTL_SDMMC4_ENABLE_CLK_IN (0x3 << 4) +#define PADCTL_SDMMC4_DEEP_LOOPBACK (1 << 0) +#define PADCTL_SDMMC1_CD_SOURCE (1 << 0) +#define PADCTL_SDMMC1_WP_SOURCE (1 << 1) +#define PADCTL_SDMMC3_CD_SOURCE (1 << 2) +#define PADCTL_SDMMC3_WP_SOURCE (1 << 3) + +typedef struct { + uint32_t asdbgreg; /* 0x810 */ + uint32_t reserved0[0x31]; + uint32_t sdmmc1_clk_lpbk_control; /* 0x8D4 */ + uint32_t sdmmc3_clk_lpbk_control; /* 0x8D8 */ + uint32_t emmc2_pad_cfg_control; /* 0x8DC */ + uint32_t emmc4_pad_cfg_control; /* 0x8E0 */ + uint32_t _todo0[0x6E]; + uint32_t sdmmc1_pad_cfgpadctrl; /* 0xA98 */ + uint32_t emmc2_pad_cfgpadctrl; /* 0xA9C */ + uint32_t emmc2_pad_drv_type_cfgpadctrl; /* 0xAA0 */ + uint32_t emmc2_pad_pupd_cfgpadctrl; /* 0xAA4 */ + uint32_t _todo1[0x03]; + uint32_t sdmmc3_pad_cfgpadctrl; /* 0xAB0 */ + uint32_t emmc4_pad_cfgpadctrl; /* 0xAB4 */ + uint32_t emmc4_pad_drv_type_cfgpadctrl; /* 0xAB8 */ + uint32_t emmc4_pad_pupd_cfgpadctrl; /* 0xABC */ + uint32_t _todo2[0x2E]; + uint32_t vgpio_gpio_mux_sel; /* 0xB74 */ + uint32_t qspi_sck_lpbk_control; /* 0xB78 */ +} tegra_padctl_t; + +static inline volatile tegra_padctl_t *padctl_get_regs(void) +{ + return (volatile tegra_padctl_t *)APB_PADCTL_BASE; +} + +#endif diff --git a/sept/sept-secondary/src/btn.c b/sept/sept-secondary/src/btn.c new file mode 100644 index 000000000..f845c350e --- /dev/null +++ b/sept/sept-secondary/src/btn.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "btn.h" +#include "i2c.h" +#include "gpio.h" +#include "timers.h" + +uint32_t btn_read() +{ + uint32_t res = 0; + + if (!gpio_read(GPIO_BUTTON_VOL_DOWN)) + res |= BTN_VOL_DOWN; + + if (!gpio_read(GPIO_BUTTON_VOL_UP)) + res |= BTN_VOL_UP; + + uint32_t val = 0; + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x15, &val, 1)) + { + if (val & 0x4) + res |= BTN_POWER; + } + + return res; +} + +uint32_t btn_wait() +{ + uint32_t res = 0, btn = btn_read(); + int pwr = 0; + + if (btn & BTN_POWER) + { + pwr = 1; + btn &= ~BTN_POWER; + } + + do + { + res = btn_read(); + + if (!(res & BTN_POWER) && pwr) + pwr = 0; + else if (pwr) + res &= ~BTN_POWER; + } while (btn == res); + + return res; +} + +uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask) +{ + uint32_t timeout = get_time_ms() + time_ms; + uint32_t res = btn_read() & mask; + + do + { + if (!(res & mask)) + res = btn_read() & mask; + } while (get_time_ms() < timeout); + + return res; +} \ No newline at end of file diff --git a/sept/sept-secondary/src/btn.h b/sept/sept-secondary/src/btn.h new file mode 100644 index 000000000..04f569b94 --- /dev/null +++ b/sept/sept-secondary/src/btn.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_BTN_H_ +#define FUSEE_BTN_H_ + +#define BTN_POWER 0x1 +#define BTN_VOL_DOWN 0x2 +#define BTN_VOL_UP 0x4 + +uint32_t btn_read(); +uint32_t btn_wait(); +uint32_t btn_wait_timeout(uint32_t time_ms, uint32_t mask); + +#endif \ No newline at end of file diff --git a/sept/sept-secondary/src/car.c b/sept/sept-secondary/src/car.c new file mode 100644 index 000000000..935dea922 --- /dev/null +++ b/sept/sept-secondary/src/car.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "car.h" +#include "timers.h" +#include "utils.h" + +static inline uint32_t get_clk_source_reg(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0x178; + case CARDEVICE_UARTB: return 0x17C; + case CARDEVICE_UARTC: return 0x1A0; + case CARDEVICE_I2C1: return 0x124; + case CARDEVICE_I2C5: return 0x128; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0x42C; + case CARDEVICE_HOST1X: return 0x180; + case CARDEVICE_TSEC: return 0x1F4; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 0x410; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 0x1D4; + case CARDEVICE_ACTMON: return 0x3E8; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static inline uint32_t get_clk_source_val(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_UARTC: return 0; + case CARDEVICE_I2C1: return 6; + case CARDEVICE_I2C5: return 6; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0; + case CARDEVICE_HOST1X: return 4; + case CARDEVICE_TSEC: return 0; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 0; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 0; + case CARDEVICE_ACTMON: return 6; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static inline uint32_t get_clk_source_div(CarDevice dev) { + switch (dev) { + case CARDEVICE_UARTA: return 0; + case CARDEVICE_UARTB: return 0; + case CARDEVICE_UARTC: return 0; + case CARDEVICE_I2C1: return 0; + case CARDEVICE_I2C5: return 0; + case CARDEVICE_UNK: return 0; + case CARDEVICE_SE: return 0; + case CARDEVICE_HOST1X: return 3; + case CARDEVICE_TSEC: return 2; + case CARDEVICE_SOR_SAFE: return 0; + case CARDEVICE_SOR0: return 0; + case CARDEVICE_SOR1: return 2; + case CARDEVICE_KFUSE: return 0; + case CARDEVICE_CL_DVFS: return 0; + case CARDEVICE_CORESIGHT: return 4; + case CARDEVICE_ACTMON: return 0; + case CARDEVICE_BPMP: return 0; + default: generic_panic(); + } +} + +static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x010, 0x014, 0x018, 0x360, 0x364, 0x280, 0x298}; +static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x004, 0x008, 0x00C, 0x358, 0x35C, 0x28C, 0x2A4}; + +void clk_enable(CarDevice dev) { + uint32_t clk_source_reg; + if ((clk_source_reg = get_clk_source_reg(dev))) { + MAKE_CAR_REG(clk_source_reg) = (get_clk_source_val(dev) << 29) | get_clk_source_div(dev); + } + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void clk_disable(CarDevice dev) { + MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void rst_enable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F); +} + +void rst_disable(CarDevice dev) { + MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) &= ~(BIT(dev & 0x1F)); +} + +void clkrst_enable(CarDevice dev) { + clk_enable(dev); + rst_disable(dev); +} + +void clkrst_disable(CarDevice dev) { + rst_enable(dev); + clk_disable(dev); +} + +void clkrst_reboot(CarDevice dev) { + clkrst_disable(dev); + if (dev == CARDEVICE_KFUSE) { + /* Workaround for KFUSE clock. */ + clk_enable(dev); + udelay(100); + rst_disable(dev); + udelay(200); + } else { + clkrst_enable(dev); + } +} + +void clkrst_enable_fuse_regs(bool enable) { + volatile tegra_car_t *car = car_get_regs(); + car->misc_clk_enb = ((car->misc_clk_enb & 0xEFFFFFFF) | ((enable & 1) << 28)); +} diff --git a/sept/sept-secondary/src/car.h b/sept/sept-secondary/src/car.h new file mode 100644 index 000000000..4135a54ef --- /dev/null +++ b/sept/sept-secondary/src/car.h @@ -0,0 +1,505 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_CAR_H +#define FUSEE_CAR_H + +#include <stdint.h> +#include <stdbool.h> + +#define CAR_BASE 0x60006000 +#define MAKE_CAR_REG(n) MAKE_REG32(CAR_BASE + n) + +#define CLK_L_SDMMC1 (1 << 14) +#define CLK_L_SDMMC2 (1 << 9) +#define CLK_U_SDMMC3 (1 << 5) +#define CLK_L_SDMMC4 (1 << 15) + +#define CLK_SOURCE_MASK (0b111 << 29) +#define CLK_SOURCE_FIRST (0b000 << 29) +#define CLK_DIVIDER_MASK (0xff << 0) +#define CLK_DIVIDER_UNITY (0x00 << 0) + +#define NUM_CAR_BANKS 7 + +/* Clock and reset devices. */ +typedef enum { + CARDEVICE_UARTA = ((0 << 5) | 0x6), + CARDEVICE_UARTB = ((0 << 5) | 0x7), + CARDEVICE_UARTC = ((1 << 5) | 0x17), + CARDEVICE_I2C1 = ((0 << 5) | 0xC), + CARDEVICE_I2C5 = ((1 << 5) | 0xF), + CARDEVICE_UNK = ((3 << 5) | 0x1E), + CARDEVICE_SE = ((3 << 5) | 0x1F), + CARDEVICE_HOST1X = ((0 << 5) | 0x1C), + CARDEVICE_TSEC = ((2 << 5) | 0x13), + CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E), + CARDEVICE_SOR0 = ((5 << 5) | 0x16), + CARDEVICE_SOR1 = ((5 << 5) | 0x17), + CARDEVICE_KFUSE = ((1 << 5) | 0x8), + CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B), + CARDEVICE_CORESIGHT = ((2 << 5) | 0x9), + CARDEVICE_ACTMON = ((3 << 5) | 0x17), + CARDEVICE_BPMP = ((0 << 5) | 0x1) +} CarDevice; + +/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */ +typedef struct { + uint32_t rst_src; /* _RST_SOURCE_0, 0x00 */ + + /* _RST_DEVICES_L/H/U_0 0x4-0xc */ + uint32_t rst_dev_l; + uint32_t rst_dev_h; + uint32_t rst_dev_u; + + /* _CLK_OUT_ENB_L/H/U_0 0x10-0x18 */ + uint32_t clk_out_enb_l; + uint32_t clk_out_enb_h; + uint32_t clk_out_enb_u; + + uint32_t _0x1C; + uint32_t cclk_brst_pol; /* _CCLK_BURST_POLICY_0, 0x20 */ + uint32_t super_cclk_div; /* _SUPER_CCLK_DIVIDER_0, 0x24 */ + uint32_t sclk_brst_pol; /* _SCLK_BURST_POLICY_0, 0x28 */ + uint32_t super_sclk_div; /* _SUPER_SCLK_DIVIDER_0, 0x2c */ + uint32_t clk_sys_rate; /* _CLK_SYSTEM_RATE_0, 0x30 */ + uint32_t prog_dly_clk; /* _PROG_DLY_CLK_0, 0x34 */ + uint32_t aud_sync_clk_rate; /* _AUDIO_SYNC_CLK_RATE_0, 0x38 */ + uint32_t _0x3C; + uint32_t cop_clk_skip_plcy; /* _COP_CLK_SKIP_POLICY_0, 0x40 */ + uint32_t clk_mask_arm; /* _CLK_MASK_ARM_0, 0x44 */ + uint32_t misc_clk_enb; /* _MISC_CLK_ENB_0, 0x48 */ + uint32_t clk_cpu_cmplx; /* _CLK_CPU_CMPLX_0, 0x4c */ + uint32_t osc_ctrl; /* _OSC_CTRL_0, 0x50 */ + uint32_t pll_lfsr; /* _PLL_LFSR_0, 0x54 */ + uint32_t osc_freq_det; /* _OSC_FREQ_DET_0, 0x58 */ + uint32_t osc_freq_det_stat; /* _OSC_FREQ_DET_STATUS_0, 0x5c */ + uint32_t _0x60[2]; + uint32_t plle_ss_cntl; /* _PLLE_SS_CNTL_0, 0x68 */ + uint32_t plle_misc1; /* _PLLE_MISC1_0, 0x6c */ + uint32_t _0x70[4]; + + /* PLLC 0x80-0x8c */ + uint32_t pllc_base; + uint32_t pllc_out; + uint32_t pllc_misc0; + uint32_t pllc_misc1; + + /* PLLM 0x90-0x9c */ + uint32_t pllm_base; + uint32_t pllm_out; + uint32_t pllm_misc1; + uint32_t pllm_misc2; + + /* PLLP 0xa0-0xac */ + uint32_t pllp_base; + uint32_t pllp_outa; + uint32_t pllp_outb; + uint32_t pllp_misc; + + /* PLLA 0xb0-0xbc */ + uint32_t plla_base; + uint32_t plla_out; + uint32_t plla_misc0; + uint32_t plla_misc1; + + /* PLLU 0xc0-0xcc */ + uint32_t pllu_base; + uint32_t pllu_out; + uint32_t pllu_misc1; + uint32_t pllu_misc2; + + /* PLLD 0xd0-0xdc */ + uint32_t plld_base; + uint32_t plld_out; + uint32_t plld_misc1; + uint32_t plld_misc2; + + /* PLLX 0xe0-0xe4 */ + uint32_t pllx_base; + uint32_t pllx_misc; + + /* PLLE 0xe8-0xf4 */ + uint32_t plle_base; + uint32_t plle_misc; + uint32_t plle_ss_cntl1; + uint32_t plle_ss_cntl2; + + uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */ + uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */ + + uint32_t clk_source_i2s2; /* _CLK_SOURCE_I2S2_0, 0x100 */ + uint32_t clk_source_i2s3; /* _CLK_SOURCE_I2S3_0, 0x104 */ + uint32_t clk_source_spdif_out; /* _CLK_SOURCE_SPDIF_OUT_0, 0x108 */ + uint32_t clk_source_spdif_in; /* _CLK_SOURCE_SPDIF_IN_0, 0x10c */ + uint32_t clk_source_pwm; /* _CLK_SOURCE_PWM_0, 0x110 */ + uint32_t _0x114; + uint32_t clk_source_spi2; /* _CLK_SOURCE_SPI2_0, 0x118 */ + uint32_t clk_source_spi3; /* _CLK_SOURCE_SPI3_0, 0x11c */ + uint32_t _0x120; + uint32_t clk_source_i2c1; /* _CLK_SOURCE_I2C1_0, 0x124 */ + uint32_t clk_source_i2c5; /* _CLK_SOURCE_I2C5_0, 0x128 */ + uint32_t _0x12c[2]; + uint32_t clk_source_spi1; /* _CLK_SOURCE_SPI1_0, 0x134 */ + uint32_t clk_source_disp1; /* _CLK_SOURCE_DISP1_0, 0x138 */ + uint32_t clk_source_disp2; /* _CLK_SOURCE_DISP2_0, 0x13c */ + uint32_t _0x140; + uint32_t clk_source_isp; /* _CLK_SOURCE_ISP_0, 0x144 */ + uint32_t clk_source_vi; /* _CLK_SOURCE_VI_0, 0x148 */ + uint32_t _0x14c; + uint32_t clk_source_sdmmc1; /* _CLK_SOURCE_SDMMC1_0, 0x150 */ + uint32_t clk_source_sdmmc2; /* _CLK_SOURCE_SDMMC2_0, 0x154 */ + uint32_t _0x158[3]; + uint32_t clk_source_sdmmc4; /* _CLK_SOURCE_SDMMC4_0, 0x164 */ + uint32_t _0x168[4]; + uint32_t clk_source_uarta; /* _CLK_SOURCE_UARTA_0, 0x178 */ + uint32_t clk_source_uartb; /* _CLK_SOURCE_UARTB_0, 0x17c */ + uint32_t clk_source_host1x; /* _CLK_SOURCE_HOST1X_0, 0x180 */ + uint32_t _0x184[5]; + uint32_t clk_source_i2c2; /* _CLK_SOURCE_I2C2_0, 0x198 */ + uint32_t clk_source_emc; /* _CLK_SOURCE_EMC_0, 0x19c */ + uint32_t clk_source_uartc; /* _CLK_SOURCE_UARTC_0, 0x1a0 */ + uint32_t _0x1a4; + uint32_t clk_source_vi_sensor; /* _CLK_SOURCE_VI_SENSOR_0, 0x1a8 */ + uint32_t _0x1ac[2]; + uint32_t clk_source_spi4; /* _CLK_SOURCE_SPI4_0, 0x1b4 */ + uint32_t clk_source_i2c3; /* _CLK_SOURCE_I2C3_0, 0x1b8 */ + uint32_t clk_source_sdmmc3; /* _CLK_SOURCE_SDMMC3_0, 0x1bc */ + uint32_t clk_source_uartd; /* _CLK_SOURCE_UARTD_0, 0x1c0 */ + uint32_t _0x1c4[2]; + uint32_t clk_source_owr; /* _CLK_SOURCE_OWR_0, 0x1cc */ + uint32_t _0x1d0; + uint32_t clk_source_csite; /* _CLK_SOURCE_CSITE_0, 0x1d4 */ + uint32_t clk_source_i2s1; /* _CLK_SOURCE_I2S1_0, 0x1d8 */ + uint32_t clk_source_dtv; /* _CLK_SOURCE_DTV_0, 0x1dc */ + uint32_t _0x1e0[5]; + uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */ + uint32_t _0x1f8; + + uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */ + uint32_t _0x200[32]; + + uint32_t clk_out_enb_x; /* _CLK_OUT_ENB_X_0, 0x280 */ + uint32_t clk_enb_x_set; /* _CLK_ENB_X_SET_0, 0x284 */ + uint32_t clk_enb_x_clr; /* _CLK_ENB_X_CLR_0, 0x288 */ + + uint32_t rst_devices_x; /* _RST_DEVICES_X_0, 0x28c */ + uint32_t rst_dev_x_set; /* _RST_DEV_X_SET_0, 0x290 */ + uint32_t rst_dev_x_clr; /* _RST_DEV_X_CLR_0, 0x294 */ + + uint32_t clk_out_enb_y; /* _CLK_OUT_ENB_Y_0, 0x298 */ + uint32_t clk_enb_y_set; /* _CLK_ENB_Y_SET_0, 0x29c */ + uint32_t clk_enb_y_clr; /* _CLK_ENB_Y_CLR_0, 0x2a0 */ + + uint32_t rst_devices_y; /* _RST_DEVICES_Y_0, 0x2a4 */ + uint32_t rst_dev_y_set; /* _RST_DEV_Y_SET_0, 0x2a8 */ + uint32_t rst_dev_y_clr; /* _RST_DEV_Y_CLR_0, 0x2ac */ + + uint32_t _0x2b0[17]; + uint32_t dfll_base; /* _DFLL_BASE_0, 0x2f4 */ + uint32_t _0x2f8[2]; + + /* _RST_DEV_L/H/U_SET_0 0x300-0x314 */ + uint32_t rst_dev_l_set; + uint32_t rst_dev_l_clr; + uint32_t rst_dev_h_set; + uint32_t rst_dev_h_clr; + uint32_t rst_dev_u_set; + uint32_t rst_dev_u_clr; + + uint32_t _0x318[2]; + + /* _CLK_ENB_L/H/U_CLR_0 0x320-0x334 */ + uint32_t clk_enb_l_set; + uint32_t clk_enb_l_clr; + uint32_t clk_enb_h_set; + uint32_t clk_enb_h_clr; + uint32_t clk_enb_u_set; + uint32_t clk_enb_u_clr; + + uint32_t _0x338; + uint32_t ccplex_pg_sm_ovrd; /* _CCPLEX_PG_SM_OVRD_0, 0x33c */ + uint32_t rst_cpu_cmplx_set; /* _RST_CPU_CMPLX_SET_0, 0x340 */ + uint32_t rst_cpu_cmplx_clr; /* _RST_CPU_CMPLX_CLR_0, 0x344 */ + + /* Additional (T30) registers */ + uint32_t clk_cpu_cmplx_set; /* _CLK_CPU_CMPLX_SET_0, 0x348 */ + uint32_t clk_cpu_cmplx_clr; /* _CLK_CPU_CMPLX_SET_0, 0x34c */ + + uint32_t _0x350[2]; + uint32_t rst_dev_v; /* _RST_DEVICES_V_0, 0x358 */ + uint32_t rst_dev_w; /* _RST_DEVICES_W_0, 0x35c */ + uint32_t clk_out_enb_v; /* _CLK_OUT_ENB_V_0, 0x360 */ + uint32_t clk_out_enb_w; /* _CLK_OUT_ENB_W_0, 0x364 */ + uint32_t cclkg_brst_pol; /* _CCLKG_BURST_POLICY_0, 0x368 */ + uint32_t super_cclkg_div; /* _SUPER_CCLKG_DIVIDER_0, 0x36c */ + uint32_t cclklp_brst_pol; /* _CCLKLP_BURST_POLICY_0, 0x370 */ + uint32_t super_cclkp_div; /* _SUPER_CCLKLP_DIVIDER_0, 0x374 */ + uint32_t clk_cpug_cmplx; /* _CLK_CPUG_CMPLX_0, 0x378 */ + uint32_t clk_cpulp_cmplx; /* _CLK_CPULP_CMPLX_0, 0x37c */ + uint32_t cpu_softrst_ctrl; /* _CPU_SOFTRST_CTRL_0, 0x380 */ + uint32_t cpu_softrst_ctrl1; /* _CPU_SOFTRST_CTRL1_0, 0x384 */ + uint32_t cpu_softrst_ctrl2; /* _CPU_SOFTRST_CTRL2_0, 0x388 */ + uint32_t _0x38c[5]; + uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */ + uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */ + uint32_t _0x3a8[2]; + + uint32_t _0x3b0; + uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */ + uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */ + uint32_t clk_source_i2s4; /* _CLK_SOURCE_I2S4_0, 0x3bc */ + uint32_t clk_source_i2s5; /* _CLK_SOURCE_I2S5_0, 0x3c0 */ + uint32_t clk_source_i2c4; /* _CLK_SOURCE_I2C4_0, 0x3c4 */ + uint32_t _0x3c8[2]; + uint32_t clk_source_ahub; /* _CLK_SOURCE_AHUB_0, 0x3d0 */ + uint32_t _0x3d4[4]; + uint32_t clk_source_hda2codec_2x; /* _CLK_SOURCE_HDA2CODEC_2X_0, 0x3e4 */ + uint32_t clk_source_actmon; /* _CLK_SOURCE_ACTMON_0, 0x3e8 */ + uint32_t clk_source_extperiph1; /* _CLK_SOURCE_EXTPERIPH1_0, 0x3ec */ + uint32_t clk_source_extperiph2; /* _CLK_SOURCE_EXTPERIPH2_0, 0x3f0 */ + uint32_t clk_source_extperiph3; /* _CLK_SOURCE_EXTPERIPH3_0, 0x3f4 */ + uint32_t _0x3f8; + uint32_t clk_source_i2c_slow; /* _CLK_SOURCE_I2C_SLOW_0, 0x3fc */ + uint32_t clk_source_sys; /* _CLK_SOURCE_SYS_0, 0x400 */ + uint32_t clk_source_ispb; /* _CLK_SOURCE_ISPB_0, 0x404 */ + uint32_t _0x408[2]; + uint32_t clk_source_sor1; /* _CLK_SOURCE_SOR1_0, 0x410 */ + uint32_t clk_source_sor0; /* _CLK_SOURCE_SOR0_0, 0x414 */ + uint32_t _0x418[2]; + uint32_t clk_source_sata_oob; /* _CLK_SOURCE_SATA_OOB_0, 0x420 */ + uint32_t clk_source_sata; /* _CLK_SOURCE_SATA_0, 0x424 */ + uint32_t clk_source_hda; /* _CLK_SOURCE_HDA_0, 0x428 */ + uint32_t _0x42c; + + /* _RST_DEV_V/W_SET_0 0x430-0x43c */ + uint32_t rst_dev_v_set; + uint32_t rst_dev_v_clr; + uint32_t rst_dev_w_set; + uint32_t rst_dev_w_clr; + + /* _CLK_ENB_V/W_CLR_0 0x440-0x44c */ + uint32_t clk_enb_v_set; + uint32_t clk_enb_v_clr; + uint32_t clk_enb_w_set; + uint32_t clk_enb_w_clr; + + /* Additional (T114+) registers */ + uint32_t rst_cpug_cmplx_set; /* _RST_CPUG_CMPLX_SET_0, 0x450 */ + uint32_t rst_cpug_cmplx_clr; /* _RST_CPUG_CMPLX_CLR_0, 0x454 */ + uint32_t rst_cpulp_cmplx_set; /* _RST_CPULP_CMPLX_SET_0, 0x458 */ + uint32_t rst_cpulp_cmplx_clr; /* _RST_CPULP_CMPLX_CLR_0, 0x45c */ + uint32_t clk_cpug_cmplx_set; /* _CLK_CPUG_CMPLX_SET_0, 0x460 */ + uint32_t clk_cpug_cmplx_clr; /* _CLK_CPUG_CMPLX_CLR_0, 0x464 */ + uint32_t clk_cpulp_cmplx_set; /* _CLK_CPULP_CMPLX_SET_0, 0x468 */ + uint32_t clk_cpulp_cmplx_clr; /* _CLK_CPULP_CMPLX_CLR_0, 0x46c */ + uint32_t cpu_cmplx_status; /* _CPU_CMPLX_STATUS_0, 0x470 */ + uint32_t _0x474; + uint32_t intstatus; /* _INTSTATUS_0, 0x478 */ + uint32_t intmask; /* _INTMASK_0, 0x47c */ + uint32_t utmip_pll_cfg0; /* _UTMIP_PLL_CFG0_0, 0x480 */ + uint32_t utmip_pll_cfg1; /* _UTMIP_PLL_CFG1_0, 0x484 */ + uint32_t utmip_pll_cfg2; /* _UTMIP_PLL_CFG2_0, 0x488 */ + + uint32_t plle_aux; /* _PLLE_AUX_0, 0x48c */ + uint32_t sata_pll_cfg0; /* _SATA_PLL_CFG0_0, 0x490 */ + uint32_t sata_pll_cfg1; /* _SATA_PLL_CFG1_0, 0x494 */ + uint32_t pcie_pll_cfg0; /* _PCIE_PLL_CFG0_0, 0x498 */ + + uint32_t prog_audio_dly_clk; /* _PROG_AUDIO_DLY_CLK_0, 0x49c */ + uint32_t audio_sync_clk_i2s0; /* _AUDIO_SYNC_CLK_I2S0_0, 0x4a0 */ + uint32_t audio_sync_clk_i2s1; /* _AUDIO_SYNC_CLK_I2S1_0, 0x4a4 */ + uint32_t audio_sync_clk_i2s2; /* _AUDIO_SYNC_CLK_I2S2_0, 0x4a8 */ + uint32_t audio_sync_clk_i2s3; /* _AUDIO_SYNC_CLK_I2S3_0, 0x4ac */ + uint32_t audio_sync_clk_i2s4; /* _AUDIO_SYNC_CLK_I2S4_0, 0x4b0 */ + uint32_t audio_sync_clk_spdif; /* _AUDIO_SYNC_CLK_SPDIF_0, 0x4b4 */ + + uint32_t plld2_base; /* _PLLD2_BASE_0, 0x4b8 */ + uint32_t plld2_misc; /* _PLLD2_MISC_0, 0x4bc */ + uint32_t utmip_pll_cfg3; /* _UTMIP_PLL_CFG3_0, 0x4c0 */ + uint32_t pllrefe_base; /* _PLLREFE_BASE_0, 0x4c4 */ + uint32_t pllrefe_misc; /* _PLLREFE_MISC_0, 0x4c8 */ + uint32_t pllrefe_out; /* _PLLREFE_OUT_0, 0x4cc */ + uint32_t cpu_finetrim_byp; /* _CPU_FINETRIM_BYP_0, 0x4d0 */ + uint32_t cpu_finetrim_select; /* _CPU_FINETRIM_SELECT_0, 0x4d4 */ + uint32_t cpu_finetrim_dr; /* _CPU_FINETRIM_DR_0, 0x4d8 */ + uint32_t cpu_finetrim_df; /* _CPU_FINETRIM_DF_0, 0x4dc */ + uint32_t cpu_finetrim_f; /* _CPU_FINETRIM_F_0, 0x4e0 */ + uint32_t cpu_finetrim_r; /* _CPU_FINETRIM_R_0, 0x4e4 */ + uint32_t pllc2_base; /* _PLLC2_BASE_0, 0x4e8 */ + uint32_t pllc2_misc0; /* _PLLC2_MISC_0_0, 0x4ec */ + uint32_t pllc2_misc1; /* _PLLC2_MISC_1_0, 0x4f0 */ + uint32_t pllc2_misc2; /* _PLLC2_MISC_2_0, 0x4f4 */ + uint32_t pllc2_misc3; /* _PLLC2_MISC_3_0, 0x4f8 */ + uint32_t pllc3_base; /* _PLLC3_BASE_0, 0x4fc */ + uint32_t pllc3_misc0; /* _PLLC3_MISC_0_0, 0x500 */ + uint32_t pllc3_misc1; /* _PLLC3_MISC_1_0, 0x504 */ + uint32_t pllc3_misc2; /* _PLLC3_MISC_2_0, 0x508 */ + uint32_t pllc3_misc3; /* _PLLC3_MISC_3_0, 0x50c */ + uint32_t pllx_misc1; /* _PLLX_MISC_1_0, 0x510 */ + uint32_t pllx_misc2; /* _PLLX_MISC_2_0, 0x514 */ + uint32_t pllx_misc3; /* _PLLX_MISC_3_0, 0x518 */ + uint32_t xusbio_pll_cfg0; /* _XUSBIO_PLL_CFG0_0, 0x51c */ + uint32_t xusbio_pll_cfg1; /* _XUSBIO_PLL_CFG0_1, 0x520 */ + uint32_t plle_aux1; /* _PLLE_AUX1_0, 0x524 */ + uint32_t pllp_reshift; /* _PLLP_RESHIFT_0, 0x528 */ + uint32_t utmipll_hw_pwrdn_cfg0; /* _UTMIPLL_HW_PWRDN_CFG0_0, 0x52c */ + uint32_t pllu_hw_pwrdn_cfg0; /* _PLLU_HW_PWRDN_CFG0_0, 0x530 */ + uint32_t xusb_pll_cfg0; /* _XUSB_PLL_CFG0_0, 0x534 */ + uint32_t _0x538; + uint32_t clk_cpu_misc; /* _CLK_CPU_MISC_0, 0x53c */ + uint32_t clk_cpug_misc; /* _CLK_CPUG_MISC_0, 0x540 */ + uint32_t clk_cpulp_misc; /* _CLK_CPULP_MISC_0, 0x544 */ + uint32_t pllx_hw_ctrl_cfg; /* _PLLX_HW_CTRL_CFG_0, 0x548 */ + uint32_t pllx_sw_ramp_cfg; /* _PLLX_SW_RAMP_CFG_0, 0x54c */ + uint32_t pllx_hw_ctrl_status; /* _PLLX_HW_CTRL_STATUS_0, 0x550 */ + uint32_t lvl2_clk_gate_ovre; /* _LVL2_CLK_GATE_OVRE, 0x554 */ + uint32_t super_gr3d_clk_div; /* _SUPER_GR3D_CLK_DIVIDER_0, 0x558 */ + uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */ + uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */ + uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */ + + uint32_t _0x568[2]; + uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */ + uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */ + uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */ + uint32_t _0x57c[5]; + + uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/ + uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */ + uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */ + uint32_t plldp_ss_ctrl1; /* _PLLDP_SS_CTRL1_0, 0x59c */ + uint32_t plldp_ss_ctrl2; /* _PLLDP_SS_CTRL2_0, 0x5a0 */ + uint32_t pllc4_base; /* _PLLC4_BASE_0, 0x5a4 */ + uint32_t pllc4_misc; /* _PLLC4_MISC_0, 0x5a8 */ + uint32_t _0x5ac[6]; + uint32_t clk_spare0; /* _CLK_SPARE0_0, 0x5c4 */ + uint32_t clk_spare1; /* _CLK_SPARE1_0, 0x5c8 */ + uint32_t gpu_isob_ctrl; /* _GPU_ISOB_CTRL_0, 0x5cc */ + uint32_t pllc_misc2; /* _PLLC_MISC_2_0, 0x5d0 */ + uint32_t pllc_misc3; /* _PLLC_MISC_3_0, 0x5d4 */ + uint32_t plla_misc2; /* _PLLA_MISC2_0, 0x5d8 */ + uint32_t _0x5dc[2]; + uint32_t pllc4_out; /* _PLLC4_OUT_0, 0x5e4 */ + uint32_t pllmb_base; /* _PLLMB_BASE_0, 0x5e8 */ + uint32_t pllmb_misc1; /* _PLLMB_MISC1_0, 0x5ec */ + uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */ + uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */ + uint32_t _0x5f8[2]; + + uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */ + uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */ + uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */ + uint32_t clk_source_xusb_core_dev; /* _CLK_SOURCE_XUSB_CORE_DEV_0, 0x60c */ + uint32_t clk_source_xusb_ss; /* _CLK_SOURCE_XUSB_SS_0, 0x610 */ + uint32_t clk_source_cilab; /* _CLK_SOURCE_CILAB_0, 0x614 */ + uint32_t clk_source_cilcd; /* _CLK_SOURCE_CILCD_0, 0x618 */ + uint32_t clk_source_cilef; /* _CLK_SOURCE_CILEF_0, 0x61c */ + uint32_t clk_source_dsia_lp; /* _CLK_SOURCE_DSIA_LP_0, 0x620 */ + uint32_t clk_source_dsib_lp; /* _CLK_SOURCE_DSIB_LP_0, 0x624 */ + uint32_t clk_source_entropy; /* _CLK_SOURCE_ENTROPY_0, 0x628 */ + uint32_t clk_source_dvfs_ref; /* _CLK_SOURCE_DVFS_REF_0, 0x62c */ + uint32_t clk_source_dvfs_soc; /* _CLK_SOURCE_DVFS_SOC_0, 0x630 */ + uint32_t _0x634[3]; + uint32_t clk_source_emc_latency; /* _CLK_SOURCE_EMC_LATENCY_0, 0x640 */ + uint32_t clk_source_soc_therm; /* _CLK_SOURCE_SOC_THERM_0, 0x644 */ + uint32_t _0x648; + uint32_t clk_source_dmic1; /* _CLK_SOURCE_DMIC1_0, 0x64c */ + uint32_t clk_source_dmic2; /* _CLK_SOURCE_DMIC2_0, 0x650 */ + uint32_t _0x654; + uint32_t clk_source_vi_sensor2; /* _CLK_SOURCE_VI_SENSOR2_0, 0x658 */ + uint32_t clk_source_i2c6; /* _CLK_SOURCE_I2C6_0, 0x65c */ + uint32_t clk_source_mipibif; /* _CLK_SOURCE_MIPIBIF_0, 0x660 */ + uint32_t clk_source_emc_dll; /* _CLK_SOURCE_EMC_DLL_0, 0x664 */ + uint32_t _0x668; + uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */ + uint32_t _0x670[2]; + uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */ + + uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */ + uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */ + uint32_t _0x684[2]; + uint32_t emc_div_clk_shaper_ctrl; /* _EMC_DIV_CLK_SHAPER_CTRL_0, 0x68c */ + uint32_t emc_pllc_shaper_ctrl; /* _EMC_PLLC_SHAPER_CTRL_0, 0x690 */ + + uint32_t clk_source_sdmmc_legacy_tm; /* _CLK_SOURCE_SDMMC_LEGACY_TM_0, 0x694 */ + uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */ + uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */ + uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */ + + uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */ + uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */ + uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */ + uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */ + uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */ + uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */ + + uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */ + uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */ + uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */ + uint32_t clk_source_vi_i2c; /* _CLK_SOURCE_VI_I2C_0, 0x6c8 */ + uint32_t clk_source_usb2_hsic_trk; /* _CLK_SOURCE_USB2_HSIC_TRK_0, 0x6cc */ + uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */ + uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */ + uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */ + + uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */ + uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */ + uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */ + + uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */ + uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */ + uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */ + uint32_t nvdec_super_clk_divider; /* _NVDEC_SUPER_CLK_DIVIDER_0, 0x6f4 */ + uint32_t isp_super_clk_divider; /* _ISP_SUPER_CLK_DIVIDER_0, 0x6f8 */ + uint32_t ispb_super_clk_divider; /* _ISPB_SUPER_CLK_DIVIDER_0, 0x6fc */ + uint32_t nvjpg_super_clk_divider; /* _NVJPG_SUPER_CLK_DIVIDER_0, 0x700 */ + uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */ + uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */ + uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */ + + uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */ + uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */ + uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */ + uint32_t clk_ccplex_cc4_ret_clk_enb; /* _CLK_CCPLEX_CC4_RET_CLK_ENB_0, 0x71c */ + uint32_t actmon_cpu_clk; /* _ACTMON_CPU_CLK_0, 0x720 */ + uint32_t clk_source_emc_safe; /* _CLK_SOURCE_EMC_SAFE_0, 0x724 */ + uint32_t sdmmc2_pllc4_out0_shaper_ctrl; /* _SDMMC2_PLLC4_OUT0_SHAPER_CTRL_0, 0x728 */ + uint32_t sdmmc2_pllc4_out1_shaper_ctrl; /* _SDMMC2_PLLC4_OUT1_SHAPER_CTRL_0, 0x72c */ + uint32_t sdmmc2_pllc4_out2_shaper_ctrl; /* _SDMMC2_PLLC4_OUT2_SHAPER_CTRL_0, 0x730 */ + uint32_t sdmmc2_div_clk_shaper_ctrl; /* _SDMMC2_DIV_CLK_SHAPER_CTRL_0, 0x734 */ + uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */ + uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */ + uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */ + uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */ +} tegra_car_t; + +static inline volatile tegra_car_t *car_get_regs(void) { + return (volatile tegra_car_t *)CAR_BASE; +} + +void clk_enable(CarDevice dev); +void clk_disable(CarDevice dev); +void rst_enable(CarDevice dev); +void rst_disable(CarDevice dev); + +void clkrst_enable(CarDevice dev); +void clkrst_disable(CarDevice dev); +void clkrst_reboot(CarDevice dev); + +void clkrst_enable_fuse_regs(bool enable); + +#endif diff --git a/sept/sept-secondary/src/chainloader.c b/sept/sept-secondary/src/chainloader.c new file mode 100644 index 000000000..bc222604a --- /dev/null +++ b/sept/sept-secondary/src/chainloader.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "chainloader.h" + +int g_chainloader_argc = 0; +char g_chainloader_arg_data[CHAINLOADER_ARG_DATA_MAX_SIZE] = {0}; +chainloader_entry_t g_chainloader_entries[CHAINLOADER_MAX_ENTRIES] = {0}; /* keep them sorted */ +size_t g_chainloader_num_entries = 0; +uintptr_t g_chainloader_entrypoint = 0; + +#pragma GCC optimize (3) + +static void *xmemmove(void *dst, const void *src, size_t len) +{ + const uint8_t *src8 = (const uint8_t *)src; + uint8_t *dst8 = (uint8_t *)dst; + + if (dst8 < src8) { + for (size_t i = 0; i < len; i++) { + dst8[i] = src8[i]; + } + } else if (dst8 > src8) { + for (size_t i = len; len > 0; len--) + dst8[i - 1] = src8[i - 1]; + } + + return dst; +} + +void relocate_and_chainload_main(void) { + for(size_t i = 0; i < g_chainloader_num_entries; i++) { + chainloader_entry_t *entry = &g_chainloader_entries[i]; + xmemmove((void *)entry->load_address, (const void *)entry->src_address, entry->size); + } + + ((void (*)(int, void *))g_chainloader_entrypoint)(g_chainloader_argc, g_chainloader_arg_data); +} diff --git a/sept/sept-secondary/src/chainloader.h b/sept/sept-secondary/src/chainloader.h new file mode 100644 index 000000000..0081530c3 --- /dev/null +++ b/sept/sept-secondary/src/chainloader.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_CHAINLOADER_H +#define FUSEE_CHAINLOADER_H + +#include <stddef.h> +#include <stdint.h> + +#define CHAINLOADER_ARG_DATA_MAX_SIZE 0x6200 +#define CHAINLOADER_MAX_ENTRIES 128 + +typedef struct chainloader_entry_t { + uintptr_t load_address; + uintptr_t src_address; + size_t size; + size_t num; +} chainloader_entry_t; + +extern int g_chainloader_argc; +extern chainloader_entry_t g_chainloader_entries[CHAINLOADER_MAX_ENTRIES]; /* keep them sorted */ +extern size_t g_chainloader_num_entries; +extern uintptr_t g_chainloader_entrypoint; + +extern char g_chainloader_arg_data[CHAINLOADER_ARG_DATA_MAX_SIZE]; + +void relocate_and_chainload(void); + +#endif diff --git a/sept/sept-secondary/src/di.c b/sept/sept-secondary/src/di.c new file mode 100644 index 000000000..b6f8116c9 --- /dev/null +++ b/sept/sept-secondary/src/di.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> + +#include "di.h" +#include "timers.h" +#include "i2c.h" +#include "pmc.h" +#include "max77620.h" +#include "gpio.h" +#include "pinmux.h" +#include "car.h" + +#include "di.inl" + +static uint32_t _display_ver = 0; + +static void exec_cfg(uint32_t *base, const cfg_op_t *ops, uint32_t num_ops) +{ + for (uint32_t i = 0; i < num_ops; i++) + base[ops[i].off] = ops[i].val; +} + +static void _display_dsi_wait(uint32_t timeout, uint32_t off, uint32_t mask) +{ + uint32_t end = get_time_us() + timeout; + while ((get_time_us() < end) && (MAKE_DSI_REG(off) & mask)) { + /* Wait. */ + } + udelay(5); +} + +void display_init() +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + + /* Power on. */ + uint8_t val = 0xD0; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_LDO0_CFG, &val, 1); + val = 0x09; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_GPIO7, &val, 1); + + /* Enable MIPI CAL, DSI, DISP1, HOST1X, UART_FST_MIPI_CAL, DSIA LP clocks. */ + car->rst_dev_h_clr = 0x1010000; + car->clk_enb_h_set = 0x1010000; + car->rst_dev_l_clr = 0x18000000; + car->clk_enb_l_set = 0x18000000; + car->clk_enb_x_set = 0x20000; + car->clk_source_uart_fst_mipi_cal = 0xA; + car->clk_enb_w_set = 0x80000; + car->clk_source_dsia_lp = 0xA; + + /* DPD idle. */ + pmc->io_dpd_req = 0x40000000; + pmc->io_dpd2_req = 0x40000000; + + /* Configure pins. */ + pinmux->nfc_en &= ~PINMUX_TRISTATE; + pinmux->nfc_int &= ~PINMUX_TRISTATE; + pinmux->lcd_bl_pwm &= ~PINMUX_TRISTATE; + pinmux->lcd_bl_en &= ~PINMUX_TRISTATE; + pinmux->lcd_rst &= ~PINMUX_TRISTATE; + + /* Configure Backlight +-5V GPIOs. */ + gpio_configure_mode(GPIO_LCD_BL_P5V, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_N5V, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_LCD_BL_P5V, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_N5V, GPIO_DIRECTION_OUTPUT); + + /* Enable Backlight +5V. */ + gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_HIGH); + + udelay(10000); + + /* Enable Backlight -5V. */ + gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_HIGH); + + udelay(10000); + + /* Configure Backlight PWM, EN and RST GPIOs. */ + gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_EN, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_LCD_BL_RST, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_LCD_BL_PWM, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_EN, GPIO_DIRECTION_OUTPUT); + gpio_configure_direction(GPIO_LCD_BL_RST, GPIO_DIRECTION_OUTPUT); + + /* Enable Backlight EN. */ + gpio_write(GPIO_LCD_BL_EN, GPIO_LEVEL_HIGH); + + /* Configure display interface and display. */ + MAKE_MIPI_CAL_REG(0x60) = 0; + + exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4); + exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94); + exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 60); + + udelay(10000); + + /* Enable Backlight RST. */ + gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_HIGH); + + udelay(60000); + + MAKE_DSI_REG(DSI_BTA_TIMING) = 0x50204; + MAKE_DSI_REG(DSI_WR_DATA) = 0x337; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + _display_dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO)); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x406; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + _display_dsi_wait(250000, DSI_TRIGGER, (DSI_TRIGGER_HOST | DSI_TRIGGER_VIDEO)); + + MAKE_DSI_REG(DSI_HOST_CONTROL) = (DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_IMM_BTA | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC); + _display_dsi_wait(150000, DSI_HOST_CONTROL, DSI_HOST_CONTROL_IMM_BTA); + + udelay(5000); + + _display_ver = MAKE_DSI_REG(DSI_RD_DATA); + + if (_display_ver == 0x10) + exec_cfg((uint32_t *)DSI_BASE, _display_config_4, 43); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x1105; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + + udelay(180000); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x2905; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + + udelay(20000); + + exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21); + exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3); + + MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4; + exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10); + + udelay(10000); + + exec_cfg((uint32_t *)MIPI_CAL_BASE, _display_config_8, 6); + exec_cfg((uint32_t *)DSI_BASE, _display_config_9, 4); + exec_cfg((uint32_t *)MIPI_CAL_BASE, _display_config_10, 16); + + udelay(10000); + + exec_cfg((uint32_t *)DI_BASE, _display_config_11, 113); +} + +void display_backlight(bool enable) +{ + /* Enable Backlight PWM. */ + gpio_write(GPIO_LCD_BL_PWM, enable ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW); +} + +void display_end() +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + + /* Disable Backlight. */ + display_backlight(false); + + MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 1; + MAKE_DSI_REG(DSI_WR_DATA) = 0x2805; + + MAKE_DI_REG(DC_CMD_STATE_ACCESS) = (READ_MUX | WRITE_MUX); + MAKE_DSI_REG(DSI_VIDEO_MODE_CONTROL) = 0; + + exec_cfg((uint32_t *)DI_BASE, _display_config_12, 17); + exec_cfg((uint32_t *)DSI_BASE, _display_config_13, 16); + + udelay(10000); + + if (_display_ver == 0x10) + exec_cfg((uint32_t *)DSI_BASE, _display_config_14, 22); + + MAKE_DSI_REG(DSI_WR_DATA) = 0x1005; + MAKE_DSI_REG(DSI_TRIGGER) = DSI_TRIGGER_HOST; + + udelay(50000); + + /* Disable Backlight RST. */ + gpio_write(GPIO_LCD_BL_RST, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable Backlight -5V. */ + gpio_write(GPIO_LCD_BL_N5V, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable Backlight +5V. */ + gpio_write(GPIO_LCD_BL_P5V, GPIO_LEVEL_LOW); + + udelay(10000); + + /* Disable clocks. */ + car->rst_dev_h_set = 0x1010000; + car->clk_enb_h_clr = 0x1010000; + car->rst_dev_l_set = 0x18000000; + car->clk_enb_l_clr = 0x18000000; + + MAKE_DSI_REG(DSI_PAD_CONTROL_0) = (DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF)); + MAKE_DSI_REG(DSI_POWER_CONTROL) = 0; + + /* Backlight PWM. */ + gpio_configure_mode(GPIO_LCD_BL_PWM, GPIO_MODE_SFIO); + + pinmux->lcd_bl_pwm = ((pinmux->lcd_bl_pwm & ~PINMUX_TRISTATE) | PINMUX_TRISTATE); + pinmux->lcd_bl_pwm = (((pinmux->lcd_bl_pwm >> 2) << 2) | 1); +} + +void display_color_screen(uint32_t color) +{ + exec_cfg((uint32_t *)DI_BASE, cfg_display_one_color, 8); + + /* Configure display to show single color. */ + MAKE_DI_REG(DC_WIN_AD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_WIN_BD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_WIN_CD_WIN_OPTIONS) = 0; + MAKE_DI_REG(DC_DISP_BLEND_BACKGROUND_COLOR) = color; + MAKE_DI_REG(DC_CMD_STATE_CONTROL) = ((MAKE_DI_REG(DC_CMD_STATE_CONTROL) & 0xFFFFFFFE) | GENERAL_ACT_REQ); + + udelay(35000); + + display_backlight(true); +} + +uint32_t *display_init_framebuffer(void *address) +{ + static cfg_op_t conf[sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t)] = {0}; + if (conf[0].val == 0) { + for (uint32_t i = 0; i < sizeof(cfg_display_framebuffer)/sizeof(cfg_op_t); i++) { + conf[i] = cfg_display_framebuffer[i]; + } + } + + uint32_t *lfb_addr = (uint32_t *)address; + conf[19].val = (uint32_t)address; + + /* This configures the framebuffer @ address with a resolution of 1280x720 (line stride 768). */ + exec_cfg((uint32_t *)DI_BASE, conf, 32); + + udelay(35000); + + return lfb_addr; +} diff --git a/sept/sept-secondary/src/di.h b/sept/sept-secondary/src/di.h new file mode 100644 index 000000000..4aa4f944d --- /dev/null +++ b/sept/sept-secondary/src/di.h @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_DI_H_ +#define FUSEE_DI_H_ + +#include <stdint.h> +#include <stdbool.h> + +#define HOST1X_BASE 0x50000000 +#define DI_BASE 0x54200000 +#define DSI_BASE 0x54300000 +#define VIC_BASE 0x54340000 +#define MIPI_CAL_BASE 0x700E3000 +#define MAKE_HOST1X_REG(n) MAKE_REG32(HOST1X_BASE + n) +#define MAKE_DI_REG(n) MAKE_REG32(DI_BASE + n * 4) +#define MAKE_DSI_REG(n) MAKE_REG32(DSI_BASE + n * 4) +#define MAKE_MIPI_CAL_REG(n) MAKE_REG32(MIPI_CAL_BASE + n) +#define MAKE_VIC_REG(n) MAKE_REG32(VIC_BASE + n) + +/* Display registers. */ +#define DC_CMD_GENERAL_INCR_SYNCPT 0x00 + +#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x01 +#define SYNCPT_CNTRL_NO_STALL (1 << 8) +#define SYNCPT_CNTRL_SOFT_RESET (1 << 0) + +#define DC_CMD_CONT_SYNCPT_VSYNC 0x28 +#define SYNCPT_VSYNC_ENABLE (1 << 8) + +#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031 + +#define DC_CMD_DISPLAY_COMMAND 0x32 +#define DISP_CTRL_MODE_STOP (0 << 5) +#define DISP_CTRL_MODE_C_DISPLAY (1 << 5) +#define DISP_CTRL_MODE_NC_DISPLAY (2 << 5) +#define DISP_CTRL_MODE_MASK (3 << 5) + +#define DC_CMD_DISPLAY_POWER_CONTROL 0x36 +#define PW0_ENABLE (1 << 0) +#define PW1_ENABLE (1 << 2) +#define PW2_ENABLE (1 << 4) +#define PW3_ENABLE (1 << 6) +#define PW4_ENABLE (1 << 8) +#define PM0_ENABLE (1 << 16) +#define PM1_ENABLE (1 << 18) + +#define DC_CMD_INT_MASK 0x38 +#define DC_CMD_INT_ENABLE 0x39 + +#define DC_CMD_STATE_ACCESS 0x40 +#define READ_MUX (1 << 0) +#define WRITE_MUX (1 << 2) + +#define DC_CMD_STATE_CONTROL 0x41 +#define GENERAL_ACT_REQ (1 << 0) +#define WIN_A_ACT_REQ (1 << 1) +#define WIN_B_ACT_REQ (1 << 2) +#define WIN_C_ACT_REQ (1 << 3) +#define CURSOR_ACT_REQ (1 << 7) +#define GENERAL_UPDATE (1 << 8) +#define WIN_A_UPDATE (1 << 9) +#define WIN_B_UPDATE (1 << 10) +#define WIN_C_UPDATE (1 << 11) +#define CURSOR_UPDATE (1 << 15) +#define NC_HOST_TRIG (1 << 24) + +#define DC_CMD_DISPLAY_WINDOW_HEADER 0x42 +#define WINDOW_A_SELECT (1 << 4) +#define WINDOW_B_SELECT (1 << 5) +#define WINDOW_C_SELECT (1 << 6) + +#define DC_CMD_REG_ACT_CONTROL 0x043 + +#define DC_COM_CRC_CONTROL 0x300 +#define DC_COM_PIN_OUTPUT_ENABLE(x) (0x302 + (x)) +#define DC_COM_PIN_OUTPUT_POLARITY(x) (0x306 + (x)) + +#define DC_COM_DSC_TOP_CTL 0x33E + +#define DC_DISP_DISP_WIN_OPTIONS 0x402 +#define HDMI_ENABLE (1 << 30) +#define DSI_ENABLE (1 << 29) +#define SOR1_TIMING_CYA (1 << 27) +#define SOR1_ENABLE (1 << 26) +#define SOR_ENABLE (1 << 25) +#define CURSOR_ENABLE (1 << 16) + +#define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 +#define DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER 0x404 +#define DC_DISP_DISP_TIMING_OPTIONS 0x405 +#define DC_DISP_REF_TO_SYNC 0x406 +#define DC_DISP_SYNC_WIDTH 0x407 +#define DC_DISP_BACK_PORCH 0x408 +#define DC_DISP_ACTIVE 0x409 +#define DC_DISP_FRONT_PORCH 0x40A + +#define DC_DISP_DISP_CLOCK_CONTROL 0x42E +#define PIXEL_CLK_DIVIDER_PCD1 (0 << 8) +#define PIXEL_CLK_DIVIDER_PCD1H (1 << 8) +#define PIXEL_CLK_DIVIDER_PCD2 (2 << 8) +#define PIXEL_CLK_DIVIDER_PCD3 (3 << 8) +#define PIXEL_CLK_DIVIDER_PCD4 (4 << 8) +#define PIXEL_CLK_DIVIDER_PCD6 (5 << 8) +#define PIXEL_CLK_DIVIDER_PCD8 (6 << 8) +#define PIXEL_CLK_DIVIDER_PCD9 (7 << 8) +#define PIXEL_CLK_DIVIDER_PCD12 (8 << 8) +#define PIXEL_CLK_DIVIDER_PCD16 (9 << 8) +#define PIXEL_CLK_DIVIDER_PCD18 (10 << 8) +#define PIXEL_CLK_DIVIDER_PCD24 (11 << 8) +#define PIXEL_CLK_DIVIDER_PCD13 (12 << 8) +#define SHIFT_CLK_DIVIDER(x) ((x) & 0xff) + +#define DC_DISP_DISP_INTERFACE_CONTROL 0x42F +#define DISP_DATA_FORMAT_DF1P1C (0 << 0) +#define DISP_DATA_FORMAT_DF1P2C24B (1 << 0) +#define DISP_DATA_FORMAT_DF1P2C18B (2 << 0) +#define DISP_DATA_FORMAT_DF1P2C16B (3 << 0) +#define DISP_DATA_FORMAT_DF2S (4 << 0) +#define DISP_DATA_FORMAT_DF3S (5 << 0) +#define DISP_DATA_FORMAT_DFSPI (6 << 0) +#define DISP_DATA_FORMAT_DF1P3C24B (7 << 0) +#define DISP_DATA_FORMAT_DF1P3C18B (8 << 0) +#define DISP_ALIGNMENT_MSB (0 << 8) +#define DISP_ALIGNMENT_LSB (1 << 8) +#define DISP_ORDER_RED_BLUE (0 << 9) +#define DISP_ORDER_BLUE_RED (1 << 9) + +#define DC_DISP_DISP_COLOR_CONTROL 0x430 +#define DITHER_CONTROL_MASK (3 << 8) +#define DITHER_CONTROL_DISABLE (0 << 8) +#define DITHER_CONTROL_ORDERED (2 << 8) +#define DITHER_CONTROL_ERRDIFF (3 << 8) +#define BASE_COLOR_SIZE_MASK (0xf << 0) +#define BASE_COLOR_SIZE_666 (0 << 0) +#define BASE_COLOR_SIZE_111 (1 << 0) +#define BASE_COLOR_SIZE_222 (2 << 0) +#define BASE_COLOR_SIZE_333 (3 << 0) +#define BASE_COLOR_SIZE_444 (4 << 0) +#define BASE_COLOR_SIZE_555 (5 << 0) +#define BASE_COLOR_SIZE_565 (6 << 0) +#define BASE_COLOR_SIZE_332 (7 << 0) +#define BASE_COLOR_SIZE_888 (8 << 0) + +#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431 +#define SC1_H_QUALIFIER_NONE (1 << 16) +#define SC0_H_QUALIFIER_NONE (1 << 0) + +#define DC_DISP_DATA_ENABLE_OPTIONS 0x432 +#define DE_SELECT_ACTIVE_BLANK (0 << 0) +#define DE_SELECT_ACTIVE (1 << 0) +#define DE_SELECT_ACTIVE_IS (2 << 0) +#define DE_CONTROL_ONECLK (0 << 2) +#define DE_CONTROL_NORMAL (1 << 2) +#define DE_CONTROL_EARLY_EXT (2 << 2) +#define DE_CONTROL_EARLY (3 << 2) +#define DE_CONTROL_ACTIVE_BLANK (4 << 2) + +#define DC_DISP_DC_MCCIF_FIFOCTRL 0x480 +#define DC_DISP_BLEND_BACKGROUND_COLOR 0x4E4 + +#define DC_WIN_CSC_YOF 0x611 +#define DC_WIN_CSC_KYRGB 0x612 +#define DC_WIN_CSC_KUR 0x613 +#define DC_WIN_CSC_KVR 0x614 +#define DC_WIN_CSC_KUG 0x615 +#define DC_WIN_CSC_KVG 0x616 +#define DC_WIN_CSC_KUB 0x617 +#define DC_WIN_CSC_KVB 0x618 +#define DC_WIN_AD_WIN_OPTIONS 0xB80 +#define DC_WIN_BD_WIN_OPTIONS 0xD80 +#define DC_WIN_CD_WIN_OPTIONS 0xF80 + +/* The following registers are A/B/C shadows of the 0xB80/0xD80/0xF80 registers (see DISPLAY_WINDOW_HEADER). */ +#define DC_WIN_WIN_OPTIONS 0x700 +#define H_DIRECTION (1 << 0) +#define V_DIRECTION (1 << 2) +#define COLOR_EXPAND (1 << 6) +#define CSC_ENABLE (1 << 18) +#define WIN_ENABLE (1 << 30) + +#define DC_WIN_COLOR_DEPTH 0x703 +#define WIN_COLOR_DEPTH_P1 0x0 +#define WIN_COLOR_DEPTH_P2 0x1 +#define WIN_COLOR_DEPTH_P4 0x2 +#define WIN_COLOR_DEPTH_P8 0x3 +#define WIN_COLOR_DEPTH_B4G4R4A4 0x4 +#define WIN_COLOR_DEPTH_B5G5R5A 0x5 +#define WIN_COLOR_DEPTH_B5G6R5 0x6 +#define WIN_COLOR_DEPTH_AB5G5R5 0x7 +#define WIN_COLOR_DEPTH_B8G8R8A8 0xC +#define WIN_COLOR_DEPTH_R8G8B8A8 0xD +#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 0xE +#define WIN_COLOR_DEPTH_R6x2G6x2B6x2A8 0xF +#define WIN_COLOR_DEPTH_YCbCr422 0x10 +#define WIN_COLOR_DEPTH_YUV422 0x11 +#define WIN_COLOR_DEPTH_YCbCr420P 0x12 +#define WIN_COLOR_DEPTH_YUV420P 0x13 +#define WIN_COLOR_DEPTH_YCbCr422P 0x14 +#define WIN_COLOR_DEPTH_YUV422P 0x15 +#define WIN_COLOR_DEPTH_YCbCr422R 0x16 +#define WIN_COLOR_DEPTH_YUV422R 0x17 +#define WIN_COLOR_DEPTH_YCbCr422RA 0x18 +#define WIN_COLOR_DEPTH_YUV422RA 0x19 + +#define DC_WIN_BUFFER_CONTROL 0x702 +#define DC_WIN_POSITION 0x704 + +#define DC_WIN_SIZE 0x705 +#define H_SIZE(x) (((x) & 0x1fff) << 0) +#define V_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_PRESCALED_SIZE 0x706 +#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) << 0) +#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16) + +#define DC_WIN_H_INITIAL_DDA 0x707 +#define DC_WIN_V_INITIAL_DDA 0x708 + +#define DC_WIN_DDA_INC 0x709 +#define H_DDA_INC(x) (((x) & 0xffff) << 0) +#define V_DDA_INC(x) (((x) & 0xffff) << 16) + +#define DC_WIN_LINE_STRIDE 0x70A +#define DC_WIN_DV_CONTROL 0x70E + +/* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */ +#define DC_WINBUF_START_ADDR 0x800 +#define DC_WINBUF_ADDR_H_OFFSET 0x806 +#define DC_WINBUF_ADDR_V_OFFSET 0x808 +#define DC_WINBUF_SURFACE_KIND 0x80B + +/* Display serial interface registers. */ +#define DSI_RD_DATA 0x9 +#define DSI_WR_DATA 0xA + +#define DSI_POWER_CONTROL 0xB +#define DSI_POWER_CONTROL_ENABLE 1 + +#define DSI_INT_ENABLE 0xC +#define DSI_INT_STATUS 0xD +#define DSI_INT_MASK 0xE + +#define DSI_HOST_CONTROL 0xF +#define DSI_HOST_CONTROL_FIFO_RESET (1 << 21) +#define DSI_HOST_CONTROL_CRC_RESET (1 << 20) +#define DSI_HOST_CONTROL_TX_TRIG_SOL (0 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_FIFO (1 << 12) +#define DSI_HOST_CONTROL_TX_TRIG_HOST (2 << 12) +#define DSI_HOST_CONTROL_RAW (1 << 6) +#define DSI_HOST_CONTROL_HS (1 << 5) +#define DSI_HOST_CONTROL_FIFO_SEL (1 << 4) +#define DSI_HOST_CONTROL_IMM_BTA (1 << 3) +#define DSI_HOST_CONTROL_PKT_BTA (1 << 2) +#define DSI_HOST_CONTROL_CS (1 << 1) +#define DSI_HOST_CONTROL_ECC (1 << 0) + +#define DSI_CONTROL 0x10 +#define DSI_CONTROL_HS_CLK_CTRL (1 << 20) +#define DSI_CONTROL_CHANNEL(c) (((c) & 0x3) << 16) +#define DSI_CONTROL_FORMAT(f) (((f) & 0x3) << 12) +#define DSI_CONTROL_TX_TRIG(x) (((x) & 0x3) << 8) +#define DSI_CONTROL_LANES(n) (((n) & 0x3) << 4) +#define DSI_CONTROL_DCS_ENABLE (1 << 3) +#define DSI_CONTROL_SOURCE(s) (((s) & 0x1) << 2) +#define DSI_CONTROL_VIDEO_ENABLE (1 << 1) +#define DSI_CONTROL_HOST_ENABLE (1 << 0) + +#define DSI_SOL_DELAY 0x11 +#define DSI_MAX_THRESHOLD 0x12 + +#define DSI_TRIGGER 0x13 +#define DSI_TRIGGER_HOST (1 << 1) +#define DSI_TRIGGER_VIDEO (1 << 0) + +#define DSI_TX_CRC 0x14 +#define DSI_STATUS 0x15 +#define DSI_INIT_SEQ_CONTROL 0x1A +#define DSI_INIT_SEQ_DATA_0 0x1B +#define DSI_INIT_SEQ_DATA_1 0x1C +#define DSI_INIT_SEQ_DATA_2 0x1D +#define DSI_INIT_SEQ_DATA_3 0x1E +#define DSI_PKT_SEQ_0_LO 0x23 +#define DSI_PKT_SEQ_0_HI 0x24 +#define DSI_PKT_SEQ_1_LO 0x25 +#define DSI_PKT_SEQ_1_HI 0x26 +#define DSI_PKT_SEQ_2_LO 0x27 +#define DSI_PKT_SEQ_2_HI 0x28 +#define DSI_PKT_SEQ_3_LO 0x29 +#define DSI_PKT_SEQ_3_HI 0x2A +#define DSI_PKT_SEQ_4_LO 0x2B +#define DSI_PKT_SEQ_4_HI 0x2C +#define DSI_PKT_SEQ_5_LO 0x2D +#define DSI_PKT_SEQ_5_HI 0x2E +#define DSI_DCS_CMDS 0x33 +#define DSI_PKT_LEN_0_1 0x34 +#define DSI_PKT_LEN_2_3 0x35 +#define DSI_PKT_LEN_4_5 0x36 +#define DSI_PKT_LEN_6_7 0x37 +#define DSI_PHY_TIMING_0 0x3C +#define DSI_PHY_TIMING_1 0x3D +#define DSI_PHY_TIMING_2 0x3E +#define DSI_BTA_TIMING 0x3F + +#define DSI_TIMEOUT_0 0x44 +#define DSI_TIMEOUT_LRX(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_HTX(x) (((x) & 0xffff) << 0) + +#define DSI_TIMEOUT_1 0x45 +#define DSI_TIMEOUT_PR(x) (((x) & 0xffff) << 16) +#define DSI_TIMEOUT_TA(x) (((x) & 0xffff) << 0) + +#define DSI_TO_TALLY 0x46 + +#define DSI_PAD_CONTROL_0 0x4B +#define DSI_PAD_CONTROL_VS1_PULLDN_CLK (1 << 24) +#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16) +#define DSI_PAD_CONTROL_VS1_PDIO_CLK (1 << 8) +#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0) + +#define DSI_PAD_CONTROL_CD 0x4c +#define DSI_VIDEO_MODE_CONTROL 0x4E + +#define DSI_PAD_CONTROL_1 0x4F +#define DSI_PAD_CONTROL_2 0x50 + +#define DSI_PAD_CONTROL_3 0x51 +#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12) +#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8) +#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4) +#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0) + +#define DSI_PAD_CONTROL_4 0x52 + +typedef struct _cfg_op_t +{ + uint32_t off; + uint32_t val; +} cfg_op_t; + +void display_init(); +void display_end(); + +/* Show one single color on the display. */ +void display_color_screen(uint32_t color); + +/* Switches screen backlight ON/OFF. */ +void display_backlight(bool enable); + +/* Init display in full 1280x720 resolution (B8G8R8A8, line stride 768, framebuffer size = 1280*768*4 bytes). */ +uint32_t *display_init_framebuffer(void *address); + +#endif diff --git a/sept/sept-secondary/src/di.inl b/sept/sept-secondary/src/di.inl new file mode 100644 index 000000000..e438ca5cb --- /dev/null +++ b/sept/sept-secondary/src/di.inl @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (C) 2018 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +//Clock config. +static const cfg_op_t _display_config_1[4] = { + {0x4E, 0x40000000}, //CLK_RST_CONTROLLER_CLK_SOURCE_DISP1 + {0x34, 0x4830A001}, //CLK_RST_CONTROLLER_PLLD_BASE + {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 + {0x37, 0x2D0AAA} //CLK_RST_CONTROLLER_PLLD_MISC +}; + +//Display A config. +static const cfg_op_t _display_config_2[94] = { + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_REG_ACT_CONTROL, 0x54}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_DISP_DC_MCCIF_FIFOCTRL, 0}, + {DC_DISP_DISP_MEM_HIGH_PRIORITY, 0}, + {DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER, 0}, + {DC_CMD_DISPLAY_POWER_CONTROL, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE | PW4_ENABLE | PM0_ENABLE | PM1_ENABLE}, + {DC_CMD_GENERAL_INCR_SYNCPT_CNTRL, SYNCPT_CNTRL_NO_STALL}, + {DC_CMD_CONT_SYNCPT_VSYNC, SYNCPT_VSYNC_ENABLE | 0x9}, // 9: SYNCPT + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, + {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, + {0x4E4, 0}, + {DC_COM_CRC_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ} +}; + +//DSI Init config. +static const cfg_op_t _display_config_3[60] = { + {DSI_WR_DATA, 0}, + {DSI_INT_ENABLE, 0}, + {DSI_INT_STATUS, 0}, + {DSI_INT_MASK, 0}, + {DSI_INIT_SEQ_DATA_0, 0}, + {DSI_INIT_SEQ_DATA_1, 0}, + {DSI_INIT_SEQ_DATA_2, 0}, + {DSI_INIT_SEQ_DATA_3, 0}, + {DSI_DCS_CMDS, 0}, + {DSI_PKT_SEQ_0_LO, 0}, + {DSI_PKT_SEQ_1_LO, 0}, + {DSI_PKT_SEQ_2_LO, 0}, + {DSI_PKT_SEQ_3_LO, 0}, + {DSI_PKT_SEQ_4_LO, 0}, + {DSI_PKT_SEQ_5_LO, 0}, + {DSI_PKT_SEQ_0_HI, 0}, + {DSI_PKT_SEQ_1_HI, 0}, + {DSI_PKT_SEQ_2_HI, 0}, + {DSI_PKT_SEQ_3_HI, 0}, + {DSI_PKT_SEQ_4_HI, 0}, + {DSI_PKT_SEQ_5_HI, 0}, + {DSI_CONTROL, 0}, + {DSI_PAD_CONTROL_CD, 0}, + {DSI_SOL_DELAY, 0x18}, + {DSI_MAX_THRESHOLD, 0x1E0}, + {DSI_TRIGGER, 0}, + {DSI_INIT_SEQ_CONTROL, 0}, + {DSI_PKT_LEN_0_1, 0}, + {DSI_PKT_LEN_2_3, 0}, + {DSI_PKT_LEN_4_5, 0}, + {DSI_PKT_LEN_6_7, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30109}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_PAD_CONTROL_0, DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0)}, // Enable + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, 0}, + {DSI_POWER_CONTROL, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30118}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_MAX_THRESHOLD, 0x40}, + {DSI_TRIGGER, 0}, + {DSI_TX_CRC, 0}, + {DSI_INIT_SEQ_CONTROL, 0} +}; + +//DSI config (if ver == 0x10). +static const cfg_op_t _display_config_4[43] = { + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0x9483FFB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xBD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x1939}, + {DSI_WR_DATA, 0xAAAAAAD8}, + {DSI_WR_DATA, 0xAAAAAAEB}, + {DSI_WR_DATA, 0xAAEBAAAA}, + {DSI_WR_DATA, 0xAAAAAAAA}, + {DSI_WR_DATA, 0xAAAAAAEB}, + {DSI_WR_DATA, 0xAAEBAAAA}, + {DSI_WR_DATA, 0xAA}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x1BD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2739}, + {DSI_WR_DATA, 0xFFFFFFD8}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFF}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2BD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xF39}, + {DSI_WR_DATA, 0xFFFFFFD8}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFFFF}, + {DSI_WR_DATA, 0xFFFFFF}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xBD15}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x6D915}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0xB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST} +}; + +//DSI config. +static const cfg_op_t _display_config_5[21] = { + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30172}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xA40)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x5A2F) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_PKT_SEQ_0_LO, 0x40000208}, + {DSI_PKT_SEQ_2_LO, 0x40000308}, + {DSI_PKT_SEQ_4_LO, 0x40000308}, + {DSI_PKT_SEQ_1_LO, 0x40000308}, + {DSI_PKT_SEQ_3_LO, 0x3F3B2B08}, + {DSI_PKT_SEQ_3_HI, 0x2CC}, + {DSI_PKT_SEQ_5_LO, 0x3F3B2B08}, + {DSI_PKT_SEQ_5_HI, 0x2CC}, + {DSI_PKT_LEN_0_1, 0xCE0000}, + {DSI_PKT_LEN_2_3, 0x87001A2}, + {DSI_PKT_LEN_4_5, 0x190}, + {DSI_PKT_LEN_6_7, 0x190}, + {DSI_HOST_CONTROL, 0}, +}; + +//Clock config. +static const cfg_op_t _display_config_6[3] = { + {0x34, 0x4810C001}, //CLK_RST_CONTROLLER_PLLD_BASE + {0x36, 0x20}, //CLK_RST_CONTROLLER_PLLD_MISC1 + {0x37, 0x2DFC00} //CLK_RST_CONTROLLER_PLLD_MISC +}; + +//DSI config. +static const cfg_op_t _display_config_7[10] = { + {DSI_TRIGGER, 0}, + {DSI_CONTROL, 0}, + {DSI_SOL_DELAY, 6}, + {DSI_MAX_THRESHOLD, 0x1E0}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_FIFO_SEL| DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_HS_CLK_CTRL | DSI_CONTROL_FORMAT(3) | DSI_CONTROL_LANES(3) | DSI_CONTROL_VIDEO_ENABLE}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC} +}; + +//MIPI CAL config. +static const cfg_op_t _display_config_8[6] = { + {0x18, 0}, + {2, 0xF3F10000}, + {0x16, 1}, + {0x18, 0}, + {0x18, 0x10010}, + {0x17, 0x300} +}; + +//DSI config. +static const cfg_op_t _display_config_9[4] = { + {DSI_PAD_CONTROL_1, 0}, + {DSI_PAD_CONTROL_2, 0}, + {DSI_PAD_CONTROL_3, DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3)}, + {DSI_PAD_CONTROL_4, 0} +}; + +//MIPI CAL config. +static const cfg_op_t _display_config_10[16] = { + {0xE, 0x200200}, + {0xF, 0x200200}, + {0x19, 0x200002}, + {0x1A, 0x200002}, + {5, 0}, + {6, 0}, + {7, 0}, + {8, 0}, + {9, 0}, + {0xA, 0}, + {0x10, 0}, + {0x11, 0}, + {0x1A, 0}, + {0x1C, 0}, + {0x1D, 0}, + {0, 0x2A000001} +}; + +//Display A config. +static const cfg_op_t _display_config_11[113] = { + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_DV_CONTROL, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + /* Setup default YUV colorspace conversion coefficients */ + {DC_WIN_CSC_YOF, 0xF0}, + {DC_WIN_CSC_KYRGB, 0x12A}, + {DC_WIN_CSC_KUR, 0}, + {DC_WIN_CSC_KVR, 0x198}, + {DC_WIN_CSC_KUG, 0x39B}, + {DC_WIN_CSC_KVG, 0x32F}, + {DC_WIN_CSC_KUB, 0x204}, + {DC_WIN_CSC_KVB, 0}, + /* End of color coefficients */ + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000}, + {DC_COM_PIN_OUTPUT_POLARITY(3), 0}, + {0x4E4, 0}, + {DC_COM_CRC_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {0x716, 0x10000FF}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + /* Set Display timings */ + {DC_DISP_DISP_TIMING_OPTIONS, 0}, + {DC_DISP_REF_TO_SYNC, (1 << 16)}, // h_ref_to_sync = 0, v_ref_to_sync = 1. + {DC_DISP_SYNC_WIDTH, 0x10048}, + {DC_DISP_BACK_PORCH, 0x90048}, + {DC_DISP_ACTIVE, 0x50002D0}, + {DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the DC_DISP_ACTIVE cmd. + /* End of Display timings */ + {DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE}, + {DC_COM_PIN_OUTPUT_ENABLE(1), 0}, + {DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL}, + {DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C}, + {DC_DISP_DISP_CLOCK_CONTROL, 0}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_ACCESS, READ_MUX | WRITE_MUX}, + {DC_DISP_FRONT_PORCH, 0xA0088}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_DISP_DISP_CLOCK_CONTROL, PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4)}, + {DC_DISP_DISP_COLOR_CONTROL, BASE_COLOR_SIZE_888}, + {DC_CMD_DISPLAY_COMMAND_OPTION0, 0} +}; + +////Display A config. +static const cfg_op_t _display_config_12[17] = { + {DC_DISP_FRONT_PORCH, 0xA0088}, + {DC_CMD_INT_MASK, 0}, + {DC_CMD_STATE_ACCESS, 0}, + {DC_CMD_INT_ENABLE, 0}, + {DC_CMD_CONT_SYNCPT_VSYNC, 0}, + {DC_CMD_DISPLAY_COMMAND, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_GENERAL_INCR_SYNCPT, 0x301}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, + {DC_CMD_DISPLAY_POWER_CONTROL, 0}, + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE}, + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ}, +}; + +//DSI config. +static const cfg_op_t _display_config_13[16] = { + {DSI_POWER_CONTROL, 0}, + {DSI_PAD_CONTROL_1, 0}, + {DSI_PHY_TIMING_0, 0x6070601}, + {DSI_PHY_TIMING_1, 0x40A0E05}, + {DSI_PHY_TIMING_2, 0x30109}, + {DSI_BTA_TIMING, 0x190A14}, + {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) }, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TO_TALLY, 0}, + {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, + {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, + {DSI_POWER_CONTROL, DSI_POWER_CONTROL_ENABLE}, + {DSI_MAX_THRESHOLD, 0x40}, + {DSI_TRIGGER, 0}, + {DSI_TX_CRC, 0}, + {DSI_INIT_SEQ_CONTROL, 0} +}; + +//DSI config (if ver == 0x10). +static const cfg_op_t _display_config_14[22] = { + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0x9483FFB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x2139}, + {DSI_WR_DATA, 0x191919D5}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19191919}, + {DSI_WR_DATA, 0x19}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0xB39}, + {DSI_WR_DATA, 0x4F0F41B1}, + {DSI_WR_DATA, 0xF179A433}, + {DSI_WR_DATA, 0x2D81}, + {DSI_TRIGGER, DSI_TRIGGER_HOST}, + {DSI_WR_DATA, 0x439}, + {DSI_WR_DATA, 0xB9}, + {DSI_TRIGGER, DSI_TRIGGER_HOST} +}; + +//Display A config. +static const cfg_op_t cfg_display_one_color[8] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY} //DISPLAY_CTRL_MODE: continuous display. +}; + +//Display A config. +static const cfg_op_t cfg_display_framebuffer[32] = { + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT}, //Enable window C. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT}, //Enable window B. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT}, //Enable window A. + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_COLOR_DEPTH, WIN_COLOR_DEPTH_B8G8R8A8}, //T_A8R8G8B8 //NX Default: T_A8B8G8R8, WIN_COLOR_DEPTH_R8G8B8A8 + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_WIN_POSITION, 0}, //(0,0) + {DC_WIN_H_INITIAL_DDA, 0}, + {DC_WIN_V_INITIAL_DDA, 0}, + {DC_WIN_PRESCALED_SIZE, V_PRESCALED_SIZE(1280) | H_PRESCALED_SIZE(2880)}, //Pre-scaled size: 1280x2880 bytes. + {DC_WIN_DDA_INC, V_DDA_INC(0x1000) | H_DDA_INC(0x1000)}, + {DC_WIN_SIZE, V_SIZE(1280) | H_SIZE(720)}, //Window size: 1280 vertical lines x 720 horizontal pixels. + {DC_WIN_LINE_STRIDE, 0x6000C00}, //768*2x768*4 (= 0x600 x 0xC00) bytes, see TRM for alignment requirements. + {DC_WIN_BUFFER_CONTROL, 0}, + {DC_WINBUF_SURFACE_KIND, 0}, //Regular surface. + {DC_WINBUF_START_ADDR, 0xC0000000}, //Framebuffer address. + {DC_WINBUF_ADDR_H_OFFSET, 0}, + {DC_WINBUF_ADDR_V_OFFSET, 0}, + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, 0}, + {DC_DISP_DISP_WIN_OPTIONS, DSI_ENABLE}, //DSI_ENABLE + {DC_WIN_WIN_OPTIONS, WIN_ENABLE}, //Enable window AD. + {DC_CMD_DISPLAY_COMMAND, DISP_CTRL_MODE_C_DISPLAY}, //DISPLAY_CTRL_MODE: continuous display. + {DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE}, //General update; window A update. + {DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ} //General activation request; window A activation request. +}; diff --git a/sept/sept-secondary/src/display/cfb_console.c b/sept/sept-secondary/src/display/cfb_console.c new file mode 100644 index 000000000..9d2e95b7c --- /dev/null +++ b/sept/sept-secondary/src/display/cfb_console.c @@ -0,0 +1,1619 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * cfb_console.c + * + * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel. + * + * At the moment only the 8x16 font is tested and the font fore- and + * background color is limited to black/white/gray colors. The Linux + * logo can be placed in the upper left corner and additional board + * information strings (that normaly goes to serial port) can be drawed. + * + * The console driver can use the standard PC keyboard interface (i8042) + * for character input. Character output goes to a memory mapped video + * framebuffer with little or big-endian organisation. + * With environment setting 'console=serial' the console i/o can be + * forced to serial port. + + The driver uses graphic specific defines/parameters/functions: + + VIDEO_FB_LITTLE_ENDIAN - framebuffer organisation default: big endian + VIDEO_HW_RECTFILL - graphic driver supports hardware rectangle fill + VIDEO_HW_BITBLT - graphic driver supports hardware bit blt + + Console Parameters are set by config: + + CONFIG_VIDEO_VISIBLE_COLS - x resolution + CONFIG_VIDEO_VISIBLE_ROWS - y resolution + CONFIG_VIDEO_PIXEL_SIZE - storage size in byte per pixel + CONFIG_VIDEO_DATA_FORMAT - graphical data format GDF + + CONFIG_CONSOLE_CURSOR - on/off drawing cursor is done with delay + loop in VIDEO_TSTC_FCT (i8042) + CONFIG_SYS_CONSOLE_BLINK_COUNT - value for delay loop - blink rate + CONFIG_CONSOLE_TIME - display time/date in upper right corner, + needs CONFIG_CMD_DATE and CONFIG_CONSOLE_CURSOR + CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner + CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo + CONFIG_CONSOLE_EXTRA_INFO - display additional board information strings + that normaly goes to serial port. This define + requires a board specific function: + video_drawstring (VIDEO_INFO_X, + VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT, + info); + that fills a info buffer at i=row. + s.a: board/eltec/bab7xx. +CONFIG_VGA_AS_SINGLE_DEVICE - If set the framebuffer device will be initialised + as an output only device. The Keyboard driver + will not be set-up. This may be used, if you + have none or more than one Keyboard devices + (USB Keyboard, AT Keyboard). + +CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last character. No + blinking is provided. Uses the macros CURSOR_SET + and CURSOR_OFF. +CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability of the + graphic chip. Uses the macro CURSOR_SET. + ATTENTION: If booting an OS, the display driver + must disable the hardware register of the graphic + chip. Otherwise a blinking field is displayed +*/ + +#include "video_fb.h" +#include <string.h> + + +#if defined(CONFIG_VIDEO_FONT_SMALL) +#include "video_font_small.h" +#else +#include "video_font_large.h" +#endif + +#if defined(CONFIG_CMD_DATE) +#include <rtc.h> +#endif + +#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN) +#include <watchdog.h> +#include <bmp_layout.h> + +#ifdef CONFIG_SPLASH_SCREEN_ALIGN +#define BMP_ALIGN_CENTER 0x7FFF +#endif + +#endif + +/*****************************************************************************/ +/* Cursor definition: */ +/* CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/input/i8042.c) */ +/* to let the cursor blink. Uses the macros */ +/* CURSOR_OFF and CURSOR_ON. */ +/* CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No */ +/* blinking is provided. Uses the macros CURSOR_SET */ +/* and CURSOR_OFF. */ +/* CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the */ +/* graphic chip. Uses the macro CURSOR_SET. */ +/* ATTENTION: If booting an OS, the display driver */ +/* must disable the hardware register of the graphic */ +/* chip. Otherwise a blinking field is displayed */ +/*****************************************************************************/ +#if !defined(CONFIG_CONSOLE_CURSOR) && \ + !defined(CONFIG_VIDEO_SW_CURSOR) && \ + !defined(CONFIG_VIDEO_HW_CURSOR) +/* no Cursor defined */ +#define CURSOR_ON +#define CURSOR_OFF +#define CURSOR_SET +#endif + +#ifdef CONFIG_CONSOLE_CURSOR +#ifdef CURSOR_ON +#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined +#endif +void console_cursor (int state); +#define CURSOR_ON console_cursor(1) +#define CURSOR_OFF console_cursor(0) +#define CURSOR_SET +#else +#ifdef CONFIG_CONSOLE_TIME +#error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME +#endif +#endif /* CONFIG_CONSOLE_CURSOR */ + +#ifdef CONFIG_VIDEO_SW_CURSOR +#ifdef CURSOR_ON +#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined +#endif +#define CURSOR_ON +#define CURSOR_OFF video_putchar(console_col * VIDEO_FONT_WIDTH,\ + console_row * VIDEO_FONT_HEIGHT, ' ') +#define CURSOR_SET video_set_cursor() +#endif /* CONFIG_VIDEO_SW_CURSOR */ + + +#ifdef CONFIG_VIDEO_HW_CURSOR +#ifdef CURSOR_ON +#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined +#endif +#define CURSOR_ON +#define CURSOR_OFF +#define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \ + (console_row * VIDEO_FONT_HEIGHT) + video_logo_height) +#endif /* CONFIG_VIDEO_HW_CURSOR */ + +#ifdef CONFIG_VIDEO_LOGO +#ifdef CONFIG_VIDEO_BMP_LOGO +#include <bmp_logo.h> +#define VIDEO_LOGO_WIDTH BMP_LOGO_WIDTH +#define VIDEO_LOGO_HEIGHT BMP_LOGO_HEIGHT +#define VIDEO_LOGO_LUT_OFFSET BMP_LOGO_OFFSET +#define VIDEO_LOGO_COLORS BMP_LOGO_COLORS + +#else /* CONFIG_VIDEO_BMP_LOGO */ +#define LINUX_LOGO_WIDTH 80 +#define LINUX_LOGO_HEIGHT 80 +#define LINUX_LOGO_COLORS 214 +#define LINUX_LOGO_LUT_OFFSET 0x20 +#define __initdata +#include <linux_logo.h> +#define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH +#define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT +#define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET +#define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS +#endif /* CONFIG_VIDEO_BMP_LOGO */ +#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH) +#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2) +#else /* CONFIG_VIDEO_LOGO */ +#define VIDEO_LOGO_WIDTH 0 +#define VIDEO_LOGO_HEIGHT 0 +#endif /* CONFIG_VIDEO_LOGO */ + +#ifdef CONFIG_VIDEO_COLS +#define VIDEO_COLS CONFIG_VIDEO_COLS +#else +#define VIDEO_COLS CONFIG_VIDEO_VISIBLE_COLS +#endif + +#define VIDEO_ROWS CONFIG_VIDEO_VISIBLE_ROWS +#define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*CONFIG_VIDEO_PIXEL_SIZE) +#define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2) +#define VIDEO_LINE_LEN (VIDEO_COLS*CONFIG_VIDEO_PIXEL_SIZE) +#define VIDEO_BURST_LEN (VIDEO_COLS/8) + +#ifdef CONFIG_VIDEO_LOGO +#define CONSOLE_ROWS ((VIDEO_ROWS - video_logo_height) / VIDEO_FONT_HEIGHT) +#else +#define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT) +#endif + +#define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH) +#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN) +#define CONSOLE_ROW_FIRST (video_console_address) +#define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE) +#define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE) +#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS) +#define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE) + +/* Macros */ +#ifdef VIDEO_FB_LITTLE_ENDIAN +#define SWAP16(x) ((((x) & 0x00ff) << 8) | ( (x) >> 8)) +#define SWAP32(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\ + (((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) ) +#define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | (((x) & 0x0000ff00) >> 8)|\ + (((x) & 0x00ff0000) << 8) | (((x) & 0xff000000) >> 8) ) +#else +#define SWAP16(x) (x) +#define SWAP32(x) (x) +#if defined(VIDEO_FB_16BPP_WORD_SWAP) +#define SHORTSWAP32(x) ( ((x) >> 16) | ((x) << 16) ) +#else +#define SHORTSWAP32(x) (x) +#endif +#endif + +#if defined(DEBUG) || defined(DEBUG_CFB_CONSOLE) +#define PRINTD(x) printf(x) +#else +#define PRINTD(x) +#endif + + +#ifdef CONFIG_CONSOLE_EXTRA_INFO +extern void video_get_info_str ( /* setup a board string: type, speed, etc. */ + int line_number, /* location to place info string beside logo */ + char *info /* buffer for info string */ + ); + +#endif + +#define ALIGN_UP(addr, align) (((addr) + (align) - 1) & (~((align) - 1))) +#define WIDTH_BYTES (ALIGN_UP(VIDEO_FONT_WIDTH, 8) / 8) + +static void *video_fb_address; /* frame buffer address */ +static void *video_console_address; /* console buffer start address */ + +static int video_logo_height = VIDEO_LOGO_HEIGHT; + +static int console_col = 0; /* cursor col */ +static int console_row = 0; /* cursor row */ + +static uint32_t eorx, fgx, bgx; /* color pats */ + +static const int video_font_draw_table8[] = { + 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, + 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, + 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, + 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff }; + +static const int video_font_draw_table15[] = { + 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff }; + +static const int video_font_draw_table16[] = { + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff }; + +static const int video_font_draw_table24[16][3] = { + { 0x00000000, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x0000ffff, 0xff000000 }, + { 0x00000000, 0x0000ffff, 0xffffffff }, + { 0x000000ff, 0xffff0000, 0x00000000 }, + { 0x000000ff, 0xffff0000, 0x00ffffff }, + { 0x000000ff, 0xffffffff, 0xff000000 }, + { 0x000000ff, 0xffffffff, 0xffffffff }, + { 0xffffff00, 0x00000000, 0x00000000 }, + { 0xffffff00, 0x00000000, 0x00ffffff }, + { 0xffffff00, 0x0000ffff, 0xff000000 }, + { 0xffffff00, 0x0000ffff, 0xffffffff }, + { 0xffffffff, 0xffff0000, 0x00000000 }, + { 0xffffffff, 0xffff0000, 0x00ffffff }, + { 0xffffffff, 0xffffffff, 0xff000000 }, + { 0xffffffff, 0xffffffff, 0xffffffff } }; + +static const int video_font_draw_table32[16][4] = { + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff }, + { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 }, + { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff }, + { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 }, + { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff }, + { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 }, + { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff }, + { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 }, + { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } }; + + +/******************************************************************************/ + +static void video_drawchars (int xx, int yy, unsigned char *s, int count) +{ + uint8_t *cdat, *dest, *dest0; + int rows, offset, c, cols, tbits; + + offset = yy * VIDEO_LINE_LEN + xx * CONFIG_VIDEO_PIXEL_SIZE; + dest0 = video_fb_address + offset; + + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + case GDF__8BIT_332RGB: + while (count--) { + c = *s; + cdat = video_fontdata + c * (VIDEO_FONT_HEIGHT * WIDTH_BYTES); + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; + rows--; + dest += VIDEO_LINE_LEN) { + cols = 0; + tbits = VIDEO_FONT_WIDTH; + while (tbits > 0) { + uint8_t bits = *cdat++; + + ((uint32_t *) dest)[cols + 0] = (video_font_draw_table8[bits >> 4] & eorx) ^ bgx; + ((uint32_t *) dest)[cols + 1] = (video_font_draw_table8[bits & 15] & eorx) ^ bgx; + cols += 8; + tbits -= 8; + } + } + dest0 += VIDEO_FONT_WIDTH * CONFIG_VIDEO_PIXEL_SIZE; + s++; + } + break; + + case GDF_15BIT_555RGB: + while (count--) { + c = *s; + cdat = video_fontdata + c * (VIDEO_FONT_HEIGHT * WIDTH_BYTES); + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; + rows--; + dest += VIDEO_LINE_LEN) { + cols = 0; + tbits = VIDEO_FONT_WIDTH; + while (tbits > 0) { + uint8_t bits = *cdat++; + + ((uint32_t *) dest)[cols + 0] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 6] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 1] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 4 & 3] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 2] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 2 & 3] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 3] = SHORTSWAP32 ((video_font_draw_table15 [bits & 3] & eorx) ^ bgx); + cols += 8; + tbits -= 8; + } + } + dest0 += VIDEO_FONT_WIDTH * CONFIG_VIDEO_PIXEL_SIZE; + s++; + } + break; + + case GDF_16BIT_565RGB: + while (count--) { + c = *s; + cdat = video_fontdata + c * (VIDEO_FONT_HEIGHT * WIDTH_BYTES); + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; + rows--; + dest += VIDEO_LINE_LEN) { + cols = 0; + tbits = VIDEO_FONT_WIDTH; + while (tbits > 0) { + uint8_t bits = *cdat++; + + ((uint32_t *) dest)[cols + 0] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 6] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 1] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 4 & 3] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 2] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 2 & 3] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 3] = SHORTSWAP32 ((video_font_draw_table16 [bits & 3] & eorx) ^ bgx); + cols += 8; + tbits -= 8; + } + } + dest0 += VIDEO_FONT_WIDTH * CONFIG_VIDEO_PIXEL_SIZE; + s++; + } + break; + + case GDF_32BIT_X888RGB: + while (count--) { + c = *s; + cdat = video_fontdata + c * (VIDEO_FONT_HEIGHT * WIDTH_BYTES); + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; + rows--; + dest += VIDEO_LINE_LEN) { + cols = 0; + tbits = VIDEO_FONT_WIDTH; + while (tbits > 0) { + uint8_t bits = *cdat++; + + ((uint32_t *) dest)[cols + 0] = SWAP32 ((video_font_draw_table32 [bits >> 4][0] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 1] = SWAP32 ((video_font_draw_table32 [bits >> 4][1] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 2] = SWAP32 ((video_font_draw_table32 [bits >> 4][2] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 3] = SWAP32 ((video_font_draw_table32 [bits >> 4][3] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 4] = SWAP32 ((video_font_draw_table32 [bits & 15][0] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 5] = SWAP32 ((video_font_draw_table32 [bits & 15][1] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 6] = SWAP32 ((video_font_draw_table32 [bits & 15][2] & eorx) ^ bgx); + ((uint32_t *) dest)[cols + 7] = SWAP32 ((video_font_draw_table32 [bits & 15][3] & eorx) ^ bgx); + cols += 8; + tbits -= 8; + } + } + dest0 += VIDEO_FONT_WIDTH * CONFIG_VIDEO_PIXEL_SIZE; + s++; + } + break; + + case GDF_24BIT_888RGB: + while (count--) { + c = *s; + cdat = video_fontdata + c * (VIDEO_FONT_HEIGHT * WIDTH_BYTES); + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; + rows--; + dest += VIDEO_LINE_LEN) { + cols = 0; + tbits = VIDEO_FONT_WIDTH; + while (tbits > 0) { + uint8_t bits = *cdat++; + + ((uint32_t *) dest)[cols + 0] = (video_font_draw_table24[bits >> 4][0] & eorx) ^ bgx; + ((uint32_t *) dest)[cols + 1] = (video_font_draw_table24[bits >> 4][1] & eorx) ^ bgx; + ((uint32_t *) dest)[cols + 2] = (video_font_draw_table24[bits >> 4][2] & eorx) ^ bgx; + ((uint32_t *) dest)[cols + 3] = (video_font_draw_table24[bits & 15][0] & eorx) ^ bgx; + ((uint32_t *) dest)[cols + 4] = (video_font_draw_table24[bits & 15][1] & eorx) ^ bgx; + ((uint32_t *) dest)[cols + 5] = (video_font_draw_table24[bits & 15][2] & eorx) ^ bgx; + cols += 8; + tbits -= 8; + } + } + dest0 += VIDEO_FONT_WIDTH * CONFIG_VIDEO_PIXEL_SIZE; + s++; + } + break; + } +} + +/*****************************************************************************/ + +static inline void video_drawstring (int xx, int yy, unsigned char *s) +{ + video_drawchars (xx, yy, s, strlen ((char *)s)); +} + +/*****************************************************************************/ + +static void video_putchar (int xx, int yy, unsigned char c) +{ + video_drawchars (xx, yy + video_logo_height, &c, 1); +} + +/*****************************************************************************/ +#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR) +static void video_set_cursor (void) +{ + /* swap drawing colors */ + eorx = fgx; + fgx = bgx; + bgx = eorx; + eorx = fgx ^ bgx; + /* draw cursor */ + video_putchar (console_col * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, + ' '); + /* restore drawing colors */ + eorx = fgx; + fgx = bgx; + bgx = eorx; + eorx = fgx ^ bgx; +} +#endif +/*****************************************************************************/ +#ifdef CONFIG_CONSOLE_CURSOR +void console_cursor (int state) +{ + static int last_state = 0; + +#ifdef CONFIG_CONSOLE_TIME + struct rtc_time tm; + char info[16]; + + /* time update only if cursor is on (faster scroll) */ + if (state) { + rtc_get (&tm); + + sprintf (info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min, + tm.tm_sec); + video_drawstring (CONFIG_VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH, + VIDEO_INFO_Y, (uchar *)info); + + sprintf (info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon, + tm.tm_year); + video_drawstring (CONFIG_VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH, + VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT, (uchar *)info); + } +#endif + + if (state && (last_state != state)) { + video_set_cursor (); + } + + if (!state && (last_state != state)) { + /* clear cursor */ + video_putchar (console_col * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, + ' '); + } + + last_state = state; +} +#endif + +/*****************************************************************************/ + +#ifndef VIDEO_HW_RECTFILL +static void memsetl (int *p, int c, int v) +{ + while (c--) + *(p++) = v; +} +#endif + +/*****************************************************************************/ + + +static void console_scrollup (void) +{ + /* copy up rows ignoring the first one */ + +#ifdef VIDEO_HW_BITBLT + video_hw_bitblt (CONFIG_VIDEO_PIXEL_SIZE, /* bytes per pixel */ + 0, /* source pos x */ + video_logo_height + VIDEO_FONT_HEIGHT, /* source pos y */ + 0, /* dest pos x */ + video_logo_height, /* dest pos y */ + CONFIG_VIDEO_VISIBLE_COLS, /* frame width */ + CONFIG_VIDEO_VISIBLE_ROWS - video_logo_height - VIDEO_FONT_HEIGHT /* frame height */ + ); +#else + memmove(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, + CONSOLE_SCROLL_SIZE); +#endif + + /* clear the last one */ +#ifdef VIDEO_HW_RECTFILL + video_hw_rectfill (CONFIG_VIDEO_PIXEL_SIZE, /* bytes per pixel */ + 0, /* dest pos x */ + CONFIG_VIDEO_VISIBLE_ROWS - VIDEO_FONT_HEIGHT, /* dest pos y */ + CONFIG_VIDEO_VISIBLE_COLS, /* frame width */ + VIDEO_FONT_HEIGHT, /* frame height */ + CONSOLE_BG_COL /* fill color */ + ); +#else + memsetl (CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, CONSOLE_BG_COL); +#endif +} + +/*****************************************************************************/ + +static void console_back (void) +{ + CURSOR_OFF; + console_col--; + + if (console_col < 0) { + console_col = CONSOLE_COLS - 1; + console_row--; + if (console_row < 0) + console_row = 0; + } + video_putchar (console_col * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, + ' '); +} + +/*****************************************************************************/ + +static void console_newline (void) +{ + /* Check if last character in the line was just drawn. If so, cursor was + overwriten and need not to be cleared. Cursor clearing without this + check causes overwriting the 1st character of the line if line lenght + is >= CONSOLE_COLS + */ + if (console_col < CONSOLE_COLS) + CURSOR_OFF; + console_row++; + console_col = 0; + + /* Check if we need to scroll the terminal */ + if (console_row >= CONSOLE_ROWS) { + /* Scroll everything up */ + console_scrollup (); + + /* Decrement row number */ + console_row--; + } +} + +static void console_cr (void) +{ + CURSOR_OFF; + console_col = 0; +} + +/*****************************************************************************/ + +void video_putc (const char c) +{ + static int nl = 1; + + switch (c) { + case 13: /* back to first column */ + console_cr (); + break; + + case '\n': /* next line */ + if (console_col || (!console_col && nl)) + console_newline (); + nl = 1; + break; + + case 9: /* tab 8 */ + CURSOR_OFF; + console_col |= 0x0008; + console_col &= ~0x0007; + + if (console_col >= CONSOLE_COLS) + console_newline (); + break; + + case 8: /* backspace */ + console_back (); + break; + + default: /* draw the char */ + video_putchar (console_col * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, + c); + console_col++; + + /* check for newline */ + if (console_col >= CONSOLE_COLS) { + console_newline (); + nl = 0; + } + } + CURSOR_SET; +} + + +/*****************************************************************************/ + +void video_puts (const char *s) +{ + int count = strlen (s); + + while (count--) + video_putc (*s++); +} + +/*****************************************************************************/ + +/* + * Do not enforce drivers (or board code) to provide empty + * video_set_lut() if they do not support 8 bpp format. + * Implement weak default function instead. + */ +void __video_set_lut (unsigned int index, unsigned char r, + unsigned char g, unsigned char b) +{ +} +void video_set_lut (unsigned int, unsigned char, unsigned char, unsigned char) + __attribute__((weak, alias("__video_set_lut"))); + +#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN) + +#define FILL_8BIT_332RGB(r,g,b) { \ + *fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \ + fb ++; \ +} + +#define FILL_15BIT_555RGB(r,g,b) { \ + *(unsigned short *)fb = SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3))); \ + fb += 2; \ +} + +#define FILL_16BIT_565RGB(r,g,b) { \ + *(unsigned short *)fb = SWAP16((unsigned short)((((r)>>3)<<11) | (((g)>>2)<<5) | ((b)>>3))); \ + fb += 2; \ +} + +#define FILL_32BIT_X888RGB(r,g,b) { \ + *(unsigned long *)fb = SWAP32((unsigned long)(((r<<16) | (g<<8) | b))); \ + fb += 4; \ +} + +#ifdef VIDEO_FB_LITTLE_ENDIAN +#define FILL_24BIT_888RGB(r,g,b) { \ + fb[0] = b; \ + fb[1] = g; \ + fb[2] = r; \ + fb += 3; \ +} +#else +#define FILL_24BIT_888RGB(r,g,b) { \ + fb[0] = r; \ + fb[1] = g; \ + fb[2] = b; \ + fb += 3; \ +} +#endif + +#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) +static void inline fill_555rgb_pswap(uchar *fb, int x, + uint8_t r, uint8_t g, uint8_t b) +{ + ushort *dst = (ushort *)fb; + ushort color = (ushort)(((r >> 3) << 10) | + ((g >> 3) << 5) | + (b >> 3)); + if (x & 1) + *(--dst) = color; + else + *(++dst) = color; +} +#endif + +/* + * RLE8 bitmap support + */ + +#ifdef CONFIG_VIDEO_BMP_RLE8 +/* Pre-calculated color table entry */ +struct palette { + union { + unsigned short w; /* word */ + unsigned int dw; /* double word */ + } ce; /* color entry */ +}; + +/* + * Helper to draw encoded/unencoded run. + */ +static void draw_bitmap (uchar **fb, uchar *bm, struct palette *p, + int cnt, int enc) +{ + ulong addr = (ulong)*fb; + int *off; + int enc_off = 1; + int i; + + /* + * Setup offset of the color index in the bitmap. + * Color index of encoded run is at offset 1. + */ + off = enc ? &enc_off : &i; + + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + for (i = 0; i < cnt; i++) + *(unsigned char *)addr++ = bm[*off]; + break; + case GDF_15BIT_555RGB: + case GDF_16BIT_565RGB: + /* differences handled while pre-calculating palette */ + for (i = 0; i < cnt; i++) { + *(unsigned short *)addr = p[bm[*off]].ce.w; + addr += 2; + } + break; + case GDF_32BIT_X888RGB: + for (i = 0; i < cnt; i++) { + *(unsigned long *)addr = p[bm[*off]].ce.dw; + addr += 4; + } + break; + } + *fb = (uchar *)addr; /* return modified address */ +} + +static int display_rle8_bitmap (bmp_image_t *img, int xoff, int yoff, + int width, int height) +{ + unsigned char *bm; + unsigned char *fbp; + unsigned int cnt, runlen; + int decode = 1; + int x, y, bpp, i, ncolors; + struct palette p[256]; + bmp_color_table_entry_t cte; + int green_shift, red_off; + + x = 0; + y = __le32_to_cpu(img->header.height) - 1; + ncolors = __le32_to_cpu(img->header.colors_used); + bpp = CONFIG_VIDEO_PIXEL_SIZE; + fbp = (unsigned char *)((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + xoff) * bpp); + + bm = (uchar *)img + __le32_to_cpu(img->header.data_offset); + + /* pre-calculate and setup palette */ + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + video_set_lut (i, cte.red, cte.green, cte.blue); + } + break; + case GDF_15BIT_555RGB: + case GDF_16BIT_565RGB: + if (CONFIG_VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) { + green_shift = 3; + red_off = 10; + } else { + green_shift = 2; + red_off = 11; + } + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + p[i].ce.w = SWAP16((unsigned short) + (((cte.red >> 3) << red_off) | + ((cte.green >> green_shift) << 5) | + cte.blue >> 3)); + } + break; + case GDF_32BIT_X888RGB: + for (i = 0; i < ncolors; i++) { + cte = img->color_table[i]; + p[i].ce.dw = SWAP32((cte.red << 16) | (cte.green << 8) | + cte.blue); + } + break; + default: + printf("RLE Bitmap unsupported in video mode 0x%x\n", + CONFIG_VIDEO_DATA_FORMAT); + return -1; + } + + while (decode) { + switch (bm[0]) { + case 0: + switch (bm[1]) { + case 0: + /* scan line end marker */ + bm += 2; + x = 0; + y--; + fbp = (unsigned char *) + ((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + + xoff) * bpp); + continue; + case 1: + /* end of bitmap data marker */ + decode = 0; + break; + case 2: + /* run offset marker */ + x += bm[2]; + y -= bm[3]; + fbp = (unsigned char *) + ((unsigned int)video_fb_address + + (((y + yoff) * VIDEO_COLS) + + x + xoff) * bpp); + bm += 4; + break; + default: + /* unencoded run */ + cnt = bm[1]; + runlen = cnt; + bm += 2; + if (y < height) { + if (x >= width) { + x += runlen; + goto next_run; + } + if (x + runlen > width) + cnt = width - x; + + draw_bitmap (&fbp, bm, p, cnt, 0); + x += runlen; + } +next_run: + bm += runlen; + if (runlen & 1) + bm++; /* 0 padding if length is odd */ + } + break; + default: + /* encoded run */ + if (y < height) { /* only draw into visible area */ + cnt = bm[0]; + runlen = cnt; + if (x >= width) { + x += runlen; + bm += 2; + continue; + } + if (x + runlen > width) + cnt = width - x; + + draw_bitmap (&fbp, bm, p, cnt, 1); + x += runlen; + } + bm += 2; + break; + } + } + return 0; +} +#endif + +/* + * Display the BMP file located at address bmp_image. + */ +int video_display_bitmap (ulong bmp_image, int x, int y) +{ + unsigned xcount, ycount; + unsigned *fb; + bmp_image_t *bmp = (bmp_image_t *) bmp_image; + uchar *bmap; + unsigned padded_line; + unsigned long width, height, bpp; + unsigned colors; + unsigned long compression; + bmp_color_table_entry_t cte; +#ifdef CONFIG_VIDEO_BMP_GZIP + unsigned char *dst = NULL; + ulong len; +#endif + + WATCHDOG_RESET (); + + if (!((bmp->header.signature[0] == 'B') && + (bmp->header.signature[1] == 'M'))) { + +#ifdef CONFIG_VIDEO_BMP_GZIP + /* + * Could be a gzipped bmp image, try to decrompress... + */ + len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE; + dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE); + if (dst == NULL) { + printf("Error: malloc in gunzip failed!\n"); + return(1); + } + if (gunzip(dst, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, (uchar *)bmp_image, &len) != 0) { + printf ("Error: no valid bmp or bmp.gz image at %lx\n", bmp_image); + free(dst); + return 1; + } + if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) { + printf("Image could be truncated (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n"); + } + + /* + * Set addr to decompressed image + */ + bmp = (bmp_image_t *)dst; + + if (!((bmp->header.signature[0] == 'B') && + (bmp->header.signature[1] == 'M'))) { + printf ("Error: no valid bmp.gz image at %lx\n", bmp_image); + free(dst); + return 1; + } +#else + printf ("Error: no valid bmp image at %lx\n", bmp_image); + return 1; +#endif /* CONFIG_VIDEO_BMP_GZIP */ + } + + width = le32_to_cpu (bmp->header.width); + height = le32_to_cpu (bmp->header.height); + bpp = le16_to_cpu (bmp->header.bit_count); + colors = le32_to_cpu (bmp->header.colors_used); + compression = le32_to_cpu (bmp->header.compression); + + debug ("Display-bmp: %d x %d with %d colors\n", + width, height, colors); + + if (compression != BMP_BI_RGB +#ifdef CONFIG_VIDEO_BMP_RLE8 + && compression != BMP_BI_RLE8 +#endif + ) { + printf ("Error: compression type %ld not supported\n", + compression); +#ifdef CONFIG_VIDEO_BMP_GZIP + if (dst) + free(dst); +#endif + return 1; + } + + padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3; + +#ifdef CONFIG_SPLASH_SCREEN_ALIGN + if (x == BMP_ALIGN_CENTER) + x = max(0, (CONFIG_VIDEO_VISIBLE_COLS - width) / 2); + else if (x < 0) + x = max(0, CONFIG_VIDEO_VISIBLE_COLS - width + x + 1); + + if (y == BMP_ALIGN_CENTER) + y = max(0, (CONFIG_VIDEO_VISIBLE_ROWS - height) / 2); + else if (y < 0) + y = max(0, CONFIG_VIDEO_VISIBLE_ROWS - height + y + 1); +#endif /* CONFIG_SPLASH_SCREEN_ALIGN */ + + if ((x + width) > CONFIG_VIDEO_VISIBLE_COLS) + width = CONFIG_VIDEO_VISIBLE_COLS - x; + if ((y + height) > CONFIG_VIDEO_VISIBLE_ROWS) + height = CONFIG_VIDEO_VISIBLE_ROWS - y; + + bmap = (uchar *) bmp + le32_to_cpu (bmp->header.data_offset); + fb = (uchar *) (video_fb_address + + ((y + height - 1) * VIDEO_COLS * CONFIG_VIDEO_PIXEL_SIZE) + + x * CONFIG_VIDEO_PIXEL_SIZE); + +#ifdef CONFIG_VIDEO_BMP_RLE8 + if (compression == BMP_BI_RLE8) { + return display_rle8_bitmap(bmp, + x, y, width, height); + } +#endif + + /* We handle only 4, 8, or 24 bpp bitmaps */ + switch (le16_to_cpu (bmp->header.bit_count)) { + case 4: + padded_line -= width / 2; + ycount = height; + + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF_32BIT_X888RGB: + while (ycount--) { + WATCHDOG_RESET (); + /* + * Don't assume that 'width' is an + * even number + */ + for (xcount = 0; xcount < width; xcount++) { + uchar idx; + + if (xcount & 1) { + idx = *bmap & 0xF; + bmap++; + } else + idx = *bmap >> 4; + cte = bmp->color_table[idx]; + FILL_32BIT_X888RGB(cte.red, cte.green, + cte.blue); + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * + CONFIG_VIDEO_PIXEL_SIZE; + } + break; + default: + puts("4bpp bitmap unsupported with current " + "video mode\n"); + break; + } + break; + + case 8: + padded_line -= width; + if (CONFIG_VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) { + /* Copy colormap */ + for (xcount = 0; xcount < colors; ++xcount) { + cte = bmp->color_table[xcount]; + video_set_lut (xcount, cte.red, cte.green, cte.blue); + } + } + ycount = height; + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + *fb++ = *bmap++; + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF__8BIT_332RGB: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + cte = bmp->color_table[*bmap++]; + FILL_8BIT_332RGB (cte.red, cte.green, cte.blue); + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF_15BIT_555RGB: + while (ycount--) { +#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) + int xpos = x; +#endif + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + cte = bmp->color_table[*bmap++]; +#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) + fill_555rgb_pswap (fb, xpos++, cte.red, + cte.green, cte.blue); + fb += 2; +#else + FILL_15BIT_555RGB (cte.red, cte.green, cte.blue); +#endif + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF_16BIT_565RGB: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + cte = bmp->color_table[*bmap++]; + FILL_16BIT_565RGB (cte.red, cte.green, cte.blue); + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF_32BIT_X888RGB: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + cte = bmp->color_table[*bmap++]; + FILL_32BIT_X888RGB (cte.red, cte.green, cte.blue); + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF_24BIT_888RGB: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + cte = bmp->color_table[*bmap++]; + FILL_24BIT_888RGB (cte.red, cte.green, cte.blue); + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + } + break; + case 24: + padded_line -= 3 * width; + ycount = height; + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF__8BIT_332RGB: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + FILL_8BIT_332RGB (bmap[2], bmap[1], bmap[0]); + bmap += 3; + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF_15BIT_555RGB: + while (ycount--) { +#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) + int xpos = x; +#endif + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { +#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) + fill_555rgb_pswap (fb, xpos++, bmap[2], + bmap[1], bmap[0]); + fb += 2; +#else + FILL_15BIT_555RGB (bmap[2], bmap[1], bmap[0]); +#endif + bmap += 3; + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF_16BIT_565RGB: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + FILL_16BIT_565RGB (bmap[2], bmap[1], bmap[0]); + bmap += 3; + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF_32BIT_X888RGB: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + FILL_32BIT_X888RGB (bmap[2], bmap[1], bmap[0]); + bmap += 3; + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + case GDF_24BIT_888RGB: + while (ycount--) { + WATCHDOG_RESET (); + xcount = width; + while (xcount--) { + FILL_24BIT_888RGB (bmap[2], bmap[1], bmap[0]); + bmap += 3; + } + bmap += padded_line; + fb -= (CONFIG_VIDEO_VISIBLE_COLS + width) * CONFIG_VIDEO_PIXEL_SIZE; + } + break; + default: + printf ("Error: 24 bits/pixel bitmap incompatible with current video mode\n"); + break; + } + break; + default: + printf ("Error: %d bit/pixel bitmaps not supported by U-Boot\n", + le16_to_cpu (bmp->header.bit_count)); + break; + } + +#ifdef CONFIG_VIDEO_BMP_GZIP + if (dst) { + free(dst); + } +#endif + + return (0); +} +#endif + +/*****************************************************************************/ + +#ifdef CONFIG_VIDEO_LOGO +void logo_plot (void *screen, int width, int x, int y) +{ + + int xcount, i; + int skip = (width - VIDEO_LOGO_WIDTH) * CONFIG_VIDEO_PIXEL_SIZE; + int ycount = video_logo_height; + unsigned char r, g, b, *logo_red, *logo_blue, *logo_green; + unsigned char *source; + unsigned char *dest = (unsigned char *)screen + + ((y * width * CONFIG_VIDEO_PIXEL_SIZE) + + x * CONFIG_VIDEO_PIXEL_SIZE); + +#ifdef CONFIG_VIDEO_BMP_LOGO + source = bmp_logo_bitmap; + + /* Allocate temporary space for computing colormap */ + logo_red = malloc (BMP_LOGO_COLORS); + logo_green = malloc (BMP_LOGO_COLORS); + logo_blue = malloc (BMP_LOGO_COLORS); + /* Compute color map */ + for (i = 0; i < VIDEO_LOGO_COLORS; i++) { + logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4; + logo_green[i] = (bmp_logo_palette[i] & 0x00f0); + logo_blue[i] = (bmp_logo_palette[i] & 0x000f) << 4; + } +#else + source = linux_logo; + logo_red = linux_logo_red; + logo_green = linux_logo_green; + logo_blue = linux_logo_blue; +#endif + + if (CONFIG_VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) { + for (i = 0; i < VIDEO_LOGO_COLORS; i++) { + video_set_lut (i + VIDEO_LOGO_LUT_OFFSET, + logo_red[i], logo_green[i], logo_blue[i]); + } + } + + while (ycount--) { +#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) + int xpos = x; +#endif + xcount = VIDEO_LOGO_WIDTH; + while (xcount--) { + r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET]; + g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET]; + b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET]; + + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + *dest = *source; + break; + case GDF__8BIT_332RGB: + *dest = ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6); + break; + case GDF_15BIT_555RGB: +#if defined(VIDEO_FB_16BPP_PIXEL_SWAP) + fill_555rgb_pswap (dest, xpos++, r, g, b); +#else + *(unsigned short *) dest = + SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3))); +#endif + break; + case GDF_16BIT_565RGB: + *(unsigned short *) dest = + SWAP16 ((unsigned short) (((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3))); + break; + case GDF_32BIT_X888RGB: + *(unsigned long *) dest = + SWAP32 ((unsigned long) ((r << 16) | (g << 8) | b)); + break; + case GDF_24BIT_888RGB: +#ifdef VIDEO_FB_LITTLE_ENDIAN + dest[0] = b; + dest[1] = g; + dest[2] = r; +#else + dest[0] = r; + dest[1] = g; + dest[2] = b; +#endif + break; + } + source++; + dest += CONFIG_VIDEO_PIXEL_SIZE; + } + dest += skip; + } +#ifdef CONFIG_VIDEO_BMP_LOGO + free (logo_red); + free (logo_green); + free (logo_blue); +#endif +} + +/*****************************************************************************/ + +static void *video_logo (void) +{ + char info[128]; + extern char version_string; + int space, len, y_off = 0; + +#ifdef CONFIG_SPLASH_SCREEN + char *s; + ulong addr; + + if ((s = getenv ("splashimage")) != NULL) { + int x = 0, y = 0; + + addr = simple_strtoul (s, NULL, 16); +#ifdef CONFIG_SPLASH_SCREEN_ALIGN + if ((s = getenv ("splashpos")) != NULL) { + if (s[0] == 'm') + x = BMP_ALIGN_CENTER; + else + x = simple_strtol (s, NULL, 0); + + if ((s = strchr (s + 1, ',')) != NULL) { + if (s[1] == 'm') + y = BMP_ALIGN_CENTER; + else + y = simple_strtol (s + 1, NULL, 0); + } + } +#endif /* CONFIG_SPLASH_SCREEN_ALIGN */ + + if (video_display_bitmap (addr, x, y) == 0) { + video_logo_height = 0; + return ((void *) (video_fb_address)); + } + } +#endif /* CONFIG_SPLASH_SCREEN */ + + logo_plot (video_fb_address, VIDEO_COLS, 0, 0); + + sprintf (info, " %s", &version_string); + + space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH; + len = strlen(info); + + if (len > space) { + video_drawchars (VIDEO_INFO_X, VIDEO_INFO_Y, + (uchar *)info, space); + video_drawchars (VIDEO_INFO_X + VIDEO_FONT_WIDTH, + VIDEO_INFO_Y + VIDEO_FONT_HEIGHT, + (uchar *)info + space, len - space); + y_off = 1; + } else + video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *)info); + +#ifdef CONFIG_CONSOLE_EXTRA_INFO + { + int i, n = ((video_logo_height - VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT); + + for (i = 1; i < n; i++) { + video_get_info_str (i, info); + if (!*info) + continue; + + len = strlen(info); + if (len > space) { + video_drawchars (VIDEO_INFO_X, + VIDEO_INFO_Y + + (i + y_off) * VIDEO_FONT_HEIGHT, + (uchar *)info, space); + y_off++; + video_drawchars (VIDEO_INFO_X + VIDEO_FONT_WIDTH, + VIDEO_INFO_Y + + (i + y_off) * VIDEO_FONT_HEIGHT, + (uchar *)info + space, + len - space); + } else { + video_drawstring (VIDEO_INFO_X, + VIDEO_INFO_Y + + (i + y_off) * VIDEO_FONT_HEIGHT, + (uchar *)info); + } + } + } +#endif + + return (video_fb_address + video_logo_height * VIDEO_LINE_LEN); +} +#endif + + +/*****************************************************************************/ + +int video_resume(void *videobase, int row, int col) { + unsigned char color8; + + video_fb_address = videobase; +#ifdef CONFIG_VIDEO_HW_CURSOR + video_init_hw_cursor (VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT); +#endif + + /* Init drawing pats */ + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL); + video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL); + fgx = 0x01010101; + bgx = 0x00000000; + break; + case GDF__8BIT_332RGB: + color8 = ((CONSOLE_FG_COL & 0xe0) | + ((CONSOLE_FG_COL >> 3) & 0x1c) | CONSOLE_FG_COL >> 6); + fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8; + color8 = ((CONSOLE_BG_COL & 0xe0) | + ((CONSOLE_BG_COL >> 3) & 0x1c) | CONSOLE_BG_COL >> 6); + bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8; + break; + case GDF_15BIT_555RGB: + fgx = (((CONSOLE_FG_COL >> 3) << 26) | + ((CONSOLE_FG_COL >> 3) << 21) | ((CONSOLE_FG_COL >> 3) << 16) | + ((CONSOLE_FG_COL >> 3) << 10) | ((CONSOLE_FG_COL >> 3) << 5) | + (CONSOLE_FG_COL >> 3)); + bgx = (((CONSOLE_BG_COL >> 3) << 26) | + ((CONSOLE_BG_COL >> 3) << 21) | ((CONSOLE_BG_COL >> 3) << 16) | + ((CONSOLE_BG_COL >> 3) << 10) | ((CONSOLE_BG_COL >> 3) << 5) | + (CONSOLE_BG_COL >> 3)); + break; + case GDF_16BIT_565RGB: + fgx = (((CONSOLE_FG_COL >> 3) << 27) | + ((CONSOLE_FG_COL >> 2) << 21) | ((CONSOLE_FG_COL >> 3) << 16) | + ((CONSOLE_FG_COL >> 3) << 11) | ((CONSOLE_FG_COL >> 2) << 5) | + (CONSOLE_FG_COL >> 3)); + bgx = (((CONSOLE_BG_COL >> 3) << 27) | + ((CONSOLE_BG_COL >> 2) << 21) | ((CONSOLE_BG_COL >> 3) << 16) | + ((CONSOLE_BG_COL >> 3) << 11) | ((CONSOLE_BG_COL >> 2) << 5) | + (CONSOLE_BG_COL >> 3)); + break; + case GDF_32BIT_X888RGB: + fgx = (CONSOLE_FG_COL << 16) | (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL; + bgx = (CONSOLE_BG_COL << 16) | (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL; + break; + case GDF_24BIT_888RGB: + fgx = (CONSOLE_FG_COL << 24) | (CONSOLE_FG_COL << 16) | + (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL; + bgx = (CONSOLE_BG_COL << 24) | (CONSOLE_BG_COL << 16) | + (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL; + break; + } + eorx = fgx ^ bgx; + +#ifdef CONFIG_VIDEO_LOGO + /* Plot the logo and get start point of console */ + PRINTD ("Video: Drawing the logo ...\n"); + video_console_address = video_logo (); +#else + video_console_address = video_fb_address; +#endif + + /* Initialize the console */ + console_col = col; + console_row = row; + + return 0; +} + +int video_get_col(void) { + return console_col; +} + +int video_get_row(void) { + return console_row; +} + +int video_init (void *videobase) +{ + unsigned char color8; + + video_fb_address = videobase; +#ifdef CONFIG_VIDEO_HW_CURSOR + video_init_hw_cursor (VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT); +#endif + + /* Init drawing pats */ + switch (CONFIG_VIDEO_DATA_FORMAT) { + case GDF__8BIT_INDEX: + video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL); + video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL); + fgx = 0x01010101; + bgx = 0x00000000; + break; + case GDF__8BIT_332RGB: + color8 = ((CONSOLE_FG_COL & 0xe0) | + ((CONSOLE_FG_COL >> 3) & 0x1c) | CONSOLE_FG_COL >> 6); + fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8; + color8 = ((CONSOLE_BG_COL & 0xe0) | + ((CONSOLE_BG_COL >> 3) & 0x1c) | CONSOLE_BG_COL >> 6); + bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8; + break; + case GDF_15BIT_555RGB: + fgx = (((CONSOLE_FG_COL >> 3) << 26) | + ((CONSOLE_FG_COL >> 3) << 21) | ((CONSOLE_FG_COL >> 3) << 16) | + ((CONSOLE_FG_COL >> 3) << 10) | ((CONSOLE_FG_COL >> 3) << 5) | + (CONSOLE_FG_COL >> 3)); + bgx = (((CONSOLE_BG_COL >> 3) << 26) | + ((CONSOLE_BG_COL >> 3) << 21) | ((CONSOLE_BG_COL >> 3) << 16) | + ((CONSOLE_BG_COL >> 3) << 10) | ((CONSOLE_BG_COL >> 3) << 5) | + (CONSOLE_BG_COL >> 3)); + break; + case GDF_16BIT_565RGB: + fgx = (((CONSOLE_FG_COL >> 3) << 27) | + ((CONSOLE_FG_COL >> 2) << 21) | ((CONSOLE_FG_COL >> 3) << 16) | + ((CONSOLE_FG_COL >> 3) << 11) | ((CONSOLE_FG_COL >> 2) << 5) | + (CONSOLE_FG_COL >> 3)); + bgx = (((CONSOLE_BG_COL >> 3) << 27) | + ((CONSOLE_BG_COL >> 2) << 21) | ((CONSOLE_BG_COL >> 3) << 16) | + ((CONSOLE_BG_COL >> 3) << 11) | ((CONSOLE_BG_COL >> 2) << 5) | + (CONSOLE_BG_COL >> 3)); + break; + case GDF_32BIT_X888RGB: + fgx = (CONSOLE_FG_COL << 16) | (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL; + bgx = (CONSOLE_BG_COL << 16) | (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL; + break; + case GDF_24BIT_888RGB: + fgx = (CONSOLE_FG_COL << 24) | (CONSOLE_FG_COL << 16) | + (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL; + bgx = (CONSOLE_BG_COL << 24) | (CONSOLE_BG_COL << 16) | + (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL; + break; + } + eorx = fgx ^ bgx; + +#ifdef CONFIG_VIDEO_LOGO + /* Plot the logo and get start point of console */ + PRINTD ("Video: Drawing the logo ...\n"); + video_console_address = video_logo (); +#else + video_console_address = video_fb_address; +#endif + + /* Initialize the console */ + console_col = 0; + console_row = 0; + + memsetl(CONSOLE_ROW_FIRST, VIDEO_COLS * VIDEO_ROWS, + CONSOLE_BG_COL); + + return 0; +} diff --git a/sept/sept-secondary/src/display/video_fb.h b/sept/sept-secondary/src/display/video_fb.h new file mode 100644 index 000000000..ebedc0626 --- /dev/null +++ b/sept/sept-secondary/src/display/video_fb.h @@ -0,0 +1,57 @@ +/* + * (C) Copyright 1997-2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _VIDEO_FB_H_ +#define _VIDEO_FB_H_ + +#define CONSOLE_BG_COL 0x00 +#define CONSOLE_FG_COL 0xa0 + +/* Try using the small font */ +#define CONFIG_VIDEO_FONT_SMALL + +/* + * Graphic Data Format (GDF) bits for VIDEO_DATA_FORMAT + */ +#define GDF__8BIT_INDEX 0 +#define GDF_15BIT_555RGB 1 +#define GDF_16BIT_565RGB 2 +#define GDF_32BIT_X888RGB 3 +#define GDF_24BIT_888RGB 4 +#define GDF__8BIT_332RGB 5 + +#define CONFIG_VIDEO_FB_LITTLE_ENDIAN +#define CONFIG_VIDEO_VISIBLE_COLS 720 +#define CONFIG_VIDEO_VISIBLE_ROWS 1280 +#define CONFIG_VIDEO_COLS 768 +#define CONFIG_VIDEO_PIXEL_SIZE 4 +#define CONFIG_VIDEO_DATA_FORMAT GDF_32BIT_X888RGB /* BGR actually, but w/e */ + +int video_get_col(void); +int video_get_row(void); + +int video_init(void *fb); +int video_resume(void *fb, int row, int col); +void video_puts(const char *s); + +#endif /*_VIDEO_FB_H_ */ diff --git a/sept/sept-secondary/src/display/video_font_large.h b/sept/sept-secondary/src/display/video_font_large.h new file mode 100644 index 000000000..7bb504ed5 --- /dev/null +++ b/sept/sept-secondary/src/display/video_font_large.h @@ -0,0 +1,6181 @@ +/* + * (C) Copyright 2014 + * Andrey Warkentin <andrey.warkentin@gmail.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _VIDEO_FONT_LARGE_ +#define _VIDEO_FONT_LARGE_ + +#define FONTDATAMAX 11264 + +#define VIDEO_FONT_CHARS 256 +#define VIDEO_FONT_WIDTH 12 +#define VIDEO_FONT_HEIGHT 22 +#define VIDEO_FONT_SIZE (VIDEO_FONT_CHARS * VIDEO_FONT_HEIGHT) + +static unsigned char video_fontdata[FONTDATAMAX] = { + + /* 0 0x00 '^@' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 1 0x01 '^A' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x30, 0x60, /* 001100000110 */ + 0x65, 0x30, /* 011001010011 */ + 0x6d, 0xb0, /* 011011011011 */ + 0x60, 0x30, /* 011000000011 */ + 0x62, 0x30, /* 011000100011 */ + 0x62, 0x30, /* 011000100011 */ + 0x60, 0x30, /* 011000000011 */ + 0x6f, 0xb0, /* 011011111011 */ + 0x67, 0x30, /* 011001110011 */ + 0x30, 0x60, /* 001100000110 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 2 0x02 '^B' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x7a, 0xf0, /* 011110101111 */ + 0x72, 0x70, /* 011100100111 */ + 0x7f, 0xf0, /* 011111111111 */ + 0x7d, 0xf0, /* 011111011111 */ + 0x7d, 0xf0, /* 011111011111 */ + 0x7f, 0xf0, /* 011111111111 */ + 0x70, 0x70, /* 011100000111 */ + 0x78, 0xf0, /* 011110001111 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 3 0x03 '^C' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 4 0x04 '^D' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x02, 0x00, /* 000000100000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x0f, 0x80, /* 000011111000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x07, 0x00, /* 000001110000 */ + 0x02, 0x00, /* 000000100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 5 0x05 '^E' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x02, 0x00, /* 000000100000 */ + 0x07, 0x00, /* 000001110000 */ + 0x07, 0x00, /* 000001110000 */ + 0x02, 0x00, /* 000000100000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x3d, 0xe0, /* 001111011110 */ + 0x3d, 0xe0, /* 001111011110 */ + 0x1a, 0xc0, /* 000110101100 */ + 0x02, 0x00, /* 000000100000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 6 0x06 '^F' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x36, 0xc0, /* 001101101100 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 7 0x07 '^G' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 8 0x08 '^H' */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xf9, 0xf0, /* 111110011111 */ + 0xf0, 0xf0, /* 111100001111 */ + 0xf0, 0xf0, /* 111100001111 */ + 0xe0, 0x70, /* 111000000111 */ + 0xe0, 0x70, /* 111000000111 */ + 0xc0, 0x30, /* 110000000011 */ + 0xc0, 0x30, /* 110000000011 */ + 0xe0, 0x70, /* 111000000111 */ + 0xe0, 0x70, /* 111000000111 */ + 0xf0, 0xf0, /* 111100001111 */ + 0xf0, 0xf0, /* 111100001111 */ + 0xf9, 0xf0, /* 111110011111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + + /* 9 0x09 '^I' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 10 0x0a '^J' */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xf9, 0xf0, /* 111110011111 */ + 0xf0, 0xf0, /* 111100001111 */ + 0xf0, 0xf0, /* 111100001111 */ + 0xe6, 0x70, /* 111001100111 */ + 0xe6, 0x70, /* 111001100111 */ + 0xcf, 0x30, /* 110011110011 */ + 0xcf, 0x30, /* 110011110011 */ + 0xe6, 0x70, /* 111001100111 */ + 0xe6, 0x70, /* 111001100111 */ + 0xf0, 0xf0, /* 111100001111 */ + 0xf0, 0xf0, /* 111100001111 */ + 0xf9, 0xf0, /* 111110011111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + + /* 11 0x0b '^K' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0xe0, /* 000011111110 */ + 0x0f, 0xe0, /* 000011111110 */ + 0x01, 0xe0, /* 000000011110 */ + 0x03, 0x60, /* 000000110110 */ + 0x06, 0x60, /* 000001100110 */ + 0x1e, 0x00, /* 000111100000 */ + 0x33, 0x00, /* 001100110000 */ + 0x33, 0x00, /* 001100110000 */ + 0x61, 0x80, /* 011000011000 */ + 0x61, 0x80, /* 011000011000 */ + 0x33, 0x00, /* 001100110000 */ + 0x33, 0x00, /* 001100110000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 12 0x0c '^L' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x19, 0x80, /* 000110011000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 13 0x0d '^M' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0xe0, /* 000011111110 */ + 0x0c, 0x60, /* 000011000110 */ + 0x0c, 0x60, /* 000011000110 */ + 0x0f, 0xe0, /* 000011111110 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x3c, 0x00, /* 001111000000 */ + 0x7c, 0x00, /* 011111000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 14 0x0e '^N' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0xe0, /* 000111111110 */ + 0x18, 0x60, /* 000110000110 */ + 0x18, 0x60, /* 000110000110 */ + 0x1f, 0xe0, /* 000111111110 */ + 0x18, 0x60, /* 000110000110 */ + 0x18, 0x60, /* 000110000110 */ + 0x18, 0x60, /* 000110000110 */ + 0x18, 0x60, /* 000110000110 */ + 0x18, 0x60, /* 000110000110 */ + 0x18, 0x60, /* 000110000110 */ + 0x19, 0xe0, /* 000110011110 */ + 0x1b, 0xe0, /* 000110111110 */ + 0x1b, 0xc0, /* 000110111100 */ + 0x79, 0x80, /* 011110011000 */ + 0xf8, 0x00, /* 111110000000 */ + 0xf0, 0x00, /* 111100000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 15 0x0f '^O' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x0d, 0x80, /* 000011011000 */ + 0x6d, 0xb0, /* 011011011011 */ + 0x3d, 0xe0, /* 001111011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x3d, 0xe0, /* 001111011110 */ + 0x6d, 0xb0, /* 011011011011 */ + 0x0d, 0x80, /* 000011011000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 16 0x10 '^P' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x20, /* 000000000010 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0xe0, /* 000000001110 */ + 0x01, 0xe0, /* 000000011110 */ + 0x03, 0xe0, /* 000000111110 */ + 0x07, 0xe0, /* 000001111110 */ + 0x0f, 0xe0, /* 000011111110 */ + 0x1f, 0xe0, /* 000111111110 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x1f, 0xe0, /* 000111111110 */ + 0x0f, 0xe0, /* 000011111110 */ + 0x07, 0xe0, /* 000001111110 */ + 0x03, 0xe0, /* 000000111110 */ + 0x01, 0xe0, /* 000000011110 */ + 0x00, 0xe0, /* 000000001110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x20, /* 000000000010 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 17 0x11 '^Q' */ + 0x00, 0x00, /* 000000000000 */ + 0x40, 0x00, /* 010000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x7c, 0x00, /* 011111000000 */ + 0x7e, 0x00, /* 011111100000 */ + 0x7f, 0x00, /* 011111110000 */ + 0x7f, 0x80, /* 011111111000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x7f, 0x80, /* 011111111000 */ + 0x7f, 0x00, /* 011111110000 */ + 0x7e, 0x00, /* 011111100000 */ + 0x7c, 0x00, /* 011111000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x40, 0x00, /* 010000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 18 0x12 '^R' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 19 0x13 '^S' */ + 0x00, 0x00, /* 000000000000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 20 0x14 '^T' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0xf0, /* 000111111111 */ + 0x3c, 0xc0, /* 001111001100 */ + 0x7c, 0xc0, /* 011111001100 */ + 0x7c, 0xc0, /* 011111001100 */ + 0x7c, 0xc0, /* 011111001100 */ + 0x3c, 0xc0, /* 001111001100 */ + 0x1c, 0xc0, /* 000111001100 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x1c, 0xe0, /* 000111001110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 21 0x15 '^U' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x80, /* 000000011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 22 0x16 '^V' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 23 0x17 '^W' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 24 0x18 '^X' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 25 0x19 '^Y' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 26 0x1a '^Z' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x08, 0x00, /* 000010000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x38, 0x00, /* 001110000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0xff, 0xe0, /* 111111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x38, 0x00, /* 001110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x08, 0x00, /* 000010000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 27 0x1b '^[' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x00, /* 000000010000 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0xc0, /* 000000011100 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xf0, /* 011111111111 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x01, 0xc0, /* 000000011100 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x00, /* 000000010000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 28 0x1c '^\' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 29 0x1d '^]' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x09, 0x00, /* 000010010000 */ + 0x19, 0x80, /* 000110011000 */ + 0x39, 0xc0, /* 001110011100 */ + 0x7f, 0xe0, /* 011111111110 */ + 0xff, 0xf0, /* 111111111111 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x39, 0xc0, /* 001110011100 */ + 0x19, 0x80, /* 000110011000 */ + 0x09, 0x00, /* 000010010000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 30 0x1e '^^' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 31 0x1f '^_' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 32 0x20 ' ' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 33 0x21 '!' */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 34 0x22 '"' */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 35 0x23 '#' */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0x30, /* 000000110011 */ + 0x03, 0x30, /* 000000110011 */ + 0x03, 0x30, /* 000000110011 */ + 0x06, 0x60, /* 000001100110 */ + 0x1f, 0xf0, /* 000111111111 */ + 0x1f, 0xf0, /* 000111111111 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x33, 0x00, /* 001100110000 */ + 0x66, 0x00, /* 011001100000 */ + 0x66, 0x00, /* 011001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 36 0x24 '$' */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x66, 0xe0, /* 011001101110 */ + 0x66, 0x60, /* 011001100110 */ + 0x66, 0x00, /* 011001100000 */ + 0x3e, 0x00, /* 001111100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x07, 0xc0, /* 000001111100 */ + 0x06, 0x60, /* 000001100110 */ + 0x06, 0x60, /* 000001100110 */ + 0x66, 0x60, /* 011001100110 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 37 0x25 '%' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x38, 0xc0, /* 001110001100 */ + 0x4c, 0xc0, /* 010011001100 */ + 0x45, 0x80, /* 010001011000 */ + 0x65, 0x80, /* 011001011000 */ + 0x3b, 0x00, /* 001110110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0d, 0xc0, /* 000011011100 */ + 0x1a, 0x60, /* 000110100110 */ + 0x1a, 0x20, /* 000110100010 */ + 0x33, 0x20, /* 001100110010 */ + 0x31, 0xc0, /* 001100011100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 38 0x26 '&' */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x18, 0xc0, /* 000110001100 */ + 0x18, 0xc0, /* 000110001100 */ + 0x0f, 0x80, /* 000011111000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x3e, 0x00, /* 001111100000 */ + 0x77, 0x00, /* 011101110000 */ + 0x63, 0x60, /* 011000110110 */ + 0x61, 0xe0, /* 011000011110 */ + 0x61, 0xc0, /* 011000011100 */ + 0x61, 0x80, /* 011000011000 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x1e, 0x60, /* 000111100110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 39 0x27 ''' */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 40 0x28 '(' */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x01, 0x80, /* 000000011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 41 0x29 ')' */ + 0x00, 0x00, /* 000000000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 42 0x2a '*' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x66, 0x60, /* 011001100110 */ + 0x76, 0xe0, /* 011101101110 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x76, 0xe0, /* 011101101110 */ + 0x66, 0x60, /* 011001100110 */ + 0x06, 0x00, /* 000001100000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 43 0x2b '+' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 44 0x2c ',' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 45 0x2d '-' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 46 0x2e '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 47 0x2f '/' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 48 0x30 '0' */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0x80, /* 000100011000 */ + 0x10, 0xc0, /* 000100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0x80, /* 001100001000 */ + 0x18, 0x80, /* 000110001000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 49 0x31 '1' */ + 0x00, 0x00, /* 000000000000 */ + 0x02, 0x00, /* 000000100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x36, 0x00, /* 001101100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 50 0x32 '2' */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x61, 0xc0, /* 011000011100 */ + 0x40, 0xc0, /* 010000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x30, 0x20, /* 001100000010 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 51 0x33 '3' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x20, 0xe0, /* 001000001110 */ + 0x40, 0x60, /* 010000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0xe0, /* 000000001110 */ + 0x07, 0xc0, /* 000001111100 */ + 0x0f, 0xc0, /* 000011111100 */ + 0x00, 0xe0, /* 000000001110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x40, 0x60, /* 010000000110 */ + 0x60, 0x40, /* 011000000100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 52 0x34 '4' */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x80, /* 000000111000 */ + 0x03, 0x80, /* 000000111000 */ + 0x05, 0x80, /* 000001011000 */ + 0x05, 0x80, /* 000001011000 */ + 0x09, 0x80, /* 000010011000 */ + 0x09, 0x80, /* 000010011000 */ + 0x11, 0x80, /* 000100011000 */ + 0x11, 0x80, /* 000100011000 */ + 0x21, 0x80, /* 001000011000 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x80, /* 000000011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 53 0x35 '5' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0xc0, /* 000011111100 */ + 0x0f, 0xc0, /* 000011111100 */ + 0x10, 0x00, /* 000100000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x20, 0x00, /* 001000000000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x31, 0xc0, /* 001100011100 */ + 0x00, 0xe0, /* 000000001110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x40, 0x60, /* 010000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 54 0x36 '6' */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x67, 0x80, /* 011001111000 */ + 0x6f, 0xc0, /* 011011111100 */ + 0x70, 0xe0, /* 011100001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x40, /* 011100000100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 55 0x37 '7' */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0xe0, /* 000111111110 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x60, 0x40, /* 011000000100 */ + 0x00, 0x40, /* 000000000100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0x80, /* 000000001000 */ + 0x00, 0x80, /* 000000001000 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x00, /* 000000010000 */ + 0x01, 0x00, /* 000000010000 */ + 0x03, 0x00, /* 000000110000 */ + 0x02, 0x00, /* 000000100000 */ + 0x02, 0x00, /* 000000100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 56 0x38 '8' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x11, 0x80, /* 000100011000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x18, 0x80, /* 000110001000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x11, 0x80, /* 000100011000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x18, 0x80, /* 000110001000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 57 0x39 '9' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0xe0, /* 011100001110 */ + 0x3f, 0x60, /* 001111110110 */ + 0x1e, 0x60, /* 000111100110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x01, 0x80, /* 000000011000 */ + 0x07, 0x00, /* 000001110000 */ + 0x3c, 0x00, /* 001111000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 58 0x3a ':' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 59 0x3b ';' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 60 0x3c '<' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x60, /* 000000000110 */ + 0x01, 0xc0, /* 000000011100 */ + 0x07, 0x00, /* 000001110000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x07, 0x00, /* 000001110000 */ + 0x01, 0xc0, /* 000000011100 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 61 0x3d '=' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 62 0x3e '>' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x38, 0x00, /* 001110000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x03, 0x80, /* 000000111000 */ + 0x00, 0xe0, /* 000000001110 */ + 0x00, 0xe0, /* 000000001110 */ + 0x03, 0x80, /* 000000111000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x38, 0x00, /* 001110000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 63 0x3f '?' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x39, 0xc0, /* 001110011100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 64 0x40 '@' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x30, 0x60, /* 001100000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x67, 0x20, /* 011001110010 */ + 0x6f, 0xa0, /* 011011111010 */ + 0x6c, 0xa0, /* 011011001010 */ + 0x6c, 0xa0, /* 011011001010 */ + 0x67, 0xe0, /* 011001111110 */ + 0x60, 0x00, /* 011000000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x0f, 0xe0, /* 000011111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 65 0x41 'A' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x09, 0x00, /* 000010010000 */ + 0x11, 0x80, /* 000100011000 */ + 0x11, 0x80, /* 000100011000 */ + 0x10, 0x80, /* 000100001000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x20, 0x40, /* 001000000100 */ + 0x40, 0x60, /* 010000000110 */ + 0x40, 0x60, /* 010000000110 */ + 0xe0, 0xf0, /* 111000001111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 66 0x42 'B' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0x00, /* 111111110000 */ + 0x60, 0x80, /* 011000001000 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x61, 0x80, /* 011000011000 */ + 0x7f, 0x80, /* 011111111000 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0xc0, /* 011000001100 */ + 0xff, 0x80, /* 111111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 67 0x43 'C' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0xc0, /* 000011111100 */ + 0x10, 0x60, /* 000100000110 */ + 0x20, 0x20, /* 001000000010 */ + 0x20, 0x00, /* 001000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x20, 0x00, /* 001000000000 */ + 0x30, 0x20, /* 001100000010 */ + 0x18, 0x40, /* 000110000100 */ + 0x0f, 0x80, /* 000011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 68 0x44 'D' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0x00, /* 111111110000 */ + 0x61, 0xc0, /* 011000011100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x40, /* 011000000100 */ + 0x61, 0x80, /* 011000011000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 69 0x45 'E' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x30, 0x40, /* 001100000100 */ + 0x30, 0x40, /* 001100000100 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x80, /* 001100001000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x30, 0x80, /* 001100001000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x20, /* 001100000010 */ + 0x30, 0x20, /* 001100000010 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 70 0x46 'F' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x30, 0x40, /* 001100000100 */ + 0x30, 0x40, /* 001100000100 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x80, /* 001100001000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x30, 0x80, /* 001100001000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 71 0x47 'G' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0xc0, /* 000011111100 */ + 0x10, 0x60, /* 000100000110 */ + 0x20, 0x20, /* 001000000010 */ + 0x20, 0x00, /* 001000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x61, 0xf0, /* 011000011111 */ + 0x60, 0x60, /* 011000000110 */ + 0x20, 0x60, /* 001000000110 */ + 0x30, 0x60, /* 001100000110 */ + 0x18, 0x60, /* 000110000110 */ + 0x0f, 0x80, /* 000011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 72 0x48 'H' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf0, 0xf0, /* 111100001111 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0xf0, 0xf0, /* 111100001111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 73 0x49 'I' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 74 0x4a 'J' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x38, 0x00, /* 001110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 75 0x4b 'K' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf0, 0xe0, /* 111100001110 */ + 0x61, 0x80, /* 011000011000 */ + 0x63, 0x00, /* 011000110000 */ + 0x66, 0x00, /* 011001100000 */ + 0x6c, 0x00, /* 011011000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x7c, 0x00, /* 011111000000 */ + 0x6e, 0x00, /* 011011100000 */ + 0x67, 0x00, /* 011001110000 */ + 0x63, 0x80, /* 011000111000 */ + 0x61, 0xc0, /* 011000011100 */ + 0x60, 0xe0, /* 011000001110 */ + 0xf0, 0x70, /* 111100000111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 76 0x4c 'L' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x20, /* 001100000010 */ + 0x30, 0x20, /* 001100000010 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 77 0x4d 'M' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xe0, 0x70, /* 111000000111 */ + 0x60, 0xe0, /* 011000001110 */ + 0x70, 0xe0, /* 011100001110 */ + 0x70, 0xe0, /* 011100001110 */ + 0x70, 0xe0, /* 011100001110 */ + 0x59, 0x60, /* 010110010110 */ + 0x59, 0x60, /* 010110010110 */ + 0x59, 0x60, /* 010110010110 */ + 0x4d, 0x60, /* 010011010110 */ + 0x4e, 0x60, /* 010011100110 */ + 0x4e, 0x60, /* 010011100110 */ + 0x44, 0x60, /* 010001000110 */ + 0x44, 0x60, /* 010001000110 */ + 0xe4, 0xf0, /* 111001001111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 78 0x4e 'N' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xc0, 0x70, /* 110000000111 */ + 0x60, 0x20, /* 011000000010 */ + 0x70, 0x20, /* 011100000010 */ + 0x78, 0x20, /* 011110000010 */ + 0x58, 0x20, /* 010110000010 */ + 0x4c, 0x20, /* 010011000010 */ + 0x46, 0x20, /* 010001100010 */ + 0x47, 0x20, /* 010001110010 */ + 0x43, 0x20, /* 010000110010 */ + 0x41, 0xa0, /* 010000011010 */ + 0x40, 0xe0, /* 010000001110 */ + 0x40, 0xe0, /* 010000001110 */ + 0x40, 0x60, /* 010000000110 */ + 0xe0, 0x30, /* 111000000011 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 79 0x4f 'O' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x20, 0x60, /* 001000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x20, 0x40, /* 001000000100 */ + 0x30, 0x40, /* 001100000100 */ + 0x18, 0x80, /* 000110001000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 80 0x50 'P' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0x80, /* 011111111000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x37, 0x80, /* 001101111000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 81 0x51 'Q' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x20, 0x60, /* 001000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x30, 0x40, /* 001100000100 */ + 0x38, 0x40, /* 001110000100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x23, 0x90, /* 001000111001 */ + 0x01, 0xe0, /* 000000011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 82 0x52 'R' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0x00, /* 111111110000 */ + 0x61, 0x80, /* 011000011000 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0x80, /* 011000001000 */ + 0x7f, 0x00, /* 011111110000 */ + 0x7c, 0x00, /* 011111000000 */ + 0x6e, 0x00, /* 011011100000 */ + 0x67, 0x00, /* 011001110000 */ + 0x63, 0x80, /* 011000111000 */ + 0x61, 0xc0, /* 011000011100 */ + 0x60, 0xe0, /* 011000001110 */ + 0xf0, 0x70, /* 111100000111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 83 0x53 'S' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0xe0, /* 000111111110 */ + 0x30, 0x60, /* 001100000110 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x70, 0x00, /* 011100000000 */ + 0x3c, 0x00, /* 001111000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x07, 0x80, /* 000001111000 */ + 0x01, 0xc0, /* 000000011100 */ + 0x00, 0xe0, /* 000000001110 */ + 0x40, 0x60, /* 010000000110 */ + 0x40, 0x60, /* 010000000110 */ + 0x60, 0xc0, /* 011000001100 */ + 0x7f, 0x80, /* 011111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 84 0x54 'T' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x46, 0x20, /* 010001100010 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 85 0x55 'U' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf0, 0x70, /* 111100000111 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x70, 0x40, /* 011100000100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 86 0x56 'V' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xe0, 0xe0, /* 111000001110 */ + 0x60, 0x40, /* 011000000100 */ + 0x30, 0x80, /* 001100001000 */ + 0x30, 0x80, /* 001100001000 */ + 0x30, 0x80, /* 001100001000 */ + 0x19, 0x00, /* 000110010000 */ + 0x19, 0x00, /* 000110010000 */ + 0x19, 0x00, /* 000110010000 */ + 0x0a, 0x00, /* 000010100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 87 0x57 'W' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xfe, 0xf0, /* 111111101111 */ + 0x66, 0x20, /* 011001100010 */ + 0x66, 0x20, /* 011001100010 */ + 0x66, 0x20, /* 011001100010 */ + 0x76, 0x20, /* 011101100010 */ + 0x77, 0x40, /* 011101110100 */ + 0x33, 0x40, /* 001100110100 */ + 0x37, 0x40, /* 001101110100 */ + 0x3b, 0xc0, /* 001110111100 */ + 0x3b, 0x80, /* 001110111000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 88 0x58 'X' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf0, 0x70, /* 111100000111 */ + 0x60, 0x20, /* 011000000010 */ + 0x30, 0x40, /* 001100000100 */ + 0x38, 0x80, /* 001110001000 */ + 0x18, 0x80, /* 000110001000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x11, 0x80, /* 000100011000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x40, 0x60, /* 010000000110 */ + 0xe0, 0xf0, /* 111000001111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 89 0x59 'Y' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf0, 0x70, /* 111100000111 */ + 0x60, 0x20, /* 011000000010 */ + 0x30, 0x40, /* 001100000100 */ + 0x18, 0x80, /* 000110001000 */ + 0x18, 0x80, /* 000110001000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 90 0x5a 'Z' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x20, 0xc0, /* 001000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x20, /* 000110000010 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 91 0x5b '[' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 92 0x5c '\' */ + 0x00, 0x00, /* 000000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x80, /* 000000011000 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 93 0x5d ']' */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 94 0x5e '^' */ + 0x00, 0x00, /* 000000000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1b, 0x00, /* 000110110000 */ + 0x31, 0x80, /* 001100011000 */ + 0x60, 0xc0, /* 011000001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 95 0x5f '_' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 96 0x60 '`' */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x00, /* 000000010000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x07, 0x80, /* 000001111000 */ + 0x07, 0x80, /* 000001111000 */ + 0x03, 0x00, /* 000000110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 97 0x61 'a' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x10, 0xc0, /* 000100001100 */ + 0x03, 0xc0, /* 000000111100 */ + 0x1c, 0xc0, /* 000111001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0xe0, /* 000111101110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 98 0x62 'b' */ + 0x00, 0x00, /* 000000000000 */ + 0x20, 0x00, /* 001000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0xe0, 0x00, /* 111000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x67, 0x80, /* 011001111000 */ + 0x6f, 0xc0, /* 011011111100 */ + 0x70, 0xe0, /* 011100001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x60, /* 011100000110 */ + 0x78, 0xc0, /* 011110001100 */ + 0x4f, 0x80, /* 010011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 99 0x63 'c' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x31, 0xc0, /* 001100011100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x70, 0x40, /* 011100000100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 100 0x64 'd' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0xe0, /* 000000001110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x0f, 0x60, /* 000011110110 */ + 0x31, 0xe0, /* 001100011110 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0xe0, /* 011100001110 */ + 0x39, 0x60, /* 001110010110 */ + 0x1e, 0x70, /* 000111100111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 101 0x65 'e' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x18, 0x60, /* 000110000110 */ + 0x0f, 0x80, /* 000011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 102 0x66 'f' */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0x80, /* 000000111000 */ + 0x04, 0xc0, /* 000001001100 */ + 0x04, 0xc0, /* 000001001100 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 103 0x67 'g' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x20, /* 000111110010 */ + 0x31, 0xe0, /* 001100011110 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x31, 0x80, /* 001100011000 */ + 0x3f, 0x00, /* 001111110000 */ + 0x60, 0x00, /* 011000000000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x20, 0x60, /* 001000000110 */ + 0x40, 0x20, /* 010000000010 */ + 0x40, 0x20, /* 010000000010 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 104 0x68 'h' */ + 0x00, 0x00, /* 000000000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x37, 0x80, /* 001101111000 */ + 0x39, 0xc0, /* 001110011100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x79, 0xe0, /* 011110011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 105 0x69 'i' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 106 0x6a 'j' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0xc0, /* 000000111100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x38, 0x80, /* 001110001000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 107 0x6b 'k' */ + 0x00, 0x00, /* 000000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0xe0, 0x00, /* 111000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x61, 0xc0, /* 011000011100 */ + 0x63, 0x00, /* 011000110000 */ + 0x66, 0x00, /* 011001100000 */ + 0x7c, 0x00, /* 011111000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x7c, 0x00, /* 011111000000 */ + 0x6e, 0x00, /* 011011100000 */ + 0x67, 0x00, /* 011001110000 */ + 0x63, 0x80, /* 011000111000 */ + 0xf1, 0xe0, /* 111100011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 108 0x6c 'l' */ + 0x00, 0x00, /* 000000000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 109 0x6d 'm' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xdd, 0xc0, /* 110111011100 */ + 0x6e, 0xe0, /* 011011101110 */ + 0x66, 0x60, /* 011001100110 */ + 0x66, 0x60, /* 011001100110 */ + 0x66, 0x60, /* 011001100110 */ + 0x66, 0x60, /* 011001100110 */ + 0x66, 0x60, /* 011001100110 */ + 0x66, 0x60, /* 011001100110 */ + 0x66, 0x60, /* 011001100110 */ + 0xef, 0x70, /* 111011110111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 110 0x6e 'n' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x27, 0x80, /* 001001111000 */ + 0x79, 0xc0, /* 011110011100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x79, 0xe0, /* 011110011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 111 0x6f 'o' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x40, /* 011100000100 */ + 0x38, 0x80, /* 001110001000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 112 0x70 'p' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xef, 0x80, /* 111011111000 */ + 0x71, 0xc0, /* 011100011100 */ + 0x60, 0xe0, /* 011000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x40, /* 011000000100 */ + 0x70, 0x80, /* 011100001000 */ + 0x7f, 0x00, /* 011111110000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0xf0, 0x00, /* 111100000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 113 0x71 'q' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x20, /* 000011110010 */ + 0x11, 0xe0, /* 000100011110 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x60, /* 011100000110 */ + 0x38, 0xe0, /* 001110001110 */ + 0x1f, 0xe0, /* 000111111110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0xf0, /* 000000001111 */ + 0x00, 0x00, /* 000000000000 */ + + /* 114 0x72 'r' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x73, 0x80, /* 011100111000 */ + 0x34, 0xc0, /* 001101001100 */ + 0x38, 0xc0, /* 001110001100 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 115 0x73 's' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0x40, /* 001100000100 */ + 0x38, 0x00, /* 001110000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x07, 0x80, /* 000001111000 */ + 0x01, 0xc0, /* 000000011100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x3f, 0x80, /* 001111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 116 0x74 't' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x20, /* 000011000010 */ + 0x0e, 0x40, /* 000011100100 */ + 0x07, 0x80, /* 000001111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 117 0x75 'u' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x79, 0xe0, /* 011110011110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0x60, /* 000111100110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 118 0x76 'v' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf0, 0x70, /* 111100000111 */ + 0x60, 0x20, /* 011000000010 */ + 0x30, 0x40, /* 001100000100 */ + 0x30, 0x40, /* 001100000100 */ + 0x18, 0x80, /* 000110001000 */ + 0x18, 0x80, /* 000110001000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 119 0x77 'w' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0x70, /* 111111110111 */ + 0x66, 0x20, /* 011001100010 */ + 0x66, 0x20, /* 011001100010 */ + 0x66, 0x20, /* 011001100010 */ + 0x37, 0x40, /* 001101110100 */ + 0x3b, 0x40, /* 001110110100 */ + 0x3b, 0x40, /* 001110110100 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 120 0x78 'x' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf8, 0xf0, /* 111110001111 */ + 0x70, 0x40, /* 011100000100 */ + 0x38, 0x80, /* 001110001000 */ + 0x1d, 0x00, /* 000111010000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0b, 0x80, /* 000010111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xe0, /* 001000001110 */ + 0xf1, 0xf0, /* 111100011111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 121 0x79 'y' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf0, 0xf0, /* 111100001111 */ + 0x60, 0x20, /* 011000000010 */ + 0x30, 0x40, /* 001100000100 */ + 0x30, 0x40, /* 001100000100 */ + 0x18, 0x80, /* 000110001000 */ + 0x18, 0x80, /* 000110001000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x08, 0x00, /* 000010000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 122 0x7a 'z' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0xe0, /* 011000001110 */ + 0x41, 0xc0, /* 010000011100 */ + 0x03, 0x80, /* 000000111000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x38, 0x20, /* 001110000010 */ + 0x70, 0x60, /* 011100000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 123 0x7b '{' */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0x80, /* 000000111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x38, 0x00, /* 001110000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x80, /* 000000111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 124 0x7c '|' */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 125 0x7d '}' */ + 0x00, 0x00, /* 000000000000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x01, 0xc0, /* 000000011100 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 126 0x7e '~' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1c, 0x20, /* 000111000010 */ + 0x3e, 0x60, /* 001111100110 */ + 0x67, 0xc0, /* 011001111100 */ + 0x43, 0x80, /* 010000111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 127 0x7f '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + + /* 128 0x80 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0xc0, /* 000011111100 */ + 0x10, 0x60, /* 000100000110 */ + 0x20, 0x20, /* 001000000010 */ + 0x20, 0x00, /* 001000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x20, 0x00, /* 001000000000 */ + 0x30, 0x20, /* 001100000010 */ + 0x18, 0x40, /* 000110000100 */ + 0x0f, 0x80, /* 000011111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x01, 0x80, /* 000000011000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 129 0x81 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x79, 0xe0, /* 011110011110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0x60, /* 000111100110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 130 0x82 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x18, 0x60, /* 000110000110 */ + 0x0f, 0x80, /* 000011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 131 0x83 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x02, 0x00, /* 000000100000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x10, 0xc0, /* 000100001100 */ + 0x03, 0xc0, /* 000000111100 */ + 0x1c, 0xc0, /* 000111001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0xe0, /* 000111101110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 132 0x84 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x10, 0xc0, /* 000100001100 */ + 0x03, 0xc0, /* 000000111100 */ + 0x1c, 0xc0, /* 000111001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0xe0, /* 000111101110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 133 0x85 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x10, 0xc0, /* 000100001100 */ + 0x03, 0xc0, /* 000000111100 */ + 0x1c, 0xc0, /* 000111001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0xe0, /* 000111101110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 134 0x86 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x07, 0x00, /* 000001110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x10, 0xc0, /* 000100001100 */ + 0x03, 0xc0, /* 000000111100 */ + 0x1c, 0xc0, /* 000111001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0xe0, /* 000111101110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 135 0x87 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x31, 0xc0, /* 001100011100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x70, 0x40, /* 011100000100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x01, 0x80, /* 000000011000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 136 0x88 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x02, 0x00, /* 000000100000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x18, 0x60, /* 000110000110 */ + 0x0f, 0x80, /* 000011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 137 0x89 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x18, 0x60, /* 000110000110 */ + 0x0f, 0x80, /* 000011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 138 0x8a '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0x00, /* 011000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x18, 0x60, /* 000110000110 */ + 0x0f, 0x80, /* 000011111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 139 0x8b '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 140 0x8c '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x1b, 0x00, /* 000110110000 */ + 0x31, 0x80, /* 001100011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 141 0x8d '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 142 0x8e '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x04, 0x00, /* 000001000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x11, 0x80, /* 000100011000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x40, 0x60, /* 010000000110 */ + 0xe0, 0xf0, /* 111000001111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 143 0x8f '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x04, 0x00, /* 000001000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x11, 0x80, /* 000100011000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x40, 0x60, /* 010000000110 */ + 0xe0, 0xf0, /* 111000001111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 144 0x90 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x08, 0x00, /* 000010000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x30, 0x20, /* 001100000010 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x80, /* 001100001000 */ + 0x3f, 0x80, /* 001111111000 */ + 0x30, 0x80, /* 001100001000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x20, /* 001100000010 */ + 0x30, 0x20, /* 001100000010 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 145 0x91 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x3d, 0xe0, /* 001111011110 */ + 0x66, 0x30, /* 011001100011 */ + 0x46, 0x30, /* 010001100011 */ + 0x06, 0x30, /* 000001100011 */ + 0x3f, 0xf0, /* 001111111111 */ + 0x66, 0x00, /* 011001100000 */ + 0xc6, 0x00, /* 110001100000 */ + 0xc6, 0x00, /* 110001100000 */ + 0xe7, 0x30, /* 111001110011 */ + 0x7d, 0xe0, /* 011111011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 146 0x92 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0xf0, /* 000000111111 */ + 0x07, 0x10, /* 000001110001 */ + 0x07, 0x10, /* 000001110001 */ + 0x0b, 0x00, /* 000010110000 */ + 0x0b, 0x00, /* 000010110000 */ + 0x0b, 0x20, /* 000010110010 */ + 0x13, 0xe0, /* 000100111110 */ + 0x13, 0x20, /* 000100110010 */ + 0x3f, 0x00, /* 001111110000 */ + 0x23, 0x00, /* 001000110000 */ + 0x23, 0x00, /* 001000110000 */ + 0x43, 0x10, /* 010000110001 */ + 0x43, 0x10, /* 010000110001 */ + 0xe7, 0xf0, /* 111001111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 147 0x93 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x02, 0x00, /* 000000100000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x40, /* 011100000100 */ + 0x38, 0x80, /* 001110001000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 148 0x94 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x40, /* 011100000100 */ + 0x38, 0x80, /* 001110001000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 149 0x95 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x40, /* 011100000100 */ + 0x38, 0x80, /* 001110001000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 150 0x96 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x02, 0x00, /* 000000100000 */ + 0x07, 0x00, /* 000001110000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x79, 0xe0, /* 011110011110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0x60, /* 000111100110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 151 0x97 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x79, 0xe0, /* 011110011110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0x60, /* 000111100110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 152 0x98 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xf0, 0xf0, /* 111100001111 */ + 0x60, 0x20, /* 011000000010 */ + 0x30, 0x40, /* 001100000100 */ + 0x30, 0x40, /* 001100000100 */ + 0x18, 0x80, /* 000110001000 */ + 0x18, 0x80, /* 000110001000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x0d, 0x00, /* 000011010000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x04, 0x00, /* 000001000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x08, 0x00, /* 000010000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 153 0x99 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xc0, /* 001000001100 */ + 0x20, 0x60, /* 001000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x20, 0x40, /* 001000000100 */ + 0x30, 0x40, /* 001100000100 */ + 0x18, 0x80, /* 000110001000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 154 0x9a '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0xe0, 0x30, /* 111000000011 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x60, 0x20, /* 011000000010 */ + 0x70, 0x40, /* 011100000100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 155 0x9b '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x36, 0xc0, /* 001101101100 */ + 0x26, 0xc0, /* 001001101100 */ + 0x66, 0x00, /* 011001100000 */ + 0x66, 0x00, /* 011001100000 */ + 0x66, 0x00, /* 011001100000 */ + 0x66, 0x00, /* 011001100000 */ + 0x76, 0x40, /* 011101100100 */ + 0x36, 0xc0, /* 001101101100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 156 0x9c '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x1c, 0xc0, /* 000111001100 */ + 0x18, 0xc0, /* 000110001100 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x7e, 0x00, /* 011111100000 */ + 0x7e, 0x00, /* 011111100000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x3e, 0x20, /* 001111100010 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x61, 0xc0, /* 011000011100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 157 0x9d '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 158 0x9e '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0x80, /* 011111111000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x37, 0x80, /* 001101111000 */ + 0x30, 0x00, /* 001100000000 */ + 0x33, 0x00, /* 001100110000 */ + 0x37, 0x80, /* 001101111000 */ + 0x33, 0x00, /* 001100110000 */ + 0x33, 0x00, /* 001100110000 */ + 0x33, 0x30, /* 001100110011 */ + 0x31, 0xe0, /* 001100011110 */ + 0x78, 0xc0, /* 011110001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 159 0x9f '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0xc0, /* 000000001100 */ + 0x01, 0xe0, /* 000000011110 */ + 0x03, 0x30, /* 000000110011 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x7f, 0xc0, /* 011111111100 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xcc, 0x00, /* 110011000000 */ + 0x78, 0x00, /* 011110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 160 0xa0 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x18, 0xc0, /* 000110001100 */ + 0x10, 0xc0, /* 000100001100 */ + 0x03, 0xc0, /* 000000111100 */ + 0x1c, 0xc0, /* 000111001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0xe0, /* 000111101110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 161 0xa1 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 162 0xa2 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x40, /* 011100000100 */ + 0x38, 0x80, /* 001110001000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 163 0xa3 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0x80, /* 000000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x79, 0xe0, /* 011110011110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1e, 0x60, /* 000111100110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 164 0xa4 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x1c, 0x40, /* 000111000100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x23, 0x80, /* 001000111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x27, 0x80, /* 001001111000 */ + 0x79, 0xc0, /* 011110011100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x79, 0xe0, /* 011110011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 165 0xa5 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x1c, 0x40, /* 000111000100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x23, 0x80, /* 001000111000 */ + 0xc0, 0x70, /* 110000000111 */ + 0x60, 0x20, /* 011000000010 */ + 0x70, 0x20, /* 011100000010 */ + 0x78, 0x20, /* 011110000010 */ + 0x5c, 0x20, /* 010111000010 */ + 0x4e, 0x20, /* 010011100010 */ + 0x47, 0x20, /* 010001110010 */ + 0x43, 0xa0, /* 010000111010 */ + 0x41, 0xe0, /* 010000011110 */ + 0x40, 0xe0, /* 010000001110 */ + 0x40, 0x60, /* 010000000110 */ + 0xe0, 0x30, /* 111000000011 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 166 0xa6 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x31, 0x80, /* 001100011000 */ + 0x01, 0x80, /* 000000011000 */ + 0x07, 0x80, /* 000001111000 */ + 0x19, 0x80, /* 000110011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x31, 0x80, /* 001100011000 */ + 0x33, 0x80, /* 001100111000 */ + 0x1d, 0xc0, /* 000111011100 */ + 0x00, 0x00, /* 000000000000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 167 0xa7 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0x00, /* 000001110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x10, 0xc0, /* 000100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0x80, /* 001100001000 */ + 0x19, 0x80, /* 000110011000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 168 0xa8 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x40, /* 001100000100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 169 0xa9 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 170 0xaa '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 171 0xab '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x10, 0x40, /* 000100000100 */ + 0x10, 0x80, /* 000100001000 */ + 0x11, 0x00, /* 000100010000 */ + 0x3a, 0x00, /* 001110100000 */ + 0x05, 0xc0, /* 000001011100 */ + 0x0a, 0x20, /* 000010100010 */ + 0x10, 0x20, /* 000100000010 */ + 0x20, 0xc0, /* 001000001100 */ + 0x41, 0x00, /* 010000010000 */ + 0x02, 0x00, /* 000000100000 */ + 0x03, 0xe0, /* 000000111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 172 0xac '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x10, 0x00, /* 000100000000 */ + 0x10, 0x40, /* 000100000100 */ + 0x10, 0x80, /* 000100001000 */ + 0x11, 0x00, /* 000100010000 */ + 0x3a, 0x40, /* 001110100100 */ + 0x04, 0xc0, /* 000001001100 */ + 0x09, 0x40, /* 000010010100 */ + 0x12, 0x40, /* 000100100100 */ + 0x24, 0x40, /* 001001000100 */ + 0x47, 0xe0, /* 010001111110 */ + 0x00, 0x40, /* 000000000100 */ + 0x00, 0x40, /* 000000000100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 173 0xad '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 174 0xae '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x60, /* 000001100110 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x19, 0x80, /* 000110011000 */ + 0x33, 0x00, /* 001100110000 */ + 0x66, 0x00, /* 011001100000 */ + 0x33, 0x00, /* 001100110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x06, 0x60, /* 000001100110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 175 0xaf '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x66, 0x00, /* 011001100000 */ + 0x33, 0x00, /* 001100110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x06, 0x60, /* 000001100110 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x19, 0x80, /* 000110011000 */ + 0x33, 0x00, /* 001100110000 */ + 0x66, 0x00, /* 011001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 176 0xb0 '.' */ + 0x0c, 0x30, /* 000011000011 */ + 0x08, 0x20, /* 000010000010 */ + 0x61, 0x80, /* 011000011000 */ + 0x20, 0x80, /* 001000001000 */ + 0x0c, 0x30, /* 000011000011 */ + 0x08, 0x20, /* 000010000010 */ + 0x61, 0x80, /* 011000011000 */ + 0x20, 0x80, /* 001000001000 */ + 0x0c, 0x30, /* 000011000011 */ + 0x08, 0x20, /* 000010000010 */ + 0x61, 0x80, /* 011000011000 */ + 0x20, 0x80, /* 001000001000 */ + 0x0c, 0x30, /* 000011000011 */ + 0x08, 0x20, /* 000010000010 */ + 0x61, 0x80, /* 011000011000 */ + 0x20, 0x80, /* 001000001000 */ + 0x0c, 0x30, /* 000011000011 */ + 0x08, 0x20, /* 000010000010 */ + 0x61, 0x80, /* 011000011000 */ + 0x20, 0x80, /* 001000001000 */ + 0x0c, 0x30, /* 000011000011 */ + 0x08, 0x20, /* 000010000010 */ + + /* 177 0xb1 '.' */ + 0x77, 0x70, /* 011101110111 */ + 0x22, 0x20, /* 001000100010 */ + 0x88, 0x80, /* 100010001000 */ + 0xdd, 0xd0, /* 110111011101 */ + 0x88, 0x80, /* 100010001000 */ + 0x22, 0x20, /* 001000100010 */ + 0x77, 0x70, /* 011101110111 */ + 0x22, 0x20, /* 001000100010 */ + 0x88, 0x80, /* 100010001000 */ + 0xdd, 0xd0, /* 110111011101 */ + 0x88, 0x80, /* 100010001000 */ + 0x22, 0x20, /* 001000100010 */ + 0x77, 0x70, /* 011101110111 */ + 0x22, 0x20, /* 001000100010 */ + 0x88, 0x80, /* 100010001000 */ + 0xdd, 0xd0, /* 110111011101 */ + 0x88, 0x80, /* 100010001000 */ + 0x22, 0x20, /* 001000100010 */ + 0x77, 0x70, /* 011101110111 */ + 0x22, 0x20, /* 001000100010 */ + 0x88, 0x80, /* 100010001000 */ + 0xdd, 0xd0, /* 110111011101 */ + + /* 178 0xb2 '.' */ + 0xf3, 0xc0, /* 111100111100 */ + 0xf7, 0xd0, /* 111101111101 */ + 0x9e, 0x70, /* 100111100111 */ + 0xdf, 0x70, /* 110111110111 */ + 0xf3, 0xc0, /* 111100111100 */ + 0xf7, 0xd0, /* 111101111101 */ + 0x9e, 0x70, /* 100111100111 */ + 0xdf, 0x70, /* 110111110111 */ + 0xf3, 0xc0, /* 111100111100 */ + 0xf7, 0xd0, /* 111101111101 */ + 0x9e, 0x70, /* 100111100111 */ + 0xdf, 0x70, /* 110111110111 */ + 0xf3, 0xc0, /* 111100111100 */ + 0xf7, 0xd0, /* 111101111101 */ + 0x9e, 0x70, /* 100111100111 */ + 0xdf, 0x70, /* 110111110111 */ + 0xf3, 0xc0, /* 111100111100 */ + 0xf7, 0xd0, /* 111101111101 */ + 0x9e, 0x70, /* 100111100111 */ + 0xdf, 0x70, /* 110111110111 */ + 0xf3, 0xc0, /* 111100111100 */ + 0xf7, 0xd0, /* 111101111101 */ + + /* 179 0xb3 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 180 0xb4 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 181 0xb5 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 182 0xb6 '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 183 0xb7 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0x80, /* 111111111000 */ + 0xff, 0x80, /* 111111111000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 184 0xb8 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 185 0xb9 '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0x01, 0x80, /* 000000011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 186 0xba '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 187 0xbb '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0x80, /* 111111111000 */ + 0xff, 0x80, /* 111111111000 */ + 0x01, 0x80, /* 000000011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 188 0xbc '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0xfd, 0x80, /* 111111011000 */ + 0x01, 0x80, /* 000000011000 */ + 0xff, 0x80, /* 111111111000 */ + 0xff, 0x80, /* 111111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 189 0xbd '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0xff, 0x80, /* 111111111000 */ + 0xff, 0x80, /* 111111111000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 190 0xbe '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 191 0xbf '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 192 0xc0 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 193 0xc1 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 194 0xc2 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 195 0xc3 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 196 0xc4 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 197 0xc5 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 198 0xc6 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 199 0xc7 '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 200 0xc8 '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0f, 0xf0, /* 000011111111 */ + 0x0f, 0xf0, /* 000011111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 201 0xc9 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0xf0, /* 000011111111 */ + 0x0f, 0xf0, /* 000011111111 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 202 0xca '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0xfd, 0xf0, /* 111111011111 */ + 0xfd, 0xf0, /* 111111011111 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 203 0xcb '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0xfd, 0xf0, /* 111111011111 */ + 0xfd, 0xf0, /* 111111011111 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 204 0xcc '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0d, 0xf0, /* 000011011111 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 205 0xcd '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 206 0xce '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0xfd, 0xf0, /* 111111011111 */ + 0xfd, 0xf0, /* 111111011111 */ + 0x00, 0x00, /* 000000000000 */ + 0xfd, 0xf0, /* 111111011111 */ + 0xfd, 0xf0, /* 111111011111 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 207 0xcf '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 208 0xd0 '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 209 0xd1 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 210 0xd2 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 211 0xd3 '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0f, 0xf0, /* 000011111111 */ + 0x0f, 0xf0, /* 000011111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 212 0xd4 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 213 0xd5 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 214 0xd6 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0xf0, /* 000011111111 */ + 0x0f, 0xf0, /* 000011111111 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 215 0xd7 '.' */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + 0x0d, 0x80, /* 000011011000 */ + + /* 216 0xd8 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x06, 0x00, /* 000001100000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 217 0xd9 '.' */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0xfe, 0x00, /* 111111100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 218 0xda '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0xf0, /* 000001111111 */ + 0x07, 0xf0, /* 000001111111 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + + /* 219 0xdb '.' */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + + /* 220 0xdc '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + + /* 221 0xdd '.' */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + 0xfc, 0x00, /* 111111000000 */ + + /* 222 0xde '.' */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + 0x03, 0xf0, /* 000000111111 */ + + /* 223 0xdf '.' */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0xff, 0xf0, /* 111111111111 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 224 0xe0 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x60, /* 000011110110 */ + 0x13, 0xe0, /* 000100111110 */ + 0x21, 0xc0, /* 001000011100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x70, 0x80, /* 011100001000 */ + 0x39, 0xc0, /* 001110011100 */ + 0x1f, 0x60, /* 000111110110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 225 0xe1 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x31, 0x80, /* 001100011000 */ + 0x37, 0x80, /* 001101111000 */ + 0x31, 0x80, /* 001100011000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x31, 0x80, /* 001100011000 */ + 0x77, 0x00, /* 011101110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 226 0xe2 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x3f, 0xe0, /* 001111111110 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 227 0xe3 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 228 0xe4 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0x60, /* 011000000110 */ + 0x30, 0x60, /* 001100000110 */ + 0x30, 0x00, /* 001100000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x60, /* 001100000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 229 0xe5 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0xe0, /* 000001111110 */ + 0x0f, 0xe0, /* 000011111110 */ + 0x13, 0x80, /* 000100111000 */ + 0x21, 0xc0, /* 001000011100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x60, 0xc0, /* 011000001100 */ + 0x70, 0x80, /* 011100001000 */ + 0x39, 0x00, /* 001110010000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 230 0xe6 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x39, 0xc0, /* 001110011100 */ + 0x36, 0xe0, /* 001101101110 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 231 0xe7 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x19, 0x80, /* 000110011000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x66, 0x60, /* 011001100110 */ + 0x66, 0x60, /* 011001100110 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 232 0xe8 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x19, 0x80, /* 000110011000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 233 0xe9 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x1f, 0x80, /* 000111111000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 234 0xea '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x31, 0x80, /* 001100011000 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0xd9, 0xb0, /* 110110011011 */ + 0x79, 0xe0, /* 011110011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 235 0xeb '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0x80, /* 000001111000 */ + 0x0c, 0xc0, /* 000011001100 */ + 0x18, 0x60, /* 000110000110 */ + 0x18, 0x00, /* 000110000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x0f, 0x80, /* 000011111000 */ + 0x11, 0xc0, /* 000100011100 */ + 0x20, 0xe0, /* 001000001110 */ + 0x60, 0x60, /* 011000000110 */ + 0x60, 0x60, /* 011000000110 */ + 0x70, 0x40, /* 011100000100 */ + 0x38, 0x80, /* 001110001000 */ + 0x1f, 0x00, /* 000111110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 236 0xec '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x39, 0xc0, /* 001110011100 */ + 0x6f, 0x60, /* 011011110110 */ + 0x66, 0x60, /* 011001100110 */ + 0xc6, 0x30, /* 110001100011 */ + 0xc6, 0x30, /* 110001100011 */ + 0x66, 0x60, /* 011001100110 */ + 0x6f, 0x60, /* 011011110110 */ + 0x39, 0xc0, /* 001110011100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 237 0xed '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0xc0, /* 000000001100 */ + 0x00, 0xc0, /* 000000001100 */ + 0x01, 0x80, /* 000000011000 */ + 0x01, 0x80, /* 000000011000 */ + 0x3b, 0xc0, /* 001110111100 */ + 0x6f, 0x60, /* 011011110110 */ + 0x66, 0x60, /* 011001100110 */ + 0xc6, 0x30, /* 110001100011 */ + 0xc6, 0x30, /* 110001100011 */ + 0x66, 0x60, /* 011001100110 */ + 0x6f, 0x60, /* 011011110110 */ + 0x3d, 0xc0, /* 001111011100 */ + 0x18, 0x00, /* 000110000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x30, 0x00, /* 001100000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 238 0xee '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x01, 0xc0, /* 000000011100 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x1f, 0xc0, /* 000111111100 */ + 0x18, 0x00, /* 000110000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x03, 0x00, /* 000000110000 */ + 0x01, 0xc0, /* 000000011100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 239 0xef '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x39, 0xc0, /* 001110011100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x30, 0xc0, /* 001100001100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 240 0xf0 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 241 0xf1 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 242 0xf2 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x38, 0x00, /* 001110000000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x03, 0x80, /* 000000111000 */ + 0x00, 0xe0, /* 000000001110 */ + 0x00, 0xe0, /* 000000001110 */ + 0x03, 0x80, /* 000000111000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x38, 0x00, /* 001110000000 */ + 0x60, 0x00, /* 011000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 243 0xf3 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x60, /* 000000000110 */ + 0x01, 0xc0, /* 000000011100 */ + 0x07, 0x00, /* 000001110000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x70, 0x00, /* 011100000000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x07, 0x00, /* 000001110000 */ + 0x01, 0xc0, /* 000000011100 */ + 0x00, 0x60, /* 000000000110 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 244 0xf4 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x03, 0x80, /* 000000111000 */ + 0x07, 0xc0, /* 000001111100 */ + 0x0c, 0x60, /* 000011000110 */ + 0x0c, 0x60, /* 000011000110 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x0c, 0x00, /* 000011000000 */ + + /* 245 0xf5 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x3e, 0x00, /* 001111100000 */ + 0x63, 0x00, /* 011000110000 */ + 0x63, 0x00, /* 011000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + 0x03, 0x00, /* 000000110000 */ + + /* 246 0xf6 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x7f, 0xe0, /* 011111111110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 247 0xf7 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x38, 0x00, /* 001110000000 */ + 0x6c, 0x00, /* 011011000000 */ + 0x06, 0x30, /* 000001100011 */ + 0x03, 0x60, /* 000000110110 */ + 0x39, 0xc0, /* 001110011100 */ + 0x6c, 0x00, /* 011011000000 */ + 0x06, 0x30, /* 000001100011 */ + 0x03, 0x60, /* 000000110110 */ + 0x01, 0xc0, /* 000000011100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 248 0xf8 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x19, 0x80, /* 000110011000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 249 0xf9 '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x3e, 0x00, /* 001111100000 */ + 0x3e, 0x00, /* 001111100000 */ + 0x3e, 0x00, /* 001111100000 */ + 0x1c, 0x00, /* 000111000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 250 0xfa '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x3c, 0x00, /* 001111000000 */ + 0x3c, 0x00, /* 001111000000 */ + 0x18, 0x00, /* 000110000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 251 0xfb '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x07, 0xe0, /* 000001111110 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x06, 0x00, /* 000001100000 */ + 0xc6, 0x00, /* 110001100000 */ + 0x66, 0x00, /* 011001100000 */ + 0x36, 0x00, /* 001101100000 */ + 0x1e, 0x00, /* 000111100000 */ + 0x0e, 0x00, /* 000011100000 */ + 0x06, 0x00, /* 000001100000 */ + 0x02, 0x00, /* 000000100000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 252 0xfc '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x13, 0x80, /* 000100111000 */ + 0x3d, 0xc0, /* 001111011100 */ + 0x18, 0xc0, /* 000110001100 */ + 0x18, 0xc0, /* 000110001100 */ + 0x18, 0xc0, /* 000110001100 */ + 0x18, 0xc0, /* 000110001100 */ + 0x3d, 0xe0, /* 001111011110 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 253 0xfd '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x0f, 0x00, /* 000011110000 */ + 0x1f, 0x80, /* 000111111000 */ + 0x31, 0x80, /* 001100011000 */ + 0x21, 0x80, /* 001000011000 */ + 0x03, 0x00, /* 000000110000 */ + 0x06, 0x00, /* 000001100000 */ + 0x0c, 0x00, /* 000011000000 */ + 0x18, 0x40, /* 000110000100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 254 0xfe '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x3f, 0xc0, /* 001111111100 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + + /* 255 0xff '.' */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ + 0x00, 0x00, /* 000000000000 */ +}; + +#endif /* _VIDEO_FONT_LARGE_ */ diff --git a/sept/sept-secondary/src/display/video_font_small.h b/sept/sept-secondary/src/display/video_font_small.h new file mode 100644 index 000000000..2c658fe8e --- /dev/null +++ b/sept/sept-secondary/src/display/video_font_small.h @@ -0,0 +1,4630 @@ +/* + * (C) Copyright 2000 + * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This file contains an 8x16 bitmap font for code page 437. + */ + +#ifndef _VIDEO_FONT_DATA_ +#define _VIDEO_FONT_DATA_ + +#define VIDEO_FONT_CHARS 256 +#define VIDEO_FONT_WIDTH 8 +#define VIDEO_FONT_HEIGHT 16 +#define VIDEO_FONT_SIZE (VIDEO_FONT_CHARS * VIDEO_FONT_HEIGHT) + +static unsigned char video_fontdata[VIDEO_FONT_SIZE] = { + + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x81, /* 10000001 */ + 0xa5, /* 10100101 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xdb, /* 11011011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x1a, /* 00011010 */ + 0x32, /* 00110010 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe7, /* 11100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^P' */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0xf0, /* 11110000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0e, /* 00001110 */ + 0x1e, /* 00011110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00101000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x28, /* 00101000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x86, /* 10000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x78, /* 01111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xdc, /* 11011100 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xde, /* 11011110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xde, /* 11011110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0xee, /* 11101110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0x70, /* 01110000 */ + 0x38, /* 00111000 */ + 0x1c, /* 00011100 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x36, /* 00110110 */ + 0x32, /* 00110010 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '€' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '‚' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 'ƒ' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '„' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '…' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '†' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '‡' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 'ˆ' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '‰' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a 'Š' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '‹' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c 'Œ' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e 'Ž' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '‘' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x6e, /* 01101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '’' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '“' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '”' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '•' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '–' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '—' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '˜' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 '™' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a 'š' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '›' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c 'œ' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xe6, /* 11100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e 'ž' */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xf8, /* 11111000 */ + 0xc4, /* 11000100 */ + 0xcc, /* 11001100 */ + 0xde, /* 11011110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f 'Ÿ' */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 ' ' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '¡' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '¢' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '£' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '¤' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '¥' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '¦' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '§' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '¨' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '©' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa 'ª' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '«' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xdc, /* 11011100 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '¬' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xce, /* 11001110 */ + 0x9a, /* 10011010 */ + 0x3f, /* 00111111 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '­' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '®' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '¯' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '°' */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + + /* 177 0xb1 '±' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '²' */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + + /* 179 0xb3 '³' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '´' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 'µ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '¶' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '·' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '¸' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '¹' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba 'º' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '»' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '¼' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '½' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '¾' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '¿' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 'À' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 'Á' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 'Â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 'Ã' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 'Ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 'Å' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 'Æ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 'Ç' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 'È' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 'É' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca 'Ê' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb 'Ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc 'Ì' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd 'Í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce 'Î' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf 'Ï' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 'Ð' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 'Ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 'Ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 'Ó' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 'Ô' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 'Õ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 'Ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '×' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 'Ø' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 'Ù' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda 'Ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb 'Û' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc 'Ü' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd 'Ý' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde 'Þ' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf 'ß' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 'à' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 'á' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 'â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 'ã' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 'ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 'å' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 'æ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 'ç' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 'è' */ + 0x00, /* 00000000 */ + 0x40, /* 01000000*/ + 0xe0, /* 01110000 */ + 0x1c, /* 00011100 */ + 0x06, /* 00000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 'é' */ + 0x00, /* 00000000 */ + 0x02, /* 00000010*/ + 0x0e, /* 00001110 */ + 0x78, /* 00111000 */ + 0xc0, /* 01100000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea 'ê' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb 'ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec 'ì' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed 'í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x03, /* 00000011 */ + 0x06, /* 00000110 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xf3, /* 11110011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee 'î' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef 'ï' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 'ð' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 'ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 'ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 'ó' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 'ô' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 'õ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 'ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '÷' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 'ø' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 'ù' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa 'ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb 'û' */ + 0x00, /* 00000000 */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc 'ü' */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd 'ý' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe 'þ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff 'ÿ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; + +#endif diff --git a/sept/sept-secondary/src/emc.h b/sept/sept-secondary/src/emc.h new file mode 100644 index 000000000..ebf6abed2 --- /dev/null +++ b/sept/sept-secondary/src/emc.h @@ -0,0 +1,1089 @@ +/* + * arch/arm/mach-tegra/tegra21_emc.h + * + * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef FUSEE_EMC_H_ +#define FUSEE_EMC_H_ + +#define EMC_BASE 0x7001B000 +#define EMC0_BASE 0x7001E000 +#define EMC1_BASE 0x7001F000 +#define MAKE_EMC_REG(n) MAKE_REG32(EMC_BASE + n) +#define MAKE_EMC0_REG(n) MAKE_REG32(EMC0_BASE + n) +#define MAKE_EMC1_REG(n) MAKE_REG32(EMC1_BASE + n) + +#define EMC_INTSTATUS 0x0 +#define EMC_INTSTATUS_MRR_DIVLD (0x1 << 5) +#define EMC_INTSTATUS_CLKCHANGE_COMPLETE (0x1 << 4) + +#define EMC_INTMASK 0x4 +#define EMC_DBG 0x8 +#define EMC_DBG_WRITE_MUX_ACTIVE (1 << 1) +#define EMC_DBG_CFG_SWAP_SHIFT 26 +#define EMC_DBG_CFG_SWAP_MASK \ + (0x3 << EMC_DBG_CFG_SWAP_SHIFT) +#define EMC_DBG_WRITE_ACTIVE_ONLY (1 << 30) + +#define EMC_CONFIG_SAMPLE_DELAY 0x5f0 +#define EMC_CFG_UPDATE 0x5f4 +#define EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_SHIFT 9 +#define EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_MASK \ + (0x3 << EMC_CFG_UPDATE_UPDATE_DLL_IN_UPDATE_SHIFT) +#define EMC_CFG 0xc +#define EMC_CFG_DRAM_CLKSTOP_PD (1 << 31) +#define EMC_CFG_DRAM_CLKSTOP_SR (1 << 30) +#define EMC_CFG_DRAM_ACPD (1 << 29) +#define EMC_CFG_DYN_SELF_REF (1 << 28) +#define EMC_CFG_REQACT_ASYNC (1 << 26) +#define EMC_CFG_AUTO_PRE_WR (1 << 25) +#define EMC_CFG_AUTO_PRE_RD (1 << 24) +#define EMC_CFG_MAM_PRE_WR (1 << 23) +#define EMC_CFG_MAN_PRE_RD (1 << 22) +#define EMC_CFG_PERIODIC_QRST (1 << 21) +#define EMC_CFG_PERIODIC_QRST_SHIFT (21) +#define EMC_CFG_EN_DYNAMIC_PUTERM (1 << 20) +#define EMC_CFG_DLY_WR_DQ_HALF_CLOCK (1 << 19) +#define EMC_CFG_DSR_VTTGEN_DRV_EN (1 << 18) +#define EMC_CFG_EMC2MC_CLK_RATIO (3 << 16) +#define EMC_CFG_WAIT_FOR_ISP2B_READY_B4_CC (1 << 9) +#define EMC_CFG_WAIT_FOR_VI2_READY_B4_CC (1 << 8) +#define EMC_CFG_WAIT_FOR_ISP2_READY_B4_CC (1 << 7) +#define EMC_CFG_INVERT_DQM (1 << 6) +#define EMC_CFG_WAIT_FOR_DISPLAYB_READY_B4_CC (1 << 5) +#define EMC_CFG_WAIT_FOR_DISPLAY_READY_B4_CC (1 << 4) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2 (1 << 3) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1 (1 << 2) +#define EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE (1 << 1) + +#define EMC_ADR_CFG 0x10 +#define EMC_REFCTRL 0x20 +#define EMC_REFCTRL_DEV_SEL_SHIFT 0 +#define EMC_REFCTRL_DEV_SEL_MASK \ + (0x3 << EMC_REFCTRL_DEV_SEL_SHIFT) +#define EMC_REFCTRL_ENABLE (0x1 << 31) +#define EMC_REFCTRL_ENABLE_ALL(num) \ + (((((num) > 1) ? 0 : 2) << EMC_REFCTRL_DEV_SEL_SHIFT) \ + | EMC_REFCTRL_ENABLE) +#define EMC_REFCTRL_DISABLE_ALL(num) \ + ((((num) > 1) ? 0 : 2) << EMC_REFCTRL_DEV_SEL_SHIFT) + +#define EMC_PIN 0x24 +#define EMC_PIN_PIN_CKE_PER_DEV (1 << 2) +#define EMC_PIN_PIN_CKEB (1 << 1) +#define EMC_PIN_PIN_CKE (1 << 0) + +#define EMC_CLK_FORCE_CC_TRIGGER (1 << 27) + +#define EMC_TIMING_CONTROL 0x28 +#define EMC_RC 0x2c +#define EMC_RFC 0x30 +#define EMC_RFCPB 0x590 +#define EMC_RAS 0x34 +#define EMC_RP 0x38 +#define EMC_R2W 0x3c +#define EMC_W2R 0x40 +#define EMC_R2P 0x44 +#define EMC_W2P 0x48 +#define EMC_CCDMW 0x5c0 +#define EMC_RD_RCD 0x4c +#define EMC_WR_RCD 0x50 +#define EMC_RRD 0x54 +#define EMC_REXT 0x58 +#define EMC_WDV 0x5c +#define EMC_QUSE 0x60 +#define EMC_QRST 0x64 +#define EMC_ISSUE_QRST 0x428 +#define EMC_QSAFE 0x68 +#define EMC_RDV 0x6c +#define EMC_REFRESH 0x70 +#define EMC_BURST_REFRESH_NUM 0x74 +#define EMC_PDEX2WR 0x78 +#define EMC_PDEX2RD 0x7c +#define EMC_PDEX2CKE 0x118 +#define EMC_PCHG2PDEN 0x80 +#define EMC_ACT2PDEN 0x84 +#define EMC_AR2PDEN 0x88 +#define EMC_RW2PDEN 0x8c +#define EMC_CKE2PDEN 0x11c +#define EMC_TXSR 0x90 +#define EMC_TCKE 0x94 +#define EMC_TFAW 0x98 +#define EMC_TRPAB 0x9c +#define EMC_TCLKSTABLE 0xa0 +#define EMC_TCLKSTOP 0xa4 +#define EMC_TREFBW 0xa8 +#define EMC_TPPD 0xac +#define EMC_PDEX2MRR 0xb4 +#define EMC_ODT_WRITE 0xb0 +#define EMC_WEXT 0xb8 +#define EMC_RFC_SLR 0xc0 +#define EMC_MRS_WAIT_CNT2 0xc4 +#define EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_SHIFT 16 +#define EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_MASK \ + (0x7ff << EMC_MRS_WAIT_CNT2_MRS_EXT2_WAIT_CNT_SHIFT) +#define EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_SHIFT 0 +#define EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_MASK \ + (0x3ff << EMC_MRS_WAIT_CNT2_MRS_EXT1_WAIT_CNT_SHIFT) + +#define EMC_MRS_WAIT_CNT 0xc8 +#define EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT 0 +#define EMC_MRS_WAIT_CNT_SHORT_WAIT_MASK \ + (0x3FF << EMC_MRS_WAIT_CNT_SHORT_WAIT_SHIFT) +#define EMC_MRS_WAIT_CNT_LONG_WAIT_SHIFT 16 +#define EMC_MRS_WAIT_CNT_LONG_WAIT_MASK \ + (0x3FF << EMC_MRS_WAIT_CNT_LONG_WAIT_SHIFT) + +#define EMC_MRS 0xcc +#define EMC_MODE_SET_DLL_RESET (1 << 8) +#define EMC_MRS_USE_MRS_LONG_CNT (1 << 26) + +#define EMC_EMRS 0xd0 +#define EMC_EMRS_USE_EMRS_LONG_CNT (1 << 26) + +#define EMC_REF 0xd4 +#define EMC_REF_FORCE_CMD 1 + +#define EMC_PRE 0xd8 +#define EMC_NOP 0xdc +#define EMC_SELF_REF 0xe0 +#define EMC_SELF_REF_CMD_ENABLED (1 << 0) +#define EMC_SELF_REF_ACTIVE_SELF_REF (1 << 8) +#define EMC_SELF_REF_DEV_SEL_SHIFT 30 +#define EMC_SELF_REF_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) + +#define EMC_DPD 0xe4 +#define EMC_MRW 0xe8 +#define EMC_MRW_MRW_OP_SHIFT 0 +#define EMC_MRW_MRW_OP_MASK \ + (0xff << EMC_MRW_MRW_OP_SHIFT) +#define EMC_MRW_MRW_MA_SHIFT 16 +#define EMC_MRW_MRW_MA_MASK \ + (0xff << EMC_MRW_MRW_MA_SHIFT) +#define EMC_MRW_USE_MRW_LONG_CNT 26 +#define EMC_MRW_USE_MRW_EXT_CNT 27 +#define EMC_MRW_MRW_DEV_SELECTN_SHIFT 30 +#define EMC_MRW_MRW_DEV_SELECTN_MASK \ + (0x3 << EMC_MRW_MRW_DEV_SELECTN_SHIFT) + +#define EMC_MRR 0xec +#define EMC_MRR_DEV_SEL_SHIFT 30 +#define EMC_MRR_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) +#define EMC_MRR_MA_SHIFT 16 +#define EMC_MRR_MA_MASK \ + (0xff << EMC_MRR_MA_SHIFT) +#define EMC_MRR_DATA_SHIFT 0 +#define EMC_MRR_DATA_MASK \ + (0xffff << EMC_MRR_DATA_SHIFT) +#define LPDDR2_MR4_TEMP_SHIFT 0 +#define LPDDR2_MR4_TEMP_MASK \ + (0x7 << LPDDR2_MR4_TEMP_SHIFT) + +#define EMC_CMDQ 0xf0 +#define EMC_MC2EMCQ 0xf4 +#define EMC_FBIO_SPARE 0x100 +#define EMC_FBIO_CFG5 0x104 +#define EMC_FBIO_CFG5_DRAM_TYPE_SHIFT 0 +#define EMC_FBIO_CFG5_DRAM_TYPE_MASK \ + (0x3 << EMC_FBIO_CFG5_DRAM_TYPE_SHIFT) +#define EMC_FBIO_CFG5_CMD_TX_DIS (1 << 8) +#define EMC_FBIO_CFG5_CMD_BUS_RETURN_TO_ZERO (1 << 27) + +#define EMC_CFG5_QUSE_MODE_SHIFT 13 +#define EMC_CFG5_QUSE_MODE_MASK \ + (0x7 << EMC_CFG5_QUSE_MODE_SHIFT) + +#define EMC_CFG_RSV 0x120 +#define EMC_ACPD_CONTROL 0x124 +#define EMC_MPC 0x128 +#define EMC_EMRS2 0x12c +#define EMC_EMRS2_USE_EMRS2_LONG_CNT (1 << 26) + +#define EMC_EMRS3 0x130 +#define EMC_MRW2 0x134 +#define EMC_MRW3 0x138 +#define EMC_MRW4 0x13c +#define EMC_MRW5 0x4a0 +#define EMC_MRW6 0x4a4 +#define EMC_MRW7 0x4a8 +#define EMC_MRW8 0x4ac +#define EMC_MRW9 0x4b0 +#define EMC_MRW10 0x4b4 +#define EMC_MRW11 0x4b8 +#define EMC_MRW12 0x4bc +#define EMC_MRW13 0x4c0 +#define EMC_MRW14 0x4c4 +#define EMC_MRW15 0x4d0 +#define EMC_CFG_SYNC 0x4d4 +#define EMC_CLKEN_OVERRIDE 0x140 +#define EMC_R2R 0x144 +#define EMC_W2W 0x148 +#define EMC_EINPUT 0x14c +#define EMC_EINPUT_DURATION 0x150 +#define EMC_PUTERM_EXTRA 0x154 +#define EMC_TCKESR 0x158 +#define EMC_TPD 0x15c +#define EMC_STAT_CONTROL 0x160 +#define EMC_STAT_STATUS 0x164 +#define EMC_STAT_DRAM_CLOCK_LIMIT_LO 0x19c +#define EMC_STAT_DRAM_CLOCK_LIMIT_HI 0x1a0 +#define EMC_STAT_DRAM_CLOCKS_LO 0x1a4 +#define EMC_STAT_DRAM_CLOCKS_HI 0x1a8 +#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_LO 0x1ac +#define EMC_STAT_DRAM_DEV0_ACTIVATE_CNT_HI 0x1b0 +#define EMC_STAT_DRAM_DEV0_READ_CNT_LO 0x1b4 +#define EMC_STAT_DRAM_DEV0_READ_CNT_HI 0x1b8 +#define EMC_STAT_DRAM_DEV0_READ8_CNT_LO 0x1bc +#define EMC_STAT_DRAM_DEV0_READ8_CNT_HI 0x1c0 +#define EMC_STAT_DRAM_DEV0_WRITE_CNT_LO 0x1c4 +#define EMC_STAT_DRAM_DEV0_WRITE_CNT_HI 0x1c8 +#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_LO 0x1cc +#define EMC_STAT_DRAM_DEV0_WRITE8_CNT_HI 0x1d0 +#define EMC_STAT_DRAM_DEV0_REF_CNT_LO 0x1d4 +#define EMC_STAT_DRAM_DEV0_REF_CNT_HI 0x1d8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1dc +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e0 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x1e4 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x1e8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1ec +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f0 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x1f4 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x1f8 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x1fc +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x200 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x204 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x208 +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x20c +#define EMC_STAT_DRAM_DEV0_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x210 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x214 +#define EMC_STAT_DRAM_DEV0_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x218 +#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_LO 0x21c +#define EMC_STAT_DRAM_DEV0_SR_CKE_EQ0_CLKS_HI 0x220 +#define EMC_STAT_DRAM_DEV0_DSR 0x224 +#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_LO 0x228 +#define EMC_STAT_DRAM_DEV1_ACTIVATE_CNT_HI 0x22c +#define EMC_STAT_DRAM_DEV1_READ_CNT_LO 0x230 +#define EMC_STAT_DRAM_DEV1_READ_CNT_HI 0x234 +#define EMC_STAT_DRAM_DEV1_READ8_CNT_LO 0x238 +#define EMC_STAT_DRAM_DEV1_READ8_CNT_HI 0x23c +#define EMC_STAT_DRAM_DEV1_WRITE_CNT_LO 0x240 +#define EMC_STAT_DRAM_DEV1_WRITE_CNT_HI 0x244 +#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_LO 0x248 +#define EMC_STAT_DRAM_DEV1_WRITE8_CNT_HI 0x24c +#define EMC_STAT_DRAM_DEV1_REF_CNT_LO 0x250 +#define EMC_STAT_DRAM_DEV1_REF_CNT_HI 0x254 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x258 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x25c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0x260 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0x264 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x268 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x26c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0x270 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0x274 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x278 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x27c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0x280 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0x284 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x288 +#define EMC_STAT_DRAM_DEV1_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x28c +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0x290 +#define EMC_STAT_DRAM_DEV1_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0x294 +#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_LO 0x298 +#define EMC_STAT_DRAM_DEV1_SR_CKE_EQ0_CLKS_HI 0x29c +#define EMC_STAT_DRAM_DEV1_DSR 0x2a0 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc8c +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc90 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_LO 0xc94 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_NO_BANKS_ACTIVE_CLKS_HI 0xc98 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xc9c +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_LO 0xca4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_NO_BANKS_ACTIVE_CLKS_HI 0xca8 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcac +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_LO 0xcb4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ0_SOME_BANKS_ACTIVE_CLKS_HI 0xcb8 +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcbc +#define EMC_STAT_DRAM_IO_EXTCLKS_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc0 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_LO 0xcc4 +#define EMC_STAT_DRAM_IO_CLKSTOP_CKE_EQ1_SOME_BANKS_ACTIVE_CLKS_HI 0xcc8 +#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_LO 0xccc +#define EMC_STAT_DRAM_IO_SR_CKE_EQ0_CLKS_HI 0xcd0 +#define EMC_STAT_DRAM_IO_DSR 0xcd4 +#define EMC_AUTO_CAL_CONFIG 0x2a4 +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_COMPUTE_START (1 << 0) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_MEASURE_STALL (1 << 9) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_UPDATE_STALL (1 << 10) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_ENABLE (1 << 29) +#define EMC_AUTO_CAL_CONFIG_AUTO_CAL_START (1 << 31) + +#define EMC_AUTO_CAL_CONFIG2 0x458 +#define EMC_AUTO_CAL_CONFIG3 0x45c +#define EMC_AUTO_CAL_CONFIG4 0x5b0 +#define EMC_AUTO_CAL_CONFIG5 0x5b4 +#define EMC_AUTO_CAL_CONFIG6 0x5cc +#define EMC_AUTO_CAL_CONFIG7 0x574 +#define EMC_AUTO_CAL_CONFIG8 0x2dc +#define EMC_AUTO_CAL_VREF_SEL_0 0x2f8 +#define EMC_AUTO_CAL_VREF_SEL_1 0x300 +#define EMC_AUTO_CAL_INTERVAL 0x2a8 +#define EMC_AUTO_CAL_STATUS 0x2ac +#define EMC_AUTO_CAL_STATUS2 0x3d4 +#define EMC_AUTO_CAL_CHANNEL 0x464 +#define EMC_PMACRO_RX_TERM 0xc48 +#define EMC_PMACRO_DQ_TX_DRV 0xc70 +#define EMC_PMACRO_CA_TX_DRV 0xc74 +#define EMC_PMACRO_CMD_TX_DRV 0xc4c +#define EMC_PMACRO_AUTOCAL_CFG_0 0x700 +#define EMC_PMACRO_AUTOCAL_CFG_1 0x704 +#define EMC_PMACRO_AUTOCAL_CFG_2 0x708 +#define EMC_PMACRO_AUTOCAL_CFG_COMMON 0xc78 +#define EMC_PMACRO_AUTOCAL_CFG_COMMON_E_CAL_BYPASS_DVFS (1 << 16) + +#define EMC_PMACRO_ZCTRL 0xc44 +#define EMC_XM2COMPPADCTRL 0x30c +#define EMC_XM2COMPPADCTRL_VREF_CAL_ENABLE (1 << 10) + +#define EMC_XM2COMPPADCTRL2 0x578 +#define EMC_XM2COMPPADCTRL3 0x2f4 +#define EMC_COMP_PAD_SW_CTRL 0x57c +#define EMC_REQ_CTRL 0x2b0 +#define EMC_EMC_STATUS 0x2b4 +#define EMC_EMC_STATUS_MRR_DIVLD (1 << 20) +#define EMC_EMC_STATUS_TIMING_UPDATE_STALLED (1 << 23) +#define EMC_EMC_STATUS_DRAM_IN_POWERDOWN_SHIFT 4 +#define EMC_EMC_STATUS_DRAM_IN_POWERDOWN_MASK \ + (0x3 << EMC_EMC_STATUS_DRAM_IN_POWERDOWN_SHIFT) +#define EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_SHIFT 8 +#define EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_MASK \ + (0x3 << EMC_EMC_STATUS_DRAM_IN_SELF_REFRESH_SHIFT) + +#define EMC_CFG_2 0x2b8 +#define EMC_CFG_DIG_DLL 0x2bc +#define EMC_CFG_DIG_DLL_CFG_DLL_EN (1 << 0) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_UNTIL_LOCK (1 << 1) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_ALL_TRAFFIC (1 << 3) +#define EMC_CFG_DIG_DLL_CFG_DLL_STALL_RW_UNTIL_LOCK (1 << 4) +#define EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT 6 +#define EMC_CFG_DIG_DLL_CFG_DLL_MODE_MASK \ + (0x3 << EMC_CFG_DIG_DLL_CFG_DLL_MODE_SHIFT) +#define EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT 8 +#define EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_MASK \ + (0x7 << EMC_CFG_DIG_DLL_CFG_DLL_LOCK_LIMIT_SHIFT) + +#define EMC_CFG_DIG_DLL_PERIOD 0x2c0 +#define EMC_DIG_DLL_STATUS 0x2c4 +#define EMC_DIG_DLL_STATUS_DLL_LOCK (1 << 15) +#define EMC_DIG_DLL_STATUS_DLL_PRIV_UPDATED (1 << 17) +#define EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT 0 +#define EMC_DIG_DLL_STATUS_DLL_OUT_MASK \ + (0x7ff << EMC_DIG_DLL_STATUS_DLL_OUT_SHIFT) + +#define EMC_CFG_DIG_DLL_1 0x2c8 +#define EMC_RDV_MASK 0x2cc +#define EMC_WDV_MASK 0x2d0 +#define EMC_RDV_EARLY_MASK 0x2d4 +#define EMC_RDV_EARLY 0x2d8 +#define EMC_WDV_CHK 0x4e0 +#define EMC_ZCAL_INTERVAL 0x2e0 +#define EMC_ZCAL_WAIT_CNT 0x2e4 +#define EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_MASK 0x7ff +#define EMC_ZCAL_WAIT_CNT_ZCAL_WAIT_CNT_SHIFT 0 + +#define EMC_ZCAL_MRW_CMD 0x2e8 +#define EMC_ZQ_CAL 0x2ec +#define EMC_ZQ_CAL_DEV_SEL_SHIFT 30 +#define EMC_ZQ_CAL_DEV_SEL_MASK \ + (0x3 << EMC_SELF_REF_DEV_SEL_SHIFT) +#define EMC_ZQ_CAL_LONG (1 << 4) +#define EMC_ZQ_CAL_ZQ_LATCH_CMD (1 << 1) +#define EMC_ZQ_CAL_ZQ_CAL_CMD (1 << 0) +#define EMC_ZQ_CAL_LONG_CMD_DEV0 \ + (DRAM_DEV_SEL_0 | EMC_ZQ_CAL_LONG | EMC_ZQ_CAL_CMD) +#define EMC_ZQ_CAL_LONG_CMD_DEV1 \ + (DRAM_DEV_SEL_1 | EMC_ZQ_CAL_LONG | EMC_ZQ_CAL_CMD) + +#define EMC_SCRATCH0 0x324 +#define EMC_STALL_THEN_EXE_BEFORE_CLKCHANGE 0x3c8 +#define EMC_STALL_THEN_EXE_AFTER_CLKCHANGE 0x3cc +#define EMC_UNSTALL_RW_AFTER_CLKCHANGE 0x3d0 +#define EMC_FDPD_CTRL_CMD_NO_RAMP 0x4d8 +#define EMC_FDPD_CTRL_CMD_NO_RAMP_CMD_DPD_NO_RAMP_ENABLE (1 << 0) + +#define EMC_SEL_DPD_CTRL 0x3d8 +#define EMC_SEL_DPD_CTRL_DATA_SEL_DPD_EN (1 << 8) +#define EMC_SEL_DPD_CTRL_ODT_SEL_DPD_EN (1 << 5) +#define EMC_SEL_DPD_CTRL_RESET_SEL_DPD_EN (1 << 4) +#define EMC_SEL_DPD_CTRL_CA_SEL_DPD_EN (1 << 3) +#define EMC_SEL_DPD_CTRL_CLK_SEL_DPD_EN (1 << 2) +#define EMC_SEL_DPD_CTRL_DDR3_MASK \ + ((0xf << 2) | (0x1 << 8)) +#define EMC_SEL_DPD_CTRL_MAS \ + ((0x3 << 2) | (0x1 << 5) | (0x1 << 8)) + +#define EMC_FDPD_CTRL_DQ 0x310 +#define EMC_FDPD_CTRL_CMD 0x314 +#define EMC_PRE_REFRESH_REQ_CNT 0x3dc +#define EMC_REFCTRL2 0x580 +#define EMC_FBIO_CFG7 0x584 +#define EMC_FBIO_CFG7_CH0_ENABLE (1 << 1) +#define EMC_FBIO_CFG7_CH1_ENABLE (1 << 2) + +#define EMC_DATA_BRLSHFT_0 0x588 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT 21 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE7_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT 18 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE6_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT 15 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE5_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT 12 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE4_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT 9 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE3_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT 6 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE2_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT 3 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE1_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT 0 +#define EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_0_RANK0_BYTE0_DATA_BRLSHFT_SHIFT) + +#define EMC_DATA_BRLSHFT_1 0x58c +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT 21 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE7_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT 18 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE6_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT 15 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE5_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT 12 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE4_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT 9 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE3_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT 6 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE2_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT 3 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE1_DATA_BRLSHFT_SHIFT) +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT 0 +#define EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_MASK \ + (0x7 << EMC_DATA_BRLSHFT_1_RANK1_BYTE0_DATA_BRLSHFT_SHIFT) + +#define EMC_DQS_BRLSHFT_0 0x594 +#define EMC_DQS_BRLSHFT_1 0x598 +#define EMC_CMD_BRLSHFT_0 0x59c +#define EMC_CMD_BRLSHFT_1 0x5a0 +#define EMC_CMD_BRLSHFT_2 0x5a4 +#define EMC_CMD_BRLSHFT_3 0x5a8 +#define EMC_QUSE_BRLSHFT_0 0x5ac +#define EMC_QUSE_BRLSHFT_1 0x5b8 +#define EMC_QUSE_BRLSHFT_2 0x5bc +#define EMC_QUSE_BRLSHFT_3 0x5c4 +#define EMC_FBIO_CFG8 0x5c8 +#define EMC_CMD_MAPPING_CMD0_0 0x380 +#define EMC_CMD_MAPPING_CMD0_1 0x384 +#define EMC_CMD_MAPPING_CMD0_2 0x388 +#define EMC_CMD_MAPPING_CMD1_0 0x38c +#define EMC_CMD_MAPPING_CMD1_1 0x390 +#define EMC_CMD_MAPPING_CMD1_2 0x394 +#define EMC_CMD_MAPPING_CMD2_0 0x398 +#define EMC_CMD_MAPPING_CMD2_1 0x39c +#define EMC_CMD_MAPPING_CMD2_2 0x3a0 +#define EMC_CMD_MAPPING_CMD3_0 0x3a4 +#define EMC_CMD_MAPPING_CMD3_1 0x3a8 +#define EMC_CMD_MAPPING_CMD3_2 0x3ac +#define EMC_CMD_MAPPING_BYTE 0x3b0 +#define EMC_DYN_SELF_REF_CONTROL 0x3e0 +#define EMC_TXSRDLL 0x3e4 +#define EMC_CCFIFO_ADDR 0x3e8 +#define EMC_CCFIFO_DATA 0x3ec +#define EMC_CCFIFO_STATUS 0x3f0 +#define EMC_SWIZZLE_RANK0_BYTE0 0x404 +#define EMC_SWIZZLE_RANK0_BYTE1 0x408 +#define EMC_SWIZZLE_RANK0_BYTE2 0x40c +#define EMC_SWIZZLE_RANK0_BYTE3 0x410 +#define EMC_SWIZZLE_RANK1_BYTE0 0x418 +#define EMC_SWIZZLE_RANK1_BYTE1 0x41c +#define EMC_SWIZZLE_RANK1_BYTE2 0x420 +#define EMC_SWIZZLE_RANK1_BYTE3 0x424 +#define EMC_TR_TIMING_0 0x3b4 +#define EMC_TR_CTRL_0 0x3b8 +#define EMC_TR_CTRL_1 0x3bc +#define EMC_TR_DVFS 0x460 +#define EMC_TR_DVFS_TRAINING_DVFS (1 << 0) + +#define EMC_SWITCH_BACK_CTRL 0x3c0 +#define EMC_TR_RDV 0x3c4 +#define EMC_TR_QPOP 0x3f4 +#define EMC_TR_RDV_MASK 0x3f8 +#define EMC_TR_QSAFE 0x3fc +#define EMC_TR_QRST 0x400 +#define EMC_IBDLY 0x468 +#define EMC_OBDLY 0x46c +#define EMC_TXDSRVTTGEN 0x480 +#define EMC_WE_DURATION 0x48c +#define EMC_WS_DURATION 0x490 +#define EMC_WEV 0x494 +#define EMC_WSV 0x498 +#define EMC_CFG_3 0x49c +#define EMC_CFG_PIPE_2 0x554 +#define EMC_CFG_PIPE_CLK 0x558 +#define EMC_CFG_PIPE_CLK_CLK_ALWAYS_ON (1 << 0) + +#define EMC_CFG_PIPE_1 0x55c +#define EMC_CFG_PIPE 0x560 +#define EMC_QPOP 0x564 +#define EMC_QUSE_WIDTH 0x568 +#define EMC_PUTERM_WIDTH 0x56c +#define EMC_PROTOBIST_CONFIG_ADR_1 0x5d0 +#define EMC_PROTOBIST_CONFIG_ADR_2 0x5d4 +#define EMC_PROTOBIST_MISC 0x5d8 +#define EMC_PROTOBIST_WDATA_LOWER 0x5dc +#define EMC_PROTOBIST_WDATA_UPPER 0x5e0 +#define EMC_PROTOBIST_RDATA 0x5ec +#define EMC_DLL_CFG_0 0x5e4 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_IGNORE_START (1 << 29) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_DUAL_PASS_LOCK (1 << 28) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_SHIFT 24 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_STEP_SIZE_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_SHIFT 20 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_END_COUNT_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_SHIFT 16 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_FILTER_BITS_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_SHIFT 12 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_COUNT_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_SHIFT 4 +#define EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_MASK \ + (0xff << EMC_DLL_CFG_0_DDLLCAL_CTRL_SAMPLE_DELAY_SHIFT) +#define EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_SHIFT 0 +#define EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_MASK \ + (0xf << EMC_DLL_CFG_0_DDLLCAL_UPDATE_CNT_LIMIT_SHIFT) + +#define EMC_DLL_CFG_1 0x5e8 +#define EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_SHIFT 10 +#define EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_MASK \ + (0x7ff << EMC_DLL_CFG_1_DDLLCAL_CTRL_START_TRIM_SHIFT) + +#define EMC_TRAINING_CMD 0xe00 +#define EMC_TRAINING_CMD_PRIME (1 << 0) +#define EMC_TRAINING_CMD_CA (1 << 1) +#define EMC_TRAINING_CMD_RD (1 << 2) +#define EMC_TRAINING_CMD_WR (1 << 3) +#define EMC_TRAINING_CMD_QUSE (1 << 4) +#define EMC_TRAINING_CMD_CA_VREF (1 << 5) +#define EMC_TRAINING_CMD_RD_VREF (1 << 6) +#define EMC_TRAINING_CMD_WR_VREF (1 << 7) +#define EMC_TRAINING_CMD_QUSE_VREF (1 << 8) +#define EMC_TRAINING_CMD_GO (1 << 31) + +#define EMC_TRAINING_CTRL 0xe04 +#define EMC_TRAINING_CTRL_SWAP_RANK (1 << 14) + +#define EMC_TRAINING_STATUS 0xe08 +#define EMC_TRAINING_QUSE_CORS_CTRL 0xe0c +#define EMC_TRAINING_QUSE_FINE_CTRL 0xe10 +#define EMC_TRAINING_QUSE_CTRL_MISC 0xe14 +#define EMC_TRAINING_WRITE_FINE_CTRL 0xe18 +#define EMC_TRAINING_WRITE_CTRL_MISC 0xe1c +#define EMC_TRAINING_WRITE_VREF_CTRL 0xe20 +#define EMC_TRAINING_READ_FINE_CTRL 0xe24 +#define EMC_TRAINING_READ_CTRL_MISC 0xe28 +#define EMC_TRAINING_READ_VREF_CTRL 0xe2c +#define EMC_TRAINING_CA_FINE_CTRL 0xe30 +#define EMC_TRAINING_CA_CTRL_MISC 0xe34 +#define EMC_TRAINING_CA_CTRL_MISC1 0xe38 +#define EMC_TRAINING_CA_VREF_CTRL 0xe3c +#define EMC_TRAINING_CA_TADR_CTRL 0xe40 +#define EMC_TRAINING_SETTLE 0xe44 +#define EMC_TRAINING_DEBUG_CTRL 0xe48 +#define EMC_TRAINING_DEBUG_DQ0 0xe4c +#define EMC_TRAINING_DEBUG_DQ1 0xe50 +#define EMC_TRAINING_DEBUG_DQ2 0xe54 +#define EMC_TRAINING_DEBUG_DQ3 0xe58 +#define EMC_TRAINING_MPC 0xe5c +#define EMC_TRAINING_PATRAM_CTRL 0xe60 +#define EMC_TRAINING_PATRAM_DQ 0xe64 +#define EMC_TRAINING_PATRAM_DMI 0xe68 +#define EMC_TRAINING_VREF_SETTLE 0xe6c +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE0 0xe70 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE1 0xe74 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE2 0xe78 +#define EMC_TRAINING_RW_EYE_CENTER_IB_BYTE3 0xe7c +#define EMC_TRAINING_RW_EYE_CENTER_IB_MISC 0xe80 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE0 0xe84 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE1 0xe88 +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE2 0xe8c +#define EMC_TRAINING_RW_EYE_CENTER_OB_BYTE3 0xe90 +#define EMC_TRAINING_RW_EYE_CENTER_OB_MISC 0xe94 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE0 0xe98 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE1 0xe9c +#define EMC_TRAINING_RW_OFFSET_IB_BYTE2 0xea0 +#define EMC_TRAINING_RW_OFFSET_IB_BYTE3 0xea4 +#define EMC_TRAINING_RW_OFFSET_IB_MISC 0xea8 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE0 0xeac +#define EMC_TRAINING_RW_OFFSET_OB_BYTE1 0xeb0 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE2 0xeb4 +#define EMC_TRAINING_RW_OFFSET_OB_BYTE3 0xeb8 +#define EMC_TRAINING_RW_OFFSET_OB_MISC 0xebc +#define EMC_TRAINING_OPT_CA_VREF 0xec0 +#define EMC_TRAINING_OPT_DQ_OB_VREF 0xec4 +#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK0 0xec8 +#define EMC_TRAINING_OPT_DQ_IB_VREF_RANK1 0xecc +#define EMC_TRAINING_QUSE_VREF_CTRL 0xed0 +#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK0 0xed4 +#define EMC_TRAINING_OPT_DQS_IB_VREF_RANK1 0xed8 +#define EMC_TRAINING_DRAMC_TIMING 0xedc +#define EMC_PMACRO_QUSE_DDLL_RANK0_0 0x600 +#define EMC_PMACRO_QUSE_DDLL_RANK0_1 0x604 +#define EMC_PMACRO_QUSE_DDLL_RANK0_2 0x608 +#define EMC_PMACRO_QUSE_DDLL_RANK0_3 0x60c +#define EMC_PMACRO_QUSE_DDLL_RANK0_4 0x610 +#define EMC_PMACRO_QUSE_DDLL_RANK0_5 0x614 +#define EMC_PMACRO_QUSE_DDLL_RANK1_0 0x620 +#define EMC_PMACRO_QUSE_DDLL_RANK1_1 0x624 +#define EMC_PMACRO_QUSE_DDLL_RANK1_2 0x628 +#define EMC_PMACRO_QUSE_DDLL_RANK1_3 0x62c +#define EMC_PMACRO_QUSE_DDLL_RANK1_4 0x630 +#define EMC_PMACRO_QUSE_DDLL_RANK1_5 0x634 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0 0x640 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE1_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0_OB_DDLL_LONG_DQ_RANK0_BYTE0_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1 0x644 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE3_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1_OB_DDLL_LONG_DQ_RANK0_BYTE2_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2 0x648 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE5_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2_OB_DDLL_LONG_DQ_RANK0_BYTE4_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3 0x64c +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE7_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3_OB_DDLL_LONG_DQ_RANK0_BYTE6_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4 0x650 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5 0x654 + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0 0x660 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE1_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0_OB_DDLL_LONG_DQ_RANK1_BYTE0_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1 0x664 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE3_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1_OB_DDLL_LONG_DQ_RANK1_BYTE2_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2 0x668 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE5_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2_OB_DDLL_LONG_DQ_RANK1_BYTE4_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3 0x66c +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_SHIFT \ + 16 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE7_SHIFT +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_SHIFT \ + 0 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_MASK \ + 0x3ff << \ + EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3_OB_DDLL_LONG_DQ_RANK1_BYTE6_SHIFT + +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4 0x670 +#define EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5 0x674 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0 0x680 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1 0x684 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2 0x688 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3 0x68c +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4 0x690 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5 0x694 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0 0x6a0 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1 0x6a4 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2 0x6a8 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3 0x6ac +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4 0x6b0 +#define EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5 0x6b4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0 0x6c0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1 0x6c4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2 0x6c8 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3 0x6cc +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_4 0x6d0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_5 0x6d4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0 0x6e0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1 0x6e4 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2 0x6e8 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3 0x6ec +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_4 0x6f0 +#define EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_5 0x6f4 +#define EMC_PMACRO_TX_PWRD_0 0x720 +#define EMC_PMACRO_TX_PWRD_1 0x724 +#define EMC_PMACRO_TX_PWRD_2 0x728 +#define EMC_PMACRO_TX_PWRD_3 0x72c +#define EMC_PMACRO_TX_PWRD_4 0x730 +#define EMC_PMACRO_TX_PWRD_5 0x734 +#define EMC_PMACRO_TX_SEL_CLK_SRC_0 0x740 +#define EMC_PMACRO_TX_SEL_CLK_SRC_1 0x744 +#define EMC_PMACRO_TX_SEL_CLK_SRC_3 0x74c +#define EMC_PMACRO_TX_SEL_CLK_SRC_2 0x748 +#define EMC_PMACRO_TX_SEL_CLK_SRC_4 0x750 +#define EMC_PMACRO_TX_SEL_CLK_SRC_5 0x754 +#define EMC_PMACRO_DDLL_BYPASS 0x760 +#define EMC_PMACRO_DDLL_PWRD_0 0x770 +#define EMC_PMACRO_DDLL_PWRD_1 0x774 +#define EMC_PMACRO_DDLL_PWRD_2 0x778 +#define EMC_PMACRO_CMD_CTRL_0 0x780 +#define EMC_PMACRO_CMD_CTRL_1 0x784 +#define EMC_PMACRO_CMD_CTRL_2 0x788 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0x800 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0x804 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0x808 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE0_3 0x80c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0x810 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0x814 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0x818 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE1_3 0x81c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0x820 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0x824 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0x828 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE2_3 0x82c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0x830 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0x834 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0x838 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE3_3 0x83c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0x840 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0x844 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0x848 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE4_3 0x84c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0x850 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0x854 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0x858 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE5_3 0x85c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0x860 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0x864 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0x868 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE6_3 0x86c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0x870 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0x874 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0x878 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_BYTE7_3 0x87c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_0 0x880 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_1 0x884 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_2 0x888 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD0_3 0x88c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_0 0x890 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_1 0x894 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_2 0x898 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD1_3 0x89c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_0 0x8a0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_1 0x8a4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_2 0x8a8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD2_3 0x8ac +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_0 0x8b0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_1 0x8b4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_2 0x8b8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK0_CMD3_3 0x8bc +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0x900 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0x904 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0x908 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE0_3 0x90c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0x910 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0x914 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0x918 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE1_3 0x91c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0x920 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0x924 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0x928 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE2_3 0x92c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0x930 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0x934 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0x938 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE3_3 0x93c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0x940 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0x944 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0x948 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE4_3 0x94c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0x950 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0x954 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0x958 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE5_3 0x95c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0x960 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0x964 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0x968 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE6_3 0x96c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0x970 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0x974 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0x978 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_BYTE7_3 0x97c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_0 0x980 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_1 0x984 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_2 0x988 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD0_3 0x98c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_0 0x990 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_1 0x994 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_2 0x998 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD1_3 0x99c +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_0 0x9a0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_1 0x9a4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_2 0x9a8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD2_3 0x9ac +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_0 0x9b0 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_1 0x9b4 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_2 0x9b8 +#define EMC_PMACRO_OB_DDLL_SHORT_DQ_RANK1_CMD3_3 0x9bc +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_0 0xa00 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_1 0xa04 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE0_2 0xa08 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_0 0xa10 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_1 0xa14 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE1_2 0xa18 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_0 0xa20 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_1 0xa24 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE2_2 0xa28 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_0 0xa30 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_1 0xa34 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE3_2 0xa38 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_0 0xa40 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_1 0xa44 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE4_2 0xa48 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_0 0xa50 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_1 0xa54 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE5_2 0xa58 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_0 0xa60 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_1 0xa64 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE6_2 0xa68 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_0 0xa70 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_1 0xa74 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_BYTE7_2 0xa78 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_0 0xa80 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_1 0xa84 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD0_2 0xa88 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_0 0xa90 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_1 0xa94 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD1_2 0xa98 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_0 0xaa0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_1 0xaa4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD2_2 0xaa8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_0 0xab0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_1 0xab4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK0_CMD3_2 0xab8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_0 0xb00 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_1 0xb04 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE0_2 0xb08 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_0 0xb10 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_1 0xb14 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE1_2 0xb18 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_0 0xb20 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_1 0xb24 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE2_2 0xb28 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_0 0xb30 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_1 0xb34 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE3_2 0xb38 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_0 0xb40 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_1 0xb44 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE4_2 0xb48 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_0 0xb50 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_1 0xb54 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE5_2 0xb58 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_0 0xb60 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_1 0xb64 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE6_2 0xb68 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_0 0xb70 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_1 0xb74 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_BYTE7_2 0xb78 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_0 0xb80 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_1 0xb84 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD0_2 0xb88 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_0 0xb90 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_1 0xb94 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD1_2 0xb98 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_0 0xba0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_1 0xba4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD2_2 0xba8 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_0 0xbb0 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_1 0xbb4 +#define EMC_PMACRO_IB_DDLL_SHORT_DQ_RANK1_CMD3_2 0xbb8 +#define EMC_PMACRO_IB_VREF_DQ_0 0xbe0 +#define EMC_PMACRO_IB_VREF_DQ_1 0xbe4 +#define EMC_PMACRO_IB_VREF_DQ_2 0xbe8 +#define EMC_PMACRO_IB_VREF_DQS_0 0xbf0 +#define EMC_PMACRO_IB_VREF_DQS_1 0xbf4 +#define EMC_PMACRO_IB_VREF_DQS_2 0xbf8 +#define EMC_PMACRO_IB_RXRT 0xcf4 +#define EMC_PMACRO_DDLL_LONG_CMD_0 0xc00 +#define EMC_PMACRO_DDLL_LONG_CMD_1 0xc04 +#define EMC_PMACRO_DDLL_LONG_CMD_2 0xc08 +#define EMC_PMACRO_DDLL_LONG_CMD_3 0xc0c +#define EMC_PMACRO_DDLL_LONG_CMD_4 0xc10 +#define EMC_PMACRO_DDLL_LONG_CMD_5 0xc14 +#define EMC_PMACRO_DDLL_SHORT_CMD_0 0xc20 +#define EMC_PMACRO_DDLL_SHORT_CMD_1 0xc24 +#define EMC_PMACRO_DDLL_SHORT_CMD_2 0xc28 +#define EMC_PMACRO_CFG_PM_GLOBAL_0 0xc30 +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE0 (1 << 16) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE1 (1 << 17) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE2 (1 << 18) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE3 (1 << 19) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE4 (1 << 20) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE5 (1 << 21) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE6 (1 << 22) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_BYTE7 (1 << 23) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD0 (1 << 24) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD1 (1 << 25) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD2 (1 << 26) +#define EMC_PMACRO_CFG_PM_GLOBAL_0_DISABLE_CFG_CMD3 (1 << 27) + +#define EMC_PMACRO_VTTGEN_CTRL_0 0xc34 +#define EMC_PMACRO_VTTGEN_CTRL_1 0xc38 +#define EMC_PMACRO_VTTGEN_CTRL_2 0xcf0 +#define EMC_PMACRO_BG_BIAS_CTRL_0 0xc3c +#define EMC_PMACRO_BG_BIAS_CTRL_0_BG_E_PWRD (1 << 0) +#define EMC_PMACRO_BG_BIAS_CTRL_0_BG_MODE (1 << 1) +#define EMC_PMACRO_BG_BIAS_CTRL_0_BGLP_E_PWRD (1 << 2) + +#define EMC_PMACRO_PAD_CFG_CTRL 0xc40 +#define EMC_PMACRO_CMD_PAD_RX_CTRL 0xc50 +#define EMC_PMACRO_DATA_PAD_RX_CTRL 0xc54 +#define EMC_PMACRO_CMD_RX_TERM_MODE 0xc58 +#define EMC_PMACRO_DATA_RX_TERM_MODE 0xc5c +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_SHIFT 8 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_SHIFT) +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_SHIFT 4 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_SHIFT) +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_SHIFT 0 +#define EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_MASK (0x3 << \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_SHIFT) + +#define RX_TERM_MODE \ + ~(EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSN_RX_TERM_MODE_MASK | \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQSP_RX_TERM_MODE_MASK | \ + EMC_PMACRO_DATA_RX_TERM_MODE_DATA_DQ_RX_TERM_MODE_MASK) + +#define EMC_PMACRO_CMD_PAD_TX_CTRL 0xc60 +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_E_DCC (1 << 1) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSP_TX_E_DCC (1 << 9) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQSN_TX_E_DCC (1 << 16) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_CMD_TX_E_DCC (1 << 24) +#define EMC_PMACRO_CMD_PAD_TX_CTRL_CMD_DQ_TX_DRVFORCEON (1 << 26) + +#define EMC_PMACRO_DATA_PAD_TX_CTRL 0xc64 +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_E_IVREF (1 << 0) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQ_TX_E_DCC (1 << 1) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQS_E_IVREF (1 << 8) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSP_TX_E_DCC (1 << 9) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_DQSN_TX_E_DCC (1 << 16) +#define EMC_PMACRO_DATA_PAD_TX_CTRL_DATA_CMD_TX_E_DCC (1 << 24) + +#define EMC_PMACRO_COMMON_PAD_TX_CTRL 0xc68 +#define EMC_PMACRO_BRICK_MAPPING_0 0xc80 +#define EMC_PMACRO_BRICK_MAPPING_1 0xc84 +#define EMC_PMACRO_BRICK_MAPPING_2 0xc88 +#define EMC_PMACRO_DDLLCAL_CAL 0xce0 +#define EMC_PMACRO_DDLL_OFFSET 0xce4 +#define EMC_PMACRO_DDLL_PERIODIC_OFFSET 0xce8 +#define EMC_PMACRO_BRICK_CTRL_RFU1 0x330 +#define EMC_PMACRO_BRICK_CTRL_RFU2 0x334 +#define EMC_PMACRO_CMD_BRICK_CTRL_FDPD 0x318 +#define EMC_PMACRO_DATA_BRICK_CTRL_FDPD 0x31c +#define EMC_PMACRO_TRAINING_CTRL_0 0xcf8 +#define EMC_PMACRO_TRAINING_CTRL_0_CH0_TRAINING_E_WRPTR (1 << 3) + +#define EMC_PMACRO_TRAINING_CTRL_1 0xcfc +#define EMC_PMACRO_TRAINING_CTRL_1_CH1_TRAINING_E_WRPTR (1 << 3) + +#define EMC_PMC_SCRATCH1 0x440 +#define EMC_PMC_SCRATCH2 0x444 +#define EMC_PMC_SCRATCH3 0x448 + +#endif diff --git a/sept/sept-secondary/src/exception_handlers.c b/sept/sept-secondary/src/exception_handlers.c new file mode 100644 index 000000000..e0e5392b0 --- /dev/null +++ b/sept/sept-secondary/src/exception_handlers.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <inttypes.h> + +#include "exception_handlers.h" +#include "utils.h" +#include "lib/log.h" + +#define CODE_DUMP_SIZE 0x30 +#define STACK_DUMP_SIZE 0x60 + +extern const uint32_t exception_handler_table[]; + +static const char *exception_names[] = { + "Reset", "Undefined instruction", "SWI", "Prefetch abort", "Data abort", "Reserved", "IRQ", "FIQ", +}; + +static const char *register_names[] = { + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", + "SP", "LR", "PC", "CPSR", +}; + +void setup_exception_handlers(void) { + volatile uint32_t *bpmp_exception_handler_table = (volatile uint32_t *)0x6000F200; + for (int i = 0; i < 8; i++) { + if (exception_handler_table[i] != 0) { + bpmp_exception_handler_table[i] = exception_handler_table[i]; + } + } +} + +void exception_handler_main(uint32_t *registers, unsigned int exception_type) { + uint8_t code_dump[CODE_DUMP_SIZE]; + uint8_t stack_dump[STACK_DUMP_SIZE]; + size_t code_dump_size; + size_t stack_dump_size; + + uint32_t pc = registers[15]; + uint32_t cpsr = registers[16]; + + uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE; + + print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n"); + + code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE); + stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE); + + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n", + exception_names[exception_type]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n"); + + /* Print r0 to pc. */ + for (int i = 0; i < 16; i += 2) { + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n", + register_names[i], registers[i], register_names[i+1], registers[i+1]); + } + + /* Print cpsr. */ + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]); + + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n"); + hexdump(code_dump, code_dump_size, instr_addr); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n"); + hexdump(stack_dump, stack_dump_size, registers[13]); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); + fatal_error("An exception occured!\n"); +} diff --git a/sept/sept-secondary/src/exception_handlers.h b/sept/sept-secondary/src/exception_handlers.h new file mode 100644 index 000000000..7fda29867 --- /dev/null +++ b/sept/sept-secondary/src/exception_handlers.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_EXCEPTION_HANDLERS_H +#define FUSEE_EXCEPTION_HANDLERS_H + +#include <stdint.h> +#include <stddef.h> + +/* Copies up to len bytes, stops and returns the read length on data fault. */ +size_t safecpy(void *dst, const void *src, size_t len); + +void setup_exception_handlers(void); + +#endif diff --git a/sept/sept-secondary/src/exception_handlers_asm.s b/sept/sept-secondary/src/exception_handlers_asm.s new file mode 100644 index 000000000..84b34308b --- /dev/null +++ b/sept/sept-secondary/src/exception_handlers_asm.s @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +.macro GEN_USUAL_HANDLER name, index, lr_arm_displ, lr_thumb_displ + _exception_handler_\name: + ldr sp, =_regs + stmia sp!, {r0-r7} + + /* Adjust lr to make it point to the location where the exception occured. */ + mrs r1, spsr + tst r1, #0x20 + subeq lr, lr, #\lr_arm_displ + subne lr, lr, #\lr_thumb_displ + + mov r0, sp + mov r1, #\index + b _exception_handler_common +.endm + +.section .text.exception_handlers_asm, "ax", %progbits +.arm +.align 5 + +_exception_handler_common: + mrs r2, spsr + mrs r3, cpsr + + /* Mask interrupts. */ + orr r3, #0xC0 + msr cpsr_cx, r3 + + /* Switch to the mode that triggered the interrupt, get the remaining regs, switch back. */ + ands r4, r2, #0xF + moveq r4, #0xF /* usr => sys */ + bic r5, r3, #0xF + orr r5, r4 + msr cpsr_c, r5 + stmia r0!, {r8-lr} + msr cpsr_c, r3 + + str lr, [r0], #4 + str r2, [r0] + + /* Finally, switch to system mode, setting interrupts and clearing the flags; set sp as well. */ + msr cpsr_cxsf, #0xDF + ldr sp, =(_exception_handler_stack + 0x1000) + ldr r0, =_regs + bl exception_handler_main + b . + +GEN_USUAL_HANDLER undefined_instruction, 1, 4, 2 +GEN_USUAL_HANDLER swi, 2, 4, 2 +GEN_USUAL_HANDLER prefetch_abort, 3, 4, 4 +GEN_USUAL_HANDLER data_abort_normal, 4, 8, 8 +GEN_USUAL_HANDLER fiq, 7, 4, 4 + +_exception_handler_data_abort: + /* Mask interrupts (abort mode). */ + msr cpsr_cx, #0xD7 + + adr sp, safecpy+8 + cmp lr, sp + blo _exception_handler_data_abort_normal + adr sp, _safecpy_end+8 + cmp lr, sp + bhs _exception_handler_data_abort_normal + + /* Set the flags, set r12 to 0 for safecpy, return from exception. */ + msr spsr_f, #(1 << 30) + mov r12, #0 + subs pc, lr, #4 + +.global safecpy +.type safecpy, %function +safecpy: + push {r4, lr} + mov r3, #0 + movs r12, #1 + + _safecpy_loop: + ldrb r4, [r1, r3] + cmp r12, #0 + beq _safecpy_loop_end + strb r4, [r0, r3] + add r3, #1 + cmp r3, r2 + blo _safecpy_loop + + _safecpy_loop_end: + mov r0, r3 + pop {r4, lr} + bx lr /* Need to do that separately on ARMv4. */ + +_safecpy_end: + +.section .rodata.exception_handlers_asm, "a", %progbits +.align 2 +.global exception_handler_table +exception_handler_table: + .word 0 /* Reset */ + .word _exception_handler_undefined_instruction + .word _exception_handler_swi + .word _exception_handler_prefetch_abort + .word _exception_handler_data_abort + .word 0 /* Reserved */ + .word 0 /* IRQ */ + .word _exception_handler_fiq + +.section .bss.exception_handlers_asm, "w", %nobits +.align 4 +_exception_handler_stack: .skip 0x1000 +_regs: .skip (4 * 17) diff --git a/sept/sept-secondary/src/flow.h b/sept/sept-secondary/src/flow.h new file mode 100644 index 000000000..cd98d8983 --- /dev/null +++ b/sept/sept-secondary/src/flow.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_FLOW_CTLR_H +#define FUSEE_FLOW_CTLR_H + +#include <stdint.h> + +#define FLOW_CTLR_BASE 0x60007000 +#define MAKE_FLOW_REG(n) MAKE_REG32(FLOW_CTLR_BASE + n) + +#define FLOW_CTLR_HALT_COP_EVENTS_0 MAKE_FLOW_REG(0x004) +#define FLOW_CTLR_RAM_REPAIR_0 MAKE_FLOW_REG(0x040) +#define FLOW_CTLR_FLOW_DBG_QUAL_0 MAKE_FLOW_REG(0x050) +#define FLOW_CTLR_L2FLUSH_CONTROL_0 MAKE_FLOW_REG(0x094) +#define FLOW_CTLR_BPMP_CLUSTER_CONTROL_0 MAKE_FLOW_REG(0x098) + +#endif diff --git a/sept/sept-secondary/src/fs_utils.c b/sept/sept-secondary/src/fs_utils.c new file mode 100644 index 000000000..f788c1f94 --- /dev/null +++ b/sept/sept-secondary/src/fs_utils.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "fs_utils.h" +#include "mc.h" +#include "lib/fatfs/ff.h" +#include "lib/log.h" + +FATFS sd_fs; +static bool g_sd_mounted = false; +static bool g_sd_initialized = false; +static bool g_ahb_redirect_enabled = false; + +bool mount_sd(void) +{ + /* Already mounted. */ + if (g_sd_mounted) + return true; + + /* Enable AHB redirection if necessary. */ + if (!g_ahb_redirect_enabled) { + mc_enable_ahb_redirect(); + g_ahb_redirect_enabled = true; + } + + if (!g_sd_initialized) { + /* Initialize SD. */ + if (sdmmc_device_sd_init(&g_sd_device, &g_sd_sdmmc, SDMMC_BUS_WIDTH_4BIT, SDMMC_SPEED_SDR104)) + { + g_sd_initialized = true; + + /* Mount SD. */ + if (f_mount(&sd_fs, "", 1) == FR_OK) { + print(SCREEN_LOG_LEVEL_INFO, "Mounted SD card!\n"); + g_sd_mounted = true; + } + } + else + fatal_error("Failed to initialize the SD card!.\n"); + } + + return g_sd_mounted; +} + +void unmount_sd(void) +{ + if (g_sd_mounted) + { + f_mount(NULL, "", 1); + sdmmc_device_finish(&g_sd_device); + g_sd_mounted = false; + } + + /* Disable AHB redirection if necessary. */ + if (g_ahb_redirect_enabled) { + mc_disable_ahb_redirect(); + g_ahb_redirect_enabled = false; + } +} + +uint32_t get_file_size(const char *filename) +{ + /* SD card hasn't been mounted yet. */ + if (!g_sd_mounted) + return 0; + + /* Open the file for reading. */ + FIL f; + if (f_open(&f, filename, FA_READ) != FR_OK) + return 0; + + /* Get the file size. */ + uint32_t file_size = f_size(&f); + + /* Close the file. */ + f_close(&f); + + return file_size; +} + +int read_from_file(void *dst, uint32_t dst_size, const char *filename) +{ + /* SD card hasn't been mounted yet. */ + if (!g_sd_mounted) + return 0; + + /* Open the file for reading. */ + FIL f; + if (f_open(&f, filename, FA_READ) != FR_OK) + return 0; + + /* Sync. */ + f_sync(&f); + + /* Read from file. */ + UINT br = 0; + int res = f_read(&f, dst, dst_size, &br); + f_close(&f); + + return (res == FR_OK) ? (int)br : 0; +} + +int write_to_file(void *src, uint32_t src_size, const char *filename) +{ + /* SD card hasn't been mounted yet. */ + if (!g_sd_mounted) + return 0; + + /* Open the file for writing. */ + FIL f; + if (f_open(&f, filename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) + return 0; + + /* Sync. */ + f_sync(&f); + + /* Write to file. */ + UINT bw = 0; + int res = f_write(&f, src, src_size, &bw); + f_close(&f); + + return (res == FR_OK) ? (int)bw : 0; +} \ No newline at end of file diff --git a/sept/sept-secondary/src/fs_utils.h b/sept/sept-secondary/src/fs_utils.h new file mode 100644 index 000000000..c70df83f6 --- /dev/null +++ b/sept/sept-secondary/src/fs_utils.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_FS_UTILS_H +#define FUSEE_FS_UTILS_H + +#include <stdbool.h> +#include <stdint.h> + +#include "sdmmc/sdmmc.h" +#include "utils.h" + +sdmmc_t g_sd_sdmmc; +sdmmc_device_t g_sd_device; + +bool mount_sd(void); +void unmount_sd(void); +uint32_t get_file_size(const char *filename); +int read_from_file(void *dst, uint32_t dst_size, const char *filename); +int write_to_file(void *src, uint32_t src_size, const char *filename); + +#endif diff --git a/sept/sept-secondary/src/fuse.c b/sept/sept-secondary/src/fuse.c new file mode 100644 index 000000000..cc5656cc7 --- /dev/null +++ b/sept/sept-secondary/src/fuse.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#include "car.h" +#include "fuse.h" +#include "timers.h" + +/* Prototypes for internal commands. */ +void fuse_make_regs_visible(void); + +void fuse_enable_power(void); +void fuse_disable_power(void); +void fuse_wait_idle(void); + +/* Initialize the fuse driver */ +void fuse_init(void) { + fuse_make_regs_visible(); + fuse_secondary_private_key_disable(); + fuse_disable_programming(); + + /* TODO: Overrides (iROM patches) and various reads happen here */ +} + +/* Make all fuse registers visible */ +void fuse_make_regs_visible(void) { + clkrst_enable_fuse_regs(true); +} + +/* Enable power to the fuse hardware array */ +void fuse_enable_power(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PWR_GOOD_SW = 1; + udelay(1); +} + +/* Disable power to the fuse hardware array */ +void fuse_disable_power(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PWR_GOOD_SW = 0; + udelay(1); +} + +/* Wait for the fuse driver to go idle */ +void fuse_wait_idle(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + uint32_t ctrl_val = 0; + + /* Wait for STATE_IDLE */ + while ((ctrl_val & (0xF0000)) != 0x40000) + { + udelay(1); + ctrl_val = fuse->FUSE_CTRL; + } +} + +/* Read a fuse from the hardware array */ +uint32_t fuse_hw_read(uint32_t addr) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse_wait_idle(); + + /* Program the target address */ + fuse->FUSE_REG_ADDR = addr; + + /* Enable read operation in control register */ + uint32_t ctrl_val = fuse->FUSE_CTRL; + ctrl_val &= ~0x3; + ctrl_val |= 0x1; /* Set FUSE_READ command */ + fuse->FUSE_CTRL = ctrl_val; + + fuse_wait_idle(); + + return fuse->FUSE_REG_READ; +} + +/* Write a fuse in the hardware array */ +void fuse_hw_write(uint32_t value, uint32_t addr) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse_wait_idle(); + + /* Program the target address and value */ + fuse->FUSE_REG_ADDR = addr; + fuse->FUSE_REG_WRITE = value; + + /* Enable write operation in control register */ + uint32_t ctrl_val = fuse->FUSE_CTRL; + ctrl_val &= ~0x3; + ctrl_val |= 0x2; /* Set FUSE_WRITE command */ + fuse->FUSE_CTRL = ctrl_val; + + fuse_wait_idle(); +} + +/* Sense the fuse hardware array into the shadow cache */ +void fuse_hw_sense(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse_wait_idle(); + + /* Enable sense operation in control register */ + uint32_t ctrl_val = fuse->FUSE_CTRL; + ctrl_val &= ~0x3; + ctrl_val |= 0x3; /* Set FUSE_SENSE command */ + fuse->FUSE_CTRL = ctrl_val; + + fuse_wait_idle(); +} + +/* Disables all fuse programming. */ +void fuse_disable_programming(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_DIS_PGM = 1; +} + +/* Unknown exactly what this does, but it alters the contents read from the fuse cache. */ +void fuse_secondary_private_key_disable(void) { + volatile tegra_fuse_t *fuse = fuse_get_regs(); + fuse->FUSE_PRIVATEKEYDISABLE = 0x10; +} + + +/* Read the SKU info register from the shadow cache */ +uint32_t fuse_get_sku_info(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return fuse_chip->FUSE_SKU_INFO; +} + +/* Read the bootrom patch version from a register in the shadow cache */ +uint32_t fuse_get_bootrom_patch_version(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return fuse_chip->FUSE_SOC_SPEEDO_1; +} + +/* Read a spare bit register from the shadow cache */ +uint32_t fuse_get_spare_bit(uint32_t idx) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + if (idx >= 32) { + return 0; + } + + return fuse_chip->FUSE_SPARE_BIT[idx]; +} + +/* Read a reserved ODM register from the shadow cache */ +uint32_t fuse_get_reserved_odm(uint32_t idx) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + if (idx >= 8) { + return 0; + } + + return fuse_chip->FUSE_RESERVED_ODM[idx]; +} + +/* Derive the Device ID using values in the shadow cache */ +uint64_t fuse_get_device_id(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + uint64_t device_id = 0; + uint64_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF; + uint64_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF; + uint64_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F; + uint32_t lot_code = fuse_chip->FUSE_LOT_CODE_0; + uint64_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F; + uint64_t derived_lot_code = 0; + for (unsigned int i = 0; i < 5; i++) { + derived_lot_code = (derived_lot_code * 0x24) + ((lot_code >> (24 - 6*i)) & 0x3F); + } + derived_lot_code &= 0x03FFFFFF; + + device_id |= y_coord << 0; + device_id |= x_coord << 9; + device_id |= wafer_id << 18; + device_id |= derived_lot_code << 24; + device_id |= fab_code << 50; + return device_id; +} + +/* Get the DRAM ID using values in the shadow cache */ +uint32_t fuse_get_dram_id(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + return (fuse_chip->FUSE_RESERVED_ODM[4] >> 3) & 0x7; +} + +/* Derive the Hardware Type using values in the shadow cache */ +uint32_t fuse_get_hardware_type(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + /* This function is very different between 4.x and < 4.x */ + uint32_t hardware_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 2) | ((fuse_chip->FUSE_RESERVED_ODM[4] >> 2) & 1); + + /* TODO: choose; if (mkey_get_revision() >= MASTERKEY_REVISION_400_CURRENT) { + static const uint32_t types[] = {0,1,4,3}; + + hardware_type |= (fuse_chip->FUSE_RESERVED_ODM[4] >> 14) & 0x3C; + hardware_type--; + return hardware_type > 3 ? 4 : types[hardware_type]; + } else {*/ + if (hardware_type >= 1) { + return hardware_type > 2 ? 3 : hardware_type - 1; + } else if ((fuse_chip->FUSE_SPARE_BIT[9] & 1) == 0) { + return 0; + } else { + return 3; + } +// } +} + +/* Derive the Retail Type using values in the shadow cache */ +uint32_t fuse_get_retail_type(void) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + + /* Retail type = IS_RETAIL | UNIT_TYPE */ + uint32_t retail_type = ((fuse_chip->FUSE_RESERVED_ODM[4] >> 7) & 4) | (fuse_chip->FUSE_RESERVED_ODM[4] & 3); + if (retail_type == 4) { /* Standard retail unit, IS_RETAIL | 0. */ + return 1; + } else if (retail_type == 3) { /* Standard dev unit, 0 | DEV_UNIT. */ + return 0; + } + return 2; /* IS_RETAIL | DEV_UNIT */ +} + +/* Derive the 16-byte Hardware Info using values in the shadow cache, and copy to output buffer. */ +void fuse_get_hardware_info(void *dst) { + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + uint32_t hw_info[0x4]; + + uint32_t unk_hw_fuse = fuse_chip->_0x120 & 0x3F; + uint32_t y_coord = fuse_chip->FUSE_Y_COORDINATE & 0x1FF; + uint32_t x_coord = fuse_chip->FUSE_X_COORDINATE & 0x1FF; + uint32_t wafer_id = fuse_chip->FUSE_WAFER_ID & 0x3F; + uint32_t lot_code_0 = fuse_chip->FUSE_LOT_CODE_0; + uint32_t lot_code_1 = fuse_chip->FUSE_LOT_CODE_1 & 0x0FFFFFFF; + uint32_t fab_code = fuse_chip->FUSE_FAB_CODE & 0x3F; + uint32_t vendor_code = fuse_chip->FUSE_VENDOR_CODE & 0xF; + + /* Hardware Info = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID */ + hw_info[0] = (uint32_t)((lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | (unk_hw_fuse)); + hw_info[1] = (uint32_t)((lot_code_0 << 26) | (lot_code_1 >> 2)); + hw_info[2] = (uint32_t)((fab_code << 26) | (lot_code_0 >> 6)); + hw_info[3] = (uint32_t)(vendor_code); + + memcpy(dst, hw_info, 0x10); +} diff --git a/sept/sept-secondary/src/fuse.h b/sept/sept-secondary/src/fuse.h new file mode 100644 index 000000000..528b0aff4 --- /dev/null +++ b/sept/sept-secondary/src/fuse.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_FUSE_H +#define FUSEE_FUSE_H + +#define FUSE_BASE 0x7000F800 +#define FUSE_CHIP_BASE (FUSE_BASE + 0x100) +#define MAKE_FUSE_REG(n) MAKE_REG32(FUSE_BASE + n) +#define MAKE_FUSE_CHIP_REG(n) MAKE_REG32(FUSE_CHIP_BASE + n) + +typedef struct { + uint32_t FUSE_CTRL; + uint32_t FUSE_REG_ADDR; + uint32_t FUSE_REG_READ; + uint32_t FUSE_REG_WRITE; + uint32_t FUSE_TIME_RD1; + uint32_t FUSE_TIME_RD2; + uint32_t FUSE_TIME_PGM1; + uint32_t FUSE_TIME_PGM2; + uint32_t FUSE_PRIV2INTFC; + uint32_t FUSE_FUSEBYPASS; + uint32_t FUSE_PRIVATEKEYDISABLE; + uint32_t FUSE_DIS_PGM; + uint32_t FUSE_WRITE_ACCESS; + uint32_t FUSE_PWR_GOOD_SW; + uint32_t _0x38[0x32]; +} tegra_fuse_t; + +typedef struct { + uint32_t FUSE_PRODUCTION_MODE; + uint32_t _0x4; + uint32_t _0x8; + uint32_t _0xC; + uint32_t FUSE_SKU_INFO; + uint32_t FUSE_CPU_SPEEDO_0; + uint32_t FUSE_CPU_IDDQ; + uint32_t _0x1C; + uint32_t _0x20; + uint32_t _0x24; + uint32_t FUSE_FT_REV; + uint32_t FUSE_CPU_SPEEDO_1; + uint32_t FUSE_CPU_SPEEDO_2; + uint32_t FUSE_SOC_SPEEDO_0; + uint32_t FUSE_SOC_SPEEDO_1; + uint32_t FUSE_SOC_SPEEDO_2; + uint32_t FUSE_SOC_IDDQ; + uint32_t _0x44; + uint32_t FUSE_FA; + uint32_t _0x4C; + uint32_t _0x50; + uint32_t _0x54; + uint32_t _0x58; + uint32_t _0x5C; + uint32_t _0x60; + uint32_t FUSE_PUBLIC_KEY[0x8]; + uint32_t FUSE_TSENSOR_1; + uint32_t FUSE_TSENSOR_2; + uint32_t _0x8C; + uint32_t FUSE_CP_REV; + uint32_t _0x94; + uint32_t FUSE_TSENSOR_0; + uint32_t FUSE_FIRST_BOOTROM_PATCH_SIZE_REG; + uint32_t FUSE_SECURITY_MODE; + uint32_t FUSE_PRIVATE_KEY[0x4]; + uint32_t FUSE_DEVICE_KEY; + uint32_t _0xB8; + uint32_t _0xBC; + uint32_t FUSE_RESERVED_SW; + uint32_t FUSE_VP8_ENABLE; + uint32_t FUSE_RESERVED_ODM[0x8]; + uint32_t _0xE8; + uint32_t _0xEC; + uint32_t FUSE_SKU_USB_CALIB; + uint32_t FUSE_SKU_DIRECT_CONFIG; + uint32_t _0xF8; + uint32_t _0xFC; + uint32_t FUSE_VENDOR_CODE; + uint32_t FUSE_FAB_CODE; + uint32_t FUSE_LOT_CODE_0; + uint32_t FUSE_LOT_CODE_1; + uint32_t FUSE_WAFER_ID; + uint32_t FUSE_X_COORDINATE; + uint32_t FUSE_Y_COORDINATE; + uint32_t _0x11C; + uint32_t _0x120; + uint32_t FUSE_SATA_CALIB; + uint32_t FUSE_GPU_IDDQ; + uint32_t FUSE_TSENSOR_3; + uint32_t _0x130; + uint32_t _0x134; + uint32_t _0x138; + uint32_t _0x13C; + uint32_t _0x140; + uint32_t _0x144; + uint32_t FUSE_OPT_SUBREVISION; + uint32_t _0x14C; + uint32_t _0x150; + uint32_t FUSE_TSENSOR_4; + uint32_t FUSE_TSENSOR_5; + uint32_t FUSE_TSENSOR_6; + uint32_t FUSE_TSENSOR_7; + uint32_t FUSE_OPT_PRIV_SEC_DIS; + uint32_t FUSE_PKC_DISABLE; + uint32_t _0x16C; + uint32_t _0x170; + uint32_t _0x174; + uint32_t _0x178; + uint32_t _0x17C; + uint32_t FUSE_TSENSOR_COMMON; + uint32_t _0x184; + uint32_t _0x188; + uint32_t _0x18C; + uint32_t _0x190; + uint32_t _0x194; + uint32_t _0x198; + uint32_t FUSE_DEBUG_AUTH_OVERRIDE; + uint32_t _0x1A0; + uint32_t _0x1A4; + uint32_t _0x1A8; + uint32_t _0x1AC; + uint32_t _0x1B0; + uint32_t _0x1B4; + uint32_t _0x1B8; + uint32_t _0x1BC; + uint32_t _0x1D0; + uint32_t FUSE_TSENSOR_8; + uint32_t _0x1D8; + uint32_t _0x1DC; + uint32_t _0x1E0; + uint32_t _0x1E4; + uint32_t _0x1E8; + uint32_t _0x1EC; + uint32_t _0x1F0; + uint32_t _0x1F4; + uint32_t _0x1F8; + uint32_t _0x1FC; + uint32_t _0x200; + uint32_t FUSE_RESERVED_CALIB; + uint32_t _0x208; + uint32_t _0x20C; + uint32_t _0x210; + uint32_t _0x214; + uint32_t _0x218; + uint32_t FUSE_TSENSOR_9; + uint32_t _0x220; + uint32_t _0x224; + uint32_t _0x228; + uint32_t _0x22C; + uint32_t _0x230; + uint32_t _0x234; + uint32_t _0x238; + uint32_t _0x23C; + uint32_t _0x240; + uint32_t _0x244; + uint32_t _0x248; + uint32_t _0x24C; + uint32_t FUSE_USB_CALIB_EXT; + uint32_t _0x254; + uint32_t _0x258; + uint32_t _0x25C; + uint32_t _0x260; + uint32_t _0x264; + uint32_t _0x268; + uint32_t _0x26C; + uint32_t _0x270; + uint32_t _0x274; + uint32_t _0x278; + uint32_t _0x27C; + uint32_t FUSE_SPARE_BIT[0x20]; +} tegra_fuse_chip_t; + +static inline volatile tegra_fuse_t *fuse_get_regs(void) { + return (volatile tegra_fuse_t *)FUSE_BASE; +} + +static inline volatile tegra_fuse_chip_t *fuse_chip_get_regs(void) { + return (volatile tegra_fuse_chip_t *)FUSE_CHIP_BASE; +} + +void fuse_init(void); + +uint32_t fuse_hw_read(uint32_t addr); +void fuse_hw_write(uint32_t value, uint32_t addr); +void fuse_hw_sense(void); +void fuse_disable_programming(void); +void fuse_secondary_private_key_disable(void); + +uint32_t fuse_get_sku_info(void); +uint32_t fuse_get_spare_bit(uint32_t idx); +uint32_t fuse_get_reserved_odm(uint32_t idx); + +uint32_t fuse_get_bootrom_patch_version(void); +uint64_t fuse_get_device_id(void); +uint32_t fuse_get_dram_id(void); +uint32_t fuse_get_hardware_type(void); +uint32_t fuse_get_retail_type(void); +void fuse_get_hardware_info(void *dst); + +#endif diff --git a/sept/sept-secondary/src/gpio.c b/sept/sept-secondary/src/gpio.c new file mode 100644 index 000000000..9cfec5c2f --- /dev/null +++ b/sept/sept-secondary/src/gpio.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stdint.h> +#include <errno.h> + +#include "gpio.h" +#include "utils.h" + +/** + * Returns a GPIO bank object that corresponds to the given GPIO pin, + * which can be created using the TEGRA_GPIO macro or passed from the name macro. + * + * @param pin The GPIO to get the bank for. + * @return The GPIO bank object to use for working with the given bank. + */ +static volatile tegra_gpio_bank_t *gpio_get_bank(uint32_t pin) +{ + volatile tegra_gpio_t *gpio = gpio_get_regs(); + uint32_t bank_number = pin >> GPIO_BANK_SHIFT; + + return &gpio->bank[bank_number]; +} + +/** + * @return the port number for working with the given GPIO. + */ +static volatile uint32_t gpio_get_port(uint32_t pin) +{ + return (pin >> GPIO_PORT_SHIFT) & GPIO_PORT_MASK; +} + +/** + * @return a mask to be used to work with the given GPIO + */ +static volatile uint32_t gpio_get_mask(uint32_t pin) +{ + uint32_t pin_number = pin & GPIO_PIN_MASK; + return (1 << pin_number); +} + +/** + * Performs a simple GPIO configuration operation. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param should_be_set True iff the relevant bit should be set; or false if it should be cleared. + * @param offset The offset into a gpio_bank structure + */ +static void gpio_simple_register_set(uint32_t pin, bool should_be_set, uint32_t offset) +{ + // Retrieve the register set that corresponds to the given pin and offset. + uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset; + uint32_t *cluster = (uint32_t *)cluster_addr; + + // Figure out the offset into the cluster, + // and the mask to be used. + uint32_t port = gpio_get_port(pin); + uint32_t mask = gpio_get_mask(pin); + + // Set or clear the bit, as appropriate. + if (should_be_set) + cluster[port] |= mask; + else + cluster[port] &= ~mask; +} + +/** + * Performs a simple GPIO configuration operation. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param should_be_set True iff the relevant bit should be set; or false if it should be cleared. + * @param offset The offset into a gpio_bank structure + */ +static bool gpio_simple_register_get(uint32_t pin, uint32_t offset) +{ + // Retrieve the register set that corresponds to the given pin and offset. + uintptr_t cluster_addr = (uintptr_t)gpio_get_bank(pin) + offset; + uint32_t *cluster = (uint32_t *)cluster_addr; + + // Figure out the offset into the cluster, + // and the mask to be used. + uint32_t port = gpio_get_port(pin); + uint32_t mask = gpio_get_mask(pin); + + // Convert the given value to a boolean. + return !!(cluster[port] & mask); +} + +/** + * Configures a given pin as either GPIO or SFIO. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param mode The relevant mode. + */ +void gpio_configure_mode(uint32_t pin, uint32_t mode) +{ + gpio_simple_register_set(pin, mode == GPIO_MODE_GPIO, offsetof(tegra_gpio_bank_t, config)); +} + +/** + * Configures a given pin as either INPUT or OUPUT. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param direction The relevant direction. + */ +void gpio_configure_direction(uint32_t pin, uint32_t dir) +{ + gpio_simple_register_set(pin, dir == GPIO_DIRECTION_OUTPUT, offsetof(tegra_gpio_bank_t, direction)); +} + +/** + * Drives a relevant GPIO pin as either HIGH or LOW. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param mode The relevant mode. + */ +void gpio_write(uint32_t pin, uint32_t value) +{ + gpio_simple_register_set(pin, value == GPIO_LEVEL_HIGH, offsetof(tegra_gpio_bank_t, out)); +} + +/** + * Drives a relevant GPIO pin as either HIGH or LOW. + * + * @param pin The GPIO pin to work with, as created with TEGRA_GPIO, or a named GPIO. + * @param mode The relevant mode. + */ +uint32_t gpio_read(uint32_t pin) +{ + return gpio_simple_register_get(pin, offsetof(tegra_gpio_bank_t, in)); +} diff --git a/sept/sept-secondary/src/gpio.h b/sept/sept-secondary/src/gpio.h new file mode 100644 index 000000000..41781a0ca --- /dev/null +++ b/sept/sept-secondary/src/gpio.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_GPIO_H +#define FUSEE_GPIO_H + +#include <stdint.h> + +#define GPIO_BASE 0x6000D000 +#define MAKE_GPIO_REG(n) MAKE_REG32(GPIO_BASE + n) + +#define TEGRA_GPIO_PORTS 4 +#define TEGRA_GPIO_BANKS 8 +#define GPIO_BANK_SHIFT 5 +#define GPIO_PORT_SHIFT 3 +#define GPIO_PORT_MASK 0x03 +#define GPIO_PIN_MASK 0x07 + +typedef enum { + TEGRA_GPIO_PORT_A = 0, + TEGRA_GPIO_PORT_B = 1, + TEGRA_GPIO_PORT_C = 2, + TEGRA_GPIO_PORT_D = 3, + TEGRA_GPIO_PORT_E = 4, + TEGRA_GPIO_PORT_F = 5, + TEGRA_GPIO_PORT_G = 6, + TEGRA_GPIO_PORT_H = 7, + TEGRA_GPIO_PORT_I = 8, + TEGRA_GPIO_PORT_J = 9, + TEGRA_GPIO_PORT_K = 10, + TEGRA_GPIO_PORT_L = 11, + TEGRA_GPIO_PORT_M = 12, + TEGRA_GPIO_PORT_N = 13, + TEGRA_GPIO_PORT_O = 14, + TEGRA_GPIO_PORT_P = 15, + TEGRA_GPIO_PORT_Q = 16, + TEGRA_GPIO_PORT_R = 17, + TEGRA_GPIO_PORT_S = 18, + TEGRA_GPIO_PORT_T = 19, + TEGRA_GPIO_PORT_U = 20, + TEGRA_GPIO_PORT_V = 21, + TEGRA_GPIO_PORT_W = 22, + TEGRA_GPIO_PORT_X = 23, + TEGRA_GPIO_PORT_Y = 24, + TEGRA_GPIO_PORT_Z = 25, + TEGRA_GPIO_PORT_AA = 26, + TEGRA_GPIO_PORT_BB = 27, + TEGRA_GPIO_PORT_CC = 28, + TEGRA_GPIO_PORT_DD = 29, + TEGRA_GPIO_PORT_EE = 30, + TEGRA_GPIO_PORT_FF = 31, +} tegra_gpio_port; + +typedef struct { + uint32_t config[TEGRA_GPIO_PORTS]; + uint32_t direction[TEGRA_GPIO_PORTS]; + uint32_t out[TEGRA_GPIO_PORTS]; + uint32_t in[TEGRA_GPIO_PORTS]; + uint32_t int_status[TEGRA_GPIO_PORTS]; + uint32_t int_enable[TEGRA_GPIO_PORTS]; + uint32_t int_level[TEGRA_GPIO_PORTS]; + uint32_t int_clear[TEGRA_GPIO_PORTS]; + uint32_t masked_config[TEGRA_GPIO_PORTS]; + uint32_t masked_dir_out[TEGRA_GPIO_PORTS]; + uint32_t masked_out[TEGRA_GPIO_PORTS]; + uint32_t masked_in[TEGRA_GPIO_PORTS]; + uint32_t masked_int_status[TEGRA_GPIO_PORTS]; + uint32_t masked_int_enable[TEGRA_GPIO_PORTS]; + uint32_t masked_int_level[TEGRA_GPIO_PORTS]; + uint32_t masked_int_clear[TEGRA_GPIO_PORTS]; +} tegra_gpio_bank_t; + +typedef struct { + tegra_gpio_bank_t bank[TEGRA_GPIO_BANKS]; +} tegra_gpio_t; + +static inline volatile tegra_gpio_t *gpio_get_regs(void) +{ + return (volatile tegra_gpio_t *)GPIO_BASE; +} + +#define TEGRA_GPIO(port, offset) \ + ((TEGRA_GPIO_PORT_##port * 8) + offset) + +/* Mode select */ +#define GPIO_MODE_GPIO 0 +#define GPIO_MODE_SFIO 1 + +/* Direction */ +#define GPIO_DIRECTION_INPUT 0 +#define GPIO_DIRECTION_OUTPUT 1 + +/* Level */ +#define GPIO_LEVEL_LOW 0 +#define GPIO_LEVEL_HIGH 1 + +/* Named GPIOs */ +#define GPIO_BUTTON_VOL_DOWN TEGRA_GPIO(X, 7) +#define GPIO_BUTTON_VOL_UP TEGRA_GPIO(X, 6) +#define GPIO_MICROSD_CARD_DETECT TEGRA_GPIO(Z, 1) +#define GPIO_MICROSD_WRITE_PROTECT TEGRA_GPIO(Z, 4) +#define GPIO_MICROSD_SUPPLY_ENABLE TEGRA_GPIO(E, 4) +#define GPIO_LCD_BL_P5V TEGRA_GPIO(I, 0) +#define GPIO_LCD_BL_N5V TEGRA_GPIO(I, 1) +#define GPIO_LCD_BL_PWM TEGRA_GPIO(V, 0) +#define GPIO_LCD_BL_EN TEGRA_GPIO(V, 1) +#define GPIO_LCD_BL_RST TEGRA_GPIO(V, 2) + +void gpio_configure_mode(uint32_t pin, uint32_t mode); +void gpio_configure_direction(uint32_t pin, uint32_t dir); +void gpio_write(uint32_t pin, uint32_t value); +uint32_t gpio_read(uint32_t pin); + +#endif diff --git a/sept/sept-secondary/src/hwinit.c b/sept/sept-secondary/src/hwinit.c new file mode 100644 index 000000000..f959754de --- /dev/null +++ b/sept/sept-secondary/src/hwinit.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "hwinit.h" +#include "apb_misc.h" +#include "car.h" +#include "di.h" +#include "fuse.h" +#include "gpio.h" +#include "i2c.h" +#include "max77620.h" +#include "mc.h" +#include "pinmux.h" +#include "pmc.h" +#include "se.h" +#include "sdram.h" +#include "sysctr0.h" +#include "sysreg.h" +#include "timers.h" +#include "uart.h" + +void config_oscillators() +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + car->spare_reg0 = ((car->spare_reg0 & 0xFFFFFFF3) | 4); + + SYSCTR0_CNTFID0_0 = 19200000; + TIMERUS_USEC_CFG_0 = 0x45F; + + car->osc_ctrl = 0x50000071; + pmc->osc_edpd_over = ((pmc->osc_edpd_over & 0xFFFFFF81) | 0xE); + pmc->osc_edpd_over = ((pmc->osc_edpd_over & 0xFFBFFFFF) | 0x400000); + pmc->cntrl2 = ((pmc->cntrl2 & 0xFFFFEFFF) | 0x1000); + pmc->scratch188 = ((pmc->scratch188 & 0xFCFFFFFF) | 0x2000000); + car->clk_sys_rate = 0x10; + car->pllmb_base &= 0xBFFFFFFF; + pmc->tsc_mult = ((pmc->tsc_mult & 0xFFFF0000) | 0x249F); /* 0x249F = 19200000 * (16 / 32.768 kHz) */ + car->sclk_brst_pol = 0x20004444; + car->super_sclk_div = 0x80000000; + car->clk_sys_rate = 2; +} + +void config_gpios() +{ + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + + pinmux->uart2_tx = 0; + pinmux->uart3_tx = 0; + pinmux->pe6 = PINMUX_INPUT; + pinmux->ph6 = PINMUX_INPUT; + + gpio_configure_mode(TEGRA_GPIO(G, 0), GPIO_MODE_GPIO); + gpio_configure_mode(TEGRA_GPIO(D, 1), GPIO_MODE_GPIO); + gpio_configure_mode(TEGRA_GPIO(E, 6), GPIO_MODE_GPIO); + gpio_configure_mode(TEGRA_GPIO(H, 6), GPIO_MODE_GPIO); + gpio_configure_direction(TEGRA_GPIO(G, 0), GPIO_DIRECTION_INPUT); + gpio_configure_direction(TEGRA_GPIO(D, 1), GPIO_DIRECTION_INPUT); + gpio_configure_direction(TEGRA_GPIO(E, 6), GPIO_DIRECTION_INPUT); + gpio_configure_direction(TEGRA_GPIO(H, 6), GPIO_DIRECTION_INPUT); + + pinmux->gen1_i2c_scl = PINMUX_INPUT; + pinmux->gen1_i2c_sda = PINMUX_INPUT; + pinmux->pwr_i2c_scl = PINMUX_INPUT; + pinmux->pwr_i2c_sda = PINMUX_INPUT; + pinmux->uart1_rx = 0; + pinmux->uart1_tx = (PINMUX_INPUT | PINMUX_PULL_UP); + pinmux->uart1_rts = 0; + pinmux->uart1_cts = (PINMUX_INPUT | PINMUX_PULL_DOWN); + + /* Configure volume up/down as inputs. */ + gpio_configure_mode(GPIO_BUTTON_VOL_UP, GPIO_MODE_GPIO); + gpio_configure_mode(GPIO_BUTTON_VOL_DOWN, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_BUTTON_VOL_UP, GPIO_DIRECTION_INPUT); + gpio_configure_direction(GPIO_BUTTON_VOL_DOWN, GPIO_DIRECTION_INPUT); +} + +void config_pmc_scratch() +{ + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + pmc->scratch20 &= 0xFFF3FFFF; + pmc->scratch190 &= 0xFFFFFFFE; + pmc->secure_scratch21 |= 0x10; +} + +void mbist_workaround() +{ + volatile tegra_car_t *car = car_get_regs(); + + car->clk_source_sor1 = ((car->clk_source_sor1 | 0x8000) & 0xFFFFBFFF); + car->plld_base |= 0x40800000u; + car->rst_dev_y_clr = 0x40; + car->rst_dev_x_clr = 0x40000; + car->rst_dev_l_clr = 0x18000000; + udelay(2); + + /* Setup I2S. */ + MAKE_I2S_REG(0x0A0) |= 0x400; + MAKE_I2S_REG(0x088) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x1A0) |= 0x400; + MAKE_I2S_REG(0x188) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x2A0) |= 0x400; + MAKE_I2S_REG(0x288) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x3A0) |= 0x400; + MAKE_I2S_REG(0x388) &= 0xFFFFFFFE; + MAKE_I2S_REG(0x4A0) |= 0x400; + MAKE_I2S_REG(0x488) &= 0xFFFFFFFE; + + MAKE_DI_REG(DC_COM_DSC_TOP_CTL) |= 4; + MAKE_VIC_REG(0x8C) = 0xFFFFFFFF; + udelay(2); + + /* Set devices in reset. */ + car->rst_dev_y_set = 0x40; + car->rst_dev_l_set = 0x18000000; + car->rst_dev_x_set = 0x40000; + + /* Clock out enables. */ + car->clk_out_enb_h = 0xC0; + car->clk_out_enb_l = 0x80000130; + car->clk_out_enb_u = 0x1F00200; + car->clk_out_enb_v = 0x80400808; + car->clk_out_enb_w = 0x402000FC; + car->clk_out_enb_x = 0x23000780; + car->clk_out_enb_y = 0x300; + + /* LVL2 clock gate overrides. */ + car->lvl2_clk_gate_ovra = 0; + car->lvl2_clk_gate_ovrb = 0; + car->lvl2_clk_gate_ovrc = 0; + car->lvl2_clk_gate_ovrd = 0; + car->lvl2_clk_gate_ovre = 0; + + /* Configure clock sources. */ + car->plld_base &= 0x1F7FFFFF; + car->clk_source_sor1 &= 0xFFFF3FFF; + car->clk_source_vi = ((car->clk_source_vi & 0x1FFFFFFF) | 0x80000000); + car->clk_source_host1x = ((car->clk_source_host1x & 0x1FFFFFFF) | 0x80000000); + car->clk_source_nvenc = ((car->clk_source_nvenc & 0x1FFFFFFF) | 0x80000000); +} + +void config_se_brom() +{ + volatile tegra_fuse_chip_t *fuse_chip = fuse_chip_get_regs(); + volatile tegra_se_t *se = se_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* Bootrom part we skipped. */ + uint32_t sbk[4] = {fuse_chip->FUSE_PRIVATE_KEY[0], fuse_chip->FUSE_PRIVATE_KEY[1], fuse_chip->FUSE_PRIVATE_KEY[2], fuse_chip->FUSE_PRIVATE_KEY[3]}; + set_aes_keyslot(0xE, sbk, 0x10); + + /* Lock SBK from being read. */ + se->AES_KEYSLOT_FLAGS[0xE] = 0x7E; + + /* This memset needs to happen here, else TZRAM will behave weirdly later on. */ + memset((void *)0x7C010000, 0, 0x10000); + + pmc->crypto_op = 0; + se->INT_STATUS_REG = 0x1F; + + /* Lock SSK (although it's not set and unused anyways). */ + se->AES_KEYSLOT_FLAGS[0xF] = 0x7E; + + /* Clear the boot reason to avoid problems later */ + pmc->scratch200 = 0; + pmc->reset_status = 0; +} + +void nx_hwinit() +{ + volatile tegra_car_t *car = car_get_regs(); + + /* This stuff was handled by whatever loaded us. */ + /* + config_se_brom(); + + AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; + pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); + + mbist_workaround(); + + clkrst_reboot(CARDEVICE_SE); + + fuse_init(); + + mc_enable(); + + config_oscillators(); + */ + + /* Disable pinmux tristate input clamping. */ + APB_MISC_PP_PINMUX_GLOBAL_0 = 0; + + /* Configure GPIOs. */ + /* NOTE: [3.0.0+] Part of the GPIO configuration is skipped if the unit is SDEV. */ + /* NOTE: [6.0.0+] The GPIO configuration's order was changed a bit. */ + config_gpios(); + + /* Uncomment for UART debugging. */ + /* + clkrst_reboot(CARDEVICE_UARTC); + uart_init(UART_C, 115200); + */ + + /* Reboot CL-DVFS. */ + clkrst_reboot(CARDEVICE_CL_DVFS); + + /* Reboot I2C1. */ + clkrst_reboot(CARDEVICE_I2C1); + + /* Reboot I2C5. */ + clkrst_reboot(CARDEVICE_I2C5); + + /* Reboot SE. */ + /* NOTE: [4.0.0+] This was removed. */ + /* clkrst_reboot(CARDEVICE_SE); */ + + /* Reboot unknown device. */ + clkrst_reboot(CARDEVICE_UNK); + + /* Initialize I2C1. */ + /* NOTE: [6.0.0+] This was moved to after the PMIC is configured. */ + i2c_init(I2C_1); + + /* Initialize I2C5. */ + i2c_init(I2C_5); + + /* Configure the PMIC. */ + uint8_t val = 0x40; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGBBC, &val, 1); + val = 0x60; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, &val, 1); + val = 0x38; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG0, &val, 1); + val = 0x3A; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG1, &val, 1); + val = 0x38; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_CFG2, &val, 1); + val = 0xF; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO4, &val, 1); + val = 0xC7; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_LDO8, &val, 1); + val = 0x4F; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD0, &val, 1); + val = 0x29; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD1, &val, 1); + val = 0x1B; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_SD3, &val, 1); + + /* NOTE: [3.0.0+] This was added. */ + val = 0x22; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_FPS_GPIO3, &val, 1); + + /* TODO: In 3.x+, if the unit is SDEV, the MBLPD bit is set. */ + /* + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); + val |= 0x40; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); + */ + + /* Configure SD0 voltage. */ + val = 42; /* 42 = (1125000 - 600000) / 12500 -> 1.125V */ + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD0, &val, 1); + + /* Configure and lock PMC scratch registers. */ + /* NOTE: [4.0.0+] This was removed. */ + config_pmc_scratch(); + + /* Set super clock burst policy. */ + car->sclk_brst_pol = ((car->sclk_brst_pol & 0xFFFF8888) | 0x3333); + + /* Configure memory controller carveouts. */ + /* NOTE: [4.0.0+] This is now done in the Secure Monitor. */ + /* mc_config_carveout(); */ + + /* Initialize SDRAM. */ + sdram_init(); + + /* Save SDRAM LP0 parameters. */ + sdram_lp0_save_params(sdram_get_params()); +} \ No newline at end of file diff --git a/sept/sept-secondary/src/hwinit.h b/sept/sept-secondary/src/hwinit.h new file mode 100644 index 000000000..d76512ef3 --- /dev/null +++ b/sept/sept-secondary/src/hwinit.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_HWINIT_H_ +#define FUSEE_HWINIT_H_ + +#define I2S_BASE 0x702D1000 +#define MAKE_I2S_REG(n) MAKE_REG32(I2S_BASE + n) + +void nx_hwinit(); + +#endif diff --git a/sept/sept-secondary/src/i2c.c b/sept/sept-secondary/src/i2c.c new file mode 100644 index 000000000..aec946cf2 --- /dev/null +++ b/sept/sept-secondary/src/i2c.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "i2c.h" +#include "utils.h" +#include "timers.h" + +/* Prototypes for internal commands. */ +volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id); +void i2c_load_config(volatile tegra_i2c_t *regs); + +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size); +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size); + +bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size); +bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size); + +/* Initialize I2C based on registers. */ +void i2c_init(unsigned int id) { + volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); + + /* Setup divisor, and clear the bus. */ + regs->I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; + regs->I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; + + /* Load hardware configuration. */ + i2c_load_config(regs); + + /* Wait a while until BUS_CLEAR_DONE is set. */ + for (unsigned int i = 0; i < 10; i++) { + udelay(20000); + if (regs->I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { + break; + } + } + + /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ + regs->I2C_I2C_BUS_CLEAR_STATUS_0; + + /* Read and set the Interrupt Status. */ + uint32_t int_status = regs->I2C_INTERRUPT_STATUS_REGISTER_0; + regs->I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; +} + +/* Sets a bit in a PMIC register over I2C during CPU shutdown. */ +void i2c_send_pmic_cpu_shutdown_cmd(void) { + uint32_t val = 0; + /* PMIC == Device 4:3C. */ + i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); + val |= 4; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, 0x41, &val, 1); +} + +/* Queries the value of TI charger bit over I2C. */ +bool i2c_query_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); + return (val & 0x80) != 0; +} + +/* Clears TI charger bit over I2C. */ +void i2c_clear_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); + val &= 0x7F; + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); +} + +/* Sets TI charger bit over I2C. */ +void i2c_set_ti_charger_bit_7(void) { + uint32_t val = 0; + /* TI Charger = Device 0:6B. */ + i2c_query(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); + val |= 0x80; + i2c_send(I2C_1, BQ24193_I2C_ADDR, 0, &val, 1); +} + +/* Get registers pointer based on I2C ID. */ +volatile tegra_i2c_t *i2c_get_registers_from_id(unsigned int id) { + switch (id) { + case I2C_1: + return I2C1_REGS; + case I2C_2: + return I2C2_REGS; + case I2C_3: + return I2C3_REGS; + case I2C_4: + return I2C4_REGS; + case I2C_5: + return I2C5_REGS; + case I2C_6: + return I2C6_REGS; + default: + generic_panic(); + } + return NULL; +} + +/* Load hardware config for I2C4. */ +void i2c_load_config(volatile tegra_i2c_t *regs) { + /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ + regs->I2C_I2C_CONFIG_LOAD_0 = 0x25; + + /* Wait a bit for master config to be loaded. */ + for (unsigned int i = 0; i < 20; i++) { + udelay(1); + if (!(regs->I2C_I2C_CONFIG_LOAD_0 & 1)) { + break; + } + } +} + +/* Reads a register from a device over I2C, writes result to output. */ +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size) { + volatile tegra_i2c_t *regs = i2c_get_registers_from_id(id); + uint32_t val = r; + + /* Write single byte register ID to device. */ + if (!i2c_write(regs, device, &val, 1)) { + return false; + } + /* Limit output size to 32-bits. */ + if (dst_size > 4) { + return false; + } + + return i2c_read(regs, device, dst, dst_size); +} + +/* Writes a value to a register over I2C. */ +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size) { + uint32_t val = r; + if (src_size == 0) { + return true; + } else if (src_size <= 3) { + memcpy(((uint8_t *)&val) + 1, src, src_size); + return i2c_write(i2c_get_registers_from_id(id), device, &val, src_size + 1); + } else { + return false; + } +} + +/* Writes bytes to device over I2C. */ +bool i2c_write(volatile tegra_i2c_t *regs, uint8_t device, void *src, size_t src_size) { + if (src_size > 4) { + return false; + } else if (src_size == 0) { + return true; + } + + /* Set device for 7-bit write mode. */ + regs->I2C_I2C_CMD_ADDR0_0 = device << 1; + + /* Load in data to write. */ + regs->I2C_I2C_CMD_DATA1_0 = read32le(src, 0); + + /* Set config with LENGTH = src_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + regs->I2C_I2C_CNFG_0 = ((src_size << 1) - 2) | 0x2800; + + i2c_load_config(regs); + + /* Config |= SEND; */ + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); + + while (regs->I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ + return (regs->I2C_I2C_STATUS_0 & 0xF) == 0; +} + +/* Reads bytes from device over I2C. */ +bool i2c_read(volatile tegra_i2c_t *regs, uint8_t device, void *dst, size_t dst_size) { + if (dst_size > 4) { + return false; + } else if (dst_size == 0) { + return true; + } + + /* Set device for 7-bit read mode. */ + regs->I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1; + + /* Set config with LENGTH = dst_size, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + regs->I2C_I2C_CNFG_0 = ((dst_size << 1) - 2) | 0x2840; + + i2c_load_config(regs); + + /* Config |= SEND; */ + regs->I2C_I2C_CNFG_0 = ((regs->I2C_I2C_CNFG_0 & 0xFFFFFDFF) | 0x200); + + while (regs->I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Ensure success. */ + if ((regs->I2C_I2C_STATUS_0 & 0xF) != 0) { + return false; + } + + uint32_t val = regs->I2C_I2C_CMD_DATA1_0; + memcpy(dst, &val, dst_size); + return true; +} diff --git a/sept/sept-secondary/src/i2c.h b/sept/sept-secondary/src/i2c.h new file mode 100644 index 000000000..9399b0024 --- /dev/null +++ b/sept/sept-secondary/src/i2c.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_I2C_H +#define FUSEE_I2C_H + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#define I2C1234_BASE 0x7000C000 +#define I2C56_BASE 0x7000D000 + +#define I2C_1 0 +#define I2C_2 1 +#define I2C_3 2 +#define I2C_4 3 +#define I2C_5 4 +#define I2C_6 5 + +#define MAX77621_CPU_I2C_ADDR 0x1B +#define MAX77621_GPU_I2C_ADDR 0x1C +#define MAX17050_I2C_ADDR 0x36 +#define MAX77620_PWR_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 +#define BQ24193_I2C_ADDR 0x6B + +typedef struct { + uint32_t I2C_I2C_CNFG_0; + uint32_t I2C_I2C_CMD_ADDR0_0; + uint32_t I2C_I2C_CMD_ADDR1_0; + uint32_t I2C_I2C_CMD_DATA1_0; + uint32_t I2C_I2C_CMD_DATA2_0; + uint32_t _0x14; + uint32_t _0x18; + uint32_t I2C_I2C_STATUS_0; + uint32_t I2C_I2C_SL_CNFG_0; + uint32_t I2C_I2C_SL_RCVD_0; + uint32_t I2C_I2C_SL_STATUS_0; + uint32_t I2C_I2C_SL_ADDR1_0; + uint32_t I2C_I2C_SL_ADDR2_0; + uint32_t I2C_I2C_TLOW_SEXT_0; + uint32_t _0x38; + uint32_t I2C_I2C_SL_DELAY_COUNT_0; + uint32_t I2C_I2C_SL_INT_MASK_0; + uint32_t I2C_I2C_SL_INT_SOURCE_0; + uint32_t I2C_I2C_SL_INT_SET_0; + uint32_t _0x4C; + uint32_t I2C_I2C_TX_PACKET_FIFO_0; + uint32_t I2C_I2C_RX_FIFO_0; + uint32_t I2C_PACKET_TRANSFER_STATUS_0; + uint32_t I2C_FIFO_CONTROL_0; + uint32_t I2C_FIFO_STATUS_0; + uint32_t I2C_INTERRUPT_MASK_REGISTER_0; + uint32_t I2C_INTERRUPT_STATUS_REGISTER_0; + uint32_t I2C_I2C_CLK_DIVISOR_REGISTER_0; + uint32_t I2C_I2C_INTERRUPT_SOURCE_REGISTER_0; + uint32_t I2C_I2C_INTERRUPT_SET_REGISTER_0; + uint32_t I2C_I2C_SLV_TX_PACKET_FIFO_0; + uint32_t I2C_I2C_SLV_RX_FIFO_0; + uint32_t I2C_I2C_SLV_PACKET_STATUS_0; + uint32_t I2C_I2C_BUS_CLEAR_CONFIG_0; + uint32_t I2C_I2C_BUS_CLEAR_STATUS_0; + uint32_t I2C_I2C_CONFIG_LOAD_0; + uint32_t _0x90; + uint32_t I2C_I2C_INTERFACE_TIMING_0_0; + uint32_t I2C_I2C_INTERFACE_TIMING_1_0; + uint32_t I2C_I2C_HS_INTERFACE_TIMING_0_0; + uint32_t I2C_I2C_HS_INTERFACE_TIMING_1_0; +} tegra_i2c_t; + +#define I2C1_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x000)) +#define I2C2_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x400)) +#define I2C3_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x500)) +#define I2C4_REGS ((volatile tegra_i2c_t *)(I2C1234_BASE + 0x700)) +#define I2C5_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x000)) +#define I2C6_REGS ((volatile tegra_i2c_t *)(I2C56_BASE + 0x100)) + +void i2c_init(unsigned int id); +bool i2c_query(unsigned int id, uint8_t device, uint8_t r, void *dst, size_t dst_size); +bool i2c_send(unsigned int id, uint8_t device, uint8_t r, void *src, size_t src_size); + +void i2c_send_pmic_cpu_shutdown_cmd(void); +bool i2c_query_ti_charger_bit_7(void); +void i2c_clear_ti_charger_bit_7(void); +void i2c_set_ti_charger_bit_7(void); + +#endif diff --git a/sept/sept-secondary/src/init.c b/sept/sept-secondary/src/init.c new file mode 100644 index 000000000..c061fc00c --- /dev/null +++ b/sept/sept-secondary/src/init.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <stddef.h> +#include <string.h> +#include <malloc.h> +#include <sys/iosupport.h> +#include "utils.h" + +void __libc_init_array(void); +void __libc_fini_array(void); + +extern uint8_t __bss_start__[], __bss_end__[]; +extern uint8_t __heap_start__[], __heap_end__[]; + +extern char *fake_heap_start; +extern char *fake_heap_end; + +int __program_argc; +void **__program_argv; + +void __attribute__((noreturn)) __program_exit(int rc); +void __attribute__((noreturn)) (*__program_exit_callback)(int rc) = NULL; + +static void __program_parse_argc_argv(int argc, char *argdata); +static void __program_cleanup_argv(void); + +static void __program_init_heap(void) { + fake_heap_start = (char*)__heap_start__; + fake_heap_end = (char*)__heap_end__; +} + +static void __program_init_newlib_hooks(void) { + __syscalls.exit = __program_exit; /* For exit, etc. */ +} + +static void __program_move_additional_sections(void) { +#if defined(FUSEE_STAGE1_SRC) || defined(FUSEE_STAGE2_SRC) + extern uint8_t __chainloader_lma__[], __chainloader_start__[], __chainloader_bss_start__[], __chainloader_end__[]; + memcpy(__chainloader_start__, __chainloader_lma__, __chainloader_bss_start__ - __chainloader_start__); + memset(__chainloader_bss_start__, 0, __chainloader_end__ - __chainloader_bss_start__); +#endif +} + +void __program_init(int argc, char *argdata) { + /* Zero-fill the .bss section */ + memset(__bss_start__, 0, __bss_end__ - __bss_start__); + + __program_init_heap(); + __program_init_newlib_hooks(); + __program_parse_argc_argv(argc, argdata); + + /* Once argv is parsed, we can discard the low IRAM region */ + __program_move_additional_sections(); + __libc_init_array(); +} + +void __program_exit(int rc) { + __libc_fini_array(); + __program_cleanup_argv(); + if (__program_exit_callback == NULL) { + /* Default callback */ + generic_panic(); + } else { + __program_exit_callback(rc); + } + for (;;); +} + +#ifdef FUSEE_STAGE1_SRC +static void __program_parse_argc_argv(int argc, char *argdata) { + __program_argc = 0; + __program_argv = NULL; +} +#elif defined(FUSEE_STAGE2_SRC) +#include "stage2.h" +static void __program_parse_argc_argv(int argc, char *argdata) { + size_t pos = 0, len; + + __program_argc = argc; + + __program_argv = malloc(argc * sizeof(void **)); + if (__program_argv == NULL) { + generic_panic(); + } + + len = strlen(argdata); + __program_argv[0] = malloc(len + 1); + if (__program_argv[0] == NULL) { + generic_panic(); + } + strcpy((char *)__program_argv[0], argdata); + pos += len + 1; + + __program_argv[1] = malloc(sizeof(stage2_args_t)); + if (__program_argv[1] == NULL) { + generic_panic(); + } + memcpy(__program_argv[1], argdata + pos, sizeof(stage2_args_t)); +} +#else +static void __program_parse_argc_argv(int argc, char *argdata) { + size_t pos = 0, len; + + __program_argc = argc; + + __program_argv = malloc(argc * sizeof(void **)); + if (__program_argv == NULL) { + generic_panic(); + } + + for (int i = 0; i < argc; i++) { + len = strlen(argdata + pos); + __program_argv[i] = malloc(len + 1); + if (__program_argv[i] == NULL) { + generic_panic(); + } + strcpy((char *)__program_argv[i], argdata + pos); + pos += len + 1; + } +} +#endif + +static void __program_cleanup_argv(void) { +#ifndef FUSEE_STAGE1_SRC + for (int i = 0; i < __program_argc; i++) { + free(__program_argv[i]); + __program_argv[i] = NULL; + } + free(__program_argv); +#endif +} diff --git a/sept/sept-secondary/src/lib/fatfs/00history.txt b/sept/sept-secondary/src/lib/fatfs/00history.txt new file mode 100644 index 000000000..9b67d02a1 --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/00history.txt @@ -0,0 +1,324 @@ +---------------------------------------------------------------------------- + Revision history of FatFs module +---------------------------------------------------------------------------- + +R0.00 (February 26, 2006) + + Prototype. + + + +R0.01 (April 29, 2006) + + The first release. + + + +R0.02 (June 01, 2006) + + Added FAT12 support. + Removed unbuffered mode. + Fixed a problem on small (<32M) partition. + + + +R0.02a (June 10, 2006) + + Added a configuration option (_FS_MINIMUM). + + + +R0.03 (September 22, 2006) + + Added f_rename(). + Changed option _FS_MINIMUM to _FS_MINIMIZE. + + + +R0.03a (December 11, 2006) + + Improved cluster scan algorithm to write files fast. + Fixed f_mkdir() creates incorrect directory on FAT32. + + + +R0.04 (February 04, 2007) + + Added f_mkfs(). + Supported multiple drive system. + Changed some interfaces for multiple drive system. + Changed f_mountdrv() to f_mount(). + + + +R0.04a (April 01, 2007) + + Supported multiple partitions on a physical drive. + Added a capability of extending file size to f_lseek(). + Added minimization level 3. + Fixed an endian sensitive code in f_mkfs(). + + + +R0.04b (May 05, 2007) + + Added a configuration option _USE_NTFLAG. + Added FSINFO support. + Fixed DBCS name can result FR_INVALID_NAME. + Fixed short seek (<= csize) collapses the file object. + + + +R0.05 (August 25, 2007) + + Changed arguments of f_read(), f_write() and f_mkfs(). + Fixed f_mkfs() on FAT32 creates incorrect FSINFO. + Fixed f_mkdir() on FAT32 creates incorrect directory. + + + +R0.05a (February 03, 2008) + + Added f_truncate() and f_utime(). + Fixed off by one error at FAT sub-type determination. + Fixed btr in f_read() can be mistruncated. + Fixed cached sector is not flushed when create and close without write. + + + +R0.06 (April 01, 2008) + + Added fputc(), fputs(), fprintf() and fgets(). + Improved performance of f_lseek() on moving to the same or following cluster. + + + +R0.07 (April 01, 2009) + + Merged Tiny-FatFs as a configuration option. (_FS_TINY) + Added long file name feature. (_USE_LFN) + Added multiple code page feature. (_CODE_PAGE) + Added re-entrancy for multitask operation. (_FS_REENTRANT) + Added auto cluster size selection to f_mkfs(). + Added rewind option to f_readdir(). + Changed result code of critical errors. + Renamed string functions to avoid name collision. + + + +R0.07a (April 14, 2009) + + Septemberarated out OS dependent code on reentrant cfg. + Added multiple sector size feature. + + + +R0.07c (June 21, 2009) + + Fixed f_unlink() can return FR_OK on error. + Fixed wrong cache control in f_lseek(). + Added relative path feature. + Added f_chdir() and f_chdrive(). + Added proper case conversion to extended character. + + + +R0.07e (November 03, 2009) + + Septemberarated out configuration options from ff.h to ffconf.h. + Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH. + Fixed name matching error on the 13 character boundary. + Added a configuration option, _LFN_UNICODE. + Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. + + + +R0.08 (May 15, 2010) + + Added a memory configuration option. (_USE_LFN = 3) + Added file lock feature. (_FS_SHARE) + Added fast seek feature. (_USE_FASTSEEK) + Changed some types on the API, XCHAR->TCHAR. + Changed .fname in the FILINFO structure on Unicode cfg. + String functions support UTF-8 encoding files on Unicode cfg. + + + +R0.08a (August 16, 2010) + + Added f_getcwd(). (_FS_RPATH = 2) + Added sector erase feature. (_USE_ERASE) + Moved file lock semaphore table from fs object to the bss. + Fixed f_mkfs() creates wrong FAT32 volume. + + + +R0.08b (January 15, 2011) + + Fast seek feature is also applied to f_read() and f_write(). + f_lseek() reports required table size on creating CLMP. + Extended format syntax of f_printf(). + Ignores duplicated directory separators in given path name. + + + +R0.09 (September 06, 2011) + + f_mkfs() supports multiple partition to complete the multiple partition feature. + Added f_fdisk(). + + + +R0.09a (August 27, 2012) + + Changed f_open() and f_opendir() reject null object pointer to avoid crash. + Changed option name _FS_SHARE to _FS_LOCK. + Fixed assertion failure due to OS/2 EA on FAT12/16 volume. + + + +R0.09b (January 24, 2013) + + Added f_setlabel() and f_getlabel(). + + + +R0.10 (October 02, 2013) + + Added selection of character encoding on the file. (_STRF_ENCODE) + Added f_closedir(). + Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO) + Added forced mount feature with changes of f_mount(). + Improved behavior of volume auto detection. + Improved write throughput of f_puts() and f_printf(). + Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write(). + Fixed f_write() can be truncated when the file size is close to 4GB. + Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error. + + + +R0.10a (January 15, 2014) + + Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID) + Added a configuration option of minimum sector size. (_MIN_SS) + 2nd argument of f_rename() can have a drive number and it will be ignored. + Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10) + Fixed f_close() invalidates the file object without volume lock. + Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10) + Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07) + + + +R0.10b (May 19, 2014) + + Fixed a hard error in the disk I/O layer can collapse the directory entry. + Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07) + + + +R0.10c (November 09, 2014) + + Added a configuration option for the platforms without RTC. (_FS_NORTC) + Changed option name _USE_ERASE to _USE_TRIM. + Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b) + Fixed a potential problem of FAT access that can appear on disk error. + Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08) + + + +R0.11 (February 09, 2015) + + Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND) + Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c) + Fixed _FS_NORTC option does not work properly. (appeared at R0.10c) + + + +R0.11a (September 05, 2015) + + Fixed wrong media change can lead a deadlock at thread-safe configuration. + Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE) + Removed some code pages actually not exist on the standard systems. (_CODE_PAGE) + Fixed errors in the case conversion teble of code page 437 and 850 (ff.c). + Fixed errors in the case conversion teble of Unicode (cc*.c). + + + +R0.12 (April 12, 2016) + + Added support for exFAT file system. (_FS_EXFAT) + Added f_expand(). (_USE_EXPAND) + Changed some members in FINFO structure and behavior of f_readdir(). + Added an option _USE_CHMOD. + Removed an option _WORD_ACCESS. + Fixed errors in the case conversion table of Unicode (cc*.c). + + + +R0.12a (July 10, 2016) + + Added support for creating exFAT volume with some changes of f_mkfs(). + Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed. + f_forward() is available regardless of _FS_TINY. + Fixed f_mkfs() creates wrong volume. (appeared at R0.12) + Fixed wrong memory read in create_name(). (appeared at R0.12) + Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD. + + + +R0.12b (September 04, 2016) + + Made f_rename() be able to rename objects with the same name but case. + Fixed an error in the case conversion teble of code page 866. (ff.c) + Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12) + Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12) + Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12) + Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12) + Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12) + Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12) + + + +R0.12c (March 04, 2017) + + Improved write throughput at the fragmented file on the exFAT volume. + Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN. + Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12) + Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c) + + + +R0.13 (May 21, 2017) + + Changed heading character of configuration keywords "_" to "FF_". + Removed ASCII-only configuration, FF_CODE_PAGE = 1. Use FF_CODE_PAGE = 437 instead. + Added f_setcp(), run-time code page configuration. (FF_CODE_PAGE = 0) + Improved cluster allocation time on stretch a deep buried cluster chain. + Improved processing time of f_mkdir() with large cluster size by using FF_USE_LFN = 3. + Improved NoFatChain flag of the fragmented file to be set after it is truncated and got contiguous. + Fixed archive attribute is left not set when a file on the exFAT volume is renamed. (appeared at R0.12) + Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c) + Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c) + + + +R0.13a (October 14, 2017) + + Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2) + Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF). + Added dynamic memory allocation option for working buffer of f_mkfs() and f_fdisk(). + Fixed f_fdisk() and f_mkfs() create the partition table with wrong CHS parameters. (appeared at R0.09) + Fixed f_unlink() can cause lost clusters at fragmented file on the exFAT volume. (appeared at R0.12c) + Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12) + + + +R0.13b (April 07, 2018) + + Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3) + Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2) + Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c) + Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b) + + + diff --git a/sept/sept-secondary/src/lib/fatfs/00readme.txt b/sept/sept-secondary/src/lib/fatfs/00readme.txt new file mode 100644 index 000000000..15426d2e2 --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/00readme.txt @@ -0,0 +1,22 @@ +FatFs Module Source Files R0.13b + + +FILES + + 00readme.txt This file. + 00history.txt Revision history. + ff.c FatFs module. + ffconf.h Configuration file of FatFs module. + ff.h Common include file for FatFs and application module. + diskio.h Common include file for FatFs and disk I/O module. + diskio.c An example of glue function to attach existing disk I/O module to FatFs. + integer.h Integer type definitions for FatFs. + ffunicode.c Optional Unicode utility functions. + ffsystem.c An example of optional O/S related functions. + + + Low level disk I/O module is not included in this archive because the FatFs + module is only a generic file system layer and it does not depend on any specific + storage device. You need to provide a low level disk I/O module written to + control the storage device that attached to the target system. + diff --git a/sept/sept-secondary/src/lib/fatfs/diskio.c b/sept/sept-secondary/src/lib/fatfs/diskio.c new file mode 100644 index 000000000..c2840973b --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/diskio.c @@ -0,0 +1,95 @@ +/*-----------------------------------------------------------------------*/ +/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ +/*-----------------------------------------------------------------------*/ +/* If a working storage control module is available, it should be */ +/* attached to the FatFs via a glue function rather than modifying it. */ +/* This is an example of glue functions to attach various exsisting */ +/* storage control modules to the FatFs module with a defined API. */ +/*-----------------------------------------------------------------------*/ + +#include <stdbool.h> +#include <string.h> +#include "diskio.h" /* FatFs lower layer API */ +#include "../../fs_utils.h" + +/*-----------------------------------------------------------------------*/ +/* Get Drive Status */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_status ( + BYTE pdrv /* Physical drive nmuber to identify the drive */ +) +{ + return 0; +} + + + +/*-----------------------------------------------------------------------*/ +/* Inidialize a Drive */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_initialize ( + BYTE pdrv /* Physical drive nmuber to identify the drive */ +) +{ + return 0; +} + + + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_read ( + BYTE pdrv, /* Physical drive nmuber to identify the drive */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Start sector in LBA */ + UINT count /* Number of sectors to read */ +) +{ + switch (pdrv) { + case 0: + return sdmmc_device_read(&g_sd_device, sector, count, (void *)buff) ? RES_OK : RES_ERROR; + default: + return RES_PARERR; + } +} + + + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_write ( + BYTE pdrv, /* Physical drive nmuber to identify the drive */ + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Start sector in LBA */ + UINT count /* Number of sectors to write */ +) +{ + switch (pdrv) { + case 0: + return sdmmc_device_write(&g_sd_device, sector, count, (void *)buff) ? RES_OK : RES_ERROR; + default: + return RES_PARERR; + } +} + + + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_ioctl ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE cmd, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + return RES_OK; +} + diff --git a/sept/sept-secondary/src/lib/fatfs/diskio.h b/sept/sept-secondary/src/lib/fatfs/diskio.h new file mode 100644 index 000000000..1fa4400ea --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/diskio.h @@ -0,0 +1,80 @@ +/*-----------------------------------------------------------------------/ +/ Low level disk interface modlue include file (C)ChaN, 2014 / +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" + + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + + +DSTATUS disk_initialize (BYTE pdrv); +DSTATUS disk_status (BYTE pdrv); +DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); +DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); + + +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (Used by FatFs) */ +#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ +#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ +#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ + +/* Generic command (Not used by FatFs) */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ +#define CTRL_FORMAT 8 /* Create physical format on the media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ +#define ISDIO_READ 55 /* Read data form SD iSDIO register */ +#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ +#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sept/sept-secondary/src/lib/fatfs/ff.c b/sept/sept-secondary/src/lib/fatfs/ff.c new file mode 100644 index 000000000..754ef72d3 --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/ff.c @@ -0,0 +1,6535 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem Module R0.13b / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2018, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wincompatible-pointer-types" + +#include "ff.h" /* Declarations of FatFs API */ +#include "diskio.h" /* Declarations of device I/O functions */ + + +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if FF_DEFINED != 63463 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +/* Character code support macros */ +#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z') +#define IsLower(c) ((c) >= 'a' && (c) <= 'z') +#define IsDigit(c) ((c) >= '0' && (c) <= '9') +#define IsSurrogate(c) ((c) >= 0xD800 && (c) <= 0xDFFF) +#define IsSurrogateH(c) ((c) >= 0xD800 && (c) <= 0xDBFF) +#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF) + + +/* Additional file attribute bits for internal use */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + +/* Additional file access control and file status flags for internal use */ +#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */ +#define FA_MODIFIED 0x40 /* File has been modified */ +#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */ + + +/* Name status flags in fn[11] */ +#define NSFLAG 11 /* Index of the name status byte */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ +#define NS_NOLFN 0x40 /* Do not find LFN */ +#define NS_NONAME 0x80 /* Not followed */ + + +/* Limits and boundaries */ +#define MAX_DIR 0x200000 /* Max size of FAT directory */ +#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ +#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */ +#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */ +#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ +#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ + + +/* FatFs refers the FAT structure as simple byte array instead of structure member +/ because the C structure is not binary compatible between different platforms */ + +#define BS_JmpBoot 0 /* x86 jump instruction (3-byte) */ +#define BS_OEMName 3 /* OEM name (8-byte) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (WORD) */ +#define BPB_NumFATs 16 /* Number of FATs (BYTE) */ +#define BPB_RootEntCnt 17 /* Size of root directory area for FAT [entry] (WORD) */ +#define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ +#define BPB_Media 21 /* Media descriptor byte (BYTE) */ +#define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ +#define BPB_SecPerTrk 24 /* Number of sectors per track for int13h [sector] (WORD) */ +#define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ +#define BPB_HiddSec 28 /* Volume offset from top of the drive (DWORD) */ +#define BPB_TotSec32 32 /* Volume size (32-bit) [sector] (DWORD) */ +#define BS_DrvNum 36 /* Physical drive number for int13h (BYTE) */ +#define BS_NTres 37 /* WindowsNT error flag (BYTE) */ +#define BS_BootSig 38 /* Extended boot signature (BYTE) */ +#define BS_VolID 39 /* Volume serial number (DWORD) */ +#define BS_VolLab 43 /* Volume label string (8-byte) */ +#define BS_FilSysType 54 /* Filesystem type string (8-byte) */ +#define BS_BootCode 62 /* Boot code (448-byte) */ +#define BS_55AA 510 /* Signature word (WORD) */ + +#define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ +#define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ +#define BPB_FSVer32 42 /* FAT32: Filesystem version (WORD) */ +#define BPB_RootClus32 44 /* FAT32: Root directory cluster (DWORD) */ +#define BPB_FSInfo32 48 /* FAT32: Offset of FSINFO sector (WORD) */ +#define BPB_BkBootSec32 50 /* FAT32: Offset of backup boot sector (WORD) */ +#define BS_DrvNum32 64 /* FAT32: Physical drive number for int13h (BYTE) */ +#define BS_NTres32 65 /* FAT32: Error flag (BYTE) */ +#define BS_BootSig32 66 /* FAT32: Extended boot signature (BYTE) */ +#define BS_VolID32 67 /* FAT32: Volume serial number (DWORD) */ +#define BS_VolLab32 71 /* FAT32: Volume label string (8-byte) */ +#define BS_FilSysType32 82 /* FAT32: Filesystem type string (8-byte) */ +#define BS_BootCode32 90 /* FAT32: Boot code (420-byte) */ + +#define BPB_ZeroedEx 11 /* exFAT: MBZ field (53-byte) */ +#define BPB_VolOfsEx 64 /* exFAT: Volume offset from top of the drive [sector] (QWORD) */ +#define BPB_TotSecEx 72 /* exFAT: Volume size [sector] (QWORD) */ +#define BPB_FatOfsEx 80 /* exFAT: FAT offset from top of the volume [sector] (DWORD) */ +#define BPB_FatSzEx 84 /* exFAT: FAT size [sector] (DWORD) */ +#define BPB_DataOfsEx 88 /* exFAT: Data offset from top of the volume [sector] (DWORD) */ +#define BPB_NumClusEx 92 /* exFAT: Number of clusters (DWORD) */ +#define BPB_RootClusEx 96 /* exFAT: Root directory start cluster (DWORD) */ +#define BPB_VolIDEx 100 /* exFAT: Volume serial number (DWORD) */ +#define BPB_FSVerEx 104 /* exFAT: Filesystem version (WORD) */ +#define BPB_VolFlagEx 106 /* exFAT: Volume flags (WORD) */ +#define BPB_BytsPerSecEx 108 /* exFAT: Log2 of sector size in unit of byte (BYTE) */ +#define BPB_SecPerClusEx 109 /* exFAT: Log2 of cluster size in unit of sector (BYTE) */ +#define BPB_NumFATsEx 110 /* exFAT: Number of FATs (BYTE) */ +#define BPB_DrvNumEx 111 /* exFAT: Physical drive number for int13h (BYTE) */ +#define BPB_PercInUseEx 112 /* exFAT: Percent in use (BYTE) */ +#define BPB_RsvdEx 113 /* exFAT: Reserved (7-byte) */ +#define BS_BootCodeEx 120 /* exFAT: Boot code (390-byte) */ + +#define DIR_Name 0 /* Short file name (11-byte) */ +#define DIR_Attr 11 /* Attribute (BYTE) */ +#define DIR_NTres 12 /* Lower case flag (BYTE) */ +#define DIR_CrtTime10 13 /* Created time sub-second (BYTE) */ +#define DIR_CrtTime 14 /* Created time (DWORD) */ +#define DIR_LstAccDate 18 /* Last accessed date (WORD) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (WORD) */ +#define DIR_ModTime 22 /* Modified time (DWORD) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (WORD) */ +#define DIR_FileSize 28 /* File size (DWORD) */ +#define LDIR_Ord 0 /* LFN: LFN order and LLE flag (BYTE) */ +#define LDIR_Attr 11 /* LFN: LFN attribute (BYTE) */ +#define LDIR_Type 12 /* LFN: Entry type (BYTE) */ +#define LDIR_Chksum 13 /* LFN: Checksum of the SFN (BYTE) */ +#define LDIR_FstClusLO 26 /* LFN: MBZ field (WORD) */ +#define XDIR_Type 0 /* exFAT: Type of exFAT directory entry (BYTE) */ +#define XDIR_NumLabel 1 /* exFAT: Number of volume label characters (BYTE) */ +#define XDIR_Label 2 /* exFAT: Volume label (11-WORD) */ +#define XDIR_CaseSum 4 /* exFAT: Sum of case conversion table (DWORD) */ +#define XDIR_NumSec 1 /* exFAT: Number of secondary entries (BYTE) */ +#define XDIR_SetSum 2 /* exFAT: Sum of the set of directory entries (WORD) */ +#define XDIR_Attr 4 /* exFAT: File attribute (WORD) */ +#define XDIR_CrtTime 8 /* exFAT: Created time (DWORD) */ +#define XDIR_ModTime 12 /* exFAT: Modified time (DWORD) */ +#define XDIR_AccTime 16 /* exFAT: Last accessed time (DWORD) */ +#define XDIR_CrtTime10 20 /* exFAT: Created time subsecond (BYTE) */ +#define XDIR_ModTime10 21 /* exFAT: Modified time subsecond (BYTE) */ +#define XDIR_CrtTZ 22 /* exFAT: Created timezone (BYTE) */ +#define XDIR_ModTZ 23 /* exFAT: Modified timezone (BYTE) */ +#define XDIR_AccTZ 24 /* exFAT: Last accessed timezone (BYTE) */ +#define XDIR_GenFlags 33 /* exFAT: General secondary flags (BYTE) */ +#define XDIR_NumName 35 /* exFAT: Number of file name characters (BYTE) */ +#define XDIR_NameHash 36 /* exFAT: Hash of file name (WORD) */ +#define XDIR_ValidFileSize 40 /* exFAT: Valid file size (QWORD) */ +#define XDIR_FstClus 52 /* exFAT: First cluster of the file data (DWORD) */ +#define XDIR_FileSize 56 /* exFAT: File/Directory size (QWORD) */ + +#define SZDIRE 32 /* Size of a directory entry */ +#define DDEM 0xE5 /* Deleted directory entry mark set to DIR_Name[0] */ +#define RDDEM 0x05 /* Replacement of the character collides with DDEM */ +#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */ + +#define FSI_LeadSig 0 /* FAT32 FSI: Leading signature (DWORD) */ +#define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ +#define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ +#define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ + +#define MBR_Table 446 /* MBR: Offset of partition table in the MBR */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define PTE_Boot 0 /* MBR PTE: Boot indicator */ +#define PTE_StHead 1 /* MBR PTE: Start head */ +#define PTE_StSec 2 /* MBR PTE: Start sector */ +#define PTE_StCyl 3 /* MBR PTE: Start cylinder */ +#define PTE_System 4 /* MBR PTE: System ID */ +#define PTE_EdHead 5 /* MBR PTE: End head */ +#define PTE_EdSec 6 /* MBR PTE: End sector */ +#define PTE_EdCyl 7 /* MBR PTE: End cylinder */ +#define PTE_StLba 8 /* MBR PTE: Start in LBA */ +#define PTE_SizLba 12 /* MBR PTE: Size in LBA */ + + +/* Post process on fatal error in the file operations */ +#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } + + +/* Re-entrancy related */ +#if FF_FS_REENTRANT +#if FF_USE_LFN == 1 +#error Static LFN work area cannot be used at thread-safe configuration +#endif +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define LEAVE_FF(fs, res) return res +#endif + + +/* Definitions of volume - physical location conversion */ +#if FF_MULTI_PARTITION +#define LD2PD(vol) VolToPart[vol].pd /* Get physical drive number */ +#define LD2PT(vol) VolToPart[vol].pt /* Get partition index */ +#else +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Find first valid partition or in SFD */ +#endif + + +/* Definitions of sector size */ +#if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096) +#error Wrong sector size configuration +#endif +#if FF_MAX_SS == FF_MIN_SS +#define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */ +#else +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#endif + + +/* Timestamp */ +#if FF_FS_NORTC == 1 +#if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31 +#error Invalid FF_FS_NORTC settings +#endif +#define GET_FATTIME() ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16) +#else +#define GET_FATTIME() get_fattime() +#endif + + +/* File lock controls */ +#if FF_FS_LOCK != 0 +#if FF_FS_READONLY +#error FF_FS_LOCK must be 0 at read-only configuration +#endif +typedef struct { + FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ + DWORD clu; /* Object ID 2, containing directory (0:root) */ + DWORD ofs; /* Object ID 3, offset in the directory */ + WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ +} FILESEM; +#endif + + +/* SBCS up-case tables (\x80-\xFF) */ +#define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT720 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT737 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT771 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDC,0xDE,0xDE, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF} +#define TBL_CT775 {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT850 {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \ + 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \ + 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT852 {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} +#define TBL_CT855 {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \ + 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \ + 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT857 {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT860 {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \ + 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT861 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT862 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT863 {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \ + 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \ + 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT864 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT865 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT866 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT869 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \ + 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \ + 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \ + 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF} + + +/* DBCS code range |----- 1st byte -----| |----------- 2nd byte -----------| */ +#define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00} +#define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00} +#define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE} +#define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00} + + +/* Macros for table definitions */ +#define MERGE_2STR(a, b) a ## b +#define MKCVTBL(hd, cp) MERGE_2STR(hd, cp) + + + + +/*-------------------------------------------------------------------------- + + Module Private Work Area + +---------------------------------------------------------------------------*/ +/* Remark: Variables defined here without initial value shall be guaranteed +/ zero/null at start-up. If not, the linker option or start-up routine is +/ not compliance with C standard. */ + +/*--------------------------------*/ +/* File/Volume controls */ +/*--------------------------------*/ + +#if FF_VOLUMES < 1 || FF_VOLUMES > 10 +#error Wrong FF_VOLUMES setting +#endif +static FATFS* FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ +static WORD Fsid; /* Filesystem mount ID */ + +#if FF_FS_RPATH != 0 +static BYTE CurrVol; /* Current drive */ +#endif + +#if FF_FS_LOCK != 0 +static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ +#endif + +#if FF_STR_VOLUME_ID +#ifdef FF_VOLUME_STRS +static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ +#endif +#endif + + +/*--------------------------------*/ +/* LFN/Directory working buffer */ +/*--------------------------------*/ + +#if FF_USE_LFN == 0 /* Non-LFN configuration */ +#if FF_FS_EXFAT +#error LFN must be enabled when enable exFAT +#endif +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() +#define LEAVE_MKFS(res) return res + +#else /* LFN configurations */ +#if FF_MAX_LFN < 12 || FF_MAX_LFN > 255 +#error Wrong setting of FF_MAX_LFN +#endif +#if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12 +#error Wrong setting of FF_LFN_BUF or FF_SFN_BUF +#endif +#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3 +#error Wrong setting of FF_LFN_UNICODE +#endif +static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* FAT: Offset of LFN characters in the directory entry */ +#define MAXDIRB(nc) ((nc + 44U) / 15 * SZDIRE) /* exFAT: Size of directory entry block scratchpad buffer needed for the name length */ + +#if FF_USE_LFN == 1 /* LFN enabled with static working buffer */ +#if FF_FS_EXFAT +static BYTE DirBuf[MAXDIRB(FF_MAX_LFN)]; /* Directory entry block scratchpad buffer */ +#endif +static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() +#define LEAVE_MKFS(res) return res + +#elif FF_USE_LFN == 2 /* LFN enabled with dynamic working buffer on the stack */ +#if FF_FS_EXFAT +#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; BYTE dbuf[MAXDIRB(FF_MAX_LFN)]; /* LFN working buffer and directory entry block scratchpad buffer */ +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; } +#define FREE_NAMBUF() +#else +#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; /* LFN working buffer */ +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; } +#define FREE_NAMBUF() +#endif +#define LEAVE_MKFS(res) return res + +#elif FF_USE_LFN == 3 /* LFN enabled with dynamic working buffer on the heap */ +#if FF_FS_EXFAT +#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer and directory entry block scratchpad buffer */ +#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2 + MAXDIRB(FF_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+FF_MAX_LFN+1); } +#define FREE_NAMBUF() ff_memfree(lfn) +#else +#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer */ +#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } +#define FREE_NAMBUF() ff_memfree(lfn) +#endif +#define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; } +#define MAX_MALLOC 0x8000 /* Must be >=FF_MAX_SS */ + +#else +#error Wrong setting of FF_USE_LFN + +#endif /* FF_USE_LFN == 1 */ +#endif /* FF_USE_LFN == 0 */ + + + +/*--------------------------------*/ +/* Code conversion tables */ +/*--------------------------------*/ + +#if FF_CODE_PAGE == 0 /* Run-time code page configuration */ +#define CODEPAGE CodePage +static WORD CodePage; /* Current code page */ +static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */ +static const BYTE Ct437[] = TBL_CT437; +static const BYTE Ct720[] = TBL_CT720; +static const BYTE Ct737[] = TBL_CT737; +static const BYTE Ct771[] = TBL_CT771; +static const BYTE Ct775[] = TBL_CT775; +static const BYTE Ct850[] = TBL_CT850; +static const BYTE Ct852[] = TBL_CT852; +static const BYTE Ct855[] = TBL_CT855; +static const BYTE Ct857[] = TBL_CT857; +static const BYTE Ct860[] = TBL_CT860; +static const BYTE Ct861[] = TBL_CT861; +static const BYTE Ct862[] = TBL_CT862; +static const BYTE Ct863[] = TBL_CT863; +static const BYTE Ct864[] = TBL_CT864; +static const BYTE Ct865[] = TBL_CT865; +static const BYTE Ct866[] = TBL_CT866; +static const BYTE Ct869[] = TBL_CT869; +static const BYTE Dc932[] = TBL_DC932; +static const BYTE Dc936[] = TBL_DC936; +static const BYTE Dc949[] = TBL_DC949; +static const BYTE Dc950[] = TBL_DC950; + +#elif FF_CODE_PAGE < 900 /* Static code page configuration (SBCS) */ +#define CODEPAGE FF_CODE_PAGE +static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE); + +#else /* Static code page configuration (DBCS) */ +#define CODEPAGE FF_CODE_PAGE +static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); + +#endif + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* Load/Store multi-byte word in the FAT structure */ +/*-----------------------------------------------------------------------*/ + +static WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ +{ + WORD rv; + + rv = ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ +{ + DWORD rv; + + rv = ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +#if FF_FS_EXFAT +static QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ +{ + QWORD rv; + + rv = ptr[7]; + rv = rv << 8 | ptr[6]; + rv = rv << 8 | ptr[5]; + rv = rv << 8 | ptr[4]; + rv = rv << 8 | ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} +#endif + +#if !FF_FS_READONLY +static void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} + +static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} + +#if FF_FS_EXFAT +static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} +#endif +#endif /* !FF_FS_READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +static void mem_cpy (void* dst, const void* src, UINT cnt) +{ + BYTE *d = (BYTE*)dst; + const BYTE *s = (const BYTE*)src; + + if (cnt != 0) { + do { + *d++ = *s++; + } while (--cnt); + } +} + + +/* Fill memory block */ +static void mem_set (void* dst, int val, UINT cnt) +{ + BYTE *d = (BYTE*)dst; + + do { + *d++ = (BYTE)val; + } while (--cnt); +} + + +/* Compare memory block */ +static int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */ +{ + const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; + int r = 0; + + do { + r = *d++ - *s++; + } while (--cnt && r == 0); + + return r; +} + + +/* Check if chr is contained in the string */ +static int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ +{ + while (*str && *str != chr) str++; + return *str; +} + + +/* Test if the character is DBC 1st byte */ +static int dbc_1st (BYTE c) +{ +#if FF_CODE_PAGE == 0 /* Variable code page */ + if (DbcTbl && c >= DbcTbl[0]) { + if (c <= DbcTbl[1]) return 1; /* 1st byte range 1 */ + if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; /* 1st byte range 2 */ + } +#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ + if (c >= DbcTbl[0]) { + if (c <= DbcTbl[1]) return 1; + if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; + } +#else /* SBCS fixed code page */ + if (c != 0) return 0; /* Always false */ +#endif + return 0; +} + + +/* Test if the character is DBC 2nd byte */ +static int dbc_2nd (BYTE c) +{ +#if FF_CODE_PAGE == 0 /* Variable code page */ + if (DbcTbl && c >= DbcTbl[4]) { + if (c <= DbcTbl[5]) return 1; /* 2nd byte range 1 */ + if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; /* 2nd byte range 2 */ + if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; /* 2nd byte range 3 */ + } +#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ + if (c >= DbcTbl[4]) { + if (c <= DbcTbl[5]) return 1; + if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; + if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; + } +#else /* SBCS fixed code page */ + if (c != 0) return 0; /* Always false */ +#endif + return 0; +} + + +#if FF_USE_LFN + +/* Get a character from TCHAR string in defined API encodeing */ +static DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */ + const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ +) +{ + DWORD uc; + const TCHAR *p = *str; + +#if FF_LFN_UNICODE == 1 /* UTF-16 input */ + WCHAR wc; + + uc = *p++; /* Get a unit */ + if (IsSurrogate(uc)) { /* Surrogate? */ + wc = *p++; /* Get low surrogate */ + if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF; /* Wrong surrogate? */ + uc = uc << 16 | wc; + } + +#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ + BYTE b; + int nf; + + uc = (BYTE)*p++; /* Get a unit */ + if (uc & 0x80) { /* Multiple byte code? */ + if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */ + uc &= 0x1F; nf = 1; + } else { + if ((uc & 0xF0) == 0xE0) { /* 3-byte sequence? */ + uc &= 0x0F; nf = 2; + } else { + if ((uc & 0xF8) == 0xF0) { /* 4-byte sequence? */ + uc &= 0x07; nf = 3; + } else { /* Wrong sequence */ + return 0xFFFFFFFF; + } + } + } + do { /* Get trailing bytes */ + b = (BYTE)*p++; + if ((b & 0xC0) != 0x80) return 0xFFFFFFFF; /* Wrong sequence? */ + uc = uc << 6 | (b & 0x3F); + } while (--nf != 0); + if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + } + +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + uc = (TCHAR)*p++; /* Get a unit */ + if (uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + +#else /* ANSI/OEM input */ + BYTE b; + WCHAR wc; + + wc = (BYTE)*p++; /* Get a byte */ + if (dbc_1st((BYTE)wc)) { /* Is it a DBC 1st byte? */ + b = (BYTE)*p++; /* Get 2nd byte */ + if (!dbc_2nd(b)) return 0xFFFFFFFF; /* Invalid code? */ + wc = (wc << 8) + b; /* Make a DBC */ + } + if (wc != 0) { + wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM ==> Unicode */ + if (wc == 0) return 0xFFFFFFFF; /* Invalid code? */ + } + uc = wc; + +#endif + *str = p; /* Next read pointer */ + return uc; +} + + +/* Output a TCHAR string in defined API encoding */ +static BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ + DWORD chr, /* UTF-16 encoded character (Double encoding unit char if >=0x10000) */ + TCHAR* buf, /* Output buffer */ + UINT szb /* Size of the buffer */ +) +{ +#if FF_LFN_UNICODE == 1 /* UTF-16 output */ + WCHAR hs, wc; + + hs = (WCHAR)(chr >> 16); + wc = (WCHAR)chr; + if (hs == 0) { /* Single encoding unit? */ + if (szb < 1 || IsSurrogate(wc)) return 0; /* Buffer overflow or wrong code? */ + *buf = wc; + return 1; + } + if (szb < 2 || !IsSurrogateH(hs) || !IsSurrogateL(wc)) return 0; /* Buffer overflow or wrong surrogate? */ + *buf++ = hs; + *buf++ = wc; + return 2; + +#elif FF_LFN_UNICODE == 2 /* UTF-8 output */ + DWORD hc; + + if (chr < 0x80) { /* Single byte code? */ + if (szb < 1) return 0; /* Buffer overflow? */ + *buf = (TCHAR)chr; + return 1; + } + if (chr < 0x800) { /* 2-byte sequence? */ + if (szb < 2) return 0; /* Buffer overflow? */ + *buf++ = (TCHAR)(0xC0 | (chr >> 6 & 0x1F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 2; + } + if (chr < 0x10000) { /* 3-byte sequence? */ + if (szb < 3 || IsSurrogate(chr)) return 0; /* Buffer overflow or wrong code? */ + *buf++ = (TCHAR)(0xE0 | (chr >> 12 & 0x0F)); + *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 3; + } + /* 4-byte sequence */ + if (szb < 4) return 0; /* Buffer overflow? */ + hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ + chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ + if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ + chr = (hc | chr) + 0x10000; + *buf++ = (TCHAR)(0xF0 | (chr >> 18 & 0x07)); + *buf++ = (TCHAR)(0x80 | (chr >> 12 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 4; + +#elif FF_LFN_UNICODE == 3 /* UTF-32 output */ + DWORD hc; + + if (szb < 1) return 0; /* Buffer overflow? */ + if (chr >= 0x10000) { /* Out of BMP? */ + hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ + chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ + if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ + chr = (hc | chr) + 0x10000; + } + *buf++ = (TCHAR)chr; + return 1; + +#else /* ANSI/OEM output */ + WCHAR wc; + + wc = ff_uni2oem(chr, CODEPAGE); + if (wc >= 0x100) { /* Is this a DBC? */ + if (szb < 2) return 0; + *buf++ = (char)(wc >> 8); /* Store DBC 1st byte */ + *buf++ = (TCHAR)wc; /* Store DBC 2nd byte */ + return 2; + } + if (wc == 0 || szb < 1) return 0; /* Invalid char or buffer overflow? */ + *buf++ = (TCHAR)wc; /* Store the character */ + return 1; +#endif +} +#endif /* FF_USE_LFN */ + + +#if FF_FS_REENTRANT +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +static int lock_fs ( /* 1:Ok, 0:timeout */ + FATFS* fs /* Filesystem object */ +) +{ + return ff_req_grant(fs->sobj); +} + + +static void unlock_fs ( + FATFS* fs, /* Filesystem object */ + FRESULT res /* Result code to be returned */ +) +{ + if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) { + ff_rel_grant(fs->sobj); + } +} + +#endif + + + +#if FF_FS_LOCK != 0 +/*-----------------------------------------------------------------------*/ +/* File lock control functions */ +/*-----------------------------------------------------------------------*/ + +static FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR* dp, /* Directory object pointing the file to be checked */ + int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ +) +{ + UINT i, be; + + /* Search open object table for the object */ + be = 0; + for (i = 0; i < FF_FS_LOCK; i++) { + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dp->obj.fs && /* Check if the object matches with an open object */ + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } else { /* Blank entry */ + be = 1; + } + } + if (i == FF_FS_LOCK) { /* The object has not been opened */ + return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK; /* Is there a blank entry for new object? */ + } + + /* The object was opened. Reject any open against writing file and all write mode open */ + return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static int enq_lock (void) /* Check if an entry is available for a new object */ +{ + UINT i; + + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + return (i == FF_FS_LOCK) ? 0 : 1; +} + + +static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ + DIR* dp, /* Directory object pointing the file to register or increment */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i; + + + for (i = 0; i < FF_FS_LOCK; i++) { /* Find the object */ + if (Files[i].fs == dp->obj.fs && + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } + + if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */ + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + if (i == FF_FS_LOCK) return 0; /* No free entry to register (int err) */ + Files[i].fs = dp->obj.fs; + Files[i].clu = dp->obj.sclust; + Files[i].ofs = dp->dptr; + Files[i].ctr = 0; + } + + if (acc >= 1 && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; /* Index number origin from 1 */ +} + + +static FRESULT dec_lock ( /* Decrement object open counter */ + UINT i /* Semaphore index (1..) */ +) +{ + WORD n; + FRESULT res; + + + if (--i < FF_FS_LOCK) { /* Index number origin from 0 */ + n = Files[i].ctr; + if (n == 0x100) n = 0; /* If write mode open, delete the entry */ + if (n > 0) n--; /* Decrement read mode open count */ + Files[i].ctr = n; + if (n == 0) Files[i].fs = 0; /* Delete the entry if open count gets zero */ + res = FR_OK; + } else { + res = FR_INT_ERR; /* Invalid index nunber */ + } + return res; +} + + +static void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < FF_FS_LOCK; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} + +#endif /* FF_FS_LOCK != 0 */ + + + +/*-----------------------------------------------------------------------*/ +/* Move/Flush disk access window in the filesystem object */ +/*-----------------------------------------------------------------------*/ +#if !FF_FS_READONLY +static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs /* Filesystem object */ +) +{ + FRESULT res = FR_OK; + + + if (fs->wflag) { /* Is the disk access window dirty */ + if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write back the window */ + fs->wflag = 0; /* Clear window dirty flag */ + if (fs->winsect - fs->fatbase < fs->fsize) { /* Is it in the 1st FAT? */ + if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */ + } + } else { + res = FR_DISK_ERR; + } + } + return res; +} +#endif + + +static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs, /* Filesystem object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) +{ + FRESULT res = FR_OK; + + + if (sector != fs->winsect) { /* Window offset changed? */ +#if !FF_FS_READONLY + res = sync_window(fs); /* Write-back changes */ +#endif + if (res == FR_OK) { /* Fill sector window with new data */ + if (disk_read(fs->pdrv, fs->win, sector, 1) != RES_OK) { + sector = 0xFFFFFFFF; /* Invalidate window if read data is not valid */ + res = FR_DISK_ERR; + } + fs->winsect = sector; + } + } + return res; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Synchronize filesystem and data on the storage */ +/*-----------------------------------------------------------------------*/ + +static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs /* Filesystem object */ +) +{ + FRESULT res; + + + res = sync_window(fs); + if (res == FR_OK) { + if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */ + /* Create FSInfo structure */ + mem_set(fs->win, 0, SS(fs)); + st_word(fs->win + BS_55AA, 0xAA55); + st_dword(fs->win + FSI_LeadSig, 0x41615252); + st_dword(fs->win + FSI_StrucSig, 0x61417272); + st_dword(fs->win + FSI_Free_Count, fs->free_clst); + st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); + /* Write it into the FSInfo sector */ + fs->winsect = fs->volbase + 1; + disk_write(fs->pdrv, fs->win, fs->winsect, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the lower layer */ + if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; + } + + return res; +} + +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Get physical sector number from cluster number */ +/*-----------------------------------------------------------------------*/ + +static DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ + FATFS* fs, /* Filesystem object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; /* Cluster number is origin from 2 */ + if (clst >= fs->n_fatent - 2) return 0; /* Is it invalid cluster number? */ + return fs->database + fs->csize * clst; /* Start sector number of the cluster */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + +static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst /* Cluster number to get the value */ +) +{ + UINT wc, bc; + DWORD val; + FATFS *fs = obj->fs; + + + if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */ + val = 1; /* Internal error */ + + } else { + val = 0xFFFFFFFF; /* Default value falls on disk error */ + + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc = fs->win[bc++ % SS(fs)]; /* Get 1st byte of the entry */ + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc |= fs->win[bc % SS(fs)] << 8; /* Merge 2nd byte of the entry */ + val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); /* Adjust bit position */ + break; + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; + val = ld_word(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */ + break; + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */ + break; +#if FF_FS_EXFAT + case FS_EXFAT : + if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) { /* Object except root dir must have valid data length */ + DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ + DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ + + if (obj->stat == 2 && cofs <= clen) { /* Is it a contiguous chain? */ + val = (cofs == clen) ? 0x7FFFFFFF : clst + 1; /* No data on the FAT, generate the value */ + break; + } + if (obj->stat == 3 && cofs < obj->n_cont) { /* Is it in the 1st fragment? */ + val = clst + 1; /* Generate the value */ + break; + } + if (obj->stat != 2) { /* Get value from FAT if FAT chain is valid */ + if (obj->n_frag != 0) { /* Is it on the growing edge? */ + val = 0x7FFFFFFF; /* Generate EOC */ + } else { + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; + } + break; + } + } + /* go to default */ +#endif + default: + val = 1; /* Internal error */ + } + } + + return val; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + +static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ + FATFS* fs, /* Corresponding filesystem object */ + DWORD clst, /* FAT index number (cluster number) to be changed */ + DWORD val /* New value to be set to the entry */ +) +{ + UINT bc; + BYTE *p; + FRESULT res = FR_INT_ERR; + + + if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */ + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; /* bc: byte offset of the entry */ + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc++ % SS(fs); + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Put 1st byte */ + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc % SS(fs); + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); /* Put 2nd byte */ + fs->wflag = 1; + break; + + case FS_FAT16 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */ + fs->wflag = 1; + break; + + case FS_FAT32 : +#if FF_FS_EXFAT + case FS_EXFAT : +#endif + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { + val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); + } + st_dword(fs->win + clst * 4 % SS(fs), val); + fs->wflag = 1; + break; + } + } + return res; +} + +#endif /* !FF_FS_READONLY */ + + + + +#if FF_FS_EXFAT && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* exFAT: Accessing FAT and Allocation Bitmap */ +/*-----------------------------------------------------------------------*/ + +/*--------------------------------------*/ +/* Find a contiguous free cluster block */ +/*--------------------------------------*/ + +static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD clst, /* Cluster number to scan from */ + DWORD ncl /* Number of contiguous clusters to find (1..) */ +) +{ + BYTE bm, bv; + UINT i; + DWORD val, scl, ctr; + + + clst -= 2; /* The first bit in the bitmap corresponds to cluster #2 */ + if (clst >= fs->n_fatent - 2) clst = 0; + scl = val = clst; ctr = 0; + for (;;) { + if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */ + i = val / 8 % SS(fs); bm = 1 << (val % 8); + do { + do { + bv = fs->win[i] & bm; bm <<= 1; /* Get bit value */ + if (++val >= fs->n_fatent - 2) { /* Next cluster (with wrap-around) */ + val = 0; bm = 0; i = SS(fs); + } + if (bv == 0) { /* Is it a free cluster? */ + if (++ctr == ncl) return scl + 2; /* Check if run length is sufficient for required */ + } else { + scl = val; ctr = 0; /* Encountered a cluster in-use, restart to scan */ + } + if (val == clst) return 0; /* All cluster scanned? */ + } while (bm != 0); + bm = 1; + } while (++i < SS(fs)); + } +} + + +/*----------------------------------------*/ +/* Set/Clear a block of allocation bitmap */ +/*----------------------------------------*/ + +static FRESULT change_bitmap ( + FATFS* fs, /* Filesystem object */ + DWORD clst, /* Cluster number to change from */ + DWORD ncl, /* Number of clusters to be changed */ + int bv /* bit value to be set (0 or 1) */ +) +{ + BYTE bm; + UINT i; + DWORD sect; + + + clst -= 2; /* The first bit corresponds to cluster #2 */ + sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */ + i = clst / 8 % SS(fs); /* Byte offset in the sector */ + bm = 1 << (clst % 8); /* Bit mask in the byte */ + for (;;) { + if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR; + do { + do { + if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR; /* Is the bit expected value? */ + fs->win[i] ^= bm; /* Flip the bit */ + fs->wflag = 1; + if (--ncl == 0) return FR_OK; /* All bits processed? */ + } while (bm <<= 1); /* Next bit */ + bm = 1; + } while (++i < SS(fs)); /* Next byte */ + i = 0; + } +} + + +/*---------------------------------------------*/ +/* Fill the first fragment of the FAT chain */ +/*---------------------------------------------*/ + +static FRESULT fill_first_frag ( + FFOBJID* obj /* Pointer to the corresponding object */ +) +{ + FRESULT res; + DWORD cl, n; + + + if (obj->stat == 3) { /* Has the object been changed 'fragmented' in this session? */ + for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) { /* Create cluster chain on the FAT */ + res = put_fat(obj->fs, cl, cl + 1); + if (res != FR_OK) return res; + } + obj->stat = 0; /* Change status 'FAT chain is valid' */ + } + return FR_OK; +} + + +/*---------------------------------------------*/ +/* Fill the last fragment of the FAT chain */ +/*---------------------------------------------*/ + +static FRESULT fill_last_frag ( + FFOBJID* obj, /* Pointer to the corresponding object */ + DWORD lcl, /* Last cluster of the fragment */ + DWORD term /* Value to set the last FAT entry */ +) +{ + FRESULT res; + + + while (obj->n_frag > 0) { /* Create the chain of last fragment */ + res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term); + if (res != FR_OK) return res; + obj->n_frag--; + } + return FR_OK; +} + +#endif /* FF_FS_EXFAT && !FF_FS_READONLY */ + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ + +static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst, /* Cluster to remove a chain from */ + DWORD pclst /* Previous cluster of clst (0:entire chain) */ +) +{ + FRESULT res = FR_OK; + DWORD nxt; + FATFS *fs = obj->fs; +#if FF_FS_EXFAT || FF_USE_TRIM + DWORD scl = clst, ecl = clst; +#endif +#if FF_USE_TRIM + DWORD rt[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Check if in valid range */ + + /* Mark the previous cluster 'EOC' on the FAT if it exists */ + if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) { + res = put_fat(fs, pclst, 0xFFFFFFFF); + if (res != FR_OK) return res; + } + + /* Remove the chain */ + do { + nxt = get_fat(obj, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) return FR_INT_ERR; /* Internal error? */ + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error? */ + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { + res = put_fat(fs, clst, 0); /* Mark the cluster 'free' on the FAT */ + if (res != FR_OK) return res; + } + if (fs->free_clst < fs->n_fatent - 2) { /* Update FSINFO */ + fs->free_clst++; + fs->fsi_flag |= 1; + } +#if FF_FS_EXFAT || FF_USE_TRIM + if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ + ecl = nxt; + } else { /* End of contiguous cluster block */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */ + if (res != FR_OK) return res; + } +#endif +#if FF_USE_TRIM + rt[0] = clst2sect(fs, scl); /* Start of data area freed */ + rt[1] = clst2sect(fs, ecl) + fs->csize - 1; /* End of data area freed */ + disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform device the data in the block is no longer needed */ +#endif + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } while (clst < fs->n_fatent); /* Repeat while not the last link */ + +#if FF_FS_EXFAT + /* Some post processes for chain status */ + if (fs->fs_type == FS_EXFAT) { + if (pclst == 0) { /* Has the entire chain been removed? */ + obj->stat = 0; /* Change the chain status 'initial' */ + } else { + if (obj->stat == 0) { /* Is it a fragmented chain from the beginning of this session? */ + clst = obj->sclust; /* Follow the chain to check if it gets contiguous */ + while (clst != pclst) { + nxt = get_fat(obj, clst); + if (nxt < 2) return FR_INT_ERR; + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; + if (nxt != clst + 1) break; /* Not contiguous? */ + clst++; + } + if (clst == pclst) { /* Has the chain got contiguous again? */ + obj->stat = 2; /* Change the chain status 'contiguous' */ + } + } else { + if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) { /* Was the chain fragmented in this session and got contiguous again? */ + obj->stat = 2; /* Change the chain status 'contiguous' */ + } + } + } + } +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch a chain or Create a new chain */ +/*-----------------------------------------------------------------------*/ + +static DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst /* Cluster# to stretch, 0:Create a new chain */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + FATFS *fs = obj->fs; + + + if (clst == 0) { /* Create a new chain */ + scl = fs->last_clst; /* Suggested cluster to start to find */ + if (scl == 0 || scl >= fs->n_fatent) scl = 1; + } + else { /* Stretch a chain */ + cs = get_fat(obj, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* Test for insanity */ + if (cs == 0xFFFFFFFF) return cs; /* Test for disk error */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; /* Cluster to start to find */ + } + if (fs->free_clst == 0) return 0; /* No free cluster */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ + if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ + res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ + if (res == FR_INT_ERR) return 1; + if (res == FR_DISK_ERR) return 0xFFFFFFFF; + if (clst == 0) { /* Is it a new chain? */ + obj->stat = 2; /* Set status 'contiguous' */ + } else { /* It is a stretched chain */ + if (obj->stat == 2 && ncl != scl + 1) { /* Is the chain got fragmented? */ + obj->n_cont = scl - obj->sclust; /* Set size of the contiguous part */ + obj->stat = 3; /* Change status 'just fragmented' */ + } + } + if (obj->stat != 2) { /* Is the file non-contiguous? */ + if (ncl == clst + 1) { /* Is the cluster next to previous one? */ + obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2; /* Increment size of last framgent */ + } else { /* New fragment */ + if (obj->n_frag == 0) obj->n_frag = 1; + res = fill_last_frag(obj, clst, ncl); /* Fill last fragment on the FAT and link it to new one */ + if (res == FR_OK) obj->n_frag = 1; + } + } + } else +#endif + { /* On the FAT/FAT32 volume */ + ncl = 0; + if (scl == clst) { /* Stretching an existing chain? */ + ncl = scl + 1; /* Test if next cluster is free */ + if (ncl >= fs->n_fatent) ncl = 2; + cs = get_fat(obj, ncl); /* Get next cluster status */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ + if (cs != 0) { /* Not free? */ + cs = fs->last_clst; /* Start at suggested cluster if it is valid */ + if (cs >= 2 && cs < fs->n_fatent) scl = cs; + ncl = 0; + } + } + if (ncl == 0) { /* The new cluster cannot be contiguous and find another fragment */ + ncl = scl; /* Start cluster */ + for (;;) { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) { /* Check wrap-around */ + ncl = 2; + if (ncl > scl) return 0; /* No free cluster found? */ + } + cs = get_fat(obj, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster? */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ + if (ncl == scl) return 0; /* No free cluster found? */ + } + } + res = put_fat(fs, ncl, 0xFFFFFFFF); /* Mark the new cluster 'EOC' */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it from the previous one if needed */ + } + } + + if (res == FR_OK) { /* Update FSINFO if function succeeded. */ + fs->last_clst = ncl; + if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--; + fs->fsi_flag |= 1; + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; /* Failed. Generate error status */ + } + + return ncl; /* Return new cluster number or error status */ +} + +#endif /* !FF_FS_READONLY */ + + + + +#if FF_USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +static DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + FSIZE_t ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + FATFS *fs = fp->obj.fs; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = (DWORD)(ofs / SS(fs) / fs->csize); /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (ncl == 0) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} + +#endif /* FF_USE_FASTSEEK */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Fill a cluster with zeros */ +/*-----------------------------------------------------------------------*/ + +#if !FF_FS_READONLY +static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS *fs, /* Filesystem object */ + DWORD clst /* Directory table to clear */ +) +{ + DWORD sect; + UINT n, szb; + BYTE *ibuf; + + + if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */ + sect = clst2sect(fs, clst); /* Top of the cluster */ + fs->winsect = sect; /* Set window to top of the cluster */ + mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */ +#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ + /* Allocate a temporary buffer */ + for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ; + if (szb > SS(fs)) { /* Buffer allocated? */ + mem_set(ibuf, 0, szb); + szb /= SS(fs); /* Bytes -> Sectors */ + for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + ff_memfree(ibuf); + } else +#endif + { + ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */ + for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + } + return (n == fs->csize) ? FR_OK : FR_DISK_ERR; +} +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp, /* Pointer to directory object */ + DWORD ofs /* Offset of directory table */ +) +{ + DWORD csz, clst; + FATFS *fs = dp->obj.fs; + + + if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) { /* Check range of offset and alignment */ + return FR_INT_ERR; + } + dp->dptr = ofs; /* Set current offset */ + clst = dp->obj.sclust; /* Table start cluster (0:root) */ + if (clst == 0 && fs->fs_type >= FS_FAT32) { /* Replace cluster# 0 with root cluster# */ + clst = fs->dirbase; + if (FF_FS_EXFAT) dp->obj.stat = 0; /* exFAT: Root dir has an FAT chain */ + } + + if (clst == 0) { /* Static table (root-directory on the FAT volume) */ + if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */ + dp->sect = fs->dirbase; + + } else { /* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */ + csz = (DWORD)fs->csize * SS(fs); /* Bytes per cluster */ + while (ofs >= csz) { /* Follow cluster chain */ + clst = get_fat(&dp->obj, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Reached to end of table or internal error */ + ofs -= csz; + } + dp->sect = clst2sect(fs, clst); + } + dp->clust = clst; /* Current cluster# */ + if (dp->sect == 0) return FR_INT_ERR; + dp->sect += ofs / SS(fs); /* Sector# of the directory entry */ + dp->dir = fs->win + (ofs % SS(fs)); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory table index next */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + DIR* dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD ofs, clst; + FATFS *fs = dp->obj.fs; + + + ofs = dp->dptr + SZDIRE; /* Next entry */ + if (dp->sect == 0 || ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) return FR_NO_FILE; /* Report EOT when offset has reached max value */ + + if (ofs % SS(fs) == 0) { /* Sector changed? */ + dp->sect++; /* Next sector */ + + if (dp->clust == 0) { /* Static table */ + if (ofs / SZDIRE >= fs->n_rootdir) { /* Report EOT if it reached end of static table */ + dp->sect = 0; return FR_NO_FILE; + } + } + else { /* Dynamic table */ + if ((ofs / SS(fs) & (fs->csize - 1)) == 0) { /* Cluster changed? */ + clst = get_fat(&dp->obj, dp->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst >= fs->n_fatent) { /* It reached end of dynamic table */ +#if !FF_FS_READONLY + if (!stretch) { /* If no stretch, report EOT */ + dp->sect = 0; return FR_NO_FILE; + } + clst = create_chain(&dp->obj, dp->clust); /* Allocate a cluster */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (dir_clear(fs, clst) != FR_OK) return FR_DISK_ERR; /* Clean up the stretched table */ + if (FF_FS_EXFAT) dp->obj.stat |= 4; /* exFAT: The directory has been stretched */ +#else + if (!stretch) dp->sect = 0; /* (this line is to suppress compiler warning) */ + dp->sect = 0; return FR_NO_FILE; /* Report EOT */ +#endif + } + dp->clust = clst; /* Initialize data for new cluster */ + dp->sect = clst2sect(fs, clst); + } + } + } + dp->dptr = ofs; /* Current entry */ + dp->dir = fs->win + ofs % SS(fs); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Directory handling - Reserve a block of directory entries */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp, /* Pointer to the directory object */ + UINT nent /* Number of contiguous entries to allocate */ +) +{ + FRESULT res; + UINT n; + FATFS *fs = dp->obj.fs; + + + res = dir_sdi(dp, 0); + if (res == FR_OK) { + n = 0; + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; +#if FF_FS_EXFAT + if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) { +#else + if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) { +#endif + if (++n == nent) break; /* A block of contiguous free entries is found */ + } else { + n = 0; /* Not a blank entry. Restart to search */ + } + res = dir_next(dp, 1); + } while (res == FR_OK); /* Next entry with table stretch enabled */ + } + + if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ + return res; +} + +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT: Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ + FATFS* fs, /* Pointer to the fs object */ + const BYTE* dir /* Pointer to the key entry */ +) +{ + DWORD cl; + + cl = ld_word(dir + DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) { + cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16; + } + + return cl; +} + + +#if !FF_FS_READONLY +static void st_clust ( + FATFS* fs, /* Pointer to the fs object */ + BYTE* dir, /* Pointer to the key entry */ + DWORD cl /* Value to be set */ +) +{ + st_word(dir + DIR_FstClusLO, (WORD)cl); + if (fs->fs_type == FS_FAT32) { + st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16)); + } +} +#endif + + + +#if FF_USE_LFN +/*--------------------------------------------------------*/ +/* FAT-LFN: Compare a part of file name with an LFN entry */ +/*--------------------------------------------------------*/ + +static int cmp_lfn ( /* 1:matched, 0:not matched */ + const WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */ + BYTE* dir /* Pointer to the directory entry containing the part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */ + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc != 0) { + if (i >= FF_MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */ + return 0; /* Not matched */ + } + wc = uc; + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; /* Last segment matched but different length */ + + return 1; /* The part of LFN matched */ +} + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT +/*-----------------------------------------------------*/ +/* FAT-LFN: Pick a part of file name from an LFN entry */ +/*-----------------------------------------------------*/ + +static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ + WCHAR* lfnbuf, /* Pointer to the LFN working buffer */ + BYTE* dir /* Pointer to the LFN entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO is 0 */ + + i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc != 0) { + if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */ + if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; /* The part of LFN is valid */ +} +#endif + + +#if !FF_FS_READONLY +/*-----------------------------------------*/ +/* FAT-LFN: Create an entry of LFN entries */ +/*-----------------------------------------*/ + +static void put_lfn ( + const WCHAR* lfn, /* Pointer to the LFN */ + BYTE* dir, /* Pointer to the LFN entry to be created */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* Checksum of the corresponding SFN */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set checksum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + st_word(dir + LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN working buffer */ + s = wc = 0; + do { + if (wc != 0xFFFF) wc = lfn[i++]; /* Get an effective character */ + st_word(dir + LfnOfs[s], wc); /* Put it */ + if (wc == 0) wc = 0xFFFF; /* Padding characters for left locations */ + } while (++s < 13); + if (wc == 0xFFFF || !lfn[i]) ord |= LLEF; /* Last LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_LFN */ + + + +#if FF_USE_LFN && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Create a Numbered SFN */ +/*-----------------------------------------------------------------------*/ + +static void gen_numname ( + BYTE* dst, /* Pointer to the buffer to store numbered SFN */ + const BYTE* src, /* Pointer to SFN */ + const WCHAR* lfn, /* Pointer to LFN */ + UINT seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + WCHAR wc; + DWORD sr; + + + mem_cpy(dst, src, 11); + + if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */ + sr = seq; + while (*lfn) { /* Create a CRC as hash value */ + wc = *lfn++; + for (i = 0; i < 16; i++) { + sr = (sr << 1) + (wc & 1); + wc >>= 1; + if (sr & 0x10000) sr ^= 0x11021; + } + } + seq = (UINT)sr; + } + + /* itoa (hexdecimal) */ + i = 7; + do { + c = (BYTE)((seq % 16) + '0'); + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } while (seq); + ns[i] = '~'; + + /* Append the number to the SFN body */ + for (j = 0; j < i && dst[j] != ' '; j++) { + if (dbc_1st(dst[j])) { + if (j == i - 1) break; + j++; + } + } + do { + dst[j++] = (i < 8) ? ns[i++] : ' '; + } while (j < 8); +} +#endif /* FF_USE_LFN && !FF_FS_READONLY */ + + + +#if FF_USE_LFN +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Calculate checksum of an SFN entry */ +/*-----------------------------------------------------------------------*/ + +static BYTE sum_sfn ( + const BYTE* dir /* Pointer to the SFN entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do { + sum = (sum >> 1) + (sum << 7) + *dir++; + } while (--n); + return sum; +} + +#endif /* FF_USE_LFN */ + + + +#if FF_FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* exFAT: Checksum */ +/*-----------------------------------------------------------------------*/ + +static WORD xdir_sum ( /* Get checksum of the directoly entry block */ + const BYTE* dir /* Directory entry block to be calculated */ +) +{ + UINT i, szblk; + WORD sum; + + + szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; /* Number of bytes of the entry block */ + for (i = sum = 0; i < szblk; i++) { + if (i == XDIR_SetSum) { /* Skip 2-byte sum field */ + i++; + } else { + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; + } + } + return sum; +} + + + +static WORD xname_sum ( /* Get check sum (to be used as hash) of the file name */ + const WCHAR* name /* File name to be calculated */ +) +{ + WCHAR chr; + WORD sum = 0; + + + while ((chr = *name++) != 0) { + chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be up-case converted */ + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); + } + return sum; +} + + +#if !FF_FS_READONLY && FF_USE_MKFS +static DWORD xsum32 ( /* Returns 32-bit checksum */ + BYTE dat, /* Byte to be calculated (byte-by-byte processing) */ + DWORD sum /* Previous sum value */ +) +{ + sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; + return sum; +} +#endif + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 +/*------------------------------------------------------*/ +/* exFAT: Get object information from a directory block */ +/*------------------------------------------------------*/ + +static void get_xfileinfo ( + BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */ + FILINFO* fno /* Buffer to store the extracted file information */ +) +{ + WCHAR wc, hs; + UINT di, si, nc; + + /* Get file name from the entry block */ + si = SZDIRE * 2; /* 1st C1 entry */ + nc = 0; hs = 0; di = 0; + while (nc < dirb[XDIR_NumName]) { + if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */ + if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ + wc = ld_word(dirb + si); si += 2; nc++; /* Get a character */ + if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ + hs = wc; continue; /* Get low surrogate */ + } + wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */ + if (wc == 0) { di = 0; break; } /* Buffer overflow or wrong encoding? */ + di += wc; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ + fno->fname[di] = 0; /* Terminate the name */ + fno->altname[0] = 0; /* exFAT does not support SFN */ + + fno->fattrib = dirb[XDIR_Attr]; /* Attribute */ + fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */ + fno->ftime = ld_word(dirb + XDIR_ModTime + 0); /* Time */ + fno->fdate = ld_word(dirb + XDIR_ModTime + 2); /* Date */ +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ + + +/*-----------------------------------*/ +/* exFAT: Get a directry entry block */ +/*-----------------------------------*/ + +static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ + DIR* dp /* Reading direcotry object pointing top of the entry block to load */ +) +{ + FRESULT res; + UINT i, sz_ent; + BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */ + + + /* Load 85 entry */ + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR; /* Invalid order */ + mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE); + sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE; + if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR; + + /* Load C0 entry */ + res = dir_next(dp, 0); + if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR; /* Invalid order */ + mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE); + if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR; + + /* Load C1 entries */ + i = 2 * SZDIRE; /* C1 offset to load */ + do { + res = dir_next(dp, 0); + if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR; /* Invalid order */ + if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE); + } while ((i += SZDIRE) < sz_ent); + + /* Sanity check (do it for only accessible object) */ + if (i <= MAXDIRB(FF_MAX_LFN)) { + if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR; + } + return FR_OK; +} + + +/*------------------------------------------------------------------*/ +/* exFAT: Initialize object allocation info with loaded entry block */ +/*------------------------------------------------------------------*/ + +static void init_alloc_info ( + FATFS* fs, /* Filesystem object */ + FFOBJID* obj /* Object allocation information to be initialized */ +) +{ + obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Start cluster */ + obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */ + obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; /* Allocation status */ + obj->n_frag = 0; /* No last fragment info */ +} + + + +#if !FF_FS_READONLY || FF_FS_RPATH != 0 +/*------------------------------------------------*/ +/* exFAT: Load the object's directory entry block */ +/*------------------------------------------------*/ + +static FRESULT load_obj_xdir ( + DIR* dp, /* Blank directory object to be used to access containing direcotry */ + const FFOBJID* obj /* Object with its containing directory information */ +) +{ + FRESULT res; + + /* Open object containing directory */ + dp->obj.fs = obj->fs; + dp->obj.sclust = obj->c_scl; + dp->obj.stat = (BYTE)obj->c_size; + dp->obj.objsize = obj->c_size & 0xFFFFFF00; + dp->obj.n_frag = 0; + dp->blk_ofs = obj->c_ofs; + + res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ + if (res == FR_OK) { + res = load_xdir(dp); /* Load the object's entry block */ + } + return res; +} +#endif + + +#if !FF_FS_READONLY +/*----------------------------------------*/ +/* exFAT: Store the directory entry block */ +/*----------------------------------------*/ + +static FRESULT store_xdir ( + DIR* dp /* Pointer to the direcotry object */ +) +{ + FRESULT res; + UINT nent; + BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */ + + /* Create set sum */ + st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); + nent = dirb[XDIR_NumSec] + 1; + + /* Store the direcotry entry block to the directory */ + res = dir_sdi(dp, dp->blk_ofs); + while (res == FR_OK) { + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) break; + mem_cpy(dp->dir, dirb, SZDIRE); + dp->obj.fs->wflag = 1; + if (--nent == 0) break; + dirb += SZDIRE; + res = dir_next(dp, 0); + } + return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR; +} + + + +/*-------------------------------------------*/ +/* exFAT: Create a new directory enrty block */ +/*-------------------------------------------*/ + +static void create_xdir ( + BYTE* dirb, /* Pointer to the direcotry entry block buffer */ + const WCHAR* lfn /* Pointer to the object name */ +) +{ + UINT i; + BYTE nc1, nlen; + WCHAR wc; + + + /* Create 85,C0 entry */ + mem_set(dirb, 0, 2 * SZDIRE); + dirb[0 * SZDIRE + XDIR_Type] = 0x85; /* 85 entry */ + dirb[1 * SZDIRE + XDIR_Type] = 0xC0; /* C0 entry */ + + /* Create C1 entries */ + i = SZDIRE * 2; /* Top of C1 entries */ + nlen = nc1 = 0; wc = 1; + do { + dirb[i++] = 0xC1; dirb[i++] = 0; /* Entry type C1 */ + do { /* Fill name field */ + if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */ + st_word(dirb + i, wc); /* Store it */ + i += 2; + } while (i % SZDIRE != 0); + nc1++; + } while (lfn[nlen]); /* Fill next entry if any char follows */ + + dirb[XDIR_NumName] = nlen; /* Set name length */ + dirb[XDIR_NumSec] = 1 + nc1; /* Set secondary count (C0 + C1s) */ + st_word(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_FS_EXFAT */ + + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ + +#define dir_read_file(dp) dir_read(dp, 0) +#define dir_read_label(dp) dir_read(dp, 1) + +static FRESULT dir_read ( + DIR* dp, /* Pointer to the directory object */ + int vol /* Filtered by 0:file/directory or 1:volume label */ +) +{ + FRESULT res = FR_NO_FILE; + FATFS *fs = dp->obj.fs; + BYTE a, c; +#if FF_USE_LFN + BYTE ord = 0xFF, sum = 0xFF; +#endif + + while (dp->sect) { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + c = dp->dir[DIR_Name]; /* Test for the entry type */ + if (c == 0) { + res = FR_NO_FILE; break; /* Reached to end of the directory */ + } +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + if (FF_USE_LABEL && vol) { + if (c == 0x83) break; /* Volume label entry? */ + } else { + if (c == 0x85) { /* Start of the file entry block? */ + dp->blk_ofs = dp->dptr; /* Get location of the block */ + res = load_xdir(dp); /* Load the entry block */ + if (res == FR_OK) { + dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK; /* Get attribute */ + } + break; + } + } + } else +#endif + { /* On the FAT/FAT32 volume */ + dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ +#if FF_USE_LFN /* LFN configuration */ + if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (c & LLEF) { /* Is it start of an LFN sequence? */ + sum = dp->dir[LDIR_Chksum]; + c &= (BYTE)~LLEF; ord = c; + dp->blk_ofs = dp->dptr; + } + /* Check LFN validity and capture it */ + ord = (c == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } else { /* An SFN entry is found */ + if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */ + dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */ + } + break; + } + } +#else /* Non LFN configuration */ + if (c != DDEM && c != '.' && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */ + break; + } +#endif + } + res = dir_next(dp, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dp->sect = 0; /* Terminate the read operation on error or EOT */ + return res; +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_USE_LABEL || FF_FS_RPATH >= 2 */ + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp /* Pointer to the directory object with the file name */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; + BYTE c; +#if FF_USE_LFN + BYTE a, ord, sum; +#endif + + res = dir_sdi(dp, 0); /* Rewind directory object */ + if (res != FR_OK) return res; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + BYTE nc; + UINT di, ni; + WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ + + while ((res = dir_read_file(dp)) == FR_OK) { /* Read an item */ +#if FF_MAX_LFN < 255 + if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */ +#endif + if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ + for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare the name */ + if ((di % SZDIRE) == 0) di += 2; + if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; + } + if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */ + } + return res; + } +#endif + /* On the FAT/FAT32 volume */ +#if FF_USE_LFN + ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ +#endif + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + c = dp->dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if FF_USE_LFN /* LFN configuration */ + dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; + if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (!(dp->fn[NSFLAG] & NS_NOLFN)) { + if (c & LLEF) { /* Is it start of LFN sequence? */ + sum = dp->dir[LDIR_Chksum]; + c &= (BYTE)~LLEF; ord = c; /* LFN start order */ + dp->blk_ofs = dp->dptr; /* Start offset of LFN */ + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } + } else { /* An SFN entry is found */ + if (ord == 0 && sum == sum_sfn(dp->dir)) break; /* LFN matched? */ + if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */ + ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } + } +#else /* Non LFN configuration */ + dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK; + if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */ +#endif + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + + return res; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ + DIR* dp /* Target directory with object name to be created */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if FF_USE_LFN /* LFN configuration */ + UINT n, nlen, nent; + BYTE sn[12], sum; + + + if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */ + for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ + res = dir_alloc(dp, nent); /* Allocate entries */ + if (res != FR_OK) return res; + dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */ + + if (dp->obj.stat & 4) { /* Has the directory been stretched? */ + dp->obj.stat &= ~4; + res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */ + if (res != FR_OK) return res; + res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */ + if (res != FR_OK) return res; + if (dp->obj.sclust != 0) { /* Is it a sub directory? */ + DIR dj; + + res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */ + if (res != FR_OK) return res; + dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ + st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */ + st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); + fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; + res = store_xdir(&dj); /* Store the object status */ + if (res != FR_OK) return res; + } + } + + create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ + return FR_OK; + } +#endif + /* On the FAT/FAT32 volume */ + mem_cpy(sn, dp->fn, 12); + if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ + dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */ + res = dir_find(dp); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + dp->fn[NSFLAG] = sn[NSFLAG]; + } + + /* Create an SFN with/without LFNs. */ + nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1; /* Number of entries to allocate */ + res = dir_alloc(dp, nent); /* Allocate entries */ + if (res == FR_OK && --nent) { /* Set LFN entry if needed */ + res = dir_sdi(dp, dp->dptr - nent * SZDIRE); + if (res == FR_OK) { + sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */ + do { /* Store LFN entries in bottom first */ + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum); + fs->wflag = 1; + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK && --nent); + } + } + +#else /* Non LFN configuration */ + res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ + +#endif + + /* Set SFN entry */ + if (res == FR_OK) { + res = move_window(fs, dp->sect); + if (res == FR_OK) { + mem_set(dp->dir, 0, SZDIRE); /* Clean the entry */ + mem_cpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */ +#if FF_USE_LFN + dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + fs->wflag = 1; + } + } + + return res; +} + +#endif /* !FF_FS_READONLY */ + + + +#if !FF_FS_READONLY && FF_FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ + DIR* dp /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if FF_USE_LFN /* LFN configuration */ + DWORD last = dp->dptr; + + res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs); /* Goto top of the entry block if LFN is exist */ + if (res == FR_OK) { + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + dp->dir[XDIR_Type] &= 0x7F; /* Clear the entry InUse flag. */ + } else { /* On the FAT/FAT32 volume */ + dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'. */ + } + fs->wflag = 1; + if (dp->dptr >= last) break; /* If reached last entry then all entries of the object has been deleted. */ + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } +#else /* Non LFN configuration */ + + res = move_window(fs, dp->sect); + if (res == FR_OK) { + dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'.*/ + fs->wflag = 1; + } +#endif + + return res; +} + +#endif /* !FF_FS_READONLY && FF_FS_MINIMIZE == 0 */ + + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ + +static void get_fileinfo ( + DIR* dp, /* Pointer to the directory object */ + FILINFO* fno /* Pointer to the file information to be filled */ +) +{ + UINT si, di; +#if FF_USE_LFN + WCHAR wc, hs; + FATFS *fs = dp->obj.fs; +#else + TCHAR c; +#endif + + + fno->fname[0] = 0; /* Invaidate file info */ + if (dp->sect == 0) return; /* Exit if read pointer has reached end of directory */ + +#if FF_USE_LFN /* LFN configuration */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + get_xfileinfo(fs->dirbuf, fno); + return; + } else +#endif + { /* On the FAT/FAT32 volume */ + if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */ + si = di = hs = 0; + while (fs->lfnbuf[si] != 0) { + wc = fs->lfnbuf[si++]; /* Get an LFN character (UTF-16) */ + if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ + hs = wc; continue; /* Get low surrogate */ + } + wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in UTF-16 or UTF-8 encoding */ + if (wc == 0) { di = 0; break; } /* Invalid char or buffer overflow? */ + di += wc; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + fno->fname[di] = 0; /* Terminate the LFN (null string means LFN is invalid) */ + } + } + + si = di = 0; + while (si < 11) { /* Get SFN from SFN entry */ + wc = dp->dir[si++]; /* Get a char */ + if (wc == ' ') continue; /* Skip padding spaces */ + if (wc == RDDEM) wc = DDEM; /* Restore replaced DDEM character */ + if (si == 9 && di < FF_SFN_BUF) fno->altname[di++] = '.'; /* Insert a . if extension is exist */ +#if FF_LFN_UNICODE >= 1 /* Unicode output */ + if (dbc_1st((BYTE)wc) && si != 8 && si != 11 && dbc_2nd(dp->dir[si])) { /* Make a DBC if needed */ + wc = wc << 8 | dp->dir[si++]; + } + wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */ + if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */ + wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in Unicode */ + if (wc == 0) { di = 0; break; } /* Buffer overflow? */ + di += wc; +#else /* ANSI/OEM output */ + fno->altname[di++] = (TCHAR)wc; /* Store it without any conversion */ +#endif + } + fno->altname[di] = 0; /* Terminate the SFN (null string means SFN is invalid) */ + + if (fno->fname[0] == 0) { /* If LFN is invalid, altname[] needs to be copied to fname[] */ + if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */ + fno->fname[di++] = '?'; + } else { + for (si = di = 0; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */ + wc = (WCHAR)fno->altname[si]; + if (IsUpper(wc) && (dp->dir[DIR_NTres] & ((si >= 9) ? NS_EXT : NS_BODY))) wc += 0x20; + fno->fname[di] = (TCHAR)wc; + } + } + fno->fname[di] = 0; /* Terminate the LFN */ + if (!dp->dir[DIR_NTres]) fno->altname[0] = 0; /* Altname is not needed if neither LFN nor case info is exist. */ + } + +#else /* Non-LFN configuration */ + si = di = 0; + while (si < 11) { /* Copy name body and extension */ + c = (TCHAR)dp->dir[si++]; + if (c == ' ') continue; /* Skip padding spaces */ + if (c == RDDEM) c = DDEM; /* Restore replaced DDEM character */ + if (si == 9) fno->fname[di++] = '.';/* Insert a . if extension is exist */ + fno->fname[di++] = c; + } + fno->fname[di] = 0; +#endif + + fno->fattrib = dp->dir[DIR_Attr]; /* Attribute */ + fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */ + fno->ftime = ld_word(dp->dir + DIR_ModTime + 0); /* Time */ + fno->fdate = ld_word(dp->dir + DIR_ModTime + 2); /* Date */ +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ + + + +#if FF_USE_FIND && FF_FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Pattern matching */ +/*-----------------------------------------------------------------------*/ + +static DWORD get_achar ( /* Get a character and advances ptr */ + const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ +) +{ + DWORD chr; + + +#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode input */ + chr = tchar2uni(ptr); + if (chr == 0xFFFFFFFF) chr = 0; /* Wrong UTF encoding is recognized as end of the string */ + chr = ff_wtoupper(chr); + +#else /* ANSI/OEM input */ + chr = (BYTE)*(*ptr)++; /* Get a byte */ + if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */ +#if FF_CODE_PAGE == 0 + if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#elif FF_CODE_PAGE < 900 + if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#endif +#if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900 + if (dbc_1st((BYTE)chr)) { /* Get DBC 2nd byte if needed */ + chr = dbc_2nd((BYTE)**ptr) ? chr << 8 | (BYTE)*(*ptr)++ : 0; + } +#endif + +#endif + return chr; +} + + +static int pattern_matching ( /* 0:not matched, 1:matched */ + const TCHAR* pat, /* Matching pattern */ + const TCHAR* nam, /* String to be tested */ + int skip, /* Number of pre-skip chars (number of ?s) */ + int inf /* Infinite search (* specified) */ +) +{ + const TCHAR *pp, *np; + DWORD pc, nc; + int nm, nx; + + + while (skip--) { /* Pre-skip name chars */ + if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */ + } + if (*pat == 0 && inf) return 1; /* (short circuit) */ + + do { + pp = pat; np = nam; /* Top of pattern and name to match */ + for (;;) { + if (*pp == '?' || *pp == '*') { /* Wildcard? */ + nm = nx = 0; + do { /* Analyze the wildcard block */ + if (*pp++ == '?') nm++; else nx = 1; + } while (*pp == '?' || *pp == '*'); + if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */ + nc = *np; break; /* Branch mismatched */ + } + pc = get_achar(&pp); /* Get a pattern char */ + nc = get_achar(&np); /* Get a name char */ + if (pc != nc) break; /* Branch mismatched? */ + if (pc == 0) return 1; /* Branch matched? (matched at end of both strings) */ + } + get_achar(&nam); /* nam++ */ + } while (inf && nc); /* Retry until end of name if infinite search is specified */ + + return 0; +} + +#endif /* FF_USE_FIND && FF_FS_MINIMIZE <= 1 */ + + + +/*-----------------------------------------------------------------------*/ +/* Pick a top segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ + DIR* dp, /* Pointer to the directory object */ + const TCHAR** path /* Pointer to pointer to the segment in the path string */ +) +{ +#if FF_USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR wc, *lfn; + DWORD uc; + UINT i, ni, si, di; + const TCHAR *p; + + + /* Create LFN into LFN working buffer */ + p = *path; lfn = dp->obj.fs->lfnbuf; di = 0; + for (;;) { + uc = tchar2uni(&p); /* Get a character */ + if (uc == 0xFFFFFFFF) return FR_INVALID_NAME; /* Invalid code or UTF decode error */ + if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16); /* Store high surrogate if needed */ + wc = (WCHAR)uc; + if (wc < ' ' || wc == '/' || wc == '\\') break; /* Break if end of the path or a separator is found */ + if (wc < 0x80 && chk_chr("\"*:<>\?|\x7F", wc)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */ + if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */ + lfn[di++] = wc; /* Store the Unicode character */ + } + while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */ + *path = p; /* Return pointer to the next segment */ + cf = (wc < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ + +#if FF_FS_RPATH != 0 + if ((di == 1 && lfn[di - 1] == '.') || + (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */ + lfn[di] = 0; + for (i = 0; i < 11; i++) { /* Create dot name for SFN entry */ + dp->fn[i] = (i < di) ? '.' : ' '; + } + dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) { /* Snip off trailing spaces and dots if exist */ + wc = lfn[di - 1]; + if (wc != ' ' && wc != '.') break; + di--; + } + lfn[di] = 0; /* LFN is created into the working buffer */ + if (di == 0) return FR_INVALID_NAME; /* Reject null name */ + + /* Create SFN in directory form */ + for (si = 0; lfn[si] == ' '; si++) ; /* Remove leading spaces */ + if (si > 0 || lfn[si] == '.') cf |= NS_LOSS | NS_LFN; /* Is there any leading space or dot? */ + while (di > 0 && lfn[di - 1] != '.') di--; /* Find last dot (di<=si: no extension) */ + + mem_set(dp->fn, ' ', 11); + i = b = 0; ni = 8; + for (;;) { + wc = lfn[si++]; /* Get an LFN character */ + if (wc == 0) break; /* Break on end of the LFN */ + if (wc == ' ' || (wc == '.' && si != di)) { /* Remove embedded spaces and dots */ + cf |= NS_LOSS | NS_LFN; + continue; + } + + if (i >= ni || si == di) { /* End of field? */ + if (ni == 11) { /* Name extension overflow? */ + cf |= NS_LOSS | NS_LFN; + break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Name body overflow? */ + if (si > di) break; /* No name extension? */ + si = di; i = 8; ni = 11; b <<= 2; /* Enter name extension */ + continue; + } + + if (wc >= 0x80) { /* Is this a non-ASCII character? */ + cf |= NS_LFN; /* LFN entry needs to be created */ +#if FF_CODE_PAGE == 0 + if (ExCvt) { /* At SBCS */ + wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ + if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ + } else { /* At DBCS */ + wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ + } +#elif FF_CODE_PAGE < 900 /* SBCS cfg */ + wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ + if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ +#else /* DBCS cfg */ + wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */ +#endif + } + + if (wc >= 0x100) { /* Is this a DBC? */ + if (i >= ni - 1) { /* Field overflow? */ + cf |= NS_LOSS | NS_LFN; + i = ni; continue; /* Next field */ + } + dp->fn[i++] = (BYTE)(wc >> 8); /* Put 1st byte */ + } else { /* SBC */ + if (wc == 0 || chk_chr("+,;=[]", wc)) { /* Replace illegal characters for SFN if needed */ + wc = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } else { + if (IsUpper(wc)) { /* ASCII upper case? */ + b |= 2; + } + if (IsLower(wc)) { /* ASCII lower case? */ + b |= 1; wc -= 0x20; + } + } + } + dp->fn[i++] = (BYTE)wc; + } + + if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + + if (ni == 8) b <<= 2; /* Shift capital flags if no extension */ + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; /* LFN entry needs to be created if composite capitals */ + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */ + if (b & 0x01) cf |= NS_EXT; /* NT flag (Extension has small capital letters only) */ + if (b & 0x04) cf |= NS_BODY; /* NT flag (Body has small capital letters only) */ + } + + dp->fn[NSFLAG] = cf; /* SFN is created into dp->fn[] */ + + return FR_OK; + + +#else /* FF_USE_LFN : Non-LFN configuration */ + BYTE c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + p = *path; sfn = dp->fn; + mem_set(sfn, ' ', 11); + si = i = 0; ni = 8; +#if FF_FS_RPATH != 0 + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; + *path = p + si; /* Return pointer to the next segment */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */ + return FR_OK; + } +#endif + for (;;) { + c = (BYTE)p[si++]; /* Get a byte */ + if (c <= ' ') break; /* Break if end of the path name */ + if (c == '/' || c == '\\') { /* Break if a separator is found */ + while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */ + break; + } + if (c == '.' || i >= ni) { /* End of body or field overflow? */ + if (ni == 11 || c != '.') return FR_INVALID_NAME; /* Field overflow or invalid dot? */ + i = 8; ni = 11; /* Enter file extension field */ + continue; + } +#if FF_CODE_PAGE == 0 + if (ExCvt && c >= 0x80) { /* Is SBC extended character? */ + c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ + } +#elif FF_CODE_PAGE < 900 + if (c >= 0x80) { /* Is SBC extended character? */ + c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ + } +#endif + if (dbc_1st(c)) { /* Check if it is a DBC 1st byte */ + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */ + sfn[i++] = c; + sfn[i++] = d; + } else { /* SBC */ + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */ + if (IsLower(c)) c -= 0x20; /* To upper */ + sfn[i++] = c; + } + } + *path = p + si; /* Return pointer to the next segment */ + if (i == 0) return FR_INVALID_NAME; /* Reject nul string */ + + if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ + + return FR_OK; +#endif /* FF_USE_LFN */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR* dp, /* Directory object to return last directory and found object */ + const TCHAR* path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE ns; + FATFS *fs = dp->obj.fs; + + +#if FF_FS_RPATH != 0 + if (*path != '/' && *path != '\\') { /* Without heading separator */ + dp->obj.sclust = fs->cdir; /* Start from current directory */ + } else +#endif + { /* With heading separator */ + while (*path == '/' || *path == '\\') path++; /* Strip heading separator */ + dp->obj.sclust = 0; /* Start from root directory */ + } +#if FF_FS_EXFAT + dp->obj.n_frag = 0; /* Invalidate last fragment counter of the object */ +#if FF_FS_RPATH != 0 + if (fs->fs_type == FS_EXFAT && dp->obj.sclust) { /* exFAT: Retrieve the sub-directory's status */ + DIR dj; + + dp->obj.c_scl = fs->cdc_scl; + dp->obj.c_size = fs->cdc_size; + dp->obj.c_ofs = fs->cdc_ofs; + res = load_obj_xdir(&dj, &dp->obj); + if (res != FR_OK) return res; + dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize); + dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + } +#endif +#endif + + if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */ + dp->fn[NSFLAG] = NS_NONAME; + res = dir_sdi(dp, 0); + + } else { /* Follow path */ + for (;;) { + res = create_name(dp, &path); /* Get a segment name of the path */ + if (res != FR_OK) break; + res = dir_find(dp); /* Find an object with the segment name */ + ns = dp->fn[NSFLAG]; + if (res != FR_OK) { /* Failed to find the object */ + if (res == FR_NO_FILE) { /* Object is not found */ + if (FF_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, stay there */ + if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ + dp->fn[NSFLAG] = NS_NONAME; + res = FR_OK; + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ + } + } + break; + } + if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ + /* Get into the sub-directory */ + if (!(dp->obj.attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */ + res = FR_NO_PATH; break; + } +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* Save containing directory information for next dir */ + dp->obj.c_scl = dp->obj.sclust; + dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; + dp->obj.c_ofs = dp->blk_ofs; + init_alloc_info(fs, &dp->obj); /* Open next directory */ + } else +#endif + { + dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs)); /* Open next directory */ + } + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get logical drive number from path name */ +/*-----------------------------------------------------------------------*/ + +static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive number or null pointer) */ + const TCHAR** path /* Pointer to pointer to the path name */ +) +{ + const TCHAR *tp, *tt; + TCHAR tc; + int i, vol = -1; +#if FF_STR_VOLUME_ID /* Find string volume ID */ + const char *sp; + char c; +#endif + + tt = tp = *path; + if (!tp) return vol; /* Invalid path name? */ + do tc = *tt++; while ((UINT)tc >= (FF_USE_LFN ? ' ' : '!') && tc != ':'); /* Find a colon in the path */ + + if (tc == ':') { /* DOS/Windows style volume ID? */ + i = FF_VOLUMES; + if (IsDigit(*tp) && tp + 2 == tt) { /* Is there a numeric volume ID + colon? */ + i = (int)*tp - '0'; /* Get the LD number */ + } +#if FF_STR_VOLUME_ID == 1 /* Arbitrary string is enabled */ + else { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *tp++; + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ + } +#endif + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tt; /* Snip the drive prefix off */ + } + return vol; + } +#if FF_STR_VOLUME_ID == 2 /* Unix style volume ID is enabled */ + if (*tp == '/') { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *(++tp); + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || (tc != '/' && (UINT)tc >= (FF_USE_LFN ? ' ' : '!'))) && ++i < FF_VOLUMES); /* Repeat for each ID until pattern match */ + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tp; /* Snip the drive prefix off */ + return vol; + } + } +#endif + /* No drive prefix is found */ +#if FF_FS_RPATH != 0 + vol = CurrVol; /* Default drive is current drive */ +#else + vol = 0; /* Default drive is 0 */ +#endif + return vol; /* Return the default drive */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT VBR */ +/*-----------------------------------------------------------------------*/ + +static BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ +) +{ + fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ + if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */ + + if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always here regardless of the sector size) */ + +#if FF_FS_EXFAT + if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* Check if exFAT VBR */ +#endif + if (fs->win[BS_JmpBoot] == 0xE9 || fs->win[BS_JmpBoot] == 0xEB || fs->win[BS_JmpBoot] == 0xE8) { /* Valid JumpBoot code? */ + if (!mem_cmp(fs->win + BS_FilSysType, "FAT", 3)) return 0; /* Is it an FAT VBR? */ + if (!mem_cmp(fs->win + BS_FilSysType32, "FAT32", 5)) return 0; /* Is it an FAT32 VBR? */ + } + return 2; /* Valid BS but not FAT */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Determine logical drive number and mount the volume if needed */ +/*-----------------------------------------------------------------------*/ + +static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */ + const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ + FATFS** rfs, /* Pointer to pointer to the found filesystem object */ + BYTE mode /* !=0: Check write protection for write access */ +) +{ + BYTE fmt, *pt; + int vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; + WORD nrsv; + FATFS *fs; + UINT i; + + + /* Get logical drive number */ + *rfs = 0; + vol = get_ldnumber(path); + if (vol < 0) return FR_INVALID_DRIVE; + + /* Check if the filesystem object is valid or not */ + fs = FatFs[vol]; /* Get pointer to the filesystem object */ + if (!fs) return FR_NOT_ENABLED; /* Is the filesystem object available? */ +#if FF_FS_REENTRANT + if (!lock_fs(fs)) return FR_TIMEOUT; /* Lock the volume */ +#endif + *rfs = fs; /* Return pointer to the filesystem object */ + + mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ + if (fs->fs_type != 0) { /* If the volume has been mounted */ + stat = disk_status(fs->pdrv); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ + if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ + return FR_WRITE_PROTECTED; + } + return FR_OK; /* The filesystem object is valid */ + } + } + + /* The filesystem object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */ + + fs->fs_type = 0; /* Clear the filesystem object */ + fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ + if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + } + if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; + } +#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ + if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; + if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; +#endif + + /* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */ + bsect = 0; + fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */ + if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */ + for (i = 0; i < 4; i++) { /* Get partition offset */ + pt = fs->win + (MBR_Table + i * SZ_PTE); + br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0; + } + i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */ + if (i != 0) i--; + do { /* Find an FAT volume */ + bsect = br[i]; + fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ + } while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4); + } + if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ + if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* An FAT volume is found (bsect). Following code initializes the filesystem object */ + +#if FF_FS_EXFAT + if (fmt == 1) { + QWORD maxlba; + + for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ + if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; + + if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ + + if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ + return FR_NO_FILESYSTEM; + } + + maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */ + if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */ + + fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ + + fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ + if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ + + fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ + if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */ + + nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ + if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ + fs->n_fatent = nclst + 2; + + /* Boundaries and Limits */ + fs->volbase = bsect; + fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); + fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); + if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); + + /* Check if bitmap location is in assumption (at the first cluster) */ + if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR; + for (i = 0; i < SS(fs); i += SZDIRE) { + if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */ + } + if (i == SS(fs)) return FR_NO_FILESYSTEM; +#if !FF_FS_READONLY + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ +#endif + fmt = FS_EXFAT; /* FAT sub-type */ + } else +#endif /* FF_FS_EXFAT */ + { + if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ + + fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ + if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ + if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= fs->n_fats; /* Number of sectors for FAT area */ + + fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ + if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + + fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ + + tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ + if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); + + nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = 0; + if (nclst <= MAX_FAT32) fmt = FS_FAT32; + if (nclst <= MAX_FAT16) fmt = FS_FAT16; + if (nclst <= MAX_FAT12) fmt = FS_FAT12; + if (fmt == 0) return FR_NO_FILESYSTEM; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->volbase = bsect; /* Volume start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + fs->database = bsect + sysect; /* Data start sector */ + if (fmt == FS_FAT32) { + if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ + if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ + } else { + if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */ + +#if !FF_FS_READONLY + /* Get FSInfo if available */ + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ + fs->fsi_flag = 0x80; +#if (FF_FS_NOFSINFO & 3) != 3 + if (fmt == FS_FAT32 /* Allow to update FSInfo only if BPB_FSInfo32 == 1 */ + && ld_word(fs->win + BPB_FSInfo32) == 1 + && move_window(fs, bsect + 1) == FR_OK) + { + fs->fsi_flag = 0; + if (ld_word(fs->win + BS_55AA) == 0xAA55 /* Load FSInfo data if available */ + && ld_dword(fs->win + FSI_LeadSig) == 0x41615252 + && ld_dword(fs->win + FSI_StrucSig) == 0x61417272) + { +#if (FF_FS_NOFSINFO & 1) == 0 + fs->free_clst = ld_dword(fs->win + FSI_Free_Count); +#endif +#if (FF_FS_NOFSINFO & 2) == 0 + fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free); +#endif + } + } +#endif /* (FF_FS_NOFSINFO & 3) != 3 */ +#endif /* !FF_FS_READONLY */ + } + + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* Volume mount ID */ +#if FF_USE_LFN == 1 + fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ +#if FF_FS_EXFAT + fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */ +#endif +#endif +#if FF_FS_RPATH != 0 + fs->cdir = 0; /* Initialize current directory */ +#endif +#if FF_FS_LOCK != 0 /* Clear file lock semaphores */ + clear_lock(fs); +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/directory object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ + FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ + FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ +) +{ + FRESULT res = FR_INVALID_OBJECT; + + + if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */ +#if FF_FS_REENTRANT + if (lock_fs(obj->fs)) { /* Obtain the filesystem object */ + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + res = FR_OK; + } else { + unlock_fs(obj->fs, FR_OK); + } + } else { + res = FR_TIMEOUT; + } +#else + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + res = FR_OK; + } +#endif + } + *rfs = (res == FR_OK) ? obj->fs : 0; /* Corresponding filesystem object */ + return res; +} + + + + +/*--------------------------------------------------------------------------- + + Public Functions (FatFs API) + +----------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mount ( + FATFS* fs, /* Pointer to the filesystem object (NULL:unmount)*/ + const TCHAR* path, /* Logical drive number to be mounted/unmounted */ + BYTE opt /* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */ +) +{ + FATFS *cfs; + int vol; + FRESULT res; + const TCHAR *rp = path; + + + /* Get logical drive number */ + vol = get_ldnumber(&rp); + if (vol < 0) return FR_INVALID_DRIVE; + cfs = FatFs[vol]; /* Pointer to fs object */ + + if (cfs) { +#if FF_FS_LOCK != 0 + clear_lock(cfs); +#endif +#if FF_FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; +#endif + cfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) { + fs->fs_type = 0; /* Clear new fs object */ +#if FF_FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted later */ + + res = find_volume(&path, &fs, 0); /* Force mounted the volume */ + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL* fp, /* Pointer to the blank file object */ + const TCHAR* path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; +#if !FF_FS_READONLY + DWORD dw, cl, bcs, clst, sc; + FSIZE_t ofs; +#endif + DEF_NAMBUF + + + if (!fp) return FR_INVALID_OBJECT; + + /* Get logical drive number */ + mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND; + res = find_volume(&path, &fs, mode); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ +#if !FF_FS_READONLY /* Read/Write configuration */ + if (res == FR_OK) { + if (dj.fn[NSFLAG] & NS_NONAME) { /* Origin directory itself? */ + res = FR_INVALID_NAME; + } +#if FF_FS_LOCK != 0 + else { + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */ + } +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) { /* There is no file to open, create a new entry */ +#if FF_FS_LOCK != 0 + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + } + mode |= FA_CREATE_ALWAYS; /* File is created */ + } + else { /* Any object with the same name is already existing */ + if (dj.obj.attr & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */ + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate the file if overwrite mode */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + /* Get current allocation info */ + fp->obj.fs = fs; + init_alloc_info(fs, &fp->obj); + /* Set directory entry block initial state */ + mem_set(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */ + mem_set(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */ + fs->dirbuf[XDIR_Attr] = AM_ARC; + st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME()); + fs->dirbuf[XDIR_GenFlags] = 1; + res = store_xdir(&dj); + if (res == FR_OK && fp->obj.sclust != 0) { /* Remove the cluster chain if exist */ + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fs->last_clst = fp->obj.sclust - 1; /* Reuse the cluster hole */ + } + } else +#endif + { + /* Set directory entry initial state */ + cl = ld_clust(fs, dj.dir); /* Get current cluster chain */ + st_dword(dj.dir + DIR_CrtTime, GET_FATTIME()); /* Set created time */ + dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */ + st_clust(fs, dj.dir, 0); /* Reset file allocation info */ + st_dword(dj.dir + DIR_FileSize, 0); + fs->wflag = 1; + if (cl != 0) { /* Remove the cluster chain if exist */ + dw = fs->winsect; + res = remove_chain(&dj.obj, cl, 0); + if (res == FR_OK) { + res = move_window(fs, dw); + fs->last_clst = cl - 1; /* Reuse the cluster hole */ + } + } + } + } + } + else { /* Open an existing file */ + if (res == FR_OK) { /* Is the object exsiting? */ + if (dj.obj.attr & AM_DIR) { /* File open against a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */ + res = FR_DENIED; + } + } + } + } + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED; /* Set file change flag if created or overwritten */ + fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dj.dir; +#if FF_FS_LOCK != 0 + fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */ + if (fp->obj.lockid == 0) res = FR_INT_ERR; +#endif + } +#else /* R/O configuration */ + if (res == FR_OK) { + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it origin directory itself? */ + res = FR_INVALID_NAME; + } else { + if (dj.obj.attr & AM_DIR) { /* Is it a directory? */ + res = FR_NO_FILE; + } + } + } +#endif + + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fp->obj.c_scl = dj.obj.sclust; /* Get containing directory info */ + fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fp->obj.c_ofs = dj.blk_ofs; + init_alloc_info(fs, &fp->obj); + } else +#endif + { + fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */ + fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize); + } +#if FF_USE_FASTSEEK + fp->cltbl = 0; /* Disable fast seek mode */ +#endif + fp->obj.fs = fs; /* Validate the file object */ + fp->obj.id = fs->id; + fp->flag = mode; /* Set file access mode */ + fp->err = 0; /* Clear error flag */ + fp->sect = 0; /* Invalidate current data sector */ + fp->fptr = 0; /* Set file pointer top of the file */ +#if !FF_FS_READONLY +#if !FF_FS_TINY + mem_set(fp->buf, 0, FF_MAX_SS); /* Clear sector buffer */ +#endif + if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */ + fp->fptr = fp->obj.objsize; /* Offset to seek */ + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */ + clst = fp->obj.sclust; /* Follow the cluster chain */ + for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) { + clst = get_fat(&fp->obj, clst); + if (clst <= 1) res = FR_INT_ERR; + if (clst == 0xFFFFFFFF) res = FR_DISK_ERR; + } + fp->clust = clst; + if (res == FR_OK && ofs % SS(fs)) { /* Fill sector buffer if not on the sector boundary */ + if ((sc = clst2sect(fs, clst)) == 0) { + res = FR_INT_ERR; + } else { + fp->sect = sc + (DWORD)(ofs / SS(fs)); +#if !FF_FS_TINY + if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; +#endif + } + } + } +#endif + } + + FREE_NAMBUF(); + } + + if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL* fp, /* Pointer to the file object */ + void* buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT* br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + FSIZE_t remain; + UINT rcnt, cc, csect; + BYTE *rbuff = (BYTE*)buff; + + + *br = 0; /* Clear read byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + remain = fp->obj.objsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr; /* Repeat until btr bytes read */ + btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (csect == 0) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow cluster chain from the origin */ + } else { /* Middle or end of the file */ +#if FF_USE_FASTSEEK + if (fp->cltbl) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } else +#endif + { + clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */ + } + } + if (clst < 2) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clst2sect(fs, fp->clust); /* Get current sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fs); /* When remaining bytes >= sector size, */ + if (cc > 0) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fs->csize) { /* Clip at cluster boundary */ + cc = fs->csize - csect; + } + if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if FF_FS_TINY + if (fs->wflag && fs->winsect - sect < cc) { + mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs)); + } +#else + if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) { + mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs)); + } +#endif +#endif + rcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !FF_FS_TINY + if (fp->sect != sect) { /* Load data sector if not in cache */ +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ + } +#endif + fp->sect = sect; + } + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */ +#if FF_FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#else + mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#endif + } + + LEAVE_FF(fs, FR_OK); +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL* fp, /* Pointer to the file object */ + const void* buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT* bw /* Pointer to number of bytes written */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + UINT wcnt, cc, csect; + const BYTE *wbuff = (const BYTE*)buff; + + + *bw = 0; /* Clear write byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ + if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { + btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); + } + + for ( ; btw; /* Repeat until all data written */ + btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) { + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */ + if (csect == 0) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow from the origin */ + if (clst == 0) { /* If no cluster is allocated, */ + clst = create_chain(&fp->obj, 0); /* create a new cluster chain */ + } + } else { /* On the middle or end of the file */ +#if FF_USE_FASTSEEK + if (fp->cltbl) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } else +#endif + { + clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */ + } +#if FF_FS_TINY + if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ +#else + if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + sect = clst2sect(fs, fp->clust); /* Get current sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fs); /* When remaining bytes >= sector size, */ + if (cc > 0) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fs->csize) { /* Clip at cluster boundary */ + cc = fs->csize - csect; + } + if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if FF_FS_MINIMIZE <= 2 +#if FF_FS_TINY + if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs)); + fs->wflag = 0; + } +#else + if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif +#endif + wcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if FF_FS_TINY + if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */ + if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); + fs->winsect = sect; + } +#else + if (fp->sect != sect && /* Fill sector cache with file data */ + fp->fptr < fp->obj.objsize && + disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { + ABORT(fs, FR_DISK_ERR); + } +#endif + fp->sect = sect; + } + wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */ +#if FF_FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fs->wflag = 1; +#else + mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fp->flag |= FA_DIRTY; +#endif + } + + fp->flag |= FA_MODIFIED; /* Set file change flag */ + + LEAVE_FF(fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD tm; + BYTE *dir; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) { + if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ +#if !FF_FS_TINY + if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + /* Update the directory entry */ + tm = GET_FATTIME(); /* Modified time */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */ + if (res == FR_OK) { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } + if (res == FR_OK) { + DIR dj; + DEF_NAMBUF + + INIT_NAMBUF(fs); + res = load_obj_xdir(&dj, &fp->obj); /* Load directory entry block */ + if (res == FR_OK) { + fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */ + st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); + st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); + st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */ + fs->dirbuf[XDIR_ModTime10] = 0; + st_dword(fs->dirbuf + XDIR_AccTime, 0); + res = store_xdir(&dj); /* Restore it to the directory */ + if (res == FR_OK) { + res = sync_fs(fs); + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + FREE_NAMBUF(); + } + } else +#endif + { + res = move_window(fs, fp->dir_sect); + if (res == FR_OK) { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */ + st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ + st_dword(dir + DIR_ModTime, tm); /* Update modified time */ + st_word(dir + DIR_LstAccDate, 0); + fs->wflag = 1; + res = sync_fs(fs); /* Restore it to the directory */ + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL* fp /* Pointer to the file object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + +#if !FF_FS_READONLY + res = f_sync(fp); /* Flush cached data */ + if (res == FR_OK) +#endif + { + res = validate(&fp->obj, &fs); /* Lock volume */ + if (res == FR_OK) { +#if FF_FS_LOCK != 0 + res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ + if (res == FR_OK) fp->obj.fs = 0; /* Invalidate file object */ +#else + fp->obj.fs = 0; /* Invalidate file object */ +#endif +#if FF_FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + } + return res; +} + + + + +#if FF_FS_RPATH >= 1 +/*-----------------------------------------------------------------------*/ +/* Change Current Directory or Current Drive, Get Current Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chdrive ( + const TCHAR* path /* Drive number to set */ +) +{ + int vol; + + + /* Get logical drive number */ + vol = get_ldnumber(&path); + if (vol < 0) return FR_INVALID_DRIVE; + CurrVol = (BYTE)vol; /* Set it as current volume */ + + return FR_OK; +} + + + +FRESULT f_chdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ +#if FF_STR_VOLUME_ID == 2 + UINT i; +#endif + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it the start directory itself? */ + fs->cdir = dj.obj.sclust; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->cdc_scl = dj.obj.c_scl; + fs->cdc_size = dj.obj.c_size; + fs->cdc_ofs = dj.obj.c_ofs; + } +#endif + } else { + if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ + fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ + fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fs->cdc_ofs = dj.blk_ofs; + } else +#endif + { + fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ + } + } else { + res = FR_NO_PATH; /* Reached but a file */ + } + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; +#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed at Unix style volume ID */ + if (res == FR_OK) { + for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */ + CurrVol = (BYTE)i; + } +#endif + } + + LEAVE_FF(fs, res); +} + + +#if FF_FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR* buff, /* Pointer to the directory path */ + UINT len /* Size of buff in unit of TCHAR */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + UINT i, n; + DWORD ccl; + TCHAR *tp = buff; +#if FF_VOLUMES >= 2 + UINT vl; +#endif +#if FF_STR_VOLUME_ID + const char *vp; +#endif + FILINFO fno; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + + /* Follow parent directories and create the path */ + i = len; /* Bottom of buffer (directory stack base) */ + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) */ + dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ + while ((ccl = dj.obj.sclust) != 0) { /* Repeat while current directory is a sub-directory */ + res = dir_sdi(&dj, 1 * SZDIRE); /* Get parent directory */ + if (res != FR_OK) break; + res = move_window(fs, dj.sect); + if (res != FR_OK) break; + dj.obj.sclust = ld_clust(fs, dj.dir); /* Goto parent directory */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child directory */ + res = dir_read_file(&dj); + if (res != FR_OK) break; + if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; + get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ + for (n = 0; fno.fname[n]; n++) ; /* Name length */ + if (i < n + 1) { /* Insufficient space to store the path name? */ + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) buff[--i] = fno.fname[--n]; /* Stack the name */ + buff[--i] = '/'; + } + } + if (res == FR_OK) { + if (i == len) buff[--i] = '/'; /* Is it the root-directory? */ +#if FF_VOLUMES >= 2 /* Put drive prefix */ + vl = 0; +#if FF_STR_VOLUME_ID >= 1 /* String volume ID */ + for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ; + if (i >= n + 2) { + if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/'; + for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ; + if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':'; + vl++; + } +#else /* Numeric volume ID */ + if (i >= 3) { + *tp++ = (TCHAR)'0' + CurrVol; + *tp++ = (TCHAR)':'; + vl = 2; + } +#endif + if (vl == 0) res = FR_NOT_ENOUGH_CORE; +#endif + /* Add current directory path */ + if (res == FR_OK) { + do *tp++ = buff[i++]; while (i < len); /* Copy stacked path string */ + } + } + FREE_NAMBUF(); + } + + *tp = 0; + LEAVE_FF(fs, res); +} + +#endif /* FF_FS_RPATH >= 2 */ +#endif /* FF_FS_RPATH >= 1 */ + + + +#if FF_FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File Read/Write Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL* fp, /* Pointer to the file object */ + FSIZE_t ofs /* File pointer from top of file */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, bcs, nsect; + FSIZE_t ifptr; +#if FF_USE_FASTSEEK + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; +#endif + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) res = (FRESULT)fp->err; +#if FF_FS_EXFAT && !FF_FS_READONLY + if (res == FR_OK && fs->fs_type == FS_EXFAT) { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } +#endif + if (res != FR_OK) LEAVE_FF(fs, res); + +#if FF_USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->obj.sclust; /* Origin of the chain */ + if (cl != 0) { + do { + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { + pcl = cl; ncl++; + cl = get_fat(&fp->obj, cl); + if (cl <= 1) ABORT(fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + } while (cl == pcl + 1); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) { + *tbl = 0; /* Terminate table */ + } else { + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + } + } else { /* Fast seek */ + if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */ + fp->fptr = ofs; /* Set file pointer */ + if (ofs > 0) { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clst2sect(fs, fp->clust); + if (dsc == 0) ABORT(fs, FR_INT_ERR); + dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1); + if (fp->fptr % SS(fs) && dsc != fp->sect) { /* Refill sector cache if needed */ +#if !FF_FS_TINY +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ +#endif + fp->sect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { +#if FF_FS_EXFAT + if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4 GiB - 1 if at FATxx */ +#endif + if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) { /* In read-only mode, clip offset with the file size */ + ofs = fp->obj.objsize; + } + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs > 0) { + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } else { /* When seek to back cluster, */ + clst = fp->obj.sclust; /* start from the first cluster */ +#if !FF_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(&fp->obj, 0); + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->obj.sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ + ofs -= bcs; fp->fptr += bcs; +#if !FF_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) { /* No FAT chain object needs correct objsize to generate FAT value */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */ + if (clst == 0) { /* Clip file size in case of disk full */ + ofs = 0; break; + } + } else +#endif + { + clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ + } + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); + fp->clust = clst; + } + fp->fptr += ofs; + if (ofs % SS(fs)) { + nsect = clst2sect(fs, clst); /* Current sector */ + if (nsect == 0) ABORT(fs, FR_INT_ERR); + nsect += (DWORD)(ofs / SS(fs)); + } + } + } + if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */ +#if !FF_FS_TINY +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ +#endif + fp->sect = nsect; + } + } + + LEAVE_FF(fs, res); +} + + + +#if FF_FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directory Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + DIR* dp, /* Pointer to directory object to create */ + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + + if (!dp) return FR_INVALID_OBJECT; + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) { + dp->obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(dp, path); /* Follow the path to the directory */ + if (res == FR_OK) { /* Follow completed */ + if (!(dp->fn[NSFLAG] & NS_NONAME)) { /* It is not the origin directory itself */ + if (dp->obj.attr & AM_DIR) { /* This object is a sub-directory */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */ + dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; + dp->obj.c_ofs = dp->blk_ofs; + init_alloc_info(fs, &dp->obj); /* Get object allocation info */ + } else +#endif + { + dp->obj.sclust = ld_clust(fs, dp->dir); /* Get object allocation info */ + } + } else { /* This object is a file */ + res = FR_NO_PATH; + } + } + if (res == FR_OK) { + dp->obj.id = fs->id; + res = dir_sdi(dp, 0); /* Rewind directory */ +#if FF_FS_LOCK != 0 + if (res == FR_OK) { + if (dp->obj.sclust != 0) { + dp->obj.lockid = inc_lock(dp, 0); /* Lock the sub directory */ + if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES; + } else { + dp->obj.lockid = 0; /* Root directory need not to be locked */ + } + } +#endif + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function faild */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Close Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_closedir ( + DIR *dp /* Pointer to the directory object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + + + res = validate(&dp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) { +#if FF_FS_LOCK != 0 + if (dp->obj.lockid) res = dec_lock(dp->obj.lockid); /* Decrement sub-directory open counter */ + if (res == FR_OK) dp->obj.fs = 0; /* Invalidate directory object */ +#else + dp->obj.fs = 0; /* Invalidate directory object */ +#endif +#if FF_FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entries in Sequence */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + + res = validate(&dp->obj, &fs); /* Check validity of the directory object */ + if (res == FR_OK) { + if (!fno) { + res = dir_sdi(dp, 0); /* Rewind the directory object */ + } else { + INIT_NAMBUF(fs); + res = dir_read_file(dp); /* Read an item */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */ + if (res == FR_OK) { /* A valid entry is found */ + get_fileinfo(dp, fno); /* Get the object information */ + res = dir_next(dp, 0); /* Increment index for next */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory now */ + } + FREE_NAMBUF(); + } + } + LEAVE_FF(fs, res); +} + + + +#if FF_USE_FIND +/*-----------------------------------------------------------------------*/ +/* Find Next File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findnext ( + DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to the file information structure */ +) +{ + FRESULT res; + + + for (;;) { + res = f_readdir(dp, fno); /* Get a directory item */ + if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */ + if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */ +#if FF_USE_LFN && FF_USE_FIND == 2 + if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */ +#endif + } + return res; +} + + + +/*-----------------------------------------------------------------------*/ +/* Find First File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findfirst ( + DIR* dp, /* Pointer to the blank directory object */ + FILINFO* fno, /* Pointer to the file information structure */ + const TCHAR* path, /* Pointer to the directory to open */ + const TCHAR* pattern /* Pointer to the matching pattern */ +) +{ + FRESULT res; + + + dp->pat = pattern; /* Save pointer to pattern string */ + res = f_opendir(dp, path); /* Open the target directory */ + if (res == FR_OK) { + res = f_findnext(dp, fno); /* Find the first item */ + } + return res; +} + +#endif /* FF_USE_FIND */ + + + +#if FF_FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR* path, /* Pointer to the file path */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &dj.obj.fs, 0); + if (res == FR_OK) { + INIT_NAMBUF(dj.obj.fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* It is origin directory */ + res = FR_INVALID_NAME; + } else { /* Found an object */ + if (fno) get_fileinfo(&dj, fno); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(dj.obj.fs, res); +} + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR* path, /* Logical drive number */ + DWORD* nclst, /* Pointer to a variable to return number of free clusters */ + FATFS** fatfs /* Pointer to return pointer to corresponding filesystem object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD nfree, clst, sect, stat; + UINT i; + FFOBJID obj; + + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) { + *fatfs = fs; /* Return ptr to the fs object */ + /* If free_clst is valid, return it without full FAT scan */ + if (fs->free_clst <= fs->n_fatent - 2) { + *nclst = fs->free_clst; + } else { + /* Scan FAT to obtain number of free clusters */ + nfree = 0; + if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */ + clst = 2; obj.fs = fs; + do { + stat = get_fat(&obj, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) nfree++; + } while (++clst < fs->n_fatent); + } else { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* exFAT: Scan allocation bitmap */ + BYTE bm; + UINT b; + + clst = fs->n_fatent - 2; /* Number of clusters */ + sect = fs->database; /* Assuming bitmap starts at cluster 2 */ + i = 0; /* Offset in the sector */ + do { /* Counts numbuer of bits with zero in the bitmap */ + if (i == 0) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + } + for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) { + if (!(bm & 1)) nfree++; + bm >>= 1; + } + i = (i + 1) % SS(fs); + } while (clst); + } else +#endif + { /* FAT16/32: Scan WORD/DWORD FAT entries */ + clst = fs->n_fatent; /* Number of entries */ + sect = fs->fatbase; /* Top of the FAT */ + i = 0; /* Offset in the sector */ + do { /* Counts numbuer of entries with zero in the FAT */ + if (i == 0) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + } + if (fs->fs_type == FS_FAT16) { + if (ld_word(fs->win + i) == 0) nfree++; + i += 2; + } else { + if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++; + i += 4; + } + i %= SS(fs); + } while (--clst); + } + } + *nclst = nfree; /* Return the free clusters */ + fs->free_clst = nfree; /* Now free_clst is valid */ + fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */ + } + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD ncl; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + if (fp->fptr < fp->obj.objsize) { /* Process when fptr is not on the eof */ + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fp->obj.sclust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(&fp->obj, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fs->n_fatent) { + res = remove_chain(&fp->obj, ncl, fp->clust); + } + } + fp->obj.objsize = fp->fptr; /* Set file size to current read/write point */ + fp->flag |= FA_MODIFIED; +#if !FF_FS_TINY + if (res == FR_OK && (fp->flag & FA_DIRTY)) { + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) { + res = FR_DISK_ERR; + } else { + fp->flag &= (BYTE)~FA_DIRTY; + } + } +#endif + if (res != FR_OK) ABORT(fs, res); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR* path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + DIR dj, sdj; + DWORD dclst = 0; + FATFS *fs; +#if FF_FS_EXFAT + FFOBJID obj; +#endif + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) { + res = FR_INVALID_NAME; /* Cannot remove dot entry */ + } +#if FF_FS_LOCK != 0 + if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */ +#endif + if (res == FR_OK) { /* The object is accessible */ + if (dj.fn[NSFLAG] & NS_NONAME) { + res = FR_INVALID_NAME; /* Cannot remove the origin directory */ + } else { + if (dj.obj.attr & AM_RDO) { + res = FR_DENIED; /* Cannot remove R/O object */ + } + } + if (res == FR_OK) { +#if FF_FS_EXFAT + obj.fs = fs; + if (fs->fs_type == FS_EXFAT) { + init_alloc_info(fs, &obj); + dclst = obj.sclust; + } else +#endif + { + dclst = ld_clust(fs, dj.dir); + } + if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory? */ +#if FF_FS_RPATH != 0 + if (dclst == fs->cdir) { /* Is it the current directory? */ + res = FR_DENIED; + } else +#endif + { + sdj.obj.fs = fs; /* Open the sub-directory */ + sdj.obj.sclust = dclst; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + sdj.obj.objsize = obj.objsize; + sdj.obj.stat = obj.stat; + } +#endif + res = dir_sdi(&sdj, 0); + if (res == FR_OK) { + res = dir_read_file(&sdj); /* Test if the directory is empty */ + if (res == FR_OK) res = FR_DENIED; /* Not empty? */ + if (res == FR_NO_FILE) res = FR_OK; /* Empty? */ + } + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK && dclst != 0) { /* Remove the cluster chain if exist */ +#if FF_FS_EXFAT + res = remove_chain(&obj, dclst, 0); +#else + res = remove_chain(&dj.obj, dclst, 0); +#endif + } + if (res == FR_OK) res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + BYTE *dir; + DWORD dcl, pcl, tm; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ + if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { + res = FR_INVALID_NAME; + } + if (res == FR_NO_FILE) { /* Can create a new directory */ + dcl = create_chain(&dj.obj, 0); /* Allocate a cluster for the new directory table */ + dj.obj.objsize = (DWORD)fs->csize * SS(fs); + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ + if (dcl == 1) res = FR_INT_ERR; + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) res = sync_window(fs); /* Flush FAT */ + tm = GET_FATTIME(); + if (res == FR_OK) { /* Initialize the new directory table */ + res = dir_clear(fs, dcl); /* Clean up the new table */ + if (res == FR_OK && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT)) { /* Create dot entries (FAT only) */ + dir = fs->win; + mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + st_dword(dir + DIR_ModTime, tm); + st_clust(fs, dir, dcl); + mem_cpy(dir + SZDIRE, dir, SZDIRE); /* Create ".." entry */ + dir[SZDIRE + 1] = '.'; pcl = dj.obj.sclust; + st_clust(fs, dir + SZDIRE, pcl); + fs->wflag = 1; + } + } + if (res == FR_OK) { + res = dir_register(&dj); /* Register the object to the directoy */ + } + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */ + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */ + st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ + st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)dj.obj.objsize); /* File size needs to be valid */ + st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)dj.obj.objsize); + fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */ + fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ + res = store_xdir(&dj); + } else +#endif + { + dir = dj.dir; + st_dword(dir + DIR_ModTime, tm); /* Created time */ + st_clust(fs, dir, dcl); /* Table start cluster */ + dir[DIR_Attr] = AM_DIR; /* Attribute */ + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } else { + remove_chain(&dj.obj, dcl, 0); /* Could not register, remove cluster chain */ + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR* path_old, /* Pointer to the object name to be renamed */ + const TCHAR* path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DIR djo, djn; + FATFS *fs; + BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir; + DWORD dw; + DEF_NAMBUF + + + get_ldnumber(&path_new); /* Snip the drive number of new name off */ + res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */ + if (res == FR_OK) { + djo.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&djo, path_old); /* Check old object */ + if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */ +#if FF_FS_LOCK != 0 + if (res == FR_OK) { + res = chk_lock(&djo, 2); + } +#endif + if (res == FR_OK) { /* Object to be renamed is found */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* At exFAT volume */ + BYTE nf, nn; + WORD nh; + + mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ + mem_cpy(&djn, &djo, sizeof djo); + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName]; + nh = ld_word(fs->dirbuf + XDIR_NameHash); + mem_cpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */ + fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn; + st_word(fs->dirbuf + XDIR_NameHash, nh); + if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ +/* Start of critical section where an interruption can cause a cross-link */ + res = store_xdir(&djn); + } + } + } else +#endif + { /* At FAT/FAT32 volume */ + mem_cpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */ + mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy directory entry of the object except name */ + mem_cpy(dir + 13, buf + 13, SZDIRE - 13); + dir[DIR_Attr] = buf[DIR_Attr]; + if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ + fs->wflag = 1; + if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) { /* Update .. entry in the sub-directory if needed */ + dw = clst2sect(fs, ld_clust(fs, dir)); + if (dw == 0) { + res = FR_INT_ERR; + } else { +/* Start of critical section where an interruption can cause a cross-link */ + res = move_window(fs, dw); + dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */ + if (res == FR_OK && dir[1] == '.') { + st_clust(fs, dir, djn.obj.sclust); + fs->wflag = 1; + } + } + } + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) { + res = sync_fs(fs); + } + } +/* End of the critical section */ + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_FS_MINIMIZE == 0 */ +#endif /* FF_FS_MINIMIZE <= 1 */ +#endif /* FF_FS_MINIMIZE <= 2 */ + + + +#if FF_USE_CHMOD && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR* path, /* Pointer to the file path */ + BYTE attr, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) { + mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + res = store_xdir(&dj); + } else +#endif + { + dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR* path, /* Pointer to the file/directory name */ + const FILINFO* fno /* Pointer to the timestamp to be set */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + res = store_xdir(&dj); + } else +#endif + { + st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_USE_CHMOD && !FF_FS_READONLY */ + + + +#if FF_USE_LABEL +/*-----------------------------------------------------------------------*/ +/* Get Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getlabel ( + const TCHAR* path, /* Logical drive number */ + TCHAR* label, /* Buffer to store the volume label */ + DWORD* vsn /* Variable to store the volume serial number */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + UINT si, di; + WCHAR wc; + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + + /* Get volume label */ + if (res == FR_OK && label) { + dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = dir_read_label(&dj); /* Find a volume label entry */ + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + WCHAR hs; + + for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */ + wc = ld_word(dj.dir + XDIR_Label + si * 2); + if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */ + hs = wc; continue; + } + wc = put_utf((DWORD)hs << 16 | wc, &label[di], 4); + if (wc == 0) { di = 0; break; } + di += wc; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + label[di] = 0; + } else +#endif + { + si = di = 0; /* Extract volume label from AM_VOL entry */ + while (si < 11) { + wc = dj.dir[si++]; +#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode output */ + if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++]; /* Is it a DBC? */ + wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */ + if (wc != 0) wc = put_utf(wc, &label[di], 4); /* Put it in Unicode */ + if (wc == 0) { di = 0; break; } + di += wc; +#else /* ANSI/OEM output */ + label[di++] = (TCHAR)wc; +#endif + } + do { /* Truncate trailing spaces */ + label[di] = 0; + if (di == 0) break; + } while (label[--di] == ' '); + } + } + } + if (res == FR_NO_FILE) { /* No label entry and return nul string */ + label[0] = 0; + res = FR_OK; + } + } + + /* Get volume serial number */ + if (res == FR_OK && vsn) { + res = move_window(fs, fs->volbase); + if (res == FR_OK) { + switch (fs->fs_type) { + case FS_EXFAT: + di = BPB_VolIDEx; break; + + case FS_FAT32: + di = BS_VolID32; break; + + default: + di = BS_VolID; + } + *vsn = ld_dword(fs->win + di); + } + } + + LEAVE_FF(fs, res); +} + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Set Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setlabel ( + const TCHAR* label /* Volume label to set with heading logical drive number */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + BYTE dirvn[22]; + UINT di; + WCHAR wc; + static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */ +#if FF_USE_LFN + DWORD dc; +#endif + + /* Get logical drive */ + res = find_volume(&label, &fs, FA_WRITE); + if (res != FR_OK) LEAVE_FF(fs, res); + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + mem_set(dirvn, 0, 22); + di = 0; + while ((UINT)*label >= ' ') { /* Create volume label */ + dc = tchar2uni(&label); /* Get a Unicode character */ + if (dc >= 0x10000) { + if (dc == 0xFFFFFFFF || di >= 10) { /* Wrong surrogate or buffer overflow */ + dc = 0; + } else { + st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++; + } + } + if (dc == 0 || chk_chr(badchr + 7, (int)dc) || di >= 11) { /* Check validity of the volume label */ + LEAVE_FF(fs, FR_INVALID_NAME); + } + st_word(dirvn + di * 2, (WCHAR)dc); di++; + } + } else +#endif + { /* On the FAT/FAT32 volume */ + mem_set(dirvn, ' ', 11); + di = 0; + while ((UINT)*label >= ' ') { /* Create volume label */ +#if FF_USE_LFN + dc = tchar2uni(&label); + wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0; +#else /* ANSI/OEM input */ + wc = (BYTE)*label++; + if (dbc_1st((BYTE)wc)) wc = dbc_2nd((BYTE)*label) ? wc << 8 | (BYTE)*label++ : 0; + if (IsLower(wc)) wc -= 0x20; /* To upper ASCII characters */ +#if FF_CODE_PAGE == 0 + if (ExCvt && wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ +#elif FF_CODE_PAGE < 900 + if (wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ +#endif +#endif + if (wc == 0 || chk_chr(badchr + 0, (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */ + LEAVE_FF(fs, FR_INVALID_NAME); + } + if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8); + dirvn[di++] = (BYTE)wc; + } + if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */ + while (di && dirvn[di - 1] == ' ') di--; /* Snip trailing spaces */ + } + + /* Set volume label */ + dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = dir_read_label(&dj); /* Get volume label entry */ + if (res == FR_OK) { + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { + dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */ + mem_cpy(dj.dir + XDIR_Label, dirvn, 22); + } else { + if (di != 0) { + mem_cpy(dj.dir, dirvn, 11); /* Change the volume label */ + } else { + dj.dir[DIR_Name] = DDEM; /* Remove the volume label */ + } + } + fs->wflag = 1; + res = sync_fs(fs); + } else { /* No volume label entry or an error */ + if (res == FR_NO_FILE) { + res = FR_OK; + if (di != 0) { /* Create a volume label entry */ + res = dir_alloc(&dj, 1); /* Allocate an entry */ + if (res == FR_OK) { + mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */ + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { + dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */ + dj.dir[XDIR_NumLabel] = (BYTE)di; + mem_cpy(dj.dir + XDIR_Label, dirvn, 22); + } else { + dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ + mem_cpy(dj.dir, dirvn, 11); + } + fs->wflag = 1; + res = sync_fs(fs); + } + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_LABEL */ + + + +#if FF_USE_EXPAND && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Allocate a Contiguous Blocks to the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_expand ( + FIL* fp, /* Pointer to the file object */ + FSIZE_t fsz, /* File size to be expanded to */ + BYTE opt /* Operation mode 0:Find and prepare or 1:Find and allocate */ +) +{ + FRESULT res; + FATFS *fs; + DWORD n, clst, stcl, scl, ncl, tcl, lclst; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); +#if FF_FS_EXFAT + if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ +#endif + n = (DWORD)fs->csize * SS(fs); /* Cluster size */ + tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0); /* Number of clusters required */ + stcl = fs->last_clst; lclst = 0; + if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2; + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + scl = find_bitmap(fs, stcl, tcl); /* Find a contiguous cluster block */ + if (scl == 0) res = FR_DENIED; /* No contiguous cluster block was found */ + if (scl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) { /* A contiguous free area is found */ + if (opt) { /* Allocate it now */ + res = change_bitmap(fs, scl, tcl, 1); /* Mark the cluster block 'in use' */ + lclst = scl + tcl - 1; + } else { /* Set it as suggested point for next allocation */ + lclst = scl - 1; + } + } + } else +#endif + { + scl = clst = stcl; ncl = 0; + for (;;) { /* Find a contiguous cluster block */ + n = get_fat(&fp->obj, clst); + if (++clst >= fs->n_fatent) clst = 2; + if (n == 1) { res = FR_INT_ERR; break; } + if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (n == 0) { /* Is it a free cluster? */ + if (++ncl == tcl) break; /* Break if a contiguous cluster block is found */ + } else { + scl = clst; ncl = 0; /* Not a free cluster */ + } + if (clst == stcl) { res = FR_DENIED; break; } /* No contiguous cluster? */ + } + if (res == FR_OK) { /* A contiguous free area is found */ + if (opt) { /* Allocate it now */ + for (clst = scl, n = tcl; n; clst++, n--) { /* Create a cluster chain on the FAT */ + res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1); + if (res != FR_OK) break; + lclst = clst; + } + } else { /* Set it as suggested point for next allocation */ + lclst = scl - 1; + } + } + } + + if (res == FR_OK) { + fs->last_clst = lclst; /* Set suggested start cluster to start next */ + if (opt) { /* Is it allocated now? */ + fp->obj.sclust = scl; /* Update object allocation information */ + fp->obj.objsize = fsz; + if (FF_FS_EXFAT) fp->obj.stat = 2; /* Set status 'contiguous chain' */ + fp->flag |= FA_MODIFIED; + if (fs->free_clst <= fs->n_fatent - 2) { /* Update FSINFO */ + fs->free_clst -= tcl; + fs->fsi_flag |= 1; + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_USE_EXPAND && !FF_FS_READONLY */ + + + +#if FF_USE_FORWARD +/*-----------------------------------------------------------------------*/ +/* Forward Data to the Stream Directly */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_forward ( + FIL* fp, /* Pointer to the file object */ + UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ + UINT btf, /* Number of bytes to forward */ + UINT* bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + FSIZE_t remain; + UINT rcnt, csect; + BYTE *dbuf; + + + *bf = 0; /* Clear transfer byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + remain = fp->obj.objsize - fp->fptr; + if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ + + for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream goes busy */ + fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + if (csect == 0) { /* On the cluster boundary? */ + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->obj.sclust : get_fat(&fp->obj, fp->clust); + if (clst <= 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clst2sect(fs, fp->clust); /* Get current data sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; +#if FF_FS_TINY + if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window to the file data */ + dbuf = fs->win; +#else + if (fp->sect != sect) { /* Fill sector cache with file data */ +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + } + dbuf = fp->buf; +#endif + fp->sect = sect; + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (rcnt > btf) rcnt = btf; /* Clip it by btr if needed */ + rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt); /* Forward the file data */ + if (rcnt == 0) ABORT(fs, FR_INT_ERR); + } + + LEAVE_FF(fs, FR_OK); +} +#endif /* FF_USE_FORWARD */ + + + +#if FF_USE_MKFS && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Create an FAT/exFAT volume */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkfs ( + const TCHAR* path, /* Logical drive number */ + BYTE opt, /* Format option */ + DWORD au, /* Size of allocation unit (cluster) [byte] */ + void* work, /* Pointer to working buffer (null: use heap memory) */ + UINT len /* Size of working buffer [byte] */ +) +{ + const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */ + const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */ + static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */ + static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ + BYTE fmt, sys, *buf, *pte, pdrv, part; + WORD ss; /* Sector size */ + DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n; + DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */ + DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */ + UINT i; + int vol; + DSTATUS stat; +#if FF_USE_TRIM || FF_FS_EXFAT + DWORD tbl[3]; +#endif + + + /* Check mounted drive and clear work area */ + vol = get_ldnumber(&path); /* Get target logical drive */ + if (vol < 0) return FR_INVALID_DRIVE; + if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the volume if mounted */ + pdrv = LD2PD(vol); /* Physical drive */ + part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */ + + /* Check physical drive status */ + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */ +#if FF_MAX_SS != FF_MIN_SS /* Get sector size of the medium if variable sector size cfg. */ + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; + if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; +#else + ss = FF_MAX_SS; +#endif + if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ + au /= ss; /* Cluster size in unit of sector */ + + /* Get working buffer */ +#if FF_USE_LFN == 3 + if (!work) { /* Use heap memory for working buffer */ + for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && (buf = ff_memalloc(szb_buf)) == 0; szb_buf /= 2) ; + sz_buf = szb_buf / ss; /* Size of working buffer (sector) */ + } else +#endif + { + buf = (BYTE*)work; /* Working buffer */ + sz_buf = len / ss; /* Size of working buffer (sector) */ + szb_buf = sz_buf * ss; /* Size of working buffer (byte) */ + } + if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE; + + /* Determine where the volume to be located (b_vol, sz_vol) */ + if (FF_MULTI_PARTITION && part != 0) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ + if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ + pte = buf + (MBR_Table + (part - 1) * SZ_PTE); + if (pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED); /* No partition? */ + b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ + sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ + } else { + /* Create a single-partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */ + if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); + sz_vol -= b_vol; /* Volume size */ + } + if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128s */ + + /* Pre-determine the FAT type */ + do { + if (FF_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */ + if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) { /* exFAT only, vol >= 64Ms or au > 128s ? */ + fmt = FS_EXFAT; break; + } + } + if (au > 128) LEAVE_MKFS(FR_INVALID_PARAMETER); /* Too large au for FAT/FAT32 */ + if (opt & FM_FAT32) { /* FAT32 possible? */ + if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */ + fmt = FS_FAT32; break; + } + } + if (!(opt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER); /* no-FAT? */ + fmt = FS_FAT16; + } while (0); + +#if FF_FS_EXFAT + if (fmt == FS_EXFAT) { /* Create an exFAT volume */ + DWORD szb_bit, szb_case, sum, nb, cl; + WCHAR ch, si; + UINT j, st; + BYTE b; + + if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ +#if FF_USE_TRIM + tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area may be erased */ + disk_ioctl(pdrv, CTRL_TRIM, tbl); +#endif + /* Determine FAT location, data location and number of clusters */ + if (au == 0) { /* au auto-selection */ + au = 8; + if (sz_vol >= 0x80000) au = 64; /* >= 512Ks */ + if (sz_vol >= 0x4000000) au = 256; /* >= 64Ms */ + } + b_fat = b_vol + 32; /* FAT start at offset 32 */ + sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ + b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */ + if (b_data >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ + n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */ + if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */ + if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */ + + szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ + tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */ + + /* Create a compressed up-case table */ + sect = b_data + au * tbl[0]; /* Table start sector */ + sum = 0; /* Table checksum to be stored in the 82 entry */ + st = 0; si = 0; i = 0; j = 0; szb_case = 0; + do { + switch (st) { + case 0: + ch = (WCHAR)ff_wtoupper(si); /* Get an up-case char */ + if (ch != si) { + si++; break; /* Store the up-case char if exist */ + } + for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */ + if (j >= 128) { + ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */ + } + st = 1; /* Do not compress short run */ + /* go to next case */ + case 1: + ch = si++; /* Fill the short run */ + if (--j == 0) st = 0; + break; + + default: + ch = (WCHAR)j; si += (WCHAR)j; /* Number of chars to skip */ + st = 0; + } + sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ + sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); + i += 2; szb_case += 2; + if (si == 0 || i == szb_buf) { /* Write buffered data when buffer full or end of process */ + n = (i + ss - 1) / ss; + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; i = 0; + } + } while (si); + tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */ + tbl[2] = 1; /* Number of root dir clusters */ + + /* Initialize the allocation bitmap */ + sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */ + nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */ + do { + mem_set(buf, 0, szb_buf); + for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ; + for (b = 1; nb != 0 && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ; + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + + /* Initialize the FAT */ + sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */ + j = nb = cl = 0; + do { + mem_set(buf, 0, szb_buf); i = 0; /* Clear work area and reset write index */ + if (cl == 0) { /* Set entry 0 and 1 */ + st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++; + st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++; + } + do { /* Create chains of bitmap, up-case and root dir */ + while (nb != 0 && i < szb_buf) { /* Create a chain */ + st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF); + i += 4; cl++; nb--; + } + if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */ + } while (nb != 0 && i < szb_buf); + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + + /* Initialize the root directory */ + mem_set(buf, 0, szb_buf); + buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */ + buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */ + st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ + st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ + buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */ + st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */ + st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */ + st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */ + sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */ + do { /* Fill root directory sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + mem_set(buf, 0, ss); + sect += n; nsect -= n; + } while (nsect); + + /* Create two set of the exFAT VBR blocks */ + sect = b_vol; + for (n = 0; n < 2; n++) { + /* Main record (+0) */ + mem_set(buf, 0, ss); + mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */ + st_dword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ + st_dword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ + st_dword(buf + BPB_FatOfsEx, b_fat - b_vol); /* FAT offset [sector] */ + st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_DataOfsEx, b_data - b_vol); /* Data offset [sector] */ + st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ + st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */ + st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */ + st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ + for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ + for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ + buf[BPB_NumFATsEx] = 1; /* Number of FATs */ + buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */ + st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ + st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ + for (i = sum = 0; i < ss; i++) { /* VBR checksum */ + if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); + } + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + /* Extended bootstrap record (+1..+8) */ + mem_set(buf, 0, ss); + st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ + for (j = 1; j < 9; j++) { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + /* OEM/Reserved record (+9..+10) */ + mem_set(buf, 0, ss); + for ( ; j < 11; j++) { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + /* Sum record (+11) */ + for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + + } else +#endif /* FF_FS_EXFAT */ + { /* Create an FAT/FAT32 volume */ + do { + pau = au; + /* Pre-determine number of clusters and FAT sub-type */ + if (fmt == FS_FAT32) { /* FAT32 volume */ + if (pau == 0) { /* au auto-selection */ + n = sz_vol / 0x20000; /* Volume size in unit of 128KS */ + for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = sz_vol / pau; /* Number of clusters */ + sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 32; /* Number of reserved sectors */ + sz_dir = 0; /* No static directory */ + if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED); + } else { /* FAT volume */ + if (pau == 0) { /* au auto-selection */ + n = sz_vol / 0x1000; /* Volume size in unit of 4KS */ + for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = sz_vol / pau; + if (n_clst > MAX_FAT12) { + n = n_clst * 2 + 4; /* FAT size [byte] */ + } else { + fmt = FS_FAT12; + n = (n_clst * 3 + 1) / 2 + 3; /* FAT size [byte] */ + } + sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 1; /* Number of reserved sectors */ + sz_dir = (DWORD)n_rootdir * SZDIRE / ss; /* Rootdir size [sector] */ + } + b_fat = b_vol + sz_rsv; /* FAT base */ + b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */ + + /* Align data base to erase block boundary (for flash memory media) */ + n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */ + if (fmt == FS_FAT32) { /* FAT32: Move FAT base */ + sz_rsv += n; b_fat += n; + } else { /* FAT: Expand FAT size */ + sz_fat += n / n_fats; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume */ + n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau; + if (fmt == FS_FAT32) { + if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32 */ + if (au == 0 && (au = pau / 2) != 0) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + } + if (fmt == FS_FAT16) { + if (n_clst > MAX_FAT16) { /* Too many clusters for FAT16 */ + if (au == 0 && (pau * 2) <= 64) { + au = pau * 2; continue; /* Adjust cluster size and retry */ + } + if ((opt & FM_FAT32)) { + fmt = FS_FAT32; continue; /* Switch type to FAT32 and retry */ + } + if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + if (n_clst <= MAX_FAT12) { /* Too few clusters for FAT16 */ + if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + } + if (fmt == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters for FAT12 */ + + /* Ok, it is the valid cluster configuration */ + break; + } while (1); + +#if FF_USE_TRIM + tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area can be erased */ + disk_ioctl(pdrv, CTRL_TRIM, tbl); +#endif + /* Create FAT VBR */ + mem_set(buf, 0, ss); + mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ + st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ + buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ + st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ + buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */ + st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */ + if (sz_vol < 0x10000) { + st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ + } else { + st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */ + } + buf[BPB_Media] = 0xF8; /* Media descriptor byte */ + st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ + st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ + st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ + if (fmt == FS_FAT32) { + st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ + st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ + st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ + st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ + buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } else { + st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ + st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ + buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ + + /* Create FSINFO record if needed */ + if (fmt == FS_FAT32) { + disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ + mem_set(buf, 0, ss); + st_dword(buf + FSI_LeadSig, 0x41615252); + st_dword(buf + FSI_StrucSig, 0x61417272); + st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ + st_word(buf + BS_55AA, 0xAA55); + disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ + disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ + } + + /* Initialize FAT area */ + mem_set(buf, 0, (UINT)szb_buf); + sect = b_fat; /* FAT start sector */ + for (i = 0; i < n_fats; i++) { /* Initialize FATs each */ + if (fmt == FS_FAT32) { + st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */ + st_dword(buf + 4, 0xFFFFFFFF); /* Entry 1 */ + st_dword(buf + 8, 0x0FFFFFFF); /* Entry 2 (root directory) */ + } else { + st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */ + } + nsect = sz_fat; /* Number of FAT sectors */ + do { /* Fill FAT sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + mem_set(buf, 0, ss); + sect += n; nsect -= n; + } while (nsect); + } + + /* Initialize root directory (fill with zero) */ + nsect = (fmt == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ + do { + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + } + + /* Determine system ID in the partition table */ + if (FF_FS_EXFAT && fmt == FS_EXFAT) { + sys = 0x07; /* HPFS/NTFS/exFAT */ + } else { + if (fmt == FS_FAT32) { + sys = 0x0C; /* FAT32X */ + } else { + if (sz_vol >= 0x10000) { + sys = 0x06; /* FAT12/16 (large) */ + } else { + sys = (fmt == FS_FAT16) ? 0x04 : 0x01; /* FAT16 : FAT12 */ + } + } + } + + /* Update partition information */ + if (FF_MULTI_PARTITION && part != 0) { /* Created in the existing partition */ + /* Update system ID in the partition table */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ + buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */ + } else { /* Created as a new single partition */ + if (!(opt & FM_SFD)) { /* Create partition table if in FDISK format */ + mem_set(buf, 0, ss); + st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ + pte = buf + MBR_Table; /* Create partition table for single partition in the drive */ + pte[PTE_Boot] = 0; /* Boot indicator */ + pte[PTE_StHead] = 1; /* Start head */ + pte[PTE_StSec] = 1; /* Start sector */ + pte[PTE_StCyl] = 0; /* Start cylinder */ + pte[PTE_System] = sys; /* System type */ + n = (b_vol + sz_vol) / (63 * 255); /* (End CHS may be invalid) */ + pte[PTE_EdHead] = 254; /* End head */ + pte[PTE_EdSec] = (BYTE)(((n >> 2) & 0xC0) | 63); /* End sector */ + pte[PTE_EdCyl] = (BYTE)n; /* End cylinder */ + st_dword(pte + PTE_StLba, b_vol); /* Start offset in LBA */ + st_dword(pte + PTE_SizLba, sz_vol); /* Size in sectors */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the MBR */ + } + } + + if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + + LEAVE_MKFS(FR_OK); +} + + + +#if FF_MULTI_PARTITION +/*-----------------------------------------------------------------------*/ +/* Create Partition Table on the Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD* szt, /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer (null: use heap memory) */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + FRESULT res; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + buf = (BYTE*)work; +#if FF_USE_LFN == 3 + if (!buf) buf = ff_memalloc(FF_MAX_SS); /* Use heap memory for working buffer */ +#endif + if (!buf) return FR_NOT_ENOUGH_CORE; + + /* Determine the CHS without any consideration of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = (BYTE)(n - 1); + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, FF_MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; /* Number of cylinders */ + if (p_cyl == 0) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += 63; sz_part -= 63; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; /* End cylinder */ + if (e_cyl >= tot_cyl) LEAVE_MKFS(FR_INVALID_PARAMETER); + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x07; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + st_dword(p + 8, s_part); /* Start sector in LBA */ + st_dword(p + 12, sz_part); /* Number of sectors */ + + /* Next partition */ + b_cyl += p_cyl; + } + st_word(p, 0xAA55); /* MBR signature (always at offset 510) */ + + /* Write it to the MBR */ + res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; + LEAVE_MKFS(res); +} + +#endif /* FF_MULTI_PARTITION */ +#endif /* FF_USE_MKFS && !FF_FS_READONLY */ + + + + +#if FF_USE_STRFUNC +#if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3) +#error Wrong FF_STRF_ENCODE setting +#endif +/*-----------------------------------------------------------------------*/ +/* Get a String from the File */ +/*-----------------------------------------------------------------------*/ + +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (items) */ + FIL* fp /* Pointer to the file object */ +) +{ + int nc = 0; + TCHAR *p = buff; + BYTE s[4]; + UINT rc; + DWORD dc; +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2 + WCHAR wc; +#endif +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3 + UINT ct; +#endif + +#if FF_USE_LFN && FF_LFN_UNICODE /* With code conversion (Unicode API) */ + /* Make a room for the character and terminator */ + if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2; + if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4; + if (FF_LFN_UNICODE == 3) len -= 1; + while (nc < len) { +#if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + wc = s[0]; + if (dbc_1st((BYTE)wc)) { + f_read(fp, s, 1, &rc); + if (rc != 1 || !dbc_2nd(s[0])) continue; + wc = wc << 8 | s[0]; + } + dc = ff_oem2uni(wc, CODEPAGE); + if (dc == 0) continue; +#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (IsSurrogateL(dc)) continue; + if (IsSurrogateH(dc)) { + f_read(fp, s, 2, &rc); + if (rc != 2) break; + wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (!IsSurrogateL(wc)) continue; + dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF); + } +#else /* Read a character in UTF-8 */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + dc = s[0]; + if (dc >= 0x80) { /* Multi-byte character? */ + ct = 0; + if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } /* 2-byte? */ + if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte? */ + if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte? */ + if (ct == 0) continue; + f_read(fp, s, ct, &rc); /* Get trailing bytes */ + if (rc != ct) break; + rc = 0; + do { /* Merge trailing bytes */ + if ((s[rc] & 0xC0) != 0x80) break; + dc = dc << 6 | (s[rc] & 0x3F); + } while (++rc < ct); + if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue; /* Wrong encoding? */ + } +#endif + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; /* Strip \r off if needed */ +#if FF_LFN_UNICODE == 1 || FF_LFN_UNICODE == 3 /* Output it in UTF-16/32 encoding */ + if (FF_LFN_UNICODE == 1 && dc >= 0x10000) { /* Out of BMP at UTF-16? */ + *p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++; /* Make and output high surrogate */ + dc = 0xDC00 | (dc & 0x3FF); /* Make low surrogate */ + } + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; /* End of line? */ +#elif FF_LFN_UNICODE == 2 /* Output it in UTF-8 encoding */ + if (dc < 0x80) { /* 1-byte */ + *p++ = (TCHAR)dc; + nc++; + if (dc == '\n') break; /* End of line? */ + } else { + if (dc < 0x800) { /* 2-byte */ + *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 2; + } else { + if (dc < 0x10000) { /* 3-byte */ + *p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F)); + *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 3; + } else { /* 4-byte */ + *p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07)); + *p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 4; + } + } + } +#endif + } + +#else /* Byte-by-byte without any conversion (ANSI/OEM API) */ + len -= 1; /* Make a room for the terminator */ + while (nc < len) { + f_read(fp, s, 1, &rc); + if (rc != 1) break; + dc = s[0]; + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; + } +#endif + + *p = 0; /* Terminate the string */ + return nc ? buff : 0; /* When no data read due to EOF or error, return with error. */ +} + + + + +#if !FF_FS_READONLY +#include <stdarg.h> +/*-----------------------------------------------------------------------*/ +/* Put a Character to the File */ +/*-----------------------------------------------------------------------*/ + +typedef struct { /* Putchar output buffer and work area */ + FIL *fp; /* Ptr to the writing file */ + int idx, nchr; /* Write index of buf[] (-1:error), number of encoding units written */ +#if FF_USE_LFN && FF_LFN_UNICODE == 1 + WCHAR hs; +#elif FF_USE_LFN && FF_LFN_UNICODE == 2 + BYTE bs[4]; + UINT wi, ct; +#endif + BYTE buf[64]; /* Write buffer */ +} putbuff; + + +static +void putc_bfd ( /* Buffered write with code conversion */ + putbuff* pb, + TCHAR c +) +{ + UINT n; + int i, nc; +#if FF_USE_LFN && FF_LFN_UNICODE + WCHAR hs, wc; +#if FF_LFN_UNICODE == 2 + DWORD dc; + TCHAR *tp; +#endif +#endif + + if (FF_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */ + putc_bfd(pb, '\r'); + } + + i = pb->idx; /* Write index of pb->buf[] */ + if (i < 0) return; + nc = pb->nchr; /* Write unit counter */ + +#if FF_USE_LFN && FF_LFN_UNICODE +#if FF_LFN_UNICODE == 1 /* UTF-16 input */ + if (IsSurrogateH(c)) { + pb->hs = c; return; + } + hs = pb->hs; pb->hs = 0; + if (hs != 0) { + if (!IsSurrogateL(c)) hs = 0; + } else { + if (IsSurrogateL(c)) return; + } + wc = c; +#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ + for (;;) { + if (pb->ct == 0) { /* Out of multi-byte sequence? */ + pb->bs[pb->wi = 0] = (BYTE)c; /* Save 1st byte */ + if ((BYTE)c < 0x80) break; /* 1-byte? */ + if (((BYTE)c & 0xE0) == 0xC0) pb->ct = 1; /* 2-byte? */ + if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2; /* 3-byte? */ + if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3; /* 4-byte? */ + return; + } else { /* In the multi-byte sequence */ + if (((BYTE)c & 0xC0) != 0x80) { /* Broken sequence? */ + pb->ct = 0; continue; + } + pb->bs[++pb->wi] = (BYTE)c; /* Save the trailing byte */ + if (--pb->ct == 0) break; /* End of multi-byte sequence? */ + return; + } + } + tp = (TCHAR*)pb->bs; + dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ + if (dc == 0xFFFFFFFF) return; + wc = (WCHAR)dc; + hs = (WCHAR)(dc >> 16); +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + if (IsSurrogate(c) || c >= 0x110000) return; + if (c >= 0x10000) { + hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40)); /* Make high surrogate */ + wc = 0xDC00 | (c & 0x3FF); /* Make low surrogate */ + } else { + hs = 0; + wc = (WCHAR)c; + } +#endif + +#if FF_STRF_ENCODE == 1 /* Write a character in UTF-16LE */ + if (hs != 0) { + st_word(&pb->buf[i], hs); + i += 2; + nc++; + } + st_word(&pb->buf[i], wc); + i += 2; +#elif FF_STRF_ENCODE == 2 /* Write a character in UTF-16BE */ + if (hs != 0) { + pb->buf[i++] = (BYTE)(hs >> 8); + pb->buf[i++] = (BYTE)hs; + nc++; + } + pb->buf[i++] = (BYTE)(wc >> 8); + pb->buf[i++] = (BYTE)wc; +#elif FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ + if (hs != 0) { /* 4-byte */ + nc += 3; + hs = (hs & 0x3FF) + 0x40; + pb->buf[i++] = (BYTE)(0xF0 | hs >> 8); + pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F)); + pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F)); + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } else { + if (wc < 0x80) { /* 1-byte */ + pb->buf[i++] = (BYTE)wc; + } else { + if (wc < 0x800) { /* 2-byte */ + nc += 1; + pb->buf[i++] = (BYTE)(0xC0 | wc >> 6); + } else { /* 3-byte */ + nc += 2; + pb->buf[i++] = (BYTE)(0xE0 | wc >> 12); + pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F)); + } + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } + } +#else /* Write it in ANSI/OEM */ + if (hs != 0) return; + wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */ + if (wc == 0) return;; + if (wc >= 0x100) { + pb->buf[i++] = (BYTE)(wc >> 8); nc++; + } + pb->buf[i++] = (BYTE)wc; +#endif + +#else /* ANSI/OEM input (without re-encode) */ + pb->buf[i++] = (BYTE)c; +#endif + + if (i >= (int)(sizeof pb->buf) - 4) { /* Write buffered characters to the file */ + f_write(pb->fp, pb->buf, (UINT)i, &n); + i = (n == (UINT)i) ? 0 : -1; + } + pb->idx = i; + pb->nchr = nc + 1; +} + + +static +int putc_flush ( /* Flush left characters in the buffer */ + putbuff* pb +) +{ + UINT nw; + + if ( pb->idx >= 0 /* Flush buffered characters to the file */ + && f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK + && (UINT)pb->idx == nw) return pb->nchr; + return EOF; +} + + +static +void putc_init ( /* Initialize write buffer */ + putbuff* pb, + FIL* fp +) +{ + mem_set(pb, 0, sizeof (putbuff)); + pb->fp = fp; +} + + + +int f_putc ( + TCHAR c, /* A character to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + putc_bfd(&pb, c); /* Put the character */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a String to the File */ +/*-----------------------------------------------------------------------*/ + +int f_puts ( + const TCHAR* str, /* Pointer to the string to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + while (*str) putc_bfd(&pb, *str++); /* Put the string */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a Formatted String to the File */ +/*-----------------------------------------------------------------------*/ + +int f_printf ( + FIL* fp, /* Pointer to the file object */ + const TCHAR* fmt, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + putbuff pb; + BYTE f, r; + UINT i, j, w; + DWORD v; + TCHAR c, d, str[32], *p; + + + putc_init(&pb, fp); + + va_start(arp, fmt); + + for (;;) { + c = *fmt++; + if (c == 0) break; /* End of string */ + if (c != '%') { /* Non escape character */ + putc_bfd(&pb, c); + continue; + } + w = f = 0; + c = *fmt++; + if (c == '0') { /* Flag: '0' padding */ + f = 1; c = *fmt++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *fmt++; + } + } + if (c == '*') { /* Minimum width by argument */ + w = va_arg(arp, int); + c = *fmt++; + } else { + while (IsDigit(c)) { /* Minimum width */ + w = w * 10 + c - '0'; + c = *fmt++; + } + } + if (c == 'l' || c == 'L') { /* Type prefix: Size is long int */ + f |= 4; c = *fmt++; + } + if (c == 0) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) { /* Atgument type is... */ + case 'S' : /* String */ + p = va_arg(arp, TCHAR*); + for (j = 0; p[j]; j++) ; + if (!(f & 2)) { /* Right padded */ + while (j++ < w) putc_bfd(&pb, ' ') ; + } + while (*p) putc_bfd(&pb, *p++) ; /* String body */ + while (j++ < w) putc_bfd(&pb, ' ') ; /* Left padded */ + continue; + + case 'C' : /* Character */ + putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; + + case 'B' : /* Unsigned binary */ + r = 2; break; + + case 'O' : /* Unsigned octal */ + r = 8; break; + + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + + case 'X' : /* Unsigned hexdecimal */ + r = 16; break; + + default: /* Unknown type (pass-through) */ + putc_bfd(&pb, c); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (TCHAR)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + str[i++] = d + '0'; + } while (v && i < sizeof str / sizeof *str); + if (f & 8) str[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + if (!(f & 2)) { + while (j++ < w) putc_bfd(&pb, d); /* Right pad */ + } + do { + putc_bfd(&pb, str[--i]); /* Number body */ + } while (i); + while (j++ < w) putc_bfd(&pb, d); /* Left pad */ + } + + va_end(arp); + + return putc_flush(&pb); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_STRFUNC */ + + + +#if FF_CODE_PAGE == 0 +/*-----------------------------------------------------------------------*/ +/* Set Active Codepage for the Path Name */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setcp ( + WORD cp /* Value to be set as active code page */ +) +{ + static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0}; + static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; + UINT i; + + + for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ; /* Find the code page */ + if (validcp[i] != cp) return FR_INVALID_PARAMETER; /* Not found? */ + + CodePage = cp; + if (cp >= 900) { /* DBCS */ + ExCvt = 0; + DbcTbl = tables[i]; + } else { /* SBCS */ + ExCvt = tables[i]; + DbcTbl = 0; + } + return FR_OK; +} +#endif /* FF_CODE_PAGE == 0 */ + diff --git a/sept/sept-secondary/src/lib/fatfs/ff.h b/sept/sept-secondary/src/lib/fatfs/ff.h new file mode 100644 index 000000000..cd90d6d6d --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/ff.h @@ -0,0 +1,376 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem module R0.13b / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2018, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: + +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ + + +#ifndef FF_DEFINED +#define FF_DEFINED 63463 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" /* Basic integer types */ +#include "ffconf.h" /* FatFs configuration options */ + +#if FF_DEFINED != FFCONF_DEF +#error Wrong configuration file (ffconf.h). +#endif + + + +/* Definitions of volume management */ + +#if FF_MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#endif + +#if FF_STR_VOLUME_ID +#ifndef FF_VOLUME_STRS +extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ +#endif +#endif + + + +/* Type of path name strings on FatFs API */ + +#ifndef _INC_TCHAR +#define _INC_TCHAR + +#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */ +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */ +typedef char TCHAR; +#define _T(x) u8 ## x +#define _TEXT(x) u8 ## x +#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ +typedef DWORD TCHAR; +#define _T(x) U ## x +#define _TEXT(x) U ## x +#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) +#error Wrong FF_LFN_UNICODE setting +#else /* ANSI/OEM code in SBCS/DBCS */ +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + +#endif + + + +/* Type of file size variables */ + +#if FF_FS_EXFAT +typedef QWORD FSIZE_t; +#else +typedef DWORD FSIZE_t; +#endif + + + +/* Filesystem object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* Filesystem type (0:N/A) */ + BYTE pdrv; /* Physical drive number */ + BYTE n_fats; /* Number of FATs (1 or 2) */ + BYTE wflag; /* win[] flag (b0:dirty) */ + BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ + WORD id; /* Volume mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ + WORD csize; /* Cluster size [sectors] */ +#if FF_MAX_SS != FF_MIN_SS + WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ +#endif +#if FF_USE_LFN + WCHAR* lfnbuf; /* LFN working buffer */ +#endif +#if FF_FS_EXFAT + BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ +#endif +#if FF_FS_REENTRANT + FF_SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !FF_FS_READONLY + DWORD last_clst; /* Last allocated cluster */ + DWORD free_clst; /* Number of free clusters */ +#endif +#if FF_FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#if FF_FS_EXFAT + DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ + DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ + DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ +#endif +#endif + DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ + DWORD fsize; /* Size of an FAT [sectors] */ + DWORD volbase; /* Volume base sector */ + DWORD fatbase; /* FAT base sector */ + DWORD dirbase; /* Root directory base sector/cluster */ + DWORD database; /* Data base sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +} FATFS; + + + +/* Object ID and allocation information (FFOBJID) */ + +typedef struct { + FATFS* fs; /* Pointer to the hosting volume of this object */ + WORD id; /* Hosting volume mount ID */ + BYTE attr; /* Object attribute */ + BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */ + DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ + FSIZE_t objsize; /* Object size (valid when sclust != 0) */ +#if FF_FS_EXFAT + DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ + DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ + DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ + DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ + DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ +#endif +#if FF_FS_LOCK + UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ +#endif +} FFOBJID; + + + +/* File object structure (FIL) */ + +typedef struct { + FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ + BYTE flag; /* File status flags */ + BYTE err; /* Abort flag (error code) */ + FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ + DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ + DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ +#if !FF_FS_READONLY + DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ + BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ +#endif +#if FF_USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ +#endif +#if !FF_FS_TINY + BYTE buf[FF_MAX_SS]; /* File private data read/write window */ +#endif +} FIL; + + + +/* Directory object structure (DIR) */ + +typedef struct { + FFOBJID obj; /* Object identifier */ + DWORD dptr; /* Current read/write offset */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector (0:Read operation has terminated) */ + BYTE* dir; /* Pointer to the directory item in the win[] */ + BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ +#if FF_USE_LFN + DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ +#endif +#if FF_USE_FIND + const TCHAR* pat; /* Pointer to the name matching pattern */ +#endif +} DIR; + + + +/* File information structure (FILINFO) */ + +typedef struct { + FSIZE_t fsize; /* File size */ + WORD fdate; /* Modified date */ + WORD ftime; /* Modified time */ + BYTE fattrib; /* File attribute */ +#if FF_USE_LFN + TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */ + TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ +#else + TCHAR fname[12 + 1]; /* File name */ +#endif +} FILINFO; + + + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ + +FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ +FRESULT f_close (FIL* fp); /* Close an open file object */ +FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ +FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ +FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ +FRESULT f_truncate (FIL* fp); /* Truncate the file */ +FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ +FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ +FRESULT f_closedir (DIR* dp); /* Close an open directory */ +FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ +FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ +FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ +FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ +FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ +FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ +FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ +FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ +FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ +FRESULT f_chdir (const TCHAR* path); /* Change current directory */ +FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ +FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ +FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ +FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ +FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ +FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ +FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ +FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ +FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ +FRESULT f_setcp (WORD cp); /* Set current code page */ +int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ +int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ +int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ + +#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) +#define f_error(fp) ((fp)->err) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->obj.objsize) +#define f_rewind(fp) f_lseek((fp), 0) +#define f_rewinddir(dp) f_readdir((dp), 0) +#define f_rmdir(path) f_unlink(path) +#define f_unmount(path) f_mount(0, path, 0) + +#ifndef EOF +#define EOF (-1) +#endif + + + + +/*--------------------------------------------------------------*/ +/* Additional user defined functions */ + +/* RTC function */ +#if !FF_FS_READONLY && !FF_FS_NORTC +DWORD get_fattime (void); +#endif + +/* LFN support functions */ +#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ +WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ +WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ +DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ +#endif +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif + +/* Sync functions */ +#if FF_FS_REENTRANT +int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ +int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ +void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ +int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ +#endif + + + + +/*--------------------------------------------------------------*/ +/* Flags and offset address */ + + +/* File access mode and open method flags (3rd argument of f_open) */ +#define FA_READ 0x01 +#define FA_WRITE 0x02 +#define FA_OPEN_EXISTING 0x00 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA_OPEN_APPEND 0x30 + +/* Fast seek controls (2nd argument of f_lseek) */ +#define CREATE_LINKMAP ((FSIZE_t)0 - 1) + +/* Format options (2nd argument of f_mkfs) */ +#define FM_FAT 0x01 +#define FM_FAT32 0x02 +#define FM_EXFAT 0x04 +#define FM_ANY 0x07 +#define FM_SFD 0x08 + +/* Filesystem type (FATFS.fs_type) */ +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 +#define FS_EXFAT 4 + +/* File attribute bits for directory entry (FILINFO.fattrib) */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ + + +#ifdef __cplusplus +} +#endif + +#endif /* FF_DEFINED */ diff --git a/sept/sept-secondary/src/lib/fatfs/ffconf.h b/sept/sept-secondary/src/lib/fatfs/ffconf.h new file mode 100644 index 000000000..d12bb8e2f --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/ffconf.h @@ -0,0 +1,289 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - Configuration file +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 63463 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: Basic functions are fully enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_STRFUNC 2 +/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 0 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 850 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 1 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function +/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. +/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can +/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN +/ specification. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree() in ffsystem.c, need to be added to the project. */ + + +#define FF_LFN_UNICODE 2 +/* This option switches the character encoding on the API when LFN is enabled. +/ +/ 0: ANSI/OEM in current CP (TCHAR = char) +/ 1: Unicode in UTF-16 (TCHAR = WCHAR) +/ 2: Unicode in UTF-8 (TCHAR = char) +/ 3: Unicode in UTF-32 (TCHAR = DWORD) +/ +/ Also behavior of string I/O functions will be affected by this option. +/ When LFN is not enabled, this option has no effect. */ + + +#define FF_LFN_BUF 255 +#define FF_SFN_BUF 12 +/* This set of options defines size of file name members in the FILINFO structure +/ which is used to read out directory items. These values should be suffcient for +/ the file names to read. The maximum possible length of the read file name depends +/ on character encoding. When LFN is not enabled, these options have no effect. */ + + +#define FF_STRF_ENCODE 3 +/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(), +/ f_putc(), f_puts and f_printf() convert the character encoding in it. +/ This option selects assumption of character encoding ON THE FILE to be +/ read/written via those functions. +/ +/ 0: ANSI/OEM in current CP +/ 1: Unicode in UTF-16LE +/ 2: Unicode in UTF-16BE +/ 3: Unicode in UTF-8 +*/ + + +#define FF_FS_RPATH 0 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 1 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "sdmc" +/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. +/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each +/ logical drives. Number of items must not be less than FF_VOLUMES. Valid +/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are +/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is +/ not defined, a user defined volume string table needs to be defined as: +/ +/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... +*/ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk. But a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 1 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ To enable exFAT, also LFN needs to be enabled. +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 1 +#define FF_NORTC_MON 1 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2018 +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. Every object modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 0 +#define FF_FS_TIMEOUT 1000 +#define FF_SYNC_t HANDLE +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + +/* #include <windows.h> // O/S definitions */ + + + +/*--- End of configuration options ---*/ diff --git a/sept/sept-secondary/src/lib/fatfs/ffsystem.c b/sept/sept-secondary/src/lib/fatfs/ffsystem.c new file mode 100644 index 000000000..9df330f99 --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/ffsystem.c @@ -0,0 +1,171 @@ +/*------------------------------------------------------------------------*/ +/* Sample Code of OS Dependent Functions for FatFs */ +/* (C)ChaN, 2017 */ +/*------------------------------------------------------------------------*/ + + +#include "ff.h" + + + +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ + +/*------------------------------------------------------------------------*/ +/* Allocate a memory block */ +/*------------------------------------------------------------------------*/ + +void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */ + UINT msize /* Number of bytes to allocate */ +) +{ + return malloc(msize); /* Allocate a new memory block with POSIX API */ +} + + +/*------------------------------------------------------------------------*/ +/* Free a memory block */ +/*------------------------------------------------------------------------*/ + +void ff_memfree ( + void* mblock /* Pointer to the memory block to free (nothing to do for null) */ +) +{ + free(mblock); /* Free the memory block with POSIX API */ +} + +#endif + + + +#if FF_FS_REENTRANT /* Mutal exclusion */ + +/*------------------------------------------------------------------------*/ +/* Create a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to create a new +/ synchronization object for the volume, such as semaphore and mutex. +/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR. +*/ + +//const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */ + + +int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ + BYTE vol, /* Corresponding volume (logical drive number) */ + FF_SYNC_t* sobj /* Pointer to return the created sync object */ +) +{ + /* Win32 */ + *sobj = CreateMutex(NULL, FALSE, NULL); + return (int)(*sobj != INVALID_HANDLE_VALUE); + + /* uITRON */ +// T_CSEM csem = {TA_TPRI,1,1}; +// *sobj = acre_sem(&csem); +// return (int)(*sobj > 0); + + /* uC/OS-II */ +// OS_ERR err; +// *sobj = OSMutexCreate(0, &err); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// *sobj = xSemaphoreCreateMutex(); +// return (int)(*sobj != NULL); + + /* CMSIS-RTOS */ +// *sobj = osMutexCreate(Mutex + vol); +// return (int)(*sobj != NULL); +} + + +/*------------------------------------------------------------------------*/ +/* Delete a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to delete a synchronization +/ object that created with ff_cre_syncobj() function. When a 0 is returned, +/ the f_mount() function fails with FR_INT_ERR. +*/ + +int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ + FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ +) +{ + /* Win32 */ + return (int)CloseHandle(sobj); + + /* uITRON */ +// return (int)(del_sem(sobj) == E_OK); + + /* uC/OS-II */ +// OS_ERR err; +// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// vSemaphoreDelete(sobj); +// return 1; + + /* CMSIS-RTOS */ +// return (int)(osMutexDelete(sobj) == osOK); +} + + +/*------------------------------------------------------------------------*/ +/* Request Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on entering file functions to lock the volume. +/ When a 0 is returned, the file function fails with FR_TIMEOUT. +*/ + +int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ + FF_SYNC_t sobj /* Sync object to wait */ +) +{ + /* Win32 */ + return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0); + + /* uITRON */ +// return (int)(wai_sem(sobj) == E_OK); + + /* uC/OS-II */ +// OS_ERR err; +// OSMutexPend(sobj, FF_FS_TIMEOUT, &err)); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); + + /* CMSIS-RTOS */ +// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK); +} + + +/*------------------------------------------------------------------------*/ +/* Release Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on leaving file functions to unlock the volume. +*/ + +void ff_rel_grant ( + FF_SYNC_t sobj /* Sync object to be signaled */ +) +{ + /* Win32 */ + ReleaseMutex(sobj); + + /* uITRON */ +// sig_sem(sobj); + + /* uC/OS-II */ +// OSMutexPost(sobj); + + /* FreeRTOS */ +// xSemaphoreGive(sobj); + + /* CMSIS-RTOS */ +// osMutexRelease(sobj); +} + +#endif + diff --git a/sept/sept-secondary/src/lib/fatfs/ffunicode.c b/sept/sept-secondary/src/lib/fatfs/ffunicode.c new file mode 100644 index 000000000..9a5d37ef7 --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/ffunicode.c @@ -0,0 +1,15597 @@ +/*------------------------------------------------------------------------*/ +/* Unicode handling functions for FatFs R0.13b */ +/*------------------------------------------------------------------------*/ +/* This module will occupy a huge memory in the .const section when the / +/ FatFs is configured for LFN with DBCS. If the system has any Unicode / +/ utilitiy for the code conversion, this module should be modified to use / +/ that function to avoid silly memory consumption. / +/-------------------------------------------------------------------------*/ +/* +/ Copyright (C) 2018, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +*/ + + +#include "ff.h" + +#if FF_USE_LFN /* This module is blanked when non-LFN configuration */ + +#if FF_DEFINED != 63463 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + +#define MERGE2(a, b) a ## b +#define CVTBL(tbl, cp) MERGE2(tbl, cp) + + +/*------------------------------------------------------------------------*/ +/* Code Conversion Tables */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */ +static const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */ + 0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180, + 0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6, + 0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE, + 0x03A1, 0x83AF, 0x03A3, 0x83B0, 0x03A4, 0x83B1, 0x03A5, 0x83B2, 0x03A6, 0x83B3, 0x03A7, 0x83B4, 0x03A8, 0x83B5, 0x03A9, 0x83B6, + 0x03B1, 0x83BF, 0x03B2, 0x83C0, 0x03B3, 0x83C1, 0x03B4, 0x83C2, 0x03B5, 0x83C3, 0x03B6, 0x83C4, 0x03B7, 0x83C5, 0x03B8, 0x83C6, + 0x03B9, 0x83C7, 0x03BA, 0x83C8, 0x03BB, 0x83C9, 0x03BC, 0x83CA, 0x03BD, 0x83CB, 0x03BE, 0x83CC, 0x03BF, 0x83CD, 0x03C0, 0x83CE, + 0x03C1, 0x83CF, 0x03C3, 0x83D0, 0x03C4, 0x83D1, 0x03C5, 0x83D2, 0x03C6, 0x83D3, 0x03C7, 0x83D4, 0x03C8, 0x83D5, 0x03C9, 0x83D6, + 0x0401, 0x8446, 0x0410, 0x8440, 0x0411, 0x8441, 0x0412, 0x8442, 0x0413, 0x8443, 0x0414, 0x8444, 0x0415, 0x8445, 0x0416, 0x8447, + 0x0417, 0x8448, 0x0418, 0x8449, 0x0419, 0x844A, 0x041A, 0x844B, 0x041B, 0x844C, 0x041C, 0x844D, 0x041D, 0x844E, 0x041E, 0x844F, + 0x041F, 0x8450, 0x0420, 0x8451, 0x0421, 0x8452, 0x0422, 0x8453, 0x0423, 0x8454, 0x0424, 0x8455, 0x0425, 0x8456, 0x0426, 0x8457, + 0x0427, 0x8458, 0x0428, 0x8459, 0x0429, 0x845A, 0x042A, 0x845B, 0x042B, 0x845C, 0x042C, 0x845D, 0x042D, 0x845E, 0x042E, 0x845F, + 0x042F, 0x8460, 0x0430, 0x8470, 0x0431, 0x8471, 0x0432, 0x8472, 0x0433, 0x8473, 0x0434, 0x8474, 0x0435, 0x8475, 0x0436, 0x8477, + 0x0437, 0x8478, 0x0438, 0x8479, 0x0439, 0x847A, 0x043A, 0x847B, 0x043B, 0x847C, 0x043C, 0x847D, 0x043D, 0x847E, 0x043E, 0x8480, + 0x043F, 0x8481, 0x0440, 0x8482, 0x0441, 0x8483, 0x0442, 0x8484, 0x0443, 0x8485, 0x0444, 0x8486, 0x0445, 0x8487, 0x0446, 0x8488, + 0x0447, 0x8489, 0x0448, 0x848A, 0x0449, 0x848B, 0x044A, 0x848C, 0x044B, 0x848D, 0x044C, 0x848E, 0x044D, 0x848F, 0x044E, 0x8490, + 0x044F, 0x8491, 0x0451, 0x8476, 0x2010, 0x815D, 0x2015, 0x815C, 0x2018, 0x8165, 0x2019, 0x8166, 0x201C, 0x8167, 0x201D, 0x8168, + 0x2020, 0x81F5, 0x2021, 0x81F6, 0x2025, 0x8164, 0x2026, 0x8163, 0x2030, 0x81F1, 0x2032, 0x818C, 0x2033, 0x818D, 0x203B, 0x81A6, + 0x2103, 0x818E, 0x2116, 0x8782, 0x2121, 0x8784, 0x212B, 0x81F0, 0x2160, 0x8754, 0x2161, 0x8755, 0x2162, 0x8756, 0x2163, 0x8757, + 0x2164, 0x8758, 0x2165, 0x8759, 0x2166, 0x875A, 0x2167, 0x875B, 0x2168, 0x875C, 0x2169, 0x875D, 0x2170, 0xFA40, 0x2171, 0xFA41, + 0x2172, 0xFA42, 0x2173, 0xFA43, 0x2174, 0xFA44, 0x2175, 0xFA45, 0x2176, 0xFA46, 0x2177, 0xFA47, 0x2178, 0xFA48, 0x2179, 0xFA49, + 0x2190, 0x81A9, 0x2191, 0x81AA, 0x2192, 0x81A8, 0x2193, 0x81AB, 0x21D2, 0x81CB, 0x21D4, 0x81CC, 0x2200, 0x81CD, 0x2202, 0x81DD, + 0x2203, 0x81CE, 0x2207, 0x81DE, 0x2208, 0x81B8, 0x220B, 0x81B9, 0x2211, 0x8794, 0x221A, 0x81E3, 0x221D, 0x81E5, 0x221E, 0x8187, + 0x221F, 0x8798, 0x2220, 0x81DA, 0x2225, 0x8161, 0x2227, 0x81C8, 0x2228, 0x81C9, 0x2229, 0x81BF, 0x222A, 0x81BE, 0x222B, 0x81E7, + 0x222C, 0x81E8, 0x222E, 0x8793, 0x2234, 0x8188, 0x2235, 0x81E6, 0x223D, 0x81E4, 0x2252, 0x81E0, 0x2260, 0x8182, 0x2261, 0x81DF, + 0x2266, 0x8185, 0x2267, 0x8186, 0x226A, 0x81E1, 0x226B, 0x81E2, 0x2282, 0x81BC, 0x2283, 0x81BD, 0x2286, 0x81BA, 0x2287, 0x81BB, + 0x22A5, 0x81DB, 0x22BF, 0x8799, 0x2312, 0x81DC, 0x2460, 0x8740, 0x2461, 0x8741, 0x2462, 0x8742, 0x2463, 0x8743, 0x2464, 0x8744, + 0x2465, 0x8745, 0x2466, 0x8746, 0x2467, 0x8747, 0x2468, 0x8748, 0x2469, 0x8749, 0x246A, 0x874A, 0x246B, 0x874B, 0x246C, 0x874C, + 0x246D, 0x874D, 0x246E, 0x874E, 0x246F, 0x874F, 0x2470, 0x8750, 0x2471, 0x8751, 0x2472, 0x8752, 0x2473, 0x8753, 0x2500, 0x849F, + 0x2501, 0x84AA, 0x2502, 0x84A0, 0x2503, 0x84AB, 0x250C, 0x84A1, 0x250F, 0x84AC, 0x2510, 0x84A2, 0x2513, 0x84AD, 0x2514, 0x84A4, + 0x2517, 0x84AF, 0x2518, 0x84A3, 0x251B, 0x84AE, 0x251C, 0x84A5, 0x251D, 0x84BA, 0x2520, 0x84B5, 0x2523, 0x84B0, 0x2524, 0x84A7, + 0x2525, 0x84BC, 0x2528, 0x84B7, 0x252B, 0x84B2, 0x252C, 0x84A6, 0x252F, 0x84B6, 0x2530, 0x84BB, 0x2533, 0x84B1, 0x2534, 0x84A8, + 0x2537, 0x84B8, 0x2538, 0x84BD, 0x253B, 0x84B3, 0x253C, 0x84A9, 0x253F, 0x84B9, 0x2542, 0x84BE, 0x254B, 0x84B4, 0x25A0, 0x81A1, + 0x25A1, 0x81A0, 0x25B2, 0x81A3, 0x25B3, 0x81A2, 0x25BC, 0x81A5, 0x25BD, 0x81A4, 0x25C6, 0x819F, 0x25C7, 0x819E, 0x25CB, 0x819B, + 0x25CE, 0x819D, 0x25CF, 0x819C, 0x25EF, 0x81FC, 0x2605, 0x819A, 0x2606, 0x8199, 0x2640, 0x818A, 0x2642, 0x8189, 0x266A, 0x81F4, + 0x266D, 0x81F3, 0x266F, 0x81F2, 0x3000, 0x8140, 0x3001, 0x8141, 0x3002, 0x8142, 0x3003, 0x8156, 0x3005, 0x8158, 0x3006, 0x8159, + 0x3007, 0x815A, 0x3008, 0x8171, 0x3009, 0x8172, 0x300A, 0x8173, 0x300B, 0x8174, 0x300C, 0x8175, 0x300D, 0x8176, 0x300E, 0x8177, + 0x300F, 0x8178, 0x3010, 0x8179, 0x3011, 0x817A, 0x3012, 0x81A7, 0x3013, 0x81AC, 0x3014, 0x816B, 0x3015, 0x816C, 0x301D, 0x8780, + 0x301F, 0x8781, 0x3041, 0x829F, 0x3042, 0x82A0, 0x3043, 0x82A1, 0x3044, 0x82A2, 0x3045, 0x82A3, 0x3046, 0x82A4, 0x3047, 0x82A5, + 0x3048, 0x82A6, 0x3049, 0x82A7, 0x304A, 0x82A8, 0x304B, 0x82A9, 0x304C, 0x82AA, 0x304D, 0x82AB, 0x304E, 0x82AC, 0x304F, 0x82AD, + 0x3050, 0x82AE, 0x3051, 0x82AF, 0x3052, 0x82B0, 0x3053, 0x82B1, 0x3054, 0x82B2, 0x3055, 0x82B3, 0x3056, 0x82B4, 0x3057, 0x82B5, + 0x3058, 0x82B6, 0x3059, 0x82B7, 0x305A, 0x82B8, 0x305B, 0x82B9, 0x305C, 0x82BA, 0x305D, 0x82BB, 0x305E, 0x82BC, 0x305F, 0x82BD, + 0x3060, 0x82BE, 0x3061, 0x82BF, 0x3062, 0x82C0, 0x3063, 0x82C1, 0x3064, 0x82C2, 0x3065, 0x82C3, 0x3066, 0x82C4, 0x3067, 0x82C5, + 0x3068, 0x82C6, 0x3069, 0x82C7, 0x306A, 0x82C8, 0x306B, 0x82C9, 0x306C, 0x82CA, 0x306D, 0x82CB, 0x306E, 0x82CC, 0x306F, 0x82CD, + 0x3070, 0x82CE, 0x3071, 0x82CF, 0x3072, 0x82D0, 0x3073, 0x82D1, 0x3074, 0x82D2, 0x3075, 0x82D3, 0x3076, 0x82D4, 0x3077, 0x82D5, + 0x3078, 0x82D6, 0x3079, 0x82D7, 0x307A, 0x82D8, 0x307B, 0x82D9, 0x307C, 0x82DA, 0x307D, 0x82DB, 0x307E, 0x82DC, 0x307F, 0x82DD, + 0x3080, 0x82DE, 0x3081, 0x82DF, 0x3082, 0x82E0, 0x3083, 0x82E1, 0x3084, 0x82E2, 0x3085, 0x82E3, 0x3086, 0x82E4, 0x3087, 0x82E5, + 0x3088, 0x82E6, 0x3089, 0x82E7, 0x308A, 0x82E8, 0x308B, 0x82E9, 0x308C, 0x82EA, 0x308D, 0x82EB, 0x308E, 0x82EC, 0x308F, 0x82ED, + 0x3090, 0x82EE, 0x3091, 0x82EF, 0x3092, 0x82F0, 0x3093, 0x82F1, 0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154, 0x309E, 0x8155, + 0x30A1, 0x8340, 0x30A2, 0x8341, 0x30A3, 0x8342, 0x30A4, 0x8343, 0x30A5, 0x8344, 0x30A6, 0x8345, 0x30A7, 0x8346, 0x30A8, 0x8347, + 0x30A9, 0x8348, 0x30AA, 0x8349, 0x30AB, 0x834A, 0x30AC, 0x834B, 0x30AD, 0x834C, 0x30AE, 0x834D, 0x30AF, 0x834E, 0x30B0, 0x834F, + 0x30B1, 0x8350, 0x30B2, 0x8351, 0x30B3, 0x8352, 0x30B4, 0x8353, 0x30B5, 0x8354, 0x30B6, 0x8355, 0x30B7, 0x8356, 0x30B8, 0x8357, + 0x30B9, 0x8358, 0x30BA, 0x8359, 0x30BB, 0x835A, 0x30BC, 0x835B, 0x30BD, 0x835C, 0x30BE, 0x835D, 0x30BF, 0x835E, 0x30C0, 0x835F, + 0x30C1, 0x8360, 0x30C2, 0x8361, 0x30C3, 0x8362, 0x30C4, 0x8363, 0x30C5, 0x8364, 0x30C6, 0x8365, 0x30C7, 0x8366, 0x30C8, 0x8367, + 0x30C9, 0x8368, 0x30CA, 0x8369, 0x30CB, 0x836A, 0x30CC, 0x836B, 0x30CD, 0x836C, 0x30CE, 0x836D, 0x30CF, 0x836E, 0x30D0, 0x836F, + 0x30D1, 0x8370, 0x30D2, 0x8371, 0x30D3, 0x8372, 0x30D4, 0x8373, 0x30D5, 0x8374, 0x30D6, 0x8375, 0x30D7, 0x8376, 0x30D8, 0x8377, + 0x30D9, 0x8378, 0x30DA, 0x8379, 0x30DB, 0x837A, 0x30DC, 0x837B, 0x30DD, 0x837C, 0x30DE, 0x837D, 0x30DF, 0x837E, 0x30E0, 0x8380, + 0x30E1, 0x8381, 0x30E2, 0x8382, 0x30E3, 0x8383, 0x30E4, 0x8384, 0x30E5, 0x8385, 0x30E6, 0x8386, 0x30E7, 0x8387, 0x30E8, 0x8388, + 0x30E9, 0x8389, 0x30EA, 0x838A, 0x30EB, 0x838B, 0x30EC, 0x838C, 0x30ED, 0x838D, 0x30EE, 0x838E, 0x30EF, 0x838F, 0x30F0, 0x8390, + 0x30F1, 0x8391, 0x30F2, 0x8392, 0x30F3, 0x8393, 0x30F4, 0x8394, 0x30F5, 0x8395, 0x30F6, 0x8396, 0x30FB, 0x8145, 0x30FC, 0x815B, + 0x30FD, 0x8152, 0x30FE, 0x8153, 0x3231, 0x878A, 0x3232, 0x878B, 0x3239, 0x878C, 0x32A4, 0x8785, 0x32A5, 0x8786, 0x32A6, 0x8787, + 0x32A7, 0x8788, 0x32A8, 0x8789, 0x3303, 0x8765, 0x330D, 0x8769, 0x3314, 0x8760, 0x3318, 0x8763, 0x3322, 0x8761, 0x3323, 0x876B, + 0x3326, 0x876A, 0x3327, 0x8764, 0x332B, 0x876C, 0x3336, 0x8766, 0x333B, 0x876E, 0x3349, 0x875F, 0x334A, 0x876D, 0x334D, 0x8762, + 0x3351, 0x8767, 0x3357, 0x8768, 0x337B, 0x877E, 0x337C, 0x878F, 0x337D, 0x878E, 0x337E, 0x878D, 0x338E, 0x8772, 0x338F, 0x8773, + 0x339C, 0x876F, 0x339D, 0x8770, 0x339E, 0x8771, 0x33A1, 0x8775, 0x33C4, 0x8774, 0x33CD, 0x8783, 0x4E00, 0x88EA, 0x4E01, 0x929A, + 0x4E03, 0x8EB5, 0x4E07, 0x969C, 0x4E08, 0x8FE4, 0x4E09, 0x8E4F, 0x4E0A, 0x8FE3, 0x4E0B, 0x89BA, 0x4E0D, 0x9573, 0x4E0E, 0x975E, + 0x4E10, 0x98A0, 0x4E11, 0x894E, 0x4E14, 0x8A8E, 0x4E15, 0x98A1, 0x4E16, 0x90A2, 0x4E17, 0x99C0, 0x4E18, 0x8B75, 0x4E19, 0x95B8, + 0x4E1E, 0x8FE5, 0x4E21, 0x97BC, 0x4E26, 0x95C0, 0x4E28, 0xFA68, 0x4E2A, 0x98A2, 0x4E2D, 0x9286, 0x4E31, 0x98A3, 0x4E32, 0x8BF8, + 0x4E36, 0x98A4, 0x4E38, 0x8ADB, 0x4E39, 0x924F, 0x4E3B, 0x8EE5, 0x4E3C, 0x98A5, 0x4E3F, 0x98A6, 0x4E42, 0x98A7, 0x4E43, 0x9454, + 0x4E45, 0x8B76, 0x4E4B, 0x9456, 0x4E4D, 0x93E1, 0x4E4E, 0x8CC1, 0x4E4F, 0x9652, 0x4E55, 0xE568, 0x4E56, 0x98A8, 0x4E57, 0x8FE6, + 0x4E58, 0x98A9, 0x4E59, 0x89B3, 0x4E5D, 0x8BE3, 0x4E5E, 0x8CEE, 0x4E5F, 0x96E7, 0x4E62, 0x9BA4, 0x4E71, 0x9790, 0x4E73, 0x93FB, + 0x4E7E, 0x8AA3, 0x4E80, 0x8B54, 0x4E82, 0x98AA, 0x4E85, 0x98AB, 0x4E86, 0x97B9, 0x4E88, 0x975C, 0x4E89, 0x9188, 0x4E8A, 0x98AD, + 0x4E8B, 0x8E96, 0x4E8C, 0x93F1, 0x4E8E, 0x98B0, 0x4E91, 0x895D, 0x4E92, 0x8CDD, 0x4E94, 0x8CDC, 0x4E95, 0x88E4, 0x4E98, 0x986A, + 0x4E99, 0x9869, 0x4E9B, 0x8DB1, 0x4E9C, 0x889F, 0x4E9E, 0x98B1, 0x4E9F, 0x98B2, 0x4EA0, 0x98B3, 0x4EA1, 0x9653, 0x4EA2, 0x98B4, + 0x4EA4, 0x8CF0, 0x4EA5, 0x88E5, 0x4EA6, 0x9692, 0x4EA8, 0x8B9C, 0x4EAB, 0x8B9D, 0x4EAC, 0x8B9E, 0x4EAD, 0x92E0, 0x4EAE, 0x97BA, + 0x4EB0, 0x98B5, 0x4EB3, 0x98B6, 0x4EB6, 0x98B7, 0x4EBA, 0x906C, 0x4EC0, 0x8F59, 0x4EC1, 0x906D, 0x4EC2, 0x98BC, 0x4EC4, 0x98BA, + 0x4EC6, 0x98BB, 0x4EC7, 0x8B77, 0x4ECA, 0x8DA1, 0x4ECB, 0x89EE, 0x4ECD, 0x98B9, 0x4ECE, 0x98B8, 0x4ECF, 0x95A7, 0x4ED4, 0x8E65, + 0x4ED5, 0x8E64, 0x4ED6, 0x91BC, 0x4ED7, 0x98BD, 0x4ED8, 0x9574, 0x4ED9, 0x90E5, 0x4EDD, 0x8157, 0x4EDE, 0x98BE, 0x4EDF, 0x98C0, + 0x4EE1, 0xFA69, 0x4EE3, 0x91E3, 0x4EE4, 0x97DF, 0x4EE5, 0x88C8, 0x4EED, 0x98BF, 0x4EEE, 0x89BC, 0x4EF0, 0x8BC2, 0x4EF2, 0x9287, + 0x4EF6, 0x8C8F, 0x4EF7, 0x98C1, 0x4EFB, 0x9443, 0x4EFC, 0xFA6A, 0x4F00, 0xFA6B, 0x4F01, 0x8AE9, 0x4F03, 0xFA6C, 0x4F09, 0x98C2, + 0x4F0A, 0x88C9, 0x4F0D, 0x8CDE, 0x4F0E, 0x8AEA, 0x4F0F, 0x959A, 0x4F10, 0x94B0, 0x4F11, 0x8B78, 0x4F1A, 0x89EF, 0x4F1C, 0x98E5, + 0x4F1D, 0x9360, 0x4F2F, 0x948C, 0x4F30, 0x98C4, 0x4F34, 0x94BA, 0x4F36, 0x97E0, 0x4F38, 0x904C, 0x4F39, 0xFA6D, 0x4F3A, 0x8E66, + 0x4F3C, 0x8E97, 0x4F3D, 0x89BE, 0x4F43, 0x92CF, 0x4F46, 0x9241, 0x4F47, 0x98C8, 0x4F4D, 0x88CA, 0x4F4E, 0x92E1, 0x4F4F, 0x8F5A, + 0x4F50, 0x8DB2, 0x4F51, 0x9743, 0x4F53, 0x91CC, 0x4F55, 0x89BD, 0x4F56, 0xFA6E, 0x4F57, 0x98C7, 0x4F59, 0x975D, 0x4F5A, 0x98C3, + 0x4F5B, 0x98C5, 0x4F5C, 0x8DEC, 0x4F5D, 0x98C6, 0x4F5E, 0x9B43, 0x4F69, 0x98CE, 0x4F6F, 0x98D1, 0x4F70, 0x98CF, 0x4F73, 0x89C0, + 0x4F75, 0x95B9, 0x4F76, 0x98C9, 0x4F7B, 0x98CD, 0x4F7C, 0x8CF1, 0x4F7F, 0x8E67, 0x4F83, 0x8AA4, 0x4F86, 0x98D2, 0x4F88, 0x98CA, + 0x4F8A, 0xFA70, 0x4F8B, 0x97E1, 0x4F8D, 0x8E98, 0x4F8F, 0x98CB, 0x4F91, 0x98D0, 0x4F92, 0xFA6F, 0x4F94, 0xFA72, 0x4F96, 0x98D3, + 0x4F98, 0x98CC, 0x4F9A, 0xFA71, 0x4F9B, 0x8B9F, 0x4F9D, 0x88CB, 0x4FA0, 0x8BA0, 0x4FA1, 0x89BF, 0x4FAB, 0x9B44, 0x4FAD, 0x9699, + 0x4FAE, 0x958E, 0x4FAF, 0x8CF2, 0x4FB5, 0x904E, 0x4FB6, 0x97B5, 0x4FBF, 0x95D6, 0x4FC2, 0x8C57, 0x4FC3, 0x91A3, 0x4FC4, 0x89E2, + 0x4FC9, 0xFA61, 0x4FCA, 0x8F72, 0x4FCD, 0xFA73, 0x4FCE, 0x98D7, 0x4FD0, 0x98DC, 0x4FD1, 0x98DA, 0x4FD4, 0x98D5, 0x4FD7, 0x91AD, + 0x4FD8, 0x98D8, 0x4FDA, 0x98DB, 0x4FDB, 0x98D9, 0x4FDD, 0x95DB, 0x4FDF, 0x98D6, 0x4FE1, 0x904D, 0x4FE3, 0x9693, 0x4FE4, 0x98DD, + 0x4FE5, 0x98DE, 0x4FEE, 0x8F43, 0x4FEF, 0x98EB, 0x4FF3, 0x946F, 0x4FF5, 0x9555, 0x4FF6, 0x98E6, 0x4FF8, 0x95EE, 0x4FFA, 0x89B4, + 0x4FFE, 0x98EA, 0x4FFF, 0xFA76, 0x5005, 0x98E4, 0x5006, 0x98ED, 0x5009, 0x9171, 0x500B, 0x8CC2, 0x500D, 0x947B, 0x500F, 0xE0C5, + 0x5011, 0x98EC, 0x5012, 0x937C, 0x5014, 0x98E1, 0x5016, 0x8CF4, 0x5019, 0x8CF3, 0x501A, 0x98DF, 0x501E, 0xFA77, 0x501F, 0x8ED8, + 0x5021, 0x98E7, 0x5022, 0xFA75, 0x5023, 0x95ED, 0x5024, 0x926C, 0x5025, 0x98E3, 0x5026, 0x8C91, 0x5028, 0x98E0, 0x5029, 0x98E8, + 0x502A, 0x98E2, 0x502B, 0x97CF, 0x502C, 0x98E9, 0x502D, 0x9860, 0x5036, 0x8BE4, 0x5039, 0x8C90, 0x5040, 0xFA74, 0x5042, 0xFA7A, + 0x5043, 0x98EE, 0x5046, 0xFA78, 0x5047, 0x98EF, 0x5048, 0x98F3, 0x5049, 0x88CC, 0x504F, 0x95CE, 0x5050, 0x98F2, 0x5055, 0x98F1, + 0x5056, 0x98F5, 0x505A, 0x98F4, 0x505C, 0x92E2, 0x5065, 0x8C92, 0x506C, 0x98F6, 0x5070, 0xFA79, 0x5072, 0x8EC3, 0x5074, 0x91A4, + 0x5075, 0x92E3, 0x5076, 0x8BF4, 0x5078, 0x98F7, 0x507D, 0x8B55, 0x5080, 0x98F8, 0x5085, 0x98FA, 0x508D, 0x9654, 0x5091, 0x8C86, + 0x5094, 0xFA7B, 0x5098, 0x8E50, 0x5099, 0x94F5, 0x509A, 0x98F9, 0x50AC, 0x8DC3, 0x50AD, 0x9762, 0x50B2, 0x98FC, 0x50B3, 0x9942, + 0x50B4, 0x98FB, 0x50B5, 0x8DC2, 0x50B7, 0x8F9D, 0x50BE, 0x8C58, 0x50C2, 0x9943, 0x50C5, 0x8BCD, 0x50C9, 0x9940, 0x50CA, 0x9941, + 0x50CD, 0x93AD, 0x50CF, 0x919C, 0x50D1, 0x8BA1, 0x50D5, 0x966C, 0x50D6, 0x9944, 0x50D8, 0xFA7D, 0x50DA, 0x97BB, 0x50DE, 0x9945, + 0x50E3, 0x9948, 0x50E5, 0x9946, 0x50E7, 0x916D, 0x50ED, 0x9947, 0x50EE, 0x9949, 0x50F4, 0xFA7C, 0x50F5, 0x994B, 0x50F9, 0x994A, + 0x50FB, 0x95C6, 0x5100, 0x8B56, 0x5101, 0x994D, 0x5102, 0x994E, 0x5104, 0x89AD, 0x5109, 0x994C, 0x5112, 0x8EF2, 0x5114, 0x9951, + 0x5115, 0x9950, 0x5116, 0x994F, 0x5118, 0x98D4, 0x511A, 0x9952, 0x511F, 0x8F9E, 0x5121, 0x9953, 0x512A, 0x9744, 0x5132, 0x96D7, + 0x5137, 0x9955, 0x513A, 0x9954, 0x513B, 0x9957, 0x513C, 0x9956, 0x513F, 0x9958, 0x5140, 0x9959, 0x5141, 0x88F2, 0x5143, 0x8CB3, + 0x5144, 0x8C5A, 0x5145, 0x8F5B, 0x5146, 0x929B, 0x5147, 0x8BA2, 0x5148, 0x90E6, 0x5149, 0x8CF5, 0x514A, 0xFA7E, 0x514B, 0x8D8E, + 0x514C, 0x995B, 0x514D, 0x96C6, 0x514E, 0x9365, 0x5150, 0x8E99, 0x5152, 0x995A, 0x5154, 0x995C, 0x515A, 0x937D, 0x515C, 0x8A95, + 0x5162, 0x995D, 0x5164, 0xFA80, 0x5165, 0x93FC, 0x5168, 0x9153, 0x5169, 0x995F, 0x516A, 0x9960, 0x516B, 0x94AA, 0x516C, 0x8CF6, + 0x516D, 0x985A, 0x516E, 0x9961, 0x5171, 0x8BA4, 0x5175, 0x95BA, 0x5176, 0x91B4, 0x5177, 0x8BEF, 0x5178, 0x9354, 0x517C, 0x8C93, + 0x5180, 0x9962, 0x5182, 0x9963, 0x5185, 0x93E0, 0x5186, 0x897E, 0x5189, 0x9966, 0x518A, 0x8DFB, 0x518C, 0x9965, 0x518D, 0x8DC4, + 0x518F, 0x9967, 0x5190, 0xE3EC, 0x5191, 0x9968, 0x5192, 0x9660, 0x5193, 0x9969, 0x5195, 0x996A, 0x5196, 0x996B, 0x5197, 0x8FE7, + 0x5199, 0x8ECA, 0x519D, 0xFA81, 0x51A0, 0x8AA5, 0x51A2, 0x996E, 0x51A4, 0x996C, 0x51A5, 0x96BB, 0x51A6, 0x996D, 0x51A8, 0x9579, + 0x51A9, 0x996F, 0x51AA, 0x9970, 0x51AB, 0x9971, 0x51AC, 0x937E, 0x51B0, 0x9975, 0x51B1, 0x9973, 0x51B2, 0x9974, 0x51B3, 0x9972, + 0x51B4, 0x8DE1, 0x51B5, 0x9976, 0x51B6, 0x96E8, 0x51B7, 0x97E2, 0x51BD, 0x9977, 0x51BE, 0xFA82, 0x51C4, 0x90A6, 0x51C5, 0x9978, + 0x51C6, 0x8F79, 0x51C9, 0x9979, 0x51CB, 0x929C, 0x51CC, 0x97BD, 0x51CD, 0x9380, 0x51D6, 0x99C3, 0x51DB, 0x997A, 0x51DC, 0xEAA3, + 0x51DD, 0x8BC3, 0x51E0, 0x997B, 0x51E1, 0x967D, 0x51E6, 0x8F88, 0x51E7, 0x91FA, 0x51E9, 0x997D, 0x51EA, 0x93E2, 0x51EC, 0xFA83, + 0x51ED, 0x997E, 0x51F0, 0x9980, 0x51F1, 0x8A4D, 0x51F5, 0x9981, 0x51F6, 0x8BA5, 0x51F8, 0x93CA, 0x51F9, 0x899A, 0x51FA, 0x8F6F, + 0x51FD, 0x949F, 0x51FE, 0x9982, 0x5200, 0x9381, 0x5203, 0x906E, 0x5204, 0x9983, 0x5206, 0x95AA, 0x5207, 0x90D8, 0x5208, 0x8AA0, + 0x520A, 0x8AA7, 0x520B, 0x9984, 0x520E, 0x9986, 0x5211, 0x8C59, 0x5214, 0x9985, 0x5215, 0xFA84, 0x5217, 0x97F1, 0x521D, 0x8F89, + 0x5224, 0x94BB, 0x5225, 0x95CA, 0x5227, 0x9987, 0x5229, 0x9798, 0x522A, 0x9988, 0x522E, 0x9989, 0x5230, 0x939E, 0x5233, 0x998A, + 0x5236, 0x90A7, 0x5237, 0x8DFC, 0x5238, 0x8C94, 0x5239, 0x998B, 0x523A, 0x8E68, 0x523B, 0x8D8F, 0x5243, 0x92E4, 0x5244, 0x998D, + 0x5247, 0x91A5, 0x524A, 0x8DED, 0x524B, 0x998E, 0x524C, 0x998F, 0x524D, 0x914F, 0x524F, 0x998C, 0x5254, 0x9991, 0x5256, 0x9655, + 0x525B, 0x8D84, 0x525E, 0x9990, 0x5263, 0x8C95, 0x5264, 0x8DDC, 0x5265, 0x948D, 0x5269, 0x9994, 0x526A, 0x9992, 0x526F, 0x959B, + 0x5270, 0x8FE8, 0x5271, 0x999B, 0x5272, 0x8A84, 0x5273, 0x9995, 0x5274, 0x9993, 0x5275, 0x916E, 0x527D, 0x9997, 0x527F, 0x9996, + 0x5283, 0x8A63, 0x5287, 0x8C80, 0x5288, 0x999C, 0x5289, 0x97AB, 0x528D, 0x9998, 0x5291, 0x999D, 0x5292, 0x999A, 0x5294, 0x9999, + 0x529B, 0x97CD, 0x529C, 0xFA85, 0x529F, 0x8CF7, 0x52A0, 0x89C1, 0x52A3, 0x97F2, 0x52A6, 0xFA86, 0x52A9, 0x8F95, 0x52AA, 0x9377, + 0x52AB, 0x8D85, 0x52AC, 0x99A0, 0x52AD, 0x99A1, 0x52AF, 0xFB77, 0x52B1, 0x97E3, 0x52B4, 0x984A, 0x52B5, 0x99A3, 0x52B9, 0x8CF8, + 0x52BC, 0x99A2, 0x52BE, 0x8A4E, 0x52C0, 0xFA87, 0x52C1, 0x99A4, 0x52C3, 0x9675, 0x52C5, 0x92BA, 0x52C7, 0x9745, 0x52C9, 0x95D7, + 0x52CD, 0x99A5, 0x52D2, 0xE8D3, 0x52D5, 0x93AE, 0x52D7, 0x99A6, 0x52D8, 0x8AA8, 0x52D9, 0x96B1, 0x52DB, 0xFA88, 0x52DD, 0x8F9F, + 0x52DE, 0x99A7, 0x52DF, 0x95E5, 0x52E0, 0x99AB, 0x52E2, 0x90A8, 0x52E3, 0x99A8, 0x52E4, 0x8BCE, 0x52E6, 0x99A9, 0x52E7, 0x8AA9, + 0x52F2, 0x8C4D, 0x52F3, 0x99AC, 0x52F5, 0x99AD, 0x52F8, 0x99AE, 0x52F9, 0x99AF, 0x52FA, 0x8ED9, 0x52FE, 0x8CF9, 0x52FF, 0x96DC, + 0x5300, 0xFA89, 0x5301, 0x96E6, 0x5302, 0x93F5, 0x5305, 0x95EF, 0x5306, 0x99B0, 0x5307, 0xFA8A, 0x5308, 0x99B1, 0x530D, 0x99B3, + 0x530F, 0x99B5, 0x5310, 0x99B4, 0x5315, 0x99B6, 0x5316, 0x89BB, 0x5317, 0x966B, 0x5319, 0x8DFA, 0x531A, 0x99B7, 0x531D, 0x9178, + 0x5320, 0x8FA0, 0x5321, 0x8BA7, 0x5323, 0x99B8, 0x5324, 0xFA8B, 0x532A, 0x94D9, 0x532F, 0x99B9, 0x5331, 0x99BA, 0x5333, 0x99BB, + 0x5338, 0x99BC, 0x5339, 0x9543, 0x533A, 0x8BE6, 0x533B, 0x88E3, 0x533F, 0x93BD, 0x5340, 0x99BD, 0x5341, 0x8F5C, 0x5343, 0x90E7, + 0x5345, 0x99BF, 0x5346, 0x99BE, 0x5347, 0x8FA1, 0x5348, 0x8CDF, 0x5349, 0x99C1, 0x534A, 0x94BC, 0x534D, 0x99C2, 0x5351, 0x94DA, + 0x5352, 0x91B2, 0x5353, 0x91EC, 0x5354, 0x8BA6, 0x5357, 0x93EC, 0x5358, 0x9250, 0x535A, 0x948E, 0x535C, 0x966D, 0x535E, 0x99C4, + 0x5360, 0x90E8, 0x5366, 0x8C54, 0x5369, 0x99C5, 0x536E, 0x99C6, 0x536F, 0x894B, 0x5370, 0x88F3, 0x5371, 0x8AEB, 0x5372, 0xFA8C, + 0x5373, 0x91A6, 0x5374, 0x8B70, 0x5375, 0x9791, 0x5377, 0x99C9, 0x5378, 0x89B5, 0x537B, 0x99C8, 0x537F, 0x8BA8, 0x5382, 0x99CA, + 0x5384, 0x96EF, 0x5393, 0xFA8D, 0x5396, 0x99CB, 0x5398, 0x97D0, 0x539A, 0x8CFA, 0x539F, 0x8CB4, 0x53A0, 0x99CC, 0x53A5, 0x99CE, + 0x53A6, 0x99CD, 0x53A8, 0x907E, 0x53A9, 0x8958, 0x53AD, 0x897D, 0x53AE, 0x99CF, 0x53B0, 0x99D0, 0x53B2, 0xFA8E, 0x53B3, 0x8CB5, + 0x53B6, 0x99D1, 0x53BB, 0x8B8E, 0x53C2, 0x8E51, 0x53C3, 0x99D2, 0x53C8, 0x9694, 0x53C9, 0x8DB3, 0x53CA, 0x8B79, 0x53CB, 0x9746, + 0x53CC, 0x916F, 0x53CD, 0x94BD, 0x53CE, 0x8EFB, 0x53D4, 0x8F66, 0x53D6, 0x8EE6, 0x53D7, 0x8EF3, 0x53D9, 0x8F96, 0x53DB, 0x94BE, + 0x53DD, 0xFA8F, 0x53DF, 0x99D5, 0x53E1, 0x8962, 0x53E2, 0x9170, 0x53E3, 0x8CFB, 0x53E4, 0x8CC3, 0x53E5, 0x8BE5, 0x53E8, 0x99D9, + 0x53E9, 0x9240, 0x53EA, 0x91FC, 0x53EB, 0x8BA9, 0x53EC, 0x8FA2, 0x53ED, 0x99DA, 0x53EE, 0x99D8, 0x53EF, 0x89C2, 0x53F0, 0x91E4, + 0x53F1, 0x8EB6, 0x53F2, 0x8E6A, 0x53F3, 0x8945, 0x53F6, 0x8A90, 0x53F7, 0x8D86, 0x53F8, 0x8E69, 0x53FA, 0x99DB, 0x5401, 0x99DC, + 0x5403, 0x8B68, 0x5404, 0x8A65, 0x5408, 0x8D87, 0x5409, 0x8B67, 0x540A, 0x92DD, 0x540B, 0x8944, 0x540C, 0x93AF, 0x540D, 0x96BC, + 0x540E, 0x8D40, 0x540F, 0x9799, 0x5410, 0x9366, 0x5411, 0x8CFC, 0x541B, 0x8C4E, 0x541D, 0x99E5, 0x541F, 0x8BE1, 0x5420, 0x9669, + 0x5426, 0x94DB, 0x5429, 0x99E4, 0x542B, 0x8ADC, 0x542C, 0x99DF, 0x542D, 0x99E0, 0x542E, 0x99E2, 0x5436, 0x99E3, 0x5438, 0x8B7A, + 0x5439, 0x9081, 0x543B, 0x95AB, 0x543C, 0x99E1, 0x543D, 0x99DD, 0x543E, 0x8CE1, 0x5440, 0x99DE, 0x5442, 0x9843, 0x5446, 0x95F0, + 0x5448, 0x92E6, 0x5449, 0x8CE0, 0x544A, 0x8D90, 0x544E, 0x99E6, 0x5451, 0x93DB, 0x545F, 0x99EA, 0x5468, 0x8EFC, 0x546A, 0x8EF4, + 0x5470, 0x99ED, 0x5471, 0x99EB, 0x5473, 0x96A1, 0x5475, 0x99E8, 0x5476, 0x99F1, 0x5477, 0x99EC, 0x547B, 0x99EF, 0x547C, 0x8CC4, + 0x547D, 0x96BD, 0x5480, 0x99F0, 0x5484, 0x99F2, 0x5486, 0x99F4, 0x548A, 0xFA92, 0x548B, 0x8DEE, 0x548C, 0x9861, 0x548E, 0x99E9, + 0x548F, 0x99E7, 0x5490, 0x99F3, 0x5492, 0x99EE, 0x549C, 0xFA91, 0x54A2, 0x99F6, 0x54A4, 0x9A42, 0x54A5, 0x99F8, 0x54A8, 0x99FC, + 0x54A9, 0xFA93, 0x54AB, 0x9A40, 0x54AC, 0x99F9, 0x54AF, 0x9A5D, 0x54B2, 0x8DE7, 0x54B3, 0x8A50, 0x54B8, 0x99F7, 0x54BC, 0x9A44, + 0x54BD, 0x88F4, 0x54BE, 0x9A43, 0x54C0, 0x88A3, 0x54C1, 0x9569, 0x54C2, 0x9A41, 0x54C4, 0x99FA, 0x54C7, 0x99F5, 0x54C8, 0x99FB, + 0x54C9, 0x8DC6, 0x54D8, 0x9A45, 0x54E1, 0x88F5, 0x54E2, 0x9A4E, 0x54E5, 0x9A46, 0x54E6, 0x9A47, 0x54E8, 0x8FA3, 0x54E9, 0x9689, + 0x54ED, 0x9A4C, 0x54EE, 0x9A4B, 0x54F2, 0x934E, 0x54FA, 0x9A4D, 0x54FD, 0x9A4A, 0x54FF, 0xFA94, 0x5504, 0x8953, 0x5506, 0x8DB4, + 0x5507, 0x904F, 0x550F, 0x9A48, 0x5510, 0x9382, 0x5514, 0x9A49, 0x5516, 0x88A0, 0x552E, 0x9A53, 0x552F, 0x9742, 0x5531, 0x8FA5, + 0x5533, 0x9A59, 0x5538, 0x9A58, 0x5539, 0x9A4F, 0x553E, 0x91C1, 0x5540, 0x9A50, 0x5544, 0x91ED, 0x5545, 0x9A55, 0x5546, 0x8FA4, + 0x554C, 0x9A52, 0x554F, 0x96E2, 0x5553, 0x8C5B, 0x5556, 0x9A56, 0x5557, 0x9A57, 0x555C, 0x9A54, 0x555D, 0x9A5A, 0x5563, 0x9A51, + 0x557B, 0x9A60, 0x557C, 0x9A65, 0x557E, 0x9A61, 0x5580, 0x9A5C, 0x5583, 0x9A66, 0x5584, 0x9150, 0x5586, 0xFA95, 0x5587, 0x9A68, + 0x5589, 0x8D41, 0x558A, 0x9A5E, 0x558B, 0x929D, 0x5598, 0x9A62, 0x5599, 0x9A5B, 0x559A, 0x8AAB, 0x559C, 0x8AEC, 0x559D, 0x8A85, + 0x559E, 0x9A63, 0x559F, 0x9A5F, 0x55A7, 0x8C96, 0x55A8, 0x9A69, 0x55A9, 0x9A67, 0x55AA, 0x9172, 0x55AB, 0x8B69, 0x55AC, 0x8BAA, + 0x55AE, 0x9A64, 0x55B0, 0x8BF2, 0x55B6, 0x8963, 0x55C4, 0x9A6D, 0x55C5, 0x9A6B, 0x55C7, 0x9AA5, 0x55D4, 0x9A70, 0x55DA, 0x9A6A, + 0x55DC, 0x9A6E, 0x55DF, 0x9A6C, 0x55E3, 0x8E6B, 0x55E4, 0x9A6F, 0x55F7, 0x9A72, 0x55F9, 0x9A77, 0x55FD, 0x9A75, 0x55FE, 0x9A74, + 0x5606, 0x9251, 0x5609, 0x89C3, 0x5614, 0x9A71, 0x5616, 0x9A73, 0x5617, 0x8FA6, 0x5618, 0x8952, 0x561B, 0x9A76, 0x5629, 0x89DC, + 0x562F, 0x9A82, 0x5631, 0x8FFA, 0x5632, 0x9A7D, 0x5634, 0x9A7B, 0x5636, 0x9A7C, 0x5638, 0x9A7E, 0x5642, 0x895C, 0x564C, 0x9158, + 0x564E, 0x9A78, 0x5650, 0x9A79, 0x565B, 0x8A9A, 0x5664, 0x9A81, 0x5668, 0x8AED, 0x566A, 0x9A84, 0x566B, 0x9A80, 0x566C, 0x9A83, + 0x5674, 0x95AC, 0x5678, 0x93D3, 0x567A, 0x94B6, 0x5680, 0x9A86, 0x5686, 0x9A85, 0x5687, 0x8A64, 0x568A, 0x9A87, 0x568F, 0x9A8A, + 0x5694, 0x9A89, 0x56A0, 0x9A88, 0x56A2, 0x9458, 0x56A5, 0x9A8B, 0x56AE, 0x9A8C, 0x56B4, 0x9A8E, 0x56B6, 0x9A8D, 0x56BC, 0x9A90, + 0x56C0, 0x9A93, 0x56C1, 0x9A91, 0x56C2, 0x9A8F, 0x56C3, 0x9A92, 0x56C8, 0x9A94, 0x56CE, 0x9A95, 0x56D1, 0x9A96, 0x56D3, 0x9A97, + 0x56D7, 0x9A98, 0x56D8, 0x9964, 0x56DA, 0x8EFA, 0x56DB, 0x8E6C, 0x56DE, 0x89F1, 0x56E0, 0x88F6, 0x56E3, 0x9263, 0x56EE, 0x9A99, + 0x56F0, 0x8DA2, 0x56F2, 0x88CD, 0x56F3, 0x907D, 0x56F9, 0x9A9A, 0x56FA, 0x8CC5, 0x56FD, 0x8D91, 0x56FF, 0x9A9C, 0x5700, 0x9A9B, + 0x5703, 0x95DE, 0x5704, 0x9A9D, 0x5708, 0x9A9F, 0x5709, 0x9A9E, 0x570B, 0x9AA0, 0x570D, 0x9AA1, 0x570F, 0x8C97, 0x5712, 0x8980, + 0x5713, 0x9AA2, 0x5716, 0x9AA4, 0x5718, 0x9AA3, 0x571C, 0x9AA6, 0x571F, 0x9379, 0x5726, 0x9AA7, 0x5727, 0x88B3, 0x5728, 0x8DDD, + 0x572D, 0x8C5C, 0x5730, 0x926E, 0x5737, 0x9AA8, 0x5738, 0x9AA9, 0x573B, 0x9AAB, 0x5740, 0x9AAC, 0x5742, 0x8DE2, 0x5747, 0x8BCF, + 0x574A, 0x9656, 0x574E, 0x9AAA, 0x574F, 0x9AAD, 0x5750, 0x8DBF, 0x5751, 0x8D42, 0x5759, 0xFA96, 0x5761, 0x9AB1, 0x5764, 0x8DA3, + 0x5765, 0xFA97, 0x5766, 0x9252, 0x5769, 0x9AAE, 0x576A, 0x92D8, 0x577F, 0x9AB2, 0x5782, 0x9082, 0x5788, 0x9AB0, 0x5789, 0x9AB3, + 0x578B, 0x8C5E, 0x5793, 0x9AB4, 0x57A0, 0x9AB5, 0x57A2, 0x8D43, 0x57A3, 0x8A5F, 0x57A4, 0x9AB7, 0x57AA, 0x9AB8, 0x57AC, 0xFA98, + 0x57B0, 0x9AB9, 0x57B3, 0x9AB6, 0x57C0, 0x9AAF, 0x57C3, 0x9ABA, 0x57C6, 0x9ABB, 0x57C7, 0xFA9A, 0x57C8, 0xFA99, 0x57CB, 0x9684, + 0x57CE, 0x8FE9, 0x57D2, 0x9ABD, 0x57D3, 0x9ABE, 0x57D4, 0x9ABC, 0x57D6, 0x9AC0, 0x57DC, 0x9457, 0x57DF, 0x88E6, 0x57E0, 0x9575, + 0x57E3, 0x9AC1, 0x57F4, 0x8FFB, 0x57F7, 0x8EB7, 0x57F9, 0x947C, 0x57FA, 0x8AEE, 0x57FC, 0x8DE9, 0x5800, 0x9678, 0x5802, 0x93B0, + 0x5805, 0x8C98, 0x5806, 0x91CD, 0x580A, 0x9ABF, 0x580B, 0x9AC2, 0x5815, 0x91C2, 0x5819, 0x9AC3, 0x581D, 0x9AC4, 0x5821, 0x9AC6, + 0x5824, 0x92E7, 0x582A, 0x8AAC, 0x582F, 0xEA9F, 0x5830, 0x8981, 0x5831, 0x95F1, 0x5834, 0x8FEA, 0x5835, 0x9367, 0x583A, 0x8DE4, + 0x583D, 0x9ACC, 0x5840, 0x95BB, 0x5841, 0x97DB, 0x584A, 0x89F2, 0x584B, 0x9AC8, 0x5851, 0x9159, 0x5852, 0x9ACB, 0x5854, 0x9383, + 0x5857, 0x9368, 0x5858, 0x9384, 0x5859, 0x94B7, 0x585A, 0x92CB, 0x585E, 0x8DC7, 0x5862, 0x9AC7, 0x5869, 0x8996, 0x586B, 0x9355, + 0x5870, 0x9AC9, 0x5872, 0x9AC5, 0x5875, 0x906F, 0x5879, 0x9ACD, 0x587E, 0x8F6D, 0x5883, 0x8BAB, 0x5885, 0x9ACE, 0x5893, 0x95E6, + 0x5897, 0x919D, 0x589C, 0x92C4, 0x589E, 0xFA9D, 0x589F, 0x9AD0, 0x58A8, 0x966E, 0x58AB, 0x9AD1, 0x58AE, 0x9AD6, 0x58B2, 0xFA9E, + 0x58B3, 0x95AD, 0x58B8, 0x9AD5, 0x58B9, 0x9ACF, 0x58BA, 0x9AD2, 0x58BB, 0x9AD4, 0x58BE, 0x8DA4, 0x58C1, 0x95C7, 0x58C5, 0x9AD7, + 0x58C7, 0x9264, 0x58CA, 0x89F3, 0x58CC, 0x8FEB, 0x58D1, 0x9AD9, 0x58D3, 0x9AD8, 0x58D5, 0x8D88, 0x58D7, 0x9ADA, 0x58D8, 0x9ADC, + 0x58D9, 0x9ADB, 0x58DC, 0x9ADE, 0x58DE, 0x9AD3, 0x58DF, 0x9AE0, 0x58E4, 0x9ADF, 0x58E5, 0x9ADD, 0x58EB, 0x8E6D, 0x58EC, 0x9070, + 0x58EE, 0x9173, 0x58EF, 0x9AE1, 0x58F0, 0x90BA, 0x58F1, 0x88EB, 0x58F2, 0x9484, 0x58F7, 0x92D9, 0x58F9, 0x9AE3, 0x58FA, 0x9AE2, + 0x58FB, 0x9AE4, 0x58FC, 0x9AE5, 0x58FD, 0x9AE6, 0x5902, 0x9AE7, 0x5909, 0x95CF, 0x590A, 0x9AE8, 0x590B, 0xFA9F, 0x590F, 0x89C4, + 0x5910, 0x9AE9, 0x5915, 0x975B, 0x5916, 0x8A4F, 0x5918, 0x99C7, 0x5919, 0x8F67, 0x591A, 0x91BD, 0x591B, 0x9AEA, 0x591C, 0x96E9, + 0x5922, 0x96B2, 0x5925, 0x9AEC, 0x5927, 0x91E5, 0x5929, 0x9356, 0x592A, 0x91BE, 0x592B, 0x9576, 0x592C, 0x9AED, 0x592D, 0x9AEE, + 0x592E, 0x899B, 0x5931, 0x8EB8, 0x5932, 0x9AEF, 0x5937, 0x88CE, 0x5938, 0x9AF0, 0x593E, 0x9AF1, 0x5944, 0x8982, 0x5947, 0x8AEF, + 0x5948, 0x93DE, 0x5949, 0x95F2, 0x594E, 0x9AF5, 0x594F, 0x9174, 0x5950, 0x9AF4, 0x5951, 0x8C5F, 0x5953, 0xFAA0, 0x5954, 0x967A, + 0x5955, 0x9AF3, 0x5957, 0x9385, 0x5958, 0x9AF7, 0x595A, 0x9AF6, 0x595B, 0xFAA1, 0x595D, 0xFAA2, 0x5960, 0x9AF9, 0x5962, 0x9AF8, + 0x5963, 0xFAA3, 0x5965, 0x899C, 0x5967, 0x9AFA, 0x5968, 0x8FA7, 0x5969, 0x9AFC, 0x596A, 0x9244, 0x596C, 0x9AFB, 0x596E, 0x95B1, + 0x5973, 0x8F97, 0x5974, 0x937A, 0x5978, 0x9B40, 0x597D, 0x8D44, 0x5981, 0x9B41, 0x5982, 0x9440, 0x5983, 0x94DC, 0x5984, 0x96CF, + 0x598A, 0x9444, 0x598D, 0x9B4A, 0x5993, 0x8B57, 0x5996, 0x9764, 0x5999, 0x96AD, 0x599B, 0x9BAA, 0x599D, 0x9B42, 0x59A3, 0x9B45, + 0x59A4, 0xFAA4, 0x59A5, 0x91C3, 0x59A8, 0x9657, 0x59AC, 0x9369, 0x59B2, 0x9B46, 0x59B9, 0x9685, 0x59BA, 0xFAA5, 0x59BB, 0x8DC8, + 0x59BE, 0x8FA8, 0x59C6, 0x9B47, 0x59C9, 0x8E6F, 0x59CB, 0x8E6E, 0x59D0, 0x88B7, 0x59D1, 0x8CC6, 0x59D3, 0x90A9, 0x59D4, 0x88CF, + 0x59D9, 0x9B4B, 0x59DA, 0x9B4C, 0x59DC, 0x9B49, 0x59E5, 0x8957, 0x59E6, 0x8AAD, 0x59E8, 0x9B48, 0x59EA, 0x96C3, 0x59EB, 0x9550, + 0x59F6, 0x88A6, 0x59FB, 0x88F7, 0x59FF, 0x8E70, 0x5A01, 0x88D0, 0x5A03, 0x88A1, 0x5A09, 0x9B51, 0x5A11, 0x9B4F, 0x5A18, 0x96BA, + 0x5A1A, 0x9B52, 0x5A1C, 0x9B50, 0x5A1F, 0x9B4E, 0x5A20, 0x9050, 0x5A25, 0x9B4D, 0x5A29, 0x95D8, 0x5A2F, 0x8CE2, 0x5A35, 0x9B56, + 0x5A36, 0x9B57, 0x5A3C, 0x8FA9, 0x5A40, 0x9B53, 0x5A41, 0x984B, 0x5A46, 0x946B, 0x5A49, 0x9B55, 0x5A5A, 0x8DA5, 0x5A62, 0x9B58, + 0x5A66, 0x9577, 0x5A6A, 0x9B59, 0x5A6C, 0x9B54, 0x5A7F, 0x96B9, 0x5A92, 0x947D, 0x5A9A, 0x9B5A, 0x5A9B, 0x9551, 0x5ABC, 0x9B5B, + 0x5ABD, 0x9B5F, 0x5ABE, 0x9B5C, 0x5AC1, 0x89C5, 0x5AC2, 0x9B5E, 0x5AC9, 0x8EB9, 0x5ACB, 0x9B5D, 0x5ACC, 0x8C99, 0x5AD0, 0x9B6B, + 0x5AD6, 0x9B64, 0x5AD7, 0x9B61, 0x5AE1, 0x9284, 0x5AE3, 0x9B60, 0x5AE6, 0x9B62, 0x5AE9, 0x9B63, 0x5AFA, 0x9B65, 0x5AFB, 0x9B66, + 0x5B09, 0x8AF0, 0x5B0B, 0x9B68, 0x5B0C, 0x9B67, 0x5B16, 0x9B69, 0x5B22, 0x8FEC, 0x5B2A, 0x9B6C, 0x5B2C, 0x92DA, 0x5B30, 0x8964, + 0x5B32, 0x9B6A, 0x5B36, 0x9B6D, 0x5B3E, 0x9B6E, 0x5B40, 0x9B71, 0x5B43, 0x9B6F, 0x5B45, 0x9B70, 0x5B50, 0x8E71, 0x5B51, 0x9B72, + 0x5B54, 0x8D45, 0x5B55, 0x9B73, 0x5B56, 0xFAA6, 0x5B57, 0x8E9A, 0x5B58, 0x91B6, 0x5B5A, 0x9B74, 0x5B5B, 0x9B75, 0x5B5C, 0x8E79, + 0x5B5D, 0x8D46, 0x5B5F, 0x96D0, 0x5B63, 0x8B47, 0x5B64, 0x8CC7, 0x5B65, 0x9B76, 0x5B66, 0x8A77, 0x5B69, 0x9B77, 0x5B6B, 0x91B7, + 0x5B70, 0x9B78, 0x5B71, 0x9BA1, 0x5B73, 0x9B79, 0x5B75, 0x9B7A, 0x5B78, 0x9B7B, 0x5B7A, 0x9B7D, 0x5B80, 0x9B7E, 0x5B83, 0x9B80, + 0x5B85, 0x91EE, 0x5B87, 0x8946, 0x5B88, 0x8EE7, 0x5B89, 0x88C0, 0x5B8B, 0x9176, 0x5B8C, 0x8AAE, 0x5B8D, 0x8EB3, 0x5B8F, 0x8D47, + 0x5B95, 0x9386, 0x5B97, 0x8F40, 0x5B98, 0x8AAF, 0x5B99, 0x9288, 0x5B9A, 0x92E8, 0x5B9B, 0x88B6, 0x5B9C, 0x8B58, 0x5B9D, 0x95F3, + 0x5B9F, 0x8EC0, 0x5BA2, 0x8B71, 0x5BA3, 0x90E9, 0x5BA4, 0x8EBA, 0x5BA5, 0x9747, 0x5BA6, 0x9B81, 0x5BAE, 0x8B7B, 0x5BB0, 0x8DC9, + 0x5BB3, 0x8A51, 0x5BB4, 0x8983, 0x5BB5, 0x8FAA, 0x5BB6, 0x89C6, 0x5BB8, 0x9B82, 0x5BB9, 0x9765, 0x5BBF, 0x8F68, 0x5BC0, 0xFAA7, + 0x5BC2, 0x8EE2, 0x5BC3, 0x9B83, 0x5BC4, 0x8AF1, 0x5BC5, 0x93D0, 0x5BC6, 0x96A7, 0x5BC7, 0x9B84, 0x5BC9, 0x9B85, 0x5BCC, 0x9578, + 0x5BD0, 0x9B87, 0x5BD2, 0x8AA6, 0x5BD3, 0x8BF5, 0x5BD4, 0x9B86, 0x5BD8, 0xFAA9, 0x5BDB, 0x8AB0, 0x5BDD, 0x9051, 0x5BDE, 0x9B8B, + 0x5BDF, 0x8E40, 0x5BE1, 0x89C7, 0x5BE2, 0x9B8A, 0x5BE4, 0x9B88, 0x5BE5, 0x9B8C, 0x5BE6, 0x9B89, 0x5BE7, 0x944A, 0x5BE8, 0x9ECB, + 0x5BE9, 0x9052, 0x5BEB, 0x9B8D, 0x5BEC, 0xFAAA, 0x5BEE, 0x97BE, 0x5BF0, 0x9B8E, 0x5BF3, 0x9B90, 0x5BF5, 0x929E, 0x5BF6, 0x9B8F, + 0x5BF8, 0x90A1, 0x5BFA, 0x8E9B, 0x5BFE, 0x91CE, 0x5BFF, 0x8EF5, 0x5C01, 0x9595, 0x5C02, 0x90EA, 0x5C04, 0x8ECB, 0x5C05, 0x9B91, + 0x5C06, 0x8FAB, 0x5C07, 0x9B92, 0x5C08, 0x9B93, 0x5C09, 0x88D1, 0x5C0A, 0x91B8, 0x5C0B, 0x9071, 0x5C0D, 0x9B94, 0x5C0E, 0x93B1, + 0x5C0F, 0x8FAC, 0x5C11, 0x8FAD, 0x5C13, 0x9B95, 0x5C16, 0x90EB, 0x5C1A, 0x8FAE, 0x5C1E, 0xFAAB, 0x5C20, 0x9B96, 0x5C22, 0x9B97, + 0x5C24, 0x96DE, 0x5C28, 0x9B98, 0x5C2D, 0x8BC4, 0x5C31, 0x8F41, 0x5C38, 0x9B99, 0x5C39, 0x9B9A, 0x5C3A, 0x8EDA, 0x5C3B, 0x904B, + 0x5C3C, 0x93F2, 0x5C3D, 0x9073, 0x5C3E, 0x94F6, 0x5C3F, 0x9441, 0x5C40, 0x8BC7, 0x5C41, 0x9B9B, 0x5C45, 0x8B8F, 0x5C46, 0x9B9C, + 0x5C48, 0x8BFC, 0x5C4A, 0x93CD, 0x5C4B, 0x89AE, 0x5C4D, 0x8E72, 0x5C4E, 0x9B9D, 0x5C4F, 0x9BA0, 0x5C50, 0x9B9F, 0x5C51, 0x8BFB, + 0x5C53, 0x9B9E, 0x5C55, 0x9357, 0x5C5E, 0x91AE, 0x5C60, 0x936A, 0x5C61, 0x8EC6, 0x5C64, 0x9177, 0x5C65, 0x979A, 0x5C6C, 0x9BA2, + 0x5C6E, 0x9BA3, 0x5C6F, 0x93D4, 0x5C71, 0x8E52, 0x5C76, 0x9BA5, 0x5C79, 0x9BA6, 0x5C8C, 0x9BA7, 0x5C90, 0x8AF2, 0x5C91, 0x9BA8, + 0x5C94, 0x9BA9, 0x5CA1, 0x89AA, 0x5CA6, 0xFAAC, 0x5CA8, 0x915A, 0x5CA9, 0x8AE2, 0x5CAB, 0x9BAB, 0x5CAC, 0x96A6, 0x5CB1, 0x91D0, + 0x5CB3, 0x8A78, 0x5CB6, 0x9BAD, 0x5CB7, 0x9BAF, 0x5CB8, 0x8ADD, 0x5CBA, 0xFAAD, 0x5CBB, 0x9BAC, 0x5CBC, 0x9BAE, 0x5CBE, 0x9BB1, + 0x5CC5, 0x9BB0, 0x5CC7, 0x9BB2, 0x5CD9, 0x9BB3, 0x5CE0, 0x93BB, 0x5CE1, 0x8BAC, 0x5CE8, 0x89E3, 0x5CE9, 0x9BB4, 0x5CEA, 0x9BB9, + 0x5CED, 0x9BB7, 0x5CEF, 0x95F5, 0x5CF0, 0x95F4, 0x5CF5, 0xFAAE, 0x5CF6, 0x9387, 0x5CFA, 0x9BB6, 0x5CFB, 0x8F73, 0x5CFD, 0x9BB5, + 0x5D07, 0x9092, 0x5D0B, 0x9BBA, 0x5D0E, 0x8DE8, 0x5D11, 0x9BC0, 0x5D14, 0x9BC1, 0x5D15, 0x9BBB, 0x5D16, 0x8A52, 0x5D17, 0x9BBC, + 0x5D18, 0x9BC5, 0x5D19, 0x9BC4, 0x5D1A, 0x9BC3, 0x5D1B, 0x9BBF, 0x5D1F, 0x9BBE, 0x5D22, 0x9BC2, 0x5D27, 0xFAAF, 0x5D29, 0x95F6, + 0x5D42, 0xFAB2, 0x5D4B, 0x9BC9, 0x5D4C, 0x9BC6, 0x5D4E, 0x9BC8, 0x5D50, 0x9792, 0x5D52, 0x9BC7, 0x5D53, 0xFAB0, 0x5D5C, 0x9BBD, + 0x5D69, 0x9093, 0x5D6C, 0x9BCA, 0x5D6D, 0xFAB3, 0x5D6F, 0x8DB5, 0x5D73, 0x9BCB, 0x5D76, 0x9BCC, 0x5D82, 0x9BCF, 0x5D84, 0x9BCE, + 0x5D87, 0x9BCD, 0x5D8B, 0x9388, 0x5D8C, 0x9BB8, 0x5D90, 0x9BD5, 0x5D9D, 0x9BD1, 0x5DA2, 0x9BD0, 0x5DAC, 0x9BD2, 0x5DAE, 0x9BD3, + 0x5DB7, 0x9BD6, 0x5DB8, 0xFAB4, 0x5DB9, 0xFAB5, 0x5DBA, 0x97E4, 0x5DBC, 0x9BD7, 0x5DBD, 0x9BD4, 0x5DC9, 0x9BD8, 0x5DCC, 0x8ADE, + 0x5DCD, 0x9BD9, 0x5DD0, 0xFAB6, 0x5DD2, 0x9BDB, 0x5DD3, 0x9BDA, 0x5DD6, 0x9BDC, 0x5DDB, 0x9BDD, 0x5DDD, 0x90EC, 0x5DDE, 0x8F42, + 0x5DE1, 0x8F84, 0x5DE3, 0x9183, 0x5DE5, 0x8D48, 0x5DE6, 0x8DB6, 0x5DE7, 0x8D49, 0x5DE8, 0x8B90, 0x5DEB, 0x9BDE, 0x5DEE, 0x8DB7, + 0x5DF1, 0x8CC8, 0x5DF2, 0x9BDF, 0x5DF3, 0x96A4, 0x5DF4, 0x9462, 0x5DF5, 0x9BE0, 0x5DF7, 0x8D4A, 0x5DFB, 0x8AAA, 0x5DFD, 0x9246, + 0x5DFE, 0x8BD0, 0x5E02, 0x8E73, 0x5E03, 0x957A, 0x5E06, 0x94BF, 0x5E0B, 0x9BE1, 0x5E0C, 0x8AF3, 0x5E11, 0x9BE4, 0x5E16, 0x929F, + 0x5E19, 0x9BE3, 0x5E1A, 0x9BE2, 0x5E1B, 0x9BE5, 0x5E1D, 0x92E9, 0x5E25, 0x9083, 0x5E2B, 0x8E74, 0x5E2D, 0x90C8, 0x5E2F, 0x91D1, + 0x5E30, 0x8B41, 0x5E33, 0x92A0, 0x5E36, 0x9BE6, 0x5E37, 0x9BE7, 0x5E38, 0x8FED, 0x5E3D, 0x9658, 0x5E40, 0x9BEA, 0x5E43, 0x9BE9, + 0x5E44, 0x9BE8, 0x5E45, 0x959D, 0x5E47, 0x9BF1, 0x5E4C, 0x9679, 0x5E4E, 0x9BEB, 0x5E54, 0x9BED, 0x5E55, 0x968B, 0x5E57, 0x9BEC, + 0x5E5F, 0x9BEE, 0x5E61, 0x94A6, 0x5E62, 0x9BEF, 0x5E63, 0x95BC, 0x5E64, 0x9BF0, 0x5E72, 0x8AB1, 0x5E73, 0x95BD, 0x5E74, 0x944E, + 0x5E75, 0x9BF2, 0x5E76, 0x9BF3, 0x5E78, 0x8D4B, 0x5E79, 0x8AB2, 0x5E7A, 0x9BF4, 0x5E7B, 0x8CB6, 0x5E7C, 0x9763, 0x5E7D, 0x9748, + 0x5E7E, 0x8AF4, 0x5E7F, 0x9BF6, 0x5E81, 0x92A1, 0x5E83, 0x8D4C, 0x5E84, 0x8FAF, 0x5E87, 0x94DD, 0x5E8A, 0x8FB0, 0x5E8F, 0x8F98, + 0x5E95, 0x92EA, 0x5E96, 0x95F7, 0x5E97, 0x9358, 0x5E9A, 0x8D4D, 0x5E9C, 0x957B, 0x5EA0, 0x9BF7, 0x5EA6, 0x9378, 0x5EA7, 0x8DC0, + 0x5EAB, 0x8CC9, 0x5EAD, 0x92EB, 0x5EB5, 0x88C1, 0x5EB6, 0x8F8E, 0x5EB7, 0x8D4E, 0x5EB8, 0x9766, 0x5EC1, 0x9BF8, 0x5EC2, 0x9BF9, + 0x5EC3, 0x9470, 0x5EC8, 0x9BFA, 0x5EC9, 0x97F5, 0x5ECA, 0x984C, 0x5ECF, 0x9BFC, 0x5ED0, 0x9BFB, 0x5ED3, 0x8A66, 0x5ED6, 0x9C40, + 0x5EDA, 0x9C43, 0x5EDB, 0x9C44, 0x5EDD, 0x9C42, 0x5EDF, 0x955F, 0x5EE0, 0x8FB1, 0x5EE1, 0x9C46, 0x5EE2, 0x9C45, 0x5EE3, 0x9C41, + 0x5EE8, 0x9C47, 0x5EE9, 0x9C48, 0x5EEC, 0x9C49, 0x5EF0, 0x9C4C, 0x5EF1, 0x9C4A, 0x5EF3, 0x9C4B, 0x5EF4, 0x9C4D, 0x5EF6, 0x8984, + 0x5EF7, 0x92EC, 0x5EF8, 0x9C4E, 0x5EFA, 0x8C9A, 0x5EFB, 0x89F4, 0x5EFC, 0x9455, 0x5EFE, 0x9C4F, 0x5EFF, 0x93F9, 0x5F01, 0x95D9, + 0x5F03, 0x9C50, 0x5F04, 0x984D, 0x5F09, 0x9C51, 0x5F0A, 0x95BE, 0x5F0B, 0x9C54, 0x5F0C, 0x989F, 0x5F0D, 0x98AF, 0x5F0F, 0x8EAE, + 0x5F10, 0x93F3, 0x5F11, 0x9C55, 0x5F13, 0x8B7C, 0x5F14, 0x92A2, 0x5F15, 0x88F8, 0x5F16, 0x9C56, 0x5F17, 0x95A4, 0x5F18, 0x8D4F, + 0x5F1B, 0x926F, 0x5F1F, 0x92ED, 0x5F21, 0xFAB7, 0x5F25, 0x96ED, 0x5F26, 0x8CB7, 0x5F27, 0x8CCA, 0x5F29, 0x9C57, 0x5F2D, 0x9C58, + 0x5F2F, 0x9C5E, 0x5F31, 0x8EE3, 0x5F34, 0xFAB8, 0x5F35, 0x92A3, 0x5F37, 0x8BAD, 0x5F38, 0x9C59, 0x5F3C, 0x954A, 0x5F3E, 0x9265, + 0x5F41, 0x9C5A, 0x5F45, 0xFA67, 0x5F48, 0x9C5B, 0x5F4A, 0x8BAE, 0x5F4C, 0x9C5C, 0x5F4E, 0x9C5D, 0x5F51, 0x9C5F, 0x5F53, 0x9396, + 0x5F56, 0x9C60, 0x5F57, 0x9C61, 0x5F59, 0x9C62, 0x5F5C, 0x9C53, 0x5F5D, 0x9C52, 0x5F61, 0x9C63, 0x5F62, 0x8C60, 0x5F66, 0x9546, + 0x5F67, 0xFAB9, 0x5F69, 0x8DCA, 0x5F6A, 0x9556, 0x5F6B, 0x92A4, 0x5F6C, 0x956A, 0x5F6D, 0x9C64, 0x5F70, 0x8FB2, 0x5F71, 0x8965, + 0x5F73, 0x9C65, 0x5F77, 0x9C66, 0x5F79, 0x96F0, 0x5F7C, 0x94DE, 0x5F7F, 0x9C69, 0x5F80, 0x899D, 0x5F81, 0x90AA, 0x5F82, 0x9C68, + 0x5F83, 0x9C67, 0x5F84, 0x8C61, 0x5F85, 0x91D2, 0x5F87, 0x9C6D, 0x5F88, 0x9C6B, 0x5F8A, 0x9C6A, 0x5F8B, 0x97A5, 0x5F8C, 0x8CE3, + 0x5F90, 0x8F99, 0x5F91, 0x9C6C, 0x5F92, 0x936B, 0x5F93, 0x8F5D, 0x5F97, 0x93BE, 0x5F98, 0x9C70, 0x5F99, 0x9C6F, 0x5F9E, 0x9C6E, + 0x5FA0, 0x9C71, 0x5FA1, 0x8CE4, 0x5FA8, 0x9C72, 0x5FA9, 0x959C, 0x5FAA, 0x8F7A, 0x5FAD, 0x9C73, 0x5FAE, 0x94F7, 0x5FB3, 0x93BF, + 0x5FB4, 0x92A5, 0x5FB7, 0xFABA, 0x5FB9, 0x934F, 0x5FBC, 0x9C74, 0x5FBD, 0x8B4A, 0x5FC3, 0x9053, 0x5FC5, 0x954B, 0x5FCC, 0x8AF5, + 0x5FCD, 0x9445, 0x5FD6, 0x9C75, 0x5FD7, 0x8E75, 0x5FD8, 0x9659, 0x5FD9, 0x965A, 0x5FDC, 0x899E, 0x5FDD, 0x9C7A, 0x5FDE, 0xFABB, + 0x5FE0, 0x9289, 0x5FE4, 0x9C77, 0x5FEB, 0x89F5, 0x5FF0, 0x9CAB, 0x5FF1, 0x9C79, 0x5FF5, 0x944F, 0x5FF8, 0x9C78, 0x5FFB, 0x9C76, + 0x5FFD, 0x8D9A, 0x5FFF, 0x9C7C, 0x600E, 0x9C83, 0x600F, 0x9C89, 0x6010, 0x9C81, 0x6012, 0x937B, 0x6015, 0x9C86, 0x6016, 0x957C, + 0x6019, 0x9C80, 0x601B, 0x9C85, 0x601C, 0x97E5, 0x601D, 0x8E76, 0x6020, 0x91D3, 0x6021, 0x9C7D, 0x6025, 0x8B7D, 0x6026, 0x9C88, + 0x6027, 0x90AB, 0x6028, 0x8985, 0x6029, 0x9C82, 0x602A, 0x89F6, 0x602B, 0x9C87, 0x602F, 0x8BAF, 0x6031, 0x9C84, 0x603A, 0x9C8A, + 0x6041, 0x9C8C, 0x6042, 0x9C96, 0x6043, 0x9C94, 0x6046, 0x9C91, 0x604A, 0x9C90, 0x604B, 0x97F6, 0x604D, 0x9C92, 0x6050, 0x8BB0, + 0x6052, 0x8D50, 0x6055, 0x8F9A, 0x6059, 0x9C99, 0x605A, 0x9C8B, 0x605D, 0xFABC, 0x605F, 0x9C8F, 0x6060, 0x9C7E, 0x6062, 0x89F8, + 0x6063, 0x9C93, 0x6064, 0x9C95, 0x6065, 0x9270, 0x6068, 0x8DA6, 0x6069, 0x89B6, 0x606A, 0x9C8D, 0x606B, 0x9C98, 0x606C, 0x9C97, + 0x606D, 0x8BB1, 0x606F, 0x91A7, 0x6070, 0x8A86, 0x6075, 0x8C62, 0x6077, 0x9C8E, 0x6081, 0x9C9A, 0x6083, 0x9C9D, 0x6084, 0x9C9F, + 0x6085, 0xFABD, 0x6089, 0x8EBB, 0x608A, 0xFABE, 0x608B, 0x9CA5, 0x608C, 0x92EE, 0x608D, 0x9C9B, 0x6092, 0x9CA3, 0x6094, 0x89F7, + 0x6096, 0x9CA1, 0x6097, 0x9CA2, 0x609A, 0x9C9E, 0x609B, 0x9CA0, 0x609F, 0x8CE5, 0x60A0, 0x9749, 0x60A3, 0x8AB3, 0x60A6, 0x8978, + 0x60A7, 0x9CA4, 0x60A9, 0x9459, 0x60AA, 0x88AB, 0x60B2, 0x94DF, 0x60B3, 0x9C7B, 0x60B4, 0x9CAA, 0x60B5, 0x9CAE, 0x60B6, 0x96E3, + 0x60B8, 0x9CA7, 0x60BC, 0x9389, 0x60BD, 0x9CAC, 0x60C5, 0x8FEE, 0x60C6, 0x9CAD, 0x60C7, 0x93D5, 0x60D1, 0x9866, 0x60D3, 0x9CA9, + 0x60D5, 0xFAC0, 0x60D8, 0x9CAF, 0x60DA, 0x8D9B, 0x60DC, 0x90C9, 0x60DE, 0xFABF, 0x60DF, 0x88D2, 0x60E0, 0x9CA8, 0x60E1, 0x9CA6, + 0x60E3, 0x9179, 0x60E7, 0x9C9C, 0x60E8, 0x8E53, 0x60F0, 0x91C4, 0x60F1, 0x9CBB, 0x60F2, 0xFAC2, 0x60F3, 0x917A, 0x60F4, 0x9CB6, + 0x60F6, 0x9CB3, 0x60F7, 0x9CB4, 0x60F9, 0x8EE4, 0x60FA, 0x9CB7, 0x60FB, 0x9CBA, 0x6100, 0x9CB5, 0x6101, 0x8F44, 0x6103, 0x9CB8, + 0x6106, 0x9CB2, 0x6108, 0x96FA, 0x6109, 0x96F9, 0x610D, 0x9CBC, 0x610E, 0x9CBD, 0x610F, 0x88D3, 0x6111, 0xFAC3, 0x6115, 0x9CB1, + 0x611A, 0x8BF0, 0x611B, 0x88A4, 0x611F, 0x8AB4, 0x6120, 0xFAC1, 0x6121, 0x9CB9, 0x6127, 0x9CC1, 0x6128, 0x9CC0, 0x612C, 0x9CC5, + 0x6130, 0xFAC5, 0x6134, 0x9CC6, 0x6137, 0xFAC4, 0x613C, 0x9CC4, 0x613D, 0x9CC7, 0x613E, 0x9CBF, 0x613F, 0x9CC3, 0x6142, 0x9CC8, + 0x6144, 0x9CC9, 0x6147, 0x9CBE, 0x6148, 0x8E9C, 0x614A, 0x9CC2, 0x614B, 0x91D4, 0x614C, 0x8D51, 0x614D, 0x9CB0, 0x614E, 0x9054, + 0x6153, 0x9CD6, 0x6155, 0x95E7, 0x6158, 0x9CCC, 0x6159, 0x9CCD, 0x615A, 0x9CCE, 0x615D, 0x9CD5, 0x615F, 0x9CD4, 0x6162, 0x969D, + 0x6163, 0x8AB5, 0x6165, 0x9CD2, 0x6167, 0x8C64, 0x6168, 0x8A53, 0x616B, 0x9CCF, 0x616E, 0x97B6, 0x616F, 0x9CD1, 0x6170, 0x88D4, + 0x6171, 0x9CD3, 0x6173, 0x9CCA, 0x6174, 0x9CD0, 0x6175, 0x9CD7, 0x6176, 0x8C63, 0x6177, 0x9CCB, 0x617E, 0x977C, 0x6182, 0x974A, + 0x6187, 0x9CDA, 0x618A, 0x9CDE, 0x618E, 0x919E, 0x6190, 0x97F7, 0x6191, 0x9CDF, 0x6194, 0x9CDC, 0x6196, 0x9CD9, 0x6198, 0xFAC6, + 0x6199, 0x9CD8, 0x619A, 0x9CDD, 0x61A4, 0x95AE, 0x61A7, 0x93B2, 0x61A9, 0x8C65, 0x61AB, 0x9CE0, 0x61AC, 0x9CDB, 0x61AE, 0x9CE1, + 0x61B2, 0x8C9B, 0x61B6, 0x89AF, 0x61BA, 0x9CE9, 0x61BE, 0x8AB6, 0x61C3, 0x9CE7, 0x61C6, 0x9CE8, 0x61C7, 0x8DA7, 0x61C8, 0x9CE6, + 0x61C9, 0x9CE4, 0x61CA, 0x9CE3, 0x61CB, 0x9CEA, 0x61CC, 0x9CE2, 0x61CD, 0x9CEC, 0x61D0, 0x89F9, 0x61E3, 0x9CEE, 0x61E6, 0x9CED, + 0x61F2, 0x92A6, 0x61F4, 0x9CF1, 0x61F6, 0x9CEF, 0x61F7, 0x9CE5, 0x61F8, 0x8C9C, 0x61FA, 0x9CF0, 0x61FC, 0x9CF4, 0x61FD, 0x9CF3, + 0x61FE, 0x9CF5, 0x61FF, 0x9CF2, 0x6200, 0x9CF6, 0x6208, 0x9CF7, 0x6209, 0x9CF8, 0x620A, 0x95E8, 0x620C, 0x9CFA, 0x620D, 0x9CF9, + 0x620E, 0x8F5E, 0x6210, 0x90AC, 0x6211, 0x89E4, 0x6212, 0x89FA, 0x6213, 0xFAC7, 0x6214, 0x9CFB, 0x6216, 0x88BD, 0x621A, 0x90CA, + 0x621B, 0x9CFC, 0x621D, 0xE6C1, 0x621E, 0x9D40, 0x621F, 0x8C81, 0x6221, 0x9D41, 0x6226, 0x90ED, 0x622A, 0x9D42, 0x622E, 0x9D43, + 0x622F, 0x8B59, 0x6230, 0x9D44, 0x6232, 0x9D45, 0x6233, 0x9D46, 0x6234, 0x91D5, 0x6238, 0x8CCB, 0x623B, 0x96DF, 0x623F, 0x965B, + 0x6240, 0x8F8A, 0x6241, 0x9D47, 0x6247, 0x90EE, 0x6248, 0xE7BB, 0x6249, 0x94E0, 0x624B, 0x8EE8, 0x624D, 0x8DCB, 0x624E, 0x9D48, + 0x6253, 0x91C5, 0x6255, 0x95A5, 0x6258, 0x91EF, 0x625B, 0x9D4B, 0x625E, 0x9D49, 0x6260, 0x9D4C, 0x6263, 0x9D4A, 0x6268, 0x9D4D, + 0x626E, 0x95AF, 0x6271, 0x88B5, 0x6276, 0x957D, 0x6279, 0x94E1, 0x627C, 0x9D4E, 0x627E, 0x9D51, 0x627F, 0x8FB3, 0x6280, 0x8B5A, + 0x6282, 0x9D4F, 0x6283, 0x9D56, 0x6284, 0x8FB4, 0x6289, 0x9D50, 0x628A, 0x9463, 0x6291, 0x977D, 0x6292, 0x9D52, 0x6293, 0x9D53, + 0x6294, 0x9D57, 0x6295, 0x938A, 0x6296, 0x9D54, 0x6297, 0x8D52, 0x6298, 0x90DC, 0x629B, 0x9D65, 0x629C, 0x94B2, 0x629E, 0x91F0, + 0x62A6, 0xFAC8, 0x62AB, 0x94E2, 0x62AC, 0x9DAB, 0x62B1, 0x95F8, 0x62B5, 0x92EF, 0x62B9, 0x9695, 0x62BB, 0x9D5A, 0x62BC, 0x899F, + 0x62BD, 0x928A, 0x62C2, 0x9D63, 0x62C5, 0x9253, 0x62C6, 0x9D5D, 0x62C7, 0x9D64, 0x62C8, 0x9D5F, 0x62C9, 0x9D66, 0x62CA, 0x9D62, + 0x62CC, 0x9D61, 0x62CD, 0x948F, 0x62CF, 0x9D5B, 0x62D0, 0x89FB, 0x62D1, 0x9D59, 0x62D2, 0x8B91, 0x62D3, 0x91F1, 0x62D4, 0x9D55, + 0x62D7, 0x9D58, 0x62D8, 0x8D53, 0x62D9, 0x90D9, 0x62DB, 0x8FB5, 0x62DC, 0x9D60, 0x62DD, 0x9471, 0x62E0, 0x8B92, 0x62E1, 0x8A67, + 0x62EC, 0x8A87, 0x62ED, 0x9040, 0x62EE, 0x9D68, 0x62EF, 0x9D6D, 0x62F1, 0x9D69, 0x62F3, 0x8C9D, 0x62F5, 0x9D6E, 0x62F6, 0x8E41, + 0x62F7, 0x8D89, 0x62FE, 0x8F45, 0x62FF, 0x9D5C, 0x6301, 0x8E9D, 0x6302, 0x9D6B, 0x6307, 0x8E77, 0x6308, 0x9D6C, 0x6309, 0x88C2, + 0x630C, 0x9D67, 0x6311, 0x92A7, 0x6319, 0x8B93, 0x631F, 0x8BB2, 0x6327, 0x9D6A, 0x6328, 0x88A5, 0x632B, 0x8DC1, 0x632F, 0x9055, + 0x633A, 0x92F0, 0x633D, 0x94D2, 0x633E, 0x9D70, 0x633F, 0x917D, 0x6349, 0x91A8, 0x634C, 0x8E4A, 0x634D, 0x9D71, 0x634F, 0x9D73, + 0x6350, 0x9D6F, 0x6355, 0x95DF, 0x6357, 0x92BB, 0x635C, 0x917B, 0x6367, 0x95F9, 0x6368, 0x8ECC, 0x6369, 0x9D80, 0x636B, 0x9D7E, + 0x636E, 0x9098, 0x6372, 0x8C9E, 0x6376, 0x9D78, 0x6377, 0x8FB7, 0x637A, 0x93E6, 0x637B, 0x9450, 0x6380, 0x9D76, 0x6383, 0x917C, + 0x6388, 0x8EF6, 0x6389, 0x9D7B, 0x638C, 0x8FB6, 0x638E, 0x9D75, 0x638F, 0x9D7A, 0x6392, 0x9472, 0x6396, 0x9D74, 0x6398, 0x8C40, + 0x639B, 0x8A7C, 0x639F, 0x9D7C, 0x63A0, 0x97A9, 0x63A1, 0x8DCC, 0x63A2, 0x9254, 0x63A3, 0x9D79, 0x63A5, 0x90DA, 0x63A7, 0x8D54, + 0x63A8, 0x9084, 0x63A9, 0x8986, 0x63AA, 0x915B, 0x63AB, 0x9D77, 0x63AC, 0x8B64, 0x63B2, 0x8C66, 0x63B4, 0x92CD, 0x63B5, 0x9D7D, + 0x63BB, 0x917E, 0x63BE, 0x9D81, 0x63C0, 0x9D83, 0x63C3, 0x91B5, 0x63C4, 0x9D89, 0x63C6, 0x9D84, 0x63C9, 0x9D86, 0x63CF, 0x9560, + 0x63D0, 0x92F1, 0x63D2, 0x9D87, 0x63D6, 0x974B, 0x63DA, 0x9767, 0x63DB, 0x8AB7, 0x63E1, 0x88AC, 0x63E3, 0x9D85, 0x63E9, 0x9D82, + 0x63EE, 0x8AF6, 0x63F4, 0x8987, 0x63F5, 0xFAC9, 0x63F6, 0x9D88, 0x63FA, 0x9768, 0x6406, 0x9D8C, 0x640D, 0x91B9, 0x640F, 0x9D93, + 0x6413, 0x9D8D, 0x6416, 0x9D8A, 0x6417, 0x9D91, 0x641C, 0x9D72, 0x6426, 0x9D8E, 0x6428, 0x9D92, 0x642C, 0x94C0, 0x642D, 0x938B, + 0x6434, 0x9D8B, 0x6436, 0x9D8F, 0x643A, 0x8C67, 0x643E, 0x8DEF, 0x6442, 0x90DB, 0x644E, 0x9D97, 0x6458, 0x9345, 0x6460, 0xFACA, + 0x6467, 0x9D94, 0x6469, 0x9680, 0x646F, 0x9D95, 0x6476, 0x9D96, 0x6478, 0x96CC, 0x647A, 0x90A0, 0x6483, 0x8C82, 0x6488, 0x9D9D, + 0x6492, 0x8E54, 0x6493, 0x9D9A, 0x6495, 0x9D99, 0x649A, 0x9451, 0x649D, 0xFACB, 0x649E, 0x93B3, 0x64A4, 0x9350, 0x64A5, 0x9D9B, + 0x64A9, 0x9D9C, 0x64AB, 0x958F, 0x64AD, 0x9464, 0x64AE, 0x8E42, 0x64B0, 0x90EF, 0x64B2, 0x966F, 0x64B9, 0x8A68, 0x64BB, 0x9DA3, + 0x64BC, 0x9D9E, 0x64C1, 0x9769, 0x64C2, 0x9DA5, 0x64C5, 0x9DA1, 0x64C7, 0x9DA2, 0x64CD, 0x9180, 0x64CE, 0xFACC, 0x64D2, 0x9DA0, + 0x64D4, 0x9D5E, 0x64D8, 0x9DA4, 0x64DA, 0x9D9F, 0x64E0, 0x9DA9, 0x64E1, 0x9DAA, 0x64E2, 0x9346, 0x64E3, 0x9DAC, 0x64E6, 0x8E43, + 0x64E7, 0x9DA7, 0x64EC, 0x8B5B, 0x64EF, 0x9DAD, 0x64F1, 0x9DA6, 0x64F2, 0x9DB1, 0x64F4, 0x9DB0, 0x64F6, 0x9DAF, 0x64FA, 0x9DB2, + 0x64FD, 0x9DB4, 0x64FE, 0x8FEF, 0x6500, 0x9DB3, 0x6505, 0x9DB7, 0x6518, 0x9DB5, 0x651C, 0x9DB6, 0x651D, 0x9D90, 0x6523, 0x9DB9, + 0x6524, 0x9DB8, 0x652A, 0x9D98, 0x652B, 0x9DBA, 0x652C, 0x9DAE, 0x652F, 0x8E78, 0x6534, 0x9DBB, 0x6535, 0x9DBC, 0x6536, 0x9DBE, + 0x6537, 0x9DBD, 0x6538, 0x9DBF, 0x6539, 0x89FC, 0x653B, 0x8D55, 0x653E, 0x95FA, 0x653F, 0x90AD, 0x6545, 0x8CCC, 0x6548, 0x9DC1, + 0x654D, 0x9DC4, 0x654E, 0xFACD, 0x654F, 0x9571, 0x6551, 0x8B7E, 0x6555, 0x9DC3, 0x6556, 0x9DC2, 0x6557, 0x9473, 0x6558, 0x9DC5, + 0x6559, 0x8BB3, 0x655D, 0x9DC7, 0x655E, 0x9DC6, 0x6562, 0x8AB8, 0x6563, 0x8E55, 0x6566, 0x93D6, 0x656C, 0x8C68, 0x6570, 0x9094, + 0x6572, 0x9DC8, 0x6574, 0x90AE, 0x6575, 0x9347, 0x6577, 0x957E, 0x6578, 0x9DC9, 0x6582, 0x9DCA, 0x6583, 0x9DCB, 0x6587, 0x95B6, + 0x6588, 0x9B7C, 0x6589, 0x90C4, 0x658C, 0x956B, 0x658E, 0x8DD6, 0x6590, 0x94E3, 0x6591, 0x94C1, 0x6597, 0x936C, 0x6599, 0x97BF, + 0x659B, 0x9DCD, 0x659C, 0x8ECE, 0x659F, 0x9DCE, 0x65A1, 0x88B4, 0x65A4, 0x8BD2, 0x65A5, 0x90CB, 0x65A7, 0x9580, 0x65AB, 0x9DCF, + 0x65AC, 0x8E61, 0x65AD, 0x9266, 0x65AF, 0x8E7A, 0x65B0, 0x9056, 0x65B7, 0x9DD0, 0x65B9, 0x95FB, 0x65BC, 0x8997, 0x65BD, 0x8E7B, + 0x65C1, 0x9DD3, 0x65C3, 0x9DD1, 0x65C4, 0x9DD4, 0x65C5, 0x97B7, 0x65C6, 0x9DD2, 0x65CB, 0x90F9, 0x65CC, 0x9DD5, 0x65CF, 0x91B0, + 0x65D2, 0x9DD6, 0x65D7, 0x8AF8, 0x65D9, 0x9DD8, 0x65DB, 0x9DD7, 0x65E0, 0x9DD9, 0x65E1, 0x9DDA, 0x65E2, 0x8AF9, 0x65E5, 0x93FA, + 0x65E6, 0x9255, 0x65E7, 0x8B8C, 0x65E8, 0x8E7C, 0x65E9, 0x9181, 0x65EC, 0x8F7B, 0x65ED, 0x88AE, 0x65F1, 0x9DDB, 0x65FA, 0x89A0, + 0x65FB, 0x9DDF, 0x6600, 0xFACE, 0x6602, 0x8D56, 0x6603, 0x9DDE, 0x6606, 0x8DA9, 0x6607, 0x8FB8, 0x6609, 0xFAD1, 0x660A, 0x9DDD, + 0x660C, 0x8FB9, 0x660E, 0x96BE, 0x660F, 0x8DA8, 0x6613, 0x88D5, 0x6614, 0x90CC, 0x6615, 0xFACF, 0x661C, 0x9DE4, 0x661E, 0xFAD3, + 0x661F, 0x90AF, 0x6620, 0x8966, 0x6624, 0xFAD4, 0x6625, 0x8F74, 0x6627, 0x9686, 0x6628, 0x8DF0, 0x662D, 0x8FBA, 0x662E, 0xFAD2, + 0x662F, 0x90A5, 0x6631, 0xFA63, 0x6634, 0x9DE3, 0x6635, 0x9DE1, 0x6636, 0x9DE2, 0x663B, 0xFAD0, 0x663C, 0x928B, 0x663F, 0x9E45, + 0x6641, 0x9DE8, 0x6642, 0x8E9E, 0x6643, 0x8D57, 0x6644, 0x9DE6, 0x6649, 0x9DE7, 0x664B, 0x9057, 0x664F, 0x9DE5, 0x6652, 0x8E4E, + 0x6657, 0xFAD6, 0x6659, 0xFAD7, 0x665D, 0x9DEA, 0x665E, 0x9DE9, 0x665F, 0x9DEE, 0x6662, 0x9DEF, 0x6664, 0x9DEB, 0x6665, 0xFAD5, + 0x6666, 0x8A41, 0x6667, 0x9DEC, 0x6668, 0x9DED, 0x6669, 0x94D3, 0x666E, 0x9581, 0x666F, 0x8C69, 0x6670, 0x9DF0, 0x6673, 0xFAD9, + 0x6674, 0x90B0, 0x6676, 0x8FBB, 0x667A, 0x9271, 0x6681, 0x8BC5, 0x6683, 0x9DF1, 0x6684, 0x9DF5, 0x6687, 0x89C9, 0x6688, 0x9DF2, + 0x6689, 0x9DF4, 0x668E, 0x9DF3, 0x6691, 0x8F8B, 0x6696, 0x9267, 0x6697, 0x88C3, 0x6698, 0x9DF6, 0x6699, 0xFADA, 0x669D, 0x9DF7, + 0x66A0, 0xFADB, 0x66A2, 0x92A8, 0x66A6, 0x97EF, 0x66AB, 0x8E62, 0x66AE, 0x95E9, 0x66B2, 0xFADC, 0x66B4, 0x965C, 0x66B8, 0x9E41, + 0x66B9, 0x9DF9, 0x66BC, 0x9DFC, 0x66BE, 0x9DFB, 0x66BF, 0xFADD, 0x66C1, 0x9DF8, 0x66C4, 0x9E40, 0x66C7, 0x93DC, 0x66C9, 0x9DFA, + 0x66D6, 0x9E42, 0x66D9, 0x8F8C, 0x66DA, 0x9E43, 0x66DC, 0x976A, 0x66DD, 0x9498, 0x66E0, 0x9E44, 0x66E6, 0x9E46, 0x66E9, 0x9E47, + 0x66F0, 0x9E48, 0x66F2, 0x8BC8, 0x66F3, 0x8967, 0x66F4, 0x8D58, 0x66F5, 0x9E49, 0x66F7, 0x9E4A, 0x66F8, 0x8F91, 0x66F9, 0x9182, + 0x66FA, 0xFADE, 0x66FB, 0xFA66, 0x66FC, 0x99D6, 0x66FD, 0x915D, 0x66FE, 0x915C, 0x66FF, 0x91D6, 0x6700, 0x8DC5, 0x6703, 0x98F0, + 0x6708, 0x8C8E, 0x6709, 0x974C, 0x670B, 0x95FC, 0x670D, 0x959E, 0x670E, 0xFADF, 0x670F, 0x9E4B, 0x6714, 0x8DF1, 0x6715, 0x92BD, + 0x6716, 0x9E4C, 0x6717, 0x984E, 0x671B, 0x965D, 0x671D, 0x92A9, 0x671E, 0x9E4D, 0x671F, 0x8AFA, 0x6726, 0x9E4E, 0x6727, 0x9E4F, + 0x6728, 0x96D8, 0x672A, 0x96A2, 0x672B, 0x9696, 0x672C, 0x967B, 0x672D, 0x8E44, 0x672E, 0x9E51, 0x6731, 0x8EE9, 0x6734, 0x9670, + 0x6736, 0x9E53, 0x6737, 0x9E56, 0x6738, 0x9E55, 0x673A, 0x8AF7, 0x673D, 0x8B80, 0x673F, 0x9E52, 0x6741, 0x9E54, 0x6746, 0x9E57, + 0x6749, 0x9099, 0x674E, 0x979B, 0x674F, 0x88C7, 0x6750, 0x8DDE, 0x6751, 0x91BA, 0x6753, 0x8EDB, 0x6756, 0x8FF1, 0x6759, 0x9E5A, + 0x675C, 0x936D, 0x675E, 0x9E58, 0x675F, 0x91A9, 0x6760, 0x9E59, 0x6761, 0x8FF0, 0x6762, 0x96DB, 0x6763, 0x9E5B, 0x6764, 0x9E5C, + 0x6765, 0x9788, 0x6766, 0xFAE1, 0x676A, 0x9E61, 0x676D, 0x8D59, 0x676F, 0x9474, 0x6770, 0x9E5E, 0x6771, 0x938C, 0x6772, 0x9DDC, + 0x6773, 0x9DE0, 0x6775, 0x8B6E, 0x6777, 0x9466, 0x677C, 0x9E60, 0x677E, 0x8FBC, 0x677F, 0x94C2, 0x6785, 0x9E66, 0x6787, 0x94F8, + 0x6789, 0x9E5D, 0x678B, 0x9E63, 0x678C, 0x9E62, 0x6790, 0x90CD, 0x6795, 0x968D, 0x6797, 0x97D1, 0x679A, 0x9687, 0x679C, 0x89CA, + 0x679D, 0x8E7D, 0x67A0, 0x9867, 0x67A1, 0x9E65, 0x67A2, 0x9095, 0x67A6, 0x9E64, 0x67A9, 0x9E5F, 0x67AF, 0x8CCD, 0x67B3, 0x9E6B, + 0x67B4, 0x9E69, 0x67B6, 0x89CB, 0x67B7, 0x9E67, 0x67B8, 0x9E6D, 0x67B9, 0x9E73, 0x67BB, 0xFAE2, 0x67C0, 0xFAE4, 0x67C1, 0x91C6, + 0x67C4, 0x95BF, 0x67C6, 0x9E75, 0x67CA, 0x9541, 0x67CE, 0x9E74, 0x67CF, 0x9490, 0x67D0, 0x965E, 0x67D1, 0x8AB9, 0x67D3, 0x90F5, + 0x67D4, 0x8F5F, 0x67D8, 0x92D1, 0x67DA, 0x974D, 0x67DD, 0x9E70, 0x67DE, 0x9E6F, 0x67E2, 0x9E71, 0x67E4, 0x9E6E, 0x67E7, 0x9E76, + 0x67E9, 0x9E6C, 0x67EC, 0x9E6A, 0x67EE, 0x9E72, 0x67EF, 0x9E68, 0x67F1, 0x928C, 0x67F3, 0x96F6, 0x67F4, 0x8EC4, 0x67F5, 0x8DF2, + 0x67FB, 0x8DB8, 0x67FE, 0x968F, 0x67FF, 0x8A60, 0x6801, 0xFAE5, 0x6802, 0x92CC, 0x6803, 0x93C8, 0x6804, 0x8968, 0x6813, 0x90F0, + 0x6816, 0x90B2, 0x6817, 0x8C49, 0x681E, 0x9E78, 0x6821, 0x8D5A, 0x6822, 0x8A9C, 0x6829, 0x9E7A, 0x682A, 0x8A94, 0x682B, 0x9E81, + 0x6832, 0x9E7D, 0x6834, 0x90F1, 0x6838, 0x8A6A, 0x6839, 0x8DAA, 0x683C, 0x8A69, 0x683D, 0x8DCD, 0x6840, 0x9E7B, 0x6841, 0x8C85, + 0x6842, 0x8C6A, 0x6843, 0x938D, 0x6844, 0xFAE6, 0x6846, 0x9E79, 0x6848, 0x88C4, 0x684D, 0x9E7C, 0x684E, 0x9E7E, 0x6850, 0x8BCB, + 0x6851, 0x8C4B, 0x6852, 0xFAE3, 0x6853, 0x8ABA, 0x6854, 0x8B6A, 0x6859, 0x9E82, 0x685C, 0x8DF7, 0x685D, 0x9691, 0x685F, 0x8E56, + 0x6863, 0x9E83, 0x6867, 0x954F, 0x6874, 0x9E8F, 0x6876, 0x89B1, 0x6877, 0x9E84, 0x687E, 0x9E95, 0x687F, 0x9E85, 0x6881, 0x97C0, + 0x6883, 0x9E8C, 0x6885, 0x947E, 0x688D, 0x9E94, 0x688F, 0x9E87, 0x6893, 0x88B2, 0x6894, 0x9E89, 0x6897, 0x8D5B, 0x689B, 0x9E8B, + 0x689D, 0x9E8A, 0x689F, 0x9E86, 0x68A0, 0x9E91, 0x68A2, 0x8FBD, 0x68A6, 0x9AEB, 0x68A7, 0x8CE6, 0x68A8, 0x979C, 0x68AD, 0x9E88, + 0x68AF, 0x92F2, 0x68B0, 0x8A42, 0x68B1, 0x8DAB, 0x68B3, 0x9E80, 0x68B5, 0x9E90, 0x68B6, 0x8A81, 0x68B9, 0x9E8E, 0x68BA, 0x9E92, + 0x68BC, 0x938E, 0x68C4, 0x8AFC, 0x68C6, 0x9EB0, 0x68C8, 0xFA64, 0x68C9, 0x96C7, 0x68CA, 0x9E97, 0x68CB, 0x8AFB, 0x68CD, 0x9E9E, + 0x68CF, 0xFAE7, 0x68D2, 0x965F, 0x68D4, 0x9E9F, 0x68D5, 0x9EA1, 0x68D7, 0x9EA5, 0x68D8, 0x9E99, 0x68DA, 0x9249, 0x68DF, 0x938F, + 0x68E0, 0x9EA9, 0x68E1, 0x9E9C, 0x68E3, 0x9EA6, 0x68E7, 0x9EA0, 0x68EE, 0x9058, 0x68EF, 0x9EAA, 0x68F2, 0x90B1, 0x68F9, 0x9EA8, + 0x68FA, 0x8ABB, 0x6900, 0x986F, 0x6901, 0x9E96, 0x6904, 0x9EA4, 0x6905, 0x88D6, 0x6908, 0x9E98, 0x690B, 0x96B8, 0x690C, 0x9E9D, + 0x690D, 0x9041, 0x690E, 0x92C5, 0x690F, 0x9E93, 0x6912, 0x9EA3, 0x6919, 0x909A, 0x691A, 0x9EAD, 0x691B, 0x8A91, 0x691C, 0x8C9F, + 0x6921, 0x9EAF, 0x6922, 0x9E9A, 0x6923, 0x9EAE, 0x6925, 0x9EA7, 0x6926, 0x9E9B, 0x6928, 0x9EAB, 0x692A, 0x9EAC, 0x6930, 0x9EBD, + 0x6934, 0x93CC, 0x6936, 0x9EA2, 0x6939, 0x9EB9, 0x693D, 0x9EBB, 0x693F, 0x92D6, 0x694A, 0x976B, 0x6953, 0x9596, 0x6954, 0x9EB6, + 0x6955, 0x91C8, 0x6959, 0x9EBC, 0x695A, 0x915E, 0x695C, 0x9EB3, 0x695D, 0x9EC0, 0x695E, 0x9EBF, 0x6960, 0x93ED, 0x6961, 0x9EBE, + 0x6962, 0x93E8, 0x6968, 0xFAE9, 0x696A, 0x9EC2, 0x696B, 0x9EB5, 0x696D, 0x8BC6, 0x696E, 0x9EB8, 0x696F, 0x8F7C, 0x6973, 0x9480, + 0x6974, 0x9EBA, 0x6975, 0x8BC9, 0x6977, 0x9EB2, 0x6978, 0x9EB4, 0x6979, 0x9EB1, 0x697C, 0x984F, 0x697D, 0x8A79, 0x697E, 0x9EB7, + 0x6981, 0x9EC1, 0x6982, 0x8A54, 0x698A, 0x8DE5, 0x698E, 0x897C, 0x6991, 0x9ED2, 0x6994, 0x9850, 0x6995, 0x9ED5, 0x6998, 0xFAEB, + 0x699B, 0x9059, 0x699C, 0x9ED4, 0x69A0, 0x9ED3, 0x69A7, 0x9ED0, 0x69AE, 0x9EC4, 0x69B1, 0x9EE1, 0x69B2, 0x9EC3, 0x69B4, 0x9ED6, + 0x69BB, 0x9ECE, 0x69BE, 0x9EC9, 0x69BF, 0x9EC6, 0x69C1, 0x9EC7, 0x69C3, 0x9ECF, 0x69C7, 0xEAA0, 0x69CA, 0x9ECC, 0x69CB, 0x8D5C, + 0x69CC, 0x92C6, 0x69CD, 0x9184, 0x69CE, 0x9ECA, 0x69D0, 0x9EC5, 0x69D3, 0x9EC8, 0x69D8, 0x976C, 0x69D9, 0x968A, 0x69DD, 0x9ECD, + 0x69DE, 0x9ED7, 0x69E2, 0xFAEC, 0x69E7, 0x9EDF, 0x69E8, 0x9ED8, 0x69EB, 0x9EE5, 0x69ED, 0x9EE3, 0x69F2, 0x9EDE, 0x69F9, 0x9EDD, + 0x69FB, 0x92CE, 0x69FD, 0x9185, 0x69FF, 0x9EDB, 0x6A02, 0x9ED9, 0x6A05, 0x9EE0, 0x6A0A, 0x9EE6, 0x6A0B, 0x94F3, 0x6A0C, 0x9EEC, + 0x6A12, 0x9EE7, 0x6A13, 0x9EEA, 0x6A14, 0x9EE4, 0x6A17, 0x9294, 0x6A19, 0x9557, 0x6A1B, 0x9EDA, 0x6A1E, 0x9EE2, 0x6A1F, 0x8FBE, + 0x6A21, 0x96CD, 0x6A22, 0x9EF6, 0x6A23, 0x9EE9, 0x6A29, 0x8CA0, 0x6A2A, 0x89A1, 0x6A2B, 0x8A7E, 0x6A2E, 0x9ED1, 0x6A30, 0xFAED, + 0x6A35, 0x8FBF, 0x6A36, 0x9EEE, 0x6A38, 0x9EF5, 0x6A39, 0x8EF7, 0x6A3A, 0x8A92, 0x6A3D, 0x924D, 0x6A44, 0x9EEB, 0x6A46, 0xFAEF, + 0x6A47, 0x9EF0, 0x6A48, 0x9EF4, 0x6A4B, 0x8BB4, 0x6A58, 0x8B6B, 0x6A59, 0x9EF2, 0x6A5F, 0x8B40, 0x6A61, 0x93C9, 0x6A62, 0x9EF1, + 0x6A66, 0x9EF3, 0x6A6B, 0xFAEE, 0x6A72, 0x9EED, 0x6A73, 0xFAF0, 0x6A78, 0x9EEF, 0x6A7E, 0xFAF1, 0x6A7F, 0x8A80, 0x6A80, 0x9268, + 0x6A84, 0x9EFA, 0x6A8D, 0x9EF8, 0x6A8E, 0x8CE7, 0x6A90, 0x9EF7, 0x6A97, 0x9F40, 0x6A9C, 0x9E77, 0x6AA0, 0x9EF9, 0x6AA2, 0x9EFB, + 0x6AA3, 0x9EFC, 0x6AAA, 0x9F4B, 0x6AAC, 0x9F47, 0x6AAE, 0x9E8D, 0x6AB3, 0x9F46, 0x6AB8, 0x9F45, 0x6ABB, 0x9F42, 0x6AC1, 0x9EE8, + 0x6AC2, 0x9F44, 0x6AC3, 0x9F43, 0x6AD1, 0x9F49, 0x6AD3, 0x9845, 0x6ADA, 0x9F4C, 0x6ADB, 0x8BF9, 0x6ADE, 0x9F48, 0x6ADF, 0x9F4A, + 0x6AE2, 0xFAF2, 0x6AE4, 0xFAF3, 0x6AE8, 0x94A5, 0x6AEA, 0x9F4D, 0x6AFA, 0x9F51, 0x6AFB, 0x9F4E, 0x6B04, 0x9793, 0x6B05, 0x9F4F, + 0x6B0A, 0x9EDC, 0x6B12, 0x9F52, 0x6B16, 0x9F53, 0x6B1D, 0x8954, 0x6B1F, 0x9F55, 0x6B20, 0x8C87, 0x6B21, 0x8E9F, 0x6B23, 0x8BD3, + 0x6B27, 0x89A2, 0x6B32, 0x977E, 0x6B37, 0x9F57, 0x6B38, 0x9F56, 0x6B39, 0x9F59, 0x6B3A, 0x8B5C, 0x6B3D, 0x8BD4, 0x6B3E, 0x8ABC, + 0x6B43, 0x9F5C, 0x6B47, 0x9F5B, 0x6B49, 0x9F5D, 0x6B4C, 0x89CC, 0x6B4E, 0x9256, 0x6B50, 0x9F5E, 0x6B53, 0x8ABD, 0x6B54, 0x9F60, + 0x6B59, 0x9F5F, 0x6B5B, 0x9F61, 0x6B5F, 0x9F62, 0x6B61, 0x9F63, 0x6B62, 0x8E7E, 0x6B63, 0x90B3, 0x6B64, 0x8D9F, 0x6B66, 0x9590, + 0x6B69, 0x95E0, 0x6B6A, 0x9863, 0x6B6F, 0x8E95, 0x6B73, 0x8DCE, 0x6B74, 0x97F0, 0x6B78, 0x9F64, 0x6B79, 0x9F65, 0x6B7B, 0x8E80, + 0x6B7F, 0x9F66, 0x6B80, 0x9F67, 0x6B83, 0x9F69, 0x6B84, 0x9F68, 0x6B86, 0x9677, 0x6B89, 0x8F7D, 0x6B8A, 0x8EEA, 0x6B8B, 0x8E63, + 0x6B8D, 0x9F6A, 0x6B95, 0x9F6C, 0x6B96, 0x9042, 0x6B98, 0x9F6B, 0x6B9E, 0x9F6D, 0x6BA4, 0x9F6E, 0x6BAA, 0x9F6F, 0x6BAB, 0x9F70, + 0x6BAF, 0x9F71, 0x6BB1, 0x9F73, 0x6BB2, 0x9F72, 0x6BB3, 0x9F74, 0x6BB4, 0x89A3, 0x6BB5, 0x9269, 0x6BB7, 0x9F75, 0x6BBA, 0x8E45, + 0x6BBB, 0x8A6B, 0x6BBC, 0x9F76, 0x6BBF, 0x9361, 0x6BC0, 0x9ACA, 0x6BC5, 0x8B42, 0x6BC6, 0x9F77, 0x6BCB, 0x9F78, 0x6BCD, 0x95EA, + 0x6BCE, 0x9688, 0x6BD2, 0x93C5, 0x6BD3, 0x9F79, 0x6BD4, 0x94E4, 0x6BD6, 0xFAF4, 0x6BD8, 0x94F9, 0x6BDB, 0x96D1, 0x6BDF, 0x9F7A, + 0x6BEB, 0x9F7C, 0x6BEC, 0x9F7B, 0x6BEF, 0x9F7E, 0x6BF3, 0x9F7D, 0x6C08, 0x9F81, 0x6C0F, 0x8E81, 0x6C11, 0x96AF, 0x6C13, 0x9F82, + 0x6C14, 0x9F83, 0x6C17, 0x8B43, 0x6C1B, 0x9F84, 0x6C23, 0x9F86, 0x6C24, 0x9F85, 0x6C34, 0x9085, 0x6C37, 0x9558, 0x6C38, 0x8969, + 0x6C3E, 0x94C3, 0x6C3F, 0xFAF5, 0x6C40, 0x92F3, 0x6C41, 0x8F60, 0x6C42, 0x8B81, 0x6C4E, 0x94C4, 0x6C50, 0x8EAC, 0x6C55, 0x9F88, + 0x6C57, 0x8ABE, 0x6C5A, 0x8998, 0x6C5C, 0xFAF6, 0x6C5D, 0x93F0, 0x6C5E, 0x9F87, 0x6C5F, 0x8D5D, 0x6C60, 0x9272, 0x6C62, 0x9F89, + 0x6C68, 0x9F91, 0x6C6A, 0x9F8A, 0x6C6F, 0xFAF8, 0x6C70, 0x91BF, 0x6C72, 0x8B82, 0x6C73, 0x9F92, 0x6C7A, 0x8C88, 0x6C7D, 0x8B44, + 0x6C7E, 0x9F90, 0x6C81, 0x9F8E, 0x6C82, 0x9F8B, 0x6C83, 0x9780, 0x6C86, 0xFAF7, 0x6C88, 0x92BE, 0x6C8C, 0x93D7, 0x6C8D, 0x9F8C, + 0x6C90, 0x9F94, 0x6C92, 0x9F93, 0x6C93, 0x8C42, 0x6C96, 0x89AB, 0x6C99, 0x8DB9, 0x6C9A, 0x9F8D, 0x6C9B, 0x9F8F, 0x6CA1, 0x9676, + 0x6CA2, 0x91F2, 0x6CAB, 0x9697, 0x6CAE, 0x9F9C, 0x6CB1, 0x9F9D, 0x6CB3, 0x89CD, 0x6CB8, 0x95A6, 0x6CB9, 0x96FB, 0x6CBA, 0x9F9F, + 0x6CBB, 0x8EA1, 0x6CBC, 0x8FC0, 0x6CBD, 0x9F98, 0x6CBE, 0x9F9E, 0x6CBF, 0x8988, 0x6CC1, 0x8BB5, 0x6CC4, 0x9F95, 0x6CC5, 0x9F9A, + 0x6CC9, 0x90F2, 0x6CCA, 0x9491, 0x6CCC, 0x94E5, 0x6CD3, 0x9F97, 0x6CD5, 0x9640, 0x6CD7, 0x9F99, 0x6CD9, 0x9FA2, 0x6CDA, 0xFAF9, + 0x6CDB, 0x9FA0, 0x6CDD, 0x9F9B, 0x6CE1, 0x9641, 0x6CE2, 0x9467, 0x6CE3, 0x8B83, 0x6CE5, 0x9344, 0x6CE8, 0x928D, 0x6CEA, 0x9FA3, + 0x6CEF, 0x9FA1, 0x6CF0, 0x91D7, 0x6CF1, 0x9F96, 0x6CF3, 0x896A, 0x6D04, 0xFAFA, 0x6D0B, 0x976D, 0x6D0C, 0x9FAE, 0x6D12, 0x9FAD, + 0x6D17, 0x90F4, 0x6D19, 0x9FAA, 0x6D1B, 0x978C, 0x6D1E, 0x93B4, 0x6D1F, 0x9FA4, 0x6D25, 0x92C3, 0x6D29, 0x896B, 0x6D2A, 0x8D5E, + 0x6D2B, 0x9FA7, 0x6D32, 0x8F46, 0x6D33, 0x9FAC, 0x6D35, 0x9FAB, 0x6D36, 0x9FA6, 0x6D38, 0x9FA9, 0x6D3B, 0x8A88, 0x6D3D, 0x9FA8, + 0x6D3E, 0x9468, 0x6D41, 0x97AC, 0x6D44, 0x8FF2, 0x6D45, 0x90F3, 0x6D59, 0x9FB4, 0x6D5A, 0x9FB2, 0x6D5C, 0x956C, 0x6D63, 0x9FAF, + 0x6D64, 0x9FB1, 0x6D66, 0x8959, 0x6D69, 0x8D5F, 0x6D6A, 0x9851, 0x6D6C, 0x8A5C, 0x6D6E, 0x9582, 0x6D6F, 0xFAFC, 0x6D74, 0x9781, + 0x6D77, 0x8A43, 0x6D78, 0x905A, 0x6D79, 0x9FB3, 0x6D85, 0x9FB8, 0x6D87, 0xFAFB, 0x6D88, 0x8FC1, 0x6D8C, 0x974F, 0x6D8E, 0x9FB5, + 0x6D93, 0x9FB0, 0x6D95, 0x9FB6, 0x6D96, 0xFB40, 0x6D99, 0x97DC, 0x6D9B, 0x9393, 0x6D9C, 0x93C0, 0x6DAC, 0xFB41, 0x6DAF, 0x8A55, + 0x6DB2, 0x8974, 0x6DB5, 0x9FBC, 0x6DB8, 0x9FBF, 0x6DBC, 0x97C1, 0x6DC0, 0x9784, 0x6DC5, 0x9FC6, 0x6DC6, 0x9FC0, 0x6DC7, 0x9FBD, + 0x6DCB, 0x97D2, 0x6DCC, 0x9FC3, 0x6DCF, 0xFB42, 0x6DD1, 0x8F69, 0x6DD2, 0x9FC5, 0x6DD5, 0x9FCA, 0x6DD8, 0x9391, 0x6DD9, 0x9FC8, + 0x6DDE, 0x9FC2, 0x6DE1, 0x9257, 0x6DE4, 0x9FC9, 0x6DE6, 0x9FBE, 0x6DE8, 0x9FC4, 0x6DEA, 0x9FCB, 0x6DEB, 0x88FA, 0x6DEC, 0x9FC1, + 0x6DEE, 0x9FCC, 0x6DF1, 0x905B, 0x6DF2, 0xFB44, 0x6DF3, 0x8F7E, 0x6DF5, 0x95A3, 0x6DF7, 0x8DAC, 0x6DF8, 0xFB43, 0x6DF9, 0x9FB9, + 0x6DFA, 0x9FC7, 0x6DFB, 0x9359, 0x6DFC, 0xFB45, 0x6E05, 0x90B4, 0x6E07, 0x8A89, 0x6E08, 0x8DCF, 0x6E09, 0x8FC2, 0x6E0A, 0x9FBB, + 0x6E0B, 0x8F61, 0x6E13, 0x8C6B, 0x6E15, 0x9FBA, 0x6E19, 0x9FD0, 0x6E1A, 0x8F8D, 0x6E1B, 0x8CB8, 0x6E1D, 0x9FDF, 0x6E1F, 0x9FD9, + 0x6E20, 0x8B94, 0x6E21, 0x936E, 0x6E23, 0x9FD4, 0x6E24, 0x9FDD, 0x6E25, 0x88AD, 0x6E26, 0x8951, 0x6E27, 0xFB48, 0x6E29, 0x89B7, + 0x6E2B, 0x9FD6, 0x6E2C, 0x91AA, 0x6E2D, 0x9FCD, 0x6E2E, 0x9FCF, 0x6E2F, 0x8D60, 0x6E38, 0x9FE0, 0x6E39, 0xFB46, 0x6E3A, 0x9FDB, + 0x6E3C, 0xFB49, 0x6E3E, 0x9FD3, 0x6E43, 0x9FDA, 0x6E4A, 0x96A9, 0x6E4D, 0x9FD8, 0x6E4E, 0x9FDC, 0x6E56, 0x8CCE, 0x6E58, 0x8FC3, + 0x6E5B, 0x9258, 0x6E5C, 0xFB47, 0x6E5F, 0x9FD2, 0x6E67, 0x974E, 0x6E6B, 0x9FD5, 0x6E6E, 0x9FCE, 0x6E6F, 0x9392, 0x6E72, 0x9FD1, + 0x6E76, 0x9FD7, 0x6E7E, 0x9870, 0x6E7F, 0x8EBC, 0x6E80, 0x969E, 0x6E82, 0x9FE1, 0x6E8C, 0x94AC, 0x6E8F, 0x9FED, 0x6E90, 0x8CB9, + 0x6E96, 0x8F80, 0x6E98, 0x9FE3, 0x6E9C, 0x97AD, 0x6E9D, 0x8D61, 0x6E9F, 0x9FF0, 0x6EA2, 0x88EC, 0x6EA5, 0x9FEE, 0x6EAA, 0x9FE2, + 0x6EAF, 0x9FE8, 0x6EB2, 0x9FEA, 0x6EB6, 0x976E, 0x6EB7, 0x9FE5, 0x6EBA, 0x934D, 0x6EBD, 0x9FE7, 0x6EBF, 0xFB4A, 0x6EC2, 0x9FEF, + 0x6EC4, 0x9FE9, 0x6EC5, 0x96C5, 0x6EC9, 0x9FE4, 0x6ECB, 0x8EA0, 0x6ECC, 0x9FFC, 0x6ED1, 0x8A8A, 0x6ED3, 0x9FE6, 0x6ED4, 0x9FEB, + 0x6ED5, 0x9FEC, 0x6EDD, 0x91EA, 0x6EDE, 0x91D8, 0x6EEC, 0x9FF4, 0x6EEF, 0x9FFA, 0x6EF2, 0x9FF8, 0x6EF4, 0x9348, 0x6EF7, 0xE042, + 0x6EF8, 0x9FF5, 0x6EFE, 0x9FF6, 0x6EFF, 0x9FDE, 0x6F01, 0x8B99, 0x6F02, 0x9559, 0x6F06, 0x8EBD, 0x6F09, 0x8D97, 0x6F0F, 0x9852, + 0x6F11, 0x9FF2, 0x6F13, 0xE041, 0x6F14, 0x8989, 0x6F15, 0x9186, 0x6F20, 0x9499, 0x6F22, 0x8ABF, 0x6F23, 0x97F8, 0x6F2B, 0x969F, + 0x6F2C, 0x92D0, 0x6F31, 0x9FF9, 0x6F32, 0x9FFB, 0x6F38, 0x9151, 0x6F3E, 0xE040, 0x6F3F, 0x9FF7, 0x6F41, 0x9FF1, 0x6F45, 0x8AC1, + 0x6F54, 0x8C89, 0x6F58, 0xE04E, 0x6F5B, 0xE049, 0x6F5C, 0x90F6, 0x6F5F, 0x8A83, 0x6F64, 0x8F81, 0x6F66, 0xE052, 0x6F6D, 0xE04B, + 0x6F6E, 0x92AA, 0x6F6F, 0xE048, 0x6F70, 0x92D7, 0x6F74, 0xE06B, 0x6F78, 0xE045, 0x6F7A, 0xE044, 0x6F7C, 0xE04D, 0x6F80, 0xE047, + 0x6F81, 0xE046, 0x6F82, 0xE04C, 0x6F84, 0x909F, 0x6F86, 0xE043, 0x6F88, 0xFB4B, 0x6F8E, 0xE04F, 0x6F91, 0xE050, 0x6F97, 0x8AC0, + 0x6FA1, 0xE055, 0x6FA3, 0xE054, 0x6FA4, 0xE056, 0x6FAA, 0xE059, 0x6FB1, 0x9362, 0x6FB3, 0xE053, 0x6FB5, 0xFB4C, 0x6FB9, 0xE057, + 0x6FC0, 0x8C83, 0x6FC1, 0x91F7, 0x6FC2, 0xE051, 0x6FC3, 0x945A, 0x6FC6, 0xE058, 0x6FD4, 0xE05D, 0x6FD5, 0xE05B, 0x6FD8, 0xE05E, + 0x6FDB, 0xE061, 0x6FDF, 0xE05A, 0x6FE0, 0x8D8A, 0x6FE1, 0x9447, 0x6FE4, 0x9FB7, 0x6FEB, 0x9794, 0x6FEC, 0xE05C, 0x6FEE, 0xE060, + 0x6FEF, 0x91F3, 0x6FF1, 0xE05F, 0x6FF3, 0xE04A, 0x6FF5, 0xFB4D, 0x6FF6, 0xE889, 0x6FFA, 0xE064, 0x6FFE, 0xE068, 0x7001, 0xE066, + 0x7005, 0xFB4E, 0x7007, 0xFB4F, 0x7009, 0xE062, 0x700B, 0xE063, 0x700F, 0xE067, 0x7011, 0xE065, 0x7015, 0x956D, 0x7018, 0xE06D, + 0x701A, 0xE06A, 0x701B, 0xE069, 0x701D, 0xE06C, 0x701E, 0x93D2, 0x701F, 0xE06E, 0x7026, 0x9295, 0x7027, 0x91EB, 0x7028, 0xFB50, + 0x702C, 0x90A3, 0x7030, 0xE06F, 0x7032, 0xE071, 0x703E, 0xE070, 0x704C, 0x9FF3, 0x7051, 0xE072, 0x7058, 0x93E5, 0x7063, 0xE073, + 0x706B, 0x89CE, 0x706F, 0x9394, 0x7070, 0x8A44, 0x7078, 0x8B84, 0x707C, 0x8EDC, 0x707D, 0x8DD0, 0x7085, 0xFB51, 0x7089, 0x9846, + 0x708A, 0x9086, 0x708E, 0x898A, 0x7092, 0xE075, 0x7099, 0xE074, 0x70AB, 0xFB52, 0x70AC, 0xE078, 0x70AD, 0x9259, 0x70AE, 0xE07B, + 0x70AF, 0xE076, 0x70B3, 0xE07A, 0x70B8, 0xE079, 0x70B9, 0x935F, 0x70BA, 0x88D7, 0x70BB, 0xFA62, 0x70C8, 0x97F3, 0x70CB, 0xE07D, + 0x70CF, 0x8947, 0x70D9, 0xE080, 0x70DD, 0xE07E, 0x70DF, 0xE07C, 0x70F1, 0xE077, 0x70F9, 0x9642, 0x70FD, 0xE082, 0x7104, 0xFB54, + 0x7109, 0xE081, 0x710F, 0xFB53, 0x7114, 0x898B, 0x7119, 0xE084, 0x711A, 0x95B0, 0x711C, 0xE083, 0x7121, 0x96B3, 0x7126, 0x8FC5, + 0x7136, 0x9152, 0x713C, 0x8FC4, 0x7146, 0xFB56, 0x7147, 0xFB57, 0x7149, 0x97F9, 0x714C, 0xE08A, 0x714E, 0x90F7, 0x7155, 0xE086, + 0x7156, 0xE08B, 0x7159, 0x898C, 0x715C, 0xFB55, 0x7162, 0xE089, 0x7164, 0x9481, 0x7165, 0xE085, 0x7166, 0xE088, 0x7167, 0x8FC6, + 0x7169, 0x94CF, 0x716C, 0xE08C, 0x716E, 0x8ECF, 0x717D, 0x90F8, 0x7184, 0xE08F, 0x7188, 0xE087, 0x718A, 0x8C46, 0x718F, 0xE08D, + 0x7194, 0x976F, 0x7195, 0xE090, 0x7199, 0xEAA4, 0x719F, 0x8F6E, 0x71A8, 0xE091, 0x71AC, 0xE092, 0x71B1, 0x944D, 0x71B9, 0xE094, + 0x71BE, 0xE095, 0x71C1, 0xFB59, 0x71C3, 0x9452, 0x71C8, 0x9395, 0x71C9, 0xE097, 0x71CE, 0xE099, 0x71D0, 0x97D3, 0x71D2, 0xE096, + 0x71D4, 0xE098, 0x71D5, 0x898D, 0x71D7, 0xE093, 0x71DF, 0x9A7A, 0x71E0, 0xE09A, 0x71E5, 0x9187, 0x71E6, 0x8E57, 0x71E7, 0xE09C, + 0x71EC, 0xE09B, 0x71ED, 0x9043, 0x71EE, 0x99D7, 0x71F5, 0xE09D, 0x71F9, 0xE09F, 0x71FB, 0xE08E, 0x71FC, 0xE09E, 0x71FE, 0xFB5A, + 0x71FF, 0xE0A0, 0x7206, 0x949A, 0x720D, 0xE0A1, 0x7210, 0xE0A2, 0x721B, 0xE0A3, 0x7228, 0xE0A4, 0x722A, 0x92DC, 0x722C, 0xE0A6, + 0x722D, 0xE0A5, 0x7230, 0xE0A7, 0x7232, 0xE0A8, 0x7235, 0x8EDD, 0x7236, 0x9583, 0x723A, 0x96EA, 0x723B, 0xE0A9, 0x723C, 0xE0AA, + 0x723D, 0x9175, 0x723E, 0x8EA2, 0x723F, 0xE0AB, 0x7240, 0xE0AC, 0x7246, 0xE0AD, 0x7247, 0x95D0, 0x7248, 0x94C5, 0x724B, 0xE0AE, + 0x724C, 0x9476, 0x7252, 0x92AB, 0x7258, 0xE0AF, 0x7259, 0x89E5, 0x725B, 0x8B8D, 0x725D, 0x96C4, 0x725F, 0x96B4, 0x7261, 0x89B2, + 0x7262, 0x9853, 0x7267, 0x9671, 0x7269, 0x95A8, 0x7272, 0x90B5, 0x7274, 0xE0B0, 0x7279, 0x93C1, 0x727D, 0x8CA1, 0x727E, 0xE0B1, + 0x7280, 0x8DD2, 0x7281, 0xE0B3, 0x7282, 0xE0B2, 0x7287, 0xE0B4, 0x7292, 0xE0B5, 0x7296, 0xE0B6, 0x72A0, 0x8B5D, 0x72A2, 0xE0B7, + 0x72A7, 0xE0B8, 0x72AC, 0x8CA2, 0x72AF, 0x94C6, 0x72B1, 0xFB5B, 0x72B2, 0xE0BA, 0x72B6, 0x8FF3, 0x72B9, 0xE0B9, 0x72BE, 0xFB5C, + 0x72C2, 0x8BB6, 0x72C3, 0xE0BB, 0x72C4, 0xE0BD, 0x72C6, 0xE0BC, 0x72CE, 0xE0BE, 0x72D0, 0x8CCF, 0x72D2, 0xE0BF, 0x72D7, 0x8BE7, + 0x72D9, 0x915F, 0x72DB, 0x8D9D, 0x72E0, 0xE0C1, 0x72E1, 0xE0C2, 0x72E2, 0xE0C0, 0x72E9, 0x8EEB, 0x72EC, 0x93C6, 0x72ED, 0x8BB7, + 0x72F7, 0xE0C4, 0x72F8, 0x924B, 0x72F9, 0xE0C3, 0x72FC, 0x9854, 0x72FD, 0x9482, 0x730A, 0xE0C7, 0x7316, 0xE0C9, 0x7317, 0xE0C6, + 0x731B, 0x96D2, 0x731C, 0xE0C8, 0x731D, 0xE0CA, 0x731F, 0x97C2, 0x7324, 0xFB5D, 0x7325, 0xE0CE, 0x7329, 0xE0CD, 0x732A, 0x9296, + 0x732B, 0x944C, 0x732E, 0x8CA3, 0x732F, 0xE0CC, 0x7334, 0xE0CB, 0x7336, 0x9750, 0x7337, 0x9751, 0x733E, 0xE0CF, 0x733F, 0x898E, + 0x7344, 0x8D96, 0x7345, 0x8E82, 0x734E, 0xE0D0, 0x734F, 0xE0D1, 0x7357, 0xE0D3, 0x7363, 0x8F62, 0x7368, 0xE0D5, 0x736A, 0xE0D4, + 0x7370, 0xE0D6, 0x7372, 0x8A6C, 0x7375, 0xE0D8, 0x7377, 0xFB5F, 0x7378, 0xE0D7, 0x737A, 0xE0DA, 0x737B, 0xE0D9, 0x7384, 0x8CBA, + 0x7387, 0x97A6, 0x7389, 0x8BCA, 0x738B, 0x89A4, 0x7396, 0x8BE8, 0x73A9, 0x8ADF, 0x73B2, 0x97E6, 0x73B3, 0xE0DC, 0x73BB, 0xE0DE, + 0x73BD, 0xFB60, 0x73C0, 0xE0DF, 0x73C2, 0x89CF, 0x73C8, 0xE0DB, 0x73C9, 0xFB61, 0x73CA, 0x8E58, 0x73CD, 0x92BF, 0x73CE, 0xE0DD, + 0x73D2, 0xFB64, 0x73D6, 0xFB62, 0x73DE, 0xE0E2, 0x73E0, 0x8EEC, 0x73E3, 0xFB63, 0x73E5, 0xE0E0, 0x73EA, 0x8C5D, 0x73ED, 0x94C7, + 0x73EE, 0xE0E1, 0x73F1, 0xE0FC, 0x73F5, 0xFB66, 0x73F8, 0xE0E7, 0x73FE, 0x8CBB, 0x7403, 0x8B85, 0x7405, 0xE0E4, 0x7406, 0x979D, + 0x7407, 0xFB65, 0x7409, 0x97AE, 0x7422, 0x91F4, 0x7425, 0xE0E6, 0x7426, 0xFB67, 0x7429, 0xFB69, 0x742A, 0xFB68, 0x742E, 0xFB6A, + 0x7432, 0xE0E8, 0x7433, 0x97D4, 0x7434, 0x8BD5, 0x7435, 0x94FA, 0x7436, 0x9469, 0x743A, 0xE0E9, 0x743F, 0xE0EB, 0x7441, 0xE0EE, + 0x7455, 0xE0EA, 0x7459, 0xE0ED, 0x745A, 0x8CE8, 0x745B, 0x896C, 0x745C, 0xE0EF, 0x745E, 0x9090, 0x745F, 0xE0EC, 0x7460, 0x97DA, + 0x7462, 0xFB6B, 0x7463, 0xE0F2, 0x7464, 0xEAA2, 0x7469, 0xE0F0, 0x746A, 0xE0F3, 0x746F, 0xE0E5, 0x7470, 0xE0F1, 0x7473, 0x8DBA, + 0x7476, 0xE0F4, 0x747E, 0xE0F5, 0x7483, 0x979E, 0x7489, 0xFB6C, 0x748B, 0xE0F6, 0x749E, 0xE0F7, 0x749F, 0xFB6D, 0x74A2, 0xE0E3, + 0x74A7, 0xE0F8, 0x74B0, 0x8AC2, 0x74BD, 0x8EA3, 0x74CA, 0xE0F9, 0x74CF, 0xE0FA, 0x74D4, 0xE0FB, 0x74DC, 0x895A, 0x74E0, 0xE140, + 0x74E2, 0x955A, 0x74E3, 0xE141, 0x74E6, 0x8AA2, 0x74E7, 0xE142, 0x74E9, 0xE143, 0x74EE, 0xE144, 0x74F0, 0xE146, 0x74F1, 0xE147, + 0x74F2, 0xE145, 0x74F6, 0x9572, 0x74F7, 0xE149, 0x74F8, 0xE148, 0x7501, 0xFB6E, 0x7503, 0xE14B, 0x7504, 0xE14A, 0x7505, 0xE14C, + 0x750C, 0xE14D, 0x750D, 0xE14F, 0x750E, 0xE14E, 0x7511, 0x8D99, 0x7513, 0xE151, 0x7515, 0xE150, 0x7518, 0x8AC3, 0x751A, 0x9072, + 0x751C, 0x935B, 0x751E, 0xE152, 0x751F, 0x90B6, 0x7523, 0x8E59, 0x7525, 0x8999, 0x7526, 0xE153, 0x7528, 0x9770, 0x752B, 0x95E1, + 0x752C, 0xE154, 0x752F, 0xFAA8, 0x7530, 0x9363, 0x7531, 0x9752, 0x7532, 0x8D62, 0x7533, 0x905C, 0x7537, 0x926A, 0x7538, 0x99B2, + 0x753A, 0x92AC, 0x753B, 0x89E6, 0x753C, 0xE155, 0x7544, 0xE156, 0x7546, 0xE15B, 0x7549, 0xE159, 0x754A, 0xE158, 0x754B, 0x9DC0, + 0x754C, 0x8A45, 0x754D, 0xE157, 0x754F, 0x88D8, 0x7551, 0x94A8, 0x7554, 0x94C8, 0x7559, 0x97AF, 0x755A, 0xE15C, 0x755B, 0xE15A, + 0x755C, 0x927B, 0x755D, 0x90A4, 0x7560, 0x94A9, 0x7562, 0x954C, 0x7564, 0xE15E, 0x7565, 0x97AA, 0x7566, 0x8C6C, 0x7567, 0xE15F, + 0x7569, 0xE15D, 0x756A, 0x94D4, 0x756B, 0xE160, 0x756D, 0xE161, 0x756F, 0xFB6F, 0x7570, 0x88D9, 0x7573, 0x8FF4, 0x7574, 0xE166, + 0x7576, 0xE163, 0x7577, 0x93EB, 0x7578, 0xE162, 0x757F, 0x8B45, 0x7582, 0xE169, 0x7586, 0xE164, 0x7587, 0xE165, 0x7589, 0xE168, + 0x758A, 0xE167, 0x758B, 0x9544, 0x758E, 0x9161, 0x758F, 0x9160, 0x7591, 0x8B5E, 0x7594, 0xE16A, 0x759A, 0xE16B, 0x759D, 0xE16C, + 0x75A3, 0xE16E, 0x75A5, 0xE16D, 0x75AB, 0x8975, 0x75B1, 0xE176, 0x75B2, 0x94E6, 0x75B3, 0xE170, 0x75B5, 0xE172, 0x75B8, 0xE174, + 0x75B9, 0x905D, 0x75BC, 0xE175, 0x75BD, 0xE173, 0x75BE, 0x8EBE, 0x75C2, 0xE16F, 0x75C3, 0xE171, 0x75C5, 0x9561, 0x75C7, 0x8FC7, + 0x75CA, 0xE178, 0x75CD, 0xE177, 0x75D2, 0xE179, 0x75D4, 0x8EA4, 0x75D5, 0x8DAD, 0x75D8, 0x9397, 0x75D9, 0xE17A, 0x75DB, 0x92C9, + 0x75DE, 0xE17C, 0x75E2, 0x979F, 0x75E3, 0xE17B, 0x75E9, 0x9189, 0x75F0, 0xE182, 0x75F2, 0xE184, 0x75F3, 0xE185, 0x75F4, 0x9273, + 0x75FA, 0xE183, 0x75FC, 0xE180, 0x75FE, 0xE17D, 0x75FF, 0xE17E, 0x7601, 0xE181, 0x7609, 0xE188, 0x760B, 0xE186, 0x760D, 0xE187, + 0x761F, 0xE189, 0x7620, 0xE18B, 0x7621, 0xE18C, 0x7622, 0xE18D, 0x7624, 0xE18E, 0x7627, 0xE18A, 0x7630, 0xE190, 0x7634, 0xE18F, + 0x763B, 0xE191, 0x7642, 0x97C3, 0x7646, 0xE194, 0x7647, 0xE192, 0x7648, 0xE193, 0x764C, 0x8AE0, 0x7652, 0x96FC, 0x7656, 0x95C8, + 0x7658, 0xE196, 0x765C, 0xE195, 0x7661, 0xE197, 0x7662, 0xE198, 0x7667, 0xE19C, 0x7668, 0xE199, 0x7669, 0xE19A, 0x766A, 0xE19B, + 0x766C, 0xE19D, 0x7670, 0xE19E, 0x7672, 0xE19F, 0x7676, 0xE1A0, 0x7678, 0xE1A1, 0x767A, 0x94AD, 0x767B, 0x936F, 0x767C, 0xE1A2, + 0x767D, 0x9492, 0x767E, 0x9553, 0x7680, 0xE1A3, 0x7682, 0xFB70, 0x7683, 0xE1A4, 0x7684, 0x9349, 0x7686, 0x8A46, 0x7687, 0x8D63, + 0x7688, 0xE1A5, 0x768B, 0xE1A6, 0x768E, 0xE1A7, 0x7690, 0x8E48, 0x7693, 0xE1A9, 0x7696, 0xE1A8, 0x7699, 0xE1AA, 0x769A, 0xE1AB, + 0x769B, 0xFB73, 0x769C, 0xFB71, 0x769E, 0xFB72, 0x76A6, 0xFB74, 0x76AE, 0x94E7, 0x76B0, 0xE1AC, 0x76B4, 0xE1AD, 0x76B7, 0xEA89, + 0x76B8, 0xE1AE, 0x76B9, 0xE1AF, 0x76BA, 0xE1B0, 0x76BF, 0x8E4D, 0x76C2, 0xE1B1, 0x76C3, 0x9475, 0x76C6, 0x967E, 0x76C8, 0x896D, + 0x76CA, 0x8976, 0x76CD, 0xE1B2, 0x76D2, 0xE1B4, 0x76D6, 0xE1B3, 0x76D7, 0x9390, 0x76DB, 0x90B7, 0x76DC, 0x9F58, 0x76DE, 0xE1B5, + 0x76DF, 0x96BF, 0x76E1, 0xE1B6, 0x76E3, 0x8AC4, 0x76E4, 0x94D5, 0x76E5, 0xE1B7, 0x76E7, 0xE1B8, 0x76EA, 0xE1B9, 0x76EE, 0x96DA, + 0x76F2, 0x96D3, 0x76F4, 0x92BC, 0x76F8, 0x918A, 0x76FB, 0xE1BB, 0x76FE, 0x8F82, 0x7701, 0x8FC8, 0x7704, 0xE1BE, 0x7707, 0xE1BD, + 0x7708, 0xE1BC, 0x7709, 0x94FB, 0x770B, 0x8AC5, 0x770C, 0x8CA7, 0x771B, 0xE1C4, 0x771E, 0xE1C1, 0x771F, 0x905E, 0x7720, 0x96B0, + 0x7724, 0xE1C0, 0x7725, 0xE1C2, 0x7726, 0xE1C3, 0x7729, 0xE1BF, 0x7737, 0xE1C5, 0x7738, 0xE1C6, 0x773A, 0x92AD, 0x773C, 0x8AE1, + 0x7740, 0x9285, 0x7746, 0xFB76, 0x7747, 0xE1C7, 0x775A, 0xE1C8, 0x775B, 0xE1CB, 0x7761, 0x9087, 0x7763, 0x93C2, 0x7765, 0xE1CC, + 0x7766, 0x9672, 0x7768, 0xE1C9, 0x776B, 0xE1CA, 0x7779, 0xE1CF, 0x777E, 0xE1CE, 0x777F, 0xE1CD, 0x778B, 0xE1D1, 0x778E, 0xE1D0, + 0x7791, 0xE1D2, 0x779E, 0xE1D4, 0x77A0, 0xE1D3, 0x77A5, 0x95CB, 0x77AC, 0x8F75, 0x77AD, 0x97C4, 0x77B0, 0xE1D5, 0x77B3, 0x93B5, + 0x77B6, 0xE1D6, 0x77B9, 0xE1D7, 0x77BB, 0xE1DB, 0x77BC, 0xE1D9, 0x77BD, 0xE1DA, 0x77BF, 0xE1D8, 0x77C7, 0xE1DC, 0x77CD, 0xE1DD, + 0x77D7, 0xE1DE, 0x77DA, 0xE1DF, 0x77DB, 0x96B5, 0x77DC, 0xE1E0, 0x77E2, 0x96EE, 0x77E3, 0xE1E1, 0x77E5, 0x926D, 0x77E7, 0x948A, + 0x77E9, 0x8BE9, 0x77ED, 0x925A, 0x77EE, 0xE1E2, 0x77EF, 0x8BB8, 0x77F3, 0x90CE, 0x77FC, 0xE1E3, 0x7802, 0x8DBB, 0x780C, 0xE1E4, + 0x7812, 0xE1E5, 0x7814, 0x8CA4, 0x7815, 0x8DD3, 0x7820, 0xE1E7, 0x7821, 0xFB78, 0x7825, 0x9375, 0x7826, 0x8DD4, 0x7827, 0x8B6D, + 0x7832, 0x9643, 0x7834, 0x946A, 0x783A, 0x9376, 0x783F, 0x8D7B, 0x7845, 0xE1E9, 0x784E, 0xFB79, 0x785D, 0x8FC9, 0x7864, 0xFB7A, + 0x786B, 0x97B0, 0x786C, 0x8D64, 0x786F, 0x8CA5, 0x7872, 0x94A1, 0x7874, 0xE1EB, 0x787A, 0xFB7B, 0x787C, 0xE1ED, 0x7881, 0x8CE9, + 0x7886, 0xE1EC, 0x7887, 0x92F4, 0x788C, 0xE1EF, 0x788D, 0x8A56, 0x788E, 0xE1EA, 0x7891, 0x94E8, 0x7893, 0x894F, 0x7895, 0x8DEA, + 0x7897, 0x9871, 0x789A, 0xE1EE, 0x78A3, 0xE1F0, 0x78A7, 0x95C9, 0x78A9, 0x90D7, 0x78AA, 0xE1F2, 0x78AF, 0xE1F3, 0x78B5, 0xE1F1, + 0x78BA, 0x8A6D, 0x78BC, 0xE1F9, 0x78BE, 0xE1F8, 0x78C1, 0x8EA5, 0x78C5, 0xE1FA, 0x78C6, 0xE1F5, 0x78CA, 0xE1FB, 0x78CB, 0xE1F6, + 0x78D0, 0x94D6, 0x78D1, 0xE1F4, 0x78D4, 0xE1F7, 0x78DA, 0xE241, 0x78E7, 0xE240, 0x78E8, 0x9681, 0x78EC, 0xE1FC, 0x78EF, 0x88E9, + 0x78F4, 0xE243, 0x78FD, 0xE242, 0x7901, 0x8FCA, 0x7907, 0xE244, 0x790E, 0x9162, 0x7911, 0xE246, 0x7912, 0xE245, 0x7919, 0xE247, + 0x7926, 0xE1E6, 0x792A, 0xE1E8, 0x792B, 0xE249, 0x792C, 0xE248, 0x7930, 0xFB7C, 0x793A, 0x8EA6, 0x793C, 0x97E7, 0x793E, 0x8ED0, + 0x7940, 0xE24A, 0x7941, 0x8C56, 0x7947, 0x8B5F, 0x7948, 0x8B46, 0x7949, 0x8E83, 0x7950, 0x9753, 0x7953, 0xE250, 0x7955, 0xE24F, + 0x7956, 0x9163, 0x7957, 0xE24C, 0x795A, 0xE24E, 0x795D, 0x8F6A, 0x795E, 0x905F, 0x795F, 0xE24D, 0x7960, 0xE24B, 0x7962, 0x9449, + 0x7965, 0x8FCB, 0x7968, 0x955B, 0x796D, 0x8DD5, 0x7977, 0x9398, 0x797A, 0xE251, 0x797F, 0xE252, 0x7980, 0xE268, 0x7981, 0x8BD6, + 0x7984, 0x985C, 0x7985, 0x9154, 0x798A, 0xE253, 0x798D, 0x89D0, 0x798E, 0x92F5, 0x798F, 0x959F, 0x7994, 0xFB81, 0x799B, 0xFB83, + 0x799D, 0xE254, 0x79A6, 0x8B9A, 0x79A7, 0xE255, 0x79AA, 0xE257, 0x79AE, 0xE258, 0x79B0, 0x9448, 0x79B3, 0xE259, 0x79B9, 0xE25A, + 0x79BA, 0xE25B, 0x79BD, 0x8BD7, 0x79BE, 0x89D1, 0x79BF, 0x93C3, 0x79C0, 0x8F47, 0x79C1, 0x8E84, 0x79C9, 0xE25C, 0x79CB, 0x8F48, + 0x79D1, 0x89C8, 0x79D2, 0x9562, 0x79D5, 0xE25D, 0x79D8, 0x94E9, 0x79DF, 0x9164, 0x79E1, 0xE260, 0x79E3, 0xE261, 0x79E4, 0x9489, + 0x79E6, 0x9060, 0x79E7, 0xE25E, 0x79E9, 0x9281, 0x79EC, 0xE25F, 0x79F0, 0x8FCC, 0x79FB, 0x88DA, 0x7A00, 0x8B48, 0x7A08, 0xE262, + 0x7A0B, 0x92F6, 0x7A0D, 0xE263, 0x7A0E, 0x90C5, 0x7A14, 0x96AB, 0x7A17, 0x9542, 0x7A18, 0xE264, 0x7A19, 0xE265, 0x7A1A, 0x9274, + 0x7A1C, 0x97C5, 0x7A1F, 0xE267, 0x7A20, 0xE266, 0x7A2E, 0x8EED, 0x7A31, 0xE269, 0x7A32, 0x88EE, 0x7A37, 0xE26C, 0x7A3B, 0xE26A, + 0x7A3C, 0x89D2, 0x7A3D, 0x8C6D, 0x7A3E, 0xE26B, 0x7A3F, 0x8D65, 0x7A40, 0x8D92, 0x7A42, 0x95E4, 0x7A43, 0xE26D, 0x7A46, 0x9673, + 0x7A49, 0xE26F, 0x7A4D, 0x90CF, 0x7A4E, 0x896E, 0x7A4F, 0x89B8, 0x7A50, 0x88AA, 0x7A57, 0xE26E, 0x7A61, 0xE270, 0x7A62, 0xE271, + 0x7A63, 0x8FF5, 0x7A69, 0xE272, 0x7A6B, 0x8A6E, 0x7A70, 0xE274, 0x7A74, 0x8C8A, 0x7A76, 0x8B86, 0x7A79, 0xE275, 0x7A7A, 0x8BF3, + 0x7A7D, 0xE276, 0x7A7F, 0x90FA, 0x7A81, 0x93CB, 0x7A83, 0x90DE, 0x7A84, 0x8DF3, 0x7A88, 0xE277, 0x7A92, 0x9282, 0x7A93, 0x918B, + 0x7A95, 0xE279, 0x7A96, 0xE27B, 0x7A97, 0xE278, 0x7A98, 0xE27A, 0x7A9F, 0x8C41, 0x7AA9, 0xE27C, 0x7AAA, 0x8C45, 0x7AAE, 0x8B87, + 0x7AAF, 0x9771, 0x7AB0, 0xE27E, 0x7AB6, 0xE280, 0x7ABA, 0x894D, 0x7ABF, 0xE283, 0x7AC3, 0x8A96, 0x7AC4, 0xE282, 0x7AC5, 0xE281, + 0x7AC7, 0xE285, 0x7AC8, 0xE27D, 0x7ACA, 0xE286, 0x7ACB, 0x97A7, 0x7ACD, 0xE287, 0x7ACF, 0xE288, 0x7AD1, 0xFB84, 0x7AD2, 0x9AF2, + 0x7AD3, 0xE28A, 0x7AD5, 0xE289, 0x7AD9, 0xE28B, 0x7ADA, 0xE28C, 0x7ADC, 0x97B3, 0x7ADD, 0xE28D, 0x7ADF, 0xE8ED, 0x7AE0, 0x8FCD, + 0x7AE1, 0xE28E, 0x7AE2, 0xE28F, 0x7AE3, 0x8F76, 0x7AE5, 0x93B6, 0x7AE6, 0xE290, 0x7AE7, 0xFB85, 0x7AEA, 0x9247, 0x7AEB, 0xFB87, + 0x7AED, 0xE291, 0x7AEF, 0x925B, 0x7AF0, 0xE292, 0x7AF6, 0x8BA3, 0x7AF8, 0x995E, 0x7AF9, 0x927C, 0x7AFA, 0x8EB1, 0x7AFF, 0x8AC6, + 0x7B02, 0xE293, 0x7B04, 0xE2A0, 0x7B06, 0xE296, 0x7B08, 0x8B88, 0x7B0A, 0xE295, 0x7B0B, 0xE2A2, 0x7B0F, 0xE294, 0x7B11, 0x8FCE, + 0x7B18, 0xE298, 0x7B19, 0xE299, 0x7B1B, 0x934A, 0x7B1E, 0xE29A, 0x7B20, 0x8A7D, 0x7B25, 0x9079, 0x7B26, 0x9584, 0x7B28, 0xE29C, + 0x7B2C, 0x91E6, 0x7B33, 0xE297, 0x7B35, 0xE29B, 0x7B36, 0xE29D, 0x7B39, 0x8DF9, 0x7B45, 0xE2A4, 0x7B46, 0x954D, 0x7B48, 0x94A4, + 0x7B49, 0x9399, 0x7B4B, 0x8BD8, 0x7B4C, 0xE2A3, 0x7B4D, 0xE2A1, 0x7B4F, 0x94B3, 0x7B50, 0xE29E, 0x7B51, 0x927D, 0x7B52, 0x939B, + 0x7B54, 0x939A, 0x7B56, 0x8DF4, 0x7B5D, 0xE2B6, 0x7B65, 0xE2A6, 0x7B67, 0xE2A8, 0x7B6C, 0xE2AB, 0x7B6E, 0xE2AC, 0x7B70, 0xE2A9, + 0x7B71, 0xE2AA, 0x7B74, 0xE2A7, 0x7B75, 0xE2A5, 0x7B7A, 0xE29F, 0x7B86, 0x95CD, 0x7B87, 0x89D3, 0x7B8B, 0xE2B3, 0x7B8D, 0xE2B0, + 0x7B8F, 0xE2B5, 0x7B92, 0xE2B4, 0x7B94, 0x9493, 0x7B95, 0x96A5, 0x7B97, 0x8E5A, 0x7B98, 0xE2AE, 0x7B99, 0xE2B7, 0x7B9A, 0xE2B2, + 0x7B9C, 0xE2B1, 0x7B9D, 0xE2AD, 0x7B9E, 0xFB88, 0x7B9F, 0xE2AF, 0x7BA1, 0x8AC7, 0x7BAA, 0x925C, 0x7BAD, 0x90FB, 0x7BB1, 0x94A0, + 0x7BB4, 0xE2BC, 0x7BB8, 0x94A2, 0x7BC0, 0x90DF, 0x7BC1, 0xE2B9, 0x7BC4, 0x94CD, 0x7BC6, 0xE2BD, 0x7BC7, 0x95D1, 0x7BC9, 0x927A, + 0x7BCB, 0xE2B8, 0x7BCC, 0xE2BA, 0x7BCF, 0xE2BB, 0x7BDD, 0xE2BE, 0x7BE0, 0x8EC2, 0x7BE4, 0x93C4, 0x7BE5, 0xE2C3, 0x7BE6, 0xE2C2, + 0x7BE9, 0xE2BF, 0x7BED, 0x9855, 0x7BF3, 0xE2C8, 0x7BF6, 0xE2CC, 0x7BF7, 0xE2C9, 0x7C00, 0xE2C5, 0x7C07, 0xE2C6, 0x7C0D, 0xE2CB, + 0x7C11, 0xE2C0, 0x7C12, 0x99D3, 0x7C13, 0xE2C7, 0x7C14, 0xE2C1, 0x7C17, 0xE2CA, 0x7C1F, 0xE2D0, 0x7C21, 0x8AC8, 0x7C23, 0xE2CD, + 0x7C27, 0xE2CE, 0x7C2A, 0xE2CF, 0x7C2B, 0xE2D2, 0x7C37, 0xE2D1, 0x7C38, 0x94F4, 0x7C3D, 0xE2D3, 0x7C3E, 0x97FA, 0x7C3F, 0x95EB, + 0x7C40, 0xE2D8, 0x7C43, 0xE2D5, 0x7C4C, 0xE2D4, 0x7C4D, 0x90D0, 0x7C4F, 0xE2D7, 0x7C50, 0xE2D9, 0x7C54, 0xE2D6, 0x7C56, 0xE2DD, + 0x7C58, 0xE2DA, 0x7C5F, 0xE2DB, 0x7C60, 0xE2C4, 0x7C64, 0xE2DC, 0x7C65, 0xE2DE, 0x7C6C, 0xE2DF, 0x7C73, 0x95C4, 0x7C75, 0xE2E0, + 0x7C7E, 0x96E0, 0x7C81, 0x8BCC, 0x7C82, 0x8C48, 0x7C83, 0xE2E1, 0x7C89, 0x95B2, 0x7C8B, 0x9088, 0x7C8D, 0x96AE, 0x7C90, 0xE2E2, + 0x7C92, 0x97B1, 0x7C95, 0x9494, 0x7C97, 0x9165, 0x7C98, 0x9453, 0x7C9B, 0x8F6C, 0x7C9F, 0x88BE, 0x7CA1, 0xE2E7, 0x7CA2, 0xE2E5, + 0x7CA4, 0xE2E3, 0x7CA5, 0x8A9F, 0x7CA7, 0x8FCF, 0x7CA8, 0xE2E8, 0x7CAB, 0xE2E6, 0x7CAD, 0xE2E4, 0x7CAE, 0xE2EC, 0x7CB1, 0xE2EB, + 0x7CB2, 0xE2EA, 0x7CB3, 0xE2E9, 0x7CB9, 0xE2ED, 0x7CBD, 0xE2EE, 0x7CBE, 0x90B8, 0x7CC0, 0xE2EF, 0x7CC2, 0xE2F1, 0x7CC5, 0xE2F0, + 0x7CCA, 0x8CD0, 0x7CCE, 0x9157, 0x7CD2, 0xE2F3, 0x7CD6, 0x939C, 0x7CD8, 0xE2F2, 0x7CDC, 0xE2F4, 0x7CDE, 0x95B3, 0x7CDF, 0x918C, + 0x7CE0, 0x8D66, 0x7CE2, 0xE2F5, 0x7CE7, 0x97C6, 0x7CEF, 0xE2F7, 0x7CF2, 0xE2F8, 0x7CF4, 0xE2F9, 0x7CF6, 0xE2FA, 0x7CF8, 0x8E85, + 0x7CFA, 0xE2FB, 0x7CFB, 0x8C6E, 0x7CFE, 0x8B8A, 0x7D00, 0x8B49, 0x7D02, 0xE340, 0x7D04, 0x96F1, 0x7D05, 0x8D67, 0x7D06, 0xE2FC, + 0x7D0A, 0xE343, 0x7D0B, 0x96E4, 0x7D0D, 0x945B, 0x7D10, 0x9552, 0x7D14, 0x8F83, 0x7D15, 0xE342, 0x7D17, 0x8ED1, 0x7D18, 0x8D68, + 0x7D19, 0x8E86, 0x7D1A, 0x8B89, 0x7D1B, 0x95B4, 0x7D1C, 0xE341, 0x7D20, 0x9166, 0x7D21, 0x9661, 0x7D22, 0x8DF5, 0x7D2B, 0x8E87, + 0x7D2C, 0x92DB, 0x7D2E, 0xE346, 0x7D2F, 0x97DD, 0x7D30, 0x8DD7, 0x7D32, 0xE347, 0x7D33, 0x9061, 0x7D35, 0xE349, 0x7D39, 0x8FD0, + 0x7D3A, 0x8DAE, 0x7D3F, 0xE348, 0x7D42, 0x8F49, 0x7D43, 0x8CBC, 0x7D44, 0x9167, 0x7D45, 0xE344, 0x7D46, 0xE34A, 0x7D48, 0xFB8A, + 0x7D4B, 0xE345, 0x7D4C, 0x8C6F, 0x7D4E, 0xE34D, 0x7D4F, 0xE351, 0x7D50, 0x8C8B, 0x7D56, 0xE34C, 0x7D5B, 0xE355, 0x7D5C, 0xFB8B, + 0x7D5E, 0x8D69, 0x7D61, 0x978D, 0x7D62, 0x88BA, 0x7D63, 0xE352, 0x7D66, 0x8B8B, 0x7D68, 0xE34F, 0x7D6E, 0xE350, 0x7D71, 0x939D, + 0x7D72, 0xE34E, 0x7D73, 0xE34B, 0x7D75, 0x8A47, 0x7D76, 0x90E2, 0x7D79, 0x8CA6, 0x7D7D, 0xE357, 0x7D89, 0xE354, 0x7D8F, 0xE356, + 0x7D93, 0xE353, 0x7D99, 0x8C70, 0x7D9A, 0x91B1, 0x7D9B, 0xE358, 0x7D9C, 0x918E, 0x7D9F, 0xE365, 0x7DA0, 0xFB8D, 0x7DA2, 0xE361, + 0x7DA3, 0xE35B, 0x7DAB, 0xE35F, 0x7DAC, 0x8EF8, 0x7DAD, 0x88DB, 0x7DAE, 0xE35A, 0x7DAF, 0xE362, 0x7DB0, 0xE366, 0x7DB1, 0x8D6A, + 0x7DB2, 0x96D4, 0x7DB4, 0x92D4, 0x7DB5, 0xE35C, 0x7DB7, 0xFB8C, 0x7DB8, 0xE364, 0x7DBA, 0xE359, 0x7DBB, 0x925D, 0x7DBD, 0xE35E, + 0x7DBE, 0x88BB, 0x7DBF, 0x96C8, 0x7DC7, 0xE35D, 0x7DCA, 0x8BD9, 0x7DCB, 0x94EA, 0x7DCF, 0x918D, 0x7DD1, 0x97CE, 0x7DD2, 0x8F8F, + 0x7DD5, 0xE38E, 0x7DD6, 0xFB8E, 0x7DD8, 0xE367, 0x7DDA, 0x90FC, 0x7DDC, 0xE363, 0x7DDD, 0xE368, 0x7DDE, 0xE36A, 0x7DE0, 0x92F7, + 0x7DE1, 0xE36D, 0x7DE4, 0xE369, 0x7DE8, 0x95D2, 0x7DE9, 0x8AC9, 0x7DEC, 0x96C9, 0x7DEF, 0x88DC, 0x7DF2, 0xE36C, 0x7DF4, 0x97FB, + 0x7DFB, 0xE36B, 0x7E01, 0x898F, 0x7E04, 0x93EA, 0x7E05, 0xE36E, 0x7E09, 0xE375, 0x7E0A, 0xE36F, 0x7E0B, 0xE376, 0x7E12, 0xE372, + 0x7E1B, 0x949B, 0x7E1E, 0x8EC8, 0x7E1F, 0xE374, 0x7E21, 0xE371, 0x7E22, 0xE377, 0x7E23, 0xE370, 0x7E26, 0x8F63, 0x7E2B, 0x9644, + 0x7E2E, 0x8F6B, 0x7E31, 0xE373, 0x7E32, 0xE380, 0x7E35, 0xE37B, 0x7E37, 0xE37E, 0x7E39, 0xE37C, 0x7E3A, 0xE381, 0x7E3B, 0xE37A, + 0x7E3D, 0xE360, 0x7E3E, 0x90D1, 0x7E41, 0x94C9, 0x7E43, 0xE37D, 0x7E46, 0xE378, 0x7E4A, 0x9140, 0x7E4B, 0x8C71, 0x7E4D, 0x8F4A, + 0x7E52, 0xFB8F, 0x7E54, 0x9044, 0x7E55, 0x9155, 0x7E56, 0xE384, 0x7E59, 0xE386, 0x7E5A, 0xE387, 0x7E5D, 0xE383, 0x7E5E, 0xE385, + 0x7E66, 0xE379, 0x7E67, 0xE382, 0x7E69, 0xE38A, 0x7E6A, 0xE389, 0x7E6D, 0x969A, 0x7E70, 0x8C4A, 0x7E79, 0xE388, 0x7E7B, 0xE38C, + 0x7E7C, 0xE38B, 0x7E7D, 0xE38F, 0x7E7F, 0xE391, 0x7E82, 0x8E5B, 0x7E83, 0xE38D, 0x7E88, 0xE392, 0x7E89, 0xE393, 0x7E8A, 0xFA5C, + 0x7E8C, 0xE394, 0x7E8E, 0xE39A, 0x7E8F, 0x935A, 0x7E90, 0xE396, 0x7E92, 0xE395, 0x7E93, 0xE397, 0x7E94, 0xE398, 0x7E96, 0xE399, + 0x7E9B, 0xE39B, 0x7E9C, 0xE39C, 0x7F36, 0x8ACA, 0x7F38, 0xE39D, 0x7F3A, 0xE39E, 0x7F45, 0xE39F, 0x7F47, 0xFB90, 0x7F4C, 0xE3A0, + 0x7F4D, 0xE3A1, 0x7F4E, 0xE3A2, 0x7F50, 0xE3A3, 0x7F51, 0xE3A4, 0x7F54, 0xE3A6, 0x7F55, 0xE3A5, 0x7F58, 0xE3A7, 0x7F5F, 0xE3A8, + 0x7F60, 0xE3A9, 0x7F67, 0xE3AC, 0x7F68, 0xE3AA, 0x7F69, 0xE3AB, 0x7F6A, 0x8DDF, 0x7F6B, 0x8C72, 0x7F6E, 0x9275, 0x7F70, 0x94B1, + 0x7F72, 0x8F90, 0x7F75, 0x946C, 0x7F77, 0x94EB, 0x7F78, 0xE3AD, 0x7F79, 0x9CEB, 0x7F82, 0xE3AE, 0x7F83, 0xE3B0, 0x7F85, 0x9785, + 0x7F86, 0xE3AF, 0x7F87, 0xE3B2, 0x7F88, 0xE3B1, 0x7F8A, 0x9772, 0x7F8C, 0xE3B3, 0x7F8E, 0x94FC, 0x7F94, 0xE3B4, 0x7F9A, 0xE3B7, + 0x7F9D, 0xE3B6, 0x7F9E, 0xE3B5, 0x7FA1, 0xFB91, 0x7FA3, 0xE3B8, 0x7FA4, 0x8C51, 0x7FA8, 0x9141, 0x7FA9, 0x8B60, 0x7FAE, 0xE3BC, + 0x7FAF, 0xE3B9, 0x7FB2, 0xE3BA, 0x7FB6, 0xE3BD, 0x7FB8, 0xE3BE, 0x7FB9, 0xE3BB, 0x7FBD, 0x8948, 0x7FC1, 0x89A5, 0x7FC5, 0xE3C0, + 0x7FC6, 0xE3C1, 0x7FCA, 0xE3C2, 0x7FCC, 0x9782, 0x7FD2, 0x8F4B, 0x7FD4, 0xE3C4, 0x7FD5, 0xE3C3, 0x7FE0, 0x9089, 0x7FE1, 0xE3C5, + 0x7FE6, 0xE3C6, 0x7FE9, 0xE3C7, 0x7FEB, 0x8AE3, 0x7FF0, 0x8ACB, 0x7FF3, 0xE3C8, 0x7FF9, 0xE3C9, 0x7FFB, 0x967C, 0x7FFC, 0x9783, + 0x8000, 0x9773, 0x8001, 0x9856, 0x8003, 0x8D6C, 0x8004, 0xE3CC, 0x8005, 0x8ED2, 0x8006, 0xE3CB, 0x800B, 0xE3CD, 0x800C, 0x8EA7, + 0x8010, 0x91CF, 0x8012, 0xE3CE, 0x8015, 0x8D6B, 0x8017, 0x96D5, 0x8018, 0xE3CF, 0x8019, 0xE3D0, 0x801C, 0xE3D1, 0x8021, 0xE3D2, + 0x8028, 0xE3D3, 0x8033, 0x8EA8, 0x8036, 0x96EB, 0x803B, 0xE3D5, 0x803D, 0x925E, 0x803F, 0xE3D4, 0x8046, 0xE3D7, 0x804A, 0xE3D6, + 0x8052, 0xE3D8, 0x8056, 0x90B9, 0x8058, 0xE3D9, 0x805A, 0xE3DA, 0x805E, 0x95B7, 0x805F, 0xE3DB, 0x8061, 0x918F, 0x8062, 0xE3DC, + 0x8068, 0xE3DD, 0x806F, 0x97FC, 0x8070, 0xE3E0, 0x8072, 0xE3DF, 0x8073, 0xE3DE, 0x8074, 0x92AE, 0x8076, 0xE3E1, 0x8077, 0x9045, + 0x8079, 0xE3E2, 0x807D, 0xE3E3, 0x807E, 0x9857, 0x807F, 0xE3E4, 0x8084, 0xE3E5, 0x8085, 0xE3E7, 0x8086, 0xE3E6, 0x8087, 0x94A3, + 0x8089, 0x93F7, 0x808B, 0x985D, 0x808C, 0x94A7, 0x8093, 0xE3E9, 0x8096, 0x8FD1, 0x8098, 0x9549, 0x809A, 0xE3EA, 0x809B, 0xE3E8, + 0x809D, 0x8ACC, 0x80A1, 0x8CD2, 0x80A2, 0x8E88, 0x80A5, 0x94EC, 0x80A9, 0x8CA8, 0x80AA, 0x9662, 0x80AC, 0xE3ED, 0x80AD, 0xE3EB, + 0x80AF, 0x8D6D, 0x80B1, 0x8D6E, 0x80B2, 0x88E7, 0x80B4, 0x8DE6, 0x80BA, 0x9478, 0x80C3, 0x88DD, 0x80C4, 0xE3F2, 0x80C6, 0x925F, + 0x80CC, 0x9477, 0x80CE, 0x91D9, 0x80D6, 0xE3F4, 0x80D9, 0xE3F0, 0x80DA, 0xE3F3, 0x80DB, 0xE3EE, 0x80DD, 0xE3F1, 0x80DE, 0x9645, + 0x80E1, 0x8CD3, 0x80E4, 0x88FB, 0x80E5, 0xE3EF, 0x80EF, 0xE3F6, 0x80F1, 0xE3F7, 0x80F4, 0x93B7, 0x80F8, 0x8BB9, 0x80FC, 0xE445, + 0x80FD, 0x945C, 0x8102, 0x8E89, 0x8105, 0x8BBA, 0x8106, 0x90C6, 0x8107, 0x9865, 0x8108, 0x96AC, 0x8109, 0xE3F5, 0x810A, 0x90D2, + 0x811A, 0x8B72, 0x811B, 0xE3F8, 0x8123, 0xE3FA, 0x8129, 0xE3F9, 0x812F, 0xE3FB, 0x8131, 0x9245, 0x8133, 0x945D, 0x8139, 0x92AF, + 0x813E, 0xE442, 0x8146, 0xE441, 0x814B, 0xE3FC, 0x814E, 0x9074, 0x8150, 0x9585, 0x8151, 0xE444, 0x8153, 0xE443, 0x8154, 0x8D6F, + 0x8155, 0x9872, 0x815F, 0xE454, 0x8165, 0xE448, 0x8166, 0xE449, 0x816B, 0x8EEE, 0x816E, 0xE447, 0x8170, 0x8D98, 0x8171, 0xE446, + 0x8174, 0xE44A, 0x8178, 0x92B0, 0x8179, 0x95A0, 0x817A, 0x9142, 0x817F, 0x91DA, 0x8180, 0xE44E, 0x8182, 0xE44F, 0x8183, 0xE44B, + 0x8188, 0xE44C, 0x818A, 0xE44D, 0x818F, 0x8D70, 0x8193, 0xE455, 0x8195, 0xE451, 0x819A, 0x9586, 0x819C, 0x968C, 0x819D, 0x9547, + 0x81A0, 0xE450, 0x81A3, 0xE453, 0x81A4, 0xE452, 0x81A8, 0x9663, 0x81A9, 0xE456, 0x81B0, 0xE457, 0x81B3, 0x9156, 0x81B5, 0xE458, + 0x81B8, 0xE45A, 0x81BA, 0xE45E, 0x81BD, 0xE45B, 0x81BE, 0xE459, 0x81BF, 0x945E, 0x81C0, 0xE45C, 0x81C2, 0xE45D, 0x81C6, 0x89B0, + 0x81C8, 0xE464, 0x81C9, 0xE45F, 0x81CD, 0xE460, 0x81D1, 0xE461, 0x81D3, 0x919F, 0x81D8, 0xE463, 0x81D9, 0xE462, 0x81DA, 0xE465, + 0x81DF, 0xE466, 0x81E0, 0xE467, 0x81E3, 0x9062, 0x81E5, 0x89E7, 0x81E7, 0xE468, 0x81E8, 0x97D5, 0x81EA, 0x8EA9, 0x81ED, 0x8F4C, + 0x81F3, 0x8E8A, 0x81F4, 0x9276, 0x81FA, 0xE469, 0x81FB, 0xE46A, 0x81FC, 0x8950, 0x81FE, 0xE46B, 0x8201, 0xE46C, 0x8202, 0xE46D, + 0x8205, 0xE46E, 0x8207, 0xE46F, 0x8208, 0x8BBB, 0x8209, 0x9DA8, 0x820A, 0xE470, 0x820C, 0x90E3, 0x820D, 0xE471, 0x820E, 0x8EC9, + 0x8210, 0xE472, 0x8212, 0x98AE, 0x8216, 0xE473, 0x8217, 0x95DC, 0x8218, 0x8ADA, 0x821B, 0x9143, 0x821C, 0x8F77, 0x821E, 0x9591, + 0x821F, 0x8F4D, 0x8229, 0xE474, 0x822A, 0x8D71, 0x822B, 0xE475, 0x822C, 0x94CA, 0x822E, 0xE484, 0x8233, 0xE477, 0x8235, 0x91C7, + 0x8236, 0x9495, 0x8237, 0x8CBD, 0x8238, 0xE476, 0x8239, 0x9144, 0x8240, 0xE478, 0x8247, 0x92F8, 0x8258, 0xE47A, 0x8259, 0xE479, + 0x825A, 0xE47C, 0x825D, 0xE47B, 0x825F, 0xE47D, 0x8262, 0xE480, 0x8264, 0xE47E, 0x8266, 0x8ACD, 0x8268, 0xE481, 0x826A, 0xE482, + 0x826B, 0xE483, 0x826E, 0x8DAF, 0x826F, 0x97C7, 0x8271, 0xE485, 0x8272, 0x9046, 0x8276, 0x8990, 0x8277, 0xE486, 0x8278, 0xE487, + 0x827E, 0xE488, 0x828B, 0x88F0, 0x828D, 0xE489, 0x8292, 0xE48A, 0x8299, 0x9587, 0x829D, 0x8EC5, 0x829F, 0xE48C, 0x82A5, 0x8A48, + 0x82A6, 0x88B0, 0x82AB, 0xE48B, 0x82AC, 0xE48E, 0x82AD, 0x946D, 0x82AF, 0x9063, 0x82B1, 0x89D4, 0x82B3, 0x9646, 0x82B8, 0x8C7C, + 0x82B9, 0x8BDA, 0x82BB, 0xE48D, 0x82BD, 0x89E8, 0x82C5, 0x8AA1, 0x82D1, 0x8991, 0x82D2, 0xE492, 0x82D3, 0x97E8, 0x82D4, 0x91DB, + 0x82D7, 0x9563, 0x82D9, 0xE49E, 0x82DB, 0x89D5, 0x82DC, 0xE49C, 0x82DE, 0xE49A, 0x82DF, 0xE491, 0x82E1, 0xE48F, 0x82E3, 0xE490, + 0x82E5, 0x8EE1, 0x82E6, 0x8BEA, 0x82E7, 0x9297, 0x82EB, 0x93CF, 0x82F1, 0x8970, 0x82F3, 0xE494, 0x82F4, 0xE493, 0x82F9, 0xE499, + 0x82FA, 0xE495, 0x82FB, 0xE498, 0x8301, 0xFB93, 0x8302, 0x96CE, 0x8303, 0xE497, 0x8304, 0x89D6, 0x8305, 0x8A9D, 0x8306, 0xE49B, + 0x8309, 0xE49D, 0x830E, 0x8C73, 0x8316, 0xE4A1, 0x8317, 0xE4AA, 0x8318, 0xE4AB, 0x831C, 0x88A9, 0x8323, 0xE4B2, 0x8328, 0x88EF, + 0x832B, 0xE4A9, 0x832F, 0xE4A8, 0x8331, 0xE4A3, 0x8332, 0xE4A2, 0x8334, 0xE4A0, 0x8335, 0xE49F, 0x8336, 0x9283, 0x8338, 0x91F9, + 0x8339, 0xE4A5, 0x8340, 0xE4A4, 0x8345, 0xE4A7, 0x8349, 0x9190, 0x834A, 0x8C74, 0x834F, 0x8960, 0x8350, 0xE4A6, 0x8352, 0x8D72, + 0x8358, 0x9191, 0x8362, 0xFB94, 0x8373, 0xE4B8, 0x8375, 0xE4B9, 0x8377, 0x89D7, 0x837B, 0x89AC, 0x837C, 0xE4B6, 0x837F, 0xFB95, + 0x8385, 0xE4AC, 0x8387, 0xE4B4, 0x8389, 0xE4BB, 0x838A, 0xE4B5, 0x838E, 0xE4B3, 0x8393, 0xE496, 0x8396, 0xE4B1, 0x839A, 0xE4AD, + 0x839E, 0x8ACE, 0x839F, 0xE4AF, 0x83A0, 0xE4BA, 0x83A2, 0xE4B0, 0x83A8, 0xE4BC, 0x83AA, 0xE4AE, 0x83AB, 0x949C, 0x83B1, 0x9789, + 0x83B5, 0xE4B7, 0x83BD, 0xE4CD, 0x83C1, 0xE4C5, 0x83C5, 0x909B, 0x83C7, 0xFB96, 0x83CA, 0x8B65, 0x83CC, 0x8BDB, 0x83CE, 0xE4C0, + 0x83D3, 0x89D9, 0x83D6, 0x8FD2, 0x83D8, 0xE4C3, 0x83DC, 0x8DD8, 0x83DF, 0x9370, 0x83E0, 0xE4C8, 0x83E9, 0x95EC, 0x83EB, 0xE4BF, + 0x83EF, 0x89D8, 0x83F0, 0x8CD4, 0x83F1, 0x9548, 0x83F2, 0xE4C9, 0x83F4, 0xE4BD, 0x83F6, 0xFB97, 0x83F7, 0xE4C6, 0x83FB, 0xE4D0, + 0x83FD, 0xE4C1, 0x8403, 0xE4C2, 0x8404, 0x93B8, 0x8407, 0xE4C7, 0x840B, 0xE4C4, 0x840C, 0x9647, 0x840D, 0xE4CA, 0x840E, 0x88DE, + 0x8413, 0xE4BE, 0x8420, 0xE4CC, 0x8422, 0xE4CB, 0x8429, 0x948B, 0x842A, 0xE4D2, 0x842C, 0xE4DD, 0x8431, 0x8A9E, 0x8435, 0xE4E0, + 0x8438, 0xE4CE, 0x843C, 0xE4D3, 0x843D, 0x978E, 0x8446, 0xE4DC, 0x8448, 0xFB98, 0x8449, 0x9774, 0x844E, 0x97A8, 0x8457, 0x9298, + 0x845B, 0x8A8B, 0x8461, 0x9592, 0x8462, 0xE4E2, 0x8463, 0x939F, 0x8466, 0x88AF, 0x8469, 0xE4DB, 0x846B, 0xE4D7, 0x846C, 0x9192, + 0x846D, 0xE4D1, 0x846E, 0xE4D9, 0x846F, 0xE4DE, 0x8471, 0x944B, 0x8475, 0x88A8, 0x8477, 0xE4D6, 0x8479, 0xE4DF, 0x847A, 0x9598, + 0x8482, 0xE4DA, 0x8484, 0xE4D5, 0x848B, 0x8FD3, 0x8490, 0x8F4E, 0x8494, 0x8EAA, 0x8499, 0x96D6, 0x849C, 0x9566, 0x849F, 0xE4E5, + 0x84A1, 0xE4EE, 0x84AD, 0xE4D8, 0x84B2, 0x8A97, 0x84B4, 0xFB99, 0x84B8, 0x8FF6, 0x84B9, 0xE4E3, 0x84BB, 0xE4E8, 0x84BC, 0x9193, + 0x84BF, 0xE4E4, 0x84C1, 0xE4EB, 0x84C4, 0x927E, 0x84C6, 0xE4EC, 0x84C9, 0x9775, 0x84CA, 0xE4E1, 0x84CB, 0x8A57, 0x84CD, 0xE4E7, + 0x84D0, 0xE4EA, 0x84D1, 0x96AA, 0x84D6, 0xE4ED, 0x84D9, 0xE4E6, 0x84DA, 0xE4E9, 0x84DC, 0xFA60, 0x84EC, 0x9648, 0x84EE, 0x9840, + 0x84F4, 0xE4F1, 0x84FC, 0xE4F8, 0x84FF, 0xE4F0, 0x8500, 0x8EC1, 0x8506, 0xE4CF, 0x8511, 0x95CC, 0x8513, 0x96A0, 0x8514, 0xE4F7, + 0x8515, 0xE4F6, 0x8517, 0xE4F2, 0x8518, 0xE4F3, 0x851A, 0x8955, 0x851F, 0xE4F5, 0x8521, 0xE4EF, 0x8526, 0x92D3, 0x852C, 0xE4F4, + 0x852D, 0x88FC, 0x8535, 0x91A0, 0x853D, 0x95C1, 0x8540, 0xE4F9, 0x8541, 0xE540, 0x8543, 0x94D7, 0x8548, 0xE4FC, 0x8549, 0x8FD4, + 0x854A, 0x8EC7, 0x854B, 0xE542, 0x854E, 0x8BBC, 0x8553, 0xFB9A, 0x8555, 0xE543, 0x8557, 0x9599, 0x8558, 0xE4FB, 0x8559, 0xFB9B, + 0x855A, 0xE4D4, 0x8563, 0xE4FA, 0x8568, 0x986E, 0x8569, 0x93A0, 0x856A, 0x9593, 0x856B, 0xFB9C, 0x856D, 0xE54A, 0x8577, 0xE550, + 0x857E, 0xE551, 0x8580, 0xE544, 0x8584, 0x9496, 0x8587, 0xE54E, 0x8588, 0xE546, 0x858A, 0xE548, 0x8590, 0xE552, 0x8591, 0xE547, + 0x8594, 0xE54B, 0x8597, 0x8992, 0x8599, 0x93E3, 0x859B, 0xE54C, 0x859C, 0xE54F, 0x85A4, 0xE545, 0x85A6, 0x9145, 0x85A8, 0xE549, + 0x85A9, 0x8E46, 0x85AA, 0x9064, 0x85AB, 0x8C4F, 0x85AC, 0x96F2, 0x85AE, 0x96F7, 0x85AF, 0x8F92, 0x85B0, 0xFB9E, 0x85B9, 0xE556, + 0x85BA, 0xE554, 0x85C1, 0x986D, 0x85C9, 0xE553, 0x85CD, 0x9795, 0x85CF, 0xE555, 0x85D0, 0xE557, 0x85D5, 0xE558, 0x85DC, 0xE55B, + 0x85DD, 0xE559, 0x85E4, 0x93A1, 0x85E5, 0xE55A, 0x85E9, 0x94CB, 0x85EA, 0xE54D, 0x85F7, 0x8F93, 0x85F9, 0xE55C, 0x85FA, 0xE561, + 0x85FB, 0x9194, 0x85FE, 0xE560, 0x8602, 0xE541, 0x8606, 0xE562, 0x8607, 0x9168, 0x860A, 0xE55D, 0x860B, 0xE55F, 0x8613, 0xE55E, + 0x8616, 0x9F50, 0x8617, 0x9F41, 0x861A, 0xE564, 0x8622, 0xE563, 0x862D, 0x9796, 0x862F, 0xE1BA, 0x8630, 0xE565, 0x863F, 0xE566, + 0x864D, 0xE567, 0x864E, 0x8CD5, 0x8650, 0x8B73, 0x8654, 0xE569, 0x8655, 0x997C, 0x865A, 0x8B95, 0x865C, 0x97B8, 0x865E, 0x8BF1, + 0x865F, 0xE56A, 0x8667, 0xE56B, 0x866B, 0x928E, 0x8671, 0xE56C, 0x8679, 0x93F8, 0x867B, 0x88B8, 0x868A, 0x89E1, 0x868B, 0xE571, + 0x868C, 0xE572, 0x8693, 0xE56D, 0x8695, 0x8E5C, 0x86A3, 0xE56E, 0x86A4, 0x9461, 0x86A9, 0xE56F, 0x86AA, 0xE570, 0x86AB, 0xE57A, + 0x86AF, 0xE574, 0x86B0, 0xE577, 0x86B6, 0xE573, 0x86C4, 0xE575, 0x86C6, 0xE576, 0x86C7, 0x8ED6, 0x86C9, 0xE578, 0x86CB, 0x9260, + 0x86CD, 0x8C75, 0x86CE, 0x8A61, 0x86D4, 0xE57B, 0x86D9, 0x8A5E, 0x86DB, 0xE581, 0x86DE, 0xE57C, 0x86DF, 0xE580, 0x86E4, 0x94B8, + 0x86E9, 0xE57D, 0x86EC, 0xE57E, 0x86ED, 0x9567, 0x86EE, 0x94D8, 0x86EF, 0xE582, 0x86F8, 0x91FB, 0x86F9, 0xE58C, 0x86FB, 0xE588, + 0x86FE, 0x89E9, 0x8700, 0xE586, 0x8702, 0x9649, 0x8703, 0xE587, 0x8706, 0xE584, 0x8708, 0xE585, 0x8709, 0xE58A, 0x870A, 0xE58D, + 0x870D, 0xE58B, 0x8711, 0xE589, 0x8712, 0xE583, 0x8718, 0x9277, 0x871A, 0xE594, 0x871C, 0x96A8, 0x8725, 0xE592, 0x8729, 0xE593, + 0x8734, 0xE58E, 0x8737, 0xE590, 0x873B, 0xE591, 0x873F, 0xE58F, 0x8749, 0x90E4, 0x874B, 0x9858, 0x874C, 0xE598, 0x874E, 0xE599, + 0x8753, 0xE59F, 0x8755, 0x9049, 0x8757, 0xE59B, 0x8759, 0xE59E, 0x875F, 0xE596, 0x8760, 0xE595, 0x8763, 0xE5A0, 0x8766, 0x89DA, + 0x8768, 0xE59C, 0x876A, 0xE5A1, 0x876E, 0xE59D, 0x8774, 0xE59A, 0x8776, 0x92B1, 0x8778, 0xE597, 0x877F, 0x9488, 0x8782, 0xE5A5, + 0x878D, 0x975A, 0x879F, 0xE5A4, 0x87A2, 0xE5A3, 0x87AB, 0xE5AC, 0x87AF, 0xE5A6, 0x87B3, 0xE5AE, 0x87BA, 0x9786, 0x87BB, 0xE5B1, + 0x87BD, 0xE5A8, 0x87C0, 0xE5A9, 0x87C4, 0xE5AD, 0x87C6, 0xE5B0, 0x87C7, 0xE5AF, 0x87CB, 0xE5A7, 0x87D0, 0xE5AA, 0x87D2, 0xE5BB, + 0x87E0, 0xE5B4, 0x87EF, 0xE5B2, 0x87F2, 0xE5B3, 0x87F6, 0xE5B8, 0x87F7, 0xE5B9, 0x87F9, 0x8A49, 0x87FB, 0x8B61, 0x87FE, 0xE5B7, + 0x8805, 0xE5A2, 0x8807, 0xFBA1, 0x880D, 0xE5B6, 0x880E, 0xE5BA, 0x880F, 0xE5B5, 0x8811, 0xE5BC, 0x8815, 0xE5BE, 0x8816, 0xE5BD, + 0x8821, 0xE5C0, 0x8822, 0xE5BF, 0x8823, 0xE579, 0x8827, 0xE5C4, 0x8831, 0xE5C1, 0x8836, 0xE5C2, 0x8839, 0xE5C3, 0x883B, 0xE5C5, + 0x8840, 0x8C8C, 0x8842, 0xE5C7, 0x8844, 0xE5C6, 0x8846, 0x8F4F, 0x884C, 0x8D73, 0x884D, 0x9FA5, 0x8852, 0xE5C8, 0x8853, 0x8F70, + 0x8857, 0x8A58, 0x8859, 0xE5C9, 0x885B, 0x8971, 0x885D, 0x8FD5, 0x885E, 0xE5CA, 0x8861, 0x8D74, 0x8862, 0xE5CB, 0x8863, 0x88DF, + 0x8868, 0x955C, 0x886B, 0xE5CC, 0x8870, 0x908A, 0x8872, 0xE5D3, 0x8875, 0xE5D0, 0x8877, 0x928F, 0x887D, 0xE5D1, 0x887E, 0xE5CE, + 0x887F, 0x8BDC, 0x8881, 0xE5CD, 0x8882, 0xE5D4, 0x8888, 0x8C55, 0x888B, 0x91DC, 0x888D, 0xE5DA, 0x8892, 0xE5D6, 0x8896, 0x91B3, + 0x8897, 0xE5D5, 0x8899, 0xE5D8, 0x889E, 0xE5CF, 0x88A2, 0xE5D9, 0x88A4, 0xE5DB, 0x88AB, 0x94ED, 0x88AE, 0xE5D7, 0x88B0, 0xE5DC, + 0x88B1, 0xE5DE, 0x88B4, 0x8CD1, 0x88B5, 0xE5D2, 0x88B7, 0x88BF, 0x88BF, 0xE5DD, 0x88C1, 0x8DD9, 0x88C2, 0x97F4, 0x88C3, 0xE5DF, + 0x88C4, 0xE5E0, 0x88C5, 0x9195, 0x88CF, 0x97A0, 0x88D4, 0xE5E1, 0x88D5, 0x9754, 0x88D8, 0xE5E2, 0x88D9, 0xE5E3, 0x88DC, 0x95E2, + 0x88DD, 0xE5E4, 0x88DF, 0x8DBE, 0x88E1, 0x97A1, 0x88E8, 0xE5E9, 0x88F2, 0xE5EA, 0x88F3, 0x8FD6, 0x88F4, 0xE5E8, 0x88F5, 0xFBA2, + 0x88F8, 0x9787, 0x88F9, 0xE5E5, 0x88FC, 0xE5E7, 0x88FD, 0x90BB, 0x88FE, 0x909E, 0x8902, 0xE5E6, 0x8904, 0xE5EB, 0x8907, 0x95A1, + 0x890A, 0xE5ED, 0x890C, 0xE5EC, 0x8910, 0x8A8C, 0x8912, 0x964A, 0x8913, 0xE5EE, 0x891C, 0xFA5D, 0x891D, 0xE5FA, 0x891E, 0xE5F0, + 0x8925, 0xE5F1, 0x892A, 0xE5F2, 0x892B, 0xE5F3, 0x8936, 0xE5F7, 0x8938, 0xE5F8, 0x893B, 0xE5F6, 0x8941, 0xE5F4, 0x8943, 0xE5EF, + 0x8944, 0xE5F5, 0x894C, 0xE5F9, 0x894D, 0xE8B5, 0x8956, 0x89A6, 0x895E, 0xE5FC, 0x895F, 0x8BDD, 0x8960, 0xE5FB, 0x8964, 0xE641, + 0x8966, 0xE640, 0x896A, 0xE643, 0x896D, 0xE642, 0x896F, 0xE644, 0x8972, 0x8F50, 0x8974, 0xE645, 0x8977, 0xE646, 0x897E, 0xE647, + 0x897F, 0x90BC, 0x8981, 0x9776, 0x8983, 0xE648, 0x8986, 0x95A2, 0x8987, 0x9465, 0x8988, 0xE649, 0x898A, 0xE64A, 0x898B, 0x8CA9, + 0x898F, 0x8B4B, 0x8993, 0xE64B, 0x8996, 0x8E8B, 0x8997, 0x9460, 0x8998, 0xE64C, 0x899A, 0x8A6F, 0x89A1, 0xE64D, 0x89A6, 0xE64F, + 0x89A7, 0x9797, 0x89A9, 0xE64E, 0x89AA, 0x9065, 0x89AC, 0xE650, 0x89AF, 0xE651, 0x89B2, 0xE652, 0x89B3, 0x8ACF, 0x89BA, 0xE653, + 0x89BD, 0xE654, 0x89BF, 0xE655, 0x89C0, 0xE656, 0x89D2, 0x8A70, 0x89DA, 0xE657, 0x89DC, 0xE658, 0x89DD, 0xE659, 0x89E3, 0x89F0, + 0x89E6, 0x9047, 0x89E7, 0xE65A, 0x89F4, 0xE65B, 0x89F8, 0xE65C, 0x8A00, 0x8CBE, 0x8A02, 0x92F9, 0x8A03, 0xE65D, 0x8A08, 0x8C76, + 0x8A0A, 0x9075, 0x8A0C, 0xE660, 0x8A0E, 0x93A2, 0x8A10, 0xE65F, 0x8A12, 0xFBA3, 0x8A13, 0x8C50, 0x8A16, 0xE65E, 0x8A17, 0x91F5, + 0x8A18, 0x8B4C, 0x8A1B, 0xE661, 0x8A1D, 0xE662, 0x8A1F, 0x8FD7, 0x8A23, 0x8C8D, 0x8A25, 0xE663, 0x8A2A, 0x964B, 0x8A2D, 0x90DD, + 0x8A31, 0x8B96, 0x8A33, 0x96F3, 0x8A34, 0x9169, 0x8A36, 0xE664, 0x8A37, 0xFBA4, 0x8A3A, 0x9066, 0x8A3B, 0x9290, 0x8A3C, 0x8FD8, + 0x8A41, 0xE665, 0x8A46, 0xE668, 0x8A48, 0xE669, 0x8A50, 0x8DBC, 0x8A51, 0x91C0, 0x8A52, 0xE667, 0x8A54, 0x8FD9, 0x8A55, 0x955D, + 0x8A5B, 0xE666, 0x8A5E, 0x8E8C, 0x8A60, 0x8972, 0x8A62, 0xE66D, 0x8A63, 0x8C77, 0x8A66, 0x8E8E, 0x8A69, 0x8E8D, 0x8A6B, 0x986C, + 0x8A6C, 0xE66C, 0x8A6D, 0xE66B, 0x8A6E, 0x9146, 0x8A70, 0x8B6C, 0x8A71, 0x9862, 0x8A72, 0x8A59, 0x8A73, 0x8FDA, 0x8A79, 0xFBA5, + 0x8A7C, 0xE66A, 0x8A82, 0xE66F, 0x8A84, 0xE670, 0x8A85, 0xE66E, 0x8A87, 0x8CD6, 0x8A89, 0x975F, 0x8A8C, 0x8E8F, 0x8A8D, 0x9446, + 0x8A91, 0xE673, 0x8A93, 0x90BE, 0x8A95, 0x9261, 0x8A98, 0x9755, 0x8A9A, 0xE676, 0x8A9E, 0x8CEA, 0x8AA0, 0x90BD, 0x8AA1, 0xE672, + 0x8AA3, 0xE677, 0x8AA4, 0x8CEB, 0x8AA5, 0xE674, 0x8AA6, 0xE675, 0x8AA7, 0xFBA6, 0x8AA8, 0xE671, 0x8AAC, 0x90E0, 0x8AAD, 0x93C7, + 0x8AB0, 0x924E, 0x8AB2, 0x89DB, 0x8AB9, 0x94EE, 0x8ABC, 0x8B62, 0x8ABE, 0xFBA7, 0x8ABF, 0x92B2, 0x8AC2, 0xE67A, 0x8AC4, 0xE678, + 0x8AC7, 0x926B, 0x8ACB, 0x90BF, 0x8ACC, 0x8AD0, 0x8ACD, 0xE679, 0x8ACF, 0x907A, 0x8AD2, 0x97C8, 0x8AD6, 0x985F, 0x8ADA, 0xE67B, + 0x8ADB, 0xE687, 0x8ADC, 0x92B3, 0x8ADE, 0xE686, 0x8ADF, 0xFBA8, 0x8AE0, 0xE683, 0x8AE1, 0xE68B, 0x8AE2, 0xE684, 0x8AE4, 0xE680, + 0x8AE6, 0x92FA, 0x8AE7, 0xE67E, 0x8AEB, 0xE67C, 0x8AED, 0x9740, 0x8AEE, 0x8E90, 0x8AF1, 0xE681, 0x8AF3, 0xE67D, 0x8AF6, 0xFBAA, + 0x8AF7, 0xE685, 0x8AF8, 0x8F94, 0x8AFA, 0x8CBF, 0x8AFE, 0x91F8, 0x8B00, 0x9664, 0x8B01, 0x8979, 0x8B02, 0x88E0, 0x8B04, 0x93A3, + 0x8B07, 0xE689, 0x8B0C, 0xE688, 0x8B0E, 0x93E4, 0x8B10, 0xE68D, 0x8B14, 0xE682, 0x8B16, 0xE68C, 0x8B17, 0xE68E, 0x8B19, 0x8CAA, + 0x8B1A, 0xE68A, 0x8B1B, 0x8D75, 0x8B1D, 0x8ED3, 0x8B20, 0xE68F, 0x8B21, 0x9777, 0x8B26, 0xE692, 0x8B28, 0xE695, 0x8B2B, 0xE693, + 0x8B2C, 0x9554, 0x8B33, 0xE690, 0x8B39, 0x8BDE, 0x8B3E, 0xE694, 0x8B41, 0xE696, 0x8B49, 0xE69A, 0x8B4C, 0xE697, 0x8B4E, 0xE699, + 0x8B4F, 0xE698, 0x8B53, 0xFBAB, 0x8B56, 0xE69B, 0x8B58, 0x8EAF, 0x8B5A, 0xE69D, 0x8B5B, 0xE69C, 0x8B5C, 0x9588, 0x8B5F, 0xE69F, + 0x8B66, 0x8C78, 0x8B6B, 0xE69E, 0x8B6C, 0xE6A0, 0x8B6F, 0xE6A1, 0x8B70, 0x8B63, 0x8B71, 0xE3BF, 0x8B72, 0x8FF7, 0x8B74, 0xE6A2, + 0x8B77, 0x8CEC, 0x8B7D, 0xE6A3, 0x8B7F, 0xFBAC, 0x8B80, 0xE6A4, 0x8B83, 0x8E5D, 0x8B8A, 0x9DCC, 0x8B8C, 0xE6A5, 0x8B8E, 0xE6A6, + 0x8B90, 0x8F51, 0x8B92, 0xE6A7, 0x8B93, 0xE6A8, 0x8B96, 0xE6A9, 0x8B99, 0xE6AA, 0x8B9A, 0xE6AB, 0x8C37, 0x924A, 0x8C3A, 0xE6AC, + 0x8C3F, 0xE6AE, 0x8C41, 0xE6AD, 0x8C46, 0x93A4, 0x8C48, 0xE6AF, 0x8C4A, 0x964C, 0x8C4C, 0xE6B0, 0x8C4E, 0xE6B1, 0x8C50, 0xE6B2, + 0x8C55, 0xE6B3, 0x8C5A, 0x93D8, 0x8C61, 0x8FDB, 0x8C62, 0xE6B4, 0x8C6A, 0x8D8B, 0x8C6B, 0x98AC, 0x8C6C, 0xE6B5, 0x8C78, 0xE6B6, + 0x8C79, 0x955E, 0x8C7A, 0xE6B7, 0x8C7C, 0xE6BF, 0x8C82, 0xE6B8, 0x8C85, 0xE6BA, 0x8C89, 0xE6B9, 0x8C8A, 0xE6BB, 0x8C8C, 0x9665, + 0x8C8D, 0xE6BC, 0x8C8E, 0xE6BD, 0x8C94, 0xE6BE, 0x8C98, 0xE6C0, 0x8C9D, 0x8A4C, 0x8C9E, 0x92E5, 0x8CA0, 0x9589, 0x8CA1, 0x8DE0, + 0x8CA2, 0x8D76, 0x8CA7, 0x956E, 0x8CA8, 0x89DD, 0x8CA9, 0x94CC, 0x8CAA, 0xE6C3, 0x8CAB, 0x8AD1, 0x8CAC, 0x90D3, 0x8CAD, 0xE6C2, + 0x8CAE, 0xE6C7, 0x8CAF, 0x9299, 0x8CB0, 0x96E1, 0x8CB2, 0xE6C5, 0x8CB3, 0xE6C6, 0x8CB4, 0x8B4D, 0x8CB6, 0xE6C8, 0x8CB7, 0x9483, + 0x8CB8, 0x91DD, 0x8CBB, 0x94EF, 0x8CBC, 0x935C, 0x8CBD, 0xE6C4, 0x8CBF, 0x9666, 0x8CC0, 0x89EA, 0x8CC1, 0xE6CA, 0x8CC2, 0x9847, + 0x8CC3, 0x92C0, 0x8CC4, 0x9864, 0x8CC7, 0x8E91, 0x8CC8, 0xE6C9, 0x8CCA, 0x91AF, 0x8CCD, 0xE6DA, 0x8CCE, 0x9147, 0x8CD1, 0x93F6, + 0x8CD3, 0x956F, 0x8CDA, 0xE6CD, 0x8CDB, 0x8E5E, 0x8CDC, 0x8E92, 0x8CDE, 0x8FDC, 0x8CE0, 0x9485, 0x8CE2, 0x8CAB, 0x8CE3, 0xE6CC, + 0x8CE4, 0xE6CB, 0x8CE6, 0x958A, 0x8CEA, 0x8EBF, 0x8CED, 0x9371, 0x8CF0, 0xFBAD, 0x8CF4, 0xFBAE, 0x8CFA, 0xE6CF, 0x8CFB, 0xE6D0, + 0x8CFC, 0x8D77, 0x8CFD, 0xE6CE, 0x8D04, 0xE6D1, 0x8D05, 0xE6D2, 0x8D07, 0xE6D4, 0x8D08, 0x91A1, 0x8D0A, 0xE6D3, 0x8D0B, 0x8AE4, + 0x8D0D, 0xE6D6, 0x8D0F, 0xE6D5, 0x8D10, 0xE6D7, 0x8D12, 0xFBAF, 0x8D13, 0xE6D9, 0x8D14, 0xE6DB, 0x8D16, 0xE6DC, 0x8D64, 0x90D4, + 0x8D66, 0x8ECD, 0x8D67, 0xE6DD, 0x8D6B, 0x8A71, 0x8D6D, 0xE6DE, 0x8D70, 0x9196, 0x8D71, 0xE6DF, 0x8D73, 0xE6E0, 0x8D74, 0x958B, + 0x8D76, 0xFBB0, 0x8D77, 0x8B4E, 0x8D81, 0xE6E1, 0x8D85, 0x92B4, 0x8D8A, 0x897A, 0x8D99, 0xE6E2, 0x8DA3, 0x8EEF, 0x8DA8, 0x9096, + 0x8DB3, 0x91AB, 0x8DBA, 0xE6E5, 0x8DBE, 0xE6E4, 0x8DC2, 0xE6E3, 0x8DCB, 0xE6EB, 0x8DCC, 0xE6E9, 0x8DCF, 0xE6E6, 0x8DD6, 0xE6E8, + 0x8DDA, 0xE6E7, 0x8DDB, 0xE6EA, 0x8DDD, 0x8B97, 0x8DDF, 0xE6EE, 0x8DE1, 0x90D5, 0x8DE3, 0xE6EF, 0x8DE8, 0x8CD7, 0x8DEA, 0xE6EC, + 0x8DEB, 0xE6ED, 0x8DEF, 0x9848, 0x8DF3, 0x92B5, 0x8DF5, 0x9148, 0x8DFC, 0xE6F0, 0x8DFF, 0xE6F3, 0x8E08, 0xE6F1, 0x8E09, 0xE6F2, + 0x8E0A, 0x9778, 0x8E0F, 0x93A5, 0x8E10, 0xE6F6, 0x8E1D, 0xE6F4, 0x8E1E, 0xE6F5, 0x8E1F, 0xE6F7, 0x8E2A, 0xE748, 0x8E30, 0xE6FA, + 0x8E34, 0xE6FB, 0x8E35, 0xE6F9, 0x8E42, 0xE6F8, 0x8E44, 0x92FB, 0x8E47, 0xE740, 0x8E48, 0xE744, 0x8E49, 0xE741, 0x8E4A, 0xE6FC, + 0x8E4C, 0xE742, 0x8E50, 0xE743, 0x8E55, 0xE74A, 0x8E59, 0xE745, 0x8E5F, 0x90D6, 0x8E60, 0xE747, 0x8E63, 0xE749, 0x8E64, 0xE746, + 0x8E72, 0xE74C, 0x8E74, 0x8F52, 0x8E76, 0xE74B, 0x8E7C, 0xE74D, 0x8E81, 0xE74E, 0x8E84, 0xE751, 0x8E85, 0xE750, 0x8E87, 0xE74F, + 0x8E8A, 0xE753, 0x8E8B, 0xE752, 0x8E8D, 0x96F4, 0x8E91, 0xE755, 0x8E93, 0xE754, 0x8E94, 0xE756, 0x8E99, 0xE757, 0x8EA1, 0xE759, + 0x8EAA, 0xE758, 0x8EAB, 0x9067, 0x8EAC, 0xE75A, 0x8EAF, 0x8BEB, 0x8EB0, 0xE75B, 0x8EB1, 0xE75D, 0x8EBE, 0xE75E, 0x8EC5, 0xE75F, + 0x8EC6, 0xE75C, 0x8EC8, 0xE760, 0x8ECA, 0x8ED4, 0x8ECB, 0xE761, 0x8ECC, 0x8B4F, 0x8ECD, 0x8C52, 0x8ECF, 0xFBB2, 0x8ED2, 0x8CAC, + 0x8EDB, 0xE762, 0x8EDF, 0x93EE, 0x8EE2, 0x935D, 0x8EE3, 0xE763, 0x8EEB, 0xE766, 0x8EF8, 0x8EB2, 0x8EFB, 0xE765, 0x8EFC, 0xE764, + 0x8EFD, 0x8C79, 0x8EFE, 0xE767, 0x8F03, 0x8A72, 0x8F05, 0xE769, 0x8F09, 0x8DDA, 0x8F0A, 0xE768, 0x8F0C, 0xE771, 0x8F12, 0xE76B, + 0x8F13, 0xE76D, 0x8F14, 0x95E3, 0x8F15, 0xE76A, 0x8F19, 0xE76C, 0x8F1B, 0xE770, 0x8F1C, 0xE76E, 0x8F1D, 0x8B50, 0x8F1F, 0xE76F, + 0x8F26, 0xE772, 0x8F29, 0x9479, 0x8F2A, 0x97D6, 0x8F2F, 0x8F53, 0x8F33, 0xE773, 0x8F38, 0x9741, 0x8F39, 0xE775, 0x8F3B, 0xE774, + 0x8F3E, 0xE778, 0x8F3F, 0x9760, 0x8F42, 0xE777, 0x8F44, 0x8A8D, 0x8F45, 0xE776, 0x8F46, 0xE77B, 0x8F49, 0xE77A, 0x8F4C, 0xE779, + 0x8F4D, 0x9351, 0x8F4E, 0xE77C, 0x8F57, 0xE77D, 0x8F5C, 0xE77E, 0x8F5F, 0x8D8C, 0x8F61, 0x8C44, 0x8F62, 0xE780, 0x8F63, 0xE781, + 0x8F64, 0xE782, 0x8F9B, 0x9068, 0x8F9C, 0xE783, 0x8F9E, 0x8EAB, 0x8F9F, 0xE784, 0x8FA3, 0xE785, 0x8FA7, 0x999F, 0x8FA8, 0x999E, + 0x8FAD, 0xE786, 0x8FAE, 0xE390, 0x8FAF, 0xE787, 0x8FB0, 0x9243, 0x8FB1, 0x904A, 0x8FB2, 0x945F, 0x8FB7, 0xE788, 0x8FBA, 0x95D3, + 0x8FBB, 0x92D2, 0x8FBC, 0x8D9E, 0x8FBF, 0x9248, 0x8FC2, 0x8949, 0x8FC4, 0x9698, 0x8FC5, 0x9076, 0x8FCE, 0x8C7D, 0x8FD1, 0x8BDF, + 0x8FD4, 0x95D4, 0x8FDA, 0xE789, 0x8FE2, 0xE78B, 0x8FE5, 0xE78A, 0x8FE6, 0x89DE, 0x8FE9, 0x93F4, 0x8FEA, 0xE78C, 0x8FEB, 0x9497, + 0x8FED, 0x9352, 0x8FEF, 0xE78D, 0x8FF0, 0x8F71, 0x8FF4, 0xE78F, 0x8FF7, 0x96C0, 0x8FF8, 0xE79E, 0x8FF9, 0xE791, 0x8FFA, 0xE792, + 0x8FFD, 0x92C7, 0x9000, 0x91DE, 0x9001, 0x9197, 0x9003, 0x93A6, 0x9005, 0xE790, 0x9006, 0x8B74, 0x900B, 0xE799, 0x900D, 0xE796, + 0x900E, 0xE7A3, 0x900F, 0x93A7, 0x9010, 0x9280, 0x9011, 0xE793, 0x9013, 0x92FC, 0x9014, 0x9372, 0x9015, 0xE794, 0x9016, 0xE798, + 0x9017, 0x9080, 0x9019, 0x9487, 0x901A, 0x92CA, 0x901D, 0x90C0, 0x901E, 0xE797, 0x901F, 0x91AC, 0x9020, 0x91A2, 0x9021, 0xE795, + 0x9022, 0x88A7, 0x9023, 0x9841, 0x9027, 0xE79A, 0x902E, 0x91DF, 0x9031, 0x8F54, 0x9032, 0x9069, 0x9035, 0xE79C, 0x9036, 0xE79B, + 0x9038, 0x88ED, 0x9039, 0xE79D, 0x903C, 0x954E, 0x903E, 0xE7A5, 0x9041, 0x93D9, 0x9042, 0x908B, 0x9045, 0x9278, 0x9047, 0x8BF6, + 0x9049, 0xE7A4, 0x904A, 0x9756, 0x904B, 0x895E, 0x904D, 0x95D5, 0x904E, 0x89DF, 0x904F, 0xE79F, 0x9050, 0xE7A0, 0x9051, 0xE7A1, + 0x9052, 0xE7A2, 0x9053, 0x93B9, 0x9054, 0x9242, 0x9055, 0x88E1, 0x9056, 0xE7A6, 0x9058, 0xE7A7, 0x9059, 0xEAA1, 0x905C, 0x91BB, + 0x905E, 0xE7A8, 0x9060, 0x8993, 0x9061, 0x916B, 0x9063, 0x8CAD, 0x9065, 0x9779, 0x9067, 0xFBB5, 0x9068, 0xE7A9, 0x9069, 0x934B, + 0x906D, 0x9198, 0x906E, 0x8ED5, 0x906F, 0xE7AA, 0x9072, 0xE7AD, 0x9075, 0x8F85, 0x9076, 0xE7AB, 0x9077, 0x914A, 0x9078, 0x9149, + 0x907A, 0x88E2, 0x907C, 0x97C9, 0x907D, 0xE7AF, 0x907F, 0x94F0, 0x9080, 0xE7B1, 0x9081, 0xE7B0, 0x9082, 0xE7AE, 0x9083, 0xE284, + 0x9084, 0x8AD2, 0x9087, 0xE78E, 0x9089, 0xE7B3, 0x908A, 0xE7B2, 0x908F, 0xE7B4, 0x9091, 0x9757, 0x90A3, 0x93DF, 0x90A6, 0x964D, + 0x90A8, 0xE7B5, 0x90AA, 0x8ED7, 0x90AF, 0xE7B6, 0x90B1, 0xE7B7, 0x90B5, 0xE7B8, 0x90B8, 0x9340, 0x90C1, 0x88E8, 0x90CA, 0x8D78, + 0x90CE, 0x9859, 0x90DB, 0xE7BC, 0x90DE, 0xFBB6, 0x90E1, 0x8C53, 0x90E2, 0xE7B9, 0x90E4, 0xE7BA, 0x90E8, 0x9594, 0x90ED, 0x8A73, + 0x90F5, 0x9758, 0x90F7, 0x8BBD, 0x90FD, 0x9373, 0x9102, 0xE7BD, 0x9112, 0xE7BE, 0x9115, 0xFBB8, 0x9119, 0xE7BF, 0x9127, 0xFBB9, + 0x912D, 0x9341, 0x9130, 0xE7C1, 0x9132, 0xE7C0, 0x9149, 0x93D1, 0x914A, 0xE7C2, 0x914B, 0x8F55, 0x914C, 0x8EDE, 0x914D, 0x947A, + 0x914E, 0x9291, 0x9152, 0x8EF0, 0x9154, 0x908C, 0x9156, 0xE7C3, 0x9158, 0xE7C4, 0x9162, 0x907C, 0x9163, 0xE7C5, 0x9165, 0xE7C6, + 0x9169, 0xE7C7, 0x916A, 0x978F, 0x916C, 0x8F56, 0x9172, 0xE7C9, 0x9173, 0xE7C8, 0x9175, 0x8D79, 0x9177, 0x8D93, 0x9178, 0x8E5F, + 0x9182, 0xE7CC, 0x9187, 0x8F86, 0x9189, 0xE7CB, 0x918B, 0xE7CA, 0x918D, 0x91E7, 0x9190, 0x8CED, 0x9192, 0x90C1, 0x9197, 0x94AE, + 0x919C, 0x8F58, 0x91A2, 0xE7CD, 0x91A4, 0x8FDD, 0x91AA, 0xE7D0, 0x91AB, 0xE7CE, 0x91AF, 0xE7CF, 0x91B4, 0xE7D2, 0x91B5, 0xE7D1, + 0x91B8, 0x8FF8, 0x91BA, 0xE7D3, 0x91C0, 0xE7D4, 0x91C1, 0xE7D5, 0x91C6, 0x94CE, 0x91C7, 0x8DD1, 0x91C8, 0x8EDF, 0x91C9, 0xE7D6, + 0x91CB, 0xE7D7, 0x91CC, 0x97A2, 0x91CD, 0x8F64, 0x91CE, 0x96EC, 0x91CF, 0x97CA, 0x91D0, 0xE7D8, 0x91D1, 0x8BE0, 0x91D6, 0xE7D9, + 0x91D7, 0xFBBB, 0x91D8, 0x9342, 0x91DA, 0xFBBA, 0x91DB, 0xE7DC, 0x91DC, 0x8A98, 0x91DD, 0x906A, 0x91DE, 0xFBBC, 0x91DF, 0xE7DA, + 0x91E1, 0xE7DB, 0x91E3, 0x92DE, 0x91E4, 0xFBBF, 0x91E5, 0xFBC0, 0x91E6, 0x9674, 0x91E7, 0x8BFA, 0x91ED, 0xFBBD, 0x91EE, 0xFBBE, + 0x91F5, 0xE7DE, 0x91F6, 0xE7DF, 0x91FC, 0xE7DD, 0x91FF, 0xE7E1, 0x9206, 0xFBC1, 0x920A, 0xFBC3, 0x920D, 0x93DD, 0x920E, 0x8A62, + 0x9210, 0xFBC2, 0x9211, 0xE7E5, 0x9214, 0xE7E2, 0x9215, 0xE7E4, 0x921E, 0xE7E0, 0x9229, 0xE86E, 0x922C, 0xE7E3, 0x9234, 0x97E9, + 0x9237, 0x8CD8, 0x9239, 0xFBCA, 0x923A, 0xFBC4, 0x923C, 0xFBC6, 0x923F, 0xE7ED, 0x9240, 0xFBC5, 0x9244, 0x9353, 0x9245, 0xE7E8, + 0x9248, 0xE7EB, 0x9249, 0xE7E9, 0x924B, 0xE7EE, 0x924E, 0xFBC7, 0x9250, 0xE7EF, 0x9251, 0xFBC9, 0x9257, 0xE7E7, 0x9259, 0xFBC8, + 0x925A, 0xE7F4, 0x925B, 0x8994, 0x925E, 0xE7E6, 0x9262, 0x94AB, 0x9264, 0xE7EA, 0x9266, 0x8FDE, 0x9267, 0xFBCB, 0x9271, 0x8D7A, + 0x9277, 0xFBCD, 0x9278, 0xFBCE, 0x927E, 0x9667, 0x9280, 0x8BE2, 0x9283, 0x8F65, 0x9285, 0x93BA, 0x9288, 0xFA5F, 0x9291, 0x914C, + 0x9293, 0xE7F2, 0x9295, 0xE7EC, 0x9296, 0xE7F1, 0x9298, 0x96C1, 0x929A, 0x92B6, 0x929B, 0xE7F3, 0x929C, 0xE7F0, 0x92A7, 0xFBCC, + 0x92AD, 0x914B, 0x92B7, 0xE7F7, 0x92B9, 0xE7F6, 0x92CF, 0xE7F5, 0x92D0, 0xFBD2, 0x92D2, 0x964E, 0x92D3, 0xFBD6, 0x92D5, 0xFBD4, + 0x92D7, 0xFBD0, 0x92D9, 0xFBD1, 0x92E0, 0xFBD5, 0x92E4, 0x8F9B, 0x92E7, 0xFBCF, 0x92E9, 0xE7F8, 0x92EA, 0x95DD, 0x92ED, 0x8973, + 0x92F2, 0x9565, 0x92F3, 0x9292, 0x92F8, 0x8B98, 0x92F9, 0xFA65, 0x92FA, 0xE7FA, 0x92FB, 0xFBD9, 0x92FC, 0x8D7C, 0x92FF, 0xFBDC, + 0x9302, 0xFBDE, 0x9306, 0x8E4B, 0x930F, 0xE7F9, 0x9310, 0x908D, 0x9318, 0x908E, 0x9319, 0xE840, 0x931A, 0xE842, 0x931D, 0xFBDD, + 0x931E, 0xFBDB, 0x9320, 0x8FF9, 0x9321, 0xFBD8, 0x9322, 0xE841, 0x9323, 0xE843, 0x9325, 0xFBD7, 0x9326, 0x8BD1, 0x9328, 0x9564, + 0x932B, 0x8EE0, 0x932C, 0x9842, 0x932E, 0xE7FC, 0x932F, 0x8DF6, 0x9332, 0x985E, 0x9335, 0xE845, 0x933A, 0xE844, 0x933B, 0xE846, + 0x9344, 0xE7FB, 0x9348, 0xFA5E, 0x934B, 0x93E7, 0x934D, 0x9374, 0x9354, 0x92D5, 0x9356, 0xE84B, 0x9357, 0xFBE0, 0x935B, 0x9262, + 0x935C, 0xE847, 0x9360, 0xE848, 0x936C, 0x8C4C, 0x936E, 0xE84A, 0x9370, 0xFBDF, 0x9375, 0x8CAE, 0x937C, 0xE849, 0x937E, 0x8FDF, + 0x938C, 0x8A99, 0x9394, 0xE84F, 0x9396, 0x8DBD, 0x9397, 0x9199, 0x939A, 0x92C8, 0x93A4, 0xFBE1, 0x93A7, 0x8A5A, 0x93AC, 0xE84D, + 0x93AD, 0xE84E, 0x93AE, 0x92C1, 0x93B0, 0xE84C, 0x93B9, 0xE850, 0x93C3, 0xE856, 0x93C6, 0xFBE2, 0x93C8, 0xE859, 0x93D0, 0xE858, + 0x93D1, 0x934C, 0x93D6, 0xE851, 0x93D7, 0xE852, 0x93D8, 0xE855, 0x93DD, 0xE857, 0x93DE, 0xFBE3, 0x93E1, 0x8BBE, 0x93E4, 0xE85A, + 0x93E5, 0xE854, 0x93E8, 0xE853, 0x93F8, 0xFBE4, 0x9403, 0xE85E, 0x9407, 0xE85F, 0x9410, 0xE860, 0x9413, 0xE85D, 0x9414, 0xE85C, + 0x9418, 0x8FE0, 0x9419, 0x93A8, 0x941A, 0xE85B, 0x9421, 0xE864, 0x942B, 0xE862, 0x9431, 0xFBE5, 0x9435, 0xE863, 0x9436, 0xE861, + 0x9438, 0x91F6, 0x943A, 0xE865, 0x9441, 0xE866, 0x9444, 0xE868, 0x9445, 0xFBE6, 0x9448, 0xFBE7, 0x9451, 0x8AD3, 0x9452, 0xE867, + 0x9453, 0x96F8, 0x945A, 0xE873, 0x945B, 0xE869, 0x945E, 0xE86C, 0x9460, 0xE86A, 0x9462, 0xE86B, 0x946A, 0xE86D, 0x9470, 0xE86F, + 0x9475, 0xE870, 0x9477, 0xE871, 0x947C, 0xE874, 0x947D, 0xE872, 0x947E, 0xE875, 0x947F, 0xE877, 0x9481, 0xE876, 0x9577, 0x92B7, + 0x9580, 0x96E5, 0x9582, 0xE878, 0x9583, 0x914D, 0x9587, 0xE879, 0x9589, 0x95C2, 0x958A, 0xE87A, 0x958B, 0x8A4A, 0x958F, 0x895B, + 0x9591, 0x8AD5, 0x9592, 0xFBE8, 0x9593, 0x8AD4, 0x9594, 0xE87B, 0x9596, 0xE87C, 0x9598, 0xE87D, 0x9599, 0xE87E, 0x95A0, 0xE880, + 0x95A2, 0x8AD6, 0x95A3, 0x8A74, 0x95A4, 0x8D7D, 0x95A5, 0x94B4, 0x95A7, 0xE882, 0x95A8, 0xE881, 0x95AD, 0xE883, 0x95B2, 0x897B, + 0x95B9, 0xE886, 0x95BB, 0xE885, 0x95BC, 0xE884, 0x95BE, 0xE887, 0x95C3, 0xE88A, 0x95C7, 0x88C5, 0x95CA, 0xE888, 0x95CC, 0xE88C, + 0x95CD, 0xE88B, 0x95D4, 0xE88E, 0x95D5, 0xE88D, 0x95D6, 0xE88F, 0x95D8, 0x93AC, 0x95DC, 0xE890, 0x95E1, 0xE891, 0x95E2, 0xE893, + 0x95E5, 0xE892, 0x961C, 0x958C, 0x9621, 0xE894, 0x9628, 0xE895, 0x962A, 0x8DE3, 0x962E, 0xE896, 0x962F, 0xE897, 0x9632, 0x9668, + 0x963B, 0x916A, 0x963F, 0x88A2, 0x9640, 0x91C9, 0x9642, 0xE898, 0x9644, 0x958D, 0x964B, 0xE89B, 0x964C, 0xE899, 0x964D, 0x8D7E, + 0x964F, 0xE89A, 0x9650, 0x8CC0, 0x965B, 0x95C3, 0x965C, 0xE89D, 0x965D, 0xE89F, 0x965E, 0xE89E, 0x965F, 0xE8A0, 0x9662, 0x8940, + 0x9663, 0x9077, 0x9664, 0x8F9C, 0x9665, 0x8AD7, 0x9666, 0xE8A1, 0x966A, 0x9486, 0x966C, 0xE8A3, 0x9670, 0x8941, 0x9672, 0xE8A2, + 0x9673, 0x92C2, 0x9675, 0x97CB, 0x9676, 0x93A9, 0x9677, 0xE89C, 0x9678, 0x97A4, 0x967A, 0x8CAF, 0x967D, 0x977A, 0x9685, 0x8BF7, + 0x9686, 0x97B2, 0x9688, 0x8C47, 0x968A, 0x91E0, 0x968B, 0xE440, 0x968D, 0xE8A4, 0x968E, 0x8A4B, 0x968F, 0x908F, 0x9694, 0x8A75, + 0x9695, 0xE8A6, 0x9697, 0xE8A7, 0x9698, 0xE8A5, 0x9699, 0x8C84, 0x969B, 0x8DDB, 0x969C, 0x8FE1, 0x969D, 0xFBEB, 0x96A0, 0x8942, + 0x96A3, 0x97D7, 0x96A7, 0xE8A9, 0x96A8, 0xE7AC, 0x96AA, 0xE8A8, 0x96AF, 0xFBEC, 0x96B0, 0xE8AC, 0x96B1, 0xE8AA, 0x96B2, 0xE8AB, + 0x96B4, 0xE8AD, 0x96B6, 0xE8AE, 0x96B7, 0x97EA, 0x96B8, 0xE8AF, 0x96B9, 0xE8B0, 0x96BB, 0x90C7, 0x96BC, 0x94B9, 0x96C0, 0x909D, + 0x96C1, 0x8AE5, 0x96C4, 0x9759, 0x96C5, 0x89EB, 0x96C6, 0x8F57, 0x96C7, 0x8CD9, 0x96C9, 0xE8B3, 0x96CB, 0xE8B2, 0x96CC, 0x8E93, + 0x96CD, 0xE8B4, 0x96CE, 0xE8B1, 0x96D1, 0x8E47, 0x96D5, 0xE8B8, 0x96D6, 0xE5AB, 0x96D9, 0x99D4, 0x96DB, 0x9097, 0x96DC, 0xE8B6, + 0x96E2, 0x97A3, 0x96E3, 0x93EF, 0x96E8, 0x894A, 0x96EA, 0x90E1, 0x96EB, 0x8EB4, 0x96F0, 0x95B5, 0x96F2, 0x895F, 0x96F6, 0x97EB, + 0x96F7, 0x978B, 0x96F9, 0xE8B9, 0x96FB, 0x9364, 0x9700, 0x8EF9, 0x9704, 0xE8BA, 0x9706, 0xE8BB, 0x9707, 0x906B, 0x9708, 0xE8BC, + 0x970A, 0x97EC, 0x970D, 0xE8B7, 0x970E, 0xE8BE, 0x970F, 0xE8C0, 0x9711, 0xE8BF, 0x9713, 0xE8BD, 0x9716, 0xE8C1, 0x9719, 0xE8C2, + 0x971C, 0x919A, 0x971E, 0x89E0, 0x9724, 0xE8C3, 0x9727, 0x96B6, 0x972A, 0xE8C4, 0x9730, 0xE8C5, 0x9732, 0x9849, 0x9733, 0xFBED, + 0x9738, 0x9E50, 0x9739, 0xE8C6, 0x973B, 0xFBEE, 0x973D, 0xE8C7, 0x973E, 0xE8C8, 0x9742, 0xE8CC, 0x9743, 0xFBEF, 0x9744, 0xE8C9, + 0x9746, 0xE8CA, 0x9748, 0xE8CB, 0x9749, 0xE8CD, 0x974D, 0xFBF0, 0x974F, 0xFBF1, 0x9751, 0xFBF2, 0x9752, 0x90C2, 0x9755, 0xFBF3, + 0x9756, 0x96F5, 0x9759, 0x90C3, 0x975C, 0xE8CE, 0x975E, 0x94F1, 0x9760, 0xE8CF, 0x9761, 0xEA72, 0x9762, 0x96CA, 0x9764, 0xE8D0, + 0x9766, 0xE8D1, 0x9768, 0xE8D2, 0x9769, 0x8A76, 0x976B, 0xE8D4, 0x976D, 0x9078, 0x9771, 0xE8D5, 0x9774, 0x8C43, 0x9779, 0xE8D6, + 0x977A, 0xE8DA, 0x977C, 0xE8D8, 0x9781, 0xE8D9, 0x9784, 0x8A93, 0x9785, 0xE8D7, 0x9786, 0xE8DB, 0x978B, 0xE8DC, 0x978D, 0x88C6, + 0x978F, 0xE8DD, 0x9790, 0xE8DE, 0x9798, 0x8FE2, 0x979C, 0xE8DF, 0x97A0, 0x8B66, 0x97A3, 0xE8E2, 0x97A6, 0xE8E1, 0x97A8, 0xE8E0, + 0x97AB, 0xE691, 0x97AD, 0x95DA, 0x97B3, 0xE8E3, 0x97B4, 0xE8E4, 0x97C3, 0xE8E5, 0x97C6, 0xE8E6, 0x97C8, 0xE8E7, 0x97CB, 0xE8E8, + 0x97D3, 0x8AD8, 0x97DC, 0xE8E9, 0x97ED, 0xE8EA, 0x97EE, 0x9442, 0x97F2, 0xE8EC, 0x97F3, 0x89B9, 0x97F5, 0xE8EF, 0x97F6, 0xE8EE, + 0x97FB, 0x8943, 0x97FF, 0x8BBF, 0x9801, 0x95C5, 0x9802, 0x92B8, 0x9803, 0x8DA0, 0x9805, 0x8D80, 0x9806, 0x8F87, 0x9808, 0x907B, + 0x980C, 0xE8F1, 0x980F, 0xE8F0, 0x9810, 0x9761, 0x9811, 0x8AE6, 0x9812, 0x94D0, 0x9813, 0x93DA, 0x9817, 0x909C, 0x9818, 0x97CC, + 0x981A, 0x8C7A, 0x9821, 0xE8F4, 0x9824, 0xE8F3, 0x982C, 0x966A, 0x982D, 0x93AA, 0x9834, 0x896F, 0x9837, 0xE8F5, 0x9838, 0xE8F2, + 0x983B, 0x9570, 0x983C, 0x978A, 0x983D, 0xE8F6, 0x9846, 0xE8F7, 0x984B, 0xE8F9, 0x984C, 0x91E8, 0x984D, 0x8A7A, 0x984E, 0x8A7B, + 0x984F, 0xE8F8, 0x9854, 0x8AE7, 0x9855, 0x8CB0, 0x9857, 0xFBF4, 0x9858, 0x8AE8, 0x985B, 0x935E, 0x985E, 0x97DE, 0x9865, 0xFBF5, + 0x9867, 0x8CDA, 0x986B, 0xE8FA, 0x986F, 0xE8FB, 0x9870, 0xE8FC, 0x9871, 0xE940, 0x9873, 0xE942, 0x9874, 0xE941, 0x98A8, 0x9597, + 0x98AA, 0xE943, 0x98AF, 0xE944, 0x98B1, 0xE945, 0x98B6, 0xE946, 0x98C3, 0xE948, 0x98C4, 0xE947, 0x98C6, 0xE949, 0x98DB, 0x94F2, + 0x98DC, 0xE3CA, 0x98DF, 0x9048, 0x98E2, 0x8B51, 0x98E9, 0xE94A, 0x98EB, 0xE94B, 0x98ED, 0x99AA, 0x98EE, 0x9F5A, 0x98EF, 0x94D1, + 0x98F2, 0x88F9, 0x98F4, 0x88B9, 0x98FC, 0x8E94, 0x98FD, 0x964F, 0x98FE, 0x8FFC, 0x9903, 0xE94C, 0x9905, 0x96DD, 0x9909, 0xE94D, + 0x990A, 0x977B, 0x990C, 0x8961, 0x9910, 0x8E60, 0x9912, 0xE94E, 0x9913, 0x89EC, 0x9914, 0xE94F, 0x9918, 0xE950, 0x991D, 0xE952, + 0x991E, 0xE953, 0x9920, 0xE955, 0x9921, 0xE951, 0x9924, 0xE954, 0x9927, 0xFBF8, 0x9928, 0x8AD9, 0x992C, 0xE956, 0x992E, 0xE957, + 0x993D, 0xE958, 0x993E, 0xE959, 0x9942, 0xE95A, 0x9945, 0xE95C, 0x9949, 0xE95B, 0x994B, 0xE95E, 0x994C, 0xE961, 0x9950, 0xE95D, + 0x9951, 0xE95F, 0x9952, 0xE960, 0x9955, 0xE962, 0x9957, 0x8BC0, 0x9996, 0x8EF1, 0x9997, 0xE963, 0x9998, 0xE964, 0x9999, 0x8D81, + 0x999E, 0xFBFA, 0x99A5, 0xE965, 0x99A8, 0x8A5D, 0x99AC, 0x946E, 0x99AD, 0xE966, 0x99AE, 0xE967, 0x99B3, 0x9279, 0x99B4, 0x93E9, + 0x99BC, 0xE968, 0x99C1, 0x949D, 0x99C4, 0x91CA, 0x99C5, 0x8977, 0x99C6, 0x8BEC, 0x99C8, 0x8BED, 0x99D0, 0x9293, 0x99D1, 0xE96D, + 0x99D2, 0x8BEE, 0x99D5, 0x89ED, 0x99D8, 0xE96C, 0x99DB, 0xE96A, 0x99DD, 0xE96B, 0x99DF, 0xE969, 0x99E2, 0xE977, 0x99ED, 0xE96E, + 0x99EE, 0xE96F, 0x99F1, 0xE970, 0x99F2, 0xE971, 0x99F8, 0xE973, 0x99FB, 0xE972, 0x99FF, 0x8F78, 0x9A01, 0xE974, 0x9A05, 0xE976, + 0x9A0E, 0x8B52, 0x9A0F, 0xE975, 0x9A12, 0x919B, 0x9A13, 0x8CB1, 0x9A19, 0xE978, 0x9A28, 0x91CB, 0x9A2B, 0xE979, 0x9A30, 0x93AB, + 0x9A37, 0xE97A, 0x9A3E, 0xE980, 0x9A40, 0xE97D, 0x9A42, 0xE97C, 0x9A43, 0xE97E, 0x9A45, 0xE97B, 0x9A4D, 0xE982, 0x9A4E, 0xFBFB, + 0x9A55, 0xE981, 0x9A57, 0xE984, 0x9A5A, 0x8BC1, 0x9A5B, 0xE983, 0x9A5F, 0xE985, 0x9A62, 0xE986, 0x9A64, 0xE988, 0x9A65, 0xE987, + 0x9A69, 0xE989, 0x9A6A, 0xE98B, 0x9A6B, 0xE98A, 0x9AA8, 0x8D9C, 0x9AAD, 0xE98C, 0x9AB0, 0xE98D, 0x9AB8, 0x8A5B, 0x9ABC, 0xE98E, + 0x9AC0, 0xE98F, 0x9AC4, 0x9091, 0x9ACF, 0xE990, 0x9AD1, 0xE991, 0x9AD3, 0xE992, 0x9AD4, 0xE993, 0x9AD8, 0x8D82, 0x9AD9, 0xFBFC, + 0x9ADC, 0xFC40, 0x9ADE, 0xE994, 0x9ADF, 0xE995, 0x9AE2, 0xE996, 0x9AE3, 0xE997, 0x9AE6, 0xE998, 0x9AEA, 0x94AF, 0x9AEB, 0xE99A, + 0x9AED, 0x9545, 0x9AEE, 0xE99B, 0x9AEF, 0xE999, 0x9AF1, 0xE99D, 0x9AF4, 0xE99C, 0x9AF7, 0xE99E, 0x9AFB, 0xE99F, 0x9B06, 0xE9A0, + 0x9B18, 0xE9A1, 0x9B1A, 0xE9A2, 0x9B1F, 0xE9A3, 0x9B22, 0xE9A4, 0x9B23, 0xE9A5, 0x9B25, 0xE9A6, 0x9B27, 0xE9A7, 0x9B28, 0xE9A8, + 0x9B29, 0xE9A9, 0x9B2A, 0xE9AA, 0x9B2E, 0xE9AB, 0x9B2F, 0xE9AC, 0x9B31, 0x9F54, 0x9B32, 0xE9AD, 0x9B3B, 0xE2F6, 0x9B3C, 0x8B53, + 0x9B41, 0x8A40, 0x9B42, 0x8DB0, 0x9B43, 0xE9AF, 0x9B44, 0xE9AE, 0x9B45, 0x96A3, 0x9B4D, 0xE9B1, 0x9B4E, 0xE9B2, 0x9B4F, 0xE9B0, + 0x9B51, 0xE9B3, 0x9B54, 0x9682, 0x9B58, 0xE9B4, 0x9B5A, 0x8B9B, 0x9B6F, 0x9844, 0x9B72, 0xFC42, 0x9B74, 0xE9B5, 0x9B75, 0xFC41, + 0x9B83, 0xE9B7, 0x9B8E, 0x88BC, 0x9B8F, 0xFC43, 0x9B91, 0xE9B8, 0x9B92, 0x95A9, 0x9B93, 0xE9B6, 0x9B96, 0xE9B9, 0x9B97, 0xE9BA, + 0x9B9F, 0xE9BB, 0x9BA0, 0xE9BC, 0x9BA8, 0xE9BD, 0x9BAA, 0x968E, 0x9BAB, 0x8E4C, 0x9BAD, 0x8DF8, 0x9BAE, 0x914E, 0x9BB1, 0xFC44, + 0x9BB4, 0xE9BE, 0x9BB9, 0xE9C1, 0x9BBB, 0xFC45, 0x9BC0, 0xE9BF, 0x9BC6, 0xE9C2, 0x9BC9, 0x8CEF, 0x9BCA, 0xE9C0, 0x9BCF, 0xE9C3, + 0x9BD1, 0xE9C4, 0x9BD2, 0xE9C5, 0x9BD4, 0xE9C9, 0x9BD6, 0x8E49, 0x9BDB, 0x91E2, 0x9BE1, 0xE9CA, 0x9BE2, 0xE9C7, 0x9BE3, 0xE9C6, + 0x9BE4, 0xE9C8, 0x9BE8, 0x8C7E, 0x9BF0, 0xE9CE, 0x9BF1, 0xE9CD, 0x9BF2, 0xE9CC, 0x9BF5, 0x88B1, 0x9C00, 0xFC46, 0x9C04, 0xE9D8, + 0x9C06, 0xE9D4, 0x9C08, 0xE9D5, 0x9C09, 0xE9D1, 0x9C0A, 0xE9D7, 0x9C0C, 0xE9D3, 0x9C0D, 0x8A82, 0x9C10, 0x986B, 0x9C12, 0xE9D6, + 0x9C13, 0xE9D2, 0x9C14, 0xE9D0, 0x9C15, 0xE9CF, 0x9C1B, 0xE9DA, 0x9C21, 0xE9DD, 0x9C24, 0xE9DC, 0x9C25, 0xE9DB, 0x9C2D, 0x9568, + 0x9C2E, 0xE9D9, 0x9C2F, 0x88F1, 0x9C30, 0xE9DE, 0x9C32, 0xE9E0, 0x9C39, 0x8A8F, 0x9C3A, 0xE9CB, 0x9C3B, 0x8956, 0x9C3E, 0xE9E2, + 0x9C46, 0xE9E1, 0x9C47, 0xE9DF, 0x9C48, 0x924C, 0x9C52, 0x9690, 0x9C57, 0x97D8, 0x9C5A, 0xE9E3, 0x9C60, 0xE9E4, 0x9C67, 0xE9E5, + 0x9C76, 0xE9E6, 0x9C78, 0xE9E7, 0x9CE5, 0x92B9, 0x9CE7, 0xE9E8, 0x9CE9, 0x94B5, 0x9CEB, 0xE9ED, 0x9CEC, 0xE9E9, 0x9CF0, 0xE9EA, + 0x9CF3, 0x9650, 0x9CF4, 0x96C2, 0x9CF6, 0x93CE, 0x9D03, 0xE9EE, 0x9D06, 0xE9EF, 0x9D07, 0x93BC, 0x9D08, 0xE9EC, 0x9D09, 0xE9EB, + 0x9D0E, 0x89A8, 0x9D12, 0xE9F7, 0x9D15, 0xE9F6, 0x9D1B, 0x8995, 0x9D1F, 0xE9F4, 0x9D23, 0xE9F3, 0x9D26, 0xE9F1, 0x9D28, 0x8A9B, + 0x9D2A, 0xE9F0, 0x9D2B, 0x8EB0, 0x9D2C, 0x89A7, 0x9D3B, 0x8D83, 0x9D3E, 0xE9FA, 0x9D3F, 0xE9F9, 0x9D41, 0xE9F8, 0x9D44, 0xE9F5, + 0x9D46, 0xE9FB, 0x9D48, 0xE9FC, 0x9D50, 0xEA44, 0x9D51, 0xEA43, 0x9D59, 0xEA45, 0x9D5C, 0x894C, 0x9D5D, 0xEA40, 0x9D5E, 0xEA41, + 0x9D60, 0x8D94, 0x9D61, 0x96B7, 0x9D64, 0xEA42, 0x9D6B, 0xFC48, 0x9D6C, 0x9651, 0x9D6F, 0xEA4A, 0x9D70, 0xFC47, 0x9D72, 0xEA46, + 0x9D7A, 0xEA4B, 0x9D87, 0xEA48, 0x9D89, 0xEA47, 0x9D8F, 0x8C7B, 0x9D9A, 0xEA4C, 0x9DA4, 0xEA4D, 0x9DA9, 0xEA4E, 0x9DAB, 0xEA49, + 0x9DAF, 0xE9F2, 0x9DB2, 0xEA4F, 0x9DB4, 0x92DF, 0x9DB8, 0xEA53, 0x9DBA, 0xEA54, 0x9DBB, 0xEA52, 0x9DC1, 0xEA51, 0x9DC2, 0xEA57, + 0x9DC4, 0xEA50, 0x9DC6, 0xEA55, 0x9DCF, 0xEA56, 0x9DD3, 0xEA59, 0x9DD9, 0xEA58, 0x9DE6, 0xEA5B, 0x9DED, 0xEA5C, 0x9DEF, 0xEA5D, + 0x9DF2, 0x9868, 0x9DF8, 0xEA5A, 0x9DF9, 0x91E9, 0x9DFA, 0x8DEB, 0x9DFD, 0xEA5E, 0x9E19, 0xFC4A, 0x9E1A, 0xEA5F, 0x9E1B, 0xEA60, + 0x9E1E, 0xEA61, 0x9E75, 0xEA62, 0x9E78, 0x8CB2, 0x9E79, 0xEA63, 0x9E7D, 0xEA64, 0x9E7F, 0x8EAD, 0x9E81, 0xEA65, 0x9E88, 0xEA66, + 0x9E8B, 0xEA67, 0x9E8C, 0xEA68, 0x9E91, 0xEA6B, 0x9E92, 0xEA69, 0x9E93, 0x985B, 0x9E95, 0xEA6A, 0x9E97, 0x97ED, 0x9E9D, 0xEA6C, + 0x9E9F, 0x97D9, 0x9EA5, 0xEA6D, 0x9EA6, 0x949E, 0x9EA9, 0xEA6E, 0x9EAA, 0xEA70, 0x9EAD, 0xEA71, 0x9EB8, 0xEA6F, 0x9EB9, 0x8D8D, + 0x9EBA, 0x96CB, 0x9EBB, 0x9683, 0x9EBC, 0x9BF5, 0x9EBE, 0x9F80, 0x9EBF, 0x969B, 0x9EC4, 0x89A9, 0x9ECC, 0xEA73, 0x9ECD, 0x8B6F, + 0x9ECE, 0xEA74, 0x9ECF, 0xEA75, 0x9ED0, 0xEA76, 0x9ED1, 0xFC4B, 0x9ED2, 0x8D95, 0x9ED4, 0xEA77, 0x9ED8, 0xE0D2, 0x9ED9, 0x96D9, + 0x9EDB, 0x91E1, 0x9EDC, 0xEA78, 0x9EDD, 0xEA7A, 0x9EDE, 0xEA79, 0x9EE0, 0xEA7B, 0x9EE5, 0xEA7C, 0x9EE8, 0xEA7D, 0x9EEF, 0xEA7E, + 0x9EF4, 0xEA80, 0x9EF6, 0xEA81, 0x9EF7, 0xEA82, 0x9EF9, 0xEA83, 0x9EFB, 0xEA84, 0x9EFC, 0xEA85, 0x9EFD, 0xEA86, 0x9F07, 0xEA87, + 0x9F08, 0xEA88, 0x9F0E, 0x9343, 0x9F13, 0x8CDB, 0x9F15, 0xEA8A, 0x9F20, 0x916C, 0x9F21, 0xEA8B, 0x9F2C, 0xEA8C, 0x9F3B, 0x9540, + 0x9F3E, 0xEA8D, 0x9F4A, 0xEA8E, 0x9F4B, 0xE256, 0x9F4E, 0xE6D8, 0x9F4F, 0xE8EB, 0x9F52, 0xEA8F, 0x9F54, 0xEA90, 0x9F5F, 0xEA92, + 0x9F60, 0xEA93, 0x9F61, 0xEA94, 0x9F62, 0x97EE, 0x9F63, 0xEA91, 0x9F66, 0xEA95, 0x9F67, 0xEA96, 0x9F6A, 0xEA98, 0x9F6C, 0xEA97, + 0x9F72, 0xEA9A, 0x9F76, 0xEA9B, 0x9F77, 0xEA99, 0x9F8D, 0x97B4, 0x9F95, 0xEA9C, 0x9F9C, 0xEA9D, 0x9F9D, 0xE273, 0x9FA0, 0xEA9E, + 0xF929, 0xFAE0, 0xF9DC, 0xFBE9, 0xFA0E, 0xFA90, 0xFA0F, 0xFA9B, 0xFA10, 0xFA9C, 0xFA11, 0xFAB1, 0xFA12, 0xFAD8, 0xFA13, 0xFAE8, + 0xFA14, 0xFAEA, 0xFA15, 0xFB58, 0xFA16, 0xFB5E, 0xFA17, 0xFB75, 0xFA18, 0xFB7D, 0xFA19, 0xFB7E, 0xFA1A, 0xFB80, 0xFA1B, 0xFB82, + 0xFA1C, 0xFB86, 0xFA1D, 0xFB89, 0xFA1E, 0xFB92, 0xFA1F, 0xFB9D, 0xFA20, 0xFB9F, 0xFA21, 0xFBA0, 0xFA22, 0xFBA9, 0xFA23, 0xFBB1, + 0xFA24, 0xFBB3, 0xFA25, 0xFBB4, 0xFA26, 0xFBB7, 0xFA27, 0xFBD3, 0xFA28, 0xFBDA, 0xFA29, 0xFBEA, 0xFA2A, 0xFBF6, 0xFA2B, 0xFBF7, + 0xFA2C, 0xFBF9, 0xFA2D, 0xFC49, 0xFF01, 0x8149, 0xFF02, 0xFA57, 0xFF03, 0x8194, 0xFF04, 0x8190, 0xFF05, 0x8193, 0xFF06, 0x8195, + 0xFF07, 0xFA56, 0xFF08, 0x8169, 0xFF09, 0x816A, 0xFF0A, 0x8196, 0xFF0B, 0x817B, 0xFF0C, 0x8143, 0xFF0D, 0x817C, 0xFF0E, 0x8144, + 0xFF0F, 0x815E, 0xFF10, 0x824F, 0xFF11, 0x8250, 0xFF12, 0x8251, 0xFF13, 0x8252, 0xFF14, 0x8253, 0xFF15, 0x8254, 0xFF16, 0x8255, + 0xFF17, 0x8256, 0xFF18, 0x8257, 0xFF19, 0x8258, 0xFF1A, 0x8146, 0xFF1B, 0x8147, 0xFF1C, 0x8183, 0xFF1D, 0x8181, 0xFF1E, 0x8184, + 0xFF1F, 0x8148, 0xFF20, 0x8197, 0xFF21, 0x8260, 0xFF22, 0x8261, 0xFF23, 0x8262, 0xFF24, 0x8263, 0xFF25, 0x8264, 0xFF26, 0x8265, + 0xFF27, 0x8266, 0xFF28, 0x8267, 0xFF29, 0x8268, 0xFF2A, 0x8269, 0xFF2B, 0x826A, 0xFF2C, 0x826B, 0xFF2D, 0x826C, 0xFF2E, 0x826D, + 0xFF2F, 0x826E, 0xFF30, 0x826F, 0xFF31, 0x8270, 0xFF32, 0x8271, 0xFF33, 0x8272, 0xFF34, 0x8273, 0xFF35, 0x8274, 0xFF36, 0x8275, + 0xFF37, 0x8276, 0xFF38, 0x8277, 0xFF39, 0x8278, 0xFF3A, 0x8279, 0xFF3B, 0x816D, 0xFF3C, 0x815F, 0xFF3D, 0x816E, 0xFF3E, 0x814F, + 0xFF3F, 0x8151, 0xFF40, 0x814D, 0xFF41, 0x8281, 0xFF42, 0x8282, 0xFF43, 0x8283, 0xFF44, 0x8284, 0xFF45, 0x8285, 0xFF46, 0x8286, + 0xFF47, 0x8287, 0xFF48, 0x8288, 0xFF49, 0x8289, 0xFF4A, 0x828A, 0xFF4B, 0x828B, 0xFF4C, 0x828C, 0xFF4D, 0x828D, 0xFF4E, 0x828E, + 0xFF4F, 0x828F, 0xFF50, 0x8290, 0xFF51, 0x8291, 0xFF52, 0x8292, 0xFF53, 0x8293, 0xFF54, 0x8294, 0xFF55, 0x8295, 0xFF56, 0x8296, + 0xFF57, 0x8297, 0xFF58, 0x8298, 0xFF59, 0x8299, 0xFF5A, 0x829A, 0xFF5B, 0x816F, 0xFF5C, 0x8162, 0xFF5D, 0x8170, 0xFF5E, 0x8160, + 0xFF61, 0x00A1, 0xFF62, 0x00A2, 0xFF63, 0x00A3, 0xFF64, 0x00A4, 0xFF65, 0x00A5, 0xFF66, 0x00A6, 0xFF67, 0x00A7, 0xFF68, 0x00A8, + 0xFF69, 0x00A9, 0xFF6A, 0x00AA, 0xFF6B, 0x00AB, 0xFF6C, 0x00AC, 0xFF6D, 0x00AD, 0xFF6E, 0x00AE, 0xFF6F, 0x00AF, 0xFF70, 0x00B0, + 0xFF71, 0x00B1, 0xFF72, 0x00B2, 0xFF73, 0x00B3, 0xFF74, 0x00B4, 0xFF75, 0x00B5, 0xFF76, 0x00B6, 0xFF77, 0x00B7, 0xFF78, 0x00B8, + 0xFF79, 0x00B9, 0xFF7A, 0x00BA, 0xFF7B, 0x00BB, 0xFF7C, 0x00BC, 0xFF7D, 0x00BD, 0xFF7E, 0x00BE, 0xFF7F, 0x00BF, 0xFF80, 0x00C0, + 0xFF81, 0x00C1, 0xFF82, 0x00C2, 0xFF83, 0x00C3, 0xFF84, 0x00C4, 0xFF85, 0x00C5, 0xFF86, 0x00C6, 0xFF87, 0x00C7, 0xFF88, 0x00C8, + 0xFF89, 0x00C9, 0xFF8A, 0x00CA, 0xFF8B, 0x00CB, 0xFF8C, 0x00CC, 0xFF8D, 0x00CD, 0xFF8E, 0x00CE, 0xFF8F, 0x00CF, 0xFF90, 0x00D0, + 0xFF91, 0x00D1, 0xFF92, 0x00D2, 0xFF93, 0x00D3, 0xFF94, 0x00D4, 0xFF95, 0x00D5, 0xFF96, 0x00D6, 0xFF97, 0x00D7, 0xFF98, 0x00D8, + 0xFF99, 0x00D9, 0xFF9A, 0x00DA, 0xFF9B, 0x00DB, 0xFF9C, 0x00DC, 0xFF9D, 0x00DD, 0xFF9E, 0x00DE, 0xFF9F, 0x00DF, 0xFFE0, 0x8191, + 0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0 +}; + +static const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */ + 0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68, + 0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70, + 0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78, + 0x00B9, 0xFF79, 0x00BA, 0xFF7A, 0x00BB, 0xFF7B, 0x00BC, 0xFF7C, 0x00BD, 0xFF7D, 0x00BE, 0xFF7E, 0x00BF, 0xFF7F, 0x00C0, 0xFF80, + 0x00C1, 0xFF81, 0x00C2, 0xFF82, 0x00C3, 0xFF83, 0x00C4, 0xFF84, 0x00C5, 0xFF85, 0x00C6, 0xFF86, 0x00C7, 0xFF87, 0x00C8, 0xFF88, + 0x00C9, 0xFF89, 0x00CA, 0xFF8A, 0x00CB, 0xFF8B, 0x00CC, 0xFF8C, 0x00CD, 0xFF8D, 0x00CE, 0xFF8E, 0x00CF, 0xFF8F, 0x00D0, 0xFF90, + 0x00D1, 0xFF91, 0x00D2, 0xFF92, 0x00D3, 0xFF93, 0x00D4, 0xFF94, 0x00D5, 0xFF95, 0x00D6, 0xFF96, 0x00D7, 0xFF97, 0x00D8, 0xFF98, + 0x00D9, 0xFF99, 0x00DA, 0xFF9A, 0x00DB, 0xFF9B, 0x00DC, 0xFF9C, 0x00DD, 0xFF9D, 0x00DE, 0xFF9E, 0x00DF, 0xFF9F, 0x8140, 0x3000, + 0x8141, 0x3001, 0x8142, 0x3002, 0x8143, 0xFF0C, 0x8144, 0xFF0E, 0x8145, 0x30FB, 0x8146, 0xFF1A, 0x8147, 0xFF1B, 0x8148, 0xFF1F, + 0x8149, 0xFF01, 0x814A, 0x309B, 0x814B, 0x309C, 0x814C, 0x00B4, 0x814D, 0xFF40, 0x814E, 0x00A8, 0x814F, 0xFF3E, 0x8150, 0xFFE3, + 0x8151, 0xFF3F, 0x8152, 0x30FD, 0x8153, 0x30FE, 0x8154, 0x309D, 0x8155, 0x309E, 0x8156, 0x3003, 0x8157, 0x4EDD, 0x8158, 0x3005, + 0x8159, 0x3006, 0x815A, 0x3007, 0x815B, 0x30FC, 0x815C, 0x2015, 0x815D, 0x2010, 0x815E, 0xFF0F, 0x815F, 0xFF3C, 0x8160, 0xFF5E, + 0x8161, 0x2225, 0x8162, 0xFF5C, 0x8163, 0x2026, 0x8164, 0x2025, 0x8165, 0x2018, 0x8166, 0x2019, 0x8167, 0x201C, 0x8168, 0x201D, + 0x8169, 0xFF08, 0x816A, 0xFF09, 0x816B, 0x3014, 0x816C, 0x3015, 0x816D, 0xFF3B, 0x816E, 0xFF3D, 0x816F, 0xFF5B, 0x8170, 0xFF5D, + 0x8171, 0x3008, 0x8172, 0x3009, 0x8173, 0x300A, 0x8174, 0x300B, 0x8175, 0x300C, 0x8176, 0x300D, 0x8177, 0x300E, 0x8178, 0x300F, + 0x8179, 0x3010, 0x817A, 0x3011, 0x817B, 0xFF0B, 0x817C, 0xFF0D, 0x817D, 0x00B1, 0x817E, 0x00D7, 0x8180, 0x00F7, 0x8181, 0xFF1D, + 0x8182, 0x2260, 0x8183, 0xFF1C, 0x8184, 0xFF1E, 0x8185, 0x2266, 0x8186, 0x2267, 0x8187, 0x221E, 0x8188, 0x2234, 0x8189, 0x2642, + 0x818A, 0x2640, 0x818B, 0x00B0, 0x818C, 0x2032, 0x818D, 0x2033, 0x818E, 0x2103, 0x818F, 0xFFE5, 0x8190, 0xFF04, 0x8191, 0xFFE0, + 0x8192, 0xFFE1, 0x8193, 0xFF05, 0x8194, 0xFF03, 0x8195, 0xFF06, 0x8196, 0xFF0A, 0x8197, 0xFF20, 0x8198, 0x00A7, 0x8199, 0x2606, + 0x819A, 0x2605, 0x819B, 0x25CB, 0x819C, 0x25CF, 0x819D, 0x25CE, 0x819E, 0x25C7, 0x819F, 0x25C6, 0x81A0, 0x25A1, 0x81A1, 0x25A0, + 0x81A2, 0x25B3, 0x81A3, 0x25B2, 0x81A4, 0x25BD, 0x81A5, 0x25BC, 0x81A6, 0x203B, 0x81A7, 0x3012, 0x81A8, 0x2192, 0x81A9, 0x2190, + 0x81AA, 0x2191, 0x81AB, 0x2193, 0x81AC, 0x3013, 0x81B8, 0x2208, 0x81B9, 0x220B, 0x81BA, 0x2286, 0x81BB, 0x2287, 0x81BC, 0x2282, + 0x81BD, 0x2283, 0x81BE, 0x222A, 0x81BF, 0x2229, 0x81C8, 0x2227, 0x81C9, 0x2228, 0x81CA, 0xFFE2, 0x81CB, 0x21D2, 0x81CC, 0x21D4, + 0x81CD, 0x2200, 0x81CE, 0x2203, 0x81DA, 0x2220, 0x81DB, 0x22A5, 0x81DC, 0x2312, 0x81DD, 0x2202, 0x81DE, 0x2207, 0x81DF, 0x2261, + 0x81E0, 0x2252, 0x81E1, 0x226A, 0x81E2, 0x226B, 0x81E3, 0x221A, 0x81E4, 0x223D, 0x81E5, 0x221D, 0x81E6, 0x2235, 0x81E7, 0x222B, + 0x81E8, 0x222C, 0x81F0, 0x212B, 0x81F1, 0x2030, 0x81F2, 0x266F, 0x81F3, 0x266D, 0x81F4, 0x266A, 0x81F5, 0x2020, 0x81F6, 0x2021, + 0x81F7, 0x00B6, 0x81FC, 0x25EF, 0x824F, 0xFF10, 0x8250, 0xFF11, 0x8251, 0xFF12, 0x8252, 0xFF13, 0x8253, 0xFF14, 0x8254, 0xFF15, + 0x8255, 0xFF16, 0x8256, 0xFF17, 0x8257, 0xFF18, 0x8258, 0xFF19, 0x8260, 0xFF21, 0x8261, 0xFF22, 0x8262, 0xFF23, 0x8263, 0xFF24, + 0x8264, 0xFF25, 0x8265, 0xFF26, 0x8266, 0xFF27, 0x8267, 0xFF28, 0x8268, 0xFF29, 0x8269, 0xFF2A, 0x826A, 0xFF2B, 0x826B, 0xFF2C, + 0x826C, 0xFF2D, 0x826D, 0xFF2E, 0x826E, 0xFF2F, 0x826F, 0xFF30, 0x8270, 0xFF31, 0x8271, 0xFF32, 0x8272, 0xFF33, 0x8273, 0xFF34, + 0x8274, 0xFF35, 0x8275, 0xFF36, 0x8276, 0xFF37, 0x8277, 0xFF38, 0x8278, 0xFF39, 0x8279, 0xFF3A, 0x8281, 0xFF41, 0x8282, 0xFF42, + 0x8283, 0xFF43, 0x8284, 0xFF44, 0x8285, 0xFF45, 0x8286, 0xFF46, 0x8287, 0xFF47, 0x8288, 0xFF48, 0x8289, 0xFF49, 0x828A, 0xFF4A, + 0x828B, 0xFF4B, 0x828C, 0xFF4C, 0x828D, 0xFF4D, 0x828E, 0xFF4E, 0x828F, 0xFF4F, 0x8290, 0xFF50, 0x8291, 0xFF51, 0x8292, 0xFF52, + 0x8293, 0xFF53, 0x8294, 0xFF54, 0x8295, 0xFF55, 0x8296, 0xFF56, 0x8297, 0xFF57, 0x8298, 0xFF58, 0x8299, 0xFF59, 0x829A, 0xFF5A, + 0x829F, 0x3041, 0x82A0, 0x3042, 0x82A1, 0x3043, 0x82A2, 0x3044, 0x82A3, 0x3045, 0x82A4, 0x3046, 0x82A5, 0x3047, 0x82A6, 0x3048, + 0x82A7, 0x3049, 0x82A8, 0x304A, 0x82A9, 0x304B, 0x82AA, 0x304C, 0x82AB, 0x304D, 0x82AC, 0x304E, 0x82AD, 0x304F, 0x82AE, 0x3050, + 0x82AF, 0x3051, 0x82B0, 0x3052, 0x82B1, 0x3053, 0x82B2, 0x3054, 0x82B3, 0x3055, 0x82B4, 0x3056, 0x82B5, 0x3057, 0x82B6, 0x3058, + 0x82B7, 0x3059, 0x82B8, 0x305A, 0x82B9, 0x305B, 0x82BA, 0x305C, 0x82BB, 0x305D, 0x82BC, 0x305E, 0x82BD, 0x305F, 0x82BE, 0x3060, + 0x82BF, 0x3061, 0x82C0, 0x3062, 0x82C1, 0x3063, 0x82C2, 0x3064, 0x82C3, 0x3065, 0x82C4, 0x3066, 0x82C5, 0x3067, 0x82C6, 0x3068, + 0x82C7, 0x3069, 0x82C8, 0x306A, 0x82C9, 0x306B, 0x82CA, 0x306C, 0x82CB, 0x306D, 0x82CC, 0x306E, 0x82CD, 0x306F, 0x82CE, 0x3070, + 0x82CF, 0x3071, 0x82D0, 0x3072, 0x82D1, 0x3073, 0x82D2, 0x3074, 0x82D3, 0x3075, 0x82D4, 0x3076, 0x82D5, 0x3077, 0x82D6, 0x3078, + 0x82D7, 0x3079, 0x82D8, 0x307A, 0x82D9, 0x307B, 0x82DA, 0x307C, 0x82DB, 0x307D, 0x82DC, 0x307E, 0x82DD, 0x307F, 0x82DE, 0x3080, + 0x82DF, 0x3081, 0x82E0, 0x3082, 0x82E1, 0x3083, 0x82E2, 0x3084, 0x82E3, 0x3085, 0x82E4, 0x3086, 0x82E5, 0x3087, 0x82E6, 0x3088, + 0x82E7, 0x3089, 0x82E8, 0x308A, 0x82E9, 0x308B, 0x82EA, 0x308C, 0x82EB, 0x308D, 0x82EC, 0x308E, 0x82ED, 0x308F, 0x82EE, 0x3090, + 0x82EF, 0x3091, 0x82F0, 0x3092, 0x82F1, 0x3093, 0x8340, 0x30A1, 0x8341, 0x30A2, 0x8342, 0x30A3, 0x8343, 0x30A4, 0x8344, 0x30A5, + 0x8345, 0x30A6, 0x8346, 0x30A7, 0x8347, 0x30A8, 0x8348, 0x30A9, 0x8349, 0x30AA, 0x834A, 0x30AB, 0x834B, 0x30AC, 0x834C, 0x30AD, + 0x834D, 0x30AE, 0x834E, 0x30AF, 0x834F, 0x30B0, 0x8350, 0x30B1, 0x8351, 0x30B2, 0x8352, 0x30B3, 0x8353, 0x30B4, 0x8354, 0x30B5, + 0x8355, 0x30B6, 0x8356, 0x30B7, 0x8357, 0x30B8, 0x8358, 0x30B9, 0x8359, 0x30BA, 0x835A, 0x30BB, 0x835B, 0x30BC, 0x835C, 0x30BD, + 0x835D, 0x30BE, 0x835E, 0x30BF, 0x835F, 0x30C0, 0x8360, 0x30C1, 0x8361, 0x30C2, 0x8362, 0x30C3, 0x8363, 0x30C4, 0x8364, 0x30C5, + 0x8365, 0x30C6, 0x8366, 0x30C7, 0x8367, 0x30C8, 0x8368, 0x30C9, 0x8369, 0x30CA, 0x836A, 0x30CB, 0x836B, 0x30CC, 0x836C, 0x30CD, + 0x836D, 0x30CE, 0x836E, 0x30CF, 0x836F, 0x30D0, 0x8370, 0x30D1, 0x8371, 0x30D2, 0x8372, 0x30D3, 0x8373, 0x30D4, 0x8374, 0x30D5, + 0x8375, 0x30D6, 0x8376, 0x30D7, 0x8377, 0x30D8, 0x8378, 0x30D9, 0x8379, 0x30DA, 0x837A, 0x30DB, 0x837B, 0x30DC, 0x837C, 0x30DD, + 0x837D, 0x30DE, 0x837E, 0x30DF, 0x8380, 0x30E0, 0x8381, 0x30E1, 0x8382, 0x30E2, 0x8383, 0x30E3, 0x8384, 0x30E4, 0x8385, 0x30E5, + 0x8386, 0x30E6, 0x8387, 0x30E7, 0x8388, 0x30E8, 0x8389, 0x30E9, 0x838A, 0x30EA, 0x838B, 0x30EB, 0x838C, 0x30EC, 0x838D, 0x30ED, + 0x838E, 0x30EE, 0x838F, 0x30EF, 0x8390, 0x30F0, 0x8391, 0x30F1, 0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x30F4, 0x8395, 0x30F5, + 0x8396, 0x30F6, 0x839F, 0x0391, 0x83A0, 0x0392, 0x83A1, 0x0393, 0x83A2, 0x0394, 0x83A3, 0x0395, 0x83A4, 0x0396, 0x83A5, 0x0397, + 0x83A6, 0x0398, 0x83A7, 0x0399, 0x83A8, 0x039A, 0x83A9, 0x039B, 0x83AA, 0x039C, 0x83AB, 0x039D, 0x83AC, 0x039E, 0x83AD, 0x039F, + 0x83AE, 0x03A0, 0x83AF, 0x03A1, 0x83B0, 0x03A3, 0x83B1, 0x03A4, 0x83B2, 0x03A5, 0x83B3, 0x03A6, 0x83B4, 0x03A7, 0x83B5, 0x03A8, + 0x83B6, 0x03A9, 0x83BF, 0x03B1, 0x83C0, 0x03B2, 0x83C1, 0x03B3, 0x83C2, 0x03B4, 0x83C3, 0x03B5, 0x83C4, 0x03B6, 0x83C5, 0x03B7, + 0x83C6, 0x03B8, 0x83C7, 0x03B9, 0x83C8, 0x03BA, 0x83C9, 0x03BB, 0x83CA, 0x03BC, 0x83CB, 0x03BD, 0x83CC, 0x03BE, 0x83CD, 0x03BF, + 0x83CE, 0x03C0, 0x83CF, 0x03C1, 0x83D0, 0x03C3, 0x83D1, 0x03C4, 0x83D2, 0x03C5, 0x83D3, 0x03C6, 0x83D4, 0x03C7, 0x83D5, 0x03C8, + 0x83D6, 0x03C9, 0x8440, 0x0410, 0x8441, 0x0411, 0x8442, 0x0412, 0x8443, 0x0413, 0x8444, 0x0414, 0x8445, 0x0415, 0x8446, 0x0401, + 0x8447, 0x0416, 0x8448, 0x0417, 0x8449, 0x0418, 0x844A, 0x0419, 0x844B, 0x041A, 0x844C, 0x041B, 0x844D, 0x041C, 0x844E, 0x041D, + 0x844F, 0x041E, 0x8450, 0x041F, 0x8451, 0x0420, 0x8452, 0x0421, 0x8453, 0x0422, 0x8454, 0x0423, 0x8455, 0x0424, 0x8456, 0x0425, + 0x8457, 0x0426, 0x8458, 0x0427, 0x8459, 0x0428, 0x845A, 0x0429, 0x845B, 0x042A, 0x845C, 0x042B, 0x845D, 0x042C, 0x845E, 0x042D, + 0x845F, 0x042E, 0x8460, 0x042F, 0x8470, 0x0430, 0x8471, 0x0431, 0x8472, 0x0432, 0x8473, 0x0433, 0x8474, 0x0434, 0x8475, 0x0435, + 0x8476, 0x0451, 0x8477, 0x0436, 0x8478, 0x0437, 0x8479, 0x0438, 0x847A, 0x0439, 0x847B, 0x043A, 0x847C, 0x043B, 0x847D, 0x043C, + 0x847E, 0x043D, 0x8480, 0x043E, 0x8481, 0x043F, 0x8482, 0x0440, 0x8483, 0x0441, 0x8484, 0x0442, 0x8485, 0x0443, 0x8486, 0x0444, + 0x8487, 0x0445, 0x8488, 0x0446, 0x8489, 0x0447, 0x848A, 0x0448, 0x848B, 0x0449, 0x848C, 0x044A, 0x848D, 0x044B, 0x848E, 0x044C, + 0x848F, 0x044D, 0x8490, 0x044E, 0x8491, 0x044F, 0x849F, 0x2500, 0x84A0, 0x2502, 0x84A1, 0x250C, 0x84A2, 0x2510, 0x84A3, 0x2518, + 0x84A4, 0x2514, 0x84A5, 0x251C, 0x84A6, 0x252C, 0x84A7, 0x2524, 0x84A8, 0x2534, 0x84A9, 0x253C, 0x84AA, 0x2501, 0x84AB, 0x2503, + 0x84AC, 0x250F, 0x84AD, 0x2513, 0x84AE, 0x251B, 0x84AF, 0x2517, 0x84B0, 0x2523, 0x84B1, 0x2533, 0x84B2, 0x252B, 0x84B3, 0x253B, + 0x84B4, 0x254B, 0x84B5, 0x2520, 0x84B6, 0x252F, 0x84B7, 0x2528, 0x84B8, 0x2537, 0x84B9, 0x253F, 0x84BA, 0x251D, 0x84BB, 0x2530, + 0x84BC, 0x2525, 0x84BD, 0x2538, 0x84BE, 0x2542, 0x8740, 0x2460, 0x8741, 0x2461, 0x8742, 0x2462, 0x8743, 0x2463, 0x8744, 0x2464, + 0x8745, 0x2465, 0x8746, 0x2466, 0x8747, 0x2467, 0x8748, 0x2468, 0x8749, 0x2469, 0x874A, 0x246A, 0x874B, 0x246B, 0x874C, 0x246C, + 0x874D, 0x246D, 0x874E, 0x246E, 0x874F, 0x246F, 0x8750, 0x2470, 0x8751, 0x2471, 0x8752, 0x2472, 0x8753, 0x2473, 0x8754, 0x2160, + 0x8755, 0x2161, 0x8756, 0x2162, 0x8757, 0x2163, 0x8758, 0x2164, 0x8759, 0x2165, 0x875A, 0x2166, 0x875B, 0x2167, 0x875C, 0x2168, + 0x875D, 0x2169, 0x875F, 0x3349, 0x8760, 0x3314, 0x8761, 0x3322, 0x8762, 0x334D, 0x8763, 0x3318, 0x8764, 0x3327, 0x8765, 0x3303, + 0x8766, 0x3336, 0x8767, 0x3351, 0x8768, 0x3357, 0x8769, 0x330D, 0x876A, 0x3326, 0x876B, 0x3323, 0x876C, 0x332B, 0x876D, 0x334A, + 0x876E, 0x333B, 0x876F, 0x339C, 0x8770, 0x339D, 0x8771, 0x339E, 0x8772, 0x338E, 0x8773, 0x338F, 0x8774, 0x33C4, 0x8775, 0x33A1, + 0x877E, 0x337B, 0x8780, 0x301D, 0x8781, 0x301F, 0x8782, 0x2116, 0x8783, 0x33CD, 0x8784, 0x2121, 0x8785, 0x32A4, 0x8786, 0x32A5, + 0x8787, 0x32A6, 0x8788, 0x32A7, 0x8789, 0x32A8, 0x878A, 0x3231, 0x878B, 0x3232, 0x878C, 0x3239, 0x878D, 0x337E, 0x878E, 0x337D, + 0x878F, 0x337C, 0x8793, 0x222E, 0x8794, 0x2211, 0x8798, 0x221F, 0x8799, 0x22BF, 0x889F, 0x4E9C, 0x88A0, 0x5516, 0x88A1, 0x5A03, + 0x88A2, 0x963F, 0x88A3, 0x54C0, 0x88A4, 0x611B, 0x88A5, 0x6328, 0x88A6, 0x59F6, 0x88A7, 0x9022, 0x88A8, 0x8475, 0x88A9, 0x831C, + 0x88AA, 0x7A50, 0x88AB, 0x60AA, 0x88AC, 0x63E1, 0x88AD, 0x6E25, 0x88AE, 0x65ED, 0x88AF, 0x8466, 0x88B0, 0x82A6, 0x88B1, 0x9BF5, + 0x88B2, 0x6893, 0x88B3, 0x5727, 0x88B4, 0x65A1, 0x88B5, 0x6271, 0x88B6, 0x5B9B, 0x88B7, 0x59D0, 0x88B8, 0x867B, 0x88B9, 0x98F4, + 0x88BA, 0x7D62, 0x88BB, 0x7DBE, 0x88BC, 0x9B8E, 0x88BD, 0x6216, 0x88BE, 0x7C9F, 0x88BF, 0x88B7, 0x88C0, 0x5B89, 0x88C1, 0x5EB5, + 0x88C2, 0x6309, 0x88C3, 0x6697, 0x88C4, 0x6848, 0x88C5, 0x95C7, 0x88C6, 0x978D, 0x88C7, 0x674F, 0x88C8, 0x4EE5, 0x88C9, 0x4F0A, + 0x88CA, 0x4F4D, 0x88CB, 0x4F9D, 0x88CC, 0x5049, 0x88CD, 0x56F2, 0x88CE, 0x5937, 0x88CF, 0x59D4, 0x88D0, 0x5A01, 0x88D1, 0x5C09, + 0x88D2, 0x60DF, 0x88D3, 0x610F, 0x88D4, 0x6170, 0x88D5, 0x6613, 0x88D6, 0x6905, 0x88D7, 0x70BA, 0x88D8, 0x754F, 0x88D9, 0x7570, + 0x88DA, 0x79FB, 0x88DB, 0x7DAD, 0x88DC, 0x7DEF, 0x88DD, 0x80C3, 0x88DE, 0x840E, 0x88DF, 0x8863, 0x88E0, 0x8B02, 0x88E1, 0x9055, + 0x88E2, 0x907A, 0x88E3, 0x533B, 0x88E4, 0x4E95, 0x88E5, 0x4EA5, 0x88E6, 0x57DF, 0x88E7, 0x80B2, 0x88E8, 0x90C1, 0x88E9, 0x78EF, + 0x88EA, 0x4E00, 0x88EB, 0x58F1, 0x88EC, 0x6EA2, 0x88ED, 0x9038, 0x88EE, 0x7A32, 0x88EF, 0x8328, 0x88F0, 0x828B, 0x88F1, 0x9C2F, + 0x88F2, 0x5141, 0x88F3, 0x5370, 0x88F4, 0x54BD, 0x88F5, 0x54E1, 0x88F6, 0x56E0, 0x88F7, 0x59FB, 0x88F8, 0x5F15, 0x88F9, 0x98F2, + 0x88FA, 0x6DEB, 0x88FB, 0x80E4, 0x88FC, 0x852D, 0x8940, 0x9662, 0x8941, 0x9670, 0x8942, 0x96A0, 0x8943, 0x97FB, 0x8944, 0x540B, + 0x8945, 0x53F3, 0x8946, 0x5B87, 0x8947, 0x70CF, 0x8948, 0x7FBD, 0x8949, 0x8FC2, 0x894A, 0x96E8, 0x894B, 0x536F, 0x894C, 0x9D5C, + 0x894D, 0x7ABA, 0x894E, 0x4E11, 0x894F, 0x7893, 0x8950, 0x81FC, 0x8951, 0x6E26, 0x8952, 0x5618, 0x8953, 0x5504, 0x8954, 0x6B1D, + 0x8955, 0x851A, 0x8956, 0x9C3B, 0x8957, 0x59E5, 0x8958, 0x53A9, 0x8959, 0x6D66, 0x895A, 0x74DC, 0x895B, 0x958F, 0x895C, 0x5642, + 0x895D, 0x4E91, 0x895E, 0x904B, 0x895F, 0x96F2, 0x8960, 0x834F, 0x8961, 0x990C, 0x8962, 0x53E1, 0x8963, 0x55B6, 0x8964, 0x5B30, + 0x8965, 0x5F71, 0x8966, 0x6620, 0x8967, 0x66F3, 0x8968, 0x6804, 0x8969, 0x6C38, 0x896A, 0x6CF3, 0x896B, 0x6D29, 0x896C, 0x745B, + 0x896D, 0x76C8, 0x896E, 0x7A4E, 0x896F, 0x9834, 0x8970, 0x82F1, 0x8971, 0x885B, 0x8972, 0x8A60, 0x8973, 0x92ED, 0x8974, 0x6DB2, + 0x8975, 0x75AB, 0x8976, 0x76CA, 0x8977, 0x99C5, 0x8978, 0x60A6, 0x8979, 0x8B01, 0x897A, 0x8D8A, 0x897B, 0x95B2, 0x897C, 0x698E, + 0x897D, 0x53AD, 0x897E, 0x5186, 0x8980, 0x5712, 0x8981, 0x5830, 0x8982, 0x5944, 0x8983, 0x5BB4, 0x8984, 0x5EF6, 0x8985, 0x6028, + 0x8986, 0x63A9, 0x8987, 0x63F4, 0x8988, 0x6CBF, 0x8989, 0x6F14, 0x898A, 0x708E, 0x898B, 0x7114, 0x898C, 0x7159, 0x898D, 0x71D5, + 0x898E, 0x733F, 0x898F, 0x7E01, 0x8990, 0x8276, 0x8991, 0x82D1, 0x8992, 0x8597, 0x8993, 0x9060, 0x8994, 0x925B, 0x8995, 0x9D1B, + 0x8996, 0x5869, 0x8997, 0x65BC, 0x8998, 0x6C5A, 0x8999, 0x7525, 0x899A, 0x51F9, 0x899B, 0x592E, 0x899C, 0x5965, 0x899D, 0x5F80, + 0x899E, 0x5FDC, 0x899F, 0x62BC, 0x89A0, 0x65FA, 0x89A1, 0x6A2A, 0x89A2, 0x6B27, 0x89A3, 0x6BB4, 0x89A4, 0x738B, 0x89A5, 0x7FC1, + 0x89A6, 0x8956, 0x89A7, 0x9D2C, 0x89A8, 0x9D0E, 0x89A9, 0x9EC4, 0x89AA, 0x5CA1, 0x89AB, 0x6C96, 0x89AC, 0x837B, 0x89AD, 0x5104, + 0x89AE, 0x5C4B, 0x89AF, 0x61B6, 0x89B0, 0x81C6, 0x89B1, 0x6876, 0x89B2, 0x7261, 0x89B3, 0x4E59, 0x89B4, 0x4FFA, 0x89B5, 0x5378, + 0x89B6, 0x6069, 0x89B7, 0x6E29, 0x89B8, 0x7A4F, 0x89B9, 0x97F3, 0x89BA, 0x4E0B, 0x89BB, 0x5316, 0x89BC, 0x4EEE, 0x89BD, 0x4F55, + 0x89BE, 0x4F3D, 0x89BF, 0x4FA1, 0x89C0, 0x4F73, 0x89C1, 0x52A0, 0x89C2, 0x53EF, 0x89C3, 0x5609, 0x89C4, 0x590F, 0x89C5, 0x5AC1, + 0x89C6, 0x5BB6, 0x89C7, 0x5BE1, 0x89C8, 0x79D1, 0x89C9, 0x6687, 0x89CA, 0x679C, 0x89CB, 0x67B6, 0x89CC, 0x6B4C, 0x89CD, 0x6CB3, + 0x89CE, 0x706B, 0x89CF, 0x73C2, 0x89D0, 0x798D, 0x89D1, 0x79BE, 0x89D2, 0x7A3C, 0x89D3, 0x7B87, 0x89D4, 0x82B1, 0x89D5, 0x82DB, + 0x89D6, 0x8304, 0x89D7, 0x8377, 0x89D8, 0x83EF, 0x89D9, 0x83D3, 0x89DA, 0x8766, 0x89DB, 0x8AB2, 0x89DC, 0x5629, 0x89DD, 0x8CA8, + 0x89DE, 0x8FE6, 0x89DF, 0x904E, 0x89E0, 0x971E, 0x89E1, 0x868A, 0x89E2, 0x4FC4, 0x89E3, 0x5CE8, 0x89E4, 0x6211, 0x89E5, 0x7259, + 0x89E6, 0x753B, 0x89E7, 0x81E5, 0x89E8, 0x82BD, 0x89E9, 0x86FE, 0x89EA, 0x8CC0, 0x89EB, 0x96C5, 0x89EC, 0x9913, 0x89ED, 0x99D5, + 0x89EE, 0x4ECB, 0x89EF, 0x4F1A, 0x89F0, 0x89E3, 0x89F1, 0x56DE, 0x89F2, 0x584A, 0x89F3, 0x58CA, 0x89F4, 0x5EFB, 0x89F5, 0x5FEB, + 0x89F6, 0x602A, 0x89F7, 0x6094, 0x89F8, 0x6062, 0x89F9, 0x61D0, 0x89FA, 0x6212, 0x89FB, 0x62D0, 0x89FC, 0x6539, 0x8A40, 0x9B41, + 0x8A41, 0x6666, 0x8A42, 0x68B0, 0x8A43, 0x6D77, 0x8A44, 0x7070, 0x8A45, 0x754C, 0x8A46, 0x7686, 0x8A47, 0x7D75, 0x8A48, 0x82A5, + 0x8A49, 0x87F9, 0x8A4A, 0x958B, 0x8A4B, 0x968E, 0x8A4C, 0x8C9D, 0x8A4D, 0x51F1, 0x8A4E, 0x52BE, 0x8A4F, 0x5916, 0x8A50, 0x54B3, + 0x8A51, 0x5BB3, 0x8A52, 0x5D16, 0x8A53, 0x6168, 0x8A54, 0x6982, 0x8A55, 0x6DAF, 0x8A56, 0x788D, 0x8A57, 0x84CB, 0x8A58, 0x8857, + 0x8A59, 0x8A72, 0x8A5A, 0x93A7, 0x8A5B, 0x9AB8, 0x8A5C, 0x6D6C, 0x8A5D, 0x99A8, 0x8A5E, 0x86D9, 0x8A5F, 0x57A3, 0x8A60, 0x67FF, + 0x8A61, 0x86CE, 0x8A62, 0x920E, 0x8A63, 0x5283, 0x8A64, 0x5687, 0x8A65, 0x5404, 0x8A66, 0x5ED3, 0x8A67, 0x62E1, 0x8A68, 0x64B9, + 0x8A69, 0x683C, 0x8A6A, 0x6838, 0x8A6B, 0x6BBB, 0x8A6C, 0x7372, 0x8A6D, 0x78BA, 0x8A6E, 0x7A6B, 0x8A6F, 0x899A, 0x8A70, 0x89D2, + 0x8A71, 0x8D6B, 0x8A72, 0x8F03, 0x8A73, 0x90ED, 0x8A74, 0x95A3, 0x8A75, 0x9694, 0x8A76, 0x9769, 0x8A77, 0x5B66, 0x8A78, 0x5CB3, + 0x8A79, 0x697D, 0x8A7A, 0x984D, 0x8A7B, 0x984E, 0x8A7C, 0x639B, 0x8A7D, 0x7B20, 0x8A7E, 0x6A2B, 0x8A80, 0x6A7F, 0x8A81, 0x68B6, + 0x8A82, 0x9C0D, 0x8A83, 0x6F5F, 0x8A84, 0x5272, 0x8A85, 0x559D, 0x8A86, 0x6070, 0x8A87, 0x62EC, 0x8A88, 0x6D3B, 0x8A89, 0x6E07, + 0x8A8A, 0x6ED1, 0x8A8B, 0x845B, 0x8A8C, 0x8910, 0x8A8D, 0x8F44, 0x8A8E, 0x4E14, 0x8A8F, 0x9C39, 0x8A90, 0x53F6, 0x8A91, 0x691B, + 0x8A92, 0x6A3A, 0x8A93, 0x9784, 0x8A94, 0x682A, 0x8A95, 0x515C, 0x8A96, 0x7AC3, 0x8A97, 0x84B2, 0x8A98, 0x91DC, 0x8A99, 0x938C, + 0x8A9A, 0x565B, 0x8A9B, 0x9D28, 0x8A9C, 0x6822, 0x8A9D, 0x8305, 0x8A9E, 0x8431, 0x8A9F, 0x7CA5, 0x8AA0, 0x5208, 0x8AA1, 0x82C5, + 0x8AA2, 0x74E6, 0x8AA3, 0x4E7E, 0x8AA4, 0x4F83, 0x8AA5, 0x51A0, 0x8AA6, 0x5BD2, 0x8AA7, 0x520A, 0x8AA8, 0x52D8, 0x8AA9, 0x52E7, + 0x8AAA, 0x5DFB, 0x8AAB, 0x559A, 0x8AAC, 0x582A, 0x8AAD, 0x59E6, 0x8AAE, 0x5B8C, 0x8AAF, 0x5B98, 0x8AB0, 0x5BDB, 0x8AB1, 0x5E72, + 0x8AB2, 0x5E79, 0x8AB3, 0x60A3, 0x8AB4, 0x611F, 0x8AB5, 0x6163, 0x8AB6, 0x61BE, 0x8AB7, 0x63DB, 0x8AB8, 0x6562, 0x8AB9, 0x67D1, + 0x8ABA, 0x6853, 0x8ABB, 0x68FA, 0x8ABC, 0x6B3E, 0x8ABD, 0x6B53, 0x8ABE, 0x6C57, 0x8ABF, 0x6F22, 0x8AC0, 0x6F97, 0x8AC1, 0x6F45, + 0x8AC2, 0x74B0, 0x8AC3, 0x7518, 0x8AC4, 0x76E3, 0x8AC5, 0x770B, 0x8AC6, 0x7AFF, 0x8AC7, 0x7BA1, 0x8AC8, 0x7C21, 0x8AC9, 0x7DE9, + 0x8ACA, 0x7F36, 0x8ACB, 0x7FF0, 0x8ACC, 0x809D, 0x8ACD, 0x8266, 0x8ACE, 0x839E, 0x8ACF, 0x89B3, 0x8AD0, 0x8ACC, 0x8AD1, 0x8CAB, + 0x8AD2, 0x9084, 0x8AD3, 0x9451, 0x8AD4, 0x9593, 0x8AD5, 0x9591, 0x8AD6, 0x95A2, 0x8AD7, 0x9665, 0x8AD8, 0x97D3, 0x8AD9, 0x9928, + 0x8ADA, 0x8218, 0x8ADB, 0x4E38, 0x8ADC, 0x542B, 0x8ADD, 0x5CB8, 0x8ADE, 0x5DCC, 0x8ADF, 0x73A9, 0x8AE0, 0x764C, 0x8AE1, 0x773C, + 0x8AE2, 0x5CA9, 0x8AE3, 0x7FEB, 0x8AE4, 0x8D0B, 0x8AE5, 0x96C1, 0x8AE6, 0x9811, 0x8AE7, 0x9854, 0x8AE8, 0x9858, 0x8AE9, 0x4F01, + 0x8AEA, 0x4F0E, 0x8AEB, 0x5371, 0x8AEC, 0x559C, 0x8AED, 0x5668, 0x8AEE, 0x57FA, 0x8AEF, 0x5947, 0x8AF0, 0x5B09, 0x8AF1, 0x5BC4, + 0x8AF2, 0x5C90, 0x8AF3, 0x5E0C, 0x8AF4, 0x5E7E, 0x8AF5, 0x5FCC, 0x8AF6, 0x63EE, 0x8AF7, 0x673A, 0x8AF8, 0x65D7, 0x8AF9, 0x65E2, + 0x8AFA, 0x671F, 0x8AFB, 0x68CB, 0x8AFC, 0x68C4, 0x8B40, 0x6A5F, 0x8B41, 0x5E30, 0x8B42, 0x6BC5, 0x8B43, 0x6C17, 0x8B44, 0x6C7D, + 0x8B45, 0x757F, 0x8B46, 0x7948, 0x8B47, 0x5B63, 0x8B48, 0x7A00, 0x8B49, 0x7D00, 0x8B4A, 0x5FBD, 0x8B4B, 0x898F, 0x8B4C, 0x8A18, + 0x8B4D, 0x8CB4, 0x8B4E, 0x8D77, 0x8B4F, 0x8ECC, 0x8B50, 0x8F1D, 0x8B51, 0x98E2, 0x8B52, 0x9A0E, 0x8B53, 0x9B3C, 0x8B54, 0x4E80, + 0x8B55, 0x507D, 0x8B56, 0x5100, 0x8B57, 0x5993, 0x8B58, 0x5B9C, 0x8B59, 0x622F, 0x8B5A, 0x6280, 0x8B5B, 0x64EC, 0x8B5C, 0x6B3A, + 0x8B5D, 0x72A0, 0x8B5E, 0x7591, 0x8B5F, 0x7947, 0x8B60, 0x7FA9, 0x8B61, 0x87FB, 0x8B62, 0x8ABC, 0x8B63, 0x8B70, 0x8B64, 0x63AC, + 0x8B65, 0x83CA, 0x8B66, 0x97A0, 0x8B67, 0x5409, 0x8B68, 0x5403, 0x8B69, 0x55AB, 0x8B6A, 0x6854, 0x8B6B, 0x6A58, 0x8B6C, 0x8A70, + 0x8B6D, 0x7827, 0x8B6E, 0x6775, 0x8B6F, 0x9ECD, 0x8B70, 0x5374, 0x8B71, 0x5BA2, 0x8B72, 0x811A, 0x8B73, 0x8650, 0x8B74, 0x9006, + 0x8B75, 0x4E18, 0x8B76, 0x4E45, 0x8B77, 0x4EC7, 0x8B78, 0x4F11, 0x8B79, 0x53CA, 0x8B7A, 0x5438, 0x8B7B, 0x5BAE, 0x8B7C, 0x5F13, + 0x8B7D, 0x6025, 0x8B7E, 0x6551, 0x8B80, 0x673D, 0x8B81, 0x6C42, 0x8B82, 0x6C72, 0x8B83, 0x6CE3, 0x8B84, 0x7078, 0x8B85, 0x7403, + 0x8B86, 0x7A76, 0x8B87, 0x7AAE, 0x8B88, 0x7B08, 0x8B89, 0x7D1A, 0x8B8A, 0x7CFE, 0x8B8B, 0x7D66, 0x8B8C, 0x65E7, 0x8B8D, 0x725B, + 0x8B8E, 0x53BB, 0x8B8F, 0x5C45, 0x8B90, 0x5DE8, 0x8B91, 0x62D2, 0x8B92, 0x62E0, 0x8B93, 0x6319, 0x8B94, 0x6E20, 0x8B95, 0x865A, + 0x8B96, 0x8A31, 0x8B97, 0x8DDD, 0x8B98, 0x92F8, 0x8B99, 0x6F01, 0x8B9A, 0x79A6, 0x8B9B, 0x9B5A, 0x8B9C, 0x4EA8, 0x8B9D, 0x4EAB, + 0x8B9E, 0x4EAC, 0x8B9F, 0x4F9B, 0x8BA0, 0x4FA0, 0x8BA1, 0x50D1, 0x8BA2, 0x5147, 0x8BA3, 0x7AF6, 0x8BA4, 0x5171, 0x8BA5, 0x51F6, + 0x8BA6, 0x5354, 0x8BA7, 0x5321, 0x8BA8, 0x537F, 0x8BA9, 0x53EB, 0x8BAA, 0x55AC, 0x8BAB, 0x5883, 0x8BAC, 0x5CE1, 0x8BAD, 0x5F37, + 0x8BAE, 0x5F4A, 0x8BAF, 0x602F, 0x8BB0, 0x6050, 0x8BB1, 0x606D, 0x8BB2, 0x631F, 0x8BB3, 0x6559, 0x8BB4, 0x6A4B, 0x8BB5, 0x6CC1, + 0x8BB6, 0x72C2, 0x8BB7, 0x72ED, 0x8BB8, 0x77EF, 0x8BB9, 0x80F8, 0x8BBA, 0x8105, 0x8BBB, 0x8208, 0x8BBC, 0x854E, 0x8BBD, 0x90F7, + 0x8BBE, 0x93E1, 0x8BBF, 0x97FF, 0x8BC0, 0x9957, 0x8BC1, 0x9A5A, 0x8BC2, 0x4EF0, 0x8BC3, 0x51DD, 0x8BC4, 0x5C2D, 0x8BC5, 0x6681, + 0x8BC6, 0x696D, 0x8BC7, 0x5C40, 0x8BC8, 0x66F2, 0x8BC9, 0x6975, 0x8BCA, 0x7389, 0x8BCB, 0x6850, 0x8BCC, 0x7C81, 0x8BCD, 0x50C5, + 0x8BCE, 0x52E4, 0x8BCF, 0x5747, 0x8BD0, 0x5DFE, 0x8BD1, 0x9326, 0x8BD2, 0x65A4, 0x8BD3, 0x6B23, 0x8BD4, 0x6B3D, 0x8BD5, 0x7434, + 0x8BD6, 0x7981, 0x8BD7, 0x79BD, 0x8BD8, 0x7B4B, 0x8BD9, 0x7DCA, 0x8BDA, 0x82B9, 0x8BDB, 0x83CC, 0x8BDC, 0x887F, 0x8BDD, 0x895F, + 0x8BDE, 0x8B39, 0x8BDF, 0x8FD1, 0x8BE0, 0x91D1, 0x8BE1, 0x541F, 0x8BE2, 0x9280, 0x8BE3, 0x4E5D, 0x8BE4, 0x5036, 0x8BE5, 0x53E5, + 0x8BE6, 0x533A, 0x8BE7, 0x72D7, 0x8BE8, 0x7396, 0x8BE9, 0x77E9, 0x8BEA, 0x82E6, 0x8BEB, 0x8EAF, 0x8BEC, 0x99C6, 0x8BED, 0x99C8, + 0x8BEE, 0x99D2, 0x8BEF, 0x5177, 0x8BF0, 0x611A, 0x8BF1, 0x865E, 0x8BF2, 0x55B0, 0x8BF3, 0x7A7A, 0x8BF4, 0x5076, 0x8BF5, 0x5BD3, + 0x8BF6, 0x9047, 0x8BF7, 0x9685, 0x8BF8, 0x4E32, 0x8BF9, 0x6ADB, 0x8BFA, 0x91E7, 0x8BFB, 0x5C51, 0x8BFC, 0x5C48, 0x8C40, 0x6398, + 0x8C41, 0x7A9F, 0x8C42, 0x6C93, 0x8C43, 0x9774, 0x8C44, 0x8F61, 0x8C45, 0x7AAA, 0x8C46, 0x718A, 0x8C47, 0x9688, 0x8C48, 0x7C82, + 0x8C49, 0x6817, 0x8C4A, 0x7E70, 0x8C4B, 0x6851, 0x8C4C, 0x936C, 0x8C4D, 0x52F2, 0x8C4E, 0x541B, 0x8C4F, 0x85AB, 0x8C50, 0x8A13, + 0x8C51, 0x7FA4, 0x8C52, 0x8ECD, 0x8C53, 0x90E1, 0x8C54, 0x5366, 0x8C55, 0x8888, 0x8C56, 0x7941, 0x8C57, 0x4FC2, 0x8C58, 0x50BE, + 0x8C59, 0x5211, 0x8C5A, 0x5144, 0x8C5B, 0x5553, 0x8C5C, 0x572D, 0x8C5D, 0x73EA, 0x8C5E, 0x578B, 0x8C5F, 0x5951, 0x8C60, 0x5F62, + 0x8C61, 0x5F84, 0x8C62, 0x6075, 0x8C63, 0x6176, 0x8C64, 0x6167, 0x8C65, 0x61A9, 0x8C66, 0x63B2, 0x8C67, 0x643A, 0x8C68, 0x656C, + 0x8C69, 0x666F, 0x8C6A, 0x6842, 0x8C6B, 0x6E13, 0x8C6C, 0x7566, 0x8C6D, 0x7A3D, 0x8C6E, 0x7CFB, 0x8C6F, 0x7D4C, 0x8C70, 0x7D99, + 0x8C71, 0x7E4B, 0x8C72, 0x7F6B, 0x8C73, 0x830E, 0x8C74, 0x834A, 0x8C75, 0x86CD, 0x8C76, 0x8A08, 0x8C77, 0x8A63, 0x8C78, 0x8B66, + 0x8C79, 0x8EFD, 0x8C7A, 0x981A, 0x8C7B, 0x9D8F, 0x8C7C, 0x82B8, 0x8C7D, 0x8FCE, 0x8C7E, 0x9BE8, 0x8C80, 0x5287, 0x8C81, 0x621F, + 0x8C82, 0x6483, 0x8C83, 0x6FC0, 0x8C84, 0x9699, 0x8C85, 0x6841, 0x8C86, 0x5091, 0x8C87, 0x6B20, 0x8C88, 0x6C7A, 0x8C89, 0x6F54, + 0x8C8A, 0x7A74, 0x8C8B, 0x7D50, 0x8C8C, 0x8840, 0x8C8D, 0x8A23, 0x8C8E, 0x6708, 0x8C8F, 0x4EF6, 0x8C90, 0x5039, 0x8C91, 0x5026, + 0x8C92, 0x5065, 0x8C93, 0x517C, 0x8C94, 0x5238, 0x8C95, 0x5263, 0x8C96, 0x55A7, 0x8C97, 0x570F, 0x8C98, 0x5805, 0x8C99, 0x5ACC, + 0x8C9A, 0x5EFA, 0x8C9B, 0x61B2, 0x8C9C, 0x61F8, 0x8C9D, 0x62F3, 0x8C9E, 0x6372, 0x8C9F, 0x691C, 0x8CA0, 0x6A29, 0x8CA1, 0x727D, + 0x8CA2, 0x72AC, 0x8CA3, 0x732E, 0x8CA4, 0x7814, 0x8CA5, 0x786F, 0x8CA6, 0x7D79, 0x8CA7, 0x770C, 0x8CA8, 0x80A9, 0x8CA9, 0x898B, + 0x8CAA, 0x8B19, 0x8CAB, 0x8CE2, 0x8CAC, 0x8ED2, 0x8CAD, 0x9063, 0x8CAE, 0x9375, 0x8CAF, 0x967A, 0x8CB0, 0x9855, 0x8CB1, 0x9A13, + 0x8CB2, 0x9E78, 0x8CB3, 0x5143, 0x8CB4, 0x539F, 0x8CB5, 0x53B3, 0x8CB6, 0x5E7B, 0x8CB7, 0x5F26, 0x8CB8, 0x6E1B, 0x8CB9, 0x6E90, + 0x8CBA, 0x7384, 0x8CBB, 0x73FE, 0x8CBC, 0x7D43, 0x8CBD, 0x8237, 0x8CBE, 0x8A00, 0x8CBF, 0x8AFA, 0x8CC0, 0x9650, 0x8CC1, 0x4E4E, + 0x8CC2, 0x500B, 0x8CC3, 0x53E4, 0x8CC4, 0x547C, 0x8CC5, 0x56FA, 0x8CC6, 0x59D1, 0x8CC7, 0x5B64, 0x8CC8, 0x5DF1, 0x8CC9, 0x5EAB, + 0x8CCA, 0x5F27, 0x8CCB, 0x6238, 0x8CCC, 0x6545, 0x8CCD, 0x67AF, 0x8CCE, 0x6E56, 0x8CCF, 0x72D0, 0x8CD0, 0x7CCA, 0x8CD1, 0x88B4, + 0x8CD2, 0x80A1, 0x8CD3, 0x80E1, 0x8CD4, 0x83F0, 0x8CD5, 0x864E, 0x8CD6, 0x8A87, 0x8CD7, 0x8DE8, 0x8CD8, 0x9237, 0x8CD9, 0x96C7, + 0x8CDA, 0x9867, 0x8CDB, 0x9F13, 0x8CDC, 0x4E94, 0x8CDD, 0x4E92, 0x8CDE, 0x4F0D, 0x8CDF, 0x5348, 0x8CE0, 0x5449, 0x8CE1, 0x543E, + 0x8CE2, 0x5A2F, 0x8CE3, 0x5F8C, 0x8CE4, 0x5FA1, 0x8CE5, 0x609F, 0x8CE6, 0x68A7, 0x8CE7, 0x6A8E, 0x8CE8, 0x745A, 0x8CE9, 0x7881, + 0x8CEA, 0x8A9E, 0x8CEB, 0x8AA4, 0x8CEC, 0x8B77, 0x8CED, 0x9190, 0x8CEE, 0x4E5E, 0x8CEF, 0x9BC9, 0x8CF0, 0x4EA4, 0x8CF1, 0x4F7C, + 0x8CF2, 0x4FAF, 0x8CF3, 0x5019, 0x8CF4, 0x5016, 0x8CF5, 0x5149, 0x8CF6, 0x516C, 0x8CF7, 0x529F, 0x8CF8, 0x52B9, 0x8CF9, 0x52FE, + 0x8CFA, 0x539A, 0x8CFB, 0x53E3, 0x8CFC, 0x5411, 0x8D40, 0x540E, 0x8D41, 0x5589, 0x8D42, 0x5751, 0x8D43, 0x57A2, 0x8D44, 0x597D, + 0x8D45, 0x5B54, 0x8D46, 0x5B5D, 0x8D47, 0x5B8F, 0x8D48, 0x5DE5, 0x8D49, 0x5DE7, 0x8D4A, 0x5DF7, 0x8D4B, 0x5E78, 0x8D4C, 0x5E83, + 0x8D4D, 0x5E9A, 0x8D4E, 0x5EB7, 0x8D4F, 0x5F18, 0x8D50, 0x6052, 0x8D51, 0x614C, 0x8D52, 0x6297, 0x8D53, 0x62D8, 0x8D54, 0x63A7, + 0x8D55, 0x653B, 0x8D56, 0x6602, 0x8D57, 0x6643, 0x8D58, 0x66F4, 0x8D59, 0x676D, 0x8D5A, 0x6821, 0x8D5B, 0x6897, 0x8D5C, 0x69CB, + 0x8D5D, 0x6C5F, 0x8D5E, 0x6D2A, 0x8D5F, 0x6D69, 0x8D60, 0x6E2F, 0x8D61, 0x6E9D, 0x8D62, 0x7532, 0x8D63, 0x7687, 0x8D64, 0x786C, + 0x8D65, 0x7A3F, 0x8D66, 0x7CE0, 0x8D67, 0x7D05, 0x8D68, 0x7D18, 0x8D69, 0x7D5E, 0x8D6A, 0x7DB1, 0x8D6B, 0x8015, 0x8D6C, 0x8003, + 0x8D6D, 0x80AF, 0x8D6E, 0x80B1, 0x8D6F, 0x8154, 0x8D70, 0x818F, 0x8D71, 0x822A, 0x8D72, 0x8352, 0x8D73, 0x884C, 0x8D74, 0x8861, + 0x8D75, 0x8B1B, 0x8D76, 0x8CA2, 0x8D77, 0x8CFC, 0x8D78, 0x90CA, 0x8D79, 0x9175, 0x8D7A, 0x9271, 0x8D7B, 0x783F, 0x8D7C, 0x92FC, + 0x8D7D, 0x95A4, 0x8D7E, 0x964D, 0x8D80, 0x9805, 0x8D81, 0x9999, 0x8D82, 0x9AD8, 0x8D83, 0x9D3B, 0x8D84, 0x525B, 0x8D85, 0x52AB, + 0x8D86, 0x53F7, 0x8D87, 0x5408, 0x8D88, 0x58D5, 0x8D89, 0x62F7, 0x8D8A, 0x6FE0, 0x8D8B, 0x8C6A, 0x8D8C, 0x8F5F, 0x8D8D, 0x9EB9, + 0x8D8E, 0x514B, 0x8D8F, 0x523B, 0x8D90, 0x544A, 0x8D91, 0x56FD, 0x8D92, 0x7A40, 0x8D93, 0x9177, 0x8D94, 0x9D60, 0x8D95, 0x9ED2, + 0x8D96, 0x7344, 0x8D97, 0x6F09, 0x8D98, 0x8170, 0x8D99, 0x7511, 0x8D9A, 0x5FFD, 0x8D9B, 0x60DA, 0x8D9C, 0x9AA8, 0x8D9D, 0x72DB, + 0x8D9E, 0x8FBC, 0x8D9F, 0x6B64, 0x8DA0, 0x9803, 0x8DA1, 0x4ECA, 0x8DA2, 0x56F0, 0x8DA3, 0x5764, 0x8DA4, 0x58BE, 0x8DA5, 0x5A5A, + 0x8DA6, 0x6068, 0x8DA7, 0x61C7, 0x8DA8, 0x660F, 0x8DA9, 0x6606, 0x8DAA, 0x6839, 0x8DAB, 0x68B1, 0x8DAC, 0x6DF7, 0x8DAD, 0x75D5, + 0x8DAE, 0x7D3A, 0x8DAF, 0x826E, 0x8DB0, 0x9B42, 0x8DB1, 0x4E9B, 0x8DB2, 0x4F50, 0x8DB3, 0x53C9, 0x8DB4, 0x5506, 0x8DB5, 0x5D6F, + 0x8DB6, 0x5DE6, 0x8DB7, 0x5DEE, 0x8DB8, 0x67FB, 0x8DB9, 0x6C99, 0x8DBA, 0x7473, 0x8DBB, 0x7802, 0x8DBC, 0x8A50, 0x8DBD, 0x9396, + 0x8DBE, 0x88DF, 0x8DBF, 0x5750, 0x8DC0, 0x5EA7, 0x8DC1, 0x632B, 0x8DC2, 0x50B5, 0x8DC3, 0x50AC, 0x8DC4, 0x518D, 0x8DC5, 0x6700, + 0x8DC6, 0x54C9, 0x8DC7, 0x585E, 0x8DC8, 0x59BB, 0x8DC9, 0x5BB0, 0x8DCA, 0x5F69, 0x8DCB, 0x624D, 0x8DCC, 0x63A1, 0x8DCD, 0x683D, + 0x8DCE, 0x6B73, 0x8DCF, 0x6E08, 0x8DD0, 0x707D, 0x8DD1, 0x91C7, 0x8DD2, 0x7280, 0x8DD3, 0x7815, 0x8DD4, 0x7826, 0x8DD5, 0x796D, + 0x8DD6, 0x658E, 0x8DD7, 0x7D30, 0x8DD8, 0x83DC, 0x8DD9, 0x88C1, 0x8DDA, 0x8F09, 0x8DDB, 0x969B, 0x8DDC, 0x5264, 0x8DDD, 0x5728, + 0x8DDE, 0x6750, 0x8DDF, 0x7F6A, 0x8DE0, 0x8CA1, 0x8DE1, 0x51B4, 0x8DE2, 0x5742, 0x8DE3, 0x962A, 0x8DE4, 0x583A, 0x8DE5, 0x698A, + 0x8DE6, 0x80B4, 0x8DE7, 0x54B2, 0x8DE8, 0x5D0E, 0x8DE9, 0x57FC, 0x8DEA, 0x7895, 0x8DEB, 0x9DFA, 0x8DEC, 0x4F5C, 0x8DED, 0x524A, + 0x8DEE, 0x548B, 0x8DEF, 0x643E, 0x8DF0, 0x6628, 0x8DF1, 0x6714, 0x8DF2, 0x67F5, 0x8DF3, 0x7A84, 0x8DF4, 0x7B56, 0x8DF5, 0x7D22, + 0x8DF6, 0x932F, 0x8DF7, 0x685C, 0x8DF8, 0x9BAD, 0x8DF9, 0x7B39, 0x8DFA, 0x5319, 0x8DFB, 0x518A, 0x8DFC, 0x5237, 0x8E40, 0x5BDF, + 0x8E41, 0x62F6, 0x8E42, 0x64AE, 0x8E43, 0x64E6, 0x8E44, 0x672D, 0x8E45, 0x6BBA, 0x8E46, 0x85A9, 0x8E47, 0x96D1, 0x8E48, 0x7690, + 0x8E49, 0x9BD6, 0x8E4A, 0x634C, 0x8E4B, 0x9306, 0x8E4C, 0x9BAB, 0x8E4D, 0x76BF, 0x8E4E, 0x6652, 0x8E4F, 0x4E09, 0x8E50, 0x5098, + 0x8E51, 0x53C2, 0x8E52, 0x5C71, 0x8E53, 0x60E8, 0x8E54, 0x6492, 0x8E55, 0x6563, 0x8E56, 0x685F, 0x8E57, 0x71E6, 0x8E58, 0x73CA, + 0x8E59, 0x7523, 0x8E5A, 0x7B97, 0x8E5B, 0x7E82, 0x8E5C, 0x8695, 0x8E5D, 0x8B83, 0x8E5E, 0x8CDB, 0x8E5F, 0x9178, 0x8E60, 0x9910, + 0x8E61, 0x65AC, 0x8E62, 0x66AB, 0x8E63, 0x6B8B, 0x8E64, 0x4ED5, 0x8E65, 0x4ED4, 0x8E66, 0x4F3A, 0x8E67, 0x4F7F, 0x8E68, 0x523A, + 0x8E69, 0x53F8, 0x8E6A, 0x53F2, 0x8E6B, 0x55E3, 0x8E6C, 0x56DB, 0x8E6D, 0x58EB, 0x8E6E, 0x59CB, 0x8E6F, 0x59C9, 0x8E70, 0x59FF, + 0x8E71, 0x5B50, 0x8E72, 0x5C4D, 0x8E73, 0x5E02, 0x8E74, 0x5E2B, 0x8E75, 0x5FD7, 0x8E76, 0x601D, 0x8E77, 0x6307, 0x8E78, 0x652F, + 0x8E79, 0x5B5C, 0x8E7A, 0x65AF, 0x8E7B, 0x65BD, 0x8E7C, 0x65E8, 0x8E7D, 0x679D, 0x8E7E, 0x6B62, 0x8E80, 0x6B7B, 0x8E81, 0x6C0F, + 0x8E82, 0x7345, 0x8E83, 0x7949, 0x8E84, 0x79C1, 0x8E85, 0x7CF8, 0x8E86, 0x7D19, 0x8E87, 0x7D2B, 0x8E88, 0x80A2, 0x8E89, 0x8102, + 0x8E8A, 0x81F3, 0x8E8B, 0x8996, 0x8E8C, 0x8A5E, 0x8E8D, 0x8A69, 0x8E8E, 0x8A66, 0x8E8F, 0x8A8C, 0x8E90, 0x8AEE, 0x8E91, 0x8CC7, + 0x8E92, 0x8CDC, 0x8E93, 0x96CC, 0x8E94, 0x98FC, 0x8E95, 0x6B6F, 0x8E96, 0x4E8B, 0x8E97, 0x4F3C, 0x8E98, 0x4F8D, 0x8E99, 0x5150, + 0x8E9A, 0x5B57, 0x8E9B, 0x5BFA, 0x8E9C, 0x6148, 0x8E9D, 0x6301, 0x8E9E, 0x6642, 0x8E9F, 0x6B21, 0x8EA0, 0x6ECB, 0x8EA1, 0x6CBB, + 0x8EA2, 0x723E, 0x8EA3, 0x74BD, 0x8EA4, 0x75D4, 0x8EA5, 0x78C1, 0x8EA6, 0x793A, 0x8EA7, 0x800C, 0x8EA8, 0x8033, 0x8EA9, 0x81EA, + 0x8EAA, 0x8494, 0x8EAB, 0x8F9E, 0x8EAC, 0x6C50, 0x8EAD, 0x9E7F, 0x8EAE, 0x5F0F, 0x8EAF, 0x8B58, 0x8EB0, 0x9D2B, 0x8EB1, 0x7AFA, + 0x8EB2, 0x8EF8, 0x8EB3, 0x5B8D, 0x8EB4, 0x96EB, 0x8EB5, 0x4E03, 0x8EB6, 0x53F1, 0x8EB7, 0x57F7, 0x8EB8, 0x5931, 0x8EB9, 0x5AC9, + 0x8EBA, 0x5BA4, 0x8EBB, 0x6089, 0x8EBC, 0x6E7F, 0x8EBD, 0x6F06, 0x8EBE, 0x75BE, 0x8EBF, 0x8CEA, 0x8EC0, 0x5B9F, 0x8EC1, 0x8500, + 0x8EC2, 0x7BE0, 0x8EC3, 0x5072, 0x8EC4, 0x67F4, 0x8EC5, 0x829D, 0x8EC6, 0x5C61, 0x8EC7, 0x854A, 0x8EC8, 0x7E1E, 0x8EC9, 0x820E, + 0x8ECA, 0x5199, 0x8ECB, 0x5C04, 0x8ECC, 0x6368, 0x8ECD, 0x8D66, 0x8ECE, 0x659C, 0x8ECF, 0x716E, 0x8ED0, 0x793E, 0x8ED1, 0x7D17, + 0x8ED2, 0x8005, 0x8ED3, 0x8B1D, 0x8ED4, 0x8ECA, 0x8ED5, 0x906E, 0x8ED6, 0x86C7, 0x8ED7, 0x90AA, 0x8ED8, 0x501F, 0x8ED9, 0x52FA, + 0x8EDA, 0x5C3A, 0x8EDB, 0x6753, 0x8EDC, 0x707C, 0x8EDD, 0x7235, 0x8EDE, 0x914C, 0x8EDF, 0x91C8, 0x8EE0, 0x932B, 0x8EE1, 0x82E5, + 0x8EE2, 0x5BC2, 0x8EE3, 0x5F31, 0x8EE4, 0x60F9, 0x8EE5, 0x4E3B, 0x8EE6, 0x53D6, 0x8EE7, 0x5B88, 0x8EE8, 0x624B, 0x8EE9, 0x6731, + 0x8EEA, 0x6B8A, 0x8EEB, 0x72E9, 0x8EEC, 0x73E0, 0x8EED, 0x7A2E, 0x8EEE, 0x816B, 0x8EEF, 0x8DA3, 0x8EF0, 0x9152, 0x8EF1, 0x9996, + 0x8EF2, 0x5112, 0x8EF3, 0x53D7, 0x8EF4, 0x546A, 0x8EF5, 0x5BFF, 0x8EF6, 0x6388, 0x8EF7, 0x6A39, 0x8EF8, 0x7DAC, 0x8EF9, 0x9700, + 0x8EFA, 0x56DA, 0x8EFB, 0x53CE, 0x8EFC, 0x5468, 0x8F40, 0x5B97, 0x8F41, 0x5C31, 0x8F42, 0x5DDE, 0x8F43, 0x4FEE, 0x8F44, 0x6101, + 0x8F45, 0x62FE, 0x8F46, 0x6D32, 0x8F47, 0x79C0, 0x8F48, 0x79CB, 0x8F49, 0x7D42, 0x8F4A, 0x7E4D, 0x8F4B, 0x7FD2, 0x8F4C, 0x81ED, + 0x8F4D, 0x821F, 0x8F4E, 0x8490, 0x8F4F, 0x8846, 0x8F50, 0x8972, 0x8F51, 0x8B90, 0x8F52, 0x8E74, 0x8F53, 0x8F2F, 0x8F54, 0x9031, + 0x8F55, 0x914B, 0x8F56, 0x916C, 0x8F57, 0x96C6, 0x8F58, 0x919C, 0x8F59, 0x4EC0, 0x8F5A, 0x4F4F, 0x8F5B, 0x5145, 0x8F5C, 0x5341, + 0x8F5D, 0x5F93, 0x8F5E, 0x620E, 0x8F5F, 0x67D4, 0x8F60, 0x6C41, 0x8F61, 0x6E0B, 0x8F62, 0x7363, 0x8F63, 0x7E26, 0x8F64, 0x91CD, + 0x8F65, 0x9283, 0x8F66, 0x53D4, 0x8F67, 0x5919, 0x8F68, 0x5BBF, 0x8F69, 0x6DD1, 0x8F6A, 0x795D, 0x8F6B, 0x7E2E, 0x8F6C, 0x7C9B, + 0x8F6D, 0x587E, 0x8F6E, 0x719F, 0x8F6F, 0x51FA, 0x8F70, 0x8853, 0x8F71, 0x8FF0, 0x8F72, 0x4FCA, 0x8F73, 0x5CFB, 0x8F74, 0x6625, + 0x8F75, 0x77AC, 0x8F76, 0x7AE3, 0x8F77, 0x821C, 0x8F78, 0x99FF, 0x8F79, 0x51C6, 0x8F7A, 0x5FAA, 0x8F7B, 0x65EC, 0x8F7C, 0x696F, + 0x8F7D, 0x6B89, 0x8F7E, 0x6DF3, 0x8F80, 0x6E96, 0x8F81, 0x6F64, 0x8F82, 0x76FE, 0x8F83, 0x7D14, 0x8F84, 0x5DE1, 0x8F85, 0x9075, + 0x8F86, 0x9187, 0x8F87, 0x9806, 0x8F88, 0x51E6, 0x8F89, 0x521D, 0x8F8A, 0x6240, 0x8F8B, 0x6691, 0x8F8C, 0x66D9, 0x8F8D, 0x6E1A, + 0x8F8E, 0x5EB6, 0x8F8F, 0x7DD2, 0x8F90, 0x7F72, 0x8F91, 0x66F8, 0x8F92, 0x85AF, 0x8F93, 0x85F7, 0x8F94, 0x8AF8, 0x8F95, 0x52A9, + 0x8F96, 0x53D9, 0x8F97, 0x5973, 0x8F98, 0x5E8F, 0x8F99, 0x5F90, 0x8F9A, 0x6055, 0x8F9B, 0x92E4, 0x8F9C, 0x9664, 0x8F9D, 0x50B7, + 0x8F9E, 0x511F, 0x8F9F, 0x52DD, 0x8FA0, 0x5320, 0x8FA1, 0x5347, 0x8FA2, 0x53EC, 0x8FA3, 0x54E8, 0x8FA4, 0x5546, 0x8FA5, 0x5531, + 0x8FA6, 0x5617, 0x8FA7, 0x5968, 0x8FA8, 0x59BE, 0x8FA9, 0x5A3C, 0x8FAA, 0x5BB5, 0x8FAB, 0x5C06, 0x8FAC, 0x5C0F, 0x8FAD, 0x5C11, + 0x8FAE, 0x5C1A, 0x8FAF, 0x5E84, 0x8FB0, 0x5E8A, 0x8FB1, 0x5EE0, 0x8FB2, 0x5F70, 0x8FB3, 0x627F, 0x8FB4, 0x6284, 0x8FB5, 0x62DB, + 0x8FB6, 0x638C, 0x8FB7, 0x6377, 0x8FB8, 0x6607, 0x8FB9, 0x660C, 0x8FBA, 0x662D, 0x8FBB, 0x6676, 0x8FBC, 0x677E, 0x8FBD, 0x68A2, + 0x8FBE, 0x6A1F, 0x8FBF, 0x6A35, 0x8FC0, 0x6CBC, 0x8FC1, 0x6D88, 0x8FC2, 0x6E09, 0x8FC3, 0x6E58, 0x8FC4, 0x713C, 0x8FC5, 0x7126, + 0x8FC6, 0x7167, 0x8FC7, 0x75C7, 0x8FC8, 0x7701, 0x8FC9, 0x785D, 0x8FCA, 0x7901, 0x8FCB, 0x7965, 0x8FCC, 0x79F0, 0x8FCD, 0x7AE0, + 0x8FCE, 0x7B11, 0x8FCF, 0x7CA7, 0x8FD0, 0x7D39, 0x8FD1, 0x8096, 0x8FD2, 0x83D6, 0x8FD3, 0x848B, 0x8FD4, 0x8549, 0x8FD5, 0x885D, + 0x8FD6, 0x88F3, 0x8FD7, 0x8A1F, 0x8FD8, 0x8A3C, 0x8FD9, 0x8A54, 0x8FDA, 0x8A73, 0x8FDB, 0x8C61, 0x8FDC, 0x8CDE, 0x8FDD, 0x91A4, + 0x8FDE, 0x9266, 0x8FDF, 0x937E, 0x8FE0, 0x9418, 0x8FE1, 0x969C, 0x8FE2, 0x9798, 0x8FE3, 0x4E0A, 0x8FE4, 0x4E08, 0x8FE5, 0x4E1E, + 0x8FE6, 0x4E57, 0x8FE7, 0x5197, 0x8FE8, 0x5270, 0x8FE9, 0x57CE, 0x8FEA, 0x5834, 0x8FEB, 0x58CC, 0x8FEC, 0x5B22, 0x8FED, 0x5E38, + 0x8FEE, 0x60C5, 0x8FEF, 0x64FE, 0x8FF0, 0x6761, 0x8FF1, 0x6756, 0x8FF2, 0x6D44, 0x8FF3, 0x72B6, 0x8FF4, 0x7573, 0x8FF5, 0x7A63, + 0x8FF6, 0x84B8, 0x8FF7, 0x8B72, 0x8FF8, 0x91B8, 0x8FF9, 0x9320, 0x8FFA, 0x5631, 0x8FFB, 0x57F4, 0x8FFC, 0x98FE, 0x9040, 0x62ED, + 0x9041, 0x690D, 0x9042, 0x6B96, 0x9043, 0x71ED, 0x9044, 0x7E54, 0x9045, 0x8077, 0x9046, 0x8272, 0x9047, 0x89E6, 0x9048, 0x98DF, + 0x9049, 0x8755, 0x904A, 0x8FB1, 0x904B, 0x5C3B, 0x904C, 0x4F38, 0x904D, 0x4FE1, 0x904E, 0x4FB5, 0x904F, 0x5507, 0x9050, 0x5A20, + 0x9051, 0x5BDD, 0x9052, 0x5BE9, 0x9053, 0x5FC3, 0x9054, 0x614E, 0x9055, 0x632F, 0x9056, 0x65B0, 0x9057, 0x664B, 0x9058, 0x68EE, + 0x9059, 0x699B, 0x905A, 0x6D78, 0x905B, 0x6DF1, 0x905C, 0x7533, 0x905D, 0x75B9, 0x905E, 0x771F, 0x905F, 0x795E, 0x9060, 0x79E6, + 0x9061, 0x7D33, 0x9062, 0x81E3, 0x9063, 0x82AF, 0x9064, 0x85AA, 0x9065, 0x89AA, 0x9066, 0x8A3A, 0x9067, 0x8EAB, 0x9068, 0x8F9B, + 0x9069, 0x9032, 0x906A, 0x91DD, 0x906B, 0x9707, 0x906C, 0x4EBA, 0x906D, 0x4EC1, 0x906E, 0x5203, 0x906F, 0x5875, 0x9070, 0x58EC, + 0x9071, 0x5C0B, 0x9072, 0x751A, 0x9073, 0x5C3D, 0x9074, 0x814E, 0x9075, 0x8A0A, 0x9076, 0x8FC5, 0x9077, 0x9663, 0x9078, 0x976D, + 0x9079, 0x7B25, 0x907A, 0x8ACF, 0x907B, 0x9808, 0x907C, 0x9162, 0x907D, 0x56F3, 0x907E, 0x53A8, 0x9080, 0x9017, 0x9081, 0x5439, + 0x9082, 0x5782, 0x9083, 0x5E25, 0x9084, 0x63A8, 0x9085, 0x6C34, 0x9086, 0x708A, 0x9087, 0x7761, 0x9088, 0x7C8B, 0x9089, 0x7FE0, + 0x908A, 0x8870, 0x908B, 0x9042, 0x908C, 0x9154, 0x908D, 0x9310, 0x908E, 0x9318, 0x908F, 0x968F, 0x9090, 0x745E, 0x9091, 0x9AC4, + 0x9092, 0x5D07, 0x9093, 0x5D69, 0x9094, 0x6570, 0x9095, 0x67A2, 0x9096, 0x8DA8, 0x9097, 0x96DB, 0x9098, 0x636E, 0x9099, 0x6749, + 0x909A, 0x6919, 0x909B, 0x83C5, 0x909C, 0x9817, 0x909D, 0x96C0, 0x909E, 0x88FE, 0x909F, 0x6F84, 0x90A0, 0x647A, 0x90A1, 0x5BF8, + 0x90A2, 0x4E16, 0x90A3, 0x702C, 0x90A4, 0x755D, 0x90A5, 0x662F, 0x90A6, 0x51C4, 0x90A7, 0x5236, 0x90A8, 0x52E2, 0x90A9, 0x59D3, + 0x90AA, 0x5F81, 0x90AB, 0x6027, 0x90AC, 0x6210, 0x90AD, 0x653F, 0x90AE, 0x6574, 0x90AF, 0x661F, 0x90B0, 0x6674, 0x90B1, 0x68F2, + 0x90B2, 0x6816, 0x90B3, 0x6B63, 0x90B4, 0x6E05, 0x90B5, 0x7272, 0x90B6, 0x751F, 0x90B7, 0x76DB, 0x90B8, 0x7CBE, 0x90B9, 0x8056, + 0x90BA, 0x58F0, 0x90BB, 0x88FD, 0x90BC, 0x897F, 0x90BD, 0x8AA0, 0x90BE, 0x8A93, 0x90BF, 0x8ACB, 0x90C0, 0x901D, 0x90C1, 0x9192, + 0x90C2, 0x9752, 0x90C3, 0x9759, 0x90C4, 0x6589, 0x90C5, 0x7A0E, 0x90C6, 0x8106, 0x90C7, 0x96BB, 0x90C8, 0x5E2D, 0x90C9, 0x60DC, + 0x90CA, 0x621A, 0x90CB, 0x65A5, 0x90CC, 0x6614, 0x90CD, 0x6790, 0x90CE, 0x77F3, 0x90CF, 0x7A4D, 0x90D0, 0x7C4D, 0x90D1, 0x7E3E, + 0x90D2, 0x810A, 0x90D3, 0x8CAC, 0x90D4, 0x8D64, 0x90D5, 0x8DE1, 0x90D6, 0x8E5F, 0x90D7, 0x78A9, 0x90D8, 0x5207, 0x90D9, 0x62D9, + 0x90DA, 0x63A5, 0x90DB, 0x6442, 0x90DC, 0x6298, 0x90DD, 0x8A2D, 0x90DE, 0x7A83, 0x90DF, 0x7BC0, 0x90E0, 0x8AAC, 0x90E1, 0x96EA, + 0x90E2, 0x7D76, 0x90E3, 0x820C, 0x90E4, 0x8749, 0x90E5, 0x4ED9, 0x90E6, 0x5148, 0x90E7, 0x5343, 0x90E8, 0x5360, 0x90E9, 0x5BA3, + 0x90EA, 0x5C02, 0x90EB, 0x5C16, 0x90EC, 0x5DDD, 0x90ED, 0x6226, 0x90EE, 0x6247, 0x90EF, 0x64B0, 0x90F0, 0x6813, 0x90F1, 0x6834, + 0x90F2, 0x6CC9, 0x90F3, 0x6D45, 0x90F4, 0x6D17, 0x90F5, 0x67D3, 0x90F6, 0x6F5C, 0x90F7, 0x714E, 0x90F8, 0x717D, 0x90F9, 0x65CB, + 0x90FA, 0x7A7F, 0x90FB, 0x7BAD, 0x90FC, 0x7DDA, 0x9140, 0x7E4A, 0x9141, 0x7FA8, 0x9142, 0x817A, 0x9143, 0x821B, 0x9144, 0x8239, + 0x9145, 0x85A6, 0x9146, 0x8A6E, 0x9147, 0x8CCE, 0x9148, 0x8DF5, 0x9149, 0x9078, 0x914A, 0x9077, 0x914B, 0x92AD, 0x914C, 0x9291, + 0x914D, 0x9583, 0x914E, 0x9BAE, 0x914F, 0x524D, 0x9150, 0x5584, 0x9151, 0x6F38, 0x9152, 0x7136, 0x9153, 0x5168, 0x9154, 0x7985, + 0x9155, 0x7E55, 0x9156, 0x81B3, 0x9157, 0x7CCE, 0x9158, 0x564C, 0x9159, 0x5851, 0x915A, 0x5CA8, 0x915B, 0x63AA, 0x915C, 0x66FE, + 0x915D, 0x66FD, 0x915E, 0x695A, 0x915F, 0x72D9, 0x9160, 0x758F, 0x9161, 0x758E, 0x9162, 0x790E, 0x9163, 0x7956, 0x9164, 0x79DF, + 0x9165, 0x7C97, 0x9166, 0x7D20, 0x9167, 0x7D44, 0x9168, 0x8607, 0x9169, 0x8A34, 0x916A, 0x963B, 0x916B, 0x9061, 0x916C, 0x9F20, + 0x916D, 0x50E7, 0x916E, 0x5275, 0x916F, 0x53CC, 0x9170, 0x53E2, 0x9171, 0x5009, 0x9172, 0x55AA, 0x9173, 0x58EE, 0x9174, 0x594F, + 0x9175, 0x723D, 0x9176, 0x5B8B, 0x9177, 0x5C64, 0x9178, 0x531D, 0x9179, 0x60E3, 0x917A, 0x60F3, 0x917B, 0x635C, 0x917C, 0x6383, + 0x917D, 0x633F, 0x917E, 0x63BB, 0x9180, 0x64CD, 0x9181, 0x65E9, 0x9182, 0x66F9, 0x9183, 0x5DE3, 0x9184, 0x69CD, 0x9185, 0x69FD, + 0x9186, 0x6F15, 0x9187, 0x71E5, 0x9188, 0x4E89, 0x9189, 0x75E9, 0x918A, 0x76F8, 0x918B, 0x7A93, 0x918C, 0x7CDF, 0x918D, 0x7DCF, + 0x918E, 0x7D9C, 0x918F, 0x8061, 0x9190, 0x8349, 0x9191, 0x8358, 0x9192, 0x846C, 0x9193, 0x84BC, 0x9194, 0x85FB, 0x9195, 0x88C5, + 0x9196, 0x8D70, 0x9197, 0x9001, 0x9198, 0x906D, 0x9199, 0x9397, 0x919A, 0x971C, 0x919B, 0x9A12, 0x919C, 0x50CF, 0x919D, 0x5897, + 0x919E, 0x618E, 0x919F, 0x81D3, 0x91A0, 0x8535, 0x91A1, 0x8D08, 0x91A2, 0x9020, 0x91A3, 0x4FC3, 0x91A4, 0x5074, 0x91A5, 0x5247, + 0x91A6, 0x5373, 0x91A7, 0x606F, 0x91A8, 0x6349, 0x91A9, 0x675F, 0x91AA, 0x6E2C, 0x91AB, 0x8DB3, 0x91AC, 0x901F, 0x91AD, 0x4FD7, + 0x91AE, 0x5C5E, 0x91AF, 0x8CCA, 0x91B0, 0x65CF, 0x91B1, 0x7D9A, 0x91B2, 0x5352, 0x91B3, 0x8896, 0x91B4, 0x5176, 0x91B5, 0x63C3, + 0x91B6, 0x5B58, 0x91B7, 0x5B6B, 0x91B8, 0x5C0A, 0x91B9, 0x640D, 0x91BA, 0x6751, 0x91BB, 0x905C, 0x91BC, 0x4ED6, 0x91BD, 0x591A, + 0x91BE, 0x592A, 0x91BF, 0x6C70, 0x91C0, 0x8A51, 0x91C1, 0x553E, 0x91C2, 0x5815, 0x91C3, 0x59A5, 0x91C4, 0x60F0, 0x91C5, 0x6253, + 0x91C6, 0x67C1, 0x91C7, 0x8235, 0x91C8, 0x6955, 0x91C9, 0x9640, 0x91CA, 0x99C4, 0x91CB, 0x9A28, 0x91CC, 0x4F53, 0x91CD, 0x5806, + 0x91CE, 0x5BFE, 0x91CF, 0x8010, 0x91D0, 0x5CB1, 0x91D1, 0x5E2F, 0x91D2, 0x5F85, 0x91D3, 0x6020, 0x91D4, 0x614B, 0x91D5, 0x6234, + 0x91D6, 0x66FF, 0x91D7, 0x6CF0, 0x91D8, 0x6EDE, 0x91D9, 0x80CE, 0x91DA, 0x817F, 0x91DB, 0x82D4, 0x91DC, 0x888B, 0x91DD, 0x8CB8, + 0x91DE, 0x9000, 0x91DF, 0x902E, 0x91E0, 0x968A, 0x91E1, 0x9EDB, 0x91E2, 0x9BDB, 0x91E3, 0x4EE3, 0x91E4, 0x53F0, 0x91E5, 0x5927, + 0x91E6, 0x7B2C, 0x91E7, 0x918D, 0x91E8, 0x984C, 0x91E9, 0x9DF9, 0x91EA, 0x6EDD, 0x91EB, 0x7027, 0x91EC, 0x5353, 0x91ED, 0x5544, + 0x91EE, 0x5B85, 0x91EF, 0x6258, 0x91F0, 0x629E, 0x91F1, 0x62D3, 0x91F2, 0x6CA2, 0x91F3, 0x6FEF, 0x91F4, 0x7422, 0x91F5, 0x8A17, + 0x91F6, 0x9438, 0x91F7, 0x6FC1, 0x91F8, 0x8AFE, 0x91F9, 0x8338, 0x91FA, 0x51E7, 0x91FB, 0x86F8, 0x91FC, 0x53EA, 0x9240, 0x53E9, + 0x9241, 0x4F46, 0x9242, 0x9054, 0x9243, 0x8FB0, 0x9244, 0x596A, 0x9245, 0x8131, 0x9246, 0x5DFD, 0x9247, 0x7AEA, 0x9248, 0x8FBF, + 0x9249, 0x68DA, 0x924A, 0x8C37, 0x924B, 0x72F8, 0x924C, 0x9C48, 0x924D, 0x6A3D, 0x924E, 0x8AB0, 0x924F, 0x4E39, 0x9250, 0x5358, + 0x9251, 0x5606, 0x9252, 0x5766, 0x9253, 0x62C5, 0x9254, 0x63A2, 0x9255, 0x65E6, 0x9256, 0x6B4E, 0x9257, 0x6DE1, 0x9258, 0x6E5B, + 0x9259, 0x70AD, 0x925A, 0x77ED, 0x925B, 0x7AEF, 0x925C, 0x7BAA, 0x925D, 0x7DBB, 0x925E, 0x803D, 0x925F, 0x80C6, 0x9260, 0x86CB, + 0x9261, 0x8A95, 0x9262, 0x935B, 0x9263, 0x56E3, 0x9264, 0x58C7, 0x9265, 0x5F3E, 0x9266, 0x65AD, 0x9267, 0x6696, 0x9268, 0x6A80, + 0x9269, 0x6BB5, 0x926A, 0x7537, 0x926B, 0x8AC7, 0x926C, 0x5024, 0x926D, 0x77E5, 0x926E, 0x5730, 0x926F, 0x5F1B, 0x9270, 0x6065, + 0x9271, 0x667A, 0x9272, 0x6C60, 0x9273, 0x75F4, 0x9274, 0x7A1A, 0x9275, 0x7F6E, 0x9276, 0x81F4, 0x9277, 0x8718, 0x9278, 0x9045, + 0x9279, 0x99B3, 0x927A, 0x7BC9, 0x927B, 0x755C, 0x927C, 0x7AF9, 0x927D, 0x7B51, 0x927E, 0x84C4, 0x9280, 0x9010, 0x9281, 0x79E9, + 0x9282, 0x7A92, 0x9283, 0x8336, 0x9284, 0x5AE1, 0x9285, 0x7740, 0x9286, 0x4E2D, 0x9287, 0x4EF2, 0x9288, 0x5B99, 0x9289, 0x5FE0, + 0x928A, 0x62BD, 0x928B, 0x663C, 0x928C, 0x67F1, 0x928D, 0x6CE8, 0x928E, 0x866B, 0x928F, 0x8877, 0x9290, 0x8A3B, 0x9291, 0x914E, + 0x9292, 0x92F3, 0x9293, 0x99D0, 0x9294, 0x6A17, 0x9295, 0x7026, 0x9296, 0x732A, 0x9297, 0x82E7, 0x9298, 0x8457, 0x9299, 0x8CAF, + 0x929A, 0x4E01, 0x929B, 0x5146, 0x929C, 0x51CB, 0x929D, 0x558B, 0x929E, 0x5BF5, 0x929F, 0x5E16, 0x92A0, 0x5E33, 0x92A1, 0x5E81, + 0x92A2, 0x5F14, 0x92A3, 0x5F35, 0x92A4, 0x5F6B, 0x92A5, 0x5FB4, 0x92A6, 0x61F2, 0x92A7, 0x6311, 0x92A8, 0x66A2, 0x92A9, 0x671D, + 0x92AA, 0x6F6E, 0x92AB, 0x7252, 0x92AC, 0x753A, 0x92AD, 0x773A, 0x92AE, 0x8074, 0x92AF, 0x8139, 0x92B0, 0x8178, 0x92B1, 0x8776, + 0x92B2, 0x8ABF, 0x92B3, 0x8ADC, 0x92B4, 0x8D85, 0x92B5, 0x8DF3, 0x92B6, 0x929A, 0x92B7, 0x9577, 0x92B8, 0x9802, 0x92B9, 0x9CE5, + 0x92BA, 0x52C5, 0x92BB, 0x6357, 0x92BC, 0x76F4, 0x92BD, 0x6715, 0x92BE, 0x6C88, 0x92BF, 0x73CD, 0x92C0, 0x8CC3, 0x92C1, 0x93AE, + 0x92C2, 0x9673, 0x92C3, 0x6D25, 0x92C4, 0x589C, 0x92C5, 0x690E, 0x92C6, 0x69CC, 0x92C7, 0x8FFD, 0x92C8, 0x939A, 0x92C9, 0x75DB, + 0x92CA, 0x901A, 0x92CB, 0x585A, 0x92CC, 0x6802, 0x92CD, 0x63B4, 0x92CE, 0x69FB, 0x92CF, 0x4F43, 0x92D0, 0x6F2C, 0x92D1, 0x67D8, + 0x92D2, 0x8FBB, 0x92D3, 0x8526, 0x92D4, 0x7DB4, 0x92D5, 0x9354, 0x92D6, 0x693F, 0x92D7, 0x6F70, 0x92D8, 0x576A, 0x92D9, 0x58F7, + 0x92DA, 0x5B2C, 0x92DB, 0x7D2C, 0x92DC, 0x722A, 0x92DD, 0x540A, 0x92DE, 0x91E3, 0x92DF, 0x9DB4, 0x92E0, 0x4EAD, 0x92E1, 0x4F4E, + 0x92E2, 0x505C, 0x92E3, 0x5075, 0x92E4, 0x5243, 0x92E5, 0x8C9E, 0x92E6, 0x5448, 0x92E7, 0x5824, 0x92E8, 0x5B9A, 0x92E9, 0x5E1D, + 0x92EA, 0x5E95, 0x92EB, 0x5EAD, 0x92EC, 0x5EF7, 0x92ED, 0x5F1F, 0x92EE, 0x608C, 0x92EF, 0x62B5, 0x92F0, 0x633A, 0x92F1, 0x63D0, + 0x92F2, 0x68AF, 0x92F3, 0x6C40, 0x92F4, 0x7887, 0x92F5, 0x798E, 0x92F6, 0x7A0B, 0x92F7, 0x7DE0, 0x92F8, 0x8247, 0x92F9, 0x8A02, + 0x92FA, 0x8AE6, 0x92FB, 0x8E44, 0x92FC, 0x9013, 0x9340, 0x90B8, 0x9341, 0x912D, 0x9342, 0x91D8, 0x9343, 0x9F0E, 0x9344, 0x6CE5, + 0x9345, 0x6458, 0x9346, 0x64E2, 0x9347, 0x6575, 0x9348, 0x6EF4, 0x9349, 0x7684, 0x934A, 0x7B1B, 0x934B, 0x9069, 0x934C, 0x93D1, + 0x934D, 0x6EBA, 0x934E, 0x54F2, 0x934F, 0x5FB9, 0x9350, 0x64A4, 0x9351, 0x8F4D, 0x9352, 0x8FED, 0x9353, 0x9244, 0x9354, 0x5178, + 0x9355, 0x586B, 0x9356, 0x5929, 0x9357, 0x5C55, 0x9358, 0x5E97, 0x9359, 0x6DFB, 0x935A, 0x7E8F, 0x935B, 0x751C, 0x935C, 0x8CBC, + 0x935D, 0x8EE2, 0x935E, 0x985B, 0x935F, 0x70B9, 0x9360, 0x4F1D, 0x9361, 0x6BBF, 0x9362, 0x6FB1, 0x9363, 0x7530, 0x9364, 0x96FB, + 0x9365, 0x514E, 0x9366, 0x5410, 0x9367, 0x5835, 0x9368, 0x5857, 0x9369, 0x59AC, 0x936A, 0x5C60, 0x936B, 0x5F92, 0x936C, 0x6597, + 0x936D, 0x675C, 0x936E, 0x6E21, 0x936F, 0x767B, 0x9370, 0x83DF, 0x9371, 0x8CED, 0x9372, 0x9014, 0x9373, 0x90FD, 0x9374, 0x934D, + 0x9375, 0x7825, 0x9376, 0x783A, 0x9377, 0x52AA, 0x9378, 0x5EA6, 0x9379, 0x571F, 0x937A, 0x5974, 0x937B, 0x6012, 0x937C, 0x5012, + 0x937D, 0x515A, 0x937E, 0x51AC, 0x9380, 0x51CD, 0x9381, 0x5200, 0x9382, 0x5510, 0x9383, 0x5854, 0x9384, 0x5858, 0x9385, 0x5957, + 0x9386, 0x5B95, 0x9387, 0x5CF6, 0x9388, 0x5D8B, 0x9389, 0x60BC, 0x938A, 0x6295, 0x938B, 0x642D, 0x938C, 0x6771, 0x938D, 0x6843, + 0x938E, 0x68BC, 0x938F, 0x68DF, 0x9390, 0x76D7, 0x9391, 0x6DD8, 0x9392, 0x6E6F, 0x9393, 0x6D9B, 0x9394, 0x706F, 0x9395, 0x71C8, + 0x9396, 0x5F53, 0x9397, 0x75D8, 0x9398, 0x7977, 0x9399, 0x7B49, 0x939A, 0x7B54, 0x939B, 0x7B52, 0x939C, 0x7CD6, 0x939D, 0x7D71, + 0x939E, 0x5230, 0x939F, 0x8463, 0x93A0, 0x8569, 0x93A1, 0x85E4, 0x93A2, 0x8A0E, 0x93A3, 0x8B04, 0x93A4, 0x8C46, 0x93A5, 0x8E0F, + 0x93A6, 0x9003, 0x93A7, 0x900F, 0x93A8, 0x9419, 0x93A9, 0x9676, 0x93AA, 0x982D, 0x93AB, 0x9A30, 0x93AC, 0x95D8, 0x93AD, 0x50CD, + 0x93AE, 0x52D5, 0x93AF, 0x540C, 0x93B0, 0x5802, 0x93B1, 0x5C0E, 0x93B2, 0x61A7, 0x93B3, 0x649E, 0x93B4, 0x6D1E, 0x93B5, 0x77B3, + 0x93B6, 0x7AE5, 0x93B7, 0x80F4, 0x93B8, 0x8404, 0x93B9, 0x9053, 0x93BA, 0x9285, 0x93BB, 0x5CE0, 0x93BC, 0x9D07, 0x93BD, 0x533F, + 0x93BE, 0x5F97, 0x93BF, 0x5FB3, 0x93C0, 0x6D9C, 0x93C1, 0x7279, 0x93C2, 0x7763, 0x93C3, 0x79BF, 0x93C4, 0x7BE4, 0x93C5, 0x6BD2, + 0x93C6, 0x72EC, 0x93C7, 0x8AAD, 0x93C8, 0x6803, 0x93C9, 0x6A61, 0x93CA, 0x51F8, 0x93CB, 0x7A81, 0x93CC, 0x6934, 0x93CD, 0x5C4A, + 0x93CE, 0x9CF6, 0x93CF, 0x82EB, 0x93D0, 0x5BC5, 0x93D1, 0x9149, 0x93D2, 0x701E, 0x93D3, 0x5678, 0x93D4, 0x5C6F, 0x93D5, 0x60C7, + 0x93D6, 0x6566, 0x93D7, 0x6C8C, 0x93D8, 0x8C5A, 0x93D9, 0x9041, 0x93DA, 0x9813, 0x93DB, 0x5451, 0x93DC, 0x66C7, 0x93DD, 0x920D, + 0x93DE, 0x5948, 0x93DF, 0x90A3, 0x93E0, 0x5185, 0x93E1, 0x4E4D, 0x93E2, 0x51EA, 0x93E3, 0x8599, 0x93E4, 0x8B0E, 0x93E5, 0x7058, + 0x93E6, 0x637A, 0x93E7, 0x934B, 0x93E8, 0x6962, 0x93E9, 0x99B4, 0x93EA, 0x7E04, 0x93EB, 0x7577, 0x93EC, 0x5357, 0x93ED, 0x6960, + 0x93EE, 0x8EDF, 0x93EF, 0x96E3, 0x93F0, 0x6C5D, 0x93F1, 0x4E8C, 0x93F2, 0x5C3C, 0x93F3, 0x5F10, 0x93F4, 0x8FE9, 0x93F5, 0x5302, + 0x93F6, 0x8CD1, 0x93F7, 0x8089, 0x93F8, 0x8679, 0x93F9, 0x5EFF, 0x93FA, 0x65E5, 0x93FB, 0x4E73, 0x93FC, 0x5165, 0x9440, 0x5982, + 0x9441, 0x5C3F, 0x9442, 0x97EE, 0x9443, 0x4EFB, 0x9444, 0x598A, 0x9445, 0x5FCD, 0x9446, 0x8A8D, 0x9447, 0x6FE1, 0x9448, 0x79B0, + 0x9449, 0x7962, 0x944A, 0x5BE7, 0x944B, 0x8471, 0x944C, 0x732B, 0x944D, 0x71B1, 0x944E, 0x5E74, 0x944F, 0x5FF5, 0x9450, 0x637B, + 0x9451, 0x649A, 0x9452, 0x71C3, 0x9453, 0x7C98, 0x9454, 0x4E43, 0x9455, 0x5EFC, 0x9456, 0x4E4B, 0x9457, 0x57DC, 0x9458, 0x56A2, + 0x9459, 0x60A9, 0x945A, 0x6FC3, 0x945B, 0x7D0D, 0x945C, 0x80FD, 0x945D, 0x8133, 0x945E, 0x81BF, 0x945F, 0x8FB2, 0x9460, 0x8997, + 0x9461, 0x86A4, 0x9462, 0x5DF4, 0x9463, 0x628A, 0x9464, 0x64AD, 0x9465, 0x8987, 0x9466, 0x6777, 0x9467, 0x6CE2, 0x9468, 0x6D3E, + 0x9469, 0x7436, 0x946A, 0x7834, 0x946B, 0x5A46, 0x946C, 0x7F75, 0x946D, 0x82AD, 0x946E, 0x99AC, 0x946F, 0x4FF3, 0x9470, 0x5EC3, + 0x9471, 0x62DD, 0x9472, 0x6392, 0x9473, 0x6557, 0x9474, 0x676F, 0x9475, 0x76C3, 0x9476, 0x724C, 0x9477, 0x80CC, 0x9478, 0x80BA, + 0x9479, 0x8F29, 0x947A, 0x914D, 0x947B, 0x500D, 0x947C, 0x57F9, 0x947D, 0x5A92, 0x947E, 0x6885, 0x9480, 0x6973, 0x9481, 0x7164, + 0x9482, 0x72FD, 0x9483, 0x8CB7, 0x9484, 0x58F2, 0x9485, 0x8CE0, 0x9486, 0x966A, 0x9487, 0x9019, 0x9488, 0x877F, 0x9489, 0x79E4, + 0x948A, 0x77E7, 0x948B, 0x8429, 0x948C, 0x4F2F, 0x948D, 0x5265, 0x948E, 0x535A, 0x948F, 0x62CD, 0x9490, 0x67CF, 0x9491, 0x6CCA, + 0x9492, 0x767D, 0x9493, 0x7B94, 0x9494, 0x7C95, 0x9495, 0x8236, 0x9496, 0x8584, 0x9497, 0x8FEB, 0x9498, 0x66DD, 0x9499, 0x6F20, + 0x949A, 0x7206, 0x949B, 0x7E1B, 0x949C, 0x83AB, 0x949D, 0x99C1, 0x949E, 0x9EA6, 0x949F, 0x51FD, 0x94A0, 0x7BB1, 0x94A1, 0x7872, + 0x94A2, 0x7BB8, 0x94A3, 0x8087, 0x94A4, 0x7B48, 0x94A5, 0x6AE8, 0x94A6, 0x5E61, 0x94A7, 0x808C, 0x94A8, 0x7551, 0x94A9, 0x7560, + 0x94AA, 0x516B, 0x94AB, 0x9262, 0x94AC, 0x6E8C, 0x94AD, 0x767A, 0x94AE, 0x9197, 0x94AF, 0x9AEA, 0x94B0, 0x4F10, 0x94B1, 0x7F70, + 0x94B2, 0x629C, 0x94B3, 0x7B4F, 0x94B4, 0x95A5, 0x94B5, 0x9CE9, 0x94B6, 0x567A, 0x94B7, 0x5859, 0x94B8, 0x86E4, 0x94B9, 0x96BC, + 0x94BA, 0x4F34, 0x94BB, 0x5224, 0x94BC, 0x534A, 0x94BD, 0x53CD, 0x94BE, 0x53DB, 0x94BF, 0x5E06, 0x94C0, 0x642C, 0x94C1, 0x6591, + 0x94C2, 0x677F, 0x94C3, 0x6C3E, 0x94C4, 0x6C4E, 0x94C5, 0x7248, 0x94C6, 0x72AF, 0x94C7, 0x73ED, 0x94C8, 0x7554, 0x94C9, 0x7E41, + 0x94CA, 0x822C, 0x94CB, 0x85E9, 0x94CC, 0x8CA9, 0x94CD, 0x7BC4, 0x94CE, 0x91C6, 0x94CF, 0x7169, 0x94D0, 0x9812, 0x94D1, 0x98EF, + 0x94D2, 0x633D, 0x94D3, 0x6669, 0x94D4, 0x756A, 0x94D5, 0x76E4, 0x94D6, 0x78D0, 0x94D7, 0x8543, 0x94D8, 0x86EE, 0x94D9, 0x532A, + 0x94DA, 0x5351, 0x94DB, 0x5426, 0x94DC, 0x5983, 0x94DD, 0x5E87, 0x94DE, 0x5F7C, 0x94DF, 0x60B2, 0x94E0, 0x6249, 0x94E1, 0x6279, + 0x94E2, 0x62AB, 0x94E3, 0x6590, 0x94E4, 0x6BD4, 0x94E5, 0x6CCC, 0x94E6, 0x75B2, 0x94E7, 0x76AE, 0x94E8, 0x7891, 0x94E9, 0x79D8, + 0x94EA, 0x7DCB, 0x94EB, 0x7F77, 0x94EC, 0x80A5, 0x94ED, 0x88AB, 0x94EE, 0x8AB9, 0x94EF, 0x8CBB, 0x94F0, 0x907F, 0x94F1, 0x975E, + 0x94F2, 0x98DB, 0x94F3, 0x6A0B, 0x94F4, 0x7C38, 0x94F5, 0x5099, 0x94F6, 0x5C3E, 0x94F7, 0x5FAE, 0x94F8, 0x6787, 0x94F9, 0x6BD8, + 0x94FA, 0x7435, 0x94FB, 0x7709, 0x94FC, 0x7F8E, 0x9540, 0x9F3B, 0x9541, 0x67CA, 0x9542, 0x7A17, 0x9543, 0x5339, 0x9544, 0x758B, + 0x9545, 0x9AED, 0x9546, 0x5F66, 0x9547, 0x819D, 0x9548, 0x83F1, 0x9549, 0x8098, 0x954A, 0x5F3C, 0x954B, 0x5FC5, 0x954C, 0x7562, + 0x954D, 0x7B46, 0x954E, 0x903C, 0x954F, 0x6867, 0x9550, 0x59EB, 0x9551, 0x5A9B, 0x9552, 0x7D10, 0x9553, 0x767E, 0x9554, 0x8B2C, + 0x9555, 0x4FF5, 0x9556, 0x5F6A, 0x9557, 0x6A19, 0x9558, 0x6C37, 0x9559, 0x6F02, 0x955A, 0x74E2, 0x955B, 0x7968, 0x955C, 0x8868, + 0x955D, 0x8A55, 0x955E, 0x8C79, 0x955F, 0x5EDF, 0x9560, 0x63CF, 0x9561, 0x75C5, 0x9562, 0x79D2, 0x9563, 0x82D7, 0x9564, 0x9328, + 0x9565, 0x92F2, 0x9566, 0x849C, 0x9567, 0x86ED, 0x9568, 0x9C2D, 0x9569, 0x54C1, 0x956A, 0x5F6C, 0x956B, 0x658C, 0x956C, 0x6D5C, + 0x956D, 0x7015, 0x956E, 0x8CA7, 0x956F, 0x8CD3, 0x9570, 0x983B, 0x9571, 0x654F, 0x9572, 0x74F6, 0x9573, 0x4E0D, 0x9574, 0x4ED8, + 0x9575, 0x57E0, 0x9576, 0x592B, 0x9577, 0x5A66, 0x9578, 0x5BCC, 0x9579, 0x51A8, 0x957A, 0x5E03, 0x957B, 0x5E9C, 0x957C, 0x6016, + 0x957D, 0x6276, 0x957E, 0x6577, 0x9580, 0x65A7, 0x9581, 0x666E, 0x9582, 0x6D6E, 0x9583, 0x7236, 0x9584, 0x7B26, 0x9585, 0x8150, + 0x9586, 0x819A, 0x9587, 0x8299, 0x9588, 0x8B5C, 0x9589, 0x8CA0, 0x958A, 0x8CE6, 0x958B, 0x8D74, 0x958C, 0x961C, 0x958D, 0x9644, + 0x958E, 0x4FAE, 0x958F, 0x64AB, 0x9590, 0x6B66, 0x9591, 0x821E, 0x9592, 0x8461, 0x9593, 0x856A, 0x9594, 0x90E8, 0x9595, 0x5C01, + 0x9596, 0x6953, 0x9597, 0x98A8, 0x9598, 0x847A, 0x9599, 0x8557, 0x959A, 0x4F0F, 0x959B, 0x526F, 0x959C, 0x5FA9, 0x959D, 0x5E45, + 0x959E, 0x670D, 0x959F, 0x798F, 0x95A0, 0x8179, 0x95A1, 0x8907, 0x95A2, 0x8986, 0x95A3, 0x6DF5, 0x95A4, 0x5F17, 0x95A5, 0x6255, + 0x95A6, 0x6CB8, 0x95A7, 0x4ECF, 0x95A8, 0x7269, 0x95A9, 0x9B92, 0x95AA, 0x5206, 0x95AB, 0x543B, 0x95AC, 0x5674, 0x95AD, 0x58B3, + 0x95AE, 0x61A4, 0x95AF, 0x626E, 0x95B0, 0x711A, 0x95B1, 0x596E, 0x95B2, 0x7C89, 0x95B3, 0x7CDE, 0x95B4, 0x7D1B, 0x95B5, 0x96F0, + 0x95B6, 0x6587, 0x95B7, 0x805E, 0x95B8, 0x4E19, 0x95B9, 0x4F75, 0x95BA, 0x5175, 0x95BB, 0x5840, 0x95BC, 0x5E63, 0x95BD, 0x5E73, + 0x95BE, 0x5F0A, 0x95BF, 0x67C4, 0x95C0, 0x4E26, 0x95C1, 0x853D, 0x95C2, 0x9589, 0x95C3, 0x965B, 0x95C4, 0x7C73, 0x95C5, 0x9801, + 0x95C6, 0x50FB, 0x95C7, 0x58C1, 0x95C8, 0x7656, 0x95C9, 0x78A7, 0x95CA, 0x5225, 0x95CB, 0x77A5, 0x95CC, 0x8511, 0x95CD, 0x7B86, + 0x95CE, 0x504F, 0x95CF, 0x5909, 0x95D0, 0x7247, 0x95D1, 0x7BC7, 0x95D2, 0x7DE8, 0x95D3, 0x8FBA, 0x95D4, 0x8FD4, 0x95D5, 0x904D, + 0x95D6, 0x4FBF, 0x95D7, 0x52C9, 0x95D8, 0x5A29, 0x95D9, 0x5F01, 0x95DA, 0x97AD, 0x95DB, 0x4FDD, 0x95DC, 0x8217, 0x95DD, 0x92EA, + 0x95DE, 0x5703, 0x95DF, 0x6355, 0x95E0, 0x6B69, 0x95E1, 0x752B, 0x95E2, 0x88DC, 0x95E3, 0x8F14, 0x95E4, 0x7A42, 0x95E5, 0x52DF, + 0x95E6, 0x5893, 0x95E7, 0x6155, 0x95E8, 0x620A, 0x95E9, 0x66AE, 0x95EA, 0x6BCD, 0x95EB, 0x7C3F, 0x95EC, 0x83E9, 0x95ED, 0x5023, + 0x95EE, 0x4FF8, 0x95EF, 0x5305, 0x95F0, 0x5446, 0x95F1, 0x5831, 0x95F2, 0x5949, 0x95F3, 0x5B9D, 0x95F4, 0x5CF0, 0x95F5, 0x5CEF, + 0x95F6, 0x5D29, 0x95F7, 0x5E96, 0x95F8, 0x62B1, 0x95F9, 0x6367, 0x95FA, 0x653E, 0x95FB, 0x65B9, 0x95FC, 0x670B, 0x9640, 0x6CD5, + 0x9641, 0x6CE1, 0x9642, 0x70F9, 0x9643, 0x7832, 0x9644, 0x7E2B, 0x9645, 0x80DE, 0x9646, 0x82B3, 0x9647, 0x840C, 0x9648, 0x84EC, + 0x9649, 0x8702, 0x964A, 0x8912, 0x964B, 0x8A2A, 0x964C, 0x8C4A, 0x964D, 0x90A6, 0x964E, 0x92D2, 0x964F, 0x98FD, 0x9650, 0x9CF3, + 0x9651, 0x9D6C, 0x9652, 0x4E4F, 0x9653, 0x4EA1, 0x9654, 0x508D, 0x9655, 0x5256, 0x9656, 0x574A, 0x9657, 0x59A8, 0x9658, 0x5E3D, + 0x9659, 0x5FD8, 0x965A, 0x5FD9, 0x965B, 0x623F, 0x965C, 0x66B4, 0x965D, 0x671B, 0x965E, 0x67D0, 0x965F, 0x68D2, 0x9660, 0x5192, + 0x9661, 0x7D21, 0x9662, 0x80AA, 0x9663, 0x81A8, 0x9664, 0x8B00, 0x9665, 0x8C8C, 0x9666, 0x8CBF, 0x9667, 0x927E, 0x9668, 0x9632, + 0x9669, 0x5420, 0x966A, 0x982C, 0x966B, 0x5317, 0x966C, 0x50D5, 0x966D, 0x535C, 0x966E, 0x58A8, 0x966F, 0x64B2, 0x9670, 0x6734, + 0x9671, 0x7267, 0x9672, 0x7766, 0x9673, 0x7A46, 0x9674, 0x91E6, 0x9675, 0x52C3, 0x9676, 0x6CA1, 0x9677, 0x6B86, 0x9678, 0x5800, + 0x9679, 0x5E4C, 0x967A, 0x5954, 0x967B, 0x672C, 0x967C, 0x7FFB, 0x967D, 0x51E1, 0x967E, 0x76C6, 0x9680, 0x6469, 0x9681, 0x78E8, + 0x9682, 0x9B54, 0x9683, 0x9EBB, 0x9684, 0x57CB, 0x9685, 0x59B9, 0x9686, 0x6627, 0x9687, 0x679A, 0x9688, 0x6BCE, 0x9689, 0x54E9, + 0x968A, 0x69D9, 0x968B, 0x5E55, 0x968C, 0x819C, 0x968D, 0x6795, 0x968E, 0x9BAA, 0x968F, 0x67FE, 0x9690, 0x9C52, 0x9691, 0x685D, + 0x9692, 0x4EA6, 0x9693, 0x4FE3, 0x9694, 0x53C8, 0x9695, 0x62B9, 0x9696, 0x672B, 0x9697, 0x6CAB, 0x9698, 0x8FC4, 0x9699, 0x4FAD, + 0x969A, 0x7E6D, 0x969B, 0x9EBF, 0x969C, 0x4E07, 0x969D, 0x6162, 0x969E, 0x6E80, 0x969F, 0x6F2B, 0x96A0, 0x8513, 0x96A1, 0x5473, + 0x96A2, 0x672A, 0x96A3, 0x9B45, 0x96A4, 0x5DF3, 0x96A5, 0x7B95, 0x96A6, 0x5CAC, 0x96A7, 0x5BC6, 0x96A8, 0x871C, 0x96A9, 0x6E4A, + 0x96AA, 0x84D1, 0x96AB, 0x7A14, 0x96AC, 0x8108, 0x96AD, 0x5999, 0x96AE, 0x7C8D, 0x96AF, 0x6C11, 0x96B0, 0x7720, 0x96B1, 0x52D9, + 0x96B2, 0x5922, 0x96B3, 0x7121, 0x96B4, 0x725F, 0x96B5, 0x77DB, 0x96B6, 0x9727, 0x96B7, 0x9D61, 0x96B8, 0x690B, 0x96B9, 0x5A7F, + 0x96BA, 0x5A18, 0x96BB, 0x51A5, 0x96BC, 0x540D, 0x96BD, 0x547D, 0x96BE, 0x660E, 0x96BF, 0x76DF, 0x96C0, 0x8FF7, 0x96C1, 0x9298, + 0x96C2, 0x9CF4, 0x96C3, 0x59EA, 0x96C4, 0x725D, 0x96C5, 0x6EC5, 0x96C6, 0x514D, 0x96C7, 0x68C9, 0x96C8, 0x7DBF, 0x96C9, 0x7DEC, + 0x96CA, 0x9762, 0x96CB, 0x9EBA, 0x96CC, 0x6478, 0x96CD, 0x6A21, 0x96CE, 0x8302, 0x96CF, 0x5984, 0x96D0, 0x5B5F, 0x96D1, 0x6BDB, + 0x96D2, 0x731B, 0x96D3, 0x76F2, 0x96D4, 0x7DB2, 0x96D5, 0x8017, 0x96D6, 0x8499, 0x96D7, 0x5132, 0x96D8, 0x6728, 0x96D9, 0x9ED9, + 0x96DA, 0x76EE, 0x96DB, 0x6762, 0x96DC, 0x52FF, 0x96DD, 0x9905, 0x96DE, 0x5C24, 0x96DF, 0x623B, 0x96E0, 0x7C7E, 0x96E1, 0x8CB0, + 0x96E2, 0x554F, 0x96E3, 0x60B6, 0x96E4, 0x7D0B, 0x96E5, 0x9580, 0x96E6, 0x5301, 0x96E7, 0x4E5F, 0x96E8, 0x51B6, 0x96E9, 0x591C, + 0x96EA, 0x723A, 0x96EB, 0x8036, 0x96EC, 0x91CE, 0x96ED, 0x5F25, 0x96EE, 0x77E2, 0x96EF, 0x5384, 0x96F0, 0x5F79, 0x96F1, 0x7D04, + 0x96F2, 0x85AC, 0x96F3, 0x8A33, 0x96F4, 0x8E8D, 0x96F5, 0x9756, 0x96F6, 0x67F3, 0x96F7, 0x85AE, 0x96F8, 0x9453, 0x96F9, 0x6109, + 0x96FA, 0x6108, 0x96FB, 0x6CB9, 0x96FC, 0x7652, 0x9740, 0x8AED, 0x9741, 0x8F38, 0x9742, 0x552F, 0x9743, 0x4F51, 0x9744, 0x512A, + 0x9745, 0x52C7, 0x9746, 0x53CB, 0x9747, 0x5BA5, 0x9748, 0x5E7D, 0x9749, 0x60A0, 0x974A, 0x6182, 0x974B, 0x63D6, 0x974C, 0x6709, + 0x974D, 0x67DA, 0x974E, 0x6E67, 0x974F, 0x6D8C, 0x9750, 0x7336, 0x9751, 0x7337, 0x9752, 0x7531, 0x9753, 0x7950, 0x9754, 0x88D5, + 0x9755, 0x8A98, 0x9756, 0x904A, 0x9757, 0x9091, 0x9758, 0x90F5, 0x9759, 0x96C4, 0x975A, 0x878D, 0x975B, 0x5915, 0x975C, 0x4E88, + 0x975D, 0x4F59, 0x975E, 0x4E0E, 0x975F, 0x8A89, 0x9760, 0x8F3F, 0x9761, 0x9810, 0x9762, 0x50AD, 0x9763, 0x5E7C, 0x9764, 0x5996, + 0x9765, 0x5BB9, 0x9766, 0x5EB8, 0x9767, 0x63DA, 0x9768, 0x63FA, 0x9769, 0x64C1, 0x976A, 0x66DC, 0x976B, 0x694A, 0x976C, 0x69D8, + 0x976D, 0x6D0B, 0x976E, 0x6EB6, 0x976F, 0x7194, 0x9770, 0x7528, 0x9771, 0x7AAF, 0x9772, 0x7F8A, 0x9773, 0x8000, 0x9774, 0x8449, + 0x9775, 0x84C9, 0x9776, 0x8981, 0x9777, 0x8B21, 0x9778, 0x8E0A, 0x9779, 0x9065, 0x977A, 0x967D, 0x977B, 0x990A, 0x977C, 0x617E, + 0x977D, 0x6291, 0x977E, 0x6B32, 0x9780, 0x6C83, 0x9781, 0x6D74, 0x9782, 0x7FCC, 0x9783, 0x7FFC, 0x9784, 0x6DC0, 0x9785, 0x7F85, + 0x9786, 0x87BA, 0x9787, 0x88F8, 0x9788, 0x6765, 0x9789, 0x83B1, 0x978A, 0x983C, 0x978B, 0x96F7, 0x978C, 0x6D1B, 0x978D, 0x7D61, + 0x978E, 0x843D, 0x978F, 0x916A, 0x9790, 0x4E71, 0x9791, 0x5375, 0x9792, 0x5D50, 0x9793, 0x6B04, 0x9794, 0x6FEB, 0x9795, 0x85CD, + 0x9796, 0x862D, 0x9797, 0x89A7, 0x9798, 0x5229, 0x9799, 0x540F, 0x979A, 0x5C65, 0x979B, 0x674E, 0x979C, 0x68A8, 0x979D, 0x7406, + 0x979E, 0x7483, 0x979F, 0x75E2, 0x97A0, 0x88CF, 0x97A1, 0x88E1, 0x97A2, 0x91CC, 0x97A3, 0x96E2, 0x97A4, 0x9678, 0x97A5, 0x5F8B, + 0x97A6, 0x7387, 0x97A7, 0x7ACB, 0x97A8, 0x844E, 0x97A9, 0x63A0, 0x97AA, 0x7565, 0x97AB, 0x5289, 0x97AC, 0x6D41, 0x97AD, 0x6E9C, + 0x97AE, 0x7409, 0x97AF, 0x7559, 0x97B0, 0x786B, 0x97B1, 0x7C92, 0x97B2, 0x9686, 0x97B3, 0x7ADC, 0x97B4, 0x9F8D, 0x97B5, 0x4FB6, + 0x97B6, 0x616E, 0x97B7, 0x65C5, 0x97B8, 0x865C, 0x97B9, 0x4E86, 0x97BA, 0x4EAE, 0x97BB, 0x50DA, 0x97BC, 0x4E21, 0x97BD, 0x51CC, + 0x97BE, 0x5BEE, 0x97BF, 0x6599, 0x97C0, 0x6881, 0x97C1, 0x6DBC, 0x97C2, 0x731F, 0x97C3, 0x7642, 0x97C4, 0x77AD, 0x97C5, 0x7A1C, + 0x97C6, 0x7CE7, 0x97C7, 0x826F, 0x97C8, 0x8AD2, 0x97C9, 0x907C, 0x97CA, 0x91CF, 0x97CB, 0x9675, 0x97CC, 0x9818, 0x97CD, 0x529B, + 0x97CE, 0x7DD1, 0x97CF, 0x502B, 0x97D0, 0x5398, 0x97D1, 0x6797, 0x97D2, 0x6DCB, 0x97D3, 0x71D0, 0x97D4, 0x7433, 0x97D5, 0x81E8, + 0x97D6, 0x8F2A, 0x97D7, 0x96A3, 0x97D8, 0x9C57, 0x97D9, 0x9E9F, 0x97DA, 0x7460, 0x97DB, 0x5841, 0x97DC, 0x6D99, 0x97DD, 0x7D2F, + 0x97DE, 0x985E, 0x97DF, 0x4EE4, 0x97E0, 0x4F36, 0x97E1, 0x4F8B, 0x97E2, 0x51B7, 0x97E3, 0x52B1, 0x97E4, 0x5DBA, 0x97E5, 0x601C, + 0x97E6, 0x73B2, 0x97E7, 0x793C, 0x97E8, 0x82D3, 0x97E9, 0x9234, 0x97EA, 0x96B7, 0x97EB, 0x96F6, 0x97EC, 0x970A, 0x97ED, 0x9E97, + 0x97EE, 0x9F62, 0x97EF, 0x66A6, 0x97F0, 0x6B74, 0x97F1, 0x5217, 0x97F2, 0x52A3, 0x97F3, 0x70C8, 0x97F4, 0x88C2, 0x97F5, 0x5EC9, + 0x97F6, 0x604B, 0x97F7, 0x6190, 0x97F8, 0x6F23, 0x97F9, 0x7149, 0x97FA, 0x7C3E, 0x97FB, 0x7DF4, 0x97FC, 0x806F, 0x9840, 0x84EE, + 0x9841, 0x9023, 0x9842, 0x932C, 0x9843, 0x5442, 0x9844, 0x9B6F, 0x9845, 0x6AD3, 0x9846, 0x7089, 0x9847, 0x8CC2, 0x9848, 0x8DEF, + 0x9849, 0x9732, 0x984A, 0x52B4, 0x984B, 0x5A41, 0x984C, 0x5ECA, 0x984D, 0x5F04, 0x984E, 0x6717, 0x984F, 0x697C, 0x9850, 0x6994, + 0x9851, 0x6D6A, 0x9852, 0x6F0F, 0x9853, 0x7262, 0x9854, 0x72FC, 0x9855, 0x7BED, 0x9856, 0x8001, 0x9857, 0x807E, 0x9858, 0x874B, + 0x9859, 0x90CE, 0x985A, 0x516D, 0x985B, 0x9E93, 0x985C, 0x7984, 0x985D, 0x808B, 0x985E, 0x9332, 0x985F, 0x8AD6, 0x9860, 0x502D, + 0x9861, 0x548C, 0x9862, 0x8A71, 0x9863, 0x6B6A, 0x9864, 0x8CC4, 0x9865, 0x8107, 0x9866, 0x60D1, 0x9867, 0x67A0, 0x9868, 0x9DF2, + 0x9869, 0x4E99, 0x986A, 0x4E98, 0x986B, 0x9C10, 0x986C, 0x8A6B, 0x986D, 0x85C1, 0x986E, 0x8568, 0x986F, 0x6900, 0x9870, 0x6E7E, + 0x9871, 0x7897, 0x9872, 0x8155, 0x989F, 0x5F0C, 0x98A0, 0x4E10, 0x98A1, 0x4E15, 0x98A2, 0x4E2A, 0x98A3, 0x4E31, 0x98A4, 0x4E36, + 0x98A5, 0x4E3C, 0x98A6, 0x4E3F, 0x98A7, 0x4E42, 0x98A8, 0x4E56, 0x98A9, 0x4E58, 0x98AA, 0x4E82, 0x98AB, 0x4E85, 0x98AC, 0x8C6B, + 0x98AD, 0x4E8A, 0x98AE, 0x8212, 0x98AF, 0x5F0D, 0x98B0, 0x4E8E, 0x98B1, 0x4E9E, 0x98B2, 0x4E9F, 0x98B3, 0x4EA0, 0x98B4, 0x4EA2, + 0x98B5, 0x4EB0, 0x98B6, 0x4EB3, 0x98B7, 0x4EB6, 0x98B8, 0x4ECE, 0x98B9, 0x4ECD, 0x98BA, 0x4EC4, 0x98BB, 0x4EC6, 0x98BC, 0x4EC2, + 0x98BD, 0x4ED7, 0x98BE, 0x4EDE, 0x98BF, 0x4EED, 0x98C0, 0x4EDF, 0x98C1, 0x4EF7, 0x98C2, 0x4F09, 0x98C3, 0x4F5A, 0x98C4, 0x4F30, + 0x98C5, 0x4F5B, 0x98C6, 0x4F5D, 0x98C7, 0x4F57, 0x98C8, 0x4F47, 0x98C9, 0x4F76, 0x98CA, 0x4F88, 0x98CB, 0x4F8F, 0x98CC, 0x4F98, + 0x98CD, 0x4F7B, 0x98CE, 0x4F69, 0x98CF, 0x4F70, 0x98D0, 0x4F91, 0x98D1, 0x4F6F, 0x98D2, 0x4F86, 0x98D3, 0x4F96, 0x98D4, 0x5118, + 0x98D5, 0x4FD4, 0x98D6, 0x4FDF, 0x98D7, 0x4FCE, 0x98D8, 0x4FD8, 0x98D9, 0x4FDB, 0x98DA, 0x4FD1, 0x98DB, 0x4FDA, 0x98DC, 0x4FD0, + 0x98DD, 0x4FE4, 0x98DE, 0x4FE5, 0x98DF, 0x501A, 0x98E0, 0x5028, 0x98E1, 0x5014, 0x98E2, 0x502A, 0x98E3, 0x5025, 0x98E4, 0x5005, + 0x98E5, 0x4F1C, 0x98E6, 0x4FF6, 0x98E7, 0x5021, 0x98E8, 0x5029, 0x98E9, 0x502C, 0x98EA, 0x4FFE, 0x98EB, 0x4FEF, 0x98EC, 0x5011, + 0x98ED, 0x5006, 0x98EE, 0x5043, 0x98EF, 0x5047, 0x98F0, 0x6703, 0x98F1, 0x5055, 0x98F2, 0x5050, 0x98F3, 0x5048, 0x98F4, 0x505A, + 0x98F5, 0x5056, 0x98F6, 0x506C, 0x98F7, 0x5078, 0x98F8, 0x5080, 0x98F9, 0x509A, 0x98FA, 0x5085, 0x98FB, 0x50B4, 0x98FC, 0x50B2, + 0x9940, 0x50C9, 0x9941, 0x50CA, 0x9942, 0x50B3, 0x9943, 0x50C2, 0x9944, 0x50D6, 0x9945, 0x50DE, 0x9946, 0x50E5, 0x9947, 0x50ED, + 0x9948, 0x50E3, 0x9949, 0x50EE, 0x994A, 0x50F9, 0x994B, 0x50F5, 0x994C, 0x5109, 0x994D, 0x5101, 0x994E, 0x5102, 0x994F, 0x5116, + 0x9950, 0x5115, 0x9951, 0x5114, 0x9952, 0x511A, 0x9953, 0x5121, 0x9954, 0x513A, 0x9955, 0x5137, 0x9956, 0x513C, 0x9957, 0x513B, + 0x9958, 0x513F, 0x9959, 0x5140, 0x995A, 0x5152, 0x995B, 0x514C, 0x995C, 0x5154, 0x995D, 0x5162, 0x995E, 0x7AF8, 0x995F, 0x5169, + 0x9960, 0x516A, 0x9961, 0x516E, 0x9962, 0x5180, 0x9963, 0x5182, 0x9964, 0x56D8, 0x9965, 0x518C, 0x9966, 0x5189, 0x9967, 0x518F, + 0x9968, 0x5191, 0x9969, 0x5193, 0x996A, 0x5195, 0x996B, 0x5196, 0x996C, 0x51A4, 0x996D, 0x51A6, 0x996E, 0x51A2, 0x996F, 0x51A9, + 0x9970, 0x51AA, 0x9971, 0x51AB, 0x9972, 0x51B3, 0x9973, 0x51B1, 0x9974, 0x51B2, 0x9975, 0x51B0, 0x9976, 0x51B5, 0x9977, 0x51BD, + 0x9978, 0x51C5, 0x9979, 0x51C9, 0x997A, 0x51DB, 0x997B, 0x51E0, 0x997C, 0x8655, 0x997D, 0x51E9, 0x997E, 0x51ED, 0x9980, 0x51F0, + 0x9981, 0x51F5, 0x9982, 0x51FE, 0x9983, 0x5204, 0x9984, 0x520B, 0x9985, 0x5214, 0x9986, 0x520E, 0x9987, 0x5227, 0x9988, 0x522A, + 0x9989, 0x522E, 0x998A, 0x5233, 0x998B, 0x5239, 0x998C, 0x524F, 0x998D, 0x5244, 0x998E, 0x524B, 0x998F, 0x524C, 0x9990, 0x525E, + 0x9991, 0x5254, 0x9992, 0x526A, 0x9993, 0x5274, 0x9994, 0x5269, 0x9995, 0x5273, 0x9996, 0x527F, 0x9997, 0x527D, 0x9998, 0x528D, + 0x9999, 0x5294, 0x999A, 0x5292, 0x999B, 0x5271, 0x999C, 0x5288, 0x999D, 0x5291, 0x999E, 0x8FA8, 0x999F, 0x8FA7, 0x99A0, 0x52AC, + 0x99A1, 0x52AD, 0x99A2, 0x52BC, 0x99A3, 0x52B5, 0x99A4, 0x52C1, 0x99A5, 0x52CD, 0x99A6, 0x52D7, 0x99A7, 0x52DE, 0x99A8, 0x52E3, + 0x99A9, 0x52E6, 0x99AA, 0x98ED, 0x99AB, 0x52E0, 0x99AC, 0x52F3, 0x99AD, 0x52F5, 0x99AE, 0x52F8, 0x99AF, 0x52F9, 0x99B0, 0x5306, + 0x99B1, 0x5308, 0x99B2, 0x7538, 0x99B3, 0x530D, 0x99B4, 0x5310, 0x99B5, 0x530F, 0x99B6, 0x5315, 0x99B7, 0x531A, 0x99B8, 0x5323, + 0x99B9, 0x532F, 0x99BA, 0x5331, 0x99BB, 0x5333, 0x99BC, 0x5338, 0x99BD, 0x5340, 0x99BE, 0x5346, 0x99BF, 0x5345, 0x99C0, 0x4E17, + 0x99C1, 0x5349, 0x99C2, 0x534D, 0x99C3, 0x51D6, 0x99C4, 0x535E, 0x99C5, 0x5369, 0x99C6, 0x536E, 0x99C7, 0x5918, 0x99C8, 0x537B, + 0x99C9, 0x5377, 0x99CA, 0x5382, 0x99CB, 0x5396, 0x99CC, 0x53A0, 0x99CD, 0x53A6, 0x99CE, 0x53A5, 0x99CF, 0x53AE, 0x99D0, 0x53B0, + 0x99D1, 0x53B6, 0x99D2, 0x53C3, 0x99D3, 0x7C12, 0x99D4, 0x96D9, 0x99D5, 0x53DF, 0x99D6, 0x66FC, 0x99D7, 0x71EE, 0x99D8, 0x53EE, + 0x99D9, 0x53E8, 0x99DA, 0x53ED, 0x99DB, 0x53FA, 0x99DC, 0x5401, 0x99DD, 0x543D, 0x99DE, 0x5440, 0x99DF, 0x542C, 0x99E0, 0x542D, + 0x99E1, 0x543C, 0x99E2, 0x542E, 0x99E3, 0x5436, 0x99E4, 0x5429, 0x99E5, 0x541D, 0x99E6, 0x544E, 0x99E7, 0x548F, 0x99E8, 0x5475, + 0x99E9, 0x548E, 0x99EA, 0x545F, 0x99EB, 0x5471, 0x99EC, 0x5477, 0x99ED, 0x5470, 0x99EE, 0x5492, 0x99EF, 0x547B, 0x99F0, 0x5480, + 0x99F1, 0x5476, 0x99F2, 0x5484, 0x99F3, 0x5490, 0x99F4, 0x5486, 0x99F5, 0x54C7, 0x99F6, 0x54A2, 0x99F7, 0x54B8, 0x99F8, 0x54A5, + 0x99F9, 0x54AC, 0x99FA, 0x54C4, 0x99FB, 0x54C8, 0x99FC, 0x54A8, 0x9A40, 0x54AB, 0x9A41, 0x54C2, 0x9A42, 0x54A4, 0x9A43, 0x54BE, + 0x9A44, 0x54BC, 0x9A45, 0x54D8, 0x9A46, 0x54E5, 0x9A47, 0x54E6, 0x9A48, 0x550F, 0x9A49, 0x5514, 0x9A4A, 0x54FD, 0x9A4B, 0x54EE, + 0x9A4C, 0x54ED, 0x9A4D, 0x54FA, 0x9A4E, 0x54E2, 0x9A4F, 0x5539, 0x9A50, 0x5540, 0x9A51, 0x5563, 0x9A52, 0x554C, 0x9A53, 0x552E, + 0x9A54, 0x555C, 0x9A55, 0x5545, 0x9A56, 0x5556, 0x9A57, 0x5557, 0x9A58, 0x5538, 0x9A59, 0x5533, 0x9A5A, 0x555D, 0x9A5B, 0x5599, + 0x9A5C, 0x5580, 0x9A5D, 0x54AF, 0x9A5E, 0x558A, 0x9A5F, 0x559F, 0x9A60, 0x557B, 0x9A61, 0x557E, 0x9A62, 0x5598, 0x9A63, 0x559E, + 0x9A64, 0x55AE, 0x9A65, 0x557C, 0x9A66, 0x5583, 0x9A67, 0x55A9, 0x9A68, 0x5587, 0x9A69, 0x55A8, 0x9A6A, 0x55DA, 0x9A6B, 0x55C5, + 0x9A6C, 0x55DF, 0x9A6D, 0x55C4, 0x9A6E, 0x55DC, 0x9A6F, 0x55E4, 0x9A70, 0x55D4, 0x9A71, 0x5614, 0x9A72, 0x55F7, 0x9A73, 0x5616, + 0x9A74, 0x55FE, 0x9A75, 0x55FD, 0x9A76, 0x561B, 0x9A77, 0x55F9, 0x9A78, 0x564E, 0x9A79, 0x5650, 0x9A7A, 0x71DF, 0x9A7B, 0x5634, + 0x9A7C, 0x5636, 0x9A7D, 0x5632, 0x9A7E, 0x5638, 0x9A80, 0x566B, 0x9A81, 0x5664, 0x9A82, 0x562F, 0x9A83, 0x566C, 0x9A84, 0x566A, + 0x9A85, 0x5686, 0x9A86, 0x5680, 0x9A87, 0x568A, 0x9A88, 0x56A0, 0x9A89, 0x5694, 0x9A8A, 0x568F, 0x9A8B, 0x56A5, 0x9A8C, 0x56AE, + 0x9A8D, 0x56B6, 0x9A8E, 0x56B4, 0x9A8F, 0x56C2, 0x9A90, 0x56BC, 0x9A91, 0x56C1, 0x9A92, 0x56C3, 0x9A93, 0x56C0, 0x9A94, 0x56C8, + 0x9A95, 0x56CE, 0x9A96, 0x56D1, 0x9A97, 0x56D3, 0x9A98, 0x56D7, 0x9A99, 0x56EE, 0x9A9A, 0x56F9, 0x9A9B, 0x5700, 0x9A9C, 0x56FF, + 0x9A9D, 0x5704, 0x9A9E, 0x5709, 0x9A9F, 0x5708, 0x9AA0, 0x570B, 0x9AA1, 0x570D, 0x9AA2, 0x5713, 0x9AA3, 0x5718, 0x9AA4, 0x5716, + 0x9AA5, 0x55C7, 0x9AA6, 0x571C, 0x9AA7, 0x5726, 0x9AA8, 0x5737, 0x9AA9, 0x5738, 0x9AAA, 0x574E, 0x9AAB, 0x573B, 0x9AAC, 0x5740, + 0x9AAD, 0x574F, 0x9AAE, 0x5769, 0x9AAF, 0x57C0, 0x9AB0, 0x5788, 0x9AB1, 0x5761, 0x9AB2, 0x577F, 0x9AB3, 0x5789, 0x9AB4, 0x5793, + 0x9AB5, 0x57A0, 0x9AB6, 0x57B3, 0x9AB7, 0x57A4, 0x9AB8, 0x57AA, 0x9AB9, 0x57B0, 0x9ABA, 0x57C3, 0x9ABB, 0x57C6, 0x9ABC, 0x57D4, + 0x9ABD, 0x57D2, 0x9ABE, 0x57D3, 0x9ABF, 0x580A, 0x9AC0, 0x57D6, 0x9AC1, 0x57E3, 0x9AC2, 0x580B, 0x9AC3, 0x5819, 0x9AC4, 0x581D, + 0x9AC5, 0x5872, 0x9AC6, 0x5821, 0x9AC7, 0x5862, 0x9AC8, 0x584B, 0x9AC9, 0x5870, 0x9ACA, 0x6BC0, 0x9ACB, 0x5852, 0x9ACC, 0x583D, + 0x9ACD, 0x5879, 0x9ACE, 0x5885, 0x9ACF, 0x58B9, 0x9AD0, 0x589F, 0x9AD1, 0x58AB, 0x9AD2, 0x58BA, 0x9AD3, 0x58DE, 0x9AD4, 0x58BB, + 0x9AD5, 0x58B8, 0x9AD6, 0x58AE, 0x9AD7, 0x58C5, 0x9AD8, 0x58D3, 0x9AD9, 0x58D1, 0x9ADA, 0x58D7, 0x9ADB, 0x58D9, 0x9ADC, 0x58D8, + 0x9ADD, 0x58E5, 0x9ADE, 0x58DC, 0x9ADF, 0x58E4, 0x9AE0, 0x58DF, 0x9AE1, 0x58EF, 0x9AE2, 0x58FA, 0x9AE3, 0x58F9, 0x9AE4, 0x58FB, + 0x9AE5, 0x58FC, 0x9AE6, 0x58FD, 0x9AE7, 0x5902, 0x9AE8, 0x590A, 0x9AE9, 0x5910, 0x9AEA, 0x591B, 0x9AEB, 0x68A6, 0x9AEC, 0x5925, + 0x9AED, 0x592C, 0x9AEE, 0x592D, 0x9AEF, 0x5932, 0x9AF0, 0x5938, 0x9AF1, 0x593E, 0x9AF2, 0x7AD2, 0x9AF3, 0x5955, 0x9AF4, 0x5950, + 0x9AF5, 0x594E, 0x9AF6, 0x595A, 0x9AF7, 0x5958, 0x9AF8, 0x5962, 0x9AF9, 0x5960, 0x9AFA, 0x5967, 0x9AFB, 0x596C, 0x9AFC, 0x5969, + 0x9B40, 0x5978, 0x9B41, 0x5981, 0x9B42, 0x599D, 0x9B43, 0x4F5E, 0x9B44, 0x4FAB, 0x9B45, 0x59A3, 0x9B46, 0x59B2, 0x9B47, 0x59C6, + 0x9B48, 0x59E8, 0x9B49, 0x59DC, 0x9B4A, 0x598D, 0x9B4B, 0x59D9, 0x9B4C, 0x59DA, 0x9B4D, 0x5A25, 0x9B4E, 0x5A1F, 0x9B4F, 0x5A11, + 0x9B50, 0x5A1C, 0x9B51, 0x5A09, 0x9B52, 0x5A1A, 0x9B53, 0x5A40, 0x9B54, 0x5A6C, 0x9B55, 0x5A49, 0x9B56, 0x5A35, 0x9B57, 0x5A36, + 0x9B58, 0x5A62, 0x9B59, 0x5A6A, 0x9B5A, 0x5A9A, 0x9B5B, 0x5ABC, 0x9B5C, 0x5ABE, 0x9B5D, 0x5ACB, 0x9B5E, 0x5AC2, 0x9B5F, 0x5ABD, + 0x9B60, 0x5AE3, 0x9B61, 0x5AD7, 0x9B62, 0x5AE6, 0x9B63, 0x5AE9, 0x9B64, 0x5AD6, 0x9B65, 0x5AFA, 0x9B66, 0x5AFB, 0x9B67, 0x5B0C, + 0x9B68, 0x5B0B, 0x9B69, 0x5B16, 0x9B6A, 0x5B32, 0x9B6B, 0x5AD0, 0x9B6C, 0x5B2A, 0x9B6D, 0x5B36, 0x9B6E, 0x5B3E, 0x9B6F, 0x5B43, + 0x9B70, 0x5B45, 0x9B71, 0x5B40, 0x9B72, 0x5B51, 0x9B73, 0x5B55, 0x9B74, 0x5B5A, 0x9B75, 0x5B5B, 0x9B76, 0x5B65, 0x9B77, 0x5B69, + 0x9B78, 0x5B70, 0x9B79, 0x5B73, 0x9B7A, 0x5B75, 0x9B7B, 0x5B78, 0x9B7C, 0x6588, 0x9B7D, 0x5B7A, 0x9B7E, 0x5B80, 0x9B80, 0x5B83, + 0x9B81, 0x5BA6, 0x9B82, 0x5BB8, 0x9B83, 0x5BC3, 0x9B84, 0x5BC7, 0x9B85, 0x5BC9, 0x9B86, 0x5BD4, 0x9B87, 0x5BD0, 0x9B88, 0x5BE4, + 0x9B89, 0x5BE6, 0x9B8A, 0x5BE2, 0x9B8B, 0x5BDE, 0x9B8C, 0x5BE5, 0x9B8D, 0x5BEB, 0x9B8E, 0x5BF0, 0x9B8F, 0x5BF6, 0x9B90, 0x5BF3, + 0x9B91, 0x5C05, 0x9B92, 0x5C07, 0x9B93, 0x5C08, 0x9B94, 0x5C0D, 0x9B95, 0x5C13, 0x9B96, 0x5C20, 0x9B97, 0x5C22, 0x9B98, 0x5C28, + 0x9B99, 0x5C38, 0x9B9A, 0x5C39, 0x9B9B, 0x5C41, 0x9B9C, 0x5C46, 0x9B9D, 0x5C4E, 0x9B9E, 0x5C53, 0x9B9F, 0x5C50, 0x9BA0, 0x5C4F, + 0x9BA1, 0x5B71, 0x9BA2, 0x5C6C, 0x9BA3, 0x5C6E, 0x9BA4, 0x4E62, 0x9BA5, 0x5C76, 0x9BA6, 0x5C79, 0x9BA7, 0x5C8C, 0x9BA8, 0x5C91, + 0x9BA9, 0x5C94, 0x9BAA, 0x599B, 0x9BAB, 0x5CAB, 0x9BAC, 0x5CBB, 0x9BAD, 0x5CB6, 0x9BAE, 0x5CBC, 0x9BAF, 0x5CB7, 0x9BB0, 0x5CC5, + 0x9BB1, 0x5CBE, 0x9BB2, 0x5CC7, 0x9BB3, 0x5CD9, 0x9BB4, 0x5CE9, 0x9BB5, 0x5CFD, 0x9BB6, 0x5CFA, 0x9BB7, 0x5CED, 0x9BB8, 0x5D8C, + 0x9BB9, 0x5CEA, 0x9BBA, 0x5D0B, 0x9BBB, 0x5D15, 0x9BBC, 0x5D17, 0x9BBD, 0x5D5C, 0x9BBE, 0x5D1F, 0x9BBF, 0x5D1B, 0x9BC0, 0x5D11, + 0x9BC1, 0x5D14, 0x9BC2, 0x5D22, 0x9BC3, 0x5D1A, 0x9BC4, 0x5D19, 0x9BC5, 0x5D18, 0x9BC6, 0x5D4C, 0x9BC7, 0x5D52, 0x9BC8, 0x5D4E, + 0x9BC9, 0x5D4B, 0x9BCA, 0x5D6C, 0x9BCB, 0x5D73, 0x9BCC, 0x5D76, 0x9BCD, 0x5D87, 0x9BCE, 0x5D84, 0x9BCF, 0x5D82, 0x9BD0, 0x5DA2, + 0x9BD1, 0x5D9D, 0x9BD2, 0x5DAC, 0x9BD3, 0x5DAE, 0x9BD4, 0x5DBD, 0x9BD5, 0x5D90, 0x9BD6, 0x5DB7, 0x9BD7, 0x5DBC, 0x9BD8, 0x5DC9, + 0x9BD9, 0x5DCD, 0x9BDA, 0x5DD3, 0x9BDB, 0x5DD2, 0x9BDC, 0x5DD6, 0x9BDD, 0x5DDB, 0x9BDE, 0x5DEB, 0x9BDF, 0x5DF2, 0x9BE0, 0x5DF5, + 0x9BE1, 0x5E0B, 0x9BE2, 0x5E1A, 0x9BE3, 0x5E19, 0x9BE4, 0x5E11, 0x9BE5, 0x5E1B, 0x9BE6, 0x5E36, 0x9BE7, 0x5E37, 0x9BE8, 0x5E44, + 0x9BE9, 0x5E43, 0x9BEA, 0x5E40, 0x9BEB, 0x5E4E, 0x9BEC, 0x5E57, 0x9BED, 0x5E54, 0x9BEE, 0x5E5F, 0x9BEF, 0x5E62, 0x9BF0, 0x5E64, + 0x9BF1, 0x5E47, 0x9BF2, 0x5E75, 0x9BF3, 0x5E76, 0x9BF4, 0x5E7A, 0x9BF5, 0x9EBC, 0x9BF6, 0x5E7F, 0x9BF7, 0x5EA0, 0x9BF8, 0x5EC1, + 0x9BF9, 0x5EC2, 0x9BFA, 0x5EC8, 0x9BFB, 0x5ED0, 0x9BFC, 0x5ECF, 0x9C40, 0x5ED6, 0x9C41, 0x5EE3, 0x9C42, 0x5EDD, 0x9C43, 0x5EDA, + 0x9C44, 0x5EDB, 0x9C45, 0x5EE2, 0x9C46, 0x5EE1, 0x9C47, 0x5EE8, 0x9C48, 0x5EE9, 0x9C49, 0x5EEC, 0x9C4A, 0x5EF1, 0x9C4B, 0x5EF3, + 0x9C4C, 0x5EF0, 0x9C4D, 0x5EF4, 0x9C4E, 0x5EF8, 0x9C4F, 0x5EFE, 0x9C50, 0x5F03, 0x9C51, 0x5F09, 0x9C52, 0x5F5D, 0x9C53, 0x5F5C, + 0x9C54, 0x5F0B, 0x9C55, 0x5F11, 0x9C56, 0x5F16, 0x9C57, 0x5F29, 0x9C58, 0x5F2D, 0x9C59, 0x5F38, 0x9C5A, 0x5F41, 0x9C5B, 0x5F48, + 0x9C5C, 0x5F4C, 0x9C5D, 0x5F4E, 0x9C5E, 0x5F2F, 0x9C5F, 0x5F51, 0x9C60, 0x5F56, 0x9C61, 0x5F57, 0x9C62, 0x5F59, 0x9C63, 0x5F61, + 0x9C64, 0x5F6D, 0x9C65, 0x5F73, 0x9C66, 0x5F77, 0x9C67, 0x5F83, 0x9C68, 0x5F82, 0x9C69, 0x5F7F, 0x9C6A, 0x5F8A, 0x9C6B, 0x5F88, + 0x9C6C, 0x5F91, 0x9C6D, 0x5F87, 0x9C6E, 0x5F9E, 0x9C6F, 0x5F99, 0x9C70, 0x5F98, 0x9C71, 0x5FA0, 0x9C72, 0x5FA8, 0x9C73, 0x5FAD, + 0x9C74, 0x5FBC, 0x9C75, 0x5FD6, 0x9C76, 0x5FFB, 0x9C77, 0x5FE4, 0x9C78, 0x5FF8, 0x9C79, 0x5FF1, 0x9C7A, 0x5FDD, 0x9C7B, 0x60B3, + 0x9C7C, 0x5FFF, 0x9C7D, 0x6021, 0x9C7E, 0x6060, 0x9C80, 0x6019, 0x9C81, 0x6010, 0x9C82, 0x6029, 0x9C83, 0x600E, 0x9C84, 0x6031, + 0x9C85, 0x601B, 0x9C86, 0x6015, 0x9C87, 0x602B, 0x9C88, 0x6026, 0x9C89, 0x600F, 0x9C8A, 0x603A, 0x9C8B, 0x605A, 0x9C8C, 0x6041, + 0x9C8D, 0x606A, 0x9C8E, 0x6077, 0x9C8F, 0x605F, 0x9C90, 0x604A, 0x9C91, 0x6046, 0x9C92, 0x604D, 0x9C93, 0x6063, 0x9C94, 0x6043, + 0x9C95, 0x6064, 0x9C96, 0x6042, 0x9C97, 0x606C, 0x9C98, 0x606B, 0x9C99, 0x6059, 0x9C9A, 0x6081, 0x9C9B, 0x608D, 0x9C9C, 0x60E7, + 0x9C9D, 0x6083, 0x9C9E, 0x609A, 0x9C9F, 0x6084, 0x9CA0, 0x609B, 0x9CA1, 0x6096, 0x9CA2, 0x6097, 0x9CA3, 0x6092, 0x9CA4, 0x60A7, + 0x9CA5, 0x608B, 0x9CA6, 0x60E1, 0x9CA7, 0x60B8, 0x9CA8, 0x60E0, 0x9CA9, 0x60D3, 0x9CAA, 0x60B4, 0x9CAB, 0x5FF0, 0x9CAC, 0x60BD, + 0x9CAD, 0x60C6, 0x9CAE, 0x60B5, 0x9CAF, 0x60D8, 0x9CB0, 0x614D, 0x9CB1, 0x6115, 0x9CB2, 0x6106, 0x9CB3, 0x60F6, 0x9CB4, 0x60F7, + 0x9CB5, 0x6100, 0x9CB6, 0x60F4, 0x9CB7, 0x60FA, 0x9CB8, 0x6103, 0x9CB9, 0x6121, 0x9CBA, 0x60FB, 0x9CBB, 0x60F1, 0x9CBC, 0x610D, + 0x9CBD, 0x610E, 0x9CBE, 0x6147, 0x9CBF, 0x613E, 0x9CC0, 0x6128, 0x9CC1, 0x6127, 0x9CC2, 0x614A, 0x9CC3, 0x613F, 0x9CC4, 0x613C, + 0x9CC5, 0x612C, 0x9CC6, 0x6134, 0x9CC7, 0x613D, 0x9CC8, 0x6142, 0x9CC9, 0x6144, 0x9CCA, 0x6173, 0x9CCB, 0x6177, 0x9CCC, 0x6158, + 0x9CCD, 0x6159, 0x9CCE, 0x615A, 0x9CCF, 0x616B, 0x9CD0, 0x6174, 0x9CD1, 0x616F, 0x9CD2, 0x6165, 0x9CD3, 0x6171, 0x9CD4, 0x615F, + 0x9CD5, 0x615D, 0x9CD6, 0x6153, 0x9CD7, 0x6175, 0x9CD8, 0x6199, 0x9CD9, 0x6196, 0x9CDA, 0x6187, 0x9CDB, 0x61AC, 0x9CDC, 0x6194, + 0x9CDD, 0x619A, 0x9CDE, 0x618A, 0x9CDF, 0x6191, 0x9CE0, 0x61AB, 0x9CE1, 0x61AE, 0x9CE2, 0x61CC, 0x9CE3, 0x61CA, 0x9CE4, 0x61C9, + 0x9CE5, 0x61F7, 0x9CE6, 0x61C8, 0x9CE7, 0x61C3, 0x9CE8, 0x61C6, 0x9CE9, 0x61BA, 0x9CEA, 0x61CB, 0x9CEB, 0x7F79, 0x9CEC, 0x61CD, + 0x9CED, 0x61E6, 0x9CEE, 0x61E3, 0x9CEF, 0x61F6, 0x9CF0, 0x61FA, 0x9CF1, 0x61F4, 0x9CF2, 0x61FF, 0x9CF3, 0x61FD, 0x9CF4, 0x61FC, + 0x9CF5, 0x61FE, 0x9CF6, 0x6200, 0x9CF7, 0x6208, 0x9CF8, 0x6209, 0x9CF9, 0x620D, 0x9CFA, 0x620C, 0x9CFB, 0x6214, 0x9CFC, 0x621B, + 0x9D40, 0x621E, 0x9D41, 0x6221, 0x9D42, 0x622A, 0x9D43, 0x622E, 0x9D44, 0x6230, 0x9D45, 0x6232, 0x9D46, 0x6233, 0x9D47, 0x6241, + 0x9D48, 0x624E, 0x9D49, 0x625E, 0x9D4A, 0x6263, 0x9D4B, 0x625B, 0x9D4C, 0x6260, 0x9D4D, 0x6268, 0x9D4E, 0x627C, 0x9D4F, 0x6282, + 0x9D50, 0x6289, 0x9D51, 0x627E, 0x9D52, 0x6292, 0x9D53, 0x6293, 0x9D54, 0x6296, 0x9D55, 0x62D4, 0x9D56, 0x6283, 0x9D57, 0x6294, + 0x9D58, 0x62D7, 0x9D59, 0x62D1, 0x9D5A, 0x62BB, 0x9D5B, 0x62CF, 0x9D5C, 0x62FF, 0x9D5D, 0x62C6, 0x9D5E, 0x64D4, 0x9D5F, 0x62C8, + 0x9D60, 0x62DC, 0x9D61, 0x62CC, 0x9D62, 0x62CA, 0x9D63, 0x62C2, 0x9D64, 0x62C7, 0x9D65, 0x629B, 0x9D66, 0x62C9, 0x9D67, 0x630C, + 0x9D68, 0x62EE, 0x9D69, 0x62F1, 0x9D6A, 0x6327, 0x9D6B, 0x6302, 0x9D6C, 0x6308, 0x9D6D, 0x62EF, 0x9D6E, 0x62F5, 0x9D6F, 0x6350, + 0x9D70, 0x633E, 0x9D71, 0x634D, 0x9D72, 0x641C, 0x9D73, 0x634F, 0x9D74, 0x6396, 0x9D75, 0x638E, 0x9D76, 0x6380, 0x9D77, 0x63AB, + 0x9D78, 0x6376, 0x9D79, 0x63A3, 0x9D7A, 0x638F, 0x9D7B, 0x6389, 0x9D7C, 0x639F, 0x9D7D, 0x63B5, 0x9D7E, 0x636B, 0x9D80, 0x6369, + 0x9D81, 0x63BE, 0x9D82, 0x63E9, 0x9D83, 0x63C0, 0x9D84, 0x63C6, 0x9D85, 0x63E3, 0x9D86, 0x63C9, 0x9D87, 0x63D2, 0x9D88, 0x63F6, + 0x9D89, 0x63C4, 0x9D8A, 0x6416, 0x9D8B, 0x6434, 0x9D8C, 0x6406, 0x9D8D, 0x6413, 0x9D8E, 0x6426, 0x9D8F, 0x6436, 0x9D90, 0x651D, + 0x9D91, 0x6417, 0x9D92, 0x6428, 0x9D93, 0x640F, 0x9D94, 0x6467, 0x9D95, 0x646F, 0x9D96, 0x6476, 0x9D97, 0x644E, 0x9D98, 0x652A, + 0x9D99, 0x6495, 0x9D9A, 0x6493, 0x9D9B, 0x64A5, 0x9D9C, 0x64A9, 0x9D9D, 0x6488, 0x9D9E, 0x64BC, 0x9D9F, 0x64DA, 0x9DA0, 0x64D2, + 0x9DA1, 0x64C5, 0x9DA2, 0x64C7, 0x9DA3, 0x64BB, 0x9DA4, 0x64D8, 0x9DA5, 0x64C2, 0x9DA6, 0x64F1, 0x9DA7, 0x64E7, 0x9DA8, 0x8209, + 0x9DA9, 0x64E0, 0x9DAA, 0x64E1, 0x9DAB, 0x62AC, 0x9DAC, 0x64E3, 0x9DAD, 0x64EF, 0x9DAE, 0x652C, 0x9DAF, 0x64F6, 0x9DB0, 0x64F4, + 0x9DB1, 0x64F2, 0x9DB2, 0x64FA, 0x9DB3, 0x6500, 0x9DB4, 0x64FD, 0x9DB5, 0x6518, 0x9DB6, 0x651C, 0x9DB7, 0x6505, 0x9DB8, 0x6524, + 0x9DB9, 0x6523, 0x9DBA, 0x652B, 0x9DBB, 0x6534, 0x9DBC, 0x6535, 0x9DBD, 0x6537, 0x9DBE, 0x6536, 0x9DBF, 0x6538, 0x9DC0, 0x754B, + 0x9DC1, 0x6548, 0x9DC2, 0x6556, 0x9DC3, 0x6555, 0x9DC4, 0x654D, 0x9DC5, 0x6558, 0x9DC6, 0x655E, 0x9DC7, 0x655D, 0x9DC8, 0x6572, + 0x9DC9, 0x6578, 0x9DCA, 0x6582, 0x9DCB, 0x6583, 0x9DCC, 0x8B8A, 0x9DCD, 0x659B, 0x9DCE, 0x659F, 0x9DCF, 0x65AB, 0x9DD0, 0x65B7, + 0x9DD1, 0x65C3, 0x9DD2, 0x65C6, 0x9DD3, 0x65C1, 0x9DD4, 0x65C4, 0x9DD5, 0x65CC, 0x9DD6, 0x65D2, 0x9DD7, 0x65DB, 0x9DD8, 0x65D9, + 0x9DD9, 0x65E0, 0x9DDA, 0x65E1, 0x9DDB, 0x65F1, 0x9DDC, 0x6772, 0x9DDD, 0x660A, 0x9DDE, 0x6603, 0x9DDF, 0x65FB, 0x9DE0, 0x6773, + 0x9DE1, 0x6635, 0x9DE2, 0x6636, 0x9DE3, 0x6634, 0x9DE4, 0x661C, 0x9DE5, 0x664F, 0x9DE6, 0x6644, 0x9DE7, 0x6649, 0x9DE8, 0x6641, + 0x9DE9, 0x665E, 0x9DEA, 0x665D, 0x9DEB, 0x6664, 0x9DEC, 0x6667, 0x9DED, 0x6668, 0x9DEE, 0x665F, 0x9DEF, 0x6662, 0x9DF0, 0x6670, + 0x9DF1, 0x6683, 0x9DF2, 0x6688, 0x9DF3, 0x668E, 0x9DF4, 0x6689, 0x9DF5, 0x6684, 0x9DF6, 0x6698, 0x9DF7, 0x669D, 0x9DF8, 0x66C1, + 0x9DF9, 0x66B9, 0x9DFA, 0x66C9, 0x9DFB, 0x66BE, 0x9DFC, 0x66BC, 0x9E40, 0x66C4, 0x9E41, 0x66B8, 0x9E42, 0x66D6, 0x9E43, 0x66DA, + 0x9E44, 0x66E0, 0x9E45, 0x663F, 0x9E46, 0x66E6, 0x9E47, 0x66E9, 0x9E48, 0x66F0, 0x9E49, 0x66F5, 0x9E4A, 0x66F7, 0x9E4B, 0x670F, + 0x9E4C, 0x6716, 0x9E4D, 0x671E, 0x9E4E, 0x6726, 0x9E4F, 0x6727, 0x9E50, 0x9738, 0x9E51, 0x672E, 0x9E52, 0x673F, 0x9E53, 0x6736, + 0x9E54, 0x6741, 0x9E55, 0x6738, 0x9E56, 0x6737, 0x9E57, 0x6746, 0x9E58, 0x675E, 0x9E59, 0x6760, 0x9E5A, 0x6759, 0x9E5B, 0x6763, + 0x9E5C, 0x6764, 0x9E5D, 0x6789, 0x9E5E, 0x6770, 0x9E5F, 0x67A9, 0x9E60, 0x677C, 0x9E61, 0x676A, 0x9E62, 0x678C, 0x9E63, 0x678B, + 0x9E64, 0x67A6, 0x9E65, 0x67A1, 0x9E66, 0x6785, 0x9E67, 0x67B7, 0x9E68, 0x67EF, 0x9E69, 0x67B4, 0x9E6A, 0x67EC, 0x9E6B, 0x67B3, + 0x9E6C, 0x67E9, 0x9E6D, 0x67B8, 0x9E6E, 0x67E4, 0x9E6F, 0x67DE, 0x9E70, 0x67DD, 0x9E71, 0x67E2, 0x9E72, 0x67EE, 0x9E73, 0x67B9, + 0x9E74, 0x67CE, 0x9E75, 0x67C6, 0x9E76, 0x67E7, 0x9E77, 0x6A9C, 0x9E78, 0x681E, 0x9E79, 0x6846, 0x9E7A, 0x6829, 0x9E7B, 0x6840, + 0x9E7C, 0x684D, 0x9E7D, 0x6832, 0x9E7E, 0x684E, 0x9E80, 0x68B3, 0x9E81, 0x682B, 0x9E82, 0x6859, 0x9E83, 0x6863, 0x9E84, 0x6877, + 0x9E85, 0x687F, 0x9E86, 0x689F, 0x9E87, 0x688F, 0x9E88, 0x68AD, 0x9E89, 0x6894, 0x9E8A, 0x689D, 0x9E8B, 0x689B, 0x9E8C, 0x6883, + 0x9E8D, 0x6AAE, 0x9E8E, 0x68B9, 0x9E8F, 0x6874, 0x9E90, 0x68B5, 0x9E91, 0x68A0, 0x9E92, 0x68BA, 0x9E93, 0x690F, 0x9E94, 0x688D, + 0x9E95, 0x687E, 0x9E96, 0x6901, 0x9E97, 0x68CA, 0x9E98, 0x6908, 0x9E99, 0x68D8, 0x9E9A, 0x6922, 0x9E9B, 0x6926, 0x9E9C, 0x68E1, + 0x9E9D, 0x690C, 0x9E9E, 0x68CD, 0x9E9F, 0x68D4, 0x9EA0, 0x68E7, 0x9EA1, 0x68D5, 0x9EA2, 0x6936, 0x9EA3, 0x6912, 0x9EA4, 0x6904, + 0x9EA5, 0x68D7, 0x9EA6, 0x68E3, 0x9EA7, 0x6925, 0x9EA8, 0x68F9, 0x9EA9, 0x68E0, 0x9EAA, 0x68EF, 0x9EAB, 0x6928, 0x9EAC, 0x692A, + 0x9EAD, 0x691A, 0x9EAE, 0x6923, 0x9EAF, 0x6921, 0x9EB0, 0x68C6, 0x9EB1, 0x6979, 0x9EB2, 0x6977, 0x9EB3, 0x695C, 0x9EB4, 0x6978, + 0x9EB5, 0x696B, 0x9EB6, 0x6954, 0x9EB7, 0x697E, 0x9EB8, 0x696E, 0x9EB9, 0x6939, 0x9EBA, 0x6974, 0x9EBB, 0x693D, 0x9EBC, 0x6959, + 0x9EBD, 0x6930, 0x9EBE, 0x6961, 0x9EBF, 0x695E, 0x9EC0, 0x695D, 0x9EC1, 0x6981, 0x9EC2, 0x696A, 0x9EC3, 0x69B2, 0x9EC4, 0x69AE, + 0x9EC5, 0x69D0, 0x9EC6, 0x69BF, 0x9EC7, 0x69C1, 0x9EC8, 0x69D3, 0x9EC9, 0x69BE, 0x9ECA, 0x69CE, 0x9ECB, 0x5BE8, 0x9ECC, 0x69CA, + 0x9ECD, 0x69DD, 0x9ECE, 0x69BB, 0x9ECF, 0x69C3, 0x9ED0, 0x69A7, 0x9ED1, 0x6A2E, 0x9ED2, 0x6991, 0x9ED3, 0x69A0, 0x9ED4, 0x699C, + 0x9ED5, 0x6995, 0x9ED6, 0x69B4, 0x9ED7, 0x69DE, 0x9ED8, 0x69E8, 0x9ED9, 0x6A02, 0x9EDA, 0x6A1B, 0x9EDB, 0x69FF, 0x9EDC, 0x6B0A, + 0x9EDD, 0x69F9, 0x9EDE, 0x69F2, 0x9EDF, 0x69E7, 0x9EE0, 0x6A05, 0x9EE1, 0x69B1, 0x9EE2, 0x6A1E, 0x9EE3, 0x69ED, 0x9EE4, 0x6A14, + 0x9EE5, 0x69EB, 0x9EE6, 0x6A0A, 0x9EE7, 0x6A12, 0x9EE8, 0x6AC1, 0x9EE9, 0x6A23, 0x9EEA, 0x6A13, 0x9EEB, 0x6A44, 0x9EEC, 0x6A0C, + 0x9EED, 0x6A72, 0x9EEE, 0x6A36, 0x9EEF, 0x6A78, 0x9EF0, 0x6A47, 0x9EF1, 0x6A62, 0x9EF2, 0x6A59, 0x9EF3, 0x6A66, 0x9EF4, 0x6A48, + 0x9EF5, 0x6A38, 0x9EF6, 0x6A22, 0x9EF7, 0x6A90, 0x9EF8, 0x6A8D, 0x9EF9, 0x6AA0, 0x9EFA, 0x6A84, 0x9EFB, 0x6AA2, 0x9EFC, 0x6AA3, + 0x9F40, 0x6A97, 0x9F41, 0x8617, 0x9F42, 0x6ABB, 0x9F43, 0x6AC3, 0x9F44, 0x6AC2, 0x9F45, 0x6AB8, 0x9F46, 0x6AB3, 0x9F47, 0x6AAC, + 0x9F48, 0x6ADE, 0x9F49, 0x6AD1, 0x9F4A, 0x6ADF, 0x9F4B, 0x6AAA, 0x9F4C, 0x6ADA, 0x9F4D, 0x6AEA, 0x9F4E, 0x6AFB, 0x9F4F, 0x6B05, + 0x9F50, 0x8616, 0x9F51, 0x6AFA, 0x9F52, 0x6B12, 0x9F53, 0x6B16, 0x9F54, 0x9B31, 0x9F55, 0x6B1F, 0x9F56, 0x6B38, 0x9F57, 0x6B37, + 0x9F58, 0x76DC, 0x9F59, 0x6B39, 0x9F5A, 0x98EE, 0x9F5B, 0x6B47, 0x9F5C, 0x6B43, 0x9F5D, 0x6B49, 0x9F5E, 0x6B50, 0x9F5F, 0x6B59, + 0x9F60, 0x6B54, 0x9F61, 0x6B5B, 0x9F62, 0x6B5F, 0x9F63, 0x6B61, 0x9F64, 0x6B78, 0x9F65, 0x6B79, 0x9F66, 0x6B7F, 0x9F67, 0x6B80, + 0x9F68, 0x6B84, 0x9F69, 0x6B83, 0x9F6A, 0x6B8D, 0x9F6B, 0x6B98, 0x9F6C, 0x6B95, 0x9F6D, 0x6B9E, 0x9F6E, 0x6BA4, 0x9F6F, 0x6BAA, + 0x9F70, 0x6BAB, 0x9F71, 0x6BAF, 0x9F72, 0x6BB2, 0x9F73, 0x6BB1, 0x9F74, 0x6BB3, 0x9F75, 0x6BB7, 0x9F76, 0x6BBC, 0x9F77, 0x6BC6, + 0x9F78, 0x6BCB, 0x9F79, 0x6BD3, 0x9F7A, 0x6BDF, 0x9F7B, 0x6BEC, 0x9F7C, 0x6BEB, 0x9F7D, 0x6BF3, 0x9F7E, 0x6BEF, 0x9F80, 0x9EBE, + 0x9F81, 0x6C08, 0x9F82, 0x6C13, 0x9F83, 0x6C14, 0x9F84, 0x6C1B, 0x9F85, 0x6C24, 0x9F86, 0x6C23, 0x9F87, 0x6C5E, 0x9F88, 0x6C55, + 0x9F89, 0x6C62, 0x9F8A, 0x6C6A, 0x9F8B, 0x6C82, 0x9F8C, 0x6C8D, 0x9F8D, 0x6C9A, 0x9F8E, 0x6C81, 0x9F8F, 0x6C9B, 0x9F90, 0x6C7E, + 0x9F91, 0x6C68, 0x9F92, 0x6C73, 0x9F93, 0x6C92, 0x9F94, 0x6C90, 0x9F95, 0x6CC4, 0x9F96, 0x6CF1, 0x9F97, 0x6CD3, 0x9F98, 0x6CBD, + 0x9F99, 0x6CD7, 0x9F9A, 0x6CC5, 0x9F9B, 0x6CDD, 0x9F9C, 0x6CAE, 0x9F9D, 0x6CB1, 0x9F9E, 0x6CBE, 0x9F9F, 0x6CBA, 0x9FA0, 0x6CDB, + 0x9FA1, 0x6CEF, 0x9FA2, 0x6CD9, 0x9FA3, 0x6CEA, 0x9FA4, 0x6D1F, 0x9FA5, 0x884D, 0x9FA6, 0x6D36, 0x9FA7, 0x6D2B, 0x9FA8, 0x6D3D, + 0x9FA9, 0x6D38, 0x9FAA, 0x6D19, 0x9FAB, 0x6D35, 0x9FAC, 0x6D33, 0x9FAD, 0x6D12, 0x9FAE, 0x6D0C, 0x9FAF, 0x6D63, 0x9FB0, 0x6D93, + 0x9FB1, 0x6D64, 0x9FB2, 0x6D5A, 0x9FB3, 0x6D79, 0x9FB4, 0x6D59, 0x9FB5, 0x6D8E, 0x9FB6, 0x6D95, 0x9FB7, 0x6FE4, 0x9FB8, 0x6D85, + 0x9FB9, 0x6DF9, 0x9FBA, 0x6E15, 0x9FBB, 0x6E0A, 0x9FBC, 0x6DB5, 0x9FBD, 0x6DC7, 0x9FBE, 0x6DE6, 0x9FBF, 0x6DB8, 0x9FC0, 0x6DC6, + 0x9FC1, 0x6DEC, 0x9FC2, 0x6DDE, 0x9FC3, 0x6DCC, 0x9FC4, 0x6DE8, 0x9FC5, 0x6DD2, 0x9FC6, 0x6DC5, 0x9FC7, 0x6DFA, 0x9FC8, 0x6DD9, + 0x9FC9, 0x6DE4, 0x9FCA, 0x6DD5, 0x9FCB, 0x6DEA, 0x9FCC, 0x6DEE, 0x9FCD, 0x6E2D, 0x9FCE, 0x6E6E, 0x9FCF, 0x6E2E, 0x9FD0, 0x6E19, + 0x9FD1, 0x6E72, 0x9FD2, 0x6E5F, 0x9FD3, 0x6E3E, 0x9FD4, 0x6E23, 0x9FD5, 0x6E6B, 0x9FD6, 0x6E2B, 0x9FD7, 0x6E76, 0x9FD8, 0x6E4D, + 0x9FD9, 0x6E1F, 0x9FDA, 0x6E43, 0x9FDB, 0x6E3A, 0x9FDC, 0x6E4E, 0x9FDD, 0x6E24, 0x9FDE, 0x6EFF, 0x9FDF, 0x6E1D, 0x9FE0, 0x6E38, + 0x9FE1, 0x6E82, 0x9FE2, 0x6EAA, 0x9FE3, 0x6E98, 0x9FE4, 0x6EC9, 0x9FE5, 0x6EB7, 0x9FE6, 0x6ED3, 0x9FE7, 0x6EBD, 0x9FE8, 0x6EAF, + 0x9FE9, 0x6EC4, 0x9FEA, 0x6EB2, 0x9FEB, 0x6ED4, 0x9FEC, 0x6ED5, 0x9FED, 0x6E8F, 0x9FEE, 0x6EA5, 0x9FEF, 0x6EC2, 0x9FF0, 0x6E9F, + 0x9FF1, 0x6F41, 0x9FF2, 0x6F11, 0x9FF3, 0x704C, 0x9FF4, 0x6EEC, 0x9FF5, 0x6EF8, 0x9FF6, 0x6EFE, 0x9FF7, 0x6F3F, 0x9FF8, 0x6EF2, + 0x9FF9, 0x6F31, 0x9FFA, 0x6EEF, 0x9FFB, 0x6F32, 0x9FFC, 0x6ECC, 0xE040, 0x6F3E, 0xE041, 0x6F13, 0xE042, 0x6EF7, 0xE043, 0x6F86, + 0xE044, 0x6F7A, 0xE045, 0x6F78, 0xE046, 0x6F81, 0xE047, 0x6F80, 0xE048, 0x6F6F, 0xE049, 0x6F5B, 0xE04A, 0x6FF3, 0xE04B, 0x6F6D, + 0xE04C, 0x6F82, 0xE04D, 0x6F7C, 0xE04E, 0x6F58, 0xE04F, 0x6F8E, 0xE050, 0x6F91, 0xE051, 0x6FC2, 0xE052, 0x6F66, 0xE053, 0x6FB3, + 0xE054, 0x6FA3, 0xE055, 0x6FA1, 0xE056, 0x6FA4, 0xE057, 0x6FB9, 0xE058, 0x6FC6, 0xE059, 0x6FAA, 0xE05A, 0x6FDF, 0xE05B, 0x6FD5, + 0xE05C, 0x6FEC, 0xE05D, 0x6FD4, 0xE05E, 0x6FD8, 0xE05F, 0x6FF1, 0xE060, 0x6FEE, 0xE061, 0x6FDB, 0xE062, 0x7009, 0xE063, 0x700B, + 0xE064, 0x6FFA, 0xE065, 0x7011, 0xE066, 0x7001, 0xE067, 0x700F, 0xE068, 0x6FFE, 0xE069, 0x701B, 0xE06A, 0x701A, 0xE06B, 0x6F74, + 0xE06C, 0x701D, 0xE06D, 0x7018, 0xE06E, 0x701F, 0xE06F, 0x7030, 0xE070, 0x703E, 0xE071, 0x7032, 0xE072, 0x7051, 0xE073, 0x7063, + 0xE074, 0x7099, 0xE075, 0x7092, 0xE076, 0x70AF, 0xE077, 0x70F1, 0xE078, 0x70AC, 0xE079, 0x70B8, 0xE07A, 0x70B3, 0xE07B, 0x70AE, + 0xE07C, 0x70DF, 0xE07D, 0x70CB, 0xE07E, 0x70DD, 0xE080, 0x70D9, 0xE081, 0x7109, 0xE082, 0x70FD, 0xE083, 0x711C, 0xE084, 0x7119, + 0xE085, 0x7165, 0xE086, 0x7155, 0xE087, 0x7188, 0xE088, 0x7166, 0xE089, 0x7162, 0xE08A, 0x714C, 0xE08B, 0x7156, 0xE08C, 0x716C, + 0xE08D, 0x718F, 0xE08E, 0x71FB, 0xE08F, 0x7184, 0xE090, 0x7195, 0xE091, 0x71A8, 0xE092, 0x71AC, 0xE093, 0x71D7, 0xE094, 0x71B9, + 0xE095, 0x71BE, 0xE096, 0x71D2, 0xE097, 0x71C9, 0xE098, 0x71D4, 0xE099, 0x71CE, 0xE09A, 0x71E0, 0xE09B, 0x71EC, 0xE09C, 0x71E7, + 0xE09D, 0x71F5, 0xE09E, 0x71FC, 0xE09F, 0x71F9, 0xE0A0, 0x71FF, 0xE0A1, 0x720D, 0xE0A2, 0x7210, 0xE0A3, 0x721B, 0xE0A4, 0x7228, + 0xE0A5, 0x722D, 0xE0A6, 0x722C, 0xE0A7, 0x7230, 0xE0A8, 0x7232, 0xE0A9, 0x723B, 0xE0AA, 0x723C, 0xE0AB, 0x723F, 0xE0AC, 0x7240, + 0xE0AD, 0x7246, 0xE0AE, 0x724B, 0xE0AF, 0x7258, 0xE0B0, 0x7274, 0xE0B1, 0x727E, 0xE0B2, 0x7282, 0xE0B3, 0x7281, 0xE0B4, 0x7287, + 0xE0B5, 0x7292, 0xE0B6, 0x7296, 0xE0B7, 0x72A2, 0xE0B8, 0x72A7, 0xE0B9, 0x72B9, 0xE0BA, 0x72B2, 0xE0BB, 0x72C3, 0xE0BC, 0x72C6, + 0xE0BD, 0x72C4, 0xE0BE, 0x72CE, 0xE0BF, 0x72D2, 0xE0C0, 0x72E2, 0xE0C1, 0x72E0, 0xE0C2, 0x72E1, 0xE0C3, 0x72F9, 0xE0C4, 0x72F7, + 0xE0C5, 0x500F, 0xE0C6, 0x7317, 0xE0C7, 0x730A, 0xE0C8, 0x731C, 0xE0C9, 0x7316, 0xE0CA, 0x731D, 0xE0CB, 0x7334, 0xE0CC, 0x732F, + 0xE0CD, 0x7329, 0xE0CE, 0x7325, 0xE0CF, 0x733E, 0xE0D0, 0x734E, 0xE0D1, 0x734F, 0xE0D2, 0x9ED8, 0xE0D3, 0x7357, 0xE0D4, 0x736A, + 0xE0D5, 0x7368, 0xE0D6, 0x7370, 0xE0D7, 0x7378, 0xE0D8, 0x7375, 0xE0D9, 0x737B, 0xE0DA, 0x737A, 0xE0DB, 0x73C8, 0xE0DC, 0x73B3, + 0xE0DD, 0x73CE, 0xE0DE, 0x73BB, 0xE0DF, 0x73C0, 0xE0E0, 0x73E5, 0xE0E1, 0x73EE, 0xE0E2, 0x73DE, 0xE0E3, 0x74A2, 0xE0E4, 0x7405, + 0xE0E5, 0x746F, 0xE0E6, 0x7425, 0xE0E7, 0x73F8, 0xE0E8, 0x7432, 0xE0E9, 0x743A, 0xE0EA, 0x7455, 0xE0EB, 0x743F, 0xE0EC, 0x745F, + 0xE0ED, 0x7459, 0xE0EE, 0x7441, 0xE0EF, 0x745C, 0xE0F0, 0x7469, 0xE0F1, 0x7470, 0xE0F2, 0x7463, 0xE0F3, 0x746A, 0xE0F4, 0x7476, + 0xE0F5, 0x747E, 0xE0F6, 0x748B, 0xE0F7, 0x749E, 0xE0F8, 0x74A7, 0xE0F9, 0x74CA, 0xE0FA, 0x74CF, 0xE0FB, 0x74D4, 0xE0FC, 0x73F1, + 0xE140, 0x74E0, 0xE141, 0x74E3, 0xE142, 0x74E7, 0xE143, 0x74E9, 0xE144, 0x74EE, 0xE145, 0x74F2, 0xE146, 0x74F0, 0xE147, 0x74F1, + 0xE148, 0x74F8, 0xE149, 0x74F7, 0xE14A, 0x7504, 0xE14B, 0x7503, 0xE14C, 0x7505, 0xE14D, 0x750C, 0xE14E, 0x750E, 0xE14F, 0x750D, + 0xE150, 0x7515, 0xE151, 0x7513, 0xE152, 0x751E, 0xE153, 0x7526, 0xE154, 0x752C, 0xE155, 0x753C, 0xE156, 0x7544, 0xE157, 0x754D, + 0xE158, 0x754A, 0xE159, 0x7549, 0xE15A, 0x755B, 0xE15B, 0x7546, 0xE15C, 0x755A, 0xE15D, 0x7569, 0xE15E, 0x7564, 0xE15F, 0x7567, + 0xE160, 0x756B, 0xE161, 0x756D, 0xE162, 0x7578, 0xE163, 0x7576, 0xE164, 0x7586, 0xE165, 0x7587, 0xE166, 0x7574, 0xE167, 0x758A, + 0xE168, 0x7589, 0xE169, 0x7582, 0xE16A, 0x7594, 0xE16B, 0x759A, 0xE16C, 0x759D, 0xE16D, 0x75A5, 0xE16E, 0x75A3, 0xE16F, 0x75C2, + 0xE170, 0x75B3, 0xE171, 0x75C3, 0xE172, 0x75B5, 0xE173, 0x75BD, 0xE174, 0x75B8, 0xE175, 0x75BC, 0xE176, 0x75B1, 0xE177, 0x75CD, + 0xE178, 0x75CA, 0xE179, 0x75D2, 0xE17A, 0x75D9, 0xE17B, 0x75E3, 0xE17C, 0x75DE, 0xE17D, 0x75FE, 0xE17E, 0x75FF, 0xE180, 0x75FC, + 0xE181, 0x7601, 0xE182, 0x75F0, 0xE183, 0x75FA, 0xE184, 0x75F2, 0xE185, 0x75F3, 0xE186, 0x760B, 0xE187, 0x760D, 0xE188, 0x7609, + 0xE189, 0x761F, 0xE18A, 0x7627, 0xE18B, 0x7620, 0xE18C, 0x7621, 0xE18D, 0x7622, 0xE18E, 0x7624, 0xE18F, 0x7634, 0xE190, 0x7630, + 0xE191, 0x763B, 0xE192, 0x7647, 0xE193, 0x7648, 0xE194, 0x7646, 0xE195, 0x765C, 0xE196, 0x7658, 0xE197, 0x7661, 0xE198, 0x7662, + 0xE199, 0x7668, 0xE19A, 0x7669, 0xE19B, 0x766A, 0xE19C, 0x7667, 0xE19D, 0x766C, 0xE19E, 0x7670, 0xE19F, 0x7672, 0xE1A0, 0x7676, + 0xE1A1, 0x7678, 0xE1A2, 0x767C, 0xE1A3, 0x7680, 0xE1A4, 0x7683, 0xE1A5, 0x7688, 0xE1A6, 0x768B, 0xE1A7, 0x768E, 0xE1A8, 0x7696, + 0xE1A9, 0x7693, 0xE1AA, 0x7699, 0xE1AB, 0x769A, 0xE1AC, 0x76B0, 0xE1AD, 0x76B4, 0xE1AE, 0x76B8, 0xE1AF, 0x76B9, 0xE1B0, 0x76BA, + 0xE1B1, 0x76C2, 0xE1B2, 0x76CD, 0xE1B3, 0x76D6, 0xE1B4, 0x76D2, 0xE1B5, 0x76DE, 0xE1B6, 0x76E1, 0xE1B7, 0x76E5, 0xE1B8, 0x76E7, + 0xE1B9, 0x76EA, 0xE1BA, 0x862F, 0xE1BB, 0x76FB, 0xE1BC, 0x7708, 0xE1BD, 0x7707, 0xE1BE, 0x7704, 0xE1BF, 0x7729, 0xE1C0, 0x7724, + 0xE1C1, 0x771E, 0xE1C2, 0x7725, 0xE1C3, 0x7726, 0xE1C4, 0x771B, 0xE1C5, 0x7737, 0xE1C6, 0x7738, 0xE1C7, 0x7747, 0xE1C8, 0x775A, + 0xE1C9, 0x7768, 0xE1CA, 0x776B, 0xE1CB, 0x775B, 0xE1CC, 0x7765, 0xE1CD, 0x777F, 0xE1CE, 0x777E, 0xE1CF, 0x7779, 0xE1D0, 0x778E, + 0xE1D1, 0x778B, 0xE1D2, 0x7791, 0xE1D3, 0x77A0, 0xE1D4, 0x779E, 0xE1D5, 0x77B0, 0xE1D6, 0x77B6, 0xE1D7, 0x77B9, 0xE1D8, 0x77BF, + 0xE1D9, 0x77BC, 0xE1DA, 0x77BD, 0xE1DB, 0x77BB, 0xE1DC, 0x77C7, 0xE1DD, 0x77CD, 0xE1DE, 0x77D7, 0xE1DF, 0x77DA, 0xE1E0, 0x77DC, + 0xE1E1, 0x77E3, 0xE1E2, 0x77EE, 0xE1E3, 0x77FC, 0xE1E4, 0x780C, 0xE1E5, 0x7812, 0xE1E6, 0x7926, 0xE1E7, 0x7820, 0xE1E8, 0x792A, + 0xE1E9, 0x7845, 0xE1EA, 0x788E, 0xE1EB, 0x7874, 0xE1EC, 0x7886, 0xE1ED, 0x787C, 0xE1EE, 0x789A, 0xE1EF, 0x788C, 0xE1F0, 0x78A3, + 0xE1F1, 0x78B5, 0xE1F2, 0x78AA, 0xE1F3, 0x78AF, 0xE1F4, 0x78D1, 0xE1F5, 0x78C6, 0xE1F6, 0x78CB, 0xE1F7, 0x78D4, 0xE1F8, 0x78BE, + 0xE1F9, 0x78BC, 0xE1FA, 0x78C5, 0xE1FB, 0x78CA, 0xE1FC, 0x78EC, 0xE240, 0x78E7, 0xE241, 0x78DA, 0xE242, 0x78FD, 0xE243, 0x78F4, + 0xE244, 0x7907, 0xE245, 0x7912, 0xE246, 0x7911, 0xE247, 0x7919, 0xE248, 0x792C, 0xE249, 0x792B, 0xE24A, 0x7940, 0xE24B, 0x7960, + 0xE24C, 0x7957, 0xE24D, 0x795F, 0xE24E, 0x795A, 0xE24F, 0x7955, 0xE250, 0x7953, 0xE251, 0x797A, 0xE252, 0x797F, 0xE253, 0x798A, + 0xE254, 0x799D, 0xE255, 0x79A7, 0xE256, 0x9F4B, 0xE257, 0x79AA, 0xE258, 0x79AE, 0xE259, 0x79B3, 0xE25A, 0x79B9, 0xE25B, 0x79BA, + 0xE25C, 0x79C9, 0xE25D, 0x79D5, 0xE25E, 0x79E7, 0xE25F, 0x79EC, 0xE260, 0x79E1, 0xE261, 0x79E3, 0xE262, 0x7A08, 0xE263, 0x7A0D, + 0xE264, 0x7A18, 0xE265, 0x7A19, 0xE266, 0x7A20, 0xE267, 0x7A1F, 0xE268, 0x7980, 0xE269, 0x7A31, 0xE26A, 0x7A3B, 0xE26B, 0x7A3E, + 0xE26C, 0x7A37, 0xE26D, 0x7A43, 0xE26E, 0x7A57, 0xE26F, 0x7A49, 0xE270, 0x7A61, 0xE271, 0x7A62, 0xE272, 0x7A69, 0xE273, 0x9F9D, + 0xE274, 0x7A70, 0xE275, 0x7A79, 0xE276, 0x7A7D, 0xE277, 0x7A88, 0xE278, 0x7A97, 0xE279, 0x7A95, 0xE27A, 0x7A98, 0xE27B, 0x7A96, + 0xE27C, 0x7AA9, 0xE27D, 0x7AC8, 0xE27E, 0x7AB0, 0xE280, 0x7AB6, 0xE281, 0x7AC5, 0xE282, 0x7AC4, 0xE283, 0x7ABF, 0xE284, 0x9083, + 0xE285, 0x7AC7, 0xE286, 0x7ACA, 0xE287, 0x7ACD, 0xE288, 0x7ACF, 0xE289, 0x7AD5, 0xE28A, 0x7AD3, 0xE28B, 0x7AD9, 0xE28C, 0x7ADA, + 0xE28D, 0x7ADD, 0xE28E, 0x7AE1, 0xE28F, 0x7AE2, 0xE290, 0x7AE6, 0xE291, 0x7AED, 0xE292, 0x7AF0, 0xE293, 0x7B02, 0xE294, 0x7B0F, + 0xE295, 0x7B0A, 0xE296, 0x7B06, 0xE297, 0x7B33, 0xE298, 0x7B18, 0xE299, 0x7B19, 0xE29A, 0x7B1E, 0xE29B, 0x7B35, 0xE29C, 0x7B28, + 0xE29D, 0x7B36, 0xE29E, 0x7B50, 0xE29F, 0x7B7A, 0xE2A0, 0x7B04, 0xE2A1, 0x7B4D, 0xE2A2, 0x7B0B, 0xE2A3, 0x7B4C, 0xE2A4, 0x7B45, + 0xE2A5, 0x7B75, 0xE2A6, 0x7B65, 0xE2A7, 0x7B74, 0xE2A8, 0x7B67, 0xE2A9, 0x7B70, 0xE2AA, 0x7B71, 0xE2AB, 0x7B6C, 0xE2AC, 0x7B6E, + 0xE2AD, 0x7B9D, 0xE2AE, 0x7B98, 0xE2AF, 0x7B9F, 0xE2B0, 0x7B8D, 0xE2B1, 0x7B9C, 0xE2B2, 0x7B9A, 0xE2B3, 0x7B8B, 0xE2B4, 0x7B92, + 0xE2B5, 0x7B8F, 0xE2B6, 0x7B5D, 0xE2B7, 0x7B99, 0xE2B8, 0x7BCB, 0xE2B9, 0x7BC1, 0xE2BA, 0x7BCC, 0xE2BB, 0x7BCF, 0xE2BC, 0x7BB4, + 0xE2BD, 0x7BC6, 0xE2BE, 0x7BDD, 0xE2BF, 0x7BE9, 0xE2C0, 0x7C11, 0xE2C1, 0x7C14, 0xE2C2, 0x7BE6, 0xE2C3, 0x7BE5, 0xE2C4, 0x7C60, + 0xE2C5, 0x7C00, 0xE2C6, 0x7C07, 0xE2C7, 0x7C13, 0xE2C8, 0x7BF3, 0xE2C9, 0x7BF7, 0xE2CA, 0x7C17, 0xE2CB, 0x7C0D, 0xE2CC, 0x7BF6, + 0xE2CD, 0x7C23, 0xE2CE, 0x7C27, 0xE2CF, 0x7C2A, 0xE2D0, 0x7C1F, 0xE2D1, 0x7C37, 0xE2D2, 0x7C2B, 0xE2D3, 0x7C3D, 0xE2D4, 0x7C4C, + 0xE2D5, 0x7C43, 0xE2D6, 0x7C54, 0xE2D7, 0x7C4F, 0xE2D8, 0x7C40, 0xE2D9, 0x7C50, 0xE2DA, 0x7C58, 0xE2DB, 0x7C5F, 0xE2DC, 0x7C64, + 0xE2DD, 0x7C56, 0xE2DE, 0x7C65, 0xE2DF, 0x7C6C, 0xE2E0, 0x7C75, 0xE2E1, 0x7C83, 0xE2E2, 0x7C90, 0xE2E3, 0x7CA4, 0xE2E4, 0x7CAD, + 0xE2E5, 0x7CA2, 0xE2E6, 0x7CAB, 0xE2E7, 0x7CA1, 0xE2E8, 0x7CA8, 0xE2E9, 0x7CB3, 0xE2EA, 0x7CB2, 0xE2EB, 0x7CB1, 0xE2EC, 0x7CAE, + 0xE2ED, 0x7CB9, 0xE2EE, 0x7CBD, 0xE2EF, 0x7CC0, 0xE2F0, 0x7CC5, 0xE2F1, 0x7CC2, 0xE2F2, 0x7CD8, 0xE2F3, 0x7CD2, 0xE2F4, 0x7CDC, + 0xE2F5, 0x7CE2, 0xE2F6, 0x9B3B, 0xE2F7, 0x7CEF, 0xE2F8, 0x7CF2, 0xE2F9, 0x7CF4, 0xE2FA, 0x7CF6, 0xE2FB, 0x7CFA, 0xE2FC, 0x7D06, + 0xE340, 0x7D02, 0xE341, 0x7D1C, 0xE342, 0x7D15, 0xE343, 0x7D0A, 0xE344, 0x7D45, 0xE345, 0x7D4B, 0xE346, 0x7D2E, 0xE347, 0x7D32, + 0xE348, 0x7D3F, 0xE349, 0x7D35, 0xE34A, 0x7D46, 0xE34B, 0x7D73, 0xE34C, 0x7D56, 0xE34D, 0x7D4E, 0xE34E, 0x7D72, 0xE34F, 0x7D68, + 0xE350, 0x7D6E, 0xE351, 0x7D4F, 0xE352, 0x7D63, 0xE353, 0x7D93, 0xE354, 0x7D89, 0xE355, 0x7D5B, 0xE356, 0x7D8F, 0xE357, 0x7D7D, + 0xE358, 0x7D9B, 0xE359, 0x7DBA, 0xE35A, 0x7DAE, 0xE35B, 0x7DA3, 0xE35C, 0x7DB5, 0xE35D, 0x7DC7, 0xE35E, 0x7DBD, 0xE35F, 0x7DAB, + 0xE360, 0x7E3D, 0xE361, 0x7DA2, 0xE362, 0x7DAF, 0xE363, 0x7DDC, 0xE364, 0x7DB8, 0xE365, 0x7D9F, 0xE366, 0x7DB0, 0xE367, 0x7DD8, + 0xE368, 0x7DDD, 0xE369, 0x7DE4, 0xE36A, 0x7DDE, 0xE36B, 0x7DFB, 0xE36C, 0x7DF2, 0xE36D, 0x7DE1, 0xE36E, 0x7E05, 0xE36F, 0x7E0A, + 0xE370, 0x7E23, 0xE371, 0x7E21, 0xE372, 0x7E12, 0xE373, 0x7E31, 0xE374, 0x7E1F, 0xE375, 0x7E09, 0xE376, 0x7E0B, 0xE377, 0x7E22, + 0xE378, 0x7E46, 0xE379, 0x7E66, 0xE37A, 0x7E3B, 0xE37B, 0x7E35, 0xE37C, 0x7E39, 0xE37D, 0x7E43, 0xE37E, 0x7E37, 0xE380, 0x7E32, + 0xE381, 0x7E3A, 0xE382, 0x7E67, 0xE383, 0x7E5D, 0xE384, 0x7E56, 0xE385, 0x7E5E, 0xE386, 0x7E59, 0xE387, 0x7E5A, 0xE388, 0x7E79, + 0xE389, 0x7E6A, 0xE38A, 0x7E69, 0xE38B, 0x7E7C, 0xE38C, 0x7E7B, 0xE38D, 0x7E83, 0xE38E, 0x7DD5, 0xE38F, 0x7E7D, 0xE390, 0x8FAE, + 0xE391, 0x7E7F, 0xE392, 0x7E88, 0xE393, 0x7E89, 0xE394, 0x7E8C, 0xE395, 0x7E92, 0xE396, 0x7E90, 0xE397, 0x7E93, 0xE398, 0x7E94, + 0xE399, 0x7E96, 0xE39A, 0x7E8E, 0xE39B, 0x7E9B, 0xE39C, 0x7E9C, 0xE39D, 0x7F38, 0xE39E, 0x7F3A, 0xE39F, 0x7F45, 0xE3A0, 0x7F4C, + 0xE3A1, 0x7F4D, 0xE3A2, 0x7F4E, 0xE3A3, 0x7F50, 0xE3A4, 0x7F51, 0xE3A5, 0x7F55, 0xE3A6, 0x7F54, 0xE3A7, 0x7F58, 0xE3A8, 0x7F5F, + 0xE3A9, 0x7F60, 0xE3AA, 0x7F68, 0xE3AB, 0x7F69, 0xE3AC, 0x7F67, 0xE3AD, 0x7F78, 0xE3AE, 0x7F82, 0xE3AF, 0x7F86, 0xE3B0, 0x7F83, + 0xE3B1, 0x7F88, 0xE3B2, 0x7F87, 0xE3B3, 0x7F8C, 0xE3B4, 0x7F94, 0xE3B5, 0x7F9E, 0xE3B6, 0x7F9D, 0xE3B7, 0x7F9A, 0xE3B8, 0x7FA3, + 0xE3B9, 0x7FAF, 0xE3BA, 0x7FB2, 0xE3BB, 0x7FB9, 0xE3BC, 0x7FAE, 0xE3BD, 0x7FB6, 0xE3BE, 0x7FB8, 0xE3BF, 0x8B71, 0xE3C0, 0x7FC5, + 0xE3C1, 0x7FC6, 0xE3C2, 0x7FCA, 0xE3C3, 0x7FD5, 0xE3C4, 0x7FD4, 0xE3C5, 0x7FE1, 0xE3C6, 0x7FE6, 0xE3C7, 0x7FE9, 0xE3C8, 0x7FF3, + 0xE3C9, 0x7FF9, 0xE3CA, 0x98DC, 0xE3CB, 0x8006, 0xE3CC, 0x8004, 0xE3CD, 0x800B, 0xE3CE, 0x8012, 0xE3CF, 0x8018, 0xE3D0, 0x8019, + 0xE3D1, 0x801C, 0xE3D2, 0x8021, 0xE3D3, 0x8028, 0xE3D4, 0x803F, 0xE3D5, 0x803B, 0xE3D6, 0x804A, 0xE3D7, 0x8046, 0xE3D8, 0x8052, + 0xE3D9, 0x8058, 0xE3DA, 0x805A, 0xE3DB, 0x805F, 0xE3DC, 0x8062, 0xE3DD, 0x8068, 0xE3DE, 0x8073, 0xE3DF, 0x8072, 0xE3E0, 0x8070, + 0xE3E1, 0x8076, 0xE3E2, 0x8079, 0xE3E3, 0x807D, 0xE3E4, 0x807F, 0xE3E5, 0x8084, 0xE3E6, 0x8086, 0xE3E7, 0x8085, 0xE3E8, 0x809B, + 0xE3E9, 0x8093, 0xE3EA, 0x809A, 0xE3EB, 0x80AD, 0xE3EC, 0x5190, 0xE3ED, 0x80AC, 0xE3EE, 0x80DB, 0xE3EF, 0x80E5, 0xE3F0, 0x80D9, + 0xE3F1, 0x80DD, 0xE3F2, 0x80C4, 0xE3F3, 0x80DA, 0xE3F4, 0x80D6, 0xE3F5, 0x8109, 0xE3F6, 0x80EF, 0xE3F7, 0x80F1, 0xE3F8, 0x811B, + 0xE3F9, 0x8129, 0xE3FA, 0x8123, 0xE3FB, 0x812F, 0xE3FC, 0x814B, 0xE440, 0x968B, 0xE441, 0x8146, 0xE442, 0x813E, 0xE443, 0x8153, + 0xE444, 0x8151, 0xE445, 0x80FC, 0xE446, 0x8171, 0xE447, 0x816E, 0xE448, 0x8165, 0xE449, 0x8166, 0xE44A, 0x8174, 0xE44B, 0x8183, + 0xE44C, 0x8188, 0xE44D, 0x818A, 0xE44E, 0x8180, 0xE44F, 0x8182, 0xE450, 0x81A0, 0xE451, 0x8195, 0xE452, 0x81A4, 0xE453, 0x81A3, + 0xE454, 0x815F, 0xE455, 0x8193, 0xE456, 0x81A9, 0xE457, 0x81B0, 0xE458, 0x81B5, 0xE459, 0x81BE, 0xE45A, 0x81B8, 0xE45B, 0x81BD, + 0xE45C, 0x81C0, 0xE45D, 0x81C2, 0xE45E, 0x81BA, 0xE45F, 0x81C9, 0xE460, 0x81CD, 0xE461, 0x81D1, 0xE462, 0x81D9, 0xE463, 0x81D8, + 0xE464, 0x81C8, 0xE465, 0x81DA, 0xE466, 0x81DF, 0xE467, 0x81E0, 0xE468, 0x81E7, 0xE469, 0x81FA, 0xE46A, 0x81FB, 0xE46B, 0x81FE, + 0xE46C, 0x8201, 0xE46D, 0x8202, 0xE46E, 0x8205, 0xE46F, 0x8207, 0xE470, 0x820A, 0xE471, 0x820D, 0xE472, 0x8210, 0xE473, 0x8216, + 0xE474, 0x8229, 0xE475, 0x822B, 0xE476, 0x8238, 0xE477, 0x8233, 0xE478, 0x8240, 0xE479, 0x8259, 0xE47A, 0x8258, 0xE47B, 0x825D, + 0xE47C, 0x825A, 0xE47D, 0x825F, 0xE47E, 0x8264, 0xE480, 0x8262, 0xE481, 0x8268, 0xE482, 0x826A, 0xE483, 0x826B, 0xE484, 0x822E, + 0xE485, 0x8271, 0xE486, 0x8277, 0xE487, 0x8278, 0xE488, 0x827E, 0xE489, 0x828D, 0xE48A, 0x8292, 0xE48B, 0x82AB, 0xE48C, 0x829F, + 0xE48D, 0x82BB, 0xE48E, 0x82AC, 0xE48F, 0x82E1, 0xE490, 0x82E3, 0xE491, 0x82DF, 0xE492, 0x82D2, 0xE493, 0x82F4, 0xE494, 0x82F3, + 0xE495, 0x82FA, 0xE496, 0x8393, 0xE497, 0x8303, 0xE498, 0x82FB, 0xE499, 0x82F9, 0xE49A, 0x82DE, 0xE49B, 0x8306, 0xE49C, 0x82DC, + 0xE49D, 0x8309, 0xE49E, 0x82D9, 0xE49F, 0x8335, 0xE4A0, 0x8334, 0xE4A1, 0x8316, 0xE4A2, 0x8332, 0xE4A3, 0x8331, 0xE4A4, 0x8340, + 0xE4A5, 0x8339, 0xE4A6, 0x8350, 0xE4A7, 0x8345, 0xE4A8, 0x832F, 0xE4A9, 0x832B, 0xE4AA, 0x8317, 0xE4AB, 0x8318, 0xE4AC, 0x8385, + 0xE4AD, 0x839A, 0xE4AE, 0x83AA, 0xE4AF, 0x839F, 0xE4B0, 0x83A2, 0xE4B1, 0x8396, 0xE4B2, 0x8323, 0xE4B3, 0x838E, 0xE4B4, 0x8387, + 0xE4B5, 0x838A, 0xE4B6, 0x837C, 0xE4B7, 0x83B5, 0xE4B8, 0x8373, 0xE4B9, 0x8375, 0xE4BA, 0x83A0, 0xE4BB, 0x8389, 0xE4BC, 0x83A8, + 0xE4BD, 0x83F4, 0xE4BE, 0x8413, 0xE4BF, 0x83EB, 0xE4C0, 0x83CE, 0xE4C1, 0x83FD, 0xE4C2, 0x8403, 0xE4C3, 0x83D8, 0xE4C4, 0x840B, + 0xE4C5, 0x83C1, 0xE4C6, 0x83F7, 0xE4C7, 0x8407, 0xE4C8, 0x83E0, 0xE4C9, 0x83F2, 0xE4CA, 0x840D, 0xE4CB, 0x8422, 0xE4CC, 0x8420, + 0xE4CD, 0x83BD, 0xE4CE, 0x8438, 0xE4CF, 0x8506, 0xE4D0, 0x83FB, 0xE4D1, 0x846D, 0xE4D2, 0x842A, 0xE4D3, 0x843C, 0xE4D4, 0x855A, + 0xE4D5, 0x8484, 0xE4D6, 0x8477, 0xE4D7, 0x846B, 0xE4D8, 0x84AD, 0xE4D9, 0x846E, 0xE4DA, 0x8482, 0xE4DB, 0x8469, 0xE4DC, 0x8446, + 0xE4DD, 0x842C, 0xE4DE, 0x846F, 0xE4DF, 0x8479, 0xE4E0, 0x8435, 0xE4E1, 0x84CA, 0xE4E2, 0x8462, 0xE4E3, 0x84B9, 0xE4E4, 0x84BF, + 0xE4E5, 0x849F, 0xE4E6, 0x84D9, 0xE4E7, 0x84CD, 0xE4E8, 0x84BB, 0xE4E9, 0x84DA, 0xE4EA, 0x84D0, 0xE4EB, 0x84C1, 0xE4EC, 0x84C6, + 0xE4ED, 0x84D6, 0xE4EE, 0x84A1, 0xE4EF, 0x8521, 0xE4F0, 0x84FF, 0xE4F1, 0x84F4, 0xE4F2, 0x8517, 0xE4F3, 0x8518, 0xE4F4, 0x852C, + 0xE4F5, 0x851F, 0xE4F6, 0x8515, 0xE4F7, 0x8514, 0xE4F8, 0x84FC, 0xE4F9, 0x8540, 0xE4FA, 0x8563, 0xE4FB, 0x8558, 0xE4FC, 0x8548, + 0xE540, 0x8541, 0xE541, 0x8602, 0xE542, 0x854B, 0xE543, 0x8555, 0xE544, 0x8580, 0xE545, 0x85A4, 0xE546, 0x8588, 0xE547, 0x8591, + 0xE548, 0x858A, 0xE549, 0x85A8, 0xE54A, 0x856D, 0xE54B, 0x8594, 0xE54C, 0x859B, 0xE54D, 0x85EA, 0xE54E, 0x8587, 0xE54F, 0x859C, + 0xE550, 0x8577, 0xE551, 0x857E, 0xE552, 0x8590, 0xE553, 0x85C9, 0xE554, 0x85BA, 0xE555, 0x85CF, 0xE556, 0x85B9, 0xE557, 0x85D0, + 0xE558, 0x85D5, 0xE559, 0x85DD, 0xE55A, 0x85E5, 0xE55B, 0x85DC, 0xE55C, 0x85F9, 0xE55D, 0x860A, 0xE55E, 0x8613, 0xE55F, 0x860B, + 0xE560, 0x85FE, 0xE561, 0x85FA, 0xE562, 0x8606, 0xE563, 0x8622, 0xE564, 0x861A, 0xE565, 0x8630, 0xE566, 0x863F, 0xE567, 0x864D, + 0xE568, 0x4E55, 0xE569, 0x8654, 0xE56A, 0x865F, 0xE56B, 0x8667, 0xE56C, 0x8671, 0xE56D, 0x8693, 0xE56E, 0x86A3, 0xE56F, 0x86A9, + 0xE570, 0x86AA, 0xE571, 0x868B, 0xE572, 0x868C, 0xE573, 0x86B6, 0xE574, 0x86AF, 0xE575, 0x86C4, 0xE576, 0x86C6, 0xE577, 0x86B0, + 0xE578, 0x86C9, 0xE579, 0x8823, 0xE57A, 0x86AB, 0xE57B, 0x86D4, 0xE57C, 0x86DE, 0xE57D, 0x86E9, 0xE57E, 0x86EC, 0xE580, 0x86DF, + 0xE581, 0x86DB, 0xE582, 0x86EF, 0xE583, 0x8712, 0xE584, 0x8706, 0xE585, 0x8708, 0xE586, 0x8700, 0xE587, 0x8703, 0xE588, 0x86FB, + 0xE589, 0x8711, 0xE58A, 0x8709, 0xE58B, 0x870D, 0xE58C, 0x86F9, 0xE58D, 0x870A, 0xE58E, 0x8734, 0xE58F, 0x873F, 0xE590, 0x8737, + 0xE591, 0x873B, 0xE592, 0x8725, 0xE593, 0x8729, 0xE594, 0x871A, 0xE595, 0x8760, 0xE596, 0x875F, 0xE597, 0x8778, 0xE598, 0x874C, + 0xE599, 0x874E, 0xE59A, 0x8774, 0xE59B, 0x8757, 0xE59C, 0x8768, 0xE59D, 0x876E, 0xE59E, 0x8759, 0xE59F, 0x8753, 0xE5A0, 0x8763, + 0xE5A1, 0x876A, 0xE5A2, 0x8805, 0xE5A3, 0x87A2, 0xE5A4, 0x879F, 0xE5A5, 0x8782, 0xE5A6, 0x87AF, 0xE5A7, 0x87CB, 0xE5A8, 0x87BD, + 0xE5A9, 0x87C0, 0xE5AA, 0x87D0, 0xE5AB, 0x96D6, 0xE5AC, 0x87AB, 0xE5AD, 0x87C4, 0xE5AE, 0x87B3, 0xE5AF, 0x87C7, 0xE5B0, 0x87C6, + 0xE5B1, 0x87BB, 0xE5B2, 0x87EF, 0xE5B3, 0x87F2, 0xE5B4, 0x87E0, 0xE5B5, 0x880F, 0xE5B6, 0x880D, 0xE5B7, 0x87FE, 0xE5B8, 0x87F6, + 0xE5B9, 0x87F7, 0xE5BA, 0x880E, 0xE5BB, 0x87D2, 0xE5BC, 0x8811, 0xE5BD, 0x8816, 0xE5BE, 0x8815, 0xE5BF, 0x8822, 0xE5C0, 0x8821, + 0xE5C1, 0x8831, 0xE5C2, 0x8836, 0xE5C3, 0x8839, 0xE5C4, 0x8827, 0xE5C5, 0x883B, 0xE5C6, 0x8844, 0xE5C7, 0x8842, 0xE5C8, 0x8852, + 0xE5C9, 0x8859, 0xE5CA, 0x885E, 0xE5CB, 0x8862, 0xE5CC, 0x886B, 0xE5CD, 0x8881, 0xE5CE, 0x887E, 0xE5CF, 0x889E, 0xE5D0, 0x8875, + 0xE5D1, 0x887D, 0xE5D2, 0x88B5, 0xE5D3, 0x8872, 0xE5D4, 0x8882, 0xE5D5, 0x8897, 0xE5D6, 0x8892, 0xE5D7, 0x88AE, 0xE5D8, 0x8899, + 0xE5D9, 0x88A2, 0xE5DA, 0x888D, 0xE5DB, 0x88A4, 0xE5DC, 0x88B0, 0xE5DD, 0x88BF, 0xE5DE, 0x88B1, 0xE5DF, 0x88C3, 0xE5E0, 0x88C4, + 0xE5E1, 0x88D4, 0xE5E2, 0x88D8, 0xE5E3, 0x88D9, 0xE5E4, 0x88DD, 0xE5E5, 0x88F9, 0xE5E6, 0x8902, 0xE5E7, 0x88FC, 0xE5E8, 0x88F4, + 0xE5E9, 0x88E8, 0xE5EA, 0x88F2, 0xE5EB, 0x8904, 0xE5EC, 0x890C, 0xE5ED, 0x890A, 0xE5EE, 0x8913, 0xE5EF, 0x8943, 0xE5F0, 0x891E, + 0xE5F1, 0x8925, 0xE5F2, 0x892A, 0xE5F3, 0x892B, 0xE5F4, 0x8941, 0xE5F5, 0x8944, 0xE5F6, 0x893B, 0xE5F7, 0x8936, 0xE5F8, 0x8938, + 0xE5F9, 0x894C, 0xE5FA, 0x891D, 0xE5FB, 0x8960, 0xE5FC, 0x895E, 0xE640, 0x8966, 0xE641, 0x8964, 0xE642, 0x896D, 0xE643, 0x896A, + 0xE644, 0x896F, 0xE645, 0x8974, 0xE646, 0x8977, 0xE647, 0x897E, 0xE648, 0x8983, 0xE649, 0x8988, 0xE64A, 0x898A, 0xE64B, 0x8993, + 0xE64C, 0x8998, 0xE64D, 0x89A1, 0xE64E, 0x89A9, 0xE64F, 0x89A6, 0xE650, 0x89AC, 0xE651, 0x89AF, 0xE652, 0x89B2, 0xE653, 0x89BA, + 0xE654, 0x89BD, 0xE655, 0x89BF, 0xE656, 0x89C0, 0xE657, 0x89DA, 0xE658, 0x89DC, 0xE659, 0x89DD, 0xE65A, 0x89E7, 0xE65B, 0x89F4, + 0xE65C, 0x89F8, 0xE65D, 0x8A03, 0xE65E, 0x8A16, 0xE65F, 0x8A10, 0xE660, 0x8A0C, 0xE661, 0x8A1B, 0xE662, 0x8A1D, 0xE663, 0x8A25, + 0xE664, 0x8A36, 0xE665, 0x8A41, 0xE666, 0x8A5B, 0xE667, 0x8A52, 0xE668, 0x8A46, 0xE669, 0x8A48, 0xE66A, 0x8A7C, 0xE66B, 0x8A6D, + 0xE66C, 0x8A6C, 0xE66D, 0x8A62, 0xE66E, 0x8A85, 0xE66F, 0x8A82, 0xE670, 0x8A84, 0xE671, 0x8AA8, 0xE672, 0x8AA1, 0xE673, 0x8A91, + 0xE674, 0x8AA5, 0xE675, 0x8AA6, 0xE676, 0x8A9A, 0xE677, 0x8AA3, 0xE678, 0x8AC4, 0xE679, 0x8ACD, 0xE67A, 0x8AC2, 0xE67B, 0x8ADA, + 0xE67C, 0x8AEB, 0xE67D, 0x8AF3, 0xE67E, 0x8AE7, 0xE680, 0x8AE4, 0xE681, 0x8AF1, 0xE682, 0x8B14, 0xE683, 0x8AE0, 0xE684, 0x8AE2, + 0xE685, 0x8AF7, 0xE686, 0x8ADE, 0xE687, 0x8ADB, 0xE688, 0x8B0C, 0xE689, 0x8B07, 0xE68A, 0x8B1A, 0xE68B, 0x8AE1, 0xE68C, 0x8B16, + 0xE68D, 0x8B10, 0xE68E, 0x8B17, 0xE68F, 0x8B20, 0xE690, 0x8B33, 0xE691, 0x97AB, 0xE692, 0x8B26, 0xE693, 0x8B2B, 0xE694, 0x8B3E, + 0xE695, 0x8B28, 0xE696, 0x8B41, 0xE697, 0x8B4C, 0xE698, 0x8B4F, 0xE699, 0x8B4E, 0xE69A, 0x8B49, 0xE69B, 0x8B56, 0xE69C, 0x8B5B, + 0xE69D, 0x8B5A, 0xE69E, 0x8B6B, 0xE69F, 0x8B5F, 0xE6A0, 0x8B6C, 0xE6A1, 0x8B6F, 0xE6A2, 0x8B74, 0xE6A3, 0x8B7D, 0xE6A4, 0x8B80, + 0xE6A5, 0x8B8C, 0xE6A6, 0x8B8E, 0xE6A7, 0x8B92, 0xE6A8, 0x8B93, 0xE6A9, 0x8B96, 0xE6AA, 0x8B99, 0xE6AB, 0x8B9A, 0xE6AC, 0x8C3A, + 0xE6AD, 0x8C41, 0xE6AE, 0x8C3F, 0xE6AF, 0x8C48, 0xE6B0, 0x8C4C, 0xE6B1, 0x8C4E, 0xE6B2, 0x8C50, 0xE6B3, 0x8C55, 0xE6B4, 0x8C62, + 0xE6B5, 0x8C6C, 0xE6B6, 0x8C78, 0xE6B7, 0x8C7A, 0xE6B8, 0x8C82, 0xE6B9, 0x8C89, 0xE6BA, 0x8C85, 0xE6BB, 0x8C8A, 0xE6BC, 0x8C8D, + 0xE6BD, 0x8C8E, 0xE6BE, 0x8C94, 0xE6BF, 0x8C7C, 0xE6C0, 0x8C98, 0xE6C1, 0x621D, 0xE6C2, 0x8CAD, 0xE6C3, 0x8CAA, 0xE6C4, 0x8CBD, + 0xE6C5, 0x8CB2, 0xE6C6, 0x8CB3, 0xE6C7, 0x8CAE, 0xE6C8, 0x8CB6, 0xE6C9, 0x8CC8, 0xE6CA, 0x8CC1, 0xE6CB, 0x8CE4, 0xE6CC, 0x8CE3, + 0xE6CD, 0x8CDA, 0xE6CE, 0x8CFD, 0xE6CF, 0x8CFA, 0xE6D0, 0x8CFB, 0xE6D1, 0x8D04, 0xE6D2, 0x8D05, 0xE6D3, 0x8D0A, 0xE6D4, 0x8D07, + 0xE6D5, 0x8D0F, 0xE6D6, 0x8D0D, 0xE6D7, 0x8D10, 0xE6D8, 0x9F4E, 0xE6D9, 0x8D13, 0xE6DA, 0x8CCD, 0xE6DB, 0x8D14, 0xE6DC, 0x8D16, + 0xE6DD, 0x8D67, 0xE6DE, 0x8D6D, 0xE6DF, 0x8D71, 0xE6E0, 0x8D73, 0xE6E1, 0x8D81, 0xE6E2, 0x8D99, 0xE6E3, 0x8DC2, 0xE6E4, 0x8DBE, + 0xE6E5, 0x8DBA, 0xE6E6, 0x8DCF, 0xE6E7, 0x8DDA, 0xE6E8, 0x8DD6, 0xE6E9, 0x8DCC, 0xE6EA, 0x8DDB, 0xE6EB, 0x8DCB, 0xE6EC, 0x8DEA, + 0xE6ED, 0x8DEB, 0xE6EE, 0x8DDF, 0xE6EF, 0x8DE3, 0xE6F0, 0x8DFC, 0xE6F1, 0x8E08, 0xE6F2, 0x8E09, 0xE6F3, 0x8DFF, 0xE6F4, 0x8E1D, + 0xE6F5, 0x8E1E, 0xE6F6, 0x8E10, 0xE6F7, 0x8E1F, 0xE6F8, 0x8E42, 0xE6F9, 0x8E35, 0xE6FA, 0x8E30, 0xE6FB, 0x8E34, 0xE6FC, 0x8E4A, + 0xE740, 0x8E47, 0xE741, 0x8E49, 0xE742, 0x8E4C, 0xE743, 0x8E50, 0xE744, 0x8E48, 0xE745, 0x8E59, 0xE746, 0x8E64, 0xE747, 0x8E60, + 0xE748, 0x8E2A, 0xE749, 0x8E63, 0xE74A, 0x8E55, 0xE74B, 0x8E76, 0xE74C, 0x8E72, 0xE74D, 0x8E7C, 0xE74E, 0x8E81, 0xE74F, 0x8E87, + 0xE750, 0x8E85, 0xE751, 0x8E84, 0xE752, 0x8E8B, 0xE753, 0x8E8A, 0xE754, 0x8E93, 0xE755, 0x8E91, 0xE756, 0x8E94, 0xE757, 0x8E99, + 0xE758, 0x8EAA, 0xE759, 0x8EA1, 0xE75A, 0x8EAC, 0xE75B, 0x8EB0, 0xE75C, 0x8EC6, 0xE75D, 0x8EB1, 0xE75E, 0x8EBE, 0xE75F, 0x8EC5, + 0xE760, 0x8EC8, 0xE761, 0x8ECB, 0xE762, 0x8EDB, 0xE763, 0x8EE3, 0xE764, 0x8EFC, 0xE765, 0x8EFB, 0xE766, 0x8EEB, 0xE767, 0x8EFE, + 0xE768, 0x8F0A, 0xE769, 0x8F05, 0xE76A, 0x8F15, 0xE76B, 0x8F12, 0xE76C, 0x8F19, 0xE76D, 0x8F13, 0xE76E, 0x8F1C, 0xE76F, 0x8F1F, + 0xE770, 0x8F1B, 0xE771, 0x8F0C, 0xE772, 0x8F26, 0xE773, 0x8F33, 0xE774, 0x8F3B, 0xE775, 0x8F39, 0xE776, 0x8F45, 0xE777, 0x8F42, + 0xE778, 0x8F3E, 0xE779, 0x8F4C, 0xE77A, 0x8F49, 0xE77B, 0x8F46, 0xE77C, 0x8F4E, 0xE77D, 0x8F57, 0xE77E, 0x8F5C, 0xE780, 0x8F62, + 0xE781, 0x8F63, 0xE782, 0x8F64, 0xE783, 0x8F9C, 0xE784, 0x8F9F, 0xE785, 0x8FA3, 0xE786, 0x8FAD, 0xE787, 0x8FAF, 0xE788, 0x8FB7, + 0xE789, 0x8FDA, 0xE78A, 0x8FE5, 0xE78B, 0x8FE2, 0xE78C, 0x8FEA, 0xE78D, 0x8FEF, 0xE78E, 0x9087, 0xE78F, 0x8FF4, 0xE790, 0x9005, + 0xE791, 0x8FF9, 0xE792, 0x8FFA, 0xE793, 0x9011, 0xE794, 0x9015, 0xE795, 0x9021, 0xE796, 0x900D, 0xE797, 0x901E, 0xE798, 0x9016, + 0xE799, 0x900B, 0xE79A, 0x9027, 0xE79B, 0x9036, 0xE79C, 0x9035, 0xE79D, 0x9039, 0xE79E, 0x8FF8, 0xE79F, 0x904F, 0xE7A0, 0x9050, + 0xE7A1, 0x9051, 0xE7A2, 0x9052, 0xE7A3, 0x900E, 0xE7A4, 0x9049, 0xE7A5, 0x903E, 0xE7A6, 0x9056, 0xE7A7, 0x9058, 0xE7A8, 0x905E, + 0xE7A9, 0x9068, 0xE7AA, 0x906F, 0xE7AB, 0x9076, 0xE7AC, 0x96A8, 0xE7AD, 0x9072, 0xE7AE, 0x9082, 0xE7AF, 0x907D, 0xE7B0, 0x9081, + 0xE7B1, 0x9080, 0xE7B2, 0x908A, 0xE7B3, 0x9089, 0xE7B4, 0x908F, 0xE7B5, 0x90A8, 0xE7B6, 0x90AF, 0xE7B7, 0x90B1, 0xE7B8, 0x90B5, + 0xE7B9, 0x90E2, 0xE7BA, 0x90E4, 0xE7BB, 0x6248, 0xE7BC, 0x90DB, 0xE7BD, 0x9102, 0xE7BE, 0x9112, 0xE7BF, 0x9119, 0xE7C0, 0x9132, + 0xE7C1, 0x9130, 0xE7C2, 0x914A, 0xE7C3, 0x9156, 0xE7C4, 0x9158, 0xE7C5, 0x9163, 0xE7C6, 0x9165, 0xE7C7, 0x9169, 0xE7C8, 0x9173, + 0xE7C9, 0x9172, 0xE7CA, 0x918B, 0xE7CB, 0x9189, 0xE7CC, 0x9182, 0xE7CD, 0x91A2, 0xE7CE, 0x91AB, 0xE7CF, 0x91AF, 0xE7D0, 0x91AA, + 0xE7D1, 0x91B5, 0xE7D2, 0x91B4, 0xE7D3, 0x91BA, 0xE7D4, 0x91C0, 0xE7D5, 0x91C1, 0xE7D6, 0x91C9, 0xE7D7, 0x91CB, 0xE7D8, 0x91D0, + 0xE7D9, 0x91D6, 0xE7DA, 0x91DF, 0xE7DB, 0x91E1, 0xE7DC, 0x91DB, 0xE7DD, 0x91FC, 0xE7DE, 0x91F5, 0xE7DF, 0x91F6, 0xE7E0, 0x921E, + 0xE7E1, 0x91FF, 0xE7E2, 0x9214, 0xE7E3, 0x922C, 0xE7E4, 0x9215, 0xE7E5, 0x9211, 0xE7E6, 0x925E, 0xE7E7, 0x9257, 0xE7E8, 0x9245, + 0xE7E9, 0x9249, 0xE7EA, 0x9264, 0xE7EB, 0x9248, 0xE7EC, 0x9295, 0xE7ED, 0x923F, 0xE7EE, 0x924B, 0xE7EF, 0x9250, 0xE7F0, 0x929C, + 0xE7F1, 0x9296, 0xE7F2, 0x9293, 0xE7F3, 0x929B, 0xE7F4, 0x925A, 0xE7F5, 0x92CF, 0xE7F6, 0x92B9, 0xE7F7, 0x92B7, 0xE7F8, 0x92E9, + 0xE7F9, 0x930F, 0xE7FA, 0x92FA, 0xE7FB, 0x9344, 0xE7FC, 0x932E, 0xE840, 0x9319, 0xE841, 0x9322, 0xE842, 0x931A, 0xE843, 0x9323, + 0xE844, 0x933A, 0xE845, 0x9335, 0xE846, 0x933B, 0xE847, 0x935C, 0xE848, 0x9360, 0xE849, 0x937C, 0xE84A, 0x936E, 0xE84B, 0x9356, + 0xE84C, 0x93B0, 0xE84D, 0x93AC, 0xE84E, 0x93AD, 0xE84F, 0x9394, 0xE850, 0x93B9, 0xE851, 0x93D6, 0xE852, 0x93D7, 0xE853, 0x93E8, + 0xE854, 0x93E5, 0xE855, 0x93D8, 0xE856, 0x93C3, 0xE857, 0x93DD, 0xE858, 0x93D0, 0xE859, 0x93C8, 0xE85A, 0x93E4, 0xE85B, 0x941A, + 0xE85C, 0x9414, 0xE85D, 0x9413, 0xE85E, 0x9403, 0xE85F, 0x9407, 0xE860, 0x9410, 0xE861, 0x9436, 0xE862, 0x942B, 0xE863, 0x9435, + 0xE864, 0x9421, 0xE865, 0x943A, 0xE866, 0x9441, 0xE867, 0x9452, 0xE868, 0x9444, 0xE869, 0x945B, 0xE86A, 0x9460, 0xE86B, 0x9462, + 0xE86C, 0x945E, 0xE86D, 0x946A, 0xE86E, 0x9229, 0xE86F, 0x9470, 0xE870, 0x9475, 0xE871, 0x9477, 0xE872, 0x947D, 0xE873, 0x945A, + 0xE874, 0x947C, 0xE875, 0x947E, 0xE876, 0x9481, 0xE877, 0x947F, 0xE878, 0x9582, 0xE879, 0x9587, 0xE87A, 0x958A, 0xE87B, 0x9594, + 0xE87C, 0x9596, 0xE87D, 0x9598, 0xE87E, 0x9599, 0xE880, 0x95A0, 0xE881, 0x95A8, 0xE882, 0x95A7, 0xE883, 0x95AD, 0xE884, 0x95BC, + 0xE885, 0x95BB, 0xE886, 0x95B9, 0xE887, 0x95BE, 0xE888, 0x95CA, 0xE889, 0x6FF6, 0xE88A, 0x95C3, 0xE88B, 0x95CD, 0xE88C, 0x95CC, + 0xE88D, 0x95D5, 0xE88E, 0x95D4, 0xE88F, 0x95D6, 0xE890, 0x95DC, 0xE891, 0x95E1, 0xE892, 0x95E5, 0xE893, 0x95E2, 0xE894, 0x9621, + 0xE895, 0x9628, 0xE896, 0x962E, 0xE897, 0x962F, 0xE898, 0x9642, 0xE899, 0x964C, 0xE89A, 0x964F, 0xE89B, 0x964B, 0xE89C, 0x9677, + 0xE89D, 0x965C, 0xE89E, 0x965E, 0xE89F, 0x965D, 0xE8A0, 0x965F, 0xE8A1, 0x9666, 0xE8A2, 0x9672, 0xE8A3, 0x966C, 0xE8A4, 0x968D, + 0xE8A5, 0x9698, 0xE8A6, 0x9695, 0xE8A7, 0x9697, 0xE8A8, 0x96AA, 0xE8A9, 0x96A7, 0xE8AA, 0x96B1, 0xE8AB, 0x96B2, 0xE8AC, 0x96B0, + 0xE8AD, 0x96B4, 0xE8AE, 0x96B6, 0xE8AF, 0x96B8, 0xE8B0, 0x96B9, 0xE8B1, 0x96CE, 0xE8B2, 0x96CB, 0xE8B3, 0x96C9, 0xE8B4, 0x96CD, + 0xE8B5, 0x894D, 0xE8B6, 0x96DC, 0xE8B7, 0x970D, 0xE8B8, 0x96D5, 0xE8B9, 0x96F9, 0xE8BA, 0x9704, 0xE8BB, 0x9706, 0xE8BC, 0x9708, + 0xE8BD, 0x9713, 0xE8BE, 0x970E, 0xE8BF, 0x9711, 0xE8C0, 0x970F, 0xE8C1, 0x9716, 0xE8C2, 0x9719, 0xE8C3, 0x9724, 0xE8C4, 0x972A, + 0xE8C5, 0x9730, 0xE8C6, 0x9739, 0xE8C7, 0x973D, 0xE8C8, 0x973E, 0xE8C9, 0x9744, 0xE8CA, 0x9746, 0xE8CB, 0x9748, 0xE8CC, 0x9742, + 0xE8CD, 0x9749, 0xE8CE, 0x975C, 0xE8CF, 0x9760, 0xE8D0, 0x9764, 0xE8D1, 0x9766, 0xE8D2, 0x9768, 0xE8D3, 0x52D2, 0xE8D4, 0x976B, + 0xE8D5, 0x9771, 0xE8D6, 0x9779, 0xE8D7, 0x9785, 0xE8D8, 0x977C, 0xE8D9, 0x9781, 0xE8DA, 0x977A, 0xE8DB, 0x9786, 0xE8DC, 0x978B, + 0xE8DD, 0x978F, 0xE8DE, 0x9790, 0xE8DF, 0x979C, 0xE8E0, 0x97A8, 0xE8E1, 0x97A6, 0xE8E2, 0x97A3, 0xE8E3, 0x97B3, 0xE8E4, 0x97B4, + 0xE8E5, 0x97C3, 0xE8E6, 0x97C6, 0xE8E7, 0x97C8, 0xE8E8, 0x97CB, 0xE8E9, 0x97DC, 0xE8EA, 0x97ED, 0xE8EB, 0x9F4F, 0xE8EC, 0x97F2, + 0xE8ED, 0x7ADF, 0xE8EE, 0x97F6, 0xE8EF, 0x97F5, 0xE8F0, 0x980F, 0xE8F1, 0x980C, 0xE8F2, 0x9838, 0xE8F3, 0x9824, 0xE8F4, 0x9821, + 0xE8F5, 0x9837, 0xE8F6, 0x983D, 0xE8F7, 0x9846, 0xE8F8, 0x984F, 0xE8F9, 0x984B, 0xE8FA, 0x986B, 0xE8FB, 0x986F, 0xE8FC, 0x9870, + 0xE940, 0x9871, 0xE941, 0x9874, 0xE942, 0x9873, 0xE943, 0x98AA, 0xE944, 0x98AF, 0xE945, 0x98B1, 0xE946, 0x98B6, 0xE947, 0x98C4, + 0xE948, 0x98C3, 0xE949, 0x98C6, 0xE94A, 0x98E9, 0xE94B, 0x98EB, 0xE94C, 0x9903, 0xE94D, 0x9909, 0xE94E, 0x9912, 0xE94F, 0x9914, + 0xE950, 0x9918, 0xE951, 0x9921, 0xE952, 0x991D, 0xE953, 0x991E, 0xE954, 0x9924, 0xE955, 0x9920, 0xE956, 0x992C, 0xE957, 0x992E, + 0xE958, 0x993D, 0xE959, 0x993E, 0xE95A, 0x9942, 0xE95B, 0x9949, 0xE95C, 0x9945, 0xE95D, 0x9950, 0xE95E, 0x994B, 0xE95F, 0x9951, + 0xE960, 0x9952, 0xE961, 0x994C, 0xE962, 0x9955, 0xE963, 0x9997, 0xE964, 0x9998, 0xE965, 0x99A5, 0xE966, 0x99AD, 0xE967, 0x99AE, + 0xE968, 0x99BC, 0xE969, 0x99DF, 0xE96A, 0x99DB, 0xE96B, 0x99DD, 0xE96C, 0x99D8, 0xE96D, 0x99D1, 0xE96E, 0x99ED, 0xE96F, 0x99EE, + 0xE970, 0x99F1, 0xE971, 0x99F2, 0xE972, 0x99FB, 0xE973, 0x99F8, 0xE974, 0x9A01, 0xE975, 0x9A0F, 0xE976, 0x9A05, 0xE977, 0x99E2, + 0xE978, 0x9A19, 0xE979, 0x9A2B, 0xE97A, 0x9A37, 0xE97B, 0x9A45, 0xE97C, 0x9A42, 0xE97D, 0x9A40, 0xE97E, 0x9A43, 0xE980, 0x9A3E, + 0xE981, 0x9A55, 0xE982, 0x9A4D, 0xE983, 0x9A5B, 0xE984, 0x9A57, 0xE985, 0x9A5F, 0xE986, 0x9A62, 0xE987, 0x9A65, 0xE988, 0x9A64, + 0xE989, 0x9A69, 0xE98A, 0x9A6B, 0xE98B, 0x9A6A, 0xE98C, 0x9AAD, 0xE98D, 0x9AB0, 0xE98E, 0x9ABC, 0xE98F, 0x9AC0, 0xE990, 0x9ACF, + 0xE991, 0x9AD1, 0xE992, 0x9AD3, 0xE993, 0x9AD4, 0xE994, 0x9ADE, 0xE995, 0x9ADF, 0xE996, 0x9AE2, 0xE997, 0x9AE3, 0xE998, 0x9AE6, + 0xE999, 0x9AEF, 0xE99A, 0x9AEB, 0xE99B, 0x9AEE, 0xE99C, 0x9AF4, 0xE99D, 0x9AF1, 0xE99E, 0x9AF7, 0xE99F, 0x9AFB, 0xE9A0, 0x9B06, + 0xE9A1, 0x9B18, 0xE9A2, 0x9B1A, 0xE9A3, 0x9B1F, 0xE9A4, 0x9B22, 0xE9A5, 0x9B23, 0xE9A6, 0x9B25, 0xE9A7, 0x9B27, 0xE9A8, 0x9B28, + 0xE9A9, 0x9B29, 0xE9AA, 0x9B2A, 0xE9AB, 0x9B2E, 0xE9AC, 0x9B2F, 0xE9AD, 0x9B32, 0xE9AE, 0x9B44, 0xE9AF, 0x9B43, 0xE9B0, 0x9B4F, + 0xE9B1, 0x9B4D, 0xE9B2, 0x9B4E, 0xE9B3, 0x9B51, 0xE9B4, 0x9B58, 0xE9B5, 0x9B74, 0xE9B6, 0x9B93, 0xE9B7, 0x9B83, 0xE9B8, 0x9B91, + 0xE9B9, 0x9B96, 0xE9BA, 0x9B97, 0xE9BB, 0x9B9F, 0xE9BC, 0x9BA0, 0xE9BD, 0x9BA8, 0xE9BE, 0x9BB4, 0xE9BF, 0x9BC0, 0xE9C0, 0x9BCA, + 0xE9C1, 0x9BB9, 0xE9C2, 0x9BC6, 0xE9C3, 0x9BCF, 0xE9C4, 0x9BD1, 0xE9C5, 0x9BD2, 0xE9C6, 0x9BE3, 0xE9C7, 0x9BE2, 0xE9C8, 0x9BE4, + 0xE9C9, 0x9BD4, 0xE9CA, 0x9BE1, 0xE9CB, 0x9C3A, 0xE9CC, 0x9BF2, 0xE9CD, 0x9BF1, 0xE9CE, 0x9BF0, 0xE9CF, 0x9C15, 0xE9D0, 0x9C14, + 0xE9D1, 0x9C09, 0xE9D2, 0x9C13, 0xE9D3, 0x9C0C, 0xE9D4, 0x9C06, 0xE9D5, 0x9C08, 0xE9D6, 0x9C12, 0xE9D7, 0x9C0A, 0xE9D8, 0x9C04, + 0xE9D9, 0x9C2E, 0xE9DA, 0x9C1B, 0xE9DB, 0x9C25, 0xE9DC, 0x9C24, 0xE9DD, 0x9C21, 0xE9DE, 0x9C30, 0xE9DF, 0x9C47, 0xE9E0, 0x9C32, + 0xE9E1, 0x9C46, 0xE9E2, 0x9C3E, 0xE9E3, 0x9C5A, 0xE9E4, 0x9C60, 0xE9E5, 0x9C67, 0xE9E6, 0x9C76, 0xE9E7, 0x9C78, 0xE9E8, 0x9CE7, + 0xE9E9, 0x9CEC, 0xE9EA, 0x9CF0, 0xE9EB, 0x9D09, 0xE9EC, 0x9D08, 0xE9ED, 0x9CEB, 0xE9EE, 0x9D03, 0xE9EF, 0x9D06, 0xE9F0, 0x9D2A, + 0xE9F1, 0x9D26, 0xE9F2, 0x9DAF, 0xE9F3, 0x9D23, 0xE9F4, 0x9D1F, 0xE9F5, 0x9D44, 0xE9F6, 0x9D15, 0xE9F7, 0x9D12, 0xE9F8, 0x9D41, + 0xE9F9, 0x9D3F, 0xE9FA, 0x9D3E, 0xE9FB, 0x9D46, 0xE9FC, 0x9D48, 0xEA40, 0x9D5D, 0xEA41, 0x9D5E, 0xEA42, 0x9D64, 0xEA43, 0x9D51, + 0xEA44, 0x9D50, 0xEA45, 0x9D59, 0xEA46, 0x9D72, 0xEA47, 0x9D89, 0xEA48, 0x9D87, 0xEA49, 0x9DAB, 0xEA4A, 0x9D6F, 0xEA4B, 0x9D7A, + 0xEA4C, 0x9D9A, 0xEA4D, 0x9DA4, 0xEA4E, 0x9DA9, 0xEA4F, 0x9DB2, 0xEA50, 0x9DC4, 0xEA51, 0x9DC1, 0xEA52, 0x9DBB, 0xEA53, 0x9DB8, + 0xEA54, 0x9DBA, 0xEA55, 0x9DC6, 0xEA56, 0x9DCF, 0xEA57, 0x9DC2, 0xEA58, 0x9DD9, 0xEA59, 0x9DD3, 0xEA5A, 0x9DF8, 0xEA5B, 0x9DE6, + 0xEA5C, 0x9DED, 0xEA5D, 0x9DEF, 0xEA5E, 0x9DFD, 0xEA5F, 0x9E1A, 0xEA60, 0x9E1B, 0xEA61, 0x9E1E, 0xEA62, 0x9E75, 0xEA63, 0x9E79, + 0xEA64, 0x9E7D, 0xEA65, 0x9E81, 0xEA66, 0x9E88, 0xEA67, 0x9E8B, 0xEA68, 0x9E8C, 0xEA69, 0x9E92, 0xEA6A, 0x9E95, 0xEA6B, 0x9E91, + 0xEA6C, 0x9E9D, 0xEA6D, 0x9EA5, 0xEA6E, 0x9EA9, 0xEA6F, 0x9EB8, 0xEA70, 0x9EAA, 0xEA71, 0x9EAD, 0xEA72, 0x9761, 0xEA73, 0x9ECC, + 0xEA74, 0x9ECE, 0xEA75, 0x9ECF, 0xEA76, 0x9ED0, 0xEA77, 0x9ED4, 0xEA78, 0x9EDC, 0xEA79, 0x9EDE, 0xEA7A, 0x9EDD, 0xEA7B, 0x9EE0, + 0xEA7C, 0x9EE5, 0xEA7D, 0x9EE8, 0xEA7E, 0x9EEF, 0xEA80, 0x9EF4, 0xEA81, 0x9EF6, 0xEA82, 0x9EF7, 0xEA83, 0x9EF9, 0xEA84, 0x9EFB, + 0xEA85, 0x9EFC, 0xEA86, 0x9EFD, 0xEA87, 0x9F07, 0xEA88, 0x9F08, 0xEA89, 0x76B7, 0xEA8A, 0x9F15, 0xEA8B, 0x9F21, 0xEA8C, 0x9F2C, + 0xEA8D, 0x9F3E, 0xEA8E, 0x9F4A, 0xEA8F, 0x9F52, 0xEA90, 0x9F54, 0xEA91, 0x9F63, 0xEA92, 0x9F5F, 0xEA93, 0x9F60, 0xEA94, 0x9F61, + 0xEA95, 0x9F66, 0xEA96, 0x9F67, 0xEA97, 0x9F6C, 0xEA98, 0x9F6A, 0xEA99, 0x9F77, 0xEA9A, 0x9F72, 0xEA9B, 0x9F76, 0xEA9C, 0x9F95, + 0xEA9D, 0x9F9C, 0xEA9E, 0x9FA0, 0xEA9F, 0x582F, 0xEAA0, 0x69C7, 0xEAA1, 0x9059, 0xEAA2, 0x7464, 0xEAA3, 0x51DC, 0xEAA4, 0x7199, + 0xFA40, 0x2170, 0xFA41, 0x2171, 0xFA42, 0x2172, 0xFA43, 0x2173, 0xFA44, 0x2174, 0xFA45, 0x2175, 0xFA46, 0x2176, 0xFA47, 0x2177, + 0xFA48, 0x2178, 0xFA49, 0x2179, 0xFA55, 0xFFE4, 0xFA56, 0xFF07, 0xFA57, 0xFF02, 0xFA5C, 0x7E8A, 0xFA5D, 0x891C, 0xFA5E, 0x9348, + 0xFA5F, 0x9288, 0xFA60, 0x84DC, 0xFA61, 0x4FC9, 0xFA62, 0x70BB, 0xFA63, 0x6631, 0xFA64, 0x68C8, 0xFA65, 0x92F9, 0xFA66, 0x66FB, + 0xFA67, 0x5F45, 0xFA68, 0x4E28, 0xFA69, 0x4EE1, 0xFA6A, 0x4EFC, 0xFA6B, 0x4F00, 0xFA6C, 0x4F03, 0xFA6D, 0x4F39, 0xFA6E, 0x4F56, + 0xFA6F, 0x4F92, 0xFA70, 0x4F8A, 0xFA71, 0x4F9A, 0xFA72, 0x4F94, 0xFA73, 0x4FCD, 0xFA74, 0x5040, 0xFA75, 0x5022, 0xFA76, 0x4FFF, + 0xFA77, 0x501E, 0xFA78, 0x5046, 0xFA79, 0x5070, 0xFA7A, 0x5042, 0xFA7B, 0x5094, 0xFA7C, 0x50F4, 0xFA7D, 0x50D8, 0xFA7E, 0x514A, + 0xFA80, 0x5164, 0xFA81, 0x519D, 0xFA82, 0x51BE, 0xFA83, 0x51EC, 0xFA84, 0x5215, 0xFA85, 0x529C, 0xFA86, 0x52A6, 0xFA87, 0x52C0, + 0xFA88, 0x52DB, 0xFA89, 0x5300, 0xFA8A, 0x5307, 0xFA8B, 0x5324, 0xFA8C, 0x5372, 0xFA8D, 0x5393, 0xFA8E, 0x53B2, 0xFA8F, 0x53DD, + 0xFA90, 0xFA0E, 0xFA91, 0x549C, 0xFA92, 0x548A, 0xFA93, 0x54A9, 0xFA94, 0x54FF, 0xFA95, 0x5586, 0xFA96, 0x5759, 0xFA97, 0x5765, + 0xFA98, 0x57AC, 0xFA99, 0x57C8, 0xFA9A, 0x57C7, 0xFA9B, 0xFA0F, 0xFA9C, 0xFA10, 0xFA9D, 0x589E, 0xFA9E, 0x58B2, 0xFA9F, 0x590B, + 0xFAA0, 0x5953, 0xFAA1, 0x595B, 0xFAA2, 0x595D, 0xFAA3, 0x5963, 0xFAA4, 0x59A4, 0xFAA5, 0x59BA, 0xFAA6, 0x5B56, 0xFAA7, 0x5BC0, + 0xFAA8, 0x752F, 0xFAA9, 0x5BD8, 0xFAAA, 0x5BEC, 0xFAAB, 0x5C1E, 0xFAAC, 0x5CA6, 0xFAAD, 0x5CBA, 0xFAAE, 0x5CF5, 0xFAAF, 0x5D27, + 0xFAB0, 0x5D53, 0xFAB1, 0xFA11, 0xFAB2, 0x5D42, 0xFAB3, 0x5D6D, 0xFAB4, 0x5DB8, 0xFAB5, 0x5DB9, 0xFAB6, 0x5DD0, 0xFAB7, 0x5F21, + 0xFAB8, 0x5F34, 0xFAB9, 0x5F67, 0xFABA, 0x5FB7, 0xFABB, 0x5FDE, 0xFABC, 0x605D, 0xFABD, 0x6085, 0xFABE, 0x608A, 0xFABF, 0x60DE, + 0xFAC0, 0x60D5, 0xFAC1, 0x6120, 0xFAC2, 0x60F2, 0xFAC3, 0x6111, 0xFAC4, 0x6137, 0xFAC5, 0x6130, 0xFAC6, 0x6198, 0xFAC7, 0x6213, + 0xFAC8, 0x62A6, 0xFAC9, 0x63F5, 0xFACA, 0x6460, 0xFACB, 0x649D, 0xFACC, 0x64CE, 0xFACD, 0x654E, 0xFACE, 0x6600, 0xFACF, 0x6615, + 0xFAD0, 0x663B, 0xFAD1, 0x6609, 0xFAD2, 0x662E, 0xFAD3, 0x661E, 0xFAD4, 0x6624, 0xFAD5, 0x6665, 0xFAD6, 0x6657, 0xFAD7, 0x6659, + 0xFAD8, 0xFA12, 0xFAD9, 0x6673, 0xFADA, 0x6699, 0xFADB, 0x66A0, 0xFADC, 0x66B2, 0xFADD, 0x66BF, 0xFADE, 0x66FA, 0xFADF, 0x670E, + 0xFAE0, 0xF929, 0xFAE1, 0x6766, 0xFAE2, 0x67BB, 0xFAE3, 0x6852, 0xFAE4, 0x67C0, 0xFAE5, 0x6801, 0xFAE6, 0x6844, 0xFAE7, 0x68CF, + 0xFAE8, 0xFA13, 0xFAE9, 0x6968, 0xFAEA, 0xFA14, 0xFAEB, 0x6998, 0xFAEC, 0x69E2, 0xFAED, 0x6A30, 0xFAEE, 0x6A6B, 0xFAEF, 0x6A46, + 0xFAF0, 0x6A73, 0xFAF1, 0x6A7E, 0xFAF2, 0x6AE2, 0xFAF3, 0x6AE4, 0xFAF4, 0x6BD6, 0xFAF5, 0x6C3F, 0xFAF6, 0x6C5C, 0xFAF7, 0x6C86, + 0xFAF8, 0x6C6F, 0xFAF9, 0x6CDA, 0xFAFA, 0x6D04, 0xFAFB, 0x6D87, 0xFAFC, 0x6D6F, 0xFB40, 0x6D96, 0xFB41, 0x6DAC, 0xFB42, 0x6DCF, + 0xFB43, 0x6DF8, 0xFB44, 0x6DF2, 0xFB45, 0x6DFC, 0xFB46, 0x6E39, 0xFB47, 0x6E5C, 0xFB48, 0x6E27, 0xFB49, 0x6E3C, 0xFB4A, 0x6EBF, + 0xFB4B, 0x6F88, 0xFB4C, 0x6FB5, 0xFB4D, 0x6FF5, 0xFB4E, 0x7005, 0xFB4F, 0x7007, 0xFB50, 0x7028, 0xFB51, 0x7085, 0xFB52, 0x70AB, + 0xFB53, 0x710F, 0xFB54, 0x7104, 0xFB55, 0x715C, 0xFB56, 0x7146, 0xFB57, 0x7147, 0xFB58, 0xFA15, 0xFB59, 0x71C1, 0xFB5A, 0x71FE, + 0xFB5B, 0x72B1, 0xFB5C, 0x72BE, 0xFB5D, 0x7324, 0xFB5E, 0xFA16, 0xFB5F, 0x7377, 0xFB60, 0x73BD, 0xFB61, 0x73C9, 0xFB62, 0x73D6, + 0xFB63, 0x73E3, 0xFB64, 0x73D2, 0xFB65, 0x7407, 0xFB66, 0x73F5, 0xFB67, 0x7426, 0xFB68, 0x742A, 0xFB69, 0x7429, 0xFB6A, 0x742E, + 0xFB6B, 0x7462, 0xFB6C, 0x7489, 0xFB6D, 0x749F, 0xFB6E, 0x7501, 0xFB6F, 0x756F, 0xFB70, 0x7682, 0xFB71, 0x769C, 0xFB72, 0x769E, + 0xFB73, 0x769B, 0xFB74, 0x76A6, 0xFB75, 0xFA17, 0xFB76, 0x7746, 0xFB77, 0x52AF, 0xFB78, 0x7821, 0xFB79, 0x784E, 0xFB7A, 0x7864, + 0xFB7B, 0x787A, 0xFB7C, 0x7930, 0xFB7D, 0xFA18, 0xFB7E, 0xFA19, 0xFB80, 0xFA1A, 0xFB81, 0x7994, 0xFB82, 0xFA1B, 0xFB83, 0x799B, + 0xFB84, 0x7AD1, 0xFB85, 0x7AE7, 0xFB86, 0xFA1C, 0xFB87, 0x7AEB, 0xFB88, 0x7B9E, 0xFB89, 0xFA1D, 0xFB8A, 0x7D48, 0xFB8B, 0x7D5C, + 0xFB8C, 0x7DB7, 0xFB8D, 0x7DA0, 0xFB8E, 0x7DD6, 0xFB8F, 0x7E52, 0xFB90, 0x7F47, 0xFB91, 0x7FA1, 0xFB92, 0xFA1E, 0xFB93, 0x8301, + 0xFB94, 0x8362, 0xFB95, 0x837F, 0xFB96, 0x83C7, 0xFB97, 0x83F6, 0xFB98, 0x8448, 0xFB99, 0x84B4, 0xFB9A, 0x8553, 0xFB9B, 0x8559, + 0xFB9C, 0x856B, 0xFB9D, 0xFA1F, 0xFB9E, 0x85B0, 0xFB9F, 0xFA20, 0xFBA0, 0xFA21, 0xFBA1, 0x8807, 0xFBA2, 0x88F5, 0xFBA3, 0x8A12, + 0xFBA4, 0x8A37, 0xFBA5, 0x8A79, 0xFBA6, 0x8AA7, 0xFBA7, 0x8ABE, 0xFBA8, 0x8ADF, 0xFBA9, 0xFA22, 0xFBAA, 0x8AF6, 0xFBAB, 0x8B53, + 0xFBAC, 0x8B7F, 0xFBAD, 0x8CF0, 0xFBAE, 0x8CF4, 0xFBAF, 0x8D12, 0xFBB0, 0x8D76, 0xFBB1, 0xFA23, 0xFBB2, 0x8ECF, 0xFBB3, 0xFA24, + 0xFBB4, 0xFA25, 0xFBB5, 0x9067, 0xFBB6, 0x90DE, 0xFBB7, 0xFA26, 0xFBB8, 0x9115, 0xFBB9, 0x9127, 0xFBBA, 0x91DA, 0xFBBB, 0x91D7, + 0xFBBC, 0x91DE, 0xFBBD, 0x91ED, 0xFBBE, 0x91EE, 0xFBBF, 0x91E4, 0xFBC0, 0x91E5, 0xFBC1, 0x9206, 0xFBC2, 0x9210, 0xFBC3, 0x920A, + 0xFBC4, 0x923A, 0xFBC5, 0x9240, 0xFBC6, 0x923C, 0xFBC7, 0x924E, 0xFBC8, 0x9259, 0xFBC9, 0x9251, 0xFBCA, 0x9239, 0xFBCB, 0x9267, + 0xFBCC, 0x92A7, 0xFBCD, 0x9277, 0xFBCE, 0x9278, 0xFBCF, 0x92E7, 0xFBD0, 0x92D7, 0xFBD1, 0x92D9, 0xFBD2, 0x92D0, 0xFBD3, 0xFA27, + 0xFBD4, 0x92D5, 0xFBD5, 0x92E0, 0xFBD6, 0x92D3, 0xFBD7, 0x9325, 0xFBD8, 0x9321, 0xFBD9, 0x92FB, 0xFBDA, 0xFA28, 0xFBDB, 0x931E, + 0xFBDC, 0x92FF, 0xFBDD, 0x931D, 0xFBDE, 0x9302, 0xFBDF, 0x9370, 0xFBE0, 0x9357, 0xFBE1, 0x93A4, 0xFBE2, 0x93C6, 0xFBE3, 0x93DE, + 0xFBE4, 0x93F8, 0xFBE5, 0x9431, 0xFBE6, 0x9445, 0xFBE7, 0x9448, 0xFBE8, 0x9592, 0xFBE9, 0xF9DC, 0xFBEA, 0xFA29, 0xFBEB, 0x969D, + 0xFBEC, 0x96AF, 0xFBED, 0x9733, 0xFBEE, 0x973B, 0xFBEF, 0x9743, 0xFBF0, 0x974D, 0xFBF1, 0x974F, 0xFBF2, 0x9751, 0xFBF3, 0x9755, + 0xFBF4, 0x9857, 0xFBF5, 0x9865, 0xFBF6, 0xFA2A, 0xFBF7, 0xFA2B, 0xFBF8, 0x9927, 0xFBF9, 0xFA2C, 0xFBFA, 0x999E, 0xFBFB, 0x9A4E, + 0xFBFC, 0x9AD9, 0xFC40, 0x9ADC, 0xFC41, 0x9B75, 0xFC42, 0x9B72, 0xFC43, 0x9B8F, 0xFC44, 0x9BB1, 0xFC45, 0x9BBB, 0xFC46, 0x9C00, + 0xFC47, 0x9D70, 0xFC48, 0x9D6B, 0xFC49, 0xFA2D, 0xFC4A, 0x9E19, 0xFC4B, 0x9ED1, 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */ +static const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */ + 0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4, + 0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE, + 0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9, + 0x0144, 0xA8BD, 0x0148, 0xA8BE, 0x014D, 0xA8AD, 0x016B, 0xA8B1, 0x01CE, 0xA8A3, 0x01D0, 0xA8AB, 0x01D2, 0xA8AF, 0x01D4, 0xA8B3, + 0x01D6, 0xA8B5, 0x01D8, 0xA8B6, 0x01DA, 0xA8B7, 0x01DC, 0xA8B8, 0x0251, 0xA8BB, 0x0261, 0xA8C0, 0x02C7, 0xA1A6, 0x02C9, 0xA1A5, + 0x02CA, 0xA840, 0x02CB, 0xA841, 0x02D9, 0xA842, 0x0391, 0xA6A1, 0x0392, 0xA6A2, 0x0393, 0xA6A3, 0x0394, 0xA6A4, 0x0395, 0xA6A5, + 0x0396, 0xA6A6, 0x0397, 0xA6A7, 0x0398, 0xA6A8, 0x0399, 0xA6A9, 0x039A, 0xA6AA, 0x039B, 0xA6AB, 0x039C, 0xA6AC, 0x039D, 0xA6AD, + 0x039E, 0xA6AE, 0x039F, 0xA6AF, 0x03A0, 0xA6B0, 0x03A1, 0xA6B1, 0x03A3, 0xA6B2, 0x03A4, 0xA6B3, 0x03A5, 0xA6B4, 0x03A6, 0xA6B5, + 0x03A7, 0xA6B6, 0x03A8, 0xA6B7, 0x03A9, 0xA6B8, 0x03B1, 0xA6C1, 0x03B2, 0xA6C2, 0x03B3, 0xA6C3, 0x03B4, 0xA6C4, 0x03B5, 0xA6C5, + 0x03B6, 0xA6C6, 0x03B7, 0xA6C7, 0x03B8, 0xA6C8, 0x03B9, 0xA6C9, 0x03BA, 0xA6CA, 0x03BB, 0xA6CB, 0x03BC, 0xA6CC, 0x03BD, 0xA6CD, + 0x03BE, 0xA6CE, 0x03BF, 0xA6CF, 0x03C0, 0xA6D0, 0x03C1, 0xA6D1, 0x03C3, 0xA6D2, 0x03C4, 0xA6D3, 0x03C5, 0xA6D4, 0x03C6, 0xA6D5, + 0x03C7, 0xA6D6, 0x03C8, 0xA6D7, 0x03C9, 0xA6D8, 0x0401, 0xA7A7, 0x0410, 0xA7A1, 0x0411, 0xA7A2, 0x0412, 0xA7A3, 0x0413, 0xA7A4, + 0x0414, 0xA7A5, 0x0415, 0xA7A6, 0x0416, 0xA7A8, 0x0417, 0xA7A9, 0x0418, 0xA7AA, 0x0419, 0xA7AB, 0x041A, 0xA7AC, 0x041B, 0xA7AD, + 0x041C, 0xA7AE, 0x041D, 0xA7AF, 0x041E, 0xA7B0, 0x041F, 0xA7B1, 0x0420, 0xA7B2, 0x0421, 0xA7B3, 0x0422, 0xA7B4, 0x0423, 0xA7B5, + 0x0424, 0xA7B6, 0x0425, 0xA7B7, 0x0426, 0xA7B8, 0x0427, 0xA7B9, 0x0428, 0xA7BA, 0x0429, 0xA7BB, 0x042A, 0xA7BC, 0x042B, 0xA7BD, + 0x042C, 0xA7BE, 0x042D, 0xA7BF, 0x042E, 0xA7C0, 0x042F, 0xA7C1, 0x0430, 0xA7D1, 0x0431, 0xA7D2, 0x0432, 0xA7D3, 0x0433, 0xA7D4, + 0x0434, 0xA7D5, 0x0435, 0xA7D6, 0x0436, 0xA7D8, 0x0437, 0xA7D9, 0x0438, 0xA7DA, 0x0439, 0xA7DB, 0x043A, 0xA7DC, 0x043B, 0xA7DD, + 0x043C, 0xA7DE, 0x043D, 0xA7DF, 0x043E, 0xA7E0, 0x043F, 0xA7E1, 0x0440, 0xA7E2, 0x0441, 0xA7E3, 0x0442, 0xA7E4, 0x0443, 0xA7E5, + 0x0444, 0xA7E6, 0x0445, 0xA7E7, 0x0446, 0xA7E8, 0x0447, 0xA7E9, 0x0448, 0xA7EA, 0x0449, 0xA7EB, 0x044A, 0xA7EC, 0x044B, 0xA7ED, + 0x044C, 0xA7EE, 0x044D, 0xA7EF, 0x044E, 0xA7F0, 0x044F, 0xA7F1, 0x0451, 0xA7D7, 0x2010, 0xA95C, 0x2013, 0xA843, 0x2014, 0xA1AA, + 0x2015, 0xA844, 0x2016, 0xA1AC, 0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1, 0x2025, 0xA845, 0x2026, 0xA1AD, + 0x2030, 0xA1EB, 0x2032, 0xA1E4, 0x2033, 0xA1E5, 0x2035, 0xA846, 0x203B, 0xA1F9, 0x20AC, 0x0080, 0x2103, 0xA1E6, 0x2105, 0xA847, + 0x2109, 0xA848, 0x2116, 0xA1ED, 0x2121, 0xA959, 0x2160, 0xA2F1, 0x2161, 0xA2F2, 0x2162, 0xA2F3, 0x2163, 0xA2F4, 0x2164, 0xA2F5, + 0x2165, 0xA2F6, 0x2166, 0xA2F7, 0x2167, 0xA2F8, 0x2168, 0xA2F9, 0x2169, 0xA2FA, 0x216A, 0xA2FB, 0x216B, 0xA2FC, 0x2170, 0xA2A1, + 0x2171, 0xA2A2, 0x2172, 0xA2A3, 0x2173, 0xA2A4, 0x2174, 0xA2A5, 0x2175, 0xA2A6, 0x2176, 0xA2A7, 0x2177, 0xA2A8, 0x2178, 0xA2A9, + 0x2179, 0xA2AA, 0x2190, 0xA1FB, 0x2191, 0xA1FC, 0x2192, 0xA1FA, 0x2193, 0xA1FD, 0x2196, 0xA849, 0x2197, 0xA84A, 0x2198, 0xA84B, + 0x2199, 0xA84C, 0x2208, 0xA1CA, 0x220F, 0xA1C7, 0x2211, 0xA1C6, 0x2215, 0xA84D, 0x221A, 0xA1CC, 0x221D, 0xA1D8, 0x221E, 0xA1DE, + 0x221F, 0xA84E, 0x2220, 0xA1CF, 0x2223, 0xA84F, 0x2225, 0xA1CE, 0x2227, 0xA1C4, 0x2228, 0xA1C5, 0x2229, 0xA1C9, 0x222A, 0xA1C8, + 0x222B, 0xA1D2, 0x222E, 0xA1D3, 0x2234, 0xA1E0, 0x2235, 0xA1DF, 0x2236, 0xA1C3, 0x2237, 0xA1CB, 0x223D, 0xA1D7, 0x2248, 0xA1D6, + 0x224C, 0xA1D5, 0x2252, 0xA850, 0x2260, 0xA1D9, 0x2261, 0xA1D4, 0x2264, 0xA1DC, 0x2265, 0xA1DD, 0x2266, 0xA851, 0x2267, 0xA852, + 0x226E, 0xA1DA, 0x226F, 0xA1DB, 0x2295, 0xA892, 0x2299, 0xA1D1, 0x22A5, 0xA1CD, 0x22BF, 0xA853, 0x2312, 0xA1D0, 0x2460, 0xA2D9, + 0x2461, 0xA2DA, 0x2462, 0xA2DB, 0x2463, 0xA2DC, 0x2464, 0xA2DD, 0x2465, 0xA2DE, 0x2466, 0xA2DF, 0x2467, 0xA2E0, 0x2468, 0xA2E1, + 0x2469, 0xA2E2, 0x2474, 0xA2C5, 0x2475, 0xA2C6, 0x2476, 0xA2C7, 0x2477, 0xA2C8, 0x2478, 0xA2C9, 0x2479, 0xA2CA, 0x247A, 0xA2CB, + 0x247B, 0xA2CC, 0x247C, 0xA2CD, 0x247D, 0xA2CE, 0x247E, 0xA2CF, 0x247F, 0xA2D0, 0x2480, 0xA2D1, 0x2481, 0xA2D2, 0x2482, 0xA2D3, + 0x2483, 0xA2D4, 0x2484, 0xA2D5, 0x2485, 0xA2D6, 0x2486, 0xA2D7, 0x2487, 0xA2D8, 0x2488, 0xA2B1, 0x2489, 0xA2B2, 0x248A, 0xA2B3, + 0x248B, 0xA2B4, 0x248C, 0xA2B5, 0x248D, 0xA2B6, 0x248E, 0xA2B7, 0x248F, 0xA2B8, 0x2490, 0xA2B9, 0x2491, 0xA2BA, 0x2492, 0xA2BB, + 0x2493, 0xA2BC, 0x2494, 0xA2BD, 0x2495, 0xA2BE, 0x2496, 0xA2BF, 0x2497, 0xA2C0, 0x2498, 0xA2C1, 0x2499, 0xA2C2, 0x249A, 0xA2C3, + 0x249B, 0xA2C4, 0x2500, 0xA9A4, 0x2501, 0xA9A5, 0x2502, 0xA9A6, 0x2503, 0xA9A7, 0x2504, 0xA9A8, 0x2505, 0xA9A9, 0x2506, 0xA9AA, + 0x2507, 0xA9AB, 0x2508, 0xA9AC, 0x2509, 0xA9AD, 0x250A, 0xA9AE, 0x250B, 0xA9AF, 0x250C, 0xA9B0, 0x250D, 0xA9B1, 0x250E, 0xA9B2, + 0x250F, 0xA9B3, 0x2510, 0xA9B4, 0x2511, 0xA9B5, 0x2512, 0xA9B6, 0x2513, 0xA9B7, 0x2514, 0xA9B8, 0x2515, 0xA9B9, 0x2516, 0xA9BA, + 0x2517, 0xA9BB, 0x2518, 0xA9BC, 0x2519, 0xA9BD, 0x251A, 0xA9BE, 0x251B, 0xA9BF, 0x251C, 0xA9C0, 0x251D, 0xA9C1, 0x251E, 0xA9C2, + 0x251F, 0xA9C3, 0x2520, 0xA9C4, 0x2521, 0xA9C5, 0x2522, 0xA9C6, 0x2523, 0xA9C7, 0x2524, 0xA9C8, 0x2525, 0xA9C9, 0x2526, 0xA9CA, + 0x2527, 0xA9CB, 0x2528, 0xA9CC, 0x2529, 0xA9CD, 0x252A, 0xA9CE, 0x252B, 0xA9CF, 0x252C, 0xA9D0, 0x252D, 0xA9D1, 0x252E, 0xA9D2, + 0x252F, 0xA9D3, 0x2530, 0xA9D4, 0x2531, 0xA9D5, 0x2532, 0xA9D6, 0x2533, 0xA9D7, 0x2534, 0xA9D8, 0x2535, 0xA9D9, 0x2536, 0xA9DA, + 0x2537, 0xA9DB, 0x2538, 0xA9DC, 0x2539, 0xA9DD, 0x253A, 0xA9DE, 0x253B, 0xA9DF, 0x253C, 0xA9E0, 0x253D, 0xA9E1, 0x253E, 0xA9E2, + 0x253F, 0xA9E3, 0x2540, 0xA9E4, 0x2541, 0xA9E5, 0x2542, 0xA9E6, 0x2543, 0xA9E7, 0x2544, 0xA9E8, 0x2545, 0xA9E9, 0x2546, 0xA9EA, + 0x2547, 0xA9EB, 0x2548, 0xA9EC, 0x2549, 0xA9ED, 0x254A, 0xA9EE, 0x254B, 0xA9EF, 0x2550, 0xA854, 0x2551, 0xA855, 0x2552, 0xA856, + 0x2553, 0xA857, 0x2554, 0xA858, 0x2555, 0xA859, 0x2556, 0xA85A, 0x2557, 0xA85B, 0x2558, 0xA85C, 0x2559, 0xA85D, 0x255A, 0xA85E, + 0x255B, 0xA85F, 0x255C, 0xA860, 0x255D, 0xA861, 0x255E, 0xA862, 0x255F, 0xA863, 0x2560, 0xA864, 0x2561, 0xA865, 0x2562, 0xA866, + 0x2563, 0xA867, 0x2564, 0xA868, 0x2565, 0xA869, 0x2566, 0xA86A, 0x2567, 0xA86B, 0x2568, 0xA86C, 0x2569, 0xA86D, 0x256A, 0xA86E, + 0x256B, 0xA86F, 0x256C, 0xA870, 0x256D, 0xA871, 0x256E, 0xA872, 0x256F, 0xA873, 0x2570, 0xA874, 0x2571, 0xA875, 0x2572, 0xA876, + 0x2573, 0xA877, 0x2581, 0xA878, 0x2582, 0xA879, 0x2583, 0xA87A, 0x2584, 0xA87B, 0x2585, 0xA87C, 0x2586, 0xA87D, 0x2587, 0xA87E, + 0x2588, 0xA880, 0x2589, 0xA881, 0x258A, 0xA882, 0x258B, 0xA883, 0x258C, 0xA884, 0x258D, 0xA885, 0x258E, 0xA886, 0x258F, 0xA887, + 0x2593, 0xA888, 0x2594, 0xA889, 0x2595, 0xA88A, 0x25A0, 0xA1F6, 0x25A1, 0xA1F5, 0x25B2, 0xA1F8, 0x25B3, 0xA1F7, 0x25BC, 0xA88B, + 0x25BD, 0xA88C, 0x25C6, 0xA1F4, 0x25C7, 0xA1F3, 0x25CB, 0xA1F0, 0x25CE, 0xA1F2, 0x25CF, 0xA1F1, 0x25E2, 0xA88D, 0x25E3, 0xA88E, + 0x25E4, 0xA88F, 0x25E5, 0xA890, 0x2605, 0xA1EF, 0x2606, 0xA1EE, 0x2609, 0xA891, 0x2640, 0xA1E2, 0x2642, 0xA1E1, 0x3000, 0xA1A1, + 0x3001, 0xA1A2, 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3005, 0xA1A9, 0x3006, 0xA965, 0x3007, 0xA996, 0x3008, 0xA1B4, 0x3009, 0xA1B5, + 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BE, 0x3011, 0xA1BF, + 0x3012, 0xA893, 0x3013, 0xA1FE, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3016, 0xA1BC, 0x3017, 0xA1BD, 0x301D, 0xA894, 0x301E, 0xA895, + 0x3021, 0xA940, 0x3022, 0xA941, 0x3023, 0xA942, 0x3024, 0xA943, 0x3025, 0xA944, 0x3026, 0xA945, 0x3027, 0xA946, 0x3028, 0xA947, + 0x3029, 0xA948, 0x3041, 0xA4A1, 0x3042, 0xA4A2, 0x3043, 0xA4A3, 0x3044, 0xA4A4, 0x3045, 0xA4A5, 0x3046, 0xA4A6, 0x3047, 0xA4A7, + 0x3048, 0xA4A8, 0x3049, 0xA4A9, 0x304A, 0xA4AA, 0x304B, 0xA4AB, 0x304C, 0xA4AC, 0x304D, 0xA4AD, 0x304E, 0xA4AE, 0x304F, 0xA4AF, + 0x3050, 0xA4B0, 0x3051, 0xA4B1, 0x3052, 0xA4B2, 0x3053, 0xA4B3, 0x3054, 0xA4B4, 0x3055, 0xA4B5, 0x3056, 0xA4B6, 0x3057, 0xA4B7, + 0x3058, 0xA4B8, 0x3059, 0xA4B9, 0x305A, 0xA4BA, 0x305B, 0xA4BB, 0x305C, 0xA4BC, 0x305D, 0xA4BD, 0x305E, 0xA4BE, 0x305F, 0xA4BF, + 0x3060, 0xA4C0, 0x3061, 0xA4C1, 0x3062, 0xA4C2, 0x3063, 0xA4C3, 0x3064, 0xA4C4, 0x3065, 0xA4C5, 0x3066, 0xA4C6, 0x3067, 0xA4C7, + 0x3068, 0xA4C8, 0x3069, 0xA4C9, 0x306A, 0xA4CA, 0x306B, 0xA4CB, 0x306C, 0xA4CC, 0x306D, 0xA4CD, 0x306E, 0xA4CE, 0x306F, 0xA4CF, + 0x3070, 0xA4D0, 0x3071, 0xA4D1, 0x3072, 0xA4D2, 0x3073, 0xA4D3, 0x3074, 0xA4D4, 0x3075, 0xA4D5, 0x3076, 0xA4D6, 0x3077, 0xA4D7, + 0x3078, 0xA4D8, 0x3079, 0xA4D9, 0x307A, 0xA4DA, 0x307B, 0xA4DB, 0x307C, 0xA4DC, 0x307D, 0xA4DD, 0x307E, 0xA4DE, 0x307F, 0xA4DF, + 0x3080, 0xA4E0, 0x3081, 0xA4E1, 0x3082, 0xA4E2, 0x3083, 0xA4E3, 0x3084, 0xA4E4, 0x3085, 0xA4E5, 0x3086, 0xA4E6, 0x3087, 0xA4E7, + 0x3088, 0xA4E8, 0x3089, 0xA4E9, 0x308A, 0xA4EA, 0x308B, 0xA4EB, 0x308C, 0xA4EC, 0x308D, 0xA4ED, 0x308E, 0xA4EE, 0x308F, 0xA4EF, + 0x3090, 0xA4F0, 0x3091, 0xA4F1, 0x3092, 0xA4F2, 0x3093, 0xA4F3, 0x309B, 0xA961, 0x309C, 0xA962, 0x309D, 0xA966, 0x309E, 0xA967, + 0x30A1, 0xA5A1, 0x30A2, 0xA5A2, 0x30A3, 0xA5A3, 0x30A4, 0xA5A4, 0x30A5, 0xA5A5, 0x30A6, 0xA5A6, 0x30A7, 0xA5A7, 0x30A8, 0xA5A8, + 0x30A9, 0xA5A9, 0x30AA, 0xA5AA, 0x30AB, 0xA5AB, 0x30AC, 0xA5AC, 0x30AD, 0xA5AD, 0x30AE, 0xA5AE, 0x30AF, 0xA5AF, 0x30B0, 0xA5B0, + 0x30B1, 0xA5B1, 0x30B2, 0xA5B2, 0x30B3, 0xA5B3, 0x30B4, 0xA5B4, 0x30B5, 0xA5B5, 0x30B6, 0xA5B6, 0x30B7, 0xA5B7, 0x30B8, 0xA5B8, + 0x30B9, 0xA5B9, 0x30BA, 0xA5BA, 0x30BB, 0xA5BB, 0x30BC, 0xA5BC, 0x30BD, 0xA5BD, 0x30BE, 0xA5BE, 0x30BF, 0xA5BF, 0x30C0, 0xA5C0, + 0x30C1, 0xA5C1, 0x30C2, 0xA5C2, 0x30C3, 0xA5C3, 0x30C4, 0xA5C4, 0x30C5, 0xA5C5, 0x30C6, 0xA5C6, 0x30C7, 0xA5C7, 0x30C8, 0xA5C8, + 0x30C9, 0xA5C9, 0x30CA, 0xA5CA, 0x30CB, 0xA5CB, 0x30CC, 0xA5CC, 0x30CD, 0xA5CD, 0x30CE, 0xA5CE, 0x30CF, 0xA5CF, 0x30D0, 0xA5D0, + 0x30D1, 0xA5D1, 0x30D2, 0xA5D2, 0x30D3, 0xA5D3, 0x30D4, 0xA5D4, 0x30D5, 0xA5D5, 0x30D6, 0xA5D6, 0x30D7, 0xA5D7, 0x30D8, 0xA5D8, + 0x30D9, 0xA5D9, 0x30DA, 0xA5DA, 0x30DB, 0xA5DB, 0x30DC, 0xA5DC, 0x30DD, 0xA5DD, 0x30DE, 0xA5DE, 0x30DF, 0xA5DF, 0x30E0, 0xA5E0, + 0x30E1, 0xA5E1, 0x30E2, 0xA5E2, 0x30E3, 0xA5E3, 0x30E4, 0xA5E4, 0x30E5, 0xA5E5, 0x30E6, 0xA5E6, 0x30E7, 0xA5E7, 0x30E8, 0xA5E8, + 0x30E9, 0xA5E9, 0x30EA, 0xA5EA, 0x30EB, 0xA5EB, 0x30EC, 0xA5EC, 0x30ED, 0xA5ED, 0x30EE, 0xA5EE, 0x30EF, 0xA5EF, 0x30F0, 0xA5F0, + 0x30F1, 0xA5F1, 0x30F2, 0xA5F2, 0x30F3, 0xA5F3, 0x30F4, 0xA5F4, 0x30F5, 0xA5F5, 0x30F6, 0xA5F6, 0x30FC, 0xA960, 0x30FD, 0xA963, + 0x30FE, 0xA964, 0x3105, 0xA8C5, 0x3106, 0xA8C6, 0x3107, 0xA8C7, 0x3108, 0xA8C8, 0x3109, 0xA8C9, 0x310A, 0xA8CA, 0x310B, 0xA8CB, + 0x310C, 0xA8CC, 0x310D, 0xA8CD, 0x310E, 0xA8CE, 0x310F, 0xA8CF, 0x3110, 0xA8D0, 0x3111, 0xA8D1, 0x3112, 0xA8D2, 0x3113, 0xA8D3, + 0x3114, 0xA8D4, 0x3115, 0xA8D5, 0x3116, 0xA8D6, 0x3117, 0xA8D7, 0x3118, 0xA8D8, 0x3119, 0xA8D9, 0x311A, 0xA8DA, 0x311B, 0xA8DB, + 0x311C, 0xA8DC, 0x311D, 0xA8DD, 0x311E, 0xA8DE, 0x311F, 0xA8DF, 0x3120, 0xA8E0, 0x3121, 0xA8E1, 0x3122, 0xA8E2, 0x3123, 0xA8E3, + 0x3124, 0xA8E4, 0x3125, 0xA8E5, 0x3126, 0xA8E6, 0x3127, 0xA8E7, 0x3128, 0xA8E8, 0x3129, 0xA8E9, 0x3220, 0xA2E5, 0x3221, 0xA2E6, + 0x3222, 0xA2E7, 0x3223, 0xA2E8, 0x3224, 0xA2E9, 0x3225, 0xA2EA, 0x3226, 0xA2EB, 0x3227, 0xA2EC, 0x3228, 0xA2ED, 0x3229, 0xA2EE, + 0x3231, 0xA95A, 0x32A3, 0xA949, 0x338E, 0xA94A, 0x338F, 0xA94B, 0x339C, 0xA94C, 0x339D, 0xA94D, 0x339E, 0xA94E, 0x33A1, 0xA94F, + 0x33C4, 0xA950, 0x33CE, 0xA951, 0x33D1, 0xA952, 0x33D2, 0xA953, 0x33D5, 0xA954, 0x4E00, 0xD2BB, 0x4E01, 0xB6A1, 0x4E02, 0x8140, + 0x4E03, 0xC6DF, 0x4E04, 0x8141, 0x4E05, 0x8142, 0x4E06, 0x8143, 0x4E07, 0xCDF2, 0x4E08, 0xD5C9, 0x4E09, 0xC8FD, 0x4E0A, 0xC9CF, + 0x4E0B, 0xCFC2, 0x4E0C, 0xD8A2, 0x4E0D, 0xB2BB, 0x4E0E, 0xD3EB, 0x4E0F, 0x8144, 0x4E10, 0xD8A4, 0x4E11, 0xB3F3, 0x4E12, 0x8145, + 0x4E13, 0xD7A8, 0x4E14, 0xC7D2, 0x4E15, 0xD8A7, 0x4E16, 0xCAC0, 0x4E17, 0x8146, 0x4E18, 0xC7F0, 0x4E19, 0xB1FB, 0x4E1A, 0xD2B5, + 0x4E1B, 0xB4D4, 0x4E1C, 0xB6AB, 0x4E1D, 0xCBBF, 0x4E1E, 0xD8A9, 0x4E1F, 0x8147, 0x4E20, 0x8148, 0x4E21, 0x8149, 0x4E22, 0xB6AA, + 0x4E23, 0x814A, 0x4E24, 0xC1BD, 0x4E25, 0xD1CF, 0x4E26, 0x814B, 0x4E27, 0xC9A5, 0x4E28, 0xD8AD, 0x4E29, 0x814C, 0x4E2A, 0xB8F6, + 0x4E2B, 0xD1BE, 0x4E2C, 0xE3DC, 0x4E2D, 0xD6D0, 0x4E2E, 0x814D, 0x4E2F, 0x814E, 0x4E30, 0xB7E1, 0x4E31, 0x814F, 0x4E32, 0xB4AE, + 0x4E33, 0x8150, 0x4E34, 0xC1D9, 0x4E35, 0x8151, 0x4E36, 0xD8BC, 0x4E37, 0x8152, 0x4E38, 0xCDE8, 0x4E39, 0xB5A4, 0x4E3A, 0xCEAA, + 0x4E3B, 0xD6F7, 0x4E3C, 0x8153, 0x4E3D, 0xC0F6, 0x4E3E, 0xBED9, 0x4E3F, 0xD8AF, 0x4E40, 0x8154, 0x4E41, 0x8155, 0x4E42, 0x8156, + 0x4E43, 0xC4CB, 0x4E44, 0x8157, 0x4E45, 0xBEC3, 0x4E46, 0x8158, 0x4E47, 0xD8B1, 0x4E48, 0xC3B4, 0x4E49, 0xD2E5, 0x4E4A, 0x8159, + 0x4E4B, 0xD6AE, 0x4E4C, 0xCEDA, 0x4E4D, 0xD5A7, 0x4E4E, 0xBAF5, 0x4E4F, 0xB7A6, 0x4E50, 0xC0D6, 0x4E51, 0x815A, 0x4E52, 0xC6B9, + 0x4E53, 0xC5D2, 0x4E54, 0xC7C7, 0x4E55, 0x815B, 0x4E56, 0xB9D4, 0x4E57, 0x815C, 0x4E58, 0xB3CB, 0x4E59, 0xD2D2, 0x4E5A, 0x815D, + 0x4E5B, 0x815E, 0x4E5C, 0xD8BF, 0x4E5D, 0xBEC5, 0x4E5E, 0xC6F2, 0x4E5F, 0xD2B2, 0x4E60, 0xCFB0, 0x4E61, 0xCFE7, 0x4E62, 0x815F, + 0x4E63, 0x8160, 0x4E64, 0x8161, 0x4E65, 0x8162, 0x4E66, 0xCAE9, 0x4E67, 0x8163, 0x4E68, 0x8164, 0x4E69, 0xD8C0, 0x4E6A, 0x8165, + 0x4E6B, 0x8166, 0x4E6C, 0x8167, 0x4E6D, 0x8168, 0x4E6E, 0x8169, 0x4E6F, 0x816A, 0x4E70, 0xC2F2, 0x4E71, 0xC2D2, 0x4E72, 0x816B, + 0x4E73, 0xC8E9, 0x4E74, 0x816C, 0x4E75, 0x816D, 0x4E76, 0x816E, 0x4E77, 0x816F, 0x4E78, 0x8170, 0x4E79, 0x8171, 0x4E7A, 0x8172, + 0x4E7B, 0x8173, 0x4E7C, 0x8174, 0x4E7D, 0x8175, 0x4E7E, 0xC7AC, 0x4E7F, 0x8176, 0x4E80, 0x8177, 0x4E81, 0x8178, 0x4E82, 0x8179, + 0x4E83, 0x817A, 0x4E84, 0x817B, 0x4E85, 0x817C, 0x4E86, 0xC1CB, 0x4E87, 0x817D, 0x4E88, 0xD3E8, 0x4E89, 0xD5F9, 0x4E8A, 0x817E, + 0x4E8B, 0xCAC2, 0x4E8C, 0xB6FE, 0x4E8D, 0xD8A1, 0x4E8E, 0xD3DA, 0x4E8F, 0xBFF7, 0x4E90, 0x8180, 0x4E91, 0xD4C6, 0x4E92, 0xBBA5, + 0x4E93, 0xD8C1, 0x4E94, 0xCEE5, 0x4E95, 0xBEAE, 0x4E96, 0x8181, 0x4E97, 0x8182, 0x4E98, 0xD8A8, 0x4E99, 0x8183, 0x4E9A, 0xD1C7, + 0x4E9B, 0xD0A9, 0x4E9C, 0x8184, 0x4E9D, 0x8185, 0x4E9E, 0x8186, 0x4E9F, 0xD8BD, 0x4EA0, 0xD9EF, 0x4EA1, 0xCDF6, 0x4EA2, 0xBFBA, + 0x4EA3, 0x8187, 0x4EA4, 0xBDBB, 0x4EA5, 0xBAA5, 0x4EA6, 0xD2E0, 0x4EA7, 0xB2FA, 0x4EA8, 0xBAE0, 0x4EA9, 0xC4B6, 0x4EAA, 0x8188, + 0x4EAB, 0xCFED, 0x4EAC, 0xBEA9, 0x4EAD, 0xCDA4, 0x4EAE, 0xC1C1, 0x4EAF, 0x8189, 0x4EB0, 0x818A, 0x4EB1, 0x818B, 0x4EB2, 0xC7D7, + 0x4EB3, 0xD9F1, 0x4EB4, 0x818C, 0x4EB5, 0xD9F4, 0x4EB6, 0x818D, 0x4EB7, 0x818E, 0x4EB8, 0x818F, 0x4EB9, 0x8190, 0x4EBA, 0xC8CB, + 0x4EBB, 0xD8E9, 0x4EBC, 0x8191, 0x4EBD, 0x8192, 0x4EBE, 0x8193, 0x4EBF, 0xD2DA, 0x4EC0, 0xCAB2, 0x4EC1, 0xC8CA, 0x4EC2, 0xD8EC, + 0x4EC3, 0xD8EA, 0x4EC4, 0xD8C6, 0x4EC5, 0xBDF6, 0x4EC6, 0xC6CD, 0x4EC7, 0xB3F0, 0x4EC8, 0x8194, 0x4EC9, 0xD8EB, 0x4ECA, 0xBDF1, + 0x4ECB, 0xBDE9, 0x4ECC, 0x8195, 0x4ECD, 0xC8D4, 0x4ECE, 0xB4D3, 0x4ECF, 0x8196, 0x4ED0, 0x8197, 0x4ED1, 0xC2D8, 0x4ED2, 0x8198, + 0x4ED3, 0xB2D6, 0x4ED4, 0xD7D0, 0x4ED5, 0xCACB, 0x4ED6, 0xCBFB, 0x4ED7, 0xD5CC, 0x4ED8, 0xB8B6, 0x4ED9, 0xCFC9, 0x4EDA, 0x8199, + 0x4EDB, 0x819A, 0x4EDC, 0x819B, 0x4EDD, 0xD9DA, 0x4EDE, 0xD8F0, 0x4EDF, 0xC7AA, 0x4EE0, 0x819C, 0x4EE1, 0xD8EE, 0x4EE2, 0x819D, + 0x4EE3, 0xB4FA, 0x4EE4, 0xC1EE, 0x4EE5, 0xD2D4, 0x4EE6, 0x819E, 0x4EE7, 0x819F, 0x4EE8, 0xD8ED, 0x4EE9, 0x81A0, 0x4EEA, 0xD2C7, + 0x4EEB, 0xD8EF, 0x4EEC, 0xC3C7, 0x4EED, 0x81A1, 0x4EEE, 0x81A2, 0x4EEF, 0x81A3, 0x4EF0, 0xD1F6, 0x4EF1, 0x81A4, 0x4EF2, 0xD6D9, + 0x4EF3, 0xD8F2, 0x4EF4, 0x81A5, 0x4EF5, 0xD8F5, 0x4EF6, 0xBCFE, 0x4EF7, 0xBCDB, 0x4EF8, 0x81A6, 0x4EF9, 0x81A7, 0x4EFA, 0x81A8, + 0x4EFB, 0xC8CE, 0x4EFC, 0x81A9, 0x4EFD, 0xB7DD, 0x4EFE, 0x81AA, 0x4EFF, 0xB7C2, 0x4F00, 0x81AB, 0x4F01, 0xC6F3, 0x4F02, 0x81AC, + 0x4F03, 0x81AD, 0x4F04, 0x81AE, 0x4F05, 0x81AF, 0x4F06, 0x81B0, 0x4F07, 0x81B1, 0x4F08, 0x81B2, 0x4F09, 0xD8F8, 0x4F0A, 0xD2C1, + 0x4F0B, 0x81B3, 0x4F0C, 0x81B4, 0x4F0D, 0xCEE9, 0x4F0E, 0xBCBF, 0x4F0F, 0xB7FC, 0x4F10, 0xB7A5, 0x4F11, 0xD0DD, 0x4F12, 0x81B5, + 0x4F13, 0x81B6, 0x4F14, 0x81B7, 0x4F15, 0x81B8, 0x4F16, 0x81B9, 0x4F17, 0xD6DA, 0x4F18, 0xD3C5, 0x4F19, 0xBBEF, 0x4F1A, 0xBBE1, + 0x4F1B, 0xD8F1, 0x4F1C, 0x81BA, 0x4F1D, 0x81BB, 0x4F1E, 0xC9A1, 0x4F1F, 0xCEB0, 0x4F20, 0xB4AB, 0x4F21, 0x81BC, 0x4F22, 0xD8F3, + 0x4F23, 0x81BD, 0x4F24, 0xC9CB, 0x4F25, 0xD8F6, 0x4F26, 0xC2D7, 0x4F27, 0xD8F7, 0x4F28, 0x81BE, 0x4F29, 0x81BF, 0x4F2A, 0xCEB1, + 0x4F2B, 0xD8F9, 0x4F2C, 0x81C0, 0x4F2D, 0x81C1, 0x4F2E, 0x81C2, 0x4F2F, 0xB2AE, 0x4F30, 0xB9C0, 0x4F31, 0x81C3, 0x4F32, 0xD9A3, + 0x4F33, 0x81C4, 0x4F34, 0xB0E9, 0x4F35, 0x81C5, 0x4F36, 0xC1E6, 0x4F37, 0x81C6, 0x4F38, 0xC9EC, 0x4F39, 0x81C7, 0x4F3A, 0xCBC5, + 0x4F3B, 0x81C8, 0x4F3C, 0xCBC6, 0x4F3D, 0xD9A4, 0x4F3E, 0x81C9, 0x4F3F, 0x81CA, 0x4F40, 0x81CB, 0x4F41, 0x81CC, 0x4F42, 0x81CD, + 0x4F43, 0xB5E8, 0x4F44, 0x81CE, 0x4F45, 0x81CF, 0x4F46, 0xB5AB, 0x4F47, 0x81D0, 0x4F48, 0x81D1, 0x4F49, 0x81D2, 0x4F4A, 0x81D3, + 0x4F4B, 0x81D4, 0x4F4C, 0x81D5, 0x4F4D, 0xCEBB, 0x4F4E, 0xB5CD, 0x4F4F, 0xD7A1, 0x4F50, 0xD7F4, 0x4F51, 0xD3D3, 0x4F52, 0x81D6, + 0x4F53, 0xCCE5, 0x4F54, 0x81D7, 0x4F55, 0xBACE, 0x4F56, 0x81D8, 0x4F57, 0xD9A2, 0x4F58, 0xD9DC, 0x4F59, 0xD3E0, 0x4F5A, 0xD8FD, + 0x4F5B, 0xB7F0, 0x4F5C, 0xD7F7, 0x4F5D, 0xD8FE, 0x4F5E, 0xD8FA, 0x4F5F, 0xD9A1, 0x4F60, 0xC4E3, 0x4F61, 0x81D9, 0x4F62, 0x81DA, + 0x4F63, 0xD3B6, 0x4F64, 0xD8F4, 0x4F65, 0xD9DD, 0x4F66, 0x81DB, 0x4F67, 0xD8FB, 0x4F68, 0x81DC, 0x4F69, 0xC5E5, 0x4F6A, 0x81DD, + 0x4F6B, 0x81DE, 0x4F6C, 0xC0D0, 0x4F6D, 0x81DF, 0x4F6E, 0x81E0, 0x4F6F, 0xD1F0, 0x4F70, 0xB0DB, 0x4F71, 0x81E1, 0x4F72, 0x81E2, + 0x4F73, 0xBCD1, 0x4F74, 0xD9A6, 0x4F75, 0x81E3, 0x4F76, 0xD9A5, 0x4F77, 0x81E4, 0x4F78, 0x81E5, 0x4F79, 0x81E6, 0x4F7A, 0x81E7, + 0x4F7B, 0xD9AC, 0x4F7C, 0xD9AE, 0x4F7D, 0x81E8, 0x4F7E, 0xD9AB, 0x4F7F, 0xCAB9, 0x4F80, 0x81E9, 0x4F81, 0x81EA, 0x4F82, 0x81EB, + 0x4F83, 0xD9A9, 0x4F84, 0xD6B6, 0x4F85, 0x81EC, 0x4F86, 0x81ED, 0x4F87, 0x81EE, 0x4F88, 0xB3DE, 0x4F89, 0xD9A8, 0x4F8A, 0x81EF, + 0x4F8B, 0xC0FD, 0x4F8C, 0x81F0, 0x4F8D, 0xCACC, 0x4F8E, 0x81F1, 0x4F8F, 0xD9AA, 0x4F90, 0x81F2, 0x4F91, 0xD9A7, 0x4F92, 0x81F3, + 0x4F93, 0x81F4, 0x4F94, 0xD9B0, 0x4F95, 0x81F5, 0x4F96, 0x81F6, 0x4F97, 0xB6B1, 0x4F98, 0x81F7, 0x4F99, 0x81F8, 0x4F9A, 0x81F9, + 0x4F9B, 0xB9A9, 0x4F9C, 0x81FA, 0x4F9D, 0xD2C0, 0x4F9E, 0x81FB, 0x4F9F, 0x81FC, 0x4FA0, 0xCFC0, 0x4FA1, 0x81FD, 0x4FA2, 0x81FE, + 0x4FA3, 0xC2C2, 0x4FA4, 0x8240, 0x4FA5, 0xBDC4, 0x4FA6, 0xD5EC, 0x4FA7, 0xB2E0, 0x4FA8, 0xC7C8, 0x4FA9, 0xBFEB, 0x4FAA, 0xD9AD, + 0x4FAB, 0x8241, 0x4FAC, 0xD9AF, 0x4FAD, 0x8242, 0x4FAE, 0xCEEA, 0x4FAF, 0xBAEE, 0x4FB0, 0x8243, 0x4FB1, 0x8244, 0x4FB2, 0x8245, + 0x4FB3, 0x8246, 0x4FB4, 0x8247, 0x4FB5, 0xC7D6, 0x4FB6, 0x8248, 0x4FB7, 0x8249, 0x4FB8, 0x824A, 0x4FB9, 0x824B, 0x4FBA, 0x824C, + 0x4FBB, 0x824D, 0x4FBC, 0x824E, 0x4FBD, 0x824F, 0x4FBE, 0x8250, 0x4FBF, 0xB1E3, 0x4FC0, 0x8251, 0x4FC1, 0x8252, 0x4FC2, 0x8253, + 0x4FC3, 0xB4D9, 0x4FC4, 0xB6ED, 0x4FC5, 0xD9B4, 0x4FC6, 0x8254, 0x4FC7, 0x8255, 0x4FC8, 0x8256, 0x4FC9, 0x8257, 0x4FCA, 0xBFA1, + 0x4FCB, 0x8258, 0x4FCC, 0x8259, 0x4FCD, 0x825A, 0x4FCE, 0xD9DE, 0x4FCF, 0xC7CE, 0x4FD0, 0xC0FE, 0x4FD1, 0xD9B8, 0x4FD2, 0x825B, + 0x4FD3, 0x825C, 0x4FD4, 0x825D, 0x4FD5, 0x825E, 0x4FD6, 0x825F, 0x4FD7, 0xCBD7, 0x4FD8, 0xB7FD, 0x4FD9, 0x8260, 0x4FDA, 0xD9B5, + 0x4FDB, 0x8261, 0x4FDC, 0xD9B7, 0x4FDD, 0xB1A3, 0x4FDE, 0xD3E1, 0x4FDF, 0xD9B9, 0x4FE0, 0x8262, 0x4FE1, 0xD0C5, 0x4FE2, 0x8263, + 0x4FE3, 0xD9B6, 0x4FE4, 0x8264, 0x4FE5, 0x8265, 0x4FE6, 0xD9B1, 0x4FE7, 0x8266, 0x4FE8, 0xD9B2, 0x4FE9, 0xC1A9, 0x4FEA, 0xD9B3, + 0x4FEB, 0x8267, 0x4FEC, 0x8268, 0x4FED, 0xBCF3, 0x4FEE, 0xD0DE, 0x4FEF, 0xB8A9, 0x4FF0, 0x8269, 0x4FF1, 0xBEE3, 0x4FF2, 0x826A, + 0x4FF3, 0xD9BD, 0x4FF4, 0x826B, 0x4FF5, 0x826C, 0x4FF6, 0x826D, 0x4FF7, 0x826E, 0x4FF8, 0xD9BA, 0x4FF9, 0x826F, 0x4FFA, 0xB0B3, + 0x4FFB, 0x8270, 0x4FFC, 0x8271, 0x4FFD, 0x8272, 0x4FFE, 0xD9C2, 0x4FFF, 0x8273, 0x5000, 0x8274, 0x5001, 0x8275, 0x5002, 0x8276, + 0x5003, 0x8277, 0x5004, 0x8278, 0x5005, 0x8279, 0x5006, 0x827A, 0x5007, 0x827B, 0x5008, 0x827C, 0x5009, 0x827D, 0x500A, 0x827E, + 0x500B, 0x8280, 0x500C, 0xD9C4, 0x500D, 0xB1B6, 0x500E, 0x8281, 0x500F, 0xD9BF, 0x5010, 0x8282, 0x5011, 0x8283, 0x5012, 0xB5B9, + 0x5013, 0x8284, 0x5014, 0xBEF3, 0x5015, 0x8285, 0x5016, 0x8286, 0x5017, 0x8287, 0x5018, 0xCCC8, 0x5019, 0xBAF2, 0x501A, 0xD2D0, + 0x501B, 0x8288, 0x501C, 0xD9C3, 0x501D, 0x8289, 0x501E, 0x828A, 0x501F, 0xBDE8, 0x5020, 0x828B, 0x5021, 0xB3AB, 0x5022, 0x828C, + 0x5023, 0x828D, 0x5024, 0x828E, 0x5025, 0xD9C5, 0x5026, 0xBEEB, 0x5027, 0x828F, 0x5028, 0xD9C6, 0x5029, 0xD9BB, 0x502A, 0xC4DF, + 0x502B, 0x8290, 0x502C, 0xD9BE, 0x502D, 0xD9C1, 0x502E, 0xD9C0, 0x502F, 0x8291, 0x5030, 0x8292, 0x5031, 0x8293, 0x5032, 0x8294, + 0x5033, 0x8295, 0x5034, 0x8296, 0x5035, 0x8297, 0x5036, 0x8298, 0x5037, 0x8299, 0x5038, 0x829A, 0x5039, 0x829B, 0x503A, 0xD5AE, + 0x503B, 0x829C, 0x503C, 0xD6B5, 0x503D, 0x829D, 0x503E, 0xC7E3, 0x503F, 0x829E, 0x5040, 0x829F, 0x5041, 0x82A0, 0x5042, 0x82A1, + 0x5043, 0xD9C8, 0x5044, 0x82A2, 0x5045, 0x82A3, 0x5046, 0x82A4, 0x5047, 0xBCD9, 0x5048, 0xD9CA, 0x5049, 0x82A5, 0x504A, 0x82A6, + 0x504B, 0x82A7, 0x504C, 0xD9BC, 0x504D, 0x82A8, 0x504E, 0xD9CB, 0x504F, 0xC6AB, 0x5050, 0x82A9, 0x5051, 0x82AA, 0x5052, 0x82AB, + 0x5053, 0x82AC, 0x5054, 0x82AD, 0x5055, 0xD9C9, 0x5056, 0x82AE, 0x5057, 0x82AF, 0x5058, 0x82B0, 0x5059, 0x82B1, 0x505A, 0xD7F6, + 0x505B, 0x82B2, 0x505C, 0xCDA3, 0x505D, 0x82B3, 0x505E, 0x82B4, 0x505F, 0x82B5, 0x5060, 0x82B6, 0x5061, 0x82B7, 0x5062, 0x82B8, + 0x5063, 0x82B9, 0x5064, 0x82BA, 0x5065, 0xBDA1, 0x5066, 0x82BB, 0x5067, 0x82BC, 0x5068, 0x82BD, 0x5069, 0x82BE, 0x506A, 0x82BF, + 0x506B, 0x82C0, 0x506C, 0xD9CC, 0x506D, 0x82C1, 0x506E, 0x82C2, 0x506F, 0x82C3, 0x5070, 0x82C4, 0x5071, 0x82C5, 0x5072, 0x82C6, + 0x5073, 0x82C7, 0x5074, 0x82C8, 0x5075, 0x82C9, 0x5076, 0xC5BC, 0x5077, 0xCDB5, 0x5078, 0x82CA, 0x5079, 0x82CB, 0x507A, 0x82CC, + 0x507B, 0xD9CD, 0x507C, 0x82CD, 0x507D, 0x82CE, 0x507E, 0xD9C7, 0x507F, 0xB3A5, 0x5080, 0xBFFE, 0x5081, 0x82CF, 0x5082, 0x82D0, + 0x5083, 0x82D1, 0x5084, 0x82D2, 0x5085, 0xB8B5, 0x5086, 0x82D3, 0x5087, 0x82D4, 0x5088, 0xC0FC, 0x5089, 0x82D5, 0x508A, 0x82D6, + 0x508B, 0x82D7, 0x508C, 0x82D8, 0x508D, 0xB0F8, 0x508E, 0x82D9, 0x508F, 0x82DA, 0x5090, 0x82DB, 0x5091, 0x82DC, 0x5092, 0x82DD, + 0x5093, 0x82DE, 0x5094, 0x82DF, 0x5095, 0x82E0, 0x5096, 0x82E1, 0x5097, 0x82E2, 0x5098, 0x82E3, 0x5099, 0x82E4, 0x509A, 0x82E5, + 0x509B, 0x82E6, 0x509C, 0x82E7, 0x509D, 0x82E8, 0x509E, 0x82E9, 0x509F, 0x82EA, 0x50A0, 0x82EB, 0x50A1, 0x82EC, 0x50A2, 0x82ED, + 0x50A3, 0xB4F6, 0x50A4, 0x82EE, 0x50A5, 0xD9CE, 0x50A6, 0x82EF, 0x50A7, 0xD9CF, 0x50A8, 0xB4A2, 0x50A9, 0xD9D0, 0x50AA, 0x82F0, + 0x50AB, 0x82F1, 0x50AC, 0xB4DF, 0x50AD, 0x82F2, 0x50AE, 0x82F3, 0x50AF, 0x82F4, 0x50B0, 0x82F5, 0x50B1, 0x82F6, 0x50B2, 0xB0C1, + 0x50B3, 0x82F7, 0x50B4, 0x82F8, 0x50B5, 0x82F9, 0x50B6, 0x82FA, 0x50B7, 0x82FB, 0x50B8, 0x82FC, 0x50B9, 0x82FD, 0x50BA, 0xD9D1, + 0x50BB, 0xC9B5, 0x50BC, 0x82FE, 0x50BD, 0x8340, 0x50BE, 0x8341, 0x50BF, 0x8342, 0x50C0, 0x8343, 0x50C1, 0x8344, 0x50C2, 0x8345, + 0x50C3, 0x8346, 0x50C4, 0x8347, 0x50C5, 0x8348, 0x50C6, 0x8349, 0x50C7, 0x834A, 0x50C8, 0x834B, 0x50C9, 0x834C, 0x50CA, 0x834D, + 0x50CB, 0x834E, 0x50CC, 0x834F, 0x50CD, 0x8350, 0x50CE, 0x8351, 0x50CF, 0xCFF1, 0x50D0, 0x8352, 0x50D1, 0x8353, 0x50D2, 0x8354, + 0x50D3, 0x8355, 0x50D4, 0x8356, 0x50D5, 0x8357, 0x50D6, 0xD9D2, 0x50D7, 0x8358, 0x50D8, 0x8359, 0x50D9, 0x835A, 0x50DA, 0xC1C5, + 0x50DB, 0x835B, 0x50DC, 0x835C, 0x50DD, 0x835D, 0x50DE, 0x835E, 0x50DF, 0x835F, 0x50E0, 0x8360, 0x50E1, 0x8361, 0x50E2, 0x8362, + 0x50E3, 0x8363, 0x50E4, 0x8364, 0x50E5, 0x8365, 0x50E6, 0xD9D6, 0x50E7, 0xC9AE, 0x50E8, 0x8366, 0x50E9, 0x8367, 0x50EA, 0x8368, + 0x50EB, 0x8369, 0x50EC, 0xD9D5, 0x50ED, 0xD9D4, 0x50EE, 0xD9D7, 0x50EF, 0x836A, 0x50F0, 0x836B, 0x50F1, 0x836C, 0x50F2, 0x836D, + 0x50F3, 0xCBDB, 0x50F4, 0x836E, 0x50F5, 0xBDA9, 0x50F6, 0x836F, 0x50F7, 0x8370, 0x50F8, 0x8371, 0x50F9, 0x8372, 0x50FA, 0x8373, + 0x50FB, 0xC6A7, 0x50FC, 0x8374, 0x50FD, 0x8375, 0x50FE, 0x8376, 0x50FF, 0x8377, 0x5100, 0x8378, 0x5101, 0x8379, 0x5102, 0x837A, + 0x5103, 0x837B, 0x5104, 0x837C, 0x5105, 0x837D, 0x5106, 0xD9D3, 0x5107, 0xD9D8, 0x5108, 0x837E, 0x5109, 0x8380, 0x510A, 0x8381, + 0x510B, 0xD9D9, 0x510C, 0x8382, 0x510D, 0x8383, 0x510E, 0x8384, 0x510F, 0x8385, 0x5110, 0x8386, 0x5111, 0x8387, 0x5112, 0xC8E5, + 0x5113, 0x8388, 0x5114, 0x8389, 0x5115, 0x838A, 0x5116, 0x838B, 0x5117, 0x838C, 0x5118, 0x838D, 0x5119, 0x838E, 0x511A, 0x838F, + 0x511B, 0x8390, 0x511C, 0x8391, 0x511D, 0x8392, 0x511E, 0x8393, 0x511F, 0x8394, 0x5120, 0x8395, 0x5121, 0xC0DC, 0x5122, 0x8396, + 0x5123, 0x8397, 0x5124, 0x8398, 0x5125, 0x8399, 0x5126, 0x839A, 0x5127, 0x839B, 0x5128, 0x839C, 0x5129, 0x839D, 0x512A, 0x839E, + 0x512B, 0x839F, 0x512C, 0x83A0, 0x512D, 0x83A1, 0x512E, 0x83A2, 0x512F, 0x83A3, 0x5130, 0x83A4, 0x5131, 0x83A5, 0x5132, 0x83A6, + 0x5133, 0x83A7, 0x5134, 0x83A8, 0x5135, 0x83A9, 0x5136, 0x83AA, 0x5137, 0x83AB, 0x5138, 0x83AC, 0x5139, 0x83AD, 0x513A, 0x83AE, + 0x513B, 0x83AF, 0x513C, 0x83B0, 0x513D, 0x83B1, 0x513E, 0x83B2, 0x513F, 0xB6F9, 0x5140, 0xD8A3, 0x5141, 0xD4CA, 0x5142, 0x83B3, + 0x5143, 0xD4AA, 0x5144, 0xD0D6, 0x5145, 0xB3E4, 0x5146, 0xD5D7, 0x5147, 0x83B4, 0x5148, 0xCFC8, 0x5149, 0xB9E2, 0x514A, 0x83B5, + 0x514B, 0xBFCB, 0x514C, 0x83B6, 0x514D, 0xC3E2, 0x514E, 0x83B7, 0x514F, 0x83B8, 0x5150, 0x83B9, 0x5151, 0xB6D2, 0x5152, 0x83BA, + 0x5153, 0x83BB, 0x5154, 0xCDC3, 0x5155, 0xD9EE, 0x5156, 0xD9F0, 0x5157, 0x83BC, 0x5158, 0x83BD, 0x5159, 0x83BE, 0x515A, 0xB5B3, + 0x515B, 0x83BF, 0x515C, 0xB6B5, 0x515D, 0x83C0, 0x515E, 0x83C1, 0x515F, 0x83C2, 0x5160, 0x83C3, 0x5161, 0x83C4, 0x5162, 0xBEA4, + 0x5163, 0x83C5, 0x5164, 0x83C6, 0x5165, 0xC8EB, 0x5166, 0x83C7, 0x5167, 0x83C8, 0x5168, 0xC8AB, 0x5169, 0x83C9, 0x516A, 0x83CA, + 0x516B, 0xB0CB, 0x516C, 0xB9AB, 0x516D, 0xC1F9, 0x516E, 0xD9E2, 0x516F, 0x83CB, 0x5170, 0xC0BC, 0x5171, 0xB9B2, 0x5172, 0x83CC, + 0x5173, 0xB9D8, 0x5174, 0xD0CB, 0x5175, 0xB1F8, 0x5176, 0xC6E4, 0x5177, 0xBEDF, 0x5178, 0xB5E4, 0x5179, 0xD7C8, 0x517A, 0x83CD, + 0x517B, 0xD1F8, 0x517C, 0xBCE6, 0x517D, 0xCADE, 0x517E, 0x83CE, 0x517F, 0x83CF, 0x5180, 0xBCBD, 0x5181, 0xD9E6, 0x5182, 0xD8E7, + 0x5183, 0x83D0, 0x5184, 0x83D1, 0x5185, 0xC4DA, 0x5186, 0x83D2, 0x5187, 0x83D3, 0x5188, 0xB8D4, 0x5189, 0xC8BD, 0x518A, 0x83D4, + 0x518B, 0x83D5, 0x518C, 0xB2E1, 0x518D, 0xD4D9, 0x518E, 0x83D6, 0x518F, 0x83D7, 0x5190, 0x83D8, 0x5191, 0x83D9, 0x5192, 0xC3B0, + 0x5193, 0x83DA, 0x5194, 0x83DB, 0x5195, 0xC3E1, 0x5196, 0xDAA2, 0x5197, 0xC8DF, 0x5198, 0x83DC, 0x5199, 0xD0B4, 0x519A, 0x83DD, + 0x519B, 0xBEFC, 0x519C, 0xC5A9, 0x519D, 0x83DE, 0x519E, 0x83DF, 0x519F, 0x83E0, 0x51A0, 0xB9DA, 0x51A1, 0x83E1, 0x51A2, 0xDAA3, + 0x51A3, 0x83E2, 0x51A4, 0xD4A9, 0x51A5, 0xDAA4, 0x51A6, 0x83E3, 0x51A7, 0x83E4, 0x51A8, 0x83E5, 0x51A9, 0x83E6, 0x51AA, 0x83E7, + 0x51AB, 0xD9FB, 0x51AC, 0xB6AC, 0x51AD, 0x83E8, 0x51AE, 0x83E9, 0x51AF, 0xB7EB, 0x51B0, 0xB1F9, 0x51B1, 0xD9FC, 0x51B2, 0xB3E5, + 0x51B3, 0xBEF6, 0x51B4, 0x83EA, 0x51B5, 0xBFF6, 0x51B6, 0xD2B1, 0x51B7, 0xC0E4, 0x51B8, 0x83EB, 0x51B9, 0x83EC, 0x51BA, 0x83ED, + 0x51BB, 0xB6B3, 0x51BC, 0xD9FE, 0x51BD, 0xD9FD, 0x51BE, 0x83EE, 0x51BF, 0x83EF, 0x51C0, 0xBEBB, 0x51C1, 0x83F0, 0x51C2, 0x83F1, + 0x51C3, 0x83F2, 0x51C4, 0xC6E0, 0x51C5, 0x83F3, 0x51C6, 0xD7BC, 0x51C7, 0xDAA1, 0x51C8, 0x83F4, 0x51C9, 0xC1B9, 0x51CA, 0x83F5, + 0x51CB, 0xB5F2, 0x51CC, 0xC1E8, 0x51CD, 0x83F6, 0x51CE, 0x83F7, 0x51CF, 0xBCF5, 0x51D0, 0x83F8, 0x51D1, 0xB4D5, 0x51D2, 0x83F9, + 0x51D3, 0x83FA, 0x51D4, 0x83FB, 0x51D5, 0x83FC, 0x51D6, 0x83FD, 0x51D7, 0x83FE, 0x51D8, 0x8440, 0x51D9, 0x8441, 0x51DA, 0x8442, + 0x51DB, 0xC1DD, 0x51DC, 0x8443, 0x51DD, 0xC4FD, 0x51DE, 0x8444, 0x51DF, 0x8445, 0x51E0, 0xBCB8, 0x51E1, 0xB7B2, 0x51E2, 0x8446, + 0x51E3, 0x8447, 0x51E4, 0xB7EF, 0x51E5, 0x8448, 0x51E6, 0x8449, 0x51E7, 0x844A, 0x51E8, 0x844B, 0x51E9, 0x844C, 0x51EA, 0x844D, + 0x51EB, 0xD9EC, 0x51EC, 0x844E, 0x51ED, 0xC6BE, 0x51EE, 0x844F, 0x51EF, 0xBFAD, 0x51F0, 0xBBCB, 0x51F1, 0x8450, 0x51F2, 0x8451, + 0x51F3, 0xB5CA, 0x51F4, 0x8452, 0x51F5, 0xDBC9, 0x51F6, 0xD0D7, 0x51F7, 0x8453, 0x51F8, 0xCDB9, 0x51F9, 0xB0BC, 0x51FA, 0xB3F6, + 0x51FB, 0xBBF7, 0x51FC, 0xDBCA, 0x51FD, 0xBAAF, 0x51FE, 0x8454, 0x51FF, 0xD4E4, 0x5200, 0xB5B6, 0x5201, 0xB5F3, 0x5202, 0xD8D6, + 0x5203, 0xC8D0, 0x5204, 0x8455, 0x5205, 0x8456, 0x5206, 0xB7D6, 0x5207, 0xC7D0, 0x5208, 0xD8D7, 0x5209, 0x8457, 0x520A, 0xBFAF, + 0x520B, 0x8458, 0x520C, 0x8459, 0x520D, 0xDBBB, 0x520E, 0xD8D8, 0x520F, 0x845A, 0x5210, 0x845B, 0x5211, 0xD0CC, 0x5212, 0xBBAE, + 0x5213, 0x845C, 0x5214, 0x845D, 0x5215, 0x845E, 0x5216, 0xEBBE, 0x5217, 0xC1D0, 0x5218, 0xC1F5, 0x5219, 0xD4F2, 0x521A, 0xB8D5, + 0x521B, 0xB4B4, 0x521C, 0x845F, 0x521D, 0xB3F5, 0x521E, 0x8460, 0x521F, 0x8461, 0x5220, 0xC9BE, 0x5221, 0x8462, 0x5222, 0x8463, + 0x5223, 0x8464, 0x5224, 0xC5D0, 0x5225, 0x8465, 0x5226, 0x8466, 0x5227, 0x8467, 0x5228, 0xC5D9, 0x5229, 0xC0FB, 0x522A, 0x8468, + 0x522B, 0xB1F0, 0x522C, 0x8469, 0x522D, 0xD8D9, 0x522E, 0xB9CE, 0x522F, 0x846A, 0x5230, 0xB5BD, 0x5231, 0x846B, 0x5232, 0x846C, + 0x5233, 0xD8DA, 0x5234, 0x846D, 0x5235, 0x846E, 0x5236, 0xD6C6, 0x5237, 0xCBA2, 0x5238, 0xC8AF, 0x5239, 0xC9B2, 0x523A, 0xB4CC, + 0x523B, 0xBFCC, 0x523C, 0x846F, 0x523D, 0xB9F4, 0x523E, 0x8470, 0x523F, 0xD8DB, 0x5240, 0xD8DC, 0x5241, 0xB6E7, 0x5242, 0xBCC1, + 0x5243, 0xCCEA, 0x5244, 0x8471, 0x5245, 0x8472, 0x5246, 0x8473, 0x5247, 0x8474, 0x5248, 0x8475, 0x5249, 0x8476, 0x524A, 0xCFF7, + 0x524B, 0x8477, 0x524C, 0xD8DD, 0x524D, 0xC7B0, 0x524E, 0x8478, 0x524F, 0x8479, 0x5250, 0xB9D0, 0x5251, 0xBDA3, 0x5252, 0x847A, + 0x5253, 0x847B, 0x5254, 0xCCDE, 0x5255, 0x847C, 0x5256, 0xC6CA, 0x5257, 0x847D, 0x5258, 0x847E, 0x5259, 0x8480, 0x525A, 0x8481, + 0x525B, 0x8482, 0x525C, 0xD8E0, 0x525D, 0x8483, 0x525E, 0xD8DE, 0x525F, 0x8484, 0x5260, 0x8485, 0x5261, 0xD8DF, 0x5262, 0x8486, + 0x5263, 0x8487, 0x5264, 0x8488, 0x5265, 0xB0FE, 0x5266, 0x8489, 0x5267, 0xBEE7, 0x5268, 0x848A, 0x5269, 0xCAA3, 0x526A, 0xBCF4, + 0x526B, 0x848B, 0x526C, 0x848C, 0x526D, 0x848D, 0x526E, 0x848E, 0x526F, 0xB8B1, 0x5270, 0x848F, 0x5271, 0x8490, 0x5272, 0xB8EE, + 0x5273, 0x8491, 0x5274, 0x8492, 0x5275, 0x8493, 0x5276, 0x8494, 0x5277, 0x8495, 0x5278, 0x8496, 0x5279, 0x8497, 0x527A, 0x8498, + 0x527B, 0x8499, 0x527C, 0x849A, 0x527D, 0xD8E2, 0x527E, 0x849B, 0x527F, 0xBDCB, 0x5280, 0x849C, 0x5281, 0xD8E4, 0x5282, 0xD8E3, + 0x5283, 0x849D, 0x5284, 0x849E, 0x5285, 0x849F, 0x5286, 0x84A0, 0x5287, 0x84A1, 0x5288, 0xC5FC, 0x5289, 0x84A2, 0x528A, 0x84A3, + 0x528B, 0x84A4, 0x528C, 0x84A5, 0x528D, 0x84A6, 0x528E, 0x84A7, 0x528F, 0x84A8, 0x5290, 0xD8E5, 0x5291, 0x84A9, 0x5292, 0x84AA, + 0x5293, 0xD8E6, 0x5294, 0x84AB, 0x5295, 0x84AC, 0x5296, 0x84AD, 0x5297, 0x84AE, 0x5298, 0x84AF, 0x5299, 0x84B0, 0x529A, 0x84B1, + 0x529B, 0xC1A6, 0x529C, 0x84B2, 0x529D, 0xC8B0, 0x529E, 0xB0EC, 0x529F, 0xB9A6, 0x52A0, 0xBCD3, 0x52A1, 0xCEF1, 0x52A2, 0xDBBD, + 0x52A3, 0xC1D3, 0x52A4, 0x84B3, 0x52A5, 0x84B4, 0x52A6, 0x84B5, 0x52A7, 0x84B6, 0x52A8, 0xB6AF, 0x52A9, 0xD6FA, 0x52AA, 0xC5AC, + 0x52AB, 0xBDD9, 0x52AC, 0xDBBE, 0x52AD, 0xDBBF, 0x52AE, 0x84B7, 0x52AF, 0x84B8, 0x52B0, 0x84B9, 0x52B1, 0xC0F8, 0x52B2, 0xBEA2, + 0x52B3, 0xC0CD, 0x52B4, 0x84BA, 0x52B5, 0x84BB, 0x52B6, 0x84BC, 0x52B7, 0x84BD, 0x52B8, 0x84BE, 0x52B9, 0x84BF, 0x52BA, 0x84C0, + 0x52BB, 0x84C1, 0x52BC, 0x84C2, 0x52BD, 0x84C3, 0x52BE, 0xDBC0, 0x52BF, 0xCAC6, 0x52C0, 0x84C4, 0x52C1, 0x84C5, 0x52C2, 0x84C6, + 0x52C3, 0xB2AA, 0x52C4, 0x84C7, 0x52C5, 0x84C8, 0x52C6, 0x84C9, 0x52C7, 0xD3C2, 0x52C8, 0x84CA, 0x52C9, 0xC3E3, 0x52CA, 0x84CB, + 0x52CB, 0xD1AB, 0x52CC, 0x84CC, 0x52CD, 0x84CD, 0x52CE, 0x84CE, 0x52CF, 0x84CF, 0x52D0, 0xDBC2, 0x52D1, 0x84D0, 0x52D2, 0xC0D5, + 0x52D3, 0x84D1, 0x52D4, 0x84D2, 0x52D5, 0x84D3, 0x52D6, 0xDBC3, 0x52D7, 0x84D4, 0x52D8, 0xBFB1, 0x52D9, 0x84D5, 0x52DA, 0x84D6, + 0x52DB, 0x84D7, 0x52DC, 0x84D8, 0x52DD, 0x84D9, 0x52DE, 0x84DA, 0x52DF, 0xC4BC, 0x52E0, 0x84DB, 0x52E1, 0x84DC, 0x52E2, 0x84DD, + 0x52E3, 0x84DE, 0x52E4, 0xC7DA, 0x52E5, 0x84DF, 0x52E6, 0x84E0, 0x52E7, 0x84E1, 0x52E8, 0x84E2, 0x52E9, 0x84E3, 0x52EA, 0x84E4, + 0x52EB, 0x84E5, 0x52EC, 0x84E6, 0x52ED, 0x84E7, 0x52EE, 0x84E8, 0x52EF, 0x84E9, 0x52F0, 0xDBC4, 0x52F1, 0x84EA, 0x52F2, 0x84EB, + 0x52F3, 0x84EC, 0x52F4, 0x84ED, 0x52F5, 0x84EE, 0x52F6, 0x84EF, 0x52F7, 0x84F0, 0x52F8, 0x84F1, 0x52F9, 0xD9E8, 0x52FA, 0xC9D7, + 0x52FB, 0x84F2, 0x52FC, 0x84F3, 0x52FD, 0x84F4, 0x52FE, 0xB9B4, 0x52FF, 0xCEF0, 0x5300, 0xD4C8, 0x5301, 0x84F5, 0x5302, 0x84F6, + 0x5303, 0x84F7, 0x5304, 0x84F8, 0x5305, 0xB0FC, 0x5306, 0xB4D2, 0x5307, 0x84F9, 0x5308, 0xD0D9, 0x5309, 0x84FA, 0x530A, 0x84FB, + 0x530B, 0x84FC, 0x530C, 0x84FD, 0x530D, 0xD9E9, 0x530E, 0x84FE, 0x530F, 0xDECB, 0x5310, 0xD9EB, 0x5311, 0x8540, 0x5312, 0x8541, + 0x5313, 0x8542, 0x5314, 0x8543, 0x5315, 0xD8B0, 0x5316, 0xBBAF, 0x5317, 0xB1B1, 0x5318, 0x8544, 0x5319, 0xB3D7, 0x531A, 0xD8CE, + 0x531B, 0x8545, 0x531C, 0x8546, 0x531D, 0xD4D1, 0x531E, 0x8547, 0x531F, 0x8548, 0x5320, 0xBDB3, 0x5321, 0xBFEF, 0x5322, 0x8549, + 0x5323, 0xCFBB, 0x5324, 0x854A, 0x5325, 0x854B, 0x5326, 0xD8D0, 0x5327, 0x854C, 0x5328, 0x854D, 0x5329, 0x854E, 0x532A, 0xB7CB, + 0x532B, 0x854F, 0x532C, 0x8550, 0x532D, 0x8551, 0x532E, 0xD8D1, 0x532F, 0x8552, 0x5330, 0x8553, 0x5331, 0x8554, 0x5332, 0x8555, + 0x5333, 0x8556, 0x5334, 0x8557, 0x5335, 0x8558, 0x5336, 0x8559, 0x5337, 0x855A, 0x5338, 0x855B, 0x5339, 0xC6A5, 0x533A, 0xC7F8, + 0x533B, 0xD2BD, 0x533C, 0x855C, 0x533D, 0x855D, 0x533E, 0xD8D2, 0x533F, 0xC4E4, 0x5340, 0x855E, 0x5341, 0xCAAE, 0x5342, 0x855F, + 0x5343, 0xC7A7, 0x5344, 0x8560, 0x5345, 0xD8A6, 0x5346, 0x8561, 0x5347, 0xC9FD, 0x5348, 0xCEE7, 0x5349, 0xBBDC, 0x534A, 0xB0EB, + 0x534B, 0x8562, 0x534C, 0x8563, 0x534D, 0x8564, 0x534E, 0xBBAA, 0x534F, 0xD0AD, 0x5350, 0x8565, 0x5351, 0xB1B0, 0x5352, 0xD7E4, + 0x5353, 0xD7BF, 0x5354, 0x8566, 0x5355, 0xB5A5, 0x5356, 0xC2F4, 0x5357, 0xC4CF, 0x5358, 0x8567, 0x5359, 0x8568, 0x535A, 0xB2A9, + 0x535B, 0x8569, 0x535C, 0xB2B7, 0x535D, 0x856A, 0x535E, 0xB1E5, 0x535F, 0xDFB2, 0x5360, 0xD5BC, 0x5361, 0xBFA8, 0x5362, 0xC2AC, + 0x5363, 0xD8D5, 0x5364, 0xC2B1, 0x5365, 0x856B, 0x5366, 0xD8D4, 0x5367, 0xCED4, 0x5368, 0x856C, 0x5369, 0xDAE0, 0x536A, 0x856D, + 0x536B, 0xCEC0, 0x536C, 0x856E, 0x536D, 0x856F, 0x536E, 0xD8B4, 0x536F, 0xC3AE, 0x5370, 0xD3A1, 0x5371, 0xCEA3, 0x5372, 0x8570, + 0x5373, 0xBCB4, 0x5374, 0xC8B4, 0x5375, 0xC2D1, 0x5376, 0x8571, 0x5377, 0xBEED, 0x5378, 0xD0B6, 0x5379, 0x8572, 0x537A, 0xDAE1, + 0x537B, 0x8573, 0x537C, 0x8574, 0x537D, 0x8575, 0x537E, 0x8576, 0x537F, 0xC7E4, 0x5380, 0x8577, 0x5381, 0x8578, 0x5382, 0xB3A7, + 0x5383, 0x8579, 0x5384, 0xB6F2, 0x5385, 0xCCFC, 0x5386, 0xC0FA, 0x5387, 0x857A, 0x5388, 0x857B, 0x5389, 0xC0F7, 0x538A, 0x857C, + 0x538B, 0xD1B9, 0x538C, 0xD1E1, 0x538D, 0xD8C7, 0x538E, 0x857D, 0x538F, 0x857E, 0x5390, 0x8580, 0x5391, 0x8581, 0x5392, 0x8582, + 0x5393, 0x8583, 0x5394, 0x8584, 0x5395, 0xB2DE, 0x5396, 0x8585, 0x5397, 0x8586, 0x5398, 0xC0E5, 0x5399, 0x8587, 0x539A, 0xBAF1, + 0x539B, 0x8588, 0x539C, 0x8589, 0x539D, 0xD8C8, 0x539E, 0x858A, 0x539F, 0xD4AD, 0x53A0, 0x858B, 0x53A1, 0x858C, 0x53A2, 0xCFE1, + 0x53A3, 0xD8C9, 0x53A4, 0x858D, 0x53A5, 0xD8CA, 0x53A6, 0xCFC3, 0x53A7, 0x858E, 0x53A8, 0xB3F8, 0x53A9, 0xBEC7, 0x53AA, 0x858F, + 0x53AB, 0x8590, 0x53AC, 0x8591, 0x53AD, 0x8592, 0x53AE, 0xD8CB, 0x53AF, 0x8593, 0x53B0, 0x8594, 0x53B1, 0x8595, 0x53B2, 0x8596, + 0x53B3, 0x8597, 0x53B4, 0x8598, 0x53B5, 0x8599, 0x53B6, 0xDBCC, 0x53B7, 0x859A, 0x53B8, 0x859B, 0x53B9, 0x859C, 0x53BA, 0x859D, + 0x53BB, 0xC8A5, 0x53BC, 0x859E, 0x53BD, 0x859F, 0x53BE, 0x85A0, 0x53BF, 0xCFD8, 0x53C0, 0x85A1, 0x53C1, 0xC8FE, 0x53C2, 0xB2CE, + 0x53C3, 0x85A2, 0x53C4, 0x85A3, 0x53C5, 0x85A4, 0x53C6, 0x85A5, 0x53C7, 0x85A6, 0x53C8, 0xD3D6, 0x53C9, 0xB2E6, 0x53CA, 0xBCB0, + 0x53CB, 0xD3D1, 0x53CC, 0xCBAB, 0x53CD, 0xB7B4, 0x53CE, 0x85A7, 0x53CF, 0x85A8, 0x53D0, 0x85A9, 0x53D1, 0xB7A2, 0x53D2, 0x85AA, + 0x53D3, 0x85AB, 0x53D4, 0xCAE5, 0x53D5, 0x85AC, 0x53D6, 0xC8A1, 0x53D7, 0xCADC, 0x53D8, 0xB1E4, 0x53D9, 0xD0F0, 0x53DA, 0x85AD, + 0x53DB, 0xC5D1, 0x53DC, 0x85AE, 0x53DD, 0x85AF, 0x53DE, 0x85B0, 0x53DF, 0xDBC5, 0x53E0, 0xB5FE, 0x53E1, 0x85B1, 0x53E2, 0x85B2, + 0x53E3, 0xBFDA, 0x53E4, 0xB9C5, 0x53E5, 0xBEE4, 0x53E6, 0xC1ED, 0x53E7, 0x85B3, 0x53E8, 0xDFB6, 0x53E9, 0xDFB5, 0x53EA, 0xD6BB, + 0x53EB, 0xBDD0, 0x53EC, 0xD5D9, 0x53ED, 0xB0C8, 0x53EE, 0xB6A3, 0x53EF, 0xBFC9, 0x53F0, 0xCCA8, 0x53F1, 0xDFB3, 0x53F2, 0xCAB7, + 0x53F3, 0xD3D2, 0x53F4, 0x85B4, 0x53F5, 0xD8CF, 0x53F6, 0xD2B6, 0x53F7, 0xBAC5, 0x53F8, 0xCBBE, 0x53F9, 0xCCBE, 0x53FA, 0x85B5, + 0x53FB, 0xDFB7, 0x53FC, 0xB5F0, 0x53FD, 0xDFB4, 0x53FE, 0x85B6, 0x53FF, 0x85B7, 0x5400, 0x85B8, 0x5401, 0xD3F5, 0x5402, 0x85B9, + 0x5403, 0xB3D4, 0x5404, 0xB8F7, 0x5405, 0x85BA, 0x5406, 0xDFBA, 0x5407, 0x85BB, 0x5408, 0xBACF, 0x5409, 0xBCAA, 0x540A, 0xB5F5, + 0x540B, 0x85BC, 0x540C, 0xCDAC, 0x540D, 0xC3FB, 0x540E, 0xBAF3, 0x540F, 0xC0F4, 0x5410, 0xCDC2, 0x5411, 0xCFF2, 0x5412, 0xDFB8, + 0x5413, 0xCFC5, 0x5414, 0x85BD, 0x5415, 0xC2C0, 0x5416, 0xDFB9, 0x5417, 0xC2F0, 0x5418, 0x85BE, 0x5419, 0x85BF, 0x541A, 0x85C0, + 0x541B, 0xBEFD, 0x541C, 0x85C1, 0x541D, 0xC1DF, 0x541E, 0xCDCC, 0x541F, 0xD2F7, 0x5420, 0xB7CD, 0x5421, 0xDFC1, 0x5422, 0x85C2, + 0x5423, 0xDFC4, 0x5424, 0x85C3, 0x5425, 0x85C4, 0x5426, 0xB7F1, 0x5427, 0xB0C9, 0x5428, 0xB6D6, 0x5429, 0xB7D4, 0x542A, 0x85C5, + 0x542B, 0xBAAC, 0x542C, 0xCCFD, 0x542D, 0xBFD4, 0x542E, 0xCBB1, 0x542F, 0xC6F4, 0x5430, 0x85C6, 0x5431, 0xD6A8, 0x5432, 0xDFC5, + 0x5433, 0x85C7, 0x5434, 0xCEE2, 0x5435, 0xB3B3, 0x5436, 0x85C8, 0x5437, 0x85C9, 0x5438, 0xCEFC, 0x5439, 0xB4B5, 0x543A, 0x85CA, + 0x543B, 0xCEC7, 0x543C, 0xBAF0, 0x543D, 0x85CB, 0x543E, 0xCEE1, 0x543F, 0x85CC, 0x5440, 0xD1BD, 0x5441, 0x85CD, 0x5442, 0x85CE, + 0x5443, 0xDFC0, 0x5444, 0x85CF, 0x5445, 0x85D0, 0x5446, 0xB4F4, 0x5447, 0x85D1, 0x5448, 0xB3CA, 0x5449, 0x85D2, 0x544A, 0xB8E6, + 0x544B, 0xDFBB, 0x544C, 0x85D3, 0x544D, 0x85D4, 0x544E, 0x85D5, 0x544F, 0x85D6, 0x5450, 0xC4C5, 0x5451, 0x85D7, 0x5452, 0xDFBC, + 0x5453, 0xDFBD, 0x5454, 0xDFBE, 0x5455, 0xC5BB, 0x5456, 0xDFBF, 0x5457, 0xDFC2, 0x5458, 0xD4B1, 0x5459, 0xDFC3, 0x545A, 0x85D8, + 0x545B, 0xC7BA, 0x545C, 0xCED8, 0x545D, 0x85D9, 0x545E, 0x85DA, 0x545F, 0x85DB, 0x5460, 0x85DC, 0x5461, 0x85DD, 0x5462, 0xC4D8, + 0x5463, 0x85DE, 0x5464, 0xDFCA, 0x5465, 0x85DF, 0x5466, 0xDFCF, 0x5467, 0x85E0, 0x5468, 0xD6DC, 0x5469, 0x85E1, 0x546A, 0x85E2, + 0x546B, 0x85E3, 0x546C, 0x85E4, 0x546D, 0x85E5, 0x546E, 0x85E6, 0x546F, 0x85E7, 0x5470, 0x85E8, 0x5471, 0xDFC9, 0x5472, 0xDFDA, + 0x5473, 0xCEB6, 0x5474, 0x85E9, 0x5475, 0xBAC7, 0x5476, 0xDFCE, 0x5477, 0xDFC8, 0x5478, 0xC5DE, 0x5479, 0x85EA, 0x547A, 0x85EB, + 0x547B, 0xC9EB, 0x547C, 0xBAF4, 0x547D, 0xC3FC, 0x547E, 0x85EC, 0x547F, 0x85ED, 0x5480, 0xBED7, 0x5481, 0x85EE, 0x5482, 0xDFC6, + 0x5483, 0x85EF, 0x5484, 0xDFCD, 0x5485, 0x85F0, 0x5486, 0xC5D8, 0x5487, 0x85F1, 0x5488, 0x85F2, 0x5489, 0x85F3, 0x548A, 0x85F4, + 0x548B, 0xD5A6, 0x548C, 0xBACD, 0x548D, 0x85F5, 0x548E, 0xBECC, 0x548F, 0xD3BD, 0x5490, 0xB8C0, 0x5491, 0x85F6, 0x5492, 0xD6E4, + 0x5493, 0x85F7, 0x5494, 0xDFC7, 0x5495, 0xB9BE, 0x5496, 0xBFA7, 0x5497, 0x85F8, 0x5498, 0x85F9, 0x5499, 0xC1FC, 0x549A, 0xDFCB, + 0x549B, 0xDFCC, 0x549C, 0x85FA, 0x549D, 0xDFD0, 0x549E, 0x85FB, 0x549F, 0x85FC, 0x54A0, 0x85FD, 0x54A1, 0x85FE, 0x54A2, 0x8640, + 0x54A3, 0xDFDB, 0x54A4, 0xDFE5, 0x54A5, 0x8641, 0x54A6, 0xDFD7, 0x54A7, 0xDFD6, 0x54A8, 0xD7C9, 0x54A9, 0xDFE3, 0x54AA, 0xDFE4, + 0x54AB, 0xE5EB, 0x54AC, 0xD2A7, 0x54AD, 0xDFD2, 0x54AE, 0x8642, 0x54AF, 0xBFA9, 0x54B0, 0x8643, 0x54B1, 0xD4DB, 0x54B2, 0x8644, + 0x54B3, 0xBFC8, 0x54B4, 0xDFD4, 0x54B5, 0x8645, 0x54B6, 0x8646, 0x54B7, 0x8647, 0x54B8, 0xCFCC, 0x54B9, 0x8648, 0x54BA, 0x8649, + 0x54BB, 0xDFDD, 0x54BC, 0x864A, 0x54BD, 0xD1CA, 0x54BE, 0x864B, 0x54BF, 0xDFDE, 0x54C0, 0xB0A7, 0x54C1, 0xC6B7, 0x54C2, 0xDFD3, + 0x54C3, 0x864C, 0x54C4, 0xBAE5, 0x54C5, 0x864D, 0x54C6, 0xB6DF, 0x54C7, 0xCDDB, 0x54C8, 0xB9FE, 0x54C9, 0xD4D5, 0x54CA, 0x864E, + 0x54CB, 0x864F, 0x54CC, 0xDFDF, 0x54CD, 0xCFEC, 0x54CE, 0xB0A5, 0x54CF, 0xDFE7, 0x54D0, 0xDFD1, 0x54D1, 0xD1C6, 0x54D2, 0xDFD5, + 0x54D3, 0xDFD8, 0x54D4, 0xDFD9, 0x54D5, 0xDFDC, 0x54D6, 0x8650, 0x54D7, 0xBBA9, 0x54D8, 0x8651, 0x54D9, 0xDFE0, 0x54DA, 0xDFE1, + 0x54DB, 0x8652, 0x54DC, 0xDFE2, 0x54DD, 0xDFE6, 0x54DE, 0xDFE8, 0x54DF, 0xD3B4, 0x54E0, 0x8653, 0x54E1, 0x8654, 0x54E2, 0x8655, + 0x54E3, 0x8656, 0x54E4, 0x8657, 0x54E5, 0xB8E7, 0x54E6, 0xC5B6, 0x54E7, 0xDFEA, 0x54E8, 0xC9DA, 0x54E9, 0xC1A8, 0x54EA, 0xC4C4, + 0x54EB, 0x8658, 0x54EC, 0x8659, 0x54ED, 0xBFDE, 0x54EE, 0xCFF8, 0x54EF, 0x865A, 0x54F0, 0x865B, 0x54F1, 0x865C, 0x54F2, 0xD5DC, + 0x54F3, 0xDFEE, 0x54F4, 0x865D, 0x54F5, 0x865E, 0x54F6, 0x865F, 0x54F7, 0x8660, 0x54F8, 0x8661, 0x54F9, 0x8662, 0x54FA, 0xB2B8, + 0x54FB, 0x8663, 0x54FC, 0xBADF, 0x54FD, 0xDFEC, 0x54FE, 0x8664, 0x54FF, 0xDBC1, 0x5500, 0x8665, 0x5501, 0xD1E4, 0x5502, 0x8666, + 0x5503, 0x8667, 0x5504, 0x8668, 0x5505, 0x8669, 0x5506, 0xCBF4, 0x5507, 0xB4BD, 0x5508, 0x866A, 0x5509, 0xB0A6, 0x550A, 0x866B, + 0x550B, 0x866C, 0x550C, 0x866D, 0x550D, 0x866E, 0x550E, 0x866F, 0x550F, 0xDFF1, 0x5510, 0xCCC6, 0x5511, 0xDFF2, 0x5512, 0x8670, + 0x5513, 0x8671, 0x5514, 0xDFED, 0x5515, 0x8672, 0x5516, 0x8673, 0x5517, 0x8674, 0x5518, 0x8675, 0x5519, 0x8676, 0x551A, 0x8677, + 0x551B, 0xDFE9, 0x551C, 0x8678, 0x551D, 0x8679, 0x551E, 0x867A, 0x551F, 0x867B, 0x5520, 0xDFEB, 0x5521, 0x867C, 0x5522, 0xDFEF, + 0x5523, 0xDFF0, 0x5524, 0xBBBD, 0x5525, 0x867D, 0x5526, 0x867E, 0x5527, 0xDFF3, 0x5528, 0x8680, 0x5529, 0x8681, 0x552A, 0xDFF4, + 0x552B, 0x8682, 0x552C, 0xBBA3, 0x552D, 0x8683, 0x552E, 0xCADB, 0x552F, 0xCEA8, 0x5530, 0xE0A7, 0x5531, 0xB3AA, 0x5532, 0x8684, + 0x5533, 0xE0A6, 0x5534, 0x8685, 0x5535, 0x8686, 0x5536, 0x8687, 0x5537, 0xE0A1, 0x5538, 0x8688, 0x5539, 0x8689, 0x553A, 0x868A, + 0x553B, 0x868B, 0x553C, 0xDFFE, 0x553D, 0x868C, 0x553E, 0xCDD9, 0x553F, 0xDFFC, 0x5540, 0x868D, 0x5541, 0xDFFA, 0x5542, 0x868E, + 0x5543, 0xBFD0, 0x5544, 0xD7C4, 0x5545, 0x868F, 0x5546, 0xC9CC, 0x5547, 0x8690, 0x5548, 0x8691, 0x5549, 0xDFF8, 0x554A, 0xB0A1, + 0x554B, 0x8692, 0x554C, 0x8693, 0x554D, 0x8694, 0x554E, 0x8695, 0x554F, 0x8696, 0x5550, 0xDFFD, 0x5551, 0x8697, 0x5552, 0x8698, + 0x5553, 0x8699, 0x5554, 0x869A, 0x5555, 0xDFFB, 0x5556, 0xE0A2, 0x5557, 0x869B, 0x5558, 0x869C, 0x5559, 0x869D, 0x555A, 0x869E, + 0x555B, 0x869F, 0x555C, 0xE0A8, 0x555D, 0x86A0, 0x555E, 0x86A1, 0x555F, 0x86A2, 0x5560, 0x86A3, 0x5561, 0xB7C8, 0x5562, 0x86A4, + 0x5563, 0x86A5, 0x5564, 0xC6A1, 0x5565, 0xC9B6, 0x5566, 0xC0B2, 0x5567, 0xDFF5, 0x5568, 0x86A6, 0x5569, 0x86A7, 0x556A, 0xC5BE, + 0x556B, 0x86A8, 0x556C, 0xD8C4, 0x556D, 0xDFF9, 0x556E, 0xC4F6, 0x556F, 0x86A9, 0x5570, 0x86AA, 0x5571, 0x86AB, 0x5572, 0x86AC, + 0x5573, 0x86AD, 0x5574, 0x86AE, 0x5575, 0xE0A3, 0x5576, 0xE0A4, 0x5577, 0xE0A5, 0x5578, 0xD0A5, 0x5579, 0x86AF, 0x557A, 0x86B0, + 0x557B, 0xE0B4, 0x557C, 0xCCE4, 0x557D, 0x86B1, 0x557E, 0xE0B1, 0x557F, 0x86B2, 0x5580, 0xBFA6, 0x5581, 0xE0AF, 0x5582, 0xCEB9, + 0x5583, 0xE0AB, 0x5584, 0xC9C6, 0x5585, 0x86B3, 0x5586, 0x86B4, 0x5587, 0xC0AE, 0x5588, 0xE0AE, 0x5589, 0xBAED, 0x558A, 0xBAB0, + 0x558B, 0xE0A9, 0x558C, 0x86B5, 0x558D, 0x86B6, 0x558E, 0x86B7, 0x558F, 0xDFF6, 0x5590, 0x86B8, 0x5591, 0xE0B3, 0x5592, 0x86B9, + 0x5593, 0x86BA, 0x5594, 0xE0B8, 0x5595, 0x86BB, 0x5596, 0x86BC, 0x5597, 0x86BD, 0x5598, 0xB4AD, 0x5599, 0xE0B9, 0x559A, 0x86BE, + 0x559B, 0x86BF, 0x559C, 0xCFB2, 0x559D, 0xBAC8, 0x559E, 0x86C0, 0x559F, 0xE0B0, 0x55A0, 0x86C1, 0x55A1, 0x86C2, 0x55A2, 0x86C3, + 0x55A3, 0x86C4, 0x55A4, 0x86C5, 0x55A5, 0x86C6, 0x55A6, 0x86C7, 0x55A7, 0xD0FA, 0x55A8, 0x86C8, 0x55A9, 0x86C9, 0x55AA, 0x86CA, + 0x55AB, 0x86CB, 0x55AC, 0x86CC, 0x55AD, 0x86CD, 0x55AE, 0x86CE, 0x55AF, 0x86CF, 0x55B0, 0x86D0, 0x55B1, 0xE0AC, 0x55B2, 0x86D1, + 0x55B3, 0xD4FB, 0x55B4, 0x86D2, 0x55B5, 0xDFF7, 0x55B6, 0x86D3, 0x55B7, 0xC5E7, 0x55B8, 0x86D4, 0x55B9, 0xE0AD, 0x55BA, 0x86D5, + 0x55BB, 0xD3F7, 0x55BC, 0x86D6, 0x55BD, 0xE0B6, 0x55BE, 0xE0B7, 0x55BF, 0x86D7, 0x55C0, 0x86D8, 0x55C1, 0x86D9, 0x55C2, 0x86DA, + 0x55C3, 0x86DB, 0x55C4, 0xE0C4, 0x55C5, 0xD0E1, 0x55C6, 0x86DC, 0x55C7, 0x86DD, 0x55C8, 0x86DE, 0x55C9, 0xE0BC, 0x55CA, 0x86DF, + 0x55CB, 0x86E0, 0x55CC, 0xE0C9, 0x55CD, 0xE0CA, 0x55CE, 0x86E1, 0x55CF, 0x86E2, 0x55D0, 0x86E3, 0x55D1, 0xE0BE, 0x55D2, 0xE0AA, + 0x55D3, 0xC9A4, 0x55D4, 0xE0C1, 0x55D5, 0x86E4, 0x55D6, 0xE0B2, 0x55D7, 0x86E5, 0x55D8, 0x86E6, 0x55D9, 0x86E7, 0x55DA, 0x86E8, + 0x55DB, 0x86E9, 0x55DC, 0xCAC8, 0x55DD, 0xE0C3, 0x55DE, 0x86EA, 0x55DF, 0xE0B5, 0x55E0, 0x86EB, 0x55E1, 0xCECB, 0x55E2, 0x86EC, + 0x55E3, 0xCBC3, 0x55E4, 0xE0CD, 0x55E5, 0xE0C6, 0x55E6, 0xE0C2, 0x55E7, 0x86ED, 0x55E8, 0xE0CB, 0x55E9, 0x86EE, 0x55EA, 0xE0BA, + 0x55EB, 0xE0BF, 0x55EC, 0xE0C0, 0x55ED, 0x86EF, 0x55EE, 0x86F0, 0x55EF, 0xE0C5, 0x55F0, 0x86F1, 0x55F1, 0x86F2, 0x55F2, 0xE0C7, + 0x55F3, 0xE0C8, 0x55F4, 0x86F3, 0x55F5, 0xE0CC, 0x55F6, 0x86F4, 0x55F7, 0xE0BB, 0x55F8, 0x86F5, 0x55F9, 0x86F6, 0x55FA, 0x86F7, + 0x55FB, 0x86F8, 0x55FC, 0x86F9, 0x55FD, 0xCBD4, 0x55FE, 0xE0D5, 0x55FF, 0x86FA, 0x5600, 0xE0D6, 0x5601, 0xE0D2, 0x5602, 0x86FB, + 0x5603, 0x86FC, 0x5604, 0x86FD, 0x5605, 0x86FE, 0x5606, 0x8740, 0x5607, 0x8741, 0x5608, 0xE0D0, 0x5609, 0xBCCE, 0x560A, 0x8742, + 0x560B, 0x8743, 0x560C, 0xE0D1, 0x560D, 0x8744, 0x560E, 0xB8C2, 0x560F, 0xD8C5, 0x5610, 0x8745, 0x5611, 0x8746, 0x5612, 0x8747, + 0x5613, 0x8748, 0x5614, 0x8749, 0x5615, 0x874A, 0x5616, 0x874B, 0x5617, 0x874C, 0x5618, 0xD0EA, 0x5619, 0x874D, 0x561A, 0x874E, + 0x561B, 0xC2EF, 0x561C, 0x874F, 0x561D, 0x8750, 0x561E, 0xE0CF, 0x561F, 0xE0BD, 0x5620, 0x8751, 0x5621, 0x8752, 0x5622, 0x8753, + 0x5623, 0xE0D4, 0x5624, 0xE0D3, 0x5625, 0x8754, 0x5626, 0x8755, 0x5627, 0xE0D7, 0x5628, 0x8756, 0x5629, 0x8757, 0x562A, 0x8758, + 0x562B, 0x8759, 0x562C, 0xE0DC, 0x562D, 0xE0D8, 0x562E, 0x875A, 0x562F, 0x875B, 0x5630, 0x875C, 0x5631, 0xD6F6, 0x5632, 0xB3B0, + 0x5633, 0x875D, 0x5634, 0xD7EC, 0x5635, 0x875E, 0x5636, 0xCBBB, 0x5637, 0x875F, 0x5638, 0x8760, 0x5639, 0xE0DA, 0x563A, 0x8761, + 0x563B, 0xCEFB, 0x563C, 0x8762, 0x563D, 0x8763, 0x563E, 0x8764, 0x563F, 0xBAD9, 0x5640, 0x8765, 0x5641, 0x8766, 0x5642, 0x8767, + 0x5643, 0x8768, 0x5644, 0x8769, 0x5645, 0x876A, 0x5646, 0x876B, 0x5647, 0x876C, 0x5648, 0x876D, 0x5649, 0x876E, 0x564A, 0x876F, + 0x564B, 0x8770, 0x564C, 0xE0E1, 0x564D, 0xE0DD, 0x564E, 0xD2AD, 0x564F, 0x8771, 0x5650, 0x8772, 0x5651, 0x8773, 0x5652, 0x8774, + 0x5653, 0x8775, 0x5654, 0xE0E2, 0x5655, 0x8776, 0x5656, 0x8777, 0x5657, 0xE0DB, 0x5658, 0xE0D9, 0x5659, 0xE0DF, 0x565A, 0x8778, + 0x565B, 0x8779, 0x565C, 0xE0E0, 0x565D, 0x877A, 0x565E, 0x877B, 0x565F, 0x877C, 0x5660, 0x877D, 0x5661, 0x877E, 0x5662, 0xE0DE, + 0x5663, 0x8780, 0x5664, 0xE0E4, 0x5665, 0x8781, 0x5666, 0x8782, 0x5667, 0x8783, 0x5668, 0xC6F7, 0x5669, 0xD8AC, 0x566A, 0xD4EB, + 0x566B, 0xE0E6, 0x566C, 0xCAC9, 0x566D, 0x8784, 0x566E, 0x8785, 0x566F, 0x8786, 0x5670, 0x8787, 0x5671, 0xE0E5, 0x5672, 0x8788, + 0x5673, 0x8789, 0x5674, 0x878A, 0x5675, 0x878B, 0x5676, 0xB8C1, 0x5677, 0x878C, 0x5678, 0x878D, 0x5679, 0x878E, 0x567A, 0x878F, + 0x567B, 0xE0E7, 0x567C, 0xE0E8, 0x567D, 0x8790, 0x567E, 0x8791, 0x567F, 0x8792, 0x5680, 0x8793, 0x5681, 0x8794, 0x5682, 0x8795, + 0x5683, 0x8796, 0x5684, 0x8797, 0x5685, 0xE0E9, 0x5686, 0xE0E3, 0x5687, 0x8798, 0x5688, 0x8799, 0x5689, 0x879A, 0x568A, 0x879B, + 0x568B, 0x879C, 0x568C, 0x879D, 0x568D, 0x879E, 0x568E, 0xBABF, 0x568F, 0xCCE7, 0x5690, 0x879F, 0x5691, 0x87A0, 0x5692, 0x87A1, + 0x5693, 0xE0EA, 0x5694, 0x87A2, 0x5695, 0x87A3, 0x5696, 0x87A4, 0x5697, 0x87A5, 0x5698, 0x87A6, 0x5699, 0x87A7, 0x569A, 0x87A8, + 0x569B, 0x87A9, 0x569C, 0x87AA, 0x569D, 0x87AB, 0x569E, 0x87AC, 0x569F, 0x87AD, 0x56A0, 0x87AE, 0x56A1, 0x87AF, 0x56A2, 0x87B0, + 0x56A3, 0xCFF9, 0x56A4, 0x87B1, 0x56A5, 0x87B2, 0x56A6, 0x87B3, 0x56A7, 0x87B4, 0x56A8, 0x87B5, 0x56A9, 0x87B6, 0x56AA, 0x87B7, + 0x56AB, 0x87B8, 0x56AC, 0x87B9, 0x56AD, 0x87BA, 0x56AE, 0x87BB, 0x56AF, 0xE0EB, 0x56B0, 0x87BC, 0x56B1, 0x87BD, 0x56B2, 0x87BE, + 0x56B3, 0x87BF, 0x56B4, 0x87C0, 0x56B5, 0x87C1, 0x56B6, 0x87C2, 0x56B7, 0xC8C2, 0x56B8, 0x87C3, 0x56B9, 0x87C4, 0x56BA, 0x87C5, + 0x56BB, 0x87C6, 0x56BC, 0xBDC0, 0x56BD, 0x87C7, 0x56BE, 0x87C8, 0x56BF, 0x87C9, 0x56C0, 0x87CA, 0x56C1, 0x87CB, 0x56C2, 0x87CC, + 0x56C3, 0x87CD, 0x56C4, 0x87CE, 0x56C5, 0x87CF, 0x56C6, 0x87D0, 0x56C7, 0x87D1, 0x56C8, 0x87D2, 0x56C9, 0x87D3, 0x56CA, 0xC4D2, + 0x56CB, 0x87D4, 0x56CC, 0x87D5, 0x56CD, 0x87D6, 0x56CE, 0x87D7, 0x56CF, 0x87D8, 0x56D0, 0x87D9, 0x56D1, 0x87DA, 0x56D2, 0x87DB, + 0x56D3, 0x87DC, 0x56D4, 0xE0EC, 0x56D5, 0x87DD, 0x56D6, 0x87DE, 0x56D7, 0xE0ED, 0x56D8, 0x87DF, 0x56D9, 0x87E0, 0x56DA, 0xC7F4, + 0x56DB, 0xCBC4, 0x56DC, 0x87E1, 0x56DD, 0xE0EE, 0x56DE, 0xBBD8, 0x56DF, 0xD8B6, 0x56E0, 0xD2F2, 0x56E1, 0xE0EF, 0x56E2, 0xCDC5, + 0x56E3, 0x87E2, 0x56E4, 0xB6DA, 0x56E5, 0x87E3, 0x56E6, 0x87E4, 0x56E7, 0x87E5, 0x56E8, 0x87E6, 0x56E9, 0x87E7, 0x56EA, 0x87E8, + 0x56EB, 0xE0F1, 0x56EC, 0x87E9, 0x56ED, 0xD4B0, 0x56EE, 0x87EA, 0x56EF, 0x87EB, 0x56F0, 0xC0A7, 0x56F1, 0xB4D1, 0x56F2, 0x87EC, + 0x56F3, 0x87ED, 0x56F4, 0xCEA7, 0x56F5, 0xE0F0, 0x56F6, 0x87EE, 0x56F7, 0x87EF, 0x56F8, 0x87F0, 0x56F9, 0xE0F2, 0x56FA, 0xB9CC, + 0x56FB, 0x87F1, 0x56FC, 0x87F2, 0x56FD, 0xB9FA, 0x56FE, 0xCDBC, 0x56FF, 0xE0F3, 0x5700, 0x87F3, 0x5701, 0x87F4, 0x5702, 0x87F5, + 0x5703, 0xC6D4, 0x5704, 0xE0F4, 0x5705, 0x87F6, 0x5706, 0xD4B2, 0x5707, 0x87F7, 0x5708, 0xC8A6, 0x5709, 0xE0F6, 0x570A, 0xE0F5, + 0x570B, 0x87F8, 0x570C, 0x87F9, 0x570D, 0x87FA, 0x570E, 0x87FB, 0x570F, 0x87FC, 0x5710, 0x87FD, 0x5711, 0x87FE, 0x5712, 0x8840, + 0x5713, 0x8841, 0x5714, 0x8842, 0x5715, 0x8843, 0x5716, 0x8844, 0x5717, 0x8845, 0x5718, 0x8846, 0x5719, 0x8847, 0x571A, 0x8848, + 0x571B, 0x8849, 0x571C, 0xE0F7, 0x571D, 0x884A, 0x571E, 0x884B, 0x571F, 0xCDC1, 0x5720, 0x884C, 0x5721, 0x884D, 0x5722, 0x884E, + 0x5723, 0xCAA5, 0x5724, 0x884F, 0x5725, 0x8850, 0x5726, 0x8851, 0x5727, 0x8852, 0x5728, 0xD4DA, 0x5729, 0xDBD7, 0x572A, 0xDBD9, + 0x572B, 0x8853, 0x572C, 0xDBD8, 0x572D, 0xB9E7, 0x572E, 0xDBDC, 0x572F, 0xDBDD, 0x5730, 0xB5D8, 0x5731, 0x8854, 0x5732, 0x8855, + 0x5733, 0xDBDA, 0x5734, 0x8856, 0x5735, 0x8857, 0x5736, 0x8858, 0x5737, 0x8859, 0x5738, 0x885A, 0x5739, 0xDBDB, 0x573A, 0xB3A1, + 0x573B, 0xDBDF, 0x573C, 0x885B, 0x573D, 0x885C, 0x573E, 0xBBF8, 0x573F, 0x885D, 0x5740, 0xD6B7, 0x5741, 0x885E, 0x5742, 0xDBE0, + 0x5743, 0x885F, 0x5744, 0x8860, 0x5745, 0x8861, 0x5746, 0x8862, 0x5747, 0xBEF9, 0x5748, 0x8863, 0x5749, 0x8864, 0x574A, 0xB7BB, + 0x574B, 0x8865, 0x574C, 0xDBD0, 0x574D, 0xCCAE, 0x574E, 0xBFB2, 0x574F, 0xBBB5, 0x5750, 0xD7F8, 0x5751, 0xBFD3, 0x5752, 0x8866, + 0x5753, 0x8867, 0x5754, 0x8868, 0x5755, 0x8869, 0x5756, 0x886A, 0x5757, 0xBFE9, 0x5758, 0x886B, 0x5759, 0x886C, 0x575A, 0xBCE1, + 0x575B, 0xCCB3, 0x575C, 0xDBDE, 0x575D, 0xB0D3, 0x575E, 0xCEEB, 0x575F, 0xB7D8, 0x5760, 0xD7B9, 0x5761, 0xC6C2, 0x5762, 0x886D, + 0x5763, 0x886E, 0x5764, 0xC0A4, 0x5765, 0x886F, 0x5766, 0xCCB9, 0x5767, 0x8870, 0x5768, 0xDBE7, 0x5769, 0xDBE1, 0x576A, 0xC6BA, + 0x576B, 0xDBE3, 0x576C, 0x8871, 0x576D, 0xDBE8, 0x576E, 0x8872, 0x576F, 0xC5F7, 0x5770, 0x8873, 0x5771, 0x8874, 0x5772, 0x8875, + 0x5773, 0xDBEA, 0x5774, 0x8876, 0x5775, 0x8877, 0x5776, 0xDBE9, 0x5777, 0xBFC0, 0x5778, 0x8878, 0x5779, 0x8879, 0x577A, 0x887A, + 0x577B, 0xDBE6, 0x577C, 0xDBE5, 0x577D, 0x887B, 0x577E, 0x887C, 0x577F, 0x887D, 0x5780, 0x887E, 0x5781, 0x8880, 0x5782, 0xB4B9, + 0x5783, 0xC0AC, 0x5784, 0xC2A2, 0x5785, 0xDBE2, 0x5786, 0xDBE4, 0x5787, 0x8881, 0x5788, 0x8882, 0x5789, 0x8883, 0x578A, 0x8884, + 0x578B, 0xD0CD, 0x578C, 0xDBED, 0x578D, 0x8885, 0x578E, 0x8886, 0x578F, 0x8887, 0x5790, 0x8888, 0x5791, 0x8889, 0x5792, 0xC0DD, + 0x5793, 0xDBF2, 0x5794, 0x888A, 0x5795, 0x888B, 0x5796, 0x888C, 0x5797, 0x888D, 0x5798, 0x888E, 0x5799, 0x888F, 0x579A, 0x8890, + 0x579B, 0xB6E2, 0x579C, 0x8891, 0x579D, 0x8892, 0x579E, 0x8893, 0x579F, 0x8894, 0x57A0, 0xDBF3, 0x57A1, 0xDBD2, 0x57A2, 0xB9B8, + 0x57A3, 0xD4AB, 0x57A4, 0xDBEC, 0x57A5, 0x8895, 0x57A6, 0xBFD1, 0x57A7, 0xDBF0, 0x57A8, 0x8896, 0x57A9, 0xDBD1, 0x57AA, 0x8897, + 0x57AB, 0xB5E6, 0x57AC, 0x8898, 0x57AD, 0xDBEB, 0x57AE, 0xBFE5, 0x57AF, 0x8899, 0x57B0, 0x889A, 0x57B1, 0x889B, 0x57B2, 0xDBEE, + 0x57B3, 0x889C, 0x57B4, 0xDBF1, 0x57B5, 0x889D, 0x57B6, 0x889E, 0x57B7, 0x889F, 0x57B8, 0xDBF9, 0x57B9, 0x88A0, 0x57BA, 0x88A1, + 0x57BB, 0x88A2, 0x57BC, 0x88A3, 0x57BD, 0x88A4, 0x57BE, 0x88A5, 0x57BF, 0x88A6, 0x57C0, 0x88A7, 0x57C1, 0x88A8, 0x57C2, 0xB9A1, + 0x57C3, 0xB0A3, 0x57C4, 0x88A9, 0x57C5, 0x88AA, 0x57C6, 0x88AB, 0x57C7, 0x88AC, 0x57C8, 0x88AD, 0x57C9, 0x88AE, 0x57CA, 0x88AF, + 0x57CB, 0xC2F1, 0x57CC, 0x88B0, 0x57CD, 0x88B1, 0x57CE, 0xB3C7, 0x57CF, 0xDBEF, 0x57D0, 0x88B2, 0x57D1, 0x88B3, 0x57D2, 0xDBF8, + 0x57D3, 0x88B4, 0x57D4, 0xC6D2, 0x57D5, 0xDBF4, 0x57D6, 0x88B5, 0x57D7, 0x88B6, 0x57D8, 0xDBF5, 0x57D9, 0xDBF7, 0x57DA, 0xDBF6, + 0x57DB, 0x88B7, 0x57DC, 0x88B8, 0x57DD, 0xDBFE, 0x57DE, 0x88B9, 0x57DF, 0xD3F2, 0x57E0, 0xB2BA, 0x57E1, 0x88BA, 0x57E2, 0x88BB, + 0x57E3, 0x88BC, 0x57E4, 0xDBFD, 0x57E5, 0x88BD, 0x57E6, 0x88BE, 0x57E7, 0x88BF, 0x57E8, 0x88C0, 0x57E9, 0x88C1, 0x57EA, 0x88C2, + 0x57EB, 0x88C3, 0x57EC, 0x88C4, 0x57ED, 0xDCA4, 0x57EE, 0x88C5, 0x57EF, 0xDBFB, 0x57F0, 0x88C6, 0x57F1, 0x88C7, 0x57F2, 0x88C8, + 0x57F3, 0x88C9, 0x57F4, 0xDBFA, 0x57F5, 0x88CA, 0x57F6, 0x88CB, 0x57F7, 0x88CC, 0x57F8, 0xDBFC, 0x57F9, 0xC5E0, 0x57FA, 0xBBF9, + 0x57FB, 0x88CD, 0x57FC, 0x88CE, 0x57FD, 0xDCA3, 0x57FE, 0x88CF, 0x57FF, 0x88D0, 0x5800, 0xDCA5, 0x5801, 0x88D1, 0x5802, 0xCCC3, + 0x5803, 0x88D2, 0x5804, 0x88D3, 0x5805, 0x88D4, 0x5806, 0xB6D1, 0x5807, 0xDDC0, 0x5808, 0x88D5, 0x5809, 0x88D6, 0x580A, 0x88D7, + 0x580B, 0xDCA1, 0x580C, 0x88D8, 0x580D, 0xDCA2, 0x580E, 0x88D9, 0x580F, 0x88DA, 0x5810, 0x88DB, 0x5811, 0xC7B5, 0x5812, 0x88DC, + 0x5813, 0x88DD, 0x5814, 0x88DE, 0x5815, 0xB6E9, 0x5816, 0x88DF, 0x5817, 0x88E0, 0x5818, 0x88E1, 0x5819, 0xDCA7, 0x581A, 0x88E2, + 0x581B, 0x88E3, 0x581C, 0x88E4, 0x581D, 0x88E5, 0x581E, 0xDCA6, 0x581F, 0x88E6, 0x5820, 0xDCA9, 0x5821, 0xB1A4, 0x5822, 0x88E7, + 0x5823, 0x88E8, 0x5824, 0xB5CC, 0x5825, 0x88E9, 0x5826, 0x88EA, 0x5827, 0x88EB, 0x5828, 0x88EC, 0x5829, 0x88ED, 0x582A, 0xBFB0, + 0x582B, 0x88EE, 0x582C, 0x88EF, 0x582D, 0x88F0, 0x582E, 0x88F1, 0x582F, 0x88F2, 0x5830, 0xD1DF, 0x5831, 0x88F3, 0x5832, 0x88F4, + 0x5833, 0x88F5, 0x5834, 0x88F6, 0x5835, 0xB6C2, 0x5836, 0x88F7, 0x5837, 0x88F8, 0x5838, 0x88F9, 0x5839, 0x88FA, 0x583A, 0x88FB, + 0x583B, 0x88FC, 0x583C, 0x88FD, 0x583D, 0x88FE, 0x583E, 0x8940, 0x583F, 0x8941, 0x5840, 0x8942, 0x5841, 0x8943, 0x5842, 0x8944, + 0x5843, 0x8945, 0x5844, 0xDCA8, 0x5845, 0x8946, 0x5846, 0x8947, 0x5847, 0x8948, 0x5848, 0x8949, 0x5849, 0x894A, 0x584A, 0x894B, + 0x584B, 0x894C, 0x584C, 0xCBFA, 0x584D, 0xEBF3, 0x584E, 0x894D, 0x584F, 0x894E, 0x5850, 0x894F, 0x5851, 0xCBDC, 0x5852, 0x8950, + 0x5853, 0x8951, 0x5854, 0xCBFE, 0x5855, 0x8952, 0x5856, 0x8953, 0x5857, 0x8954, 0x5858, 0xCCC1, 0x5859, 0x8955, 0x585A, 0x8956, + 0x585B, 0x8957, 0x585C, 0x8958, 0x585D, 0x8959, 0x585E, 0xC8FB, 0x585F, 0x895A, 0x5860, 0x895B, 0x5861, 0x895C, 0x5862, 0x895D, + 0x5863, 0x895E, 0x5864, 0x895F, 0x5865, 0xDCAA, 0x5866, 0x8960, 0x5867, 0x8961, 0x5868, 0x8962, 0x5869, 0x8963, 0x586A, 0x8964, + 0x586B, 0xCCEE, 0x586C, 0xDCAB, 0x586D, 0x8965, 0x586E, 0x8966, 0x586F, 0x8967, 0x5870, 0x8968, 0x5871, 0x8969, 0x5872, 0x896A, + 0x5873, 0x896B, 0x5874, 0x896C, 0x5875, 0x896D, 0x5876, 0x896E, 0x5877, 0x896F, 0x5878, 0x8970, 0x5879, 0x8971, 0x587A, 0x8972, + 0x587B, 0x8973, 0x587C, 0x8974, 0x587D, 0x8975, 0x587E, 0xDBD3, 0x587F, 0x8976, 0x5880, 0xDCAF, 0x5881, 0xDCAC, 0x5882, 0x8977, + 0x5883, 0xBEB3, 0x5884, 0x8978, 0x5885, 0xCAFB, 0x5886, 0x8979, 0x5887, 0x897A, 0x5888, 0x897B, 0x5889, 0xDCAD, 0x588A, 0x897C, + 0x588B, 0x897D, 0x588C, 0x897E, 0x588D, 0x8980, 0x588E, 0x8981, 0x588F, 0x8982, 0x5890, 0x8983, 0x5891, 0x8984, 0x5892, 0xC9CA, + 0x5893, 0xC4B9, 0x5894, 0x8985, 0x5895, 0x8986, 0x5896, 0x8987, 0x5897, 0x8988, 0x5898, 0x8989, 0x5899, 0xC7BD, 0x589A, 0xDCAE, + 0x589B, 0x898A, 0x589C, 0x898B, 0x589D, 0x898C, 0x589E, 0xD4F6, 0x589F, 0xD0E6, 0x58A0, 0x898D, 0x58A1, 0x898E, 0x58A2, 0x898F, + 0x58A3, 0x8990, 0x58A4, 0x8991, 0x58A5, 0x8992, 0x58A6, 0x8993, 0x58A7, 0x8994, 0x58A8, 0xC4AB, 0x58A9, 0xB6D5, 0x58AA, 0x8995, + 0x58AB, 0x8996, 0x58AC, 0x8997, 0x58AD, 0x8998, 0x58AE, 0x8999, 0x58AF, 0x899A, 0x58B0, 0x899B, 0x58B1, 0x899C, 0x58B2, 0x899D, + 0x58B3, 0x899E, 0x58B4, 0x899F, 0x58B5, 0x89A0, 0x58B6, 0x89A1, 0x58B7, 0x89A2, 0x58B8, 0x89A3, 0x58B9, 0x89A4, 0x58BA, 0x89A5, + 0x58BB, 0x89A6, 0x58BC, 0xDBD4, 0x58BD, 0x89A7, 0x58BE, 0x89A8, 0x58BF, 0x89A9, 0x58C0, 0x89AA, 0x58C1, 0xB1DA, 0x58C2, 0x89AB, + 0x58C3, 0x89AC, 0x58C4, 0x89AD, 0x58C5, 0xDBD5, 0x58C6, 0x89AE, 0x58C7, 0x89AF, 0x58C8, 0x89B0, 0x58C9, 0x89B1, 0x58CA, 0x89B2, + 0x58CB, 0x89B3, 0x58CC, 0x89B4, 0x58CD, 0x89B5, 0x58CE, 0x89B6, 0x58CF, 0x89B7, 0x58D0, 0x89B8, 0x58D1, 0xDBD6, 0x58D2, 0x89B9, + 0x58D3, 0x89BA, 0x58D4, 0x89BB, 0x58D5, 0xBABE, 0x58D6, 0x89BC, 0x58D7, 0x89BD, 0x58D8, 0x89BE, 0x58D9, 0x89BF, 0x58DA, 0x89C0, + 0x58DB, 0x89C1, 0x58DC, 0x89C2, 0x58DD, 0x89C3, 0x58DE, 0x89C4, 0x58DF, 0x89C5, 0x58E0, 0x89C6, 0x58E1, 0x89C7, 0x58E2, 0x89C8, + 0x58E3, 0x89C9, 0x58E4, 0xC8C0, 0x58E5, 0x89CA, 0x58E6, 0x89CB, 0x58E7, 0x89CC, 0x58E8, 0x89CD, 0x58E9, 0x89CE, 0x58EA, 0x89CF, + 0x58EB, 0xCABF, 0x58EC, 0xC8C9, 0x58ED, 0x89D0, 0x58EE, 0xD7B3, 0x58EF, 0x89D1, 0x58F0, 0xC9F9, 0x58F1, 0x89D2, 0x58F2, 0x89D3, + 0x58F3, 0xBFC7, 0x58F4, 0x89D4, 0x58F5, 0x89D5, 0x58F6, 0xBAF8, 0x58F7, 0x89D6, 0x58F8, 0x89D7, 0x58F9, 0xD2BC, 0x58FA, 0x89D8, + 0x58FB, 0x89D9, 0x58FC, 0x89DA, 0x58FD, 0x89DB, 0x58FE, 0x89DC, 0x58FF, 0x89DD, 0x5900, 0x89DE, 0x5901, 0x89DF, 0x5902, 0xE2BA, + 0x5903, 0x89E0, 0x5904, 0xB4A6, 0x5905, 0x89E1, 0x5906, 0x89E2, 0x5907, 0xB1B8, 0x5908, 0x89E3, 0x5909, 0x89E4, 0x590A, 0x89E5, + 0x590B, 0x89E6, 0x590C, 0x89E7, 0x590D, 0xB8B4, 0x590E, 0x89E8, 0x590F, 0xCFC4, 0x5910, 0x89E9, 0x5911, 0x89EA, 0x5912, 0x89EB, + 0x5913, 0x89EC, 0x5914, 0xD9E7, 0x5915, 0xCFA6, 0x5916, 0xCDE2, 0x5917, 0x89ED, 0x5918, 0x89EE, 0x5919, 0xD9ED, 0x591A, 0xB6E0, + 0x591B, 0x89EF, 0x591C, 0xD2B9, 0x591D, 0x89F0, 0x591E, 0x89F1, 0x591F, 0xB9BB, 0x5920, 0x89F2, 0x5921, 0x89F3, 0x5922, 0x89F4, + 0x5923, 0x89F5, 0x5924, 0xE2B9, 0x5925, 0xE2B7, 0x5926, 0x89F6, 0x5927, 0xB4F3, 0x5928, 0x89F7, 0x5929, 0xCCEC, 0x592A, 0xCCAB, + 0x592B, 0xB7F2, 0x592C, 0x89F8, 0x592D, 0xD8B2, 0x592E, 0xD1EB, 0x592F, 0xBABB, 0x5930, 0x89F9, 0x5931, 0xCAA7, 0x5932, 0x89FA, + 0x5933, 0x89FB, 0x5934, 0xCDB7, 0x5935, 0x89FC, 0x5936, 0x89FD, 0x5937, 0xD2C4, 0x5938, 0xBFE4, 0x5939, 0xBCD0, 0x593A, 0xB6E1, + 0x593B, 0x89FE, 0x593C, 0xDEC5, 0x593D, 0x8A40, 0x593E, 0x8A41, 0x593F, 0x8A42, 0x5940, 0x8A43, 0x5941, 0xDEC6, 0x5942, 0xDBBC, + 0x5943, 0x8A44, 0x5944, 0xD1D9, 0x5945, 0x8A45, 0x5946, 0x8A46, 0x5947, 0xC6E6, 0x5948, 0xC4CE, 0x5949, 0xB7EE, 0x594A, 0x8A47, + 0x594B, 0xB7DC, 0x594C, 0x8A48, 0x594D, 0x8A49, 0x594E, 0xBFFC, 0x594F, 0xD7E0, 0x5950, 0x8A4A, 0x5951, 0xC6F5, 0x5952, 0x8A4B, + 0x5953, 0x8A4C, 0x5954, 0xB1BC, 0x5955, 0xDEC8, 0x5956, 0xBDB1, 0x5957, 0xCCD7, 0x5958, 0xDECA, 0x5959, 0x8A4D, 0x595A, 0xDEC9, + 0x595B, 0x8A4E, 0x595C, 0x8A4F, 0x595D, 0x8A50, 0x595E, 0x8A51, 0x595F, 0x8A52, 0x5960, 0xB5EC, 0x5961, 0x8A53, 0x5962, 0xC9DD, + 0x5963, 0x8A54, 0x5964, 0x8A55, 0x5965, 0xB0C2, 0x5966, 0x8A56, 0x5967, 0x8A57, 0x5968, 0x8A58, 0x5969, 0x8A59, 0x596A, 0x8A5A, + 0x596B, 0x8A5B, 0x596C, 0x8A5C, 0x596D, 0x8A5D, 0x596E, 0x8A5E, 0x596F, 0x8A5F, 0x5970, 0x8A60, 0x5971, 0x8A61, 0x5972, 0x8A62, + 0x5973, 0xC5AE, 0x5974, 0xC5AB, 0x5975, 0x8A63, 0x5976, 0xC4CC, 0x5977, 0x8A64, 0x5978, 0xBCE9, 0x5979, 0xCBFD, 0x597A, 0x8A65, + 0x597B, 0x8A66, 0x597C, 0x8A67, 0x597D, 0xBAC3, 0x597E, 0x8A68, 0x597F, 0x8A69, 0x5980, 0x8A6A, 0x5981, 0xE5F9, 0x5982, 0xC8E7, + 0x5983, 0xE5FA, 0x5984, 0xCDFD, 0x5985, 0x8A6B, 0x5986, 0xD7B1, 0x5987, 0xB8BE, 0x5988, 0xC2E8, 0x5989, 0x8A6C, 0x598A, 0xC8D1, + 0x598B, 0x8A6D, 0x598C, 0x8A6E, 0x598D, 0xE5FB, 0x598E, 0x8A6F, 0x598F, 0x8A70, 0x5990, 0x8A71, 0x5991, 0x8A72, 0x5992, 0xB6CA, + 0x5993, 0xBCCB, 0x5994, 0x8A73, 0x5995, 0x8A74, 0x5996, 0xD1FD, 0x5997, 0xE6A1, 0x5998, 0x8A75, 0x5999, 0xC3EE, 0x599A, 0x8A76, + 0x599B, 0x8A77, 0x599C, 0x8A78, 0x599D, 0x8A79, 0x599E, 0xE6A4, 0x599F, 0x8A7A, 0x59A0, 0x8A7B, 0x59A1, 0x8A7C, 0x59A2, 0x8A7D, + 0x59A3, 0xE5FE, 0x59A4, 0xE6A5, 0x59A5, 0xCDD7, 0x59A6, 0x8A7E, 0x59A7, 0x8A80, 0x59A8, 0xB7C1, 0x59A9, 0xE5FC, 0x59AA, 0xE5FD, + 0x59AB, 0xE6A3, 0x59AC, 0x8A81, 0x59AD, 0x8A82, 0x59AE, 0xC4DD, 0x59AF, 0xE6A8, 0x59B0, 0x8A83, 0x59B1, 0x8A84, 0x59B2, 0xE6A7, + 0x59B3, 0x8A85, 0x59B4, 0x8A86, 0x59B5, 0x8A87, 0x59B6, 0x8A88, 0x59B7, 0x8A89, 0x59B8, 0x8A8A, 0x59B9, 0xC3C3, 0x59BA, 0x8A8B, + 0x59BB, 0xC6DE, 0x59BC, 0x8A8C, 0x59BD, 0x8A8D, 0x59BE, 0xE6AA, 0x59BF, 0x8A8E, 0x59C0, 0x8A8F, 0x59C1, 0x8A90, 0x59C2, 0x8A91, + 0x59C3, 0x8A92, 0x59C4, 0x8A93, 0x59C5, 0x8A94, 0x59C6, 0xC4B7, 0x59C7, 0x8A95, 0x59C8, 0x8A96, 0x59C9, 0x8A97, 0x59CA, 0xE6A2, + 0x59CB, 0xCABC, 0x59CC, 0x8A98, 0x59CD, 0x8A99, 0x59CE, 0x8A9A, 0x59CF, 0x8A9B, 0x59D0, 0xBDE3, 0x59D1, 0xB9C3, 0x59D2, 0xE6A6, + 0x59D3, 0xD0D5, 0x59D4, 0xCEAF, 0x59D5, 0x8A9C, 0x59D6, 0x8A9D, 0x59D7, 0xE6A9, 0x59D8, 0xE6B0, 0x59D9, 0x8A9E, 0x59DA, 0xD2A6, + 0x59DB, 0x8A9F, 0x59DC, 0xBDAA, 0x59DD, 0xE6AD, 0x59DE, 0x8AA0, 0x59DF, 0x8AA1, 0x59E0, 0x8AA2, 0x59E1, 0x8AA3, 0x59E2, 0x8AA4, + 0x59E3, 0xE6AF, 0x59E4, 0x8AA5, 0x59E5, 0xC0D1, 0x59E6, 0x8AA6, 0x59E7, 0x8AA7, 0x59E8, 0xD2CC, 0x59E9, 0x8AA8, 0x59EA, 0x8AA9, + 0x59EB, 0x8AAA, 0x59EC, 0xBCA7, 0x59ED, 0x8AAB, 0x59EE, 0x8AAC, 0x59EF, 0x8AAD, 0x59F0, 0x8AAE, 0x59F1, 0x8AAF, 0x59F2, 0x8AB0, + 0x59F3, 0x8AB1, 0x59F4, 0x8AB2, 0x59F5, 0x8AB3, 0x59F6, 0x8AB4, 0x59F7, 0x8AB5, 0x59F8, 0x8AB6, 0x59F9, 0xE6B1, 0x59FA, 0x8AB7, + 0x59FB, 0xD2F6, 0x59FC, 0x8AB8, 0x59FD, 0x8AB9, 0x59FE, 0x8ABA, 0x59FF, 0xD7CB, 0x5A00, 0x8ABB, 0x5A01, 0xCDFE, 0x5A02, 0x8ABC, + 0x5A03, 0xCDDE, 0x5A04, 0xC2A6, 0x5A05, 0xE6AB, 0x5A06, 0xE6AC, 0x5A07, 0xBDBF, 0x5A08, 0xE6AE, 0x5A09, 0xE6B3, 0x5A0A, 0x8ABD, + 0x5A0B, 0x8ABE, 0x5A0C, 0xE6B2, 0x5A0D, 0x8ABF, 0x5A0E, 0x8AC0, 0x5A0F, 0x8AC1, 0x5A10, 0x8AC2, 0x5A11, 0xE6B6, 0x5A12, 0x8AC3, + 0x5A13, 0xE6B8, 0x5A14, 0x8AC4, 0x5A15, 0x8AC5, 0x5A16, 0x8AC6, 0x5A17, 0x8AC7, 0x5A18, 0xC4EF, 0x5A19, 0x8AC8, 0x5A1A, 0x8AC9, + 0x5A1B, 0x8ACA, 0x5A1C, 0xC4C8, 0x5A1D, 0x8ACB, 0x5A1E, 0x8ACC, 0x5A1F, 0xBEEA, 0x5A20, 0xC9EF, 0x5A21, 0x8ACD, 0x5A22, 0x8ACE, + 0x5A23, 0xE6B7, 0x5A24, 0x8ACF, 0x5A25, 0xB6F0, 0x5A26, 0x8AD0, 0x5A27, 0x8AD1, 0x5A28, 0x8AD2, 0x5A29, 0xC3E4, 0x5A2A, 0x8AD3, + 0x5A2B, 0x8AD4, 0x5A2C, 0x8AD5, 0x5A2D, 0x8AD6, 0x5A2E, 0x8AD7, 0x5A2F, 0x8AD8, 0x5A30, 0x8AD9, 0x5A31, 0xD3E9, 0x5A32, 0xE6B4, + 0x5A33, 0x8ADA, 0x5A34, 0xE6B5, 0x5A35, 0x8ADB, 0x5A36, 0xC8A2, 0x5A37, 0x8ADC, 0x5A38, 0x8ADD, 0x5A39, 0x8ADE, 0x5A3A, 0x8ADF, + 0x5A3B, 0x8AE0, 0x5A3C, 0xE6BD, 0x5A3D, 0x8AE1, 0x5A3E, 0x8AE2, 0x5A3F, 0x8AE3, 0x5A40, 0xE6B9, 0x5A41, 0x8AE4, 0x5A42, 0x8AE5, + 0x5A43, 0x8AE6, 0x5A44, 0x8AE7, 0x5A45, 0x8AE8, 0x5A46, 0xC6C5, 0x5A47, 0x8AE9, 0x5A48, 0x8AEA, 0x5A49, 0xCDF1, 0x5A4A, 0xE6BB, + 0x5A4B, 0x8AEB, 0x5A4C, 0x8AEC, 0x5A4D, 0x8AED, 0x5A4E, 0x8AEE, 0x5A4F, 0x8AEF, 0x5A50, 0x8AF0, 0x5A51, 0x8AF1, 0x5A52, 0x8AF2, + 0x5A53, 0x8AF3, 0x5A54, 0x8AF4, 0x5A55, 0xE6BC, 0x5A56, 0x8AF5, 0x5A57, 0x8AF6, 0x5A58, 0x8AF7, 0x5A59, 0x8AF8, 0x5A5A, 0xBBE9, + 0x5A5B, 0x8AF9, 0x5A5C, 0x8AFA, 0x5A5D, 0x8AFB, 0x5A5E, 0x8AFC, 0x5A5F, 0x8AFD, 0x5A60, 0x8AFE, 0x5A61, 0x8B40, 0x5A62, 0xE6BE, + 0x5A63, 0x8B41, 0x5A64, 0x8B42, 0x5A65, 0x8B43, 0x5A66, 0x8B44, 0x5A67, 0xE6BA, 0x5A68, 0x8B45, 0x5A69, 0x8B46, 0x5A6A, 0xC0B7, + 0x5A6B, 0x8B47, 0x5A6C, 0x8B48, 0x5A6D, 0x8B49, 0x5A6E, 0x8B4A, 0x5A6F, 0x8B4B, 0x5A70, 0x8B4C, 0x5A71, 0x8B4D, 0x5A72, 0x8B4E, + 0x5A73, 0x8B4F, 0x5A74, 0xD3A4, 0x5A75, 0xE6BF, 0x5A76, 0xC9F4, 0x5A77, 0xE6C3, 0x5A78, 0x8B50, 0x5A79, 0x8B51, 0x5A7A, 0xE6C4, + 0x5A7B, 0x8B52, 0x5A7C, 0x8B53, 0x5A7D, 0x8B54, 0x5A7E, 0x8B55, 0x5A7F, 0xD0F6, 0x5A80, 0x8B56, 0x5A81, 0x8B57, 0x5A82, 0x8B58, + 0x5A83, 0x8B59, 0x5A84, 0x8B5A, 0x5A85, 0x8B5B, 0x5A86, 0x8B5C, 0x5A87, 0x8B5D, 0x5A88, 0x8B5E, 0x5A89, 0x8B5F, 0x5A8A, 0x8B60, + 0x5A8B, 0x8B61, 0x5A8C, 0x8B62, 0x5A8D, 0x8B63, 0x5A8E, 0x8B64, 0x5A8F, 0x8B65, 0x5A90, 0x8B66, 0x5A91, 0x8B67, 0x5A92, 0xC3BD, + 0x5A93, 0x8B68, 0x5A94, 0x8B69, 0x5A95, 0x8B6A, 0x5A96, 0x8B6B, 0x5A97, 0x8B6C, 0x5A98, 0x8B6D, 0x5A99, 0x8B6E, 0x5A9A, 0xC3C4, + 0x5A9B, 0xE6C2, 0x5A9C, 0x8B6F, 0x5A9D, 0x8B70, 0x5A9E, 0x8B71, 0x5A9F, 0x8B72, 0x5AA0, 0x8B73, 0x5AA1, 0x8B74, 0x5AA2, 0x8B75, + 0x5AA3, 0x8B76, 0x5AA4, 0x8B77, 0x5AA5, 0x8B78, 0x5AA6, 0x8B79, 0x5AA7, 0x8B7A, 0x5AA8, 0x8B7B, 0x5AA9, 0x8B7C, 0x5AAA, 0xE6C1, + 0x5AAB, 0x8B7D, 0x5AAC, 0x8B7E, 0x5AAD, 0x8B80, 0x5AAE, 0x8B81, 0x5AAF, 0x8B82, 0x5AB0, 0x8B83, 0x5AB1, 0x8B84, 0x5AB2, 0xE6C7, + 0x5AB3, 0xCFB1, 0x5AB4, 0x8B85, 0x5AB5, 0xEBF4, 0x5AB6, 0x8B86, 0x5AB7, 0x8B87, 0x5AB8, 0xE6CA, 0x5AB9, 0x8B88, 0x5ABA, 0x8B89, + 0x5ABB, 0x8B8A, 0x5ABC, 0x8B8B, 0x5ABD, 0x8B8C, 0x5ABE, 0xE6C5, 0x5ABF, 0x8B8D, 0x5AC0, 0x8B8E, 0x5AC1, 0xBCDE, 0x5AC2, 0xC9A9, + 0x5AC3, 0x8B8F, 0x5AC4, 0x8B90, 0x5AC5, 0x8B91, 0x5AC6, 0x8B92, 0x5AC7, 0x8B93, 0x5AC8, 0x8B94, 0x5AC9, 0xBCB5, 0x5ACA, 0x8B95, + 0x5ACB, 0x8B96, 0x5ACC, 0xCFD3, 0x5ACD, 0x8B97, 0x5ACE, 0x8B98, 0x5ACF, 0x8B99, 0x5AD0, 0x8B9A, 0x5AD1, 0x8B9B, 0x5AD2, 0xE6C8, + 0x5AD3, 0x8B9C, 0x5AD4, 0xE6C9, 0x5AD5, 0x8B9D, 0x5AD6, 0xE6CE, 0x5AD7, 0x8B9E, 0x5AD8, 0xE6D0, 0x5AD9, 0x8B9F, 0x5ADA, 0x8BA0, + 0x5ADB, 0x8BA1, 0x5ADC, 0xE6D1, 0x5ADD, 0x8BA2, 0x5ADE, 0x8BA3, 0x5ADF, 0x8BA4, 0x5AE0, 0xE6CB, 0x5AE1, 0xB5D5, 0x5AE2, 0x8BA5, + 0x5AE3, 0xE6CC, 0x5AE4, 0x8BA6, 0x5AE5, 0x8BA7, 0x5AE6, 0xE6CF, 0x5AE7, 0x8BA8, 0x5AE8, 0x8BA9, 0x5AE9, 0xC4DB, 0x5AEA, 0x8BAA, + 0x5AEB, 0xE6C6, 0x5AEC, 0x8BAB, 0x5AED, 0x8BAC, 0x5AEE, 0x8BAD, 0x5AEF, 0x8BAE, 0x5AF0, 0x8BAF, 0x5AF1, 0xE6CD, 0x5AF2, 0x8BB0, + 0x5AF3, 0x8BB1, 0x5AF4, 0x8BB2, 0x5AF5, 0x8BB3, 0x5AF6, 0x8BB4, 0x5AF7, 0x8BB5, 0x5AF8, 0x8BB6, 0x5AF9, 0x8BB7, 0x5AFA, 0x8BB8, + 0x5AFB, 0x8BB9, 0x5AFC, 0x8BBA, 0x5AFD, 0x8BBB, 0x5AFE, 0x8BBC, 0x5AFF, 0x8BBD, 0x5B00, 0x8BBE, 0x5B01, 0x8BBF, 0x5B02, 0x8BC0, + 0x5B03, 0x8BC1, 0x5B04, 0x8BC2, 0x5B05, 0x8BC3, 0x5B06, 0x8BC4, 0x5B07, 0x8BC5, 0x5B08, 0x8BC6, 0x5B09, 0xE6D2, 0x5B0A, 0x8BC7, + 0x5B0B, 0x8BC8, 0x5B0C, 0x8BC9, 0x5B0D, 0x8BCA, 0x5B0E, 0x8BCB, 0x5B0F, 0x8BCC, 0x5B10, 0x8BCD, 0x5B11, 0x8BCE, 0x5B12, 0x8BCF, + 0x5B13, 0x8BD0, 0x5B14, 0x8BD1, 0x5B15, 0x8BD2, 0x5B16, 0xE6D4, 0x5B17, 0xE6D3, 0x5B18, 0x8BD3, 0x5B19, 0x8BD4, 0x5B1A, 0x8BD5, + 0x5B1B, 0x8BD6, 0x5B1C, 0x8BD7, 0x5B1D, 0x8BD8, 0x5B1E, 0x8BD9, 0x5B1F, 0x8BDA, 0x5B20, 0x8BDB, 0x5B21, 0x8BDC, 0x5B22, 0x8BDD, + 0x5B23, 0x8BDE, 0x5B24, 0x8BDF, 0x5B25, 0x8BE0, 0x5B26, 0x8BE1, 0x5B27, 0x8BE2, 0x5B28, 0x8BE3, 0x5B29, 0x8BE4, 0x5B2A, 0x8BE5, + 0x5B2B, 0x8BE6, 0x5B2C, 0x8BE7, 0x5B2D, 0x8BE8, 0x5B2E, 0x8BE9, 0x5B2F, 0x8BEA, 0x5B30, 0x8BEB, 0x5B31, 0x8BEC, 0x5B32, 0xE6D5, + 0x5B33, 0x8BED, 0x5B34, 0xD9F8, 0x5B35, 0x8BEE, 0x5B36, 0x8BEF, 0x5B37, 0xE6D6, 0x5B38, 0x8BF0, 0x5B39, 0x8BF1, 0x5B3A, 0x8BF2, + 0x5B3B, 0x8BF3, 0x5B3C, 0x8BF4, 0x5B3D, 0x8BF5, 0x5B3E, 0x8BF6, 0x5B3F, 0x8BF7, 0x5B40, 0xE6D7, 0x5B41, 0x8BF8, 0x5B42, 0x8BF9, + 0x5B43, 0x8BFA, 0x5B44, 0x8BFB, 0x5B45, 0x8BFC, 0x5B46, 0x8BFD, 0x5B47, 0x8BFE, 0x5B48, 0x8C40, 0x5B49, 0x8C41, 0x5B4A, 0x8C42, + 0x5B4B, 0x8C43, 0x5B4C, 0x8C44, 0x5B4D, 0x8C45, 0x5B4E, 0x8C46, 0x5B4F, 0x8C47, 0x5B50, 0xD7D3, 0x5B51, 0xE6DD, 0x5B52, 0x8C48, + 0x5B53, 0xE6DE, 0x5B54, 0xBFD7, 0x5B55, 0xD4D0, 0x5B56, 0x8C49, 0x5B57, 0xD7D6, 0x5B58, 0xB4E6, 0x5B59, 0xCBEF, 0x5B5A, 0xE6DA, + 0x5B5B, 0xD8C3, 0x5B5C, 0xD7CE, 0x5B5D, 0xD0A2, 0x5B5E, 0x8C4A, 0x5B5F, 0xC3CF, 0x5B60, 0x8C4B, 0x5B61, 0x8C4C, 0x5B62, 0xE6DF, + 0x5B63, 0xBCBE, 0x5B64, 0xB9C2, 0x5B65, 0xE6DB, 0x5B66, 0xD1A7, 0x5B67, 0x8C4D, 0x5B68, 0x8C4E, 0x5B69, 0xBAA2, 0x5B6A, 0xC2CF, + 0x5B6B, 0x8C4F, 0x5B6C, 0xD8AB, 0x5B6D, 0x8C50, 0x5B6E, 0x8C51, 0x5B6F, 0x8C52, 0x5B70, 0xCAEB, 0x5B71, 0xE5EE, 0x5B72, 0x8C53, + 0x5B73, 0xE6DC, 0x5B74, 0x8C54, 0x5B75, 0xB7F5, 0x5B76, 0x8C55, 0x5B77, 0x8C56, 0x5B78, 0x8C57, 0x5B79, 0x8C58, 0x5B7A, 0xC8E6, + 0x5B7B, 0x8C59, 0x5B7C, 0x8C5A, 0x5B7D, 0xC4F5, 0x5B7E, 0x8C5B, 0x5B7F, 0x8C5C, 0x5B80, 0xE5B2, 0x5B81, 0xC4FE, 0x5B82, 0x8C5D, + 0x5B83, 0xCBFC, 0x5B84, 0xE5B3, 0x5B85, 0xD5AC, 0x5B86, 0x8C5E, 0x5B87, 0xD3EE, 0x5B88, 0xCAD8, 0x5B89, 0xB0B2, 0x5B8A, 0x8C5F, + 0x5B8B, 0xCBCE, 0x5B8C, 0xCDEA, 0x5B8D, 0x8C60, 0x5B8E, 0x8C61, 0x5B8F, 0xBAEA, 0x5B90, 0x8C62, 0x5B91, 0x8C63, 0x5B92, 0x8C64, + 0x5B93, 0xE5B5, 0x5B94, 0x8C65, 0x5B95, 0xE5B4, 0x5B96, 0x8C66, 0x5B97, 0xD7DA, 0x5B98, 0xB9D9, 0x5B99, 0xD6E6, 0x5B9A, 0xB6A8, + 0x5B9B, 0xCDF0, 0x5B9C, 0xD2CB, 0x5B9D, 0xB1A6, 0x5B9E, 0xCAB5, 0x5B9F, 0x8C67, 0x5BA0, 0xB3E8, 0x5BA1, 0xC9F3, 0x5BA2, 0xBFCD, + 0x5BA3, 0xD0FB, 0x5BA4, 0xCAD2, 0x5BA5, 0xE5B6, 0x5BA6, 0xBBC2, 0x5BA7, 0x8C68, 0x5BA8, 0x8C69, 0x5BA9, 0x8C6A, 0x5BAA, 0xCFDC, + 0x5BAB, 0xB9AC, 0x5BAC, 0x8C6B, 0x5BAD, 0x8C6C, 0x5BAE, 0x8C6D, 0x5BAF, 0x8C6E, 0x5BB0, 0xD4D7, 0x5BB1, 0x8C6F, 0x5BB2, 0x8C70, + 0x5BB3, 0xBAA6, 0x5BB4, 0xD1E7, 0x5BB5, 0xCFFC, 0x5BB6, 0xBCD2, 0x5BB7, 0x8C71, 0x5BB8, 0xE5B7, 0x5BB9, 0xC8DD, 0x5BBA, 0x8C72, + 0x5BBB, 0x8C73, 0x5BBC, 0x8C74, 0x5BBD, 0xBFED, 0x5BBE, 0xB1F6, 0x5BBF, 0xCBDE, 0x5BC0, 0x8C75, 0x5BC1, 0x8C76, 0x5BC2, 0xBCC5, + 0x5BC3, 0x8C77, 0x5BC4, 0xBCC4, 0x5BC5, 0xD2FA, 0x5BC6, 0xC3DC, 0x5BC7, 0xBFDC, 0x5BC8, 0x8C78, 0x5BC9, 0x8C79, 0x5BCA, 0x8C7A, + 0x5BCB, 0x8C7B, 0x5BCC, 0xB8BB, 0x5BCD, 0x8C7C, 0x5BCE, 0x8C7D, 0x5BCF, 0x8C7E, 0x5BD0, 0xC3C2, 0x5BD1, 0x8C80, 0x5BD2, 0xBAAE, + 0x5BD3, 0xD4A2, 0x5BD4, 0x8C81, 0x5BD5, 0x8C82, 0x5BD6, 0x8C83, 0x5BD7, 0x8C84, 0x5BD8, 0x8C85, 0x5BD9, 0x8C86, 0x5BDA, 0x8C87, + 0x5BDB, 0x8C88, 0x5BDC, 0x8C89, 0x5BDD, 0xC7DE, 0x5BDE, 0xC4AF, 0x5BDF, 0xB2EC, 0x5BE0, 0x8C8A, 0x5BE1, 0xB9D1, 0x5BE2, 0x8C8B, + 0x5BE3, 0x8C8C, 0x5BE4, 0xE5BB, 0x5BE5, 0xC1C8, 0x5BE6, 0x8C8D, 0x5BE7, 0x8C8E, 0x5BE8, 0xD5AF, 0x5BE9, 0x8C8F, 0x5BEA, 0x8C90, + 0x5BEB, 0x8C91, 0x5BEC, 0x8C92, 0x5BED, 0x8C93, 0x5BEE, 0xE5BC, 0x5BEF, 0x8C94, 0x5BF0, 0xE5BE, 0x5BF1, 0x8C95, 0x5BF2, 0x8C96, + 0x5BF3, 0x8C97, 0x5BF4, 0x8C98, 0x5BF5, 0x8C99, 0x5BF6, 0x8C9A, 0x5BF7, 0x8C9B, 0x5BF8, 0xB4E7, 0x5BF9, 0xB6D4, 0x5BFA, 0xCBC2, + 0x5BFB, 0xD1B0, 0x5BFC, 0xB5BC, 0x5BFD, 0x8C9C, 0x5BFE, 0x8C9D, 0x5BFF, 0xCAD9, 0x5C00, 0x8C9E, 0x5C01, 0xB7E2, 0x5C02, 0x8C9F, + 0x5C03, 0x8CA0, 0x5C04, 0xC9E4, 0x5C05, 0x8CA1, 0x5C06, 0xBDAB, 0x5C07, 0x8CA2, 0x5C08, 0x8CA3, 0x5C09, 0xCEBE, 0x5C0A, 0xD7F0, + 0x5C0B, 0x8CA4, 0x5C0C, 0x8CA5, 0x5C0D, 0x8CA6, 0x5C0E, 0x8CA7, 0x5C0F, 0xD0A1, 0x5C10, 0x8CA8, 0x5C11, 0xC9D9, 0x5C12, 0x8CA9, + 0x5C13, 0x8CAA, 0x5C14, 0xB6FB, 0x5C15, 0xE6D8, 0x5C16, 0xBCE2, 0x5C17, 0x8CAB, 0x5C18, 0xB3BE, 0x5C19, 0x8CAC, 0x5C1A, 0xC9D0, + 0x5C1B, 0x8CAD, 0x5C1C, 0xE6D9, 0x5C1D, 0xB3A2, 0x5C1E, 0x8CAE, 0x5C1F, 0x8CAF, 0x5C20, 0x8CB0, 0x5C21, 0x8CB1, 0x5C22, 0xDECC, + 0x5C23, 0x8CB2, 0x5C24, 0xD3C8, 0x5C25, 0xDECD, 0x5C26, 0x8CB3, 0x5C27, 0xD2A2, 0x5C28, 0x8CB4, 0x5C29, 0x8CB5, 0x5C2A, 0x8CB6, + 0x5C2B, 0x8CB7, 0x5C2C, 0xDECE, 0x5C2D, 0x8CB8, 0x5C2E, 0x8CB9, 0x5C2F, 0x8CBA, 0x5C30, 0x8CBB, 0x5C31, 0xBECD, 0x5C32, 0x8CBC, + 0x5C33, 0x8CBD, 0x5C34, 0xDECF, 0x5C35, 0x8CBE, 0x5C36, 0x8CBF, 0x5C37, 0x8CC0, 0x5C38, 0xCAAC, 0x5C39, 0xD2FC, 0x5C3A, 0xB3DF, + 0x5C3B, 0xE5EA, 0x5C3C, 0xC4E1, 0x5C3D, 0xBEA1, 0x5C3E, 0xCEB2, 0x5C3F, 0xC4F2, 0x5C40, 0xBED6, 0x5C41, 0xC6A8, 0x5C42, 0xB2E3, + 0x5C43, 0x8CC1, 0x5C44, 0x8CC2, 0x5C45, 0xBED3, 0x5C46, 0x8CC3, 0x5C47, 0x8CC4, 0x5C48, 0xC7FC, 0x5C49, 0xCCEB, 0x5C4A, 0xBDEC, + 0x5C4B, 0xCEDD, 0x5C4C, 0x8CC5, 0x5C4D, 0x8CC6, 0x5C4E, 0xCABA, 0x5C4F, 0xC6C1, 0x5C50, 0xE5EC, 0x5C51, 0xD0BC, 0x5C52, 0x8CC7, + 0x5C53, 0x8CC8, 0x5C54, 0x8CC9, 0x5C55, 0xD5B9, 0x5C56, 0x8CCA, 0x5C57, 0x8CCB, 0x5C58, 0x8CCC, 0x5C59, 0xE5ED, 0x5C5A, 0x8CCD, + 0x5C5B, 0x8CCE, 0x5C5C, 0x8CCF, 0x5C5D, 0x8CD0, 0x5C5E, 0xCAF4, 0x5C5F, 0x8CD1, 0x5C60, 0xCDC0, 0x5C61, 0xC2C5, 0x5C62, 0x8CD2, + 0x5C63, 0xE5EF, 0x5C64, 0x8CD3, 0x5C65, 0xC2C4, 0x5C66, 0xE5F0, 0x5C67, 0x8CD4, 0x5C68, 0x8CD5, 0x5C69, 0x8CD6, 0x5C6A, 0x8CD7, + 0x5C6B, 0x8CD8, 0x5C6C, 0x8CD9, 0x5C6D, 0x8CDA, 0x5C6E, 0xE5F8, 0x5C6F, 0xCDCD, 0x5C70, 0x8CDB, 0x5C71, 0xC9BD, 0x5C72, 0x8CDC, + 0x5C73, 0x8CDD, 0x5C74, 0x8CDE, 0x5C75, 0x8CDF, 0x5C76, 0x8CE0, 0x5C77, 0x8CE1, 0x5C78, 0x8CE2, 0x5C79, 0xD2D9, 0x5C7A, 0xE1A8, + 0x5C7B, 0x8CE3, 0x5C7C, 0x8CE4, 0x5C7D, 0x8CE5, 0x5C7E, 0x8CE6, 0x5C7F, 0xD3EC, 0x5C80, 0x8CE7, 0x5C81, 0xCBEA, 0x5C82, 0xC6F1, + 0x5C83, 0x8CE8, 0x5C84, 0x8CE9, 0x5C85, 0x8CEA, 0x5C86, 0x8CEB, 0x5C87, 0x8CEC, 0x5C88, 0xE1AC, 0x5C89, 0x8CED, 0x5C8A, 0x8CEE, + 0x5C8B, 0x8CEF, 0x5C8C, 0xE1A7, 0x5C8D, 0xE1A9, 0x5C8E, 0x8CF0, 0x5C8F, 0x8CF1, 0x5C90, 0xE1AA, 0x5C91, 0xE1AF, 0x5C92, 0x8CF2, + 0x5C93, 0x8CF3, 0x5C94, 0xB2ED, 0x5C95, 0x8CF4, 0x5C96, 0xE1AB, 0x5C97, 0xB8DA, 0x5C98, 0xE1AD, 0x5C99, 0xE1AE, 0x5C9A, 0xE1B0, + 0x5C9B, 0xB5BA, 0x5C9C, 0xE1B1, 0x5C9D, 0x8CF5, 0x5C9E, 0x8CF6, 0x5C9F, 0x8CF7, 0x5CA0, 0x8CF8, 0x5CA1, 0x8CF9, 0x5CA2, 0xE1B3, + 0x5CA3, 0xE1B8, 0x5CA4, 0x8CFA, 0x5CA5, 0x8CFB, 0x5CA6, 0x8CFC, 0x5CA7, 0x8CFD, 0x5CA8, 0x8CFE, 0x5CA9, 0xD1D2, 0x5CAA, 0x8D40, + 0x5CAB, 0xE1B6, 0x5CAC, 0xE1B5, 0x5CAD, 0xC1EB, 0x5CAE, 0x8D41, 0x5CAF, 0x8D42, 0x5CB0, 0x8D43, 0x5CB1, 0xE1B7, 0x5CB2, 0x8D44, + 0x5CB3, 0xD4C0, 0x5CB4, 0x8D45, 0x5CB5, 0xE1B2, 0x5CB6, 0x8D46, 0x5CB7, 0xE1BA, 0x5CB8, 0xB0B6, 0x5CB9, 0x8D47, 0x5CBA, 0x8D48, + 0x5CBB, 0x8D49, 0x5CBC, 0x8D4A, 0x5CBD, 0xE1B4, 0x5CBE, 0x8D4B, 0x5CBF, 0xBFF9, 0x5CC0, 0x8D4C, 0x5CC1, 0xE1B9, 0x5CC2, 0x8D4D, + 0x5CC3, 0x8D4E, 0x5CC4, 0xE1BB, 0x5CC5, 0x8D4F, 0x5CC6, 0x8D50, 0x5CC7, 0x8D51, 0x5CC8, 0x8D52, 0x5CC9, 0x8D53, 0x5CCA, 0x8D54, + 0x5CCB, 0xE1BE, 0x5CCC, 0x8D55, 0x5CCD, 0x8D56, 0x5CCE, 0x8D57, 0x5CCF, 0x8D58, 0x5CD0, 0x8D59, 0x5CD1, 0x8D5A, 0x5CD2, 0xE1BC, + 0x5CD3, 0x8D5B, 0x5CD4, 0x8D5C, 0x5CD5, 0x8D5D, 0x5CD6, 0x8D5E, 0x5CD7, 0x8D5F, 0x5CD8, 0x8D60, 0x5CD9, 0xD6C5, 0x5CDA, 0x8D61, + 0x5CDB, 0x8D62, 0x5CDC, 0x8D63, 0x5CDD, 0x8D64, 0x5CDE, 0x8D65, 0x5CDF, 0x8D66, 0x5CE0, 0x8D67, 0x5CE1, 0xCFBF, 0x5CE2, 0x8D68, + 0x5CE3, 0x8D69, 0x5CE4, 0xE1BD, 0x5CE5, 0xE1BF, 0x5CE6, 0xC2CD, 0x5CE7, 0x8D6A, 0x5CE8, 0xB6EB, 0x5CE9, 0x8D6B, 0x5CEA, 0xD3F8, + 0x5CEB, 0x8D6C, 0x5CEC, 0x8D6D, 0x5CED, 0xC7CD, 0x5CEE, 0x8D6E, 0x5CEF, 0x8D6F, 0x5CF0, 0xB7E5, 0x5CF1, 0x8D70, 0x5CF2, 0x8D71, + 0x5CF3, 0x8D72, 0x5CF4, 0x8D73, 0x5CF5, 0x8D74, 0x5CF6, 0x8D75, 0x5CF7, 0x8D76, 0x5CF8, 0x8D77, 0x5CF9, 0x8D78, 0x5CFA, 0x8D79, + 0x5CFB, 0xBEFE, 0x5CFC, 0x8D7A, 0x5CFD, 0x8D7B, 0x5CFE, 0x8D7C, 0x5CFF, 0x8D7D, 0x5D00, 0x8D7E, 0x5D01, 0x8D80, 0x5D02, 0xE1C0, + 0x5D03, 0xE1C1, 0x5D04, 0x8D81, 0x5D05, 0x8D82, 0x5D06, 0xE1C7, 0x5D07, 0xB3E7, 0x5D08, 0x8D83, 0x5D09, 0x8D84, 0x5D0A, 0x8D85, + 0x5D0B, 0x8D86, 0x5D0C, 0x8D87, 0x5D0D, 0x8D88, 0x5D0E, 0xC6E9, 0x5D0F, 0x8D89, 0x5D10, 0x8D8A, 0x5D11, 0x8D8B, 0x5D12, 0x8D8C, + 0x5D13, 0x8D8D, 0x5D14, 0xB4DE, 0x5D15, 0x8D8E, 0x5D16, 0xD1C2, 0x5D17, 0x8D8F, 0x5D18, 0x8D90, 0x5D19, 0x8D91, 0x5D1A, 0x8D92, + 0x5D1B, 0xE1C8, 0x5D1C, 0x8D93, 0x5D1D, 0x8D94, 0x5D1E, 0xE1C6, 0x5D1F, 0x8D95, 0x5D20, 0x8D96, 0x5D21, 0x8D97, 0x5D22, 0x8D98, + 0x5D23, 0x8D99, 0x5D24, 0xE1C5, 0x5D25, 0x8D9A, 0x5D26, 0xE1C3, 0x5D27, 0xE1C2, 0x5D28, 0x8D9B, 0x5D29, 0xB1C0, 0x5D2A, 0x8D9C, + 0x5D2B, 0x8D9D, 0x5D2C, 0x8D9E, 0x5D2D, 0xD5B8, 0x5D2E, 0xE1C4, 0x5D2F, 0x8D9F, 0x5D30, 0x8DA0, 0x5D31, 0x8DA1, 0x5D32, 0x8DA2, + 0x5D33, 0x8DA3, 0x5D34, 0xE1CB, 0x5D35, 0x8DA4, 0x5D36, 0x8DA5, 0x5D37, 0x8DA6, 0x5D38, 0x8DA7, 0x5D39, 0x8DA8, 0x5D3A, 0x8DA9, + 0x5D3B, 0x8DAA, 0x5D3C, 0x8DAB, 0x5D3D, 0xE1CC, 0x5D3E, 0xE1CA, 0x5D3F, 0x8DAC, 0x5D40, 0x8DAD, 0x5D41, 0x8DAE, 0x5D42, 0x8DAF, + 0x5D43, 0x8DB0, 0x5D44, 0x8DB1, 0x5D45, 0x8DB2, 0x5D46, 0x8DB3, 0x5D47, 0xEFFA, 0x5D48, 0x8DB4, 0x5D49, 0x8DB5, 0x5D4A, 0xE1D3, + 0x5D4B, 0xE1D2, 0x5D4C, 0xC7B6, 0x5D4D, 0x8DB6, 0x5D4E, 0x8DB7, 0x5D4F, 0x8DB8, 0x5D50, 0x8DB9, 0x5D51, 0x8DBA, 0x5D52, 0x8DBB, + 0x5D53, 0x8DBC, 0x5D54, 0x8DBD, 0x5D55, 0x8DBE, 0x5D56, 0x8DBF, 0x5D57, 0x8DC0, 0x5D58, 0xE1C9, 0x5D59, 0x8DC1, 0x5D5A, 0x8DC2, + 0x5D5B, 0xE1CE, 0x5D5C, 0x8DC3, 0x5D5D, 0xE1D0, 0x5D5E, 0x8DC4, 0x5D5F, 0x8DC5, 0x5D60, 0x8DC6, 0x5D61, 0x8DC7, 0x5D62, 0x8DC8, + 0x5D63, 0x8DC9, 0x5D64, 0x8DCA, 0x5D65, 0x8DCB, 0x5D66, 0x8DCC, 0x5D67, 0x8DCD, 0x5D68, 0x8DCE, 0x5D69, 0xE1D4, 0x5D6A, 0x8DCF, + 0x5D6B, 0xE1D1, 0x5D6C, 0xE1CD, 0x5D6D, 0x8DD0, 0x5D6E, 0x8DD1, 0x5D6F, 0xE1CF, 0x5D70, 0x8DD2, 0x5D71, 0x8DD3, 0x5D72, 0x8DD4, + 0x5D73, 0x8DD5, 0x5D74, 0xE1D5, 0x5D75, 0x8DD6, 0x5D76, 0x8DD7, 0x5D77, 0x8DD8, 0x5D78, 0x8DD9, 0x5D79, 0x8DDA, 0x5D7A, 0x8DDB, + 0x5D7B, 0x8DDC, 0x5D7C, 0x8DDD, 0x5D7D, 0x8DDE, 0x5D7E, 0x8DDF, 0x5D7F, 0x8DE0, 0x5D80, 0x8DE1, 0x5D81, 0x8DE2, 0x5D82, 0xE1D6, + 0x5D83, 0x8DE3, 0x5D84, 0x8DE4, 0x5D85, 0x8DE5, 0x5D86, 0x8DE6, 0x5D87, 0x8DE7, 0x5D88, 0x8DE8, 0x5D89, 0x8DE9, 0x5D8A, 0x8DEA, + 0x5D8B, 0x8DEB, 0x5D8C, 0x8DEC, 0x5D8D, 0x8DED, 0x5D8E, 0x8DEE, 0x5D8F, 0x8DEF, 0x5D90, 0x8DF0, 0x5D91, 0x8DF1, 0x5D92, 0x8DF2, + 0x5D93, 0x8DF3, 0x5D94, 0x8DF4, 0x5D95, 0x8DF5, 0x5D96, 0x8DF6, 0x5D97, 0x8DF7, 0x5D98, 0x8DF8, 0x5D99, 0xE1D7, 0x5D9A, 0x8DF9, + 0x5D9B, 0x8DFA, 0x5D9C, 0x8DFB, 0x5D9D, 0xE1D8, 0x5D9E, 0x8DFC, 0x5D9F, 0x8DFD, 0x5DA0, 0x8DFE, 0x5DA1, 0x8E40, 0x5DA2, 0x8E41, + 0x5DA3, 0x8E42, 0x5DA4, 0x8E43, 0x5DA5, 0x8E44, 0x5DA6, 0x8E45, 0x5DA7, 0x8E46, 0x5DA8, 0x8E47, 0x5DA9, 0x8E48, 0x5DAA, 0x8E49, + 0x5DAB, 0x8E4A, 0x5DAC, 0x8E4B, 0x5DAD, 0x8E4C, 0x5DAE, 0x8E4D, 0x5DAF, 0x8E4E, 0x5DB0, 0x8E4F, 0x5DB1, 0x8E50, 0x5DB2, 0x8E51, + 0x5DB3, 0x8E52, 0x5DB4, 0x8E53, 0x5DB5, 0x8E54, 0x5DB6, 0x8E55, 0x5DB7, 0xE1DA, 0x5DB8, 0x8E56, 0x5DB9, 0x8E57, 0x5DBA, 0x8E58, + 0x5DBB, 0x8E59, 0x5DBC, 0x8E5A, 0x5DBD, 0x8E5B, 0x5DBE, 0x8E5C, 0x5DBF, 0x8E5D, 0x5DC0, 0x8E5E, 0x5DC1, 0x8E5F, 0x5DC2, 0x8E60, + 0x5DC3, 0x8E61, 0x5DC4, 0x8E62, 0x5DC5, 0xE1DB, 0x5DC6, 0x8E63, 0x5DC7, 0x8E64, 0x5DC8, 0x8E65, 0x5DC9, 0x8E66, 0x5DCA, 0x8E67, + 0x5DCB, 0x8E68, 0x5DCC, 0x8E69, 0x5DCD, 0xCEA1, 0x5DCE, 0x8E6A, 0x5DCF, 0x8E6B, 0x5DD0, 0x8E6C, 0x5DD1, 0x8E6D, 0x5DD2, 0x8E6E, + 0x5DD3, 0x8E6F, 0x5DD4, 0x8E70, 0x5DD5, 0x8E71, 0x5DD6, 0x8E72, 0x5DD7, 0x8E73, 0x5DD8, 0x8E74, 0x5DD9, 0x8E75, 0x5DDA, 0x8E76, + 0x5DDB, 0xE7DD, 0x5DDC, 0x8E77, 0x5DDD, 0xB4A8, 0x5DDE, 0xD6DD, 0x5DDF, 0x8E78, 0x5DE0, 0x8E79, 0x5DE1, 0xD1B2, 0x5DE2, 0xB3B2, + 0x5DE3, 0x8E7A, 0x5DE4, 0x8E7B, 0x5DE5, 0xB9A4, 0x5DE6, 0xD7F3, 0x5DE7, 0xC7C9, 0x5DE8, 0xBEDE, 0x5DE9, 0xB9AE, 0x5DEA, 0x8E7C, + 0x5DEB, 0xCED7, 0x5DEC, 0x8E7D, 0x5DED, 0x8E7E, 0x5DEE, 0xB2EE, 0x5DEF, 0xDBCF, 0x5DF0, 0x8E80, 0x5DF1, 0xBCBA, 0x5DF2, 0xD2D1, + 0x5DF3, 0xCBC8, 0x5DF4, 0xB0CD, 0x5DF5, 0x8E81, 0x5DF6, 0x8E82, 0x5DF7, 0xCFEF, 0x5DF8, 0x8E83, 0x5DF9, 0x8E84, 0x5DFA, 0x8E85, + 0x5DFB, 0x8E86, 0x5DFC, 0x8E87, 0x5DFD, 0xD9E3, 0x5DFE, 0xBDED, 0x5DFF, 0x8E88, 0x5E00, 0x8E89, 0x5E01, 0xB1D2, 0x5E02, 0xCAD0, + 0x5E03, 0xB2BC, 0x5E04, 0x8E8A, 0x5E05, 0xCBA7, 0x5E06, 0xB7AB, 0x5E07, 0x8E8B, 0x5E08, 0xCAA6, 0x5E09, 0x8E8C, 0x5E0A, 0x8E8D, + 0x5E0B, 0x8E8E, 0x5E0C, 0xCFA3, 0x5E0D, 0x8E8F, 0x5E0E, 0x8E90, 0x5E0F, 0xE0F8, 0x5E10, 0xD5CA, 0x5E11, 0xE0FB, 0x5E12, 0x8E91, + 0x5E13, 0x8E92, 0x5E14, 0xE0FA, 0x5E15, 0xC5C1, 0x5E16, 0xCCFB, 0x5E17, 0x8E93, 0x5E18, 0xC1B1, 0x5E19, 0xE0F9, 0x5E1A, 0xD6E3, + 0x5E1B, 0xB2AF, 0x5E1C, 0xD6C4, 0x5E1D, 0xB5DB, 0x5E1E, 0x8E94, 0x5E1F, 0x8E95, 0x5E20, 0x8E96, 0x5E21, 0x8E97, 0x5E22, 0x8E98, + 0x5E23, 0x8E99, 0x5E24, 0x8E9A, 0x5E25, 0x8E9B, 0x5E26, 0xB4F8, 0x5E27, 0xD6A1, 0x5E28, 0x8E9C, 0x5E29, 0x8E9D, 0x5E2A, 0x8E9E, + 0x5E2B, 0x8E9F, 0x5E2C, 0x8EA0, 0x5E2D, 0xCFAF, 0x5E2E, 0xB0EF, 0x5E2F, 0x8EA1, 0x5E30, 0x8EA2, 0x5E31, 0xE0FC, 0x5E32, 0x8EA3, + 0x5E33, 0x8EA4, 0x5E34, 0x8EA5, 0x5E35, 0x8EA6, 0x5E36, 0x8EA7, 0x5E37, 0xE1A1, 0x5E38, 0xB3A3, 0x5E39, 0x8EA8, 0x5E3A, 0x8EA9, + 0x5E3B, 0xE0FD, 0x5E3C, 0xE0FE, 0x5E3D, 0xC3B1, 0x5E3E, 0x8EAA, 0x5E3F, 0x8EAB, 0x5E40, 0x8EAC, 0x5E41, 0x8EAD, 0x5E42, 0xC3DD, + 0x5E43, 0x8EAE, 0x5E44, 0xE1A2, 0x5E45, 0xB7F9, 0x5E46, 0x8EAF, 0x5E47, 0x8EB0, 0x5E48, 0x8EB1, 0x5E49, 0x8EB2, 0x5E4A, 0x8EB3, + 0x5E4B, 0x8EB4, 0x5E4C, 0xBBCF, 0x5E4D, 0x8EB5, 0x5E4E, 0x8EB6, 0x5E4F, 0x8EB7, 0x5E50, 0x8EB8, 0x5E51, 0x8EB9, 0x5E52, 0x8EBA, + 0x5E53, 0x8EBB, 0x5E54, 0xE1A3, 0x5E55, 0xC4BB, 0x5E56, 0x8EBC, 0x5E57, 0x8EBD, 0x5E58, 0x8EBE, 0x5E59, 0x8EBF, 0x5E5A, 0x8EC0, + 0x5E5B, 0xE1A4, 0x5E5C, 0x8EC1, 0x5E5D, 0x8EC2, 0x5E5E, 0xE1A5, 0x5E5F, 0x8EC3, 0x5E60, 0x8EC4, 0x5E61, 0xE1A6, 0x5E62, 0xB4B1, + 0x5E63, 0x8EC5, 0x5E64, 0x8EC6, 0x5E65, 0x8EC7, 0x5E66, 0x8EC8, 0x5E67, 0x8EC9, 0x5E68, 0x8ECA, 0x5E69, 0x8ECB, 0x5E6A, 0x8ECC, + 0x5E6B, 0x8ECD, 0x5E6C, 0x8ECE, 0x5E6D, 0x8ECF, 0x5E6E, 0x8ED0, 0x5E6F, 0x8ED1, 0x5E70, 0x8ED2, 0x5E71, 0x8ED3, 0x5E72, 0xB8C9, + 0x5E73, 0xC6BD, 0x5E74, 0xC4EA, 0x5E75, 0x8ED4, 0x5E76, 0xB2A2, 0x5E77, 0x8ED5, 0x5E78, 0xD0D2, 0x5E79, 0x8ED6, 0x5E7A, 0xE7DB, + 0x5E7B, 0xBBC3, 0x5E7C, 0xD3D7, 0x5E7D, 0xD3C4, 0x5E7E, 0x8ED7, 0x5E7F, 0xB9E3, 0x5E80, 0xE2CF, 0x5E81, 0x8ED8, 0x5E82, 0x8ED9, + 0x5E83, 0x8EDA, 0x5E84, 0xD7AF, 0x5E85, 0x8EDB, 0x5E86, 0xC7EC, 0x5E87, 0xB1D3, 0x5E88, 0x8EDC, 0x5E89, 0x8EDD, 0x5E8A, 0xB4B2, + 0x5E8B, 0xE2D1, 0x5E8C, 0x8EDE, 0x5E8D, 0x8EDF, 0x5E8E, 0x8EE0, 0x5E8F, 0xD0F2, 0x5E90, 0xC2AE, 0x5E91, 0xE2D0, 0x5E92, 0x8EE1, + 0x5E93, 0xBFE2, 0x5E94, 0xD3A6, 0x5E95, 0xB5D7, 0x5E96, 0xE2D2, 0x5E97, 0xB5EA, 0x5E98, 0x8EE2, 0x5E99, 0xC3ED, 0x5E9A, 0xB8FD, + 0x5E9B, 0x8EE3, 0x5E9C, 0xB8AE, 0x5E9D, 0x8EE4, 0x5E9E, 0xC5D3, 0x5E9F, 0xB7CF, 0x5EA0, 0xE2D4, 0x5EA1, 0x8EE5, 0x5EA2, 0x8EE6, + 0x5EA3, 0x8EE7, 0x5EA4, 0x8EE8, 0x5EA5, 0xE2D3, 0x5EA6, 0xB6C8, 0x5EA7, 0xD7F9, 0x5EA8, 0x8EE9, 0x5EA9, 0x8EEA, 0x5EAA, 0x8EEB, + 0x5EAB, 0x8EEC, 0x5EAC, 0x8EED, 0x5EAD, 0xCDA5, 0x5EAE, 0x8EEE, 0x5EAF, 0x8EEF, 0x5EB0, 0x8EF0, 0x5EB1, 0x8EF1, 0x5EB2, 0x8EF2, + 0x5EB3, 0xE2D8, 0x5EB4, 0x8EF3, 0x5EB5, 0xE2D6, 0x5EB6, 0xCAFC, 0x5EB7, 0xBFB5, 0x5EB8, 0xD3B9, 0x5EB9, 0xE2D5, 0x5EBA, 0x8EF4, + 0x5EBB, 0x8EF5, 0x5EBC, 0x8EF6, 0x5EBD, 0x8EF7, 0x5EBE, 0xE2D7, 0x5EBF, 0x8EF8, 0x5EC0, 0x8EF9, 0x5EC1, 0x8EFA, 0x5EC2, 0x8EFB, + 0x5EC3, 0x8EFC, 0x5EC4, 0x8EFD, 0x5EC5, 0x8EFE, 0x5EC6, 0x8F40, 0x5EC7, 0x8F41, 0x5EC8, 0x8F42, 0x5EC9, 0xC1AE, 0x5ECA, 0xC0C8, + 0x5ECB, 0x8F43, 0x5ECC, 0x8F44, 0x5ECD, 0x8F45, 0x5ECE, 0x8F46, 0x5ECF, 0x8F47, 0x5ED0, 0x8F48, 0x5ED1, 0xE2DB, 0x5ED2, 0xE2DA, + 0x5ED3, 0xC0AA, 0x5ED4, 0x8F49, 0x5ED5, 0x8F4A, 0x5ED6, 0xC1CE, 0x5ED7, 0x8F4B, 0x5ED8, 0x8F4C, 0x5ED9, 0x8F4D, 0x5EDA, 0x8F4E, + 0x5EDB, 0xE2DC, 0x5EDC, 0x8F4F, 0x5EDD, 0x8F50, 0x5EDE, 0x8F51, 0x5EDF, 0x8F52, 0x5EE0, 0x8F53, 0x5EE1, 0x8F54, 0x5EE2, 0x8F55, + 0x5EE3, 0x8F56, 0x5EE4, 0x8F57, 0x5EE5, 0x8F58, 0x5EE6, 0x8F59, 0x5EE7, 0x8F5A, 0x5EE8, 0xE2DD, 0x5EE9, 0x8F5B, 0x5EEA, 0xE2DE, + 0x5EEB, 0x8F5C, 0x5EEC, 0x8F5D, 0x5EED, 0x8F5E, 0x5EEE, 0x8F5F, 0x5EEF, 0x8F60, 0x5EF0, 0x8F61, 0x5EF1, 0x8F62, 0x5EF2, 0x8F63, + 0x5EF3, 0x8F64, 0x5EF4, 0xDBC8, 0x5EF5, 0x8F65, 0x5EF6, 0xD1D3, 0x5EF7, 0xCDA2, 0x5EF8, 0x8F66, 0x5EF9, 0x8F67, 0x5EFA, 0xBDA8, + 0x5EFB, 0x8F68, 0x5EFC, 0x8F69, 0x5EFD, 0x8F6A, 0x5EFE, 0xDEC3, 0x5EFF, 0xD8A5, 0x5F00, 0xBFAA, 0x5F01, 0xDBCD, 0x5F02, 0xD2EC, + 0x5F03, 0xC6FA, 0x5F04, 0xC5AA, 0x5F05, 0x8F6B, 0x5F06, 0x8F6C, 0x5F07, 0x8F6D, 0x5F08, 0xDEC4, 0x5F09, 0x8F6E, 0x5F0A, 0xB1D7, + 0x5F0B, 0xDFAE, 0x5F0C, 0x8F6F, 0x5F0D, 0x8F70, 0x5F0E, 0x8F71, 0x5F0F, 0xCABD, 0x5F10, 0x8F72, 0x5F11, 0xDFB1, 0x5F12, 0x8F73, + 0x5F13, 0xB9AD, 0x5F14, 0x8F74, 0x5F15, 0xD2FD, 0x5F16, 0x8F75, 0x5F17, 0xB8A5, 0x5F18, 0xBAEB, 0x5F19, 0x8F76, 0x5F1A, 0x8F77, + 0x5F1B, 0xB3DA, 0x5F1C, 0x8F78, 0x5F1D, 0x8F79, 0x5F1E, 0x8F7A, 0x5F1F, 0xB5DC, 0x5F20, 0xD5C5, 0x5F21, 0x8F7B, 0x5F22, 0x8F7C, + 0x5F23, 0x8F7D, 0x5F24, 0x8F7E, 0x5F25, 0xC3D6, 0x5F26, 0xCFD2, 0x5F27, 0xBBA1, 0x5F28, 0x8F80, 0x5F29, 0xE5F3, 0x5F2A, 0xE5F2, + 0x5F2B, 0x8F81, 0x5F2C, 0x8F82, 0x5F2D, 0xE5F4, 0x5F2E, 0x8F83, 0x5F2F, 0xCDE4, 0x5F30, 0x8F84, 0x5F31, 0xC8F5, 0x5F32, 0x8F85, + 0x5F33, 0x8F86, 0x5F34, 0x8F87, 0x5F35, 0x8F88, 0x5F36, 0x8F89, 0x5F37, 0x8F8A, 0x5F38, 0x8F8B, 0x5F39, 0xB5AF, 0x5F3A, 0xC7BF, + 0x5F3B, 0x8F8C, 0x5F3C, 0xE5F6, 0x5F3D, 0x8F8D, 0x5F3E, 0x8F8E, 0x5F3F, 0x8F8F, 0x5F40, 0xECB0, 0x5F41, 0x8F90, 0x5F42, 0x8F91, + 0x5F43, 0x8F92, 0x5F44, 0x8F93, 0x5F45, 0x8F94, 0x5F46, 0x8F95, 0x5F47, 0x8F96, 0x5F48, 0x8F97, 0x5F49, 0x8F98, 0x5F4A, 0x8F99, + 0x5F4B, 0x8F9A, 0x5F4C, 0x8F9B, 0x5F4D, 0x8F9C, 0x5F4E, 0x8F9D, 0x5F4F, 0x8F9E, 0x5F50, 0xE5E6, 0x5F51, 0x8F9F, 0x5F52, 0xB9E9, + 0x5F53, 0xB5B1, 0x5F54, 0x8FA0, 0x5F55, 0xC2BC, 0x5F56, 0xE5E8, 0x5F57, 0xE5E7, 0x5F58, 0xE5E9, 0x5F59, 0x8FA1, 0x5F5A, 0x8FA2, + 0x5F5B, 0x8FA3, 0x5F5C, 0x8FA4, 0x5F5D, 0xD2CD, 0x5F5E, 0x8FA5, 0x5F5F, 0x8FA6, 0x5F60, 0x8FA7, 0x5F61, 0xE1EA, 0x5F62, 0xD0CE, + 0x5F63, 0x8FA8, 0x5F64, 0xCDAE, 0x5F65, 0x8FA9, 0x5F66, 0xD1E5, 0x5F67, 0x8FAA, 0x5F68, 0x8FAB, 0x5F69, 0xB2CA, 0x5F6A, 0xB1EB, + 0x5F6B, 0x8FAC, 0x5F6C, 0xB1F2, 0x5F6D, 0xC5ED, 0x5F6E, 0x8FAD, 0x5F6F, 0x8FAE, 0x5F70, 0xD5C3, 0x5F71, 0xD3B0, 0x5F72, 0x8FAF, + 0x5F73, 0xE1DC, 0x5F74, 0x8FB0, 0x5F75, 0x8FB1, 0x5F76, 0x8FB2, 0x5F77, 0xE1DD, 0x5F78, 0x8FB3, 0x5F79, 0xD2DB, 0x5F7A, 0x8FB4, + 0x5F7B, 0xB3B9, 0x5F7C, 0xB1CB, 0x5F7D, 0x8FB5, 0x5F7E, 0x8FB6, 0x5F7F, 0x8FB7, 0x5F80, 0xCDF9, 0x5F81, 0xD5F7, 0x5F82, 0xE1DE, + 0x5F83, 0x8FB8, 0x5F84, 0xBEB6, 0x5F85, 0xB4FD, 0x5F86, 0x8FB9, 0x5F87, 0xE1DF, 0x5F88, 0xBADC, 0x5F89, 0xE1E0, 0x5F8A, 0xBBB2, + 0x5F8B, 0xC2C9, 0x5F8C, 0xE1E1, 0x5F8D, 0x8FBA, 0x5F8E, 0x8FBB, 0x5F8F, 0x8FBC, 0x5F90, 0xD0EC, 0x5F91, 0x8FBD, 0x5F92, 0xCDBD, + 0x5F93, 0x8FBE, 0x5F94, 0x8FBF, 0x5F95, 0xE1E2, 0x5F96, 0x8FC0, 0x5F97, 0xB5C3, 0x5F98, 0xC5C7, 0x5F99, 0xE1E3, 0x5F9A, 0x8FC1, + 0x5F9B, 0x8FC2, 0x5F9C, 0xE1E4, 0x5F9D, 0x8FC3, 0x5F9E, 0x8FC4, 0x5F9F, 0x8FC5, 0x5FA0, 0x8FC6, 0x5FA1, 0xD3F9, 0x5FA2, 0x8FC7, + 0x5FA3, 0x8FC8, 0x5FA4, 0x8FC9, 0x5FA5, 0x8FCA, 0x5FA6, 0x8FCB, 0x5FA7, 0x8FCC, 0x5FA8, 0xE1E5, 0x5FA9, 0x8FCD, 0x5FAA, 0xD1AD, + 0x5FAB, 0x8FCE, 0x5FAC, 0x8FCF, 0x5FAD, 0xE1E6, 0x5FAE, 0xCEA2, 0x5FAF, 0x8FD0, 0x5FB0, 0x8FD1, 0x5FB1, 0x8FD2, 0x5FB2, 0x8FD3, + 0x5FB3, 0x8FD4, 0x5FB4, 0x8FD5, 0x5FB5, 0xE1E7, 0x5FB6, 0x8FD6, 0x5FB7, 0xB5C2, 0x5FB8, 0x8FD7, 0x5FB9, 0x8FD8, 0x5FBA, 0x8FD9, + 0x5FBB, 0x8FDA, 0x5FBC, 0xE1E8, 0x5FBD, 0xBBD5, 0x5FBE, 0x8FDB, 0x5FBF, 0x8FDC, 0x5FC0, 0x8FDD, 0x5FC1, 0x8FDE, 0x5FC2, 0x8FDF, + 0x5FC3, 0xD0C4, 0x5FC4, 0xE2E0, 0x5FC5, 0xB1D8, 0x5FC6, 0xD2E4, 0x5FC7, 0x8FE0, 0x5FC8, 0x8FE1, 0x5FC9, 0xE2E1, 0x5FCA, 0x8FE2, + 0x5FCB, 0x8FE3, 0x5FCC, 0xBCC9, 0x5FCD, 0xC8CC, 0x5FCE, 0x8FE4, 0x5FCF, 0xE2E3, 0x5FD0, 0xECFE, 0x5FD1, 0xECFD, 0x5FD2, 0xDFAF, + 0x5FD3, 0x8FE5, 0x5FD4, 0x8FE6, 0x5FD5, 0x8FE7, 0x5FD6, 0xE2E2, 0x5FD7, 0xD6BE, 0x5FD8, 0xCDFC, 0x5FD9, 0xC3A6, 0x5FDA, 0x8FE8, + 0x5FDB, 0x8FE9, 0x5FDC, 0x8FEA, 0x5FDD, 0xE3C3, 0x5FDE, 0x8FEB, 0x5FDF, 0x8FEC, 0x5FE0, 0xD6D2, 0x5FE1, 0xE2E7, 0x5FE2, 0x8FED, + 0x5FE3, 0x8FEE, 0x5FE4, 0xE2E8, 0x5FE5, 0x8FEF, 0x5FE6, 0x8FF0, 0x5FE7, 0xD3C7, 0x5FE8, 0x8FF1, 0x5FE9, 0x8FF2, 0x5FEA, 0xE2EC, + 0x5FEB, 0xBFEC, 0x5FEC, 0x8FF3, 0x5FED, 0xE2ED, 0x5FEE, 0xE2E5, 0x5FEF, 0x8FF4, 0x5FF0, 0x8FF5, 0x5FF1, 0xB3C0, 0x5FF2, 0x8FF6, + 0x5FF3, 0x8FF7, 0x5FF4, 0x8FF8, 0x5FF5, 0xC4EE, 0x5FF6, 0x8FF9, 0x5FF7, 0x8FFA, 0x5FF8, 0xE2EE, 0x5FF9, 0x8FFB, 0x5FFA, 0x8FFC, + 0x5FFB, 0xD0C3, 0x5FFC, 0x8FFD, 0x5FFD, 0xBAF6, 0x5FFE, 0xE2E9, 0x5FFF, 0xB7DE, 0x6000, 0xBBB3, 0x6001, 0xCCAC, 0x6002, 0xCBCB, + 0x6003, 0xE2E4, 0x6004, 0xE2E6, 0x6005, 0xE2EA, 0x6006, 0xE2EB, 0x6007, 0x8FFE, 0x6008, 0x9040, 0x6009, 0x9041, 0x600A, 0xE2F7, + 0x600B, 0x9042, 0x600C, 0x9043, 0x600D, 0xE2F4, 0x600E, 0xD4F5, 0x600F, 0xE2F3, 0x6010, 0x9044, 0x6011, 0x9045, 0x6012, 0xC5AD, + 0x6013, 0x9046, 0x6014, 0xD5FA, 0x6015, 0xC5C2, 0x6016, 0xB2C0, 0x6017, 0x9047, 0x6018, 0x9048, 0x6019, 0xE2EF, 0x601A, 0x9049, + 0x601B, 0xE2F2, 0x601C, 0xC1AF, 0x601D, 0xCBBC, 0x601E, 0x904A, 0x601F, 0x904B, 0x6020, 0xB5A1, 0x6021, 0xE2F9, 0x6022, 0x904C, + 0x6023, 0x904D, 0x6024, 0x904E, 0x6025, 0xBCB1, 0x6026, 0xE2F1, 0x6027, 0xD0D4, 0x6028, 0xD4B9, 0x6029, 0xE2F5, 0x602A, 0xB9D6, + 0x602B, 0xE2F6, 0x602C, 0x904F, 0x602D, 0x9050, 0x602E, 0x9051, 0x602F, 0xC7D3, 0x6030, 0x9052, 0x6031, 0x9053, 0x6032, 0x9054, + 0x6033, 0x9055, 0x6034, 0x9056, 0x6035, 0xE2F0, 0x6036, 0x9057, 0x6037, 0x9058, 0x6038, 0x9059, 0x6039, 0x905A, 0x603A, 0x905B, + 0x603B, 0xD7DC, 0x603C, 0xEDA1, 0x603D, 0x905C, 0x603E, 0x905D, 0x603F, 0xE2F8, 0x6040, 0x905E, 0x6041, 0xEDA5, 0x6042, 0xE2FE, + 0x6043, 0xCAD1, 0x6044, 0x905F, 0x6045, 0x9060, 0x6046, 0x9061, 0x6047, 0x9062, 0x6048, 0x9063, 0x6049, 0x9064, 0x604A, 0x9065, + 0x604B, 0xC1B5, 0x604C, 0x9066, 0x604D, 0xBBD0, 0x604E, 0x9067, 0x604F, 0x9068, 0x6050, 0xBFD6, 0x6051, 0x9069, 0x6052, 0xBAE3, + 0x6053, 0x906A, 0x6054, 0x906B, 0x6055, 0xCBA1, 0x6056, 0x906C, 0x6057, 0x906D, 0x6058, 0x906E, 0x6059, 0xEDA6, 0x605A, 0xEDA3, + 0x605B, 0x906F, 0x605C, 0x9070, 0x605D, 0xEDA2, 0x605E, 0x9071, 0x605F, 0x9072, 0x6060, 0x9073, 0x6061, 0x9074, 0x6062, 0xBBD6, + 0x6063, 0xEDA7, 0x6064, 0xD0F4, 0x6065, 0x9075, 0x6066, 0x9076, 0x6067, 0xEDA4, 0x6068, 0xBADE, 0x6069, 0xB6F7, 0x606A, 0xE3A1, + 0x606B, 0xB6B2, 0x606C, 0xCCF1, 0x606D, 0xB9A7, 0x606E, 0x9077, 0x606F, 0xCFA2, 0x6070, 0xC7A1, 0x6071, 0x9078, 0x6072, 0x9079, + 0x6073, 0xBFD2, 0x6074, 0x907A, 0x6075, 0x907B, 0x6076, 0xB6F1, 0x6077, 0x907C, 0x6078, 0xE2FA, 0x6079, 0xE2FB, 0x607A, 0xE2FD, + 0x607B, 0xE2FC, 0x607C, 0xC4D5, 0x607D, 0xE3A2, 0x607E, 0x907D, 0x607F, 0xD3C1, 0x6080, 0x907E, 0x6081, 0x9080, 0x6082, 0x9081, + 0x6083, 0xE3A7, 0x6084, 0xC7C4, 0x6085, 0x9082, 0x6086, 0x9083, 0x6087, 0x9084, 0x6088, 0x9085, 0x6089, 0xCFA4, 0x608A, 0x9086, + 0x608B, 0x9087, 0x608C, 0xE3A9, 0x608D, 0xBAB7, 0x608E, 0x9088, 0x608F, 0x9089, 0x6090, 0x908A, 0x6091, 0x908B, 0x6092, 0xE3A8, + 0x6093, 0x908C, 0x6094, 0xBBDA, 0x6095, 0x908D, 0x6096, 0xE3A3, 0x6097, 0x908E, 0x6098, 0x908F, 0x6099, 0x9090, 0x609A, 0xE3A4, + 0x609B, 0xE3AA, 0x609C, 0x9091, 0x609D, 0xE3A6, 0x609E, 0x9092, 0x609F, 0xCEF2, 0x60A0, 0xD3C6, 0x60A1, 0x9093, 0x60A2, 0x9094, + 0x60A3, 0xBBBC, 0x60A4, 0x9095, 0x60A5, 0x9096, 0x60A6, 0xD4C3, 0x60A7, 0x9097, 0x60A8, 0xC4FA, 0x60A9, 0x9098, 0x60AA, 0x9099, + 0x60AB, 0xEDA8, 0x60AC, 0xD0FC, 0x60AD, 0xE3A5, 0x60AE, 0x909A, 0x60AF, 0xC3F5, 0x60B0, 0x909B, 0x60B1, 0xE3AD, 0x60B2, 0xB1AF, + 0x60B3, 0x909C, 0x60B4, 0xE3B2, 0x60B5, 0x909D, 0x60B6, 0x909E, 0x60B7, 0x909F, 0x60B8, 0xBCC2, 0x60B9, 0x90A0, 0x60BA, 0x90A1, + 0x60BB, 0xE3AC, 0x60BC, 0xB5BF, 0x60BD, 0x90A2, 0x60BE, 0x90A3, 0x60BF, 0x90A4, 0x60C0, 0x90A5, 0x60C1, 0x90A6, 0x60C2, 0x90A7, + 0x60C3, 0x90A8, 0x60C4, 0x90A9, 0x60C5, 0xC7E9, 0x60C6, 0xE3B0, 0x60C7, 0x90AA, 0x60C8, 0x90AB, 0x60C9, 0x90AC, 0x60CA, 0xBEAA, + 0x60CB, 0xCDEF, 0x60CC, 0x90AD, 0x60CD, 0x90AE, 0x60CE, 0x90AF, 0x60CF, 0x90B0, 0x60D0, 0x90B1, 0x60D1, 0xBBF3, 0x60D2, 0x90B2, + 0x60D3, 0x90B3, 0x60D4, 0x90B4, 0x60D5, 0xCCE8, 0x60D6, 0x90B5, 0x60D7, 0x90B6, 0x60D8, 0xE3AF, 0x60D9, 0x90B7, 0x60DA, 0xE3B1, + 0x60DB, 0x90B8, 0x60DC, 0xCFA7, 0x60DD, 0xE3AE, 0x60DE, 0x90B9, 0x60DF, 0xCEA9, 0x60E0, 0xBBDD, 0x60E1, 0x90BA, 0x60E2, 0x90BB, + 0x60E3, 0x90BC, 0x60E4, 0x90BD, 0x60E5, 0x90BE, 0x60E6, 0xB5EB, 0x60E7, 0xBEE5, 0x60E8, 0xB2D2, 0x60E9, 0xB3CD, 0x60EA, 0x90BF, + 0x60EB, 0xB1B9, 0x60EC, 0xE3AB, 0x60ED, 0xB2D1, 0x60EE, 0xB5AC, 0x60EF, 0xB9DF, 0x60F0, 0xB6E8, 0x60F1, 0x90C0, 0x60F2, 0x90C1, + 0x60F3, 0xCFEB, 0x60F4, 0xE3B7, 0x60F5, 0x90C2, 0x60F6, 0xBBCC, 0x60F7, 0x90C3, 0x60F8, 0x90C4, 0x60F9, 0xC8C7, 0x60FA, 0xD0CA, + 0x60FB, 0x90C5, 0x60FC, 0x90C6, 0x60FD, 0x90C7, 0x60FE, 0x90C8, 0x60FF, 0x90C9, 0x6100, 0xE3B8, 0x6101, 0xB3EE, 0x6102, 0x90CA, + 0x6103, 0x90CB, 0x6104, 0x90CC, 0x6105, 0x90CD, 0x6106, 0xEDA9, 0x6107, 0x90CE, 0x6108, 0xD3FA, 0x6109, 0xD3E4, 0x610A, 0x90CF, + 0x610B, 0x90D0, 0x610C, 0x90D1, 0x610D, 0xEDAA, 0x610E, 0xE3B9, 0x610F, 0xD2E2, 0x6110, 0x90D2, 0x6111, 0x90D3, 0x6112, 0x90D4, + 0x6113, 0x90D5, 0x6114, 0x90D6, 0x6115, 0xE3B5, 0x6116, 0x90D7, 0x6117, 0x90D8, 0x6118, 0x90D9, 0x6119, 0x90DA, 0x611A, 0xD3DE, + 0x611B, 0x90DB, 0x611C, 0x90DC, 0x611D, 0x90DD, 0x611E, 0x90DE, 0x611F, 0xB8D0, 0x6120, 0xE3B3, 0x6121, 0x90DF, 0x6122, 0x90E0, + 0x6123, 0xE3B6, 0x6124, 0xB7DF, 0x6125, 0x90E1, 0x6126, 0xE3B4, 0x6127, 0xC0A2, 0x6128, 0x90E2, 0x6129, 0x90E3, 0x612A, 0x90E4, + 0x612B, 0xE3BA, 0x612C, 0x90E5, 0x612D, 0x90E6, 0x612E, 0x90E7, 0x612F, 0x90E8, 0x6130, 0x90E9, 0x6131, 0x90EA, 0x6132, 0x90EB, + 0x6133, 0x90EC, 0x6134, 0x90ED, 0x6135, 0x90EE, 0x6136, 0x90EF, 0x6137, 0x90F0, 0x6138, 0x90F1, 0x6139, 0x90F2, 0x613A, 0x90F3, + 0x613B, 0x90F4, 0x613C, 0x90F5, 0x613D, 0x90F6, 0x613E, 0x90F7, 0x613F, 0xD4B8, 0x6140, 0x90F8, 0x6141, 0x90F9, 0x6142, 0x90FA, + 0x6143, 0x90FB, 0x6144, 0x90FC, 0x6145, 0x90FD, 0x6146, 0x90FE, 0x6147, 0x9140, 0x6148, 0xB4C8, 0x6149, 0x9141, 0x614A, 0xE3BB, + 0x614B, 0x9142, 0x614C, 0xBBC5, 0x614D, 0x9143, 0x614E, 0xC9F7, 0x614F, 0x9144, 0x6150, 0x9145, 0x6151, 0xC9E5, 0x6152, 0x9146, + 0x6153, 0x9147, 0x6154, 0x9148, 0x6155, 0xC4BD, 0x6156, 0x9149, 0x6157, 0x914A, 0x6158, 0x914B, 0x6159, 0x914C, 0x615A, 0x914D, + 0x615B, 0x914E, 0x615C, 0x914F, 0x615D, 0xEDAB, 0x615E, 0x9150, 0x615F, 0x9151, 0x6160, 0x9152, 0x6161, 0x9153, 0x6162, 0xC2FD, + 0x6163, 0x9154, 0x6164, 0x9155, 0x6165, 0x9156, 0x6166, 0x9157, 0x6167, 0xBBDB, 0x6168, 0xBFAE, 0x6169, 0x9158, 0x616A, 0x9159, + 0x616B, 0x915A, 0x616C, 0x915B, 0x616D, 0x915C, 0x616E, 0x915D, 0x616F, 0x915E, 0x6170, 0xCEBF, 0x6171, 0x915F, 0x6172, 0x9160, + 0x6173, 0x9161, 0x6174, 0x9162, 0x6175, 0xE3BC, 0x6176, 0x9163, 0x6177, 0xBFB6, 0x6178, 0x9164, 0x6179, 0x9165, 0x617A, 0x9166, + 0x617B, 0x9167, 0x617C, 0x9168, 0x617D, 0x9169, 0x617E, 0x916A, 0x617F, 0x916B, 0x6180, 0x916C, 0x6181, 0x916D, 0x6182, 0x916E, + 0x6183, 0x916F, 0x6184, 0x9170, 0x6185, 0x9171, 0x6186, 0x9172, 0x6187, 0x9173, 0x6188, 0x9174, 0x6189, 0x9175, 0x618A, 0x9176, + 0x618B, 0xB1EF, 0x618C, 0x9177, 0x618D, 0x9178, 0x618E, 0xD4F7, 0x618F, 0x9179, 0x6190, 0x917A, 0x6191, 0x917B, 0x6192, 0x917C, + 0x6193, 0x917D, 0x6194, 0xE3BE, 0x6195, 0x917E, 0x6196, 0x9180, 0x6197, 0x9181, 0x6198, 0x9182, 0x6199, 0x9183, 0x619A, 0x9184, + 0x619B, 0x9185, 0x619C, 0x9186, 0x619D, 0xEDAD, 0x619E, 0x9187, 0x619F, 0x9188, 0x61A0, 0x9189, 0x61A1, 0x918A, 0x61A2, 0x918B, + 0x61A3, 0x918C, 0x61A4, 0x918D, 0x61A5, 0x918E, 0x61A6, 0x918F, 0x61A7, 0xE3BF, 0x61A8, 0xBAA9, 0x61A9, 0xEDAC, 0x61AA, 0x9190, + 0x61AB, 0x9191, 0x61AC, 0xE3BD, 0x61AD, 0x9192, 0x61AE, 0x9193, 0x61AF, 0x9194, 0x61B0, 0x9195, 0x61B1, 0x9196, 0x61B2, 0x9197, + 0x61B3, 0x9198, 0x61B4, 0x9199, 0x61B5, 0x919A, 0x61B6, 0x919B, 0x61B7, 0xE3C0, 0x61B8, 0x919C, 0x61B9, 0x919D, 0x61BA, 0x919E, + 0x61BB, 0x919F, 0x61BC, 0x91A0, 0x61BD, 0x91A1, 0x61BE, 0xBAB6, 0x61BF, 0x91A2, 0x61C0, 0x91A3, 0x61C1, 0x91A4, 0x61C2, 0xB6AE, + 0x61C3, 0x91A5, 0x61C4, 0x91A6, 0x61C5, 0x91A7, 0x61C6, 0x91A8, 0x61C7, 0x91A9, 0x61C8, 0xD0B8, 0x61C9, 0x91AA, 0x61CA, 0xB0C3, + 0x61CB, 0xEDAE, 0x61CC, 0x91AB, 0x61CD, 0x91AC, 0x61CE, 0x91AD, 0x61CF, 0x91AE, 0x61D0, 0x91AF, 0x61D1, 0xEDAF, 0x61D2, 0xC0C1, + 0x61D3, 0x91B0, 0x61D4, 0xE3C1, 0x61D5, 0x91B1, 0x61D6, 0x91B2, 0x61D7, 0x91B3, 0x61D8, 0x91B4, 0x61D9, 0x91B5, 0x61DA, 0x91B6, + 0x61DB, 0x91B7, 0x61DC, 0x91B8, 0x61DD, 0x91B9, 0x61DE, 0x91BA, 0x61DF, 0x91BB, 0x61E0, 0x91BC, 0x61E1, 0x91BD, 0x61E2, 0x91BE, + 0x61E3, 0x91BF, 0x61E4, 0x91C0, 0x61E5, 0x91C1, 0x61E6, 0xC5B3, 0x61E7, 0x91C2, 0x61E8, 0x91C3, 0x61E9, 0x91C4, 0x61EA, 0x91C5, + 0x61EB, 0x91C6, 0x61EC, 0x91C7, 0x61ED, 0x91C8, 0x61EE, 0x91C9, 0x61EF, 0x91CA, 0x61F0, 0x91CB, 0x61F1, 0x91CC, 0x61F2, 0x91CD, + 0x61F3, 0x91CE, 0x61F4, 0x91CF, 0x61F5, 0xE3C2, 0x61F6, 0x91D0, 0x61F7, 0x91D1, 0x61F8, 0x91D2, 0x61F9, 0x91D3, 0x61FA, 0x91D4, + 0x61FB, 0x91D5, 0x61FC, 0x91D6, 0x61FD, 0x91D7, 0x61FE, 0x91D8, 0x61FF, 0xDCB2, 0x6200, 0x91D9, 0x6201, 0x91DA, 0x6202, 0x91DB, + 0x6203, 0x91DC, 0x6204, 0x91DD, 0x6205, 0x91DE, 0x6206, 0xEDB0, 0x6207, 0x91DF, 0x6208, 0xB8EA, 0x6209, 0x91E0, 0x620A, 0xCEEC, + 0x620B, 0xEAA7, 0x620C, 0xD0E7, 0x620D, 0xCAF9, 0x620E, 0xC8D6, 0x620F, 0xCFB7, 0x6210, 0xB3C9, 0x6211, 0xCED2, 0x6212, 0xBDE4, + 0x6213, 0x91E1, 0x6214, 0x91E2, 0x6215, 0xE3DE, 0x6216, 0xBBF2, 0x6217, 0xEAA8, 0x6218, 0xD5BD, 0x6219, 0x91E3, 0x621A, 0xC6DD, + 0x621B, 0xEAA9, 0x621C, 0x91E4, 0x621D, 0x91E5, 0x621E, 0x91E6, 0x621F, 0xEAAA, 0x6220, 0x91E7, 0x6221, 0xEAAC, 0x6222, 0xEAAB, + 0x6223, 0x91E8, 0x6224, 0xEAAE, 0x6225, 0xEAAD, 0x6226, 0x91E9, 0x6227, 0x91EA, 0x6228, 0x91EB, 0x6229, 0x91EC, 0x622A, 0xBDD8, + 0x622B, 0x91ED, 0x622C, 0xEAAF, 0x622D, 0x91EE, 0x622E, 0xC2BE, 0x622F, 0x91EF, 0x6230, 0x91F0, 0x6231, 0x91F1, 0x6232, 0x91F2, + 0x6233, 0xB4C1, 0x6234, 0xB4F7, 0x6235, 0x91F3, 0x6236, 0x91F4, 0x6237, 0xBBA7, 0x6238, 0x91F5, 0x6239, 0x91F6, 0x623A, 0x91F7, + 0x623B, 0x91F8, 0x623C, 0x91F9, 0x623D, 0xECE6, 0x623E, 0xECE5, 0x623F, 0xB7BF, 0x6240, 0xCBF9, 0x6241, 0xB1E2, 0x6242, 0x91FA, + 0x6243, 0xECE7, 0x6244, 0x91FB, 0x6245, 0x91FC, 0x6246, 0x91FD, 0x6247, 0xC9C8, 0x6248, 0xECE8, 0x6249, 0xECE9, 0x624A, 0x91FE, + 0x624B, 0xCAD6, 0x624C, 0xDED0, 0x624D, 0xB2C5, 0x624E, 0xD4FA, 0x624F, 0x9240, 0x6250, 0x9241, 0x6251, 0xC6CB, 0x6252, 0xB0C7, + 0x6253, 0xB4F2, 0x6254, 0xC8D3, 0x6255, 0x9242, 0x6256, 0x9243, 0x6257, 0x9244, 0x6258, 0xCDD0, 0x6259, 0x9245, 0x625A, 0x9246, + 0x625B, 0xBFB8, 0x625C, 0x9247, 0x625D, 0x9248, 0x625E, 0x9249, 0x625F, 0x924A, 0x6260, 0x924B, 0x6261, 0x924C, 0x6262, 0x924D, + 0x6263, 0xBFDB, 0x6264, 0x924E, 0x6265, 0x924F, 0x6266, 0xC7A4, 0x6267, 0xD6B4, 0x6268, 0x9250, 0x6269, 0xC0A9, 0x626A, 0xDED1, + 0x626B, 0xC9A8, 0x626C, 0xD1EF, 0x626D, 0xC5A4, 0x626E, 0xB0E7, 0x626F, 0xB3B6, 0x6270, 0xC8C5, 0x6271, 0x9251, 0x6272, 0x9252, + 0x6273, 0xB0E2, 0x6274, 0x9253, 0x6275, 0x9254, 0x6276, 0xB7F6, 0x6277, 0x9255, 0x6278, 0x9256, 0x6279, 0xC5FA, 0x627A, 0x9257, + 0x627B, 0x9258, 0x627C, 0xB6F3, 0x627D, 0x9259, 0x627E, 0xD5D2, 0x627F, 0xB3D0, 0x6280, 0xBCBC, 0x6281, 0x925A, 0x6282, 0x925B, + 0x6283, 0x925C, 0x6284, 0xB3AD, 0x6285, 0x925D, 0x6286, 0x925E, 0x6287, 0x925F, 0x6288, 0x9260, 0x6289, 0xBEF1, 0x628A, 0xB0D1, + 0x628B, 0x9261, 0x628C, 0x9262, 0x628D, 0x9263, 0x628E, 0x9264, 0x628F, 0x9265, 0x6290, 0x9266, 0x6291, 0xD2D6, 0x6292, 0xCAE3, + 0x6293, 0xD7A5, 0x6294, 0x9267, 0x6295, 0xCDB6, 0x6296, 0xB6B6, 0x6297, 0xBFB9, 0x6298, 0xD5DB, 0x6299, 0x9268, 0x629A, 0xB8A7, + 0x629B, 0xC5D7, 0x629C, 0x9269, 0x629D, 0x926A, 0x629E, 0x926B, 0x629F, 0xDED2, 0x62A0, 0xBFD9, 0x62A1, 0xC2D5, 0x62A2, 0xC7C0, + 0x62A3, 0x926C, 0x62A4, 0xBBA4, 0x62A5, 0xB1A8, 0x62A6, 0x926D, 0x62A7, 0x926E, 0x62A8, 0xC5EA, 0x62A9, 0x926F, 0x62AA, 0x9270, + 0x62AB, 0xC5FB, 0x62AC, 0xCCA7, 0x62AD, 0x9271, 0x62AE, 0x9272, 0x62AF, 0x9273, 0x62B0, 0x9274, 0x62B1, 0xB1A7, 0x62B2, 0x9275, + 0x62B3, 0x9276, 0x62B4, 0x9277, 0x62B5, 0xB5D6, 0x62B6, 0x9278, 0x62B7, 0x9279, 0x62B8, 0x927A, 0x62B9, 0xC4A8, 0x62BA, 0x927B, + 0x62BB, 0xDED3, 0x62BC, 0xD1BA, 0x62BD, 0xB3E9, 0x62BE, 0x927C, 0x62BF, 0xC3F2, 0x62C0, 0x927D, 0x62C1, 0x927E, 0x62C2, 0xB7F7, + 0x62C3, 0x9280, 0x62C4, 0xD6F4, 0x62C5, 0xB5A3, 0x62C6, 0xB2F0, 0x62C7, 0xC4B4, 0x62C8, 0xC4E9, 0x62C9, 0xC0AD, 0x62CA, 0xDED4, + 0x62CB, 0x9281, 0x62CC, 0xB0E8, 0x62CD, 0xC5C4, 0x62CE, 0xC1E0, 0x62CF, 0x9282, 0x62D0, 0xB9D5, 0x62D1, 0x9283, 0x62D2, 0xBEDC, + 0x62D3, 0xCDD8, 0x62D4, 0xB0CE, 0x62D5, 0x9284, 0x62D6, 0xCDCF, 0x62D7, 0xDED6, 0x62D8, 0xBED0, 0x62D9, 0xD7BE, 0x62DA, 0xDED5, + 0x62DB, 0xD5D0, 0x62DC, 0xB0DD, 0x62DD, 0x9285, 0x62DE, 0x9286, 0x62DF, 0xC4E2, 0x62E0, 0x9287, 0x62E1, 0x9288, 0x62E2, 0xC2A3, + 0x62E3, 0xBCF0, 0x62E4, 0x9289, 0x62E5, 0xD3B5, 0x62E6, 0xC0B9, 0x62E7, 0xC5A1, 0x62E8, 0xB2A6, 0x62E9, 0xD4F1, 0x62EA, 0x928A, + 0x62EB, 0x928B, 0x62EC, 0xC0A8, 0x62ED, 0xCAC3, 0x62EE, 0xDED7, 0x62EF, 0xD5FC, 0x62F0, 0x928C, 0x62F1, 0xB9B0, 0x62F2, 0x928D, + 0x62F3, 0xC8AD, 0x62F4, 0xCBA9, 0x62F5, 0x928E, 0x62F6, 0xDED9, 0x62F7, 0xBFBD, 0x62F8, 0x928F, 0x62F9, 0x9290, 0x62FA, 0x9291, + 0x62FB, 0x9292, 0x62FC, 0xC6B4, 0x62FD, 0xD7A7, 0x62FE, 0xCAB0, 0x62FF, 0xC4C3, 0x6300, 0x9293, 0x6301, 0xB3D6, 0x6302, 0xB9D2, + 0x6303, 0x9294, 0x6304, 0x9295, 0x6305, 0x9296, 0x6306, 0x9297, 0x6307, 0xD6B8, 0x6308, 0xEAFC, 0x6309, 0xB0B4, 0x630A, 0x9298, + 0x630B, 0x9299, 0x630C, 0x929A, 0x630D, 0x929B, 0x630E, 0xBFE6, 0x630F, 0x929C, 0x6310, 0x929D, 0x6311, 0xCCF4, 0x6312, 0x929E, + 0x6313, 0x929F, 0x6314, 0x92A0, 0x6315, 0x92A1, 0x6316, 0xCDDA, 0x6317, 0x92A2, 0x6318, 0x92A3, 0x6319, 0x92A4, 0x631A, 0xD6BF, + 0x631B, 0xC2CE, 0x631C, 0x92A5, 0x631D, 0xCECE, 0x631E, 0xCCA2, 0x631F, 0xD0AE, 0x6320, 0xC4D3, 0x6321, 0xB5B2, 0x6322, 0xDED8, + 0x6323, 0xD5F5, 0x6324, 0xBCB7, 0x6325, 0xBBD3, 0x6326, 0x92A6, 0x6327, 0x92A7, 0x6328, 0xB0A4, 0x6329, 0x92A8, 0x632A, 0xC5B2, + 0x632B, 0xB4EC, 0x632C, 0x92A9, 0x632D, 0x92AA, 0x632E, 0x92AB, 0x632F, 0xD5F1, 0x6330, 0x92AC, 0x6331, 0x92AD, 0x6332, 0xEAFD, + 0x6333, 0x92AE, 0x6334, 0x92AF, 0x6335, 0x92B0, 0x6336, 0x92B1, 0x6337, 0x92B2, 0x6338, 0x92B3, 0x6339, 0xDEDA, 0x633A, 0xCDA6, + 0x633B, 0x92B4, 0x633C, 0x92B5, 0x633D, 0xCDEC, 0x633E, 0x92B6, 0x633F, 0x92B7, 0x6340, 0x92B8, 0x6341, 0x92B9, 0x6342, 0xCEE6, + 0x6343, 0xDEDC, 0x6344, 0x92BA, 0x6345, 0xCDB1, 0x6346, 0xC0A6, 0x6347, 0x92BB, 0x6348, 0x92BC, 0x6349, 0xD7BD, 0x634A, 0x92BD, + 0x634B, 0xDEDB, 0x634C, 0xB0C6, 0x634D, 0xBAB4, 0x634E, 0xC9D3, 0x634F, 0xC4F3, 0x6350, 0xBEE8, 0x6351, 0x92BE, 0x6352, 0x92BF, + 0x6353, 0x92C0, 0x6354, 0x92C1, 0x6355, 0xB2B6, 0x6356, 0x92C2, 0x6357, 0x92C3, 0x6358, 0x92C4, 0x6359, 0x92C5, 0x635A, 0x92C6, + 0x635B, 0x92C7, 0x635C, 0x92C8, 0x635D, 0x92C9, 0x635E, 0xC0CC, 0x635F, 0xCBF0, 0x6360, 0x92CA, 0x6361, 0xBCF1, 0x6362, 0xBBBB, + 0x6363, 0xB5B7, 0x6364, 0x92CB, 0x6365, 0x92CC, 0x6366, 0x92CD, 0x6367, 0xC5F5, 0x6368, 0x92CE, 0x6369, 0xDEE6, 0x636A, 0x92CF, + 0x636B, 0x92D0, 0x636C, 0x92D1, 0x636D, 0xDEE3, 0x636E, 0xBEDD, 0x636F, 0x92D2, 0x6370, 0x92D3, 0x6371, 0xDEDF, 0x6372, 0x92D4, + 0x6373, 0x92D5, 0x6374, 0x92D6, 0x6375, 0x92D7, 0x6376, 0xB4B7, 0x6377, 0xBDDD, 0x6378, 0x92D8, 0x6379, 0x92D9, 0x637A, 0xDEE0, + 0x637B, 0xC4ED, 0x637C, 0x92DA, 0x637D, 0x92DB, 0x637E, 0x92DC, 0x637F, 0x92DD, 0x6380, 0xCFC6, 0x6381, 0x92DE, 0x6382, 0xB5E0, + 0x6383, 0x92DF, 0x6384, 0x92E0, 0x6385, 0x92E1, 0x6386, 0x92E2, 0x6387, 0xB6DE, 0x6388, 0xCADA, 0x6389, 0xB5F4, 0x638A, 0xDEE5, + 0x638B, 0x92E3, 0x638C, 0xD5C6, 0x638D, 0x92E4, 0x638E, 0xDEE1, 0x638F, 0xCCCD, 0x6390, 0xC6FE, 0x6391, 0x92E5, 0x6392, 0xC5C5, + 0x6393, 0x92E6, 0x6394, 0x92E7, 0x6395, 0x92E8, 0x6396, 0xD2B4, 0x6397, 0x92E9, 0x6398, 0xBEF2, 0x6399, 0x92EA, 0x639A, 0x92EB, + 0x639B, 0x92EC, 0x639C, 0x92ED, 0x639D, 0x92EE, 0x639E, 0x92EF, 0x639F, 0x92F0, 0x63A0, 0xC2D3, 0x63A1, 0x92F1, 0x63A2, 0xCCBD, + 0x63A3, 0xB3B8, 0x63A4, 0x92F2, 0x63A5, 0xBDD3, 0x63A6, 0x92F3, 0x63A7, 0xBFD8, 0x63A8, 0xCDC6, 0x63A9, 0xD1DA, 0x63AA, 0xB4EB, + 0x63AB, 0x92F4, 0x63AC, 0xDEE4, 0x63AD, 0xDEDD, 0x63AE, 0xDEE7, 0x63AF, 0x92F5, 0x63B0, 0xEAFE, 0x63B1, 0x92F6, 0x63B2, 0x92F7, + 0x63B3, 0xC2B0, 0x63B4, 0xDEE2, 0x63B5, 0x92F8, 0x63B6, 0x92F9, 0x63B7, 0xD6C0, 0x63B8, 0xB5A7, 0x63B9, 0x92FA, 0x63BA, 0xB2F4, + 0x63BB, 0x92FB, 0x63BC, 0xDEE8, 0x63BD, 0x92FC, 0x63BE, 0xDEF2, 0x63BF, 0x92FD, 0x63C0, 0x92FE, 0x63C1, 0x9340, 0x63C2, 0x9341, + 0x63C3, 0x9342, 0x63C4, 0xDEED, 0x63C5, 0x9343, 0x63C6, 0xDEF1, 0x63C7, 0x9344, 0x63C8, 0x9345, 0x63C9, 0xC8E0, 0x63CA, 0x9346, + 0x63CB, 0x9347, 0x63CC, 0x9348, 0x63CD, 0xD7E1, 0x63CE, 0xDEEF, 0x63CF, 0xC3E8, 0x63D0, 0xCCE1, 0x63D1, 0x9349, 0x63D2, 0xB2E5, + 0x63D3, 0x934A, 0x63D4, 0x934B, 0x63D5, 0x934C, 0x63D6, 0xD2BE, 0x63D7, 0x934D, 0x63D8, 0x934E, 0x63D9, 0x934F, 0x63DA, 0x9350, + 0x63DB, 0x9351, 0x63DC, 0x9352, 0x63DD, 0x9353, 0x63DE, 0xDEEE, 0x63DF, 0x9354, 0x63E0, 0xDEEB, 0x63E1, 0xCED5, 0x63E2, 0x9355, + 0x63E3, 0xB4A7, 0x63E4, 0x9356, 0x63E5, 0x9357, 0x63E6, 0x9358, 0x63E7, 0x9359, 0x63E8, 0x935A, 0x63E9, 0xBFAB, 0x63EA, 0xBEBE, + 0x63EB, 0x935B, 0x63EC, 0x935C, 0x63ED, 0xBDD2, 0x63EE, 0x935D, 0x63EF, 0x935E, 0x63F0, 0x935F, 0x63F1, 0x9360, 0x63F2, 0xDEE9, + 0x63F3, 0x9361, 0x63F4, 0xD4AE, 0x63F5, 0x9362, 0x63F6, 0xDEDE, 0x63F7, 0x9363, 0x63F8, 0xDEEA, 0x63F9, 0x9364, 0x63FA, 0x9365, + 0x63FB, 0x9366, 0x63FC, 0x9367, 0x63FD, 0xC0BF, 0x63FE, 0x9368, 0x63FF, 0xDEEC, 0x6400, 0xB2F3, 0x6401, 0xB8E9, 0x6402, 0xC2A7, + 0x6403, 0x9369, 0x6404, 0x936A, 0x6405, 0xBDC1, 0x6406, 0x936B, 0x6407, 0x936C, 0x6408, 0x936D, 0x6409, 0x936E, 0x640A, 0x936F, + 0x640B, 0xDEF5, 0x640C, 0xDEF8, 0x640D, 0x9370, 0x640E, 0x9371, 0x640F, 0xB2AB, 0x6410, 0xB4A4, 0x6411, 0x9372, 0x6412, 0x9373, + 0x6413, 0xB4EA, 0x6414, 0xC9A6, 0x6415, 0x9374, 0x6416, 0x9375, 0x6417, 0x9376, 0x6418, 0x9377, 0x6419, 0x9378, 0x641A, 0x9379, + 0x641B, 0xDEF6, 0x641C, 0xCBD1, 0x641D, 0x937A, 0x641E, 0xB8E3, 0x641F, 0x937B, 0x6420, 0xDEF7, 0x6421, 0xDEFA, 0x6422, 0x937C, + 0x6423, 0x937D, 0x6424, 0x937E, 0x6425, 0x9380, 0x6426, 0xDEF9, 0x6427, 0x9381, 0x6428, 0x9382, 0x6429, 0x9383, 0x642A, 0xCCC2, + 0x642B, 0x9384, 0x642C, 0xB0E1, 0x642D, 0xB4EE, 0x642E, 0x9385, 0x642F, 0x9386, 0x6430, 0x9387, 0x6431, 0x9388, 0x6432, 0x9389, + 0x6433, 0x938A, 0x6434, 0xE5BA, 0x6435, 0x938B, 0x6436, 0x938C, 0x6437, 0x938D, 0x6438, 0x938E, 0x6439, 0x938F, 0x643A, 0xD0AF, + 0x643B, 0x9390, 0x643C, 0x9391, 0x643D, 0xB2EB, 0x643E, 0x9392, 0x643F, 0xEBA1, 0x6440, 0x9393, 0x6441, 0xDEF4, 0x6442, 0x9394, + 0x6443, 0x9395, 0x6444, 0xC9E3, 0x6445, 0xDEF3, 0x6446, 0xB0DA, 0x6447, 0xD2A1, 0x6448, 0xB1F7, 0x6449, 0x9396, 0x644A, 0xCCAF, + 0x644B, 0x9397, 0x644C, 0x9398, 0x644D, 0x9399, 0x644E, 0x939A, 0x644F, 0x939B, 0x6450, 0x939C, 0x6451, 0x939D, 0x6452, 0xDEF0, + 0x6453, 0x939E, 0x6454, 0xCBA4, 0x6455, 0x939F, 0x6456, 0x93A0, 0x6457, 0x93A1, 0x6458, 0xD5AA, 0x6459, 0x93A2, 0x645A, 0x93A3, + 0x645B, 0x93A4, 0x645C, 0x93A5, 0x645D, 0x93A6, 0x645E, 0xDEFB, 0x645F, 0x93A7, 0x6460, 0x93A8, 0x6461, 0x93A9, 0x6462, 0x93AA, + 0x6463, 0x93AB, 0x6464, 0x93AC, 0x6465, 0x93AD, 0x6466, 0x93AE, 0x6467, 0xB4DD, 0x6468, 0x93AF, 0x6469, 0xC4A6, 0x646A, 0x93B0, + 0x646B, 0x93B1, 0x646C, 0x93B2, 0x646D, 0xDEFD, 0x646E, 0x93B3, 0x646F, 0x93B4, 0x6470, 0x93B5, 0x6471, 0x93B6, 0x6472, 0x93B7, + 0x6473, 0x93B8, 0x6474, 0x93B9, 0x6475, 0x93BA, 0x6476, 0x93BB, 0x6477, 0x93BC, 0x6478, 0xC3FE, 0x6479, 0xC4A1, 0x647A, 0xDFA1, + 0x647B, 0x93BD, 0x647C, 0x93BE, 0x647D, 0x93BF, 0x647E, 0x93C0, 0x647F, 0x93C1, 0x6480, 0x93C2, 0x6481, 0x93C3, 0x6482, 0xC1CC, + 0x6483, 0x93C4, 0x6484, 0xDEFC, 0x6485, 0xBEEF, 0x6486, 0x93C5, 0x6487, 0xC6B2, 0x6488, 0x93C6, 0x6489, 0x93C7, 0x648A, 0x93C8, + 0x648B, 0x93C9, 0x648C, 0x93CA, 0x648D, 0x93CB, 0x648E, 0x93CC, 0x648F, 0x93CD, 0x6490, 0x93CE, 0x6491, 0xB3C5, 0x6492, 0xC8F6, + 0x6493, 0x93CF, 0x6494, 0x93D0, 0x6495, 0xCBBA, 0x6496, 0xDEFE, 0x6497, 0x93D1, 0x6498, 0x93D2, 0x6499, 0xDFA4, 0x649A, 0x93D3, + 0x649B, 0x93D4, 0x649C, 0x93D5, 0x649D, 0x93D6, 0x649E, 0xD7B2, 0x649F, 0x93D7, 0x64A0, 0x93D8, 0x64A1, 0x93D9, 0x64A2, 0x93DA, + 0x64A3, 0x93DB, 0x64A4, 0xB3B7, 0x64A5, 0x93DC, 0x64A6, 0x93DD, 0x64A7, 0x93DE, 0x64A8, 0x93DF, 0x64A9, 0xC1C3, 0x64AA, 0x93E0, + 0x64AB, 0x93E1, 0x64AC, 0xC7CB, 0x64AD, 0xB2A5, 0x64AE, 0xB4E9, 0x64AF, 0x93E2, 0x64B0, 0xD7AB, 0x64B1, 0x93E3, 0x64B2, 0x93E4, + 0x64B3, 0x93E5, 0x64B4, 0x93E6, 0x64B5, 0xC4EC, 0x64B6, 0x93E7, 0x64B7, 0xDFA2, 0x64B8, 0xDFA3, 0x64B9, 0x93E8, 0x64BA, 0xDFA5, + 0x64BB, 0x93E9, 0x64BC, 0xBAB3, 0x64BD, 0x93EA, 0x64BE, 0x93EB, 0x64BF, 0x93EC, 0x64C0, 0xDFA6, 0x64C1, 0x93ED, 0x64C2, 0xC0DE, + 0x64C3, 0x93EE, 0x64C4, 0x93EF, 0x64C5, 0xC9C3, 0x64C6, 0x93F0, 0x64C7, 0x93F1, 0x64C8, 0x93F2, 0x64C9, 0x93F3, 0x64CA, 0x93F4, + 0x64CB, 0x93F5, 0x64CC, 0x93F6, 0x64CD, 0xB2D9, 0x64CE, 0xC7E6, 0x64CF, 0x93F7, 0x64D0, 0xDFA7, 0x64D1, 0x93F8, 0x64D2, 0xC7DC, + 0x64D3, 0x93F9, 0x64D4, 0x93FA, 0x64D5, 0x93FB, 0x64D6, 0x93FC, 0x64D7, 0xDFA8, 0x64D8, 0xEBA2, 0x64D9, 0x93FD, 0x64DA, 0x93FE, + 0x64DB, 0x9440, 0x64DC, 0x9441, 0x64DD, 0x9442, 0x64DE, 0xCBD3, 0x64DF, 0x9443, 0x64E0, 0x9444, 0x64E1, 0x9445, 0x64E2, 0xDFAA, + 0x64E3, 0x9446, 0x64E4, 0xDFA9, 0x64E5, 0x9447, 0x64E6, 0xB2C1, 0x64E7, 0x9448, 0x64E8, 0x9449, 0x64E9, 0x944A, 0x64EA, 0x944B, + 0x64EB, 0x944C, 0x64EC, 0x944D, 0x64ED, 0x944E, 0x64EE, 0x944F, 0x64EF, 0x9450, 0x64F0, 0x9451, 0x64F1, 0x9452, 0x64F2, 0x9453, + 0x64F3, 0x9454, 0x64F4, 0x9455, 0x64F5, 0x9456, 0x64F6, 0x9457, 0x64F7, 0x9458, 0x64F8, 0x9459, 0x64F9, 0x945A, 0x64FA, 0x945B, + 0x64FB, 0x945C, 0x64FC, 0x945D, 0x64FD, 0x945E, 0x64FE, 0x945F, 0x64FF, 0x9460, 0x6500, 0xC5CA, 0x6501, 0x9461, 0x6502, 0x9462, + 0x6503, 0x9463, 0x6504, 0x9464, 0x6505, 0x9465, 0x6506, 0x9466, 0x6507, 0x9467, 0x6508, 0x9468, 0x6509, 0xDFAB, 0x650A, 0x9469, + 0x650B, 0x946A, 0x650C, 0x946B, 0x650D, 0x946C, 0x650E, 0x946D, 0x650F, 0x946E, 0x6510, 0x946F, 0x6511, 0x9470, 0x6512, 0xD4DC, + 0x6513, 0x9471, 0x6514, 0x9472, 0x6515, 0x9473, 0x6516, 0x9474, 0x6517, 0x9475, 0x6518, 0xC8C1, 0x6519, 0x9476, 0x651A, 0x9477, + 0x651B, 0x9478, 0x651C, 0x9479, 0x651D, 0x947A, 0x651E, 0x947B, 0x651F, 0x947C, 0x6520, 0x947D, 0x6521, 0x947E, 0x6522, 0x9480, + 0x6523, 0x9481, 0x6524, 0x9482, 0x6525, 0xDFAC, 0x6526, 0x9483, 0x6527, 0x9484, 0x6528, 0x9485, 0x6529, 0x9486, 0x652A, 0x9487, + 0x652B, 0xBEF0, 0x652C, 0x9488, 0x652D, 0x9489, 0x652E, 0xDFAD, 0x652F, 0xD6A7, 0x6530, 0x948A, 0x6531, 0x948B, 0x6532, 0x948C, + 0x6533, 0x948D, 0x6534, 0xEAB7, 0x6535, 0xEBB6, 0x6536, 0xCAD5, 0x6537, 0x948E, 0x6538, 0xD8FC, 0x6539, 0xB8C4, 0x653A, 0x948F, + 0x653B, 0xB9A5, 0x653C, 0x9490, 0x653D, 0x9491, 0x653E, 0xB7C5, 0x653F, 0xD5FE, 0x6540, 0x9492, 0x6541, 0x9493, 0x6542, 0x9494, + 0x6543, 0x9495, 0x6544, 0x9496, 0x6545, 0xB9CA, 0x6546, 0x9497, 0x6547, 0x9498, 0x6548, 0xD0A7, 0x6549, 0xF4CD, 0x654A, 0x9499, + 0x654B, 0x949A, 0x654C, 0xB5D0, 0x654D, 0x949B, 0x654E, 0x949C, 0x654F, 0xC3F4, 0x6550, 0x949D, 0x6551, 0xBEC8, 0x6552, 0x949E, + 0x6553, 0x949F, 0x6554, 0x94A0, 0x6555, 0xEBB7, 0x6556, 0xB0BD, 0x6557, 0x94A1, 0x6558, 0x94A2, 0x6559, 0xBDCC, 0x655A, 0x94A3, + 0x655B, 0xC1B2, 0x655C, 0x94A4, 0x655D, 0xB1D6, 0x655E, 0xB3A8, 0x655F, 0x94A5, 0x6560, 0x94A6, 0x6561, 0x94A7, 0x6562, 0xB8D2, + 0x6563, 0xC9A2, 0x6564, 0x94A8, 0x6565, 0x94A9, 0x6566, 0xB6D8, 0x6567, 0x94AA, 0x6568, 0x94AB, 0x6569, 0x94AC, 0x656A, 0x94AD, + 0x656B, 0xEBB8, 0x656C, 0xBEB4, 0x656D, 0x94AE, 0x656E, 0x94AF, 0x656F, 0x94B0, 0x6570, 0xCAFD, 0x6571, 0x94B1, 0x6572, 0xC7C3, + 0x6573, 0x94B2, 0x6574, 0xD5FB, 0x6575, 0x94B3, 0x6576, 0x94B4, 0x6577, 0xB7F3, 0x6578, 0x94B5, 0x6579, 0x94B6, 0x657A, 0x94B7, + 0x657B, 0x94B8, 0x657C, 0x94B9, 0x657D, 0x94BA, 0x657E, 0x94BB, 0x657F, 0x94BC, 0x6580, 0x94BD, 0x6581, 0x94BE, 0x6582, 0x94BF, + 0x6583, 0x94C0, 0x6584, 0x94C1, 0x6585, 0x94C2, 0x6586, 0x94C3, 0x6587, 0xCEC4, 0x6588, 0x94C4, 0x6589, 0x94C5, 0x658A, 0x94C6, + 0x658B, 0xD5AB, 0x658C, 0xB1F3, 0x658D, 0x94C7, 0x658E, 0x94C8, 0x658F, 0x94C9, 0x6590, 0xECB3, 0x6591, 0xB0DF, 0x6592, 0x94CA, + 0x6593, 0xECB5, 0x6594, 0x94CB, 0x6595, 0x94CC, 0x6596, 0x94CD, 0x6597, 0xB6B7, 0x6598, 0x94CE, 0x6599, 0xC1CF, 0x659A, 0x94CF, + 0x659B, 0xF5FA, 0x659C, 0xD0B1, 0x659D, 0x94D0, 0x659E, 0x94D1, 0x659F, 0xD5E5, 0x65A0, 0x94D2, 0x65A1, 0xCED3, 0x65A2, 0x94D3, + 0x65A3, 0x94D4, 0x65A4, 0xBDEF, 0x65A5, 0xB3E2, 0x65A6, 0x94D5, 0x65A7, 0xB8AB, 0x65A8, 0x94D6, 0x65A9, 0xD5B6, 0x65AA, 0x94D7, + 0x65AB, 0xEDBD, 0x65AC, 0x94D8, 0x65AD, 0xB6CF, 0x65AE, 0x94D9, 0x65AF, 0xCBB9, 0x65B0, 0xD0C2, 0x65B1, 0x94DA, 0x65B2, 0x94DB, + 0x65B3, 0x94DC, 0x65B4, 0x94DD, 0x65B5, 0x94DE, 0x65B6, 0x94DF, 0x65B7, 0x94E0, 0x65B8, 0x94E1, 0x65B9, 0xB7BD, 0x65BA, 0x94E2, + 0x65BB, 0x94E3, 0x65BC, 0xECB6, 0x65BD, 0xCAA9, 0x65BE, 0x94E4, 0x65BF, 0x94E5, 0x65C0, 0x94E6, 0x65C1, 0xC5D4, 0x65C2, 0x94E7, + 0x65C3, 0xECB9, 0x65C4, 0xECB8, 0x65C5, 0xC2C3, 0x65C6, 0xECB7, 0x65C7, 0x94E8, 0x65C8, 0x94E9, 0x65C9, 0x94EA, 0x65CA, 0x94EB, + 0x65CB, 0xD0FD, 0x65CC, 0xECBA, 0x65CD, 0x94EC, 0x65CE, 0xECBB, 0x65CF, 0xD7E5, 0x65D0, 0x94ED, 0x65D1, 0x94EE, 0x65D2, 0xECBC, + 0x65D3, 0x94EF, 0x65D4, 0x94F0, 0x65D5, 0x94F1, 0x65D6, 0xECBD, 0x65D7, 0xC6EC, 0x65D8, 0x94F2, 0x65D9, 0x94F3, 0x65DA, 0x94F4, + 0x65DB, 0x94F5, 0x65DC, 0x94F6, 0x65DD, 0x94F7, 0x65DE, 0x94F8, 0x65DF, 0x94F9, 0x65E0, 0xCEDE, 0x65E1, 0x94FA, 0x65E2, 0xBCC8, + 0x65E3, 0x94FB, 0x65E4, 0x94FC, 0x65E5, 0xC8D5, 0x65E6, 0xB5A9, 0x65E7, 0xBEC9, 0x65E8, 0xD6BC, 0x65E9, 0xD4E7, 0x65EA, 0x94FD, + 0x65EB, 0x94FE, 0x65EC, 0xD1AE, 0x65ED, 0xD0F1, 0x65EE, 0xEAB8, 0x65EF, 0xEAB9, 0x65F0, 0xEABA, 0x65F1, 0xBAB5, 0x65F2, 0x9540, + 0x65F3, 0x9541, 0x65F4, 0x9542, 0x65F5, 0x9543, 0x65F6, 0xCAB1, 0x65F7, 0xBFF5, 0x65F8, 0x9544, 0x65F9, 0x9545, 0x65FA, 0xCDFA, + 0x65FB, 0x9546, 0x65FC, 0x9547, 0x65FD, 0x9548, 0x65FE, 0x9549, 0x65FF, 0x954A, 0x6600, 0xEAC0, 0x6601, 0x954B, 0x6602, 0xB0BA, + 0x6603, 0xEABE, 0x6604, 0x954C, 0x6605, 0x954D, 0x6606, 0xC0A5, 0x6607, 0x954E, 0x6608, 0x954F, 0x6609, 0x9550, 0x660A, 0xEABB, + 0x660B, 0x9551, 0x660C, 0xB2FD, 0x660D, 0x9552, 0x660E, 0xC3F7, 0x660F, 0xBBE8, 0x6610, 0x9553, 0x6611, 0x9554, 0x6612, 0x9555, + 0x6613, 0xD2D7, 0x6614, 0xCEF4, 0x6615, 0xEABF, 0x6616, 0x9556, 0x6617, 0x9557, 0x6618, 0x9558, 0x6619, 0xEABC, 0x661A, 0x9559, + 0x661B, 0x955A, 0x661C, 0x955B, 0x661D, 0xEAC3, 0x661E, 0x955C, 0x661F, 0xD0C7, 0x6620, 0xD3B3, 0x6621, 0x955D, 0x6622, 0x955E, + 0x6623, 0x955F, 0x6624, 0x9560, 0x6625, 0xB4BA, 0x6626, 0x9561, 0x6627, 0xC3C1, 0x6628, 0xD7F2, 0x6629, 0x9562, 0x662A, 0x9563, + 0x662B, 0x9564, 0x662C, 0x9565, 0x662D, 0xD5D1, 0x662E, 0x9566, 0x662F, 0xCAC7, 0x6630, 0x9567, 0x6631, 0xEAC5, 0x6632, 0x9568, + 0x6633, 0x9569, 0x6634, 0xEAC4, 0x6635, 0xEAC7, 0x6636, 0xEAC6, 0x6637, 0x956A, 0x6638, 0x956B, 0x6639, 0x956C, 0x663A, 0x956D, + 0x663B, 0x956E, 0x663C, 0xD6E7, 0x663D, 0x956F, 0x663E, 0xCFD4, 0x663F, 0x9570, 0x6640, 0x9571, 0x6641, 0xEACB, 0x6642, 0x9572, + 0x6643, 0xBBCE, 0x6644, 0x9573, 0x6645, 0x9574, 0x6646, 0x9575, 0x6647, 0x9576, 0x6648, 0x9577, 0x6649, 0x9578, 0x664A, 0x9579, + 0x664B, 0xBDFA, 0x664C, 0xC9CE, 0x664D, 0x957A, 0x664E, 0x957B, 0x664F, 0xEACC, 0x6650, 0x957C, 0x6651, 0x957D, 0x6652, 0xC9B9, + 0x6653, 0xCFFE, 0x6654, 0xEACA, 0x6655, 0xD4CE, 0x6656, 0xEACD, 0x6657, 0xEACF, 0x6658, 0x957E, 0x6659, 0x9580, 0x665A, 0xCDED, + 0x665B, 0x9581, 0x665C, 0x9582, 0x665D, 0x9583, 0x665E, 0x9584, 0x665F, 0xEAC9, 0x6660, 0x9585, 0x6661, 0xEACE, 0x6662, 0x9586, + 0x6663, 0x9587, 0x6664, 0xCEEE, 0x6665, 0x9588, 0x6666, 0xBBDE, 0x6667, 0x9589, 0x6668, 0xB3BF, 0x6669, 0x958A, 0x666A, 0x958B, + 0x666B, 0x958C, 0x666C, 0x958D, 0x666D, 0x958E, 0x666E, 0xC6D5, 0x666F, 0xBEB0, 0x6670, 0xCEFA, 0x6671, 0x958F, 0x6672, 0x9590, + 0x6673, 0x9591, 0x6674, 0xC7E7, 0x6675, 0x9592, 0x6676, 0xBEA7, 0x6677, 0xEAD0, 0x6678, 0x9593, 0x6679, 0x9594, 0x667A, 0xD6C7, + 0x667B, 0x9595, 0x667C, 0x9596, 0x667D, 0x9597, 0x667E, 0xC1C0, 0x667F, 0x9598, 0x6680, 0x9599, 0x6681, 0x959A, 0x6682, 0xD4DD, + 0x6683, 0x959B, 0x6684, 0xEAD1, 0x6685, 0x959C, 0x6686, 0x959D, 0x6687, 0xCFBE, 0x6688, 0x959E, 0x6689, 0x959F, 0x668A, 0x95A0, + 0x668B, 0x95A1, 0x668C, 0xEAD2, 0x668D, 0x95A2, 0x668E, 0x95A3, 0x668F, 0x95A4, 0x6690, 0x95A5, 0x6691, 0xCAEE, 0x6692, 0x95A6, + 0x6693, 0x95A7, 0x6694, 0x95A8, 0x6695, 0x95A9, 0x6696, 0xC5AF, 0x6697, 0xB0B5, 0x6698, 0x95AA, 0x6699, 0x95AB, 0x669A, 0x95AC, + 0x669B, 0x95AD, 0x669C, 0x95AE, 0x669D, 0xEAD4, 0x669E, 0x95AF, 0x669F, 0x95B0, 0x66A0, 0x95B1, 0x66A1, 0x95B2, 0x66A2, 0x95B3, + 0x66A3, 0x95B4, 0x66A4, 0x95B5, 0x66A5, 0x95B6, 0x66A6, 0x95B7, 0x66A7, 0xEAD3, 0x66A8, 0xF4DF, 0x66A9, 0x95B8, 0x66AA, 0x95B9, + 0x66AB, 0x95BA, 0x66AC, 0x95BB, 0x66AD, 0x95BC, 0x66AE, 0xC4BA, 0x66AF, 0x95BD, 0x66B0, 0x95BE, 0x66B1, 0x95BF, 0x66B2, 0x95C0, + 0x66B3, 0x95C1, 0x66B4, 0xB1A9, 0x66B5, 0x95C2, 0x66B6, 0x95C3, 0x66B7, 0x95C4, 0x66B8, 0x95C5, 0x66B9, 0xE5DF, 0x66BA, 0x95C6, + 0x66BB, 0x95C7, 0x66BC, 0x95C8, 0x66BD, 0x95C9, 0x66BE, 0xEAD5, 0x66BF, 0x95CA, 0x66C0, 0x95CB, 0x66C1, 0x95CC, 0x66C2, 0x95CD, + 0x66C3, 0x95CE, 0x66C4, 0x95CF, 0x66C5, 0x95D0, 0x66C6, 0x95D1, 0x66C7, 0x95D2, 0x66C8, 0x95D3, 0x66C9, 0x95D4, 0x66CA, 0x95D5, + 0x66CB, 0x95D6, 0x66CC, 0x95D7, 0x66CD, 0x95D8, 0x66CE, 0x95D9, 0x66CF, 0x95DA, 0x66D0, 0x95DB, 0x66D1, 0x95DC, 0x66D2, 0x95DD, + 0x66D3, 0x95DE, 0x66D4, 0x95DF, 0x66D5, 0x95E0, 0x66D6, 0x95E1, 0x66D7, 0x95E2, 0x66D8, 0x95E3, 0x66D9, 0xCAEF, 0x66DA, 0x95E4, + 0x66DB, 0xEAD6, 0x66DC, 0xEAD7, 0x66DD, 0xC6D8, 0x66DE, 0x95E5, 0x66DF, 0x95E6, 0x66E0, 0x95E7, 0x66E1, 0x95E8, 0x66E2, 0x95E9, + 0x66E3, 0x95EA, 0x66E4, 0x95EB, 0x66E5, 0x95EC, 0x66E6, 0xEAD8, 0x66E7, 0x95ED, 0x66E8, 0x95EE, 0x66E9, 0xEAD9, 0x66EA, 0x95EF, + 0x66EB, 0x95F0, 0x66EC, 0x95F1, 0x66ED, 0x95F2, 0x66EE, 0x95F3, 0x66EF, 0x95F4, 0x66F0, 0xD4BB, 0x66F1, 0x95F5, 0x66F2, 0xC7FA, + 0x66F3, 0xD2B7, 0x66F4, 0xB8FC, 0x66F5, 0x95F6, 0x66F6, 0x95F7, 0x66F7, 0xEAC2, 0x66F8, 0x95F8, 0x66F9, 0xB2DC, 0x66FA, 0x95F9, + 0x66FB, 0x95FA, 0x66FC, 0xC2FC, 0x66FD, 0x95FB, 0x66FE, 0xD4F8, 0x66FF, 0xCCE6, 0x6700, 0xD7EE, 0x6701, 0x95FC, 0x6702, 0x95FD, + 0x6703, 0x95FE, 0x6704, 0x9640, 0x6705, 0x9641, 0x6706, 0x9642, 0x6707, 0x9643, 0x6708, 0xD4C2, 0x6709, 0xD3D0, 0x670A, 0xEBC3, + 0x670B, 0xC5F3, 0x670C, 0x9644, 0x670D, 0xB7FE, 0x670E, 0x9645, 0x670F, 0x9646, 0x6710, 0xEBD4, 0x6711, 0x9647, 0x6712, 0x9648, + 0x6713, 0x9649, 0x6714, 0xCBB7, 0x6715, 0xEBDE, 0x6716, 0x964A, 0x6717, 0xC0CA, 0x6718, 0x964B, 0x6719, 0x964C, 0x671A, 0x964D, + 0x671B, 0xCDFB, 0x671C, 0x964E, 0x671D, 0xB3AF, 0x671E, 0x964F, 0x671F, 0xC6DA, 0x6720, 0x9650, 0x6721, 0x9651, 0x6722, 0x9652, + 0x6723, 0x9653, 0x6724, 0x9654, 0x6725, 0x9655, 0x6726, 0xEBFC, 0x6727, 0x9656, 0x6728, 0xC4BE, 0x6729, 0x9657, 0x672A, 0xCEB4, + 0x672B, 0xC4A9, 0x672C, 0xB1BE, 0x672D, 0xD4FD, 0x672E, 0x9658, 0x672F, 0xCAF5, 0x6730, 0x9659, 0x6731, 0xD6EC, 0x6732, 0x965A, + 0x6733, 0x965B, 0x6734, 0xC6D3, 0x6735, 0xB6E4, 0x6736, 0x965C, 0x6737, 0x965D, 0x6738, 0x965E, 0x6739, 0x965F, 0x673A, 0xBBFA, + 0x673B, 0x9660, 0x673C, 0x9661, 0x673D, 0xD0E0, 0x673E, 0x9662, 0x673F, 0x9663, 0x6740, 0xC9B1, 0x6741, 0x9664, 0x6742, 0xD4D3, + 0x6743, 0xC8A8, 0x6744, 0x9665, 0x6745, 0x9666, 0x6746, 0xB8CB, 0x6747, 0x9667, 0x6748, 0xE8BE, 0x6749, 0xC9BC, 0x674A, 0x9668, + 0x674B, 0x9669, 0x674C, 0xE8BB, 0x674D, 0x966A, 0x674E, 0xC0EE, 0x674F, 0xD0D3, 0x6750, 0xB2C4, 0x6751, 0xB4E5, 0x6752, 0x966B, + 0x6753, 0xE8BC, 0x6754, 0x966C, 0x6755, 0x966D, 0x6756, 0xD5C8, 0x6757, 0x966E, 0x6758, 0x966F, 0x6759, 0x9670, 0x675A, 0x9671, + 0x675B, 0x9672, 0x675C, 0xB6C5, 0x675D, 0x9673, 0x675E, 0xE8BD, 0x675F, 0xCAF8, 0x6760, 0xB8DC, 0x6761, 0xCCF5, 0x6762, 0x9674, + 0x6763, 0x9675, 0x6764, 0x9676, 0x6765, 0xC0B4, 0x6766, 0x9677, 0x6767, 0x9678, 0x6768, 0xD1EE, 0x6769, 0xE8BF, 0x676A, 0xE8C2, + 0x676B, 0x9679, 0x676C, 0x967A, 0x676D, 0xBABC, 0x676E, 0x967B, 0x676F, 0xB1AD, 0x6770, 0xBDDC, 0x6771, 0x967C, 0x6772, 0xEABD, + 0x6773, 0xE8C3, 0x6774, 0x967D, 0x6775, 0xE8C6, 0x6776, 0x967E, 0x6777, 0xE8CB, 0x6778, 0x9680, 0x6779, 0x9681, 0x677A, 0x9682, + 0x677B, 0x9683, 0x677C, 0xE8CC, 0x677D, 0x9684, 0x677E, 0xCBC9, 0x677F, 0xB0E5, 0x6780, 0x9685, 0x6781, 0xBCAB, 0x6782, 0x9686, + 0x6783, 0x9687, 0x6784, 0xB9B9, 0x6785, 0x9688, 0x6786, 0x9689, 0x6787, 0xE8C1, 0x6788, 0x968A, 0x6789, 0xCDF7, 0x678A, 0x968B, + 0x678B, 0xE8CA, 0x678C, 0x968C, 0x678D, 0x968D, 0x678E, 0x968E, 0x678F, 0x968F, 0x6790, 0xCEF6, 0x6791, 0x9690, 0x6792, 0x9691, + 0x6793, 0x9692, 0x6794, 0x9693, 0x6795, 0xD5ED, 0x6796, 0x9694, 0x6797, 0xC1D6, 0x6798, 0xE8C4, 0x6799, 0x9695, 0x679A, 0xC3B6, + 0x679B, 0x9696, 0x679C, 0xB9FB, 0x679D, 0xD6A6, 0x679E, 0xE8C8, 0x679F, 0x9697, 0x67A0, 0x9698, 0x67A1, 0x9699, 0x67A2, 0xCAE0, + 0x67A3, 0xD4E6, 0x67A4, 0x969A, 0x67A5, 0xE8C0, 0x67A6, 0x969B, 0x67A7, 0xE8C5, 0x67A8, 0xE8C7, 0x67A9, 0x969C, 0x67AA, 0xC7B9, + 0x67AB, 0xB7E3, 0x67AC, 0x969D, 0x67AD, 0xE8C9, 0x67AE, 0x969E, 0x67AF, 0xBFDD, 0x67B0, 0xE8D2, 0x67B1, 0x969F, 0x67B2, 0x96A0, + 0x67B3, 0xE8D7, 0x67B4, 0x96A1, 0x67B5, 0xE8D5, 0x67B6, 0xBCDC, 0x67B7, 0xBCCF, 0x67B8, 0xE8DB, 0x67B9, 0x96A2, 0x67BA, 0x96A3, + 0x67BB, 0x96A4, 0x67BC, 0x96A5, 0x67BD, 0x96A6, 0x67BE, 0x96A7, 0x67BF, 0x96A8, 0x67C0, 0x96A9, 0x67C1, 0xE8DE, 0x67C2, 0x96AA, + 0x67C3, 0xE8DA, 0x67C4, 0xB1FA, 0x67C5, 0x96AB, 0x67C6, 0x96AC, 0x67C7, 0x96AD, 0x67C8, 0x96AE, 0x67C9, 0x96AF, 0x67CA, 0x96B0, + 0x67CB, 0x96B1, 0x67CC, 0x96B2, 0x67CD, 0x96B3, 0x67CE, 0x96B4, 0x67CF, 0xB0D8, 0x67D0, 0xC4B3, 0x67D1, 0xB8CC, 0x67D2, 0xC6E2, + 0x67D3, 0xC8BE, 0x67D4, 0xC8E1, 0x67D5, 0x96B5, 0x67D6, 0x96B6, 0x67D7, 0x96B7, 0x67D8, 0xE8CF, 0x67D9, 0xE8D4, 0x67DA, 0xE8D6, + 0x67DB, 0x96B8, 0x67DC, 0xB9F1, 0x67DD, 0xE8D8, 0x67DE, 0xD7F5, 0x67DF, 0x96B9, 0x67E0, 0xC4FB, 0x67E1, 0x96BA, 0x67E2, 0xE8DC, + 0x67E3, 0x96BB, 0x67E4, 0x96BC, 0x67E5, 0xB2E9, 0x67E6, 0x96BD, 0x67E7, 0x96BE, 0x67E8, 0x96BF, 0x67E9, 0xE8D1, 0x67EA, 0x96C0, + 0x67EB, 0x96C1, 0x67EC, 0xBCED, 0x67ED, 0x96C2, 0x67EE, 0x96C3, 0x67EF, 0xBFC2, 0x67F0, 0xE8CD, 0x67F1, 0xD6F9, 0x67F2, 0x96C4, + 0x67F3, 0xC1F8, 0x67F4, 0xB2F1, 0x67F5, 0x96C5, 0x67F6, 0x96C6, 0x67F7, 0x96C7, 0x67F8, 0x96C8, 0x67F9, 0x96C9, 0x67FA, 0x96CA, + 0x67FB, 0x96CB, 0x67FC, 0x96CC, 0x67FD, 0xE8DF, 0x67FE, 0x96CD, 0x67FF, 0xCAC1, 0x6800, 0xE8D9, 0x6801, 0x96CE, 0x6802, 0x96CF, + 0x6803, 0x96D0, 0x6804, 0x96D1, 0x6805, 0xD5A4, 0x6806, 0x96D2, 0x6807, 0xB1EA, 0x6808, 0xD5BB, 0x6809, 0xE8CE, 0x680A, 0xE8D0, + 0x680B, 0xB6B0, 0x680C, 0xE8D3, 0x680D, 0x96D3, 0x680E, 0xE8DD, 0x680F, 0xC0B8, 0x6810, 0x96D4, 0x6811, 0xCAF7, 0x6812, 0x96D5, + 0x6813, 0xCBA8, 0x6814, 0x96D6, 0x6815, 0x96D7, 0x6816, 0xC6DC, 0x6817, 0xC0F5, 0x6818, 0x96D8, 0x6819, 0x96D9, 0x681A, 0x96DA, + 0x681B, 0x96DB, 0x681C, 0x96DC, 0x681D, 0xE8E9, 0x681E, 0x96DD, 0x681F, 0x96DE, 0x6820, 0x96DF, 0x6821, 0xD0A3, 0x6822, 0x96E0, + 0x6823, 0x96E1, 0x6824, 0x96E2, 0x6825, 0x96E3, 0x6826, 0x96E4, 0x6827, 0x96E5, 0x6828, 0x96E6, 0x6829, 0xE8F2, 0x682A, 0xD6EA, + 0x682B, 0x96E7, 0x682C, 0x96E8, 0x682D, 0x96E9, 0x682E, 0x96EA, 0x682F, 0x96EB, 0x6830, 0x96EC, 0x6831, 0x96ED, 0x6832, 0xE8E0, + 0x6833, 0xE8E1, 0x6834, 0x96EE, 0x6835, 0x96EF, 0x6836, 0x96F0, 0x6837, 0xD1F9, 0x6838, 0xBACB, 0x6839, 0xB8F9, 0x683A, 0x96F1, + 0x683B, 0x96F2, 0x683C, 0xB8F1, 0x683D, 0xD4D4, 0x683E, 0xE8EF, 0x683F, 0x96F3, 0x6840, 0xE8EE, 0x6841, 0xE8EC, 0x6842, 0xB9F0, + 0x6843, 0xCCD2, 0x6844, 0xE8E6, 0x6845, 0xCEA6, 0x6846, 0xBFF2, 0x6847, 0x96F4, 0x6848, 0xB0B8, 0x6849, 0xE8F1, 0x684A, 0xE8F0, + 0x684B, 0x96F5, 0x684C, 0xD7C0, 0x684D, 0x96F6, 0x684E, 0xE8E4, 0x684F, 0x96F7, 0x6850, 0xCDA9, 0x6851, 0xC9A3, 0x6852, 0x96F8, + 0x6853, 0xBBB8, 0x6854, 0xBDDB, 0x6855, 0xE8EA, 0x6856, 0x96F9, 0x6857, 0x96FA, 0x6858, 0x96FB, 0x6859, 0x96FC, 0x685A, 0x96FD, + 0x685B, 0x96FE, 0x685C, 0x9740, 0x685D, 0x9741, 0x685E, 0x9742, 0x685F, 0x9743, 0x6860, 0xE8E2, 0x6861, 0xE8E3, 0x6862, 0xE8E5, + 0x6863, 0xB5B5, 0x6864, 0xE8E7, 0x6865, 0xC7C5, 0x6866, 0xE8EB, 0x6867, 0xE8ED, 0x6868, 0xBDB0, 0x6869, 0xD7AE, 0x686A, 0x9744, + 0x686B, 0xE8F8, 0x686C, 0x9745, 0x686D, 0x9746, 0x686E, 0x9747, 0x686F, 0x9748, 0x6870, 0x9749, 0x6871, 0x974A, 0x6872, 0x974B, + 0x6873, 0x974C, 0x6874, 0xE8F5, 0x6875, 0x974D, 0x6876, 0xCDB0, 0x6877, 0xE8F6, 0x6878, 0x974E, 0x6879, 0x974F, 0x687A, 0x9750, + 0x687B, 0x9751, 0x687C, 0x9752, 0x687D, 0x9753, 0x687E, 0x9754, 0x687F, 0x9755, 0x6880, 0x9756, 0x6881, 0xC1BA, 0x6882, 0x9757, + 0x6883, 0xE8E8, 0x6884, 0x9758, 0x6885, 0xC3B7, 0x6886, 0xB0F0, 0x6887, 0x9759, 0x6888, 0x975A, 0x6889, 0x975B, 0x688A, 0x975C, + 0x688B, 0x975D, 0x688C, 0x975E, 0x688D, 0x975F, 0x688E, 0x9760, 0x688F, 0xE8F4, 0x6890, 0x9761, 0x6891, 0x9762, 0x6892, 0x9763, + 0x6893, 0xE8F7, 0x6894, 0x9764, 0x6895, 0x9765, 0x6896, 0x9766, 0x6897, 0xB9A3, 0x6898, 0x9767, 0x6899, 0x9768, 0x689A, 0x9769, + 0x689B, 0x976A, 0x689C, 0x976B, 0x689D, 0x976C, 0x689E, 0x976D, 0x689F, 0x976E, 0x68A0, 0x976F, 0x68A1, 0x9770, 0x68A2, 0xC9D2, + 0x68A3, 0x9771, 0x68A4, 0x9772, 0x68A5, 0x9773, 0x68A6, 0xC3CE, 0x68A7, 0xCEE0, 0x68A8, 0xC0E6, 0x68A9, 0x9774, 0x68AA, 0x9775, + 0x68AB, 0x9776, 0x68AC, 0x9777, 0x68AD, 0xCBF3, 0x68AE, 0x9778, 0x68AF, 0xCCDD, 0x68B0, 0xD0B5, 0x68B1, 0x9779, 0x68B2, 0x977A, + 0x68B3, 0xCAE1, 0x68B4, 0x977B, 0x68B5, 0xE8F3, 0x68B6, 0x977C, 0x68B7, 0x977D, 0x68B8, 0x977E, 0x68B9, 0x9780, 0x68BA, 0x9781, + 0x68BB, 0x9782, 0x68BC, 0x9783, 0x68BD, 0x9784, 0x68BE, 0x9785, 0x68BF, 0x9786, 0x68C0, 0xBCEC, 0x68C1, 0x9787, 0x68C2, 0xE8F9, + 0x68C3, 0x9788, 0x68C4, 0x9789, 0x68C5, 0x978A, 0x68C6, 0x978B, 0x68C7, 0x978C, 0x68C8, 0x978D, 0x68C9, 0xC3DE, 0x68CA, 0x978E, + 0x68CB, 0xC6E5, 0x68CC, 0x978F, 0x68CD, 0xB9F7, 0x68CE, 0x9790, 0x68CF, 0x9791, 0x68D0, 0x9792, 0x68D1, 0x9793, 0x68D2, 0xB0F4, + 0x68D3, 0x9794, 0x68D4, 0x9795, 0x68D5, 0xD7D8, 0x68D6, 0x9796, 0x68D7, 0x9797, 0x68D8, 0xBCAC, 0x68D9, 0x9798, 0x68DA, 0xC5EF, + 0x68DB, 0x9799, 0x68DC, 0x979A, 0x68DD, 0x979B, 0x68DE, 0x979C, 0x68DF, 0x979D, 0x68E0, 0xCCC4, 0x68E1, 0x979E, 0x68E2, 0x979F, + 0x68E3, 0xE9A6, 0x68E4, 0x97A0, 0x68E5, 0x97A1, 0x68E6, 0x97A2, 0x68E7, 0x97A3, 0x68E8, 0x97A4, 0x68E9, 0x97A5, 0x68EA, 0x97A6, + 0x68EB, 0x97A7, 0x68EC, 0x97A8, 0x68ED, 0x97A9, 0x68EE, 0xC9AD, 0x68EF, 0x97AA, 0x68F0, 0xE9A2, 0x68F1, 0xC0E2, 0x68F2, 0x97AB, + 0x68F3, 0x97AC, 0x68F4, 0x97AD, 0x68F5, 0xBFC3, 0x68F6, 0x97AE, 0x68F7, 0x97AF, 0x68F8, 0x97B0, 0x68F9, 0xE8FE, 0x68FA, 0xB9D7, + 0x68FB, 0x97B1, 0x68FC, 0xE8FB, 0x68FD, 0x97B2, 0x68FE, 0x97B3, 0x68FF, 0x97B4, 0x6900, 0x97B5, 0x6901, 0xE9A4, 0x6902, 0x97B6, + 0x6903, 0x97B7, 0x6904, 0x97B8, 0x6905, 0xD2CE, 0x6906, 0x97B9, 0x6907, 0x97BA, 0x6908, 0x97BB, 0x6909, 0x97BC, 0x690A, 0x97BD, + 0x690B, 0xE9A3, 0x690C, 0x97BE, 0x690D, 0xD6B2, 0x690E, 0xD7B5, 0x690F, 0x97BF, 0x6910, 0xE9A7, 0x6911, 0x97C0, 0x6912, 0xBDB7, + 0x6913, 0x97C1, 0x6914, 0x97C2, 0x6915, 0x97C3, 0x6916, 0x97C4, 0x6917, 0x97C5, 0x6918, 0x97C6, 0x6919, 0x97C7, 0x691A, 0x97C8, + 0x691B, 0x97C9, 0x691C, 0x97CA, 0x691D, 0x97CB, 0x691E, 0x97CC, 0x691F, 0xE8FC, 0x6920, 0xE8FD, 0x6921, 0x97CD, 0x6922, 0x97CE, + 0x6923, 0x97CF, 0x6924, 0xE9A1, 0x6925, 0x97D0, 0x6926, 0x97D1, 0x6927, 0x97D2, 0x6928, 0x97D3, 0x6929, 0x97D4, 0x692A, 0x97D5, + 0x692B, 0x97D6, 0x692C, 0x97D7, 0x692D, 0xCDD6, 0x692E, 0x97D8, 0x692F, 0x97D9, 0x6930, 0xD2AC, 0x6931, 0x97DA, 0x6932, 0x97DB, + 0x6933, 0x97DC, 0x6934, 0xE9B2, 0x6935, 0x97DD, 0x6936, 0x97DE, 0x6937, 0x97DF, 0x6938, 0x97E0, 0x6939, 0xE9A9, 0x693A, 0x97E1, + 0x693B, 0x97E2, 0x693C, 0x97E3, 0x693D, 0xB4AA, 0x693E, 0x97E4, 0x693F, 0xB4BB, 0x6940, 0x97E5, 0x6941, 0x97E6, 0x6942, 0xE9AB, + 0x6943, 0x97E7, 0x6944, 0x97E8, 0x6945, 0x97E9, 0x6946, 0x97EA, 0x6947, 0x97EB, 0x6948, 0x97EC, 0x6949, 0x97ED, 0x694A, 0x97EE, + 0x694B, 0x97EF, 0x694C, 0x97F0, 0x694D, 0x97F1, 0x694E, 0x97F2, 0x694F, 0x97F3, 0x6950, 0x97F4, 0x6951, 0x97F5, 0x6952, 0x97F6, + 0x6953, 0x97F7, 0x6954, 0xD0A8, 0x6955, 0x97F8, 0x6956, 0x97F9, 0x6957, 0xE9A5, 0x6958, 0x97FA, 0x6959, 0x97FB, 0x695A, 0xB3FE, + 0x695B, 0x97FC, 0x695C, 0x97FD, 0x695D, 0xE9AC, 0x695E, 0xC0E3, 0x695F, 0x97FE, 0x6960, 0xE9AA, 0x6961, 0x9840, 0x6962, 0x9841, + 0x6963, 0xE9B9, 0x6964, 0x9842, 0x6965, 0x9843, 0x6966, 0xE9B8, 0x6967, 0x9844, 0x6968, 0x9845, 0x6969, 0x9846, 0x696A, 0x9847, + 0x696B, 0xE9AE, 0x696C, 0x9848, 0x696D, 0x9849, 0x696E, 0xE8FA, 0x696F, 0x984A, 0x6970, 0x984B, 0x6971, 0xE9A8, 0x6972, 0x984C, + 0x6973, 0x984D, 0x6974, 0x984E, 0x6975, 0x984F, 0x6976, 0x9850, 0x6977, 0xBFAC, 0x6978, 0xE9B1, 0x6979, 0xE9BA, 0x697A, 0x9851, + 0x697B, 0x9852, 0x697C, 0xC2A5, 0x697D, 0x9853, 0x697E, 0x9854, 0x697F, 0x9855, 0x6980, 0xE9AF, 0x6981, 0x9856, 0x6982, 0xB8C5, + 0x6983, 0x9857, 0x6984, 0xE9AD, 0x6985, 0x9858, 0x6986, 0xD3DC, 0x6987, 0xE9B4, 0x6988, 0xE9B5, 0x6989, 0xE9B7, 0x698A, 0x9859, + 0x698B, 0x985A, 0x698C, 0x985B, 0x698D, 0xE9C7, 0x698E, 0x985C, 0x698F, 0x985D, 0x6990, 0x985E, 0x6991, 0x985F, 0x6992, 0x9860, + 0x6993, 0x9861, 0x6994, 0xC0C6, 0x6995, 0xE9C5, 0x6996, 0x9862, 0x6997, 0x9863, 0x6998, 0xE9B0, 0x6999, 0x9864, 0x699A, 0x9865, + 0x699B, 0xE9BB, 0x699C, 0xB0F1, 0x699D, 0x9866, 0x699E, 0x9867, 0x699F, 0x9868, 0x69A0, 0x9869, 0x69A1, 0x986A, 0x69A2, 0x986B, + 0x69A3, 0x986C, 0x69A4, 0x986D, 0x69A5, 0x986E, 0x69A6, 0x986F, 0x69A7, 0xE9BC, 0x69A8, 0xD5A5, 0x69A9, 0x9870, 0x69AA, 0x9871, + 0x69AB, 0xE9BE, 0x69AC, 0x9872, 0x69AD, 0xE9BF, 0x69AE, 0x9873, 0x69AF, 0x9874, 0x69B0, 0x9875, 0x69B1, 0xE9C1, 0x69B2, 0x9876, + 0x69B3, 0x9877, 0x69B4, 0xC1F1, 0x69B5, 0x9878, 0x69B6, 0x9879, 0x69B7, 0xC8B6, 0x69B8, 0x987A, 0x69B9, 0x987B, 0x69BA, 0x987C, + 0x69BB, 0xE9BD, 0x69BC, 0x987D, 0x69BD, 0x987E, 0x69BE, 0x9880, 0x69BF, 0x9881, 0x69C0, 0x9882, 0x69C1, 0xE9C2, 0x69C2, 0x9883, + 0x69C3, 0x9884, 0x69C4, 0x9885, 0x69C5, 0x9886, 0x69C6, 0x9887, 0x69C7, 0x9888, 0x69C8, 0x9889, 0x69C9, 0x988A, 0x69CA, 0xE9C3, + 0x69CB, 0x988B, 0x69CC, 0xE9B3, 0x69CD, 0x988C, 0x69CE, 0xE9B6, 0x69CF, 0x988D, 0x69D0, 0xBBB1, 0x69D1, 0x988E, 0x69D2, 0x988F, + 0x69D3, 0x9890, 0x69D4, 0xE9C0, 0x69D5, 0x9891, 0x69D6, 0x9892, 0x69D7, 0x9893, 0x69D8, 0x9894, 0x69D9, 0x9895, 0x69DA, 0x9896, + 0x69DB, 0xBCF7, 0x69DC, 0x9897, 0x69DD, 0x9898, 0x69DE, 0x9899, 0x69DF, 0xE9C4, 0x69E0, 0xE9C6, 0x69E1, 0x989A, 0x69E2, 0x989B, + 0x69E3, 0x989C, 0x69E4, 0x989D, 0x69E5, 0x989E, 0x69E6, 0x989F, 0x69E7, 0x98A0, 0x69E8, 0x98A1, 0x69E9, 0x98A2, 0x69EA, 0x98A3, + 0x69EB, 0x98A4, 0x69EC, 0x98A5, 0x69ED, 0xE9CA, 0x69EE, 0x98A6, 0x69EF, 0x98A7, 0x69F0, 0x98A8, 0x69F1, 0x98A9, 0x69F2, 0xE9CE, + 0x69F3, 0x98AA, 0x69F4, 0x98AB, 0x69F5, 0x98AC, 0x69F6, 0x98AD, 0x69F7, 0x98AE, 0x69F8, 0x98AF, 0x69F9, 0x98B0, 0x69FA, 0x98B1, + 0x69FB, 0x98B2, 0x69FC, 0x98B3, 0x69FD, 0xB2DB, 0x69FE, 0x98B4, 0x69FF, 0xE9C8, 0x6A00, 0x98B5, 0x6A01, 0x98B6, 0x6A02, 0x98B7, + 0x6A03, 0x98B8, 0x6A04, 0x98B9, 0x6A05, 0x98BA, 0x6A06, 0x98BB, 0x6A07, 0x98BC, 0x6A08, 0x98BD, 0x6A09, 0x98BE, 0x6A0A, 0xB7AE, + 0x6A0B, 0x98BF, 0x6A0C, 0x98C0, 0x6A0D, 0x98C1, 0x6A0E, 0x98C2, 0x6A0F, 0x98C3, 0x6A10, 0x98C4, 0x6A11, 0x98C5, 0x6A12, 0x98C6, + 0x6A13, 0x98C7, 0x6A14, 0x98C8, 0x6A15, 0x98C9, 0x6A16, 0x98CA, 0x6A17, 0xE9CB, 0x6A18, 0xE9CC, 0x6A19, 0x98CB, 0x6A1A, 0x98CC, + 0x6A1B, 0x98CD, 0x6A1C, 0x98CE, 0x6A1D, 0x98CF, 0x6A1E, 0x98D0, 0x6A1F, 0xD5C1, 0x6A20, 0x98D1, 0x6A21, 0xC4A3, 0x6A22, 0x98D2, + 0x6A23, 0x98D3, 0x6A24, 0x98D4, 0x6A25, 0x98D5, 0x6A26, 0x98D6, 0x6A27, 0x98D7, 0x6A28, 0xE9D8, 0x6A29, 0x98D8, 0x6A2A, 0xBAE1, + 0x6A2B, 0x98D9, 0x6A2C, 0x98DA, 0x6A2D, 0x98DB, 0x6A2E, 0x98DC, 0x6A2F, 0xE9C9, 0x6A30, 0x98DD, 0x6A31, 0xD3A3, 0x6A32, 0x98DE, + 0x6A33, 0x98DF, 0x6A34, 0x98E0, 0x6A35, 0xE9D4, 0x6A36, 0x98E1, 0x6A37, 0x98E2, 0x6A38, 0x98E3, 0x6A39, 0x98E4, 0x6A3A, 0x98E5, + 0x6A3B, 0x98E6, 0x6A3C, 0x98E7, 0x6A3D, 0xE9D7, 0x6A3E, 0xE9D0, 0x6A3F, 0x98E8, 0x6A40, 0x98E9, 0x6A41, 0x98EA, 0x6A42, 0x98EB, + 0x6A43, 0x98EC, 0x6A44, 0xE9CF, 0x6A45, 0x98ED, 0x6A46, 0x98EE, 0x6A47, 0xC7C1, 0x6A48, 0x98EF, 0x6A49, 0x98F0, 0x6A4A, 0x98F1, + 0x6A4B, 0x98F2, 0x6A4C, 0x98F3, 0x6A4D, 0x98F4, 0x6A4E, 0x98F5, 0x6A4F, 0x98F6, 0x6A50, 0xE9D2, 0x6A51, 0x98F7, 0x6A52, 0x98F8, + 0x6A53, 0x98F9, 0x6A54, 0x98FA, 0x6A55, 0x98FB, 0x6A56, 0x98FC, 0x6A57, 0x98FD, 0x6A58, 0xE9D9, 0x6A59, 0xB3C8, 0x6A5A, 0x98FE, + 0x6A5B, 0xE9D3, 0x6A5C, 0x9940, 0x6A5D, 0x9941, 0x6A5E, 0x9942, 0x6A5F, 0x9943, 0x6A60, 0x9944, 0x6A61, 0xCFF0, 0x6A62, 0x9945, + 0x6A63, 0x9946, 0x6A64, 0x9947, 0x6A65, 0xE9CD, 0x6A66, 0x9948, 0x6A67, 0x9949, 0x6A68, 0x994A, 0x6A69, 0x994B, 0x6A6A, 0x994C, + 0x6A6B, 0x994D, 0x6A6C, 0x994E, 0x6A6D, 0x994F, 0x6A6E, 0x9950, 0x6A6F, 0x9951, 0x6A70, 0x9952, 0x6A71, 0xB3F7, 0x6A72, 0x9953, + 0x6A73, 0x9954, 0x6A74, 0x9955, 0x6A75, 0x9956, 0x6A76, 0x9957, 0x6A77, 0x9958, 0x6A78, 0x9959, 0x6A79, 0xE9D6, 0x6A7A, 0x995A, + 0x6A7B, 0x995B, 0x6A7C, 0xE9DA, 0x6A7D, 0x995C, 0x6A7E, 0x995D, 0x6A7F, 0x995E, 0x6A80, 0xCCB4, 0x6A81, 0x995F, 0x6A82, 0x9960, + 0x6A83, 0x9961, 0x6A84, 0xCFAD, 0x6A85, 0x9962, 0x6A86, 0x9963, 0x6A87, 0x9964, 0x6A88, 0x9965, 0x6A89, 0x9966, 0x6A8A, 0x9967, + 0x6A8B, 0x9968, 0x6A8C, 0x9969, 0x6A8D, 0x996A, 0x6A8E, 0xE9D5, 0x6A8F, 0x996B, 0x6A90, 0xE9DC, 0x6A91, 0xE9DB, 0x6A92, 0x996C, + 0x6A93, 0x996D, 0x6A94, 0x996E, 0x6A95, 0x996F, 0x6A96, 0x9970, 0x6A97, 0xE9DE, 0x6A98, 0x9971, 0x6A99, 0x9972, 0x6A9A, 0x9973, + 0x6A9B, 0x9974, 0x6A9C, 0x9975, 0x6A9D, 0x9976, 0x6A9E, 0x9977, 0x6A9F, 0x9978, 0x6AA0, 0xE9D1, 0x6AA1, 0x9979, 0x6AA2, 0x997A, + 0x6AA3, 0x997B, 0x6AA4, 0x997C, 0x6AA5, 0x997D, 0x6AA6, 0x997E, 0x6AA7, 0x9980, 0x6AA8, 0x9981, 0x6AA9, 0xE9DD, 0x6AAA, 0x9982, + 0x6AAB, 0xE9DF, 0x6AAC, 0xC3CA, 0x6AAD, 0x9983, 0x6AAE, 0x9984, 0x6AAF, 0x9985, 0x6AB0, 0x9986, 0x6AB1, 0x9987, 0x6AB2, 0x9988, + 0x6AB3, 0x9989, 0x6AB4, 0x998A, 0x6AB5, 0x998B, 0x6AB6, 0x998C, 0x6AB7, 0x998D, 0x6AB8, 0x998E, 0x6AB9, 0x998F, 0x6ABA, 0x9990, + 0x6ABB, 0x9991, 0x6ABC, 0x9992, 0x6ABD, 0x9993, 0x6ABE, 0x9994, 0x6ABF, 0x9995, 0x6AC0, 0x9996, 0x6AC1, 0x9997, 0x6AC2, 0x9998, + 0x6AC3, 0x9999, 0x6AC4, 0x999A, 0x6AC5, 0x999B, 0x6AC6, 0x999C, 0x6AC7, 0x999D, 0x6AC8, 0x999E, 0x6AC9, 0x999F, 0x6ACA, 0x99A0, + 0x6ACB, 0x99A1, 0x6ACC, 0x99A2, 0x6ACD, 0x99A3, 0x6ACE, 0x99A4, 0x6ACF, 0x99A5, 0x6AD0, 0x99A6, 0x6AD1, 0x99A7, 0x6AD2, 0x99A8, + 0x6AD3, 0x99A9, 0x6AD4, 0x99AA, 0x6AD5, 0x99AB, 0x6AD6, 0x99AC, 0x6AD7, 0x99AD, 0x6AD8, 0x99AE, 0x6AD9, 0x99AF, 0x6ADA, 0x99B0, + 0x6ADB, 0x99B1, 0x6ADC, 0x99B2, 0x6ADD, 0x99B3, 0x6ADE, 0x99B4, 0x6ADF, 0x99B5, 0x6AE0, 0x99B6, 0x6AE1, 0x99B7, 0x6AE2, 0x99B8, + 0x6AE3, 0x99B9, 0x6AE4, 0x99BA, 0x6AE5, 0x99BB, 0x6AE6, 0x99BC, 0x6AE7, 0x99BD, 0x6AE8, 0x99BE, 0x6AE9, 0x99BF, 0x6AEA, 0x99C0, + 0x6AEB, 0x99C1, 0x6AEC, 0x99C2, 0x6AED, 0x99C3, 0x6AEE, 0x99C4, 0x6AEF, 0x99C5, 0x6AF0, 0x99C6, 0x6AF1, 0x99C7, 0x6AF2, 0x99C8, + 0x6AF3, 0x99C9, 0x6AF4, 0x99CA, 0x6AF5, 0x99CB, 0x6AF6, 0x99CC, 0x6AF7, 0x99CD, 0x6AF8, 0x99CE, 0x6AF9, 0x99CF, 0x6AFA, 0x99D0, + 0x6AFB, 0x99D1, 0x6AFC, 0x99D2, 0x6AFD, 0x99D3, 0x6AFE, 0x99D4, 0x6AFF, 0x99D5, 0x6B00, 0x99D6, 0x6B01, 0x99D7, 0x6B02, 0x99D8, + 0x6B03, 0x99D9, 0x6B04, 0x99DA, 0x6B05, 0x99DB, 0x6B06, 0x99DC, 0x6B07, 0x99DD, 0x6B08, 0x99DE, 0x6B09, 0x99DF, 0x6B0A, 0x99E0, + 0x6B0B, 0x99E1, 0x6B0C, 0x99E2, 0x6B0D, 0x99E3, 0x6B0E, 0x99E4, 0x6B0F, 0x99E5, 0x6B10, 0x99E6, 0x6B11, 0x99E7, 0x6B12, 0x99E8, + 0x6B13, 0x99E9, 0x6B14, 0x99EA, 0x6B15, 0x99EB, 0x6B16, 0x99EC, 0x6B17, 0x99ED, 0x6B18, 0x99EE, 0x6B19, 0x99EF, 0x6B1A, 0x99F0, + 0x6B1B, 0x99F1, 0x6B1C, 0x99F2, 0x6B1D, 0x99F3, 0x6B1E, 0x99F4, 0x6B1F, 0x99F5, 0x6B20, 0xC7B7, 0x6B21, 0xB4CE, 0x6B22, 0xBBB6, + 0x6B23, 0xD0C0, 0x6B24, 0xECA3, 0x6B25, 0x99F6, 0x6B26, 0x99F7, 0x6B27, 0xC5B7, 0x6B28, 0x99F8, 0x6B29, 0x99F9, 0x6B2A, 0x99FA, + 0x6B2B, 0x99FB, 0x6B2C, 0x99FC, 0x6B2D, 0x99FD, 0x6B2E, 0x99FE, 0x6B2F, 0x9A40, 0x6B30, 0x9A41, 0x6B31, 0x9A42, 0x6B32, 0xD3FB, + 0x6B33, 0x9A43, 0x6B34, 0x9A44, 0x6B35, 0x9A45, 0x6B36, 0x9A46, 0x6B37, 0xECA4, 0x6B38, 0x9A47, 0x6B39, 0xECA5, 0x6B3A, 0xC6DB, + 0x6B3B, 0x9A48, 0x6B3C, 0x9A49, 0x6B3D, 0x9A4A, 0x6B3E, 0xBFEE, 0x6B3F, 0x9A4B, 0x6B40, 0x9A4C, 0x6B41, 0x9A4D, 0x6B42, 0x9A4E, + 0x6B43, 0xECA6, 0x6B44, 0x9A4F, 0x6B45, 0x9A50, 0x6B46, 0xECA7, 0x6B47, 0xD0AA, 0x6B48, 0x9A51, 0x6B49, 0xC7B8, 0x6B4A, 0x9A52, + 0x6B4B, 0x9A53, 0x6B4C, 0xB8E8, 0x6B4D, 0x9A54, 0x6B4E, 0x9A55, 0x6B4F, 0x9A56, 0x6B50, 0x9A57, 0x6B51, 0x9A58, 0x6B52, 0x9A59, + 0x6B53, 0x9A5A, 0x6B54, 0x9A5B, 0x6B55, 0x9A5C, 0x6B56, 0x9A5D, 0x6B57, 0x9A5E, 0x6B58, 0x9A5F, 0x6B59, 0xECA8, 0x6B5A, 0x9A60, + 0x6B5B, 0x9A61, 0x6B5C, 0x9A62, 0x6B5D, 0x9A63, 0x6B5E, 0x9A64, 0x6B5F, 0x9A65, 0x6B60, 0x9A66, 0x6B61, 0x9A67, 0x6B62, 0xD6B9, + 0x6B63, 0xD5FD, 0x6B64, 0xB4CB, 0x6B65, 0xB2BD, 0x6B66, 0xCEE4, 0x6B67, 0xC6E7, 0x6B68, 0x9A68, 0x6B69, 0x9A69, 0x6B6A, 0xCDE1, + 0x6B6B, 0x9A6A, 0x6B6C, 0x9A6B, 0x6B6D, 0x9A6C, 0x6B6E, 0x9A6D, 0x6B6F, 0x9A6E, 0x6B70, 0x9A6F, 0x6B71, 0x9A70, 0x6B72, 0x9A71, + 0x6B73, 0x9A72, 0x6B74, 0x9A73, 0x6B75, 0x9A74, 0x6B76, 0x9A75, 0x6B77, 0x9A76, 0x6B78, 0x9A77, 0x6B79, 0xB4F5, 0x6B7A, 0x9A78, + 0x6B7B, 0xCBC0, 0x6B7C, 0xBCDF, 0x6B7D, 0x9A79, 0x6B7E, 0x9A7A, 0x6B7F, 0x9A7B, 0x6B80, 0x9A7C, 0x6B81, 0xE9E2, 0x6B82, 0xE9E3, + 0x6B83, 0xD1EA, 0x6B84, 0xE9E5, 0x6B85, 0x9A7D, 0x6B86, 0xB4F9, 0x6B87, 0xE9E4, 0x6B88, 0x9A7E, 0x6B89, 0xD1B3, 0x6B8A, 0xCAE2, + 0x6B8B, 0xB2D0, 0x6B8C, 0x9A80, 0x6B8D, 0xE9E8, 0x6B8E, 0x9A81, 0x6B8F, 0x9A82, 0x6B90, 0x9A83, 0x6B91, 0x9A84, 0x6B92, 0xE9E6, + 0x6B93, 0xE9E7, 0x6B94, 0x9A85, 0x6B95, 0x9A86, 0x6B96, 0xD6B3, 0x6B97, 0x9A87, 0x6B98, 0x9A88, 0x6B99, 0x9A89, 0x6B9A, 0xE9E9, + 0x6B9B, 0xE9EA, 0x6B9C, 0x9A8A, 0x6B9D, 0x9A8B, 0x6B9E, 0x9A8C, 0x6B9F, 0x9A8D, 0x6BA0, 0x9A8E, 0x6BA1, 0xE9EB, 0x6BA2, 0x9A8F, + 0x6BA3, 0x9A90, 0x6BA4, 0x9A91, 0x6BA5, 0x9A92, 0x6BA6, 0x9A93, 0x6BA7, 0x9A94, 0x6BA8, 0x9A95, 0x6BA9, 0x9A96, 0x6BAA, 0xE9EC, + 0x6BAB, 0x9A97, 0x6BAC, 0x9A98, 0x6BAD, 0x9A99, 0x6BAE, 0x9A9A, 0x6BAF, 0x9A9B, 0x6BB0, 0x9A9C, 0x6BB1, 0x9A9D, 0x6BB2, 0x9A9E, + 0x6BB3, 0xECAF, 0x6BB4, 0xC5B9, 0x6BB5, 0xB6CE, 0x6BB6, 0x9A9F, 0x6BB7, 0xD2F3, 0x6BB8, 0x9AA0, 0x6BB9, 0x9AA1, 0x6BBA, 0x9AA2, + 0x6BBB, 0x9AA3, 0x6BBC, 0x9AA4, 0x6BBD, 0x9AA5, 0x6BBE, 0x9AA6, 0x6BBF, 0xB5EE, 0x6BC0, 0x9AA7, 0x6BC1, 0xBBD9, 0x6BC2, 0xECB1, + 0x6BC3, 0x9AA8, 0x6BC4, 0x9AA9, 0x6BC5, 0xD2E3, 0x6BC6, 0x9AAA, 0x6BC7, 0x9AAB, 0x6BC8, 0x9AAC, 0x6BC9, 0x9AAD, 0x6BCA, 0x9AAE, + 0x6BCB, 0xCEE3, 0x6BCC, 0x9AAF, 0x6BCD, 0xC4B8, 0x6BCE, 0x9AB0, 0x6BCF, 0xC3BF, 0x6BD0, 0x9AB1, 0x6BD1, 0x9AB2, 0x6BD2, 0xB6BE, + 0x6BD3, 0xD8B9, 0x6BD4, 0xB1C8, 0x6BD5, 0xB1CF, 0x6BD6, 0xB1D1, 0x6BD7, 0xC5FE, 0x6BD8, 0x9AB3, 0x6BD9, 0xB1D0, 0x6BDA, 0x9AB4, + 0x6BDB, 0xC3AB, 0x6BDC, 0x9AB5, 0x6BDD, 0x9AB6, 0x6BDE, 0x9AB7, 0x6BDF, 0x9AB8, 0x6BE0, 0x9AB9, 0x6BE1, 0xD5B1, 0x6BE2, 0x9ABA, + 0x6BE3, 0x9ABB, 0x6BE4, 0x9ABC, 0x6BE5, 0x9ABD, 0x6BE6, 0x9ABE, 0x6BE7, 0x9ABF, 0x6BE8, 0x9AC0, 0x6BE9, 0x9AC1, 0x6BEA, 0xEBA4, + 0x6BEB, 0xBAC1, 0x6BEC, 0x9AC2, 0x6BED, 0x9AC3, 0x6BEE, 0x9AC4, 0x6BEF, 0xCCBA, 0x6BF0, 0x9AC5, 0x6BF1, 0x9AC6, 0x6BF2, 0x9AC7, + 0x6BF3, 0xEBA5, 0x6BF4, 0x9AC8, 0x6BF5, 0xEBA7, 0x6BF6, 0x9AC9, 0x6BF7, 0x9ACA, 0x6BF8, 0x9ACB, 0x6BF9, 0xEBA8, 0x6BFA, 0x9ACC, + 0x6BFB, 0x9ACD, 0x6BFC, 0x9ACE, 0x6BFD, 0xEBA6, 0x6BFE, 0x9ACF, 0x6BFF, 0x9AD0, 0x6C00, 0x9AD1, 0x6C01, 0x9AD2, 0x6C02, 0x9AD3, + 0x6C03, 0x9AD4, 0x6C04, 0x9AD5, 0x6C05, 0xEBA9, 0x6C06, 0xEBAB, 0x6C07, 0xEBAA, 0x6C08, 0x9AD6, 0x6C09, 0x9AD7, 0x6C0A, 0x9AD8, + 0x6C0B, 0x9AD9, 0x6C0C, 0x9ADA, 0x6C0D, 0xEBAC, 0x6C0E, 0x9ADB, 0x6C0F, 0xCACF, 0x6C10, 0xD8B5, 0x6C11, 0xC3F1, 0x6C12, 0x9ADC, + 0x6C13, 0xC3A5, 0x6C14, 0xC6F8, 0x6C15, 0xEBAD, 0x6C16, 0xC4CA, 0x6C17, 0x9ADD, 0x6C18, 0xEBAE, 0x6C19, 0xEBAF, 0x6C1A, 0xEBB0, + 0x6C1B, 0xB7D5, 0x6C1C, 0x9ADE, 0x6C1D, 0x9ADF, 0x6C1E, 0x9AE0, 0x6C1F, 0xB7FA, 0x6C20, 0x9AE1, 0x6C21, 0xEBB1, 0x6C22, 0xC7E2, + 0x6C23, 0x9AE2, 0x6C24, 0xEBB3, 0x6C25, 0x9AE3, 0x6C26, 0xBAA4, 0x6C27, 0xD1F5, 0x6C28, 0xB0B1, 0x6C29, 0xEBB2, 0x6C2A, 0xEBB4, + 0x6C2B, 0x9AE4, 0x6C2C, 0x9AE5, 0x6C2D, 0x9AE6, 0x6C2E, 0xB5AA, 0x6C2F, 0xC2C8, 0x6C30, 0xC7E8, 0x6C31, 0x9AE7, 0x6C32, 0xEBB5, + 0x6C33, 0x9AE8, 0x6C34, 0xCBAE, 0x6C35, 0xE3DF, 0x6C36, 0x9AE9, 0x6C37, 0x9AEA, 0x6C38, 0xD3C0, 0x6C39, 0x9AEB, 0x6C3A, 0x9AEC, + 0x6C3B, 0x9AED, 0x6C3C, 0x9AEE, 0x6C3D, 0xD9DB, 0x6C3E, 0x9AEF, 0x6C3F, 0x9AF0, 0x6C40, 0xCDA1, 0x6C41, 0xD6AD, 0x6C42, 0xC7F3, + 0x6C43, 0x9AF1, 0x6C44, 0x9AF2, 0x6C45, 0x9AF3, 0x6C46, 0xD9E0, 0x6C47, 0xBBE3, 0x6C48, 0x9AF4, 0x6C49, 0xBABA, 0x6C4A, 0xE3E2, + 0x6C4B, 0x9AF5, 0x6C4C, 0x9AF6, 0x6C4D, 0x9AF7, 0x6C4E, 0x9AF8, 0x6C4F, 0x9AF9, 0x6C50, 0xCFAB, 0x6C51, 0x9AFA, 0x6C52, 0x9AFB, + 0x6C53, 0x9AFC, 0x6C54, 0xE3E0, 0x6C55, 0xC9C7, 0x6C56, 0x9AFD, 0x6C57, 0xBAB9, 0x6C58, 0x9AFE, 0x6C59, 0x9B40, 0x6C5A, 0x9B41, + 0x6C5B, 0xD1B4, 0x6C5C, 0xE3E1, 0x6C5D, 0xC8EA, 0x6C5E, 0xB9AF, 0x6C5F, 0xBDAD, 0x6C60, 0xB3D8, 0x6C61, 0xCEDB, 0x6C62, 0x9B42, + 0x6C63, 0x9B43, 0x6C64, 0xCCC0, 0x6C65, 0x9B44, 0x6C66, 0x9B45, 0x6C67, 0x9B46, 0x6C68, 0xE3E8, 0x6C69, 0xE3E9, 0x6C6A, 0xCDF4, + 0x6C6B, 0x9B47, 0x6C6C, 0x9B48, 0x6C6D, 0x9B49, 0x6C6E, 0x9B4A, 0x6C6F, 0x9B4B, 0x6C70, 0xCCAD, 0x6C71, 0x9B4C, 0x6C72, 0xBCB3, + 0x6C73, 0x9B4D, 0x6C74, 0xE3EA, 0x6C75, 0x9B4E, 0x6C76, 0xE3EB, 0x6C77, 0x9B4F, 0x6C78, 0x9B50, 0x6C79, 0xD0DA, 0x6C7A, 0x9B51, + 0x6C7B, 0x9B52, 0x6C7C, 0x9B53, 0x6C7D, 0xC6FB, 0x6C7E, 0xB7DA, 0x6C7F, 0x9B54, 0x6C80, 0x9B55, 0x6C81, 0xC7DF, 0x6C82, 0xD2CA, + 0x6C83, 0xCED6, 0x6C84, 0x9B56, 0x6C85, 0xE3E4, 0x6C86, 0xE3EC, 0x6C87, 0x9B57, 0x6C88, 0xC9F2, 0x6C89, 0xB3C1, 0x6C8A, 0x9B58, + 0x6C8B, 0x9B59, 0x6C8C, 0xE3E7, 0x6C8D, 0x9B5A, 0x6C8E, 0x9B5B, 0x6C8F, 0xC6E3, 0x6C90, 0xE3E5, 0x6C91, 0x9B5C, 0x6C92, 0x9B5D, + 0x6C93, 0xEDB3, 0x6C94, 0xE3E6, 0x6C95, 0x9B5E, 0x6C96, 0x9B5F, 0x6C97, 0x9B60, 0x6C98, 0x9B61, 0x6C99, 0xC9B3, 0x6C9A, 0x9B62, + 0x6C9B, 0xC5E6, 0x6C9C, 0x9B63, 0x6C9D, 0x9B64, 0x6C9E, 0x9B65, 0x6C9F, 0xB9B5, 0x6CA0, 0x9B66, 0x6CA1, 0xC3BB, 0x6CA2, 0x9B67, + 0x6CA3, 0xE3E3, 0x6CA4, 0xC5BD, 0x6CA5, 0xC1A4, 0x6CA6, 0xC2D9, 0x6CA7, 0xB2D7, 0x6CA8, 0x9B68, 0x6CA9, 0xE3ED, 0x6CAA, 0xBBA6, + 0x6CAB, 0xC4AD, 0x6CAC, 0x9B69, 0x6CAD, 0xE3F0, 0x6CAE, 0xBEDA, 0x6CAF, 0x9B6A, 0x6CB0, 0x9B6B, 0x6CB1, 0xE3FB, 0x6CB2, 0xE3F5, + 0x6CB3, 0xBAD3, 0x6CB4, 0x9B6C, 0x6CB5, 0x9B6D, 0x6CB6, 0x9B6E, 0x6CB7, 0x9B6F, 0x6CB8, 0xB7D0, 0x6CB9, 0xD3CD, 0x6CBA, 0x9B70, + 0x6CBB, 0xD6CE, 0x6CBC, 0xD5D3, 0x6CBD, 0xB9C1, 0x6CBE, 0xD5B4, 0x6CBF, 0xD1D8, 0x6CC0, 0x9B71, 0x6CC1, 0x9B72, 0x6CC2, 0x9B73, + 0x6CC3, 0x9B74, 0x6CC4, 0xD0B9, 0x6CC5, 0xC7F6, 0x6CC6, 0x9B75, 0x6CC7, 0x9B76, 0x6CC8, 0x9B77, 0x6CC9, 0xC8AA, 0x6CCA, 0xB2B4, + 0x6CCB, 0x9B78, 0x6CCC, 0xC3DA, 0x6CCD, 0x9B79, 0x6CCE, 0x9B7A, 0x6CCF, 0x9B7B, 0x6CD0, 0xE3EE, 0x6CD1, 0x9B7C, 0x6CD2, 0x9B7D, + 0x6CD3, 0xE3FC, 0x6CD4, 0xE3EF, 0x6CD5, 0xB7A8, 0x6CD6, 0xE3F7, 0x6CD7, 0xE3F4, 0x6CD8, 0x9B7E, 0x6CD9, 0x9B80, 0x6CDA, 0x9B81, + 0x6CDB, 0xB7BA, 0x6CDC, 0x9B82, 0x6CDD, 0x9B83, 0x6CDE, 0xC5A2, 0x6CDF, 0x9B84, 0x6CE0, 0xE3F6, 0x6CE1, 0xC5DD, 0x6CE2, 0xB2A8, + 0x6CE3, 0xC6FC, 0x6CE4, 0x9B85, 0x6CE5, 0xC4E0, 0x6CE6, 0x9B86, 0x6CE7, 0x9B87, 0x6CE8, 0xD7A2, 0x6CE9, 0x9B88, 0x6CEA, 0xC0E1, + 0x6CEB, 0xE3F9, 0x6CEC, 0x9B89, 0x6CED, 0x9B8A, 0x6CEE, 0xE3FA, 0x6CEF, 0xE3FD, 0x6CF0, 0xCCA9, 0x6CF1, 0xE3F3, 0x6CF2, 0x9B8B, + 0x6CF3, 0xD3BE, 0x6CF4, 0x9B8C, 0x6CF5, 0xB1C3, 0x6CF6, 0xEDB4, 0x6CF7, 0xE3F1, 0x6CF8, 0xE3F2, 0x6CF9, 0x9B8D, 0x6CFA, 0xE3F8, + 0x6CFB, 0xD0BA, 0x6CFC, 0xC6C3, 0x6CFD, 0xD4F3, 0x6CFE, 0xE3FE, 0x6CFF, 0x9B8E, 0x6D00, 0x9B8F, 0x6D01, 0xBDE0, 0x6D02, 0x9B90, + 0x6D03, 0x9B91, 0x6D04, 0xE4A7, 0x6D05, 0x9B92, 0x6D06, 0x9B93, 0x6D07, 0xE4A6, 0x6D08, 0x9B94, 0x6D09, 0x9B95, 0x6D0A, 0x9B96, + 0x6D0B, 0xD1F3, 0x6D0C, 0xE4A3, 0x6D0D, 0x9B97, 0x6D0E, 0xE4A9, 0x6D0F, 0x9B98, 0x6D10, 0x9B99, 0x6D11, 0x9B9A, 0x6D12, 0xC8F7, + 0x6D13, 0x9B9B, 0x6D14, 0x9B9C, 0x6D15, 0x9B9D, 0x6D16, 0x9B9E, 0x6D17, 0xCFB4, 0x6D18, 0x9B9F, 0x6D19, 0xE4A8, 0x6D1A, 0xE4AE, + 0x6D1B, 0xC2E5, 0x6D1C, 0x9BA0, 0x6D1D, 0x9BA1, 0x6D1E, 0xB6B4, 0x6D1F, 0x9BA2, 0x6D20, 0x9BA3, 0x6D21, 0x9BA4, 0x6D22, 0x9BA5, + 0x6D23, 0x9BA6, 0x6D24, 0x9BA7, 0x6D25, 0xBDF2, 0x6D26, 0x9BA8, 0x6D27, 0xE4A2, 0x6D28, 0x9BA9, 0x6D29, 0x9BAA, 0x6D2A, 0xBAE9, + 0x6D2B, 0xE4AA, 0x6D2C, 0x9BAB, 0x6D2D, 0x9BAC, 0x6D2E, 0xE4AC, 0x6D2F, 0x9BAD, 0x6D30, 0x9BAE, 0x6D31, 0xB6FD, 0x6D32, 0xD6DE, + 0x6D33, 0xE4B2, 0x6D34, 0x9BAF, 0x6D35, 0xE4AD, 0x6D36, 0x9BB0, 0x6D37, 0x9BB1, 0x6D38, 0x9BB2, 0x6D39, 0xE4A1, 0x6D3A, 0x9BB3, + 0x6D3B, 0xBBEE, 0x6D3C, 0xCDDD, 0x6D3D, 0xC7A2, 0x6D3E, 0xC5C9, 0x6D3F, 0x9BB4, 0x6D40, 0x9BB5, 0x6D41, 0xC1F7, 0x6D42, 0x9BB6, + 0x6D43, 0xE4A4, 0x6D44, 0x9BB7, 0x6D45, 0xC7B3, 0x6D46, 0xBDAC, 0x6D47, 0xBDBD, 0x6D48, 0xE4A5, 0x6D49, 0x9BB8, 0x6D4A, 0xD7C7, + 0x6D4B, 0xB2E2, 0x6D4C, 0x9BB9, 0x6D4D, 0xE4AB, 0x6D4E, 0xBCC3, 0x6D4F, 0xE4AF, 0x6D50, 0x9BBA, 0x6D51, 0xBBEB, 0x6D52, 0xE4B0, + 0x6D53, 0xC5A8, 0x6D54, 0xE4B1, 0x6D55, 0x9BBB, 0x6D56, 0x9BBC, 0x6D57, 0x9BBD, 0x6D58, 0x9BBE, 0x6D59, 0xD5E3, 0x6D5A, 0xBFA3, + 0x6D5B, 0x9BBF, 0x6D5C, 0xE4BA, 0x6D5D, 0x9BC0, 0x6D5E, 0xE4B7, 0x6D5F, 0x9BC1, 0x6D60, 0xE4BB, 0x6D61, 0x9BC2, 0x6D62, 0x9BC3, + 0x6D63, 0xE4BD, 0x6D64, 0x9BC4, 0x6D65, 0x9BC5, 0x6D66, 0xC6D6, 0x6D67, 0x9BC6, 0x6D68, 0x9BC7, 0x6D69, 0xBAC6, 0x6D6A, 0xC0CB, + 0x6D6B, 0x9BC8, 0x6D6C, 0x9BC9, 0x6D6D, 0x9BCA, 0x6D6E, 0xB8A1, 0x6D6F, 0xE4B4, 0x6D70, 0x9BCB, 0x6D71, 0x9BCC, 0x6D72, 0x9BCD, + 0x6D73, 0x9BCE, 0x6D74, 0xD4A1, 0x6D75, 0x9BCF, 0x6D76, 0x9BD0, 0x6D77, 0xBAA3, 0x6D78, 0xBDFE, 0x6D79, 0x9BD1, 0x6D7A, 0x9BD2, + 0x6D7B, 0x9BD3, 0x6D7C, 0xE4BC, 0x6D7D, 0x9BD4, 0x6D7E, 0x9BD5, 0x6D7F, 0x9BD6, 0x6D80, 0x9BD7, 0x6D81, 0x9BD8, 0x6D82, 0xCDBF, + 0x6D83, 0x9BD9, 0x6D84, 0x9BDA, 0x6D85, 0xC4F9, 0x6D86, 0x9BDB, 0x6D87, 0x9BDC, 0x6D88, 0xCFFB, 0x6D89, 0xC9E6, 0x6D8A, 0x9BDD, + 0x6D8B, 0x9BDE, 0x6D8C, 0xD3BF, 0x6D8D, 0x9BDF, 0x6D8E, 0xCFD1, 0x6D8F, 0x9BE0, 0x6D90, 0x9BE1, 0x6D91, 0xE4B3, 0x6D92, 0x9BE2, + 0x6D93, 0xE4B8, 0x6D94, 0xE4B9, 0x6D95, 0xCCE9, 0x6D96, 0x9BE3, 0x6D97, 0x9BE4, 0x6D98, 0x9BE5, 0x6D99, 0x9BE6, 0x6D9A, 0x9BE7, + 0x6D9B, 0xCCCE, 0x6D9C, 0x9BE8, 0x6D9D, 0xC0D4, 0x6D9E, 0xE4B5, 0x6D9F, 0xC1B0, 0x6DA0, 0xE4B6, 0x6DA1, 0xCED0, 0x6DA2, 0x9BE9, + 0x6DA3, 0xBBC1, 0x6DA4, 0xB5D3, 0x6DA5, 0x9BEA, 0x6DA6, 0xC8F3, 0x6DA7, 0xBDA7, 0x6DA8, 0xD5C7, 0x6DA9, 0xC9AC, 0x6DAA, 0xB8A2, + 0x6DAB, 0xE4CA, 0x6DAC, 0x9BEB, 0x6DAD, 0x9BEC, 0x6DAE, 0xE4CC, 0x6DAF, 0xD1C4, 0x6DB0, 0x9BED, 0x6DB1, 0x9BEE, 0x6DB2, 0xD2BA, + 0x6DB3, 0x9BEF, 0x6DB4, 0x9BF0, 0x6DB5, 0xBAAD, 0x6DB6, 0x9BF1, 0x6DB7, 0x9BF2, 0x6DB8, 0xBAD4, 0x6DB9, 0x9BF3, 0x6DBA, 0x9BF4, + 0x6DBB, 0x9BF5, 0x6DBC, 0x9BF6, 0x6DBD, 0x9BF7, 0x6DBE, 0x9BF8, 0x6DBF, 0xE4C3, 0x6DC0, 0xB5ED, 0x6DC1, 0x9BF9, 0x6DC2, 0x9BFA, + 0x6DC3, 0x9BFB, 0x6DC4, 0xD7CD, 0x6DC5, 0xE4C0, 0x6DC6, 0xCFFD, 0x6DC7, 0xE4BF, 0x6DC8, 0x9BFC, 0x6DC9, 0x9BFD, 0x6DCA, 0x9BFE, + 0x6DCB, 0xC1DC, 0x6DCC, 0xCCCA, 0x6DCD, 0x9C40, 0x6DCE, 0x9C41, 0x6DCF, 0x9C42, 0x6DD0, 0x9C43, 0x6DD1, 0xCAE7, 0x6DD2, 0x9C44, + 0x6DD3, 0x9C45, 0x6DD4, 0x9C46, 0x6DD5, 0x9C47, 0x6DD6, 0xC4D7, 0x6DD7, 0x9C48, 0x6DD8, 0xCCD4, 0x6DD9, 0xE4C8, 0x6DDA, 0x9C49, + 0x6DDB, 0x9C4A, 0x6DDC, 0x9C4B, 0x6DDD, 0xE4C7, 0x6DDE, 0xE4C1, 0x6DDF, 0x9C4C, 0x6DE0, 0xE4C4, 0x6DE1, 0xB5AD, 0x6DE2, 0x9C4D, + 0x6DE3, 0x9C4E, 0x6DE4, 0xD3D9, 0x6DE5, 0x9C4F, 0x6DE6, 0xE4C6, 0x6DE7, 0x9C50, 0x6DE8, 0x9C51, 0x6DE9, 0x9C52, 0x6DEA, 0x9C53, + 0x6DEB, 0xD2F9, 0x6DEC, 0xB4E3, 0x6DED, 0x9C54, 0x6DEE, 0xBBB4, 0x6DEF, 0x9C55, 0x6DF0, 0x9C56, 0x6DF1, 0xC9EE, 0x6DF2, 0x9C57, + 0x6DF3, 0xB4BE, 0x6DF4, 0x9C58, 0x6DF5, 0x9C59, 0x6DF6, 0x9C5A, 0x6DF7, 0xBBEC, 0x6DF8, 0x9C5B, 0x6DF9, 0xD1CD, 0x6DFA, 0x9C5C, + 0x6DFB, 0xCCED, 0x6DFC, 0xEDB5, 0x6DFD, 0x9C5D, 0x6DFE, 0x9C5E, 0x6DFF, 0x9C5F, 0x6E00, 0x9C60, 0x6E01, 0x9C61, 0x6E02, 0x9C62, + 0x6E03, 0x9C63, 0x6E04, 0x9C64, 0x6E05, 0xC7E5, 0x6E06, 0x9C65, 0x6E07, 0x9C66, 0x6E08, 0x9C67, 0x6E09, 0x9C68, 0x6E0A, 0xD4A8, + 0x6E0B, 0x9C69, 0x6E0C, 0xE4CB, 0x6E0D, 0xD7D5, 0x6E0E, 0xE4C2, 0x6E0F, 0x9C6A, 0x6E10, 0xBDA5, 0x6E11, 0xE4C5, 0x6E12, 0x9C6B, + 0x6E13, 0x9C6C, 0x6E14, 0xD3E6, 0x6E15, 0x9C6D, 0x6E16, 0xE4C9, 0x6E17, 0xC9F8, 0x6E18, 0x9C6E, 0x6E19, 0x9C6F, 0x6E1A, 0xE4BE, + 0x6E1B, 0x9C70, 0x6E1C, 0x9C71, 0x6E1D, 0xD3E5, 0x6E1E, 0x9C72, 0x6E1F, 0x9C73, 0x6E20, 0xC7FE, 0x6E21, 0xB6C9, 0x6E22, 0x9C74, + 0x6E23, 0xD4FC, 0x6E24, 0xB2B3, 0x6E25, 0xE4D7, 0x6E26, 0x9C75, 0x6E27, 0x9C76, 0x6E28, 0x9C77, 0x6E29, 0xCEC2, 0x6E2A, 0x9C78, + 0x6E2B, 0xE4CD, 0x6E2C, 0x9C79, 0x6E2D, 0xCEBC, 0x6E2E, 0x9C7A, 0x6E2F, 0xB8DB, 0x6E30, 0x9C7B, 0x6E31, 0x9C7C, 0x6E32, 0xE4D6, + 0x6E33, 0x9C7D, 0x6E34, 0xBFCA, 0x6E35, 0x9C7E, 0x6E36, 0x9C80, 0x6E37, 0x9C81, 0x6E38, 0xD3CE, 0x6E39, 0x9C82, 0x6E3A, 0xC3EC, + 0x6E3B, 0x9C83, 0x6E3C, 0x9C84, 0x6E3D, 0x9C85, 0x6E3E, 0x9C86, 0x6E3F, 0x9C87, 0x6E40, 0x9C88, 0x6E41, 0x9C89, 0x6E42, 0x9C8A, + 0x6E43, 0xC5C8, 0x6E44, 0xE4D8, 0x6E45, 0x9C8B, 0x6E46, 0x9C8C, 0x6E47, 0x9C8D, 0x6E48, 0x9C8E, 0x6E49, 0x9C8F, 0x6E4A, 0x9C90, + 0x6E4B, 0x9C91, 0x6E4C, 0x9C92, 0x6E4D, 0xCDC4, 0x6E4E, 0xE4CF, 0x6E4F, 0x9C93, 0x6E50, 0x9C94, 0x6E51, 0x9C95, 0x6E52, 0x9C96, + 0x6E53, 0xE4D4, 0x6E54, 0xE4D5, 0x6E55, 0x9C97, 0x6E56, 0xBAFE, 0x6E57, 0x9C98, 0x6E58, 0xCFE6, 0x6E59, 0x9C99, 0x6E5A, 0x9C9A, + 0x6E5B, 0xD5BF, 0x6E5C, 0x9C9B, 0x6E5D, 0x9C9C, 0x6E5E, 0x9C9D, 0x6E5F, 0xE4D2, 0x6E60, 0x9C9E, 0x6E61, 0x9C9F, 0x6E62, 0x9CA0, + 0x6E63, 0x9CA1, 0x6E64, 0x9CA2, 0x6E65, 0x9CA3, 0x6E66, 0x9CA4, 0x6E67, 0x9CA5, 0x6E68, 0x9CA6, 0x6E69, 0x9CA7, 0x6E6A, 0x9CA8, + 0x6E6B, 0xE4D0, 0x6E6C, 0x9CA9, 0x6E6D, 0x9CAA, 0x6E6E, 0xE4CE, 0x6E6F, 0x9CAB, 0x6E70, 0x9CAC, 0x6E71, 0x9CAD, 0x6E72, 0x9CAE, + 0x6E73, 0x9CAF, 0x6E74, 0x9CB0, 0x6E75, 0x9CB1, 0x6E76, 0x9CB2, 0x6E77, 0x9CB3, 0x6E78, 0x9CB4, 0x6E79, 0x9CB5, 0x6E7A, 0x9CB6, + 0x6E7B, 0x9CB7, 0x6E7C, 0x9CB8, 0x6E7D, 0x9CB9, 0x6E7E, 0xCDE5, 0x6E7F, 0xCAAA, 0x6E80, 0x9CBA, 0x6E81, 0x9CBB, 0x6E82, 0x9CBC, + 0x6E83, 0xC0A3, 0x6E84, 0x9CBD, 0x6E85, 0xBDA6, 0x6E86, 0xE4D3, 0x6E87, 0x9CBE, 0x6E88, 0x9CBF, 0x6E89, 0xB8C8, 0x6E8A, 0x9CC0, + 0x6E8B, 0x9CC1, 0x6E8C, 0x9CC2, 0x6E8D, 0x9CC3, 0x6E8E, 0x9CC4, 0x6E8F, 0xE4E7, 0x6E90, 0xD4B4, 0x6E91, 0x9CC5, 0x6E92, 0x9CC6, + 0x6E93, 0x9CC7, 0x6E94, 0x9CC8, 0x6E95, 0x9CC9, 0x6E96, 0x9CCA, 0x6E97, 0x9CCB, 0x6E98, 0xE4DB, 0x6E99, 0x9CCC, 0x6E9A, 0x9CCD, + 0x6E9B, 0x9CCE, 0x6E9C, 0xC1EF, 0x6E9D, 0x9CCF, 0x6E9E, 0x9CD0, 0x6E9F, 0xE4E9, 0x6EA0, 0x9CD1, 0x6EA1, 0x9CD2, 0x6EA2, 0xD2E7, + 0x6EA3, 0x9CD3, 0x6EA4, 0x9CD4, 0x6EA5, 0xE4DF, 0x6EA6, 0x9CD5, 0x6EA7, 0xE4E0, 0x6EA8, 0x9CD6, 0x6EA9, 0x9CD7, 0x6EAA, 0xCFAA, + 0x6EAB, 0x9CD8, 0x6EAC, 0x9CD9, 0x6EAD, 0x9CDA, 0x6EAE, 0x9CDB, 0x6EAF, 0xCBDD, 0x6EB0, 0x9CDC, 0x6EB1, 0xE4DA, 0x6EB2, 0xE4D1, + 0x6EB3, 0x9CDD, 0x6EB4, 0xE4E5, 0x6EB5, 0x9CDE, 0x6EB6, 0xC8DC, 0x6EB7, 0xE4E3, 0x6EB8, 0x9CDF, 0x6EB9, 0x9CE0, 0x6EBA, 0xC4E7, + 0x6EBB, 0xE4E2, 0x6EBC, 0x9CE1, 0x6EBD, 0xE4E1, 0x6EBE, 0x9CE2, 0x6EBF, 0x9CE3, 0x6EC0, 0x9CE4, 0x6EC1, 0xB3FC, 0x6EC2, 0xE4E8, + 0x6EC3, 0x9CE5, 0x6EC4, 0x9CE6, 0x6EC5, 0x9CE7, 0x6EC6, 0x9CE8, 0x6EC7, 0xB5E1, 0x6EC8, 0x9CE9, 0x6EC9, 0x9CEA, 0x6ECA, 0x9CEB, + 0x6ECB, 0xD7CC, 0x6ECC, 0x9CEC, 0x6ECD, 0x9CED, 0x6ECE, 0x9CEE, 0x6ECF, 0xE4E6, 0x6ED0, 0x9CEF, 0x6ED1, 0xBBAC, 0x6ED2, 0x9CF0, + 0x6ED3, 0xD7D2, 0x6ED4, 0xCCCF, 0x6ED5, 0xEBF8, 0x6ED6, 0x9CF1, 0x6ED7, 0xE4E4, 0x6ED8, 0x9CF2, 0x6ED9, 0x9CF3, 0x6EDA, 0xB9F6, + 0x6EDB, 0x9CF4, 0x6EDC, 0x9CF5, 0x6EDD, 0x9CF6, 0x6EDE, 0xD6CD, 0x6EDF, 0xE4D9, 0x6EE0, 0xE4DC, 0x6EE1, 0xC2FA, 0x6EE2, 0xE4DE, + 0x6EE3, 0x9CF7, 0x6EE4, 0xC2CB, 0x6EE5, 0xC0C4, 0x6EE6, 0xC2D0, 0x6EE7, 0x9CF8, 0x6EE8, 0xB1F5, 0x6EE9, 0xCCB2, 0x6EEA, 0x9CF9, + 0x6EEB, 0x9CFA, 0x6EEC, 0x9CFB, 0x6EED, 0x9CFC, 0x6EEE, 0x9CFD, 0x6EEF, 0x9CFE, 0x6EF0, 0x9D40, 0x6EF1, 0x9D41, 0x6EF2, 0x9D42, + 0x6EF3, 0x9D43, 0x6EF4, 0xB5CE, 0x6EF5, 0x9D44, 0x6EF6, 0x9D45, 0x6EF7, 0x9D46, 0x6EF8, 0x9D47, 0x6EF9, 0xE4EF, 0x6EFA, 0x9D48, + 0x6EFB, 0x9D49, 0x6EFC, 0x9D4A, 0x6EFD, 0x9D4B, 0x6EFE, 0x9D4C, 0x6EFF, 0x9D4D, 0x6F00, 0x9D4E, 0x6F01, 0x9D4F, 0x6F02, 0xC6AF, + 0x6F03, 0x9D50, 0x6F04, 0x9D51, 0x6F05, 0x9D52, 0x6F06, 0xC6E1, 0x6F07, 0x9D53, 0x6F08, 0x9D54, 0x6F09, 0xE4F5, 0x6F0A, 0x9D55, + 0x6F0B, 0x9D56, 0x6F0C, 0x9D57, 0x6F0D, 0x9D58, 0x6F0E, 0x9D59, 0x6F0F, 0xC2A9, 0x6F10, 0x9D5A, 0x6F11, 0x9D5B, 0x6F12, 0x9D5C, + 0x6F13, 0xC0EC, 0x6F14, 0xD1DD, 0x6F15, 0xE4EE, 0x6F16, 0x9D5D, 0x6F17, 0x9D5E, 0x6F18, 0x9D5F, 0x6F19, 0x9D60, 0x6F1A, 0x9D61, + 0x6F1B, 0x9D62, 0x6F1C, 0x9D63, 0x6F1D, 0x9D64, 0x6F1E, 0x9D65, 0x6F1F, 0x9D66, 0x6F20, 0xC4AE, 0x6F21, 0x9D67, 0x6F22, 0x9D68, + 0x6F23, 0x9D69, 0x6F24, 0xE4ED, 0x6F25, 0x9D6A, 0x6F26, 0x9D6B, 0x6F27, 0x9D6C, 0x6F28, 0x9D6D, 0x6F29, 0xE4F6, 0x6F2A, 0xE4F4, + 0x6F2B, 0xC2FE, 0x6F2C, 0x9D6E, 0x6F2D, 0xE4DD, 0x6F2E, 0x9D6F, 0x6F2F, 0xE4F0, 0x6F30, 0x9D70, 0x6F31, 0xCAFE, 0x6F32, 0x9D71, + 0x6F33, 0xD5C4, 0x6F34, 0x9D72, 0x6F35, 0x9D73, 0x6F36, 0xE4F1, 0x6F37, 0x9D74, 0x6F38, 0x9D75, 0x6F39, 0x9D76, 0x6F3A, 0x9D77, + 0x6F3B, 0x9D78, 0x6F3C, 0x9D79, 0x6F3D, 0x9D7A, 0x6F3E, 0xD1FA, 0x6F3F, 0x9D7B, 0x6F40, 0x9D7C, 0x6F41, 0x9D7D, 0x6F42, 0x9D7E, + 0x6F43, 0x9D80, 0x6F44, 0x9D81, 0x6F45, 0x9D82, 0x6F46, 0xE4EB, 0x6F47, 0xE4EC, 0x6F48, 0x9D83, 0x6F49, 0x9D84, 0x6F4A, 0x9D85, + 0x6F4B, 0xE4F2, 0x6F4C, 0x9D86, 0x6F4D, 0xCEAB, 0x6F4E, 0x9D87, 0x6F4F, 0x9D88, 0x6F50, 0x9D89, 0x6F51, 0x9D8A, 0x6F52, 0x9D8B, + 0x6F53, 0x9D8C, 0x6F54, 0x9D8D, 0x6F55, 0x9D8E, 0x6F56, 0x9D8F, 0x6F57, 0x9D90, 0x6F58, 0xC5CB, 0x6F59, 0x9D91, 0x6F5A, 0x9D92, + 0x6F5B, 0x9D93, 0x6F5C, 0xC7B1, 0x6F5D, 0x9D94, 0x6F5E, 0xC2BA, 0x6F5F, 0x9D95, 0x6F60, 0x9D96, 0x6F61, 0x9D97, 0x6F62, 0xE4EA, + 0x6F63, 0x9D98, 0x6F64, 0x9D99, 0x6F65, 0x9D9A, 0x6F66, 0xC1CA, 0x6F67, 0x9D9B, 0x6F68, 0x9D9C, 0x6F69, 0x9D9D, 0x6F6A, 0x9D9E, + 0x6F6B, 0x9D9F, 0x6F6C, 0x9DA0, 0x6F6D, 0xCCB6, 0x6F6E, 0xB3B1, 0x6F6F, 0x9DA1, 0x6F70, 0x9DA2, 0x6F71, 0x9DA3, 0x6F72, 0xE4FB, + 0x6F73, 0x9DA4, 0x6F74, 0xE4F3, 0x6F75, 0x9DA5, 0x6F76, 0x9DA6, 0x6F77, 0x9DA7, 0x6F78, 0xE4FA, 0x6F79, 0x9DA8, 0x6F7A, 0xE4FD, + 0x6F7B, 0x9DA9, 0x6F7C, 0xE4FC, 0x6F7D, 0x9DAA, 0x6F7E, 0x9DAB, 0x6F7F, 0x9DAC, 0x6F80, 0x9DAD, 0x6F81, 0x9DAE, 0x6F82, 0x9DAF, + 0x6F83, 0x9DB0, 0x6F84, 0xB3CE, 0x6F85, 0x9DB1, 0x6F86, 0x9DB2, 0x6F87, 0x9DB3, 0x6F88, 0xB3BA, 0x6F89, 0xE4F7, 0x6F8A, 0x9DB4, + 0x6F8B, 0x9DB5, 0x6F8C, 0xE4F9, 0x6F8D, 0xE4F8, 0x6F8E, 0xC5EC, 0x6F8F, 0x9DB6, 0x6F90, 0x9DB7, 0x6F91, 0x9DB8, 0x6F92, 0x9DB9, + 0x6F93, 0x9DBA, 0x6F94, 0x9DBB, 0x6F95, 0x9DBC, 0x6F96, 0x9DBD, 0x6F97, 0x9DBE, 0x6F98, 0x9DBF, 0x6F99, 0x9DC0, 0x6F9A, 0x9DC1, + 0x6F9B, 0x9DC2, 0x6F9C, 0xC0BD, 0x6F9D, 0x9DC3, 0x6F9E, 0x9DC4, 0x6F9F, 0x9DC5, 0x6FA0, 0x9DC6, 0x6FA1, 0xD4E8, 0x6FA2, 0x9DC7, + 0x6FA3, 0x9DC8, 0x6FA4, 0x9DC9, 0x6FA5, 0x9DCA, 0x6FA6, 0x9DCB, 0x6FA7, 0xE5A2, 0x6FA8, 0x9DCC, 0x6FA9, 0x9DCD, 0x6FAA, 0x9DCE, + 0x6FAB, 0x9DCF, 0x6FAC, 0x9DD0, 0x6FAD, 0x9DD1, 0x6FAE, 0x9DD2, 0x6FAF, 0x9DD3, 0x6FB0, 0x9DD4, 0x6FB1, 0x9DD5, 0x6FB2, 0x9DD6, + 0x6FB3, 0xB0C4, 0x6FB4, 0x9DD7, 0x6FB5, 0x9DD8, 0x6FB6, 0xE5A4, 0x6FB7, 0x9DD9, 0x6FB8, 0x9DDA, 0x6FB9, 0xE5A3, 0x6FBA, 0x9DDB, + 0x6FBB, 0x9DDC, 0x6FBC, 0x9DDD, 0x6FBD, 0x9DDE, 0x6FBE, 0x9DDF, 0x6FBF, 0x9DE0, 0x6FC0, 0xBCA4, 0x6FC1, 0x9DE1, 0x6FC2, 0xE5A5, + 0x6FC3, 0x9DE2, 0x6FC4, 0x9DE3, 0x6FC5, 0x9DE4, 0x6FC6, 0x9DE5, 0x6FC7, 0x9DE6, 0x6FC8, 0x9DE7, 0x6FC9, 0xE5A1, 0x6FCA, 0x9DE8, + 0x6FCB, 0x9DE9, 0x6FCC, 0x9DEA, 0x6FCD, 0x9DEB, 0x6FCE, 0x9DEC, 0x6FCF, 0x9DED, 0x6FD0, 0x9DEE, 0x6FD1, 0xE4FE, 0x6FD2, 0xB1F4, + 0x6FD3, 0x9DEF, 0x6FD4, 0x9DF0, 0x6FD5, 0x9DF1, 0x6FD6, 0x9DF2, 0x6FD7, 0x9DF3, 0x6FD8, 0x9DF4, 0x6FD9, 0x9DF5, 0x6FDA, 0x9DF6, + 0x6FDB, 0x9DF7, 0x6FDC, 0x9DF8, 0x6FDD, 0x9DF9, 0x6FDE, 0xE5A8, 0x6FDF, 0x9DFA, 0x6FE0, 0xE5A9, 0x6FE1, 0xE5A6, 0x6FE2, 0x9DFB, + 0x6FE3, 0x9DFC, 0x6FE4, 0x9DFD, 0x6FE5, 0x9DFE, 0x6FE6, 0x9E40, 0x6FE7, 0x9E41, 0x6FE8, 0x9E42, 0x6FE9, 0x9E43, 0x6FEA, 0x9E44, + 0x6FEB, 0x9E45, 0x6FEC, 0x9E46, 0x6FED, 0x9E47, 0x6FEE, 0xE5A7, 0x6FEF, 0xE5AA, 0x6FF0, 0x9E48, 0x6FF1, 0x9E49, 0x6FF2, 0x9E4A, + 0x6FF3, 0x9E4B, 0x6FF4, 0x9E4C, 0x6FF5, 0x9E4D, 0x6FF6, 0x9E4E, 0x6FF7, 0x9E4F, 0x6FF8, 0x9E50, 0x6FF9, 0x9E51, 0x6FFA, 0x9E52, + 0x6FFB, 0x9E53, 0x6FFC, 0x9E54, 0x6FFD, 0x9E55, 0x6FFE, 0x9E56, 0x6FFF, 0x9E57, 0x7000, 0x9E58, 0x7001, 0x9E59, 0x7002, 0x9E5A, + 0x7003, 0x9E5B, 0x7004, 0x9E5C, 0x7005, 0x9E5D, 0x7006, 0x9E5E, 0x7007, 0x9E5F, 0x7008, 0x9E60, 0x7009, 0x9E61, 0x700A, 0x9E62, + 0x700B, 0x9E63, 0x700C, 0x9E64, 0x700D, 0x9E65, 0x700E, 0x9E66, 0x700F, 0x9E67, 0x7010, 0x9E68, 0x7011, 0xC6D9, 0x7012, 0x9E69, + 0x7013, 0x9E6A, 0x7014, 0x9E6B, 0x7015, 0x9E6C, 0x7016, 0x9E6D, 0x7017, 0x9E6E, 0x7018, 0x9E6F, 0x7019, 0x9E70, 0x701A, 0xE5AB, + 0x701B, 0xE5AD, 0x701C, 0x9E71, 0x701D, 0x9E72, 0x701E, 0x9E73, 0x701F, 0x9E74, 0x7020, 0x9E75, 0x7021, 0x9E76, 0x7022, 0x9E77, + 0x7023, 0xE5AC, 0x7024, 0x9E78, 0x7025, 0x9E79, 0x7026, 0x9E7A, 0x7027, 0x9E7B, 0x7028, 0x9E7C, 0x7029, 0x9E7D, 0x702A, 0x9E7E, + 0x702B, 0x9E80, 0x702C, 0x9E81, 0x702D, 0x9E82, 0x702E, 0x9E83, 0x702F, 0x9E84, 0x7030, 0x9E85, 0x7031, 0x9E86, 0x7032, 0x9E87, + 0x7033, 0x9E88, 0x7034, 0x9E89, 0x7035, 0xE5AF, 0x7036, 0x9E8A, 0x7037, 0x9E8B, 0x7038, 0x9E8C, 0x7039, 0xE5AE, 0x703A, 0x9E8D, + 0x703B, 0x9E8E, 0x703C, 0x9E8F, 0x703D, 0x9E90, 0x703E, 0x9E91, 0x703F, 0x9E92, 0x7040, 0x9E93, 0x7041, 0x9E94, 0x7042, 0x9E95, + 0x7043, 0x9E96, 0x7044, 0x9E97, 0x7045, 0x9E98, 0x7046, 0x9E99, 0x7047, 0x9E9A, 0x7048, 0x9E9B, 0x7049, 0x9E9C, 0x704A, 0x9E9D, + 0x704B, 0x9E9E, 0x704C, 0xB9E0, 0x704D, 0x9E9F, 0x704E, 0x9EA0, 0x704F, 0xE5B0, 0x7050, 0x9EA1, 0x7051, 0x9EA2, 0x7052, 0x9EA3, + 0x7053, 0x9EA4, 0x7054, 0x9EA5, 0x7055, 0x9EA6, 0x7056, 0x9EA7, 0x7057, 0x9EA8, 0x7058, 0x9EA9, 0x7059, 0x9EAA, 0x705A, 0x9EAB, + 0x705B, 0x9EAC, 0x705C, 0x9EAD, 0x705D, 0x9EAE, 0x705E, 0xE5B1, 0x705F, 0x9EAF, 0x7060, 0x9EB0, 0x7061, 0x9EB1, 0x7062, 0x9EB2, + 0x7063, 0x9EB3, 0x7064, 0x9EB4, 0x7065, 0x9EB5, 0x7066, 0x9EB6, 0x7067, 0x9EB7, 0x7068, 0x9EB8, 0x7069, 0x9EB9, 0x706A, 0x9EBA, + 0x706B, 0xBBF0, 0x706C, 0xECE1, 0x706D, 0xC3F0, 0x706E, 0x9EBB, 0x706F, 0xB5C6, 0x7070, 0xBBD2, 0x7071, 0x9EBC, 0x7072, 0x9EBD, + 0x7073, 0x9EBE, 0x7074, 0x9EBF, 0x7075, 0xC1E9, 0x7076, 0xD4EE, 0x7077, 0x9EC0, 0x7078, 0xBEC4, 0x7079, 0x9EC1, 0x707A, 0x9EC2, + 0x707B, 0x9EC3, 0x707C, 0xD7C6, 0x707D, 0x9EC4, 0x707E, 0xD4D6, 0x707F, 0xB2D3, 0x7080, 0xECBE, 0x7081, 0x9EC5, 0x7082, 0x9EC6, + 0x7083, 0x9EC7, 0x7084, 0x9EC8, 0x7085, 0xEAC1, 0x7086, 0x9EC9, 0x7087, 0x9ECA, 0x7088, 0x9ECB, 0x7089, 0xC2AF, 0x708A, 0xB4B6, + 0x708B, 0x9ECC, 0x708C, 0x9ECD, 0x708D, 0x9ECE, 0x708E, 0xD1D7, 0x708F, 0x9ECF, 0x7090, 0x9ED0, 0x7091, 0x9ED1, 0x7092, 0xB3B4, + 0x7093, 0x9ED2, 0x7094, 0xC8B2, 0x7095, 0xBFBB, 0x7096, 0xECC0, 0x7097, 0x9ED3, 0x7098, 0x9ED4, 0x7099, 0xD6CB, 0x709A, 0x9ED5, + 0x709B, 0x9ED6, 0x709C, 0xECBF, 0x709D, 0xECC1, 0x709E, 0x9ED7, 0x709F, 0x9ED8, 0x70A0, 0x9ED9, 0x70A1, 0x9EDA, 0x70A2, 0x9EDB, + 0x70A3, 0x9EDC, 0x70A4, 0x9EDD, 0x70A5, 0x9EDE, 0x70A6, 0x9EDF, 0x70A7, 0x9EE0, 0x70A8, 0x9EE1, 0x70A9, 0x9EE2, 0x70AA, 0x9EE3, + 0x70AB, 0xECC5, 0x70AC, 0xBEE6, 0x70AD, 0xCCBF, 0x70AE, 0xC5DA, 0x70AF, 0xBEBC, 0x70B0, 0x9EE4, 0x70B1, 0xECC6, 0x70B2, 0x9EE5, + 0x70B3, 0xB1FE, 0x70B4, 0x9EE6, 0x70B5, 0x9EE7, 0x70B6, 0x9EE8, 0x70B7, 0xECC4, 0x70B8, 0xD5A8, 0x70B9, 0xB5E3, 0x70BA, 0x9EE9, + 0x70BB, 0xECC2, 0x70BC, 0xC1B6, 0x70BD, 0xB3E3, 0x70BE, 0x9EEA, 0x70BF, 0x9EEB, 0x70C0, 0xECC3, 0x70C1, 0xCBB8, 0x70C2, 0xC0C3, + 0x70C3, 0xCCFE, 0x70C4, 0x9EEC, 0x70C5, 0x9EED, 0x70C6, 0x9EEE, 0x70C7, 0x9EEF, 0x70C8, 0xC1D2, 0x70C9, 0x9EF0, 0x70CA, 0xECC8, + 0x70CB, 0x9EF1, 0x70CC, 0x9EF2, 0x70CD, 0x9EF3, 0x70CE, 0x9EF4, 0x70CF, 0x9EF5, 0x70D0, 0x9EF6, 0x70D1, 0x9EF7, 0x70D2, 0x9EF8, + 0x70D3, 0x9EF9, 0x70D4, 0x9EFA, 0x70D5, 0x9EFB, 0x70D6, 0x9EFC, 0x70D7, 0x9EFD, 0x70D8, 0xBAE6, 0x70D9, 0xC0D3, 0x70DA, 0x9EFE, + 0x70DB, 0xD6F2, 0x70DC, 0x9F40, 0x70DD, 0x9F41, 0x70DE, 0x9F42, 0x70DF, 0xD1CC, 0x70E0, 0x9F43, 0x70E1, 0x9F44, 0x70E2, 0x9F45, + 0x70E3, 0x9F46, 0x70E4, 0xBFBE, 0x70E5, 0x9F47, 0x70E6, 0xB7B3, 0x70E7, 0xC9D5, 0x70E8, 0xECC7, 0x70E9, 0xBBE2, 0x70EA, 0x9F48, + 0x70EB, 0xCCCC, 0x70EC, 0xBDFD, 0x70ED, 0xC8C8, 0x70EE, 0x9F49, 0x70EF, 0xCFA9, 0x70F0, 0x9F4A, 0x70F1, 0x9F4B, 0x70F2, 0x9F4C, + 0x70F3, 0x9F4D, 0x70F4, 0x9F4E, 0x70F5, 0x9F4F, 0x70F6, 0x9F50, 0x70F7, 0xCDE9, 0x70F8, 0x9F51, 0x70F9, 0xC5EB, 0x70FA, 0x9F52, + 0x70FB, 0x9F53, 0x70FC, 0x9F54, 0x70FD, 0xB7E9, 0x70FE, 0x9F55, 0x70FF, 0x9F56, 0x7100, 0x9F57, 0x7101, 0x9F58, 0x7102, 0x9F59, + 0x7103, 0x9F5A, 0x7104, 0x9F5B, 0x7105, 0x9F5C, 0x7106, 0x9F5D, 0x7107, 0x9F5E, 0x7108, 0x9F5F, 0x7109, 0xD1C9, 0x710A, 0xBAB8, + 0x710B, 0x9F60, 0x710C, 0x9F61, 0x710D, 0x9F62, 0x710E, 0x9F63, 0x710F, 0x9F64, 0x7110, 0xECC9, 0x7111, 0x9F65, 0x7112, 0x9F66, + 0x7113, 0xECCA, 0x7114, 0x9F67, 0x7115, 0xBBC0, 0x7116, 0xECCB, 0x7117, 0x9F68, 0x7118, 0xECE2, 0x7119, 0xB1BA, 0x711A, 0xB7D9, + 0x711B, 0x9F69, 0x711C, 0x9F6A, 0x711D, 0x9F6B, 0x711E, 0x9F6C, 0x711F, 0x9F6D, 0x7120, 0x9F6E, 0x7121, 0x9F6F, 0x7122, 0x9F70, + 0x7123, 0x9F71, 0x7124, 0x9F72, 0x7125, 0x9F73, 0x7126, 0xBDB9, 0x7127, 0x9F74, 0x7128, 0x9F75, 0x7129, 0x9F76, 0x712A, 0x9F77, + 0x712B, 0x9F78, 0x712C, 0x9F79, 0x712D, 0x9F7A, 0x712E, 0x9F7B, 0x712F, 0xECCC, 0x7130, 0xD1E6, 0x7131, 0xECCD, 0x7132, 0x9F7C, + 0x7133, 0x9F7D, 0x7134, 0x9F7E, 0x7135, 0x9F80, 0x7136, 0xC8BB, 0x7137, 0x9F81, 0x7138, 0x9F82, 0x7139, 0x9F83, 0x713A, 0x9F84, + 0x713B, 0x9F85, 0x713C, 0x9F86, 0x713D, 0x9F87, 0x713E, 0x9F88, 0x713F, 0x9F89, 0x7140, 0x9F8A, 0x7141, 0x9F8B, 0x7142, 0x9F8C, + 0x7143, 0x9F8D, 0x7144, 0x9F8E, 0x7145, 0xECD1, 0x7146, 0x9F8F, 0x7147, 0x9F90, 0x7148, 0x9F91, 0x7149, 0x9F92, 0x714A, 0xECD3, + 0x714B, 0x9F93, 0x714C, 0xBBCD, 0x714D, 0x9F94, 0x714E, 0xBCE5, 0x714F, 0x9F95, 0x7150, 0x9F96, 0x7151, 0x9F97, 0x7152, 0x9F98, + 0x7153, 0x9F99, 0x7154, 0x9F9A, 0x7155, 0x9F9B, 0x7156, 0x9F9C, 0x7157, 0x9F9D, 0x7158, 0x9F9E, 0x7159, 0x9F9F, 0x715A, 0x9FA0, + 0x715B, 0x9FA1, 0x715C, 0xECCF, 0x715D, 0x9FA2, 0x715E, 0xC9B7, 0x715F, 0x9FA3, 0x7160, 0x9FA4, 0x7161, 0x9FA5, 0x7162, 0x9FA6, + 0x7163, 0x9FA7, 0x7164, 0xC3BA, 0x7165, 0x9FA8, 0x7166, 0xECE3, 0x7167, 0xD5D5, 0x7168, 0xECD0, 0x7169, 0x9FA9, 0x716A, 0x9FAA, + 0x716B, 0x9FAB, 0x716C, 0x9FAC, 0x716D, 0x9FAD, 0x716E, 0xD6F3, 0x716F, 0x9FAE, 0x7170, 0x9FAF, 0x7171, 0x9FB0, 0x7172, 0xECD2, + 0x7173, 0xECCE, 0x7174, 0x9FB1, 0x7175, 0x9FB2, 0x7176, 0x9FB3, 0x7177, 0x9FB4, 0x7178, 0xECD4, 0x7179, 0x9FB5, 0x717A, 0xECD5, + 0x717B, 0x9FB6, 0x717C, 0x9FB7, 0x717D, 0xC9BF, 0x717E, 0x9FB8, 0x717F, 0x9FB9, 0x7180, 0x9FBA, 0x7181, 0x9FBB, 0x7182, 0x9FBC, + 0x7183, 0x9FBD, 0x7184, 0xCFA8, 0x7185, 0x9FBE, 0x7186, 0x9FBF, 0x7187, 0x9FC0, 0x7188, 0x9FC1, 0x7189, 0x9FC2, 0x718A, 0xD0DC, + 0x718B, 0x9FC3, 0x718C, 0x9FC4, 0x718D, 0x9FC5, 0x718E, 0x9FC6, 0x718F, 0xD1AC, 0x7190, 0x9FC7, 0x7191, 0x9FC8, 0x7192, 0x9FC9, + 0x7193, 0x9FCA, 0x7194, 0xC8DB, 0x7195, 0x9FCB, 0x7196, 0x9FCC, 0x7197, 0x9FCD, 0x7198, 0xECD6, 0x7199, 0xCEF5, 0x719A, 0x9FCE, + 0x719B, 0x9FCF, 0x719C, 0x9FD0, 0x719D, 0x9FD1, 0x719E, 0x9FD2, 0x719F, 0xCAEC, 0x71A0, 0xECDA, 0x71A1, 0x9FD3, 0x71A2, 0x9FD4, + 0x71A3, 0x9FD5, 0x71A4, 0x9FD6, 0x71A5, 0x9FD7, 0x71A6, 0x9FD8, 0x71A7, 0x9FD9, 0x71A8, 0xECD9, 0x71A9, 0x9FDA, 0x71AA, 0x9FDB, + 0x71AB, 0x9FDC, 0x71AC, 0xB0BE, 0x71AD, 0x9FDD, 0x71AE, 0x9FDE, 0x71AF, 0x9FDF, 0x71B0, 0x9FE0, 0x71B1, 0x9FE1, 0x71B2, 0x9FE2, + 0x71B3, 0xECD7, 0x71B4, 0x9FE3, 0x71B5, 0xECD8, 0x71B6, 0x9FE4, 0x71B7, 0x9FE5, 0x71B8, 0x9FE6, 0x71B9, 0xECE4, 0x71BA, 0x9FE7, + 0x71BB, 0x9FE8, 0x71BC, 0x9FE9, 0x71BD, 0x9FEA, 0x71BE, 0x9FEB, 0x71BF, 0x9FEC, 0x71C0, 0x9FED, 0x71C1, 0x9FEE, 0x71C2, 0x9FEF, + 0x71C3, 0xC8BC, 0x71C4, 0x9FF0, 0x71C5, 0x9FF1, 0x71C6, 0x9FF2, 0x71C7, 0x9FF3, 0x71C8, 0x9FF4, 0x71C9, 0x9FF5, 0x71CA, 0x9FF6, + 0x71CB, 0x9FF7, 0x71CC, 0x9FF8, 0x71CD, 0x9FF9, 0x71CE, 0xC1C7, 0x71CF, 0x9FFA, 0x71D0, 0x9FFB, 0x71D1, 0x9FFC, 0x71D2, 0x9FFD, + 0x71D3, 0x9FFE, 0x71D4, 0xECDC, 0x71D5, 0xD1E0, 0x71D6, 0xA040, 0x71D7, 0xA041, 0x71D8, 0xA042, 0x71D9, 0xA043, 0x71DA, 0xA044, + 0x71DB, 0xA045, 0x71DC, 0xA046, 0x71DD, 0xA047, 0x71DE, 0xA048, 0x71DF, 0xA049, 0x71E0, 0xECDB, 0x71E1, 0xA04A, 0x71E2, 0xA04B, + 0x71E3, 0xA04C, 0x71E4, 0xA04D, 0x71E5, 0xD4EF, 0x71E6, 0xA04E, 0x71E7, 0xECDD, 0x71E8, 0xA04F, 0x71E9, 0xA050, 0x71EA, 0xA051, + 0x71EB, 0xA052, 0x71EC, 0xA053, 0x71ED, 0xA054, 0x71EE, 0xDBC6, 0x71EF, 0xA055, 0x71F0, 0xA056, 0x71F1, 0xA057, 0x71F2, 0xA058, + 0x71F3, 0xA059, 0x71F4, 0xA05A, 0x71F5, 0xA05B, 0x71F6, 0xA05C, 0x71F7, 0xA05D, 0x71F8, 0xA05E, 0x71F9, 0xECDE, 0x71FA, 0xA05F, + 0x71FB, 0xA060, 0x71FC, 0xA061, 0x71FD, 0xA062, 0x71FE, 0xA063, 0x71FF, 0xA064, 0x7200, 0xA065, 0x7201, 0xA066, 0x7202, 0xA067, + 0x7203, 0xA068, 0x7204, 0xA069, 0x7205, 0xA06A, 0x7206, 0xB1AC, 0x7207, 0xA06B, 0x7208, 0xA06C, 0x7209, 0xA06D, 0x720A, 0xA06E, + 0x720B, 0xA06F, 0x720C, 0xA070, 0x720D, 0xA071, 0x720E, 0xA072, 0x720F, 0xA073, 0x7210, 0xA074, 0x7211, 0xA075, 0x7212, 0xA076, + 0x7213, 0xA077, 0x7214, 0xA078, 0x7215, 0xA079, 0x7216, 0xA07A, 0x7217, 0xA07B, 0x7218, 0xA07C, 0x7219, 0xA07D, 0x721A, 0xA07E, + 0x721B, 0xA080, 0x721C, 0xA081, 0x721D, 0xECDF, 0x721E, 0xA082, 0x721F, 0xA083, 0x7220, 0xA084, 0x7221, 0xA085, 0x7222, 0xA086, + 0x7223, 0xA087, 0x7224, 0xA088, 0x7225, 0xA089, 0x7226, 0xA08A, 0x7227, 0xA08B, 0x7228, 0xECE0, 0x7229, 0xA08C, 0x722A, 0xD7A6, + 0x722B, 0xA08D, 0x722C, 0xC5C0, 0x722D, 0xA08E, 0x722E, 0xA08F, 0x722F, 0xA090, 0x7230, 0xEBBC, 0x7231, 0xB0AE, 0x7232, 0xA091, + 0x7233, 0xA092, 0x7234, 0xA093, 0x7235, 0xBEF4, 0x7236, 0xB8B8, 0x7237, 0xD2AF, 0x7238, 0xB0D6, 0x7239, 0xB5F9, 0x723A, 0xA094, + 0x723B, 0xD8B3, 0x723C, 0xA095, 0x723D, 0xCBAC, 0x723E, 0xA096, 0x723F, 0xE3DD, 0x7240, 0xA097, 0x7241, 0xA098, 0x7242, 0xA099, + 0x7243, 0xA09A, 0x7244, 0xA09B, 0x7245, 0xA09C, 0x7246, 0xA09D, 0x7247, 0xC6AC, 0x7248, 0xB0E6, 0x7249, 0xA09E, 0x724A, 0xA09F, + 0x724B, 0xA0A0, 0x724C, 0xC5C6, 0x724D, 0xEBB9, 0x724E, 0xA0A1, 0x724F, 0xA0A2, 0x7250, 0xA0A3, 0x7251, 0xA0A4, 0x7252, 0xEBBA, + 0x7253, 0xA0A5, 0x7254, 0xA0A6, 0x7255, 0xA0A7, 0x7256, 0xEBBB, 0x7257, 0xA0A8, 0x7258, 0xA0A9, 0x7259, 0xD1C0, 0x725A, 0xA0AA, + 0x725B, 0xC5A3, 0x725C, 0xA0AB, 0x725D, 0xEAF2, 0x725E, 0xA0AC, 0x725F, 0xC4B2, 0x7260, 0xA0AD, 0x7261, 0xC4B5, 0x7262, 0xC0CE, + 0x7263, 0xA0AE, 0x7264, 0xA0AF, 0x7265, 0xA0B0, 0x7266, 0xEAF3, 0x7267, 0xC4C1, 0x7268, 0xA0B1, 0x7269, 0xCEEF, 0x726A, 0xA0B2, + 0x726B, 0xA0B3, 0x726C, 0xA0B4, 0x726D, 0xA0B5, 0x726E, 0xEAF0, 0x726F, 0xEAF4, 0x7270, 0xA0B6, 0x7271, 0xA0B7, 0x7272, 0xC9FC, + 0x7273, 0xA0B8, 0x7274, 0xA0B9, 0x7275, 0xC7A3, 0x7276, 0xA0BA, 0x7277, 0xA0BB, 0x7278, 0xA0BC, 0x7279, 0xCCD8, 0x727A, 0xCEFE, + 0x727B, 0xA0BD, 0x727C, 0xA0BE, 0x727D, 0xA0BF, 0x727E, 0xEAF5, 0x727F, 0xEAF6, 0x7280, 0xCFAC, 0x7281, 0xC0E7, 0x7282, 0xA0C0, + 0x7283, 0xA0C1, 0x7284, 0xEAF7, 0x7285, 0xA0C2, 0x7286, 0xA0C3, 0x7287, 0xA0C4, 0x7288, 0xA0C5, 0x7289, 0xA0C6, 0x728A, 0xB6BF, + 0x728B, 0xEAF8, 0x728C, 0xA0C7, 0x728D, 0xEAF9, 0x728E, 0xA0C8, 0x728F, 0xEAFA, 0x7290, 0xA0C9, 0x7291, 0xA0CA, 0x7292, 0xEAFB, + 0x7293, 0xA0CB, 0x7294, 0xA0CC, 0x7295, 0xA0CD, 0x7296, 0xA0CE, 0x7297, 0xA0CF, 0x7298, 0xA0D0, 0x7299, 0xA0D1, 0x729A, 0xA0D2, + 0x729B, 0xA0D3, 0x729C, 0xA0D4, 0x729D, 0xA0D5, 0x729E, 0xA0D6, 0x729F, 0xEAF1, 0x72A0, 0xA0D7, 0x72A1, 0xA0D8, 0x72A2, 0xA0D9, + 0x72A3, 0xA0DA, 0x72A4, 0xA0DB, 0x72A5, 0xA0DC, 0x72A6, 0xA0DD, 0x72A7, 0xA0DE, 0x72A8, 0xA0DF, 0x72A9, 0xA0E0, 0x72AA, 0xA0E1, + 0x72AB, 0xA0E2, 0x72AC, 0xC8AE, 0x72AD, 0xE1EB, 0x72AE, 0xA0E3, 0x72AF, 0xB7B8, 0x72B0, 0xE1EC, 0x72B1, 0xA0E4, 0x72B2, 0xA0E5, + 0x72B3, 0xA0E6, 0x72B4, 0xE1ED, 0x72B5, 0xA0E7, 0x72B6, 0xD7B4, 0x72B7, 0xE1EE, 0x72B8, 0xE1EF, 0x72B9, 0xD3CC, 0x72BA, 0xA0E8, + 0x72BB, 0xA0E9, 0x72BC, 0xA0EA, 0x72BD, 0xA0EB, 0x72BE, 0xA0EC, 0x72BF, 0xA0ED, 0x72C0, 0xA0EE, 0x72C1, 0xE1F1, 0x72C2, 0xBFF1, + 0x72C3, 0xE1F0, 0x72C4, 0xB5D2, 0x72C5, 0xA0EF, 0x72C6, 0xA0F0, 0x72C7, 0xA0F1, 0x72C8, 0xB1B7, 0x72C9, 0xA0F2, 0x72CA, 0xA0F3, + 0x72CB, 0xA0F4, 0x72CC, 0xA0F5, 0x72CD, 0xE1F3, 0x72CE, 0xE1F2, 0x72CF, 0xA0F6, 0x72D0, 0xBAFC, 0x72D1, 0xA0F7, 0x72D2, 0xE1F4, + 0x72D3, 0xA0F8, 0x72D4, 0xA0F9, 0x72D5, 0xA0FA, 0x72D6, 0xA0FB, 0x72D7, 0xB9B7, 0x72D8, 0xA0FC, 0x72D9, 0xBED1, 0x72DA, 0xA0FD, + 0x72DB, 0xA0FE, 0x72DC, 0xAA40, 0x72DD, 0xAA41, 0x72DE, 0xC4FC, 0x72DF, 0xAA42, 0x72E0, 0xBADD, 0x72E1, 0xBDC6, 0x72E2, 0xAA43, + 0x72E3, 0xAA44, 0x72E4, 0xAA45, 0x72E5, 0xAA46, 0x72E6, 0xAA47, 0x72E7, 0xAA48, 0x72E8, 0xE1F5, 0x72E9, 0xE1F7, 0x72EA, 0xAA49, + 0x72EB, 0xAA4A, 0x72EC, 0xB6C0, 0x72ED, 0xCFC1, 0x72EE, 0xCAA8, 0x72EF, 0xE1F6, 0x72F0, 0xD5F8, 0x72F1, 0xD3FC, 0x72F2, 0xE1F8, + 0x72F3, 0xE1FC, 0x72F4, 0xE1F9, 0x72F5, 0xAA4B, 0x72F6, 0xAA4C, 0x72F7, 0xE1FA, 0x72F8, 0xC0EA, 0x72F9, 0xAA4D, 0x72FA, 0xE1FE, + 0x72FB, 0xE2A1, 0x72FC, 0xC0C7, 0x72FD, 0xAA4E, 0x72FE, 0xAA4F, 0x72FF, 0xAA50, 0x7300, 0xAA51, 0x7301, 0xE1FB, 0x7302, 0xAA52, + 0x7303, 0xE1FD, 0x7304, 0xAA53, 0x7305, 0xAA54, 0x7306, 0xAA55, 0x7307, 0xAA56, 0x7308, 0xAA57, 0x7309, 0xAA58, 0x730A, 0xE2A5, + 0x730B, 0xAA59, 0x730C, 0xAA5A, 0x730D, 0xAA5B, 0x730E, 0xC1D4, 0x730F, 0xAA5C, 0x7310, 0xAA5D, 0x7311, 0xAA5E, 0x7312, 0xAA5F, + 0x7313, 0xE2A3, 0x7314, 0xAA60, 0x7315, 0xE2A8, 0x7316, 0xB2FE, 0x7317, 0xE2A2, 0x7318, 0xAA61, 0x7319, 0xAA62, 0x731A, 0xAA63, + 0x731B, 0xC3CD, 0x731C, 0xB2C2, 0x731D, 0xE2A7, 0x731E, 0xE2A6, 0x731F, 0xAA64, 0x7320, 0xAA65, 0x7321, 0xE2A4, 0x7322, 0xE2A9, + 0x7323, 0xAA66, 0x7324, 0xAA67, 0x7325, 0xE2AB, 0x7326, 0xAA68, 0x7327, 0xAA69, 0x7328, 0xAA6A, 0x7329, 0xD0C9, 0x732A, 0xD6ED, + 0x732B, 0xC3A8, 0x732C, 0xE2AC, 0x732D, 0xAA6B, 0x732E, 0xCFD7, 0x732F, 0xAA6C, 0x7330, 0xAA6D, 0x7331, 0xE2AE, 0x7332, 0xAA6E, + 0x7333, 0xAA6F, 0x7334, 0xBAEF, 0x7335, 0xAA70, 0x7336, 0xAA71, 0x7337, 0xE9E0, 0x7338, 0xE2AD, 0x7339, 0xE2AA, 0x733A, 0xAA72, + 0x733B, 0xAA73, 0x733C, 0xAA74, 0x733D, 0xAA75, 0x733E, 0xBBAB, 0x733F, 0xD4B3, 0x7340, 0xAA76, 0x7341, 0xAA77, 0x7342, 0xAA78, + 0x7343, 0xAA79, 0x7344, 0xAA7A, 0x7345, 0xAA7B, 0x7346, 0xAA7C, 0x7347, 0xAA7D, 0x7348, 0xAA7E, 0x7349, 0xAA80, 0x734A, 0xAA81, + 0x734B, 0xAA82, 0x734C, 0xAA83, 0x734D, 0xE2B0, 0x734E, 0xAA84, 0x734F, 0xAA85, 0x7350, 0xE2AF, 0x7351, 0xAA86, 0x7352, 0xE9E1, + 0x7353, 0xAA87, 0x7354, 0xAA88, 0x7355, 0xAA89, 0x7356, 0xAA8A, 0x7357, 0xE2B1, 0x7358, 0xAA8B, 0x7359, 0xAA8C, 0x735A, 0xAA8D, + 0x735B, 0xAA8E, 0x735C, 0xAA8F, 0x735D, 0xAA90, 0x735E, 0xAA91, 0x735F, 0xAA92, 0x7360, 0xE2B2, 0x7361, 0xAA93, 0x7362, 0xAA94, + 0x7363, 0xAA95, 0x7364, 0xAA96, 0x7365, 0xAA97, 0x7366, 0xAA98, 0x7367, 0xAA99, 0x7368, 0xAA9A, 0x7369, 0xAA9B, 0x736A, 0xAA9C, + 0x736B, 0xAA9D, 0x736C, 0xE2B3, 0x736D, 0xCCA1, 0x736E, 0xAA9E, 0x736F, 0xE2B4, 0x7370, 0xAA9F, 0x7371, 0xAAA0, 0x7372, 0xAB40, + 0x7373, 0xAB41, 0x7374, 0xAB42, 0x7375, 0xAB43, 0x7376, 0xAB44, 0x7377, 0xAB45, 0x7378, 0xAB46, 0x7379, 0xAB47, 0x737A, 0xAB48, + 0x737B, 0xAB49, 0x737C, 0xAB4A, 0x737D, 0xAB4B, 0x737E, 0xE2B5, 0x737F, 0xAB4C, 0x7380, 0xAB4D, 0x7381, 0xAB4E, 0x7382, 0xAB4F, + 0x7383, 0xAB50, 0x7384, 0xD0FE, 0x7385, 0xAB51, 0x7386, 0xAB52, 0x7387, 0xC2CA, 0x7388, 0xAB53, 0x7389, 0xD3F1, 0x738A, 0xAB54, + 0x738B, 0xCDF5, 0x738C, 0xAB55, 0x738D, 0xAB56, 0x738E, 0xE7E0, 0x738F, 0xAB57, 0x7390, 0xAB58, 0x7391, 0xE7E1, 0x7392, 0xAB59, + 0x7393, 0xAB5A, 0x7394, 0xAB5B, 0x7395, 0xAB5C, 0x7396, 0xBEC1, 0x7397, 0xAB5D, 0x7398, 0xAB5E, 0x7399, 0xAB5F, 0x739A, 0xAB60, + 0x739B, 0xC2EA, 0x739C, 0xAB61, 0x739D, 0xAB62, 0x739E, 0xAB63, 0x739F, 0xE7E4, 0x73A0, 0xAB64, 0x73A1, 0xAB65, 0x73A2, 0xE7E3, + 0x73A3, 0xAB66, 0x73A4, 0xAB67, 0x73A5, 0xAB68, 0x73A6, 0xAB69, 0x73A7, 0xAB6A, 0x73A8, 0xAB6B, 0x73A9, 0xCDE6, 0x73AA, 0xAB6C, + 0x73AB, 0xC3B5, 0x73AC, 0xAB6D, 0x73AD, 0xAB6E, 0x73AE, 0xE7E2, 0x73AF, 0xBBB7, 0x73B0, 0xCFD6, 0x73B1, 0xAB6F, 0x73B2, 0xC1E1, + 0x73B3, 0xE7E9, 0x73B4, 0xAB70, 0x73B5, 0xAB71, 0x73B6, 0xAB72, 0x73B7, 0xE7E8, 0x73B8, 0xAB73, 0x73B9, 0xAB74, 0x73BA, 0xE7F4, + 0x73BB, 0xB2A3, 0x73BC, 0xAB75, 0x73BD, 0xAB76, 0x73BE, 0xAB77, 0x73BF, 0xAB78, 0x73C0, 0xE7EA, 0x73C1, 0xAB79, 0x73C2, 0xE7E6, + 0x73C3, 0xAB7A, 0x73C4, 0xAB7B, 0x73C5, 0xAB7C, 0x73C6, 0xAB7D, 0x73C7, 0xAB7E, 0x73C8, 0xE7EC, 0x73C9, 0xE7EB, 0x73CA, 0xC9BA, + 0x73CB, 0xAB80, 0x73CC, 0xAB81, 0x73CD, 0xD5E4, 0x73CE, 0xAB82, 0x73CF, 0xE7E5, 0x73D0, 0xB7A9, 0x73D1, 0xE7E7, 0x73D2, 0xAB83, + 0x73D3, 0xAB84, 0x73D4, 0xAB85, 0x73D5, 0xAB86, 0x73D6, 0xAB87, 0x73D7, 0xAB88, 0x73D8, 0xAB89, 0x73D9, 0xE7EE, 0x73DA, 0xAB8A, + 0x73DB, 0xAB8B, 0x73DC, 0xAB8C, 0x73DD, 0xAB8D, 0x73DE, 0xE7F3, 0x73DF, 0xAB8E, 0x73E0, 0xD6E9, 0x73E1, 0xAB8F, 0x73E2, 0xAB90, + 0x73E3, 0xAB91, 0x73E4, 0xAB92, 0x73E5, 0xE7ED, 0x73E6, 0xAB93, 0x73E7, 0xE7F2, 0x73E8, 0xAB94, 0x73E9, 0xE7F1, 0x73EA, 0xAB95, + 0x73EB, 0xAB96, 0x73EC, 0xAB97, 0x73ED, 0xB0E0, 0x73EE, 0xAB98, 0x73EF, 0xAB99, 0x73F0, 0xAB9A, 0x73F1, 0xAB9B, 0x73F2, 0xE7F5, + 0x73F3, 0xAB9C, 0x73F4, 0xAB9D, 0x73F5, 0xAB9E, 0x73F6, 0xAB9F, 0x73F7, 0xABA0, 0x73F8, 0xAC40, 0x73F9, 0xAC41, 0x73FA, 0xAC42, + 0x73FB, 0xAC43, 0x73FC, 0xAC44, 0x73FD, 0xAC45, 0x73FE, 0xAC46, 0x73FF, 0xAC47, 0x7400, 0xAC48, 0x7401, 0xAC49, 0x7402, 0xAC4A, + 0x7403, 0xC7F2, 0x7404, 0xAC4B, 0x7405, 0xC0C5, 0x7406, 0xC0ED, 0x7407, 0xAC4C, 0x7408, 0xAC4D, 0x7409, 0xC1F0, 0x740A, 0xE7F0, + 0x740B, 0xAC4E, 0x740C, 0xAC4F, 0x740D, 0xAC50, 0x740E, 0xAC51, 0x740F, 0xE7F6, 0x7410, 0xCBF6, 0x7411, 0xAC52, 0x7412, 0xAC53, + 0x7413, 0xAC54, 0x7414, 0xAC55, 0x7415, 0xAC56, 0x7416, 0xAC57, 0x7417, 0xAC58, 0x7418, 0xAC59, 0x7419, 0xAC5A, 0x741A, 0xE8A2, + 0x741B, 0xE8A1, 0x741C, 0xAC5B, 0x741D, 0xAC5C, 0x741E, 0xAC5D, 0x741F, 0xAC5E, 0x7420, 0xAC5F, 0x7421, 0xAC60, 0x7422, 0xD7C1, + 0x7423, 0xAC61, 0x7424, 0xAC62, 0x7425, 0xE7FA, 0x7426, 0xE7F9, 0x7427, 0xAC63, 0x7428, 0xE7FB, 0x7429, 0xAC64, 0x742A, 0xE7F7, + 0x742B, 0xAC65, 0x742C, 0xE7FE, 0x742D, 0xAC66, 0x742E, 0xE7FD, 0x742F, 0xAC67, 0x7430, 0xE7FC, 0x7431, 0xAC68, 0x7432, 0xAC69, + 0x7433, 0xC1D5, 0x7434, 0xC7D9, 0x7435, 0xC5FD, 0x7436, 0xC5C3, 0x7437, 0xAC6A, 0x7438, 0xAC6B, 0x7439, 0xAC6C, 0x743A, 0xAC6D, + 0x743B, 0xAC6E, 0x743C, 0xC7ED, 0x743D, 0xAC6F, 0x743E, 0xAC70, 0x743F, 0xAC71, 0x7440, 0xAC72, 0x7441, 0xE8A3, 0x7442, 0xAC73, + 0x7443, 0xAC74, 0x7444, 0xAC75, 0x7445, 0xAC76, 0x7446, 0xAC77, 0x7447, 0xAC78, 0x7448, 0xAC79, 0x7449, 0xAC7A, 0x744A, 0xAC7B, + 0x744B, 0xAC7C, 0x744C, 0xAC7D, 0x744D, 0xAC7E, 0x744E, 0xAC80, 0x744F, 0xAC81, 0x7450, 0xAC82, 0x7451, 0xAC83, 0x7452, 0xAC84, + 0x7453, 0xAC85, 0x7454, 0xAC86, 0x7455, 0xE8A6, 0x7456, 0xAC87, 0x7457, 0xE8A5, 0x7458, 0xAC88, 0x7459, 0xE8A7, 0x745A, 0xBAF7, + 0x745B, 0xE7F8, 0x745C, 0xE8A4, 0x745D, 0xAC89, 0x745E, 0xC8F0, 0x745F, 0xC9AA, 0x7460, 0xAC8A, 0x7461, 0xAC8B, 0x7462, 0xAC8C, + 0x7463, 0xAC8D, 0x7464, 0xAC8E, 0x7465, 0xAC8F, 0x7466, 0xAC90, 0x7467, 0xAC91, 0x7468, 0xAC92, 0x7469, 0xAC93, 0x746A, 0xAC94, + 0x746B, 0xAC95, 0x746C, 0xAC96, 0x746D, 0xE8A9, 0x746E, 0xAC97, 0x746F, 0xAC98, 0x7470, 0xB9E5, 0x7471, 0xAC99, 0x7472, 0xAC9A, + 0x7473, 0xAC9B, 0x7474, 0xAC9C, 0x7475, 0xAC9D, 0x7476, 0xD1FE, 0x7477, 0xE8A8, 0x7478, 0xAC9E, 0x7479, 0xAC9F, 0x747A, 0xACA0, + 0x747B, 0xAD40, 0x747C, 0xAD41, 0x747D, 0xAD42, 0x747E, 0xE8AA, 0x747F, 0xAD43, 0x7480, 0xE8AD, 0x7481, 0xE8AE, 0x7482, 0xAD44, + 0x7483, 0xC1A7, 0x7484, 0xAD45, 0x7485, 0xAD46, 0x7486, 0xAD47, 0x7487, 0xE8AF, 0x7488, 0xAD48, 0x7489, 0xAD49, 0x748A, 0xAD4A, + 0x748B, 0xE8B0, 0x748C, 0xAD4B, 0x748D, 0xAD4C, 0x748E, 0xE8AC, 0x748F, 0xAD4D, 0x7490, 0xE8B4, 0x7491, 0xAD4E, 0x7492, 0xAD4F, + 0x7493, 0xAD50, 0x7494, 0xAD51, 0x7495, 0xAD52, 0x7496, 0xAD53, 0x7497, 0xAD54, 0x7498, 0xAD55, 0x7499, 0xAD56, 0x749A, 0xAD57, + 0x749B, 0xAD58, 0x749C, 0xE8AB, 0x749D, 0xAD59, 0x749E, 0xE8B1, 0x749F, 0xAD5A, 0x74A0, 0xAD5B, 0x74A1, 0xAD5C, 0x74A2, 0xAD5D, + 0x74A3, 0xAD5E, 0x74A4, 0xAD5F, 0x74A5, 0xAD60, 0x74A6, 0xAD61, 0x74A7, 0xE8B5, 0x74A8, 0xE8B2, 0x74A9, 0xE8B3, 0x74AA, 0xAD62, + 0x74AB, 0xAD63, 0x74AC, 0xAD64, 0x74AD, 0xAD65, 0x74AE, 0xAD66, 0x74AF, 0xAD67, 0x74B0, 0xAD68, 0x74B1, 0xAD69, 0x74B2, 0xAD6A, + 0x74B3, 0xAD6B, 0x74B4, 0xAD6C, 0x74B5, 0xAD6D, 0x74B6, 0xAD6E, 0x74B7, 0xAD6F, 0x74B8, 0xAD70, 0x74B9, 0xAD71, 0x74BA, 0xE8B7, + 0x74BB, 0xAD72, 0x74BC, 0xAD73, 0x74BD, 0xAD74, 0x74BE, 0xAD75, 0x74BF, 0xAD76, 0x74C0, 0xAD77, 0x74C1, 0xAD78, 0x74C2, 0xAD79, + 0x74C3, 0xAD7A, 0x74C4, 0xAD7B, 0x74C5, 0xAD7C, 0x74C6, 0xAD7D, 0x74C7, 0xAD7E, 0x74C8, 0xAD80, 0x74C9, 0xAD81, 0x74CA, 0xAD82, + 0x74CB, 0xAD83, 0x74CC, 0xAD84, 0x74CD, 0xAD85, 0x74CE, 0xAD86, 0x74CF, 0xAD87, 0x74D0, 0xAD88, 0x74D1, 0xAD89, 0x74D2, 0xE8B6, + 0x74D3, 0xAD8A, 0x74D4, 0xAD8B, 0x74D5, 0xAD8C, 0x74D6, 0xAD8D, 0x74D7, 0xAD8E, 0x74D8, 0xAD8F, 0x74D9, 0xAD90, 0x74DA, 0xAD91, + 0x74DB, 0xAD92, 0x74DC, 0xB9CF, 0x74DD, 0xAD93, 0x74DE, 0xF0AC, 0x74DF, 0xAD94, 0x74E0, 0xF0AD, 0x74E1, 0xAD95, 0x74E2, 0xC6B0, + 0x74E3, 0xB0EA, 0x74E4, 0xC8BF, 0x74E5, 0xAD96, 0x74E6, 0xCDDF, 0x74E7, 0xAD97, 0x74E8, 0xAD98, 0x74E9, 0xAD99, 0x74EA, 0xAD9A, + 0x74EB, 0xAD9B, 0x74EC, 0xAD9C, 0x74ED, 0xAD9D, 0x74EE, 0xCECD, 0x74EF, 0xEAB1, 0x74F0, 0xAD9E, 0x74F1, 0xAD9F, 0x74F2, 0xADA0, + 0x74F3, 0xAE40, 0x74F4, 0xEAB2, 0x74F5, 0xAE41, 0x74F6, 0xC6BF, 0x74F7, 0xB4C9, 0x74F8, 0xAE42, 0x74F9, 0xAE43, 0x74FA, 0xAE44, + 0x74FB, 0xAE45, 0x74FC, 0xAE46, 0x74FD, 0xAE47, 0x74FE, 0xAE48, 0x74FF, 0xEAB3, 0x7500, 0xAE49, 0x7501, 0xAE4A, 0x7502, 0xAE4B, + 0x7503, 0xAE4C, 0x7504, 0xD5E7, 0x7505, 0xAE4D, 0x7506, 0xAE4E, 0x7507, 0xAE4F, 0x7508, 0xAE50, 0x7509, 0xAE51, 0x750A, 0xAE52, + 0x750B, 0xAE53, 0x750C, 0xAE54, 0x750D, 0xDDF9, 0x750E, 0xAE55, 0x750F, 0xEAB4, 0x7510, 0xAE56, 0x7511, 0xEAB5, 0x7512, 0xAE57, + 0x7513, 0xEAB6, 0x7514, 0xAE58, 0x7515, 0xAE59, 0x7516, 0xAE5A, 0x7517, 0xAE5B, 0x7518, 0xB8CA, 0x7519, 0xDFB0, 0x751A, 0xC9F5, + 0x751B, 0xAE5C, 0x751C, 0xCCF0, 0x751D, 0xAE5D, 0x751E, 0xAE5E, 0x751F, 0xC9FA, 0x7520, 0xAE5F, 0x7521, 0xAE60, 0x7522, 0xAE61, + 0x7523, 0xAE62, 0x7524, 0xAE63, 0x7525, 0xC9FB, 0x7526, 0xAE64, 0x7527, 0xAE65, 0x7528, 0xD3C3, 0x7529, 0xCBA6, 0x752A, 0xAE66, + 0x752B, 0xB8A6, 0x752C, 0xF0AE, 0x752D, 0xB1C2, 0x752E, 0xAE67, 0x752F, 0xE5B8, 0x7530, 0xCCEF, 0x7531, 0xD3C9, 0x7532, 0xBCD7, + 0x7533, 0xC9EA, 0x7534, 0xAE68, 0x7535, 0xB5E7, 0x7536, 0xAE69, 0x7537, 0xC4D0, 0x7538, 0xB5E9, 0x7539, 0xAE6A, 0x753A, 0xEEAE, + 0x753B, 0xBBAD, 0x753C, 0xAE6B, 0x753D, 0xAE6C, 0x753E, 0xE7DE, 0x753F, 0xAE6D, 0x7540, 0xEEAF, 0x7541, 0xAE6E, 0x7542, 0xAE6F, + 0x7543, 0xAE70, 0x7544, 0xAE71, 0x7545, 0xB3A9, 0x7546, 0xAE72, 0x7547, 0xAE73, 0x7548, 0xEEB2, 0x7549, 0xAE74, 0x754A, 0xAE75, + 0x754B, 0xEEB1, 0x754C, 0xBDE7, 0x754D, 0xAE76, 0x754E, 0xEEB0, 0x754F, 0xCEB7, 0x7550, 0xAE77, 0x7551, 0xAE78, 0x7552, 0xAE79, + 0x7553, 0xAE7A, 0x7554, 0xC5CF, 0x7555, 0xAE7B, 0x7556, 0xAE7C, 0x7557, 0xAE7D, 0x7558, 0xAE7E, 0x7559, 0xC1F4, 0x755A, 0xDBCE, + 0x755B, 0xEEB3, 0x755C, 0xD0F3, 0x755D, 0xAE80, 0x755E, 0xAE81, 0x755F, 0xAE82, 0x7560, 0xAE83, 0x7561, 0xAE84, 0x7562, 0xAE85, + 0x7563, 0xAE86, 0x7564, 0xAE87, 0x7565, 0xC2D4, 0x7566, 0xC6E8, 0x7567, 0xAE88, 0x7568, 0xAE89, 0x7569, 0xAE8A, 0x756A, 0xB7AC, + 0x756B, 0xAE8B, 0x756C, 0xAE8C, 0x756D, 0xAE8D, 0x756E, 0xAE8E, 0x756F, 0xAE8F, 0x7570, 0xAE90, 0x7571, 0xAE91, 0x7572, 0xEEB4, + 0x7573, 0xAE92, 0x7574, 0xB3EB, 0x7575, 0xAE93, 0x7576, 0xAE94, 0x7577, 0xAE95, 0x7578, 0xBBFB, 0x7579, 0xEEB5, 0x757A, 0xAE96, + 0x757B, 0xAE97, 0x757C, 0xAE98, 0x757D, 0xAE99, 0x757E, 0xAE9A, 0x757F, 0xE7DC, 0x7580, 0xAE9B, 0x7581, 0xAE9C, 0x7582, 0xAE9D, + 0x7583, 0xEEB6, 0x7584, 0xAE9E, 0x7585, 0xAE9F, 0x7586, 0xBDAE, 0x7587, 0xAEA0, 0x7588, 0xAF40, 0x7589, 0xAF41, 0x758A, 0xAF42, + 0x758B, 0xF1E2, 0x758C, 0xAF43, 0x758D, 0xAF44, 0x758E, 0xAF45, 0x758F, 0xCAE8, 0x7590, 0xAF46, 0x7591, 0xD2C9, 0x7592, 0xF0DA, + 0x7593, 0xAF47, 0x7594, 0xF0DB, 0x7595, 0xAF48, 0x7596, 0xF0DC, 0x7597, 0xC1C6, 0x7598, 0xAF49, 0x7599, 0xB8ED, 0x759A, 0xBECE, + 0x759B, 0xAF4A, 0x759C, 0xAF4B, 0x759D, 0xF0DE, 0x759E, 0xAF4C, 0x759F, 0xC5B1, 0x75A0, 0xF0DD, 0x75A1, 0xD1F1, 0x75A2, 0xAF4D, + 0x75A3, 0xF0E0, 0x75A4, 0xB0CC, 0x75A5, 0xBDEA, 0x75A6, 0xAF4E, 0x75A7, 0xAF4F, 0x75A8, 0xAF50, 0x75A9, 0xAF51, 0x75AA, 0xAF52, + 0x75AB, 0xD2DF, 0x75AC, 0xF0DF, 0x75AD, 0xAF53, 0x75AE, 0xB4AF, 0x75AF, 0xB7E8, 0x75B0, 0xF0E6, 0x75B1, 0xF0E5, 0x75B2, 0xC6A3, + 0x75B3, 0xF0E1, 0x75B4, 0xF0E2, 0x75B5, 0xB4C3, 0x75B6, 0xAF54, 0x75B7, 0xAF55, 0x75B8, 0xF0E3, 0x75B9, 0xD5EE, 0x75BA, 0xAF56, + 0x75BB, 0xAF57, 0x75BC, 0xCCDB, 0x75BD, 0xBED2, 0x75BE, 0xBCB2, 0x75BF, 0xAF58, 0x75C0, 0xAF59, 0x75C1, 0xAF5A, 0x75C2, 0xF0E8, + 0x75C3, 0xF0E7, 0x75C4, 0xF0E4, 0x75C5, 0xB2A1, 0x75C6, 0xAF5B, 0x75C7, 0xD6A2, 0x75C8, 0xD3B8, 0x75C9, 0xBEB7, 0x75CA, 0xC8AC, + 0x75CB, 0xAF5C, 0x75CC, 0xAF5D, 0x75CD, 0xF0EA, 0x75CE, 0xAF5E, 0x75CF, 0xAF5F, 0x75D0, 0xAF60, 0x75D1, 0xAF61, 0x75D2, 0xD1F7, + 0x75D3, 0xAF62, 0x75D4, 0xD6CC, 0x75D5, 0xBADB, 0x75D6, 0xF0E9, 0x75D7, 0xAF63, 0x75D8, 0xB6BB, 0x75D9, 0xAF64, 0x75DA, 0xAF65, + 0x75DB, 0xCDB4, 0x75DC, 0xAF66, 0x75DD, 0xAF67, 0x75DE, 0xC6A6, 0x75DF, 0xAF68, 0x75E0, 0xAF69, 0x75E1, 0xAF6A, 0x75E2, 0xC1A1, + 0x75E3, 0xF0EB, 0x75E4, 0xF0EE, 0x75E5, 0xAF6B, 0x75E6, 0xF0ED, 0x75E7, 0xF0F0, 0x75E8, 0xF0EC, 0x75E9, 0xAF6C, 0x75EA, 0xBBBE, + 0x75EB, 0xF0EF, 0x75EC, 0xAF6D, 0x75ED, 0xAF6E, 0x75EE, 0xAF6F, 0x75EF, 0xAF70, 0x75F0, 0xCCB5, 0x75F1, 0xF0F2, 0x75F2, 0xAF71, + 0x75F3, 0xAF72, 0x75F4, 0xB3D5, 0x75F5, 0xAF73, 0x75F6, 0xAF74, 0x75F7, 0xAF75, 0x75F8, 0xAF76, 0x75F9, 0xB1D4, 0x75FA, 0xAF77, + 0x75FB, 0xAF78, 0x75FC, 0xF0F3, 0x75FD, 0xAF79, 0x75FE, 0xAF7A, 0x75FF, 0xF0F4, 0x7600, 0xF0F6, 0x7601, 0xB4E1, 0x7602, 0xAF7B, + 0x7603, 0xF0F1, 0x7604, 0xAF7C, 0x7605, 0xF0F7, 0x7606, 0xAF7D, 0x7607, 0xAF7E, 0x7608, 0xAF80, 0x7609, 0xAF81, 0x760A, 0xF0FA, + 0x760B, 0xAF82, 0x760C, 0xF0F8, 0x760D, 0xAF83, 0x760E, 0xAF84, 0x760F, 0xAF85, 0x7610, 0xF0F5, 0x7611, 0xAF86, 0x7612, 0xAF87, + 0x7613, 0xAF88, 0x7614, 0xAF89, 0x7615, 0xF0FD, 0x7616, 0xAF8A, 0x7617, 0xF0F9, 0x7618, 0xF0FC, 0x7619, 0xF0FE, 0x761A, 0xAF8B, + 0x761B, 0xF1A1, 0x761C, 0xAF8C, 0x761D, 0xAF8D, 0x761E, 0xAF8E, 0x761F, 0xCEC1, 0x7620, 0xF1A4, 0x7621, 0xAF8F, 0x7622, 0xF1A3, + 0x7623, 0xAF90, 0x7624, 0xC1F6, 0x7625, 0xF0FB, 0x7626, 0xCADD, 0x7627, 0xAF91, 0x7628, 0xAF92, 0x7629, 0xB4F1, 0x762A, 0xB1F1, + 0x762B, 0xCCB1, 0x762C, 0xAF93, 0x762D, 0xF1A6, 0x762E, 0xAF94, 0x762F, 0xAF95, 0x7630, 0xF1A7, 0x7631, 0xAF96, 0x7632, 0xAF97, + 0x7633, 0xF1AC, 0x7634, 0xD5CE, 0x7635, 0xF1A9, 0x7636, 0xAF98, 0x7637, 0xAF99, 0x7638, 0xC8B3, 0x7639, 0xAF9A, 0x763A, 0xAF9B, + 0x763B, 0xAF9C, 0x763C, 0xF1A2, 0x763D, 0xAF9D, 0x763E, 0xF1AB, 0x763F, 0xF1A8, 0x7640, 0xF1A5, 0x7641, 0xAF9E, 0x7642, 0xAF9F, + 0x7643, 0xF1AA, 0x7644, 0xAFA0, 0x7645, 0xB040, 0x7646, 0xB041, 0x7647, 0xB042, 0x7648, 0xB043, 0x7649, 0xB044, 0x764A, 0xB045, + 0x764B, 0xB046, 0x764C, 0xB0A9, 0x764D, 0xF1AD, 0x764E, 0xB047, 0x764F, 0xB048, 0x7650, 0xB049, 0x7651, 0xB04A, 0x7652, 0xB04B, + 0x7653, 0xB04C, 0x7654, 0xF1AF, 0x7655, 0xB04D, 0x7656, 0xF1B1, 0x7657, 0xB04E, 0x7658, 0xB04F, 0x7659, 0xB050, 0x765A, 0xB051, + 0x765B, 0xB052, 0x765C, 0xF1B0, 0x765D, 0xB053, 0x765E, 0xF1AE, 0x765F, 0xB054, 0x7660, 0xB055, 0x7661, 0xB056, 0x7662, 0xB057, + 0x7663, 0xD1A2, 0x7664, 0xB058, 0x7665, 0xB059, 0x7666, 0xB05A, 0x7667, 0xB05B, 0x7668, 0xB05C, 0x7669, 0xB05D, 0x766A, 0xB05E, + 0x766B, 0xF1B2, 0x766C, 0xB05F, 0x766D, 0xB060, 0x766E, 0xB061, 0x766F, 0xF1B3, 0x7670, 0xB062, 0x7671, 0xB063, 0x7672, 0xB064, + 0x7673, 0xB065, 0x7674, 0xB066, 0x7675, 0xB067, 0x7676, 0xB068, 0x7677, 0xB069, 0x7678, 0xB9EF, 0x7679, 0xB06A, 0x767A, 0xB06B, + 0x767B, 0xB5C7, 0x767C, 0xB06C, 0x767D, 0xB0D7, 0x767E, 0xB0D9, 0x767F, 0xB06D, 0x7680, 0xB06E, 0x7681, 0xB06F, 0x7682, 0xD4ED, + 0x7683, 0xB070, 0x7684, 0xB5C4, 0x7685, 0xB071, 0x7686, 0xBDD4, 0x7687, 0xBBCA, 0x7688, 0xF0A7, 0x7689, 0xB072, 0x768A, 0xB073, + 0x768B, 0xB8DE, 0x768C, 0xB074, 0x768D, 0xB075, 0x768E, 0xF0A8, 0x768F, 0xB076, 0x7690, 0xB077, 0x7691, 0xB0A8, 0x7692, 0xB078, + 0x7693, 0xF0A9, 0x7694, 0xB079, 0x7695, 0xB07A, 0x7696, 0xCDEE, 0x7697, 0xB07B, 0x7698, 0xB07C, 0x7699, 0xF0AA, 0x769A, 0xB07D, + 0x769B, 0xB07E, 0x769C, 0xB080, 0x769D, 0xB081, 0x769E, 0xB082, 0x769F, 0xB083, 0x76A0, 0xB084, 0x76A1, 0xB085, 0x76A2, 0xB086, + 0x76A3, 0xB087, 0x76A4, 0xF0AB, 0x76A5, 0xB088, 0x76A6, 0xB089, 0x76A7, 0xB08A, 0x76A8, 0xB08B, 0x76A9, 0xB08C, 0x76AA, 0xB08D, + 0x76AB, 0xB08E, 0x76AC, 0xB08F, 0x76AD, 0xB090, 0x76AE, 0xC6A4, 0x76AF, 0xB091, 0x76B0, 0xB092, 0x76B1, 0xD6E5, 0x76B2, 0xF1E4, + 0x76B3, 0xB093, 0x76B4, 0xF1E5, 0x76B5, 0xB094, 0x76B6, 0xB095, 0x76B7, 0xB096, 0x76B8, 0xB097, 0x76B9, 0xB098, 0x76BA, 0xB099, + 0x76BB, 0xB09A, 0x76BC, 0xB09B, 0x76BD, 0xB09C, 0x76BE, 0xB09D, 0x76BF, 0xC3F3, 0x76C0, 0xB09E, 0x76C1, 0xB09F, 0x76C2, 0xD3DB, + 0x76C3, 0xB0A0, 0x76C4, 0xB140, 0x76C5, 0xD6D1, 0x76C6, 0xC5E8, 0x76C7, 0xB141, 0x76C8, 0xD3AF, 0x76C9, 0xB142, 0x76CA, 0xD2E6, + 0x76CB, 0xB143, 0x76CC, 0xB144, 0x76CD, 0xEEC1, 0x76CE, 0xB0BB, 0x76CF, 0xD5B5, 0x76D0, 0xD1CE, 0x76D1, 0xBCE0, 0x76D2, 0xBAD0, + 0x76D3, 0xB145, 0x76D4, 0xBFF8, 0x76D5, 0xB146, 0x76D6, 0xB8C7, 0x76D7, 0xB5C1, 0x76D8, 0xC5CC, 0x76D9, 0xB147, 0x76DA, 0xB148, + 0x76DB, 0xCAA2, 0x76DC, 0xB149, 0x76DD, 0xB14A, 0x76DE, 0xB14B, 0x76DF, 0xC3CB, 0x76E0, 0xB14C, 0x76E1, 0xB14D, 0x76E2, 0xB14E, + 0x76E3, 0xB14F, 0x76E4, 0xB150, 0x76E5, 0xEEC2, 0x76E6, 0xB151, 0x76E7, 0xB152, 0x76E8, 0xB153, 0x76E9, 0xB154, 0x76EA, 0xB155, + 0x76EB, 0xB156, 0x76EC, 0xB157, 0x76ED, 0xB158, 0x76EE, 0xC4BF, 0x76EF, 0xB6A2, 0x76F0, 0xB159, 0x76F1, 0xEDEC, 0x76F2, 0xC3A4, + 0x76F3, 0xB15A, 0x76F4, 0xD6B1, 0x76F5, 0xB15B, 0x76F6, 0xB15C, 0x76F7, 0xB15D, 0x76F8, 0xCFE0, 0x76F9, 0xEDEF, 0x76FA, 0xB15E, + 0x76FB, 0xB15F, 0x76FC, 0xC5CE, 0x76FD, 0xB160, 0x76FE, 0xB6DC, 0x76FF, 0xB161, 0x7700, 0xB162, 0x7701, 0xCAA1, 0x7702, 0xB163, + 0x7703, 0xB164, 0x7704, 0xEDED, 0x7705, 0xB165, 0x7706, 0xB166, 0x7707, 0xEDF0, 0x7708, 0xEDF1, 0x7709, 0xC3BC, 0x770A, 0xB167, + 0x770B, 0xBFB4, 0x770C, 0xB168, 0x770D, 0xEDEE, 0x770E, 0xB169, 0x770F, 0xB16A, 0x7710, 0xB16B, 0x7711, 0xB16C, 0x7712, 0xB16D, + 0x7713, 0xB16E, 0x7714, 0xB16F, 0x7715, 0xB170, 0x7716, 0xB171, 0x7717, 0xB172, 0x7718, 0xB173, 0x7719, 0xEDF4, 0x771A, 0xEDF2, + 0x771B, 0xB174, 0x771C, 0xB175, 0x771D, 0xB176, 0x771E, 0xB177, 0x771F, 0xD5E6, 0x7720, 0xC3DF, 0x7721, 0xB178, 0x7722, 0xEDF3, + 0x7723, 0xB179, 0x7724, 0xB17A, 0x7725, 0xB17B, 0x7726, 0xEDF6, 0x7727, 0xB17C, 0x7728, 0xD5A3, 0x7729, 0xD1A3, 0x772A, 0xB17D, + 0x772B, 0xB17E, 0x772C, 0xB180, 0x772D, 0xEDF5, 0x772E, 0xB181, 0x772F, 0xC3D0, 0x7730, 0xB182, 0x7731, 0xB183, 0x7732, 0xB184, + 0x7733, 0xB185, 0x7734, 0xB186, 0x7735, 0xEDF7, 0x7736, 0xBFF4, 0x7737, 0xBEEC, 0x7738, 0xEDF8, 0x7739, 0xB187, 0x773A, 0xCCF7, + 0x773B, 0xB188, 0x773C, 0xD1DB, 0x773D, 0xB189, 0x773E, 0xB18A, 0x773F, 0xB18B, 0x7740, 0xD7C5, 0x7741, 0xD5F6, 0x7742, 0xB18C, + 0x7743, 0xEDFC, 0x7744, 0xB18D, 0x7745, 0xB18E, 0x7746, 0xB18F, 0x7747, 0xEDFB, 0x7748, 0xB190, 0x7749, 0xB191, 0x774A, 0xB192, + 0x774B, 0xB193, 0x774C, 0xB194, 0x774D, 0xB195, 0x774E, 0xB196, 0x774F, 0xB197, 0x7750, 0xEDF9, 0x7751, 0xEDFA, 0x7752, 0xB198, + 0x7753, 0xB199, 0x7754, 0xB19A, 0x7755, 0xB19B, 0x7756, 0xB19C, 0x7757, 0xB19D, 0x7758, 0xB19E, 0x7759, 0xB19F, 0x775A, 0xEDFD, + 0x775B, 0xBEA6, 0x775C, 0xB1A0, 0x775D, 0xB240, 0x775E, 0xB241, 0x775F, 0xB242, 0x7760, 0xB243, 0x7761, 0xCBAF, 0x7762, 0xEEA1, + 0x7763, 0xB6BD, 0x7764, 0xB244, 0x7765, 0xEEA2, 0x7766, 0xC4C0, 0x7767, 0xB245, 0x7768, 0xEDFE, 0x7769, 0xB246, 0x776A, 0xB247, + 0x776B, 0xBDDE, 0x776C, 0xB2C7, 0x776D, 0xB248, 0x776E, 0xB249, 0x776F, 0xB24A, 0x7770, 0xB24B, 0x7771, 0xB24C, 0x7772, 0xB24D, + 0x7773, 0xB24E, 0x7774, 0xB24F, 0x7775, 0xB250, 0x7776, 0xB251, 0x7777, 0xB252, 0x7778, 0xB253, 0x7779, 0xB6C3, 0x777A, 0xB254, + 0x777B, 0xB255, 0x777C, 0xB256, 0x777D, 0xEEA5, 0x777E, 0xD8BA, 0x777F, 0xEEA3, 0x7780, 0xEEA6, 0x7781, 0xB257, 0x7782, 0xB258, + 0x7783, 0xB259, 0x7784, 0xC3E9, 0x7785, 0xB3F2, 0x7786, 0xB25A, 0x7787, 0xB25B, 0x7788, 0xB25C, 0x7789, 0xB25D, 0x778A, 0xB25E, + 0x778B, 0xB25F, 0x778C, 0xEEA7, 0x778D, 0xEEA4, 0x778E, 0xCFB9, 0x778F, 0xB260, 0x7790, 0xB261, 0x7791, 0xEEA8, 0x7792, 0xC2F7, + 0x7793, 0xB262, 0x7794, 0xB263, 0x7795, 0xB264, 0x7796, 0xB265, 0x7797, 0xB266, 0x7798, 0xB267, 0x7799, 0xB268, 0x779A, 0xB269, + 0x779B, 0xB26A, 0x779C, 0xB26B, 0x779D, 0xB26C, 0x779E, 0xB26D, 0x779F, 0xEEA9, 0x77A0, 0xEEAA, 0x77A1, 0xB26E, 0x77A2, 0xDEAB, + 0x77A3, 0xB26F, 0x77A4, 0xB270, 0x77A5, 0xC6B3, 0x77A6, 0xB271, 0x77A7, 0xC7C6, 0x77A8, 0xB272, 0x77A9, 0xD6F5, 0x77AA, 0xB5C9, + 0x77AB, 0xB273, 0x77AC, 0xCBB2, 0x77AD, 0xB274, 0x77AE, 0xB275, 0x77AF, 0xB276, 0x77B0, 0xEEAB, 0x77B1, 0xB277, 0x77B2, 0xB278, + 0x77B3, 0xCDAB, 0x77B4, 0xB279, 0x77B5, 0xEEAC, 0x77B6, 0xB27A, 0x77B7, 0xB27B, 0x77B8, 0xB27C, 0x77B9, 0xB27D, 0x77BA, 0xB27E, + 0x77BB, 0xD5B0, 0x77BC, 0xB280, 0x77BD, 0xEEAD, 0x77BE, 0xB281, 0x77BF, 0xF6C4, 0x77C0, 0xB282, 0x77C1, 0xB283, 0x77C2, 0xB284, + 0x77C3, 0xB285, 0x77C4, 0xB286, 0x77C5, 0xB287, 0x77C6, 0xB288, 0x77C7, 0xB289, 0x77C8, 0xB28A, 0x77C9, 0xB28B, 0x77CA, 0xB28C, + 0x77CB, 0xB28D, 0x77CC, 0xB28E, 0x77CD, 0xDBC7, 0x77CE, 0xB28F, 0x77CF, 0xB290, 0x77D0, 0xB291, 0x77D1, 0xB292, 0x77D2, 0xB293, + 0x77D3, 0xB294, 0x77D4, 0xB295, 0x77D5, 0xB296, 0x77D6, 0xB297, 0x77D7, 0xB4A3, 0x77D8, 0xB298, 0x77D9, 0xB299, 0x77DA, 0xB29A, + 0x77DB, 0xC3AC, 0x77DC, 0xF1E6, 0x77DD, 0xB29B, 0x77DE, 0xB29C, 0x77DF, 0xB29D, 0x77E0, 0xB29E, 0x77E1, 0xB29F, 0x77E2, 0xCAB8, + 0x77E3, 0xD2D3, 0x77E4, 0xB2A0, 0x77E5, 0xD6AA, 0x77E6, 0xB340, 0x77E7, 0xEFF2, 0x77E8, 0xB341, 0x77E9, 0xBED8, 0x77EA, 0xB342, + 0x77EB, 0xBDC3, 0x77EC, 0xEFF3, 0x77ED, 0xB6CC, 0x77EE, 0xB0AB, 0x77EF, 0xB343, 0x77F0, 0xB344, 0x77F1, 0xB345, 0x77F2, 0xB346, + 0x77F3, 0xCAAF, 0x77F4, 0xB347, 0x77F5, 0xB348, 0x77F6, 0xEDB6, 0x77F7, 0xB349, 0x77F8, 0xEDB7, 0x77F9, 0xB34A, 0x77FA, 0xB34B, + 0x77FB, 0xB34C, 0x77FC, 0xB34D, 0x77FD, 0xCEF9, 0x77FE, 0xB7AF, 0x77FF, 0xBFF3, 0x7800, 0xEDB8, 0x7801, 0xC2EB, 0x7802, 0xC9B0, + 0x7803, 0xB34E, 0x7804, 0xB34F, 0x7805, 0xB350, 0x7806, 0xB351, 0x7807, 0xB352, 0x7808, 0xB353, 0x7809, 0xEDB9, 0x780A, 0xB354, + 0x780B, 0xB355, 0x780C, 0xC6F6, 0x780D, 0xBFB3, 0x780E, 0xB356, 0x780F, 0xB357, 0x7810, 0xB358, 0x7811, 0xEDBC, 0x7812, 0xC5F8, + 0x7813, 0xB359, 0x7814, 0xD1D0, 0x7815, 0xB35A, 0x7816, 0xD7A9, 0x7817, 0xEDBA, 0x7818, 0xEDBB, 0x7819, 0xB35B, 0x781A, 0xD1E2, + 0x781B, 0xB35C, 0x781C, 0xEDBF, 0x781D, 0xEDC0, 0x781E, 0xB35D, 0x781F, 0xEDC4, 0x7820, 0xB35E, 0x7821, 0xB35F, 0x7822, 0xB360, + 0x7823, 0xEDC8, 0x7824, 0xB361, 0x7825, 0xEDC6, 0x7826, 0xEDCE, 0x7827, 0xD5E8, 0x7828, 0xB362, 0x7829, 0xEDC9, 0x782A, 0xB363, + 0x782B, 0xB364, 0x782C, 0xEDC7, 0x782D, 0xEDBE, 0x782E, 0xB365, 0x782F, 0xB366, 0x7830, 0xC5E9, 0x7831, 0xB367, 0x7832, 0xB368, + 0x7833, 0xB369, 0x7834, 0xC6C6, 0x7835, 0xB36A, 0x7836, 0xB36B, 0x7837, 0xC9E9, 0x7838, 0xD4D2, 0x7839, 0xEDC1, 0x783A, 0xEDC2, + 0x783B, 0xEDC3, 0x783C, 0xEDC5, 0x783D, 0xB36C, 0x783E, 0xC0F9, 0x783F, 0xB36D, 0x7840, 0xB4A1, 0x7841, 0xB36E, 0x7842, 0xB36F, + 0x7843, 0xB370, 0x7844, 0xB371, 0x7845, 0xB9E8, 0x7846, 0xB372, 0x7847, 0xEDD0, 0x7848, 0xB373, 0x7849, 0xB374, 0x784A, 0xB375, + 0x784B, 0xB376, 0x784C, 0xEDD1, 0x784D, 0xB377, 0x784E, 0xEDCA, 0x784F, 0xB378, 0x7850, 0xEDCF, 0x7851, 0xB379, 0x7852, 0xCEF8, + 0x7853, 0xB37A, 0x7854, 0xB37B, 0x7855, 0xCBB6, 0x7856, 0xEDCC, 0x7857, 0xEDCD, 0x7858, 0xB37C, 0x7859, 0xB37D, 0x785A, 0xB37E, + 0x785B, 0xB380, 0x785C, 0xB381, 0x785D, 0xCFF5, 0x785E, 0xB382, 0x785F, 0xB383, 0x7860, 0xB384, 0x7861, 0xB385, 0x7862, 0xB386, + 0x7863, 0xB387, 0x7864, 0xB388, 0x7865, 0xB389, 0x7866, 0xB38A, 0x7867, 0xB38B, 0x7868, 0xB38C, 0x7869, 0xB38D, 0x786A, 0xEDD2, + 0x786B, 0xC1F2, 0x786C, 0xD3B2, 0x786D, 0xEDCB, 0x786E, 0xC8B7, 0x786F, 0xB38E, 0x7870, 0xB38F, 0x7871, 0xB390, 0x7872, 0xB391, + 0x7873, 0xB392, 0x7874, 0xB393, 0x7875, 0xB394, 0x7876, 0xB395, 0x7877, 0xBCEF, 0x7878, 0xB396, 0x7879, 0xB397, 0x787A, 0xB398, + 0x787B, 0xB399, 0x787C, 0xC5F0, 0x787D, 0xB39A, 0x787E, 0xB39B, 0x787F, 0xB39C, 0x7880, 0xB39D, 0x7881, 0xB39E, 0x7882, 0xB39F, + 0x7883, 0xB3A0, 0x7884, 0xB440, 0x7885, 0xB441, 0x7886, 0xB442, 0x7887, 0xEDD6, 0x7888, 0xB443, 0x7889, 0xB5EF, 0x788A, 0xB444, + 0x788B, 0xB445, 0x788C, 0xC2B5, 0x788D, 0xB0AD, 0x788E, 0xCBE9, 0x788F, 0xB446, 0x7890, 0xB447, 0x7891, 0xB1AE, 0x7892, 0xB448, + 0x7893, 0xEDD4, 0x7894, 0xB449, 0x7895, 0xB44A, 0x7896, 0xB44B, 0x7897, 0xCDEB, 0x7898, 0xB5E2, 0x7899, 0xB44C, 0x789A, 0xEDD5, + 0x789B, 0xEDD3, 0x789C, 0xEDD7, 0x789D, 0xB44D, 0x789E, 0xB44E, 0x789F, 0xB5FA, 0x78A0, 0xB44F, 0x78A1, 0xEDD8, 0x78A2, 0xB450, + 0x78A3, 0xEDD9, 0x78A4, 0xB451, 0x78A5, 0xEDDC, 0x78A6, 0xB452, 0x78A7, 0xB1CC, 0x78A8, 0xB453, 0x78A9, 0xB454, 0x78AA, 0xB455, + 0x78AB, 0xB456, 0x78AC, 0xB457, 0x78AD, 0xB458, 0x78AE, 0xB459, 0x78AF, 0xB45A, 0x78B0, 0xC5F6, 0x78B1, 0xBCEE, 0x78B2, 0xEDDA, + 0x78B3, 0xCCBC, 0x78B4, 0xB2EA, 0x78B5, 0xB45B, 0x78B6, 0xB45C, 0x78B7, 0xB45D, 0x78B8, 0xB45E, 0x78B9, 0xEDDB, 0x78BA, 0xB45F, + 0x78BB, 0xB460, 0x78BC, 0xB461, 0x78BD, 0xB462, 0x78BE, 0xC4EB, 0x78BF, 0xB463, 0x78C0, 0xB464, 0x78C1, 0xB4C5, 0x78C2, 0xB465, + 0x78C3, 0xB466, 0x78C4, 0xB467, 0x78C5, 0xB0F5, 0x78C6, 0xB468, 0x78C7, 0xB469, 0x78C8, 0xB46A, 0x78C9, 0xEDDF, 0x78CA, 0xC0DA, + 0x78CB, 0xB4E8, 0x78CC, 0xB46B, 0x78CD, 0xB46C, 0x78CE, 0xB46D, 0x78CF, 0xB46E, 0x78D0, 0xC5CD, 0x78D1, 0xB46F, 0x78D2, 0xB470, + 0x78D3, 0xB471, 0x78D4, 0xEDDD, 0x78D5, 0xBFC4, 0x78D6, 0xB472, 0x78D7, 0xB473, 0x78D8, 0xB474, 0x78D9, 0xEDDE, 0x78DA, 0xB475, + 0x78DB, 0xB476, 0x78DC, 0xB477, 0x78DD, 0xB478, 0x78DE, 0xB479, 0x78DF, 0xB47A, 0x78E0, 0xB47B, 0x78E1, 0xB47C, 0x78E2, 0xB47D, + 0x78E3, 0xB47E, 0x78E4, 0xB480, 0x78E5, 0xB481, 0x78E6, 0xB482, 0x78E7, 0xB483, 0x78E8, 0xC4A5, 0x78E9, 0xB484, 0x78EA, 0xB485, + 0x78EB, 0xB486, 0x78EC, 0xEDE0, 0x78ED, 0xB487, 0x78EE, 0xB488, 0x78EF, 0xB489, 0x78F0, 0xB48A, 0x78F1, 0xB48B, 0x78F2, 0xEDE1, + 0x78F3, 0xB48C, 0x78F4, 0xEDE3, 0x78F5, 0xB48D, 0x78F6, 0xB48E, 0x78F7, 0xC1D7, 0x78F8, 0xB48F, 0x78F9, 0xB490, 0x78FA, 0xBBC7, + 0x78FB, 0xB491, 0x78FC, 0xB492, 0x78FD, 0xB493, 0x78FE, 0xB494, 0x78FF, 0xB495, 0x7900, 0xB496, 0x7901, 0xBDB8, 0x7902, 0xB497, + 0x7903, 0xB498, 0x7904, 0xB499, 0x7905, 0xEDE2, 0x7906, 0xB49A, 0x7907, 0xB49B, 0x7908, 0xB49C, 0x7909, 0xB49D, 0x790A, 0xB49E, + 0x790B, 0xB49F, 0x790C, 0xB4A0, 0x790D, 0xB540, 0x790E, 0xB541, 0x790F, 0xB542, 0x7910, 0xB543, 0x7911, 0xB544, 0x7912, 0xB545, + 0x7913, 0xEDE4, 0x7914, 0xB546, 0x7915, 0xB547, 0x7916, 0xB548, 0x7917, 0xB549, 0x7918, 0xB54A, 0x7919, 0xB54B, 0x791A, 0xB54C, + 0x791B, 0xB54D, 0x791C, 0xB54E, 0x791D, 0xB54F, 0x791E, 0xEDE6, 0x791F, 0xB550, 0x7920, 0xB551, 0x7921, 0xB552, 0x7922, 0xB553, + 0x7923, 0xB554, 0x7924, 0xEDE5, 0x7925, 0xB555, 0x7926, 0xB556, 0x7927, 0xB557, 0x7928, 0xB558, 0x7929, 0xB559, 0x792A, 0xB55A, + 0x792B, 0xB55B, 0x792C, 0xB55C, 0x792D, 0xB55D, 0x792E, 0xB55E, 0x792F, 0xB55F, 0x7930, 0xB560, 0x7931, 0xB561, 0x7932, 0xB562, + 0x7933, 0xB563, 0x7934, 0xEDE7, 0x7935, 0xB564, 0x7936, 0xB565, 0x7937, 0xB566, 0x7938, 0xB567, 0x7939, 0xB568, 0x793A, 0xCABE, + 0x793B, 0xECEA, 0x793C, 0xC0F1, 0x793D, 0xB569, 0x793E, 0xC9E7, 0x793F, 0xB56A, 0x7940, 0xECEB, 0x7941, 0xC6EE, 0x7942, 0xB56B, + 0x7943, 0xB56C, 0x7944, 0xB56D, 0x7945, 0xB56E, 0x7946, 0xECEC, 0x7947, 0xB56F, 0x7948, 0xC6ED, 0x7949, 0xECED, 0x794A, 0xB570, + 0x794B, 0xB571, 0x794C, 0xB572, 0x794D, 0xB573, 0x794E, 0xB574, 0x794F, 0xB575, 0x7950, 0xB576, 0x7951, 0xB577, 0x7952, 0xB578, + 0x7953, 0xECF0, 0x7954, 0xB579, 0x7955, 0xB57A, 0x7956, 0xD7E6, 0x7957, 0xECF3, 0x7958, 0xB57B, 0x7959, 0xB57C, 0x795A, 0xECF1, + 0x795B, 0xECEE, 0x795C, 0xECEF, 0x795D, 0xD7A3, 0x795E, 0xC9F1, 0x795F, 0xCBEE, 0x7960, 0xECF4, 0x7961, 0xB57D, 0x7962, 0xECF2, + 0x7963, 0xB57E, 0x7964, 0xB580, 0x7965, 0xCFE9, 0x7966, 0xB581, 0x7967, 0xECF6, 0x7968, 0xC6B1, 0x7969, 0xB582, 0x796A, 0xB583, + 0x796B, 0xB584, 0x796C, 0xB585, 0x796D, 0xBCC0, 0x796E, 0xB586, 0x796F, 0xECF5, 0x7970, 0xB587, 0x7971, 0xB588, 0x7972, 0xB589, + 0x7973, 0xB58A, 0x7974, 0xB58B, 0x7975, 0xB58C, 0x7976, 0xB58D, 0x7977, 0xB5BB, 0x7978, 0xBBF6, 0x7979, 0xB58E, 0x797A, 0xECF7, + 0x797B, 0xB58F, 0x797C, 0xB590, 0x797D, 0xB591, 0x797E, 0xB592, 0x797F, 0xB593, 0x7980, 0xD9F7, 0x7981, 0xBDFB, 0x7982, 0xB594, + 0x7983, 0xB595, 0x7984, 0xC2BB, 0x7985, 0xECF8, 0x7986, 0xB596, 0x7987, 0xB597, 0x7988, 0xB598, 0x7989, 0xB599, 0x798A, 0xECF9, + 0x798B, 0xB59A, 0x798C, 0xB59B, 0x798D, 0xB59C, 0x798E, 0xB59D, 0x798F, 0xB8A3, 0x7990, 0xB59E, 0x7991, 0xB59F, 0x7992, 0xB5A0, + 0x7993, 0xB640, 0x7994, 0xB641, 0x7995, 0xB642, 0x7996, 0xB643, 0x7997, 0xB644, 0x7998, 0xB645, 0x7999, 0xB646, 0x799A, 0xECFA, + 0x799B, 0xB647, 0x799C, 0xB648, 0x799D, 0xB649, 0x799E, 0xB64A, 0x799F, 0xB64B, 0x79A0, 0xB64C, 0x79A1, 0xB64D, 0x79A2, 0xB64E, + 0x79A3, 0xB64F, 0x79A4, 0xB650, 0x79A5, 0xB651, 0x79A6, 0xB652, 0x79A7, 0xECFB, 0x79A8, 0xB653, 0x79A9, 0xB654, 0x79AA, 0xB655, + 0x79AB, 0xB656, 0x79AC, 0xB657, 0x79AD, 0xB658, 0x79AE, 0xB659, 0x79AF, 0xB65A, 0x79B0, 0xB65B, 0x79B1, 0xB65C, 0x79B2, 0xB65D, + 0x79B3, 0xECFC, 0x79B4, 0xB65E, 0x79B5, 0xB65F, 0x79B6, 0xB660, 0x79B7, 0xB661, 0x79B8, 0xB662, 0x79B9, 0xD3ED, 0x79BA, 0xD8AE, + 0x79BB, 0xC0EB, 0x79BC, 0xB663, 0x79BD, 0xC7DD, 0x79BE, 0xBACC, 0x79BF, 0xB664, 0x79C0, 0xD0E3, 0x79C1, 0xCBBD, 0x79C2, 0xB665, + 0x79C3, 0xCDBA, 0x79C4, 0xB666, 0x79C5, 0xB667, 0x79C6, 0xB8D1, 0x79C7, 0xB668, 0x79C8, 0xB669, 0x79C9, 0xB1FC, 0x79CA, 0xB66A, + 0x79CB, 0xC7EF, 0x79CC, 0xB66B, 0x79CD, 0xD6D6, 0x79CE, 0xB66C, 0x79CF, 0xB66D, 0x79D0, 0xB66E, 0x79D1, 0xBFC6, 0x79D2, 0xC3EB, + 0x79D3, 0xB66F, 0x79D4, 0xB670, 0x79D5, 0xEFF5, 0x79D6, 0xB671, 0x79D7, 0xB672, 0x79D8, 0xC3D8, 0x79D9, 0xB673, 0x79DA, 0xB674, + 0x79DB, 0xB675, 0x79DC, 0xB676, 0x79DD, 0xB677, 0x79DE, 0xB678, 0x79DF, 0xD7E2, 0x79E0, 0xB679, 0x79E1, 0xB67A, 0x79E2, 0xB67B, + 0x79E3, 0xEFF7, 0x79E4, 0xB3D3, 0x79E5, 0xB67C, 0x79E6, 0xC7D8, 0x79E7, 0xD1ED, 0x79E8, 0xB67D, 0x79E9, 0xD6C8, 0x79EA, 0xB67E, + 0x79EB, 0xEFF8, 0x79EC, 0xB680, 0x79ED, 0xEFF6, 0x79EE, 0xB681, 0x79EF, 0xBBFD, 0x79F0, 0xB3C6, 0x79F1, 0xB682, 0x79F2, 0xB683, + 0x79F3, 0xB684, 0x79F4, 0xB685, 0x79F5, 0xB686, 0x79F6, 0xB687, 0x79F7, 0xB688, 0x79F8, 0xBDD5, 0x79F9, 0xB689, 0x79FA, 0xB68A, + 0x79FB, 0xD2C6, 0x79FC, 0xB68B, 0x79FD, 0xBBE0, 0x79FE, 0xB68C, 0x79FF, 0xB68D, 0x7A00, 0xCFA1, 0x7A01, 0xB68E, 0x7A02, 0xEFFC, + 0x7A03, 0xEFFB, 0x7A04, 0xB68F, 0x7A05, 0xB690, 0x7A06, 0xEFF9, 0x7A07, 0xB691, 0x7A08, 0xB692, 0x7A09, 0xB693, 0x7A0A, 0xB694, + 0x7A0B, 0xB3CC, 0x7A0C, 0xB695, 0x7A0D, 0xC9D4, 0x7A0E, 0xCBB0, 0x7A0F, 0xB696, 0x7A10, 0xB697, 0x7A11, 0xB698, 0x7A12, 0xB699, + 0x7A13, 0xB69A, 0x7A14, 0xEFFE, 0x7A15, 0xB69B, 0x7A16, 0xB69C, 0x7A17, 0xB0DE, 0x7A18, 0xB69D, 0x7A19, 0xB69E, 0x7A1A, 0xD6C9, + 0x7A1B, 0xB69F, 0x7A1C, 0xB6A0, 0x7A1D, 0xB740, 0x7A1E, 0xEFFD, 0x7A1F, 0xB741, 0x7A20, 0xB3ED, 0x7A21, 0xB742, 0x7A22, 0xB743, + 0x7A23, 0xF6D5, 0x7A24, 0xB744, 0x7A25, 0xB745, 0x7A26, 0xB746, 0x7A27, 0xB747, 0x7A28, 0xB748, 0x7A29, 0xB749, 0x7A2A, 0xB74A, + 0x7A2B, 0xB74B, 0x7A2C, 0xB74C, 0x7A2D, 0xB74D, 0x7A2E, 0xB74E, 0x7A2F, 0xB74F, 0x7A30, 0xB750, 0x7A31, 0xB751, 0x7A32, 0xB752, + 0x7A33, 0xCEC8, 0x7A34, 0xB753, 0x7A35, 0xB754, 0x7A36, 0xB755, 0x7A37, 0xF0A2, 0x7A38, 0xB756, 0x7A39, 0xF0A1, 0x7A3A, 0xB757, + 0x7A3B, 0xB5BE, 0x7A3C, 0xBCDA, 0x7A3D, 0xBBFC, 0x7A3E, 0xB758, 0x7A3F, 0xB8E5, 0x7A40, 0xB759, 0x7A41, 0xB75A, 0x7A42, 0xB75B, + 0x7A43, 0xB75C, 0x7A44, 0xB75D, 0x7A45, 0xB75E, 0x7A46, 0xC4C2, 0x7A47, 0xB75F, 0x7A48, 0xB760, 0x7A49, 0xB761, 0x7A4A, 0xB762, + 0x7A4B, 0xB763, 0x7A4C, 0xB764, 0x7A4D, 0xB765, 0x7A4E, 0xB766, 0x7A4F, 0xB767, 0x7A50, 0xB768, 0x7A51, 0xF0A3, 0x7A52, 0xB769, + 0x7A53, 0xB76A, 0x7A54, 0xB76B, 0x7A55, 0xB76C, 0x7A56, 0xB76D, 0x7A57, 0xCBEB, 0x7A58, 0xB76E, 0x7A59, 0xB76F, 0x7A5A, 0xB770, + 0x7A5B, 0xB771, 0x7A5C, 0xB772, 0x7A5D, 0xB773, 0x7A5E, 0xB774, 0x7A5F, 0xB775, 0x7A60, 0xB776, 0x7A61, 0xB777, 0x7A62, 0xB778, + 0x7A63, 0xB779, 0x7A64, 0xB77A, 0x7A65, 0xB77B, 0x7A66, 0xB77C, 0x7A67, 0xB77D, 0x7A68, 0xB77E, 0x7A69, 0xB780, 0x7A6A, 0xB781, + 0x7A6B, 0xB782, 0x7A6C, 0xB783, 0x7A6D, 0xB784, 0x7A6E, 0xB785, 0x7A6F, 0xB786, 0x7A70, 0xF0A6, 0x7A71, 0xB787, 0x7A72, 0xB788, + 0x7A73, 0xB789, 0x7A74, 0xD1A8, 0x7A75, 0xB78A, 0x7A76, 0xBEBF, 0x7A77, 0xC7EE, 0x7A78, 0xF1B6, 0x7A79, 0xF1B7, 0x7A7A, 0xBFD5, + 0x7A7B, 0xB78B, 0x7A7C, 0xB78C, 0x7A7D, 0xB78D, 0x7A7E, 0xB78E, 0x7A7F, 0xB4A9, 0x7A80, 0xF1B8, 0x7A81, 0xCDBB, 0x7A82, 0xB78F, + 0x7A83, 0xC7D4, 0x7A84, 0xD5AD, 0x7A85, 0xB790, 0x7A86, 0xF1B9, 0x7A87, 0xB791, 0x7A88, 0xF1BA, 0x7A89, 0xB792, 0x7A8A, 0xB793, + 0x7A8B, 0xB794, 0x7A8C, 0xB795, 0x7A8D, 0xC7CF, 0x7A8E, 0xB796, 0x7A8F, 0xB797, 0x7A90, 0xB798, 0x7A91, 0xD2A4, 0x7A92, 0xD6CF, + 0x7A93, 0xB799, 0x7A94, 0xB79A, 0x7A95, 0xF1BB, 0x7A96, 0xBDD1, 0x7A97, 0xB4B0, 0x7A98, 0xBEBD, 0x7A99, 0xB79B, 0x7A9A, 0xB79C, + 0x7A9B, 0xB79D, 0x7A9C, 0xB4DC, 0x7A9D, 0xCED1, 0x7A9E, 0xB79E, 0x7A9F, 0xBFDF, 0x7AA0, 0xF1BD, 0x7AA1, 0xB79F, 0x7AA2, 0xB7A0, + 0x7AA3, 0xB840, 0x7AA4, 0xB841, 0x7AA5, 0xBFFA, 0x7AA6, 0xF1BC, 0x7AA7, 0xB842, 0x7AA8, 0xF1BF, 0x7AA9, 0xB843, 0x7AAA, 0xB844, + 0x7AAB, 0xB845, 0x7AAC, 0xF1BE, 0x7AAD, 0xF1C0, 0x7AAE, 0xB846, 0x7AAF, 0xB847, 0x7AB0, 0xB848, 0x7AB1, 0xB849, 0x7AB2, 0xB84A, + 0x7AB3, 0xF1C1, 0x7AB4, 0xB84B, 0x7AB5, 0xB84C, 0x7AB6, 0xB84D, 0x7AB7, 0xB84E, 0x7AB8, 0xB84F, 0x7AB9, 0xB850, 0x7ABA, 0xB851, + 0x7ABB, 0xB852, 0x7ABC, 0xB853, 0x7ABD, 0xB854, 0x7ABE, 0xB855, 0x7ABF, 0xC1FE, 0x7AC0, 0xB856, 0x7AC1, 0xB857, 0x7AC2, 0xB858, + 0x7AC3, 0xB859, 0x7AC4, 0xB85A, 0x7AC5, 0xB85B, 0x7AC6, 0xB85C, 0x7AC7, 0xB85D, 0x7AC8, 0xB85E, 0x7AC9, 0xB85F, 0x7ACA, 0xB860, + 0x7ACB, 0xC1A2, 0x7ACC, 0xB861, 0x7ACD, 0xB862, 0x7ACE, 0xB863, 0x7ACF, 0xB864, 0x7AD0, 0xB865, 0x7AD1, 0xB866, 0x7AD2, 0xB867, + 0x7AD3, 0xB868, 0x7AD4, 0xB869, 0x7AD5, 0xB86A, 0x7AD6, 0xCAFA, 0x7AD7, 0xB86B, 0x7AD8, 0xB86C, 0x7AD9, 0xD5BE, 0x7ADA, 0xB86D, + 0x7ADB, 0xB86E, 0x7ADC, 0xB86F, 0x7ADD, 0xB870, 0x7ADE, 0xBEBA, 0x7ADF, 0xBEB9, 0x7AE0, 0xD5C2, 0x7AE1, 0xB871, 0x7AE2, 0xB872, + 0x7AE3, 0xBFA2, 0x7AE4, 0xB873, 0x7AE5, 0xCDAF, 0x7AE6, 0xF1B5, 0x7AE7, 0xB874, 0x7AE8, 0xB875, 0x7AE9, 0xB876, 0x7AEA, 0xB877, + 0x7AEB, 0xB878, 0x7AEC, 0xB879, 0x7AED, 0xBDDF, 0x7AEE, 0xB87A, 0x7AEF, 0xB6CB, 0x7AF0, 0xB87B, 0x7AF1, 0xB87C, 0x7AF2, 0xB87D, + 0x7AF3, 0xB87E, 0x7AF4, 0xB880, 0x7AF5, 0xB881, 0x7AF6, 0xB882, 0x7AF7, 0xB883, 0x7AF8, 0xB884, 0x7AF9, 0xD6F1, 0x7AFA, 0xF3C3, + 0x7AFB, 0xB885, 0x7AFC, 0xB886, 0x7AFD, 0xF3C4, 0x7AFE, 0xB887, 0x7AFF, 0xB8CD, 0x7B00, 0xB888, 0x7B01, 0xB889, 0x7B02, 0xB88A, + 0x7B03, 0xF3C6, 0x7B04, 0xF3C7, 0x7B05, 0xB88B, 0x7B06, 0xB0CA, 0x7B07, 0xB88C, 0x7B08, 0xF3C5, 0x7B09, 0xB88D, 0x7B0A, 0xF3C9, + 0x7B0B, 0xCBF1, 0x7B0C, 0xB88E, 0x7B0D, 0xB88F, 0x7B0E, 0xB890, 0x7B0F, 0xF3CB, 0x7B10, 0xB891, 0x7B11, 0xD0A6, 0x7B12, 0xB892, + 0x7B13, 0xB893, 0x7B14, 0xB1CA, 0x7B15, 0xF3C8, 0x7B16, 0xB894, 0x7B17, 0xB895, 0x7B18, 0xB896, 0x7B19, 0xF3CF, 0x7B1A, 0xB897, + 0x7B1B, 0xB5D1, 0x7B1C, 0xB898, 0x7B1D, 0xB899, 0x7B1E, 0xF3D7, 0x7B1F, 0xB89A, 0x7B20, 0xF3D2, 0x7B21, 0xB89B, 0x7B22, 0xB89C, + 0x7B23, 0xB89D, 0x7B24, 0xF3D4, 0x7B25, 0xF3D3, 0x7B26, 0xB7FB, 0x7B27, 0xB89E, 0x7B28, 0xB1BF, 0x7B29, 0xB89F, 0x7B2A, 0xF3CE, + 0x7B2B, 0xF3CA, 0x7B2C, 0xB5DA, 0x7B2D, 0xB8A0, 0x7B2E, 0xF3D0, 0x7B2F, 0xB940, 0x7B30, 0xB941, 0x7B31, 0xF3D1, 0x7B32, 0xB942, + 0x7B33, 0xF3D5, 0x7B34, 0xB943, 0x7B35, 0xB944, 0x7B36, 0xB945, 0x7B37, 0xB946, 0x7B38, 0xF3CD, 0x7B39, 0xB947, 0x7B3A, 0xBCE3, + 0x7B3B, 0xB948, 0x7B3C, 0xC1FD, 0x7B3D, 0xB949, 0x7B3E, 0xF3D6, 0x7B3F, 0xB94A, 0x7B40, 0xB94B, 0x7B41, 0xB94C, 0x7B42, 0xB94D, + 0x7B43, 0xB94E, 0x7B44, 0xB94F, 0x7B45, 0xF3DA, 0x7B46, 0xB950, 0x7B47, 0xF3CC, 0x7B48, 0xB951, 0x7B49, 0xB5C8, 0x7B4A, 0xB952, + 0x7B4B, 0xBDEE, 0x7B4C, 0xF3DC, 0x7B4D, 0xB953, 0x7B4E, 0xB954, 0x7B4F, 0xB7A4, 0x7B50, 0xBFF0, 0x7B51, 0xD6FE, 0x7B52, 0xCDB2, + 0x7B53, 0xB955, 0x7B54, 0xB4F0, 0x7B55, 0xB956, 0x7B56, 0xB2DF, 0x7B57, 0xB957, 0x7B58, 0xF3D8, 0x7B59, 0xB958, 0x7B5A, 0xF3D9, + 0x7B5B, 0xC9B8, 0x7B5C, 0xB959, 0x7B5D, 0xF3DD, 0x7B5E, 0xB95A, 0x7B5F, 0xB95B, 0x7B60, 0xF3DE, 0x7B61, 0xB95C, 0x7B62, 0xF3E1, + 0x7B63, 0xB95D, 0x7B64, 0xB95E, 0x7B65, 0xB95F, 0x7B66, 0xB960, 0x7B67, 0xB961, 0x7B68, 0xB962, 0x7B69, 0xB963, 0x7B6A, 0xB964, + 0x7B6B, 0xB965, 0x7B6C, 0xB966, 0x7B6D, 0xB967, 0x7B6E, 0xF3DF, 0x7B6F, 0xB968, 0x7B70, 0xB969, 0x7B71, 0xF3E3, 0x7B72, 0xF3E2, + 0x7B73, 0xB96A, 0x7B74, 0xB96B, 0x7B75, 0xF3DB, 0x7B76, 0xB96C, 0x7B77, 0xBFEA, 0x7B78, 0xB96D, 0x7B79, 0xB3EF, 0x7B7A, 0xB96E, + 0x7B7B, 0xF3E0, 0x7B7C, 0xB96F, 0x7B7D, 0xB970, 0x7B7E, 0xC7A9, 0x7B7F, 0xB971, 0x7B80, 0xBCF2, 0x7B81, 0xB972, 0x7B82, 0xB973, + 0x7B83, 0xB974, 0x7B84, 0xB975, 0x7B85, 0xF3EB, 0x7B86, 0xB976, 0x7B87, 0xB977, 0x7B88, 0xB978, 0x7B89, 0xB979, 0x7B8A, 0xB97A, + 0x7B8B, 0xB97B, 0x7B8C, 0xB97C, 0x7B8D, 0xB9BF, 0x7B8E, 0xB97D, 0x7B8F, 0xB97E, 0x7B90, 0xF3E4, 0x7B91, 0xB980, 0x7B92, 0xB981, + 0x7B93, 0xB982, 0x7B94, 0xB2AD, 0x7B95, 0xBBFE, 0x7B96, 0xB983, 0x7B97, 0xCBE3, 0x7B98, 0xB984, 0x7B99, 0xB985, 0x7B9A, 0xB986, + 0x7B9B, 0xB987, 0x7B9C, 0xF3ED, 0x7B9D, 0xF3E9, 0x7B9E, 0xB988, 0x7B9F, 0xB989, 0x7BA0, 0xB98A, 0x7BA1, 0xB9DC, 0x7BA2, 0xF3EE, + 0x7BA3, 0xB98B, 0x7BA4, 0xB98C, 0x7BA5, 0xB98D, 0x7BA6, 0xF3E5, 0x7BA7, 0xF3E6, 0x7BA8, 0xF3EA, 0x7BA9, 0xC2E1, 0x7BAA, 0xF3EC, + 0x7BAB, 0xF3EF, 0x7BAC, 0xF3E8, 0x7BAD, 0xBCFD, 0x7BAE, 0xB98E, 0x7BAF, 0xB98F, 0x7BB0, 0xB990, 0x7BB1, 0xCFE4, 0x7BB2, 0xB991, + 0x7BB3, 0xB992, 0x7BB4, 0xF3F0, 0x7BB5, 0xB993, 0x7BB6, 0xB994, 0x7BB7, 0xB995, 0x7BB8, 0xF3E7, 0x7BB9, 0xB996, 0x7BBA, 0xB997, + 0x7BBB, 0xB998, 0x7BBC, 0xB999, 0x7BBD, 0xB99A, 0x7BBE, 0xB99B, 0x7BBF, 0xB99C, 0x7BC0, 0xB99D, 0x7BC1, 0xF3F2, 0x7BC2, 0xB99E, + 0x7BC3, 0xB99F, 0x7BC4, 0xB9A0, 0x7BC5, 0xBA40, 0x7BC6, 0xD7AD, 0x7BC7, 0xC6AA, 0x7BC8, 0xBA41, 0x7BC9, 0xBA42, 0x7BCA, 0xBA43, + 0x7BCB, 0xBA44, 0x7BCC, 0xF3F3, 0x7BCD, 0xBA45, 0x7BCE, 0xBA46, 0x7BCF, 0xBA47, 0x7BD0, 0xBA48, 0x7BD1, 0xF3F1, 0x7BD2, 0xBA49, + 0x7BD3, 0xC2A8, 0x7BD4, 0xBA4A, 0x7BD5, 0xBA4B, 0x7BD6, 0xBA4C, 0x7BD7, 0xBA4D, 0x7BD8, 0xBA4E, 0x7BD9, 0xB8DD, 0x7BDA, 0xF3F5, + 0x7BDB, 0xBA4F, 0x7BDC, 0xBA50, 0x7BDD, 0xF3F4, 0x7BDE, 0xBA51, 0x7BDF, 0xBA52, 0x7BE0, 0xBA53, 0x7BE1, 0xB4DB, 0x7BE2, 0xBA54, + 0x7BE3, 0xBA55, 0x7BE4, 0xBA56, 0x7BE5, 0xF3F6, 0x7BE6, 0xF3F7, 0x7BE7, 0xBA57, 0x7BE8, 0xBA58, 0x7BE9, 0xBA59, 0x7BEA, 0xF3F8, + 0x7BEB, 0xBA5A, 0x7BEC, 0xBA5B, 0x7BED, 0xBA5C, 0x7BEE, 0xC0BA, 0x7BEF, 0xBA5D, 0x7BF0, 0xBA5E, 0x7BF1, 0xC0E9, 0x7BF2, 0xBA5F, + 0x7BF3, 0xBA60, 0x7BF4, 0xBA61, 0x7BF5, 0xBA62, 0x7BF6, 0xBA63, 0x7BF7, 0xC5F1, 0x7BF8, 0xBA64, 0x7BF9, 0xBA65, 0x7BFA, 0xBA66, + 0x7BFB, 0xBA67, 0x7BFC, 0xF3FB, 0x7BFD, 0xBA68, 0x7BFE, 0xF3FA, 0x7BFF, 0xBA69, 0x7C00, 0xBA6A, 0x7C01, 0xBA6B, 0x7C02, 0xBA6C, + 0x7C03, 0xBA6D, 0x7C04, 0xBA6E, 0x7C05, 0xBA6F, 0x7C06, 0xBA70, 0x7C07, 0xB4D8, 0x7C08, 0xBA71, 0x7C09, 0xBA72, 0x7C0A, 0xBA73, + 0x7C0B, 0xF3FE, 0x7C0C, 0xF3F9, 0x7C0D, 0xBA74, 0x7C0E, 0xBA75, 0x7C0F, 0xF3FC, 0x7C10, 0xBA76, 0x7C11, 0xBA77, 0x7C12, 0xBA78, + 0x7C13, 0xBA79, 0x7C14, 0xBA7A, 0x7C15, 0xBA7B, 0x7C16, 0xF3FD, 0x7C17, 0xBA7C, 0x7C18, 0xBA7D, 0x7C19, 0xBA7E, 0x7C1A, 0xBA80, + 0x7C1B, 0xBA81, 0x7C1C, 0xBA82, 0x7C1D, 0xBA83, 0x7C1E, 0xBA84, 0x7C1F, 0xF4A1, 0x7C20, 0xBA85, 0x7C21, 0xBA86, 0x7C22, 0xBA87, + 0x7C23, 0xBA88, 0x7C24, 0xBA89, 0x7C25, 0xBA8A, 0x7C26, 0xF4A3, 0x7C27, 0xBBC9, 0x7C28, 0xBA8B, 0x7C29, 0xBA8C, 0x7C2A, 0xF4A2, + 0x7C2B, 0xBA8D, 0x7C2C, 0xBA8E, 0x7C2D, 0xBA8F, 0x7C2E, 0xBA90, 0x7C2F, 0xBA91, 0x7C30, 0xBA92, 0x7C31, 0xBA93, 0x7C32, 0xBA94, + 0x7C33, 0xBA95, 0x7C34, 0xBA96, 0x7C35, 0xBA97, 0x7C36, 0xBA98, 0x7C37, 0xBA99, 0x7C38, 0xF4A4, 0x7C39, 0xBA9A, 0x7C3A, 0xBA9B, + 0x7C3B, 0xBA9C, 0x7C3C, 0xBA9D, 0x7C3D, 0xBA9E, 0x7C3E, 0xBA9F, 0x7C3F, 0xB2BE, 0x7C40, 0xF4A6, 0x7C41, 0xF4A5, 0x7C42, 0xBAA0, + 0x7C43, 0xBB40, 0x7C44, 0xBB41, 0x7C45, 0xBB42, 0x7C46, 0xBB43, 0x7C47, 0xBB44, 0x7C48, 0xBB45, 0x7C49, 0xBB46, 0x7C4A, 0xBB47, + 0x7C4B, 0xBB48, 0x7C4C, 0xBB49, 0x7C4D, 0xBCAE, 0x7C4E, 0xBB4A, 0x7C4F, 0xBB4B, 0x7C50, 0xBB4C, 0x7C51, 0xBB4D, 0x7C52, 0xBB4E, + 0x7C53, 0xBB4F, 0x7C54, 0xBB50, 0x7C55, 0xBB51, 0x7C56, 0xBB52, 0x7C57, 0xBB53, 0x7C58, 0xBB54, 0x7C59, 0xBB55, 0x7C5A, 0xBB56, + 0x7C5B, 0xBB57, 0x7C5C, 0xBB58, 0x7C5D, 0xBB59, 0x7C5E, 0xBB5A, 0x7C5F, 0xBB5B, 0x7C60, 0xBB5C, 0x7C61, 0xBB5D, 0x7C62, 0xBB5E, + 0x7C63, 0xBB5F, 0x7C64, 0xBB60, 0x7C65, 0xBB61, 0x7C66, 0xBB62, 0x7C67, 0xBB63, 0x7C68, 0xBB64, 0x7C69, 0xBB65, 0x7C6A, 0xBB66, + 0x7C6B, 0xBB67, 0x7C6C, 0xBB68, 0x7C6D, 0xBB69, 0x7C6E, 0xBB6A, 0x7C6F, 0xBB6B, 0x7C70, 0xBB6C, 0x7C71, 0xBB6D, 0x7C72, 0xBB6E, + 0x7C73, 0xC3D7, 0x7C74, 0xD9E1, 0x7C75, 0xBB6F, 0x7C76, 0xBB70, 0x7C77, 0xBB71, 0x7C78, 0xBB72, 0x7C79, 0xBB73, 0x7C7A, 0xBB74, + 0x7C7B, 0xC0E0, 0x7C7C, 0xF4CC, 0x7C7D, 0xD7D1, 0x7C7E, 0xBB75, 0x7C7F, 0xBB76, 0x7C80, 0xBB77, 0x7C81, 0xBB78, 0x7C82, 0xBB79, + 0x7C83, 0xBB7A, 0x7C84, 0xBB7B, 0x7C85, 0xBB7C, 0x7C86, 0xBB7D, 0x7C87, 0xBB7E, 0x7C88, 0xBB80, 0x7C89, 0xB7DB, 0x7C8A, 0xBB81, + 0x7C8B, 0xBB82, 0x7C8C, 0xBB83, 0x7C8D, 0xBB84, 0x7C8E, 0xBB85, 0x7C8F, 0xBB86, 0x7C90, 0xBB87, 0x7C91, 0xF4CE, 0x7C92, 0xC1A3, + 0x7C93, 0xBB88, 0x7C94, 0xBB89, 0x7C95, 0xC6C9, 0x7C96, 0xBB8A, 0x7C97, 0xB4D6, 0x7C98, 0xD5B3, 0x7C99, 0xBB8B, 0x7C9A, 0xBB8C, + 0x7C9B, 0xBB8D, 0x7C9C, 0xF4D0, 0x7C9D, 0xF4CF, 0x7C9E, 0xF4D1, 0x7C9F, 0xCBDA, 0x7CA0, 0xBB8E, 0x7CA1, 0xBB8F, 0x7CA2, 0xF4D2, + 0x7CA3, 0xBB90, 0x7CA4, 0xD4C1, 0x7CA5, 0xD6E0, 0x7CA6, 0xBB91, 0x7CA7, 0xBB92, 0x7CA8, 0xBB93, 0x7CA9, 0xBB94, 0x7CAA, 0xB7E0, + 0x7CAB, 0xBB95, 0x7CAC, 0xBB96, 0x7CAD, 0xBB97, 0x7CAE, 0xC1B8, 0x7CAF, 0xBB98, 0x7CB0, 0xBB99, 0x7CB1, 0xC1BB, 0x7CB2, 0xF4D3, + 0x7CB3, 0xBEAC, 0x7CB4, 0xBB9A, 0x7CB5, 0xBB9B, 0x7CB6, 0xBB9C, 0x7CB7, 0xBB9D, 0x7CB8, 0xBB9E, 0x7CB9, 0xB4E2, 0x7CBA, 0xBB9F, + 0x7CBB, 0xBBA0, 0x7CBC, 0xF4D4, 0x7CBD, 0xF4D5, 0x7CBE, 0xBEAB, 0x7CBF, 0xBC40, 0x7CC0, 0xBC41, 0x7CC1, 0xF4D6, 0x7CC2, 0xBC42, + 0x7CC3, 0xBC43, 0x7CC4, 0xBC44, 0x7CC5, 0xF4DB, 0x7CC6, 0xBC45, 0x7CC7, 0xF4D7, 0x7CC8, 0xF4DA, 0x7CC9, 0xBC46, 0x7CCA, 0xBAFD, + 0x7CCB, 0xBC47, 0x7CCC, 0xF4D8, 0x7CCD, 0xF4D9, 0x7CCE, 0xBC48, 0x7CCF, 0xBC49, 0x7CD0, 0xBC4A, 0x7CD1, 0xBC4B, 0x7CD2, 0xBC4C, + 0x7CD3, 0xBC4D, 0x7CD4, 0xBC4E, 0x7CD5, 0xB8E2, 0x7CD6, 0xCCC7, 0x7CD7, 0xF4DC, 0x7CD8, 0xBC4F, 0x7CD9, 0xB2DA, 0x7CDA, 0xBC50, + 0x7CDB, 0xBC51, 0x7CDC, 0xC3D3, 0x7CDD, 0xBC52, 0x7CDE, 0xBC53, 0x7CDF, 0xD4E3, 0x7CE0, 0xBFB7, 0x7CE1, 0xBC54, 0x7CE2, 0xBC55, + 0x7CE3, 0xBC56, 0x7CE4, 0xBC57, 0x7CE5, 0xBC58, 0x7CE6, 0xBC59, 0x7CE7, 0xBC5A, 0x7CE8, 0xF4DD, 0x7CE9, 0xBC5B, 0x7CEA, 0xBC5C, + 0x7CEB, 0xBC5D, 0x7CEC, 0xBC5E, 0x7CED, 0xBC5F, 0x7CEE, 0xBC60, 0x7CEF, 0xC5B4, 0x7CF0, 0xBC61, 0x7CF1, 0xBC62, 0x7CF2, 0xBC63, + 0x7CF3, 0xBC64, 0x7CF4, 0xBC65, 0x7CF5, 0xBC66, 0x7CF6, 0xBC67, 0x7CF7, 0xBC68, 0x7CF8, 0xF4E9, 0x7CF9, 0xBC69, 0x7CFA, 0xBC6A, + 0x7CFB, 0xCFB5, 0x7CFC, 0xBC6B, 0x7CFD, 0xBC6C, 0x7CFE, 0xBC6D, 0x7CFF, 0xBC6E, 0x7D00, 0xBC6F, 0x7D01, 0xBC70, 0x7D02, 0xBC71, + 0x7D03, 0xBC72, 0x7D04, 0xBC73, 0x7D05, 0xBC74, 0x7D06, 0xBC75, 0x7D07, 0xBC76, 0x7D08, 0xBC77, 0x7D09, 0xBC78, 0x7D0A, 0xCEC9, + 0x7D0B, 0xBC79, 0x7D0C, 0xBC7A, 0x7D0D, 0xBC7B, 0x7D0E, 0xBC7C, 0x7D0F, 0xBC7D, 0x7D10, 0xBC7E, 0x7D11, 0xBC80, 0x7D12, 0xBC81, + 0x7D13, 0xBC82, 0x7D14, 0xBC83, 0x7D15, 0xBC84, 0x7D16, 0xBC85, 0x7D17, 0xBC86, 0x7D18, 0xBC87, 0x7D19, 0xBC88, 0x7D1A, 0xBC89, + 0x7D1B, 0xBC8A, 0x7D1C, 0xBC8B, 0x7D1D, 0xBC8C, 0x7D1E, 0xBC8D, 0x7D1F, 0xBC8E, 0x7D20, 0xCBD8, 0x7D21, 0xBC8F, 0x7D22, 0xCBF7, + 0x7D23, 0xBC90, 0x7D24, 0xBC91, 0x7D25, 0xBC92, 0x7D26, 0xBC93, 0x7D27, 0xBDF4, 0x7D28, 0xBC94, 0x7D29, 0xBC95, 0x7D2A, 0xBC96, + 0x7D2B, 0xD7CF, 0x7D2C, 0xBC97, 0x7D2D, 0xBC98, 0x7D2E, 0xBC99, 0x7D2F, 0xC0DB, 0x7D30, 0xBC9A, 0x7D31, 0xBC9B, 0x7D32, 0xBC9C, + 0x7D33, 0xBC9D, 0x7D34, 0xBC9E, 0x7D35, 0xBC9F, 0x7D36, 0xBCA0, 0x7D37, 0xBD40, 0x7D38, 0xBD41, 0x7D39, 0xBD42, 0x7D3A, 0xBD43, + 0x7D3B, 0xBD44, 0x7D3C, 0xBD45, 0x7D3D, 0xBD46, 0x7D3E, 0xBD47, 0x7D3F, 0xBD48, 0x7D40, 0xBD49, 0x7D41, 0xBD4A, 0x7D42, 0xBD4B, + 0x7D43, 0xBD4C, 0x7D44, 0xBD4D, 0x7D45, 0xBD4E, 0x7D46, 0xBD4F, 0x7D47, 0xBD50, 0x7D48, 0xBD51, 0x7D49, 0xBD52, 0x7D4A, 0xBD53, + 0x7D4B, 0xBD54, 0x7D4C, 0xBD55, 0x7D4D, 0xBD56, 0x7D4E, 0xBD57, 0x7D4F, 0xBD58, 0x7D50, 0xBD59, 0x7D51, 0xBD5A, 0x7D52, 0xBD5B, + 0x7D53, 0xBD5C, 0x7D54, 0xBD5D, 0x7D55, 0xBD5E, 0x7D56, 0xBD5F, 0x7D57, 0xBD60, 0x7D58, 0xBD61, 0x7D59, 0xBD62, 0x7D5A, 0xBD63, + 0x7D5B, 0xBD64, 0x7D5C, 0xBD65, 0x7D5D, 0xBD66, 0x7D5E, 0xBD67, 0x7D5F, 0xBD68, 0x7D60, 0xBD69, 0x7D61, 0xBD6A, 0x7D62, 0xBD6B, + 0x7D63, 0xBD6C, 0x7D64, 0xBD6D, 0x7D65, 0xBD6E, 0x7D66, 0xBD6F, 0x7D67, 0xBD70, 0x7D68, 0xBD71, 0x7D69, 0xBD72, 0x7D6A, 0xBD73, + 0x7D6B, 0xBD74, 0x7D6C, 0xBD75, 0x7D6D, 0xBD76, 0x7D6E, 0xD0F5, 0x7D6F, 0xBD77, 0x7D70, 0xBD78, 0x7D71, 0xBD79, 0x7D72, 0xBD7A, + 0x7D73, 0xBD7B, 0x7D74, 0xBD7C, 0x7D75, 0xBD7D, 0x7D76, 0xBD7E, 0x7D77, 0xF4EA, 0x7D78, 0xBD80, 0x7D79, 0xBD81, 0x7D7A, 0xBD82, + 0x7D7B, 0xBD83, 0x7D7C, 0xBD84, 0x7D7D, 0xBD85, 0x7D7E, 0xBD86, 0x7D7F, 0xBD87, 0x7D80, 0xBD88, 0x7D81, 0xBD89, 0x7D82, 0xBD8A, + 0x7D83, 0xBD8B, 0x7D84, 0xBD8C, 0x7D85, 0xBD8D, 0x7D86, 0xBD8E, 0x7D87, 0xBD8F, 0x7D88, 0xBD90, 0x7D89, 0xBD91, 0x7D8A, 0xBD92, + 0x7D8B, 0xBD93, 0x7D8C, 0xBD94, 0x7D8D, 0xBD95, 0x7D8E, 0xBD96, 0x7D8F, 0xBD97, 0x7D90, 0xBD98, 0x7D91, 0xBD99, 0x7D92, 0xBD9A, + 0x7D93, 0xBD9B, 0x7D94, 0xBD9C, 0x7D95, 0xBD9D, 0x7D96, 0xBD9E, 0x7D97, 0xBD9F, 0x7D98, 0xBDA0, 0x7D99, 0xBE40, 0x7D9A, 0xBE41, + 0x7D9B, 0xBE42, 0x7D9C, 0xBE43, 0x7D9D, 0xBE44, 0x7D9E, 0xBE45, 0x7D9F, 0xBE46, 0x7DA0, 0xBE47, 0x7DA1, 0xBE48, 0x7DA2, 0xBE49, + 0x7DA3, 0xBE4A, 0x7DA4, 0xBE4B, 0x7DA5, 0xBE4C, 0x7DA6, 0xF4EB, 0x7DA7, 0xBE4D, 0x7DA8, 0xBE4E, 0x7DA9, 0xBE4F, 0x7DAA, 0xBE50, + 0x7DAB, 0xBE51, 0x7DAC, 0xBE52, 0x7DAD, 0xBE53, 0x7DAE, 0xF4EC, 0x7DAF, 0xBE54, 0x7DB0, 0xBE55, 0x7DB1, 0xBE56, 0x7DB2, 0xBE57, + 0x7DB3, 0xBE58, 0x7DB4, 0xBE59, 0x7DB5, 0xBE5A, 0x7DB6, 0xBE5B, 0x7DB7, 0xBE5C, 0x7DB8, 0xBE5D, 0x7DB9, 0xBE5E, 0x7DBA, 0xBE5F, + 0x7DBB, 0xBE60, 0x7DBC, 0xBE61, 0x7DBD, 0xBE62, 0x7DBE, 0xBE63, 0x7DBF, 0xBE64, 0x7DC0, 0xBE65, 0x7DC1, 0xBE66, 0x7DC2, 0xBE67, + 0x7DC3, 0xBE68, 0x7DC4, 0xBE69, 0x7DC5, 0xBE6A, 0x7DC6, 0xBE6B, 0x7DC7, 0xBE6C, 0x7DC8, 0xBE6D, 0x7DC9, 0xBE6E, 0x7DCA, 0xBE6F, + 0x7DCB, 0xBE70, 0x7DCC, 0xBE71, 0x7DCD, 0xBE72, 0x7DCE, 0xBE73, 0x7DCF, 0xBE74, 0x7DD0, 0xBE75, 0x7DD1, 0xBE76, 0x7DD2, 0xBE77, + 0x7DD3, 0xBE78, 0x7DD4, 0xBE79, 0x7DD5, 0xBE7A, 0x7DD6, 0xBE7B, 0x7DD7, 0xBE7C, 0x7DD8, 0xBE7D, 0x7DD9, 0xBE7E, 0x7DDA, 0xBE80, + 0x7DDB, 0xBE81, 0x7DDC, 0xBE82, 0x7DDD, 0xBE83, 0x7DDE, 0xBE84, 0x7DDF, 0xBE85, 0x7DE0, 0xBE86, 0x7DE1, 0xBE87, 0x7DE2, 0xBE88, + 0x7DE3, 0xBE89, 0x7DE4, 0xBE8A, 0x7DE5, 0xBE8B, 0x7DE6, 0xBE8C, 0x7DE7, 0xBE8D, 0x7DE8, 0xBE8E, 0x7DE9, 0xBE8F, 0x7DEA, 0xBE90, + 0x7DEB, 0xBE91, 0x7DEC, 0xBE92, 0x7DED, 0xBE93, 0x7DEE, 0xBE94, 0x7DEF, 0xBE95, 0x7DF0, 0xBE96, 0x7DF1, 0xBE97, 0x7DF2, 0xBE98, + 0x7DF3, 0xBE99, 0x7DF4, 0xBE9A, 0x7DF5, 0xBE9B, 0x7DF6, 0xBE9C, 0x7DF7, 0xBE9D, 0x7DF8, 0xBE9E, 0x7DF9, 0xBE9F, 0x7DFA, 0xBEA0, + 0x7DFB, 0xBF40, 0x7DFC, 0xBF41, 0x7DFD, 0xBF42, 0x7DFE, 0xBF43, 0x7DFF, 0xBF44, 0x7E00, 0xBF45, 0x7E01, 0xBF46, 0x7E02, 0xBF47, + 0x7E03, 0xBF48, 0x7E04, 0xBF49, 0x7E05, 0xBF4A, 0x7E06, 0xBF4B, 0x7E07, 0xBF4C, 0x7E08, 0xBF4D, 0x7E09, 0xBF4E, 0x7E0A, 0xBF4F, + 0x7E0B, 0xBF50, 0x7E0C, 0xBF51, 0x7E0D, 0xBF52, 0x7E0E, 0xBF53, 0x7E0F, 0xBF54, 0x7E10, 0xBF55, 0x7E11, 0xBF56, 0x7E12, 0xBF57, + 0x7E13, 0xBF58, 0x7E14, 0xBF59, 0x7E15, 0xBF5A, 0x7E16, 0xBF5B, 0x7E17, 0xBF5C, 0x7E18, 0xBF5D, 0x7E19, 0xBF5E, 0x7E1A, 0xBF5F, + 0x7E1B, 0xBF60, 0x7E1C, 0xBF61, 0x7E1D, 0xBF62, 0x7E1E, 0xBF63, 0x7E1F, 0xBF64, 0x7E20, 0xBF65, 0x7E21, 0xBF66, 0x7E22, 0xBF67, + 0x7E23, 0xBF68, 0x7E24, 0xBF69, 0x7E25, 0xBF6A, 0x7E26, 0xBF6B, 0x7E27, 0xBF6C, 0x7E28, 0xBF6D, 0x7E29, 0xBF6E, 0x7E2A, 0xBF6F, + 0x7E2B, 0xBF70, 0x7E2C, 0xBF71, 0x7E2D, 0xBF72, 0x7E2E, 0xBF73, 0x7E2F, 0xBF74, 0x7E30, 0xBF75, 0x7E31, 0xBF76, 0x7E32, 0xBF77, + 0x7E33, 0xBF78, 0x7E34, 0xBF79, 0x7E35, 0xBF7A, 0x7E36, 0xBF7B, 0x7E37, 0xBF7C, 0x7E38, 0xBF7D, 0x7E39, 0xBF7E, 0x7E3A, 0xBF80, + 0x7E3B, 0xF7E3, 0x7E3C, 0xBF81, 0x7E3D, 0xBF82, 0x7E3E, 0xBF83, 0x7E3F, 0xBF84, 0x7E40, 0xBF85, 0x7E41, 0xB7B1, 0x7E42, 0xBF86, + 0x7E43, 0xBF87, 0x7E44, 0xBF88, 0x7E45, 0xBF89, 0x7E46, 0xBF8A, 0x7E47, 0xF4ED, 0x7E48, 0xBF8B, 0x7E49, 0xBF8C, 0x7E4A, 0xBF8D, + 0x7E4B, 0xBF8E, 0x7E4C, 0xBF8F, 0x7E4D, 0xBF90, 0x7E4E, 0xBF91, 0x7E4F, 0xBF92, 0x7E50, 0xBF93, 0x7E51, 0xBF94, 0x7E52, 0xBF95, + 0x7E53, 0xBF96, 0x7E54, 0xBF97, 0x7E55, 0xBF98, 0x7E56, 0xBF99, 0x7E57, 0xBF9A, 0x7E58, 0xBF9B, 0x7E59, 0xBF9C, 0x7E5A, 0xBF9D, + 0x7E5B, 0xBF9E, 0x7E5C, 0xBF9F, 0x7E5D, 0xBFA0, 0x7E5E, 0xC040, 0x7E5F, 0xC041, 0x7E60, 0xC042, 0x7E61, 0xC043, 0x7E62, 0xC044, + 0x7E63, 0xC045, 0x7E64, 0xC046, 0x7E65, 0xC047, 0x7E66, 0xC048, 0x7E67, 0xC049, 0x7E68, 0xC04A, 0x7E69, 0xC04B, 0x7E6A, 0xC04C, + 0x7E6B, 0xC04D, 0x7E6C, 0xC04E, 0x7E6D, 0xC04F, 0x7E6E, 0xC050, 0x7E6F, 0xC051, 0x7E70, 0xC052, 0x7E71, 0xC053, 0x7E72, 0xC054, + 0x7E73, 0xC055, 0x7E74, 0xC056, 0x7E75, 0xC057, 0x7E76, 0xC058, 0x7E77, 0xC059, 0x7E78, 0xC05A, 0x7E79, 0xC05B, 0x7E7A, 0xC05C, + 0x7E7B, 0xC05D, 0x7E7C, 0xC05E, 0x7E7D, 0xC05F, 0x7E7E, 0xC060, 0x7E7F, 0xC061, 0x7E80, 0xC062, 0x7E81, 0xC063, 0x7E82, 0xD7EB, + 0x7E83, 0xC064, 0x7E84, 0xC065, 0x7E85, 0xC066, 0x7E86, 0xC067, 0x7E87, 0xC068, 0x7E88, 0xC069, 0x7E89, 0xC06A, 0x7E8A, 0xC06B, + 0x7E8B, 0xC06C, 0x7E8C, 0xC06D, 0x7E8D, 0xC06E, 0x7E8E, 0xC06F, 0x7E8F, 0xC070, 0x7E90, 0xC071, 0x7E91, 0xC072, 0x7E92, 0xC073, + 0x7E93, 0xC074, 0x7E94, 0xC075, 0x7E95, 0xC076, 0x7E96, 0xC077, 0x7E97, 0xC078, 0x7E98, 0xC079, 0x7E99, 0xC07A, 0x7E9A, 0xC07B, + 0x7E9B, 0xF4EE, 0x7E9C, 0xC07C, 0x7E9D, 0xC07D, 0x7E9E, 0xC07E, 0x7E9F, 0xE6F9, 0x7EA0, 0xBEC0, 0x7EA1, 0xE6FA, 0x7EA2, 0xBAEC, + 0x7EA3, 0xE6FB, 0x7EA4, 0xCFCB, 0x7EA5, 0xE6FC, 0x7EA6, 0xD4BC, 0x7EA7, 0xBCB6, 0x7EA8, 0xE6FD, 0x7EA9, 0xE6FE, 0x7EAA, 0xBCCD, + 0x7EAB, 0xC8D2, 0x7EAC, 0xCEB3, 0x7EAD, 0xE7A1, 0x7EAE, 0xC080, 0x7EAF, 0xB4BF, 0x7EB0, 0xE7A2, 0x7EB1, 0xC9B4, 0x7EB2, 0xB8D9, + 0x7EB3, 0xC4C9, 0x7EB4, 0xC081, 0x7EB5, 0xD7DD, 0x7EB6, 0xC2DA, 0x7EB7, 0xB7D7, 0x7EB8, 0xD6BD, 0x7EB9, 0xCEC6, 0x7EBA, 0xB7C4, + 0x7EBB, 0xC082, 0x7EBC, 0xC083, 0x7EBD, 0xC5A6, 0x7EBE, 0xE7A3, 0x7EBF, 0xCFDF, 0x7EC0, 0xE7A4, 0x7EC1, 0xE7A5, 0x7EC2, 0xE7A6, + 0x7EC3, 0xC1B7, 0x7EC4, 0xD7E9, 0x7EC5, 0xC9F0, 0x7EC6, 0xCFB8, 0x7EC7, 0xD6AF, 0x7EC8, 0xD6D5, 0x7EC9, 0xE7A7, 0x7ECA, 0xB0ED, + 0x7ECB, 0xE7A8, 0x7ECC, 0xE7A9, 0x7ECD, 0xC9DC, 0x7ECE, 0xD2EF, 0x7ECF, 0xBEAD, 0x7ED0, 0xE7AA, 0x7ED1, 0xB0F3, 0x7ED2, 0xC8DE, + 0x7ED3, 0xBDE1, 0x7ED4, 0xE7AB, 0x7ED5, 0xC8C6, 0x7ED6, 0xC084, 0x7ED7, 0xE7AC, 0x7ED8, 0xBBE6, 0x7ED9, 0xB8F8, 0x7EDA, 0xD1A4, + 0x7EDB, 0xE7AD, 0x7EDC, 0xC2E7, 0x7EDD, 0xBEF8, 0x7EDE, 0xBDCA, 0x7EDF, 0xCDB3, 0x7EE0, 0xE7AE, 0x7EE1, 0xE7AF, 0x7EE2, 0xBEEE, + 0x7EE3, 0xD0E5, 0x7EE4, 0xC085, 0x7EE5, 0xCBE7, 0x7EE6, 0xCCD0, 0x7EE7, 0xBCCC, 0x7EE8, 0xE7B0, 0x7EE9, 0xBCA8, 0x7EEA, 0xD0F7, + 0x7EEB, 0xE7B1, 0x7EEC, 0xC086, 0x7EED, 0xD0F8, 0x7EEE, 0xE7B2, 0x7EEF, 0xE7B3, 0x7EF0, 0xB4C2, 0x7EF1, 0xE7B4, 0x7EF2, 0xE7B5, + 0x7EF3, 0xC9FE, 0x7EF4, 0xCEAC, 0x7EF5, 0xC3E0, 0x7EF6, 0xE7B7, 0x7EF7, 0xB1C1, 0x7EF8, 0xB3F1, 0x7EF9, 0xC087, 0x7EFA, 0xE7B8, + 0x7EFB, 0xE7B9, 0x7EFC, 0xD7DB, 0x7EFD, 0xD5C0, 0x7EFE, 0xE7BA, 0x7EFF, 0xC2CC, 0x7F00, 0xD7BA, 0x7F01, 0xE7BB, 0x7F02, 0xE7BC, + 0x7F03, 0xE7BD, 0x7F04, 0xBCEA, 0x7F05, 0xC3E5, 0x7F06, 0xC0C2, 0x7F07, 0xE7BE, 0x7F08, 0xE7BF, 0x7F09, 0xBCA9, 0x7F0A, 0xC088, + 0x7F0B, 0xE7C0, 0x7F0C, 0xE7C1, 0x7F0D, 0xE7B6, 0x7F0E, 0xB6D0, 0x7F0F, 0xE7C2, 0x7F10, 0xC089, 0x7F11, 0xE7C3, 0x7F12, 0xE7C4, + 0x7F13, 0xBBBA, 0x7F14, 0xB5DE, 0x7F15, 0xC2C6, 0x7F16, 0xB1E0, 0x7F17, 0xE7C5, 0x7F18, 0xD4B5, 0x7F19, 0xE7C6, 0x7F1A, 0xB8BF, + 0x7F1B, 0xE7C8, 0x7F1C, 0xE7C7, 0x7F1D, 0xB7EC, 0x7F1E, 0xC08A, 0x7F1F, 0xE7C9, 0x7F20, 0xB2F8, 0x7F21, 0xE7CA, 0x7F22, 0xE7CB, + 0x7F23, 0xE7CC, 0x7F24, 0xE7CD, 0x7F25, 0xE7CE, 0x7F26, 0xE7CF, 0x7F27, 0xE7D0, 0x7F28, 0xD3A7, 0x7F29, 0xCBF5, 0x7F2A, 0xE7D1, + 0x7F2B, 0xE7D2, 0x7F2C, 0xE7D3, 0x7F2D, 0xE7D4, 0x7F2E, 0xC9C9, 0x7F2F, 0xE7D5, 0x7F30, 0xE7D6, 0x7F31, 0xE7D7, 0x7F32, 0xE7D8, + 0x7F33, 0xE7D9, 0x7F34, 0xBDC9, 0x7F35, 0xE7DA, 0x7F36, 0xF3BE, 0x7F37, 0xC08B, 0x7F38, 0xB8D7, 0x7F39, 0xC08C, 0x7F3A, 0xC8B1, + 0x7F3B, 0xC08D, 0x7F3C, 0xC08E, 0x7F3D, 0xC08F, 0x7F3E, 0xC090, 0x7F3F, 0xC091, 0x7F40, 0xC092, 0x7F41, 0xC093, 0x7F42, 0xF3BF, + 0x7F43, 0xC094, 0x7F44, 0xF3C0, 0x7F45, 0xF3C1, 0x7F46, 0xC095, 0x7F47, 0xC096, 0x7F48, 0xC097, 0x7F49, 0xC098, 0x7F4A, 0xC099, + 0x7F4B, 0xC09A, 0x7F4C, 0xC09B, 0x7F4D, 0xC09C, 0x7F4E, 0xC09D, 0x7F4F, 0xC09E, 0x7F50, 0xB9DE, 0x7F51, 0xCDF8, 0x7F52, 0xC09F, + 0x7F53, 0xC0A0, 0x7F54, 0xD8E8, 0x7F55, 0xBAB1, 0x7F56, 0xC140, 0x7F57, 0xC2DE, 0x7F58, 0xEEB7, 0x7F59, 0xC141, 0x7F5A, 0xB7A3, + 0x7F5B, 0xC142, 0x7F5C, 0xC143, 0x7F5D, 0xC144, 0x7F5E, 0xC145, 0x7F5F, 0xEEB9, 0x7F60, 0xC146, 0x7F61, 0xEEB8, 0x7F62, 0xB0D5, + 0x7F63, 0xC147, 0x7F64, 0xC148, 0x7F65, 0xC149, 0x7F66, 0xC14A, 0x7F67, 0xC14B, 0x7F68, 0xEEBB, 0x7F69, 0xD5D6, 0x7F6A, 0xD7EF, + 0x7F6B, 0xC14C, 0x7F6C, 0xC14D, 0x7F6D, 0xC14E, 0x7F6E, 0xD6C3, 0x7F6F, 0xC14F, 0x7F70, 0xC150, 0x7F71, 0xEEBD, 0x7F72, 0xCAF0, + 0x7F73, 0xC151, 0x7F74, 0xEEBC, 0x7F75, 0xC152, 0x7F76, 0xC153, 0x7F77, 0xC154, 0x7F78, 0xC155, 0x7F79, 0xEEBE, 0x7F7A, 0xC156, + 0x7F7B, 0xC157, 0x7F7C, 0xC158, 0x7F7D, 0xC159, 0x7F7E, 0xEEC0, 0x7F7F, 0xC15A, 0x7F80, 0xC15B, 0x7F81, 0xEEBF, 0x7F82, 0xC15C, + 0x7F83, 0xC15D, 0x7F84, 0xC15E, 0x7F85, 0xC15F, 0x7F86, 0xC160, 0x7F87, 0xC161, 0x7F88, 0xC162, 0x7F89, 0xC163, 0x7F8A, 0xD1F2, + 0x7F8B, 0xC164, 0x7F8C, 0xC7BC, 0x7F8D, 0xC165, 0x7F8E, 0xC3C0, 0x7F8F, 0xC166, 0x7F90, 0xC167, 0x7F91, 0xC168, 0x7F92, 0xC169, + 0x7F93, 0xC16A, 0x7F94, 0xB8E1, 0x7F95, 0xC16B, 0x7F96, 0xC16C, 0x7F97, 0xC16D, 0x7F98, 0xC16E, 0x7F99, 0xC16F, 0x7F9A, 0xC1E7, + 0x7F9B, 0xC170, 0x7F9C, 0xC171, 0x7F9D, 0xF4C6, 0x7F9E, 0xD0DF, 0x7F9F, 0xF4C7, 0x7FA0, 0xC172, 0x7FA1, 0xCFDB, 0x7FA2, 0xC173, + 0x7FA3, 0xC174, 0x7FA4, 0xC8BA, 0x7FA5, 0xC175, 0x7FA6, 0xC176, 0x7FA7, 0xF4C8, 0x7FA8, 0xC177, 0x7FA9, 0xC178, 0x7FAA, 0xC179, + 0x7FAB, 0xC17A, 0x7FAC, 0xC17B, 0x7FAD, 0xC17C, 0x7FAE, 0xC17D, 0x7FAF, 0xF4C9, 0x7FB0, 0xF4CA, 0x7FB1, 0xC17E, 0x7FB2, 0xF4CB, + 0x7FB3, 0xC180, 0x7FB4, 0xC181, 0x7FB5, 0xC182, 0x7FB6, 0xC183, 0x7FB7, 0xC184, 0x7FB8, 0xD9FA, 0x7FB9, 0xB8FE, 0x7FBA, 0xC185, + 0x7FBB, 0xC186, 0x7FBC, 0xE5F1, 0x7FBD, 0xD3F0, 0x7FBE, 0xC187, 0x7FBF, 0xF4E0, 0x7FC0, 0xC188, 0x7FC1, 0xCECC, 0x7FC2, 0xC189, + 0x7FC3, 0xC18A, 0x7FC4, 0xC18B, 0x7FC5, 0xB3E1, 0x7FC6, 0xC18C, 0x7FC7, 0xC18D, 0x7FC8, 0xC18E, 0x7FC9, 0xC18F, 0x7FCA, 0xF1B4, + 0x7FCB, 0xC190, 0x7FCC, 0xD2EE, 0x7FCD, 0xC191, 0x7FCE, 0xF4E1, 0x7FCF, 0xC192, 0x7FD0, 0xC193, 0x7FD1, 0xC194, 0x7FD2, 0xC195, + 0x7FD3, 0xC196, 0x7FD4, 0xCFE8, 0x7FD5, 0xF4E2, 0x7FD6, 0xC197, 0x7FD7, 0xC198, 0x7FD8, 0xC7CC, 0x7FD9, 0xC199, 0x7FDA, 0xC19A, + 0x7FDB, 0xC19B, 0x7FDC, 0xC19C, 0x7FDD, 0xC19D, 0x7FDE, 0xC19E, 0x7FDF, 0xB5D4, 0x7FE0, 0xB4E4, 0x7FE1, 0xF4E4, 0x7FE2, 0xC19F, + 0x7FE3, 0xC1A0, 0x7FE4, 0xC240, 0x7FE5, 0xF4E3, 0x7FE6, 0xF4E5, 0x7FE7, 0xC241, 0x7FE8, 0xC242, 0x7FE9, 0xF4E6, 0x7FEA, 0xC243, + 0x7FEB, 0xC244, 0x7FEC, 0xC245, 0x7FED, 0xC246, 0x7FEE, 0xF4E7, 0x7FEF, 0xC247, 0x7FF0, 0xBAB2, 0x7FF1, 0xB0BF, 0x7FF2, 0xC248, + 0x7FF3, 0xF4E8, 0x7FF4, 0xC249, 0x7FF5, 0xC24A, 0x7FF6, 0xC24B, 0x7FF7, 0xC24C, 0x7FF8, 0xC24D, 0x7FF9, 0xC24E, 0x7FFA, 0xC24F, + 0x7FFB, 0xB7AD, 0x7FFC, 0xD2ED, 0x7FFD, 0xC250, 0x7FFE, 0xC251, 0x7FFF, 0xC252, 0x8000, 0xD2AB, 0x8001, 0xC0CF, 0x8002, 0xC253, + 0x8003, 0xBFBC, 0x8004, 0xEBA3, 0x8005, 0xD5DF, 0x8006, 0xEAC8, 0x8007, 0xC254, 0x8008, 0xC255, 0x8009, 0xC256, 0x800A, 0xC257, + 0x800B, 0xF1F3, 0x800C, 0xB6F8, 0x800D, 0xCBA3, 0x800E, 0xC258, 0x800F, 0xC259, 0x8010, 0xC4CD, 0x8011, 0xC25A, 0x8012, 0xF1E7, + 0x8013, 0xC25B, 0x8014, 0xF1E8, 0x8015, 0xB8FB, 0x8016, 0xF1E9, 0x8017, 0xBAC4, 0x8018, 0xD4C5, 0x8019, 0xB0D2, 0x801A, 0xC25C, + 0x801B, 0xC25D, 0x801C, 0xF1EA, 0x801D, 0xC25E, 0x801E, 0xC25F, 0x801F, 0xC260, 0x8020, 0xF1EB, 0x8021, 0xC261, 0x8022, 0xF1EC, + 0x8023, 0xC262, 0x8024, 0xC263, 0x8025, 0xF1ED, 0x8026, 0xF1EE, 0x8027, 0xF1EF, 0x8028, 0xF1F1, 0x8029, 0xF1F0, 0x802A, 0xC5D5, + 0x802B, 0xC264, 0x802C, 0xC265, 0x802D, 0xC266, 0x802E, 0xC267, 0x802F, 0xC268, 0x8030, 0xC269, 0x8031, 0xF1F2, 0x8032, 0xC26A, + 0x8033, 0xB6FA, 0x8034, 0xC26B, 0x8035, 0xF1F4, 0x8036, 0xD2AE, 0x8037, 0xDEC7, 0x8038, 0xCBCA, 0x8039, 0xC26C, 0x803A, 0xC26D, + 0x803B, 0xB3DC, 0x803C, 0xC26E, 0x803D, 0xB5A2, 0x803E, 0xC26F, 0x803F, 0xB9A2, 0x8040, 0xC270, 0x8041, 0xC271, 0x8042, 0xC4F4, + 0x8043, 0xF1F5, 0x8044, 0xC272, 0x8045, 0xC273, 0x8046, 0xF1F6, 0x8047, 0xC274, 0x8048, 0xC275, 0x8049, 0xC276, 0x804A, 0xC1C4, + 0x804B, 0xC1FB, 0x804C, 0xD6B0, 0x804D, 0xF1F7, 0x804E, 0xC277, 0x804F, 0xC278, 0x8050, 0xC279, 0x8051, 0xC27A, 0x8052, 0xF1F8, + 0x8053, 0xC27B, 0x8054, 0xC1AA, 0x8055, 0xC27C, 0x8056, 0xC27D, 0x8057, 0xC27E, 0x8058, 0xC6B8, 0x8059, 0xC280, 0x805A, 0xBEDB, + 0x805B, 0xC281, 0x805C, 0xC282, 0x805D, 0xC283, 0x805E, 0xC284, 0x805F, 0xC285, 0x8060, 0xC286, 0x8061, 0xC287, 0x8062, 0xC288, + 0x8063, 0xC289, 0x8064, 0xC28A, 0x8065, 0xC28B, 0x8066, 0xC28C, 0x8067, 0xC28D, 0x8068, 0xC28E, 0x8069, 0xF1F9, 0x806A, 0xB4CF, + 0x806B, 0xC28F, 0x806C, 0xC290, 0x806D, 0xC291, 0x806E, 0xC292, 0x806F, 0xC293, 0x8070, 0xC294, 0x8071, 0xF1FA, 0x8072, 0xC295, + 0x8073, 0xC296, 0x8074, 0xC297, 0x8075, 0xC298, 0x8076, 0xC299, 0x8077, 0xC29A, 0x8078, 0xC29B, 0x8079, 0xC29C, 0x807A, 0xC29D, + 0x807B, 0xC29E, 0x807C, 0xC29F, 0x807D, 0xC2A0, 0x807E, 0xC340, 0x807F, 0xEDB2, 0x8080, 0xEDB1, 0x8081, 0xC341, 0x8082, 0xC342, + 0x8083, 0xCBE0, 0x8084, 0xD2DE, 0x8085, 0xC343, 0x8086, 0xCBC1, 0x8087, 0xD5D8, 0x8088, 0xC344, 0x8089, 0xC8E2, 0x808A, 0xC345, + 0x808B, 0xC0DF, 0x808C, 0xBCA1, 0x808D, 0xC346, 0x808E, 0xC347, 0x808F, 0xC348, 0x8090, 0xC349, 0x8091, 0xC34A, 0x8092, 0xC34B, + 0x8093, 0xEBC1, 0x8094, 0xC34C, 0x8095, 0xC34D, 0x8096, 0xD0A4, 0x8097, 0xC34E, 0x8098, 0xD6E2, 0x8099, 0xC34F, 0x809A, 0xB6C7, + 0x809B, 0xB8D8, 0x809C, 0xEBC0, 0x809D, 0xB8CE, 0x809E, 0xC350, 0x809F, 0xEBBF, 0x80A0, 0xB3A6, 0x80A1, 0xB9C9, 0x80A2, 0xD6AB, + 0x80A3, 0xC351, 0x80A4, 0xB7F4, 0x80A5, 0xB7CA, 0x80A6, 0xC352, 0x80A7, 0xC353, 0x80A8, 0xC354, 0x80A9, 0xBCE7, 0x80AA, 0xB7BE, + 0x80AB, 0xEBC6, 0x80AC, 0xC355, 0x80AD, 0xEBC7, 0x80AE, 0xB0B9, 0x80AF, 0xBFCF, 0x80B0, 0xC356, 0x80B1, 0xEBC5, 0x80B2, 0xD3FD, + 0x80B3, 0xC357, 0x80B4, 0xEBC8, 0x80B5, 0xC358, 0x80B6, 0xC359, 0x80B7, 0xEBC9, 0x80B8, 0xC35A, 0x80B9, 0xC35B, 0x80BA, 0xB7CE, + 0x80BB, 0xC35C, 0x80BC, 0xEBC2, 0x80BD, 0xEBC4, 0x80BE, 0xC9F6, 0x80BF, 0xD6D7, 0x80C0, 0xD5CD, 0x80C1, 0xD0B2, 0x80C2, 0xEBCF, + 0x80C3, 0xCEB8, 0x80C4, 0xEBD0, 0x80C5, 0xC35D, 0x80C6, 0xB5A8, 0x80C7, 0xC35E, 0x80C8, 0xC35F, 0x80C9, 0xC360, 0x80CA, 0xC361, + 0x80CB, 0xC362, 0x80CC, 0xB1B3, 0x80CD, 0xEBD2, 0x80CE, 0xCCA5, 0x80CF, 0xC363, 0x80D0, 0xC364, 0x80D1, 0xC365, 0x80D2, 0xC366, + 0x80D3, 0xC367, 0x80D4, 0xC368, 0x80D5, 0xC369, 0x80D6, 0xC5D6, 0x80D7, 0xEBD3, 0x80D8, 0xC36A, 0x80D9, 0xEBD1, 0x80DA, 0xC5DF, + 0x80DB, 0xEBCE, 0x80DC, 0xCAA4, 0x80DD, 0xEBD5, 0x80DE, 0xB0FB, 0x80DF, 0xC36B, 0x80E0, 0xC36C, 0x80E1, 0xBAFA, 0x80E2, 0xC36D, + 0x80E3, 0xC36E, 0x80E4, 0xD8B7, 0x80E5, 0xF1E3, 0x80E6, 0xC36F, 0x80E7, 0xEBCA, 0x80E8, 0xEBCB, 0x80E9, 0xEBCC, 0x80EA, 0xEBCD, + 0x80EB, 0xEBD6, 0x80EC, 0xE6C0, 0x80ED, 0xEBD9, 0x80EE, 0xC370, 0x80EF, 0xBFE8, 0x80F0, 0xD2C8, 0x80F1, 0xEBD7, 0x80F2, 0xEBDC, + 0x80F3, 0xB8EC, 0x80F4, 0xEBD8, 0x80F5, 0xC371, 0x80F6, 0xBDBA, 0x80F7, 0xC372, 0x80F8, 0xD0D8, 0x80F9, 0xC373, 0x80FA, 0xB0B7, + 0x80FB, 0xC374, 0x80FC, 0xEBDD, 0x80FD, 0xC4DC, 0x80FE, 0xC375, 0x80FF, 0xC376, 0x8100, 0xC377, 0x8101, 0xC378, 0x8102, 0xD6AC, + 0x8103, 0xC379, 0x8104, 0xC37A, 0x8105, 0xC37B, 0x8106, 0xB4E0, 0x8107, 0xC37C, 0x8108, 0xC37D, 0x8109, 0xC2F6, 0x810A, 0xBCB9, + 0x810B, 0xC37E, 0x810C, 0xC380, 0x810D, 0xEBDA, 0x810E, 0xEBDB, 0x810F, 0xD4E0, 0x8110, 0xC6EA, 0x8111, 0xC4D4, 0x8112, 0xEBDF, + 0x8113, 0xC5A7, 0x8114, 0xD9F5, 0x8115, 0xC381, 0x8116, 0xB2B1, 0x8117, 0xC382, 0x8118, 0xEBE4, 0x8119, 0xC383, 0x811A, 0xBDC5, + 0x811B, 0xC384, 0x811C, 0xC385, 0x811D, 0xC386, 0x811E, 0xEBE2, 0x811F, 0xC387, 0x8120, 0xC388, 0x8121, 0xC389, 0x8122, 0xC38A, + 0x8123, 0xC38B, 0x8124, 0xC38C, 0x8125, 0xC38D, 0x8126, 0xC38E, 0x8127, 0xC38F, 0x8128, 0xC390, 0x8129, 0xC391, 0x812A, 0xC392, + 0x812B, 0xC393, 0x812C, 0xEBE3, 0x812D, 0xC394, 0x812E, 0xC395, 0x812F, 0xB8AC, 0x8130, 0xC396, 0x8131, 0xCDD1, 0x8132, 0xEBE5, + 0x8133, 0xC397, 0x8134, 0xC398, 0x8135, 0xC399, 0x8136, 0xEBE1, 0x8137, 0xC39A, 0x8138, 0xC1B3, 0x8139, 0xC39B, 0x813A, 0xC39C, + 0x813B, 0xC39D, 0x813C, 0xC39E, 0x813D, 0xC39F, 0x813E, 0xC6A2, 0x813F, 0xC3A0, 0x8140, 0xC440, 0x8141, 0xC441, 0x8142, 0xC442, + 0x8143, 0xC443, 0x8144, 0xC444, 0x8145, 0xC445, 0x8146, 0xCCF3, 0x8147, 0xC446, 0x8148, 0xEBE6, 0x8149, 0xC447, 0x814A, 0xC0B0, + 0x814B, 0xD2B8, 0x814C, 0xEBE7, 0x814D, 0xC448, 0x814E, 0xC449, 0x814F, 0xC44A, 0x8150, 0xB8AF, 0x8151, 0xB8AD, 0x8152, 0xC44B, + 0x8153, 0xEBE8, 0x8154, 0xC7BB, 0x8155, 0xCDF3, 0x8156, 0xC44C, 0x8157, 0xC44D, 0x8158, 0xC44E, 0x8159, 0xEBEA, 0x815A, 0xEBEB, + 0x815B, 0xC44F, 0x815C, 0xC450, 0x815D, 0xC451, 0x815E, 0xC452, 0x815F, 0xC453, 0x8160, 0xEBED, 0x8161, 0xC454, 0x8162, 0xC455, + 0x8163, 0xC456, 0x8164, 0xC457, 0x8165, 0xD0C8, 0x8166, 0xC458, 0x8167, 0xEBF2, 0x8168, 0xC459, 0x8169, 0xEBEE, 0x816A, 0xC45A, + 0x816B, 0xC45B, 0x816C, 0xC45C, 0x816D, 0xEBF1, 0x816E, 0xC8F9, 0x816F, 0xC45D, 0x8170, 0xD1FC, 0x8171, 0xEBEC, 0x8172, 0xC45E, + 0x8173, 0xC45F, 0x8174, 0xEBE9, 0x8175, 0xC460, 0x8176, 0xC461, 0x8177, 0xC462, 0x8178, 0xC463, 0x8179, 0xB8B9, 0x817A, 0xCFD9, + 0x817B, 0xC4E5, 0x817C, 0xEBEF, 0x817D, 0xEBF0, 0x817E, 0xCCDA, 0x817F, 0xCDC8, 0x8180, 0xB0F2, 0x8181, 0xC464, 0x8182, 0xEBF6, + 0x8183, 0xC465, 0x8184, 0xC466, 0x8185, 0xC467, 0x8186, 0xC468, 0x8187, 0xC469, 0x8188, 0xEBF5, 0x8189, 0xC46A, 0x818A, 0xB2B2, + 0x818B, 0xC46B, 0x818C, 0xC46C, 0x818D, 0xC46D, 0x818E, 0xC46E, 0x818F, 0xB8E0, 0x8190, 0xC46F, 0x8191, 0xEBF7, 0x8192, 0xC470, + 0x8193, 0xC471, 0x8194, 0xC472, 0x8195, 0xC473, 0x8196, 0xC474, 0x8197, 0xC475, 0x8198, 0xB1EC, 0x8199, 0xC476, 0x819A, 0xC477, + 0x819B, 0xCCC5, 0x819C, 0xC4A4, 0x819D, 0xCFA5, 0x819E, 0xC478, 0x819F, 0xC479, 0x81A0, 0xC47A, 0x81A1, 0xC47B, 0x81A2, 0xC47C, + 0x81A3, 0xEBF9, 0x81A4, 0xC47D, 0x81A5, 0xC47E, 0x81A6, 0xECA2, 0x81A7, 0xC480, 0x81A8, 0xC5F2, 0x81A9, 0xC481, 0x81AA, 0xEBFA, + 0x81AB, 0xC482, 0x81AC, 0xC483, 0x81AD, 0xC484, 0x81AE, 0xC485, 0x81AF, 0xC486, 0x81B0, 0xC487, 0x81B1, 0xC488, 0x81B2, 0xC489, + 0x81B3, 0xC9C5, 0x81B4, 0xC48A, 0x81B5, 0xC48B, 0x81B6, 0xC48C, 0x81B7, 0xC48D, 0x81B8, 0xC48E, 0x81B9, 0xC48F, 0x81BA, 0xE2DF, + 0x81BB, 0xEBFE, 0x81BC, 0xC490, 0x81BD, 0xC491, 0x81BE, 0xC492, 0x81BF, 0xC493, 0x81C0, 0xCDCE, 0x81C1, 0xECA1, 0x81C2, 0xB1DB, + 0x81C3, 0xD3B7, 0x81C4, 0xC494, 0x81C5, 0xC495, 0x81C6, 0xD2DC, 0x81C7, 0xC496, 0x81C8, 0xC497, 0x81C9, 0xC498, 0x81CA, 0xEBFD, + 0x81CB, 0xC499, 0x81CC, 0xEBFB, 0x81CD, 0xC49A, 0x81CE, 0xC49B, 0x81CF, 0xC49C, 0x81D0, 0xC49D, 0x81D1, 0xC49E, 0x81D2, 0xC49F, + 0x81D3, 0xC4A0, 0x81D4, 0xC540, 0x81D5, 0xC541, 0x81D6, 0xC542, 0x81D7, 0xC543, 0x81D8, 0xC544, 0x81D9, 0xC545, 0x81DA, 0xC546, + 0x81DB, 0xC547, 0x81DC, 0xC548, 0x81DD, 0xC549, 0x81DE, 0xC54A, 0x81DF, 0xC54B, 0x81E0, 0xC54C, 0x81E1, 0xC54D, 0x81E2, 0xC54E, + 0x81E3, 0xB3BC, 0x81E4, 0xC54F, 0x81E5, 0xC550, 0x81E6, 0xC551, 0x81E7, 0xEAB0, 0x81E8, 0xC552, 0x81E9, 0xC553, 0x81EA, 0xD7D4, + 0x81EB, 0xC554, 0x81EC, 0xF4AB, 0x81ED, 0xB3F4, 0x81EE, 0xC555, 0x81EF, 0xC556, 0x81F0, 0xC557, 0x81F1, 0xC558, 0x81F2, 0xC559, + 0x81F3, 0xD6C1, 0x81F4, 0xD6C2, 0x81F5, 0xC55A, 0x81F6, 0xC55B, 0x81F7, 0xC55C, 0x81F8, 0xC55D, 0x81F9, 0xC55E, 0x81FA, 0xC55F, + 0x81FB, 0xD5E9, 0x81FC, 0xBECA, 0x81FD, 0xC560, 0x81FE, 0xF4A7, 0x81FF, 0xC561, 0x8200, 0xD2A8, 0x8201, 0xF4A8, 0x8202, 0xF4A9, + 0x8203, 0xC562, 0x8204, 0xF4AA, 0x8205, 0xBECB, 0x8206, 0xD3DF, 0x8207, 0xC563, 0x8208, 0xC564, 0x8209, 0xC565, 0x820A, 0xC566, + 0x820B, 0xC567, 0x820C, 0xC9E0, 0x820D, 0xC9E1, 0x820E, 0xC568, 0x820F, 0xC569, 0x8210, 0xF3C2, 0x8211, 0xC56A, 0x8212, 0xCAE6, + 0x8213, 0xC56B, 0x8214, 0xCCF2, 0x8215, 0xC56C, 0x8216, 0xC56D, 0x8217, 0xC56E, 0x8218, 0xC56F, 0x8219, 0xC570, 0x821A, 0xC571, + 0x821B, 0xE2B6, 0x821C, 0xCBB4, 0x821D, 0xC572, 0x821E, 0xCEE8, 0x821F, 0xD6DB, 0x8220, 0xC573, 0x8221, 0xF4AD, 0x8222, 0xF4AE, + 0x8223, 0xF4AF, 0x8224, 0xC574, 0x8225, 0xC575, 0x8226, 0xC576, 0x8227, 0xC577, 0x8228, 0xF4B2, 0x8229, 0xC578, 0x822A, 0xBABD, + 0x822B, 0xF4B3, 0x822C, 0xB0E3, 0x822D, 0xF4B0, 0x822E, 0xC579, 0x822F, 0xF4B1, 0x8230, 0xBDA2, 0x8231, 0xB2D5, 0x8232, 0xC57A, + 0x8233, 0xF4B6, 0x8234, 0xF4B7, 0x8235, 0xB6E6, 0x8236, 0xB2B0, 0x8237, 0xCFCF, 0x8238, 0xF4B4, 0x8239, 0xB4AC, 0x823A, 0xC57B, + 0x823B, 0xF4B5, 0x823C, 0xC57C, 0x823D, 0xC57D, 0x823E, 0xF4B8, 0x823F, 0xC57E, 0x8240, 0xC580, 0x8241, 0xC581, 0x8242, 0xC582, + 0x8243, 0xC583, 0x8244, 0xF4B9, 0x8245, 0xC584, 0x8246, 0xC585, 0x8247, 0xCDA7, 0x8248, 0xC586, 0x8249, 0xF4BA, 0x824A, 0xC587, + 0x824B, 0xF4BB, 0x824C, 0xC588, 0x824D, 0xC589, 0x824E, 0xC58A, 0x824F, 0xF4BC, 0x8250, 0xC58B, 0x8251, 0xC58C, 0x8252, 0xC58D, + 0x8253, 0xC58E, 0x8254, 0xC58F, 0x8255, 0xC590, 0x8256, 0xC591, 0x8257, 0xC592, 0x8258, 0xCBD2, 0x8259, 0xC593, 0x825A, 0xF4BD, + 0x825B, 0xC594, 0x825C, 0xC595, 0x825D, 0xC596, 0x825E, 0xC597, 0x825F, 0xF4BE, 0x8260, 0xC598, 0x8261, 0xC599, 0x8262, 0xC59A, + 0x8263, 0xC59B, 0x8264, 0xC59C, 0x8265, 0xC59D, 0x8266, 0xC59E, 0x8267, 0xC59F, 0x8268, 0xF4BF, 0x8269, 0xC5A0, 0x826A, 0xC640, + 0x826B, 0xC641, 0x826C, 0xC642, 0x826D, 0xC643, 0x826E, 0xF4DE, 0x826F, 0xC1BC, 0x8270, 0xBCE8, 0x8271, 0xC644, 0x8272, 0xC9AB, + 0x8273, 0xD1DE, 0x8274, 0xE5F5, 0x8275, 0xC645, 0x8276, 0xC646, 0x8277, 0xC647, 0x8278, 0xC648, 0x8279, 0xDCB3, 0x827A, 0xD2D5, + 0x827B, 0xC649, 0x827C, 0xC64A, 0x827D, 0xDCB4, 0x827E, 0xB0AC, 0x827F, 0xDCB5, 0x8280, 0xC64B, 0x8281, 0xC64C, 0x8282, 0xBDDA, + 0x8283, 0xC64D, 0x8284, 0xDCB9, 0x8285, 0xC64E, 0x8286, 0xC64F, 0x8287, 0xC650, 0x8288, 0xD8C2, 0x8289, 0xC651, 0x828A, 0xDCB7, + 0x828B, 0xD3F3, 0x828C, 0xC652, 0x828D, 0xC9D6, 0x828E, 0xDCBA, 0x828F, 0xDCB6, 0x8290, 0xC653, 0x8291, 0xDCBB, 0x8292, 0xC3A2, + 0x8293, 0xC654, 0x8294, 0xC655, 0x8295, 0xC656, 0x8296, 0xC657, 0x8297, 0xDCBC, 0x8298, 0xDCC5, 0x8299, 0xDCBD, 0x829A, 0xC658, + 0x829B, 0xC659, 0x829C, 0xCEDF, 0x829D, 0xD6A5, 0x829E, 0xC65A, 0x829F, 0xDCCF, 0x82A0, 0xC65B, 0x82A1, 0xDCCD, 0x82A2, 0xC65C, + 0x82A3, 0xC65D, 0x82A4, 0xDCD2, 0x82A5, 0xBDE6, 0x82A6, 0xC2AB, 0x82A7, 0xC65E, 0x82A8, 0xDCB8, 0x82A9, 0xDCCB, 0x82AA, 0xDCCE, + 0x82AB, 0xDCBE, 0x82AC, 0xB7D2, 0x82AD, 0xB0C5, 0x82AE, 0xDCC7, 0x82AF, 0xD0BE, 0x82B0, 0xDCC1, 0x82B1, 0xBBA8, 0x82B2, 0xC65F, + 0x82B3, 0xB7BC, 0x82B4, 0xDCCC, 0x82B5, 0xC660, 0x82B6, 0xC661, 0x82B7, 0xDCC6, 0x82B8, 0xDCBF, 0x82B9, 0xC7DB, 0x82BA, 0xC662, + 0x82BB, 0xC663, 0x82BC, 0xC664, 0x82BD, 0xD1BF, 0x82BE, 0xDCC0, 0x82BF, 0xC665, 0x82C0, 0xC666, 0x82C1, 0xDCCA, 0x82C2, 0xC667, + 0x82C3, 0xC668, 0x82C4, 0xDCD0, 0x82C5, 0xC669, 0x82C6, 0xC66A, 0x82C7, 0xCEAD, 0x82C8, 0xDCC2, 0x82C9, 0xC66B, 0x82CA, 0xDCC3, + 0x82CB, 0xDCC8, 0x82CC, 0xDCC9, 0x82CD, 0xB2D4, 0x82CE, 0xDCD1, 0x82CF, 0xCBD5, 0x82D0, 0xC66C, 0x82D1, 0xD4B7, 0x82D2, 0xDCDB, + 0x82D3, 0xDCDF, 0x82D4, 0xCCA6, 0x82D5, 0xDCE6, 0x82D6, 0xC66D, 0x82D7, 0xC3E7, 0x82D8, 0xDCDC, 0x82D9, 0xC66E, 0x82DA, 0xC66F, + 0x82DB, 0xBFC1, 0x82DC, 0xDCD9, 0x82DD, 0xC670, 0x82DE, 0xB0FA, 0x82DF, 0xB9B6, 0x82E0, 0xDCE5, 0x82E1, 0xDCD3, 0x82E2, 0xC671, + 0x82E3, 0xDCC4, 0x82E4, 0xDCD6, 0x82E5, 0xC8F4, 0x82E6, 0xBFE0, 0x82E7, 0xC672, 0x82E8, 0xC673, 0x82E9, 0xC674, 0x82EA, 0xC675, + 0x82EB, 0xC9BB, 0x82EC, 0xC676, 0x82ED, 0xC677, 0x82EE, 0xC678, 0x82EF, 0xB1BD, 0x82F0, 0xC679, 0x82F1, 0xD3A2, 0x82F2, 0xC67A, + 0x82F3, 0xC67B, 0x82F4, 0xDCDA, 0x82F5, 0xC67C, 0x82F6, 0xC67D, 0x82F7, 0xDCD5, 0x82F8, 0xC67E, 0x82F9, 0xC6BB, 0x82FA, 0xC680, + 0x82FB, 0xDCDE, 0x82FC, 0xC681, 0x82FD, 0xC682, 0x82FE, 0xC683, 0x82FF, 0xC684, 0x8300, 0xC685, 0x8301, 0xD7C2, 0x8302, 0xC3AF, + 0x8303, 0xB7B6, 0x8304, 0xC7D1, 0x8305, 0xC3A9, 0x8306, 0xDCE2, 0x8307, 0xDCD8, 0x8308, 0xDCEB, 0x8309, 0xDCD4, 0x830A, 0xC686, + 0x830B, 0xC687, 0x830C, 0xDCDD, 0x830D, 0xC688, 0x830E, 0xBEA5, 0x830F, 0xDCD7, 0x8310, 0xC689, 0x8311, 0xDCE0, 0x8312, 0xC68A, + 0x8313, 0xC68B, 0x8314, 0xDCE3, 0x8315, 0xDCE4, 0x8316, 0xC68C, 0x8317, 0xDCF8, 0x8318, 0xC68D, 0x8319, 0xC68E, 0x831A, 0xDCE1, + 0x831B, 0xDDA2, 0x831C, 0xDCE7, 0x831D, 0xC68F, 0x831E, 0xC690, 0x831F, 0xC691, 0x8320, 0xC692, 0x8321, 0xC693, 0x8322, 0xC694, + 0x8323, 0xC695, 0x8324, 0xC696, 0x8325, 0xC697, 0x8326, 0xC698, 0x8327, 0xBCEB, 0x8328, 0xB4C4, 0x8329, 0xC699, 0x832A, 0xC69A, + 0x832B, 0xC3A3, 0x832C, 0xB2E7, 0x832D, 0xDCFA, 0x832E, 0xC69B, 0x832F, 0xDCF2, 0x8330, 0xC69C, 0x8331, 0xDCEF, 0x8332, 0xC69D, + 0x8333, 0xDCFC, 0x8334, 0xDCEE, 0x8335, 0xD2F0, 0x8336, 0xB2E8, 0x8337, 0xC69E, 0x8338, 0xC8D7, 0x8339, 0xC8E3, 0x833A, 0xDCFB, + 0x833B, 0xC69F, 0x833C, 0xDCED, 0x833D, 0xC6A0, 0x833E, 0xC740, 0x833F, 0xC741, 0x8340, 0xDCF7, 0x8341, 0xC742, 0x8342, 0xC743, + 0x8343, 0xDCF5, 0x8344, 0xC744, 0x8345, 0xC745, 0x8346, 0xBEA3, 0x8347, 0xDCF4, 0x8348, 0xC746, 0x8349, 0xB2DD, 0x834A, 0xC747, + 0x834B, 0xC748, 0x834C, 0xC749, 0x834D, 0xC74A, 0x834E, 0xC74B, 0x834F, 0xDCF3, 0x8350, 0xBCF6, 0x8351, 0xDCE8, 0x8352, 0xBBC4, + 0x8353, 0xC74C, 0x8354, 0xC0F3, 0x8355, 0xC74D, 0x8356, 0xC74E, 0x8357, 0xC74F, 0x8358, 0xC750, 0x8359, 0xC751, 0x835A, 0xBCD4, + 0x835B, 0xDCE9, 0x835C, 0xDCEA, 0x835D, 0xC752, 0x835E, 0xDCF1, 0x835F, 0xDCF6, 0x8360, 0xDCF9, 0x8361, 0xB5B4, 0x8362, 0xC753, + 0x8363, 0xC8D9, 0x8364, 0xBBE7, 0x8365, 0xDCFE, 0x8366, 0xDCFD, 0x8367, 0xD3AB, 0x8368, 0xDDA1, 0x8369, 0xDDA3, 0x836A, 0xDDA5, + 0x836B, 0xD2F1, 0x836C, 0xDDA4, 0x836D, 0xDDA6, 0x836E, 0xDDA7, 0x836F, 0xD2A9, 0x8370, 0xC754, 0x8371, 0xC755, 0x8372, 0xC756, + 0x8373, 0xC757, 0x8374, 0xC758, 0x8375, 0xC759, 0x8376, 0xC75A, 0x8377, 0xBAC9, 0x8378, 0xDDA9, 0x8379, 0xC75B, 0x837A, 0xC75C, + 0x837B, 0xDDB6, 0x837C, 0xDDB1, 0x837D, 0xDDB4, 0x837E, 0xC75D, 0x837F, 0xC75E, 0x8380, 0xC75F, 0x8381, 0xC760, 0x8382, 0xC761, + 0x8383, 0xC762, 0x8384, 0xC763, 0x8385, 0xDDB0, 0x8386, 0xC6CE, 0x8387, 0xC764, 0x8388, 0xC765, 0x8389, 0xC0F2, 0x838A, 0xC766, + 0x838B, 0xC767, 0x838C, 0xC768, 0x838D, 0xC769, 0x838E, 0xC9AF, 0x838F, 0xC76A, 0x8390, 0xC76B, 0x8391, 0xC76C, 0x8392, 0xDCEC, + 0x8393, 0xDDAE, 0x8394, 0xC76D, 0x8395, 0xC76E, 0x8396, 0xC76F, 0x8397, 0xC770, 0x8398, 0xDDB7, 0x8399, 0xC771, 0x839A, 0xC772, + 0x839B, 0xDCF0, 0x839C, 0xDDAF, 0x839D, 0xC773, 0x839E, 0xDDB8, 0x839F, 0xC774, 0x83A0, 0xDDAC, 0x83A1, 0xC775, 0x83A2, 0xC776, + 0x83A3, 0xC777, 0x83A4, 0xC778, 0x83A5, 0xC779, 0x83A6, 0xC77A, 0x83A7, 0xC77B, 0x83A8, 0xDDB9, 0x83A9, 0xDDB3, 0x83AA, 0xDDAD, + 0x83AB, 0xC4AA, 0x83AC, 0xC77C, 0x83AD, 0xC77D, 0x83AE, 0xC77E, 0x83AF, 0xC780, 0x83B0, 0xDDA8, 0x83B1, 0xC0B3, 0x83B2, 0xC1AB, + 0x83B3, 0xDDAA, 0x83B4, 0xDDAB, 0x83B5, 0xC781, 0x83B6, 0xDDB2, 0x83B7, 0xBBF1, 0x83B8, 0xDDB5, 0x83B9, 0xD3A8, 0x83BA, 0xDDBA, + 0x83BB, 0xC782, 0x83BC, 0xDDBB, 0x83BD, 0xC3A7, 0x83BE, 0xC783, 0x83BF, 0xC784, 0x83C0, 0xDDD2, 0x83C1, 0xDDBC, 0x83C2, 0xC785, + 0x83C3, 0xC786, 0x83C4, 0xC787, 0x83C5, 0xDDD1, 0x83C6, 0xC788, 0x83C7, 0xB9BD, 0x83C8, 0xC789, 0x83C9, 0xC78A, 0x83CA, 0xBED5, + 0x83CB, 0xC78B, 0x83CC, 0xBEFA, 0x83CD, 0xC78C, 0x83CE, 0xC78D, 0x83CF, 0xBACA, 0x83D0, 0xC78E, 0x83D1, 0xC78F, 0x83D2, 0xC790, + 0x83D3, 0xC791, 0x83D4, 0xDDCA, 0x83D5, 0xC792, 0x83D6, 0xDDC5, 0x83D7, 0xC793, 0x83D8, 0xDDBF, 0x83D9, 0xC794, 0x83DA, 0xC795, + 0x83DB, 0xC796, 0x83DC, 0xB2CB, 0x83DD, 0xDDC3, 0x83DE, 0xC797, 0x83DF, 0xDDCB, 0x83E0, 0xB2A4, 0x83E1, 0xDDD5, 0x83E2, 0xC798, + 0x83E3, 0xC799, 0x83E4, 0xC79A, 0x83E5, 0xDDBE, 0x83E6, 0xC79B, 0x83E7, 0xC79C, 0x83E8, 0xC79D, 0x83E9, 0xC6D0, 0x83EA, 0xDDD0, + 0x83EB, 0xC79E, 0x83EC, 0xC79F, 0x83ED, 0xC7A0, 0x83EE, 0xC840, 0x83EF, 0xC841, 0x83F0, 0xDDD4, 0x83F1, 0xC1E2, 0x83F2, 0xB7C6, + 0x83F3, 0xC842, 0x83F4, 0xC843, 0x83F5, 0xC844, 0x83F6, 0xC845, 0x83F7, 0xC846, 0x83F8, 0xDDCE, 0x83F9, 0xDDCF, 0x83FA, 0xC847, + 0x83FB, 0xC848, 0x83FC, 0xC849, 0x83FD, 0xDDC4, 0x83FE, 0xC84A, 0x83FF, 0xC84B, 0x8400, 0xC84C, 0x8401, 0xDDBD, 0x8402, 0xC84D, + 0x8403, 0xDDCD, 0x8404, 0xCCD1, 0x8405, 0xC84E, 0x8406, 0xDDC9, 0x8407, 0xC84F, 0x8408, 0xC850, 0x8409, 0xC851, 0x840A, 0xC852, + 0x840B, 0xDDC2, 0x840C, 0xC3C8, 0x840D, 0xC6BC, 0x840E, 0xCEAE, 0x840F, 0xDDCC, 0x8410, 0xC853, 0x8411, 0xDDC8, 0x8412, 0xC854, + 0x8413, 0xC855, 0x8414, 0xC856, 0x8415, 0xC857, 0x8416, 0xC858, 0x8417, 0xC859, 0x8418, 0xDDC1, 0x8419, 0xC85A, 0x841A, 0xC85B, + 0x841B, 0xC85C, 0x841C, 0xDDC6, 0x841D, 0xC2DC, 0x841E, 0xC85D, 0x841F, 0xC85E, 0x8420, 0xC85F, 0x8421, 0xC860, 0x8422, 0xC861, + 0x8423, 0xC862, 0x8424, 0xD3A9, 0x8425, 0xD3AA, 0x8426, 0xDDD3, 0x8427, 0xCFF4, 0x8428, 0xC8F8, 0x8429, 0xC863, 0x842A, 0xC864, + 0x842B, 0xC865, 0x842C, 0xC866, 0x842D, 0xC867, 0x842E, 0xC868, 0x842F, 0xC869, 0x8430, 0xC86A, 0x8431, 0xDDE6, 0x8432, 0xC86B, + 0x8433, 0xC86C, 0x8434, 0xC86D, 0x8435, 0xC86E, 0x8436, 0xC86F, 0x8437, 0xC870, 0x8438, 0xDDC7, 0x8439, 0xC871, 0x843A, 0xC872, + 0x843B, 0xC873, 0x843C, 0xDDE0, 0x843D, 0xC2E4, 0x843E, 0xC874, 0x843F, 0xC875, 0x8440, 0xC876, 0x8441, 0xC877, 0x8442, 0xC878, + 0x8443, 0xC879, 0x8444, 0xC87A, 0x8445, 0xC87B, 0x8446, 0xDDE1, 0x8447, 0xC87C, 0x8448, 0xC87D, 0x8449, 0xC87E, 0x844A, 0xC880, + 0x844B, 0xC881, 0x844C, 0xC882, 0x844D, 0xC883, 0x844E, 0xC884, 0x844F, 0xC885, 0x8450, 0xC886, 0x8451, 0xDDD7, 0x8452, 0xC887, + 0x8453, 0xC888, 0x8454, 0xC889, 0x8455, 0xC88A, 0x8456, 0xC88B, 0x8457, 0xD6F8, 0x8458, 0xC88C, 0x8459, 0xDDD9, 0x845A, 0xDDD8, + 0x845B, 0xB8F0, 0x845C, 0xDDD6, 0x845D, 0xC88D, 0x845E, 0xC88E, 0x845F, 0xC88F, 0x8460, 0xC890, 0x8461, 0xC6CF, 0x8462, 0xC891, + 0x8463, 0xB6AD, 0x8464, 0xC892, 0x8465, 0xC893, 0x8466, 0xC894, 0x8467, 0xC895, 0x8468, 0xC896, 0x8469, 0xDDE2, 0x846A, 0xC897, + 0x846B, 0xBAF9, 0x846C, 0xD4E1, 0x846D, 0xDDE7, 0x846E, 0xC898, 0x846F, 0xC899, 0x8470, 0xC89A, 0x8471, 0xB4D0, 0x8472, 0xC89B, + 0x8473, 0xDDDA, 0x8474, 0xC89C, 0x8475, 0xBFFB, 0x8476, 0xDDE3, 0x8477, 0xC89D, 0x8478, 0xDDDF, 0x8479, 0xC89E, 0x847A, 0xDDDD, + 0x847B, 0xC89F, 0x847C, 0xC8A0, 0x847D, 0xC940, 0x847E, 0xC941, 0x847F, 0xC942, 0x8480, 0xC943, 0x8481, 0xC944, 0x8482, 0xB5D9, + 0x8483, 0xC945, 0x8484, 0xC946, 0x8485, 0xC947, 0x8486, 0xC948, 0x8487, 0xDDDB, 0x8488, 0xDDDC, 0x8489, 0xDDDE, 0x848A, 0xC949, + 0x848B, 0xBDAF, 0x848C, 0xDDE4, 0x848D, 0xC94A, 0x848E, 0xDDE5, 0x848F, 0xC94B, 0x8490, 0xC94C, 0x8491, 0xC94D, 0x8492, 0xC94E, + 0x8493, 0xC94F, 0x8494, 0xC950, 0x8495, 0xC951, 0x8496, 0xC952, 0x8497, 0xDDF5, 0x8498, 0xC953, 0x8499, 0xC3C9, 0x849A, 0xC954, + 0x849B, 0xC955, 0x849C, 0xCBE2, 0x849D, 0xC956, 0x849E, 0xC957, 0x849F, 0xC958, 0x84A0, 0xC959, 0x84A1, 0xDDF2, 0x84A2, 0xC95A, + 0x84A3, 0xC95B, 0x84A4, 0xC95C, 0x84A5, 0xC95D, 0x84A6, 0xC95E, 0x84A7, 0xC95F, 0x84A8, 0xC960, 0x84A9, 0xC961, 0x84AA, 0xC962, + 0x84AB, 0xC963, 0x84AC, 0xC964, 0x84AD, 0xC965, 0x84AE, 0xC966, 0x84AF, 0xD8E1, 0x84B0, 0xC967, 0x84B1, 0xC968, 0x84B2, 0xC6D1, + 0x84B3, 0xC969, 0x84B4, 0xDDF4, 0x84B5, 0xC96A, 0x84B6, 0xC96B, 0x84B7, 0xC96C, 0x84B8, 0xD5F4, 0x84B9, 0xDDF3, 0x84BA, 0xDDF0, + 0x84BB, 0xC96D, 0x84BC, 0xC96E, 0x84BD, 0xDDEC, 0x84BE, 0xC96F, 0x84BF, 0xDDEF, 0x84C0, 0xC970, 0x84C1, 0xDDE8, 0x84C2, 0xC971, + 0x84C3, 0xC972, 0x84C4, 0xD0EE, 0x84C5, 0xC973, 0x84C6, 0xC974, 0x84C7, 0xC975, 0x84C8, 0xC976, 0x84C9, 0xC8D8, 0x84CA, 0xDDEE, + 0x84CB, 0xC977, 0x84CC, 0xC978, 0x84CD, 0xDDE9, 0x84CE, 0xC979, 0x84CF, 0xC97A, 0x84D0, 0xDDEA, 0x84D1, 0xCBF2, 0x84D2, 0xC97B, + 0x84D3, 0xDDED, 0x84D4, 0xC97C, 0x84D5, 0xC97D, 0x84D6, 0xB1CD, 0x84D7, 0xC97E, 0x84D8, 0xC980, 0x84D9, 0xC981, 0x84DA, 0xC982, + 0x84DB, 0xC983, 0x84DC, 0xC984, 0x84DD, 0xC0B6, 0x84DE, 0xC985, 0x84DF, 0xBCBB, 0x84E0, 0xDDF1, 0x84E1, 0xC986, 0x84E2, 0xC987, + 0x84E3, 0xDDF7, 0x84E4, 0xC988, 0x84E5, 0xDDF6, 0x84E6, 0xDDEB, 0x84E7, 0xC989, 0x84E8, 0xC98A, 0x84E9, 0xC98B, 0x84EA, 0xC98C, + 0x84EB, 0xC98D, 0x84EC, 0xC5EE, 0x84ED, 0xC98E, 0x84EE, 0xC98F, 0x84EF, 0xC990, 0x84F0, 0xDDFB, 0x84F1, 0xC991, 0x84F2, 0xC992, + 0x84F3, 0xC993, 0x84F4, 0xC994, 0x84F5, 0xC995, 0x84F6, 0xC996, 0x84F7, 0xC997, 0x84F8, 0xC998, 0x84F9, 0xC999, 0x84FA, 0xC99A, + 0x84FB, 0xC99B, 0x84FC, 0xDEA4, 0x84FD, 0xC99C, 0x84FE, 0xC99D, 0x84FF, 0xDEA3, 0x8500, 0xC99E, 0x8501, 0xC99F, 0x8502, 0xC9A0, + 0x8503, 0xCA40, 0x8504, 0xCA41, 0x8505, 0xCA42, 0x8506, 0xCA43, 0x8507, 0xCA44, 0x8508, 0xCA45, 0x8509, 0xCA46, 0x850A, 0xCA47, + 0x850B, 0xCA48, 0x850C, 0xDDF8, 0x850D, 0xCA49, 0x850E, 0xCA4A, 0x850F, 0xCA4B, 0x8510, 0xCA4C, 0x8511, 0xC3EF, 0x8512, 0xCA4D, + 0x8513, 0xC2FB, 0x8514, 0xCA4E, 0x8515, 0xCA4F, 0x8516, 0xCA50, 0x8517, 0xD5E1, 0x8518, 0xCA51, 0x8519, 0xCA52, 0x851A, 0xCEB5, + 0x851B, 0xCA53, 0x851C, 0xCA54, 0x851D, 0xCA55, 0x851E, 0xCA56, 0x851F, 0xDDFD, 0x8520, 0xCA57, 0x8521, 0xB2CC, 0x8522, 0xCA58, + 0x8523, 0xCA59, 0x8524, 0xCA5A, 0x8525, 0xCA5B, 0x8526, 0xCA5C, 0x8527, 0xCA5D, 0x8528, 0xCA5E, 0x8529, 0xCA5F, 0x852A, 0xCA60, + 0x852B, 0xC4E8, 0x852C, 0xCADF, 0x852D, 0xCA61, 0x852E, 0xCA62, 0x852F, 0xCA63, 0x8530, 0xCA64, 0x8531, 0xCA65, 0x8532, 0xCA66, + 0x8533, 0xCA67, 0x8534, 0xCA68, 0x8535, 0xCA69, 0x8536, 0xCA6A, 0x8537, 0xC7BE, 0x8538, 0xDDFA, 0x8539, 0xDDFC, 0x853A, 0xDDFE, + 0x853B, 0xDEA2, 0x853C, 0xB0AA, 0x853D, 0xB1CE, 0x853E, 0xCA6B, 0x853F, 0xCA6C, 0x8540, 0xCA6D, 0x8541, 0xCA6E, 0x8542, 0xCA6F, + 0x8543, 0xDEAC, 0x8544, 0xCA70, 0x8545, 0xCA71, 0x8546, 0xCA72, 0x8547, 0xCA73, 0x8548, 0xDEA6, 0x8549, 0xBDB6, 0x854A, 0xC8EF, + 0x854B, 0xCA74, 0x854C, 0xCA75, 0x854D, 0xCA76, 0x854E, 0xCA77, 0x854F, 0xCA78, 0x8550, 0xCA79, 0x8551, 0xCA7A, 0x8552, 0xCA7B, + 0x8553, 0xCA7C, 0x8554, 0xCA7D, 0x8555, 0xCA7E, 0x8556, 0xDEA1, 0x8557, 0xCA80, 0x8558, 0xCA81, 0x8559, 0xDEA5, 0x855A, 0xCA82, + 0x855B, 0xCA83, 0x855C, 0xCA84, 0x855D, 0xCA85, 0x855E, 0xDEA9, 0x855F, 0xCA86, 0x8560, 0xCA87, 0x8561, 0xCA88, 0x8562, 0xCA89, + 0x8563, 0xCA8A, 0x8564, 0xDEA8, 0x8565, 0xCA8B, 0x8566, 0xCA8C, 0x8567, 0xCA8D, 0x8568, 0xDEA7, 0x8569, 0xCA8E, 0x856A, 0xCA8F, + 0x856B, 0xCA90, 0x856C, 0xCA91, 0x856D, 0xCA92, 0x856E, 0xCA93, 0x856F, 0xCA94, 0x8570, 0xCA95, 0x8571, 0xCA96, 0x8572, 0xDEAD, + 0x8573, 0xCA97, 0x8574, 0xD4CC, 0x8575, 0xCA98, 0x8576, 0xCA99, 0x8577, 0xCA9A, 0x8578, 0xCA9B, 0x8579, 0xDEB3, 0x857A, 0xDEAA, + 0x857B, 0xDEAE, 0x857C, 0xCA9C, 0x857D, 0xCA9D, 0x857E, 0xC0D9, 0x857F, 0xCA9E, 0x8580, 0xCA9F, 0x8581, 0xCAA0, 0x8582, 0xCB40, + 0x8583, 0xCB41, 0x8584, 0xB1A1, 0x8585, 0xDEB6, 0x8586, 0xCB42, 0x8587, 0xDEB1, 0x8588, 0xCB43, 0x8589, 0xCB44, 0x858A, 0xCB45, + 0x858B, 0xCB46, 0x858C, 0xCB47, 0x858D, 0xCB48, 0x858E, 0xCB49, 0x858F, 0xDEB2, 0x8590, 0xCB4A, 0x8591, 0xCB4B, 0x8592, 0xCB4C, + 0x8593, 0xCB4D, 0x8594, 0xCB4E, 0x8595, 0xCB4F, 0x8596, 0xCB50, 0x8597, 0xCB51, 0x8598, 0xCB52, 0x8599, 0xCB53, 0x859A, 0xCB54, + 0x859B, 0xD1A6, 0x859C, 0xDEB5, 0x859D, 0xCB55, 0x859E, 0xCB56, 0x859F, 0xCB57, 0x85A0, 0xCB58, 0x85A1, 0xCB59, 0x85A2, 0xCB5A, + 0x85A3, 0xCB5B, 0x85A4, 0xDEAF, 0x85A5, 0xCB5C, 0x85A6, 0xCB5D, 0x85A7, 0xCB5E, 0x85A8, 0xDEB0, 0x85A9, 0xCB5F, 0x85AA, 0xD0BD, + 0x85AB, 0xCB60, 0x85AC, 0xCB61, 0x85AD, 0xCB62, 0x85AE, 0xDEB4, 0x85AF, 0xCAED, 0x85B0, 0xDEB9, 0x85B1, 0xCB63, 0x85B2, 0xCB64, + 0x85B3, 0xCB65, 0x85B4, 0xCB66, 0x85B5, 0xCB67, 0x85B6, 0xCB68, 0x85B7, 0xDEB8, 0x85B8, 0xCB69, 0x85B9, 0xDEB7, 0x85BA, 0xCB6A, + 0x85BB, 0xCB6B, 0x85BC, 0xCB6C, 0x85BD, 0xCB6D, 0x85BE, 0xCB6E, 0x85BF, 0xCB6F, 0x85C0, 0xCB70, 0x85C1, 0xDEBB, 0x85C2, 0xCB71, + 0x85C3, 0xCB72, 0x85C4, 0xCB73, 0x85C5, 0xCB74, 0x85C6, 0xCB75, 0x85C7, 0xCB76, 0x85C8, 0xCB77, 0x85C9, 0xBDE5, 0x85CA, 0xCB78, + 0x85CB, 0xCB79, 0x85CC, 0xCB7A, 0x85CD, 0xCB7B, 0x85CE, 0xCB7C, 0x85CF, 0xB2D8, 0x85D0, 0xC3EA, 0x85D1, 0xCB7D, 0x85D2, 0xCB7E, + 0x85D3, 0xDEBA, 0x85D4, 0xCB80, 0x85D5, 0xC5BA, 0x85D6, 0xCB81, 0x85D7, 0xCB82, 0x85D8, 0xCB83, 0x85D9, 0xCB84, 0x85DA, 0xCB85, + 0x85DB, 0xCB86, 0x85DC, 0xDEBC, 0x85DD, 0xCB87, 0x85DE, 0xCB88, 0x85DF, 0xCB89, 0x85E0, 0xCB8A, 0x85E1, 0xCB8B, 0x85E2, 0xCB8C, + 0x85E3, 0xCB8D, 0x85E4, 0xCCD9, 0x85E5, 0xCB8E, 0x85E6, 0xCB8F, 0x85E7, 0xCB90, 0x85E8, 0xCB91, 0x85E9, 0xB7AA, 0x85EA, 0xCB92, + 0x85EB, 0xCB93, 0x85EC, 0xCB94, 0x85ED, 0xCB95, 0x85EE, 0xCB96, 0x85EF, 0xCB97, 0x85F0, 0xCB98, 0x85F1, 0xCB99, 0x85F2, 0xCB9A, + 0x85F3, 0xCB9B, 0x85F4, 0xCB9C, 0x85F5, 0xCB9D, 0x85F6, 0xCB9E, 0x85F7, 0xCB9F, 0x85F8, 0xCBA0, 0x85F9, 0xCC40, 0x85FA, 0xCC41, + 0x85FB, 0xD4E5, 0x85FC, 0xCC42, 0x85FD, 0xCC43, 0x85FE, 0xCC44, 0x85FF, 0xDEBD, 0x8600, 0xCC45, 0x8601, 0xCC46, 0x8602, 0xCC47, + 0x8603, 0xCC48, 0x8604, 0xCC49, 0x8605, 0xDEBF, 0x8606, 0xCC4A, 0x8607, 0xCC4B, 0x8608, 0xCC4C, 0x8609, 0xCC4D, 0x860A, 0xCC4E, + 0x860B, 0xCC4F, 0x860C, 0xCC50, 0x860D, 0xCC51, 0x860E, 0xCC52, 0x860F, 0xCC53, 0x8610, 0xCC54, 0x8611, 0xC4A2, 0x8612, 0xCC55, + 0x8613, 0xCC56, 0x8614, 0xCC57, 0x8615, 0xCC58, 0x8616, 0xDEC1, 0x8617, 0xCC59, 0x8618, 0xCC5A, 0x8619, 0xCC5B, 0x861A, 0xCC5C, + 0x861B, 0xCC5D, 0x861C, 0xCC5E, 0x861D, 0xCC5F, 0x861E, 0xCC60, 0x861F, 0xCC61, 0x8620, 0xCC62, 0x8621, 0xCC63, 0x8622, 0xCC64, + 0x8623, 0xCC65, 0x8624, 0xCC66, 0x8625, 0xCC67, 0x8626, 0xCC68, 0x8627, 0xDEBE, 0x8628, 0xCC69, 0x8629, 0xDEC0, 0x862A, 0xCC6A, + 0x862B, 0xCC6B, 0x862C, 0xCC6C, 0x862D, 0xCC6D, 0x862E, 0xCC6E, 0x862F, 0xCC6F, 0x8630, 0xCC70, 0x8631, 0xCC71, 0x8632, 0xCC72, + 0x8633, 0xCC73, 0x8634, 0xCC74, 0x8635, 0xCC75, 0x8636, 0xCC76, 0x8637, 0xCC77, 0x8638, 0xD5BA, 0x8639, 0xCC78, 0x863A, 0xCC79, + 0x863B, 0xCC7A, 0x863C, 0xDEC2, 0x863D, 0xCC7B, 0x863E, 0xCC7C, 0x863F, 0xCC7D, 0x8640, 0xCC7E, 0x8641, 0xCC80, 0x8642, 0xCC81, + 0x8643, 0xCC82, 0x8644, 0xCC83, 0x8645, 0xCC84, 0x8646, 0xCC85, 0x8647, 0xCC86, 0x8648, 0xCC87, 0x8649, 0xCC88, 0x864A, 0xCC89, + 0x864B, 0xCC8A, 0x864C, 0xCC8B, 0x864D, 0xF2AE, 0x864E, 0xBBA2, 0x864F, 0xC2B2, 0x8650, 0xC5B0, 0x8651, 0xC2C7, 0x8652, 0xCC8C, + 0x8653, 0xCC8D, 0x8654, 0xF2AF, 0x8655, 0xCC8E, 0x8656, 0xCC8F, 0x8657, 0xCC90, 0x8658, 0xCC91, 0x8659, 0xCC92, 0x865A, 0xD0E9, + 0x865B, 0xCC93, 0x865C, 0xCC94, 0x865D, 0xCC95, 0x865E, 0xD3DD, 0x865F, 0xCC96, 0x8660, 0xCC97, 0x8661, 0xCC98, 0x8662, 0xEBBD, + 0x8663, 0xCC99, 0x8664, 0xCC9A, 0x8665, 0xCC9B, 0x8666, 0xCC9C, 0x8667, 0xCC9D, 0x8668, 0xCC9E, 0x8669, 0xCC9F, 0x866A, 0xCCA0, + 0x866B, 0xB3E6, 0x866C, 0xF2B0, 0x866D, 0xCD40, 0x866E, 0xF2B1, 0x866F, 0xCD41, 0x8670, 0xCD42, 0x8671, 0xCAAD, 0x8672, 0xCD43, + 0x8673, 0xCD44, 0x8674, 0xCD45, 0x8675, 0xCD46, 0x8676, 0xCD47, 0x8677, 0xCD48, 0x8678, 0xCD49, 0x8679, 0xBAE7, 0x867A, 0xF2B3, + 0x867B, 0xF2B5, 0x867C, 0xF2B4, 0x867D, 0xCBE4, 0x867E, 0xCFBA, 0x867F, 0xF2B2, 0x8680, 0xCAB4, 0x8681, 0xD2CF, 0x8682, 0xC2EC, + 0x8683, 0xCD4A, 0x8684, 0xCD4B, 0x8685, 0xCD4C, 0x8686, 0xCD4D, 0x8687, 0xCD4E, 0x8688, 0xCD4F, 0x8689, 0xCD50, 0x868A, 0xCEC3, + 0x868B, 0xF2B8, 0x868C, 0xB0F6, 0x868D, 0xF2B7, 0x868E, 0xCD51, 0x868F, 0xCD52, 0x8690, 0xCD53, 0x8691, 0xCD54, 0x8692, 0xCD55, + 0x8693, 0xF2BE, 0x8694, 0xCD56, 0x8695, 0xB2CF, 0x8696, 0xCD57, 0x8697, 0xCD58, 0x8698, 0xCD59, 0x8699, 0xCD5A, 0x869A, 0xCD5B, + 0x869B, 0xCD5C, 0x869C, 0xD1C1, 0x869D, 0xF2BA, 0x869E, 0xCD5D, 0x869F, 0xCD5E, 0x86A0, 0xCD5F, 0x86A1, 0xCD60, 0x86A2, 0xCD61, + 0x86A3, 0xF2BC, 0x86A4, 0xD4E9, 0x86A5, 0xCD62, 0x86A6, 0xCD63, 0x86A7, 0xF2BB, 0x86A8, 0xF2B6, 0x86A9, 0xF2BF, 0x86AA, 0xF2BD, + 0x86AB, 0xCD64, 0x86AC, 0xF2B9, 0x86AD, 0xCD65, 0x86AE, 0xCD66, 0x86AF, 0xF2C7, 0x86B0, 0xF2C4, 0x86B1, 0xF2C6, 0x86B2, 0xCD67, + 0x86B3, 0xCD68, 0x86B4, 0xF2CA, 0x86B5, 0xF2C2, 0x86B6, 0xF2C0, 0x86B7, 0xCD69, 0x86B8, 0xCD6A, 0x86B9, 0xCD6B, 0x86BA, 0xF2C5, + 0x86BB, 0xCD6C, 0x86BC, 0xCD6D, 0x86BD, 0xCD6E, 0x86BE, 0xCD6F, 0x86BF, 0xCD70, 0x86C0, 0xD6FB, 0x86C1, 0xCD71, 0x86C2, 0xCD72, + 0x86C3, 0xCD73, 0x86C4, 0xF2C1, 0x86C5, 0xCD74, 0x86C6, 0xC7F9, 0x86C7, 0xC9DF, 0x86C8, 0xCD75, 0x86C9, 0xF2C8, 0x86CA, 0xB9C6, + 0x86CB, 0xB5B0, 0x86CC, 0xCD76, 0x86CD, 0xCD77, 0x86CE, 0xF2C3, 0x86CF, 0xF2C9, 0x86D0, 0xF2D0, 0x86D1, 0xF2D6, 0x86D2, 0xCD78, + 0x86D3, 0xCD79, 0x86D4, 0xBBD7, 0x86D5, 0xCD7A, 0x86D6, 0xCD7B, 0x86D7, 0xCD7C, 0x86D8, 0xF2D5, 0x86D9, 0xCDDC, 0x86DA, 0xCD7D, + 0x86DB, 0xD6EB, 0x86DC, 0xCD7E, 0x86DD, 0xCD80, 0x86DE, 0xF2D2, 0x86DF, 0xF2D4, 0x86E0, 0xCD81, 0x86E1, 0xCD82, 0x86E2, 0xCD83, + 0x86E3, 0xCD84, 0x86E4, 0xB8F2, 0x86E5, 0xCD85, 0x86E6, 0xCD86, 0x86E7, 0xCD87, 0x86E8, 0xCD88, 0x86E9, 0xF2CB, 0x86EA, 0xCD89, + 0x86EB, 0xCD8A, 0x86EC, 0xCD8B, 0x86ED, 0xF2CE, 0x86EE, 0xC2F9, 0x86EF, 0xCD8C, 0x86F0, 0xD5DD, 0x86F1, 0xF2CC, 0x86F2, 0xF2CD, + 0x86F3, 0xF2CF, 0x86F4, 0xF2D3, 0x86F5, 0xCD8D, 0x86F6, 0xCD8E, 0x86F7, 0xCD8F, 0x86F8, 0xF2D9, 0x86F9, 0xD3BC, 0x86FA, 0xCD90, + 0x86FB, 0xCD91, 0x86FC, 0xCD92, 0x86FD, 0xCD93, 0x86FE, 0xB6EA, 0x86FF, 0xCD94, 0x8700, 0xCAF1, 0x8701, 0xCD95, 0x8702, 0xB7E4, + 0x8703, 0xF2D7, 0x8704, 0xCD96, 0x8705, 0xCD97, 0x8706, 0xCD98, 0x8707, 0xF2D8, 0x8708, 0xF2DA, 0x8709, 0xF2DD, 0x870A, 0xF2DB, + 0x870B, 0xCD99, 0x870C, 0xCD9A, 0x870D, 0xF2DC, 0x870E, 0xCD9B, 0x870F, 0xCD9C, 0x8710, 0xCD9D, 0x8711, 0xCD9E, 0x8712, 0xD1D1, + 0x8713, 0xF2D1, 0x8714, 0xCD9F, 0x8715, 0xCDC9, 0x8716, 0xCDA0, 0x8717, 0xCECF, 0x8718, 0xD6A9, 0x8719, 0xCE40, 0x871A, 0xF2E3, + 0x871B, 0xCE41, 0x871C, 0xC3DB, 0x871D, 0xCE42, 0x871E, 0xF2E0, 0x871F, 0xCE43, 0x8720, 0xCE44, 0x8721, 0xC0AF, 0x8722, 0xF2EC, + 0x8723, 0xF2DE, 0x8724, 0xCE45, 0x8725, 0xF2E1, 0x8726, 0xCE46, 0x8727, 0xCE47, 0x8728, 0xCE48, 0x8729, 0xF2E8, 0x872A, 0xCE49, + 0x872B, 0xCE4A, 0x872C, 0xCE4B, 0x872D, 0xCE4C, 0x872E, 0xF2E2, 0x872F, 0xCE4D, 0x8730, 0xCE4E, 0x8731, 0xF2E7, 0x8732, 0xCE4F, + 0x8733, 0xCE50, 0x8734, 0xF2E6, 0x8735, 0xCE51, 0x8736, 0xCE52, 0x8737, 0xF2E9, 0x8738, 0xCE53, 0x8739, 0xCE54, 0x873A, 0xCE55, + 0x873B, 0xF2DF, 0x873C, 0xCE56, 0x873D, 0xCE57, 0x873E, 0xF2E4, 0x873F, 0xF2EA, 0x8740, 0xCE58, 0x8741, 0xCE59, 0x8742, 0xCE5A, + 0x8743, 0xCE5B, 0x8744, 0xCE5C, 0x8745, 0xCE5D, 0x8746, 0xCE5E, 0x8747, 0xD3AC, 0x8748, 0xF2E5, 0x8749, 0xB2F5, 0x874A, 0xCE5F, + 0x874B, 0xCE60, 0x874C, 0xF2F2, 0x874D, 0xCE61, 0x874E, 0xD0AB, 0x874F, 0xCE62, 0x8750, 0xCE63, 0x8751, 0xCE64, 0x8752, 0xCE65, + 0x8753, 0xF2F5, 0x8754, 0xCE66, 0x8755, 0xCE67, 0x8756, 0xCE68, 0x8757, 0xBBC8, 0x8758, 0xCE69, 0x8759, 0xF2F9, 0x875A, 0xCE6A, + 0x875B, 0xCE6B, 0x875C, 0xCE6C, 0x875D, 0xCE6D, 0x875E, 0xCE6E, 0x875F, 0xCE6F, 0x8760, 0xF2F0, 0x8761, 0xCE70, 0x8762, 0xCE71, + 0x8763, 0xF2F6, 0x8764, 0xF2F8, 0x8765, 0xF2FA, 0x8766, 0xCE72, 0x8767, 0xCE73, 0x8768, 0xCE74, 0x8769, 0xCE75, 0x876A, 0xCE76, + 0x876B, 0xCE77, 0x876C, 0xCE78, 0x876D, 0xCE79, 0x876E, 0xF2F3, 0x876F, 0xCE7A, 0x8770, 0xF2F1, 0x8771, 0xCE7B, 0x8772, 0xCE7C, + 0x8773, 0xCE7D, 0x8774, 0xBAFB, 0x8775, 0xCE7E, 0x8776, 0xB5FB, 0x8777, 0xCE80, 0x8778, 0xCE81, 0x8779, 0xCE82, 0x877A, 0xCE83, + 0x877B, 0xF2EF, 0x877C, 0xF2F7, 0x877D, 0xF2ED, 0x877E, 0xF2EE, 0x877F, 0xCE84, 0x8780, 0xCE85, 0x8781, 0xCE86, 0x8782, 0xF2EB, + 0x8783, 0xF3A6, 0x8784, 0xCE87, 0x8785, 0xF3A3, 0x8786, 0xCE88, 0x8787, 0xCE89, 0x8788, 0xF3A2, 0x8789, 0xCE8A, 0x878A, 0xCE8B, + 0x878B, 0xF2F4, 0x878C, 0xCE8C, 0x878D, 0xC8DA, 0x878E, 0xCE8D, 0x878F, 0xCE8E, 0x8790, 0xCE8F, 0x8791, 0xCE90, 0x8792, 0xCE91, + 0x8793, 0xF2FB, 0x8794, 0xCE92, 0x8795, 0xCE93, 0x8796, 0xCE94, 0x8797, 0xF3A5, 0x8798, 0xCE95, 0x8799, 0xCE96, 0x879A, 0xCE97, + 0x879B, 0xCE98, 0x879C, 0xCE99, 0x879D, 0xCE9A, 0x879E, 0xCE9B, 0x879F, 0xC3F8, 0x87A0, 0xCE9C, 0x87A1, 0xCE9D, 0x87A2, 0xCE9E, + 0x87A3, 0xCE9F, 0x87A4, 0xCEA0, 0x87A5, 0xCF40, 0x87A6, 0xCF41, 0x87A7, 0xCF42, 0x87A8, 0xF2FD, 0x87A9, 0xCF43, 0x87AA, 0xCF44, + 0x87AB, 0xF3A7, 0x87AC, 0xF3A9, 0x87AD, 0xF3A4, 0x87AE, 0xCF45, 0x87AF, 0xF2FC, 0x87B0, 0xCF46, 0x87B1, 0xCF47, 0x87B2, 0xCF48, + 0x87B3, 0xF3AB, 0x87B4, 0xCF49, 0x87B5, 0xF3AA, 0x87B6, 0xCF4A, 0x87B7, 0xCF4B, 0x87B8, 0xCF4C, 0x87B9, 0xCF4D, 0x87BA, 0xC2DD, + 0x87BB, 0xCF4E, 0x87BC, 0xCF4F, 0x87BD, 0xF3AE, 0x87BE, 0xCF50, 0x87BF, 0xCF51, 0x87C0, 0xF3B0, 0x87C1, 0xCF52, 0x87C2, 0xCF53, + 0x87C3, 0xCF54, 0x87C4, 0xCF55, 0x87C5, 0xCF56, 0x87C6, 0xF3A1, 0x87C7, 0xCF57, 0x87C8, 0xCF58, 0x87C9, 0xCF59, 0x87CA, 0xF3B1, + 0x87CB, 0xF3AC, 0x87CC, 0xCF5A, 0x87CD, 0xCF5B, 0x87CE, 0xCF5C, 0x87CF, 0xCF5D, 0x87D0, 0xCF5E, 0x87D1, 0xF3AF, 0x87D2, 0xF2FE, + 0x87D3, 0xF3AD, 0x87D4, 0xCF5F, 0x87D5, 0xCF60, 0x87D6, 0xCF61, 0x87D7, 0xCF62, 0x87D8, 0xCF63, 0x87D9, 0xCF64, 0x87DA, 0xCF65, + 0x87DB, 0xF3B2, 0x87DC, 0xCF66, 0x87DD, 0xCF67, 0x87DE, 0xCF68, 0x87DF, 0xCF69, 0x87E0, 0xF3B4, 0x87E1, 0xCF6A, 0x87E2, 0xCF6B, + 0x87E3, 0xCF6C, 0x87E4, 0xCF6D, 0x87E5, 0xF3A8, 0x87E6, 0xCF6E, 0x87E7, 0xCF6F, 0x87E8, 0xCF70, 0x87E9, 0xCF71, 0x87EA, 0xF3B3, + 0x87EB, 0xCF72, 0x87EC, 0xCF73, 0x87ED, 0xCF74, 0x87EE, 0xF3B5, 0x87EF, 0xCF75, 0x87F0, 0xCF76, 0x87F1, 0xCF77, 0x87F2, 0xCF78, + 0x87F3, 0xCF79, 0x87F4, 0xCF7A, 0x87F5, 0xCF7B, 0x87F6, 0xCF7C, 0x87F7, 0xCF7D, 0x87F8, 0xCF7E, 0x87F9, 0xD0B7, 0x87FA, 0xCF80, + 0x87FB, 0xCF81, 0x87FC, 0xCF82, 0x87FD, 0xCF83, 0x87FE, 0xF3B8, 0x87FF, 0xCF84, 0x8800, 0xCF85, 0x8801, 0xCF86, 0x8802, 0xCF87, + 0x8803, 0xD9F9, 0x8804, 0xCF88, 0x8805, 0xCF89, 0x8806, 0xCF8A, 0x8807, 0xCF8B, 0x8808, 0xCF8C, 0x8809, 0xCF8D, 0x880A, 0xF3B9, + 0x880B, 0xCF8E, 0x880C, 0xCF8F, 0x880D, 0xCF90, 0x880E, 0xCF91, 0x880F, 0xCF92, 0x8810, 0xCF93, 0x8811, 0xCF94, 0x8812, 0xCF95, + 0x8813, 0xF3B7, 0x8814, 0xCF96, 0x8815, 0xC8E4, 0x8816, 0xF3B6, 0x8817, 0xCF97, 0x8818, 0xCF98, 0x8819, 0xCF99, 0x881A, 0xCF9A, + 0x881B, 0xF3BA, 0x881C, 0xCF9B, 0x881D, 0xCF9C, 0x881E, 0xCF9D, 0x881F, 0xCF9E, 0x8820, 0xCF9F, 0x8821, 0xF3BB, 0x8822, 0xB4C0, + 0x8823, 0xCFA0, 0x8824, 0xD040, 0x8825, 0xD041, 0x8826, 0xD042, 0x8827, 0xD043, 0x8828, 0xD044, 0x8829, 0xD045, 0x882A, 0xD046, + 0x882B, 0xD047, 0x882C, 0xD048, 0x882D, 0xD049, 0x882E, 0xD04A, 0x882F, 0xD04B, 0x8830, 0xD04C, 0x8831, 0xD04D, 0x8832, 0xEEC3, + 0x8833, 0xD04E, 0x8834, 0xD04F, 0x8835, 0xD050, 0x8836, 0xD051, 0x8837, 0xD052, 0x8838, 0xD053, 0x8839, 0xF3BC, 0x883A, 0xD054, + 0x883B, 0xD055, 0x883C, 0xF3BD, 0x883D, 0xD056, 0x883E, 0xD057, 0x883F, 0xD058, 0x8840, 0xD1AA, 0x8841, 0xD059, 0x8842, 0xD05A, + 0x8843, 0xD05B, 0x8844, 0xF4AC, 0x8845, 0xD0C6, 0x8846, 0xD05C, 0x8847, 0xD05D, 0x8848, 0xD05E, 0x8849, 0xD05F, 0x884A, 0xD060, + 0x884B, 0xD061, 0x884C, 0xD0D0, 0x884D, 0xD1DC, 0x884E, 0xD062, 0x884F, 0xD063, 0x8850, 0xD064, 0x8851, 0xD065, 0x8852, 0xD066, + 0x8853, 0xD067, 0x8854, 0xCFCE, 0x8855, 0xD068, 0x8856, 0xD069, 0x8857, 0xBDD6, 0x8858, 0xD06A, 0x8859, 0xD1C3, 0x885A, 0xD06B, + 0x885B, 0xD06C, 0x885C, 0xD06D, 0x885D, 0xD06E, 0x885E, 0xD06F, 0x885F, 0xD070, 0x8860, 0xD071, 0x8861, 0xBAE2, 0x8862, 0xE1E9, + 0x8863, 0xD2C2, 0x8864, 0xF1C2, 0x8865, 0xB2B9, 0x8866, 0xD072, 0x8867, 0xD073, 0x8868, 0xB1ED, 0x8869, 0xF1C3, 0x886A, 0xD074, + 0x886B, 0xC9C0, 0x886C, 0xB3C4, 0x886D, 0xD075, 0x886E, 0xD9F2, 0x886F, 0xD076, 0x8870, 0xCBA5, 0x8871, 0xD077, 0x8872, 0xF1C4, + 0x8873, 0xD078, 0x8874, 0xD079, 0x8875, 0xD07A, 0x8876, 0xD07B, 0x8877, 0xD6D4, 0x8878, 0xD07C, 0x8879, 0xD07D, 0x887A, 0xD07E, + 0x887B, 0xD080, 0x887C, 0xD081, 0x887D, 0xF1C5, 0x887E, 0xF4C0, 0x887F, 0xF1C6, 0x8880, 0xD082, 0x8881, 0xD4AC, 0x8882, 0xF1C7, + 0x8883, 0xD083, 0x8884, 0xB0C0, 0x8885, 0xF4C1, 0x8886, 0xD084, 0x8887, 0xD085, 0x8888, 0xF4C2, 0x8889, 0xD086, 0x888A, 0xD087, + 0x888B, 0xB4FC, 0x888C, 0xD088, 0x888D, 0xC5DB, 0x888E, 0xD089, 0x888F, 0xD08A, 0x8890, 0xD08B, 0x8891, 0xD08C, 0x8892, 0xCCBB, + 0x8893, 0xD08D, 0x8894, 0xD08E, 0x8895, 0xD08F, 0x8896, 0xD0E4, 0x8897, 0xD090, 0x8898, 0xD091, 0x8899, 0xD092, 0x889A, 0xD093, + 0x889B, 0xD094, 0x889C, 0xCDE0, 0x889D, 0xD095, 0x889E, 0xD096, 0x889F, 0xD097, 0x88A0, 0xD098, 0x88A1, 0xD099, 0x88A2, 0xF1C8, + 0x88A3, 0xD09A, 0x88A4, 0xD9F3, 0x88A5, 0xD09B, 0x88A6, 0xD09C, 0x88A7, 0xD09D, 0x88A8, 0xD09E, 0x88A9, 0xD09F, 0x88AA, 0xD0A0, + 0x88AB, 0xB1BB, 0x88AC, 0xD140, 0x88AD, 0xCFAE, 0x88AE, 0xD141, 0x88AF, 0xD142, 0x88B0, 0xD143, 0x88B1, 0xB8A4, 0x88B2, 0xD144, + 0x88B3, 0xD145, 0x88B4, 0xD146, 0x88B5, 0xD147, 0x88B6, 0xD148, 0x88B7, 0xF1CA, 0x88B8, 0xD149, 0x88B9, 0xD14A, 0x88BA, 0xD14B, + 0x88BB, 0xD14C, 0x88BC, 0xF1CB, 0x88BD, 0xD14D, 0x88BE, 0xD14E, 0x88BF, 0xD14F, 0x88C0, 0xD150, 0x88C1, 0xB2C3, 0x88C2, 0xC1D1, + 0x88C3, 0xD151, 0x88C4, 0xD152, 0x88C5, 0xD7B0, 0x88C6, 0xF1C9, 0x88C7, 0xD153, 0x88C8, 0xD154, 0x88C9, 0xF1CC, 0x88CA, 0xD155, + 0x88CB, 0xD156, 0x88CC, 0xD157, 0x88CD, 0xD158, 0x88CE, 0xF1CE, 0x88CF, 0xD159, 0x88D0, 0xD15A, 0x88D1, 0xD15B, 0x88D2, 0xD9F6, + 0x88D3, 0xD15C, 0x88D4, 0xD2E1, 0x88D5, 0xD4A3, 0x88D6, 0xD15D, 0x88D7, 0xD15E, 0x88D8, 0xF4C3, 0x88D9, 0xC8B9, 0x88DA, 0xD15F, + 0x88DB, 0xD160, 0x88DC, 0xD161, 0x88DD, 0xD162, 0x88DE, 0xD163, 0x88DF, 0xF4C4, 0x88E0, 0xD164, 0x88E1, 0xD165, 0x88E2, 0xF1CD, + 0x88E3, 0xF1CF, 0x88E4, 0xBFE3, 0x88E5, 0xF1D0, 0x88E6, 0xD166, 0x88E7, 0xD167, 0x88E8, 0xF1D4, 0x88E9, 0xD168, 0x88EA, 0xD169, + 0x88EB, 0xD16A, 0x88EC, 0xD16B, 0x88ED, 0xD16C, 0x88EE, 0xD16D, 0x88EF, 0xD16E, 0x88F0, 0xF1D6, 0x88F1, 0xF1D1, 0x88F2, 0xD16F, + 0x88F3, 0xC9D1, 0x88F4, 0xC5E1, 0x88F5, 0xD170, 0x88F6, 0xD171, 0x88F7, 0xD172, 0x88F8, 0xC2E3, 0x88F9, 0xB9FC, 0x88FA, 0xD173, + 0x88FB, 0xD174, 0x88FC, 0xF1D3, 0x88FD, 0xD175, 0x88FE, 0xF1D5, 0x88FF, 0xD176, 0x8900, 0xD177, 0x8901, 0xD178, 0x8902, 0xB9D3, + 0x8903, 0xD179, 0x8904, 0xD17A, 0x8905, 0xD17B, 0x8906, 0xD17C, 0x8907, 0xD17D, 0x8908, 0xD17E, 0x8909, 0xD180, 0x890A, 0xF1DB, + 0x890B, 0xD181, 0x890C, 0xD182, 0x890D, 0xD183, 0x890E, 0xD184, 0x890F, 0xD185, 0x8910, 0xBAD6, 0x8911, 0xD186, 0x8912, 0xB0FD, + 0x8913, 0xF1D9, 0x8914, 0xD187, 0x8915, 0xD188, 0x8916, 0xD189, 0x8917, 0xD18A, 0x8918, 0xD18B, 0x8919, 0xF1D8, 0x891A, 0xF1D2, + 0x891B, 0xF1DA, 0x891C, 0xD18C, 0x891D, 0xD18D, 0x891E, 0xD18E, 0x891F, 0xD18F, 0x8920, 0xD190, 0x8921, 0xF1D7, 0x8922, 0xD191, + 0x8923, 0xD192, 0x8924, 0xD193, 0x8925, 0xC8EC, 0x8926, 0xD194, 0x8927, 0xD195, 0x8928, 0xD196, 0x8929, 0xD197, 0x892A, 0xCDCA, + 0x892B, 0xF1DD, 0x892C, 0xD198, 0x892D, 0xD199, 0x892E, 0xD19A, 0x892F, 0xD19B, 0x8930, 0xE5BD, 0x8931, 0xD19C, 0x8932, 0xD19D, + 0x8933, 0xD19E, 0x8934, 0xF1DC, 0x8935, 0xD19F, 0x8936, 0xF1DE, 0x8937, 0xD1A0, 0x8938, 0xD240, 0x8939, 0xD241, 0x893A, 0xD242, + 0x893B, 0xD243, 0x893C, 0xD244, 0x893D, 0xD245, 0x893E, 0xD246, 0x893F, 0xD247, 0x8940, 0xD248, 0x8941, 0xF1DF, 0x8942, 0xD249, + 0x8943, 0xD24A, 0x8944, 0xCFE5, 0x8945, 0xD24B, 0x8946, 0xD24C, 0x8947, 0xD24D, 0x8948, 0xD24E, 0x8949, 0xD24F, 0x894A, 0xD250, + 0x894B, 0xD251, 0x894C, 0xD252, 0x894D, 0xD253, 0x894E, 0xD254, 0x894F, 0xD255, 0x8950, 0xD256, 0x8951, 0xD257, 0x8952, 0xD258, + 0x8953, 0xD259, 0x8954, 0xD25A, 0x8955, 0xD25B, 0x8956, 0xD25C, 0x8957, 0xD25D, 0x8958, 0xD25E, 0x8959, 0xD25F, 0x895A, 0xD260, + 0x895B, 0xD261, 0x895C, 0xD262, 0x895D, 0xD263, 0x895E, 0xF4C5, 0x895F, 0xBDF3, 0x8960, 0xD264, 0x8961, 0xD265, 0x8962, 0xD266, + 0x8963, 0xD267, 0x8964, 0xD268, 0x8965, 0xD269, 0x8966, 0xF1E0, 0x8967, 0xD26A, 0x8968, 0xD26B, 0x8969, 0xD26C, 0x896A, 0xD26D, + 0x896B, 0xD26E, 0x896C, 0xD26F, 0x896D, 0xD270, 0x896E, 0xD271, 0x896F, 0xD272, 0x8970, 0xD273, 0x8971, 0xD274, 0x8972, 0xD275, + 0x8973, 0xD276, 0x8974, 0xD277, 0x8975, 0xD278, 0x8976, 0xD279, 0x8977, 0xD27A, 0x8978, 0xD27B, 0x8979, 0xD27C, 0x897A, 0xD27D, + 0x897B, 0xF1E1, 0x897C, 0xD27E, 0x897D, 0xD280, 0x897E, 0xD281, 0x897F, 0xCEF7, 0x8980, 0xD282, 0x8981, 0xD2AA, 0x8982, 0xD283, + 0x8983, 0xF1FB, 0x8984, 0xD284, 0x8985, 0xD285, 0x8986, 0xB8B2, 0x8987, 0xD286, 0x8988, 0xD287, 0x8989, 0xD288, 0x898A, 0xD289, + 0x898B, 0xD28A, 0x898C, 0xD28B, 0x898D, 0xD28C, 0x898E, 0xD28D, 0x898F, 0xD28E, 0x8990, 0xD28F, 0x8991, 0xD290, 0x8992, 0xD291, + 0x8993, 0xD292, 0x8994, 0xD293, 0x8995, 0xD294, 0x8996, 0xD295, 0x8997, 0xD296, 0x8998, 0xD297, 0x8999, 0xD298, 0x899A, 0xD299, + 0x899B, 0xD29A, 0x899C, 0xD29B, 0x899D, 0xD29C, 0x899E, 0xD29D, 0x899F, 0xD29E, 0x89A0, 0xD29F, 0x89A1, 0xD2A0, 0x89A2, 0xD340, + 0x89A3, 0xD341, 0x89A4, 0xD342, 0x89A5, 0xD343, 0x89A6, 0xD344, 0x89A7, 0xD345, 0x89A8, 0xD346, 0x89A9, 0xD347, 0x89AA, 0xD348, + 0x89AB, 0xD349, 0x89AC, 0xD34A, 0x89AD, 0xD34B, 0x89AE, 0xD34C, 0x89AF, 0xD34D, 0x89B0, 0xD34E, 0x89B1, 0xD34F, 0x89B2, 0xD350, + 0x89B3, 0xD351, 0x89B4, 0xD352, 0x89B5, 0xD353, 0x89B6, 0xD354, 0x89B7, 0xD355, 0x89B8, 0xD356, 0x89B9, 0xD357, 0x89BA, 0xD358, + 0x89BB, 0xD359, 0x89BC, 0xD35A, 0x89BD, 0xD35B, 0x89BE, 0xD35C, 0x89BF, 0xD35D, 0x89C0, 0xD35E, 0x89C1, 0xBCFB, 0x89C2, 0xB9DB, + 0x89C3, 0xD35F, 0x89C4, 0xB9E6, 0x89C5, 0xC3D9, 0x89C6, 0xCAD3, 0x89C7, 0xEAE8, 0x89C8, 0xC0C0, 0x89C9, 0xBEF5, 0x89CA, 0xEAE9, + 0x89CB, 0xEAEA, 0x89CC, 0xEAEB, 0x89CD, 0xD360, 0x89CE, 0xEAEC, 0x89CF, 0xEAED, 0x89D0, 0xEAEE, 0x89D1, 0xEAEF, 0x89D2, 0xBDC7, + 0x89D3, 0xD361, 0x89D4, 0xD362, 0x89D5, 0xD363, 0x89D6, 0xF5FB, 0x89D7, 0xD364, 0x89D8, 0xD365, 0x89D9, 0xD366, 0x89DA, 0xF5FD, + 0x89DB, 0xD367, 0x89DC, 0xF5FE, 0x89DD, 0xD368, 0x89DE, 0xF5FC, 0x89DF, 0xD369, 0x89E0, 0xD36A, 0x89E1, 0xD36B, 0x89E2, 0xD36C, + 0x89E3, 0xBDE2, 0x89E4, 0xD36D, 0x89E5, 0xF6A1, 0x89E6, 0xB4A5, 0x89E7, 0xD36E, 0x89E8, 0xD36F, 0x89E9, 0xD370, 0x89EA, 0xD371, + 0x89EB, 0xF6A2, 0x89EC, 0xD372, 0x89ED, 0xD373, 0x89EE, 0xD374, 0x89EF, 0xF6A3, 0x89F0, 0xD375, 0x89F1, 0xD376, 0x89F2, 0xD377, + 0x89F3, 0xECB2, 0x89F4, 0xD378, 0x89F5, 0xD379, 0x89F6, 0xD37A, 0x89F7, 0xD37B, 0x89F8, 0xD37C, 0x89F9, 0xD37D, 0x89FA, 0xD37E, + 0x89FB, 0xD380, 0x89FC, 0xD381, 0x89FD, 0xD382, 0x89FE, 0xD383, 0x89FF, 0xD384, 0x8A00, 0xD1D4, 0x8A01, 0xD385, 0x8A02, 0xD386, + 0x8A03, 0xD387, 0x8A04, 0xD388, 0x8A05, 0xD389, 0x8A06, 0xD38A, 0x8A07, 0xD9EA, 0x8A08, 0xD38B, 0x8A09, 0xD38C, 0x8A0A, 0xD38D, + 0x8A0B, 0xD38E, 0x8A0C, 0xD38F, 0x8A0D, 0xD390, 0x8A0E, 0xD391, 0x8A0F, 0xD392, 0x8A10, 0xD393, 0x8A11, 0xD394, 0x8A12, 0xD395, + 0x8A13, 0xD396, 0x8A14, 0xD397, 0x8A15, 0xD398, 0x8A16, 0xD399, 0x8A17, 0xD39A, 0x8A18, 0xD39B, 0x8A19, 0xD39C, 0x8A1A, 0xD39D, + 0x8A1B, 0xD39E, 0x8A1C, 0xD39F, 0x8A1D, 0xD3A0, 0x8A1E, 0xD440, 0x8A1F, 0xD441, 0x8A20, 0xD442, 0x8A21, 0xD443, 0x8A22, 0xD444, + 0x8A23, 0xD445, 0x8A24, 0xD446, 0x8A25, 0xD447, 0x8A26, 0xD448, 0x8A27, 0xD449, 0x8A28, 0xD44A, 0x8A29, 0xD44B, 0x8A2A, 0xD44C, + 0x8A2B, 0xD44D, 0x8A2C, 0xD44E, 0x8A2D, 0xD44F, 0x8A2E, 0xD450, 0x8A2F, 0xD451, 0x8A30, 0xD452, 0x8A31, 0xD453, 0x8A32, 0xD454, + 0x8A33, 0xD455, 0x8A34, 0xD456, 0x8A35, 0xD457, 0x8A36, 0xD458, 0x8A37, 0xD459, 0x8A38, 0xD45A, 0x8A39, 0xD45B, 0x8A3A, 0xD45C, + 0x8A3B, 0xD45D, 0x8A3C, 0xD45E, 0x8A3D, 0xD45F, 0x8A3E, 0xF6A4, 0x8A3F, 0xD460, 0x8A40, 0xD461, 0x8A41, 0xD462, 0x8A42, 0xD463, + 0x8A43, 0xD464, 0x8A44, 0xD465, 0x8A45, 0xD466, 0x8A46, 0xD467, 0x8A47, 0xD468, 0x8A48, 0xEEBA, 0x8A49, 0xD469, 0x8A4A, 0xD46A, + 0x8A4B, 0xD46B, 0x8A4C, 0xD46C, 0x8A4D, 0xD46D, 0x8A4E, 0xD46E, 0x8A4F, 0xD46F, 0x8A50, 0xD470, 0x8A51, 0xD471, 0x8A52, 0xD472, + 0x8A53, 0xD473, 0x8A54, 0xD474, 0x8A55, 0xD475, 0x8A56, 0xD476, 0x8A57, 0xD477, 0x8A58, 0xD478, 0x8A59, 0xD479, 0x8A5A, 0xD47A, + 0x8A5B, 0xD47B, 0x8A5C, 0xD47C, 0x8A5D, 0xD47D, 0x8A5E, 0xD47E, 0x8A5F, 0xD480, 0x8A60, 0xD481, 0x8A61, 0xD482, 0x8A62, 0xD483, + 0x8A63, 0xD484, 0x8A64, 0xD485, 0x8A65, 0xD486, 0x8A66, 0xD487, 0x8A67, 0xD488, 0x8A68, 0xD489, 0x8A69, 0xD48A, 0x8A6A, 0xD48B, + 0x8A6B, 0xD48C, 0x8A6C, 0xD48D, 0x8A6D, 0xD48E, 0x8A6E, 0xD48F, 0x8A6F, 0xD490, 0x8A70, 0xD491, 0x8A71, 0xD492, 0x8A72, 0xD493, + 0x8A73, 0xD494, 0x8A74, 0xD495, 0x8A75, 0xD496, 0x8A76, 0xD497, 0x8A77, 0xD498, 0x8A78, 0xD499, 0x8A79, 0xD5B2, 0x8A7A, 0xD49A, + 0x8A7B, 0xD49B, 0x8A7C, 0xD49C, 0x8A7D, 0xD49D, 0x8A7E, 0xD49E, 0x8A7F, 0xD49F, 0x8A80, 0xD4A0, 0x8A81, 0xD540, 0x8A82, 0xD541, + 0x8A83, 0xD542, 0x8A84, 0xD543, 0x8A85, 0xD544, 0x8A86, 0xD545, 0x8A87, 0xD546, 0x8A88, 0xD547, 0x8A89, 0xD3FE, 0x8A8A, 0xCCDC, + 0x8A8B, 0xD548, 0x8A8C, 0xD549, 0x8A8D, 0xD54A, 0x8A8E, 0xD54B, 0x8A8F, 0xD54C, 0x8A90, 0xD54D, 0x8A91, 0xD54E, 0x8A92, 0xD54F, + 0x8A93, 0xCAC4, 0x8A94, 0xD550, 0x8A95, 0xD551, 0x8A96, 0xD552, 0x8A97, 0xD553, 0x8A98, 0xD554, 0x8A99, 0xD555, 0x8A9A, 0xD556, + 0x8A9B, 0xD557, 0x8A9C, 0xD558, 0x8A9D, 0xD559, 0x8A9E, 0xD55A, 0x8A9F, 0xD55B, 0x8AA0, 0xD55C, 0x8AA1, 0xD55D, 0x8AA2, 0xD55E, + 0x8AA3, 0xD55F, 0x8AA4, 0xD560, 0x8AA5, 0xD561, 0x8AA6, 0xD562, 0x8AA7, 0xD563, 0x8AA8, 0xD564, 0x8AA9, 0xD565, 0x8AAA, 0xD566, + 0x8AAB, 0xD567, 0x8AAC, 0xD568, 0x8AAD, 0xD569, 0x8AAE, 0xD56A, 0x8AAF, 0xD56B, 0x8AB0, 0xD56C, 0x8AB1, 0xD56D, 0x8AB2, 0xD56E, + 0x8AB3, 0xD56F, 0x8AB4, 0xD570, 0x8AB5, 0xD571, 0x8AB6, 0xD572, 0x8AB7, 0xD573, 0x8AB8, 0xD574, 0x8AB9, 0xD575, 0x8ABA, 0xD576, + 0x8ABB, 0xD577, 0x8ABC, 0xD578, 0x8ABD, 0xD579, 0x8ABE, 0xD57A, 0x8ABF, 0xD57B, 0x8AC0, 0xD57C, 0x8AC1, 0xD57D, 0x8AC2, 0xD57E, + 0x8AC3, 0xD580, 0x8AC4, 0xD581, 0x8AC5, 0xD582, 0x8AC6, 0xD583, 0x8AC7, 0xD584, 0x8AC8, 0xD585, 0x8AC9, 0xD586, 0x8ACA, 0xD587, + 0x8ACB, 0xD588, 0x8ACC, 0xD589, 0x8ACD, 0xD58A, 0x8ACE, 0xD58B, 0x8ACF, 0xD58C, 0x8AD0, 0xD58D, 0x8AD1, 0xD58E, 0x8AD2, 0xD58F, + 0x8AD3, 0xD590, 0x8AD4, 0xD591, 0x8AD5, 0xD592, 0x8AD6, 0xD593, 0x8AD7, 0xD594, 0x8AD8, 0xD595, 0x8AD9, 0xD596, 0x8ADA, 0xD597, + 0x8ADB, 0xD598, 0x8ADC, 0xD599, 0x8ADD, 0xD59A, 0x8ADE, 0xD59B, 0x8ADF, 0xD59C, 0x8AE0, 0xD59D, 0x8AE1, 0xD59E, 0x8AE2, 0xD59F, + 0x8AE3, 0xD5A0, 0x8AE4, 0xD640, 0x8AE5, 0xD641, 0x8AE6, 0xD642, 0x8AE7, 0xD643, 0x8AE8, 0xD644, 0x8AE9, 0xD645, 0x8AEA, 0xD646, + 0x8AEB, 0xD647, 0x8AEC, 0xD648, 0x8AED, 0xD649, 0x8AEE, 0xD64A, 0x8AEF, 0xD64B, 0x8AF0, 0xD64C, 0x8AF1, 0xD64D, 0x8AF2, 0xD64E, + 0x8AF3, 0xD64F, 0x8AF4, 0xD650, 0x8AF5, 0xD651, 0x8AF6, 0xD652, 0x8AF7, 0xD653, 0x8AF8, 0xD654, 0x8AF9, 0xD655, 0x8AFA, 0xD656, + 0x8AFB, 0xD657, 0x8AFC, 0xD658, 0x8AFD, 0xD659, 0x8AFE, 0xD65A, 0x8AFF, 0xD65B, 0x8B00, 0xD65C, 0x8B01, 0xD65D, 0x8B02, 0xD65E, + 0x8B03, 0xD65F, 0x8B04, 0xD660, 0x8B05, 0xD661, 0x8B06, 0xD662, 0x8B07, 0xE5C0, 0x8B08, 0xD663, 0x8B09, 0xD664, 0x8B0A, 0xD665, + 0x8B0B, 0xD666, 0x8B0C, 0xD667, 0x8B0D, 0xD668, 0x8B0E, 0xD669, 0x8B0F, 0xD66A, 0x8B10, 0xD66B, 0x8B11, 0xD66C, 0x8B12, 0xD66D, + 0x8B13, 0xD66E, 0x8B14, 0xD66F, 0x8B15, 0xD670, 0x8B16, 0xD671, 0x8B17, 0xD672, 0x8B18, 0xD673, 0x8B19, 0xD674, 0x8B1A, 0xD675, + 0x8B1B, 0xD676, 0x8B1C, 0xD677, 0x8B1D, 0xD678, 0x8B1E, 0xD679, 0x8B1F, 0xD67A, 0x8B20, 0xD67B, 0x8B21, 0xD67C, 0x8B22, 0xD67D, + 0x8B23, 0xD67E, 0x8B24, 0xD680, 0x8B25, 0xD681, 0x8B26, 0xF6A5, 0x8B27, 0xD682, 0x8B28, 0xD683, 0x8B29, 0xD684, 0x8B2A, 0xD685, + 0x8B2B, 0xD686, 0x8B2C, 0xD687, 0x8B2D, 0xD688, 0x8B2E, 0xD689, 0x8B2F, 0xD68A, 0x8B30, 0xD68B, 0x8B31, 0xD68C, 0x8B32, 0xD68D, + 0x8B33, 0xD68E, 0x8B34, 0xD68F, 0x8B35, 0xD690, 0x8B36, 0xD691, 0x8B37, 0xD692, 0x8B38, 0xD693, 0x8B39, 0xD694, 0x8B3A, 0xD695, + 0x8B3B, 0xD696, 0x8B3C, 0xD697, 0x8B3D, 0xD698, 0x8B3E, 0xD699, 0x8B3F, 0xD69A, 0x8B40, 0xD69B, 0x8B41, 0xD69C, 0x8B42, 0xD69D, + 0x8B43, 0xD69E, 0x8B44, 0xD69F, 0x8B45, 0xD6A0, 0x8B46, 0xD740, 0x8B47, 0xD741, 0x8B48, 0xD742, 0x8B49, 0xD743, 0x8B4A, 0xD744, + 0x8B4B, 0xD745, 0x8B4C, 0xD746, 0x8B4D, 0xD747, 0x8B4E, 0xD748, 0x8B4F, 0xD749, 0x8B50, 0xD74A, 0x8B51, 0xD74B, 0x8B52, 0xD74C, + 0x8B53, 0xD74D, 0x8B54, 0xD74E, 0x8B55, 0xD74F, 0x8B56, 0xD750, 0x8B57, 0xD751, 0x8B58, 0xD752, 0x8B59, 0xD753, 0x8B5A, 0xD754, + 0x8B5B, 0xD755, 0x8B5C, 0xD756, 0x8B5D, 0xD757, 0x8B5E, 0xD758, 0x8B5F, 0xD759, 0x8B60, 0xD75A, 0x8B61, 0xD75B, 0x8B62, 0xD75C, + 0x8B63, 0xD75D, 0x8B64, 0xD75E, 0x8B65, 0xD75F, 0x8B66, 0xBEAF, 0x8B67, 0xD760, 0x8B68, 0xD761, 0x8B69, 0xD762, 0x8B6A, 0xD763, + 0x8B6B, 0xD764, 0x8B6C, 0xC6A9, 0x8B6D, 0xD765, 0x8B6E, 0xD766, 0x8B6F, 0xD767, 0x8B70, 0xD768, 0x8B71, 0xD769, 0x8B72, 0xD76A, + 0x8B73, 0xD76B, 0x8B74, 0xD76C, 0x8B75, 0xD76D, 0x8B76, 0xD76E, 0x8B77, 0xD76F, 0x8B78, 0xD770, 0x8B79, 0xD771, 0x8B7A, 0xD772, + 0x8B7B, 0xD773, 0x8B7C, 0xD774, 0x8B7D, 0xD775, 0x8B7E, 0xD776, 0x8B7F, 0xD777, 0x8B80, 0xD778, 0x8B81, 0xD779, 0x8B82, 0xD77A, + 0x8B83, 0xD77B, 0x8B84, 0xD77C, 0x8B85, 0xD77D, 0x8B86, 0xD77E, 0x8B87, 0xD780, 0x8B88, 0xD781, 0x8B89, 0xD782, 0x8B8A, 0xD783, + 0x8B8B, 0xD784, 0x8B8C, 0xD785, 0x8B8D, 0xD786, 0x8B8E, 0xD787, 0x8B8F, 0xD788, 0x8B90, 0xD789, 0x8B91, 0xD78A, 0x8B92, 0xD78B, + 0x8B93, 0xD78C, 0x8B94, 0xD78D, 0x8B95, 0xD78E, 0x8B96, 0xD78F, 0x8B97, 0xD790, 0x8B98, 0xD791, 0x8B99, 0xD792, 0x8B9A, 0xD793, + 0x8B9B, 0xD794, 0x8B9C, 0xD795, 0x8B9D, 0xD796, 0x8B9E, 0xD797, 0x8B9F, 0xD798, 0x8BA0, 0xDAA5, 0x8BA1, 0xBCC6, 0x8BA2, 0xB6A9, + 0x8BA3, 0xB8BC, 0x8BA4, 0xC8CF, 0x8BA5, 0xBCA5, 0x8BA6, 0xDAA6, 0x8BA7, 0xDAA7, 0x8BA8, 0xCCD6, 0x8BA9, 0xC8C3, 0x8BAA, 0xDAA8, + 0x8BAB, 0xC6FD, 0x8BAC, 0xD799, 0x8BAD, 0xD1B5, 0x8BAE, 0xD2E9, 0x8BAF, 0xD1B6, 0x8BB0, 0xBCC7, 0x8BB1, 0xD79A, 0x8BB2, 0xBDB2, + 0x8BB3, 0xBBE4, 0x8BB4, 0xDAA9, 0x8BB5, 0xDAAA, 0x8BB6, 0xD1C8, 0x8BB7, 0xDAAB, 0x8BB8, 0xD0ED, 0x8BB9, 0xB6EF, 0x8BBA, 0xC2DB, + 0x8BBB, 0xD79B, 0x8BBC, 0xCBCF, 0x8BBD, 0xB7ED, 0x8BBE, 0xC9E8, 0x8BBF, 0xB7C3, 0x8BC0, 0xBEF7, 0x8BC1, 0xD6A4, 0x8BC2, 0xDAAC, + 0x8BC3, 0xDAAD, 0x8BC4, 0xC6C0, 0x8BC5, 0xD7E7, 0x8BC6, 0xCAB6, 0x8BC7, 0xD79C, 0x8BC8, 0xD5A9, 0x8BC9, 0xCBDF, 0x8BCA, 0xD5EF, + 0x8BCB, 0xDAAE, 0x8BCC, 0xD6DF, 0x8BCD, 0xB4CA, 0x8BCE, 0xDAB0, 0x8BCF, 0xDAAF, 0x8BD0, 0xD79D, 0x8BD1, 0xD2EB, 0x8BD2, 0xDAB1, + 0x8BD3, 0xDAB2, 0x8BD4, 0xDAB3, 0x8BD5, 0xCAD4, 0x8BD6, 0xDAB4, 0x8BD7, 0xCAAB, 0x8BD8, 0xDAB5, 0x8BD9, 0xDAB6, 0x8BDA, 0xB3CF, + 0x8BDB, 0xD6EF, 0x8BDC, 0xDAB7, 0x8BDD, 0xBBB0, 0x8BDE, 0xB5AE, 0x8BDF, 0xDAB8, 0x8BE0, 0xDAB9, 0x8BE1, 0xB9EE, 0x8BE2, 0xD1AF, + 0x8BE3, 0xD2E8, 0x8BE4, 0xDABA, 0x8BE5, 0xB8C3, 0x8BE6, 0xCFEA, 0x8BE7, 0xB2EF, 0x8BE8, 0xDABB, 0x8BE9, 0xDABC, 0x8BEA, 0xD79E, + 0x8BEB, 0xBDEB, 0x8BEC, 0xCEDC, 0x8BED, 0xD3EF, 0x8BEE, 0xDABD, 0x8BEF, 0xCEF3, 0x8BF0, 0xDABE, 0x8BF1, 0xD3D5, 0x8BF2, 0xBBE5, + 0x8BF3, 0xDABF, 0x8BF4, 0xCBB5, 0x8BF5, 0xCBD0, 0x8BF6, 0xDAC0, 0x8BF7, 0xC7EB, 0x8BF8, 0xD6EE, 0x8BF9, 0xDAC1, 0x8BFA, 0xC5B5, + 0x8BFB, 0xB6C1, 0x8BFC, 0xDAC2, 0x8BFD, 0xB7CC, 0x8BFE, 0xBFCE, 0x8BFF, 0xDAC3, 0x8C00, 0xDAC4, 0x8C01, 0xCBAD, 0x8C02, 0xDAC5, + 0x8C03, 0xB5F7, 0x8C04, 0xDAC6, 0x8C05, 0xC1C2, 0x8C06, 0xD7BB, 0x8C07, 0xDAC7, 0x8C08, 0xCCB8, 0x8C09, 0xD79F, 0x8C0A, 0xD2EA, + 0x8C0B, 0xC4B1, 0x8C0C, 0xDAC8, 0x8C0D, 0xB5FD, 0x8C0E, 0xBBD1, 0x8C0F, 0xDAC9, 0x8C10, 0xD0B3, 0x8C11, 0xDACA, 0x8C12, 0xDACB, + 0x8C13, 0xCEBD, 0x8C14, 0xDACC, 0x8C15, 0xDACD, 0x8C16, 0xDACE, 0x8C17, 0xB2F7, 0x8C18, 0xDAD1, 0x8C19, 0xDACF, 0x8C1A, 0xD1E8, + 0x8C1B, 0xDAD0, 0x8C1C, 0xC3D5, 0x8C1D, 0xDAD2, 0x8C1E, 0xD7A0, 0x8C1F, 0xDAD3, 0x8C20, 0xDAD4, 0x8C21, 0xDAD5, 0x8C22, 0xD0BB, + 0x8C23, 0xD2A5, 0x8C24, 0xB0F9, 0x8C25, 0xDAD6, 0x8C26, 0xC7AB, 0x8C27, 0xDAD7, 0x8C28, 0xBDF7, 0x8C29, 0xC3A1, 0x8C2A, 0xDAD8, + 0x8C2B, 0xDAD9, 0x8C2C, 0xC3FD, 0x8C2D, 0xCCB7, 0x8C2E, 0xDADA, 0x8C2F, 0xDADB, 0x8C30, 0xC0BE, 0x8C31, 0xC6D7, 0x8C32, 0xDADC, + 0x8C33, 0xDADD, 0x8C34, 0xC7B4, 0x8C35, 0xDADE, 0x8C36, 0xDADF, 0x8C37, 0xB9C8, 0x8C38, 0xD840, 0x8C39, 0xD841, 0x8C3A, 0xD842, + 0x8C3B, 0xD843, 0x8C3C, 0xD844, 0x8C3D, 0xD845, 0x8C3E, 0xD846, 0x8C3F, 0xD847, 0x8C40, 0xD848, 0x8C41, 0xBBED, 0x8C42, 0xD849, + 0x8C43, 0xD84A, 0x8C44, 0xD84B, 0x8C45, 0xD84C, 0x8C46, 0xB6B9, 0x8C47, 0xF4F8, 0x8C48, 0xD84D, 0x8C49, 0xF4F9, 0x8C4A, 0xD84E, + 0x8C4B, 0xD84F, 0x8C4C, 0xCDE3, 0x8C4D, 0xD850, 0x8C4E, 0xD851, 0x8C4F, 0xD852, 0x8C50, 0xD853, 0x8C51, 0xD854, 0x8C52, 0xD855, + 0x8C53, 0xD856, 0x8C54, 0xD857, 0x8C55, 0xF5B9, 0x8C56, 0xD858, 0x8C57, 0xD859, 0x8C58, 0xD85A, 0x8C59, 0xD85B, 0x8C5A, 0xEBE0, + 0x8C5B, 0xD85C, 0x8C5C, 0xD85D, 0x8C5D, 0xD85E, 0x8C5E, 0xD85F, 0x8C5F, 0xD860, 0x8C60, 0xD861, 0x8C61, 0xCFF3, 0x8C62, 0xBBBF, + 0x8C63, 0xD862, 0x8C64, 0xD863, 0x8C65, 0xD864, 0x8C66, 0xD865, 0x8C67, 0xD866, 0x8C68, 0xD867, 0x8C69, 0xD868, 0x8C6A, 0xBAC0, + 0x8C6B, 0xD4A5, 0x8C6C, 0xD869, 0x8C6D, 0xD86A, 0x8C6E, 0xD86B, 0x8C6F, 0xD86C, 0x8C70, 0xD86D, 0x8C71, 0xD86E, 0x8C72, 0xD86F, + 0x8C73, 0xE1D9, 0x8C74, 0xD870, 0x8C75, 0xD871, 0x8C76, 0xD872, 0x8C77, 0xD873, 0x8C78, 0xF5F4, 0x8C79, 0xB1AA, 0x8C7A, 0xB2F2, + 0x8C7B, 0xD874, 0x8C7C, 0xD875, 0x8C7D, 0xD876, 0x8C7E, 0xD877, 0x8C7F, 0xD878, 0x8C80, 0xD879, 0x8C81, 0xD87A, 0x8C82, 0xF5F5, + 0x8C83, 0xD87B, 0x8C84, 0xD87C, 0x8C85, 0xF5F7, 0x8C86, 0xD87D, 0x8C87, 0xD87E, 0x8C88, 0xD880, 0x8C89, 0xBAD1, 0x8C8A, 0xF5F6, + 0x8C8B, 0xD881, 0x8C8C, 0xC3B2, 0x8C8D, 0xD882, 0x8C8E, 0xD883, 0x8C8F, 0xD884, 0x8C90, 0xD885, 0x8C91, 0xD886, 0x8C92, 0xD887, + 0x8C93, 0xD888, 0x8C94, 0xF5F9, 0x8C95, 0xD889, 0x8C96, 0xD88A, 0x8C97, 0xD88B, 0x8C98, 0xF5F8, 0x8C99, 0xD88C, 0x8C9A, 0xD88D, + 0x8C9B, 0xD88E, 0x8C9C, 0xD88F, 0x8C9D, 0xD890, 0x8C9E, 0xD891, 0x8C9F, 0xD892, 0x8CA0, 0xD893, 0x8CA1, 0xD894, 0x8CA2, 0xD895, + 0x8CA3, 0xD896, 0x8CA4, 0xD897, 0x8CA5, 0xD898, 0x8CA6, 0xD899, 0x8CA7, 0xD89A, 0x8CA8, 0xD89B, 0x8CA9, 0xD89C, 0x8CAA, 0xD89D, + 0x8CAB, 0xD89E, 0x8CAC, 0xD89F, 0x8CAD, 0xD8A0, 0x8CAE, 0xD940, 0x8CAF, 0xD941, 0x8CB0, 0xD942, 0x8CB1, 0xD943, 0x8CB2, 0xD944, + 0x8CB3, 0xD945, 0x8CB4, 0xD946, 0x8CB5, 0xD947, 0x8CB6, 0xD948, 0x8CB7, 0xD949, 0x8CB8, 0xD94A, 0x8CB9, 0xD94B, 0x8CBA, 0xD94C, + 0x8CBB, 0xD94D, 0x8CBC, 0xD94E, 0x8CBD, 0xD94F, 0x8CBE, 0xD950, 0x8CBF, 0xD951, 0x8CC0, 0xD952, 0x8CC1, 0xD953, 0x8CC2, 0xD954, + 0x8CC3, 0xD955, 0x8CC4, 0xD956, 0x8CC5, 0xD957, 0x8CC6, 0xD958, 0x8CC7, 0xD959, 0x8CC8, 0xD95A, 0x8CC9, 0xD95B, 0x8CCA, 0xD95C, + 0x8CCB, 0xD95D, 0x8CCC, 0xD95E, 0x8CCD, 0xD95F, 0x8CCE, 0xD960, 0x8CCF, 0xD961, 0x8CD0, 0xD962, 0x8CD1, 0xD963, 0x8CD2, 0xD964, + 0x8CD3, 0xD965, 0x8CD4, 0xD966, 0x8CD5, 0xD967, 0x8CD6, 0xD968, 0x8CD7, 0xD969, 0x8CD8, 0xD96A, 0x8CD9, 0xD96B, 0x8CDA, 0xD96C, + 0x8CDB, 0xD96D, 0x8CDC, 0xD96E, 0x8CDD, 0xD96F, 0x8CDE, 0xD970, 0x8CDF, 0xD971, 0x8CE0, 0xD972, 0x8CE1, 0xD973, 0x8CE2, 0xD974, + 0x8CE3, 0xD975, 0x8CE4, 0xD976, 0x8CE5, 0xD977, 0x8CE6, 0xD978, 0x8CE7, 0xD979, 0x8CE8, 0xD97A, 0x8CE9, 0xD97B, 0x8CEA, 0xD97C, + 0x8CEB, 0xD97D, 0x8CEC, 0xD97E, 0x8CED, 0xD980, 0x8CEE, 0xD981, 0x8CEF, 0xD982, 0x8CF0, 0xD983, 0x8CF1, 0xD984, 0x8CF2, 0xD985, + 0x8CF3, 0xD986, 0x8CF4, 0xD987, 0x8CF5, 0xD988, 0x8CF6, 0xD989, 0x8CF7, 0xD98A, 0x8CF8, 0xD98B, 0x8CF9, 0xD98C, 0x8CFA, 0xD98D, + 0x8CFB, 0xD98E, 0x8CFC, 0xD98F, 0x8CFD, 0xD990, 0x8CFE, 0xD991, 0x8CFF, 0xD992, 0x8D00, 0xD993, 0x8D01, 0xD994, 0x8D02, 0xD995, + 0x8D03, 0xD996, 0x8D04, 0xD997, 0x8D05, 0xD998, 0x8D06, 0xD999, 0x8D07, 0xD99A, 0x8D08, 0xD99B, 0x8D09, 0xD99C, 0x8D0A, 0xD99D, + 0x8D0B, 0xD99E, 0x8D0C, 0xD99F, 0x8D0D, 0xD9A0, 0x8D0E, 0xDA40, 0x8D0F, 0xDA41, 0x8D10, 0xDA42, 0x8D11, 0xDA43, 0x8D12, 0xDA44, + 0x8D13, 0xDA45, 0x8D14, 0xDA46, 0x8D15, 0xDA47, 0x8D16, 0xDA48, 0x8D17, 0xDA49, 0x8D18, 0xDA4A, 0x8D19, 0xDA4B, 0x8D1A, 0xDA4C, + 0x8D1B, 0xDA4D, 0x8D1C, 0xDA4E, 0x8D1D, 0xB1B4, 0x8D1E, 0xD5EA, 0x8D1F, 0xB8BA, 0x8D20, 0xDA4F, 0x8D21, 0xB9B1, 0x8D22, 0xB2C6, + 0x8D23, 0xD4F0, 0x8D24, 0xCFCD, 0x8D25, 0xB0DC, 0x8D26, 0xD5CB, 0x8D27, 0xBBF5, 0x8D28, 0xD6CA, 0x8D29, 0xB7B7, 0x8D2A, 0xCCB0, + 0x8D2B, 0xC6B6, 0x8D2C, 0xB1E1, 0x8D2D, 0xB9BA, 0x8D2E, 0xD6FC, 0x8D2F, 0xB9E1, 0x8D30, 0xB7A1, 0x8D31, 0xBCFA, 0x8D32, 0xEADA, + 0x8D33, 0xEADB, 0x8D34, 0xCCF9, 0x8D35, 0xB9F3, 0x8D36, 0xEADC, 0x8D37, 0xB4FB, 0x8D38, 0xC3B3, 0x8D39, 0xB7D1, 0x8D3A, 0xBAD8, + 0x8D3B, 0xEADD, 0x8D3C, 0xD4F4, 0x8D3D, 0xEADE, 0x8D3E, 0xBCD6, 0x8D3F, 0xBBDF, 0x8D40, 0xEADF, 0x8D41, 0xC1DE, 0x8D42, 0xC2B8, + 0x8D43, 0xD4DF, 0x8D44, 0xD7CA, 0x8D45, 0xEAE0, 0x8D46, 0xEAE1, 0x8D47, 0xEAE4, 0x8D48, 0xEAE2, 0x8D49, 0xEAE3, 0x8D4A, 0xC9DE, + 0x8D4B, 0xB8B3, 0x8D4C, 0xB6C4, 0x8D4D, 0xEAE5, 0x8D4E, 0xCAEA, 0x8D4F, 0xC9CD, 0x8D50, 0xB4CD, 0x8D51, 0xDA50, 0x8D52, 0xDA51, + 0x8D53, 0xE2D9, 0x8D54, 0xC5E2, 0x8D55, 0xEAE6, 0x8D56, 0xC0B5, 0x8D57, 0xDA52, 0x8D58, 0xD7B8, 0x8D59, 0xEAE7, 0x8D5A, 0xD7AC, + 0x8D5B, 0xC8FC, 0x8D5C, 0xD8D3, 0x8D5D, 0xD8CD, 0x8D5E, 0xD4DE, 0x8D5F, 0xDA53, 0x8D60, 0xD4F9, 0x8D61, 0xC9C4, 0x8D62, 0xD3AE, + 0x8D63, 0xB8D3, 0x8D64, 0xB3E0, 0x8D65, 0xDA54, 0x8D66, 0xC9E2, 0x8D67, 0xF4F6, 0x8D68, 0xDA55, 0x8D69, 0xDA56, 0x8D6A, 0xDA57, + 0x8D6B, 0xBAD5, 0x8D6C, 0xDA58, 0x8D6D, 0xF4F7, 0x8D6E, 0xDA59, 0x8D6F, 0xDA5A, 0x8D70, 0xD7DF, 0x8D71, 0xDA5B, 0x8D72, 0xDA5C, + 0x8D73, 0xF4F1, 0x8D74, 0xB8B0, 0x8D75, 0xD5D4, 0x8D76, 0xB8CF, 0x8D77, 0xC6F0, 0x8D78, 0xDA5D, 0x8D79, 0xDA5E, 0x8D7A, 0xDA5F, + 0x8D7B, 0xDA60, 0x8D7C, 0xDA61, 0x8D7D, 0xDA62, 0x8D7E, 0xDA63, 0x8D7F, 0xDA64, 0x8D80, 0xDA65, 0x8D81, 0xB3C3, 0x8D82, 0xDA66, + 0x8D83, 0xDA67, 0x8D84, 0xF4F2, 0x8D85, 0xB3AC, 0x8D86, 0xDA68, 0x8D87, 0xDA69, 0x8D88, 0xDA6A, 0x8D89, 0xDA6B, 0x8D8A, 0xD4BD, + 0x8D8B, 0xC7F7, 0x8D8C, 0xDA6C, 0x8D8D, 0xDA6D, 0x8D8E, 0xDA6E, 0x8D8F, 0xDA6F, 0x8D90, 0xDA70, 0x8D91, 0xF4F4, 0x8D92, 0xDA71, + 0x8D93, 0xDA72, 0x8D94, 0xF4F3, 0x8D95, 0xDA73, 0x8D96, 0xDA74, 0x8D97, 0xDA75, 0x8D98, 0xDA76, 0x8D99, 0xDA77, 0x8D9A, 0xDA78, + 0x8D9B, 0xDA79, 0x8D9C, 0xDA7A, 0x8D9D, 0xDA7B, 0x8D9E, 0xDA7C, 0x8D9F, 0xCCCB, 0x8DA0, 0xDA7D, 0x8DA1, 0xDA7E, 0x8DA2, 0xDA80, + 0x8DA3, 0xC8A4, 0x8DA4, 0xDA81, 0x8DA5, 0xDA82, 0x8DA6, 0xDA83, 0x8DA7, 0xDA84, 0x8DA8, 0xDA85, 0x8DA9, 0xDA86, 0x8DAA, 0xDA87, + 0x8DAB, 0xDA88, 0x8DAC, 0xDA89, 0x8DAD, 0xDA8A, 0x8DAE, 0xDA8B, 0x8DAF, 0xDA8C, 0x8DB0, 0xDA8D, 0x8DB1, 0xF4F5, 0x8DB2, 0xDA8E, + 0x8DB3, 0xD7E3, 0x8DB4, 0xC5BF, 0x8DB5, 0xF5C0, 0x8DB6, 0xDA8F, 0x8DB7, 0xDA90, 0x8DB8, 0xF5BB, 0x8DB9, 0xDA91, 0x8DBA, 0xF5C3, + 0x8DBB, 0xDA92, 0x8DBC, 0xF5C2, 0x8DBD, 0xDA93, 0x8DBE, 0xD6BA, 0x8DBF, 0xF5C1, 0x8DC0, 0xDA94, 0x8DC1, 0xDA95, 0x8DC2, 0xDA96, + 0x8DC3, 0xD4BE, 0x8DC4, 0xF5C4, 0x8DC5, 0xDA97, 0x8DC6, 0xF5CC, 0x8DC7, 0xDA98, 0x8DC8, 0xDA99, 0x8DC9, 0xDA9A, 0x8DCA, 0xDA9B, + 0x8DCB, 0xB0CF, 0x8DCC, 0xB5F8, 0x8DCD, 0xDA9C, 0x8DCE, 0xF5C9, 0x8DCF, 0xF5CA, 0x8DD0, 0xDA9D, 0x8DD1, 0xC5DC, 0x8DD2, 0xDA9E, + 0x8DD3, 0xDA9F, 0x8DD4, 0xDAA0, 0x8DD5, 0xDB40, 0x8DD6, 0xF5C5, 0x8DD7, 0xF5C6, 0x8DD8, 0xDB41, 0x8DD9, 0xDB42, 0x8DDA, 0xF5C7, + 0x8DDB, 0xF5CB, 0x8DDC, 0xDB43, 0x8DDD, 0xBEE0, 0x8DDE, 0xF5C8, 0x8DDF, 0xB8FA, 0x8DE0, 0xDB44, 0x8DE1, 0xDB45, 0x8DE2, 0xDB46, + 0x8DE3, 0xF5D0, 0x8DE4, 0xF5D3, 0x8DE5, 0xDB47, 0x8DE6, 0xDB48, 0x8DE7, 0xDB49, 0x8DE8, 0xBFE7, 0x8DE9, 0xDB4A, 0x8DEA, 0xB9F2, + 0x8DEB, 0xF5BC, 0x8DEC, 0xF5CD, 0x8DED, 0xDB4B, 0x8DEE, 0xDB4C, 0x8DEF, 0xC2B7, 0x8DF0, 0xDB4D, 0x8DF1, 0xDB4E, 0x8DF2, 0xDB4F, + 0x8DF3, 0xCCF8, 0x8DF4, 0xDB50, 0x8DF5, 0xBCF9, 0x8DF6, 0xDB51, 0x8DF7, 0xF5CE, 0x8DF8, 0xF5CF, 0x8DF9, 0xF5D1, 0x8DFA, 0xB6E5, + 0x8DFB, 0xF5D2, 0x8DFC, 0xDB52, 0x8DFD, 0xF5D5, 0x8DFE, 0xDB53, 0x8DFF, 0xDB54, 0x8E00, 0xDB55, 0x8E01, 0xDB56, 0x8E02, 0xDB57, + 0x8E03, 0xDB58, 0x8E04, 0xDB59, 0x8E05, 0xF5BD, 0x8E06, 0xDB5A, 0x8E07, 0xDB5B, 0x8E08, 0xDB5C, 0x8E09, 0xF5D4, 0x8E0A, 0xD3BB, + 0x8E0B, 0xDB5D, 0x8E0C, 0xB3EC, 0x8E0D, 0xDB5E, 0x8E0E, 0xDB5F, 0x8E0F, 0xCCA4, 0x8E10, 0xDB60, 0x8E11, 0xDB61, 0x8E12, 0xDB62, + 0x8E13, 0xDB63, 0x8E14, 0xF5D6, 0x8E15, 0xDB64, 0x8E16, 0xDB65, 0x8E17, 0xDB66, 0x8E18, 0xDB67, 0x8E19, 0xDB68, 0x8E1A, 0xDB69, + 0x8E1B, 0xDB6A, 0x8E1C, 0xDB6B, 0x8E1D, 0xF5D7, 0x8E1E, 0xBEE1, 0x8E1F, 0xF5D8, 0x8E20, 0xDB6C, 0x8E21, 0xDB6D, 0x8E22, 0xCCDF, + 0x8E23, 0xF5DB, 0x8E24, 0xDB6E, 0x8E25, 0xDB6F, 0x8E26, 0xDB70, 0x8E27, 0xDB71, 0x8E28, 0xDB72, 0x8E29, 0xB2C8, 0x8E2A, 0xD7D9, + 0x8E2B, 0xDB73, 0x8E2C, 0xF5D9, 0x8E2D, 0xDB74, 0x8E2E, 0xF5DA, 0x8E2F, 0xF5DC, 0x8E30, 0xDB75, 0x8E31, 0xF5E2, 0x8E32, 0xDB76, + 0x8E33, 0xDB77, 0x8E34, 0xDB78, 0x8E35, 0xF5E0, 0x8E36, 0xDB79, 0x8E37, 0xDB7A, 0x8E38, 0xDB7B, 0x8E39, 0xF5DF, 0x8E3A, 0xF5DD, + 0x8E3B, 0xDB7C, 0x8E3C, 0xDB7D, 0x8E3D, 0xF5E1, 0x8E3E, 0xDB7E, 0x8E3F, 0xDB80, 0x8E40, 0xF5DE, 0x8E41, 0xF5E4, 0x8E42, 0xF5E5, + 0x8E43, 0xDB81, 0x8E44, 0xCCE3, 0x8E45, 0xDB82, 0x8E46, 0xDB83, 0x8E47, 0xE5BF, 0x8E48, 0xB5B8, 0x8E49, 0xF5E3, 0x8E4A, 0xF5E8, + 0x8E4B, 0xCCA3, 0x8E4C, 0xDB84, 0x8E4D, 0xDB85, 0x8E4E, 0xDB86, 0x8E4F, 0xDB87, 0x8E50, 0xDB88, 0x8E51, 0xF5E6, 0x8E52, 0xF5E7, + 0x8E53, 0xDB89, 0x8E54, 0xDB8A, 0x8E55, 0xDB8B, 0x8E56, 0xDB8C, 0x8E57, 0xDB8D, 0x8E58, 0xDB8E, 0x8E59, 0xF5BE, 0x8E5A, 0xDB8F, + 0x8E5B, 0xDB90, 0x8E5C, 0xDB91, 0x8E5D, 0xDB92, 0x8E5E, 0xDB93, 0x8E5F, 0xDB94, 0x8E60, 0xDB95, 0x8E61, 0xDB96, 0x8E62, 0xDB97, + 0x8E63, 0xDB98, 0x8E64, 0xDB99, 0x8E65, 0xDB9A, 0x8E66, 0xB1C4, 0x8E67, 0xDB9B, 0x8E68, 0xDB9C, 0x8E69, 0xF5BF, 0x8E6A, 0xDB9D, + 0x8E6B, 0xDB9E, 0x8E6C, 0xB5C5, 0x8E6D, 0xB2E4, 0x8E6E, 0xDB9F, 0x8E6F, 0xF5EC, 0x8E70, 0xF5E9, 0x8E71, 0xDBA0, 0x8E72, 0xB6D7, + 0x8E73, 0xDC40, 0x8E74, 0xF5ED, 0x8E75, 0xDC41, 0x8E76, 0xF5EA, 0x8E77, 0xDC42, 0x8E78, 0xDC43, 0x8E79, 0xDC44, 0x8E7A, 0xDC45, + 0x8E7B, 0xDC46, 0x8E7C, 0xF5EB, 0x8E7D, 0xDC47, 0x8E7E, 0xDC48, 0x8E7F, 0xB4DA, 0x8E80, 0xDC49, 0x8E81, 0xD4EA, 0x8E82, 0xDC4A, + 0x8E83, 0xDC4B, 0x8E84, 0xDC4C, 0x8E85, 0xF5EE, 0x8E86, 0xDC4D, 0x8E87, 0xB3F9, 0x8E88, 0xDC4E, 0x8E89, 0xDC4F, 0x8E8A, 0xDC50, + 0x8E8B, 0xDC51, 0x8E8C, 0xDC52, 0x8E8D, 0xDC53, 0x8E8E, 0xDC54, 0x8E8F, 0xF5EF, 0x8E90, 0xF5F1, 0x8E91, 0xDC55, 0x8E92, 0xDC56, + 0x8E93, 0xDC57, 0x8E94, 0xF5F0, 0x8E95, 0xDC58, 0x8E96, 0xDC59, 0x8E97, 0xDC5A, 0x8E98, 0xDC5B, 0x8E99, 0xDC5C, 0x8E9A, 0xDC5D, + 0x8E9B, 0xDC5E, 0x8E9C, 0xF5F2, 0x8E9D, 0xDC5F, 0x8E9E, 0xF5F3, 0x8E9F, 0xDC60, 0x8EA0, 0xDC61, 0x8EA1, 0xDC62, 0x8EA2, 0xDC63, + 0x8EA3, 0xDC64, 0x8EA4, 0xDC65, 0x8EA5, 0xDC66, 0x8EA6, 0xDC67, 0x8EA7, 0xDC68, 0x8EA8, 0xDC69, 0x8EA9, 0xDC6A, 0x8EAA, 0xDC6B, + 0x8EAB, 0xC9ED, 0x8EAC, 0xB9AA, 0x8EAD, 0xDC6C, 0x8EAE, 0xDC6D, 0x8EAF, 0xC7FB, 0x8EB0, 0xDC6E, 0x8EB1, 0xDC6F, 0x8EB2, 0xB6E3, + 0x8EB3, 0xDC70, 0x8EB4, 0xDC71, 0x8EB5, 0xDC72, 0x8EB6, 0xDC73, 0x8EB7, 0xDC74, 0x8EB8, 0xDC75, 0x8EB9, 0xDC76, 0x8EBA, 0xCCC9, + 0x8EBB, 0xDC77, 0x8EBC, 0xDC78, 0x8EBD, 0xDC79, 0x8EBE, 0xDC7A, 0x8EBF, 0xDC7B, 0x8EC0, 0xDC7C, 0x8EC1, 0xDC7D, 0x8EC2, 0xDC7E, + 0x8EC3, 0xDC80, 0x8EC4, 0xDC81, 0x8EC5, 0xDC82, 0x8EC6, 0xDC83, 0x8EC7, 0xDC84, 0x8EC8, 0xDC85, 0x8EC9, 0xDC86, 0x8ECA, 0xDC87, + 0x8ECB, 0xDC88, 0x8ECC, 0xDC89, 0x8ECD, 0xDC8A, 0x8ECE, 0xEAA6, 0x8ECF, 0xDC8B, 0x8ED0, 0xDC8C, 0x8ED1, 0xDC8D, 0x8ED2, 0xDC8E, + 0x8ED3, 0xDC8F, 0x8ED4, 0xDC90, 0x8ED5, 0xDC91, 0x8ED6, 0xDC92, 0x8ED7, 0xDC93, 0x8ED8, 0xDC94, 0x8ED9, 0xDC95, 0x8EDA, 0xDC96, + 0x8EDB, 0xDC97, 0x8EDC, 0xDC98, 0x8EDD, 0xDC99, 0x8EDE, 0xDC9A, 0x8EDF, 0xDC9B, 0x8EE0, 0xDC9C, 0x8EE1, 0xDC9D, 0x8EE2, 0xDC9E, + 0x8EE3, 0xDC9F, 0x8EE4, 0xDCA0, 0x8EE5, 0xDD40, 0x8EE6, 0xDD41, 0x8EE7, 0xDD42, 0x8EE8, 0xDD43, 0x8EE9, 0xDD44, 0x8EEA, 0xDD45, + 0x8EEB, 0xDD46, 0x8EEC, 0xDD47, 0x8EED, 0xDD48, 0x8EEE, 0xDD49, 0x8EEF, 0xDD4A, 0x8EF0, 0xDD4B, 0x8EF1, 0xDD4C, 0x8EF2, 0xDD4D, + 0x8EF3, 0xDD4E, 0x8EF4, 0xDD4F, 0x8EF5, 0xDD50, 0x8EF6, 0xDD51, 0x8EF7, 0xDD52, 0x8EF8, 0xDD53, 0x8EF9, 0xDD54, 0x8EFA, 0xDD55, + 0x8EFB, 0xDD56, 0x8EFC, 0xDD57, 0x8EFD, 0xDD58, 0x8EFE, 0xDD59, 0x8EFF, 0xDD5A, 0x8F00, 0xDD5B, 0x8F01, 0xDD5C, 0x8F02, 0xDD5D, + 0x8F03, 0xDD5E, 0x8F04, 0xDD5F, 0x8F05, 0xDD60, 0x8F06, 0xDD61, 0x8F07, 0xDD62, 0x8F08, 0xDD63, 0x8F09, 0xDD64, 0x8F0A, 0xDD65, + 0x8F0B, 0xDD66, 0x8F0C, 0xDD67, 0x8F0D, 0xDD68, 0x8F0E, 0xDD69, 0x8F0F, 0xDD6A, 0x8F10, 0xDD6B, 0x8F11, 0xDD6C, 0x8F12, 0xDD6D, + 0x8F13, 0xDD6E, 0x8F14, 0xDD6F, 0x8F15, 0xDD70, 0x8F16, 0xDD71, 0x8F17, 0xDD72, 0x8F18, 0xDD73, 0x8F19, 0xDD74, 0x8F1A, 0xDD75, + 0x8F1B, 0xDD76, 0x8F1C, 0xDD77, 0x8F1D, 0xDD78, 0x8F1E, 0xDD79, 0x8F1F, 0xDD7A, 0x8F20, 0xDD7B, 0x8F21, 0xDD7C, 0x8F22, 0xDD7D, + 0x8F23, 0xDD7E, 0x8F24, 0xDD80, 0x8F25, 0xDD81, 0x8F26, 0xDD82, 0x8F27, 0xDD83, 0x8F28, 0xDD84, 0x8F29, 0xDD85, 0x8F2A, 0xDD86, + 0x8F2B, 0xDD87, 0x8F2C, 0xDD88, 0x8F2D, 0xDD89, 0x8F2E, 0xDD8A, 0x8F2F, 0xDD8B, 0x8F30, 0xDD8C, 0x8F31, 0xDD8D, 0x8F32, 0xDD8E, + 0x8F33, 0xDD8F, 0x8F34, 0xDD90, 0x8F35, 0xDD91, 0x8F36, 0xDD92, 0x8F37, 0xDD93, 0x8F38, 0xDD94, 0x8F39, 0xDD95, 0x8F3A, 0xDD96, + 0x8F3B, 0xDD97, 0x8F3C, 0xDD98, 0x8F3D, 0xDD99, 0x8F3E, 0xDD9A, 0x8F3F, 0xDD9B, 0x8F40, 0xDD9C, 0x8F41, 0xDD9D, 0x8F42, 0xDD9E, + 0x8F43, 0xDD9F, 0x8F44, 0xDDA0, 0x8F45, 0xDE40, 0x8F46, 0xDE41, 0x8F47, 0xDE42, 0x8F48, 0xDE43, 0x8F49, 0xDE44, 0x8F4A, 0xDE45, + 0x8F4B, 0xDE46, 0x8F4C, 0xDE47, 0x8F4D, 0xDE48, 0x8F4E, 0xDE49, 0x8F4F, 0xDE4A, 0x8F50, 0xDE4B, 0x8F51, 0xDE4C, 0x8F52, 0xDE4D, + 0x8F53, 0xDE4E, 0x8F54, 0xDE4F, 0x8F55, 0xDE50, 0x8F56, 0xDE51, 0x8F57, 0xDE52, 0x8F58, 0xDE53, 0x8F59, 0xDE54, 0x8F5A, 0xDE55, + 0x8F5B, 0xDE56, 0x8F5C, 0xDE57, 0x8F5D, 0xDE58, 0x8F5E, 0xDE59, 0x8F5F, 0xDE5A, 0x8F60, 0xDE5B, 0x8F61, 0xDE5C, 0x8F62, 0xDE5D, + 0x8F63, 0xDE5E, 0x8F64, 0xDE5F, 0x8F65, 0xDE60, 0x8F66, 0xB3B5, 0x8F67, 0xD4FE, 0x8F68, 0xB9EC, 0x8F69, 0xD0F9, 0x8F6A, 0xDE61, + 0x8F6B, 0xE9ED, 0x8F6C, 0xD7AA, 0x8F6D, 0xE9EE, 0x8F6E, 0xC2D6, 0x8F6F, 0xC8ED, 0x8F70, 0xBAE4, 0x8F71, 0xE9EF, 0x8F72, 0xE9F0, + 0x8F73, 0xE9F1, 0x8F74, 0xD6E1, 0x8F75, 0xE9F2, 0x8F76, 0xE9F3, 0x8F77, 0xE9F5, 0x8F78, 0xE9F4, 0x8F79, 0xE9F6, 0x8F7A, 0xE9F7, + 0x8F7B, 0xC7E1, 0x8F7C, 0xE9F8, 0x8F7D, 0xD4D8, 0x8F7E, 0xE9F9, 0x8F7F, 0xBDCE, 0x8F80, 0xDE62, 0x8F81, 0xE9FA, 0x8F82, 0xE9FB, + 0x8F83, 0xBDCF, 0x8F84, 0xE9FC, 0x8F85, 0xB8A8, 0x8F86, 0xC1BE, 0x8F87, 0xE9FD, 0x8F88, 0xB1B2, 0x8F89, 0xBBD4, 0x8F8A, 0xB9F5, + 0x8F8B, 0xE9FE, 0x8F8C, 0xDE63, 0x8F8D, 0xEAA1, 0x8F8E, 0xEAA2, 0x8F8F, 0xEAA3, 0x8F90, 0xB7F8, 0x8F91, 0xBCAD, 0x8F92, 0xDE64, + 0x8F93, 0xCAE4, 0x8F94, 0xE0CE, 0x8F95, 0xD4AF, 0x8F96, 0xCFBD, 0x8F97, 0xD5B7, 0x8F98, 0xEAA4, 0x8F99, 0xD5DE, 0x8F9A, 0xEAA5, + 0x8F9B, 0xD0C1, 0x8F9C, 0xB9BC, 0x8F9D, 0xDE65, 0x8F9E, 0xB4C7, 0x8F9F, 0xB1D9, 0x8FA0, 0xDE66, 0x8FA1, 0xDE67, 0x8FA2, 0xDE68, + 0x8FA3, 0xC0B1, 0x8FA4, 0xDE69, 0x8FA5, 0xDE6A, 0x8FA6, 0xDE6B, 0x8FA7, 0xDE6C, 0x8FA8, 0xB1E6, 0x8FA9, 0xB1E7, 0x8FAA, 0xDE6D, + 0x8FAB, 0xB1E8, 0x8FAC, 0xDE6E, 0x8FAD, 0xDE6F, 0x8FAE, 0xDE70, 0x8FAF, 0xDE71, 0x8FB0, 0xB3BD, 0x8FB1, 0xC8E8, 0x8FB2, 0xDE72, + 0x8FB3, 0xDE73, 0x8FB4, 0xDE74, 0x8FB5, 0xDE75, 0x8FB6, 0xE5C1, 0x8FB7, 0xDE76, 0x8FB8, 0xDE77, 0x8FB9, 0xB1DF, 0x8FBA, 0xDE78, + 0x8FBB, 0xDE79, 0x8FBC, 0xDE7A, 0x8FBD, 0xC1C9, 0x8FBE, 0xB4EF, 0x8FBF, 0xDE7B, 0x8FC0, 0xDE7C, 0x8FC1, 0xC7A8, 0x8FC2, 0xD3D8, + 0x8FC3, 0xDE7D, 0x8FC4, 0xC6F9, 0x8FC5, 0xD1B8, 0x8FC6, 0xDE7E, 0x8FC7, 0xB9FD, 0x8FC8, 0xC2F5, 0x8FC9, 0xDE80, 0x8FCA, 0xDE81, + 0x8FCB, 0xDE82, 0x8FCC, 0xDE83, 0x8FCD, 0xDE84, 0x8FCE, 0xD3AD, 0x8FCF, 0xDE85, 0x8FD0, 0xD4CB, 0x8FD1, 0xBDFC, 0x8FD2, 0xDE86, + 0x8FD3, 0xE5C2, 0x8FD4, 0xB7B5, 0x8FD5, 0xE5C3, 0x8FD6, 0xDE87, 0x8FD7, 0xDE88, 0x8FD8, 0xBBB9, 0x8FD9, 0xD5E2, 0x8FDA, 0xDE89, + 0x8FDB, 0xBDF8, 0x8FDC, 0xD4B6, 0x8FDD, 0xCEA5, 0x8FDE, 0xC1AC, 0x8FDF, 0xB3D9, 0x8FE0, 0xDE8A, 0x8FE1, 0xDE8B, 0x8FE2, 0xCCF6, + 0x8FE3, 0xDE8C, 0x8FE4, 0xE5C6, 0x8FE5, 0xE5C4, 0x8FE6, 0xE5C8, 0x8FE7, 0xDE8D, 0x8FE8, 0xE5CA, 0x8FE9, 0xE5C7, 0x8FEA, 0xB5CF, + 0x8FEB, 0xC6C8, 0x8FEC, 0xDE8E, 0x8FED, 0xB5FC, 0x8FEE, 0xE5C5, 0x8FEF, 0xDE8F, 0x8FF0, 0xCAF6, 0x8FF1, 0xDE90, 0x8FF2, 0xDE91, + 0x8FF3, 0xE5C9, 0x8FF4, 0xDE92, 0x8FF5, 0xDE93, 0x8FF6, 0xDE94, 0x8FF7, 0xC3D4, 0x8FF8, 0xB1C5, 0x8FF9, 0xBCA3, 0x8FFA, 0xDE95, + 0x8FFB, 0xDE96, 0x8FFC, 0xDE97, 0x8FFD, 0xD7B7, 0x8FFE, 0xDE98, 0x8FFF, 0xDE99, 0x9000, 0xCDCB, 0x9001, 0xCBCD, 0x9002, 0xCACA, + 0x9003, 0xCCD3, 0x9004, 0xE5CC, 0x9005, 0xE5CB, 0x9006, 0xC4E6, 0x9007, 0xDE9A, 0x9008, 0xDE9B, 0x9009, 0xD1A1, 0x900A, 0xD1B7, + 0x900B, 0xE5CD, 0x900C, 0xDE9C, 0x900D, 0xE5D0, 0x900E, 0xDE9D, 0x900F, 0xCDB8, 0x9010, 0xD6F0, 0x9011, 0xE5CF, 0x9012, 0xB5DD, + 0x9013, 0xDE9E, 0x9014, 0xCDBE, 0x9015, 0xDE9F, 0x9016, 0xE5D1, 0x9017, 0xB6BA, 0x9018, 0xDEA0, 0x9019, 0xDF40, 0x901A, 0xCDA8, + 0x901B, 0xB9E4, 0x901C, 0xDF41, 0x901D, 0xCAC5, 0x901E, 0xB3D1, 0x901F, 0xCBD9, 0x9020, 0xD4EC, 0x9021, 0xE5D2, 0x9022, 0xB7EA, + 0x9023, 0xDF42, 0x9024, 0xDF43, 0x9025, 0xDF44, 0x9026, 0xE5CE, 0x9027, 0xDF45, 0x9028, 0xDF46, 0x9029, 0xDF47, 0x902A, 0xDF48, + 0x902B, 0xDF49, 0x902C, 0xDF4A, 0x902D, 0xE5D5, 0x902E, 0xB4FE, 0x902F, 0xE5D6, 0x9030, 0xDF4B, 0x9031, 0xDF4C, 0x9032, 0xDF4D, + 0x9033, 0xDF4E, 0x9034, 0xDF4F, 0x9035, 0xE5D3, 0x9036, 0xE5D4, 0x9037, 0xDF50, 0x9038, 0xD2DD, 0x9039, 0xDF51, 0x903A, 0xDF52, + 0x903B, 0xC2DF, 0x903C, 0xB1C6, 0x903D, 0xDF53, 0x903E, 0xD3E2, 0x903F, 0xDF54, 0x9040, 0xDF55, 0x9041, 0xB6DD, 0x9042, 0xCBEC, + 0x9043, 0xDF56, 0x9044, 0xE5D7, 0x9045, 0xDF57, 0x9046, 0xDF58, 0x9047, 0xD3F6, 0x9048, 0xDF59, 0x9049, 0xDF5A, 0x904A, 0xDF5B, + 0x904B, 0xDF5C, 0x904C, 0xDF5D, 0x904D, 0xB1E9, 0x904E, 0xDF5E, 0x904F, 0xB6F4, 0x9050, 0xE5DA, 0x9051, 0xE5D8, 0x9052, 0xE5D9, + 0x9053, 0xB5C0, 0x9054, 0xDF5F, 0x9055, 0xDF60, 0x9056, 0xDF61, 0x9057, 0xD2C5, 0x9058, 0xE5DC, 0x9059, 0xDF62, 0x905A, 0xDF63, + 0x905B, 0xE5DE, 0x905C, 0xDF64, 0x905D, 0xDF65, 0x905E, 0xDF66, 0x905F, 0xDF67, 0x9060, 0xDF68, 0x9061, 0xDF69, 0x9062, 0xE5DD, + 0x9063, 0xC7B2, 0x9064, 0xDF6A, 0x9065, 0xD2A3, 0x9066, 0xDF6B, 0x9067, 0xDF6C, 0x9068, 0xE5DB, 0x9069, 0xDF6D, 0x906A, 0xDF6E, + 0x906B, 0xDF6F, 0x906C, 0xDF70, 0x906D, 0xD4E2, 0x906E, 0xD5DA, 0x906F, 0xDF71, 0x9070, 0xDF72, 0x9071, 0xDF73, 0x9072, 0xDF74, + 0x9073, 0xDF75, 0x9074, 0xE5E0, 0x9075, 0xD7F1, 0x9076, 0xDF76, 0x9077, 0xDF77, 0x9078, 0xDF78, 0x9079, 0xDF79, 0x907A, 0xDF7A, + 0x907B, 0xDF7B, 0x907C, 0xDF7C, 0x907D, 0xE5E1, 0x907E, 0xDF7D, 0x907F, 0xB1DC, 0x9080, 0xD1FB, 0x9081, 0xDF7E, 0x9082, 0xE5E2, + 0x9083, 0xE5E4, 0x9084, 0xDF80, 0x9085, 0xDF81, 0x9086, 0xDF82, 0x9087, 0xDF83, 0x9088, 0xE5E3, 0x9089, 0xDF84, 0x908A, 0xDF85, + 0x908B, 0xE5E5, 0x908C, 0xDF86, 0x908D, 0xDF87, 0x908E, 0xDF88, 0x908F, 0xDF89, 0x9090, 0xDF8A, 0x9091, 0xD2D8, 0x9092, 0xDF8B, + 0x9093, 0xB5CB, 0x9094, 0xDF8C, 0x9095, 0xE7DF, 0x9096, 0xDF8D, 0x9097, 0xDAF5, 0x9098, 0xDF8E, 0x9099, 0xDAF8, 0x909A, 0xDF8F, + 0x909B, 0xDAF6, 0x909C, 0xDF90, 0x909D, 0xDAF7, 0x909E, 0xDF91, 0x909F, 0xDF92, 0x90A0, 0xDF93, 0x90A1, 0xDAFA, 0x90A2, 0xD0CF, + 0x90A3, 0xC4C7, 0x90A4, 0xDF94, 0x90A5, 0xDF95, 0x90A6, 0xB0EE, 0x90A7, 0xDF96, 0x90A8, 0xDF97, 0x90A9, 0xDF98, 0x90AA, 0xD0B0, + 0x90AB, 0xDF99, 0x90AC, 0xDAF9, 0x90AD, 0xDF9A, 0x90AE, 0xD3CA, 0x90AF, 0xBAAA, 0x90B0, 0xDBA2, 0x90B1, 0xC7F1, 0x90B2, 0xDF9B, + 0x90B3, 0xDAFC, 0x90B4, 0xDAFB, 0x90B5, 0xC9DB, 0x90B6, 0xDAFD, 0x90B7, 0xDF9C, 0x90B8, 0xDBA1, 0x90B9, 0xD7DE, 0x90BA, 0xDAFE, + 0x90BB, 0xC1DA, 0x90BC, 0xDF9D, 0x90BD, 0xDF9E, 0x90BE, 0xDBA5, 0x90BF, 0xDF9F, 0x90C0, 0xDFA0, 0x90C1, 0xD3F4, 0x90C2, 0xE040, + 0x90C3, 0xE041, 0x90C4, 0xDBA7, 0x90C5, 0xDBA4, 0x90C6, 0xE042, 0x90C7, 0xDBA8, 0x90C8, 0xE043, 0x90C9, 0xE044, 0x90CA, 0xBDBC, + 0x90CB, 0xE045, 0x90CC, 0xE046, 0x90CD, 0xE047, 0x90CE, 0xC0C9, 0x90CF, 0xDBA3, 0x90D0, 0xDBA6, 0x90D1, 0xD6A3, 0x90D2, 0xE048, + 0x90D3, 0xDBA9, 0x90D4, 0xE049, 0x90D5, 0xE04A, 0x90D6, 0xE04B, 0x90D7, 0xDBAD, 0x90D8, 0xE04C, 0x90D9, 0xE04D, 0x90DA, 0xE04E, + 0x90DB, 0xDBAE, 0x90DC, 0xDBAC, 0x90DD, 0xBAC2, 0x90DE, 0xE04F, 0x90DF, 0xE050, 0x90E0, 0xE051, 0x90E1, 0xBFA4, 0x90E2, 0xDBAB, + 0x90E3, 0xE052, 0x90E4, 0xE053, 0x90E5, 0xE054, 0x90E6, 0xDBAA, 0x90E7, 0xD4C7, 0x90E8, 0xB2BF, 0x90E9, 0xE055, 0x90EA, 0xE056, + 0x90EB, 0xDBAF, 0x90EC, 0xE057, 0x90ED, 0xB9F9, 0x90EE, 0xE058, 0x90EF, 0xDBB0, 0x90F0, 0xE059, 0x90F1, 0xE05A, 0x90F2, 0xE05B, + 0x90F3, 0xE05C, 0x90F4, 0xB3BB, 0x90F5, 0xE05D, 0x90F6, 0xE05E, 0x90F7, 0xE05F, 0x90F8, 0xB5A6, 0x90F9, 0xE060, 0x90FA, 0xE061, + 0x90FB, 0xE062, 0x90FC, 0xE063, 0x90FD, 0xB6BC, 0x90FE, 0xDBB1, 0x90FF, 0xE064, 0x9100, 0xE065, 0x9101, 0xE066, 0x9102, 0xB6F5, + 0x9103, 0xE067, 0x9104, 0xDBB2, 0x9105, 0xE068, 0x9106, 0xE069, 0x9107, 0xE06A, 0x9108, 0xE06B, 0x9109, 0xE06C, 0x910A, 0xE06D, + 0x910B, 0xE06E, 0x910C, 0xE06F, 0x910D, 0xE070, 0x910E, 0xE071, 0x910F, 0xE072, 0x9110, 0xE073, 0x9111, 0xE074, 0x9112, 0xE075, + 0x9113, 0xE076, 0x9114, 0xE077, 0x9115, 0xE078, 0x9116, 0xE079, 0x9117, 0xE07A, 0x9118, 0xE07B, 0x9119, 0xB1C9, 0x911A, 0xE07C, + 0x911B, 0xE07D, 0x911C, 0xE07E, 0x911D, 0xE080, 0x911E, 0xDBB4, 0x911F, 0xE081, 0x9120, 0xE082, 0x9121, 0xE083, 0x9122, 0xDBB3, + 0x9123, 0xDBB5, 0x9124, 0xE084, 0x9125, 0xE085, 0x9126, 0xE086, 0x9127, 0xE087, 0x9128, 0xE088, 0x9129, 0xE089, 0x912A, 0xE08A, + 0x912B, 0xE08B, 0x912C, 0xE08C, 0x912D, 0xE08D, 0x912E, 0xE08E, 0x912F, 0xDBB7, 0x9130, 0xE08F, 0x9131, 0xDBB6, 0x9132, 0xE090, + 0x9133, 0xE091, 0x9134, 0xE092, 0x9135, 0xE093, 0x9136, 0xE094, 0x9137, 0xE095, 0x9138, 0xE096, 0x9139, 0xDBB8, 0x913A, 0xE097, + 0x913B, 0xE098, 0x913C, 0xE099, 0x913D, 0xE09A, 0x913E, 0xE09B, 0x913F, 0xE09C, 0x9140, 0xE09D, 0x9141, 0xE09E, 0x9142, 0xE09F, + 0x9143, 0xDBB9, 0x9144, 0xE0A0, 0x9145, 0xE140, 0x9146, 0xDBBA, 0x9147, 0xE141, 0x9148, 0xE142, 0x9149, 0xD3CF, 0x914A, 0xF4FA, + 0x914B, 0xC7F5, 0x914C, 0xD7C3, 0x914D, 0xC5E4, 0x914E, 0xF4FC, 0x914F, 0xF4FD, 0x9150, 0xF4FB, 0x9151, 0xE143, 0x9152, 0xBEC6, + 0x9153, 0xE144, 0x9154, 0xE145, 0x9155, 0xE146, 0x9156, 0xE147, 0x9157, 0xD0EF, 0x9158, 0xE148, 0x9159, 0xE149, 0x915A, 0xB7D3, + 0x915B, 0xE14A, 0x915C, 0xE14B, 0x915D, 0xD4CD, 0x915E, 0xCCAA, 0x915F, 0xE14C, 0x9160, 0xE14D, 0x9161, 0xF5A2, 0x9162, 0xF5A1, + 0x9163, 0xBAA8, 0x9164, 0xF4FE, 0x9165, 0xCBD6, 0x9166, 0xE14E, 0x9167, 0xE14F, 0x9168, 0xE150, 0x9169, 0xF5A4, 0x916A, 0xC0D2, + 0x916B, 0xE151, 0x916C, 0xB3EA, 0x916D, 0xE152, 0x916E, 0xCDAA, 0x916F, 0xF5A5, 0x9170, 0xF5A3, 0x9171, 0xBDB4, 0x9172, 0xF5A8, + 0x9173, 0xE153, 0x9174, 0xF5A9, 0x9175, 0xBDCD, 0x9176, 0xC3B8, 0x9177, 0xBFE1, 0x9178, 0xCBE1, 0x9179, 0xF5AA, 0x917A, 0xE154, + 0x917B, 0xE155, 0x917C, 0xE156, 0x917D, 0xF5A6, 0x917E, 0xF5A7, 0x917F, 0xC4F0, 0x9180, 0xE157, 0x9181, 0xE158, 0x9182, 0xE159, + 0x9183, 0xE15A, 0x9184, 0xE15B, 0x9185, 0xF5AC, 0x9186, 0xE15C, 0x9187, 0xB4BC, 0x9188, 0xE15D, 0x9189, 0xD7ED, 0x918A, 0xE15E, + 0x918B, 0xB4D7, 0x918C, 0xF5AB, 0x918D, 0xF5AE, 0x918E, 0xE15F, 0x918F, 0xE160, 0x9190, 0xF5AD, 0x9191, 0xF5AF, 0x9192, 0xD0D1, + 0x9193, 0xE161, 0x9194, 0xE162, 0x9195, 0xE163, 0x9196, 0xE164, 0x9197, 0xE165, 0x9198, 0xE166, 0x9199, 0xE167, 0x919A, 0xC3D1, + 0x919B, 0xC8A9, 0x919C, 0xE168, 0x919D, 0xE169, 0x919E, 0xE16A, 0x919F, 0xE16B, 0x91A0, 0xE16C, 0x91A1, 0xE16D, 0x91A2, 0xF5B0, + 0x91A3, 0xF5B1, 0x91A4, 0xE16E, 0x91A5, 0xE16F, 0x91A6, 0xE170, 0x91A7, 0xE171, 0x91A8, 0xE172, 0x91A9, 0xE173, 0x91AA, 0xF5B2, + 0x91AB, 0xE174, 0x91AC, 0xE175, 0x91AD, 0xF5B3, 0x91AE, 0xF5B4, 0x91AF, 0xF5B5, 0x91B0, 0xE176, 0x91B1, 0xE177, 0x91B2, 0xE178, + 0x91B3, 0xE179, 0x91B4, 0xF5B7, 0x91B5, 0xF5B6, 0x91B6, 0xE17A, 0x91B7, 0xE17B, 0x91B8, 0xE17C, 0x91B9, 0xE17D, 0x91BA, 0xF5B8, + 0x91BB, 0xE17E, 0x91BC, 0xE180, 0x91BD, 0xE181, 0x91BE, 0xE182, 0x91BF, 0xE183, 0x91C0, 0xE184, 0x91C1, 0xE185, 0x91C2, 0xE186, + 0x91C3, 0xE187, 0x91C4, 0xE188, 0x91C5, 0xE189, 0x91C6, 0xE18A, 0x91C7, 0xB2C9, 0x91C8, 0xE18B, 0x91C9, 0xD3D4, 0x91CA, 0xCACD, + 0x91CB, 0xE18C, 0x91CC, 0xC0EF, 0x91CD, 0xD6D8, 0x91CE, 0xD2B0, 0x91CF, 0xC1BF, 0x91D0, 0xE18D, 0x91D1, 0xBDF0, 0x91D2, 0xE18E, + 0x91D3, 0xE18F, 0x91D4, 0xE190, 0x91D5, 0xE191, 0x91D6, 0xE192, 0x91D7, 0xE193, 0x91D8, 0xE194, 0x91D9, 0xE195, 0x91DA, 0xE196, + 0x91DB, 0xE197, 0x91DC, 0xB8AA, 0x91DD, 0xE198, 0x91DE, 0xE199, 0x91DF, 0xE19A, 0x91E0, 0xE19B, 0x91E1, 0xE19C, 0x91E2, 0xE19D, + 0x91E3, 0xE19E, 0x91E4, 0xE19F, 0x91E5, 0xE1A0, 0x91E6, 0xE240, 0x91E7, 0xE241, 0x91E8, 0xE242, 0x91E9, 0xE243, 0x91EA, 0xE244, + 0x91EB, 0xE245, 0x91EC, 0xE246, 0x91ED, 0xE247, 0x91EE, 0xE248, 0x91EF, 0xE249, 0x91F0, 0xE24A, 0x91F1, 0xE24B, 0x91F2, 0xE24C, + 0x91F3, 0xE24D, 0x91F4, 0xE24E, 0x91F5, 0xE24F, 0x91F6, 0xE250, 0x91F7, 0xE251, 0x91F8, 0xE252, 0x91F9, 0xE253, 0x91FA, 0xE254, + 0x91FB, 0xE255, 0x91FC, 0xE256, 0x91FD, 0xE257, 0x91FE, 0xE258, 0x91FF, 0xE259, 0x9200, 0xE25A, 0x9201, 0xE25B, 0x9202, 0xE25C, + 0x9203, 0xE25D, 0x9204, 0xE25E, 0x9205, 0xE25F, 0x9206, 0xE260, 0x9207, 0xE261, 0x9208, 0xE262, 0x9209, 0xE263, 0x920A, 0xE264, + 0x920B, 0xE265, 0x920C, 0xE266, 0x920D, 0xE267, 0x920E, 0xE268, 0x920F, 0xE269, 0x9210, 0xE26A, 0x9211, 0xE26B, 0x9212, 0xE26C, + 0x9213, 0xE26D, 0x9214, 0xE26E, 0x9215, 0xE26F, 0x9216, 0xE270, 0x9217, 0xE271, 0x9218, 0xE272, 0x9219, 0xE273, 0x921A, 0xE274, + 0x921B, 0xE275, 0x921C, 0xE276, 0x921D, 0xE277, 0x921E, 0xE278, 0x921F, 0xE279, 0x9220, 0xE27A, 0x9221, 0xE27B, 0x9222, 0xE27C, + 0x9223, 0xE27D, 0x9224, 0xE27E, 0x9225, 0xE280, 0x9226, 0xE281, 0x9227, 0xE282, 0x9228, 0xE283, 0x9229, 0xE284, 0x922A, 0xE285, + 0x922B, 0xE286, 0x922C, 0xE287, 0x922D, 0xE288, 0x922E, 0xE289, 0x922F, 0xE28A, 0x9230, 0xE28B, 0x9231, 0xE28C, 0x9232, 0xE28D, + 0x9233, 0xE28E, 0x9234, 0xE28F, 0x9235, 0xE290, 0x9236, 0xE291, 0x9237, 0xE292, 0x9238, 0xE293, 0x9239, 0xE294, 0x923A, 0xE295, + 0x923B, 0xE296, 0x923C, 0xE297, 0x923D, 0xE298, 0x923E, 0xE299, 0x923F, 0xE29A, 0x9240, 0xE29B, 0x9241, 0xE29C, 0x9242, 0xE29D, + 0x9243, 0xE29E, 0x9244, 0xE29F, 0x9245, 0xE2A0, 0x9246, 0xE340, 0x9247, 0xE341, 0x9248, 0xE342, 0x9249, 0xE343, 0x924A, 0xE344, + 0x924B, 0xE345, 0x924C, 0xE346, 0x924D, 0xE347, 0x924E, 0xE348, 0x924F, 0xE349, 0x9250, 0xE34A, 0x9251, 0xE34B, 0x9252, 0xE34C, + 0x9253, 0xE34D, 0x9254, 0xE34E, 0x9255, 0xE34F, 0x9256, 0xE350, 0x9257, 0xE351, 0x9258, 0xE352, 0x9259, 0xE353, 0x925A, 0xE354, + 0x925B, 0xE355, 0x925C, 0xE356, 0x925D, 0xE357, 0x925E, 0xE358, 0x925F, 0xE359, 0x9260, 0xE35A, 0x9261, 0xE35B, 0x9262, 0xE35C, + 0x9263, 0xE35D, 0x9264, 0xE35E, 0x9265, 0xE35F, 0x9266, 0xE360, 0x9267, 0xE361, 0x9268, 0xE362, 0x9269, 0xE363, 0x926A, 0xE364, + 0x926B, 0xE365, 0x926C, 0xE366, 0x926D, 0xE367, 0x926E, 0xE368, 0x926F, 0xE369, 0x9270, 0xE36A, 0x9271, 0xE36B, 0x9272, 0xE36C, + 0x9273, 0xE36D, 0x9274, 0xBCF8, 0x9275, 0xE36E, 0x9276, 0xE36F, 0x9277, 0xE370, 0x9278, 0xE371, 0x9279, 0xE372, 0x927A, 0xE373, + 0x927B, 0xE374, 0x927C, 0xE375, 0x927D, 0xE376, 0x927E, 0xE377, 0x927F, 0xE378, 0x9280, 0xE379, 0x9281, 0xE37A, 0x9282, 0xE37B, + 0x9283, 0xE37C, 0x9284, 0xE37D, 0x9285, 0xE37E, 0x9286, 0xE380, 0x9287, 0xE381, 0x9288, 0xE382, 0x9289, 0xE383, 0x928A, 0xE384, + 0x928B, 0xE385, 0x928C, 0xE386, 0x928D, 0xE387, 0x928E, 0xF6C6, 0x928F, 0xE388, 0x9290, 0xE389, 0x9291, 0xE38A, 0x9292, 0xE38B, + 0x9293, 0xE38C, 0x9294, 0xE38D, 0x9295, 0xE38E, 0x9296, 0xE38F, 0x9297, 0xE390, 0x9298, 0xE391, 0x9299, 0xE392, 0x929A, 0xE393, + 0x929B, 0xE394, 0x929C, 0xE395, 0x929D, 0xE396, 0x929E, 0xE397, 0x929F, 0xE398, 0x92A0, 0xE399, 0x92A1, 0xE39A, 0x92A2, 0xE39B, + 0x92A3, 0xE39C, 0x92A4, 0xE39D, 0x92A5, 0xE39E, 0x92A6, 0xE39F, 0x92A7, 0xE3A0, 0x92A8, 0xE440, 0x92A9, 0xE441, 0x92AA, 0xE442, + 0x92AB, 0xE443, 0x92AC, 0xE444, 0x92AD, 0xE445, 0x92AE, 0xF6C7, 0x92AF, 0xE446, 0x92B0, 0xE447, 0x92B1, 0xE448, 0x92B2, 0xE449, + 0x92B3, 0xE44A, 0x92B4, 0xE44B, 0x92B5, 0xE44C, 0x92B6, 0xE44D, 0x92B7, 0xE44E, 0x92B8, 0xE44F, 0x92B9, 0xE450, 0x92BA, 0xE451, + 0x92BB, 0xE452, 0x92BC, 0xE453, 0x92BD, 0xE454, 0x92BE, 0xE455, 0x92BF, 0xE456, 0x92C0, 0xE457, 0x92C1, 0xE458, 0x92C2, 0xE459, + 0x92C3, 0xE45A, 0x92C4, 0xE45B, 0x92C5, 0xE45C, 0x92C6, 0xE45D, 0x92C7, 0xE45E, 0x92C8, 0xF6C8, 0x92C9, 0xE45F, 0x92CA, 0xE460, + 0x92CB, 0xE461, 0x92CC, 0xE462, 0x92CD, 0xE463, 0x92CE, 0xE464, 0x92CF, 0xE465, 0x92D0, 0xE466, 0x92D1, 0xE467, 0x92D2, 0xE468, + 0x92D3, 0xE469, 0x92D4, 0xE46A, 0x92D5, 0xE46B, 0x92D6, 0xE46C, 0x92D7, 0xE46D, 0x92D8, 0xE46E, 0x92D9, 0xE46F, 0x92DA, 0xE470, + 0x92DB, 0xE471, 0x92DC, 0xE472, 0x92DD, 0xE473, 0x92DE, 0xE474, 0x92DF, 0xE475, 0x92E0, 0xE476, 0x92E1, 0xE477, 0x92E2, 0xE478, + 0x92E3, 0xE479, 0x92E4, 0xE47A, 0x92E5, 0xE47B, 0x92E6, 0xE47C, 0x92E7, 0xE47D, 0x92E8, 0xE47E, 0x92E9, 0xE480, 0x92EA, 0xE481, + 0x92EB, 0xE482, 0x92EC, 0xE483, 0x92ED, 0xE484, 0x92EE, 0xE485, 0x92EF, 0xE486, 0x92F0, 0xE487, 0x92F1, 0xE488, 0x92F2, 0xE489, + 0x92F3, 0xE48A, 0x92F4, 0xE48B, 0x92F5, 0xE48C, 0x92F6, 0xE48D, 0x92F7, 0xE48E, 0x92F8, 0xE48F, 0x92F9, 0xE490, 0x92FA, 0xE491, + 0x92FB, 0xE492, 0x92FC, 0xE493, 0x92FD, 0xE494, 0x92FE, 0xE495, 0x92FF, 0xE496, 0x9300, 0xE497, 0x9301, 0xE498, 0x9302, 0xE499, + 0x9303, 0xE49A, 0x9304, 0xE49B, 0x9305, 0xE49C, 0x9306, 0xE49D, 0x9307, 0xE49E, 0x9308, 0xE49F, 0x9309, 0xE4A0, 0x930A, 0xE540, + 0x930B, 0xE541, 0x930C, 0xE542, 0x930D, 0xE543, 0x930E, 0xE544, 0x930F, 0xE545, 0x9310, 0xE546, 0x9311, 0xE547, 0x9312, 0xE548, + 0x9313, 0xE549, 0x9314, 0xE54A, 0x9315, 0xE54B, 0x9316, 0xE54C, 0x9317, 0xE54D, 0x9318, 0xE54E, 0x9319, 0xE54F, 0x931A, 0xE550, + 0x931B, 0xE551, 0x931C, 0xE552, 0x931D, 0xE553, 0x931E, 0xE554, 0x931F, 0xE555, 0x9320, 0xE556, 0x9321, 0xE557, 0x9322, 0xE558, + 0x9323, 0xE559, 0x9324, 0xE55A, 0x9325, 0xE55B, 0x9326, 0xE55C, 0x9327, 0xE55D, 0x9328, 0xE55E, 0x9329, 0xE55F, 0x932A, 0xE560, + 0x932B, 0xE561, 0x932C, 0xE562, 0x932D, 0xE563, 0x932E, 0xE564, 0x932F, 0xE565, 0x9330, 0xE566, 0x9331, 0xE567, 0x9332, 0xE568, + 0x9333, 0xE569, 0x9334, 0xE56A, 0x9335, 0xE56B, 0x9336, 0xE56C, 0x9337, 0xE56D, 0x9338, 0xE56E, 0x9339, 0xE56F, 0x933A, 0xE570, + 0x933B, 0xE571, 0x933C, 0xE572, 0x933D, 0xE573, 0x933E, 0xF6C9, 0x933F, 0xE574, 0x9340, 0xE575, 0x9341, 0xE576, 0x9342, 0xE577, + 0x9343, 0xE578, 0x9344, 0xE579, 0x9345, 0xE57A, 0x9346, 0xE57B, 0x9347, 0xE57C, 0x9348, 0xE57D, 0x9349, 0xE57E, 0x934A, 0xE580, + 0x934B, 0xE581, 0x934C, 0xE582, 0x934D, 0xE583, 0x934E, 0xE584, 0x934F, 0xE585, 0x9350, 0xE586, 0x9351, 0xE587, 0x9352, 0xE588, + 0x9353, 0xE589, 0x9354, 0xE58A, 0x9355, 0xE58B, 0x9356, 0xE58C, 0x9357, 0xE58D, 0x9358, 0xE58E, 0x9359, 0xE58F, 0x935A, 0xE590, + 0x935B, 0xE591, 0x935C, 0xE592, 0x935D, 0xE593, 0x935E, 0xE594, 0x935F, 0xE595, 0x9360, 0xE596, 0x9361, 0xE597, 0x9362, 0xE598, + 0x9363, 0xE599, 0x9364, 0xE59A, 0x9365, 0xE59B, 0x9366, 0xE59C, 0x9367, 0xE59D, 0x9368, 0xE59E, 0x9369, 0xE59F, 0x936A, 0xF6CA, + 0x936B, 0xE5A0, 0x936C, 0xE640, 0x936D, 0xE641, 0x936E, 0xE642, 0x936F, 0xE643, 0x9370, 0xE644, 0x9371, 0xE645, 0x9372, 0xE646, + 0x9373, 0xE647, 0x9374, 0xE648, 0x9375, 0xE649, 0x9376, 0xE64A, 0x9377, 0xE64B, 0x9378, 0xE64C, 0x9379, 0xE64D, 0x937A, 0xE64E, + 0x937B, 0xE64F, 0x937C, 0xE650, 0x937D, 0xE651, 0x937E, 0xE652, 0x937F, 0xE653, 0x9380, 0xE654, 0x9381, 0xE655, 0x9382, 0xE656, + 0x9383, 0xE657, 0x9384, 0xE658, 0x9385, 0xE659, 0x9386, 0xE65A, 0x9387, 0xE65B, 0x9388, 0xE65C, 0x9389, 0xE65D, 0x938A, 0xE65E, + 0x938B, 0xE65F, 0x938C, 0xE660, 0x938D, 0xE661, 0x938E, 0xE662, 0x938F, 0xF6CC, 0x9390, 0xE663, 0x9391, 0xE664, 0x9392, 0xE665, + 0x9393, 0xE666, 0x9394, 0xE667, 0x9395, 0xE668, 0x9396, 0xE669, 0x9397, 0xE66A, 0x9398, 0xE66B, 0x9399, 0xE66C, 0x939A, 0xE66D, + 0x939B, 0xE66E, 0x939C, 0xE66F, 0x939D, 0xE670, 0x939E, 0xE671, 0x939F, 0xE672, 0x93A0, 0xE673, 0x93A1, 0xE674, 0x93A2, 0xE675, + 0x93A3, 0xE676, 0x93A4, 0xE677, 0x93A5, 0xE678, 0x93A6, 0xE679, 0x93A7, 0xE67A, 0x93A8, 0xE67B, 0x93A9, 0xE67C, 0x93AA, 0xE67D, + 0x93AB, 0xE67E, 0x93AC, 0xE680, 0x93AD, 0xE681, 0x93AE, 0xE682, 0x93AF, 0xE683, 0x93B0, 0xE684, 0x93B1, 0xE685, 0x93B2, 0xE686, + 0x93B3, 0xE687, 0x93B4, 0xE688, 0x93B5, 0xE689, 0x93B6, 0xE68A, 0x93B7, 0xE68B, 0x93B8, 0xE68C, 0x93B9, 0xE68D, 0x93BA, 0xE68E, + 0x93BB, 0xE68F, 0x93BC, 0xE690, 0x93BD, 0xE691, 0x93BE, 0xE692, 0x93BF, 0xE693, 0x93C0, 0xE694, 0x93C1, 0xE695, 0x93C2, 0xE696, + 0x93C3, 0xE697, 0x93C4, 0xE698, 0x93C5, 0xE699, 0x93C6, 0xE69A, 0x93C7, 0xE69B, 0x93C8, 0xE69C, 0x93C9, 0xE69D, 0x93CA, 0xF6CB, + 0x93CB, 0xE69E, 0x93CC, 0xE69F, 0x93CD, 0xE6A0, 0x93CE, 0xE740, 0x93CF, 0xE741, 0x93D0, 0xE742, 0x93D1, 0xE743, 0x93D2, 0xE744, + 0x93D3, 0xE745, 0x93D4, 0xE746, 0x93D5, 0xE747, 0x93D6, 0xF7E9, 0x93D7, 0xE748, 0x93D8, 0xE749, 0x93D9, 0xE74A, 0x93DA, 0xE74B, + 0x93DB, 0xE74C, 0x93DC, 0xE74D, 0x93DD, 0xE74E, 0x93DE, 0xE74F, 0x93DF, 0xE750, 0x93E0, 0xE751, 0x93E1, 0xE752, 0x93E2, 0xE753, + 0x93E3, 0xE754, 0x93E4, 0xE755, 0x93E5, 0xE756, 0x93E6, 0xE757, 0x93E7, 0xE758, 0x93E8, 0xE759, 0x93E9, 0xE75A, 0x93EA, 0xE75B, + 0x93EB, 0xE75C, 0x93EC, 0xE75D, 0x93ED, 0xE75E, 0x93EE, 0xE75F, 0x93EF, 0xE760, 0x93F0, 0xE761, 0x93F1, 0xE762, 0x93F2, 0xE763, + 0x93F3, 0xE764, 0x93F4, 0xE765, 0x93F5, 0xE766, 0x93F6, 0xE767, 0x93F7, 0xE768, 0x93F8, 0xE769, 0x93F9, 0xE76A, 0x93FA, 0xE76B, + 0x93FB, 0xE76C, 0x93FC, 0xE76D, 0x93FD, 0xE76E, 0x93FE, 0xE76F, 0x93FF, 0xE770, 0x9400, 0xE771, 0x9401, 0xE772, 0x9402, 0xE773, + 0x9403, 0xE774, 0x9404, 0xE775, 0x9405, 0xE776, 0x9406, 0xE777, 0x9407, 0xE778, 0x9408, 0xE779, 0x9409, 0xE77A, 0x940A, 0xE77B, + 0x940B, 0xE77C, 0x940C, 0xE77D, 0x940D, 0xE77E, 0x940E, 0xE780, 0x940F, 0xE781, 0x9410, 0xE782, 0x9411, 0xE783, 0x9412, 0xE784, + 0x9413, 0xE785, 0x9414, 0xE786, 0x9415, 0xE787, 0x9416, 0xE788, 0x9417, 0xE789, 0x9418, 0xE78A, 0x9419, 0xE78B, 0x941A, 0xE78C, + 0x941B, 0xE78D, 0x941C, 0xE78E, 0x941D, 0xE78F, 0x941E, 0xE790, 0x941F, 0xE791, 0x9420, 0xE792, 0x9421, 0xE793, 0x9422, 0xE794, + 0x9423, 0xE795, 0x9424, 0xE796, 0x9425, 0xE797, 0x9426, 0xE798, 0x9427, 0xE799, 0x9428, 0xE79A, 0x9429, 0xE79B, 0x942A, 0xE79C, + 0x942B, 0xE79D, 0x942C, 0xE79E, 0x942D, 0xE79F, 0x942E, 0xE7A0, 0x942F, 0xE840, 0x9430, 0xE841, 0x9431, 0xE842, 0x9432, 0xE843, + 0x9433, 0xE844, 0x9434, 0xE845, 0x9435, 0xE846, 0x9436, 0xE847, 0x9437, 0xE848, 0x9438, 0xE849, 0x9439, 0xE84A, 0x943A, 0xE84B, + 0x943B, 0xE84C, 0x943C, 0xE84D, 0x943D, 0xE84E, 0x943E, 0xF6CD, 0x943F, 0xE84F, 0x9440, 0xE850, 0x9441, 0xE851, 0x9442, 0xE852, + 0x9443, 0xE853, 0x9444, 0xE854, 0x9445, 0xE855, 0x9446, 0xE856, 0x9447, 0xE857, 0x9448, 0xE858, 0x9449, 0xE859, 0x944A, 0xE85A, + 0x944B, 0xE85B, 0x944C, 0xE85C, 0x944D, 0xE85D, 0x944E, 0xE85E, 0x944F, 0xE85F, 0x9450, 0xE860, 0x9451, 0xE861, 0x9452, 0xE862, + 0x9453, 0xE863, 0x9454, 0xE864, 0x9455, 0xE865, 0x9456, 0xE866, 0x9457, 0xE867, 0x9458, 0xE868, 0x9459, 0xE869, 0x945A, 0xE86A, + 0x945B, 0xE86B, 0x945C, 0xE86C, 0x945D, 0xE86D, 0x945E, 0xE86E, 0x945F, 0xE86F, 0x9460, 0xE870, 0x9461, 0xE871, 0x9462, 0xE872, + 0x9463, 0xE873, 0x9464, 0xE874, 0x9465, 0xE875, 0x9466, 0xE876, 0x9467, 0xE877, 0x9468, 0xE878, 0x9469, 0xE879, 0x946A, 0xE87A, + 0x946B, 0xF6CE, 0x946C, 0xE87B, 0x946D, 0xE87C, 0x946E, 0xE87D, 0x946F, 0xE87E, 0x9470, 0xE880, 0x9471, 0xE881, 0x9472, 0xE882, + 0x9473, 0xE883, 0x9474, 0xE884, 0x9475, 0xE885, 0x9476, 0xE886, 0x9477, 0xE887, 0x9478, 0xE888, 0x9479, 0xE889, 0x947A, 0xE88A, + 0x947B, 0xE88B, 0x947C, 0xE88C, 0x947D, 0xE88D, 0x947E, 0xE88E, 0x947F, 0xE88F, 0x9480, 0xE890, 0x9481, 0xE891, 0x9482, 0xE892, + 0x9483, 0xE893, 0x9484, 0xE894, 0x9485, 0xEEC4, 0x9486, 0xEEC5, 0x9487, 0xEEC6, 0x9488, 0xD5EB, 0x9489, 0xB6A4, 0x948A, 0xEEC8, + 0x948B, 0xEEC7, 0x948C, 0xEEC9, 0x948D, 0xEECA, 0x948E, 0xC7A5, 0x948F, 0xEECB, 0x9490, 0xEECC, 0x9491, 0xE895, 0x9492, 0xB7B0, + 0x9493, 0xB5F6, 0x9494, 0xEECD, 0x9495, 0xEECF, 0x9496, 0xE896, 0x9497, 0xEECE, 0x9498, 0xE897, 0x9499, 0xB8C6, 0x949A, 0xEED0, + 0x949B, 0xEED1, 0x949C, 0xEED2, 0x949D, 0xB6DB, 0x949E, 0xB3AE, 0x949F, 0xD6D3, 0x94A0, 0xC4C6, 0x94A1, 0xB1B5, 0x94A2, 0xB8D6, + 0x94A3, 0xEED3, 0x94A4, 0xEED4, 0x94A5, 0xD4BF, 0x94A6, 0xC7D5, 0x94A7, 0xBEFB, 0x94A8, 0xCED9, 0x94A9, 0xB9B3, 0x94AA, 0xEED6, + 0x94AB, 0xEED5, 0x94AC, 0xEED8, 0x94AD, 0xEED7, 0x94AE, 0xC5A5, 0x94AF, 0xEED9, 0x94B0, 0xEEDA, 0x94B1, 0xC7AE, 0x94B2, 0xEEDB, + 0x94B3, 0xC7AF, 0x94B4, 0xEEDC, 0x94B5, 0xB2A7, 0x94B6, 0xEEDD, 0x94B7, 0xEEDE, 0x94B8, 0xEEDF, 0x94B9, 0xEEE0, 0x94BA, 0xEEE1, + 0x94BB, 0xD7EA, 0x94BC, 0xEEE2, 0x94BD, 0xEEE3, 0x94BE, 0xBCD8, 0x94BF, 0xEEE4, 0x94C0, 0xD3CB, 0x94C1, 0xCCFA, 0x94C2, 0xB2AC, + 0x94C3, 0xC1E5, 0x94C4, 0xEEE5, 0x94C5, 0xC7A6, 0x94C6, 0xC3AD, 0x94C7, 0xE898, 0x94C8, 0xEEE6, 0x94C9, 0xEEE7, 0x94CA, 0xEEE8, + 0x94CB, 0xEEE9, 0x94CC, 0xEEEA, 0x94CD, 0xEEEB, 0x94CE, 0xEEEC, 0x94CF, 0xE899, 0x94D0, 0xEEED, 0x94D1, 0xEEEE, 0x94D2, 0xEEEF, + 0x94D3, 0xE89A, 0x94D4, 0xE89B, 0x94D5, 0xEEF0, 0x94D6, 0xEEF1, 0x94D7, 0xEEF2, 0x94D8, 0xEEF4, 0x94D9, 0xEEF3, 0x94DA, 0xE89C, + 0x94DB, 0xEEF5, 0x94DC, 0xCDAD, 0x94DD, 0xC2C1, 0x94DE, 0xEEF6, 0x94DF, 0xEEF7, 0x94E0, 0xEEF8, 0x94E1, 0xD5A1, 0x94E2, 0xEEF9, + 0x94E3, 0xCFB3, 0x94E4, 0xEEFA, 0x94E5, 0xEEFB, 0x94E6, 0xE89D, 0x94E7, 0xEEFC, 0x94E8, 0xEEFD, 0x94E9, 0xEFA1, 0x94EA, 0xEEFE, + 0x94EB, 0xEFA2, 0x94EC, 0xB8F5, 0x94ED, 0xC3FA, 0x94EE, 0xEFA3, 0x94EF, 0xEFA4, 0x94F0, 0xBDC2, 0x94F1, 0xD2BF, 0x94F2, 0xB2F9, + 0x94F3, 0xEFA5, 0x94F4, 0xEFA6, 0x94F5, 0xEFA7, 0x94F6, 0xD2F8, 0x94F7, 0xEFA8, 0x94F8, 0xD6FD, 0x94F9, 0xEFA9, 0x94FA, 0xC6CC, + 0x94FB, 0xE89E, 0x94FC, 0xEFAA, 0x94FD, 0xEFAB, 0x94FE, 0xC1B4, 0x94FF, 0xEFAC, 0x9500, 0xCFFA, 0x9501, 0xCBF8, 0x9502, 0xEFAE, + 0x9503, 0xEFAD, 0x9504, 0xB3FA, 0x9505, 0xB9F8, 0x9506, 0xEFAF, 0x9507, 0xEFB0, 0x9508, 0xD0E2, 0x9509, 0xEFB1, 0x950A, 0xEFB2, + 0x950B, 0xB7E6, 0x950C, 0xD0BF, 0x950D, 0xEFB3, 0x950E, 0xEFB4, 0x950F, 0xEFB5, 0x9510, 0xC8F1, 0x9511, 0xCCE0, 0x9512, 0xEFB6, + 0x9513, 0xEFB7, 0x9514, 0xEFB8, 0x9515, 0xEFB9, 0x9516, 0xEFBA, 0x9517, 0xD5E0, 0x9518, 0xEFBB, 0x9519, 0xB4ED, 0x951A, 0xC3AA, + 0x951B, 0xEFBC, 0x951C, 0xE89F, 0x951D, 0xEFBD, 0x951E, 0xEFBE, 0x951F, 0xEFBF, 0x9520, 0xE8A0, 0x9521, 0xCEFD, 0x9522, 0xEFC0, + 0x9523, 0xC2E0, 0x9524, 0xB4B8, 0x9525, 0xD7B6, 0x9526, 0xBDF5, 0x9527, 0xE940, 0x9528, 0xCFC7, 0x9529, 0xEFC3, 0x952A, 0xEFC1, + 0x952B, 0xEFC2, 0x952C, 0xEFC4, 0x952D, 0xB6A7, 0x952E, 0xBCFC, 0x952F, 0xBEE2, 0x9530, 0xC3CC, 0x9531, 0xEFC5, 0x9532, 0xEFC6, + 0x9533, 0xE941, 0x9534, 0xEFC7, 0x9535, 0xEFCF, 0x9536, 0xEFC8, 0x9537, 0xEFC9, 0x9538, 0xEFCA, 0x9539, 0xC7C2, 0x953A, 0xEFF1, + 0x953B, 0xB6CD, 0x953C, 0xEFCB, 0x953D, 0xE942, 0x953E, 0xEFCC, 0x953F, 0xEFCD, 0x9540, 0xB6C6, 0x9541, 0xC3BE, 0x9542, 0xEFCE, + 0x9543, 0xE943, 0x9544, 0xEFD0, 0x9545, 0xEFD1, 0x9546, 0xEFD2, 0x9547, 0xD5F2, 0x9548, 0xE944, 0x9549, 0xEFD3, 0x954A, 0xC4F7, + 0x954B, 0xE945, 0x954C, 0xEFD4, 0x954D, 0xC4F8, 0x954E, 0xEFD5, 0x954F, 0xEFD6, 0x9550, 0xB8E4, 0x9551, 0xB0F7, 0x9552, 0xEFD7, + 0x9553, 0xEFD8, 0x9554, 0xEFD9, 0x9555, 0xE946, 0x9556, 0xEFDA, 0x9557, 0xEFDB, 0x9558, 0xEFDC, 0x9559, 0xEFDD, 0x955A, 0xE947, + 0x955B, 0xEFDE, 0x955C, 0xBEB5, 0x955D, 0xEFE1, 0x955E, 0xEFDF, 0x955F, 0xEFE0, 0x9560, 0xE948, 0x9561, 0xEFE2, 0x9562, 0xEFE3, + 0x9563, 0xC1CD, 0x9564, 0xEFE4, 0x9565, 0xEFE5, 0x9566, 0xEFE6, 0x9567, 0xEFE7, 0x9568, 0xEFE8, 0x9569, 0xEFE9, 0x956A, 0xEFEA, + 0x956B, 0xEFEB, 0x956C, 0xEFEC, 0x956D, 0xC0D8, 0x956E, 0xE949, 0x956F, 0xEFED, 0x9570, 0xC1AD, 0x9571, 0xEFEE, 0x9572, 0xEFEF, + 0x9573, 0xEFF0, 0x9574, 0xE94A, 0x9575, 0xE94B, 0x9576, 0xCFE2, 0x9577, 0xE94C, 0x9578, 0xE94D, 0x9579, 0xE94E, 0x957A, 0xE94F, + 0x957B, 0xE950, 0x957C, 0xE951, 0x957D, 0xE952, 0x957E, 0xE953, 0x957F, 0xB3A4, 0x9580, 0xE954, 0x9581, 0xE955, 0x9582, 0xE956, + 0x9583, 0xE957, 0x9584, 0xE958, 0x9585, 0xE959, 0x9586, 0xE95A, 0x9587, 0xE95B, 0x9588, 0xE95C, 0x9589, 0xE95D, 0x958A, 0xE95E, + 0x958B, 0xE95F, 0x958C, 0xE960, 0x958D, 0xE961, 0x958E, 0xE962, 0x958F, 0xE963, 0x9590, 0xE964, 0x9591, 0xE965, 0x9592, 0xE966, + 0x9593, 0xE967, 0x9594, 0xE968, 0x9595, 0xE969, 0x9596, 0xE96A, 0x9597, 0xE96B, 0x9598, 0xE96C, 0x9599, 0xE96D, 0x959A, 0xE96E, + 0x959B, 0xE96F, 0x959C, 0xE970, 0x959D, 0xE971, 0x959E, 0xE972, 0x959F, 0xE973, 0x95A0, 0xE974, 0x95A1, 0xE975, 0x95A2, 0xE976, + 0x95A3, 0xE977, 0x95A4, 0xE978, 0x95A5, 0xE979, 0x95A6, 0xE97A, 0x95A7, 0xE97B, 0x95A8, 0xE97C, 0x95A9, 0xE97D, 0x95AA, 0xE97E, + 0x95AB, 0xE980, 0x95AC, 0xE981, 0x95AD, 0xE982, 0x95AE, 0xE983, 0x95AF, 0xE984, 0x95B0, 0xE985, 0x95B1, 0xE986, 0x95B2, 0xE987, + 0x95B3, 0xE988, 0x95B4, 0xE989, 0x95B5, 0xE98A, 0x95B6, 0xE98B, 0x95B7, 0xE98C, 0x95B8, 0xE98D, 0x95B9, 0xE98E, 0x95BA, 0xE98F, + 0x95BB, 0xE990, 0x95BC, 0xE991, 0x95BD, 0xE992, 0x95BE, 0xE993, 0x95BF, 0xE994, 0x95C0, 0xE995, 0x95C1, 0xE996, 0x95C2, 0xE997, + 0x95C3, 0xE998, 0x95C4, 0xE999, 0x95C5, 0xE99A, 0x95C6, 0xE99B, 0x95C7, 0xE99C, 0x95C8, 0xE99D, 0x95C9, 0xE99E, 0x95CA, 0xE99F, + 0x95CB, 0xE9A0, 0x95CC, 0xEA40, 0x95CD, 0xEA41, 0x95CE, 0xEA42, 0x95CF, 0xEA43, 0x95D0, 0xEA44, 0x95D1, 0xEA45, 0x95D2, 0xEA46, + 0x95D3, 0xEA47, 0x95D4, 0xEA48, 0x95D5, 0xEA49, 0x95D6, 0xEA4A, 0x95D7, 0xEA4B, 0x95D8, 0xEA4C, 0x95D9, 0xEA4D, 0x95DA, 0xEA4E, + 0x95DB, 0xEA4F, 0x95DC, 0xEA50, 0x95DD, 0xEA51, 0x95DE, 0xEA52, 0x95DF, 0xEA53, 0x95E0, 0xEA54, 0x95E1, 0xEA55, 0x95E2, 0xEA56, + 0x95E3, 0xEA57, 0x95E4, 0xEA58, 0x95E5, 0xEA59, 0x95E6, 0xEA5A, 0x95E7, 0xEA5B, 0x95E8, 0xC3C5, 0x95E9, 0xE3C5, 0x95EA, 0xC9C1, + 0x95EB, 0xE3C6, 0x95EC, 0xEA5C, 0x95ED, 0xB1D5, 0x95EE, 0xCECA, 0x95EF, 0xB4B3, 0x95F0, 0xC8F2, 0x95F1, 0xE3C7, 0x95F2, 0xCFD0, + 0x95F3, 0xE3C8, 0x95F4, 0xBCE4, 0x95F5, 0xE3C9, 0x95F6, 0xE3CA, 0x95F7, 0xC3C6, 0x95F8, 0xD5A2, 0x95F9, 0xC4D6, 0x95FA, 0xB9EB, + 0x95FB, 0xCEC5, 0x95FC, 0xE3CB, 0x95FD, 0xC3F6, 0x95FE, 0xE3CC, 0x95FF, 0xEA5D, 0x9600, 0xB7A7, 0x9601, 0xB8F3, 0x9602, 0xBAD2, + 0x9603, 0xE3CD, 0x9604, 0xE3CE, 0x9605, 0xD4C4, 0x9606, 0xE3CF, 0x9607, 0xEA5E, 0x9608, 0xE3D0, 0x9609, 0xD1CB, 0x960A, 0xE3D1, + 0x960B, 0xE3D2, 0x960C, 0xE3D3, 0x960D, 0xE3D4, 0x960E, 0xD1D6, 0x960F, 0xE3D5, 0x9610, 0xB2FB, 0x9611, 0xC0BB, 0x9612, 0xE3D6, + 0x9613, 0xEA5F, 0x9614, 0xC0AB, 0x9615, 0xE3D7, 0x9616, 0xE3D8, 0x9617, 0xE3D9, 0x9618, 0xEA60, 0x9619, 0xE3DA, 0x961A, 0xE3DB, + 0x961B, 0xEA61, 0x961C, 0xB8B7, 0x961D, 0xDAE2, 0x961E, 0xEA62, 0x961F, 0xB6D3, 0x9620, 0xEA63, 0x9621, 0xDAE4, 0x9622, 0xDAE3, + 0x9623, 0xEA64, 0x9624, 0xEA65, 0x9625, 0xEA66, 0x9626, 0xEA67, 0x9627, 0xEA68, 0x9628, 0xEA69, 0x9629, 0xEA6A, 0x962A, 0xDAE6, + 0x962B, 0xEA6B, 0x962C, 0xEA6C, 0x962D, 0xEA6D, 0x962E, 0xC8EE, 0x962F, 0xEA6E, 0x9630, 0xEA6F, 0x9631, 0xDAE5, 0x9632, 0xB7C0, + 0x9633, 0xD1F4, 0x9634, 0xD2F5, 0x9635, 0xD5F3, 0x9636, 0xBDD7, 0x9637, 0xEA70, 0x9638, 0xEA71, 0x9639, 0xEA72, 0x963A, 0xEA73, + 0x963B, 0xD7E8, 0x963C, 0xDAE8, 0x963D, 0xDAE7, 0x963E, 0xEA74, 0x963F, 0xB0A2, 0x9640, 0xCDD3, 0x9641, 0xEA75, 0x9642, 0xDAE9, + 0x9643, 0xEA76, 0x9644, 0xB8BD, 0x9645, 0xBCCA, 0x9646, 0xC2BD, 0x9647, 0xC2A4, 0x9648, 0xB3C2, 0x9649, 0xDAEA, 0x964A, 0xEA77, + 0x964B, 0xC2AA, 0x964C, 0xC4B0, 0x964D, 0xBDB5, 0x964E, 0xEA78, 0x964F, 0xEA79, 0x9650, 0xCFDE, 0x9651, 0xEA7A, 0x9652, 0xEA7B, + 0x9653, 0xEA7C, 0x9654, 0xDAEB, 0x9655, 0xC9C2, 0x9656, 0xEA7D, 0x9657, 0xEA7E, 0x9658, 0xEA80, 0x9659, 0xEA81, 0x965A, 0xEA82, + 0x965B, 0xB1DD, 0x965C, 0xEA83, 0x965D, 0xEA84, 0x965E, 0xEA85, 0x965F, 0xDAEC, 0x9660, 0xEA86, 0x9661, 0xB6B8, 0x9662, 0xD4BA, + 0x9663, 0xEA87, 0x9664, 0xB3FD, 0x9665, 0xEA88, 0x9666, 0xEA89, 0x9667, 0xDAED, 0x9668, 0xD4C9, 0x9669, 0xCFD5, 0x966A, 0xC5E3, + 0x966B, 0xEA8A, 0x966C, 0xDAEE, 0x966D, 0xEA8B, 0x966E, 0xEA8C, 0x966F, 0xEA8D, 0x9670, 0xEA8E, 0x9671, 0xEA8F, 0x9672, 0xDAEF, + 0x9673, 0xEA90, 0x9674, 0xDAF0, 0x9675, 0xC1EA, 0x9676, 0xCCD5, 0x9677, 0xCFDD, 0x9678, 0xEA91, 0x9679, 0xEA92, 0x967A, 0xEA93, + 0x967B, 0xEA94, 0x967C, 0xEA95, 0x967D, 0xEA96, 0x967E, 0xEA97, 0x967F, 0xEA98, 0x9680, 0xEA99, 0x9681, 0xEA9A, 0x9682, 0xEA9B, + 0x9683, 0xEA9C, 0x9684, 0xEA9D, 0x9685, 0xD3E7, 0x9686, 0xC2A1, 0x9687, 0xEA9E, 0x9688, 0xDAF1, 0x9689, 0xEA9F, 0x968A, 0xEAA0, + 0x968B, 0xCBE5, 0x968C, 0xEB40, 0x968D, 0xDAF2, 0x968E, 0xEB41, 0x968F, 0xCBE6, 0x9690, 0xD2FE, 0x9691, 0xEB42, 0x9692, 0xEB43, + 0x9693, 0xEB44, 0x9694, 0xB8F4, 0x9695, 0xEB45, 0x9696, 0xEB46, 0x9697, 0xDAF3, 0x9698, 0xB0AF, 0x9699, 0xCFB6, 0x969A, 0xEB47, + 0x969B, 0xEB48, 0x969C, 0xD5CF, 0x969D, 0xEB49, 0x969E, 0xEB4A, 0x969F, 0xEB4B, 0x96A0, 0xEB4C, 0x96A1, 0xEB4D, 0x96A2, 0xEB4E, + 0x96A3, 0xEB4F, 0x96A4, 0xEB50, 0x96A5, 0xEB51, 0x96A6, 0xEB52, 0x96A7, 0xCBED, 0x96A8, 0xEB53, 0x96A9, 0xEB54, 0x96AA, 0xEB55, + 0x96AB, 0xEB56, 0x96AC, 0xEB57, 0x96AD, 0xEB58, 0x96AE, 0xEB59, 0x96AF, 0xEB5A, 0x96B0, 0xDAF4, 0x96B1, 0xEB5B, 0x96B2, 0xEB5C, + 0x96B3, 0xE3C4, 0x96B4, 0xEB5D, 0x96B5, 0xEB5E, 0x96B6, 0xC1A5, 0x96B7, 0xEB5F, 0x96B8, 0xEB60, 0x96B9, 0xF6BF, 0x96BA, 0xEB61, + 0x96BB, 0xEB62, 0x96BC, 0xF6C0, 0x96BD, 0xF6C1, 0x96BE, 0xC4D1, 0x96BF, 0xEB63, 0x96C0, 0xC8B8, 0x96C1, 0xD1E3, 0x96C2, 0xEB64, + 0x96C3, 0xEB65, 0x96C4, 0xD0DB, 0x96C5, 0xD1C5, 0x96C6, 0xBCAF, 0x96C7, 0xB9CD, 0x96C8, 0xEB66, 0x96C9, 0xEFF4, 0x96CA, 0xEB67, + 0x96CB, 0xEB68, 0x96CC, 0xB4C6, 0x96CD, 0xD3BA, 0x96CE, 0xF6C2, 0x96CF, 0xB3FB, 0x96D0, 0xEB69, 0x96D1, 0xEB6A, 0x96D2, 0xF6C3, + 0x96D3, 0xEB6B, 0x96D4, 0xEB6C, 0x96D5, 0xB5F1, 0x96D6, 0xEB6D, 0x96D7, 0xEB6E, 0x96D8, 0xEB6F, 0x96D9, 0xEB70, 0x96DA, 0xEB71, + 0x96DB, 0xEB72, 0x96DC, 0xEB73, 0x96DD, 0xEB74, 0x96DE, 0xEB75, 0x96DF, 0xEB76, 0x96E0, 0xF6C5, 0x96E1, 0xEB77, 0x96E2, 0xEB78, + 0x96E3, 0xEB79, 0x96E4, 0xEB7A, 0x96E5, 0xEB7B, 0x96E6, 0xEB7C, 0x96E7, 0xEB7D, 0x96E8, 0xD3EA, 0x96E9, 0xF6A7, 0x96EA, 0xD1A9, + 0x96EB, 0xEB7E, 0x96EC, 0xEB80, 0x96ED, 0xEB81, 0x96EE, 0xEB82, 0x96EF, 0xF6A9, 0x96F0, 0xEB83, 0x96F1, 0xEB84, 0x96F2, 0xEB85, + 0x96F3, 0xF6A8, 0x96F4, 0xEB86, 0x96F5, 0xEB87, 0x96F6, 0xC1E3, 0x96F7, 0xC0D7, 0x96F8, 0xEB88, 0x96F9, 0xB1A2, 0x96FA, 0xEB89, + 0x96FB, 0xEB8A, 0x96FC, 0xEB8B, 0x96FD, 0xEB8C, 0x96FE, 0xCEED, 0x96FF, 0xEB8D, 0x9700, 0xD0E8, 0x9701, 0xF6AB, 0x9702, 0xEB8E, + 0x9703, 0xEB8F, 0x9704, 0xCFF6, 0x9705, 0xEB90, 0x9706, 0xF6AA, 0x9707, 0xD5F0, 0x9708, 0xF6AC, 0x9709, 0xC3B9, 0x970A, 0xEB91, + 0x970B, 0xEB92, 0x970C, 0xEB93, 0x970D, 0xBBF4, 0x970E, 0xF6AE, 0x970F, 0xF6AD, 0x9710, 0xEB94, 0x9711, 0xEB95, 0x9712, 0xEB96, + 0x9713, 0xC4DE, 0x9714, 0xEB97, 0x9715, 0xEB98, 0x9716, 0xC1D8, 0x9717, 0xEB99, 0x9718, 0xEB9A, 0x9719, 0xEB9B, 0x971A, 0xEB9C, + 0x971B, 0xEB9D, 0x971C, 0xCBAA, 0x971D, 0xEB9E, 0x971E, 0xCFBC, 0x971F, 0xEB9F, 0x9720, 0xEBA0, 0x9721, 0xEC40, 0x9722, 0xEC41, + 0x9723, 0xEC42, 0x9724, 0xEC43, 0x9725, 0xEC44, 0x9726, 0xEC45, 0x9727, 0xEC46, 0x9728, 0xEC47, 0x9729, 0xEC48, 0x972A, 0xF6AF, + 0x972B, 0xEC49, 0x972C, 0xEC4A, 0x972D, 0xF6B0, 0x972E, 0xEC4B, 0x972F, 0xEC4C, 0x9730, 0xF6B1, 0x9731, 0xEC4D, 0x9732, 0xC2B6, + 0x9733, 0xEC4E, 0x9734, 0xEC4F, 0x9735, 0xEC50, 0x9736, 0xEC51, 0x9737, 0xEC52, 0x9738, 0xB0D4, 0x9739, 0xC5F9, 0x973A, 0xEC53, + 0x973B, 0xEC54, 0x973C, 0xEC55, 0x973D, 0xEC56, 0x973E, 0xF6B2, 0x973F, 0xEC57, 0x9740, 0xEC58, 0x9741, 0xEC59, 0x9742, 0xEC5A, + 0x9743, 0xEC5B, 0x9744, 0xEC5C, 0x9745, 0xEC5D, 0x9746, 0xEC5E, 0x9747, 0xEC5F, 0x9748, 0xEC60, 0x9749, 0xEC61, 0x974A, 0xEC62, + 0x974B, 0xEC63, 0x974C, 0xEC64, 0x974D, 0xEC65, 0x974E, 0xEC66, 0x974F, 0xEC67, 0x9750, 0xEC68, 0x9751, 0xEC69, 0x9752, 0xC7E0, + 0x9753, 0xF6A6, 0x9754, 0xEC6A, 0x9755, 0xEC6B, 0x9756, 0xBEB8, 0x9757, 0xEC6C, 0x9758, 0xEC6D, 0x9759, 0xBEB2, 0x975A, 0xEC6E, + 0x975B, 0xB5E5, 0x975C, 0xEC6F, 0x975D, 0xEC70, 0x975E, 0xB7C7, 0x975F, 0xEC71, 0x9760, 0xBFBF, 0x9761, 0xC3D2, 0x9762, 0xC3E6, + 0x9763, 0xEC72, 0x9764, 0xEC73, 0x9765, 0xD8CC, 0x9766, 0xEC74, 0x9767, 0xEC75, 0x9768, 0xEC76, 0x9769, 0xB8EF, 0x976A, 0xEC77, + 0x976B, 0xEC78, 0x976C, 0xEC79, 0x976D, 0xEC7A, 0x976E, 0xEC7B, 0x976F, 0xEC7C, 0x9770, 0xEC7D, 0x9771, 0xEC7E, 0x9772, 0xEC80, + 0x9773, 0xBDF9, 0x9774, 0xD1A5, 0x9775, 0xEC81, 0x9776, 0xB0D0, 0x9777, 0xEC82, 0x9778, 0xEC83, 0x9779, 0xEC84, 0x977A, 0xEC85, + 0x977B, 0xEC86, 0x977C, 0xF7B0, 0x977D, 0xEC87, 0x977E, 0xEC88, 0x977F, 0xEC89, 0x9780, 0xEC8A, 0x9781, 0xEC8B, 0x9782, 0xEC8C, + 0x9783, 0xEC8D, 0x9784, 0xEC8E, 0x9785, 0xF7B1, 0x9786, 0xEC8F, 0x9787, 0xEC90, 0x9788, 0xEC91, 0x9789, 0xEC92, 0x978A, 0xEC93, + 0x978B, 0xD0AC, 0x978C, 0xEC94, 0x978D, 0xB0B0, 0x978E, 0xEC95, 0x978F, 0xEC96, 0x9790, 0xEC97, 0x9791, 0xF7B2, 0x9792, 0xF7B3, + 0x9793, 0xEC98, 0x9794, 0xF7B4, 0x9795, 0xEC99, 0x9796, 0xEC9A, 0x9797, 0xEC9B, 0x9798, 0xC7CA, 0x9799, 0xEC9C, 0x979A, 0xEC9D, + 0x979B, 0xEC9E, 0x979C, 0xEC9F, 0x979D, 0xECA0, 0x979E, 0xED40, 0x979F, 0xED41, 0x97A0, 0xBECF, 0x97A1, 0xED42, 0x97A2, 0xED43, + 0x97A3, 0xF7B7, 0x97A4, 0xED44, 0x97A5, 0xED45, 0x97A6, 0xED46, 0x97A7, 0xED47, 0x97A8, 0xED48, 0x97A9, 0xED49, 0x97AA, 0xED4A, + 0x97AB, 0xF7B6, 0x97AC, 0xED4B, 0x97AD, 0xB1DE, 0x97AE, 0xED4C, 0x97AF, 0xF7B5, 0x97B0, 0xED4D, 0x97B1, 0xED4E, 0x97B2, 0xF7B8, + 0x97B3, 0xED4F, 0x97B4, 0xF7B9, 0x97B5, 0xED50, 0x97B6, 0xED51, 0x97B7, 0xED52, 0x97B8, 0xED53, 0x97B9, 0xED54, 0x97BA, 0xED55, + 0x97BB, 0xED56, 0x97BC, 0xED57, 0x97BD, 0xED58, 0x97BE, 0xED59, 0x97BF, 0xED5A, 0x97C0, 0xED5B, 0x97C1, 0xED5C, 0x97C2, 0xED5D, + 0x97C3, 0xED5E, 0x97C4, 0xED5F, 0x97C5, 0xED60, 0x97C6, 0xED61, 0x97C7, 0xED62, 0x97C8, 0xED63, 0x97C9, 0xED64, 0x97CA, 0xED65, + 0x97CB, 0xED66, 0x97CC, 0xED67, 0x97CD, 0xED68, 0x97CE, 0xED69, 0x97CF, 0xED6A, 0x97D0, 0xED6B, 0x97D1, 0xED6C, 0x97D2, 0xED6D, + 0x97D3, 0xED6E, 0x97D4, 0xED6F, 0x97D5, 0xED70, 0x97D6, 0xED71, 0x97D7, 0xED72, 0x97D8, 0xED73, 0x97D9, 0xED74, 0x97DA, 0xED75, + 0x97DB, 0xED76, 0x97DC, 0xED77, 0x97DD, 0xED78, 0x97DE, 0xED79, 0x97DF, 0xED7A, 0x97E0, 0xED7B, 0x97E1, 0xED7C, 0x97E2, 0xED7D, + 0x97E3, 0xED7E, 0x97E4, 0xED80, 0x97E5, 0xED81, 0x97E6, 0xCEA4, 0x97E7, 0xC8CD, 0x97E8, 0xED82, 0x97E9, 0xBAAB, 0x97EA, 0xE8B8, + 0x97EB, 0xE8B9, 0x97EC, 0xE8BA, 0x97ED, 0xBEC2, 0x97EE, 0xED83, 0x97EF, 0xED84, 0x97F0, 0xED85, 0x97F1, 0xED86, 0x97F2, 0xED87, + 0x97F3, 0xD2F4, 0x97F4, 0xED88, 0x97F5, 0xD4CF, 0x97F6, 0xC9D8, 0x97F7, 0xED89, 0x97F8, 0xED8A, 0x97F9, 0xED8B, 0x97FA, 0xED8C, + 0x97FB, 0xED8D, 0x97FC, 0xED8E, 0x97FD, 0xED8F, 0x97FE, 0xED90, 0x97FF, 0xED91, 0x9800, 0xED92, 0x9801, 0xED93, 0x9802, 0xED94, + 0x9803, 0xED95, 0x9804, 0xED96, 0x9805, 0xED97, 0x9806, 0xED98, 0x9807, 0xED99, 0x9808, 0xED9A, 0x9809, 0xED9B, 0x980A, 0xED9C, + 0x980B, 0xED9D, 0x980C, 0xED9E, 0x980D, 0xED9F, 0x980E, 0xEDA0, 0x980F, 0xEE40, 0x9810, 0xEE41, 0x9811, 0xEE42, 0x9812, 0xEE43, + 0x9813, 0xEE44, 0x9814, 0xEE45, 0x9815, 0xEE46, 0x9816, 0xEE47, 0x9817, 0xEE48, 0x9818, 0xEE49, 0x9819, 0xEE4A, 0x981A, 0xEE4B, + 0x981B, 0xEE4C, 0x981C, 0xEE4D, 0x981D, 0xEE4E, 0x981E, 0xEE4F, 0x981F, 0xEE50, 0x9820, 0xEE51, 0x9821, 0xEE52, 0x9822, 0xEE53, + 0x9823, 0xEE54, 0x9824, 0xEE55, 0x9825, 0xEE56, 0x9826, 0xEE57, 0x9827, 0xEE58, 0x9828, 0xEE59, 0x9829, 0xEE5A, 0x982A, 0xEE5B, + 0x982B, 0xEE5C, 0x982C, 0xEE5D, 0x982D, 0xEE5E, 0x982E, 0xEE5F, 0x982F, 0xEE60, 0x9830, 0xEE61, 0x9831, 0xEE62, 0x9832, 0xEE63, + 0x9833, 0xEE64, 0x9834, 0xEE65, 0x9835, 0xEE66, 0x9836, 0xEE67, 0x9837, 0xEE68, 0x9838, 0xEE69, 0x9839, 0xEE6A, 0x983A, 0xEE6B, + 0x983B, 0xEE6C, 0x983C, 0xEE6D, 0x983D, 0xEE6E, 0x983E, 0xEE6F, 0x983F, 0xEE70, 0x9840, 0xEE71, 0x9841, 0xEE72, 0x9842, 0xEE73, + 0x9843, 0xEE74, 0x9844, 0xEE75, 0x9845, 0xEE76, 0x9846, 0xEE77, 0x9847, 0xEE78, 0x9848, 0xEE79, 0x9849, 0xEE7A, 0x984A, 0xEE7B, + 0x984B, 0xEE7C, 0x984C, 0xEE7D, 0x984D, 0xEE7E, 0x984E, 0xEE80, 0x984F, 0xEE81, 0x9850, 0xEE82, 0x9851, 0xEE83, 0x9852, 0xEE84, + 0x9853, 0xEE85, 0x9854, 0xEE86, 0x9855, 0xEE87, 0x9856, 0xEE88, 0x9857, 0xEE89, 0x9858, 0xEE8A, 0x9859, 0xEE8B, 0x985A, 0xEE8C, + 0x985B, 0xEE8D, 0x985C, 0xEE8E, 0x985D, 0xEE8F, 0x985E, 0xEE90, 0x985F, 0xEE91, 0x9860, 0xEE92, 0x9861, 0xEE93, 0x9862, 0xEE94, + 0x9863, 0xEE95, 0x9864, 0xEE96, 0x9865, 0xEE97, 0x9866, 0xEE98, 0x9867, 0xEE99, 0x9868, 0xEE9A, 0x9869, 0xEE9B, 0x986A, 0xEE9C, + 0x986B, 0xEE9D, 0x986C, 0xEE9E, 0x986D, 0xEE9F, 0x986E, 0xEEA0, 0x986F, 0xEF40, 0x9870, 0xEF41, 0x9871, 0xEF42, 0x9872, 0xEF43, + 0x9873, 0xEF44, 0x9874, 0xEF45, 0x9875, 0xD2B3, 0x9876, 0xB6A5, 0x9877, 0xC7EA, 0x9878, 0xF1FC, 0x9879, 0xCFEE, 0x987A, 0xCBB3, + 0x987B, 0xD0EB, 0x987C, 0xE7EF, 0x987D, 0xCDE7, 0x987E, 0xB9CB, 0x987F, 0xB6D9, 0x9880, 0xF1FD, 0x9881, 0xB0E4, 0x9882, 0xCBCC, + 0x9883, 0xF1FE, 0x9884, 0xD4A4, 0x9885, 0xC2AD, 0x9886, 0xC1EC, 0x9887, 0xC6C4, 0x9888, 0xBEB1, 0x9889, 0xF2A1, 0x988A, 0xBCD5, + 0x988B, 0xEF46, 0x988C, 0xF2A2, 0x988D, 0xF2A3, 0x988E, 0xEF47, 0x988F, 0xF2A4, 0x9890, 0xD2C3, 0x9891, 0xC6B5, 0x9892, 0xEF48, + 0x9893, 0xCDC7, 0x9894, 0xF2A5, 0x9895, 0xEF49, 0x9896, 0xD3B1, 0x9897, 0xBFC5, 0x9898, 0xCCE2, 0x9899, 0xEF4A, 0x989A, 0xF2A6, + 0x989B, 0xF2A7, 0x989C, 0xD1D5, 0x989D, 0xB6EE, 0x989E, 0xF2A8, 0x989F, 0xF2A9, 0x98A0, 0xB5DF, 0x98A1, 0xF2AA, 0x98A2, 0xF2AB, + 0x98A3, 0xEF4B, 0x98A4, 0xB2FC, 0x98A5, 0xF2AC, 0x98A6, 0xF2AD, 0x98A7, 0xC8A7, 0x98A8, 0xEF4C, 0x98A9, 0xEF4D, 0x98AA, 0xEF4E, + 0x98AB, 0xEF4F, 0x98AC, 0xEF50, 0x98AD, 0xEF51, 0x98AE, 0xEF52, 0x98AF, 0xEF53, 0x98B0, 0xEF54, 0x98B1, 0xEF55, 0x98B2, 0xEF56, + 0x98B3, 0xEF57, 0x98B4, 0xEF58, 0x98B5, 0xEF59, 0x98B6, 0xEF5A, 0x98B7, 0xEF5B, 0x98B8, 0xEF5C, 0x98B9, 0xEF5D, 0x98BA, 0xEF5E, + 0x98BB, 0xEF5F, 0x98BC, 0xEF60, 0x98BD, 0xEF61, 0x98BE, 0xEF62, 0x98BF, 0xEF63, 0x98C0, 0xEF64, 0x98C1, 0xEF65, 0x98C2, 0xEF66, + 0x98C3, 0xEF67, 0x98C4, 0xEF68, 0x98C5, 0xEF69, 0x98C6, 0xEF6A, 0x98C7, 0xEF6B, 0x98C8, 0xEF6C, 0x98C9, 0xEF6D, 0x98CA, 0xEF6E, + 0x98CB, 0xEF6F, 0x98CC, 0xEF70, 0x98CD, 0xEF71, 0x98CE, 0xB7E7, 0x98CF, 0xEF72, 0x98D0, 0xEF73, 0x98D1, 0xECA9, 0x98D2, 0xECAA, + 0x98D3, 0xECAB, 0x98D4, 0xEF74, 0x98D5, 0xECAC, 0x98D6, 0xEF75, 0x98D7, 0xEF76, 0x98D8, 0xC6AE, 0x98D9, 0xECAD, 0x98DA, 0xECAE, + 0x98DB, 0xEF77, 0x98DC, 0xEF78, 0x98DD, 0xEF79, 0x98DE, 0xB7C9, 0x98DF, 0xCAB3, 0x98E0, 0xEF7A, 0x98E1, 0xEF7B, 0x98E2, 0xEF7C, + 0x98E3, 0xEF7D, 0x98E4, 0xEF7E, 0x98E5, 0xEF80, 0x98E6, 0xEF81, 0x98E7, 0xE2B8, 0x98E8, 0xF7CF, 0x98E9, 0xEF82, 0x98EA, 0xEF83, + 0x98EB, 0xEF84, 0x98EC, 0xEF85, 0x98ED, 0xEF86, 0x98EE, 0xEF87, 0x98EF, 0xEF88, 0x98F0, 0xEF89, 0x98F1, 0xEF8A, 0x98F2, 0xEF8B, + 0x98F3, 0xEF8C, 0x98F4, 0xEF8D, 0x98F5, 0xEF8E, 0x98F6, 0xEF8F, 0x98F7, 0xEF90, 0x98F8, 0xEF91, 0x98F9, 0xEF92, 0x98FA, 0xEF93, + 0x98FB, 0xEF94, 0x98FC, 0xEF95, 0x98FD, 0xEF96, 0x98FE, 0xEF97, 0x98FF, 0xEF98, 0x9900, 0xEF99, 0x9901, 0xEF9A, 0x9902, 0xEF9B, + 0x9903, 0xEF9C, 0x9904, 0xEF9D, 0x9905, 0xEF9E, 0x9906, 0xEF9F, 0x9907, 0xEFA0, 0x9908, 0xF040, 0x9909, 0xF041, 0x990A, 0xF042, + 0x990B, 0xF043, 0x990C, 0xF044, 0x990D, 0xF7D0, 0x990E, 0xF045, 0x990F, 0xF046, 0x9910, 0xB2CD, 0x9911, 0xF047, 0x9912, 0xF048, + 0x9913, 0xF049, 0x9914, 0xF04A, 0x9915, 0xF04B, 0x9916, 0xF04C, 0x9917, 0xF04D, 0x9918, 0xF04E, 0x9919, 0xF04F, 0x991A, 0xF050, + 0x991B, 0xF051, 0x991C, 0xF052, 0x991D, 0xF053, 0x991E, 0xF054, 0x991F, 0xF055, 0x9920, 0xF056, 0x9921, 0xF057, 0x9922, 0xF058, + 0x9923, 0xF059, 0x9924, 0xF05A, 0x9925, 0xF05B, 0x9926, 0xF05C, 0x9927, 0xF05D, 0x9928, 0xF05E, 0x9929, 0xF05F, 0x992A, 0xF060, + 0x992B, 0xF061, 0x992C, 0xF062, 0x992D, 0xF063, 0x992E, 0xF7D1, 0x992F, 0xF064, 0x9930, 0xF065, 0x9931, 0xF066, 0x9932, 0xF067, + 0x9933, 0xF068, 0x9934, 0xF069, 0x9935, 0xF06A, 0x9936, 0xF06B, 0x9937, 0xF06C, 0x9938, 0xF06D, 0x9939, 0xF06E, 0x993A, 0xF06F, + 0x993B, 0xF070, 0x993C, 0xF071, 0x993D, 0xF072, 0x993E, 0xF073, 0x993F, 0xF074, 0x9940, 0xF075, 0x9941, 0xF076, 0x9942, 0xF077, + 0x9943, 0xF078, 0x9944, 0xF079, 0x9945, 0xF07A, 0x9946, 0xF07B, 0x9947, 0xF07C, 0x9948, 0xF07D, 0x9949, 0xF07E, 0x994A, 0xF080, + 0x994B, 0xF081, 0x994C, 0xF082, 0x994D, 0xF083, 0x994E, 0xF084, 0x994F, 0xF085, 0x9950, 0xF086, 0x9951, 0xF087, 0x9952, 0xF088, + 0x9953, 0xF089, 0x9954, 0xF7D3, 0x9955, 0xF7D2, 0x9956, 0xF08A, 0x9957, 0xF08B, 0x9958, 0xF08C, 0x9959, 0xF08D, 0x995A, 0xF08E, + 0x995B, 0xF08F, 0x995C, 0xF090, 0x995D, 0xF091, 0x995E, 0xF092, 0x995F, 0xF093, 0x9960, 0xF094, 0x9961, 0xF095, 0x9962, 0xF096, + 0x9963, 0xE2BB, 0x9964, 0xF097, 0x9965, 0xBCA2, 0x9966, 0xF098, 0x9967, 0xE2BC, 0x9968, 0xE2BD, 0x9969, 0xE2BE, 0x996A, 0xE2BF, + 0x996B, 0xE2C0, 0x996C, 0xE2C1, 0x996D, 0xB7B9, 0x996E, 0xD2FB, 0x996F, 0xBDA4, 0x9970, 0xCACE, 0x9971, 0xB1A5, 0x9972, 0xCBC7, + 0x9973, 0xF099, 0x9974, 0xE2C2, 0x9975, 0xB6FC, 0x9976, 0xC8C4, 0x9977, 0xE2C3, 0x9978, 0xF09A, 0x9979, 0xF09B, 0x997A, 0xBDC8, + 0x997B, 0xF09C, 0x997C, 0xB1FD, 0x997D, 0xE2C4, 0x997E, 0xF09D, 0x997F, 0xB6F6, 0x9980, 0xE2C5, 0x9981, 0xC4D9, 0x9982, 0xF09E, + 0x9983, 0xF09F, 0x9984, 0xE2C6, 0x9985, 0xCFDA, 0x9986, 0xB9DD, 0x9987, 0xE2C7, 0x9988, 0xC0A1, 0x9989, 0xF0A0, 0x998A, 0xE2C8, + 0x998B, 0xB2F6, 0x998C, 0xF140, 0x998D, 0xE2C9, 0x998E, 0xF141, 0x998F, 0xC1F3, 0x9990, 0xE2CA, 0x9991, 0xE2CB, 0x9992, 0xC2F8, + 0x9993, 0xE2CC, 0x9994, 0xE2CD, 0x9995, 0xE2CE, 0x9996, 0xCAD7, 0x9997, 0xD8B8, 0x9998, 0xD9E5, 0x9999, 0xCFE3, 0x999A, 0xF142, + 0x999B, 0xF143, 0x999C, 0xF144, 0x999D, 0xF145, 0x999E, 0xF146, 0x999F, 0xF147, 0x99A0, 0xF148, 0x99A1, 0xF149, 0x99A2, 0xF14A, + 0x99A3, 0xF14B, 0x99A4, 0xF14C, 0x99A5, 0xF0A5, 0x99A6, 0xF14D, 0x99A7, 0xF14E, 0x99A8, 0xDCB0, 0x99A9, 0xF14F, 0x99AA, 0xF150, + 0x99AB, 0xF151, 0x99AC, 0xF152, 0x99AD, 0xF153, 0x99AE, 0xF154, 0x99AF, 0xF155, 0x99B0, 0xF156, 0x99B1, 0xF157, 0x99B2, 0xF158, + 0x99B3, 0xF159, 0x99B4, 0xF15A, 0x99B5, 0xF15B, 0x99B6, 0xF15C, 0x99B7, 0xF15D, 0x99B8, 0xF15E, 0x99B9, 0xF15F, 0x99BA, 0xF160, + 0x99BB, 0xF161, 0x99BC, 0xF162, 0x99BD, 0xF163, 0x99BE, 0xF164, 0x99BF, 0xF165, 0x99C0, 0xF166, 0x99C1, 0xF167, 0x99C2, 0xF168, + 0x99C3, 0xF169, 0x99C4, 0xF16A, 0x99C5, 0xF16B, 0x99C6, 0xF16C, 0x99C7, 0xF16D, 0x99C8, 0xF16E, 0x99C9, 0xF16F, 0x99CA, 0xF170, + 0x99CB, 0xF171, 0x99CC, 0xF172, 0x99CD, 0xF173, 0x99CE, 0xF174, 0x99CF, 0xF175, 0x99D0, 0xF176, 0x99D1, 0xF177, 0x99D2, 0xF178, + 0x99D3, 0xF179, 0x99D4, 0xF17A, 0x99D5, 0xF17B, 0x99D6, 0xF17C, 0x99D7, 0xF17D, 0x99D8, 0xF17E, 0x99D9, 0xF180, 0x99DA, 0xF181, + 0x99DB, 0xF182, 0x99DC, 0xF183, 0x99DD, 0xF184, 0x99DE, 0xF185, 0x99DF, 0xF186, 0x99E0, 0xF187, 0x99E1, 0xF188, 0x99E2, 0xF189, + 0x99E3, 0xF18A, 0x99E4, 0xF18B, 0x99E5, 0xF18C, 0x99E6, 0xF18D, 0x99E7, 0xF18E, 0x99E8, 0xF18F, 0x99E9, 0xF190, 0x99EA, 0xF191, + 0x99EB, 0xF192, 0x99EC, 0xF193, 0x99ED, 0xF194, 0x99EE, 0xF195, 0x99EF, 0xF196, 0x99F0, 0xF197, 0x99F1, 0xF198, 0x99F2, 0xF199, + 0x99F3, 0xF19A, 0x99F4, 0xF19B, 0x99F5, 0xF19C, 0x99F6, 0xF19D, 0x99F7, 0xF19E, 0x99F8, 0xF19F, 0x99F9, 0xF1A0, 0x99FA, 0xF240, + 0x99FB, 0xF241, 0x99FC, 0xF242, 0x99FD, 0xF243, 0x99FE, 0xF244, 0x99FF, 0xF245, 0x9A00, 0xF246, 0x9A01, 0xF247, 0x9A02, 0xF248, + 0x9A03, 0xF249, 0x9A04, 0xF24A, 0x9A05, 0xF24B, 0x9A06, 0xF24C, 0x9A07, 0xF24D, 0x9A08, 0xF24E, 0x9A09, 0xF24F, 0x9A0A, 0xF250, + 0x9A0B, 0xF251, 0x9A0C, 0xF252, 0x9A0D, 0xF253, 0x9A0E, 0xF254, 0x9A0F, 0xF255, 0x9A10, 0xF256, 0x9A11, 0xF257, 0x9A12, 0xF258, + 0x9A13, 0xF259, 0x9A14, 0xF25A, 0x9A15, 0xF25B, 0x9A16, 0xF25C, 0x9A17, 0xF25D, 0x9A18, 0xF25E, 0x9A19, 0xF25F, 0x9A1A, 0xF260, + 0x9A1B, 0xF261, 0x9A1C, 0xF262, 0x9A1D, 0xF263, 0x9A1E, 0xF264, 0x9A1F, 0xF265, 0x9A20, 0xF266, 0x9A21, 0xF267, 0x9A22, 0xF268, + 0x9A23, 0xF269, 0x9A24, 0xF26A, 0x9A25, 0xF26B, 0x9A26, 0xF26C, 0x9A27, 0xF26D, 0x9A28, 0xF26E, 0x9A29, 0xF26F, 0x9A2A, 0xF270, + 0x9A2B, 0xF271, 0x9A2C, 0xF272, 0x9A2D, 0xF273, 0x9A2E, 0xF274, 0x9A2F, 0xF275, 0x9A30, 0xF276, 0x9A31, 0xF277, 0x9A32, 0xF278, + 0x9A33, 0xF279, 0x9A34, 0xF27A, 0x9A35, 0xF27B, 0x9A36, 0xF27C, 0x9A37, 0xF27D, 0x9A38, 0xF27E, 0x9A39, 0xF280, 0x9A3A, 0xF281, + 0x9A3B, 0xF282, 0x9A3C, 0xF283, 0x9A3D, 0xF284, 0x9A3E, 0xF285, 0x9A3F, 0xF286, 0x9A40, 0xF287, 0x9A41, 0xF288, 0x9A42, 0xF289, + 0x9A43, 0xF28A, 0x9A44, 0xF28B, 0x9A45, 0xF28C, 0x9A46, 0xF28D, 0x9A47, 0xF28E, 0x9A48, 0xF28F, 0x9A49, 0xF290, 0x9A4A, 0xF291, + 0x9A4B, 0xF292, 0x9A4C, 0xF293, 0x9A4D, 0xF294, 0x9A4E, 0xF295, 0x9A4F, 0xF296, 0x9A50, 0xF297, 0x9A51, 0xF298, 0x9A52, 0xF299, + 0x9A53, 0xF29A, 0x9A54, 0xF29B, 0x9A55, 0xF29C, 0x9A56, 0xF29D, 0x9A57, 0xF29E, 0x9A58, 0xF29F, 0x9A59, 0xF2A0, 0x9A5A, 0xF340, + 0x9A5B, 0xF341, 0x9A5C, 0xF342, 0x9A5D, 0xF343, 0x9A5E, 0xF344, 0x9A5F, 0xF345, 0x9A60, 0xF346, 0x9A61, 0xF347, 0x9A62, 0xF348, + 0x9A63, 0xF349, 0x9A64, 0xF34A, 0x9A65, 0xF34B, 0x9A66, 0xF34C, 0x9A67, 0xF34D, 0x9A68, 0xF34E, 0x9A69, 0xF34F, 0x9A6A, 0xF350, + 0x9A6B, 0xF351, 0x9A6C, 0xC2ED, 0x9A6D, 0xD4A6, 0x9A6E, 0xCDD4, 0x9A6F, 0xD1B1, 0x9A70, 0xB3DB, 0x9A71, 0xC7FD, 0x9A72, 0xF352, + 0x9A73, 0xB2B5, 0x9A74, 0xC2BF, 0x9A75, 0xE6E0, 0x9A76, 0xCABB, 0x9A77, 0xE6E1, 0x9A78, 0xE6E2, 0x9A79, 0xBED4, 0x9A7A, 0xE6E3, + 0x9A7B, 0xD7A4, 0x9A7C, 0xCDD5, 0x9A7D, 0xE6E5, 0x9A7E, 0xBCDD, 0x9A7F, 0xE6E4, 0x9A80, 0xE6E6, 0x9A81, 0xE6E7, 0x9A82, 0xC2EE, + 0x9A83, 0xF353, 0x9A84, 0xBDBE, 0x9A85, 0xE6E8, 0x9A86, 0xC2E6, 0x9A87, 0xBAA7, 0x9A88, 0xE6E9, 0x9A89, 0xF354, 0x9A8A, 0xE6EA, + 0x9A8B, 0xB3D2, 0x9A8C, 0xD1E9, 0x9A8D, 0xF355, 0x9A8E, 0xF356, 0x9A8F, 0xBFA5, 0x9A90, 0xE6EB, 0x9A91, 0xC6EF, 0x9A92, 0xE6EC, + 0x9A93, 0xE6ED, 0x9A94, 0xF357, 0x9A95, 0xF358, 0x9A96, 0xE6EE, 0x9A97, 0xC6AD, 0x9A98, 0xE6EF, 0x9A99, 0xF359, 0x9A9A, 0xC9A7, + 0x9A9B, 0xE6F0, 0x9A9C, 0xE6F1, 0x9A9D, 0xE6F2, 0x9A9E, 0xE5B9, 0x9A9F, 0xE6F3, 0x9AA0, 0xE6F4, 0x9AA1, 0xC2E2, 0x9AA2, 0xE6F5, + 0x9AA3, 0xE6F6, 0x9AA4, 0xD6E8, 0x9AA5, 0xE6F7, 0x9AA6, 0xF35A, 0x9AA7, 0xE6F8, 0x9AA8, 0xB9C7, 0x9AA9, 0xF35B, 0x9AAA, 0xF35C, + 0x9AAB, 0xF35D, 0x9AAC, 0xF35E, 0x9AAD, 0xF35F, 0x9AAE, 0xF360, 0x9AAF, 0xF361, 0x9AB0, 0xF7BB, 0x9AB1, 0xF7BA, 0x9AB2, 0xF362, + 0x9AB3, 0xF363, 0x9AB4, 0xF364, 0x9AB5, 0xF365, 0x9AB6, 0xF7BE, 0x9AB7, 0xF7BC, 0x9AB8, 0xBAA1, 0x9AB9, 0xF366, 0x9ABA, 0xF7BF, + 0x9ABB, 0xF367, 0x9ABC, 0xF7C0, 0x9ABD, 0xF368, 0x9ABE, 0xF369, 0x9ABF, 0xF36A, 0x9AC0, 0xF7C2, 0x9AC1, 0xF7C1, 0x9AC2, 0xF7C4, + 0x9AC3, 0xF36B, 0x9AC4, 0xF36C, 0x9AC5, 0xF7C3, 0x9AC6, 0xF36D, 0x9AC7, 0xF36E, 0x9AC8, 0xF36F, 0x9AC9, 0xF370, 0x9ACA, 0xF371, + 0x9ACB, 0xF7C5, 0x9ACC, 0xF7C6, 0x9ACD, 0xF372, 0x9ACE, 0xF373, 0x9ACF, 0xF374, 0x9AD0, 0xF375, 0x9AD1, 0xF7C7, 0x9AD2, 0xF376, + 0x9AD3, 0xCBE8, 0x9AD4, 0xF377, 0x9AD5, 0xF378, 0x9AD6, 0xF379, 0x9AD7, 0xF37A, 0x9AD8, 0xB8DF, 0x9AD9, 0xF37B, 0x9ADA, 0xF37C, + 0x9ADB, 0xF37D, 0x9ADC, 0xF37E, 0x9ADD, 0xF380, 0x9ADE, 0xF381, 0x9ADF, 0xF7D4, 0x9AE0, 0xF382, 0x9AE1, 0xF7D5, 0x9AE2, 0xF383, + 0x9AE3, 0xF384, 0x9AE4, 0xF385, 0x9AE5, 0xF386, 0x9AE6, 0xF7D6, 0x9AE7, 0xF387, 0x9AE8, 0xF388, 0x9AE9, 0xF389, 0x9AEA, 0xF38A, + 0x9AEB, 0xF7D8, 0x9AEC, 0xF38B, 0x9AED, 0xF7DA, 0x9AEE, 0xF38C, 0x9AEF, 0xF7D7, 0x9AF0, 0xF38D, 0x9AF1, 0xF38E, 0x9AF2, 0xF38F, + 0x9AF3, 0xF390, 0x9AF4, 0xF391, 0x9AF5, 0xF392, 0x9AF6, 0xF393, 0x9AF7, 0xF394, 0x9AF8, 0xF395, 0x9AF9, 0xF7DB, 0x9AFA, 0xF396, + 0x9AFB, 0xF7D9, 0x9AFC, 0xF397, 0x9AFD, 0xF398, 0x9AFE, 0xF399, 0x9AFF, 0xF39A, 0x9B00, 0xF39B, 0x9B01, 0xF39C, 0x9B02, 0xF39D, + 0x9B03, 0xD7D7, 0x9B04, 0xF39E, 0x9B05, 0xF39F, 0x9B06, 0xF3A0, 0x9B07, 0xF440, 0x9B08, 0xF7DC, 0x9B09, 0xF441, 0x9B0A, 0xF442, + 0x9B0B, 0xF443, 0x9B0C, 0xF444, 0x9B0D, 0xF445, 0x9B0E, 0xF446, 0x9B0F, 0xF7DD, 0x9B10, 0xF447, 0x9B11, 0xF448, 0x9B12, 0xF449, + 0x9B13, 0xF7DE, 0x9B14, 0xF44A, 0x9B15, 0xF44B, 0x9B16, 0xF44C, 0x9B17, 0xF44D, 0x9B18, 0xF44E, 0x9B19, 0xF44F, 0x9B1A, 0xF450, + 0x9B1B, 0xF451, 0x9B1C, 0xF452, 0x9B1D, 0xF453, 0x9B1E, 0xF454, 0x9B1F, 0xF7DF, 0x9B20, 0xF455, 0x9B21, 0xF456, 0x9B22, 0xF457, + 0x9B23, 0xF7E0, 0x9B24, 0xF458, 0x9B25, 0xF459, 0x9B26, 0xF45A, 0x9B27, 0xF45B, 0x9B28, 0xF45C, 0x9B29, 0xF45D, 0x9B2A, 0xF45E, + 0x9B2B, 0xF45F, 0x9B2C, 0xF460, 0x9B2D, 0xF461, 0x9B2E, 0xF462, 0x9B2F, 0xDBCB, 0x9B30, 0xF463, 0x9B31, 0xF464, 0x9B32, 0xD8AA, + 0x9B33, 0xF465, 0x9B34, 0xF466, 0x9B35, 0xF467, 0x9B36, 0xF468, 0x9B37, 0xF469, 0x9B38, 0xF46A, 0x9B39, 0xF46B, 0x9B3A, 0xF46C, + 0x9B3B, 0xE5F7, 0x9B3C, 0xB9ED, 0x9B3D, 0xF46D, 0x9B3E, 0xF46E, 0x9B3F, 0xF46F, 0x9B40, 0xF470, 0x9B41, 0xBFFD, 0x9B42, 0xBBEA, + 0x9B43, 0xF7C9, 0x9B44, 0xC6C7, 0x9B45, 0xF7C8, 0x9B46, 0xF471, 0x9B47, 0xF7CA, 0x9B48, 0xF7CC, 0x9B49, 0xF7CB, 0x9B4A, 0xF472, + 0x9B4B, 0xF473, 0x9B4C, 0xF474, 0x9B4D, 0xF7CD, 0x9B4E, 0xF475, 0x9B4F, 0xCEBA, 0x9B50, 0xF476, 0x9B51, 0xF7CE, 0x9B52, 0xF477, + 0x9B53, 0xF478, 0x9B54, 0xC4A7, 0x9B55, 0xF479, 0x9B56, 0xF47A, 0x9B57, 0xF47B, 0x9B58, 0xF47C, 0x9B59, 0xF47D, 0x9B5A, 0xF47E, + 0x9B5B, 0xF480, 0x9B5C, 0xF481, 0x9B5D, 0xF482, 0x9B5E, 0xF483, 0x9B5F, 0xF484, 0x9B60, 0xF485, 0x9B61, 0xF486, 0x9B62, 0xF487, + 0x9B63, 0xF488, 0x9B64, 0xF489, 0x9B65, 0xF48A, 0x9B66, 0xF48B, 0x9B67, 0xF48C, 0x9B68, 0xF48D, 0x9B69, 0xF48E, 0x9B6A, 0xF48F, + 0x9B6B, 0xF490, 0x9B6C, 0xF491, 0x9B6D, 0xF492, 0x9B6E, 0xF493, 0x9B6F, 0xF494, 0x9B70, 0xF495, 0x9B71, 0xF496, 0x9B72, 0xF497, + 0x9B73, 0xF498, 0x9B74, 0xF499, 0x9B75, 0xF49A, 0x9B76, 0xF49B, 0x9B77, 0xF49C, 0x9B78, 0xF49D, 0x9B79, 0xF49E, 0x9B7A, 0xF49F, + 0x9B7B, 0xF4A0, 0x9B7C, 0xF540, 0x9B7D, 0xF541, 0x9B7E, 0xF542, 0x9B7F, 0xF543, 0x9B80, 0xF544, 0x9B81, 0xF545, 0x9B82, 0xF546, + 0x9B83, 0xF547, 0x9B84, 0xF548, 0x9B85, 0xF549, 0x9B86, 0xF54A, 0x9B87, 0xF54B, 0x9B88, 0xF54C, 0x9B89, 0xF54D, 0x9B8A, 0xF54E, + 0x9B8B, 0xF54F, 0x9B8C, 0xF550, 0x9B8D, 0xF551, 0x9B8E, 0xF552, 0x9B8F, 0xF553, 0x9B90, 0xF554, 0x9B91, 0xF555, 0x9B92, 0xF556, + 0x9B93, 0xF557, 0x9B94, 0xF558, 0x9B95, 0xF559, 0x9B96, 0xF55A, 0x9B97, 0xF55B, 0x9B98, 0xF55C, 0x9B99, 0xF55D, 0x9B9A, 0xF55E, + 0x9B9B, 0xF55F, 0x9B9C, 0xF560, 0x9B9D, 0xF561, 0x9B9E, 0xF562, 0x9B9F, 0xF563, 0x9BA0, 0xF564, 0x9BA1, 0xF565, 0x9BA2, 0xF566, + 0x9BA3, 0xF567, 0x9BA4, 0xF568, 0x9BA5, 0xF569, 0x9BA6, 0xF56A, 0x9BA7, 0xF56B, 0x9BA8, 0xF56C, 0x9BA9, 0xF56D, 0x9BAA, 0xF56E, + 0x9BAB, 0xF56F, 0x9BAC, 0xF570, 0x9BAD, 0xF571, 0x9BAE, 0xF572, 0x9BAF, 0xF573, 0x9BB0, 0xF574, 0x9BB1, 0xF575, 0x9BB2, 0xF576, + 0x9BB3, 0xF577, 0x9BB4, 0xF578, 0x9BB5, 0xF579, 0x9BB6, 0xF57A, 0x9BB7, 0xF57B, 0x9BB8, 0xF57C, 0x9BB9, 0xF57D, 0x9BBA, 0xF57E, + 0x9BBB, 0xF580, 0x9BBC, 0xF581, 0x9BBD, 0xF582, 0x9BBE, 0xF583, 0x9BBF, 0xF584, 0x9BC0, 0xF585, 0x9BC1, 0xF586, 0x9BC2, 0xF587, + 0x9BC3, 0xF588, 0x9BC4, 0xF589, 0x9BC5, 0xF58A, 0x9BC6, 0xF58B, 0x9BC7, 0xF58C, 0x9BC8, 0xF58D, 0x9BC9, 0xF58E, 0x9BCA, 0xF58F, + 0x9BCB, 0xF590, 0x9BCC, 0xF591, 0x9BCD, 0xF592, 0x9BCE, 0xF593, 0x9BCF, 0xF594, 0x9BD0, 0xF595, 0x9BD1, 0xF596, 0x9BD2, 0xF597, + 0x9BD3, 0xF598, 0x9BD4, 0xF599, 0x9BD5, 0xF59A, 0x9BD6, 0xF59B, 0x9BD7, 0xF59C, 0x9BD8, 0xF59D, 0x9BD9, 0xF59E, 0x9BDA, 0xF59F, + 0x9BDB, 0xF5A0, 0x9BDC, 0xF640, 0x9BDD, 0xF641, 0x9BDE, 0xF642, 0x9BDF, 0xF643, 0x9BE0, 0xF644, 0x9BE1, 0xF645, 0x9BE2, 0xF646, + 0x9BE3, 0xF647, 0x9BE4, 0xF648, 0x9BE5, 0xF649, 0x9BE6, 0xF64A, 0x9BE7, 0xF64B, 0x9BE8, 0xF64C, 0x9BE9, 0xF64D, 0x9BEA, 0xF64E, + 0x9BEB, 0xF64F, 0x9BEC, 0xF650, 0x9BED, 0xF651, 0x9BEE, 0xF652, 0x9BEF, 0xF653, 0x9BF0, 0xF654, 0x9BF1, 0xF655, 0x9BF2, 0xF656, + 0x9BF3, 0xF657, 0x9BF4, 0xF658, 0x9BF5, 0xF659, 0x9BF6, 0xF65A, 0x9BF7, 0xF65B, 0x9BF8, 0xF65C, 0x9BF9, 0xF65D, 0x9BFA, 0xF65E, + 0x9BFB, 0xF65F, 0x9BFC, 0xF660, 0x9BFD, 0xF661, 0x9BFE, 0xF662, 0x9BFF, 0xF663, 0x9C00, 0xF664, 0x9C01, 0xF665, 0x9C02, 0xF666, + 0x9C03, 0xF667, 0x9C04, 0xF668, 0x9C05, 0xF669, 0x9C06, 0xF66A, 0x9C07, 0xF66B, 0x9C08, 0xF66C, 0x9C09, 0xF66D, 0x9C0A, 0xF66E, + 0x9C0B, 0xF66F, 0x9C0C, 0xF670, 0x9C0D, 0xF671, 0x9C0E, 0xF672, 0x9C0F, 0xF673, 0x9C10, 0xF674, 0x9C11, 0xF675, 0x9C12, 0xF676, + 0x9C13, 0xF677, 0x9C14, 0xF678, 0x9C15, 0xF679, 0x9C16, 0xF67A, 0x9C17, 0xF67B, 0x9C18, 0xF67C, 0x9C19, 0xF67D, 0x9C1A, 0xF67E, + 0x9C1B, 0xF680, 0x9C1C, 0xF681, 0x9C1D, 0xF682, 0x9C1E, 0xF683, 0x9C1F, 0xF684, 0x9C20, 0xF685, 0x9C21, 0xF686, 0x9C22, 0xF687, + 0x9C23, 0xF688, 0x9C24, 0xF689, 0x9C25, 0xF68A, 0x9C26, 0xF68B, 0x9C27, 0xF68C, 0x9C28, 0xF68D, 0x9C29, 0xF68E, 0x9C2A, 0xF68F, + 0x9C2B, 0xF690, 0x9C2C, 0xF691, 0x9C2D, 0xF692, 0x9C2E, 0xF693, 0x9C2F, 0xF694, 0x9C30, 0xF695, 0x9C31, 0xF696, 0x9C32, 0xF697, + 0x9C33, 0xF698, 0x9C34, 0xF699, 0x9C35, 0xF69A, 0x9C36, 0xF69B, 0x9C37, 0xF69C, 0x9C38, 0xF69D, 0x9C39, 0xF69E, 0x9C3A, 0xF69F, + 0x9C3B, 0xF6A0, 0x9C3C, 0xF740, 0x9C3D, 0xF741, 0x9C3E, 0xF742, 0x9C3F, 0xF743, 0x9C40, 0xF744, 0x9C41, 0xF745, 0x9C42, 0xF746, + 0x9C43, 0xF747, 0x9C44, 0xF748, 0x9C45, 0xF749, 0x9C46, 0xF74A, 0x9C47, 0xF74B, 0x9C48, 0xF74C, 0x9C49, 0xF74D, 0x9C4A, 0xF74E, + 0x9C4B, 0xF74F, 0x9C4C, 0xF750, 0x9C4D, 0xF751, 0x9C4E, 0xF752, 0x9C4F, 0xF753, 0x9C50, 0xF754, 0x9C51, 0xF755, 0x9C52, 0xF756, + 0x9C53, 0xF757, 0x9C54, 0xF758, 0x9C55, 0xF759, 0x9C56, 0xF75A, 0x9C57, 0xF75B, 0x9C58, 0xF75C, 0x9C59, 0xF75D, 0x9C5A, 0xF75E, + 0x9C5B, 0xF75F, 0x9C5C, 0xF760, 0x9C5D, 0xF761, 0x9C5E, 0xF762, 0x9C5F, 0xF763, 0x9C60, 0xF764, 0x9C61, 0xF765, 0x9C62, 0xF766, + 0x9C63, 0xF767, 0x9C64, 0xF768, 0x9C65, 0xF769, 0x9C66, 0xF76A, 0x9C67, 0xF76B, 0x9C68, 0xF76C, 0x9C69, 0xF76D, 0x9C6A, 0xF76E, + 0x9C6B, 0xF76F, 0x9C6C, 0xF770, 0x9C6D, 0xF771, 0x9C6E, 0xF772, 0x9C6F, 0xF773, 0x9C70, 0xF774, 0x9C71, 0xF775, 0x9C72, 0xF776, + 0x9C73, 0xF777, 0x9C74, 0xF778, 0x9C75, 0xF779, 0x9C76, 0xF77A, 0x9C77, 0xF77B, 0x9C78, 0xF77C, 0x9C79, 0xF77D, 0x9C7A, 0xF77E, + 0x9C7B, 0xF780, 0x9C7C, 0xD3E3, 0x9C7D, 0xF781, 0x9C7E, 0xF782, 0x9C7F, 0xF6CF, 0x9C80, 0xF783, 0x9C81, 0xC2B3, 0x9C82, 0xF6D0, + 0x9C83, 0xF784, 0x9C84, 0xF785, 0x9C85, 0xF6D1, 0x9C86, 0xF6D2, 0x9C87, 0xF6D3, 0x9C88, 0xF6D4, 0x9C89, 0xF786, 0x9C8A, 0xF787, + 0x9C8B, 0xF6D6, 0x9C8C, 0xF788, 0x9C8D, 0xB1AB, 0x9C8E, 0xF6D7, 0x9C8F, 0xF789, 0x9C90, 0xF6D8, 0x9C91, 0xF6D9, 0x9C92, 0xF6DA, + 0x9C93, 0xF78A, 0x9C94, 0xF6DB, 0x9C95, 0xF6DC, 0x9C96, 0xF78B, 0x9C97, 0xF78C, 0x9C98, 0xF78D, 0x9C99, 0xF78E, 0x9C9A, 0xF6DD, + 0x9C9B, 0xF6DE, 0x9C9C, 0xCFCA, 0x9C9D, 0xF78F, 0x9C9E, 0xF6DF, 0x9C9F, 0xF6E0, 0x9CA0, 0xF6E1, 0x9CA1, 0xF6E2, 0x9CA2, 0xF6E3, + 0x9CA3, 0xF6E4, 0x9CA4, 0xC0F0, 0x9CA5, 0xF6E5, 0x9CA6, 0xF6E6, 0x9CA7, 0xF6E7, 0x9CA8, 0xF6E8, 0x9CA9, 0xF6E9, 0x9CAA, 0xF790, + 0x9CAB, 0xF6EA, 0x9CAC, 0xF791, 0x9CAD, 0xF6EB, 0x9CAE, 0xF6EC, 0x9CAF, 0xF792, 0x9CB0, 0xF6ED, 0x9CB1, 0xF6EE, 0x9CB2, 0xF6EF, + 0x9CB3, 0xF6F0, 0x9CB4, 0xF6F1, 0x9CB5, 0xF6F2, 0x9CB6, 0xF6F3, 0x9CB7, 0xF6F4, 0x9CB8, 0xBEA8, 0x9CB9, 0xF793, 0x9CBA, 0xF6F5, + 0x9CBB, 0xF6F6, 0x9CBC, 0xF6F7, 0x9CBD, 0xF6F8, 0x9CBE, 0xF794, 0x9CBF, 0xF795, 0x9CC0, 0xF796, 0x9CC1, 0xF797, 0x9CC2, 0xF798, + 0x9CC3, 0xC8FA, 0x9CC4, 0xF6F9, 0x9CC5, 0xF6FA, 0x9CC6, 0xF6FB, 0x9CC7, 0xF6FC, 0x9CC8, 0xF799, 0x9CC9, 0xF79A, 0x9CCA, 0xF6FD, + 0x9CCB, 0xF6FE, 0x9CCC, 0xF7A1, 0x9CCD, 0xF7A2, 0x9CCE, 0xF7A3, 0x9CCF, 0xF7A4, 0x9CD0, 0xF7A5, 0x9CD1, 0xF79B, 0x9CD2, 0xF79C, + 0x9CD3, 0xF7A6, 0x9CD4, 0xF7A7, 0x9CD5, 0xF7A8, 0x9CD6, 0xB1EE, 0x9CD7, 0xF7A9, 0x9CD8, 0xF7AA, 0x9CD9, 0xF7AB, 0x9CDA, 0xF79D, + 0x9CDB, 0xF79E, 0x9CDC, 0xF7AC, 0x9CDD, 0xF7AD, 0x9CDE, 0xC1DB, 0x9CDF, 0xF7AE, 0x9CE0, 0xF79F, 0x9CE1, 0xF7A0, 0x9CE2, 0xF7AF, + 0x9CE3, 0xF840, 0x9CE4, 0xF841, 0x9CE5, 0xF842, 0x9CE6, 0xF843, 0x9CE7, 0xF844, 0x9CE8, 0xF845, 0x9CE9, 0xF846, 0x9CEA, 0xF847, + 0x9CEB, 0xF848, 0x9CEC, 0xF849, 0x9CED, 0xF84A, 0x9CEE, 0xF84B, 0x9CEF, 0xF84C, 0x9CF0, 0xF84D, 0x9CF1, 0xF84E, 0x9CF2, 0xF84F, + 0x9CF3, 0xF850, 0x9CF4, 0xF851, 0x9CF5, 0xF852, 0x9CF6, 0xF853, 0x9CF7, 0xF854, 0x9CF8, 0xF855, 0x9CF9, 0xF856, 0x9CFA, 0xF857, + 0x9CFB, 0xF858, 0x9CFC, 0xF859, 0x9CFD, 0xF85A, 0x9CFE, 0xF85B, 0x9CFF, 0xF85C, 0x9D00, 0xF85D, 0x9D01, 0xF85E, 0x9D02, 0xF85F, + 0x9D03, 0xF860, 0x9D04, 0xF861, 0x9D05, 0xF862, 0x9D06, 0xF863, 0x9D07, 0xF864, 0x9D08, 0xF865, 0x9D09, 0xF866, 0x9D0A, 0xF867, + 0x9D0B, 0xF868, 0x9D0C, 0xF869, 0x9D0D, 0xF86A, 0x9D0E, 0xF86B, 0x9D0F, 0xF86C, 0x9D10, 0xF86D, 0x9D11, 0xF86E, 0x9D12, 0xF86F, + 0x9D13, 0xF870, 0x9D14, 0xF871, 0x9D15, 0xF872, 0x9D16, 0xF873, 0x9D17, 0xF874, 0x9D18, 0xF875, 0x9D19, 0xF876, 0x9D1A, 0xF877, + 0x9D1B, 0xF878, 0x9D1C, 0xF879, 0x9D1D, 0xF87A, 0x9D1E, 0xF87B, 0x9D1F, 0xF87C, 0x9D20, 0xF87D, 0x9D21, 0xF87E, 0x9D22, 0xF880, + 0x9D23, 0xF881, 0x9D24, 0xF882, 0x9D25, 0xF883, 0x9D26, 0xF884, 0x9D27, 0xF885, 0x9D28, 0xF886, 0x9D29, 0xF887, 0x9D2A, 0xF888, + 0x9D2B, 0xF889, 0x9D2C, 0xF88A, 0x9D2D, 0xF88B, 0x9D2E, 0xF88C, 0x9D2F, 0xF88D, 0x9D30, 0xF88E, 0x9D31, 0xF88F, 0x9D32, 0xF890, + 0x9D33, 0xF891, 0x9D34, 0xF892, 0x9D35, 0xF893, 0x9D36, 0xF894, 0x9D37, 0xF895, 0x9D38, 0xF896, 0x9D39, 0xF897, 0x9D3A, 0xF898, + 0x9D3B, 0xF899, 0x9D3C, 0xF89A, 0x9D3D, 0xF89B, 0x9D3E, 0xF89C, 0x9D3F, 0xF89D, 0x9D40, 0xF89E, 0x9D41, 0xF89F, 0x9D42, 0xF8A0, + 0x9D43, 0xF940, 0x9D44, 0xF941, 0x9D45, 0xF942, 0x9D46, 0xF943, 0x9D47, 0xF944, 0x9D48, 0xF945, 0x9D49, 0xF946, 0x9D4A, 0xF947, + 0x9D4B, 0xF948, 0x9D4C, 0xF949, 0x9D4D, 0xF94A, 0x9D4E, 0xF94B, 0x9D4F, 0xF94C, 0x9D50, 0xF94D, 0x9D51, 0xF94E, 0x9D52, 0xF94F, + 0x9D53, 0xF950, 0x9D54, 0xF951, 0x9D55, 0xF952, 0x9D56, 0xF953, 0x9D57, 0xF954, 0x9D58, 0xF955, 0x9D59, 0xF956, 0x9D5A, 0xF957, + 0x9D5B, 0xF958, 0x9D5C, 0xF959, 0x9D5D, 0xF95A, 0x9D5E, 0xF95B, 0x9D5F, 0xF95C, 0x9D60, 0xF95D, 0x9D61, 0xF95E, 0x9D62, 0xF95F, + 0x9D63, 0xF960, 0x9D64, 0xF961, 0x9D65, 0xF962, 0x9D66, 0xF963, 0x9D67, 0xF964, 0x9D68, 0xF965, 0x9D69, 0xF966, 0x9D6A, 0xF967, + 0x9D6B, 0xF968, 0x9D6C, 0xF969, 0x9D6D, 0xF96A, 0x9D6E, 0xF96B, 0x9D6F, 0xF96C, 0x9D70, 0xF96D, 0x9D71, 0xF96E, 0x9D72, 0xF96F, + 0x9D73, 0xF970, 0x9D74, 0xF971, 0x9D75, 0xF972, 0x9D76, 0xF973, 0x9D77, 0xF974, 0x9D78, 0xF975, 0x9D79, 0xF976, 0x9D7A, 0xF977, + 0x9D7B, 0xF978, 0x9D7C, 0xF979, 0x9D7D, 0xF97A, 0x9D7E, 0xF97B, 0x9D7F, 0xF97C, 0x9D80, 0xF97D, 0x9D81, 0xF97E, 0x9D82, 0xF980, + 0x9D83, 0xF981, 0x9D84, 0xF982, 0x9D85, 0xF983, 0x9D86, 0xF984, 0x9D87, 0xF985, 0x9D88, 0xF986, 0x9D89, 0xF987, 0x9D8A, 0xF988, + 0x9D8B, 0xF989, 0x9D8C, 0xF98A, 0x9D8D, 0xF98B, 0x9D8E, 0xF98C, 0x9D8F, 0xF98D, 0x9D90, 0xF98E, 0x9D91, 0xF98F, 0x9D92, 0xF990, + 0x9D93, 0xF991, 0x9D94, 0xF992, 0x9D95, 0xF993, 0x9D96, 0xF994, 0x9D97, 0xF995, 0x9D98, 0xF996, 0x9D99, 0xF997, 0x9D9A, 0xF998, + 0x9D9B, 0xF999, 0x9D9C, 0xF99A, 0x9D9D, 0xF99B, 0x9D9E, 0xF99C, 0x9D9F, 0xF99D, 0x9DA0, 0xF99E, 0x9DA1, 0xF99F, 0x9DA2, 0xF9A0, + 0x9DA3, 0xFA40, 0x9DA4, 0xFA41, 0x9DA5, 0xFA42, 0x9DA6, 0xFA43, 0x9DA7, 0xFA44, 0x9DA8, 0xFA45, 0x9DA9, 0xFA46, 0x9DAA, 0xFA47, + 0x9DAB, 0xFA48, 0x9DAC, 0xFA49, 0x9DAD, 0xFA4A, 0x9DAE, 0xFA4B, 0x9DAF, 0xFA4C, 0x9DB0, 0xFA4D, 0x9DB1, 0xFA4E, 0x9DB2, 0xFA4F, + 0x9DB3, 0xFA50, 0x9DB4, 0xFA51, 0x9DB5, 0xFA52, 0x9DB6, 0xFA53, 0x9DB7, 0xFA54, 0x9DB8, 0xFA55, 0x9DB9, 0xFA56, 0x9DBA, 0xFA57, + 0x9DBB, 0xFA58, 0x9DBC, 0xFA59, 0x9DBD, 0xFA5A, 0x9DBE, 0xFA5B, 0x9DBF, 0xFA5C, 0x9DC0, 0xFA5D, 0x9DC1, 0xFA5E, 0x9DC2, 0xFA5F, + 0x9DC3, 0xFA60, 0x9DC4, 0xFA61, 0x9DC5, 0xFA62, 0x9DC6, 0xFA63, 0x9DC7, 0xFA64, 0x9DC8, 0xFA65, 0x9DC9, 0xFA66, 0x9DCA, 0xFA67, + 0x9DCB, 0xFA68, 0x9DCC, 0xFA69, 0x9DCD, 0xFA6A, 0x9DCE, 0xFA6B, 0x9DCF, 0xFA6C, 0x9DD0, 0xFA6D, 0x9DD1, 0xFA6E, 0x9DD2, 0xFA6F, + 0x9DD3, 0xFA70, 0x9DD4, 0xFA71, 0x9DD5, 0xFA72, 0x9DD6, 0xFA73, 0x9DD7, 0xFA74, 0x9DD8, 0xFA75, 0x9DD9, 0xFA76, 0x9DDA, 0xFA77, + 0x9DDB, 0xFA78, 0x9DDC, 0xFA79, 0x9DDD, 0xFA7A, 0x9DDE, 0xFA7B, 0x9DDF, 0xFA7C, 0x9DE0, 0xFA7D, 0x9DE1, 0xFA7E, 0x9DE2, 0xFA80, + 0x9DE3, 0xFA81, 0x9DE4, 0xFA82, 0x9DE5, 0xFA83, 0x9DE6, 0xFA84, 0x9DE7, 0xFA85, 0x9DE8, 0xFA86, 0x9DE9, 0xFA87, 0x9DEA, 0xFA88, + 0x9DEB, 0xFA89, 0x9DEC, 0xFA8A, 0x9DED, 0xFA8B, 0x9DEE, 0xFA8C, 0x9DEF, 0xFA8D, 0x9DF0, 0xFA8E, 0x9DF1, 0xFA8F, 0x9DF2, 0xFA90, + 0x9DF3, 0xFA91, 0x9DF4, 0xFA92, 0x9DF5, 0xFA93, 0x9DF6, 0xFA94, 0x9DF7, 0xFA95, 0x9DF8, 0xFA96, 0x9DF9, 0xFA97, 0x9DFA, 0xFA98, + 0x9DFB, 0xFA99, 0x9DFC, 0xFA9A, 0x9DFD, 0xFA9B, 0x9DFE, 0xFA9C, 0x9DFF, 0xFA9D, 0x9E00, 0xFA9E, 0x9E01, 0xFA9F, 0x9E02, 0xFAA0, + 0x9E03, 0xFB40, 0x9E04, 0xFB41, 0x9E05, 0xFB42, 0x9E06, 0xFB43, 0x9E07, 0xFB44, 0x9E08, 0xFB45, 0x9E09, 0xFB46, 0x9E0A, 0xFB47, + 0x9E0B, 0xFB48, 0x9E0C, 0xFB49, 0x9E0D, 0xFB4A, 0x9E0E, 0xFB4B, 0x9E0F, 0xFB4C, 0x9E10, 0xFB4D, 0x9E11, 0xFB4E, 0x9E12, 0xFB4F, + 0x9E13, 0xFB50, 0x9E14, 0xFB51, 0x9E15, 0xFB52, 0x9E16, 0xFB53, 0x9E17, 0xFB54, 0x9E18, 0xFB55, 0x9E19, 0xFB56, 0x9E1A, 0xFB57, + 0x9E1B, 0xFB58, 0x9E1C, 0xFB59, 0x9E1D, 0xFB5A, 0x9E1E, 0xFB5B, 0x9E1F, 0xC4F1, 0x9E20, 0xF0AF, 0x9E21, 0xBCA6, 0x9E22, 0xF0B0, + 0x9E23, 0xC3F9, 0x9E24, 0xFB5C, 0x9E25, 0xC5B8, 0x9E26, 0xD1BB, 0x9E27, 0xFB5D, 0x9E28, 0xF0B1, 0x9E29, 0xF0B2, 0x9E2A, 0xF0B3, + 0x9E2B, 0xF0B4, 0x9E2C, 0xF0B5, 0x9E2D, 0xD1BC, 0x9E2E, 0xFB5E, 0x9E2F, 0xD1EC, 0x9E30, 0xFB5F, 0x9E31, 0xF0B7, 0x9E32, 0xF0B6, + 0x9E33, 0xD4A7, 0x9E34, 0xFB60, 0x9E35, 0xCDD2, 0x9E36, 0xF0B8, 0x9E37, 0xF0BA, 0x9E38, 0xF0B9, 0x9E39, 0xF0BB, 0x9E3A, 0xF0BC, + 0x9E3B, 0xFB61, 0x9E3C, 0xFB62, 0x9E3D, 0xB8EB, 0x9E3E, 0xF0BD, 0x9E3F, 0xBAE8, 0x9E40, 0xFB63, 0x9E41, 0xF0BE, 0x9E42, 0xF0BF, + 0x9E43, 0xBEE9, 0x9E44, 0xF0C0, 0x9E45, 0xB6EC, 0x9E46, 0xF0C1, 0x9E47, 0xF0C2, 0x9E48, 0xF0C3, 0x9E49, 0xF0C4, 0x9E4A, 0xC8B5, + 0x9E4B, 0xF0C5, 0x9E4C, 0xF0C6, 0x9E4D, 0xFB64, 0x9E4E, 0xF0C7, 0x9E4F, 0xC5F4, 0x9E50, 0xFB65, 0x9E51, 0xF0C8, 0x9E52, 0xFB66, + 0x9E53, 0xFB67, 0x9E54, 0xFB68, 0x9E55, 0xF0C9, 0x9E56, 0xFB69, 0x9E57, 0xF0CA, 0x9E58, 0xF7BD, 0x9E59, 0xFB6A, 0x9E5A, 0xF0CB, + 0x9E5B, 0xF0CC, 0x9E5C, 0xF0CD, 0x9E5D, 0xFB6B, 0x9E5E, 0xF0CE, 0x9E5F, 0xFB6C, 0x9E60, 0xFB6D, 0x9E61, 0xFB6E, 0x9E62, 0xFB6F, + 0x9E63, 0xF0CF, 0x9E64, 0xBAD7, 0x9E65, 0xFB70, 0x9E66, 0xF0D0, 0x9E67, 0xF0D1, 0x9E68, 0xF0D2, 0x9E69, 0xF0D3, 0x9E6A, 0xF0D4, + 0x9E6B, 0xF0D5, 0x9E6C, 0xF0D6, 0x9E6D, 0xF0D8, 0x9E6E, 0xFB71, 0x9E6F, 0xFB72, 0x9E70, 0xD3A5, 0x9E71, 0xF0D7, 0x9E72, 0xFB73, + 0x9E73, 0xF0D9, 0x9E74, 0xFB74, 0x9E75, 0xFB75, 0x9E76, 0xFB76, 0x9E77, 0xFB77, 0x9E78, 0xFB78, 0x9E79, 0xFB79, 0x9E7A, 0xFB7A, + 0x9E7B, 0xFB7B, 0x9E7C, 0xFB7C, 0x9E7D, 0xFB7D, 0x9E7E, 0xF5BA, 0x9E7F, 0xC2B9, 0x9E80, 0xFB7E, 0x9E81, 0xFB80, 0x9E82, 0xF7E4, + 0x9E83, 0xFB81, 0x9E84, 0xFB82, 0x9E85, 0xFB83, 0x9E86, 0xFB84, 0x9E87, 0xF7E5, 0x9E88, 0xF7E6, 0x9E89, 0xFB85, 0x9E8A, 0xFB86, + 0x9E8B, 0xF7E7, 0x9E8C, 0xFB87, 0x9E8D, 0xFB88, 0x9E8E, 0xFB89, 0x9E8F, 0xFB8A, 0x9E90, 0xFB8B, 0x9E91, 0xFB8C, 0x9E92, 0xF7E8, + 0x9E93, 0xC2B4, 0x9E94, 0xFB8D, 0x9E95, 0xFB8E, 0x9E96, 0xFB8F, 0x9E97, 0xFB90, 0x9E98, 0xFB91, 0x9E99, 0xFB92, 0x9E9A, 0xFB93, + 0x9E9B, 0xFB94, 0x9E9C, 0xFB95, 0x9E9D, 0xF7EA, 0x9E9E, 0xFB96, 0x9E9F, 0xF7EB, 0x9EA0, 0xFB97, 0x9EA1, 0xFB98, 0x9EA2, 0xFB99, + 0x9EA3, 0xFB9A, 0x9EA4, 0xFB9B, 0x9EA5, 0xFB9C, 0x9EA6, 0xC2F3, 0x9EA7, 0xFB9D, 0x9EA8, 0xFB9E, 0x9EA9, 0xFB9F, 0x9EAA, 0xFBA0, + 0x9EAB, 0xFC40, 0x9EAC, 0xFC41, 0x9EAD, 0xFC42, 0x9EAE, 0xFC43, 0x9EAF, 0xFC44, 0x9EB0, 0xFC45, 0x9EB1, 0xFC46, 0x9EB2, 0xFC47, + 0x9EB3, 0xFC48, 0x9EB4, 0xF4F0, 0x9EB5, 0xFC49, 0x9EB6, 0xFC4A, 0x9EB7, 0xFC4B, 0x9EB8, 0xF4EF, 0x9EB9, 0xFC4C, 0x9EBA, 0xFC4D, + 0x9EBB, 0xC2E9, 0x9EBC, 0xFC4E, 0x9EBD, 0xF7E1, 0x9EBE, 0xF7E2, 0x9EBF, 0xFC4F, 0x9EC0, 0xFC50, 0x9EC1, 0xFC51, 0x9EC2, 0xFC52, + 0x9EC3, 0xFC53, 0x9EC4, 0xBBC6, 0x9EC5, 0xFC54, 0x9EC6, 0xFC55, 0x9EC7, 0xFC56, 0x9EC8, 0xFC57, 0x9EC9, 0xD9E4, 0x9ECA, 0xFC58, + 0x9ECB, 0xFC59, 0x9ECC, 0xFC5A, 0x9ECD, 0xCAF2, 0x9ECE, 0xC0E8, 0x9ECF, 0xF0A4, 0x9ED0, 0xFC5B, 0x9ED1, 0xBADA, 0x9ED2, 0xFC5C, + 0x9ED3, 0xFC5D, 0x9ED4, 0xC7AD, 0x9ED5, 0xFC5E, 0x9ED6, 0xFC5F, 0x9ED7, 0xFC60, 0x9ED8, 0xC4AC, 0x9ED9, 0xFC61, 0x9EDA, 0xFC62, + 0x9EDB, 0xF7EC, 0x9EDC, 0xF7ED, 0x9EDD, 0xF7EE, 0x9EDE, 0xFC63, 0x9EDF, 0xF7F0, 0x9EE0, 0xF7EF, 0x9EE1, 0xFC64, 0x9EE2, 0xF7F1, + 0x9EE3, 0xFC65, 0x9EE4, 0xFC66, 0x9EE5, 0xF7F4, 0x9EE6, 0xFC67, 0x9EE7, 0xF7F3, 0x9EE8, 0xFC68, 0x9EE9, 0xF7F2, 0x9EEA, 0xF7F5, + 0x9EEB, 0xFC69, 0x9EEC, 0xFC6A, 0x9EED, 0xFC6B, 0x9EEE, 0xFC6C, 0x9EEF, 0xF7F6, 0x9EF0, 0xFC6D, 0x9EF1, 0xFC6E, 0x9EF2, 0xFC6F, + 0x9EF3, 0xFC70, 0x9EF4, 0xFC71, 0x9EF5, 0xFC72, 0x9EF6, 0xFC73, 0x9EF7, 0xFC74, 0x9EF8, 0xFC75, 0x9EF9, 0xEDE9, 0x9EFA, 0xFC76, + 0x9EFB, 0xEDEA, 0x9EFC, 0xEDEB, 0x9EFD, 0xFC77, 0x9EFE, 0xF6BC, 0x9EFF, 0xFC78, 0x9F00, 0xFC79, 0x9F01, 0xFC7A, 0x9F02, 0xFC7B, + 0x9F03, 0xFC7C, 0x9F04, 0xFC7D, 0x9F05, 0xFC7E, 0x9F06, 0xFC80, 0x9F07, 0xFC81, 0x9F08, 0xFC82, 0x9F09, 0xFC83, 0x9F0A, 0xFC84, + 0x9F0B, 0xF6BD, 0x9F0C, 0xFC85, 0x9F0D, 0xF6BE, 0x9F0E, 0xB6A6, 0x9F0F, 0xFC86, 0x9F10, 0xD8BE, 0x9F11, 0xFC87, 0x9F12, 0xFC88, + 0x9F13, 0xB9C4, 0x9F14, 0xFC89, 0x9F15, 0xFC8A, 0x9F16, 0xFC8B, 0x9F17, 0xD8BB, 0x9F18, 0xFC8C, 0x9F19, 0xDCB1, 0x9F1A, 0xFC8D, + 0x9F1B, 0xFC8E, 0x9F1C, 0xFC8F, 0x9F1D, 0xFC90, 0x9F1E, 0xFC91, 0x9F1F, 0xFC92, 0x9F20, 0xCAF3, 0x9F21, 0xFC93, 0x9F22, 0xF7F7, + 0x9F23, 0xFC94, 0x9F24, 0xFC95, 0x9F25, 0xFC96, 0x9F26, 0xFC97, 0x9F27, 0xFC98, 0x9F28, 0xFC99, 0x9F29, 0xFC9A, 0x9F2A, 0xFC9B, + 0x9F2B, 0xFC9C, 0x9F2C, 0xF7F8, 0x9F2D, 0xFC9D, 0x9F2E, 0xFC9E, 0x9F2F, 0xF7F9, 0x9F30, 0xFC9F, 0x9F31, 0xFCA0, 0x9F32, 0xFD40, + 0x9F33, 0xFD41, 0x9F34, 0xFD42, 0x9F35, 0xFD43, 0x9F36, 0xFD44, 0x9F37, 0xF7FB, 0x9F38, 0xFD45, 0x9F39, 0xF7FA, 0x9F3A, 0xFD46, + 0x9F3B, 0xB1C7, 0x9F3C, 0xFD47, 0x9F3D, 0xF7FC, 0x9F3E, 0xF7FD, 0x9F3F, 0xFD48, 0x9F40, 0xFD49, 0x9F41, 0xFD4A, 0x9F42, 0xFD4B, + 0x9F43, 0xFD4C, 0x9F44, 0xF7FE, 0x9F45, 0xFD4D, 0x9F46, 0xFD4E, 0x9F47, 0xFD4F, 0x9F48, 0xFD50, 0x9F49, 0xFD51, 0x9F4A, 0xFD52, + 0x9F4B, 0xFD53, 0x9F4C, 0xFD54, 0x9F4D, 0xFD55, 0x9F4E, 0xFD56, 0x9F4F, 0xFD57, 0x9F50, 0xC6EB, 0x9F51, 0xECB4, 0x9F52, 0xFD58, + 0x9F53, 0xFD59, 0x9F54, 0xFD5A, 0x9F55, 0xFD5B, 0x9F56, 0xFD5C, 0x9F57, 0xFD5D, 0x9F58, 0xFD5E, 0x9F59, 0xFD5F, 0x9F5A, 0xFD60, + 0x9F5B, 0xFD61, 0x9F5C, 0xFD62, 0x9F5D, 0xFD63, 0x9F5E, 0xFD64, 0x9F5F, 0xFD65, 0x9F60, 0xFD66, 0x9F61, 0xFD67, 0x9F62, 0xFD68, + 0x9F63, 0xFD69, 0x9F64, 0xFD6A, 0x9F65, 0xFD6B, 0x9F66, 0xFD6C, 0x9F67, 0xFD6D, 0x9F68, 0xFD6E, 0x9F69, 0xFD6F, 0x9F6A, 0xFD70, + 0x9F6B, 0xFD71, 0x9F6C, 0xFD72, 0x9F6D, 0xFD73, 0x9F6E, 0xFD74, 0x9F6F, 0xFD75, 0x9F70, 0xFD76, 0x9F71, 0xFD77, 0x9F72, 0xFD78, + 0x9F73, 0xFD79, 0x9F74, 0xFD7A, 0x9F75, 0xFD7B, 0x9F76, 0xFD7C, 0x9F77, 0xFD7D, 0x9F78, 0xFD7E, 0x9F79, 0xFD80, 0x9F7A, 0xFD81, + 0x9F7B, 0xFD82, 0x9F7C, 0xFD83, 0x9F7D, 0xFD84, 0x9F7E, 0xFD85, 0x9F7F, 0xB3DD, 0x9F80, 0xF6B3, 0x9F81, 0xFD86, 0x9F82, 0xFD87, + 0x9F83, 0xF6B4, 0x9F84, 0xC1E4, 0x9F85, 0xF6B5, 0x9F86, 0xF6B6, 0x9F87, 0xF6B7, 0x9F88, 0xF6B8, 0x9F89, 0xF6B9, 0x9F8A, 0xF6BA, + 0x9F8B, 0xC8A3, 0x9F8C, 0xF6BB, 0x9F8D, 0xFD88, 0x9F8E, 0xFD89, 0x9F8F, 0xFD8A, 0x9F90, 0xFD8B, 0x9F91, 0xFD8C, 0x9F92, 0xFD8D, + 0x9F93, 0xFD8E, 0x9F94, 0xFD8F, 0x9F95, 0xFD90, 0x9F96, 0xFD91, 0x9F97, 0xFD92, 0x9F98, 0xFD93, 0x9F99, 0xC1FA, 0x9F9A, 0xB9A8, + 0x9F9B, 0xEDE8, 0x9F9C, 0xFD94, 0x9F9D, 0xFD95, 0x9F9E, 0xFD96, 0x9F9F, 0xB9EA, 0x9FA0, 0xD9DF, 0x9FA1, 0xFD97, 0x9FA2, 0xFD98, + 0x9FA3, 0xFD99, 0x9FA4, 0xFD9A, 0x9FA5, 0xFD9B, 0xF92C, 0xFD9C, 0xF979, 0xFD9D, 0xF995, 0xFD9E, 0xF9E7, 0xFD9F, 0xF9F1, 0xFDA0, + 0xFA0C, 0xFE40, 0xFA0D, 0xFE41, 0xFA0E, 0xFE42, 0xFA0F, 0xFE43, 0xFA11, 0xFE44, 0xFA13, 0xFE45, 0xFA14, 0xFE46, 0xFA18, 0xFE47, + 0xFA1F, 0xFE48, 0xFA20, 0xFE49, 0xFA21, 0xFE4A, 0xFA23, 0xFE4B, 0xFA24, 0xFE4C, 0xFA27, 0xFE4D, 0xFA28, 0xFE4E, 0xFA29, 0xFE4F, + 0xFE30, 0xA955, 0xFE31, 0xA6F2, 0xFE33, 0xA6F4, 0xFE34, 0xA6F5, 0xFE35, 0xA6E0, 0xFE36, 0xA6E1, 0xFE37, 0xA6F0, 0xFE38, 0xA6F1, + 0xFE39, 0xA6E2, 0xFE3A, 0xA6E3, 0xFE3B, 0xA6EE, 0xFE3C, 0xA6EF, 0xFE3D, 0xA6E6, 0xFE3E, 0xA6E7, 0xFE3F, 0xA6E4, 0xFE40, 0xA6E5, + 0xFE41, 0xA6E8, 0xFE42, 0xA6E9, 0xFE43, 0xA6EA, 0xFE44, 0xA6EB, 0xFE49, 0xA968, 0xFE4A, 0xA969, 0xFE4B, 0xA96A, 0xFE4C, 0xA96B, + 0xFE4D, 0xA96C, 0xFE4E, 0xA96D, 0xFE4F, 0xA96E, 0xFE50, 0xA96F, 0xFE51, 0xA970, 0xFE52, 0xA971, 0xFE54, 0xA972, 0xFE55, 0xA973, + 0xFE56, 0xA974, 0xFE57, 0xA975, 0xFE59, 0xA976, 0xFE5A, 0xA977, 0xFE5B, 0xA978, 0xFE5C, 0xA979, 0xFE5D, 0xA97A, 0xFE5E, 0xA97B, + 0xFE5F, 0xA97C, 0xFE60, 0xA97D, 0xFE61, 0xA97E, 0xFE62, 0xA980, 0xFE63, 0xA981, 0xFE64, 0xA982, 0xFE65, 0xA983, 0xFE66, 0xA984, + 0xFE68, 0xA985, 0xFE69, 0xA986, 0xFE6A, 0xA987, 0xFE6B, 0xA988, 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA1E7, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA3DC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA1AB, 0xFFE0, 0xA1E9, 0xFFE1, 0xA1EA, 0xFFE2, 0xA956, 0xFFE3, 0xA3FE, 0xFFE4, 0xA957, 0xFFE5, 0xA3A4, + 0, 0 +}; + +static const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */ + 0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17, + 0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F, + 0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42, + 0x8157, 0x4E44, 0x8158, 0x4E46, 0x8159, 0x4E4A, 0x815A, 0x4E51, 0x815B, 0x4E55, 0x815C, 0x4E57, 0x815D, 0x4E5A, 0x815E, 0x4E5B, + 0x815F, 0x4E62, 0x8160, 0x4E63, 0x8161, 0x4E64, 0x8162, 0x4E65, 0x8163, 0x4E67, 0x8164, 0x4E68, 0x8165, 0x4E6A, 0x8166, 0x4E6B, + 0x8167, 0x4E6C, 0x8168, 0x4E6D, 0x8169, 0x4E6E, 0x816A, 0x4E6F, 0x816B, 0x4E72, 0x816C, 0x4E74, 0x816D, 0x4E75, 0x816E, 0x4E76, + 0x816F, 0x4E77, 0x8170, 0x4E78, 0x8171, 0x4E79, 0x8172, 0x4E7A, 0x8173, 0x4E7B, 0x8174, 0x4E7C, 0x8175, 0x4E7D, 0x8176, 0x4E7F, + 0x8177, 0x4E80, 0x8178, 0x4E81, 0x8179, 0x4E82, 0x817A, 0x4E83, 0x817B, 0x4E84, 0x817C, 0x4E85, 0x817D, 0x4E87, 0x817E, 0x4E8A, + 0x8180, 0x4E90, 0x8181, 0x4E96, 0x8182, 0x4E97, 0x8183, 0x4E99, 0x8184, 0x4E9C, 0x8185, 0x4E9D, 0x8186, 0x4E9E, 0x8187, 0x4EA3, + 0x8188, 0x4EAA, 0x8189, 0x4EAF, 0x818A, 0x4EB0, 0x818B, 0x4EB1, 0x818C, 0x4EB4, 0x818D, 0x4EB6, 0x818E, 0x4EB7, 0x818F, 0x4EB8, + 0x8190, 0x4EB9, 0x8191, 0x4EBC, 0x8192, 0x4EBD, 0x8193, 0x4EBE, 0x8194, 0x4EC8, 0x8195, 0x4ECC, 0x8196, 0x4ECF, 0x8197, 0x4ED0, + 0x8198, 0x4ED2, 0x8199, 0x4EDA, 0x819A, 0x4EDB, 0x819B, 0x4EDC, 0x819C, 0x4EE0, 0x819D, 0x4EE2, 0x819E, 0x4EE6, 0x819F, 0x4EE7, + 0x81A0, 0x4EE9, 0x81A1, 0x4EED, 0x81A2, 0x4EEE, 0x81A3, 0x4EEF, 0x81A4, 0x4EF1, 0x81A5, 0x4EF4, 0x81A6, 0x4EF8, 0x81A7, 0x4EF9, + 0x81A8, 0x4EFA, 0x81A9, 0x4EFC, 0x81AA, 0x4EFE, 0x81AB, 0x4F00, 0x81AC, 0x4F02, 0x81AD, 0x4F03, 0x81AE, 0x4F04, 0x81AF, 0x4F05, + 0x81B0, 0x4F06, 0x81B1, 0x4F07, 0x81B2, 0x4F08, 0x81B3, 0x4F0B, 0x81B4, 0x4F0C, 0x81B5, 0x4F12, 0x81B6, 0x4F13, 0x81B7, 0x4F14, + 0x81B8, 0x4F15, 0x81B9, 0x4F16, 0x81BA, 0x4F1C, 0x81BB, 0x4F1D, 0x81BC, 0x4F21, 0x81BD, 0x4F23, 0x81BE, 0x4F28, 0x81BF, 0x4F29, + 0x81C0, 0x4F2C, 0x81C1, 0x4F2D, 0x81C2, 0x4F2E, 0x81C3, 0x4F31, 0x81C4, 0x4F33, 0x81C5, 0x4F35, 0x81C6, 0x4F37, 0x81C7, 0x4F39, + 0x81C8, 0x4F3B, 0x81C9, 0x4F3E, 0x81CA, 0x4F3F, 0x81CB, 0x4F40, 0x81CC, 0x4F41, 0x81CD, 0x4F42, 0x81CE, 0x4F44, 0x81CF, 0x4F45, + 0x81D0, 0x4F47, 0x81D1, 0x4F48, 0x81D2, 0x4F49, 0x81D3, 0x4F4A, 0x81D4, 0x4F4B, 0x81D5, 0x4F4C, 0x81D6, 0x4F52, 0x81D7, 0x4F54, + 0x81D8, 0x4F56, 0x81D9, 0x4F61, 0x81DA, 0x4F62, 0x81DB, 0x4F66, 0x81DC, 0x4F68, 0x81DD, 0x4F6A, 0x81DE, 0x4F6B, 0x81DF, 0x4F6D, + 0x81E0, 0x4F6E, 0x81E1, 0x4F71, 0x81E2, 0x4F72, 0x81E3, 0x4F75, 0x81E4, 0x4F77, 0x81E5, 0x4F78, 0x81E6, 0x4F79, 0x81E7, 0x4F7A, + 0x81E8, 0x4F7D, 0x81E9, 0x4F80, 0x81EA, 0x4F81, 0x81EB, 0x4F82, 0x81EC, 0x4F85, 0x81ED, 0x4F86, 0x81EE, 0x4F87, 0x81EF, 0x4F8A, + 0x81F0, 0x4F8C, 0x81F1, 0x4F8E, 0x81F2, 0x4F90, 0x81F3, 0x4F92, 0x81F4, 0x4F93, 0x81F5, 0x4F95, 0x81F6, 0x4F96, 0x81F7, 0x4F98, + 0x81F8, 0x4F99, 0x81F9, 0x4F9A, 0x81FA, 0x4F9C, 0x81FB, 0x4F9E, 0x81FC, 0x4F9F, 0x81FD, 0x4FA1, 0x81FE, 0x4FA2, 0x8240, 0x4FA4, + 0x8241, 0x4FAB, 0x8242, 0x4FAD, 0x8243, 0x4FB0, 0x8244, 0x4FB1, 0x8245, 0x4FB2, 0x8246, 0x4FB3, 0x8247, 0x4FB4, 0x8248, 0x4FB6, + 0x8249, 0x4FB7, 0x824A, 0x4FB8, 0x824B, 0x4FB9, 0x824C, 0x4FBA, 0x824D, 0x4FBB, 0x824E, 0x4FBC, 0x824F, 0x4FBD, 0x8250, 0x4FBE, + 0x8251, 0x4FC0, 0x8252, 0x4FC1, 0x8253, 0x4FC2, 0x8254, 0x4FC6, 0x8255, 0x4FC7, 0x8256, 0x4FC8, 0x8257, 0x4FC9, 0x8258, 0x4FCB, + 0x8259, 0x4FCC, 0x825A, 0x4FCD, 0x825B, 0x4FD2, 0x825C, 0x4FD3, 0x825D, 0x4FD4, 0x825E, 0x4FD5, 0x825F, 0x4FD6, 0x8260, 0x4FD9, + 0x8261, 0x4FDB, 0x8262, 0x4FE0, 0x8263, 0x4FE2, 0x8264, 0x4FE4, 0x8265, 0x4FE5, 0x8266, 0x4FE7, 0x8267, 0x4FEB, 0x8268, 0x4FEC, + 0x8269, 0x4FF0, 0x826A, 0x4FF2, 0x826B, 0x4FF4, 0x826C, 0x4FF5, 0x826D, 0x4FF6, 0x826E, 0x4FF7, 0x826F, 0x4FF9, 0x8270, 0x4FFB, + 0x8271, 0x4FFC, 0x8272, 0x4FFD, 0x8273, 0x4FFF, 0x8274, 0x5000, 0x8275, 0x5001, 0x8276, 0x5002, 0x8277, 0x5003, 0x8278, 0x5004, + 0x8279, 0x5005, 0x827A, 0x5006, 0x827B, 0x5007, 0x827C, 0x5008, 0x827D, 0x5009, 0x827E, 0x500A, 0x8280, 0x500B, 0x8281, 0x500E, + 0x8282, 0x5010, 0x8283, 0x5011, 0x8284, 0x5013, 0x8285, 0x5015, 0x8286, 0x5016, 0x8287, 0x5017, 0x8288, 0x501B, 0x8289, 0x501D, + 0x828A, 0x501E, 0x828B, 0x5020, 0x828C, 0x5022, 0x828D, 0x5023, 0x828E, 0x5024, 0x828F, 0x5027, 0x8290, 0x502B, 0x8291, 0x502F, + 0x8292, 0x5030, 0x8293, 0x5031, 0x8294, 0x5032, 0x8295, 0x5033, 0x8296, 0x5034, 0x8297, 0x5035, 0x8298, 0x5036, 0x8299, 0x5037, + 0x829A, 0x5038, 0x829B, 0x5039, 0x829C, 0x503B, 0x829D, 0x503D, 0x829E, 0x503F, 0x829F, 0x5040, 0x82A0, 0x5041, 0x82A1, 0x5042, + 0x82A2, 0x5044, 0x82A3, 0x5045, 0x82A4, 0x5046, 0x82A5, 0x5049, 0x82A6, 0x504A, 0x82A7, 0x504B, 0x82A8, 0x504D, 0x82A9, 0x5050, + 0x82AA, 0x5051, 0x82AB, 0x5052, 0x82AC, 0x5053, 0x82AD, 0x5054, 0x82AE, 0x5056, 0x82AF, 0x5057, 0x82B0, 0x5058, 0x82B1, 0x5059, + 0x82B2, 0x505B, 0x82B3, 0x505D, 0x82B4, 0x505E, 0x82B5, 0x505F, 0x82B6, 0x5060, 0x82B7, 0x5061, 0x82B8, 0x5062, 0x82B9, 0x5063, + 0x82BA, 0x5064, 0x82BB, 0x5066, 0x82BC, 0x5067, 0x82BD, 0x5068, 0x82BE, 0x5069, 0x82BF, 0x506A, 0x82C0, 0x506B, 0x82C1, 0x506D, + 0x82C2, 0x506E, 0x82C3, 0x506F, 0x82C4, 0x5070, 0x82C5, 0x5071, 0x82C6, 0x5072, 0x82C7, 0x5073, 0x82C8, 0x5074, 0x82C9, 0x5075, + 0x82CA, 0x5078, 0x82CB, 0x5079, 0x82CC, 0x507A, 0x82CD, 0x507C, 0x82CE, 0x507D, 0x82CF, 0x5081, 0x82D0, 0x5082, 0x82D1, 0x5083, + 0x82D2, 0x5084, 0x82D3, 0x5086, 0x82D4, 0x5087, 0x82D5, 0x5089, 0x82D6, 0x508A, 0x82D7, 0x508B, 0x82D8, 0x508C, 0x82D9, 0x508E, + 0x82DA, 0x508F, 0x82DB, 0x5090, 0x82DC, 0x5091, 0x82DD, 0x5092, 0x82DE, 0x5093, 0x82DF, 0x5094, 0x82E0, 0x5095, 0x82E1, 0x5096, + 0x82E2, 0x5097, 0x82E3, 0x5098, 0x82E4, 0x5099, 0x82E5, 0x509A, 0x82E6, 0x509B, 0x82E7, 0x509C, 0x82E8, 0x509D, 0x82E9, 0x509E, + 0x82EA, 0x509F, 0x82EB, 0x50A0, 0x82EC, 0x50A1, 0x82ED, 0x50A2, 0x82EE, 0x50A4, 0x82EF, 0x50A6, 0x82F0, 0x50AA, 0x82F1, 0x50AB, + 0x82F2, 0x50AD, 0x82F3, 0x50AE, 0x82F4, 0x50AF, 0x82F5, 0x50B0, 0x82F6, 0x50B1, 0x82F7, 0x50B3, 0x82F8, 0x50B4, 0x82F9, 0x50B5, + 0x82FA, 0x50B6, 0x82FB, 0x50B7, 0x82FC, 0x50B8, 0x82FD, 0x50B9, 0x82FE, 0x50BC, 0x8340, 0x50BD, 0x8341, 0x50BE, 0x8342, 0x50BF, + 0x8343, 0x50C0, 0x8344, 0x50C1, 0x8345, 0x50C2, 0x8346, 0x50C3, 0x8347, 0x50C4, 0x8348, 0x50C5, 0x8349, 0x50C6, 0x834A, 0x50C7, + 0x834B, 0x50C8, 0x834C, 0x50C9, 0x834D, 0x50CA, 0x834E, 0x50CB, 0x834F, 0x50CC, 0x8350, 0x50CD, 0x8351, 0x50CE, 0x8352, 0x50D0, + 0x8353, 0x50D1, 0x8354, 0x50D2, 0x8355, 0x50D3, 0x8356, 0x50D4, 0x8357, 0x50D5, 0x8358, 0x50D7, 0x8359, 0x50D8, 0x835A, 0x50D9, + 0x835B, 0x50DB, 0x835C, 0x50DC, 0x835D, 0x50DD, 0x835E, 0x50DE, 0x835F, 0x50DF, 0x8360, 0x50E0, 0x8361, 0x50E1, 0x8362, 0x50E2, + 0x8363, 0x50E3, 0x8364, 0x50E4, 0x8365, 0x50E5, 0x8366, 0x50E8, 0x8367, 0x50E9, 0x8368, 0x50EA, 0x8369, 0x50EB, 0x836A, 0x50EF, + 0x836B, 0x50F0, 0x836C, 0x50F1, 0x836D, 0x50F2, 0x836E, 0x50F4, 0x836F, 0x50F6, 0x8370, 0x50F7, 0x8371, 0x50F8, 0x8372, 0x50F9, + 0x8373, 0x50FA, 0x8374, 0x50FC, 0x8375, 0x50FD, 0x8376, 0x50FE, 0x8377, 0x50FF, 0x8378, 0x5100, 0x8379, 0x5101, 0x837A, 0x5102, + 0x837B, 0x5103, 0x837C, 0x5104, 0x837D, 0x5105, 0x837E, 0x5108, 0x8380, 0x5109, 0x8381, 0x510A, 0x8382, 0x510C, 0x8383, 0x510D, + 0x8384, 0x510E, 0x8385, 0x510F, 0x8386, 0x5110, 0x8387, 0x5111, 0x8388, 0x5113, 0x8389, 0x5114, 0x838A, 0x5115, 0x838B, 0x5116, + 0x838C, 0x5117, 0x838D, 0x5118, 0x838E, 0x5119, 0x838F, 0x511A, 0x8390, 0x511B, 0x8391, 0x511C, 0x8392, 0x511D, 0x8393, 0x511E, + 0x8394, 0x511F, 0x8395, 0x5120, 0x8396, 0x5122, 0x8397, 0x5123, 0x8398, 0x5124, 0x8399, 0x5125, 0x839A, 0x5126, 0x839B, 0x5127, + 0x839C, 0x5128, 0x839D, 0x5129, 0x839E, 0x512A, 0x839F, 0x512B, 0x83A0, 0x512C, 0x83A1, 0x512D, 0x83A2, 0x512E, 0x83A3, 0x512F, + 0x83A4, 0x5130, 0x83A5, 0x5131, 0x83A6, 0x5132, 0x83A7, 0x5133, 0x83A8, 0x5134, 0x83A9, 0x5135, 0x83AA, 0x5136, 0x83AB, 0x5137, + 0x83AC, 0x5138, 0x83AD, 0x5139, 0x83AE, 0x513A, 0x83AF, 0x513B, 0x83B0, 0x513C, 0x83B1, 0x513D, 0x83B2, 0x513E, 0x83B3, 0x5142, + 0x83B4, 0x5147, 0x83B5, 0x514A, 0x83B6, 0x514C, 0x83B7, 0x514E, 0x83B8, 0x514F, 0x83B9, 0x5150, 0x83BA, 0x5152, 0x83BB, 0x5153, + 0x83BC, 0x5157, 0x83BD, 0x5158, 0x83BE, 0x5159, 0x83BF, 0x515B, 0x83C0, 0x515D, 0x83C1, 0x515E, 0x83C2, 0x515F, 0x83C3, 0x5160, + 0x83C4, 0x5161, 0x83C5, 0x5163, 0x83C6, 0x5164, 0x83C7, 0x5166, 0x83C8, 0x5167, 0x83C9, 0x5169, 0x83CA, 0x516A, 0x83CB, 0x516F, + 0x83CC, 0x5172, 0x83CD, 0x517A, 0x83CE, 0x517E, 0x83CF, 0x517F, 0x83D0, 0x5183, 0x83D1, 0x5184, 0x83D2, 0x5186, 0x83D3, 0x5187, + 0x83D4, 0x518A, 0x83D5, 0x518B, 0x83D6, 0x518E, 0x83D7, 0x518F, 0x83D8, 0x5190, 0x83D9, 0x5191, 0x83DA, 0x5193, 0x83DB, 0x5194, + 0x83DC, 0x5198, 0x83DD, 0x519A, 0x83DE, 0x519D, 0x83DF, 0x519E, 0x83E0, 0x519F, 0x83E1, 0x51A1, 0x83E2, 0x51A3, 0x83E3, 0x51A6, + 0x83E4, 0x51A7, 0x83E5, 0x51A8, 0x83E6, 0x51A9, 0x83E7, 0x51AA, 0x83E8, 0x51AD, 0x83E9, 0x51AE, 0x83EA, 0x51B4, 0x83EB, 0x51B8, + 0x83EC, 0x51B9, 0x83ED, 0x51BA, 0x83EE, 0x51BE, 0x83EF, 0x51BF, 0x83F0, 0x51C1, 0x83F1, 0x51C2, 0x83F2, 0x51C3, 0x83F3, 0x51C5, + 0x83F4, 0x51C8, 0x83F5, 0x51CA, 0x83F6, 0x51CD, 0x83F7, 0x51CE, 0x83F8, 0x51D0, 0x83F9, 0x51D2, 0x83FA, 0x51D3, 0x83FB, 0x51D4, + 0x83FC, 0x51D5, 0x83FD, 0x51D6, 0x83FE, 0x51D7, 0x8440, 0x51D8, 0x8441, 0x51D9, 0x8442, 0x51DA, 0x8443, 0x51DC, 0x8444, 0x51DE, + 0x8445, 0x51DF, 0x8446, 0x51E2, 0x8447, 0x51E3, 0x8448, 0x51E5, 0x8449, 0x51E6, 0x844A, 0x51E7, 0x844B, 0x51E8, 0x844C, 0x51E9, + 0x844D, 0x51EA, 0x844E, 0x51EC, 0x844F, 0x51EE, 0x8450, 0x51F1, 0x8451, 0x51F2, 0x8452, 0x51F4, 0x8453, 0x51F7, 0x8454, 0x51FE, + 0x8455, 0x5204, 0x8456, 0x5205, 0x8457, 0x5209, 0x8458, 0x520B, 0x8459, 0x520C, 0x845A, 0x520F, 0x845B, 0x5210, 0x845C, 0x5213, + 0x845D, 0x5214, 0x845E, 0x5215, 0x845F, 0x521C, 0x8460, 0x521E, 0x8461, 0x521F, 0x8462, 0x5221, 0x8463, 0x5222, 0x8464, 0x5223, + 0x8465, 0x5225, 0x8466, 0x5226, 0x8467, 0x5227, 0x8468, 0x522A, 0x8469, 0x522C, 0x846A, 0x522F, 0x846B, 0x5231, 0x846C, 0x5232, + 0x846D, 0x5234, 0x846E, 0x5235, 0x846F, 0x523C, 0x8470, 0x523E, 0x8471, 0x5244, 0x8472, 0x5245, 0x8473, 0x5246, 0x8474, 0x5247, + 0x8475, 0x5248, 0x8476, 0x5249, 0x8477, 0x524B, 0x8478, 0x524E, 0x8479, 0x524F, 0x847A, 0x5252, 0x847B, 0x5253, 0x847C, 0x5255, + 0x847D, 0x5257, 0x847E, 0x5258, 0x8480, 0x5259, 0x8481, 0x525A, 0x8482, 0x525B, 0x8483, 0x525D, 0x8484, 0x525F, 0x8485, 0x5260, + 0x8486, 0x5262, 0x8487, 0x5263, 0x8488, 0x5264, 0x8489, 0x5266, 0x848A, 0x5268, 0x848B, 0x526B, 0x848C, 0x526C, 0x848D, 0x526D, + 0x848E, 0x526E, 0x848F, 0x5270, 0x8490, 0x5271, 0x8491, 0x5273, 0x8492, 0x5274, 0x8493, 0x5275, 0x8494, 0x5276, 0x8495, 0x5277, + 0x8496, 0x5278, 0x8497, 0x5279, 0x8498, 0x527A, 0x8499, 0x527B, 0x849A, 0x527C, 0x849B, 0x527E, 0x849C, 0x5280, 0x849D, 0x5283, + 0x849E, 0x5284, 0x849F, 0x5285, 0x84A0, 0x5286, 0x84A1, 0x5287, 0x84A2, 0x5289, 0x84A3, 0x528A, 0x84A4, 0x528B, 0x84A5, 0x528C, + 0x84A6, 0x528D, 0x84A7, 0x528E, 0x84A8, 0x528F, 0x84A9, 0x5291, 0x84AA, 0x5292, 0x84AB, 0x5294, 0x84AC, 0x5295, 0x84AD, 0x5296, + 0x84AE, 0x5297, 0x84AF, 0x5298, 0x84B0, 0x5299, 0x84B1, 0x529A, 0x84B2, 0x529C, 0x84B3, 0x52A4, 0x84B4, 0x52A5, 0x84B5, 0x52A6, + 0x84B6, 0x52A7, 0x84B7, 0x52AE, 0x84B8, 0x52AF, 0x84B9, 0x52B0, 0x84BA, 0x52B4, 0x84BB, 0x52B5, 0x84BC, 0x52B6, 0x84BD, 0x52B7, + 0x84BE, 0x52B8, 0x84BF, 0x52B9, 0x84C0, 0x52BA, 0x84C1, 0x52BB, 0x84C2, 0x52BC, 0x84C3, 0x52BD, 0x84C4, 0x52C0, 0x84C5, 0x52C1, + 0x84C6, 0x52C2, 0x84C7, 0x52C4, 0x84C8, 0x52C5, 0x84C9, 0x52C6, 0x84CA, 0x52C8, 0x84CB, 0x52CA, 0x84CC, 0x52CC, 0x84CD, 0x52CD, + 0x84CE, 0x52CE, 0x84CF, 0x52CF, 0x84D0, 0x52D1, 0x84D1, 0x52D3, 0x84D2, 0x52D4, 0x84D3, 0x52D5, 0x84D4, 0x52D7, 0x84D5, 0x52D9, + 0x84D6, 0x52DA, 0x84D7, 0x52DB, 0x84D8, 0x52DC, 0x84D9, 0x52DD, 0x84DA, 0x52DE, 0x84DB, 0x52E0, 0x84DC, 0x52E1, 0x84DD, 0x52E2, + 0x84DE, 0x52E3, 0x84DF, 0x52E5, 0x84E0, 0x52E6, 0x84E1, 0x52E7, 0x84E2, 0x52E8, 0x84E3, 0x52E9, 0x84E4, 0x52EA, 0x84E5, 0x52EB, + 0x84E6, 0x52EC, 0x84E7, 0x52ED, 0x84E8, 0x52EE, 0x84E9, 0x52EF, 0x84EA, 0x52F1, 0x84EB, 0x52F2, 0x84EC, 0x52F3, 0x84ED, 0x52F4, + 0x84EE, 0x52F5, 0x84EF, 0x52F6, 0x84F0, 0x52F7, 0x84F1, 0x52F8, 0x84F2, 0x52FB, 0x84F3, 0x52FC, 0x84F4, 0x52FD, 0x84F5, 0x5301, + 0x84F6, 0x5302, 0x84F7, 0x5303, 0x84F8, 0x5304, 0x84F9, 0x5307, 0x84FA, 0x5309, 0x84FB, 0x530A, 0x84FC, 0x530B, 0x84FD, 0x530C, + 0x84FE, 0x530E, 0x8540, 0x5311, 0x8541, 0x5312, 0x8542, 0x5313, 0x8543, 0x5314, 0x8544, 0x5318, 0x8545, 0x531B, 0x8546, 0x531C, + 0x8547, 0x531E, 0x8548, 0x531F, 0x8549, 0x5322, 0x854A, 0x5324, 0x854B, 0x5325, 0x854C, 0x5327, 0x854D, 0x5328, 0x854E, 0x5329, + 0x854F, 0x532B, 0x8550, 0x532C, 0x8551, 0x532D, 0x8552, 0x532F, 0x8553, 0x5330, 0x8554, 0x5331, 0x8555, 0x5332, 0x8556, 0x5333, + 0x8557, 0x5334, 0x8558, 0x5335, 0x8559, 0x5336, 0x855A, 0x5337, 0x855B, 0x5338, 0x855C, 0x533C, 0x855D, 0x533D, 0x855E, 0x5340, + 0x855F, 0x5342, 0x8560, 0x5344, 0x8561, 0x5346, 0x8562, 0x534B, 0x8563, 0x534C, 0x8564, 0x534D, 0x8565, 0x5350, 0x8566, 0x5354, + 0x8567, 0x5358, 0x8568, 0x5359, 0x8569, 0x535B, 0x856A, 0x535D, 0x856B, 0x5365, 0x856C, 0x5368, 0x856D, 0x536A, 0x856E, 0x536C, + 0x856F, 0x536D, 0x8570, 0x5372, 0x8571, 0x5376, 0x8572, 0x5379, 0x8573, 0x537B, 0x8574, 0x537C, 0x8575, 0x537D, 0x8576, 0x537E, + 0x8577, 0x5380, 0x8578, 0x5381, 0x8579, 0x5383, 0x857A, 0x5387, 0x857B, 0x5388, 0x857C, 0x538A, 0x857D, 0x538E, 0x857E, 0x538F, + 0x8580, 0x5390, 0x8581, 0x5391, 0x8582, 0x5392, 0x8583, 0x5393, 0x8584, 0x5394, 0x8585, 0x5396, 0x8586, 0x5397, 0x8587, 0x5399, + 0x8588, 0x539B, 0x8589, 0x539C, 0x858A, 0x539E, 0x858B, 0x53A0, 0x858C, 0x53A1, 0x858D, 0x53A4, 0x858E, 0x53A7, 0x858F, 0x53AA, + 0x8590, 0x53AB, 0x8591, 0x53AC, 0x8592, 0x53AD, 0x8593, 0x53AF, 0x8594, 0x53B0, 0x8595, 0x53B1, 0x8596, 0x53B2, 0x8597, 0x53B3, + 0x8598, 0x53B4, 0x8599, 0x53B5, 0x859A, 0x53B7, 0x859B, 0x53B8, 0x859C, 0x53B9, 0x859D, 0x53BA, 0x859E, 0x53BC, 0x859F, 0x53BD, + 0x85A0, 0x53BE, 0x85A1, 0x53C0, 0x85A2, 0x53C3, 0x85A3, 0x53C4, 0x85A4, 0x53C5, 0x85A5, 0x53C6, 0x85A6, 0x53C7, 0x85A7, 0x53CE, + 0x85A8, 0x53CF, 0x85A9, 0x53D0, 0x85AA, 0x53D2, 0x85AB, 0x53D3, 0x85AC, 0x53D5, 0x85AD, 0x53DA, 0x85AE, 0x53DC, 0x85AF, 0x53DD, + 0x85B0, 0x53DE, 0x85B1, 0x53E1, 0x85B2, 0x53E2, 0x85B3, 0x53E7, 0x85B4, 0x53F4, 0x85B5, 0x53FA, 0x85B6, 0x53FE, 0x85B7, 0x53FF, + 0x85B8, 0x5400, 0x85B9, 0x5402, 0x85BA, 0x5405, 0x85BB, 0x5407, 0x85BC, 0x540B, 0x85BD, 0x5414, 0x85BE, 0x5418, 0x85BF, 0x5419, + 0x85C0, 0x541A, 0x85C1, 0x541C, 0x85C2, 0x5422, 0x85C3, 0x5424, 0x85C4, 0x5425, 0x85C5, 0x542A, 0x85C6, 0x5430, 0x85C7, 0x5433, + 0x85C8, 0x5436, 0x85C9, 0x5437, 0x85CA, 0x543A, 0x85CB, 0x543D, 0x85CC, 0x543F, 0x85CD, 0x5441, 0x85CE, 0x5442, 0x85CF, 0x5444, + 0x85D0, 0x5445, 0x85D1, 0x5447, 0x85D2, 0x5449, 0x85D3, 0x544C, 0x85D4, 0x544D, 0x85D5, 0x544E, 0x85D6, 0x544F, 0x85D7, 0x5451, + 0x85D8, 0x545A, 0x85D9, 0x545D, 0x85DA, 0x545E, 0x85DB, 0x545F, 0x85DC, 0x5460, 0x85DD, 0x5461, 0x85DE, 0x5463, 0x85DF, 0x5465, + 0x85E0, 0x5467, 0x85E1, 0x5469, 0x85E2, 0x546A, 0x85E3, 0x546B, 0x85E4, 0x546C, 0x85E5, 0x546D, 0x85E6, 0x546E, 0x85E7, 0x546F, + 0x85E8, 0x5470, 0x85E9, 0x5474, 0x85EA, 0x5479, 0x85EB, 0x547A, 0x85EC, 0x547E, 0x85ED, 0x547F, 0x85EE, 0x5481, 0x85EF, 0x5483, + 0x85F0, 0x5485, 0x85F1, 0x5487, 0x85F2, 0x5488, 0x85F3, 0x5489, 0x85F4, 0x548A, 0x85F5, 0x548D, 0x85F6, 0x5491, 0x85F7, 0x5493, + 0x85F8, 0x5497, 0x85F9, 0x5498, 0x85FA, 0x549C, 0x85FB, 0x549E, 0x85FC, 0x549F, 0x85FD, 0x54A0, 0x85FE, 0x54A1, 0x8640, 0x54A2, + 0x8641, 0x54A5, 0x8642, 0x54AE, 0x8643, 0x54B0, 0x8644, 0x54B2, 0x8645, 0x54B5, 0x8646, 0x54B6, 0x8647, 0x54B7, 0x8648, 0x54B9, + 0x8649, 0x54BA, 0x864A, 0x54BC, 0x864B, 0x54BE, 0x864C, 0x54C3, 0x864D, 0x54C5, 0x864E, 0x54CA, 0x864F, 0x54CB, 0x8650, 0x54D6, + 0x8651, 0x54D8, 0x8652, 0x54DB, 0x8653, 0x54E0, 0x8654, 0x54E1, 0x8655, 0x54E2, 0x8656, 0x54E3, 0x8657, 0x54E4, 0x8658, 0x54EB, + 0x8659, 0x54EC, 0x865A, 0x54EF, 0x865B, 0x54F0, 0x865C, 0x54F1, 0x865D, 0x54F4, 0x865E, 0x54F5, 0x865F, 0x54F6, 0x8660, 0x54F7, + 0x8661, 0x54F8, 0x8662, 0x54F9, 0x8663, 0x54FB, 0x8664, 0x54FE, 0x8665, 0x5500, 0x8666, 0x5502, 0x8667, 0x5503, 0x8668, 0x5504, + 0x8669, 0x5505, 0x866A, 0x5508, 0x866B, 0x550A, 0x866C, 0x550B, 0x866D, 0x550C, 0x866E, 0x550D, 0x866F, 0x550E, 0x8670, 0x5512, + 0x8671, 0x5513, 0x8672, 0x5515, 0x8673, 0x5516, 0x8674, 0x5517, 0x8675, 0x5518, 0x8676, 0x5519, 0x8677, 0x551A, 0x8678, 0x551C, + 0x8679, 0x551D, 0x867A, 0x551E, 0x867B, 0x551F, 0x867C, 0x5521, 0x867D, 0x5525, 0x867E, 0x5526, 0x8680, 0x5528, 0x8681, 0x5529, + 0x8682, 0x552B, 0x8683, 0x552D, 0x8684, 0x5532, 0x8685, 0x5534, 0x8686, 0x5535, 0x8687, 0x5536, 0x8688, 0x5538, 0x8689, 0x5539, + 0x868A, 0x553A, 0x868B, 0x553B, 0x868C, 0x553D, 0x868D, 0x5540, 0x868E, 0x5542, 0x868F, 0x5545, 0x8690, 0x5547, 0x8691, 0x5548, + 0x8692, 0x554B, 0x8693, 0x554C, 0x8694, 0x554D, 0x8695, 0x554E, 0x8696, 0x554F, 0x8697, 0x5551, 0x8698, 0x5552, 0x8699, 0x5553, + 0x869A, 0x5554, 0x869B, 0x5557, 0x869C, 0x5558, 0x869D, 0x5559, 0x869E, 0x555A, 0x869F, 0x555B, 0x86A0, 0x555D, 0x86A1, 0x555E, + 0x86A2, 0x555F, 0x86A3, 0x5560, 0x86A4, 0x5562, 0x86A5, 0x5563, 0x86A6, 0x5568, 0x86A7, 0x5569, 0x86A8, 0x556B, 0x86A9, 0x556F, + 0x86AA, 0x5570, 0x86AB, 0x5571, 0x86AC, 0x5572, 0x86AD, 0x5573, 0x86AE, 0x5574, 0x86AF, 0x5579, 0x86B0, 0x557A, 0x86B1, 0x557D, + 0x86B2, 0x557F, 0x86B3, 0x5585, 0x86B4, 0x5586, 0x86B5, 0x558C, 0x86B6, 0x558D, 0x86B7, 0x558E, 0x86B8, 0x5590, 0x86B9, 0x5592, + 0x86BA, 0x5593, 0x86BB, 0x5595, 0x86BC, 0x5596, 0x86BD, 0x5597, 0x86BE, 0x559A, 0x86BF, 0x559B, 0x86C0, 0x559E, 0x86C1, 0x55A0, + 0x86C2, 0x55A1, 0x86C3, 0x55A2, 0x86C4, 0x55A3, 0x86C5, 0x55A4, 0x86C6, 0x55A5, 0x86C7, 0x55A6, 0x86C8, 0x55A8, 0x86C9, 0x55A9, + 0x86CA, 0x55AA, 0x86CB, 0x55AB, 0x86CC, 0x55AC, 0x86CD, 0x55AD, 0x86CE, 0x55AE, 0x86CF, 0x55AF, 0x86D0, 0x55B0, 0x86D1, 0x55B2, + 0x86D2, 0x55B4, 0x86D3, 0x55B6, 0x86D4, 0x55B8, 0x86D5, 0x55BA, 0x86D6, 0x55BC, 0x86D7, 0x55BF, 0x86D8, 0x55C0, 0x86D9, 0x55C1, + 0x86DA, 0x55C2, 0x86DB, 0x55C3, 0x86DC, 0x55C6, 0x86DD, 0x55C7, 0x86DE, 0x55C8, 0x86DF, 0x55CA, 0x86E0, 0x55CB, 0x86E1, 0x55CE, + 0x86E2, 0x55CF, 0x86E3, 0x55D0, 0x86E4, 0x55D5, 0x86E5, 0x55D7, 0x86E6, 0x55D8, 0x86E7, 0x55D9, 0x86E8, 0x55DA, 0x86E9, 0x55DB, + 0x86EA, 0x55DE, 0x86EB, 0x55E0, 0x86EC, 0x55E2, 0x86ED, 0x55E7, 0x86EE, 0x55E9, 0x86EF, 0x55ED, 0x86F0, 0x55EE, 0x86F1, 0x55F0, + 0x86F2, 0x55F1, 0x86F3, 0x55F4, 0x86F4, 0x55F6, 0x86F5, 0x55F8, 0x86F6, 0x55F9, 0x86F7, 0x55FA, 0x86F8, 0x55FB, 0x86F9, 0x55FC, + 0x86FA, 0x55FF, 0x86FB, 0x5602, 0x86FC, 0x5603, 0x86FD, 0x5604, 0x86FE, 0x5605, 0x8740, 0x5606, 0x8741, 0x5607, 0x8742, 0x560A, + 0x8743, 0x560B, 0x8744, 0x560D, 0x8745, 0x5610, 0x8746, 0x5611, 0x8747, 0x5612, 0x8748, 0x5613, 0x8749, 0x5614, 0x874A, 0x5615, + 0x874B, 0x5616, 0x874C, 0x5617, 0x874D, 0x5619, 0x874E, 0x561A, 0x874F, 0x561C, 0x8750, 0x561D, 0x8751, 0x5620, 0x8752, 0x5621, + 0x8753, 0x5622, 0x8754, 0x5625, 0x8755, 0x5626, 0x8756, 0x5628, 0x8757, 0x5629, 0x8758, 0x562A, 0x8759, 0x562B, 0x875A, 0x562E, + 0x875B, 0x562F, 0x875C, 0x5630, 0x875D, 0x5633, 0x875E, 0x5635, 0x875F, 0x5637, 0x8760, 0x5638, 0x8761, 0x563A, 0x8762, 0x563C, + 0x8763, 0x563D, 0x8764, 0x563E, 0x8765, 0x5640, 0x8766, 0x5641, 0x8767, 0x5642, 0x8768, 0x5643, 0x8769, 0x5644, 0x876A, 0x5645, + 0x876B, 0x5646, 0x876C, 0x5647, 0x876D, 0x5648, 0x876E, 0x5649, 0x876F, 0x564A, 0x8770, 0x564B, 0x8771, 0x564F, 0x8772, 0x5650, + 0x8773, 0x5651, 0x8774, 0x5652, 0x8775, 0x5653, 0x8776, 0x5655, 0x8777, 0x5656, 0x8778, 0x565A, 0x8779, 0x565B, 0x877A, 0x565D, + 0x877B, 0x565E, 0x877C, 0x565F, 0x877D, 0x5660, 0x877E, 0x5661, 0x8780, 0x5663, 0x8781, 0x5665, 0x8782, 0x5666, 0x8783, 0x5667, + 0x8784, 0x566D, 0x8785, 0x566E, 0x8786, 0x566F, 0x8787, 0x5670, 0x8788, 0x5672, 0x8789, 0x5673, 0x878A, 0x5674, 0x878B, 0x5675, + 0x878C, 0x5677, 0x878D, 0x5678, 0x878E, 0x5679, 0x878F, 0x567A, 0x8790, 0x567D, 0x8791, 0x567E, 0x8792, 0x567F, 0x8793, 0x5680, + 0x8794, 0x5681, 0x8795, 0x5682, 0x8796, 0x5683, 0x8797, 0x5684, 0x8798, 0x5687, 0x8799, 0x5688, 0x879A, 0x5689, 0x879B, 0x568A, + 0x879C, 0x568B, 0x879D, 0x568C, 0x879E, 0x568D, 0x879F, 0x5690, 0x87A0, 0x5691, 0x87A1, 0x5692, 0x87A2, 0x5694, 0x87A3, 0x5695, + 0x87A4, 0x5696, 0x87A5, 0x5697, 0x87A6, 0x5698, 0x87A7, 0x5699, 0x87A8, 0x569A, 0x87A9, 0x569B, 0x87AA, 0x569C, 0x87AB, 0x569D, + 0x87AC, 0x569E, 0x87AD, 0x569F, 0x87AE, 0x56A0, 0x87AF, 0x56A1, 0x87B0, 0x56A2, 0x87B1, 0x56A4, 0x87B2, 0x56A5, 0x87B3, 0x56A6, + 0x87B4, 0x56A7, 0x87B5, 0x56A8, 0x87B6, 0x56A9, 0x87B7, 0x56AA, 0x87B8, 0x56AB, 0x87B9, 0x56AC, 0x87BA, 0x56AD, 0x87BB, 0x56AE, + 0x87BC, 0x56B0, 0x87BD, 0x56B1, 0x87BE, 0x56B2, 0x87BF, 0x56B3, 0x87C0, 0x56B4, 0x87C1, 0x56B5, 0x87C2, 0x56B6, 0x87C3, 0x56B8, + 0x87C4, 0x56B9, 0x87C5, 0x56BA, 0x87C6, 0x56BB, 0x87C7, 0x56BD, 0x87C8, 0x56BE, 0x87C9, 0x56BF, 0x87CA, 0x56C0, 0x87CB, 0x56C1, + 0x87CC, 0x56C2, 0x87CD, 0x56C3, 0x87CE, 0x56C4, 0x87CF, 0x56C5, 0x87D0, 0x56C6, 0x87D1, 0x56C7, 0x87D2, 0x56C8, 0x87D3, 0x56C9, + 0x87D4, 0x56CB, 0x87D5, 0x56CC, 0x87D6, 0x56CD, 0x87D7, 0x56CE, 0x87D8, 0x56CF, 0x87D9, 0x56D0, 0x87DA, 0x56D1, 0x87DB, 0x56D2, + 0x87DC, 0x56D3, 0x87DD, 0x56D5, 0x87DE, 0x56D6, 0x87DF, 0x56D8, 0x87E0, 0x56D9, 0x87E1, 0x56DC, 0x87E2, 0x56E3, 0x87E3, 0x56E5, + 0x87E4, 0x56E6, 0x87E5, 0x56E7, 0x87E6, 0x56E8, 0x87E7, 0x56E9, 0x87E8, 0x56EA, 0x87E9, 0x56EC, 0x87EA, 0x56EE, 0x87EB, 0x56EF, + 0x87EC, 0x56F2, 0x87ED, 0x56F3, 0x87EE, 0x56F6, 0x87EF, 0x56F7, 0x87F0, 0x56F8, 0x87F1, 0x56FB, 0x87F2, 0x56FC, 0x87F3, 0x5700, + 0x87F4, 0x5701, 0x87F5, 0x5702, 0x87F6, 0x5705, 0x87F7, 0x5707, 0x87F8, 0x570B, 0x87F9, 0x570C, 0x87FA, 0x570D, 0x87FB, 0x570E, + 0x87FC, 0x570F, 0x87FD, 0x5710, 0x87FE, 0x5711, 0x8840, 0x5712, 0x8841, 0x5713, 0x8842, 0x5714, 0x8843, 0x5715, 0x8844, 0x5716, + 0x8845, 0x5717, 0x8846, 0x5718, 0x8847, 0x5719, 0x8848, 0x571A, 0x8849, 0x571B, 0x884A, 0x571D, 0x884B, 0x571E, 0x884C, 0x5720, + 0x884D, 0x5721, 0x884E, 0x5722, 0x884F, 0x5724, 0x8850, 0x5725, 0x8851, 0x5726, 0x8852, 0x5727, 0x8853, 0x572B, 0x8854, 0x5731, + 0x8855, 0x5732, 0x8856, 0x5734, 0x8857, 0x5735, 0x8858, 0x5736, 0x8859, 0x5737, 0x885A, 0x5738, 0x885B, 0x573C, 0x885C, 0x573D, + 0x885D, 0x573F, 0x885E, 0x5741, 0x885F, 0x5743, 0x8860, 0x5744, 0x8861, 0x5745, 0x8862, 0x5746, 0x8863, 0x5748, 0x8864, 0x5749, + 0x8865, 0x574B, 0x8866, 0x5752, 0x8867, 0x5753, 0x8868, 0x5754, 0x8869, 0x5755, 0x886A, 0x5756, 0x886B, 0x5758, 0x886C, 0x5759, + 0x886D, 0x5762, 0x886E, 0x5763, 0x886F, 0x5765, 0x8870, 0x5767, 0x8871, 0x576C, 0x8872, 0x576E, 0x8873, 0x5770, 0x8874, 0x5771, + 0x8875, 0x5772, 0x8876, 0x5774, 0x8877, 0x5775, 0x8878, 0x5778, 0x8879, 0x5779, 0x887A, 0x577A, 0x887B, 0x577D, 0x887C, 0x577E, + 0x887D, 0x577F, 0x887E, 0x5780, 0x8880, 0x5781, 0x8881, 0x5787, 0x8882, 0x5788, 0x8883, 0x5789, 0x8884, 0x578A, 0x8885, 0x578D, + 0x8886, 0x578E, 0x8887, 0x578F, 0x8888, 0x5790, 0x8889, 0x5791, 0x888A, 0x5794, 0x888B, 0x5795, 0x888C, 0x5796, 0x888D, 0x5797, + 0x888E, 0x5798, 0x888F, 0x5799, 0x8890, 0x579A, 0x8891, 0x579C, 0x8892, 0x579D, 0x8893, 0x579E, 0x8894, 0x579F, 0x8895, 0x57A5, + 0x8896, 0x57A8, 0x8897, 0x57AA, 0x8898, 0x57AC, 0x8899, 0x57AF, 0x889A, 0x57B0, 0x889B, 0x57B1, 0x889C, 0x57B3, 0x889D, 0x57B5, + 0x889E, 0x57B6, 0x889F, 0x57B7, 0x88A0, 0x57B9, 0x88A1, 0x57BA, 0x88A2, 0x57BB, 0x88A3, 0x57BC, 0x88A4, 0x57BD, 0x88A5, 0x57BE, + 0x88A6, 0x57BF, 0x88A7, 0x57C0, 0x88A8, 0x57C1, 0x88A9, 0x57C4, 0x88AA, 0x57C5, 0x88AB, 0x57C6, 0x88AC, 0x57C7, 0x88AD, 0x57C8, + 0x88AE, 0x57C9, 0x88AF, 0x57CA, 0x88B0, 0x57CC, 0x88B1, 0x57CD, 0x88B2, 0x57D0, 0x88B3, 0x57D1, 0x88B4, 0x57D3, 0x88B5, 0x57D6, + 0x88B6, 0x57D7, 0x88B7, 0x57DB, 0x88B8, 0x57DC, 0x88B9, 0x57DE, 0x88BA, 0x57E1, 0x88BB, 0x57E2, 0x88BC, 0x57E3, 0x88BD, 0x57E5, + 0x88BE, 0x57E6, 0x88BF, 0x57E7, 0x88C0, 0x57E8, 0x88C1, 0x57E9, 0x88C2, 0x57EA, 0x88C3, 0x57EB, 0x88C4, 0x57EC, 0x88C5, 0x57EE, + 0x88C6, 0x57F0, 0x88C7, 0x57F1, 0x88C8, 0x57F2, 0x88C9, 0x57F3, 0x88CA, 0x57F5, 0x88CB, 0x57F6, 0x88CC, 0x57F7, 0x88CD, 0x57FB, + 0x88CE, 0x57FC, 0x88CF, 0x57FE, 0x88D0, 0x57FF, 0x88D1, 0x5801, 0x88D2, 0x5803, 0x88D3, 0x5804, 0x88D4, 0x5805, 0x88D5, 0x5808, + 0x88D6, 0x5809, 0x88D7, 0x580A, 0x88D8, 0x580C, 0x88D9, 0x580E, 0x88DA, 0x580F, 0x88DB, 0x5810, 0x88DC, 0x5812, 0x88DD, 0x5813, + 0x88DE, 0x5814, 0x88DF, 0x5816, 0x88E0, 0x5817, 0x88E1, 0x5818, 0x88E2, 0x581A, 0x88E3, 0x581B, 0x88E4, 0x581C, 0x88E5, 0x581D, + 0x88E6, 0x581F, 0x88E7, 0x5822, 0x88E8, 0x5823, 0x88E9, 0x5825, 0x88EA, 0x5826, 0x88EB, 0x5827, 0x88EC, 0x5828, 0x88ED, 0x5829, + 0x88EE, 0x582B, 0x88EF, 0x582C, 0x88F0, 0x582D, 0x88F1, 0x582E, 0x88F2, 0x582F, 0x88F3, 0x5831, 0x88F4, 0x5832, 0x88F5, 0x5833, + 0x88F6, 0x5834, 0x88F7, 0x5836, 0x88F8, 0x5837, 0x88F9, 0x5838, 0x88FA, 0x5839, 0x88FB, 0x583A, 0x88FC, 0x583B, 0x88FD, 0x583C, + 0x88FE, 0x583D, 0x8940, 0x583E, 0x8941, 0x583F, 0x8942, 0x5840, 0x8943, 0x5841, 0x8944, 0x5842, 0x8945, 0x5843, 0x8946, 0x5845, + 0x8947, 0x5846, 0x8948, 0x5847, 0x8949, 0x5848, 0x894A, 0x5849, 0x894B, 0x584A, 0x894C, 0x584B, 0x894D, 0x584E, 0x894E, 0x584F, + 0x894F, 0x5850, 0x8950, 0x5852, 0x8951, 0x5853, 0x8952, 0x5855, 0x8953, 0x5856, 0x8954, 0x5857, 0x8955, 0x5859, 0x8956, 0x585A, + 0x8957, 0x585B, 0x8958, 0x585C, 0x8959, 0x585D, 0x895A, 0x585F, 0x895B, 0x5860, 0x895C, 0x5861, 0x895D, 0x5862, 0x895E, 0x5863, + 0x895F, 0x5864, 0x8960, 0x5866, 0x8961, 0x5867, 0x8962, 0x5868, 0x8963, 0x5869, 0x8964, 0x586A, 0x8965, 0x586D, 0x8966, 0x586E, + 0x8967, 0x586F, 0x8968, 0x5870, 0x8969, 0x5871, 0x896A, 0x5872, 0x896B, 0x5873, 0x896C, 0x5874, 0x896D, 0x5875, 0x896E, 0x5876, + 0x896F, 0x5877, 0x8970, 0x5878, 0x8971, 0x5879, 0x8972, 0x587A, 0x8973, 0x587B, 0x8974, 0x587C, 0x8975, 0x587D, 0x8976, 0x587F, + 0x8977, 0x5882, 0x8978, 0x5884, 0x8979, 0x5886, 0x897A, 0x5887, 0x897B, 0x5888, 0x897C, 0x588A, 0x897D, 0x588B, 0x897E, 0x588C, + 0x8980, 0x588D, 0x8981, 0x588E, 0x8982, 0x588F, 0x8983, 0x5890, 0x8984, 0x5891, 0x8985, 0x5894, 0x8986, 0x5895, 0x8987, 0x5896, + 0x8988, 0x5897, 0x8989, 0x5898, 0x898A, 0x589B, 0x898B, 0x589C, 0x898C, 0x589D, 0x898D, 0x58A0, 0x898E, 0x58A1, 0x898F, 0x58A2, + 0x8990, 0x58A3, 0x8991, 0x58A4, 0x8992, 0x58A5, 0x8993, 0x58A6, 0x8994, 0x58A7, 0x8995, 0x58AA, 0x8996, 0x58AB, 0x8997, 0x58AC, + 0x8998, 0x58AD, 0x8999, 0x58AE, 0x899A, 0x58AF, 0x899B, 0x58B0, 0x899C, 0x58B1, 0x899D, 0x58B2, 0x899E, 0x58B3, 0x899F, 0x58B4, + 0x89A0, 0x58B5, 0x89A1, 0x58B6, 0x89A2, 0x58B7, 0x89A3, 0x58B8, 0x89A4, 0x58B9, 0x89A5, 0x58BA, 0x89A6, 0x58BB, 0x89A7, 0x58BD, + 0x89A8, 0x58BE, 0x89A9, 0x58BF, 0x89AA, 0x58C0, 0x89AB, 0x58C2, 0x89AC, 0x58C3, 0x89AD, 0x58C4, 0x89AE, 0x58C6, 0x89AF, 0x58C7, + 0x89B0, 0x58C8, 0x89B1, 0x58C9, 0x89B2, 0x58CA, 0x89B3, 0x58CB, 0x89B4, 0x58CC, 0x89B5, 0x58CD, 0x89B6, 0x58CE, 0x89B7, 0x58CF, + 0x89B8, 0x58D0, 0x89B9, 0x58D2, 0x89BA, 0x58D3, 0x89BB, 0x58D4, 0x89BC, 0x58D6, 0x89BD, 0x58D7, 0x89BE, 0x58D8, 0x89BF, 0x58D9, + 0x89C0, 0x58DA, 0x89C1, 0x58DB, 0x89C2, 0x58DC, 0x89C3, 0x58DD, 0x89C4, 0x58DE, 0x89C5, 0x58DF, 0x89C6, 0x58E0, 0x89C7, 0x58E1, + 0x89C8, 0x58E2, 0x89C9, 0x58E3, 0x89CA, 0x58E5, 0x89CB, 0x58E6, 0x89CC, 0x58E7, 0x89CD, 0x58E8, 0x89CE, 0x58E9, 0x89CF, 0x58EA, + 0x89D0, 0x58ED, 0x89D1, 0x58EF, 0x89D2, 0x58F1, 0x89D3, 0x58F2, 0x89D4, 0x58F4, 0x89D5, 0x58F5, 0x89D6, 0x58F7, 0x89D7, 0x58F8, + 0x89D8, 0x58FA, 0x89D9, 0x58FB, 0x89DA, 0x58FC, 0x89DB, 0x58FD, 0x89DC, 0x58FE, 0x89DD, 0x58FF, 0x89DE, 0x5900, 0x89DF, 0x5901, + 0x89E0, 0x5903, 0x89E1, 0x5905, 0x89E2, 0x5906, 0x89E3, 0x5908, 0x89E4, 0x5909, 0x89E5, 0x590A, 0x89E6, 0x590B, 0x89E7, 0x590C, + 0x89E8, 0x590E, 0x89E9, 0x5910, 0x89EA, 0x5911, 0x89EB, 0x5912, 0x89EC, 0x5913, 0x89ED, 0x5917, 0x89EE, 0x5918, 0x89EF, 0x591B, + 0x89F0, 0x591D, 0x89F1, 0x591E, 0x89F2, 0x5920, 0x89F3, 0x5921, 0x89F4, 0x5922, 0x89F5, 0x5923, 0x89F6, 0x5926, 0x89F7, 0x5928, + 0x89F8, 0x592C, 0x89F9, 0x5930, 0x89FA, 0x5932, 0x89FB, 0x5933, 0x89FC, 0x5935, 0x89FD, 0x5936, 0x89FE, 0x593B, 0x8A40, 0x593D, + 0x8A41, 0x593E, 0x8A42, 0x593F, 0x8A43, 0x5940, 0x8A44, 0x5943, 0x8A45, 0x5945, 0x8A46, 0x5946, 0x8A47, 0x594A, 0x8A48, 0x594C, + 0x8A49, 0x594D, 0x8A4A, 0x5950, 0x8A4B, 0x5952, 0x8A4C, 0x5953, 0x8A4D, 0x5959, 0x8A4E, 0x595B, 0x8A4F, 0x595C, 0x8A50, 0x595D, + 0x8A51, 0x595E, 0x8A52, 0x595F, 0x8A53, 0x5961, 0x8A54, 0x5963, 0x8A55, 0x5964, 0x8A56, 0x5966, 0x8A57, 0x5967, 0x8A58, 0x5968, + 0x8A59, 0x5969, 0x8A5A, 0x596A, 0x8A5B, 0x596B, 0x8A5C, 0x596C, 0x8A5D, 0x596D, 0x8A5E, 0x596E, 0x8A5F, 0x596F, 0x8A60, 0x5970, + 0x8A61, 0x5971, 0x8A62, 0x5972, 0x8A63, 0x5975, 0x8A64, 0x5977, 0x8A65, 0x597A, 0x8A66, 0x597B, 0x8A67, 0x597C, 0x8A68, 0x597E, + 0x8A69, 0x597F, 0x8A6A, 0x5980, 0x8A6B, 0x5985, 0x8A6C, 0x5989, 0x8A6D, 0x598B, 0x8A6E, 0x598C, 0x8A6F, 0x598E, 0x8A70, 0x598F, + 0x8A71, 0x5990, 0x8A72, 0x5991, 0x8A73, 0x5994, 0x8A74, 0x5995, 0x8A75, 0x5998, 0x8A76, 0x599A, 0x8A77, 0x599B, 0x8A78, 0x599C, + 0x8A79, 0x599D, 0x8A7A, 0x599F, 0x8A7B, 0x59A0, 0x8A7C, 0x59A1, 0x8A7D, 0x59A2, 0x8A7E, 0x59A6, 0x8A80, 0x59A7, 0x8A81, 0x59AC, + 0x8A82, 0x59AD, 0x8A83, 0x59B0, 0x8A84, 0x59B1, 0x8A85, 0x59B3, 0x8A86, 0x59B4, 0x8A87, 0x59B5, 0x8A88, 0x59B6, 0x8A89, 0x59B7, + 0x8A8A, 0x59B8, 0x8A8B, 0x59BA, 0x8A8C, 0x59BC, 0x8A8D, 0x59BD, 0x8A8E, 0x59BF, 0x8A8F, 0x59C0, 0x8A90, 0x59C1, 0x8A91, 0x59C2, + 0x8A92, 0x59C3, 0x8A93, 0x59C4, 0x8A94, 0x59C5, 0x8A95, 0x59C7, 0x8A96, 0x59C8, 0x8A97, 0x59C9, 0x8A98, 0x59CC, 0x8A99, 0x59CD, + 0x8A9A, 0x59CE, 0x8A9B, 0x59CF, 0x8A9C, 0x59D5, 0x8A9D, 0x59D6, 0x8A9E, 0x59D9, 0x8A9F, 0x59DB, 0x8AA0, 0x59DE, 0x8AA1, 0x59DF, + 0x8AA2, 0x59E0, 0x8AA3, 0x59E1, 0x8AA4, 0x59E2, 0x8AA5, 0x59E4, 0x8AA6, 0x59E6, 0x8AA7, 0x59E7, 0x8AA8, 0x59E9, 0x8AA9, 0x59EA, + 0x8AAA, 0x59EB, 0x8AAB, 0x59ED, 0x8AAC, 0x59EE, 0x8AAD, 0x59EF, 0x8AAE, 0x59F0, 0x8AAF, 0x59F1, 0x8AB0, 0x59F2, 0x8AB1, 0x59F3, + 0x8AB2, 0x59F4, 0x8AB3, 0x59F5, 0x8AB4, 0x59F6, 0x8AB5, 0x59F7, 0x8AB6, 0x59F8, 0x8AB7, 0x59FA, 0x8AB8, 0x59FC, 0x8AB9, 0x59FD, + 0x8ABA, 0x59FE, 0x8ABB, 0x5A00, 0x8ABC, 0x5A02, 0x8ABD, 0x5A0A, 0x8ABE, 0x5A0B, 0x8ABF, 0x5A0D, 0x8AC0, 0x5A0E, 0x8AC1, 0x5A0F, + 0x8AC2, 0x5A10, 0x8AC3, 0x5A12, 0x8AC4, 0x5A14, 0x8AC5, 0x5A15, 0x8AC6, 0x5A16, 0x8AC7, 0x5A17, 0x8AC8, 0x5A19, 0x8AC9, 0x5A1A, + 0x8ACA, 0x5A1B, 0x8ACB, 0x5A1D, 0x8ACC, 0x5A1E, 0x8ACD, 0x5A21, 0x8ACE, 0x5A22, 0x8ACF, 0x5A24, 0x8AD0, 0x5A26, 0x8AD1, 0x5A27, + 0x8AD2, 0x5A28, 0x8AD3, 0x5A2A, 0x8AD4, 0x5A2B, 0x8AD5, 0x5A2C, 0x8AD6, 0x5A2D, 0x8AD7, 0x5A2E, 0x8AD8, 0x5A2F, 0x8AD9, 0x5A30, + 0x8ADA, 0x5A33, 0x8ADB, 0x5A35, 0x8ADC, 0x5A37, 0x8ADD, 0x5A38, 0x8ADE, 0x5A39, 0x8ADF, 0x5A3A, 0x8AE0, 0x5A3B, 0x8AE1, 0x5A3D, + 0x8AE2, 0x5A3E, 0x8AE3, 0x5A3F, 0x8AE4, 0x5A41, 0x8AE5, 0x5A42, 0x8AE6, 0x5A43, 0x8AE7, 0x5A44, 0x8AE8, 0x5A45, 0x8AE9, 0x5A47, + 0x8AEA, 0x5A48, 0x8AEB, 0x5A4B, 0x8AEC, 0x5A4C, 0x8AED, 0x5A4D, 0x8AEE, 0x5A4E, 0x8AEF, 0x5A4F, 0x8AF0, 0x5A50, 0x8AF1, 0x5A51, + 0x8AF2, 0x5A52, 0x8AF3, 0x5A53, 0x8AF4, 0x5A54, 0x8AF5, 0x5A56, 0x8AF6, 0x5A57, 0x8AF7, 0x5A58, 0x8AF8, 0x5A59, 0x8AF9, 0x5A5B, + 0x8AFA, 0x5A5C, 0x8AFB, 0x5A5D, 0x8AFC, 0x5A5E, 0x8AFD, 0x5A5F, 0x8AFE, 0x5A60, 0x8B40, 0x5A61, 0x8B41, 0x5A63, 0x8B42, 0x5A64, + 0x8B43, 0x5A65, 0x8B44, 0x5A66, 0x8B45, 0x5A68, 0x8B46, 0x5A69, 0x8B47, 0x5A6B, 0x8B48, 0x5A6C, 0x8B49, 0x5A6D, 0x8B4A, 0x5A6E, + 0x8B4B, 0x5A6F, 0x8B4C, 0x5A70, 0x8B4D, 0x5A71, 0x8B4E, 0x5A72, 0x8B4F, 0x5A73, 0x8B50, 0x5A78, 0x8B51, 0x5A79, 0x8B52, 0x5A7B, + 0x8B53, 0x5A7C, 0x8B54, 0x5A7D, 0x8B55, 0x5A7E, 0x8B56, 0x5A80, 0x8B57, 0x5A81, 0x8B58, 0x5A82, 0x8B59, 0x5A83, 0x8B5A, 0x5A84, + 0x8B5B, 0x5A85, 0x8B5C, 0x5A86, 0x8B5D, 0x5A87, 0x8B5E, 0x5A88, 0x8B5F, 0x5A89, 0x8B60, 0x5A8A, 0x8B61, 0x5A8B, 0x8B62, 0x5A8C, + 0x8B63, 0x5A8D, 0x8B64, 0x5A8E, 0x8B65, 0x5A8F, 0x8B66, 0x5A90, 0x8B67, 0x5A91, 0x8B68, 0x5A93, 0x8B69, 0x5A94, 0x8B6A, 0x5A95, + 0x8B6B, 0x5A96, 0x8B6C, 0x5A97, 0x8B6D, 0x5A98, 0x8B6E, 0x5A99, 0x8B6F, 0x5A9C, 0x8B70, 0x5A9D, 0x8B71, 0x5A9E, 0x8B72, 0x5A9F, + 0x8B73, 0x5AA0, 0x8B74, 0x5AA1, 0x8B75, 0x5AA2, 0x8B76, 0x5AA3, 0x8B77, 0x5AA4, 0x8B78, 0x5AA5, 0x8B79, 0x5AA6, 0x8B7A, 0x5AA7, + 0x8B7B, 0x5AA8, 0x8B7C, 0x5AA9, 0x8B7D, 0x5AAB, 0x8B7E, 0x5AAC, 0x8B80, 0x5AAD, 0x8B81, 0x5AAE, 0x8B82, 0x5AAF, 0x8B83, 0x5AB0, + 0x8B84, 0x5AB1, 0x8B85, 0x5AB4, 0x8B86, 0x5AB6, 0x8B87, 0x5AB7, 0x8B88, 0x5AB9, 0x8B89, 0x5ABA, 0x8B8A, 0x5ABB, 0x8B8B, 0x5ABC, + 0x8B8C, 0x5ABD, 0x8B8D, 0x5ABF, 0x8B8E, 0x5AC0, 0x8B8F, 0x5AC3, 0x8B90, 0x5AC4, 0x8B91, 0x5AC5, 0x8B92, 0x5AC6, 0x8B93, 0x5AC7, + 0x8B94, 0x5AC8, 0x8B95, 0x5ACA, 0x8B96, 0x5ACB, 0x8B97, 0x5ACD, 0x8B98, 0x5ACE, 0x8B99, 0x5ACF, 0x8B9A, 0x5AD0, 0x8B9B, 0x5AD1, + 0x8B9C, 0x5AD3, 0x8B9D, 0x5AD5, 0x8B9E, 0x5AD7, 0x8B9F, 0x5AD9, 0x8BA0, 0x5ADA, 0x8BA1, 0x5ADB, 0x8BA2, 0x5ADD, 0x8BA3, 0x5ADE, + 0x8BA4, 0x5ADF, 0x8BA5, 0x5AE2, 0x8BA6, 0x5AE4, 0x8BA7, 0x5AE5, 0x8BA8, 0x5AE7, 0x8BA9, 0x5AE8, 0x8BAA, 0x5AEA, 0x8BAB, 0x5AEC, + 0x8BAC, 0x5AED, 0x8BAD, 0x5AEE, 0x8BAE, 0x5AEF, 0x8BAF, 0x5AF0, 0x8BB0, 0x5AF2, 0x8BB1, 0x5AF3, 0x8BB2, 0x5AF4, 0x8BB3, 0x5AF5, + 0x8BB4, 0x5AF6, 0x8BB5, 0x5AF7, 0x8BB6, 0x5AF8, 0x8BB7, 0x5AF9, 0x8BB8, 0x5AFA, 0x8BB9, 0x5AFB, 0x8BBA, 0x5AFC, 0x8BBB, 0x5AFD, + 0x8BBC, 0x5AFE, 0x8BBD, 0x5AFF, 0x8BBE, 0x5B00, 0x8BBF, 0x5B01, 0x8BC0, 0x5B02, 0x8BC1, 0x5B03, 0x8BC2, 0x5B04, 0x8BC3, 0x5B05, + 0x8BC4, 0x5B06, 0x8BC5, 0x5B07, 0x8BC6, 0x5B08, 0x8BC7, 0x5B0A, 0x8BC8, 0x5B0B, 0x8BC9, 0x5B0C, 0x8BCA, 0x5B0D, 0x8BCB, 0x5B0E, + 0x8BCC, 0x5B0F, 0x8BCD, 0x5B10, 0x8BCE, 0x5B11, 0x8BCF, 0x5B12, 0x8BD0, 0x5B13, 0x8BD1, 0x5B14, 0x8BD2, 0x5B15, 0x8BD3, 0x5B18, + 0x8BD4, 0x5B19, 0x8BD5, 0x5B1A, 0x8BD6, 0x5B1B, 0x8BD7, 0x5B1C, 0x8BD8, 0x5B1D, 0x8BD9, 0x5B1E, 0x8BDA, 0x5B1F, 0x8BDB, 0x5B20, + 0x8BDC, 0x5B21, 0x8BDD, 0x5B22, 0x8BDE, 0x5B23, 0x8BDF, 0x5B24, 0x8BE0, 0x5B25, 0x8BE1, 0x5B26, 0x8BE2, 0x5B27, 0x8BE3, 0x5B28, + 0x8BE4, 0x5B29, 0x8BE5, 0x5B2A, 0x8BE6, 0x5B2B, 0x8BE7, 0x5B2C, 0x8BE8, 0x5B2D, 0x8BE9, 0x5B2E, 0x8BEA, 0x5B2F, 0x8BEB, 0x5B30, + 0x8BEC, 0x5B31, 0x8BED, 0x5B33, 0x8BEE, 0x5B35, 0x8BEF, 0x5B36, 0x8BF0, 0x5B38, 0x8BF1, 0x5B39, 0x8BF2, 0x5B3A, 0x8BF3, 0x5B3B, + 0x8BF4, 0x5B3C, 0x8BF5, 0x5B3D, 0x8BF6, 0x5B3E, 0x8BF7, 0x5B3F, 0x8BF8, 0x5B41, 0x8BF9, 0x5B42, 0x8BFA, 0x5B43, 0x8BFB, 0x5B44, + 0x8BFC, 0x5B45, 0x8BFD, 0x5B46, 0x8BFE, 0x5B47, 0x8C40, 0x5B48, 0x8C41, 0x5B49, 0x8C42, 0x5B4A, 0x8C43, 0x5B4B, 0x8C44, 0x5B4C, + 0x8C45, 0x5B4D, 0x8C46, 0x5B4E, 0x8C47, 0x5B4F, 0x8C48, 0x5B52, 0x8C49, 0x5B56, 0x8C4A, 0x5B5E, 0x8C4B, 0x5B60, 0x8C4C, 0x5B61, + 0x8C4D, 0x5B67, 0x8C4E, 0x5B68, 0x8C4F, 0x5B6B, 0x8C50, 0x5B6D, 0x8C51, 0x5B6E, 0x8C52, 0x5B6F, 0x8C53, 0x5B72, 0x8C54, 0x5B74, + 0x8C55, 0x5B76, 0x8C56, 0x5B77, 0x8C57, 0x5B78, 0x8C58, 0x5B79, 0x8C59, 0x5B7B, 0x8C5A, 0x5B7C, 0x8C5B, 0x5B7E, 0x8C5C, 0x5B7F, + 0x8C5D, 0x5B82, 0x8C5E, 0x5B86, 0x8C5F, 0x5B8A, 0x8C60, 0x5B8D, 0x8C61, 0x5B8E, 0x8C62, 0x5B90, 0x8C63, 0x5B91, 0x8C64, 0x5B92, + 0x8C65, 0x5B94, 0x8C66, 0x5B96, 0x8C67, 0x5B9F, 0x8C68, 0x5BA7, 0x8C69, 0x5BA8, 0x8C6A, 0x5BA9, 0x8C6B, 0x5BAC, 0x8C6C, 0x5BAD, + 0x8C6D, 0x5BAE, 0x8C6E, 0x5BAF, 0x8C6F, 0x5BB1, 0x8C70, 0x5BB2, 0x8C71, 0x5BB7, 0x8C72, 0x5BBA, 0x8C73, 0x5BBB, 0x8C74, 0x5BBC, + 0x8C75, 0x5BC0, 0x8C76, 0x5BC1, 0x8C77, 0x5BC3, 0x8C78, 0x5BC8, 0x8C79, 0x5BC9, 0x8C7A, 0x5BCA, 0x8C7B, 0x5BCB, 0x8C7C, 0x5BCD, + 0x8C7D, 0x5BCE, 0x8C7E, 0x5BCF, 0x8C80, 0x5BD1, 0x8C81, 0x5BD4, 0x8C82, 0x5BD5, 0x8C83, 0x5BD6, 0x8C84, 0x5BD7, 0x8C85, 0x5BD8, + 0x8C86, 0x5BD9, 0x8C87, 0x5BDA, 0x8C88, 0x5BDB, 0x8C89, 0x5BDC, 0x8C8A, 0x5BE0, 0x8C8B, 0x5BE2, 0x8C8C, 0x5BE3, 0x8C8D, 0x5BE6, + 0x8C8E, 0x5BE7, 0x8C8F, 0x5BE9, 0x8C90, 0x5BEA, 0x8C91, 0x5BEB, 0x8C92, 0x5BEC, 0x8C93, 0x5BED, 0x8C94, 0x5BEF, 0x8C95, 0x5BF1, + 0x8C96, 0x5BF2, 0x8C97, 0x5BF3, 0x8C98, 0x5BF4, 0x8C99, 0x5BF5, 0x8C9A, 0x5BF6, 0x8C9B, 0x5BF7, 0x8C9C, 0x5BFD, 0x8C9D, 0x5BFE, + 0x8C9E, 0x5C00, 0x8C9F, 0x5C02, 0x8CA0, 0x5C03, 0x8CA1, 0x5C05, 0x8CA2, 0x5C07, 0x8CA3, 0x5C08, 0x8CA4, 0x5C0B, 0x8CA5, 0x5C0C, + 0x8CA6, 0x5C0D, 0x8CA7, 0x5C0E, 0x8CA8, 0x5C10, 0x8CA9, 0x5C12, 0x8CAA, 0x5C13, 0x8CAB, 0x5C17, 0x8CAC, 0x5C19, 0x8CAD, 0x5C1B, + 0x8CAE, 0x5C1E, 0x8CAF, 0x5C1F, 0x8CB0, 0x5C20, 0x8CB1, 0x5C21, 0x8CB2, 0x5C23, 0x8CB3, 0x5C26, 0x8CB4, 0x5C28, 0x8CB5, 0x5C29, + 0x8CB6, 0x5C2A, 0x8CB7, 0x5C2B, 0x8CB8, 0x5C2D, 0x8CB9, 0x5C2E, 0x8CBA, 0x5C2F, 0x8CBB, 0x5C30, 0x8CBC, 0x5C32, 0x8CBD, 0x5C33, + 0x8CBE, 0x5C35, 0x8CBF, 0x5C36, 0x8CC0, 0x5C37, 0x8CC1, 0x5C43, 0x8CC2, 0x5C44, 0x8CC3, 0x5C46, 0x8CC4, 0x5C47, 0x8CC5, 0x5C4C, + 0x8CC6, 0x5C4D, 0x8CC7, 0x5C52, 0x8CC8, 0x5C53, 0x8CC9, 0x5C54, 0x8CCA, 0x5C56, 0x8CCB, 0x5C57, 0x8CCC, 0x5C58, 0x8CCD, 0x5C5A, + 0x8CCE, 0x5C5B, 0x8CCF, 0x5C5C, 0x8CD0, 0x5C5D, 0x8CD1, 0x5C5F, 0x8CD2, 0x5C62, 0x8CD3, 0x5C64, 0x8CD4, 0x5C67, 0x8CD5, 0x5C68, + 0x8CD6, 0x5C69, 0x8CD7, 0x5C6A, 0x8CD8, 0x5C6B, 0x8CD9, 0x5C6C, 0x8CDA, 0x5C6D, 0x8CDB, 0x5C70, 0x8CDC, 0x5C72, 0x8CDD, 0x5C73, + 0x8CDE, 0x5C74, 0x8CDF, 0x5C75, 0x8CE0, 0x5C76, 0x8CE1, 0x5C77, 0x8CE2, 0x5C78, 0x8CE3, 0x5C7B, 0x8CE4, 0x5C7C, 0x8CE5, 0x5C7D, + 0x8CE6, 0x5C7E, 0x8CE7, 0x5C80, 0x8CE8, 0x5C83, 0x8CE9, 0x5C84, 0x8CEA, 0x5C85, 0x8CEB, 0x5C86, 0x8CEC, 0x5C87, 0x8CED, 0x5C89, + 0x8CEE, 0x5C8A, 0x8CEF, 0x5C8B, 0x8CF0, 0x5C8E, 0x8CF1, 0x5C8F, 0x8CF2, 0x5C92, 0x8CF3, 0x5C93, 0x8CF4, 0x5C95, 0x8CF5, 0x5C9D, + 0x8CF6, 0x5C9E, 0x8CF7, 0x5C9F, 0x8CF8, 0x5CA0, 0x8CF9, 0x5CA1, 0x8CFA, 0x5CA4, 0x8CFB, 0x5CA5, 0x8CFC, 0x5CA6, 0x8CFD, 0x5CA7, + 0x8CFE, 0x5CA8, 0x8D40, 0x5CAA, 0x8D41, 0x5CAE, 0x8D42, 0x5CAF, 0x8D43, 0x5CB0, 0x8D44, 0x5CB2, 0x8D45, 0x5CB4, 0x8D46, 0x5CB6, + 0x8D47, 0x5CB9, 0x8D48, 0x5CBA, 0x8D49, 0x5CBB, 0x8D4A, 0x5CBC, 0x8D4B, 0x5CBE, 0x8D4C, 0x5CC0, 0x8D4D, 0x5CC2, 0x8D4E, 0x5CC3, + 0x8D4F, 0x5CC5, 0x8D50, 0x5CC6, 0x8D51, 0x5CC7, 0x8D52, 0x5CC8, 0x8D53, 0x5CC9, 0x8D54, 0x5CCA, 0x8D55, 0x5CCC, 0x8D56, 0x5CCD, + 0x8D57, 0x5CCE, 0x8D58, 0x5CCF, 0x8D59, 0x5CD0, 0x8D5A, 0x5CD1, 0x8D5B, 0x5CD3, 0x8D5C, 0x5CD4, 0x8D5D, 0x5CD5, 0x8D5E, 0x5CD6, + 0x8D5F, 0x5CD7, 0x8D60, 0x5CD8, 0x8D61, 0x5CDA, 0x8D62, 0x5CDB, 0x8D63, 0x5CDC, 0x8D64, 0x5CDD, 0x8D65, 0x5CDE, 0x8D66, 0x5CDF, + 0x8D67, 0x5CE0, 0x8D68, 0x5CE2, 0x8D69, 0x5CE3, 0x8D6A, 0x5CE7, 0x8D6B, 0x5CE9, 0x8D6C, 0x5CEB, 0x8D6D, 0x5CEC, 0x8D6E, 0x5CEE, + 0x8D6F, 0x5CEF, 0x8D70, 0x5CF1, 0x8D71, 0x5CF2, 0x8D72, 0x5CF3, 0x8D73, 0x5CF4, 0x8D74, 0x5CF5, 0x8D75, 0x5CF6, 0x8D76, 0x5CF7, + 0x8D77, 0x5CF8, 0x8D78, 0x5CF9, 0x8D79, 0x5CFA, 0x8D7A, 0x5CFC, 0x8D7B, 0x5CFD, 0x8D7C, 0x5CFE, 0x8D7D, 0x5CFF, 0x8D7E, 0x5D00, + 0x8D80, 0x5D01, 0x8D81, 0x5D04, 0x8D82, 0x5D05, 0x8D83, 0x5D08, 0x8D84, 0x5D09, 0x8D85, 0x5D0A, 0x8D86, 0x5D0B, 0x8D87, 0x5D0C, + 0x8D88, 0x5D0D, 0x8D89, 0x5D0F, 0x8D8A, 0x5D10, 0x8D8B, 0x5D11, 0x8D8C, 0x5D12, 0x8D8D, 0x5D13, 0x8D8E, 0x5D15, 0x8D8F, 0x5D17, + 0x8D90, 0x5D18, 0x8D91, 0x5D19, 0x8D92, 0x5D1A, 0x8D93, 0x5D1C, 0x8D94, 0x5D1D, 0x8D95, 0x5D1F, 0x8D96, 0x5D20, 0x8D97, 0x5D21, + 0x8D98, 0x5D22, 0x8D99, 0x5D23, 0x8D9A, 0x5D25, 0x8D9B, 0x5D28, 0x8D9C, 0x5D2A, 0x8D9D, 0x5D2B, 0x8D9E, 0x5D2C, 0x8D9F, 0x5D2F, + 0x8DA0, 0x5D30, 0x8DA1, 0x5D31, 0x8DA2, 0x5D32, 0x8DA3, 0x5D33, 0x8DA4, 0x5D35, 0x8DA5, 0x5D36, 0x8DA6, 0x5D37, 0x8DA7, 0x5D38, + 0x8DA8, 0x5D39, 0x8DA9, 0x5D3A, 0x8DAA, 0x5D3B, 0x8DAB, 0x5D3C, 0x8DAC, 0x5D3F, 0x8DAD, 0x5D40, 0x8DAE, 0x5D41, 0x8DAF, 0x5D42, + 0x8DB0, 0x5D43, 0x8DB1, 0x5D44, 0x8DB2, 0x5D45, 0x8DB3, 0x5D46, 0x8DB4, 0x5D48, 0x8DB5, 0x5D49, 0x8DB6, 0x5D4D, 0x8DB7, 0x5D4E, + 0x8DB8, 0x5D4F, 0x8DB9, 0x5D50, 0x8DBA, 0x5D51, 0x8DBB, 0x5D52, 0x8DBC, 0x5D53, 0x8DBD, 0x5D54, 0x8DBE, 0x5D55, 0x8DBF, 0x5D56, + 0x8DC0, 0x5D57, 0x8DC1, 0x5D59, 0x8DC2, 0x5D5A, 0x8DC3, 0x5D5C, 0x8DC4, 0x5D5E, 0x8DC5, 0x5D5F, 0x8DC6, 0x5D60, 0x8DC7, 0x5D61, + 0x8DC8, 0x5D62, 0x8DC9, 0x5D63, 0x8DCA, 0x5D64, 0x8DCB, 0x5D65, 0x8DCC, 0x5D66, 0x8DCD, 0x5D67, 0x8DCE, 0x5D68, 0x8DCF, 0x5D6A, + 0x8DD0, 0x5D6D, 0x8DD1, 0x5D6E, 0x8DD2, 0x5D70, 0x8DD3, 0x5D71, 0x8DD4, 0x5D72, 0x8DD5, 0x5D73, 0x8DD6, 0x5D75, 0x8DD7, 0x5D76, + 0x8DD8, 0x5D77, 0x8DD9, 0x5D78, 0x8DDA, 0x5D79, 0x8DDB, 0x5D7A, 0x8DDC, 0x5D7B, 0x8DDD, 0x5D7C, 0x8DDE, 0x5D7D, 0x8DDF, 0x5D7E, + 0x8DE0, 0x5D7F, 0x8DE1, 0x5D80, 0x8DE2, 0x5D81, 0x8DE3, 0x5D83, 0x8DE4, 0x5D84, 0x8DE5, 0x5D85, 0x8DE6, 0x5D86, 0x8DE7, 0x5D87, + 0x8DE8, 0x5D88, 0x8DE9, 0x5D89, 0x8DEA, 0x5D8A, 0x8DEB, 0x5D8B, 0x8DEC, 0x5D8C, 0x8DED, 0x5D8D, 0x8DEE, 0x5D8E, 0x8DEF, 0x5D8F, + 0x8DF0, 0x5D90, 0x8DF1, 0x5D91, 0x8DF2, 0x5D92, 0x8DF3, 0x5D93, 0x8DF4, 0x5D94, 0x8DF5, 0x5D95, 0x8DF6, 0x5D96, 0x8DF7, 0x5D97, + 0x8DF8, 0x5D98, 0x8DF9, 0x5D9A, 0x8DFA, 0x5D9B, 0x8DFB, 0x5D9C, 0x8DFC, 0x5D9E, 0x8DFD, 0x5D9F, 0x8DFE, 0x5DA0, 0x8E40, 0x5DA1, + 0x8E41, 0x5DA2, 0x8E42, 0x5DA3, 0x8E43, 0x5DA4, 0x8E44, 0x5DA5, 0x8E45, 0x5DA6, 0x8E46, 0x5DA7, 0x8E47, 0x5DA8, 0x8E48, 0x5DA9, + 0x8E49, 0x5DAA, 0x8E4A, 0x5DAB, 0x8E4B, 0x5DAC, 0x8E4C, 0x5DAD, 0x8E4D, 0x5DAE, 0x8E4E, 0x5DAF, 0x8E4F, 0x5DB0, 0x8E50, 0x5DB1, + 0x8E51, 0x5DB2, 0x8E52, 0x5DB3, 0x8E53, 0x5DB4, 0x8E54, 0x5DB5, 0x8E55, 0x5DB6, 0x8E56, 0x5DB8, 0x8E57, 0x5DB9, 0x8E58, 0x5DBA, + 0x8E59, 0x5DBB, 0x8E5A, 0x5DBC, 0x8E5B, 0x5DBD, 0x8E5C, 0x5DBE, 0x8E5D, 0x5DBF, 0x8E5E, 0x5DC0, 0x8E5F, 0x5DC1, 0x8E60, 0x5DC2, + 0x8E61, 0x5DC3, 0x8E62, 0x5DC4, 0x8E63, 0x5DC6, 0x8E64, 0x5DC7, 0x8E65, 0x5DC8, 0x8E66, 0x5DC9, 0x8E67, 0x5DCA, 0x8E68, 0x5DCB, + 0x8E69, 0x5DCC, 0x8E6A, 0x5DCE, 0x8E6B, 0x5DCF, 0x8E6C, 0x5DD0, 0x8E6D, 0x5DD1, 0x8E6E, 0x5DD2, 0x8E6F, 0x5DD3, 0x8E70, 0x5DD4, + 0x8E71, 0x5DD5, 0x8E72, 0x5DD6, 0x8E73, 0x5DD7, 0x8E74, 0x5DD8, 0x8E75, 0x5DD9, 0x8E76, 0x5DDA, 0x8E77, 0x5DDC, 0x8E78, 0x5DDF, + 0x8E79, 0x5DE0, 0x8E7A, 0x5DE3, 0x8E7B, 0x5DE4, 0x8E7C, 0x5DEA, 0x8E7D, 0x5DEC, 0x8E7E, 0x5DED, 0x8E80, 0x5DF0, 0x8E81, 0x5DF5, + 0x8E82, 0x5DF6, 0x8E83, 0x5DF8, 0x8E84, 0x5DF9, 0x8E85, 0x5DFA, 0x8E86, 0x5DFB, 0x8E87, 0x5DFC, 0x8E88, 0x5DFF, 0x8E89, 0x5E00, + 0x8E8A, 0x5E04, 0x8E8B, 0x5E07, 0x8E8C, 0x5E09, 0x8E8D, 0x5E0A, 0x8E8E, 0x5E0B, 0x8E8F, 0x5E0D, 0x8E90, 0x5E0E, 0x8E91, 0x5E12, + 0x8E92, 0x5E13, 0x8E93, 0x5E17, 0x8E94, 0x5E1E, 0x8E95, 0x5E1F, 0x8E96, 0x5E20, 0x8E97, 0x5E21, 0x8E98, 0x5E22, 0x8E99, 0x5E23, + 0x8E9A, 0x5E24, 0x8E9B, 0x5E25, 0x8E9C, 0x5E28, 0x8E9D, 0x5E29, 0x8E9E, 0x5E2A, 0x8E9F, 0x5E2B, 0x8EA0, 0x5E2C, 0x8EA1, 0x5E2F, + 0x8EA2, 0x5E30, 0x8EA3, 0x5E32, 0x8EA4, 0x5E33, 0x8EA5, 0x5E34, 0x8EA6, 0x5E35, 0x8EA7, 0x5E36, 0x8EA8, 0x5E39, 0x8EA9, 0x5E3A, + 0x8EAA, 0x5E3E, 0x8EAB, 0x5E3F, 0x8EAC, 0x5E40, 0x8EAD, 0x5E41, 0x8EAE, 0x5E43, 0x8EAF, 0x5E46, 0x8EB0, 0x5E47, 0x8EB1, 0x5E48, + 0x8EB2, 0x5E49, 0x8EB3, 0x5E4A, 0x8EB4, 0x5E4B, 0x8EB5, 0x5E4D, 0x8EB6, 0x5E4E, 0x8EB7, 0x5E4F, 0x8EB8, 0x5E50, 0x8EB9, 0x5E51, + 0x8EBA, 0x5E52, 0x8EBB, 0x5E53, 0x8EBC, 0x5E56, 0x8EBD, 0x5E57, 0x8EBE, 0x5E58, 0x8EBF, 0x5E59, 0x8EC0, 0x5E5A, 0x8EC1, 0x5E5C, + 0x8EC2, 0x5E5D, 0x8EC3, 0x5E5F, 0x8EC4, 0x5E60, 0x8EC5, 0x5E63, 0x8EC6, 0x5E64, 0x8EC7, 0x5E65, 0x8EC8, 0x5E66, 0x8EC9, 0x5E67, + 0x8ECA, 0x5E68, 0x8ECB, 0x5E69, 0x8ECC, 0x5E6A, 0x8ECD, 0x5E6B, 0x8ECE, 0x5E6C, 0x8ECF, 0x5E6D, 0x8ED0, 0x5E6E, 0x8ED1, 0x5E6F, + 0x8ED2, 0x5E70, 0x8ED3, 0x5E71, 0x8ED4, 0x5E75, 0x8ED5, 0x5E77, 0x8ED6, 0x5E79, 0x8ED7, 0x5E7E, 0x8ED8, 0x5E81, 0x8ED9, 0x5E82, + 0x8EDA, 0x5E83, 0x8EDB, 0x5E85, 0x8EDC, 0x5E88, 0x8EDD, 0x5E89, 0x8EDE, 0x5E8C, 0x8EDF, 0x5E8D, 0x8EE0, 0x5E8E, 0x8EE1, 0x5E92, + 0x8EE2, 0x5E98, 0x8EE3, 0x5E9B, 0x8EE4, 0x5E9D, 0x8EE5, 0x5EA1, 0x8EE6, 0x5EA2, 0x8EE7, 0x5EA3, 0x8EE8, 0x5EA4, 0x8EE9, 0x5EA8, + 0x8EEA, 0x5EA9, 0x8EEB, 0x5EAA, 0x8EEC, 0x5EAB, 0x8EED, 0x5EAC, 0x8EEE, 0x5EAE, 0x8EEF, 0x5EAF, 0x8EF0, 0x5EB0, 0x8EF1, 0x5EB1, + 0x8EF2, 0x5EB2, 0x8EF3, 0x5EB4, 0x8EF4, 0x5EBA, 0x8EF5, 0x5EBB, 0x8EF6, 0x5EBC, 0x8EF7, 0x5EBD, 0x8EF8, 0x5EBF, 0x8EF9, 0x5EC0, + 0x8EFA, 0x5EC1, 0x8EFB, 0x5EC2, 0x8EFC, 0x5EC3, 0x8EFD, 0x5EC4, 0x8EFE, 0x5EC5, 0x8F40, 0x5EC6, 0x8F41, 0x5EC7, 0x8F42, 0x5EC8, + 0x8F43, 0x5ECB, 0x8F44, 0x5ECC, 0x8F45, 0x5ECD, 0x8F46, 0x5ECE, 0x8F47, 0x5ECF, 0x8F48, 0x5ED0, 0x8F49, 0x5ED4, 0x8F4A, 0x5ED5, + 0x8F4B, 0x5ED7, 0x8F4C, 0x5ED8, 0x8F4D, 0x5ED9, 0x8F4E, 0x5EDA, 0x8F4F, 0x5EDC, 0x8F50, 0x5EDD, 0x8F51, 0x5EDE, 0x8F52, 0x5EDF, + 0x8F53, 0x5EE0, 0x8F54, 0x5EE1, 0x8F55, 0x5EE2, 0x8F56, 0x5EE3, 0x8F57, 0x5EE4, 0x8F58, 0x5EE5, 0x8F59, 0x5EE6, 0x8F5A, 0x5EE7, + 0x8F5B, 0x5EE9, 0x8F5C, 0x5EEB, 0x8F5D, 0x5EEC, 0x8F5E, 0x5EED, 0x8F5F, 0x5EEE, 0x8F60, 0x5EEF, 0x8F61, 0x5EF0, 0x8F62, 0x5EF1, + 0x8F63, 0x5EF2, 0x8F64, 0x5EF3, 0x8F65, 0x5EF5, 0x8F66, 0x5EF8, 0x8F67, 0x5EF9, 0x8F68, 0x5EFB, 0x8F69, 0x5EFC, 0x8F6A, 0x5EFD, + 0x8F6B, 0x5F05, 0x8F6C, 0x5F06, 0x8F6D, 0x5F07, 0x8F6E, 0x5F09, 0x8F6F, 0x5F0C, 0x8F70, 0x5F0D, 0x8F71, 0x5F0E, 0x8F72, 0x5F10, + 0x8F73, 0x5F12, 0x8F74, 0x5F14, 0x8F75, 0x5F16, 0x8F76, 0x5F19, 0x8F77, 0x5F1A, 0x8F78, 0x5F1C, 0x8F79, 0x5F1D, 0x8F7A, 0x5F1E, + 0x8F7B, 0x5F21, 0x8F7C, 0x5F22, 0x8F7D, 0x5F23, 0x8F7E, 0x5F24, 0x8F80, 0x5F28, 0x8F81, 0x5F2B, 0x8F82, 0x5F2C, 0x8F83, 0x5F2E, + 0x8F84, 0x5F30, 0x8F85, 0x5F32, 0x8F86, 0x5F33, 0x8F87, 0x5F34, 0x8F88, 0x5F35, 0x8F89, 0x5F36, 0x8F8A, 0x5F37, 0x8F8B, 0x5F38, + 0x8F8C, 0x5F3B, 0x8F8D, 0x5F3D, 0x8F8E, 0x5F3E, 0x8F8F, 0x5F3F, 0x8F90, 0x5F41, 0x8F91, 0x5F42, 0x8F92, 0x5F43, 0x8F93, 0x5F44, + 0x8F94, 0x5F45, 0x8F95, 0x5F46, 0x8F96, 0x5F47, 0x8F97, 0x5F48, 0x8F98, 0x5F49, 0x8F99, 0x5F4A, 0x8F9A, 0x5F4B, 0x8F9B, 0x5F4C, + 0x8F9C, 0x5F4D, 0x8F9D, 0x5F4E, 0x8F9E, 0x5F4F, 0x8F9F, 0x5F51, 0x8FA0, 0x5F54, 0x8FA1, 0x5F59, 0x8FA2, 0x5F5A, 0x8FA3, 0x5F5B, + 0x8FA4, 0x5F5C, 0x8FA5, 0x5F5E, 0x8FA6, 0x5F5F, 0x8FA7, 0x5F60, 0x8FA8, 0x5F63, 0x8FA9, 0x5F65, 0x8FAA, 0x5F67, 0x8FAB, 0x5F68, + 0x8FAC, 0x5F6B, 0x8FAD, 0x5F6E, 0x8FAE, 0x5F6F, 0x8FAF, 0x5F72, 0x8FB0, 0x5F74, 0x8FB1, 0x5F75, 0x8FB2, 0x5F76, 0x8FB3, 0x5F78, + 0x8FB4, 0x5F7A, 0x8FB5, 0x5F7D, 0x8FB6, 0x5F7E, 0x8FB7, 0x5F7F, 0x8FB8, 0x5F83, 0x8FB9, 0x5F86, 0x8FBA, 0x5F8D, 0x8FBB, 0x5F8E, + 0x8FBC, 0x5F8F, 0x8FBD, 0x5F91, 0x8FBE, 0x5F93, 0x8FBF, 0x5F94, 0x8FC0, 0x5F96, 0x8FC1, 0x5F9A, 0x8FC2, 0x5F9B, 0x8FC3, 0x5F9D, + 0x8FC4, 0x5F9E, 0x8FC5, 0x5F9F, 0x8FC6, 0x5FA0, 0x8FC7, 0x5FA2, 0x8FC8, 0x5FA3, 0x8FC9, 0x5FA4, 0x8FCA, 0x5FA5, 0x8FCB, 0x5FA6, + 0x8FCC, 0x5FA7, 0x8FCD, 0x5FA9, 0x8FCE, 0x5FAB, 0x8FCF, 0x5FAC, 0x8FD0, 0x5FAF, 0x8FD1, 0x5FB0, 0x8FD2, 0x5FB1, 0x8FD3, 0x5FB2, + 0x8FD4, 0x5FB3, 0x8FD5, 0x5FB4, 0x8FD6, 0x5FB6, 0x8FD7, 0x5FB8, 0x8FD8, 0x5FB9, 0x8FD9, 0x5FBA, 0x8FDA, 0x5FBB, 0x8FDB, 0x5FBE, + 0x8FDC, 0x5FBF, 0x8FDD, 0x5FC0, 0x8FDE, 0x5FC1, 0x8FDF, 0x5FC2, 0x8FE0, 0x5FC7, 0x8FE1, 0x5FC8, 0x8FE2, 0x5FCA, 0x8FE3, 0x5FCB, + 0x8FE4, 0x5FCE, 0x8FE5, 0x5FD3, 0x8FE6, 0x5FD4, 0x8FE7, 0x5FD5, 0x8FE8, 0x5FDA, 0x8FE9, 0x5FDB, 0x8FEA, 0x5FDC, 0x8FEB, 0x5FDE, + 0x8FEC, 0x5FDF, 0x8FED, 0x5FE2, 0x8FEE, 0x5FE3, 0x8FEF, 0x5FE5, 0x8FF0, 0x5FE6, 0x8FF1, 0x5FE8, 0x8FF2, 0x5FE9, 0x8FF3, 0x5FEC, + 0x8FF4, 0x5FEF, 0x8FF5, 0x5FF0, 0x8FF6, 0x5FF2, 0x8FF7, 0x5FF3, 0x8FF8, 0x5FF4, 0x8FF9, 0x5FF6, 0x8FFA, 0x5FF7, 0x8FFB, 0x5FF9, + 0x8FFC, 0x5FFA, 0x8FFD, 0x5FFC, 0x8FFE, 0x6007, 0x9040, 0x6008, 0x9041, 0x6009, 0x9042, 0x600B, 0x9043, 0x600C, 0x9044, 0x6010, + 0x9045, 0x6011, 0x9046, 0x6013, 0x9047, 0x6017, 0x9048, 0x6018, 0x9049, 0x601A, 0x904A, 0x601E, 0x904B, 0x601F, 0x904C, 0x6022, + 0x904D, 0x6023, 0x904E, 0x6024, 0x904F, 0x602C, 0x9050, 0x602D, 0x9051, 0x602E, 0x9052, 0x6030, 0x9053, 0x6031, 0x9054, 0x6032, + 0x9055, 0x6033, 0x9056, 0x6034, 0x9057, 0x6036, 0x9058, 0x6037, 0x9059, 0x6038, 0x905A, 0x6039, 0x905B, 0x603A, 0x905C, 0x603D, + 0x905D, 0x603E, 0x905E, 0x6040, 0x905F, 0x6044, 0x9060, 0x6045, 0x9061, 0x6046, 0x9062, 0x6047, 0x9063, 0x6048, 0x9064, 0x6049, + 0x9065, 0x604A, 0x9066, 0x604C, 0x9067, 0x604E, 0x9068, 0x604F, 0x9069, 0x6051, 0x906A, 0x6053, 0x906B, 0x6054, 0x906C, 0x6056, + 0x906D, 0x6057, 0x906E, 0x6058, 0x906F, 0x605B, 0x9070, 0x605C, 0x9071, 0x605E, 0x9072, 0x605F, 0x9073, 0x6060, 0x9074, 0x6061, + 0x9075, 0x6065, 0x9076, 0x6066, 0x9077, 0x606E, 0x9078, 0x6071, 0x9079, 0x6072, 0x907A, 0x6074, 0x907B, 0x6075, 0x907C, 0x6077, + 0x907D, 0x607E, 0x907E, 0x6080, 0x9080, 0x6081, 0x9081, 0x6082, 0x9082, 0x6085, 0x9083, 0x6086, 0x9084, 0x6087, 0x9085, 0x6088, + 0x9086, 0x608A, 0x9087, 0x608B, 0x9088, 0x608E, 0x9089, 0x608F, 0x908A, 0x6090, 0x908B, 0x6091, 0x908C, 0x6093, 0x908D, 0x6095, + 0x908E, 0x6097, 0x908F, 0x6098, 0x9090, 0x6099, 0x9091, 0x609C, 0x9092, 0x609E, 0x9093, 0x60A1, 0x9094, 0x60A2, 0x9095, 0x60A4, + 0x9096, 0x60A5, 0x9097, 0x60A7, 0x9098, 0x60A9, 0x9099, 0x60AA, 0x909A, 0x60AE, 0x909B, 0x60B0, 0x909C, 0x60B3, 0x909D, 0x60B5, + 0x909E, 0x60B6, 0x909F, 0x60B7, 0x90A0, 0x60B9, 0x90A1, 0x60BA, 0x90A2, 0x60BD, 0x90A3, 0x60BE, 0x90A4, 0x60BF, 0x90A5, 0x60C0, + 0x90A6, 0x60C1, 0x90A7, 0x60C2, 0x90A8, 0x60C3, 0x90A9, 0x60C4, 0x90AA, 0x60C7, 0x90AB, 0x60C8, 0x90AC, 0x60C9, 0x90AD, 0x60CC, + 0x90AE, 0x60CD, 0x90AF, 0x60CE, 0x90B0, 0x60CF, 0x90B1, 0x60D0, 0x90B2, 0x60D2, 0x90B3, 0x60D3, 0x90B4, 0x60D4, 0x90B5, 0x60D6, + 0x90B6, 0x60D7, 0x90B7, 0x60D9, 0x90B8, 0x60DB, 0x90B9, 0x60DE, 0x90BA, 0x60E1, 0x90BB, 0x60E2, 0x90BC, 0x60E3, 0x90BD, 0x60E4, + 0x90BE, 0x60E5, 0x90BF, 0x60EA, 0x90C0, 0x60F1, 0x90C1, 0x60F2, 0x90C2, 0x60F5, 0x90C3, 0x60F7, 0x90C4, 0x60F8, 0x90C5, 0x60FB, + 0x90C6, 0x60FC, 0x90C7, 0x60FD, 0x90C8, 0x60FE, 0x90C9, 0x60FF, 0x90CA, 0x6102, 0x90CB, 0x6103, 0x90CC, 0x6104, 0x90CD, 0x6105, + 0x90CE, 0x6107, 0x90CF, 0x610A, 0x90D0, 0x610B, 0x90D1, 0x610C, 0x90D2, 0x6110, 0x90D3, 0x6111, 0x90D4, 0x6112, 0x90D5, 0x6113, + 0x90D6, 0x6114, 0x90D7, 0x6116, 0x90D8, 0x6117, 0x90D9, 0x6118, 0x90DA, 0x6119, 0x90DB, 0x611B, 0x90DC, 0x611C, 0x90DD, 0x611D, + 0x90DE, 0x611E, 0x90DF, 0x6121, 0x90E0, 0x6122, 0x90E1, 0x6125, 0x90E2, 0x6128, 0x90E3, 0x6129, 0x90E4, 0x612A, 0x90E5, 0x612C, + 0x90E6, 0x612D, 0x90E7, 0x612E, 0x90E8, 0x612F, 0x90E9, 0x6130, 0x90EA, 0x6131, 0x90EB, 0x6132, 0x90EC, 0x6133, 0x90ED, 0x6134, + 0x90EE, 0x6135, 0x90EF, 0x6136, 0x90F0, 0x6137, 0x90F1, 0x6138, 0x90F2, 0x6139, 0x90F3, 0x613A, 0x90F4, 0x613B, 0x90F5, 0x613C, + 0x90F6, 0x613D, 0x90F7, 0x613E, 0x90F8, 0x6140, 0x90F9, 0x6141, 0x90FA, 0x6142, 0x90FB, 0x6143, 0x90FC, 0x6144, 0x90FD, 0x6145, + 0x90FE, 0x6146, 0x9140, 0x6147, 0x9141, 0x6149, 0x9142, 0x614B, 0x9143, 0x614D, 0x9144, 0x614F, 0x9145, 0x6150, 0x9146, 0x6152, + 0x9147, 0x6153, 0x9148, 0x6154, 0x9149, 0x6156, 0x914A, 0x6157, 0x914B, 0x6158, 0x914C, 0x6159, 0x914D, 0x615A, 0x914E, 0x615B, + 0x914F, 0x615C, 0x9150, 0x615E, 0x9151, 0x615F, 0x9152, 0x6160, 0x9153, 0x6161, 0x9154, 0x6163, 0x9155, 0x6164, 0x9156, 0x6165, + 0x9157, 0x6166, 0x9158, 0x6169, 0x9159, 0x616A, 0x915A, 0x616B, 0x915B, 0x616C, 0x915C, 0x616D, 0x915D, 0x616E, 0x915E, 0x616F, + 0x915F, 0x6171, 0x9160, 0x6172, 0x9161, 0x6173, 0x9162, 0x6174, 0x9163, 0x6176, 0x9164, 0x6178, 0x9165, 0x6179, 0x9166, 0x617A, + 0x9167, 0x617B, 0x9168, 0x617C, 0x9169, 0x617D, 0x916A, 0x617E, 0x916B, 0x617F, 0x916C, 0x6180, 0x916D, 0x6181, 0x916E, 0x6182, + 0x916F, 0x6183, 0x9170, 0x6184, 0x9171, 0x6185, 0x9172, 0x6186, 0x9173, 0x6187, 0x9174, 0x6188, 0x9175, 0x6189, 0x9176, 0x618A, + 0x9177, 0x618C, 0x9178, 0x618D, 0x9179, 0x618F, 0x917A, 0x6190, 0x917B, 0x6191, 0x917C, 0x6192, 0x917D, 0x6193, 0x917E, 0x6195, + 0x9180, 0x6196, 0x9181, 0x6197, 0x9182, 0x6198, 0x9183, 0x6199, 0x9184, 0x619A, 0x9185, 0x619B, 0x9186, 0x619C, 0x9187, 0x619E, + 0x9188, 0x619F, 0x9189, 0x61A0, 0x918A, 0x61A1, 0x918B, 0x61A2, 0x918C, 0x61A3, 0x918D, 0x61A4, 0x918E, 0x61A5, 0x918F, 0x61A6, + 0x9190, 0x61AA, 0x9191, 0x61AB, 0x9192, 0x61AD, 0x9193, 0x61AE, 0x9194, 0x61AF, 0x9195, 0x61B0, 0x9196, 0x61B1, 0x9197, 0x61B2, + 0x9198, 0x61B3, 0x9199, 0x61B4, 0x919A, 0x61B5, 0x919B, 0x61B6, 0x919C, 0x61B8, 0x919D, 0x61B9, 0x919E, 0x61BA, 0x919F, 0x61BB, + 0x91A0, 0x61BC, 0x91A1, 0x61BD, 0x91A2, 0x61BF, 0x91A3, 0x61C0, 0x91A4, 0x61C1, 0x91A5, 0x61C3, 0x91A6, 0x61C4, 0x91A7, 0x61C5, + 0x91A8, 0x61C6, 0x91A9, 0x61C7, 0x91AA, 0x61C9, 0x91AB, 0x61CC, 0x91AC, 0x61CD, 0x91AD, 0x61CE, 0x91AE, 0x61CF, 0x91AF, 0x61D0, + 0x91B0, 0x61D3, 0x91B1, 0x61D5, 0x91B2, 0x61D6, 0x91B3, 0x61D7, 0x91B4, 0x61D8, 0x91B5, 0x61D9, 0x91B6, 0x61DA, 0x91B7, 0x61DB, + 0x91B8, 0x61DC, 0x91B9, 0x61DD, 0x91BA, 0x61DE, 0x91BB, 0x61DF, 0x91BC, 0x61E0, 0x91BD, 0x61E1, 0x91BE, 0x61E2, 0x91BF, 0x61E3, + 0x91C0, 0x61E4, 0x91C1, 0x61E5, 0x91C2, 0x61E7, 0x91C3, 0x61E8, 0x91C4, 0x61E9, 0x91C5, 0x61EA, 0x91C6, 0x61EB, 0x91C7, 0x61EC, + 0x91C8, 0x61ED, 0x91C9, 0x61EE, 0x91CA, 0x61EF, 0x91CB, 0x61F0, 0x91CC, 0x61F1, 0x91CD, 0x61F2, 0x91CE, 0x61F3, 0x91CF, 0x61F4, + 0x91D0, 0x61F6, 0x91D1, 0x61F7, 0x91D2, 0x61F8, 0x91D3, 0x61F9, 0x91D4, 0x61FA, 0x91D5, 0x61FB, 0x91D6, 0x61FC, 0x91D7, 0x61FD, + 0x91D8, 0x61FE, 0x91D9, 0x6200, 0x91DA, 0x6201, 0x91DB, 0x6202, 0x91DC, 0x6203, 0x91DD, 0x6204, 0x91DE, 0x6205, 0x91DF, 0x6207, + 0x91E0, 0x6209, 0x91E1, 0x6213, 0x91E2, 0x6214, 0x91E3, 0x6219, 0x91E4, 0x621C, 0x91E5, 0x621D, 0x91E6, 0x621E, 0x91E7, 0x6220, + 0x91E8, 0x6223, 0x91E9, 0x6226, 0x91EA, 0x6227, 0x91EB, 0x6228, 0x91EC, 0x6229, 0x91ED, 0x622B, 0x91EE, 0x622D, 0x91EF, 0x622F, + 0x91F0, 0x6230, 0x91F1, 0x6231, 0x91F2, 0x6232, 0x91F3, 0x6235, 0x91F4, 0x6236, 0x91F5, 0x6238, 0x91F6, 0x6239, 0x91F7, 0x623A, + 0x91F8, 0x623B, 0x91F9, 0x623C, 0x91FA, 0x6242, 0x91FB, 0x6244, 0x91FC, 0x6245, 0x91FD, 0x6246, 0x91FE, 0x624A, 0x9240, 0x624F, + 0x9241, 0x6250, 0x9242, 0x6255, 0x9243, 0x6256, 0x9244, 0x6257, 0x9245, 0x6259, 0x9246, 0x625A, 0x9247, 0x625C, 0x9248, 0x625D, + 0x9249, 0x625E, 0x924A, 0x625F, 0x924B, 0x6260, 0x924C, 0x6261, 0x924D, 0x6262, 0x924E, 0x6264, 0x924F, 0x6265, 0x9250, 0x6268, + 0x9251, 0x6271, 0x9252, 0x6272, 0x9253, 0x6274, 0x9254, 0x6275, 0x9255, 0x6277, 0x9256, 0x6278, 0x9257, 0x627A, 0x9258, 0x627B, + 0x9259, 0x627D, 0x925A, 0x6281, 0x925B, 0x6282, 0x925C, 0x6283, 0x925D, 0x6285, 0x925E, 0x6286, 0x925F, 0x6287, 0x9260, 0x6288, + 0x9261, 0x628B, 0x9262, 0x628C, 0x9263, 0x628D, 0x9264, 0x628E, 0x9265, 0x628F, 0x9266, 0x6290, 0x9267, 0x6294, 0x9268, 0x6299, + 0x9269, 0x629C, 0x926A, 0x629D, 0x926B, 0x629E, 0x926C, 0x62A3, 0x926D, 0x62A6, 0x926E, 0x62A7, 0x926F, 0x62A9, 0x9270, 0x62AA, + 0x9271, 0x62AD, 0x9272, 0x62AE, 0x9273, 0x62AF, 0x9274, 0x62B0, 0x9275, 0x62B2, 0x9276, 0x62B3, 0x9277, 0x62B4, 0x9278, 0x62B6, + 0x9279, 0x62B7, 0x927A, 0x62B8, 0x927B, 0x62BA, 0x927C, 0x62BE, 0x927D, 0x62C0, 0x927E, 0x62C1, 0x9280, 0x62C3, 0x9281, 0x62CB, + 0x9282, 0x62CF, 0x9283, 0x62D1, 0x9284, 0x62D5, 0x9285, 0x62DD, 0x9286, 0x62DE, 0x9287, 0x62E0, 0x9288, 0x62E1, 0x9289, 0x62E4, + 0x928A, 0x62EA, 0x928B, 0x62EB, 0x928C, 0x62F0, 0x928D, 0x62F2, 0x928E, 0x62F5, 0x928F, 0x62F8, 0x9290, 0x62F9, 0x9291, 0x62FA, + 0x9292, 0x62FB, 0x9293, 0x6300, 0x9294, 0x6303, 0x9295, 0x6304, 0x9296, 0x6305, 0x9297, 0x6306, 0x9298, 0x630A, 0x9299, 0x630B, + 0x929A, 0x630C, 0x929B, 0x630D, 0x929C, 0x630F, 0x929D, 0x6310, 0x929E, 0x6312, 0x929F, 0x6313, 0x92A0, 0x6314, 0x92A1, 0x6315, + 0x92A2, 0x6317, 0x92A3, 0x6318, 0x92A4, 0x6319, 0x92A5, 0x631C, 0x92A6, 0x6326, 0x92A7, 0x6327, 0x92A8, 0x6329, 0x92A9, 0x632C, + 0x92AA, 0x632D, 0x92AB, 0x632E, 0x92AC, 0x6330, 0x92AD, 0x6331, 0x92AE, 0x6333, 0x92AF, 0x6334, 0x92B0, 0x6335, 0x92B1, 0x6336, + 0x92B2, 0x6337, 0x92B3, 0x6338, 0x92B4, 0x633B, 0x92B5, 0x633C, 0x92B6, 0x633E, 0x92B7, 0x633F, 0x92B8, 0x6340, 0x92B9, 0x6341, + 0x92BA, 0x6344, 0x92BB, 0x6347, 0x92BC, 0x6348, 0x92BD, 0x634A, 0x92BE, 0x6351, 0x92BF, 0x6352, 0x92C0, 0x6353, 0x92C1, 0x6354, + 0x92C2, 0x6356, 0x92C3, 0x6357, 0x92C4, 0x6358, 0x92C5, 0x6359, 0x92C6, 0x635A, 0x92C7, 0x635B, 0x92C8, 0x635C, 0x92C9, 0x635D, + 0x92CA, 0x6360, 0x92CB, 0x6364, 0x92CC, 0x6365, 0x92CD, 0x6366, 0x92CE, 0x6368, 0x92CF, 0x636A, 0x92D0, 0x636B, 0x92D1, 0x636C, + 0x92D2, 0x636F, 0x92D3, 0x6370, 0x92D4, 0x6372, 0x92D5, 0x6373, 0x92D6, 0x6374, 0x92D7, 0x6375, 0x92D8, 0x6378, 0x92D9, 0x6379, + 0x92DA, 0x637C, 0x92DB, 0x637D, 0x92DC, 0x637E, 0x92DD, 0x637F, 0x92DE, 0x6381, 0x92DF, 0x6383, 0x92E0, 0x6384, 0x92E1, 0x6385, + 0x92E2, 0x6386, 0x92E3, 0x638B, 0x92E4, 0x638D, 0x92E5, 0x6391, 0x92E6, 0x6393, 0x92E7, 0x6394, 0x92E8, 0x6395, 0x92E9, 0x6397, + 0x92EA, 0x6399, 0x92EB, 0x639A, 0x92EC, 0x639B, 0x92ED, 0x639C, 0x92EE, 0x639D, 0x92EF, 0x639E, 0x92F0, 0x639F, 0x92F1, 0x63A1, + 0x92F2, 0x63A4, 0x92F3, 0x63A6, 0x92F4, 0x63AB, 0x92F5, 0x63AF, 0x92F6, 0x63B1, 0x92F7, 0x63B2, 0x92F8, 0x63B5, 0x92F9, 0x63B6, + 0x92FA, 0x63B9, 0x92FB, 0x63BB, 0x92FC, 0x63BD, 0x92FD, 0x63BF, 0x92FE, 0x63C0, 0x9340, 0x63C1, 0x9341, 0x63C2, 0x9342, 0x63C3, + 0x9343, 0x63C5, 0x9344, 0x63C7, 0x9345, 0x63C8, 0x9346, 0x63CA, 0x9347, 0x63CB, 0x9348, 0x63CC, 0x9349, 0x63D1, 0x934A, 0x63D3, + 0x934B, 0x63D4, 0x934C, 0x63D5, 0x934D, 0x63D7, 0x934E, 0x63D8, 0x934F, 0x63D9, 0x9350, 0x63DA, 0x9351, 0x63DB, 0x9352, 0x63DC, + 0x9353, 0x63DD, 0x9354, 0x63DF, 0x9355, 0x63E2, 0x9356, 0x63E4, 0x9357, 0x63E5, 0x9358, 0x63E6, 0x9359, 0x63E7, 0x935A, 0x63E8, + 0x935B, 0x63EB, 0x935C, 0x63EC, 0x935D, 0x63EE, 0x935E, 0x63EF, 0x935F, 0x63F0, 0x9360, 0x63F1, 0x9361, 0x63F3, 0x9362, 0x63F5, + 0x9363, 0x63F7, 0x9364, 0x63F9, 0x9365, 0x63FA, 0x9366, 0x63FB, 0x9367, 0x63FC, 0x9368, 0x63FE, 0x9369, 0x6403, 0x936A, 0x6404, + 0x936B, 0x6406, 0x936C, 0x6407, 0x936D, 0x6408, 0x936E, 0x6409, 0x936F, 0x640A, 0x9370, 0x640D, 0x9371, 0x640E, 0x9372, 0x6411, + 0x9373, 0x6412, 0x9374, 0x6415, 0x9375, 0x6416, 0x9376, 0x6417, 0x9377, 0x6418, 0x9378, 0x6419, 0x9379, 0x641A, 0x937A, 0x641D, + 0x937B, 0x641F, 0x937C, 0x6422, 0x937D, 0x6423, 0x937E, 0x6424, 0x9380, 0x6425, 0x9381, 0x6427, 0x9382, 0x6428, 0x9383, 0x6429, + 0x9384, 0x642B, 0x9385, 0x642E, 0x9386, 0x642F, 0x9387, 0x6430, 0x9388, 0x6431, 0x9389, 0x6432, 0x938A, 0x6433, 0x938B, 0x6435, + 0x938C, 0x6436, 0x938D, 0x6437, 0x938E, 0x6438, 0x938F, 0x6439, 0x9390, 0x643B, 0x9391, 0x643C, 0x9392, 0x643E, 0x9393, 0x6440, + 0x9394, 0x6442, 0x9395, 0x6443, 0x9396, 0x6449, 0x9397, 0x644B, 0x9398, 0x644C, 0x9399, 0x644D, 0x939A, 0x644E, 0x939B, 0x644F, + 0x939C, 0x6450, 0x939D, 0x6451, 0x939E, 0x6453, 0x939F, 0x6455, 0x93A0, 0x6456, 0x93A1, 0x6457, 0x93A2, 0x6459, 0x93A3, 0x645A, + 0x93A4, 0x645B, 0x93A5, 0x645C, 0x93A6, 0x645D, 0x93A7, 0x645F, 0x93A8, 0x6460, 0x93A9, 0x6461, 0x93AA, 0x6462, 0x93AB, 0x6463, + 0x93AC, 0x6464, 0x93AD, 0x6465, 0x93AE, 0x6466, 0x93AF, 0x6468, 0x93B0, 0x646A, 0x93B1, 0x646B, 0x93B2, 0x646C, 0x93B3, 0x646E, + 0x93B4, 0x646F, 0x93B5, 0x6470, 0x93B6, 0x6471, 0x93B7, 0x6472, 0x93B8, 0x6473, 0x93B9, 0x6474, 0x93BA, 0x6475, 0x93BB, 0x6476, + 0x93BC, 0x6477, 0x93BD, 0x647B, 0x93BE, 0x647C, 0x93BF, 0x647D, 0x93C0, 0x647E, 0x93C1, 0x647F, 0x93C2, 0x6480, 0x93C3, 0x6481, + 0x93C4, 0x6483, 0x93C5, 0x6486, 0x93C6, 0x6488, 0x93C7, 0x6489, 0x93C8, 0x648A, 0x93C9, 0x648B, 0x93CA, 0x648C, 0x93CB, 0x648D, + 0x93CC, 0x648E, 0x93CD, 0x648F, 0x93CE, 0x6490, 0x93CF, 0x6493, 0x93D0, 0x6494, 0x93D1, 0x6497, 0x93D2, 0x6498, 0x93D3, 0x649A, + 0x93D4, 0x649B, 0x93D5, 0x649C, 0x93D6, 0x649D, 0x93D7, 0x649F, 0x93D8, 0x64A0, 0x93D9, 0x64A1, 0x93DA, 0x64A2, 0x93DB, 0x64A3, + 0x93DC, 0x64A5, 0x93DD, 0x64A6, 0x93DE, 0x64A7, 0x93DF, 0x64A8, 0x93E0, 0x64AA, 0x93E1, 0x64AB, 0x93E2, 0x64AF, 0x93E3, 0x64B1, + 0x93E4, 0x64B2, 0x93E5, 0x64B3, 0x93E6, 0x64B4, 0x93E7, 0x64B6, 0x93E8, 0x64B9, 0x93E9, 0x64BB, 0x93EA, 0x64BD, 0x93EB, 0x64BE, + 0x93EC, 0x64BF, 0x93ED, 0x64C1, 0x93EE, 0x64C3, 0x93EF, 0x64C4, 0x93F0, 0x64C6, 0x93F1, 0x64C7, 0x93F2, 0x64C8, 0x93F3, 0x64C9, + 0x93F4, 0x64CA, 0x93F5, 0x64CB, 0x93F6, 0x64CC, 0x93F7, 0x64CF, 0x93F8, 0x64D1, 0x93F9, 0x64D3, 0x93FA, 0x64D4, 0x93FB, 0x64D5, + 0x93FC, 0x64D6, 0x93FD, 0x64D9, 0x93FE, 0x64DA, 0x9440, 0x64DB, 0x9441, 0x64DC, 0x9442, 0x64DD, 0x9443, 0x64DF, 0x9444, 0x64E0, + 0x9445, 0x64E1, 0x9446, 0x64E3, 0x9447, 0x64E5, 0x9448, 0x64E7, 0x9449, 0x64E8, 0x944A, 0x64E9, 0x944B, 0x64EA, 0x944C, 0x64EB, + 0x944D, 0x64EC, 0x944E, 0x64ED, 0x944F, 0x64EE, 0x9450, 0x64EF, 0x9451, 0x64F0, 0x9452, 0x64F1, 0x9453, 0x64F2, 0x9454, 0x64F3, + 0x9455, 0x64F4, 0x9456, 0x64F5, 0x9457, 0x64F6, 0x9458, 0x64F7, 0x9459, 0x64F8, 0x945A, 0x64F9, 0x945B, 0x64FA, 0x945C, 0x64FB, + 0x945D, 0x64FC, 0x945E, 0x64FD, 0x945F, 0x64FE, 0x9460, 0x64FF, 0x9461, 0x6501, 0x9462, 0x6502, 0x9463, 0x6503, 0x9464, 0x6504, + 0x9465, 0x6505, 0x9466, 0x6506, 0x9467, 0x6507, 0x9468, 0x6508, 0x9469, 0x650A, 0x946A, 0x650B, 0x946B, 0x650C, 0x946C, 0x650D, + 0x946D, 0x650E, 0x946E, 0x650F, 0x946F, 0x6510, 0x9470, 0x6511, 0x9471, 0x6513, 0x9472, 0x6514, 0x9473, 0x6515, 0x9474, 0x6516, + 0x9475, 0x6517, 0x9476, 0x6519, 0x9477, 0x651A, 0x9478, 0x651B, 0x9479, 0x651C, 0x947A, 0x651D, 0x947B, 0x651E, 0x947C, 0x651F, + 0x947D, 0x6520, 0x947E, 0x6521, 0x9480, 0x6522, 0x9481, 0x6523, 0x9482, 0x6524, 0x9483, 0x6526, 0x9484, 0x6527, 0x9485, 0x6528, + 0x9486, 0x6529, 0x9487, 0x652A, 0x9488, 0x652C, 0x9489, 0x652D, 0x948A, 0x6530, 0x948B, 0x6531, 0x948C, 0x6532, 0x948D, 0x6533, + 0x948E, 0x6537, 0x948F, 0x653A, 0x9490, 0x653C, 0x9491, 0x653D, 0x9492, 0x6540, 0x9493, 0x6541, 0x9494, 0x6542, 0x9495, 0x6543, + 0x9496, 0x6544, 0x9497, 0x6546, 0x9498, 0x6547, 0x9499, 0x654A, 0x949A, 0x654B, 0x949B, 0x654D, 0x949C, 0x654E, 0x949D, 0x6550, + 0x949E, 0x6552, 0x949F, 0x6553, 0x94A0, 0x6554, 0x94A1, 0x6557, 0x94A2, 0x6558, 0x94A3, 0x655A, 0x94A4, 0x655C, 0x94A5, 0x655F, + 0x94A6, 0x6560, 0x94A7, 0x6561, 0x94A8, 0x6564, 0x94A9, 0x6565, 0x94AA, 0x6567, 0x94AB, 0x6568, 0x94AC, 0x6569, 0x94AD, 0x656A, + 0x94AE, 0x656D, 0x94AF, 0x656E, 0x94B0, 0x656F, 0x94B1, 0x6571, 0x94B2, 0x6573, 0x94B3, 0x6575, 0x94B4, 0x6576, 0x94B5, 0x6578, + 0x94B6, 0x6579, 0x94B7, 0x657A, 0x94B8, 0x657B, 0x94B9, 0x657C, 0x94BA, 0x657D, 0x94BB, 0x657E, 0x94BC, 0x657F, 0x94BD, 0x6580, + 0x94BE, 0x6581, 0x94BF, 0x6582, 0x94C0, 0x6583, 0x94C1, 0x6584, 0x94C2, 0x6585, 0x94C3, 0x6586, 0x94C4, 0x6588, 0x94C5, 0x6589, + 0x94C6, 0x658A, 0x94C7, 0x658D, 0x94C8, 0x658E, 0x94C9, 0x658F, 0x94CA, 0x6592, 0x94CB, 0x6594, 0x94CC, 0x6595, 0x94CD, 0x6596, + 0x94CE, 0x6598, 0x94CF, 0x659A, 0x94D0, 0x659D, 0x94D1, 0x659E, 0x94D2, 0x65A0, 0x94D3, 0x65A2, 0x94D4, 0x65A3, 0x94D5, 0x65A6, + 0x94D6, 0x65A8, 0x94D7, 0x65AA, 0x94D8, 0x65AC, 0x94D9, 0x65AE, 0x94DA, 0x65B1, 0x94DB, 0x65B2, 0x94DC, 0x65B3, 0x94DD, 0x65B4, + 0x94DE, 0x65B5, 0x94DF, 0x65B6, 0x94E0, 0x65B7, 0x94E1, 0x65B8, 0x94E2, 0x65BA, 0x94E3, 0x65BB, 0x94E4, 0x65BE, 0x94E5, 0x65BF, + 0x94E6, 0x65C0, 0x94E7, 0x65C2, 0x94E8, 0x65C7, 0x94E9, 0x65C8, 0x94EA, 0x65C9, 0x94EB, 0x65CA, 0x94EC, 0x65CD, 0x94ED, 0x65D0, + 0x94EE, 0x65D1, 0x94EF, 0x65D3, 0x94F0, 0x65D4, 0x94F1, 0x65D5, 0x94F2, 0x65D8, 0x94F3, 0x65D9, 0x94F4, 0x65DA, 0x94F5, 0x65DB, + 0x94F6, 0x65DC, 0x94F7, 0x65DD, 0x94F8, 0x65DE, 0x94F9, 0x65DF, 0x94FA, 0x65E1, 0x94FB, 0x65E3, 0x94FC, 0x65E4, 0x94FD, 0x65EA, + 0x94FE, 0x65EB, 0x9540, 0x65F2, 0x9541, 0x65F3, 0x9542, 0x65F4, 0x9543, 0x65F5, 0x9544, 0x65F8, 0x9545, 0x65F9, 0x9546, 0x65FB, + 0x9547, 0x65FC, 0x9548, 0x65FD, 0x9549, 0x65FE, 0x954A, 0x65FF, 0x954B, 0x6601, 0x954C, 0x6604, 0x954D, 0x6605, 0x954E, 0x6607, + 0x954F, 0x6608, 0x9550, 0x6609, 0x9551, 0x660B, 0x9552, 0x660D, 0x9553, 0x6610, 0x9554, 0x6611, 0x9555, 0x6612, 0x9556, 0x6616, + 0x9557, 0x6617, 0x9558, 0x6618, 0x9559, 0x661A, 0x955A, 0x661B, 0x955B, 0x661C, 0x955C, 0x661E, 0x955D, 0x6621, 0x955E, 0x6622, + 0x955F, 0x6623, 0x9560, 0x6624, 0x9561, 0x6626, 0x9562, 0x6629, 0x9563, 0x662A, 0x9564, 0x662B, 0x9565, 0x662C, 0x9566, 0x662E, + 0x9567, 0x6630, 0x9568, 0x6632, 0x9569, 0x6633, 0x956A, 0x6637, 0x956B, 0x6638, 0x956C, 0x6639, 0x956D, 0x663A, 0x956E, 0x663B, + 0x956F, 0x663D, 0x9570, 0x663F, 0x9571, 0x6640, 0x9572, 0x6642, 0x9573, 0x6644, 0x9574, 0x6645, 0x9575, 0x6646, 0x9576, 0x6647, + 0x9577, 0x6648, 0x9578, 0x6649, 0x9579, 0x664A, 0x957A, 0x664D, 0x957B, 0x664E, 0x957C, 0x6650, 0x957D, 0x6651, 0x957E, 0x6658, + 0x9580, 0x6659, 0x9581, 0x665B, 0x9582, 0x665C, 0x9583, 0x665D, 0x9584, 0x665E, 0x9585, 0x6660, 0x9586, 0x6662, 0x9587, 0x6663, + 0x9588, 0x6665, 0x9589, 0x6667, 0x958A, 0x6669, 0x958B, 0x666A, 0x958C, 0x666B, 0x958D, 0x666C, 0x958E, 0x666D, 0x958F, 0x6671, + 0x9590, 0x6672, 0x9591, 0x6673, 0x9592, 0x6675, 0x9593, 0x6678, 0x9594, 0x6679, 0x9595, 0x667B, 0x9596, 0x667C, 0x9597, 0x667D, + 0x9598, 0x667F, 0x9599, 0x6680, 0x959A, 0x6681, 0x959B, 0x6683, 0x959C, 0x6685, 0x959D, 0x6686, 0x959E, 0x6688, 0x959F, 0x6689, + 0x95A0, 0x668A, 0x95A1, 0x668B, 0x95A2, 0x668D, 0x95A3, 0x668E, 0x95A4, 0x668F, 0x95A5, 0x6690, 0x95A6, 0x6692, 0x95A7, 0x6693, + 0x95A8, 0x6694, 0x95A9, 0x6695, 0x95AA, 0x6698, 0x95AB, 0x6699, 0x95AC, 0x669A, 0x95AD, 0x669B, 0x95AE, 0x669C, 0x95AF, 0x669E, + 0x95B0, 0x669F, 0x95B1, 0x66A0, 0x95B2, 0x66A1, 0x95B3, 0x66A2, 0x95B4, 0x66A3, 0x95B5, 0x66A4, 0x95B6, 0x66A5, 0x95B7, 0x66A6, + 0x95B8, 0x66A9, 0x95B9, 0x66AA, 0x95BA, 0x66AB, 0x95BB, 0x66AC, 0x95BC, 0x66AD, 0x95BD, 0x66AF, 0x95BE, 0x66B0, 0x95BF, 0x66B1, + 0x95C0, 0x66B2, 0x95C1, 0x66B3, 0x95C2, 0x66B5, 0x95C3, 0x66B6, 0x95C4, 0x66B7, 0x95C5, 0x66B8, 0x95C6, 0x66BA, 0x95C7, 0x66BB, + 0x95C8, 0x66BC, 0x95C9, 0x66BD, 0x95CA, 0x66BF, 0x95CB, 0x66C0, 0x95CC, 0x66C1, 0x95CD, 0x66C2, 0x95CE, 0x66C3, 0x95CF, 0x66C4, + 0x95D0, 0x66C5, 0x95D1, 0x66C6, 0x95D2, 0x66C7, 0x95D3, 0x66C8, 0x95D4, 0x66C9, 0x95D5, 0x66CA, 0x95D6, 0x66CB, 0x95D7, 0x66CC, + 0x95D8, 0x66CD, 0x95D9, 0x66CE, 0x95DA, 0x66CF, 0x95DB, 0x66D0, 0x95DC, 0x66D1, 0x95DD, 0x66D2, 0x95DE, 0x66D3, 0x95DF, 0x66D4, + 0x95E0, 0x66D5, 0x95E1, 0x66D6, 0x95E2, 0x66D7, 0x95E3, 0x66D8, 0x95E4, 0x66DA, 0x95E5, 0x66DE, 0x95E6, 0x66DF, 0x95E7, 0x66E0, + 0x95E8, 0x66E1, 0x95E9, 0x66E2, 0x95EA, 0x66E3, 0x95EB, 0x66E4, 0x95EC, 0x66E5, 0x95ED, 0x66E7, 0x95EE, 0x66E8, 0x95EF, 0x66EA, + 0x95F0, 0x66EB, 0x95F1, 0x66EC, 0x95F2, 0x66ED, 0x95F3, 0x66EE, 0x95F4, 0x66EF, 0x95F5, 0x66F1, 0x95F6, 0x66F5, 0x95F7, 0x66F6, + 0x95F8, 0x66F8, 0x95F9, 0x66FA, 0x95FA, 0x66FB, 0x95FB, 0x66FD, 0x95FC, 0x6701, 0x95FD, 0x6702, 0x95FE, 0x6703, 0x9640, 0x6704, + 0x9641, 0x6705, 0x9642, 0x6706, 0x9643, 0x6707, 0x9644, 0x670C, 0x9645, 0x670E, 0x9646, 0x670F, 0x9647, 0x6711, 0x9648, 0x6712, + 0x9649, 0x6713, 0x964A, 0x6716, 0x964B, 0x6718, 0x964C, 0x6719, 0x964D, 0x671A, 0x964E, 0x671C, 0x964F, 0x671E, 0x9650, 0x6720, + 0x9651, 0x6721, 0x9652, 0x6722, 0x9653, 0x6723, 0x9654, 0x6724, 0x9655, 0x6725, 0x9656, 0x6727, 0x9657, 0x6729, 0x9658, 0x672E, + 0x9659, 0x6730, 0x965A, 0x6732, 0x965B, 0x6733, 0x965C, 0x6736, 0x965D, 0x6737, 0x965E, 0x6738, 0x965F, 0x6739, 0x9660, 0x673B, + 0x9661, 0x673C, 0x9662, 0x673E, 0x9663, 0x673F, 0x9664, 0x6741, 0x9665, 0x6744, 0x9666, 0x6745, 0x9667, 0x6747, 0x9668, 0x674A, + 0x9669, 0x674B, 0x966A, 0x674D, 0x966B, 0x6752, 0x966C, 0x6754, 0x966D, 0x6755, 0x966E, 0x6757, 0x966F, 0x6758, 0x9670, 0x6759, + 0x9671, 0x675A, 0x9672, 0x675B, 0x9673, 0x675D, 0x9674, 0x6762, 0x9675, 0x6763, 0x9676, 0x6764, 0x9677, 0x6766, 0x9678, 0x6767, + 0x9679, 0x676B, 0x967A, 0x676C, 0x967B, 0x676E, 0x967C, 0x6771, 0x967D, 0x6774, 0x967E, 0x6776, 0x9680, 0x6778, 0x9681, 0x6779, + 0x9682, 0x677A, 0x9683, 0x677B, 0x9684, 0x677D, 0x9685, 0x6780, 0x9686, 0x6782, 0x9687, 0x6783, 0x9688, 0x6785, 0x9689, 0x6786, + 0x968A, 0x6788, 0x968B, 0x678A, 0x968C, 0x678C, 0x968D, 0x678D, 0x968E, 0x678E, 0x968F, 0x678F, 0x9690, 0x6791, 0x9691, 0x6792, + 0x9692, 0x6793, 0x9693, 0x6794, 0x9694, 0x6796, 0x9695, 0x6799, 0x9696, 0x679B, 0x9697, 0x679F, 0x9698, 0x67A0, 0x9699, 0x67A1, + 0x969A, 0x67A4, 0x969B, 0x67A6, 0x969C, 0x67A9, 0x969D, 0x67AC, 0x969E, 0x67AE, 0x969F, 0x67B1, 0x96A0, 0x67B2, 0x96A1, 0x67B4, + 0x96A2, 0x67B9, 0x96A3, 0x67BA, 0x96A4, 0x67BB, 0x96A5, 0x67BC, 0x96A6, 0x67BD, 0x96A7, 0x67BE, 0x96A8, 0x67BF, 0x96A9, 0x67C0, + 0x96AA, 0x67C2, 0x96AB, 0x67C5, 0x96AC, 0x67C6, 0x96AD, 0x67C7, 0x96AE, 0x67C8, 0x96AF, 0x67C9, 0x96B0, 0x67CA, 0x96B1, 0x67CB, + 0x96B2, 0x67CC, 0x96B3, 0x67CD, 0x96B4, 0x67CE, 0x96B5, 0x67D5, 0x96B6, 0x67D6, 0x96B7, 0x67D7, 0x96B8, 0x67DB, 0x96B9, 0x67DF, + 0x96BA, 0x67E1, 0x96BB, 0x67E3, 0x96BC, 0x67E4, 0x96BD, 0x67E6, 0x96BE, 0x67E7, 0x96BF, 0x67E8, 0x96C0, 0x67EA, 0x96C1, 0x67EB, + 0x96C2, 0x67ED, 0x96C3, 0x67EE, 0x96C4, 0x67F2, 0x96C5, 0x67F5, 0x96C6, 0x67F6, 0x96C7, 0x67F7, 0x96C8, 0x67F8, 0x96C9, 0x67F9, + 0x96CA, 0x67FA, 0x96CB, 0x67FB, 0x96CC, 0x67FC, 0x96CD, 0x67FE, 0x96CE, 0x6801, 0x96CF, 0x6802, 0x96D0, 0x6803, 0x96D1, 0x6804, + 0x96D2, 0x6806, 0x96D3, 0x680D, 0x96D4, 0x6810, 0x96D5, 0x6812, 0x96D6, 0x6814, 0x96D7, 0x6815, 0x96D8, 0x6818, 0x96D9, 0x6819, + 0x96DA, 0x681A, 0x96DB, 0x681B, 0x96DC, 0x681C, 0x96DD, 0x681E, 0x96DE, 0x681F, 0x96DF, 0x6820, 0x96E0, 0x6822, 0x96E1, 0x6823, + 0x96E2, 0x6824, 0x96E3, 0x6825, 0x96E4, 0x6826, 0x96E5, 0x6827, 0x96E6, 0x6828, 0x96E7, 0x682B, 0x96E8, 0x682C, 0x96E9, 0x682D, + 0x96EA, 0x682E, 0x96EB, 0x682F, 0x96EC, 0x6830, 0x96ED, 0x6831, 0x96EE, 0x6834, 0x96EF, 0x6835, 0x96F0, 0x6836, 0x96F1, 0x683A, + 0x96F2, 0x683B, 0x96F3, 0x683F, 0x96F4, 0x6847, 0x96F5, 0x684B, 0x96F6, 0x684D, 0x96F7, 0x684F, 0x96F8, 0x6852, 0x96F9, 0x6856, + 0x96FA, 0x6857, 0x96FB, 0x6858, 0x96FC, 0x6859, 0x96FD, 0x685A, 0x96FE, 0x685B, 0x9740, 0x685C, 0x9741, 0x685D, 0x9742, 0x685E, + 0x9743, 0x685F, 0x9744, 0x686A, 0x9745, 0x686C, 0x9746, 0x686D, 0x9747, 0x686E, 0x9748, 0x686F, 0x9749, 0x6870, 0x974A, 0x6871, + 0x974B, 0x6872, 0x974C, 0x6873, 0x974D, 0x6875, 0x974E, 0x6878, 0x974F, 0x6879, 0x9750, 0x687A, 0x9751, 0x687B, 0x9752, 0x687C, + 0x9753, 0x687D, 0x9754, 0x687E, 0x9755, 0x687F, 0x9756, 0x6880, 0x9757, 0x6882, 0x9758, 0x6884, 0x9759, 0x6887, 0x975A, 0x6888, + 0x975B, 0x6889, 0x975C, 0x688A, 0x975D, 0x688B, 0x975E, 0x688C, 0x975F, 0x688D, 0x9760, 0x688E, 0x9761, 0x6890, 0x9762, 0x6891, + 0x9763, 0x6892, 0x9764, 0x6894, 0x9765, 0x6895, 0x9766, 0x6896, 0x9767, 0x6898, 0x9768, 0x6899, 0x9769, 0x689A, 0x976A, 0x689B, + 0x976B, 0x689C, 0x976C, 0x689D, 0x976D, 0x689E, 0x976E, 0x689F, 0x976F, 0x68A0, 0x9770, 0x68A1, 0x9771, 0x68A3, 0x9772, 0x68A4, + 0x9773, 0x68A5, 0x9774, 0x68A9, 0x9775, 0x68AA, 0x9776, 0x68AB, 0x9777, 0x68AC, 0x9778, 0x68AE, 0x9779, 0x68B1, 0x977A, 0x68B2, + 0x977B, 0x68B4, 0x977C, 0x68B6, 0x977D, 0x68B7, 0x977E, 0x68B8, 0x9780, 0x68B9, 0x9781, 0x68BA, 0x9782, 0x68BB, 0x9783, 0x68BC, + 0x9784, 0x68BD, 0x9785, 0x68BE, 0x9786, 0x68BF, 0x9787, 0x68C1, 0x9788, 0x68C3, 0x9789, 0x68C4, 0x978A, 0x68C5, 0x978B, 0x68C6, + 0x978C, 0x68C7, 0x978D, 0x68C8, 0x978E, 0x68CA, 0x978F, 0x68CC, 0x9790, 0x68CE, 0x9791, 0x68CF, 0x9792, 0x68D0, 0x9793, 0x68D1, + 0x9794, 0x68D3, 0x9795, 0x68D4, 0x9796, 0x68D6, 0x9797, 0x68D7, 0x9798, 0x68D9, 0x9799, 0x68DB, 0x979A, 0x68DC, 0x979B, 0x68DD, + 0x979C, 0x68DE, 0x979D, 0x68DF, 0x979E, 0x68E1, 0x979F, 0x68E2, 0x97A0, 0x68E4, 0x97A1, 0x68E5, 0x97A2, 0x68E6, 0x97A3, 0x68E7, + 0x97A4, 0x68E8, 0x97A5, 0x68E9, 0x97A6, 0x68EA, 0x97A7, 0x68EB, 0x97A8, 0x68EC, 0x97A9, 0x68ED, 0x97AA, 0x68EF, 0x97AB, 0x68F2, + 0x97AC, 0x68F3, 0x97AD, 0x68F4, 0x97AE, 0x68F6, 0x97AF, 0x68F7, 0x97B0, 0x68F8, 0x97B1, 0x68FB, 0x97B2, 0x68FD, 0x97B3, 0x68FE, + 0x97B4, 0x68FF, 0x97B5, 0x6900, 0x97B6, 0x6902, 0x97B7, 0x6903, 0x97B8, 0x6904, 0x97B9, 0x6906, 0x97BA, 0x6907, 0x97BB, 0x6908, + 0x97BC, 0x6909, 0x97BD, 0x690A, 0x97BE, 0x690C, 0x97BF, 0x690F, 0x97C0, 0x6911, 0x97C1, 0x6913, 0x97C2, 0x6914, 0x97C3, 0x6915, + 0x97C4, 0x6916, 0x97C5, 0x6917, 0x97C6, 0x6918, 0x97C7, 0x6919, 0x97C8, 0x691A, 0x97C9, 0x691B, 0x97CA, 0x691C, 0x97CB, 0x691D, + 0x97CC, 0x691E, 0x97CD, 0x6921, 0x97CE, 0x6922, 0x97CF, 0x6923, 0x97D0, 0x6925, 0x97D1, 0x6926, 0x97D2, 0x6927, 0x97D3, 0x6928, + 0x97D4, 0x6929, 0x97D5, 0x692A, 0x97D6, 0x692B, 0x97D7, 0x692C, 0x97D8, 0x692E, 0x97D9, 0x692F, 0x97DA, 0x6931, 0x97DB, 0x6932, + 0x97DC, 0x6933, 0x97DD, 0x6935, 0x97DE, 0x6936, 0x97DF, 0x6937, 0x97E0, 0x6938, 0x97E1, 0x693A, 0x97E2, 0x693B, 0x97E3, 0x693C, + 0x97E4, 0x693E, 0x97E5, 0x6940, 0x97E6, 0x6941, 0x97E7, 0x6943, 0x97E8, 0x6944, 0x97E9, 0x6945, 0x97EA, 0x6946, 0x97EB, 0x6947, + 0x97EC, 0x6948, 0x97ED, 0x6949, 0x97EE, 0x694A, 0x97EF, 0x694B, 0x97F0, 0x694C, 0x97F1, 0x694D, 0x97F2, 0x694E, 0x97F3, 0x694F, + 0x97F4, 0x6950, 0x97F5, 0x6951, 0x97F6, 0x6952, 0x97F7, 0x6953, 0x97F8, 0x6955, 0x97F9, 0x6956, 0x97FA, 0x6958, 0x97FB, 0x6959, + 0x97FC, 0x695B, 0x97FD, 0x695C, 0x97FE, 0x695F, 0x9840, 0x6961, 0x9841, 0x6962, 0x9842, 0x6964, 0x9843, 0x6965, 0x9844, 0x6967, + 0x9845, 0x6968, 0x9846, 0x6969, 0x9847, 0x696A, 0x9848, 0x696C, 0x9849, 0x696D, 0x984A, 0x696F, 0x984B, 0x6970, 0x984C, 0x6972, + 0x984D, 0x6973, 0x984E, 0x6974, 0x984F, 0x6975, 0x9850, 0x6976, 0x9851, 0x697A, 0x9852, 0x697B, 0x9853, 0x697D, 0x9854, 0x697E, + 0x9855, 0x697F, 0x9856, 0x6981, 0x9857, 0x6983, 0x9858, 0x6985, 0x9859, 0x698A, 0x985A, 0x698B, 0x985B, 0x698C, 0x985C, 0x698E, + 0x985D, 0x698F, 0x985E, 0x6990, 0x985F, 0x6991, 0x9860, 0x6992, 0x9861, 0x6993, 0x9862, 0x6996, 0x9863, 0x6997, 0x9864, 0x6999, + 0x9865, 0x699A, 0x9866, 0x699D, 0x9867, 0x699E, 0x9868, 0x699F, 0x9869, 0x69A0, 0x986A, 0x69A1, 0x986B, 0x69A2, 0x986C, 0x69A3, + 0x986D, 0x69A4, 0x986E, 0x69A5, 0x986F, 0x69A6, 0x9870, 0x69A9, 0x9871, 0x69AA, 0x9872, 0x69AC, 0x9873, 0x69AE, 0x9874, 0x69AF, + 0x9875, 0x69B0, 0x9876, 0x69B2, 0x9877, 0x69B3, 0x9878, 0x69B5, 0x9879, 0x69B6, 0x987A, 0x69B8, 0x987B, 0x69B9, 0x987C, 0x69BA, + 0x987D, 0x69BC, 0x987E, 0x69BD, 0x9880, 0x69BE, 0x9881, 0x69BF, 0x9882, 0x69C0, 0x9883, 0x69C2, 0x9884, 0x69C3, 0x9885, 0x69C4, + 0x9886, 0x69C5, 0x9887, 0x69C6, 0x9888, 0x69C7, 0x9889, 0x69C8, 0x988A, 0x69C9, 0x988B, 0x69CB, 0x988C, 0x69CD, 0x988D, 0x69CF, + 0x988E, 0x69D1, 0x988F, 0x69D2, 0x9890, 0x69D3, 0x9891, 0x69D5, 0x9892, 0x69D6, 0x9893, 0x69D7, 0x9894, 0x69D8, 0x9895, 0x69D9, + 0x9896, 0x69DA, 0x9897, 0x69DC, 0x9898, 0x69DD, 0x9899, 0x69DE, 0x989A, 0x69E1, 0x989B, 0x69E2, 0x989C, 0x69E3, 0x989D, 0x69E4, + 0x989E, 0x69E5, 0x989F, 0x69E6, 0x98A0, 0x69E7, 0x98A1, 0x69E8, 0x98A2, 0x69E9, 0x98A3, 0x69EA, 0x98A4, 0x69EB, 0x98A5, 0x69EC, + 0x98A6, 0x69EE, 0x98A7, 0x69EF, 0x98A8, 0x69F0, 0x98A9, 0x69F1, 0x98AA, 0x69F3, 0x98AB, 0x69F4, 0x98AC, 0x69F5, 0x98AD, 0x69F6, + 0x98AE, 0x69F7, 0x98AF, 0x69F8, 0x98B0, 0x69F9, 0x98B1, 0x69FA, 0x98B2, 0x69FB, 0x98B3, 0x69FC, 0x98B4, 0x69FE, 0x98B5, 0x6A00, + 0x98B6, 0x6A01, 0x98B7, 0x6A02, 0x98B8, 0x6A03, 0x98B9, 0x6A04, 0x98BA, 0x6A05, 0x98BB, 0x6A06, 0x98BC, 0x6A07, 0x98BD, 0x6A08, + 0x98BE, 0x6A09, 0x98BF, 0x6A0B, 0x98C0, 0x6A0C, 0x98C1, 0x6A0D, 0x98C2, 0x6A0E, 0x98C3, 0x6A0F, 0x98C4, 0x6A10, 0x98C5, 0x6A11, + 0x98C6, 0x6A12, 0x98C7, 0x6A13, 0x98C8, 0x6A14, 0x98C9, 0x6A15, 0x98CA, 0x6A16, 0x98CB, 0x6A19, 0x98CC, 0x6A1A, 0x98CD, 0x6A1B, + 0x98CE, 0x6A1C, 0x98CF, 0x6A1D, 0x98D0, 0x6A1E, 0x98D1, 0x6A20, 0x98D2, 0x6A22, 0x98D3, 0x6A23, 0x98D4, 0x6A24, 0x98D5, 0x6A25, + 0x98D6, 0x6A26, 0x98D7, 0x6A27, 0x98D8, 0x6A29, 0x98D9, 0x6A2B, 0x98DA, 0x6A2C, 0x98DB, 0x6A2D, 0x98DC, 0x6A2E, 0x98DD, 0x6A30, + 0x98DE, 0x6A32, 0x98DF, 0x6A33, 0x98E0, 0x6A34, 0x98E1, 0x6A36, 0x98E2, 0x6A37, 0x98E3, 0x6A38, 0x98E4, 0x6A39, 0x98E5, 0x6A3A, + 0x98E6, 0x6A3B, 0x98E7, 0x6A3C, 0x98E8, 0x6A3F, 0x98E9, 0x6A40, 0x98EA, 0x6A41, 0x98EB, 0x6A42, 0x98EC, 0x6A43, 0x98ED, 0x6A45, + 0x98EE, 0x6A46, 0x98EF, 0x6A48, 0x98F0, 0x6A49, 0x98F1, 0x6A4A, 0x98F2, 0x6A4B, 0x98F3, 0x6A4C, 0x98F4, 0x6A4D, 0x98F5, 0x6A4E, + 0x98F6, 0x6A4F, 0x98F7, 0x6A51, 0x98F8, 0x6A52, 0x98F9, 0x6A53, 0x98FA, 0x6A54, 0x98FB, 0x6A55, 0x98FC, 0x6A56, 0x98FD, 0x6A57, + 0x98FE, 0x6A5A, 0x9940, 0x6A5C, 0x9941, 0x6A5D, 0x9942, 0x6A5E, 0x9943, 0x6A5F, 0x9944, 0x6A60, 0x9945, 0x6A62, 0x9946, 0x6A63, + 0x9947, 0x6A64, 0x9948, 0x6A66, 0x9949, 0x6A67, 0x994A, 0x6A68, 0x994B, 0x6A69, 0x994C, 0x6A6A, 0x994D, 0x6A6B, 0x994E, 0x6A6C, + 0x994F, 0x6A6D, 0x9950, 0x6A6E, 0x9951, 0x6A6F, 0x9952, 0x6A70, 0x9953, 0x6A72, 0x9954, 0x6A73, 0x9955, 0x6A74, 0x9956, 0x6A75, + 0x9957, 0x6A76, 0x9958, 0x6A77, 0x9959, 0x6A78, 0x995A, 0x6A7A, 0x995B, 0x6A7B, 0x995C, 0x6A7D, 0x995D, 0x6A7E, 0x995E, 0x6A7F, + 0x995F, 0x6A81, 0x9960, 0x6A82, 0x9961, 0x6A83, 0x9962, 0x6A85, 0x9963, 0x6A86, 0x9964, 0x6A87, 0x9965, 0x6A88, 0x9966, 0x6A89, + 0x9967, 0x6A8A, 0x9968, 0x6A8B, 0x9969, 0x6A8C, 0x996A, 0x6A8D, 0x996B, 0x6A8F, 0x996C, 0x6A92, 0x996D, 0x6A93, 0x996E, 0x6A94, + 0x996F, 0x6A95, 0x9970, 0x6A96, 0x9971, 0x6A98, 0x9972, 0x6A99, 0x9973, 0x6A9A, 0x9974, 0x6A9B, 0x9975, 0x6A9C, 0x9976, 0x6A9D, + 0x9977, 0x6A9E, 0x9978, 0x6A9F, 0x9979, 0x6AA1, 0x997A, 0x6AA2, 0x997B, 0x6AA3, 0x997C, 0x6AA4, 0x997D, 0x6AA5, 0x997E, 0x6AA6, + 0x9980, 0x6AA7, 0x9981, 0x6AA8, 0x9982, 0x6AAA, 0x9983, 0x6AAD, 0x9984, 0x6AAE, 0x9985, 0x6AAF, 0x9986, 0x6AB0, 0x9987, 0x6AB1, + 0x9988, 0x6AB2, 0x9989, 0x6AB3, 0x998A, 0x6AB4, 0x998B, 0x6AB5, 0x998C, 0x6AB6, 0x998D, 0x6AB7, 0x998E, 0x6AB8, 0x998F, 0x6AB9, + 0x9990, 0x6ABA, 0x9991, 0x6ABB, 0x9992, 0x6ABC, 0x9993, 0x6ABD, 0x9994, 0x6ABE, 0x9995, 0x6ABF, 0x9996, 0x6AC0, 0x9997, 0x6AC1, + 0x9998, 0x6AC2, 0x9999, 0x6AC3, 0x999A, 0x6AC4, 0x999B, 0x6AC5, 0x999C, 0x6AC6, 0x999D, 0x6AC7, 0x999E, 0x6AC8, 0x999F, 0x6AC9, + 0x99A0, 0x6ACA, 0x99A1, 0x6ACB, 0x99A2, 0x6ACC, 0x99A3, 0x6ACD, 0x99A4, 0x6ACE, 0x99A5, 0x6ACF, 0x99A6, 0x6AD0, 0x99A7, 0x6AD1, + 0x99A8, 0x6AD2, 0x99A9, 0x6AD3, 0x99AA, 0x6AD4, 0x99AB, 0x6AD5, 0x99AC, 0x6AD6, 0x99AD, 0x6AD7, 0x99AE, 0x6AD8, 0x99AF, 0x6AD9, + 0x99B0, 0x6ADA, 0x99B1, 0x6ADB, 0x99B2, 0x6ADC, 0x99B3, 0x6ADD, 0x99B4, 0x6ADE, 0x99B5, 0x6ADF, 0x99B6, 0x6AE0, 0x99B7, 0x6AE1, + 0x99B8, 0x6AE2, 0x99B9, 0x6AE3, 0x99BA, 0x6AE4, 0x99BB, 0x6AE5, 0x99BC, 0x6AE6, 0x99BD, 0x6AE7, 0x99BE, 0x6AE8, 0x99BF, 0x6AE9, + 0x99C0, 0x6AEA, 0x99C1, 0x6AEB, 0x99C2, 0x6AEC, 0x99C3, 0x6AED, 0x99C4, 0x6AEE, 0x99C5, 0x6AEF, 0x99C6, 0x6AF0, 0x99C7, 0x6AF1, + 0x99C8, 0x6AF2, 0x99C9, 0x6AF3, 0x99CA, 0x6AF4, 0x99CB, 0x6AF5, 0x99CC, 0x6AF6, 0x99CD, 0x6AF7, 0x99CE, 0x6AF8, 0x99CF, 0x6AF9, + 0x99D0, 0x6AFA, 0x99D1, 0x6AFB, 0x99D2, 0x6AFC, 0x99D3, 0x6AFD, 0x99D4, 0x6AFE, 0x99D5, 0x6AFF, 0x99D6, 0x6B00, 0x99D7, 0x6B01, + 0x99D8, 0x6B02, 0x99D9, 0x6B03, 0x99DA, 0x6B04, 0x99DB, 0x6B05, 0x99DC, 0x6B06, 0x99DD, 0x6B07, 0x99DE, 0x6B08, 0x99DF, 0x6B09, + 0x99E0, 0x6B0A, 0x99E1, 0x6B0B, 0x99E2, 0x6B0C, 0x99E3, 0x6B0D, 0x99E4, 0x6B0E, 0x99E5, 0x6B0F, 0x99E6, 0x6B10, 0x99E7, 0x6B11, + 0x99E8, 0x6B12, 0x99E9, 0x6B13, 0x99EA, 0x6B14, 0x99EB, 0x6B15, 0x99EC, 0x6B16, 0x99ED, 0x6B17, 0x99EE, 0x6B18, 0x99EF, 0x6B19, + 0x99F0, 0x6B1A, 0x99F1, 0x6B1B, 0x99F2, 0x6B1C, 0x99F3, 0x6B1D, 0x99F4, 0x6B1E, 0x99F5, 0x6B1F, 0x99F6, 0x6B25, 0x99F7, 0x6B26, + 0x99F8, 0x6B28, 0x99F9, 0x6B29, 0x99FA, 0x6B2A, 0x99FB, 0x6B2B, 0x99FC, 0x6B2C, 0x99FD, 0x6B2D, 0x99FE, 0x6B2E, 0x9A40, 0x6B2F, + 0x9A41, 0x6B30, 0x9A42, 0x6B31, 0x9A43, 0x6B33, 0x9A44, 0x6B34, 0x9A45, 0x6B35, 0x9A46, 0x6B36, 0x9A47, 0x6B38, 0x9A48, 0x6B3B, + 0x9A49, 0x6B3C, 0x9A4A, 0x6B3D, 0x9A4B, 0x6B3F, 0x9A4C, 0x6B40, 0x9A4D, 0x6B41, 0x9A4E, 0x6B42, 0x9A4F, 0x6B44, 0x9A50, 0x6B45, + 0x9A51, 0x6B48, 0x9A52, 0x6B4A, 0x9A53, 0x6B4B, 0x9A54, 0x6B4D, 0x9A55, 0x6B4E, 0x9A56, 0x6B4F, 0x9A57, 0x6B50, 0x9A58, 0x6B51, + 0x9A59, 0x6B52, 0x9A5A, 0x6B53, 0x9A5B, 0x6B54, 0x9A5C, 0x6B55, 0x9A5D, 0x6B56, 0x9A5E, 0x6B57, 0x9A5F, 0x6B58, 0x9A60, 0x6B5A, + 0x9A61, 0x6B5B, 0x9A62, 0x6B5C, 0x9A63, 0x6B5D, 0x9A64, 0x6B5E, 0x9A65, 0x6B5F, 0x9A66, 0x6B60, 0x9A67, 0x6B61, 0x9A68, 0x6B68, + 0x9A69, 0x6B69, 0x9A6A, 0x6B6B, 0x9A6B, 0x6B6C, 0x9A6C, 0x6B6D, 0x9A6D, 0x6B6E, 0x9A6E, 0x6B6F, 0x9A6F, 0x6B70, 0x9A70, 0x6B71, + 0x9A71, 0x6B72, 0x9A72, 0x6B73, 0x9A73, 0x6B74, 0x9A74, 0x6B75, 0x9A75, 0x6B76, 0x9A76, 0x6B77, 0x9A77, 0x6B78, 0x9A78, 0x6B7A, + 0x9A79, 0x6B7D, 0x9A7A, 0x6B7E, 0x9A7B, 0x6B7F, 0x9A7C, 0x6B80, 0x9A7D, 0x6B85, 0x9A7E, 0x6B88, 0x9A80, 0x6B8C, 0x9A81, 0x6B8E, + 0x9A82, 0x6B8F, 0x9A83, 0x6B90, 0x9A84, 0x6B91, 0x9A85, 0x6B94, 0x9A86, 0x6B95, 0x9A87, 0x6B97, 0x9A88, 0x6B98, 0x9A89, 0x6B99, + 0x9A8A, 0x6B9C, 0x9A8B, 0x6B9D, 0x9A8C, 0x6B9E, 0x9A8D, 0x6B9F, 0x9A8E, 0x6BA0, 0x9A8F, 0x6BA2, 0x9A90, 0x6BA3, 0x9A91, 0x6BA4, + 0x9A92, 0x6BA5, 0x9A93, 0x6BA6, 0x9A94, 0x6BA7, 0x9A95, 0x6BA8, 0x9A96, 0x6BA9, 0x9A97, 0x6BAB, 0x9A98, 0x6BAC, 0x9A99, 0x6BAD, + 0x9A9A, 0x6BAE, 0x9A9B, 0x6BAF, 0x9A9C, 0x6BB0, 0x9A9D, 0x6BB1, 0x9A9E, 0x6BB2, 0x9A9F, 0x6BB6, 0x9AA0, 0x6BB8, 0x9AA1, 0x6BB9, + 0x9AA2, 0x6BBA, 0x9AA3, 0x6BBB, 0x9AA4, 0x6BBC, 0x9AA5, 0x6BBD, 0x9AA6, 0x6BBE, 0x9AA7, 0x6BC0, 0x9AA8, 0x6BC3, 0x9AA9, 0x6BC4, + 0x9AAA, 0x6BC6, 0x9AAB, 0x6BC7, 0x9AAC, 0x6BC8, 0x9AAD, 0x6BC9, 0x9AAE, 0x6BCA, 0x9AAF, 0x6BCC, 0x9AB0, 0x6BCE, 0x9AB1, 0x6BD0, + 0x9AB2, 0x6BD1, 0x9AB3, 0x6BD8, 0x9AB4, 0x6BDA, 0x9AB5, 0x6BDC, 0x9AB6, 0x6BDD, 0x9AB7, 0x6BDE, 0x9AB8, 0x6BDF, 0x9AB9, 0x6BE0, + 0x9ABA, 0x6BE2, 0x9ABB, 0x6BE3, 0x9ABC, 0x6BE4, 0x9ABD, 0x6BE5, 0x9ABE, 0x6BE6, 0x9ABF, 0x6BE7, 0x9AC0, 0x6BE8, 0x9AC1, 0x6BE9, + 0x9AC2, 0x6BEC, 0x9AC3, 0x6BED, 0x9AC4, 0x6BEE, 0x9AC5, 0x6BF0, 0x9AC6, 0x6BF1, 0x9AC7, 0x6BF2, 0x9AC8, 0x6BF4, 0x9AC9, 0x6BF6, + 0x9ACA, 0x6BF7, 0x9ACB, 0x6BF8, 0x9ACC, 0x6BFA, 0x9ACD, 0x6BFB, 0x9ACE, 0x6BFC, 0x9ACF, 0x6BFE, 0x9AD0, 0x6BFF, 0x9AD1, 0x6C00, + 0x9AD2, 0x6C01, 0x9AD3, 0x6C02, 0x9AD4, 0x6C03, 0x9AD5, 0x6C04, 0x9AD6, 0x6C08, 0x9AD7, 0x6C09, 0x9AD8, 0x6C0A, 0x9AD9, 0x6C0B, + 0x9ADA, 0x6C0C, 0x9ADB, 0x6C0E, 0x9ADC, 0x6C12, 0x9ADD, 0x6C17, 0x9ADE, 0x6C1C, 0x9ADF, 0x6C1D, 0x9AE0, 0x6C1E, 0x9AE1, 0x6C20, + 0x9AE2, 0x6C23, 0x9AE3, 0x6C25, 0x9AE4, 0x6C2B, 0x9AE5, 0x6C2C, 0x9AE6, 0x6C2D, 0x9AE7, 0x6C31, 0x9AE8, 0x6C33, 0x9AE9, 0x6C36, + 0x9AEA, 0x6C37, 0x9AEB, 0x6C39, 0x9AEC, 0x6C3A, 0x9AED, 0x6C3B, 0x9AEE, 0x6C3C, 0x9AEF, 0x6C3E, 0x9AF0, 0x6C3F, 0x9AF1, 0x6C43, + 0x9AF2, 0x6C44, 0x9AF3, 0x6C45, 0x9AF4, 0x6C48, 0x9AF5, 0x6C4B, 0x9AF6, 0x6C4C, 0x9AF7, 0x6C4D, 0x9AF8, 0x6C4E, 0x9AF9, 0x6C4F, + 0x9AFA, 0x6C51, 0x9AFB, 0x6C52, 0x9AFC, 0x6C53, 0x9AFD, 0x6C56, 0x9AFE, 0x6C58, 0x9B40, 0x6C59, 0x9B41, 0x6C5A, 0x9B42, 0x6C62, + 0x9B43, 0x6C63, 0x9B44, 0x6C65, 0x9B45, 0x6C66, 0x9B46, 0x6C67, 0x9B47, 0x6C6B, 0x9B48, 0x6C6C, 0x9B49, 0x6C6D, 0x9B4A, 0x6C6E, + 0x9B4B, 0x6C6F, 0x9B4C, 0x6C71, 0x9B4D, 0x6C73, 0x9B4E, 0x6C75, 0x9B4F, 0x6C77, 0x9B50, 0x6C78, 0x9B51, 0x6C7A, 0x9B52, 0x6C7B, + 0x9B53, 0x6C7C, 0x9B54, 0x6C7F, 0x9B55, 0x6C80, 0x9B56, 0x6C84, 0x9B57, 0x6C87, 0x9B58, 0x6C8A, 0x9B59, 0x6C8B, 0x9B5A, 0x6C8D, + 0x9B5B, 0x6C8E, 0x9B5C, 0x6C91, 0x9B5D, 0x6C92, 0x9B5E, 0x6C95, 0x9B5F, 0x6C96, 0x9B60, 0x6C97, 0x9B61, 0x6C98, 0x9B62, 0x6C9A, + 0x9B63, 0x6C9C, 0x9B64, 0x6C9D, 0x9B65, 0x6C9E, 0x9B66, 0x6CA0, 0x9B67, 0x6CA2, 0x9B68, 0x6CA8, 0x9B69, 0x6CAC, 0x9B6A, 0x6CAF, + 0x9B6B, 0x6CB0, 0x9B6C, 0x6CB4, 0x9B6D, 0x6CB5, 0x9B6E, 0x6CB6, 0x9B6F, 0x6CB7, 0x9B70, 0x6CBA, 0x9B71, 0x6CC0, 0x9B72, 0x6CC1, + 0x9B73, 0x6CC2, 0x9B74, 0x6CC3, 0x9B75, 0x6CC6, 0x9B76, 0x6CC7, 0x9B77, 0x6CC8, 0x9B78, 0x6CCB, 0x9B79, 0x6CCD, 0x9B7A, 0x6CCE, + 0x9B7B, 0x6CCF, 0x9B7C, 0x6CD1, 0x9B7D, 0x6CD2, 0x9B7E, 0x6CD8, 0x9B80, 0x6CD9, 0x9B81, 0x6CDA, 0x9B82, 0x6CDC, 0x9B83, 0x6CDD, + 0x9B84, 0x6CDF, 0x9B85, 0x6CE4, 0x9B86, 0x6CE6, 0x9B87, 0x6CE7, 0x9B88, 0x6CE9, 0x9B89, 0x6CEC, 0x9B8A, 0x6CED, 0x9B8B, 0x6CF2, + 0x9B8C, 0x6CF4, 0x9B8D, 0x6CF9, 0x9B8E, 0x6CFF, 0x9B8F, 0x6D00, 0x9B90, 0x6D02, 0x9B91, 0x6D03, 0x9B92, 0x6D05, 0x9B93, 0x6D06, + 0x9B94, 0x6D08, 0x9B95, 0x6D09, 0x9B96, 0x6D0A, 0x9B97, 0x6D0D, 0x9B98, 0x6D0F, 0x9B99, 0x6D10, 0x9B9A, 0x6D11, 0x9B9B, 0x6D13, + 0x9B9C, 0x6D14, 0x9B9D, 0x6D15, 0x9B9E, 0x6D16, 0x9B9F, 0x6D18, 0x9BA0, 0x6D1C, 0x9BA1, 0x6D1D, 0x9BA2, 0x6D1F, 0x9BA3, 0x6D20, + 0x9BA4, 0x6D21, 0x9BA5, 0x6D22, 0x9BA6, 0x6D23, 0x9BA7, 0x6D24, 0x9BA8, 0x6D26, 0x9BA9, 0x6D28, 0x9BAA, 0x6D29, 0x9BAB, 0x6D2C, + 0x9BAC, 0x6D2D, 0x9BAD, 0x6D2F, 0x9BAE, 0x6D30, 0x9BAF, 0x6D34, 0x9BB0, 0x6D36, 0x9BB1, 0x6D37, 0x9BB2, 0x6D38, 0x9BB3, 0x6D3A, + 0x9BB4, 0x6D3F, 0x9BB5, 0x6D40, 0x9BB6, 0x6D42, 0x9BB7, 0x6D44, 0x9BB8, 0x6D49, 0x9BB9, 0x6D4C, 0x9BBA, 0x6D50, 0x9BBB, 0x6D55, + 0x9BBC, 0x6D56, 0x9BBD, 0x6D57, 0x9BBE, 0x6D58, 0x9BBF, 0x6D5B, 0x9BC0, 0x6D5D, 0x9BC1, 0x6D5F, 0x9BC2, 0x6D61, 0x9BC3, 0x6D62, + 0x9BC4, 0x6D64, 0x9BC5, 0x6D65, 0x9BC6, 0x6D67, 0x9BC7, 0x6D68, 0x9BC8, 0x6D6B, 0x9BC9, 0x6D6C, 0x9BCA, 0x6D6D, 0x9BCB, 0x6D70, + 0x9BCC, 0x6D71, 0x9BCD, 0x6D72, 0x9BCE, 0x6D73, 0x9BCF, 0x6D75, 0x9BD0, 0x6D76, 0x9BD1, 0x6D79, 0x9BD2, 0x6D7A, 0x9BD3, 0x6D7B, + 0x9BD4, 0x6D7D, 0x9BD5, 0x6D7E, 0x9BD6, 0x6D7F, 0x9BD7, 0x6D80, 0x9BD8, 0x6D81, 0x9BD9, 0x6D83, 0x9BDA, 0x6D84, 0x9BDB, 0x6D86, + 0x9BDC, 0x6D87, 0x9BDD, 0x6D8A, 0x9BDE, 0x6D8B, 0x9BDF, 0x6D8D, 0x9BE0, 0x6D8F, 0x9BE1, 0x6D90, 0x9BE2, 0x6D92, 0x9BE3, 0x6D96, + 0x9BE4, 0x6D97, 0x9BE5, 0x6D98, 0x9BE6, 0x6D99, 0x9BE7, 0x6D9A, 0x9BE8, 0x6D9C, 0x9BE9, 0x6DA2, 0x9BEA, 0x6DA5, 0x9BEB, 0x6DAC, + 0x9BEC, 0x6DAD, 0x9BED, 0x6DB0, 0x9BEE, 0x6DB1, 0x9BEF, 0x6DB3, 0x9BF0, 0x6DB4, 0x9BF1, 0x6DB6, 0x9BF2, 0x6DB7, 0x9BF3, 0x6DB9, + 0x9BF4, 0x6DBA, 0x9BF5, 0x6DBB, 0x9BF6, 0x6DBC, 0x9BF7, 0x6DBD, 0x9BF8, 0x6DBE, 0x9BF9, 0x6DC1, 0x9BFA, 0x6DC2, 0x9BFB, 0x6DC3, + 0x9BFC, 0x6DC8, 0x9BFD, 0x6DC9, 0x9BFE, 0x6DCA, 0x9C40, 0x6DCD, 0x9C41, 0x6DCE, 0x9C42, 0x6DCF, 0x9C43, 0x6DD0, 0x9C44, 0x6DD2, + 0x9C45, 0x6DD3, 0x9C46, 0x6DD4, 0x9C47, 0x6DD5, 0x9C48, 0x6DD7, 0x9C49, 0x6DDA, 0x9C4A, 0x6DDB, 0x9C4B, 0x6DDC, 0x9C4C, 0x6DDF, + 0x9C4D, 0x6DE2, 0x9C4E, 0x6DE3, 0x9C4F, 0x6DE5, 0x9C50, 0x6DE7, 0x9C51, 0x6DE8, 0x9C52, 0x6DE9, 0x9C53, 0x6DEA, 0x9C54, 0x6DED, + 0x9C55, 0x6DEF, 0x9C56, 0x6DF0, 0x9C57, 0x6DF2, 0x9C58, 0x6DF4, 0x9C59, 0x6DF5, 0x9C5A, 0x6DF6, 0x9C5B, 0x6DF8, 0x9C5C, 0x6DFA, + 0x9C5D, 0x6DFD, 0x9C5E, 0x6DFE, 0x9C5F, 0x6DFF, 0x9C60, 0x6E00, 0x9C61, 0x6E01, 0x9C62, 0x6E02, 0x9C63, 0x6E03, 0x9C64, 0x6E04, + 0x9C65, 0x6E06, 0x9C66, 0x6E07, 0x9C67, 0x6E08, 0x9C68, 0x6E09, 0x9C69, 0x6E0B, 0x9C6A, 0x6E0F, 0x9C6B, 0x6E12, 0x9C6C, 0x6E13, + 0x9C6D, 0x6E15, 0x9C6E, 0x6E18, 0x9C6F, 0x6E19, 0x9C70, 0x6E1B, 0x9C71, 0x6E1C, 0x9C72, 0x6E1E, 0x9C73, 0x6E1F, 0x9C74, 0x6E22, + 0x9C75, 0x6E26, 0x9C76, 0x6E27, 0x9C77, 0x6E28, 0x9C78, 0x6E2A, 0x9C79, 0x6E2C, 0x9C7A, 0x6E2E, 0x9C7B, 0x6E30, 0x9C7C, 0x6E31, + 0x9C7D, 0x6E33, 0x9C7E, 0x6E35, 0x9C80, 0x6E36, 0x9C81, 0x6E37, 0x9C82, 0x6E39, 0x9C83, 0x6E3B, 0x9C84, 0x6E3C, 0x9C85, 0x6E3D, + 0x9C86, 0x6E3E, 0x9C87, 0x6E3F, 0x9C88, 0x6E40, 0x9C89, 0x6E41, 0x9C8A, 0x6E42, 0x9C8B, 0x6E45, 0x9C8C, 0x6E46, 0x9C8D, 0x6E47, + 0x9C8E, 0x6E48, 0x9C8F, 0x6E49, 0x9C90, 0x6E4A, 0x9C91, 0x6E4B, 0x9C92, 0x6E4C, 0x9C93, 0x6E4F, 0x9C94, 0x6E50, 0x9C95, 0x6E51, + 0x9C96, 0x6E52, 0x9C97, 0x6E55, 0x9C98, 0x6E57, 0x9C99, 0x6E59, 0x9C9A, 0x6E5A, 0x9C9B, 0x6E5C, 0x9C9C, 0x6E5D, 0x9C9D, 0x6E5E, + 0x9C9E, 0x6E60, 0x9C9F, 0x6E61, 0x9CA0, 0x6E62, 0x9CA1, 0x6E63, 0x9CA2, 0x6E64, 0x9CA3, 0x6E65, 0x9CA4, 0x6E66, 0x9CA5, 0x6E67, + 0x9CA6, 0x6E68, 0x9CA7, 0x6E69, 0x9CA8, 0x6E6A, 0x9CA9, 0x6E6C, 0x9CAA, 0x6E6D, 0x9CAB, 0x6E6F, 0x9CAC, 0x6E70, 0x9CAD, 0x6E71, + 0x9CAE, 0x6E72, 0x9CAF, 0x6E73, 0x9CB0, 0x6E74, 0x9CB1, 0x6E75, 0x9CB2, 0x6E76, 0x9CB3, 0x6E77, 0x9CB4, 0x6E78, 0x9CB5, 0x6E79, + 0x9CB6, 0x6E7A, 0x9CB7, 0x6E7B, 0x9CB8, 0x6E7C, 0x9CB9, 0x6E7D, 0x9CBA, 0x6E80, 0x9CBB, 0x6E81, 0x9CBC, 0x6E82, 0x9CBD, 0x6E84, + 0x9CBE, 0x6E87, 0x9CBF, 0x6E88, 0x9CC0, 0x6E8A, 0x9CC1, 0x6E8B, 0x9CC2, 0x6E8C, 0x9CC3, 0x6E8D, 0x9CC4, 0x6E8E, 0x9CC5, 0x6E91, + 0x9CC6, 0x6E92, 0x9CC7, 0x6E93, 0x9CC8, 0x6E94, 0x9CC9, 0x6E95, 0x9CCA, 0x6E96, 0x9CCB, 0x6E97, 0x9CCC, 0x6E99, 0x9CCD, 0x6E9A, + 0x9CCE, 0x6E9B, 0x9CCF, 0x6E9D, 0x9CD0, 0x6E9E, 0x9CD1, 0x6EA0, 0x9CD2, 0x6EA1, 0x9CD3, 0x6EA3, 0x9CD4, 0x6EA4, 0x9CD5, 0x6EA6, + 0x9CD6, 0x6EA8, 0x9CD7, 0x6EA9, 0x9CD8, 0x6EAB, 0x9CD9, 0x6EAC, 0x9CDA, 0x6EAD, 0x9CDB, 0x6EAE, 0x9CDC, 0x6EB0, 0x9CDD, 0x6EB3, + 0x9CDE, 0x6EB5, 0x9CDF, 0x6EB8, 0x9CE0, 0x6EB9, 0x9CE1, 0x6EBC, 0x9CE2, 0x6EBE, 0x9CE3, 0x6EBF, 0x9CE4, 0x6EC0, 0x9CE5, 0x6EC3, + 0x9CE6, 0x6EC4, 0x9CE7, 0x6EC5, 0x9CE8, 0x6EC6, 0x9CE9, 0x6EC8, 0x9CEA, 0x6EC9, 0x9CEB, 0x6ECA, 0x9CEC, 0x6ECC, 0x9CED, 0x6ECD, + 0x9CEE, 0x6ECE, 0x9CEF, 0x6ED0, 0x9CF0, 0x6ED2, 0x9CF1, 0x6ED6, 0x9CF2, 0x6ED8, 0x9CF3, 0x6ED9, 0x9CF4, 0x6EDB, 0x9CF5, 0x6EDC, + 0x9CF6, 0x6EDD, 0x9CF7, 0x6EE3, 0x9CF8, 0x6EE7, 0x9CF9, 0x6EEA, 0x9CFA, 0x6EEB, 0x9CFB, 0x6EEC, 0x9CFC, 0x6EED, 0x9CFD, 0x6EEE, + 0x9CFE, 0x6EEF, 0x9D40, 0x6EF0, 0x9D41, 0x6EF1, 0x9D42, 0x6EF2, 0x9D43, 0x6EF3, 0x9D44, 0x6EF5, 0x9D45, 0x6EF6, 0x9D46, 0x6EF7, + 0x9D47, 0x6EF8, 0x9D48, 0x6EFA, 0x9D49, 0x6EFB, 0x9D4A, 0x6EFC, 0x9D4B, 0x6EFD, 0x9D4C, 0x6EFE, 0x9D4D, 0x6EFF, 0x9D4E, 0x6F00, + 0x9D4F, 0x6F01, 0x9D50, 0x6F03, 0x9D51, 0x6F04, 0x9D52, 0x6F05, 0x9D53, 0x6F07, 0x9D54, 0x6F08, 0x9D55, 0x6F0A, 0x9D56, 0x6F0B, + 0x9D57, 0x6F0C, 0x9D58, 0x6F0D, 0x9D59, 0x6F0E, 0x9D5A, 0x6F10, 0x9D5B, 0x6F11, 0x9D5C, 0x6F12, 0x9D5D, 0x6F16, 0x9D5E, 0x6F17, + 0x9D5F, 0x6F18, 0x9D60, 0x6F19, 0x9D61, 0x6F1A, 0x9D62, 0x6F1B, 0x9D63, 0x6F1C, 0x9D64, 0x6F1D, 0x9D65, 0x6F1E, 0x9D66, 0x6F1F, + 0x9D67, 0x6F21, 0x9D68, 0x6F22, 0x9D69, 0x6F23, 0x9D6A, 0x6F25, 0x9D6B, 0x6F26, 0x9D6C, 0x6F27, 0x9D6D, 0x6F28, 0x9D6E, 0x6F2C, + 0x9D6F, 0x6F2E, 0x9D70, 0x6F30, 0x9D71, 0x6F32, 0x9D72, 0x6F34, 0x9D73, 0x6F35, 0x9D74, 0x6F37, 0x9D75, 0x6F38, 0x9D76, 0x6F39, + 0x9D77, 0x6F3A, 0x9D78, 0x6F3B, 0x9D79, 0x6F3C, 0x9D7A, 0x6F3D, 0x9D7B, 0x6F3F, 0x9D7C, 0x6F40, 0x9D7D, 0x6F41, 0x9D7E, 0x6F42, + 0x9D80, 0x6F43, 0x9D81, 0x6F44, 0x9D82, 0x6F45, 0x9D83, 0x6F48, 0x9D84, 0x6F49, 0x9D85, 0x6F4A, 0x9D86, 0x6F4C, 0x9D87, 0x6F4E, + 0x9D88, 0x6F4F, 0x9D89, 0x6F50, 0x9D8A, 0x6F51, 0x9D8B, 0x6F52, 0x9D8C, 0x6F53, 0x9D8D, 0x6F54, 0x9D8E, 0x6F55, 0x9D8F, 0x6F56, + 0x9D90, 0x6F57, 0x9D91, 0x6F59, 0x9D92, 0x6F5A, 0x9D93, 0x6F5B, 0x9D94, 0x6F5D, 0x9D95, 0x6F5F, 0x9D96, 0x6F60, 0x9D97, 0x6F61, + 0x9D98, 0x6F63, 0x9D99, 0x6F64, 0x9D9A, 0x6F65, 0x9D9B, 0x6F67, 0x9D9C, 0x6F68, 0x9D9D, 0x6F69, 0x9D9E, 0x6F6A, 0x9D9F, 0x6F6B, + 0x9DA0, 0x6F6C, 0x9DA1, 0x6F6F, 0x9DA2, 0x6F70, 0x9DA3, 0x6F71, 0x9DA4, 0x6F73, 0x9DA5, 0x6F75, 0x9DA6, 0x6F76, 0x9DA7, 0x6F77, + 0x9DA8, 0x6F79, 0x9DA9, 0x6F7B, 0x9DAA, 0x6F7D, 0x9DAB, 0x6F7E, 0x9DAC, 0x6F7F, 0x9DAD, 0x6F80, 0x9DAE, 0x6F81, 0x9DAF, 0x6F82, + 0x9DB0, 0x6F83, 0x9DB1, 0x6F85, 0x9DB2, 0x6F86, 0x9DB3, 0x6F87, 0x9DB4, 0x6F8A, 0x9DB5, 0x6F8B, 0x9DB6, 0x6F8F, 0x9DB7, 0x6F90, + 0x9DB8, 0x6F91, 0x9DB9, 0x6F92, 0x9DBA, 0x6F93, 0x9DBB, 0x6F94, 0x9DBC, 0x6F95, 0x9DBD, 0x6F96, 0x9DBE, 0x6F97, 0x9DBF, 0x6F98, + 0x9DC0, 0x6F99, 0x9DC1, 0x6F9A, 0x9DC2, 0x6F9B, 0x9DC3, 0x6F9D, 0x9DC4, 0x6F9E, 0x9DC5, 0x6F9F, 0x9DC6, 0x6FA0, 0x9DC7, 0x6FA2, + 0x9DC8, 0x6FA3, 0x9DC9, 0x6FA4, 0x9DCA, 0x6FA5, 0x9DCB, 0x6FA6, 0x9DCC, 0x6FA8, 0x9DCD, 0x6FA9, 0x9DCE, 0x6FAA, 0x9DCF, 0x6FAB, + 0x9DD0, 0x6FAC, 0x9DD1, 0x6FAD, 0x9DD2, 0x6FAE, 0x9DD3, 0x6FAF, 0x9DD4, 0x6FB0, 0x9DD5, 0x6FB1, 0x9DD6, 0x6FB2, 0x9DD7, 0x6FB4, + 0x9DD8, 0x6FB5, 0x9DD9, 0x6FB7, 0x9DDA, 0x6FB8, 0x9DDB, 0x6FBA, 0x9DDC, 0x6FBB, 0x9DDD, 0x6FBC, 0x9DDE, 0x6FBD, 0x9DDF, 0x6FBE, + 0x9DE0, 0x6FBF, 0x9DE1, 0x6FC1, 0x9DE2, 0x6FC3, 0x9DE3, 0x6FC4, 0x9DE4, 0x6FC5, 0x9DE5, 0x6FC6, 0x9DE6, 0x6FC7, 0x9DE7, 0x6FC8, + 0x9DE8, 0x6FCA, 0x9DE9, 0x6FCB, 0x9DEA, 0x6FCC, 0x9DEB, 0x6FCD, 0x9DEC, 0x6FCE, 0x9DED, 0x6FCF, 0x9DEE, 0x6FD0, 0x9DEF, 0x6FD3, + 0x9DF0, 0x6FD4, 0x9DF1, 0x6FD5, 0x9DF2, 0x6FD6, 0x9DF3, 0x6FD7, 0x9DF4, 0x6FD8, 0x9DF5, 0x6FD9, 0x9DF6, 0x6FDA, 0x9DF7, 0x6FDB, + 0x9DF8, 0x6FDC, 0x9DF9, 0x6FDD, 0x9DFA, 0x6FDF, 0x9DFB, 0x6FE2, 0x9DFC, 0x6FE3, 0x9DFD, 0x6FE4, 0x9DFE, 0x6FE5, 0x9E40, 0x6FE6, + 0x9E41, 0x6FE7, 0x9E42, 0x6FE8, 0x9E43, 0x6FE9, 0x9E44, 0x6FEA, 0x9E45, 0x6FEB, 0x9E46, 0x6FEC, 0x9E47, 0x6FED, 0x9E48, 0x6FF0, + 0x9E49, 0x6FF1, 0x9E4A, 0x6FF2, 0x9E4B, 0x6FF3, 0x9E4C, 0x6FF4, 0x9E4D, 0x6FF5, 0x9E4E, 0x6FF6, 0x9E4F, 0x6FF7, 0x9E50, 0x6FF8, + 0x9E51, 0x6FF9, 0x9E52, 0x6FFA, 0x9E53, 0x6FFB, 0x9E54, 0x6FFC, 0x9E55, 0x6FFD, 0x9E56, 0x6FFE, 0x9E57, 0x6FFF, 0x9E58, 0x7000, + 0x9E59, 0x7001, 0x9E5A, 0x7002, 0x9E5B, 0x7003, 0x9E5C, 0x7004, 0x9E5D, 0x7005, 0x9E5E, 0x7006, 0x9E5F, 0x7007, 0x9E60, 0x7008, + 0x9E61, 0x7009, 0x9E62, 0x700A, 0x9E63, 0x700B, 0x9E64, 0x700C, 0x9E65, 0x700D, 0x9E66, 0x700E, 0x9E67, 0x700F, 0x9E68, 0x7010, + 0x9E69, 0x7012, 0x9E6A, 0x7013, 0x9E6B, 0x7014, 0x9E6C, 0x7015, 0x9E6D, 0x7016, 0x9E6E, 0x7017, 0x9E6F, 0x7018, 0x9E70, 0x7019, + 0x9E71, 0x701C, 0x9E72, 0x701D, 0x9E73, 0x701E, 0x9E74, 0x701F, 0x9E75, 0x7020, 0x9E76, 0x7021, 0x9E77, 0x7022, 0x9E78, 0x7024, + 0x9E79, 0x7025, 0x9E7A, 0x7026, 0x9E7B, 0x7027, 0x9E7C, 0x7028, 0x9E7D, 0x7029, 0x9E7E, 0x702A, 0x9E80, 0x702B, 0x9E81, 0x702C, + 0x9E82, 0x702D, 0x9E83, 0x702E, 0x9E84, 0x702F, 0x9E85, 0x7030, 0x9E86, 0x7031, 0x9E87, 0x7032, 0x9E88, 0x7033, 0x9E89, 0x7034, + 0x9E8A, 0x7036, 0x9E8B, 0x7037, 0x9E8C, 0x7038, 0x9E8D, 0x703A, 0x9E8E, 0x703B, 0x9E8F, 0x703C, 0x9E90, 0x703D, 0x9E91, 0x703E, + 0x9E92, 0x703F, 0x9E93, 0x7040, 0x9E94, 0x7041, 0x9E95, 0x7042, 0x9E96, 0x7043, 0x9E97, 0x7044, 0x9E98, 0x7045, 0x9E99, 0x7046, + 0x9E9A, 0x7047, 0x9E9B, 0x7048, 0x9E9C, 0x7049, 0x9E9D, 0x704A, 0x9E9E, 0x704B, 0x9E9F, 0x704D, 0x9EA0, 0x704E, 0x9EA1, 0x7050, + 0x9EA2, 0x7051, 0x9EA3, 0x7052, 0x9EA4, 0x7053, 0x9EA5, 0x7054, 0x9EA6, 0x7055, 0x9EA7, 0x7056, 0x9EA8, 0x7057, 0x9EA9, 0x7058, + 0x9EAA, 0x7059, 0x9EAB, 0x705A, 0x9EAC, 0x705B, 0x9EAD, 0x705C, 0x9EAE, 0x705D, 0x9EAF, 0x705F, 0x9EB0, 0x7060, 0x9EB1, 0x7061, + 0x9EB2, 0x7062, 0x9EB3, 0x7063, 0x9EB4, 0x7064, 0x9EB5, 0x7065, 0x9EB6, 0x7066, 0x9EB7, 0x7067, 0x9EB8, 0x7068, 0x9EB9, 0x7069, + 0x9EBA, 0x706A, 0x9EBB, 0x706E, 0x9EBC, 0x7071, 0x9EBD, 0x7072, 0x9EBE, 0x7073, 0x9EBF, 0x7074, 0x9EC0, 0x7077, 0x9EC1, 0x7079, + 0x9EC2, 0x707A, 0x9EC3, 0x707B, 0x9EC4, 0x707D, 0x9EC5, 0x7081, 0x9EC6, 0x7082, 0x9EC7, 0x7083, 0x9EC8, 0x7084, 0x9EC9, 0x7086, + 0x9ECA, 0x7087, 0x9ECB, 0x7088, 0x9ECC, 0x708B, 0x9ECD, 0x708C, 0x9ECE, 0x708D, 0x9ECF, 0x708F, 0x9ED0, 0x7090, 0x9ED1, 0x7091, + 0x9ED2, 0x7093, 0x9ED3, 0x7097, 0x9ED4, 0x7098, 0x9ED5, 0x709A, 0x9ED6, 0x709B, 0x9ED7, 0x709E, 0x9ED8, 0x709F, 0x9ED9, 0x70A0, + 0x9EDA, 0x70A1, 0x9EDB, 0x70A2, 0x9EDC, 0x70A3, 0x9EDD, 0x70A4, 0x9EDE, 0x70A5, 0x9EDF, 0x70A6, 0x9EE0, 0x70A7, 0x9EE1, 0x70A8, + 0x9EE2, 0x70A9, 0x9EE3, 0x70AA, 0x9EE4, 0x70B0, 0x9EE5, 0x70B2, 0x9EE6, 0x70B4, 0x9EE7, 0x70B5, 0x9EE8, 0x70B6, 0x9EE9, 0x70BA, + 0x9EEA, 0x70BE, 0x9EEB, 0x70BF, 0x9EEC, 0x70C4, 0x9EED, 0x70C5, 0x9EEE, 0x70C6, 0x9EEF, 0x70C7, 0x9EF0, 0x70C9, 0x9EF1, 0x70CB, + 0x9EF2, 0x70CC, 0x9EF3, 0x70CD, 0x9EF4, 0x70CE, 0x9EF5, 0x70CF, 0x9EF6, 0x70D0, 0x9EF7, 0x70D1, 0x9EF8, 0x70D2, 0x9EF9, 0x70D3, + 0x9EFA, 0x70D4, 0x9EFB, 0x70D5, 0x9EFC, 0x70D6, 0x9EFD, 0x70D7, 0x9EFE, 0x70DA, 0x9F40, 0x70DC, 0x9F41, 0x70DD, 0x9F42, 0x70DE, + 0x9F43, 0x70E0, 0x9F44, 0x70E1, 0x9F45, 0x70E2, 0x9F46, 0x70E3, 0x9F47, 0x70E5, 0x9F48, 0x70EA, 0x9F49, 0x70EE, 0x9F4A, 0x70F0, + 0x9F4B, 0x70F1, 0x9F4C, 0x70F2, 0x9F4D, 0x70F3, 0x9F4E, 0x70F4, 0x9F4F, 0x70F5, 0x9F50, 0x70F6, 0x9F51, 0x70F8, 0x9F52, 0x70FA, + 0x9F53, 0x70FB, 0x9F54, 0x70FC, 0x9F55, 0x70FE, 0x9F56, 0x70FF, 0x9F57, 0x7100, 0x9F58, 0x7101, 0x9F59, 0x7102, 0x9F5A, 0x7103, + 0x9F5B, 0x7104, 0x9F5C, 0x7105, 0x9F5D, 0x7106, 0x9F5E, 0x7107, 0x9F5F, 0x7108, 0x9F60, 0x710B, 0x9F61, 0x710C, 0x9F62, 0x710D, + 0x9F63, 0x710E, 0x9F64, 0x710F, 0x9F65, 0x7111, 0x9F66, 0x7112, 0x9F67, 0x7114, 0x9F68, 0x7117, 0x9F69, 0x711B, 0x9F6A, 0x711C, + 0x9F6B, 0x711D, 0x9F6C, 0x711E, 0x9F6D, 0x711F, 0x9F6E, 0x7120, 0x9F6F, 0x7121, 0x9F70, 0x7122, 0x9F71, 0x7123, 0x9F72, 0x7124, + 0x9F73, 0x7125, 0x9F74, 0x7127, 0x9F75, 0x7128, 0x9F76, 0x7129, 0x9F77, 0x712A, 0x9F78, 0x712B, 0x9F79, 0x712C, 0x9F7A, 0x712D, + 0x9F7B, 0x712E, 0x9F7C, 0x7132, 0x9F7D, 0x7133, 0x9F7E, 0x7134, 0x9F80, 0x7135, 0x9F81, 0x7137, 0x9F82, 0x7138, 0x9F83, 0x7139, + 0x9F84, 0x713A, 0x9F85, 0x713B, 0x9F86, 0x713C, 0x9F87, 0x713D, 0x9F88, 0x713E, 0x9F89, 0x713F, 0x9F8A, 0x7140, 0x9F8B, 0x7141, + 0x9F8C, 0x7142, 0x9F8D, 0x7143, 0x9F8E, 0x7144, 0x9F8F, 0x7146, 0x9F90, 0x7147, 0x9F91, 0x7148, 0x9F92, 0x7149, 0x9F93, 0x714B, + 0x9F94, 0x714D, 0x9F95, 0x714F, 0x9F96, 0x7150, 0x9F97, 0x7151, 0x9F98, 0x7152, 0x9F99, 0x7153, 0x9F9A, 0x7154, 0x9F9B, 0x7155, + 0x9F9C, 0x7156, 0x9F9D, 0x7157, 0x9F9E, 0x7158, 0x9F9F, 0x7159, 0x9FA0, 0x715A, 0x9FA1, 0x715B, 0x9FA2, 0x715D, 0x9FA3, 0x715F, + 0x9FA4, 0x7160, 0x9FA5, 0x7161, 0x9FA6, 0x7162, 0x9FA7, 0x7163, 0x9FA8, 0x7165, 0x9FA9, 0x7169, 0x9FAA, 0x716A, 0x9FAB, 0x716B, + 0x9FAC, 0x716C, 0x9FAD, 0x716D, 0x9FAE, 0x716F, 0x9FAF, 0x7170, 0x9FB0, 0x7171, 0x9FB1, 0x7174, 0x9FB2, 0x7175, 0x9FB3, 0x7176, + 0x9FB4, 0x7177, 0x9FB5, 0x7179, 0x9FB6, 0x717B, 0x9FB7, 0x717C, 0x9FB8, 0x717E, 0x9FB9, 0x717F, 0x9FBA, 0x7180, 0x9FBB, 0x7181, + 0x9FBC, 0x7182, 0x9FBD, 0x7183, 0x9FBE, 0x7185, 0x9FBF, 0x7186, 0x9FC0, 0x7187, 0x9FC1, 0x7188, 0x9FC2, 0x7189, 0x9FC3, 0x718B, + 0x9FC4, 0x718C, 0x9FC5, 0x718D, 0x9FC6, 0x718E, 0x9FC7, 0x7190, 0x9FC8, 0x7191, 0x9FC9, 0x7192, 0x9FCA, 0x7193, 0x9FCB, 0x7195, + 0x9FCC, 0x7196, 0x9FCD, 0x7197, 0x9FCE, 0x719A, 0x9FCF, 0x719B, 0x9FD0, 0x719C, 0x9FD1, 0x719D, 0x9FD2, 0x719E, 0x9FD3, 0x71A1, + 0x9FD4, 0x71A2, 0x9FD5, 0x71A3, 0x9FD6, 0x71A4, 0x9FD7, 0x71A5, 0x9FD8, 0x71A6, 0x9FD9, 0x71A7, 0x9FDA, 0x71A9, 0x9FDB, 0x71AA, + 0x9FDC, 0x71AB, 0x9FDD, 0x71AD, 0x9FDE, 0x71AE, 0x9FDF, 0x71AF, 0x9FE0, 0x71B0, 0x9FE1, 0x71B1, 0x9FE2, 0x71B2, 0x9FE3, 0x71B4, + 0x9FE4, 0x71B6, 0x9FE5, 0x71B7, 0x9FE6, 0x71B8, 0x9FE7, 0x71BA, 0x9FE8, 0x71BB, 0x9FE9, 0x71BC, 0x9FEA, 0x71BD, 0x9FEB, 0x71BE, + 0x9FEC, 0x71BF, 0x9FED, 0x71C0, 0x9FEE, 0x71C1, 0x9FEF, 0x71C2, 0x9FF0, 0x71C4, 0x9FF1, 0x71C5, 0x9FF2, 0x71C6, 0x9FF3, 0x71C7, + 0x9FF4, 0x71C8, 0x9FF5, 0x71C9, 0x9FF6, 0x71CA, 0x9FF7, 0x71CB, 0x9FF8, 0x71CC, 0x9FF9, 0x71CD, 0x9FFA, 0x71CF, 0x9FFB, 0x71D0, + 0x9FFC, 0x71D1, 0x9FFD, 0x71D2, 0x9FFE, 0x71D3, 0xA040, 0x71D6, 0xA041, 0x71D7, 0xA042, 0x71D8, 0xA043, 0x71D9, 0xA044, 0x71DA, + 0xA045, 0x71DB, 0xA046, 0x71DC, 0xA047, 0x71DD, 0xA048, 0x71DE, 0xA049, 0x71DF, 0xA04A, 0x71E1, 0xA04B, 0x71E2, 0xA04C, 0x71E3, + 0xA04D, 0x71E4, 0xA04E, 0x71E6, 0xA04F, 0x71E8, 0xA050, 0x71E9, 0xA051, 0x71EA, 0xA052, 0x71EB, 0xA053, 0x71EC, 0xA054, 0x71ED, + 0xA055, 0x71EF, 0xA056, 0x71F0, 0xA057, 0x71F1, 0xA058, 0x71F2, 0xA059, 0x71F3, 0xA05A, 0x71F4, 0xA05B, 0x71F5, 0xA05C, 0x71F6, + 0xA05D, 0x71F7, 0xA05E, 0x71F8, 0xA05F, 0x71FA, 0xA060, 0x71FB, 0xA061, 0x71FC, 0xA062, 0x71FD, 0xA063, 0x71FE, 0xA064, 0x71FF, + 0xA065, 0x7200, 0xA066, 0x7201, 0xA067, 0x7202, 0xA068, 0x7203, 0xA069, 0x7204, 0xA06A, 0x7205, 0xA06B, 0x7207, 0xA06C, 0x7208, + 0xA06D, 0x7209, 0xA06E, 0x720A, 0xA06F, 0x720B, 0xA070, 0x720C, 0xA071, 0x720D, 0xA072, 0x720E, 0xA073, 0x720F, 0xA074, 0x7210, + 0xA075, 0x7211, 0xA076, 0x7212, 0xA077, 0x7213, 0xA078, 0x7214, 0xA079, 0x7215, 0xA07A, 0x7216, 0xA07B, 0x7217, 0xA07C, 0x7218, + 0xA07D, 0x7219, 0xA07E, 0x721A, 0xA080, 0x721B, 0xA081, 0x721C, 0xA082, 0x721E, 0xA083, 0x721F, 0xA084, 0x7220, 0xA085, 0x7221, + 0xA086, 0x7222, 0xA087, 0x7223, 0xA088, 0x7224, 0xA089, 0x7225, 0xA08A, 0x7226, 0xA08B, 0x7227, 0xA08C, 0x7229, 0xA08D, 0x722B, + 0xA08E, 0x722D, 0xA08F, 0x722E, 0xA090, 0x722F, 0xA091, 0x7232, 0xA092, 0x7233, 0xA093, 0x7234, 0xA094, 0x723A, 0xA095, 0x723C, + 0xA096, 0x723E, 0xA097, 0x7240, 0xA098, 0x7241, 0xA099, 0x7242, 0xA09A, 0x7243, 0xA09B, 0x7244, 0xA09C, 0x7245, 0xA09D, 0x7246, + 0xA09E, 0x7249, 0xA09F, 0x724A, 0xA0A0, 0x724B, 0xA0A1, 0x724E, 0xA0A2, 0x724F, 0xA0A3, 0x7250, 0xA0A4, 0x7251, 0xA0A5, 0x7253, + 0xA0A6, 0x7254, 0xA0A7, 0x7255, 0xA0A8, 0x7257, 0xA0A9, 0x7258, 0xA0AA, 0x725A, 0xA0AB, 0x725C, 0xA0AC, 0x725E, 0xA0AD, 0x7260, + 0xA0AE, 0x7263, 0xA0AF, 0x7264, 0xA0B0, 0x7265, 0xA0B1, 0x7268, 0xA0B2, 0x726A, 0xA0B3, 0x726B, 0xA0B4, 0x726C, 0xA0B5, 0x726D, + 0xA0B6, 0x7270, 0xA0B7, 0x7271, 0xA0B8, 0x7273, 0xA0B9, 0x7274, 0xA0BA, 0x7276, 0xA0BB, 0x7277, 0xA0BC, 0x7278, 0xA0BD, 0x727B, + 0xA0BE, 0x727C, 0xA0BF, 0x727D, 0xA0C0, 0x7282, 0xA0C1, 0x7283, 0xA0C2, 0x7285, 0xA0C3, 0x7286, 0xA0C4, 0x7287, 0xA0C5, 0x7288, + 0xA0C6, 0x7289, 0xA0C7, 0x728C, 0xA0C8, 0x728E, 0xA0C9, 0x7290, 0xA0CA, 0x7291, 0xA0CB, 0x7293, 0xA0CC, 0x7294, 0xA0CD, 0x7295, + 0xA0CE, 0x7296, 0xA0CF, 0x7297, 0xA0D0, 0x7298, 0xA0D1, 0x7299, 0xA0D2, 0x729A, 0xA0D3, 0x729B, 0xA0D4, 0x729C, 0xA0D5, 0x729D, + 0xA0D6, 0x729E, 0xA0D7, 0x72A0, 0xA0D8, 0x72A1, 0xA0D9, 0x72A2, 0xA0DA, 0x72A3, 0xA0DB, 0x72A4, 0xA0DC, 0x72A5, 0xA0DD, 0x72A6, + 0xA0DE, 0x72A7, 0xA0DF, 0x72A8, 0xA0E0, 0x72A9, 0xA0E1, 0x72AA, 0xA0E2, 0x72AB, 0xA0E3, 0x72AE, 0xA0E4, 0x72B1, 0xA0E5, 0x72B2, + 0xA0E6, 0x72B3, 0xA0E7, 0x72B5, 0xA0E8, 0x72BA, 0xA0E9, 0x72BB, 0xA0EA, 0x72BC, 0xA0EB, 0x72BD, 0xA0EC, 0x72BE, 0xA0ED, 0x72BF, + 0xA0EE, 0x72C0, 0xA0EF, 0x72C5, 0xA0F0, 0x72C6, 0xA0F1, 0x72C7, 0xA0F2, 0x72C9, 0xA0F3, 0x72CA, 0xA0F4, 0x72CB, 0xA0F5, 0x72CC, + 0xA0F6, 0x72CF, 0xA0F7, 0x72D1, 0xA0F8, 0x72D3, 0xA0F9, 0x72D4, 0xA0FA, 0x72D5, 0xA0FB, 0x72D6, 0xA0FC, 0x72D8, 0xA0FD, 0x72DA, + 0xA0FE, 0x72DB, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7, 0xA1A5, 0x02C9, 0xA1A6, 0x02C7, 0xA1A7, 0x00A8, + 0xA1A8, 0x3003, 0xA1A9, 0x3005, 0xA1AA, 0x2014, 0xA1AB, 0xFF5E, 0xA1AC, 0x2016, 0xA1AD, 0x2026, 0xA1AE, 0x2018, 0xA1AF, 0x2019, + 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008, 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, + 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3016, 0xA1BD, 0x3017, 0xA1BE, 0x3010, 0xA1BF, 0x3011, + 0xA1C0, 0x00B1, 0xA1C1, 0x00D7, 0xA1C2, 0x00F7, 0xA1C3, 0x2236, 0xA1C4, 0x2227, 0xA1C5, 0x2228, 0xA1C6, 0x2211, 0xA1C7, 0x220F, + 0xA1C8, 0x222A, 0xA1C9, 0x2229, 0xA1CA, 0x2208, 0xA1CB, 0x2237, 0xA1CC, 0x221A, 0xA1CD, 0x22A5, 0xA1CE, 0x2225, 0xA1CF, 0x2220, + 0xA1D0, 0x2312, 0xA1D1, 0x2299, 0xA1D2, 0x222B, 0xA1D3, 0x222E, 0xA1D4, 0x2261, 0xA1D5, 0x224C, 0xA1D6, 0x2248, 0xA1D7, 0x223D, + 0xA1D8, 0x221D, 0xA1D9, 0x2260, 0xA1DA, 0x226E, 0xA1DB, 0x226F, 0xA1DC, 0x2264, 0xA1DD, 0x2265, 0xA1DE, 0x221E, 0xA1DF, 0x2235, + 0xA1E0, 0x2234, 0xA1E1, 0x2642, 0xA1E2, 0x2640, 0xA1E3, 0x00B0, 0xA1E4, 0x2032, 0xA1E5, 0x2033, 0xA1E6, 0x2103, 0xA1E7, 0xFF04, + 0xA1E8, 0x00A4, 0xA1E9, 0xFFE0, 0xA1EA, 0xFFE1, 0xA1EB, 0x2030, 0xA1EC, 0x00A7, 0xA1ED, 0x2116, 0xA1EE, 0x2606, 0xA1EF, 0x2605, + 0xA1F0, 0x25CB, 0xA1F1, 0x25CF, 0xA1F2, 0x25CE, 0xA1F3, 0x25C7, 0xA1F4, 0x25C6, 0xA1F5, 0x25A1, 0xA1F6, 0x25A0, 0xA1F7, 0x25B3, + 0xA1F8, 0x25B2, 0xA1F9, 0x203B, 0xA1FA, 0x2192, 0xA1FB, 0x2190, 0xA1FC, 0x2191, 0xA1FD, 0x2193, 0xA1FE, 0x3013, 0xA2A1, 0x2170, + 0xA2A2, 0x2171, 0xA2A3, 0x2172, 0xA2A4, 0x2173, 0xA2A5, 0x2174, 0xA2A6, 0x2175, 0xA2A7, 0x2176, 0xA2A8, 0x2177, 0xA2A9, 0x2178, + 0xA2AA, 0x2179, 0xA2B1, 0x2488, 0xA2B2, 0x2489, 0xA2B3, 0x248A, 0xA2B4, 0x248B, 0xA2B5, 0x248C, 0xA2B6, 0x248D, 0xA2B7, 0x248E, + 0xA2B8, 0x248F, 0xA2B9, 0x2490, 0xA2BA, 0x2491, 0xA2BB, 0x2492, 0xA2BC, 0x2493, 0xA2BD, 0x2494, 0xA2BE, 0x2495, 0xA2BF, 0x2496, + 0xA2C0, 0x2497, 0xA2C1, 0x2498, 0xA2C2, 0x2499, 0xA2C3, 0x249A, 0xA2C4, 0x249B, 0xA2C5, 0x2474, 0xA2C6, 0x2475, 0xA2C7, 0x2476, + 0xA2C8, 0x2477, 0xA2C9, 0x2478, 0xA2CA, 0x2479, 0xA2CB, 0x247A, 0xA2CC, 0x247B, 0xA2CD, 0x247C, 0xA2CE, 0x247D, 0xA2CF, 0x247E, + 0xA2D0, 0x247F, 0xA2D1, 0x2480, 0xA2D2, 0x2481, 0xA2D3, 0x2482, 0xA2D4, 0x2483, 0xA2D5, 0x2484, 0xA2D6, 0x2485, 0xA2D7, 0x2486, + 0xA2D8, 0x2487, 0xA2D9, 0x2460, 0xA2DA, 0x2461, 0xA2DB, 0x2462, 0xA2DC, 0x2463, 0xA2DD, 0x2464, 0xA2DE, 0x2465, 0xA2DF, 0x2466, + 0xA2E0, 0x2467, 0xA2E1, 0x2468, 0xA2E2, 0x2469, 0xA2E5, 0x3220, 0xA2E6, 0x3221, 0xA2E7, 0x3222, 0xA2E8, 0x3223, 0xA2E9, 0x3224, + 0xA2EA, 0x3225, 0xA2EB, 0x3226, 0xA2EC, 0x3227, 0xA2ED, 0x3228, 0xA2EE, 0x3229, 0xA2F1, 0x2160, 0xA2F2, 0x2161, 0xA2F3, 0x2162, + 0xA2F4, 0x2163, 0xA2F5, 0x2164, 0xA2F6, 0x2165, 0xA2F7, 0x2166, 0xA2F8, 0x2167, 0xA2F9, 0x2168, 0xA2FA, 0x2169, 0xA2FB, 0x216A, + 0xA2FC, 0x216B, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, 0xA3A4, 0xFFE5, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, 0xA3DC, 0xFF3C, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA4A1, 0x3041, + 0xA4A2, 0x3042, 0xA4A3, 0x3043, 0xA4A4, 0x3044, 0xA4A5, 0x3045, 0xA4A6, 0x3046, 0xA4A7, 0x3047, 0xA4A8, 0x3048, 0xA4A9, 0x3049, + 0xA4AA, 0x304A, 0xA4AB, 0x304B, 0xA4AC, 0x304C, 0xA4AD, 0x304D, 0xA4AE, 0x304E, 0xA4AF, 0x304F, 0xA4B0, 0x3050, 0xA4B1, 0x3051, + 0xA4B2, 0x3052, 0xA4B3, 0x3053, 0xA4B4, 0x3054, 0xA4B5, 0x3055, 0xA4B6, 0x3056, 0xA4B7, 0x3057, 0xA4B8, 0x3058, 0xA4B9, 0x3059, + 0xA4BA, 0x305A, 0xA4BB, 0x305B, 0xA4BC, 0x305C, 0xA4BD, 0x305D, 0xA4BE, 0x305E, 0xA4BF, 0x305F, 0xA4C0, 0x3060, 0xA4C1, 0x3061, + 0xA4C2, 0x3062, 0xA4C3, 0x3063, 0xA4C4, 0x3064, 0xA4C5, 0x3065, 0xA4C6, 0x3066, 0xA4C7, 0x3067, 0xA4C8, 0x3068, 0xA4C9, 0x3069, + 0xA4CA, 0x306A, 0xA4CB, 0x306B, 0xA4CC, 0x306C, 0xA4CD, 0x306D, 0xA4CE, 0x306E, 0xA4CF, 0x306F, 0xA4D0, 0x3070, 0xA4D1, 0x3071, + 0xA4D2, 0x3072, 0xA4D3, 0x3073, 0xA4D4, 0x3074, 0xA4D5, 0x3075, 0xA4D6, 0x3076, 0xA4D7, 0x3077, 0xA4D8, 0x3078, 0xA4D9, 0x3079, + 0xA4DA, 0x307A, 0xA4DB, 0x307B, 0xA4DC, 0x307C, 0xA4DD, 0x307D, 0xA4DE, 0x307E, 0xA4DF, 0x307F, 0xA4E0, 0x3080, 0xA4E1, 0x3081, + 0xA4E2, 0x3082, 0xA4E3, 0x3083, 0xA4E4, 0x3084, 0xA4E5, 0x3085, 0xA4E6, 0x3086, 0xA4E7, 0x3087, 0xA4E8, 0x3088, 0xA4E9, 0x3089, + 0xA4EA, 0x308A, 0xA4EB, 0x308B, 0xA4EC, 0x308C, 0xA4ED, 0x308D, 0xA4EE, 0x308E, 0xA4EF, 0x308F, 0xA4F0, 0x3090, 0xA4F1, 0x3091, + 0xA4F2, 0x3092, 0xA4F3, 0x3093, 0xA5A1, 0x30A1, 0xA5A2, 0x30A2, 0xA5A3, 0x30A3, 0xA5A4, 0x30A4, 0xA5A5, 0x30A5, 0xA5A6, 0x30A6, + 0xA5A7, 0x30A7, 0xA5A8, 0x30A8, 0xA5A9, 0x30A9, 0xA5AA, 0x30AA, 0xA5AB, 0x30AB, 0xA5AC, 0x30AC, 0xA5AD, 0x30AD, 0xA5AE, 0x30AE, + 0xA5AF, 0x30AF, 0xA5B0, 0x30B0, 0xA5B1, 0x30B1, 0xA5B2, 0x30B2, 0xA5B3, 0x30B3, 0xA5B4, 0x30B4, 0xA5B5, 0x30B5, 0xA5B6, 0x30B6, + 0xA5B7, 0x30B7, 0xA5B8, 0x30B8, 0xA5B9, 0x30B9, 0xA5BA, 0x30BA, 0xA5BB, 0x30BB, 0xA5BC, 0x30BC, 0xA5BD, 0x30BD, 0xA5BE, 0x30BE, + 0xA5BF, 0x30BF, 0xA5C0, 0x30C0, 0xA5C1, 0x30C1, 0xA5C2, 0x30C2, 0xA5C3, 0x30C3, 0xA5C4, 0x30C4, 0xA5C5, 0x30C5, 0xA5C6, 0x30C6, + 0xA5C7, 0x30C7, 0xA5C8, 0x30C8, 0xA5C9, 0x30C9, 0xA5CA, 0x30CA, 0xA5CB, 0x30CB, 0xA5CC, 0x30CC, 0xA5CD, 0x30CD, 0xA5CE, 0x30CE, + 0xA5CF, 0x30CF, 0xA5D0, 0x30D0, 0xA5D1, 0x30D1, 0xA5D2, 0x30D2, 0xA5D3, 0x30D3, 0xA5D4, 0x30D4, 0xA5D5, 0x30D5, 0xA5D6, 0x30D6, + 0xA5D7, 0x30D7, 0xA5D8, 0x30D8, 0xA5D9, 0x30D9, 0xA5DA, 0x30DA, 0xA5DB, 0x30DB, 0xA5DC, 0x30DC, 0xA5DD, 0x30DD, 0xA5DE, 0x30DE, + 0xA5DF, 0x30DF, 0xA5E0, 0x30E0, 0xA5E1, 0x30E1, 0xA5E2, 0x30E2, 0xA5E3, 0x30E3, 0xA5E4, 0x30E4, 0xA5E5, 0x30E5, 0xA5E6, 0x30E6, + 0xA5E7, 0x30E7, 0xA5E8, 0x30E8, 0xA5E9, 0x30E9, 0xA5EA, 0x30EA, 0xA5EB, 0x30EB, 0xA5EC, 0x30EC, 0xA5ED, 0x30ED, 0xA5EE, 0x30EE, + 0xA5EF, 0x30EF, 0xA5F0, 0x30F0, 0xA5F1, 0x30F1, 0xA5F2, 0x30F2, 0xA5F3, 0x30F3, 0xA5F4, 0x30F4, 0xA5F5, 0x30F5, 0xA5F6, 0x30F6, + 0xA6A1, 0x0391, 0xA6A2, 0x0392, 0xA6A3, 0x0393, 0xA6A4, 0x0394, 0xA6A5, 0x0395, 0xA6A6, 0x0396, 0xA6A7, 0x0397, 0xA6A8, 0x0398, + 0xA6A9, 0x0399, 0xA6AA, 0x039A, 0xA6AB, 0x039B, 0xA6AC, 0x039C, 0xA6AD, 0x039D, 0xA6AE, 0x039E, 0xA6AF, 0x039F, 0xA6B0, 0x03A0, + 0xA6B1, 0x03A1, 0xA6B2, 0x03A3, 0xA6B3, 0x03A4, 0xA6B4, 0x03A5, 0xA6B5, 0x03A6, 0xA6B6, 0x03A7, 0xA6B7, 0x03A8, 0xA6B8, 0x03A9, + 0xA6C1, 0x03B1, 0xA6C2, 0x03B2, 0xA6C3, 0x03B3, 0xA6C4, 0x03B4, 0xA6C5, 0x03B5, 0xA6C6, 0x03B6, 0xA6C7, 0x03B7, 0xA6C8, 0x03B8, + 0xA6C9, 0x03B9, 0xA6CA, 0x03BA, 0xA6CB, 0x03BB, 0xA6CC, 0x03BC, 0xA6CD, 0x03BD, 0xA6CE, 0x03BE, 0xA6CF, 0x03BF, 0xA6D0, 0x03C0, + 0xA6D1, 0x03C1, 0xA6D2, 0x03C3, 0xA6D3, 0x03C4, 0xA6D4, 0x03C5, 0xA6D5, 0x03C6, 0xA6D6, 0x03C7, 0xA6D7, 0x03C8, 0xA6D8, 0x03C9, + 0xA6E0, 0xFE35, 0xA6E1, 0xFE36, 0xA6E2, 0xFE39, 0xA6E3, 0xFE3A, 0xA6E4, 0xFE3F, 0xA6E5, 0xFE40, 0xA6E6, 0xFE3D, 0xA6E7, 0xFE3E, + 0xA6E8, 0xFE41, 0xA6E9, 0xFE42, 0xA6EA, 0xFE43, 0xA6EB, 0xFE44, 0xA6EE, 0xFE3B, 0xA6EF, 0xFE3C, 0xA6F0, 0xFE37, 0xA6F1, 0xFE38, + 0xA6F2, 0xFE31, 0xA6F4, 0xFE33, 0xA6F5, 0xFE34, 0xA7A1, 0x0410, 0xA7A2, 0x0411, 0xA7A3, 0x0412, 0xA7A4, 0x0413, 0xA7A5, 0x0414, + 0xA7A6, 0x0415, 0xA7A7, 0x0401, 0xA7A8, 0x0416, 0xA7A9, 0x0417, 0xA7AA, 0x0418, 0xA7AB, 0x0419, 0xA7AC, 0x041A, 0xA7AD, 0x041B, + 0xA7AE, 0x041C, 0xA7AF, 0x041D, 0xA7B0, 0x041E, 0xA7B1, 0x041F, 0xA7B2, 0x0420, 0xA7B3, 0x0421, 0xA7B4, 0x0422, 0xA7B5, 0x0423, + 0xA7B6, 0x0424, 0xA7B7, 0x0425, 0xA7B8, 0x0426, 0xA7B9, 0x0427, 0xA7BA, 0x0428, 0xA7BB, 0x0429, 0xA7BC, 0x042A, 0xA7BD, 0x042B, + 0xA7BE, 0x042C, 0xA7BF, 0x042D, 0xA7C0, 0x042E, 0xA7C1, 0x042F, 0xA7D1, 0x0430, 0xA7D2, 0x0431, 0xA7D3, 0x0432, 0xA7D4, 0x0433, + 0xA7D5, 0x0434, 0xA7D6, 0x0435, 0xA7D7, 0x0451, 0xA7D8, 0x0436, 0xA7D9, 0x0437, 0xA7DA, 0x0438, 0xA7DB, 0x0439, 0xA7DC, 0x043A, + 0xA7DD, 0x043B, 0xA7DE, 0x043C, 0xA7DF, 0x043D, 0xA7E0, 0x043E, 0xA7E1, 0x043F, 0xA7E2, 0x0440, 0xA7E3, 0x0441, 0xA7E4, 0x0442, + 0xA7E5, 0x0443, 0xA7E6, 0x0444, 0xA7E7, 0x0445, 0xA7E8, 0x0446, 0xA7E9, 0x0447, 0xA7EA, 0x0448, 0xA7EB, 0x0449, 0xA7EC, 0x044A, + 0xA7ED, 0x044B, 0xA7EE, 0x044C, 0xA7EF, 0x044D, 0xA7F0, 0x044E, 0xA7F1, 0x044F, 0xA840, 0x02CA, 0xA841, 0x02CB, 0xA842, 0x02D9, + 0xA843, 0x2013, 0xA844, 0x2015, 0xA845, 0x2025, 0xA846, 0x2035, 0xA847, 0x2105, 0xA848, 0x2109, 0xA849, 0x2196, 0xA84A, 0x2197, + 0xA84B, 0x2198, 0xA84C, 0x2199, 0xA84D, 0x2215, 0xA84E, 0x221F, 0xA84F, 0x2223, 0xA850, 0x2252, 0xA851, 0x2266, 0xA852, 0x2267, + 0xA853, 0x22BF, 0xA854, 0x2550, 0xA855, 0x2551, 0xA856, 0x2552, 0xA857, 0x2553, 0xA858, 0x2554, 0xA859, 0x2555, 0xA85A, 0x2556, + 0xA85B, 0x2557, 0xA85C, 0x2558, 0xA85D, 0x2559, 0xA85E, 0x255A, 0xA85F, 0x255B, 0xA860, 0x255C, 0xA861, 0x255D, 0xA862, 0x255E, + 0xA863, 0x255F, 0xA864, 0x2560, 0xA865, 0x2561, 0xA866, 0x2562, 0xA867, 0x2563, 0xA868, 0x2564, 0xA869, 0x2565, 0xA86A, 0x2566, + 0xA86B, 0x2567, 0xA86C, 0x2568, 0xA86D, 0x2569, 0xA86E, 0x256A, 0xA86F, 0x256B, 0xA870, 0x256C, 0xA871, 0x256D, 0xA872, 0x256E, + 0xA873, 0x256F, 0xA874, 0x2570, 0xA875, 0x2571, 0xA876, 0x2572, 0xA877, 0x2573, 0xA878, 0x2581, 0xA879, 0x2582, 0xA87A, 0x2583, + 0xA87B, 0x2584, 0xA87C, 0x2585, 0xA87D, 0x2586, 0xA87E, 0x2587, 0xA880, 0x2588, 0xA881, 0x2589, 0xA882, 0x258A, 0xA883, 0x258B, + 0xA884, 0x258C, 0xA885, 0x258D, 0xA886, 0x258E, 0xA887, 0x258F, 0xA888, 0x2593, 0xA889, 0x2594, 0xA88A, 0x2595, 0xA88B, 0x25BC, + 0xA88C, 0x25BD, 0xA88D, 0x25E2, 0xA88E, 0x25E3, 0xA88F, 0x25E4, 0xA890, 0x25E5, 0xA891, 0x2609, 0xA892, 0x2295, 0xA893, 0x3012, + 0xA894, 0x301D, 0xA895, 0x301E, 0xA8A1, 0x0101, 0xA8A2, 0x00E1, 0xA8A3, 0x01CE, 0xA8A4, 0x00E0, 0xA8A5, 0x0113, 0xA8A6, 0x00E9, + 0xA8A7, 0x011B, 0xA8A8, 0x00E8, 0xA8A9, 0x012B, 0xA8AA, 0x00ED, 0xA8AB, 0x01D0, 0xA8AC, 0x00EC, 0xA8AD, 0x014D, 0xA8AE, 0x00F3, + 0xA8AF, 0x01D2, 0xA8B0, 0x00F2, 0xA8B1, 0x016B, 0xA8B2, 0x00FA, 0xA8B3, 0x01D4, 0xA8B4, 0x00F9, 0xA8B5, 0x01D6, 0xA8B6, 0x01D8, + 0xA8B7, 0x01DA, 0xA8B8, 0x01DC, 0xA8B9, 0x00FC, 0xA8BA, 0x00EA, 0xA8BB, 0x0251, 0xA8BD, 0x0144, 0xA8BE, 0x0148, 0xA8C0, 0x0261, + 0xA8C5, 0x3105, 0xA8C6, 0x3106, 0xA8C7, 0x3107, 0xA8C8, 0x3108, 0xA8C9, 0x3109, 0xA8CA, 0x310A, 0xA8CB, 0x310B, 0xA8CC, 0x310C, + 0xA8CD, 0x310D, 0xA8CE, 0x310E, 0xA8CF, 0x310F, 0xA8D0, 0x3110, 0xA8D1, 0x3111, 0xA8D2, 0x3112, 0xA8D3, 0x3113, 0xA8D4, 0x3114, + 0xA8D5, 0x3115, 0xA8D6, 0x3116, 0xA8D7, 0x3117, 0xA8D8, 0x3118, 0xA8D9, 0x3119, 0xA8DA, 0x311A, 0xA8DB, 0x311B, 0xA8DC, 0x311C, + 0xA8DD, 0x311D, 0xA8DE, 0x311E, 0xA8DF, 0x311F, 0xA8E0, 0x3120, 0xA8E1, 0x3121, 0xA8E2, 0x3122, 0xA8E3, 0x3123, 0xA8E4, 0x3124, + 0xA8E5, 0x3125, 0xA8E6, 0x3126, 0xA8E7, 0x3127, 0xA8E8, 0x3128, 0xA8E9, 0x3129, 0xA940, 0x3021, 0xA941, 0x3022, 0xA942, 0x3023, + 0xA943, 0x3024, 0xA944, 0x3025, 0xA945, 0x3026, 0xA946, 0x3027, 0xA947, 0x3028, 0xA948, 0x3029, 0xA949, 0x32A3, 0xA94A, 0x338E, + 0xA94B, 0x338F, 0xA94C, 0x339C, 0xA94D, 0x339D, 0xA94E, 0x339E, 0xA94F, 0x33A1, 0xA950, 0x33C4, 0xA951, 0x33CE, 0xA952, 0x33D1, + 0xA953, 0x33D2, 0xA954, 0x33D5, 0xA955, 0xFE30, 0xA956, 0xFFE2, 0xA957, 0xFFE4, 0xA959, 0x2121, 0xA95A, 0x3231, 0xA95C, 0x2010, + 0xA960, 0x30FC, 0xA961, 0x309B, 0xA962, 0x309C, 0xA963, 0x30FD, 0xA964, 0x30FE, 0xA965, 0x3006, 0xA966, 0x309D, 0xA967, 0x309E, + 0xA968, 0xFE49, 0xA969, 0xFE4A, 0xA96A, 0xFE4B, 0xA96B, 0xFE4C, 0xA96C, 0xFE4D, 0xA96D, 0xFE4E, 0xA96E, 0xFE4F, 0xA96F, 0xFE50, + 0xA970, 0xFE51, 0xA971, 0xFE52, 0xA972, 0xFE54, 0xA973, 0xFE55, 0xA974, 0xFE56, 0xA975, 0xFE57, 0xA976, 0xFE59, 0xA977, 0xFE5A, + 0xA978, 0xFE5B, 0xA979, 0xFE5C, 0xA97A, 0xFE5D, 0xA97B, 0xFE5E, 0xA97C, 0xFE5F, 0xA97D, 0xFE60, 0xA97E, 0xFE61, 0xA980, 0xFE62, + 0xA981, 0xFE63, 0xA982, 0xFE64, 0xA983, 0xFE65, 0xA984, 0xFE66, 0xA985, 0xFE68, 0xA986, 0xFE69, 0xA987, 0xFE6A, 0xA988, 0xFE6B, + 0xA996, 0x3007, 0xA9A4, 0x2500, 0xA9A5, 0x2501, 0xA9A6, 0x2502, 0xA9A7, 0x2503, 0xA9A8, 0x2504, 0xA9A9, 0x2505, 0xA9AA, 0x2506, + 0xA9AB, 0x2507, 0xA9AC, 0x2508, 0xA9AD, 0x2509, 0xA9AE, 0x250A, 0xA9AF, 0x250B, 0xA9B0, 0x250C, 0xA9B1, 0x250D, 0xA9B2, 0x250E, + 0xA9B3, 0x250F, 0xA9B4, 0x2510, 0xA9B5, 0x2511, 0xA9B6, 0x2512, 0xA9B7, 0x2513, 0xA9B8, 0x2514, 0xA9B9, 0x2515, 0xA9BA, 0x2516, + 0xA9BB, 0x2517, 0xA9BC, 0x2518, 0xA9BD, 0x2519, 0xA9BE, 0x251A, 0xA9BF, 0x251B, 0xA9C0, 0x251C, 0xA9C1, 0x251D, 0xA9C2, 0x251E, + 0xA9C3, 0x251F, 0xA9C4, 0x2520, 0xA9C5, 0x2521, 0xA9C6, 0x2522, 0xA9C7, 0x2523, 0xA9C8, 0x2524, 0xA9C9, 0x2525, 0xA9CA, 0x2526, + 0xA9CB, 0x2527, 0xA9CC, 0x2528, 0xA9CD, 0x2529, 0xA9CE, 0x252A, 0xA9CF, 0x252B, 0xA9D0, 0x252C, 0xA9D1, 0x252D, 0xA9D2, 0x252E, + 0xA9D3, 0x252F, 0xA9D4, 0x2530, 0xA9D5, 0x2531, 0xA9D6, 0x2532, 0xA9D7, 0x2533, 0xA9D8, 0x2534, 0xA9D9, 0x2535, 0xA9DA, 0x2536, + 0xA9DB, 0x2537, 0xA9DC, 0x2538, 0xA9DD, 0x2539, 0xA9DE, 0x253A, 0xA9DF, 0x253B, 0xA9E0, 0x253C, 0xA9E1, 0x253D, 0xA9E2, 0x253E, + 0xA9E3, 0x253F, 0xA9E4, 0x2540, 0xA9E5, 0x2541, 0xA9E6, 0x2542, 0xA9E7, 0x2543, 0xA9E8, 0x2544, 0xA9E9, 0x2545, 0xA9EA, 0x2546, + 0xA9EB, 0x2547, 0xA9EC, 0x2548, 0xA9ED, 0x2549, 0xA9EE, 0x254A, 0xA9EF, 0x254B, 0xAA40, 0x72DC, 0xAA41, 0x72DD, 0xAA42, 0x72DF, + 0xAA43, 0x72E2, 0xAA44, 0x72E3, 0xAA45, 0x72E4, 0xAA46, 0x72E5, 0xAA47, 0x72E6, 0xAA48, 0x72E7, 0xAA49, 0x72EA, 0xAA4A, 0x72EB, + 0xAA4B, 0x72F5, 0xAA4C, 0x72F6, 0xAA4D, 0x72F9, 0xAA4E, 0x72FD, 0xAA4F, 0x72FE, 0xAA50, 0x72FF, 0xAA51, 0x7300, 0xAA52, 0x7302, + 0xAA53, 0x7304, 0xAA54, 0x7305, 0xAA55, 0x7306, 0xAA56, 0x7307, 0xAA57, 0x7308, 0xAA58, 0x7309, 0xAA59, 0x730B, 0xAA5A, 0x730C, + 0xAA5B, 0x730D, 0xAA5C, 0x730F, 0xAA5D, 0x7310, 0xAA5E, 0x7311, 0xAA5F, 0x7312, 0xAA60, 0x7314, 0xAA61, 0x7318, 0xAA62, 0x7319, + 0xAA63, 0x731A, 0xAA64, 0x731F, 0xAA65, 0x7320, 0xAA66, 0x7323, 0xAA67, 0x7324, 0xAA68, 0x7326, 0xAA69, 0x7327, 0xAA6A, 0x7328, + 0xAA6B, 0x732D, 0xAA6C, 0x732F, 0xAA6D, 0x7330, 0xAA6E, 0x7332, 0xAA6F, 0x7333, 0xAA70, 0x7335, 0xAA71, 0x7336, 0xAA72, 0x733A, + 0xAA73, 0x733B, 0xAA74, 0x733C, 0xAA75, 0x733D, 0xAA76, 0x7340, 0xAA77, 0x7341, 0xAA78, 0x7342, 0xAA79, 0x7343, 0xAA7A, 0x7344, + 0xAA7B, 0x7345, 0xAA7C, 0x7346, 0xAA7D, 0x7347, 0xAA7E, 0x7348, 0xAA80, 0x7349, 0xAA81, 0x734A, 0xAA82, 0x734B, 0xAA83, 0x734C, + 0xAA84, 0x734E, 0xAA85, 0x734F, 0xAA86, 0x7351, 0xAA87, 0x7353, 0xAA88, 0x7354, 0xAA89, 0x7355, 0xAA8A, 0x7356, 0xAA8B, 0x7358, + 0xAA8C, 0x7359, 0xAA8D, 0x735A, 0xAA8E, 0x735B, 0xAA8F, 0x735C, 0xAA90, 0x735D, 0xAA91, 0x735E, 0xAA92, 0x735F, 0xAA93, 0x7361, + 0xAA94, 0x7362, 0xAA95, 0x7363, 0xAA96, 0x7364, 0xAA97, 0x7365, 0xAA98, 0x7366, 0xAA99, 0x7367, 0xAA9A, 0x7368, 0xAA9B, 0x7369, + 0xAA9C, 0x736A, 0xAA9D, 0x736B, 0xAA9E, 0x736E, 0xAA9F, 0x7370, 0xAAA0, 0x7371, 0xAB40, 0x7372, 0xAB41, 0x7373, 0xAB42, 0x7374, + 0xAB43, 0x7375, 0xAB44, 0x7376, 0xAB45, 0x7377, 0xAB46, 0x7378, 0xAB47, 0x7379, 0xAB48, 0x737A, 0xAB49, 0x737B, 0xAB4A, 0x737C, + 0xAB4B, 0x737D, 0xAB4C, 0x737F, 0xAB4D, 0x7380, 0xAB4E, 0x7381, 0xAB4F, 0x7382, 0xAB50, 0x7383, 0xAB51, 0x7385, 0xAB52, 0x7386, + 0xAB53, 0x7388, 0xAB54, 0x738A, 0xAB55, 0x738C, 0xAB56, 0x738D, 0xAB57, 0x738F, 0xAB58, 0x7390, 0xAB59, 0x7392, 0xAB5A, 0x7393, + 0xAB5B, 0x7394, 0xAB5C, 0x7395, 0xAB5D, 0x7397, 0xAB5E, 0x7398, 0xAB5F, 0x7399, 0xAB60, 0x739A, 0xAB61, 0x739C, 0xAB62, 0x739D, + 0xAB63, 0x739E, 0xAB64, 0x73A0, 0xAB65, 0x73A1, 0xAB66, 0x73A3, 0xAB67, 0x73A4, 0xAB68, 0x73A5, 0xAB69, 0x73A6, 0xAB6A, 0x73A7, + 0xAB6B, 0x73A8, 0xAB6C, 0x73AA, 0xAB6D, 0x73AC, 0xAB6E, 0x73AD, 0xAB6F, 0x73B1, 0xAB70, 0x73B4, 0xAB71, 0x73B5, 0xAB72, 0x73B6, + 0xAB73, 0x73B8, 0xAB74, 0x73B9, 0xAB75, 0x73BC, 0xAB76, 0x73BD, 0xAB77, 0x73BE, 0xAB78, 0x73BF, 0xAB79, 0x73C1, 0xAB7A, 0x73C3, + 0xAB7B, 0x73C4, 0xAB7C, 0x73C5, 0xAB7D, 0x73C6, 0xAB7E, 0x73C7, 0xAB80, 0x73CB, 0xAB81, 0x73CC, 0xAB82, 0x73CE, 0xAB83, 0x73D2, + 0xAB84, 0x73D3, 0xAB85, 0x73D4, 0xAB86, 0x73D5, 0xAB87, 0x73D6, 0xAB88, 0x73D7, 0xAB89, 0x73D8, 0xAB8A, 0x73DA, 0xAB8B, 0x73DB, + 0xAB8C, 0x73DC, 0xAB8D, 0x73DD, 0xAB8E, 0x73DF, 0xAB8F, 0x73E1, 0xAB90, 0x73E2, 0xAB91, 0x73E3, 0xAB92, 0x73E4, 0xAB93, 0x73E6, + 0xAB94, 0x73E8, 0xAB95, 0x73EA, 0xAB96, 0x73EB, 0xAB97, 0x73EC, 0xAB98, 0x73EE, 0xAB99, 0x73EF, 0xAB9A, 0x73F0, 0xAB9B, 0x73F1, + 0xAB9C, 0x73F3, 0xAB9D, 0x73F4, 0xAB9E, 0x73F5, 0xAB9F, 0x73F6, 0xABA0, 0x73F7, 0xAC40, 0x73F8, 0xAC41, 0x73F9, 0xAC42, 0x73FA, + 0xAC43, 0x73FB, 0xAC44, 0x73FC, 0xAC45, 0x73FD, 0xAC46, 0x73FE, 0xAC47, 0x73FF, 0xAC48, 0x7400, 0xAC49, 0x7401, 0xAC4A, 0x7402, + 0xAC4B, 0x7404, 0xAC4C, 0x7407, 0xAC4D, 0x7408, 0xAC4E, 0x740B, 0xAC4F, 0x740C, 0xAC50, 0x740D, 0xAC51, 0x740E, 0xAC52, 0x7411, + 0xAC53, 0x7412, 0xAC54, 0x7413, 0xAC55, 0x7414, 0xAC56, 0x7415, 0xAC57, 0x7416, 0xAC58, 0x7417, 0xAC59, 0x7418, 0xAC5A, 0x7419, + 0xAC5B, 0x741C, 0xAC5C, 0x741D, 0xAC5D, 0x741E, 0xAC5E, 0x741F, 0xAC5F, 0x7420, 0xAC60, 0x7421, 0xAC61, 0x7423, 0xAC62, 0x7424, + 0xAC63, 0x7427, 0xAC64, 0x7429, 0xAC65, 0x742B, 0xAC66, 0x742D, 0xAC67, 0x742F, 0xAC68, 0x7431, 0xAC69, 0x7432, 0xAC6A, 0x7437, + 0xAC6B, 0x7438, 0xAC6C, 0x7439, 0xAC6D, 0x743A, 0xAC6E, 0x743B, 0xAC6F, 0x743D, 0xAC70, 0x743E, 0xAC71, 0x743F, 0xAC72, 0x7440, + 0xAC73, 0x7442, 0xAC74, 0x7443, 0xAC75, 0x7444, 0xAC76, 0x7445, 0xAC77, 0x7446, 0xAC78, 0x7447, 0xAC79, 0x7448, 0xAC7A, 0x7449, + 0xAC7B, 0x744A, 0xAC7C, 0x744B, 0xAC7D, 0x744C, 0xAC7E, 0x744D, 0xAC80, 0x744E, 0xAC81, 0x744F, 0xAC82, 0x7450, 0xAC83, 0x7451, + 0xAC84, 0x7452, 0xAC85, 0x7453, 0xAC86, 0x7454, 0xAC87, 0x7456, 0xAC88, 0x7458, 0xAC89, 0x745D, 0xAC8A, 0x7460, 0xAC8B, 0x7461, + 0xAC8C, 0x7462, 0xAC8D, 0x7463, 0xAC8E, 0x7464, 0xAC8F, 0x7465, 0xAC90, 0x7466, 0xAC91, 0x7467, 0xAC92, 0x7468, 0xAC93, 0x7469, + 0xAC94, 0x746A, 0xAC95, 0x746B, 0xAC96, 0x746C, 0xAC97, 0x746E, 0xAC98, 0x746F, 0xAC99, 0x7471, 0xAC9A, 0x7472, 0xAC9B, 0x7473, + 0xAC9C, 0x7474, 0xAC9D, 0x7475, 0xAC9E, 0x7478, 0xAC9F, 0x7479, 0xACA0, 0x747A, 0xAD40, 0x747B, 0xAD41, 0x747C, 0xAD42, 0x747D, + 0xAD43, 0x747F, 0xAD44, 0x7482, 0xAD45, 0x7484, 0xAD46, 0x7485, 0xAD47, 0x7486, 0xAD48, 0x7488, 0xAD49, 0x7489, 0xAD4A, 0x748A, + 0xAD4B, 0x748C, 0xAD4C, 0x748D, 0xAD4D, 0x748F, 0xAD4E, 0x7491, 0xAD4F, 0x7492, 0xAD50, 0x7493, 0xAD51, 0x7494, 0xAD52, 0x7495, + 0xAD53, 0x7496, 0xAD54, 0x7497, 0xAD55, 0x7498, 0xAD56, 0x7499, 0xAD57, 0x749A, 0xAD58, 0x749B, 0xAD59, 0x749D, 0xAD5A, 0x749F, + 0xAD5B, 0x74A0, 0xAD5C, 0x74A1, 0xAD5D, 0x74A2, 0xAD5E, 0x74A3, 0xAD5F, 0x74A4, 0xAD60, 0x74A5, 0xAD61, 0x74A6, 0xAD62, 0x74AA, + 0xAD63, 0x74AB, 0xAD64, 0x74AC, 0xAD65, 0x74AD, 0xAD66, 0x74AE, 0xAD67, 0x74AF, 0xAD68, 0x74B0, 0xAD69, 0x74B1, 0xAD6A, 0x74B2, + 0xAD6B, 0x74B3, 0xAD6C, 0x74B4, 0xAD6D, 0x74B5, 0xAD6E, 0x74B6, 0xAD6F, 0x74B7, 0xAD70, 0x74B8, 0xAD71, 0x74B9, 0xAD72, 0x74BB, + 0xAD73, 0x74BC, 0xAD74, 0x74BD, 0xAD75, 0x74BE, 0xAD76, 0x74BF, 0xAD77, 0x74C0, 0xAD78, 0x74C1, 0xAD79, 0x74C2, 0xAD7A, 0x74C3, + 0xAD7B, 0x74C4, 0xAD7C, 0x74C5, 0xAD7D, 0x74C6, 0xAD7E, 0x74C7, 0xAD80, 0x74C8, 0xAD81, 0x74C9, 0xAD82, 0x74CA, 0xAD83, 0x74CB, + 0xAD84, 0x74CC, 0xAD85, 0x74CD, 0xAD86, 0x74CE, 0xAD87, 0x74CF, 0xAD88, 0x74D0, 0xAD89, 0x74D1, 0xAD8A, 0x74D3, 0xAD8B, 0x74D4, + 0xAD8C, 0x74D5, 0xAD8D, 0x74D6, 0xAD8E, 0x74D7, 0xAD8F, 0x74D8, 0xAD90, 0x74D9, 0xAD91, 0x74DA, 0xAD92, 0x74DB, 0xAD93, 0x74DD, + 0xAD94, 0x74DF, 0xAD95, 0x74E1, 0xAD96, 0x74E5, 0xAD97, 0x74E7, 0xAD98, 0x74E8, 0xAD99, 0x74E9, 0xAD9A, 0x74EA, 0xAD9B, 0x74EB, + 0xAD9C, 0x74EC, 0xAD9D, 0x74ED, 0xAD9E, 0x74F0, 0xAD9F, 0x74F1, 0xADA0, 0x74F2, 0xAE40, 0x74F3, 0xAE41, 0x74F5, 0xAE42, 0x74F8, + 0xAE43, 0x74F9, 0xAE44, 0x74FA, 0xAE45, 0x74FB, 0xAE46, 0x74FC, 0xAE47, 0x74FD, 0xAE48, 0x74FE, 0xAE49, 0x7500, 0xAE4A, 0x7501, + 0xAE4B, 0x7502, 0xAE4C, 0x7503, 0xAE4D, 0x7505, 0xAE4E, 0x7506, 0xAE4F, 0x7507, 0xAE50, 0x7508, 0xAE51, 0x7509, 0xAE52, 0x750A, + 0xAE53, 0x750B, 0xAE54, 0x750C, 0xAE55, 0x750E, 0xAE56, 0x7510, 0xAE57, 0x7512, 0xAE58, 0x7514, 0xAE59, 0x7515, 0xAE5A, 0x7516, + 0xAE5B, 0x7517, 0xAE5C, 0x751B, 0xAE5D, 0x751D, 0xAE5E, 0x751E, 0xAE5F, 0x7520, 0xAE60, 0x7521, 0xAE61, 0x7522, 0xAE62, 0x7523, + 0xAE63, 0x7524, 0xAE64, 0x7526, 0xAE65, 0x7527, 0xAE66, 0x752A, 0xAE67, 0x752E, 0xAE68, 0x7534, 0xAE69, 0x7536, 0xAE6A, 0x7539, + 0xAE6B, 0x753C, 0xAE6C, 0x753D, 0xAE6D, 0x753F, 0xAE6E, 0x7541, 0xAE6F, 0x7542, 0xAE70, 0x7543, 0xAE71, 0x7544, 0xAE72, 0x7546, + 0xAE73, 0x7547, 0xAE74, 0x7549, 0xAE75, 0x754A, 0xAE76, 0x754D, 0xAE77, 0x7550, 0xAE78, 0x7551, 0xAE79, 0x7552, 0xAE7A, 0x7553, + 0xAE7B, 0x7555, 0xAE7C, 0x7556, 0xAE7D, 0x7557, 0xAE7E, 0x7558, 0xAE80, 0x755D, 0xAE81, 0x755E, 0xAE82, 0x755F, 0xAE83, 0x7560, + 0xAE84, 0x7561, 0xAE85, 0x7562, 0xAE86, 0x7563, 0xAE87, 0x7564, 0xAE88, 0x7567, 0xAE89, 0x7568, 0xAE8A, 0x7569, 0xAE8B, 0x756B, + 0xAE8C, 0x756C, 0xAE8D, 0x756D, 0xAE8E, 0x756E, 0xAE8F, 0x756F, 0xAE90, 0x7570, 0xAE91, 0x7571, 0xAE92, 0x7573, 0xAE93, 0x7575, + 0xAE94, 0x7576, 0xAE95, 0x7577, 0xAE96, 0x757A, 0xAE97, 0x757B, 0xAE98, 0x757C, 0xAE99, 0x757D, 0xAE9A, 0x757E, 0xAE9B, 0x7580, + 0xAE9C, 0x7581, 0xAE9D, 0x7582, 0xAE9E, 0x7584, 0xAE9F, 0x7585, 0xAEA0, 0x7587, 0xAF40, 0x7588, 0xAF41, 0x7589, 0xAF42, 0x758A, + 0xAF43, 0x758C, 0xAF44, 0x758D, 0xAF45, 0x758E, 0xAF46, 0x7590, 0xAF47, 0x7593, 0xAF48, 0x7595, 0xAF49, 0x7598, 0xAF4A, 0x759B, + 0xAF4B, 0x759C, 0xAF4C, 0x759E, 0xAF4D, 0x75A2, 0xAF4E, 0x75A6, 0xAF4F, 0x75A7, 0xAF50, 0x75A8, 0xAF51, 0x75A9, 0xAF52, 0x75AA, + 0xAF53, 0x75AD, 0xAF54, 0x75B6, 0xAF55, 0x75B7, 0xAF56, 0x75BA, 0xAF57, 0x75BB, 0xAF58, 0x75BF, 0xAF59, 0x75C0, 0xAF5A, 0x75C1, + 0xAF5B, 0x75C6, 0xAF5C, 0x75CB, 0xAF5D, 0x75CC, 0xAF5E, 0x75CE, 0xAF5F, 0x75CF, 0xAF60, 0x75D0, 0xAF61, 0x75D1, 0xAF62, 0x75D3, + 0xAF63, 0x75D7, 0xAF64, 0x75D9, 0xAF65, 0x75DA, 0xAF66, 0x75DC, 0xAF67, 0x75DD, 0xAF68, 0x75DF, 0xAF69, 0x75E0, 0xAF6A, 0x75E1, + 0xAF6B, 0x75E5, 0xAF6C, 0x75E9, 0xAF6D, 0x75EC, 0xAF6E, 0x75ED, 0xAF6F, 0x75EE, 0xAF70, 0x75EF, 0xAF71, 0x75F2, 0xAF72, 0x75F3, + 0xAF73, 0x75F5, 0xAF74, 0x75F6, 0xAF75, 0x75F7, 0xAF76, 0x75F8, 0xAF77, 0x75FA, 0xAF78, 0x75FB, 0xAF79, 0x75FD, 0xAF7A, 0x75FE, + 0xAF7B, 0x7602, 0xAF7C, 0x7604, 0xAF7D, 0x7606, 0xAF7E, 0x7607, 0xAF80, 0x7608, 0xAF81, 0x7609, 0xAF82, 0x760B, 0xAF83, 0x760D, + 0xAF84, 0x760E, 0xAF85, 0x760F, 0xAF86, 0x7611, 0xAF87, 0x7612, 0xAF88, 0x7613, 0xAF89, 0x7614, 0xAF8A, 0x7616, 0xAF8B, 0x761A, + 0xAF8C, 0x761C, 0xAF8D, 0x761D, 0xAF8E, 0x761E, 0xAF8F, 0x7621, 0xAF90, 0x7623, 0xAF91, 0x7627, 0xAF92, 0x7628, 0xAF93, 0x762C, + 0xAF94, 0x762E, 0xAF95, 0x762F, 0xAF96, 0x7631, 0xAF97, 0x7632, 0xAF98, 0x7636, 0xAF99, 0x7637, 0xAF9A, 0x7639, 0xAF9B, 0x763A, + 0xAF9C, 0x763B, 0xAF9D, 0x763D, 0xAF9E, 0x7641, 0xAF9F, 0x7642, 0xAFA0, 0x7644, 0xB040, 0x7645, 0xB041, 0x7646, 0xB042, 0x7647, + 0xB043, 0x7648, 0xB044, 0x7649, 0xB045, 0x764A, 0xB046, 0x764B, 0xB047, 0x764E, 0xB048, 0x764F, 0xB049, 0x7650, 0xB04A, 0x7651, + 0xB04B, 0x7652, 0xB04C, 0x7653, 0xB04D, 0x7655, 0xB04E, 0x7657, 0xB04F, 0x7658, 0xB050, 0x7659, 0xB051, 0x765A, 0xB052, 0x765B, + 0xB053, 0x765D, 0xB054, 0x765F, 0xB055, 0x7660, 0xB056, 0x7661, 0xB057, 0x7662, 0xB058, 0x7664, 0xB059, 0x7665, 0xB05A, 0x7666, + 0xB05B, 0x7667, 0xB05C, 0x7668, 0xB05D, 0x7669, 0xB05E, 0x766A, 0xB05F, 0x766C, 0xB060, 0x766D, 0xB061, 0x766E, 0xB062, 0x7670, + 0xB063, 0x7671, 0xB064, 0x7672, 0xB065, 0x7673, 0xB066, 0x7674, 0xB067, 0x7675, 0xB068, 0x7676, 0xB069, 0x7677, 0xB06A, 0x7679, + 0xB06B, 0x767A, 0xB06C, 0x767C, 0xB06D, 0x767F, 0xB06E, 0x7680, 0xB06F, 0x7681, 0xB070, 0x7683, 0xB071, 0x7685, 0xB072, 0x7689, + 0xB073, 0x768A, 0xB074, 0x768C, 0xB075, 0x768D, 0xB076, 0x768F, 0xB077, 0x7690, 0xB078, 0x7692, 0xB079, 0x7694, 0xB07A, 0x7695, + 0xB07B, 0x7697, 0xB07C, 0x7698, 0xB07D, 0x769A, 0xB07E, 0x769B, 0xB080, 0x769C, 0xB081, 0x769D, 0xB082, 0x769E, 0xB083, 0x769F, + 0xB084, 0x76A0, 0xB085, 0x76A1, 0xB086, 0x76A2, 0xB087, 0x76A3, 0xB088, 0x76A5, 0xB089, 0x76A6, 0xB08A, 0x76A7, 0xB08B, 0x76A8, + 0xB08C, 0x76A9, 0xB08D, 0x76AA, 0xB08E, 0x76AB, 0xB08F, 0x76AC, 0xB090, 0x76AD, 0xB091, 0x76AF, 0xB092, 0x76B0, 0xB093, 0x76B3, + 0xB094, 0x76B5, 0xB095, 0x76B6, 0xB096, 0x76B7, 0xB097, 0x76B8, 0xB098, 0x76B9, 0xB099, 0x76BA, 0xB09A, 0x76BB, 0xB09B, 0x76BC, + 0xB09C, 0x76BD, 0xB09D, 0x76BE, 0xB09E, 0x76C0, 0xB09F, 0x76C1, 0xB0A0, 0x76C3, 0xB0A1, 0x554A, 0xB0A2, 0x963F, 0xB0A3, 0x57C3, + 0xB0A4, 0x6328, 0xB0A5, 0x54CE, 0xB0A6, 0x5509, 0xB0A7, 0x54C0, 0xB0A8, 0x7691, 0xB0A9, 0x764C, 0xB0AA, 0x853C, 0xB0AB, 0x77EE, + 0xB0AC, 0x827E, 0xB0AD, 0x788D, 0xB0AE, 0x7231, 0xB0AF, 0x9698, 0xB0B0, 0x978D, 0xB0B1, 0x6C28, 0xB0B2, 0x5B89, 0xB0B3, 0x4FFA, + 0xB0B4, 0x6309, 0xB0B5, 0x6697, 0xB0B6, 0x5CB8, 0xB0B7, 0x80FA, 0xB0B8, 0x6848, 0xB0B9, 0x80AE, 0xB0BA, 0x6602, 0xB0BB, 0x76CE, + 0xB0BC, 0x51F9, 0xB0BD, 0x6556, 0xB0BE, 0x71AC, 0xB0BF, 0x7FF1, 0xB0C0, 0x8884, 0xB0C1, 0x50B2, 0xB0C2, 0x5965, 0xB0C3, 0x61CA, + 0xB0C4, 0x6FB3, 0xB0C5, 0x82AD, 0xB0C6, 0x634C, 0xB0C7, 0x6252, 0xB0C8, 0x53ED, 0xB0C9, 0x5427, 0xB0CA, 0x7B06, 0xB0CB, 0x516B, + 0xB0CC, 0x75A4, 0xB0CD, 0x5DF4, 0xB0CE, 0x62D4, 0xB0CF, 0x8DCB, 0xB0D0, 0x9776, 0xB0D1, 0x628A, 0xB0D2, 0x8019, 0xB0D3, 0x575D, + 0xB0D4, 0x9738, 0xB0D5, 0x7F62, 0xB0D6, 0x7238, 0xB0D7, 0x767D, 0xB0D8, 0x67CF, 0xB0D9, 0x767E, 0xB0DA, 0x6446, 0xB0DB, 0x4F70, + 0xB0DC, 0x8D25, 0xB0DD, 0x62DC, 0xB0DE, 0x7A17, 0xB0DF, 0x6591, 0xB0E0, 0x73ED, 0xB0E1, 0x642C, 0xB0E2, 0x6273, 0xB0E3, 0x822C, + 0xB0E4, 0x9881, 0xB0E5, 0x677F, 0xB0E6, 0x7248, 0xB0E7, 0x626E, 0xB0E8, 0x62CC, 0xB0E9, 0x4F34, 0xB0EA, 0x74E3, 0xB0EB, 0x534A, + 0xB0EC, 0x529E, 0xB0ED, 0x7ECA, 0xB0EE, 0x90A6, 0xB0EF, 0x5E2E, 0xB0F0, 0x6886, 0xB0F1, 0x699C, 0xB0F2, 0x8180, 0xB0F3, 0x7ED1, + 0xB0F4, 0x68D2, 0xB0F5, 0x78C5, 0xB0F6, 0x868C, 0xB0F7, 0x9551, 0xB0F8, 0x508D, 0xB0F9, 0x8C24, 0xB0FA, 0x82DE, 0xB0FB, 0x80DE, + 0xB0FC, 0x5305, 0xB0FD, 0x8912, 0xB0FE, 0x5265, 0xB140, 0x76C4, 0xB141, 0x76C7, 0xB142, 0x76C9, 0xB143, 0x76CB, 0xB144, 0x76CC, + 0xB145, 0x76D3, 0xB146, 0x76D5, 0xB147, 0x76D9, 0xB148, 0x76DA, 0xB149, 0x76DC, 0xB14A, 0x76DD, 0xB14B, 0x76DE, 0xB14C, 0x76E0, + 0xB14D, 0x76E1, 0xB14E, 0x76E2, 0xB14F, 0x76E3, 0xB150, 0x76E4, 0xB151, 0x76E6, 0xB152, 0x76E7, 0xB153, 0x76E8, 0xB154, 0x76E9, + 0xB155, 0x76EA, 0xB156, 0x76EB, 0xB157, 0x76EC, 0xB158, 0x76ED, 0xB159, 0x76F0, 0xB15A, 0x76F3, 0xB15B, 0x76F5, 0xB15C, 0x76F6, + 0xB15D, 0x76F7, 0xB15E, 0x76FA, 0xB15F, 0x76FB, 0xB160, 0x76FD, 0xB161, 0x76FF, 0xB162, 0x7700, 0xB163, 0x7702, 0xB164, 0x7703, + 0xB165, 0x7705, 0xB166, 0x7706, 0xB167, 0x770A, 0xB168, 0x770C, 0xB169, 0x770E, 0xB16A, 0x770F, 0xB16B, 0x7710, 0xB16C, 0x7711, + 0xB16D, 0x7712, 0xB16E, 0x7713, 0xB16F, 0x7714, 0xB170, 0x7715, 0xB171, 0x7716, 0xB172, 0x7717, 0xB173, 0x7718, 0xB174, 0x771B, + 0xB175, 0x771C, 0xB176, 0x771D, 0xB177, 0x771E, 0xB178, 0x7721, 0xB179, 0x7723, 0xB17A, 0x7724, 0xB17B, 0x7725, 0xB17C, 0x7727, + 0xB17D, 0x772A, 0xB17E, 0x772B, 0xB180, 0x772C, 0xB181, 0x772E, 0xB182, 0x7730, 0xB183, 0x7731, 0xB184, 0x7732, 0xB185, 0x7733, + 0xB186, 0x7734, 0xB187, 0x7739, 0xB188, 0x773B, 0xB189, 0x773D, 0xB18A, 0x773E, 0xB18B, 0x773F, 0xB18C, 0x7742, 0xB18D, 0x7744, + 0xB18E, 0x7745, 0xB18F, 0x7746, 0xB190, 0x7748, 0xB191, 0x7749, 0xB192, 0x774A, 0xB193, 0x774B, 0xB194, 0x774C, 0xB195, 0x774D, + 0xB196, 0x774E, 0xB197, 0x774F, 0xB198, 0x7752, 0xB199, 0x7753, 0xB19A, 0x7754, 0xB19B, 0x7755, 0xB19C, 0x7756, 0xB19D, 0x7757, + 0xB19E, 0x7758, 0xB19F, 0x7759, 0xB1A0, 0x775C, 0xB1A1, 0x8584, 0xB1A2, 0x96F9, 0xB1A3, 0x4FDD, 0xB1A4, 0x5821, 0xB1A5, 0x9971, + 0xB1A6, 0x5B9D, 0xB1A7, 0x62B1, 0xB1A8, 0x62A5, 0xB1A9, 0x66B4, 0xB1AA, 0x8C79, 0xB1AB, 0x9C8D, 0xB1AC, 0x7206, 0xB1AD, 0x676F, + 0xB1AE, 0x7891, 0xB1AF, 0x60B2, 0xB1B0, 0x5351, 0xB1B1, 0x5317, 0xB1B2, 0x8F88, 0xB1B3, 0x80CC, 0xB1B4, 0x8D1D, 0xB1B5, 0x94A1, + 0xB1B6, 0x500D, 0xB1B7, 0x72C8, 0xB1B8, 0x5907, 0xB1B9, 0x60EB, 0xB1BA, 0x7119, 0xB1BB, 0x88AB, 0xB1BC, 0x5954, 0xB1BD, 0x82EF, + 0xB1BE, 0x672C, 0xB1BF, 0x7B28, 0xB1C0, 0x5D29, 0xB1C1, 0x7EF7, 0xB1C2, 0x752D, 0xB1C3, 0x6CF5, 0xB1C4, 0x8E66, 0xB1C5, 0x8FF8, + 0xB1C6, 0x903C, 0xB1C7, 0x9F3B, 0xB1C8, 0x6BD4, 0xB1C9, 0x9119, 0xB1CA, 0x7B14, 0xB1CB, 0x5F7C, 0xB1CC, 0x78A7, 0xB1CD, 0x84D6, + 0xB1CE, 0x853D, 0xB1CF, 0x6BD5, 0xB1D0, 0x6BD9, 0xB1D1, 0x6BD6, 0xB1D2, 0x5E01, 0xB1D3, 0x5E87, 0xB1D4, 0x75F9, 0xB1D5, 0x95ED, + 0xB1D6, 0x655D, 0xB1D7, 0x5F0A, 0xB1D8, 0x5FC5, 0xB1D9, 0x8F9F, 0xB1DA, 0x58C1, 0xB1DB, 0x81C2, 0xB1DC, 0x907F, 0xB1DD, 0x965B, + 0xB1DE, 0x97AD, 0xB1DF, 0x8FB9, 0xB1E0, 0x7F16, 0xB1E1, 0x8D2C, 0xB1E2, 0x6241, 0xB1E3, 0x4FBF, 0xB1E4, 0x53D8, 0xB1E5, 0x535E, + 0xB1E6, 0x8FA8, 0xB1E7, 0x8FA9, 0xB1E8, 0x8FAB, 0xB1E9, 0x904D, 0xB1EA, 0x6807, 0xB1EB, 0x5F6A, 0xB1EC, 0x8198, 0xB1ED, 0x8868, + 0xB1EE, 0x9CD6, 0xB1EF, 0x618B, 0xB1F0, 0x522B, 0xB1F1, 0x762A, 0xB1F2, 0x5F6C, 0xB1F3, 0x658C, 0xB1F4, 0x6FD2, 0xB1F5, 0x6EE8, + 0xB1F6, 0x5BBE, 0xB1F7, 0x6448, 0xB1F8, 0x5175, 0xB1F9, 0x51B0, 0xB1FA, 0x67C4, 0xB1FB, 0x4E19, 0xB1FC, 0x79C9, 0xB1FD, 0x997C, + 0xB1FE, 0x70B3, 0xB240, 0x775D, 0xB241, 0x775E, 0xB242, 0x775F, 0xB243, 0x7760, 0xB244, 0x7764, 0xB245, 0x7767, 0xB246, 0x7769, + 0xB247, 0x776A, 0xB248, 0x776D, 0xB249, 0x776E, 0xB24A, 0x776F, 0xB24B, 0x7770, 0xB24C, 0x7771, 0xB24D, 0x7772, 0xB24E, 0x7773, + 0xB24F, 0x7774, 0xB250, 0x7775, 0xB251, 0x7776, 0xB252, 0x7777, 0xB253, 0x7778, 0xB254, 0x777A, 0xB255, 0x777B, 0xB256, 0x777C, + 0xB257, 0x7781, 0xB258, 0x7782, 0xB259, 0x7783, 0xB25A, 0x7786, 0xB25B, 0x7787, 0xB25C, 0x7788, 0xB25D, 0x7789, 0xB25E, 0x778A, + 0xB25F, 0x778B, 0xB260, 0x778F, 0xB261, 0x7790, 0xB262, 0x7793, 0xB263, 0x7794, 0xB264, 0x7795, 0xB265, 0x7796, 0xB266, 0x7797, + 0xB267, 0x7798, 0xB268, 0x7799, 0xB269, 0x779A, 0xB26A, 0x779B, 0xB26B, 0x779C, 0xB26C, 0x779D, 0xB26D, 0x779E, 0xB26E, 0x77A1, + 0xB26F, 0x77A3, 0xB270, 0x77A4, 0xB271, 0x77A6, 0xB272, 0x77A8, 0xB273, 0x77AB, 0xB274, 0x77AD, 0xB275, 0x77AE, 0xB276, 0x77AF, + 0xB277, 0x77B1, 0xB278, 0x77B2, 0xB279, 0x77B4, 0xB27A, 0x77B6, 0xB27B, 0x77B7, 0xB27C, 0x77B8, 0xB27D, 0x77B9, 0xB27E, 0x77BA, + 0xB280, 0x77BC, 0xB281, 0x77BE, 0xB282, 0x77C0, 0xB283, 0x77C1, 0xB284, 0x77C2, 0xB285, 0x77C3, 0xB286, 0x77C4, 0xB287, 0x77C5, + 0xB288, 0x77C6, 0xB289, 0x77C7, 0xB28A, 0x77C8, 0xB28B, 0x77C9, 0xB28C, 0x77CA, 0xB28D, 0x77CB, 0xB28E, 0x77CC, 0xB28F, 0x77CE, + 0xB290, 0x77CF, 0xB291, 0x77D0, 0xB292, 0x77D1, 0xB293, 0x77D2, 0xB294, 0x77D3, 0xB295, 0x77D4, 0xB296, 0x77D5, 0xB297, 0x77D6, + 0xB298, 0x77D8, 0xB299, 0x77D9, 0xB29A, 0x77DA, 0xB29B, 0x77DD, 0xB29C, 0x77DE, 0xB29D, 0x77DF, 0xB29E, 0x77E0, 0xB29F, 0x77E1, + 0xB2A0, 0x77E4, 0xB2A1, 0x75C5, 0xB2A2, 0x5E76, 0xB2A3, 0x73BB, 0xB2A4, 0x83E0, 0xB2A5, 0x64AD, 0xB2A6, 0x62E8, 0xB2A7, 0x94B5, + 0xB2A8, 0x6CE2, 0xB2A9, 0x535A, 0xB2AA, 0x52C3, 0xB2AB, 0x640F, 0xB2AC, 0x94C2, 0xB2AD, 0x7B94, 0xB2AE, 0x4F2F, 0xB2AF, 0x5E1B, + 0xB2B0, 0x8236, 0xB2B1, 0x8116, 0xB2B2, 0x818A, 0xB2B3, 0x6E24, 0xB2B4, 0x6CCA, 0xB2B5, 0x9A73, 0xB2B6, 0x6355, 0xB2B7, 0x535C, + 0xB2B8, 0x54FA, 0xB2B9, 0x8865, 0xB2BA, 0x57E0, 0xB2BB, 0x4E0D, 0xB2BC, 0x5E03, 0xB2BD, 0x6B65, 0xB2BE, 0x7C3F, 0xB2BF, 0x90E8, + 0xB2C0, 0x6016, 0xB2C1, 0x64E6, 0xB2C2, 0x731C, 0xB2C3, 0x88C1, 0xB2C4, 0x6750, 0xB2C5, 0x624D, 0xB2C6, 0x8D22, 0xB2C7, 0x776C, + 0xB2C8, 0x8E29, 0xB2C9, 0x91C7, 0xB2CA, 0x5F69, 0xB2CB, 0x83DC, 0xB2CC, 0x8521, 0xB2CD, 0x9910, 0xB2CE, 0x53C2, 0xB2CF, 0x8695, + 0xB2D0, 0x6B8B, 0xB2D1, 0x60ED, 0xB2D2, 0x60E8, 0xB2D3, 0x707F, 0xB2D4, 0x82CD, 0xB2D5, 0x8231, 0xB2D6, 0x4ED3, 0xB2D7, 0x6CA7, + 0xB2D8, 0x85CF, 0xB2D9, 0x64CD, 0xB2DA, 0x7CD9, 0xB2DB, 0x69FD, 0xB2DC, 0x66F9, 0xB2DD, 0x8349, 0xB2DE, 0x5395, 0xB2DF, 0x7B56, + 0xB2E0, 0x4FA7, 0xB2E1, 0x518C, 0xB2E2, 0x6D4B, 0xB2E3, 0x5C42, 0xB2E4, 0x8E6D, 0xB2E5, 0x63D2, 0xB2E6, 0x53C9, 0xB2E7, 0x832C, + 0xB2E8, 0x8336, 0xB2E9, 0x67E5, 0xB2EA, 0x78B4, 0xB2EB, 0x643D, 0xB2EC, 0x5BDF, 0xB2ED, 0x5C94, 0xB2EE, 0x5DEE, 0xB2EF, 0x8BE7, + 0xB2F0, 0x62C6, 0xB2F1, 0x67F4, 0xB2F2, 0x8C7A, 0xB2F3, 0x6400, 0xB2F4, 0x63BA, 0xB2F5, 0x8749, 0xB2F6, 0x998B, 0xB2F7, 0x8C17, + 0xB2F8, 0x7F20, 0xB2F9, 0x94F2, 0xB2FA, 0x4EA7, 0xB2FB, 0x9610, 0xB2FC, 0x98A4, 0xB2FD, 0x660C, 0xB2FE, 0x7316, 0xB340, 0x77E6, + 0xB341, 0x77E8, 0xB342, 0x77EA, 0xB343, 0x77EF, 0xB344, 0x77F0, 0xB345, 0x77F1, 0xB346, 0x77F2, 0xB347, 0x77F4, 0xB348, 0x77F5, + 0xB349, 0x77F7, 0xB34A, 0x77F9, 0xB34B, 0x77FA, 0xB34C, 0x77FB, 0xB34D, 0x77FC, 0xB34E, 0x7803, 0xB34F, 0x7804, 0xB350, 0x7805, + 0xB351, 0x7806, 0xB352, 0x7807, 0xB353, 0x7808, 0xB354, 0x780A, 0xB355, 0x780B, 0xB356, 0x780E, 0xB357, 0x780F, 0xB358, 0x7810, + 0xB359, 0x7813, 0xB35A, 0x7815, 0xB35B, 0x7819, 0xB35C, 0x781B, 0xB35D, 0x781E, 0xB35E, 0x7820, 0xB35F, 0x7821, 0xB360, 0x7822, + 0xB361, 0x7824, 0xB362, 0x7828, 0xB363, 0x782A, 0xB364, 0x782B, 0xB365, 0x782E, 0xB366, 0x782F, 0xB367, 0x7831, 0xB368, 0x7832, + 0xB369, 0x7833, 0xB36A, 0x7835, 0xB36B, 0x7836, 0xB36C, 0x783D, 0xB36D, 0x783F, 0xB36E, 0x7841, 0xB36F, 0x7842, 0xB370, 0x7843, + 0xB371, 0x7844, 0xB372, 0x7846, 0xB373, 0x7848, 0xB374, 0x7849, 0xB375, 0x784A, 0xB376, 0x784B, 0xB377, 0x784D, 0xB378, 0x784F, + 0xB379, 0x7851, 0xB37A, 0x7853, 0xB37B, 0x7854, 0xB37C, 0x7858, 0xB37D, 0x7859, 0xB37E, 0x785A, 0xB380, 0x785B, 0xB381, 0x785C, + 0xB382, 0x785E, 0xB383, 0x785F, 0xB384, 0x7860, 0xB385, 0x7861, 0xB386, 0x7862, 0xB387, 0x7863, 0xB388, 0x7864, 0xB389, 0x7865, + 0xB38A, 0x7866, 0xB38B, 0x7867, 0xB38C, 0x7868, 0xB38D, 0x7869, 0xB38E, 0x786F, 0xB38F, 0x7870, 0xB390, 0x7871, 0xB391, 0x7872, + 0xB392, 0x7873, 0xB393, 0x7874, 0xB394, 0x7875, 0xB395, 0x7876, 0xB396, 0x7878, 0xB397, 0x7879, 0xB398, 0x787A, 0xB399, 0x787B, + 0xB39A, 0x787D, 0xB39B, 0x787E, 0xB39C, 0x787F, 0xB39D, 0x7880, 0xB39E, 0x7881, 0xB39F, 0x7882, 0xB3A0, 0x7883, 0xB3A1, 0x573A, + 0xB3A2, 0x5C1D, 0xB3A3, 0x5E38, 0xB3A4, 0x957F, 0xB3A5, 0x507F, 0xB3A6, 0x80A0, 0xB3A7, 0x5382, 0xB3A8, 0x655E, 0xB3A9, 0x7545, + 0xB3AA, 0x5531, 0xB3AB, 0x5021, 0xB3AC, 0x8D85, 0xB3AD, 0x6284, 0xB3AE, 0x949E, 0xB3AF, 0x671D, 0xB3B0, 0x5632, 0xB3B1, 0x6F6E, + 0xB3B2, 0x5DE2, 0xB3B3, 0x5435, 0xB3B4, 0x7092, 0xB3B5, 0x8F66, 0xB3B6, 0x626F, 0xB3B7, 0x64A4, 0xB3B8, 0x63A3, 0xB3B9, 0x5F7B, + 0xB3BA, 0x6F88, 0xB3BB, 0x90F4, 0xB3BC, 0x81E3, 0xB3BD, 0x8FB0, 0xB3BE, 0x5C18, 0xB3BF, 0x6668, 0xB3C0, 0x5FF1, 0xB3C1, 0x6C89, + 0xB3C2, 0x9648, 0xB3C3, 0x8D81, 0xB3C4, 0x886C, 0xB3C5, 0x6491, 0xB3C6, 0x79F0, 0xB3C7, 0x57CE, 0xB3C8, 0x6A59, 0xB3C9, 0x6210, + 0xB3CA, 0x5448, 0xB3CB, 0x4E58, 0xB3CC, 0x7A0B, 0xB3CD, 0x60E9, 0xB3CE, 0x6F84, 0xB3CF, 0x8BDA, 0xB3D0, 0x627F, 0xB3D1, 0x901E, + 0xB3D2, 0x9A8B, 0xB3D3, 0x79E4, 0xB3D4, 0x5403, 0xB3D5, 0x75F4, 0xB3D6, 0x6301, 0xB3D7, 0x5319, 0xB3D8, 0x6C60, 0xB3D9, 0x8FDF, + 0xB3DA, 0x5F1B, 0xB3DB, 0x9A70, 0xB3DC, 0x803B, 0xB3DD, 0x9F7F, 0xB3DE, 0x4F88, 0xB3DF, 0x5C3A, 0xB3E0, 0x8D64, 0xB3E1, 0x7FC5, + 0xB3E2, 0x65A5, 0xB3E3, 0x70BD, 0xB3E4, 0x5145, 0xB3E5, 0x51B2, 0xB3E6, 0x866B, 0xB3E7, 0x5D07, 0xB3E8, 0x5BA0, 0xB3E9, 0x62BD, + 0xB3EA, 0x916C, 0xB3EB, 0x7574, 0xB3EC, 0x8E0C, 0xB3ED, 0x7A20, 0xB3EE, 0x6101, 0xB3EF, 0x7B79, 0xB3F0, 0x4EC7, 0xB3F1, 0x7EF8, + 0xB3F2, 0x7785, 0xB3F3, 0x4E11, 0xB3F4, 0x81ED, 0xB3F5, 0x521D, 0xB3F6, 0x51FA, 0xB3F7, 0x6A71, 0xB3F8, 0x53A8, 0xB3F9, 0x8E87, + 0xB3FA, 0x9504, 0xB3FB, 0x96CF, 0xB3FC, 0x6EC1, 0xB3FD, 0x9664, 0xB3FE, 0x695A, 0xB440, 0x7884, 0xB441, 0x7885, 0xB442, 0x7886, + 0xB443, 0x7888, 0xB444, 0x788A, 0xB445, 0x788B, 0xB446, 0x788F, 0xB447, 0x7890, 0xB448, 0x7892, 0xB449, 0x7894, 0xB44A, 0x7895, + 0xB44B, 0x7896, 0xB44C, 0x7899, 0xB44D, 0x789D, 0xB44E, 0x789E, 0xB44F, 0x78A0, 0xB450, 0x78A2, 0xB451, 0x78A4, 0xB452, 0x78A6, + 0xB453, 0x78A8, 0xB454, 0x78A9, 0xB455, 0x78AA, 0xB456, 0x78AB, 0xB457, 0x78AC, 0xB458, 0x78AD, 0xB459, 0x78AE, 0xB45A, 0x78AF, + 0xB45B, 0x78B5, 0xB45C, 0x78B6, 0xB45D, 0x78B7, 0xB45E, 0x78B8, 0xB45F, 0x78BA, 0xB460, 0x78BB, 0xB461, 0x78BC, 0xB462, 0x78BD, + 0xB463, 0x78BF, 0xB464, 0x78C0, 0xB465, 0x78C2, 0xB466, 0x78C3, 0xB467, 0x78C4, 0xB468, 0x78C6, 0xB469, 0x78C7, 0xB46A, 0x78C8, + 0xB46B, 0x78CC, 0xB46C, 0x78CD, 0xB46D, 0x78CE, 0xB46E, 0x78CF, 0xB46F, 0x78D1, 0xB470, 0x78D2, 0xB471, 0x78D3, 0xB472, 0x78D6, + 0xB473, 0x78D7, 0xB474, 0x78D8, 0xB475, 0x78DA, 0xB476, 0x78DB, 0xB477, 0x78DC, 0xB478, 0x78DD, 0xB479, 0x78DE, 0xB47A, 0x78DF, + 0xB47B, 0x78E0, 0xB47C, 0x78E1, 0xB47D, 0x78E2, 0xB47E, 0x78E3, 0xB480, 0x78E4, 0xB481, 0x78E5, 0xB482, 0x78E6, 0xB483, 0x78E7, + 0xB484, 0x78E9, 0xB485, 0x78EA, 0xB486, 0x78EB, 0xB487, 0x78ED, 0xB488, 0x78EE, 0xB489, 0x78EF, 0xB48A, 0x78F0, 0xB48B, 0x78F1, + 0xB48C, 0x78F3, 0xB48D, 0x78F5, 0xB48E, 0x78F6, 0xB48F, 0x78F8, 0xB490, 0x78F9, 0xB491, 0x78FB, 0xB492, 0x78FC, 0xB493, 0x78FD, + 0xB494, 0x78FE, 0xB495, 0x78FF, 0xB496, 0x7900, 0xB497, 0x7902, 0xB498, 0x7903, 0xB499, 0x7904, 0xB49A, 0x7906, 0xB49B, 0x7907, + 0xB49C, 0x7908, 0xB49D, 0x7909, 0xB49E, 0x790A, 0xB49F, 0x790B, 0xB4A0, 0x790C, 0xB4A1, 0x7840, 0xB4A2, 0x50A8, 0xB4A3, 0x77D7, + 0xB4A4, 0x6410, 0xB4A5, 0x89E6, 0xB4A6, 0x5904, 0xB4A7, 0x63E3, 0xB4A8, 0x5DDD, 0xB4A9, 0x7A7F, 0xB4AA, 0x693D, 0xB4AB, 0x4F20, + 0xB4AC, 0x8239, 0xB4AD, 0x5598, 0xB4AE, 0x4E32, 0xB4AF, 0x75AE, 0xB4B0, 0x7A97, 0xB4B1, 0x5E62, 0xB4B2, 0x5E8A, 0xB4B3, 0x95EF, + 0xB4B4, 0x521B, 0xB4B5, 0x5439, 0xB4B6, 0x708A, 0xB4B7, 0x6376, 0xB4B8, 0x9524, 0xB4B9, 0x5782, 0xB4BA, 0x6625, 0xB4BB, 0x693F, + 0xB4BC, 0x9187, 0xB4BD, 0x5507, 0xB4BE, 0x6DF3, 0xB4BF, 0x7EAF, 0xB4C0, 0x8822, 0xB4C1, 0x6233, 0xB4C2, 0x7EF0, 0xB4C3, 0x75B5, + 0xB4C4, 0x8328, 0xB4C5, 0x78C1, 0xB4C6, 0x96CC, 0xB4C7, 0x8F9E, 0xB4C8, 0x6148, 0xB4C9, 0x74F7, 0xB4CA, 0x8BCD, 0xB4CB, 0x6B64, + 0xB4CC, 0x523A, 0xB4CD, 0x8D50, 0xB4CE, 0x6B21, 0xB4CF, 0x806A, 0xB4D0, 0x8471, 0xB4D1, 0x56F1, 0xB4D2, 0x5306, 0xB4D3, 0x4ECE, + 0xB4D4, 0x4E1B, 0xB4D5, 0x51D1, 0xB4D6, 0x7C97, 0xB4D7, 0x918B, 0xB4D8, 0x7C07, 0xB4D9, 0x4FC3, 0xB4DA, 0x8E7F, 0xB4DB, 0x7BE1, + 0xB4DC, 0x7A9C, 0xB4DD, 0x6467, 0xB4DE, 0x5D14, 0xB4DF, 0x50AC, 0xB4E0, 0x8106, 0xB4E1, 0x7601, 0xB4E2, 0x7CB9, 0xB4E3, 0x6DEC, + 0xB4E4, 0x7FE0, 0xB4E5, 0x6751, 0xB4E6, 0x5B58, 0xB4E7, 0x5BF8, 0xB4E8, 0x78CB, 0xB4E9, 0x64AE, 0xB4EA, 0x6413, 0xB4EB, 0x63AA, + 0xB4EC, 0x632B, 0xB4ED, 0x9519, 0xB4EE, 0x642D, 0xB4EF, 0x8FBE, 0xB4F0, 0x7B54, 0xB4F1, 0x7629, 0xB4F2, 0x6253, 0xB4F3, 0x5927, + 0xB4F4, 0x5446, 0xB4F5, 0x6B79, 0xB4F6, 0x50A3, 0xB4F7, 0x6234, 0xB4F8, 0x5E26, 0xB4F9, 0x6B86, 0xB4FA, 0x4EE3, 0xB4FB, 0x8D37, + 0xB4FC, 0x888B, 0xB4FD, 0x5F85, 0xB4FE, 0x902E, 0xB540, 0x790D, 0xB541, 0x790E, 0xB542, 0x790F, 0xB543, 0x7910, 0xB544, 0x7911, + 0xB545, 0x7912, 0xB546, 0x7914, 0xB547, 0x7915, 0xB548, 0x7916, 0xB549, 0x7917, 0xB54A, 0x7918, 0xB54B, 0x7919, 0xB54C, 0x791A, + 0xB54D, 0x791B, 0xB54E, 0x791C, 0xB54F, 0x791D, 0xB550, 0x791F, 0xB551, 0x7920, 0xB552, 0x7921, 0xB553, 0x7922, 0xB554, 0x7923, + 0xB555, 0x7925, 0xB556, 0x7926, 0xB557, 0x7927, 0xB558, 0x7928, 0xB559, 0x7929, 0xB55A, 0x792A, 0xB55B, 0x792B, 0xB55C, 0x792C, + 0xB55D, 0x792D, 0xB55E, 0x792E, 0xB55F, 0x792F, 0xB560, 0x7930, 0xB561, 0x7931, 0xB562, 0x7932, 0xB563, 0x7933, 0xB564, 0x7935, + 0xB565, 0x7936, 0xB566, 0x7937, 0xB567, 0x7938, 0xB568, 0x7939, 0xB569, 0x793D, 0xB56A, 0x793F, 0xB56B, 0x7942, 0xB56C, 0x7943, + 0xB56D, 0x7944, 0xB56E, 0x7945, 0xB56F, 0x7947, 0xB570, 0x794A, 0xB571, 0x794B, 0xB572, 0x794C, 0xB573, 0x794D, 0xB574, 0x794E, + 0xB575, 0x794F, 0xB576, 0x7950, 0xB577, 0x7951, 0xB578, 0x7952, 0xB579, 0x7954, 0xB57A, 0x7955, 0xB57B, 0x7958, 0xB57C, 0x7959, + 0xB57D, 0x7961, 0xB57E, 0x7963, 0xB580, 0x7964, 0xB581, 0x7966, 0xB582, 0x7969, 0xB583, 0x796A, 0xB584, 0x796B, 0xB585, 0x796C, + 0xB586, 0x796E, 0xB587, 0x7970, 0xB588, 0x7971, 0xB589, 0x7972, 0xB58A, 0x7973, 0xB58B, 0x7974, 0xB58C, 0x7975, 0xB58D, 0x7976, + 0xB58E, 0x7979, 0xB58F, 0x797B, 0xB590, 0x797C, 0xB591, 0x797D, 0xB592, 0x797E, 0xB593, 0x797F, 0xB594, 0x7982, 0xB595, 0x7983, + 0xB596, 0x7986, 0xB597, 0x7987, 0xB598, 0x7988, 0xB599, 0x7989, 0xB59A, 0x798B, 0xB59B, 0x798C, 0xB59C, 0x798D, 0xB59D, 0x798E, + 0xB59E, 0x7990, 0xB59F, 0x7991, 0xB5A0, 0x7992, 0xB5A1, 0x6020, 0xB5A2, 0x803D, 0xB5A3, 0x62C5, 0xB5A4, 0x4E39, 0xB5A5, 0x5355, + 0xB5A6, 0x90F8, 0xB5A7, 0x63B8, 0xB5A8, 0x80C6, 0xB5A9, 0x65E6, 0xB5AA, 0x6C2E, 0xB5AB, 0x4F46, 0xB5AC, 0x60EE, 0xB5AD, 0x6DE1, + 0xB5AE, 0x8BDE, 0xB5AF, 0x5F39, 0xB5B0, 0x86CB, 0xB5B1, 0x5F53, 0xB5B2, 0x6321, 0xB5B3, 0x515A, 0xB5B4, 0x8361, 0xB5B5, 0x6863, + 0xB5B6, 0x5200, 0xB5B7, 0x6363, 0xB5B8, 0x8E48, 0xB5B9, 0x5012, 0xB5BA, 0x5C9B, 0xB5BB, 0x7977, 0xB5BC, 0x5BFC, 0xB5BD, 0x5230, + 0xB5BE, 0x7A3B, 0xB5BF, 0x60BC, 0xB5C0, 0x9053, 0xB5C1, 0x76D7, 0xB5C2, 0x5FB7, 0xB5C3, 0x5F97, 0xB5C4, 0x7684, 0xB5C5, 0x8E6C, + 0xB5C6, 0x706F, 0xB5C7, 0x767B, 0xB5C8, 0x7B49, 0xB5C9, 0x77AA, 0xB5CA, 0x51F3, 0xB5CB, 0x9093, 0xB5CC, 0x5824, 0xB5CD, 0x4F4E, + 0xB5CE, 0x6EF4, 0xB5CF, 0x8FEA, 0xB5D0, 0x654C, 0xB5D1, 0x7B1B, 0xB5D2, 0x72C4, 0xB5D3, 0x6DA4, 0xB5D4, 0x7FDF, 0xB5D5, 0x5AE1, + 0xB5D6, 0x62B5, 0xB5D7, 0x5E95, 0xB5D8, 0x5730, 0xB5D9, 0x8482, 0xB5DA, 0x7B2C, 0xB5DB, 0x5E1D, 0xB5DC, 0x5F1F, 0xB5DD, 0x9012, + 0xB5DE, 0x7F14, 0xB5DF, 0x98A0, 0xB5E0, 0x6382, 0xB5E1, 0x6EC7, 0xB5E2, 0x7898, 0xB5E3, 0x70B9, 0xB5E4, 0x5178, 0xB5E5, 0x975B, + 0xB5E6, 0x57AB, 0xB5E7, 0x7535, 0xB5E8, 0x4F43, 0xB5E9, 0x7538, 0xB5EA, 0x5E97, 0xB5EB, 0x60E6, 0xB5EC, 0x5960, 0xB5ED, 0x6DC0, + 0xB5EE, 0x6BBF, 0xB5EF, 0x7889, 0xB5F0, 0x53FC, 0xB5F1, 0x96D5, 0xB5F2, 0x51CB, 0xB5F3, 0x5201, 0xB5F4, 0x6389, 0xB5F5, 0x540A, + 0xB5F6, 0x9493, 0xB5F7, 0x8C03, 0xB5F8, 0x8DCC, 0xB5F9, 0x7239, 0xB5FA, 0x789F, 0xB5FB, 0x8776, 0xB5FC, 0x8FED, 0xB5FD, 0x8C0D, + 0xB5FE, 0x53E0, 0xB640, 0x7993, 0xB641, 0x7994, 0xB642, 0x7995, 0xB643, 0x7996, 0xB644, 0x7997, 0xB645, 0x7998, 0xB646, 0x7999, + 0xB647, 0x799B, 0xB648, 0x799C, 0xB649, 0x799D, 0xB64A, 0x799E, 0xB64B, 0x799F, 0xB64C, 0x79A0, 0xB64D, 0x79A1, 0xB64E, 0x79A2, + 0xB64F, 0x79A3, 0xB650, 0x79A4, 0xB651, 0x79A5, 0xB652, 0x79A6, 0xB653, 0x79A8, 0xB654, 0x79A9, 0xB655, 0x79AA, 0xB656, 0x79AB, + 0xB657, 0x79AC, 0xB658, 0x79AD, 0xB659, 0x79AE, 0xB65A, 0x79AF, 0xB65B, 0x79B0, 0xB65C, 0x79B1, 0xB65D, 0x79B2, 0xB65E, 0x79B4, + 0xB65F, 0x79B5, 0xB660, 0x79B6, 0xB661, 0x79B7, 0xB662, 0x79B8, 0xB663, 0x79BC, 0xB664, 0x79BF, 0xB665, 0x79C2, 0xB666, 0x79C4, + 0xB667, 0x79C5, 0xB668, 0x79C7, 0xB669, 0x79C8, 0xB66A, 0x79CA, 0xB66B, 0x79CC, 0xB66C, 0x79CE, 0xB66D, 0x79CF, 0xB66E, 0x79D0, + 0xB66F, 0x79D3, 0xB670, 0x79D4, 0xB671, 0x79D6, 0xB672, 0x79D7, 0xB673, 0x79D9, 0xB674, 0x79DA, 0xB675, 0x79DB, 0xB676, 0x79DC, + 0xB677, 0x79DD, 0xB678, 0x79DE, 0xB679, 0x79E0, 0xB67A, 0x79E1, 0xB67B, 0x79E2, 0xB67C, 0x79E5, 0xB67D, 0x79E8, 0xB67E, 0x79EA, + 0xB680, 0x79EC, 0xB681, 0x79EE, 0xB682, 0x79F1, 0xB683, 0x79F2, 0xB684, 0x79F3, 0xB685, 0x79F4, 0xB686, 0x79F5, 0xB687, 0x79F6, + 0xB688, 0x79F7, 0xB689, 0x79F9, 0xB68A, 0x79FA, 0xB68B, 0x79FC, 0xB68C, 0x79FE, 0xB68D, 0x79FF, 0xB68E, 0x7A01, 0xB68F, 0x7A04, + 0xB690, 0x7A05, 0xB691, 0x7A07, 0xB692, 0x7A08, 0xB693, 0x7A09, 0xB694, 0x7A0A, 0xB695, 0x7A0C, 0xB696, 0x7A0F, 0xB697, 0x7A10, + 0xB698, 0x7A11, 0xB699, 0x7A12, 0xB69A, 0x7A13, 0xB69B, 0x7A15, 0xB69C, 0x7A16, 0xB69D, 0x7A18, 0xB69E, 0x7A19, 0xB69F, 0x7A1B, + 0xB6A0, 0x7A1C, 0xB6A1, 0x4E01, 0xB6A2, 0x76EF, 0xB6A3, 0x53EE, 0xB6A4, 0x9489, 0xB6A5, 0x9876, 0xB6A6, 0x9F0E, 0xB6A7, 0x952D, + 0xB6A8, 0x5B9A, 0xB6A9, 0x8BA2, 0xB6AA, 0x4E22, 0xB6AB, 0x4E1C, 0xB6AC, 0x51AC, 0xB6AD, 0x8463, 0xB6AE, 0x61C2, 0xB6AF, 0x52A8, + 0xB6B0, 0x680B, 0xB6B1, 0x4F97, 0xB6B2, 0x606B, 0xB6B3, 0x51BB, 0xB6B4, 0x6D1E, 0xB6B5, 0x515C, 0xB6B6, 0x6296, 0xB6B7, 0x6597, + 0xB6B8, 0x9661, 0xB6B9, 0x8C46, 0xB6BA, 0x9017, 0xB6BB, 0x75D8, 0xB6BC, 0x90FD, 0xB6BD, 0x7763, 0xB6BE, 0x6BD2, 0xB6BF, 0x728A, + 0xB6C0, 0x72EC, 0xB6C1, 0x8BFB, 0xB6C2, 0x5835, 0xB6C3, 0x7779, 0xB6C4, 0x8D4C, 0xB6C5, 0x675C, 0xB6C6, 0x9540, 0xB6C7, 0x809A, + 0xB6C8, 0x5EA6, 0xB6C9, 0x6E21, 0xB6CA, 0x5992, 0xB6CB, 0x7AEF, 0xB6CC, 0x77ED, 0xB6CD, 0x953B, 0xB6CE, 0x6BB5, 0xB6CF, 0x65AD, + 0xB6D0, 0x7F0E, 0xB6D1, 0x5806, 0xB6D2, 0x5151, 0xB6D3, 0x961F, 0xB6D4, 0x5BF9, 0xB6D5, 0x58A9, 0xB6D6, 0x5428, 0xB6D7, 0x8E72, + 0xB6D8, 0x6566, 0xB6D9, 0x987F, 0xB6DA, 0x56E4, 0xB6DB, 0x949D, 0xB6DC, 0x76FE, 0xB6DD, 0x9041, 0xB6DE, 0x6387, 0xB6DF, 0x54C6, + 0xB6E0, 0x591A, 0xB6E1, 0x593A, 0xB6E2, 0x579B, 0xB6E3, 0x8EB2, 0xB6E4, 0x6735, 0xB6E5, 0x8DFA, 0xB6E6, 0x8235, 0xB6E7, 0x5241, + 0xB6E8, 0x60F0, 0xB6E9, 0x5815, 0xB6EA, 0x86FE, 0xB6EB, 0x5CE8, 0xB6EC, 0x9E45, 0xB6ED, 0x4FC4, 0xB6EE, 0x989D, 0xB6EF, 0x8BB9, + 0xB6F0, 0x5A25, 0xB6F1, 0x6076, 0xB6F2, 0x5384, 0xB6F3, 0x627C, 0xB6F4, 0x904F, 0xB6F5, 0x9102, 0xB6F6, 0x997F, 0xB6F7, 0x6069, + 0xB6F8, 0x800C, 0xB6F9, 0x513F, 0xB6FA, 0x8033, 0xB6FB, 0x5C14, 0xB6FC, 0x9975, 0xB6FD, 0x6D31, 0xB6FE, 0x4E8C, 0xB740, 0x7A1D, + 0xB741, 0x7A1F, 0xB742, 0x7A21, 0xB743, 0x7A22, 0xB744, 0x7A24, 0xB745, 0x7A25, 0xB746, 0x7A26, 0xB747, 0x7A27, 0xB748, 0x7A28, + 0xB749, 0x7A29, 0xB74A, 0x7A2A, 0xB74B, 0x7A2B, 0xB74C, 0x7A2C, 0xB74D, 0x7A2D, 0xB74E, 0x7A2E, 0xB74F, 0x7A2F, 0xB750, 0x7A30, + 0xB751, 0x7A31, 0xB752, 0x7A32, 0xB753, 0x7A34, 0xB754, 0x7A35, 0xB755, 0x7A36, 0xB756, 0x7A38, 0xB757, 0x7A3A, 0xB758, 0x7A3E, + 0xB759, 0x7A40, 0xB75A, 0x7A41, 0xB75B, 0x7A42, 0xB75C, 0x7A43, 0xB75D, 0x7A44, 0xB75E, 0x7A45, 0xB75F, 0x7A47, 0xB760, 0x7A48, + 0xB761, 0x7A49, 0xB762, 0x7A4A, 0xB763, 0x7A4B, 0xB764, 0x7A4C, 0xB765, 0x7A4D, 0xB766, 0x7A4E, 0xB767, 0x7A4F, 0xB768, 0x7A50, + 0xB769, 0x7A52, 0xB76A, 0x7A53, 0xB76B, 0x7A54, 0xB76C, 0x7A55, 0xB76D, 0x7A56, 0xB76E, 0x7A58, 0xB76F, 0x7A59, 0xB770, 0x7A5A, + 0xB771, 0x7A5B, 0xB772, 0x7A5C, 0xB773, 0x7A5D, 0xB774, 0x7A5E, 0xB775, 0x7A5F, 0xB776, 0x7A60, 0xB777, 0x7A61, 0xB778, 0x7A62, + 0xB779, 0x7A63, 0xB77A, 0x7A64, 0xB77B, 0x7A65, 0xB77C, 0x7A66, 0xB77D, 0x7A67, 0xB77E, 0x7A68, 0xB780, 0x7A69, 0xB781, 0x7A6A, + 0xB782, 0x7A6B, 0xB783, 0x7A6C, 0xB784, 0x7A6D, 0xB785, 0x7A6E, 0xB786, 0x7A6F, 0xB787, 0x7A71, 0xB788, 0x7A72, 0xB789, 0x7A73, + 0xB78A, 0x7A75, 0xB78B, 0x7A7B, 0xB78C, 0x7A7C, 0xB78D, 0x7A7D, 0xB78E, 0x7A7E, 0xB78F, 0x7A82, 0xB790, 0x7A85, 0xB791, 0x7A87, + 0xB792, 0x7A89, 0xB793, 0x7A8A, 0xB794, 0x7A8B, 0xB795, 0x7A8C, 0xB796, 0x7A8E, 0xB797, 0x7A8F, 0xB798, 0x7A90, 0xB799, 0x7A93, + 0xB79A, 0x7A94, 0xB79B, 0x7A99, 0xB79C, 0x7A9A, 0xB79D, 0x7A9B, 0xB79E, 0x7A9E, 0xB79F, 0x7AA1, 0xB7A0, 0x7AA2, 0xB7A1, 0x8D30, + 0xB7A2, 0x53D1, 0xB7A3, 0x7F5A, 0xB7A4, 0x7B4F, 0xB7A5, 0x4F10, 0xB7A6, 0x4E4F, 0xB7A7, 0x9600, 0xB7A8, 0x6CD5, 0xB7A9, 0x73D0, + 0xB7AA, 0x85E9, 0xB7AB, 0x5E06, 0xB7AC, 0x756A, 0xB7AD, 0x7FFB, 0xB7AE, 0x6A0A, 0xB7AF, 0x77FE, 0xB7B0, 0x9492, 0xB7B1, 0x7E41, + 0xB7B2, 0x51E1, 0xB7B3, 0x70E6, 0xB7B4, 0x53CD, 0xB7B5, 0x8FD4, 0xB7B6, 0x8303, 0xB7B7, 0x8D29, 0xB7B8, 0x72AF, 0xB7B9, 0x996D, + 0xB7BA, 0x6CDB, 0xB7BB, 0x574A, 0xB7BC, 0x82B3, 0xB7BD, 0x65B9, 0xB7BE, 0x80AA, 0xB7BF, 0x623F, 0xB7C0, 0x9632, 0xB7C1, 0x59A8, + 0xB7C2, 0x4EFF, 0xB7C3, 0x8BBF, 0xB7C4, 0x7EBA, 0xB7C5, 0x653E, 0xB7C6, 0x83F2, 0xB7C7, 0x975E, 0xB7C8, 0x5561, 0xB7C9, 0x98DE, + 0xB7CA, 0x80A5, 0xB7CB, 0x532A, 0xB7CC, 0x8BFD, 0xB7CD, 0x5420, 0xB7CE, 0x80BA, 0xB7CF, 0x5E9F, 0xB7D0, 0x6CB8, 0xB7D1, 0x8D39, + 0xB7D2, 0x82AC, 0xB7D3, 0x915A, 0xB7D4, 0x5429, 0xB7D5, 0x6C1B, 0xB7D6, 0x5206, 0xB7D7, 0x7EB7, 0xB7D8, 0x575F, 0xB7D9, 0x711A, + 0xB7DA, 0x6C7E, 0xB7DB, 0x7C89, 0xB7DC, 0x594B, 0xB7DD, 0x4EFD, 0xB7DE, 0x5FFF, 0xB7DF, 0x6124, 0xB7E0, 0x7CAA, 0xB7E1, 0x4E30, + 0xB7E2, 0x5C01, 0xB7E3, 0x67AB, 0xB7E4, 0x8702, 0xB7E5, 0x5CF0, 0xB7E6, 0x950B, 0xB7E7, 0x98CE, 0xB7E8, 0x75AF, 0xB7E9, 0x70FD, + 0xB7EA, 0x9022, 0xB7EB, 0x51AF, 0xB7EC, 0x7F1D, 0xB7ED, 0x8BBD, 0xB7EE, 0x5949, 0xB7EF, 0x51E4, 0xB7F0, 0x4F5B, 0xB7F1, 0x5426, + 0xB7F2, 0x592B, 0xB7F3, 0x6577, 0xB7F4, 0x80A4, 0xB7F5, 0x5B75, 0xB7F6, 0x6276, 0xB7F7, 0x62C2, 0xB7F8, 0x8F90, 0xB7F9, 0x5E45, + 0xB7FA, 0x6C1F, 0xB7FB, 0x7B26, 0xB7FC, 0x4F0F, 0xB7FD, 0x4FD8, 0xB7FE, 0x670D, 0xB840, 0x7AA3, 0xB841, 0x7AA4, 0xB842, 0x7AA7, + 0xB843, 0x7AA9, 0xB844, 0x7AAA, 0xB845, 0x7AAB, 0xB846, 0x7AAE, 0xB847, 0x7AAF, 0xB848, 0x7AB0, 0xB849, 0x7AB1, 0xB84A, 0x7AB2, + 0xB84B, 0x7AB4, 0xB84C, 0x7AB5, 0xB84D, 0x7AB6, 0xB84E, 0x7AB7, 0xB84F, 0x7AB8, 0xB850, 0x7AB9, 0xB851, 0x7ABA, 0xB852, 0x7ABB, + 0xB853, 0x7ABC, 0xB854, 0x7ABD, 0xB855, 0x7ABE, 0xB856, 0x7AC0, 0xB857, 0x7AC1, 0xB858, 0x7AC2, 0xB859, 0x7AC3, 0xB85A, 0x7AC4, + 0xB85B, 0x7AC5, 0xB85C, 0x7AC6, 0xB85D, 0x7AC7, 0xB85E, 0x7AC8, 0xB85F, 0x7AC9, 0xB860, 0x7ACA, 0xB861, 0x7ACC, 0xB862, 0x7ACD, + 0xB863, 0x7ACE, 0xB864, 0x7ACF, 0xB865, 0x7AD0, 0xB866, 0x7AD1, 0xB867, 0x7AD2, 0xB868, 0x7AD3, 0xB869, 0x7AD4, 0xB86A, 0x7AD5, + 0xB86B, 0x7AD7, 0xB86C, 0x7AD8, 0xB86D, 0x7ADA, 0xB86E, 0x7ADB, 0xB86F, 0x7ADC, 0xB870, 0x7ADD, 0xB871, 0x7AE1, 0xB872, 0x7AE2, + 0xB873, 0x7AE4, 0xB874, 0x7AE7, 0xB875, 0x7AE8, 0xB876, 0x7AE9, 0xB877, 0x7AEA, 0xB878, 0x7AEB, 0xB879, 0x7AEC, 0xB87A, 0x7AEE, + 0xB87B, 0x7AF0, 0xB87C, 0x7AF1, 0xB87D, 0x7AF2, 0xB87E, 0x7AF3, 0xB880, 0x7AF4, 0xB881, 0x7AF5, 0xB882, 0x7AF6, 0xB883, 0x7AF7, + 0xB884, 0x7AF8, 0xB885, 0x7AFB, 0xB886, 0x7AFC, 0xB887, 0x7AFE, 0xB888, 0x7B00, 0xB889, 0x7B01, 0xB88A, 0x7B02, 0xB88B, 0x7B05, + 0xB88C, 0x7B07, 0xB88D, 0x7B09, 0xB88E, 0x7B0C, 0xB88F, 0x7B0D, 0xB890, 0x7B0E, 0xB891, 0x7B10, 0xB892, 0x7B12, 0xB893, 0x7B13, + 0xB894, 0x7B16, 0xB895, 0x7B17, 0xB896, 0x7B18, 0xB897, 0x7B1A, 0xB898, 0x7B1C, 0xB899, 0x7B1D, 0xB89A, 0x7B1F, 0xB89B, 0x7B21, + 0xB89C, 0x7B22, 0xB89D, 0x7B23, 0xB89E, 0x7B27, 0xB89F, 0x7B29, 0xB8A0, 0x7B2D, 0xB8A1, 0x6D6E, 0xB8A2, 0x6DAA, 0xB8A3, 0x798F, + 0xB8A4, 0x88B1, 0xB8A5, 0x5F17, 0xB8A6, 0x752B, 0xB8A7, 0x629A, 0xB8A8, 0x8F85, 0xB8A9, 0x4FEF, 0xB8AA, 0x91DC, 0xB8AB, 0x65A7, + 0xB8AC, 0x812F, 0xB8AD, 0x8151, 0xB8AE, 0x5E9C, 0xB8AF, 0x8150, 0xB8B0, 0x8D74, 0xB8B1, 0x526F, 0xB8B2, 0x8986, 0xB8B3, 0x8D4B, + 0xB8B4, 0x590D, 0xB8B5, 0x5085, 0xB8B6, 0x4ED8, 0xB8B7, 0x961C, 0xB8B8, 0x7236, 0xB8B9, 0x8179, 0xB8BA, 0x8D1F, 0xB8BB, 0x5BCC, + 0xB8BC, 0x8BA3, 0xB8BD, 0x9644, 0xB8BE, 0x5987, 0xB8BF, 0x7F1A, 0xB8C0, 0x5490, 0xB8C1, 0x5676, 0xB8C2, 0x560E, 0xB8C3, 0x8BE5, + 0xB8C4, 0x6539, 0xB8C5, 0x6982, 0xB8C6, 0x9499, 0xB8C7, 0x76D6, 0xB8C8, 0x6E89, 0xB8C9, 0x5E72, 0xB8CA, 0x7518, 0xB8CB, 0x6746, + 0xB8CC, 0x67D1, 0xB8CD, 0x7AFF, 0xB8CE, 0x809D, 0xB8CF, 0x8D76, 0xB8D0, 0x611F, 0xB8D1, 0x79C6, 0xB8D2, 0x6562, 0xB8D3, 0x8D63, + 0xB8D4, 0x5188, 0xB8D5, 0x521A, 0xB8D6, 0x94A2, 0xB8D7, 0x7F38, 0xB8D8, 0x809B, 0xB8D9, 0x7EB2, 0xB8DA, 0x5C97, 0xB8DB, 0x6E2F, + 0xB8DC, 0x6760, 0xB8DD, 0x7BD9, 0xB8DE, 0x768B, 0xB8DF, 0x9AD8, 0xB8E0, 0x818F, 0xB8E1, 0x7F94, 0xB8E2, 0x7CD5, 0xB8E3, 0x641E, + 0xB8E4, 0x9550, 0xB8E5, 0x7A3F, 0xB8E6, 0x544A, 0xB8E7, 0x54E5, 0xB8E8, 0x6B4C, 0xB8E9, 0x6401, 0xB8EA, 0x6208, 0xB8EB, 0x9E3D, + 0xB8EC, 0x80F3, 0xB8ED, 0x7599, 0xB8EE, 0x5272, 0xB8EF, 0x9769, 0xB8F0, 0x845B, 0xB8F1, 0x683C, 0xB8F2, 0x86E4, 0xB8F3, 0x9601, + 0xB8F4, 0x9694, 0xB8F5, 0x94EC, 0xB8F6, 0x4E2A, 0xB8F7, 0x5404, 0xB8F8, 0x7ED9, 0xB8F9, 0x6839, 0xB8FA, 0x8DDF, 0xB8FB, 0x8015, + 0xB8FC, 0x66F4, 0xB8FD, 0x5E9A, 0xB8FE, 0x7FB9, 0xB940, 0x7B2F, 0xB941, 0x7B30, 0xB942, 0x7B32, 0xB943, 0x7B34, 0xB944, 0x7B35, + 0xB945, 0x7B36, 0xB946, 0x7B37, 0xB947, 0x7B39, 0xB948, 0x7B3B, 0xB949, 0x7B3D, 0xB94A, 0x7B3F, 0xB94B, 0x7B40, 0xB94C, 0x7B41, + 0xB94D, 0x7B42, 0xB94E, 0x7B43, 0xB94F, 0x7B44, 0xB950, 0x7B46, 0xB951, 0x7B48, 0xB952, 0x7B4A, 0xB953, 0x7B4D, 0xB954, 0x7B4E, + 0xB955, 0x7B53, 0xB956, 0x7B55, 0xB957, 0x7B57, 0xB958, 0x7B59, 0xB959, 0x7B5C, 0xB95A, 0x7B5E, 0xB95B, 0x7B5F, 0xB95C, 0x7B61, + 0xB95D, 0x7B63, 0xB95E, 0x7B64, 0xB95F, 0x7B65, 0xB960, 0x7B66, 0xB961, 0x7B67, 0xB962, 0x7B68, 0xB963, 0x7B69, 0xB964, 0x7B6A, + 0xB965, 0x7B6B, 0xB966, 0x7B6C, 0xB967, 0x7B6D, 0xB968, 0x7B6F, 0xB969, 0x7B70, 0xB96A, 0x7B73, 0xB96B, 0x7B74, 0xB96C, 0x7B76, + 0xB96D, 0x7B78, 0xB96E, 0x7B7A, 0xB96F, 0x7B7C, 0xB970, 0x7B7D, 0xB971, 0x7B7F, 0xB972, 0x7B81, 0xB973, 0x7B82, 0xB974, 0x7B83, + 0xB975, 0x7B84, 0xB976, 0x7B86, 0xB977, 0x7B87, 0xB978, 0x7B88, 0xB979, 0x7B89, 0xB97A, 0x7B8A, 0xB97B, 0x7B8B, 0xB97C, 0x7B8C, + 0xB97D, 0x7B8E, 0xB97E, 0x7B8F, 0xB980, 0x7B91, 0xB981, 0x7B92, 0xB982, 0x7B93, 0xB983, 0x7B96, 0xB984, 0x7B98, 0xB985, 0x7B99, + 0xB986, 0x7B9A, 0xB987, 0x7B9B, 0xB988, 0x7B9E, 0xB989, 0x7B9F, 0xB98A, 0x7BA0, 0xB98B, 0x7BA3, 0xB98C, 0x7BA4, 0xB98D, 0x7BA5, + 0xB98E, 0x7BAE, 0xB98F, 0x7BAF, 0xB990, 0x7BB0, 0xB991, 0x7BB2, 0xB992, 0x7BB3, 0xB993, 0x7BB5, 0xB994, 0x7BB6, 0xB995, 0x7BB7, + 0xB996, 0x7BB9, 0xB997, 0x7BBA, 0xB998, 0x7BBB, 0xB999, 0x7BBC, 0xB99A, 0x7BBD, 0xB99B, 0x7BBE, 0xB99C, 0x7BBF, 0xB99D, 0x7BC0, + 0xB99E, 0x7BC2, 0xB99F, 0x7BC3, 0xB9A0, 0x7BC4, 0xB9A1, 0x57C2, 0xB9A2, 0x803F, 0xB9A3, 0x6897, 0xB9A4, 0x5DE5, 0xB9A5, 0x653B, + 0xB9A6, 0x529F, 0xB9A7, 0x606D, 0xB9A8, 0x9F9A, 0xB9A9, 0x4F9B, 0xB9AA, 0x8EAC, 0xB9AB, 0x516C, 0xB9AC, 0x5BAB, 0xB9AD, 0x5F13, + 0xB9AE, 0x5DE9, 0xB9AF, 0x6C5E, 0xB9B0, 0x62F1, 0xB9B1, 0x8D21, 0xB9B2, 0x5171, 0xB9B3, 0x94A9, 0xB9B4, 0x52FE, 0xB9B5, 0x6C9F, + 0xB9B6, 0x82DF, 0xB9B7, 0x72D7, 0xB9B8, 0x57A2, 0xB9B9, 0x6784, 0xB9BA, 0x8D2D, 0xB9BB, 0x591F, 0xB9BC, 0x8F9C, 0xB9BD, 0x83C7, + 0xB9BE, 0x5495, 0xB9BF, 0x7B8D, 0xB9C0, 0x4F30, 0xB9C1, 0x6CBD, 0xB9C2, 0x5B64, 0xB9C3, 0x59D1, 0xB9C4, 0x9F13, 0xB9C5, 0x53E4, + 0xB9C6, 0x86CA, 0xB9C7, 0x9AA8, 0xB9C8, 0x8C37, 0xB9C9, 0x80A1, 0xB9CA, 0x6545, 0xB9CB, 0x987E, 0xB9CC, 0x56FA, 0xB9CD, 0x96C7, + 0xB9CE, 0x522E, 0xB9CF, 0x74DC, 0xB9D0, 0x5250, 0xB9D1, 0x5BE1, 0xB9D2, 0x6302, 0xB9D3, 0x8902, 0xB9D4, 0x4E56, 0xB9D5, 0x62D0, + 0xB9D6, 0x602A, 0xB9D7, 0x68FA, 0xB9D8, 0x5173, 0xB9D9, 0x5B98, 0xB9DA, 0x51A0, 0xB9DB, 0x89C2, 0xB9DC, 0x7BA1, 0xB9DD, 0x9986, + 0xB9DE, 0x7F50, 0xB9DF, 0x60EF, 0xB9E0, 0x704C, 0xB9E1, 0x8D2F, 0xB9E2, 0x5149, 0xB9E3, 0x5E7F, 0xB9E4, 0x901B, 0xB9E5, 0x7470, + 0xB9E6, 0x89C4, 0xB9E7, 0x572D, 0xB9E8, 0x7845, 0xB9E9, 0x5F52, 0xB9EA, 0x9F9F, 0xB9EB, 0x95FA, 0xB9EC, 0x8F68, 0xB9ED, 0x9B3C, + 0xB9EE, 0x8BE1, 0xB9EF, 0x7678, 0xB9F0, 0x6842, 0xB9F1, 0x67DC, 0xB9F2, 0x8DEA, 0xB9F3, 0x8D35, 0xB9F4, 0x523D, 0xB9F5, 0x8F8A, + 0xB9F6, 0x6EDA, 0xB9F7, 0x68CD, 0xB9F8, 0x9505, 0xB9F9, 0x90ED, 0xB9FA, 0x56FD, 0xB9FB, 0x679C, 0xB9FC, 0x88F9, 0xB9FD, 0x8FC7, + 0xB9FE, 0x54C8, 0xBA40, 0x7BC5, 0xBA41, 0x7BC8, 0xBA42, 0x7BC9, 0xBA43, 0x7BCA, 0xBA44, 0x7BCB, 0xBA45, 0x7BCD, 0xBA46, 0x7BCE, + 0xBA47, 0x7BCF, 0xBA48, 0x7BD0, 0xBA49, 0x7BD2, 0xBA4A, 0x7BD4, 0xBA4B, 0x7BD5, 0xBA4C, 0x7BD6, 0xBA4D, 0x7BD7, 0xBA4E, 0x7BD8, + 0xBA4F, 0x7BDB, 0xBA50, 0x7BDC, 0xBA51, 0x7BDE, 0xBA52, 0x7BDF, 0xBA53, 0x7BE0, 0xBA54, 0x7BE2, 0xBA55, 0x7BE3, 0xBA56, 0x7BE4, + 0xBA57, 0x7BE7, 0xBA58, 0x7BE8, 0xBA59, 0x7BE9, 0xBA5A, 0x7BEB, 0xBA5B, 0x7BEC, 0xBA5C, 0x7BED, 0xBA5D, 0x7BEF, 0xBA5E, 0x7BF0, + 0xBA5F, 0x7BF2, 0xBA60, 0x7BF3, 0xBA61, 0x7BF4, 0xBA62, 0x7BF5, 0xBA63, 0x7BF6, 0xBA64, 0x7BF8, 0xBA65, 0x7BF9, 0xBA66, 0x7BFA, + 0xBA67, 0x7BFB, 0xBA68, 0x7BFD, 0xBA69, 0x7BFF, 0xBA6A, 0x7C00, 0xBA6B, 0x7C01, 0xBA6C, 0x7C02, 0xBA6D, 0x7C03, 0xBA6E, 0x7C04, + 0xBA6F, 0x7C05, 0xBA70, 0x7C06, 0xBA71, 0x7C08, 0xBA72, 0x7C09, 0xBA73, 0x7C0A, 0xBA74, 0x7C0D, 0xBA75, 0x7C0E, 0xBA76, 0x7C10, + 0xBA77, 0x7C11, 0xBA78, 0x7C12, 0xBA79, 0x7C13, 0xBA7A, 0x7C14, 0xBA7B, 0x7C15, 0xBA7C, 0x7C17, 0xBA7D, 0x7C18, 0xBA7E, 0x7C19, + 0xBA80, 0x7C1A, 0xBA81, 0x7C1B, 0xBA82, 0x7C1C, 0xBA83, 0x7C1D, 0xBA84, 0x7C1E, 0xBA85, 0x7C20, 0xBA86, 0x7C21, 0xBA87, 0x7C22, + 0xBA88, 0x7C23, 0xBA89, 0x7C24, 0xBA8A, 0x7C25, 0xBA8B, 0x7C28, 0xBA8C, 0x7C29, 0xBA8D, 0x7C2B, 0xBA8E, 0x7C2C, 0xBA8F, 0x7C2D, + 0xBA90, 0x7C2E, 0xBA91, 0x7C2F, 0xBA92, 0x7C30, 0xBA93, 0x7C31, 0xBA94, 0x7C32, 0xBA95, 0x7C33, 0xBA96, 0x7C34, 0xBA97, 0x7C35, + 0xBA98, 0x7C36, 0xBA99, 0x7C37, 0xBA9A, 0x7C39, 0xBA9B, 0x7C3A, 0xBA9C, 0x7C3B, 0xBA9D, 0x7C3C, 0xBA9E, 0x7C3D, 0xBA9F, 0x7C3E, + 0xBAA0, 0x7C42, 0xBAA1, 0x9AB8, 0xBAA2, 0x5B69, 0xBAA3, 0x6D77, 0xBAA4, 0x6C26, 0xBAA5, 0x4EA5, 0xBAA6, 0x5BB3, 0xBAA7, 0x9A87, + 0xBAA8, 0x9163, 0xBAA9, 0x61A8, 0xBAAA, 0x90AF, 0xBAAB, 0x97E9, 0xBAAC, 0x542B, 0xBAAD, 0x6DB5, 0xBAAE, 0x5BD2, 0xBAAF, 0x51FD, + 0xBAB0, 0x558A, 0xBAB1, 0x7F55, 0xBAB2, 0x7FF0, 0xBAB3, 0x64BC, 0xBAB4, 0x634D, 0xBAB5, 0x65F1, 0xBAB6, 0x61BE, 0xBAB7, 0x608D, + 0xBAB8, 0x710A, 0xBAB9, 0x6C57, 0xBABA, 0x6C49, 0xBABB, 0x592F, 0xBABC, 0x676D, 0xBABD, 0x822A, 0xBABE, 0x58D5, 0xBABF, 0x568E, + 0xBAC0, 0x8C6A, 0xBAC1, 0x6BEB, 0xBAC2, 0x90DD, 0xBAC3, 0x597D, 0xBAC4, 0x8017, 0xBAC5, 0x53F7, 0xBAC6, 0x6D69, 0xBAC7, 0x5475, + 0xBAC8, 0x559D, 0xBAC9, 0x8377, 0xBACA, 0x83CF, 0xBACB, 0x6838, 0xBACC, 0x79BE, 0xBACD, 0x548C, 0xBACE, 0x4F55, 0xBACF, 0x5408, + 0xBAD0, 0x76D2, 0xBAD1, 0x8C89, 0xBAD2, 0x9602, 0xBAD3, 0x6CB3, 0xBAD4, 0x6DB8, 0xBAD5, 0x8D6B, 0xBAD6, 0x8910, 0xBAD7, 0x9E64, + 0xBAD8, 0x8D3A, 0xBAD9, 0x563F, 0xBADA, 0x9ED1, 0xBADB, 0x75D5, 0xBADC, 0x5F88, 0xBADD, 0x72E0, 0xBADE, 0x6068, 0xBADF, 0x54FC, + 0xBAE0, 0x4EA8, 0xBAE1, 0x6A2A, 0xBAE2, 0x8861, 0xBAE3, 0x6052, 0xBAE4, 0x8F70, 0xBAE5, 0x54C4, 0xBAE6, 0x70D8, 0xBAE7, 0x8679, + 0xBAE8, 0x9E3F, 0xBAE9, 0x6D2A, 0xBAEA, 0x5B8F, 0xBAEB, 0x5F18, 0xBAEC, 0x7EA2, 0xBAED, 0x5589, 0xBAEE, 0x4FAF, 0xBAEF, 0x7334, + 0xBAF0, 0x543C, 0xBAF1, 0x539A, 0xBAF2, 0x5019, 0xBAF3, 0x540E, 0xBAF4, 0x547C, 0xBAF5, 0x4E4E, 0xBAF6, 0x5FFD, 0xBAF7, 0x745A, + 0xBAF8, 0x58F6, 0xBAF9, 0x846B, 0xBAFA, 0x80E1, 0xBAFB, 0x8774, 0xBAFC, 0x72D0, 0xBAFD, 0x7CCA, 0xBAFE, 0x6E56, 0xBB40, 0x7C43, + 0xBB41, 0x7C44, 0xBB42, 0x7C45, 0xBB43, 0x7C46, 0xBB44, 0x7C47, 0xBB45, 0x7C48, 0xBB46, 0x7C49, 0xBB47, 0x7C4A, 0xBB48, 0x7C4B, + 0xBB49, 0x7C4C, 0xBB4A, 0x7C4E, 0xBB4B, 0x7C4F, 0xBB4C, 0x7C50, 0xBB4D, 0x7C51, 0xBB4E, 0x7C52, 0xBB4F, 0x7C53, 0xBB50, 0x7C54, + 0xBB51, 0x7C55, 0xBB52, 0x7C56, 0xBB53, 0x7C57, 0xBB54, 0x7C58, 0xBB55, 0x7C59, 0xBB56, 0x7C5A, 0xBB57, 0x7C5B, 0xBB58, 0x7C5C, + 0xBB59, 0x7C5D, 0xBB5A, 0x7C5E, 0xBB5B, 0x7C5F, 0xBB5C, 0x7C60, 0xBB5D, 0x7C61, 0xBB5E, 0x7C62, 0xBB5F, 0x7C63, 0xBB60, 0x7C64, + 0xBB61, 0x7C65, 0xBB62, 0x7C66, 0xBB63, 0x7C67, 0xBB64, 0x7C68, 0xBB65, 0x7C69, 0xBB66, 0x7C6A, 0xBB67, 0x7C6B, 0xBB68, 0x7C6C, + 0xBB69, 0x7C6D, 0xBB6A, 0x7C6E, 0xBB6B, 0x7C6F, 0xBB6C, 0x7C70, 0xBB6D, 0x7C71, 0xBB6E, 0x7C72, 0xBB6F, 0x7C75, 0xBB70, 0x7C76, + 0xBB71, 0x7C77, 0xBB72, 0x7C78, 0xBB73, 0x7C79, 0xBB74, 0x7C7A, 0xBB75, 0x7C7E, 0xBB76, 0x7C7F, 0xBB77, 0x7C80, 0xBB78, 0x7C81, + 0xBB79, 0x7C82, 0xBB7A, 0x7C83, 0xBB7B, 0x7C84, 0xBB7C, 0x7C85, 0xBB7D, 0x7C86, 0xBB7E, 0x7C87, 0xBB80, 0x7C88, 0xBB81, 0x7C8A, + 0xBB82, 0x7C8B, 0xBB83, 0x7C8C, 0xBB84, 0x7C8D, 0xBB85, 0x7C8E, 0xBB86, 0x7C8F, 0xBB87, 0x7C90, 0xBB88, 0x7C93, 0xBB89, 0x7C94, + 0xBB8A, 0x7C96, 0xBB8B, 0x7C99, 0xBB8C, 0x7C9A, 0xBB8D, 0x7C9B, 0xBB8E, 0x7CA0, 0xBB8F, 0x7CA1, 0xBB90, 0x7CA3, 0xBB91, 0x7CA6, + 0xBB92, 0x7CA7, 0xBB93, 0x7CA8, 0xBB94, 0x7CA9, 0xBB95, 0x7CAB, 0xBB96, 0x7CAC, 0xBB97, 0x7CAD, 0xBB98, 0x7CAF, 0xBB99, 0x7CB0, + 0xBB9A, 0x7CB4, 0xBB9B, 0x7CB5, 0xBB9C, 0x7CB6, 0xBB9D, 0x7CB7, 0xBB9E, 0x7CB8, 0xBB9F, 0x7CBA, 0xBBA0, 0x7CBB, 0xBBA1, 0x5F27, + 0xBBA2, 0x864E, 0xBBA3, 0x552C, 0xBBA4, 0x62A4, 0xBBA5, 0x4E92, 0xBBA6, 0x6CAA, 0xBBA7, 0x6237, 0xBBA8, 0x82B1, 0xBBA9, 0x54D7, + 0xBBAA, 0x534E, 0xBBAB, 0x733E, 0xBBAC, 0x6ED1, 0xBBAD, 0x753B, 0xBBAE, 0x5212, 0xBBAF, 0x5316, 0xBBB0, 0x8BDD, 0xBBB1, 0x69D0, + 0xBBB2, 0x5F8A, 0xBBB3, 0x6000, 0xBBB4, 0x6DEE, 0xBBB5, 0x574F, 0xBBB6, 0x6B22, 0xBBB7, 0x73AF, 0xBBB8, 0x6853, 0xBBB9, 0x8FD8, + 0xBBBA, 0x7F13, 0xBBBB, 0x6362, 0xBBBC, 0x60A3, 0xBBBD, 0x5524, 0xBBBE, 0x75EA, 0xBBBF, 0x8C62, 0xBBC0, 0x7115, 0xBBC1, 0x6DA3, + 0xBBC2, 0x5BA6, 0xBBC3, 0x5E7B, 0xBBC4, 0x8352, 0xBBC5, 0x614C, 0xBBC6, 0x9EC4, 0xBBC7, 0x78FA, 0xBBC8, 0x8757, 0xBBC9, 0x7C27, + 0xBBCA, 0x7687, 0xBBCB, 0x51F0, 0xBBCC, 0x60F6, 0xBBCD, 0x714C, 0xBBCE, 0x6643, 0xBBCF, 0x5E4C, 0xBBD0, 0x604D, 0xBBD1, 0x8C0E, + 0xBBD2, 0x7070, 0xBBD3, 0x6325, 0xBBD4, 0x8F89, 0xBBD5, 0x5FBD, 0xBBD6, 0x6062, 0xBBD7, 0x86D4, 0xBBD8, 0x56DE, 0xBBD9, 0x6BC1, + 0xBBDA, 0x6094, 0xBBDB, 0x6167, 0xBBDC, 0x5349, 0xBBDD, 0x60E0, 0xBBDE, 0x6666, 0xBBDF, 0x8D3F, 0xBBE0, 0x79FD, 0xBBE1, 0x4F1A, + 0xBBE2, 0x70E9, 0xBBE3, 0x6C47, 0xBBE4, 0x8BB3, 0xBBE5, 0x8BF2, 0xBBE6, 0x7ED8, 0xBBE7, 0x8364, 0xBBE8, 0x660F, 0xBBE9, 0x5A5A, + 0xBBEA, 0x9B42, 0xBBEB, 0x6D51, 0xBBEC, 0x6DF7, 0xBBED, 0x8C41, 0xBBEE, 0x6D3B, 0xBBEF, 0x4F19, 0xBBF0, 0x706B, 0xBBF1, 0x83B7, + 0xBBF2, 0x6216, 0xBBF3, 0x60D1, 0xBBF4, 0x970D, 0xBBF5, 0x8D27, 0xBBF6, 0x7978, 0xBBF7, 0x51FB, 0xBBF8, 0x573E, 0xBBF9, 0x57FA, + 0xBBFA, 0x673A, 0xBBFB, 0x7578, 0xBBFC, 0x7A3D, 0xBBFD, 0x79EF, 0xBBFE, 0x7B95, 0xBC40, 0x7CBF, 0xBC41, 0x7CC0, 0xBC42, 0x7CC2, + 0xBC43, 0x7CC3, 0xBC44, 0x7CC4, 0xBC45, 0x7CC6, 0xBC46, 0x7CC9, 0xBC47, 0x7CCB, 0xBC48, 0x7CCE, 0xBC49, 0x7CCF, 0xBC4A, 0x7CD0, + 0xBC4B, 0x7CD1, 0xBC4C, 0x7CD2, 0xBC4D, 0x7CD3, 0xBC4E, 0x7CD4, 0xBC4F, 0x7CD8, 0xBC50, 0x7CDA, 0xBC51, 0x7CDB, 0xBC52, 0x7CDD, + 0xBC53, 0x7CDE, 0xBC54, 0x7CE1, 0xBC55, 0x7CE2, 0xBC56, 0x7CE3, 0xBC57, 0x7CE4, 0xBC58, 0x7CE5, 0xBC59, 0x7CE6, 0xBC5A, 0x7CE7, + 0xBC5B, 0x7CE9, 0xBC5C, 0x7CEA, 0xBC5D, 0x7CEB, 0xBC5E, 0x7CEC, 0xBC5F, 0x7CED, 0xBC60, 0x7CEE, 0xBC61, 0x7CF0, 0xBC62, 0x7CF1, + 0xBC63, 0x7CF2, 0xBC64, 0x7CF3, 0xBC65, 0x7CF4, 0xBC66, 0x7CF5, 0xBC67, 0x7CF6, 0xBC68, 0x7CF7, 0xBC69, 0x7CF9, 0xBC6A, 0x7CFA, + 0xBC6B, 0x7CFC, 0xBC6C, 0x7CFD, 0xBC6D, 0x7CFE, 0xBC6E, 0x7CFF, 0xBC6F, 0x7D00, 0xBC70, 0x7D01, 0xBC71, 0x7D02, 0xBC72, 0x7D03, + 0xBC73, 0x7D04, 0xBC74, 0x7D05, 0xBC75, 0x7D06, 0xBC76, 0x7D07, 0xBC77, 0x7D08, 0xBC78, 0x7D09, 0xBC79, 0x7D0B, 0xBC7A, 0x7D0C, + 0xBC7B, 0x7D0D, 0xBC7C, 0x7D0E, 0xBC7D, 0x7D0F, 0xBC7E, 0x7D10, 0xBC80, 0x7D11, 0xBC81, 0x7D12, 0xBC82, 0x7D13, 0xBC83, 0x7D14, + 0xBC84, 0x7D15, 0xBC85, 0x7D16, 0xBC86, 0x7D17, 0xBC87, 0x7D18, 0xBC88, 0x7D19, 0xBC89, 0x7D1A, 0xBC8A, 0x7D1B, 0xBC8B, 0x7D1C, + 0xBC8C, 0x7D1D, 0xBC8D, 0x7D1E, 0xBC8E, 0x7D1F, 0xBC8F, 0x7D21, 0xBC90, 0x7D23, 0xBC91, 0x7D24, 0xBC92, 0x7D25, 0xBC93, 0x7D26, + 0xBC94, 0x7D28, 0xBC95, 0x7D29, 0xBC96, 0x7D2A, 0xBC97, 0x7D2C, 0xBC98, 0x7D2D, 0xBC99, 0x7D2E, 0xBC9A, 0x7D30, 0xBC9B, 0x7D31, + 0xBC9C, 0x7D32, 0xBC9D, 0x7D33, 0xBC9E, 0x7D34, 0xBC9F, 0x7D35, 0xBCA0, 0x7D36, 0xBCA1, 0x808C, 0xBCA2, 0x9965, 0xBCA3, 0x8FF9, + 0xBCA4, 0x6FC0, 0xBCA5, 0x8BA5, 0xBCA6, 0x9E21, 0xBCA7, 0x59EC, 0xBCA8, 0x7EE9, 0xBCA9, 0x7F09, 0xBCAA, 0x5409, 0xBCAB, 0x6781, + 0xBCAC, 0x68D8, 0xBCAD, 0x8F91, 0xBCAE, 0x7C4D, 0xBCAF, 0x96C6, 0xBCB0, 0x53CA, 0xBCB1, 0x6025, 0xBCB2, 0x75BE, 0xBCB3, 0x6C72, + 0xBCB4, 0x5373, 0xBCB5, 0x5AC9, 0xBCB6, 0x7EA7, 0xBCB7, 0x6324, 0xBCB8, 0x51E0, 0xBCB9, 0x810A, 0xBCBA, 0x5DF1, 0xBCBB, 0x84DF, + 0xBCBC, 0x6280, 0xBCBD, 0x5180, 0xBCBE, 0x5B63, 0xBCBF, 0x4F0E, 0xBCC0, 0x796D, 0xBCC1, 0x5242, 0xBCC2, 0x60B8, 0xBCC3, 0x6D4E, + 0xBCC4, 0x5BC4, 0xBCC5, 0x5BC2, 0xBCC6, 0x8BA1, 0xBCC7, 0x8BB0, 0xBCC8, 0x65E2, 0xBCC9, 0x5FCC, 0xBCCA, 0x9645, 0xBCCB, 0x5993, + 0xBCCC, 0x7EE7, 0xBCCD, 0x7EAA, 0xBCCE, 0x5609, 0xBCCF, 0x67B7, 0xBCD0, 0x5939, 0xBCD1, 0x4F73, 0xBCD2, 0x5BB6, 0xBCD3, 0x52A0, + 0xBCD4, 0x835A, 0xBCD5, 0x988A, 0xBCD6, 0x8D3E, 0xBCD7, 0x7532, 0xBCD8, 0x94BE, 0xBCD9, 0x5047, 0xBCDA, 0x7A3C, 0xBCDB, 0x4EF7, + 0xBCDC, 0x67B6, 0xBCDD, 0x9A7E, 0xBCDE, 0x5AC1, 0xBCDF, 0x6B7C, 0xBCE0, 0x76D1, 0xBCE1, 0x575A, 0xBCE2, 0x5C16, 0xBCE3, 0x7B3A, + 0xBCE4, 0x95F4, 0xBCE5, 0x714E, 0xBCE6, 0x517C, 0xBCE7, 0x80A9, 0xBCE8, 0x8270, 0xBCE9, 0x5978, 0xBCEA, 0x7F04, 0xBCEB, 0x8327, + 0xBCEC, 0x68C0, 0xBCED, 0x67EC, 0xBCEE, 0x78B1, 0xBCEF, 0x7877, 0xBCF0, 0x62E3, 0xBCF1, 0x6361, 0xBCF2, 0x7B80, 0xBCF3, 0x4FED, + 0xBCF4, 0x526A, 0xBCF5, 0x51CF, 0xBCF6, 0x8350, 0xBCF7, 0x69DB, 0xBCF8, 0x9274, 0xBCF9, 0x8DF5, 0xBCFA, 0x8D31, 0xBCFB, 0x89C1, + 0xBCFC, 0x952E, 0xBCFD, 0x7BAD, 0xBCFE, 0x4EF6, 0xBD40, 0x7D37, 0xBD41, 0x7D38, 0xBD42, 0x7D39, 0xBD43, 0x7D3A, 0xBD44, 0x7D3B, + 0xBD45, 0x7D3C, 0xBD46, 0x7D3D, 0xBD47, 0x7D3E, 0xBD48, 0x7D3F, 0xBD49, 0x7D40, 0xBD4A, 0x7D41, 0xBD4B, 0x7D42, 0xBD4C, 0x7D43, + 0xBD4D, 0x7D44, 0xBD4E, 0x7D45, 0xBD4F, 0x7D46, 0xBD50, 0x7D47, 0xBD51, 0x7D48, 0xBD52, 0x7D49, 0xBD53, 0x7D4A, 0xBD54, 0x7D4B, + 0xBD55, 0x7D4C, 0xBD56, 0x7D4D, 0xBD57, 0x7D4E, 0xBD58, 0x7D4F, 0xBD59, 0x7D50, 0xBD5A, 0x7D51, 0xBD5B, 0x7D52, 0xBD5C, 0x7D53, + 0xBD5D, 0x7D54, 0xBD5E, 0x7D55, 0xBD5F, 0x7D56, 0xBD60, 0x7D57, 0xBD61, 0x7D58, 0xBD62, 0x7D59, 0xBD63, 0x7D5A, 0xBD64, 0x7D5B, + 0xBD65, 0x7D5C, 0xBD66, 0x7D5D, 0xBD67, 0x7D5E, 0xBD68, 0x7D5F, 0xBD69, 0x7D60, 0xBD6A, 0x7D61, 0xBD6B, 0x7D62, 0xBD6C, 0x7D63, + 0xBD6D, 0x7D64, 0xBD6E, 0x7D65, 0xBD6F, 0x7D66, 0xBD70, 0x7D67, 0xBD71, 0x7D68, 0xBD72, 0x7D69, 0xBD73, 0x7D6A, 0xBD74, 0x7D6B, + 0xBD75, 0x7D6C, 0xBD76, 0x7D6D, 0xBD77, 0x7D6F, 0xBD78, 0x7D70, 0xBD79, 0x7D71, 0xBD7A, 0x7D72, 0xBD7B, 0x7D73, 0xBD7C, 0x7D74, + 0xBD7D, 0x7D75, 0xBD7E, 0x7D76, 0xBD80, 0x7D78, 0xBD81, 0x7D79, 0xBD82, 0x7D7A, 0xBD83, 0x7D7B, 0xBD84, 0x7D7C, 0xBD85, 0x7D7D, + 0xBD86, 0x7D7E, 0xBD87, 0x7D7F, 0xBD88, 0x7D80, 0xBD89, 0x7D81, 0xBD8A, 0x7D82, 0xBD8B, 0x7D83, 0xBD8C, 0x7D84, 0xBD8D, 0x7D85, + 0xBD8E, 0x7D86, 0xBD8F, 0x7D87, 0xBD90, 0x7D88, 0xBD91, 0x7D89, 0xBD92, 0x7D8A, 0xBD93, 0x7D8B, 0xBD94, 0x7D8C, 0xBD95, 0x7D8D, + 0xBD96, 0x7D8E, 0xBD97, 0x7D8F, 0xBD98, 0x7D90, 0xBD99, 0x7D91, 0xBD9A, 0x7D92, 0xBD9B, 0x7D93, 0xBD9C, 0x7D94, 0xBD9D, 0x7D95, + 0xBD9E, 0x7D96, 0xBD9F, 0x7D97, 0xBDA0, 0x7D98, 0xBDA1, 0x5065, 0xBDA2, 0x8230, 0xBDA3, 0x5251, 0xBDA4, 0x996F, 0xBDA5, 0x6E10, + 0xBDA6, 0x6E85, 0xBDA7, 0x6DA7, 0xBDA8, 0x5EFA, 0xBDA9, 0x50F5, 0xBDAA, 0x59DC, 0xBDAB, 0x5C06, 0xBDAC, 0x6D46, 0xBDAD, 0x6C5F, + 0xBDAE, 0x7586, 0xBDAF, 0x848B, 0xBDB0, 0x6868, 0xBDB1, 0x5956, 0xBDB2, 0x8BB2, 0xBDB3, 0x5320, 0xBDB4, 0x9171, 0xBDB5, 0x964D, + 0xBDB6, 0x8549, 0xBDB7, 0x6912, 0xBDB8, 0x7901, 0xBDB9, 0x7126, 0xBDBA, 0x80F6, 0xBDBB, 0x4EA4, 0xBDBC, 0x90CA, 0xBDBD, 0x6D47, + 0xBDBE, 0x9A84, 0xBDBF, 0x5A07, 0xBDC0, 0x56BC, 0xBDC1, 0x6405, 0xBDC2, 0x94F0, 0xBDC3, 0x77EB, 0xBDC4, 0x4FA5, 0xBDC5, 0x811A, + 0xBDC6, 0x72E1, 0xBDC7, 0x89D2, 0xBDC8, 0x997A, 0xBDC9, 0x7F34, 0xBDCA, 0x7EDE, 0xBDCB, 0x527F, 0xBDCC, 0x6559, 0xBDCD, 0x9175, + 0xBDCE, 0x8F7F, 0xBDCF, 0x8F83, 0xBDD0, 0x53EB, 0xBDD1, 0x7A96, 0xBDD2, 0x63ED, 0xBDD3, 0x63A5, 0xBDD4, 0x7686, 0xBDD5, 0x79F8, + 0xBDD6, 0x8857, 0xBDD7, 0x9636, 0xBDD8, 0x622A, 0xBDD9, 0x52AB, 0xBDDA, 0x8282, 0xBDDB, 0x6854, 0xBDDC, 0x6770, 0xBDDD, 0x6377, + 0xBDDE, 0x776B, 0xBDDF, 0x7AED, 0xBDE0, 0x6D01, 0xBDE1, 0x7ED3, 0xBDE2, 0x89E3, 0xBDE3, 0x59D0, 0xBDE4, 0x6212, 0xBDE5, 0x85C9, + 0xBDE6, 0x82A5, 0xBDE7, 0x754C, 0xBDE8, 0x501F, 0xBDE9, 0x4ECB, 0xBDEA, 0x75A5, 0xBDEB, 0x8BEB, 0xBDEC, 0x5C4A, 0xBDED, 0x5DFE, + 0xBDEE, 0x7B4B, 0xBDEF, 0x65A4, 0xBDF0, 0x91D1, 0xBDF1, 0x4ECA, 0xBDF2, 0x6D25, 0xBDF3, 0x895F, 0xBDF4, 0x7D27, 0xBDF5, 0x9526, + 0xBDF6, 0x4EC5, 0xBDF7, 0x8C28, 0xBDF8, 0x8FDB, 0xBDF9, 0x9773, 0xBDFA, 0x664B, 0xBDFB, 0x7981, 0xBDFC, 0x8FD1, 0xBDFD, 0x70EC, + 0xBDFE, 0x6D78, 0xBE40, 0x7D99, 0xBE41, 0x7D9A, 0xBE42, 0x7D9B, 0xBE43, 0x7D9C, 0xBE44, 0x7D9D, 0xBE45, 0x7D9E, 0xBE46, 0x7D9F, + 0xBE47, 0x7DA0, 0xBE48, 0x7DA1, 0xBE49, 0x7DA2, 0xBE4A, 0x7DA3, 0xBE4B, 0x7DA4, 0xBE4C, 0x7DA5, 0xBE4D, 0x7DA7, 0xBE4E, 0x7DA8, + 0xBE4F, 0x7DA9, 0xBE50, 0x7DAA, 0xBE51, 0x7DAB, 0xBE52, 0x7DAC, 0xBE53, 0x7DAD, 0xBE54, 0x7DAF, 0xBE55, 0x7DB0, 0xBE56, 0x7DB1, + 0xBE57, 0x7DB2, 0xBE58, 0x7DB3, 0xBE59, 0x7DB4, 0xBE5A, 0x7DB5, 0xBE5B, 0x7DB6, 0xBE5C, 0x7DB7, 0xBE5D, 0x7DB8, 0xBE5E, 0x7DB9, + 0xBE5F, 0x7DBA, 0xBE60, 0x7DBB, 0xBE61, 0x7DBC, 0xBE62, 0x7DBD, 0xBE63, 0x7DBE, 0xBE64, 0x7DBF, 0xBE65, 0x7DC0, 0xBE66, 0x7DC1, + 0xBE67, 0x7DC2, 0xBE68, 0x7DC3, 0xBE69, 0x7DC4, 0xBE6A, 0x7DC5, 0xBE6B, 0x7DC6, 0xBE6C, 0x7DC7, 0xBE6D, 0x7DC8, 0xBE6E, 0x7DC9, + 0xBE6F, 0x7DCA, 0xBE70, 0x7DCB, 0xBE71, 0x7DCC, 0xBE72, 0x7DCD, 0xBE73, 0x7DCE, 0xBE74, 0x7DCF, 0xBE75, 0x7DD0, 0xBE76, 0x7DD1, + 0xBE77, 0x7DD2, 0xBE78, 0x7DD3, 0xBE79, 0x7DD4, 0xBE7A, 0x7DD5, 0xBE7B, 0x7DD6, 0xBE7C, 0x7DD7, 0xBE7D, 0x7DD8, 0xBE7E, 0x7DD9, + 0xBE80, 0x7DDA, 0xBE81, 0x7DDB, 0xBE82, 0x7DDC, 0xBE83, 0x7DDD, 0xBE84, 0x7DDE, 0xBE85, 0x7DDF, 0xBE86, 0x7DE0, 0xBE87, 0x7DE1, + 0xBE88, 0x7DE2, 0xBE89, 0x7DE3, 0xBE8A, 0x7DE4, 0xBE8B, 0x7DE5, 0xBE8C, 0x7DE6, 0xBE8D, 0x7DE7, 0xBE8E, 0x7DE8, 0xBE8F, 0x7DE9, + 0xBE90, 0x7DEA, 0xBE91, 0x7DEB, 0xBE92, 0x7DEC, 0xBE93, 0x7DED, 0xBE94, 0x7DEE, 0xBE95, 0x7DEF, 0xBE96, 0x7DF0, 0xBE97, 0x7DF1, + 0xBE98, 0x7DF2, 0xBE99, 0x7DF3, 0xBE9A, 0x7DF4, 0xBE9B, 0x7DF5, 0xBE9C, 0x7DF6, 0xBE9D, 0x7DF7, 0xBE9E, 0x7DF8, 0xBE9F, 0x7DF9, + 0xBEA0, 0x7DFA, 0xBEA1, 0x5C3D, 0xBEA2, 0x52B2, 0xBEA3, 0x8346, 0xBEA4, 0x5162, 0xBEA5, 0x830E, 0xBEA6, 0x775B, 0xBEA7, 0x6676, + 0xBEA8, 0x9CB8, 0xBEA9, 0x4EAC, 0xBEAA, 0x60CA, 0xBEAB, 0x7CBE, 0xBEAC, 0x7CB3, 0xBEAD, 0x7ECF, 0xBEAE, 0x4E95, 0xBEAF, 0x8B66, + 0xBEB0, 0x666F, 0xBEB1, 0x9888, 0xBEB2, 0x9759, 0xBEB3, 0x5883, 0xBEB4, 0x656C, 0xBEB5, 0x955C, 0xBEB6, 0x5F84, 0xBEB7, 0x75C9, + 0xBEB8, 0x9756, 0xBEB9, 0x7ADF, 0xBEBA, 0x7ADE, 0xBEBB, 0x51C0, 0xBEBC, 0x70AF, 0xBEBD, 0x7A98, 0xBEBE, 0x63EA, 0xBEBF, 0x7A76, + 0xBEC0, 0x7EA0, 0xBEC1, 0x7396, 0xBEC2, 0x97ED, 0xBEC3, 0x4E45, 0xBEC4, 0x7078, 0xBEC5, 0x4E5D, 0xBEC6, 0x9152, 0xBEC7, 0x53A9, + 0xBEC8, 0x6551, 0xBEC9, 0x65E7, 0xBECA, 0x81FC, 0xBECB, 0x8205, 0xBECC, 0x548E, 0xBECD, 0x5C31, 0xBECE, 0x759A, 0xBECF, 0x97A0, + 0xBED0, 0x62D8, 0xBED1, 0x72D9, 0xBED2, 0x75BD, 0xBED3, 0x5C45, 0xBED4, 0x9A79, 0xBED5, 0x83CA, 0xBED6, 0x5C40, 0xBED7, 0x5480, + 0xBED8, 0x77E9, 0xBED9, 0x4E3E, 0xBEDA, 0x6CAE, 0xBEDB, 0x805A, 0xBEDC, 0x62D2, 0xBEDD, 0x636E, 0xBEDE, 0x5DE8, 0xBEDF, 0x5177, + 0xBEE0, 0x8DDD, 0xBEE1, 0x8E1E, 0xBEE2, 0x952F, 0xBEE3, 0x4FF1, 0xBEE4, 0x53E5, 0xBEE5, 0x60E7, 0xBEE6, 0x70AC, 0xBEE7, 0x5267, + 0xBEE8, 0x6350, 0xBEE9, 0x9E43, 0xBEEA, 0x5A1F, 0xBEEB, 0x5026, 0xBEEC, 0x7737, 0xBEED, 0x5377, 0xBEEE, 0x7EE2, 0xBEEF, 0x6485, + 0xBEF0, 0x652B, 0xBEF1, 0x6289, 0xBEF2, 0x6398, 0xBEF3, 0x5014, 0xBEF4, 0x7235, 0xBEF5, 0x89C9, 0xBEF6, 0x51B3, 0xBEF7, 0x8BC0, + 0xBEF8, 0x7EDD, 0xBEF9, 0x5747, 0xBEFA, 0x83CC, 0xBEFB, 0x94A7, 0xBEFC, 0x519B, 0xBEFD, 0x541B, 0xBEFE, 0x5CFB, 0xBF40, 0x7DFB, + 0xBF41, 0x7DFC, 0xBF42, 0x7DFD, 0xBF43, 0x7DFE, 0xBF44, 0x7DFF, 0xBF45, 0x7E00, 0xBF46, 0x7E01, 0xBF47, 0x7E02, 0xBF48, 0x7E03, + 0xBF49, 0x7E04, 0xBF4A, 0x7E05, 0xBF4B, 0x7E06, 0xBF4C, 0x7E07, 0xBF4D, 0x7E08, 0xBF4E, 0x7E09, 0xBF4F, 0x7E0A, 0xBF50, 0x7E0B, + 0xBF51, 0x7E0C, 0xBF52, 0x7E0D, 0xBF53, 0x7E0E, 0xBF54, 0x7E0F, 0xBF55, 0x7E10, 0xBF56, 0x7E11, 0xBF57, 0x7E12, 0xBF58, 0x7E13, + 0xBF59, 0x7E14, 0xBF5A, 0x7E15, 0xBF5B, 0x7E16, 0xBF5C, 0x7E17, 0xBF5D, 0x7E18, 0xBF5E, 0x7E19, 0xBF5F, 0x7E1A, 0xBF60, 0x7E1B, + 0xBF61, 0x7E1C, 0xBF62, 0x7E1D, 0xBF63, 0x7E1E, 0xBF64, 0x7E1F, 0xBF65, 0x7E20, 0xBF66, 0x7E21, 0xBF67, 0x7E22, 0xBF68, 0x7E23, + 0xBF69, 0x7E24, 0xBF6A, 0x7E25, 0xBF6B, 0x7E26, 0xBF6C, 0x7E27, 0xBF6D, 0x7E28, 0xBF6E, 0x7E29, 0xBF6F, 0x7E2A, 0xBF70, 0x7E2B, + 0xBF71, 0x7E2C, 0xBF72, 0x7E2D, 0xBF73, 0x7E2E, 0xBF74, 0x7E2F, 0xBF75, 0x7E30, 0xBF76, 0x7E31, 0xBF77, 0x7E32, 0xBF78, 0x7E33, + 0xBF79, 0x7E34, 0xBF7A, 0x7E35, 0xBF7B, 0x7E36, 0xBF7C, 0x7E37, 0xBF7D, 0x7E38, 0xBF7E, 0x7E39, 0xBF80, 0x7E3A, 0xBF81, 0x7E3C, + 0xBF82, 0x7E3D, 0xBF83, 0x7E3E, 0xBF84, 0x7E3F, 0xBF85, 0x7E40, 0xBF86, 0x7E42, 0xBF87, 0x7E43, 0xBF88, 0x7E44, 0xBF89, 0x7E45, + 0xBF8A, 0x7E46, 0xBF8B, 0x7E48, 0xBF8C, 0x7E49, 0xBF8D, 0x7E4A, 0xBF8E, 0x7E4B, 0xBF8F, 0x7E4C, 0xBF90, 0x7E4D, 0xBF91, 0x7E4E, + 0xBF92, 0x7E4F, 0xBF93, 0x7E50, 0xBF94, 0x7E51, 0xBF95, 0x7E52, 0xBF96, 0x7E53, 0xBF97, 0x7E54, 0xBF98, 0x7E55, 0xBF99, 0x7E56, + 0xBF9A, 0x7E57, 0xBF9B, 0x7E58, 0xBF9C, 0x7E59, 0xBF9D, 0x7E5A, 0xBF9E, 0x7E5B, 0xBF9F, 0x7E5C, 0xBFA0, 0x7E5D, 0xBFA1, 0x4FCA, + 0xBFA2, 0x7AE3, 0xBFA3, 0x6D5A, 0xBFA4, 0x90E1, 0xBFA5, 0x9A8F, 0xBFA6, 0x5580, 0xBFA7, 0x5496, 0xBFA8, 0x5361, 0xBFA9, 0x54AF, + 0xBFAA, 0x5F00, 0xBFAB, 0x63E9, 0xBFAC, 0x6977, 0xBFAD, 0x51EF, 0xBFAE, 0x6168, 0xBFAF, 0x520A, 0xBFB0, 0x582A, 0xBFB1, 0x52D8, + 0xBFB2, 0x574E, 0xBFB3, 0x780D, 0xBFB4, 0x770B, 0xBFB5, 0x5EB7, 0xBFB6, 0x6177, 0xBFB7, 0x7CE0, 0xBFB8, 0x625B, 0xBFB9, 0x6297, + 0xBFBA, 0x4EA2, 0xBFBB, 0x7095, 0xBFBC, 0x8003, 0xBFBD, 0x62F7, 0xBFBE, 0x70E4, 0xBFBF, 0x9760, 0xBFC0, 0x5777, 0xBFC1, 0x82DB, + 0xBFC2, 0x67EF, 0xBFC3, 0x68F5, 0xBFC4, 0x78D5, 0xBFC5, 0x9897, 0xBFC6, 0x79D1, 0xBFC7, 0x58F3, 0xBFC8, 0x54B3, 0xBFC9, 0x53EF, + 0xBFCA, 0x6E34, 0xBFCB, 0x514B, 0xBFCC, 0x523B, 0xBFCD, 0x5BA2, 0xBFCE, 0x8BFE, 0xBFCF, 0x80AF, 0xBFD0, 0x5543, 0xBFD1, 0x57A6, + 0xBFD2, 0x6073, 0xBFD3, 0x5751, 0xBFD4, 0x542D, 0xBFD5, 0x7A7A, 0xBFD6, 0x6050, 0xBFD7, 0x5B54, 0xBFD8, 0x63A7, 0xBFD9, 0x62A0, + 0xBFDA, 0x53E3, 0xBFDB, 0x6263, 0xBFDC, 0x5BC7, 0xBFDD, 0x67AF, 0xBFDE, 0x54ED, 0xBFDF, 0x7A9F, 0xBFE0, 0x82E6, 0xBFE1, 0x9177, + 0xBFE2, 0x5E93, 0xBFE3, 0x88E4, 0xBFE4, 0x5938, 0xBFE5, 0x57AE, 0xBFE6, 0x630E, 0xBFE7, 0x8DE8, 0xBFE8, 0x80EF, 0xBFE9, 0x5757, + 0xBFEA, 0x7B77, 0xBFEB, 0x4FA9, 0xBFEC, 0x5FEB, 0xBFED, 0x5BBD, 0xBFEE, 0x6B3E, 0xBFEF, 0x5321, 0xBFF0, 0x7B50, 0xBFF1, 0x72C2, + 0xBFF2, 0x6846, 0xBFF3, 0x77FF, 0xBFF4, 0x7736, 0xBFF5, 0x65F7, 0xBFF6, 0x51B5, 0xBFF7, 0x4E8F, 0xBFF8, 0x76D4, 0xBFF9, 0x5CBF, + 0xBFFA, 0x7AA5, 0xBFFB, 0x8475, 0xBFFC, 0x594E, 0xBFFD, 0x9B41, 0xBFFE, 0x5080, 0xC040, 0x7E5E, 0xC041, 0x7E5F, 0xC042, 0x7E60, + 0xC043, 0x7E61, 0xC044, 0x7E62, 0xC045, 0x7E63, 0xC046, 0x7E64, 0xC047, 0x7E65, 0xC048, 0x7E66, 0xC049, 0x7E67, 0xC04A, 0x7E68, + 0xC04B, 0x7E69, 0xC04C, 0x7E6A, 0xC04D, 0x7E6B, 0xC04E, 0x7E6C, 0xC04F, 0x7E6D, 0xC050, 0x7E6E, 0xC051, 0x7E6F, 0xC052, 0x7E70, + 0xC053, 0x7E71, 0xC054, 0x7E72, 0xC055, 0x7E73, 0xC056, 0x7E74, 0xC057, 0x7E75, 0xC058, 0x7E76, 0xC059, 0x7E77, 0xC05A, 0x7E78, + 0xC05B, 0x7E79, 0xC05C, 0x7E7A, 0xC05D, 0x7E7B, 0xC05E, 0x7E7C, 0xC05F, 0x7E7D, 0xC060, 0x7E7E, 0xC061, 0x7E7F, 0xC062, 0x7E80, + 0xC063, 0x7E81, 0xC064, 0x7E83, 0xC065, 0x7E84, 0xC066, 0x7E85, 0xC067, 0x7E86, 0xC068, 0x7E87, 0xC069, 0x7E88, 0xC06A, 0x7E89, + 0xC06B, 0x7E8A, 0xC06C, 0x7E8B, 0xC06D, 0x7E8C, 0xC06E, 0x7E8D, 0xC06F, 0x7E8E, 0xC070, 0x7E8F, 0xC071, 0x7E90, 0xC072, 0x7E91, + 0xC073, 0x7E92, 0xC074, 0x7E93, 0xC075, 0x7E94, 0xC076, 0x7E95, 0xC077, 0x7E96, 0xC078, 0x7E97, 0xC079, 0x7E98, 0xC07A, 0x7E99, + 0xC07B, 0x7E9A, 0xC07C, 0x7E9C, 0xC07D, 0x7E9D, 0xC07E, 0x7E9E, 0xC080, 0x7EAE, 0xC081, 0x7EB4, 0xC082, 0x7EBB, 0xC083, 0x7EBC, + 0xC084, 0x7ED6, 0xC085, 0x7EE4, 0xC086, 0x7EEC, 0xC087, 0x7EF9, 0xC088, 0x7F0A, 0xC089, 0x7F10, 0xC08A, 0x7F1E, 0xC08B, 0x7F37, + 0xC08C, 0x7F39, 0xC08D, 0x7F3B, 0xC08E, 0x7F3C, 0xC08F, 0x7F3D, 0xC090, 0x7F3E, 0xC091, 0x7F3F, 0xC092, 0x7F40, 0xC093, 0x7F41, + 0xC094, 0x7F43, 0xC095, 0x7F46, 0xC096, 0x7F47, 0xC097, 0x7F48, 0xC098, 0x7F49, 0xC099, 0x7F4A, 0xC09A, 0x7F4B, 0xC09B, 0x7F4C, + 0xC09C, 0x7F4D, 0xC09D, 0x7F4E, 0xC09E, 0x7F4F, 0xC09F, 0x7F52, 0xC0A0, 0x7F53, 0xC0A1, 0x9988, 0xC0A2, 0x6127, 0xC0A3, 0x6E83, + 0xC0A4, 0x5764, 0xC0A5, 0x6606, 0xC0A6, 0x6346, 0xC0A7, 0x56F0, 0xC0A8, 0x62EC, 0xC0A9, 0x6269, 0xC0AA, 0x5ED3, 0xC0AB, 0x9614, + 0xC0AC, 0x5783, 0xC0AD, 0x62C9, 0xC0AE, 0x5587, 0xC0AF, 0x8721, 0xC0B0, 0x814A, 0xC0B1, 0x8FA3, 0xC0B2, 0x5566, 0xC0B3, 0x83B1, + 0xC0B4, 0x6765, 0xC0B5, 0x8D56, 0xC0B6, 0x84DD, 0xC0B7, 0x5A6A, 0xC0B8, 0x680F, 0xC0B9, 0x62E6, 0xC0BA, 0x7BEE, 0xC0BB, 0x9611, + 0xC0BC, 0x5170, 0xC0BD, 0x6F9C, 0xC0BE, 0x8C30, 0xC0BF, 0x63FD, 0xC0C0, 0x89C8, 0xC0C1, 0x61D2, 0xC0C2, 0x7F06, 0xC0C3, 0x70C2, + 0xC0C4, 0x6EE5, 0xC0C5, 0x7405, 0xC0C6, 0x6994, 0xC0C7, 0x72FC, 0xC0C8, 0x5ECA, 0xC0C9, 0x90CE, 0xC0CA, 0x6717, 0xC0CB, 0x6D6A, + 0xC0CC, 0x635E, 0xC0CD, 0x52B3, 0xC0CE, 0x7262, 0xC0CF, 0x8001, 0xC0D0, 0x4F6C, 0xC0D1, 0x59E5, 0xC0D2, 0x916A, 0xC0D3, 0x70D9, + 0xC0D4, 0x6D9D, 0xC0D5, 0x52D2, 0xC0D6, 0x4E50, 0xC0D7, 0x96F7, 0xC0D8, 0x956D, 0xC0D9, 0x857E, 0xC0DA, 0x78CA, 0xC0DB, 0x7D2F, + 0xC0DC, 0x5121, 0xC0DD, 0x5792, 0xC0DE, 0x64C2, 0xC0DF, 0x808B, 0xC0E0, 0x7C7B, 0xC0E1, 0x6CEA, 0xC0E2, 0x68F1, 0xC0E3, 0x695E, + 0xC0E4, 0x51B7, 0xC0E5, 0x5398, 0xC0E6, 0x68A8, 0xC0E7, 0x7281, 0xC0E8, 0x9ECE, 0xC0E9, 0x7BF1, 0xC0EA, 0x72F8, 0xC0EB, 0x79BB, + 0xC0EC, 0x6F13, 0xC0ED, 0x7406, 0xC0EE, 0x674E, 0xC0EF, 0x91CC, 0xC0F0, 0x9CA4, 0xC0F1, 0x793C, 0xC0F2, 0x8389, 0xC0F3, 0x8354, + 0xC0F4, 0x540F, 0xC0F5, 0x6817, 0xC0F6, 0x4E3D, 0xC0F7, 0x5389, 0xC0F8, 0x52B1, 0xC0F9, 0x783E, 0xC0FA, 0x5386, 0xC0FB, 0x5229, + 0xC0FC, 0x5088, 0xC0FD, 0x4F8B, 0xC0FE, 0x4FD0, 0xC140, 0x7F56, 0xC141, 0x7F59, 0xC142, 0x7F5B, 0xC143, 0x7F5C, 0xC144, 0x7F5D, + 0xC145, 0x7F5E, 0xC146, 0x7F60, 0xC147, 0x7F63, 0xC148, 0x7F64, 0xC149, 0x7F65, 0xC14A, 0x7F66, 0xC14B, 0x7F67, 0xC14C, 0x7F6B, + 0xC14D, 0x7F6C, 0xC14E, 0x7F6D, 0xC14F, 0x7F6F, 0xC150, 0x7F70, 0xC151, 0x7F73, 0xC152, 0x7F75, 0xC153, 0x7F76, 0xC154, 0x7F77, + 0xC155, 0x7F78, 0xC156, 0x7F7A, 0xC157, 0x7F7B, 0xC158, 0x7F7C, 0xC159, 0x7F7D, 0xC15A, 0x7F7F, 0xC15B, 0x7F80, 0xC15C, 0x7F82, + 0xC15D, 0x7F83, 0xC15E, 0x7F84, 0xC15F, 0x7F85, 0xC160, 0x7F86, 0xC161, 0x7F87, 0xC162, 0x7F88, 0xC163, 0x7F89, 0xC164, 0x7F8B, + 0xC165, 0x7F8D, 0xC166, 0x7F8F, 0xC167, 0x7F90, 0xC168, 0x7F91, 0xC169, 0x7F92, 0xC16A, 0x7F93, 0xC16B, 0x7F95, 0xC16C, 0x7F96, + 0xC16D, 0x7F97, 0xC16E, 0x7F98, 0xC16F, 0x7F99, 0xC170, 0x7F9B, 0xC171, 0x7F9C, 0xC172, 0x7FA0, 0xC173, 0x7FA2, 0xC174, 0x7FA3, + 0xC175, 0x7FA5, 0xC176, 0x7FA6, 0xC177, 0x7FA8, 0xC178, 0x7FA9, 0xC179, 0x7FAA, 0xC17A, 0x7FAB, 0xC17B, 0x7FAC, 0xC17C, 0x7FAD, + 0xC17D, 0x7FAE, 0xC17E, 0x7FB1, 0xC180, 0x7FB3, 0xC181, 0x7FB4, 0xC182, 0x7FB5, 0xC183, 0x7FB6, 0xC184, 0x7FB7, 0xC185, 0x7FBA, + 0xC186, 0x7FBB, 0xC187, 0x7FBE, 0xC188, 0x7FC0, 0xC189, 0x7FC2, 0xC18A, 0x7FC3, 0xC18B, 0x7FC4, 0xC18C, 0x7FC6, 0xC18D, 0x7FC7, + 0xC18E, 0x7FC8, 0xC18F, 0x7FC9, 0xC190, 0x7FCB, 0xC191, 0x7FCD, 0xC192, 0x7FCF, 0xC193, 0x7FD0, 0xC194, 0x7FD1, 0xC195, 0x7FD2, + 0xC196, 0x7FD3, 0xC197, 0x7FD6, 0xC198, 0x7FD7, 0xC199, 0x7FD9, 0xC19A, 0x7FDA, 0xC19B, 0x7FDB, 0xC19C, 0x7FDC, 0xC19D, 0x7FDD, + 0xC19E, 0x7FDE, 0xC19F, 0x7FE2, 0xC1A0, 0x7FE3, 0xC1A1, 0x75E2, 0xC1A2, 0x7ACB, 0xC1A3, 0x7C92, 0xC1A4, 0x6CA5, 0xC1A5, 0x96B6, + 0xC1A6, 0x529B, 0xC1A7, 0x7483, 0xC1A8, 0x54E9, 0xC1A9, 0x4FE9, 0xC1AA, 0x8054, 0xC1AB, 0x83B2, 0xC1AC, 0x8FDE, 0xC1AD, 0x9570, + 0xC1AE, 0x5EC9, 0xC1AF, 0x601C, 0xC1B0, 0x6D9F, 0xC1B1, 0x5E18, 0xC1B2, 0x655B, 0xC1B3, 0x8138, 0xC1B4, 0x94FE, 0xC1B5, 0x604B, + 0xC1B6, 0x70BC, 0xC1B7, 0x7EC3, 0xC1B8, 0x7CAE, 0xC1B9, 0x51C9, 0xC1BA, 0x6881, 0xC1BB, 0x7CB1, 0xC1BC, 0x826F, 0xC1BD, 0x4E24, + 0xC1BE, 0x8F86, 0xC1BF, 0x91CF, 0xC1C0, 0x667E, 0xC1C1, 0x4EAE, 0xC1C2, 0x8C05, 0xC1C3, 0x64A9, 0xC1C4, 0x804A, 0xC1C5, 0x50DA, + 0xC1C6, 0x7597, 0xC1C7, 0x71CE, 0xC1C8, 0x5BE5, 0xC1C9, 0x8FBD, 0xC1CA, 0x6F66, 0xC1CB, 0x4E86, 0xC1CC, 0x6482, 0xC1CD, 0x9563, + 0xC1CE, 0x5ED6, 0xC1CF, 0x6599, 0xC1D0, 0x5217, 0xC1D1, 0x88C2, 0xC1D2, 0x70C8, 0xC1D3, 0x52A3, 0xC1D4, 0x730E, 0xC1D5, 0x7433, + 0xC1D6, 0x6797, 0xC1D7, 0x78F7, 0xC1D8, 0x9716, 0xC1D9, 0x4E34, 0xC1DA, 0x90BB, 0xC1DB, 0x9CDE, 0xC1DC, 0x6DCB, 0xC1DD, 0x51DB, + 0xC1DE, 0x8D41, 0xC1DF, 0x541D, 0xC1E0, 0x62CE, 0xC1E1, 0x73B2, 0xC1E2, 0x83F1, 0xC1E3, 0x96F6, 0xC1E4, 0x9F84, 0xC1E5, 0x94C3, + 0xC1E6, 0x4F36, 0xC1E7, 0x7F9A, 0xC1E8, 0x51CC, 0xC1E9, 0x7075, 0xC1EA, 0x9675, 0xC1EB, 0x5CAD, 0xC1EC, 0x9886, 0xC1ED, 0x53E6, + 0xC1EE, 0x4EE4, 0xC1EF, 0x6E9C, 0xC1F0, 0x7409, 0xC1F1, 0x69B4, 0xC1F2, 0x786B, 0xC1F3, 0x998F, 0xC1F4, 0x7559, 0xC1F5, 0x5218, + 0xC1F6, 0x7624, 0xC1F7, 0x6D41, 0xC1F8, 0x67F3, 0xC1F9, 0x516D, 0xC1FA, 0x9F99, 0xC1FB, 0x804B, 0xC1FC, 0x5499, 0xC1FD, 0x7B3C, + 0xC1FE, 0x7ABF, 0xC240, 0x7FE4, 0xC241, 0x7FE7, 0xC242, 0x7FE8, 0xC243, 0x7FEA, 0xC244, 0x7FEB, 0xC245, 0x7FEC, 0xC246, 0x7FED, + 0xC247, 0x7FEF, 0xC248, 0x7FF2, 0xC249, 0x7FF4, 0xC24A, 0x7FF5, 0xC24B, 0x7FF6, 0xC24C, 0x7FF7, 0xC24D, 0x7FF8, 0xC24E, 0x7FF9, + 0xC24F, 0x7FFA, 0xC250, 0x7FFD, 0xC251, 0x7FFE, 0xC252, 0x7FFF, 0xC253, 0x8002, 0xC254, 0x8007, 0xC255, 0x8008, 0xC256, 0x8009, + 0xC257, 0x800A, 0xC258, 0x800E, 0xC259, 0x800F, 0xC25A, 0x8011, 0xC25B, 0x8013, 0xC25C, 0x801A, 0xC25D, 0x801B, 0xC25E, 0x801D, + 0xC25F, 0x801E, 0xC260, 0x801F, 0xC261, 0x8021, 0xC262, 0x8023, 0xC263, 0x8024, 0xC264, 0x802B, 0xC265, 0x802C, 0xC266, 0x802D, + 0xC267, 0x802E, 0xC268, 0x802F, 0xC269, 0x8030, 0xC26A, 0x8032, 0xC26B, 0x8034, 0xC26C, 0x8039, 0xC26D, 0x803A, 0xC26E, 0x803C, + 0xC26F, 0x803E, 0xC270, 0x8040, 0xC271, 0x8041, 0xC272, 0x8044, 0xC273, 0x8045, 0xC274, 0x8047, 0xC275, 0x8048, 0xC276, 0x8049, + 0xC277, 0x804E, 0xC278, 0x804F, 0xC279, 0x8050, 0xC27A, 0x8051, 0xC27B, 0x8053, 0xC27C, 0x8055, 0xC27D, 0x8056, 0xC27E, 0x8057, + 0xC280, 0x8059, 0xC281, 0x805B, 0xC282, 0x805C, 0xC283, 0x805D, 0xC284, 0x805E, 0xC285, 0x805F, 0xC286, 0x8060, 0xC287, 0x8061, + 0xC288, 0x8062, 0xC289, 0x8063, 0xC28A, 0x8064, 0xC28B, 0x8065, 0xC28C, 0x8066, 0xC28D, 0x8067, 0xC28E, 0x8068, 0xC28F, 0x806B, + 0xC290, 0x806C, 0xC291, 0x806D, 0xC292, 0x806E, 0xC293, 0x806F, 0xC294, 0x8070, 0xC295, 0x8072, 0xC296, 0x8073, 0xC297, 0x8074, + 0xC298, 0x8075, 0xC299, 0x8076, 0xC29A, 0x8077, 0xC29B, 0x8078, 0xC29C, 0x8079, 0xC29D, 0x807A, 0xC29E, 0x807B, 0xC29F, 0x807C, + 0xC2A0, 0x807D, 0xC2A1, 0x9686, 0xC2A2, 0x5784, 0xC2A3, 0x62E2, 0xC2A4, 0x9647, 0xC2A5, 0x697C, 0xC2A6, 0x5A04, 0xC2A7, 0x6402, + 0xC2A8, 0x7BD3, 0xC2A9, 0x6F0F, 0xC2AA, 0x964B, 0xC2AB, 0x82A6, 0xC2AC, 0x5362, 0xC2AD, 0x9885, 0xC2AE, 0x5E90, 0xC2AF, 0x7089, + 0xC2B0, 0x63B3, 0xC2B1, 0x5364, 0xC2B2, 0x864F, 0xC2B3, 0x9C81, 0xC2B4, 0x9E93, 0xC2B5, 0x788C, 0xC2B6, 0x9732, 0xC2B7, 0x8DEF, + 0xC2B8, 0x8D42, 0xC2B9, 0x9E7F, 0xC2BA, 0x6F5E, 0xC2BB, 0x7984, 0xC2BC, 0x5F55, 0xC2BD, 0x9646, 0xC2BE, 0x622E, 0xC2BF, 0x9A74, + 0xC2C0, 0x5415, 0xC2C1, 0x94DD, 0xC2C2, 0x4FA3, 0xC2C3, 0x65C5, 0xC2C4, 0x5C65, 0xC2C5, 0x5C61, 0xC2C6, 0x7F15, 0xC2C7, 0x8651, + 0xC2C8, 0x6C2F, 0xC2C9, 0x5F8B, 0xC2CA, 0x7387, 0xC2CB, 0x6EE4, 0xC2CC, 0x7EFF, 0xC2CD, 0x5CE6, 0xC2CE, 0x631B, 0xC2CF, 0x5B6A, + 0xC2D0, 0x6EE6, 0xC2D1, 0x5375, 0xC2D2, 0x4E71, 0xC2D3, 0x63A0, 0xC2D4, 0x7565, 0xC2D5, 0x62A1, 0xC2D6, 0x8F6E, 0xC2D7, 0x4F26, + 0xC2D8, 0x4ED1, 0xC2D9, 0x6CA6, 0xC2DA, 0x7EB6, 0xC2DB, 0x8BBA, 0xC2DC, 0x841D, 0xC2DD, 0x87BA, 0xC2DE, 0x7F57, 0xC2DF, 0x903B, + 0xC2E0, 0x9523, 0xC2E1, 0x7BA9, 0xC2E2, 0x9AA1, 0xC2E3, 0x88F8, 0xC2E4, 0x843D, 0xC2E5, 0x6D1B, 0xC2E6, 0x9A86, 0xC2E7, 0x7EDC, + 0xC2E8, 0x5988, 0xC2E9, 0x9EBB, 0xC2EA, 0x739B, 0xC2EB, 0x7801, 0xC2EC, 0x8682, 0xC2ED, 0x9A6C, 0xC2EE, 0x9A82, 0xC2EF, 0x561B, + 0xC2F0, 0x5417, 0xC2F1, 0x57CB, 0xC2F2, 0x4E70, 0xC2F3, 0x9EA6, 0xC2F4, 0x5356, 0xC2F5, 0x8FC8, 0xC2F6, 0x8109, 0xC2F7, 0x7792, + 0xC2F8, 0x9992, 0xC2F9, 0x86EE, 0xC2FA, 0x6EE1, 0xC2FB, 0x8513, 0xC2FC, 0x66FC, 0xC2FD, 0x6162, 0xC2FE, 0x6F2B, 0xC340, 0x807E, + 0xC341, 0x8081, 0xC342, 0x8082, 0xC343, 0x8085, 0xC344, 0x8088, 0xC345, 0x808A, 0xC346, 0x808D, 0xC347, 0x808E, 0xC348, 0x808F, + 0xC349, 0x8090, 0xC34A, 0x8091, 0xC34B, 0x8092, 0xC34C, 0x8094, 0xC34D, 0x8095, 0xC34E, 0x8097, 0xC34F, 0x8099, 0xC350, 0x809E, + 0xC351, 0x80A3, 0xC352, 0x80A6, 0xC353, 0x80A7, 0xC354, 0x80A8, 0xC355, 0x80AC, 0xC356, 0x80B0, 0xC357, 0x80B3, 0xC358, 0x80B5, + 0xC359, 0x80B6, 0xC35A, 0x80B8, 0xC35B, 0x80B9, 0xC35C, 0x80BB, 0xC35D, 0x80C5, 0xC35E, 0x80C7, 0xC35F, 0x80C8, 0xC360, 0x80C9, + 0xC361, 0x80CA, 0xC362, 0x80CB, 0xC363, 0x80CF, 0xC364, 0x80D0, 0xC365, 0x80D1, 0xC366, 0x80D2, 0xC367, 0x80D3, 0xC368, 0x80D4, + 0xC369, 0x80D5, 0xC36A, 0x80D8, 0xC36B, 0x80DF, 0xC36C, 0x80E0, 0xC36D, 0x80E2, 0xC36E, 0x80E3, 0xC36F, 0x80E6, 0xC370, 0x80EE, + 0xC371, 0x80F5, 0xC372, 0x80F7, 0xC373, 0x80F9, 0xC374, 0x80FB, 0xC375, 0x80FE, 0xC376, 0x80FF, 0xC377, 0x8100, 0xC378, 0x8101, + 0xC379, 0x8103, 0xC37A, 0x8104, 0xC37B, 0x8105, 0xC37C, 0x8107, 0xC37D, 0x8108, 0xC37E, 0x810B, 0xC380, 0x810C, 0xC381, 0x8115, + 0xC382, 0x8117, 0xC383, 0x8119, 0xC384, 0x811B, 0xC385, 0x811C, 0xC386, 0x811D, 0xC387, 0x811F, 0xC388, 0x8120, 0xC389, 0x8121, + 0xC38A, 0x8122, 0xC38B, 0x8123, 0xC38C, 0x8124, 0xC38D, 0x8125, 0xC38E, 0x8126, 0xC38F, 0x8127, 0xC390, 0x8128, 0xC391, 0x8129, + 0xC392, 0x812A, 0xC393, 0x812B, 0xC394, 0x812D, 0xC395, 0x812E, 0xC396, 0x8130, 0xC397, 0x8133, 0xC398, 0x8134, 0xC399, 0x8135, + 0xC39A, 0x8137, 0xC39B, 0x8139, 0xC39C, 0x813A, 0xC39D, 0x813B, 0xC39E, 0x813C, 0xC39F, 0x813D, 0xC3A0, 0x813F, 0xC3A1, 0x8C29, + 0xC3A2, 0x8292, 0xC3A3, 0x832B, 0xC3A4, 0x76F2, 0xC3A5, 0x6C13, 0xC3A6, 0x5FD9, 0xC3A7, 0x83BD, 0xC3A8, 0x732B, 0xC3A9, 0x8305, + 0xC3AA, 0x951A, 0xC3AB, 0x6BDB, 0xC3AC, 0x77DB, 0xC3AD, 0x94C6, 0xC3AE, 0x536F, 0xC3AF, 0x8302, 0xC3B0, 0x5192, 0xC3B1, 0x5E3D, + 0xC3B2, 0x8C8C, 0xC3B3, 0x8D38, 0xC3B4, 0x4E48, 0xC3B5, 0x73AB, 0xC3B6, 0x679A, 0xC3B7, 0x6885, 0xC3B8, 0x9176, 0xC3B9, 0x9709, + 0xC3BA, 0x7164, 0xC3BB, 0x6CA1, 0xC3BC, 0x7709, 0xC3BD, 0x5A92, 0xC3BE, 0x9541, 0xC3BF, 0x6BCF, 0xC3C0, 0x7F8E, 0xC3C1, 0x6627, + 0xC3C2, 0x5BD0, 0xC3C3, 0x59B9, 0xC3C4, 0x5A9A, 0xC3C5, 0x95E8, 0xC3C6, 0x95F7, 0xC3C7, 0x4EEC, 0xC3C8, 0x840C, 0xC3C9, 0x8499, + 0xC3CA, 0x6AAC, 0xC3CB, 0x76DF, 0xC3CC, 0x9530, 0xC3CD, 0x731B, 0xC3CE, 0x68A6, 0xC3CF, 0x5B5F, 0xC3D0, 0x772F, 0xC3D1, 0x919A, + 0xC3D2, 0x9761, 0xC3D3, 0x7CDC, 0xC3D4, 0x8FF7, 0xC3D5, 0x8C1C, 0xC3D6, 0x5F25, 0xC3D7, 0x7C73, 0xC3D8, 0x79D8, 0xC3D9, 0x89C5, + 0xC3DA, 0x6CCC, 0xC3DB, 0x871C, 0xC3DC, 0x5BC6, 0xC3DD, 0x5E42, 0xC3DE, 0x68C9, 0xC3DF, 0x7720, 0xC3E0, 0x7EF5, 0xC3E1, 0x5195, + 0xC3E2, 0x514D, 0xC3E3, 0x52C9, 0xC3E4, 0x5A29, 0xC3E5, 0x7F05, 0xC3E6, 0x9762, 0xC3E7, 0x82D7, 0xC3E8, 0x63CF, 0xC3E9, 0x7784, + 0xC3EA, 0x85D0, 0xC3EB, 0x79D2, 0xC3EC, 0x6E3A, 0xC3ED, 0x5E99, 0xC3EE, 0x5999, 0xC3EF, 0x8511, 0xC3F0, 0x706D, 0xC3F1, 0x6C11, + 0xC3F2, 0x62BF, 0xC3F3, 0x76BF, 0xC3F4, 0x654F, 0xC3F5, 0x60AF, 0xC3F6, 0x95FD, 0xC3F7, 0x660E, 0xC3F8, 0x879F, 0xC3F9, 0x9E23, + 0xC3FA, 0x94ED, 0xC3FB, 0x540D, 0xC3FC, 0x547D, 0xC3FD, 0x8C2C, 0xC3FE, 0x6478, 0xC440, 0x8140, 0xC441, 0x8141, 0xC442, 0x8142, + 0xC443, 0x8143, 0xC444, 0x8144, 0xC445, 0x8145, 0xC446, 0x8147, 0xC447, 0x8149, 0xC448, 0x814D, 0xC449, 0x814E, 0xC44A, 0x814F, + 0xC44B, 0x8152, 0xC44C, 0x8156, 0xC44D, 0x8157, 0xC44E, 0x8158, 0xC44F, 0x815B, 0xC450, 0x815C, 0xC451, 0x815D, 0xC452, 0x815E, + 0xC453, 0x815F, 0xC454, 0x8161, 0xC455, 0x8162, 0xC456, 0x8163, 0xC457, 0x8164, 0xC458, 0x8166, 0xC459, 0x8168, 0xC45A, 0x816A, + 0xC45B, 0x816B, 0xC45C, 0x816C, 0xC45D, 0x816F, 0xC45E, 0x8172, 0xC45F, 0x8173, 0xC460, 0x8175, 0xC461, 0x8176, 0xC462, 0x8177, + 0xC463, 0x8178, 0xC464, 0x8181, 0xC465, 0x8183, 0xC466, 0x8184, 0xC467, 0x8185, 0xC468, 0x8186, 0xC469, 0x8187, 0xC46A, 0x8189, + 0xC46B, 0x818B, 0xC46C, 0x818C, 0xC46D, 0x818D, 0xC46E, 0x818E, 0xC46F, 0x8190, 0xC470, 0x8192, 0xC471, 0x8193, 0xC472, 0x8194, + 0xC473, 0x8195, 0xC474, 0x8196, 0xC475, 0x8197, 0xC476, 0x8199, 0xC477, 0x819A, 0xC478, 0x819E, 0xC479, 0x819F, 0xC47A, 0x81A0, + 0xC47B, 0x81A1, 0xC47C, 0x81A2, 0xC47D, 0x81A4, 0xC47E, 0x81A5, 0xC480, 0x81A7, 0xC481, 0x81A9, 0xC482, 0x81AB, 0xC483, 0x81AC, + 0xC484, 0x81AD, 0xC485, 0x81AE, 0xC486, 0x81AF, 0xC487, 0x81B0, 0xC488, 0x81B1, 0xC489, 0x81B2, 0xC48A, 0x81B4, 0xC48B, 0x81B5, + 0xC48C, 0x81B6, 0xC48D, 0x81B7, 0xC48E, 0x81B8, 0xC48F, 0x81B9, 0xC490, 0x81BC, 0xC491, 0x81BD, 0xC492, 0x81BE, 0xC493, 0x81BF, + 0xC494, 0x81C4, 0xC495, 0x81C5, 0xC496, 0x81C7, 0xC497, 0x81C8, 0xC498, 0x81C9, 0xC499, 0x81CB, 0xC49A, 0x81CD, 0xC49B, 0x81CE, + 0xC49C, 0x81CF, 0xC49D, 0x81D0, 0xC49E, 0x81D1, 0xC49F, 0x81D2, 0xC4A0, 0x81D3, 0xC4A1, 0x6479, 0xC4A2, 0x8611, 0xC4A3, 0x6A21, + 0xC4A4, 0x819C, 0xC4A5, 0x78E8, 0xC4A6, 0x6469, 0xC4A7, 0x9B54, 0xC4A8, 0x62B9, 0xC4A9, 0x672B, 0xC4AA, 0x83AB, 0xC4AB, 0x58A8, + 0xC4AC, 0x9ED8, 0xC4AD, 0x6CAB, 0xC4AE, 0x6F20, 0xC4AF, 0x5BDE, 0xC4B0, 0x964C, 0xC4B1, 0x8C0B, 0xC4B2, 0x725F, 0xC4B3, 0x67D0, + 0xC4B4, 0x62C7, 0xC4B5, 0x7261, 0xC4B6, 0x4EA9, 0xC4B7, 0x59C6, 0xC4B8, 0x6BCD, 0xC4B9, 0x5893, 0xC4BA, 0x66AE, 0xC4BB, 0x5E55, + 0xC4BC, 0x52DF, 0xC4BD, 0x6155, 0xC4BE, 0x6728, 0xC4BF, 0x76EE, 0xC4C0, 0x7766, 0xC4C1, 0x7267, 0xC4C2, 0x7A46, 0xC4C3, 0x62FF, + 0xC4C4, 0x54EA, 0xC4C5, 0x5450, 0xC4C6, 0x94A0, 0xC4C7, 0x90A3, 0xC4C8, 0x5A1C, 0xC4C9, 0x7EB3, 0xC4CA, 0x6C16, 0xC4CB, 0x4E43, + 0xC4CC, 0x5976, 0xC4CD, 0x8010, 0xC4CE, 0x5948, 0xC4CF, 0x5357, 0xC4D0, 0x7537, 0xC4D1, 0x96BE, 0xC4D2, 0x56CA, 0xC4D3, 0x6320, + 0xC4D4, 0x8111, 0xC4D5, 0x607C, 0xC4D6, 0x95F9, 0xC4D7, 0x6DD6, 0xC4D8, 0x5462, 0xC4D9, 0x9981, 0xC4DA, 0x5185, 0xC4DB, 0x5AE9, + 0xC4DC, 0x80FD, 0xC4DD, 0x59AE, 0xC4DE, 0x9713, 0xC4DF, 0x502A, 0xC4E0, 0x6CE5, 0xC4E1, 0x5C3C, 0xC4E2, 0x62DF, 0xC4E3, 0x4F60, + 0xC4E4, 0x533F, 0xC4E5, 0x817B, 0xC4E6, 0x9006, 0xC4E7, 0x6EBA, 0xC4E8, 0x852B, 0xC4E9, 0x62C8, 0xC4EA, 0x5E74, 0xC4EB, 0x78BE, + 0xC4EC, 0x64B5, 0xC4ED, 0x637B, 0xC4EE, 0x5FF5, 0xC4EF, 0x5A18, 0xC4F0, 0x917F, 0xC4F1, 0x9E1F, 0xC4F2, 0x5C3F, 0xC4F3, 0x634F, + 0xC4F4, 0x8042, 0xC4F5, 0x5B7D, 0xC4F6, 0x556E, 0xC4F7, 0x954A, 0xC4F8, 0x954D, 0xC4F9, 0x6D85, 0xC4FA, 0x60A8, 0xC4FB, 0x67E0, + 0xC4FC, 0x72DE, 0xC4FD, 0x51DD, 0xC4FE, 0x5B81, 0xC540, 0x81D4, 0xC541, 0x81D5, 0xC542, 0x81D6, 0xC543, 0x81D7, 0xC544, 0x81D8, + 0xC545, 0x81D9, 0xC546, 0x81DA, 0xC547, 0x81DB, 0xC548, 0x81DC, 0xC549, 0x81DD, 0xC54A, 0x81DE, 0xC54B, 0x81DF, 0xC54C, 0x81E0, + 0xC54D, 0x81E1, 0xC54E, 0x81E2, 0xC54F, 0x81E4, 0xC550, 0x81E5, 0xC551, 0x81E6, 0xC552, 0x81E8, 0xC553, 0x81E9, 0xC554, 0x81EB, + 0xC555, 0x81EE, 0xC556, 0x81EF, 0xC557, 0x81F0, 0xC558, 0x81F1, 0xC559, 0x81F2, 0xC55A, 0x81F5, 0xC55B, 0x81F6, 0xC55C, 0x81F7, + 0xC55D, 0x81F8, 0xC55E, 0x81F9, 0xC55F, 0x81FA, 0xC560, 0x81FD, 0xC561, 0x81FF, 0xC562, 0x8203, 0xC563, 0x8207, 0xC564, 0x8208, + 0xC565, 0x8209, 0xC566, 0x820A, 0xC567, 0x820B, 0xC568, 0x820E, 0xC569, 0x820F, 0xC56A, 0x8211, 0xC56B, 0x8213, 0xC56C, 0x8215, + 0xC56D, 0x8216, 0xC56E, 0x8217, 0xC56F, 0x8218, 0xC570, 0x8219, 0xC571, 0x821A, 0xC572, 0x821D, 0xC573, 0x8220, 0xC574, 0x8224, + 0xC575, 0x8225, 0xC576, 0x8226, 0xC577, 0x8227, 0xC578, 0x8229, 0xC579, 0x822E, 0xC57A, 0x8232, 0xC57B, 0x823A, 0xC57C, 0x823C, + 0xC57D, 0x823D, 0xC57E, 0x823F, 0xC580, 0x8240, 0xC581, 0x8241, 0xC582, 0x8242, 0xC583, 0x8243, 0xC584, 0x8245, 0xC585, 0x8246, + 0xC586, 0x8248, 0xC587, 0x824A, 0xC588, 0x824C, 0xC589, 0x824D, 0xC58A, 0x824E, 0xC58B, 0x8250, 0xC58C, 0x8251, 0xC58D, 0x8252, + 0xC58E, 0x8253, 0xC58F, 0x8254, 0xC590, 0x8255, 0xC591, 0x8256, 0xC592, 0x8257, 0xC593, 0x8259, 0xC594, 0x825B, 0xC595, 0x825C, + 0xC596, 0x825D, 0xC597, 0x825E, 0xC598, 0x8260, 0xC599, 0x8261, 0xC59A, 0x8262, 0xC59B, 0x8263, 0xC59C, 0x8264, 0xC59D, 0x8265, + 0xC59E, 0x8266, 0xC59F, 0x8267, 0xC5A0, 0x8269, 0xC5A1, 0x62E7, 0xC5A2, 0x6CDE, 0xC5A3, 0x725B, 0xC5A4, 0x626D, 0xC5A5, 0x94AE, + 0xC5A6, 0x7EBD, 0xC5A7, 0x8113, 0xC5A8, 0x6D53, 0xC5A9, 0x519C, 0xC5AA, 0x5F04, 0xC5AB, 0x5974, 0xC5AC, 0x52AA, 0xC5AD, 0x6012, + 0xC5AE, 0x5973, 0xC5AF, 0x6696, 0xC5B0, 0x8650, 0xC5B1, 0x759F, 0xC5B2, 0x632A, 0xC5B3, 0x61E6, 0xC5B4, 0x7CEF, 0xC5B5, 0x8BFA, + 0xC5B6, 0x54E6, 0xC5B7, 0x6B27, 0xC5B8, 0x9E25, 0xC5B9, 0x6BB4, 0xC5BA, 0x85D5, 0xC5BB, 0x5455, 0xC5BC, 0x5076, 0xC5BD, 0x6CA4, + 0xC5BE, 0x556A, 0xC5BF, 0x8DB4, 0xC5C0, 0x722C, 0xC5C1, 0x5E15, 0xC5C2, 0x6015, 0xC5C3, 0x7436, 0xC5C4, 0x62CD, 0xC5C5, 0x6392, + 0xC5C6, 0x724C, 0xC5C7, 0x5F98, 0xC5C8, 0x6E43, 0xC5C9, 0x6D3E, 0xC5CA, 0x6500, 0xC5CB, 0x6F58, 0xC5CC, 0x76D8, 0xC5CD, 0x78D0, + 0xC5CE, 0x76FC, 0xC5CF, 0x7554, 0xC5D0, 0x5224, 0xC5D1, 0x53DB, 0xC5D2, 0x4E53, 0xC5D3, 0x5E9E, 0xC5D4, 0x65C1, 0xC5D5, 0x802A, + 0xC5D6, 0x80D6, 0xC5D7, 0x629B, 0xC5D8, 0x5486, 0xC5D9, 0x5228, 0xC5DA, 0x70AE, 0xC5DB, 0x888D, 0xC5DC, 0x8DD1, 0xC5DD, 0x6CE1, + 0xC5DE, 0x5478, 0xC5DF, 0x80DA, 0xC5E0, 0x57F9, 0xC5E1, 0x88F4, 0xC5E2, 0x8D54, 0xC5E3, 0x966A, 0xC5E4, 0x914D, 0xC5E5, 0x4F69, + 0xC5E6, 0x6C9B, 0xC5E7, 0x55B7, 0xC5E8, 0x76C6, 0xC5E9, 0x7830, 0xC5EA, 0x62A8, 0xC5EB, 0x70F9, 0xC5EC, 0x6F8E, 0xC5ED, 0x5F6D, + 0xC5EE, 0x84EC, 0xC5EF, 0x68DA, 0xC5F0, 0x787C, 0xC5F1, 0x7BF7, 0xC5F2, 0x81A8, 0xC5F3, 0x670B, 0xC5F4, 0x9E4F, 0xC5F5, 0x6367, + 0xC5F6, 0x78B0, 0xC5F7, 0x576F, 0xC5F8, 0x7812, 0xC5F9, 0x9739, 0xC5FA, 0x6279, 0xC5FB, 0x62AB, 0xC5FC, 0x5288, 0xC5FD, 0x7435, + 0xC5FE, 0x6BD7, 0xC640, 0x826A, 0xC641, 0x826B, 0xC642, 0x826C, 0xC643, 0x826D, 0xC644, 0x8271, 0xC645, 0x8275, 0xC646, 0x8276, + 0xC647, 0x8277, 0xC648, 0x8278, 0xC649, 0x827B, 0xC64A, 0x827C, 0xC64B, 0x8280, 0xC64C, 0x8281, 0xC64D, 0x8283, 0xC64E, 0x8285, + 0xC64F, 0x8286, 0xC650, 0x8287, 0xC651, 0x8289, 0xC652, 0x828C, 0xC653, 0x8290, 0xC654, 0x8293, 0xC655, 0x8294, 0xC656, 0x8295, + 0xC657, 0x8296, 0xC658, 0x829A, 0xC659, 0x829B, 0xC65A, 0x829E, 0xC65B, 0x82A0, 0xC65C, 0x82A2, 0xC65D, 0x82A3, 0xC65E, 0x82A7, + 0xC65F, 0x82B2, 0xC660, 0x82B5, 0xC661, 0x82B6, 0xC662, 0x82BA, 0xC663, 0x82BB, 0xC664, 0x82BC, 0xC665, 0x82BF, 0xC666, 0x82C0, + 0xC667, 0x82C2, 0xC668, 0x82C3, 0xC669, 0x82C5, 0xC66A, 0x82C6, 0xC66B, 0x82C9, 0xC66C, 0x82D0, 0xC66D, 0x82D6, 0xC66E, 0x82D9, + 0xC66F, 0x82DA, 0xC670, 0x82DD, 0xC671, 0x82E2, 0xC672, 0x82E7, 0xC673, 0x82E8, 0xC674, 0x82E9, 0xC675, 0x82EA, 0xC676, 0x82EC, + 0xC677, 0x82ED, 0xC678, 0x82EE, 0xC679, 0x82F0, 0xC67A, 0x82F2, 0xC67B, 0x82F3, 0xC67C, 0x82F5, 0xC67D, 0x82F6, 0xC67E, 0x82F8, + 0xC680, 0x82FA, 0xC681, 0x82FC, 0xC682, 0x82FD, 0xC683, 0x82FE, 0xC684, 0x82FF, 0xC685, 0x8300, 0xC686, 0x830A, 0xC687, 0x830B, + 0xC688, 0x830D, 0xC689, 0x8310, 0xC68A, 0x8312, 0xC68B, 0x8313, 0xC68C, 0x8316, 0xC68D, 0x8318, 0xC68E, 0x8319, 0xC68F, 0x831D, + 0xC690, 0x831E, 0xC691, 0x831F, 0xC692, 0x8320, 0xC693, 0x8321, 0xC694, 0x8322, 0xC695, 0x8323, 0xC696, 0x8324, 0xC697, 0x8325, + 0xC698, 0x8326, 0xC699, 0x8329, 0xC69A, 0x832A, 0xC69B, 0x832E, 0xC69C, 0x8330, 0xC69D, 0x8332, 0xC69E, 0x8337, 0xC69F, 0x833B, + 0xC6A0, 0x833D, 0xC6A1, 0x5564, 0xC6A2, 0x813E, 0xC6A3, 0x75B2, 0xC6A4, 0x76AE, 0xC6A5, 0x5339, 0xC6A6, 0x75DE, 0xC6A7, 0x50FB, + 0xC6A8, 0x5C41, 0xC6A9, 0x8B6C, 0xC6AA, 0x7BC7, 0xC6AB, 0x504F, 0xC6AC, 0x7247, 0xC6AD, 0x9A97, 0xC6AE, 0x98D8, 0xC6AF, 0x6F02, + 0xC6B0, 0x74E2, 0xC6B1, 0x7968, 0xC6B2, 0x6487, 0xC6B3, 0x77A5, 0xC6B4, 0x62FC, 0xC6B5, 0x9891, 0xC6B6, 0x8D2B, 0xC6B7, 0x54C1, + 0xC6B8, 0x8058, 0xC6B9, 0x4E52, 0xC6BA, 0x576A, 0xC6BB, 0x82F9, 0xC6BC, 0x840D, 0xC6BD, 0x5E73, 0xC6BE, 0x51ED, 0xC6BF, 0x74F6, + 0xC6C0, 0x8BC4, 0xC6C1, 0x5C4F, 0xC6C2, 0x5761, 0xC6C3, 0x6CFC, 0xC6C4, 0x9887, 0xC6C5, 0x5A46, 0xC6C6, 0x7834, 0xC6C7, 0x9B44, + 0xC6C8, 0x8FEB, 0xC6C9, 0x7C95, 0xC6CA, 0x5256, 0xC6CB, 0x6251, 0xC6CC, 0x94FA, 0xC6CD, 0x4EC6, 0xC6CE, 0x8386, 0xC6CF, 0x8461, + 0xC6D0, 0x83E9, 0xC6D1, 0x84B2, 0xC6D2, 0x57D4, 0xC6D3, 0x6734, 0xC6D4, 0x5703, 0xC6D5, 0x666E, 0xC6D6, 0x6D66, 0xC6D7, 0x8C31, + 0xC6D8, 0x66DD, 0xC6D9, 0x7011, 0xC6DA, 0x671F, 0xC6DB, 0x6B3A, 0xC6DC, 0x6816, 0xC6DD, 0x621A, 0xC6DE, 0x59BB, 0xC6DF, 0x4E03, + 0xC6E0, 0x51C4, 0xC6E1, 0x6F06, 0xC6E2, 0x67D2, 0xC6E3, 0x6C8F, 0xC6E4, 0x5176, 0xC6E5, 0x68CB, 0xC6E6, 0x5947, 0xC6E7, 0x6B67, + 0xC6E8, 0x7566, 0xC6E9, 0x5D0E, 0xC6EA, 0x8110, 0xC6EB, 0x9F50, 0xC6EC, 0x65D7, 0xC6ED, 0x7948, 0xC6EE, 0x7941, 0xC6EF, 0x9A91, + 0xC6F0, 0x8D77, 0xC6F1, 0x5C82, 0xC6F2, 0x4E5E, 0xC6F3, 0x4F01, 0xC6F4, 0x542F, 0xC6F5, 0x5951, 0xC6F6, 0x780C, 0xC6F7, 0x5668, + 0xC6F8, 0x6C14, 0xC6F9, 0x8FC4, 0xC6FA, 0x5F03, 0xC6FB, 0x6C7D, 0xC6FC, 0x6CE3, 0xC6FD, 0x8BAB, 0xC6FE, 0x6390, 0xC740, 0x833E, + 0xC741, 0x833F, 0xC742, 0x8341, 0xC743, 0x8342, 0xC744, 0x8344, 0xC745, 0x8345, 0xC746, 0x8348, 0xC747, 0x834A, 0xC748, 0x834B, + 0xC749, 0x834C, 0xC74A, 0x834D, 0xC74B, 0x834E, 0xC74C, 0x8353, 0xC74D, 0x8355, 0xC74E, 0x8356, 0xC74F, 0x8357, 0xC750, 0x8358, + 0xC751, 0x8359, 0xC752, 0x835D, 0xC753, 0x8362, 0xC754, 0x8370, 0xC755, 0x8371, 0xC756, 0x8372, 0xC757, 0x8373, 0xC758, 0x8374, + 0xC759, 0x8375, 0xC75A, 0x8376, 0xC75B, 0x8379, 0xC75C, 0x837A, 0xC75D, 0x837E, 0xC75E, 0x837F, 0xC75F, 0x8380, 0xC760, 0x8381, + 0xC761, 0x8382, 0xC762, 0x8383, 0xC763, 0x8384, 0xC764, 0x8387, 0xC765, 0x8388, 0xC766, 0x838A, 0xC767, 0x838B, 0xC768, 0x838C, + 0xC769, 0x838D, 0xC76A, 0x838F, 0xC76B, 0x8390, 0xC76C, 0x8391, 0xC76D, 0x8394, 0xC76E, 0x8395, 0xC76F, 0x8396, 0xC770, 0x8397, + 0xC771, 0x8399, 0xC772, 0x839A, 0xC773, 0x839D, 0xC774, 0x839F, 0xC775, 0x83A1, 0xC776, 0x83A2, 0xC777, 0x83A3, 0xC778, 0x83A4, + 0xC779, 0x83A5, 0xC77A, 0x83A6, 0xC77B, 0x83A7, 0xC77C, 0x83AC, 0xC77D, 0x83AD, 0xC77E, 0x83AE, 0xC780, 0x83AF, 0xC781, 0x83B5, + 0xC782, 0x83BB, 0xC783, 0x83BE, 0xC784, 0x83BF, 0xC785, 0x83C2, 0xC786, 0x83C3, 0xC787, 0x83C4, 0xC788, 0x83C6, 0xC789, 0x83C8, + 0xC78A, 0x83C9, 0xC78B, 0x83CB, 0xC78C, 0x83CD, 0xC78D, 0x83CE, 0xC78E, 0x83D0, 0xC78F, 0x83D1, 0xC790, 0x83D2, 0xC791, 0x83D3, + 0xC792, 0x83D5, 0xC793, 0x83D7, 0xC794, 0x83D9, 0xC795, 0x83DA, 0xC796, 0x83DB, 0xC797, 0x83DE, 0xC798, 0x83E2, 0xC799, 0x83E3, + 0xC79A, 0x83E4, 0xC79B, 0x83E6, 0xC79C, 0x83E7, 0xC79D, 0x83E8, 0xC79E, 0x83EB, 0xC79F, 0x83EC, 0xC7A0, 0x83ED, 0xC7A1, 0x6070, + 0xC7A2, 0x6D3D, 0xC7A3, 0x7275, 0xC7A4, 0x6266, 0xC7A5, 0x948E, 0xC7A6, 0x94C5, 0xC7A7, 0x5343, 0xC7A8, 0x8FC1, 0xC7A9, 0x7B7E, + 0xC7AA, 0x4EDF, 0xC7AB, 0x8C26, 0xC7AC, 0x4E7E, 0xC7AD, 0x9ED4, 0xC7AE, 0x94B1, 0xC7AF, 0x94B3, 0xC7B0, 0x524D, 0xC7B1, 0x6F5C, + 0xC7B2, 0x9063, 0xC7B3, 0x6D45, 0xC7B4, 0x8C34, 0xC7B5, 0x5811, 0xC7B6, 0x5D4C, 0xC7B7, 0x6B20, 0xC7B8, 0x6B49, 0xC7B9, 0x67AA, + 0xC7BA, 0x545B, 0xC7BB, 0x8154, 0xC7BC, 0x7F8C, 0xC7BD, 0x5899, 0xC7BE, 0x8537, 0xC7BF, 0x5F3A, 0xC7C0, 0x62A2, 0xC7C1, 0x6A47, + 0xC7C2, 0x9539, 0xC7C3, 0x6572, 0xC7C4, 0x6084, 0xC7C5, 0x6865, 0xC7C6, 0x77A7, 0xC7C7, 0x4E54, 0xC7C8, 0x4FA8, 0xC7C9, 0x5DE7, + 0xC7CA, 0x9798, 0xC7CB, 0x64AC, 0xC7CC, 0x7FD8, 0xC7CD, 0x5CED, 0xC7CE, 0x4FCF, 0xC7CF, 0x7A8D, 0xC7D0, 0x5207, 0xC7D1, 0x8304, + 0xC7D2, 0x4E14, 0xC7D3, 0x602F, 0xC7D4, 0x7A83, 0xC7D5, 0x94A6, 0xC7D6, 0x4FB5, 0xC7D7, 0x4EB2, 0xC7D8, 0x79E6, 0xC7D9, 0x7434, + 0xC7DA, 0x52E4, 0xC7DB, 0x82B9, 0xC7DC, 0x64D2, 0xC7DD, 0x79BD, 0xC7DE, 0x5BDD, 0xC7DF, 0x6C81, 0xC7E0, 0x9752, 0xC7E1, 0x8F7B, + 0xC7E2, 0x6C22, 0xC7E3, 0x503E, 0xC7E4, 0x537F, 0xC7E5, 0x6E05, 0xC7E6, 0x64CE, 0xC7E7, 0x6674, 0xC7E8, 0x6C30, 0xC7E9, 0x60C5, + 0xC7EA, 0x9877, 0xC7EB, 0x8BF7, 0xC7EC, 0x5E86, 0xC7ED, 0x743C, 0xC7EE, 0x7A77, 0xC7EF, 0x79CB, 0xC7F0, 0x4E18, 0xC7F1, 0x90B1, + 0xC7F2, 0x7403, 0xC7F3, 0x6C42, 0xC7F4, 0x56DA, 0xC7F5, 0x914B, 0xC7F6, 0x6CC5, 0xC7F7, 0x8D8B, 0xC7F8, 0x533A, 0xC7F9, 0x86C6, + 0xC7FA, 0x66F2, 0xC7FB, 0x8EAF, 0xC7FC, 0x5C48, 0xC7FD, 0x9A71, 0xC7FE, 0x6E20, 0xC840, 0x83EE, 0xC841, 0x83EF, 0xC842, 0x83F3, + 0xC843, 0x83F4, 0xC844, 0x83F5, 0xC845, 0x83F6, 0xC846, 0x83F7, 0xC847, 0x83FA, 0xC848, 0x83FB, 0xC849, 0x83FC, 0xC84A, 0x83FE, + 0xC84B, 0x83FF, 0xC84C, 0x8400, 0xC84D, 0x8402, 0xC84E, 0x8405, 0xC84F, 0x8407, 0xC850, 0x8408, 0xC851, 0x8409, 0xC852, 0x840A, + 0xC853, 0x8410, 0xC854, 0x8412, 0xC855, 0x8413, 0xC856, 0x8414, 0xC857, 0x8415, 0xC858, 0x8416, 0xC859, 0x8417, 0xC85A, 0x8419, + 0xC85B, 0x841A, 0xC85C, 0x841B, 0xC85D, 0x841E, 0xC85E, 0x841F, 0xC85F, 0x8420, 0xC860, 0x8421, 0xC861, 0x8422, 0xC862, 0x8423, + 0xC863, 0x8429, 0xC864, 0x842A, 0xC865, 0x842B, 0xC866, 0x842C, 0xC867, 0x842D, 0xC868, 0x842E, 0xC869, 0x842F, 0xC86A, 0x8430, + 0xC86B, 0x8432, 0xC86C, 0x8433, 0xC86D, 0x8434, 0xC86E, 0x8435, 0xC86F, 0x8436, 0xC870, 0x8437, 0xC871, 0x8439, 0xC872, 0x843A, + 0xC873, 0x843B, 0xC874, 0x843E, 0xC875, 0x843F, 0xC876, 0x8440, 0xC877, 0x8441, 0xC878, 0x8442, 0xC879, 0x8443, 0xC87A, 0x8444, + 0xC87B, 0x8445, 0xC87C, 0x8447, 0xC87D, 0x8448, 0xC87E, 0x8449, 0xC880, 0x844A, 0xC881, 0x844B, 0xC882, 0x844C, 0xC883, 0x844D, + 0xC884, 0x844E, 0xC885, 0x844F, 0xC886, 0x8450, 0xC887, 0x8452, 0xC888, 0x8453, 0xC889, 0x8454, 0xC88A, 0x8455, 0xC88B, 0x8456, + 0xC88C, 0x8458, 0xC88D, 0x845D, 0xC88E, 0x845E, 0xC88F, 0x845F, 0xC890, 0x8460, 0xC891, 0x8462, 0xC892, 0x8464, 0xC893, 0x8465, + 0xC894, 0x8466, 0xC895, 0x8467, 0xC896, 0x8468, 0xC897, 0x846A, 0xC898, 0x846E, 0xC899, 0x846F, 0xC89A, 0x8470, 0xC89B, 0x8472, + 0xC89C, 0x8474, 0xC89D, 0x8477, 0xC89E, 0x8479, 0xC89F, 0x847B, 0xC8A0, 0x847C, 0xC8A1, 0x53D6, 0xC8A2, 0x5A36, 0xC8A3, 0x9F8B, + 0xC8A4, 0x8DA3, 0xC8A5, 0x53BB, 0xC8A6, 0x5708, 0xC8A7, 0x98A7, 0xC8A8, 0x6743, 0xC8A9, 0x919B, 0xC8AA, 0x6CC9, 0xC8AB, 0x5168, + 0xC8AC, 0x75CA, 0xC8AD, 0x62F3, 0xC8AE, 0x72AC, 0xC8AF, 0x5238, 0xC8B0, 0x529D, 0xC8B1, 0x7F3A, 0xC8B2, 0x7094, 0xC8B3, 0x7638, + 0xC8B4, 0x5374, 0xC8B5, 0x9E4A, 0xC8B6, 0x69B7, 0xC8B7, 0x786E, 0xC8B8, 0x96C0, 0xC8B9, 0x88D9, 0xC8BA, 0x7FA4, 0xC8BB, 0x7136, + 0xC8BC, 0x71C3, 0xC8BD, 0x5189, 0xC8BE, 0x67D3, 0xC8BF, 0x74E4, 0xC8C0, 0x58E4, 0xC8C1, 0x6518, 0xC8C2, 0x56B7, 0xC8C3, 0x8BA9, + 0xC8C4, 0x9976, 0xC8C5, 0x6270, 0xC8C6, 0x7ED5, 0xC8C7, 0x60F9, 0xC8C8, 0x70ED, 0xC8C9, 0x58EC, 0xC8CA, 0x4EC1, 0xC8CB, 0x4EBA, + 0xC8CC, 0x5FCD, 0xC8CD, 0x97E7, 0xC8CE, 0x4EFB, 0xC8CF, 0x8BA4, 0xC8D0, 0x5203, 0xC8D1, 0x598A, 0xC8D2, 0x7EAB, 0xC8D3, 0x6254, + 0xC8D4, 0x4ECD, 0xC8D5, 0x65E5, 0xC8D6, 0x620E, 0xC8D7, 0x8338, 0xC8D8, 0x84C9, 0xC8D9, 0x8363, 0xC8DA, 0x878D, 0xC8DB, 0x7194, + 0xC8DC, 0x6EB6, 0xC8DD, 0x5BB9, 0xC8DE, 0x7ED2, 0xC8DF, 0x5197, 0xC8E0, 0x63C9, 0xC8E1, 0x67D4, 0xC8E2, 0x8089, 0xC8E3, 0x8339, + 0xC8E4, 0x8815, 0xC8E5, 0x5112, 0xC8E6, 0x5B7A, 0xC8E7, 0x5982, 0xC8E8, 0x8FB1, 0xC8E9, 0x4E73, 0xC8EA, 0x6C5D, 0xC8EB, 0x5165, + 0xC8EC, 0x8925, 0xC8ED, 0x8F6F, 0xC8EE, 0x962E, 0xC8EF, 0x854A, 0xC8F0, 0x745E, 0xC8F1, 0x9510, 0xC8F2, 0x95F0, 0xC8F3, 0x6DA6, + 0xC8F4, 0x82E5, 0xC8F5, 0x5F31, 0xC8F6, 0x6492, 0xC8F7, 0x6D12, 0xC8F8, 0x8428, 0xC8F9, 0x816E, 0xC8FA, 0x9CC3, 0xC8FB, 0x585E, + 0xC8FC, 0x8D5B, 0xC8FD, 0x4E09, 0xC8FE, 0x53C1, 0xC940, 0x847D, 0xC941, 0x847E, 0xC942, 0x847F, 0xC943, 0x8480, 0xC944, 0x8481, + 0xC945, 0x8483, 0xC946, 0x8484, 0xC947, 0x8485, 0xC948, 0x8486, 0xC949, 0x848A, 0xC94A, 0x848D, 0xC94B, 0x848F, 0xC94C, 0x8490, + 0xC94D, 0x8491, 0xC94E, 0x8492, 0xC94F, 0x8493, 0xC950, 0x8494, 0xC951, 0x8495, 0xC952, 0x8496, 0xC953, 0x8498, 0xC954, 0x849A, + 0xC955, 0x849B, 0xC956, 0x849D, 0xC957, 0x849E, 0xC958, 0x849F, 0xC959, 0x84A0, 0xC95A, 0x84A2, 0xC95B, 0x84A3, 0xC95C, 0x84A4, + 0xC95D, 0x84A5, 0xC95E, 0x84A6, 0xC95F, 0x84A7, 0xC960, 0x84A8, 0xC961, 0x84A9, 0xC962, 0x84AA, 0xC963, 0x84AB, 0xC964, 0x84AC, + 0xC965, 0x84AD, 0xC966, 0x84AE, 0xC967, 0x84B0, 0xC968, 0x84B1, 0xC969, 0x84B3, 0xC96A, 0x84B5, 0xC96B, 0x84B6, 0xC96C, 0x84B7, + 0xC96D, 0x84BB, 0xC96E, 0x84BC, 0xC96F, 0x84BE, 0xC970, 0x84C0, 0xC971, 0x84C2, 0xC972, 0x84C3, 0xC973, 0x84C5, 0xC974, 0x84C6, + 0xC975, 0x84C7, 0xC976, 0x84C8, 0xC977, 0x84CB, 0xC978, 0x84CC, 0xC979, 0x84CE, 0xC97A, 0x84CF, 0xC97B, 0x84D2, 0xC97C, 0x84D4, + 0xC97D, 0x84D5, 0xC97E, 0x84D7, 0xC980, 0x84D8, 0xC981, 0x84D9, 0xC982, 0x84DA, 0xC983, 0x84DB, 0xC984, 0x84DC, 0xC985, 0x84DE, + 0xC986, 0x84E1, 0xC987, 0x84E2, 0xC988, 0x84E4, 0xC989, 0x84E7, 0xC98A, 0x84E8, 0xC98B, 0x84E9, 0xC98C, 0x84EA, 0xC98D, 0x84EB, + 0xC98E, 0x84ED, 0xC98F, 0x84EE, 0xC990, 0x84EF, 0xC991, 0x84F1, 0xC992, 0x84F2, 0xC993, 0x84F3, 0xC994, 0x84F4, 0xC995, 0x84F5, + 0xC996, 0x84F6, 0xC997, 0x84F7, 0xC998, 0x84F8, 0xC999, 0x84F9, 0xC99A, 0x84FA, 0xC99B, 0x84FB, 0xC99C, 0x84FD, 0xC99D, 0x84FE, + 0xC99E, 0x8500, 0xC99F, 0x8501, 0xC9A0, 0x8502, 0xC9A1, 0x4F1E, 0xC9A2, 0x6563, 0xC9A3, 0x6851, 0xC9A4, 0x55D3, 0xC9A5, 0x4E27, + 0xC9A6, 0x6414, 0xC9A7, 0x9A9A, 0xC9A8, 0x626B, 0xC9A9, 0x5AC2, 0xC9AA, 0x745F, 0xC9AB, 0x8272, 0xC9AC, 0x6DA9, 0xC9AD, 0x68EE, + 0xC9AE, 0x50E7, 0xC9AF, 0x838E, 0xC9B0, 0x7802, 0xC9B1, 0x6740, 0xC9B2, 0x5239, 0xC9B3, 0x6C99, 0xC9B4, 0x7EB1, 0xC9B5, 0x50BB, + 0xC9B6, 0x5565, 0xC9B7, 0x715E, 0xC9B8, 0x7B5B, 0xC9B9, 0x6652, 0xC9BA, 0x73CA, 0xC9BB, 0x82EB, 0xC9BC, 0x6749, 0xC9BD, 0x5C71, + 0xC9BE, 0x5220, 0xC9BF, 0x717D, 0xC9C0, 0x886B, 0xC9C1, 0x95EA, 0xC9C2, 0x9655, 0xC9C3, 0x64C5, 0xC9C4, 0x8D61, 0xC9C5, 0x81B3, + 0xC9C6, 0x5584, 0xC9C7, 0x6C55, 0xC9C8, 0x6247, 0xC9C9, 0x7F2E, 0xC9CA, 0x5892, 0xC9CB, 0x4F24, 0xC9CC, 0x5546, 0xC9CD, 0x8D4F, + 0xC9CE, 0x664C, 0xC9CF, 0x4E0A, 0xC9D0, 0x5C1A, 0xC9D1, 0x88F3, 0xC9D2, 0x68A2, 0xC9D3, 0x634E, 0xC9D4, 0x7A0D, 0xC9D5, 0x70E7, + 0xC9D6, 0x828D, 0xC9D7, 0x52FA, 0xC9D8, 0x97F6, 0xC9D9, 0x5C11, 0xC9DA, 0x54E8, 0xC9DB, 0x90B5, 0xC9DC, 0x7ECD, 0xC9DD, 0x5962, + 0xC9DE, 0x8D4A, 0xC9DF, 0x86C7, 0xC9E0, 0x820C, 0xC9E1, 0x820D, 0xC9E2, 0x8D66, 0xC9E3, 0x6444, 0xC9E4, 0x5C04, 0xC9E5, 0x6151, + 0xC9E6, 0x6D89, 0xC9E7, 0x793E, 0xC9E8, 0x8BBE, 0xC9E9, 0x7837, 0xC9EA, 0x7533, 0xC9EB, 0x547B, 0xC9EC, 0x4F38, 0xC9ED, 0x8EAB, + 0xC9EE, 0x6DF1, 0xC9EF, 0x5A20, 0xC9F0, 0x7EC5, 0xC9F1, 0x795E, 0xC9F2, 0x6C88, 0xC9F3, 0x5BA1, 0xC9F4, 0x5A76, 0xC9F5, 0x751A, + 0xC9F6, 0x80BE, 0xC9F7, 0x614E, 0xC9F8, 0x6E17, 0xC9F9, 0x58F0, 0xC9FA, 0x751F, 0xC9FB, 0x7525, 0xC9FC, 0x7272, 0xC9FD, 0x5347, + 0xC9FE, 0x7EF3, 0xCA40, 0x8503, 0xCA41, 0x8504, 0xCA42, 0x8505, 0xCA43, 0x8506, 0xCA44, 0x8507, 0xCA45, 0x8508, 0xCA46, 0x8509, + 0xCA47, 0x850A, 0xCA48, 0x850B, 0xCA49, 0x850D, 0xCA4A, 0x850E, 0xCA4B, 0x850F, 0xCA4C, 0x8510, 0xCA4D, 0x8512, 0xCA4E, 0x8514, + 0xCA4F, 0x8515, 0xCA50, 0x8516, 0xCA51, 0x8518, 0xCA52, 0x8519, 0xCA53, 0x851B, 0xCA54, 0x851C, 0xCA55, 0x851D, 0xCA56, 0x851E, + 0xCA57, 0x8520, 0xCA58, 0x8522, 0xCA59, 0x8523, 0xCA5A, 0x8524, 0xCA5B, 0x8525, 0xCA5C, 0x8526, 0xCA5D, 0x8527, 0xCA5E, 0x8528, + 0xCA5F, 0x8529, 0xCA60, 0x852A, 0xCA61, 0x852D, 0xCA62, 0x852E, 0xCA63, 0x852F, 0xCA64, 0x8530, 0xCA65, 0x8531, 0xCA66, 0x8532, + 0xCA67, 0x8533, 0xCA68, 0x8534, 0xCA69, 0x8535, 0xCA6A, 0x8536, 0xCA6B, 0x853E, 0xCA6C, 0x853F, 0xCA6D, 0x8540, 0xCA6E, 0x8541, + 0xCA6F, 0x8542, 0xCA70, 0x8544, 0xCA71, 0x8545, 0xCA72, 0x8546, 0xCA73, 0x8547, 0xCA74, 0x854B, 0xCA75, 0x854C, 0xCA76, 0x854D, + 0xCA77, 0x854E, 0xCA78, 0x854F, 0xCA79, 0x8550, 0xCA7A, 0x8551, 0xCA7B, 0x8552, 0xCA7C, 0x8553, 0xCA7D, 0x8554, 0xCA7E, 0x8555, + 0xCA80, 0x8557, 0xCA81, 0x8558, 0xCA82, 0x855A, 0xCA83, 0x855B, 0xCA84, 0x855C, 0xCA85, 0x855D, 0xCA86, 0x855F, 0xCA87, 0x8560, + 0xCA88, 0x8561, 0xCA89, 0x8562, 0xCA8A, 0x8563, 0xCA8B, 0x8565, 0xCA8C, 0x8566, 0xCA8D, 0x8567, 0xCA8E, 0x8569, 0xCA8F, 0x856A, + 0xCA90, 0x856B, 0xCA91, 0x856C, 0xCA92, 0x856D, 0xCA93, 0x856E, 0xCA94, 0x856F, 0xCA95, 0x8570, 0xCA96, 0x8571, 0xCA97, 0x8573, + 0xCA98, 0x8575, 0xCA99, 0x8576, 0xCA9A, 0x8577, 0xCA9B, 0x8578, 0xCA9C, 0x857C, 0xCA9D, 0x857D, 0xCA9E, 0x857F, 0xCA9F, 0x8580, + 0xCAA0, 0x8581, 0xCAA1, 0x7701, 0xCAA2, 0x76DB, 0xCAA3, 0x5269, 0xCAA4, 0x80DC, 0xCAA5, 0x5723, 0xCAA6, 0x5E08, 0xCAA7, 0x5931, + 0xCAA8, 0x72EE, 0xCAA9, 0x65BD, 0xCAAA, 0x6E7F, 0xCAAB, 0x8BD7, 0xCAAC, 0x5C38, 0xCAAD, 0x8671, 0xCAAE, 0x5341, 0xCAAF, 0x77F3, + 0xCAB0, 0x62FE, 0xCAB1, 0x65F6, 0xCAB2, 0x4EC0, 0xCAB3, 0x98DF, 0xCAB4, 0x8680, 0xCAB5, 0x5B9E, 0xCAB6, 0x8BC6, 0xCAB7, 0x53F2, + 0xCAB8, 0x77E2, 0xCAB9, 0x4F7F, 0xCABA, 0x5C4E, 0xCABB, 0x9A76, 0xCABC, 0x59CB, 0xCABD, 0x5F0F, 0xCABE, 0x793A, 0xCABF, 0x58EB, + 0xCAC0, 0x4E16, 0xCAC1, 0x67FF, 0xCAC2, 0x4E8B, 0xCAC3, 0x62ED, 0xCAC4, 0x8A93, 0xCAC5, 0x901D, 0xCAC6, 0x52BF, 0xCAC7, 0x662F, + 0xCAC8, 0x55DC, 0xCAC9, 0x566C, 0xCACA, 0x9002, 0xCACB, 0x4ED5, 0xCACC, 0x4F8D, 0xCACD, 0x91CA, 0xCACE, 0x9970, 0xCACF, 0x6C0F, + 0xCAD0, 0x5E02, 0xCAD1, 0x6043, 0xCAD2, 0x5BA4, 0xCAD3, 0x89C6, 0xCAD4, 0x8BD5, 0xCAD5, 0x6536, 0xCAD6, 0x624B, 0xCAD7, 0x9996, + 0xCAD8, 0x5B88, 0xCAD9, 0x5BFF, 0xCADA, 0x6388, 0xCADB, 0x552E, 0xCADC, 0x53D7, 0xCADD, 0x7626, 0xCADE, 0x517D, 0xCADF, 0x852C, + 0xCAE0, 0x67A2, 0xCAE1, 0x68B3, 0xCAE2, 0x6B8A, 0xCAE3, 0x6292, 0xCAE4, 0x8F93, 0xCAE5, 0x53D4, 0xCAE6, 0x8212, 0xCAE7, 0x6DD1, + 0xCAE8, 0x758F, 0xCAE9, 0x4E66, 0xCAEA, 0x8D4E, 0xCAEB, 0x5B70, 0xCAEC, 0x719F, 0xCAED, 0x85AF, 0xCAEE, 0x6691, 0xCAEF, 0x66D9, + 0xCAF0, 0x7F72, 0xCAF1, 0x8700, 0xCAF2, 0x9ECD, 0xCAF3, 0x9F20, 0xCAF4, 0x5C5E, 0xCAF5, 0x672F, 0xCAF6, 0x8FF0, 0xCAF7, 0x6811, + 0xCAF8, 0x675F, 0xCAF9, 0x620D, 0xCAFA, 0x7AD6, 0xCAFB, 0x5885, 0xCAFC, 0x5EB6, 0xCAFD, 0x6570, 0xCAFE, 0x6F31, 0xCB40, 0x8582, + 0xCB41, 0x8583, 0xCB42, 0x8586, 0xCB43, 0x8588, 0xCB44, 0x8589, 0xCB45, 0x858A, 0xCB46, 0x858B, 0xCB47, 0x858C, 0xCB48, 0x858D, + 0xCB49, 0x858E, 0xCB4A, 0x8590, 0xCB4B, 0x8591, 0xCB4C, 0x8592, 0xCB4D, 0x8593, 0xCB4E, 0x8594, 0xCB4F, 0x8595, 0xCB50, 0x8596, + 0xCB51, 0x8597, 0xCB52, 0x8598, 0xCB53, 0x8599, 0xCB54, 0x859A, 0xCB55, 0x859D, 0xCB56, 0x859E, 0xCB57, 0x859F, 0xCB58, 0x85A0, + 0xCB59, 0x85A1, 0xCB5A, 0x85A2, 0xCB5B, 0x85A3, 0xCB5C, 0x85A5, 0xCB5D, 0x85A6, 0xCB5E, 0x85A7, 0xCB5F, 0x85A9, 0xCB60, 0x85AB, + 0xCB61, 0x85AC, 0xCB62, 0x85AD, 0xCB63, 0x85B1, 0xCB64, 0x85B2, 0xCB65, 0x85B3, 0xCB66, 0x85B4, 0xCB67, 0x85B5, 0xCB68, 0x85B6, + 0xCB69, 0x85B8, 0xCB6A, 0x85BA, 0xCB6B, 0x85BB, 0xCB6C, 0x85BC, 0xCB6D, 0x85BD, 0xCB6E, 0x85BE, 0xCB6F, 0x85BF, 0xCB70, 0x85C0, + 0xCB71, 0x85C2, 0xCB72, 0x85C3, 0xCB73, 0x85C4, 0xCB74, 0x85C5, 0xCB75, 0x85C6, 0xCB76, 0x85C7, 0xCB77, 0x85C8, 0xCB78, 0x85CA, + 0xCB79, 0x85CB, 0xCB7A, 0x85CC, 0xCB7B, 0x85CD, 0xCB7C, 0x85CE, 0xCB7D, 0x85D1, 0xCB7E, 0x85D2, 0xCB80, 0x85D4, 0xCB81, 0x85D6, + 0xCB82, 0x85D7, 0xCB83, 0x85D8, 0xCB84, 0x85D9, 0xCB85, 0x85DA, 0xCB86, 0x85DB, 0xCB87, 0x85DD, 0xCB88, 0x85DE, 0xCB89, 0x85DF, + 0xCB8A, 0x85E0, 0xCB8B, 0x85E1, 0xCB8C, 0x85E2, 0xCB8D, 0x85E3, 0xCB8E, 0x85E5, 0xCB8F, 0x85E6, 0xCB90, 0x85E7, 0xCB91, 0x85E8, + 0xCB92, 0x85EA, 0xCB93, 0x85EB, 0xCB94, 0x85EC, 0xCB95, 0x85ED, 0xCB96, 0x85EE, 0xCB97, 0x85EF, 0xCB98, 0x85F0, 0xCB99, 0x85F1, + 0xCB9A, 0x85F2, 0xCB9B, 0x85F3, 0xCB9C, 0x85F4, 0xCB9D, 0x85F5, 0xCB9E, 0x85F6, 0xCB9F, 0x85F7, 0xCBA0, 0x85F8, 0xCBA1, 0x6055, + 0xCBA2, 0x5237, 0xCBA3, 0x800D, 0xCBA4, 0x6454, 0xCBA5, 0x8870, 0xCBA6, 0x7529, 0xCBA7, 0x5E05, 0xCBA8, 0x6813, 0xCBA9, 0x62F4, + 0xCBAA, 0x971C, 0xCBAB, 0x53CC, 0xCBAC, 0x723D, 0xCBAD, 0x8C01, 0xCBAE, 0x6C34, 0xCBAF, 0x7761, 0xCBB0, 0x7A0E, 0xCBB1, 0x542E, + 0xCBB2, 0x77AC, 0xCBB3, 0x987A, 0xCBB4, 0x821C, 0xCBB5, 0x8BF4, 0xCBB6, 0x7855, 0xCBB7, 0x6714, 0xCBB8, 0x70C1, 0xCBB9, 0x65AF, + 0xCBBA, 0x6495, 0xCBBB, 0x5636, 0xCBBC, 0x601D, 0xCBBD, 0x79C1, 0xCBBE, 0x53F8, 0xCBBF, 0x4E1D, 0xCBC0, 0x6B7B, 0xCBC1, 0x8086, + 0xCBC2, 0x5BFA, 0xCBC3, 0x55E3, 0xCBC4, 0x56DB, 0xCBC5, 0x4F3A, 0xCBC6, 0x4F3C, 0xCBC7, 0x9972, 0xCBC8, 0x5DF3, 0xCBC9, 0x677E, + 0xCBCA, 0x8038, 0xCBCB, 0x6002, 0xCBCC, 0x9882, 0xCBCD, 0x9001, 0xCBCE, 0x5B8B, 0xCBCF, 0x8BBC, 0xCBD0, 0x8BF5, 0xCBD1, 0x641C, + 0xCBD2, 0x8258, 0xCBD3, 0x64DE, 0xCBD4, 0x55FD, 0xCBD5, 0x82CF, 0xCBD6, 0x9165, 0xCBD7, 0x4FD7, 0xCBD8, 0x7D20, 0xCBD9, 0x901F, + 0xCBDA, 0x7C9F, 0xCBDB, 0x50F3, 0xCBDC, 0x5851, 0xCBDD, 0x6EAF, 0xCBDE, 0x5BBF, 0xCBDF, 0x8BC9, 0xCBE0, 0x8083, 0xCBE1, 0x9178, + 0xCBE2, 0x849C, 0xCBE3, 0x7B97, 0xCBE4, 0x867D, 0xCBE5, 0x968B, 0xCBE6, 0x968F, 0xCBE7, 0x7EE5, 0xCBE8, 0x9AD3, 0xCBE9, 0x788E, + 0xCBEA, 0x5C81, 0xCBEB, 0x7A57, 0xCBEC, 0x9042, 0xCBED, 0x96A7, 0xCBEE, 0x795F, 0xCBEF, 0x5B59, 0xCBF0, 0x635F, 0xCBF1, 0x7B0B, + 0xCBF2, 0x84D1, 0xCBF3, 0x68AD, 0xCBF4, 0x5506, 0xCBF5, 0x7F29, 0xCBF6, 0x7410, 0xCBF7, 0x7D22, 0xCBF8, 0x9501, 0xCBF9, 0x6240, + 0xCBFA, 0x584C, 0xCBFB, 0x4ED6, 0xCBFC, 0x5B83, 0xCBFD, 0x5979, 0xCBFE, 0x5854, 0xCC40, 0x85F9, 0xCC41, 0x85FA, 0xCC42, 0x85FC, + 0xCC43, 0x85FD, 0xCC44, 0x85FE, 0xCC45, 0x8600, 0xCC46, 0x8601, 0xCC47, 0x8602, 0xCC48, 0x8603, 0xCC49, 0x8604, 0xCC4A, 0x8606, + 0xCC4B, 0x8607, 0xCC4C, 0x8608, 0xCC4D, 0x8609, 0xCC4E, 0x860A, 0xCC4F, 0x860B, 0xCC50, 0x860C, 0xCC51, 0x860D, 0xCC52, 0x860E, + 0xCC53, 0x860F, 0xCC54, 0x8610, 0xCC55, 0x8612, 0xCC56, 0x8613, 0xCC57, 0x8614, 0xCC58, 0x8615, 0xCC59, 0x8617, 0xCC5A, 0x8618, + 0xCC5B, 0x8619, 0xCC5C, 0x861A, 0xCC5D, 0x861B, 0xCC5E, 0x861C, 0xCC5F, 0x861D, 0xCC60, 0x861E, 0xCC61, 0x861F, 0xCC62, 0x8620, + 0xCC63, 0x8621, 0xCC64, 0x8622, 0xCC65, 0x8623, 0xCC66, 0x8624, 0xCC67, 0x8625, 0xCC68, 0x8626, 0xCC69, 0x8628, 0xCC6A, 0x862A, + 0xCC6B, 0x862B, 0xCC6C, 0x862C, 0xCC6D, 0x862D, 0xCC6E, 0x862E, 0xCC6F, 0x862F, 0xCC70, 0x8630, 0xCC71, 0x8631, 0xCC72, 0x8632, + 0xCC73, 0x8633, 0xCC74, 0x8634, 0xCC75, 0x8635, 0xCC76, 0x8636, 0xCC77, 0x8637, 0xCC78, 0x8639, 0xCC79, 0x863A, 0xCC7A, 0x863B, + 0xCC7B, 0x863D, 0xCC7C, 0x863E, 0xCC7D, 0x863F, 0xCC7E, 0x8640, 0xCC80, 0x8641, 0xCC81, 0x8642, 0xCC82, 0x8643, 0xCC83, 0x8644, + 0xCC84, 0x8645, 0xCC85, 0x8646, 0xCC86, 0x8647, 0xCC87, 0x8648, 0xCC88, 0x8649, 0xCC89, 0x864A, 0xCC8A, 0x864B, 0xCC8B, 0x864C, + 0xCC8C, 0x8652, 0xCC8D, 0x8653, 0xCC8E, 0x8655, 0xCC8F, 0x8656, 0xCC90, 0x8657, 0xCC91, 0x8658, 0xCC92, 0x8659, 0xCC93, 0x865B, + 0xCC94, 0x865C, 0xCC95, 0x865D, 0xCC96, 0x865F, 0xCC97, 0x8660, 0xCC98, 0x8661, 0xCC99, 0x8663, 0xCC9A, 0x8664, 0xCC9B, 0x8665, + 0xCC9C, 0x8666, 0xCC9D, 0x8667, 0xCC9E, 0x8668, 0xCC9F, 0x8669, 0xCCA0, 0x866A, 0xCCA1, 0x736D, 0xCCA2, 0x631E, 0xCCA3, 0x8E4B, + 0xCCA4, 0x8E0F, 0xCCA5, 0x80CE, 0xCCA6, 0x82D4, 0xCCA7, 0x62AC, 0xCCA8, 0x53F0, 0xCCA9, 0x6CF0, 0xCCAA, 0x915E, 0xCCAB, 0x592A, + 0xCCAC, 0x6001, 0xCCAD, 0x6C70, 0xCCAE, 0x574D, 0xCCAF, 0x644A, 0xCCB0, 0x8D2A, 0xCCB1, 0x762B, 0xCCB2, 0x6EE9, 0xCCB3, 0x575B, + 0xCCB4, 0x6A80, 0xCCB5, 0x75F0, 0xCCB6, 0x6F6D, 0xCCB7, 0x8C2D, 0xCCB8, 0x8C08, 0xCCB9, 0x5766, 0xCCBA, 0x6BEF, 0xCCBB, 0x8892, + 0xCCBC, 0x78B3, 0xCCBD, 0x63A2, 0xCCBE, 0x53F9, 0xCCBF, 0x70AD, 0xCCC0, 0x6C64, 0xCCC1, 0x5858, 0xCCC2, 0x642A, 0xCCC3, 0x5802, + 0xCCC4, 0x68E0, 0xCCC5, 0x819B, 0xCCC6, 0x5510, 0xCCC7, 0x7CD6, 0xCCC8, 0x5018, 0xCCC9, 0x8EBA, 0xCCCA, 0x6DCC, 0xCCCB, 0x8D9F, + 0xCCCC, 0x70EB, 0xCCCD, 0x638F, 0xCCCE, 0x6D9B, 0xCCCF, 0x6ED4, 0xCCD0, 0x7EE6, 0xCCD1, 0x8404, 0xCCD2, 0x6843, 0xCCD3, 0x9003, + 0xCCD4, 0x6DD8, 0xCCD5, 0x9676, 0xCCD6, 0x8BA8, 0xCCD7, 0x5957, 0xCCD8, 0x7279, 0xCCD9, 0x85E4, 0xCCDA, 0x817E, 0xCCDB, 0x75BC, + 0xCCDC, 0x8A8A, 0xCCDD, 0x68AF, 0xCCDE, 0x5254, 0xCCDF, 0x8E22, 0xCCE0, 0x9511, 0xCCE1, 0x63D0, 0xCCE2, 0x9898, 0xCCE3, 0x8E44, + 0xCCE4, 0x557C, 0xCCE5, 0x4F53, 0xCCE6, 0x66FF, 0xCCE7, 0x568F, 0xCCE8, 0x60D5, 0xCCE9, 0x6D95, 0xCCEA, 0x5243, 0xCCEB, 0x5C49, + 0xCCEC, 0x5929, 0xCCED, 0x6DFB, 0xCCEE, 0x586B, 0xCCEF, 0x7530, 0xCCF0, 0x751C, 0xCCF1, 0x606C, 0xCCF2, 0x8214, 0xCCF3, 0x8146, + 0xCCF4, 0x6311, 0xCCF5, 0x6761, 0xCCF6, 0x8FE2, 0xCCF7, 0x773A, 0xCCF8, 0x8DF3, 0xCCF9, 0x8D34, 0xCCFA, 0x94C1, 0xCCFB, 0x5E16, + 0xCCFC, 0x5385, 0xCCFD, 0x542C, 0xCCFE, 0x70C3, 0xCD40, 0x866D, 0xCD41, 0x866F, 0xCD42, 0x8670, 0xCD43, 0x8672, 0xCD44, 0x8673, + 0xCD45, 0x8674, 0xCD46, 0x8675, 0xCD47, 0x8676, 0xCD48, 0x8677, 0xCD49, 0x8678, 0xCD4A, 0x8683, 0xCD4B, 0x8684, 0xCD4C, 0x8685, + 0xCD4D, 0x8686, 0xCD4E, 0x8687, 0xCD4F, 0x8688, 0xCD50, 0x8689, 0xCD51, 0x868E, 0xCD52, 0x868F, 0xCD53, 0x8690, 0xCD54, 0x8691, + 0xCD55, 0x8692, 0xCD56, 0x8694, 0xCD57, 0x8696, 0xCD58, 0x8697, 0xCD59, 0x8698, 0xCD5A, 0x8699, 0xCD5B, 0x869A, 0xCD5C, 0x869B, + 0xCD5D, 0x869E, 0xCD5E, 0x869F, 0xCD5F, 0x86A0, 0xCD60, 0x86A1, 0xCD61, 0x86A2, 0xCD62, 0x86A5, 0xCD63, 0x86A6, 0xCD64, 0x86AB, + 0xCD65, 0x86AD, 0xCD66, 0x86AE, 0xCD67, 0x86B2, 0xCD68, 0x86B3, 0xCD69, 0x86B7, 0xCD6A, 0x86B8, 0xCD6B, 0x86B9, 0xCD6C, 0x86BB, + 0xCD6D, 0x86BC, 0xCD6E, 0x86BD, 0xCD6F, 0x86BE, 0xCD70, 0x86BF, 0xCD71, 0x86C1, 0xCD72, 0x86C2, 0xCD73, 0x86C3, 0xCD74, 0x86C5, + 0xCD75, 0x86C8, 0xCD76, 0x86CC, 0xCD77, 0x86CD, 0xCD78, 0x86D2, 0xCD79, 0x86D3, 0xCD7A, 0x86D5, 0xCD7B, 0x86D6, 0xCD7C, 0x86D7, + 0xCD7D, 0x86DA, 0xCD7E, 0x86DC, 0xCD80, 0x86DD, 0xCD81, 0x86E0, 0xCD82, 0x86E1, 0xCD83, 0x86E2, 0xCD84, 0x86E3, 0xCD85, 0x86E5, + 0xCD86, 0x86E6, 0xCD87, 0x86E7, 0xCD88, 0x86E8, 0xCD89, 0x86EA, 0xCD8A, 0x86EB, 0xCD8B, 0x86EC, 0xCD8C, 0x86EF, 0xCD8D, 0x86F5, + 0xCD8E, 0x86F6, 0xCD8F, 0x86F7, 0xCD90, 0x86FA, 0xCD91, 0x86FB, 0xCD92, 0x86FC, 0xCD93, 0x86FD, 0xCD94, 0x86FF, 0xCD95, 0x8701, + 0xCD96, 0x8704, 0xCD97, 0x8705, 0xCD98, 0x8706, 0xCD99, 0x870B, 0xCD9A, 0x870C, 0xCD9B, 0x870E, 0xCD9C, 0x870F, 0xCD9D, 0x8710, + 0xCD9E, 0x8711, 0xCD9F, 0x8714, 0xCDA0, 0x8716, 0xCDA1, 0x6C40, 0xCDA2, 0x5EF7, 0xCDA3, 0x505C, 0xCDA4, 0x4EAD, 0xCDA5, 0x5EAD, + 0xCDA6, 0x633A, 0xCDA7, 0x8247, 0xCDA8, 0x901A, 0xCDA9, 0x6850, 0xCDAA, 0x916E, 0xCDAB, 0x77B3, 0xCDAC, 0x540C, 0xCDAD, 0x94DC, + 0xCDAE, 0x5F64, 0xCDAF, 0x7AE5, 0xCDB0, 0x6876, 0xCDB1, 0x6345, 0xCDB2, 0x7B52, 0xCDB3, 0x7EDF, 0xCDB4, 0x75DB, 0xCDB5, 0x5077, + 0xCDB6, 0x6295, 0xCDB7, 0x5934, 0xCDB8, 0x900F, 0xCDB9, 0x51F8, 0xCDBA, 0x79C3, 0xCDBB, 0x7A81, 0xCDBC, 0x56FE, 0xCDBD, 0x5F92, + 0xCDBE, 0x9014, 0xCDBF, 0x6D82, 0xCDC0, 0x5C60, 0xCDC1, 0x571F, 0xCDC2, 0x5410, 0xCDC3, 0x5154, 0xCDC4, 0x6E4D, 0xCDC5, 0x56E2, + 0xCDC6, 0x63A8, 0xCDC7, 0x9893, 0xCDC8, 0x817F, 0xCDC9, 0x8715, 0xCDCA, 0x892A, 0xCDCB, 0x9000, 0xCDCC, 0x541E, 0xCDCD, 0x5C6F, + 0xCDCE, 0x81C0, 0xCDCF, 0x62D6, 0xCDD0, 0x6258, 0xCDD1, 0x8131, 0xCDD2, 0x9E35, 0xCDD3, 0x9640, 0xCDD4, 0x9A6E, 0xCDD5, 0x9A7C, + 0xCDD6, 0x692D, 0xCDD7, 0x59A5, 0xCDD8, 0x62D3, 0xCDD9, 0x553E, 0xCDDA, 0x6316, 0xCDDB, 0x54C7, 0xCDDC, 0x86D9, 0xCDDD, 0x6D3C, + 0xCDDE, 0x5A03, 0xCDDF, 0x74E6, 0xCDE0, 0x889C, 0xCDE1, 0x6B6A, 0xCDE2, 0x5916, 0xCDE3, 0x8C4C, 0xCDE4, 0x5F2F, 0xCDE5, 0x6E7E, + 0xCDE6, 0x73A9, 0xCDE7, 0x987D, 0xCDE8, 0x4E38, 0xCDE9, 0x70F7, 0xCDEA, 0x5B8C, 0xCDEB, 0x7897, 0xCDEC, 0x633D, 0xCDED, 0x665A, + 0xCDEE, 0x7696, 0xCDEF, 0x60CB, 0xCDF0, 0x5B9B, 0xCDF1, 0x5A49, 0xCDF2, 0x4E07, 0xCDF3, 0x8155, 0xCDF4, 0x6C6A, 0xCDF5, 0x738B, + 0xCDF6, 0x4EA1, 0xCDF7, 0x6789, 0xCDF8, 0x7F51, 0xCDF9, 0x5F80, 0xCDFA, 0x65FA, 0xCDFB, 0x671B, 0xCDFC, 0x5FD8, 0xCDFD, 0x5984, + 0xCDFE, 0x5A01, 0xCE40, 0x8719, 0xCE41, 0x871B, 0xCE42, 0x871D, 0xCE43, 0x871F, 0xCE44, 0x8720, 0xCE45, 0x8724, 0xCE46, 0x8726, + 0xCE47, 0x8727, 0xCE48, 0x8728, 0xCE49, 0x872A, 0xCE4A, 0x872B, 0xCE4B, 0x872C, 0xCE4C, 0x872D, 0xCE4D, 0x872F, 0xCE4E, 0x8730, + 0xCE4F, 0x8732, 0xCE50, 0x8733, 0xCE51, 0x8735, 0xCE52, 0x8736, 0xCE53, 0x8738, 0xCE54, 0x8739, 0xCE55, 0x873A, 0xCE56, 0x873C, + 0xCE57, 0x873D, 0xCE58, 0x8740, 0xCE59, 0x8741, 0xCE5A, 0x8742, 0xCE5B, 0x8743, 0xCE5C, 0x8744, 0xCE5D, 0x8745, 0xCE5E, 0x8746, + 0xCE5F, 0x874A, 0xCE60, 0x874B, 0xCE61, 0x874D, 0xCE62, 0x874F, 0xCE63, 0x8750, 0xCE64, 0x8751, 0xCE65, 0x8752, 0xCE66, 0x8754, + 0xCE67, 0x8755, 0xCE68, 0x8756, 0xCE69, 0x8758, 0xCE6A, 0x875A, 0xCE6B, 0x875B, 0xCE6C, 0x875C, 0xCE6D, 0x875D, 0xCE6E, 0x875E, + 0xCE6F, 0x875F, 0xCE70, 0x8761, 0xCE71, 0x8762, 0xCE72, 0x8766, 0xCE73, 0x8767, 0xCE74, 0x8768, 0xCE75, 0x8769, 0xCE76, 0x876A, + 0xCE77, 0x876B, 0xCE78, 0x876C, 0xCE79, 0x876D, 0xCE7A, 0x876F, 0xCE7B, 0x8771, 0xCE7C, 0x8772, 0xCE7D, 0x8773, 0xCE7E, 0x8775, + 0xCE80, 0x8777, 0xCE81, 0x8778, 0xCE82, 0x8779, 0xCE83, 0x877A, 0xCE84, 0x877F, 0xCE85, 0x8780, 0xCE86, 0x8781, 0xCE87, 0x8784, + 0xCE88, 0x8786, 0xCE89, 0x8787, 0xCE8A, 0x8789, 0xCE8B, 0x878A, 0xCE8C, 0x878C, 0xCE8D, 0x878E, 0xCE8E, 0x878F, 0xCE8F, 0x8790, + 0xCE90, 0x8791, 0xCE91, 0x8792, 0xCE92, 0x8794, 0xCE93, 0x8795, 0xCE94, 0x8796, 0xCE95, 0x8798, 0xCE96, 0x8799, 0xCE97, 0x879A, + 0xCE98, 0x879B, 0xCE99, 0x879C, 0xCE9A, 0x879D, 0xCE9B, 0x879E, 0xCE9C, 0x87A0, 0xCE9D, 0x87A1, 0xCE9E, 0x87A2, 0xCE9F, 0x87A3, + 0xCEA0, 0x87A4, 0xCEA1, 0x5DCD, 0xCEA2, 0x5FAE, 0xCEA3, 0x5371, 0xCEA4, 0x97E6, 0xCEA5, 0x8FDD, 0xCEA6, 0x6845, 0xCEA7, 0x56F4, + 0xCEA8, 0x552F, 0xCEA9, 0x60DF, 0xCEAA, 0x4E3A, 0xCEAB, 0x6F4D, 0xCEAC, 0x7EF4, 0xCEAD, 0x82C7, 0xCEAE, 0x840E, 0xCEAF, 0x59D4, + 0xCEB0, 0x4F1F, 0xCEB1, 0x4F2A, 0xCEB2, 0x5C3E, 0xCEB3, 0x7EAC, 0xCEB4, 0x672A, 0xCEB5, 0x851A, 0xCEB6, 0x5473, 0xCEB7, 0x754F, + 0xCEB8, 0x80C3, 0xCEB9, 0x5582, 0xCEBA, 0x9B4F, 0xCEBB, 0x4F4D, 0xCEBC, 0x6E2D, 0xCEBD, 0x8C13, 0xCEBE, 0x5C09, 0xCEBF, 0x6170, + 0xCEC0, 0x536B, 0xCEC1, 0x761F, 0xCEC2, 0x6E29, 0xCEC3, 0x868A, 0xCEC4, 0x6587, 0xCEC5, 0x95FB, 0xCEC6, 0x7EB9, 0xCEC7, 0x543B, + 0xCEC8, 0x7A33, 0xCEC9, 0x7D0A, 0xCECA, 0x95EE, 0xCECB, 0x55E1, 0xCECC, 0x7FC1, 0xCECD, 0x74EE, 0xCECE, 0x631D, 0xCECF, 0x8717, + 0xCED0, 0x6DA1, 0xCED1, 0x7A9D, 0xCED2, 0x6211, 0xCED3, 0x65A1, 0xCED4, 0x5367, 0xCED5, 0x63E1, 0xCED6, 0x6C83, 0xCED7, 0x5DEB, + 0xCED8, 0x545C, 0xCED9, 0x94A8, 0xCEDA, 0x4E4C, 0xCEDB, 0x6C61, 0xCEDC, 0x8BEC, 0xCEDD, 0x5C4B, 0xCEDE, 0x65E0, 0xCEDF, 0x829C, + 0xCEE0, 0x68A7, 0xCEE1, 0x543E, 0xCEE2, 0x5434, 0xCEE3, 0x6BCB, 0xCEE4, 0x6B66, 0xCEE5, 0x4E94, 0xCEE6, 0x6342, 0xCEE7, 0x5348, + 0xCEE8, 0x821E, 0xCEE9, 0x4F0D, 0xCEEA, 0x4FAE, 0xCEEB, 0x575E, 0xCEEC, 0x620A, 0xCEED, 0x96FE, 0xCEEE, 0x6664, 0xCEEF, 0x7269, + 0xCEF0, 0x52FF, 0xCEF1, 0x52A1, 0xCEF2, 0x609F, 0xCEF3, 0x8BEF, 0xCEF4, 0x6614, 0xCEF5, 0x7199, 0xCEF6, 0x6790, 0xCEF7, 0x897F, + 0xCEF8, 0x7852, 0xCEF9, 0x77FD, 0xCEFA, 0x6670, 0xCEFB, 0x563B, 0xCEFC, 0x5438, 0xCEFD, 0x9521, 0xCEFE, 0x727A, 0xCF40, 0x87A5, + 0xCF41, 0x87A6, 0xCF42, 0x87A7, 0xCF43, 0x87A9, 0xCF44, 0x87AA, 0xCF45, 0x87AE, 0xCF46, 0x87B0, 0xCF47, 0x87B1, 0xCF48, 0x87B2, + 0xCF49, 0x87B4, 0xCF4A, 0x87B6, 0xCF4B, 0x87B7, 0xCF4C, 0x87B8, 0xCF4D, 0x87B9, 0xCF4E, 0x87BB, 0xCF4F, 0x87BC, 0xCF50, 0x87BE, + 0xCF51, 0x87BF, 0xCF52, 0x87C1, 0xCF53, 0x87C2, 0xCF54, 0x87C3, 0xCF55, 0x87C4, 0xCF56, 0x87C5, 0xCF57, 0x87C7, 0xCF58, 0x87C8, + 0xCF59, 0x87C9, 0xCF5A, 0x87CC, 0xCF5B, 0x87CD, 0xCF5C, 0x87CE, 0xCF5D, 0x87CF, 0xCF5E, 0x87D0, 0xCF5F, 0x87D4, 0xCF60, 0x87D5, + 0xCF61, 0x87D6, 0xCF62, 0x87D7, 0xCF63, 0x87D8, 0xCF64, 0x87D9, 0xCF65, 0x87DA, 0xCF66, 0x87DC, 0xCF67, 0x87DD, 0xCF68, 0x87DE, + 0xCF69, 0x87DF, 0xCF6A, 0x87E1, 0xCF6B, 0x87E2, 0xCF6C, 0x87E3, 0xCF6D, 0x87E4, 0xCF6E, 0x87E6, 0xCF6F, 0x87E7, 0xCF70, 0x87E8, + 0xCF71, 0x87E9, 0xCF72, 0x87EB, 0xCF73, 0x87EC, 0xCF74, 0x87ED, 0xCF75, 0x87EF, 0xCF76, 0x87F0, 0xCF77, 0x87F1, 0xCF78, 0x87F2, + 0xCF79, 0x87F3, 0xCF7A, 0x87F4, 0xCF7B, 0x87F5, 0xCF7C, 0x87F6, 0xCF7D, 0x87F7, 0xCF7E, 0x87F8, 0xCF80, 0x87FA, 0xCF81, 0x87FB, + 0xCF82, 0x87FC, 0xCF83, 0x87FD, 0xCF84, 0x87FF, 0xCF85, 0x8800, 0xCF86, 0x8801, 0xCF87, 0x8802, 0xCF88, 0x8804, 0xCF89, 0x8805, + 0xCF8A, 0x8806, 0xCF8B, 0x8807, 0xCF8C, 0x8808, 0xCF8D, 0x8809, 0xCF8E, 0x880B, 0xCF8F, 0x880C, 0xCF90, 0x880D, 0xCF91, 0x880E, + 0xCF92, 0x880F, 0xCF93, 0x8810, 0xCF94, 0x8811, 0xCF95, 0x8812, 0xCF96, 0x8814, 0xCF97, 0x8817, 0xCF98, 0x8818, 0xCF99, 0x8819, + 0xCF9A, 0x881A, 0xCF9B, 0x881C, 0xCF9C, 0x881D, 0xCF9D, 0x881E, 0xCF9E, 0x881F, 0xCF9F, 0x8820, 0xCFA0, 0x8823, 0xCFA1, 0x7A00, + 0xCFA2, 0x606F, 0xCFA3, 0x5E0C, 0xCFA4, 0x6089, 0xCFA5, 0x819D, 0xCFA6, 0x5915, 0xCFA7, 0x60DC, 0xCFA8, 0x7184, 0xCFA9, 0x70EF, + 0xCFAA, 0x6EAA, 0xCFAB, 0x6C50, 0xCFAC, 0x7280, 0xCFAD, 0x6A84, 0xCFAE, 0x88AD, 0xCFAF, 0x5E2D, 0xCFB0, 0x4E60, 0xCFB1, 0x5AB3, + 0xCFB2, 0x559C, 0xCFB3, 0x94E3, 0xCFB4, 0x6D17, 0xCFB5, 0x7CFB, 0xCFB6, 0x9699, 0xCFB7, 0x620F, 0xCFB8, 0x7EC6, 0xCFB9, 0x778E, + 0xCFBA, 0x867E, 0xCFBB, 0x5323, 0xCFBC, 0x971E, 0xCFBD, 0x8F96, 0xCFBE, 0x6687, 0xCFBF, 0x5CE1, 0xCFC0, 0x4FA0, 0xCFC1, 0x72ED, + 0xCFC2, 0x4E0B, 0xCFC3, 0x53A6, 0xCFC4, 0x590F, 0xCFC5, 0x5413, 0xCFC6, 0x6380, 0xCFC7, 0x9528, 0xCFC8, 0x5148, 0xCFC9, 0x4ED9, + 0xCFCA, 0x9C9C, 0xCFCB, 0x7EA4, 0xCFCC, 0x54B8, 0xCFCD, 0x8D24, 0xCFCE, 0x8854, 0xCFCF, 0x8237, 0xCFD0, 0x95F2, 0xCFD1, 0x6D8E, + 0xCFD2, 0x5F26, 0xCFD3, 0x5ACC, 0xCFD4, 0x663E, 0xCFD5, 0x9669, 0xCFD6, 0x73B0, 0xCFD7, 0x732E, 0xCFD8, 0x53BF, 0xCFD9, 0x817A, + 0xCFDA, 0x9985, 0xCFDB, 0x7FA1, 0xCFDC, 0x5BAA, 0xCFDD, 0x9677, 0xCFDE, 0x9650, 0xCFDF, 0x7EBF, 0xCFE0, 0x76F8, 0xCFE1, 0x53A2, + 0xCFE2, 0x9576, 0xCFE3, 0x9999, 0xCFE4, 0x7BB1, 0xCFE5, 0x8944, 0xCFE6, 0x6E58, 0xCFE7, 0x4E61, 0xCFE8, 0x7FD4, 0xCFE9, 0x7965, + 0xCFEA, 0x8BE6, 0xCFEB, 0x60F3, 0xCFEC, 0x54CD, 0xCFED, 0x4EAB, 0xCFEE, 0x9879, 0xCFEF, 0x5DF7, 0xCFF0, 0x6A61, 0xCFF1, 0x50CF, + 0xCFF2, 0x5411, 0xCFF3, 0x8C61, 0xCFF4, 0x8427, 0xCFF5, 0x785D, 0xCFF6, 0x9704, 0xCFF7, 0x524A, 0xCFF8, 0x54EE, 0xCFF9, 0x56A3, + 0xCFFA, 0x9500, 0xCFFB, 0x6D88, 0xCFFC, 0x5BB5, 0xCFFD, 0x6DC6, 0xCFFE, 0x6653, 0xD040, 0x8824, 0xD041, 0x8825, 0xD042, 0x8826, + 0xD043, 0x8827, 0xD044, 0x8828, 0xD045, 0x8829, 0xD046, 0x882A, 0xD047, 0x882B, 0xD048, 0x882C, 0xD049, 0x882D, 0xD04A, 0x882E, + 0xD04B, 0x882F, 0xD04C, 0x8830, 0xD04D, 0x8831, 0xD04E, 0x8833, 0xD04F, 0x8834, 0xD050, 0x8835, 0xD051, 0x8836, 0xD052, 0x8837, + 0xD053, 0x8838, 0xD054, 0x883A, 0xD055, 0x883B, 0xD056, 0x883D, 0xD057, 0x883E, 0xD058, 0x883F, 0xD059, 0x8841, 0xD05A, 0x8842, + 0xD05B, 0x8843, 0xD05C, 0x8846, 0xD05D, 0x8847, 0xD05E, 0x8848, 0xD05F, 0x8849, 0xD060, 0x884A, 0xD061, 0x884B, 0xD062, 0x884E, + 0xD063, 0x884F, 0xD064, 0x8850, 0xD065, 0x8851, 0xD066, 0x8852, 0xD067, 0x8853, 0xD068, 0x8855, 0xD069, 0x8856, 0xD06A, 0x8858, + 0xD06B, 0x885A, 0xD06C, 0x885B, 0xD06D, 0x885C, 0xD06E, 0x885D, 0xD06F, 0x885E, 0xD070, 0x885F, 0xD071, 0x8860, 0xD072, 0x8866, + 0xD073, 0x8867, 0xD074, 0x886A, 0xD075, 0x886D, 0xD076, 0x886F, 0xD077, 0x8871, 0xD078, 0x8873, 0xD079, 0x8874, 0xD07A, 0x8875, + 0xD07B, 0x8876, 0xD07C, 0x8878, 0xD07D, 0x8879, 0xD07E, 0x887A, 0xD080, 0x887B, 0xD081, 0x887C, 0xD082, 0x8880, 0xD083, 0x8883, + 0xD084, 0x8886, 0xD085, 0x8887, 0xD086, 0x8889, 0xD087, 0x888A, 0xD088, 0x888C, 0xD089, 0x888E, 0xD08A, 0x888F, 0xD08B, 0x8890, + 0xD08C, 0x8891, 0xD08D, 0x8893, 0xD08E, 0x8894, 0xD08F, 0x8895, 0xD090, 0x8897, 0xD091, 0x8898, 0xD092, 0x8899, 0xD093, 0x889A, + 0xD094, 0x889B, 0xD095, 0x889D, 0xD096, 0x889E, 0xD097, 0x889F, 0xD098, 0x88A0, 0xD099, 0x88A1, 0xD09A, 0x88A3, 0xD09B, 0x88A5, + 0xD09C, 0x88A6, 0xD09D, 0x88A7, 0xD09E, 0x88A8, 0xD09F, 0x88A9, 0xD0A0, 0x88AA, 0xD0A1, 0x5C0F, 0xD0A2, 0x5B5D, 0xD0A3, 0x6821, + 0xD0A4, 0x8096, 0xD0A5, 0x5578, 0xD0A6, 0x7B11, 0xD0A7, 0x6548, 0xD0A8, 0x6954, 0xD0A9, 0x4E9B, 0xD0AA, 0x6B47, 0xD0AB, 0x874E, + 0xD0AC, 0x978B, 0xD0AD, 0x534F, 0xD0AE, 0x631F, 0xD0AF, 0x643A, 0xD0B0, 0x90AA, 0xD0B1, 0x659C, 0xD0B2, 0x80C1, 0xD0B3, 0x8C10, + 0xD0B4, 0x5199, 0xD0B5, 0x68B0, 0xD0B6, 0x5378, 0xD0B7, 0x87F9, 0xD0B8, 0x61C8, 0xD0B9, 0x6CC4, 0xD0BA, 0x6CFB, 0xD0BB, 0x8C22, + 0xD0BC, 0x5C51, 0xD0BD, 0x85AA, 0xD0BE, 0x82AF, 0xD0BF, 0x950C, 0xD0C0, 0x6B23, 0xD0C1, 0x8F9B, 0xD0C2, 0x65B0, 0xD0C3, 0x5FFB, + 0xD0C4, 0x5FC3, 0xD0C5, 0x4FE1, 0xD0C6, 0x8845, 0xD0C7, 0x661F, 0xD0C8, 0x8165, 0xD0C9, 0x7329, 0xD0CA, 0x60FA, 0xD0CB, 0x5174, + 0xD0CC, 0x5211, 0xD0CD, 0x578B, 0xD0CE, 0x5F62, 0xD0CF, 0x90A2, 0xD0D0, 0x884C, 0xD0D1, 0x9192, 0xD0D2, 0x5E78, 0xD0D3, 0x674F, + 0xD0D4, 0x6027, 0xD0D5, 0x59D3, 0xD0D6, 0x5144, 0xD0D7, 0x51F6, 0xD0D8, 0x80F8, 0xD0D9, 0x5308, 0xD0DA, 0x6C79, 0xD0DB, 0x96C4, + 0xD0DC, 0x718A, 0xD0DD, 0x4F11, 0xD0DE, 0x4FEE, 0xD0DF, 0x7F9E, 0xD0E0, 0x673D, 0xD0E1, 0x55C5, 0xD0E2, 0x9508, 0xD0E3, 0x79C0, + 0xD0E4, 0x8896, 0xD0E5, 0x7EE3, 0xD0E6, 0x589F, 0xD0E7, 0x620C, 0xD0E8, 0x9700, 0xD0E9, 0x865A, 0xD0EA, 0x5618, 0xD0EB, 0x987B, + 0xD0EC, 0x5F90, 0xD0ED, 0x8BB8, 0xD0EE, 0x84C4, 0xD0EF, 0x9157, 0xD0F0, 0x53D9, 0xD0F1, 0x65ED, 0xD0F2, 0x5E8F, 0xD0F3, 0x755C, + 0xD0F4, 0x6064, 0xD0F5, 0x7D6E, 0xD0F6, 0x5A7F, 0xD0F7, 0x7EEA, 0xD0F8, 0x7EED, 0xD0F9, 0x8F69, 0xD0FA, 0x55A7, 0xD0FB, 0x5BA3, + 0xD0FC, 0x60AC, 0xD0FD, 0x65CB, 0xD0FE, 0x7384, 0xD140, 0x88AC, 0xD141, 0x88AE, 0xD142, 0x88AF, 0xD143, 0x88B0, 0xD144, 0x88B2, + 0xD145, 0x88B3, 0xD146, 0x88B4, 0xD147, 0x88B5, 0xD148, 0x88B6, 0xD149, 0x88B8, 0xD14A, 0x88B9, 0xD14B, 0x88BA, 0xD14C, 0x88BB, + 0xD14D, 0x88BD, 0xD14E, 0x88BE, 0xD14F, 0x88BF, 0xD150, 0x88C0, 0xD151, 0x88C3, 0xD152, 0x88C4, 0xD153, 0x88C7, 0xD154, 0x88C8, + 0xD155, 0x88CA, 0xD156, 0x88CB, 0xD157, 0x88CC, 0xD158, 0x88CD, 0xD159, 0x88CF, 0xD15A, 0x88D0, 0xD15B, 0x88D1, 0xD15C, 0x88D3, + 0xD15D, 0x88D6, 0xD15E, 0x88D7, 0xD15F, 0x88DA, 0xD160, 0x88DB, 0xD161, 0x88DC, 0xD162, 0x88DD, 0xD163, 0x88DE, 0xD164, 0x88E0, + 0xD165, 0x88E1, 0xD166, 0x88E6, 0xD167, 0x88E7, 0xD168, 0x88E9, 0xD169, 0x88EA, 0xD16A, 0x88EB, 0xD16B, 0x88EC, 0xD16C, 0x88ED, + 0xD16D, 0x88EE, 0xD16E, 0x88EF, 0xD16F, 0x88F2, 0xD170, 0x88F5, 0xD171, 0x88F6, 0xD172, 0x88F7, 0xD173, 0x88FA, 0xD174, 0x88FB, + 0xD175, 0x88FD, 0xD176, 0x88FF, 0xD177, 0x8900, 0xD178, 0x8901, 0xD179, 0x8903, 0xD17A, 0x8904, 0xD17B, 0x8905, 0xD17C, 0x8906, + 0xD17D, 0x8907, 0xD17E, 0x8908, 0xD180, 0x8909, 0xD181, 0x890B, 0xD182, 0x890C, 0xD183, 0x890D, 0xD184, 0x890E, 0xD185, 0x890F, + 0xD186, 0x8911, 0xD187, 0x8914, 0xD188, 0x8915, 0xD189, 0x8916, 0xD18A, 0x8917, 0xD18B, 0x8918, 0xD18C, 0x891C, 0xD18D, 0x891D, + 0xD18E, 0x891E, 0xD18F, 0x891F, 0xD190, 0x8920, 0xD191, 0x8922, 0xD192, 0x8923, 0xD193, 0x8924, 0xD194, 0x8926, 0xD195, 0x8927, + 0xD196, 0x8928, 0xD197, 0x8929, 0xD198, 0x892C, 0xD199, 0x892D, 0xD19A, 0x892E, 0xD19B, 0x892F, 0xD19C, 0x8931, 0xD19D, 0x8932, + 0xD19E, 0x8933, 0xD19F, 0x8935, 0xD1A0, 0x8937, 0xD1A1, 0x9009, 0xD1A2, 0x7663, 0xD1A3, 0x7729, 0xD1A4, 0x7EDA, 0xD1A5, 0x9774, + 0xD1A6, 0x859B, 0xD1A7, 0x5B66, 0xD1A8, 0x7A74, 0xD1A9, 0x96EA, 0xD1AA, 0x8840, 0xD1AB, 0x52CB, 0xD1AC, 0x718F, 0xD1AD, 0x5FAA, + 0xD1AE, 0x65EC, 0xD1AF, 0x8BE2, 0xD1B0, 0x5BFB, 0xD1B1, 0x9A6F, 0xD1B2, 0x5DE1, 0xD1B3, 0x6B89, 0xD1B4, 0x6C5B, 0xD1B5, 0x8BAD, + 0xD1B6, 0x8BAF, 0xD1B7, 0x900A, 0xD1B8, 0x8FC5, 0xD1B9, 0x538B, 0xD1BA, 0x62BC, 0xD1BB, 0x9E26, 0xD1BC, 0x9E2D, 0xD1BD, 0x5440, + 0xD1BE, 0x4E2B, 0xD1BF, 0x82BD, 0xD1C0, 0x7259, 0xD1C1, 0x869C, 0xD1C2, 0x5D16, 0xD1C3, 0x8859, 0xD1C4, 0x6DAF, 0xD1C5, 0x96C5, + 0xD1C6, 0x54D1, 0xD1C7, 0x4E9A, 0xD1C8, 0x8BB6, 0xD1C9, 0x7109, 0xD1CA, 0x54BD, 0xD1CB, 0x9609, 0xD1CC, 0x70DF, 0xD1CD, 0x6DF9, + 0xD1CE, 0x76D0, 0xD1CF, 0x4E25, 0xD1D0, 0x7814, 0xD1D1, 0x8712, 0xD1D2, 0x5CA9, 0xD1D3, 0x5EF6, 0xD1D4, 0x8A00, 0xD1D5, 0x989C, + 0xD1D6, 0x960E, 0xD1D7, 0x708E, 0xD1D8, 0x6CBF, 0xD1D9, 0x5944, 0xD1DA, 0x63A9, 0xD1DB, 0x773C, 0xD1DC, 0x884D, 0xD1DD, 0x6F14, + 0xD1DE, 0x8273, 0xD1DF, 0x5830, 0xD1E0, 0x71D5, 0xD1E1, 0x538C, 0xD1E2, 0x781A, 0xD1E3, 0x96C1, 0xD1E4, 0x5501, 0xD1E5, 0x5F66, + 0xD1E6, 0x7130, 0xD1E7, 0x5BB4, 0xD1E8, 0x8C1A, 0xD1E9, 0x9A8C, 0xD1EA, 0x6B83, 0xD1EB, 0x592E, 0xD1EC, 0x9E2F, 0xD1ED, 0x79E7, + 0xD1EE, 0x6768, 0xD1EF, 0x626C, 0xD1F0, 0x4F6F, 0xD1F1, 0x75A1, 0xD1F2, 0x7F8A, 0xD1F3, 0x6D0B, 0xD1F4, 0x9633, 0xD1F5, 0x6C27, + 0xD1F6, 0x4EF0, 0xD1F7, 0x75D2, 0xD1F8, 0x517B, 0xD1F9, 0x6837, 0xD1FA, 0x6F3E, 0xD1FB, 0x9080, 0xD1FC, 0x8170, 0xD1FD, 0x5996, + 0xD1FE, 0x7476, 0xD240, 0x8938, 0xD241, 0x8939, 0xD242, 0x893A, 0xD243, 0x893B, 0xD244, 0x893C, 0xD245, 0x893D, 0xD246, 0x893E, + 0xD247, 0x893F, 0xD248, 0x8940, 0xD249, 0x8942, 0xD24A, 0x8943, 0xD24B, 0x8945, 0xD24C, 0x8946, 0xD24D, 0x8947, 0xD24E, 0x8948, + 0xD24F, 0x8949, 0xD250, 0x894A, 0xD251, 0x894B, 0xD252, 0x894C, 0xD253, 0x894D, 0xD254, 0x894E, 0xD255, 0x894F, 0xD256, 0x8950, + 0xD257, 0x8951, 0xD258, 0x8952, 0xD259, 0x8953, 0xD25A, 0x8954, 0xD25B, 0x8955, 0xD25C, 0x8956, 0xD25D, 0x8957, 0xD25E, 0x8958, + 0xD25F, 0x8959, 0xD260, 0x895A, 0xD261, 0x895B, 0xD262, 0x895C, 0xD263, 0x895D, 0xD264, 0x8960, 0xD265, 0x8961, 0xD266, 0x8962, + 0xD267, 0x8963, 0xD268, 0x8964, 0xD269, 0x8965, 0xD26A, 0x8967, 0xD26B, 0x8968, 0xD26C, 0x8969, 0xD26D, 0x896A, 0xD26E, 0x896B, + 0xD26F, 0x896C, 0xD270, 0x896D, 0xD271, 0x896E, 0xD272, 0x896F, 0xD273, 0x8970, 0xD274, 0x8971, 0xD275, 0x8972, 0xD276, 0x8973, + 0xD277, 0x8974, 0xD278, 0x8975, 0xD279, 0x8976, 0xD27A, 0x8977, 0xD27B, 0x8978, 0xD27C, 0x8979, 0xD27D, 0x897A, 0xD27E, 0x897C, + 0xD280, 0x897D, 0xD281, 0x897E, 0xD282, 0x8980, 0xD283, 0x8982, 0xD284, 0x8984, 0xD285, 0x8985, 0xD286, 0x8987, 0xD287, 0x8988, + 0xD288, 0x8989, 0xD289, 0x898A, 0xD28A, 0x898B, 0xD28B, 0x898C, 0xD28C, 0x898D, 0xD28D, 0x898E, 0xD28E, 0x898F, 0xD28F, 0x8990, + 0xD290, 0x8991, 0xD291, 0x8992, 0xD292, 0x8993, 0xD293, 0x8994, 0xD294, 0x8995, 0xD295, 0x8996, 0xD296, 0x8997, 0xD297, 0x8998, + 0xD298, 0x8999, 0xD299, 0x899A, 0xD29A, 0x899B, 0xD29B, 0x899C, 0xD29C, 0x899D, 0xD29D, 0x899E, 0xD29E, 0x899F, 0xD29F, 0x89A0, + 0xD2A0, 0x89A1, 0xD2A1, 0x6447, 0xD2A2, 0x5C27, 0xD2A3, 0x9065, 0xD2A4, 0x7A91, 0xD2A5, 0x8C23, 0xD2A6, 0x59DA, 0xD2A7, 0x54AC, + 0xD2A8, 0x8200, 0xD2A9, 0x836F, 0xD2AA, 0x8981, 0xD2AB, 0x8000, 0xD2AC, 0x6930, 0xD2AD, 0x564E, 0xD2AE, 0x8036, 0xD2AF, 0x7237, + 0xD2B0, 0x91CE, 0xD2B1, 0x51B6, 0xD2B2, 0x4E5F, 0xD2B3, 0x9875, 0xD2B4, 0x6396, 0xD2B5, 0x4E1A, 0xD2B6, 0x53F6, 0xD2B7, 0x66F3, + 0xD2B8, 0x814B, 0xD2B9, 0x591C, 0xD2BA, 0x6DB2, 0xD2BB, 0x4E00, 0xD2BC, 0x58F9, 0xD2BD, 0x533B, 0xD2BE, 0x63D6, 0xD2BF, 0x94F1, + 0xD2C0, 0x4F9D, 0xD2C1, 0x4F0A, 0xD2C2, 0x8863, 0xD2C3, 0x9890, 0xD2C4, 0x5937, 0xD2C5, 0x9057, 0xD2C6, 0x79FB, 0xD2C7, 0x4EEA, + 0xD2C8, 0x80F0, 0xD2C9, 0x7591, 0xD2CA, 0x6C82, 0xD2CB, 0x5B9C, 0xD2CC, 0x59E8, 0xD2CD, 0x5F5D, 0xD2CE, 0x6905, 0xD2CF, 0x8681, + 0xD2D0, 0x501A, 0xD2D1, 0x5DF2, 0xD2D2, 0x4E59, 0xD2D3, 0x77E3, 0xD2D4, 0x4EE5, 0xD2D5, 0x827A, 0xD2D6, 0x6291, 0xD2D7, 0x6613, + 0xD2D8, 0x9091, 0xD2D9, 0x5C79, 0xD2DA, 0x4EBF, 0xD2DB, 0x5F79, 0xD2DC, 0x81C6, 0xD2DD, 0x9038, 0xD2DE, 0x8084, 0xD2DF, 0x75AB, + 0xD2E0, 0x4EA6, 0xD2E1, 0x88D4, 0xD2E2, 0x610F, 0xD2E3, 0x6BC5, 0xD2E4, 0x5FC6, 0xD2E5, 0x4E49, 0xD2E6, 0x76CA, 0xD2E7, 0x6EA2, + 0xD2E8, 0x8BE3, 0xD2E9, 0x8BAE, 0xD2EA, 0x8C0A, 0xD2EB, 0x8BD1, 0xD2EC, 0x5F02, 0xD2ED, 0x7FFC, 0xD2EE, 0x7FCC, 0xD2EF, 0x7ECE, + 0xD2F0, 0x8335, 0xD2F1, 0x836B, 0xD2F2, 0x56E0, 0xD2F3, 0x6BB7, 0xD2F4, 0x97F3, 0xD2F5, 0x9634, 0xD2F6, 0x59FB, 0xD2F7, 0x541F, + 0xD2F8, 0x94F6, 0xD2F9, 0x6DEB, 0xD2FA, 0x5BC5, 0xD2FB, 0x996E, 0xD2FC, 0x5C39, 0xD2FD, 0x5F15, 0xD2FE, 0x9690, 0xD340, 0x89A2, + 0xD341, 0x89A3, 0xD342, 0x89A4, 0xD343, 0x89A5, 0xD344, 0x89A6, 0xD345, 0x89A7, 0xD346, 0x89A8, 0xD347, 0x89A9, 0xD348, 0x89AA, + 0xD349, 0x89AB, 0xD34A, 0x89AC, 0xD34B, 0x89AD, 0xD34C, 0x89AE, 0xD34D, 0x89AF, 0xD34E, 0x89B0, 0xD34F, 0x89B1, 0xD350, 0x89B2, + 0xD351, 0x89B3, 0xD352, 0x89B4, 0xD353, 0x89B5, 0xD354, 0x89B6, 0xD355, 0x89B7, 0xD356, 0x89B8, 0xD357, 0x89B9, 0xD358, 0x89BA, + 0xD359, 0x89BB, 0xD35A, 0x89BC, 0xD35B, 0x89BD, 0xD35C, 0x89BE, 0xD35D, 0x89BF, 0xD35E, 0x89C0, 0xD35F, 0x89C3, 0xD360, 0x89CD, + 0xD361, 0x89D3, 0xD362, 0x89D4, 0xD363, 0x89D5, 0xD364, 0x89D7, 0xD365, 0x89D8, 0xD366, 0x89D9, 0xD367, 0x89DB, 0xD368, 0x89DD, + 0xD369, 0x89DF, 0xD36A, 0x89E0, 0xD36B, 0x89E1, 0xD36C, 0x89E2, 0xD36D, 0x89E4, 0xD36E, 0x89E7, 0xD36F, 0x89E8, 0xD370, 0x89E9, + 0xD371, 0x89EA, 0xD372, 0x89EC, 0xD373, 0x89ED, 0xD374, 0x89EE, 0xD375, 0x89F0, 0xD376, 0x89F1, 0xD377, 0x89F2, 0xD378, 0x89F4, + 0xD379, 0x89F5, 0xD37A, 0x89F6, 0xD37B, 0x89F7, 0xD37C, 0x89F8, 0xD37D, 0x89F9, 0xD37E, 0x89FA, 0xD380, 0x89FB, 0xD381, 0x89FC, + 0xD382, 0x89FD, 0xD383, 0x89FE, 0xD384, 0x89FF, 0xD385, 0x8A01, 0xD386, 0x8A02, 0xD387, 0x8A03, 0xD388, 0x8A04, 0xD389, 0x8A05, + 0xD38A, 0x8A06, 0xD38B, 0x8A08, 0xD38C, 0x8A09, 0xD38D, 0x8A0A, 0xD38E, 0x8A0B, 0xD38F, 0x8A0C, 0xD390, 0x8A0D, 0xD391, 0x8A0E, + 0xD392, 0x8A0F, 0xD393, 0x8A10, 0xD394, 0x8A11, 0xD395, 0x8A12, 0xD396, 0x8A13, 0xD397, 0x8A14, 0xD398, 0x8A15, 0xD399, 0x8A16, + 0xD39A, 0x8A17, 0xD39B, 0x8A18, 0xD39C, 0x8A19, 0xD39D, 0x8A1A, 0xD39E, 0x8A1B, 0xD39F, 0x8A1C, 0xD3A0, 0x8A1D, 0xD3A1, 0x5370, + 0xD3A2, 0x82F1, 0xD3A3, 0x6A31, 0xD3A4, 0x5A74, 0xD3A5, 0x9E70, 0xD3A6, 0x5E94, 0xD3A7, 0x7F28, 0xD3A8, 0x83B9, 0xD3A9, 0x8424, + 0xD3AA, 0x8425, 0xD3AB, 0x8367, 0xD3AC, 0x8747, 0xD3AD, 0x8FCE, 0xD3AE, 0x8D62, 0xD3AF, 0x76C8, 0xD3B0, 0x5F71, 0xD3B1, 0x9896, + 0xD3B2, 0x786C, 0xD3B3, 0x6620, 0xD3B4, 0x54DF, 0xD3B5, 0x62E5, 0xD3B6, 0x4F63, 0xD3B7, 0x81C3, 0xD3B8, 0x75C8, 0xD3B9, 0x5EB8, + 0xD3BA, 0x96CD, 0xD3BB, 0x8E0A, 0xD3BC, 0x86F9, 0xD3BD, 0x548F, 0xD3BE, 0x6CF3, 0xD3BF, 0x6D8C, 0xD3C0, 0x6C38, 0xD3C1, 0x607F, + 0xD3C2, 0x52C7, 0xD3C3, 0x7528, 0xD3C4, 0x5E7D, 0xD3C5, 0x4F18, 0xD3C6, 0x60A0, 0xD3C7, 0x5FE7, 0xD3C8, 0x5C24, 0xD3C9, 0x7531, + 0xD3CA, 0x90AE, 0xD3CB, 0x94C0, 0xD3CC, 0x72B9, 0xD3CD, 0x6CB9, 0xD3CE, 0x6E38, 0xD3CF, 0x9149, 0xD3D0, 0x6709, 0xD3D1, 0x53CB, + 0xD3D2, 0x53F3, 0xD3D3, 0x4F51, 0xD3D4, 0x91C9, 0xD3D5, 0x8BF1, 0xD3D6, 0x53C8, 0xD3D7, 0x5E7C, 0xD3D8, 0x8FC2, 0xD3D9, 0x6DE4, + 0xD3DA, 0x4E8E, 0xD3DB, 0x76C2, 0xD3DC, 0x6986, 0xD3DD, 0x865E, 0xD3DE, 0x611A, 0xD3DF, 0x8206, 0xD3E0, 0x4F59, 0xD3E1, 0x4FDE, + 0xD3E2, 0x903E, 0xD3E3, 0x9C7C, 0xD3E4, 0x6109, 0xD3E5, 0x6E1D, 0xD3E6, 0x6E14, 0xD3E7, 0x9685, 0xD3E8, 0x4E88, 0xD3E9, 0x5A31, + 0xD3EA, 0x96E8, 0xD3EB, 0x4E0E, 0xD3EC, 0x5C7F, 0xD3ED, 0x79B9, 0xD3EE, 0x5B87, 0xD3EF, 0x8BED, 0xD3F0, 0x7FBD, 0xD3F1, 0x7389, + 0xD3F2, 0x57DF, 0xD3F3, 0x828B, 0xD3F4, 0x90C1, 0xD3F5, 0x5401, 0xD3F6, 0x9047, 0xD3F7, 0x55BB, 0xD3F8, 0x5CEA, 0xD3F9, 0x5FA1, + 0xD3FA, 0x6108, 0xD3FB, 0x6B32, 0xD3FC, 0x72F1, 0xD3FD, 0x80B2, 0xD3FE, 0x8A89, 0xD440, 0x8A1E, 0xD441, 0x8A1F, 0xD442, 0x8A20, + 0xD443, 0x8A21, 0xD444, 0x8A22, 0xD445, 0x8A23, 0xD446, 0x8A24, 0xD447, 0x8A25, 0xD448, 0x8A26, 0xD449, 0x8A27, 0xD44A, 0x8A28, + 0xD44B, 0x8A29, 0xD44C, 0x8A2A, 0xD44D, 0x8A2B, 0xD44E, 0x8A2C, 0xD44F, 0x8A2D, 0xD450, 0x8A2E, 0xD451, 0x8A2F, 0xD452, 0x8A30, + 0xD453, 0x8A31, 0xD454, 0x8A32, 0xD455, 0x8A33, 0xD456, 0x8A34, 0xD457, 0x8A35, 0xD458, 0x8A36, 0xD459, 0x8A37, 0xD45A, 0x8A38, + 0xD45B, 0x8A39, 0xD45C, 0x8A3A, 0xD45D, 0x8A3B, 0xD45E, 0x8A3C, 0xD45F, 0x8A3D, 0xD460, 0x8A3F, 0xD461, 0x8A40, 0xD462, 0x8A41, + 0xD463, 0x8A42, 0xD464, 0x8A43, 0xD465, 0x8A44, 0xD466, 0x8A45, 0xD467, 0x8A46, 0xD468, 0x8A47, 0xD469, 0x8A49, 0xD46A, 0x8A4A, + 0xD46B, 0x8A4B, 0xD46C, 0x8A4C, 0xD46D, 0x8A4D, 0xD46E, 0x8A4E, 0xD46F, 0x8A4F, 0xD470, 0x8A50, 0xD471, 0x8A51, 0xD472, 0x8A52, + 0xD473, 0x8A53, 0xD474, 0x8A54, 0xD475, 0x8A55, 0xD476, 0x8A56, 0xD477, 0x8A57, 0xD478, 0x8A58, 0xD479, 0x8A59, 0xD47A, 0x8A5A, + 0xD47B, 0x8A5B, 0xD47C, 0x8A5C, 0xD47D, 0x8A5D, 0xD47E, 0x8A5E, 0xD480, 0x8A5F, 0xD481, 0x8A60, 0xD482, 0x8A61, 0xD483, 0x8A62, + 0xD484, 0x8A63, 0xD485, 0x8A64, 0xD486, 0x8A65, 0xD487, 0x8A66, 0xD488, 0x8A67, 0xD489, 0x8A68, 0xD48A, 0x8A69, 0xD48B, 0x8A6A, + 0xD48C, 0x8A6B, 0xD48D, 0x8A6C, 0xD48E, 0x8A6D, 0xD48F, 0x8A6E, 0xD490, 0x8A6F, 0xD491, 0x8A70, 0xD492, 0x8A71, 0xD493, 0x8A72, + 0xD494, 0x8A73, 0xD495, 0x8A74, 0xD496, 0x8A75, 0xD497, 0x8A76, 0xD498, 0x8A77, 0xD499, 0x8A78, 0xD49A, 0x8A7A, 0xD49B, 0x8A7B, + 0xD49C, 0x8A7C, 0xD49D, 0x8A7D, 0xD49E, 0x8A7E, 0xD49F, 0x8A7F, 0xD4A0, 0x8A80, 0xD4A1, 0x6D74, 0xD4A2, 0x5BD3, 0xD4A3, 0x88D5, + 0xD4A4, 0x9884, 0xD4A5, 0x8C6B, 0xD4A6, 0x9A6D, 0xD4A7, 0x9E33, 0xD4A8, 0x6E0A, 0xD4A9, 0x51A4, 0xD4AA, 0x5143, 0xD4AB, 0x57A3, + 0xD4AC, 0x8881, 0xD4AD, 0x539F, 0xD4AE, 0x63F4, 0xD4AF, 0x8F95, 0xD4B0, 0x56ED, 0xD4B1, 0x5458, 0xD4B2, 0x5706, 0xD4B3, 0x733F, + 0xD4B4, 0x6E90, 0xD4B5, 0x7F18, 0xD4B6, 0x8FDC, 0xD4B7, 0x82D1, 0xD4B8, 0x613F, 0xD4B9, 0x6028, 0xD4BA, 0x9662, 0xD4BB, 0x66F0, + 0xD4BC, 0x7EA6, 0xD4BD, 0x8D8A, 0xD4BE, 0x8DC3, 0xD4BF, 0x94A5, 0xD4C0, 0x5CB3, 0xD4C1, 0x7CA4, 0xD4C2, 0x6708, 0xD4C3, 0x60A6, + 0xD4C4, 0x9605, 0xD4C5, 0x8018, 0xD4C6, 0x4E91, 0xD4C7, 0x90E7, 0xD4C8, 0x5300, 0xD4C9, 0x9668, 0xD4CA, 0x5141, 0xD4CB, 0x8FD0, + 0xD4CC, 0x8574, 0xD4CD, 0x915D, 0xD4CE, 0x6655, 0xD4CF, 0x97F5, 0xD4D0, 0x5B55, 0xD4D1, 0x531D, 0xD4D2, 0x7838, 0xD4D3, 0x6742, + 0xD4D4, 0x683D, 0xD4D5, 0x54C9, 0xD4D6, 0x707E, 0xD4D7, 0x5BB0, 0xD4D8, 0x8F7D, 0xD4D9, 0x518D, 0xD4DA, 0x5728, 0xD4DB, 0x54B1, + 0xD4DC, 0x6512, 0xD4DD, 0x6682, 0xD4DE, 0x8D5E, 0xD4DF, 0x8D43, 0xD4E0, 0x810F, 0xD4E1, 0x846C, 0xD4E2, 0x906D, 0xD4E3, 0x7CDF, + 0xD4E4, 0x51FF, 0xD4E5, 0x85FB, 0xD4E6, 0x67A3, 0xD4E7, 0x65E9, 0xD4E8, 0x6FA1, 0xD4E9, 0x86A4, 0xD4EA, 0x8E81, 0xD4EB, 0x566A, + 0xD4EC, 0x9020, 0xD4ED, 0x7682, 0xD4EE, 0x7076, 0xD4EF, 0x71E5, 0xD4F0, 0x8D23, 0xD4F1, 0x62E9, 0xD4F2, 0x5219, 0xD4F3, 0x6CFD, + 0xD4F4, 0x8D3C, 0xD4F5, 0x600E, 0xD4F6, 0x589E, 0xD4F7, 0x618E, 0xD4F8, 0x66FE, 0xD4F9, 0x8D60, 0xD4FA, 0x624E, 0xD4FB, 0x55B3, + 0xD4FC, 0x6E23, 0xD4FD, 0x672D, 0xD4FE, 0x8F67, 0xD540, 0x8A81, 0xD541, 0x8A82, 0xD542, 0x8A83, 0xD543, 0x8A84, 0xD544, 0x8A85, + 0xD545, 0x8A86, 0xD546, 0x8A87, 0xD547, 0x8A88, 0xD548, 0x8A8B, 0xD549, 0x8A8C, 0xD54A, 0x8A8D, 0xD54B, 0x8A8E, 0xD54C, 0x8A8F, + 0xD54D, 0x8A90, 0xD54E, 0x8A91, 0xD54F, 0x8A92, 0xD550, 0x8A94, 0xD551, 0x8A95, 0xD552, 0x8A96, 0xD553, 0x8A97, 0xD554, 0x8A98, + 0xD555, 0x8A99, 0xD556, 0x8A9A, 0xD557, 0x8A9B, 0xD558, 0x8A9C, 0xD559, 0x8A9D, 0xD55A, 0x8A9E, 0xD55B, 0x8A9F, 0xD55C, 0x8AA0, + 0xD55D, 0x8AA1, 0xD55E, 0x8AA2, 0xD55F, 0x8AA3, 0xD560, 0x8AA4, 0xD561, 0x8AA5, 0xD562, 0x8AA6, 0xD563, 0x8AA7, 0xD564, 0x8AA8, + 0xD565, 0x8AA9, 0xD566, 0x8AAA, 0xD567, 0x8AAB, 0xD568, 0x8AAC, 0xD569, 0x8AAD, 0xD56A, 0x8AAE, 0xD56B, 0x8AAF, 0xD56C, 0x8AB0, + 0xD56D, 0x8AB1, 0xD56E, 0x8AB2, 0xD56F, 0x8AB3, 0xD570, 0x8AB4, 0xD571, 0x8AB5, 0xD572, 0x8AB6, 0xD573, 0x8AB7, 0xD574, 0x8AB8, + 0xD575, 0x8AB9, 0xD576, 0x8ABA, 0xD577, 0x8ABB, 0xD578, 0x8ABC, 0xD579, 0x8ABD, 0xD57A, 0x8ABE, 0xD57B, 0x8ABF, 0xD57C, 0x8AC0, + 0xD57D, 0x8AC1, 0xD57E, 0x8AC2, 0xD580, 0x8AC3, 0xD581, 0x8AC4, 0xD582, 0x8AC5, 0xD583, 0x8AC6, 0xD584, 0x8AC7, 0xD585, 0x8AC8, + 0xD586, 0x8AC9, 0xD587, 0x8ACA, 0xD588, 0x8ACB, 0xD589, 0x8ACC, 0xD58A, 0x8ACD, 0xD58B, 0x8ACE, 0xD58C, 0x8ACF, 0xD58D, 0x8AD0, + 0xD58E, 0x8AD1, 0xD58F, 0x8AD2, 0xD590, 0x8AD3, 0xD591, 0x8AD4, 0xD592, 0x8AD5, 0xD593, 0x8AD6, 0xD594, 0x8AD7, 0xD595, 0x8AD8, + 0xD596, 0x8AD9, 0xD597, 0x8ADA, 0xD598, 0x8ADB, 0xD599, 0x8ADC, 0xD59A, 0x8ADD, 0xD59B, 0x8ADE, 0xD59C, 0x8ADF, 0xD59D, 0x8AE0, + 0xD59E, 0x8AE1, 0xD59F, 0x8AE2, 0xD5A0, 0x8AE3, 0xD5A1, 0x94E1, 0xD5A2, 0x95F8, 0xD5A3, 0x7728, 0xD5A4, 0x6805, 0xD5A5, 0x69A8, + 0xD5A6, 0x548B, 0xD5A7, 0x4E4D, 0xD5A8, 0x70B8, 0xD5A9, 0x8BC8, 0xD5AA, 0x6458, 0xD5AB, 0x658B, 0xD5AC, 0x5B85, 0xD5AD, 0x7A84, + 0xD5AE, 0x503A, 0xD5AF, 0x5BE8, 0xD5B0, 0x77BB, 0xD5B1, 0x6BE1, 0xD5B2, 0x8A79, 0xD5B3, 0x7C98, 0xD5B4, 0x6CBE, 0xD5B5, 0x76CF, + 0xD5B6, 0x65A9, 0xD5B7, 0x8F97, 0xD5B8, 0x5D2D, 0xD5B9, 0x5C55, 0xD5BA, 0x8638, 0xD5BB, 0x6808, 0xD5BC, 0x5360, 0xD5BD, 0x6218, + 0xD5BE, 0x7AD9, 0xD5BF, 0x6E5B, 0xD5C0, 0x7EFD, 0xD5C1, 0x6A1F, 0xD5C2, 0x7AE0, 0xD5C3, 0x5F70, 0xD5C4, 0x6F33, 0xD5C5, 0x5F20, + 0xD5C6, 0x638C, 0xD5C7, 0x6DA8, 0xD5C8, 0x6756, 0xD5C9, 0x4E08, 0xD5CA, 0x5E10, 0xD5CB, 0x8D26, 0xD5CC, 0x4ED7, 0xD5CD, 0x80C0, + 0xD5CE, 0x7634, 0xD5CF, 0x969C, 0xD5D0, 0x62DB, 0xD5D1, 0x662D, 0xD5D2, 0x627E, 0xD5D3, 0x6CBC, 0xD5D4, 0x8D75, 0xD5D5, 0x7167, + 0xD5D6, 0x7F69, 0xD5D7, 0x5146, 0xD5D8, 0x8087, 0xD5D9, 0x53EC, 0xD5DA, 0x906E, 0xD5DB, 0x6298, 0xD5DC, 0x54F2, 0xD5DD, 0x86F0, + 0xD5DE, 0x8F99, 0xD5DF, 0x8005, 0xD5E0, 0x9517, 0xD5E1, 0x8517, 0xD5E2, 0x8FD9, 0xD5E3, 0x6D59, 0xD5E4, 0x73CD, 0xD5E5, 0x659F, + 0xD5E6, 0x771F, 0xD5E7, 0x7504, 0xD5E8, 0x7827, 0xD5E9, 0x81FB, 0xD5EA, 0x8D1E, 0xD5EB, 0x9488, 0xD5EC, 0x4FA6, 0xD5ED, 0x6795, + 0xD5EE, 0x75B9, 0xD5EF, 0x8BCA, 0xD5F0, 0x9707, 0xD5F1, 0x632F, 0xD5F2, 0x9547, 0xD5F3, 0x9635, 0xD5F4, 0x84B8, 0xD5F5, 0x6323, + 0xD5F6, 0x7741, 0xD5F7, 0x5F81, 0xD5F8, 0x72F0, 0xD5F9, 0x4E89, 0xD5FA, 0x6014, 0xD5FB, 0x6574, 0xD5FC, 0x62EF, 0xD5FD, 0x6B63, + 0xD5FE, 0x653F, 0xD640, 0x8AE4, 0xD641, 0x8AE5, 0xD642, 0x8AE6, 0xD643, 0x8AE7, 0xD644, 0x8AE8, 0xD645, 0x8AE9, 0xD646, 0x8AEA, + 0xD647, 0x8AEB, 0xD648, 0x8AEC, 0xD649, 0x8AED, 0xD64A, 0x8AEE, 0xD64B, 0x8AEF, 0xD64C, 0x8AF0, 0xD64D, 0x8AF1, 0xD64E, 0x8AF2, + 0xD64F, 0x8AF3, 0xD650, 0x8AF4, 0xD651, 0x8AF5, 0xD652, 0x8AF6, 0xD653, 0x8AF7, 0xD654, 0x8AF8, 0xD655, 0x8AF9, 0xD656, 0x8AFA, + 0xD657, 0x8AFB, 0xD658, 0x8AFC, 0xD659, 0x8AFD, 0xD65A, 0x8AFE, 0xD65B, 0x8AFF, 0xD65C, 0x8B00, 0xD65D, 0x8B01, 0xD65E, 0x8B02, + 0xD65F, 0x8B03, 0xD660, 0x8B04, 0xD661, 0x8B05, 0xD662, 0x8B06, 0xD663, 0x8B08, 0xD664, 0x8B09, 0xD665, 0x8B0A, 0xD666, 0x8B0B, + 0xD667, 0x8B0C, 0xD668, 0x8B0D, 0xD669, 0x8B0E, 0xD66A, 0x8B0F, 0xD66B, 0x8B10, 0xD66C, 0x8B11, 0xD66D, 0x8B12, 0xD66E, 0x8B13, + 0xD66F, 0x8B14, 0xD670, 0x8B15, 0xD671, 0x8B16, 0xD672, 0x8B17, 0xD673, 0x8B18, 0xD674, 0x8B19, 0xD675, 0x8B1A, 0xD676, 0x8B1B, + 0xD677, 0x8B1C, 0xD678, 0x8B1D, 0xD679, 0x8B1E, 0xD67A, 0x8B1F, 0xD67B, 0x8B20, 0xD67C, 0x8B21, 0xD67D, 0x8B22, 0xD67E, 0x8B23, + 0xD680, 0x8B24, 0xD681, 0x8B25, 0xD682, 0x8B27, 0xD683, 0x8B28, 0xD684, 0x8B29, 0xD685, 0x8B2A, 0xD686, 0x8B2B, 0xD687, 0x8B2C, + 0xD688, 0x8B2D, 0xD689, 0x8B2E, 0xD68A, 0x8B2F, 0xD68B, 0x8B30, 0xD68C, 0x8B31, 0xD68D, 0x8B32, 0xD68E, 0x8B33, 0xD68F, 0x8B34, + 0xD690, 0x8B35, 0xD691, 0x8B36, 0xD692, 0x8B37, 0xD693, 0x8B38, 0xD694, 0x8B39, 0xD695, 0x8B3A, 0xD696, 0x8B3B, 0xD697, 0x8B3C, + 0xD698, 0x8B3D, 0xD699, 0x8B3E, 0xD69A, 0x8B3F, 0xD69B, 0x8B40, 0xD69C, 0x8B41, 0xD69D, 0x8B42, 0xD69E, 0x8B43, 0xD69F, 0x8B44, + 0xD6A0, 0x8B45, 0xD6A1, 0x5E27, 0xD6A2, 0x75C7, 0xD6A3, 0x90D1, 0xD6A4, 0x8BC1, 0xD6A5, 0x829D, 0xD6A6, 0x679D, 0xD6A7, 0x652F, + 0xD6A8, 0x5431, 0xD6A9, 0x8718, 0xD6AA, 0x77E5, 0xD6AB, 0x80A2, 0xD6AC, 0x8102, 0xD6AD, 0x6C41, 0xD6AE, 0x4E4B, 0xD6AF, 0x7EC7, + 0xD6B0, 0x804C, 0xD6B1, 0x76F4, 0xD6B2, 0x690D, 0xD6B3, 0x6B96, 0xD6B4, 0x6267, 0xD6B5, 0x503C, 0xD6B6, 0x4F84, 0xD6B7, 0x5740, + 0xD6B8, 0x6307, 0xD6B9, 0x6B62, 0xD6BA, 0x8DBE, 0xD6BB, 0x53EA, 0xD6BC, 0x65E8, 0xD6BD, 0x7EB8, 0xD6BE, 0x5FD7, 0xD6BF, 0x631A, + 0xD6C0, 0x63B7, 0xD6C1, 0x81F3, 0xD6C2, 0x81F4, 0xD6C3, 0x7F6E, 0xD6C4, 0x5E1C, 0xD6C5, 0x5CD9, 0xD6C6, 0x5236, 0xD6C7, 0x667A, + 0xD6C8, 0x79E9, 0xD6C9, 0x7A1A, 0xD6CA, 0x8D28, 0xD6CB, 0x7099, 0xD6CC, 0x75D4, 0xD6CD, 0x6EDE, 0xD6CE, 0x6CBB, 0xD6CF, 0x7A92, + 0xD6D0, 0x4E2D, 0xD6D1, 0x76C5, 0xD6D2, 0x5FE0, 0xD6D3, 0x949F, 0xD6D4, 0x8877, 0xD6D5, 0x7EC8, 0xD6D6, 0x79CD, 0xD6D7, 0x80BF, + 0xD6D8, 0x91CD, 0xD6D9, 0x4EF2, 0xD6DA, 0x4F17, 0xD6DB, 0x821F, 0xD6DC, 0x5468, 0xD6DD, 0x5DDE, 0xD6DE, 0x6D32, 0xD6DF, 0x8BCC, + 0xD6E0, 0x7CA5, 0xD6E1, 0x8F74, 0xD6E2, 0x8098, 0xD6E3, 0x5E1A, 0xD6E4, 0x5492, 0xD6E5, 0x76B1, 0xD6E6, 0x5B99, 0xD6E7, 0x663C, + 0xD6E8, 0x9AA4, 0xD6E9, 0x73E0, 0xD6EA, 0x682A, 0xD6EB, 0x86DB, 0xD6EC, 0x6731, 0xD6ED, 0x732A, 0xD6EE, 0x8BF8, 0xD6EF, 0x8BDB, + 0xD6F0, 0x9010, 0xD6F1, 0x7AF9, 0xD6F2, 0x70DB, 0xD6F3, 0x716E, 0xD6F4, 0x62C4, 0xD6F5, 0x77A9, 0xD6F6, 0x5631, 0xD6F7, 0x4E3B, + 0xD6F8, 0x8457, 0xD6F9, 0x67F1, 0xD6FA, 0x52A9, 0xD6FB, 0x86C0, 0xD6FC, 0x8D2E, 0xD6FD, 0x94F8, 0xD6FE, 0x7B51, 0xD740, 0x8B46, + 0xD741, 0x8B47, 0xD742, 0x8B48, 0xD743, 0x8B49, 0xD744, 0x8B4A, 0xD745, 0x8B4B, 0xD746, 0x8B4C, 0xD747, 0x8B4D, 0xD748, 0x8B4E, + 0xD749, 0x8B4F, 0xD74A, 0x8B50, 0xD74B, 0x8B51, 0xD74C, 0x8B52, 0xD74D, 0x8B53, 0xD74E, 0x8B54, 0xD74F, 0x8B55, 0xD750, 0x8B56, + 0xD751, 0x8B57, 0xD752, 0x8B58, 0xD753, 0x8B59, 0xD754, 0x8B5A, 0xD755, 0x8B5B, 0xD756, 0x8B5C, 0xD757, 0x8B5D, 0xD758, 0x8B5E, + 0xD759, 0x8B5F, 0xD75A, 0x8B60, 0xD75B, 0x8B61, 0xD75C, 0x8B62, 0xD75D, 0x8B63, 0xD75E, 0x8B64, 0xD75F, 0x8B65, 0xD760, 0x8B67, + 0xD761, 0x8B68, 0xD762, 0x8B69, 0xD763, 0x8B6A, 0xD764, 0x8B6B, 0xD765, 0x8B6D, 0xD766, 0x8B6E, 0xD767, 0x8B6F, 0xD768, 0x8B70, + 0xD769, 0x8B71, 0xD76A, 0x8B72, 0xD76B, 0x8B73, 0xD76C, 0x8B74, 0xD76D, 0x8B75, 0xD76E, 0x8B76, 0xD76F, 0x8B77, 0xD770, 0x8B78, + 0xD771, 0x8B79, 0xD772, 0x8B7A, 0xD773, 0x8B7B, 0xD774, 0x8B7C, 0xD775, 0x8B7D, 0xD776, 0x8B7E, 0xD777, 0x8B7F, 0xD778, 0x8B80, + 0xD779, 0x8B81, 0xD77A, 0x8B82, 0xD77B, 0x8B83, 0xD77C, 0x8B84, 0xD77D, 0x8B85, 0xD77E, 0x8B86, 0xD780, 0x8B87, 0xD781, 0x8B88, + 0xD782, 0x8B89, 0xD783, 0x8B8A, 0xD784, 0x8B8B, 0xD785, 0x8B8C, 0xD786, 0x8B8D, 0xD787, 0x8B8E, 0xD788, 0x8B8F, 0xD789, 0x8B90, + 0xD78A, 0x8B91, 0xD78B, 0x8B92, 0xD78C, 0x8B93, 0xD78D, 0x8B94, 0xD78E, 0x8B95, 0xD78F, 0x8B96, 0xD790, 0x8B97, 0xD791, 0x8B98, + 0xD792, 0x8B99, 0xD793, 0x8B9A, 0xD794, 0x8B9B, 0xD795, 0x8B9C, 0xD796, 0x8B9D, 0xD797, 0x8B9E, 0xD798, 0x8B9F, 0xD799, 0x8BAC, + 0xD79A, 0x8BB1, 0xD79B, 0x8BBB, 0xD79C, 0x8BC7, 0xD79D, 0x8BD0, 0xD79E, 0x8BEA, 0xD79F, 0x8C09, 0xD7A0, 0x8C1E, 0xD7A1, 0x4F4F, + 0xD7A2, 0x6CE8, 0xD7A3, 0x795D, 0xD7A4, 0x9A7B, 0xD7A5, 0x6293, 0xD7A6, 0x722A, 0xD7A7, 0x62FD, 0xD7A8, 0x4E13, 0xD7A9, 0x7816, + 0xD7AA, 0x8F6C, 0xD7AB, 0x64B0, 0xD7AC, 0x8D5A, 0xD7AD, 0x7BC6, 0xD7AE, 0x6869, 0xD7AF, 0x5E84, 0xD7B0, 0x88C5, 0xD7B1, 0x5986, + 0xD7B2, 0x649E, 0xD7B3, 0x58EE, 0xD7B4, 0x72B6, 0xD7B5, 0x690E, 0xD7B6, 0x9525, 0xD7B7, 0x8FFD, 0xD7B8, 0x8D58, 0xD7B9, 0x5760, + 0xD7BA, 0x7F00, 0xD7BB, 0x8C06, 0xD7BC, 0x51C6, 0xD7BD, 0x6349, 0xD7BE, 0x62D9, 0xD7BF, 0x5353, 0xD7C0, 0x684C, 0xD7C1, 0x7422, + 0xD7C2, 0x8301, 0xD7C3, 0x914C, 0xD7C4, 0x5544, 0xD7C5, 0x7740, 0xD7C6, 0x707C, 0xD7C7, 0x6D4A, 0xD7C8, 0x5179, 0xD7C9, 0x54A8, + 0xD7CA, 0x8D44, 0xD7CB, 0x59FF, 0xD7CC, 0x6ECB, 0xD7CD, 0x6DC4, 0xD7CE, 0x5B5C, 0xD7CF, 0x7D2B, 0xD7D0, 0x4ED4, 0xD7D1, 0x7C7D, + 0xD7D2, 0x6ED3, 0xD7D3, 0x5B50, 0xD7D4, 0x81EA, 0xD7D5, 0x6E0D, 0xD7D6, 0x5B57, 0xD7D7, 0x9B03, 0xD7D8, 0x68D5, 0xD7D9, 0x8E2A, + 0xD7DA, 0x5B97, 0xD7DB, 0x7EFC, 0xD7DC, 0x603B, 0xD7DD, 0x7EB5, 0xD7DE, 0x90B9, 0xD7DF, 0x8D70, 0xD7E0, 0x594F, 0xD7E1, 0x63CD, + 0xD7E2, 0x79DF, 0xD7E3, 0x8DB3, 0xD7E4, 0x5352, 0xD7E5, 0x65CF, 0xD7E6, 0x7956, 0xD7E7, 0x8BC5, 0xD7E8, 0x963B, 0xD7E9, 0x7EC4, + 0xD7EA, 0x94BB, 0xD7EB, 0x7E82, 0xD7EC, 0x5634, 0xD7ED, 0x9189, 0xD7EE, 0x6700, 0xD7EF, 0x7F6A, 0xD7F0, 0x5C0A, 0xD7F1, 0x9075, + 0xD7F2, 0x6628, 0xD7F3, 0x5DE6, 0xD7F4, 0x4F50, 0xD7F5, 0x67DE, 0xD7F6, 0x505A, 0xD7F7, 0x4F5C, 0xD7F8, 0x5750, 0xD7F9, 0x5EA7, + 0xD840, 0x8C38, 0xD841, 0x8C39, 0xD842, 0x8C3A, 0xD843, 0x8C3B, 0xD844, 0x8C3C, 0xD845, 0x8C3D, 0xD846, 0x8C3E, 0xD847, 0x8C3F, + 0xD848, 0x8C40, 0xD849, 0x8C42, 0xD84A, 0x8C43, 0xD84B, 0x8C44, 0xD84C, 0x8C45, 0xD84D, 0x8C48, 0xD84E, 0x8C4A, 0xD84F, 0x8C4B, + 0xD850, 0x8C4D, 0xD851, 0x8C4E, 0xD852, 0x8C4F, 0xD853, 0x8C50, 0xD854, 0x8C51, 0xD855, 0x8C52, 0xD856, 0x8C53, 0xD857, 0x8C54, + 0xD858, 0x8C56, 0xD859, 0x8C57, 0xD85A, 0x8C58, 0xD85B, 0x8C59, 0xD85C, 0x8C5B, 0xD85D, 0x8C5C, 0xD85E, 0x8C5D, 0xD85F, 0x8C5E, + 0xD860, 0x8C5F, 0xD861, 0x8C60, 0xD862, 0x8C63, 0xD863, 0x8C64, 0xD864, 0x8C65, 0xD865, 0x8C66, 0xD866, 0x8C67, 0xD867, 0x8C68, + 0xD868, 0x8C69, 0xD869, 0x8C6C, 0xD86A, 0x8C6D, 0xD86B, 0x8C6E, 0xD86C, 0x8C6F, 0xD86D, 0x8C70, 0xD86E, 0x8C71, 0xD86F, 0x8C72, + 0xD870, 0x8C74, 0xD871, 0x8C75, 0xD872, 0x8C76, 0xD873, 0x8C77, 0xD874, 0x8C7B, 0xD875, 0x8C7C, 0xD876, 0x8C7D, 0xD877, 0x8C7E, + 0xD878, 0x8C7F, 0xD879, 0x8C80, 0xD87A, 0x8C81, 0xD87B, 0x8C83, 0xD87C, 0x8C84, 0xD87D, 0x8C86, 0xD87E, 0x8C87, 0xD880, 0x8C88, + 0xD881, 0x8C8B, 0xD882, 0x8C8D, 0xD883, 0x8C8E, 0xD884, 0x8C8F, 0xD885, 0x8C90, 0xD886, 0x8C91, 0xD887, 0x8C92, 0xD888, 0x8C93, + 0xD889, 0x8C95, 0xD88A, 0x8C96, 0xD88B, 0x8C97, 0xD88C, 0x8C99, 0xD88D, 0x8C9A, 0xD88E, 0x8C9B, 0xD88F, 0x8C9C, 0xD890, 0x8C9D, + 0xD891, 0x8C9E, 0xD892, 0x8C9F, 0xD893, 0x8CA0, 0xD894, 0x8CA1, 0xD895, 0x8CA2, 0xD896, 0x8CA3, 0xD897, 0x8CA4, 0xD898, 0x8CA5, + 0xD899, 0x8CA6, 0xD89A, 0x8CA7, 0xD89B, 0x8CA8, 0xD89C, 0x8CA9, 0xD89D, 0x8CAA, 0xD89E, 0x8CAB, 0xD89F, 0x8CAC, 0xD8A0, 0x8CAD, + 0xD8A1, 0x4E8D, 0xD8A2, 0x4E0C, 0xD8A3, 0x5140, 0xD8A4, 0x4E10, 0xD8A5, 0x5EFF, 0xD8A6, 0x5345, 0xD8A7, 0x4E15, 0xD8A8, 0x4E98, + 0xD8A9, 0x4E1E, 0xD8AA, 0x9B32, 0xD8AB, 0x5B6C, 0xD8AC, 0x5669, 0xD8AD, 0x4E28, 0xD8AE, 0x79BA, 0xD8AF, 0x4E3F, 0xD8B0, 0x5315, + 0xD8B1, 0x4E47, 0xD8B2, 0x592D, 0xD8B3, 0x723B, 0xD8B4, 0x536E, 0xD8B5, 0x6C10, 0xD8B6, 0x56DF, 0xD8B7, 0x80E4, 0xD8B8, 0x9997, + 0xD8B9, 0x6BD3, 0xD8BA, 0x777E, 0xD8BB, 0x9F17, 0xD8BC, 0x4E36, 0xD8BD, 0x4E9F, 0xD8BE, 0x9F10, 0xD8BF, 0x4E5C, 0xD8C0, 0x4E69, + 0xD8C1, 0x4E93, 0xD8C2, 0x8288, 0xD8C3, 0x5B5B, 0xD8C4, 0x556C, 0xD8C5, 0x560F, 0xD8C6, 0x4EC4, 0xD8C7, 0x538D, 0xD8C8, 0x539D, + 0xD8C9, 0x53A3, 0xD8CA, 0x53A5, 0xD8CB, 0x53AE, 0xD8CC, 0x9765, 0xD8CD, 0x8D5D, 0xD8CE, 0x531A, 0xD8CF, 0x53F5, 0xD8D0, 0x5326, + 0xD8D1, 0x532E, 0xD8D2, 0x533E, 0xD8D3, 0x8D5C, 0xD8D4, 0x5366, 0xD8D5, 0x5363, 0xD8D6, 0x5202, 0xD8D7, 0x5208, 0xD8D8, 0x520E, + 0xD8D9, 0x522D, 0xD8DA, 0x5233, 0xD8DB, 0x523F, 0xD8DC, 0x5240, 0xD8DD, 0x524C, 0xD8DE, 0x525E, 0xD8DF, 0x5261, 0xD8E0, 0x525C, + 0xD8E1, 0x84AF, 0xD8E2, 0x527D, 0xD8E3, 0x5282, 0xD8E4, 0x5281, 0xD8E5, 0x5290, 0xD8E6, 0x5293, 0xD8E7, 0x5182, 0xD8E8, 0x7F54, + 0xD8E9, 0x4EBB, 0xD8EA, 0x4EC3, 0xD8EB, 0x4EC9, 0xD8EC, 0x4EC2, 0xD8ED, 0x4EE8, 0xD8EE, 0x4EE1, 0xD8EF, 0x4EEB, 0xD8F0, 0x4EDE, + 0xD8F1, 0x4F1B, 0xD8F2, 0x4EF3, 0xD8F3, 0x4F22, 0xD8F4, 0x4F64, 0xD8F5, 0x4EF5, 0xD8F6, 0x4F25, 0xD8F7, 0x4F27, 0xD8F8, 0x4F09, + 0xD8F9, 0x4F2B, 0xD8FA, 0x4F5E, 0xD8FB, 0x4F67, 0xD8FC, 0x6538, 0xD8FD, 0x4F5A, 0xD8FE, 0x4F5D, 0xD940, 0x8CAE, 0xD941, 0x8CAF, + 0xD942, 0x8CB0, 0xD943, 0x8CB1, 0xD944, 0x8CB2, 0xD945, 0x8CB3, 0xD946, 0x8CB4, 0xD947, 0x8CB5, 0xD948, 0x8CB6, 0xD949, 0x8CB7, + 0xD94A, 0x8CB8, 0xD94B, 0x8CB9, 0xD94C, 0x8CBA, 0xD94D, 0x8CBB, 0xD94E, 0x8CBC, 0xD94F, 0x8CBD, 0xD950, 0x8CBE, 0xD951, 0x8CBF, + 0xD952, 0x8CC0, 0xD953, 0x8CC1, 0xD954, 0x8CC2, 0xD955, 0x8CC3, 0xD956, 0x8CC4, 0xD957, 0x8CC5, 0xD958, 0x8CC6, 0xD959, 0x8CC7, + 0xD95A, 0x8CC8, 0xD95B, 0x8CC9, 0xD95C, 0x8CCA, 0xD95D, 0x8CCB, 0xD95E, 0x8CCC, 0xD95F, 0x8CCD, 0xD960, 0x8CCE, 0xD961, 0x8CCF, + 0xD962, 0x8CD0, 0xD963, 0x8CD1, 0xD964, 0x8CD2, 0xD965, 0x8CD3, 0xD966, 0x8CD4, 0xD967, 0x8CD5, 0xD968, 0x8CD6, 0xD969, 0x8CD7, + 0xD96A, 0x8CD8, 0xD96B, 0x8CD9, 0xD96C, 0x8CDA, 0xD96D, 0x8CDB, 0xD96E, 0x8CDC, 0xD96F, 0x8CDD, 0xD970, 0x8CDE, 0xD971, 0x8CDF, + 0xD972, 0x8CE0, 0xD973, 0x8CE1, 0xD974, 0x8CE2, 0xD975, 0x8CE3, 0xD976, 0x8CE4, 0xD977, 0x8CE5, 0xD978, 0x8CE6, 0xD979, 0x8CE7, + 0xD97A, 0x8CE8, 0xD97B, 0x8CE9, 0xD97C, 0x8CEA, 0xD97D, 0x8CEB, 0xD97E, 0x8CEC, 0xD980, 0x8CED, 0xD981, 0x8CEE, 0xD982, 0x8CEF, + 0xD983, 0x8CF0, 0xD984, 0x8CF1, 0xD985, 0x8CF2, 0xD986, 0x8CF3, 0xD987, 0x8CF4, 0xD988, 0x8CF5, 0xD989, 0x8CF6, 0xD98A, 0x8CF7, + 0xD98B, 0x8CF8, 0xD98C, 0x8CF9, 0xD98D, 0x8CFA, 0xD98E, 0x8CFB, 0xD98F, 0x8CFC, 0xD990, 0x8CFD, 0xD991, 0x8CFE, 0xD992, 0x8CFF, + 0xD993, 0x8D00, 0xD994, 0x8D01, 0xD995, 0x8D02, 0xD996, 0x8D03, 0xD997, 0x8D04, 0xD998, 0x8D05, 0xD999, 0x8D06, 0xD99A, 0x8D07, + 0xD99B, 0x8D08, 0xD99C, 0x8D09, 0xD99D, 0x8D0A, 0xD99E, 0x8D0B, 0xD99F, 0x8D0C, 0xD9A0, 0x8D0D, 0xD9A1, 0x4F5F, 0xD9A2, 0x4F57, + 0xD9A3, 0x4F32, 0xD9A4, 0x4F3D, 0xD9A5, 0x4F76, 0xD9A6, 0x4F74, 0xD9A7, 0x4F91, 0xD9A8, 0x4F89, 0xD9A9, 0x4F83, 0xD9AA, 0x4F8F, + 0xD9AB, 0x4F7E, 0xD9AC, 0x4F7B, 0xD9AD, 0x4FAA, 0xD9AE, 0x4F7C, 0xD9AF, 0x4FAC, 0xD9B0, 0x4F94, 0xD9B1, 0x4FE6, 0xD9B2, 0x4FE8, + 0xD9B3, 0x4FEA, 0xD9B4, 0x4FC5, 0xD9B5, 0x4FDA, 0xD9B6, 0x4FE3, 0xD9B7, 0x4FDC, 0xD9B8, 0x4FD1, 0xD9B9, 0x4FDF, 0xD9BA, 0x4FF8, + 0xD9BB, 0x5029, 0xD9BC, 0x504C, 0xD9BD, 0x4FF3, 0xD9BE, 0x502C, 0xD9BF, 0x500F, 0xD9C0, 0x502E, 0xD9C1, 0x502D, 0xD9C2, 0x4FFE, + 0xD9C3, 0x501C, 0xD9C4, 0x500C, 0xD9C5, 0x5025, 0xD9C6, 0x5028, 0xD9C7, 0x507E, 0xD9C8, 0x5043, 0xD9C9, 0x5055, 0xD9CA, 0x5048, + 0xD9CB, 0x504E, 0xD9CC, 0x506C, 0xD9CD, 0x507B, 0xD9CE, 0x50A5, 0xD9CF, 0x50A7, 0xD9D0, 0x50A9, 0xD9D1, 0x50BA, 0xD9D2, 0x50D6, + 0xD9D3, 0x5106, 0xD9D4, 0x50ED, 0xD9D5, 0x50EC, 0xD9D6, 0x50E6, 0xD9D7, 0x50EE, 0xD9D8, 0x5107, 0xD9D9, 0x510B, 0xD9DA, 0x4EDD, + 0xD9DB, 0x6C3D, 0xD9DC, 0x4F58, 0xD9DD, 0x4F65, 0xD9DE, 0x4FCE, 0xD9DF, 0x9FA0, 0xD9E0, 0x6C46, 0xD9E1, 0x7C74, 0xD9E2, 0x516E, + 0xD9E3, 0x5DFD, 0xD9E4, 0x9EC9, 0xD9E5, 0x9998, 0xD9E6, 0x5181, 0xD9E7, 0x5914, 0xD9E8, 0x52F9, 0xD9E9, 0x530D, 0xD9EA, 0x8A07, + 0xD9EB, 0x5310, 0xD9EC, 0x51EB, 0xD9ED, 0x5919, 0xD9EE, 0x5155, 0xD9EF, 0x4EA0, 0xD9F0, 0x5156, 0xD9F1, 0x4EB3, 0xD9F2, 0x886E, + 0xD9F3, 0x88A4, 0xD9F4, 0x4EB5, 0xD9F5, 0x8114, 0xD9F6, 0x88D2, 0xD9F7, 0x7980, 0xD9F8, 0x5B34, 0xD9F9, 0x8803, 0xD9FA, 0x7FB8, + 0xD9FB, 0x51AB, 0xD9FC, 0x51B1, 0xD9FD, 0x51BD, 0xD9FE, 0x51BC, 0xDA40, 0x8D0E, 0xDA41, 0x8D0F, 0xDA42, 0x8D10, 0xDA43, 0x8D11, + 0xDA44, 0x8D12, 0xDA45, 0x8D13, 0xDA46, 0x8D14, 0xDA47, 0x8D15, 0xDA48, 0x8D16, 0xDA49, 0x8D17, 0xDA4A, 0x8D18, 0xDA4B, 0x8D19, + 0xDA4C, 0x8D1A, 0xDA4D, 0x8D1B, 0xDA4E, 0x8D1C, 0xDA4F, 0x8D20, 0xDA50, 0x8D51, 0xDA51, 0x8D52, 0xDA52, 0x8D57, 0xDA53, 0x8D5F, + 0xDA54, 0x8D65, 0xDA55, 0x8D68, 0xDA56, 0x8D69, 0xDA57, 0x8D6A, 0xDA58, 0x8D6C, 0xDA59, 0x8D6E, 0xDA5A, 0x8D6F, 0xDA5B, 0x8D71, + 0xDA5C, 0x8D72, 0xDA5D, 0x8D78, 0xDA5E, 0x8D79, 0xDA5F, 0x8D7A, 0xDA60, 0x8D7B, 0xDA61, 0x8D7C, 0xDA62, 0x8D7D, 0xDA63, 0x8D7E, + 0xDA64, 0x8D7F, 0xDA65, 0x8D80, 0xDA66, 0x8D82, 0xDA67, 0x8D83, 0xDA68, 0x8D86, 0xDA69, 0x8D87, 0xDA6A, 0x8D88, 0xDA6B, 0x8D89, + 0xDA6C, 0x8D8C, 0xDA6D, 0x8D8D, 0xDA6E, 0x8D8E, 0xDA6F, 0x8D8F, 0xDA70, 0x8D90, 0xDA71, 0x8D92, 0xDA72, 0x8D93, 0xDA73, 0x8D95, + 0xDA74, 0x8D96, 0xDA75, 0x8D97, 0xDA76, 0x8D98, 0xDA77, 0x8D99, 0xDA78, 0x8D9A, 0xDA79, 0x8D9B, 0xDA7A, 0x8D9C, 0xDA7B, 0x8D9D, + 0xDA7C, 0x8D9E, 0xDA7D, 0x8DA0, 0xDA7E, 0x8DA1, 0xDA80, 0x8DA2, 0xDA81, 0x8DA4, 0xDA82, 0x8DA5, 0xDA83, 0x8DA6, 0xDA84, 0x8DA7, + 0xDA85, 0x8DA8, 0xDA86, 0x8DA9, 0xDA87, 0x8DAA, 0xDA88, 0x8DAB, 0xDA89, 0x8DAC, 0xDA8A, 0x8DAD, 0xDA8B, 0x8DAE, 0xDA8C, 0x8DAF, + 0xDA8D, 0x8DB0, 0xDA8E, 0x8DB2, 0xDA8F, 0x8DB6, 0xDA90, 0x8DB7, 0xDA91, 0x8DB9, 0xDA92, 0x8DBB, 0xDA93, 0x8DBD, 0xDA94, 0x8DC0, + 0xDA95, 0x8DC1, 0xDA96, 0x8DC2, 0xDA97, 0x8DC5, 0xDA98, 0x8DC7, 0xDA99, 0x8DC8, 0xDA9A, 0x8DC9, 0xDA9B, 0x8DCA, 0xDA9C, 0x8DCD, + 0xDA9D, 0x8DD0, 0xDA9E, 0x8DD2, 0xDA9F, 0x8DD3, 0xDAA0, 0x8DD4, 0xDAA1, 0x51C7, 0xDAA2, 0x5196, 0xDAA3, 0x51A2, 0xDAA4, 0x51A5, + 0xDAA5, 0x8BA0, 0xDAA6, 0x8BA6, 0xDAA7, 0x8BA7, 0xDAA8, 0x8BAA, 0xDAA9, 0x8BB4, 0xDAAA, 0x8BB5, 0xDAAB, 0x8BB7, 0xDAAC, 0x8BC2, + 0xDAAD, 0x8BC3, 0xDAAE, 0x8BCB, 0xDAAF, 0x8BCF, 0xDAB0, 0x8BCE, 0xDAB1, 0x8BD2, 0xDAB2, 0x8BD3, 0xDAB3, 0x8BD4, 0xDAB4, 0x8BD6, + 0xDAB5, 0x8BD8, 0xDAB6, 0x8BD9, 0xDAB7, 0x8BDC, 0xDAB8, 0x8BDF, 0xDAB9, 0x8BE0, 0xDABA, 0x8BE4, 0xDABB, 0x8BE8, 0xDABC, 0x8BE9, + 0xDABD, 0x8BEE, 0xDABE, 0x8BF0, 0xDABF, 0x8BF3, 0xDAC0, 0x8BF6, 0xDAC1, 0x8BF9, 0xDAC2, 0x8BFC, 0xDAC3, 0x8BFF, 0xDAC4, 0x8C00, + 0xDAC5, 0x8C02, 0xDAC6, 0x8C04, 0xDAC7, 0x8C07, 0xDAC8, 0x8C0C, 0xDAC9, 0x8C0F, 0xDACA, 0x8C11, 0xDACB, 0x8C12, 0xDACC, 0x8C14, + 0xDACD, 0x8C15, 0xDACE, 0x8C16, 0xDACF, 0x8C19, 0xDAD0, 0x8C1B, 0xDAD1, 0x8C18, 0xDAD2, 0x8C1D, 0xDAD3, 0x8C1F, 0xDAD4, 0x8C20, + 0xDAD5, 0x8C21, 0xDAD6, 0x8C25, 0xDAD7, 0x8C27, 0xDAD8, 0x8C2A, 0xDAD9, 0x8C2B, 0xDADA, 0x8C2E, 0xDADB, 0x8C2F, 0xDADC, 0x8C32, + 0xDADD, 0x8C33, 0xDADE, 0x8C35, 0xDADF, 0x8C36, 0xDAE0, 0x5369, 0xDAE1, 0x537A, 0xDAE2, 0x961D, 0xDAE3, 0x9622, 0xDAE4, 0x9621, + 0xDAE5, 0x9631, 0xDAE6, 0x962A, 0xDAE7, 0x963D, 0xDAE8, 0x963C, 0xDAE9, 0x9642, 0xDAEA, 0x9649, 0xDAEB, 0x9654, 0xDAEC, 0x965F, + 0xDAED, 0x9667, 0xDAEE, 0x966C, 0xDAEF, 0x9672, 0xDAF0, 0x9674, 0xDAF1, 0x9688, 0xDAF2, 0x968D, 0xDAF3, 0x9697, 0xDAF4, 0x96B0, + 0xDAF5, 0x9097, 0xDAF6, 0x909B, 0xDAF7, 0x909D, 0xDAF8, 0x9099, 0xDAF9, 0x90AC, 0xDAFA, 0x90A1, 0xDAFB, 0x90B4, 0xDAFC, 0x90B3, + 0xDAFD, 0x90B6, 0xDAFE, 0x90BA, 0xDB40, 0x8DD5, 0xDB41, 0x8DD8, 0xDB42, 0x8DD9, 0xDB43, 0x8DDC, 0xDB44, 0x8DE0, 0xDB45, 0x8DE1, + 0xDB46, 0x8DE2, 0xDB47, 0x8DE5, 0xDB48, 0x8DE6, 0xDB49, 0x8DE7, 0xDB4A, 0x8DE9, 0xDB4B, 0x8DED, 0xDB4C, 0x8DEE, 0xDB4D, 0x8DF0, + 0xDB4E, 0x8DF1, 0xDB4F, 0x8DF2, 0xDB50, 0x8DF4, 0xDB51, 0x8DF6, 0xDB52, 0x8DFC, 0xDB53, 0x8DFE, 0xDB54, 0x8DFF, 0xDB55, 0x8E00, + 0xDB56, 0x8E01, 0xDB57, 0x8E02, 0xDB58, 0x8E03, 0xDB59, 0x8E04, 0xDB5A, 0x8E06, 0xDB5B, 0x8E07, 0xDB5C, 0x8E08, 0xDB5D, 0x8E0B, + 0xDB5E, 0x8E0D, 0xDB5F, 0x8E0E, 0xDB60, 0x8E10, 0xDB61, 0x8E11, 0xDB62, 0x8E12, 0xDB63, 0x8E13, 0xDB64, 0x8E15, 0xDB65, 0x8E16, + 0xDB66, 0x8E17, 0xDB67, 0x8E18, 0xDB68, 0x8E19, 0xDB69, 0x8E1A, 0xDB6A, 0x8E1B, 0xDB6B, 0x8E1C, 0xDB6C, 0x8E20, 0xDB6D, 0x8E21, + 0xDB6E, 0x8E24, 0xDB6F, 0x8E25, 0xDB70, 0x8E26, 0xDB71, 0x8E27, 0xDB72, 0x8E28, 0xDB73, 0x8E2B, 0xDB74, 0x8E2D, 0xDB75, 0x8E30, + 0xDB76, 0x8E32, 0xDB77, 0x8E33, 0xDB78, 0x8E34, 0xDB79, 0x8E36, 0xDB7A, 0x8E37, 0xDB7B, 0x8E38, 0xDB7C, 0x8E3B, 0xDB7D, 0x8E3C, + 0xDB7E, 0x8E3E, 0xDB80, 0x8E3F, 0xDB81, 0x8E43, 0xDB82, 0x8E45, 0xDB83, 0x8E46, 0xDB84, 0x8E4C, 0xDB85, 0x8E4D, 0xDB86, 0x8E4E, + 0xDB87, 0x8E4F, 0xDB88, 0x8E50, 0xDB89, 0x8E53, 0xDB8A, 0x8E54, 0xDB8B, 0x8E55, 0xDB8C, 0x8E56, 0xDB8D, 0x8E57, 0xDB8E, 0x8E58, + 0xDB8F, 0x8E5A, 0xDB90, 0x8E5B, 0xDB91, 0x8E5C, 0xDB92, 0x8E5D, 0xDB93, 0x8E5E, 0xDB94, 0x8E5F, 0xDB95, 0x8E60, 0xDB96, 0x8E61, + 0xDB97, 0x8E62, 0xDB98, 0x8E63, 0xDB99, 0x8E64, 0xDB9A, 0x8E65, 0xDB9B, 0x8E67, 0xDB9C, 0x8E68, 0xDB9D, 0x8E6A, 0xDB9E, 0x8E6B, + 0xDB9F, 0x8E6E, 0xDBA0, 0x8E71, 0xDBA1, 0x90B8, 0xDBA2, 0x90B0, 0xDBA3, 0x90CF, 0xDBA4, 0x90C5, 0xDBA5, 0x90BE, 0xDBA6, 0x90D0, + 0xDBA7, 0x90C4, 0xDBA8, 0x90C7, 0xDBA9, 0x90D3, 0xDBAA, 0x90E6, 0xDBAB, 0x90E2, 0xDBAC, 0x90DC, 0xDBAD, 0x90D7, 0xDBAE, 0x90DB, + 0xDBAF, 0x90EB, 0xDBB0, 0x90EF, 0xDBB1, 0x90FE, 0xDBB2, 0x9104, 0xDBB3, 0x9122, 0xDBB4, 0x911E, 0xDBB5, 0x9123, 0xDBB6, 0x9131, + 0xDBB7, 0x912F, 0xDBB8, 0x9139, 0xDBB9, 0x9143, 0xDBBA, 0x9146, 0xDBBB, 0x520D, 0xDBBC, 0x5942, 0xDBBD, 0x52A2, 0xDBBE, 0x52AC, + 0xDBBF, 0x52AD, 0xDBC0, 0x52BE, 0xDBC1, 0x54FF, 0xDBC2, 0x52D0, 0xDBC3, 0x52D6, 0xDBC4, 0x52F0, 0xDBC5, 0x53DF, 0xDBC6, 0x71EE, + 0xDBC7, 0x77CD, 0xDBC8, 0x5EF4, 0xDBC9, 0x51F5, 0xDBCA, 0x51FC, 0xDBCB, 0x9B2F, 0xDBCC, 0x53B6, 0xDBCD, 0x5F01, 0xDBCE, 0x755A, + 0xDBCF, 0x5DEF, 0xDBD0, 0x574C, 0xDBD1, 0x57A9, 0xDBD2, 0x57A1, 0xDBD3, 0x587E, 0xDBD4, 0x58BC, 0xDBD5, 0x58C5, 0xDBD6, 0x58D1, + 0xDBD7, 0x5729, 0xDBD8, 0x572C, 0xDBD9, 0x572A, 0xDBDA, 0x5733, 0xDBDB, 0x5739, 0xDBDC, 0x572E, 0xDBDD, 0x572F, 0xDBDE, 0x575C, + 0xDBDF, 0x573B, 0xDBE0, 0x5742, 0xDBE1, 0x5769, 0xDBE2, 0x5785, 0xDBE3, 0x576B, 0xDBE4, 0x5786, 0xDBE5, 0x577C, 0xDBE6, 0x577B, + 0xDBE7, 0x5768, 0xDBE8, 0x576D, 0xDBE9, 0x5776, 0xDBEA, 0x5773, 0xDBEB, 0x57AD, 0xDBEC, 0x57A4, 0xDBED, 0x578C, 0xDBEE, 0x57B2, + 0xDBEF, 0x57CF, 0xDBF0, 0x57A7, 0xDBF1, 0x57B4, 0xDBF2, 0x5793, 0xDBF3, 0x57A0, 0xDBF4, 0x57D5, 0xDBF5, 0x57D8, 0xDBF6, 0x57DA, + 0xDBF7, 0x57D9, 0xDBF8, 0x57D2, 0xDBF9, 0x57B8, 0xDBFA, 0x57F4, 0xDBFB, 0x57EF, 0xDBFC, 0x57F8, 0xDBFD, 0x57E4, 0xDBFE, 0x57DD, + 0xDC40, 0x8E73, 0xDC41, 0x8E75, 0xDC42, 0x8E77, 0xDC43, 0x8E78, 0xDC44, 0x8E79, 0xDC45, 0x8E7A, 0xDC46, 0x8E7B, 0xDC47, 0x8E7D, + 0xDC48, 0x8E7E, 0xDC49, 0x8E80, 0xDC4A, 0x8E82, 0xDC4B, 0x8E83, 0xDC4C, 0x8E84, 0xDC4D, 0x8E86, 0xDC4E, 0x8E88, 0xDC4F, 0x8E89, + 0xDC50, 0x8E8A, 0xDC51, 0x8E8B, 0xDC52, 0x8E8C, 0xDC53, 0x8E8D, 0xDC54, 0x8E8E, 0xDC55, 0x8E91, 0xDC56, 0x8E92, 0xDC57, 0x8E93, + 0xDC58, 0x8E95, 0xDC59, 0x8E96, 0xDC5A, 0x8E97, 0xDC5B, 0x8E98, 0xDC5C, 0x8E99, 0xDC5D, 0x8E9A, 0xDC5E, 0x8E9B, 0xDC5F, 0x8E9D, + 0xDC60, 0x8E9F, 0xDC61, 0x8EA0, 0xDC62, 0x8EA1, 0xDC63, 0x8EA2, 0xDC64, 0x8EA3, 0xDC65, 0x8EA4, 0xDC66, 0x8EA5, 0xDC67, 0x8EA6, + 0xDC68, 0x8EA7, 0xDC69, 0x8EA8, 0xDC6A, 0x8EA9, 0xDC6B, 0x8EAA, 0xDC6C, 0x8EAD, 0xDC6D, 0x8EAE, 0xDC6E, 0x8EB0, 0xDC6F, 0x8EB1, + 0xDC70, 0x8EB3, 0xDC71, 0x8EB4, 0xDC72, 0x8EB5, 0xDC73, 0x8EB6, 0xDC74, 0x8EB7, 0xDC75, 0x8EB8, 0xDC76, 0x8EB9, 0xDC77, 0x8EBB, + 0xDC78, 0x8EBC, 0xDC79, 0x8EBD, 0xDC7A, 0x8EBE, 0xDC7B, 0x8EBF, 0xDC7C, 0x8EC0, 0xDC7D, 0x8EC1, 0xDC7E, 0x8EC2, 0xDC80, 0x8EC3, + 0xDC81, 0x8EC4, 0xDC82, 0x8EC5, 0xDC83, 0x8EC6, 0xDC84, 0x8EC7, 0xDC85, 0x8EC8, 0xDC86, 0x8EC9, 0xDC87, 0x8ECA, 0xDC88, 0x8ECB, + 0xDC89, 0x8ECC, 0xDC8A, 0x8ECD, 0xDC8B, 0x8ECF, 0xDC8C, 0x8ED0, 0xDC8D, 0x8ED1, 0xDC8E, 0x8ED2, 0xDC8F, 0x8ED3, 0xDC90, 0x8ED4, + 0xDC91, 0x8ED5, 0xDC92, 0x8ED6, 0xDC93, 0x8ED7, 0xDC94, 0x8ED8, 0xDC95, 0x8ED9, 0xDC96, 0x8EDA, 0xDC97, 0x8EDB, 0xDC98, 0x8EDC, + 0xDC99, 0x8EDD, 0xDC9A, 0x8EDE, 0xDC9B, 0x8EDF, 0xDC9C, 0x8EE0, 0xDC9D, 0x8EE1, 0xDC9E, 0x8EE2, 0xDC9F, 0x8EE3, 0xDCA0, 0x8EE4, + 0xDCA1, 0x580B, 0xDCA2, 0x580D, 0xDCA3, 0x57FD, 0xDCA4, 0x57ED, 0xDCA5, 0x5800, 0xDCA6, 0x581E, 0xDCA7, 0x5819, 0xDCA8, 0x5844, + 0xDCA9, 0x5820, 0xDCAA, 0x5865, 0xDCAB, 0x586C, 0xDCAC, 0x5881, 0xDCAD, 0x5889, 0xDCAE, 0x589A, 0xDCAF, 0x5880, 0xDCB0, 0x99A8, + 0xDCB1, 0x9F19, 0xDCB2, 0x61FF, 0xDCB3, 0x8279, 0xDCB4, 0x827D, 0xDCB5, 0x827F, 0xDCB6, 0x828F, 0xDCB7, 0x828A, 0xDCB8, 0x82A8, + 0xDCB9, 0x8284, 0xDCBA, 0x828E, 0xDCBB, 0x8291, 0xDCBC, 0x8297, 0xDCBD, 0x8299, 0xDCBE, 0x82AB, 0xDCBF, 0x82B8, 0xDCC0, 0x82BE, + 0xDCC1, 0x82B0, 0xDCC2, 0x82C8, 0xDCC3, 0x82CA, 0xDCC4, 0x82E3, 0xDCC5, 0x8298, 0xDCC6, 0x82B7, 0xDCC7, 0x82AE, 0xDCC8, 0x82CB, + 0xDCC9, 0x82CC, 0xDCCA, 0x82C1, 0xDCCB, 0x82A9, 0xDCCC, 0x82B4, 0xDCCD, 0x82A1, 0xDCCE, 0x82AA, 0xDCCF, 0x829F, 0xDCD0, 0x82C4, + 0xDCD1, 0x82CE, 0xDCD2, 0x82A4, 0xDCD3, 0x82E1, 0xDCD4, 0x8309, 0xDCD5, 0x82F7, 0xDCD6, 0x82E4, 0xDCD7, 0x830F, 0xDCD8, 0x8307, + 0xDCD9, 0x82DC, 0xDCDA, 0x82F4, 0xDCDB, 0x82D2, 0xDCDC, 0x82D8, 0xDCDD, 0x830C, 0xDCDE, 0x82FB, 0xDCDF, 0x82D3, 0xDCE0, 0x8311, + 0xDCE1, 0x831A, 0xDCE2, 0x8306, 0xDCE3, 0x8314, 0xDCE4, 0x8315, 0xDCE5, 0x82E0, 0xDCE6, 0x82D5, 0xDCE7, 0x831C, 0xDCE8, 0x8351, + 0xDCE9, 0x835B, 0xDCEA, 0x835C, 0xDCEB, 0x8308, 0xDCEC, 0x8392, 0xDCED, 0x833C, 0xDCEE, 0x8334, 0xDCEF, 0x8331, 0xDCF0, 0x839B, + 0xDCF1, 0x835E, 0xDCF2, 0x832F, 0xDCF3, 0x834F, 0xDCF4, 0x8347, 0xDCF5, 0x8343, 0xDCF6, 0x835F, 0xDCF7, 0x8340, 0xDCF8, 0x8317, + 0xDCF9, 0x8360, 0xDCFA, 0x832D, 0xDCFB, 0x833A, 0xDCFC, 0x8333, 0xDCFD, 0x8366, 0xDCFE, 0x8365, 0xDD40, 0x8EE5, 0xDD41, 0x8EE6, + 0xDD42, 0x8EE7, 0xDD43, 0x8EE8, 0xDD44, 0x8EE9, 0xDD45, 0x8EEA, 0xDD46, 0x8EEB, 0xDD47, 0x8EEC, 0xDD48, 0x8EED, 0xDD49, 0x8EEE, + 0xDD4A, 0x8EEF, 0xDD4B, 0x8EF0, 0xDD4C, 0x8EF1, 0xDD4D, 0x8EF2, 0xDD4E, 0x8EF3, 0xDD4F, 0x8EF4, 0xDD50, 0x8EF5, 0xDD51, 0x8EF6, + 0xDD52, 0x8EF7, 0xDD53, 0x8EF8, 0xDD54, 0x8EF9, 0xDD55, 0x8EFA, 0xDD56, 0x8EFB, 0xDD57, 0x8EFC, 0xDD58, 0x8EFD, 0xDD59, 0x8EFE, + 0xDD5A, 0x8EFF, 0xDD5B, 0x8F00, 0xDD5C, 0x8F01, 0xDD5D, 0x8F02, 0xDD5E, 0x8F03, 0xDD5F, 0x8F04, 0xDD60, 0x8F05, 0xDD61, 0x8F06, + 0xDD62, 0x8F07, 0xDD63, 0x8F08, 0xDD64, 0x8F09, 0xDD65, 0x8F0A, 0xDD66, 0x8F0B, 0xDD67, 0x8F0C, 0xDD68, 0x8F0D, 0xDD69, 0x8F0E, + 0xDD6A, 0x8F0F, 0xDD6B, 0x8F10, 0xDD6C, 0x8F11, 0xDD6D, 0x8F12, 0xDD6E, 0x8F13, 0xDD6F, 0x8F14, 0xDD70, 0x8F15, 0xDD71, 0x8F16, + 0xDD72, 0x8F17, 0xDD73, 0x8F18, 0xDD74, 0x8F19, 0xDD75, 0x8F1A, 0xDD76, 0x8F1B, 0xDD77, 0x8F1C, 0xDD78, 0x8F1D, 0xDD79, 0x8F1E, + 0xDD7A, 0x8F1F, 0xDD7B, 0x8F20, 0xDD7C, 0x8F21, 0xDD7D, 0x8F22, 0xDD7E, 0x8F23, 0xDD80, 0x8F24, 0xDD81, 0x8F25, 0xDD82, 0x8F26, + 0xDD83, 0x8F27, 0xDD84, 0x8F28, 0xDD85, 0x8F29, 0xDD86, 0x8F2A, 0xDD87, 0x8F2B, 0xDD88, 0x8F2C, 0xDD89, 0x8F2D, 0xDD8A, 0x8F2E, + 0xDD8B, 0x8F2F, 0xDD8C, 0x8F30, 0xDD8D, 0x8F31, 0xDD8E, 0x8F32, 0xDD8F, 0x8F33, 0xDD90, 0x8F34, 0xDD91, 0x8F35, 0xDD92, 0x8F36, + 0xDD93, 0x8F37, 0xDD94, 0x8F38, 0xDD95, 0x8F39, 0xDD96, 0x8F3A, 0xDD97, 0x8F3B, 0xDD98, 0x8F3C, 0xDD99, 0x8F3D, 0xDD9A, 0x8F3E, + 0xDD9B, 0x8F3F, 0xDD9C, 0x8F40, 0xDD9D, 0x8F41, 0xDD9E, 0x8F42, 0xDD9F, 0x8F43, 0xDDA0, 0x8F44, 0xDDA1, 0x8368, 0xDDA2, 0x831B, + 0xDDA3, 0x8369, 0xDDA4, 0x836C, 0xDDA5, 0x836A, 0xDDA6, 0x836D, 0xDDA7, 0x836E, 0xDDA8, 0x83B0, 0xDDA9, 0x8378, 0xDDAA, 0x83B3, + 0xDDAB, 0x83B4, 0xDDAC, 0x83A0, 0xDDAD, 0x83AA, 0xDDAE, 0x8393, 0xDDAF, 0x839C, 0xDDB0, 0x8385, 0xDDB1, 0x837C, 0xDDB2, 0x83B6, + 0xDDB3, 0x83A9, 0xDDB4, 0x837D, 0xDDB5, 0x83B8, 0xDDB6, 0x837B, 0xDDB7, 0x8398, 0xDDB8, 0x839E, 0xDDB9, 0x83A8, 0xDDBA, 0x83BA, + 0xDDBB, 0x83BC, 0xDDBC, 0x83C1, 0xDDBD, 0x8401, 0xDDBE, 0x83E5, 0xDDBF, 0x83D8, 0xDDC0, 0x5807, 0xDDC1, 0x8418, 0xDDC2, 0x840B, + 0xDDC3, 0x83DD, 0xDDC4, 0x83FD, 0xDDC5, 0x83D6, 0xDDC6, 0x841C, 0xDDC7, 0x8438, 0xDDC8, 0x8411, 0xDDC9, 0x8406, 0xDDCA, 0x83D4, + 0xDDCB, 0x83DF, 0xDDCC, 0x840F, 0xDDCD, 0x8403, 0xDDCE, 0x83F8, 0xDDCF, 0x83F9, 0xDDD0, 0x83EA, 0xDDD1, 0x83C5, 0xDDD2, 0x83C0, + 0xDDD3, 0x8426, 0xDDD4, 0x83F0, 0xDDD5, 0x83E1, 0xDDD6, 0x845C, 0xDDD7, 0x8451, 0xDDD8, 0x845A, 0xDDD9, 0x8459, 0xDDDA, 0x8473, + 0xDDDB, 0x8487, 0xDDDC, 0x8488, 0xDDDD, 0x847A, 0xDDDE, 0x8489, 0xDDDF, 0x8478, 0xDDE0, 0x843C, 0xDDE1, 0x8446, 0xDDE2, 0x8469, + 0xDDE3, 0x8476, 0xDDE4, 0x848C, 0xDDE5, 0x848E, 0xDDE6, 0x8431, 0xDDE7, 0x846D, 0xDDE8, 0x84C1, 0xDDE9, 0x84CD, 0xDDEA, 0x84D0, + 0xDDEB, 0x84E6, 0xDDEC, 0x84BD, 0xDDED, 0x84D3, 0xDDEE, 0x84CA, 0xDDEF, 0x84BF, 0xDDF0, 0x84BA, 0xDDF1, 0x84E0, 0xDDF2, 0x84A1, + 0xDDF3, 0x84B9, 0xDDF4, 0x84B4, 0xDDF5, 0x8497, 0xDDF6, 0x84E5, 0xDDF7, 0x84E3, 0xDDF8, 0x850C, 0xDDF9, 0x750D, 0xDDFA, 0x8538, + 0xDDFB, 0x84F0, 0xDDFC, 0x8539, 0xDDFD, 0x851F, 0xDDFE, 0x853A, 0xDE40, 0x8F45, 0xDE41, 0x8F46, 0xDE42, 0x8F47, 0xDE43, 0x8F48, + 0xDE44, 0x8F49, 0xDE45, 0x8F4A, 0xDE46, 0x8F4B, 0xDE47, 0x8F4C, 0xDE48, 0x8F4D, 0xDE49, 0x8F4E, 0xDE4A, 0x8F4F, 0xDE4B, 0x8F50, + 0xDE4C, 0x8F51, 0xDE4D, 0x8F52, 0xDE4E, 0x8F53, 0xDE4F, 0x8F54, 0xDE50, 0x8F55, 0xDE51, 0x8F56, 0xDE52, 0x8F57, 0xDE53, 0x8F58, + 0xDE54, 0x8F59, 0xDE55, 0x8F5A, 0xDE56, 0x8F5B, 0xDE57, 0x8F5C, 0xDE58, 0x8F5D, 0xDE59, 0x8F5E, 0xDE5A, 0x8F5F, 0xDE5B, 0x8F60, + 0xDE5C, 0x8F61, 0xDE5D, 0x8F62, 0xDE5E, 0x8F63, 0xDE5F, 0x8F64, 0xDE60, 0x8F65, 0xDE61, 0x8F6A, 0xDE62, 0x8F80, 0xDE63, 0x8F8C, + 0xDE64, 0x8F92, 0xDE65, 0x8F9D, 0xDE66, 0x8FA0, 0xDE67, 0x8FA1, 0xDE68, 0x8FA2, 0xDE69, 0x8FA4, 0xDE6A, 0x8FA5, 0xDE6B, 0x8FA6, + 0xDE6C, 0x8FA7, 0xDE6D, 0x8FAA, 0xDE6E, 0x8FAC, 0xDE6F, 0x8FAD, 0xDE70, 0x8FAE, 0xDE71, 0x8FAF, 0xDE72, 0x8FB2, 0xDE73, 0x8FB3, + 0xDE74, 0x8FB4, 0xDE75, 0x8FB5, 0xDE76, 0x8FB7, 0xDE77, 0x8FB8, 0xDE78, 0x8FBA, 0xDE79, 0x8FBB, 0xDE7A, 0x8FBC, 0xDE7B, 0x8FBF, + 0xDE7C, 0x8FC0, 0xDE7D, 0x8FC3, 0xDE7E, 0x8FC6, 0xDE80, 0x8FC9, 0xDE81, 0x8FCA, 0xDE82, 0x8FCB, 0xDE83, 0x8FCC, 0xDE84, 0x8FCD, + 0xDE85, 0x8FCF, 0xDE86, 0x8FD2, 0xDE87, 0x8FD6, 0xDE88, 0x8FD7, 0xDE89, 0x8FDA, 0xDE8A, 0x8FE0, 0xDE8B, 0x8FE1, 0xDE8C, 0x8FE3, + 0xDE8D, 0x8FE7, 0xDE8E, 0x8FEC, 0xDE8F, 0x8FEF, 0xDE90, 0x8FF1, 0xDE91, 0x8FF2, 0xDE92, 0x8FF4, 0xDE93, 0x8FF5, 0xDE94, 0x8FF6, + 0xDE95, 0x8FFA, 0xDE96, 0x8FFB, 0xDE97, 0x8FFC, 0xDE98, 0x8FFE, 0xDE99, 0x8FFF, 0xDE9A, 0x9007, 0xDE9B, 0x9008, 0xDE9C, 0x900C, + 0xDE9D, 0x900E, 0xDE9E, 0x9013, 0xDE9F, 0x9015, 0xDEA0, 0x9018, 0xDEA1, 0x8556, 0xDEA2, 0x853B, 0xDEA3, 0x84FF, 0xDEA4, 0x84FC, + 0xDEA5, 0x8559, 0xDEA6, 0x8548, 0xDEA7, 0x8568, 0xDEA8, 0x8564, 0xDEA9, 0x855E, 0xDEAA, 0x857A, 0xDEAB, 0x77A2, 0xDEAC, 0x8543, + 0xDEAD, 0x8572, 0xDEAE, 0x857B, 0xDEAF, 0x85A4, 0xDEB0, 0x85A8, 0xDEB1, 0x8587, 0xDEB2, 0x858F, 0xDEB3, 0x8579, 0xDEB4, 0x85AE, + 0xDEB5, 0x859C, 0xDEB6, 0x8585, 0xDEB7, 0x85B9, 0xDEB8, 0x85B7, 0xDEB9, 0x85B0, 0xDEBA, 0x85D3, 0xDEBB, 0x85C1, 0xDEBC, 0x85DC, + 0xDEBD, 0x85FF, 0xDEBE, 0x8627, 0xDEBF, 0x8605, 0xDEC0, 0x8629, 0xDEC1, 0x8616, 0xDEC2, 0x863C, 0xDEC3, 0x5EFE, 0xDEC4, 0x5F08, + 0xDEC5, 0x593C, 0xDEC6, 0x5941, 0xDEC7, 0x8037, 0xDEC8, 0x5955, 0xDEC9, 0x595A, 0xDECA, 0x5958, 0xDECB, 0x530F, 0xDECC, 0x5C22, + 0xDECD, 0x5C25, 0xDECE, 0x5C2C, 0xDECF, 0x5C34, 0xDED0, 0x624C, 0xDED1, 0x626A, 0xDED2, 0x629F, 0xDED3, 0x62BB, 0xDED4, 0x62CA, + 0xDED5, 0x62DA, 0xDED6, 0x62D7, 0xDED7, 0x62EE, 0xDED8, 0x6322, 0xDED9, 0x62F6, 0xDEDA, 0x6339, 0xDEDB, 0x634B, 0xDEDC, 0x6343, + 0xDEDD, 0x63AD, 0xDEDE, 0x63F6, 0xDEDF, 0x6371, 0xDEE0, 0x637A, 0xDEE1, 0x638E, 0xDEE2, 0x63B4, 0xDEE3, 0x636D, 0xDEE4, 0x63AC, + 0xDEE5, 0x638A, 0xDEE6, 0x6369, 0xDEE7, 0x63AE, 0xDEE8, 0x63BC, 0xDEE9, 0x63F2, 0xDEEA, 0x63F8, 0xDEEB, 0x63E0, 0xDEEC, 0x63FF, + 0xDEED, 0x63C4, 0xDEEE, 0x63DE, 0xDEEF, 0x63CE, 0xDEF0, 0x6452, 0xDEF1, 0x63C6, 0xDEF2, 0x63BE, 0xDEF3, 0x6445, 0xDEF4, 0x6441, + 0xDEF5, 0x640B, 0xDEF6, 0x641B, 0xDEF7, 0x6420, 0xDEF8, 0x640C, 0xDEF9, 0x6426, 0xDEFA, 0x6421, 0xDEFB, 0x645E, 0xDEFC, 0x6484, + 0xDEFD, 0x646D, 0xDEFE, 0x6496, 0xDF40, 0x9019, 0xDF41, 0x901C, 0xDF42, 0x9023, 0xDF43, 0x9024, 0xDF44, 0x9025, 0xDF45, 0x9027, + 0xDF46, 0x9028, 0xDF47, 0x9029, 0xDF48, 0x902A, 0xDF49, 0x902B, 0xDF4A, 0x902C, 0xDF4B, 0x9030, 0xDF4C, 0x9031, 0xDF4D, 0x9032, + 0xDF4E, 0x9033, 0xDF4F, 0x9034, 0xDF50, 0x9037, 0xDF51, 0x9039, 0xDF52, 0x903A, 0xDF53, 0x903D, 0xDF54, 0x903F, 0xDF55, 0x9040, + 0xDF56, 0x9043, 0xDF57, 0x9045, 0xDF58, 0x9046, 0xDF59, 0x9048, 0xDF5A, 0x9049, 0xDF5B, 0x904A, 0xDF5C, 0x904B, 0xDF5D, 0x904C, + 0xDF5E, 0x904E, 0xDF5F, 0x9054, 0xDF60, 0x9055, 0xDF61, 0x9056, 0xDF62, 0x9059, 0xDF63, 0x905A, 0xDF64, 0x905C, 0xDF65, 0x905D, + 0xDF66, 0x905E, 0xDF67, 0x905F, 0xDF68, 0x9060, 0xDF69, 0x9061, 0xDF6A, 0x9064, 0xDF6B, 0x9066, 0xDF6C, 0x9067, 0xDF6D, 0x9069, + 0xDF6E, 0x906A, 0xDF6F, 0x906B, 0xDF70, 0x906C, 0xDF71, 0x906F, 0xDF72, 0x9070, 0xDF73, 0x9071, 0xDF74, 0x9072, 0xDF75, 0x9073, + 0xDF76, 0x9076, 0xDF77, 0x9077, 0xDF78, 0x9078, 0xDF79, 0x9079, 0xDF7A, 0x907A, 0xDF7B, 0x907B, 0xDF7C, 0x907C, 0xDF7D, 0x907E, + 0xDF7E, 0x9081, 0xDF80, 0x9084, 0xDF81, 0x9085, 0xDF82, 0x9086, 0xDF83, 0x9087, 0xDF84, 0x9089, 0xDF85, 0x908A, 0xDF86, 0x908C, + 0xDF87, 0x908D, 0xDF88, 0x908E, 0xDF89, 0x908F, 0xDF8A, 0x9090, 0xDF8B, 0x9092, 0xDF8C, 0x9094, 0xDF8D, 0x9096, 0xDF8E, 0x9098, + 0xDF8F, 0x909A, 0xDF90, 0x909C, 0xDF91, 0x909E, 0xDF92, 0x909F, 0xDF93, 0x90A0, 0xDF94, 0x90A4, 0xDF95, 0x90A5, 0xDF96, 0x90A7, + 0xDF97, 0x90A8, 0xDF98, 0x90A9, 0xDF99, 0x90AB, 0xDF9A, 0x90AD, 0xDF9B, 0x90B2, 0xDF9C, 0x90B7, 0xDF9D, 0x90BC, 0xDF9E, 0x90BD, + 0xDF9F, 0x90BF, 0xDFA0, 0x90C0, 0xDFA1, 0x647A, 0xDFA2, 0x64B7, 0xDFA3, 0x64B8, 0xDFA4, 0x6499, 0xDFA5, 0x64BA, 0xDFA6, 0x64C0, + 0xDFA7, 0x64D0, 0xDFA8, 0x64D7, 0xDFA9, 0x64E4, 0xDFAA, 0x64E2, 0xDFAB, 0x6509, 0xDFAC, 0x6525, 0xDFAD, 0x652E, 0xDFAE, 0x5F0B, + 0xDFAF, 0x5FD2, 0xDFB0, 0x7519, 0xDFB1, 0x5F11, 0xDFB2, 0x535F, 0xDFB3, 0x53F1, 0xDFB4, 0x53FD, 0xDFB5, 0x53E9, 0xDFB6, 0x53E8, + 0xDFB7, 0x53FB, 0xDFB8, 0x5412, 0xDFB9, 0x5416, 0xDFBA, 0x5406, 0xDFBB, 0x544B, 0xDFBC, 0x5452, 0xDFBD, 0x5453, 0xDFBE, 0x5454, + 0xDFBF, 0x5456, 0xDFC0, 0x5443, 0xDFC1, 0x5421, 0xDFC2, 0x5457, 0xDFC3, 0x5459, 0xDFC4, 0x5423, 0xDFC5, 0x5432, 0xDFC6, 0x5482, + 0xDFC7, 0x5494, 0xDFC8, 0x5477, 0xDFC9, 0x5471, 0xDFCA, 0x5464, 0xDFCB, 0x549A, 0xDFCC, 0x549B, 0xDFCD, 0x5484, 0xDFCE, 0x5476, + 0xDFCF, 0x5466, 0xDFD0, 0x549D, 0xDFD1, 0x54D0, 0xDFD2, 0x54AD, 0xDFD3, 0x54C2, 0xDFD4, 0x54B4, 0xDFD5, 0x54D2, 0xDFD6, 0x54A7, + 0xDFD7, 0x54A6, 0xDFD8, 0x54D3, 0xDFD9, 0x54D4, 0xDFDA, 0x5472, 0xDFDB, 0x54A3, 0xDFDC, 0x54D5, 0xDFDD, 0x54BB, 0xDFDE, 0x54BF, + 0xDFDF, 0x54CC, 0xDFE0, 0x54D9, 0xDFE1, 0x54DA, 0xDFE2, 0x54DC, 0xDFE3, 0x54A9, 0xDFE4, 0x54AA, 0xDFE5, 0x54A4, 0xDFE6, 0x54DD, + 0xDFE7, 0x54CF, 0xDFE8, 0x54DE, 0xDFE9, 0x551B, 0xDFEA, 0x54E7, 0xDFEB, 0x5520, 0xDFEC, 0x54FD, 0xDFED, 0x5514, 0xDFEE, 0x54F3, + 0xDFEF, 0x5522, 0xDFF0, 0x5523, 0xDFF1, 0x550F, 0xDFF2, 0x5511, 0xDFF3, 0x5527, 0xDFF4, 0x552A, 0xDFF5, 0x5567, 0xDFF6, 0x558F, + 0xDFF7, 0x55B5, 0xDFF8, 0x5549, 0xDFF9, 0x556D, 0xDFFA, 0x5541, 0xDFFB, 0x5555, 0xDFFC, 0x553F, 0xDFFD, 0x5550, 0xDFFE, 0x553C, + 0xE040, 0x90C2, 0xE041, 0x90C3, 0xE042, 0x90C6, 0xE043, 0x90C8, 0xE044, 0x90C9, 0xE045, 0x90CB, 0xE046, 0x90CC, 0xE047, 0x90CD, + 0xE048, 0x90D2, 0xE049, 0x90D4, 0xE04A, 0x90D5, 0xE04B, 0x90D6, 0xE04C, 0x90D8, 0xE04D, 0x90D9, 0xE04E, 0x90DA, 0xE04F, 0x90DE, + 0xE050, 0x90DF, 0xE051, 0x90E0, 0xE052, 0x90E3, 0xE053, 0x90E4, 0xE054, 0x90E5, 0xE055, 0x90E9, 0xE056, 0x90EA, 0xE057, 0x90EC, + 0xE058, 0x90EE, 0xE059, 0x90F0, 0xE05A, 0x90F1, 0xE05B, 0x90F2, 0xE05C, 0x90F3, 0xE05D, 0x90F5, 0xE05E, 0x90F6, 0xE05F, 0x90F7, + 0xE060, 0x90F9, 0xE061, 0x90FA, 0xE062, 0x90FB, 0xE063, 0x90FC, 0xE064, 0x90FF, 0xE065, 0x9100, 0xE066, 0x9101, 0xE067, 0x9103, + 0xE068, 0x9105, 0xE069, 0x9106, 0xE06A, 0x9107, 0xE06B, 0x9108, 0xE06C, 0x9109, 0xE06D, 0x910A, 0xE06E, 0x910B, 0xE06F, 0x910C, + 0xE070, 0x910D, 0xE071, 0x910E, 0xE072, 0x910F, 0xE073, 0x9110, 0xE074, 0x9111, 0xE075, 0x9112, 0xE076, 0x9113, 0xE077, 0x9114, + 0xE078, 0x9115, 0xE079, 0x9116, 0xE07A, 0x9117, 0xE07B, 0x9118, 0xE07C, 0x911A, 0xE07D, 0x911B, 0xE07E, 0x911C, 0xE080, 0x911D, + 0xE081, 0x911F, 0xE082, 0x9120, 0xE083, 0x9121, 0xE084, 0x9124, 0xE085, 0x9125, 0xE086, 0x9126, 0xE087, 0x9127, 0xE088, 0x9128, + 0xE089, 0x9129, 0xE08A, 0x912A, 0xE08B, 0x912B, 0xE08C, 0x912C, 0xE08D, 0x912D, 0xE08E, 0x912E, 0xE08F, 0x9130, 0xE090, 0x9132, + 0xE091, 0x9133, 0xE092, 0x9134, 0xE093, 0x9135, 0xE094, 0x9136, 0xE095, 0x9137, 0xE096, 0x9138, 0xE097, 0x913A, 0xE098, 0x913B, + 0xE099, 0x913C, 0xE09A, 0x913D, 0xE09B, 0x913E, 0xE09C, 0x913F, 0xE09D, 0x9140, 0xE09E, 0x9141, 0xE09F, 0x9142, 0xE0A0, 0x9144, + 0xE0A1, 0x5537, 0xE0A2, 0x5556, 0xE0A3, 0x5575, 0xE0A4, 0x5576, 0xE0A5, 0x5577, 0xE0A6, 0x5533, 0xE0A7, 0x5530, 0xE0A8, 0x555C, + 0xE0A9, 0x558B, 0xE0AA, 0x55D2, 0xE0AB, 0x5583, 0xE0AC, 0x55B1, 0xE0AD, 0x55B9, 0xE0AE, 0x5588, 0xE0AF, 0x5581, 0xE0B0, 0x559F, + 0xE0B1, 0x557E, 0xE0B2, 0x55D6, 0xE0B3, 0x5591, 0xE0B4, 0x557B, 0xE0B5, 0x55DF, 0xE0B6, 0x55BD, 0xE0B7, 0x55BE, 0xE0B8, 0x5594, + 0xE0B9, 0x5599, 0xE0BA, 0x55EA, 0xE0BB, 0x55F7, 0xE0BC, 0x55C9, 0xE0BD, 0x561F, 0xE0BE, 0x55D1, 0xE0BF, 0x55EB, 0xE0C0, 0x55EC, + 0xE0C1, 0x55D4, 0xE0C2, 0x55E6, 0xE0C3, 0x55DD, 0xE0C4, 0x55C4, 0xE0C5, 0x55EF, 0xE0C6, 0x55E5, 0xE0C7, 0x55F2, 0xE0C8, 0x55F3, + 0xE0C9, 0x55CC, 0xE0CA, 0x55CD, 0xE0CB, 0x55E8, 0xE0CC, 0x55F5, 0xE0CD, 0x55E4, 0xE0CE, 0x8F94, 0xE0CF, 0x561E, 0xE0D0, 0x5608, + 0xE0D1, 0x560C, 0xE0D2, 0x5601, 0xE0D3, 0x5624, 0xE0D4, 0x5623, 0xE0D5, 0x55FE, 0xE0D6, 0x5600, 0xE0D7, 0x5627, 0xE0D8, 0x562D, + 0xE0D9, 0x5658, 0xE0DA, 0x5639, 0xE0DB, 0x5657, 0xE0DC, 0x562C, 0xE0DD, 0x564D, 0xE0DE, 0x5662, 0xE0DF, 0x5659, 0xE0E0, 0x565C, + 0xE0E1, 0x564C, 0xE0E2, 0x5654, 0xE0E3, 0x5686, 0xE0E4, 0x5664, 0xE0E5, 0x5671, 0xE0E6, 0x566B, 0xE0E7, 0x567B, 0xE0E8, 0x567C, + 0xE0E9, 0x5685, 0xE0EA, 0x5693, 0xE0EB, 0x56AF, 0xE0EC, 0x56D4, 0xE0ED, 0x56D7, 0xE0EE, 0x56DD, 0xE0EF, 0x56E1, 0xE0F0, 0x56F5, + 0xE0F1, 0x56EB, 0xE0F2, 0x56F9, 0xE0F3, 0x56FF, 0xE0F4, 0x5704, 0xE0F5, 0x570A, 0xE0F6, 0x5709, 0xE0F7, 0x571C, 0xE0F8, 0x5E0F, + 0xE0F9, 0x5E19, 0xE0FA, 0x5E14, 0xE0FB, 0x5E11, 0xE0FC, 0x5E31, 0xE0FD, 0x5E3B, 0xE0FE, 0x5E3C, 0xE140, 0x9145, 0xE141, 0x9147, + 0xE142, 0x9148, 0xE143, 0x9151, 0xE144, 0x9153, 0xE145, 0x9154, 0xE146, 0x9155, 0xE147, 0x9156, 0xE148, 0x9158, 0xE149, 0x9159, + 0xE14A, 0x915B, 0xE14B, 0x915C, 0xE14C, 0x915F, 0xE14D, 0x9160, 0xE14E, 0x9166, 0xE14F, 0x9167, 0xE150, 0x9168, 0xE151, 0x916B, + 0xE152, 0x916D, 0xE153, 0x9173, 0xE154, 0x917A, 0xE155, 0x917B, 0xE156, 0x917C, 0xE157, 0x9180, 0xE158, 0x9181, 0xE159, 0x9182, + 0xE15A, 0x9183, 0xE15B, 0x9184, 0xE15C, 0x9186, 0xE15D, 0x9188, 0xE15E, 0x918A, 0xE15F, 0x918E, 0xE160, 0x918F, 0xE161, 0x9193, + 0xE162, 0x9194, 0xE163, 0x9195, 0xE164, 0x9196, 0xE165, 0x9197, 0xE166, 0x9198, 0xE167, 0x9199, 0xE168, 0x919C, 0xE169, 0x919D, + 0xE16A, 0x919E, 0xE16B, 0x919F, 0xE16C, 0x91A0, 0xE16D, 0x91A1, 0xE16E, 0x91A4, 0xE16F, 0x91A5, 0xE170, 0x91A6, 0xE171, 0x91A7, + 0xE172, 0x91A8, 0xE173, 0x91A9, 0xE174, 0x91AB, 0xE175, 0x91AC, 0xE176, 0x91B0, 0xE177, 0x91B1, 0xE178, 0x91B2, 0xE179, 0x91B3, + 0xE17A, 0x91B6, 0xE17B, 0x91B7, 0xE17C, 0x91B8, 0xE17D, 0x91B9, 0xE17E, 0x91BB, 0xE180, 0x91BC, 0xE181, 0x91BD, 0xE182, 0x91BE, + 0xE183, 0x91BF, 0xE184, 0x91C0, 0xE185, 0x91C1, 0xE186, 0x91C2, 0xE187, 0x91C3, 0xE188, 0x91C4, 0xE189, 0x91C5, 0xE18A, 0x91C6, + 0xE18B, 0x91C8, 0xE18C, 0x91CB, 0xE18D, 0x91D0, 0xE18E, 0x91D2, 0xE18F, 0x91D3, 0xE190, 0x91D4, 0xE191, 0x91D5, 0xE192, 0x91D6, + 0xE193, 0x91D7, 0xE194, 0x91D8, 0xE195, 0x91D9, 0xE196, 0x91DA, 0xE197, 0x91DB, 0xE198, 0x91DD, 0xE199, 0x91DE, 0xE19A, 0x91DF, + 0xE19B, 0x91E0, 0xE19C, 0x91E1, 0xE19D, 0x91E2, 0xE19E, 0x91E3, 0xE19F, 0x91E4, 0xE1A0, 0x91E5, 0xE1A1, 0x5E37, 0xE1A2, 0x5E44, + 0xE1A3, 0x5E54, 0xE1A4, 0x5E5B, 0xE1A5, 0x5E5E, 0xE1A6, 0x5E61, 0xE1A7, 0x5C8C, 0xE1A8, 0x5C7A, 0xE1A9, 0x5C8D, 0xE1AA, 0x5C90, + 0xE1AB, 0x5C96, 0xE1AC, 0x5C88, 0xE1AD, 0x5C98, 0xE1AE, 0x5C99, 0xE1AF, 0x5C91, 0xE1B0, 0x5C9A, 0xE1B1, 0x5C9C, 0xE1B2, 0x5CB5, + 0xE1B3, 0x5CA2, 0xE1B4, 0x5CBD, 0xE1B5, 0x5CAC, 0xE1B6, 0x5CAB, 0xE1B7, 0x5CB1, 0xE1B8, 0x5CA3, 0xE1B9, 0x5CC1, 0xE1BA, 0x5CB7, + 0xE1BB, 0x5CC4, 0xE1BC, 0x5CD2, 0xE1BD, 0x5CE4, 0xE1BE, 0x5CCB, 0xE1BF, 0x5CE5, 0xE1C0, 0x5D02, 0xE1C1, 0x5D03, 0xE1C2, 0x5D27, + 0xE1C3, 0x5D26, 0xE1C4, 0x5D2E, 0xE1C5, 0x5D24, 0xE1C6, 0x5D1E, 0xE1C7, 0x5D06, 0xE1C8, 0x5D1B, 0xE1C9, 0x5D58, 0xE1CA, 0x5D3E, + 0xE1CB, 0x5D34, 0xE1CC, 0x5D3D, 0xE1CD, 0x5D6C, 0xE1CE, 0x5D5B, 0xE1CF, 0x5D6F, 0xE1D0, 0x5D5D, 0xE1D1, 0x5D6B, 0xE1D2, 0x5D4B, + 0xE1D3, 0x5D4A, 0xE1D4, 0x5D69, 0xE1D5, 0x5D74, 0xE1D6, 0x5D82, 0xE1D7, 0x5D99, 0xE1D8, 0x5D9D, 0xE1D9, 0x8C73, 0xE1DA, 0x5DB7, + 0xE1DB, 0x5DC5, 0xE1DC, 0x5F73, 0xE1DD, 0x5F77, 0xE1DE, 0x5F82, 0xE1DF, 0x5F87, 0xE1E0, 0x5F89, 0xE1E1, 0x5F8C, 0xE1E2, 0x5F95, + 0xE1E3, 0x5F99, 0xE1E4, 0x5F9C, 0xE1E5, 0x5FA8, 0xE1E6, 0x5FAD, 0xE1E7, 0x5FB5, 0xE1E8, 0x5FBC, 0xE1E9, 0x8862, 0xE1EA, 0x5F61, + 0xE1EB, 0x72AD, 0xE1EC, 0x72B0, 0xE1ED, 0x72B4, 0xE1EE, 0x72B7, 0xE1EF, 0x72B8, 0xE1F0, 0x72C3, 0xE1F1, 0x72C1, 0xE1F2, 0x72CE, + 0xE1F3, 0x72CD, 0xE1F4, 0x72D2, 0xE1F5, 0x72E8, 0xE1F6, 0x72EF, 0xE1F7, 0x72E9, 0xE1F8, 0x72F2, 0xE1F9, 0x72F4, 0xE1FA, 0x72F7, + 0xE1FB, 0x7301, 0xE1FC, 0x72F3, 0xE1FD, 0x7303, 0xE1FE, 0x72FA, 0xE240, 0x91E6, 0xE241, 0x91E7, 0xE242, 0x91E8, 0xE243, 0x91E9, + 0xE244, 0x91EA, 0xE245, 0x91EB, 0xE246, 0x91EC, 0xE247, 0x91ED, 0xE248, 0x91EE, 0xE249, 0x91EF, 0xE24A, 0x91F0, 0xE24B, 0x91F1, + 0xE24C, 0x91F2, 0xE24D, 0x91F3, 0xE24E, 0x91F4, 0xE24F, 0x91F5, 0xE250, 0x91F6, 0xE251, 0x91F7, 0xE252, 0x91F8, 0xE253, 0x91F9, + 0xE254, 0x91FA, 0xE255, 0x91FB, 0xE256, 0x91FC, 0xE257, 0x91FD, 0xE258, 0x91FE, 0xE259, 0x91FF, 0xE25A, 0x9200, 0xE25B, 0x9201, + 0xE25C, 0x9202, 0xE25D, 0x9203, 0xE25E, 0x9204, 0xE25F, 0x9205, 0xE260, 0x9206, 0xE261, 0x9207, 0xE262, 0x9208, 0xE263, 0x9209, + 0xE264, 0x920A, 0xE265, 0x920B, 0xE266, 0x920C, 0xE267, 0x920D, 0xE268, 0x920E, 0xE269, 0x920F, 0xE26A, 0x9210, 0xE26B, 0x9211, + 0xE26C, 0x9212, 0xE26D, 0x9213, 0xE26E, 0x9214, 0xE26F, 0x9215, 0xE270, 0x9216, 0xE271, 0x9217, 0xE272, 0x9218, 0xE273, 0x9219, + 0xE274, 0x921A, 0xE275, 0x921B, 0xE276, 0x921C, 0xE277, 0x921D, 0xE278, 0x921E, 0xE279, 0x921F, 0xE27A, 0x9220, 0xE27B, 0x9221, + 0xE27C, 0x9222, 0xE27D, 0x9223, 0xE27E, 0x9224, 0xE280, 0x9225, 0xE281, 0x9226, 0xE282, 0x9227, 0xE283, 0x9228, 0xE284, 0x9229, + 0xE285, 0x922A, 0xE286, 0x922B, 0xE287, 0x922C, 0xE288, 0x922D, 0xE289, 0x922E, 0xE28A, 0x922F, 0xE28B, 0x9230, 0xE28C, 0x9231, + 0xE28D, 0x9232, 0xE28E, 0x9233, 0xE28F, 0x9234, 0xE290, 0x9235, 0xE291, 0x9236, 0xE292, 0x9237, 0xE293, 0x9238, 0xE294, 0x9239, + 0xE295, 0x923A, 0xE296, 0x923B, 0xE297, 0x923C, 0xE298, 0x923D, 0xE299, 0x923E, 0xE29A, 0x923F, 0xE29B, 0x9240, 0xE29C, 0x9241, + 0xE29D, 0x9242, 0xE29E, 0x9243, 0xE29F, 0x9244, 0xE2A0, 0x9245, 0xE2A1, 0x72FB, 0xE2A2, 0x7317, 0xE2A3, 0x7313, 0xE2A4, 0x7321, + 0xE2A5, 0x730A, 0xE2A6, 0x731E, 0xE2A7, 0x731D, 0xE2A8, 0x7315, 0xE2A9, 0x7322, 0xE2AA, 0x7339, 0xE2AB, 0x7325, 0xE2AC, 0x732C, + 0xE2AD, 0x7338, 0xE2AE, 0x7331, 0xE2AF, 0x7350, 0xE2B0, 0x734D, 0xE2B1, 0x7357, 0xE2B2, 0x7360, 0xE2B3, 0x736C, 0xE2B4, 0x736F, + 0xE2B5, 0x737E, 0xE2B6, 0x821B, 0xE2B7, 0x5925, 0xE2B8, 0x98E7, 0xE2B9, 0x5924, 0xE2BA, 0x5902, 0xE2BB, 0x9963, 0xE2BC, 0x9967, + 0xE2BD, 0x9968, 0xE2BE, 0x9969, 0xE2BF, 0x996A, 0xE2C0, 0x996B, 0xE2C1, 0x996C, 0xE2C2, 0x9974, 0xE2C3, 0x9977, 0xE2C4, 0x997D, + 0xE2C5, 0x9980, 0xE2C6, 0x9984, 0xE2C7, 0x9987, 0xE2C8, 0x998A, 0xE2C9, 0x998D, 0xE2CA, 0x9990, 0xE2CB, 0x9991, 0xE2CC, 0x9993, + 0xE2CD, 0x9994, 0xE2CE, 0x9995, 0xE2CF, 0x5E80, 0xE2D0, 0x5E91, 0xE2D1, 0x5E8B, 0xE2D2, 0x5E96, 0xE2D3, 0x5EA5, 0xE2D4, 0x5EA0, + 0xE2D5, 0x5EB9, 0xE2D6, 0x5EB5, 0xE2D7, 0x5EBE, 0xE2D8, 0x5EB3, 0xE2D9, 0x8D53, 0xE2DA, 0x5ED2, 0xE2DB, 0x5ED1, 0xE2DC, 0x5EDB, + 0xE2DD, 0x5EE8, 0xE2DE, 0x5EEA, 0xE2DF, 0x81BA, 0xE2E0, 0x5FC4, 0xE2E1, 0x5FC9, 0xE2E2, 0x5FD6, 0xE2E3, 0x5FCF, 0xE2E4, 0x6003, + 0xE2E5, 0x5FEE, 0xE2E6, 0x6004, 0xE2E7, 0x5FE1, 0xE2E8, 0x5FE4, 0xE2E9, 0x5FFE, 0xE2EA, 0x6005, 0xE2EB, 0x6006, 0xE2EC, 0x5FEA, + 0xE2ED, 0x5FED, 0xE2EE, 0x5FF8, 0xE2EF, 0x6019, 0xE2F0, 0x6035, 0xE2F1, 0x6026, 0xE2F2, 0x601B, 0xE2F3, 0x600F, 0xE2F4, 0x600D, + 0xE2F5, 0x6029, 0xE2F6, 0x602B, 0xE2F7, 0x600A, 0xE2F8, 0x603F, 0xE2F9, 0x6021, 0xE2FA, 0x6078, 0xE2FB, 0x6079, 0xE2FC, 0x607B, + 0xE2FD, 0x607A, 0xE2FE, 0x6042, 0xE340, 0x9246, 0xE341, 0x9247, 0xE342, 0x9248, 0xE343, 0x9249, 0xE344, 0x924A, 0xE345, 0x924B, + 0xE346, 0x924C, 0xE347, 0x924D, 0xE348, 0x924E, 0xE349, 0x924F, 0xE34A, 0x9250, 0xE34B, 0x9251, 0xE34C, 0x9252, 0xE34D, 0x9253, + 0xE34E, 0x9254, 0xE34F, 0x9255, 0xE350, 0x9256, 0xE351, 0x9257, 0xE352, 0x9258, 0xE353, 0x9259, 0xE354, 0x925A, 0xE355, 0x925B, + 0xE356, 0x925C, 0xE357, 0x925D, 0xE358, 0x925E, 0xE359, 0x925F, 0xE35A, 0x9260, 0xE35B, 0x9261, 0xE35C, 0x9262, 0xE35D, 0x9263, + 0xE35E, 0x9264, 0xE35F, 0x9265, 0xE360, 0x9266, 0xE361, 0x9267, 0xE362, 0x9268, 0xE363, 0x9269, 0xE364, 0x926A, 0xE365, 0x926B, + 0xE366, 0x926C, 0xE367, 0x926D, 0xE368, 0x926E, 0xE369, 0x926F, 0xE36A, 0x9270, 0xE36B, 0x9271, 0xE36C, 0x9272, 0xE36D, 0x9273, + 0xE36E, 0x9275, 0xE36F, 0x9276, 0xE370, 0x9277, 0xE371, 0x9278, 0xE372, 0x9279, 0xE373, 0x927A, 0xE374, 0x927B, 0xE375, 0x927C, + 0xE376, 0x927D, 0xE377, 0x927E, 0xE378, 0x927F, 0xE379, 0x9280, 0xE37A, 0x9281, 0xE37B, 0x9282, 0xE37C, 0x9283, 0xE37D, 0x9284, + 0xE37E, 0x9285, 0xE380, 0x9286, 0xE381, 0x9287, 0xE382, 0x9288, 0xE383, 0x9289, 0xE384, 0x928A, 0xE385, 0x928B, 0xE386, 0x928C, + 0xE387, 0x928D, 0xE388, 0x928F, 0xE389, 0x9290, 0xE38A, 0x9291, 0xE38B, 0x9292, 0xE38C, 0x9293, 0xE38D, 0x9294, 0xE38E, 0x9295, + 0xE38F, 0x9296, 0xE390, 0x9297, 0xE391, 0x9298, 0xE392, 0x9299, 0xE393, 0x929A, 0xE394, 0x929B, 0xE395, 0x929C, 0xE396, 0x929D, + 0xE397, 0x929E, 0xE398, 0x929F, 0xE399, 0x92A0, 0xE39A, 0x92A1, 0xE39B, 0x92A2, 0xE39C, 0x92A3, 0xE39D, 0x92A4, 0xE39E, 0x92A5, + 0xE39F, 0x92A6, 0xE3A0, 0x92A7, 0xE3A1, 0x606A, 0xE3A2, 0x607D, 0xE3A3, 0x6096, 0xE3A4, 0x609A, 0xE3A5, 0x60AD, 0xE3A6, 0x609D, + 0xE3A7, 0x6083, 0xE3A8, 0x6092, 0xE3A9, 0x608C, 0xE3AA, 0x609B, 0xE3AB, 0x60EC, 0xE3AC, 0x60BB, 0xE3AD, 0x60B1, 0xE3AE, 0x60DD, + 0xE3AF, 0x60D8, 0xE3B0, 0x60C6, 0xE3B1, 0x60DA, 0xE3B2, 0x60B4, 0xE3B3, 0x6120, 0xE3B4, 0x6126, 0xE3B5, 0x6115, 0xE3B6, 0x6123, + 0xE3B7, 0x60F4, 0xE3B8, 0x6100, 0xE3B9, 0x610E, 0xE3BA, 0x612B, 0xE3BB, 0x614A, 0xE3BC, 0x6175, 0xE3BD, 0x61AC, 0xE3BE, 0x6194, + 0xE3BF, 0x61A7, 0xE3C0, 0x61B7, 0xE3C1, 0x61D4, 0xE3C2, 0x61F5, 0xE3C3, 0x5FDD, 0xE3C4, 0x96B3, 0xE3C5, 0x95E9, 0xE3C6, 0x95EB, + 0xE3C7, 0x95F1, 0xE3C8, 0x95F3, 0xE3C9, 0x95F5, 0xE3CA, 0x95F6, 0xE3CB, 0x95FC, 0xE3CC, 0x95FE, 0xE3CD, 0x9603, 0xE3CE, 0x9604, + 0xE3CF, 0x9606, 0xE3D0, 0x9608, 0xE3D1, 0x960A, 0xE3D2, 0x960B, 0xE3D3, 0x960C, 0xE3D4, 0x960D, 0xE3D5, 0x960F, 0xE3D6, 0x9612, + 0xE3D7, 0x9615, 0xE3D8, 0x9616, 0xE3D9, 0x9617, 0xE3DA, 0x9619, 0xE3DB, 0x961A, 0xE3DC, 0x4E2C, 0xE3DD, 0x723F, 0xE3DE, 0x6215, + 0xE3DF, 0x6C35, 0xE3E0, 0x6C54, 0xE3E1, 0x6C5C, 0xE3E2, 0x6C4A, 0xE3E3, 0x6CA3, 0xE3E4, 0x6C85, 0xE3E5, 0x6C90, 0xE3E6, 0x6C94, + 0xE3E7, 0x6C8C, 0xE3E8, 0x6C68, 0xE3E9, 0x6C69, 0xE3EA, 0x6C74, 0xE3EB, 0x6C76, 0xE3EC, 0x6C86, 0xE3ED, 0x6CA9, 0xE3EE, 0x6CD0, + 0xE3EF, 0x6CD4, 0xE3F0, 0x6CAD, 0xE3F1, 0x6CF7, 0xE3F2, 0x6CF8, 0xE3F3, 0x6CF1, 0xE3F4, 0x6CD7, 0xE3F5, 0x6CB2, 0xE3F6, 0x6CE0, + 0xE3F7, 0x6CD6, 0xE3F8, 0x6CFA, 0xE3F9, 0x6CEB, 0xE3FA, 0x6CEE, 0xE3FB, 0x6CB1, 0xE3FC, 0x6CD3, 0xE3FD, 0x6CEF, 0xE3FE, 0x6CFE, + 0xE440, 0x92A8, 0xE441, 0x92A9, 0xE442, 0x92AA, 0xE443, 0x92AB, 0xE444, 0x92AC, 0xE445, 0x92AD, 0xE446, 0x92AF, 0xE447, 0x92B0, + 0xE448, 0x92B1, 0xE449, 0x92B2, 0xE44A, 0x92B3, 0xE44B, 0x92B4, 0xE44C, 0x92B5, 0xE44D, 0x92B6, 0xE44E, 0x92B7, 0xE44F, 0x92B8, + 0xE450, 0x92B9, 0xE451, 0x92BA, 0xE452, 0x92BB, 0xE453, 0x92BC, 0xE454, 0x92BD, 0xE455, 0x92BE, 0xE456, 0x92BF, 0xE457, 0x92C0, + 0xE458, 0x92C1, 0xE459, 0x92C2, 0xE45A, 0x92C3, 0xE45B, 0x92C4, 0xE45C, 0x92C5, 0xE45D, 0x92C6, 0xE45E, 0x92C7, 0xE45F, 0x92C9, + 0xE460, 0x92CA, 0xE461, 0x92CB, 0xE462, 0x92CC, 0xE463, 0x92CD, 0xE464, 0x92CE, 0xE465, 0x92CF, 0xE466, 0x92D0, 0xE467, 0x92D1, + 0xE468, 0x92D2, 0xE469, 0x92D3, 0xE46A, 0x92D4, 0xE46B, 0x92D5, 0xE46C, 0x92D6, 0xE46D, 0x92D7, 0xE46E, 0x92D8, 0xE46F, 0x92D9, + 0xE470, 0x92DA, 0xE471, 0x92DB, 0xE472, 0x92DC, 0xE473, 0x92DD, 0xE474, 0x92DE, 0xE475, 0x92DF, 0xE476, 0x92E0, 0xE477, 0x92E1, + 0xE478, 0x92E2, 0xE479, 0x92E3, 0xE47A, 0x92E4, 0xE47B, 0x92E5, 0xE47C, 0x92E6, 0xE47D, 0x92E7, 0xE47E, 0x92E8, 0xE480, 0x92E9, + 0xE481, 0x92EA, 0xE482, 0x92EB, 0xE483, 0x92EC, 0xE484, 0x92ED, 0xE485, 0x92EE, 0xE486, 0x92EF, 0xE487, 0x92F0, 0xE488, 0x92F1, + 0xE489, 0x92F2, 0xE48A, 0x92F3, 0xE48B, 0x92F4, 0xE48C, 0x92F5, 0xE48D, 0x92F6, 0xE48E, 0x92F7, 0xE48F, 0x92F8, 0xE490, 0x92F9, + 0xE491, 0x92FA, 0xE492, 0x92FB, 0xE493, 0x92FC, 0xE494, 0x92FD, 0xE495, 0x92FE, 0xE496, 0x92FF, 0xE497, 0x9300, 0xE498, 0x9301, + 0xE499, 0x9302, 0xE49A, 0x9303, 0xE49B, 0x9304, 0xE49C, 0x9305, 0xE49D, 0x9306, 0xE49E, 0x9307, 0xE49F, 0x9308, 0xE4A0, 0x9309, + 0xE4A1, 0x6D39, 0xE4A2, 0x6D27, 0xE4A3, 0x6D0C, 0xE4A4, 0x6D43, 0xE4A5, 0x6D48, 0xE4A6, 0x6D07, 0xE4A7, 0x6D04, 0xE4A8, 0x6D19, + 0xE4A9, 0x6D0E, 0xE4AA, 0x6D2B, 0xE4AB, 0x6D4D, 0xE4AC, 0x6D2E, 0xE4AD, 0x6D35, 0xE4AE, 0x6D1A, 0xE4AF, 0x6D4F, 0xE4B0, 0x6D52, + 0xE4B1, 0x6D54, 0xE4B2, 0x6D33, 0xE4B3, 0x6D91, 0xE4B4, 0x6D6F, 0xE4B5, 0x6D9E, 0xE4B6, 0x6DA0, 0xE4B7, 0x6D5E, 0xE4B8, 0x6D93, + 0xE4B9, 0x6D94, 0xE4BA, 0x6D5C, 0xE4BB, 0x6D60, 0xE4BC, 0x6D7C, 0xE4BD, 0x6D63, 0xE4BE, 0x6E1A, 0xE4BF, 0x6DC7, 0xE4C0, 0x6DC5, + 0xE4C1, 0x6DDE, 0xE4C2, 0x6E0E, 0xE4C3, 0x6DBF, 0xE4C4, 0x6DE0, 0xE4C5, 0x6E11, 0xE4C6, 0x6DE6, 0xE4C7, 0x6DDD, 0xE4C8, 0x6DD9, + 0xE4C9, 0x6E16, 0xE4CA, 0x6DAB, 0xE4CB, 0x6E0C, 0xE4CC, 0x6DAE, 0xE4CD, 0x6E2B, 0xE4CE, 0x6E6E, 0xE4CF, 0x6E4E, 0xE4D0, 0x6E6B, + 0xE4D1, 0x6EB2, 0xE4D2, 0x6E5F, 0xE4D3, 0x6E86, 0xE4D4, 0x6E53, 0xE4D5, 0x6E54, 0xE4D6, 0x6E32, 0xE4D7, 0x6E25, 0xE4D8, 0x6E44, + 0xE4D9, 0x6EDF, 0xE4DA, 0x6EB1, 0xE4DB, 0x6E98, 0xE4DC, 0x6EE0, 0xE4DD, 0x6F2D, 0xE4DE, 0x6EE2, 0xE4DF, 0x6EA5, 0xE4E0, 0x6EA7, + 0xE4E1, 0x6EBD, 0xE4E2, 0x6EBB, 0xE4E3, 0x6EB7, 0xE4E4, 0x6ED7, 0xE4E5, 0x6EB4, 0xE4E6, 0x6ECF, 0xE4E7, 0x6E8F, 0xE4E8, 0x6EC2, + 0xE4E9, 0x6E9F, 0xE4EA, 0x6F62, 0xE4EB, 0x6F46, 0xE4EC, 0x6F47, 0xE4ED, 0x6F24, 0xE4EE, 0x6F15, 0xE4EF, 0x6EF9, 0xE4F0, 0x6F2F, + 0xE4F1, 0x6F36, 0xE4F2, 0x6F4B, 0xE4F3, 0x6F74, 0xE4F4, 0x6F2A, 0xE4F5, 0x6F09, 0xE4F6, 0x6F29, 0xE4F7, 0x6F89, 0xE4F8, 0x6F8D, + 0xE4F9, 0x6F8C, 0xE4FA, 0x6F78, 0xE4FB, 0x6F72, 0xE4FC, 0x6F7C, 0xE4FD, 0x6F7A, 0xE4FE, 0x6FD1, 0xE540, 0x930A, 0xE541, 0x930B, + 0xE542, 0x930C, 0xE543, 0x930D, 0xE544, 0x930E, 0xE545, 0x930F, 0xE546, 0x9310, 0xE547, 0x9311, 0xE548, 0x9312, 0xE549, 0x9313, + 0xE54A, 0x9314, 0xE54B, 0x9315, 0xE54C, 0x9316, 0xE54D, 0x9317, 0xE54E, 0x9318, 0xE54F, 0x9319, 0xE550, 0x931A, 0xE551, 0x931B, + 0xE552, 0x931C, 0xE553, 0x931D, 0xE554, 0x931E, 0xE555, 0x931F, 0xE556, 0x9320, 0xE557, 0x9321, 0xE558, 0x9322, 0xE559, 0x9323, + 0xE55A, 0x9324, 0xE55B, 0x9325, 0xE55C, 0x9326, 0xE55D, 0x9327, 0xE55E, 0x9328, 0xE55F, 0x9329, 0xE560, 0x932A, 0xE561, 0x932B, + 0xE562, 0x932C, 0xE563, 0x932D, 0xE564, 0x932E, 0xE565, 0x932F, 0xE566, 0x9330, 0xE567, 0x9331, 0xE568, 0x9332, 0xE569, 0x9333, + 0xE56A, 0x9334, 0xE56B, 0x9335, 0xE56C, 0x9336, 0xE56D, 0x9337, 0xE56E, 0x9338, 0xE56F, 0x9339, 0xE570, 0x933A, 0xE571, 0x933B, + 0xE572, 0x933C, 0xE573, 0x933D, 0xE574, 0x933F, 0xE575, 0x9340, 0xE576, 0x9341, 0xE577, 0x9342, 0xE578, 0x9343, 0xE579, 0x9344, + 0xE57A, 0x9345, 0xE57B, 0x9346, 0xE57C, 0x9347, 0xE57D, 0x9348, 0xE57E, 0x9349, 0xE580, 0x934A, 0xE581, 0x934B, 0xE582, 0x934C, + 0xE583, 0x934D, 0xE584, 0x934E, 0xE585, 0x934F, 0xE586, 0x9350, 0xE587, 0x9351, 0xE588, 0x9352, 0xE589, 0x9353, 0xE58A, 0x9354, + 0xE58B, 0x9355, 0xE58C, 0x9356, 0xE58D, 0x9357, 0xE58E, 0x9358, 0xE58F, 0x9359, 0xE590, 0x935A, 0xE591, 0x935B, 0xE592, 0x935C, + 0xE593, 0x935D, 0xE594, 0x935E, 0xE595, 0x935F, 0xE596, 0x9360, 0xE597, 0x9361, 0xE598, 0x9362, 0xE599, 0x9363, 0xE59A, 0x9364, + 0xE59B, 0x9365, 0xE59C, 0x9366, 0xE59D, 0x9367, 0xE59E, 0x9368, 0xE59F, 0x9369, 0xE5A0, 0x936B, 0xE5A1, 0x6FC9, 0xE5A2, 0x6FA7, + 0xE5A3, 0x6FB9, 0xE5A4, 0x6FB6, 0xE5A5, 0x6FC2, 0xE5A6, 0x6FE1, 0xE5A7, 0x6FEE, 0xE5A8, 0x6FDE, 0xE5A9, 0x6FE0, 0xE5AA, 0x6FEF, + 0xE5AB, 0x701A, 0xE5AC, 0x7023, 0xE5AD, 0x701B, 0xE5AE, 0x7039, 0xE5AF, 0x7035, 0xE5B0, 0x704F, 0xE5B1, 0x705E, 0xE5B2, 0x5B80, + 0xE5B3, 0x5B84, 0xE5B4, 0x5B95, 0xE5B5, 0x5B93, 0xE5B6, 0x5BA5, 0xE5B7, 0x5BB8, 0xE5B8, 0x752F, 0xE5B9, 0x9A9E, 0xE5BA, 0x6434, + 0xE5BB, 0x5BE4, 0xE5BC, 0x5BEE, 0xE5BD, 0x8930, 0xE5BE, 0x5BF0, 0xE5BF, 0x8E47, 0xE5C0, 0x8B07, 0xE5C1, 0x8FB6, 0xE5C2, 0x8FD3, + 0xE5C3, 0x8FD5, 0xE5C4, 0x8FE5, 0xE5C5, 0x8FEE, 0xE5C6, 0x8FE4, 0xE5C7, 0x8FE9, 0xE5C8, 0x8FE6, 0xE5C9, 0x8FF3, 0xE5CA, 0x8FE8, + 0xE5CB, 0x9005, 0xE5CC, 0x9004, 0xE5CD, 0x900B, 0xE5CE, 0x9026, 0xE5CF, 0x9011, 0xE5D0, 0x900D, 0xE5D1, 0x9016, 0xE5D2, 0x9021, + 0xE5D3, 0x9035, 0xE5D4, 0x9036, 0xE5D5, 0x902D, 0xE5D6, 0x902F, 0xE5D7, 0x9044, 0xE5D8, 0x9051, 0xE5D9, 0x9052, 0xE5DA, 0x9050, + 0xE5DB, 0x9068, 0xE5DC, 0x9058, 0xE5DD, 0x9062, 0xE5DE, 0x905B, 0xE5DF, 0x66B9, 0xE5E0, 0x9074, 0xE5E1, 0x907D, 0xE5E2, 0x9082, + 0xE5E3, 0x9088, 0xE5E4, 0x9083, 0xE5E5, 0x908B, 0xE5E6, 0x5F50, 0xE5E7, 0x5F57, 0xE5E8, 0x5F56, 0xE5E9, 0x5F58, 0xE5EA, 0x5C3B, + 0xE5EB, 0x54AB, 0xE5EC, 0x5C50, 0xE5ED, 0x5C59, 0xE5EE, 0x5B71, 0xE5EF, 0x5C63, 0xE5F0, 0x5C66, 0xE5F1, 0x7FBC, 0xE5F2, 0x5F2A, + 0xE5F3, 0x5F29, 0xE5F4, 0x5F2D, 0xE5F5, 0x8274, 0xE5F6, 0x5F3C, 0xE5F7, 0x9B3B, 0xE5F8, 0x5C6E, 0xE5F9, 0x5981, 0xE5FA, 0x5983, + 0xE5FB, 0x598D, 0xE5FC, 0x59A9, 0xE5FD, 0x59AA, 0xE5FE, 0x59A3, 0xE640, 0x936C, 0xE641, 0x936D, 0xE642, 0x936E, 0xE643, 0x936F, + 0xE644, 0x9370, 0xE645, 0x9371, 0xE646, 0x9372, 0xE647, 0x9373, 0xE648, 0x9374, 0xE649, 0x9375, 0xE64A, 0x9376, 0xE64B, 0x9377, + 0xE64C, 0x9378, 0xE64D, 0x9379, 0xE64E, 0x937A, 0xE64F, 0x937B, 0xE650, 0x937C, 0xE651, 0x937D, 0xE652, 0x937E, 0xE653, 0x937F, + 0xE654, 0x9380, 0xE655, 0x9381, 0xE656, 0x9382, 0xE657, 0x9383, 0xE658, 0x9384, 0xE659, 0x9385, 0xE65A, 0x9386, 0xE65B, 0x9387, + 0xE65C, 0x9388, 0xE65D, 0x9389, 0xE65E, 0x938A, 0xE65F, 0x938B, 0xE660, 0x938C, 0xE661, 0x938D, 0xE662, 0x938E, 0xE663, 0x9390, + 0xE664, 0x9391, 0xE665, 0x9392, 0xE666, 0x9393, 0xE667, 0x9394, 0xE668, 0x9395, 0xE669, 0x9396, 0xE66A, 0x9397, 0xE66B, 0x9398, + 0xE66C, 0x9399, 0xE66D, 0x939A, 0xE66E, 0x939B, 0xE66F, 0x939C, 0xE670, 0x939D, 0xE671, 0x939E, 0xE672, 0x939F, 0xE673, 0x93A0, + 0xE674, 0x93A1, 0xE675, 0x93A2, 0xE676, 0x93A3, 0xE677, 0x93A4, 0xE678, 0x93A5, 0xE679, 0x93A6, 0xE67A, 0x93A7, 0xE67B, 0x93A8, + 0xE67C, 0x93A9, 0xE67D, 0x93AA, 0xE67E, 0x93AB, 0xE680, 0x93AC, 0xE681, 0x93AD, 0xE682, 0x93AE, 0xE683, 0x93AF, 0xE684, 0x93B0, + 0xE685, 0x93B1, 0xE686, 0x93B2, 0xE687, 0x93B3, 0xE688, 0x93B4, 0xE689, 0x93B5, 0xE68A, 0x93B6, 0xE68B, 0x93B7, 0xE68C, 0x93B8, + 0xE68D, 0x93B9, 0xE68E, 0x93BA, 0xE68F, 0x93BB, 0xE690, 0x93BC, 0xE691, 0x93BD, 0xE692, 0x93BE, 0xE693, 0x93BF, 0xE694, 0x93C0, + 0xE695, 0x93C1, 0xE696, 0x93C2, 0xE697, 0x93C3, 0xE698, 0x93C4, 0xE699, 0x93C5, 0xE69A, 0x93C6, 0xE69B, 0x93C7, 0xE69C, 0x93C8, + 0xE69D, 0x93C9, 0xE69E, 0x93CB, 0xE69F, 0x93CC, 0xE6A0, 0x93CD, 0xE6A1, 0x5997, 0xE6A2, 0x59CA, 0xE6A3, 0x59AB, 0xE6A4, 0x599E, + 0xE6A5, 0x59A4, 0xE6A6, 0x59D2, 0xE6A7, 0x59B2, 0xE6A8, 0x59AF, 0xE6A9, 0x59D7, 0xE6AA, 0x59BE, 0xE6AB, 0x5A05, 0xE6AC, 0x5A06, + 0xE6AD, 0x59DD, 0xE6AE, 0x5A08, 0xE6AF, 0x59E3, 0xE6B0, 0x59D8, 0xE6B1, 0x59F9, 0xE6B2, 0x5A0C, 0xE6B3, 0x5A09, 0xE6B4, 0x5A32, + 0xE6B5, 0x5A34, 0xE6B6, 0x5A11, 0xE6B7, 0x5A23, 0xE6B8, 0x5A13, 0xE6B9, 0x5A40, 0xE6BA, 0x5A67, 0xE6BB, 0x5A4A, 0xE6BC, 0x5A55, + 0xE6BD, 0x5A3C, 0xE6BE, 0x5A62, 0xE6BF, 0x5A75, 0xE6C0, 0x80EC, 0xE6C1, 0x5AAA, 0xE6C2, 0x5A9B, 0xE6C3, 0x5A77, 0xE6C4, 0x5A7A, + 0xE6C5, 0x5ABE, 0xE6C6, 0x5AEB, 0xE6C7, 0x5AB2, 0xE6C8, 0x5AD2, 0xE6C9, 0x5AD4, 0xE6CA, 0x5AB8, 0xE6CB, 0x5AE0, 0xE6CC, 0x5AE3, + 0xE6CD, 0x5AF1, 0xE6CE, 0x5AD6, 0xE6CF, 0x5AE6, 0xE6D0, 0x5AD8, 0xE6D1, 0x5ADC, 0xE6D2, 0x5B09, 0xE6D3, 0x5B17, 0xE6D4, 0x5B16, + 0xE6D5, 0x5B32, 0xE6D6, 0x5B37, 0xE6D7, 0x5B40, 0xE6D8, 0x5C15, 0xE6D9, 0x5C1C, 0xE6DA, 0x5B5A, 0xE6DB, 0x5B65, 0xE6DC, 0x5B73, + 0xE6DD, 0x5B51, 0xE6DE, 0x5B53, 0xE6DF, 0x5B62, 0xE6E0, 0x9A75, 0xE6E1, 0x9A77, 0xE6E2, 0x9A78, 0xE6E3, 0x9A7A, 0xE6E4, 0x9A7F, + 0xE6E5, 0x9A7D, 0xE6E6, 0x9A80, 0xE6E7, 0x9A81, 0xE6E8, 0x9A85, 0xE6E9, 0x9A88, 0xE6EA, 0x9A8A, 0xE6EB, 0x9A90, 0xE6EC, 0x9A92, + 0xE6ED, 0x9A93, 0xE6EE, 0x9A96, 0xE6EF, 0x9A98, 0xE6F0, 0x9A9B, 0xE6F1, 0x9A9C, 0xE6F2, 0x9A9D, 0xE6F3, 0x9A9F, 0xE6F4, 0x9AA0, + 0xE6F5, 0x9AA2, 0xE6F6, 0x9AA3, 0xE6F7, 0x9AA5, 0xE6F8, 0x9AA7, 0xE6F9, 0x7E9F, 0xE6FA, 0x7EA1, 0xE6FB, 0x7EA3, 0xE6FC, 0x7EA5, + 0xE6FD, 0x7EA8, 0xE6FE, 0x7EA9, 0xE740, 0x93CE, 0xE741, 0x93CF, 0xE742, 0x93D0, 0xE743, 0x93D1, 0xE744, 0x93D2, 0xE745, 0x93D3, + 0xE746, 0x93D4, 0xE747, 0x93D5, 0xE748, 0x93D7, 0xE749, 0x93D8, 0xE74A, 0x93D9, 0xE74B, 0x93DA, 0xE74C, 0x93DB, 0xE74D, 0x93DC, + 0xE74E, 0x93DD, 0xE74F, 0x93DE, 0xE750, 0x93DF, 0xE751, 0x93E0, 0xE752, 0x93E1, 0xE753, 0x93E2, 0xE754, 0x93E3, 0xE755, 0x93E4, + 0xE756, 0x93E5, 0xE757, 0x93E6, 0xE758, 0x93E7, 0xE759, 0x93E8, 0xE75A, 0x93E9, 0xE75B, 0x93EA, 0xE75C, 0x93EB, 0xE75D, 0x93EC, + 0xE75E, 0x93ED, 0xE75F, 0x93EE, 0xE760, 0x93EF, 0xE761, 0x93F0, 0xE762, 0x93F1, 0xE763, 0x93F2, 0xE764, 0x93F3, 0xE765, 0x93F4, + 0xE766, 0x93F5, 0xE767, 0x93F6, 0xE768, 0x93F7, 0xE769, 0x93F8, 0xE76A, 0x93F9, 0xE76B, 0x93FA, 0xE76C, 0x93FB, 0xE76D, 0x93FC, + 0xE76E, 0x93FD, 0xE76F, 0x93FE, 0xE770, 0x93FF, 0xE771, 0x9400, 0xE772, 0x9401, 0xE773, 0x9402, 0xE774, 0x9403, 0xE775, 0x9404, + 0xE776, 0x9405, 0xE777, 0x9406, 0xE778, 0x9407, 0xE779, 0x9408, 0xE77A, 0x9409, 0xE77B, 0x940A, 0xE77C, 0x940B, 0xE77D, 0x940C, + 0xE77E, 0x940D, 0xE780, 0x940E, 0xE781, 0x940F, 0xE782, 0x9410, 0xE783, 0x9411, 0xE784, 0x9412, 0xE785, 0x9413, 0xE786, 0x9414, + 0xE787, 0x9415, 0xE788, 0x9416, 0xE789, 0x9417, 0xE78A, 0x9418, 0xE78B, 0x9419, 0xE78C, 0x941A, 0xE78D, 0x941B, 0xE78E, 0x941C, + 0xE78F, 0x941D, 0xE790, 0x941E, 0xE791, 0x941F, 0xE792, 0x9420, 0xE793, 0x9421, 0xE794, 0x9422, 0xE795, 0x9423, 0xE796, 0x9424, + 0xE797, 0x9425, 0xE798, 0x9426, 0xE799, 0x9427, 0xE79A, 0x9428, 0xE79B, 0x9429, 0xE79C, 0x942A, 0xE79D, 0x942B, 0xE79E, 0x942C, + 0xE79F, 0x942D, 0xE7A0, 0x942E, 0xE7A1, 0x7EAD, 0xE7A2, 0x7EB0, 0xE7A3, 0x7EBE, 0xE7A4, 0x7EC0, 0xE7A5, 0x7EC1, 0xE7A6, 0x7EC2, + 0xE7A7, 0x7EC9, 0xE7A8, 0x7ECB, 0xE7A9, 0x7ECC, 0xE7AA, 0x7ED0, 0xE7AB, 0x7ED4, 0xE7AC, 0x7ED7, 0xE7AD, 0x7EDB, 0xE7AE, 0x7EE0, + 0xE7AF, 0x7EE1, 0xE7B0, 0x7EE8, 0xE7B1, 0x7EEB, 0xE7B2, 0x7EEE, 0xE7B3, 0x7EEF, 0xE7B4, 0x7EF1, 0xE7B5, 0x7EF2, 0xE7B6, 0x7F0D, + 0xE7B7, 0x7EF6, 0xE7B8, 0x7EFA, 0xE7B9, 0x7EFB, 0xE7BA, 0x7EFE, 0xE7BB, 0x7F01, 0xE7BC, 0x7F02, 0xE7BD, 0x7F03, 0xE7BE, 0x7F07, + 0xE7BF, 0x7F08, 0xE7C0, 0x7F0B, 0xE7C1, 0x7F0C, 0xE7C2, 0x7F0F, 0xE7C3, 0x7F11, 0xE7C4, 0x7F12, 0xE7C5, 0x7F17, 0xE7C6, 0x7F19, + 0xE7C7, 0x7F1C, 0xE7C8, 0x7F1B, 0xE7C9, 0x7F1F, 0xE7CA, 0x7F21, 0xE7CB, 0x7F22, 0xE7CC, 0x7F23, 0xE7CD, 0x7F24, 0xE7CE, 0x7F25, + 0xE7CF, 0x7F26, 0xE7D0, 0x7F27, 0xE7D1, 0x7F2A, 0xE7D2, 0x7F2B, 0xE7D3, 0x7F2C, 0xE7D4, 0x7F2D, 0xE7D5, 0x7F2F, 0xE7D6, 0x7F30, + 0xE7D7, 0x7F31, 0xE7D8, 0x7F32, 0xE7D9, 0x7F33, 0xE7DA, 0x7F35, 0xE7DB, 0x5E7A, 0xE7DC, 0x757F, 0xE7DD, 0x5DDB, 0xE7DE, 0x753E, + 0xE7DF, 0x9095, 0xE7E0, 0x738E, 0xE7E1, 0x7391, 0xE7E2, 0x73AE, 0xE7E3, 0x73A2, 0xE7E4, 0x739F, 0xE7E5, 0x73CF, 0xE7E6, 0x73C2, + 0xE7E7, 0x73D1, 0xE7E8, 0x73B7, 0xE7E9, 0x73B3, 0xE7EA, 0x73C0, 0xE7EB, 0x73C9, 0xE7EC, 0x73C8, 0xE7ED, 0x73E5, 0xE7EE, 0x73D9, + 0xE7EF, 0x987C, 0xE7F0, 0x740A, 0xE7F1, 0x73E9, 0xE7F2, 0x73E7, 0xE7F3, 0x73DE, 0xE7F4, 0x73BA, 0xE7F5, 0x73F2, 0xE7F6, 0x740F, + 0xE7F7, 0x742A, 0xE7F8, 0x745B, 0xE7F9, 0x7426, 0xE7FA, 0x7425, 0xE7FB, 0x7428, 0xE7FC, 0x7430, 0xE7FD, 0x742E, 0xE7FE, 0x742C, + 0xE840, 0x942F, 0xE841, 0x9430, 0xE842, 0x9431, 0xE843, 0x9432, 0xE844, 0x9433, 0xE845, 0x9434, 0xE846, 0x9435, 0xE847, 0x9436, + 0xE848, 0x9437, 0xE849, 0x9438, 0xE84A, 0x9439, 0xE84B, 0x943A, 0xE84C, 0x943B, 0xE84D, 0x943C, 0xE84E, 0x943D, 0xE84F, 0x943F, + 0xE850, 0x9440, 0xE851, 0x9441, 0xE852, 0x9442, 0xE853, 0x9443, 0xE854, 0x9444, 0xE855, 0x9445, 0xE856, 0x9446, 0xE857, 0x9447, + 0xE858, 0x9448, 0xE859, 0x9449, 0xE85A, 0x944A, 0xE85B, 0x944B, 0xE85C, 0x944C, 0xE85D, 0x944D, 0xE85E, 0x944E, 0xE85F, 0x944F, + 0xE860, 0x9450, 0xE861, 0x9451, 0xE862, 0x9452, 0xE863, 0x9453, 0xE864, 0x9454, 0xE865, 0x9455, 0xE866, 0x9456, 0xE867, 0x9457, + 0xE868, 0x9458, 0xE869, 0x9459, 0xE86A, 0x945A, 0xE86B, 0x945B, 0xE86C, 0x945C, 0xE86D, 0x945D, 0xE86E, 0x945E, 0xE86F, 0x945F, + 0xE870, 0x9460, 0xE871, 0x9461, 0xE872, 0x9462, 0xE873, 0x9463, 0xE874, 0x9464, 0xE875, 0x9465, 0xE876, 0x9466, 0xE877, 0x9467, + 0xE878, 0x9468, 0xE879, 0x9469, 0xE87A, 0x946A, 0xE87B, 0x946C, 0xE87C, 0x946D, 0xE87D, 0x946E, 0xE87E, 0x946F, 0xE880, 0x9470, + 0xE881, 0x9471, 0xE882, 0x9472, 0xE883, 0x9473, 0xE884, 0x9474, 0xE885, 0x9475, 0xE886, 0x9476, 0xE887, 0x9477, 0xE888, 0x9478, + 0xE889, 0x9479, 0xE88A, 0x947A, 0xE88B, 0x947B, 0xE88C, 0x947C, 0xE88D, 0x947D, 0xE88E, 0x947E, 0xE88F, 0x947F, 0xE890, 0x9480, + 0xE891, 0x9481, 0xE892, 0x9482, 0xE893, 0x9483, 0xE894, 0x9484, 0xE895, 0x9491, 0xE896, 0x9496, 0xE897, 0x9498, 0xE898, 0x94C7, + 0xE899, 0x94CF, 0xE89A, 0x94D3, 0xE89B, 0x94D4, 0xE89C, 0x94DA, 0xE89D, 0x94E6, 0xE89E, 0x94FB, 0xE89F, 0x951C, 0xE8A0, 0x9520, + 0xE8A1, 0x741B, 0xE8A2, 0x741A, 0xE8A3, 0x7441, 0xE8A4, 0x745C, 0xE8A5, 0x7457, 0xE8A6, 0x7455, 0xE8A7, 0x7459, 0xE8A8, 0x7477, + 0xE8A9, 0x746D, 0xE8AA, 0x747E, 0xE8AB, 0x749C, 0xE8AC, 0x748E, 0xE8AD, 0x7480, 0xE8AE, 0x7481, 0xE8AF, 0x7487, 0xE8B0, 0x748B, + 0xE8B1, 0x749E, 0xE8B2, 0x74A8, 0xE8B3, 0x74A9, 0xE8B4, 0x7490, 0xE8B5, 0x74A7, 0xE8B6, 0x74D2, 0xE8B7, 0x74BA, 0xE8B8, 0x97EA, + 0xE8B9, 0x97EB, 0xE8BA, 0x97EC, 0xE8BB, 0x674C, 0xE8BC, 0x6753, 0xE8BD, 0x675E, 0xE8BE, 0x6748, 0xE8BF, 0x6769, 0xE8C0, 0x67A5, + 0xE8C1, 0x6787, 0xE8C2, 0x676A, 0xE8C3, 0x6773, 0xE8C4, 0x6798, 0xE8C5, 0x67A7, 0xE8C6, 0x6775, 0xE8C7, 0x67A8, 0xE8C8, 0x679E, + 0xE8C9, 0x67AD, 0xE8CA, 0x678B, 0xE8CB, 0x6777, 0xE8CC, 0x677C, 0xE8CD, 0x67F0, 0xE8CE, 0x6809, 0xE8CF, 0x67D8, 0xE8D0, 0x680A, + 0xE8D1, 0x67E9, 0xE8D2, 0x67B0, 0xE8D3, 0x680C, 0xE8D4, 0x67D9, 0xE8D5, 0x67B5, 0xE8D6, 0x67DA, 0xE8D7, 0x67B3, 0xE8D8, 0x67DD, + 0xE8D9, 0x6800, 0xE8DA, 0x67C3, 0xE8DB, 0x67B8, 0xE8DC, 0x67E2, 0xE8DD, 0x680E, 0xE8DE, 0x67C1, 0xE8DF, 0x67FD, 0xE8E0, 0x6832, + 0xE8E1, 0x6833, 0xE8E2, 0x6860, 0xE8E3, 0x6861, 0xE8E4, 0x684E, 0xE8E5, 0x6862, 0xE8E6, 0x6844, 0xE8E7, 0x6864, 0xE8E8, 0x6883, + 0xE8E9, 0x681D, 0xE8EA, 0x6855, 0xE8EB, 0x6866, 0xE8EC, 0x6841, 0xE8ED, 0x6867, 0xE8EE, 0x6840, 0xE8EF, 0x683E, 0xE8F0, 0x684A, + 0xE8F1, 0x6849, 0xE8F2, 0x6829, 0xE8F3, 0x68B5, 0xE8F4, 0x688F, 0xE8F5, 0x6874, 0xE8F6, 0x6877, 0xE8F7, 0x6893, 0xE8F8, 0x686B, + 0xE8F9, 0x68C2, 0xE8FA, 0x696E, 0xE8FB, 0x68FC, 0xE8FC, 0x691F, 0xE8FD, 0x6920, 0xE8FE, 0x68F9, 0xE940, 0x9527, 0xE941, 0x9533, + 0xE942, 0x953D, 0xE943, 0x9543, 0xE944, 0x9548, 0xE945, 0x954B, 0xE946, 0x9555, 0xE947, 0x955A, 0xE948, 0x9560, 0xE949, 0x956E, + 0xE94A, 0x9574, 0xE94B, 0x9575, 0xE94C, 0x9577, 0xE94D, 0x9578, 0xE94E, 0x9579, 0xE94F, 0x957A, 0xE950, 0x957B, 0xE951, 0x957C, + 0xE952, 0x957D, 0xE953, 0x957E, 0xE954, 0x9580, 0xE955, 0x9581, 0xE956, 0x9582, 0xE957, 0x9583, 0xE958, 0x9584, 0xE959, 0x9585, + 0xE95A, 0x9586, 0xE95B, 0x9587, 0xE95C, 0x9588, 0xE95D, 0x9589, 0xE95E, 0x958A, 0xE95F, 0x958B, 0xE960, 0x958C, 0xE961, 0x958D, + 0xE962, 0x958E, 0xE963, 0x958F, 0xE964, 0x9590, 0xE965, 0x9591, 0xE966, 0x9592, 0xE967, 0x9593, 0xE968, 0x9594, 0xE969, 0x9595, + 0xE96A, 0x9596, 0xE96B, 0x9597, 0xE96C, 0x9598, 0xE96D, 0x9599, 0xE96E, 0x959A, 0xE96F, 0x959B, 0xE970, 0x959C, 0xE971, 0x959D, + 0xE972, 0x959E, 0xE973, 0x959F, 0xE974, 0x95A0, 0xE975, 0x95A1, 0xE976, 0x95A2, 0xE977, 0x95A3, 0xE978, 0x95A4, 0xE979, 0x95A5, + 0xE97A, 0x95A6, 0xE97B, 0x95A7, 0xE97C, 0x95A8, 0xE97D, 0x95A9, 0xE97E, 0x95AA, 0xE980, 0x95AB, 0xE981, 0x95AC, 0xE982, 0x95AD, + 0xE983, 0x95AE, 0xE984, 0x95AF, 0xE985, 0x95B0, 0xE986, 0x95B1, 0xE987, 0x95B2, 0xE988, 0x95B3, 0xE989, 0x95B4, 0xE98A, 0x95B5, + 0xE98B, 0x95B6, 0xE98C, 0x95B7, 0xE98D, 0x95B8, 0xE98E, 0x95B9, 0xE98F, 0x95BA, 0xE990, 0x95BB, 0xE991, 0x95BC, 0xE992, 0x95BD, + 0xE993, 0x95BE, 0xE994, 0x95BF, 0xE995, 0x95C0, 0xE996, 0x95C1, 0xE997, 0x95C2, 0xE998, 0x95C3, 0xE999, 0x95C4, 0xE99A, 0x95C5, + 0xE99B, 0x95C6, 0xE99C, 0x95C7, 0xE99D, 0x95C8, 0xE99E, 0x95C9, 0xE99F, 0x95CA, 0xE9A0, 0x95CB, 0xE9A1, 0x6924, 0xE9A2, 0x68F0, + 0xE9A3, 0x690B, 0xE9A4, 0x6901, 0xE9A5, 0x6957, 0xE9A6, 0x68E3, 0xE9A7, 0x6910, 0xE9A8, 0x6971, 0xE9A9, 0x6939, 0xE9AA, 0x6960, + 0xE9AB, 0x6942, 0xE9AC, 0x695D, 0xE9AD, 0x6984, 0xE9AE, 0x696B, 0xE9AF, 0x6980, 0xE9B0, 0x6998, 0xE9B1, 0x6978, 0xE9B2, 0x6934, + 0xE9B3, 0x69CC, 0xE9B4, 0x6987, 0xE9B5, 0x6988, 0xE9B6, 0x69CE, 0xE9B7, 0x6989, 0xE9B8, 0x6966, 0xE9B9, 0x6963, 0xE9BA, 0x6979, + 0xE9BB, 0x699B, 0xE9BC, 0x69A7, 0xE9BD, 0x69BB, 0xE9BE, 0x69AB, 0xE9BF, 0x69AD, 0xE9C0, 0x69D4, 0xE9C1, 0x69B1, 0xE9C2, 0x69C1, + 0xE9C3, 0x69CA, 0xE9C4, 0x69DF, 0xE9C5, 0x6995, 0xE9C6, 0x69E0, 0xE9C7, 0x698D, 0xE9C8, 0x69FF, 0xE9C9, 0x6A2F, 0xE9CA, 0x69ED, + 0xE9CB, 0x6A17, 0xE9CC, 0x6A18, 0xE9CD, 0x6A65, 0xE9CE, 0x69F2, 0xE9CF, 0x6A44, 0xE9D0, 0x6A3E, 0xE9D1, 0x6AA0, 0xE9D2, 0x6A50, + 0xE9D3, 0x6A5B, 0xE9D4, 0x6A35, 0xE9D5, 0x6A8E, 0xE9D6, 0x6A79, 0xE9D7, 0x6A3D, 0xE9D8, 0x6A28, 0xE9D9, 0x6A58, 0xE9DA, 0x6A7C, + 0xE9DB, 0x6A91, 0xE9DC, 0x6A90, 0xE9DD, 0x6AA9, 0xE9DE, 0x6A97, 0xE9DF, 0x6AAB, 0xE9E0, 0x7337, 0xE9E1, 0x7352, 0xE9E2, 0x6B81, + 0xE9E3, 0x6B82, 0xE9E4, 0x6B87, 0xE9E5, 0x6B84, 0xE9E6, 0x6B92, 0xE9E7, 0x6B93, 0xE9E8, 0x6B8D, 0xE9E9, 0x6B9A, 0xE9EA, 0x6B9B, + 0xE9EB, 0x6BA1, 0xE9EC, 0x6BAA, 0xE9ED, 0x8F6B, 0xE9EE, 0x8F6D, 0xE9EF, 0x8F71, 0xE9F0, 0x8F72, 0xE9F1, 0x8F73, 0xE9F2, 0x8F75, + 0xE9F3, 0x8F76, 0xE9F4, 0x8F78, 0xE9F5, 0x8F77, 0xE9F6, 0x8F79, 0xE9F7, 0x8F7A, 0xE9F8, 0x8F7C, 0xE9F9, 0x8F7E, 0xE9FA, 0x8F81, + 0xE9FB, 0x8F82, 0xE9FC, 0x8F84, 0xE9FD, 0x8F87, 0xE9FE, 0x8F8B, 0xEA40, 0x95CC, 0xEA41, 0x95CD, 0xEA42, 0x95CE, 0xEA43, 0x95CF, + 0xEA44, 0x95D0, 0xEA45, 0x95D1, 0xEA46, 0x95D2, 0xEA47, 0x95D3, 0xEA48, 0x95D4, 0xEA49, 0x95D5, 0xEA4A, 0x95D6, 0xEA4B, 0x95D7, + 0xEA4C, 0x95D8, 0xEA4D, 0x95D9, 0xEA4E, 0x95DA, 0xEA4F, 0x95DB, 0xEA50, 0x95DC, 0xEA51, 0x95DD, 0xEA52, 0x95DE, 0xEA53, 0x95DF, + 0xEA54, 0x95E0, 0xEA55, 0x95E1, 0xEA56, 0x95E2, 0xEA57, 0x95E3, 0xEA58, 0x95E4, 0xEA59, 0x95E5, 0xEA5A, 0x95E6, 0xEA5B, 0x95E7, + 0xEA5C, 0x95EC, 0xEA5D, 0x95FF, 0xEA5E, 0x9607, 0xEA5F, 0x9613, 0xEA60, 0x9618, 0xEA61, 0x961B, 0xEA62, 0x961E, 0xEA63, 0x9620, + 0xEA64, 0x9623, 0xEA65, 0x9624, 0xEA66, 0x9625, 0xEA67, 0x9626, 0xEA68, 0x9627, 0xEA69, 0x9628, 0xEA6A, 0x9629, 0xEA6B, 0x962B, + 0xEA6C, 0x962C, 0xEA6D, 0x962D, 0xEA6E, 0x962F, 0xEA6F, 0x9630, 0xEA70, 0x9637, 0xEA71, 0x9638, 0xEA72, 0x9639, 0xEA73, 0x963A, + 0xEA74, 0x963E, 0xEA75, 0x9641, 0xEA76, 0x9643, 0xEA77, 0x964A, 0xEA78, 0x964E, 0xEA79, 0x964F, 0xEA7A, 0x9651, 0xEA7B, 0x9652, + 0xEA7C, 0x9653, 0xEA7D, 0x9656, 0xEA7E, 0x9657, 0xEA80, 0x9658, 0xEA81, 0x9659, 0xEA82, 0x965A, 0xEA83, 0x965C, 0xEA84, 0x965D, + 0xEA85, 0x965E, 0xEA86, 0x9660, 0xEA87, 0x9663, 0xEA88, 0x9665, 0xEA89, 0x9666, 0xEA8A, 0x966B, 0xEA8B, 0x966D, 0xEA8C, 0x966E, + 0xEA8D, 0x966F, 0xEA8E, 0x9670, 0xEA8F, 0x9671, 0xEA90, 0x9673, 0xEA91, 0x9678, 0xEA92, 0x9679, 0xEA93, 0x967A, 0xEA94, 0x967B, + 0xEA95, 0x967C, 0xEA96, 0x967D, 0xEA97, 0x967E, 0xEA98, 0x967F, 0xEA99, 0x9680, 0xEA9A, 0x9681, 0xEA9B, 0x9682, 0xEA9C, 0x9683, + 0xEA9D, 0x9684, 0xEA9E, 0x9687, 0xEA9F, 0x9689, 0xEAA0, 0x968A, 0xEAA1, 0x8F8D, 0xEAA2, 0x8F8E, 0xEAA3, 0x8F8F, 0xEAA4, 0x8F98, + 0xEAA5, 0x8F9A, 0xEAA6, 0x8ECE, 0xEAA7, 0x620B, 0xEAA8, 0x6217, 0xEAA9, 0x621B, 0xEAAA, 0x621F, 0xEAAB, 0x6222, 0xEAAC, 0x6221, + 0xEAAD, 0x6225, 0xEAAE, 0x6224, 0xEAAF, 0x622C, 0xEAB0, 0x81E7, 0xEAB1, 0x74EF, 0xEAB2, 0x74F4, 0xEAB3, 0x74FF, 0xEAB4, 0x750F, + 0xEAB5, 0x7511, 0xEAB6, 0x7513, 0xEAB7, 0x6534, 0xEAB8, 0x65EE, 0xEAB9, 0x65EF, 0xEABA, 0x65F0, 0xEABB, 0x660A, 0xEABC, 0x6619, + 0xEABD, 0x6772, 0xEABE, 0x6603, 0xEABF, 0x6615, 0xEAC0, 0x6600, 0xEAC1, 0x7085, 0xEAC2, 0x66F7, 0xEAC3, 0x661D, 0xEAC4, 0x6634, + 0xEAC5, 0x6631, 0xEAC6, 0x6636, 0xEAC7, 0x6635, 0xEAC8, 0x8006, 0xEAC9, 0x665F, 0xEACA, 0x6654, 0xEACB, 0x6641, 0xEACC, 0x664F, + 0xEACD, 0x6656, 0xEACE, 0x6661, 0xEACF, 0x6657, 0xEAD0, 0x6677, 0xEAD1, 0x6684, 0xEAD2, 0x668C, 0xEAD3, 0x66A7, 0xEAD4, 0x669D, + 0xEAD5, 0x66BE, 0xEAD6, 0x66DB, 0xEAD7, 0x66DC, 0xEAD8, 0x66E6, 0xEAD9, 0x66E9, 0xEADA, 0x8D32, 0xEADB, 0x8D33, 0xEADC, 0x8D36, + 0xEADD, 0x8D3B, 0xEADE, 0x8D3D, 0xEADF, 0x8D40, 0xEAE0, 0x8D45, 0xEAE1, 0x8D46, 0xEAE2, 0x8D48, 0xEAE3, 0x8D49, 0xEAE4, 0x8D47, + 0xEAE5, 0x8D4D, 0xEAE6, 0x8D55, 0xEAE7, 0x8D59, 0xEAE8, 0x89C7, 0xEAE9, 0x89CA, 0xEAEA, 0x89CB, 0xEAEB, 0x89CC, 0xEAEC, 0x89CE, + 0xEAED, 0x89CF, 0xEAEE, 0x89D0, 0xEAEF, 0x89D1, 0xEAF0, 0x726E, 0xEAF1, 0x729F, 0xEAF2, 0x725D, 0xEAF3, 0x7266, 0xEAF4, 0x726F, + 0xEAF5, 0x727E, 0xEAF6, 0x727F, 0xEAF7, 0x7284, 0xEAF8, 0x728B, 0xEAF9, 0x728D, 0xEAFA, 0x728F, 0xEAFB, 0x7292, 0xEAFC, 0x6308, + 0xEAFD, 0x6332, 0xEAFE, 0x63B0, 0xEB40, 0x968C, 0xEB41, 0x968E, 0xEB42, 0x9691, 0xEB43, 0x9692, 0xEB44, 0x9693, 0xEB45, 0x9695, + 0xEB46, 0x9696, 0xEB47, 0x969A, 0xEB48, 0x969B, 0xEB49, 0x969D, 0xEB4A, 0x969E, 0xEB4B, 0x969F, 0xEB4C, 0x96A0, 0xEB4D, 0x96A1, + 0xEB4E, 0x96A2, 0xEB4F, 0x96A3, 0xEB50, 0x96A4, 0xEB51, 0x96A5, 0xEB52, 0x96A6, 0xEB53, 0x96A8, 0xEB54, 0x96A9, 0xEB55, 0x96AA, + 0xEB56, 0x96AB, 0xEB57, 0x96AC, 0xEB58, 0x96AD, 0xEB59, 0x96AE, 0xEB5A, 0x96AF, 0xEB5B, 0x96B1, 0xEB5C, 0x96B2, 0xEB5D, 0x96B4, + 0xEB5E, 0x96B5, 0xEB5F, 0x96B7, 0xEB60, 0x96B8, 0xEB61, 0x96BA, 0xEB62, 0x96BB, 0xEB63, 0x96BF, 0xEB64, 0x96C2, 0xEB65, 0x96C3, + 0xEB66, 0x96C8, 0xEB67, 0x96CA, 0xEB68, 0x96CB, 0xEB69, 0x96D0, 0xEB6A, 0x96D1, 0xEB6B, 0x96D3, 0xEB6C, 0x96D4, 0xEB6D, 0x96D6, + 0xEB6E, 0x96D7, 0xEB6F, 0x96D8, 0xEB70, 0x96D9, 0xEB71, 0x96DA, 0xEB72, 0x96DB, 0xEB73, 0x96DC, 0xEB74, 0x96DD, 0xEB75, 0x96DE, + 0xEB76, 0x96DF, 0xEB77, 0x96E1, 0xEB78, 0x96E2, 0xEB79, 0x96E3, 0xEB7A, 0x96E4, 0xEB7B, 0x96E5, 0xEB7C, 0x96E6, 0xEB7D, 0x96E7, + 0xEB7E, 0x96EB, 0xEB80, 0x96EC, 0xEB81, 0x96ED, 0xEB82, 0x96EE, 0xEB83, 0x96F0, 0xEB84, 0x96F1, 0xEB85, 0x96F2, 0xEB86, 0x96F4, + 0xEB87, 0x96F5, 0xEB88, 0x96F8, 0xEB89, 0x96FA, 0xEB8A, 0x96FB, 0xEB8B, 0x96FC, 0xEB8C, 0x96FD, 0xEB8D, 0x96FF, 0xEB8E, 0x9702, + 0xEB8F, 0x9703, 0xEB90, 0x9705, 0xEB91, 0x970A, 0xEB92, 0x970B, 0xEB93, 0x970C, 0xEB94, 0x9710, 0xEB95, 0x9711, 0xEB96, 0x9712, + 0xEB97, 0x9714, 0xEB98, 0x9715, 0xEB99, 0x9717, 0xEB9A, 0x9718, 0xEB9B, 0x9719, 0xEB9C, 0x971A, 0xEB9D, 0x971B, 0xEB9E, 0x971D, + 0xEB9F, 0x971F, 0xEBA0, 0x9720, 0xEBA1, 0x643F, 0xEBA2, 0x64D8, 0xEBA3, 0x8004, 0xEBA4, 0x6BEA, 0xEBA5, 0x6BF3, 0xEBA6, 0x6BFD, + 0xEBA7, 0x6BF5, 0xEBA8, 0x6BF9, 0xEBA9, 0x6C05, 0xEBAA, 0x6C07, 0xEBAB, 0x6C06, 0xEBAC, 0x6C0D, 0xEBAD, 0x6C15, 0xEBAE, 0x6C18, + 0xEBAF, 0x6C19, 0xEBB0, 0x6C1A, 0xEBB1, 0x6C21, 0xEBB2, 0x6C29, 0xEBB3, 0x6C24, 0xEBB4, 0x6C2A, 0xEBB5, 0x6C32, 0xEBB6, 0x6535, + 0xEBB7, 0x6555, 0xEBB8, 0x656B, 0xEBB9, 0x724D, 0xEBBA, 0x7252, 0xEBBB, 0x7256, 0xEBBC, 0x7230, 0xEBBD, 0x8662, 0xEBBE, 0x5216, + 0xEBBF, 0x809F, 0xEBC0, 0x809C, 0xEBC1, 0x8093, 0xEBC2, 0x80BC, 0xEBC3, 0x670A, 0xEBC4, 0x80BD, 0xEBC5, 0x80B1, 0xEBC6, 0x80AB, + 0xEBC7, 0x80AD, 0xEBC8, 0x80B4, 0xEBC9, 0x80B7, 0xEBCA, 0x80E7, 0xEBCB, 0x80E8, 0xEBCC, 0x80E9, 0xEBCD, 0x80EA, 0xEBCE, 0x80DB, + 0xEBCF, 0x80C2, 0xEBD0, 0x80C4, 0xEBD1, 0x80D9, 0xEBD2, 0x80CD, 0xEBD3, 0x80D7, 0xEBD4, 0x6710, 0xEBD5, 0x80DD, 0xEBD6, 0x80EB, + 0xEBD7, 0x80F1, 0xEBD8, 0x80F4, 0xEBD9, 0x80ED, 0xEBDA, 0x810D, 0xEBDB, 0x810E, 0xEBDC, 0x80F2, 0xEBDD, 0x80FC, 0xEBDE, 0x6715, + 0xEBDF, 0x8112, 0xEBE0, 0x8C5A, 0xEBE1, 0x8136, 0xEBE2, 0x811E, 0xEBE3, 0x812C, 0xEBE4, 0x8118, 0xEBE5, 0x8132, 0xEBE6, 0x8148, + 0xEBE7, 0x814C, 0xEBE8, 0x8153, 0xEBE9, 0x8174, 0xEBEA, 0x8159, 0xEBEB, 0x815A, 0xEBEC, 0x8171, 0xEBED, 0x8160, 0xEBEE, 0x8169, + 0xEBEF, 0x817C, 0xEBF0, 0x817D, 0xEBF1, 0x816D, 0xEBF2, 0x8167, 0xEBF3, 0x584D, 0xEBF4, 0x5AB5, 0xEBF5, 0x8188, 0xEBF6, 0x8182, + 0xEBF7, 0x8191, 0xEBF8, 0x6ED5, 0xEBF9, 0x81A3, 0xEBFA, 0x81AA, 0xEBFB, 0x81CC, 0xEBFC, 0x6726, 0xEBFD, 0x81CA, 0xEBFE, 0x81BB, + 0xEC40, 0x9721, 0xEC41, 0x9722, 0xEC42, 0x9723, 0xEC43, 0x9724, 0xEC44, 0x9725, 0xEC45, 0x9726, 0xEC46, 0x9727, 0xEC47, 0x9728, + 0xEC48, 0x9729, 0xEC49, 0x972B, 0xEC4A, 0x972C, 0xEC4B, 0x972E, 0xEC4C, 0x972F, 0xEC4D, 0x9731, 0xEC4E, 0x9733, 0xEC4F, 0x9734, + 0xEC50, 0x9735, 0xEC51, 0x9736, 0xEC52, 0x9737, 0xEC53, 0x973A, 0xEC54, 0x973B, 0xEC55, 0x973C, 0xEC56, 0x973D, 0xEC57, 0x973F, + 0xEC58, 0x9740, 0xEC59, 0x9741, 0xEC5A, 0x9742, 0xEC5B, 0x9743, 0xEC5C, 0x9744, 0xEC5D, 0x9745, 0xEC5E, 0x9746, 0xEC5F, 0x9747, + 0xEC60, 0x9748, 0xEC61, 0x9749, 0xEC62, 0x974A, 0xEC63, 0x974B, 0xEC64, 0x974C, 0xEC65, 0x974D, 0xEC66, 0x974E, 0xEC67, 0x974F, + 0xEC68, 0x9750, 0xEC69, 0x9751, 0xEC6A, 0x9754, 0xEC6B, 0x9755, 0xEC6C, 0x9757, 0xEC6D, 0x9758, 0xEC6E, 0x975A, 0xEC6F, 0x975C, + 0xEC70, 0x975D, 0xEC71, 0x975F, 0xEC72, 0x9763, 0xEC73, 0x9764, 0xEC74, 0x9766, 0xEC75, 0x9767, 0xEC76, 0x9768, 0xEC77, 0x976A, + 0xEC78, 0x976B, 0xEC79, 0x976C, 0xEC7A, 0x976D, 0xEC7B, 0x976E, 0xEC7C, 0x976F, 0xEC7D, 0x9770, 0xEC7E, 0x9771, 0xEC80, 0x9772, + 0xEC81, 0x9775, 0xEC82, 0x9777, 0xEC83, 0x9778, 0xEC84, 0x9779, 0xEC85, 0x977A, 0xEC86, 0x977B, 0xEC87, 0x977D, 0xEC88, 0x977E, + 0xEC89, 0x977F, 0xEC8A, 0x9780, 0xEC8B, 0x9781, 0xEC8C, 0x9782, 0xEC8D, 0x9783, 0xEC8E, 0x9784, 0xEC8F, 0x9786, 0xEC90, 0x9787, + 0xEC91, 0x9788, 0xEC92, 0x9789, 0xEC93, 0x978A, 0xEC94, 0x978C, 0xEC95, 0x978E, 0xEC96, 0x978F, 0xEC97, 0x9790, 0xEC98, 0x9793, + 0xEC99, 0x9795, 0xEC9A, 0x9796, 0xEC9B, 0x9797, 0xEC9C, 0x9799, 0xEC9D, 0x979A, 0xEC9E, 0x979B, 0xEC9F, 0x979C, 0xECA0, 0x979D, + 0xECA1, 0x81C1, 0xECA2, 0x81A6, 0xECA3, 0x6B24, 0xECA4, 0x6B37, 0xECA5, 0x6B39, 0xECA6, 0x6B43, 0xECA7, 0x6B46, 0xECA8, 0x6B59, + 0xECA9, 0x98D1, 0xECAA, 0x98D2, 0xECAB, 0x98D3, 0xECAC, 0x98D5, 0xECAD, 0x98D9, 0xECAE, 0x98DA, 0xECAF, 0x6BB3, 0xECB0, 0x5F40, + 0xECB1, 0x6BC2, 0xECB2, 0x89F3, 0xECB3, 0x6590, 0xECB4, 0x9F51, 0xECB5, 0x6593, 0xECB6, 0x65BC, 0xECB7, 0x65C6, 0xECB8, 0x65C4, + 0xECB9, 0x65C3, 0xECBA, 0x65CC, 0xECBB, 0x65CE, 0xECBC, 0x65D2, 0xECBD, 0x65D6, 0xECBE, 0x7080, 0xECBF, 0x709C, 0xECC0, 0x7096, + 0xECC1, 0x709D, 0xECC2, 0x70BB, 0xECC3, 0x70C0, 0xECC4, 0x70B7, 0xECC5, 0x70AB, 0xECC6, 0x70B1, 0xECC7, 0x70E8, 0xECC8, 0x70CA, + 0xECC9, 0x7110, 0xECCA, 0x7113, 0xECCB, 0x7116, 0xECCC, 0x712F, 0xECCD, 0x7131, 0xECCE, 0x7173, 0xECCF, 0x715C, 0xECD0, 0x7168, + 0xECD1, 0x7145, 0xECD2, 0x7172, 0xECD3, 0x714A, 0xECD4, 0x7178, 0xECD5, 0x717A, 0xECD6, 0x7198, 0xECD7, 0x71B3, 0xECD8, 0x71B5, + 0xECD9, 0x71A8, 0xECDA, 0x71A0, 0xECDB, 0x71E0, 0xECDC, 0x71D4, 0xECDD, 0x71E7, 0xECDE, 0x71F9, 0xECDF, 0x721D, 0xECE0, 0x7228, + 0xECE1, 0x706C, 0xECE2, 0x7118, 0xECE3, 0x7166, 0xECE4, 0x71B9, 0xECE5, 0x623E, 0xECE6, 0x623D, 0xECE7, 0x6243, 0xECE8, 0x6248, + 0xECE9, 0x6249, 0xECEA, 0x793B, 0xECEB, 0x7940, 0xECEC, 0x7946, 0xECED, 0x7949, 0xECEE, 0x795B, 0xECEF, 0x795C, 0xECF0, 0x7953, + 0xECF1, 0x795A, 0xECF2, 0x7962, 0xECF3, 0x7957, 0xECF4, 0x7960, 0xECF5, 0x796F, 0xECF6, 0x7967, 0xECF7, 0x797A, 0xECF8, 0x7985, + 0xECF9, 0x798A, 0xECFA, 0x799A, 0xECFB, 0x79A7, 0xECFC, 0x79B3, 0xECFD, 0x5FD1, 0xECFE, 0x5FD0, 0xED40, 0x979E, 0xED41, 0x979F, + 0xED42, 0x97A1, 0xED43, 0x97A2, 0xED44, 0x97A4, 0xED45, 0x97A5, 0xED46, 0x97A6, 0xED47, 0x97A7, 0xED48, 0x97A8, 0xED49, 0x97A9, + 0xED4A, 0x97AA, 0xED4B, 0x97AC, 0xED4C, 0x97AE, 0xED4D, 0x97B0, 0xED4E, 0x97B1, 0xED4F, 0x97B3, 0xED50, 0x97B5, 0xED51, 0x97B6, + 0xED52, 0x97B7, 0xED53, 0x97B8, 0xED54, 0x97B9, 0xED55, 0x97BA, 0xED56, 0x97BB, 0xED57, 0x97BC, 0xED58, 0x97BD, 0xED59, 0x97BE, + 0xED5A, 0x97BF, 0xED5B, 0x97C0, 0xED5C, 0x97C1, 0xED5D, 0x97C2, 0xED5E, 0x97C3, 0xED5F, 0x97C4, 0xED60, 0x97C5, 0xED61, 0x97C6, + 0xED62, 0x97C7, 0xED63, 0x97C8, 0xED64, 0x97C9, 0xED65, 0x97CA, 0xED66, 0x97CB, 0xED67, 0x97CC, 0xED68, 0x97CD, 0xED69, 0x97CE, + 0xED6A, 0x97CF, 0xED6B, 0x97D0, 0xED6C, 0x97D1, 0xED6D, 0x97D2, 0xED6E, 0x97D3, 0xED6F, 0x97D4, 0xED70, 0x97D5, 0xED71, 0x97D6, + 0xED72, 0x97D7, 0xED73, 0x97D8, 0xED74, 0x97D9, 0xED75, 0x97DA, 0xED76, 0x97DB, 0xED77, 0x97DC, 0xED78, 0x97DD, 0xED79, 0x97DE, + 0xED7A, 0x97DF, 0xED7B, 0x97E0, 0xED7C, 0x97E1, 0xED7D, 0x97E2, 0xED7E, 0x97E3, 0xED80, 0x97E4, 0xED81, 0x97E5, 0xED82, 0x97E8, + 0xED83, 0x97EE, 0xED84, 0x97EF, 0xED85, 0x97F0, 0xED86, 0x97F1, 0xED87, 0x97F2, 0xED88, 0x97F4, 0xED89, 0x97F7, 0xED8A, 0x97F8, + 0xED8B, 0x97F9, 0xED8C, 0x97FA, 0xED8D, 0x97FB, 0xED8E, 0x97FC, 0xED8F, 0x97FD, 0xED90, 0x97FE, 0xED91, 0x97FF, 0xED92, 0x9800, + 0xED93, 0x9801, 0xED94, 0x9802, 0xED95, 0x9803, 0xED96, 0x9804, 0xED97, 0x9805, 0xED98, 0x9806, 0xED99, 0x9807, 0xED9A, 0x9808, + 0xED9B, 0x9809, 0xED9C, 0x980A, 0xED9D, 0x980B, 0xED9E, 0x980C, 0xED9F, 0x980D, 0xEDA0, 0x980E, 0xEDA1, 0x603C, 0xEDA2, 0x605D, + 0xEDA3, 0x605A, 0xEDA4, 0x6067, 0xEDA5, 0x6041, 0xEDA6, 0x6059, 0xEDA7, 0x6063, 0xEDA8, 0x60AB, 0xEDA9, 0x6106, 0xEDAA, 0x610D, + 0xEDAB, 0x615D, 0xEDAC, 0x61A9, 0xEDAD, 0x619D, 0xEDAE, 0x61CB, 0xEDAF, 0x61D1, 0xEDB0, 0x6206, 0xEDB1, 0x8080, 0xEDB2, 0x807F, + 0xEDB3, 0x6C93, 0xEDB4, 0x6CF6, 0xEDB5, 0x6DFC, 0xEDB6, 0x77F6, 0xEDB7, 0x77F8, 0xEDB8, 0x7800, 0xEDB9, 0x7809, 0xEDBA, 0x7817, + 0xEDBB, 0x7818, 0xEDBC, 0x7811, 0xEDBD, 0x65AB, 0xEDBE, 0x782D, 0xEDBF, 0x781C, 0xEDC0, 0x781D, 0xEDC1, 0x7839, 0xEDC2, 0x783A, + 0xEDC3, 0x783B, 0xEDC4, 0x781F, 0xEDC5, 0x783C, 0xEDC6, 0x7825, 0xEDC7, 0x782C, 0xEDC8, 0x7823, 0xEDC9, 0x7829, 0xEDCA, 0x784E, + 0xEDCB, 0x786D, 0xEDCC, 0x7856, 0xEDCD, 0x7857, 0xEDCE, 0x7826, 0xEDCF, 0x7850, 0xEDD0, 0x7847, 0xEDD1, 0x784C, 0xEDD2, 0x786A, + 0xEDD3, 0x789B, 0xEDD4, 0x7893, 0xEDD5, 0x789A, 0xEDD6, 0x7887, 0xEDD7, 0x789C, 0xEDD8, 0x78A1, 0xEDD9, 0x78A3, 0xEDDA, 0x78B2, + 0xEDDB, 0x78B9, 0xEDDC, 0x78A5, 0xEDDD, 0x78D4, 0xEDDE, 0x78D9, 0xEDDF, 0x78C9, 0xEDE0, 0x78EC, 0xEDE1, 0x78F2, 0xEDE2, 0x7905, + 0xEDE3, 0x78F4, 0xEDE4, 0x7913, 0xEDE5, 0x7924, 0xEDE6, 0x791E, 0xEDE7, 0x7934, 0xEDE8, 0x9F9B, 0xEDE9, 0x9EF9, 0xEDEA, 0x9EFB, + 0xEDEB, 0x9EFC, 0xEDEC, 0x76F1, 0xEDED, 0x7704, 0xEDEE, 0x770D, 0xEDEF, 0x76F9, 0xEDF0, 0x7707, 0xEDF1, 0x7708, 0xEDF2, 0x771A, + 0xEDF3, 0x7722, 0xEDF4, 0x7719, 0xEDF5, 0x772D, 0xEDF6, 0x7726, 0xEDF7, 0x7735, 0xEDF8, 0x7738, 0xEDF9, 0x7750, 0xEDFA, 0x7751, + 0xEDFB, 0x7747, 0xEDFC, 0x7743, 0xEDFD, 0x775A, 0xEDFE, 0x7768, 0xEE40, 0x980F, 0xEE41, 0x9810, 0xEE42, 0x9811, 0xEE43, 0x9812, + 0xEE44, 0x9813, 0xEE45, 0x9814, 0xEE46, 0x9815, 0xEE47, 0x9816, 0xEE48, 0x9817, 0xEE49, 0x9818, 0xEE4A, 0x9819, 0xEE4B, 0x981A, + 0xEE4C, 0x981B, 0xEE4D, 0x981C, 0xEE4E, 0x981D, 0xEE4F, 0x981E, 0xEE50, 0x981F, 0xEE51, 0x9820, 0xEE52, 0x9821, 0xEE53, 0x9822, + 0xEE54, 0x9823, 0xEE55, 0x9824, 0xEE56, 0x9825, 0xEE57, 0x9826, 0xEE58, 0x9827, 0xEE59, 0x9828, 0xEE5A, 0x9829, 0xEE5B, 0x982A, + 0xEE5C, 0x982B, 0xEE5D, 0x982C, 0xEE5E, 0x982D, 0xEE5F, 0x982E, 0xEE60, 0x982F, 0xEE61, 0x9830, 0xEE62, 0x9831, 0xEE63, 0x9832, + 0xEE64, 0x9833, 0xEE65, 0x9834, 0xEE66, 0x9835, 0xEE67, 0x9836, 0xEE68, 0x9837, 0xEE69, 0x9838, 0xEE6A, 0x9839, 0xEE6B, 0x983A, + 0xEE6C, 0x983B, 0xEE6D, 0x983C, 0xEE6E, 0x983D, 0xEE6F, 0x983E, 0xEE70, 0x983F, 0xEE71, 0x9840, 0xEE72, 0x9841, 0xEE73, 0x9842, + 0xEE74, 0x9843, 0xEE75, 0x9844, 0xEE76, 0x9845, 0xEE77, 0x9846, 0xEE78, 0x9847, 0xEE79, 0x9848, 0xEE7A, 0x9849, 0xEE7B, 0x984A, + 0xEE7C, 0x984B, 0xEE7D, 0x984C, 0xEE7E, 0x984D, 0xEE80, 0x984E, 0xEE81, 0x984F, 0xEE82, 0x9850, 0xEE83, 0x9851, 0xEE84, 0x9852, + 0xEE85, 0x9853, 0xEE86, 0x9854, 0xEE87, 0x9855, 0xEE88, 0x9856, 0xEE89, 0x9857, 0xEE8A, 0x9858, 0xEE8B, 0x9859, 0xEE8C, 0x985A, + 0xEE8D, 0x985B, 0xEE8E, 0x985C, 0xEE8F, 0x985D, 0xEE90, 0x985E, 0xEE91, 0x985F, 0xEE92, 0x9860, 0xEE93, 0x9861, 0xEE94, 0x9862, + 0xEE95, 0x9863, 0xEE96, 0x9864, 0xEE97, 0x9865, 0xEE98, 0x9866, 0xEE99, 0x9867, 0xEE9A, 0x9868, 0xEE9B, 0x9869, 0xEE9C, 0x986A, + 0xEE9D, 0x986B, 0xEE9E, 0x986C, 0xEE9F, 0x986D, 0xEEA0, 0x986E, 0xEEA1, 0x7762, 0xEEA2, 0x7765, 0xEEA3, 0x777F, 0xEEA4, 0x778D, + 0xEEA5, 0x777D, 0xEEA6, 0x7780, 0xEEA7, 0x778C, 0xEEA8, 0x7791, 0xEEA9, 0x779F, 0xEEAA, 0x77A0, 0xEEAB, 0x77B0, 0xEEAC, 0x77B5, + 0xEEAD, 0x77BD, 0xEEAE, 0x753A, 0xEEAF, 0x7540, 0xEEB0, 0x754E, 0xEEB1, 0x754B, 0xEEB2, 0x7548, 0xEEB3, 0x755B, 0xEEB4, 0x7572, + 0xEEB5, 0x7579, 0xEEB6, 0x7583, 0xEEB7, 0x7F58, 0xEEB8, 0x7F61, 0xEEB9, 0x7F5F, 0xEEBA, 0x8A48, 0xEEBB, 0x7F68, 0xEEBC, 0x7F74, + 0xEEBD, 0x7F71, 0xEEBE, 0x7F79, 0xEEBF, 0x7F81, 0xEEC0, 0x7F7E, 0xEEC1, 0x76CD, 0xEEC2, 0x76E5, 0xEEC3, 0x8832, 0xEEC4, 0x9485, + 0xEEC5, 0x9486, 0xEEC6, 0x9487, 0xEEC7, 0x948B, 0xEEC8, 0x948A, 0xEEC9, 0x948C, 0xEECA, 0x948D, 0xEECB, 0x948F, 0xEECC, 0x9490, + 0xEECD, 0x9494, 0xEECE, 0x9497, 0xEECF, 0x9495, 0xEED0, 0x949A, 0xEED1, 0x949B, 0xEED2, 0x949C, 0xEED3, 0x94A3, 0xEED4, 0x94A4, + 0xEED5, 0x94AB, 0xEED6, 0x94AA, 0xEED7, 0x94AD, 0xEED8, 0x94AC, 0xEED9, 0x94AF, 0xEEDA, 0x94B0, 0xEEDB, 0x94B2, 0xEEDC, 0x94B4, + 0xEEDD, 0x94B6, 0xEEDE, 0x94B7, 0xEEDF, 0x94B8, 0xEEE0, 0x94B9, 0xEEE1, 0x94BA, 0xEEE2, 0x94BC, 0xEEE3, 0x94BD, 0xEEE4, 0x94BF, + 0xEEE5, 0x94C4, 0xEEE6, 0x94C8, 0xEEE7, 0x94C9, 0xEEE8, 0x94CA, 0xEEE9, 0x94CB, 0xEEEA, 0x94CC, 0xEEEB, 0x94CD, 0xEEEC, 0x94CE, + 0xEEED, 0x94D0, 0xEEEE, 0x94D1, 0xEEEF, 0x94D2, 0xEEF0, 0x94D5, 0xEEF1, 0x94D6, 0xEEF2, 0x94D7, 0xEEF3, 0x94D9, 0xEEF4, 0x94D8, + 0xEEF5, 0x94DB, 0xEEF6, 0x94DE, 0xEEF7, 0x94DF, 0xEEF8, 0x94E0, 0xEEF9, 0x94E2, 0xEEFA, 0x94E4, 0xEEFB, 0x94E5, 0xEEFC, 0x94E7, + 0xEEFD, 0x94E8, 0xEEFE, 0x94EA, 0xEF40, 0x986F, 0xEF41, 0x9870, 0xEF42, 0x9871, 0xEF43, 0x9872, 0xEF44, 0x9873, 0xEF45, 0x9874, + 0xEF46, 0x988B, 0xEF47, 0x988E, 0xEF48, 0x9892, 0xEF49, 0x9895, 0xEF4A, 0x9899, 0xEF4B, 0x98A3, 0xEF4C, 0x98A8, 0xEF4D, 0x98A9, + 0xEF4E, 0x98AA, 0xEF4F, 0x98AB, 0xEF50, 0x98AC, 0xEF51, 0x98AD, 0xEF52, 0x98AE, 0xEF53, 0x98AF, 0xEF54, 0x98B0, 0xEF55, 0x98B1, + 0xEF56, 0x98B2, 0xEF57, 0x98B3, 0xEF58, 0x98B4, 0xEF59, 0x98B5, 0xEF5A, 0x98B6, 0xEF5B, 0x98B7, 0xEF5C, 0x98B8, 0xEF5D, 0x98B9, + 0xEF5E, 0x98BA, 0xEF5F, 0x98BB, 0xEF60, 0x98BC, 0xEF61, 0x98BD, 0xEF62, 0x98BE, 0xEF63, 0x98BF, 0xEF64, 0x98C0, 0xEF65, 0x98C1, + 0xEF66, 0x98C2, 0xEF67, 0x98C3, 0xEF68, 0x98C4, 0xEF69, 0x98C5, 0xEF6A, 0x98C6, 0xEF6B, 0x98C7, 0xEF6C, 0x98C8, 0xEF6D, 0x98C9, + 0xEF6E, 0x98CA, 0xEF6F, 0x98CB, 0xEF70, 0x98CC, 0xEF71, 0x98CD, 0xEF72, 0x98CF, 0xEF73, 0x98D0, 0xEF74, 0x98D4, 0xEF75, 0x98D6, + 0xEF76, 0x98D7, 0xEF77, 0x98DB, 0xEF78, 0x98DC, 0xEF79, 0x98DD, 0xEF7A, 0x98E0, 0xEF7B, 0x98E1, 0xEF7C, 0x98E2, 0xEF7D, 0x98E3, + 0xEF7E, 0x98E4, 0xEF80, 0x98E5, 0xEF81, 0x98E6, 0xEF82, 0x98E9, 0xEF83, 0x98EA, 0xEF84, 0x98EB, 0xEF85, 0x98EC, 0xEF86, 0x98ED, + 0xEF87, 0x98EE, 0xEF88, 0x98EF, 0xEF89, 0x98F0, 0xEF8A, 0x98F1, 0xEF8B, 0x98F2, 0xEF8C, 0x98F3, 0xEF8D, 0x98F4, 0xEF8E, 0x98F5, + 0xEF8F, 0x98F6, 0xEF90, 0x98F7, 0xEF91, 0x98F8, 0xEF92, 0x98F9, 0xEF93, 0x98FA, 0xEF94, 0x98FB, 0xEF95, 0x98FC, 0xEF96, 0x98FD, + 0xEF97, 0x98FE, 0xEF98, 0x98FF, 0xEF99, 0x9900, 0xEF9A, 0x9901, 0xEF9B, 0x9902, 0xEF9C, 0x9903, 0xEF9D, 0x9904, 0xEF9E, 0x9905, + 0xEF9F, 0x9906, 0xEFA0, 0x9907, 0xEFA1, 0x94E9, 0xEFA2, 0x94EB, 0xEFA3, 0x94EE, 0xEFA4, 0x94EF, 0xEFA5, 0x94F3, 0xEFA6, 0x94F4, + 0xEFA7, 0x94F5, 0xEFA8, 0x94F7, 0xEFA9, 0x94F9, 0xEFAA, 0x94FC, 0xEFAB, 0x94FD, 0xEFAC, 0x94FF, 0xEFAD, 0x9503, 0xEFAE, 0x9502, + 0xEFAF, 0x9506, 0xEFB0, 0x9507, 0xEFB1, 0x9509, 0xEFB2, 0x950A, 0xEFB3, 0x950D, 0xEFB4, 0x950E, 0xEFB5, 0x950F, 0xEFB6, 0x9512, + 0xEFB7, 0x9513, 0xEFB8, 0x9514, 0xEFB9, 0x9515, 0xEFBA, 0x9516, 0xEFBB, 0x9518, 0xEFBC, 0x951B, 0xEFBD, 0x951D, 0xEFBE, 0x951E, + 0xEFBF, 0x951F, 0xEFC0, 0x9522, 0xEFC1, 0x952A, 0xEFC2, 0x952B, 0xEFC3, 0x9529, 0xEFC4, 0x952C, 0xEFC5, 0x9531, 0xEFC6, 0x9532, + 0xEFC7, 0x9534, 0xEFC8, 0x9536, 0xEFC9, 0x9537, 0xEFCA, 0x9538, 0xEFCB, 0x953C, 0xEFCC, 0x953E, 0xEFCD, 0x953F, 0xEFCE, 0x9542, + 0xEFCF, 0x9535, 0xEFD0, 0x9544, 0xEFD1, 0x9545, 0xEFD2, 0x9546, 0xEFD3, 0x9549, 0xEFD4, 0x954C, 0xEFD5, 0x954E, 0xEFD6, 0x954F, + 0xEFD7, 0x9552, 0xEFD8, 0x9553, 0xEFD9, 0x9554, 0xEFDA, 0x9556, 0xEFDB, 0x9557, 0xEFDC, 0x9558, 0xEFDD, 0x9559, 0xEFDE, 0x955B, + 0xEFDF, 0x955E, 0xEFE0, 0x955F, 0xEFE1, 0x955D, 0xEFE2, 0x9561, 0xEFE3, 0x9562, 0xEFE4, 0x9564, 0xEFE5, 0x9565, 0xEFE6, 0x9566, + 0xEFE7, 0x9567, 0xEFE8, 0x9568, 0xEFE9, 0x9569, 0xEFEA, 0x956A, 0xEFEB, 0x956B, 0xEFEC, 0x956C, 0xEFED, 0x956F, 0xEFEE, 0x9571, + 0xEFEF, 0x9572, 0xEFF0, 0x9573, 0xEFF1, 0x953A, 0xEFF2, 0x77E7, 0xEFF3, 0x77EC, 0xEFF4, 0x96C9, 0xEFF5, 0x79D5, 0xEFF6, 0x79ED, + 0xEFF7, 0x79E3, 0xEFF8, 0x79EB, 0xEFF9, 0x7A06, 0xEFFA, 0x5D47, 0xEFFB, 0x7A03, 0xEFFC, 0x7A02, 0xEFFD, 0x7A1E, 0xEFFE, 0x7A14, + 0xF040, 0x9908, 0xF041, 0x9909, 0xF042, 0x990A, 0xF043, 0x990B, 0xF044, 0x990C, 0xF045, 0x990E, 0xF046, 0x990F, 0xF047, 0x9911, + 0xF048, 0x9912, 0xF049, 0x9913, 0xF04A, 0x9914, 0xF04B, 0x9915, 0xF04C, 0x9916, 0xF04D, 0x9917, 0xF04E, 0x9918, 0xF04F, 0x9919, + 0xF050, 0x991A, 0xF051, 0x991B, 0xF052, 0x991C, 0xF053, 0x991D, 0xF054, 0x991E, 0xF055, 0x991F, 0xF056, 0x9920, 0xF057, 0x9921, + 0xF058, 0x9922, 0xF059, 0x9923, 0xF05A, 0x9924, 0xF05B, 0x9925, 0xF05C, 0x9926, 0xF05D, 0x9927, 0xF05E, 0x9928, 0xF05F, 0x9929, + 0xF060, 0x992A, 0xF061, 0x992B, 0xF062, 0x992C, 0xF063, 0x992D, 0xF064, 0x992F, 0xF065, 0x9930, 0xF066, 0x9931, 0xF067, 0x9932, + 0xF068, 0x9933, 0xF069, 0x9934, 0xF06A, 0x9935, 0xF06B, 0x9936, 0xF06C, 0x9937, 0xF06D, 0x9938, 0xF06E, 0x9939, 0xF06F, 0x993A, + 0xF070, 0x993B, 0xF071, 0x993C, 0xF072, 0x993D, 0xF073, 0x993E, 0xF074, 0x993F, 0xF075, 0x9940, 0xF076, 0x9941, 0xF077, 0x9942, + 0xF078, 0x9943, 0xF079, 0x9944, 0xF07A, 0x9945, 0xF07B, 0x9946, 0xF07C, 0x9947, 0xF07D, 0x9948, 0xF07E, 0x9949, 0xF080, 0x994A, + 0xF081, 0x994B, 0xF082, 0x994C, 0xF083, 0x994D, 0xF084, 0x994E, 0xF085, 0x994F, 0xF086, 0x9950, 0xF087, 0x9951, 0xF088, 0x9952, + 0xF089, 0x9953, 0xF08A, 0x9956, 0xF08B, 0x9957, 0xF08C, 0x9958, 0xF08D, 0x9959, 0xF08E, 0x995A, 0xF08F, 0x995B, 0xF090, 0x995C, + 0xF091, 0x995D, 0xF092, 0x995E, 0xF093, 0x995F, 0xF094, 0x9960, 0xF095, 0x9961, 0xF096, 0x9962, 0xF097, 0x9964, 0xF098, 0x9966, + 0xF099, 0x9973, 0xF09A, 0x9978, 0xF09B, 0x9979, 0xF09C, 0x997B, 0xF09D, 0x997E, 0xF09E, 0x9982, 0xF09F, 0x9983, 0xF0A0, 0x9989, + 0xF0A1, 0x7A39, 0xF0A2, 0x7A37, 0xF0A3, 0x7A51, 0xF0A4, 0x9ECF, 0xF0A5, 0x99A5, 0xF0A6, 0x7A70, 0xF0A7, 0x7688, 0xF0A8, 0x768E, + 0xF0A9, 0x7693, 0xF0AA, 0x7699, 0xF0AB, 0x76A4, 0xF0AC, 0x74DE, 0xF0AD, 0x74E0, 0xF0AE, 0x752C, 0xF0AF, 0x9E20, 0xF0B0, 0x9E22, + 0xF0B1, 0x9E28, 0xF0B2, 0x9E29, 0xF0B3, 0x9E2A, 0xF0B4, 0x9E2B, 0xF0B5, 0x9E2C, 0xF0B6, 0x9E32, 0xF0B7, 0x9E31, 0xF0B8, 0x9E36, + 0xF0B9, 0x9E38, 0xF0BA, 0x9E37, 0xF0BB, 0x9E39, 0xF0BC, 0x9E3A, 0xF0BD, 0x9E3E, 0xF0BE, 0x9E41, 0xF0BF, 0x9E42, 0xF0C0, 0x9E44, + 0xF0C1, 0x9E46, 0xF0C2, 0x9E47, 0xF0C3, 0x9E48, 0xF0C4, 0x9E49, 0xF0C5, 0x9E4B, 0xF0C6, 0x9E4C, 0xF0C7, 0x9E4E, 0xF0C8, 0x9E51, + 0xF0C9, 0x9E55, 0xF0CA, 0x9E57, 0xF0CB, 0x9E5A, 0xF0CC, 0x9E5B, 0xF0CD, 0x9E5C, 0xF0CE, 0x9E5E, 0xF0CF, 0x9E63, 0xF0D0, 0x9E66, + 0xF0D1, 0x9E67, 0xF0D2, 0x9E68, 0xF0D3, 0x9E69, 0xF0D4, 0x9E6A, 0xF0D5, 0x9E6B, 0xF0D6, 0x9E6C, 0xF0D7, 0x9E71, 0xF0D8, 0x9E6D, + 0xF0D9, 0x9E73, 0xF0DA, 0x7592, 0xF0DB, 0x7594, 0xF0DC, 0x7596, 0xF0DD, 0x75A0, 0xF0DE, 0x759D, 0xF0DF, 0x75AC, 0xF0E0, 0x75A3, + 0xF0E1, 0x75B3, 0xF0E2, 0x75B4, 0xF0E3, 0x75B8, 0xF0E4, 0x75C4, 0xF0E5, 0x75B1, 0xF0E6, 0x75B0, 0xF0E7, 0x75C3, 0xF0E8, 0x75C2, + 0xF0E9, 0x75D6, 0xF0EA, 0x75CD, 0xF0EB, 0x75E3, 0xF0EC, 0x75E8, 0xF0ED, 0x75E6, 0xF0EE, 0x75E4, 0xF0EF, 0x75EB, 0xF0F0, 0x75E7, + 0xF0F1, 0x7603, 0xF0F2, 0x75F1, 0xF0F3, 0x75FC, 0xF0F4, 0x75FF, 0xF0F5, 0x7610, 0xF0F6, 0x7600, 0xF0F7, 0x7605, 0xF0F8, 0x760C, + 0xF0F9, 0x7617, 0xF0FA, 0x760A, 0xF0FB, 0x7625, 0xF0FC, 0x7618, 0xF0FD, 0x7615, 0xF0FE, 0x7619, 0xF140, 0x998C, 0xF141, 0x998E, + 0xF142, 0x999A, 0xF143, 0x999B, 0xF144, 0x999C, 0xF145, 0x999D, 0xF146, 0x999E, 0xF147, 0x999F, 0xF148, 0x99A0, 0xF149, 0x99A1, + 0xF14A, 0x99A2, 0xF14B, 0x99A3, 0xF14C, 0x99A4, 0xF14D, 0x99A6, 0xF14E, 0x99A7, 0xF14F, 0x99A9, 0xF150, 0x99AA, 0xF151, 0x99AB, + 0xF152, 0x99AC, 0xF153, 0x99AD, 0xF154, 0x99AE, 0xF155, 0x99AF, 0xF156, 0x99B0, 0xF157, 0x99B1, 0xF158, 0x99B2, 0xF159, 0x99B3, + 0xF15A, 0x99B4, 0xF15B, 0x99B5, 0xF15C, 0x99B6, 0xF15D, 0x99B7, 0xF15E, 0x99B8, 0xF15F, 0x99B9, 0xF160, 0x99BA, 0xF161, 0x99BB, + 0xF162, 0x99BC, 0xF163, 0x99BD, 0xF164, 0x99BE, 0xF165, 0x99BF, 0xF166, 0x99C0, 0xF167, 0x99C1, 0xF168, 0x99C2, 0xF169, 0x99C3, + 0xF16A, 0x99C4, 0xF16B, 0x99C5, 0xF16C, 0x99C6, 0xF16D, 0x99C7, 0xF16E, 0x99C8, 0xF16F, 0x99C9, 0xF170, 0x99CA, 0xF171, 0x99CB, + 0xF172, 0x99CC, 0xF173, 0x99CD, 0xF174, 0x99CE, 0xF175, 0x99CF, 0xF176, 0x99D0, 0xF177, 0x99D1, 0xF178, 0x99D2, 0xF179, 0x99D3, + 0xF17A, 0x99D4, 0xF17B, 0x99D5, 0xF17C, 0x99D6, 0xF17D, 0x99D7, 0xF17E, 0x99D8, 0xF180, 0x99D9, 0xF181, 0x99DA, 0xF182, 0x99DB, + 0xF183, 0x99DC, 0xF184, 0x99DD, 0xF185, 0x99DE, 0xF186, 0x99DF, 0xF187, 0x99E0, 0xF188, 0x99E1, 0xF189, 0x99E2, 0xF18A, 0x99E3, + 0xF18B, 0x99E4, 0xF18C, 0x99E5, 0xF18D, 0x99E6, 0xF18E, 0x99E7, 0xF18F, 0x99E8, 0xF190, 0x99E9, 0xF191, 0x99EA, 0xF192, 0x99EB, + 0xF193, 0x99EC, 0xF194, 0x99ED, 0xF195, 0x99EE, 0xF196, 0x99EF, 0xF197, 0x99F0, 0xF198, 0x99F1, 0xF199, 0x99F2, 0xF19A, 0x99F3, + 0xF19B, 0x99F4, 0xF19C, 0x99F5, 0xF19D, 0x99F6, 0xF19E, 0x99F7, 0xF19F, 0x99F8, 0xF1A0, 0x99F9, 0xF1A1, 0x761B, 0xF1A2, 0x763C, + 0xF1A3, 0x7622, 0xF1A4, 0x7620, 0xF1A5, 0x7640, 0xF1A6, 0x762D, 0xF1A7, 0x7630, 0xF1A8, 0x763F, 0xF1A9, 0x7635, 0xF1AA, 0x7643, + 0xF1AB, 0x763E, 0xF1AC, 0x7633, 0xF1AD, 0x764D, 0xF1AE, 0x765E, 0xF1AF, 0x7654, 0xF1B0, 0x765C, 0xF1B1, 0x7656, 0xF1B2, 0x766B, + 0xF1B3, 0x766F, 0xF1B4, 0x7FCA, 0xF1B5, 0x7AE6, 0xF1B6, 0x7A78, 0xF1B7, 0x7A79, 0xF1B8, 0x7A80, 0xF1B9, 0x7A86, 0xF1BA, 0x7A88, + 0xF1BB, 0x7A95, 0xF1BC, 0x7AA6, 0xF1BD, 0x7AA0, 0xF1BE, 0x7AAC, 0xF1BF, 0x7AA8, 0xF1C0, 0x7AAD, 0xF1C1, 0x7AB3, 0xF1C2, 0x8864, + 0xF1C3, 0x8869, 0xF1C4, 0x8872, 0xF1C5, 0x887D, 0xF1C6, 0x887F, 0xF1C7, 0x8882, 0xF1C8, 0x88A2, 0xF1C9, 0x88C6, 0xF1CA, 0x88B7, + 0xF1CB, 0x88BC, 0xF1CC, 0x88C9, 0xF1CD, 0x88E2, 0xF1CE, 0x88CE, 0xF1CF, 0x88E3, 0xF1D0, 0x88E5, 0xF1D1, 0x88F1, 0xF1D2, 0x891A, + 0xF1D3, 0x88FC, 0xF1D4, 0x88E8, 0xF1D5, 0x88FE, 0xF1D6, 0x88F0, 0xF1D7, 0x8921, 0xF1D8, 0x8919, 0xF1D9, 0x8913, 0xF1DA, 0x891B, + 0xF1DB, 0x890A, 0xF1DC, 0x8934, 0xF1DD, 0x892B, 0xF1DE, 0x8936, 0xF1DF, 0x8941, 0xF1E0, 0x8966, 0xF1E1, 0x897B, 0xF1E2, 0x758B, + 0xF1E3, 0x80E5, 0xF1E4, 0x76B2, 0xF1E5, 0x76B4, 0xF1E6, 0x77DC, 0xF1E7, 0x8012, 0xF1E8, 0x8014, 0xF1E9, 0x8016, 0xF1EA, 0x801C, + 0xF1EB, 0x8020, 0xF1EC, 0x8022, 0xF1ED, 0x8025, 0xF1EE, 0x8026, 0xF1EF, 0x8027, 0xF1F0, 0x8029, 0xF1F1, 0x8028, 0xF1F2, 0x8031, + 0xF1F3, 0x800B, 0xF1F4, 0x8035, 0xF1F5, 0x8043, 0xF1F6, 0x8046, 0xF1F7, 0x804D, 0xF1F8, 0x8052, 0xF1F9, 0x8069, 0xF1FA, 0x8071, + 0xF1FB, 0x8983, 0xF1FC, 0x9878, 0xF1FD, 0x9880, 0xF1FE, 0x9883, 0xF240, 0x99FA, 0xF241, 0x99FB, 0xF242, 0x99FC, 0xF243, 0x99FD, + 0xF244, 0x99FE, 0xF245, 0x99FF, 0xF246, 0x9A00, 0xF247, 0x9A01, 0xF248, 0x9A02, 0xF249, 0x9A03, 0xF24A, 0x9A04, 0xF24B, 0x9A05, + 0xF24C, 0x9A06, 0xF24D, 0x9A07, 0xF24E, 0x9A08, 0xF24F, 0x9A09, 0xF250, 0x9A0A, 0xF251, 0x9A0B, 0xF252, 0x9A0C, 0xF253, 0x9A0D, + 0xF254, 0x9A0E, 0xF255, 0x9A0F, 0xF256, 0x9A10, 0xF257, 0x9A11, 0xF258, 0x9A12, 0xF259, 0x9A13, 0xF25A, 0x9A14, 0xF25B, 0x9A15, + 0xF25C, 0x9A16, 0xF25D, 0x9A17, 0xF25E, 0x9A18, 0xF25F, 0x9A19, 0xF260, 0x9A1A, 0xF261, 0x9A1B, 0xF262, 0x9A1C, 0xF263, 0x9A1D, + 0xF264, 0x9A1E, 0xF265, 0x9A1F, 0xF266, 0x9A20, 0xF267, 0x9A21, 0xF268, 0x9A22, 0xF269, 0x9A23, 0xF26A, 0x9A24, 0xF26B, 0x9A25, + 0xF26C, 0x9A26, 0xF26D, 0x9A27, 0xF26E, 0x9A28, 0xF26F, 0x9A29, 0xF270, 0x9A2A, 0xF271, 0x9A2B, 0xF272, 0x9A2C, 0xF273, 0x9A2D, + 0xF274, 0x9A2E, 0xF275, 0x9A2F, 0xF276, 0x9A30, 0xF277, 0x9A31, 0xF278, 0x9A32, 0xF279, 0x9A33, 0xF27A, 0x9A34, 0xF27B, 0x9A35, + 0xF27C, 0x9A36, 0xF27D, 0x9A37, 0xF27E, 0x9A38, 0xF280, 0x9A39, 0xF281, 0x9A3A, 0xF282, 0x9A3B, 0xF283, 0x9A3C, 0xF284, 0x9A3D, + 0xF285, 0x9A3E, 0xF286, 0x9A3F, 0xF287, 0x9A40, 0xF288, 0x9A41, 0xF289, 0x9A42, 0xF28A, 0x9A43, 0xF28B, 0x9A44, 0xF28C, 0x9A45, + 0xF28D, 0x9A46, 0xF28E, 0x9A47, 0xF28F, 0x9A48, 0xF290, 0x9A49, 0xF291, 0x9A4A, 0xF292, 0x9A4B, 0xF293, 0x9A4C, 0xF294, 0x9A4D, + 0xF295, 0x9A4E, 0xF296, 0x9A4F, 0xF297, 0x9A50, 0xF298, 0x9A51, 0xF299, 0x9A52, 0xF29A, 0x9A53, 0xF29B, 0x9A54, 0xF29C, 0x9A55, + 0xF29D, 0x9A56, 0xF29E, 0x9A57, 0xF29F, 0x9A58, 0xF2A0, 0x9A59, 0xF2A1, 0x9889, 0xF2A2, 0x988C, 0xF2A3, 0x988D, 0xF2A4, 0x988F, + 0xF2A5, 0x9894, 0xF2A6, 0x989A, 0xF2A7, 0x989B, 0xF2A8, 0x989E, 0xF2A9, 0x989F, 0xF2AA, 0x98A1, 0xF2AB, 0x98A2, 0xF2AC, 0x98A5, + 0xF2AD, 0x98A6, 0xF2AE, 0x864D, 0xF2AF, 0x8654, 0xF2B0, 0x866C, 0xF2B1, 0x866E, 0xF2B2, 0x867F, 0xF2B3, 0x867A, 0xF2B4, 0x867C, + 0xF2B5, 0x867B, 0xF2B6, 0x86A8, 0xF2B7, 0x868D, 0xF2B8, 0x868B, 0xF2B9, 0x86AC, 0xF2BA, 0x869D, 0xF2BB, 0x86A7, 0xF2BC, 0x86A3, + 0xF2BD, 0x86AA, 0xF2BE, 0x8693, 0xF2BF, 0x86A9, 0xF2C0, 0x86B6, 0xF2C1, 0x86C4, 0xF2C2, 0x86B5, 0xF2C3, 0x86CE, 0xF2C4, 0x86B0, + 0xF2C5, 0x86BA, 0xF2C6, 0x86B1, 0xF2C7, 0x86AF, 0xF2C8, 0x86C9, 0xF2C9, 0x86CF, 0xF2CA, 0x86B4, 0xF2CB, 0x86E9, 0xF2CC, 0x86F1, + 0xF2CD, 0x86F2, 0xF2CE, 0x86ED, 0xF2CF, 0x86F3, 0xF2D0, 0x86D0, 0xF2D1, 0x8713, 0xF2D2, 0x86DE, 0xF2D3, 0x86F4, 0xF2D4, 0x86DF, + 0xF2D5, 0x86D8, 0xF2D6, 0x86D1, 0xF2D7, 0x8703, 0xF2D8, 0x8707, 0xF2D9, 0x86F8, 0xF2DA, 0x8708, 0xF2DB, 0x870A, 0xF2DC, 0x870D, + 0xF2DD, 0x8709, 0xF2DE, 0x8723, 0xF2DF, 0x873B, 0xF2E0, 0x871E, 0xF2E1, 0x8725, 0xF2E2, 0x872E, 0xF2E3, 0x871A, 0xF2E4, 0x873E, + 0xF2E5, 0x8748, 0xF2E6, 0x8734, 0xF2E7, 0x8731, 0xF2E8, 0x8729, 0xF2E9, 0x8737, 0xF2EA, 0x873F, 0xF2EB, 0x8782, 0xF2EC, 0x8722, + 0xF2ED, 0x877D, 0xF2EE, 0x877E, 0xF2EF, 0x877B, 0xF2F0, 0x8760, 0xF2F1, 0x8770, 0xF2F2, 0x874C, 0xF2F3, 0x876E, 0xF2F4, 0x878B, + 0xF2F5, 0x8753, 0xF2F6, 0x8763, 0xF2F7, 0x877C, 0xF2F8, 0x8764, 0xF2F9, 0x8759, 0xF2FA, 0x8765, 0xF2FB, 0x8793, 0xF2FC, 0x87AF, + 0xF2FD, 0x87A8, 0xF2FE, 0x87D2, 0xF340, 0x9A5A, 0xF341, 0x9A5B, 0xF342, 0x9A5C, 0xF343, 0x9A5D, 0xF344, 0x9A5E, 0xF345, 0x9A5F, + 0xF346, 0x9A60, 0xF347, 0x9A61, 0xF348, 0x9A62, 0xF349, 0x9A63, 0xF34A, 0x9A64, 0xF34B, 0x9A65, 0xF34C, 0x9A66, 0xF34D, 0x9A67, + 0xF34E, 0x9A68, 0xF34F, 0x9A69, 0xF350, 0x9A6A, 0xF351, 0x9A6B, 0xF352, 0x9A72, 0xF353, 0x9A83, 0xF354, 0x9A89, 0xF355, 0x9A8D, + 0xF356, 0x9A8E, 0xF357, 0x9A94, 0xF358, 0x9A95, 0xF359, 0x9A99, 0xF35A, 0x9AA6, 0xF35B, 0x9AA9, 0xF35C, 0x9AAA, 0xF35D, 0x9AAB, + 0xF35E, 0x9AAC, 0xF35F, 0x9AAD, 0xF360, 0x9AAE, 0xF361, 0x9AAF, 0xF362, 0x9AB2, 0xF363, 0x9AB3, 0xF364, 0x9AB4, 0xF365, 0x9AB5, + 0xF366, 0x9AB9, 0xF367, 0x9ABB, 0xF368, 0x9ABD, 0xF369, 0x9ABE, 0xF36A, 0x9ABF, 0xF36B, 0x9AC3, 0xF36C, 0x9AC4, 0xF36D, 0x9AC6, + 0xF36E, 0x9AC7, 0xF36F, 0x9AC8, 0xF370, 0x9AC9, 0xF371, 0x9ACA, 0xF372, 0x9ACD, 0xF373, 0x9ACE, 0xF374, 0x9ACF, 0xF375, 0x9AD0, + 0xF376, 0x9AD2, 0xF377, 0x9AD4, 0xF378, 0x9AD5, 0xF379, 0x9AD6, 0xF37A, 0x9AD7, 0xF37B, 0x9AD9, 0xF37C, 0x9ADA, 0xF37D, 0x9ADB, + 0xF37E, 0x9ADC, 0xF380, 0x9ADD, 0xF381, 0x9ADE, 0xF382, 0x9AE0, 0xF383, 0x9AE2, 0xF384, 0x9AE3, 0xF385, 0x9AE4, 0xF386, 0x9AE5, + 0xF387, 0x9AE7, 0xF388, 0x9AE8, 0xF389, 0x9AE9, 0xF38A, 0x9AEA, 0xF38B, 0x9AEC, 0xF38C, 0x9AEE, 0xF38D, 0x9AF0, 0xF38E, 0x9AF1, + 0xF38F, 0x9AF2, 0xF390, 0x9AF3, 0xF391, 0x9AF4, 0xF392, 0x9AF5, 0xF393, 0x9AF6, 0xF394, 0x9AF7, 0xF395, 0x9AF8, 0xF396, 0x9AFA, + 0xF397, 0x9AFC, 0xF398, 0x9AFD, 0xF399, 0x9AFE, 0xF39A, 0x9AFF, 0xF39B, 0x9B00, 0xF39C, 0x9B01, 0xF39D, 0x9B02, 0xF39E, 0x9B04, + 0xF39F, 0x9B05, 0xF3A0, 0x9B06, 0xF3A1, 0x87C6, 0xF3A2, 0x8788, 0xF3A3, 0x8785, 0xF3A4, 0x87AD, 0xF3A5, 0x8797, 0xF3A6, 0x8783, + 0xF3A7, 0x87AB, 0xF3A8, 0x87E5, 0xF3A9, 0x87AC, 0xF3AA, 0x87B5, 0xF3AB, 0x87B3, 0xF3AC, 0x87CB, 0xF3AD, 0x87D3, 0xF3AE, 0x87BD, + 0xF3AF, 0x87D1, 0xF3B0, 0x87C0, 0xF3B1, 0x87CA, 0xF3B2, 0x87DB, 0xF3B3, 0x87EA, 0xF3B4, 0x87E0, 0xF3B5, 0x87EE, 0xF3B6, 0x8816, + 0xF3B7, 0x8813, 0xF3B8, 0x87FE, 0xF3B9, 0x880A, 0xF3BA, 0x881B, 0xF3BB, 0x8821, 0xF3BC, 0x8839, 0xF3BD, 0x883C, 0xF3BE, 0x7F36, + 0xF3BF, 0x7F42, 0xF3C0, 0x7F44, 0xF3C1, 0x7F45, 0xF3C2, 0x8210, 0xF3C3, 0x7AFA, 0xF3C4, 0x7AFD, 0xF3C5, 0x7B08, 0xF3C6, 0x7B03, + 0xF3C7, 0x7B04, 0xF3C8, 0x7B15, 0xF3C9, 0x7B0A, 0xF3CA, 0x7B2B, 0xF3CB, 0x7B0F, 0xF3CC, 0x7B47, 0xF3CD, 0x7B38, 0xF3CE, 0x7B2A, + 0xF3CF, 0x7B19, 0xF3D0, 0x7B2E, 0xF3D1, 0x7B31, 0xF3D2, 0x7B20, 0xF3D3, 0x7B25, 0xF3D4, 0x7B24, 0xF3D5, 0x7B33, 0xF3D6, 0x7B3E, + 0xF3D7, 0x7B1E, 0xF3D8, 0x7B58, 0xF3D9, 0x7B5A, 0xF3DA, 0x7B45, 0xF3DB, 0x7B75, 0xF3DC, 0x7B4C, 0xF3DD, 0x7B5D, 0xF3DE, 0x7B60, + 0xF3DF, 0x7B6E, 0xF3E0, 0x7B7B, 0xF3E1, 0x7B62, 0xF3E2, 0x7B72, 0xF3E3, 0x7B71, 0xF3E4, 0x7B90, 0xF3E5, 0x7BA6, 0xF3E6, 0x7BA7, + 0xF3E7, 0x7BB8, 0xF3E8, 0x7BAC, 0xF3E9, 0x7B9D, 0xF3EA, 0x7BA8, 0xF3EB, 0x7B85, 0xF3EC, 0x7BAA, 0xF3ED, 0x7B9C, 0xF3EE, 0x7BA2, + 0xF3EF, 0x7BAB, 0xF3F0, 0x7BB4, 0xF3F1, 0x7BD1, 0xF3F2, 0x7BC1, 0xF3F3, 0x7BCC, 0xF3F4, 0x7BDD, 0xF3F5, 0x7BDA, 0xF3F6, 0x7BE5, + 0xF3F7, 0x7BE6, 0xF3F8, 0x7BEA, 0xF3F9, 0x7C0C, 0xF3FA, 0x7BFE, 0xF3FB, 0x7BFC, 0xF3FC, 0x7C0F, 0xF3FD, 0x7C16, 0xF3FE, 0x7C0B, + 0xF440, 0x9B07, 0xF441, 0x9B09, 0xF442, 0x9B0A, 0xF443, 0x9B0B, 0xF444, 0x9B0C, 0xF445, 0x9B0D, 0xF446, 0x9B0E, 0xF447, 0x9B10, + 0xF448, 0x9B11, 0xF449, 0x9B12, 0xF44A, 0x9B14, 0xF44B, 0x9B15, 0xF44C, 0x9B16, 0xF44D, 0x9B17, 0xF44E, 0x9B18, 0xF44F, 0x9B19, + 0xF450, 0x9B1A, 0xF451, 0x9B1B, 0xF452, 0x9B1C, 0xF453, 0x9B1D, 0xF454, 0x9B1E, 0xF455, 0x9B20, 0xF456, 0x9B21, 0xF457, 0x9B22, + 0xF458, 0x9B24, 0xF459, 0x9B25, 0xF45A, 0x9B26, 0xF45B, 0x9B27, 0xF45C, 0x9B28, 0xF45D, 0x9B29, 0xF45E, 0x9B2A, 0xF45F, 0x9B2B, + 0xF460, 0x9B2C, 0xF461, 0x9B2D, 0xF462, 0x9B2E, 0xF463, 0x9B30, 0xF464, 0x9B31, 0xF465, 0x9B33, 0xF466, 0x9B34, 0xF467, 0x9B35, + 0xF468, 0x9B36, 0xF469, 0x9B37, 0xF46A, 0x9B38, 0xF46B, 0x9B39, 0xF46C, 0x9B3A, 0xF46D, 0x9B3D, 0xF46E, 0x9B3E, 0xF46F, 0x9B3F, + 0xF470, 0x9B40, 0xF471, 0x9B46, 0xF472, 0x9B4A, 0xF473, 0x9B4B, 0xF474, 0x9B4C, 0xF475, 0x9B4E, 0xF476, 0x9B50, 0xF477, 0x9B52, + 0xF478, 0x9B53, 0xF479, 0x9B55, 0xF47A, 0x9B56, 0xF47B, 0x9B57, 0xF47C, 0x9B58, 0xF47D, 0x9B59, 0xF47E, 0x9B5A, 0xF480, 0x9B5B, + 0xF481, 0x9B5C, 0xF482, 0x9B5D, 0xF483, 0x9B5E, 0xF484, 0x9B5F, 0xF485, 0x9B60, 0xF486, 0x9B61, 0xF487, 0x9B62, 0xF488, 0x9B63, + 0xF489, 0x9B64, 0xF48A, 0x9B65, 0xF48B, 0x9B66, 0xF48C, 0x9B67, 0xF48D, 0x9B68, 0xF48E, 0x9B69, 0xF48F, 0x9B6A, 0xF490, 0x9B6B, + 0xF491, 0x9B6C, 0xF492, 0x9B6D, 0xF493, 0x9B6E, 0xF494, 0x9B6F, 0xF495, 0x9B70, 0xF496, 0x9B71, 0xF497, 0x9B72, 0xF498, 0x9B73, + 0xF499, 0x9B74, 0xF49A, 0x9B75, 0xF49B, 0x9B76, 0xF49C, 0x9B77, 0xF49D, 0x9B78, 0xF49E, 0x9B79, 0xF49F, 0x9B7A, 0xF4A0, 0x9B7B, + 0xF4A1, 0x7C1F, 0xF4A2, 0x7C2A, 0xF4A3, 0x7C26, 0xF4A4, 0x7C38, 0xF4A5, 0x7C41, 0xF4A6, 0x7C40, 0xF4A7, 0x81FE, 0xF4A8, 0x8201, + 0xF4A9, 0x8202, 0xF4AA, 0x8204, 0xF4AB, 0x81EC, 0xF4AC, 0x8844, 0xF4AD, 0x8221, 0xF4AE, 0x8222, 0xF4AF, 0x8223, 0xF4B0, 0x822D, + 0xF4B1, 0x822F, 0xF4B2, 0x8228, 0xF4B3, 0x822B, 0xF4B4, 0x8238, 0xF4B5, 0x823B, 0xF4B6, 0x8233, 0xF4B7, 0x8234, 0xF4B8, 0x823E, + 0xF4B9, 0x8244, 0xF4BA, 0x8249, 0xF4BB, 0x824B, 0xF4BC, 0x824F, 0xF4BD, 0x825A, 0xF4BE, 0x825F, 0xF4BF, 0x8268, 0xF4C0, 0x887E, + 0xF4C1, 0x8885, 0xF4C2, 0x8888, 0xF4C3, 0x88D8, 0xF4C4, 0x88DF, 0xF4C5, 0x895E, 0xF4C6, 0x7F9D, 0xF4C7, 0x7F9F, 0xF4C8, 0x7FA7, + 0xF4C9, 0x7FAF, 0xF4CA, 0x7FB0, 0xF4CB, 0x7FB2, 0xF4CC, 0x7C7C, 0xF4CD, 0x6549, 0xF4CE, 0x7C91, 0xF4CF, 0x7C9D, 0xF4D0, 0x7C9C, + 0xF4D1, 0x7C9E, 0xF4D2, 0x7CA2, 0xF4D3, 0x7CB2, 0xF4D4, 0x7CBC, 0xF4D5, 0x7CBD, 0xF4D6, 0x7CC1, 0xF4D7, 0x7CC7, 0xF4D8, 0x7CCC, + 0xF4D9, 0x7CCD, 0xF4DA, 0x7CC8, 0xF4DB, 0x7CC5, 0xF4DC, 0x7CD7, 0xF4DD, 0x7CE8, 0xF4DE, 0x826E, 0xF4DF, 0x66A8, 0xF4E0, 0x7FBF, + 0xF4E1, 0x7FCE, 0xF4E2, 0x7FD5, 0xF4E3, 0x7FE5, 0xF4E4, 0x7FE1, 0xF4E5, 0x7FE6, 0xF4E6, 0x7FE9, 0xF4E7, 0x7FEE, 0xF4E8, 0x7FF3, + 0xF4E9, 0x7CF8, 0xF4EA, 0x7D77, 0xF4EB, 0x7DA6, 0xF4EC, 0x7DAE, 0xF4ED, 0x7E47, 0xF4EE, 0x7E9B, 0xF4EF, 0x9EB8, 0xF4F0, 0x9EB4, + 0xF4F1, 0x8D73, 0xF4F2, 0x8D84, 0xF4F3, 0x8D94, 0xF4F4, 0x8D91, 0xF4F5, 0x8DB1, 0xF4F6, 0x8D67, 0xF4F7, 0x8D6D, 0xF4F8, 0x8C47, + 0xF4F9, 0x8C49, 0xF4FA, 0x914A, 0xF4FB, 0x9150, 0xF4FC, 0x914E, 0xF4FD, 0x914F, 0xF4FE, 0x9164, 0xF540, 0x9B7C, 0xF541, 0x9B7D, + 0xF542, 0x9B7E, 0xF543, 0x9B7F, 0xF544, 0x9B80, 0xF545, 0x9B81, 0xF546, 0x9B82, 0xF547, 0x9B83, 0xF548, 0x9B84, 0xF549, 0x9B85, + 0xF54A, 0x9B86, 0xF54B, 0x9B87, 0xF54C, 0x9B88, 0xF54D, 0x9B89, 0xF54E, 0x9B8A, 0xF54F, 0x9B8B, 0xF550, 0x9B8C, 0xF551, 0x9B8D, + 0xF552, 0x9B8E, 0xF553, 0x9B8F, 0xF554, 0x9B90, 0xF555, 0x9B91, 0xF556, 0x9B92, 0xF557, 0x9B93, 0xF558, 0x9B94, 0xF559, 0x9B95, + 0xF55A, 0x9B96, 0xF55B, 0x9B97, 0xF55C, 0x9B98, 0xF55D, 0x9B99, 0xF55E, 0x9B9A, 0xF55F, 0x9B9B, 0xF560, 0x9B9C, 0xF561, 0x9B9D, + 0xF562, 0x9B9E, 0xF563, 0x9B9F, 0xF564, 0x9BA0, 0xF565, 0x9BA1, 0xF566, 0x9BA2, 0xF567, 0x9BA3, 0xF568, 0x9BA4, 0xF569, 0x9BA5, + 0xF56A, 0x9BA6, 0xF56B, 0x9BA7, 0xF56C, 0x9BA8, 0xF56D, 0x9BA9, 0xF56E, 0x9BAA, 0xF56F, 0x9BAB, 0xF570, 0x9BAC, 0xF571, 0x9BAD, + 0xF572, 0x9BAE, 0xF573, 0x9BAF, 0xF574, 0x9BB0, 0xF575, 0x9BB1, 0xF576, 0x9BB2, 0xF577, 0x9BB3, 0xF578, 0x9BB4, 0xF579, 0x9BB5, + 0xF57A, 0x9BB6, 0xF57B, 0x9BB7, 0xF57C, 0x9BB8, 0xF57D, 0x9BB9, 0xF57E, 0x9BBA, 0xF580, 0x9BBB, 0xF581, 0x9BBC, 0xF582, 0x9BBD, + 0xF583, 0x9BBE, 0xF584, 0x9BBF, 0xF585, 0x9BC0, 0xF586, 0x9BC1, 0xF587, 0x9BC2, 0xF588, 0x9BC3, 0xF589, 0x9BC4, 0xF58A, 0x9BC5, + 0xF58B, 0x9BC6, 0xF58C, 0x9BC7, 0xF58D, 0x9BC8, 0xF58E, 0x9BC9, 0xF58F, 0x9BCA, 0xF590, 0x9BCB, 0xF591, 0x9BCC, 0xF592, 0x9BCD, + 0xF593, 0x9BCE, 0xF594, 0x9BCF, 0xF595, 0x9BD0, 0xF596, 0x9BD1, 0xF597, 0x9BD2, 0xF598, 0x9BD3, 0xF599, 0x9BD4, 0xF59A, 0x9BD5, + 0xF59B, 0x9BD6, 0xF59C, 0x9BD7, 0xF59D, 0x9BD8, 0xF59E, 0x9BD9, 0xF59F, 0x9BDA, 0xF5A0, 0x9BDB, 0xF5A1, 0x9162, 0xF5A2, 0x9161, + 0xF5A3, 0x9170, 0xF5A4, 0x9169, 0xF5A5, 0x916F, 0xF5A6, 0x917D, 0xF5A7, 0x917E, 0xF5A8, 0x9172, 0xF5A9, 0x9174, 0xF5AA, 0x9179, + 0xF5AB, 0x918C, 0xF5AC, 0x9185, 0xF5AD, 0x9190, 0xF5AE, 0x918D, 0xF5AF, 0x9191, 0xF5B0, 0x91A2, 0xF5B1, 0x91A3, 0xF5B2, 0x91AA, + 0xF5B3, 0x91AD, 0xF5B4, 0x91AE, 0xF5B5, 0x91AF, 0xF5B6, 0x91B5, 0xF5B7, 0x91B4, 0xF5B8, 0x91BA, 0xF5B9, 0x8C55, 0xF5BA, 0x9E7E, + 0xF5BB, 0x8DB8, 0xF5BC, 0x8DEB, 0xF5BD, 0x8E05, 0xF5BE, 0x8E59, 0xF5BF, 0x8E69, 0xF5C0, 0x8DB5, 0xF5C1, 0x8DBF, 0xF5C2, 0x8DBC, + 0xF5C3, 0x8DBA, 0xF5C4, 0x8DC4, 0xF5C5, 0x8DD6, 0xF5C6, 0x8DD7, 0xF5C7, 0x8DDA, 0xF5C8, 0x8DDE, 0xF5C9, 0x8DCE, 0xF5CA, 0x8DCF, + 0xF5CB, 0x8DDB, 0xF5CC, 0x8DC6, 0xF5CD, 0x8DEC, 0xF5CE, 0x8DF7, 0xF5CF, 0x8DF8, 0xF5D0, 0x8DE3, 0xF5D1, 0x8DF9, 0xF5D2, 0x8DFB, + 0xF5D3, 0x8DE4, 0xF5D4, 0x8E09, 0xF5D5, 0x8DFD, 0xF5D6, 0x8E14, 0xF5D7, 0x8E1D, 0xF5D8, 0x8E1F, 0xF5D9, 0x8E2C, 0xF5DA, 0x8E2E, + 0xF5DB, 0x8E23, 0xF5DC, 0x8E2F, 0xF5DD, 0x8E3A, 0xF5DE, 0x8E40, 0xF5DF, 0x8E39, 0xF5E0, 0x8E35, 0xF5E1, 0x8E3D, 0xF5E2, 0x8E31, + 0xF5E3, 0x8E49, 0xF5E4, 0x8E41, 0xF5E5, 0x8E42, 0xF5E6, 0x8E51, 0xF5E7, 0x8E52, 0xF5E8, 0x8E4A, 0xF5E9, 0x8E70, 0xF5EA, 0x8E76, + 0xF5EB, 0x8E7C, 0xF5EC, 0x8E6F, 0xF5ED, 0x8E74, 0xF5EE, 0x8E85, 0xF5EF, 0x8E8F, 0xF5F0, 0x8E94, 0xF5F1, 0x8E90, 0xF5F2, 0x8E9C, + 0xF5F3, 0x8E9E, 0xF5F4, 0x8C78, 0xF5F5, 0x8C82, 0xF5F6, 0x8C8A, 0xF5F7, 0x8C85, 0xF5F8, 0x8C98, 0xF5F9, 0x8C94, 0xF5FA, 0x659B, + 0xF5FB, 0x89D6, 0xF5FC, 0x89DE, 0xF5FD, 0x89DA, 0xF5FE, 0x89DC, 0xF640, 0x9BDC, 0xF641, 0x9BDD, 0xF642, 0x9BDE, 0xF643, 0x9BDF, + 0xF644, 0x9BE0, 0xF645, 0x9BE1, 0xF646, 0x9BE2, 0xF647, 0x9BE3, 0xF648, 0x9BE4, 0xF649, 0x9BE5, 0xF64A, 0x9BE6, 0xF64B, 0x9BE7, + 0xF64C, 0x9BE8, 0xF64D, 0x9BE9, 0xF64E, 0x9BEA, 0xF64F, 0x9BEB, 0xF650, 0x9BEC, 0xF651, 0x9BED, 0xF652, 0x9BEE, 0xF653, 0x9BEF, + 0xF654, 0x9BF0, 0xF655, 0x9BF1, 0xF656, 0x9BF2, 0xF657, 0x9BF3, 0xF658, 0x9BF4, 0xF659, 0x9BF5, 0xF65A, 0x9BF6, 0xF65B, 0x9BF7, + 0xF65C, 0x9BF8, 0xF65D, 0x9BF9, 0xF65E, 0x9BFA, 0xF65F, 0x9BFB, 0xF660, 0x9BFC, 0xF661, 0x9BFD, 0xF662, 0x9BFE, 0xF663, 0x9BFF, + 0xF664, 0x9C00, 0xF665, 0x9C01, 0xF666, 0x9C02, 0xF667, 0x9C03, 0xF668, 0x9C04, 0xF669, 0x9C05, 0xF66A, 0x9C06, 0xF66B, 0x9C07, + 0xF66C, 0x9C08, 0xF66D, 0x9C09, 0xF66E, 0x9C0A, 0xF66F, 0x9C0B, 0xF670, 0x9C0C, 0xF671, 0x9C0D, 0xF672, 0x9C0E, 0xF673, 0x9C0F, + 0xF674, 0x9C10, 0xF675, 0x9C11, 0xF676, 0x9C12, 0xF677, 0x9C13, 0xF678, 0x9C14, 0xF679, 0x9C15, 0xF67A, 0x9C16, 0xF67B, 0x9C17, + 0xF67C, 0x9C18, 0xF67D, 0x9C19, 0xF67E, 0x9C1A, 0xF680, 0x9C1B, 0xF681, 0x9C1C, 0xF682, 0x9C1D, 0xF683, 0x9C1E, 0xF684, 0x9C1F, + 0xF685, 0x9C20, 0xF686, 0x9C21, 0xF687, 0x9C22, 0xF688, 0x9C23, 0xF689, 0x9C24, 0xF68A, 0x9C25, 0xF68B, 0x9C26, 0xF68C, 0x9C27, + 0xF68D, 0x9C28, 0xF68E, 0x9C29, 0xF68F, 0x9C2A, 0xF690, 0x9C2B, 0xF691, 0x9C2C, 0xF692, 0x9C2D, 0xF693, 0x9C2E, 0xF694, 0x9C2F, + 0xF695, 0x9C30, 0xF696, 0x9C31, 0xF697, 0x9C32, 0xF698, 0x9C33, 0xF699, 0x9C34, 0xF69A, 0x9C35, 0xF69B, 0x9C36, 0xF69C, 0x9C37, + 0xF69D, 0x9C38, 0xF69E, 0x9C39, 0xF69F, 0x9C3A, 0xF6A0, 0x9C3B, 0xF6A1, 0x89E5, 0xF6A2, 0x89EB, 0xF6A3, 0x89EF, 0xF6A4, 0x8A3E, + 0xF6A5, 0x8B26, 0xF6A6, 0x9753, 0xF6A7, 0x96E9, 0xF6A8, 0x96F3, 0xF6A9, 0x96EF, 0xF6AA, 0x9706, 0xF6AB, 0x9701, 0xF6AC, 0x9708, + 0xF6AD, 0x970F, 0xF6AE, 0x970E, 0xF6AF, 0x972A, 0xF6B0, 0x972D, 0xF6B1, 0x9730, 0xF6B2, 0x973E, 0xF6B3, 0x9F80, 0xF6B4, 0x9F83, + 0xF6B5, 0x9F85, 0xF6B6, 0x9F86, 0xF6B7, 0x9F87, 0xF6B8, 0x9F88, 0xF6B9, 0x9F89, 0xF6BA, 0x9F8A, 0xF6BB, 0x9F8C, 0xF6BC, 0x9EFE, + 0xF6BD, 0x9F0B, 0xF6BE, 0x9F0D, 0xF6BF, 0x96B9, 0xF6C0, 0x96BC, 0xF6C1, 0x96BD, 0xF6C2, 0x96CE, 0xF6C3, 0x96D2, 0xF6C4, 0x77BF, + 0xF6C5, 0x96E0, 0xF6C6, 0x928E, 0xF6C7, 0x92AE, 0xF6C8, 0x92C8, 0xF6C9, 0x933E, 0xF6CA, 0x936A, 0xF6CB, 0x93CA, 0xF6CC, 0x938F, + 0xF6CD, 0x943E, 0xF6CE, 0x946B, 0xF6CF, 0x9C7F, 0xF6D0, 0x9C82, 0xF6D1, 0x9C85, 0xF6D2, 0x9C86, 0xF6D3, 0x9C87, 0xF6D4, 0x9C88, + 0xF6D5, 0x7A23, 0xF6D6, 0x9C8B, 0xF6D7, 0x9C8E, 0xF6D8, 0x9C90, 0xF6D9, 0x9C91, 0xF6DA, 0x9C92, 0xF6DB, 0x9C94, 0xF6DC, 0x9C95, + 0xF6DD, 0x9C9A, 0xF6DE, 0x9C9B, 0xF6DF, 0x9C9E, 0xF6E0, 0x9C9F, 0xF6E1, 0x9CA0, 0xF6E2, 0x9CA1, 0xF6E3, 0x9CA2, 0xF6E4, 0x9CA3, + 0xF6E5, 0x9CA5, 0xF6E6, 0x9CA6, 0xF6E7, 0x9CA7, 0xF6E8, 0x9CA8, 0xF6E9, 0x9CA9, 0xF6EA, 0x9CAB, 0xF6EB, 0x9CAD, 0xF6EC, 0x9CAE, + 0xF6ED, 0x9CB0, 0xF6EE, 0x9CB1, 0xF6EF, 0x9CB2, 0xF6F0, 0x9CB3, 0xF6F1, 0x9CB4, 0xF6F2, 0x9CB5, 0xF6F3, 0x9CB6, 0xF6F4, 0x9CB7, + 0xF6F5, 0x9CBA, 0xF6F6, 0x9CBB, 0xF6F7, 0x9CBC, 0xF6F8, 0x9CBD, 0xF6F9, 0x9CC4, 0xF6FA, 0x9CC5, 0xF6FB, 0x9CC6, 0xF6FC, 0x9CC7, + 0xF6FD, 0x9CCA, 0xF6FE, 0x9CCB, 0xF740, 0x9C3C, 0xF741, 0x9C3D, 0xF742, 0x9C3E, 0xF743, 0x9C3F, 0xF744, 0x9C40, 0xF745, 0x9C41, + 0xF746, 0x9C42, 0xF747, 0x9C43, 0xF748, 0x9C44, 0xF749, 0x9C45, 0xF74A, 0x9C46, 0xF74B, 0x9C47, 0xF74C, 0x9C48, 0xF74D, 0x9C49, + 0xF74E, 0x9C4A, 0xF74F, 0x9C4B, 0xF750, 0x9C4C, 0xF751, 0x9C4D, 0xF752, 0x9C4E, 0xF753, 0x9C4F, 0xF754, 0x9C50, 0xF755, 0x9C51, + 0xF756, 0x9C52, 0xF757, 0x9C53, 0xF758, 0x9C54, 0xF759, 0x9C55, 0xF75A, 0x9C56, 0xF75B, 0x9C57, 0xF75C, 0x9C58, 0xF75D, 0x9C59, + 0xF75E, 0x9C5A, 0xF75F, 0x9C5B, 0xF760, 0x9C5C, 0xF761, 0x9C5D, 0xF762, 0x9C5E, 0xF763, 0x9C5F, 0xF764, 0x9C60, 0xF765, 0x9C61, + 0xF766, 0x9C62, 0xF767, 0x9C63, 0xF768, 0x9C64, 0xF769, 0x9C65, 0xF76A, 0x9C66, 0xF76B, 0x9C67, 0xF76C, 0x9C68, 0xF76D, 0x9C69, + 0xF76E, 0x9C6A, 0xF76F, 0x9C6B, 0xF770, 0x9C6C, 0xF771, 0x9C6D, 0xF772, 0x9C6E, 0xF773, 0x9C6F, 0xF774, 0x9C70, 0xF775, 0x9C71, + 0xF776, 0x9C72, 0xF777, 0x9C73, 0xF778, 0x9C74, 0xF779, 0x9C75, 0xF77A, 0x9C76, 0xF77B, 0x9C77, 0xF77C, 0x9C78, 0xF77D, 0x9C79, + 0xF77E, 0x9C7A, 0xF780, 0x9C7B, 0xF781, 0x9C7D, 0xF782, 0x9C7E, 0xF783, 0x9C80, 0xF784, 0x9C83, 0xF785, 0x9C84, 0xF786, 0x9C89, + 0xF787, 0x9C8A, 0xF788, 0x9C8C, 0xF789, 0x9C8F, 0xF78A, 0x9C93, 0xF78B, 0x9C96, 0xF78C, 0x9C97, 0xF78D, 0x9C98, 0xF78E, 0x9C99, + 0xF78F, 0x9C9D, 0xF790, 0x9CAA, 0xF791, 0x9CAC, 0xF792, 0x9CAF, 0xF793, 0x9CB9, 0xF794, 0x9CBE, 0xF795, 0x9CBF, 0xF796, 0x9CC0, + 0xF797, 0x9CC1, 0xF798, 0x9CC2, 0xF799, 0x9CC8, 0xF79A, 0x9CC9, 0xF79B, 0x9CD1, 0xF79C, 0x9CD2, 0xF79D, 0x9CDA, 0xF79E, 0x9CDB, + 0xF79F, 0x9CE0, 0xF7A0, 0x9CE1, 0xF7A1, 0x9CCC, 0xF7A2, 0x9CCD, 0xF7A3, 0x9CCE, 0xF7A4, 0x9CCF, 0xF7A5, 0x9CD0, 0xF7A6, 0x9CD3, + 0xF7A7, 0x9CD4, 0xF7A8, 0x9CD5, 0xF7A9, 0x9CD7, 0xF7AA, 0x9CD8, 0xF7AB, 0x9CD9, 0xF7AC, 0x9CDC, 0xF7AD, 0x9CDD, 0xF7AE, 0x9CDF, + 0xF7AF, 0x9CE2, 0xF7B0, 0x977C, 0xF7B1, 0x9785, 0xF7B2, 0x9791, 0xF7B3, 0x9792, 0xF7B4, 0x9794, 0xF7B5, 0x97AF, 0xF7B6, 0x97AB, + 0xF7B7, 0x97A3, 0xF7B8, 0x97B2, 0xF7B9, 0x97B4, 0xF7BA, 0x9AB1, 0xF7BB, 0x9AB0, 0xF7BC, 0x9AB7, 0xF7BD, 0x9E58, 0xF7BE, 0x9AB6, + 0xF7BF, 0x9ABA, 0xF7C0, 0x9ABC, 0xF7C1, 0x9AC1, 0xF7C2, 0x9AC0, 0xF7C3, 0x9AC5, 0xF7C4, 0x9AC2, 0xF7C5, 0x9ACB, 0xF7C6, 0x9ACC, + 0xF7C7, 0x9AD1, 0xF7C8, 0x9B45, 0xF7C9, 0x9B43, 0xF7CA, 0x9B47, 0xF7CB, 0x9B49, 0xF7CC, 0x9B48, 0xF7CD, 0x9B4D, 0xF7CE, 0x9B51, + 0xF7CF, 0x98E8, 0xF7D0, 0x990D, 0xF7D1, 0x992E, 0xF7D2, 0x9955, 0xF7D3, 0x9954, 0xF7D4, 0x9ADF, 0xF7D5, 0x9AE1, 0xF7D6, 0x9AE6, + 0xF7D7, 0x9AEF, 0xF7D8, 0x9AEB, 0xF7D9, 0x9AFB, 0xF7DA, 0x9AED, 0xF7DB, 0x9AF9, 0xF7DC, 0x9B08, 0xF7DD, 0x9B0F, 0xF7DE, 0x9B13, + 0xF7DF, 0x9B1F, 0xF7E0, 0x9B23, 0xF7E1, 0x9EBD, 0xF7E2, 0x9EBE, 0xF7E3, 0x7E3B, 0xF7E4, 0x9E82, 0xF7E5, 0x9E87, 0xF7E6, 0x9E88, + 0xF7E7, 0x9E8B, 0xF7E8, 0x9E92, 0xF7E9, 0x93D6, 0xF7EA, 0x9E9D, 0xF7EB, 0x9E9F, 0xF7EC, 0x9EDB, 0xF7ED, 0x9EDC, 0xF7EE, 0x9EDD, + 0xF7EF, 0x9EE0, 0xF7F0, 0x9EDF, 0xF7F1, 0x9EE2, 0xF7F2, 0x9EE9, 0xF7F3, 0x9EE7, 0xF7F4, 0x9EE5, 0xF7F5, 0x9EEA, 0xF7F6, 0x9EEF, + 0xF7F7, 0x9F22, 0xF7F8, 0x9F2C, 0xF7F9, 0x9F2F, 0xF7FA, 0x9F39, 0xF7FB, 0x9F37, 0xF7FC, 0x9F3D, 0xF7FD, 0x9F3E, 0xF7FE, 0x9F44, + 0xF840, 0x9CE3, 0xF841, 0x9CE4, 0xF842, 0x9CE5, 0xF843, 0x9CE6, 0xF844, 0x9CE7, 0xF845, 0x9CE8, 0xF846, 0x9CE9, 0xF847, 0x9CEA, + 0xF848, 0x9CEB, 0xF849, 0x9CEC, 0xF84A, 0x9CED, 0xF84B, 0x9CEE, 0xF84C, 0x9CEF, 0xF84D, 0x9CF0, 0xF84E, 0x9CF1, 0xF84F, 0x9CF2, + 0xF850, 0x9CF3, 0xF851, 0x9CF4, 0xF852, 0x9CF5, 0xF853, 0x9CF6, 0xF854, 0x9CF7, 0xF855, 0x9CF8, 0xF856, 0x9CF9, 0xF857, 0x9CFA, + 0xF858, 0x9CFB, 0xF859, 0x9CFC, 0xF85A, 0x9CFD, 0xF85B, 0x9CFE, 0xF85C, 0x9CFF, 0xF85D, 0x9D00, 0xF85E, 0x9D01, 0xF85F, 0x9D02, + 0xF860, 0x9D03, 0xF861, 0x9D04, 0xF862, 0x9D05, 0xF863, 0x9D06, 0xF864, 0x9D07, 0xF865, 0x9D08, 0xF866, 0x9D09, 0xF867, 0x9D0A, + 0xF868, 0x9D0B, 0xF869, 0x9D0C, 0xF86A, 0x9D0D, 0xF86B, 0x9D0E, 0xF86C, 0x9D0F, 0xF86D, 0x9D10, 0xF86E, 0x9D11, 0xF86F, 0x9D12, + 0xF870, 0x9D13, 0xF871, 0x9D14, 0xF872, 0x9D15, 0xF873, 0x9D16, 0xF874, 0x9D17, 0xF875, 0x9D18, 0xF876, 0x9D19, 0xF877, 0x9D1A, + 0xF878, 0x9D1B, 0xF879, 0x9D1C, 0xF87A, 0x9D1D, 0xF87B, 0x9D1E, 0xF87C, 0x9D1F, 0xF87D, 0x9D20, 0xF87E, 0x9D21, 0xF880, 0x9D22, + 0xF881, 0x9D23, 0xF882, 0x9D24, 0xF883, 0x9D25, 0xF884, 0x9D26, 0xF885, 0x9D27, 0xF886, 0x9D28, 0xF887, 0x9D29, 0xF888, 0x9D2A, + 0xF889, 0x9D2B, 0xF88A, 0x9D2C, 0xF88B, 0x9D2D, 0xF88C, 0x9D2E, 0xF88D, 0x9D2F, 0xF88E, 0x9D30, 0xF88F, 0x9D31, 0xF890, 0x9D32, + 0xF891, 0x9D33, 0xF892, 0x9D34, 0xF893, 0x9D35, 0xF894, 0x9D36, 0xF895, 0x9D37, 0xF896, 0x9D38, 0xF897, 0x9D39, 0xF898, 0x9D3A, + 0xF899, 0x9D3B, 0xF89A, 0x9D3C, 0xF89B, 0x9D3D, 0xF89C, 0x9D3E, 0xF89D, 0x9D3F, 0xF89E, 0x9D40, 0xF89F, 0x9D41, 0xF8A0, 0x9D42, + 0xF940, 0x9D43, 0xF941, 0x9D44, 0xF942, 0x9D45, 0xF943, 0x9D46, 0xF944, 0x9D47, 0xF945, 0x9D48, 0xF946, 0x9D49, 0xF947, 0x9D4A, + 0xF948, 0x9D4B, 0xF949, 0x9D4C, 0xF94A, 0x9D4D, 0xF94B, 0x9D4E, 0xF94C, 0x9D4F, 0xF94D, 0x9D50, 0xF94E, 0x9D51, 0xF94F, 0x9D52, + 0xF950, 0x9D53, 0xF951, 0x9D54, 0xF952, 0x9D55, 0xF953, 0x9D56, 0xF954, 0x9D57, 0xF955, 0x9D58, 0xF956, 0x9D59, 0xF957, 0x9D5A, + 0xF958, 0x9D5B, 0xF959, 0x9D5C, 0xF95A, 0x9D5D, 0xF95B, 0x9D5E, 0xF95C, 0x9D5F, 0xF95D, 0x9D60, 0xF95E, 0x9D61, 0xF95F, 0x9D62, + 0xF960, 0x9D63, 0xF961, 0x9D64, 0xF962, 0x9D65, 0xF963, 0x9D66, 0xF964, 0x9D67, 0xF965, 0x9D68, 0xF966, 0x9D69, 0xF967, 0x9D6A, + 0xF968, 0x9D6B, 0xF969, 0x9D6C, 0xF96A, 0x9D6D, 0xF96B, 0x9D6E, 0xF96C, 0x9D6F, 0xF96D, 0x9D70, 0xF96E, 0x9D71, 0xF96F, 0x9D72, + 0xF970, 0x9D73, 0xF971, 0x9D74, 0xF972, 0x9D75, 0xF973, 0x9D76, 0xF974, 0x9D77, 0xF975, 0x9D78, 0xF976, 0x9D79, 0xF977, 0x9D7A, + 0xF978, 0x9D7B, 0xF979, 0x9D7C, 0xF97A, 0x9D7D, 0xF97B, 0x9D7E, 0xF97C, 0x9D7F, 0xF97D, 0x9D80, 0xF97E, 0x9D81, 0xF980, 0x9D82, + 0xF981, 0x9D83, 0xF982, 0x9D84, 0xF983, 0x9D85, 0xF984, 0x9D86, 0xF985, 0x9D87, 0xF986, 0x9D88, 0xF987, 0x9D89, 0xF988, 0x9D8A, + 0xF989, 0x9D8B, 0xF98A, 0x9D8C, 0xF98B, 0x9D8D, 0xF98C, 0x9D8E, 0xF98D, 0x9D8F, 0xF98E, 0x9D90, 0xF98F, 0x9D91, 0xF990, 0x9D92, + 0xF991, 0x9D93, 0xF992, 0x9D94, 0xF993, 0x9D95, 0xF994, 0x9D96, 0xF995, 0x9D97, 0xF996, 0x9D98, 0xF997, 0x9D99, 0xF998, 0x9D9A, + 0xF999, 0x9D9B, 0xF99A, 0x9D9C, 0xF99B, 0x9D9D, 0xF99C, 0x9D9E, 0xF99D, 0x9D9F, 0xF99E, 0x9DA0, 0xF99F, 0x9DA1, 0xF9A0, 0x9DA2, + 0xFA40, 0x9DA3, 0xFA41, 0x9DA4, 0xFA42, 0x9DA5, 0xFA43, 0x9DA6, 0xFA44, 0x9DA7, 0xFA45, 0x9DA8, 0xFA46, 0x9DA9, 0xFA47, 0x9DAA, + 0xFA48, 0x9DAB, 0xFA49, 0x9DAC, 0xFA4A, 0x9DAD, 0xFA4B, 0x9DAE, 0xFA4C, 0x9DAF, 0xFA4D, 0x9DB0, 0xFA4E, 0x9DB1, 0xFA4F, 0x9DB2, + 0xFA50, 0x9DB3, 0xFA51, 0x9DB4, 0xFA52, 0x9DB5, 0xFA53, 0x9DB6, 0xFA54, 0x9DB7, 0xFA55, 0x9DB8, 0xFA56, 0x9DB9, 0xFA57, 0x9DBA, + 0xFA58, 0x9DBB, 0xFA59, 0x9DBC, 0xFA5A, 0x9DBD, 0xFA5B, 0x9DBE, 0xFA5C, 0x9DBF, 0xFA5D, 0x9DC0, 0xFA5E, 0x9DC1, 0xFA5F, 0x9DC2, + 0xFA60, 0x9DC3, 0xFA61, 0x9DC4, 0xFA62, 0x9DC5, 0xFA63, 0x9DC6, 0xFA64, 0x9DC7, 0xFA65, 0x9DC8, 0xFA66, 0x9DC9, 0xFA67, 0x9DCA, + 0xFA68, 0x9DCB, 0xFA69, 0x9DCC, 0xFA6A, 0x9DCD, 0xFA6B, 0x9DCE, 0xFA6C, 0x9DCF, 0xFA6D, 0x9DD0, 0xFA6E, 0x9DD1, 0xFA6F, 0x9DD2, + 0xFA70, 0x9DD3, 0xFA71, 0x9DD4, 0xFA72, 0x9DD5, 0xFA73, 0x9DD6, 0xFA74, 0x9DD7, 0xFA75, 0x9DD8, 0xFA76, 0x9DD9, 0xFA77, 0x9DDA, + 0xFA78, 0x9DDB, 0xFA79, 0x9DDC, 0xFA7A, 0x9DDD, 0xFA7B, 0x9DDE, 0xFA7C, 0x9DDF, 0xFA7D, 0x9DE0, 0xFA7E, 0x9DE1, 0xFA80, 0x9DE2, + 0xFA81, 0x9DE3, 0xFA82, 0x9DE4, 0xFA83, 0x9DE5, 0xFA84, 0x9DE6, 0xFA85, 0x9DE7, 0xFA86, 0x9DE8, 0xFA87, 0x9DE9, 0xFA88, 0x9DEA, + 0xFA89, 0x9DEB, 0xFA8A, 0x9DEC, 0xFA8B, 0x9DED, 0xFA8C, 0x9DEE, 0xFA8D, 0x9DEF, 0xFA8E, 0x9DF0, 0xFA8F, 0x9DF1, 0xFA90, 0x9DF2, + 0xFA91, 0x9DF3, 0xFA92, 0x9DF4, 0xFA93, 0x9DF5, 0xFA94, 0x9DF6, 0xFA95, 0x9DF7, 0xFA96, 0x9DF8, 0xFA97, 0x9DF9, 0xFA98, 0x9DFA, + 0xFA99, 0x9DFB, 0xFA9A, 0x9DFC, 0xFA9B, 0x9DFD, 0xFA9C, 0x9DFE, 0xFA9D, 0x9DFF, 0xFA9E, 0x9E00, 0xFA9F, 0x9E01, 0xFAA0, 0x9E02, + 0xFB40, 0x9E03, 0xFB41, 0x9E04, 0xFB42, 0x9E05, 0xFB43, 0x9E06, 0xFB44, 0x9E07, 0xFB45, 0x9E08, 0xFB46, 0x9E09, 0xFB47, 0x9E0A, + 0xFB48, 0x9E0B, 0xFB49, 0x9E0C, 0xFB4A, 0x9E0D, 0xFB4B, 0x9E0E, 0xFB4C, 0x9E0F, 0xFB4D, 0x9E10, 0xFB4E, 0x9E11, 0xFB4F, 0x9E12, + 0xFB50, 0x9E13, 0xFB51, 0x9E14, 0xFB52, 0x9E15, 0xFB53, 0x9E16, 0xFB54, 0x9E17, 0xFB55, 0x9E18, 0xFB56, 0x9E19, 0xFB57, 0x9E1A, + 0xFB58, 0x9E1B, 0xFB59, 0x9E1C, 0xFB5A, 0x9E1D, 0xFB5B, 0x9E1E, 0xFB5C, 0x9E24, 0xFB5D, 0x9E27, 0xFB5E, 0x9E2E, 0xFB5F, 0x9E30, + 0xFB60, 0x9E34, 0xFB61, 0x9E3B, 0xFB62, 0x9E3C, 0xFB63, 0x9E40, 0xFB64, 0x9E4D, 0xFB65, 0x9E50, 0xFB66, 0x9E52, 0xFB67, 0x9E53, + 0xFB68, 0x9E54, 0xFB69, 0x9E56, 0xFB6A, 0x9E59, 0xFB6B, 0x9E5D, 0xFB6C, 0x9E5F, 0xFB6D, 0x9E60, 0xFB6E, 0x9E61, 0xFB6F, 0x9E62, + 0xFB70, 0x9E65, 0xFB71, 0x9E6E, 0xFB72, 0x9E6F, 0xFB73, 0x9E72, 0xFB74, 0x9E74, 0xFB75, 0x9E75, 0xFB76, 0x9E76, 0xFB77, 0x9E77, + 0xFB78, 0x9E78, 0xFB79, 0x9E79, 0xFB7A, 0x9E7A, 0xFB7B, 0x9E7B, 0xFB7C, 0x9E7C, 0xFB7D, 0x9E7D, 0xFB7E, 0x9E80, 0xFB80, 0x9E81, + 0xFB81, 0x9E83, 0xFB82, 0x9E84, 0xFB83, 0x9E85, 0xFB84, 0x9E86, 0xFB85, 0x9E89, 0xFB86, 0x9E8A, 0xFB87, 0x9E8C, 0xFB88, 0x9E8D, + 0xFB89, 0x9E8E, 0xFB8A, 0x9E8F, 0xFB8B, 0x9E90, 0xFB8C, 0x9E91, 0xFB8D, 0x9E94, 0xFB8E, 0x9E95, 0xFB8F, 0x9E96, 0xFB90, 0x9E97, + 0xFB91, 0x9E98, 0xFB92, 0x9E99, 0xFB93, 0x9E9A, 0xFB94, 0x9E9B, 0xFB95, 0x9E9C, 0xFB96, 0x9E9E, 0xFB97, 0x9EA0, 0xFB98, 0x9EA1, + 0xFB99, 0x9EA2, 0xFB9A, 0x9EA3, 0xFB9B, 0x9EA4, 0xFB9C, 0x9EA5, 0xFB9D, 0x9EA7, 0xFB9E, 0x9EA8, 0xFB9F, 0x9EA9, 0xFBA0, 0x9EAA, + 0xFC40, 0x9EAB, 0xFC41, 0x9EAC, 0xFC42, 0x9EAD, 0xFC43, 0x9EAE, 0xFC44, 0x9EAF, 0xFC45, 0x9EB0, 0xFC46, 0x9EB1, 0xFC47, 0x9EB2, + 0xFC48, 0x9EB3, 0xFC49, 0x9EB5, 0xFC4A, 0x9EB6, 0xFC4B, 0x9EB7, 0xFC4C, 0x9EB9, 0xFC4D, 0x9EBA, 0xFC4E, 0x9EBC, 0xFC4F, 0x9EBF, + 0xFC50, 0x9EC0, 0xFC51, 0x9EC1, 0xFC52, 0x9EC2, 0xFC53, 0x9EC3, 0xFC54, 0x9EC5, 0xFC55, 0x9EC6, 0xFC56, 0x9EC7, 0xFC57, 0x9EC8, + 0xFC58, 0x9ECA, 0xFC59, 0x9ECB, 0xFC5A, 0x9ECC, 0xFC5B, 0x9ED0, 0xFC5C, 0x9ED2, 0xFC5D, 0x9ED3, 0xFC5E, 0x9ED5, 0xFC5F, 0x9ED6, + 0xFC60, 0x9ED7, 0xFC61, 0x9ED9, 0xFC62, 0x9EDA, 0xFC63, 0x9EDE, 0xFC64, 0x9EE1, 0xFC65, 0x9EE3, 0xFC66, 0x9EE4, 0xFC67, 0x9EE6, + 0xFC68, 0x9EE8, 0xFC69, 0x9EEB, 0xFC6A, 0x9EEC, 0xFC6B, 0x9EED, 0xFC6C, 0x9EEE, 0xFC6D, 0x9EF0, 0xFC6E, 0x9EF1, 0xFC6F, 0x9EF2, + 0xFC70, 0x9EF3, 0xFC71, 0x9EF4, 0xFC72, 0x9EF5, 0xFC73, 0x9EF6, 0xFC74, 0x9EF7, 0xFC75, 0x9EF8, 0xFC76, 0x9EFA, 0xFC77, 0x9EFD, + 0xFC78, 0x9EFF, 0xFC79, 0x9F00, 0xFC7A, 0x9F01, 0xFC7B, 0x9F02, 0xFC7C, 0x9F03, 0xFC7D, 0x9F04, 0xFC7E, 0x9F05, 0xFC80, 0x9F06, + 0xFC81, 0x9F07, 0xFC82, 0x9F08, 0xFC83, 0x9F09, 0xFC84, 0x9F0A, 0xFC85, 0x9F0C, 0xFC86, 0x9F0F, 0xFC87, 0x9F11, 0xFC88, 0x9F12, + 0xFC89, 0x9F14, 0xFC8A, 0x9F15, 0xFC8B, 0x9F16, 0xFC8C, 0x9F18, 0xFC8D, 0x9F1A, 0xFC8E, 0x9F1B, 0xFC8F, 0x9F1C, 0xFC90, 0x9F1D, + 0xFC91, 0x9F1E, 0xFC92, 0x9F1F, 0xFC93, 0x9F21, 0xFC94, 0x9F23, 0xFC95, 0x9F24, 0xFC96, 0x9F25, 0xFC97, 0x9F26, 0xFC98, 0x9F27, + 0xFC99, 0x9F28, 0xFC9A, 0x9F29, 0xFC9B, 0x9F2A, 0xFC9C, 0x9F2B, 0xFC9D, 0x9F2D, 0xFC9E, 0x9F2E, 0xFC9F, 0x9F30, 0xFCA0, 0x9F31, + 0xFD40, 0x9F32, 0xFD41, 0x9F33, 0xFD42, 0x9F34, 0xFD43, 0x9F35, 0xFD44, 0x9F36, 0xFD45, 0x9F38, 0xFD46, 0x9F3A, 0xFD47, 0x9F3C, + 0xFD48, 0x9F3F, 0xFD49, 0x9F40, 0xFD4A, 0x9F41, 0xFD4B, 0x9F42, 0xFD4C, 0x9F43, 0xFD4D, 0x9F45, 0xFD4E, 0x9F46, 0xFD4F, 0x9F47, + 0xFD50, 0x9F48, 0xFD51, 0x9F49, 0xFD52, 0x9F4A, 0xFD53, 0x9F4B, 0xFD54, 0x9F4C, 0xFD55, 0x9F4D, 0xFD56, 0x9F4E, 0xFD57, 0x9F4F, + 0xFD58, 0x9F52, 0xFD59, 0x9F53, 0xFD5A, 0x9F54, 0xFD5B, 0x9F55, 0xFD5C, 0x9F56, 0xFD5D, 0x9F57, 0xFD5E, 0x9F58, 0xFD5F, 0x9F59, + 0xFD60, 0x9F5A, 0xFD61, 0x9F5B, 0xFD62, 0x9F5C, 0xFD63, 0x9F5D, 0xFD64, 0x9F5E, 0xFD65, 0x9F5F, 0xFD66, 0x9F60, 0xFD67, 0x9F61, + 0xFD68, 0x9F62, 0xFD69, 0x9F63, 0xFD6A, 0x9F64, 0xFD6B, 0x9F65, 0xFD6C, 0x9F66, 0xFD6D, 0x9F67, 0xFD6E, 0x9F68, 0xFD6F, 0x9F69, + 0xFD70, 0x9F6A, 0xFD71, 0x9F6B, 0xFD72, 0x9F6C, 0xFD73, 0x9F6D, 0xFD74, 0x9F6E, 0xFD75, 0x9F6F, 0xFD76, 0x9F70, 0xFD77, 0x9F71, + 0xFD78, 0x9F72, 0xFD79, 0x9F73, 0xFD7A, 0x9F74, 0xFD7B, 0x9F75, 0xFD7C, 0x9F76, 0xFD7D, 0x9F77, 0xFD7E, 0x9F78, 0xFD80, 0x9F79, + 0xFD81, 0x9F7A, 0xFD82, 0x9F7B, 0xFD83, 0x9F7C, 0xFD84, 0x9F7D, 0xFD85, 0x9F7E, 0xFD86, 0x9F81, 0xFD87, 0x9F82, 0xFD88, 0x9F8D, + 0xFD89, 0x9F8E, 0xFD8A, 0x9F8F, 0xFD8B, 0x9F90, 0xFD8C, 0x9F91, 0xFD8D, 0x9F92, 0xFD8E, 0x9F93, 0xFD8F, 0x9F94, 0xFD90, 0x9F95, + 0xFD91, 0x9F96, 0xFD92, 0x9F97, 0xFD93, 0x9F98, 0xFD94, 0x9F9C, 0xFD95, 0x9F9D, 0xFD96, 0x9F9E, 0xFD97, 0x9FA1, 0xFD98, 0x9FA2, + 0xFD99, 0x9FA3, 0xFD9A, 0x9FA4, 0xFD9B, 0x9FA5, 0xFD9C, 0xF92C, 0xFD9D, 0xF979, 0xFD9E, 0xF995, 0xFD9F, 0xF9E7, 0xFDA0, 0xF9F1, + 0xFE40, 0xFA0C, 0xFE41, 0xFA0D, 0xFE42, 0xFA0E, 0xFE43, 0xFA0F, 0xFE44, 0xFA11, 0xFE45, 0xFA13, 0xFE46, 0xFA14, 0xFE47, 0xFA18, + 0xFE48, 0xFA1F, 0xFE49, 0xFA20, 0xFE4A, 0xFA21, 0xFE4B, 0xFA23, 0xFE4C, 0xFA24, 0xFE4D, 0xFA27, 0xFE4E, 0xFA28, 0xFE4F, 0xFA29, + 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */ +static const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */ + 0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6, + 0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6, + 0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF, + 0x00D8, 0xA8AA, 0x00DE, 0xA8AD, 0x00DF, 0xA9AC, 0x00E6, 0xA9A1, 0x00F0, 0xA9A3, 0x00F7, 0xA1C0, 0x00F8, 0xA9AA, 0x00FE, 0xA9AD, + 0x0111, 0xA9A2, 0x0126, 0xA8A4, 0x0127, 0xA9A4, 0x0131, 0xA9A5, 0x0132, 0xA8A6, 0x0133, 0xA9A6, 0x0138, 0xA9A7, 0x013F, 0xA8A8, + 0x0140, 0xA9A8, 0x0141, 0xA8A9, 0x0142, 0xA9A9, 0x0149, 0xA9B0, 0x014A, 0xA8AF, 0x014B, 0xA9AF, 0x0152, 0xA8AB, 0x0153, 0xA9AB, + 0x0166, 0xA8AE, 0x0167, 0xA9AE, 0x02C7, 0xA2A7, 0x02D0, 0xA2B0, 0x02D8, 0xA2A8, 0x02D9, 0xA2AB, 0x02DA, 0xA2AA, 0x02DB, 0xA2AD, + 0x02DD, 0xA2A9, 0x0391, 0xA5C1, 0x0392, 0xA5C2, 0x0393, 0xA5C3, 0x0394, 0xA5C4, 0x0395, 0xA5C5, 0x0396, 0xA5C6, 0x0397, 0xA5C7, + 0x0398, 0xA5C8, 0x0399, 0xA5C9, 0x039A, 0xA5CA, 0x039B, 0xA5CB, 0x039C, 0xA5CC, 0x039D, 0xA5CD, 0x039E, 0xA5CE, 0x039F, 0xA5CF, + 0x03A0, 0xA5D0, 0x03A1, 0xA5D1, 0x03A3, 0xA5D2, 0x03A4, 0xA5D3, 0x03A5, 0xA5D4, 0x03A6, 0xA5D5, 0x03A7, 0xA5D6, 0x03A8, 0xA5D7, + 0x03A9, 0xA5D8, 0x03B1, 0xA5E1, 0x03B2, 0xA5E2, 0x03B3, 0xA5E3, 0x03B4, 0xA5E4, 0x03B5, 0xA5E5, 0x03B6, 0xA5E6, 0x03B7, 0xA5E7, + 0x03B8, 0xA5E8, 0x03B9, 0xA5E9, 0x03BA, 0xA5EA, 0x03BB, 0xA5EB, 0x03BC, 0xA5EC, 0x03BD, 0xA5ED, 0x03BE, 0xA5EE, 0x03BF, 0xA5EF, + 0x03C0, 0xA5F0, 0x03C1, 0xA5F1, 0x03C3, 0xA5F2, 0x03C4, 0xA5F3, 0x03C5, 0xA5F4, 0x03C6, 0xA5F5, 0x03C7, 0xA5F6, 0x03C8, 0xA5F7, + 0x03C9, 0xA5F8, 0x0401, 0xACA7, 0x0410, 0xACA1, 0x0411, 0xACA2, 0x0412, 0xACA3, 0x0413, 0xACA4, 0x0414, 0xACA5, 0x0415, 0xACA6, + 0x0416, 0xACA8, 0x0417, 0xACA9, 0x0418, 0xACAA, 0x0419, 0xACAB, 0x041A, 0xACAC, 0x041B, 0xACAD, 0x041C, 0xACAE, 0x041D, 0xACAF, + 0x041E, 0xACB0, 0x041F, 0xACB1, 0x0420, 0xACB2, 0x0421, 0xACB3, 0x0422, 0xACB4, 0x0423, 0xACB5, 0x0424, 0xACB6, 0x0425, 0xACB7, + 0x0426, 0xACB8, 0x0427, 0xACB9, 0x0428, 0xACBA, 0x0429, 0xACBB, 0x042A, 0xACBC, 0x042B, 0xACBD, 0x042C, 0xACBE, 0x042D, 0xACBF, + 0x042E, 0xACC0, 0x042F, 0xACC1, 0x0430, 0xACD1, 0x0431, 0xACD2, 0x0432, 0xACD3, 0x0433, 0xACD4, 0x0434, 0xACD5, 0x0435, 0xACD6, + 0x0436, 0xACD8, 0x0437, 0xACD9, 0x0438, 0xACDA, 0x0439, 0xACDB, 0x043A, 0xACDC, 0x043B, 0xACDD, 0x043C, 0xACDE, 0x043D, 0xACDF, + 0x043E, 0xACE0, 0x043F, 0xACE1, 0x0440, 0xACE2, 0x0441, 0xACE3, 0x0442, 0xACE4, 0x0443, 0xACE5, 0x0444, 0xACE6, 0x0445, 0xACE7, + 0x0446, 0xACE8, 0x0447, 0xACE9, 0x0448, 0xACEA, 0x0449, 0xACEB, 0x044A, 0xACEC, 0x044B, 0xACED, 0x044C, 0xACEE, 0x044D, 0xACEF, + 0x044E, 0xACF0, 0x044F, 0xACF1, 0x0451, 0xACD7, 0x2015, 0xA1AA, 0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1, + 0x2020, 0xA2D3, 0x2021, 0xA2D4, 0x2025, 0xA1A5, 0x2026, 0xA1A6, 0x2030, 0xA2B6, 0x2032, 0xA1C7, 0x2033, 0xA1C8, 0x203B, 0xA1D8, + 0x2074, 0xA9F9, 0x207F, 0xA9FA, 0x2081, 0xA9FB, 0x2082, 0xA9FC, 0x2083, 0xA9FD, 0x2084, 0xA9FE, 0x20AC, 0xA2E6, 0x2103, 0xA1C9, + 0x2109, 0xA2B5, 0x2113, 0xA7A4, 0x2116, 0xA2E0, 0x2121, 0xA2E5, 0x2122, 0xA2E2, 0x2126, 0xA7D9, 0x212B, 0xA1CA, 0x2153, 0xA8F7, + 0x2154, 0xA8F8, 0x215B, 0xA8FB, 0x215C, 0xA8FC, 0x215D, 0xA8FD, 0x215E, 0xA8FE, 0x2160, 0xA5B0, 0x2161, 0xA5B1, 0x2162, 0xA5B2, + 0x2163, 0xA5B3, 0x2164, 0xA5B4, 0x2165, 0xA5B5, 0x2166, 0xA5B6, 0x2167, 0xA5B7, 0x2168, 0xA5B8, 0x2169, 0xA5B9, 0x2170, 0xA5A1, + 0x2171, 0xA5A2, 0x2172, 0xA5A3, 0x2173, 0xA5A4, 0x2174, 0xA5A5, 0x2175, 0xA5A6, 0x2176, 0xA5A7, 0x2177, 0xA5A8, 0x2178, 0xA5A9, + 0x2179, 0xA5AA, 0x2190, 0xA1E7, 0x2191, 0xA1E8, 0x2192, 0xA1E6, 0x2193, 0xA1E9, 0x2194, 0xA1EA, 0x2195, 0xA2D5, 0x2196, 0xA2D8, + 0x2197, 0xA2D6, 0x2198, 0xA2D9, 0x2199, 0xA2D7, 0x21D2, 0xA2A1, 0x21D4, 0xA2A2, 0x2200, 0xA2A3, 0x2202, 0xA1D3, 0x2203, 0xA2A4, + 0x2207, 0xA1D4, 0x2208, 0xA1F4, 0x220B, 0xA1F5, 0x220F, 0xA2B3, 0x2211, 0xA2B2, 0x221A, 0xA1EE, 0x221D, 0xA1F0, 0x221E, 0xA1C4, + 0x2220, 0xA1D0, 0x2225, 0xA1AB, 0x2227, 0xA1FC, 0x2228, 0xA1FD, 0x2229, 0xA1FB, 0x222A, 0xA1FA, 0x222B, 0xA1F2, 0x222C, 0xA1F3, + 0x222E, 0xA2B1, 0x2234, 0xA1C5, 0x2235, 0xA1F1, 0x223C, 0xA1AD, 0x223D, 0xA1EF, 0x2252, 0xA1D6, 0x2260, 0xA1C1, 0x2261, 0xA1D5, + 0x2264, 0xA1C2, 0x2265, 0xA1C3, 0x226A, 0xA1EC, 0x226B, 0xA1ED, 0x2282, 0xA1F8, 0x2283, 0xA1F9, 0x2286, 0xA1F6, 0x2287, 0xA1F7, + 0x2299, 0xA2C1, 0x22A5, 0xA1D1, 0x2312, 0xA1D2, 0x2460, 0xA8E7, 0x2461, 0xA8E8, 0x2462, 0xA8E9, 0x2463, 0xA8EA, 0x2464, 0xA8EB, + 0x2465, 0xA8EC, 0x2466, 0xA8ED, 0x2467, 0xA8EE, 0x2468, 0xA8EF, 0x2469, 0xA8F0, 0x246A, 0xA8F1, 0x246B, 0xA8F2, 0x246C, 0xA8F3, + 0x246D, 0xA8F4, 0x246E, 0xA8F5, 0x2474, 0xA9E7, 0x2475, 0xA9E8, 0x2476, 0xA9E9, 0x2477, 0xA9EA, 0x2478, 0xA9EB, 0x2479, 0xA9EC, + 0x247A, 0xA9ED, 0x247B, 0xA9EE, 0x247C, 0xA9EF, 0x247D, 0xA9F0, 0x247E, 0xA9F1, 0x247F, 0xA9F2, 0x2480, 0xA9F3, 0x2481, 0xA9F4, + 0x2482, 0xA9F5, 0x249C, 0xA9CD, 0x249D, 0xA9CE, 0x249E, 0xA9CF, 0x249F, 0xA9D0, 0x24A0, 0xA9D1, 0x24A1, 0xA9D2, 0x24A2, 0xA9D3, + 0x24A3, 0xA9D4, 0x24A4, 0xA9D5, 0x24A5, 0xA9D6, 0x24A6, 0xA9D7, 0x24A7, 0xA9D8, 0x24A8, 0xA9D9, 0x24A9, 0xA9DA, 0x24AA, 0xA9DB, + 0x24AB, 0xA9DC, 0x24AC, 0xA9DD, 0x24AD, 0xA9DE, 0x24AE, 0xA9DF, 0x24AF, 0xA9E0, 0x24B0, 0xA9E1, 0x24B1, 0xA9E2, 0x24B2, 0xA9E3, + 0x24B3, 0xA9E4, 0x24B4, 0xA9E5, 0x24B5, 0xA9E6, 0x24D0, 0xA8CD, 0x24D1, 0xA8CE, 0x24D2, 0xA8CF, 0x24D3, 0xA8D0, 0x24D4, 0xA8D1, + 0x24D5, 0xA8D2, 0x24D6, 0xA8D3, 0x24D7, 0xA8D4, 0x24D8, 0xA8D5, 0x24D9, 0xA8D6, 0x24DA, 0xA8D7, 0x24DB, 0xA8D8, 0x24DC, 0xA8D9, + 0x24DD, 0xA8DA, 0x24DE, 0xA8DB, 0x24DF, 0xA8DC, 0x24E0, 0xA8DD, 0x24E1, 0xA8DE, 0x24E2, 0xA8DF, 0x24E3, 0xA8E0, 0x24E4, 0xA8E1, + 0x24E5, 0xA8E2, 0x24E6, 0xA8E3, 0x24E7, 0xA8E4, 0x24E8, 0xA8E5, 0x24E9, 0xA8E6, 0x2500, 0xA6A1, 0x2501, 0xA6AC, 0x2502, 0xA6A2, + 0x2503, 0xA6AD, 0x250C, 0xA6A3, 0x250D, 0xA6C8, 0x250E, 0xA6C7, 0x250F, 0xA6AE, 0x2510, 0xA6A4, 0x2511, 0xA6C2, 0x2512, 0xA6C1, + 0x2513, 0xA6AF, 0x2514, 0xA6A6, 0x2515, 0xA6C6, 0x2516, 0xA6C5, 0x2517, 0xA6B1, 0x2518, 0xA6A5, 0x2519, 0xA6C4, 0x251A, 0xA6C3, + 0x251B, 0xA6B0, 0x251C, 0xA6A7, 0x251D, 0xA6BC, 0x251E, 0xA6C9, 0x251F, 0xA6CA, 0x2520, 0xA6B7, 0x2521, 0xA6CB, 0x2522, 0xA6CC, + 0x2523, 0xA6B2, 0x2524, 0xA6A9, 0x2525, 0xA6BE, 0x2526, 0xA6CD, 0x2527, 0xA6CE, 0x2528, 0xA6B9, 0x2529, 0xA6CF, 0x252A, 0xA6D0, + 0x252B, 0xA6B4, 0x252C, 0xA6A8, 0x252D, 0xA6D1, 0x252E, 0xA6D2, 0x252F, 0xA6B8, 0x2530, 0xA6BD, 0x2531, 0xA6D3, 0x2532, 0xA6D4, + 0x2533, 0xA6B3, 0x2534, 0xA6AA, 0x2535, 0xA6D5, 0x2536, 0xA6D6, 0x2537, 0xA6BA, 0x2538, 0xA6BF, 0x2539, 0xA6D7, 0x253A, 0xA6D8, + 0x253B, 0xA6B5, 0x253C, 0xA6AB, 0x253D, 0xA6D9, 0x253E, 0xA6DA, 0x253F, 0xA6BB, 0x2540, 0xA6DB, 0x2541, 0xA6DC, 0x2542, 0xA6C0, + 0x2543, 0xA6DD, 0x2544, 0xA6DE, 0x2545, 0xA6DF, 0x2546, 0xA6E0, 0x2547, 0xA6E1, 0x2548, 0xA6E2, 0x2549, 0xA6E3, 0x254A, 0xA6E4, + 0x254B, 0xA6B6, 0x2592, 0xA2C6, 0x25A0, 0xA1E1, 0x25A1, 0xA1E0, 0x25A3, 0xA2C3, 0x25A4, 0xA2C7, 0x25A5, 0xA2C8, 0x25A6, 0xA2CB, + 0x25A7, 0xA2CA, 0x25A8, 0xA2C9, 0x25A9, 0xA2CC, 0x25B2, 0xA1E3, 0x25B3, 0xA1E2, 0x25B6, 0xA2BA, 0x25B7, 0xA2B9, 0x25BC, 0xA1E5, + 0x25BD, 0xA1E4, 0x25C0, 0xA2B8, 0x25C1, 0xA2B7, 0x25C6, 0xA1DF, 0x25C7, 0xA1DE, 0x25C8, 0xA2C2, 0x25CB, 0xA1DB, 0x25CE, 0xA1DD, + 0x25CF, 0xA1DC, 0x25D0, 0xA2C4, 0x25D1, 0xA2C5, 0x2605, 0xA1DA, 0x2606, 0xA1D9, 0x260E, 0xA2CF, 0x260F, 0xA2CE, 0x261C, 0xA2D0, + 0x261E, 0xA2D1, 0x2640, 0xA1CF, 0x2642, 0xA1CE, 0x2660, 0xA2BC, 0x2661, 0xA2BD, 0x2663, 0xA2C0, 0x2664, 0xA2BB, 0x2665, 0xA2BE, + 0x2667, 0xA2BF, 0x2668, 0xA2CD, 0x2669, 0xA2DB, 0x266A, 0xA2DC, 0x266C, 0xA2DD, 0x266D, 0xA2DA, 0x3000, 0xA1A1, 0x3001, 0xA1A2, + 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3008, 0xA1B4, 0x3009, 0xA1B5, 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, + 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BC, 0x3011, 0xA1BD, 0x3013, 0xA1EB, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3041, 0xAAA1, + 0x3042, 0xAAA2, 0x3043, 0xAAA3, 0x3044, 0xAAA4, 0x3045, 0xAAA5, 0x3046, 0xAAA6, 0x3047, 0xAAA7, 0x3048, 0xAAA8, 0x3049, 0xAAA9, + 0x304A, 0xAAAA, 0x304B, 0xAAAB, 0x304C, 0xAAAC, 0x304D, 0xAAAD, 0x304E, 0xAAAE, 0x304F, 0xAAAF, 0x3050, 0xAAB0, 0x3051, 0xAAB1, + 0x3052, 0xAAB2, 0x3053, 0xAAB3, 0x3054, 0xAAB4, 0x3055, 0xAAB5, 0x3056, 0xAAB6, 0x3057, 0xAAB7, 0x3058, 0xAAB8, 0x3059, 0xAAB9, + 0x305A, 0xAABA, 0x305B, 0xAABB, 0x305C, 0xAABC, 0x305D, 0xAABD, 0x305E, 0xAABE, 0x305F, 0xAABF, 0x3060, 0xAAC0, 0x3061, 0xAAC1, + 0x3062, 0xAAC2, 0x3063, 0xAAC3, 0x3064, 0xAAC4, 0x3065, 0xAAC5, 0x3066, 0xAAC6, 0x3067, 0xAAC7, 0x3068, 0xAAC8, 0x3069, 0xAAC9, + 0x306A, 0xAACA, 0x306B, 0xAACB, 0x306C, 0xAACC, 0x306D, 0xAACD, 0x306E, 0xAACE, 0x306F, 0xAACF, 0x3070, 0xAAD0, 0x3071, 0xAAD1, + 0x3072, 0xAAD2, 0x3073, 0xAAD3, 0x3074, 0xAAD4, 0x3075, 0xAAD5, 0x3076, 0xAAD6, 0x3077, 0xAAD7, 0x3078, 0xAAD8, 0x3079, 0xAAD9, + 0x307A, 0xAADA, 0x307B, 0xAADB, 0x307C, 0xAADC, 0x307D, 0xAADD, 0x307E, 0xAADE, 0x307F, 0xAADF, 0x3080, 0xAAE0, 0x3081, 0xAAE1, + 0x3082, 0xAAE2, 0x3083, 0xAAE3, 0x3084, 0xAAE4, 0x3085, 0xAAE5, 0x3086, 0xAAE6, 0x3087, 0xAAE7, 0x3088, 0xAAE8, 0x3089, 0xAAE9, + 0x308A, 0xAAEA, 0x308B, 0xAAEB, 0x308C, 0xAAEC, 0x308D, 0xAAED, 0x308E, 0xAAEE, 0x308F, 0xAAEF, 0x3090, 0xAAF0, 0x3091, 0xAAF1, + 0x3092, 0xAAF2, 0x3093, 0xAAF3, 0x30A1, 0xABA1, 0x30A2, 0xABA2, 0x30A3, 0xABA3, 0x30A4, 0xABA4, 0x30A5, 0xABA5, 0x30A6, 0xABA6, + 0x30A7, 0xABA7, 0x30A8, 0xABA8, 0x30A9, 0xABA9, 0x30AA, 0xABAA, 0x30AB, 0xABAB, 0x30AC, 0xABAC, 0x30AD, 0xABAD, 0x30AE, 0xABAE, + 0x30AF, 0xABAF, 0x30B0, 0xABB0, 0x30B1, 0xABB1, 0x30B2, 0xABB2, 0x30B3, 0xABB3, 0x30B4, 0xABB4, 0x30B5, 0xABB5, 0x30B6, 0xABB6, + 0x30B7, 0xABB7, 0x30B8, 0xABB8, 0x30B9, 0xABB9, 0x30BA, 0xABBA, 0x30BB, 0xABBB, 0x30BC, 0xABBC, 0x30BD, 0xABBD, 0x30BE, 0xABBE, + 0x30BF, 0xABBF, 0x30C0, 0xABC0, 0x30C1, 0xABC1, 0x30C2, 0xABC2, 0x30C3, 0xABC3, 0x30C4, 0xABC4, 0x30C5, 0xABC5, 0x30C6, 0xABC6, + 0x30C7, 0xABC7, 0x30C8, 0xABC8, 0x30C9, 0xABC9, 0x30CA, 0xABCA, 0x30CB, 0xABCB, 0x30CC, 0xABCC, 0x30CD, 0xABCD, 0x30CE, 0xABCE, + 0x30CF, 0xABCF, 0x30D0, 0xABD0, 0x30D1, 0xABD1, 0x30D2, 0xABD2, 0x30D3, 0xABD3, 0x30D4, 0xABD4, 0x30D5, 0xABD5, 0x30D6, 0xABD6, + 0x30D7, 0xABD7, 0x30D8, 0xABD8, 0x30D9, 0xABD9, 0x30DA, 0xABDA, 0x30DB, 0xABDB, 0x30DC, 0xABDC, 0x30DD, 0xABDD, 0x30DE, 0xABDE, + 0x30DF, 0xABDF, 0x30E0, 0xABE0, 0x30E1, 0xABE1, 0x30E2, 0xABE2, 0x30E3, 0xABE3, 0x30E4, 0xABE4, 0x30E5, 0xABE5, 0x30E6, 0xABE6, + 0x30E7, 0xABE7, 0x30E8, 0xABE8, 0x30E9, 0xABE9, 0x30EA, 0xABEA, 0x30EB, 0xABEB, 0x30EC, 0xABEC, 0x30ED, 0xABED, 0x30EE, 0xABEE, + 0x30EF, 0xABEF, 0x30F0, 0xABF0, 0x30F1, 0xABF1, 0x30F2, 0xABF2, 0x30F3, 0xABF3, 0x30F4, 0xABF4, 0x30F5, 0xABF5, 0x30F6, 0xABF6, + 0x3131, 0xA4A1, 0x3132, 0xA4A2, 0x3133, 0xA4A3, 0x3134, 0xA4A4, 0x3135, 0xA4A5, 0x3136, 0xA4A6, 0x3137, 0xA4A7, 0x3138, 0xA4A8, + 0x3139, 0xA4A9, 0x313A, 0xA4AA, 0x313B, 0xA4AB, 0x313C, 0xA4AC, 0x313D, 0xA4AD, 0x313E, 0xA4AE, 0x313F, 0xA4AF, 0x3140, 0xA4B0, + 0x3141, 0xA4B1, 0x3142, 0xA4B2, 0x3143, 0xA4B3, 0x3144, 0xA4B4, 0x3145, 0xA4B5, 0x3146, 0xA4B6, 0x3147, 0xA4B7, 0x3148, 0xA4B8, + 0x3149, 0xA4B9, 0x314A, 0xA4BA, 0x314B, 0xA4BB, 0x314C, 0xA4BC, 0x314D, 0xA4BD, 0x314E, 0xA4BE, 0x314F, 0xA4BF, 0x3150, 0xA4C0, + 0x3151, 0xA4C1, 0x3152, 0xA4C2, 0x3153, 0xA4C3, 0x3154, 0xA4C4, 0x3155, 0xA4C5, 0x3156, 0xA4C6, 0x3157, 0xA4C7, 0x3158, 0xA4C8, + 0x3159, 0xA4C9, 0x315A, 0xA4CA, 0x315B, 0xA4CB, 0x315C, 0xA4CC, 0x315D, 0xA4CD, 0x315E, 0xA4CE, 0x315F, 0xA4CF, 0x3160, 0xA4D0, + 0x3161, 0xA4D1, 0x3162, 0xA4D2, 0x3163, 0xA4D3, 0x3164, 0xA4D4, 0x3165, 0xA4D5, 0x3166, 0xA4D6, 0x3167, 0xA4D7, 0x3168, 0xA4D8, + 0x3169, 0xA4D9, 0x316A, 0xA4DA, 0x316B, 0xA4DB, 0x316C, 0xA4DC, 0x316D, 0xA4DD, 0x316E, 0xA4DE, 0x316F, 0xA4DF, 0x3170, 0xA4E0, + 0x3171, 0xA4E1, 0x3172, 0xA4E2, 0x3173, 0xA4E3, 0x3174, 0xA4E4, 0x3175, 0xA4E5, 0x3176, 0xA4E6, 0x3177, 0xA4E7, 0x3178, 0xA4E8, + 0x3179, 0xA4E9, 0x317A, 0xA4EA, 0x317B, 0xA4EB, 0x317C, 0xA4EC, 0x317D, 0xA4ED, 0x317E, 0xA4EE, 0x317F, 0xA4EF, 0x3180, 0xA4F0, + 0x3181, 0xA4F1, 0x3182, 0xA4F2, 0x3183, 0xA4F3, 0x3184, 0xA4F4, 0x3185, 0xA4F5, 0x3186, 0xA4F6, 0x3187, 0xA4F7, 0x3188, 0xA4F8, + 0x3189, 0xA4F9, 0x318A, 0xA4FA, 0x318B, 0xA4FB, 0x318C, 0xA4FC, 0x318D, 0xA4FD, 0x318E, 0xA4FE, 0x3200, 0xA9B1, 0x3201, 0xA9B2, + 0x3202, 0xA9B3, 0x3203, 0xA9B4, 0x3204, 0xA9B5, 0x3205, 0xA9B6, 0x3206, 0xA9B7, 0x3207, 0xA9B8, 0x3208, 0xA9B9, 0x3209, 0xA9BA, + 0x320A, 0xA9BB, 0x320B, 0xA9BC, 0x320C, 0xA9BD, 0x320D, 0xA9BE, 0x320E, 0xA9BF, 0x320F, 0xA9C0, 0x3210, 0xA9C1, 0x3211, 0xA9C2, + 0x3212, 0xA9C3, 0x3213, 0xA9C4, 0x3214, 0xA9C5, 0x3215, 0xA9C6, 0x3216, 0xA9C7, 0x3217, 0xA9C8, 0x3218, 0xA9C9, 0x3219, 0xA9CA, + 0x321A, 0xA9CB, 0x321B, 0xA9CC, 0x321C, 0xA2DF, 0x3260, 0xA8B1, 0x3261, 0xA8B2, 0x3262, 0xA8B3, 0x3263, 0xA8B4, 0x3264, 0xA8B5, + 0x3265, 0xA8B6, 0x3266, 0xA8B7, 0x3267, 0xA8B8, 0x3268, 0xA8B9, 0x3269, 0xA8BA, 0x326A, 0xA8BB, 0x326B, 0xA8BC, 0x326C, 0xA8BD, + 0x326D, 0xA8BE, 0x326E, 0xA8BF, 0x326F, 0xA8C0, 0x3270, 0xA8C1, 0x3271, 0xA8C2, 0x3272, 0xA8C3, 0x3273, 0xA8C4, 0x3274, 0xA8C5, + 0x3275, 0xA8C6, 0x3276, 0xA8C7, 0x3277, 0xA8C8, 0x3278, 0xA8C9, 0x3279, 0xA8CA, 0x327A, 0xA8CB, 0x327B, 0xA8CC, 0x327F, 0xA2DE, + 0x3380, 0xA7C9, 0x3381, 0xA7CA, 0x3382, 0xA7CB, 0x3383, 0xA7CC, 0x3384, 0xA7CD, 0x3388, 0xA7BA, 0x3389, 0xA7BB, 0x338A, 0xA7DC, + 0x338B, 0xA7DD, 0x338C, 0xA7DE, 0x338D, 0xA7B6, 0x338E, 0xA7B7, 0x338F, 0xA7B8, 0x3390, 0xA7D4, 0x3391, 0xA7D5, 0x3392, 0xA7D6, + 0x3393, 0xA7D7, 0x3394, 0xA7D8, 0x3395, 0xA7A1, 0x3396, 0xA7A2, 0x3397, 0xA7A3, 0x3398, 0xA7A5, 0x3399, 0xA7AB, 0x339A, 0xA7AC, + 0x339B, 0xA7AD, 0x339C, 0xA7AE, 0x339D, 0xA7AF, 0x339E, 0xA7B0, 0x339F, 0xA7B1, 0x33A0, 0xA7B2, 0x33A1, 0xA7B3, 0x33A2, 0xA7B4, + 0x33A3, 0xA7A7, 0x33A4, 0xA7A8, 0x33A5, 0xA7A9, 0x33A6, 0xA7AA, 0x33A7, 0xA7BD, 0x33A8, 0xA7BE, 0x33A9, 0xA7E5, 0x33AA, 0xA7E6, + 0x33AB, 0xA7E7, 0x33AC, 0xA7E8, 0x33AD, 0xA7E1, 0x33AE, 0xA7E2, 0x33AF, 0xA7E3, 0x33B0, 0xA7BF, 0x33B1, 0xA7C0, 0x33B2, 0xA7C1, + 0x33B3, 0xA7C2, 0x33B4, 0xA7C3, 0x33B5, 0xA7C4, 0x33B6, 0xA7C5, 0x33B7, 0xA7C6, 0x33B8, 0xA7C7, 0x33B9, 0xA7C8, 0x33BA, 0xA7CE, + 0x33BB, 0xA7CF, 0x33BC, 0xA7D0, 0x33BD, 0xA7D1, 0x33BE, 0xA7D2, 0x33BF, 0xA7D3, 0x33C0, 0xA7DA, 0x33C1, 0xA7DB, 0x33C2, 0xA2E3, + 0x33C3, 0xA7EC, 0x33C4, 0xA7A6, 0x33C5, 0xA7E0, 0x33C6, 0xA7EF, 0x33C7, 0xA2E1, 0x33C8, 0xA7BC, 0x33C9, 0xA7ED, 0x33CA, 0xA7B5, + 0x33CF, 0xA7B9, 0x33D0, 0xA7EA, 0x33D3, 0xA7EB, 0x33D6, 0xA7DF, 0x33D8, 0xA2E4, 0x33DB, 0xA7E4, 0x33DC, 0xA7EE, 0x33DD, 0xA7E9, + 0x4E00, 0xECE9, 0x4E01, 0xEFCB, 0x4E03, 0xF6D2, 0x4E07, 0xD8B2, 0x4E08, 0xEDDB, 0x4E09, 0xDFB2, 0x4E0A, 0xDFBE, 0x4E0B, 0xF9BB, + 0x4E0D, 0xDCF4, 0x4E11, 0xF5E4, 0x4E14, 0xF3A6, 0x4E15, 0xDDE0, 0x4E16, 0xE1A6, 0x4E18, 0xCEF8, 0x4E19, 0xDCB0, 0x4E1E, 0xE3AA, + 0x4E2D, 0xF1E9, 0x4E32, 0xCDFA, 0x4E38, 0xFCAF, 0x4E39, 0xD3A1, 0x4E3B, 0xF1AB, 0x4E42, 0xE7D1, 0x4E43, 0xD2AC, 0x4E45, 0xCEF9, + 0x4E4B, 0xF1FD, 0x4E4D, 0xDEBF, 0x4E4E, 0xFBBA, 0x4E4F, 0xF9B9, 0x4E56, 0xCED2, 0x4E58, 0xE3AB, 0x4E59, 0xEBE0, 0x4E5D, 0xCEFA, + 0x4E5E, 0xCBF7, 0x4E5F, 0xE5A5, 0x4E6B, 0xCAE1, 0x4E6D, 0xD4CC, 0x4E73, 0xEAE1, 0x4E76, 0xDCE3, 0x4E77, 0xDFAD, 0x4E7E, 0xCBEB, + 0x4E82, 0xD5AF, 0x4E86, 0xD6F5, 0x4E88, 0xE5F8, 0x4E8B, 0xDEC0, 0x4E8C, 0xECA3, 0x4E8E, 0xE9CD, 0x4E90, 0xEAA7, 0x4E91, 0xE9F6, + 0x4E92, 0xFBBB, 0x4E94, 0xE7E9, 0x4E95, 0xEFCC, 0x4E98, 0xD0E6, 0x4E9B, 0xDEC1, 0x4E9E, 0xE4AC, 0x4EA1, 0xD8CC, 0x4EA2, 0xF9F1, + 0x4EA4, 0xCEDF, 0x4EA5, 0xFAA4, 0x4EA6, 0xE6B2, 0x4EA8, 0xFAFB, 0x4EAB, 0xFABD, 0x4EAC, 0xCCC8, 0x4EAD, 0xEFCD, 0x4EAE, 0xD5D5, + 0x4EB6, 0xD3A2, 0x4EBA, 0xECD1, 0x4EC0, 0xE4A7, 0x4EC1, 0xECD2, 0x4EC4, 0xF6B1, 0x4EC7, 0xCEFB, 0x4ECA, 0xD0D1, 0x4ECB, 0xCBBF, + 0x4ECD, 0xEDA4, 0x4ED4, 0xEDA8, 0x4ED5, 0xDEC2, 0x4ED6, 0xF6E2, 0x4ED7, 0xEDDC, 0x4ED8, 0xDCF5, 0x4ED9, 0xE0B9, 0x4EDD, 0xD4CE, + 0x4EDF, 0xF4B5, 0x4EE3, 0xD3DB, 0x4EE4, 0xD6B5, 0x4EE5, 0xECA4, 0x4EF0, 0xE4E6, 0x4EF2, 0xF1EA, 0x4EF6, 0xCBEC, 0x4EF7, 0xCBC0, + 0x4EFB, 0xECF2, 0x4F01, 0xD0EA, 0x4F09, 0xF9F2, 0x4F0A, 0xECA5, 0x4F0B, 0xD0DF, 0x4F0D, 0xE7EA, 0x4F0E, 0xD0EB, 0x4F0F, 0xDCD1, + 0x4F10, 0xDBE9, 0x4F11, 0xFDCC, 0x4F2F, 0xDBD7, 0x4F34, 0xDAE1, 0x4F36, 0xD6B6, 0x4F38, 0xE3DF, 0x4F3A, 0xDEC3, 0x4F3C, 0xDEC4, + 0x4F3D, 0xCAA1, 0x4F43, 0xEEEC, 0x4F46, 0xD3A3, 0x4F47, 0xEEB7, 0x4F48, 0xF8CF, 0x4F4D, 0xEAC8, 0x4F4E, 0xEEB8, 0x4F4F, 0xF1AC, + 0x4F50, 0xF1A5, 0x4F51, 0xE9CE, 0x4F55, 0xF9BC, 0x4F59, 0xE5F9, 0x4F5A, 0xECEA, 0x4F5B, 0xDDD6, 0x4F5C, 0xEDC2, 0x4F69, 0xF8A5, + 0x4F6F, 0xE5BA, 0x4F70, 0xDBD8, 0x4F73, 0xCAA2, 0x4F76, 0xD1CD, 0x4F7A, 0xEEED, 0x4F7E, 0xECEB, 0x4F7F, 0xDEC5, 0x4F81, 0xE3E0, + 0x4F83, 0xCAC9, 0x4F84, 0xF2E9, 0x4F86, 0xD5CE, 0x4F88, 0xF6B6, 0x4F8A, 0xCEC2, 0x4F8B, 0xD6C7, 0x4F8D, 0xE3B4, 0x4F8F, 0xF1AD, + 0x4F91, 0xEAE2, 0x4F96, 0xD7C2, 0x4F98, 0xF3A7, 0x4F9B, 0xCDEA, 0x4F9D, 0xEBEE, 0x4FAE, 0xD9B2, 0x4FAF, 0xFDA5, 0x4FB5, 0xF6D5, + 0x4FB6, 0xD5E2, 0x4FBF, 0xF8B5, 0x4FC2, 0xCCF5, 0x4FC3, 0xF5B5, 0x4FC4, 0xE4AD, 0x4FC9, 0xE7EB, 0x4FCA, 0xF1D5, 0x4FCE, 0xF0BB, + 0x4FD1, 0xE9B5, 0x4FD3, 0xCCC9, 0x4FD4, 0xFAD5, 0x4FD7, 0xE1D4, 0x4FDA, 0xD7D6, 0x4FDD, 0xDCC1, 0x4FDF, 0xDEC6, 0x4FE0, 0xFAEF, + 0x4FE1, 0xE3E1, 0x4FEE, 0xE1F3, 0x4FEF, 0xDCF6, 0x4FF1, 0xCEFC, 0x4FF3, 0xDBC4, 0x4FF5, 0xF8F1, 0x4FF8, 0xDCE4, 0x4FFA, 0xE5EF, + 0x5002, 0xDCB1, 0x5006, 0xD5D6, 0x5009, 0xF3DA, 0x500B, 0xCBC1, 0x500D, 0xDBC3, 0x5011, 0xD9FA, 0x5012, 0xD3EE, 0x5016, 0xFAB8, + 0x5019, 0xFDA6, 0x501A, 0xEBEF, 0x501C, 0xF4A6, 0x501E, 0xCCCA, 0x501F, 0xF3A8, 0x5021, 0xF3DB, 0x5023, 0xDBA7, 0x5024, 0xF6B7, + 0x5026, 0xCFE6, 0x5027, 0xF0F2, 0x5028, 0xCBDA, 0x502A, 0xE7D2, 0x502B, 0xD7C3, 0x502C, 0xF6F0, 0x502D, 0xE8DE, 0x503B, 0xE5A6, + 0x5043, 0xE5E7, 0x5047, 0xCAA3, 0x5048, 0xCCA7, 0x5049, 0xEAC9, 0x504F, 0xF8B6, 0x5055, 0xFAA5, 0x505A, 0xF1AE, 0x505C, 0xEFCE, + 0x5065, 0xCBED, 0x5074, 0xF6B0, 0x5075, 0xEFCF, 0x5076, 0xE9CF, 0x5078, 0xF7DE, 0x5080, 0xCED3, 0x5085, 0xDCF7, 0x508D, 0xDBA8, + 0x5091, 0xCBF8, 0x5098, 0xDFA1, 0x5099, 0xDDE1, 0x50AC, 0xF5CA, 0x50AD, 0xE9B6, 0x50B2, 0xE7EC, 0x50B3, 0xEEEE, 0x50B5, 0xF3F0, + 0x50B7, 0xDFBF, 0x50BE, 0xCCCB, 0x50C5, 0xD0C1, 0x50C9, 0xF4D2, 0x50CA, 0xE0BA, 0x50CF, 0xDFC0, 0x50D1, 0xCEE0, 0x50D5, 0xDCD2, + 0x50D6, 0xFDEA, 0x50DA, 0xD6F6, 0x50DE, 0xEACA, 0x50E5, 0xE8E9, 0x50E7, 0xE3AC, 0x50ED, 0xF3D0, 0x50F9, 0xCAA4, 0x50FB, 0xDBF8, + 0x50FF, 0xDEC7, 0x5100, 0xEBF0, 0x5101, 0xF1D6, 0x5104, 0xE5E2, 0x5106, 0xCCCC, 0x5109, 0xCBFB, 0x5112, 0xEAE3, 0x511F, 0xDFC1, + 0x5121, 0xD6ED, 0x512A, 0xE9D0, 0x5132, 0xEEB9, 0x5137, 0xD5E3, 0x513A, 0xD1D3, 0x513C, 0xE5F0, 0x5140, 0xE8B4, 0x5141, 0xEBC3, + 0x5143, 0xEAAA, 0x5144, 0xFAFC, 0x5145, 0xF5F6, 0x5146, 0xF0BC, 0x5147, 0xFDD4, 0x5148, 0xE0BB, 0x5149, 0xCEC3, 0x514B, 0xD0BA, + 0x514C, 0xF7BA, 0x514D, 0xD8F3, 0x514E, 0xF7CD, 0x5152, 0xE4AE, 0x515C, 0xD4DF, 0x5162, 0xD0E7, 0x5165, 0xECFD, 0x5167, 0xD2AE, + 0x5168, 0xEEEF, 0x5169, 0xD5D7, 0x516A, 0xEAE4, 0x516B, 0xF8A2, 0x516C, 0xCDEB, 0x516D, 0xD7BF, 0x516E, 0xFBB1, 0x5171, 0xCDEC, + 0x5175, 0xDCB2, 0x5176, 0xD0EC, 0x5177, 0xCEFD, 0x5178, 0xEEF0, 0x517C, 0xCCC2, 0x5180, 0xD0ED, 0x5186, 0xE5F7, 0x518A, 0xF3FC, + 0x518D, 0xEEA2, 0x5192, 0xD9B3, 0x5195, 0xD8F4, 0x5197, 0xE9B7, 0x51A0, 0xCEAE, 0x51A5, 0xD9A2, 0x51AA, 0xD8F1, 0x51AC, 0xD4CF, + 0x51B6, 0xE5A7, 0x51B7, 0xD5D2, 0x51BD, 0xD6A9, 0x51C4, 0xF4A2, 0x51C6, 0xF1D7, 0x51C9, 0xD5D8, 0x51CB, 0xF0BD, 0x51CC, 0xD7D0, + 0x51CD, 0xD4D0, 0x51DC, 0xD7CF, 0x51DD, 0xEBEA, 0x51DE, 0xFDEB, 0x51E1, 0xDBED, 0x51F0, 0xFCC5, 0x51F1, 0xCBC2, 0x51F6, 0xFDD5, + 0x51F8, 0xF4C8, 0x51F9, 0xE8EA, 0x51FA, 0xF5F3, 0x51FD, 0xF9DE, 0x5200, 0xD3EF, 0x5203, 0xECD3, 0x5206, 0xDDC2, 0x5207, 0xEFB7, + 0x5208, 0xE7D4, 0x520A, 0xCACA, 0x520E, 0xD9FB, 0x5211, 0xFAFD, 0x5217, 0xD6AA, 0x521D, 0xF4F8, 0x5224, 0xF7F7, 0x5225, 0xDCAC, + 0x5229, 0xD7D7, 0x522A, 0xDFA2, 0x522E, 0xCEBE, 0x5230, 0xD3F0, 0x5236, 0xF0A4, 0x5237, 0xE1EC, 0x5238, 0xCFE7, 0x5239, 0xF3CB, + 0x523A, 0xEDA9, 0x523B, 0xCABE, 0x5243, 0xF4EF, 0x5247, 0xF6CE, 0x524A, 0xDEFB, 0x524B, 0xD0BB, 0x524C, 0xD5B7, 0x524D, 0xEEF1, + 0x5254, 0xF4A8, 0x5256, 0xDCF8, 0x525B, 0xCBA7, 0x525D, 0xDACE, 0x5261, 0xE0E6, 0x5269, 0xEDA5, 0x526A, 0xEEF2, 0x526F, 0xDCF9, + 0x5272, 0xF9DC, 0x5275, 0xF3DC, 0x527D, 0xF8F2, 0x527F, 0xF4F9, 0x5283, 0xFCF1, 0x5287, 0xD0BC, 0x5288, 0xDBF9, 0x5289, 0xD7B1, + 0x528D, 0xCBFC, 0x5291, 0xF0A5, 0x5292, 0xCBFD, 0x529B, 0xD5F4, 0x529F, 0xCDED, 0x52A0, 0xCAA5, 0x52A3, 0xD6AB, 0x52A4, 0xD0C2, + 0x52A9, 0xF0BE, 0x52AA, 0xD2BD, 0x52AB, 0xCCA4, 0x52BE, 0xFAB6, 0x52C1, 0xCCCD, 0x52C3, 0xDAFA, 0x52C5, 0xF6CF, 0x52C7, 0xE9B8, + 0x52C9, 0xD8F5, 0x52CD, 0xCCCE, 0x52D2, 0xD7CD, 0x52D5, 0xD4D1, 0x52D6, 0xE9ED, 0x52D8, 0xCAEB, 0x52D9, 0xD9E2, 0x52DB, 0xFDB2, + 0x52DD, 0xE3AD, 0x52DE, 0xD6CC, 0x52DF, 0xD9B4, 0x52E2, 0xE1A7, 0x52E3, 0xEED3, 0x52E4, 0xD0C3, 0x52F3, 0xFDB3, 0x52F5, 0xD5E4, + 0x52F8, 0xCFE8, 0x52FA, 0xEDC3, 0x52FB, 0xD0B2, 0x52FE, 0xCEFE, 0x52FF, 0xDAA8, 0x5305, 0xF8D0, 0x5308, 0xFDD6, 0x530D, 0xF8D1, + 0x530F, 0xF8D2, 0x5310, 0xDCD3, 0x5315, 0xDDE2, 0x5316, 0xFBF9, 0x5317, 0xDDC1, 0x5319, 0xE3B5, 0x5320, 0xEDDD, 0x5321, 0xCEC4, + 0x5323, 0xCBA1, 0x532A, 0xDDE3, 0x532F, 0xFCDD, 0x5339, 0xF9AF, 0x533F, 0xD2FB, 0x5340, 0xCFA1, 0x5341, 0xE4A8, 0x5343, 0xF4B6, + 0x5344, 0xECFE, 0x5347, 0xE3AE, 0x5348, 0xE7ED, 0x5349, 0xFDC1, 0x534A, 0xDAE2, 0x534D, 0xD8B3, 0x5351, 0xDDE4, 0x5352, 0xF0EF, + 0x5353, 0xF6F1, 0x5354, 0xFAF0, 0x5357, 0xD1F5, 0x535A, 0xDACF, 0x535C, 0xDCD4, 0x535E, 0xDCA6, 0x5360, 0xEFBF, 0x5366, 0xCECF, + 0x5368, 0xE0D9, 0x536F, 0xD9D6, 0x5370, 0xECD4, 0x5371, 0xEACB, 0x5374, 0xCABF, 0x5375, 0xD5B0, 0x5377, 0xCFE9, 0x537D, 0xF1ED, + 0x537F, 0xCCCF, 0x5384, 0xE4F8, 0x5393, 0xE4ED, 0x5398, 0xD7D8, 0x539A, 0xFDA7, 0x539F, 0xEAAB, 0x53A0, 0xF6B2, 0x53A5, 0xCFF0, + 0x53A6, 0xF9BD, 0x53AD, 0xE6F4, 0x53BB, 0xCBDB, 0x53C3, 0xF3D1, 0x53C8, 0xE9D1, 0x53C9, 0xF3A9, 0x53CA, 0xD0E0, 0x53CB, 0xE9D2, + 0x53CD, 0xDAE3, 0x53D4, 0xE2D2, 0x53D6, 0xF6A2, 0x53D7, 0xE1F4, 0x53DB, 0xDAE4, 0x53E1, 0xE7D5, 0x53E2, 0xF5BF, 0x53E3, 0xCFA2, + 0x53E4, 0xCDAF, 0x53E5, 0xCFA3, 0x53E9, 0xCDB0, 0x53EA, 0xF1FE, 0x53EB, 0xD0A3, 0x53EC, 0xE1AF, 0x53ED, 0xF8A3, 0x53EF, 0xCAA6, + 0x53F0, 0xF7BB, 0x53F1, 0xF2EA, 0x53F2, 0xDEC8, 0x53F3, 0xE9D3, 0x53F8, 0xDEC9, 0x5403, 0xFDDE, 0x5404, 0xCAC0, 0x5408, 0xF9EA, + 0x5409, 0xD1CE, 0x540A, 0xEED4, 0x540C, 0xD4D2, 0x540D, 0xD9A3, 0x540E, 0xFDA8, 0x540F, 0xD7D9, 0x5410, 0xF7CE, 0x5411, 0xFABE, + 0x541B, 0xCFD6, 0x541D, 0xD7F0, 0x541F, 0xEBE1, 0x5420, 0xF8C5, 0x5426, 0xDCFA, 0x5429, 0xDDC3, 0x542B, 0xF9DF, 0x5433, 0xE7EF, + 0x5438, 0xFDE5, 0x5439, 0xF6A3, 0x543B, 0xD9FC, 0x543C, 0xFDA9, 0x543E, 0xE7EE, 0x5442, 0xD5E5, 0x5448, 0xEFD0, 0x544A, 0xCDB1, + 0x5451, 0xF7A2, 0x5468, 0xF1B2, 0x546A, 0xF1B1, 0x5471, 0xCDB2, 0x5473, 0xDAAB, 0x5475, 0xCAA7, 0x547B, 0xE3E2, 0x547C, 0xFBBC, + 0x547D, 0xD9A4, 0x5480, 0xEEBA, 0x5486, 0xF8D3, 0x548C, 0xFBFA, 0x548E, 0xCFA4, 0x5490, 0xDCFB, 0x54A4, 0xF6E3, 0x54A8, 0xEDAA, + 0x54AB, 0xF2A1, 0x54AC, 0xCEE1, 0x54B3, 0xFAA6, 0x54B8, 0xF9E0, 0x54BD, 0xECD6, 0x54C0, 0xE4EE, 0x54C1, 0xF9A1, 0x54C4, 0xFBEF, + 0x54C8, 0xF9EB, 0x54C9, 0xEEA3, 0x54E1, 0xEAAC, 0x54E5, 0xCAA8, 0x54E8, 0xF4FA, 0x54ED, 0xCDD6, 0x54EE, 0xFCF6, 0x54F2, 0xF4C9, + 0x54FA, 0xF8D4, 0x5504, 0xF8A6, 0x5506, 0xDECA, 0x5507, 0xF2C6, 0x550E, 0xD7DA, 0x5510, 0xD3D0, 0x551C, 0xD8C5, 0x552F, 0xEAE6, + 0x5531, 0xF3DD, 0x5535, 0xE4DA, 0x553E, 0xF6E4, 0x5544, 0xF6F2, 0x5546, 0xDFC2, 0x554F, 0xD9FD, 0x5553, 0xCCF6, 0x5556, 0xD3BA, + 0x555E, 0xE4AF, 0x5563, 0xF9E1, 0x557C, 0xF0A6, 0x5580, 0xCBD3, 0x5584, 0xE0BC, 0x5586, 0xF4CA, 0x5587, 0xD4FA, 0x5589, 0xFDAA, + 0x558A, 0xF9E2, 0x5598, 0xF4B7, 0x5599, 0xFDC2, 0x559A, 0xFCB0, 0x559C, 0xFDEC, 0x559D, 0xCAE2, 0x55A7, 0xFDBD, 0x55A9, 0xEAE7, + 0x55AA, 0xDFC3, 0x55AB, 0xD1D2, 0x55AC, 0xCEE2, 0x55AE, 0xD3A4, 0x55C5, 0xFDAB, 0x55C7, 0xDFE0, 0x55D4, 0xF2C7, 0x55DA, 0xE7F0, + 0x55DC, 0xD0EE, 0x55DF, 0xF3AA, 0x55E3, 0xDECB, 0x55E4, 0xF6B8, 0x55FD, 0xE1F5, 0x55FE, 0xF1B3, 0x5606, 0xF7A3, 0x5609, 0xCAA9, + 0x5614, 0xCFA5, 0x5617, 0xDFC4, 0x562F, 0xE1B0, 0x5632, 0xF0BF, 0x5634, 0xF6A4, 0x5636, 0xE3B6, 0x5653, 0xFAC6, 0x5668, 0xD0EF, + 0x566B, 0xFDED, 0x5674, 0xDDC4, 0x5686, 0xFCF7, 0x56A5, 0xE6BF, 0x56AC, 0xDEAD, 0x56AE, 0xFABF, 0x56B4, 0xE5F1, 0x56BC, 0xEDC4, + 0x56CA, 0xD2A5, 0x56CD, 0xFDEE, 0x56D1, 0xF5B6, 0x56DA, 0xE1F6, 0x56DB, 0xDECC, 0x56DE, 0xFCDE, 0x56E0, 0xECD7, 0x56F0, 0xCDDD, + 0x56F9, 0xD6B7, 0x56FA, 0xCDB3, 0x5703, 0xF8D5, 0x5704, 0xE5D8, 0x5708, 0xCFEA, 0x570B, 0xCFD0, 0x570D, 0xEACC, 0x5712, 0xEAAE, + 0x5713, 0xEAAD, 0x5716, 0xD3F1, 0x5718, 0xD3A5, 0x571F, 0xF7CF, 0x5728, 0xEEA4, 0x572D, 0xD0A4, 0x5730, 0xF2A2, 0x573B, 0xD0F0, + 0x5740, 0xF2A3, 0x5742, 0xF7F8, 0x5747, 0xD0B3, 0x574A, 0xDBA9, 0x574D, 0xD3BB, 0x574E, 0xCAEC, 0x5750, 0xF1A6, 0x5751, 0xCBD5, + 0x5761, 0xF7E7, 0x5764, 0xCDDE, 0x5766, 0xF7A4, 0x576A, 0xF8C0, 0x576E, 0xD3DD, 0x5770, 0xCCD0, 0x5775, 0xCFA6, 0x577C, 0xF6F3, + 0x5782, 0xE1F7, 0x5788, 0xD3DC, 0x578B, 0xFAFE, 0x5793, 0xFAA7, 0x57A0, 0xEBD9, 0x57A2, 0xCFA7, 0x57A3, 0xEAAF, 0x57C3, 0xE4EF, + 0x57C7, 0xE9B9, 0x57C8, 0xF1D8, 0x57CB, 0xD8D8, 0x57CE, 0xE0F2, 0x57DF, 0xE6B4, 0x57E0, 0xDCFC, 0x57F0, 0xF3F1, 0x57F4, 0xE3D0, + 0x57F7, 0xF2FB, 0x57F9, 0xDBC6, 0x57FA, 0xD0F1, 0x57FC, 0xD0F2, 0x5800, 0xCFDC, 0x5802, 0xD3D1, 0x5805, 0xCCB1, 0x5806, 0xF7D8, + 0x5808, 0xCBA8, 0x5809, 0xEBBC, 0x580A, 0xE4BE, 0x581E, 0xF4DC, 0x5821, 0xDCC2, 0x5824, 0xF0A7, 0x5827, 0xE6C0, 0x582A, 0xCAED, + 0x582F, 0xE8EB, 0x5830, 0xE5E8, 0x5831, 0xDCC3, 0x5834, 0xEDDE, 0x5835, 0xD3F2, 0x583A, 0xCCF7, 0x584A, 0xCED4, 0x584B, 0xE7AB, + 0x584F, 0xCBC3, 0x5851, 0xE1B1, 0x5854, 0xF7B2, 0x5857, 0xD3F3, 0x5858, 0xD3D2, 0x585A, 0xF5C0, 0x585E, 0xDFDD, 0x5861, 0xEEF3, + 0x5862, 0xE7F1, 0x5864, 0xFDB4, 0x5875, 0xF2C8, 0x5879, 0xF3D2, 0x587C, 0xEEF4, 0x587E, 0xE2D3, 0x5883, 0xCCD1, 0x5885, 0xDFEA, + 0x5889, 0xE9BA, 0x5893, 0xD9D7, 0x589C, 0xF5CD, 0x589E, 0xF1F2, 0x589F, 0xFAC7, 0x58A8, 0xD9F8, 0x58A9, 0xD4C2, 0x58AE, 0xF6E5, + 0x58B3, 0xDDC5, 0x58BA, 0xE7F2, 0x58BB, 0xEDDF, 0x58BE, 0xCACB, 0x58C1, 0xDBFA, 0x58C5, 0xE8B5, 0x58C7, 0xD3A6, 0x58CE, 0xFDB5, + 0x58D1, 0xF9C9, 0x58D3, 0xE4E2, 0x58D5, 0xFBBD, 0x58D8, 0xD7A4, 0x58D9, 0xCEC5, 0x58DE, 0xCED5, 0x58DF, 0xD6E6, 0x58E4, 0xE5BD, + 0x58EB, 0xDECD, 0x58EC, 0xECF3, 0x58EF, 0xEDE0, 0x58F9, 0xECEC, 0x58FA, 0xFBBE, 0x58FB, 0xDFEB, 0x58FD, 0xE1F8, 0x590F, 0xF9BE, + 0x5914, 0xD0F3, 0x5915, 0xE0AA, 0x5916, 0xE8E2, 0x5919, 0xE2D4, 0x591A, 0xD2FD, 0x591C, 0xE5A8, 0x5922, 0xD9D3, 0x5927, 0xD3DE, + 0x5929, 0xF4B8, 0x592A, 0xF7BC, 0x592B, 0xDCFD, 0x592D, 0xE8EC, 0x592E, 0xE4E7, 0x5931, 0xE3F7, 0x5937, 0xECA8, 0x593E, 0xFAF1, + 0x5944, 0xE5F2, 0x5947, 0xD0F4, 0x5948, 0xD2AF, 0x5949, 0xDCE5, 0x594E, 0xD0A5, 0x594F, 0xF1B4, 0x5950, 0xFCB1, 0x5951, 0xCCF8, + 0x5954, 0xDDC6, 0x5955, 0xFAD1, 0x5957, 0xF7DF, 0x595A, 0xFAA8, 0x5960, 0xEEF5, 0x5962, 0xDECE, 0x5967, 0xE7F3, 0x596A, 0xF7AC, + 0x596B, 0xEBC4, 0x596C, 0xEDE1, 0x596D, 0xE0AB, 0x596E, 0xDDC7, 0x5973, 0xD2B3, 0x5974, 0xD2BF, 0x5978, 0xCACC, 0x597D, 0xFBBF, + 0x5982, 0xE5FD, 0x5983, 0xDDE5, 0x5984, 0xD8CD, 0x598A, 0xECF4, 0x5993, 0xD0F5, 0x5996, 0xE8ED, 0x5997, 0xD0D2, 0x5999, 0xD9D8, + 0x59A5, 0xF6E6, 0x59A8, 0xDBAA, 0x59AC, 0xF7E0, 0x59B9, 0xD8D9, 0x59BB, 0xF4A3, 0x59BE, 0xF4DD, 0x59C3, 0xEFD1, 0x59C6, 0xD9B5, + 0x59C9, 0xEDAB, 0x59CB, 0xE3B7, 0x59D0, 0xEEBB, 0x59D1, 0xCDB4, 0x59D3, 0xE0F3, 0x59D4, 0xEACD, 0x59D9, 0xECF5, 0x59DA, 0xE8EE, + 0x59DC, 0xCBA9, 0x59DD, 0xF1AF, 0x59E6, 0xCACD, 0x59E8, 0xECA9, 0x59EA, 0xF2EB, 0x59EC, 0xFDEF, 0x59EE, 0xF9F3, 0x59F8, 0xE6C1, + 0x59FB, 0xECD8, 0x59FF, 0xEDAC, 0x5A01, 0xEACE, 0x5A03, 0xE8DF, 0x5A11, 0xDECF, 0x5A18, 0xD2A6, 0x5A1B, 0xE7F4, 0x5A1C, 0xD1D6, + 0x5A1F, 0xE6C2, 0x5A20, 0xE3E3, 0x5A25, 0xE4B0, 0x5A29, 0xD8B4, 0x5A36, 0xF6A5, 0x5A3C, 0xF3DE, 0x5A41, 0xD7A5, 0x5A46, 0xF7E8, + 0x5A49, 0xE8C6, 0x5A5A, 0xFBE6, 0x5A62, 0xDDE6, 0x5A66, 0xDCFE, 0x5A92, 0xD8DA, 0x5A9A, 0xDAAC, 0x5A9B, 0xEAB0, 0x5AA4, 0xE3B8, + 0x5AC1, 0xCAAA, 0x5AC2, 0xE1F9, 0x5AC4, 0xEAB1, 0x5AC9, 0xF2EC, 0x5ACC, 0xFAEE, 0x5AE1, 0xEED5, 0x5AE6, 0xF9F4, 0x5AE9, 0xD2EC, + 0x5B05, 0xFBFB, 0x5B09, 0xFDF0, 0x5B0B, 0xE0BD, 0x5B0C, 0xCEE3, 0x5B16, 0xF8C6, 0x5B2A, 0xDEAE, 0x5B40, 0xDFC5, 0x5B43, 0xE5BE, + 0x5B50, 0xEDAD, 0x5B51, 0xFAEA, 0x5B54, 0xCDEE, 0x5B55, 0xEDA6, 0x5B57, 0xEDAE, 0x5B58, 0xF0ED, 0x5B5A, 0xDDA1, 0x5B5C, 0xEDAF, + 0x5B5D, 0xFCF8, 0x5B5F, 0xD8EB, 0x5B63, 0xCCF9, 0x5B64, 0xCDB5, 0x5B69, 0xFAA9, 0x5B6B, 0xE1DD, 0x5B70, 0xE2D5, 0x5B71, 0xEDCF, + 0x5B75, 0xDDA2, 0x5B78, 0xF9CA, 0x5B7A, 0xEAE8, 0x5B7C, 0xE5ED, 0x5B85, 0xD3EB, 0x5B87, 0xE9D4, 0x5B88, 0xE1FA, 0x5B89, 0xE4CC, + 0x5B8B, 0xE1E4, 0x5B8C, 0xE8C7, 0x5B8F, 0xCEDB, 0x5B93, 0xDCD5, 0x5B95, 0xF7B5, 0x5B96, 0xFCF3, 0x5B97, 0xF0F3, 0x5B98, 0xCEAF, + 0x5B99, 0xF1B5, 0x5B9A, 0xEFD2, 0x5B9B, 0xE8C8, 0x5B9C, 0xEBF1, 0x5BA2, 0xCBD4, 0x5BA3, 0xE0BE, 0x5BA4, 0xE3F8, 0x5BA5, 0xEAE9, + 0x5BA6, 0xFCB2, 0x5BAC, 0xE0F4, 0x5BAE, 0xCFE0, 0x5BB0, 0xEEA5, 0x5BB3, 0xFAAA, 0x5BB4, 0xE6C3, 0x5BB5, 0xE1B2, 0x5BB6, 0xCAAB, + 0x5BB8, 0xE3E4, 0x5BB9, 0xE9BB, 0x5BBF, 0xE2D6, 0x5BC0, 0xF3F2, 0x5BC2, 0xEED6, 0x5BC3, 0xEAB2, 0x5BC4, 0xD0F6, 0x5BC5, 0xECD9, + 0x5BC6, 0xDACB, 0x5BC7, 0xCFA8, 0x5BCC, 0xDDA3, 0x5BD0, 0xD8DB, 0x5BD2, 0xF9CE, 0x5BD3, 0xE9D5, 0x5BD4, 0xE3D1, 0x5BD7, 0xD2BC, + 0x5BDE, 0xD8AC, 0x5BDF, 0xF3CC, 0x5BE1, 0xCDFB, 0x5BE2, 0xF6D6, 0x5BE4, 0xE7F5, 0x5BE5, 0xE8EF, 0x5BE6, 0xE3F9, 0x5BE7, 0xD2BB, + 0x5BE8, 0xF3F3, 0x5BE9, 0xE3FB, 0x5BEB, 0xDED0, 0x5BEC, 0xCEB0, 0x5BEE, 0xD6F7, 0x5BEF, 0xF1D9, 0x5BF5, 0xF5C1, 0x5BF6, 0xDCC4, + 0x5BF8, 0xF5BB, 0x5BFA, 0xDED1, 0x5C01, 0xDCE6, 0x5C04, 0xDED2, 0x5C07, 0xEDE2, 0x5C08, 0xEEF6, 0x5C09, 0xEACF, 0x5C0A, 0xF0EE, + 0x5C0B, 0xE3FC, 0x5C0D, 0xD3DF, 0x5C0E, 0xD3F4, 0x5C0F, 0xE1B3, 0x5C11, 0xE1B4, 0x5C16, 0xF4D3, 0x5C19, 0xDFC6, 0x5C24, 0xE9D6, + 0x5C28, 0xDBAB, 0x5C31, 0xF6A6, 0x5C38, 0xE3B9, 0x5C39, 0xEBC5, 0x5C3A, 0xF4A9, 0x5C3B, 0xCDB6, 0x5C3C, 0xD2F9, 0x5C3E, 0xDAAD, + 0x5C3F, 0xD2E3, 0x5C40, 0xCFD1, 0x5C45, 0xCBDC, 0x5C46, 0xCCFA, 0x5C48, 0xCFDD, 0x5C4B, 0xE8A9, 0x5C4D, 0xE3BB, 0x5C4E, 0xE3BA, + 0x5C51, 0xE0DA, 0x5C55, 0xEEF7, 0x5C5B, 0xDCB3, 0x5C60, 0xD3F5, 0x5C62, 0xD7A6, 0x5C64, 0xF6B5, 0x5C65, 0xD7DB, 0x5C6C, 0xE1D5, + 0x5C6F, 0xD4EA, 0x5C71, 0xDFA3, 0x5C79, 0xFDDF, 0x5C90, 0xD0F7, 0x5C91, 0xEDD4, 0x5CA1, 0xCBAA, 0x5CA9, 0xE4DB, 0x5CAB, 0xE1FB, + 0x5CAC, 0xCBA2, 0x5CB1, 0xD3E0, 0x5CB3, 0xE4BF, 0x5CB5, 0xFBC0, 0x5CB7, 0xDABE, 0x5CB8, 0xE4CD, 0x5CBA, 0xD6B9, 0x5CBE, 0xEFC0, + 0x5CC0, 0xE1FC, 0x5CD9, 0xF6B9, 0x5CE0, 0xDFC7, 0x5CE8, 0xE4B1, 0x5CEF, 0xDCE7, 0x5CF0, 0xDCE8, 0x5CF4, 0xFAD6, 0x5CF6, 0xD3F6, + 0x5CFB, 0xF1DA, 0x5CFD, 0xFAF2, 0x5D07, 0xE2FD, 0x5D0D, 0xD5CF, 0x5D0E, 0xD0F8, 0x5D11, 0xCDDF, 0x5D14, 0xF5CB, 0x5D16, 0xE4F0, + 0x5D17, 0xCBAB, 0x5D19, 0xD7C4, 0x5D27, 0xE2FE, 0x5D29, 0xDDDA, 0x5D4B, 0xDAAE, 0x5D4C, 0xCAEE, 0x5D50, 0xD5B9, 0x5D69, 0xE3A1, + 0x5D6C, 0xE8E3, 0x5D6F, 0xF3AB, 0x5D87, 0xCFA9, 0x5D8B, 0xD3F7, 0x5D9D, 0xD4F1, 0x5DA0, 0xCEE4, 0x5DA2, 0xE8F2, 0x5DAA, 0xE5F5, + 0x5DB8, 0xE7AE, 0x5DBA, 0xD6BA, 0x5DBC, 0xDFEC, 0x5DBD, 0xE4C0, 0x5DCD, 0xE8E4, 0x5DD2, 0xD8B5, 0x5DD6, 0xE4DC, 0x5DDD, 0xF4B9, + 0x5DDE, 0xF1B6, 0x5DE1, 0xE2DE, 0x5DE2, 0xE1B5, 0x5DE5, 0xCDEF, 0x5DE6, 0xF1A7, 0x5DE7, 0xCEE5, 0x5DE8, 0xCBDD, 0x5DEB, 0xD9E3, + 0x5DEE, 0xF3AC, 0x5DF1, 0xD0F9, 0x5DF2, 0xECAB, 0x5DF3, 0xDED3, 0x5DF4, 0xF7E9, 0x5DF7, 0xF9F5, 0x5DFD, 0xE1DE, 0x5DFE, 0xCBEE, + 0x5E02, 0xE3BC, 0x5E03, 0xF8D6, 0x5E06, 0xDBEE, 0x5E0C, 0xFDF1, 0x5E11, 0xF7B6, 0x5E16, 0xF4DE, 0x5E19, 0xF2ED, 0x5E1B, 0xDBD9, + 0x5E1D, 0xF0A8, 0x5E25, 0xE1FD, 0x5E2B, 0xDED4, 0x5E2D, 0xE0AC, 0x5E33, 0xEDE3, 0x5E36, 0xD3E1, 0x5E38, 0xDFC8, 0x5E3D, 0xD9B6, + 0x5E3F, 0xFDAC, 0x5E40, 0xEFD3, 0x5E44, 0xE4C1, 0x5E45, 0xF8EB, 0x5E47, 0xDBAC, 0x5E4C, 0xFCC6, 0x5E55, 0xD8AD, 0x5E5F, 0xF6BA, + 0x5E61, 0xDBDF, 0x5E62, 0xD3D3, 0x5E63, 0xF8C7, 0x5E72, 0xCACE, 0x5E73, 0xF8C1, 0x5E74, 0xD2B4, 0x5E77, 0xDCB4, 0x5E78, 0xFAB9, + 0x5E79, 0xCACF, 0x5E7B, 0xFCB3, 0x5E7C, 0xEAEA, 0x5E7D, 0xEAEB, 0x5E7E, 0xD0FA, 0x5E84, 0xEDE4, 0x5E87, 0xDDE7, 0x5E8A, 0xDFC9, + 0x5E8F, 0xDFED, 0x5E95, 0xEEBC, 0x5E97, 0xEFC1, 0x5E9A, 0xCCD2, 0x5E9C, 0xDDA4, 0x5EA0, 0xDFCA, 0x5EA6, 0xD3F8, 0x5EA7, 0xF1A8, + 0x5EAB, 0xCDB7, 0x5EAD, 0xEFD4, 0x5EB5, 0xE4DD, 0x5EB6, 0xDFEE, 0x5EB7, 0xCBAC, 0x5EB8, 0xE9BC, 0x5EBE, 0xEAEC, 0x5EC2, 0xDFCB, + 0x5EC8, 0xF9BF, 0x5EC9, 0xD6AF, 0x5ECA, 0xD5C6, 0x5ED0, 0xCFAA, 0x5ED3, 0xCEA9, 0x5ED6, 0xD6F8, 0x5EDA, 0xF1B7, 0x5EDB, 0xEEF8, + 0x5EDF, 0xD9D9, 0x5EE0, 0xF3DF, 0x5EE2, 0xF8C8, 0x5EE3, 0xCEC6, 0x5EEC, 0xD5E6, 0x5EF3, 0xF4E6, 0x5EF6, 0xE6C5, 0x5EF7, 0xEFD5, + 0x5EFA, 0xCBEF, 0x5EFB, 0xFCDF, 0x5F01, 0xDCA7, 0x5F04, 0xD6E7, 0x5F0A, 0xF8C9, 0x5F0F, 0xE3D2, 0x5F11, 0xE3BD, 0x5F13, 0xCFE1, + 0x5F14, 0xF0C0, 0x5F15, 0xECDA, 0x5F17, 0xDDD7, 0x5F18, 0xFBF0, 0x5F1B, 0xECAC, 0x5F1F, 0xF0A9, 0x5F26, 0xFAD7, 0x5F27, 0xFBC1, + 0x5F29, 0xD2C0, 0x5F31, 0xE5B0, 0x5F35, 0xEDE5, 0x5F3A, 0xCBAD, 0x5F3C, 0xF9B0, 0x5F48, 0xF7A5, 0x5F4A, 0xCBAE, 0x5F4C, 0xDAAF, + 0x5F4E, 0xD8B6, 0x5F56, 0xD3A7, 0x5F57, 0xFBB2, 0x5F59, 0xFDC4, 0x5F5B, 0xECAD, 0x5F62, 0xFBA1, 0x5F66, 0xE5E9, 0x5F67, 0xE9EE, + 0x5F69, 0xF3F4, 0x5F6A, 0xF8F3, 0x5F6B, 0xF0C1, 0x5F6C, 0xDEAF, 0x5F6D, 0xF8B0, 0x5F70, 0xF3E0, 0x5F71, 0xE7AF, 0x5F77, 0xDBAD, + 0x5F79, 0xE6B5, 0x5F7C, 0xF9A8, 0x5F7F, 0xDDD8, 0x5F80, 0xE8D9, 0x5F81, 0xEFD6, 0x5F85, 0xD3E2, 0x5F87, 0xE2DF, 0x5F8A, 0xFCE0, + 0x5F8B, 0xD7C8, 0x5F8C, 0xFDAD, 0x5F90, 0xDFEF, 0x5F91, 0xCCD3, 0x5F92, 0xD3F9, 0x5F97, 0xD4F0, 0x5F98, 0xDBC7, 0x5F99, 0xDED5, + 0x5F9E, 0xF0F4, 0x5FA0, 0xD5D0, 0x5FA1, 0xE5D9, 0x5FA8, 0xFCC7, 0x5FA9, 0xDCD6, 0x5FAA, 0xE2E0, 0x5FAE, 0xDAB0, 0x5FB5, 0xF3A3, + 0x5FB7, 0xD3EC, 0x5FB9, 0xF4CB, 0x5FBD, 0xFDC5, 0x5FC3, 0xE3FD, 0x5FC5, 0xF9B1, 0x5FCC, 0xD0FB, 0x5FCD, 0xECDB, 0x5FD6, 0xF5BC, + 0x5FD7, 0xF2A4, 0x5FD8, 0xD8CE, 0x5FD9, 0xD8CF, 0x5FE0, 0xF5F7, 0x5FEB, 0xF6E1, 0x5FF5, 0xD2B7, 0x5FFD, 0xFBEC, 0x5FFF, 0xDDC8, + 0x600F, 0xE4E8, 0x6012, 0xD2C1, 0x6016, 0xF8D7, 0x601C, 0xD6BB, 0x601D, 0xDED6, 0x6020, 0xF7BD, 0x6021, 0xECAE, 0x6025, 0xD0E1, + 0x6027, 0xE0F5, 0x6028, 0xEAB3, 0x602A, 0xCED6, 0x602F, 0xCCA5, 0x6041, 0xECF6, 0x6042, 0xE2E1, 0x6043, 0xE3BE, 0x604D, 0xFCC8, + 0x6050, 0xCDF0, 0x6052, 0xF9F6, 0x6055, 0xDFF0, 0x6059, 0xE5BF, 0x605D, 0xCEBF, 0x6062, 0xFCE1, 0x6063, 0xEDB0, 0x6064, 0xFDD1, + 0x6065, 0xF6BB, 0x6068, 0xF9CF, 0x6069, 0xEBDA, 0x606A, 0xCAC1, 0x606C, 0xD2B8, 0x606D, 0xCDF1, 0x606F, 0xE3D3, 0x6070, 0xFDE6, + 0x6085, 0xE6ED, 0x6089, 0xE3FA, 0x608C, 0xF0AA, 0x608D, 0xF9D0, 0x6094, 0xFCE2, 0x6096, 0xF8A7, 0x609A, 0xE1E5, 0x609B, 0xEEF9, + 0x609F, 0xE7F6, 0x60A0, 0xEAED, 0x60A3, 0xFCB4, 0x60A4, 0xF5C2, 0x60A7, 0xD7DC, 0x60B0, 0xF0F5, 0x60B2, 0xDDE8, 0x60B3, 0xD3ED, + 0x60B4, 0xF5FC, 0x60B6, 0xDABF, 0x60B8, 0xCCFB, 0x60BC, 0xD3FA, 0x60BD, 0xF4A4, 0x60C5, 0xEFD7, 0x60C7, 0xD4C3, 0x60D1, 0xFBE3, + 0x60DA, 0xFBED, 0x60DC, 0xE0AD, 0x60DF, 0xEAEE, 0x60E0, 0xFBB3, 0x60E1, 0xE4C2, 0x60F0, 0xF6E7, 0x60F1, 0xD2DD, 0x60F3, 0xDFCC, + 0x60F6, 0xFCC9, 0x60F9, 0xE5A9, 0x60FA, 0xE0F6, 0x60FB, 0xF6B3, 0x6101, 0xE1FE, 0x6106, 0xCBF0, 0x6108, 0xEAEF, 0x6109, 0xEAF0, + 0x610D, 0xDAC0, 0x610E, 0xF8B4, 0x610F, 0xEBF2, 0x6115, 0xE4C3, 0x611A, 0xE9D7, 0x611B, 0xE4F1, 0x611F, 0xCAEF, 0x6127, 0xCED7, + 0x6130, 0xFCCA, 0x6134, 0xF3E1, 0x6137, 0xCBC4, 0x613C, 0xE3E5, 0x613E, 0xCBC5, 0x613F, 0xEAB4, 0x6142, 0xE9BD, 0x6144, 0xD7C9, + 0x6147, 0xEBDB, 0x6148, 0xEDB1, 0x614A, 0xCCC3, 0x614B, 0xF7BE, 0x614C, 0xFCCB, 0x6153, 0xF8F4, 0x6155, 0xD9B7, 0x6158, 0xF3D3, + 0x6159, 0xF3D4, 0x615D, 0xF7E4, 0x615F, 0xF7D1, 0x6162, 0xD8B7, 0x6163, 0xCEB1, 0x6164, 0xCAC2, 0x6167, 0xFBB4, 0x6168, 0xCBC6, + 0x616B, 0xF0F6, 0x616E, 0xD5E7, 0x6170, 0xEAD0, 0x6176, 0xCCD4, 0x6177, 0xCBAF, 0x617D, 0xF4AA, 0x617E, 0xE9AF, 0x6181, 0xF5C3, + 0x6182, 0xE9D8, 0x618A, 0xDDE9, 0x618E, 0xF1F3, 0x6190, 0xD5FB, 0x6191, 0xDEBB, 0x6194, 0xF4FB, 0x6198, 0xFDF3, 0x6199, 0xFDF2, + 0x619A, 0xF7A6, 0x61A4, 0xDDC9, 0x61A7, 0xD4D3, 0x61A9, 0xCCA8, 0x61AB, 0xDAC1, 0x61AC, 0xCCD5, 0x61AE, 0xD9E4, 0x61B2, 0xFACA, + 0x61B6, 0xE5E3, 0x61BA, 0xD3BC, 0x61BE, 0xCAF0, 0x61C3, 0xD0C4, 0x61C7, 0xCAD0, 0x61C8, 0xFAAB, 0x61C9, 0xEBEB, 0x61CA, 0xE7F8, + 0x61CB, 0xD9E5, 0x61E6, 0xD1D7, 0x61F2, 0xF3A4, 0x61F6, 0xD4FB, 0x61F7, 0xFCE3, 0x61F8, 0xFAD8, 0x61FA, 0xF3D5, 0x61FC, 0xCFAB, + 0x61FF, 0xEBF3, 0x6200, 0xD5FC, 0x6207, 0xD3D4, 0x6208, 0xCDFC, 0x620A, 0xD9E6, 0x620C, 0xE2F9, 0x620D, 0xE2A1, 0x620E, 0xEBD4, + 0x6210, 0xE0F7, 0x6211, 0xE4B2, 0x6212, 0xCCFC, 0x6216, 0xFBE4, 0x621A, 0xF4AB, 0x621F, 0xD0BD, 0x6221, 0xCAF1, 0x622A, 0xEFB8, + 0x622E, 0xD7C0, 0x6230, 0xEEFA, 0x6231, 0xFDF4, 0x6234, 0xD3E3, 0x6236, 0xFBC2, 0x623E, 0xD5E8, 0x623F, 0xDBAE, 0x6240, 0xE1B6, + 0x6241, 0xF8B7, 0x6247, 0xE0BF, 0x6248, 0xFBC3, 0x6249, 0xDDEA, 0x624B, 0xE2A2, 0x624D, 0xEEA6, 0x6253, 0xF6E8, 0x6258, 0xF6F5, + 0x626E, 0xDDCA, 0x6271, 0xD0E2, 0x6276, 0xDDA6, 0x6279, 0xDDEB, 0x627C, 0xE4F9, 0x627F, 0xE3AF, 0x6280, 0xD0FC, 0x6284, 0xF4FC, + 0x6289, 0xCCBC, 0x628A, 0xF7EA, 0x6291, 0xE5E4, 0x6292, 0xDFF1, 0x6295, 0xF7E1, 0x6297, 0xF9F7, 0x6298, 0xEFB9, 0x629B, 0xF8D8, + 0x62AB, 0xF9A9, 0x62B1, 0xF8D9, 0x62B5, 0xEEBD, 0x62B9, 0xD8C6, 0x62BC, 0xE4E3, 0x62BD, 0xF5CE, 0x62C2, 0xDDD9, 0x62C7, 0xD9E7, + 0x62C8, 0xD2B9, 0x62C9, 0xD5C3, 0x62CC, 0xDAE5, 0x62CD, 0xDAD0, 0x62CF, 0xD1D9, 0x62D0, 0xCED8, 0x62D2, 0xCBDE, 0x62D3, 0xF4AC, + 0x62D4, 0xDAFB, 0x62D6, 0xF6E9, 0x62D7, 0xE8F3, 0x62D8, 0xCFAC, 0x62D9, 0xF0F0, 0x62DB, 0xF4FD, 0x62DC, 0xDBC8, 0x62EC, 0xCEC0, + 0x62ED, 0xE3D4, 0x62EE, 0xD1CF, 0x62EF, 0xF1F5, 0x62F1, 0xCDF2, 0x62F3, 0xCFEB, 0x62F7, 0xCDB8, 0x62FE, 0xE3A6, 0x62FF, 0xD1DA, + 0x6301, 0xF2A5, 0x6307, 0xF2A6, 0x6309, 0xE4CE, 0x6311, 0xD3FB, 0x632B, 0xF1A9, 0x632F, 0xF2C9, 0x633A, 0xEFD8, 0x633B, 0xE6C9, + 0x633D, 0xD8B8, 0x633E, 0xFAF3, 0x6349, 0xF3B5, 0x634C, 0xF8A4, 0x634F, 0xD1F3, 0x6350, 0xE6C8, 0x6355, 0xF8DA, 0x6367, 0xDCE9, + 0x6368, 0xDED7, 0x636E, 0xCBDF, 0x6372, 0xCFEC, 0x6377, 0xF4DF, 0x637A, 0xD1F4, 0x637B, 0xD2BA, 0x637F, 0xDFF2, 0x6383, 0xE1B7, + 0x6388, 0xE2A3, 0x6389, 0xD3FC, 0x638C, 0xEDE6, 0x6392, 0xDBC9, 0x6396, 0xE4FA, 0x6398, 0xCFDE, 0x639B, 0xCED0, 0x63A0, 0xD5D3, + 0x63A1, 0xF3F5, 0x63A2, 0xF7AE, 0x63A5, 0xEFC8, 0x63A7, 0xCDF3, 0x63A8, 0xF5CF, 0x63A9, 0xE5F3, 0x63AA, 0xF0C2, 0x63C0, 0xCAD1, + 0x63C4, 0xEAF1, 0x63C6, 0xD0A6, 0x63CF, 0xD9DA, 0x63D0, 0xF0AB, 0x63D6, 0xEBE7, 0x63DA, 0xE5C0, 0x63DB, 0xFCB5, 0x63E1, 0xE4C4, + 0x63ED, 0xCCA9, 0x63EE, 0xFDC6, 0x63F4, 0xEAB5, 0x63F6, 0xE5AA, 0x63F7, 0xDFBA, 0x640D, 0xE1DF, 0x640F, 0xDAD1, 0x6414, 0xE1B8, + 0x6416, 0xE8F4, 0x6417, 0xD3FD, 0x641C, 0xE2A4, 0x6422, 0xF2CA, 0x642C, 0xDAE6, 0x642D, 0xF7B3, 0x643A, 0xFDCD, 0x643E, 0xF3B6, + 0x6458, 0xEED7, 0x6460, 0xF5C4, 0x6469, 0xD8A4, 0x646F, 0xF2A7, 0x6478, 0xD9B8, 0x6479, 0xD9B9, 0x647A, 0xEFC9, 0x6488, 0xD6CE, + 0x6491, 0xF7CB, 0x6492, 0xDFAE, 0x6493, 0xE8F5, 0x649A, 0xD2B5, 0x649E, 0xD3D5, 0x64A4, 0xF4CC, 0x64A5, 0xDAFC, 0x64AB, 0xD9E8, + 0x64AD, 0xF7EB, 0x64AE, 0xF5C9, 0x64B0, 0xF3BC, 0x64B2, 0xDAD2, 0x64BB, 0xD3B5, 0x64C1, 0xE8B6, 0x64C4, 0xD6CF, 0x64C5, 0xF4BA, + 0x64C7, 0xF7C9, 0x64CA, 0xCCAA, 0x64CD, 0xF0C3, 0x64CE, 0xCCD6, 0x64D2, 0xD0D3, 0x64D4, 0xD3BD, 0x64D8, 0xDBFB, 0x64DA, 0xCBE0, + 0x64E1, 0xD3E4, 0x64E2, 0xF6F7, 0x64E5, 0xD5BA, 0x64E6, 0xF3CD, 0x64E7, 0xCBE1, 0x64EC, 0xEBF4, 0x64F2, 0xF4AD, 0x64F4, 0xFCAA, + 0x64FA, 0xF7EC, 0x64FE, 0xE8F6, 0x6500, 0xDAE7, 0x6504, 0xF7CC, 0x6518, 0xE5C1, 0x651D, 0xE0EE, 0x6523, 0xD5FD, 0x652A, 0xCEE6, + 0x652B, 0xFCAB, 0x652C, 0xD5BB, 0x652F, 0xF2A8, 0x6536, 0xE2A5, 0x6537, 0xCDB9, 0x6538, 0xEAF2, 0x6539, 0xCBC7, 0x653B, 0xCDF4, + 0x653E, 0xDBAF, 0x653F, 0xEFD9, 0x6545, 0xCDBA, 0x6548, 0xFCF9, 0x654D, 0xDFF3, 0x654E, 0xCEE7, 0x654F, 0xDAC2, 0x6551, 0xCFAD, + 0x6556, 0xE7F9, 0x6557, 0xF8A8, 0x655E, 0xF3E2, 0x6562, 0xCAF2, 0x6563, 0xDFA4, 0x6566, 0xD4C4, 0x656C, 0xCCD7, 0x656D, 0xE5C2, + 0x6572, 0xCDBB, 0x6574, 0xEFDA, 0x6575, 0xEED8, 0x6577, 0xDDA7, 0x6578, 0xE2A6, 0x657E, 0xE0C0, 0x6582, 0xD6B0, 0x6583, 0xF8CA, + 0x6585, 0xFCFA, 0x6587, 0xD9FE, 0x658C, 0xDEB0, 0x6590, 0xDDEC, 0x6591, 0xDAE8, 0x6597, 0xD4E0, 0x6599, 0xD6F9, 0x659B, 0xCDD7, + 0x659C, 0xDED8, 0x659F, 0xF2F8, 0x65A1, 0xE4D6, 0x65A4, 0xD0C5, 0x65A5, 0xF4AE, 0x65A7, 0xDDA8, 0x65AB, 0xEDC5, 0x65AC, 0xF3D6, + 0x65AF, 0xDED9, 0x65B0, 0xE3E6, 0x65B7, 0xD3A8, 0x65B9, 0xDBB0, 0x65BC, 0xE5DA, 0x65BD, 0xE3BF, 0x65C1, 0xDBB1, 0x65C5, 0xD5E9, + 0x65CB, 0xE0C1, 0x65CC, 0xEFDB, 0x65CF, 0xF0E9, 0x65D2, 0xD7B2, 0x65D7, 0xD0FD, 0x65E0, 0xD9E9, 0x65E3, 0xD0FE, 0x65E5, 0xECED, + 0x65E6, 0xD3A9, 0x65E8, 0xF2A9, 0x65E9, 0xF0C4, 0x65EC, 0xE2E2, 0x65ED, 0xE9EF, 0x65F1, 0xF9D1, 0x65F4, 0xE9D9, 0x65FA, 0xE8DA, + 0x65FB, 0xDAC3, 0x65FC, 0xDAC4, 0x65FD, 0xD4C5, 0x65FF, 0xE7FA, 0x6606, 0xCDE0, 0x6607, 0xE3B0, 0x6609, 0xDBB2, 0x660A, 0xFBC4, + 0x660C, 0xF3E3, 0x660E, 0xD9A5, 0x660F, 0xFBE7, 0x6610, 0xDDCB, 0x6611, 0xD0D4, 0x6613, 0xE6B6, 0x6614, 0xE0AE, 0x6615, 0xFDDA, + 0x661E, 0xDCB5, 0x661F, 0xE0F8, 0x6620, 0xE7B1, 0x6625, 0xF5F0, 0x6627, 0xD8DC, 0x6628, 0xEDC6, 0x662D, 0xE1B9, 0x662F, 0xE3C0, + 0x6630, 0xF9C0, 0x6631, 0xE9F0, 0x6634, 0xD9DB, 0x6636, 0xF3E4, 0x663A, 0xDCB6, 0x663B, 0xE4E9, 0x6641, 0xF0C5, 0x6642, 0xE3C1, + 0x6643, 0xFCCC, 0x6644, 0xFCCD, 0x6649, 0xF2CB, 0x664B, 0xF2CC, 0x664F, 0xE4CF, 0x6659, 0xF1DB, 0x665B, 0xFAD9, 0x665D, 0xF1B8, + 0x665E, 0xFDF5, 0x665F, 0xE0F9, 0x6664, 0xE7FB, 0x6665, 0xFCB7, 0x6666, 0xFCE4, 0x6667, 0xFBC5, 0x6668, 0xE3E7, 0x6669, 0xD8B9, + 0x666B, 0xF6F8, 0x666E, 0xDCC5, 0x666F, 0xCCD8, 0x6673, 0xE0AF, 0x6674, 0xF4E7, 0x6676, 0xEFDC, 0x6677, 0xCFFC, 0x6678, 0xEFDD, + 0x667A, 0xF2AA, 0x6684, 0xFDBE, 0x6687, 0xCAAC, 0x6688, 0xFDBB, 0x6689, 0xFDC7, 0x668E, 0xE7B2, 0x6690, 0xEAD1, 0x6691, 0xDFF4, + 0x6696, 0xD1EC, 0x6697, 0xE4DE, 0x6698, 0xE5C3, 0x669D, 0xD9A6, 0x66A0, 0xCDBC, 0x66A2, 0xF3E5, 0x66AB, 0xEDD5, 0x66AE, 0xD9BA, + 0x66B2, 0xEDE7, 0x66B3, 0xFBB5, 0x66B4, 0xF8EC, 0x66B9, 0xE0E7, 0x66BB, 0xCCD9, 0x66BE, 0xD4C6, 0x66C4, 0xE7A5, 0x66C6, 0xD5F5, + 0x66C7, 0xD3BE, 0x66C9, 0xFCFB, 0x66D6, 0xE4F2, 0x66D9, 0xDFF5, 0x66DC, 0xE8F8, 0x66DD, 0xF8ED, 0x66E0, 0xCEC7, 0x66E6, 0xFDF6, + 0x66F0, 0xE8D8, 0x66F2, 0xCDD8, 0x66F3, 0xE7D6, 0x66F4, 0xCCDA, 0x66F7, 0xCAE3, 0x66F8, 0xDFF6, 0x66F9, 0xF0C7, 0x66FA, 0xF0C6, + 0x66FC, 0xD8BA, 0x66FE, 0xF1F4, 0x66FF, 0xF4F0, 0x6700, 0xF5CC, 0x6703, 0xFCE5, 0x6708, 0xEAC5, 0x6709, 0xEAF3, 0x670B, 0xDDDB, + 0x670D, 0xDCD7, 0x6714, 0xDEFD, 0x6715, 0xF2F9, 0x6717, 0xD5C7, 0x671B, 0xD8D0, 0x671D, 0xF0C8, 0x671E, 0xD1A1, 0x671F, 0xD1A2, + 0x6726, 0xD9D4, 0x6727, 0xD6E8, 0x6728, 0xD9CA, 0x672A, 0xDAB1, 0x672B, 0xD8C7, 0x672C, 0xDCE2, 0x672D, 0xF3CE, 0x672E, 0xF5F4, + 0x6731, 0xF1B9, 0x6734, 0xDAD3, 0x6736, 0xF6EA, 0x673A, 0xCFF5, 0x673D, 0xFDAE, 0x6746, 0xCAD2, 0x6749, 0xDFB4, 0x674E, 0xD7DD, + 0x674F, 0xFABA, 0x6750, 0xEEA7, 0x6751, 0xF5BD, 0x6753, 0xF8F5, 0x6756, 0xEDE8, 0x675C, 0xD4E1, 0x675E, 0xD1A3, 0x675F, 0xE1D6, + 0x676D, 0xF9F8, 0x676F, 0xDBCA, 0x6770, 0xCBF9, 0x6771, 0xD4D4, 0x6773, 0xD9DC, 0x6775, 0xEEBE, 0x6777, 0xF7ED, 0x677B, 0xD2EE, + 0x677E, 0xE1E6, 0x677F, 0xF7F9, 0x6787, 0xDDED, 0x6789, 0xE8DB, 0x678B, 0xDBB3, 0x678F, 0xD1F7, 0x6790, 0xE0B0, 0x6793, 0xD4E2, + 0x6795, 0xF6D7, 0x6797, 0xD7F9, 0x679A, 0xD8DD, 0x679C, 0xCDFD, 0x679D, 0xF2AB, 0x67AF, 0xCDBD, 0x67B0, 0xF8C2, 0x67B3, 0xF2AC, + 0x67B6, 0xCAAD, 0x67B7, 0xCAAE, 0x67B8, 0xCFAE, 0x67BE, 0xE3C2, 0x67C4, 0xDCB7, 0x67CF, 0xDBDA, 0x67D0, 0xD9BB, 0x67D1, 0xCAF3, + 0x67D2, 0xF6D3, 0x67D3, 0xE6F8, 0x67D4, 0xEAF5, 0x67DA, 0xEAF6, 0x67DD, 0xF6F9, 0x67E9, 0xCFAF, 0x67EC, 0xCAD3, 0x67EF, 0xCAAF, + 0x67F0, 0xD2B0, 0x67F1, 0xF1BA, 0x67F3, 0xD7B3, 0x67F4, 0xE3C3, 0x67F5, 0xF3FD, 0x67F6, 0xDEDA, 0x67FB, 0xDEDB, 0x67FE, 0xEFDE, + 0x6812, 0xE2E3, 0x6813, 0xEEFB, 0x6816, 0xDFF7, 0x6817, 0xD7CA, 0x6821, 0xCEE8, 0x6822, 0xDBDB, 0x682A, 0xF1BB, 0x682F, 0xE9F1, + 0x6838, 0xFAB7, 0x6839, 0xD0C6, 0x683C, 0xCCAB, 0x683D, 0xEEA8, 0x6840, 0xCBFA, 0x6841, 0xF9F9, 0x6842, 0xCCFD, 0x6843, 0xD3FE, + 0x6848, 0xE4D0, 0x684E, 0xF2EE, 0x6850, 0xD4D5, 0x6851, 0xDFCD, 0x6853, 0xFCB8, 0x6854, 0xD1D0, 0x686D, 0xF2CD, 0x6876, 0xF7D2, + 0x687F, 0xCAD4, 0x6881, 0xD5D9, 0x6885, 0xD8DE, 0x688F, 0xCDD9, 0x6893, 0xEEA9, 0x6894, 0xF6BC, 0x6897, 0xCCDB, 0x689D, 0xF0C9, + 0x689F, 0xFCFC, 0x68A1, 0xE8C9, 0x68A2, 0xF4FE, 0x68A7, 0xE7FC, 0x68A8, 0xD7DE, 0x68AD, 0xDEDC, 0x68AF, 0xF0AC, 0x68B0, 0xCCFE, + 0x68B1, 0xCDE1, 0x68B3, 0xE1BA, 0x68B5, 0xDBEF, 0x68B6, 0xDAB2, 0x68C4, 0xD1A5, 0x68C5, 0xDCB8, 0x68C9, 0xD8F6, 0x68CB, 0xD1A4, + 0x68CD, 0xCDE2, 0x68D2, 0xDCEA, 0x68D5, 0xF0F7, 0x68D7, 0xF0CA, 0x68D8, 0xD0BE, 0x68DA, 0xDDDC, 0x68DF, 0xD4D6, 0x68E0, 0xD3D6, + 0x68E7, 0xEDD0, 0x68E8, 0xCDA1, 0x68EE, 0xDFB5, 0x68F2, 0xDFF8, 0x68F9, 0xD4A1, 0x68FA, 0xCEB2, 0x6900, 0xE8CA, 0x6905, 0xEBF5, + 0x690D, 0xE3D5, 0x690E, 0xF5D0, 0x6912, 0xF5A1, 0x6927, 0xD9A7, 0x6930, 0xE5AB, 0x693D, 0xE6CB, 0x693F, 0xF5F1, 0x694A, 0xE5C5, + 0x6953, 0xF9A3, 0x6954, 0xE0DB, 0x6955, 0xF6EB, 0x6957, 0xCBF1, 0x6959, 0xD9EA, 0x695A, 0xF5A2, 0x695E, 0xD7D1, 0x6960, 0xD1F8, + 0x6961, 0xEAF8, 0x6962, 0xEAF9, 0x6963, 0xDAB3, 0x6968, 0xEFDF, 0x696B, 0xF1EF, 0x696D, 0xE5F6, 0x696E, 0xEEBF, 0x696F, 0xE2E4, + 0x6975, 0xD0BF, 0x6977, 0xFAAC, 0x6978, 0xF5D1, 0x6979, 0xE7B3, 0x6995, 0xE9BE, 0x699B, 0xF2CE, 0x699C, 0xDBB4, 0x69A5, 0xFCCE, + 0x69A7, 0xDDEE, 0x69AE, 0xE7B4, 0x69B4, 0xD7B4, 0x69BB, 0xF7B4, 0x69C1, 0xCDBE, 0x69C3, 0xDAE9, 0x69CB, 0xCFB0, 0x69CC, 0xF7D9, + 0x69CD, 0xF3E6, 0x69D0, 0xCED9, 0x69E8, 0xCEAA, 0x69EA, 0xCBC8, 0x69FB, 0xD0A7, 0x69FD, 0xF0CB, 0x69FF, 0xD0C7, 0x6A02, 0xE4C5, + 0x6A0A, 0xDBE0, 0x6A11, 0xD5DA, 0x6A13, 0xD7A7, 0x6A17, 0xEEC0, 0x6A19, 0xF8F6, 0x6A1E, 0xF5D2, 0x6A1F, 0xEDE9, 0x6A21, 0xD9BC, + 0x6A23, 0xE5C6, 0x6A35, 0xF5A3, 0x6A38, 0xDAD4, 0x6A39, 0xE2A7, 0x6A3A, 0xFBFC, 0x6A3D, 0xF1DC, 0x6A44, 0xCAF4, 0x6A48, 0xE8FA, + 0x6A4B, 0xCEE9, 0x6A52, 0xE9F8, 0x6A53, 0xE2E5, 0x6A58, 0xD0B9, 0x6A59, 0xD4F2, 0x6A5F, 0xD1A6, 0x6A61, 0xDFCE, 0x6A6B, 0xFCF4, + 0x6A80, 0xD3AA, 0x6A84, 0xCCAC, 0x6A89, 0xEFE0, 0x6A8D, 0xE5E5, 0x6A8E, 0xD0D5, 0x6A97, 0xDBFC, 0x6A9C, 0xFCE6, 0x6AA2, 0xCBFE, + 0x6AA3, 0xEDEA, 0x6AB3, 0xDEB1, 0x6ABB, 0xF9E3, 0x6AC2, 0xD4A2, 0x6AC3, 0xCFF6, 0x6AD3, 0xD6D0, 0x6ADA, 0xD5EA, 0x6ADB, 0xF1EE, + 0x6AF6, 0xFACB, 0x6AFB, 0xE5A1, 0x6B04, 0xD5B1, 0x6B0A, 0xCFED, 0x6B0C, 0xEDEB, 0x6B12, 0xD5B2, 0x6B16, 0xD5BC, 0x6B20, 0xFDE2, + 0x6B21, 0xF3AD, 0x6B23, 0xFDDB, 0x6B32, 0xE9B0, 0x6B3A, 0xD1A7, 0x6B3D, 0xFDE3, 0x6B3E, 0xCEB3, 0x6B46, 0xFDE4, 0x6B47, 0xFACE, + 0x6B4C, 0xCAB0, 0x6B4E, 0xF7A7, 0x6B50, 0xCFB1, 0x6B5F, 0xE6A2, 0x6B61, 0xFCB6, 0x6B62, 0xF2AD, 0x6B63, 0xEFE1, 0x6B64, 0xF3AE, + 0x6B65, 0xDCC6, 0x6B66, 0xD9EB, 0x6B6A, 0xE8E0, 0x6B72, 0xE1A8, 0x6B77, 0xD5F6, 0x6B78, 0xCFFD, 0x6B7B, 0xDEDD, 0x6B7F, 0xD9D1, + 0x6B83, 0xE4EA, 0x6B84, 0xF2CF, 0x6B86, 0xF7BF, 0x6B89, 0xE2E6, 0x6B8A, 0xE2A8, 0x6B96, 0xE3D6, 0x6B98, 0xEDD1, 0x6B9E, 0xE9F9, + 0x6BAE, 0xD6B1, 0x6BAF, 0xDEB2, 0x6BB2, 0xE0E8, 0x6BB5, 0xD3AB, 0x6BB7, 0xEBDC, 0x6BBA, 0xDFAF, 0x6BBC, 0xCAC3, 0x6BBF, 0xEEFC, + 0x6BC1, 0xFDC3, 0x6BC5, 0xEBF6, 0x6BC6, 0xCFB2, 0x6BCB, 0xD9EC, 0x6BCD, 0xD9BD, 0x6BCF, 0xD8DF, 0x6BD2, 0xD4B8, 0x6BD3, 0xEBBE, + 0x6BD4, 0xDDEF, 0x6BD6, 0xDDF0, 0x6BD7, 0xDDF1, 0x6BD8, 0xDDF2, 0x6BDB, 0xD9BE, 0x6BEB, 0xFBC6, 0x6BEC, 0xCFB3, 0x6C08, 0xEEFD, + 0x6C0F, 0xE4AB, 0x6C11, 0xDAC5, 0x6C13, 0xD8EC, 0x6C23, 0xD1A8, 0x6C34, 0xE2A9, 0x6C37, 0xDEBC, 0x6C38, 0xE7B5, 0x6C3E, 0xDBF0, + 0x6C40, 0xEFE2, 0x6C41, 0xF1F0, 0x6C42, 0xCFB4, 0x6C4E, 0xDBF1, 0x6C50, 0xE0B1, 0x6C55, 0xDFA5, 0x6C57, 0xF9D2, 0x6C5A, 0xE7FD, + 0x6C5D, 0xE6A3, 0x6C5E, 0xFBF1, 0x6C5F, 0xCBB0, 0x6C60, 0xF2AE, 0x6C68, 0xCDE7, 0x6C6A, 0xE8DC, 0x6C6D, 0xE7D7, 0x6C70, 0xF7C0, + 0x6C72, 0xD0E3, 0x6C76, 0xDAA1, 0x6C7A, 0xCCBD, 0x6C7D, 0xD1A9, 0x6C7E, 0xDDCC, 0x6C81, 0xE3FE, 0x6C82, 0xD1AA, 0x6C83, 0xE8AA, + 0x6C85, 0xEAB6, 0x6C86, 0xF9FA, 0x6C87, 0xE6CC, 0x6C88, 0xF6D8, 0x6C8C, 0xD4C7, 0x6C90, 0xD9CB, 0x6C92, 0xD9D2, 0x6C93, 0xD3CB, + 0x6C94, 0xD8F7, 0x6C95, 0xDAA9, 0x6C96, 0xF5F8, 0x6C99, 0xDEDE, 0x6C9A, 0xF2AF, 0x6C9B, 0xF8A9, 0x6CAB, 0xD8C8, 0x6CAE, 0xEEC1, + 0x6CB3, 0xF9C1, 0x6CB8, 0xDDF3, 0x6CB9, 0xEAFA, 0x6CBB, 0xF6BD, 0x6CBC, 0xE1BB, 0x6CBD, 0xCDBF, 0x6CBE, 0xF4D4, 0x6CBF, 0xE6CD, + 0x6CC1, 0xFCCF, 0x6CC2, 0xFBA2, 0x6CC4, 0xE0DC, 0x6CC9, 0xF4BB, 0x6CCA, 0xDAD5, 0x6CCC, 0xF9B2, 0x6CD3, 0xFBF2, 0x6CD5, 0xDBF6, + 0x6CD7, 0xDEDF, 0x6CDB, 0xDBF2, 0x6CE1, 0xF8DC, 0x6CE2, 0xF7EE, 0x6CE3, 0xEBE8, 0x6CE5, 0xD2FA, 0x6CE8, 0xF1BC, 0x6CEB, 0xFADA, + 0x6CEE, 0xDAEA, 0x6CEF, 0xDAC6, 0x6CF0, 0xF7C1, 0x6CF3, 0xE7B6, 0x6D0B, 0xE5C7, 0x6D0C, 0xD6AC, 0x6D11, 0xDCC7, 0x6D17, 0xE1A9, + 0x6D19, 0xE2AA, 0x6D1B, 0xD5A6, 0x6D1E, 0xD4D7, 0x6D25, 0xF2D0, 0x6D27, 0xEAFB, 0x6D29, 0xE0DD, 0x6D2A, 0xFBF3, 0x6D32, 0xF1BD, + 0x6D35, 0xE2E7, 0x6D36, 0xFDD7, 0x6D38, 0xCEC8, 0x6D39, 0xEAB7, 0x6D3B, 0xFCC0, 0x6D3D, 0xFDE7, 0x6D3E, 0xF7EF, 0x6D41, 0xD7B5, + 0x6D59, 0xEFBA, 0x6D5A, 0xF1DD, 0x6D5C, 0xDEB3, 0x6D63, 0xE8CB, 0x6D66, 0xF8DD, 0x6D69, 0xFBC7, 0x6D6A, 0xD5C8, 0x6D6C, 0xD7DF, + 0x6D6E, 0xDDA9, 0x6D74, 0xE9B1, 0x6D77, 0xFAAD, 0x6D78, 0xF6D9, 0x6D79, 0xFAF4, 0x6D7F, 0xF8AA, 0x6D85, 0xE6EE, 0x6D87, 0xCCDC, + 0x6D88, 0xE1BC, 0x6D89, 0xE0EF, 0x6D8C, 0xE9BF, 0x6D8D, 0xFCFD, 0x6D8E, 0xE6CE, 0x6D91, 0xE1D7, 0x6D93, 0xE6CF, 0x6D95, 0xF4F1, + 0x6DAF, 0xE4F3, 0x6DB2, 0xE4FB, 0x6DB5, 0xF9E4, 0x6DC0, 0xEFE3, 0x6DC3, 0xCFEE, 0x6DC4, 0xF6BE, 0x6DC5, 0xE0B2, 0x6DC6, 0xFCFE, + 0x6DC7, 0xD1AB, 0x6DCB, 0xD7FA, 0x6DCF, 0xFBC8, 0x6DD1, 0xE2D7, 0x6DD8, 0xD4A3, 0x6DD9, 0xF0F8, 0x6DDA, 0xD7A8, 0x6DDE, 0xE1E7, + 0x6DE1, 0xD3BF, 0x6DE8, 0xEFE4, 0x6DEA, 0xD7C5, 0x6DEB, 0xEBE2, 0x6DEE, 0xFCE7, 0x6DF1, 0xE4A2, 0x6DF3, 0xE2E8, 0x6DF5, 0xE6D0, + 0x6DF7, 0xFBE8, 0x6DF8, 0xF4E8, 0x6DF9, 0xE5F4, 0x6DFA, 0xF4BC, 0x6DFB, 0xF4D5, 0x6E17, 0xDFB6, 0x6E19, 0xFCB9, 0x6E1A, 0xEEC2, + 0x6E1B, 0xCAF5, 0x6E1F, 0xEFE5, 0x6E20, 0xCBE2, 0x6E21, 0xD4A4, 0x6E23, 0xDEE0, 0x6E24, 0xDAFD, 0x6E25, 0xE4C6, 0x6E26, 0xE8BE, + 0x6E2B, 0xE0DE, 0x6E2C, 0xF6B4, 0x6E2D, 0xEAD2, 0x6E2F, 0xF9FB, 0x6E32, 0xE0C2, 0x6E34, 0xCAE4, 0x6E36, 0xE7B7, 0x6E38, 0xEAFD, + 0x6E3A, 0xD9DD, 0x6E3C, 0xDAB4, 0x6E3D, 0xEEAA, 0x6E3E, 0xFBE9, 0x6E43, 0xDBCB, 0x6E44, 0xDAB5, 0x6E4A, 0xF1BE, 0x6E4D, 0xD3AC, + 0x6E56, 0xFBC9, 0x6E58, 0xDFCF, 0x6E5B, 0xD3C0, 0x6E5C, 0xE3D7, 0x6E5E, 0xEFE6, 0x6E5F, 0xFCD0, 0x6E67, 0xE9C0, 0x6E6B, 0xF5D3, + 0x6E6E, 0xECDC, 0x6E6F, 0xF7B7, 0x6E72, 0xEAB8, 0x6E73, 0xD1F9, 0x6E7A, 0xDCC8, 0x6E90, 0xEAB9, 0x6E96, 0xF1DE, 0x6E9C, 0xD7B6, + 0x6E9D, 0xCFB5, 0x6E9F, 0xD9A8, 0x6EA2, 0xECEE, 0x6EA5, 0xDDAA, 0x6EAA, 0xCDA2, 0x6EAB, 0xE8AE, 0x6EAF, 0xE1BD, 0x6EB1, 0xF2D1, + 0x6EB6, 0xE9C1, 0x6EBA, 0xD2FC, 0x6EC2, 0xDBB5, 0x6EC4, 0xF3E7, 0x6EC5, 0xD8FE, 0x6EC9, 0xFCD1, 0x6ECB, 0xEDB2, 0x6ECC, 0xF4AF, + 0x6ECE, 0xFBA3, 0x6ED1, 0xFCC1, 0x6ED3, 0xEEAB, 0x6ED4, 0xD4A5, 0x6EEF, 0xF4F2, 0x6EF4, 0xEED9, 0x6EF8, 0xFBCA, 0x6EFE, 0xCDE3, + 0x6EFF, 0xD8BB, 0x6F01, 0xE5DB, 0x6F02, 0xF8F7, 0x6F06, 0xF6D4, 0x6F0F, 0xD7A9, 0x6F11, 0xCBC9, 0x6F14, 0xE6D1, 0x6F15, 0xF0CC, + 0x6F20, 0xD8AE, 0x6F22, 0xF9D3, 0x6F23, 0xD5FE, 0x6F2B, 0xD8BC, 0x6F2C, 0xF2B0, 0x6F31, 0xE2AB, 0x6F32, 0xF3E8, 0x6F38, 0xEFC2, + 0x6F3F, 0xEDEC, 0x6F41, 0xE7B8, 0x6F51, 0xDAFE, 0x6F54, 0xCCBE, 0x6F57, 0xF2FC, 0x6F58, 0xDAEB, 0x6F5A, 0xE2D8, 0x6F5B, 0xEDD6, + 0x6F5E, 0xD6D1, 0x6F5F, 0xE0B3, 0x6F62, 0xFCD2, 0x6F64, 0xEBC8, 0x6F6D, 0xD3C1, 0x6F6E, 0xF0CD, 0x6F70, 0xCFF7, 0x6F7A, 0xEDD2, + 0x6F7C, 0xD4D8, 0x6F7D, 0xDCC9, 0x6F7E, 0xD7F1, 0x6F81, 0xDFBB, 0x6F84, 0xF3A5, 0x6F88, 0xF4CD, 0x6F8D, 0xF1BF, 0x6F8E, 0xF8B1, + 0x6F90, 0xE9FA, 0x6F94, 0xFBCB, 0x6F97, 0xCAD5, 0x6FA3, 0xF9D4, 0x6FA4, 0xF7CA, 0x6FA7, 0xD6C8, 0x6FAE, 0xFCE8, 0x6FAF, 0xF3BD, + 0x6FB1, 0xEEFE, 0x6FB3, 0xE7FE, 0x6FB9, 0xD3C2, 0x6FBE, 0xD3B6, 0x6FC0, 0xCCAD, 0x6FC1, 0xF6FA, 0x6FC2, 0xD6B2, 0x6FC3, 0xD2D8, + 0x6FCA, 0xE7D8, 0x6FD5, 0xE3A5, 0x6FDA, 0xE7B9, 0x6FDF, 0xF0AD, 0x6FE0, 0xFBCC, 0x6FE1, 0xEBA1, 0x6FE4, 0xD4A6, 0x6FE9, 0xFBCD, + 0x6FEB, 0xD5BD, 0x6FEC, 0xF1DF, 0x6FEF, 0xF6FB, 0x6FF1, 0xDEB4, 0x6FFE, 0xD5EB, 0x7001, 0xE5C8, 0x7005, 0xFBA4, 0x7006, 0xD4B9, + 0x7009, 0xDEE1, 0x700B, 0xE4A3, 0x700F, 0xD7B7, 0x7011, 0xF8EE, 0x7015, 0xDEB5, 0x7018, 0xD6D2, 0x701A, 0xF9D5, 0x701B, 0xE7BA, + 0x701C, 0xEBD5, 0x701D, 0xD5F7, 0x701E, 0xEFE7, 0x701F, 0xE1BE, 0x7023, 0xFAAE, 0x7027, 0xD6E9, 0x7028, 0xD6EE, 0x702F, 0xE7BB, + 0x7037, 0xECCB, 0x703E, 0xD5B3, 0x704C, 0xCEB4, 0x7050, 0xFBA5, 0x7051, 0xE1EE, 0x7058, 0xF7A8, 0x705D, 0xFBCE, 0x7063, 0xD8BD, + 0x706B, 0xFBFD, 0x7070, 0xFCE9, 0x7078, 0xCFB6, 0x707C, 0xEDC7, 0x707D, 0xEEAC, 0x7085, 0xCCDD, 0x708A, 0xF6A7, 0x708E, 0xE6FA, + 0x7092, 0xF5A4, 0x7098, 0xFDDC, 0x7099, 0xEDB3, 0x709A, 0xCEC9, 0x70A1, 0xEFE8, 0x70A4, 0xE1BF, 0x70AB, 0xFADB, 0x70AC, 0xCBE3, + 0x70AD, 0xF7A9, 0x70AF, 0xFBA6, 0x70B3, 0xDCB9, 0x70B7, 0xF1C0, 0x70B8, 0xEDC8, 0x70B9, 0xEFC3, 0x70C8, 0xD6AD, 0x70CB, 0xFDCE, + 0x70CF, 0xE8A1, 0x70D8, 0xFBF4, 0x70D9, 0xD5A7, 0x70DD, 0xF1F6, 0x70DF, 0xE6D3, 0x70F1, 0xCCDE, 0x70F9, 0xF8B2, 0x70FD, 0xDCEB, + 0x7104, 0xFDB6, 0x7109, 0xE5EA, 0x710C, 0xF1E0, 0x7119, 0xDBCC, 0x711A, 0xDDCD, 0x711E, 0xD4C8, 0x7121, 0xD9ED, 0x7126, 0xF5A5, + 0x7130, 0xE6FB, 0x7136, 0xE6D4, 0x7147, 0xFDC8, 0x7149, 0xD6A1, 0x714A, 0xFDBF, 0x714C, 0xFCD3, 0x714E, 0xEFA1, 0x7150, 0xE7BC, + 0x7156, 0xD1EE, 0x7159, 0xE6D5, 0x715C, 0xE9F2, 0x715E, 0xDFB0, 0x7164, 0xD8E0, 0x7165, 0xFCBA, 0x7166, 0xFDAF, 0x7167, 0xF0CE, + 0x7169, 0xDBE1, 0x716C, 0xE5C9, 0x716E, 0xEDB4, 0x717D, 0xE0C3, 0x7184, 0xE3D8, 0x7189, 0xE9FB, 0x718A, 0xEAA8, 0x718F, 0xFDB7, + 0x7192, 0xFBA7, 0x7194, 0xE9C2, 0x7199, 0xFDF7, 0x719F, 0xE2D9, 0x71A2, 0xDCEC, 0x71AC, 0xE8A2, 0x71B1, 0xE6F0, 0x71B9, 0xFDF8, + 0x71BA, 0xFDF9, 0x71BE, 0xF6BF, 0x71C1, 0xE7A7, 0x71C3, 0xE6D7, 0x71C8, 0xD4F3, 0x71C9, 0xD4C9, 0x71CE, 0xD6FA, 0x71D0, 0xD7F2, + 0x71D2, 0xE1C0, 0x71D4, 0xDBE2, 0x71D5, 0xE6D8, 0x71DF, 0xE7BD, 0x71E5, 0xF0CF, 0x71E6, 0xF3BE, 0x71E7, 0xE2AC, 0x71ED, 0xF5B7, + 0x71EE, 0xE0F0, 0x71FB, 0xFDB8, 0x71FC, 0xE3E8, 0x71FE, 0xD4A7, 0x71FF, 0xE8FC, 0x7200, 0xFAD2, 0x7206, 0xF8EF, 0x7210, 0xD6D3, + 0x721B, 0xD5B4, 0x722A, 0xF0D0, 0x722C, 0xF7F0, 0x722D, 0xEEB3, 0x7230, 0xEABA, 0x7232, 0xEAD3, 0x7235, 0xEDC9, 0x7236, 0xDDAB, + 0x723A, 0xE5AC, 0x723B, 0xFDA1, 0x723D, 0xDFD0, 0x723E, 0xECB3, 0x7240, 0xDFD1, 0x7246, 0xEDED, 0x7247, 0xF8B8, 0x7248, 0xF7FA, + 0x724C, 0xF8AB, 0x7252, 0xF4E0, 0x7258, 0xD4BA, 0x7259, 0xE4B3, 0x725B, 0xE9DA, 0x725D, 0xDEB6, 0x725F, 0xD9BF, 0x7261, 0xD9C0, + 0x7262, 0xD6EF, 0x7267, 0xD9CC, 0x7269, 0xDAAA, 0x7272, 0xDFE5, 0x7279, 0xF7E5, 0x727D, 0xCCB2, 0x7280, 0xDFF9, 0x7281, 0xD7E0, + 0x72A2, 0xD4BB, 0x72A7, 0xFDFA, 0x72AC, 0xCCB3, 0x72AF, 0xDBF3, 0x72C0, 0xDFD2, 0x72C2, 0xCECA, 0x72C4, 0xEEDA, 0x72CE, 0xE4E4, + 0x72D0, 0xFBCF, 0x72D7, 0xCFB7, 0x72D9, 0xEEC3, 0x72E1, 0xCEEA, 0x72E9, 0xE2AD, 0x72F8, 0xD7E1, 0x72F9, 0xFAF5, 0x72FC, 0xD5C9, + 0x72FD, 0xF8AC, 0x730A, 0xE7D9, 0x7316, 0xF3E9, 0x731B, 0xD8ED, 0x731C, 0xE3C4, 0x731D, 0xF0F1, 0x7325, 0xE8E5, 0x7329, 0xE0FA, + 0x732A, 0xEEC4, 0x732B, 0xD9DE, 0x7336, 0xEBA2, 0x7337, 0xEBA3, 0x733E, 0xFCC2, 0x733F, 0xEABB, 0x7344, 0xE8AB, 0x7345, 0xDEE2, + 0x7350, 0xEDEF, 0x7352, 0xE8A3, 0x7357, 0xCFF1, 0x7368, 0xD4BC, 0x736A, 0xFCEA, 0x7370, 0xE7BE, 0x7372, 0xFCF2, 0x7375, 0xD6B4, + 0x7378, 0xE2AE, 0x737A, 0xD3B7, 0x737B, 0xFACC, 0x7384, 0xFADC, 0x7386, 0xEDB5, 0x7387, 0xE1E3, 0x7389, 0xE8AC, 0x738B, 0xE8DD, + 0x738E, 0xEFE9, 0x7394, 0xF4BD, 0x7396, 0xCFB8, 0x7397, 0xE9DB, 0x7398, 0xD1AC, 0x739F, 0xDAC7, 0x73A7, 0xEBC9, 0x73A9, 0xE8CC, + 0x73AD, 0xDEB7, 0x73B2, 0xD6BC, 0x73B3, 0xD3E5, 0x73B9, 0xFADD, 0x73C0, 0xDAD6, 0x73C2, 0xCAB1, 0x73C9, 0xDAC8, 0x73CA, 0xDFA6, + 0x73CC, 0xF9B3, 0x73CD, 0xF2D2, 0x73CF, 0xCAC4, 0x73D6, 0xCECB, 0x73D9, 0xCDF5, 0x73DD, 0xFDB0, 0x73DE, 0xD5A8, 0x73E0, 0xF1C1, + 0x73E3, 0xE2E9, 0x73E4, 0xDCCA, 0x73E5, 0xECB4, 0x73E6, 0xFAC0, 0x73E9, 0xFBA8, 0x73EA, 0xD0A8, 0x73ED, 0xDAEC, 0x73F7, 0xD9EE, + 0x73F9, 0xE0FB, 0x73FD, 0xEFEA, 0x73FE, 0xFADE, 0x7401, 0xE0C4, 0x7403, 0xCFB9, 0x7405, 0xD5CA, 0x7406, 0xD7E2, 0x7407, 0xE2AF, + 0x7409, 0xD7B8, 0x7413, 0xE8CD, 0x741B, 0xF6DA, 0x7420, 0xEFA2, 0x7421, 0xE2DA, 0x7422, 0xF6FC, 0x7425, 0xFBD0, 0x7426, 0xD1AD, + 0x7428, 0xCDE4, 0x742A, 0xD1AE, 0x742B, 0xDCED, 0x742C, 0xE8CE, 0x742E, 0xF0F9, 0x742F, 0xCEB5, 0x7430, 0xE6FC, 0x7433, 0xD7FB, + 0x7434, 0xD0D6, 0x7435, 0xDDF5, 0x7436, 0xF7F1, 0x7438, 0xF6FD, 0x743A, 0xDBF7, 0x743F, 0xFBEA, 0x7440, 0xE9DC, 0x7441, 0xD9C1, + 0x7443, 0xF5F2, 0x7444, 0xE0C5, 0x744B, 0xEAD4, 0x7455, 0xF9C2, 0x7457, 0xEABC, 0x7459, 0xD2C5, 0x745A, 0xFBD1, 0x745B, 0xE7C0, + 0x745C, 0xEBA5, 0x745E, 0xDFFA, 0x745F, 0xE3A2, 0x7460, 0xD7B9, 0x7462, 0xE9C3, 0x7464, 0xE8FD, 0x7465, 0xE8AF, 0x7468, 0xF2D3, + 0x7469, 0xFBA9, 0x746A, 0xD8A5, 0x746F, 0xD5CB, 0x747E, 0xD0C8, 0x7482, 0xD1AF, 0x7483, 0xD7E3, 0x7487, 0xE0C6, 0x7489, 0xD6A2, + 0x748B, 0xEDF0, 0x7498, 0xD7F3, 0x749C, 0xFCD4, 0x749E, 0xDAD7, 0x749F, 0xCCDF, 0x74A1, 0xF2D4, 0x74A3, 0xD1B0, 0x74A5, 0xCCE0, + 0x74A7, 0xDBFD, 0x74A8, 0xF3BF, 0x74AA, 0xF0D1, 0x74B0, 0xFCBB, 0x74B2, 0xE2B0, 0x74B5, 0xE6A5, 0x74B9, 0xE2DB, 0x74BD, 0xDFDE, + 0x74BF, 0xE0C7, 0x74C6, 0xF2EF, 0x74CA, 0xCCE1, 0x74CF, 0xD6EA, 0x74D4, 0xE7C2, 0x74D8, 0xCEB6, 0x74DA, 0xF3C0, 0x74DC, 0xCDFE, + 0x74E0, 0xFBD2, 0x74E2, 0xF8F8, 0x74E3, 0xF7FB, 0x74E6, 0xE8BF, 0x74EE, 0xE8B7, 0x74F7, 0xEDB6, 0x7501, 0xDCBA, 0x7504, 0xCCB4, + 0x7511, 0xF1F7, 0x7515, 0xE8B8, 0x7518, 0xCAF6, 0x751A, 0xE4A4, 0x751B, 0xF4D6, 0x751F, 0xDFE6, 0x7523, 0xDFA7, 0x7525, 0xDFE7, + 0x7526, 0xE1C1, 0x7528, 0xE9C4, 0x752B, 0xDCCB, 0x752C, 0xE9C5, 0x7530, 0xEFA3, 0x7531, 0xEBA6, 0x7532, 0xCBA3, 0x7533, 0xE3E9, + 0x7537, 0xD1FB, 0x7538, 0xEFA4, 0x753A, 0xEFEB, 0x7547, 0xD0B4, 0x754C, 0xCDA3, 0x754F, 0xE8E6, 0x7551, 0xEFA5, 0x7553, 0xD3CC, + 0x7554, 0xDAED, 0x7559, 0xD7BA, 0x755B, 0xF2D5, 0x755C, 0xF5E5, 0x755D, 0xD9EF, 0x7562, 0xF9B4, 0x7565, 0xD5D4, 0x7566, 0xFDCF, + 0x756A, 0xDBE3, 0x756F, 0xF1E1, 0x7570, 0xECB6, 0x7575, 0xFBFE, 0x7576, 0xD3D7, 0x7578, 0xD1B1, 0x757A, 0xCBB1, 0x757F, 0xD1B2, + 0x7586, 0xCBB2, 0x7587, 0xF1C2, 0x758A, 0xF4E1, 0x758B, 0xF9B5, 0x758E, 0xE1C3, 0x758F, 0xE1C2, 0x7591, 0xEBF7, 0x759D, 0xDFA8, + 0x75A5, 0xCBCA, 0x75AB, 0xE6B9, 0x75B1, 0xF8DE, 0x75B2, 0xF9AA, 0x75B3, 0xCAF7, 0x75B5, 0xEDB7, 0x75B8, 0xD3B8, 0x75B9, 0xF2D6, + 0x75BC, 0xD4D9, 0x75BD, 0xEEC5, 0x75BE, 0xF2F0, 0x75C2, 0xCAB2, 0x75C5, 0xDCBB, 0x75C7, 0xF1F8, 0x75CD, 0xECB7, 0x75D2, 0xE5CA, + 0x75D4, 0xF6C0, 0x75D5, 0xFDDD, 0x75D8, 0xD4E3, 0x75D9, 0xCCE2, 0x75DB, 0xF7D4, 0x75E2, 0xD7E5, 0x75F0, 0xD3C3, 0x75F2, 0xD8A6, + 0x75F4, 0xF6C1, 0x75FA, 0xDDF6, 0x75FC, 0xCDC0, 0x7600, 0xE5DC, 0x760D, 0xE5CB, 0x7619, 0xE1C4, 0x761F, 0xE8B0, 0x7620, 0xF4B0, + 0x7621, 0xF3EA, 0x7622, 0xDAEE, 0x7624, 0xD7BB, 0x7626, 0xE2B1, 0x763B, 0xD7AA, 0x7642, 0xD6FB, 0x764C, 0xE4DF, 0x764E, 0xCAD6, + 0x7652, 0xEBA8, 0x7656, 0xDBFE, 0x7661, 0xF6C2, 0x7664, 0xEFBB, 0x7669, 0xD4FD, 0x766C, 0xE0C8, 0x7670, 0xE8B9, 0x7672, 0xEFA6, + 0x7678, 0xCDA4, 0x767B, 0xD4F4, 0x767C, 0xDBA1, 0x767D, 0xDBDC, 0x767E, 0xDBDD, 0x7684, 0xEEDC, 0x7686, 0xCBCB, 0x7687, 0xFCD5, + 0x768E, 0xCEEB, 0x7690, 0xCDC1, 0x7693, 0xFBD3, 0x76AE, 0xF9AB, 0x76BA, 0xF5D4, 0x76BF, 0xD9A9, 0x76C2, 0xE9DD, 0x76C3, 0xDBCD, + 0x76C6, 0xDDCE, 0x76C8, 0xE7C3, 0x76CA, 0xECCC, 0x76D2, 0xF9EC, 0x76D6, 0xCBCC, 0x76DB, 0xE0FC, 0x76DC, 0xD4A8, 0x76DE, 0xEDD3, + 0x76DF, 0xD8EF, 0x76E1, 0xF2D7, 0x76E3, 0xCAF8, 0x76E4, 0xDAEF, 0x76E7, 0xD6D4, 0x76EE, 0xD9CD, 0x76F2, 0xD8EE, 0x76F4, 0xF2C1, + 0x76F8, 0xDFD3, 0x76FC, 0xDAF0, 0x76FE, 0xE2EA, 0x7701, 0xE0FD, 0x7704, 0xD8F8, 0x7708, 0xF7AF, 0x7709, 0xDAB6, 0x770B, 0xCAD7, + 0x771E, 0xF2D8, 0x7720, 0xD8F9, 0x7729, 0xFADF, 0x7737, 0xCFEF, 0x7738, 0xD9C2, 0x773A, 0xF0D2, 0x773C, 0xE4D1, 0x7740, 0xF3B7, + 0x774D, 0xFAE0, 0x775B, 0xEFEC, 0x7761, 0xE2B2, 0x7763, 0xD4BD, 0x7766, 0xD9CE, 0x776B, 0xF4E2, 0x7779, 0xD4A9, 0x777E, 0xCDC2, + 0x777F, 0xE7DA, 0x778B, 0xF2D9, 0x7791, 0xD9AA, 0x779E, 0xD8BE, 0x77A5, 0xDCAD, 0x77AC, 0xE2EB, 0x77AD, 0xD6FC, 0x77B0, 0xCAF9, + 0x77B3, 0xD4DA, 0x77BB, 0xF4D7, 0x77BC, 0xCCA1, 0x77BF, 0xCFBA, 0x77D7, 0xF5B8, 0x77DB, 0xD9C3, 0x77DC, 0xD0E8, 0x77E2, 0xE3C5, + 0x77E3, 0xEBF8, 0x77E5, 0xF2B1, 0x77E9, 0xCFBB, 0x77ED, 0xD3AD, 0x77EE, 0xE8E1, 0x77EF, 0xCEEC, 0x77F3, 0xE0B4, 0x7802, 0xDEE3, + 0x7812, 0xDDF7, 0x7825, 0xF2B2, 0x7826, 0xF3F6, 0x7827, 0xF6DB, 0x782C, 0xD7FE, 0x7832, 0xF8DF, 0x7834, 0xF7F2, 0x7845, 0xD0A9, + 0x784F, 0xE6DA, 0x785D, 0xF5A6, 0x786B, 0xD7BC, 0x786C, 0xCCE3, 0x786F, 0xE6DB, 0x787C, 0xDDDD, 0x7881, 0xD1B3, 0x7887, 0xEFED, + 0x788C, 0xD6DE, 0x788D, 0xE4F4, 0x788E, 0xE1EF, 0x7891, 0xDDF8, 0x7897, 0xE8CF, 0x78A3, 0xCAE5, 0x78A7, 0xDCA1, 0x78A9, 0xE0B5, + 0x78BA, 0xFCAC, 0x78BB, 0xFCAD, 0x78BC, 0xD8A7, 0x78C1, 0xEDB8, 0x78C5, 0xDBB6, 0x78CA, 0xD6F0, 0x78CB, 0xF3AF, 0x78CE, 0xCDA5, + 0x78D0, 0xDAF1, 0x78E8, 0xD8A8, 0x78EC, 0xCCE4, 0x78EF, 0xD1B4, 0x78F5, 0xCAD8, 0x78FB, 0xDAF2, 0x7901, 0xF5A7, 0x790E, 0xF5A8, + 0x7916, 0xE6A6, 0x792A, 0xD5EC, 0x792B, 0xD5F8, 0x792C, 0xDAF3, 0x793A, 0xE3C6, 0x793E, 0xDEE4, 0x7940, 0xDEE5, 0x7941, 0xD1B5, + 0x7947, 0xD1B6, 0x7948, 0xD1B7, 0x7949, 0xF2B3, 0x7950, 0xE9DE, 0x7956, 0xF0D3, 0x7957, 0xF2B4, 0x795A, 0xF0D4, 0x795B, 0xCBE4, + 0x795C, 0xFBD4, 0x795D, 0xF5E6, 0x795E, 0xE3EA, 0x7960, 0xDEE6, 0x7965, 0xDFD4, 0x7968, 0xF8F9, 0x796D, 0xF0AE, 0x797A, 0xD1B8, + 0x797F, 0xD6DF, 0x7981, 0xD0D7, 0x798D, 0xFCA1, 0x798E, 0xEFEE, 0x798F, 0xDCD8, 0x7991, 0xE9DF, 0x79A6, 0xE5DD, 0x79A7, 0xFDFB, + 0x79AA, 0xE0C9, 0x79AE, 0xD6C9, 0x79B1, 0xD4AA, 0x79B3, 0xE5CC, 0x79B9, 0xE9E0, 0x79BD, 0xD0D8, 0x79BE, 0xFCA2, 0x79BF, 0xD4BE, + 0x79C0, 0xE2B3, 0x79C1, 0xDEE7, 0x79C9, 0xDCBC, 0x79CA, 0xD2B6, 0x79CB, 0xF5D5, 0x79D1, 0xCEA1, 0x79D2, 0xF5A9, 0x79D5, 0xDDF9, + 0x79D8, 0xDDFA, 0x79DF, 0xF0D5, 0x79E4, 0xF6DF, 0x79E6, 0xF2DA, 0x79E7, 0xE4EB, 0x79E9, 0xF2F1, 0x79FB, 0xECB9, 0x7A00, 0xFDFC, + 0x7A05, 0xE1AA, 0x7A08, 0xCAD9, 0x7A0B, 0xEFEF, 0x7A0D, 0xF5AA, 0x7A14, 0xECF9, 0x7A17, 0xF8AD, 0x7A19, 0xF2C2, 0x7A1A, 0xF6C3, + 0x7A1C, 0xD7D2, 0x7A1F, 0xF9A2, 0x7A20, 0xF0D6, 0x7A2E, 0xF0FA, 0x7A31, 0xF6E0, 0x7A36, 0xE9F3, 0x7A37, 0xF2C3, 0x7A3B, 0xD4AB, + 0x7A3C, 0xCAB3, 0x7A3D, 0xCDA6, 0x7A3F, 0xCDC3, 0x7A40, 0xCDDA, 0x7A46, 0xD9CF, 0x7A49, 0xF6C4, 0x7A4D, 0xEEDD, 0x7A4E, 0xE7C4, + 0x7A57, 0xE2B4, 0x7A61, 0xDFE2, 0x7A62, 0xE7DB, 0x7A69, 0xE8B1, 0x7A6B, 0xFCAE, 0x7A70, 0xE5CD, 0x7A74, 0xFAEB, 0x7A76, 0xCFBC, + 0x7A79, 0xCFE2, 0x7A7A, 0xCDF6, 0x7A7D, 0xEFF0, 0x7A7F, 0xF4BE, 0x7A81, 0xD4CD, 0x7A84, 0xF3B8, 0x7A88, 0xE9A1, 0x7A92, 0xF2F2, + 0x7A93, 0xF3EB, 0x7A95, 0xF0D7, 0x7A98, 0xCFD7, 0x7A9F, 0xCFDF, 0x7AA9, 0xE8C0, 0x7AAA, 0xE8C1, 0x7AAE, 0xCFE3, 0x7AAF, 0xE9A2, + 0x7ABA, 0xD0AA, 0x7AC4, 0xF3C1, 0x7AC5, 0xD0AB, 0x7AC7, 0xD4E4, 0x7ACA, 0xEFBC, 0x7ACB, 0xD8A1, 0x7AD7, 0xD9DF, 0x7AD9, 0xF3D7, + 0x7ADD, 0xDCBD, 0x7ADF, 0xCCE5, 0x7AE0, 0xEDF1, 0x7AE3, 0xF1E2, 0x7AE5, 0xD4DB, 0x7AEA, 0xE2B5, 0x7AED, 0xCAE6, 0x7AEF, 0xD3AE, + 0x7AF6, 0xCCE6, 0x7AF9, 0xF1D3, 0x7AFA, 0xF5E7, 0x7AFF, 0xCADA, 0x7B0F, 0xFBEE, 0x7B11, 0xE1C5, 0x7B19, 0xDFE9, 0x7B1B, 0xEEDE, + 0x7B1E, 0xF7C2, 0x7B20, 0xD8A2, 0x7B26, 0xDDAC, 0x7B2C, 0xF0AF, 0x7B2D, 0xD6BD, 0x7B39, 0xE1AB, 0x7B46, 0xF9B6, 0x7B49, 0xD4F5, + 0x7B4B, 0xD0C9, 0x7B4C, 0xEFA7, 0x7B4D, 0xE2EC, 0x7B4F, 0xDBEA, 0x7B50, 0xCECC, 0x7B51, 0xF5E8, 0x7B52, 0xF7D5, 0x7B54, 0xD3CD, + 0x7B56, 0xF3FE, 0x7B60, 0xD0B5, 0x7B6C, 0xE0FE, 0x7B6E, 0xDFFB, 0x7B75, 0xE6DD, 0x7B7D, 0xE8A4, 0x7B87, 0xCBCD, 0x7B8B, 0xEFA8, + 0x7B8F, 0xEEB4, 0x7B94, 0xDAD8, 0x7B95, 0xD1B9, 0x7B97, 0xDFA9, 0x7B9A, 0xF3B0, 0x7B9D, 0xCCC4, 0x7BA1, 0xCEB7, 0x7BAD, 0xEFA9, + 0x7BB1, 0xDFD5, 0x7BB4, 0xEDD7, 0x7BB8, 0xEEC6, 0x7BC0, 0xEFBD, 0x7BC1, 0xFCD6, 0x7BC4, 0xDBF4, 0x7BC6, 0xEFAA, 0x7BC7, 0xF8B9, + 0x7BC9, 0xF5E9, 0x7BD2, 0xE3D9, 0x7BE0, 0xE1C6, 0x7BE4, 0xD4BF, 0x7BE9, 0xDEE8, 0x7C07, 0xF0EA, 0x7C12, 0xF3C2, 0x7C1E, 0xD3AF, + 0x7C21, 0xCADB, 0x7C27, 0xFCD7, 0x7C2A, 0xEDD8, 0x7C2B, 0xE1C7, 0x7C3D, 0xF4D8, 0x7C3E, 0xD6B3, 0x7C3F, 0xDDAD, 0x7C43, 0xD5BE, + 0x7C4C, 0xF1C3, 0x7C4D, 0xEEDF, 0x7C60, 0xD6EB, 0x7C64, 0xF4D9, 0x7C6C, 0xD7E6, 0x7C73, 0xDAB7, 0x7C83, 0xDDFB, 0x7C89, 0xDDCF, + 0x7C92, 0xD8A3, 0x7C95, 0xDAD9, 0x7C97, 0xF0D8, 0x7C98, 0xEFC4, 0x7C9F, 0xE1D8, 0x7CA5, 0xF1D4, 0x7CA7, 0xEDF2, 0x7CAE, 0xD5DB, + 0x7CB1, 0xD5DC, 0x7CB2, 0xF3C4, 0x7CB3, 0xCBD7, 0x7CB9, 0xE2B6, 0x7CBE, 0xEFF1, 0x7CCA, 0xFBD5, 0x7CD6, 0xD3D8, 0x7CDE, 0xDDD0, + 0x7CDF, 0xF0D9, 0x7CE0, 0xCBB3, 0x7CE7, 0xD5DD, 0x7CFB, 0xCDA7, 0x7CFE, 0xD0AC, 0x7D00, 0xD1BA, 0x7D02, 0xF1C4, 0x7D04, 0xE5B3, + 0x7D05, 0xFBF5, 0x7D06, 0xE9E1, 0x7D07, 0xFDE0, 0x7D08, 0xFCBC, 0x7D0A, 0xDAA2, 0x7D0B, 0xDAA3, 0x7D0D, 0xD2A1, 0x7D10, 0xD2EF, + 0x7D14, 0xE2ED, 0x7D17, 0xDEE9, 0x7D18, 0xCEDC, 0x7D19, 0xF2B5, 0x7D1A, 0xD0E4, 0x7D1B, 0xDDD1, 0x7D20, 0xE1C8, 0x7D21, 0xDBB7, + 0x7D22, 0xDFE3, 0x7D2B, 0xEDB9, 0x7D2C, 0xF1C5, 0x7D2E, 0xF3CF, 0x7D2F, 0xD7AB, 0x7D30, 0xE1AC, 0x7D33, 0xE3EB, 0x7D35, 0xEEC7, + 0x7D39, 0xE1C9, 0x7D3A, 0xCAFA, 0x7D42, 0xF0FB, 0x7D43, 0xFAE1, 0x7D44, 0xF0DA, 0x7D45, 0xCCE7, 0x7D46, 0xDAF4, 0x7D50, 0xCCBF, + 0x7D5E, 0xCEED, 0x7D61, 0xD5A9, 0x7D62, 0xFAE2, 0x7D66, 0xD0E5, 0x7D68, 0xEBD6, 0x7D6A, 0xECDF, 0x7D6E, 0xDFFC, 0x7D71, 0xF7D6, + 0x7D72, 0xDEEA, 0x7D73, 0xCBB4, 0x7D76, 0xEFBE, 0x7D79, 0xCCB5, 0x7D7F, 0xCFBD, 0x7D8E, 0xEFF2, 0x7D8F, 0xE2B7, 0x7D93, 0xCCE8, + 0x7D9C, 0xF0FC, 0x7DA0, 0xD6E0, 0x7DA2, 0xF1C6, 0x7DAC, 0xE2B8, 0x7DAD, 0xEBAB, 0x7DB1, 0xCBB5, 0x7DB2, 0xD8D1, 0x7DB4, 0xF4CE, + 0x7DB5, 0xF3F7, 0x7DB8, 0xD7C6, 0x7DBA, 0xD1BB, 0x7DBB, 0xF7AA, 0x7DBD, 0xEDCA, 0x7DBE, 0xD7D3, 0x7DBF, 0xD8FA, 0x7DC7, 0xF6C5, + 0x7DCA, 0xD1CC, 0x7DCB, 0xDDFC, 0x7DD6, 0xDFFD, 0x7DD8, 0xF9E5, 0x7DDA, 0xE0CA, 0x7DDD, 0xF2FD, 0x7DDE, 0xD3B0, 0x7DE0, 0xF4F3, + 0x7DE1, 0xDAC9, 0x7DE3, 0xE6DE, 0x7DE8, 0xF8BA, 0x7DE9, 0xE8D0, 0x7DEC, 0xD8FB, 0x7DEF, 0xEAD5, 0x7DF4, 0xD6A3, 0x7DFB, 0xF6C6, + 0x7E09, 0xF2DB, 0x7E0A, 0xE4FC, 0x7E15, 0xE8B2, 0x7E1B, 0xDADA, 0x7E1D, 0xF2DC, 0x7E1E, 0xFBD6, 0x7E1F, 0xE9B2, 0x7E21, 0xEEAD, + 0x7E23, 0xFAE3, 0x7E2B, 0xDCEE, 0x7E2E, 0xF5EA, 0x7E2F, 0xE6E0, 0x7E31, 0xF0FD, 0x7E37, 0xD7AC, 0x7E3D, 0xF5C5, 0x7E3E, 0xEEE0, + 0x7E41, 0xDBE5, 0x7E43, 0xDDDE, 0x7E46, 0xD9F0, 0x7E47, 0xE9A3, 0x7E52, 0xF1F9, 0x7E54, 0xF2C4, 0x7E55, 0xE0CB, 0x7E5E, 0xE9A4, + 0x7E61, 0xE2B9, 0x7E69, 0xE3B1, 0x7E6A, 0xFCEB, 0x7E6B, 0xCDA8, 0x7E6D, 0xCCB6, 0x7E70, 0xF0DB, 0x7E79, 0xE6BA, 0x7E7C, 0xCDA9, + 0x7E82, 0xF3C3, 0x7E8C, 0xE1D9, 0x7E8F, 0xEFAB, 0x7E93, 0xE7C5, 0x7E96, 0xE0E9, 0x7E98, 0xF3C5, 0x7E9B, 0xD4C0, 0x7E9C, 0xD5BF, + 0x7F36, 0xDDAE, 0x7F38, 0xF9FC, 0x7F3A, 0xCCC0, 0x7F4C, 0xE5A2, 0x7F50, 0xCEB8, 0x7F54, 0xD8D2, 0x7F55, 0xF9D6, 0x7F6A, 0xF1AA, + 0x7F6B, 0xCED1, 0x7F6E, 0xF6C7, 0x7F70, 0xDBEB, 0x7F72, 0xDFFE, 0x7F75, 0xD8E1, 0x7F77, 0xF7F3, 0x7F79, 0xD7E7, 0x7F85, 0xD4FE, + 0x7F88, 0xD1BC, 0x7F8A, 0xE5CF, 0x7F8C, 0xCBB6, 0x7F8E, 0xDAB8, 0x7F94, 0xCDC4, 0x7F9A, 0xD6BE, 0x7F9E, 0xE2BA, 0x7FA4, 0xCFD8, + 0x7FA8, 0xE0CC, 0x7FA9, 0xEBF9, 0x7FB2, 0xFDFD, 0x7FB8, 0xD7E8, 0x7FB9, 0xCBD8, 0x7FBD, 0xE9E2, 0x7FC1, 0xE8BA, 0x7FC5, 0xE3C7, + 0x7FCA, 0xECCD, 0x7FCC, 0xECCE, 0x7FCE, 0xD6BF, 0x7FD2, 0xE3A7, 0x7FD4, 0xDFD6, 0x7FD5, 0xFDE8, 0x7FDF, 0xEEE1, 0x7FE0, 0xF6A8, + 0x7FE1, 0xDDFD, 0x7FE9, 0xF8BB, 0x7FEB, 0xE8D1, 0x7FF0, 0xF9D7, 0x7FF9, 0xCEEE, 0x7FFC, 0xECCF, 0x8000, 0xE9A5, 0x8001, 0xD6D5, + 0x8003, 0xCDC5, 0x8005, 0xEDBA, 0x8006, 0xD1BD, 0x8009, 0xCFBE, 0x800C, 0xECBB, 0x8010, 0xD2B1, 0x8015, 0xCCE9, 0x8017, 0xD9C4, + 0x8018, 0xE9FC, 0x802D, 0xD1BE, 0x8033, 0xECBC, 0x8036, 0xE5AD, 0x803D, 0xF7B0, 0x803F, 0xCCEA, 0x8043, 0xD3C4, 0x8046, 0xD6C0, + 0x804A, 0xD6FD, 0x8056, 0xE1A1, 0x8058, 0xDEBD, 0x805A, 0xF6A9, 0x805E, 0xDAA4, 0x806F, 0xD6A4, 0x8070, 0xF5C6, 0x8072, 0xE1A2, + 0x8073, 0xE9C6, 0x8077, 0xF2C5, 0x807D, 0xF4E9, 0x807E, 0xD6EC, 0x807F, 0xEBD3, 0x8084, 0xECBD, 0x8085, 0xE2DC, 0x8086, 0xDEEB, + 0x8087, 0xF0DC, 0x8089, 0xEBBF, 0x808B, 0xD7CE, 0x808C, 0xD1BF, 0x8096, 0xF5AB, 0x809B, 0xF9FD, 0x809D, 0xCADC, 0x80A1, 0xCDC6, + 0x80A2, 0xF2B6, 0x80A5, 0xDDFE, 0x80A9, 0xCCB7, 0x80AA, 0xDBB8, 0x80AF, 0xD0E9, 0x80B1, 0xCEDD, 0x80B2, 0xEBC0, 0x80B4, 0xFDA2, + 0x80BA, 0xF8CB, 0x80C3, 0xEAD6, 0x80C4, 0xF1B0, 0x80CC, 0xDBCE, 0x80CE, 0xF7C3, 0x80DA, 0xDBCF, 0x80DB, 0xCBA4, 0x80DE, 0xF8E0, + 0x80E1, 0xFBD7, 0x80E4, 0xEBCA, 0x80E5, 0xE0A1, 0x80F1, 0xCECD, 0x80F4, 0xD4DC, 0x80F8, 0xFDD8, 0x80FD, 0xD2F6, 0x8102, 0xF2B7, + 0x8105, 0xFAF6, 0x8106, 0xF6AA, 0x8107, 0xFAF7, 0x8108, 0xD8E6, 0x810A, 0xF4B1, 0x8118, 0xE8D2, 0x811A, 0xCAC5, 0x811B, 0xCCEB, + 0x8123, 0xE2EE, 0x8129, 0xE2BB, 0x812B, 0xF7AD, 0x812F, 0xF8E1, 0x8139, 0xF3EC, 0x813E, 0xDEA1, 0x814B, 0xE4FD, 0x814E, 0xE3EC, + 0x8150, 0xDDAF, 0x8151, 0xDDB0, 0x8154, 0xCBB7, 0x8155, 0xE8D3, 0x8165, 0xE1A3, 0x8166, 0xD2E0, 0x816B, 0xF0FE, 0x8170, 0xE9A6, + 0x8171, 0xCBF2, 0x8178, 0xEDF3, 0x8179, 0xDCD9, 0x817A, 0xE0CD, 0x817F, 0xF7DA, 0x8180, 0xDBB9, 0x8188, 0xCCAE, 0x818A, 0xDADB, + 0x818F, 0xCDC7, 0x819A, 0xDDB1, 0x819C, 0xD8AF, 0x819D, 0xE3A3, 0x81A0, 0xCEEF, 0x81A3, 0xF2F3, 0x81A8, 0xF8B3, 0x81B3, 0xE0CE, + 0x81B5, 0xF5FD, 0x81BA, 0xEBEC, 0x81BD, 0xD3C5, 0x81BE, 0xFCEC, 0x81BF, 0xD2DB, 0x81C0, 0xD4EB, 0x81C2, 0xDEA2, 0x81C6, 0xE5E6, + 0x81CD, 0xF0B0, 0x81D8, 0xD5C4, 0x81DF, 0xEDF4, 0x81E3, 0xE3ED, 0x81E5, 0xE8C2, 0x81E7, 0xEDF5, 0x81E8, 0xD7FC, 0x81EA, 0xEDBB, + 0x81ED, 0xF6AB, 0x81F3, 0xF2B8, 0x81F4, 0xF6C8, 0x81FA, 0xD3E6, 0x81FB, 0xF2DD, 0x81FC, 0xCFBF, 0x81FE, 0xEBAC, 0x8205, 0xCFC0, + 0x8207, 0xE6A8, 0x8208, 0xFDE9, 0x820A, 0xCFC1, 0x820C, 0xE0DF, 0x820D, 0xDEEC, 0x8212, 0xE0A2, 0x821B, 0xF4BF, 0x821C, 0xE2EF, + 0x821E, 0xD9F1, 0x821F, 0xF1C7, 0x8221, 0xCBB8, 0x822A, 0xF9FE, 0x822B, 0xDBBA, 0x822C, 0xDAF5, 0x8235, 0xF6EC, 0x8236, 0xDADC, + 0x8237, 0xFAE4, 0x8239, 0xE0CF, 0x8240, 0xDDB2, 0x8245, 0xE6A9, 0x8247, 0xEFF3, 0x8259, 0xF3ED, 0x8264, 0xEBFA, 0x8266, 0xF9E6, + 0x826E, 0xCADD, 0x826F, 0xD5DE, 0x8271, 0xCADE, 0x8272, 0xDFE4, 0x8276, 0xE6FD, 0x8278, 0xF5AC, 0x827E, 0xE4F5, 0x828B, 0xE9E3, + 0x828D, 0xEDCB, 0x828E, 0xCFE4, 0x8292, 0xD8D3, 0x8299, 0xDDB3, 0x829A, 0xD4EC, 0x829D, 0xF2B9, 0x829F, 0xDFB7, 0x82A5, 0xCBCE, + 0x82A6, 0xFBD8, 0x82A9, 0xD0D9, 0x82AC, 0xDDD2, 0x82AD, 0xF7F4, 0x82AE, 0xE7DC, 0x82AF, 0xE4A5, 0x82B1, 0xFCA3, 0x82B3, 0xDBBB, + 0x82B7, 0xF2BA, 0x82B8, 0xE9FD, 0x82B9, 0xD0CA, 0x82BB, 0xF5D6, 0x82BC, 0xD9C5, 0x82BD, 0xE4B4, 0x82BF, 0xEDA7, 0x82D1, 0xEABD, + 0x82D2, 0xE6FE, 0x82D4, 0xF7C4, 0x82D5, 0xF5AD, 0x82D7, 0xD9E0, 0x82DB, 0xCAB4, 0x82DE, 0xF8E2, 0x82DF, 0xCFC2, 0x82E1, 0xECBE, + 0x82E5, 0xE5B4, 0x82E6, 0xCDC8, 0x82E7, 0xEEC8, 0x82F1, 0xE7C8, 0x82FD, 0xCDC9, 0x82FE, 0xF9B7, 0x8301, 0xF1E8, 0x8302, 0xD9F2, + 0x8303, 0xDBF5, 0x8304, 0xCAB5, 0x8305, 0xD9C6, 0x8309, 0xD8C9, 0x8317, 0xD9AB, 0x8328, 0xEDBC, 0x832B, 0xD8D4, 0x832F, 0xDCDA, + 0x8331, 0xE2BC, 0x8334, 0xFCED, 0x8335, 0xECE0, 0x8336, 0xD2FE, 0x8338, 0xE9C7, 0x8339, 0xE6AA, 0x8340, 0xE2F0, 0x8347, 0xFABB, + 0x8349, 0xF5AE, 0x834A, 0xFBAA, 0x834F, 0xECFB, 0x8351, 0xECBF, 0x8352, 0xFCD8, 0x8373, 0xD4E5, 0x8377, 0xF9C3, 0x837B, 0xEEE2, + 0x8389, 0xD7E9, 0x838A, 0xEDF6, 0x838E, 0xDEED, 0x8396, 0xCCEC, 0x8398, 0xE3EE, 0x839E, 0xE8D4, 0x83A2, 0xFAF8, 0x83A9, 0xDDB4, + 0x83AA, 0xE4B5, 0x83AB, 0xD8B0, 0x83BD, 0xD8D5, 0x83C1, 0xF4EA, 0x83C5, 0xCEB9, 0x83C9, 0xD6E1, 0x83CA, 0xCFD2, 0x83CC, 0xD0B6, + 0x83D3, 0xCEA2, 0x83D6, 0xF3EE, 0x83DC, 0xF3F8, 0x83E9, 0xDCCC, 0x83EB, 0xD0CB, 0x83EF, 0xFCA4, 0x83F0, 0xCDCA, 0x83F1, 0xD7D4, + 0x83F2, 0xDEA3, 0x83F4, 0xE4E0, 0x83F9, 0xEEC9, 0x83FD, 0xE2DD, 0x8403, 0xF5FE, 0x8404, 0xD4AC, 0x840A, 0xD5D1, 0x840C, 0xD8F0, + 0x840D, 0xF8C3, 0x840E, 0xEAD7, 0x8429, 0xF5D7, 0x842C, 0xD8BF, 0x8431, 0xFDC0, 0x8438, 0xEBAD, 0x843D, 0xD5AA, 0x8449, 0xE7A8, + 0x8457, 0xEECA, 0x845B, 0xCAE7, 0x8461, 0xF8E3, 0x8463, 0xD4DD, 0x8466, 0xEAD8, 0x846B, 0xFBD9, 0x846C, 0xEDF7, 0x846F, 0xE5B5, + 0x8475, 0xD0AD, 0x847A, 0xF1F1, 0x8490, 0xE2BD, 0x8494, 0xE3C8, 0x8499, 0xD9D5, 0x849C, 0xDFAA, 0x84A1, 0xDBBC, 0x84B2, 0xF8E4, + 0x84B8, 0xF1FA, 0x84BB, 0xE5B6, 0x84BC, 0xF3EF, 0x84BF, 0xFBDA, 0x84C0, 0xE1E0, 0x84C2, 0xD9AC, 0x84C4, 0xF5EB, 0x84C6, 0xE0B6, + 0x84C9, 0xE9C8, 0x84CB, 0xCBCF, 0x84CD, 0xE3C9, 0x84D1, 0xDEEE, 0x84DA, 0xE2BE, 0x84EC, 0xDCEF, 0x84EE, 0xD6A5, 0x84F4, 0xE2F1, + 0x84FC, 0xD6FE, 0x8511, 0xD9A1, 0x8513, 0xD8C0, 0x8514, 0xDCDB, 0x8517, 0xEDBD, 0x8518, 0xDFB8, 0x851A, 0xEAA5, 0x851E, 0xD7AD, + 0x8521, 0xF3F9, 0x8523, 0xEDF8, 0x8525, 0xF5C7, 0x852C, 0xE1CA, 0x852D, 0xEBE3, 0x852F, 0xF2DE, 0x853D, 0xF8CC, 0x853F, 0xEAD9, + 0x8541, 0xD3C6, 0x8543, 0xDBE6, 0x8549, 0xF5AF, 0x854E, 0xCEF0, 0x8553, 0xE9FE, 0x8559, 0xFBB6, 0x8563, 0xE2F2, 0x8568, 0xCFF2, + 0x8569, 0xF7B9, 0x856A, 0xD9F3, 0x856D, 0xE1CB, 0x8584, 0xDADD, 0x8587, 0xDAB9, 0x858F, 0xEBFB, 0x8591, 0xCBB9, 0x8594, 0xEDF9, + 0x859B, 0xE0E0, 0x85A6, 0xF4C0, 0x85A8, 0xFDBC, 0x85A9, 0xDFB1, 0x85AA, 0xE3EF, 0x85AF, 0xE0A3, 0x85B0, 0xFDB9, 0x85BA, 0xF0B1, + 0x85C1, 0xCDCB, 0x85C9, 0xEDBE, 0x85CD, 0xD5C0, 0x85CE, 0xE3F0, 0x85CF, 0xEDFA, 0x85D5, 0xE9E4, 0x85DC, 0xD5ED, 0x85DD, 0xE7DD, + 0x85E4, 0xD4F6, 0x85E5, 0xE5B7, 0x85E9, 0xDBE7, 0x85EA, 0xE2BF, 0x85F7, 0xEECB, 0x85FA, 0xD7F4, 0x85FB, 0xF0DD, 0x85FF, 0xCEAB, + 0x8602, 0xE7DE, 0x8606, 0xD6D6, 0x8607, 0xE1CC, 0x860A, 0xE8B3, 0x8616, 0xE5EE, 0x8617, 0xDCA2, 0x861A, 0xE0D0, 0x862D, 0xD5B5, + 0x863F, 0xD5A1, 0x864E, 0xFBDB, 0x8650, 0xF9CB, 0x8654, 0xCBF3, 0x8655, 0xF4A5, 0x865B, 0xFAC8, 0x865C, 0xD6D7, 0x865E, 0xE9E5, + 0x865F, 0xFBDC, 0x8667, 0xFDD0, 0x8679, 0xFBF6, 0x868A, 0xDAA5, 0x868C, 0xDBBD, 0x8693, 0xECE2, 0x86A3, 0xCDF7, 0x86A4, 0xF0DE, + 0x86A9, 0xF6C9, 0x86C7, 0xDEEF, 0x86CB, 0xD3B1, 0x86D4, 0xFCEE, 0x86D9, 0xE8C3, 0x86DB, 0xF1C8, 0x86DF, 0xCEF1, 0x86E4, 0xF9ED, + 0x86ED, 0xF2F4, 0x86FE, 0xE4B6, 0x8700, 0xF5B9, 0x8702, 0xDCF0, 0x8703, 0xE3F1, 0x8708, 0xE8A5, 0x8718, 0xF2BB, 0x871A, 0xDEA4, + 0x871C, 0xDACC, 0x874E, 0xCAE9, 0x8755, 0xE3DA, 0x8757, 0xFCD9, 0x875F, 0xEADA, 0x8766, 0xF9C4, 0x8768, 0xE3A4, 0x8774, 0xFBDD, + 0x8776, 0xEFCA, 0x8778, 0xE8C4, 0x8782, 0xD5CC, 0x878D, 0xEBD7, 0x879F, 0xD9AD, 0x87A2, 0xFBAB, 0x87B3, 0xD3D9, 0x87BA, 0xD5A2, + 0x87C4, 0xF6DE, 0x87E0, 0xDAF6, 0x87EC, 0xE0D1, 0x87EF, 0xE9A8, 0x87F2, 0xF5F9, 0x87F9, 0xFAAF, 0x87FB, 0xEBFC, 0x87FE, 0xE0EA, + 0x8805, 0xE3B2, 0x881F, 0xD5C5, 0x8822, 0xF1E3, 0x8823, 0xD5EE, 0x8831, 0xCDCC, 0x8836, 0xEDD9, 0x883B, 0xD8C1, 0x8840, 0xFAEC, + 0x8846, 0xF1EB, 0x884C, 0xFABC, 0x884D, 0xE6E2, 0x8852, 0xFAE5, 0x8853, 0xE2FA, 0x8857, 0xCAB6, 0x8859, 0xE4B7, 0x885B, 0xEADB, + 0x885D, 0xF5FA, 0x8861, 0xFBAC, 0x8862, 0xCFC3, 0x8863, 0xEBFD, 0x8868, 0xF8FA, 0x886B, 0xDFB9, 0x8870, 0xE1F1, 0x8872, 0xD2A4, + 0x8877, 0xF5FB, 0x887E, 0xD0DA, 0x887F, 0xD0DB, 0x8881, 0xEABE, 0x8882, 0xD9B1, 0x8888, 0xCAB7, 0x888B, 0xD3E7, 0x888D, 0xF8E5, + 0x8892, 0xD3B2, 0x8896, 0xE2C0, 0x8897, 0xF2DF, 0x889E, 0xCDE5, 0x88AB, 0xF9AC, 0x88B4, 0xCDCD, 0x88C1, 0xEEAE, 0x88C2, 0xD6AE, + 0x88CF, 0xD7EA, 0x88D4, 0xE7E0, 0x88D5, 0xEBAE, 0x88D9, 0xCFD9, 0x88DC, 0xDCCD, 0x88DD, 0xEDFB, 0x88DF, 0xDEF0, 0x88E1, 0xD7EB, + 0x88E8, 0xDEA5, 0x88F3, 0xDFD7, 0x88F4, 0xDBD0, 0x88F5, 0xDBD1, 0x88F8, 0xD5A3, 0x88FD, 0xF0B2, 0x8907, 0xDCDC, 0x8910, 0xCAE8, + 0x8912, 0xF8E6, 0x8913, 0xDCCE, 0x8918, 0xEADC, 0x8919, 0xDBD2, 0x8925, 0xE9B3, 0x892A, 0xF7DB, 0x8936, 0xE3A8, 0x8938, 0xD7AE, + 0x893B, 0xE0E1, 0x8941, 0xCBBA, 0x8944, 0xE5D1, 0x895F, 0xD0DC, 0x8964, 0xD5C1, 0x896A, 0xD8CA, 0x8972, 0xE3A9, 0x897F, 0xE0A4, + 0x8981, 0xE9A9, 0x8983, 0xD3C7, 0x8986, 0xDCDD, 0x8987, 0xF8AE, 0x898B, 0xCCB8, 0x898F, 0xD0AE, 0x8993, 0xD8F2, 0x8996, 0xE3CA, + 0x89A1, 0xCCAF, 0x89A9, 0xD4AD, 0x89AA, 0xF6D1, 0x89B2, 0xD0CC, 0x89BA, 0xCAC6, 0x89BD, 0xD5C2, 0x89C0, 0xCEBA, 0x89D2, 0xCAC7, + 0x89E3, 0xFAB0, 0x89F4, 0xDFD8, 0x89F8, 0xF5BA, 0x8A00, 0xE5EB, 0x8A02, 0xEFF4, 0x8A03, 0xDDB5, 0x8A08, 0xCDAA, 0x8A0A, 0xE3F2, + 0x8A0C, 0xFBF7, 0x8A0E, 0xF7D0, 0x8A13, 0xFDBA, 0x8A16, 0xFDE1, 0x8A17, 0xF6FE, 0x8A18, 0xD1C0, 0x8A1B, 0xE8C5, 0x8A1D, 0xE4B8, + 0x8A1F, 0xE1E8, 0x8A23, 0xCCC1, 0x8A25, 0xD2ED, 0x8A2A, 0xDBBE, 0x8A2D, 0xE0E2, 0x8A31, 0xFAC9, 0x8A34, 0xE1CD, 0x8A36, 0xCAB8, + 0x8A3A, 0xF2E0, 0x8A3B, 0xF1C9, 0x8A50, 0xDEF1, 0x8A54, 0xF0DF, 0x8A55, 0xF8C4, 0x8A5B, 0xEECC, 0x8A5E, 0xDEF2, 0x8A60, 0xE7C9, + 0x8A62, 0xE2F3, 0x8A63, 0xE7E1, 0x8A66, 0xE3CB, 0x8A69, 0xE3CC, 0x8A6D, 0xCFF8, 0x8A6E, 0xEFAC, 0x8A70, 0xFDFE, 0x8A71, 0xFCA5, + 0x8A72, 0xFAB1, 0x8A73, 0xDFD9, 0x8A75, 0xE0D2, 0x8A79, 0xF4DA, 0x8A85, 0xF1CA, 0x8A87, 0xCEA3, 0x8A8C, 0xF2BC, 0x8A8D, 0xECE3, + 0x8A93, 0xE0A5, 0x8A95, 0xF7AB, 0x8A98, 0xEBAF, 0x8A9E, 0xE5DE, 0x8AA0, 0xE1A4, 0x8AA1, 0xCDAB, 0x8AA3, 0xD9F4, 0x8AA4, 0xE8A6, + 0x8AA5, 0xCDCE, 0x8AA6, 0xE1E9, 0x8AA8, 0xFCEF, 0x8AAA, 0xE0E3, 0x8AB0, 0xE2C1, 0x8AB2, 0xCEA4, 0x8AB9, 0xDEA6, 0x8ABC, 0xEBFE, + 0x8ABE, 0xEBDD, 0x8ABF, 0xF0E0, 0x8AC2, 0xF4DB, 0x8AC4, 0xE2F4, 0x8AC7, 0xD3C8, 0x8ACB, 0xF4EB, 0x8ACD, 0xEEB5, 0x8ACF, 0xF5D8, + 0x8AD2, 0xD5DF, 0x8AD6, 0xD6E5, 0x8ADB, 0xEBB0, 0x8ADC, 0xF4E3, 0x8AE1, 0xE3CD, 0x8AE6, 0xF4F4, 0x8AE7, 0xFAB2, 0x8AEA, 0xEFF5, + 0x8AEB, 0xCADF, 0x8AED, 0xEBB1, 0x8AEE, 0xEDBF, 0x8AF1, 0xFDC9, 0x8AF6, 0xE4A6, 0x8AF7, 0xF9A4, 0x8AF8, 0xF0B3, 0x8AFA, 0xE5EC, + 0x8AFE, 0xD1E7, 0x8B00, 0xD9C7, 0x8B01, 0xE4D7, 0x8B02, 0xEADD, 0x8B04, 0xD4F7, 0x8B0E, 0xDABA, 0x8B10, 0xDACD, 0x8B14, 0xF9CC, + 0x8B16, 0xE1DA, 0x8B17, 0xDBBF, 0x8B19, 0xCCC5, 0x8B1A, 0xECD0, 0x8B1B, 0xCBBB, 0x8B1D, 0xDEF3, 0x8B20, 0xE9AA, 0x8B28, 0xD9C8, + 0x8B2B, 0xEEE3, 0x8B2C, 0xD7BD, 0x8B33, 0xCFC4, 0x8B39, 0xD0CD, 0x8B41, 0xFCA6, 0x8B49, 0xF1FB, 0x8B4E, 0xFDD2, 0x8B4F, 0xD1C1, + 0x8B58, 0xE3DB, 0x8B5A, 0xD3C9, 0x8B5C, 0xDCCF, 0x8B66, 0xCCED, 0x8B6C, 0xDEA7, 0x8B6F, 0xE6BB, 0x8B70, 0xECA1, 0x8B74, 0xCCB9, + 0x8B77, 0xFBDE, 0x8B7D, 0xE7E2, 0x8B80, 0xD4C1, 0x8B8A, 0xDCA8, 0x8B90, 0xE2C2, 0x8B92, 0xF3D8, 0x8B93, 0xE5D3, 0x8B96, 0xF3D9, + 0x8B9A, 0xF3C6, 0x8C37, 0xCDDB, 0x8C3F, 0xCDAC, 0x8C41, 0xFCC3, 0x8C46, 0xD4E7, 0x8C48, 0xD1C2, 0x8C4A, 0xF9A5, 0x8C4C, 0xE8D5, + 0x8C55, 0xE3CE, 0x8C5A, 0xD4CA, 0x8C61, 0xDFDA, 0x8C6A, 0xFBDF, 0x8C6B, 0xE7E3, 0x8C79, 0xF8FB, 0x8C7A, 0xE3CF, 0x8C82, 0xF5B0, + 0x8C8A, 0xD8E7, 0x8C8C, 0xD9C9, 0x8C9D, 0xF8AF, 0x8C9E, 0xEFF6, 0x8CA0, 0xDDB6, 0x8CA1, 0xEEAF, 0x8CA2, 0xCDF8, 0x8CA7, 0xDEB8, + 0x8CA8, 0xFCA7, 0x8CA9, 0xF7FC, 0x8CAA, 0xF7B1, 0x8CAB, 0xCEBB, 0x8CAC, 0xF4A1, 0x8CAF, 0xEECD, 0x8CB0, 0xE1AE, 0x8CB3, 0xECC3, + 0x8CB4, 0xCFFE, 0x8CB6, 0xF8BF, 0x8CB7, 0xD8E2, 0x8CB8, 0xD3E8, 0x8CBB, 0xDEA8, 0x8CBC, 0xF4E4, 0x8CBD, 0xECC2, 0x8CBF, 0xD9F5, + 0x8CC0, 0xF9C5, 0x8CC1, 0xDDD3, 0x8CC2, 0xD6F1, 0x8CC3, 0xECFC, 0x8CC4, 0xFCF0, 0x8CC7, 0xEDC0, 0x8CC8, 0xCAB9, 0x8CCA, 0xEEE4, + 0x8CD1, 0xF2E1, 0x8CD3, 0xDEB9, 0x8CDA, 0xD6F2, 0x8CDC, 0xDEF4, 0x8CDE, 0xDFDB, 0x8CE0, 0xDBD3, 0x8CE2, 0xFAE7, 0x8CE3, 0xD8E3, + 0x8CE4, 0xF4C1, 0x8CE6, 0xDDB7, 0x8CEA, 0xF2F5, 0x8CED, 0xD4AE, 0x8CF4, 0xD6F3, 0x8CFB, 0xDDB8, 0x8CFC, 0xCFC5, 0x8CFD, 0xDFDF, + 0x8D04, 0xF2BE, 0x8D05, 0xF6A1, 0x8D07, 0xEBCB, 0x8D08, 0xF1FC, 0x8D0A, 0xF3C7, 0x8D0D, 0xE0EB, 0x8D13, 0xEDFC, 0x8D16, 0xE1DB, + 0x8D64, 0xEEE5, 0x8D66, 0xDEF5, 0x8D6B, 0xFAD3, 0x8D70, 0xF1CB, 0x8D73, 0xD0AF, 0x8D74, 0xDDB9, 0x8D77, 0xD1C3, 0x8D85, 0xF5B1, + 0x8D8A, 0xEAC6, 0x8D99, 0xF0E1, 0x8DA3, 0xF6AC, 0x8DA8, 0xF5D9, 0x8DB3, 0xF0EB, 0x8DBA, 0xDDBA, 0x8DBE, 0xF2BF, 0x8DC6, 0xF7C5, + 0x8DCB, 0xDBA2, 0x8DCC, 0xF2F6, 0x8DCF, 0xCABA, 0x8DDB, 0xF7F5, 0x8DDD, 0xCBE5, 0x8DE1, 0xEEE6, 0x8DE3, 0xE0D3, 0x8DE8, 0xCEA5, + 0x8DEF, 0xD6D8, 0x8DF3, 0xD4AF, 0x8E0A, 0xE9C9, 0x8E0F, 0xD3CE, 0x8E10, 0xF4C2, 0x8E1E, 0xCBE6, 0x8E2A, 0xF1A1, 0x8E30, 0xEBB2, + 0x8E35, 0xF1A2, 0x8E42, 0xEBB3, 0x8E44, 0xF0B4, 0x8E47, 0xCBF4, 0x8E48, 0xD4B0, 0x8E49, 0xF3B2, 0x8E4A, 0xFBB7, 0x8E59, 0xF5EC, + 0x8E5F, 0xEEE7, 0x8E60, 0xF4B2, 0x8E74, 0xF5ED, 0x8E76, 0xCFF3, 0x8E81, 0xF0E2, 0x8E87, 0xEECE, 0x8E8A, 0xF1CC, 0x8E8D, 0xE5B8, + 0x8EAA, 0xD7F5, 0x8EAB, 0xE3F3, 0x8EAC, 0xCFE5, 0x8EC0, 0xCFC6, 0x8ECA, 0xF3B3, 0x8ECB, 0xE4D8, 0x8ECC, 0xCFF9, 0x8ECD, 0xCFDA, + 0x8ED2, 0xFACD, 0x8EDF, 0xE6E3, 0x8EEB, 0xF2E2, 0x8EF8, 0xF5EE, 0x8EFB, 0xCABB, 0x8EFE, 0xE3DC, 0x8F03, 0xCEF2, 0x8F05, 0xD6D9, + 0x8F09, 0xEEB0, 0x8F12, 0xF4E5, 0x8F13, 0xD8C2, 0x8F14, 0xDCD0, 0x8F15, 0xCCEE, 0x8F1B, 0xD5E0, 0x8F1C, 0xF6CA, 0x8F1D, 0xFDCA, + 0x8F1E, 0xD8D6, 0x8F1F, 0xF4CF, 0x8F26, 0xD6A6, 0x8F27, 0xDCBE, 0x8F29, 0xDBD4, 0x8F2A, 0xD7C7, 0x8F2F, 0xF2FE, 0x8F33, 0xF1CD, + 0x8F38, 0xE2C3, 0x8F39, 0xDCDE, 0x8F3B, 0xDCDF, 0x8F3E, 0xEFAD, 0x8F3F, 0xE6AB, 0x8F44, 0xF9DD, 0x8F45, 0xEABF, 0x8F49, 0xEFAE, + 0x8F4D, 0xF4D0, 0x8F4E, 0xCEF3, 0x8F5D, 0xE6AC, 0x8F5F, 0xCEDE, 0x8F62, 0xD5F9, 0x8F9B, 0xE3F4, 0x8F9C, 0xCDD0, 0x8FA3, 0xD5B8, + 0x8FA6, 0xF7FD, 0x8FA8, 0xDCA9, 0x8FAD, 0xDEF6, 0x8FAF, 0xDCAA, 0x8FB0, 0xF2E3, 0x8FB1, 0xE9B4, 0x8FB2, 0xD2DC, 0x8FC2, 0xE9E6, + 0x8FC5, 0xE3F6, 0x8FCE, 0xE7CA, 0x8FD1, 0xD0CE, 0x8FD4, 0xDAF7, 0x8FE6, 0xCABC, 0x8FEA, 0xEEE8, 0x8FEB, 0xDADE, 0x8FED, 0xF2F7, + 0x8FF0, 0xE2FB, 0x8FF2, 0xCCA6, 0x8FF7, 0xDABB, 0x8FF9, 0xEEE9, 0x8FFD, 0xF5DA, 0x9000, 0xF7DC, 0x9001, 0xE1EA, 0x9002, 0xCEC1, + 0x9003, 0xD4B1, 0x9005, 0xFDB1, 0x9006, 0xE6BD, 0x9008, 0xFBAD, 0x900B, 0xF8E7, 0x900D, 0xE1CE, 0x900F, 0xF7E2, 0x9010, 0xF5EF, + 0x9011, 0xCFC7, 0x9014, 0xD4B2, 0x9015, 0xCCEF, 0x9017, 0xD4E8, 0x9019, 0xEECF, 0x901A, 0xF7D7, 0x901D, 0xE0A6, 0x901E, 0xD6C1, + 0x901F, 0xE1DC, 0x9020, 0xF0E3, 0x9021, 0xF1E4, 0x9022, 0xDCF1, 0x9023, 0xD6A7, 0x902E, 0xF4F5, 0x9031, 0xF1CE, 0x9032, 0xF2E4, + 0x9035, 0xD0B0, 0x9038, 0xECEF, 0x903C, 0xF9BA, 0x903E, 0xEBB5, 0x9041, 0xD4ED, 0x9042, 0xE2C4, 0x9047, 0xE9E7, 0x904A, 0xEBB4, + 0x904B, 0xEAA1, 0x904D, 0xF8BC, 0x904E, 0xCEA6, 0x9050, 0xF9C6, 0x9051, 0xFCDA, 0x9053, 0xD4B3, 0x9054, 0xD3B9, 0x9055, 0xEADE, + 0x9059, 0xE9AB, 0x905C, 0xE1E1, 0x905D, 0xD3CF, 0x905E, 0xF4F6, 0x9060, 0xEAC0, 0x9061, 0xE1CF, 0x9063, 0xCCBA, 0x9069, 0xEEEA, + 0x906D, 0xF0E4, 0x906E, 0xF3B4, 0x906F, 0xD4EE, 0x9072, 0xF2C0, 0x9075, 0xF1E5, 0x9077, 0xF4C3, 0x9078, 0xE0D4, 0x907A, 0xEBB6, + 0x907C, 0xD7A1, 0x907D, 0xCBE8, 0x907F, 0xF9AD, 0x9080, 0xE9AD, 0x9081, 0xD8E4, 0x9082, 0xFAB3, 0x9083, 0xE2C5, 0x9084, 0xFCBD, + 0x9087, 0xECC4, 0x9088, 0xD8B1, 0x908A, 0xDCAB, 0x908F, 0xD5A4, 0x9091, 0xEBE9, 0x9095, 0xE8BB, 0x9099, 0xD8D7, 0x90A2, 0xFBAE, + 0x90A3, 0xD1E1, 0x90A6, 0xDBC0, 0x90A8, 0xF5BE, 0x90AA, 0xDEF7, 0x90AF, 0xCAFB, 0x90B0, 0xF7C6, 0x90B1, 0xCFC8, 0x90B5, 0xE1D0, + 0x90B8, 0xEED0, 0x90C1, 0xE9F4, 0x90CA, 0xCEF4, 0x90DE, 0xD5CD, 0x90E1, 0xCFDB, 0x90E8, 0xDDBB, 0x90ED, 0xCEAC, 0x90F5, 0xE9E8, + 0x90FD, 0xD4B4, 0x9102, 0xE4C7, 0x9112, 0xF5DB, 0x9115, 0xFAC1, 0x9119, 0xDEA9, 0x9127, 0xD4F8, 0x912D, 0xEFF7, 0x9132, 0xD3B3, + 0x9149, 0xEBB7, 0x914A, 0xEFF8, 0x914B, 0xF5DC, 0x914C, 0xEDCC, 0x914D, 0xDBD5, 0x914E, 0xF1CF, 0x9152, 0xF1D0, 0x9162, 0xF5B2, + 0x9169, 0xD9AE, 0x916A, 0xD5AC, 0x916C, 0xE2C6, 0x9175, 0xFDA3, 0x9177, 0xFBE5, 0x9178, 0xDFAB, 0x9187, 0xE2F5, 0x9189, 0xF6AD, + 0x918B, 0xF5B3, 0x918D, 0xF0B5, 0x9192, 0xE1A5, 0x919C, 0xF5DD, 0x91AB, 0xECA2, 0x91AC, 0xEDFD, 0x91AE, 0xF5B4, 0x91AF, 0xFBB8, + 0x91B1, 0xDBA3, 0x91B4, 0xD6CA, 0x91B5, 0xCBD9, 0x91C0, 0xE5D4, 0x91C7, 0xF3FA, 0x91C9, 0xEBB8, 0x91CB, 0xE0B7, 0x91CC, 0xD7EC, + 0x91CD, 0xF1EC, 0x91CE, 0xE5AF, 0x91CF, 0xD5E1, 0x91D0, 0xD7ED, 0x91D1, 0xD1D1, 0x91D7, 0xE1F2, 0x91D8, 0xEFF9, 0x91DC, 0xDDBC, + 0x91DD, 0xF6DC, 0x91E3, 0xF0E5, 0x91E7, 0xF4C4, 0x91EA, 0xE9E9, 0x91F5, 0xF3FB, 0x920D, 0xD4EF, 0x9210, 0xCCA2, 0x9211, 0xF7FE, + 0x9212, 0xDFBC, 0x9217, 0xEBCD, 0x921E, 0xD0B7, 0x9234, 0xD6C2, 0x923A, 0xE8AD, 0x923F, 0xEFAF, 0x9240, 0xCBA5, 0x9245, 0xCBE9, + 0x9249, 0xFAE8, 0x9257, 0xCCC6, 0x925B, 0xE6E7, 0x925E, 0xEAC7, 0x9262, 0xDBA4, 0x9264, 0xCFC9, 0x9265, 0xE2FC, 0x9266, 0xEFFA, + 0x9280, 0xEBDE, 0x9283, 0xF5C8, 0x9285, 0xD4DE, 0x9291, 0xE0D5, 0x9293, 0xEFB0, 0x9296, 0xE2C7, 0x9298, 0xD9AF, 0x929C, 0xF9E7, + 0x92B3, 0xE7E5, 0x92B6, 0xCFCA, 0x92B7, 0xE1D1, 0x92B9, 0xE2C8, 0x92CC, 0xEFFB, 0x92CF, 0xFAF9, 0x92D2, 0xDCF2, 0x92E4, 0xE0A7, + 0x92EA, 0xF8E8, 0x92F8, 0xCBEA, 0x92FC, 0xCBBC, 0x9304, 0xD6E2, 0x9310, 0xF5DE, 0x9318, 0xF5DF, 0x931A, 0xEEB6, 0x931E, 0xE2F6, + 0x931F, 0xD3CA, 0x9320, 0xEFFC, 0x9321, 0xD1C4, 0x9322, 0xEFB1, 0x9324, 0xD1C5, 0x9326, 0xD0DE, 0x9328, 0xD9E1, 0x932B, 0xE0B8, + 0x932E, 0xCDD1, 0x932F, 0xF3B9, 0x9348, 0xE7CC, 0x934A, 0xD6A8, 0x934B, 0xCEA7, 0x934D, 0xD4B5, 0x9354, 0xE4C8, 0x935B, 0xD3B4, + 0x936E, 0xEBB9, 0x9375, 0xCBF5, 0x937C, 0xF6DD, 0x937E, 0xF1A3, 0x938C, 0xCCC7, 0x9394, 0xE9CA, 0x9396, 0xE1F0, 0x939A, 0xF5E0, + 0x93A3, 0xFBAF, 0x93A7, 0xCBD1, 0x93AC, 0xFBE0, 0x93AD, 0xF2E5, 0x93B0, 0xECF0, 0x93C3, 0xF0EC, 0x93D1, 0xEEEB, 0x93DE, 0xE9CB, + 0x93E1, 0xCCF0, 0x93E4, 0xD7AF, 0x93F6, 0xF3A1, 0x9404, 0xFCF5, 0x9418, 0xF1A4, 0x9425, 0xE0D6, 0x942B, 0xEFB2, 0x9435, 0xF4D1, + 0x9438, 0xF7A1, 0x9444, 0xF1D1, 0x9451, 0xCAFC, 0x9452, 0xCAFD, 0x945B, 0xCECE, 0x947D, 0xF3C8, 0x947F, 0xF3BA, 0x9577, 0xEDFE, + 0x9580, 0xDAA6, 0x9583, 0xE0EC, 0x9589, 0xF8CD, 0x958B, 0xCBD2, 0x958F, 0xEBCE, 0x9591, 0xF9D8, 0x9592, 0xF9D9, 0x9593, 0xCAE0, + 0x9594, 0xDACA, 0x9598, 0xCBA6, 0x95A3, 0xCAC8, 0x95A4, 0xF9EE, 0x95A5, 0xDBEC, 0x95A8, 0xD0B1, 0x95AD, 0xD5EF, 0x95B1, 0xE6F3, + 0x95BB, 0xE7A2, 0x95BC, 0xE4D9, 0x95C7, 0xE4E1, 0x95CA, 0xFCC4, 0x95D4, 0xF9EF, 0x95D5, 0xCFF4, 0x95D6, 0xF7E6, 0x95DC, 0xCEBC, + 0x95E1, 0xF4C5, 0x95E2, 0xDCA3, 0x961C, 0xDDBD, 0x9621, 0xF4C6, 0x962A, 0xF8A1, 0x962E, 0xE8D6, 0x9632, 0xDBC1, 0x963B, 0xF0E6, + 0x963F, 0xE4B9, 0x9640, 0xF6ED, 0x9642, 0xF9AE, 0x9644, 0xDDBE, 0x964B, 0xD7B0, 0x964C, 0xD8E8, 0x964D, 0xCBBD, 0x9650, 0xF9DA, + 0x965B, 0xF8CE, 0x965C, 0xF9F0, 0x965D, 0xE0ED, 0x965E, 0xE3B3, 0x965F, 0xF4B3, 0x9662, 0xEAC2, 0x9663, 0xF2E6, 0x9664, 0xF0B6, + 0x966A, 0xDBD6, 0x9670, 0xEBE4, 0x9673, 0xF2E7, 0x9675, 0xD7D5, 0x9676, 0xD4B6, 0x9677, 0xF9E8, 0x9678, 0xD7C1, 0x967D, 0xE5D5, + 0x9685, 0xE9EA, 0x9686, 0xD7CC, 0x968A, 0xD3E9, 0x968B, 0xE2C9, 0x968D, 0xFCDB, 0x968E, 0xCDAD, 0x9694, 0xCCB0, 0x9695, 0xEAA2, + 0x9698, 0xE4F6, 0x9699, 0xD0C0, 0x969B, 0xF0B7, 0x969C, 0xEEA1, 0x96A3, 0xD7F6, 0x96A7, 0xE2CA, 0x96A8, 0xE2CB, 0x96AA, 0xFACF, + 0x96B1, 0xEBDF, 0x96B7, 0xD6CB, 0x96BB, 0xF4B4, 0x96C0, 0xEDCD, 0x96C1, 0xE4D2, 0x96C4, 0xEAA9, 0x96C5, 0xE4BA, 0x96C6, 0xF3A2, + 0x96C7, 0xCDD2, 0x96C9, 0xF6CB, 0x96CB, 0xF1E6, 0x96CC, 0xEDC1, 0x96CD, 0xE8BC, 0x96CE, 0xEED1, 0x96D5, 0xF0E7, 0x96D6, 0xE2CC, + 0x96D9, 0xE4AA, 0x96DB, 0xF5E1, 0x96DC, 0xEDDA, 0x96E2, 0xD7EE, 0x96E3, 0xD1F1, 0x96E8, 0xE9EB, 0x96E9, 0xE9EC, 0x96EA, 0xE0E4, + 0x96EF, 0xDAA7, 0x96F0, 0xDDD4, 0x96F2, 0xEAA3, 0x96F6, 0xD6C3, 0x96F7, 0xD6F4, 0x96F9, 0xDADF, 0x96FB, 0xEFB3, 0x9700, 0xE2CD, + 0x9706, 0xEFFD, 0x9707, 0xF2E8, 0x9711, 0xEFC5, 0x9713, 0xE7E7, 0x9716, 0xD7FD, 0x9719, 0xE7CE, 0x971C, 0xDFDC, 0x971E, 0xF9C7, + 0x9727, 0xD9F6, 0x9730, 0xDFAC, 0x9732, 0xD6DA, 0x9739, 0xDCA4, 0x973D, 0xF0B8, 0x9742, 0xD5FA, 0x9744, 0xE4F7, 0x9748, 0xD6C4, + 0x9751, 0xF4EC, 0x9756, 0xEFFE, 0x975C, 0xF0A1, 0x975E, 0xDEAA, 0x9761, 0xDABC, 0x9762, 0xD8FC, 0x9769, 0xFAD4, 0x976D, 0xECE5, + 0x9774, 0xFCA8, 0x9777, 0xECE6, 0x977A, 0xD8CB, 0x978B, 0xFBB9, 0x978D, 0xE4D3, 0x978F, 0xCDF9, 0x97A0, 0xCFD3, 0x97A8, 0xCAEA, + 0x97AB, 0xCFD4, 0x97AD, 0xF8BD, 0x97C6, 0xF4C7, 0x97CB, 0xEADF, 0x97D3, 0xF9DB, 0x97DC, 0xD4B7, 0x97F3, 0xEBE5, 0x97F6, 0xE1D2, + 0x97FB, 0xEAA4, 0x97FF, 0xFAC2, 0x9800, 0xFBE1, 0x9801, 0xFAED, 0x9802, 0xF0A2, 0x9803, 0xCCF1, 0x9805, 0xFAA3, 0x9806, 0xE2F7, + 0x9808, 0xE2CE, 0x980A, 0xE9F5, 0x980C, 0xE1EB, 0x9810, 0xE7E8, 0x9811, 0xE8D7, 0x9812, 0xDAF8, 0x9813, 0xD4CB, 0x9817, 0xF7F6, + 0x9818, 0xD6C5, 0x982D, 0xD4E9, 0x9830, 0xFAFA, 0x9838, 0xCCF2, 0x9839, 0xF7DD, 0x983B, 0xDEBA, 0x9846, 0xCEA8, 0x984C, 0xF0B9, + 0x984D, 0xE4FE, 0x984E, 0xE4C9, 0x9854, 0xE4D4, 0x9858, 0xEAC3, 0x985A, 0xEFB4, 0x985E, 0xD7BE, 0x9865, 0xFBE2, 0x9867, 0xCDD3, + 0x986B, 0xEFB5, 0x986F, 0xFAE9, 0x98A8, 0xF9A6, 0x98AF, 0xDFBD, 0x98B1, 0xF7C7, 0x98C4, 0xF8FD, 0x98C7, 0xF8FC, 0x98DB, 0xDEAB, + 0x98DC, 0xDBE8, 0x98DF, 0xE3DD, 0x98E1, 0xE1E2, 0x98E2, 0xD1C6, 0x98ED, 0xF6D0, 0x98EE, 0xEBE6, 0x98EF, 0xDAF9, 0x98F4, 0xECC7, + 0x98FC, 0xDEF8, 0x98FD, 0xF8E9, 0x98FE, 0xE3DE, 0x9903, 0xCEF5, 0x9909, 0xFAC3, 0x990A, 0xE5D7, 0x990C, 0xECC8, 0x9910, 0xF3C9, + 0x9913, 0xE4BB, 0x9918, 0xE6AE, 0x991E, 0xEFB6, 0x9920, 0xDCBF, 0x9928, 0xCEBD, 0x9945, 0xD8C3, 0x9949, 0xD0CF, 0x994B, 0xCFFA, + 0x994C, 0xF3CA, 0x994D, 0xE0D7, 0x9951, 0xD1C7, 0x9952, 0xE9AE, 0x9954, 0xE8BD, 0x9957, 0xFAC4, 0x9996, 0xE2CF, 0x9999, 0xFAC5, + 0x999D, 0xF9B8, 0x99A5, 0xDCE0, 0x99A8, 0xFBB0, 0x99AC, 0xD8A9, 0x99AD, 0xE5DF, 0x99AE, 0xF9A7, 0x99B1, 0xF6EE, 0x99B3, 0xF6CC, + 0x99B4, 0xE2F8, 0x99B9, 0xECF1, 0x99C1, 0xDAE0, 0x99D0, 0xF1D2, 0x99D1, 0xD2CC, 0x99D2, 0xCFCB, 0x99D5, 0xCABD, 0x99D9, 0xDDBF, + 0x99DD, 0xF6EF, 0x99DF, 0xDEF9, 0x99ED, 0xFAB4, 0x99F1, 0xD5AD, 0x99FF, 0xF1E7, 0x9A01, 0xDEBE, 0x9A08, 0xDCC0, 0x9A0E, 0xD1C8, + 0x9A0F, 0xD1C9, 0x9A19, 0xF8BE, 0x9A2B, 0xCBF6, 0x9A30, 0xD4F9, 0x9A36, 0xF5E2, 0x9A37, 0xE1D3, 0x9A40, 0xD8E9, 0x9A43, 0xF8FE, + 0x9A45, 0xCFCC, 0x9A4D, 0xFDA4, 0x9A55, 0xCEF6, 0x9A57, 0xFAD0, 0x9A5A, 0xCCF3, 0x9A5B, 0xE6BE, 0x9A5F, 0xF6AE, 0x9A62, 0xD5F0, + 0x9A65, 0xD1CA, 0x9A69, 0xFCBE, 0x9A6A, 0xD5F1, 0x9AA8, 0xCDE9, 0x9AB8, 0xFAB5, 0x9AD3, 0xE2D0, 0x9AD4, 0xF4F7, 0x9AD8, 0xCDD4, + 0x9AE5, 0xE7A3, 0x9AEE, 0xDBA5, 0x9B1A, 0xE2D1, 0x9B27, 0xD7A2, 0x9B2A, 0xF7E3, 0x9B31, 0xEAA6, 0x9B3C, 0xD0A1, 0x9B41, 0xCEDA, + 0x9B42, 0xFBEB, 0x9B43, 0xDBA6, 0x9B44, 0xDBDE, 0x9B45, 0xD8E5, 0x9B4F, 0xEAE0, 0x9B54, 0xD8AA, 0x9B5A, 0xE5E0, 0x9B6F, 0xD6DB, + 0x9B8E, 0xEFC6, 0x9B91, 0xF8EA, 0x9B9F, 0xE4D5, 0x9BAB, 0xCEF7, 0x9BAE, 0xE0D8, 0x9BC9, 0xD7EF, 0x9BD6, 0xF4ED, 0x9BE4, 0xCDE6, + 0x9BE8, 0xCCF4, 0x9C0D, 0xF5E3, 0x9C10, 0xE4CA, 0x9C12, 0xDCE1, 0x9C15, 0xF9C8, 0x9C25, 0xFCBF, 0x9C32, 0xE8A7, 0x9C3B, 0xD8C4, + 0x9C47, 0xCBBE, 0x9C49, 0xDCAE, 0x9C57, 0xD7F7, 0x9CE5, 0xF0E8, 0x9CE7, 0xDDC0, 0x9CE9, 0xCFCD, 0x9CF3, 0xDCF3, 0x9CF4, 0xD9B0, + 0x9CF6, 0xE6E9, 0x9D09, 0xE4BC, 0x9D1B, 0xEAC4, 0x9D26, 0xE4EC, 0x9D28, 0xE4E5, 0x9D3B, 0xFBF8, 0x9D51, 0xCCBB, 0x9D5D, 0xE4BD, + 0x9D60, 0xCDDC, 0x9D61, 0xD9F7, 0x9D6C, 0xDDDF, 0x9D72, 0xEDCE, 0x9DA9, 0xD9D0, 0x9DAF, 0xE5A3, 0x9DB4, 0xF9CD, 0x9DC4, 0xCDAE, + 0x9DD7, 0xCFCE, 0x9DF2, 0xF6AF, 0x9DF8, 0xFDD3, 0x9DF9, 0xEBED, 0x9DFA, 0xD6DC, 0x9E1A, 0xE5A4, 0x9E1E, 0xD5B6, 0x9E75, 0xD6DD, + 0x9E79, 0xF9E9, 0x9E7D, 0xE7A4, 0x9E7F, 0xD6E3, 0x9E92, 0xD1CB, 0x9E93, 0xD6E4, 0x9E97, 0xD5F2, 0x9E9D, 0xDEFA, 0x9E9F, 0xD7F8, + 0x9EA5, 0xD8EA, 0x9EB4, 0xCFD5, 0x9EB5, 0xD8FD, 0x9EBB, 0xD8AB, 0x9EBE, 0xFDCB, 0x9EC3, 0xFCDC, 0x9ECD, 0xE0A8, 0x9ECE, 0xD5F3, + 0x9ED1, 0xFDD9, 0x9ED4, 0xCCA3, 0x9ED8, 0xD9F9, 0x9EDB, 0xD3EA, 0x9EDC, 0xF5F5, 0x9EDE, 0xEFC7, 0x9EE8, 0xD3DA, 0x9EF4, 0xDABD, + 0x9F07, 0xE8A8, 0x9F08, 0xDCAF, 0x9F0E, 0xF0A3, 0x9F13, 0xCDD5, 0x9F20, 0xE0A9, 0x9F3B, 0xDEAC, 0x9F4A, 0xF0BA, 0x9F4B, 0xEEB1, + 0x9F4E, 0xEEB2, 0x9F52, 0xF6CD, 0x9F5F, 0xEED2, 0x9F61, 0xD6C6, 0x9F67, 0xE0E5, 0x9F6A, 0xF3BB, 0x9F6C, 0xE5E1, 0x9F77, 0xE4CB, + 0x9F8D, 0xD7A3, 0x9F90, 0xDBC2, 0x9F95, 0xCAFE, 0x9F9C, 0xCFCF, 0xAC00, 0xB0A1, 0xAC01, 0xB0A2, 0xAC02, 0x8141, 0xAC03, 0x8142, + 0xAC04, 0xB0A3, 0xAC05, 0x8143, 0xAC06, 0x8144, 0xAC07, 0xB0A4, 0xAC08, 0xB0A5, 0xAC09, 0xB0A6, 0xAC0A, 0xB0A7, 0xAC0B, 0x8145, + 0xAC0C, 0x8146, 0xAC0D, 0x8147, 0xAC0E, 0x8148, 0xAC0F, 0x8149, 0xAC10, 0xB0A8, 0xAC11, 0xB0A9, 0xAC12, 0xB0AA, 0xAC13, 0xB0AB, + 0xAC14, 0xB0AC, 0xAC15, 0xB0AD, 0xAC16, 0xB0AE, 0xAC17, 0xB0AF, 0xAC18, 0x814A, 0xAC19, 0xB0B0, 0xAC1A, 0xB0B1, 0xAC1B, 0xB0B2, + 0xAC1C, 0xB0B3, 0xAC1D, 0xB0B4, 0xAC1E, 0x814B, 0xAC1F, 0x814C, 0xAC20, 0xB0B5, 0xAC21, 0x814D, 0xAC22, 0x814E, 0xAC23, 0x814F, + 0xAC24, 0xB0B6, 0xAC25, 0x8150, 0xAC26, 0x8151, 0xAC27, 0x8152, 0xAC28, 0x8153, 0xAC29, 0x8154, 0xAC2A, 0x8155, 0xAC2B, 0x8156, + 0xAC2C, 0xB0B7, 0xAC2D, 0xB0B8, 0xAC2E, 0x8157, 0xAC2F, 0xB0B9, 0xAC30, 0xB0BA, 0xAC31, 0xB0BB, 0xAC32, 0x8158, 0xAC33, 0x8159, + 0xAC34, 0x815A, 0xAC35, 0x8161, 0xAC36, 0x8162, 0xAC37, 0x8163, 0xAC38, 0xB0BC, 0xAC39, 0xB0BD, 0xAC3A, 0x8164, 0xAC3B, 0x8165, + 0xAC3C, 0xB0BE, 0xAC3D, 0x8166, 0xAC3E, 0x8167, 0xAC3F, 0x8168, 0xAC40, 0xB0BF, 0xAC41, 0x8169, 0xAC42, 0x816A, 0xAC43, 0x816B, + 0xAC44, 0x816C, 0xAC45, 0x816D, 0xAC46, 0x816E, 0xAC47, 0x816F, 0xAC48, 0x8170, 0xAC49, 0x8171, 0xAC4A, 0x8172, 0xAC4B, 0xB0C0, + 0xAC4C, 0x8173, 0xAC4D, 0xB0C1, 0xAC4E, 0x8174, 0xAC4F, 0x8175, 0xAC50, 0x8176, 0xAC51, 0x8177, 0xAC52, 0x8178, 0xAC53, 0x8179, + 0xAC54, 0xB0C2, 0xAC55, 0x817A, 0xAC56, 0x8181, 0xAC57, 0x8182, 0xAC58, 0xB0C3, 0xAC59, 0x8183, 0xAC5A, 0x8184, 0xAC5B, 0x8185, + 0xAC5C, 0xB0C4, 0xAC5D, 0x8186, 0xAC5E, 0x8187, 0xAC5F, 0x8188, 0xAC60, 0x8189, 0xAC61, 0x818A, 0xAC62, 0x818B, 0xAC63, 0x818C, + 0xAC64, 0x818D, 0xAC65, 0x818E, 0xAC66, 0x818F, 0xAC67, 0x8190, 0xAC68, 0x8191, 0xAC69, 0x8192, 0xAC6A, 0x8193, 0xAC6B, 0x8194, + 0xAC6C, 0x8195, 0xAC6D, 0x8196, 0xAC6E, 0x8197, 0xAC6F, 0x8198, 0xAC70, 0xB0C5, 0xAC71, 0xB0C6, 0xAC72, 0x8199, 0xAC73, 0x819A, + 0xAC74, 0xB0C7, 0xAC75, 0x819B, 0xAC76, 0x819C, 0xAC77, 0xB0C8, 0xAC78, 0xB0C9, 0xAC79, 0x819D, 0xAC7A, 0xB0CA, 0xAC7B, 0x819E, + 0xAC7C, 0x819F, 0xAC7D, 0x81A0, 0xAC7E, 0x81A1, 0xAC7F, 0x81A2, 0xAC80, 0xB0CB, 0xAC81, 0xB0CC, 0xAC82, 0x81A3, 0xAC83, 0xB0CD, + 0xAC84, 0xB0CE, 0xAC85, 0xB0CF, 0xAC86, 0xB0D0, 0xAC87, 0x81A4, 0xAC88, 0x81A5, 0xAC89, 0xB0D1, 0xAC8A, 0xB0D2, 0xAC8B, 0xB0D3, + 0xAC8C, 0xB0D4, 0xAC8D, 0x81A6, 0xAC8E, 0x81A7, 0xAC8F, 0x81A8, 0xAC90, 0xB0D5, 0xAC91, 0x81A9, 0xAC92, 0x81AA, 0xAC93, 0x81AB, + 0xAC94, 0xB0D6, 0xAC95, 0x81AC, 0xAC96, 0x81AD, 0xAC97, 0x81AE, 0xAC98, 0x81AF, 0xAC99, 0x81B0, 0xAC9A, 0x81B1, 0xAC9B, 0x81B2, + 0xAC9C, 0xB0D7, 0xAC9D, 0xB0D8, 0xAC9E, 0x81B3, 0xAC9F, 0xB0D9, 0xACA0, 0xB0DA, 0xACA1, 0xB0DB, 0xACA2, 0x81B4, 0xACA3, 0x81B5, + 0xACA4, 0x81B6, 0xACA5, 0x81B7, 0xACA6, 0x81B8, 0xACA7, 0x81B9, 0xACA8, 0xB0DC, 0xACA9, 0xB0DD, 0xACAA, 0xB0DE, 0xACAB, 0x81BA, + 0xACAC, 0xB0DF, 0xACAD, 0x81BB, 0xACAE, 0x81BC, 0xACAF, 0xB0E0, 0xACB0, 0xB0E1, 0xACB1, 0x81BD, 0xACB2, 0x81BE, 0xACB3, 0x81BF, + 0xACB4, 0x81C0, 0xACB5, 0x81C1, 0xACB6, 0x81C2, 0xACB7, 0x81C3, 0xACB8, 0xB0E2, 0xACB9, 0xB0E3, 0xACBA, 0x81C4, 0xACBB, 0xB0E4, + 0xACBC, 0xB0E5, 0xACBD, 0xB0E6, 0xACBE, 0x81C5, 0xACBF, 0x81C6, 0xACC0, 0x81C7, 0xACC1, 0xB0E7, 0xACC2, 0x81C8, 0xACC3, 0x81C9, + 0xACC4, 0xB0E8, 0xACC5, 0x81CA, 0xACC6, 0x81CB, 0xACC7, 0x81CC, 0xACC8, 0xB0E9, 0xACC9, 0x81CD, 0xACCA, 0x81CE, 0xACCB, 0x81CF, + 0xACCC, 0xB0EA, 0xACCD, 0x81D0, 0xACCE, 0x81D1, 0xACCF, 0x81D2, 0xACD0, 0x81D3, 0xACD1, 0x81D4, 0xACD2, 0x81D5, 0xACD3, 0x81D6, + 0xACD4, 0x81D7, 0xACD5, 0xB0EB, 0xACD6, 0x81D8, 0xACD7, 0xB0EC, 0xACD8, 0x81D9, 0xACD9, 0x81DA, 0xACDA, 0x81DB, 0xACDB, 0x81DC, + 0xACDC, 0x81DD, 0xACDD, 0x81DE, 0xACDE, 0x81DF, 0xACDF, 0x81E0, 0xACE0, 0xB0ED, 0xACE1, 0xB0EE, 0xACE2, 0x81E1, 0xACE3, 0x81E2, + 0xACE4, 0xB0EF, 0xACE5, 0x81E3, 0xACE6, 0x81E4, 0xACE7, 0xB0F0, 0xACE8, 0xB0F1, 0xACE9, 0x81E5, 0xACEA, 0xB0F2, 0xACEB, 0x81E6, + 0xACEC, 0xB0F3, 0xACED, 0x81E7, 0xACEE, 0x81E8, 0xACEF, 0xB0F4, 0xACF0, 0xB0F5, 0xACF1, 0xB0F6, 0xACF2, 0x81E9, 0xACF3, 0xB0F7, + 0xACF4, 0x81EA, 0xACF5, 0xB0F8, 0xACF6, 0xB0F9, 0xACF7, 0x81EB, 0xACF8, 0x81EC, 0xACF9, 0x81ED, 0xACFA, 0x81EE, 0xACFB, 0x81EF, + 0xACFC, 0xB0FA, 0xACFD, 0xB0FB, 0xACFE, 0x81F0, 0xACFF, 0x81F1, 0xAD00, 0xB0FC, 0xAD01, 0x81F2, 0xAD02, 0x81F3, 0xAD03, 0x81F4, + 0xAD04, 0xB0FD, 0xAD05, 0x81F5, 0xAD06, 0xB0FE, 0xAD07, 0x81F6, 0xAD08, 0x81F7, 0xAD09, 0x81F8, 0xAD0A, 0x81F9, 0xAD0B, 0x81FA, + 0xAD0C, 0xB1A1, 0xAD0D, 0xB1A2, 0xAD0E, 0x81FB, 0xAD0F, 0xB1A3, 0xAD10, 0x81FC, 0xAD11, 0xB1A4, 0xAD12, 0x81FD, 0xAD13, 0x81FE, + 0xAD14, 0x8241, 0xAD15, 0x8242, 0xAD16, 0x8243, 0xAD17, 0x8244, 0xAD18, 0xB1A5, 0xAD19, 0x8245, 0xAD1A, 0x8246, 0xAD1B, 0x8247, + 0xAD1C, 0xB1A6, 0xAD1D, 0x8248, 0xAD1E, 0x8249, 0xAD1F, 0x824A, 0xAD20, 0xB1A7, 0xAD21, 0x824B, 0xAD22, 0x824C, 0xAD23, 0x824D, + 0xAD24, 0x824E, 0xAD25, 0x824F, 0xAD26, 0x8250, 0xAD27, 0x8251, 0xAD28, 0x8252, 0xAD29, 0xB1A8, 0xAD2A, 0x8253, 0xAD2B, 0x8254, + 0xAD2C, 0xB1A9, 0xAD2D, 0xB1AA, 0xAD2E, 0x8255, 0xAD2F, 0x8256, 0xAD30, 0x8257, 0xAD31, 0x8258, 0xAD32, 0x8259, 0xAD33, 0x825A, + 0xAD34, 0xB1AB, 0xAD35, 0xB1AC, 0xAD36, 0x8261, 0xAD37, 0x8262, 0xAD38, 0xB1AD, 0xAD39, 0x8263, 0xAD3A, 0x8264, 0xAD3B, 0x8265, + 0xAD3C, 0xB1AE, 0xAD3D, 0x8266, 0xAD3E, 0x8267, 0xAD3F, 0x8268, 0xAD40, 0x8269, 0xAD41, 0x826A, 0xAD42, 0x826B, 0xAD43, 0x826C, + 0xAD44, 0xB1AF, 0xAD45, 0xB1B0, 0xAD46, 0x826D, 0xAD47, 0xB1B1, 0xAD48, 0x826E, 0xAD49, 0xB1B2, 0xAD4A, 0x826F, 0xAD4B, 0x8270, + 0xAD4C, 0x8271, 0xAD4D, 0x8272, 0xAD4E, 0x8273, 0xAD4F, 0x8274, 0xAD50, 0xB1B3, 0xAD51, 0x8275, 0xAD52, 0x8276, 0xAD53, 0x8277, + 0xAD54, 0xB1B4, 0xAD55, 0x8278, 0xAD56, 0x8279, 0xAD57, 0x827A, 0xAD58, 0xB1B5, 0xAD59, 0x8281, 0xAD5A, 0x8282, 0xAD5B, 0x8283, + 0xAD5C, 0x8284, 0xAD5D, 0x8285, 0xAD5E, 0x8286, 0xAD5F, 0x8287, 0xAD60, 0x8288, 0xAD61, 0xB1B6, 0xAD62, 0x8289, 0xAD63, 0xB1B7, + 0xAD64, 0x828A, 0xAD65, 0x828B, 0xAD66, 0x828C, 0xAD67, 0x828D, 0xAD68, 0x828E, 0xAD69, 0x828F, 0xAD6A, 0x8290, 0xAD6B, 0x8291, + 0xAD6C, 0xB1B8, 0xAD6D, 0xB1B9, 0xAD6E, 0x8292, 0xAD6F, 0x8293, 0xAD70, 0xB1BA, 0xAD71, 0x8294, 0xAD72, 0x8295, 0xAD73, 0xB1BB, + 0xAD74, 0xB1BC, 0xAD75, 0xB1BD, 0xAD76, 0xB1BE, 0xAD77, 0x8296, 0xAD78, 0x8297, 0xAD79, 0x8298, 0xAD7A, 0x8299, 0xAD7B, 0xB1BF, + 0xAD7C, 0xB1C0, 0xAD7D, 0xB1C1, 0xAD7E, 0x829A, 0xAD7F, 0xB1C2, 0xAD80, 0x829B, 0xAD81, 0xB1C3, 0xAD82, 0xB1C4, 0xAD83, 0x829C, + 0xAD84, 0x829D, 0xAD85, 0x829E, 0xAD86, 0x829F, 0xAD87, 0x82A0, 0xAD88, 0xB1C5, 0xAD89, 0xB1C6, 0xAD8A, 0x82A1, 0xAD8B, 0x82A2, + 0xAD8C, 0xB1C7, 0xAD8D, 0x82A3, 0xAD8E, 0x82A4, 0xAD8F, 0x82A5, 0xAD90, 0xB1C8, 0xAD91, 0x82A6, 0xAD92, 0x82A7, 0xAD93, 0x82A8, + 0xAD94, 0x82A9, 0xAD95, 0x82AA, 0xAD96, 0x82AB, 0xAD97, 0x82AC, 0xAD98, 0x82AD, 0xAD99, 0x82AE, 0xAD9A, 0x82AF, 0xAD9B, 0x82B0, + 0xAD9C, 0xB1C9, 0xAD9D, 0xB1CA, 0xAD9E, 0x82B1, 0xAD9F, 0x82B2, 0xADA0, 0x82B3, 0xADA1, 0x82B4, 0xADA2, 0x82B5, 0xADA3, 0x82B6, + 0xADA4, 0xB1CB, 0xADA5, 0x82B7, 0xADA6, 0x82B8, 0xADA7, 0x82B9, 0xADA8, 0x82BA, 0xADA9, 0x82BB, 0xADAA, 0x82BC, 0xADAB, 0x82BD, + 0xADAC, 0x82BE, 0xADAD, 0x82BF, 0xADAE, 0x82C0, 0xADAF, 0x82C1, 0xADB0, 0x82C2, 0xADB1, 0x82C3, 0xADB2, 0x82C4, 0xADB3, 0x82C5, + 0xADB4, 0x82C6, 0xADB5, 0x82C7, 0xADB6, 0x82C8, 0xADB7, 0xB1CC, 0xADB8, 0x82C9, 0xADB9, 0x82CA, 0xADBA, 0x82CB, 0xADBB, 0x82CC, + 0xADBC, 0x82CD, 0xADBD, 0x82CE, 0xADBE, 0x82CF, 0xADBF, 0x82D0, 0xADC0, 0xB1CD, 0xADC1, 0xB1CE, 0xADC2, 0x82D1, 0xADC3, 0x82D2, + 0xADC4, 0xB1CF, 0xADC5, 0x82D3, 0xADC6, 0x82D4, 0xADC7, 0x82D5, 0xADC8, 0xB1D0, 0xADC9, 0x82D6, 0xADCA, 0x82D7, 0xADCB, 0x82D8, + 0xADCC, 0x82D9, 0xADCD, 0x82DA, 0xADCE, 0x82DB, 0xADCF, 0x82DC, 0xADD0, 0xB1D1, 0xADD1, 0xB1D2, 0xADD2, 0x82DD, 0xADD3, 0xB1D3, + 0xADD4, 0x82DE, 0xADD5, 0x82DF, 0xADD6, 0x82E0, 0xADD7, 0x82E1, 0xADD8, 0x82E2, 0xADD9, 0x82E3, 0xADDA, 0x82E4, 0xADDB, 0x82E5, + 0xADDC, 0xB1D4, 0xADDD, 0x82E6, 0xADDE, 0x82E7, 0xADDF, 0x82E8, 0xADE0, 0xB1D5, 0xADE1, 0x82E9, 0xADE2, 0x82EA, 0xADE3, 0x82EB, + 0xADE4, 0xB1D6, 0xADE5, 0x82EC, 0xADE6, 0x82ED, 0xADE7, 0x82EE, 0xADE8, 0x82EF, 0xADE9, 0x82F0, 0xADEA, 0x82F1, 0xADEB, 0x82F2, + 0xADEC, 0x82F3, 0xADED, 0x82F4, 0xADEE, 0x82F5, 0xADEF, 0x82F6, 0xADF0, 0x82F7, 0xADF1, 0x82F8, 0xADF2, 0x82F9, 0xADF3, 0x82FA, + 0xADF4, 0x82FB, 0xADF5, 0x82FC, 0xADF6, 0x82FD, 0xADF7, 0x82FE, 0xADF8, 0xB1D7, 0xADF9, 0xB1D8, 0xADFA, 0x8341, 0xADFB, 0x8342, + 0xADFC, 0xB1D9, 0xADFD, 0x8343, 0xADFE, 0x8344, 0xADFF, 0xB1DA, 0xAE00, 0xB1DB, 0xAE01, 0xB1DC, 0xAE02, 0x8345, 0xAE03, 0x8346, + 0xAE04, 0x8347, 0xAE05, 0x8348, 0xAE06, 0x8349, 0xAE07, 0x834A, 0xAE08, 0xB1DD, 0xAE09, 0xB1DE, 0xAE0A, 0x834B, 0xAE0B, 0xB1DF, + 0xAE0C, 0x834C, 0xAE0D, 0xB1E0, 0xAE0E, 0x834D, 0xAE0F, 0x834E, 0xAE10, 0x834F, 0xAE11, 0x8350, 0xAE12, 0x8351, 0xAE13, 0x8352, + 0xAE14, 0xB1E1, 0xAE15, 0x8353, 0xAE16, 0x8354, 0xAE17, 0x8355, 0xAE18, 0x8356, 0xAE19, 0x8357, 0xAE1A, 0x8358, 0xAE1B, 0x8359, + 0xAE1C, 0x835A, 0xAE1D, 0x8361, 0xAE1E, 0x8362, 0xAE1F, 0x8363, 0xAE20, 0x8364, 0xAE21, 0x8365, 0xAE22, 0x8366, 0xAE23, 0x8367, + 0xAE24, 0x8368, 0xAE25, 0x8369, 0xAE26, 0x836A, 0xAE27, 0x836B, 0xAE28, 0x836C, 0xAE29, 0x836D, 0xAE2A, 0x836E, 0xAE2B, 0x836F, + 0xAE2C, 0x8370, 0xAE2D, 0x8371, 0xAE2E, 0x8372, 0xAE2F, 0x8373, 0xAE30, 0xB1E2, 0xAE31, 0xB1E3, 0xAE32, 0x8374, 0xAE33, 0x8375, + 0xAE34, 0xB1E4, 0xAE35, 0x8376, 0xAE36, 0x8377, 0xAE37, 0xB1E5, 0xAE38, 0xB1E6, 0xAE39, 0x8378, 0xAE3A, 0xB1E7, 0xAE3B, 0x8379, + 0xAE3C, 0x837A, 0xAE3D, 0x8381, 0xAE3E, 0x8382, 0xAE3F, 0x8383, 0xAE40, 0xB1E8, 0xAE41, 0xB1E9, 0xAE42, 0x8384, 0xAE43, 0xB1EA, + 0xAE44, 0x8385, 0xAE45, 0xB1EB, 0xAE46, 0xB1EC, 0xAE47, 0x8386, 0xAE48, 0x8387, 0xAE49, 0x8388, 0xAE4A, 0xB1ED, 0xAE4B, 0x8389, + 0xAE4C, 0xB1EE, 0xAE4D, 0xB1EF, 0xAE4E, 0xB1F0, 0xAE4F, 0x838A, 0xAE50, 0xB1F1, 0xAE51, 0x838B, 0xAE52, 0x838C, 0xAE53, 0x838D, + 0xAE54, 0xB1F2, 0xAE55, 0x838E, 0xAE56, 0xB1F3, 0xAE57, 0x838F, 0xAE58, 0x8390, 0xAE59, 0x8391, 0xAE5A, 0x8392, 0xAE5B, 0x8393, + 0xAE5C, 0xB1F4, 0xAE5D, 0xB1F5, 0xAE5E, 0x8394, 0xAE5F, 0xB1F6, 0xAE60, 0xB1F7, 0xAE61, 0xB1F8, 0xAE62, 0x8395, 0xAE63, 0x8396, + 0xAE64, 0x8397, 0xAE65, 0xB1F9, 0xAE66, 0x8398, 0xAE67, 0x8399, 0xAE68, 0xB1FA, 0xAE69, 0xB1FB, 0xAE6A, 0x839A, 0xAE6B, 0x839B, + 0xAE6C, 0xB1FC, 0xAE6D, 0x839C, 0xAE6E, 0x839D, 0xAE6F, 0x839E, 0xAE70, 0xB1FD, 0xAE71, 0x839F, 0xAE72, 0x83A0, 0xAE73, 0x83A1, + 0xAE74, 0x83A2, 0xAE75, 0x83A3, 0xAE76, 0x83A4, 0xAE77, 0x83A5, 0xAE78, 0xB1FE, 0xAE79, 0xB2A1, 0xAE7A, 0x83A6, 0xAE7B, 0xB2A2, + 0xAE7C, 0xB2A3, 0xAE7D, 0xB2A4, 0xAE7E, 0x83A7, 0xAE7F, 0x83A8, 0xAE80, 0x83A9, 0xAE81, 0x83AA, 0xAE82, 0x83AB, 0xAE83, 0x83AC, + 0xAE84, 0xB2A5, 0xAE85, 0xB2A6, 0xAE86, 0x83AD, 0xAE87, 0x83AE, 0xAE88, 0x83AF, 0xAE89, 0x83B0, 0xAE8A, 0x83B1, 0xAE8B, 0x83B2, + 0xAE8C, 0xB2A7, 0xAE8D, 0x83B3, 0xAE8E, 0x83B4, 0xAE8F, 0x83B5, 0xAE90, 0x83B6, 0xAE91, 0x83B7, 0xAE92, 0x83B8, 0xAE93, 0x83B9, + 0xAE94, 0x83BA, 0xAE95, 0x83BB, 0xAE96, 0x83BC, 0xAE97, 0x83BD, 0xAE98, 0x83BE, 0xAE99, 0x83BF, 0xAE9A, 0x83C0, 0xAE9B, 0x83C1, + 0xAE9C, 0x83C2, 0xAE9D, 0x83C3, 0xAE9E, 0x83C4, 0xAE9F, 0x83C5, 0xAEA0, 0x83C6, 0xAEA1, 0x83C7, 0xAEA2, 0x83C8, 0xAEA3, 0x83C9, + 0xAEA4, 0x83CA, 0xAEA5, 0x83CB, 0xAEA6, 0x83CC, 0xAEA7, 0x83CD, 0xAEA8, 0x83CE, 0xAEA9, 0x83CF, 0xAEAA, 0x83D0, 0xAEAB, 0x83D1, + 0xAEAC, 0x83D2, 0xAEAD, 0x83D3, 0xAEAE, 0x83D4, 0xAEAF, 0x83D5, 0xAEB0, 0x83D6, 0xAEB1, 0x83D7, 0xAEB2, 0x83D8, 0xAEB3, 0x83D9, + 0xAEB4, 0x83DA, 0xAEB5, 0x83DB, 0xAEB6, 0x83DC, 0xAEB7, 0x83DD, 0xAEB8, 0x83DE, 0xAEB9, 0x83DF, 0xAEBA, 0x83E0, 0xAEBB, 0x83E1, + 0xAEBC, 0xB2A8, 0xAEBD, 0xB2A9, 0xAEBE, 0xB2AA, 0xAEBF, 0x83E2, 0xAEC0, 0xB2AB, 0xAEC1, 0x83E3, 0xAEC2, 0x83E4, 0xAEC3, 0x83E5, + 0xAEC4, 0xB2AC, 0xAEC5, 0x83E6, 0xAEC6, 0x83E7, 0xAEC7, 0x83E8, 0xAEC8, 0x83E9, 0xAEC9, 0x83EA, 0xAECA, 0x83EB, 0xAECB, 0x83EC, + 0xAECC, 0xB2AD, 0xAECD, 0xB2AE, 0xAECE, 0x83ED, 0xAECF, 0xB2AF, 0xAED0, 0xB2B0, 0xAED1, 0xB2B1, 0xAED2, 0x83EE, 0xAED3, 0x83EF, + 0xAED4, 0x83F0, 0xAED5, 0x83F1, 0xAED6, 0x83F2, 0xAED7, 0x83F3, 0xAED8, 0xB2B2, 0xAED9, 0xB2B3, 0xAEDA, 0x83F4, 0xAEDB, 0x83F5, + 0xAEDC, 0xB2B4, 0xAEDD, 0x83F6, 0xAEDE, 0x83F7, 0xAEDF, 0x83F8, 0xAEE0, 0x83F9, 0xAEE1, 0x83FA, 0xAEE2, 0x83FB, 0xAEE3, 0x83FC, + 0xAEE4, 0x83FD, 0xAEE5, 0x83FE, 0xAEE6, 0x8441, 0xAEE7, 0x8442, 0xAEE8, 0xB2B5, 0xAEE9, 0x8443, 0xAEEA, 0x8444, 0xAEEB, 0xB2B6, + 0xAEEC, 0x8445, 0xAEED, 0xB2B7, 0xAEEE, 0x8446, 0xAEEF, 0x8447, 0xAEF0, 0x8448, 0xAEF1, 0x8449, 0xAEF2, 0x844A, 0xAEF3, 0x844B, + 0xAEF4, 0xB2B8, 0xAEF5, 0x844C, 0xAEF6, 0x844D, 0xAEF7, 0x844E, 0xAEF8, 0xB2B9, 0xAEF9, 0x844F, 0xAEFA, 0x8450, 0xAEFB, 0x8451, + 0xAEFC, 0xB2BA, 0xAEFD, 0x8452, 0xAEFE, 0x8453, 0xAEFF, 0x8454, 0xAF00, 0x8455, 0xAF01, 0x8456, 0xAF02, 0x8457, 0xAF03, 0x8458, + 0xAF04, 0x8459, 0xAF05, 0x845A, 0xAF06, 0x8461, 0xAF07, 0xB2BB, 0xAF08, 0xB2BC, 0xAF09, 0x8462, 0xAF0A, 0x8463, 0xAF0B, 0x8464, + 0xAF0C, 0x8465, 0xAF0D, 0xB2BD, 0xAF0E, 0x8466, 0xAF0F, 0x8467, 0xAF10, 0xB2BE, 0xAF11, 0x8468, 0xAF12, 0x8469, 0xAF13, 0x846A, + 0xAF14, 0x846B, 0xAF15, 0x846C, 0xAF16, 0x846D, 0xAF17, 0x846E, 0xAF18, 0x846F, 0xAF19, 0x8470, 0xAF1A, 0x8471, 0xAF1B, 0x8472, + 0xAF1C, 0x8473, 0xAF1D, 0x8474, 0xAF1E, 0x8475, 0xAF1F, 0x8476, 0xAF20, 0x8477, 0xAF21, 0x8478, 0xAF22, 0x8479, 0xAF23, 0x847A, + 0xAF24, 0x8481, 0xAF25, 0x8482, 0xAF26, 0x8483, 0xAF27, 0x8484, 0xAF28, 0x8485, 0xAF29, 0x8486, 0xAF2A, 0x8487, 0xAF2B, 0x8488, + 0xAF2C, 0xB2BF, 0xAF2D, 0xB2C0, 0xAF2E, 0x8489, 0xAF2F, 0x848A, 0xAF30, 0xB2C1, 0xAF31, 0x848B, 0xAF32, 0xB2C2, 0xAF33, 0x848C, + 0xAF34, 0xB2C3, 0xAF35, 0x848D, 0xAF36, 0x848E, 0xAF37, 0x848F, 0xAF38, 0x8490, 0xAF39, 0x8491, 0xAF3A, 0x8492, 0xAF3B, 0x8493, + 0xAF3C, 0xB2C4, 0xAF3D, 0xB2C5, 0xAF3E, 0x8494, 0xAF3F, 0xB2C6, 0xAF40, 0x8495, 0xAF41, 0xB2C7, 0xAF42, 0xB2C8, 0xAF43, 0xB2C9, + 0xAF44, 0x8496, 0xAF45, 0x8497, 0xAF46, 0x8498, 0xAF47, 0x8499, 0xAF48, 0xB2CA, 0xAF49, 0xB2CB, 0xAF4A, 0x849A, 0xAF4B, 0x849B, + 0xAF4C, 0x849C, 0xAF4D, 0x849D, 0xAF4E, 0x849E, 0xAF4F, 0x849F, 0xAF50, 0xB2CC, 0xAF51, 0x84A0, 0xAF52, 0x84A1, 0xAF53, 0x84A2, + 0xAF54, 0x84A3, 0xAF55, 0x84A4, 0xAF56, 0x84A5, 0xAF57, 0x84A6, 0xAF58, 0x84A7, 0xAF59, 0x84A8, 0xAF5A, 0x84A9, 0xAF5B, 0x84AA, + 0xAF5C, 0xB2CD, 0xAF5D, 0xB2CE, 0xAF5E, 0x84AB, 0xAF5F, 0x84AC, 0xAF60, 0x84AD, 0xAF61, 0x84AE, 0xAF62, 0x84AF, 0xAF63, 0x84B0, + 0xAF64, 0xB2CF, 0xAF65, 0xB2D0, 0xAF66, 0x84B1, 0xAF67, 0x84B2, 0xAF68, 0x84B3, 0xAF69, 0x84B4, 0xAF6A, 0x84B5, 0xAF6B, 0x84B6, + 0xAF6C, 0x84B7, 0xAF6D, 0x84B8, 0xAF6E, 0x84B9, 0xAF6F, 0x84BA, 0xAF70, 0x84BB, 0xAF71, 0x84BC, 0xAF72, 0x84BD, 0xAF73, 0x84BE, + 0xAF74, 0x84BF, 0xAF75, 0x84C0, 0xAF76, 0x84C1, 0xAF77, 0x84C2, 0xAF78, 0x84C3, 0xAF79, 0xB2D1, 0xAF7A, 0x84C4, 0xAF7B, 0x84C5, + 0xAF7C, 0x84C6, 0xAF7D, 0x84C7, 0xAF7E, 0x84C8, 0xAF7F, 0x84C9, 0xAF80, 0xB2D2, 0xAF81, 0x84CA, 0xAF82, 0x84CB, 0xAF83, 0x84CC, + 0xAF84, 0xB2D3, 0xAF85, 0x84CD, 0xAF86, 0x84CE, 0xAF87, 0x84CF, 0xAF88, 0xB2D4, 0xAF89, 0x84D0, 0xAF8A, 0x84D1, 0xAF8B, 0x84D2, + 0xAF8C, 0x84D3, 0xAF8D, 0x84D4, 0xAF8E, 0x84D5, 0xAF8F, 0x84D6, 0xAF90, 0xB2D5, 0xAF91, 0xB2D6, 0xAF92, 0x84D7, 0xAF93, 0x84D8, + 0xAF94, 0x84D9, 0xAF95, 0xB2D7, 0xAF96, 0x84DA, 0xAF97, 0x84DB, 0xAF98, 0x84DC, 0xAF99, 0x84DD, 0xAF9A, 0x84DE, 0xAF9B, 0x84DF, + 0xAF9C, 0xB2D8, 0xAF9D, 0x84E0, 0xAF9E, 0x84E1, 0xAF9F, 0x84E2, 0xAFA0, 0x84E3, 0xAFA1, 0x84E4, 0xAFA2, 0x84E5, 0xAFA3, 0x84E6, + 0xAFA4, 0x84E7, 0xAFA5, 0x84E8, 0xAFA6, 0x84E9, 0xAFA7, 0x84EA, 0xAFA8, 0x84EB, 0xAFA9, 0x84EC, 0xAFAA, 0x84ED, 0xAFAB, 0x84EE, + 0xAFAC, 0x84EF, 0xAFAD, 0x84F0, 0xAFAE, 0x84F1, 0xAFAF, 0x84F2, 0xAFB0, 0x84F3, 0xAFB1, 0x84F4, 0xAFB2, 0x84F5, 0xAFB3, 0x84F6, + 0xAFB4, 0x84F7, 0xAFB5, 0x84F8, 0xAFB6, 0x84F9, 0xAFB7, 0x84FA, 0xAFB8, 0xB2D9, 0xAFB9, 0xB2DA, 0xAFBA, 0x84FB, 0xAFBB, 0x84FC, + 0xAFBC, 0xB2DB, 0xAFBD, 0x84FD, 0xAFBE, 0x84FE, 0xAFBF, 0x8541, 0xAFC0, 0xB2DC, 0xAFC1, 0x8542, 0xAFC2, 0x8543, 0xAFC3, 0x8544, + 0xAFC4, 0x8545, 0xAFC5, 0x8546, 0xAFC6, 0x8547, 0xAFC7, 0xB2DD, 0xAFC8, 0xB2DE, 0xAFC9, 0xB2DF, 0xAFCA, 0x8548, 0xAFCB, 0xB2E0, + 0xAFCC, 0x8549, 0xAFCD, 0xB2E1, 0xAFCE, 0xB2E2, 0xAFCF, 0x854A, 0xAFD0, 0x854B, 0xAFD1, 0x854C, 0xAFD2, 0x854D, 0xAFD3, 0x854E, + 0xAFD4, 0xB2E3, 0xAFD5, 0x854F, 0xAFD6, 0x8550, 0xAFD7, 0x8551, 0xAFD8, 0x8552, 0xAFD9, 0x8553, 0xAFDA, 0x8554, 0xAFDB, 0x8555, + 0xAFDC, 0xB2E4, 0xAFDD, 0x8556, 0xAFDE, 0x8557, 0xAFDF, 0x8558, 0xAFE0, 0x8559, 0xAFE1, 0x855A, 0xAFE2, 0x8561, 0xAFE3, 0x8562, + 0xAFE4, 0x8563, 0xAFE5, 0x8564, 0xAFE6, 0x8565, 0xAFE7, 0x8566, 0xAFE8, 0xB2E5, 0xAFE9, 0xB2E6, 0xAFEA, 0x8567, 0xAFEB, 0x8568, + 0xAFEC, 0x8569, 0xAFED, 0x856A, 0xAFEE, 0x856B, 0xAFEF, 0x856C, 0xAFF0, 0xB2E7, 0xAFF1, 0xB2E8, 0xAFF2, 0x856D, 0xAFF3, 0x856E, + 0xAFF4, 0xB2E9, 0xAFF5, 0x856F, 0xAFF6, 0x8570, 0xAFF7, 0x8571, 0xAFF8, 0xB2EA, 0xAFF9, 0x8572, 0xAFFA, 0x8573, 0xAFFB, 0x8574, + 0xAFFC, 0x8575, 0xAFFD, 0x8576, 0xAFFE, 0x8577, 0xAFFF, 0x8578, 0xB000, 0xB2EB, 0xB001, 0xB2EC, 0xB002, 0x8579, 0xB003, 0x857A, + 0xB004, 0xB2ED, 0xB005, 0x8581, 0xB006, 0x8582, 0xB007, 0x8583, 0xB008, 0x8584, 0xB009, 0x8585, 0xB00A, 0x8586, 0xB00B, 0x8587, + 0xB00C, 0xB2EE, 0xB00D, 0x8588, 0xB00E, 0x8589, 0xB00F, 0x858A, 0xB010, 0xB2EF, 0xB011, 0x858B, 0xB012, 0x858C, 0xB013, 0x858D, + 0xB014, 0xB2F0, 0xB015, 0x858E, 0xB016, 0x858F, 0xB017, 0x8590, 0xB018, 0x8591, 0xB019, 0x8592, 0xB01A, 0x8593, 0xB01B, 0x8594, + 0xB01C, 0xB2F1, 0xB01D, 0xB2F2, 0xB01E, 0x8595, 0xB01F, 0x8596, 0xB020, 0x8597, 0xB021, 0x8598, 0xB022, 0x8599, 0xB023, 0x859A, + 0xB024, 0x859B, 0xB025, 0x859C, 0xB026, 0x859D, 0xB027, 0x859E, 0xB028, 0xB2F3, 0xB029, 0x859F, 0xB02A, 0x85A0, 0xB02B, 0x85A1, + 0xB02C, 0x85A2, 0xB02D, 0x85A3, 0xB02E, 0x85A4, 0xB02F, 0x85A5, 0xB030, 0x85A6, 0xB031, 0x85A7, 0xB032, 0x85A8, 0xB033, 0x85A9, + 0xB034, 0x85AA, 0xB035, 0x85AB, 0xB036, 0x85AC, 0xB037, 0x85AD, 0xB038, 0x85AE, 0xB039, 0x85AF, 0xB03A, 0x85B0, 0xB03B, 0x85B1, + 0xB03C, 0x85B2, 0xB03D, 0x85B3, 0xB03E, 0x85B4, 0xB03F, 0x85B5, 0xB040, 0x85B6, 0xB041, 0x85B7, 0xB042, 0x85B8, 0xB043, 0x85B9, + 0xB044, 0xB2F4, 0xB045, 0xB2F5, 0xB046, 0x85BA, 0xB047, 0x85BB, 0xB048, 0xB2F6, 0xB049, 0x85BC, 0xB04A, 0xB2F7, 0xB04B, 0x85BD, + 0xB04C, 0xB2F8, 0xB04D, 0x85BE, 0xB04E, 0xB2F9, 0xB04F, 0x85BF, 0xB050, 0x85C0, 0xB051, 0x85C1, 0xB052, 0x85C2, 0xB053, 0xB2FA, + 0xB054, 0xB2FB, 0xB055, 0xB2FC, 0xB056, 0x85C3, 0xB057, 0xB2FD, 0xB058, 0x85C4, 0xB059, 0xB2FE, 0xB05A, 0x85C5, 0xB05B, 0x85C6, + 0xB05C, 0x85C7, 0xB05D, 0xB3A1, 0xB05E, 0x85C8, 0xB05F, 0x85C9, 0xB060, 0x85CA, 0xB061, 0x85CB, 0xB062, 0x85CC, 0xB063, 0x85CD, + 0xB064, 0x85CE, 0xB065, 0x85CF, 0xB066, 0x85D0, 0xB067, 0x85D1, 0xB068, 0x85D2, 0xB069, 0x85D3, 0xB06A, 0x85D4, 0xB06B, 0x85D5, + 0xB06C, 0x85D6, 0xB06D, 0x85D7, 0xB06E, 0x85D8, 0xB06F, 0x85D9, 0xB070, 0x85DA, 0xB071, 0x85DB, 0xB072, 0x85DC, 0xB073, 0x85DD, + 0xB074, 0x85DE, 0xB075, 0x85DF, 0xB076, 0x85E0, 0xB077, 0x85E1, 0xB078, 0x85E2, 0xB079, 0x85E3, 0xB07A, 0x85E4, 0xB07B, 0x85E5, + 0xB07C, 0xB3A2, 0xB07D, 0xB3A3, 0xB07E, 0x85E6, 0xB07F, 0x85E7, 0xB080, 0xB3A4, 0xB081, 0x85E8, 0xB082, 0x85E9, 0xB083, 0x85EA, + 0xB084, 0xB3A5, 0xB085, 0x85EB, 0xB086, 0x85EC, 0xB087, 0x85ED, 0xB088, 0x85EE, 0xB089, 0x85EF, 0xB08A, 0x85F0, 0xB08B, 0x85F1, + 0xB08C, 0xB3A6, 0xB08D, 0xB3A7, 0xB08E, 0x85F2, 0xB08F, 0xB3A8, 0xB090, 0x85F3, 0xB091, 0xB3A9, 0xB092, 0x85F4, 0xB093, 0x85F5, + 0xB094, 0x85F6, 0xB095, 0x85F7, 0xB096, 0x85F8, 0xB097, 0x85F9, 0xB098, 0xB3AA, 0xB099, 0xB3AB, 0xB09A, 0xB3AC, 0xB09B, 0x85FA, + 0xB09C, 0xB3AD, 0xB09D, 0x85FB, 0xB09E, 0x85FC, 0xB09F, 0xB3AE, 0xB0A0, 0xB3AF, 0xB0A1, 0xB3B0, 0xB0A2, 0xB3B1, 0xB0A3, 0x85FD, + 0xB0A4, 0x85FE, 0xB0A5, 0x8641, 0xB0A6, 0x8642, 0xB0A7, 0x8643, 0xB0A8, 0xB3B2, 0xB0A9, 0xB3B3, 0xB0AA, 0x8644, 0xB0AB, 0xB3B4, + 0xB0AC, 0xB3B5, 0xB0AD, 0xB3B6, 0xB0AE, 0xB3B7, 0xB0AF, 0xB3B8, 0xB0B0, 0x8645, 0xB0B1, 0xB3B9, 0xB0B2, 0x8646, 0xB0B3, 0xB3BA, + 0xB0B4, 0xB3BB, 0xB0B5, 0xB3BC, 0xB0B6, 0x8647, 0xB0B7, 0x8648, 0xB0B8, 0xB3BD, 0xB0B9, 0x8649, 0xB0BA, 0x864A, 0xB0BB, 0x864B, + 0xB0BC, 0xB3BE, 0xB0BD, 0x864C, 0xB0BE, 0x864D, 0xB0BF, 0x864E, 0xB0C0, 0x864F, 0xB0C1, 0x8650, 0xB0C2, 0x8651, 0xB0C3, 0x8652, + 0xB0C4, 0xB3BF, 0xB0C5, 0xB3C0, 0xB0C6, 0x8653, 0xB0C7, 0xB3C1, 0xB0C8, 0xB3C2, 0xB0C9, 0xB3C3, 0xB0CA, 0x8654, 0xB0CB, 0x8655, + 0xB0CC, 0x8656, 0xB0CD, 0x8657, 0xB0CE, 0x8658, 0xB0CF, 0x8659, 0xB0D0, 0xB3C4, 0xB0D1, 0xB3C5, 0xB0D2, 0x865A, 0xB0D3, 0x8661, + 0xB0D4, 0xB3C6, 0xB0D5, 0x8662, 0xB0D6, 0x8663, 0xB0D7, 0x8664, 0xB0D8, 0xB3C7, 0xB0D9, 0x8665, 0xB0DA, 0x8666, 0xB0DB, 0x8667, + 0xB0DC, 0x8668, 0xB0DD, 0x8669, 0xB0DE, 0x866A, 0xB0DF, 0x866B, 0xB0E0, 0xB3C8, 0xB0E1, 0x866C, 0xB0E2, 0x866D, 0xB0E3, 0x866E, + 0xB0E4, 0x866F, 0xB0E5, 0xB3C9, 0xB0E6, 0x8670, 0xB0E7, 0x8671, 0xB0E8, 0x8672, 0xB0E9, 0x8673, 0xB0EA, 0x8674, 0xB0EB, 0x8675, + 0xB0EC, 0x8676, 0xB0ED, 0x8677, 0xB0EE, 0x8678, 0xB0EF, 0x8679, 0xB0F0, 0x867A, 0xB0F1, 0x8681, 0xB0F2, 0x8682, 0xB0F3, 0x8683, + 0xB0F4, 0x8684, 0xB0F5, 0x8685, 0xB0F6, 0x8686, 0xB0F7, 0x8687, 0xB0F8, 0x8688, 0xB0F9, 0x8689, 0xB0FA, 0x868A, 0xB0FB, 0x868B, + 0xB0FC, 0x868C, 0xB0FD, 0x868D, 0xB0FE, 0x868E, 0xB0FF, 0x868F, 0xB100, 0x8690, 0xB101, 0x8691, 0xB102, 0x8692, 0xB103, 0x8693, + 0xB104, 0x8694, 0xB105, 0x8695, 0xB106, 0x8696, 0xB107, 0x8697, 0xB108, 0xB3CA, 0xB109, 0xB3CB, 0xB10A, 0x8698, 0xB10B, 0xB3CC, + 0xB10C, 0xB3CD, 0xB10D, 0x8699, 0xB10E, 0x869A, 0xB10F, 0x869B, 0xB110, 0xB3CE, 0xB111, 0x869C, 0xB112, 0xB3CF, 0xB113, 0xB3D0, + 0xB114, 0x869D, 0xB115, 0x869E, 0xB116, 0x869F, 0xB117, 0x86A0, 0xB118, 0xB3D1, 0xB119, 0xB3D2, 0xB11A, 0x86A1, 0xB11B, 0xB3D3, + 0xB11C, 0xB3D4, 0xB11D, 0xB3D5, 0xB11E, 0x86A2, 0xB11F, 0x86A3, 0xB120, 0x86A4, 0xB121, 0x86A5, 0xB122, 0x86A6, 0xB123, 0xB3D6, + 0xB124, 0xB3D7, 0xB125, 0xB3D8, 0xB126, 0x86A7, 0xB127, 0x86A8, 0xB128, 0xB3D9, 0xB129, 0x86A9, 0xB12A, 0x86AA, 0xB12B, 0x86AB, + 0xB12C, 0xB3DA, 0xB12D, 0x86AC, 0xB12E, 0x86AD, 0xB12F, 0x86AE, 0xB130, 0x86AF, 0xB131, 0x86B0, 0xB132, 0x86B1, 0xB133, 0x86B2, + 0xB134, 0xB3DB, 0xB135, 0xB3DC, 0xB136, 0x86B3, 0xB137, 0xB3DD, 0xB138, 0xB3DE, 0xB139, 0xB3DF, 0xB13A, 0x86B4, 0xB13B, 0x86B5, + 0xB13C, 0x86B6, 0xB13D, 0x86B7, 0xB13E, 0x86B8, 0xB13F, 0x86B9, 0xB140, 0xB3E0, 0xB141, 0xB3E1, 0xB142, 0x86BA, 0xB143, 0x86BB, + 0xB144, 0xB3E2, 0xB145, 0x86BC, 0xB146, 0x86BD, 0xB147, 0x86BE, 0xB148, 0xB3E3, 0xB149, 0x86BF, 0xB14A, 0x86C0, 0xB14B, 0x86C1, + 0xB14C, 0x86C2, 0xB14D, 0x86C3, 0xB14E, 0x86C4, 0xB14F, 0x86C5, 0xB150, 0xB3E4, 0xB151, 0xB3E5, 0xB152, 0x86C6, 0xB153, 0x86C7, + 0xB154, 0xB3E6, 0xB155, 0xB3E7, 0xB156, 0x86C8, 0xB157, 0x86C9, 0xB158, 0xB3E8, 0xB159, 0x86CA, 0xB15A, 0x86CB, 0xB15B, 0x86CC, + 0xB15C, 0xB3E9, 0xB15D, 0x86CD, 0xB15E, 0x86CE, 0xB15F, 0x86CF, 0xB160, 0xB3EA, 0xB161, 0x86D0, 0xB162, 0x86D1, 0xB163, 0x86D2, + 0xB164, 0x86D3, 0xB165, 0x86D4, 0xB166, 0x86D5, 0xB167, 0x86D6, 0xB168, 0x86D7, 0xB169, 0x86D8, 0xB16A, 0x86D9, 0xB16B, 0x86DA, + 0xB16C, 0x86DB, 0xB16D, 0x86DC, 0xB16E, 0x86DD, 0xB16F, 0x86DE, 0xB170, 0x86DF, 0xB171, 0x86E0, 0xB172, 0x86E1, 0xB173, 0x86E2, + 0xB174, 0x86E3, 0xB175, 0x86E4, 0xB176, 0x86E5, 0xB177, 0x86E6, 0xB178, 0xB3EB, 0xB179, 0xB3EC, 0xB17A, 0x86E7, 0xB17B, 0x86E8, + 0xB17C, 0xB3ED, 0xB17D, 0x86E9, 0xB17E, 0x86EA, 0xB17F, 0x86EB, 0xB180, 0xB3EE, 0xB181, 0x86EC, 0xB182, 0xB3EF, 0xB183, 0x86ED, + 0xB184, 0x86EE, 0xB185, 0x86EF, 0xB186, 0x86F0, 0xB187, 0x86F1, 0xB188, 0xB3F0, 0xB189, 0xB3F1, 0xB18A, 0x86F2, 0xB18B, 0xB3F2, + 0xB18C, 0x86F3, 0xB18D, 0xB3F3, 0xB18E, 0x86F4, 0xB18F, 0x86F5, 0xB190, 0x86F6, 0xB191, 0x86F7, 0xB192, 0xB3F4, 0xB193, 0xB3F5, + 0xB194, 0xB3F6, 0xB195, 0x86F8, 0xB196, 0x86F9, 0xB197, 0x86FA, 0xB198, 0xB3F7, 0xB199, 0x86FB, 0xB19A, 0x86FC, 0xB19B, 0x86FD, + 0xB19C, 0xB3F8, 0xB19D, 0x86FE, 0xB19E, 0x8741, 0xB19F, 0x8742, 0xB1A0, 0x8743, 0xB1A1, 0x8744, 0xB1A2, 0x8745, 0xB1A3, 0x8746, + 0xB1A4, 0x8747, 0xB1A5, 0x8748, 0xB1A6, 0x8749, 0xB1A7, 0x874A, 0xB1A8, 0xB3F9, 0xB1A9, 0x874B, 0xB1AA, 0x874C, 0xB1AB, 0x874D, + 0xB1AC, 0x874E, 0xB1AD, 0x874F, 0xB1AE, 0x8750, 0xB1AF, 0x8751, 0xB1B0, 0x8752, 0xB1B1, 0x8753, 0xB1B2, 0x8754, 0xB1B3, 0x8755, + 0xB1B4, 0x8756, 0xB1B5, 0x8757, 0xB1B6, 0x8758, 0xB1B7, 0x8759, 0xB1B8, 0x875A, 0xB1B9, 0x8761, 0xB1BA, 0x8762, 0xB1BB, 0x8763, + 0xB1BC, 0x8764, 0xB1BD, 0x8765, 0xB1BE, 0x8766, 0xB1BF, 0x8767, 0xB1C0, 0x8768, 0xB1C1, 0x8769, 0xB1C2, 0x876A, 0xB1C3, 0x876B, + 0xB1C4, 0x876C, 0xB1C5, 0x876D, 0xB1C6, 0x876E, 0xB1C7, 0x876F, 0xB1C8, 0x8770, 0xB1C9, 0x8771, 0xB1CA, 0x8772, 0xB1CB, 0x8773, + 0xB1CC, 0xB3FA, 0xB1CD, 0x8774, 0xB1CE, 0x8775, 0xB1CF, 0x8776, 0xB1D0, 0xB3FB, 0xB1D1, 0x8777, 0xB1D2, 0x8778, 0xB1D3, 0x8779, + 0xB1D4, 0xB3FC, 0xB1D5, 0x877A, 0xB1D6, 0x8781, 0xB1D7, 0x8782, 0xB1D8, 0x8783, 0xB1D9, 0x8784, 0xB1DA, 0x8785, 0xB1DB, 0x8786, + 0xB1DC, 0xB3FD, 0xB1DD, 0xB3FE, 0xB1DE, 0x8787, 0xB1DF, 0xB4A1, 0xB1E0, 0x8788, 0xB1E1, 0x8789, 0xB1E2, 0x878A, 0xB1E3, 0x878B, + 0xB1E4, 0x878C, 0xB1E5, 0x878D, 0xB1E6, 0x878E, 0xB1E7, 0x878F, 0xB1E8, 0xB4A2, 0xB1E9, 0xB4A3, 0xB1EA, 0x8790, 0xB1EB, 0x8791, + 0xB1EC, 0xB4A4, 0xB1ED, 0x8792, 0xB1EE, 0x8793, 0xB1EF, 0x8794, 0xB1F0, 0xB4A5, 0xB1F1, 0x8795, 0xB1F2, 0x8796, 0xB1F3, 0x8797, + 0xB1F4, 0x8798, 0xB1F5, 0x8799, 0xB1F6, 0x879A, 0xB1F7, 0x879B, 0xB1F8, 0x879C, 0xB1F9, 0xB4A6, 0xB1FA, 0x879D, 0xB1FB, 0xB4A7, + 0xB1FC, 0x879E, 0xB1FD, 0xB4A8, 0xB1FE, 0x879F, 0xB1FF, 0x87A0, 0xB200, 0x87A1, 0xB201, 0x87A2, 0xB202, 0x87A3, 0xB203, 0x87A4, + 0xB204, 0xB4A9, 0xB205, 0xB4AA, 0xB206, 0x87A5, 0xB207, 0x87A6, 0xB208, 0xB4AB, 0xB209, 0x87A7, 0xB20A, 0x87A8, 0xB20B, 0xB4AC, + 0xB20C, 0xB4AD, 0xB20D, 0x87A9, 0xB20E, 0x87AA, 0xB20F, 0x87AB, 0xB210, 0x87AC, 0xB211, 0x87AD, 0xB212, 0x87AE, 0xB213, 0x87AF, + 0xB214, 0xB4AE, 0xB215, 0xB4AF, 0xB216, 0x87B0, 0xB217, 0xB4B0, 0xB218, 0x87B1, 0xB219, 0xB4B1, 0xB21A, 0x87B2, 0xB21B, 0x87B3, + 0xB21C, 0x87B4, 0xB21D, 0x87B5, 0xB21E, 0x87B6, 0xB21F, 0x87B7, 0xB220, 0xB4B2, 0xB221, 0x87B8, 0xB222, 0x87B9, 0xB223, 0x87BA, + 0xB224, 0x87BB, 0xB225, 0x87BC, 0xB226, 0x87BD, 0xB227, 0x87BE, 0xB228, 0x87BF, 0xB229, 0x87C0, 0xB22A, 0x87C1, 0xB22B, 0x87C2, + 0xB22C, 0x87C3, 0xB22D, 0x87C4, 0xB22E, 0x87C5, 0xB22F, 0x87C6, 0xB230, 0x87C7, 0xB231, 0x87C8, 0xB232, 0x87C9, 0xB233, 0x87CA, + 0xB234, 0xB4B3, 0xB235, 0x87CB, 0xB236, 0x87CC, 0xB237, 0x87CD, 0xB238, 0x87CE, 0xB239, 0x87CF, 0xB23A, 0x87D0, 0xB23B, 0x87D1, + 0xB23C, 0xB4B4, 0xB23D, 0x87D2, 0xB23E, 0x87D3, 0xB23F, 0x87D4, 0xB240, 0x87D5, 0xB241, 0x87D6, 0xB242, 0x87D7, 0xB243, 0x87D8, + 0xB244, 0x87D9, 0xB245, 0x87DA, 0xB246, 0x87DB, 0xB247, 0x87DC, 0xB248, 0x87DD, 0xB249, 0x87DE, 0xB24A, 0x87DF, 0xB24B, 0x87E0, + 0xB24C, 0x87E1, 0xB24D, 0x87E2, 0xB24E, 0x87E3, 0xB24F, 0x87E4, 0xB250, 0x87E5, 0xB251, 0x87E6, 0xB252, 0x87E7, 0xB253, 0x87E8, + 0xB254, 0x87E9, 0xB255, 0x87EA, 0xB256, 0x87EB, 0xB257, 0x87EC, 0xB258, 0xB4B5, 0xB259, 0x87ED, 0xB25A, 0x87EE, 0xB25B, 0x87EF, + 0xB25C, 0xB4B6, 0xB25D, 0x87F0, 0xB25E, 0x87F1, 0xB25F, 0x87F2, 0xB260, 0xB4B7, 0xB261, 0x87F3, 0xB262, 0x87F4, 0xB263, 0x87F5, + 0xB264, 0x87F6, 0xB265, 0x87F7, 0xB266, 0x87F8, 0xB267, 0x87F9, 0xB268, 0xB4B8, 0xB269, 0xB4B9, 0xB26A, 0x87FA, 0xB26B, 0x87FB, + 0xB26C, 0x87FC, 0xB26D, 0x87FD, 0xB26E, 0x87FE, 0xB26F, 0x8841, 0xB270, 0x8842, 0xB271, 0x8843, 0xB272, 0x8844, 0xB273, 0x8845, + 0xB274, 0xB4BA, 0xB275, 0xB4BB, 0xB276, 0x8846, 0xB277, 0x8847, 0xB278, 0x8848, 0xB279, 0x8849, 0xB27A, 0x884A, 0xB27B, 0x884B, + 0xB27C, 0xB4BC, 0xB27D, 0x884C, 0xB27E, 0x884D, 0xB27F, 0x884E, 0xB280, 0x884F, 0xB281, 0x8850, 0xB282, 0x8851, 0xB283, 0x8852, + 0xB284, 0xB4BD, 0xB285, 0xB4BE, 0xB286, 0x8853, 0xB287, 0x8854, 0xB288, 0x8855, 0xB289, 0xB4BF, 0xB28A, 0x8856, 0xB28B, 0x8857, + 0xB28C, 0x8858, 0xB28D, 0x8859, 0xB28E, 0x885A, 0xB28F, 0x8861, 0xB290, 0xB4C0, 0xB291, 0xB4C1, 0xB292, 0x8862, 0xB293, 0x8863, + 0xB294, 0xB4C2, 0xB295, 0x8864, 0xB296, 0x8865, 0xB297, 0x8866, 0xB298, 0xB4C3, 0xB299, 0xB4C4, 0xB29A, 0xB4C5, 0xB29B, 0x8867, + 0xB29C, 0x8868, 0xB29D, 0x8869, 0xB29E, 0x886A, 0xB29F, 0x886B, 0xB2A0, 0xB4C6, 0xB2A1, 0xB4C7, 0xB2A2, 0x886C, 0xB2A3, 0xB4C8, + 0xB2A4, 0x886D, 0xB2A5, 0xB4C9, 0xB2A6, 0xB4CA, 0xB2A7, 0x886E, 0xB2A8, 0x886F, 0xB2A9, 0x8870, 0xB2AA, 0xB4CB, 0xB2AB, 0x8871, + 0xB2AC, 0xB4CC, 0xB2AD, 0x8872, 0xB2AE, 0x8873, 0xB2AF, 0x8874, 0xB2B0, 0xB4CD, 0xB2B1, 0x8875, 0xB2B2, 0x8876, 0xB2B3, 0x8877, + 0xB2B4, 0xB4CE, 0xB2B5, 0x8878, 0xB2B6, 0x8879, 0xB2B7, 0x887A, 0xB2B8, 0x8881, 0xB2B9, 0x8882, 0xB2BA, 0x8883, 0xB2BB, 0x8884, + 0xB2BC, 0x8885, 0xB2BD, 0x8886, 0xB2BE, 0x8887, 0xB2BF, 0x8888, 0xB2C0, 0x8889, 0xB2C1, 0x888A, 0xB2C2, 0x888B, 0xB2C3, 0x888C, + 0xB2C4, 0x888D, 0xB2C5, 0x888E, 0xB2C6, 0x888F, 0xB2C7, 0x8890, 0xB2C8, 0xB4CF, 0xB2C9, 0xB4D0, 0xB2CA, 0x8891, 0xB2CB, 0x8892, + 0xB2CC, 0xB4D1, 0xB2CD, 0x8893, 0xB2CE, 0x8894, 0xB2CF, 0x8895, 0xB2D0, 0xB4D2, 0xB2D1, 0x8896, 0xB2D2, 0xB4D3, 0xB2D3, 0x8897, + 0xB2D4, 0x8898, 0xB2D5, 0x8899, 0xB2D6, 0x889A, 0xB2D7, 0x889B, 0xB2D8, 0xB4D4, 0xB2D9, 0xB4D5, 0xB2DA, 0x889C, 0xB2DB, 0xB4D6, + 0xB2DC, 0x889D, 0xB2DD, 0xB4D7, 0xB2DE, 0x889E, 0xB2DF, 0x889F, 0xB2E0, 0x88A0, 0xB2E1, 0x88A1, 0xB2E2, 0xB4D8, 0xB2E3, 0x88A2, + 0xB2E4, 0xB4D9, 0xB2E5, 0xB4DA, 0xB2E6, 0xB4DB, 0xB2E7, 0x88A3, 0xB2E8, 0xB4DC, 0xB2E9, 0x88A4, 0xB2EA, 0x88A5, 0xB2EB, 0xB4DD, + 0xB2EC, 0xB4DE, 0xB2ED, 0xB4DF, 0xB2EE, 0xB4E0, 0xB2EF, 0xB4E1, 0xB2F0, 0x88A6, 0xB2F1, 0x88A7, 0xB2F2, 0x88A8, 0xB2F3, 0xB4E2, + 0xB2F4, 0xB4E3, 0xB2F5, 0xB4E4, 0xB2F6, 0x88A9, 0xB2F7, 0xB4E5, 0xB2F8, 0xB4E6, 0xB2F9, 0xB4E7, 0xB2FA, 0xB4E8, 0xB2FB, 0xB4E9, + 0xB2FC, 0x88AA, 0xB2FD, 0x88AB, 0xB2FE, 0x88AC, 0xB2FF, 0xB4EA, 0xB300, 0xB4EB, 0xB301, 0xB4EC, 0xB302, 0x88AD, 0xB303, 0x88AE, + 0xB304, 0xB4ED, 0xB305, 0x88AF, 0xB306, 0x88B0, 0xB307, 0x88B1, 0xB308, 0xB4EE, 0xB309, 0x88B2, 0xB30A, 0x88B3, 0xB30B, 0x88B4, + 0xB30C, 0x88B5, 0xB30D, 0x88B6, 0xB30E, 0x88B7, 0xB30F, 0x88B8, 0xB310, 0xB4EF, 0xB311, 0xB4F0, 0xB312, 0x88B9, 0xB313, 0xB4F1, + 0xB314, 0xB4F2, 0xB315, 0xB4F3, 0xB316, 0x88BA, 0xB317, 0x88BB, 0xB318, 0x88BC, 0xB319, 0x88BD, 0xB31A, 0x88BE, 0xB31B, 0x88BF, + 0xB31C, 0xB4F4, 0xB31D, 0x88C0, 0xB31E, 0x88C1, 0xB31F, 0x88C2, 0xB320, 0x88C3, 0xB321, 0x88C4, 0xB322, 0x88C5, 0xB323, 0x88C6, + 0xB324, 0x88C7, 0xB325, 0x88C8, 0xB326, 0x88C9, 0xB327, 0x88CA, 0xB328, 0x88CB, 0xB329, 0x88CC, 0xB32A, 0x88CD, 0xB32B, 0x88CE, + 0xB32C, 0x88CF, 0xB32D, 0x88D0, 0xB32E, 0x88D1, 0xB32F, 0x88D2, 0xB330, 0x88D3, 0xB331, 0x88D4, 0xB332, 0x88D5, 0xB333, 0x88D6, + 0xB334, 0x88D7, 0xB335, 0x88D8, 0xB336, 0x88D9, 0xB337, 0x88DA, 0xB338, 0x88DB, 0xB339, 0x88DC, 0xB33A, 0x88DD, 0xB33B, 0x88DE, + 0xB33C, 0x88DF, 0xB33D, 0x88E0, 0xB33E, 0x88E1, 0xB33F, 0x88E2, 0xB340, 0x88E3, 0xB341, 0x88E4, 0xB342, 0x88E5, 0xB343, 0x88E6, + 0xB344, 0x88E7, 0xB345, 0x88E8, 0xB346, 0x88E9, 0xB347, 0x88EA, 0xB348, 0x88EB, 0xB349, 0x88EC, 0xB34A, 0x88ED, 0xB34B, 0x88EE, + 0xB34C, 0x88EF, 0xB34D, 0x88F0, 0xB34E, 0x88F1, 0xB34F, 0x88F2, 0xB350, 0x88F3, 0xB351, 0x88F4, 0xB352, 0x88F5, 0xB353, 0x88F6, + 0xB354, 0xB4F5, 0xB355, 0xB4F6, 0xB356, 0xB4F7, 0xB357, 0x88F7, 0xB358, 0xB4F8, 0xB359, 0x88F8, 0xB35A, 0x88F9, 0xB35B, 0xB4F9, + 0xB35C, 0xB4FA, 0xB35D, 0x88FA, 0xB35E, 0xB4FB, 0xB35F, 0xB4FC, 0xB360, 0x88FB, 0xB361, 0x88FC, 0xB362, 0x88FD, 0xB363, 0x88FE, + 0xB364, 0xB4FD, 0xB365, 0xB4FE, 0xB366, 0x8941, 0xB367, 0xB5A1, 0xB368, 0x8942, 0xB369, 0xB5A2, 0xB36A, 0x8943, 0xB36B, 0xB5A3, + 0xB36C, 0x8944, 0xB36D, 0x8945, 0xB36E, 0xB5A4, 0xB36F, 0x8946, 0xB370, 0xB5A5, 0xB371, 0xB5A6, 0xB372, 0x8947, 0xB373, 0x8948, + 0xB374, 0xB5A7, 0xB375, 0x8949, 0xB376, 0x894A, 0xB377, 0x894B, 0xB378, 0xB5A8, 0xB379, 0x894C, 0xB37A, 0x894D, 0xB37B, 0x894E, + 0xB37C, 0x894F, 0xB37D, 0x8950, 0xB37E, 0x8951, 0xB37F, 0x8952, 0xB380, 0xB5A9, 0xB381, 0xB5AA, 0xB382, 0x8953, 0xB383, 0xB5AB, + 0xB384, 0xB5AC, 0xB385, 0xB5AD, 0xB386, 0x8954, 0xB387, 0x8955, 0xB388, 0x8956, 0xB389, 0x8957, 0xB38A, 0x8958, 0xB38B, 0x8959, + 0xB38C, 0xB5AE, 0xB38D, 0x895A, 0xB38E, 0x8961, 0xB38F, 0x8962, 0xB390, 0xB5AF, 0xB391, 0x8963, 0xB392, 0x8964, 0xB393, 0x8965, + 0xB394, 0xB5B0, 0xB395, 0x8966, 0xB396, 0x8967, 0xB397, 0x8968, 0xB398, 0x8969, 0xB399, 0x896A, 0xB39A, 0x896B, 0xB39B, 0x896C, + 0xB39C, 0x896D, 0xB39D, 0x896E, 0xB39E, 0x896F, 0xB39F, 0x8970, 0xB3A0, 0xB5B1, 0xB3A1, 0xB5B2, 0xB3A2, 0x8971, 0xB3A3, 0x8972, + 0xB3A4, 0x8973, 0xB3A5, 0x8974, 0xB3A6, 0x8975, 0xB3A7, 0x8976, 0xB3A8, 0xB5B3, 0xB3A9, 0x8977, 0xB3AA, 0x8978, 0xB3AB, 0x8979, + 0xB3AC, 0xB5B4, 0xB3AD, 0x897A, 0xB3AE, 0x8981, 0xB3AF, 0x8982, 0xB3B0, 0x8983, 0xB3B1, 0x8984, 0xB3B2, 0x8985, 0xB3B3, 0x8986, + 0xB3B4, 0x8987, 0xB3B5, 0x8988, 0xB3B6, 0x8989, 0xB3B7, 0x898A, 0xB3B8, 0x898B, 0xB3B9, 0x898C, 0xB3BA, 0x898D, 0xB3BB, 0x898E, + 0xB3BC, 0x898F, 0xB3BD, 0x8990, 0xB3BE, 0x8991, 0xB3BF, 0x8992, 0xB3C0, 0x8993, 0xB3C1, 0x8994, 0xB3C2, 0x8995, 0xB3C3, 0x8996, + 0xB3C4, 0xB5B5, 0xB3C5, 0xB5B6, 0xB3C6, 0x8997, 0xB3C7, 0x8998, 0xB3C8, 0xB5B7, 0xB3C9, 0x8999, 0xB3CA, 0x899A, 0xB3CB, 0xB5B8, + 0xB3CC, 0xB5B9, 0xB3CD, 0x899B, 0xB3CE, 0xB5BA, 0xB3CF, 0x899C, 0xB3D0, 0xB5BB, 0xB3D1, 0x899D, 0xB3D2, 0x899E, 0xB3D3, 0x899F, + 0xB3D4, 0xB5BC, 0xB3D5, 0xB5BD, 0xB3D6, 0x89A0, 0xB3D7, 0xB5BE, 0xB3D8, 0x89A1, 0xB3D9, 0xB5BF, 0xB3DA, 0x89A2, 0xB3DB, 0xB5C0, + 0xB3DC, 0x89A3, 0xB3DD, 0xB5C1, 0xB3DE, 0x89A4, 0xB3DF, 0x89A5, 0xB3E0, 0xB5C2, 0xB3E1, 0x89A6, 0xB3E2, 0x89A7, 0xB3E3, 0x89A8, + 0xB3E4, 0xB5C3, 0xB3E5, 0x89A9, 0xB3E6, 0x89AA, 0xB3E7, 0x89AB, 0xB3E8, 0xB5C4, 0xB3E9, 0x89AC, 0xB3EA, 0x89AD, 0xB3EB, 0x89AE, + 0xB3EC, 0x89AF, 0xB3ED, 0x89B0, 0xB3EE, 0x89B1, 0xB3EF, 0x89B2, 0xB3F0, 0x89B3, 0xB3F1, 0x89B4, 0xB3F2, 0x89B5, 0xB3F3, 0x89B6, + 0xB3F4, 0x89B7, 0xB3F5, 0x89B8, 0xB3F6, 0x89B9, 0xB3F7, 0x89BA, 0xB3F8, 0x89BB, 0xB3F9, 0x89BC, 0xB3FA, 0x89BD, 0xB3FB, 0x89BE, + 0xB3FC, 0xB5C5, 0xB3FD, 0x89BF, 0xB3FE, 0x89C0, 0xB3FF, 0x89C1, 0xB400, 0x89C2, 0xB401, 0x89C3, 0xB402, 0x89C4, 0xB403, 0x89C5, + 0xB404, 0x89C6, 0xB405, 0x89C7, 0xB406, 0x89C8, 0xB407, 0x89C9, 0xB408, 0x89CA, 0xB409, 0x89CB, 0xB40A, 0x89CC, 0xB40B, 0x89CD, + 0xB40C, 0x89CE, 0xB40D, 0x89CF, 0xB40E, 0x89D0, 0xB40F, 0x89D1, 0xB410, 0xB5C6, 0xB411, 0x89D2, 0xB412, 0x89D3, 0xB413, 0x89D4, + 0xB414, 0x89D5, 0xB415, 0x89D6, 0xB416, 0x89D7, 0xB417, 0x89D8, 0xB418, 0xB5C7, 0xB419, 0x89D9, 0xB41A, 0x89DA, 0xB41B, 0x89DB, + 0xB41C, 0xB5C8, 0xB41D, 0x89DC, 0xB41E, 0x89DD, 0xB41F, 0x89DE, 0xB420, 0xB5C9, 0xB421, 0x89DF, 0xB422, 0x89E0, 0xB423, 0x89E1, + 0xB424, 0x89E2, 0xB425, 0x89E3, 0xB426, 0x89E4, 0xB427, 0x89E5, 0xB428, 0xB5CA, 0xB429, 0xB5CB, 0xB42A, 0x89E6, 0xB42B, 0xB5CC, + 0xB42C, 0x89E7, 0xB42D, 0x89E8, 0xB42E, 0x89E9, 0xB42F, 0x89EA, 0xB430, 0x89EB, 0xB431, 0x89EC, 0xB432, 0x89ED, 0xB433, 0x89EE, + 0xB434, 0xB5CD, 0xB435, 0x89EF, 0xB436, 0x89F0, 0xB437, 0x89F1, 0xB438, 0x89F2, 0xB439, 0x89F3, 0xB43A, 0x89F4, 0xB43B, 0x89F5, + 0xB43C, 0x89F6, 0xB43D, 0x89F7, 0xB43E, 0x89F8, 0xB43F, 0x89F9, 0xB440, 0x89FA, 0xB441, 0x89FB, 0xB442, 0x89FC, 0xB443, 0x89FD, + 0xB444, 0x89FE, 0xB445, 0x8A41, 0xB446, 0x8A42, 0xB447, 0x8A43, 0xB448, 0x8A44, 0xB449, 0x8A45, 0xB44A, 0x8A46, 0xB44B, 0x8A47, + 0xB44C, 0x8A48, 0xB44D, 0x8A49, 0xB44E, 0x8A4A, 0xB44F, 0x8A4B, 0xB450, 0xB5CE, 0xB451, 0xB5CF, 0xB452, 0x8A4C, 0xB453, 0x8A4D, + 0xB454, 0xB5D0, 0xB455, 0x8A4E, 0xB456, 0x8A4F, 0xB457, 0x8A50, 0xB458, 0xB5D1, 0xB459, 0x8A51, 0xB45A, 0x8A52, 0xB45B, 0x8A53, + 0xB45C, 0x8A54, 0xB45D, 0x8A55, 0xB45E, 0x8A56, 0xB45F, 0x8A57, 0xB460, 0xB5D2, 0xB461, 0xB5D3, 0xB462, 0x8A58, 0xB463, 0xB5D4, + 0xB464, 0x8A59, 0xB465, 0xB5D5, 0xB466, 0x8A5A, 0xB467, 0x8A61, 0xB468, 0x8A62, 0xB469, 0x8A63, 0xB46A, 0x8A64, 0xB46B, 0x8A65, + 0xB46C, 0xB5D6, 0xB46D, 0x8A66, 0xB46E, 0x8A67, 0xB46F, 0x8A68, 0xB470, 0x8A69, 0xB471, 0x8A6A, 0xB472, 0x8A6B, 0xB473, 0x8A6C, + 0xB474, 0x8A6D, 0xB475, 0x8A6E, 0xB476, 0x8A6F, 0xB477, 0x8A70, 0xB478, 0x8A71, 0xB479, 0x8A72, 0xB47A, 0x8A73, 0xB47B, 0x8A74, + 0xB47C, 0x8A75, 0xB47D, 0x8A76, 0xB47E, 0x8A77, 0xB47F, 0x8A78, 0xB480, 0xB5D7, 0xB481, 0x8A79, 0xB482, 0x8A7A, 0xB483, 0x8A81, + 0xB484, 0x8A82, 0xB485, 0x8A83, 0xB486, 0x8A84, 0xB487, 0x8A85, 0xB488, 0xB5D8, 0xB489, 0x8A86, 0xB48A, 0x8A87, 0xB48B, 0x8A88, + 0xB48C, 0x8A89, 0xB48D, 0x8A8A, 0xB48E, 0x8A8B, 0xB48F, 0x8A8C, 0xB490, 0x8A8D, 0xB491, 0x8A8E, 0xB492, 0x8A8F, 0xB493, 0x8A90, + 0xB494, 0x8A91, 0xB495, 0x8A92, 0xB496, 0x8A93, 0xB497, 0x8A94, 0xB498, 0x8A95, 0xB499, 0x8A96, 0xB49A, 0x8A97, 0xB49B, 0x8A98, + 0xB49C, 0x8A99, 0xB49D, 0xB5D9, 0xB49E, 0x8A9A, 0xB49F, 0x8A9B, 0xB4A0, 0x8A9C, 0xB4A1, 0x8A9D, 0xB4A2, 0x8A9E, 0xB4A3, 0x8A9F, + 0xB4A4, 0xB5DA, 0xB4A5, 0x8AA0, 0xB4A6, 0x8AA1, 0xB4A7, 0x8AA2, 0xB4A8, 0xB5DB, 0xB4A9, 0x8AA3, 0xB4AA, 0x8AA4, 0xB4AB, 0x8AA5, + 0xB4AC, 0xB5DC, 0xB4AD, 0x8AA6, 0xB4AE, 0x8AA7, 0xB4AF, 0x8AA8, 0xB4B0, 0x8AA9, 0xB4B1, 0x8AAA, 0xB4B2, 0x8AAB, 0xB4B3, 0x8AAC, + 0xB4B4, 0x8AAD, 0xB4B5, 0xB5DD, 0xB4B6, 0x8AAE, 0xB4B7, 0xB5DE, 0xB4B8, 0x8AAF, 0xB4B9, 0xB5DF, 0xB4BA, 0x8AB0, 0xB4BB, 0x8AB1, + 0xB4BC, 0x8AB2, 0xB4BD, 0x8AB3, 0xB4BE, 0x8AB4, 0xB4BF, 0x8AB5, 0xB4C0, 0xB5E0, 0xB4C1, 0x8AB6, 0xB4C2, 0x8AB7, 0xB4C3, 0x8AB8, + 0xB4C4, 0xB5E1, 0xB4C5, 0x8AB9, 0xB4C6, 0x8ABA, 0xB4C7, 0x8ABB, 0xB4C8, 0xB5E2, 0xB4C9, 0x8ABC, 0xB4CA, 0x8ABD, 0xB4CB, 0x8ABE, + 0xB4CC, 0x8ABF, 0xB4CD, 0x8AC0, 0xB4CE, 0x8AC1, 0xB4CF, 0x8AC2, 0xB4D0, 0xB5E3, 0xB4D1, 0x8AC3, 0xB4D2, 0x8AC4, 0xB4D3, 0x8AC5, + 0xB4D4, 0x8AC6, 0xB4D5, 0xB5E4, 0xB4D6, 0x8AC7, 0xB4D7, 0x8AC8, 0xB4D8, 0x8AC9, 0xB4D9, 0x8ACA, 0xB4DA, 0x8ACB, 0xB4DB, 0x8ACC, + 0xB4DC, 0xB5E5, 0xB4DD, 0xB5E6, 0xB4DE, 0x8ACD, 0xB4DF, 0x8ACE, 0xB4E0, 0xB5E7, 0xB4E1, 0x8ACF, 0xB4E2, 0x8AD0, 0xB4E3, 0xB5E8, + 0xB4E4, 0xB5E9, 0xB4E5, 0x8AD1, 0xB4E6, 0xB5EA, 0xB4E7, 0x8AD2, 0xB4E8, 0x8AD3, 0xB4E9, 0x8AD4, 0xB4EA, 0x8AD5, 0xB4EB, 0x8AD6, + 0xB4EC, 0xB5EB, 0xB4ED, 0xB5EC, 0xB4EE, 0x8AD7, 0xB4EF, 0xB5ED, 0xB4F0, 0x8AD8, 0xB4F1, 0xB5EE, 0xB4F2, 0x8AD9, 0xB4F3, 0x8ADA, + 0xB4F4, 0x8ADB, 0xB4F5, 0x8ADC, 0xB4F6, 0x8ADD, 0xB4F7, 0x8ADE, 0xB4F8, 0xB5EF, 0xB4F9, 0x8ADF, 0xB4FA, 0x8AE0, 0xB4FB, 0x8AE1, + 0xB4FC, 0x8AE2, 0xB4FD, 0x8AE3, 0xB4FE, 0x8AE4, 0xB4FF, 0x8AE5, 0xB500, 0x8AE6, 0xB501, 0x8AE7, 0xB502, 0x8AE8, 0xB503, 0x8AE9, + 0xB504, 0x8AEA, 0xB505, 0x8AEB, 0xB506, 0x8AEC, 0xB507, 0x8AED, 0xB508, 0x8AEE, 0xB509, 0x8AEF, 0xB50A, 0x8AF0, 0xB50B, 0x8AF1, + 0xB50C, 0x8AF2, 0xB50D, 0x8AF3, 0xB50E, 0x8AF4, 0xB50F, 0x8AF5, 0xB510, 0x8AF6, 0xB511, 0x8AF7, 0xB512, 0x8AF8, 0xB513, 0x8AF9, + 0xB514, 0xB5F0, 0xB515, 0xB5F1, 0xB516, 0x8AFA, 0xB517, 0x8AFB, 0xB518, 0xB5F2, 0xB519, 0x8AFC, 0xB51A, 0x8AFD, 0xB51B, 0xB5F3, + 0xB51C, 0xB5F4, 0xB51D, 0x8AFE, 0xB51E, 0x8B41, 0xB51F, 0x8B42, 0xB520, 0x8B43, 0xB521, 0x8B44, 0xB522, 0x8B45, 0xB523, 0x8B46, + 0xB524, 0xB5F5, 0xB525, 0xB5F6, 0xB526, 0x8B47, 0xB527, 0xB5F7, 0xB528, 0xB5F8, 0xB529, 0xB5F9, 0xB52A, 0xB5FA, 0xB52B, 0x8B48, + 0xB52C, 0x8B49, 0xB52D, 0x8B4A, 0xB52E, 0x8B4B, 0xB52F, 0x8B4C, 0xB530, 0xB5FB, 0xB531, 0xB5FC, 0xB532, 0x8B4D, 0xB533, 0x8B4E, + 0xB534, 0xB5FD, 0xB535, 0x8B4F, 0xB536, 0x8B50, 0xB537, 0x8B51, 0xB538, 0xB5FE, 0xB539, 0x8B52, 0xB53A, 0x8B53, 0xB53B, 0x8B54, + 0xB53C, 0x8B55, 0xB53D, 0x8B56, 0xB53E, 0x8B57, 0xB53F, 0x8B58, 0xB540, 0xB6A1, 0xB541, 0xB6A2, 0xB542, 0x8B59, 0xB543, 0xB6A3, + 0xB544, 0xB6A4, 0xB545, 0xB6A5, 0xB546, 0x8B5A, 0xB547, 0x8B61, 0xB548, 0x8B62, 0xB549, 0x8B63, 0xB54A, 0x8B64, 0xB54B, 0xB6A6, + 0xB54C, 0xB6A7, 0xB54D, 0xB6A8, 0xB54E, 0x8B65, 0xB54F, 0x8B66, 0xB550, 0xB6A9, 0xB551, 0x8B67, 0xB552, 0x8B68, 0xB553, 0x8B69, + 0xB554, 0xB6AA, 0xB555, 0x8B6A, 0xB556, 0x8B6B, 0xB557, 0x8B6C, 0xB558, 0x8B6D, 0xB559, 0x8B6E, 0xB55A, 0x8B6F, 0xB55B, 0x8B70, + 0xB55C, 0xB6AB, 0xB55D, 0xB6AC, 0xB55E, 0x8B71, 0xB55F, 0xB6AD, 0xB560, 0xB6AE, 0xB561, 0xB6AF, 0xB562, 0x8B72, 0xB563, 0x8B73, + 0xB564, 0x8B74, 0xB565, 0x8B75, 0xB566, 0x8B76, 0xB567, 0x8B77, 0xB568, 0x8B78, 0xB569, 0x8B79, 0xB56A, 0x8B7A, 0xB56B, 0x8B81, + 0xB56C, 0x8B82, 0xB56D, 0x8B83, 0xB56E, 0x8B84, 0xB56F, 0x8B85, 0xB570, 0x8B86, 0xB571, 0x8B87, 0xB572, 0x8B88, 0xB573, 0x8B89, + 0xB574, 0x8B8A, 0xB575, 0x8B8B, 0xB576, 0x8B8C, 0xB577, 0x8B8D, 0xB578, 0x8B8E, 0xB579, 0x8B8F, 0xB57A, 0x8B90, 0xB57B, 0x8B91, + 0xB57C, 0x8B92, 0xB57D, 0x8B93, 0xB57E, 0x8B94, 0xB57F, 0x8B95, 0xB580, 0x8B96, 0xB581, 0x8B97, 0xB582, 0x8B98, 0xB583, 0x8B99, + 0xB584, 0x8B9A, 0xB585, 0x8B9B, 0xB586, 0x8B9C, 0xB587, 0x8B9D, 0xB588, 0x8B9E, 0xB589, 0x8B9F, 0xB58A, 0x8BA0, 0xB58B, 0x8BA1, + 0xB58C, 0x8BA2, 0xB58D, 0x8BA3, 0xB58E, 0x8BA4, 0xB58F, 0x8BA5, 0xB590, 0x8BA6, 0xB591, 0x8BA7, 0xB592, 0x8BA8, 0xB593, 0x8BA9, + 0xB594, 0x8BAA, 0xB595, 0x8BAB, 0xB596, 0x8BAC, 0xB597, 0x8BAD, 0xB598, 0x8BAE, 0xB599, 0x8BAF, 0xB59A, 0x8BB0, 0xB59B, 0x8BB1, + 0xB59C, 0x8BB2, 0xB59D, 0x8BB3, 0xB59E, 0x8BB4, 0xB59F, 0x8BB5, 0xB5A0, 0xB6B0, 0xB5A1, 0xB6B1, 0xB5A2, 0x8BB6, 0xB5A3, 0x8BB7, + 0xB5A4, 0xB6B2, 0xB5A5, 0x8BB8, 0xB5A6, 0x8BB9, 0xB5A7, 0x8BBA, 0xB5A8, 0xB6B3, 0xB5A9, 0x8BBB, 0xB5AA, 0xB6B4, 0xB5AB, 0xB6B5, + 0xB5AC, 0x8BBC, 0xB5AD, 0x8BBD, 0xB5AE, 0x8BBE, 0xB5AF, 0x8BBF, 0xB5B0, 0xB6B6, 0xB5B1, 0xB6B7, 0xB5B2, 0x8BC0, 0xB5B3, 0xB6B8, + 0xB5B4, 0xB6B9, 0xB5B5, 0xB6BA, 0xB5B6, 0x8BC1, 0xB5B7, 0x8BC2, 0xB5B8, 0x8BC3, 0xB5B9, 0x8BC4, 0xB5BA, 0x8BC5, 0xB5BB, 0xB6BB, + 0xB5BC, 0xB6BC, 0xB5BD, 0xB6BD, 0xB5BE, 0x8BC6, 0xB5BF, 0x8BC7, 0xB5C0, 0xB6BE, 0xB5C1, 0x8BC8, 0xB5C2, 0x8BC9, 0xB5C3, 0x8BCA, + 0xB5C4, 0xB6BF, 0xB5C5, 0x8BCB, 0xB5C6, 0x8BCC, 0xB5C7, 0x8BCD, 0xB5C8, 0x8BCE, 0xB5C9, 0x8BCF, 0xB5CA, 0x8BD0, 0xB5CB, 0x8BD1, + 0xB5CC, 0xB6C0, 0xB5CD, 0xB6C1, 0xB5CE, 0x8BD2, 0xB5CF, 0xB6C2, 0xB5D0, 0xB6C3, 0xB5D1, 0xB6C4, 0xB5D2, 0x8BD3, 0xB5D3, 0x8BD4, + 0xB5D4, 0x8BD5, 0xB5D5, 0x8BD6, 0xB5D6, 0x8BD7, 0xB5D7, 0x8BD8, 0xB5D8, 0xB6C5, 0xB5D9, 0x8BD9, 0xB5DA, 0x8BDA, 0xB5DB, 0x8BDB, + 0xB5DC, 0x8BDC, 0xB5DD, 0x8BDD, 0xB5DE, 0x8BDE, 0xB5DF, 0x8BDF, 0xB5E0, 0x8BE0, 0xB5E1, 0x8BE1, 0xB5E2, 0x8BE2, 0xB5E3, 0x8BE3, + 0xB5E4, 0x8BE4, 0xB5E5, 0x8BE5, 0xB5E6, 0x8BE6, 0xB5E7, 0x8BE7, 0xB5E8, 0x8BE8, 0xB5E9, 0x8BE9, 0xB5EA, 0x8BEA, 0xB5EB, 0x8BEB, + 0xB5EC, 0xB6C6, 0xB5ED, 0x8BEC, 0xB5EE, 0x8BED, 0xB5EF, 0x8BEE, 0xB5F0, 0x8BEF, 0xB5F1, 0x8BF0, 0xB5F2, 0x8BF1, 0xB5F3, 0x8BF2, + 0xB5F4, 0x8BF3, 0xB5F5, 0x8BF4, 0xB5F6, 0x8BF5, 0xB5F7, 0x8BF6, 0xB5F8, 0x8BF7, 0xB5F9, 0x8BF8, 0xB5FA, 0x8BF9, 0xB5FB, 0x8BFA, + 0xB5FC, 0x8BFB, 0xB5FD, 0x8BFC, 0xB5FE, 0x8BFD, 0xB5FF, 0x8BFE, 0xB600, 0x8C41, 0xB601, 0x8C42, 0xB602, 0x8C43, 0xB603, 0x8C44, + 0xB604, 0x8C45, 0xB605, 0x8C46, 0xB606, 0x8C47, 0xB607, 0x8C48, 0xB608, 0x8C49, 0xB609, 0x8C4A, 0xB60A, 0x8C4B, 0xB60B, 0x8C4C, + 0xB60C, 0x8C4D, 0xB60D, 0x8C4E, 0xB60E, 0x8C4F, 0xB60F, 0x8C50, 0xB610, 0xB6C7, 0xB611, 0xB6C8, 0xB612, 0x8C51, 0xB613, 0x8C52, + 0xB614, 0xB6C9, 0xB615, 0x8C53, 0xB616, 0x8C54, 0xB617, 0x8C55, 0xB618, 0xB6CA, 0xB619, 0x8C56, 0xB61A, 0x8C57, 0xB61B, 0x8C58, + 0xB61C, 0x8C59, 0xB61D, 0x8C5A, 0xB61E, 0x8C61, 0xB61F, 0x8C62, 0xB620, 0x8C63, 0xB621, 0x8C64, 0xB622, 0x8C65, 0xB623, 0x8C66, + 0xB624, 0x8C67, 0xB625, 0xB6CB, 0xB626, 0x8C68, 0xB627, 0x8C69, 0xB628, 0x8C6A, 0xB629, 0x8C6B, 0xB62A, 0x8C6C, 0xB62B, 0x8C6D, + 0xB62C, 0xB6CC, 0xB62D, 0x8C6E, 0xB62E, 0x8C6F, 0xB62F, 0x8C70, 0xB630, 0x8C71, 0xB631, 0x8C72, 0xB632, 0x8C73, 0xB633, 0x8C74, + 0xB634, 0xB6CD, 0xB635, 0x8C75, 0xB636, 0x8C76, 0xB637, 0x8C77, 0xB638, 0x8C78, 0xB639, 0x8C79, 0xB63A, 0x8C7A, 0xB63B, 0x8C81, + 0xB63C, 0x8C82, 0xB63D, 0x8C83, 0xB63E, 0x8C84, 0xB63F, 0x8C85, 0xB640, 0x8C86, 0xB641, 0x8C87, 0xB642, 0x8C88, 0xB643, 0x8C89, + 0xB644, 0x8C8A, 0xB645, 0x8C8B, 0xB646, 0x8C8C, 0xB647, 0x8C8D, 0xB648, 0xB6CE, 0xB649, 0x8C8E, 0xB64A, 0x8C8F, 0xB64B, 0x8C90, + 0xB64C, 0x8C91, 0xB64D, 0x8C92, 0xB64E, 0x8C93, 0xB64F, 0x8C94, 0xB650, 0x8C95, 0xB651, 0x8C96, 0xB652, 0x8C97, 0xB653, 0x8C98, + 0xB654, 0x8C99, 0xB655, 0x8C9A, 0xB656, 0x8C9B, 0xB657, 0x8C9C, 0xB658, 0x8C9D, 0xB659, 0x8C9E, 0xB65A, 0x8C9F, 0xB65B, 0x8CA0, + 0xB65C, 0x8CA1, 0xB65D, 0x8CA2, 0xB65E, 0x8CA3, 0xB65F, 0x8CA4, 0xB660, 0x8CA5, 0xB661, 0x8CA6, 0xB662, 0x8CA7, 0xB663, 0x8CA8, + 0xB664, 0xB6CF, 0xB665, 0x8CA9, 0xB666, 0x8CAA, 0xB667, 0x8CAB, 0xB668, 0xB6D0, 0xB669, 0x8CAC, 0xB66A, 0x8CAD, 0xB66B, 0x8CAE, + 0xB66C, 0x8CAF, 0xB66D, 0x8CB0, 0xB66E, 0x8CB1, 0xB66F, 0x8CB2, 0xB670, 0x8CB3, 0xB671, 0x8CB4, 0xB672, 0x8CB5, 0xB673, 0x8CB6, + 0xB674, 0x8CB7, 0xB675, 0x8CB8, 0xB676, 0x8CB9, 0xB677, 0x8CBA, 0xB678, 0x8CBB, 0xB679, 0x8CBC, 0xB67A, 0x8CBD, 0xB67B, 0x8CBE, + 0xB67C, 0x8CBF, 0xB67D, 0x8CC0, 0xB67E, 0x8CC1, 0xB67F, 0x8CC2, 0xB680, 0x8CC3, 0xB681, 0x8CC4, 0xB682, 0x8CC5, 0xB683, 0x8CC6, + 0xB684, 0x8CC7, 0xB685, 0x8CC8, 0xB686, 0x8CC9, 0xB687, 0x8CCA, 0xB688, 0x8CCB, 0xB689, 0x8CCC, 0xB68A, 0x8CCD, 0xB68B, 0x8CCE, + 0xB68C, 0x8CCF, 0xB68D, 0x8CD0, 0xB68E, 0x8CD1, 0xB68F, 0x8CD2, 0xB690, 0x8CD3, 0xB691, 0x8CD4, 0xB692, 0x8CD5, 0xB693, 0x8CD6, + 0xB694, 0x8CD7, 0xB695, 0x8CD8, 0xB696, 0x8CD9, 0xB697, 0x8CDA, 0xB698, 0x8CDB, 0xB699, 0x8CDC, 0xB69A, 0x8CDD, 0xB69B, 0x8CDE, + 0xB69C, 0xB6D1, 0xB69D, 0xB6D2, 0xB69E, 0x8CDF, 0xB69F, 0x8CE0, 0xB6A0, 0xB6D3, 0xB6A1, 0x8CE1, 0xB6A2, 0x8CE2, 0xB6A3, 0x8CE3, + 0xB6A4, 0xB6D4, 0xB6A5, 0x8CE4, 0xB6A6, 0x8CE5, 0xB6A7, 0x8CE6, 0xB6A8, 0x8CE7, 0xB6A9, 0x8CE8, 0xB6AA, 0x8CE9, 0xB6AB, 0xB6D5, + 0xB6AC, 0xB6D6, 0xB6AD, 0x8CEA, 0xB6AE, 0x8CEB, 0xB6AF, 0x8CEC, 0xB6B0, 0x8CED, 0xB6B1, 0xB6D7, 0xB6B2, 0x8CEE, 0xB6B3, 0x8CEF, + 0xB6B4, 0x8CF0, 0xB6B5, 0x8CF1, 0xB6B6, 0x8CF2, 0xB6B7, 0x8CF3, 0xB6B8, 0x8CF4, 0xB6B9, 0x8CF5, 0xB6BA, 0x8CF6, 0xB6BB, 0x8CF7, + 0xB6BC, 0x8CF8, 0xB6BD, 0x8CF9, 0xB6BE, 0x8CFA, 0xB6BF, 0x8CFB, 0xB6C0, 0x8CFC, 0xB6C1, 0x8CFD, 0xB6C2, 0x8CFE, 0xB6C3, 0x8D41, + 0xB6C4, 0x8D42, 0xB6C5, 0x8D43, 0xB6C6, 0x8D44, 0xB6C7, 0x8D45, 0xB6C8, 0x8D46, 0xB6C9, 0x8D47, 0xB6CA, 0x8D48, 0xB6CB, 0x8D49, + 0xB6CC, 0x8D4A, 0xB6CD, 0x8D4B, 0xB6CE, 0x8D4C, 0xB6CF, 0x8D4D, 0xB6D0, 0x8D4E, 0xB6D1, 0x8D4F, 0xB6D2, 0x8D50, 0xB6D3, 0x8D51, + 0xB6D4, 0xB6D8, 0xB6D5, 0x8D52, 0xB6D6, 0x8D53, 0xB6D7, 0x8D54, 0xB6D8, 0x8D55, 0xB6D9, 0x8D56, 0xB6DA, 0x8D57, 0xB6DB, 0x8D58, + 0xB6DC, 0x8D59, 0xB6DD, 0x8D5A, 0xB6DE, 0x8D61, 0xB6DF, 0x8D62, 0xB6E0, 0x8D63, 0xB6E1, 0x8D64, 0xB6E2, 0x8D65, 0xB6E3, 0x8D66, + 0xB6E4, 0x8D67, 0xB6E5, 0x8D68, 0xB6E6, 0x8D69, 0xB6E7, 0x8D6A, 0xB6E8, 0x8D6B, 0xB6E9, 0x8D6C, 0xB6EA, 0x8D6D, 0xB6EB, 0x8D6E, + 0xB6EC, 0x8D6F, 0xB6ED, 0x8D70, 0xB6EE, 0x8D71, 0xB6EF, 0x8D72, 0xB6F0, 0xB6D9, 0xB6F1, 0x8D73, 0xB6F2, 0x8D74, 0xB6F3, 0x8D75, + 0xB6F4, 0xB6DA, 0xB6F5, 0x8D76, 0xB6F6, 0x8D77, 0xB6F7, 0x8D78, 0xB6F8, 0xB6DB, 0xB6F9, 0x8D79, 0xB6FA, 0x8D7A, 0xB6FB, 0x8D81, + 0xB6FC, 0x8D82, 0xB6FD, 0x8D83, 0xB6FE, 0x8D84, 0xB6FF, 0x8D85, 0xB700, 0xB6DC, 0xB701, 0xB6DD, 0xB702, 0x8D86, 0xB703, 0x8D87, + 0xB704, 0x8D88, 0xB705, 0xB6DE, 0xB706, 0x8D89, 0xB707, 0x8D8A, 0xB708, 0x8D8B, 0xB709, 0x8D8C, 0xB70A, 0x8D8D, 0xB70B, 0x8D8E, + 0xB70C, 0x8D8F, 0xB70D, 0x8D90, 0xB70E, 0x8D91, 0xB70F, 0x8D92, 0xB710, 0x8D93, 0xB711, 0x8D94, 0xB712, 0x8D95, 0xB713, 0x8D96, + 0xB714, 0x8D97, 0xB715, 0x8D98, 0xB716, 0x8D99, 0xB717, 0x8D9A, 0xB718, 0x8D9B, 0xB719, 0x8D9C, 0xB71A, 0x8D9D, 0xB71B, 0x8D9E, + 0xB71C, 0x8D9F, 0xB71D, 0x8DA0, 0xB71E, 0x8DA1, 0xB71F, 0x8DA2, 0xB720, 0x8DA3, 0xB721, 0x8DA4, 0xB722, 0x8DA5, 0xB723, 0x8DA6, + 0xB724, 0x8DA7, 0xB725, 0x8DA8, 0xB726, 0x8DA9, 0xB727, 0x8DAA, 0xB728, 0xB6DF, 0xB729, 0xB6E0, 0xB72A, 0x8DAB, 0xB72B, 0x8DAC, + 0xB72C, 0xB6E1, 0xB72D, 0x8DAD, 0xB72E, 0x8DAE, 0xB72F, 0xB6E2, 0xB730, 0xB6E3, 0xB731, 0x8DAF, 0xB732, 0x8DB0, 0xB733, 0x8DB1, + 0xB734, 0x8DB2, 0xB735, 0x8DB3, 0xB736, 0x8DB4, 0xB737, 0x8DB5, 0xB738, 0xB6E4, 0xB739, 0xB6E5, 0xB73A, 0x8DB6, 0xB73B, 0xB6E6, + 0xB73C, 0x8DB7, 0xB73D, 0x8DB8, 0xB73E, 0x8DB9, 0xB73F, 0x8DBA, 0xB740, 0x8DBB, 0xB741, 0x8DBC, 0xB742, 0x8DBD, 0xB743, 0x8DBE, + 0xB744, 0xB6E7, 0xB745, 0x8DBF, 0xB746, 0x8DC0, 0xB747, 0x8DC1, 0xB748, 0xB6E8, 0xB749, 0x8DC2, 0xB74A, 0x8DC3, 0xB74B, 0x8DC4, + 0xB74C, 0xB6E9, 0xB74D, 0x8DC5, 0xB74E, 0x8DC6, 0xB74F, 0x8DC7, 0xB750, 0x8DC8, 0xB751, 0x8DC9, 0xB752, 0x8DCA, 0xB753, 0x8DCB, + 0xB754, 0xB6EA, 0xB755, 0xB6EB, 0xB756, 0x8DCC, 0xB757, 0x8DCD, 0xB758, 0x8DCE, 0xB759, 0x8DCF, 0xB75A, 0x8DD0, 0xB75B, 0x8DD1, + 0xB75C, 0x8DD2, 0xB75D, 0x8DD3, 0xB75E, 0x8DD4, 0xB75F, 0x8DD5, 0xB760, 0xB6EC, 0xB761, 0x8DD6, 0xB762, 0x8DD7, 0xB763, 0x8DD8, + 0xB764, 0xB6ED, 0xB765, 0x8DD9, 0xB766, 0x8DDA, 0xB767, 0x8DDB, 0xB768, 0xB6EE, 0xB769, 0x8DDC, 0xB76A, 0x8DDD, 0xB76B, 0x8DDE, + 0xB76C, 0x8DDF, 0xB76D, 0x8DE0, 0xB76E, 0x8DE1, 0xB76F, 0x8DE2, 0xB770, 0xB6EF, 0xB771, 0xB6F0, 0xB772, 0x8DE3, 0xB773, 0xB6F1, + 0xB774, 0x8DE4, 0xB775, 0xB6F2, 0xB776, 0x8DE5, 0xB777, 0x8DE6, 0xB778, 0x8DE7, 0xB779, 0x8DE8, 0xB77A, 0x8DE9, 0xB77B, 0x8DEA, + 0xB77C, 0xB6F3, 0xB77D, 0xB6F4, 0xB77E, 0x8DEB, 0xB77F, 0x8DEC, 0xB780, 0xB6F5, 0xB781, 0x8DED, 0xB782, 0x8DEE, 0xB783, 0x8DEF, + 0xB784, 0xB6F6, 0xB785, 0x8DF0, 0xB786, 0x8DF1, 0xB787, 0x8DF2, 0xB788, 0x8DF3, 0xB789, 0x8DF4, 0xB78A, 0x8DF5, 0xB78B, 0x8DF6, + 0xB78C, 0xB6F7, 0xB78D, 0xB6F8, 0xB78E, 0x8DF7, 0xB78F, 0xB6F9, 0xB790, 0xB6FA, 0xB791, 0xB6FB, 0xB792, 0xB6FC, 0xB793, 0x8DF8, + 0xB794, 0x8DF9, 0xB795, 0x8DFA, 0xB796, 0xB6FD, 0xB797, 0xB6FE, 0xB798, 0xB7A1, 0xB799, 0xB7A2, 0xB79A, 0x8DFB, 0xB79B, 0x8DFC, + 0xB79C, 0xB7A3, 0xB79D, 0x8DFD, 0xB79E, 0x8DFE, 0xB79F, 0x8E41, 0xB7A0, 0xB7A4, 0xB7A1, 0x8E42, 0xB7A2, 0x8E43, 0xB7A3, 0x8E44, + 0xB7A4, 0x8E45, 0xB7A5, 0x8E46, 0xB7A6, 0x8E47, 0xB7A7, 0x8E48, 0xB7A8, 0xB7A5, 0xB7A9, 0xB7A6, 0xB7AA, 0x8E49, 0xB7AB, 0xB7A7, + 0xB7AC, 0xB7A8, 0xB7AD, 0xB7A9, 0xB7AE, 0x8E4A, 0xB7AF, 0x8E4B, 0xB7B0, 0x8E4C, 0xB7B1, 0x8E4D, 0xB7B2, 0x8E4E, 0xB7B3, 0x8E4F, + 0xB7B4, 0xB7AA, 0xB7B5, 0xB7AB, 0xB7B6, 0x8E50, 0xB7B7, 0x8E51, 0xB7B8, 0xB7AC, 0xB7B9, 0x8E52, 0xB7BA, 0x8E53, 0xB7BB, 0x8E54, + 0xB7BC, 0x8E55, 0xB7BD, 0x8E56, 0xB7BE, 0x8E57, 0xB7BF, 0x8E58, 0xB7C0, 0x8E59, 0xB7C1, 0x8E5A, 0xB7C2, 0x8E61, 0xB7C3, 0x8E62, + 0xB7C4, 0x8E63, 0xB7C5, 0x8E64, 0xB7C6, 0x8E65, 0xB7C7, 0xB7AD, 0xB7C8, 0x8E66, 0xB7C9, 0xB7AE, 0xB7CA, 0x8E67, 0xB7CB, 0x8E68, + 0xB7CC, 0x8E69, 0xB7CD, 0x8E6A, 0xB7CE, 0x8E6B, 0xB7CF, 0x8E6C, 0xB7D0, 0x8E6D, 0xB7D1, 0x8E6E, 0xB7D2, 0x8E6F, 0xB7D3, 0x8E70, + 0xB7D4, 0x8E71, 0xB7D5, 0x8E72, 0xB7D6, 0x8E73, 0xB7D7, 0x8E74, 0xB7D8, 0x8E75, 0xB7D9, 0x8E76, 0xB7DA, 0x8E77, 0xB7DB, 0x8E78, + 0xB7DC, 0x8E79, 0xB7DD, 0x8E7A, 0xB7DE, 0x8E81, 0xB7DF, 0x8E82, 0xB7E0, 0x8E83, 0xB7E1, 0x8E84, 0xB7E2, 0x8E85, 0xB7E3, 0x8E86, + 0xB7E4, 0x8E87, 0xB7E5, 0x8E88, 0xB7E6, 0x8E89, 0xB7E7, 0x8E8A, 0xB7E8, 0x8E8B, 0xB7E9, 0x8E8C, 0xB7EA, 0x8E8D, 0xB7EB, 0x8E8E, + 0xB7EC, 0xB7AF, 0xB7ED, 0xB7B0, 0xB7EE, 0x8E8F, 0xB7EF, 0x8E90, 0xB7F0, 0xB7B1, 0xB7F1, 0x8E91, 0xB7F2, 0x8E92, 0xB7F3, 0x8E93, + 0xB7F4, 0xB7B2, 0xB7F5, 0x8E94, 0xB7F6, 0x8E95, 0xB7F7, 0x8E96, 0xB7F8, 0x8E97, 0xB7F9, 0x8E98, 0xB7FA, 0x8E99, 0xB7FB, 0x8E9A, + 0xB7FC, 0xB7B3, 0xB7FD, 0xB7B4, 0xB7FE, 0x8E9B, 0xB7FF, 0xB7B5, 0xB800, 0xB7B6, 0xB801, 0xB7B7, 0xB802, 0x8E9C, 0xB803, 0x8E9D, + 0xB804, 0x8E9E, 0xB805, 0x8E9F, 0xB806, 0x8EA0, 0xB807, 0xB7B8, 0xB808, 0xB7B9, 0xB809, 0xB7BA, 0xB80A, 0x8EA1, 0xB80B, 0x8EA2, + 0xB80C, 0xB7BB, 0xB80D, 0x8EA3, 0xB80E, 0x8EA4, 0xB80F, 0x8EA5, 0xB810, 0xB7BC, 0xB811, 0x8EA6, 0xB812, 0x8EA7, 0xB813, 0x8EA8, + 0xB814, 0x8EA9, 0xB815, 0x8EAA, 0xB816, 0x8EAB, 0xB817, 0x8EAC, 0xB818, 0xB7BD, 0xB819, 0xB7BE, 0xB81A, 0x8EAD, 0xB81B, 0xB7BF, + 0xB81C, 0x8EAE, 0xB81D, 0xB7C0, 0xB81E, 0x8EAF, 0xB81F, 0x8EB0, 0xB820, 0x8EB1, 0xB821, 0x8EB2, 0xB822, 0x8EB3, 0xB823, 0x8EB4, + 0xB824, 0xB7C1, 0xB825, 0xB7C2, 0xB826, 0x8EB5, 0xB827, 0x8EB6, 0xB828, 0xB7C3, 0xB829, 0x8EB7, 0xB82A, 0x8EB8, 0xB82B, 0x8EB9, + 0xB82C, 0xB7C4, 0xB82D, 0x8EBA, 0xB82E, 0x8EBB, 0xB82F, 0x8EBC, 0xB830, 0x8EBD, 0xB831, 0x8EBE, 0xB832, 0x8EBF, 0xB833, 0x8EC0, + 0xB834, 0xB7C5, 0xB835, 0xB7C6, 0xB836, 0x8EC1, 0xB837, 0xB7C7, 0xB838, 0xB7C8, 0xB839, 0xB7C9, 0xB83A, 0x8EC2, 0xB83B, 0x8EC3, + 0xB83C, 0x8EC4, 0xB83D, 0x8EC5, 0xB83E, 0x8EC6, 0xB83F, 0x8EC7, 0xB840, 0xB7CA, 0xB841, 0x8EC8, 0xB842, 0x8EC9, 0xB843, 0x8ECA, + 0xB844, 0xB7CB, 0xB845, 0x8ECB, 0xB846, 0x8ECC, 0xB847, 0x8ECD, 0xB848, 0x8ECE, 0xB849, 0x8ECF, 0xB84A, 0x8ED0, 0xB84B, 0x8ED1, + 0xB84C, 0x8ED2, 0xB84D, 0x8ED3, 0xB84E, 0x8ED4, 0xB84F, 0x8ED5, 0xB850, 0x8ED6, 0xB851, 0xB7CC, 0xB852, 0x8ED7, 0xB853, 0xB7CD, + 0xB854, 0x8ED8, 0xB855, 0x8ED9, 0xB856, 0x8EDA, 0xB857, 0x8EDB, 0xB858, 0x8EDC, 0xB859, 0x8EDD, 0xB85A, 0x8EDE, 0xB85B, 0x8EDF, + 0xB85C, 0xB7CE, 0xB85D, 0xB7CF, 0xB85E, 0x8EE0, 0xB85F, 0x8EE1, 0xB860, 0xB7D0, 0xB861, 0x8EE2, 0xB862, 0x8EE3, 0xB863, 0x8EE4, + 0xB864, 0xB7D1, 0xB865, 0x8EE5, 0xB866, 0x8EE6, 0xB867, 0x8EE7, 0xB868, 0x8EE8, 0xB869, 0x8EE9, 0xB86A, 0x8EEA, 0xB86B, 0x8EEB, + 0xB86C, 0xB7D2, 0xB86D, 0xB7D3, 0xB86E, 0x8EEC, 0xB86F, 0xB7D4, 0xB870, 0x8EED, 0xB871, 0xB7D5, 0xB872, 0x8EEE, 0xB873, 0x8EEF, + 0xB874, 0x8EF0, 0xB875, 0x8EF1, 0xB876, 0x8EF2, 0xB877, 0x8EF3, 0xB878, 0xB7D6, 0xB879, 0x8EF4, 0xB87A, 0x8EF5, 0xB87B, 0x8EF6, + 0xB87C, 0xB7D7, 0xB87D, 0x8EF7, 0xB87E, 0x8EF8, 0xB87F, 0x8EF9, 0xB880, 0x8EFA, 0xB881, 0x8EFB, 0xB882, 0x8EFC, 0xB883, 0x8EFD, + 0xB884, 0x8EFE, 0xB885, 0x8F41, 0xB886, 0x8F42, 0xB887, 0x8F43, 0xB888, 0x8F44, 0xB889, 0x8F45, 0xB88A, 0x8F46, 0xB88B, 0x8F47, + 0xB88C, 0x8F48, 0xB88D, 0xB7D8, 0xB88E, 0x8F49, 0xB88F, 0x8F4A, 0xB890, 0x8F4B, 0xB891, 0x8F4C, 0xB892, 0x8F4D, 0xB893, 0x8F4E, + 0xB894, 0x8F4F, 0xB895, 0x8F50, 0xB896, 0x8F51, 0xB897, 0x8F52, 0xB898, 0x8F53, 0xB899, 0x8F54, 0xB89A, 0x8F55, 0xB89B, 0x8F56, + 0xB89C, 0x8F57, 0xB89D, 0x8F58, 0xB89E, 0x8F59, 0xB89F, 0x8F5A, 0xB8A0, 0x8F61, 0xB8A1, 0x8F62, 0xB8A2, 0x8F63, 0xB8A3, 0x8F64, + 0xB8A4, 0x8F65, 0xB8A5, 0x8F66, 0xB8A6, 0x8F67, 0xB8A7, 0x8F68, 0xB8A8, 0xB7D9, 0xB8A9, 0x8F69, 0xB8AA, 0x8F6A, 0xB8AB, 0x8F6B, + 0xB8AC, 0x8F6C, 0xB8AD, 0x8F6D, 0xB8AE, 0x8F6E, 0xB8AF, 0x8F6F, 0xB8B0, 0xB7DA, 0xB8B1, 0x8F70, 0xB8B2, 0x8F71, 0xB8B3, 0x8F72, + 0xB8B4, 0xB7DB, 0xB8B5, 0x8F73, 0xB8B6, 0x8F74, 0xB8B7, 0x8F75, 0xB8B8, 0xB7DC, 0xB8B9, 0x8F76, 0xB8BA, 0x8F77, 0xB8BB, 0x8F78, + 0xB8BC, 0x8F79, 0xB8BD, 0x8F7A, 0xB8BE, 0x8F81, 0xB8BF, 0x8F82, 0xB8C0, 0xB7DD, 0xB8C1, 0xB7DE, 0xB8C2, 0x8F83, 0xB8C3, 0xB7DF, + 0xB8C4, 0x8F84, 0xB8C5, 0xB7E0, 0xB8C6, 0x8F85, 0xB8C7, 0x8F86, 0xB8C8, 0x8F87, 0xB8C9, 0x8F88, 0xB8CA, 0x8F89, 0xB8CB, 0x8F8A, + 0xB8CC, 0xB7E1, 0xB8CD, 0x8F8B, 0xB8CE, 0x8F8C, 0xB8CF, 0x8F8D, 0xB8D0, 0xB7E2, 0xB8D1, 0x8F8E, 0xB8D2, 0x8F8F, 0xB8D3, 0x8F90, + 0xB8D4, 0xB7E3, 0xB8D5, 0x8F91, 0xB8D6, 0x8F92, 0xB8D7, 0x8F93, 0xB8D8, 0x8F94, 0xB8D9, 0x8F95, 0xB8DA, 0x8F96, 0xB8DB, 0x8F97, + 0xB8DC, 0x8F98, 0xB8DD, 0xB7E4, 0xB8DE, 0x8F99, 0xB8DF, 0xB7E5, 0xB8E0, 0x8F9A, 0xB8E1, 0xB7E6, 0xB8E2, 0x8F9B, 0xB8E3, 0x8F9C, + 0xB8E4, 0x8F9D, 0xB8E5, 0x8F9E, 0xB8E6, 0x8F9F, 0xB8E7, 0x8FA0, 0xB8E8, 0xB7E7, 0xB8E9, 0xB7E8, 0xB8EA, 0x8FA1, 0xB8EB, 0x8FA2, + 0xB8EC, 0xB7E9, 0xB8ED, 0x8FA3, 0xB8EE, 0x8FA4, 0xB8EF, 0x8FA5, 0xB8F0, 0xB7EA, 0xB8F1, 0x8FA6, 0xB8F2, 0x8FA7, 0xB8F3, 0x8FA8, + 0xB8F4, 0x8FA9, 0xB8F5, 0x8FAA, 0xB8F6, 0x8FAB, 0xB8F7, 0x8FAC, 0xB8F8, 0xB7EB, 0xB8F9, 0xB7EC, 0xB8FA, 0x8FAD, 0xB8FB, 0xB7ED, + 0xB8FC, 0x8FAE, 0xB8FD, 0xB7EE, 0xB8FE, 0x8FAF, 0xB8FF, 0x8FB0, 0xB900, 0x8FB1, 0xB901, 0x8FB2, 0xB902, 0x8FB3, 0xB903, 0x8FB4, + 0xB904, 0xB7EF, 0xB905, 0x8FB5, 0xB906, 0x8FB6, 0xB907, 0x8FB7, 0xB908, 0x8FB8, 0xB909, 0x8FB9, 0xB90A, 0x8FBA, 0xB90B, 0x8FBB, + 0xB90C, 0x8FBC, 0xB90D, 0x8FBD, 0xB90E, 0x8FBE, 0xB90F, 0x8FBF, 0xB910, 0x8FC0, 0xB911, 0x8FC1, 0xB912, 0x8FC2, 0xB913, 0x8FC3, + 0xB914, 0x8FC4, 0xB915, 0x8FC5, 0xB916, 0x8FC6, 0xB917, 0x8FC7, 0xB918, 0xB7F0, 0xB919, 0x8FC8, 0xB91A, 0x8FC9, 0xB91B, 0x8FCA, + 0xB91C, 0x8FCB, 0xB91D, 0x8FCC, 0xB91E, 0x8FCD, 0xB91F, 0x8FCE, 0xB920, 0xB7F1, 0xB921, 0x8FCF, 0xB922, 0x8FD0, 0xB923, 0x8FD1, + 0xB924, 0x8FD2, 0xB925, 0x8FD3, 0xB926, 0x8FD4, 0xB927, 0x8FD5, 0xB928, 0x8FD6, 0xB929, 0x8FD7, 0xB92A, 0x8FD8, 0xB92B, 0x8FD9, + 0xB92C, 0x8FDA, 0xB92D, 0x8FDB, 0xB92E, 0x8FDC, 0xB92F, 0x8FDD, 0xB930, 0x8FDE, 0xB931, 0x8FDF, 0xB932, 0x8FE0, 0xB933, 0x8FE1, + 0xB934, 0x8FE2, 0xB935, 0x8FE3, 0xB936, 0x8FE4, 0xB937, 0x8FE5, 0xB938, 0x8FE6, 0xB939, 0x8FE7, 0xB93A, 0x8FE8, 0xB93B, 0x8FE9, + 0xB93C, 0xB7F2, 0xB93D, 0xB7F3, 0xB93E, 0x8FEA, 0xB93F, 0x8FEB, 0xB940, 0xB7F4, 0xB941, 0x8FEC, 0xB942, 0x8FED, 0xB943, 0x8FEE, + 0xB944, 0xB7F5, 0xB945, 0x8FEF, 0xB946, 0x8FF0, 0xB947, 0x8FF1, 0xB948, 0x8FF2, 0xB949, 0x8FF3, 0xB94A, 0x8FF4, 0xB94B, 0x8FF5, + 0xB94C, 0xB7F6, 0xB94D, 0x8FF6, 0xB94E, 0x8FF7, 0xB94F, 0xB7F7, 0xB950, 0x8FF8, 0xB951, 0xB7F8, 0xB952, 0x8FF9, 0xB953, 0x8FFA, + 0xB954, 0x8FFB, 0xB955, 0x8FFC, 0xB956, 0x8FFD, 0xB957, 0x8FFE, 0xB958, 0xB7F9, 0xB959, 0xB7FA, 0xB95A, 0x9041, 0xB95B, 0x9042, + 0xB95C, 0xB7FB, 0xB95D, 0x9043, 0xB95E, 0x9044, 0xB95F, 0x9045, 0xB960, 0xB7FC, 0xB961, 0x9046, 0xB962, 0x9047, 0xB963, 0x9048, + 0xB964, 0x9049, 0xB965, 0x904A, 0xB966, 0x904B, 0xB967, 0x904C, 0xB968, 0xB7FD, 0xB969, 0xB7FE, 0xB96A, 0x904D, 0xB96B, 0xB8A1, + 0xB96C, 0x904E, 0xB96D, 0xB8A2, 0xB96E, 0x904F, 0xB96F, 0x9050, 0xB970, 0x9051, 0xB971, 0x9052, 0xB972, 0x9053, 0xB973, 0x9054, + 0xB974, 0xB8A3, 0xB975, 0xB8A4, 0xB976, 0x9055, 0xB977, 0x9056, 0xB978, 0xB8A5, 0xB979, 0x9057, 0xB97A, 0x9058, 0xB97B, 0x9059, + 0xB97C, 0xB8A6, 0xB97D, 0x905A, 0xB97E, 0x9061, 0xB97F, 0x9062, 0xB980, 0x9063, 0xB981, 0x9064, 0xB982, 0x9065, 0xB983, 0x9066, + 0xB984, 0xB8A7, 0xB985, 0xB8A8, 0xB986, 0x9067, 0xB987, 0xB8A9, 0xB988, 0x9068, 0xB989, 0xB8AA, 0xB98A, 0xB8AB, 0xB98B, 0x9069, + 0xB98C, 0x906A, 0xB98D, 0xB8AC, 0xB98E, 0xB8AD, 0xB98F, 0x906B, 0xB990, 0x906C, 0xB991, 0x906D, 0xB992, 0x906E, 0xB993, 0x906F, + 0xB994, 0x9070, 0xB995, 0x9071, 0xB996, 0x9072, 0xB997, 0x9073, 0xB998, 0x9074, 0xB999, 0x9075, 0xB99A, 0x9076, 0xB99B, 0x9077, + 0xB99C, 0x9078, 0xB99D, 0x9079, 0xB99E, 0x907A, 0xB99F, 0x9081, 0xB9A0, 0x9082, 0xB9A1, 0x9083, 0xB9A2, 0x9084, 0xB9A3, 0x9085, + 0xB9A4, 0x9086, 0xB9A5, 0x9087, 0xB9A6, 0x9088, 0xB9A7, 0x9089, 0xB9A8, 0x908A, 0xB9A9, 0x908B, 0xB9AA, 0x908C, 0xB9AB, 0x908D, + 0xB9AC, 0xB8AE, 0xB9AD, 0xB8AF, 0xB9AE, 0x908E, 0xB9AF, 0x908F, 0xB9B0, 0xB8B0, 0xB9B1, 0x9090, 0xB9B2, 0x9091, 0xB9B3, 0x9092, + 0xB9B4, 0xB8B1, 0xB9B5, 0x9093, 0xB9B6, 0x9094, 0xB9B7, 0x9095, 0xB9B8, 0x9096, 0xB9B9, 0x9097, 0xB9BA, 0x9098, 0xB9BB, 0x9099, + 0xB9BC, 0xB8B2, 0xB9BD, 0xB8B3, 0xB9BE, 0x909A, 0xB9BF, 0xB8B4, 0xB9C0, 0x909B, 0xB9C1, 0xB8B5, 0xB9C2, 0x909C, 0xB9C3, 0x909D, + 0xB9C4, 0x909E, 0xB9C5, 0x909F, 0xB9C6, 0x90A0, 0xB9C7, 0x90A1, 0xB9C8, 0xB8B6, 0xB9C9, 0xB8B7, 0xB9CA, 0x90A2, 0xB9CB, 0x90A3, + 0xB9CC, 0xB8B8, 0xB9CD, 0x90A4, 0xB9CE, 0xB8B9, 0xB9CF, 0xB8BA, 0xB9D0, 0xB8BB, 0xB9D1, 0xB8BC, 0xB9D2, 0xB8BD, 0xB9D3, 0x90A5, + 0xB9D4, 0x90A6, 0xB9D5, 0x90A7, 0xB9D6, 0x90A8, 0xB9D7, 0x90A9, 0xB9D8, 0xB8BE, 0xB9D9, 0xB8BF, 0xB9DA, 0x90AA, 0xB9DB, 0xB8C0, + 0xB9DC, 0x90AB, 0xB9DD, 0xB8C1, 0xB9DE, 0xB8C2, 0xB9DF, 0x90AC, 0xB9E0, 0x90AD, 0xB9E1, 0xB8C3, 0xB9E2, 0x90AE, 0xB9E3, 0xB8C4, + 0xB9E4, 0xB8C5, 0xB9E5, 0xB8C6, 0xB9E6, 0x90AF, 0xB9E7, 0x90B0, 0xB9E8, 0xB8C7, 0xB9E9, 0x90B1, 0xB9EA, 0x90B2, 0xB9EB, 0x90B3, + 0xB9EC, 0xB8C8, 0xB9ED, 0x90B4, 0xB9EE, 0x90B5, 0xB9EF, 0x90B6, 0xB9F0, 0x90B7, 0xB9F1, 0x90B8, 0xB9F2, 0x90B9, 0xB9F3, 0x90BA, + 0xB9F4, 0xB8C9, 0xB9F5, 0xB8CA, 0xB9F6, 0x90BB, 0xB9F7, 0xB8CB, 0xB9F8, 0xB8CC, 0xB9F9, 0xB8CD, 0xB9FA, 0xB8CE, 0xB9FB, 0x90BC, + 0xB9FC, 0x90BD, 0xB9FD, 0x90BE, 0xB9FE, 0x90BF, 0xB9FF, 0x90C0, 0xBA00, 0xB8CF, 0xBA01, 0xB8D0, 0xBA02, 0x90C1, 0xBA03, 0x90C2, + 0xBA04, 0x90C3, 0xBA05, 0x90C4, 0xBA06, 0x90C5, 0xBA07, 0x90C6, 0xBA08, 0xB8D1, 0xBA09, 0x90C7, 0xBA0A, 0x90C8, 0xBA0B, 0x90C9, + 0xBA0C, 0x90CA, 0xBA0D, 0x90CB, 0xBA0E, 0x90CC, 0xBA0F, 0x90CD, 0xBA10, 0x90CE, 0xBA11, 0x90CF, 0xBA12, 0x90D0, 0xBA13, 0x90D1, + 0xBA14, 0x90D2, 0xBA15, 0xB8D2, 0xBA16, 0x90D3, 0xBA17, 0x90D4, 0xBA18, 0x90D5, 0xBA19, 0x90D6, 0xBA1A, 0x90D7, 0xBA1B, 0x90D8, + 0xBA1C, 0x90D9, 0xBA1D, 0x90DA, 0xBA1E, 0x90DB, 0xBA1F, 0x90DC, 0xBA20, 0x90DD, 0xBA21, 0x90DE, 0xBA22, 0x90DF, 0xBA23, 0x90E0, + 0xBA24, 0x90E1, 0xBA25, 0x90E2, 0xBA26, 0x90E3, 0xBA27, 0x90E4, 0xBA28, 0x90E5, 0xBA29, 0x90E6, 0xBA2A, 0x90E7, 0xBA2B, 0x90E8, + 0xBA2C, 0x90E9, 0xBA2D, 0x90EA, 0xBA2E, 0x90EB, 0xBA2F, 0x90EC, 0xBA30, 0x90ED, 0xBA31, 0x90EE, 0xBA32, 0x90EF, 0xBA33, 0x90F0, + 0xBA34, 0x90F1, 0xBA35, 0x90F2, 0xBA36, 0x90F3, 0xBA37, 0x90F4, 0xBA38, 0xB8D3, 0xBA39, 0xB8D4, 0xBA3A, 0x90F5, 0xBA3B, 0x90F6, + 0xBA3C, 0xB8D5, 0xBA3D, 0x90F7, 0xBA3E, 0x90F8, 0xBA3F, 0x90F9, 0xBA40, 0xB8D6, 0xBA41, 0x90FA, 0xBA42, 0xB8D7, 0xBA43, 0x90FB, + 0xBA44, 0x90FC, 0xBA45, 0x90FD, 0xBA46, 0x90FE, 0xBA47, 0x9141, 0xBA48, 0xB8D8, 0xBA49, 0xB8D9, 0xBA4A, 0x9142, 0xBA4B, 0xB8DA, + 0xBA4C, 0x9143, 0xBA4D, 0xB8DB, 0xBA4E, 0xB8DC, 0xBA4F, 0x9144, 0xBA50, 0x9145, 0xBA51, 0x9146, 0xBA52, 0x9147, 0xBA53, 0xB8DD, + 0xBA54, 0xB8DE, 0xBA55, 0xB8DF, 0xBA56, 0x9148, 0xBA57, 0x9149, 0xBA58, 0xB8E0, 0xBA59, 0x914A, 0xBA5A, 0x914B, 0xBA5B, 0x914C, + 0xBA5C, 0xB8E1, 0xBA5D, 0x914D, 0xBA5E, 0x914E, 0xBA5F, 0x914F, 0xBA60, 0x9150, 0xBA61, 0x9151, 0xBA62, 0x9152, 0xBA63, 0x9153, + 0xBA64, 0xB8E2, 0xBA65, 0xB8E3, 0xBA66, 0x9154, 0xBA67, 0xB8E4, 0xBA68, 0xB8E5, 0xBA69, 0xB8E6, 0xBA6A, 0x9155, 0xBA6B, 0x9156, + 0xBA6C, 0x9157, 0xBA6D, 0x9158, 0xBA6E, 0x9159, 0xBA6F, 0x915A, 0xBA70, 0xB8E7, 0xBA71, 0xB8E8, 0xBA72, 0x9161, 0xBA73, 0x9162, + 0xBA74, 0xB8E9, 0xBA75, 0x9163, 0xBA76, 0x9164, 0xBA77, 0x9165, 0xBA78, 0xB8EA, 0xBA79, 0x9166, 0xBA7A, 0x9167, 0xBA7B, 0x9168, + 0xBA7C, 0x9169, 0xBA7D, 0x916A, 0xBA7E, 0x916B, 0xBA7F, 0x916C, 0xBA80, 0x916D, 0xBA81, 0x916E, 0xBA82, 0x916F, 0xBA83, 0xB8EB, + 0xBA84, 0xB8EC, 0xBA85, 0xB8ED, 0xBA86, 0x9170, 0xBA87, 0xB8EE, 0xBA88, 0x9171, 0xBA89, 0x9172, 0xBA8A, 0x9173, 0xBA8B, 0x9174, + 0xBA8C, 0xB8EF, 0xBA8D, 0x9175, 0xBA8E, 0x9176, 0xBA8F, 0x9177, 0xBA90, 0x9178, 0xBA91, 0x9179, 0xBA92, 0x917A, 0xBA93, 0x9181, + 0xBA94, 0x9182, 0xBA95, 0x9183, 0xBA96, 0x9184, 0xBA97, 0x9185, 0xBA98, 0x9186, 0xBA99, 0x9187, 0xBA9A, 0x9188, 0xBA9B, 0x9189, + 0xBA9C, 0x918A, 0xBA9D, 0x918B, 0xBA9E, 0x918C, 0xBA9F, 0x918D, 0xBAA0, 0x918E, 0xBAA1, 0x918F, 0xBAA2, 0x9190, 0xBAA3, 0x9191, + 0xBAA4, 0x9192, 0xBAA5, 0x9193, 0xBAA6, 0x9194, 0xBAA7, 0x9195, 0xBAA8, 0xB8F0, 0xBAA9, 0xB8F1, 0xBAAA, 0x9196, 0xBAAB, 0xB8F2, + 0xBAAC, 0xB8F3, 0xBAAD, 0x9197, 0xBAAE, 0x9198, 0xBAAF, 0x9199, 0xBAB0, 0xB8F4, 0xBAB1, 0x919A, 0xBAB2, 0xB8F5, 0xBAB3, 0x919B, + 0xBAB4, 0x919C, 0xBAB5, 0x919D, 0xBAB6, 0x919E, 0xBAB7, 0x919F, 0xBAB8, 0xB8F6, 0xBAB9, 0xB8F7, 0xBABA, 0x91A0, 0xBABB, 0xB8F8, + 0xBABC, 0x91A1, 0xBABD, 0xB8F9, 0xBABE, 0x91A2, 0xBABF, 0x91A3, 0xBAC0, 0x91A4, 0xBAC1, 0x91A5, 0xBAC2, 0x91A6, 0xBAC3, 0x91A7, + 0xBAC4, 0xB8FA, 0xBAC5, 0x91A8, 0xBAC6, 0x91A9, 0xBAC7, 0x91AA, 0xBAC8, 0xB8FB, 0xBAC9, 0x91AB, 0xBACA, 0x91AC, 0xBACB, 0x91AD, + 0xBACC, 0x91AE, 0xBACD, 0x91AF, 0xBACE, 0x91B0, 0xBACF, 0x91B1, 0xBAD0, 0x91B2, 0xBAD1, 0x91B3, 0xBAD2, 0x91B4, 0xBAD3, 0x91B5, + 0xBAD4, 0x91B6, 0xBAD5, 0x91B7, 0xBAD6, 0x91B8, 0xBAD7, 0x91B9, 0xBAD8, 0xB8FC, 0xBAD9, 0xB8FD, 0xBADA, 0x91BA, 0xBADB, 0x91BB, + 0xBADC, 0x91BC, 0xBADD, 0x91BD, 0xBADE, 0x91BE, 0xBADF, 0x91BF, 0xBAE0, 0x91C0, 0xBAE1, 0x91C1, 0xBAE2, 0x91C2, 0xBAE3, 0x91C3, + 0xBAE4, 0x91C4, 0xBAE5, 0x91C5, 0xBAE6, 0x91C6, 0xBAE7, 0x91C7, 0xBAE8, 0x91C8, 0xBAE9, 0x91C9, 0xBAEA, 0x91CA, 0xBAEB, 0x91CB, + 0xBAEC, 0x91CC, 0xBAED, 0x91CD, 0xBAEE, 0x91CE, 0xBAEF, 0x91CF, 0xBAF0, 0x91D0, 0xBAF1, 0x91D1, 0xBAF2, 0x91D2, 0xBAF3, 0x91D3, + 0xBAF4, 0x91D4, 0xBAF5, 0x91D5, 0xBAF6, 0x91D6, 0xBAF7, 0x91D7, 0xBAF8, 0x91D8, 0xBAF9, 0x91D9, 0xBAFA, 0x91DA, 0xBAFB, 0x91DB, + 0xBAFC, 0xB8FE, 0xBAFD, 0x91DC, 0xBAFE, 0x91DD, 0xBAFF, 0x91DE, 0xBB00, 0xB9A1, 0xBB01, 0x91DF, 0xBB02, 0x91E0, 0xBB03, 0x91E1, + 0xBB04, 0xB9A2, 0xBB05, 0x91E2, 0xBB06, 0x91E3, 0xBB07, 0x91E4, 0xBB08, 0x91E5, 0xBB09, 0x91E6, 0xBB0A, 0x91E7, 0xBB0B, 0x91E8, + 0xBB0C, 0x91E9, 0xBB0D, 0xB9A3, 0xBB0E, 0x91EA, 0xBB0F, 0xB9A4, 0xBB10, 0x91EB, 0xBB11, 0xB9A5, 0xBB12, 0x91EC, 0xBB13, 0x91ED, + 0xBB14, 0x91EE, 0xBB15, 0x91EF, 0xBB16, 0x91F0, 0xBB17, 0x91F1, 0xBB18, 0xB9A6, 0xBB19, 0x91F2, 0xBB1A, 0x91F3, 0xBB1B, 0x91F4, + 0xBB1C, 0xB9A7, 0xBB1D, 0x91F5, 0xBB1E, 0x91F6, 0xBB1F, 0x91F7, 0xBB20, 0xB9A8, 0xBB21, 0x91F8, 0xBB22, 0x91F9, 0xBB23, 0x91FA, + 0xBB24, 0x91FB, 0xBB25, 0x91FC, 0xBB26, 0x91FD, 0xBB27, 0x91FE, 0xBB28, 0x9241, 0xBB29, 0xB9A9, 0xBB2A, 0x9242, 0xBB2B, 0xB9AA, + 0xBB2C, 0x9243, 0xBB2D, 0x9244, 0xBB2E, 0x9245, 0xBB2F, 0x9246, 0xBB30, 0x9247, 0xBB31, 0x9248, 0xBB32, 0x9249, 0xBB33, 0x924A, + 0xBB34, 0xB9AB, 0xBB35, 0xB9AC, 0xBB36, 0xB9AD, 0xBB37, 0x924B, 0xBB38, 0xB9AE, 0xBB39, 0x924C, 0xBB3A, 0x924D, 0xBB3B, 0xB9AF, + 0xBB3C, 0xB9B0, 0xBB3D, 0xB9B1, 0xBB3E, 0xB9B2, 0xBB3F, 0x924E, 0xBB40, 0x924F, 0xBB41, 0x9250, 0xBB42, 0x9251, 0xBB43, 0x9252, + 0xBB44, 0xB9B3, 0xBB45, 0xB9B4, 0xBB46, 0x9253, 0xBB47, 0xB9B5, 0xBB48, 0x9254, 0xBB49, 0xB9B6, 0xBB4A, 0x9255, 0xBB4B, 0x9256, + 0xBB4C, 0x9257, 0xBB4D, 0xB9B7, 0xBB4E, 0x9258, 0xBB4F, 0xB9B8, 0xBB50, 0xB9B9, 0xBB51, 0x9259, 0xBB52, 0x925A, 0xBB53, 0x9261, + 0xBB54, 0xB9BA, 0xBB55, 0x9262, 0xBB56, 0x9263, 0xBB57, 0x9264, 0xBB58, 0xB9BB, 0xBB59, 0x9265, 0xBB5A, 0x9266, 0xBB5B, 0x9267, + 0xBB5C, 0x9268, 0xBB5D, 0x9269, 0xBB5E, 0x926A, 0xBB5F, 0x926B, 0xBB60, 0x926C, 0xBB61, 0xB9BC, 0xBB62, 0x926D, 0xBB63, 0xB9BD, + 0xBB64, 0x926E, 0xBB65, 0x926F, 0xBB66, 0x9270, 0xBB67, 0x9271, 0xBB68, 0x9272, 0xBB69, 0x9273, 0xBB6A, 0x9274, 0xBB6B, 0x9275, + 0xBB6C, 0xB9BE, 0xBB6D, 0x9276, 0xBB6E, 0x9277, 0xBB6F, 0x9278, 0xBB70, 0x9279, 0xBB71, 0x927A, 0xBB72, 0x9281, 0xBB73, 0x9282, + 0xBB74, 0x9283, 0xBB75, 0x9284, 0xBB76, 0x9285, 0xBB77, 0x9286, 0xBB78, 0x9287, 0xBB79, 0x9288, 0xBB7A, 0x9289, 0xBB7B, 0x928A, + 0xBB7C, 0x928B, 0xBB7D, 0x928C, 0xBB7E, 0x928D, 0xBB7F, 0x928E, 0xBB80, 0x928F, 0xBB81, 0x9290, 0xBB82, 0x9291, 0xBB83, 0x9292, + 0xBB84, 0x9293, 0xBB85, 0x9294, 0xBB86, 0x9295, 0xBB87, 0x9296, 0xBB88, 0xB9BF, 0xBB89, 0x9297, 0xBB8A, 0x9298, 0xBB8B, 0x9299, + 0xBB8C, 0xB9C0, 0xBB8D, 0x929A, 0xBB8E, 0x929B, 0xBB8F, 0x929C, 0xBB90, 0xB9C1, 0xBB91, 0x929D, 0xBB92, 0x929E, 0xBB93, 0x929F, + 0xBB94, 0x92A0, 0xBB95, 0x92A1, 0xBB96, 0x92A2, 0xBB97, 0x92A3, 0xBB98, 0x92A4, 0xBB99, 0x92A5, 0xBB9A, 0x92A6, 0xBB9B, 0x92A7, + 0xBB9C, 0x92A8, 0xBB9D, 0x92A9, 0xBB9E, 0x92AA, 0xBB9F, 0x92AB, 0xBBA0, 0x92AC, 0xBBA1, 0x92AD, 0xBBA2, 0x92AE, 0xBBA3, 0x92AF, + 0xBBA4, 0xB9C2, 0xBBA5, 0x92B0, 0xBBA6, 0x92B1, 0xBBA7, 0x92B2, 0xBBA8, 0xB9C3, 0xBBA9, 0x92B3, 0xBBAA, 0x92B4, 0xBBAB, 0x92B5, + 0xBBAC, 0xB9C4, 0xBBAD, 0x92B6, 0xBBAE, 0x92B7, 0xBBAF, 0x92B8, 0xBBB0, 0x92B9, 0xBBB1, 0x92BA, 0xBBB2, 0x92BB, 0xBBB3, 0x92BC, + 0xBBB4, 0xB9C5, 0xBBB5, 0x92BD, 0xBBB6, 0x92BE, 0xBBB7, 0xB9C6, 0xBBB8, 0x92BF, 0xBBB9, 0x92C0, 0xBBBA, 0x92C1, 0xBBBB, 0x92C2, + 0xBBBC, 0x92C3, 0xBBBD, 0x92C4, 0xBBBE, 0x92C5, 0xBBBF, 0x92C6, 0xBBC0, 0xB9C7, 0xBBC1, 0x92C7, 0xBBC2, 0x92C8, 0xBBC3, 0x92C9, + 0xBBC4, 0xB9C8, 0xBBC5, 0x92CA, 0xBBC6, 0x92CB, 0xBBC7, 0x92CC, 0xBBC8, 0xB9C9, 0xBBC9, 0x92CD, 0xBBCA, 0x92CE, 0xBBCB, 0x92CF, + 0xBBCC, 0x92D0, 0xBBCD, 0x92D1, 0xBBCE, 0x92D2, 0xBBCF, 0x92D3, 0xBBD0, 0xB9CA, 0xBBD1, 0x92D4, 0xBBD2, 0x92D5, 0xBBD3, 0xB9CB, + 0xBBD4, 0x92D6, 0xBBD5, 0x92D7, 0xBBD6, 0x92D8, 0xBBD7, 0x92D9, 0xBBD8, 0x92DA, 0xBBD9, 0x92DB, 0xBBDA, 0x92DC, 0xBBDB, 0x92DD, + 0xBBDC, 0x92DE, 0xBBDD, 0x92DF, 0xBBDE, 0x92E0, 0xBBDF, 0x92E1, 0xBBE0, 0x92E2, 0xBBE1, 0x92E3, 0xBBE2, 0x92E4, 0xBBE3, 0x92E5, + 0xBBE4, 0x92E6, 0xBBE5, 0x92E7, 0xBBE6, 0x92E8, 0xBBE7, 0x92E9, 0xBBE8, 0x92EA, 0xBBE9, 0x92EB, 0xBBEA, 0x92EC, 0xBBEB, 0x92ED, + 0xBBEC, 0x92EE, 0xBBED, 0x92EF, 0xBBEE, 0x92F0, 0xBBEF, 0x92F1, 0xBBF0, 0x92F2, 0xBBF1, 0x92F3, 0xBBF2, 0x92F4, 0xBBF3, 0x92F5, + 0xBBF4, 0x92F6, 0xBBF5, 0x92F7, 0xBBF6, 0x92F8, 0xBBF7, 0x92F9, 0xBBF8, 0xB9CC, 0xBBF9, 0xB9CD, 0xBBFA, 0x92FA, 0xBBFB, 0x92FB, + 0xBBFC, 0xB9CE, 0xBBFD, 0x92FC, 0xBBFE, 0x92FD, 0xBBFF, 0xB9CF, 0xBC00, 0xB9D0, 0xBC01, 0x92FE, 0xBC02, 0xB9D1, 0xBC03, 0x9341, + 0xBC04, 0x9342, 0xBC05, 0x9343, 0xBC06, 0x9344, 0xBC07, 0x9345, 0xBC08, 0xB9D2, 0xBC09, 0xB9D3, 0xBC0A, 0x9346, 0xBC0B, 0xB9D4, + 0xBC0C, 0xB9D5, 0xBC0D, 0xB9D6, 0xBC0E, 0x9347, 0xBC0F, 0xB9D7, 0xBC10, 0x9348, 0xBC11, 0xB9D8, 0xBC12, 0x9349, 0xBC13, 0x934A, + 0xBC14, 0xB9D9, 0xBC15, 0xB9DA, 0xBC16, 0xB9DB, 0xBC17, 0xB9DC, 0xBC18, 0xB9DD, 0xBC19, 0x934B, 0xBC1A, 0x934C, 0xBC1B, 0xB9DE, + 0xBC1C, 0xB9DF, 0xBC1D, 0xB9E0, 0xBC1E, 0xB9E1, 0xBC1F, 0xB9E2, 0xBC20, 0x934D, 0xBC21, 0x934E, 0xBC22, 0x934F, 0xBC23, 0x9350, + 0xBC24, 0xB9E3, 0xBC25, 0xB9E4, 0xBC26, 0x9351, 0xBC27, 0xB9E5, 0xBC28, 0x9352, 0xBC29, 0xB9E6, 0xBC2A, 0x9353, 0xBC2B, 0x9354, + 0xBC2C, 0x9355, 0xBC2D, 0xB9E7, 0xBC2E, 0x9356, 0xBC2F, 0x9357, 0xBC30, 0xB9E8, 0xBC31, 0xB9E9, 0xBC32, 0x9358, 0xBC33, 0x9359, + 0xBC34, 0xB9EA, 0xBC35, 0x935A, 0xBC36, 0x9361, 0xBC37, 0x9362, 0xBC38, 0xB9EB, 0xBC39, 0x9363, 0xBC3A, 0x9364, 0xBC3B, 0x9365, + 0xBC3C, 0x9366, 0xBC3D, 0x9367, 0xBC3E, 0x9368, 0xBC3F, 0x9369, 0xBC40, 0xB9EC, 0xBC41, 0xB9ED, 0xBC42, 0x936A, 0xBC43, 0xB9EE, + 0xBC44, 0xB9EF, 0xBC45, 0xB9F0, 0xBC46, 0x936B, 0xBC47, 0x936C, 0xBC48, 0x936D, 0xBC49, 0xB9F1, 0xBC4A, 0x936E, 0xBC4B, 0x936F, + 0xBC4C, 0xB9F2, 0xBC4D, 0xB9F3, 0xBC4E, 0x9370, 0xBC4F, 0x9371, 0xBC50, 0xB9F4, 0xBC51, 0x9372, 0xBC52, 0x9373, 0xBC53, 0x9374, + 0xBC54, 0x9375, 0xBC55, 0x9376, 0xBC56, 0x9377, 0xBC57, 0x9378, 0xBC58, 0x9379, 0xBC59, 0x937A, 0xBC5A, 0x9381, 0xBC5B, 0x9382, + 0xBC5C, 0x9383, 0xBC5D, 0xB9F5, 0xBC5E, 0x9384, 0xBC5F, 0x9385, 0xBC60, 0x9386, 0xBC61, 0x9387, 0xBC62, 0x9388, 0xBC63, 0x9389, + 0xBC64, 0x938A, 0xBC65, 0x938B, 0xBC66, 0x938C, 0xBC67, 0x938D, 0xBC68, 0x938E, 0xBC69, 0x938F, 0xBC6A, 0x9390, 0xBC6B, 0x9391, + 0xBC6C, 0x9392, 0xBC6D, 0x9393, 0xBC6E, 0x9394, 0xBC6F, 0x9395, 0xBC70, 0x9396, 0xBC71, 0x9397, 0xBC72, 0x9398, 0xBC73, 0x9399, + 0xBC74, 0x939A, 0xBC75, 0x939B, 0xBC76, 0x939C, 0xBC77, 0x939D, 0xBC78, 0x939E, 0xBC79, 0x939F, 0xBC7A, 0x93A0, 0xBC7B, 0x93A1, + 0xBC7C, 0x93A2, 0xBC7D, 0x93A3, 0xBC7E, 0x93A4, 0xBC7F, 0x93A5, 0xBC80, 0x93A6, 0xBC81, 0x93A7, 0xBC82, 0x93A8, 0xBC83, 0x93A9, + 0xBC84, 0xB9F6, 0xBC85, 0xB9F7, 0xBC86, 0x93AA, 0xBC87, 0x93AB, 0xBC88, 0xB9F8, 0xBC89, 0x93AC, 0xBC8A, 0x93AD, 0xBC8B, 0xB9F9, + 0xBC8C, 0xB9FA, 0xBC8D, 0x93AE, 0xBC8E, 0xB9FB, 0xBC8F, 0x93AF, 0xBC90, 0x93B0, 0xBC91, 0x93B1, 0xBC92, 0x93B2, 0xBC93, 0x93B3, + 0xBC94, 0xB9FC, 0xBC95, 0xB9FD, 0xBC96, 0x93B4, 0xBC97, 0xB9FE, 0xBC98, 0x93B5, 0xBC99, 0xBAA1, 0xBC9A, 0xBAA2, 0xBC9B, 0x93B6, + 0xBC9C, 0x93B7, 0xBC9D, 0x93B8, 0xBC9E, 0x93B9, 0xBC9F, 0x93BA, 0xBCA0, 0xBAA3, 0xBCA1, 0xBAA4, 0xBCA2, 0x93BB, 0xBCA3, 0x93BC, + 0xBCA4, 0xBAA5, 0xBCA5, 0x93BD, 0xBCA6, 0x93BE, 0xBCA7, 0xBAA6, 0xBCA8, 0xBAA7, 0xBCA9, 0x93BF, 0xBCAA, 0x93C0, 0xBCAB, 0x93C1, + 0xBCAC, 0x93C2, 0xBCAD, 0x93C3, 0xBCAE, 0x93C4, 0xBCAF, 0x93C5, 0xBCB0, 0xBAA8, 0xBCB1, 0xBAA9, 0xBCB2, 0x93C6, 0xBCB3, 0xBAAA, + 0xBCB4, 0xBAAB, 0xBCB5, 0xBAAC, 0xBCB6, 0x93C7, 0xBCB7, 0x93C8, 0xBCB8, 0x93C9, 0xBCB9, 0x93CA, 0xBCBA, 0x93CB, 0xBCBB, 0x93CC, + 0xBCBC, 0xBAAD, 0xBCBD, 0xBAAE, 0xBCBE, 0x93CD, 0xBCBF, 0x93CE, 0xBCC0, 0xBAAF, 0xBCC1, 0x93CF, 0xBCC2, 0x93D0, 0xBCC3, 0x93D1, + 0xBCC4, 0xBAB0, 0xBCC5, 0x93D2, 0xBCC6, 0x93D3, 0xBCC7, 0x93D4, 0xBCC8, 0x93D5, 0xBCC9, 0x93D6, 0xBCCA, 0x93D7, 0xBCCB, 0x93D8, + 0xBCCC, 0x93D9, 0xBCCD, 0xBAB1, 0xBCCE, 0x93DA, 0xBCCF, 0xBAB2, 0xBCD0, 0xBAB3, 0xBCD1, 0xBAB4, 0xBCD2, 0x93DB, 0xBCD3, 0x93DC, + 0xBCD4, 0x93DD, 0xBCD5, 0xBAB5, 0xBCD6, 0x93DE, 0xBCD7, 0x93DF, 0xBCD8, 0xBAB6, 0xBCD9, 0x93E0, 0xBCDA, 0x93E1, 0xBCDB, 0x93E2, + 0xBCDC, 0xBAB7, 0xBCDD, 0x93E3, 0xBCDE, 0x93E4, 0xBCDF, 0x93E5, 0xBCE0, 0x93E6, 0xBCE1, 0x93E7, 0xBCE2, 0x93E8, 0xBCE3, 0x93E9, + 0xBCE4, 0x93EA, 0xBCE5, 0x93EB, 0xBCE6, 0x93EC, 0xBCE7, 0x93ED, 0xBCE8, 0x93EE, 0xBCE9, 0x93EF, 0xBCEA, 0x93F0, 0xBCEB, 0x93F1, + 0xBCEC, 0x93F2, 0xBCED, 0x93F3, 0xBCEE, 0x93F4, 0xBCEF, 0x93F5, 0xBCF0, 0x93F6, 0xBCF1, 0x93F7, 0xBCF2, 0x93F8, 0xBCF3, 0x93F9, + 0xBCF4, 0xBAB8, 0xBCF5, 0xBAB9, 0xBCF6, 0xBABA, 0xBCF7, 0x93FA, 0xBCF8, 0xBABB, 0xBCF9, 0x93FB, 0xBCFA, 0x93FC, 0xBCFB, 0x93FD, + 0xBCFC, 0xBABC, 0xBCFD, 0x93FE, 0xBCFE, 0x9441, 0xBCFF, 0x9442, 0xBD00, 0x9443, 0xBD01, 0x9444, 0xBD02, 0x9445, 0xBD03, 0x9446, + 0xBD04, 0xBABD, 0xBD05, 0xBABE, 0xBD06, 0x9447, 0xBD07, 0xBABF, 0xBD08, 0x9448, 0xBD09, 0xBAC0, 0xBD0A, 0x9449, 0xBD0B, 0x944A, + 0xBD0C, 0x944B, 0xBD0D, 0x944C, 0xBD0E, 0x944D, 0xBD0F, 0x944E, 0xBD10, 0xBAC1, 0xBD11, 0x944F, 0xBD12, 0x9450, 0xBD13, 0x9451, + 0xBD14, 0xBAC2, 0xBD15, 0x9452, 0xBD16, 0x9453, 0xBD17, 0x9454, 0xBD18, 0x9455, 0xBD19, 0x9456, 0xBD1A, 0x9457, 0xBD1B, 0x9458, + 0xBD1C, 0x9459, 0xBD1D, 0x945A, 0xBD1E, 0x9461, 0xBD1F, 0x9462, 0xBD20, 0x9463, 0xBD21, 0x9464, 0xBD22, 0x9465, 0xBD23, 0x9466, + 0xBD24, 0xBAC3, 0xBD25, 0x9467, 0xBD26, 0x9468, 0xBD27, 0x9469, 0xBD28, 0x946A, 0xBD29, 0x946B, 0xBD2A, 0x946C, 0xBD2B, 0x946D, + 0xBD2C, 0xBAC4, 0xBD2D, 0x946E, 0xBD2E, 0x946F, 0xBD2F, 0x9470, 0xBD30, 0x9471, 0xBD31, 0x9472, 0xBD32, 0x9473, 0xBD33, 0x9474, + 0xBD34, 0x9475, 0xBD35, 0x9476, 0xBD36, 0x9477, 0xBD37, 0x9478, 0xBD38, 0x9479, 0xBD39, 0x947A, 0xBD3A, 0x9481, 0xBD3B, 0x9482, + 0xBD3C, 0x9483, 0xBD3D, 0x9484, 0xBD3E, 0x9485, 0xBD3F, 0x9486, 0xBD40, 0xBAC5, 0xBD41, 0x9487, 0xBD42, 0x9488, 0xBD43, 0x9489, + 0xBD44, 0x948A, 0xBD45, 0x948B, 0xBD46, 0x948C, 0xBD47, 0x948D, 0xBD48, 0xBAC6, 0xBD49, 0xBAC7, 0xBD4A, 0x948E, 0xBD4B, 0x948F, + 0xBD4C, 0xBAC8, 0xBD4D, 0x9490, 0xBD4E, 0x9491, 0xBD4F, 0x9492, 0xBD50, 0xBAC9, 0xBD51, 0x9493, 0xBD52, 0x9494, 0xBD53, 0x9495, + 0xBD54, 0x9496, 0xBD55, 0x9497, 0xBD56, 0x9498, 0xBD57, 0x9499, 0xBD58, 0xBACA, 0xBD59, 0xBACB, 0xBD5A, 0x949A, 0xBD5B, 0x949B, + 0xBD5C, 0x949C, 0xBD5D, 0x949D, 0xBD5E, 0x949E, 0xBD5F, 0x949F, 0xBD60, 0x94A0, 0xBD61, 0x94A1, 0xBD62, 0x94A2, 0xBD63, 0x94A3, + 0xBD64, 0xBACC, 0xBD65, 0x94A4, 0xBD66, 0x94A5, 0xBD67, 0x94A6, 0xBD68, 0xBACD, 0xBD69, 0x94A7, 0xBD6A, 0x94A8, 0xBD6B, 0x94A9, + 0xBD6C, 0x94AA, 0xBD6D, 0x94AB, 0xBD6E, 0x94AC, 0xBD6F, 0x94AD, 0xBD70, 0x94AE, 0xBD71, 0x94AF, 0xBD72, 0x94B0, 0xBD73, 0x94B1, + 0xBD74, 0x94B2, 0xBD75, 0x94B3, 0xBD76, 0x94B4, 0xBD77, 0x94B5, 0xBD78, 0x94B6, 0xBD79, 0x94B7, 0xBD7A, 0x94B8, 0xBD7B, 0x94B9, + 0xBD7C, 0x94BA, 0xBD7D, 0x94BB, 0xBD7E, 0x94BC, 0xBD7F, 0x94BD, 0xBD80, 0xBACE, 0xBD81, 0xBACF, 0xBD82, 0x94BE, 0xBD83, 0x94BF, + 0xBD84, 0xBAD0, 0xBD85, 0x94C0, 0xBD86, 0x94C1, 0xBD87, 0xBAD1, 0xBD88, 0xBAD2, 0xBD89, 0xBAD3, 0xBD8A, 0xBAD4, 0xBD8B, 0x94C2, + 0xBD8C, 0x94C3, 0xBD8D, 0x94C4, 0xBD8E, 0x94C5, 0xBD8F, 0x94C6, 0xBD90, 0xBAD5, 0xBD91, 0xBAD6, 0xBD92, 0x94C7, 0xBD93, 0xBAD7, + 0xBD94, 0x94C8, 0xBD95, 0xBAD8, 0xBD96, 0x94C9, 0xBD97, 0x94CA, 0xBD98, 0x94CB, 0xBD99, 0xBAD9, 0xBD9A, 0xBADA, 0xBD9B, 0x94CC, + 0xBD9C, 0xBADB, 0xBD9D, 0x94CD, 0xBD9E, 0x94CE, 0xBD9F, 0x94CF, 0xBDA0, 0x94D0, 0xBDA1, 0x94D1, 0xBDA2, 0x94D2, 0xBDA3, 0x94D3, + 0xBDA4, 0xBADC, 0xBDA5, 0x94D4, 0xBDA6, 0x94D5, 0xBDA7, 0x94D6, 0xBDA8, 0x94D7, 0xBDA9, 0x94D8, 0xBDAA, 0x94D9, 0xBDAB, 0x94DA, + 0xBDAC, 0x94DB, 0xBDAD, 0x94DC, 0xBDAE, 0x94DD, 0xBDAF, 0x94DE, 0xBDB0, 0xBADD, 0xBDB1, 0x94DF, 0xBDB2, 0x94E0, 0xBDB3, 0x94E1, + 0xBDB4, 0x94E2, 0xBDB5, 0x94E3, 0xBDB6, 0x94E4, 0xBDB7, 0x94E5, 0xBDB8, 0xBADE, 0xBDB9, 0x94E6, 0xBDBA, 0x94E7, 0xBDBB, 0x94E8, + 0xBDBC, 0x94E9, 0xBDBD, 0x94EA, 0xBDBE, 0x94EB, 0xBDBF, 0x94EC, 0xBDC0, 0x94ED, 0xBDC1, 0x94EE, 0xBDC2, 0x94EF, 0xBDC3, 0x94F0, + 0xBDC4, 0x94F1, 0xBDC5, 0x94F2, 0xBDC6, 0x94F3, 0xBDC7, 0x94F4, 0xBDC8, 0x94F5, 0xBDC9, 0x94F6, 0xBDCA, 0x94F7, 0xBDCB, 0x94F8, + 0xBDCC, 0x94F9, 0xBDCD, 0x94FA, 0xBDCE, 0x94FB, 0xBDCF, 0x94FC, 0xBDD0, 0x94FD, 0xBDD1, 0x94FE, 0xBDD2, 0x9541, 0xBDD3, 0x9542, + 0xBDD4, 0xBADF, 0xBDD5, 0xBAE0, 0xBDD6, 0x9543, 0xBDD7, 0x9544, 0xBDD8, 0xBAE1, 0xBDD9, 0x9545, 0xBDDA, 0x9546, 0xBDDB, 0x9547, + 0xBDDC, 0xBAE2, 0xBDDD, 0x9548, 0xBDDE, 0x9549, 0xBDDF, 0x954A, 0xBDE0, 0x954B, 0xBDE1, 0x954C, 0xBDE2, 0x954D, 0xBDE3, 0x954E, + 0xBDE4, 0x954F, 0xBDE5, 0x9550, 0xBDE6, 0x9551, 0xBDE7, 0x9552, 0xBDE8, 0x9553, 0xBDE9, 0xBAE3, 0xBDEA, 0x9554, 0xBDEB, 0x9555, + 0xBDEC, 0x9556, 0xBDED, 0x9557, 0xBDEE, 0x9558, 0xBDEF, 0x9559, 0xBDF0, 0xBAE4, 0xBDF1, 0x955A, 0xBDF2, 0x9561, 0xBDF3, 0x9562, + 0xBDF4, 0xBAE5, 0xBDF5, 0x9563, 0xBDF6, 0x9564, 0xBDF7, 0x9565, 0xBDF8, 0xBAE6, 0xBDF9, 0x9566, 0xBDFA, 0x9567, 0xBDFB, 0x9568, + 0xBDFC, 0x9569, 0xBDFD, 0x956A, 0xBDFE, 0x956B, 0xBDFF, 0x956C, 0xBE00, 0xBAE7, 0xBE01, 0x956D, 0xBE02, 0x956E, 0xBE03, 0xBAE8, + 0xBE04, 0x956F, 0xBE05, 0xBAE9, 0xBE06, 0x9570, 0xBE07, 0x9571, 0xBE08, 0x9572, 0xBE09, 0x9573, 0xBE0A, 0x9574, 0xBE0B, 0x9575, + 0xBE0C, 0xBAEA, 0xBE0D, 0xBAEB, 0xBE0E, 0x9576, 0xBE0F, 0x9577, 0xBE10, 0xBAEC, 0xBE11, 0x9578, 0xBE12, 0x9579, 0xBE13, 0x957A, + 0xBE14, 0xBAED, 0xBE15, 0x9581, 0xBE16, 0x9582, 0xBE17, 0x9583, 0xBE18, 0x9584, 0xBE19, 0x9585, 0xBE1A, 0x9586, 0xBE1B, 0x9587, + 0xBE1C, 0xBAEE, 0xBE1D, 0xBAEF, 0xBE1E, 0x9588, 0xBE1F, 0xBAF0, 0xBE20, 0x9589, 0xBE21, 0x958A, 0xBE22, 0x958B, 0xBE23, 0x958C, + 0xBE24, 0x958D, 0xBE25, 0x958E, 0xBE26, 0x958F, 0xBE27, 0x9590, 0xBE28, 0x9591, 0xBE29, 0x9592, 0xBE2A, 0x9593, 0xBE2B, 0x9594, + 0xBE2C, 0x9595, 0xBE2D, 0x9596, 0xBE2E, 0x9597, 0xBE2F, 0x9598, 0xBE30, 0x9599, 0xBE31, 0x959A, 0xBE32, 0x959B, 0xBE33, 0x959C, + 0xBE34, 0x959D, 0xBE35, 0x959E, 0xBE36, 0x959F, 0xBE37, 0x95A0, 0xBE38, 0x95A1, 0xBE39, 0x95A2, 0xBE3A, 0x95A3, 0xBE3B, 0x95A4, + 0xBE3C, 0x95A5, 0xBE3D, 0x95A6, 0xBE3E, 0x95A7, 0xBE3F, 0x95A8, 0xBE40, 0x95A9, 0xBE41, 0x95AA, 0xBE42, 0x95AB, 0xBE43, 0x95AC, + 0xBE44, 0xBAF1, 0xBE45, 0xBAF2, 0xBE46, 0x95AD, 0xBE47, 0x95AE, 0xBE48, 0xBAF3, 0xBE49, 0x95AF, 0xBE4A, 0x95B0, 0xBE4B, 0x95B1, + 0xBE4C, 0xBAF4, 0xBE4D, 0x95B2, 0xBE4E, 0xBAF5, 0xBE4F, 0x95B3, 0xBE50, 0x95B4, 0xBE51, 0x95B5, 0xBE52, 0x95B6, 0xBE53, 0x95B7, + 0xBE54, 0xBAF6, 0xBE55, 0xBAF7, 0xBE56, 0x95B8, 0xBE57, 0xBAF8, 0xBE58, 0x95B9, 0xBE59, 0xBAF9, 0xBE5A, 0xBAFA, 0xBE5B, 0xBAFB, + 0xBE5C, 0x95BA, 0xBE5D, 0x95BB, 0xBE5E, 0x95BC, 0xBE5F, 0x95BD, 0xBE60, 0xBAFC, 0xBE61, 0xBAFD, 0xBE62, 0x95BE, 0xBE63, 0x95BF, + 0xBE64, 0xBAFE, 0xBE65, 0x95C0, 0xBE66, 0x95C1, 0xBE67, 0x95C2, 0xBE68, 0xBBA1, 0xBE69, 0x95C3, 0xBE6A, 0xBBA2, 0xBE6B, 0x95C4, + 0xBE6C, 0x95C5, 0xBE6D, 0x95C6, 0xBE6E, 0x95C7, 0xBE6F, 0x95C8, 0xBE70, 0xBBA3, 0xBE71, 0xBBA4, 0xBE72, 0x95C9, 0xBE73, 0xBBA5, + 0xBE74, 0xBBA6, 0xBE75, 0xBBA7, 0xBE76, 0x95CA, 0xBE77, 0x95CB, 0xBE78, 0x95CC, 0xBE79, 0x95CD, 0xBE7A, 0x95CE, 0xBE7B, 0xBBA8, + 0xBE7C, 0xBBA9, 0xBE7D, 0xBBAA, 0xBE7E, 0x95CF, 0xBE7F, 0x95D0, 0xBE80, 0xBBAB, 0xBE81, 0x95D1, 0xBE82, 0x95D2, 0xBE83, 0x95D3, + 0xBE84, 0xBBAC, 0xBE85, 0x95D4, 0xBE86, 0x95D5, 0xBE87, 0x95D6, 0xBE88, 0x95D7, 0xBE89, 0x95D8, 0xBE8A, 0x95D9, 0xBE8B, 0x95DA, + 0xBE8C, 0xBBAD, 0xBE8D, 0xBBAE, 0xBE8E, 0x95DB, 0xBE8F, 0xBBAF, 0xBE90, 0xBBB0, 0xBE91, 0xBBB1, 0xBE92, 0x95DC, 0xBE93, 0x95DD, + 0xBE94, 0x95DE, 0xBE95, 0x95DF, 0xBE96, 0x95E0, 0xBE97, 0x95E1, 0xBE98, 0xBBB2, 0xBE99, 0xBBB3, 0xBE9A, 0x95E2, 0xBE9B, 0x95E3, + 0xBE9C, 0x95E4, 0xBE9D, 0x95E5, 0xBE9E, 0x95E6, 0xBE9F, 0x95E7, 0xBEA0, 0x95E8, 0xBEA1, 0x95E9, 0xBEA2, 0x95EA, 0xBEA3, 0x95EB, + 0xBEA4, 0x95EC, 0xBEA5, 0x95ED, 0xBEA6, 0x95EE, 0xBEA7, 0x95EF, 0xBEA8, 0xBBB4, 0xBEA9, 0x95F0, 0xBEAA, 0x95F1, 0xBEAB, 0x95F2, + 0xBEAC, 0x95F3, 0xBEAD, 0x95F4, 0xBEAE, 0x95F5, 0xBEAF, 0x95F6, 0xBEB0, 0x95F7, 0xBEB1, 0x95F8, 0xBEB2, 0x95F9, 0xBEB3, 0x95FA, + 0xBEB4, 0x95FB, 0xBEB5, 0x95FC, 0xBEB6, 0x95FD, 0xBEB7, 0x95FE, 0xBEB8, 0x9641, 0xBEB9, 0x9642, 0xBEBA, 0x9643, 0xBEBB, 0x9644, + 0xBEBC, 0x9645, 0xBEBD, 0x9646, 0xBEBE, 0x9647, 0xBEBF, 0x9648, 0xBEC0, 0x9649, 0xBEC1, 0x964A, 0xBEC2, 0x964B, 0xBEC3, 0x964C, + 0xBEC4, 0x964D, 0xBEC5, 0x964E, 0xBEC6, 0x964F, 0xBEC7, 0x9650, 0xBEC8, 0x9651, 0xBEC9, 0x9652, 0xBECA, 0x9653, 0xBECB, 0x9654, + 0xBECC, 0x9655, 0xBECD, 0x9656, 0xBECE, 0x9657, 0xBECF, 0x9658, 0xBED0, 0xBBB5, 0xBED1, 0xBBB6, 0xBED2, 0x9659, 0xBED3, 0x965A, + 0xBED4, 0xBBB7, 0xBED5, 0x9661, 0xBED6, 0x9662, 0xBED7, 0xBBB8, 0xBED8, 0xBBB9, 0xBED9, 0x9663, 0xBEDA, 0x9664, 0xBEDB, 0x9665, + 0xBEDC, 0x9666, 0xBEDD, 0x9667, 0xBEDE, 0x9668, 0xBEDF, 0x9669, 0xBEE0, 0xBBBA, 0xBEE1, 0x966A, 0xBEE2, 0x966B, 0xBEE3, 0xBBBB, + 0xBEE4, 0xBBBC, 0xBEE5, 0xBBBD, 0xBEE6, 0x966C, 0xBEE7, 0x966D, 0xBEE8, 0x966E, 0xBEE9, 0x966F, 0xBEEA, 0x9670, 0xBEEB, 0x9671, + 0xBEEC, 0xBBBE, 0xBEED, 0x9672, 0xBEEE, 0x9673, 0xBEEF, 0x9674, 0xBEF0, 0x9675, 0xBEF1, 0x9676, 0xBEF2, 0x9677, 0xBEF3, 0x9678, + 0xBEF4, 0x9679, 0xBEF5, 0x967A, 0xBEF6, 0x9681, 0xBEF7, 0x9682, 0xBEF8, 0x9683, 0xBEF9, 0x9684, 0xBEFA, 0x9685, 0xBEFB, 0x9686, + 0xBEFC, 0x9687, 0xBEFD, 0x9688, 0xBEFE, 0x9689, 0xBEFF, 0x968A, 0xBF00, 0x968B, 0xBF01, 0xBBBF, 0xBF02, 0x968C, 0xBF03, 0x968D, + 0xBF04, 0x968E, 0xBF05, 0x968F, 0xBF06, 0x9690, 0xBF07, 0x9691, 0xBF08, 0xBBC0, 0xBF09, 0xBBC1, 0xBF0A, 0x9692, 0xBF0B, 0x9693, + 0xBF0C, 0x9694, 0xBF0D, 0x9695, 0xBF0E, 0x9696, 0xBF0F, 0x9697, 0xBF10, 0x9698, 0xBF11, 0x9699, 0xBF12, 0x969A, 0xBF13, 0x969B, + 0xBF14, 0x969C, 0xBF15, 0x969D, 0xBF16, 0x969E, 0xBF17, 0x969F, 0xBF18, 0xBBC2, 0xBF19, 0xBBC3, 0xBF1A, 0x96A0, 0xBF1B, 0xBBC4, + 0xBF1C, 0xBBC5, 0xBF1D, 0xBBC6, 0xBF1E, 0x96A1, 0xBF1F, 0x96A2, 0xBF20, 0x96A3, 0xBF21, 0x96A4, 0xBF22, 0x96A5, 0xBF23, 0x96A6, + 0xBF24, 0x96A7, 0xBF25, 0x96A8, 0xBF26, 0x96A9, 0xBF27, 0x96AA, 0xBF28, 0x96AB, 0xBF29, 0x96AC, 0xBF2A, 0x96AD, 0xBF2B, 0x96AE, + 0xBF2C, 0x96AF, 0xBF2D, 0x96B0, 0xBF2E, 0x96B1, 0xBF2F, 0x96B2, 0xBF30, 0x96B3, 0xBF31, 0x96B4, 0xBF32, 0x96B5, 0xBF33, 0x96B6, + 0xBF34, 0x96B7, 0xBF35, 0x96B8, 0xBF36, 0x96B9, 0xBF37, 0x96BA, 0xBF38, 0x96BB, 0xBF39, 0x96BC, 0xBF3A, 0x96BD, 0xBF3B, 0x96BE, + 0xBF3C, 0x96BF, 0xBF3D, 0x96C0, 0xBF3E, 0x96C1, 0xBF3F, 0x96C2, 0xBF40, 0xBBC7, 0xBF41, 0xBBC8, 0xBF42, 0x96C3, 0xBF43, 0x96C4, + 0xBF44, 0xBBC9, 0xBF45, 0x96C5, 0xBF46, 0x96C6, 0xBF47, 0x96C7, 0xBF48, 0xBBCA, 0xBF49, 0x96C8, 0xBF4A, 0x96C9, 0xBF4B, 0x96CA, + 0xBF4C, 0x96CB, 0xBF4D, 0x96CC, 0xBF4E, 0x96CD, 0xBF4F, 0x96CE, 0xBF50, 0xBBCB, 0xBF51, 0xBBCC, 0xBF52, 0x96CF, 0xBF53, 0x96D0, + 0xBF54, 0x96D1, 0xBF55, 0xBBCD, 0xBF56, 0x96D2, 0xBF57, 0x96D3, 0xBF58, 0x96D4, 0xBF59, 0x96D5, 0xBF5A, 0x96D6, 0xBF5B, 0x96D7, + 0xBF5C, 0x96D8, 0xBF5D, 0x96D9, 0xBF5E, 0x96DA, 0xBF5F, 0x96DB, 0xBF60, 0x96DC, 0xBF61, 0x96DD, 0xBF62, 0x96DE, 0xBF63, 0x96DF, + 0xBF64, 0x96E0, 0xBF65, 0x96E1, 0xBF66, 0x96E2, 0xBF67, 0x96E3, 0xBF68, 0x96E4, 0xBF69, 0x96E5, 0xBF6A, 0x96E6, 0xBF6B, 0x96E7, + 0xBF6C, 0x96E8, 0xBF6D, 0x96E9, 0xBF6E, 0x96EA, 0xBF6F, 0x96EB, 0xBF70, 0x96EC, 0xBF71, 0x96ED, 0xBF72, 0x96EE, 0xBF73, 0x96EF, + 0xBF74, 0x96F0, 0xBF75, 0x96F1, 0xBF76, 0x96F2, 0xBF77, 0x96F3, 0xBF78, 0x96F4, 0xBF79, 0x96F5, 0xBF7A, 0x96F6, 0xBF7B, 0x96F7, + 0xBF7C, 0x96F8, 0xBF7D, 0x96F9, 0xBF7E, 0x96FA, 0xBF7F, 0x96FB, 0xBF80, 0x96FC, 0xBF81, 0x96FD, 0xBF82, 0x96FE, 0xBF83, 0x9741, + 0xBF84, 0x9742, 0xBF85, 0x9743, 0xBF86, 0x9744, 0xBF87, 0x9745, 0xBF88, 0x9746, 0xBF89, 0x9747, 0xBF8A, 0x9748, 0xBF8B, 0x9749, + 0xBF8C, 0x974A, 0xBF8D, 0x974B, 0xBF8E, 0x974C, 0xBF8F, 0x974D, 0xBF90, 0x974E, 0xBF91, 0x974F, 0xBF92, 0x9750, 0xBF93, 0x9751, + 0xBF94, 0xBBCE, 0xBF95, 0x9752, 0xBF96, 0x9753, 0xBF97, 0x9754, 0xBF98, 0x9755, 0xBF99, 0x9756, 0xBF9A, 0x9757, 0xBF9B, 0x9758, + 0xBF9C, 0x9759, 0xBF9D, 0x975A, 0xBF9E, 0x9761, 0xBF9F, 0x9762, 0xBFA0, 0x9763, 0xBFA1, 0x9764, 0xBFA2, 0x9765, 0xBFA3, 0x9766, + 0xBFA4, 0x9767, 0xBFA5, 0x9768, 0xBFA6, 0x9769, 0xBFA7, 0x976A, 0xBFA8, 0x976B, 0xBFA9, 0x976C, 0xBFAA, 0x976D, 0xBFAB, 0x976E, + 0xBFAC, 0x976F, 0xBFAD, 0x9770, 0xBFAE, 0x9771, 0xBFAF, 0x9772, 0xBFB0, 0xBBCF, 0xBFB1, 0x9773, 0xBFB2, 0x9774, 0xBFB3, 0x9775, + 0xBFB4, 0x9776, 0xBFB5, 0x9777, 0xBFB6, 0x9778, 0xBFB7, 0x9779, 0xBFB8, 0x977A, 0xBFB9, 0x9781, 0xBFBA, 0x9782, 0xBFBB, 0x9783, + 0xBFBC, 0x9784, 0xBFBD, 0x9785, 0xBFBE, 0x9786, 0xBFBF, 0x9787, 0xBFC0, 0x9788, 0xBFC1, 0x9789, 0xBFC2, 0x978A, 0xBFC3, 0x978B, + 0xBFC4, 0x978C, 0xBFC5, 0xBBD0, 0xBFC6, 0x978D, 0xBFC7, 0x978E, 0xBFC8, 0x978F, 0xBFC9, 0x9790, 0xBFCA, 0x9791, 0xBFCB, 0x9792, + 0xBFCC, 0xBBD1, 0xBFCD, 0xBBD2, 0xBFCE, 0x9793, 0xBFCF, 0x9794, 0xBFD0, 0xBBD3, 0xBFD1, 0x9795, 0xBFD2, 0x9796, 0xBFD3, 0x9797, + 0xBFD4, 0xBBD4, 0xBFD5, 0x9798, 0xBFD6, 0x9799, 0xBFD7, 0x979A, 0xBFD8, 0x979B, 0xBFD9, 0x979C, 0xBFDA, 0x979D, 0xBFDB, 0x979E, + 0xBFDC, 0xBBD5, 0xBFDD, 0x979F, 0xBFDE, 0x97A0, 0xBFDF, 0xBBD6, 0xBFE0, 0x97A1, 0xBFE1, 0xBBD7, 0xBFE2, 0x97A2, 0xBFE3, 0x97A3, + 0xBFE4, 0x97A4, 0xBFE5, 0x97A5, 0xBFE6, 0x97A6, 0xBFE7, 0x97A7, 0xBFE8, 0x97A8, 0xBFE9, 0x97A9, 0xBFEA, 0x97AA, 0xBFEB, 0x97AB, + 0xBFEC, 0x97AC, 0xBFED, 0x97AD, 0xBFEE, 0x97AE, 0xBFEF, 0x97AF, 0xBFF0, 0x97B0, 0xBFF1, 0x97B1, 0xBFF2, 0x97B2, 0xBFF3, 0x97B3, + 0xBFF4, 0x97B4, 0xBFF5, 0x97B5, 0xBFF6, 0x97B6, 0xBFF7, 0x97B7, 0xBFF8, 0x97B8, 0xBFF9, 0x97B9, 0xBFFA, 0x97BA, 0xBFFB, 0x97BB, + 0xBFFC, 0x97BC, 0xBFFD, 0x97BD, 0xBFFE, 0x97BE, 0xBFFF, 0x97BF, 0xC000, 0x97C0, 0xC001, 0x97C1, 0xC002, 0x97C2, 0xC003, 0x97C3, + 0xC004, 0x97C4, 0xC005, 0x97C5, 0xC006, 0x97C6, 0xC007, 0x97C7, 0xC008, 0x97C8, 0xC009, 0x97C9, 0xC00A, 0x97CA, 0xC00B, 0x97CB, + 0xC00C, 0x97CC, 0xC00D, 0x97CD, 0xC00E, 0x97CE, 0xC00F, 0x97CF, 0xC010, 0x97D0, 0xC011, 0x97D1, 0xC012, 0x97D2, 0xC013, 0x97D3, + 0xC014, 0x97D4, 0xC015, 0x97D5, 0xC016, 0x97D6, 0xC017, 0x97D7, 0xC018, 0x97D8, 0xC019, 0x97D9, 0xC01A, 0x97DA, 0xC01B, 0x97DB, + 0xC01C, 0x97DC, 0xC01D, 0x97DD, 0xC01E, 0x97DE, 0xC01F, 0x97DF, 0xC020, 0x97E0, 0xC021, 0x97E1, 0xC022, 0x97E2, 0xC023, 0x97E3, + 0xC024, 0x97E4, 0xC025, 0x97E5, 0xC026, 0x97E6, 0xC027, 0x97E7, 0xC028, 0x97E8, 0xC029, 0x97E9, 0xC02A, 0x97EA, 0xC02B, 0x97EB, + 0xC02C, 0x97EC, 0xC02D, 0x97ED, 0xC02E, 0x97EE, 0xC02F, 0x97EF, 0xC030, 0x97F0, 0xC031, 0x97F1, 0xC032, 0x97F2, 0xC033, 0x97F3, + 0xC034, 0x97F4, 0xC035, 0x97F5, 0xC036, 0x97F6, 0xC037, 0x97F7, 0xC038, 0x97F8, 0xC039, 0x97F9, 0xC03A, 0x97FA, 0xC03B, 0x97FB, + 0xC03C, 0xBBD8, 0xC03D, 0x97FC, 0xC03E, 0x97FD, 0xC03F, 0x97FE, 0xC040, 0x9841, 0xC041, 0x9842, 0xC042, 0x9843, 0xC043, 0x9844, + 0xC044, 0x9845, 0xC045, 0x9846, 0xC046, 0x9847, 0xC047, 0x9848, 0xC048, 0x9849, 0xC049, 0x984A, 0xC04A, 0x984B, 0xC04B, 0x984C, + 0xC04C, 0x984D, 0xC04D, 0x984E, 0xC04E, 0x984F, 0xC04F, 0x9850, 0xC050, 0x9851, 0xC051, 0xBBD9, 0xC052, 0x9852, 0xC053, 0x9853, + 0xC054, 0x9854, 0xC055, 0x9855, 0xC056, 0x9856, 0xC057, 0x9857, 0xC058, 0xBBDA, 0xC059, 0x9858, 0xC05A, 0x9859, 0xC05B, 0x985A, + 0xC05C, 0xBBDB, 0xC05D, 0x9861, 0xC05E, 0x9862, 0xC05F, 0x9863, 0xC060, 0xBBDC, 0xC061, 0x9864, 0xC062, 0x9865, 0xC063, 0x9866, + 0xC064, 0x9867, 0xC065, 0x9868, 0xC066, 0x9869, 0xC067, 0x986A, 0xC068, 0xBBDD, 0xC069, 0xBBDE, 0xC06A, 0x986B, 0xC06B, 0x986C, + 0xC06C, 0x986D, 0xC06D, 0x986E, 0xC06E, 0x986F, 0xC06F, 0x9870, 0xC070, 0x9871, 0xC071, 0x9872, 0xC072, 0x9873, 0xC073, 0x9874, + 0xC074, 0x9875, 0xC075, 0x9876, 0xC076, 0x9877, 0xC077, 0x9878, 0xC078, 0x9879, 0xC079, 0x987A, 0xC07A, 0x9881, 0xC07B, 0x9882, + 0xC07C, 0x9883, 0xC07D, 0x9884, 0xC07E, 0x9885, 0xC07F, 0x9886, 0xC080, 0x9887, 0xC081, 0x9888, 0xC082, 0x9889, 0xC083, 0x988A, + 0xC084, 0x988B, 0xC085, 0x988C, 0xC086, 0x988D, 0xC087, 0x988E, 0xC088, 0x988F, 0xC089, 0x9890, 0xC08A, 0x9891, 0xC08B, 0x9892, + 0xC08C, 0x9893, 0xC08D, 0x9894, 0xC08E, 0x9895, 0xC08F, 0x9896, 0xC090, 0xBBDF, 0xC091, 0xBBE0, 0xC092, 0x9897, 0xC093, 0x9898, + 0xC094, 0xBBE1, 0xC095, 0x9899, 0xC096, 0x989A, 0xC097, 0x989B, 0xC098, 0xBBE2, 0xC099, 0x989C, 0xC09A, 0x989D, 0xC09B, 0x989E, + 0xC09C, 0x989F, 0xC09D, 0x98A0, 0xC09E, 0x98A1, 0xC09F, 0x98A2, 0xC0A0, 0xBBE3, 0xC0A1, 0xBBE4, 0xC0A2, 0x98A3, 0xC0A3, 0xBBE5, + 0xC0A4, 0x98A4, 0xC0A5, 0xBBE6, 0xC0A6, 0x98A5, 0xC0A7, 0x98A6, 0xC0A8, 0x98A7, 0xC0A9, 0x98A8, 0xC0AA, 0x98A9, 0xC0AB, 0x98AA, + 0xC0AC, 0xBBE7, 0xC0AD, 0xBBE8, 0xC0AE, 0x98AB, 0xC0AF, 0xBBE9, 0xC0B0, 0xBBEA, 0xC0B1, 0x98AC, 0xC0B2, 0x98AD, 0xC0B3, 0xBBEB, + 0xC0B4, 0xBBEC, 0xC0B5, 0xBBED, 0xC0B6, 0xBBEE, 0xC0B7, 0x98AE, 0xC0B8, 0x98AF, 0xC0B9, 0x98B0, 0xC0BA, 0x98B1, 0xC0BB, 0x98B2, + 0xC0BC, 0xBBEF, 0xC0BD, 0xBBF0, 0xC0BE, 0x98B3, 0xC0BF, 0xBBF1, 0xC0C0, 0xBBF2, 0xC0C1, 0xBBF3, 0xC0C2, 0x98B4, 0xC0C3, 0x98B5, + 0xC0C4, 0x98B6, 0xC0C5, 0xBBF4, 0xC0C6, 0x98B7, 0xC0C7, 0x98B8, 0xC0C8, 0xBBF5, 0xC0C9, 0xBBF6, 0xC0CA, 0x98B9, 0xC0CB, 0x98BA, + 0xC0CC, 0xBBF7, 0xC0CD, 0x98BB, 0xC0CE, 0x98BC, 0xC0CF, 0x98BD, 0xC0D0, 0xBBF8, 0xC0D1, 0x98BE, 0xC0D2, 0x98BF, 0xC0D3, 0x98C0, + 0xC0D4, 0x98C1, 0xC0D5, 0x98C2, 0xC0D6, 0x98C3, 0xC0D7, 0x98C4, 0xC0D8, 0xBBF9, 0xC0D9, 0xBBFA, 0xC0DA, 0x98C5, 0xC0DB, 0xBBFB, + 0xC0DC, 0xBBFC, 0xC0DD, 0xBBFD, 0xC0DE, 0x98C6, 0xC0DF, 0x98C7, 0xC0E0, 0x98C8, 0xC0E1, 0x98C9, 0xC0E2, 0x98CA, 0xC0E3, 0x98CB, + 0xC0E4, 0xBBFE, 0xC0E5, 0xBCA1, 0xC0E6, 0x98CC, 0xC0E7, 0x98CD, 0xC0E8, 0xBCA2, 0xC0E9, 0x98CE, 0xC0EA, 0x98CF, 0xC0EB, 0x98D0, + 0xC0EC, 0xBCA3, 0xC0ED, 0x98D1, 0xC0EE, 0x98D2, 0xC0EF, 0x98D3, 0xC0F0, 0x98D4, 0xC0F1, 0x98D5, 0xC0F2, 0x98D6, 0xC0F3, 0x98D7, + 0xC0F4, 0xBCA4, 0xC0F5, 0xBCA5, 0xC0F6, 0x98D8, 0xC0F7, 0xBCA6, 0xC0F8, 0x98D9, 0xC0F9, 0xBCA7, 0xC0FA, 0x98DA, 0xC0FB, 0x98DB, + 0xC0FC, 0x98DC, 0xC0FD, 0x98DD, 0xC0FE, 0x98DE, 0xC0FF, 0x98DF, 0xC100, 0xBCA8, 0xC101, 0x98E0, 0xC102, 0x98E1, 0xC103, 0x98E2, + 0xC104, 0xBCA9, 0xC105, 0x98E3, 0xC106, 0x98E4, 0xC107, 0x98E5, 0xC108, 0xBCAA, 0xC109, 0x98E6, 0xC10A, 0x98E7, 0xC10B, 0x98E8, + 0xC10C, 0x98E9, 0xC10D, 0x98EA, 0xC10E, 0x98EB, 0xC10F, 0x98EC, 0xC110, 0xBCAB, 0xC111, 0x98ED, 0xC112, 0x98EE, 0xC113, 0x98EF, + 0xC114, 0x98F0, 0xC115, 0xBCAC, 0xC116, 0x98F1, 0xC117, 0x98F2, 0xC118, 0x98F3, 0xC119, 0x98F4, 0xC11A, 0x98F5, 0xC11B, 0x98F6, + 0xC11C, 0xBCAD, 0xC11D, 0xBCAE, 0xC11E, 0xBCAF, 0xC11F, 0xBCB0, 0xC120, 0xBCB1, 0xC121, 0x98F7, 0xC122, 0x98F8, 0xC123, 0xBCB2, + 0xC124, 0xBCB3, 0xC125, 0x98F9, 0xC126, 0xBCB4, 0xC127, 0xBCB5, 0xC128, 0x98FA, 0xC129, 0x98FB, 0xC12A, 0x98FC, 0xC12B, 0x98FD, + 0xC12C, 0xBCB6, 0xC12D, 0xBCB7, 0xC12E, 0x98FE, 0xC12F, 0xBCB8, 0xC130, 0xBCB9, 0xC131, 0xBCBA, 0xC132, 0x9941, 0xC133, 0x9942, + 0xC134, 0x9943, 0xC135, 0x9944, 0xC136, 0xBCBB, 0xC137, 0x9945, 0xC138, 0xBCBC, 0xC139, 0xBCBD, 0xC13A, 0x9946, 0xC13B, 0x9947, + 0xC13C, 0xBCBE, 0xC13D, 0x9948, 0xC13E, 0x9949, 0xC13F, 0x994A, 0xC140, 0xBCBF, 0xC141, 0x994B, 0xC142, 0x994C, 0xC143, 0x994D, + 0xC144, 0x994E, 0xC145, 0x994F, 0xC146, 0x9950, 0xC147, 0x9951, 0xC148, 0xBCC0, 0xC149, 0xBCC1, 0xC14A, 0x9952, 0xC14B, 0xBCC2, + 0xC14C, 0xBCC3, 0xC14D, 0xBCC4, 0xC14E, 0x9953, 0xC14F, 0x9954, 0xC150, 0x9955, 0xC151, 0x9956, 0xC152, 0x9957, 0xC153, 0x9958, + 0xC154, 0xBCC5, 0xC155, 0xBCC6, 0xC156, 0x9959, 0xC157, 0x995A, 0xC158, 0xBCC7, 0xC159, 0x9961, 0xC15A, 0x9962, 0xC15B, 0x9963, + 0xC15C, 0xBCC8, 0xC15D, 0x9964, 0xC15E, 0x9965, 0xC15F, 0x9966, 0xC160, 0x9967, 0xC161, 0x9968, 0xC162, 0x9969, 0xC163, 0x996A, + 0xC164, 0xBCC9, 0xC165, 0xBCCA, 0xC166, 0x996B, 0xC167, 0xBCCB, 0xC168, 0xBCCC, 0xC169, 0xBCCD, 0xC16A, 0x996C, 0xC16B, 0x996D, + 0xC16C, 0x996E, 0xC16D, 0x996F, 0xC16E, 0x9970, 0xC16F, 0x9971, 0xC170, 0xBCCE, 0xC171, 0x9972, 0xC172, 0x9973, 0xC173, 0x9974, + 0xC174, 0xBCCF, 0xC175, 0x9975, 0xC176, 0x9976, 0xC177, 0x9977, 0xC178, 0xBCD0, 0xC179, 0x9978, 0xC17A, 0x9979, 0xC17B, 0x997A, + 0xC17C, 0x9981, 0xC17D, 0x9982, 0xC17E, 0x9983, 0xC17F, 0x9984, 0xC180, 0x9985, 0xC181, 0x9986, 0xC182, 0x9987, 0xC183, 0x9988, + 0xC184, 0x9989, 0xC185, 0xBCD1, 0xC186, 0x998A, 0xC187, 0x998B, 0xC188, 0x998C, 0xC189, 0x998D, 0xC18A, 0x998E, 0xC18B, 0x998F, + 0xC18C, 0xBCD2, 0xC18D, 0xBCD3, 0xC18E, 0xBCD4, 0xC18F, 0x9990, 0xC190, 0xBCD5, 0xC191, 0x9991, 0xC192, 0x9992, 0xC193, 0x9993, + 0xC194, 0xBCD6, 0xC195, 0x9994, 0xC196, 0xBCD7, 0xC197, 0x9995, 0xC198, 0x9996, 0xC199, 0x9997, 0xC19A, 0x9998, 0xC19B, 0x9999, + 0xC19C, 0xBCD8, 0xC19D, 0xBCD9, 0xC19E, 0x999A, 0xC19F, 0xBCDA, 0xC1A0, 0x999B, 0xC1A1, 0xBCDB, 0xC1A2, 0x999C, 0xC1A3, 0x999D, + 0xC1A4, 0x999E, 0xC1A5, 0xBCDC, 0xC1A6, 0x999F, 0xC1A7, 0x99A0, 0xC1A8, 0xBCDD, 0xC1A9, 0xBCDE, 0xC1AA, 0x99A1, 0xC1AB, 0x99A2, + 0xC1AC, 0xBCDF, 0xC1AD, 0x99A3, 0xC1AE, 0x99A4, 0xC1AF, 0x99A5, 0xC1B0, 0xBCE0, 0xC1B1, 0x99A6, 0xC1B2, 0x99A7, 0xC1B3, 0x99A8, + 0xC1B4, 0x99A9, 0xC1B5, 0x99AA, 0xC1B6, 0x99AB, 0xC1B7, 0x99AC, 0xC1B8, 0x99AD, 0xC1B9, 0x99AE, 0xC1BA, 0x99AF, 0xC1BB, 0x99B0, + 0xC1BC, 0x99B1, 0xC1BD, 0xBCE1, 0xC1BE, 0x99B2, 0xC1BF, 0x99B3, 0xC1C0, 0x99B4, 0xC1C1, 0x99B5, 0xC1C2, 0x99B6, 0xC1C3, 0x99B7, + 0xC1C4, 0xBCE2, 0xC1C5, 0x99B8, 0xC1C6, 0x99B9, 0xC1C7, 0x99BA, 0xC1C8, 0xBCE3, 0xC1C9, 0x99BB, 0xC1CA, 0x99BC, 0xC1CB, 0x99BD, + 0xC1CC, 0xBCE4, 0xC1CD, 0x99BE, 0xC1CE, 0x99BF, 0xC1CF, 0x99C0, 0xC1D0, 0x99C1, 0xC1D1, 0x99C2, 0xC1D2, 0x99C3, 0xC1D3, 0x99C4, + 0xC1D4, 0xBCE5, 0xC1D5, 0x99C5, 0xC1D6, 0x99C6, 0xC1D7, 0xBCE6, 0xC1D8, 0xBCE7, 0xC1D9, 0x99C7, 0xC1DA, 0x99C8, 0xC1DB, 0x99C9, + 0xC1DC, 0x99CA, 0xC1DD, 0x99CB, 0xC1DE, 0x99CC, 0xC1DF, 0x99CD, 0xC1E0, 0xBCE8, 0xC1E1, 0x99CE, 0xC1E2, 0x99CF, 0xC1E3, 0x99D0, + 0xC1E4, 0xBCE9, 0xC1E5, 0x99D1, 0xC1E6, 0x99D2, 0xC1E7, 0x99D3, 0xC1E8, 0xBCEA, 0xC1E9, 0x99D4, 0xC1EA, 0x99D5, 0xC1EB, 0x99D6, + 0xC1EC, 0x99D7, 0xC1ED, 0x99D8, 0xC1EE, 0x99D9, 0xC1EF, 0x99DA, 0xC1F0, 0xBCEB, 0xC1F1, 0xBCEC, 0xC1F2, 0x99DB, 0xC1F3, 0xBCED, + 0xC1F4, 0x99DC, 0xC1F5, 0x99DD, 0xC1F6, 0x99DE, 0xC1F7, 0x99DF, 0xC1F8, 0x99E0, 0xC1F9, 0x99E1, 0xC1FA, 0x99E2, 0xC1FB, 0x99E3, + 0xC1FC, 0xBCEE, 0xC1FD, 0xBCEF, 0xC1FE, 0x99E4, 0xC1FF, 0x99E5, 0xC200, 0xBCF0, 0xC201, 0x99E6, 0xC202, 0x99E7, 0xC203, 0x99E8, + 0xC204, 0xBCF1, 0xC205, 0x99E9, 0xC206, 0x99EA, 0xC207, 0x99EB, 0xC208, 0x99EC, 0xC209, 0x99ED, 0xC20A, 0x99EE, 0xC20B, 0x99EF, + 0xC20C, 0xBCF2, 0xC20D, 0xBCF3, 0xC20E, 0x99F0, 0xC20F, 0xBCF4, 0xC210, 0x99F1, 0xC211, 0xBCF5, 0xC212, 0x99F2, 0xC213, 0x99F3, + 0xC214, 0x99F4, 0xC215, 0x99F5, 0xC216, 0x99F6, 0xC217, 0x99F7, 0xC218, 0xBCF6, 0xC219, 0xBCF7, 0xC21A, 0x99F8, 0xC21B, 0x99F9, + 0xC21C, 0xBCF8, 0xC21D, 0x99FA, 0xC21E, 0x99FB, 0xC21F, 0xBCF9, 0xC220, 0xBCFA, 0xC221, 0x99FC, 0xC222, 0x99FD, 0xC223, 0x99FE, + 0xC224, 0x9A41, 0xC225, 0x9A42, 0xC226, 0x9A43, 0xC227, 0x9A44, 0xC228, 0xBCFB, 0xC229, 0xBCFC, 0xC22A, 0x9A45, 0xC22B, 0xBCFD, + 0xC22C, 0x9A46, 0xC22D, 0xBCFE, 0xC22E, 0x9A47, 0xC22F, 0xBDA1, 0xC230, 0x9A48, 0xC231, 0xBDA2, 0xC232, 0xBDA3, 0xC233, 0x9A49, + 0xC234, 0xBDA4, 0xC235, 0x9A4A, 0xC236, 0x9A4B, 0xC237, 0x9A4C, 0xC238, 0x9A4D, 0xC239, 0x9A4E, 0xC23A, 0x9A4F, 0xC23B, 0x9A50, + 0xC23C, 0x9A51, 0xC23D, 0x9A52, 0xC23E, 0x9A53, 0xC23F, 0x9A54, 0xC240, 0x9A55, 0xC241, 0x9A56, 0xC242, 0x9A57, 0xC243, 0x9A58, + 0xC244, 0x9A59, 0xC245, 0x9A5A, 0xC246, 0x9A61, 0xC247, 0x9A62, 0xC248, 0xBDA5, 0xC249, 0x9A63, 0xC24A, 0x9A64, 0xC24B, 0x9A65, + 0xC24C, 0x9A66, 0xC24D, 0x9A67, 0xC24E, 0x9A68, 0xC24F, 0x9A69, 0xC250, 0xBDA6, 0xC251, 0xBDA7, 0xC252, 0x9A6A, 0xC253, 0x9A6B, + 0xC254, 0xBDA8, 0xC255, 0x9A6C, 0xC256, 0x9A6D, 0xC257, 0x9A6E, 0xC258, 0xBDA9, 0xC259, 0x9A6F, 0xC25A, 0x9A70, 0xC25B, 0x9A71, + 0xC25C, 0x9A72, 0xC25D, 0x9A73, 0xC25E, 0x9A74, 0xC25F, 0x9A75, 0xC260, 0xBDAA, 0xC261, 0x9A76, 0xC262, 0x9A77, 0xC263, 0x9A78, + 0xC264, 0x9A79, 0xC265, 0xBDAB, 0xC266, 0x9A7A, 0xC267, 0x9A81, 0xC268, 0x9A82, 0xC269, 0x9A83, 0xC26A, 0x9A84, 0xC26B, 0x9A85, + 0xC26C, 0xBDAC, 0xC26D, 0xBDAD, 0xC26E, 0x9A86, 0xC26F, 0x9A87, 0xC270, 0xBDAE, 0xC271, 0x9A88, 0xC272, 0x9A89, 0xC273, 0x9A8A, + 0xC274, 0xBDAF, 0xC275, 0x9A8B, 0xC276, 0x9A8C, 0xC277, 0x9A8D, 0xC278, 0x9A8E, 0xC279, 0x9A8F, 0xC27A, 0x9A90, 0xC27B, 0x9A91, + 0xC27C, 0xBDB0, 0xC27D, 0xBDB1, 0xC27E, 0x9A92, 0xC27F, 0xBDB2, 0xC280, 0x9A93, 0xC281, 0xBDB3, 0xC282, 0x9A94, 0xC283, 0x9A95, + 0xC284, 0x9A96, 0xC285, 0x9A97, 0xC286, 0x9A98, 0xC287, 0x9A99, 0xC288, 0xBDB4, 0xC289, 0xBDB5, 0xC28A, 0x9A9A, 0xC28B, 0x9A9B, + 0xC28C, 0x9A9C, 0xC28D, 0x9A9D, 0xC28E, 0x9A9E, 0xC28F, 0x9A9F, 0xC290, 0xBDB6, 0xC291, 0x9AA0, 0xC292, 0x9AA1, 0xC293, 0x9AA2, + 0xC294, 0x9AA3, 0xC295, 0x9AA4, 0xC296, 0x9AA5, 0xC297, 0x9AA6, 0xC298, 0xBDB7, 0xC299, 0x9AA7, 0xC29A, 0x9AA8, 0xC29B, 0xBDB8, + 0xC29C, 0x9AA9, 0xC29D, 0xBDB9, 0xC29E, 0x9AAA, 0xC29F, 0x9AAB, 0xC2A0, 0x9AAC, 0xC2A1, 0x9AAD, 0xC2A2, 0x9AAE, 0xC2A3, 0x9AAF, + 0xC2A4, 0xBDBA, 0xC2A5, 0xBDBB, 0xC2A6, 0x9AB0, 0xC2A7, 0x9AB1, 0xC2A8, 0xBDBC, 0xC2A9, 0x9AB2, 0xC2AA, 0x9AB3, 0xC2AB, 0x9AB4, + 0xC2AC, 0xBDBD, 0xC2AD, 0xBDBE, 0xC2AE, 0x9AB5, 0xC2AF, 0x9AB6, 0xC2B0, 0x9AB7, 0xC2B1, 0x9AB8, 0xC2B2, 0x9AB9, 0xC2B3, 0x9ABA, + 0xC2B4, 0xBDBF, 0xC2B5, 0xBDC0, 0xC2B6, 0x9ABB, 0xC2B7, 0xBDC1, 0xC2B8, 0x9ABC, 0xC2B9, 0xBDC2, 0xC2BA, 0x9ABD, 0xC2BB, 0x9ABE, + 0xC2BC, 0x9ABF, 0xC2BD, 0x9AC0, 0xC2BE, 0x9AC1, 0xC2BF, 0x9AC2, 0xC2C0, 0x9AC3, 0xC2C1, 0x9AC4, 0xC2C2, 0x9AC5, 0xC2C3, 0x9AC6, + 0xC2C4, 0x9AC7, 0xC2C5, 0x9AC8, 0xC2C6, 0x9AC9, 0xC2C7, 0x9ACA, 0xC2C8, 0x9ACB, 0xC2C9, 0x9ACC, 0xC2CA, 0x9ACD, 0xC2CB, 0x9ACE, + 0xC2CC, 0x9ACF, 0xC2CD, 0x9AD0, 0xC2CE, 0x9AD1, 0xC2CF, 0x9AD2, 0xC2D0, 0x9AD3, 0xC2D1, 0x9AD4, 0xC2D2, 0x9AD5, 0xC2D3, 0x9AD6, + 0xC2D4, 0x9AD7, 0xC2D5, 0x9AD8, 0xC2D6, 0x9AD9, 0xC2D7, 0x9ADA, 0xC2D8, 0x9ADB, 0xC2D9, 0x9ADC, 0xC2DA, 0x9ADD, 0xC2DB, 0x9ADE, + 0xC2DC, 0xBDC3, 0xC2DD, 0xBDC4, 0xC2DE, 0x9ADF, 0xC2DF, 0x9AE0, 0xC2E0, 0xBDC5, 0xC2E1, 0x9AE1, 0xC2E2, 0x9AE2, 0xC2E3, 0xBDC6, + 0xC2E4, 0xBDC7, 0xC2E5, 0x9AE3, 0xC2E6, 0x9AE4, 0xC2E7, 0x9AE5, 0xC2E8, 0x9AE6, 0xC2E9, 0x9AE7, 0xC2EA, 0x9AE8, 0xC2EB, 0xBDC8, + 0xC2EC, 0xBDC9, 0xC2ED, 0xBDCA, 0xC2EE, 0x9AE9, 0xC2EF, 0xBDCB, 0xC2F0, 0x9AEA, 0xC2F1, 0xBDCC, 0xC2F2, 0x9AEB, 0xC2F3, 0x9AEC, + 0xC2F4, 0x9AED, 0xC2F5, 0x9AEE, 0xC2F6, 0xBDCD, 0xC2F7, 0x9AEF, 0xC2F8, 0xBDCE, 0xC2F9, 0xBDCF, 0xC2FA, 0x9AF0, 0xC2FB, 0xBDD0, + 0xC2FC, 0xBDD1, 0xC2FD, 0x9AF1, 0xC2FE, 0x9AF2, 0xC2FF, 0x9AF3, 0xC300, 0xBDD2, 0xC301, 0x9AF4, 0xC302, 0x9AF5, 0xC303, 0x9AF6, + 0xC304, 0x9AF7, 0xC305, 0x9AF8, 0xC306, 0x9AF9, 0xC307, 0x9AFA, 0xC308, 0xBDD3, 0xC309, 0xBDD4, 0xC30A, 0x9AFB, 0xC30B, 0x9AFC, + 0xC30C, 0xBDD5, 0xC30D, 0xBDD6, 0xC30E, 0x9AFD, 0xC30F, 0x9AFE, 0xC310, 0x9B41, 0xC311, 0x9B42, 0xC312, 0x9B43, 0xC313, 0xBDD7, + 0xC314, 0xBDD8, 0xC315, 0xBDD9, 0xC316, 0x9B44, 0xC317, 0x9B45, 0xC318, 0xBDDA, 0xC319, 0x9B46, 0xC31A, 0x9B47, 0xC31B, 0x9B48, + 0xC31C, 0xBDDB, 0xC31D, 0x9B49, 0xC31E, 0x9B4A, 0xC31F, 0x9B4B, 0xC320, 0x9B4C, 0xC321, 0x9B4D, 0xC322, 0x9B4E, 0xC323, 0x9B4F, + 0xC324, 0xBDDC, 0xC325, 0xBDDD, 0xC326, 0x9B50, 0xC327, 0x9B51, 0xC328, 0xBDDE, 0xC329, 0xBDDF, 0xC32A, 0x9B52, 0xC32B, 0x9B53, + 0xC32C, 0x9B54, 0xC32D, 0x9B55, 0xC32E, 0x9B56, 0xC32F, 0x9B57, 0xC330, 0x9B58, 0xC331, 0x9B59, 0xC332, 0x9B5A, 0xC333, 0x9B61, + 0xC334, 0x9B62, 0xC335, 0x9B63, 0xC336, 0x9B64, 0xC337, 0x9B65, 0xC338, 0x9B66, 0xC339, 0x9B67, 0xC33A, 0x9B68, 0xC33B, 0x9B69, + 0xC33C, 0x9B6A, 0xC33D, 0x9B6B, 0xC33E, 0x9B6C, 0xC33F, 0x9B6D, 0xC340, 0x9B6E, 0xC341, 0x9B6F, 0xC342, 0x9B70, 0xC343, 0x9B71, + 0xC344, 0x9B72, 0xC345, 0xBDE0, 0xC346, 0x9B73, 0xC347, 0x9B74, 0xC348, 0x9B75, 0xC349, 0x9B76, 0xC34A, 0x9B77, 0xC34B, 0x9B78, + 0xC34C, 0x9B79, 0xC34D, 0x9B7A, 0xC34E, 0x9B81, 0xC34F, 0x9B82, 0xC350, 0x9B83, 0xC351, 0x9B84, 0xC352, 0x9B85, 0xC353, 0x9B86, + 0xC354, 0x9B87, 0xC355, 0x9B88, 0xC356, 0x9B89, 0xC357, 0x9B8A, 0xC358, 0x9B8B, 0xC359, 0x9B8C, 0xC35A, 0x9B8D, 0xC35B, 0x9B8E, + 0xC35C, 0x9B8F, 0xC35D, 0x9B90, 0xC35E, 0x9B91, 0xC35F, 0x9B92, 0xC360, 0x9B93, 0xC361, 0x9B94, 0xC362, 0x9B95, 0xC363, 0x9B96, + 0xC364, 0x9B97, 0xC365, 0x9B98, 0xC366, 0x9B99, 0xC367, 0x9B9A, 0xC368, 0xBDE1, 0xC369, 0xBDE2, 0xC36A, 0x9B9B, 0xC36B, 0x9B9C, + 0xC36C, 0xBDE3, 0xC36D, 0x9B9D, 0xC36E, 0x9B9E, 0xC36F, 0x9B9F, 0xC370, 0xBDE4, 0xC371, 0x9BA0, 0xC372, 0xBDE5, 0xC373, 0x9BA1, + 0xC374, 0x9BA2, 0xC375, 0x9BA3, 0xC376, 0x9BA4, 0xC377, 0x9BA5, 0xC378, 0xBDE6, 0xC379, 0xBDE7, 0xC37A, 0x9BA6, 0xC37B, 0x9BA7, + 0xC37C, 0xBDE8, 0xC37D, 0xBDE9, 0xC37E, 0x9BA8, 0xC37F, 0x9BA9, 0xC380, 0x9BAA, 0xC381, 0x9BAB, 0xC382, 0x9BAC, 0xC383, 0x9BAD, + 0xC384, 0xBDEA, 0xC385, 0x9BAE, 0xC386, 0x9BAF, 0xC387, 0x9BB0, 0xC388, 0xBDEB, 0xC389, 0x9BB1, 0xC38A, 0x9BB2, 0xC38B, 0x9BB3, + 0xC38C, 0xBDEC, 0xC38D, 0x9BB4, 0xC38E, 0x9BB5, 0xC38F, 0x9BB6, 0xC390, 0x9BB7, 0xC391, 0x9BB8, 0xC392, 0x9BB9, 0xC393, 0x9BBA, + 0xC394, 0x9BBB, 0xC395, 0x9BBC, 0xC396, 0x9BBD, 0xC397, 0x9BBE, 0xC398, 0x9BBF, 0xC399, 0x9BC0, 0xC39A, 0x9BC1, 0xC39B, 0x9BC2, + 0xC39C, 0x9BC3, 0xC39D, 0x9BC4, 0xC39E, 0x9BC5, 0xC39F, 0x9BC6, 0xC3A0, 0x9BC7, 0xC3A1, 0x9BC8, 0xC3A2, 0x9BC9, 0xC3A3, 0x9BCA, + 0xC3A4, 0x9BCB, 0xC3A5, 0x9BCC, 0xC3A6, 0x9BCD, 0xC3A7, 0x9BCE, 0xC3A8, 0x9BCF, 0xC3A9, 0x9BD0, 0xC3AA, 0x9BD1, 0xC3AB, 0x9BD2, + 0xC3AC, 0x9BD3, 0xC3AD, 0x9BD4, 0xC3AE, 0x9BD5, 0xC3AF, 0x9BD6, 0xC3B0, 0x9BD7, 0xC3B1, 0x9BD8, 0xC3B2, 0x9BD9, 0xC3B3, 0x9BDA, + 0xC3B4, 0x9BDB, 0xC3B5, 0x9BDC, 0xC3B6, 0x9BDD, 0xC3B7, 0x9BDE, 0xC3B8, 0x9BDF, 0xC3B9, 0x9BE0, 0xC3BA, 0x9BE1, 0xC3BB, 0x9BE2, + 0xC3BC, 0x9BE3, 0xC3BD, 0x9BE4, 0xC3BE, 0x9BE5, 0xC3BF, 0x9BE6, 0xC3C0, 0xBDED, 0xC3C1, 0x9BE7, 0xC3C2, 0x9BE8, 0xC3C3, 0x9BE9, + 0xC3C4, 0x9BEA, 0xC3C5, 0x9BEB, 0xC3C6, 0x9BEC, 0xC3C7, 0x9BED, 0xC3C8, 0x9BEE, 0xC3C9, 0x9BEF, 0xC3CA, 0x9BF0, 0xC3CB, 0x9BF1, + 0xC3CC, 0x9BF2, 0xC3CD, 0x9BF3, 0xC3CE, 0x9BF4, 0xC3CF, 0x9BF5, 0xC3D0, 0x9BF6, 0xC3D1, 0x9BF7, 0xC3D2, 0x9BF8, 0xC3D3, 0x9BF9, + 0xC3D4, 0x9BFA, 0xC3D5, 0x9BFB, 0xC3D6, 0x9BFC, 0xC3D7, 0x9BFD, 0xC3D8, 0xBDEE, 0xC3D9, 0xBDEF, 0xC3DA, 0x9BFE, 0xC3DB, 0x9C41, + 0xC3DC, 0xBDF0, 0xC3DD, 0x9C42, 0xC3DE, 0x9C43, 0xC3DF, 0xBDF1, 0xC3E0, 0xBDF2, 0xC3E1, 0x9C44, 0xC3E2, 0xBDF3, 0xC3E3, 0x9C45, + 0xC3E4, 0x9C46, 0xC3E5, 0x9C47, 0xC3E6, 0x9C48, 0xC3E7, 0x9C49, 0xC3E8, 0xBDF4, 0xC3E9, 0xBDF5, 0xC3EA, 0x9C4A, 0xC3EB, 0x9C4B, + 0xC3EC, 0x9C4C, 0xC3ED, 0xBDF6, 0xC3EE, 0x9C4D, 0xC3EF, 0x9C4E, 0xC3F0, 0x9C4F, 0xC3F1, 0x9C50, 0xC3F2, 0x9C51, 0xC3F3, 0x9C52, + 0xC3F4, 0xBDF7, 0xC3F5, 0xBDF8, 0xC3F6, 0x9C53, 0xC3F7, 0x9C54, 0xC3F8, 0xBDF9, 0xC3F9, 0x9C55, 0xC3FA, 0x9C56, 0xC3FB, 0x9C57, + 0xC3FC, 0x9C58, 0xC3FD, 0x9C59, 0xC3FE, 0x9C5A, 0xC3FF, 0x9C61, 0xC400, 0x9C62, 0xC401, 0x9C63, 0xC402, 0x9C64, 0xC403, 0x9C65, + 0xC404, 0x9C66, 0xC405, 0x9C67, 0xC406, 0x9C68, 0xC407, 0x9C69, 0xC408, 0xBDFA, 0xC409, 0x9C6A, 0xC40A, 0x9C6B, 0xC40B, 0x9C6C, + 0xC40C, 0x9C6D, 0xC40D, 0x9C6E, 0xC40E, 0x9C6F, 0xC40F, 0x9C70, 0xC410, 0xBDFB, 0xC411, 0x9C71, 0xC412, 0x9C72, 0xC413, 0x9C73, + 0xC414, 0x9C74, 0xC415, 0x9C75, 0xC416, 0x9C76, 0xC417, 0x9C77, 0xC418, 0x9C78, 0xC419, 0x9C79, 0xC41A, 0x9C7A, 0xC41B, 0x9C81, + 0xC41C, 0x9C82, 0xC41D, 0x9C83, 0xC41E, 0x9C84, 0xC41F, 0x9C85, 0xC420, 0x9C86, 0xC421, 0x9C87, 0xC422, 0x9C88, 0xC423, 0x9C89, + 0xC424, 0xBDFC, 0xC425, 0x9C8A, 0xC426, 0x9C8B, 0xC427, 0x9C8C, 0xC428, 0x9C8D, 0xC429, 0x9C8E, 0xC42A, 0x9C8F, 0xC42B, 0x9C90, + 0xC42C, 0xBDFD, 0xC42D, 0x9C91, 0xC42E, 0x9C92, 0xC42F, 0x9C93, 0xC430, 0xBDFE, 0xC431, 0x9C94, 0xC432, 0x9C95, 0xC433, 0x9C96, + 0xC434, 0xBEA1, 0xC435, 0x9C97, 0xC436, 0x9C98, 0xC437, 0x9C99, 0xC438, 0x9C9A, 0xC439, 0x9C9B, 0xC43A, 0x9C9C, 0xC43B, 0x9C9D, + 0xC43C, 0xBEA2, 0xC43D, 0xBEA3, 0xC43E, 0x9C9E, 0xC43F, 0x9C9F, 0xC440, 0x9CA0, 0xC441, 0x9CA1, 0xC442, 0x9CA2, 0xC443, 0x9CA3, + 0xC444, 0x9CA4, 0xC445, 0x9CA5, 0xC446, 0x9CA6, 0xC447, 0x9CA7, 0xC448, 0xBEA4, 0xC449, 0x9CA8, 0xC44A, 0x9CA9, 0xC44B, 0x9CAA, + 0xC44C, 0x9CAB, 0xC44D, 0x9CAC, 0xC44E, 0x9CAD, 0xC44F, 0x9CAE, 0xC450, 0x9CAF, 0xC451, 0x9CB0, 0xC452, 0x9CB1, 0xC453, 0x9CB2, + 0xC454, 0x9CB3, 0xC455, 0x9CB4, 0xC456, 0x9CB5, 0xC457, 0x9CB6, 0xC458, 0x9CB7, 0xC459, 0x9CB8, 0xC45A, 0x9CB9, 0xC45B, 0x9CBA, + 0xC45C, 0x9CBB, 0xC45D, 0x9CBC, 0xC45E, 0x9CBD, 0xC45F, 0x9CBE, 0xC460, 0x9CBF, 0xC461, 0x9CC0, 0xC462, 0x9CC1, 0xC463, 0x9CC2, + 0xC464, 0xBEA5, 0xC465, 0xBEA6, 0xC466, 0x9CC3, 0xC467, 0x9CC4, 0xC468, 0xBEA7, 0xC469, 0x9CC5, 0xC46A, 0x9CC6, 0xC46B, 0x9CC7, + 0xC46C, 0xBEA8, 0xC46D, 0x9CC8, 0xC46E, 0x9CC9, 0xC46F, 0x9CCA, 0xC470, 0x9CCB, 0xC471, 0x9CCC, 0xC472, 0x9CCD, 0xC473, 0x9CCE, + 0xC474, 0xBEA9, 0xC475, 0xBEAA, 0xC476, 0x9CCF, 0xC477, 0x9CD0, 0xC478, 0x9CD1, 0xC479, 0xBEAB, 0xC47A, 0x9CD2, 0xC47B, 0x9CD3, + 0xC47C, 0x9CD4, 0xC47D, 0x9CD5, 0xC47E, 0x9CD6, 0xC47F, 0x9CD7, 0xC480, 0xBEAC, 0xC481, 0x9CD8, 0xC482, 0x9CD9, 0xC483, 0x9CDA, + 0xC484, 0x9CDB, 0xC485, 0x9CDC, 0xC486, 0x9CDD, 0xC487, 0x9CDE, 0xC488, 0x9CDF, 0xC489, 0x9CE0, 0xC48A, 0x9CE1, 0xC48B, 0x9CE2, + 0xC48C, 0x9CE3, 0xC48D, 0x9CE4, 0xC48E, 0x9CE5, 0xC48F, 0x9CE6, 0xC490, 0x9CE7, 0xC491, 0x9CE8, 0xC492, 0x9CE9, 0xC493, 0x9CEA, + 0xC494, 0xBEAD, 0xC495, 0x9CEB, 0xC496, 0x9CEC, 0xC497, 0x9CED, 0xC498, 0x9CEE, 0xC499, 0x9CEF, 0xC49A, 0x9CF0, 0xC49B, 0x9CF1, + 0xC49C, 0xBEAE, 0xC49D, 0x9CF2, 0xC49E, 0x9CF3, 0xC49F, 0x9CF4, 0xC4A0, 0x9CF5, 0xC4A1, 0x9CF6, 0xC4A2, 0x9CF7, 0xC4A3, 0x9CF8, + 0xC4A4, 0x9CF9, 0xC4A5, 0x9CFA, 0xC4A6, 0x9CFB, 0xC4A7, 0x9CFC, 0xC4A8, 0x9CFD, 0xC4A9, 0x9CFE, 0xC4AA, 0x9D41, 0xC4AB, 0x9D42, + 0xC4AC, 0x9D43, 0xC4AD, 0x9D44, 0xC4AE, 0x9D45, 0xC4AF, 0x9D46, 0xC4B0, 0x9D47, 0xC4B1, 0x9D48, 0xC4B2, 0x9D49, 0xC4B3, 0x9D4A, + 0xC4B4, 0x9D4B, 0xC4B5, 0x9D4C, 0xC4B6, 0x9D4D, 0xC4B7, 0x9D4E, 0xC4B8, 0xBEAF, 0xC4B9, 0x9D4F, 0xC4BA, 0x9D50, 0xC4BB, 0x9D51, + 0xC4BC, 0xBEB0, 0xC4BD, 0x9D52, 0xC4BE, 0x9D53, 0xC4BF, 0x9D54, 0xC4C0, 0x9D55, 0xC4C1, 0x9D56, 0xC4C2, 0x9D57, 0xC4C3, 0x9D58, + 0xC4C4, 0x9D59, 0xC4C5, 0x9D5A, 0xC4C6, 0x9D61, 0xC4C7, 0x9D62, 0xC4C8, 0x9D63, 0xC4C9, 0x9D64, 0xC4CA, 0x9D65, 0xC4CB, 0x9D66, + 0xC4CC, 0x9D67, 0xC4CD, 0x9D68, 0xC4CE, 0x9D69, 0xC4CF, 0x9D6A, 0xC4D0, 0x9D6B, 0xC4D1, 0x9D6C, 0xC4D2, 0x9D6D, 0xC4D3, 0x9D6E, + 0xC4D4, 0x9D6F, 0xC4D5, 0x9D70, 0xC4D6, 0x9D71, 0xC4D7, 0x9D72, 0xC4D8, 0x9D73, 0xC4D9, 0x9D74, 0xC4DA, 0x9D75, 0xC4DB, 0x9D76, + 0xC4DC, 0x9D77, 0xC4DD, 0x9D78, 0xC4DE, 0x9D79, 0xC4DF, 0x9D7A, 0xC4E0, 0x9D81, 0xC4E1, 0x9D82, 0xC4E2, 0x9D83, 0xC4E3, 0x9D84, + 0xC4E4, 0x9D85, 0xC4E5, 0x9D86, 0xC4E6, 0x9D87, 0xC4E7, 0x9D88, 0xC4E8, 0x9D89, 0xC4E9, 0xBEB1, 0xC4EA, 0x9D8A, 0xC4EB, 0x9D8B, + 0xC4EC, 0x9D8C, 0xC4ED, 0x9D8D, 0xC4EE, 0x9D8E, 0xC4EF, 0x9D8F, 0xC4F0, 0xBEB2, 0xC4F1, 0xBEB3, 0xC4F2, 0x9D90, 0xC4F3, 0x9D91, + 0xC4F4, 0xBEB4, 0xC4F5, 0x9D92, 0xC4F6, 0x9D93, 0xC4F7, 0x9D94, 0xC4F8, 0xBEB5, 0xC4F9, 0x9D95, 0xC4FA, 0xBEB6, 0xC4FB, 0x9D96, + 0xC4FC, 0x9D97, 0xC4FD, 0x9D98, 0xC4FE, 0x9D99, 0xC4FF, 0xBEB7, 0xC500, 0xBEB8, 0xC501, 0xBEB9, 0xC502, 0x9D9A, 0xC503, 0x9D9B, + 0xC504, 0x9D9C, 0xC505, 0x9D9D, 0xC506, 0x9D9E, 0xC507, 0x9D9F, 0xC508, 0x9DA0, 0xC509, 0x9DA1, 0xC50A, 0x9DA2, 0xC50B, 0x9DA3, + 0xC50C, 0xBEBA, 0xC50D, 0x9DA4, 0xC50E, 0x9DA5, 0xC50F, 0x9DA6, 0xC510, 0xBEBB, 0xC511, 0x9DA7, 0xC512, 0x9DA8, 0xC513, 0x9DA9, + 0xC514, 0xBEBC, 0xC515, 0x9DAA, 0xC516, 0x9DAB, 0xC517, 0x9DAC, 0xC518, 0x9DAD, 0xC519, 0x9DAE, 0xC51A, 0x9DAF, 0xC51B, 0x9DB0, + 0xC51C, 0xBEBD, 0xC51D, 0x9DB1, 0xC51E, 0x9DB2, 0xC51F, 0x9DB3, 0xC520, 0x9DB4, 0xC521, 0x9DB5, 0xC522, 0x9DB6, 0xC523, 0x9DB7, + 0xC524, 0x9DB8, 0xC525, 0x9DB9, 0xC526, 0x9DBA, 0xC527, 0x9DBB, 0xC528, 0xBEBE, 0xC529, 0xBEBF, 0xC52A, 0x9DBC, 0xC52B, 0x9DBD, + 0xC52C, 0xBEC0, 0xC52D, 0x9DBE, 0xC52E, 0x9DBF, 0xC52F, 0x9DC0, 0xC530, 0xBEC1, 0xC531, 0x9DC1, 0xC532, 0x9DC2, 0xC533, 0x9DC3, + 0xC534, 0x9DC4, 0xC535, 0x9DC5, 0xC536, 0x9DC6, 0xC537, 0x9DC7, 0xC538, 0xBEC2, 0xC539, 0xBEC3, 0xC53A, 0x9DC8, 0xC53B, 0xBEC4, + 0xC53C, 0x9DC9, 0xC53D, 0xBEC5, 0xC53E, 0x9DCA, 0xC53F, 0x9DCB, 0xC540, 0x9DCC, 0xC541, 0x9DCD, 0xC542, 0x9DCE, 0xC543, 0x9DCF, + 0xC544, 0xBEC6, 0xC545, 0xBEC7, 0xC546, 0x9DD0, 0xC547, 0x9DD1, 0xC548, 0xBEC8, 0xC549, 0xBEC9, 0xC54A, 0xBECA, 0xC54B, 0x9DD2, + 0xC54C, 0xBECB, 0xC54D, 0xBECC, 0xC54E, 0xBECD, 0xC54F, 0x9DD3, 0xC550, 0x9DD4, 0xC551, 0x9DD5, 0xC552, 0x9DD6, 0xC553, 0xBECE, + 0xC554, 0xBECF, 0xC555, 0xBED0, 0xC556, 0x9DD7, 0xC557, 0xBED1, 0xC558, 0xBED2, 0xC559, 0xBED3, 0xC55A, 0x9DD8, 0xC55B, 0x9DD9, + 0xC55C, 0x9DDA, 0xC55D, 0xBED4, 0xC55E, 0xBED5, 0xC55F, 0x9DDB, 0xC560, 0xBED6, 0xC561, 0xBED7, 0xC562, 0x9DDC, 0xC563, 0x9DDD, + 0xC564, 0xBED8, 0xC565, 0x9DDE, 0xC566, 0x9DDF, 0xC567, 0x9DE0, 0xC568, 0xBED9, 0xC569, 0x9DE1, 0xC56A, 0x9DE2, 0xC56B, 0x9DE3, + 0xC56C, 0x9DE4, 0xC56D, 0x9DE5, 0xC56E, 0x9DE6, 0xC56F, 0x9DE7, 0xC570, 0xBEDA, 0xC571, 0xBEDB, 0xC572, 0x9DE8, 0xC573, 0xBEDC, + 0xC574, 0xBEDD, 0xC575, 0xBEDE, 0xC576, 0x9DE9, 0xC577, 0x9DEA, 0xC578, 0x9DEB, 0xC579, 0x9DEC, 0xC57A, 0x9DED, 0xC57B, 0x9DEE, + 0xC57C, 0xBEDF, 0xC57D, 0xBEE0, 0xC57E, 0x9DEF, 0xC57F, 0x9DF0, 0xC580, 0xBEE1, 0xC581, 0x9DF1, 0xC582, 0x9DF2, 0xC583, 0x9DF3, + 0xC584, 0xBEE2, 0xC585, 0x9DF4, 0xC586, 0x9DF5, 0xC587, 0xBEE3, 0xC588, 0x9DF6, 0xC589, 0x9DF7, 0xC58A, 0x9DF8, 0xC58B, 0x9DF9, + 0xC58C, 0xBEE4, 0xC58D, 0xBEE5, 0xC58E, 0x9DFA, 0xC58F, 0xBEE6, 0xC590, 0x9DFB, 0xC591, 0xBEE7, 0xC592, 0x9DFC, 0xC593, 0x9DFD, + 0xC594, 0x9DFE, 0xC595, 0xBEE8, 0xC596, 0x9E41, 0xC597, 0xBEE9, 0xC598, 0xBEEA, 0xC599, 0x9E42, 0xC59A, 0x9E43, 0xC59B, 0x9E44, + 0xC59C, 0xBEEB, 0xC59D, 0x9E45, 0xC59E, 0x9E46, 0xC59F, 0x9E47, 0xC5A0, 0xBEEC, 0xC5A1, 0x9E48, 0xC5A2, 0x9E49, 0xC5A3, 0x9E4A, + 0xC5A4, 0x9E4B, 0xC5A5, 0x9E4C, 0xC5A6, 0x9E4D, 0xC5A7, 0x9E4E, 0xC5A8, 0x9E4F, 0xC5A9, 0xBEED, 0xC5AA, 0x9E50, 0xC5AB, 0x9E51, + 0xC5AC, 0x9E52, 0xC5AD, 0x9E53, 0xC5AE, 0x9E54, 0xC5AF, 0x9E55, 0xC5B0, 0x9E56, 0xC5B1, 0x9E57, 0xC5B2, 0x9E58, 0xC5B3, 0x9E59, + 0xC5B4, 0xBEEE, 0xC5B5, 0xBEEF, 0xC5B6, 0x9E5A, 0xC5B7, 0x9E61, 0xC5B8, 0xBEF0, 0xC5B9, 0xBEF1, 0xC5BA, 0x9E62, 0xC5BB, 0xBEF2, + 0xC5BC, 0xBEF3, 0xC5BD, 0xBEF4, 0xC5BE, 0xBEF5, 0xC5BF, 0x9E63, 0xC5C0, 0x9E64, 0xC5C1, 0x9E65, 0xC5C2, 0x9E66, 0xC5C3, 0x9E67, + 0xC5C4, 0xBEF6, 0xC5C5, 0xBEF7, 0xC5C6, 0xBEF8, 0xC5C7, 0xBEF9, 0xC5C8, 0xBEFA, 0xC5C9, 0xBEFB, 0xC5CA, 0xBEFC, 0xC5CB, 0x9E68, + 0xC5CC, 0xBEFD, 0xC5CD, 0x9E69, 0xC5CE, 0xBEFE, 0xC5CF, 0x9E6A, 0xC5D0, 0xBFA1, 0xC5D1, 0xBFA2, 0xC5D2, 0x9E6B, 0xC5D3, 0x9E6C, + 0xC5D4, 0xBFA3, 0xC5D5, 0x9E6D, 0xC5D6, 0x9E6E, 0xC5D7, 0x9E6F, 0xC5D8, 0xBFA4, 0xC5D9, 0x9E70, 0xC5DA, 0x9E71, 0xC5DB, 0x9E72, + 0xC5DC, 0x9E73, 0xC5DD, 0x9E74, 0xC5DE, 0x9E75, 0xC5DF, 0x9E76, 0xC5E0, 0xBFA5, 0xC5E1, 0xBFA6, 0xC5E2, 0x9E77, 0xC5E3, 0xBFA7, + 0xC5E4, 0x9E78, 0xC5E5, 0xBFA8, 0xC5E6, 0x9E79, 0xC5E7, 0x9E7A, 0xC5E8, 0x9E81, 0xC5E9, 0x9E82, 0xC5EA, 0x9E83, 0xC5EB, 0x9E84, + 0xC5EC, 0xBFA9, 0xC5ED, 0xBFAA, 0xC5EE, 0xBFAB, 0xC5EF, 0x9E85, 0xC5F0, 0xBFAC, 0xC5F1, 0x9E86, 0xC5F2, 0x9E87, 0xC5F3, 0x9E88, + 0xC5F4, 0xBFAD, 0xC5F5, 0x9E89, 0xC5F6, 0xBFAE, 0xC5F7, 0xBFAF, 0xC5F8, 0x9E8A, 0xC5F9, 0x9E8B, 0xC5FA, 0x9E8C, 0xC5FB, 0x9E8D, + 0xC5FC, 0xBFB0, 0xC5FD, 0xBFB1, 0xC5FE, 0xBFB2, 0xC5FF, 0xBFB3, 0xC600, 0xBFB4, 0xC601, 0xBFB5, 0xC602, 0x9E8E, 0xC603, 0x9E8F, + 0xC604, 0x9E90, 0xC605, 0xBFB6, 0xC606, 0xBFB7, 0xC607, 0xBFB8, 0xC608, 0xBFB9, 0xC609, 0x9E91, 0xC60A, 0x9E92, 0xC60B, 0x9E93, + 0xC60C, 0xBFBA, 0xC60D, 0x9E94, 0xC60E, 0x9E95, 0xC60F, 0x9E96, 0xC610, 0xBFBB, 0xC611, 0x9E97, 0xC612, 0x9E98, 0xC613, 0x9E99, + 0xC614, 0x9E9A, 0xC615, 0x9E9B, 0xC616, 0x9E9C, 0xC617, 0x9E9D, 0xC618, 0xBFBC, 0xC619, 0xBFBD, 0xC61A, 0x9E9E, 0xC61B, 0xBFBE, + 0xC61C, 0xBFBF, 0xC61D, 0x9E9F, 0xC61E, 0x9EA0, 0xC61F, 0x9EA1, 0xC620, 0x9EA2, 0xC621, 0x9EA3, 0xC622, 0x9EA4, 0xC623, 0x9EA5, + 0xC624, 0xBFC0, 0xC625, 0xBFC1, 0xC626, 0x9EA6, 0xC627, 0x9EA7, 0xC628, 0xBFC2, 0xC629, 0x9EA8, 0xC62A, 0x9EA9, 0xC62B, 0x9EAA, + 0xC62C, 0xBFC3, 0xC62D, 0xBFC4, 0xC62E, 0xBFC5, 0xC62F, 0x9EAB, 0xC630, 0xBFC6, 0xC631, 0x9EAC, 0xC632, 0x9EAD, 0xC633, 0xBFC7, + 0xC634, 0xBFC8, 0xC635, 0xBFC9, 0xC636, 0x9EAE, 0xC637, 0xBFCA, 0xC638, 0x9EAF, 0xC639, 0xBFCB, 0xC63A, 0x9EB0, 0xC63B, 0xBFCC, + 0xC63C, 0x9EB1, 0xC63D, 0x9EB2, 0xC63E, 0x9EB3, 0xC63F, 0x9EB4, 0xC640, 0xBFCD, 0xC641, 0xBFCE, 0xC642, 0x9EB5, 0xC643, 0x9EB6, + 0xC644, 0xBFCF, 0xC645, 0x9EB7, 0xC646, 0x9EB8, 0xC647, 0x9EB9, 0xC648, 0xBFD0, 0xC649, 0x9EBA, 0xC64A, 0x9EBB, 0xC64B, 0x9EBC, + 0xC64C, 0x9EBD, 0xC64D, 0x9EBE, 0xC64E, 0x9EBF, 0xC64F, 0x9EC0, 0xC650, 0xBFD1, 0xC651, 0xBFD2, 0xC652, 0x9EC1, 0xC653, 0xBFD3, + 0xC654, 0xBFD4, 0xC655, 0xBFD5, 0xC656, 0x9EC2, 0xC657, 0x9EC3, 0xC658, 0x9EC4, 0xC659, 0x9EC5, 0xC65A, 0x9EC6, 0xC65B, 0x9EC7, + 0xC65C, 0xBFD6, 0xC65D, 0xBFD7, 0xC65E, 0x9EC8, 0xC65F, 0x9EC9, 0xC660, 0xBFD8, 0xC661, 0x9ECA, 0xC662, 0x9ECB, 0xC663, 0x9ECC, + 0xC664, 0x9ECD, 0xC665, 0x9ECE, 0xC666, 0x9ECF, 0xC667, 0x9ED0, 0xC668, 0x9ED1, 0xC669, 0x9ED2, 0xC66A, 0x9ED3, 0xC66B, 0x9ED4, + 0xC66C, 0xBFD9, 0xC66D, 0x9ED5, 0xC66E, 0x9ED6, 0xC66F, 0xBFDA, 0xC670, 0x9ED7, 0xC671, 0xBFDB, 0xC672, 0x9ED8, 0xC673, 0x9ED9, + 0xC674, 0x9EDA, 0xC675, 0x9EDB, 0xC676, 0x9EDC, 0xC677, 0x9EDD, 0xC678, 0xBFDC, 0xC679, 0xBFDD, 0xC67A, 0x9EDE, 0xC67B, 0x9EDF, + 0xC67C, 0xBFDE, 0xC67D, 0x9EE0, 0xC67E, 0x9EE1, 0xC67F, 0x9EE2, 0xC680, 0xBFDF, 0xC681, 0x9EE3, 0xC682, 0x9EE4, 0xC683, 0x9EE5, + 0xC684, 0x9EE6, 0xC685, 0x9EE7, 0xC686, 0x9EE8, 0xC687, 0x9EE9, 0xC688, 0xBFE0, 0xC689, 0xBFE1, 0xC68A, 0x9EEA, 0xC68B, 0xBFE2, + 0xC68C, 0x9EEB, 0xC68D, 0xBFE3, 0xC68E, 0x9EEC, 0xC68F, 0x9EED, 0xC690, 0x9EEE, 0xC691, 0x9EEF, 0xC692, 0x9EF0, 0xC693, 0x9EF1, + 0xC694, 0xBFE4, 0xC695, 0xBFE5, 0xC696, 0x9EF2, 0xC697, 0x9EF3, 0xC698, 0xBFE6, 0xC699, 0x9EF4, 0xC69A, 0x9EF5, 0xC69B, 0x9EF6, + 0xC69C, 0xBFE7, 0xC69D, 0x9EF7, 0xC69E, 0x9EF8, 0xC69F, 0x9EF9, 0xC6A0, 0x9EFA, 0xC6A1, 0x9EFB, 0xC6A2, 0x9EFC, 0xC6A3, 0x9EFD, + 0xC6A4, 0xBFE8, 0xC6A5, 0xBFE9, 0xC6A6, 0x9EFE, 0xC6A7, 0xBFEA, 0xC6A8, 0x9F41, 0xC6A9, 0xBFEB, 0xC6AA, 0x9F42, 0xC6AB, 0x9F43, + 0xC6AC, 0x9F44, 0xC6AD, 0x9F45, 0xC6AE, 0x9F46, 0xC6AF, 0x9F47, 0xC6B0, 0xBFEC, 0xC6B1, 0xBFED, 0xC6B2, 0x9F48, 0xC6B3, 0x9F49, + 0xC6B4, 0xBFEE, 0xC6B5, 0x9F4A, 0xC6B6, 0x9F4B, 0xC6B7, 0x9F4C, 0xC6B8, 0xBFEF, 0xC6B9, 0xBFF0, 0xC6BA, 0xBFF1, 0xC6BB, 0x9F4D, + 0xC6BC, 0x9F4E, 0xC6BD, 0x9F4F, 0xC6BE, 0x9F50, 0xC6BF, 0x9F51, 0xC6C0, 0xBFF2, 0xC6C1, 0xBFF3, 0xC6C2, 0x9F52, 0xC6C3, 0xBFF4, + 0xC6C4, 0x9F53, 0xC6C5, 0xBFF5, 0xC6C6, 0x9F54, 0xC6C7, 0x9F55, 0xC6C8, 0x9F56, 0xC6C9, 0x9F57, 0xC6CA, 0x9F58, 0xC6CB, 0x9F59, + 0xC6CC, 0xBFF6, 0xC6CD, 0xBFF7, 0xC6CE, 0x9F5A, 0xC6CF, 0x9F61, 0xC6D0, 0xBFF8, 0xC6D1, 0x9F62, 0xC6D2, 0x9F63, 0xC6D3, 0x9F64, + 0xC6D4, 0xBFF9, 0xC6D5, 0x9F65, 0xC6D6, 0x9F66, 0xC6D7, 0x9F67, 0xC6D8, 0x9F68, 0xC6D9, 0x9F69, 0xC6DA, 0x9F6A, 0xC6DB, 0x9F6B, + 0xC6DC, 0xBFFA, 0xC6DD, 0xBFFB, 0xC6DE, 0x9F6C, 0xC6DF, 0x9F6D, 0xC6E0, 0xBFFC, 0xC6E1, 0xBFFD, 0xC6E2, 0x9F6E, 0xC6E3, 0x9F6F, + 0xC6E4, 0x9F70, 0xC6E5, 0x9F71, 0xC6E6, 0x9F72, 0xC6E7, 0x9F73, 0xC6E8, 0xBFFE, 0xC6E9, 0xC0A1, 0xC6EA, 0x9F74, 0xC6EB, 0x9F75, + 0xC6EC, 0xC0A2, 0xC6ED, 0x9F76, 0xC6EE, 0x9F77, 0xC6EF, 0x9F78, 0xC6F0, 0xC0A3, 0xC6F1, 0x9F79, 0xC6F2, 0x9F7A, 0xC6F3, 0x9F81, + 0xC6F4, 0x9F82, 0xC6F5, 0x9F83, 0xC6F6, 0x9F84, 0xC6F7, 0x9F85, 0xC6F8, 0xC0A4, 0xC6F9, 0xC0A5, 0xC6FA, 0x9F86, 0xC6FB, 0x9F87, + 0xC6FC, 0x9F88, 0xC6FD, 0xC0A6, 0xC6FE, 0x9F89, 0xC6FF, 0x9F8A, 0xC700, 0x9F8B, 0xC701, 0x9F8C, 0xC702, 0x9F8D, 0xC703, 0x9F8E, + 0xC704, 0xC0A7, 0xC705, 0xC0A8, 0xC706, 0x9F8F, 0xC707, 0x9F90, 0xC708, 0xC0A9, 0xC709, 0x9F91, 0xC70A, 0x9F92, 0xC70B, 0x9F93, + 0xC70C, 0xC0AA, 0xC70D, 0x9F94, 0xC70E, 0x9F95, 0xC70F, 0x9F96, 0xC710, 0x9F97, 0xC711, 0x9F98, 0xC712, 0x9F99, 0xC713, 0x9F9A, + 0xC714, 0xC0AB, 0xC715, 0xC0AC, 0xC716, 0x9F9B, 0xC717, 0xC0AD, 0xC718, 0x9F9C, 0xC719, 0xC0AE, 0xC71A, 0x9F9D, 0xC71B, 0x9F9E, + 0xC71C, 0x9F9F, 0xC71D, 0x9FA0, 0xC71E, 0x9FA1, 0xC71F, 0x9FA2, 0xC720, 0xC0AF, 0xC721, 0xC0B0, 0xC722, 0x9FA3, 0xC723, 0x9FA4, + 0xC724, 0xC0B1, 0xC725, 0x9FA5, 0xC726, 0x9FA6, 0xC727, 0x9FA7, 0xC728, 0xC0B2, 0xC729, 0x9FA8, 0xC72A, 0x9FA9, 0xC72B, 0x9FAA, + 0xC72C, 0x9FAB, 0xC72D, 0x9FAC, 0xC72E, 0x9FAD, 0xC72F, 0x9FAE, 0xC730, 0xC0B3, 0xC731, 0xC0B4, 0xC732, 0x9FAF, 0xC733, 0xC0B5, + 0xC734, 0x9FB0, 0xC735, 0xC0B6, 0xC736, 0x9FB1, 0xC737, 0xC0B7, 0xC738, 0x9FB2, 0xC739, 0x9FB3, 0xC73A, 0x9FB4, 0xC73B, 0x9FB5, + 0xC73C, 0xC0B8, 0xC73D, 0xC0B9, 0xC73E, 0x9FB6, 0xC73F, 0x9FB7, 0xC740, 0xC0BA, 0xC741, 0x9FB8, 0xC742, 0x9FB9, 0xC743, 0x9FBA, + 0xC744, 0xC0BB, 0xC745, 0x9FBB, 0xC746, 0x9FBC, 0xC747, 0x9FBD, 0xC748, 0x9FBE, 0xC749, 0x9FBF, 0xC74A, 0xC0BC, 0xC74B, 0x9FC0, + 0xC74C, 0xC0BD, 0xC74D, 0xC0BE, 0xC74E, 0x9FC1, 0xC74F, 0xC0BF, 0xC750, 0x9FC2, 0xC751, 0xC0C0, 0xC752, 0xC0C1, 0xC753, 0xC0C2, + 0xC754, 0xC0C3, 0xC755, 0xC0C4, 0xC756, 0xC0C5, 0xC757, 0xC0C6, 0xC758, 0xC0C7, 0xC759, 0x9FC3, 0xC75A, 0x9FC4, 0xC75B, 0x9FC5, + 0xC75C, 0xC0C8, 0xC75D, 0x9FC6, 0xC75E, 0x9FC7, 0xC75F, 0x9FC8, 0xC760, 0xC0C9, 0xC761, 0x9FC9, 0xC762, 0x9FCA, 0xC763, 0x9FCB, + 0xC764, 0x9FCC, 0xC765, 0x9FCD, 0xC766, 0x9FCE, 0xC767, 0x9FCF, 0xC768, 0xC0CA, 0xC769, 0x9FD0, 0xC76A, 0x9FD1, 0xC76B, 0xC0CB, + 0xC76C, 0x9FD2, 0xC76D, 0x9FD3, 0xC76E, 0x9FD4, 0xC76F, 0x9FD5, 0xC770, 0x9FD6, 0xC771, 0x9FD7, 0xC772, 0x9FD8, 0xC773, 0x9FD9, + 0xC774, 0xC0CC, 0xC775, 0xC0CD, 0xC776, 0x9FDA, 0xC777, 0x9FDB, 0xC778, 0xC0CE, 0xC779, 0x9FDC, 0xC77A, 0x9FDD, 0xC77B, 0x9FDE, + 0xC77C, 0xC0CF, 0xC77D, 0xC0D0, 0xC77E, 0xC0D1, 0xC77F, 0x9FDF, 0xC780, 0x9FE0, 0xC781, 0x9FE1, 0xC782, 0x9FE2, 0xC783, 0xC0D2, + 0xC784, 0xC0D3, 0xC785, 0xC0D4, 0xC786, 0x9FE3, 0xC787, 0xC0D5, 0xC788, 0xC0D6, 0xC789, 0xC0D7, 0xC78A, 0xC0D8, 0xC78B, 0x9FE4, + 0xC78C, 0x9FE5, 0xC78D, 0x9FE6, 0xC78E, 0xC0D9, 0xC78F, 0x9FE7, 0xC790, 0xC0DA, 0xC791, 0xC0DB, 0xC792, 0x9FE8, 0xC793, 0x9FE9, + 0xC794, 0xC0DC, 0xC795, 0x9FEA, 0xC796, 0xC0DD, 0xC797, 0xC0DE, 0xC798, 0xC0DF, 0xC799, 0x9FEB, 0xC79A, 0xC0E0, 0xC79B, 0x9FEC, + 0xC79C, 0x9FED, 0xC79D, 0x9FEE, 0xC79E, 0x9FEF, 0xC79F, 0x9FF0, 0xC7A0, 0xC0E1, 0xC7A1, 0xC0E2, 0xC7A2, 0x9FF1, 0xC7A3, 0xC0E3, + 0xC7A4, 0xC0E4, 0xC7A5, 0xC0E5, 0xC7A6, 0xC0E6, 0xC7A7, 0x9FF2, 0xC7A8, 0x9FF3, 0xC7A9, 0x9FF4, 0xC7AA, 0x9FF5, 0xC7AB, 0x9FF6, + 0xC7AC, 0xC0E7, 0xC7AD, 0xC0E8, 0xC7AE, 0x9FF7, 0xC7AF, 0x9FF8, 0xC7B0, 0xC0E9, 0xC7B1, 0x9FF9, 0xC7B2, 0x9FFA, 0xC7B3, 0x9FFB, + 0xC7B4, 0xC0EA, 0xC7B5, 0x9FFC, 0xC7B6, 0x9FFD, 0xC7B7, 0x9FFE, 0xC7B8, 0xA041, 0xC7B9, 0xA042, 0xC7BA, 0xA043, 0xC7BB, 0xA044, + 0xC7BC, 0xC0EB, 0xC7BD, 0xC0EC, 0xC7BE, 0xA045, 0xC7BF, 0xC0ED, 0xC7C0, 0xC0EE, 0xC7C1, 0xC0EF, 0xC7C2, 0xA046, 0xC7C3, 0xA047, + 0xC7C4, 0xA048, 0xC7C5, 0xA049, 0xC7C6, 0xA04A, 0xC7C7, 0xA04B, 0xC7C8, 0xC0F0, 0xC7C9, 0xC0F1, 0xC7CA, 0xA04C, 0xC7CB, 0xA04D, + 0xC7CC, 0xC0F2, 0xC7CD, 0xA04E, 0xC7CE, 0xC0F3, 0xC7CF, 0xA04F, 0xC7D0, 0xC0F4, 0xC7D1, 0xA050, 0xC7D2, 0xA051, 0xC7D3, 0xA052, + 0xC7D4, 0xA053, 0xC7D5, 0xA054, 0xC7D6, 0xA055, 0xC7D7, 0xA056, 0xC7D8, 0xC0F5, 0xC7D9, 0xA057, 0xC7DA, 0xA058, 0xC7DB, 0xA059, + 0xC7DC, 0xA05A, 0xC7DD, 0xC0F6, 0xC7DE, 0xA061, 0xC7DF, 0xA062, 0xC7E0, 0xA063, 0xC7E1, 0xA064, 0xC7E2, 0xA065, 0xC7E3, 0xA066, + 0xC7E4, 0xC0F7, 0xC7E5, 0xA067, 0xC7E6, 0xA068, 0xC7E7, 0xA069, 0xC7E8, 0xC0F8, 0xC7E9, 0xA06A, 0xC7EA, 0xA06B, 0xC7EB, 0xA06C, + 0xC7EC, 0xC0F9, 0xC7ED, 0xA06D, 0xC7EE, 0xA06E, 0xC7EF, 0xA06F, 0xC7F0, 0xA070, 0xC7F1, 0xA071, 0xC7F2, 0xA072, 0xC7F3, 0xA073, + 0xC7F4, 0xA074, 0xC7F5, 0xA075, 0xC7F6, 0xA076, 0xC7F7, 0xA077, 0xC7F8, 0xA078, 0xC7F9, 0xA079, 0xC7FA, 0xA07A, 0xC7FB, 0xA081, + 0xC7FC, 0xA082, 0xC7FD, 0xA083, 0xC7FE, 0xA084, 0xC7FF, 0xA085, 0xC800, 0xC0FA, 0xC801, 0xC0FB, 0xC802, 0xA086, 0xC803, 0xA087, + 0xC804, 0xC0FC, 0xC805, 0xA088, 0xC806, 0xA089, 0xC807, 0xA08A, 0xC808, 0xC0FD, 0xC809, 0xA08B, 0xC80A, 0xC0FE, 0xC80B, 0xA08C, + 0xC80C, 0xA08D, 0xC80D, 0xA08E, 0xC80E, 0xA08F, 0xC80F, 0xA090, 0xC810, 0xC1A1, 0xC811, 0xC1A2, 0xC812, 0xA091, 0xC813, 0xC1A3, + 0xC814, 0xA092, 0xC815, 0xC1A4, 0xC816, 0xC1A5, 0xC817, 0xA093, 0xC818, 0xA094, 0xC819, 0xA095, 0xC81A, 0xA096, 0xC81B, 0xA097, + 0xC81C, 0xC1A6, 0xC81D, 0xC1A7, 0xC81E, 0xA098, 0xC81F, 0xA099, 0xC820, 0xC1A8, 0xC821, 0xA09A, 0xC822, 0xA09B, 0xC823, 0xA09C, + 0xC824, 0xC1A9, 0xC825, 0xA09D, 0xC826, 0xA09E, 0xC827, 0xA09F, 0xC828, 0xA0A0, 0xC829, 0xA0A1, 0xC82A, 0xA0A2, 0xC82B, 0xA0A3, + 0xC82C, 0xC1AA, 0xC82D, 0xC1AB, 0xC82E, 0xA0A4, 0xC82F, 0xC1AC, 0xC830, 0xA0A5, 0xC831, 0xC1AD, 0xC832, 0xA0A6, 0xC833, 0xA0A7, + 0xC834, 0xA0A8, 0xC835, 0xA0A9, 0xC836, 0xA0AA, 0xC837, 0xA0AB, 0xC838, 0xC1AE, 0xC839, 0xA0AC, 0xC83A, 0xA0AD, 0xC83B, 0xA0AE, + 0xC83C, 0xC1AF, 0xC83D, 0xA0AF, 0xC83E, 0xA0B0, 0xC83F, 0xA0B1, 0xC840, 0xC1B0, 0xC841, 0xA0B2, 0xC842, 0xA0B3, 0xC843, 0xA0B4, + 0xC844, 0xA0B5, 0xC845, 0xA0B6, 0xC846, 0xA0B7, 0xC847, 0xA0B8, 0xC848, 0xC1B1, 0xC849, 0xC1B2, 0xC84A, 0xA0B9, 0xC84B, 0xA0BA, + 0xC84C, 0xC1B3, 0xC84D, 0xC1B4, 0xC84E, 0xA0BB, 0xC84F, 0xA0BC, 0xC850, 0xA0BD, 0xC851, 0xA0BE, 0xC852, 0xA0BF, 0xC853, 0xA0C0, + 0xC854, 0xC1B5, 0xC855, 0xA0C1, 0xC856, 0xA0C2, 0xC857, 0xA0C3, 0xC858, 0xA0C4, 0xC859, 0xA0C5, 0xC85A, 0xA0C6, 0xC85B, 0xA0C7, + 0xC85C, 0xA0C8, 0xC85D, 0xA0C9, 0xC85E, 0xA0CA, 0xC85F, 0xA0CB, 0xC860, 0xA0CC, 0xC861, 0xA0CD, 0xC862, 0xA0CE, 0xC863, 0xA0CF, + 0xC864, 0xA0D0, 0xC865, 0xA0D1, 0xC866, 0xA0D2, 0xC867, 0xA0D3, 0xC868, 0xA0D4, 0xC869, 0xA0D5, 0xC86A, 0xA0D6, 0xC86B, 0xA0D7, + 0xC86C, 0xA0D8, 0xC86D, 0xA0D9, 0xC86E, 0xA0DA, 0xC86F, 0xA0DB, 0xC870, 0xC1B6, 0xC871, 0xC1B7, 0xC872, 0xA0DC, 0xC873, 0xA0DD, + 0xC874, 0xC1B8, 0xC875, 0xA0DE, 0xC876, 0xA0DF, 0xC877, 0xA0E0, 0xC878, 0xC1B9, 0xC879, 0xA0E1, 0xC87A, 0xC1BA, 0xC87B, 0xA0E2, + 0xC87C, 0xA0E3, 0xC87D, 0xA0E4, 0xC87E, 0xA0E5, 0xC87F, 0xA0E6, 0xC880, 0xC1BB, 0xC881, 0xC1BC, 0xC882, 0xA0E7, 0xC883, 0xC1BD, + 0xC884, 0xA0E8, 0xC885, 0xC1BE, 0xC886, 0xC1BF, 0xC887, 0xC1C0, 0xC888, 0xA0E9, 0xC889, 0xA0EA, 0xC88A, 0xA0EB, 0xC88B, 0xC1C1, + 0xC88C, 0xC1C2, 0xC88D, 0xC1C3, 0xC88E, 0xA0EC, 0xC88F, 0xA0ED, 0xC890, 0xA0EE, 0xC891, 0xA0EF, 0xC892, 0xA0F0, 0xC893, 0xA0F1, + 0xC894, 0xC1C4, 0xC895, 0xA0F2, 0xC896, 0xA0F3, 0xC897, 0xA0F4, 0xC898, 0xA0F5, 0xC899, 0xA0F6, 0xC89A, 0xA0F7, 0xC89B, 0xA0F8, + 0xC89C, 0xA0F9, 0xC89D, 0xC1C5, 0xC89E, 0xA0FA, 0xC89F, 0xC1C6, 0xC8A0, 0xA0FB, 0xC8A1, 0xC1C7, 0xC8A2, 0xA0FC, 0xC8A3, 0xA0FD, + 0xC8A4, 0xA0FE, 0xC8A5, 0xA141, 0xC8A6, 0xA142, 0xC8A7, 0xA143, 0xC8A8, 0xC1C8, 0xC8A9, 0xA144, 0xC8AA, 0xA145, 0xC8AB, 0xA146, + 0xC8AC, 0xA147, 0xC8AD, 0xA148, 0xC8AE, 0xA149, 0xC8AF, 0xA14A, 0xC8B0, 0xA14B, 0xC8B1, 0xA14C, 0xC8B2, 0xA14D, 0xC8B3, 0xA14E, + 0xC8B4, 0xA14F, 0xC8B5, 0xA150, 0xC8B6, 0xA151, 0xC8B7, 0xA152, 0xC8B8, 0xA153, 0xC8B9, 0xA154, 0xC8BA, 0xA155, 0xC8BB, 0xA156, + 0xC8BC, 0xC1C9, 0xC8BD, 0xC1CA, 0xC8BE, 0xA157, 0xC8BF, 0xA158, 0xC8C0, 0xA159, 0xC8C1, 0xA15A, 0xC8C2, 0xA161, 0xC8C3, 0xA162, + 0xC8C4, 0xC1CB, 0xC8C5, 0xA163, 0xC8C6, 0xA164, 0xC8C7, 0xA165, 0xC8C8, 0xC1CC, 0xC8C9, 0xA166, 0xC8CA, 0xA167, 0xC8CB, 0xA168, + 0xC8CC, 0xC1CD, 0xC8CD, 0xA169, 0xC8CE, 0xA16A, 0xC8CF, 0xA16B, 0xC8D0, 0xA16C, 0xC8D1, 0xA16D, 0xC8D2, 0xA16E, 0xC8D3, 0xA16F, + 0xC8D4, 0xC1CE, 0xC8D5, 0xC1CF, 0xC8D6, 0xA170, 0xC8D7, 0xC1D0, 0xC8D8, 0xA171, 0xC8D9, 0xC1D1, 0xC8DA, 0xA172, 0xC8DB, 0xA173, + 0xC8DC, 0xA174, 0xC8DD, 0xA175, 0xC8DE, 0xA176, 0xC8DF, 0xA177, 0xC8E0, 0xC1D2, 0xC8E1, 0xC1D3, 0xC8E2, 0xA178, 0xC8E3, 0xA179, + 0xC8E4, 0xC1D4, 0xC8E5, 0xA17A, 0xC8E6, 0xA181, 0xC8E7, 0xA182, 0xC8E8, 0xA183, 0xC8E9, 0xA184, 0xC8EA, 0xA185, 0xC8EB, 0xA186, + 0xC8EC, 0xA187, 0xC8ED, 0xA188, 0xC8EE, 0xA189, 0xC8EF, 0xA18A, 0xC8F0, 0xA18B, 0xC8F1, 0xA18C, 0xC8F2, 0xA18D, 0xC8F3, 0xA18E, + 0xC8F4, 0xA18F, 0xC8F5, 0xC1D5, 0xC8F6, 0xA190, 0xC8F7, 0xA191, 0xC8F8, 0xA192, 0xC8F9, 0xA193, 0xC8FA, 0xA194, 0xC8FB, 0xA195, + 0xC8FC, 0xC1D6, 0xC8FD, 0xC1D7, 0xC8FE, 0xA196, 0xC8FF, 0xA197, 0xC900, 0xC1D8, 0xC901, 0xA198, 0xC902, 0xA199, 0xC903, 0xA19A, + 0xC904, 0xC1D9, 0xC905, 0xC1DA, 0xC906, 0xC1DB, 0xC907, 0xA19B, 0xC908, 0xA19C, 0xC909, 0xA19D, 0xC90A, 0xA19E, 0xC90B, 0xA19F, + 0xC90C, 0xC1DC, 0xC90D, 0xC1DD, 0xC90E, 0xA1A0, 0xC90F, 0xC1DE, 0xC910, 0xA241, 0xC911, 0xC1DF, 0xC912, 0xA242, 0xC913, 0xA243, + 0xC914, 0xA244, 0xC915, 0xA245, 0xC916, 0xA246, 0xC917, 0xA247, 0xC918, 0xC1E0, 0xC919, 0xA248, 0xC91A, 0xA249, 0xC91B, 0xA24A, + 0xC91C, 0xA24B, 0xC91D, 0xA24C, 0xC91E, 0xA24D, 0xC91F, 0xA24E, 0xC920, 0xA24F, 0xC921, 0xA250, 0xC922, 0xA251, 0xC923, 0xA252, + 0xC924, 0xA253, 0xC925, 0xA254, 0xC926, 0xA255, 0xC927, 0xA256, 0xC928, 0xA257, 0xC929, 0xA258, 0xC92A, 0xA259, 0xC92B, 0xA25A, + 0xC92C, 0xC1E1, 0xC92D, 0xA261, 0xC92E, 0xA262, 0xC92F, 0xA263, 0xC930, 0xA264, 0xC931, 0xA265, 0xC932, 0xA266, 0xC933, 0xA267, + 0xC934, 0xC1E2, 0xC935, 0xA268, 0xC936, 0xA269, 0xC937, 0xA26A, 0xC938, 0xA26B, 0xC939, 0xA26C, 0xC93A, 0xA26D, 0xC93B, 0xA26E, + 0xC93C, 0xA26F, 0xC93D, 0xA270, 0xC93E, 0xA271, 0xC93F, 0xA272, 0xC940, 0xA273, 0xC941, 0xA274, 0xC942, 0xA275, 0xC943, 0xA276, + 0xC944, 0xA277, 0xC945, 0xA278, 0xC946, 0xA279, 0xC947, 0xA27A, 0xC948, 0xA281, 0xC949, 0xA282, 0xC94A, 0xA283, 0xC94B, 0xA284, + 0xC94C, 0xA285, 0xC94D, 0xA286, 0xC94E, 0xA287, 0xC94F, 0xA288, 0xC950, 0xC1E3, 0xC951, 0xC1E4, 0xC952, 0xA289, 0xC953, 0xA28A, + 0xC954, 0xC1E5, 0xC955, 0xA28B, 0xC956, 0xA28C, 0xC957, 0xA28D, 0xC958, 0xC1E6, 0xC959, 0xA28E, 0xC95A, 0xA28F, 0xC95B, 0xA290, + 0xC95C, 0xA291, 0xC95D, 0xA292, 0xC95E, 0xA293, 0xC95F, 0xA294, 0xC960, 0xC1E7, 0xC961, 0xC1E8, 0xC962, 0xA295, 0xC963, 0xC1E9, + 0xC964, 0xA296, 0xC965, 0xA297, 0xC966, 0xA298, 0xC967, 0xA299, 0xC968, 0xA29A, 0xC969, 0xA29B, 0xC96A, 0xA29C, 0xC96B, 0xA29D, + 0xC96C, 0xC1EA, 0xC96D, 0xA29E, 0xC96E, 0xA29F, 0xC96F, 0xA2A0, 0xC970, 0xC1EB, 0xC971, 0xA341, 0xC972, 0xA342, 0xC973, 0xA343, + 0xC974, 0xC1EC, 0xC975, 0xA344, 0xC976, 0xA345, 0xC977, 0xA346, 0xC978, 0xA347, 0xC979, 0xA348, 0xC97A, 0xA349, 0xC97B, 0xA34A, + 0xC97C, 0xC1ED, 0xC97D, 0xA34B, 0xC97E, 0xA34C, 0xC97F, 0xA34D, 0xC980, 0xA34E, 0xC981, 0xA34F, 0xC982, 0xA350, 0xC983, 0xA351, + 0xC984, 0xA352, 0xC985, 0xA353, 0xC986, 0xA354, 0xC987, 0xA355, 0xC988, 0xC1EE, 0xC989, 0xC1EF, 0xC98A, 0xA356, 0xC98B, 0xA357, + 0xC98C, 0xC1F0, 0xC98D, 0xA358, 0xC98E, 0xA359, 0xC98F, 0xA35A, 0xC990, 0xC1F1, 0xC991, 0xA361, 0xC992, 0xA362, 0xC993, 0xA363, + 0xC994, 0xA364, 0xC995, 0xA365, 0xC996, 0xA366, 0xC997, 0xA367, 0xC998, 0xC1F2, 0xC999, 0xC1F3, 0xC99A, 0xA368, 0xC99B, 0xC1F4, + 0xC99C, 0xA369, 0xC99D, 0xC1F5, 0xC99E, 0xA36A, 0xC99F, 0xA36B, 0xC9A0, 0xA36C, 0xC9A1, 0xA36D, 0xC9A2, 0xA36E, 0xC9A3, 0xA36F, + 0xC9A4, 0xA370, 0xC9A5, 0xA371, 0xC9A6, 0xA372, 0xC9A7, 0xA373, 0xC9A8, 0xA374, 0xC9A9, 0xA375, 0xC9AA, 0xA376, 0xC9AB, 0xA377, + 0xC9AC, 0xA378, 0xC9AD, 0xA379, 0xC9AE, 0xA37A, 0xC9AF, 0xA381, 0xC9B0, 0xA382, 0xC9B1, 0xA383, 0xC9B2, 0xA384, 0xC9B3, 0xA385, + 0xC9B4, 0xA386, 0xC9B5, 0xA387, 0xC9B6, 0xA388, 0xC9B7, 0xA389, 0xC9B8, 0xA38A, 0xC9B9, 0xA38B, 0xC9BA, 0xA38C, 0xC9BB, 0xA38D, + 0xC9BC, 0xA38E, 0xC9BD, 0xA38F, 0xC9BE, 0xA390, 0xC9BF, 0xA391, 0xC9C0, 0xC1F6, 0xC9C1, 0xC1F7, 0xC9C2, 0xA392, 0xC9C3, 0xA393, + 0xC9C4, 0xC1F8, 0xC9C5, 0xA394, 0xC9C6, 0xA395, 0xC9C7, 0xC1F9, 0xC9C8, 0xC1FA, 0xC9C9, 0xA396, 0xC9CA, 0xC1FB, 0xC9CB, 0xA397, + 0xC9CC, 0xA398, 0xC9CD, 0xA399, 0xC9CE, 0xA39A, 0xC9CF, 0xA39B, 0xC9D0, 0xC1FC, 0xC9D1, 0xC1FD, 0xC9D2, 0xA39C, 0xC9D3, 0xC1FE, + 0xC9D4, 0xA39D, 0xC9D5, 0xC2A1, 0xC9D6, 0xC2A2, 0xC9D7, 0xA39E, 0xC9D8, 0xA39F, 0xC9D9, 0xC2A3, 0xC9DA, 0xC2A4, 0xC9DB, 0xA3A0, + 0xC9DC, 0xC2A5, 0xC9DD, 0xC2A6, 0xC9DE, 0xA441, 0xC9DF, 0xA442, 0xC9E0, 0xC2A7, 0xC9E1, 0xA443, 0xC9E2, 0xC2A8, 0xC9E3, 0xA444, + 0xC9E4, 0xC2A9, 0xC9E5, 0xA445, 0xC9E6, 0xA446, 0xC9E7, 0xC2AA, 0xC9E8, 0xA447, 0xC9E9, 0xA448, 0xC9EA, 0xA449, 0xC9EB, 0xA44A, + 0xC9EC, 0xC2AB, 0xC9ED, 0xC2AC, 0xC9EE, 0xA44B, 0xC9EF, 0xC2AD, 0xC9F0, 0xC2AE, 0xC9F1, 0xC2AF, 0xC9F2, 0xA44C, 0xC9F3, 0xA44D, + 0xC9F4, 0xA44E, 0xC9F5, 0xA44F, 0xC9F6, 0xA450, 0xC9F7, 0xA451, 0xC9F8, 0xC2B0, 0xC9F9, 0xC2B1, 0xC9FA, 0xA452, 0xC9FB, 0xA453, + 0xC9FC, 0xC2B2, 0xC9FD, 0xA454, 0xC9FE, 0xA455, 0xC9FF, 0xA456, 0xCA00, 0xC2B3, 0xCA01, 0xA457, 0xCA02, 0xA458, 0xCA03, 0xA459, + 0xCA04, 0xA45A, 0xCA05, 0xA461, 0xCA06, 0xA462, 0xCA07, 0xA463, 0xCA08, 0xC2B4, 0xCA09, 0xC2B5, 0xCA0A, 0xA464, 0xCA0B, 0xC2B6, + 0xCA0C, 0xC2B7, 0xCA0D, 0xC2B8, 0xCA0E, 0xA465, 0xCA0F, 0xA466, 0xCA10, 0xA467, 0xCA11, 0xA468, 0xCA12, 0xA469, 0xCA13, 0xA46A, + 0xCA14, 0xC2B9, 0xCA15, 0xA46B, 0xCA16, 0xA46C, 0xCA17, 0xA46D, 0xCA18, 0xC2BA, 0xCA19, 0xA46E, 0xCA1A, 0xA46F, 0xCA1B, 0xA470, + 0xCA1C, 0xA471, 0xCA1D, 0xA472, 0xCA1E, 0xA473, 0xCA1F, 0xA474, 0xCA20, 0xA475, 0xCA21, 0xA476, 0xCA22, 0xA477, 0xCA23, 0xA478, + 0xCA24, 0xA479, 0xCA25, 0xA47A, 0xCA26, 0xA481, 0xCA27, 0xA482, 0xCA28, 0xA483, 0xCA29, 0xC2BB, 0xCA2A, 0xA484, 0xCA2B, 0xA485, + 0xCA2C, 0xA486, 0xCA2D, 0xA487, 0xCA2E, 0xA488, 0xCA2F, 0xA489, 0xCA30, 0xA48A, 0xCA31, 0xA48B, 0xCA32, 0xA48C, 0xCA33, 0xA48D, + 0xCA34, 0xA48E, 0xCA35, 0xA48F, 0xCA36, 0xA490, 0xCA37, 0xA491, 0xCA38, 0xA492, 0xCA39, 0xA493, 0xCA3A, 0xA494, 0xCA3B, 0xA495, + 0xCA3C, 0xA496, 0xCA3D, 0xA497, 0xCA3E, 0xA498, 0xCA3F, 0xA499, 0xCA40, 0xA49A, 0xCA41, 0xA49B, 0xCA42, 0xA49C, 0xCA43, 0xA49D, + 0xCA44, 0xA49E, 0xCA45, 0xA49F, 0xCA46, 0xA4A0, 0xCA47, 0xA541, 0xCA48, 0xA542, 0xCA49, 0xA543, 0xCA4A, 0xA544, 0xCA4B, 0xA545, + 0xCA4C, 0xC2BC, 0xCA4D, 0xC2BD, 0xCA4E, 0xA546, 0xCA4F, 0xA547, 0xCA50, 0xC2BE, 0xCA51, 0xA548, 0xCA52, 0xA549, 0xCA53, 0xA54A, + 0xCA54, 0xC2BF, 0xCA55, 0xA54B, 0xCA56, 0xA54C, 0xCA57, 0xA54D, 0xCA58, 0xA54E, 0xCA59, 0xA54F, 0xCA5A, 0xA550, 0xCA5B, 0xA551, + 0xCA5C, 0xC2C0, 0xCA5D, 0xC2C1, 0xCA5E, 0xA552, 0xCA5F, 0xC2C2, 0xCA60, 0xC2C3, 0xCA61, 0xC2C4, 0xCA62, 0xA553, 0xCA63, 0xA554, + 0xCA64, 0xA555, 0xCA65, 0xA556, 0xCA66, 0xA557, 0xCA67, 0xA558, 0xCA68, 0xC2C5, 0xCA69, 0xA559, 0xCA6A, 0xA55A, 0xCA6B, 0xA561, + 0xCA6C, 0xA562, 0xCA6D, 0xA563, 0xCA6E, 0xA564, 0xCA6F, 0xA565, 0xCA70, 0xA566, 0xCA71, 0xA567, 0xCA72, 0xA568, 0xCA73, 0xA569, + 0xCA74, 0xA56A, 0xCA75, 0xA56B, 0xCA76, 0xA56C, 0xCA77, 0xA56D, 0xCA78, 0xA56E, 0xCA79, 0xA56F, 0xCA7A, 0xA570, 0xCA7B, 0xA571, + 0xCA7C, 0xA572, 0xCA7D, 0xC2C6, 0xCA7E, 0xA573, 0xCA7F, 0xA574, 0xCA80, 0xA575, 0xCA81, 0xA576, 0xCA82, 0xA577, 0xCA83, 0xA578, + 0xCA84, 0xC2C7, 0xCA85, 0xA579, 0xCA86, 0xA57A, 0xCA87, 0xA581, 0xCA88, 0xA582, 0xCA89, 0xA583, 0xCA8A, 0xA584, 0xCA8B, 0xA585, + 0xCA8C, 0xA586, 0xCA8D, 0xA587, 0xCA8E, 0xA588, 0xCA8F, 0xA589, 0xCA90, 0xA58A, 0xCA91, 0xA58B, 0xCA92, 0xA58C, 0xCA93, 0xA58D, + 0xCA94, 0xA58E, 0xCA95, 0xA58F, 0xCA96, 0xA590, 0xCA97, 0xA591, 0xCA98, 0xC2C8, 0xCA99, 0xA592, 0xCA9A, 0xA593, 0xCA9B, 0xA594, + 0xCA9C, 0xA595, 0xCA9D, 0xA596, 0xCA9E, 0xA597, 0xCA9F, 0xA598, 0xCAA0, 0xA599, 0xCAA1, 0xA59A, 0xCAA2, 0xA59B, 0xCAA3, 0xA59C, + 0xCAA4, 0xA59D, 0xCAA5, 0xA59E, 0xCAA6, 0xA59F, 0xCAA7, 0xA5A0, 0xCAA8, 0xA641, 0xCAA9, 0xA642, 0xCAAA, 0xA643, 0xCAAB, 0xA644, + 0xCAAC, 0xA645, 0xCAAD, 0xA646, 0xCAAE, 0xA647, 0xCAAF, 0xA648, 0xCAB0, 0xA649, 0xCAB1, 0xA64A, 0xCAB2, 0xA64B, 0xCAB3, 0xA64C, + 0xCAB4, 0xA64D, 0xCAB5, 0xA64E, 0xCAB6, 0xA64F, 0xCAB7, 0xA650, 0xCAB8, 0xA651, 0xCAB9, 0xA652, 0xCABA, 0xA653, 0xCABB, 0xA654, + 0xCABC, 0xC2C9, 0xCABD, 0xC2CA, 0xCABE, 0xA655, 0xCABF, 0xA656, 0xCAC0, 0xC2CB, 0xCAC1, 0xA657, 0xCAC2, 0xA658, 0xCAC3, 0xA659, + 0xCAC4, 0xC2CC, 0xCAC5, 0xA65A, 0xCAC6, 0xA661, 0xCAC7, 0xA662, 0xCAC8, 0xA663, 0xCAC9, 0xA664, 0xCACA, 0xA665, 0xCACB, 0xA666, + 0xCACC, 0xC2CD, 0xCACD, 0xC2CE, 0xCACE, 0xA667, 0xCACF, 0xC2CF, 0xCAD0, 0xA668, 0xCAD1, 0xC2D0, 0xCAD2, 0xA669, 0xCAD3, 0xC2D1, + 0xCAD4, 0xA66A, 0xCAD5, 0xA66B, 0xCAD6, 0xA66C, 0xCAD7, 0xA66D, 0xCAD8, 0xC2D2, 0xCAD9, 0xC2D3, 0xCADA, 0xA66E, 0xCADB, 0xA66F, + 0xCADC, 0xA670, 0xCADD, 0xA671, 0xCADE, 0xA672, 0xCADF, 0xA673, 0xCAE0, 0xC2D4, 0xCAE1, 0xA674, 0xCAE2, 0xA675, 0xCAE3, 0xA676, + 0xCAE4, 0xA677, 0xCAE5, 0xA678, 0xCAE6, 0xA679, 0xCAE7, 0xA67A, 0xCAE8, 0xA681, 0xCAE9, 0xA682, 0xCAEA, 0xA683, 0xCAEB, 0xA684, + 0xCAEC, 0xC2D5, 0xCAED, 0xA685, 0xCAEE, 0xA686, 0xCAEF, 0xA687, 0xCAF0, 0xA688, 0xCAF1, 0xA689, 0xCAF2, 0xA68A, 0xCAF3, 0xA68B, + 0xCAF4, 0xC2D6, 0xCAF5, 0xA68C, 0xCAF6, 0xA68D, 0xCAF7, 0xA68E, 0xCAF8, 0xA68F, 0xCAF9, 0xA690, 0xCAFA, 0xA691, 0xCAFB, 0xA692, + 0xCAFC, 0xA693, 0xCAFD, 0xA694, 0xCAFE, 0xA695, 0xCAFF, 0xA696, 0xCB00, 0xA697, 0xCB01, 0xA698, 0xCB02, 0xA699, 0xCB03, 0xA69A, + 0xCB04, 0xA69B, 0xCB05, 0xA69C, 0xCB06, 0xA69D, 0xCB07, 0xA69E, 0xCB08, 0xC2D7, 0xCB09, 0xA69F, 0xCB0A, 0xA6A0, 0xCB0B, 0xA741, + 0xCB0C, 0xA742, 0xCB0D, 0xA743, 0xCB0E, 0xA744, 0xCB0F, 0xA745, 0xCB10, 0xC2D8, 0xCB11, 0xA746, 0xCB12, 0xA747, 0xCB13, 0xA748, + 0xCB14, 0xC2D9, 0xCB15, 0xA749, 0xCB16, 0xA74A, 0xCB17, 0xA74B, 0xCB18, 0xC2DA, 0xCB19, 0xA74C, 0xCB1A, 0xA74D, 0xCB1B, 0xA74E, + 0xCB1C, 0xA74F, 0xCB1D, 0xA750, 0xCB1E, 0xA751, 0xCB1F, 0xA752, 0xCB20, 0xC2DB, 0xCB21, 0xC2DC, 0xCB22, 0xA753, 0xCB23, 0xA754, + 0xCB24, 0xA755, 0xCB25, 0xA756, 0xCB26, 0xA757, 0xCB27, 0xA758, 0xCB28, 0xA759, 0xCB29, 0xA75A, 0xCB2A, 0xA761, 0xCB2B, 0xA762, + 0xCB2C, 0xA763, 0xCB2D, 0xA764, 0xCB2E, 0xA765, 0xCB2F, 0xA766, 0xCB30, 0xA767, 0xCB31, 0xA768, 0xCB32, 0xA769, 0xCB33, 0xA76A, + 0xCB34, 0xA76B, 0xCB35, 0xA76C, 0xCB36, 0xA76D, 0xCB37, 0xA76E, 0xCB38, 0xA76F, 0xCB39, 0xA770, 0xCB3A, 0xA771, 0xCB3B, 0xA772, + 0xCB3C, 0xA773, 0xCB3D, 0xA774, 0xCB3E, 0xA775, 0xCB3F, 0xA776, 0xCB40, 0xA777, 0xCB41, 0xC2DD, 0xCB42, 0xA778, 0xCB43, 0xA779, + 0xCB44, 0xA77A, 0xCB45, 0xA781, 0xCB46, 0xA782, 0xCB47, 0xA783, 0xCB48, 0xC2DE, 0xCB49, 0xC2DF, 0xCB4A, 0xA784, 0xCB4B, 0xA785, + 0xCB4C, 0xC2E0, 0xCB4D, 0xA786, 0xCB4E, 0xA787, 0xCB4F, 0xA788, 0xCB50, 0xC2E1, 0xCB51, 0xA789, 0xCB52, 0xA78A, 0xCB53, 0xA78B, + 0xCB54, 0xA78C, 0xCB55, 0xA78D, 0xCB56, 0xA78E, 0xCB57, 0xA78F, 0xCB58, 0xC2E2, 0xCB59, 0xC2E3, 0xCB5A, 0xA790, 0xCB5B, 0xA791, + 0xCB5C, 0xA792, 0xCB5D, 0xC2E4, 0xCB5E, 0xA793, 0xCB5F, 0xA794, 0xCB60, 0xA795, 0xCB61, 0xA796, 0xCB62, 0xA797, 0xCB63, 0xA798, + 0xCB64, 0xC2E5, 0xCB65, 0xA799, 0xCB66, 0xA79A, 0xCB67, 0xA79B, 0xCB68, 0xA79C, 0xCB69, 0xA79D, 0xCB6A, 0xA79E, 0xCB6B, 0xA79F, + 0xCB6C, 0xA7A0, 0xCB6D, 0xA841, 0xCB6E, 0xA842, 0xCB6F, 0xA843, 0xCB70, 0xA844, 0xCB71, 0xA845, 0xCB72, 0xA846, 0xCB73, 0xA847, + 0xCB74, 0xA848, 0xCB75, 0xA849, 0xCB76, 0xA84A, 0xCB77, 0xA84B, 0xCB78, 0xC2E6, 0xCB79, 0xC2E7, 0xCB7A, 0xA84C, 0xCB7B, 0xA84D, + 0xCB7C, 0xA84E, 0xCB7D, 0xA84F, 0xCB7E, 0xA850, 0xCB7F, 0xA851, 0xCB80, 0xA852, 0xCB81, 0xA853, 0xCB82, 0xA854, 0xCB83, 0xA855, + 0xCB84, 0xA856, 0xCB85, 0xA857, 0xCB86, 0xA858, 0xCB87, 0xA859, 0xCB88, 0xA85A, 0xCB89, 0xA861, 0xCB8A, 0xA862, 0xCB8B, 0xA863, + 0xCB8C, 0xA864, 0xCB8D, 0xA865, 0xCB8E, 0xA866, 0xCB8F, 0xA867, 0xCB90, 0xA868, 0xCB91, 0xA869, 0xCB92, 0xA86A, 0xCB93, 0xA86B, + 0xCB94, 0xA86C, 0xCB95, 0xA86D, 0xCB96, 0xA86E, 0xCB97, 0xA86F, 0xCB98, 0xA870, 0xCB99, 0xA871, 0xCB9A, 0xA872, 0xCB9B, 0xA873, + 0xCB9C, 0xC2E8, 0xCB9D, 0xA874, 0xCB9E, 0xA875, 0xCB9F, 0xA876, 0xCBA0, 0xA877, 0xCBA1, 0xA878, 0xCBA2, 0xA879, 0xCBA3, 0xA87A, + 0xCBA4, 0xA881, 0xCBA5, 0xA882, 0xCBA6, 0xA883, 0xCBA7, 0xA884, 0xCBA8, 0xA885, 0xCBA9, 0xA886, 0xCBAA, 0xA887, 0xCBAB, 0xA888, + 0xCBAC, 0xA889, 0xCBAD, 0xA88A, 0xCBAE, 0xA88B, 0xCBAF, 0xA88C, 0xCBB0, 0xA88D, 0xCBB1, 0xA88E, 0xCBB2, 0xA88F, 0xCBB3, 0xA890, + 0xCBB4, 0xA891, 0xCBB5, 0xA892, 0xCBB6, 0xA893, 0xCBB7, 0xA894, 0xCBB8, 0xC2E9, 0xCBB9, 0xA895, 0xCBBA, 0xA896, 0xCBBB, 0xA897, + 0xCBBC, 0xA898, 0xCBBD, 0xA899, 0xCBBE, 0xA89A, 0xCBBF, 0xA89B, 0xCBC0, 0xA89C, 0xCBC1, 0xA89D, 0xCBC2, 0xA89E, 0xCBC3, 0xA89F, + 0xCBC4, 0xA8A0, 0xCBC5, 0xA941, 0xCBC6, 0xA942, 0xCBC7, 0xA943, 0xCBC8, 0xA944, 0xCBC9, 0xA945, 0xCBCA, 0xA946, 0xCBCB, 0xA947, + 0xCBCC, 0xA948, 0xCBCD, 0xA949, 0xCBCE, 0xA94A, 0xCBCF, 0xA94B, 0xCBD0, 0xA94C, 0xCBD1, 0xA94D, 0xCBD2, 0xA94E, 0xCBD3, 0xA94F, + 0xCBD4, 0xC2EA, 0xCBD5, 0xA950, 0xCBD6, 0xA951, 0xCBD7, 0xA952, 0xCBD8, 0xA953, 0xCBD9, 0xA954, 0xCBDA, 0xA955, 0xCBDB, 0xA956, + 0xCBDC, 0xA957, 0xCBDD, 0xA958, 0xCBDE, 0xA959, 0xCBDF, 0xA95A, 0xCBE0, 0xA961, 0xCBE1, 0xA962, 0xCBE2, 0xA963, 0xCBE3, 0xA964, + 0xCBE4, 0xC2EB, 0xCBE5, 0xA965, 0xCBE6, 0xA966, 0xCBE7, 0xC2EC, 0xCBE8, 0xA967, 0xCBE9, 0xC2ED, 0xCBEA, 0xA968, 0xCBEB, 0xA969, + 0xCBEC, 0xA96A, 0xCBED, 0xA96B, 0xCBEE, 0xA96C, 0xCBEF, 0xA96D, 0xCBF0, 0xA96E, 0xCBF1, 0xA96F, 0xCBF2, 0xA970, 0xCBF3, 0xA971, + 0xCBF4, 0xA972, 0xCBF5, 0xA973, 0xCBF6, 0xA974, 0xCBF7, 0xA975, 0xCBF8, 0xA976, 0xCBF9, 0xA977, 0xCBFA, 0xA978, 0xCBFB, 0xA979, + 0xCBFC, 0xA97A, 0xCBFD, 0xA981, 0xCBFE, 0xA982, 0xCBFF, 0xA983, 0xCC00, 0xA984, 0xCC01, 0xA985, 0xCC02, 0xA986, 0xCC03, 0xA987, + 0xCC04, 0xA988, 0xCC05, 0xA989, 0xCC06, 0xA98A, 0xCC07, 0xA98B, 0xCC08, 0xA98C, 0xCC09, 0xA98D, 0xCC0A, 0xA98E, 0xCC0B, 0xA98F, + 0xCC0C, 0xC2EE, 0xCC0D, 0xC2EF, 0xCC0E, 0xA990, 0xCC0F, 0xA991, 0xCC10, 0xC2F0, 0xCC11, 0xA992, 0xCC12, 0xA993, 0xCC13, 0xA994, + 0xCC14, 0xC2F1, 0xCC15, 0xA995, 0xCC16, 0xA996, 0xCC17, 0xA997, 0xCC18, 0xA998, 0xCC19, 0xA999, 0xCC1A, 0xA99A, 0xCC1B, 0xA99B, + 0xCC1C, 0xC2F2, 0xCC1D, 0xC2F3, 0xCC1E, 0xA99C, 0xCC1F, 0xA99D, 0xCC20, 0xA99E, 0xCC21, 0xC2F4, 0xCC22, 0xC2F5, 0xCC23, 0xA99F, + 0xCC24, 0xA9A0, 0xCC25, 0xAA41, 0xCC26, 0xAA42, 0xCC27, 0xC2F6, 0xCC28, 0xC2F7, 0xCC29, 0xC2F8, 0xCC2A, 0xAA43, 0xCC2B, 0xAA44, + 0xCC2C, 0xC2F9, 0xCC2D, 0xAA45, 0xCC2E, 0xC2FA, 0xCC2F, 0xAA46, 0xCC30, 0xC2FB, 0xCC31, 0xAA47, 0xCC32, 0xAA48, 0xCC33, 0xAA49, + 0xCC34, 0xAA4A, 0xCC35, 0xAA4B, 0xCC36, 0xAA4C, 0xCC37, 0xAA4D, 0xCC38, 0xC2FC, 0xCC39, 0xC2FD, 0xCC3A, 0xAA4E, 0xCC3B, 0xC2FE, + 0xCC3C, 0xC3A1, 0xCC3D, 0xC3A2, 0xCC3E, 0xC3A3, 0xCC3F, 0xAA4F, 0xCC40, 0xAA50, 0xCC41, 0xAA51, 0xCC42, 0xAA52, 0xCC43, 0xAA53, + 0xCC44, 0xC3A4, 0xCC45, 0xC3A5, 0xCC46, 0xAA54, 0xCC47, 0xAA55, 0xCC48, 0xC3A6, 0xCC49, 0xAA56, 0xCC4A, 0xAA57, 0xCC4B, 0xAA58, + 0xCC4C, 0xC3A7, 0xCC4D, 0xAA59, 0xCC4E, 0xAA5A, 0xCC4F, 0xAA61, 0xCC50, 0xAA62, 0xCC51, 0xAA63, 0xCC52, 0xAA64, 0xCC53, 0xAA65, + 0xCC54, 0xC3A8, 0xCC55, 0xC3A9, 0xCC56, 0xAA66, 0xCC57, 0xC3AA, 0xCC58, 0xC3AB, 0xCC59, 0xC3AC, 0xCC5A, 0xAA67, 0xCC5B, 0xAA68, + 0xCC5C, 0xAA69, 0xCC5D, 0xAA6A, 0xCC5E, 0xAA6B, 0xCC5F, 0xAA6C, 0xCC60, 0xC3AD, 0xCC61, 0xAA6D, 0xCC62, 0xAA6E, 0xCC63, 0xAA6F, + 0xCC64, 0xC3AE, 0xCC65, 0xAA70, 0xCC66, 0xC3AF, 0xCC67, 0xAA71, 0xCC68, 0xC3B0, 0xCC69, 0xAA72, 0xCC6A, 0xAA73, 0xCC6B, 0xAA74, + 0xCC6C, 0xAA75, 0xCC6D, 0xAA76, 0xCC6E, 0xAA77, 0xCC6F, 0xAA78, 0xCC70, 0xC3B1, 0xCC71, 0xAA79, 0xCC72, 0xAA7A, 0xCC73, 0xAA81, + 0xCC74, 0xAA82, 0xCC75, 0xC3B2, 0xCC76, 0xAA83, 0xCC77, 0xAA84, 0xCC78, 0xAA85, 0xCC79, 0xAA86, 0xCC7A, 0xAA87, 0xCC7B, 0xAA88, + 0xCC7C, 0xAA89, 0xCC7D, 0xAA8A, 0xCC7E, 0xAA8B, 0xCC7F, 0xAA8C, 0xCC80, 0xAA8D, 0xCC81, 0xAA8E, 0xCC82, 0xAA8F, 0xCC83, 0xAA90, + 0xCC84, 0xAA91, 0xCC85, 0xAA92, 0xCC86, 0xAA93, 0xCC87, 0xAA94, 0xCC88, 0xAA95, 0xCC89, 0xAA96, 0xCC8A, 0xAA97, 0xCC8B, 0xAA98, + 0xCC8C, 0xAA99, 0xCC8D, 0xAA9A, 0xCC8E, 0xAA9B, 0xCC8F, 0xAA9C, 0xCC90, 0xAA9D, 0xCC91, 0xAA9E, 0xCC92, 0xAA9F, 0xCC93, 0xAAA0, + 0xCC94, 0xAB41, 0xCC95, 0xAB42, 0xCC96, 0xAB43, 0xCC97, 0xAB44, 0xCC98, 0xC3B3, 0xCC99, 0xC3B4, 0xCC9A, 0xAB45, 0xCC9B, 0xAB46, + 0xCC9C, 0xC3B5, 0xCC9D, 0xAB47, 0xCC9E, 0xAB48, 0xCC9F, 0xAB49, 0xCCA0, 0xC3B6, 0xCCA1, 0xAB4A, 0xCCA2, 0xAB4B, 0xCCA3, 0xAB4C, + 0xCCA4, 0xAB4D, 0xCCA5, 0xAB4E, 0xCCA6, 0xAB4F, 0xCCA7, 0xAB50, 0xCCA8, 0xC3B7, 0xCCA9, 0xC3B8, 0xCCAA, 0xAB51, 0xCCAB, 0xC3B9, + 0xCCAC, 0xC3BA, 0xCCAD, 0xC3BB, 0xCCAE, 0xAB52, 0xCCAF, 0xAB53, 0xCCB0, 0xAB54, 0xCCB1, 0xAB55, 0xCCB2, 0xAB56, 0xCCB3, 0xAB57, + 0xCCB4, 0xC3BC, 0xCCB5, 0xC3BD, 0xCCB6, 0xAB58, 0xCCB7, 0xAB59, 0xCCB8, 0xC3BE, 0xCCB9, 0xAB5A, 0xCCBA, 0xAB61, 0xCCBB, 0xAB62, + 0xCCBC, 0xC3BF, 0xCCBD, 0xAB63, 0xCCBE, 0xAB64, 0xCCBF, 0xAB65, 0xCCC0, 0xAB66, 0xCCC1, 0xAB67, 0xCCC2, 0xAB68, 0xCCC3, 0xAB69, + 0xCCC4, 0xC3C0, 0xCCC5, 0xC3C1, 0xCCC6, 0xAB6A, 0xCCC7, 0xC3C2, 0xCCC8, 0xAB6B, 0xCCC9, 0xC3C3, 0xCCCA, 0xAB6C, 0xCCCB, 0xAB6D, + 0xCCCC, 0xAB6E, 0xCCCD, 0xAB6F, 0xCCCE, 0xAB70, 0xCCCF, 0xAB71, 0xCCD0, 0xC3C4, 0xCCD1, 0xAB72, 0xCCD2, 0xAB73, 0xCCD3, 0xAB74, + 0xCCD4, 0xC3C5, 0xCCD5, 0xAB75, 0xCCD6, 0xAB76, 0xCCD7, 0xAB77, 0xCCD8, 0xAB78, 0xCCD9, 0xAB79, 0xCCDA, 0xAB7A, 0xCCDB, 0xAB81, + 0xCCDC, 0xAB82, 0xCCDD, 0xAB83, 0xCCDE, 0xAB84, 0xCCDF, 0xAB85, 0xCCE0, 0xAB86, 0xCCE1, 0xAB87, 0xCCE2, 0xAB88, 0xCCE3, 0xAB89, + 0xCCE4, 0xC3C6, 0xCCE5, 0xAB8A, 0xCCE6, 0xAB8B, 0xCCE7, 0xAB8C, 0xCCE8, 0xAB8D, 0xCCE9, 0xAB8E, 0xCCEA, 0xAB8F, 0xCCEB, 0xAB90, + 0xCCEC, 0xC3C7, 0xCCED, 0xAB91, 0xCCEE, 0xAB92, 0xCCEF, 0xAB93, 0xCCF0, 0xC3C8, 0xCCF1, 0xAB94, 0xCCF2, 0xAB95, 0xCCF3, 0xAB96, + 0xCCF4, 0xAB97, 0xCCF5, 0xAB98, 0xCCF6, 0xAB99, 0xCCF7, 0xAB9A, 0xCCF8, 0xAB9B, 0xCCF9, 0xAB9C, 0xCCFA, 0xAB9D, 0xCCFB, 0xAB9E, + 0xCCFC, 0xAB9F, 0xCCFD, 0xABA0, 0xCCFE, 0xAC41, 0xCCFF, 0xAC42, 0xCD00, 0xAC43, 0xCD01, 0xC3C9, 0xCD02, 0xAC44, 0xCD03, 0xAC45, + 0xCD04, 0xAC46, 0xCD05, 0xAC47, 0xCD06, 0xAC48, 0xCD07, 0xAC49, 0xCD08, 0xC3CA, 0xCD09, 0xC3CB, 0xCD0A, 0xAC4A, 0xCD0B, 0xAC4B, + 0xCD0C, 0xC3CC, 0xCD0D, 0xAC4C, 0xCD0E, 0xAC4D, 0xCD0F, 0xAC4E, 0xCD10, 0xC3CD, 0xCD11, 0xAC4F, 0xCD12, 0xAC50, 0xCD13, 0xAC51, + 0xCD14, 0xAC52, 0xCD15, 0xAC53, 0xCD16, 0xAC54, 0xCD17, 0xAC55, 0xCD18, 0xC3CE, 0xCD19, 0xC3CF, 0xCD1A, 0xAC56, 0xCD1B, 0xC3D0, + 0xCD1C, 0xAC57, 0xCD1D, 0xC3D1, 0xCD1E, 0xAC58, 0xCD1F, 0xAC59, 0xCD20, 0xAC5A, 0xCD21, 0xAC61, 0xCD22, 0xAC62, 0xCD23, 0xAC63, + 0xCD24, 0xC3D2, 0xCD25, 0xAC64, 0xCD26, 0xAC65, 0xCD27, 0xAC66, 0xCD28, 0xC3D3, 0xCD29, 0xAC67, 0xCD2A, 0xAC68, 0xCD2B, 0xAC69, + 0xCD2C, 0xC3D4, 0xCD2D, 0xAC6A, 0xCD2E, 0xAC6B, 0xCD2F, 0xAC6C, 0xCD30, 0xAC6D, 0xCD31, 0xAC6E, 0xCD32, 0xAC6F, 0xCD33, 0xAC70, + 0xCD34, 0xAC71, 0xCD35, 0xAC72, 0xCD36, 0xAC73, 0xCD37, 0xAC74, 0xCD38, 0xAC75, 0xCD39, 0xC3D5, 0xCD3A, 0xAC76, 0xCD3B, 0xAC77, + 0xCD3C, 0xAC78, 0xCD3D, 0xAC79, 0xCD3E, 0xAC7A, 0xCD3F, 0xAC81, 0xCD40, 0xAC82, 0xCD41, 0xAC83, 0xCD42, 0xAC84, 0xCD43, 0xAC85, + 0xCD44, 0xAC86, 0xCD45, 0xAC87, 0xCD46, 0xAC88, 0xCD47, 0xAC89, 0xCD48, 0xAC8A, 0xCD49, 0xAC8B, 0xCD4A, 0xAC8C, 0xCD4B, 0xAC8D, + 0xCD4C, 0xAC8E, 0xCD4D, 0xAC8F, 0xCD4E, 0xAC90, 0xCD4F, 0xAC91, 0xCD50, 0xAC92, 0xCD51, 0xAC93, 0xCD52, 0xAC94, 0xCD53, 0xAC95, + 0xCD54, 0xAC96, 0xCD55, 0xAC97, 0xCD56, 0xAC98, 0xCD57, 0xAC99, 0xCD58, 0xAC9A, 0xCD59, 0xAC9B, 0xCD5A, 0xAC9C, 0xCD5B, 0xAC9D, + 0xCD5C, 0xC3D6, 0xCD5D, 0xAC9E, 0xCD5E, 0xAC9F, 0xCD5F, 0xACA0, 0xCD60, 0xC3D7, 0xCD61, 0xAD41, 0xCD62, 0xAD42, 0xCD63, 0xAD43, + 0xCD64, 0xC3D8, 0xCD65, 0xAD44, 0xCD66, 0xAD45, 0xCD67, 0xAD46, 0xCD68, 0xAD47, 0xCD69, 0xAD48, 0xCD6A, 0xAD49, 0xCD6B, 0xAD4A, + 0xCD6C, 0xC3D9, 0xCD6D, 0xC3DA, 0xCD6E, 0xAD4B, 0xCD6F, 0xC3DB, 0xCD70, 0xAD4C, 0xCD71, 0xC3DC, 0xCD72, 0xAD4D, 0xCD73, 0xAD4E, + 0xCD74, 0xAD4F, 0xCD75, 0xAD50, 0xCD76, 0xAD51, 0xCD77, 0xAD52, 0xCD78, 0xC3DD, 0xCD79, 0xAD53, 0xCD7A, 0xAD54, 0xCD7B, 0xAD55, + 0xCD7C, 0xAD56, 0xCD7D, 0xAD57, 0xCD7E, 0xAD58, 0xCD7F, 0xAD59, 0xCD80, 0xAD5A, 0xCD81, 0xAD61, 0xCD82, 0xAD62, 0xCD83, 0xAD63, + 0xCD84, 0xAD64, 0xCD85, 0xAD65, 0xCD86, 0xAD66, 0xCD87, 0xAD67, 0xCD88, 0xC3DE, 0xCD89, 0xAD68, 0xCD8A, 0xAD69, 0xCD8B, 0xAD6A, + 0xCD8C, 0xAD6B, 0xCD8D, 0xAD6C, 0xCD8E, 0xAD6D, 0xCD8F, 0xAD6E, 0xCD90, 0xAD6F, 0xCD91, 0xAD70, 0xCD92, 0xAD71, 0xCD93, 0xAD72, + 0xCD94, 0xC3DF, 0xCD95, 0xC3E0, 0xCD96, 0xAD73, 0xCD97, 0xAD74, 0xCD98, 0xC3E1, 0xCD99, 0xAD75, 0xCD9A, 0xAD76, 0xCD9B, 0xAD77, + 0xCD9C, 0xC3E2, 0xCD9D, 0xAD78, 0xCD9E, 0xAD79, 0xCD9F, 0xAD7A, 0xCDA0, 0xAD81, 0xCDA1, 0xAD82, 0xCDA2, 0xAD83, 0xCDA3, 0xAD84, + 0xCDA4, 0xC3E3, 0xCDA5, 0xC3E4, 0xCDA6, 0xAD85, 0xCDA7, 0xC3E5, 0xCDA8, 0xAD86, 0xCDA9, 0xC3E6, 0xCDAA, 0xAD87, 0xCDAB, 0xAD88, + 0xCDAC, 0xAD89, 0xCDAD, 0xAD8A, 0xCDAE, 0xAD8B, 0xCDAF, 0xAD8C, 0xCDB0, 0xC3E7, 0xCDB1, 0xAD8D, 0xCDB2, 0xAD8E, 0xCDB3, 0xAD8F, + 0xCDB4, 0xAD90, 0xCDB5, 0xAD91, 0xCDB6, 0xAD92, 0xCDB7, 0xAD93, 0xCDB8, 0xAD94, 0xCDB9, 0xAD95, 0xCDBA, 0xAD96, 0xCDBB, 0xAD97, + 0xCDBC, 0xAD98, 0xCDBD, 0xAD99, 0xCDBE, 0xAD9A, 0xCDBF, 0xAD9B, 0xCDC0, 0xAD9C, 0xCDC1, 0xAD9D, 0xCDC2, 0xAD9E, 0xCDC3, 0xAD9F, + 0xCDC4, 0xC3E8, 0xCDC5, 0xADA0, 0xCDC6, 0xAE41, 0xCDC7, 0xAE42, 0xCDC8, 0xAE43, 0xCDC9, 0xAE44, 0xCDCA, 0xAE45, 0xCDCB, 0xAE46, + 0xCDCC, 0xC3E9, 0xCDCD, 0xAE47, 0xCDCE, 0xAE48, 0xCDCF, 0xAE49, 0xCDD0, 0xC3EA, 0xCDD1, 0xAE4A, 0xCDD2, 0xAE4B, 0xCDD3, 0xAE4C, + 0xCDD4, 0xAE4D, 0xCDD5, 0xAE4E, 0xCDD6, 0xAE4F, 0xCDD7, 0xAE50, 0xCDD8, 0xAE51, 0xCDD9, 0xAE52, 0xCDDA, 0xAE53, 0xCDDB, 0xAE54, + 0xCDDC, 0xAE55, 0xCDDD, 0xAE56, 0xCDDE, 0xAE57, 0xCDDF, 0xAE58, 0xCDE0, 0xAE59, 0xCDE1, 0xAE5A, 0xCDE2, 0xAE61, 0xCDE3, 0xAE62, + 0xCDE4, 0xAE63, 0xCDE5, 0xAE64, 0xCDE6, 0xAE65, 0xCDE7, 0xAE66, 0xCDE8, 0xC3EB, 0xCDE9, 0xAE67, 0xCDEA, 0xAE68, 0xCDEB, 0xAE69, + 0xCDEC, 0xC3EC, 0xCDED, 0xAE6A, 0xCDEE, 0xAE6B, 0xCDEF, 0xAE6C, 0xCDF0, 0xC3ED, 0xCDF1, 0xAE6D, 0xCDF2, 0xAE6E, 0xCDF3, 0xAE6F, + 0xCDF4, 0xAE70, 0xCDF5, 0xAE71, 0xCDF6, 0xAE72, 0xCDF7, 0xAE73, 0xCDF8, 0xC3EE, 0xCDF9, 0xC3EF, 0xCDFA, 0xAE74, 0xCDFB, 0xC3F0, + 0xCDFC, 0xAE75, 0xCDFD, 0xC3F1, 0xCDFE, 0xAE76, 0xCDFF, 0xAE77, 0xCE00, 0xAE78, 0xCE01, 0xAE79, 0xCE02, 0xAE7A, 0xCE03, 0xAE81, + 0xCE04, 0xC3F2, 0xCE05, 0xAE82, 0xCE06, 0xAE83, 0xCE07, 0xAE84, 0xCE08, 0xC3F3, 0xCE09, 0xAE85, 0xCE0A, 0xAE86, 0xCE0B, 0xAE87, + 0xCE0C, 0xC3F4, 0xCE0D, 0xAE88, 0xCE0E, 0xAE89, 0xCE0F, 0xAE8A, 0xCE10, 0xAE8B, 0xCE11, 0xAE8C, 0xCE12, 0xAE8D, 0xCE13, 0xAE8E, + 0xCE14, 0xC3F5, 0xCE15, 0xAE8F, 0xCE16, 0xAE90, 0xCE17, 0xAE91, 0xCE18, 0xAE92, 0xCE19, 0xC3F6, 0xCE1A, 0xAE93, 0xCE1B, 0xAE94, + 0xCE1C, 0xAE95, 0xCE1D, 0xAE96, 0xCE1E, 0xAE97, 0xCE1F, 0xAE98, 0xCE20, 0xC3F7, 0xCE21, 0xC3F8, 0xCE22, 0xAE99, 0xCE23, 0xAE9A, + 0xCE24, 0xC3F9, 0xCE25, 0xAE9B, 0xCE26, 0xAE9C, 0xCE27, 0xAE9D, 0xCE28, 0xC3FA, 0xCE29, 0xAE9E, 0xCE2A, 0xAE9F, 0xCE2B, 0xAEA0, + 0xCE2C, 0xAF41, 0xCE2D, 0xAF42, 0xCE2E, 0xAF43, 0xCE2F, 0xAF44, 0xCE30, 0xC3FB, 0xCE31, 0xC3FC, 0xCE32, 0xAF45, 0xCE33, 0xC3FD, + 0xCE34, 0xAF46, 0xCE35, 0xC3FE, 0xCE36, 0xAF47, 0xCE37, 0xAF48, 0xCE38, 0xAF49, 0xCE39, 0xAF4A, 0xCE3A, 0xAF4B, 0xCE3B, 0xAF4C, + 0xCE3C, 0xAF4D, 0xCE3D, 0xAF4E, 0xCE3E, 0xAF4F, 0xCE3F, 0xAF50, 0xCE40, 0xAF51, 0xCE41, 0xAF52, 0xCE42, 0xAF53, 0xCE43, 0xAF54, + 0xCE44, 0xAF55, 0xCE45, 0xAF56, 0xCE46, 0xAF57, 0xCE47, 0xAF58, 0xCE48, 0xAF59, 0xCE49, 0xAF5A, 0xCE4A, 0xAF61, 0xCE4B, 0xAF62, + 0xCE4C, 0xAF63, 0xCE4D, 0xAF64, 0xCE4E, 0xAF65, 0xCE4F, 0xAF66, 0xCE50, 0xAF67, 0xCE51, 0xAF68, 0xCE52, 0xAF69, 0xCE53, 0xAF6A, + 0xCE54, 0xAF6B, 0xCE55, 0xAF6C, 0xCE56, 0xAF6D, 0xCE57, 0xAF6E, 0xCE58, 0xC4A1, 0xCE59, 0xC4A2, 0xCE5A, 0xAF6F, 0xCE5B, 0xAF70, + 0xCE5C, 0xC4A3, 0xCE5D, 0xAF71, 0xCE5E, 0xAF72, 0xCE5F, 0xC4A4, 0xCE60, 0xC4A5, 0xCE61, 0xC4A6, 0xCE62, 0xAF73, 0xCE63, 0xAF74, + 0xCE64, 0xAF75, 0xCE65, 0xAF76, 0xCE66, 0xAF77, 0xCE67, 0xAF78, 0xCE68, 0xC4A7, 0xCE69, 0xC4A8, 0xCE6A, 0xAF79, 0xCE6B, 0xC4A9, + 0xCE6C, 0xAF7A, 0xCE6D, 0xC4AA, 0xCE6E, 0xAF81, 0xCE6F, 0xAF82, 0xCE70, 0xAF83, 0xCE71, 0xAF84, 0xCE72, 0xAF85, 0xCE73, 0xAF86, + 0xCE74, 0xC4AB, 0xCE75, 0xC4AC, 0xCE76, 0xAF87, 0xCE77, 0xAF88, 0xCE78, 0xC4AD, 0xCE79, 0xAF89, 0xCE7A, 0xAF8A, 0xCE7B, 0xAF8B, + 0xCE7C, 0xC4AE, 0xCE7D, 0xAF8C, 0xCE7E, 0xAF8D, 0xCE7F, 0xAF8E, 0xCE80, 0xAF8F, 0xCE81, 0xAF90, 0xCE82, 0xAF91, 0xCE83, 0xAF92, + 0xCE84, 0xC4AF, 0xCE85, 0xC4B0, 0xCE86, 0xAF93, 0xCE87, 0xC4B1, 0xCE88, 0xAF94, 0xCE89, 0xC4B2, 0xCE8A, 0xAF95, 0xCE8B, 0xAF96, + 0xCE8C, 0xAF97, 0xCE8D, 0xAF98, 0xCE8E, 0xAF99, 0xCE8F, 0xAF9A, 0xCE90, 0xC4B3, 0xCE91, 0xC4B4, 0xCE92, 0xAF9B, 0xCE93, 0xAF9C, + 0xCE94, 0xC4B5, 0xCE95, 0xAF9D, 0xCE96, 0xAF9E, 0xCE97, 0xAF9F, 0xCE98, 0xC4B6, 0xCE99, 0xAFA0, 0xCE9A, 0xB041, 0xCE9B, 0xB042, + 0xCE9C, 0xB043, 0xCE9D, 0xB044, 0xCE9E, 0xB045, 0xCE9F, 0xB046, 0xCEA0, 0xC4B7, 0xCEA1, 0xC4B8, 0xCEA2, 0xB047, 0xCEA3, 0xC4B9, + 0xCEA4, 0xC4BA, 0xCEA5, 0xC4BB, 0xCEA6, 0xB048, 0xCEA7, 0xB049, 0xCEA8, 0xB04A, 0xCEA9, 0xB04B, 0xCEAA, 0xB04C, 0xCEAB, 0xB04D, + 0xCEAC, 0xC4BC, 0xCEAD, 0xC4BD, 0xCEAE, 0xB04E, 0xCEAF, 0xB04F, 0xCEB0, 0xB050, 0xCEB1, 0xB051, 0xCEB2, 0xB052, 0xCEB3, 0xB053, + 0xCEB4, 0xB054, 0xCEB5, 0xB055, 0xCEB6, 0xB056, 0xCEB7, 0xB057, 0xCEB8, 0xB058, 0xCEB9, 0xB059, 0xCEBA, 0xB05A, 0xCEBB, 0xB061, + 0xCEBC, 0xB062, 0xCEBD, 0xB063, 0xCEBE, 0xB064, 0xCEBF, 0xB065, 0xCEC0, 0xB066, 0xCEC1, 0xC4BE, 0xCEC2, 0xB067, 0xCEC3, 0xB068, + 0xCEC4, 0xB069, 0xCEC5, 0xB06A, 0xCEC6, 0xB06B, 0xCEC7, 0xB06C, 0xCEC8, 0xB06D, 0xCEC9, 0xB06E, 0xCECA, 0xB06F, 0xCECB, 0xB070, + 0xCECC, 0xB071, 0xCECD, 0xB072, 0xCECE, 0xB073, 0xCECF, 0xB074, 0xCED0, 0xB075, 0xCED1, 0xB076, 0xCED2, 0xB077, 0xCED3, 0xB078, + 0xCED4, 0xB079, 0xCED5, 0xB07A, 0xCED6, 0xB081, 0xCED7, 0xB082, 0xCED8, 0xB083, 0xCED9, 0xB084, 0xCEDA, 0xB085, 0xCEDB, 0xB086, + 0xCEDC, 0xB087, 0xCEDD, 0xB088, 0xCEDE, 0xB089, 0xCEDF, 0xB08A, 0xCEE0, 0xB08B, 0xCEE1, 0xB08C, 0xCEE2, 0xB08D, 0xCEE3, 0xB08E, + 0xCEE4, 0xC4BF, 0xCEE5, 0xC4C0, 0xCEE6, 0xB08F, 0xCEE7, 0xB090, 0xCEE8, 0xC4C1, 0xCEE9, 0xB091, 0xCEEA, 0xB092, 0xCEEB, 0xC4C2, + 0xCEEC, 0xC4C3, 0xCEED, 0xB093, 0xCEEE, 0xB094, 0xCEEF, 0xB095, 0xCEF0, 0xB096, 0xCEF1, 0xB097, 0xCEF2, 0xB098, 0xCEF3, 0xB099, + 0xCEF4, 0xC4C4, 0xCEF5, 0xC4C5, 0xCEF6, 0xB09A, 0xCEF7, 0xC4C6, 0xCEF8, 0xC4C7, 0xCEF9, 0xC4C8, 0xCEFA, 0xB09B, 0xCEFB, 0xB09C, + 0xCEFC, 0xB09D, 0xCEFD, 0xB09E, 0xCEFE, 0xB09F, 0xCEFF, 0xB0A0, 0xCF00, 0xC4C9, 0xCF01, 0xC4CA, 0xCF02, 0xB141, 0xCF03, 0xB142, + 0xCF04, 0xC4CB, 0xCF05, 0xB143, 0xCF06, 0xB144, 0xCF07, 0xB145, 0xCF08, 0xC4CC, 0xCF09, 0xB146, 0xCF0A, 0xB147, 0xCF0B, 0xB148, + 0xCF0C, 0xB149, 0xCF0D, 0xB14A, 0xCF0E, 0xB14B, 0xCF0F, 0xB14C, 0xCF10, 0xC4CD, 0xCF11, 0xC4CE, 0xCF12, 0xB14D, 0xCF13, 0xC4CF, + 0xCF14, 0xB14E, 0xCF15, 0xC4D0, 0xCF16, 0xB14F, 0xCF17, 0xB150, 0xCF18, 0xB151, 0xCF19, 0xB152, 0xCF1A, 0xB153, 0xCF1B, 0xB154, + 0xCF1C, 0xC4D1, 0xCF1D, 0xB155, 0xCF1E, 0xB156, 0xCF1F, 0xB157, 0xCF20, 0xC4D2, 0xCF21, 0xB158, 0xCF22, 0xB159, 0xCF23, 0xB15A, + 0xCF24, 0xC4D3, 0xCF25, 0xB161, 0xCF26, 0xB162, 0xCF27, 0xB163, 0xCF28, 0xB164, 0xCF29, 0xB165, 0xCF2A, 0xB166, 0xCF2B, 0xB167, + 0xCF2C, 0xC4D4, 0xCF2D, 0xC4D5, 0xCF2E, 0xB168, 0xCF2F, 0xC4D6, 0xCF30, 0xC4D7, 0xCF31, 0xC4D8, 0xCF32, 0xB169, 0xCF33, 0xB16A, + 0xCF34, 0xB16B, 0xCF35, 0xB16C, 0xCF36, 0xB16D, 0xCF37, 0xB16E, 0xCF38, 0xC4D9, 0xCF39, 0xB16F, 0xCF3A, 0xB170, 0xCF3B, 0xB171, + 0xCF3C, 0xB172, 0xCF3D, 0xB173, 0xCF3E, 0xB174, 0xCF3F, 0xB175, 0xCF40, 0xB176, 0xCF41, 0xB177, 0xCF42, 0xB178, 0xCF43, 0xB179, + 0xCF44, 0xB17A, 0xCF45, 0xB181, 0xCF46, 0xB182, 0xCF47, 0xB183, 0xCF48, 0xB184, 0xCF49, 0xB185, 0xCF4A, 0xB186, 0xCF4B, 0xB187, + 0xCF4C, 0xB188, 0xCF4D, 0xB189, 0xCF4E, 0xB18A, 0xCF4F, 0xB18B, 0xCF50, 0xB18C, 0xCF51, 0xB18D, 0xCF52, 0xB18E, 0xCF53, 0xB18F, + 0xCF54, 0xC4DA, 0xCF55, 0xC4DB, 0xCF56, 0xB190, 0xCF57, 0xB191, 0xCF58, 0xC4DC, 0xCF59, 0xB192, 0xCF5A, 0xB193, 0xCF5B, 0xB194, + 0xCF5C, 0xC4DD, 0xCF5D, 0xB195, 0xCF5E, 0xB196, 0xCF5F, 0xB197, 0xCF60, 0xB198, 0xCF61, 0xB199, 0xCF62, 0xB19A, 0xCF63, 0xB19B, + 0xCF64, 0xC4DE, 0xCF65, 0xC4DF, 0xCF66, 0xB19C, 0xCF67, 0xC4E0, 0xCF68, 0xB19D, 0xCF69, 0xC4E1, 0xCF6A, 0xB19E, 0xCF6B, 0xB19F, + 0xCF6C, 0xB1A0, 0xCF6D, 0xB241, 0xCF6E, 0xB242, 0xCF6F, 0xB243, 0xCF70, 0xC4E2, 0xCF71, 0xC4E3, 0xCF72, 0xB244, 0xCF73, 0xB245, + 0xCF74, 0xC4E4, 0xCF75, 0xB246, 0xCF76, 0xB247, 0xCF77, 0xB248, 0xCF78, 0xC4E5, 0xCF79, 0xB249, 0xCF7A, 0xB24A, 0xCF7B, 0xB24B, + 0xCF7C, 0xB24C, 0xCF7D, 0xB24D, 0xCF7E, 0xB24E, 0xCF7F, 0xB24F, 0xCF80, 0xC4E6, 0xCF81, 0xB250, 0xCF82, 0xB251, 0xCF83, 0xB252, + 0xCF84, 0xB253, 0xCF85, 0xC4E7, 0xCF86, 0xB254, 0xCF87, 0xB255, 0xCF88, 0xB256, 0xCF89, 0xB257, 0xCF8A, 0xB258, 0xCF8B, 0xB259, + 0xCF8C, 0xC4E8, 0xCF8D, 0xB25A, 0xCF8E, 0xB261, 0xCF8F, 0xB262, 0xCF90, 0xB263, 0xCF91, 0xB264, 0xCF92, 0xB265, 0xCF93, 0xB266, + 0xCF94, 0xB267, 0xCF95, 0xB268, 0xCF96, 0xB269, 0xCF97, 0xB26A, 0xCF98, 0xB26B, 0xCF99, 0xB26C, 0xCF9A, 0xB26D, 0xCF9B, 0xB26E, + 0xCF9C, 0xB26F, 0xCF9D, 0xB270, 0xCF9E, 0xB271, 0xCF9F, 0xB272, 0xCFA0, 0xB273, 0xCFA1, 0xC4E9, 0xCFA2, 0xB274, 0xCFA3, 0xB275, + 0xCFA4, 0xB276, 0xCFA5, 0xB277, 0xCFA6, 0xB278, 0xCFA7, 0xB279, 0xCFA8, 0xC4EA, 0xCFA9, 0xB27A, 0xCFAA, 0xB281, 0xCFAB, 0xB282, + 0xCFAC, 0xB283, 0xCFAD, 0xB284, 0xCFAE, 0xB285, 0xCFAF, 0xB286, 0xCFB0, 0xC4EB, 0xCFB1, 0xB287, 0xCFB2, 0xB288, 0xCFB3, 0xB289, + 0xCFB4, 0xB28A, 0xCFB5, 0xB28B, 0xCFB6, 0xB28C, 0xCFB7, 0xB28D, 0xCFB8, 0xB28E, 0xCFB9, 0xB28F, 0xCFBA, 0xB290, 0xCFBB, 0xB291, + 0xCFBC, 0xB292, 0xCFBD, 0xB293, 0xCFBE, 0xB294, 0xCFBF, 0xB295, 0xCFC0, 0xB296, 0xCFC1, 0xB297, 0xCFC2, 0xB298, 0xCFC3, 0xB299, + 0xCFC4, 0xC4EC, 0xCFC5, 0xB29A, 0xCFC6, 0xB29B, 0xCFC7, 0xB29C, 0xCFC8, 0xB29D, 0xCFC9, 0xB29E, 0xCFCA, 0xB29F, 0xCFCB, 0xB2A0, + 0xCFCC, 0xB341, 0xCFCD, 0xB342, 0xCFCE, 0xB343, 0xCFCF, 0xB344, 0xCFD0, 0xB345, 0xCFD1, 0xB346, 0xCFD2, 0xB347, 0xCFD3, 0xB348, + 0xCFD4, 0xB349, 0xCFD5, 0xB34A, 0xCFD6, 0xB34B, 0xCFD7, 0xB34C, 0xCFD8, 0xB34D, 0xCFD9, 0xB34E, 0xCFDA, 0xB34F, 0xCFDB, 0xB350, + 0xCFDC, 0xB351, 0xCFDD, 0xB352, 0xCFDE, 0xB353, 0xCFDF, 0xB354, 0xCFE0, 0xC4ED, 0xCFE1, 0xC4EE, 0xCFE2, 0xB355, 0xCFE3, 0xB356, + 0xCFE4, 0xC4EF, 0xCFE5, 0xB357, 0xCFE6, 0xB358, 0xCFE7, 0xB359, 0xCFE8, 0xC4F0, 0xCFE9, 0xB35A, 0xCFEA, 0xB361, 0xCFEB, 0xB362, + 0xCFEC, 0xB363, 0xCFED, 0xB364, 0xCFEE, 0xB365, 0xCFEF, 0xB366, 0xCFF0, 0xC4F1, 0xCFF1, 0xC4F2, 0xCFF2, 0xB367, 0xCFF3, 0xC4F3, + 0xCFF4, 0xB368, 0xCFF5, 0xC4F4, 0xCFF6, 0xB369, 0xCFF7, 0xB36A, 0xCFF8, 0xB36B, 0xCFF9, 0xB36C, 0xCFFA, 0xB36D, 0xCFFB, 0xB36E, + 0xCFFC, 0xC4F5, 0xCFFD, 0xB36F, 0xCFFE, 0xB370, 0xCFFF, 0xB371, 0xD000, 0xC4F6, 0xD001, 0xB372, 0xD002, 0xB373, 0xD003, 0xB374, + 0xD004, 0xC4F7, 0xD005, 0xB375, 0xD006, 0xB376, 0xD007, 0xB377, 0xD008, 0xB378, 0xD009, 0xB379, 0xD00A, 0xB37A, 0xD00B, 0xB381, + 0xD00C, 0xB382, 0xD00D, 0xB383, 0xD00E, 0xB384, 0xD00F, 0xB385, 0xD010, 0xB386, 0xD011, 0xC4F8, 0xD012, 0xB387, 0xD013, 0xB388, + 0xD014, 0xB389, 0xD015, 0xB38A, 0xD016, 0xB38B, 0xD017, 0xB38C, 0xD018, 0xC4F9, 0xD019, 0xB38D, 0xD01A, 0xB38E, 0xD01B, 0xB38F, + 0xD01C, 0xB390, 0xD01D, 0xB391, 0xD01E, 0xB392, 0xD01F, 0xB393, 0xD020, 0xB394, 0xD021, 0xB395, 0xD022, 0xB396, 0xD023, 0xB397, + 0xD024, 0xB398, 0xD025, 0xB399, 0xD026, 0xB39A, 0xD027, 0xB39B, 0xD028, 0xB39C, 0xD029, 0xB39D, 0xD02A, 0xB39E, 0xD02B, 0xB39F, + 0xD02C, 0xB3A0, 0xD02D, 0xC4FA, 0xD02E, 0xB441, 0xD02F, 0xB442, 0xD030, 0xB443, 0xD031, 0xB444, 0xD032, 0xB445, 0xD033, 0xB446, + 0xD034, 0xC4FB, 0xD035, 0xC4FC, 0xD036, 0xB447, 0xD037, 0xB448, 0xD038, 0xC4FD, 0xD039, 0xB449, 0xD03A, 0xB44A, 0xD03B, 0xB44B, + 0xD03C, 0xC4FE, 0xD03D, 0xB44C, 0xD03E, 0xB44D, 0xD03F, 0xB44E, 0xD040, 0xB44F, 0xD041, 0xB450, 0xD042, 0xB451, 0xD043, 0xB452, + 0xD044, 0xC5A1, 0xD045, 0xC5A2, 0xD046, 0xB453, 0xD047, 0xC5A3, 0xD048, 0xB454, 0xD049, 0xC5A4, 0xD04A, 0xB455, 0xD04B, 0xB456, + 0xD04C, 0xB457, 0xD04D, 0xB458, 0xD04E, 0xB459, 0xD04F, 0xB45A, 0xD050, 0xC5A5, 0xD051, 0xB461, 0xD052, 0xB462, 0xD053, 0xB463, + 0xD054, 0xC5A6, 0xD055, 0xB464, 0xD056, 0xB465, 0xD057, 0xB466, 0xD058, 0xC5A7, 0xD059, 0xB467, 0xD05A, 0xB468, 0xD05B, 0xB469, + 0xD05C, 0xB46A, 0xD05D, 0xB46B, 0xD05E, 0xB46C, 0xD05F, 0xB46D, 0xD060, 0xC5A8, 0xD061, 0xB46E, 0xD062, 0xB46F, 0xD063, 0xB470, + 0xD064, 0xB471, 0xD065, 0xB472, 0xD066, 0xB473, 0xD067, 0xB474, 0xD068, 0xB475, 0xD069, 0xB476, 0xD06A, 0xB477, 0xD06B, 0xB478, + 0xD06C, 0xC5A9, 0xD06D, 0xC5AA, 0xD06E, 0xB479, 0xD06F, 0xB47A, 0xD070, 0xC5AB, 0xD071, 0xB481, 0xD072, 0xB482, 0xD073, 0xB483, + 0xD074, 0xC5AC, 0xD075, 0xB484, 0xD076, 0xB485, 0xD077, 0xB486, 0xD078, 0xB487, 0xD079, 0xB488, 0xD07A, 0xB489, 0xD07B, 0xB48A, + 0xD07C, 0xC5AD, 0xD07D, 0xC5AE, 0xD07E, 0xB48B, 0xD07F, 0xB48C, 0xD080, 0xB48D, 0xD081, 0xC5AF, 0xD082, 0xB48E, 0xD083, 0xB48F, + 0xD084, 0xB490, 0xD085, 0xB491, 0xD086, 0xB492, 0xD087, 0xB493, 0xD088, 0xB494, 0xD089, 0xB495, 0xD08A, 0xB496, 0xD08B, 0xB497, + 0xD08C, 0xB498, 0xD08D, 0xB499, 0xD08E, 0xB49A, 0xD08F, 0xB49B, 0xD090, 0xB49C, 0xD091, 0xB49D, 0xD092, 0xB49E, 0xD093, 0xB49F, + 0xD094, 0xB4A0, 0xD095, 0xB541, 0xD096, 0xB542, 0xD097, 0xB543, 0xD098, 0xB544, 0xD099, 0xB545, 0xD09A, 0xB546, 0xD09B, 0xB547, + 0xD09C, 0xB548, 0xD09D, 0xB549, 0xD09E, 0xB54A, 0xD09F, 0xB54B, 0xD0A0, 0xB54C, 0xD0A1, 0xB54D, 0xD0A2, 0xB54E, 0xD0A3, 0xB54F, + 0xD0A4, 0xC5B0, 0xD0A5, 0xC5B1, 0xD0A6, 0xB550, 0xD0A7, 0xB551, 0xD0A8, 0xC5B2, 0xD0A9, 0xB552, 0xD0AA, 0xB553, 0xD0AB, 0xB554, + 0xD0AC, 0xC5B3, 0xD0AD, 0xB555, 0xD0AE, 0xB556, 0xD0AF, 0xB557, 0xD0B0, 0xB558, 0xD0B1, 0xB559, 0xD0B2, 0xB55A, 0xD0B3, 0xB561, + 0xD0B4, 0xC5B4, 0xD0B5, 0xC5B5, 0xD0B6, 0xB562, 0xD0B7, 0xC5B6, 0xD0B8, 0xB563, 0xD0B9, 0xC5B7, 0xD0BA, 0xB564, 0xD0BB, 0xB565, + 0xD0BC, 0xB566, 0xD0BD, 0xB567, 0xD0BE, 0xB568, 0xD0BF, 0xB569, 0xD0C0, 0xC5B8, 0xD0C1, 0xC5B9, 0xD0C2, 0xB56A, 0xD0C3, 0xB56B, + 0xD0C4, 0xC5BA, 0xD0C5, 0xB56C, 0xD0C6, 0xB56D, 0xD0C7, 0xB56E, 0xD0C8, 0xC5BB, 0xD0C9, 0xC5BC, 0xD0CA, 0xB56F, 0xD0CB, 0xB570, + 0xD0CC, 0xB571, 0xD0CD, 0xB572, 0xD0CE, 0xB573, 0xD0CF, 0xB574, 0xD0D0, 0xC5BD, 0xD0D1, 0xC5BE, 0xD0D2, 0xB575, 0xD0D3, 0xC5BF, + 0xD0D4, 0xC5C0, 0xD0D5, 0xC5C1, 0xD0D6, 0xB576, 0xD0D7, 0xB577, 0xD0D8, 0xB578, 0xD0D9, 0xB579, 0xD0DA, 0xB57A, 0xD0DB, 0xB581, + 0xD0DC, 0xC5C2, 0xD0DD, 0xC5C3, 0xD0DE, 0xB582, 0xD0DF, 0xB583, 0xD0E0, 0xC5C4, 0xD0E1, 0xB584, 0xD0E2, 0xB585, 0xD0E3, 0xB586, + 0xD0E4, 0xC5C5, 0xD0E5, 0xB587, 0xD0E6, 0xB588, 0xD0E7, 0xB589, 0xD0E8, 0xB58A, 0xD0E9, 0xB58B, 0xD0EA, 0xB58C, 0xD0EB, 0xB58D, + 0xD0EC, 0xC5C6, 0xD0ED, 0xC5C7, 0xD0EE, 0xB58E, 0xD0EF, 0xC5C8, 0xD0F0, 0xC5C9, 0xD0F1, 0xC5CA, 0xD0F2, 0xB58F, 0xD0F3, 0xB590, + 0xD0F4, 0xB591, 0xD0F5, 0xB592, 0xD0F6, 0xB593, 0xD0F7, 0xB594, 0xD0F8, 0xC5CB, 0xD0F9, 0xB595, 0xD0FA, 0xB596, 0xD0FB, 0xB597, + 0xD0FC, 0xB598, 0xD0FD, 0xB599, 0xD0FE, 0xB59A, 0xD0FF, 0xB59B, 0xD100, 0xB59C, 0xD101, 0xB59D, 0xD102, 0xB59E, 0xD103, 0xB59F, + 0xD104, 0xB5A0, 0xD105, 0xB641, 0xD106, 0xB642, 0xD107, 0xB643, 0xD108, 0xB644, 0xD109, 0xB645, 0xD10A, 0xB646, 0xD10B, 0xB647, + 0xD10C, 0xB648, 0xD10D, 0xC5CC, 0xD10E, 0xB649, 0xD10F, 0xB64A, 0xD110, 0xB64B, 0xD111, 0xB64C, 0xD112, 0xB64D, 0xD113, 0xB64E, + 0xD114, 0xB64F, 0xD115, 0xB650, 0xD116, 0xB651, 0xD117, 0xB652, 0xD118, 0xB653, 0xD119, 0xB654, 0xD11A, 0xB655, 0xD11B, 0xB656, + 0xD11C, 0xB657, 0xD11D, 0xB658, 0xD11E, 0xB659, 0xD11F, 0xB65A, 0xD120, 0xB661, 0xD121, 0xB662, 0xD122, 0xB663, 0xD123, 0xB664, + 0xD124, 0xB665, 0xD125, 0xB666, 0xD126, 0xB667, 0xD127, 0xB668, 0xD128, 0xB669, 0xD129, 0xB66A, 0xD12A, 0xB66B, 0xD12B, 0xB66C, + 0xD12C, 0xB66D, 0xD12D, 0xB66E, 0xD12E, 0xB66F, 0xD12F, 0xB670, 0xD130, 0xC5CD, 0xD131, 0xC5CE, 0xD132, 0xB671, 0xD133, 0xB672, + 0xD134, 0xC5CF, 0xD135, 0xB673, 0xD136, 0xB674, 0xD137, 0xB675, 0xD138, 0xC5D0, 0xD139, 0xB676, 0xD13A, 0xC5D1, 0xD13B, 0xB677, + 0xD13C, 0xB678, 0xD13D, 0xB679, 0xD13E, 0xB67A, 0xD13F, 0xB681, 0xD140, 0xC5D2, 0xD141, 0xC5D3, 0xD142, 0xB682, 0xD143, 0xC5D4, + 0xD144, 0xC5D5, 0xD145, 0xC5D6, 0xD146, 0xB683, 0xD147, 0xB684, 0xD148, 0xB685, 0xD149, 0xB686, 0xD14A, 0xB687, 0xD14B, 0xB688, + 0xD14C, 0xC5D7, 0xD14D, 0xC5D8, 0xD14E, 0xB689, 0xD14F, 0xB68A, 0xD150, 0xC5D9, 0xD151, 0xB68B, 0xD152, 0xB68C, 0xD153, 0xB68D, + 0xD154, 0xC5DA, 0xD155, 0xB68E, 0xD156, 0xB68F, 0xD157, 0xB690, 0xD158, 0xB691, 0xD159, 0xB692, 0xD15A, 0xB693, 0xD15B, 0xB694, + 0xD15C, 0xC5DB, 0xD15D, 0xC5DC, 0xD15E, 0xB695, 0xD15F, 0xC5DD, 0xD160, 0xB696, 0xD161, 0xC5DE, 0xD162, 0xB697, 0xD163, 0xB698, + 0xD164, 0xB699, 0xD165, 0xB69A, 0xD166, 0xB69B, 0xD167, 0xB69C, 0xD168, 0xC5DF, 0xD169, 0xB69D, 0xD16A, 0xB69E, 0xD16B, 0xB69F, + 0xD16C, 0xC5E0, 0xD16D, 0xB6A0, 0xD16E, 0xB741, 0xD16F, 0xB742, 0xD170, 0xB743, 0xD171, 0xB744, 0xD172, 0xB745, 0xD173, 0xB746, + 0xD174, 0xB747, 0xD175, 0xB748, 0xD176, 0xB749, 0xD177, 0xB74A, 0xD178, 0xB74B, 0xD179, 0xB74C, 0xD17A, 0xB74D, 0xD17B, 0xB74E, + 0xD17C, 0xC5E1, 0xD17D, 0xB74F, 0xD17E, 0xB750, 0xD17F, 0xB751, 0xD180, 0xB752, 0xD181, 0xB753, 0xD182, 0xB754, 0xD183, 0xB755, + 0xD184, 0xC5E2, 0xD185, 0xB756, 0xD186, 0xB757, 0xD187, 0xB758, 0xD188, 0xC5E3, 0xD189, 0xB759, 0xD18A, 0xB75A, 0xD18B, 0xB761, + 0xD18C, 0xB762, 0xD18D, 0xB763, 0xD18E, 0xB764, 0xD18F, 0xB765, 0xD190, 0xB766, 0xD191, 0xB767, 0xD192, 0xB768, 0xD193, 0xB769, + 0xD194, 0xB76A, 0xD195, 0xB76B, 0xD196, 0xB76C, 0xD197, 0xB76D, 0xD198, 0xB76E, 0xD199, 0xB76F, 0xD19A, 0xB770, 0xD19B, 0xB771, + 0xD19C, 0xB772, 0xD19D, 0xB773, 0xD19E, 0xB774, 0xD19F, 0xB775, 0xD1A0, 0xC5E4, 0xD1A1, 0xC5E5, 0xD1A2, 0xB776, 0xD1A3, 0xB777, + 0xD1A4, 0xC5E6, 0xD1A5, 0xB778, 0xD1A6, 0xB779, 0xD1A7, 0xB77A, 0xD1A8, 0xC5E7, 0xD1A9, 0xB781, 0xD1AA, 0xB782, 0xD1AB, 0xB783, + 0xD1AC, 0xB784, 0xD1AD, 0xB785, 0xD1AE, 0xB786, 0xD1AF, 0xB787, 0xD1B0, 0xC5E8, 0xD1B1, 0xC5E9, 0xD1B2, 0xB788, 0xD1B3, 0xC5EA, + 0xD1B4, 0xB789, 0xD1B5, 0xC5EB, 0xD1B6, 0xB78A, 0xD1B7, 0xB78B, 0xD1B8, 0xB78C, 0xD1B9, 0xB78D, 0xD1BA, 0xC5EC, 0xD1BB, 0xB78E, + 0xD1BC, 0xC5ED, 0xD1BD, 0xB78F, 0xD1BE, 0xB790, 0xD1BF, 0xB791, 0xD1C0, 0xC5EE, 0xD1C1, 0xB792, 0xD1C2, 0xB793, 0xD1C3, 0xB794, + 0xD1C4, 0xB795, 0xD1C5, 0xB796, 0xD1C6, 0xB797, 0xD1C7, 0xB798, 0xD1C8, 0xB799, 0xD1C9, 0xB79A, 0xD1CA, 0xB79B, 0xD1CB, 0xB79C, + 0xD1CC, 0xB79D, 0xD1CD, 0xB79E, 0xD1CE, 0xB79F, 0xD1CF, 0xB7A0, 0xD1D0, 0xB841, 0xD1D1, 0xB842, 0xD1D2, 0xB843, 0xD1D3, 0xB844, + 0xD1D4, 0xB845, 0xD1D5, 0xB846, 0xD1D6, 0xB847, 0xD1D7, 0xB848, 0xD1D8, 0xC5EF, 0xD1D9, 0xB849, 0xD1DA, 0xB84A, 0xD1DB, 0xB84B, + 0xD1DC, 0xB84C, 0xD1DD, 0xB84D, 0xD1DE, 0xB84E, 0xD1DF, 0xB84F, 0xD1E0, 0xB850, 0xD1E1, 0xB851, 0xD1E2, 0xB852, 0xD1E3, 0xB853, + 0xD1E4, 0xB854, 0xD1E5, 0xB855, 0xD1E6, 0xB856, 0xD1E7, 0xB857, 0xD1E8, 0xB858, 0xD1E9, 0xB859, 0xD1EA, 0xB85A, 0xD1EB, 0xB861, + 0xD1EC, 0xB862, 0xD1ED, 0xB863, 0xD1EE, 0xB864, 0xD1EF, 0xB865, 0xD1F0, 0xB866, 0xD1F1, 0xB867, 0xD1F2, 0xB868, 0xD1F3, 0xB869, + 0xD1F4, 0xC5F0, 0xD1F5, 0xB86A, 0xD1F6, 0xB86B, 0xD1F7, 0xB86C, 0xD1F8, 0xC5F1, 0xD1F9, 0xB86D, 0xD1FA, 0xB86E, 0xD1FB, 0xB86F, + 0xD1FC, 0xB870, 0xD1FD, 0xB871, 0xD1FE, 0xB872, 0xD1FF, 0xB873, 0xD200, 0xB874, 0xD201, 0xB875, 0xD202, 0xB876, 0xD203, 0xB877, + 0xD204, 0xB878, 0xD205, 0xB879, 0xD206, 0xB87A, 0xD207, 0xC5F2, 0xD208, 0xB881, 0xD209, 0xC5F3, 0xD20A, 0xB882, 0xD20B, 0xB883, + 0xD20C, 0xB884, 0xD20D, 0xB885, 0xD20E, 0xB886, 0xD20F, 0xB887, 0xD210, 0xC5F4, 0xD211, 0xB888, 0xD212, 0xB889, 0xD213, 0xB88A, + 0xD214, 0xB88B, 0xD215, 0xB88C, 0xD216, 0xB88D, 0xD217, 0xB88E, 0xD218, 0xB88F, 0xD219, 0xB890, 0xD21A, 0xB891, 0xD21B, 0xB892, + 0xD21C, 0xB893, 0xD21D, 0xB894, 0xD21E, 0xB895, 0xD21F, 0xB896, 0xD220, 0xB897, 0xD221, 0xB898, 0xD222, 0xB899, 0xD223, 0xB89A, + 0xD224, 0xB89B, 0xD225, 0xB89C, 0xD226, 0xB89D, 0xD227, 0xB89E, 0xD228, 0xB89F, 0xD229, 0xB8A0, 0xD22A, 0xB941, 0xD22B, 0xB942, + 0xD22C, 0xC5F5, 0xD22D, 0xC5F6, 0xD22E, 0xB943, 0xD22F, 0xB944, 0xD230, 0xC5F7, 0xD231, 0xB945, 0xD232, 0xB946, 0xD233, 0xB947, + 0xD234, 0xC5F8, 0xD235, 0xB948, 0xD236, 0xB949, 0xD237, 0xB94A, 0xD238, 0xB94B, 0xD239, 0xB94C, 0xD23A, 0xB94D, 0xD23B, 0xB94E, + 0xD23C, 0xC5F9, 0xD23D, 0xC5FA, 0xD23E, 0xB94F, 0xD23F, 0xC5FB, 0xD240, 0xB950, 0xD241, 0xC5FC, 0xD242, 0xB951, 0xD243, 0xB952, + 0xD244, 0xB953, 0xD245, 0xB954, 0xD246, 0xB955, 0xD247, 0xB956, 0xD248, 0xC5FD, 0xD249, 0xB957, 0xD24A, 0xB958, 0xD24B, 0xB959, + 0xD24C, 0xB95A, 0xD24D, 0xB961, 0xD24E, 0xB962, 0xD24F, 0xB963, 0xD250, 0xB964, 0xD251, 0xB965, 0xD252, 0xB966, 0xD253, 0xB967, + 0xD254, 0xB968, 0xD255, 0xB969, 0xD256, 0xB96A, 0xD257, 0xB96B, 0xD258, 0xB96C, 0xD259, 0xB96D, 0xD25A, 0xB96E, 0xD25B, 0xB96F, + 0xD25C, 0xC5FE, 0xD25D, 0xB970, 0xD25E, 0xB971, 0xD25F, 0xB972, 0xD260, 0xB973, 0xD261, 0xB974, 0xD262, 0xB975, 0xD263, 0xB976, + 0xD264, 0xC6A1, 0xD265, 0xB977, 0xD266, 0xB978, 0xD267, 0xB979, 0xD268, 0xB97A, 0xD269, 0xB981, 0xD26A, 0xB982, 0xD26B, 0xB983, + 0xD26C, 0xB984, 0xD26D, 0xB985, 0xD26E, 0xB986, 0xD26F, 0xB987, 0xD270, 0xB988, 0xD271, 0xB989, 0xD272, 0xB98A, 0xD273, 0xB98B, + 0xD274, 0xB98C, 0xD275, 0xB98D, 0xD276, 0xB98E, 0xD277, 0xB98F, 0xD278, 0xB990, 0xD279, 0xB991, 0xD27A, 0xB992, 0xD27B, 0xB993, + 0xD27C, 0xB994, 0xD27D, 0xB995, 0xD27E, 0xB996, 0xD27F, 0xB997, 0xD280, 0xC6A2, 0xD281, 0xC6A3, 0xD282, 0xB998, 0xD283, 0xB999, + 0xD284, 0xC6A4, 0xD285, 0xB99A, 0xD286, 0xB99B, 0xD287, 0xB99C, 0xD288, 0xC6A5, 0xD289, 0xB99D, 0xD28A, 0xB99E, 0xD28B, 0xB99F, + 0xD28C, 0xB9A0, 0xD28D, 0xBA41, 0xD28E, 0xBA42, 0xD28F, 0xBA43, 0xD290, 0xC6A6, 0xD291, 0xC6A7, 0xD292, 0xBA44, 0xD293, 0xBA45, + 0xD294, 0xBA46, 0xD295, 0xC6A8, 0xD296, 0xBA47, 0xD297, 0xBA48, 0xD298, 0xBA49, 0xD299, 0xBA4A, 0xD29A, 0xBA4B, 0xD29B, 0xBA4C, + 0xD29C, 0xC6A9, 0xD29D, 0xBA4D, 0xD29E, 0xBA4E, 0xD29F, 0xBA4F, 0xD2A0, 0xC6AA, 0xD2A1, 0xBA50, 0xD2A2, 0xBA51, 0xD2A3, 0xBA52, + 0xD2A4, 0xC6AB, 0xD2A5, 0xBA53, 0xD2A6, 0xBA54, 0xD2A7, 0xBA55, 0xD2A8, 0xBA56, 0xD2A9, 0xBA57, 0xD2AA, 0xBA58, 0xD2AB, 0xBA59, + 0xD2AC, 0xC6AC, 0xD2AD, 0xBA5A, 0xD2AE, 0xBA61, 0xD2AF, 0xBA62, 0xD2B0, 0xBA63, 0xD2B1, 0xC6AD, 0xD2B2, 0xBA64, 0xD2B3, 0xBA65, + 0xD2B4, 0xBA66, 0xD2B5, 0xBA67, 0xD2B6, 0xBA68, 0xD2B7, 0xBA69, 0xD2B8, 0xC6AE, 0xD2B9, 0xC6AF, 0xD2BA, 0xBA6A, 0xD2BB, 0xBA6B, + 0xD2BC, 0xC6B0, 0xD2BD, 0xBA6C, 0xD2BE, 0xBA6D, 0xD2BF, 0xC6B1, 0xD2C0, 0xC6B2, 0xD2C1, 0xBA6E, 0xD2C2, 0xC6B3, 0xD2C3, 0xBA6F, + 0xD2C4, 0xBA70, 0xD2C5, 0xBA71, 0xD2C6, 0xBA72, 0xD2C7, 0xBA73, 0xD2C8, 0xC6B4, 0xD2C9, 0xC6B5, 0xD2CA, 0xBA74, 0xD2CB, 0xC6B6, + 0xD2CC, 0xBA75, 0xD2CD, 0xBA76, 0xD2CE, 0xBA77, 0xD2CF, 0xBA78, 0xD2D0, 0xBA79, 0xD2D1, 0xBA7A, 0xD2D2, 0xBA81, 0xD2D3, 0xBA82, + 0xD2D4, 0xC6B7, 0xD2D5, 0xBA83, 0xD2D6, 0xBA84, 0xD2D7, 0xBA85, 0xD2D8, 0xC6B8, 0xD2D9, 0xBA86, 0xD2DA, 0xBA87, 0xD2DB, 0xBA88, + 0xD2DC, 0xC6B9, 0xD2DD, 0xBA89, 0xD2DE, 0xBA8A, 0xD2DF, 0xBA8B, 0xD2E0, 0xBA8C, 0xD2E1, 0xBA8D, 0xD2E2, 0xBA8E, 0xD2E3, 0xBA8F, + 0xD2E4, 0xC6BA, 0xD2E5, 0xC6BB, 0xD2E6, 0xBA90, 0xD2E7, 0xBA91, 0xD2E8, 0xBA92, 0xD2E9, 0xBA93, 0xD2EA, 0xBA94, 0xD2EB, 0xBA95, + 0xD2EC, 0xBA96, 0xD2ED, 0xBA97, 0xD2EE, 0xBA98, 0xD2EF, 0xBA99, 0xD2F0, 0xC6BC, 0xD2F1, 0xC6BD, 0xD2F2, 0xBA9A, 0xD2F3, 0xBA9B, + 0xD2F4, 0xC6BE, 0xD2F5, 0xBA9C, 0xD2F6, 0xBA9D, 0xD2F7, 0xBA9E, 0xD2F8, 0xC6BF, 0xD2F9, 0xBA9F, 0xD2FA, 0xBAA0, 0xD2FB, 0xBB41, + 0xD2FC, 0xBB42, 0xD2FD, 0xBB43, 0xD2FE, 0xBB44, 0xD2FF, 0xBB45, 0xD300, 0xC6C0, 0xD301, 0xC6C1, 0xD302, 0xBB46, 0xD303, 0xC6C2, + 0xD304, 0xBB47, 0xD305, 0xC6C3, 0xD306, 0xBB48, 0xD307, 0xBB49, 0xD308, 0xBB4A, 0xD309, 0xBB4B, 0xD30A, 0xBB4C, 0xD30B, 0xBB4D, + 0xD30C, 0xC6C4, 0xD30D, 0xC6C5, 0xD30E, 0xC6C6, 0xD30F, 0xBB4E, 0xD310, 0xC6C7, 0xD311, 0xBB4F, 0xD312, 0xBB50, 0xD313, 0xBB51, + 0xD314, 0xC6C8, 0xD315, 0xBB52, 0xD316, 0xC6C9, 0xD317, 0xBB53, 0xD318, 0xBB54, 0xD319, 0xBB55, 0xD31A, 0xBB56, 0xD31B, 0xBB57, + 0xD31C, 0xC6CA, 0xD31D, 0xC6CB, 0xD31E, 0xBB58, 0xD31F, 0xC6CC, 0xD320, 0xC6CD, 0xD321, 0xC6CE, 0xD322, 0xBB59, 0xD323, 0xBB5A, + 0xD324, 0xBB61, 0xD325, 0xC6CF, 0xD326, 0xBB62, 0xD327, 0xBB63, 0xD328, 0xC6D0, 0xD329, 0xC6D1, 0xD32A, 0xBB64, 0xD32B, 0xBB65, + 0xD32C, 0xC6D2, 0xD32D, 0xBB66, 0xD32E, 0xBB67, 0xD32F, 0xBB68, 0xD330, 0xC6D3, 0xD331, 0xBB69, 0xD332, 0xBB6A, 0xD333, 0xBB6B, + 0xD334, 0xBB6C, 0xD335, 0xBB6D, 0xD336, 0xBB6E, 0xD337, 0xBB6F, 0xD338, 0xC6D4, 0xD339, 0xC6D5, 0xD33A, 0xBB70, 0xD33B, 0xC6D6, + 0xD33C, 0xC6D7, 0xD33D, 0xC6D8, 0xD33E, 0xBB71, 0xD33F, 0xBB72, 0xD340, 0xBB73, 0xD341, 0xBB74, 0xD342, 0xBB75, 0xD343, 0xBB76, + 0xD344, 0xC6D9, 0xD345, 0xC6DA, 0xD346, 0xBB77, 0xD347, 0xBB78, 0xD348, 0xBB79, 0xD349, 0xBB7A, 0xD34A, 0xBB81, 0xD34B, 0xBB82, + 0xD34C, 0xBB83, 0xD34D, 0xBB84, 0xD34E, 0xBB85, 0xD34F, 0xBB86, 0xD350, 0xBB87, 0xD351, 0xBB88, 0xD352, 0xBB89, 0xD353, 0xBB8A, + 0xD354, 0xBB8B, 0xD355, 0xBB8C, 0xD356, 0xBB8D, 0xD357, 0xBB8E, 0xD358, 0xBB8F, 0xD359, 0xBB90, 0xD35A, 0xBB91, 0xD35B, 0xBB92, + 0xD35C, 0xBB93, 0xD35D, 0xBB94, 0xD35E, 0xBB95, 0xD35F, 0xBB96, 0xD360, 0xBB97, 0xD361, 0xBB98, 0xD362, 0xBB99, 0xD363, 0xBB9A, + 0xD364, 0xBB9B, 0xD365, 0xBB9C, 0xD366, 0xBB9D, 0xD367, 0xBB9E, 0xD368, 0xBB9F, 0xD369, 0xBBA0, 0xD36A, 0xBC41, 0xD36B, 0xBC42, + 0xD36C, 0xBC43, 0xD36D, 0xBC44, 0xD36E, 0xBC45, 0xD36F, 0xBC46, 0xD370, 0xBC47, 0xD371, 0xBC48, 0xD372, 0xBC49, 0xD373, 0xBC4A, + 0xD374, 0xBC4B, 0xD375, 0xBC4C, 0xD376, 0xBC4D, 0xD377, 0xBC4E, 0xD378, 0xBC4F, 0xD379, 0xBC50, 0xD37A, 0xBC51, 0xD37B, 0xBC52, + 0xD37C, 0xC6DB, 0xD37D, 0xC6DC, 0xD37E, 0xBC53, 0xD37F, 0xBC54, 0xD380, 0xC6DD, 0xD381, 0xBC55, 0xD382, 0xBC56, 0xD383, 0xBC57, + 0xD384, 0xC6DE, 0xD385, 0xBC58, 0xD386, 0xBC59, 0xD387, 0xBC5A, 0xD388, 0xBC61, 0xD389, 0xBC62, 0xD38A, 0xBC63, 0xD38B, 0xBC64, + 0xD38C, 0xC6DF, 0xD38D, 0xC6E0, 0xD38E, 0xBC65, 0xD38F, 0xC6E1, 0xD390, 0xC6E2, 0xD391, 0xC6E3, 0xD392, 0xBC66, 0xD393, 0xBC67, + 0xD394, 0xBC68, 0xD395, 0xBC69, 0xD396, 0xBC6A, 0xD397, 0xBC6B, 0xD398, 0xC6E4, 0xD399, 0xC6E5, 0xD39A, 0xBC6C, 0xD39B, 0xBC6D, + 0xD39C, 0xC6E6, 0xD39D, 0xBC6E, 0xD39E, 0xBC6F, 0xD39F, 0xBC70, 0xD3A0, 0xC6E7, 0xD3A1, 0xBC71, 0xD3A2, 0xBC72, 0xD3A3, 0xBC73, + 0xD3A4, 0xBC74, 0xD3A5, 0xBC75, 0xD3A6, 0xBC76, 0xD3A7, 0xBC77, 0xD3A8, 0xC6E8, 0xD3A9, 0xC6E9, 0xD3AA, 0xBC78, 0xD3AB, 0xC6EA, + 0xD3AC, 0xBC79, 0xD3AD, 0xC6EB, 0xD3AE, 0xBC7A, 0xD3AF, 0xBC81, 0xD3B0, 0xBC82, 0xD3B1, 0xBC83, 0xD3B2, 0xBC84, 0xD3B3, 0xBC85, + 0xD3B4, 0xC6EC, 0xD3B5, 0xBC86, 0xD3B6, 0xBC87, 0xD3B7, 0xBC88, 0xD3B8, 0xC6ED, 0xD3B9, 0xBC89, 0xD3BA, 0xBC8A, 0xD3BB, 0xBC8B, + 0xD3BC, 0xC6EE, 0xD3BD, 0xBC8C, 0xD3BE, 0xBC8D, 0xD3BF, 0xBC8E, 0xD3C0, 0xBC8F, 0xD3C1, 0xBC90, 0xD3C2, 0xBC91, 0xD3C3, 0xBC92, + 0xD3C4, 0xC6EF, 0xD3C5, 0xC6F0, 0xD3C6, 0xBC93, 0xD3C7, 0xBC94, 0xD3C8, 0xC6F1, 0xD3C9, 0xC6F2, 0xD3CA, 0xBC95, 0xD3CB, 0xBC96, + 0xD3CC, 0xBC97, 0xD3CD, 0xBC98, 0xD3CE, 0xBC99, 0xD3CF, 0xBC9A, 0xD3D0, 0xC6F3, 0xD3D1, 0xBC9B, 0xD3D2, 0xBC9C, 0xD3D3, 0xBC9D, + 0xD3D4, 0xBC9E, 0xD3D5, 0xBC9F, 0xD3D6, 0xBCA0, 0xD3D7, 0xBD41, 0xD3D8, 0xC6F4, 0xD3D9, 0xBD42, 0xD3DA, 0xBD43, 0xD3DB, 0xBD44, + 0xD3DC, 0xBD45, 0xD3DD, 0xBD46, 0xD3DE, 0xBD47, 0xD3DF, 0xBD48, 0xD3E0, 0xBD49, 0xD3E1, 0xC6F5, 0xD3E2, 0xBD4A, 0xD3E3, 0xC6F6, + 0xD3E4, 0xBD4B, 0xD3E5, 0xBD4C, 0xD3E6, 0xBD4D, 0xD3E7, 0xBD4E, 0xD3E8, 0xBD4F, 0xD3E9, 0xBD50, 0xD3EA, 0xBD51, 0xD3EB, 0xBD52, + 0xD3EC, 0xC6F7, 0xD3ED, 0xC6F8, 0xD3EE, 0xBD53, 0xD3EF, 0xBD54, 0xD3F0, 0xC6F9, 0xD3F1, 0xBD55, 0xD3F2, 0xBD56, 0xD3F3, 0xBD57, + 0xD3F4, 0xC6FA, 0xD3F5, 0xBD58, 0xD3F6, 0xBD59, 0xD3F7, 0xBD5A, 0xD3F8, 0xBD61, 0xD3F9, 0xBD62, 0xD3FA, 0xBD63, 0xD3FB, 0xBD64, + 0xD3FC, 0xC6FB, 0xD3FD, 0xC6FC, 0xD3FE, 0xBD65, 0xD3FF, 0xC6FD, 0xD400, 0xBD66, 0xD401, 0xC6FE, 0xD402, 0xBD67, 0xD403, 0xBD68, + 0xD404, 0xBD69, 0xD405, 0xBD6A, 0xD406, 0xBD6B, 0xD407, 0xBD6C, 0xD408, 0xC7A1, 0xD409, 0xBD6D, 0xD40A, 0xBD6E, 0xD40B, 0xBD6F, + 0xD40C, 0xBD70, 0xD40D, 0xBD71, 0xD40E, 0xBD72, 0xD40F, 0xBD73, 0xD410, 0xBD74, 0xD411, 0xBD75, 0xD412, 0xBD76, 0xD413, 0xBD77, + 0xD414, 0xBD78, 0xD415, 0xBD79, 0xD416, 0xBD7A, 0xD417, 0xBD81, 0xD418, 0xBD82, 0xD419, 0xBD83, 0xD41A, 0xBD84, 0xD41B, 0xBD85, + 0xD41C, 0xBD86, 0xD41D, 0xC7A2, 0xD41E, 0xBD87, 0xD41F, 0xBD88, 0xD420, 0xBD89, 0xD421, 0xBD8A, 0xD422, 0xBD8B, 0xD423, 0xBD8C, + 0xD424, 0xBD8D, 0xD425, 0xBD8E, 0xD426, 0xBD8F, 0xD427, 0xBD90, 0xD428, 0xBD91, 0xD429, 0xBD92, 0xD42A, 0xBD93, 0xD42B, 0xBD94, + 0xD42C, 0xBD95, 0xD42D, 0xBD96, 0xD42E, 0xBD97, 0xD42F, 0xBD98, 0xD430, 0xBD99, 0xD431, 0xBD9A, 0xD432, 0xBD9B, 0xD433, 0xBD9C, + 0xD434, 0xBD9D, 0xD435, 0xBD9E, 0xD436, 0xBD9F, 0xD437, 0xBDA0, 0xD438, 0xBE41, 0xD439, 0xBE42, 0xD43A, 0xBE43, 0xD43B, 0xBE44, + 0xD43C, 0xBE45, 0xD43D, 0xBE46, 0xD43E, 0xBE47, 0xD43F, 0xBE48, 0xD440, 0xC7A3, 0xD441, 0xBE49, 0xD442, 0xBE4A, 0xD443, 0xBE4B, + 0xD444, 0xC7A4, 0xD445, 0xBE4C, 0xD446, 0xBE4D, 0xD447, 0xBE4E, 0xD448, 0xBE4F, 0xD449, 0xBE50, 0xD44A, 0xBE51, 0xD44B, 0xBE52, + 0xD44C, 0xBE53, 0xD44D, 0xBE54, 0xD44E, 0xBE55, 0xD44F, 0xBE56, 0xD450, 0xBE57, 0xD451, 0xBE58, 0xD452, 0xBE59, 0xD453, 0xBE5A, + 0xD454, 0xBE61, 0xD455, 0xBE62, 0xD456, 0xBE63, 0xD457, 0xBE64, 0xD458, 0xBE65, 0xD459, 0xBE66, 0xD45A, 0xBE67, 0xD45B, 0xBE68, + 0xD45C, 0xC7A5, 0xD45D, 0xBE69, 0xD45E, 0xBE6A, 0xD45F, 0xBE6B, 0xD460, 0xC7A6, 0xD461, 0xBE6C, 0xD462, 0xBE6D, 0xD463, 0xBE6E, + 0xD464, 0xC7A7, 0xD465, 0xBE6F, 0xD466, 0xBE70, 0xD467, 0xBE71, 0xD468, 0xBE72, 0xD469, 0xBE73, 0xD46A, 0xBE74, 0xD46B, 0xBE75, + 0xD46C, 0xBE76, 0xD46D, 0xC7A8, 0xD46E, 0xBE77, 0xD46F, 0xC7A9, 0xD470, 0xBE78, 0xD471, 0xBE79, 0xD472, 0xBE7A, 0xD473, 0xBE81, + 0xD474, 0xBE82, 0xD475, 0xBE83, 0xD476, 0xBE84, 0xD477, 0xBE85, 0xD478, 0xC7AA, 0xD479, 0xC7AB, 0xD47A, 0xBE86, 0xD47B, 0xBE87, + 0xD47C, 0xC7AC, 0xD47D, 0xBE88, 0xD47E, 0xBE89, 0xD47F, 0xC7AD, 0xD480, 0xC7AE, 0xD481, 0xBE8A, 0xD482, 0xC7AF, 0xD483, 0xBE8B, + 0xD484, 0xBE8C, 0xD485, 0xBE8D, 0xD486, 0xBE8E, 0xD487, 0xBE8F, 0xD488, 0xC7B0, 0xD489, 0xC7B1, 0xD48A, 0xBE90, 0xD48B, 0xC7B2, + 0xD48C, 0xBE91, 0xD48D, 0xC7B3, 0xD48E, 0xBE92, 0xD48F, 0xBE93, 0xD490, 0xBE94, 0xD491, 0xBE95, 0xD492, 0xBE96, 0xD493, 0xBE97, + 0xD494, 0xC7B4, 0xD495, 0xBE98, 0xD496, 0xBE99, 0xD497, 0xBE9A, 0xD498, 0xBE9B, 0xD499, 0xBE9C, 0xD49A, 0xBE9D, 0xD49B, 0xBE9E, + 0xD49C, 0xBE9F, 0xD49D, 0xBEA0, 0xD49E, 0xBF41, 0xD49F, 0xBF42, 0xD4A0, 0xBF43, 0xD4A1, 0xBF44, 0xD4A2, 0xBF45, 0xD4A3, 0xBF46, + 0xD4A4, 0xBF47, 0xD4A5, 0xBF48, 0xD4A6, 0xBF49, 0xD4A7, 0xBF4A, 0xD4A8, 0xBF4B, 0xD4A9, 0xC7B5, 0xD4AA, 0xBF4C, 0xD4AB, 0xBF4D, + 0xD4AC, 0xBF4E, 0xD4AD, 0xBF4F, 0xD4AE, 0xBF50, 0xD4AF, 0xBF51, 0xD4B0, 0xBF52, 0xD4B1, 0xBF53, 0xD4B2, 0xBF54, 0xD4B3, 0xBF55, + 0xD4B4, 0xBF56, 0xD4B5, 0xBF57, 0xD4B6, 0xBF58, 0xD4B7, 0xBF59, 0xD4B8, 0xBF5A, 0xD4B9, 0xBF61, 0xD4BA, 0xBF62, 0xD4BB, 0xBF63, + 0xD4BC, 0xBF64, 0xD4BD, 0xBF65, 0xD4BE, 0xBF66, 0xD4BF, 0xBF67, 0xD4C0, 0xBF68, 0xD4C1, 0xBF69, 0xD4C2, 0xBF6A, 0xD4C3, 0xBF6B, + 0xD4C4, 0xBF6C, 0xD4C5, 0xBF6D, 0xD4C6, 0xBF6E, 0xD4C7, 0xBF6F, 0xD4C8, 0xBF70, 0xD4C9, 0xBF71, 0xD4CA, 0xBF72, 0xD4CB, 0xBF73, + 0xD4CC, 0xC7B6, 0xD4CD, 0xBF74, 0xD4CE, 0xBF75, 0xD4CF, 0xBF76, 0xD4D0, 0xC7B7, 0xD4D1, 0xBF77, 0xD4D2, 0xBF78, 0xD4D3, 0xBF79, + 0xD4D4, 0xC7B8, 0xD4D5, 0xBF7A, 0xD4D6, 0xBF81, 0xD4D7, 0xBF82, 0xD4D8, 0xBF83, 0xD4D9, 0xBF84, 0xD4DA, 0xBF85, 0xD4DB, 0xBF86, + 0xD4DC, 0xC7B9, 0xD4DD, 0xBF87, 0xD4DE, 0xBF88, 0xD4DF, 0xC7BA, 0xD4E0, 0xBF89, 0xD4E1, 0xBF8A, 0xD4E2, 0xBF8B, 0xD4E3, 0xBF8C, + 0xD4E4, 0xBF8D, 0xD4E5, 0xBF8E, 0xD4E6, 0xBF8F, 0xD4E7, 0xBF90, 0xD4E8, 0xC7BB, 0xD4E9, 0xBF91, 0xD4EA, 0xBF92, 0xD4EB, 0xBF93, + 0xD4EC, 0xC7BC, 0xD4ED, 0xBF94, 0xD4EE, 0xBF95, 0xD4EF, 0xBF96, 0xD4F0, 0xC7BD, 0xD4F1, 0xBF97, 0xD4F2, 0xBF98, 0xD4F3, 0xBF99, + 0xD4F4, 0xBF9A, 0xD4F5, 0xBF9B, 0xD4F6, 0xBF9C, 0xD4F7, 0xBF9D, 0xD4F8, 0xC7BE, 0xD4F9, 0xBF9E, 0xD4FA, 0xBF9F, 0xD4FB, 0xC7BF, + 0xD4FC, 0xBFA0, 0xD4FD, 0xC7C0, 0xD4FE, 0xC041, 0xD4FF, 0xC042, 0xD500, 0xC043, 0xD501, 0xC044, 0xD502, 0xC045, 0xD503, 0xC046, + 0xD504, 0xC7C1, 0xD505, 0xC047, 0xD506, 0xC048, 0xD507, 0xC049, 0xD508, 0xC7C2, 0xD509, 0xC04A, 0xD50A, 0xC04B, 0xD50B, 0xC04C, + 0xD50C, 0xC7C3, 0xD50D, 0xC04D, 0xD50E, 0xC04E, 0xD50F, 0xC04F, 0xD510, 0xC050, 0xD511, 0xC051, 0xD512, 0xC052, 0xD513, 0xC053, + 0xD514, 0xC7C4, 0xD515, 0xC7C5, 0xD516, 0xC054, 0xD517, 0xC7C6, 0xD518, 0xC055, 0xD519, 0xC056, 0xD51A, 0xC057, 0xD51B, 0xC058, + 0xD51C, 0xC059, 0xD51D, 0xC05A, 0xD51E, 0xC061, 0xD51F, 0xC062, 0xD520, 0xC063, 0xD521, 0xC064, 0xD522, 0xC065, 0xD523, 0xC066, + 0xD524, 0xC067, 0xD525, 0xC068, 0xD526, 0xC069, 0xD527, 0xC06A, 0xD528, 0xC06B, 0xD529, 0xC06C, 0xD52A, 0xC06D, 0xD52B, 0xC06E, + 0xD52C, 0xC06F, 0xD52D, 0xC070, 0xD52E, 0xC071, 0xD52F, 0xC072, 0xD530, 0xC073, 0xD531, 0xC074, 0xD532, 0xC075, 0xD533, 0xC076, + 0xD534, 0xC077, 0xD535, 0xC078, 0xD536, 0xC079, 0xD537, 0xC07A, 0xD538, 0xC081, 0xD539, 0xC082, 0xD53A, 0xC083, 0xD53B, 0xC084, + 0xD53C, 0xC7C7, 0xD53D, 0xC7C8, 0xD53E, 0xC085, 0xD53F, 0xC086, 0xD540, 0xC7C9, 0xD541, 0xC087, 0xD542, 0xC088, 0xD543, 0xC089, + 0xD544, 0xC7CA, 0xD545, 0xC08A, 0xD546, 0xC08B, 0xD547, 0xC08C, 0xD548, 0xC08D, 0xD549, 0xC08E, 0xD54A, 0xC08F, 0xD54B, 0xC090, + 0xD54C, 0xC7CB, 0xD54D, 0xC7CC, 0xD54E, 0xC091, 0xD54F, 0xC7CD, 0xD550, 0xC092, 0xD551, 0xC7CE, 0xD552, 0xC093, 0xD553, 0xC094, + 0xD554, 0xC095, 0xD555, 0xC096, 0xD556, 0xC097, 0xD557, 0xC098, 0xD558, 0xC7CF, 0xD559, 0xC7D0, 0xD55A, 0xC099, 0xD55B, 0xC09A, + 0xD55C, 0xC7D1, 0xD55D, 0xC09B, 0xD55E, 0xC09C, 0xD55F, 0xC09D, 0xD560, 0xC7D2, 0xD561, 0xC09E, 0xD562, 0xC09F, 0xD563, 0xC0A0, + 0xD564, 0xC141, 0xD565, 0xC7D3, 0xD566, 0xC142, 0xD567, 0xC143, 0xD568, 0xC7D4, 0xD569, 0xC7D5, 0xD56A, 0xC144, 0xD56B, 0xC7D6, + 0xD56C, 0xC145, 0xD56D, 0xC7D7, 0xD56E, 0xC146, 0xD56F, 0xC147, 0xD570, 0xC148, 0xD571, 0xC149, 0xD572, 0xC14A, 0xD573, 0xC14B, + 0xD574, 0xC7D8, 0xD575, 0xC7D9, 0xD576, 0xC14C, 0xD577, 0xC14D, 0xD578, 0xC7DA, 0xD579, 0xC14E, 0xD57A, 0xC14F, 0xD57B, 0xC150, + 0xD57C, 0xC7DB, 0xD57D, 0xC151, 0xD57E, 0xC152, 0xD57F, 0xC153, 0xD580, 0xC154, 0xD581, 0xC155, 0xD582, 0xC156, 0xD583, 0xC157, + 0xD584, 0xC7DC, 0xD585, 0xC7DD, 0xD586, 0xC158, 0xD587, 0xC7DE, 0xD588, 0xC7DF, 0xD589, 0xC7E0, 0xD58A, 0xC159, 0xD58B, 0xC15A, + 0xD58C, 0xC161, 0xD58D, 0xC162, 0xD58E, 0xC163, 0xD58F, 0xC164, 0xD590, 0xC7E1, 0xD591, 0xC165, 0xD592, 0xC166, 0xD593, 0xC167, + 0xD594, 0xC168, 0xD595, 0xC169, 0xD596, 0xC16A, 0xD597, 0xC16B, 0xD598, 0xC16C, 0xD599, 0xC16D, 0xD59A, 0xC16E, 0xD59B, 0xC16F, + 0xD59C, 0xC170, 0xD59D, 0xC171, 0xD59E, 0xC172, 0xD59F, 0xC173, 0xD5A0, 0xC174, 0xD5A1, 0xC175, 0xD5A2, 0xC176, 0xD5A3, 0xC177, + 0xD5A4, 0xC178, 0xD5A5, 0xC7E2, 0xD5A6, 0xC179, 0xD5A7, 0xC17A, 0xD5A8, 0xC181, 0xD5A9, 0xC182, 0xD5AA, 0xC183, 0xD5AB, 0xC184, + 0xD5AC, 0xC185, 0xD5AD, 0xC186, 0xD5AE, 0xC187, 0xD5AF, 0xC188, 0xD5B0, 0xC189, 0xD5B1, 0xC18A, 0xD5B2, 0xC18B, 0xD5B3, 0xC18C, + 0xD5B4, 0xC18D, 0xD5B5, 0xC18E, 0xD5B6, 0xC18F, 0xD5B7, 0xC190, 0xD5B8, 0xC191, 0xD5B9, 0xC192, 0xD5BA, 0xC193, 0xD5BB, 0xC194, + 0xD5BC, 0xC195, 0xD5BD, 0xC196, 0xD5BE, 0xC197, 0xD5BF, 0xC198, 0xD5C0, 0xC199, 0xD5C1, 0xC19A, 0xD5C2, 0xC19B, 0xD5C3, 0xC19C, + 0xD5C4, 0xC19D, 0xD5C5, 0xC19E, 0xD5C6, 0xC19F, 0xD5C7, 0xC1A0, 0xD5C8, 0xC7E3, 0xD5C9, 0xC7E4, 0xD5CA, 0xC241, 0xD5CB, 0xC242, + 0xD5CC, 0xC7E5, 0xD5CD, 0xC243, 0xD5CE, 0xC244, 0xD5CF, 0xC245, 0xD5D0, 0xC7E6, 0xD5D1, 0xC246, 0xD5D2, 0xC7E7, 0xD5D3, 0xC247, + 0xD5D4, 0xC248, 0xD5D5, 0xC249, 0xD5D6, 0xC24A, 0xD5D7, 0xC24B, 0xD5D8, 0xC7E8, 0xD5D9, 0xC7E9, 0xD5DA, 0xC24C, 0xD5DB, 0xC7EA, + 0xD5DC, 0xC24D, 0xD5DD, 0xC7EB, 0xD5DE, 0xC24E, 0xD5DF, 0xC24F, 0xD5E0, 0xC250, 0xD5E1, 0xC251, 0xD5E2, 0xC252, 0xD5E3, 0xC253, + 0xD5E4, 0xC7EC, 0xD5E5, 0xC7ED, 0xD5E6, 0xC254, 0xD5E7, 0xC255, 0xD5E8, 0xC7EE, 0xD5E9, 0xC256, 0xD5EA, 0xC257, 0xD5EB, 0xC258, + 0xD5EC, 0xC7EF, 0xD5ED, 0xC259, 0xD5EE, 0xC25A, 0xD5EF, 0xC261, 0xD5F0, 0xC262, 0xD5F1, 0xC263, 0xD5F2, 0xC264, 0xD5F3, 0xC265, + 0xD5F4, 0xC7F0, 0xD5F5, 0xC7F1, 0xD5F6, 0xC266, 0xD5F7, 0xC7F2, 0xD5F8, 0xC267, 0xD5F9, 0xC7F3, 0xD5FA, 0xC268, 0xD5FB, 0xC269, + 0xD5FC, 0xC26A, 0xD5FD, 0xC26B, 0xD5FE, 0xC26C, 0xD5FF, 0xC26D, 0xD600, 0xC7F4, 0xD601, 0xC7F5, 0xD602, 0xC26E, 0xD603, 0xC26F, + 0xD604, 0xC7F6, 0xD605, 0xC270, 0xD606, 0xC271, 0xD607, 0xC272, 0xD608, 0xC7F7, 0xD609, 0xC273, 0xD60A, 0xC274, 0xD60B, 0xC275, + 0xD60C, 0xC276, 0xD60D, 0xC277, 0xD60E, 0xC278, 0xD60F, 0xC279, 0xD610, 0xC7F8, 0xD611, 0xC7F9, 0xD612, 0xC27A, 0xD613, 0xC7FA, + 0xD614, 0xC7FB, 0xD615, 0xC7FC, 0xD616, 0xC281, 0xD617, 0xC282, 0xD618, 0xC283, 0xD619, 0xC284, 0xD61A, 0xC285, 0xD61B, 0xC286, + 0xD61C, 0xC7FD, 0xD61D, 0xC287, 0xD61E, 0xC288, 0xD61F, 0xC289, 0xD620, 0xC7FE, 0xD621, 0xC28A, 0xD622, 0xC28B, 0xD623, 0xC28C, + 0xD624, 0xC8A1, 0xD625, 0xC28D, 0xD626, 0xC28E, 0xD627, 0xC28F, 0xD628, 0xC290, 0xD629, 0xC291, 0xD62A, 0xC292, 0xD62B, 0xC293, + 0xD62C, 0xC294, 0xD62D, 0xC8A2, 0xD62E, 0xC295, 0xD62F, 0xC296, 0xD630, 0xC297, 0xD631, 0xC298, 0xD632, 0xC299, 0xD633, 0xC29A, + 0xD634, 0xC29B, 0xD635, 0xC29C, 0xD636, 0xC29D, 0xD637, 0xC29E, 0xD638, 0xC8A3, 0xD639, 0xC8A4, 0xD63A, 0xC29F, 0xD63B, 0xC2A0, + 0xD63C, 0xC8A5, 0xD63D, 0xC341, 0xD63E, 0xC342, 0xD63F, 0xC343, 0xD640, 0xC8A6, 0xD641, 0xC344, 0xD642, 0xC345, 0xD643, 0xC346, + 0xD644, 0xC347, 0xD645, 0xC8A7, 0xD646, 0xC348, 0xD647, 0xC349, 0xD648, 0xC8A8, 0xD649, 0xC8A9, 0xD64A, 0xC34A, 0xD64B, 0xC8AA, + 0xD64C, 0xC34B, 0xD64D, 0xC8AB, 0xD64E, 0xC34C, 0xD64F, 0xC34D, 0xD650, 0xC34E, 0xD651, 0xC8AC, 0xD652, 0xC34F, 0xD653, 0xC350, + 0xD654, 0xC8AD, 0xD655, 0xC8AE, 0xD656, 0xC351, 0xD657, 0xC352, 0xD658, 0xC8AF, 0xD659, 0xC353, 0xD65A, 0xC354, 0xD65B, 0xC355, + 0xD65C, 0xC8B0, 0xD65D, 0xC356, 0xD65E, 0xC357, 0xD65F, 0xC358, 0xD660, 0xC359, 0xD661, 0xC35A, 0xD662, 0xC361, 0xD663, 0xC362, + 0xD664, 0xC363, 0xD665, 0xC364, 0xD666, 0xC365, 0xD667, 0xC8B1, 0xD668, 0xC366, 0xD669, 0xC8B2, 0xD66A, 0xC367, 0xD66B, 0xC368, + 0xD66C, 0xC369, 0xD66D, 0xC36A, 0xD66E, 0xC36B, 0xD66F, 0xC36C, 0xD670, 0xC8B3, 0xD671, 0xC8B4, 0xD672, 0xC36D, 0xD673, 0xC36E, + 0xD674, 0xC8B5, 0xD675, 0xC36F, 0xD676, 0xC370, 0xD677, 0xC371, 0xD678, 0xC372, 0xD679, 0xC373, 0xD67A, 0xC374, 0xD67B, 0xC375, + 0xD67C, 0xC376, 0xD67D, 0xC377, 0xD67E, 0xC378, 0xD67F, 0xC379, 0xD680, 0xC37A, 0xD681, 0xC381, 0xD682, 0xC382, 0xD683, 0xC8B6, + 0xD684, 0xC383, 0xD685, 0xC8B7, 0xD686, 0xC384, 0xD687, 0xC385, 0xD688, 0xC386, 0xD689, 0xC387, 0xD68A, 0xC388, 0xD68B, 0xC389, + 0xD68C, 0xC8B8, 0xD68D, 0xC8B9, 0xD68E, 0xC38A, 0xD68F, 0xC38B, 0xD690, 0xC8BA, 0xD691, 0xC38C, 0xD692, 0xC38D, 0xD693, 0xC38E, + 0xD694, 0xC8BB, 0xD695, 0xC38F, 0xD696, 0xC390, 0xD697, 0xC391, 0xD698, 0xC392, 0xD699, 0xC393, 0xD69A, 0xC394, 0xD69B, 0xC395, + 0xD69C, 0xC396, 0xD69D, 0xC8BC, 0xD69E, 0xC397, 0xD69F, 0xC8BD, 0xD6A0, 0xC398, 0xD6A1, 0xC8BE, 0xD6A2, 0xC399, 0xD6A3, 0xC39A, + 0xD6A4, 0xC39B, 0xD6A5, 0xC39C, 0xD6A6, 0xC39D, 0xD6A7, 0xC39E, 0xD6A8, 0xC8BF, 0xD6A9, 0xC39F, 0xD6AA, 0xC3A0, 0xD6AB, 0xC441, + 0xD6AC, 0xC8C0, 0xD6AD, 0xC442, 0xD6AE, 0xC443, 0xD6AF, 0xC444, 0xD6B0, 0xC8C1, 0xD6B1, 0xC445, 0xD6B2, 0xC446, 0xD6B3, 0xC447, + 0xD6B4, 0xC448, 0xD6B5, 0xC449, 0xD6B6, 0xC44A, 0xD6B7, 0xC44B, 0xD6B8, 0xC44C, 0xD6B9, 0xC8C2, 0xD6BA, 0xC44D, 0xD6BB, 0xC8C3, + 0xD6BC, 0xC44E, 0xD6BD, 0xC44F, 0xD6BE, 0xC450, 0xD6BF, 0xC451, 0xD6C0, 0xC452, 0xD6C1, 0xC453, 0xD6C2, 0xC454, 0xD6C3, 0xC455, + 0xD6C4, 0xC8C4, 0xD6C5, 0xC8C5, 0xD6C6, 0xC456, 0xD6C7, 0xC457, 0xD6C8, 0xC8C6, 0xD6C9, 0xC458, 0xD6CA, 0xC459, 0xD6CB, 0xC45A, + 0xD6CC, 0xC8C7, 0xD6CD, 0xC461, 0xD6CE, 0xC462, 0xD6CF, 0xC463, 0xD6D0, 0xC464, 0xD6D1, 0xC8C8, 0xD6D2, 0xC465, 0xD6D3, 0xC466, + 0xD6D4, 0xC8C9, 0xD6D5, 0xC467, 0xD6D6, 0xC468, 0xD6D7, 0xC8CA, 0xD6D8, 0xC469, 0xD6D9, 0xC8CB, 0xD6DA, 0xC46A, 0xD6DB, 0xC46B, + 0xD6DC, 0xC46C, 0xD6DD, 0xC46D, 0xD6DE, 0xC46E, 0xD6DF, 0xC46F, 0xD6E0, 0xC8CC, 0xD6E1, 0xC470, 0xD6E2, 0xC471, 0xD6E3, 0xC472, + 0xD6E4, 0xC8CD, 0xD6E5, 0xC473, 0xD6E6, 0xC474, 0xD6E7, 0xC475, 0xD6E8, 0xC8CE, 0xD6E9, 0xC476, 0xD6EA, 0xC477, 0xD6EB, 0xC478, + 0xD6EC, 0xC479, 0xD6ED, 0xC47A, 0xD6EE, 0xC481, 0xD6EF, 0xC482, 0xD6F0, 0xC8CF, 0xD6F1, 0xC483, 0xD6F2, 0xC484, 0xD6F3, 0xC485, + 0xD6F4, 0xC486, 0xD6F5, 0xC8D0, 0xD6F6, 0xC487, 0xD6F7, 0xC488, 0xD6F8, 0xC489, 0xD6F9, 0xC48A, 0xD6FA, 0xC48B, 0xD6FB, 0xC48C, + 0xD6FC, 0xC8D1, 0xD6FD, 0xC8D2, 0xD6FE, 0xC48D, 0xD6FF, 0xC48E, 0xD700, 0xC8D3, 0xD701, 0xC48F, 0xD702, 0xC490, 0xD703, 0xC491, + 0xD704, 0xC8D4, 0xD705, 0xC492, 0xD706, 0xC493, 0xD707, 0xC494, 0xD708, 0xC495, 0xD709, 0xC496, 0xD70A, 0xC497, 0xD70B, 0xC498, + 0xD70C, 0xC499, 0xD70D, 0xC49A, 0xD70E, 0xC49B, 0xD70F, 0xC49C, 0xD710, 0xC49D, 0xD711, 0xC8D5, 0xD712, 0xC49E, 0xD713, 0xC49F, + 0xD714, 0xC4A0, 0xD715, 0xC541, 0xD716, 0xC542, 0xD717, 0xC543, 0xD718, 0xC8D6, 0xD719, 0xC8D7, 0xD71A, 0xC544, 0xD71B, 0xC545, + 0xD71C, 0xC8D8, 0xD71D, 0xC546, 0xD71E, 0xC547, 0xD71F, 0xC548, 0xD720, 0xC8D9, 0xD721, 0xC549, 0xD722, 0xC54A, 0xD723, 0xC54B, + 0xD724, 0xC54C, 0xD725, 0xC54D, 0xD726, 0xC54E, 0xD727, 0xC54F, 0xD728, 0xC8DA, 0xD729, 0xC8DB, 0xD72A, 0xC550, 0xD72B, 0xC8DC, + 0xD72C, 0xC551, 0xD72D, 0xC8DD, 0xD72E, 0xC552, 0xD72F, 0xC553, 0xD730, 0xC554, 0xD731, 0xC555, 0xD732, 0xC556, 0xD733, 0xC557, + 0xD734, 0xC8DE, 0xD735, 0xC8DF, 0xD736, 0xC558, 0xD737, 0xC559, 0xD738, 0xC8E0, 0xD739, 0xC55A, 0xD73A, 0xC561, 0xD73B, 0xC562, + 0xD73C, 0xC8E1, 0xD73D, 0xC563, 0xD73E, 0xC564, 0xD73F, 0xC565, 0xD740, 0xC566, 0xD741, 0xC567, 0xD742, 0xC568, 0xD743, 0xC569, + 0xD744, 0xC8E2, 0xD745, 0xC56A, 0xD746, 0xC56B, 0xD747, 0xC8E3, 0xD748, 0xC56C, 0xD749, 0xC8E4, 0xD74A, 0xC56D, 0xD74B, 0xC56E, + 0xD74C, 0xC56F, 0xD74D, 0xC570, 0xD74E, 0xC571, 0xD74F, 0xC572, 0xD750, 0xC8E5, 0xD751, 0xC8E6, 0xD752, 0xC573, 0xD753, 0xC574, + 0xD754, 0xC8E7, 0xD755, 0xC575, 0xD756, 0xC8E8, 0xD757, 0xC8E9, 0xD758, 0xC8EA, 0xD759, 0xC8EB, 0xD75A, 0xC576, 0xD75B, 0xC577, + 0xD75C, 0xC578, 0xD75D, 0xC579, 0xD75E, 0xC57A, 0xD75F, 0xC581, 0xD760, 0xC8EC, 0xD761, 0xC8ED, 0xD762, 0xC582, 0xD763, 0xC8EE, + 0xD764, 0xC583, 0xD765, 0xC8EF, 0xD766, 0xC584, 0xD767, 0xC585, 0xD768, 0xC586, 0xD769, 0xC8F0, 0xD76A, 0xC587, 0xD76B, 0xC588, + 0xD76C, 0xC8F1, 0xD76D, 0xC589, 0xD76E, 0xC58A, 0xD76F, 0xC58B, 0xD770, 0xC8F2, 0xD771, 0xC58C, 0xD772, 0xC58D, 0xD773, 0xC58E, + 0xD774, 0xC8F3, 0xD775, 0xC58F, 0xD776, 0xC590, 0xD777, 0xC591, 0xD778, 0xC592, 0xD779, 0xC593, 0xD77A, 0xC594, 0xD77B, 0xC595, + 0xD77C, 0xC8F4, 0xD77D, 0xC8F5, 0xD77E, 0xC596, 0xD77F, 0xC597, 0xD780, 0xC598, 0xD781, 0xC8F6, 0xD782, 0xC599, 0xD783, 0xC59A, + 0xD784, 0xC59B, 0xD785, 0xC59C, 0xD786, 0xC59D, 0xD787, 0xC59E, 0xD788, 0xC8F7, 0xD789, 0xC8F8, 0xD78A, 0xC59F, 0xD78B, 0xC5A0, + 0xD78C, 0xC8F9, 0xD78D, 0xC641, 0xD78E, 0xC642, 0xD78F, 0xC643, 0xD790, 0xC8FA, 0xD791, 0xC644, 0xD792, 0xC645, 0xD793, 0xC646, + 0xD794, 0xC647, 0xD795, 0xC648, 0xD796, 0xC649, 0xD797, 0xC64A, 0xD798, 0xC8FB, 0xD799, 0xC8FC, 0xD79A, 0xC64B, 0xD79B, 0xC8FD, + 0xD79C, 0xC64C, 0xD79D, 0xC8FE, 0xD79E, 0xC64D, 0xD79F, 0xC64E, 0xD7A0, 0xC64F, 0xD7A1, 0xC650, 0xD7A2, 0xC651, 0xD7A3, 0xC652, + 0xF900, 0xCBD0, 0xF901, 0xCBD6, 0xF902, 0xCBE7, 0xF903, 0xCDCF, 0xF904, 0xCDE8, 0xF905, 0xCEAD, 0xF906, 0xCFFB, 0xF907, 0xD0A2, + 0xF908, 0xD0B8, 0xF909, 0xD0D0, 0xF90A, 0xD0DD, 0xF90B, 0xD1D4, 0xF90C, 0xD1D5, 0xF90D, 0xD1D8, 0xF90E, 0xD1DB, 0xF90F, 0xD1DC, + 0xF910, 0xD1DD, 0xF911, 0xD1DE, 0xF912, 0xD1DF, 0xF913, 0xD1E0, 0xF914, 0xD1E2, 0xF915, 0xD1E3, 0xF916, 0xD1E4, 0xF917, 0xD1E5, + 0xF918, 0xD1E6, 0xF919, 0xD1E8, 0xF91A, 0xD1E9, 0xF91B, 0xD1EA, 0xF91C, 0xD1EB, 0xF91D, 0xD1ED, 0xF91E, 0xD1EF, 0xF91F, 0xD1F0, + 0xF920, 0xD1F2, 0xF921, 0xD1F6, 0xF922, 0xD1FA, 0xF923, 0xD1FC, 0xF924, 0xD1FD, 0xF925, 0xD1FE, 0xF926, 0xD2A2, 0xF927, 0xD2A3, + 0xF928, 0xD2A7, 0xF929, 0xD2A8, 0xF92A, 0xD2A9, 0xF92B, 0xD2AA, 0xF92C, 0xD2AB, 0xF92D, 0xD2AD, 0xF92E, 0xD2B2, 0xF92F, 0xD2BE, + 0xF930, 0xD2C2, 0xF931, 0xD2C3, 0xF932, 0xD2C4, 0xF933, 0xD2C6, 0xF934, 0xD2C7, 0xF935, 0xD2C8, 0xF936, 0xD2C9, 0xF937, 0xD2CA, + 0xF938, 0xD2CB, 0xF939, 0xD2CD, 0xF93A, 0xD2CE, 0xF93B, 0xD2CF, 0xF93C, 0xD2D0, 0xF93D, 0xD2D1, 0xF93E, 0xD2D2, 0xF93F, 0xD2D3, + 0xF940, 0xD2D4, 0xF941, 0xD2D5, 0xF942, 0xD2D6, 0xF943, 0xD2D7, 0xF944, 0xD2D9, 0xF945, 0xD2DA, 0xF946, 0xD2DE, 0xF947, 0xD2DF, + 0xF948, 0xD2E1, 0xF949, 0xD2E2, 0xF94A, 0xD2E4, 0xF94B, 0xD2E5, 0xF94C, 0xD2E6, 0xF94D, 0xD2E7, 0xF94E, 0xD2E8, 0xF94F, 0xD2E9, + 0xF950, 0xD2EA, 0xF951, 0xD2EB, 0xF952, 0xD2F0, 0xF953, 0xD2F1, 0xF954, 0xD2F2, 0xF955, 0xD2F3, 0xF956, 0xD2F4, 0xF957, 0xD2F5, + 0xF958, 0xD2F7, 0xF959, 0xD2F8, 0xF95A, 0xD4E6, 0xF95B, 0xD4FC, 0xF95C, 0xD5A5, 0xF95D, 0xD5AB, 0xF95E, 0xD5AE, 0xF95F, 0xD6B8, + 0xF960, 0xD6CD, 0xF961, 0xD7CB, 0xF962, 0xD7E4, 0xF963, 0xDBC5, 0xF964, 0xDBE4, 0xF965, 0xDCA5, 0xF966, 0xDDA5, 0xF967, 0xDDD5, + 0xF968, 0xDDF4, 0xF969, 0xDEFC, 0xF96A, 0xDEFE, 0xF96B, 0xDFB3, 0xF96C, 0xDFE1, 0xF96D, 0xDFE8, 0xF96E, 0xE0F1, 0xF96F, 0xE1AD, + 0xF970, 0xE1ED, 0xF971, 0xE3F5, 0xF972, 0xE4A1, 0xF973, 0xE4A9, 0xF974, 0xE5AE, 0xF975, 0xE5B1, 0xF976, 0xE5B2, 0xF977, 0xE5B9, + 0xF978, 0xE5BB, 0xF979, 0xE5BC, 0xF97A, 0xE5C4, 0xF97B, 0xE5CE, 0xF97C, 0xE5D0, 0xF97D, 0xE5D2, 0xF97E, 0xE5D6, 0xF97F, 0xE5FA, + 0xF980, 0xE5FB, 0xF981, 0xE5FC, 0xF982, 0xE5FE, 0xF983, 0xE6A1, 0xF984, 0xE6A4, 0xF985, 0xE6A7, 0xF986, 0xE6AD, 0xF987, 0xE6AF, + 0xF988, 0xE6B0, 0xF989, 0xE6B1, 0xF98A, 0xE6B3, 0xF98B, 0xE6B7, 0xF98C, 0xE6B8, 0xF98D, 0xE6BC, 0xF98E, 0xE6C4, 0xF98F, 0xE6C6, + 0xF990, 0xE6C7, 0xF991, 0xE6CA, 0xF992, 0xE6D2, 0xF993, 0xE6D6, 0xF994, 0xE6D9, 0xF995, 0xE6DC, 0xF996, 0xE6DF, 0xF997, 0xE6E1, + 0xF998, 0xE6E4, 0xF999, 0xE6E5, 0xF99A, 0xE6E6, 0xF99B, 0xE6E8, 0xF99C, 0xE6EA, 0xF99D, 0xE6EB, 0xF99E, 0xE6EC, 0xF99F, 0xE6EF, + 0xF9A0, 0xE6F1, 0xF9A1, 0xE6F2, 0xF9A2, 0xE6F5, 0xF9A3, 0xE6F6, 0xF9A4, 0xE6F7, 0xF9A5, 0xE6F9, 0xF9A6, 0xE7A1, 0xF9A7, 0xE7A6, + 0xF9A8, 0xE7A9, 0xF9A9, 0xE7AA, 0xF9AA, 0xE7AC, 0xF9AB, 0xE7AD, 0xF9AC, 0xE7B0, 0xF9AD, 0xE7BF, 0xF9AE, 0xE7C1, 0xF9AF, 0xE7C6, + 0xF9B0, 0xE7C7, 0xF9B1, 0xE7CB, 0xF9B2, 0xE7CD, 0xF9B3, 0xE7CF, 0xF9B4, 0xE7D0, 0xF9B5, 0xE7D3, 0xF9B6, 0xE7DF, 0xF9B7, 0xE7E4, + 0xF9B8, 0xE7E6, 0xF9B9, 0xE7F7, 0xF9BA, 0xE8E7, 0xF9BB, 0xE8E8, 0xF9BC, 0xE8F0, 0xF9BD, 0xE8F1, 0xF9BE, 0xE8F7, 0xF9BF, 0xE8F9, + 0xF9C0, 0xE8FB, 0xF9C1, 0xE8FE, 0xF9C2, 0xE9A7, 0xF9C3, 0xE9AC, 0xF9C4, 0xE9CC, 0xF9C5, 0xE9F7, 0xF9C6, 0xEAC1, 0xF9C7, 0xEAE5, + 0xF9C8, 0xEAF4, 0xF9C9, 0xEAF7, 0xF9CA, 0xEAFC, 0xF9CB, 0xEAFE, 0xF9CC, 0xEBA4, 0xF9CD, 0xEBA7, 0xF9CE, 0xEBA9, 0xF9CF, 0xEBAA, + 0xF9D0, 0xEBBA, 0xF9D1, 0xEBBB, 0xF9D2, 0xEBBD, 0xF9D3, 0xEBC1, 0xF9D4, 0xEBC2, 0xF9D5, 0xEBC6, 0xF9D6, 0xEBC7, 0xF9D7, 0xEBCC, + 0xF9D8, 0xEBCF, 0xF9D9, 0xEBD0, 0xF9DA, 0xEBD1, 0xF9DB, 0xEBD2, 0xF9DC, 0xEBD8, 0xF9DD, 0xECA6, 0xF9DE, 0xECA7, 0xF9DF, 0xECAA, + 0xF9E0, 0xECAF, 0xF9E1, 0xECB0, 0xF9E2, 0xECB1, 0xF9E3, 0xECB2, 0xF9E4, 0xECB5, 0xF9E5, 0xECB8, 0xF9E6, 0xECBA, 0xF9E7, 0xECC0, + 0xF9E8, 0xECC1, 0xF9E9, 0xECC5, 0xF9EA, 0xECC6, 0xF9EB, 0xECC9, 0xF9EC, 0xECCA, 0xF9ED, 0xECD5, 0xF9EE, 0xECDD, 0xF9EF, 0xECDE, + 0xF9F0, 0xECE1, 0xF9F1, 0xECE4, 0xF9F2, 0xECE7, 0xF9F3, 0xECE8, 0xF9F4, 0xECF7, 0xF9F5, 0xECF8, 0xF9F6, 0xECFA, 0xF9F7, 0xEDA1, + 0xF9F8, 0xEDA2, 0xF9F9, 0xEDA3, 0xF9FA, 0xEDEE, 0xF9FB, 0xEEDB, 0xF9FC, 0xF2BD, 0xF9FD, 0xF2FA, 0xF9FE, 0xF3B1, 0xF9FF, 0xF4A7, + 0xFA00, 0xF4EE, 0xFA01, 0xF6F4, 0xFA02, 0xF6F6, 0xFA03, 0xF7B8, 0xFA04, 0xF7C8, 0xFA05, 0xF7D3, 0xFA06, 0xF8DB, 0xFA07, 0xF8F0, + 0xFA08, 0xFAA1, 0xFA09, 0xFAA2, 0xFA0A, 0xFAE6, 0xFA0B, 0xFCA9, 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA3A4, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA1AC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA2A6, 0xFFE0, 0xA1CB, 0xFFE1, 0xA1CC, 0xFFE2, 0xA1FE, 0xFFE3, 0xA3FE, 0xFFE5, 0xA1CD, 0xFFE6, 0xA3DC, + 0, 0 +}; + +static const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */ + 0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E, + 0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25, + 0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32, + 0x8159, 0xAC33, 0x815A, 0xAC34, 0x8161, 0xAC35, 0x8162, 0xAC36, 0x8163, 0xAC37, 0x8164, 0xAC3A, 0x8165, 0xAC3B, 0x8166, 0xAC3D, + 0x8167, 0xAC3E, 0x8168, 0xAC3F, 0x8169, 0xAC41, 0x816A, 0xAC42, 0x816B, 0xAC43, 0x816C, 0xAC44, 0x816D, 0xAC45, 0x816E, 0xAC46, + 0x816F, 0xAC47, 0x8170, 0xAC48, 0x8171, 0xAC49, 0x8172, 0xAC4A, 0x8173, 0xAC4C, 0x8174, 0xAC4E, 0x8175, 0xAC4F, 0x8176, 0xAC50, + 0x8177, 0xAC51, 0x8178, 0xAC52, 0x8179, 0xAC53, 0x817A, 0xAC55, 0x8181, 0xAC56, 0x8182, 0xAC57, 0x8183, 0xAC59, 0x8184, 0xAC5A, + 0x8185, 0xAC5B, 0x8186, 0xAC5D, 0x8187, 0xAC5E, 0x8188, 0xAC5F, 0x8189, 0xAC60, 0x818A, 0xAC61, 0x818B, 0xAC62, 0x818C, 0xAC63, + 0x818D, 0xAC64, 0x818E, 0xAC65, 0x818F, 0xAC66, 0x8190, 0xAC67, 0x8191, 0xAC68, 0x8192, 0xAC69, 0x8193, 0xAC6A, 0x8194, 0xAC6B, + 0x8195, 0xAC6C, 0x8196, 0xAC6D, 0x8197, 0xAC6E, 0x8198, 0xAC6F, 0x8199, 0xAC72, 0x819A, 0xAC73, 0x819B, 0xAC75, 0x819C, 0xAC76, + 0x819D, 0xAC79, 0x819E, 0xAC7B, 0x819F, 0xAC7C, 0x81A0, 0xAC7D, 0x81A1, 0xAC7E, 0x81A2, 0xAC7F, 0x81A3, 0xAC82, 0x81A4, 0xAC87, + 0x81A5, 0xAC88, 0x81A6, 0xAC8D, 0x81A7, 0xAC8E, 0x81A8, 0xAC8F, 0x81A9, 0xAC91, 0x81AA, 0xAC92, 0x81AB, 0xAC93, 0x81AC, 0xAC95, + 0x81AD, 0xAC96, 0x81AE, 0xAC97, 0x81AF, 0xAC98, 0x81B0, 0xAC99, 0x81B1, 0xAC9A, 0x81B2, 0xAC9B, 0x81B3, 0xAC9E, 0x81B4, 0xACA2, + 0x81B5, 0xACA3, 0x81B6, 0xACA4, 0x81B7, 0xACA5, 0x81B8, 0xACA6, 0x81B9, 0xACA7, 0x81BA, 0xACAB, 0x81BB, 0xACAD, 0x81BC, 0xACAE, + 0x81BD, 0xACB1, 0x81BE, 0xACB2, 0x81BF, 0xACB3, 0x81C0, 0xACB4, 0x81C1, 0xACB5, 0x81C2, 0xACB6, 0x81C3, 0xACB7, 0x81C4, 0xACBA, + 0x81C5, 0xACBE, 0x81C6, 0xACBF, 0x81C7, 0xACC0, 0x81C8, 0xACC2, 0x81C9, 0xACC3, 0x81CA, 0xACC5, 0x81CB, 0xACC6, 0x81CC, 0xACC7, + 0x81CD, 0xACC9, 0x81CE, 0xACCA, 0x81CF, 0xACCB, 0x81D0, 0xACCD, 0x81D1, 0xACCE, 0x81D2, 0xACCF, 0x81D3, 0xACD0, 0x81D4, 0xACD1, + 0x81D5, 0xACD2, 0x81D6, 0xACD3, 0x81D7, 0xACD4, 0x81D8, 0xACD6, 0x81D9, 0xACD8, 0x81DA, 0xACD9, 0x81DB, 0xACDA, 0x81DC, 0xACDB, + 0x81DD, 0xACDC, 0x81DE, 0xACDD, 0x81DF, 0xACDE, 0x81E0, 0xACDF, 0x81E1, 0xACE2, 0x81E2, 0xACE3, 0x81E3, 0xACE5, 0x81E4, 0xACE6, + 0x81E5, 0xACE9, 0x81E6, 0xACEB, 0x81E7, 0xACED, 0x81E8, 0xACEE, 0x81E9, 0xACF2, 0x81EA, 0xACF4, 0x81EB, 0xACF7, 0x81EC, 0xACF8, + 0x81ED, 0xACF9, 0x81EE, 0xACFA, 0x81EF, 0xACFB, 0x81F0, 0xACFE, 0x81F1, 0xACFF, 0x81F2, 0xAD01, 0x81F3, 0xAD02, 0x81F4, 0xAD03, + 0x81F5, 0xAD05, 0x81F6, 0xAD07, 0x81F7, 0xAD08, 0x81F8, 0xAD09, 0x81F9, 0xAD0A, 0x81FA, 0xAD0B, 0x81FB, 0xAD0E, 0x81FC, 0xAD10, + 0x81FD, 0xAD12, 0x81FE, 0xAD13, 0x8241, 0xAD14, 0x8242, 0xAD15, 0x8243, 0xAD16, 0x8244, 0xAD17, 0x8245, 0xAD19, 0x8246, 0xAD1A, + 0x8247, 0xAD1B, 0x8248, 0xAD1D, 0x8249, 0xAD1E, 0x824A, 0xAD1F, 0x824B, 0xAD21, 0x824C, 0xAD22, 0x824D, 0xAD23, 0x824E, 0xAD24, + 0x824F, 0xAD25, 0x8250, 0xAD26, 0x8251, 0xAD27, 0x8252, 0xAD28, 0x8253, 0xAD2A, 0x8254, 0xAD2B, 0x8255, 0xAD2E, 0x8256, 0xAD2F, + 0x8257, 0xAD30, 0x8258, 0xAD31, 0x8259, 0xAD32, 0x825A, 0xAD33, 0x8261, 0xAD36, 0x8262, 0xAD37, 0x8263, 0xAD39, 0x8264, 0xAD3A, + 0x8265, 0xAD3B, 0x8266, 0xAD3D, 0x8267, 0xAD3E, 0x8268, 0xAD3F, 0x8269, 0xAD40, 0x826A, 0xAD41, 0x826B, 0xAD42, 0x826C, 0xAD43, + 0x826D, 0xAD46, 0x826E, 0xAD48, 0x826F, 0xAD4A, 0x8270, 0xAD4B, 0x8271, 0xAD4C, 0x8272, 0xAD4D, 0x8273, 0xAD4E, 0x8274, 0xAD4F, + 0x8275, 0xAD51, 0x8276, 0xAD52, 0x8277, 0xAD53, 0x8278, 0xAD55, 0x8279, 0xAD56, 0x827A, 0xAD57, 0x8281, 0xAD59, 0x8282, 0xAD5A, + 0x8283, 0xAD5B, 0x8284, 0xAD5C, 0x8285, 0xAD5D, 0x8286, 0xAD5E, 0x8287, 0xAD5F, 0x8288, 0xAD60, 0x8289, 0xAD62, 0x828A, 0xAD64, + 0x828B, 0xAD65, 0x828C, 0xAD66, 0x828D, 0xAD67, 0x828E, 0xAD68, 0x828F, 0xAD69, 0x8290, 0xAD6A, 0x8291, 0xAD6B, 0x8292, 0xAD6E, + 0x8293, 0xAD6F, 0x8294, 0xAD71, 0x8295, 0xAD72, 0x8296, 0xAD77, 0x8297, 0xAD78, 0x8298, 0xAD79, 0x8299, 0xAD7A, 0x829A, 0xAD7E, + 0x829B, 0xAD80, 0x829C, 0xAD83, 0x829D, 0xAD84, 0x829E, 0xAD85, 0x829F, 0xAD86, 0x82A0, 0xAD87, 0x82A1, 0xAD8A, 0x82A2, 0xAD8B, + 0x82A3, 0xAD8D, 0x82A4, 0xAD8E, 0x82A5, 0xAD8F, 0x82A6, 0xAD91, 0x82A7, 0xAD92, 0x82A8, 0xAD93, 0x82A9, 0xAD94, 0x82AA, 0xAD95, + 0x82AB, 0xAD96, 0x82AC, 0xAD97, 0x82AD, 0xAD98, 0x82AE, 0xAD99, 0x82AF, 0xAD9A, 0x82B0, 0xAD9B, 0x82B1, 0xAD9E, 0x82B2, 0xAD9F, + 0x82B3, 0xADA0, 0x82B4, 0xADA1, 0x82B5, 0xADA2, 0x82B6, 0xADA3, 0x82B7, 0xADA5, 0x82B8, 0xADA6, 0x82B9, 0xADA7, 0x82BA, 0xADA8, + 0x82BB, 0xADA9, 0x82BC, 0xADAA, 0x82BD, 0xADAB, 0x82BE, 0xADAC, 0x82BF, 0xADAD, 0x82C0, 0xADAE, 0x82C1, 0xADAF, 0x82C2, 0xADB0, + 0x82C3, 0xADB1, 0x82C4, 0xADB2, 0x82C5, 0xADB3, 0x82C6, 0xADB4, 0x82C7, 0xADB5, 0x82C8, 0xADB6, 0x82C9, 0xADB8, 0x82CA, 0xADB9, + 0x82CB, 0xADBA, 0x82CC, 0xADBB, 0x82CD, 0xADBC, 0x82CE, 0xADBD, 0x82CF, 0xADBE, 0x82D0, 0xADBF, 0x82D1, 0xADC2, 0x82D2, 0xADC3, + 0x82D3, 0xADC5, 0x82D4, 0xADC6, 0x82D5, 0xADC7, 0x82D6, 0xADC9, 0x82D7, 0xADCA, 0x82D8, 0xADCB, 0x82D9, 0xADCC, 0x82DA, 0xADCD, + 0x82DB, 0xADCE, 0x82DC, 0xADCF, 0x82DD, 0xADD2, 0x82DE, 0xADD4, 0x82DF, 0xADD5, 0x82E0, 0xADD6, 0x82E1, 0xADD7, 0x82E2, 0xADD8, + 0x82E3, 0xADD9, 0x82E4, 0xADDA, 0x82E5, 0xADDB, 0x82E6, 0xADDD, 0x82E7, 0xADDE, 0x82E8, 0xADDF, 0x82E9, 0xADE1, 0x82EA, 0xADE2, + 0x82EB, 0xADE3, 0x82EC, 0xADE5, 0x82ED, 0xADE6, 0x82EE, 0xADE7, 0x82EF, 0xADE8, 0x82F0, 0xADE9, 0x82F1, 0xADEA, 0x82F2, 0xADEB, + 0x82F3, 0xADEC, 0x82F4, 0xADED, 0x82F5, 0xADEE, 0x82F6, 0xADEF, 0x82F7, 0xADF0, 0x82F8, 0xADF1, 0x82F9, 0xADF2, 0x82FA, 0xADF3, + 0x82FB, 0xADF4, 0x82FC, 0xADF5, 0x82FD, 0xADF6, 0x82FE, 0xADF7, 0x8341, 0xADFA, 0x8342, 0xADFB, 0x8343, 0xADFD, 0x8344, 0xADFE, + 0x8345, 0xAE02, 0x8346, 0xAE03, 0x8347, 0xAE04, 0x8348, 0xAE05, 0x8349, 0xAE06, 0x834A, 0xAE07, 0x834B, 0xAE0A, 0x834C, 0xAE0C, + 0x834D, 0xAE0E, 0x834E, 0xAE0F, 0x834F, 0xAE10, 0x8350, 0xAE11, 0x8351, 0xAE12, 0x8352, 0xAE13, 0x8353, 0xAE15, 0x8354, 0xAE16, + 0x8355, 0xAE17, 0x8356, 0xAE18, 0x8357, 0xAE19, 0x8358, 0xAE1A, 0x8359, 0xAE1B, 0x835A, 0xAE1C, 0x8361, 0xAE1D, 0x8362, 0xAE1E, + 0x8363, 0xAE1F, 0x8364, 0xAE20, 0x8365, 0xAE21, 0x8366, 0xAE22, 0x8367, 0xAE23, 0x8368, 0xAE24, 0x8369, 0xAE25, 0x836A, 0xAE26, + 0x836B, 0xAE27, 0x836C, 0xAE28, 0x836D, 0xAE29, 0x836E, 0xAE2A, 0x836F, 0xAE2B, 0x8370, 0xAE2C, 0x8371, 0xAE2D, 0x8372, 0xAE2E, + 0x8373, 0xAE2F, 0x8374, 0xAE32, 0x8375, 0xAE33, 0x8376, 0xAE35, 0x8377, 0xAE36, 0x8378, 0xAE39, 0x8379, 0xAE3B, 0x837A, 0xAE3C, + 0x8381, 0xAE3D, 0x8382, 0xAE3E, 0x8383, 0xAE3F, 0x8384, 0xAE42, 0x8385, 0xAE44, 0x8386, 0xAE47, 0x8387, 0xAE48, 0x8388, 0xAE49, + 0x8389, 0xAE4B, 0x838A, 0xAE4F, 0x838B, 0xAE51, 0x838C, 0xAE52, 0x838D, 0xAE53, 0x838E, 0xAE55, 0x838F, 0xAE57, 0x8390, 0xAE58, + 0x8391, 0xAE59, 0x8392, 0xAE5A, 0x8393, 0xAE5B, 0x8394, 0xAE5E, 0x8395, 0xAE62, 0x8396, 0xAE63, 0x8397, 0xAE64, 0x8398, 0xAE66, + 0x8399, 0xAE67, 0x839A, 0xAE6A, 0x839B, 0xAE6B, 0x839C, 0xAE6D, 0x839D, 0xAE6E, 0x839E, 0xAE6F, 0x839F, 0xAE71, 0x83A0, 0xAE72, + 0x83A1, 0xAE73, 0x83A2, 0xAE74, 0x83A3, 0xAE75, 0x83A4, 0xAE76, 0x83A5, 0xAE77, 0x83A6, 0xAE7A, 0x83A7, 0xAE7E, 0x83A8, 0xAE7F, + 0x83A9, 0xAE80, 0x83AA, 0xAE81, 0x83AB, 0xAE82, 0x83AC, 0xAE83, 0x83AD, 0xAE86, 0x83AE, 0xAE87, 0x83AF, 0xAE88, 0x83B0, 0xAE89, + 0x83B1, 0xAE8A, 0x83B2, 0xAE8B, 0x83B3, 0xAE8D, 0x83B4, 0xAE8E, 0x83B5, 0xAE8F, 0x83B6, 0xAE90, 0x83B7, 0xAE91, 0x83B8, 0xAE92, + 0x83B9, 0xAE93, 0x83BA, 0xAE94, 0x83BB, 0xAE95, 0x83BC, 0xAE96, 0x83BD, 0xAE97, 0x83BE, 0xAE98, 0x83BF, 0xAE99, 0x83C0, 0xAE9A, + 0x83C1, 0xAE9B, 0x83C2, 0xAE9C, 0x83C3, 0xAE9D, 0x83C4, 0xAE9E, 0x83C5, 0xAE9F, 0x83C6, 0xAEA0, 0x83C7, 0xAEA1, 0x83C8, 0xAEA2, + 0x83C9, 0xAEA3, 0x83CA, 0xAEA4, 0x83CB, 0xAEA5, 0x83CC, 0xAEA6, 0x83CD, 0xAEA7, 0x83CE, 0xAEA8, 0x83CF, 0xAEA9, 0x83D0, 0xAEAA, + 0x83D1, 0xAEAB, 0x83D2, 0xAEAC, 0x83D3, 0xAEAD, 0x83D4, 0xAEAE, 0x83D5, 0xAEAF, 0x83D6, 0xAEB0, 0x83D7, 0xAEB1, 0x83D8, 0xAEB2, + 0x83D9, 0xAEB3, 0x83DA, 0xAEB4, 0x83DB, 0xAEB5, 0x83DC, 0xAEB6, 0x83DD, 0xAEB7, 0x83DE, 0xAEB8, 0x83DF, 0xAEB9, 0x83E0, 0xAEBA, + 0x83E1, 0xAEBB, 0x83E2, 0xAEBF, 0x83E3, 0xAEC1, 0x83E4, 0xAEC2, 0x83E5, 0xAEC3, 0x83E6, 0xAEC5, 0x83E7, 0xAEC6, 0x83E8, 0xAEC7, + 0x83E9, 0xAEC8, 0x83EA, 0xAEC9, 0x83EB, 0xAECA, 0x83EC, 0xAECB, 0x83ED, 0xAECE, 0x83EE, 0xAED2, 0x83EF, 0xAED3, 0x83F0, 0xAED4, + 0x83F1, 0xAED5, 0x83F2, 0xAED6, 0x83F3, 0xAED7, 0x83F4, 0xAEDA, 0x83F5, 0xAEDB, 0x83F6, 0xAEDD, 0x83F7, 0xAEDE, 0x83F8, 0xAEDF, + 0x83F9, 0xAEE0, 0x83FA, 0xAEE1, 0x83FB, 0xAEE2, 0x83FC, 0xAEE3, 0x83FD, 0xAEE4, 0x83FE, 0xAEE5, 0x8441, 0xAEE6, 0x8442, 0xAEE7, + 0x8443, 0xAEE9, 0x8444, 0xAEEA, 0x8445, 0xAEEC, 0x8446, 0xAEEE, 0x8447, 0xAEEF, 0x8448, 0xAEF0, 0x8449, 0xAEF1, 0x844A, 0xAEF2, + 0x844B, 0xAEF3, 0x844C, 0xAEF5, 0x844D, 0xAEF6, 0x844E, 0xAEF7, 0x844F, 0xAEF9, 0x8450, 0xAEFA, 0x8451, 0xAEFB, 0x8452, 0xAEFD, + 0x8453, 0xAEFE, 0x8454, 0xAEFF, 0x8455, 0xAF00, 0x8456, 0xAF01, 0x8457, 0xAF02, 0x8458, 0xAF03, 0x8459, 0xAF04, 0x845A, 0xAF05, + 0x8461, 0xAF06, 0x8462, 0xAF09, 0x8463, 0xAF0A, 0x8464, 0xAF0B, 0x8465, 0xAF0C, 0x8466, 0xAF0E, 0x8467, 0xAF0F, 0x8468, 0xAF11, + 0x8469, 0xAF12, 0x846A, 0xAF13, 0x846B, 0xAF14, 0x846C, 0xAF15, 0x846D, 0xAF16, 0x846E, 0xAF17, 0x846F, 0xAF18, 0x8470, 0xAF19, + 0x8471, 0xAF1A, 0x8472, 0xAF1B, 0x8473, 0xAF1C, 0x8474, 0xAF1D, 0x8475, 0xAF1E, 0x8476, 0xAF1F, 0x8477, 0xAF20, 0x8478, 0xAF21, + 0x8479, 0xAF22, 0x847A, 0xAF23, 0x8481, 0xAF24, 0x8482, 0xAF25, 0x8483, 0xAF26, 0x8484, 0xAF27, 0x8485, 0xAF28, 0x8486, 0xAF29, + 0x8487, 0xAF2A, 0x8488, 0xAF2B, 0x8489, 0xAF2E, 0x848A, 0xAF2F, 0x848B, 0xAF31, 0x848C, 0xAF33, 0x848D, 0xAF35, 0x848E, 0xAF36, + 0x848F, 0xAF37, 0x8490, 0xAF38, 0x8491, 0xAF39, 0x8492, 0xAF3A, 0x8493, 0xAF3B, 0x8494, 0xAF3E, 0x8495, 0xAF40, 0x8496, 0xAF44, + 0x8497, 0xAF45, 0x8498, 0xAF46, 0x8499, 0xAF47, 0x849A, 0xAF4A, 0x849B, 0xAF4B, 0x849C, 0xAF4C, 0x849D, 0xAF4D, 0x849E, 0xAF4E, + 0x849F, 0xAF4F, 0x84A0, 0xAF51, 0x84A1, 0xAF52, 0x84A2, 0xAF53, 0x84A3, 0xAF54, 0x84A4, 0xAF55, 0x84A5, 0xAF56, 0x84A6, 0xAF57, + 0x84A7, 0xAF58, 0x84A8, 0xAF59, 0x84A9, 0xAF5A, 0x84AA, 0xAF5B, 0x84AB, 0xAF5E, 0x84AC, 0xAF5F, 0x84AD, 0xAF60, 0x84AE, 0xAF61, + 0x84AF, 0xAF62, 0x84B0, 0xAF63, 0x84B1, 0xAF66, 0x84B2, 0xAF67, 0x84B3, 0xAF68, 0x84B4, 0xAF69, 0x84B5, 0xAF6A, 0x84B6, 0xAF6B, + 0x84B7, 0xAF6C, 0x84B8, 0xAF6D, 0x84B9, 0xAF6E, 0x84BA, 0xAF6F, 0x84BB, 0xAF70, 0x84BC, 0xAF71, 0x84BD, 0xAF72, 0x84BE, 0xAF73, + 0x84BF, 0xAF74, 0x84C0, 0xAF75, 0x84C1, 0xAF76, 0x84C2, 0xAF77, 0x84C3, 0xAF78, 0x84C4, 0xAF7A, 0x84C5, 0xAF7B, 0x84C6, 0xAF7C, + 0x84C7, 0xAF7D, 0x84C8, 0xAF7E, 0x84C9, 0xAF7F, 0x84CA, 0xAF81, 0x84CB, 0xAF82, 0x84CC, 0xAF83, 0x84CD, 0xAF85, 0x84CE, 0xAF86, + 0x84CF, 0xAF87, 0x84D0, 0xAF89, 0x84D1, 0xAF8A, 0x84D2, 0xAF8B, 0x84D3, 0xAF8C, 0x84D4, 0xAF8D, 0x84D5, 0xAF8E, 0x84D6, 0xAF8F, + 0x84D7, 0xAF92, 0x84D8, 0xAF93, 0x84D9, 0xAF94, 0x84DA, 0xAF96, 0x84DB, 0xAF97, 0x84DC, 0xAF98, 0x84DD, 0xAF99, 0x84DE, 0xAF9A, + 0x84DF, 0xAF9B, 0x84E0, 0xAF9D, 0x84E1, 0xAF9E, 0x84E2, 0xAF9F, 0x84E3, 0xAFA0, 0x84E4, 0xAFA1, 0x84E5, 0xAFA2, 0x84E6, 0xAFA3, + 0x84E7, 0xAFA4, 0x84E8, 0xAFA5, 0x84E9, 0xAFA6, 0x84EA, 0xAFA7, 0x84EB, 0xAFA8, 0x84EC, 0xAFA9, 0x84ED, 0xAFAA, 0x84EE, 0xAFAB, + 0x84EF, 0xAFAC, 0x84F0, 0xAFAD, 0x84F1, 0xAFAE, 0x84F2, 0xAFAF, 0x84F3, 0xAFB0, 0x84F4, 0xAFB1, 0x84F5, 0xAFB2, 0x84F6, 0xAFB3, + 0x84F7, 0xAFB4, 0x84F8, 0xAFB5, 0x84F9, 0xAFB6, 0x84FA, 0xAFB7, 0x84FB, 0xAFBA, 0x84FC, 0xAFBB, 0x84FD, 0xAFBD, 0x84FE, 0xAFBE, + 0x8541, 0xAFBF, 0x8542, 0xAFC1, 0x8543, 0xAFC2, 0x8544, 0xAFC3, 0x8545, 0xAFC4, 0x8546, 0xAFC5, 0x8547, 0xAFC6, 0x8548, 0xAFCA, + 0x8549, 0xAFCC, 0x854A, 0xAFCF, 0x854B, 0xAFD0, 0x854C, 0xAFD1, 0x854D, 0xAFD2, 0x854E, 0xAFD3, 0x854F, 0xAFD5, 0x8550, 0xAFD6, + 0x8551, 0xAFD7, 0x8552, 0xAFD8, 0x8553, 0xAFD9, 0x8554, 0xAFDA, 0x8555, 0xAFDB, 0x8556, 0xAFDD, 0x8557, 0xAFDE, 0x8558, 0xAFDF, + 0x8559, 0xAFE0, 0x855A, 0xAFE1, 0x8561, 0xAFE2, 0x8562, 0xAFE3, 0x8563, 0xAFE4, 0x8564, 0xAFE5, 0x8565, 0xAFE6, 0x8566, 0xAFE7, + 0x8567, 0xAFEA, 0x8568, 0xAFEB, 0x8569, 0xAFEC, 0x856A, 0xAFED, 0x856B, 0xAFEE, 0x856C, 0xAFEF, 0x856D, 0xAFF2, 0x856E, 0xAFF3, + 0x856F, 0xAFF5, 0x8570, 0xAFF6, 0x8571, 0xAFF7, 0x8572, 0xAFF9, 0x8573, 0xAFFA, 0x8574, 0xAFFB, 0x8575, 0xAFFC, 0x8576, 0xAFFD, + 0x8577, 0xAFFE, 0x8578, 0xAFFF, 0x8579, 0xB002, 0x857A, 0xB003, 0x8581, 0xB005, 0x8582, 0xB006, 0x8583, 0xB007, 0x8584, 0xB008, + 0x8585, 0xB009, 0x8586, 0xB00A, 0x8587, 0xB00B, 0x8588, 0xB00D, 0x8589, 0xB00E, 0x858A, 0xB00F, 0x858B, 0xB011, 0x858C, 0xB012, + 0x858D, 0xB013, 0x858E, 0xB015, 0x858F, 0xB016, 0x8590, 0xB017, 0x8591, 0xB018, 0x8592, 0xB019, 0x8593, 0xB01A, 0x8594, 0xB01B, + 0x8595, 0xB01E, 0x8596, 0xB01F, 0x8597, 0xB020, 0x8598, 0xB021, 0x8599, 0xB022, 0x859A, 0xB023, 0x859B, 0xB024, 0x859C, 0xB025, + 0x859D, 0xB026, 0x859E, 0xB027, 0x859F, 0xB029, 0x85A0, 0xB02A, 0x85A1, 0xB02B, 0x85A2, 0xB02C, 0x85A3, 0xB02D, 0x85A4, 0xB02E, + 0x85A5, 0xB02F, 0x85A6, 0xB030, 0x85A7, 0xB031, 0x85A8, 0xB032, 0x85A9, 0xB033, 0x85AA, 0xB034, 0x85AB, 0xB035, 0x85AC, 0xB036, + 0x85AD, 0xB037, 0x85AE, 0xB038, 0x85AF, 0xB039, 0x85B0, 0xB03A, 0x85B1, 0xB03B, 0x85B2, 0xB03C, 0x85B3, 0xB03D, 0x85B4, 0xB03E, + 0x85B5, 0xB03F, 0x85B6, 0xB040, 0x85B7, 0xB041, 0x85B8, 0xB042, 0x85B9, 0xB043, 0x85BA, 0xB046, 0x85BB, 0xB047, 0x85BC, 0xB049, + 0x85BD, 0xB04B, 0x85BE, 0xB04D, 0x85BF, 0xB04F, 0x85C0, 0xB050, 0x85C1, 0xB051, 0x85C2, 0xB052, 0x85C3, 0xB056, 0x85C4, 0xB058, + 0x85C5, 0xB05A, 0x85C6, 0xB05B, 0x85C7, 0xB05C, 0x85C8, 0xB05E, 0x85C9, 0xB05F, 0x85CA, 0xB060, 0x85CB, 0xB061, 0x85CC, 0xB062, + 0x85CD, 0xB063, 0x85CE, 0xB064, 0x85CF, 0xB065, 0x85D0, 0xB066, 0x85D1, 0xB067, 0x85D2, 0xB068, 0x85D3, 0xB069, 0x85D4, 0xB06A, + 0x85D5, 0xB06B, 0x85D6, 0xB06C, 0x85D7, 0xB06D, 0x85D8, 0xB06E, 0x85D9, 0xB06F, 0x85DA, 0xB070, 0x85DB, 0xB071, 0x85DC, 0xB072, + 0x85DD, 0xB073, 0x85DE, 0xB074, 0x85DF, 0xB075, 0x85E0, 0xB076, 0x85E1, 0xB077, 0x85E2, 0xB078, 0x85E3, 0xB079, 0x85E4, 0xB07A, + 0x85E5, 0xB07B, 0x85E6, 0xB07E, 0x85E7, 0xB07F, 0x85E8, 0xB081, 0x85E9, 0xB082, 0x85EA, 0xB083, 0x85EB, 0xB085, 0x85EC, 0xB086, + 0x85ED, 0xB087, 0x85EE, 0xB088, 0x85EF, 0xB089, 0x85F0, 0xB08A, 0x85F1, 0xB08B, 0x85F2, 0xB08E, 0x85F3, 0xB090, 0x85F4, 0xB092, + 0x85F5, 0xB093, 0x85F6, 0xB094, 0x85F7, 0xB095, 0x85F8, 0xB096, 0x85F9, 0xB097, 0x85FA, 0xB09B, 0x85FB, 0xB09D, 0x85FC, 0xB09E, + 0x85FD, 0xB0A3, 0x85FE, 0xB0A4, 0x8641, 0xB0A5, 0x8642, 0xB0A6, 0x8643, 0xB0A7, 0x8644, 0xB0AA, 0x8645, 0xB0B0, 0x8646, 0xB0B2, + 0x8647, 0xB0B6, 0x8648, 0xB0B7, 0x8649, 0xB0B9, 0x864A, 0xB0BA, 0x864B, 0xB0BB, 0x864C, 0xB0BD, 0x864D, 0xB0BE, 0x864E, 0xB0BF, + 0x864F, 0xB0C0, 0x8650, 0xB0C1, 0x8651, 0xB0C2, 0x8652, 0xB0C3, 0x8653, 0xB0C6, 0x8654, 0xB0CA, 0x8655, 0xB0CB, 0x8656, 0xB0CC, + 0x8657, 0xB0CD, 0x8658, 0xB0CE, 0x8659, 0xB0CF, 0x865A, 0xB0D2, 0x8661, 0xB0D3, 0x8662, 0xB0D5, 0x8663, 0xB0D6, 0x8664, 0xB0D7, + 0x8665, 0xB0D9, 0x8666, 0xB0DA, 0x8667, 0xB0DB, 0x8668, 0xB0DC, 0x8669, 0xB0DD, 0x866A, 0xB0DE, 0x866B, 0xB0DF, 0x866C, 0xB0E1, + 0x866D, 0xB0E2, 0x866E, 0xB0E3, 0x866F, 0xB0E4, 0x8670, 0xB0E6, 0x8671, 0xB0E7, 0x8672, 0xB0E8, 0x8673, 0xB0E9, 0x8674, 0xB0EA, + 0x8675, 0xB0EB, 0x8676, 0xB0EC, 0x8677, 0xB0ED, 0x8678, 0xB0EE, 0x8679, 0xB0EF, 0x867A, 0xB0F0, 0x8681, 0xB0F1, 0x8682, 0xB0F2, + 0x8683, 0xB0F3, 0x8684, 0xB0F4, 0x8685, 0xB0F5, 0x8686, 0xB0F6, 0x8687, 0xB0F7, 0x8688, 0xB0F8, 0x8689, 0xB0F9, 0x868A, 0xB0FA, + 0x868B, 0xB0FB, 0x868C, 0xB0FC, 0x868D, 0xB0FD, 0x868E, 0xB0FE, 0x868F, 0xB0FF, 0x8690, 0xB100, 0x8691, 0xB101, 0x8692, 0xB102, + 0x8693, 0xB103, 0x8694, 0xB104, 0x8695, 0xB105, 0x8696, 0xB106, 0x8697, 0xB107, 0x8698, 0xB10A, 0x8699, 0xB10D, 0x869A, 0xB10E, + 0x869B, 0xB10F, 0x869C, 0xB111, 0x869D, 0xB114, 0x869E, 0xB115, 0x869F, 0xB116, 0x86A0, 0xB117, 0x86A1, 0xB11A, 0x86A2, 0xB11E, + 0x86A3, 0xB11F, 0x86A4, 0xB120, 0x86A5, 0xB121, 0x86A6, 0xB122, 0x86A7, 0xB126, 0x86A8, 0xB127, 0x86A9, 0xB129, 0x86AA, 0xB12A, + 0x86AB, 0xB12B, 0x86AC, 0xB12D, 0x86AD, 0xB12E, 0x86AE, 0xB12F, 0x86AF, 0xB130, 0x86B0, 0xB131, 0x86B1, 0xB132, 0x86B2, 0xB133, + 0x86B3, 0xB136, 0x86B4, 0xB13A, 0x86B5, 0xB13B, 0x86B6, 0xB13C, 0x86B7, 0xB13D, 0x86B8, 0xB13E, 0x86B9, 0xB13F, 0x86BA, 0xB142, + 0x86BB, 0xB143, 0x86BC, 0xB145, 0x86BD, 0xB146, 0x86BE, 0xB147, 0x86BF, 0xB149, 0x86C0, 0xB14A, 0x86C1, 0xB14B, 0x86C2, 0xB14C, + 0x86C3, 0xB14D, 0x86C4, 0xB14E, 0x86C5, 0xB14F, 0x86C6, 0xB152, 0x86C7, 0xB153, 0x86C8, 0xB156, 0x86C9, 0xB157, 0x86CA, 0xB159, + 0x86CB, 0xB15A, 0x86CC, 0xB15B, 0x86CD, 0xB15D, 0x86CE, 0xB15E, 0x86CF, 0xB15F, 0x86D0, 0xB161, 0x86D1, 0xB162, 0x86D2, 0xB163, + 0x86D3, 0xB164, 0x86D4, 0xB165, 0x86D5, 0xB166, 0x86D6, 0xB167, 0x86D7, 0xB168, 0x86D8, 0xB169, 0x86D9, 0xB16A, 0x86DA, 0xB16B, + 0x86DB, 0xB16C, 0x86DC, 0xB16D, 0x86DD, 0xB16E, 0x86DE, 0xB16F, 0x86DF, 0xB170, 0x86E0, 0xB171, 0x86E1, 0xB172, 0x86E2, 0xB173, + 0x86E3, 0xB174, 0x86E4, 0xB175, 0x86E5, 0xB176, 0x86E6, 0xB177, 0x86E7, 0xB17A, 0x86E8, 0xB17B, 0x86E9, 0xB17D, 0x86EA, 0xB17E, + 0x86EB, 0xB17F, 0x86EC, 0xB181, 0x86ED, 0xB183, 0x86EE, 0xB184, 0x86EF, 0xB185, 0x86F0, 0xB186, 0x86F1, 0xB187, 0x86F2, 0xB18A, + 0x86F3, 0xB18C, 0x86F4, 0xB18E, 0x86F5, 0xB18F, 0x86F6, 0xB190, 0x86F7, 0xB191, 0x86F8, 0xB195, 0x86F9, 0xB196, 0x86FA, 0xB197, + 0x86FB, 0xB199, 0x86FC, 0xB19A, 0x86FD, 0xB19B, 0x86FE, 0xB19D, 0x8741, 0xB19E, 0x8742, 0xB19F, 0x8743, 0xB1A0, 0x8744, 0xB1A1, + 0x8745, 0xB1A2, 0x8746, 0xB1A3, 0x8747, 0xB1A4, 0x8748, 0xB1A5, 0x8749, 0xB1A6, 0x874A, 0xB1A7, 0x874B, 0xB1A9, 0x874C, 0xB1AA, + 0x874D, 0xB1AB, 0x874E, 0xB1AC, 0x874F, 0xB1AD, 0x8750, 0xB1AE, 0x8751, 0xB1AF, 0x8752, 0xB1B0, 0x8753, 0xB1B1, 0x8754, 0xB1B2, + 0x8755, 0xB1B3, 0x8756, 0xB1B4, 0x8757, 0xB1B5, 0x8758, 0xB1B6, 0x8759, 0xB1B7, 0x875A, 0xB1B8, 0x8761, 0xB1B9, 0x8762, 0xB1BA, + 0x8763, 0xB1BB, 0x8764, 0xB1BC, 0x8765, 0xB1BD, 0x8766, 0xB1BE, 0x8767, 0xB1BF, 0x8768, 0xB1C0, 0x8769, 0xB1C1, 0x876A, 0xB1C2, + 0x876B, 0xB1C3, 0x876C, 0xB1C4, 0x876D, 0xB1C5, 0x876E, 0xB1C6, 0x876F, 0xB1C7, 0x8770, 0xB1C8, 0x8771, 0xB1C9, 0x8772, 0xB1CA, + 0x8773, 0xB1CB, 0x8774, 0xB1CD, 0x8775, 0xB1CE, 0x8776, 0xB1CF, 0x8777, 0xB1D1, 0x8778, 0xB1D2, 0x8779, 0xB1D3, 0x877A, 0xB1D5, + 0x8781, 0xB1D6, 0x8782, 0xB1D7, 0x8783, 0xB1D8, 0x8784, 0xB1D9, 0x8785, 0xB1DA, 0x8786, 0xB1DB, 0x8787, 0xB1DE, 0x8788, 0xB1E0, + 0x8789, 0xB1E1, 0x878A, 0xB1E2, 0x878B, 0xB1E3, 0x878C, 0xB1E4, 0x878D, 0xB1E5, 0x878E, 0xB1E6, 0x878F, 0xB1E7, 0x8790, 0xB1EA, + 0x8791, 0xB1EB, 0x8792, 0xB1ED, 0x8793, 0xB1EE, 0x8794, 0xB1EF, 0x8795, 0xB1F1, 0x8796, 0xB1F2, 0x8797, 0xB1F3, 0x8798, 0xB1F4, + 0x8799, 0xB1F5, 0x879A, 0xB1F6, 0x879B, 0xB1F7, 0x879C, 0xB1F8, 0x879D, 0xB1FA, 0x879E, 0xB1FC, 0x879F, 0xB1FE, 0x87A0, 0xB1FF, + 0x87A1, 0xB200, 0x87A2, 0xB201, 0x87A3, 0xB202, 0x87A4, 0xB203, 0x87A5, 0xB206, 0x87A6, 0xB207, 0x87A7, 0xB209, 0x87A8, 0xB20A, + 0x87A9, 0xB20D, 0x87AA, 0xB20E, 0x87AB, 0xB20F, 0x87AC, 0xB210, 0x87AD, 0xB211, 0x87AE, 0xB212, 0x87AF, 0xB213, 0x87B0, 0xB216, + 0x87B1, 0xB218, 0x87B2, 0xB21A, 0x87B3, 0xB21B, 0x87B4, 0xB21C, 0x87B5, 0xB21D, 0x87B6, 0xB21E, 0x87B7, 0xB21F, 0x87B8, 0xB221, + 0x87B9, 0xB222, 0x87BA, 0xB223, 0x87BB, 0xB224, 0x87BC, 0xB225, 0x87BD, 0xB226, 0x87BE, 0xB227, 0x87BF, 0xB228, 0x87C0, 0xB229, + 0x87C1, 0xB22A, 0x87C2, 0xB22B, 0x87C3, 0xB22C, 0x87C4, 0xB22D, 0x87C5, 0xB22E, 0x87C6, 0xB22F, 0x87C7, 0xB230, 0x87C8, 0xB231, + 0x87C9, 0xB232, 0x87CA, 0xB233, 0x87CB, 0xB235, 0x87CC, 0xB236, 0x87CD, 0xB237, 0x87CE, 0xB238, 0x87CF, 0xB239, 0x87D0, 0xB23A, + 0x87D1, 0xB23B, 0x87D2, 0xB23D, 0x87D3, 0xB23E, 0x87D4, 0xB23F, 0x87D5, 0xB240, 0x87D6, 0xB241, 0x87D7, 0xB242, 0x87D8, 0xB243, + 0x87D9, 0xB244, 0x87DA, 0xB245, 0x87DB, 0xB246, 0x87DC, 0xB247, 0x87DD, 0xB248, 0x87DE, 0xB249, 0x87DF, 0xB24A, 0x87E0, 0xB24B, + 0x87E1, 0xB24C, 0x87E2, 0xB24D, 0x87E3, 0xB24E, 0x87E4, 0xB24F, 0x87E5, 0xB250, 0x87E6, 0xB251, 0x87E7, 0xB252, 0x87E8, 0xB253, + 0x87E9, 0xB254, 0x87EA, 0xB255, 0x87EB, 0xB256, 0x87EC, 0xB257, 0x87ED, 0xB259, 0x87EE, 0xB25A, 0x87EF, 0xB25B, 0x87F0, 0xB25D, + 0x87F1, 0xB25E, 0x87F2, 0xB25F, 0x87F3, 0xB261, 0x87F4, 0xB262, 0x87F5, 0xB263, 0x87F6, 0xB264, 0x87F7, 0xB265, 0x87F8, 0xB266, + 0x87F9, 0xB267, 0x87FA, 0xB26A, 0x87FB, 0xB26B, 0x87FC, 0xB26C, 0x87FD, 0xB26D, 0x87FE, 0xB26E, 0x8841, 0xB26F, 0x8842, 0xB270, + 0x8843, 0xB271, 0x8844, 0xB272, 0x8845, 0xB273, 0x8846, 0xB276, 0x8847, 0xB277, 0x8848, 0xB278, 0x8849, 0xB279, 0x884A, 0xB27A, + 0x884B, 0xB27B, 0x884C, 0xB27D, 0x884D, 0xB27E, 0x884E, 0xB27F, 0x884F, 0xB280, 0x8850, 0xB281, 0x8851, 0xB282, 0x8852, 0xB283, + 0x8853, 0xB286, 0x8854, 0xB287, 0x8855, 0xB288, 0x8856, 0xB28A, 0x8857, 0xB28B, 0x8858, 0xB28C, 0x8859, 0xB28D, 0x885A, 0xB28E, + 0x8861, 0xB28F, 0x8862, 0xB292, 0x8863, 0xB293, 0x8864, 0xB295, 0x8865, 0xB296, 0x8866, 0xB297, 0x8867, 0xB29B, 0x8868, 0xB29C, + 0x8869, 0xB29D, 0x886A, 0xB29E, 0x886B, 0xB29F, 0x886C, 0xB2A2, 0x886D, 0xB2A4, 0x886E, 0xB2A7, 0x886F, 0xB2A8, 0x8870, 0xB2A9, + 0x8871, 0xB2AB, 0x8872, 0xB2AD, 0x8873, 0xB2AE, 0x8874, 0xB2AF, 0x8875, 0xB2B1, 0x8876, 0xB2B2, 0x8877, 0xB2B3, 0x8878, 0xB2B5, + 0x8879, 0xB2B6, 0x887A, 0xB2B7, 0x8881, 0xB2B8, 0x8882, 0xB2B9, 0x8883, 0xB2BA, 0x8884, 0xB2BB, 0x8885, 0xB2BC, 0x8886, 0xB2BD, + 0x8887, 0xB2BE, 0x8888, 0xB2BF, 0x8889, 0xB2C0, 0x888A, 0xB2C1, 0x888B, 0xB2C2, 0x888C, 0xB2C3, 0x888D, 0xB2C4, 0x888E, 0xB2C5, + 0x888F, 0xB2C6, 0x8890, 0xB2C7, 0x8891, 0xB2CA, 0x8892, 0xB2CB, 0x8893, 0xB2CD, 0x8894, 0xB2CE, 0x8895, 0xB2CF, 0x8896, 0xB2D1, + 0x8897, 0xB2D3, 0x8898, 0xB2D4, 0x8899, 0xB2D5, 0x889A, 0xB2D6, 0x889B, 0xB2D7, 0x889C, 0xB2DA, 0x889D, 0xB2DC, 0x889E, 0xB2DE, + 0x889F, 0xB2DF, 0x88A0, 0xB2E0, 0x88A1, 0xB2E1, 0x88A2, 0xB2E3, 0x88A3, 0xB2E7, 0x88A4, 0xB2E9, 0x88A5, 0xB2EA, 0x88A6, 0xB2F0, + 0x88A7, 0xB2F1, 0x88A8, 0xB2F2, 0x88A9, 0xB2F6, 0x88AA, 0xB2FC, 0x88AB, 0xB2FD, 0x88AC, 0xB2FE, 0x88AD, 0xB302, 0x88AE, 0xB303, + 0x88AF, 0xB305, 0x88B0, 0xB306, 0x88B1, 0xB307, 0x88B2, 0xB309, 0x88B3, 0xB30A, 0x88B4, 0xB30B, 0x88B5, 0xB30C, 0x88B6, 0xB30D, + 0x88B7, 0xB30E, 0x88B8, 0xB30F, 0x88B9, 0xB312, 0x88BA, 0xB316, 0x88BB, 0xB317, 0x88BC, 0xB318, 0x88BD, 0xB319, 0x88BE, 0xB31A, + 0x88BF, 0xB31B, 0x88C0, 0xB31D, 0x88C1, 0xB31E, 0x88C2, 0xB31F, 0x88C3, 0xB320, 0x88C4, 0xB321, 0x88C5, 0xB322, 0x88C6, 0xB323, + 0x88C7, 0xB324, 0x88C8, 0xB325, 0x88C9, 0xB326, 0x88CA, 0xB327, 0x88CB, 0xB328, 0x88CC, 0xB329, 0x88CD, 0xB32A, 0x88CE, 0xB32B, + 0x88CF, 0xB32C, 0x88D0, 0xB32D, 0x88D1, 0xB32E, 0x88D2, 0xB32F, 0x88D3, 0xB330, 0x88D4, 0xB331, 0x88D5, 0xB332, 0x88D6, 0xB333, + 0x88D7, 0xB334, 0x88D8, 0xB335, 0x88D9, 0xB336, 0x88DA, 0xB337, 0x88DB, 0xB338, 0x88DC, 0xB339, 0x88DD, 0xB33A, 0x88DE, 0xB33B, + 0x88DF, 0xB33C, 0x88E0, 0xB33D, 0x88E1, 0xB33E, 0x88E2, 0xB33F, 0x88E3, 0xB340, 0x88E4, 0xB341, 0x88E5, 0xB342, 0x88E6, 0xB343, + 0x88E7, 0xB344, 0x88E8, 0xB345, 0x88E9, 0xB346, 0x88EA, 0xB347, 0x88EB, 0xB348, 0x88EC, 0xB349, 0x88ED, 0xB34A, 0x88EE, 0xB34B, + 0x88EF, 0xB34C, 0x88F0, 0xB34D, 0x88F1, 0xB34E, 0x88F2, 0xB34F, 0x88F3, 0xB350, 0x88F4, 0xB351, 0x88F5, 0xB352, 0x88F6, 0xB353, + 0x88F7, 0xB357, 0x88F8, 0xB359, 0x88F9, 0xB35A, 0x88FA, 0xB35D, 0x88FB, 0xB360, 0x88FC, 0xB361, 0x88FD, 0xB362, 0x88FE, 0xB363, + 0x8941, 0xB366, 0x8942, 0xB368, 0x8943, 0xB36A, 0x8944, 0xB36C, 0x8945, 0xB36D, 0x8946, 0xB36F, 0x8947, 0xB372, 0x8948, 0xB373, + 0x8949, 0xB375, 0x894A, 0xB376, 0x894B, 0xB377, 0x894C, 0xB379, 0x894D, 0xB37A, 0x894E, 0xB37B, 0x894F, 0xB37C, 0x8950, 0xB37D, + 0x8951, 0xB37E, 0x8952, 0xB37F, 0x8953, 0xB382, 0x8954, 0xB386, 0x8955, 0xB387, 0x8956, 0xB388, 0x8957, 0xB389, 0x8958, 0xB38A, + 0x8959, 0xB38B, 0x895A, 0xB38D, 0x8961, 0xB38E, 0x8962, 0xB38F, 0x8963, 0xB391, 0x8964, 0xB392, 0x8965, 0xB393, 0x8966, 0xB395, + 0x8967, 0xB396, 0x8968, 0xB397, 0x8969, 0xB398, 0x896A, 0xB399, 0x896B, 0xB39A, 0x896C, 0xB39B, 0x896D, 0xB39C, 0x896E, 0xB39D, + 0x896F, 0xB39E, 0x8970, 0xB39F, 0x8971, 0xB3A2, 0x8972, 0xB3A3, 0x8973, 0xB3A4, 0x8974, 0xB3A5, 0x8975, 0xB3A6, 0x8976, 0xB3A7, + 0x8977, 0xB3A9, 0x8978, 0xB3AA, 0x8979, 0xB3AB, 0x897A, 0xB3AD, 0x8981, 0xB3AE, 0x8982, 0xB3AF, 0x8983, 0xB3B0, 0x8984, 0xB3B1, + 0x8985, 0xB3B2, 0x8986, 0xB3B3, 0x8987, 0xB3B4, 0x8988, 0xB3B5, 0x8989, 0xB3B6, 0x898A, 0xB3B7, 0x898B, 0xB3B8, 0x898C, 0xB3B9, + 0x898D, 0xB3BA, 0x898E, 0xB3BB, 0x898F, 0xB3BC, 0x8990, 0xB3BD, 0x8991, 0xB3BE, 0x8992, 0xB3BF, 0x8993, 0xB3C0, 0x8994, 0xB3C1, + 0x8995, 0xB3C2, 0x8996, 0xB3C3, 0x8997, 0xB3C6, 0x8998, 0xB3C7, 0x8999, 0xB3C9, 0x899A, 0xB3CA, 0x899B, 0xB3CD, 0x899C, 0xB3CF, + 0x899D, 0xB3D1, 0x899E, 0xB3D2, 0x899F, 0xB3D3, 0x89A0, 0xB3D6, 0x89A1, 0xB3D8, 0x89A2, 0xB3DA, 0x89A3, 0xB3DC, 0x89A4, 0xB3DE, + 0x89A5, 0xB3DF, 0x89A6, 0xB3E1, 0x89A7, 0xB3E2, 0x89A8, 0xB3E3, 0x89A9, 0xB3E5, 0x89AA, 0xB3E6, 0x89AB, 0xB3E7, 0x89AC, 0xB3E9, + 0x89AD, 0xB3EA, 0x89AE, 0xB3EB, 0x89AF, 0xB3EC, 0x89B0, 0xB3ED, 0x89B1, 0xB3EE, 0x89B2, 0xB3EF, 0x89B3, 0xB3F0, 0x89B4, 0xB3F1, + 0x89B5, 0xB3F2, 0x89B6, 0xB3F3, 0x89B7, 0xB3F4, 0x89B8, 0xB3F5, 0x89B9, 0xB3F6, 0x89BA, 0xB3F7, 0x89BB, 0xB3F8, 0x89BC, 0xB3F9, + 0x89BD, 0xB3FA, 0x89BE, 0xB3FB, 0x89BF, 0xB3FD, 0x89C0, 0xB3FE, 0x89C1, 0xB3FF, 0x89C2, 0xB400, 0x89C3, 0xB401, 0x89C4, 0xB402, + 0x89C5, 0xB403, 0x89C6, 0xB404, 0x89C7, 0xB405, 0x89C8, 0xB406, 0x89C9, 0xB407, 0x89CA, 0xB408, 0x89CB, 0xB409, 0x89CC, 0xB40A, + 0x89CD, 0xB40B, 0x89CE, 0xB40C, 0x89CF, 0xB40D, 0x89D0, 0xB40E, 0x89D1, 0xB40F, 0x89D2, 0xB411, 0x89D3, 0xB412, 0x89D4, 0xB413, + 0x89D5, 0xB414, 0x89D6, 0xB415, 0x89D7, 0xB416, 0x89D8, 0xB417, 0x89D9, 0xB419, 0x89DA, 0xB41A, 0x89DB, 0xB41B, 0x89DC, 0xB41D, + 0x89DD, 0xB41E, 0x89DE, 0xB41F, 0x89DF, 0xB421, 0x89E0, 0xB422, 0x89E1, 0xB423, 0x89E2, 0xB424, 0x89E3, 0xB425, 0x89E4, 0xB426, + 0x89E5, 0xB427, 0x89E6, 0xB42A, 0x89E7, 0xB42C, 0x89E8, 0xB42D, 0x89E9, 0xB42E, 0x89EA, 0xB42F, 0x89EB, 0xB430, 0x89EC, 0xB431, + 0x89ED, 0xB432, 0x89EE, 0xB433, 0x89EF, 0xB435, 0x89F0, 0xB436, 0x89F1, 0xB437, 0x89F2, 0xB438, 0x89F3, 0xB439, 0x89F4, 0xB43A, + 0x89F5, 0xB43B, 0x89F6, 0xB43C, 0x89F7, 0xB43D, 0x89F8, 0xB43E, 0x89F9, 0xB43F, 0x89FA, 0xB440, 0x89FB, 0xB441, 0x89FC, 0xB442, + 0x89FD, 0xB443, 0x89FE, 0xB444, 0x8A41, 0xB445, 0x8A42, 0xB446, 0x8A43, 0xB447, 0x8A44, 0xB448, 0x8A45, 0xB449, 0x8A46, 0xB44A, + 0x8A47, 0xB44B, 0x8A48, 0xB44C, 0x8A49, 0xB44D, 0x8A4A, 0xB44E, 0x8A4B, 0xB44F, 0x8A4C, 0xB452, 0x8A4D, 0xB453, 0x8A4E, 0xB455, + 0x8A4F, 0xB456, 0x8A50, 0xB457, 0x8A51, 0xB459, 0x8A52, 0xB45A, 0x8A53, 0xB45B, 0x8A54, 0xB45C, 0x8A55, 0xB45D, 0x8A56, 0xB45E, + 0x8A57, 0xB45F, 0x8A58, 0xB462, 0x8A59, 0xB464, 0x8A5A, 0xB466, 0x8A61, 0xB467, 0x8A62, 0xB468, 0x8A63, 0xB469, 0x8A64, 0xB46A, + 0x8A65, 0xB46B, 0x8A66, 0xB46D, 0x8A67, 0xB46E, 0x8A68, 0xB46F, 0x8A69, 0xB470, 0x8A6A, 0xB471, 0x8A6B, 0xB472, 0x8A6C, 0xB473, + 0x8A6D, 0xB474, 0x8A6E, 0xB475, 0x8A6F, 0xB476, 0x8A70, 0xB477, 0x8A71, 0xB478, 0x8A72, 0xB479, 0x8A73, 0xB47A, 0x8A74, 0xB47B, + 0x8A75, 0xB47C, 0x8A76, 0xB47D, 0x8A77, 0xB47E, 0x8A78, 0xB47F, 0x8A79, 0xB481, 0x8A7A, 0xB482, 0x8A81, 0xB483, 0x8A82, 0xB484, + 0x8A83, 0xB485, 0x8A84, 0xB486, 0x8A85, 0xB487, 0x8A86, 0xB489, 0x8A87, 0xB48A, 0x8A88, 0xB48B, 0x8A89, 0xB48C, 0x8A8A, 0xB48D, + 0x8A8B, 0xB48E, 0x8A8C, 0xB48F, 0x8A8D, 0xB490, 0x8A8E, 0xB491, 0x8A8F, 0xB492, 0x8A90, 0xB493, 0x8A91, 0xB494, 0x8A92, 0xB495, + 0x8A93, 0xB496, 0x8A94, 0xB497, 0x8A95, 0xB498, 0x8A96, 0xB499, 0x8A97, 0xB49A, 0x8A98, 0xB49B, 0x8A99, 0xB49C, 0x8A9A, 0xB49E, + 0x8A9B, 0xB49F, 0x8A9C, 0xB4A0, 0x8A9D, 0xB4A1, 0x8A9E, 0xB4A2, 0x8A9F, 0xB4A3, 0x8AA0, 0xB4A5, 0x8AA1, 0xB4A6, 0x8AA2, 0xB4A7, + 0x8AA3, 0xB4A9, 0x8AA4, 0xB4AA, 0x8AA5, 0xB4AB, 0x8AA6, 0xB4AD, 0x8AA7, 0xB4AE, 0x8AA8, 0xB4AF, 0x8AA9, 0xB4B0, 0x8AAA, 0xB4B1, + 0x8AAB, 0xB4B2, 0x8AAC, 0xB4B3, 0x8AAD, 0xB4B4, 0x8AAE, 0xB4B6, 0x8AAF, 0xB4B8, 0x8AB0, 0xB4BA, 0x8AB1, 0xB4BB, 0x8AB2, 0xB4BC, + 0x8AB3, 0xB4BD, 0x8AB4, 0xB4BE, 0x8AB5, 0xB4BF, 0x8AB6, 0xB4C1, 0x8AB7, 0xB4C2, 0x8AB8, 0xB4C3, 0x8AB9, 0xB4C5, 0x8ABA, 0xB4C6, + 0x8ABB, 0xB4C7, 0x8ABC, 0xB4C9, 0x8ABD, 0xB4CA, 0x8ABE, 0xB4CB, 0x8ABF, 0xB4CC, 0x8AC0, 0xB4CD, 0x8AC1, 0xB4CE, 0x8AC2, 0xB4CF, + 0x8AC3, 0xB4D1, 0x8AC4, 0xB4D2, 0x8AC5, 0xB4D3, 0x8AC6, 0xB4D4, 0x8AC7, 0xB4D6, 0x8AC8, 0xB4D7, 0x8AC9, 0xB4D8, 0x8ACA, 0xB4D9, + 0x8ACB, 0xB4DA, 0x8ACC, 0xB4DB, 0x8ACD, 0xB4DE, 0x8ACE, 0xB4DF, 0x8ACF, 0xB4E1, 0x8AD0, 0xB4E2, 0x8AD1, 0xB4E5, 0x8AD2, 0xB4E7, + 0x8AD3, 0xB4E8, 0x8AD4, 0xB4E9, 0x8AD5, 0xB4EA, 0x8AD6, 0xB4EB, 0x8AD7, 0xB4EE, 0x8AD8, 0xB4F0, 0x8AD9, 0xB4F2, 0x8ADA, 0xB4F3, + 0x8ADB, 0xB4F4, 0x8ADC, 0xB4F5, 0x8ADD, 0xB4F6, 0x8ADE, 0xB4F7, 0x8ADF, 0xB4F9, 0x8AE0, 0xB4FA, 0x8AE1, 0xB4FB, 0x8AE2, 0xB4FC, + 0x8AE3, 0xB4FD, 0x8AE4, 0xB4FE, 0x8AE5, 0xB4FF, 0x8AE6, 0xB500, 0x8AE7, 0xB501, 0x8AE8, 0xB502, 0x8AE9, 0xB503, 0x8AEA, 0xB504, + 0x8AEB, 0xB505, 0x8AEC, 0xB506, 0x8AED, 0xB507, 0x8AEE, 0xB508, 0x8AEF, 0xB509, 0x8AF0, 0xB50A, 0x8AF1, 0xB50B, 0x8AF2, 0xB50C, + 0x8AF3, 0xB50D, 0x8AF4, 0xB50E, 0x8AF5, 0xB50F, 0x8AF6, 0xB510, 0x8AF7, 0xB511, 0x8AF8, 0xB512, 0x8AF9, 0xB513, 0x8AFA, 0xB516, + 0x8AFB, 0xB517, 0x8AFC, 0xB519, 0x8AFD, 0xB51A, 0x8AFE, 0xB51D, 0x8B41, 0xB51E, 0x8B42, 0xB51F, 0x8B43, 0xB520, 0x8B44, 0xB521, + 0x8B45, 0xB522, 0x8B46, 0xB523, 0x8B47, 0xB526, 0x8B48, 0xB52B, 0x8B49, 0xB52C, 0x8B4A, 0xB52D, 0x8B4B, 0xB52E, 0x8B4C, 0xB52F, + 0x8B4D, 0xB532, 0x8B4E, 0xB533, 0x8B4F, 0xB535, 0x8B50, 0xB536, 0x8B51, 0xB537, 0x8B52, 0xB539, 0x8B53, 0xB53A, 0x8B54, 0xB53B, + 0x8B55, 0xB53C, 0x8B56, 0xB53D, 0x8B57, 0xB53E, 0x8B58, 0xB53F, 0x8B59, 0xB542, 0x8B5A, 0xB546, 0x8B61, 0xB547, 0x8B62, 0xB548, + 0x8B63, 0xB549, 0x8B64, 0xB54A, 0x8B65, 0xB54E, 0x8B66, 0xB54F, 0x8B67, 0xB551, 0x8B68, 0xB552, 0x8B69, 0xB553, 0x8B6A, 0xB555, + 0x8B6B, 0xB556, 0x8B6C, 0xB557, 0x8B6D, 0xB558, 0x8B6E, 0xB559, 0x8B6F, 0xB55A, 0x8B70, 0xB55B, 0x8B71, 0xB55E, 0x8B72, 0xB562, + 0x8B73, 0xB563, 0x8B74, 0xB564, 0x8B75, 0xB565, 0x8B76, 0xB566, 0x8B77, 0xB567, 0x8B78, 0xB568, 0x8B79, 0xB569, 0x8B7A, 0xB56A, + 0x8B81, 0xB56B, 0x8B82, 0xB56C, 0x8B83, 0xB56D, 0x8B84, 0xB56E, 0x8B85, 0xB56F, 0x8B86, 0xB570, 0x8B87, 0xB571, 0x8B88, 0xB572, + 0x8B89, 0xB573, 0x8B8A, 0xB574, 0x8B8B, 0xB575, 0x8B8C, 0xB576, 0x8B8D, 0xB577, 0x8B8E, 0xB578, 0x8B8F, 0xB579, 0x8B90, 0xB57A, + 0x8B91, 0xB57B, 0x8B92, 0xB57C, 0x8B93, 0xB57D, 0x8B94, 0xB57E, 0x8B95, 0xB57F, 0x8B96, 0xB580, 0x8B97, 0xB581, 0x8B98, 0xB582, + 0x8B99, 0xB583, 0x8B9A, 0xB584, 0x8B9B, 0xB585, 0x8B9C, 0xB586, 0x8B9D, 0xB587, 0x8B9E, 0xB588, 0x8B9F, 0xB589, 0x8BA0, 0xB58A, + 0x8BA1, 0xB58B, 0x8BA2, 0xB58C, 0x8BA3, 0xB58D, 0x8BA4, 0xB58E, 0x8BA5, 0xB58F, 0x8BA6, 0xB590, 0x8BA7, 0xB591, 0x8BA8, 0xB592, + 0x8BA9, 0xB593, 0x8BAA, 0xB594, 0x8BAB, 0xB595, 0x8BAC, 0xB596, 0x8BAD, 0xB597, 0x8BAE, 0xB598, 0x8BAF, 0xB599, 0x8BB0, 0xB59A, + 0x8BB1, 0xB59B, 0x8BB2, 0xB59C, 0x8BB3, 0xB59D, 0x8BB4, 0xB59E, 0x8BB5, 0xB59F, 0x8BB6, 0xB5A2, 0x8BB7, 0xB5A3, 0x8BB8, 0xB5A5, + 0x8BB9, 0xB5A6, 0x8BBA, 0xB5A7, 0x8BBB, 0xB5A9, 0x8BBC, 0xB5AC, 0x8BBD, 0xB5AD, 0x8BBE, 0xB5AE, 0x8BBF, 0xB5AF, 0x8BC0, 0xB5B2, + 0x8BC1, 0xB5B6, 0x8BC2, 0xB5B7, 0x8BC3, 0xB5B8, 0x8BC4, 0xB5B9, 0x8BC5, 0xB5BA, 0x8BC6, 0xB5BE, 0x8BC7, 0xB5BF, 0x8BC8, 0xB5C1, + 0x8BC9, 0xB5C2, 0x8BCA, 0xB5C3, 0x8BCB, 0xB5C5, 0x8BCC, 0xB5C6, 0x8BCD, 0xB5C7, 0x8BCE, 0xB5C8, 0x8BCF, 0xB5C9, 0x8BD0, 0xB5CA, + 0x8BD1, 0xB5CB, 0x8BD2, 0xB5CE, 0x8BD3, 0xB5D2, 0x8BD4, 0xB5D3, 0x8BD5, 0xB5D4, 0x8BD6, 0xB5D5, 0x8BD7, 0xB5D6, 0x8BD8, 0xB5D7, + 0x8BD9, 0xB5D9, 0x8BDA, 0xB5DA, 0x8BDB, 0xB5DB, 0x8BDC, 0xB5DC, 0x8BDD, 0xB5DD, 0x8BDE, 0xB5DE, 0x8BDF, 0xB5DF, 0x8BE0, 0xB5E0, + 0x8BE1, 0xB5E1, 0x8BE2, 0xB5E2, 0x8BE3, 0xB5E3, 0x8BE4, 0xB5E4, 0x8BE5, 0xB5E5, 0x8BE6, 0xB5E6, 0x8BE7, 0xB5E7, 0x8BE8, 0xB5E8, + 0x8BE9, 0xB5E9, 0x8BEA, 0xB5EA, 0x8BEB, 0xB5EB, 0x8BEC, 0xB5ED, 0x8BED, 0xB5EE, 0x8BEE, 0xB5EF, 0x8BEF, 0xB5F0, 0x8BF0, 0xB5F1, + 0x8BF1, 0xB5F2, 0x8BF2, 0xB5F3, 0x8BF3, 0xB5F4, 0x8BF4, 0xB5F5, 0x8BF5, 0xB5F6, 0x8BF6, 0xB5F7, 0x8BF7, 0xB5F8, 0x8BF8, 0xB5F9, + 0x8BF9, 0xB5FA, 0x8BFA, 0xB5FB, 0x8BFB, 0xB5FC, 0x8BFC, 0xB5FD, 0x8BFD, 0xB5FE, 0x8BFE, 0xB5FF, 0x8C41, 0xB600, 0x8C42, 0xB601, + 0x8C43, 0xB602, 0x8C44, 0xB603, 0x8C45, 0xB604, 0x8C46, 0xB605, 0x8C47, 0xB606, 0x8C48, 0xB607, 0x8C49, 0xB608, 0x8C4A, 0xB609, + 0x8C4B, 0xB60A, 0x8C4C, 0xB60B, 0x8C4D, 0xB60C, 0x8C4E, 0xB60D, 0x8C4F, 0xB60E, 0x8C50, 0xB60F, 0x8C51, 0xB612, 0x8C52, 0xB613, + 0x8C53, 0xB615, 0x8C54, 0xB616, 0x8C55, 0xB617, 0x8C56, 0xB619, 0x8C57, 0xB61A, 0x8C58, 0xB61B, 0x8C59, 0xB61C, 0x8C5A, 0xB61D, + 0x8C61, 0xB61E, 0x8C62, 0xB61F, 0x8C63, 0xB620, 0x8C64, 0xB621, 0x8C65, 0xB622, 0x8C66, 0xB623, 0x8C67, 0xB624, 0x8C68, 0xB626, + 0x8C69, 0xB627, 0x8C6A, 0xB628, 0x8C6B, 0xB629, 0x8C6C, 0xB62A, 0x8C6D, 0xB62B, 0x8C6E, 0xB62D, 0x8C6F, 0xB62E, 0x8C70, 0xB62F, + 0x8C71, 0xB630, 0x8C72, 0xB631, 0x8C73, 0xB632, 0x8C74, 0xB633, 0x8C75, 0xB635, 0x8C76, 0xB636, 0x8C77, 0xB637, 0x8C78, 0xB638, + 0x8C79, 0xB639, 0x8C7A, 0xB63A, 0x8C81, 0xB63B, 0x8C82, 0xB63C, 0x8C83, 0xB63D, 0x8C84, 0xB63E, 0x8C85, 0xB63F, 0x8C86, 0xB640, + 0x8C87, 0xB641, 0x8C88, 0xB642, 0x8C89, 0xB643, 0x8C8A, 0xB644, 0x8C8B, 0xB645, 0x8C8C, 0xB646, 0x8C8D, 0xB647, 0x8C8E, 0xB649, + 0x8C8F, 0xB64A, 0x8C90, 0xB64B, 0x8C91, 0xB64C, 0x8C92, 0xB64D, 0x8C93, 0xB64E, 0x8C94, 0xB64F, 0x8C95, 0xB650, 0x8C96, 0xB651, + 0x8C97, 0xB652, 0x8C98, 0xB653, 0x8C99, 0xB654, 0x8C9A, 0xB655, 0x8C9B, 0xB656, 0x8C9C, 0xB657, 0x8C9D, 0xB658, 0x8C9E, 0xB659, + 0x8C9F, 0xB65A, 0x8CA0, 0xB65B, 0x8CA1, 0xB65C, 0x8CA2, 0xB65D, 0x8CA3, 0xB65E, 0x8CA4, 0xB65F, 0x8CA5, 0xB660, 0x8CA6, 0xB661, + 0x8CA7, 0xB662, 0x8CA8, 0xB663, 0x8CA9, 0xB665, 0x8CAA, 0xB666, 0x8CAB, 0xB667, 0x8CAC, 0xB669, 0x8CAD, 0xB66A, 0x8CAE, 0xB66B, + 0x8CAF, 0xB66C, 0x8CB0, 0xB66D, 0x8CB1, 0xB66E, 0x8CB2, 0xB66F, 0x8CB3, 0xB670, 0x8CB4, 0xB671, 0x8CB5, 0xB672, 0x8CB6, 0xB673, + 0x8CB7, 0xB674, 0x8CB8, 0xB675, 0x8CB9, 0xB676, 0x8CBA, 0xB677, 0x8CBB, 0xB678, 0x8CBC, 0xB679, 0x8CBD, 0xB67A, 0x8CBE, 0xB67B, + 0x8CBF, 0xB67C, 0x8CC0, 0xB67D, 0x8CC1, 0xB67E, 0x8CC2, 0xB67F, 0x8CC3, 0xB680, 0x8CC4, 0xB681, 0x8CC5, 0xB682, 0x8CC6, 0xB683, + 0x8CC7, 0xB684, 0x8CC8, 0xB685, 0x8CC9, 0xB686, 0x8CCA, 0xB687, 0x8CCB, 0xB688, 0x8CCC, 0xB689, 0x8CCD, 0xB68A, 0x8CCE, 0xB68B, + 0x8CCF, 0xB68C, 0x8CD0, 0xB68D, 0x8CD1, 0xB68E, 0x8CD2, 0xB68F, 0x8CD3, 0xB690, 0x8CD4, 0xB691, 0x8CD5, 0xB692, 0x8CD6, 0xB693, + 0x8CD7, 0xB694, 0x8CD8, 0xB695, 0x8CD9, 0xB696, 0x8CDA, 0xB697, 0x8CDB, 0xB698, 0x8CDC, 0xB699, 0x8CDD, 0xB69A, 0x8CDE, 0xB69B, + 0x8CDF, 0xB69E, 0x8CE0, 0xB69F, 0x8CE1, 0xB6A1, 0x8CE2, 0xB6A2, 0x8CE3, 0xB6A3, 0x8CE4, 0xB6A5, 0x8CE5, 0xB6A6, 0x8CE6, 0xB6A7, + 0x8CE7, 0xB6A8, 0x8CE8, 0xB6A9, 0x8CE9, 0xB6AA, 0x8CEA, 0xB6AD, 0x8CEB, 0xB6AE, 0x8CEC, 0xB6AF, 0x8CED, 0xB6B0, 0x8CEE, 0xB6B2, + 0x8CEF, 0xB6B3, 0x8CF0, 0xB6B4, 0x8CF1, 0xB6B5, 0x8CF2, 0xB6B6, 0x8CF3, 0xB6B7, 0x8CF4, 0xB6B8, 0x8CF5, 0xB6B9, 0x8CF6, 0xB6BA, + 0x8CF7, 0xB6BB, 0x8CF8, 0xB6BC, 0x8CF9, 0xB6BD, 0x8CFA, 0xB6BE, 0x8CFB, 0xB6BF, 0x8CFC, 0xB6C0, 0x8CFD, 0xB6C1, 0x8CFE, 0xB6C2, + 0x8D41, 0xB6C3, 0x8D42, 0xB6C4, 0x8D43, 0xB6C5, 0x8D44, 0xB6C6, 0x8D45, 0xB6C7, 0x8D46, 0xB6C8, 0x8D47, 0xB6C9, 0x8D48, 0xB6CA, + 0x8D49, 0xB6CB, 0x8D4A, 0xB6CC, 0x8D4B, 0xB6CD, 0x8D4C, 0xB6CE, 0x8D4D, 0xB6CF, 0x8D4E, 0xB6D0, 0x8D4F, 0xB6D1, 0x8D50, 0xB6D2, + 0x8D51, 0xB6D3, 0x8D52, 0xB6D5, 0x8D53, 0xB6D6, 0x8D54, 0xB6D7, 0x8D55, 0xB6D8, 0x8D56, 0xB6D9, 0x8D57, 0xB6DA, 0x8D58, 0xB6DB, + 0x8D59, 0xB6DC, 0x8D5A, 0xB6DD, 0x8D61, 0xB6DE, 0x8D62, 0xB6DF, 0x8D63, 0xB6E0, 0x8D64, 0xB6E1, 0x8D65, 0xB6E2, 0x8D66, 0xB6E3, + 0x8D67, 0xB6E4, 0x8D68, 0xB6E5, 0x8D69, 0xB6E6, 0x8D6A, 0xB6E7, 0x8D6B, 0xB6E8, 0x8D6C, 0xB6E9, 0x8D6D, 0xB6EA, 0x8D6E, 0xB6EB, + 0x8D6F, 0xB6EC, 0x8D70, 0xB6ED, 0x8D71, 0xB6EE, 0x8D72, 0xB6EF, 0x8D73, 0xB6F1, 0x8D74, 0xB6F2, 0x8D75, 0xB6F3, 0x8D76, 0xB6F5, + 0x8D77, 0xB6F6, 0x8D78, 0xB6F7, 0x8D79, 0xB6F9, 0x8D7A, 0xB6FA, 0x8D81, 0xB6FB, 0x8D82, 0xB6FC, 0x8D83, 0xB6FD, 0x8D84, 0xB6FE, + 0x8D85, 0xB6FF, 0x8D86, 0xB702, 0x8D87, 0xB703, 0x8D88, 0xB704, 0x8D89, 0xB706, 0x8D8A, 0xB707, 0x8D8B, 0xB708, 0x8D8C, 0xB709, + 0x8D8D, 0xB70A, 0x8D8E, 0xB70B, 0x8D8F, 0xB70C, 0x8D90, 0xB70D, 0x8D91, 0xB70E, 0x8D92, 0xB70F, 0x8D93, 0xB710, 0x8D94, 0xB711, + 0x8D95, 0xB712, 0x8D96, 0xB713, 0x8D97, 0xB714, 0x8D98, 0xB715, 0x8D99, 0xB716, 0x8D9A, 0xB717, 0x8D9B, 0xB718, 0x8D9C, 0xB719, + 0x8D9D, 0xB71A, 0x8D9E, 0xB71B, 0x8D9F, 0xB71C, 0x8DA0, 0xB71D, 0x8DA1, 0xB71E, 0x8DA2, 0xB71F, 0x8DA3, 0xB720, 0x8DA4, 0xB721, + 0x8DA5, 0xB722, 0x8DA6, 0xB723, 0x8DA7, 0xB724, 0x8DA8, 0xB725, 0x8DA9, 0xB726, 0x8DAA, 0xB727, 0x8DAB, 0xB72A, 0x8DAC, 0xB72B, + 0x8DAD, 0xB72D, 0x8DAE, 0xB72E, 0x8DAF, 0xB731, 0x8DB0, 0xB732, 0x8DB1, 0xB733, 0x8DB2, 0xB734, 0x8DB3, 0xB735, 0x8DB4, 0xB736, + 0x8DB5, 0xB737, 0x8DB6, 0xB73A, 0x8DB7, 0xB73C, 0x8DB8, 0xB73D, 0x8DB9, 0xB73E, 0x8DBA, 0xB73F, 0x8DBB, 0xB740, 0x8DBC, 0xB741, + 0x8DBD, 0xB742, 0x8DBE, 0xB743, 0x8DBF, 0xB745, 0x8DC0, 0xB746, 0x8DC1, 0xB747, 0x8DC2, 0xB749, 0x8DC3, 0xB74A, 0x8DC4, 0xB74B, + 0x8DC5, 0xB74D, 0x8DC6, 0xB74E, 0x8DC7, 0xB74F, 0x8DC8, 0xB750, 0x8DC9, 0xB751, 0x8DCA, 0xB752, 0x8DCB, 0xB753, 0x8DCC, 0xB756, + 0x8DCD, 0xB757, 0x8DCE, 0xB758, 0x8DCF, 0xB759, 0x8DD0, 0xB75A, 0x8DD1, 0xB75B, 0x8DD2, 0xB75C, 0x8DD3, 0xB75D, 0x8DD4, 0xB75E, + 0x8DD5, 0xB75F, 0x8DD6, 0xB761, 0x8DD7, 0xB762, 0x8DD8, 0xB763, 0x8DD9, 0xB765, 0x8DDA, 0xB766, 0x8DDB, 0xB767, 0x8DDC, 0xB769, + 0x8DDD, 0xB76A, 0x8DDE, 0xB76B, 0x8DDF, 0xB76C, 0x8DE0, 0xB76D, 0x8DE1, 0xB76E, 0x8DE2, 0xB76F, 0x8DE3, 0xB772, 0x8DE4, 0xB774, + 0x8DE5, 0xB776, 0x8DE6, 0xB777, 0x8DE7, 0xB778, 0x8DE8, 0xB779, 0x8DE9, 0xB77A, 0x8DEA, 0xB77B, 0x8DEB, 0xB77E, 0x8DEC, 0xB77F, + 0x8DED, 0xB781, 0x8DEE, 0xB782, 0x8DEF, 0xB783, 0x8DF0, 0xB785, 0x8DF1, 0xB786, 0x8DF2, 0xB787, 0x8DF3, 0xB788, 0x8DF4, 0xB789, + 0x8DF5, 0xB78A, 0x8DF6, 0xB78B, 0x8DF7, 0xB78E, 0x8DF8, 0xB793, 0x8DF9, 0xB794, 0x8DFA, 0xB795, 0x8DFB, 0xB79A, 0x8DFC, 0xB79B, + 0x8DFD, 0xB79D, 0x8DFE, 0xB79E, 0x8E41, 0xB79F, 0x8E42, 0xB7A1, 0x8E43, 0xB7A2, 0x8E44, 0xB7A3, 0x8E45, 0xB7A4, 0x8E46, 0xB7A5, + 0x8E47, 0xB7A6, 0x8E48, 0xB7A7, 0x8E49, 0xB7AA, 0x8E4A, 0xB7AE, 0x8E4B, 0xB7AF, 0x8E4C, 0xB7B0, 0x8E4D, 0xB7B1, 0x8E4E, 0xB7B2, + 0x8E4F, 0xB7B3, 0x8E50, 0xB7B6, 0x8E51, 0xB7B7, 0x8E52, 0xB7B9, 0x8E53, 0xB7BA, 0x8E54, 0xB7BB, 0x8E55, 0xB7BC, 0x8E56, 0xB7BD, + 0x8E57, 0xB7BE, 0x8E58, 0xB7BF, 0x8E59, 0xB7C0, 0x8E5A, 0xB7C1, 0x8E61, 0xB7C2, 0x8E62, 0xB7C3, 0x8E63, 0xB7C4, 0x8E64, 0xB7C5, + 0x8E65, 0xB7C6, 0x8E66, 0xB7C8, 0x8E67, 0xB7CA, 0x8E68, 0xB7CB, 0x8E69, 0xB7CC, 0x8E6A, 0xB7CD, 0x8E6B, 0xB7CE, 0x8E6C, 0xB7CF, + 0x8E6D, 0xB7D0, 0x8E6E, 0xB7D1, 0x8E6F, 0xB7D2, 0x8E70, 0xB7D3, 0x8E71, 0xB7D4, 0x8E72, 0xB7D5, 0x8E73, 0xB7D6, 0x8E74, 0xB7D7, + 0x8E75, 0xB7D8, 0x8E76, 0xB7D9, 0x8E77, 0xB7DA, 0x8E78, 0xB7DB, 0x8E79, 0xB7DC, 0x8E7A, 0xB7DD, 0x8E81, 0xB7DE, 0x8E82, 0xB7DF, + 0x8E83, 0xB7E0, 0x8E84, 0xB7E1, 0x8E85, 0xB7E2, 0x8E86, 0xB7E3, 0x8E87, 0xB7E4, 0x8E88, 0xB7E5, 0x8E89, 0xB7E6, 0x8E8A, 0xB7E7, + 0x8E8B, 0xB7E8, 0x8E8C, 0xB7E9, 0x8E8D, 0xB7EA, 0x8E8E, 0xB7EB, 0x8E8F, 0xB7EE, 0x8E90, 0xB7EF, 0x8E91, 0xB7F1, 0x8E92, 0xB7F2, + 0x8E93, 0xB7F3, 0x8E94, 0xB7F5, 0x8E95, 0xB7F6, 0x8E96, 0xB7F7, 0x8E97, 0xB7F8, 0x8E98, 0xB7F9, 0x8E99, 0xB7FA, 0x8E9A, 0xB7FB, + 0x8E9B, 0xB7FE, 0x8E9C, 0xB802, 0x8E9D, 0xB803, 0x8E9E, 0xB804, 0x8E9F, 0xB805, 0x8EA0, 0xB806, 0x8EA1, 0xB80A, 0x8EA2, 0xB80B, + 0x8EA3, 0xB80D, 0x8EA4, 0xB80E, 0x8EA5, 0xB80F, 0x8EA6, 0xB811, 0x8EA7, 0xB812, 0x8EA8, 0xB813, 0x8EA9, 0xB814, 0x8EAA, 0xB815, + 0x8EAB, 0xB816, 0x8EAC, 0xB817, 0x8EAD, 0xB81A, 0x8EAE, 0xB81C, 0x8EAF, 0xB81E, 0x8EB0, 0xB81F, 0x8EB1, 0xB820, 0x8EB2, 0xB821, + 0x8EB3, 0xB822, 0x8EB4, 0xB823, 0x8EB5, 0xB826, 0x8EB6, 0xB827, 0x8EB7, 0xB829, 0x8EB8, 0xB82A, 0x8EB9, 0xB82B, 0x8EBA, 0xB82D, + 0x8EBB, 0xB82E, 0x8EBC, 0xB82F, 0x8EBD, 0xB830, 0x8EBE, 0xB831, 0x8EBF, 0xB832, 0x8EC0, 0xB833, 0x8EC1, 0xB836, 0x8EC2, 0xB83A, + 0x8EC3, 0xB83B, 0x8EC4, 0xB83C, 0x8EC5, 0xB83D, 0x8EC6, 0xB83E, 0x8EC7, 0xB83F, 0x8EC8, 0xB841, 0x8EC9, 0xB842, 0x8ECA, 0xB843, + 0x8ECB, 0xB845, 0x8ECC, 0xB846, 0x8ECD, 0xB847, 0x8ECE, 0xB848, 0x8ECF, 0xB849, 0x8ED0, 0xB84A, 0x8ED1, 0xB84B, 0x8ED2, 0xB84C, + 0x8ED3, 0xB84D, 0x8ED4, 0xB84E, 0x8ED5, 0xB84F, 0x8ED6, 0xB850, 0x8ED7, 0xB852, 0x8ED8, 0xB854, 0x8ED9, 0xB855, 0x8EDA, 0xB856, + 0x8EDB, 0xB857, 0x8EDC, 0xB858, 0x8EDD, 0xB859, 0x8EDE, 0xB85A, 0x8EDF, 0xB85B, 0x8EE0, 0xB85E, 0x8EE1, 0xB85F, 0x8EE2, 0xB861, + 0x8EE3, 0xB862, 0x8EE4, 0xB863, 0x8EE5, 0xB865, 0x8EE6, 0xB866, 0x8EE7, 0xB867, 0x8EE8, 0xB868, 0x8EE9, 0xB869, 0x8EEA, 0xB86A, + 0x8EEB, 0xB86B, 0x8EEC, 0xB86E, 0x8EED, 0xB870, 0x8EEE, 0xB872, 0x8EEF, 0xB873, 0x8EF0, 0xB874, 0x8EF1, 0xB875, 0x8EF2, 0xB876, + 0x8EF3, 0xB877, 0x8EF4, 0xB879, 0x8EF5, 0xB87A, 0x8EF6, 0xB87B, 0x8EF7, 0xB87D, 0x8EF8, 0xB87E, 0x8EF9, 0xB87F, 0x8EFA, 0xB880, + 0x8EFB, 0xB881, 0x8EFC, 0xB882, 0x8EFD, 0xB883, 0x8EFE, 0xB884, 0x8F41, 0xB885, 0x8F42, 0xB886, 0x8F43, 0xB887, 0x8F44, 0xB888, + 0x8F45, 0xB889, 0x8F46, 0xB88A, 0x8F47, 0xB88B, 0x8F48, 0xB88C, 0x8F49, 0xB88E, 0x8F4A, 0xB88F, 0x8F4B, 0xB890, 0x8F4C, 0xB891, + 0x8F4D, 0xB892, 0x8F4E, 0xB893, 0x8F4F, 0xB894, 0x8F50, 0xB895, 0x8F51, 0xB896, 0x8F52, 0xB897, 0x8F53, 0xB898, 0x8F54, 0xB899, + 0x8F55, 0xB89A, 0x8F56, 0xB89B, 0x8F57, 0xB89C, 0x8F58, 0xB89D, 0x8F59, 0xB89E, 0x8F5A, 0xB89F, 0x8F61, 0xB8A0, 0x8F62, 0xB8A1, + 0x8F63, 0xB8A2, 0x8F64, 0xB8A3, 0x8F65, 0xB8A4, 0x8F66, 0xB8A5, 0x8F67, 0xB8A6, 0x8F68, 0xB8A7, 0x8F69, 0xB8A9, 0x8F6A, 0xB8AA, + 0x8F6B, 0xB8AB, 0x8F6C, 0xB8AC, 0x8F6D, 0xB8AD, 0x8F6E, 0xB8AE, 0x8F6F, 0xB8AF, 0x8F70, 0xB8B1, 0x8F71, 0xB8B2, 0x8F72, 0xB8B3, + 0x8F73, 0xB8B5, 0x8F74, 0xB8B6, 0x8F75, 0xB8B7, 0x8F76, 0xB8B9, 0x8F77, 0xB8BA, 0x8F78, 0xB8BB, 0x8F79, 0xB8BC, 0x8F7A, 0xB8BD, + 0x8F81, 0xB8BE, 0x8F82, 0xB8BF, 0x8F83, 0xB8C2, 0x8F84, 0xB8C4, 0x8F85, 0xB8C6, 0x8F86, 0xB8C7, 0x8F87, 0xB8C8, 0x8F88, 0xB8C9, + 0x8F89, 0xB8CA, 0x8F8A, 0xB8CB, 0x8F8B, 0xB8CD, 0x8F8C, 0xB8CE, 0x8F8D, 0xB8CF, 0x8F8E, 0xB8D1, 0x8F8F, 0xB8D2, 0x8F90, 0xB8D3, + 0x8F91, 0xB8D5, 0x8F92, 0xB8D6, 0x8F93, 0xB8D7, 0x8F94, 0xB8D8, 0x8F95, 0xB8D9, 0x8F96, 0xB8DA, 0x8F97, 0xB8DB, 0x8F98, 0xB8DC, + 0x8F99, 0xB8DE, 0x8F9A, 0xB8E0, 0x8F9B, 0xB8E2, 0x8F9C, 0xB8E3, 0x8F9D, 0xB8E4, 0x8F9E, 0xB8E5, 0x8F9F, 0xB8E6, 0x8FA0, 0xB8E7, + 0x8FA1, 0xB8EA, 0x8FA2, 0xB8EB, 0x8FA3, 0xB8ED, 0x8FA4, 0xB8EE, 0x8FA5, 0xB8EF, 0x8FA6, 0xB8F1, 0x8FA7, 0xB8F2, 0x8FA8, 0xB8F3, + 0x8FA9, 0xB8F4, 0x8FAA, 0xB8F5, 0x8FAB, 0xB8F6, 0x8FAC, 0xB8F7, 0x8FAD, 0xB8FA, 0x8FAE, 0xB8FC, 0x8FAF, 0xB8FE, 0x8FB0, 0xB8FF, + 0x8FB1, 0xB900, 0x8FB2, 0xB901, 0x8FB3, 0xB902, 0x8FB4, 0xB903, 0x8FB5, 0xB905, 0x8FB6, 0xB906, 0x8FB7, 0xB907, 0x8FB8, 0xB908, + 0x8FB9, 0xB909, 0x8FBA, 0xB90A, 0x8FBB, 0xB90B, 0x8FBC, 0xB90C, 0x8FBD, 0xB90D, 0x8FBE, 0xB90E, 0x8FBF, 0xB90F, 0x8FC0, 0xB910, + 0x8FC1, 0xB911, 0x8FC2, 0xB912, 0x8FC3, 0xB913, 0x8FC4, 0xB914, 0x8FC5, 0xB915, 0x8FC6, 0xB916, 0x8FC7, 0xB917, 0x8FC8, 0xB919, + 0x8FC9, 0xB91A, 0x8FCA, 0xB91B, 0x8FCB, 0xB91C, 0x8FCC, 0xB91D, 0x8FCD, 0xB91E, 0x8FCE, 0xB91F, 0x8FCF, 0xB921, 0x8FD0, 0xB922, + 0x8FD1, 0xB923, 0x8FD2, 0xB924, 0x8FD3, 0xB925, 0x8FD4, 0xB926, 0x8FD5, 0xB927, 0x8FD6, 0xB928, 0x8FD7, 0xB929, 0x8FD8, 0xB92A, + 0x8FD9, 0xB92B, 0x8FDA, 0xB92C, 0x8FDB, 0xB92D, 0x8FDC, 0xB92E, 0x8FDD, 0xB92F, 0x8FDE, 0xB930, 0x8FDF, 0xB931, 0x8FE0, 0xB932, + 0x8FE1, 0xB933, 0x8FE2, 0xB934, 0x8FE3, 0xB935, 0x8FE4, 0xB936, 0x8FE5, 0xB937, 0x8FE6, 0xB938, 0x8FE7, 0xB939, 0x8FE8, 0xB93A, + 0x8FE9, 0xB93B, 0x8FEA, 0xB93E, 0x8FEB, 0xB93F, 0x8FEC, 0xB941, 0x8FED, 0xB942, 0x8FEE, 0xB943, 0x8FEF, 0xB945, 0x8FF0, 0xB946, + 0x8FF1, 0xB947, 0x8FF2, 0xB948, 0x8FF3, 0xB949, 0x8FF4, 0xB94A, 0x8FF5, 0xB94B, 0x8FF6, 0xB94D, 0x8FF7, 0xB94E, 0x8FF8, 0xB950, + 0x8FF9, 0xB952, 0x8FFA, 0xB953, 0x8FFB, 0xB954, 0x8FFC, 0xB955, 0x8FFD, 0xB956, 0x8FFE, 0xB957, 0x9041, 0xB95A, 0x9042, 0xB95B, + 0x9043, 0xB95D, 0x9044, 0xB95E, 0x9045, 0xB95F, 0x9046, 0xB961, 0x9047, 0xB962, 0x9048, 0xB963, 0x9049, 0xB964, 0x904A, 0xB965, + 0x904B, 0xB966, 0x904C, 0xB967, 0x904D, 0xB96A, 0x904E, 0xB96C, 0x904F, 0xB96E, 0x9050, 0xB96F, 0x9051, 0xB970, 0x9052, 0xB971, + 0x9053, 0xB972, 0x9054, 0xB973, 0x9055, 0xB976, 0x9056, 0xB977, 0x9057, 0xB979, 0x9058, 0xB97A, 0x9059, 0xB97B, 0x905A, 0xB97D, + 0x9061, 0xB97E, 0x9062, 0xB97F, 0x9063, 0xB980, 0x9064, 0xB981, 0x9065, 0xB982, 0x9066, 0xB983, 0x9067, 0xB986, 0x9068, 0xB988, + 0x9069, 0xB98B, 0x906A, 0xB98C, 0x906B, 0xB98F, 0x906C, 0xB990, 0x906D, 0xB991, 0x906E, 0xB992, 0x906F, 0xB993, 0x9070, 0xB994, + 0x9071, 0xB995, 0x9072, 0xB996, 0x9073, 0xB997, 0x9074, 0xB998, 0x9075, 0xB999, 0x9076, 0xB99A, 0x9077, 0xB99B, 0x9078, 0xB99C, + 0x9079, 0xB99D, 0x907A, 0xB99E, 0x9081, 0xB99F, 0x9082, 0xB9A0, 0x9083, 0xB9A1, 0x9084, 0xB9A2, 0x9085, 0xB9A3, 0x9086, 0xB9A4, + 0x9087, 0xB9A5, 0x9088, 0xB9A6, 0x9089, 0xB9A7, 0x908A, 0xB9A8, 0x908B, 0xB9A9, 0x908C, 0xB9AA, 0x908D, 0xB9AB, 0x908E, 0xB9AE, + 0x908F, 0xB9AF, 0x9090, 0xB9B1, 0x9091, 0xB9B2, 0x9092, 0xB9B3, 0x9093, 0xB9B5, 0x9094, 0xB9B6, 0x9095, 0xB9B7, 0x9096, 0xB9B8, + 0x9097, 0xB9B9, 0x9098, 0xB9BA, 0x9099, 0xB9BB, 0x909A, 0xB9BE, 0x909B, 0xB9C0, 0x909C, 0xB9C2, 0x909D, 0xB9C3, 0x909E, 0xB9C4, + 0x909F, 0xB9C5, 0x90A0, 0xB9C6, 0x90A1, 0xB9C7, 0x90A2, 0xB9CA, 0x90A3, 0xB9CB, 0x90A4, 0xB9CD, 0x90A5, 0xB9D3, 0x90A6, 0xB9D4, + 0x90A7, 0xB9D5, 0x90A8, 0xB9D6, 0x90A9, 0xB9D7, 0x90AA, 0xB9DA, 0x90AB, 0xB9DC, 0x90AC, 0xB9DF, 0x90AD, 0xB9E0, 0x90AE, 0xB9E2, + 0x90AF, 0xB9E6, 0x90B0, 0xB9E7, 0x90B1, 0xB9E9, 0x90B2, 0xB9EA, 0x90B3, 0xB9EB, 0x90B4, 0xB9ED, 0x90B5, 0xB9EE, 0x90B6, 0xB9EF, + 0x90B7, 0xB9F0, 0x90B8, 0xB9F1, 0x90B9, 0xB9F2, 0x90BA, 0xB9F3, 0x90BB, 0xB9F6, 0x90BC, 0xB9FB, 0x90BD, 0xB9FC, 0x90BE, 0xB9FD, + 0x90BF, 0xB9FE, 0x90C0, 0xB9FF, 0x90C1, 0xBA02, 0x90C2, 0xBA03, 0x90C3, 0xBA04, 0x90C4, 0xBA05, 0x90C5, 0xBA06, 0x90C6, 0xBA07, + 0x90C7, 0xBA09, 0x90C8, 0xBA0A, 0x90C9, 0xBA0B, 0x90CA, 0xBA0C, 0x90CB, 0xBA0D, 0x90CC, 0xBA0E, 0x90CD, 0xBA0F, 0x90CE, 0xBA10, + 0x90CF, 0xBA11, 0x90D0, 0xBA12, 0x90D1, 0xBA13, 0x90D2, 0xBA14, 0x90D3, 0xBA16, 0x90D4, 0xBA17, 0x90D5, 0xBA18, 0x90D6, 0xBA19, + 0x90D7, 0xBA1A, 0x90D8, 0xBA1B, 0x90D9, 0xBA1C, 0x90DA, 0xBA1D, 0x90DB, 0xBA1E, 0x90DC, 0xBA1F, 0x90DD, 0xBA20, 0x90DE, 0xBA21, + 0x90DF, 0xBA22, 0x90E0, 0xBA23, 0x90E1, 0xBA24, 0x90E2, 0xBA25, 0x90E3, 0xBA26, 0x90E4, 0xBA27, 0x90E5, 0xBA28, 0x90E6, 0xBA29, + 0x90E7, 0xBA2A, 0x90E8, 0xBA2B, 0x90E9, 0xBA2C, 0x90EA, 0xBA2D, 0x90EB, 0xBA2E, 0x90EC, 0xBA2F, 0x90ED, 0xBA30, 0x90EE, 0xBA31, + 0x90EF, 0xBA32, 0x90F0, 0xBA33, 0x90F1, 0xBA34, 0x90F2, 0xBA35, 0x90F3, 0xBA36, 0x90F4, 0xBA37, 0x90F5, 0xBA3A, 0x90F6, 0xBA3B, + 0x90F7, 0xBA3D, 0x90F8, 0xBA3E, 0x90F9, 0xBA3F, 0x90FA, 0xBA41, 0x90FB, 0xBA43, 0x90FC, 0xBA44, 0x90FD, 0xBA45, 0x90FE, 0xBA46, + 0x9141, 0xBA47, 0x9142, 0xBA4A, 0x9143, 0xBA4C, 0x9144, 0xBA4F, 0x9145, 0xBA50, 0x9146, 0xBA51, 0x9147, 0xBA52, 0x9148, 0xBA56, + 0x9149, 0xBA57, 0x914A, 0xBA59, 0x914B, 0xBA5A, 0x914C, 0xBA5B, 0x914D, 0xBA5D, 0x914E, 0xBA5E, 0x914F, 0xBA5F, 0x9150, 0xBA60, + 0x9151, 0xBA61, 0x9152, 0xBA62, 0x9153, 0xBA63, 0x9154, 0xBA66, 0x9155, 0xBA6A, 0x9156, 0xBA6B, 0x9157, 0xBA6C, 0x9158, 0xBA6D, + 0x9159, 0xBA6E, 0x915A, 0xBA6F, 0x9161, 0xBA72, 0x9162, 0xBA73, 0x9163, 0xBA75, 0x9164, 0xBA76, 0x9165, 0xBA77, 0x9166, 0xBA79, + 0x9167, 0xBA7A, 0x9168, 0xBA7B, 0x9169, 0xBA7C, 0x916A, 0xBA7D, 0x916B, 0xBA7E, 0x916C, 0xBA7F, 0x916D, 0xBA80, 0x916E, 0xBA81, + 0x916F, 0xBA82, 0x9170, 0xBA86, 0x9171, 0xBA88, 0x9172, 0xBA89, 0x9173, 0xBA8A, 0x9174, 0xBA8B, 0x9175, 0xBA8D, 0x9176, 0xBA8E, + 0x9177, 0xBA8F, 0x9178, 0xBA90, 0x9179, 0xBA91, 0x917A, 0xBA92, 0x9181, 0xBA93, 0x9182, 0xBA94, 0x9183, 0xBA95, 0x9184, 0xBA96, + 0x9185, 0xBA97, 0x9186, 0xBA98, 0x9187, 0xBA99, 0x9188, 0xBA9A, 0x9189, 0xBA9B, 0x918A, 0xBA9C, 0x918B, 0xBA9D, 0x918C, 0xBA9E, + 0x918D, 0xBA9F, 0x918E, 0xBAA0, 0x918F, 0xBAA1, 0x9190, 0xBAA2, 0x9191, 0xBAA3, 0x9192, 0xBAA4, 0x9193, 0xBAA5, 0x9194, 0xBAA6, + 0x9195, 0xBAA7, 0x9196, 0xBAAA, 0x9197, 0xBAAD, 0x9198, 0xBAAE, 0x9199, 0xBAAF, 0x919A, 0xBAB1, 0x919B, 0xBAB3, 0x919C, 0xBAB4, + 0x919D, 0xBAB5, 0x919E, 0xBAB6, 0x919F, 0xBAB7, 0x91A0, 0xBABA, 0x91A1, 0xBABC, 0x91A2, 0xBABE, 0x91A3, 0xBABF, 0x91A4, 0xBAC0, + 0x91A5, 0xBAC1, 0x91A6, 0xBAC2, 0x91A7, 0xBAC3, 0x91A8, 0xBAC5, 0x91A9, 0xBAC6, 0x91AA, 0xBAC7, 0x91AB, 0xBAC9, 0x91AC, 0xBACA, + 0x91AD, 0xBACB, 0x91AE, 0xBACC, 0x91AF, 0xBACD, 0x91B0, 0xBACE, 0x91B1, 0xBACF, 0x91B2, 0xBAD0, 0x91B3, 0xBAD1, 0x91B4, 0xBAD2, + 0x91B5, 0xBAD3, 0x91B6, 0xBAD4, 0x91B7, 0xBAD5, 0x91B8, 0xBAD6, 0x91B9, 0xBAD7, 0x91BA, 0xBADA, 0x91BB, 0xBADB, 0x91BC, 0xBADC, + 0x91BD, 0xBADD, 0x91BE, 0xBADE, 0x91BF, 0xBADF, 0x91C0, 0xBAE0, 0x91C1, 0xBAE1, 0x91C2, 0xBAE2, 0x91C3, 0xBAE3, 0x91C4, 0xBAE4, + 0x91C5, 0xBAE5, 0x91C6, 0xBAE6, 0x91C7, 0xBAE7, 0x91C8, 0xBAE8, 0x91C9, 0xBAE9, 0x91CA, 0xBAEA, 0x91CB, 0xBAEB, 0x91CC, 0xBAEC, + 0x91CD, 0xBAED, 0x91CE, 0xBAEE, 0x91CF, 0xBAEF, 0x91D0, 0xBAF0, 0x91D1, 0xBAF1, 0x91D2, 0xBAF2, 0x91D3, 0xBAF3, 0x91D4, 0xBAF4, + 0x91D5, 0xBAF5, 0x91D6, 0xBAF6, 0x91D7, 0xBAF7, 0x91D8, 0xBAF8, 0x91D9, 0xBAF9, 0x91DA, 0xBAFA, 0x91DB, 0xBAFB, 0x91DC, 0xBAFD, + 0x91DD, 0xBAFE, 0x91DE, 0xBAFF, 0x91DF, 0xBB01, 0x91E0, 0xBB02, 0x91E1, 0xBB03, 0x91E2, 0xBB05, 0x91E3, 0xBB06, 0x91E4, 0xBB07, + 0x91E5, 0xBB08, 0x91E6, 0xBB09, 0x91E7, 0xBB0A, 0x91E8, 0xBB0B, 0x91E9, 0xBB0C, 0x91EA, 0xBB0E, 0x91EB, 0xBB10, 0x91EC, 0xBB12, + 0x91ED, 0xBB13, 0x91EE, 0xBB14, 0x91EF, 0xBB15, 0x91F0, 0xBB16, 0x91F1, 0xBB17, 0x91F2, 0xBB19, 0x91F3, 0xBB1A, 0x91F4, 0xBB1B, + 0x91F5, 0xBB1D, 0x91F6, 0xBB1E, 0x91F7, 0xBB1F, 0x91F8, 0xBB21, 0x91F9, 0xBB22, 0x91FA, 0xBB23, 0x91FB, 0xBB24, 0x91FC, 0xBB25, + 0x91FD, 0xBB26, 0x91FE, 0xBB27, 0x9241, 0xBB28, 0x9242, 0xBB2A, 0x9243, 0xBB2C, 0x9244, 0xBB2D, 0x9245, 0xBB2E, 0x9246, 0xBB2F, + 0x9247, 0xBB30, 0x9248, 0xBB31, 0x9249, 0xBB32, 0x924A, 0xBB33, 0x924B, 0xBB37, 0x924C, 0xBB39, 0x924D, 0xBB3A, 0x924E, 0xBB3F, + 0x924F, 0xBB40, 0x9250, 0xBB41, 0x9251, 0xBB42, 0x9252, 0xBB43, 0x9253, 0xBB46, 0x9254, 0xBB48, 0x9255, 0xBB4A, 0x9256, 0xBB4B, + 0x9257, 0xBB4C, 0x9258, 0xBB4E, 0x9259, 0xBB51, 0x925A, 0xBB52, 0x9261, 0xBB53, 0x9262, 0xBB55, 0x9263, 0xBB56, 0x9264, 0xBB57, + 0x9265, 0xBB59, 0x9266, 0xBB5A, 0x9267, 0xBB5B, 0x9268, 0xBB5C, 0x9269, 0xBB5D, 0x926A, 0xBB5E, 0x926B, 0xBB5F, 0x926C, 0xBB60, + 0x926D, 0xBB62, 0x926E, 0xBB64, 0x926F, 0xBB65, 0x9270, 0xBB66, 0x9271, 0xBB67, 0x9272, 0xBB68, 0x9273, 0xBB69, 0x9274, 0xBB6A, + 0x9275, 0xBB6B, 0x9276, 0xBB6D, 0x9277, 0xBB6E, 0x9278, 0xBB6F, 0x9279, 0xBB70, 0x927A, 0xBB71, 0x9281, 0xBB72, 0x9282, 0xBB73, + 0x9283, 0xBB74, 0x9284, 0xBB75, 0x9285, 0xBB76, 0x9286, 0xBB77, 0x9287, 0xBB78, 0x9288, 0xBB79, 0x9289, 0xBB7A, 0x928A, 0xBB7B, + 0x928B, 0xBB7C, 0x928C, 0xBB7D, 0x928D, 0xBB7E, 0x928E, 0xBB7F, 0x928F, 0xBB80, 0x9290, 0xBB81, 0x9291, 0xBB82, 0x9292, 0xBB83, + 0x9293, 0xBB84, 0x9294, 0xBB85, 0x9295, 0xBB86, 0x9296, 0xBB87, 0x9297, 0xBB89, 0x9298, 0xBB8A, 0x9299, 0xBB8B, 0x929A, 0xBB8D, + 0x929B, 0xBB8E, 0x929C, 0xBB8F, 0x929D, 0xBB91, 0x929E, 0xBB92, 0x929F, 0xBB93, 0x92A0, 0xBB94, 0x92A1, 0xBB95, 0x92A2, 0xBB96, + 0x92A3, 0xBB97, 0x92A4, 0xBB98, 0x92A5, 0xBB99, 0x92A6, 0xBB9A, 0x92A7, 0xBB9B, 0x92A8, 0xBB9C, 0x92A9, 0xBB9D, 0x92AA, 0xBB9E, + 0x92AB, 0xBB9F, 0x92AC, 0xBBA0, 0x92AD, 0xBBA1, 0x92AE, 0xBBA2, 0x92AF, 0xBBA3, 0x92B0, 0xBBA5, 0x92B1, 0xBBA6, 0x92B2, 0xBBA7, + 0x92B3, 0xBBA9, 0x92B4, 0xBBAA, 0x92B5, 0xBBAB, 0x92B6, 0xBBAD, 0x92B7, 0xBBAE, 0x92B8, 0xBBAF, 0x92B9, 0xBBB0, 0x92BA, 0xBBB1, + 0x92BB, 0xBBB2, 0x92BC, 0xBBB3, 0x92BD, 0xBBB5, 0x92BE, 0xBBB6, 0x92BF, 0xBBB8, 0x92C0, 0xBBB9, 0x92C1, 0xBBBA, 0x92C2, 0xBBBB, + 0x92C3, 0xBBBC, 0x92C4, 0xBBBD, 0x92C5, 0xBBBE, 0x92C6, 0xBBBF, 0x92C7, 0xBBC1, 0x92C8, 0xBBC2, 0x92C9, 0xBBC3, 0x92CA, 0xBBC5, + 0x92CB, 0xBBC6, 0x92CC, 0xBBC7, 0x92CD, 0xBBC9, 0x92CE, 0xBBCA, 0x92CF, 0xBBCB, 0x92D0, 0xBBCC, 0x92D1, 0xBBCD, 0x92D2, 0xBBCE, + 0x92D3, 0xBBCF, 0x92D4, 0xBBD1, 0x92D5, 0xBBD2, 0x92D6, 0xBBD4, 0x92D7, 0xBBD5, 0x92D8, 0xBBD6, 0x92D9, 0xBBD7, 0x92DA, 0xBBD8, + 0x92DB, 0xBBD9, 0x92DC, 0xBBDA, 0x92DD, 0xBBDB, 0x92DE, 0xBBDC, 0x92DF, 0xBBDD, 0x92E0, 0xBBDE, 0x92E1, 0xBBDF, 0x92E2, 0xBBE0, + 0x92E3, 0xBBE1, 0x92E4, 0xBBE2, 0x92E5, 0xBBE3, 0x92E6, 0xBBE4, 0x92E7, 0xBBE5, 0x92E8, 0xBBE6, 0x92E9, 0xBBE7, 0x92EA, 0xBBE8, + 0x92EB, 0xBBE9, 0x92EC, 0xBBEA, 0x92ED, 0xBBEB, 0x92EE, 0xBBEC, 0x92EF, 0xBBED, 0x92F0, 0xBBEE, 0x92F1, 0xBBEF, 0x92F2, 0xBBF0, + 0x92F3, 0xBBF1, 0x92F4, 0xBBF2, 0x92F5, 0xBBF3, 0x92F6, 0xBBF4, 0x92F7, 0xBBF5, 0x92F8, 0xBBF6, 0x92F9, 0xBBF7, 0x92FA, 0xBBFA, + 0x92FB, 0xBBFB, 0x92FC, 0xBBFD, 0x92FD, 0xBBFE, 0x92FE, 0xBC01, 0x9341, 0xBC03, 0x9342, 0xBC04, 0x9343, 0xBC05, 0x9344, 0xBC06, + 0x9345, 0xBC07, 0x9346, 0xBC0A, 0x9347, 0xBC0E, 0x9348, 0xBC10, 0x9349, 0xBC12, 0x934A, 0xBC13, 0x934B, 0xBC19, 0x934C, 0xBC1A, + 0x934D, 0xBC20, 0x934E, 0xBC21, 0x934F, 0xBC22, 0x9350, 0xBC23, 0x9351, 0xBC26, 0x9352, 0xBC28, 0x9353, 0xBC2A, 0x9354, 0xBC2B, + 0x9355, 0xBC2C, 0x9356, 0xBC2E, 0x9357, 0xBC2F, 0x9358, 0xBC32, 0x9359, 0xBC33, 0x935A, 0xBC35, 0x9361, 0xBC36, 0x9362, 0xBC37, + 0x9363, 0xBC39, 0x9364, 0xBC3A, 0x9365, 0xBC3B, 0x9366, 0xBC3C, 0x9367, 0xBC3D, 0x9368, 0xBC3E, 0x9369, 0xBC3F, 0x936A, 0xBC42, + 0x936B, 0xBC46, 0x936C, 0xBC47, 0x936D, 0xBC48, 0x936E, 0xBC4A, 0x936F, 0xBC4B, 0x9370, 0xBC4E, 0x9371, 0xBC4F, 0x9372, 0xBC51, + 0x9373, 0xBC52, 0x9374, 0xBC53, 0x9375, 0xBC54, 0x9376, 0xBC55, 0x9377, 0xBC56, 0x9378, 0xBC57, 0x9379, 0xBC58, 0x937A, 0xBC59, + 0x9381, 0xBC5A, 0x9382, 0xBC5B, 0x9383, 0xBC5C, 0x9384, 0xBC5E, 0x9385, 0xBC5F, 0x9386, 0xBC60, 0x9387, 0xBC61, 0x9388, 0xBC62, + 0x9389, 0xBC63, 0x938A, 0xBC64, 0x938B, 0xBC65, 0x938C, 0xBC66, 0x938D, 0xBC67, 0x938E, 0xBC68, 0x938F, 0xBC69, 0x9390, 0xBC6A, + 0x9391, 0xBC6B, 0x9392, 0xBC6C, 0x9393, 0xBC6D, 0x9394, 0xBC6E, 0x9395, 0xBC6F, 0x9396, 0xBC70, 0x9397, 0xBC71, 0x9398, 0xBC72, + 0x9399, 0xBC73, 0x939A, 0xBC74, 0x939B, 0xBC75, 0x939C, 0xBC76, 0x939D, 0xBC77, 0x939E, 0xBC78, 0x939F, 0xBC79, 0x93A0, 0xBC7A, + 0x93A1, 0xBC7B, 0x93A2, 0xBC7C, 0x93A3, 0xBC7D, 0x93A4, 0xBC7E, 0x93A5, 0xBC7F, 0x93A6, 0xBC80, 0x93A7, 0xBC81, 0x93A8, 0xBC82, + 0x93A9, 0xBC83, 0x93AA, 0xBC86, 0x93AB, 0xBC87, 0x93AC, 0xBC89, 0x93AD, 0xBC8A, 0x93AE, 0xBC8D, 0x93AF, 0xBC8F, 0x93B0, 0xBC90, + 0x93B1, 0xBC91, 0x93B2, 0xBC92, 0x93B3, 0xBC93, 0x93B4, 0xBC96, 0x93B5, 0xBC98, 0x93B6, 0xBC9B, 0x93B7, 0xBC9C, 0x93B8, 0xBC9D, + 0x93B9, 0xBC9E, 0x93BA, 0xBC9F, 0x93BB, 0xBCA2, 0x93BC, 0xBCA3, 0x93BD, 0xBCA5, 0x93BE, 0xBCA6, 0x93BF, 0xBCA9, 0x93C0, 0xBCAA, + 0x93C1, 0xBCAB, 0x93C2, 0xBCAC, 0x93C3, 0xBCAD, 0x93C4, 0xBCAE, 0x93C5, 0xBCAF, 0x93C6, 0xBCB2, 0x93C7, 0xBCB6, 0x93C8, 0xBCB7, + 0x93C9, 0xBCB8, 0x93CA, 0xBCB9, 0x93CB, 0xBCBA, 0x93CC, 0xBCBB, 0x93CD, 0xBCBE, 0x93CE, 0xBCBF, 0x93CF, 0xBCC1, 0x93D0, 0xBCC2, + 0x93D1, 0xBCC3, 0x93D2, 0xBCC5, 0x93D3, 0xBCC6, 0x93D4, 0xBCC7, 0x93D5, 0xBCC8, 0x93D6, 0xBCC9, 0x93D7, 0xBCCA, 0x93D8, 0xBCCB, + 0x93D9, 0xBCCC, 0x93DA, 0xBCCE, 0x93DB, 0xBCD2, 0x93DC, 0xBCD3, 0x93DD, 0xBCD4, 0x93DE, 0xBCD6, 0x93DF, 0xBCD7, 0x93E0, 0xBCD9, + 0x93E1, 0xBCDA, 0x93E2, 0xBCDB, 0x93E3, 0xBCDD, 0x93E4, 0xBCDE, 0x93E5, 0xBCDF, 0x93E6, 0xBCE0, 0x93E7, 0xBCE1, 0x93E8, 0xBCE2, + 0x93E9, 0xBCE3, 0x93EA, 0xBCE4, 0x93EB, 0xBCE5, 0x93EC, 0xBCE6, 0x93ED, 0xBCE7, 0x93EE, 0xBCE8, 0x93EF, 0xBCE9, 0x93F0, 0xBCEA, + 0x93F1, 0xBCEB, 0x93F2, 0xBCEC, 0x93F3, 0xBCED, 0x93F4, 0xBCEE, 0x93F5, 0xBCEF, 0x93F6, 0xBCF0, 0x93F7, 0xBCF1, 0x93F8, 0xBCF2, + 0x93F9, 0xBCF3, 0x93FA, 0xBCF7, 0x93FB, 0xBCF9, 0x93FC, 0xBCFA, 0x93FD, 0xBCFB, 0x93FE, 0xBCFD, 0x9441, 0xBCFE, 0x9442, 0xBCFF, + 0x9443, 0xBD00, 0x9444, 0xBD01, 0x9445, 0xBD02, 0x9446, 0xBD03, 0x9447, 0xBD06, 0x9448, 0xBD08, 0x9449, 0xBD0A, 0x944A, 0xBD0B, + 0x944B, 0xBD0C, 0x944C, 0xBD0D, 0x944D, 0xBD0E, 0x944E, 0xBD0F, 0x944F, 0xBD11, 0x9450, 0xBD12, 0x9451, 0xBD13, 0x9452, 0xBD15, + 0x9453, 0xBD16, 0x9454, 0xBD17, 0x9455, 0xBD18, 0x9456, 0xBD19, 0x9457, 0xBD1A, 0x9458, 0xBD1B, 0x9459, 0xBD1C, 0x945A, 0xBD1D, + 0x9461, 0xBD1E, 0x9462, 0xBD1F, 0x9463, 0xBD20, 0x9464, 0xBD21, 0x9465, 0xBD22, 0x9466, 0xBD23, 0x9467, 0xBD25, 0x9468, 0xBD26, + 0x9469, 0xBD27, 0x946A, 0xBD28, 0x946B, 0xBD29, 0x946C, 0xBD2A, 0x946D, 0xBD2B, 0x946E, 0xBD2D, 0x946F, 0xBD2E, 0x9470, 0xBD2F, + 0x9471, 0xBD30, 0x9472, 0xBD31, 0x9473, 0xBD32, 0x9474, 0xBD33, 0x9475, 0xBD34, 0x9476, 0xBD35, 0x9477, 0xBD36, 0x9478, 0xBD37, + 0x9479, 0xBD38, 0x947A, 0xBD39, 0x9481, 0xBD3A, 0x9482, 0xBD3B, 0x9483, 0xBD3C, 0x9484, 0xBD3D, 0x9485, 0xBD3E, 0x9486, 0xBD3F, + 0x9487, 0xBD41, 0x9488, 0xBD42, 0x9489, 0xBD43, 0x948A, 0xBD44, 0x948B, 0xBD45, 0x948C, 0xBD46, 0x948D, 0xBD47, 0x948E, 0xBD4A, + 0x948F, 0xBD4B, 0x9490, 0xBD4D, 0x9491, 0xBD4E, 0x9492, 0xBD4F, 0x9493, 0xBD51, 0x9494, 0xBD52, 0x9495, 0xBD53, 0x9496, 0xBD54, + 0x9497, 0xBD55, 0x9498, 0xBD56, 0x9499, 0xBD57, 0x949A, 0xBD5A, 0x949B, 0xBD5B, 0x949C, 0xBD5C, 0x949D, 0xBD5D, 0x949E, 0xBD5E, + 0x949F, 0xBD5F, 0x94A0, 0xBD60, 0x94A1, 0xBD61, 0x94A2, 0xBD62, 0x94A3, 0xBD63, 0x94A4, 0xBD65, 0x94A5, 0xBD66, 0x94A6, 0xBD67, + 0x94A7, 0xBD69, 0x94A8, 0xBD6A, 0x94A9, 0xBD6B, 0x94AA, 0xBD6C, 0x94AB, 0xBD6D, 0x94AC, 0xBD6E, 0x94AD, 0xBD6F, 0x94AE, 0xBD70, + 0x94AF, 0xBD71, 0x94B0, 0xBD72, 0x94B1, 0xBD73, 0x94B2, 0xBD74, 0x94B3, 0xBD75, 0x94B4, 0xBD76, 0x94B5, 0xBD77, 0x94B6, 0xBD78, + 0x94B7, 0xBD79, 0x94B8, 0xBD7A, 0x94B9, 0xBD7B, 0x94BA, 0xBD7C, 0x94BB, 0xBD7D, 0x94BC, 0xBD7E, 0x94BD, 0xBD7F, 0x94BE, 0xBD82, + 0x94BF, 0xBD83, 0x94C0, 0xBD85, 0x94C1, 0xBD86, 0x94C2, 0xBD8B, 0x94C3, 0xBD8C, 0x94C4, 0xBD8D, 0x94C5, 0xBD8E, 0x94C6, 0xBD8F, + 0x94C7, 0xBD92, 0x94C8, 0xBD94, 0x94C9, 0xBD96, 0x94CA, 0xBD97, 0x94CB, 0xBD98, 0x94CC, 0xBD9B, 0x94CD, 0xBD9D, 0x94CE, 0xBD9E, + 0x94CF, 0xBD9F, 0x94D0, 0xBDA0, 0x94D1, 0xBDA1, 0x94D2, 0xBDA2, 0x94D3, 0xBDA3, 0x94D4, 0xBDA5, 0x94D5, 0xBDA6, 0x94D6, 0xBDA7, + 0x94D7, 0xBDA8, 0x94D8, 0xBDA9, 0x94D9, 0xBDAA, 0x94DA, 0xBDAB, 0x94DB, 0xBDAC, 0x94DC, 0xBDAD, 0x94DD, 0xBDAE, 0x94DE, 0xBDAF, + 0x94DF, 0xBDB1, 0x94E0, 0xBDB2, 0x94E1, 0xBDB3, 0x94E2, 0xBDB4, 0x94E3, 0xBDB5, 0x94E4, 0xBDB6, 0x94E5, 0xBDB7, 0x94E6, 0xBDB9, + 0x94E7, 0xBDBA, 0x94E8, 0xBDBB, 0x94E9, 0xBDBC, 0x94EA, 0xBDBD, 0x94EB, 0xBDBE, 0x94EC, 0xBDBF, 0x94ED, 0xBDC0, 0x94EE, 0xBDC1, + 0x94EF, 0xBDC2, 0x94F0, 0xBDC3, 0x94F1, 0xBDC4, 0x94F2, 0xBDC5, 0x94F3, 0xBDC6, 0x94F4, 0xBDC7, 0x94F5, 0xBDC8, 0x94F6, 0xBDC9, + 0x94F7, 0xBDCA, 0x94F8, 0xBDCB, 0x94F9, 0xBDCC, 0x94FA, 0xBDCD, 0x94FB, 0xBDCE, 0x94FC, 0xBDCF, 0x94FD, 0xBDD0, 0x94FE, 0xBDD1, + 0x9541, 0xBDD2, 0x9542, 0xBDD3, 0x9543, 0xBDD6, 0x9544, 0xBDD7, 0x9545, 0xBDD9, 0x9546, 0xBDDA, 0x9547, 0xBDDB, 0x9548, 0xBDDD, + 0x9549, 0xBDDE, 0x954A, 0xBDDF, 0x954B, 0xBDE0, 0x954C, 0xBDE1, 0x954D, 0xBDE2, 0x954E, 0xBDE3, 0x954F, 0xBDE4, 0x9550, 0xBDE5, + 0x9551, 0xBDE6, 0x9552, 0xBDE7, 0x9553, 0xBDE8, 0x9554, 0xBDEA, 0x9555, 0xBDEB, 0x9556, 0xBDEC, 0x9557, 0xBDED, 0x9558, 0xBDEE, + 0x9559, 0xBDEF, 0x955A, 0xBDF1, 0x9561, 0xBDF2, 0x9562, 0xBDF3, 0x9563, 0xBDF5, 0x9564, 0xBDF6, 0x9565, 0xBDF7, 0x9566, 0xBDF9, + 0x9567, 0xBDFA, 0x9568, 0xBDFB, 0x9569, 0xBDFC, 0x956A, 0xBDFD, 0x956B, 0xBDFE, 0x956C, 0xBDFF, 0x956D, 0xBE01, 0x956E, 0xBE02, + 0x956F, 0xBE04, 0x9570, 0xBE06, 0x9571, 0xBE07, 0x9572, 0xBE08, 0x9573, 0xBE09, 0x9574, 0xBE0A, 0x9575, 0xBE0B, 0x9576, 0xBE0E, + 0x9577, 0xBE0F, 0x9578, 0xBE11, 0x9579, 0xBE12, 0x957A, 0xBE13, 0x9581, 0xBE15, 0x9582, 0xBE16, 0x9583, 0xBE17, 0x9584, 0xBE18, + 0x9585, 0xBE19, 0x9586, 0xBE1A, 0x9587, 0xBE1B, 0x9588, 0xBE1E, 0x9589, 0xBE20, 0x958A, 0xBE21, 0x958B, 0xBE22, 0x958C, 0xBE23, + 0x958D, 0xBE24, 0x958E, 0xBE25, 0x958F, 0xBE26, 0x9590, 0xBE27, 0x9591, 0xBE28, 0x9592, 0xBE29, 0x9593, 0xBE2A, 0x9594, 0xBE2B, + 0x9595, 0xBE2C, 0x9596, 0xBE2D, 0x9597, 0xBE2E, 0x9598, 0xBE2F, 0x9599, 0xBE30, 0x959A, 0xBE31, 0x959B, 0xBE32, 0x959C, 0xBE33, + 0x959D, 0xBE34, 0x959E, 0xBE35, 0x959F, 0xBE36, 0x95A0, 0xBE37, 0x95A1, 0xBE38, 0x95A2, 0xBE39, 0x95A3, 0xBE3A, 0x95A4, 0xBE3B, + 0x95A5, 0xBE3C, 0x95A6, 0xBE3D, 0x95A7, 0xBE3E, 0x95A8, 0xBE3F, 0x95A9, 0xBE40, 0x95AA, 0xBE41, 0x95AB, 0xBE42, 0x95AC, 0xBE43, + 0x95AD, 0xBE46, 0x95AE, 0xBE47, 0x95AF, 0xBE49, 0x95B0, 0xBE4A, 0x95B1, 0xBE4B, 0x95B2, 0xBE4D, 0x95B3, 0xBE4F, 0x95B4, 0xBE50, + 0x95B5, 0xBE51, 0x95B6, 0xBE52, 0x95B7, 0xBE53, 0x95B8, 0xBE56, 0x95B9, 0xBE58, 0x95BA, 0xBE5C, 0x95BB, 0xBE5D, 0x95BC, 0xBE5E, + 0x95BD, 0xBE5F, 0x95BE, 0xBE62, 0x95BF, 0xBE63, 0x95C0, 0xBE65, 0x95C1, 0xBE66, 0x95C2, 0xBE67, 0x95C3, 0xBE69, 0x95C4, 0xBE6B, + 0x95C5, 0xBE6C, 0x95C6, 0xBE6D, 0x95C7, 0xBE6E, 0x95C8, 0xBE6F, 0x95C9, 0xBE72, 0x95CA, 0xBE76, 0x95CB, 0xBE77, 0x95CC, 0xBE78, + 0x95CD, 0xBE79, 0x95CE, 0xBE7A, 0x95CF, 0xBE7E, 0x95D0, 0xBE7F, 0x95D1, 0xBE81, 0x95D2, 0xBE82, 0x95D3, 0xBE83, 0x95D4, 0xBE85, + 0x95D5, 0xBE86, 0x95D6, 0xBE87, 0x95D7, 0xBE88, 0x95D8, 0xBE89, 0x95D9, 0xBE8A, 0x95DA, 0xBE8B, 0x95DB, 0xBE8E, 0x95DC, 0xBE92, + 0x95DD, 0xBE93, 0x95DE, 0xBE94, 0x95DF, 0xBE95, 0x95E0, 0xBE96, 0x95E1, 0xBE97, 0x95E2, 0xBE9A, 0x95E3, 0xBE9B, 0x95E4, 0xBE9C, + 0x95E5, 0xBE9D, 0x95E6, 0xBE9E, 0x95E7, 0xBE9F, 0x95E8, 0xBEA0, 0x95E9, 0xBEA1, 0x95EA, 0xBEA2, 0x95EB, 0xBEA3, 0x95EC, 0xBEA4, + 0x95ED, 0xBEA5, 0x95EE, 0xBEA6, 0x95EF, 0xBEA7, 0x95F0, 0xBEA9, 0x95F1, 0xBEAA, 0x95F2, 0xBEAB, 0x95F3, 0xBEAC, 0x95F4, 0xBEAD, + 0x95F5, 0xBEAE, 0x95F6, 0xBEAF, 0x95F7, 0xBEB0, 0x95F8, 0xBEB1, 0x95F9, 0xBEB2, 0x95FA, 0xBEB3, 0x95FB, 0xBEB4, 0x95FC, 0xBEB5, + 0x95FD, 0xBEB6, 0x95FE, 0xBEB7, 0x9641, 0xBEB8, 0x9642, 0xBEB9, 0x9643, 0xBEBA, 0x9644, 0xBEBB, 0x9645, 0xBEBC, 0x9646, 0xBEBD, + 0x9647, 0xBEBE, 0x9648, 0xBEBF, 0x9649, 0xBEC0, 0x964A, 0xBEC1, 0x964B, 0xBEC2, 0x964C, 0xBEC3, 0x964D, 0xBEC4, 0x964E, 0xBEC5, + 0x964F, 0xBEC6, 0x9650, 0xBEC7, 0x9651, 0xBEC8, 0x9652, 0xBEC9, 0x9653, 0xBECA, 0x9654, 0xBECB, 0x9655, 0xBECC, 0x9656, 0xBECD, + 0x9657, 0xBECE, 0x9658, 0xBECF, 0x9659, 0xBED2, 0x965A, 0xBED3, 0x9661, 0xBED5, 0x9662, 0xBED6, 0x9663, 0xBED9, 0x9664, 0xBEDA, + 0x9665, 0xBEDB, 0x9666, 0xBEDC, 0x9667, 0xBEDD, 0x9668, 0xBEDE, 0x9669, 0xBEDF, 0x966A, 0xBEE1, 0x966B, 0xBEE2, 0x966C, 0xBEE6, + 0x966D, 0xBEE7, 0x966E, 0xBEE8, 0x966F, 0xBEE9, 0x9670, 0xBEEA, 0x9671, 0xBEEB, 0x9672, 0xBEED, 0x9673, 0xBEEE, 0x9674, 0xBEEF, + 0x9675, 0xBEF0, 0x9676, 0xBEF1, 0x9677, 0xBEF2, 0x9678, 0xBEF3, 0x9679, 0xBEF4, 0x967A, 0xBEF5, 0x9681, 0xBEF6, 0x9682, 0xBEF7, + 0x9683, 0xBEF8, 0x9684, 0xBEF9, 0x9685, 0xBEFA, 0x9686, 0xBEFB, 0x9687, 0xBEFC, 0x9688, 0xBEFD, 0x9689, 0xBEFE, 0x968A, 0xBEFF, + 0x968B, 0xBF00, 0x968C, 0xBF02, 0x968D, 0xBF03, 0x968E, 0xBF04, 0x968F, 0xBF05, 0x9690, 0xBF06, 0x9691, 0xBF07, 0x9692, 0xBF0A, + 0x9693, 0xBF0B, 0x9694, 0xBF0C, 0x9695, 0xBF0D, 0x9696, 0xBF0E, 0x9697, 0xBF0F, 0x9698, 0xBF10, 0x9699, 0xBF11, 0x969A, 0xBF12, + 0x969B, 0xBF13, 0x969C, 0xBF14, 0x969D, 0xBF15, 0x969E, 0xBF16, 0x969F, 0xBF17, 0x96A0, 0xBF1A, 0x96A1, 0xBF1E, 0x96A2, 0xBF1F, + 0x96A3, 0xBF20, 0x96A4, 0xBF21, 0x96A5, 0xBF22, 0x96A6, 0xBF23, 0x96A7, 0xBF24, 0x96A8, 0xBF25, 0x96A9, 0xBF26, 0x96AA, 0xBF27, + 0x96AB, 0xBF28, 0x96AC, 0xBF29, 0x96AD, 0xBF2A, 0x96AE, 0xBF2B, 0x96AF, 0xBF2C, 0x96B0, 0xBF2D, 0x96B1, 0xBF2E, 0x96B2, 0xBF2F, + 0x96B3, 0xBF30, 0x96B4, 0xBF31, 0x96B5, 0xBF32, 0x96B6, 0xBF33, 0x96B7, 0xBF34, 0x96B8, 0xBF35, 0x96B9, 0xBF36, 0x96BA, 0xBF37, + 0x96BB, 0xBF38, 0x96BC, 0xBF39, 0x96BD, 0xBF3A, 0x96BE, 0xBF3B, 0x96BF, 0xBF3C, 0x96C0, 0xBF3D, 0x96C1, 0xBF3E, 0x96C2, 0xBF3F, + 0x96C3, 0xBF42, 0x96C4, 0xBF43, 0x96C5, 0xBF45, 0x96C6, 0xBF46, 0x96C7, 0xBF47, 0x96C8, 0xBF49, 0x96C9, 0xBF4A, 0x96CA, 0xBF4B, + 0x96CB, 0xBF4C, 0x96CC, 0xBF4D, 0x96CD, 0xBF4E, 0x96CE, 0xBF4F, 0x96CF, 0xBF52, 0x96D0, 0xBF53, 0x96D1, 0xBF54, 0x96D2, 0xBF56, + 0x96D3, 0xBF57, 0x96D4, 0xBF58, 0x96D5, 0xBF59, 0x96D6, 0xBF5A, 0x96D7, 0xBF5B, 0x96D8, 0xBF5C, 0x96D9, 0xBF5D, 0x96DA, 0xBF5E, + 0x96DB, 0xBF5F, 0x96DC, 0xBF60, 0x96DD, 0xBF61, 0x96DE, 0xBF62, 0x96DF, 0xBF63, 0x96E0, 0xBF64, 0x96E1, 0xBF65, 0x96E2, 0xBF66, + 0x96E3, 0xBF67, 0x96E4, 0xBF68, 0x96E5, 0xBF69, 0x96E6, 0xBF6A, 0x96E7, 0xBF6B, 0x96E8, 0xBF6C, 0x96E9, 0xBF6D, 0x96EA, 0xBF6E, + 0x96EB, 0xBF6F, 0x96EC, 0xBF70, 0x96ED, 0xBF71, 0x96EE, 0xBF72, 0x96EF, 0xBF73, 0x96F0, 0xBF74, 0x96F1, 0xBF75, 0x96F2, 0xBF76, + 0x96F3, 0xBF77, 0x96F4, 0xBF78, 0x96F5, 0xBF79, 0x96F6, 0xBF7A, 0x96F7, 0xBF7B, 0x96F8, 0xBF7C, 0x96F9, 0xBF7D, 0x96FA, 0xBF7E, + 0x96FB, 0xBF7F, 0x96FC, 0xBF80, 0x96FD, 0xBF81, 0x96FE, 0xBF82, 0x9741, 0xBF83, 0x9742, 0xBF84, 0x9743, 0xBF85, 0x9744, 0xBF86, + 0x9745, 0xBF87, 0x9746, 0xBF88, 0x9747, 0xBF89, 0x9748, 0xBF8A, 0x9749, 0xBF8B, 0x974A, 0xBF8C, 0x974B, 0xBF8D, 0x974C, 0xBF8E, + 0x974D, 0xBF8F, 0x974E, 0xBF90, 0x974F, 0xBF91, 0x9750, 0xBF92, 0x9751, 0xBF93, 0x9752, 0xBF95, 0x9753, 0xBF96, 0x9754, 0xBF97, + 0x9755, 0xBF98, 0x9756, 0xBF99, 0x9757, 0xBF9A, 0x9758, 0xBF9B, 0x9759, 0xBF9C, 0x975A, 0xBF9D, 0x9761, 0xBF9E, 0x9762, 0xBF9F, + 0x9763, 0xBFA0, 0x9764, 0xBFA1, 0x9765, 0xBFA2, 0x9766, 0xBFA3, 0x9767, 0xBFA4, 0x9768, 0xBFA5, 0x9769, 0xBFA6, 0x976A, 0xBFA7, + 0x976B, 0xBFA8, 0x976C, 0xBFA9, 0x976D, 0xBFAA, 0x976E, 0xBFAB, 0x976F, 0xBFAC, 0x9770, 0xBFAD, 0x9771, 0xBFAE, 0x9772, 0xBFAF, + 0x9773, 0xBFB1, 0x9774, 0xBFB2, 0x9775, 0xBFB3, 0x9776, 0xBFB4, 0x9777, 0xBFB5, 0x9778, 0xBFB6, 0x9779, 0xBFB7, 0x977A, 0xBFB8, + 0x9781, 0xBFB9, 0x9782, 0xBFBA, 0x9783, 0xBFBB, 0x9784, 0xBFBC, 0x9785, 0xBFBD, 0x9786, 0xBFBE, 0x9787, 0xBFBF, 0x9788, 0xBFC0, + 0x9789, 0xBFC1, 0x978A, 0xBFC2, 0x978B, 0xBFC3, 0x978C, 0xBFC4, 0x978D, 0xBFC6, 0x978E, 0xBFC7, 0x978F, 0xBFC8, 0x9790, 0xBFC9, + 0x9791, 0xBFCA, 0x9792, 0xBFCB, 0x9793, 0xBFCE, 0x9794, 0xBFCF, 0x9795, 0xBFD1, 0x9796, 0xBFD2, 0x9797, 0xBFD3, 0x9798, 0xBFD5, + 0x9799, 0xBFD6, 0x979A, 0xBFD7, 0x979B, 0xBFD8, 0x979C, 0xBFD9, 0x979D, 0xBFDA, 0x979E, 0xBFDB, 0x979F, 0xBFDD, 0x97A0, 0xBFDE, + 0x97A1, 0xBFE0, 0x97A2, 0xBFE2, 0x97A3, 0xBFE3, 0x97A4, 0xBFE4, 0x97A5, 0xBFE5, 0x97A6, 0xBFE6, 0x97A7, 0xBFE7, 0x97A8, 0xBFE8, + 0x97A9, 0xBFE9, 0x97AA, 0xBFEA, 0x97AB, 0xBFEB, 0x97AC, 0xBFEC, 0x97AD, 0xBFED, 0x97AE, 0xBFEE, 0x97AF, 0xBFEF, 0x97B0, 0xBFF0, + 0x97B1, 0xBFF1, 0x97B2, 0xBFF2, 0x97B3, 0xBFF3, 0x97B4, 0xBFF4, 0x97B5, 0xBFF5, 0x97B6, 0xBFF6, 0x97B7, 0xBFF7, 0x97B8, 0xBFF8, + 0x97B9, 0xBFF9, 0x97BA, 0xBFFA, 0x97BB, 0xBFFB, 0x97BC, 0xBFFC, 0x97BD, 0xBFFD, 0x97BE, 0xBFFE, 0x97BF, 0xBFFF, 0x97C0, 0xC000, + 0x97C1, 0xC001, 0x97C2, 0xC002, 0x97C3, 0xC003, 0x97C4, 0xC004, 0x97C5, 0xC005, 0x97C6, 0xC006, 0x97C7, 0xC007, 0x97C8, 0xC008, + 0x97C9, 0xC009, 0x97CA, 0xC00A, 0x97CB, 0xC00B, 0x97CC, 0xC00C, 0x97CD, 0xC00D, 0x97CE, 0xC00E, 0x97CF, 0xC00F, 0x97D0, 0xC010, + 0x97D1, 0xC011, 0x97D2, 0xC012, 0x97D3, 0xC013, 0x97D4, 0xC014, 0x97D5, 0xC015, 0x97D6, 0xC016, 0x97D7, 0xC017, 0x97D8, 0xC018, + 0x97D9, 0xC019, 0x97DA, 0xC01A, 0x97DB, 0xC01B, 0x97DC, 0xC01C, 0x97DD, 0xC01D, 0x97DE, 0xC01E, 0x97DF, 0xC01F, 0x97E0, 0xC020, + 0x97E1, 0xC021, 0x97E2, 0xC022, 0x97E3, 0xC023, 0x97E4, 0xC024, 0x97E5, 0xC025, 0x97E6, 0xC026, 0x97E7, 0xC027, 0x97E8, 0xC028, + 0x97E9, 0xC029, 0x97EA, 0xC02A, 0x97EB, 0xC02B, 0x97EC, 0xC02C, 0x97ED, 0xC02D, 0x97EE, 0xC02E, 0x97EF, 0xC02F, 0x97F0, 0xC030, + 0x97F1, 0xC031, 0x97F2, 0xC032, 0x97F3, 0xC033, 0x97F4, 0xC034, 0x97F5, 0xC035, 0x97F6, 0xC036, 0x97F7, 0xC037, 0x97F8, 0xC038, + 0x97F9, 0xC039, 0x97FA, 0xC03A, 0x97FB, 0xC03B, 0x97FC, 0xC03D, 0x97FD, 0xC03E, 0x97FE, 0xC03F, 0x9841, 0xC040, 0x9842, 0xC041, + 0x9843, 0xC042, 0x9844, 0xC043, 0x9845, 0xC044, 0x9846, 0xC045, 0x9847, 0xC046, 0x9848, 0xC047, 0x9849, 0xC048, 0x984A, 0xC049, + 0x984B, 0xC04A, 0x984C, 0xC04B, 0x984D, 0xC04C, 0x984E, 0xC04D, 0x984F, 0xC04E, 0x9850, 0xC04F, 0x9851, 0xC050, 0x9852, 0xC052, + 0x9853, 0xC053, 0x9854, 0xC054, 0x9855, 0xC055, 0x9856, 0xC056, 0x9857, 0xC057, 0x9858, 0xC059, 0x9859, 0xC05A, 0x985A, 0xC05B, + 0x9861, 0xC05D, 0x9862, 0xC05E, 0x9863, 0xC05F, 0x9864, 0xC061, 0x9865, 0xC062, 0x9866, 0xC063, 0x9867, 0xC064, 0x9868, 0xC065, + 0x9869, 0xC066, 0x986A, 0xC067, 0x986B, 0xC06A, 0x986C, 0xC06B, 0x986D, 0xC06C, 0x986E, 0xC06D, 0x986F, 0xC06E, 0x9870, 0xC06F, + 0x9871, 0xC070, 0x9872, 0xC071, 0x9873, 0xC072, 0x9874, 0xC073, 0x9875, 0xC074, 0x9876, 0xC075, 0x9877, 0xC076, 0x9878, 0xC077, + 0x9879, 0xC078, 0x987A, 0xC079, 0x9881, 0xC07A, 0x9882, 0xC07B, 0x9883, 0xC07C, 0x9884, 0xC07D, 0x9885, 0xC07E, 0x9886, 0xC07F, + 0x9887, 0xC080, 0x9888, 0xC081, 0x9889, 0xC082, 0x988A, 0xC083, 0x988B, 0xC084, 0x988C, 0xC085, 0x988D, 0xC086, 0x988E, 0xC087, + 0x988F, 0xC088, 0x9890, 0xC089, 0x9891, 0xC08A, 0x9892, 0xC08B, 0x9893, 0xC08C, 0x9894, 0xC08D, 0x9895, 0xC08E, 0x9896, 0xC08F, + 0x9897, 0xC092, 0x9898, 0xC093, 0x9899, 0xC095, 0x989A, 0xC096, 0x989B, 0xC097, 0x989C, 0xC099, 0x989D, 0xC09A, 0x989E, 0xC09B, + 0x989F, 0xC09C, 0x98A0, 0xC09D, 0x98A1, 0xC09E, 0x98A2, 0xC09F, 0x98A3, 0xC0A2, 0x98A4, 0xC0A4, 0x98A5, 0xC0A6, 0x98A6, 0xC0A7, + 0x98A7, 0xC0A8, 0x98A8, 0xC0A9, 0x98A9, 0xC0AA, 0x98AA, 0xC0AB, 0x98AB, 0xC0AE, 0x98AC, 0xC0B1, 0x98AD, 0xC0B2, 0x98AE, 0xC0B7, + 0x98AF, 0xC0B8, 0x98B0, 0xC0B9, 0x98B1, 0xC0BA, 0x98B2, 0xC0BB, 0x98B3, 0xC0BE, 0x98B4, 0xC0C2, 0x98B5, 0xC0C3, 0x98B6, 0xC0C4, + 0x98B7, 0xC0C6, 0x98B8, 0xC0C7, 0x98B9, 0xC0CA, 0x98BA, 0xC0CB, 0x98BB, 0xC0CD, 0x98BC, 0xC0CE, 0x98BD, 0xC0CF, 0x98BE, 0xC0D1, + 0x98BF, 0xC0D2, 0x98C0, 0xC0D3, 0x98C1, 0xC0D4, 0x98C2, 0xC0D5, 0x98C3, 0xC0D6, 0x98C4, 0xC0D7, 0x98C5, 0xC0DA, 0x98C6, 0xC0DE, + 0x98C7, 0xC0DF, 0x98C8, 0xC0E0, 0x98C9, 0xC0E1, 0x98CA, 0xC0E2, 0x98CB, 0xC0E3, 0x98CC, 0xC0E6, 0x98CD, 0xC0E7, 0x98CE, 0xC0E9, + 0x98CF, 0xC0EA, 0x98D0, 0xC0EB, 0x98D1, 0xC0ED, 0x98D2, 0xC0EE, 0x98D3, 0xC0EF, 0x98D4, 0xC0F0, 0x98D5, 0xC0F1, 0x98D6, 0xC0F2, + 0x98D7, 0xC0F3, 0x98D8, 0xC0F6, 0x98D9, 0xC0F8, 0x98DA, 0xC0FA, 0x98DB, 0xC0FB, 0x98DC, 0xC0FC, 0x98DD, 0xC0FD, 0x98DE, 0xC0FE, + 0x98DF, 0xC0FF, 0x98E0, 0xC101, 0x98E1, 0xC102, 0x98E2, 0xC103, 0x98E3, 0xC105, 0x98E4, 0xC106, 0x98E5, 0xC107, 0x98E6, 0xC109, + 0x98E7, 0xC10A, 0x98E8, 0xC10B, 0x98E9, 0xC10C, 0x98EA, 0xC10D, 0x98EB, 0xC10E, 0x98EC, 0xC10F, 0x98ED, 0xC111, 0x98EE, 0xC112, + 0x98EF, 0xC113, 0x98F0, 0xC114, 0x98F1, 0xC116, 0x98F2, 0xC117, 0x98F3, 0xC118, 0x98F4, 0xC119, 0x98F5, 0xC11A, 0x98F6, 0xC11B, + 0x98F7, 0xC121, 0x98F8, 0xC122, 0x98F9, 0xC125, 0x98FA, 0xC128, 0x98FB, 0xC129, 0x98FC, 0xC12A, 0x98FD, 0xC12B, 0x98FE, 0xC12E, + 0x9941, 0xC132, 0x9942, 0xC133, 0x9943, 0xC134, 0x9944, 0xC135, 0x9945, 0xC137, 0x9946, 0xC13A, 0x9947, 0xC13B, 0x9948, 0xC13D, + 0x9949, 0xC13E, 0x994A, 0xC13F, 0x994B, 0xC141, 0x994C, 0xC142, 0x994D, 0xC143, 0x994E, 0xC144, 0x994F, 0xC145, 0x9950, 0xC146, + 0x9951, 0xC147, 0x9952, 0xC14A, 0x9953, 0xC14E, 0x9954, 0xC14F, 0x9955, 0xC150, 0x9956, 0xC151, 0x9957, 0xC152, 0x9958, 0xC153, + 0x9959, 0xC156, 0x995A, 0xC157, 0x9961, 0xC159, 0x9962, 0xC15A, 0x9963, 0xC15B, 0x9964, 0xC15D, 0x9965, 0xC15E, 0x9966, 0xC15F, + 0x9967, 0xC160, 0x9968, 0xC161, 0x9969, 0xC162, 0x996A, 0xC163, 0x996B, 0xC166, 0x996C, 0xC16A, 0x996D, 0xC16B, 0x996E, 0xC16C, + 0x996F, 0xC16D, 0x9970, 0xC16E, 0x9971, 0xC16F, 0x9972, 0xC171, 0x9973, 0xC172, 0x9974, 0xC173, 0x9975, 0xC175, 0x9976, 0xC176, + 0x9977, 0xC177, 0x9978, 0xC179, 0x9979, 0xC17A, 0x997A, 0xC17B, 0x9981, 0xC17C, 0x9982, 0xC17D, 0x9983, 0xC17E, 0x9984, 0xC17F, + 0x9985, 0xC180, 0x9986, 0xC181, 0x9987, 0xC182, 0x9988, 0xC183, 0x9989, 0xC184, 0x998A, 0xC186, 0x998B, 0xC187, 0x998C, 0xC188, + 0x998D, 0xC189, 0x998E, 0xC18A, 0x998F, 0xC18B, 0x9990, 0xC18F, 0x9991, 0xC191, 0x9992, 0xC192, 0x9993, 0xC193, 0x9994, 0xC195, + 0x9995, 0xC197, 0x9996, 0xC198, 0x9997, 0xC199, 0x9998, 0xC19A, 0x9999, 0xC19B, 0x999A, 0xC19E, 0x999B, 0xC1A0, 0x999C, 0xC1A2, + 0x999D, 0xC1A3, 0x999E, 0xC1A4, 0x999F, 0xC1A6, 0x99A0, 0xC1A7, 0x99A1, 0xC1AA, 0x99A2, 0xC1AB, 0x99A3, 0xC1AD, 0x99A4, 0xC1AE, + 0x99A5, 0xC1AF, 0x99A6, 0xC1B1, 0x99A7, 0xC1B2, 0x99A8, 0xC1B3, 0x99A9, 0xC1B4, 0x99AA, 0xC1B5, 0x99AB, 0xC1B6, 0x99AC, 0xC1B7, + 0x99AD, 0xC1B8, 0x99AE, 0xC1B9, 0x99AF, 0xC1BA, 0x99B0, 0xC1BB, 0x99B1, 0xC1BC, 0x99B2, 0xC1BE, 0x99B3, 0xC1BF, 0x99B4, 0xC1C0, + 0x99B5, 0xC1C1, 0x99B6, 0xC1C2, 0x99B7, 0xC1C3, 0x99B8, 0xC1C5, 0x99B9, 0xC1C6, 0x99BA, 0xC1C7, 0x99BB, 0xC1C9, 0x99BC, 0xC1CA, + 0x99BD, 0xC1CB, 0x99BE, 0xC1CD, 0x99BF, 0xC1CE, 0x99C0, 0xC1CF, 0x99C1, 0xC1D0, 0x99C2, 0xC1D1, 0x99C3, 0xC1D2, 0x99C4, 0xC1D3, + 0x99C5, 0xC1D5, 0x99C6, 0xC1D6, 0x99C7, 0xC1D9, 0x99C8, 0xC1DA, 0x99C9, 0xC1DB, 0x99CA, 0xC1DC, 0x99CB, 0xC1DD, 0x99CC, 0xC1DE, + 0x99CD, 0xC1DF, 0x99CE, 0xC1E1, 0x99CF, 0xC1E2, 0x99D0, 0xC1E3, 0x99D1, 0xC1E5, 0x99D2, 0xC1E6, 0x99D3, 0xC1E7, 0x99D4, 0xC1E9, + 0x99D5, 0xC1EA, 0x99D6, 0xC1EB, 0x99D7, 0xC1EC, 0x99D8, 0xC1ED, 0x99D9, 0xC1EE, 0x99DA, 0xC1EF, 0x99DB, 0xC1F2, 0x99DC, 0xC1F4, + 0x99DD, 0xC1F5, 0x99DE, 0xC1F6, 0x99DF, 0xC1F7, 0x99E0, 0xC1F8, 0x99E1, 0xC1F9, 0x99E2, 0xC1FA, 0x99E3, 0xC1FB, 0x99E4, 0xC1FE, + 0x99E5, 0xC1FF, 0x99E6, 0xC201, 0x99E7, 0xC202, 0x99E8, 0xC203, 0x99E9, 0xC205, 0x99EA, 0xC206, 0x99EB, 0xC207, 0x99EC, 0xC208, + 0x99ED, 0xC209, 0x99EE, 0xC20A, 0x99EF, 0xC20B, 0x99F0, 0xC20E, 0x99F1, 0xC210, 0x99F2, 0xC212, 0x99F3, 0xC213, 0x99F4, 0xC214, + 0x99F5, 0xC215, 0x99F6, 0xC216, 0x99F7, 0xC217, 0x99F8, 0xC21A, 0x99F9, 0xC21B, 0x99FA, 0xC21D, 0x99FB, 0xC21E, 0x99FC, 0xC221, + 0x99FD, 0xC222, 0x99FE, 0xC223, 0x9A41, 0xC224, 0x9A42, 0xC225, 0x9A43, 0xC226, 0x9A44, 0xC227, 0x9A45, 0xC22A, 0x9A46, 0xC22C, + 0x9A47, 0xC22E, 0x9A48, 0xC230, 0x9A49, 0xC233, 0x9A4A, 0xC235, 0x9A4B, 0xC236, 0x9A4C, 0xC237, 0x9A4D, 0xC238, 0x9A4E, 0xC239, + 0x9A4F, 0xC23A, 0x9A50, 0xC23B, 0x9A51, 0xC23C, 0x9A52, 0xC23D, 0x9A53, 0xC23E, 0x9A54, 0xC23F, 0x9A55, 0xC240, 0x9A56, 0xC241, + 0x9A57, 0xC242, 0x9A58, 0xC243, 0x9A59, 0xC244, 0x9A5A, 0xC245, 0x9A61, 0xC246, 0x9A62, 0xC247, 0x9A63, 0xC249, 0x9A64, 0xC24A, + 0x9A65, 0xC24B, 0x9A66, 0xC24C, 0x9A67, 0xC24D, 0x9A68, 0xC24E, 0x9A69, 0xC24F, 0x9A6A, 0xC252, 0x9A6B, 0xC253, 0x9A6C, 0xC255, + 0x9A6D, 0xC256, 0x9A6E, 0xC257, 0x9A6F, 0xC259, 0x9A70, 0xC25A, 0x9A71, 0xC25B, 0x9A72, 0xC25C, 0x9A73, 0xC25D, 0x9A74, 0xC25E, + 0x9A75, 0xC25F, 0x9A76, 0xC261, 0x9A77, 0xC262, 0x9A78, 0xC263, 0x9A79, 0xC264, 0x9A7A, 0xC266, 0x9A81, 0xC267, 0x9A82, 0xC268, + 0x9A83, 0xC269, 0x9A84, 0xC26A, 0x9A85, 0xC26B, 0x9A86, 0xC26E, 0x9A87, 0xC26F, 0x9A88, 0xC271, 0x9A89, 0xC272, 0x9A8A, 0xC273, + 0x9A8B, 0xC275, 0x9A8C, 0xC276, 0x9A8D, 0xC277, 0x9A8E, 0xC278, 0x9A8F, 0xC279, 0x9A90, 0xC27A, 0x9A91, 0xC27B, 0x9A92, 0xC27E, + 0x9A93, 0xC280, 0x9A94, 0xC282, 0x9A95, 0xC283, 0x9A96, 0xC284, 0x9A97, 0xC285, 0x9A98, 0xC286, 0x9A99, 0xC287, 0x9A9A, 0xC28A, + 0x9A9B, 0xC28B, 0x9A9C, 0xC28C, 0x9A9D, 0xC28D, 0x9A9E, 0xC28E, 0x9A9F, 0xC28F, 0x9AA0, 0xC291, 0x9AA1, 0xC292, 0x9AA2, 0xC293, + 0x9AA3, 0xC294, 0x9AA4, 0xC295, 0x9AA5, 0xC296, 0x9AA6, 0xC297, 0x9AA7, 0xC299, 0x9AA8, 0xC29A, 0x9AA9, 0xC29C, 0x9AAA, 0xC29E, + 0x9AAB, 0xC29F, 0x9AAC, 0xC2A0, 0x9AAD, 0xC2A1, 0x9AAE, 0xC2A2, 0x9AAF, 0xC2A3, 0x9AB0, 0xC2A6, 0x9AB1, 0xC2A7, 0x9AB2, 0xC2A9, + 0x9AB3, 0xC2AA, 0x9AB4, 0xC2AB, 0x9AB5, 0xC2AE, 0x9AB6, 0xC2AF, 0x9AB7, 0xC2B0, 0x9AB8, 0xC2B1, 0x9AB9, 0xC2B2, 0x9ABA, 0xC2B3, + 0x9ABB, 0xC2B6, 0x9ABC, 0xC2B8, 0x9ABD, 0xC2BA, 0x9ABE, 0xC2BB, 0x9ABF, 0xC2BC, 0x9AC0, 0xC2BD, 0x9AC1, 0xC2BE, 0x9AC2, 0xC2BF, + 0x9AC3, 0xC2C0, 0x9AC4, 0xC2C1, 0x9AC5, 0xC2C2, 0x9AC6, 0xC2C3, 0x9AC7, 0xC2C4, 0x9AC8, 0xC2C5, 0x9AC9, 0xC2C6, 0x9ACA, 0xC2C7, + 0x9ACB, 0xC2C8, 0x9ACC, 0xC2C9, 0x9ACD, 0xC2CA, 0x9ACE, 0xC2CB, 0x9ACF, 0xC2CC, 0x9AD0, 0xC2CD, 0x9AD1, 0xC2CE, 0x9AD2, 0xC2CF, + 0x9AD3, 0xC2D0, 0x9AD4, 0xC2D1, 0x9AD5, 0xC2D2, 0x9AD6, 0xC2D3, 0x9AD7, 0xC2D4, 0x9AD8, 0xC2D5, 0x9AD9, 0xC2D6, 0x9ADA, 0xC2D7, + 0x9ADB, 0xC2D8, 0x9ADC, 0xC2D9, 0x9ADD, 0xC2DA, 0x9ADE, 0xC2DB, 0x9ADF, 0xC2DE, 0x9AE0, 0xC2DF, 0x9AE1, 0xC2E1, 0x9AE2, 0xC2E2, + 0x9AE3, 0xC2E5, 0x9AE4, 0xC2E6, 0x9AE5, 0xC2E7, 0x9AE6, 0xC2E8, 0x9AE7, 0xC2E9, 0x9AE8, 0xC2EA, 0x9AE9, 0xC2EE, 0x9AEA, 0xC2F0, + 0x9AEB, 0xC2F2, 0x9AEC, 0xC2F3, 0x9AED, 0xC2F4, 0x9AEE, 0xC2F5, 0x9AEF, 0xC2F7, 0x9AF0, 0xC2FA, 0x9AF1, 0xC2FD, 0x9AF2, 0xC2FE, + 0x9AF3, 0xC2FF, 0x9AF4, 0xC301, 0x9AF5, 0xC302, 0x9AF6, 0xC303, 0x9AF7, 0xC304, 0x9AF8, 0xC305, 0x9AF9, 0xC306, 0x9AFA, 0xC307, + 0x9AFB, 0xC30A, 0x9AFC, 0xC30B, 0x9AFD, 0xC30E, 0x9AFE, 0xC30F, 0x9B41, 0xC310, 0x9B42, 0xC311, 0x9B43, 0xC312, 0x9B44, 0xC316, + 0x9B45, 0xC317, 0x9B46, 0xC319, 0x9B47, 0xC31A, 0x9B48, 0xC31B, 0x9B49, 0xC31D, 0x9B4A, 0xC31E, 0x9B4B, 0xC31F, 0x9B4C, 0xC320, + 0x9B4D, 0xC321, 0x9B4E, 0xC322, 0x9B4F, 0xC323, 0x9B50, 0xC326, 0x9B51, 0xC327, 0x9B52, 0xC32A, 0x9B53, 0xC32B, 0x9B54, 0xC32C, + 0x9B55, 0xC32D, 0x9B56, 0xC32E, 0x9B57, 0xC32F, 0x9B58, 0xC330, 0x9B59, 0xC331, 0x9B5A, 0xC332, 0x9B61, 0xC333, 0x9B62, 0xC334, + 0x9B63, 0xC335, 0x9B64, 0xC336, 0x9B65, 0xC337, 0x9B66, 0xC338, 0x9B67, 0xC339, 0x9B68, 0xC33A, 0x9B69, 0xC33B, 0x9B6A, 0xC33C, + 0x9B6B, 0xC33D, 0x9B6C, 0xC33E, 0x9B6D, 0xC33F, 0x9B6E, 0xC340, 0x9B6F, 0xC341, 0x9B70, 0xC342, 0x9B71, 0xC343, 0x9B72, 0xC344, + 0x9B73, 0xC346, 0x9B74, 0xC347, 0x9B75, 0xC348, 0x9B76, 0xC349, 0x9B77, 0xC34A, 0x9B78, 0xC34B, 0x9B79, 0xC34C, 0x9B7A, 0xC34D, + 0x9B81, 0xC34E, 0x9B82, 0xC34F, 0x9B83, 0xC350, 0x9B84, 0xC351, 0x9B85, 0xC352, 0x9B86, 0xC353, 0x9B87, 0xC354, 0x9B88, 0xC355, + 0x9B89, 0xC356, 0x9B8A, 0xC357, 0x9B8B, 0xC358, 0x9B8C, 0xC359, 0x9B8D, 0xC35A, 0x9B8E, 0xC35B, 0x9B8F, 0xC35C, 0x9B90, 0xC35D, + 0x9B91, 0xC35E, 0x9B92, 0xC35F, 0x9B93, 0xC360, 0x9B94, 0xC361, 0x9B95, 0xC362, 0x9B96, 0xC363, 0x9B97, 0xC364, 0x9B98, 0xC365, + 0x9B99, 0xC366, 0x9B9A, 0xC367, 0x9B9B, 0xC36A, 0x9B9C, 0xC36B, 0x9B9D, 0xC36D, 0x9B9E, 0xC36E, 0x9B9F, 0xC36F, 0x9BA0, 0xC371, + 0x9BA1, 0xC373, 0x9BA2, 0xC374, 0x9BA3, 0xC375, 0x9BA4, 0xC376, 0x9BA5, 0xC377, 0x9BA6, 0xC37A, 0x9BA7, 0xC37B, 0x9BA8, 0xC37E, + 0x9BA9, 0xC37F, 0x9BAA, 0xC380, 0x9BAB, 0xC381, 0x9BAC, 0xC382, 0x9BAD, 0xC383, 0x9BAE, 0xC385, 0x9BAF, 0xC386, 0x9BB0, 0xC387, + 0x9BB1, 0xC389, 0x9BB2, 0xC38A, 0x9BB3, 0xC38B, 0x9BB4, 0xC38D, 0x9BB5, 0xC38E, 0x9BB6, 0xC38F, 0x9BB7, 0xC390, 0x9BB8, 0xC391, + 0x9BB9, 0xC392, 0x9BBA, 0xC393, 0x9BBB, 0xC394, 0x9BBC, 0xC395, 0x9BBD, 0xC396, 0x9BBE, 0xC397, 0x9BBF, 0xC398, 0x9BC0, 0xC399, + 0x9BC1, 0xC39A, 0x9BC2, 0xC39B, 0x9BC3, 0xC39C, 0x9BC4, 0xC39D, 0x9BC5, 0xC39E, 0x9BC6, 0xC39F, 0x9BC7, 0xC3A0, 0x9BC8, 0xC3A1, + 0x9BC9, 0xC3A2, 0x9BCA, 0xC3A3, 0x9BCB, 0xC3A4, 0x9BCC, 0xC3A5, 0x9BCD, 0xC3A6, 0x9BCE, 0xC3A7, 0x9BCF, 0xC3A8, 0x9BD0, 0xC3A9, + 0x9BD1, 0xC3AA, 0x9BD2, 0xC3AB, 0x9BD3, 0xC3AC, 0x9BD4, 0xC3AD, 0x9BD5, 0xC3AE, 0x9BD6, 0xC3AF, 0x9BD7, 0xC3B0, 0x9BD8, 0xC3B1, + 0x9BD9, 0xC3B2, 0x9BDA, 0xC3B3, 0x9BDB, 0xC3B4, 0x9BDC, 0xC3B5, 0x9BDD, 0xC3B6, 0x9BDE, 0xC3B7, 0x9BDF, 0xC3B8, 0x9BE0, 0xC3B9, + 0x9BE1, 0xC3BA, 0x9BE2, 0xC3BB, 0x9BE3, 0xC3BC, 0x9BE4, 0xC3BD, 0x9BE5, 0xC3BE, 0x9BE6, 0xC3BF, 0x9BE7, 0xC3C1, 0x9BE8, 0xC3C2, + 0x9BE9, 0xC3C3, 0x9BEA, 0xC3C4, 0x9BEB, 0xC3C5, 0x9BEC, 0xC3C6, 0x9BED, 0xC3C7, 0x9BEE, 0xC3C8, 0x9BEF, 0xC3C9, 0x9BF0, 0xC3CA, + 0x9BF1, 0xC3CB, 0x9BF2, 0xC3CC, 0x9BF3, 0xC3CD, 0x9BF4, 0xC3CE, 0x9BF5, 0xC3CF, 0x9BF6, 0xC3D0, 0x9BF7, 0xC3D1, 0x9BF8, 0xC3D2, + 0x9BF9, 0xC3D3, 0x9BFA, 0xC3D4, 0x9BFB, 0xC3D5, 0x9BFC, 0xC3D6, 0x9BFD, 0xC3D7, 0x9BFE, 0xC3DA, 0x9C41, 0xC3DB, 0x9C42, 0xC3DD, + 0x9C43, 0xC3DE, 0x9C44, 0xC3E1, 0x9C45, 0xC3E3, 0x9C46, 0xC3E4, 0x9C47, 0xC3E5, 0x9C48, 0xC3E6, 0x9C49, 0xC3E7, 0x9C4A, 0xC3EA, + 0x9C4B, 0xC3EB, 0x9C4C, 0xC3EC, 0x9C4D, 0xC3EE, 0x9C4E, 0xC3EF, 0x9C4F, 0xC3F0, 0x9C50, 0xC3F1, 0x9C51, 0xC3F2, 0x9C52, 0xC3F3, + 0x9C53, 0xC3F6, 0x9C54, 0xC3F7, 0x9C55, 0xC3F9, 0x9C56, 0xC3FA, 0x9C57, 0xC3FB, 0x9C58, 0xC3FC, 0x9C59, 0xC3FD, 0x9C5A, 0xC3FE, + 0x9C61, 0xC3FF, 0x9C62, 0xC400, 0x9C63, 0xC401, 0x9C64, 0xC402, 0x9C65, 0xC403, 0x9C66, 0xC404, 0x9C67, 0xC405, 0x9C68, 0xC406, + 0x9C69, 0xC407, 0x9C6A, 0xC409, 0x9C6B, 0xC40A, 0x9C6C, 0xC40B, 0x9C6D, 0xC40C, 0x9C6E, 0xC40D, 0x9C6F, 0xC40E, 0x9C70, 0xC40F, + 0x9C71, 0xC411, 0x9C72, 0xC412, 0x9C73, 0xC413, 0x9C74, 0xC414, 0x9C75, 0xC415, 0x9C76, 0xC416, 0x9C77, 0xC417, 0x9C78, 0xC418, + 0x9C79, 0xC419, 0x9C7A, 0xC41A, 0x9C81, 0xC41B, 0x9C82, 0xC41C, 0x9C83, 0xC41D, 0x9C84, 0xC41E, 0x9C85, 0xC41F, 0x9C86, 0xC420, + 0x9C87, 0xC421, 0x9C88, 0xC422, 0x9C89, 0xC423, 0x9C8A, 0xC425, 0x9C8B, 0xC426, 0x9C8C, 0xC427, 0x9C8D, 0xC428, 0x9C8E, 0xC429, + 0x9C8F, 0xC42A, 0x9C90, 0xC42B, 0x9C91, 0xC42D, 0x9C92, 0xC42E, 0x9C93, 0xC42F, 0x9C94, 0xC431, 0x9C95, 0xC432, 0x9C96, 0xC433, + 0x9C97, 0xC435, 0x9C98, 0xC436, 0x9C99, 0xC437, 0x9C9A, 0xC438, 0x9C9B, 0xC439, 0x9C9C, 0xC43A, 0x9C9D, 0xC43B, 0x9C9E, 0xC43E, + 0x9C9F, 0xC43F, 0x9CA0, 0xC440, 0x9CA1, 0xC441, 0x9CA2, 0xC442, 0x9CA3, 0xC443, 0x9CA4, 0xC444, 0x9CA5, 0xC445, 0x9CA6, 0xC446, + 0x9CA7, 0xC447, 0x9CA8, 0xC449, 0x9CA9, 0xC44A, 0x9CAA, 0xC44B, 0x9CAB, 0xC44C, 0x9CAC, 0xC44D, 0x9CAD, 0xC44E, 0x9CAE, 0xC44F, + 0x9CAF, 0xC450, 0x9CB0, 0xC451, 0x9CB1, 0xC452, 0x9CB2, 0xC453, 0x9CB3, 0xC454, 0x9CB4, 0xC455, 0x9CB5, 0xC456, 0x9CB6, 0xC457, + 0x9CB7, 0xC458, 0x9CB8, 0xC459, 0x9CB9, 0xC45A, 0x9CBA, 0xC45B, 0x9CBB, 0xC45C, 0x9CBC, 0xC45D, 0x9CBD, 0xC45E, 0x9CBE, 0xC45F, + 0x9CBF, 0xC460, 0x9CC0, 0xC461, 0x9CC1, 0xC462, 0x9CC2, 0xC463, 0x9CC3, 0xC466, 0x9CC4, 0xC467, 0x9CC5, 0xC469, 0x9CC6, 0xC46A, + 0x9CC7, 0xC46B, 0x9CC8, 0xC46D, 0x9CC9, 0xC46E, 0x9CCA, 0xC46F, 0x9CCB, 0xC470, 0x9CCC, 0xC471, 0x9CCD, 0xC472, 0x9CCE, 0xC473, + 0x9CCF, 0xC476, 0x9CD0, 0xC477, 0x9CD1, 0xC478, 0x9CD2, 0xC47A, 0x9CD3, 0xC47B, 0x9CD4, 0xC47C, 0x9CD5, 0xC47D, 0x9CD6, 0xC47E, + 0x9CD7, 0xC47F, 0x9CD8, 0xC481, 0x9CD9, 0xC482, 0x9CDA, 0xC483, 0x9CDB, 0xC484, 0x9CDC, 0xC485, 0x9CDD, 0xC486, 0x9CDE, 0xC487, + 0x9CDF, 0xC488, 0x9CE0, 0xC489, 0x9CE1, 0xC48A, 0x9CE2, 0xC48B, 0x9CE3, 0xC48C, 0x9CE4, 0xC48D, 0x9CE5, 0xC48E, 0x9CE6, 0xC48F, + 0x9CE7, 0xC490, 0x9CE8, 0xC491, 0x9CE9, 0xC492, 0x9CEA, 0xC493, 0x9CEB, 0xC495, 0x9CEC, 0xC496, 0x9CED, 0xC497, 0x9CEE, 0xC498, + 0x9CEF, 0xC499, 0x9CF0, 0xC49A, 0x9CF1, 0xC49B, 0x9CF2, 0xC49D, 0x9CF3, 0xC49E, 0x9CF4, 0xC49F, 0x9CF5, 0xC4A0, 0x9CF6, 0xC4A1, + 0x9CF7, 0xC4A2, 0x9CF8, 0xC4A3, 0x9CF9, 0xC4A4, 0x9CFA, 0xC4A5, 0x9CFB, 0xC4A6, 0x9CFC, 0xC4A7, 0x9CFD, 0xC4A8, 0x9CFE, 0xC4A9, + 0x9D41, 0xC4AA, 0x9D42, 0xC4AB, 0x9D43, 0xC4AC, 0x9D44, 0xC4AD, 0x9D45, 0xC4AE, 0x9D46, 0xC4AF, 0x9D47, 0xC4B0, 0x9D48, 0xC4B1, + 0x9D49, 0xC4B2, 0x9D4A, 0xC4B3, 0x9D4B, 0xC4B4, 0x9D4C, 0xC4B5, 0x9D4D, 0xC4B6, 0x9D4E, 0xC4B7, 0x9D4F, 0xC4B9, 0x9D50, 0xC4BA, + 0x9D51, 0xC4BB, 0x9D52, 0xC4BD, 0x9D53, 0xC4BE, 0x9D54, 0xC4BF, 0x9D55, 0xC4C0, 0x9D56, 0xC4C1, 0x9D57, 0xC4C2, 0x9D58, 0xC4C3, + 0x9D59, 0xC4C4, 0x9D5A, 0xC4C5, 0x9D61, 0xC4C6, 0x9D62, 0xC4C7, 0x9D63, 0xC4C8, 0x9D64, 0xC4C9, 0x9D65, 0xC4CA, 0x9D66, 0xC4CB, + 0x9D67, 0xC4CC, 0x9D68, 0xC4CD, 0x9D69, 0xC4CE, 0x9D6A, 0xC4CF, 0x9D6B, 0xC4D0, 0x9D6C, 0xC4D1, 0x9D6D, 0xC4D2, 0x9D6E, 0xC4D3, + 0x9D6F, 0xC4D4, 0x9D70, 0xC4D5, 0x9D71, 0xC4D6, 0x9D72, 0xC4D7, 0x9D73, 0xC4D8, 0x9D74, 0xC4D9, 0x9D75, 0xC4DA, 0x9D76, 0xC4DB, + 0x9D77, 0xC4DC, 0x9D78, 0xC4DD, 0x9D79, 0xC4DE, 0x9D7A, 0xC4DF, 0x9D81, 0xC4E0, 0x9D82, 0xC4E1, 0x9D83, 0xC4E2, 0x9D84, 0xC4E3, + 0x9D85, 0xC4E4, 0x9D86, 0xC4E5, 0x9D87, 0xC4E6, 0x9D88, 0xC4E7, 0x9D89, 0xC4E8, 0x9D8A, 0xC4EA, 0x9D8B, 0xC4EB, 0x9D8C, 0xC4EC, + 0x9D8D, 0xC4ED, 0x9D8E, 0xC4EE, 0x9D8F, 0xC4EF, 0x9D90, 0xC4F2, 0x9D91, 0xC4F3, 0x9D92, 0xC4F5, 0x9D93, 0xC4F6, 0x9D94, 0xC4F7, + 0x9D95, 0xC4F9, 0x9D96, 0xC4FB, 0x9D97, 0xC4FC, 0x9D98, 0xC4FD, 0x9D99, 0xC4FE, 0x9D9A, 0xC502, 0x9D9B, 0xC503, 0x9D9C, 0xC504, + 0x9D9D, 0xC505, 0x9D9E, 0xC506, 0x9D9F, 0xC507, 0x9DA0, 0xC508, 0x9DA1, 0xC509, 0x9DA2, 0xC50A, 0x9DA3, 0xC50B, 0x9DA4, 0xC50D, + 0x9DA5, 0xC50E, 0x9DA6, 0xC50F, 0x9DA7, 0xC511, 0x9DA8, 0xC512, 0x9DA9, 0xC513, 0x9DAA, 0xC515, 0x9DAB, 0xC516, 0x9DAC, 0xC517, + 0x9DAD, 0xC518, 0x9DAE, 0xC519, 0x9DAF, 0xC51A, 0x9DB0, 0xC51B, 0x9DB1, 0xC51D, 0x9DB2, 0xC51E, 0x9DB3, 0xC51F, 0x9DB4, 0xC520, + 0x9DB5, 0xC521, 0x9DB6, 0xC522, 0x9DB7, 0xC523, 0x9DB8, 0xC524, 0x9DB9, 0xC525, 0x9DBA, 0xC526, 0x9DBB, 0xC527, 0x9DBC, 0xC52A, + 0x9DBD, 0xC52B, 0x9DBE, 0xC52D, 0x9DBF, 0xC52E, 0x9DC0, 0xC52F, 0x9DC1, 0xC531, 0x9DC2, 0xC532, 0x9DC3, 0xC533, 0x9DC4, 0xC534, + 0x9DC5, 0xC535, 0x9DC6, 0xC536, 0x9DC7, 0xC537, 0x9DC8, 0xC53A, 0x9DC9, 0xC53C, 0x9DCA, 0xC53E, 0x9DCB, 0xC53F, 0x9DCC, 0xC540, + 0x9DCD, 0xC541, 0x9DCE, 0xC542, 0x9DCF, 0xC543, 0x9DD0, 0xC546, 0x9DD1, 0xC547, 0x9DD2, 0xC54B, 0x9DD3, 0xC54F, 0x9DD4, 0xC550, + 0x9DD5, 0xC551, 0x9DD6, 0xC552, 0x9DD7, 0xC556, 0x9DD8, 0xC55A, 0x9DD9, 0xC55B, 0x9DDA, 0xC55C, 0x9DDB, 0xC55F, 0x9DDC, 0xC562, + 0x9DDD, 0xC563, 0x9DDE, 0xC565, 0x9DDF, 0xC566, 0x9DE0, 0xC567, 0x9DE1, 0xC569, 0x9DE2, 0xC56A, 0x9DE3, 0xC56B, 0x9DE4, 0xC56C, + 0x9DE5, 0xC56D, 0x9DE6, 0xC56E, 0x9DE7, 0xC56F, 0x9DE8, 0xC572, 0x9DE9, 0xC576, 0x9DEA, 0xC577, 0x9DEB, 0xC578, 0x9DEC, 0xC579, + 0x9DED, 0xC57A, 0x9DEE, 0xC57B, 0x9DEF, 0xC57E, 0x9DF0, 0xC57F, 0x9DF1, 0xC581, 0x9DF2, 0xC582, 0x9DF3, 0xC583, 0x9DF4, 0xC585, + 0x9DF5, 0xC586, 0x9DF6, 0xC588, 0x9DF7, 0xC589, 0x9DF8, 0xC58A, 0x9DF9, 0xC58B, 0x9DFA, 0xC58E, 0x9DFB, 0xC590, 0x9DFC, 0xC592, + 0x9DFD, 0xC593, 0x9DFE, 0xC594, 0x9E41, 0xC596, 0x9E42, 0xC599, 0x9E43, 0xC59A, 0x9E44, 0xC59B, 0x9E45, 0xC59D, 0x9E46, 0xC59E, + 0x9E47, 0xC59F, 0x9E48, 0xC5A1, 0x9E49, 0xC5A2, 0x9E4A, 0xC5A3, 0x9E4B, 0xC5A4, 0x9E4C, 0xC5A5, 0x9E4D, 0xC5A6, 0x9E4E, 0xC5A7, + 0x9E4F, 0xC5A8, 0x9E50, 0xC5AA, 0x9E51, 0xC5AB, 0x9E52, 0xC5AC, 0x9E53, 0xC5AD, 0x9E54, 0xC5AE, 0x9E55, 0xC5AF, 0x9E56, 0xC5B0, + 0x9E57, 0xC5B1, 0x9E58, 0xC5B2, 0x9E59, 0xC5B3, 0x9E5A, 0xC5B6, 0x9E61, 0xC5B7, 0x9E62, 0xC5BA, 0x9E63, 0xC5BF, 0x9E64, 0xC5C0, + 0x9E65, 0xC5C1, 0x9E66, 0xC5C2, 0x9E67, 0xC5C3, 0x9E68, 0xC5CB, 0x9E69, 0xC5CD, 0x9E6A, 0xC5CF, 0x9E6B, 0xC5D2, 0x9E6C, 0xC5D3, + 0x9E6D, 0xC5D5, 0x9E6E, 0xC5D6, 0x9E6F, 0xC5D7, 0x9E70, 0xC5D9, 0x9E71, 0xC5DA, 0x9E72, 0xC5DB, 0x9E73, 0xC5DC, 0x9E74, 0xC5DD, + 0x9E75, 0xC5DE, 0x9E76, 0xC5DF, 0x9E77, 0xC5E2, 0x9E78, 0xC5E4, 0x9E79, 0xC5E6, 0x9E7A, 0xC5E7, 0x9E81, 0xC5E8, 0x9E82, 0xC5E9, + 0x9E83, 0xC5EA, 0x9E84, 0xC5EB, 0x9E85, 0xC5EF, 0x9E86, 0xC5F1, 0x9E87, 0xC5F2, 0x9E88, 0xC5F3, 0x9E89, 0xC5F5, 0x9E8A, 0xC5F8, + 0x9E8B, 0xC5F9, 0x9E8C, 0xC5FA, 0x9E8D, 0xC5FB, 0x9E8E, 0xC602, 0x9E8F, 0xC603, 0x9E90, 0xC604, 0x9E91, 0xC609, 0x9E92, 0xC60A, + 0x9E93, 0xC60B, 0x9E94, 0xC60D, 0x9E95, 0xC60E, 0x9E96, 0xC60F, 0x9E97, 0xC611, 0x9E98, 0xC612, 0x9E99, 0xC613, 0x9E9A, 0xC614, + 0x9E9B, 0xC615, 0x9E9C, 0xC616, 0x9E9D, 0xC617, 0x9E9E, 0xC61A, 0x9E9F, 0xC61D, 0x9EA0, 0xC61E, 0x9EA1, 0xC61F, 0x9EA2, 0xC620, + 0x9EA3, 0xC621, 0x9EA4, 0xC622, 0x9EA5, 0xC623, 0x9EA6, 0xC626, 0x9EA7, 0xC627, 0x9EA8, 0xC629, 0x9EA9, 0xC62A, 0x9EAA, 0xC62B, + 0x9EAB, 0xC62F, 0x9EAC, 0xC631, 0x9EAD, 0xC632, 0x9EAE, 0xC636, 0x9EAF, 0xC638, 0x9EB0, 0xC63A, 0x9EB1, 0xC63C, 0x9EB2, 0xC63D, + 0x9EB3, 0xC63E, 0x9EB4, 0xC63F, 0x9EB5, 0xC642, 0x9EB6, 0xC643, 0x9EB7, 0xC645, 0x9EB8, 0xC646, 0x9EB9, 0xC647, 0x9EBA, 0xC649, + 0x9EBB, 0xC64A, 0x9EBC, 0xC64B, 0x9EBD, 0xC64C, 0x9EBE, 0xC64D, 0x9EBF, 0xC64E, 0x9EC0, 0xC64F, 0x9EC1, 0xC652, 0x9EC2, 0xC656, + 0x9EC3, 0xC657, 0x9EC4, 0xC658, 0x9EC5, 0xC659, 0x9EC6, 0xC65A, 0x9EC7, 0xC65B, 0x9EC8, 0xC65E, 0x9EC9, 0xC65F, 0x9ECA, 0xC661, + 0x9ECB, 0xC662, 0x9ECC, 0xC663, 0x9ECD, 0xC664, 0x9ECE, 0xC665, 0x9ECF, 0xC666, 0x9ED0, 0xC667, 0x9ED1, 0xC668, 0x9ED2, 0xC669, + 0x9ED3, 0xC66A, 0x9ED4, 0xC66B, 0x9ED5, 0xC66D, 0x9ED6, 0xC66E, 0x9ED7, 0xC670, 0x9ED8, 0xC672, 0x9ED9, 0xC673, 0x9EDA, 0xC674, + 0x9EDB, 0xC675, 0x9EDC, 0xC676, 0x9EDD, 0xC677, 0x9EDE, 0xC67A, 0x9EDF, 0xC67B, 0x9EE0, 0xC67D, 0x9EE1, 0xC67E, 0x9EE2, 0xC67F, + 0x9EE3, 0xC681, 0x9EE4, 0xC682, 0x9EE5, 0xC683, 0x9EE6, 0xC684, 0x9EE7, 0xC685, 0x9EE8, 0xC686, 0x9EE9, 0xC687, 0x9EEA, 0xC68A, + 0x9EEB, 0xC68C, 0x9EEC, 0xC68E, 0x9EED, 0xC68F, 0x9EEE, 0xC690, 0x9EEF, 0xC691, 0x9EF0, 0xC692, 0x9EF1, 0xC693, 0x9EF2, 0xC696, + 0x9EF3, 0xC697, 0x9EF4, 0xC699, 0x9EF5, 0xC69A, 0x9EF6, 0xC69B, 0x9EF7, 0xC69D, 0x9EF8, 0xC69E, 0x9EF9, 0xC69F, 0x9EFA, 0xC6A0, + 0x9EFB, 0xC6A1, 0x9EFC, 0xC6A2, 0x9EFD, 0xC6A3, 0x9EFE, 0xC6A6, 0x9F41, 0xC6A8, 0x9F42, 0xC6AA, 0x9F43, 0xC6AB, 0x9F44, 0xC6AC, + 0x9F45, 0xC6AD, 0x9F46, 0xC6AE, 0x9F47, 0xC6AF, 0x9F48, 0xC6B2, 0x9F49, 0xC6B3, 0x9F4A, 0xC6B5, 0x9F4B, 0xC6B6, 0x9F4C, 0xC6B7, + 0x9F4D, 0xC6BB, 0x9F4E, 0xC6BC, 0x9F4F, 0xC6BD, 0x9F50, 0xC6BE, 0x9F51, 0xC6BF, 0x9F52, 0xC6C2, 0x9F53, 0xC6C4, 0x9F54, 0xC6C6, + 0x9F55, 0xC6C7, 0x9F56, 0xC6C8, 0x9F57, 0xC6C9, 0x9F58, 0xC6CA, 0x9F59, 0xC6CB, 0x9F5A, 0xC6CE, 0x9F61, 0xC6CF, 0x9F62, 0xC6D1, + 0x9F63, 0xC6D2, 0x9F64, 0xC6D3, 0x9F65, 0xC6D5, 0x9F66, 0xC6D6, 0x9F67, 0xC6D7, 0x9F68, 0xC6D8, 0x9F69, 0xC6D9, 0x9F6A, 0xC6DA, + 0x9F6B, 0xC6DB, 0x9F6C, 0xC6DE, 0x9F6D, 0xC6DF, 0x9F6E, 0xC6E2, 0x9F6F, 0xC6E3, 0x9F70, 0xC6E4, 0x9F71, 0xC6E5, 0x9F72, 0xC6E6, + 0x9F73, 0xC6E7, 0x9F74, 0xC6EA, 0x9F75, 0xC6EB, 0x9F76, 0xC6ED, 0x9F77, 0xC6EE, 0x9F78, 0xC6EF, 0x9F79, 0xC6F1, 0x9F7A, 0xC6F2, + 0x9F81, 0xC6F3, 0x9F82, 0xC6F4, 0x9F83, 0xC6F5, 0x9F84, 0xC6F6, 0x9F85, 0xC6F7, 0x9F86, 0xC6FA, 0x9F87, 0xC6FB, 0x9F88, 0xC6FC, + 0x9F89, 0xC6FE, 0x9F8A, 0xC6FF, 0x9F8B, 0xC700, 0x9F8C, 0xC701, 0x9F8D, 0xC702, 0x9F8E, 0xC703, 0x9F8F, 0xC706, 0x9F90, 0xC707, + 0x9F91, 0xC709, 0x9F92, 0xC70A, 0x9F93, 0xC70B, 0x9F94, 0xC70D, 0x9F95, 0xC70E, 0x9F96, 0xC70F, 0x9F97, 0xC710, 0x9F98, 0xC711, + 0x9F99, 0xC712, 0x9F9A, 0xC713, 0x9F9B, 0xC716, 0x9F9C, 0xC718, 0x9F9D, 0xC71A, 0x9F9E, 0xC71B, 0x9F9F, 0xC71C, 0x9FA0, 0xC71D, + 0x9FA1, 0xC71E, 0x9FA2, 0xC71F, 0x9FA3, 0xC722, 0x9FA4, 0xC723, 0x9FA5, 0xC725, 0x9FA6, 0xC726, 0x9FA7, 0xC727, 0x9FA8, 0xC729, + 0x9FA9, 0xC72A, 0x9FAA, 0xC72B, 0x9FAB, 0xC72C, 0x9FAC, 0xC72D, 0x9FAD, 0xC72E, 0x9FAE, 0xC72F, 0x9FAF, 0xC732, 0x9FB0, 0xC734, + 0x9FB1, 0xC736, 0x9FB2, 0xC738, 0x9FB3, 0xC739, 0x9FB4, 0xC73A, 0x9FB5, 0xC73B, 0x9FB6, 0xC73E, 0x9FB7, 0xC73F, 0x9FB8, 0xC741, + 0x9FB9, 0xC742, 0x9FBA, 0xC743, 0x9FBB, 0xC745, 0x9FBC, 0xC746, 0x9FBD, 0xC747, 0x9FBE, 0xC748, 0x9FBF, 0xC749, 0x9FC0, 0xC74B, + 0x9FC1, 0xC74E, 0x9FC2, 0xC750, 0x9FC3, 0xC759, 0x9FC4, 0xC75A, 0x9FC5, 0xC75B, 0x9FC6, 0xC75D, 0x9FC7, 0xC75E, 0x9FC8, 0xC75F, + 0x9FC9, 0xC761, 0x9FCA, 0xC762, 0x9FCB, 0xC763, 0x9FCC, 0xC764, 0x9FCD, 0xC765, 0x9FCE, 0xC766, 0x9FCF, 0xC767, 0x9FD0, 0xC769, + 0x9FD1, 0xC76A, 0x9FD2, 0xC76C, 0x9FD3, 0xC76D, 0x9FD4, 0xC76E, 0x9FD5, 0xC76F, 0x9FD6, 0xC770, 0x9FD7, 0xC771, 0x9FD8, 0xC772, + 0x9FD9, 0xC773, 0x9FDA, 0xC776, 0x9FDB, 0xC777, 0x9FDC, 0xC779, 0x9FDD, 0xC77A, 0x9FDE, 0xC77B, 0x9FDF, 0xC77F, 0x9FE0, 0xC780, + 0x9FE1, 0xC781, 0x9FE2, 0xC782, 0x9FE3, 0xC786, 0x9FE4, 0xC78B, 0x9FE5, 0xC78C, 0x9FE6, 0xC78D, 0x9FE7, 0xC78F, 0x9FE8, 0xC792, + 0x9FE9, 0xC793, 0x9FEA, 0xC795, 0x9FEB, 0xC799, 0x9FEC, 0xC79B, 0x9FED, 0xC79C, 0x9FEE, 0xC79D, 0x9FEF, 0xC79E, 0x9FF0, 0xC79F, + 0x9FF1, 0xC7A2, 0x9FF2, 0xC7A7, 0x9FF3, 0xC7A8, 0x9FF4, 0xC7A9, 0x9FF5, 0xC7AA, 0x9FF6, 0xC7AB, 0x9FF7, 0xC7AE, 0x9FF8, 0xC7AF, + 0x9FF9, 0xC7B1, 0x9FFA, 0xC7B2, 0x9FFB, 0xC7B3, 0x9FFC, 0xC7B5, 0x9FFD, 0xC7B6, 0x9FFE, 0xC7B7, 0xA041, 0xC7B8, 0xA042, 0xC7B9, + 0xA043, 0xC7BA, 0xA044, 0xC7BB, 0xA045, 0xC7BE, 0xA046, 0xC7C2, 0xA047, 0xC7C3, 0xA048, 0xC7C4, 0xA049, 0xC7C5, 0xA04A, 0xC7C6, + 0xA04B, 0xC7C7, 0xA04C, 0xC7CA, 0xA04D, 0xC7CB, 0xA04E, 0xC7CD, 0xA04F, 0xC7CF, 0xA050, 0xC7D1, 0xA051, 0xC7D2, 0xA052, 0xC7D3, + 0xA053, 0xC7D4, 0xA054, 0xC7D5, 0xA055, 0xC7D6, 0xA056, 0xC7D7, 0xA057, 0xC7D9, 0xA058, 0xC7DA, 0xA059, 0xC7DB, 0xA05A, 0xC7DC, + 0xA061, 0xC7DE, 0xA062, 0xC7DF, 0xA063, 0xC7E0, 0xA064, 0xC7E1, 0xA065, 0xC7E2, 0xA066, 0xC7E3, 0xA067, 0xC7E5, 0xA068, 0xC7E6, + 0xA069, 0xC7E7, 0xA06A, 0xC7E9, 0xA06B, 0xC7EA, 0xA06C, 0xC7EB, 0xA06D, 0xC7ED, 0xA06E, 0xC7EE, 0xA06F, 0xC7EF, 0xA070, 0xC7F0, + 0xA071, 0xC7F1, 0xA072, 0xC7F2, 0xA073, 0xC7F3, 0xA074, 0xC7F4, 0xA075, 0xC7F5, 0xA076, 0xC7F6, 0xA077, 0xC7F7, 0xA078, 0xC7F8, + 0xA079, 0xC7F9, 0xA07A, 0xC7FA, 0xA081, 0xC7FB, 0xA082, 0xC7FC, 0xA083, 0xC7FD, 0xA084, 0xC7FE, 0xA085, 0xC7FF, 0xA086, 0xC802, + 0xA087, 0xC803, 0xA088, 0xC805, 0xA089, 0xC806, 0xA08A, 0xC807, 0xA08B, 0xC809, 0xA08C, 0xC80B, 0xA08D, 0xC80C, 0xA08E, 0xC80D, + 0xA08F, 0xC80E, 0xA090, 0xC80F, 0xA091, 0xC812, 0xA092, 0xC814, 0xA093, 0xC817, 0xA094, 0xC818, 0xA095, 0xC819, 0xA096, 0xC81A, + 0xA097, 0xC81B, 0xA098, 0xC81E, 0xA099, 0xC81F, 0xA09A, 0xC821, 0xA09B, 0xC822, 0xA09C, 0xC823, 0xA09D, 0xC825, 0xA09E, 0xC826, + 0xA09F, 0xC827, 0xA0A0, 0xC828, 0xA0A1, 0xC829, 0xA0A2, 0xC82A, 0xA0A3, 0xC82B, 0xA0A4, 0xC82E, 0xA0A5, 0xC830, 0xA0A6, 0xC832, + 0xA0A7, 0xC833, 0xA0A8, 0xC834, 0xA0A9, 0xC835, 0xA0AA, 0xC836, 0xA0AB, 0xC837, 0xA0AC, 0xC839, 0xA0AD, 0xC83A, 0xA0AE, 0xC83B, + 0xA0AF, 0xC83D, 0xA0B0, 0xC83E, 0xA0B1, 0xC83F, 0xA0B2, 0xC841, 0xA0B3, 0xC842, 0xA0B4, 0xC843, 0xA0B5, 0xC844, 0xA0B6, 0xC845, + 0xA0B7, 0xC846, 0xA0B8, 0xC847, 0xA0B9, 0xC84A, 0xA0BA, 0xC84B, 0xA0BB, 0xC84E, 0xA0BC, 0xC84F, 0xA0BD, 0xC850, 0xA0BE, 0xC851, + 0xA0BF, 0xC852, 0xA0C0, 0xC853, 0xA0C1, 0xC855, 0xA0C2, 0xC856, 0xA0C3, 0xC857, 0xA0C4, 0xC858, 0xA0C5, 0xC859, 0xA0C6, 0xC85A, + 0xA0C7, 0xC85B, 0xA0C8, 0xC85C, 0xA0C9, 0xC85D, 0xA0CA, 0xC85E, 0xA0CB, 0xC85F, 0xA0CC, 0xC860, 0xA0CD, 0xC861, 0xA0CE, 0xC862, + 0xA0CF, 0xC863, 0xA0D0, 0xC864, 0xA0D1, 0xC865, 0xA0D2, 0xC866, 0xA0D3, 0xC867, 0xA0D4, 0xC868, 0xA0D5, 0xC869, 0xA0D6, 0xC86A, + 0xA0D7, 0xC86B, 0xA0D8, 0xC86C, 0xA0D9, 0xC86D, 0xA0DA, 0xC86E, 0xA0DB, 0xC86F, 0xA0DC, 0xC872, 0xA0DD, 0xC873, 0xA0DE, 0xC875, + 0xA0DF, 0xC876, 0xA0E0, 0xC877, 0xA0E1, 0xC879, 0xA0E2, 0xC87B, 0xA0E3, 0xC87C, 0xA0E4, 0xC87D, 0xA0E5, 0xC87E, 0xA0E6, 0xC87F, + 0xA0E7, 0xC882, 0xA0E8, 0xC884, 0xA0E9, 0xC888, 0xA0EA, 0xC889, 0xA0EB, 0xC88A, 0xA0EC, 0xC88E, 0xA0ED, 0xC88F, 0xA0EE, 0xC890, + 0xA0EF, 0xC891, 0xA0F0, 0xC892, 0xA0F1, 0xC893, 0xA0F2, 0xC895, 0xA0F3, 0xC896, 0xA0F4, 0xC897, 0xA0F5, 0xC898, 0xA0F6, 0xC899, + 0xA0F7, 0xC89A, 0xA0F8, 0xC89B, 0xA0F9, 0xC89C, 0xA0FA, 0xC89E, 0xA0FB, 0xC8A0, 0xA0FC, 0xC8A2, 0xA0FD, 0xC8A3, 0xA0FE, 0xC8A4, + 0xA141, 0xC8A5, 0xA142, 0xC8A6, 0xA143, 0xC8A7, 0xA144, 0xC8A9, 0xA145, 0xC8AA, 0xA146, 0xC8AB, 0xA147, 0xC8AC, 0xA148, 0xC8AD, + 0xA149, 0xC8AE, 0xA14A, 0xC8AF, 0xA14B, 0xC8B0, 0xA14C, 0xC8B1, 0xA14D, 0xC8B2, 0xA14E, 0xC8B3, 0xA14F, 0xC8B4, 0xA150, 0xC8B5, + 0xA151, 0xC8B6, 0xA152, 0xC8B7, 0xA153, 0xC8B8, 0xA154, 0xC8B9, 0xA155, 0xC8BA, 0xA156, 0xC8BB, 0xA157, 0xC8BE, 0xA158, 0xC8BF, + 0xA159, 0xC8C0, 0xA15A, 0xC8C1, 0xA161, 0xC8C2, 0xA162, 0xC8C3, 0xA163, 0xC8C5, 0xA164, 0xC8C6, 0xA165, 0xC8C7, 0xA166, 0xC8C9, + 0xA167, 0xC8CA, 0xA168, 0xC8CB, 0xA169, 0xC8CD, 0xA16A, 0xC8CE, 0xA16B, 0xC8CF, 0xA16C, 0xC8D0, 0xA16D, 0xC8D1, 0xA16E, 0xC8D2, + 0xA16F, 0xC8D3, 0xA170, 0xC8D6, 0xA171, 0xC8D8, 0xA172, 0xC8DA, 0xA173, 0xC8DB, 0xA174, 0xC8DC, 0xA175, 0xC8DD, 0xA176, 0xC8DE, + 0xA177, 0xC8DF, 0xA178, 0xC8E2, 0xA179, 0xC8E3, 0xA17A, 0xC8E5, 0xA181, 0xC8E6, 0xA182, 0xC8E7, 0xA183, 0xC8E8, 0xA184, 0xC8E9, + 0xA185, 0xC8EA, 0xA186, 0xC8EB, 0xA187, 0xC8EC, 0xA188, 0xC8ED, 0xA189, 0xC8EE, 0xA18A, 0xC8EF, 0xA18B, 0xC8F0, 0xA18C, 0xC8F1, + 0xA18D, 0xC8F2, 0xA18E, 0xC8F3, 0xA18F, 0xC8F4, 0xA190, 0xC8F6, 0xA191, 0xC8F7, 0xA192, 0xC8F8, 0xA193, 0xC8F9, 0xA194, 0xC8FA, + 0xA195, 0xC8FB, 0xA196, 0xC8FE, 0xA197, 0xC8FF, 0xA198, 0xC901, 0xA199, 0xC902, 0xA19A, 0xC903, 0xA19B, 0xC907, 0xA19C, 0xC908, + 0xA19D, 0xC909, 0xA19E, 0xC90A, 0xA19F, 0xC90B, 0xA1A0, 0xC90E, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7, + 0xA1A5, 0x2025, 0xA1A6, 0x2026, 0xA1A7, 0x00A8, 0xA1A8, 0x3003, 0xA1A9, 0x00AD, 0xA1AA, 0x2015, 0xA1AB, 0x2225, 0xA1AC, 0xFF3C, + 0xA1AD, 0x223C, 0xA1AE, 0x2018, 0xA1AF, 0x2019, 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008, + 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3010, + 0xA1BD, 0x3011, 0xA1BE, 0x00B1, 0xA1BF, 0x00D7, 0xA1C0, 0x00F7, 0xA1C1, 0x2260, 0xA1C2, 0x2264, 0xA1C3, 0x2265, 0xA1C4, 0x221E, + 0xA1C5, 0x2234, 0xA1C6, 0x00B0, 0xA1C7, 0x2032, 0xA1C8, 0x2033, 0xA1C9, 0x2103, 0xA1CA, 0x212B, 0xA1CB, 0xFFE0, 0xA1CC, 0xFFE1, + 0xA1CD, 0xFFE5, 0xA1CE, 0x2642, 0xA1CF, 0x2640, 0xA1D0, 0x2220, 0xA1D1, 0x22A5, 0xA1D2, 0x2312, 0xA1D3, 0x2202, 0xA1D4, 0x2207, + 0xA1D5, 0x2261, 0xA1D6, 0x2252, 0xA1D7, 0x00A7, 0xA1D8, 0x203B, 0xA1D9, 0x2606, 0xA1DA, 0x2605, 0xA1DB, 0x25CB, 0xA1DC, 0x25CF, + 0xA1DD, 0x25CE, 0xA1DE, 0x25C7, 0xA1DF, 0x25C6, 0xA1E0, 0x25A1, 0xA1E1, 0x25A0, 0xA1E2, 0x25B3, 0xA1E3, 0x25B2, 0xA1E4, 0x25BD, + 0xA1E5, 0x25BC, 0xA1E6, 0x2192, 0xA1E7, 0x2190, 0xA1E8, 0x2191, 0xA1E9, 0x2193, 0xA1EA, 0x2194, 0xA1EB, 0x3013, 0xA1EC, 0x226A, + 0xA1ED, 0x226B, 0xA1EE, 0x221A, 0xA1EF, 0x223D, 0xA1F0, 0x221D, 0xA1F1, 0x2235, 0xA1F2, 0x222B, 0xA1F3, 0x222C, 0xA1F4, 0x2208, + 0xA1F5, 0x220B, 0xA1F6, 0x2286, 0xA1F7, 0x2287, 0xA1F8, 0x2282, 0xA1F9, 0x2283, 0xA1FA, 0x222A, 0xA1FB, 0x2229, 0xA1FC, 0x2227, + 0xA1FD, 0x2228, 0xA1FE, 0xFFE2, 0xA241, 0xC910, 0xA242, 0xC912, 0xA243, 0xC913, 0xA244, 0xC914, 0xA245, 0xC915, 0xA246, 0xC916, + 0xA247, 0xC917, 0xA248, 0xC919, 0xA249, 0xC91A, 0xA24A, 0xC91B, 0xA24B, 0xC91C, 0xA24C, 0xC91D, 0xA24D, 0xC91E, 0xA24E, 0xC91F, + 0xA24F, 0xC920, 0xA250, 0xC921, 0xA251, 0xC922, 0xA252, 0xC923, 0xA253, 0xC924, 0xA254, 0xC925, 0xA255, 0xC926, 0xA256, 0xC927, + 0xA257, 0xC928, 0xA258, 0xC929, 0xA259, 0xC92A, 0xA25A, 0xC92B, 0xA261, 0xC92D, 0xA262, 0xC92E, 0xA263, 0xC92F, 0xA264, 0xC930, + 0xA265, 0xC931, 0xA266, 0xC932, 0xA267, 0xC933, 0xA268, 0xC935, 0xA269, 0xC936, 0xA26A, 0xC937, 0xA26B, 0xC938, 0xA26C, 0xC939, + 0xA26D, 0xC93A, 0xA26E, 0xC93B, 0xA26F, 0xC93C, 0xA270, 0xC93D, 0xA271, 0xC93E, 0xA272, 0xC93F, 0xA273, 0xC940, 0xA274, 0xC941, + 0xA275, 0xC942, 0xA276, 0xC943, 0xA277, 0xC944, 0xA278, 0xC945, 0xA279, 0xC946, 0xA27A, 0xC947, 0xA281, 0xC948, 0xA282, 0xC949, + 0xA283, 0xC94A, 0xA284, 0xC94B, 0xA285, 0xC94C, 0xA286, 0xC94D, 0xA287, 0xC94E, 0xA288, 0xC94F, 0xA289, 0xC952, 0xA28A, 0xC953, + 0xA28B, 0xC955, 0xA28C, 0xC956, 0xA28D, 0xC957, 0xA28E, 0xC959, 0xA28F, 0xC95A, 0xA290, 0xC95B, 0xA291, 0xC95C, 0xA292, 0xC95D, + 0xA293, 0xC95E, 0xA294, 0xC95F, 0xA295, 0xC962, 0xA296, 0xC964, 0xA297, 0xC965, 0xA298, 0xC966, 0xA299, 0xC967, 0xA29A, 0xC968, + 0xA29B, 0xC969, 0xA29C, 0xC96A, 0xA29D, 0xC96B, 0xA29E, 0xC96D, 0xA29F, 0xC96E, 0xA2A0, 0xC96F, 0xA2A1, 0x21D2, 0xA2A2, 0x21D4, + 0xA2A3, 0x2200, 0xA2A4, 0x2203, 0xA2A5, 0x00B4, 0xA2A6, 0xFF5E, 0xA2A7, 0x02C7, 0xA2A8, 0x02D8, 0xA2A9, 0x02DD, 0xA2AA, 0x02DA, + 0xA2AB, 0x02D9, 0xA2AC, 0x00B8, 0xA2AD, 0x02DB, 0xA2AE, 0x00A1, 0xA2AF, 0x00BF, 0xA2B0, 0x02D0, 0xA2B1, 0x222E, 0xA2B2, 0x2211, + 0xA2B3, 0x220F, 0xA2B4, 0x00A4, 0xA2B5, 0x2109, 0xA2B6, 0x2030, 0xA2B7, 0x25C1, 0xA2B8, 0x25C0, 0xA2B9, 0x25B7, 0xA2BA, 0x25B6, + 0xA2BB, 0x2664, 0xA2BC, 0x2660, 0xA2BD, 0x2661, 0xA2BE, 0x2665, 0xA2BF, 0x2667, 0xA2C0, 0x2663, 0xA2C1, 0x2299, 0xA2C2, 0x25C8, + 0xA2C3, 0x25A3, 0xA2C4, 0x25D0, 0xA2C5, 0x25D1, 0xA2C6, 0x2592, 0xA2C7, 0x25A4, 0xA2C8, 0x25A5, 0xA2C9, 0x25A8, 0xA2CA, 0x25A7, + 0xA2CB, 0x25A6, 0xA2CC, 0x25A9, 0xA2CD, 0x2668, 0xA2CE, 0x260F, 0xA2CF, 0x260E, 0xA2D0, 0x261C, 0xA2D1, 0x261E, 0xA2D2, 0x00B6, + 0xA2D3, 0x2020, 0xA2D4, 0x2021, 0xA2D5, 0x2195, 0xA2D6, 0x2197, 0xA2D7, 0x2199, 0xA2D8, 0x2196, 0xA2D9, 0x2198, 0xA2DA, 0x266D, + 0xA2DB, 0x2669, 0xA2DC, 0x266A, 0xA2DD, 0x266C, 0xA2DE, 0x327F, 0xA2DF, 0x321C, 0xA2E0, 0x2116, 0xA2E1, 0x33C7, 0xA2E2, 0x2122, + 0xA2E3, 0x33C2, 0xA2E4, 0x33D8, 0xA2E5, 0x2121, 0xA2E6, 0x20AC, 0xA2E7, 0x00AE, 0xA341, 0xC971, 0xA342, 0xC972, 0xA343, 0xC973, + 0xA344, 0xC975, 0xA345, 0xC976, 0xA346, 0xC977, 0xA347, 0xC978, 0xA348, 0xC979, 0xA349, 0xC97A, 0xA34A, 0xC97B, 0xA34B, 0xC97D, + 0xA34C, 0xC97E, 0xA34D, 0xC97F, 0xA34E, 0xC980, 0xA34F, 0xC981, 0xA350, 0xC982, 0xA351, 0xC983, 0xA352, 0xC984, 0xA353, 0xC985, + 0xA354, 0xC986, 0xA355, 0xC987, 0xA356, 0xC98A, 0xA357, 0xC98B, 0xA358, 0xC98D, 0xA359, 0xC98E, 0xA35A, 0xC98F, 0xA361, 0xC991, + 0xA362, 0xC992, 0xA363, 0xC993, 0xA364, 0xC994, 0xA365, 0xC995, 0xA366, 0xC996, 0xA367, 0xC997, 0xA368, 0xC99A, 0xA369, 0xC99C, + 0xA36A, 0xC99E, 0xA36B, 0xC99F, 0xA36C, 0xC9A0, 0xA36D, 0xC9A1, 0xA36E, 0xC9A2, 0xA36F, 0xC9A3, 0xA370, 0xC9A4, 0xA371, 0xC9A5, + 0xA372, 0xC9A6, 0xA373, 0xC9A7, 0xA374, 0xC9A8, 0xA375, 0xC9A9, 0xA376, 0xC9AA, 0xA377, 0xC9AB, 0xA378, 0xC9AC, 0xA379, 0xC9AD, + 0xA37A, 0xC9AE, 0xA381, 0xC9AF, 0xA382, 0xC9B0, 0xA383, 0xC9B1, 0xA384, 0xC9B2, 0xA385, 0xC9B3, 0xA386, 0xC9B4, 0xA387, 0xC9B5, + 0xA388, 0xC9B6, 0xA389, 0xC9B7, 0xA38A, 0xC9B8, 0xA38B, 0xC9B9, 0xA38C, 0xC9BA, 0xA38D, 0xC9BB, 0xA38E, 0xC9BC, 0xA38F, 0xC9BD, + 0xA390, 0xC9BE, 0xA391, 0xC9BF, 0xA392, 0xC9C2, 0xA393, 0xC9C3, 0xA394, 0xC9C5, 0xA395, 0xC9C6, 0xA396, 0xC9C9, 0xA397, 0xC9CB, + 0xA398, 0xC9CC, 0xA399, 0xC9CD, 0xA39A, 0xC9CE, 0xA39B, 0xC9CF, 0xA39C, 0xC9D2, 0xA39D, 0xC9D4, 0xA39E, 0xC9D7, 0xA39F, 0xC9D8, + 0xA3A0, 0xC9DB, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, 0xA3A4, 0xFF04, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, 0xA3DC, 0xFFE6, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA441, 0xC9DE, + 0xA442, 0xC9DF, 0xA443, 0xC9E1, 0xA444, 0xC9E3, 0xA445, 0xC9E5, 0xA446, 0xC9E6, 0xA447, 0xC9E8, 0xA448, 0xC9E9, 0xA449, 0xC9EA, + 0xA44A, 0xC9EB, 0xA44B, 0xC9EE, 0xA44C, 0xC9F2, 0xA44D, 0xC9F3, 0xA44E, 0xC9F4, 0xA44F, 0xC9F5, 0xA450, 0xC9F6, 0xA451, 0xC9F7, + 0xA452, 0xC9FA, 0xA453, 0xC9FB, 0xA454, 0xC9FD, 0xA455, 0xC9FE, 0xA456, 0xC9FF, 0xA457, 0xCA01, 0xA458, 0xCA02, 0xA459, 0xCA03, + 0xA45A, 0xCA04, 0xA461, 0xCA05, 0xA462, 0xCA06, 0xA463, 0xCA07, 0xA464, 0xCA0A, 0xA465, 0xCA0E, 0xA466, 0xCA0F, 0xA467, 0xCA10, + 0xA468, 0xCA11, 0xA469, 0xCA12, 0xA46A, 0xCA13, 0xA46B, 0xCA15, 0xA46C, 0xCA16, 0xA46D, 0xCA17, 0xA46E, 0xCA19, 0xA46F, 0xCA1A, + 0xA470, 0xCA1B, 0xA471, 0xCA1C, 0xA472, 0xCA1D, 0xA473, 0xCA1E, 0xA474, 0xCA1F, 0xA475, 0xCA20, 0xA476, 0xCA21, 0xA477, 0xCA22, + 0xA478, 0xCA23, 0xA479, 0xCA24, 0xA47A, 0xCA25, 0xA481, 0xCA26, 0xA482, 0xCA27, 0xA483, 0xCA28, 0xA484, 0xCA2A, 0xA485, 0xCA2B, + 0xA486, 0xCA2C, 0xA487, 0xCA2D, 0xA488, 0xCA2E, 0xA489, 0xCA2F, 0xA48A, 0xCA30, 0xA48B, 0xCA31, 0xA48C, 0xCA32, 0xA48D, 0xCA33, + 0xA48E, 0xCA34, 0xA48F, 0xCA35, 0xA490, 0xCA36, 0xA491, 0xCA37, 0xA492, 0xCA38, 0xA493, 0xCA39, 0xA494, 0xCA3A, 0xA495, 0xCA3B, + 0xA496, 0xCA3C, 0xA497, 0xCA3D, 0xA498, 0xCA3E, 0xA499, 0xCA3F, 0xA49A, 0xCA40, 0xA49B, 0xCA41, 0xA49C, 0xCA42, 0xA49D, 0xCA43, + 0xA49E, 0xCA44, 0xA49F, 0xCA45, 0xA4A0, 0xCA46, 0xA4A1, 0x3131, 0xA4A2, 0x3132, 0xA4A3, 0x3133, 0xA4A4, 0x3134, 0xA4A5, 0x3135, + 0xA4A6, 0x3136, 0xA4A7, 0x3137, 0xA4A8, 0x3138, 0xA4A9, 0x3139, 0xA4AA, 0x313A, 0xA4AB, 0x313B, 0xA4AC, 0x313C, 0xA4AD, 0x313D, + 0xA4AE, 0x313E, 0xA4AF, 0x313F, 0xA4B0, 0x3140, 0xA4B1, 0x3141, 0xA4B2, 0x3142, 0xA4B3, 0x3143, 0xA4B4, 0x3144, 0xA4B5, 0x3145, + 0xA4B6, 0x3146, 0xA4B7, 0x3147, 0xA4B8, 0x3148, 0xA4B9, 0x3149, 0xA4BA, 0x314A, 0xA4BB, 0x314B, 0xA4BC, 0x314C, 0xA4BD, 0x314D, + 0xA4BE, 0x314E, 0xA4BF, 0x314F, 0xA4C0, 0x3150, 0xA4C1, 0x3151, 0xA4C2, 0x3152, 0xA4C3, 0x3153, 0xA4C4, 0x3154, 0xA4C5, 0x3155, + 0xA4C6, 0x3156, 0xA4C7, 0x3157, 0xA4C8, 0x3158, 0xA4C9, 0x3159, 0xA4CA, 0x315A, 0xA4CB, 0x315B, 0xA4CC, 0x315C, 0xA4CD, 0x315D, + 0xA4CE, 0x315E, 0xA4CF, 0x315F, 0xA4D0, 0x3160, 0xA4D1, 0x3161, 0xA4D2, 0x3162, 0xA4D3, 0x3163, 0xA4D4, 0x3164, 0xA4D5, 0x3165, + 0xA4D6, 0x3166, 0xA4D7, 0x3167, 0xA4D8, 0x3168, 0xA4D9, 0x3169, 0xA4DA, 0x316A, 0xA4DB, 0x316B, 0xA4DC, 0x316C, 0xA4DD, 0x316D, + 0xA4DE, 0x316E, 0xA4DF, 0x316F, 0xA4E0, 0x3170, 0xA4E1, 0x3171, 0xA4E2, 0x3172, 0xA4E3, 0x3173, 0xA4E4, 0x3174, 0xA4E5, 0x3175, + 0xA4E6, 0x3176, 0xA4E7, 0x3177, 0xA4E8, 0x3178, 0xA4E9, 0x3179, 0xA4EA, 0x317A, 0xA4EB, 0x317B, 0xA4EC, 0x317C, 0xA4ED, 0x317D, + 0xA4EE, 0x317E, 0xA4EF, 0x317F, 0xA4F0, 0x3180, 0xA4F1, 0x3181, 0xA4F2, 0x3182, 0xA4F3, 0x3183, 0xA4F4, 0x3184, 0xA4F5, 0x3185, + 0xA4F6, 0x3186, 0xA4F7, 0x3187, 0xA4F8, 0x3188, 0xA4F9, 0x3189, 0xA4FA, 0x318A, 0xA4FB, 0x318B, 0xA4FC, 0x318C, 0xA4FD, 0x318D, + 0xA4FE, 0x318E, 0xA541, 0xCA47, 0xA542, 0xCA48, 0xA543, 0xCA49, 0xA544, 0xCA4A, 0xA545, 0xCA4B, 0xA546, 0xCA4E, 0xA547, 0xCA4F, + 0xA548, 0xCA51, 0xA549, 0xCA52, 0xA54A, 0xCA53, 0xA54B, 0xCA55, 0xA54C, 0xCA56, 0xA54D, 0xCA57, 0xA54E, 0xCA58, 0xA54F, 0xCA59, + 0xA550, 0xCA5A, 0xA551, 0xCA5B, 0xA552, 0xCA5E, 0xA553, 0xCA62, 0xA554, 0xCA63, 0xA555, 0xCA64, 0xA556, 0xCA65, 0xA557, 0xCA66, + 0xA558, 0xCA67, 0xA559, 0xCA69, 0xA55A, 0xCA6A, 0xA561, 0xCA6B, 0xA562, 0xCA6C, 0xA563, 0xCA6D, 0xA564, 0xCA6E, 0xA565, 0xCA6F, + 0xA566, 0xCA70, 0xA567, 0xCA71, 0xA568, 0xCA72, 0xA569, 0xCA73, 0xA56A, 0xCA74, 0xA56B, 0xCA75, 0xA56C, 0xCA76, 0xA56D, 0xCA77, + 0xA56E, 0xCA78, 0xA56F, 0xCA79, 0xA570, 0xCA7A, 0xA571, 0xCA7B, 0xA572, 0xCA7C, 0xA573, 0xCA7E, 0xA574, 0xCA7F, 0xA575, 0xCA80, + 0xA576, 0xCA81, 0xA577, 0xCA82, 0xA578, 0xCA83, 0xA579, 0xCA85, 0xA57A, 0xCA86, 0xA581, 0xCA87, 0xA582, 0xCA88, 0xA583, 0xCA89, + 0xA584, 0xCA8A, 0xA585, 0xCA8B, 0xA586, 0xCA8C, 0xA587, 0xCA8D, 0xA588, 0xCA8E, 0xA589, 0xCA8F, 0xA58A, 0xCA90, 0xA58B, 0xCA91, + 0xA58C, 0xCA92, 0xA58D, 0xCA93, 0xA58E, 0xCA94, 0xA58F, 0xCA95, 0xA590, 0xCA96, 0xA591, 0xCA97, 0xA592, 0xCA99, 0xA593, 0xCA9A, + 0xA594, 0xCA9B, 0xA595, 0xCA9C, 0xA596, 0xCA9D, 0xA597, 0xCA9E, 0xA598, 0xCA9F, 0xA599, 0xCAA0, 0xA59A, 0xCAA1, 0xA59B, 0xCAA2, + 0xA59C, 0xCAA3, 0xA59D, 0xCAA4, 0xA59E, 0xCAA5, 0xA59F, 0xCAA6, 0xA5A0, 0xCAA7, 0xA5A1, 0x2170, 0xA5A2, 0x2171, 0xA5A3, 0x2172, + 0xA5A4, 0x2173, 0xA5A5, 0x2174, 0xA5A6, 0x2175, 0xA5A7, 0x2176, 0xA5A8, 0x2177, 0xA5A9, 0x2178, 0xA5AA, 0x2179, 0xA5B0, 0x2160, + 0xA5B1, 0x2161, 0xA5B2, 0x2162, 0xA5B3, 0x2163, 0xA5B4, 0x2164, 0xA5B5, 0x2165, 0xA5B6, 0x2166, 0xA5B7, 0x2167, 0xA5B8, 0x2168, + 0xA5B9, 0x2169, 0xA5C1, 0x0391, 0xA5C2, 0x0392, 0xA5C3, 0x0393, 0xA5C4, 0x0394, 0xA5C5, 0x0395, 0xA5C6, 0x0396, 0xA5C7, 0x0397, + 0xA5C8, 0x0398, 0xA5C9, 0x0399, 0xA5CA, 0x039A, 0xA5CB, 0x039B, 0xA5CC, 0x039C, 0xA5CD, 0x039D, 0xA5CE, 0x039E, 0xA5CF, 0x039F, + 0xA5D0, 0x03A0, 0xA5D1, 0x03A1, 0xA5D2, 0x03A3, 0xA5D3, 0x03A4, 0xA5D4, 0x03A5, 0xA5D5, 0x03A6, 0xA5D6, 0x03A7, 0xA5D7, 0x03A8, + 0xA5D8, 0x03A9, 0xA5E1, 0x03B1, 0xA5E2, 0x03B2, 0xA5E3, 0x03B3, 0xA5E4, 0x03B4, 0xA5E5, 0x03B5, 0xA5E6, 0x03B6, 0xA5E7, 0x03B7, + 0xA5E8, 0x03B8, 0xA5E9, 0x03B9, 0xA5EA, 0x03BA, 0xA5EB, 0x03BB, 0xA5EC, 0x03BC, 0xA5ED, 0x03BD, 0xA5EE, 0x03BE, 0xA5EF, 0x03BF, + 0xA5F0, 0x03C0, 0xA5F1, 0x03C1, 0xA5F2, 0x03C3, 0xA5F3, 0x03C4, 0xA5F4, 0x03C5, 0xA5F5, 0x03C6, 0xA5F6, 0x03C7, 0xA5F7, 0x03C8, + 0xA5F8, 0x03C9, 0xA641, 0xCAA8, 0xA642, 0xCAA9, 0xA643, 0xCAAA, 0xA644, 0xCAAB, 0xA645, 0xCAAC, 0xA646, 0xCAAD, 0xA647, 0xCAAE, + 0xA648, 0xCAAF, 0xA649, 0xCAB0, 0xA64A, 0xCAB1, 0xA64B, 0xCAB2, 0xA64C, 0xCAB3, 0xA64D, 0xCAB4, 0xA64E, 0xCAB5, 0xA64F, 0xCAB6, + 0xA650, 0xCAB7, 0xA651, 0xCAB8, 0xA652, 0xCAB9, 0xA653, 0xCABA, 0xA654, 0xCABB, 0xA655, 0xCABE, 0xA656, 0xCABF, 0xA657, 0xCAC1, + 0xA658, 0xCAC2, 0xA659, 0xCAC3, 0xA65A, 0xCAC5, 0xA661, 0xCAC6, 0xA662, 0xCAC7, 0xA663, 0xCAC8, 0xA664, 0xCAC9, 0xA665, 0xCACA, + 0xA666, 0xCACB, 0xA667, 0xCACE, 0xA668, 0xCAD0, 0xA669, 0xCAD2, 0xA66A, 0xCAD4, 0xA66B, 0xCAD5, 0xA66C, 0xCAD6, 0xA66D, 0xCAD7, + 0xA66E, 0xCADA, 0xA66F, 0xCADB, 0xA670, 0xCADC, 0xA671, 0xCADD, 0xA672, 0xCADE, 0xA673, 0xCADF, 0xA674, 0xCAE1, 0xA675, 0xCAE2, + 0xA676, 0xCAE3, 0xA677, 0xCAE4, 0xA678, 0xCAE5, 0xA679, 0xCAE6, 0xA67A, 0xCAE7, 0xA681, 0xCAE8, 0xA682, 0xCAE9, 0xA683, 0xCAEA, + 0xA684, 0xCAEB, 0xA685, 0xCAED, 0xA686, 0xCAEE, 0xA687, 0xCAEF, 0xA688, 0xCAF0, 0xA689, 0xCAF1, 0xA68A, 0xCAF2, 0xA68B, 0xCAF3, + 0xA68C, 0xCAF5, 0xA68D, 0xCAF6, 0xA68E, 0xCAF7, 0xA68F, 0xCAF8, 0xA690, 0xCAF9, 0xA691, 0xCAFA, 0xA692, 0xCAFB, 0xA693, 0xCAFC, + 0xA694, 0xCAFD, 0xA695, 0xCAFE, 0xA696, 0xCAFF, 0xA697, 0xCB00, 0xA698, 0xCB01, 0xA699, 0xCB02, 0xA69A, 0xCB03, 0xA69B, 0xCB04, + 0xA69C, 0xCB05, 0xA69D, 0xCB06, 0xA69E, 0xCB07, 0xA69F, 0xCB09, 0xA6A0, 0xCB0A, 0xA6A1, 0x2500, 0xA6A2, 0x2502, 0xA6A3, 0x250C, + 0xA6A4, 0x2510, 0xA6A5, 0x2518, 0xA6A6, 0x2514, 0xA6A7, 0x251C, 0xA6A8, 0x252C, 0xA6A9, 0x2524, 0xA6AA, 0x2534, 0xA6AB, 0x253C, + 0xA6AC, 0x2501, 0xA6AD, 0x2503, 0xA6AE, 0x250F, 0xA6AF, 0x2513, 0xA6B0, 0x251B, 0xA6B1, 0x2517, 0xA6B2, 0x2523, 0xA6B3, 0x2533, + 0xA6B4, 0x252B, 0xA6B5, 0x253B, 0xA6B6, 0x254B, 0xA6B7, 0x2520, 0xA6B8, 0x252F, 0xA6B9, 0x2528, 0xA6BA, 0x2537, 0xA6BB, 0x253F, + 0xA6BC, 0x251D, 0xA6BD, 0x2530, 0xA6BE, 0x2525, 0xA6BF, 0x2538, 0xA6C0, 0x2542, 0xA6C1, 0x2512, 0xA6C2, 0x2511, 0xA6C3, 0x251A, + 0xA6C4, 0x2519, 0xA6C5, 0x2516, 0xA6C6, 0x2515, 0xA6C7, 0x250E, 0xA6C8, 0x250D, 0xA6C9, 0x251E, 0xA6CA, 0x251F, 0xA6CB, 0x2521, + 0xA6CC, 0x2522, 0xA6CD, 0x2526, 0xA6CE, 0x2527, 0xA6CF, 0x2529, 0xA6D0, 0x252A, 0xA6D1, 0x252D, 0xA6D2, 0x252E, 0xA6D3, 0x2531, + 0xA6D4, 0x2532, 0xA6D5, 0x2535, 0xA6D6, 0x2536, 0xA6D7, 0x2539, 0xA6D8, 0x253A, 0xA6D9, 0x253D, 0xA6DA, 0x253E, 0xA6DB, 0x2540, + 0xA6DC, 0x2541, 0xA6DD, 0x2543, 0xA6DE, 0x2544, 0xA6DF, 0x2545, 0xA6E0, 0x2546, 0xA6E1, 0x2547, 0xA6E2, 0x2548, 0xA6E3, 0x2549, + 0xA6E4, 0x254A, 0xA741, 0xCB0B, 0xA742, 0xCB0C, 0xA743, 0xCB0D, 0xA744, 0xCB0E, 0xA745, 0xCB0F, 0xA746, 0xCB11, 0xA747, 0xCB12, + 0xA748, 0xCB13, 0xA749, 0xCB15, 0xA74A, 0xCB16, 0xA74B, 0xCB17, 0xA74C, 0xCB19, 0xA74D, 0xCB1A, 0xA74E, 0xCB1B, 0xA74F, 0xCB1C, + 0xA750, 0xCB1D, 0xA751, 0xCB1E, 0xA752, 0xCB1F, 0xA753, 0xCB22, 0xA754, 0xCB23, 0xA755, 0xCB24, 0xA756, 0xCB25, 0xA757, 0xCB26, + 0xA758, 0xCB27, 0xA759, 0xCB28, 0xA75A, 0xCB29, 0xA761, 0xCB2A, 0xA762, 0xCB2B, 0xA763, 0xCB2C, 0xA764, 0xCB2D, 0xA765, 0xCB2E, + 0xA766, 0xCB2F, 0xA767, 0xCB30, 0xA768, 0xCB31, 0xA769, 0xCB32, 0xA76A, 0xCB33, 0xA76B, 0xCB34, 0xA76C, 0xCB35, 0xA76D, 0xCB36, + 0xA76E, 0xCB37, 0xA76F, 0xCB38, 0xA770, 0xCB39, 0xA771, 0xCB3A, 0xA772, 0xCB3B, 0xA773, 0xCB3C, 0xA774, 0xCB3D, 0xA775, 0xCB3E, + 0xA776, 0xCB3F, 0xA777, 0xCB40, 0xA778, 0xCB42, 0xA779, 0xCB43, 0xA77A, 0xCB44, 0xA781, 0xCB45, 0xA782, 0xCB46, 0xA783, 0xCB47, + 0xA784, 0xCB4A, 0xA785, 0xCB4B, 0xA786, 0xCB4D, 0xA787, 0xCB4E, 0xA788, 0xCB4F, 0xA789, 0xCB51, 0xA78A, 0xCB52, 0xA78B, 0xCB53, + 0xA78C, 0xCB54, 0xA78D, 0xCB55, 0xA78E, 0xCB56, 0xA78F, 0xCB57, 0xA790, 0xCB5A, 0xA791, 0xCB5B, 0xA792, 0xCB5C, 0xA793, 0xCB5E, + 0xA794, 0xCB5F, 0xA795, 0xCB60, 0xA796, 0xCB61, 0xA797, 0xCB62, 0xA798, 0xCB63, 0xA799, 0xCB65, 0xA79A, 0xCB66, 0xA79B, 0xCB67, + 0xA79C, 0xCB68, 0xA79D, 0xCB69, 0xA79E, 0xCB6A, 0xA79F, 0xCB6B, 0xA7A0, 0xCB6C, 0xA7A1, 0x3395, 0xA7A2, 0x3396, 0xA7A3, 0x3397, + 0xA7A4, 0x2113, 0xA7A5, 0x3398, 0xA7A6, 0x33C4, 0xA7A7, 0x33A3, 0xA7A8, 0x33A4, 0xA7A9, 0x33A5, 0xA7AA, 0x33A6, 0xA7AB, 0x3399, + 0xA7AC, 0x339A, 0xA7AD, 0x339B, 0xA7AE, 0x339C, 0xA7AF, 0x339D, 0xA7B0, 0x339E, 0xA7B1, 0x339F, 0xA7B2, 0x33A0, 0xA7B3, 0x33A1, + 0xA7B4, 0x33A2, 0xA7B5, 0x33CA, 0xA7B6, 0x338D, 0xA7B7, 0x338E, 0xA7B8, 0x338F, 0xA7B9, 0x33CF, 0xA7BA, 0x3388, 0xA7BB, 0x3389, + 0xA7BC, 0x33C8, 0xA7BD, 0x33A7, 0xA7BE, 0x33A8, 0xA7BF, 0x33B0, 0xA7C0, 0x33B1, 0xA7C1, 0x33B2, 0xA7C2, 0x33B3, 0xA7C3, 0x33B4, + 0xA7C4, 0x33B5, 0xA7C5, 0x33B6, 0xA7C6, 0x33B7, 0xA7C7, 0x33B8, 0xA7C8, 0x33B9, 0xA7C9, 0x3380, 0xA7CA, 0x3381, 0xA7CB, 0x3382, + 0xA7CC, 0x3383, 0xA7CD, 0x3384, 0xA7CE, 0x33BA, 0xA7CF, 0x33BB, 0xA7D0, 0x33BC, 0xA7D1, 0x33BD, 0xA7D2, 0x33BE, 0xA7D3, 0x33BF, + 0xA7D4, 0x3390, 0xA7D5, 0x3391, 0xA7D6, 0x3392, 0xA7D7, 0x3393, 0xA7D8, 0x3394, 0xA7D9, 0x2126, 0xA7DA, 0x33C0, 0xA7DB, 0x33C1, + 0xA7DC, 0x338A, 0xA7DD, 0x338B, 0xA7DE, 0x338C, 0xA7DF, 0x33D6, 0xA7E0, 0x33C5, 0xA7E1, 0x33AD, 0xA7E2, 0x33AE, 0xA7E3, 0x33AF, + 0xA7E4, 0x33DB, 0xA7E5, 0x33A9, 0xA7E6, 0x33AA, 0xA7E7, 0x33AB, 0xA7E8, 0x33AC, 0xA7E9, 0x33DD, 0xA7EA, 0x33D0, 0xA7EB, 0x33D3, + 0xA7EC, 0x33C3, 0xA7ED, 0x33C9, 0xA7EE, 0x33DC, 0xA7EF, 0x33C6, 0xA841, 0xCB6D, 0xA842, 0xCB6E, 0xA843, 0xCB6F, 0xA844, 0xCB70, + 0xA845, 0xCB71, 0xA846, 0xCB72, 0xA847, 0xCB73, 0xA848, 0xCB74, 0xA849, 0xCB75, 0xA84A, 0xCB76, 0xA84B, 0xCB77, 0xA84C, 0xCB7A, + 0xA84D, 0xCB7B, 0xA84E, 0xCB7C, 0xA84F, 0xCB7D, 0xA850, 0xCB7E, 0xA851, 0xCB7F, 0xA852, 0xCB80, 0xA853, 0xCB81, 0xA854, 0xCB82, + 0xA855, 0xCB83, 0xA856, 0xCB84, 0xA857, 0xCB85, 0xA858, 0xCB86, 0xA859, 0xCB87, 0xA85A, 0xCB88, 0xA861, 0xCB89, 0xA862, 0xCB8A, + 0xA863, 0xCB8B, 0xA864, 0xCB8C, 0xA865, 0xCB8D, 0xA866, 0xCB8E, 0xA867, 0xCB8F, 0xA868, 0xCB90, 0xA869, 0xCB91, 0xA86A, 0xCB92, + 0xA86B, 0xCB93, 0xA86C, 0xCB94, 0xA86D, 0xCB95, 0xA86E, 0xCB96, 0xA86F, 0xCB97, 0xA870, 0xCB98, 0xA871, 0xCB99, 0xA872, 0xCB9A, + 0xA873, 0xCB9B, 0xA874, 0xCB9D, 0xA875, 0xCB9E, 0xA876, 0xCB9F, 0xA877, 0xCBA0, 0xA878, 0xCBA1, 0xA879, 0xCBA2, 0xA87A, 0xCBA3, + 0xA881, 0xCBA4, 0xA882, 0xCBA5, 0xA883, 0xCBA6, 0xA884, 0xCBA7, 0xA885, 0xCBA8, 0xA886, 0xCBA9, 0xA887, 0xCBAA, 0xA888, 0xCBAB, + 0xA889, 0xCBAC, 0xA88A, 0xCBAD, 0xA88B, 0xCBAE, 0xA88C, 0xCBAF, 0xA88D, 0xCBB0, 0xA88E, 0xCBB1, 0xA88F, 0xCBB2, 0xA890, 0xCBB3, + 0xA891, 0xCBB4, 0xA892, 0xCBB5, 0xA893, 0xCBB6, 0xA894, 0xCBB7, 0xA895, 0xCBB9, 0xA896, 0xCBBA, 0xA897, 0xCBBB, 0xA898, 0xCBBC, + 0xA899, 0xCBBD, 0xA89A, 0xCBBE, 0xA89B, 0xCBBF, 0xA89C, 0xCBC0, 0xA89D, 0xCBC1, 0xA89E, 0xCBC2, 0xA89F, 0xCBC3, 0xA8A0, 0xCBC4, + 0xA8A1, 0x00C6, 0xA8A2, 0x00D0, 0xA8A3, 0x00AA, 0xA8A4, 0x0126, 0xA8A6, 0x0132, 0xA8A8, 0x013F, 0xA8A9, 0x0141, 0xA8AA, 0x00D8, + 0xA8AB, 0x0152, 0xA8AC, 0x00BA, 0xA8AD, 0x00DE, 0xA8AE, 0x0166, 0xA8AF, 0x014A, 0xA8B1, 0x3260, 0xA8B2, 0x3261, 0xA8B3, 0x3262, + 0xA8B4, 0x3263, 0xA8B5, 0x3264, 0xA8B6, 0x3265, 0xA8B7, 0x3266, 0xA8B8, 0x3267, 0xA8B9, 0x3268, 0xA8BA, 0x3269, 0xA8BB, 0x326A, + 0xA8BC, 0x326B, 0xA8BD, 0x326C, 0xA8BE, 0x326D, 0xA8BF, 0x326E, 0xA8C0, 0x326F, 0xA8C1, 0x3270, 0xA8C2, 0x3271, 0xA8C3, 0x3272, + 0xA8C4, 0x3273, 0xA8C5, 0x3274, 0xA8C6, 0x3275, 0xA8C7, 0x3276, 0xA8C8, 0x3277, 0xA8C9, 0x3278, 0xA8CA, 0x3279, 0xA8CB, 0x327A, + 0xA8CC, 0x327B, 0xA8CD, 0x24D0, 0xA8CE, 0x24D1, 0xA8CF, 0x24D2, 0xA8D0, 0x24D3, 0xA8D1, 0x24D4, 0xA8D2, 0x24D5, 0xA8D3, 0x24D6, + 0xA8D4, 0x24D7, 0xA8D5, 0x24D8, 0xA8D6, 0x24D9, 0xA8D7, 0x24DA, 0xA8D8, 0x24DB, 0xA8D9, 0x24DC, 0xA8DA, 0x24DD, 0xA8DB, 0x24DE, + 0xA8DC, 0x24DF, 0xA8DD, 0x24E0, 0xA8DE, 0x24E1, 0xA8DF, 0x24E2, 0xA8E0, 0x24E3, 0xA8E1, 0x24E4, 0xA8E2, 0x24E5, 0xA8E3, 0x24E6, + 0xA8E4, 0x24E7, 0xA8E5, 0x24E8, 0xA8E6, 0x24E9, 0xA8E7, 0x2460, 0xA8E8, 0x2461, 0xA8E9, 0x2462, 0xA8EA, 0x2463, 0xA8EB, 0x2464, + 0xA8EC, 0x2465, 0xA8ED, 0x2466, 0xA8EE, 0x2467, 0xA8EF, 0x2468, 0xA8F0, 0x2469, 0xA8F1, 0x246A, 0xA8F2, 0x246B, 0xA8F3, 0x246C, + 0xA8F4, 0x246D, 0xA8F5, 0x246E, 0xA8F6, 0x00BD, 0xA8F7, 0x2153, 0xA8F8, 0x2154, 0xA8F9, 0x00BC, 0xA8FA, 0x00BE, 0xA8FB, 0x215B, + 0xA8FC, 0x215C, 0xA8FD, 0x215D, 0xA8FE, 0x215E, 0xA941, 0xCBC5, 0xA942, 0xCBC6, 0xA943, 0xCBC7, 0xA944, 0xCBC8, 0xA945, 0xCBC9, + 0xA946, 0xCBCA, 0xA947, 0xCBCB, 0xA948, 0xCBCC, 0xA949, 0xCBCD, 0xA94A, 0xCBCE, 0xA94B, 0xCBCF, 0xA94C, 0xCBD0, 0xA94D, 0xCBD1, + 0xA94E, 0xCBD2, 0xA94F, 0xCBD3, 0xA950, 0xCBD5, 0xA951, 0xCBD6, 0xA952, 0xCBD7, 0xA953, 0xCBD8, 0xA954, 0xCBD9, 0xA955, 0xCBDA, + 0xA956, 0xCBDB, 0xA957, 0xCBDC, 0xA958, 0xCBDD, 0xA959, 0xCBDE, 0xA95A, 0xCBDF, 0xA961, 0xCBE0, 0xA962, 0xCBE1, 0xA963, 0xCBE2, + 0xA964, 0xCBE3, 0xA965, 0xCBE5, 0xA966, 0xCBE6, 0xA967, 0xCBE8, 0xA968, 0xCBEA, 0xA969, 0xCBEB, 0xA96A, 0xCBEC, 0xA96B, 0xCBED, + 0xA96C, 0xCBEE, 0xA96D, 0xCBEF, 0xA96E, 0xCBF0, 0xA96F, 0xCBF1, 0xA970, 0xCBF2, 0xA971, 0xCBF3, 0xA972, 0xCBF4, 0xA973, 0xCBF5, + 0xA974, 0xCBF6, 0xA975, 0xCBF7, 0xA976, 0xCBF8, 0xA977, 0xCBF9, 0xA978, 0xCBFA, 0xA979, 0xCBFB, 0xA97A, 0xCBFC, 0xA981, 0xCBFD, + 0xA982, 0xCBFE, 0xA983, 0xCBFF, 0xA984, 0xCC00, 0xA985, 0xCC01, 0xA986, 0xCC02, 0xA987, 0xCC03, 0xA988, 0xCC04, 0xA989, 0xCC05, + 0xA98A, 0xCC06, 0xA98B, 0xCC07, 0xA98C, 0xCC08, 0xA98D, 0xCC09, 0xA98E, 0xCC0A, 0xA98F, 0xCC0B, 0xA990, 0xCC0E, 0xA991, 0xCC0F, + 0xA992, 0xCC11, 0xA993, 0xCC12, 0xA994, 0xCC13, 0xA995, 0xCC15, 0xA996, 0xCC16, 0xA997, 0xCC17, 0xA998, 0xCC18, 0xA999, 0xCC19, + 0xA99A, 0xCC1A, 0xA99B, 0xCC1B, 0xA99C, 0xCC1E, 0xA99D, 0xCC1F, 0xA99E, 0xCC20, 0xA99F, 0xCC23, 0xA9A0, 0xCC24, 0xA9A1, 0x00E6, + 0xA9A2, 0x0111, 0xA9A3, 0x00F0, 0xA9A4, 0x0127, 0xA9A5, 0x0131, 0xA9A6, 0x0133, 0xA9A7, 0x0138, 0xA9A8, 0x0140, 0xA9A9, 0x0142, + 0xA9AA, 0x00F8, 0xA9AB, 0x0153, 0xA9AC, 0x00DF, 0xA9AD, 0x00FE, 0xA9AE, 0x0167, 0xA9AF, 0x014B, 0xA9B0, 0x0149, 0xA9B1, 0x3200, + 0xA9B2, 0x3201, 0xA9B3, 0x3202, 0xA9B4, 0x3203, 0xA9B5, 0x3204, 0xA9B6, 0x3205, 0xA9B7, 0x3206, 0xA9B8, 0x3207, 0xA9B9, 0x3208, + 0xA9BA, 0x3209, 0xA9BB, 0x320A, 0xA9BC, 0x320B, 0xA9BD, 0x320C, 0xA9BE, 0x320D, 0xA9BF, 0x320E, 0xA9C0, 0x320F, 0xA9C1, 0x3210, + 0xA9C2, 0x3211, 0xA9C3, 0x3212, 0xA9C4, 0x3213, 0xA9C5, 0x3214, 0xA9C6, 0x3215, 0xA9C7, 0x3216, 0xA9C8, 0x3217, 0xA9C9, 0x3218, + 0xA9CA, 0x3219, 0xA9CB, 0x321A, 0xA9CC, 0x321B, 0xA9CD, 0x249C, 0xA9CE, 0x249D, 0xA9CF, 0x249E, 0xA9D0, 0x249F, 0xA9D1, 0x24A0, + 0xA9D2, 0x24A1, 0xA9D3, 0x24A2, 0xA9D4, 0x24A3, 0xA9D5, 0x24A4, 0xA9D6, 0x24A5, 0xA9D7, 0x24A6, 0xA9D8, 0x24A7, 0xA9D9, 0x24A8, + 0xA9DA, 0x24A9, 0xA9DB, 0x24AA, 0xA9DC, 0x24AB, 0xA9DD, 0x24AC, 0xA9DE, 0x24AD, 0xA9DF, 0x24AE, 0xA9E0, 0x24AF, 0xA9E1, 0x24B0, + 0xA9E2, 0x24B1, 0xA9E3, 0x24B2, 0xA9E4, 0x24B3, 0xA9E5, 0x24B4, 0xA9E6, 0x24B5, 0xA9E7, 0x2474, 0xA9E8, 0x2475, 0xA9E9, 0x2476, + 0xA9EA, 0x2477, 0xA9EB, 0x2478, 0xA9EC, 0x2479, 0xA9ED, 0x247A, 0xA9EE, 0x247B, 0xA9EF, 0x247C, 0xA9F0, 0x247D, 0xA9F1, 0x247E, + 0xA9F2, 0x247F, 0xA9F3, 0x2480, 0xA9F4, 0x2481, 0xA9F5, 0x2482, 0xA9F6, 0x00B9, 0xA9F7, 0x00B2, 0xA9F8, 0x00B3, 0xA9F9, 0x2074, + 0xA9FA, 0x207F, 0xA9FB, 0x2081, 0xA9FC, 0x2082, 0xA9FD, 0x2083, 0xA9FE, 0x2084, 0xAA41, 0xCC25, 0xAA42, 0xCC26, 0xAA43, 0xCC2A, + 0xAA44, 0xCC2B, 0xAA45, 0xCC2D, 0xAA46, 0xCC2F, 0xAA47, 0xCC31, 0xAA48, 0xCC32, 0xAA49, 0xCC33, 0xAA4A, 0xCC34, 0xAA4B, 0xCC35, + 0xAA4C, 0xCC36, 0xAA4D, 0xCC37, 0xAA4E, 0xCC3A, 0xAA4F, 0xCC3F, 0xAA50, 0xCC40, 0xAA51, 0xCC41, 0xAA52, 0xCC42, 0xAA53, 0xCC43, + 0xAA54, 0xCC46, 0xAA55, 0xCC47, 0xAA56, 0xCC49, 0xAA57, 0xCC4A, 0xAA58, 0xCC4B, 0xAA59, 0xCC4D, 0xAA5A, 0xCC4E, 0xAA61, 0xCC4F, + 0xAA62, 0xCC50, 0xAA63, 0xCC51, 0xAA64, 0xCC52, 0xAA65, 0xCC53, 0xAA66, 0xCC56, 0xAA67, 0xCC5A, 0xAA68, 0xCC5B, 0xAA69, 0xCC5C, + 0xAA6A, 0xCC5D, 0xAA6B, 0xCC5E, 0xAA6C, 0xCC5F, 0xAA6D, 0xCC61, 0xAA6E, 0xCC62, 0xAA6F, 0xCC63, 0xAA70, 0xCC65, 0xAA71, 0xCC67, + 0xAA72, 0xCC69, 0xAA73, 0xCC6A, 0xAA74, 0xCC6B, 0xAA75, 0xCC6C, 0xAA76, 0xCC6D, 0xAA77, 0xCC6E, 0xAA78, 0xCC6F, 0xAA79, 0xCC71, + 0xAA7A, 0xCC72, 0xAA81, 0xCC73, 0xAA82, 0xCC74, 0xAA83, 0xCC76, 0xAA84, 0xCC77, 0xAA85, 0xCC78, 0xAA86, 0xCC79, 0xAA87, 0xCC7A, + 0xAA88, 0xCC7B, 0xAA89, 0xCC7C, 0xAA8A, 0xCC7D, 0xAA8B, 0xCC7E, 0xAA8C, 0xCC7F, 0xAA8D, 0xCC80, 0xAA8E, 0xCC81, 0xAA8F, 0xCC82, + 0xAA90, 0xCC83, 0xAA91, 0xCC84, 0xAA92, 0xCC85, 0xAA93, 0xCC86, 0xAA94, 0xCC87, 0xAA95, 0xCC88, 0xAA96, 0xCC89, 0xAA97, 0xCC8A, + 0xAA98, 0xCC8B, 0xAA99, 0xCC8C, 0xAA9A, 0xCC8D, 0xAA9B, 0xCC8E, 0xAA9C, 0xCC8F, 0xAA9D, 0xCC90, 0xAA9E, 0xCC91, 0xAA9F, 0xCC92, + 0xAAA0, 0xCC93, 0xAAA1, 0x3041, 0xAAA2, 0x3042, 0xAAA3, 0x3043, 0xAAA4, 0x3044, 0xAAA5, 0x3045, 0xAAA6, 0x3046, 0xAAA7, 0x3047, + 0xAAA8, 0x3048, 0xAAA9, 0x3049, 0xAAAA, 0x304A, 0xAAAB, 0x304B, 0xAAAC, 0x304C, 0xAAAD, 0x304D, 0xAAAE, 0x304E, 0xAAAF, 0x304F, + 0xAAB0, 0x3050, 0xAAB1, 0x3051, 0xAAB2, 0x3052, 0xAAB3, 0x3053, 0xAAB4, 0x3054, 0xAAB5, 0x3055, 0xAAB6, 0x3056, 0xAAB7, 0x3057, + 0xAAB8, 0x3058, 0xAAB9, 0x3059, 0xAABA, 0x305A, 0xAABB, 0x305B, 0xAABC, 0x305C, 0xAABD, 0x305D, 0xAABE, 0x305E, 0xAABF, 0x305F, + 0xAAC0, 0x3060, 0xAAC1, 0x3061, 0xAAC2, 0x3062, 0xAAC3, 0x3063, 0xAAC4, 0x3064, 0xAAC5, 0x3065, 0xAAC6, 0x3066, 0xAAC7, 0x3067, + 0xAAC8, 0x3068, 0xAAC9, 0x3069, 0xAACA, 0x306A, 0xAACB, 0x306B, 0xAACC, 0x306C, 0xAACD, 0x306D, 0xAACE, 0x306E, 0xAACF, 0x306F, + 0xAAD0, 0x3070, 0xAAD1, 0x3071, 0xAAD2, 0x3072, 0xAAD3, 0x3073, 0xAAD4, 0x3074, 0xAAD5, 0x3075, 0xAAD6, 0x3076, 0xAAD7, 0x3077, + 0xAAD8, 0x3078, 0xAAD9, 0x3079, 0xAADA, 0x307A, 0xAADB, 0x307B, 0xAADC, 0x307C, 0xAADD, 0x307D, 0xAADE, 0x307E, 0xAADF, 0x307F, + 0xAAE0, 0x3080, 0xAAE1, 0x3081, 0xAAE2, 0x3082, 0xAAE3, 0x3083, 0xAAE4, 0x3084, 0xAAE5, 0x3085, 0xAAE6, 0x3086, 0xAAE7, 0x3087, + 0xAAE8, 0x3088, 0xAAE9, 0x3089, 0xAAEA, 0x308A, 0xAAEB, 0x308B, 0xAAEC, 0x308C, 0xAAED, 0x308D, 0xAAEE, 0x308E, 0xAAEF, 0x308F, + 0xAAF0, 0x3090, 0xAAF1, 0x3091, 0xAAF2, 0x3092, 0xAAF3, 0x3093, 0xAB41, 0xCC94, 0xAB42, 0xCC95, 0xAB43, 0xCC96, 0xAB44, 0xCC97, + 0xAB45, 0xCC9A, 0xAB46, 0xCC9B, 0xAB47, 0xCC9D, 0xAB48, 0xCC9E, 0xAB49, 0xCC9F, 0xAB4A, 0xCCA1, 0xAB4B, 0xCCA2, 0xAB4C, 0xCCA3, + 0xAB4D, 0xCCA4, 0xAB4E, 0xCCA5, 0xAB4F, 0xCCA6, 0xAB50, 0xCCA7, 0xAB51, 0xCCAA, 0xAB52, 0xCCAE, 0xAB53, 0xCCAF, 0xAB54, 0xCCB0, + 0xAB55, 0xCCB1, 0xAB56, 0xCCB2, 0xAB57, 0xCCB3, 0xAB58, 0xCCB6, 0xAB59, 0xCCB7, 0xAB5A, 0xCCB9, 0xAB61, 0xCCBA, 0xAB62, 0xCCBB, + 0xAB63, 0xCCBD, 0xAB64, 0xCCBE, 0xAB65, 0xCCBF, 0xAB66, 0xCCC0, 0xAB67, 0xCCC1, 0xAB68, 0xCCC2, 0xAB69, 0xCCC3, 0xAB6A, 0xCCC6, + 0xAB6B, 0xCCC8, 0xAB6C, 0xCCCA, 0xAB6D, 0xCCCB, 0xAB6E, 0xCCCC, 0xAB6F, 0xCCCD, 0xAB70, 0xCCCE, 0xAB71, 0xCCCF, 0xAB72, 0xCCD1, + 0xAB73, 0xCCD2, 0xAB74, 0xCCD3, 0xAB75, 0xCCD5, 0xAB76, 0xCCD6, 0xAB77, 0xCCD7, 0xAB78, 0xCCD8, 0xAB79, 0xCCD9, 0xAB7A, 0xCCDA, + 0xAB81, 0xCCDB, 0xAB82, 0xCCDC, 0xAB83, 0xCCDD, 0xAB84, 0xCCDE, 0xAB85, 0xCCDF, 0xAB86, 0xCCE0, 0xAB87, 0xCCE1, 0xAB88, 0xCCE2, + 0xAB89, 0xCCE3, 0xAB8A, 0xCCE5, 0xAB8B, 0xCCE6, 0xAB8C, 0xCCE7, 0xAB8D, 0xCCE8, 0xAB8E, 0xCCE9, 0xAB8F, 0xCCEA, 0xAB90, 0xCCEB, + 0xAB91, 0xCCED, 0xAB92, 0xCCEE, 0xAB93, 0xCCEF, 0xAB94, 0xCCF1, 0xAB95, 0xCCF2, 0xAB96, 0xCCF3, 0xAB97, 0xCCF4, 0xAB98, 0xCCF5, + 0xAB99, 0xCCF6, 0xAB9A, 0xCCF7, 0xAB9B, 0xCCF8, 0xAB9C, 0xCCF9, 0xAB9D, 0xCCFA, 0xAB9E, 0xCCFB, 0xAB9F, 0xCCFC, 0xABA0, 0xCCFD, + 0xABA1, 0x30A1, 0xABA2, 0x30A2, 0xABA3, 0x30A3, 0xABA4, 0x30A4, 0xABA5, 0x30A5, 0xABA6, 0x30A6, 0xABA7, 0x30A7, 0xABA8, 0x30A8, + 0xABA9, 0x30A9, 0xABAA, 0x30AA, 0xABAB, 0x30AB, 0xABAC, 0x30AC, 0xABAD, 0x30AD, 0xABAE, 0x30AE, 0xABAF, 0x30AF, 0xABB0, 0x30B0, + 0xABB1, 0x30B1, 0xABB2, 0x30B2, 0xABB3, 0x30B3, 0xABB4, 0x30B4, 0xABB5, 0x30B5, 0xABB6, 0x30B6, 0xABB7, 0x30B7, 0xABB8, 0x30B8, + 0xABB9, 0x30B9, 0xABBA, 0x30BA, 0xABBB, 0x30BB, 0xABBC, 0x30BC, 0xABBD, 0x30BD, 0xABBE, 0x30BE, 0xABBF, 0x30BF, 0xABC0, 0x30C0, + 0xABC1, 0x30C1, 0xABC2, 0x30C2, 0xABC3, 0x30C3, 0xABC4, 0x30C4, 0xABC5, 0x30C5, 0xABC6, 0x30C6, 0xABC7, 0x30C7, 0xABC8, 0x30C8, + 0xABC9, 0x30C9, 0xABCA, 0x30CA, 0xABCB, 0x30CB, 0xABCC, 0x30CC, 0xABCD, 0x30CD, 0xABCE, 0x30CE, 0xABCF, 0x30CF, 0xABD0, 0x30D0, + 0xABD1, 0x30D1, 0xABD2, 0x30D2, 0xABD3, 0x30D3, 0xABD4, 0x30D4, 0xABD5, 0x30D5, 0xABD6, 0x30D6, 0xABD7, 0x30D7, 0xABD8, 0x30D8, + 0xABD9, 0x30D9, 0xABDA, 0x30DA, 0xABDB, 0x30DB, 0xABDC, 0x30DC, 0xABDD, 0x30DD, 0xABDE, 0x30DE, 0xABDF, 0x30DF, 0xABE0, 0x30E0, + 0xABE1, 0x30E1, 0xABE2, 0x30E2, 0xABE3, 0x30E3, 0xABE4, 0x30E4, 0xABE5, 0x30E5, 0xABE6, 0x30E6, 0xABE7, 0x30E7, 0xABE8, 0x30E8, + 0xABE9, 0x30E9, 0xABEA, 0x30EA, 0xABEB, 0x30EB, 0xABEC, 0x30EC, 0xABED, 0x30ED, 0xABEE, 0x30EE, 0xABEF, 0x30EF, 0xABF0, 0x30F0, + 0xABF1, 0x30F1, 0xABF2, 0x30F2, 0xABF3, 0x30F3, 0xABF4, 0x30F4, 0xABF5, 0x30F5, 0xABF6, 0x30F6, 0xAC41, 0xCCFE, 0xAC42, 0xCCFF, + 0xAC43, 0xCD00, 0xAC44, 0xCD02, 0xAC45, 0xCD03, 0xAC46, 0xCD04, 0xAC47, 0xCD05, 0xAC48, 0xCD06, 0xAC49, 0xCD07, 0xAC4A, 0xCD0A, + 0xAC4B, 0xCD0B, 0xAC4C, 0xCD0D, 0xAC4D, 0xCD0E, 0xAC4E, 0xCD0F, 0xAC4F, 0xCD11, 0xAC50, 0xCD12, 0xAC51, 0xCD13, 0xAC52, 0xCD14, + 0xAC53, 0xCD15, 0xAC54, 0xCD16, 0xAC55, 0xCD17, 0xAC56, 0xCD1A, 0xAC57, 0xCD1C, 0xAC58, 0xCD1E, 0xAC59, 0xCD1F, 0xAC5A, 0xCD20, + 0xAC61, 0xCD21, 0xAC62, 0xCD22, 0xAC63, 0xCD23, 0xAC64, 0xCD25, 0xAC65, 0xCD26, 0xAC66, 0xCD27, 0xAC67, 0xCD29, 0xAC68, 0xCD2A, + 0xAC69, 0xCD2B, 0xAC6A, 0xCD2D, 0xAC6B, 0xCD2E, 0xAC6C, 0xCD2F, 0xAC6D, 0xCD30, 0xAC6E, 0xCD31, 0xAC6F, 0xCD32, 0xAC70, 0xCD33, + 0xAC71, 0xCD34, 0xAC72, 0xCD35, 0xAC73, 0xCD36, 0xAC74, 0xCD37, 0xAC75, 0xCD38, 0xAC76, 0xCD3A, 0xAC77, 0xCD3B, 0xAC78, 0xCD3C, + 0xAC79, 0xCD3D, 0xAC7A, 0xCD3E, 0xAC81, 0xCD3F, 0xAC82, 0xCD40, 0xAC83, 0xCD41, 0xAC84, 0xCD42, 0xAC85, 0xCD43, 0xAC86, 0xCD44, + 0xAC87, 0xCD45, 0xAC88, 0xCD46, 0xAC89, 0xCD47, 0xAC8A, 0xCD48, 0xAC8B, 0xCD49, 0xAC8C, 0xCD4A, 0xAC8D, 0xCD4B, 0xAC8E, 0xCD4C, + 0xAC8F, 0xCD4D, 0xAC90, 0xCD4E, 0xAC91, 0xCD4F, 0xAC92, 0xCD50, 0xAC93, 0xCD51, 0xAC94, 0xCD52, 0xAC95, 0xCD53, 0xAC96, 0xCD54, + 0xAC97, 0xCD55, 0xAC98, 0xCD56, 0xAC99, 0xCD57, 0xAC9A, 0xCD58, 0xAC9B, 0xCD59, 0xAC9C, 0xCD5A, 0xAC9D, 0xCD5B, 0xAC9E, 0xCD5D, + 0xAC9F, 0xCD5E, 0xACA0, 0xCD5F, 0xACA1, 0x0410, 0xACA2, 0x0411, 0xACA3, 0x0412, 0xACA4, 0x0413, 0xACA5, 0x0414, 0xACA6, 0x0415, + 0xACA7, 0x0401, 0xACA8, 0x0416, 0xACA9, 0x0417, 0xACAA, 0x0418, 0xACAB, 0x0419, 0xACAC, 0x041A, 0xACAD, 0x041B, 0xACAE, 0x041C, + 0xACAF, 0x041D, 0xACB0, 0x041E, 0xACB1, 0x041F, 0xACB2, 0x0420, 0xACB3, 0x0421, 0xACB4, 0x0422, 0xACB5, 0x0423, 0xACB6, 0x0424, + 0xACB7, 0x0425, 0xACB8, 0x0426, 0xACB9, 0x0427, 0xACBA, 0x0428, 0xACBB, 0x0429, 0xACBC, 0x042A, 0xACBD, 0x042B, 0xACBE, 0x042C, + 0xACBF, 0x042D, 0xACC0, 0x042E, 0xACC1, 0x042F, 0xACD1, 0x0430, 0xACD2, 0x0431, 0xACD3, 0x0432, 0xACD4, 0x0433, 0xACD5, 0x0434, + 0xACD6, 0x0435, 0xACD7, 0x0451, 0xACD8, 0x0436, 0xACD9, 0x0437, 0xACDA, 0x0438, 0xACDB, 0x0439, 0xACDC, 0x043A, 0xACDD, 0x043B, + 0xACDE, 0x043C, 0xACDF, 0x043D, 0xACE0, 0x043E, 0xACE1, 0x043F, 0xACE2, 0x0440, 0xACE3, 0x0441, 0xACE4, 0x0442, 0xACE5, 0x0443, + 0xACE6, 0x0444, 0xACE7, 0x0445, 0xACE8, 0x0446, 0xACE9, 0x0447, 0xACEA, 0x0448, 0xACEB, 0x0449, 0xACEC, 0x044A, 0xACED, 0x044B, + 0xACEE, 0x044C, 0xACEF, 0x044D, 0xACF0, 0x044E, 0xACF1, 0x044F, 0xAD41, 0xCD61, 0xAD42, 0xCD62, 0xAD43, 0xCD63, 0xAD44, 0xCD65, + 0xAD45, 0xCD66, 0xAD46, 0xCD67, 0xAD47, 0xCD68, 0xAD48, 0xCD69, 0xAD49, 0xCD6A, 0xAD4A, 0xCD6B, 0xAD4B, 0xCD6E, 0xAD4C, 0xCD70, + 0xAD4D, 0xCD72, 0xAD4E, 0xCD73, 0xAD4F, 0xCD74, 0xAD50, 0xCD75, 0xAD51, 0xCD76, 0xAD52, 0xCD77, 0xAD53, 0xCD79, 0xAD54, 0xCD7A, + 0xAD55, 0xCD7B, 0xAD56, 0xCD7C, 0xAD57, 0xCD7D, 0xAD58, 0xCD7E, 0xAD59, 0xCD7F, 0xAD5A, 0xCD80, 0xAD61, 0xCD81, 0xAD62, 0xCD82, + 0xAD63, 0xCD83, 0xAD64, 0xCD84, 0xAD65, 0xCD85, 0xAD66, 0xCD86, 0xAD67, 0xCD87, 0xAD68, 0xCD89, 0xAD69, 0xCD8A, 0xAD6A, 0xCD8B, + 0xAD6B, 0xCD8C, 0xAD6C, 0xCD8D, 0xAD6D, 0xCD8E, 0xAD6E, 0xCD8F, 0xAD6F, 0xCD90, 0xAD70, 0xCD91, 0xAD71, 0xCD92, 0xAD72, 0xCD93, + 0xAD73, 0xCD96, 0xAD74, 0xCD97, 0xAD75, 0xCD99, 0xAD76, 0xCD9A, 0xAD77, 0xCD9B, 0xAD78, 0xCD9D, 0xAD79, 0xCD9E, 0xAD7A, 0xCD9F, + 0xAD81, 0xCDA0, 0xAD82, 0xCDA1, 0xAD83, 0xCDA2, 0xAD84, 0xCDA3, 0xAD85, 0xCDA6, 0xAD86, 0xCDA8, 0xAD87, 0xCDAA, 0xAD88, 0xCDAB, + 0xAD89, 0xCDAC, 0xAD8A, 0xCDAD, 0xAD8B, 0xCDAE, 0xAD8C, 0xCDAF, 0xAD8D, 0xCDB1, 0xAD8E, 0xCDB2, 0xAD8F, 0xCDB3, 0xAD90, 0xCDB4, + 0xAD91, 0xCDB5, 0xAD92, 0xCDB6, 0xAD93, 0xCDB7, 0xAD94, 0xCDB8, 0xAD95, 0xCDB9, 0xAD96, 0xCDBA, 0xAD97, 0xCDBB, 0xAD98, 0xCDBC, + 0xAD99, 0xCDBD, 0xAD9A, 0xCDBE, 0xAD9B, 0xCDBF, 0xAD9C, 0xCDC0, 0xAD9D, 0xCDC1, 0xAD9E, 0xCDC2, 0xAD9F, 0xCDC3, 0xADA0, 0xCDC5, + 0xAE41, 0xCDC6, 0xAE42, 0xCDC7, 0xAE43, 0xCDC8, 0xAE44, 0xCDC9, 0xAE45, 0xCDCA, 0xAE46, 0xCDCB, 0xAE47, 0xCDCD, 0xAE48, 0xCDCE, + 0xAE49, 0xCDCF, 0xAE4A, 0xCDD1, 0xAE4B, 0xCDD2, 0xAE4C, 0xCDD3, 0xAE4D, 0xCDD4, 0xAE4E, 0xCDD5, 0xAE4F, 0xCDD6, 0xAE50, 0xCDD7, + 0xAE51, 0xCDD8, 0xAE52, 0xCDD9, 0xAE53, 0xCDDA, 0xAE54, 0xCDDB, 0xAE55, 0xCDDC, 0xAE56, 0xCDDD, 0xAE57, 0xCDDE, 0xAE58, 0xCDDF, + 0xAE59, 0xCDE0, 0xAE5A, 0xCDE1, 0xAE61, 0xCDE2, 0xAE62, 0xCDE3, 0xAE63, 0xCDE4, 0xAE64, 0xCDE5, 0xAE65, 0xCDE6, 0xAE66, 0xCDE7, + 0xAE67, 0xCDE9, 0xAE68, 0xCDEA, 0xAE69, 0xCDEB, 0xAE6A, 0xCDED, 0xAE6B, 0xCDEE, 0xAE6C, 0xCDEF, 0xAE6D, 0xCDF1, 0xAE6E, 0xCDF2, + 0xAE6F, 0xCDF3, 0xAE70, 0xCDF4, 0xAE71, 0xCDF5, 0xAE72, 0xCDF6, 0xAE73, 0xCDF7, 0xAE74, 0xCDFA, 0xAE75, 0xCDFC, 0xAE76, 0xCDFE, + 0xAE77, 0xCDFF, 0xAE78, 0xCE00, 0xAE79, 0xCE01, 0xAE7A, 0xCE02, 0xAE81, 0xCE03, 0xAE82, 0xCE05, 0xAE83, 0xCE06, 0xAE84, 0xCE07, + 0xAE85, 0xCE09, 0xAE86, 0xCE0A, 0xAE87, 0xCE0B, 0xAE88, 0xCE0D, 0xAE89, 0xCE0E, 0xAE8A, 0xCE0F, 0xAE8B, 0xCE10, 0xAE8C, 0xCE11, + 0xAE8D, 0xCE12, 0xAE8E, 0xCE13, 0xAE8F, 0xCE15, 0xAE90, 0xCE16, 0xAE91, 0xCE17, 0xAE92, 0xCE18, 0xAE93, 0xCE1A, 0xAE94, 0xCE1B, + 0xAE95, 0xCE1C, 0xAE96, 0xCE1D, 0xAE97, 0xCE1E, 0xAE98, 0xCE1F, 0xAE99, 0xCE22, 0xAE9A, 0xCE23, 0xAE9B, 0xCE25, 0xAE9C, 0xCE26, + 0xAE9D, 0xCE27, 0xAE9E, 0xCE29, 0xAE9F, 0xCE2A, 0xAEA0, 0xCE2B, 0xAF41, 0xCE2C, 0xAF42, 0xCE2D, 0xAF43, 0xCE2E, 0xAF44, 0xCE2F, + 0xAF45, 0xCE32, 0xAF46, 0xCE34, 0xAF47, 0xCE36, 0xAF48, 0xCE37, 0xAF49, 0xCE38, 0xAF4A, 0xCE39, 0xAF4B, 0xCE3A, 0xAF4C, 0xCE3B, + 0xAF4D, 0xCE3C, 0xAF4E, 0xCE3D, 0xAF4F, 0xCE3E, 0xAF50, 0xCE3F, 0xAF51, 0xCE40, 0xAF52, 0xCE41, 0xAF53, 0xCE42, 0xAF54, 0xCE43, + 0xAF55, 0xCE44, 0xAF56, 0xCE45, 0xAF57, 0xCE46, 0xAF58, 0xCE47, 0xAF59, 0xCE48, 0xAF5A, 0xCE49, 0xAF61, 0xCE4A, 0xAF62, 0xCE4B, + 0xAF63, 0xCE4C, 0xAF64, 0xCE4D, 0xAF65, 0xCE4E, 0xAF66, 0xCE4F, 0xAF67, 0xCE50, 0xAF68, 0xCE51, 0xAF69, 0xCE52, 0xAF6A, 0xCE53, + 0xAF6B, 0xCE54, 0xAF6C, 0xCE55, 0xAF6D, 0xCE56, 0xAF6E, 0xCE57, 0xAF6F, 0xCE5A, 0xAF70, 0xCE5B, 0xAF71, 0xCE5D, 0xAF72, 0xCE5E, + 0xAF73, 0xCE62, 0xAF74, 0xCE63, 0xAF75, 0xCE64, 0xAF76, 0xCE65, 0xAF77, 0xCE66, 0xAF78, 0xCE67, 0xAF79, 0xCE6A, 0xAF7A, 0xCE6C, + 0xAF81, 0xCE6E, 0xAF82, 0xCE6F, 0xAF83, 0xCE70, 0xAF84, 0xCE71, 0xAF85, 0xCE72, 0xAF86, 0xCE73, 0xAF87, 0xCE76, 0xAF88, 0xCE77, + 0xAF89, 0xCE79, 0xAF8A, 0xCE7A, 0xAF8B, 0xCE7B, 0xAF8C, 0xCE7D, 0xAF8D, 0xCE7E, 0xAF8E, 0xCE7F, 0xAF8F, 0xCE80, 0xAF90, 0xCE81, + 0xAF91, 0xCE82, 0xAF92, 0xCE83, 0xAF93, 0xCE86, 0xAF94, 0xCE88, 0xAF95, 0xCE8A, 0xAF96, 0xCE8B, 0xAF97, 0xCE8C, 0xAF98, 0xCE8D, + 0xAF99, 0xCE8E, 0xAF9A, 0xCE8F, 0xAF9B, 0xCE92, 0xAF9C, 0xCE93, 0xAF9D, 0xCE95, 0xAF9E, 0xCE96, 0xAF9F, 0xCE97, 0xAFA0, 0xCE99, + 0xB041, 0xCE9A, 0xB042, 0xCE9B, 0xB043, 0xCE9C, 0xB044, 0xCE9D, 0xB045, 0xCE9E, 0xB046, 0xCE9F, 0xB047, 0xCEA2, 0xB048, 0xCEA6, + 0xB049, 0xCEA7, 0xB04A, 0xCEA8, 0xB04B, 0xCEA9, 0xB04C, 0xCEAA, 0xB04D, 0xCEAB, 0xB04E, 0xCEAE, 0xB04F, 0xCEAF, 0xB050, 0xCEB0, + 0xB051, 0xCEB1, 0xB052, 0xCEB2, 0xB053, 0xCEB3, 0xB054, 0xCEB4, 0xB055, 0xCEB5, 0xB056, 0xCEB6, 0xB057, 0xCEB7, 0xB058, 0xCEB8, + 0xB059, 0xCEB9, 0xB05A, 0xCEBA, 0xB061, 0xCEBB, 0xB062, 0xCEBC, 0xB063, 0xCEBD, 0xB064, 0xCEBE, 0xB065, 0xCEBF, 0xB066, 0xCEC0, + 0xB067, 0xCEC2, 0xB068, 0xCEC3, 0xB069, 0xCEC4, 0xB06A, 0xCEC5, 0xB06B, 0xCEC6, 0xB06C, 0xCEC7, 0xB06D, 0xCEC8, 0xB06E, 0xCEC9, + 0xB06F, 0xCECA, 0xB070, 0xCECB, 0xB071, 0xCECC, 0xB072, 0xCECD, 0xB073, 0xCECE, 0xB074, 0xCECF, 0xB075, 0xCED0, 0xB076, 0xCED1, + 0xB077, 0xCED2, 0xB078, 0xCED3, 0xB079, 0xCED4, 0xB07A, 0xCED5, 0xB081, 0xCED6, 0xB082, 0xCED7, 0xB083, 0xCED8, 0xB084, 0xCED9, + 0xB085, 0xCEDA, 0xB086, 0xCEDB, 0xB087, 0xCEDC, 0xB088, 0xCEDD, 0xB089, 0xCEDE, 0xB08A, 0xCEDF, 0xB08B, 0xCEE0, 0xB08C, 0xCEE1, + 0xB08D, 0xCEE2, 0xB08E, 0xCEE3, 0xB08F, 0xCEE6, 0xB090, 0xCEE7, 0xB091, 0xCEE9, 0xB092, 0xCEEA, 0xB093, 0xCEED, 0xB094, 0xCEEE, + 0xB095, 0xCEEF, 0xB096, 0xCEF0, 0xB097, 0xCEF1, 0xB098, 0xCEF2, 0xB099, 0xCEF3, 0xB09A, 0xCEF6, 0xB09B, 0xCEFA, 0xB09C, 0xCEFB, + 0xB09D, 0xCEFC, 0xB09E, 0xCEFD, 0xB09F, 0xCEFE, 0xB0A0, 0xCEFF, 0xB0A1, 0xAC00, 0xB0A2, 0xAC01, 0xB0A3, 0xAC04, 0xB0A4, 0xAC07, + 0xB0A5, 0xAC08, 0xB0A6, 0xAC09, 0xB0A7, 0xAC0A, 0xB0A8, 0xAC10, 0xB0A9, 0xAC11, 0xB0AA, 0xAC12, 0xB0AB, 0xAC13, 0xB0AC, 0xAC14, + 0xB0AD, 0xAC15, 0xB0AE, 0xAC16, 0xB0AF, 0xAC17, 0xB0B0, 0xAC19, 0xB0B1, 0xAC1A, 0xB0B2, 0xAC1B, 0xB0B3, 0xAC1C, 0xB0B4, 0xAC1D, + 0xB0B5, 0xAC20, 0xB0B6, 0xAC24, 0xB0B7, 0xAC2C, 0xB0B8, 0xAC2D, 0xB0B9, 0xAC2F, 0xB0BA, 0xAC30, 0xB0BB, 0xAC31, 0xB0BC, 0xAC38, + 0xB0BD, 0xAC39, 0xB0BE, 0xAC3C, 0xB0BF, 0xAC40, 0xB0C0, 0xAC4B, 0xB0C1, 0xAC4D, 0xB0C2, 0xAC54, 0xB0C3, 0xAC58, 0xB0C4, 0xAC5C, + 0xB0C5, 0xAC70, 0xB0C6, 0xAC71, 0xB0C7, 0xAC74, 0xB0C8, 0xAC77, 0xB0C9, 0xAC78, 0xB0CA, 0xAC7A, 0xB0CB, 0xAC80, 0xB0CC, 0xAC81, + 0xB0CD, 0xAC83, 0xB0CE, 0xAC84, 0xB0CF, 0xAC85, 0xB0D0, 0xAC86, 0xB0D1, 0xAC89, 0xB0D2, 0xAC8A, 0xB0D3, 0xAC8B, 0xB0D4, 0xAC8C, + 0xB0D5, 0xAC90, 0xB0D6, 0xAC94, 0xB0D7, 0xAC9C, 0xB0D8, 0xAC9D, 0xB0D9, 0xAC9F, 0xB0DA, 0xACA0, 0xB0DB, 0xACA1, 0xB0DC, 0xACA8, + 0xB0DD, 0xACA9, 0xB0DE, 0xACAA, 0xB0DF, 0xACAC, 0xB0E0, 0xACAF, 0xB0E1, 0xACB0, 0xB0E2, 0xACB8, 0xB0E3, 0xACB9, 0xB0E4, 0xACBB, + 0xB0E5, 0xACBC, 0xB0E6, 0xACBD, 0xB0E7, 0xACC1, 0xB0E8, 0xACC4, 0xB0E9, 0xACC8, 0xB0EA, 0xACCC, 0xB0EB, 0xACD5, 0xB0EC, 0xACD7, + 0xB0ED, 0xACE0, 0xB0EE, 0xACE1, 0xB0EF, 0xACE4, 0xB0F0, 0xACE7, 0xB0F1, 0xACE8, 0xB0F2, 0xACEA, 0xB0F3, 0xACEC, 0xB0F4, 0xACEF, + 0xB0F5, 0xACF0, 0xB0F6, 0xACF1, 0xB0F7, 0xACF3, 0xB0F8, 0xACF5, 0xB0F9, 0xACF6, 0xB0FA, 0xACFC, 0xB0FB, 0xACFD, 0xB0FC, 0xAD00, + 0xB0FD, 0xAD04, 0xB0FE, 0xAD06, 0xB141, 0xCF02, 0xB142, 0xCF03, 0xB143, 0xCF05, 0xB144, 0xCF06, 0xB145, 0xCF07, 0xB146, 0xCF09, + 0xB147, 0xCF0A, 0xB148, 0xCF0B, 0xB149, 0xCF0C, 0xB14A, 0xCF0D, 0xB14B, 0xCF0E, 0xB14C, 0xCF0F, 0xB14D, 0xCF12, 0xB14E, 0xCF14, + 0xB14F, 0xCF16, 0xB150, 0xCF17, 0xB151, 0xCF18, 0xB152, 0xCF19, 0xB153, 0xCF1A, 0xB154, 0xCF1B, 0xB155, 0xCF1D, 0xB156, 0xCF1E, + 0xB157, 0xCF1F, 0xB158, 0xCF21, 0xB159, 0xCF22, 0xB15A, 0xCF23, 0xB161, 0xCF25, 0xB162, 0xCF26, 0xB163, 0xCF27, 0xB164, 0xCF28, + 0xB165, 0xCF29, 0xB166, 0xCF2A, 0xB167, 0xCF2B, 0xB168, 0xCF2E, 0xB169, 0xCF32, 0xB16A, 0xCF33, 0xB16B, 0xCF34, 0xB16C, 0xCF35, + 0xB16D, 0xCF36, 0xB16E, 0xCF37, 0xB16F, 0xCF39, 0xB170, 0xCF3A, 0xB171, 0xCF3B, 0xB172, 0xCF3C, 0xB173, 0xCF3D, 0xB174, 0xCF3E, + 0xB175, 0xCF3F, 0xB176, 0xCF40, 0xB177, 0xCF41, 0xB178, 0xCF42, 0xB179, 0xCF43, 0xB17A, 0xCF44, 0xB181, 0xCF45, 0xB182, 0xCF46, + 0xB183, 0xCF47, 0xB184, 0xCF48, 0xB185, 0xCF49, 0xB186, 0xCF4A, 0xB187, 0xCF4B, 0xB188, 0xCF4C, 0xB189, 0xCF4D, 0xB18A, 0xCF4E, + 0xB18B, 0xCF4F, 0xB18C, 0xCF50, 0xB18D, 0xCF51, 0xB18E, 0xCF52, 0xB18F, 0xCF53, 0xB190, 0xCF56, 0xB191, 0xCF57, 0xB192, 0xCF59, + 0xB193, 0xCF5A, 0xB194, 0xCF5B, 0xB195, 0xCF5D, 0xB196, 0xCF5E, 0xB197, 0xCF5F, 0xB198, 0xCF60, 0xB199, 0xCF61, 0xB19A, 0xCF62, + 0xB19B, 0xCF63, 0xB19C, 0xCF66, 0xB19D, 0xCF68, 0xB19E, 0xCF6A, 0xB19F, 0xCF6B, 0xB1A0, 0xCF6C, 0xB1A1, 0xAD0C, 0xB1A2, 0xAD0D, + 0xB1A3, 0xAD0F, 0xB1A4, 0xAD11, 0xB1A5, 0xAD18, 0xB1A6, 0xAD1C, 0xB1A7, 0xAD20, 0xB1A8, 0xAD29, 0xB1A9, 0xAD2C, 0xB1AA, 0xAD2D, + 0xB1AB, 0xAD34, 0xB1AC, 0xAD35, 0xB1AD, 0xAD38, 0xB1AE, 0xAD3C, 0xB1AF, 0xAD44, 0xB1B0, 0xAD45, 0xB1B1, 0xAD47, 0xB1B2, 0xAD49, + 0xB1B3, 0xAD50, 0xB1B4, 0xAD54, 0xB1B5, 0xAD58, 0xB1B6, 0xAD61, 0xB1B7, 0xAD63, 0xB1B8, 0xAD6C, 0xB1B9, 0xAD6D, 0xB1BA, 0xAD70, + 0xB1BB, 0xAD73, 0xB1BC, 0xAD74, 0xB1BD, 0xAD75, 0xB1BE, 0xAD76, 0xB1BF, 0xAD7B, 0xB1C0, 0xAD7C, 0xB1C1, 0xAD7D, 0xB1C2, 0xAD7F, + 0xB1C3, 0xAD81, 0xB1C4, 0xAD82, 0xB1C5, 0xAD88, 0xB1C6, 0xAD89, 0xB1C7, 0xAD8C, 0xB1C8, 0xAD90, 0xB1C9, 0xAD9C, 0xB1CA, 0xAD9D, + 0xB1CB, 0xADA4, 0xB1CC, 0xADB7, 0xB1CD, 0xADC0, 0xB1CE, 0xADC1, 0xB1CF, 0xADC4, 0xB1D0, 0xADC8, 0xB1D1, 0xADD0, 0xB1D2, 0xADD1, + 0xB1D3, 0xADD3, 0xB1D4, 0xADDC, 0xB1D5, 0xADE0, 0xB1D6, 0xADE4, 0xB1D7, 0xADF8, 0xB1D8, 0xADF9, 0xB1D9, 0xADFC, 0xB1DA, 0xADFF, + 0xB1DB, 0xAE00, 0xB1DC, 0xAE01, 0xB1DD, 0xAE08, 0xB1DE, 0xAE09, 0xB1DF, 0xAE0B, 0xB1E0, 0xAE0D, 0xB1E1, 0xAE14, 0xB1E2, 0xAE30, + 0xB1E3, 0xAE31, 0xB1E4, 0xAE34, 0xB1E5, 0xAE37, 0xB1E6, 0xAE38, 0xB1E7, 0xAE3A, 0xB1E8, 0xAE40, 0xB1E9, 0xAE41, 0xB1EA, 0xAE43, + 0xB1EB, 0xAE45, 0xB1EC, 0xAE46, 0xB1ED, 0xAE4A, 0xB1EE, 0xAE4C, 0xB1EF, 0xAE4D, 0xB1F0, 0xAE4E, 0xB1F1, 0xAE50, 0xB1F2, 0xAE54, + 0xB1F3, 0xAE56, 0xB1F4, 0xAE5C, 0xB1F5, 0xAE5D, 0xB1F6, 0xAE5F, 0xB1F7, 0xAE60, 0xB1F8, 0xAE61, 0xB1F9, 0xAE65, 0xB1FA, 0xAE68, + 0xB1FB, 0xAE69, 0xB1FC, 0xAE6C, 0xB1FD, 0xAE70, 0xB1FE, 0xAE78, 0xB241, 0xCF6D, 0xB242, 0xCF6E, 0xB243, 0xCF6F, 0xB244, 0xCF72, + 0xB245, 0xCF73, 0xB246, 0xCF75, 0xB247, 0xCF76, 0xB248, 0xCF77, 0xB249, 0xCF79, 0xB24A, 0xCF7A, 0xB24B, 0xCF7B, 0xB24C, 0xCF7C, + 0xB24D, 0xCF7D, 0xB24E, 0xCF7E, 0xB24F, 0xCF7F, 0xB250, 0xCF81, 0xB251, 0xCF82, 0xB252, 0xCF83, 0xB253, 0xCF84, 0xB254, 0xCF86, + 0xB255, 0xCF87, 0xB256, 0xCF88, 0xB257, 0xCF89, 0xB258, 0xCF8A, 0xB259, 0xCF8B, 0xB25A, 0xCF8D, 0xB261, 0xCF8E, 0xB262, 0xCF8F, + 0xB263, 0xCF90, 0xB264, 0xCF91, 0xB265, 0xCF92, 0xB266, 0xCF93, 0xB267, 0xCF94, 0xB268, 0xCF95, 0xB269, 0xCF96, 0xB26A, 0xCF97, + 0xB26B, 0xCF98, 0xB26C, 0xCF99, 0xB26D, 0xCF9A, 0xB26E, 0xCF9B, 0xB26F, 0xCF9C, 0xB270, 0xCF9D, 0xB271, 0xCF9E, 0xB272, 0xCF9F, + 0xB273, 0xCFA0, 0xB274, 0xCFA2, 0xB275, 0xCFA3, 0xB276, 0xCFA4, 0xB277, 0xCFA5, 0xB278, 0xCFA6, 0xB279, 0xCFA7, 0xB27A, 0xCFA9, + 0xB281, 0xCFAA, 0xB282, 0xCFAB, 0xB283, 0xCFAC, 0xB284, 0xCFAD, 0xB285, 0xCFAE, 0xB286, 0xCFAF, 0xB287, 0xCFB1, 0xB288, 0xCFB2, + 0xB289, 0xCFB3, 0xB28A, 0xCFB4, 0xB28B, 0xCFB5, 0xB28C, 0xCFB6, 0xB28D, 0xCFB7, 0xB28E, 0xCFB8, 0xB28F, 0xCFB9, 0xB290, 0xCFBA, + 0xB291, 0xCFBB, 0xB292, 0xCFBC, 0xB293, 0xCFBD, 0xB294, 0xCFBE, 0xB295, 0xCFBF, 0xB296, 0xCFC0, 0xB297, 0xCFC1, 0xB298, 0xCFC2, + 0xB299, 0xCFC3, 0xB29A, 0xCFC5, 0xB29B, 0xCFC6, 0xB29C, 0xCFC7, 0xB29D, 0xCFC8, 0xB29E, 0xCFC9, 0xB29F, 0xCFCA, 0xB2A0, 0xCFCB, + 0xB2A1, 0xAE79, 0xB2A2, 0xAE7B, 0xB2A3, 0xAE7C, 0xB2A4, 0xAE7D, 0xB2A5, 0xAE84, 0xB2A6, 0xAE85, 0xB2A7, 0xAE8C, 0xB2A8, 0xAEBC, + 0xB2A9, 0xAEBD, 0xB2AA, 0xAEBE, 0xB2AB, 0xAEC0, 0xB2AC, 0xAEC4, 0xB2AD, 0xAECC, 0xB2AE, 0xAECD, 0xB2AF, 0xAECF, 0xB2B0, 0xAED0, + 0xB2B1, 0xAED1, 0xB2B2, 0xAED8, 0xB2B3, 0xAED9, 0xB2B4, 0xAEDC, 0xB2B5, 0xAEE8, 0xB2B6, 0xAEEB, 0xB2B7, 0xAEED, 0xB2B8, 0xAEF4, + 0xB2B9, 0xAEF8, 0xB2BA, 0xAEFC, 0xB2BB, 0xAF07, 0xB2BC, 0xAF08, 0xB2BD, 0xAF0D, 0xB2BE, 0xAF10, 0xB2BF, 0xAF2C, 0xB2C0, 0xAF2D, + 0xB2C1, 0xAF30, 0xB2C2, 0xAF32, 0xB2C3, 0xAF34, 0xB2C4, 0xAF3C, 0xB2C5, 0xAF3D, 0xB2C6, 0xAF3F, 0xB2C7, 0xAF41, 0xB2C8, 0xAF42, + 0xB2C9, 0xAF43, 0xB2CA, 0xAF48, 0xB2CB, 0xAF49, 0xB2CC, 0xAF50, 0xB2CD, 0xAF5C, 0xB2CE, 0xAF5D, 0xB2CF, 0xAF64, 0xB2D0, 0xAF65, + 0xB2D1, 0xAF79, 0xB2D2, 0xAF80, 0xB2D3, 0xAF84, 0xB2D4, 0xAF88, 0xB2D5, 0xAF90, 0xB2D6, 0xAF91, 0xB2D7, 0xAF95, 0xB2D8, 0xAF9C, + 0xB2D9, 0xAFB8, 0xB2DA, 0xAFB9, 0xB2DB, 0xAFBC, 0xB2DC, 0xAFC0, 0xB2DD, 0xAFC7, 0xB2DE, 0xAFC8, 0xB2DF, 0xAFC9, 0xB2E0, 0xAFCB, + 0xB2E1, 0xAFCD, 0xB2E2, 0xAFCE, 0xB2E3, 0xAFD4, 0xB2E4, 0xAFDC, 0xB2E5, 0xAFE8, 0xB2E6, 0xAFE9, 0xB2E7, 0xAFF0, 0xB2E8, 0xAFF1, + 0xB2E9, 0xAFF4, 0xB2EA, 0xAFF8, 0xB2EB, 0xB000, 0xB2EC, 0xB001, 0xB2ED, 0xB004, 0xB2EE, 0xB00C, 0xB2EF, 0xB010, 0xB2F0, 0xB014, + 0xB2F1, 0xB01C, 0xB2F2, 0xB01D, 0xB2F3, 0xB028, 0xB2F4, 0xB044, 0xB2F5, 0xB045, 0xB2F6, 0xB048, 0xB2F7, 0xB04A, 0xB2F8, 0xB04C, + 0xB2F9, 0xB04E, 0xB2FA, 0xB053, 0xB2FB, 0xB054, 0xB2FC, 0xB055, 0xB2FD, 0xB057, 0xB2FE, 0xB059, 0xB341, 0xCFCC, 0xB342, 0xCFCD, + 0xB343, 0xCFCE, 0xB344, 0xCFCF, 0xB345, 0xCFD0, 0xB346, 0xCFD1, 0xB347, 0xCFD2, 0xB348, 0xCFD3, 0xB349, 0xCFD4, 0xB34A, 0xCFD5, + 0xB34B, 0xCFD6, 0xB34C, 0xCFD7, 0xB34D, 0xCFD8, 0xB34E, 0xCFD9, 0xB34F, 0xCFDA, 0xB350, 0xCFDB, 0xB351, 0xCFDC, 0xB352, 0xCFDD, + 0xB353, 0xCFDE, 0xB354, 0xCFDF, 0xB355, 0xCFE2, 0xB356, 0xCFE3, 0xB357, 0xCFE5, 0xB358, 0xCFE6, 0xB359, 0xCFE7, 0xB35A, 0xCFE9, + 0xB361, 0xCFEA, 0xB362, 0xCFEB, 0xB363, 0xCFEC, 0xB364, 0xCFED, 0xB365, 0xCFEE, 0xB366, 0xCFEF, 0xB367, 0xCFF2, 0xB368, 0xCFF4, + 0xB369, 0xCFF6, 0xB36A, 0xCFF7, 0xB36B, 0xCFF8, 0xB36C, 0xCFF9, 0xB36D, 0xCFFA, 0xB36E, 0xCFFB, 0xB36F, 0xCFFD, 0xB370, 0xCFFE, + 0xB371, 0xCFFF, 0xB372, 0xD001, 0xB373, 0xD002, 0xB374, 0xD003, 0xB375, 0xD005, 0xB376, 0xD006, 0xB377, 0xD007, 0xB378, 0xD008, + 0xB379, 0xD009, 0xB37A, 0xD00A, 0xB381, 0xD00B, 0xB382, 0xD00C, 0xB383, 0xD00D, 0xB384, 0xD00E, 0xB385, 0xD00F, 0xB386, 0xD010, + 0xB387, 0xD012, 0xB388, 0xD013, 0xB389, 0xD014, 0xB38A, 0xD015, 0xB38B, 0xD016, 0xB38C, 0xD017, 0xB38D, 0xD019, 0xB38E, 0xD01A, + 0xB38F, 0xD01B, 0xB390, 0xD01C, 0xB391, 0xD01D, 0xB392, 0xD01E, 0xB393, 0xD01F, 0xB394, 0xD020, 0xB395, 0xD021, 0xB396, 0xD022, + 0xB397, 0xD023, 0xB398, 0xD024, 0xB399, 0xD025, 0xB39A, 0xD026, 0xB39B, 0xD027, 0xB39C, 0xD028, 0xB39D, 0xD029, 0xB39E, 0xD02A, + 0xB39F, 0xD02B, 0xB3A0, 0xD02C, 0xB3A1, 0xB05D, 0xB3A2, 0xB07C, 0xB3A3, 0xB07D, 0xB3A4, 0xB080, 0xB3A5, 0xB084, 0xB3A6, 0xB08C, + 0xB3A7, 0xB08D, 0xB3A8, 0xB08F, 0xB3A9, 0xB091, 0xB3AA, 0xB098, 0xB3AB, 0xB099, 0xB3AC, 0xB09A, 0xB3AD, 0xB09C, 0xB3AE, 0xB09F, + 0xB3AF, 0xB0A0, 0xB3B0, 0xB0A1, 0xB3B1, 0xB0A2, 0xB3B2, 0xB0A8, 0xB3B3, 0xB0A9, 0xB3B4, 0xB0AB, 0xB3B5, 0xB0AC, 0xB3B6, 0xB0AD, + 0xB3B7, 0xB0AE, 0xB3B8, 0xB0AF, 0xB3B9, 0xB0B1, 0xB3BA, 0xB0B3, 0xB3BB, 0xB0B4, 0xB3BC, 0xB0B5, 0xB3BD, 0xB0B8, 0xB3BE, 0xB0BC, + 0xB3BF, 0xB0C4, 0xB3C0, 0xB0C5, 0xB3C1, 0xB0C7, 0xB3C2, 0xB0C8, 0xB3C3, 0xB0C9, 0xB3C4, 0xB0D0, 0xB3C5, 0xB0D1, 0xB3C6, 0xB0D4, + 0xB3C7, 0xB0D8, 0xB3C8, 0xB0E0, 0xB3C9, 0xB0E5, 0xB3CA, 0xB108, 0xB3CB, 0xB109, 0xB3CC, 0xB10B, 0xB3CD, 0xB10C, 0xB3CE, 0xB110, + 0xB3CF, 0xB112, 0xB3D0, 0xB113, 0xB3D1, 0xB118, 0xB3D2, 0xB119, 0xB3D3, 0xB11B, 0xB3D4, 0xB11C, 0xB3D5, 0xB11D, 0xB3D6, 0xB123, + 0xB3D7, 0xB124, 0xB3D8, 0xB125, 0xB3D9, 0xB128, 0xB3DA, 0xB12C, 0xB3DB, 0xB134, 0xB3DC, 0xB135, 0xB3DD, 0xB137, 0xB3DE, 0xB138, + 0xB3DF, 0xB139, 0xB3E0, 0xB140, 0xB3E1, 0xB141, 0xB3E2, 0xB144, 0xB3E3, 0xB148, 0xB3E4, 0xB150, 0xB3E5, 0xB151, 0xB3E6, 0xB154, + 0xB3E7, 0xB155, 0xB3E8, 0xB158, 0xB3E9, 0xB15C, 0xB3EA, 0xB160, 0xB3EB, 0xB178, 0xB3EC, 0xB179, 0xB3ED, 0xB17C, 0xB3EE, 0xB180, + 0xB3EF, 0xB182, 0xB3F0, 0xB188, 0xB3F1, 0xB189, 0xB3F2, 0xB18B, 0xB3F3, 0xB18D, 0xB3F4, 0xB192, 0xB3F5, 0xB193, 0xB3F6, 0xB194, + 0xB3F7, 0xB198, 0xB3F8, 0xB19C, 0xB3F9, 0xB1A8, 0xB3FA, 0xB1CC, 0xB3FB, 0xB1D0, 0xB3FC, 0xB1D4, 0xB3FD, 0xB1DC, 0xB3FE, 0xB1DD, + 0xB441, 0xD02E, 0xB442, 0xD02F, 0xB443, 0xD030, 0xB444, 0xD031, 0xB445, 0xD032, 0xB446, 0xD033, 0xB447, 0xD036, 0xB448, 0xD037, + 0xB449, 0xD039, 0xB44A, 0xD03A, 0xB44B, 0xD03B, 0xB44C, 0xD03D, 0xB44D, 0xD03E, 0xB44E, 0xD03F, 0xB44F, 0xD040, 0xB450, 0xD041, + 0xB451, 0xD042, 0xB452, 0xD043, 0xB453, 0xD046, 0xB454, 0xD048, 0xB455, 0xD04A, 0xB456, 0xD04B, 0xB457, 0xD04C, 0xB458, 0xD04D, + 0xB459, 0xD04E, 0xB45A, 0xD04F, 0xB461, 0xD051, 0xB462, 0xD052, 0xB463, 0xD053, 0xB464, 0xD055, 0xB465, 0xD056, 0xB466, 0xD057, + 0xB467, 0xD059, 0xB468, 0xD05A, 0xB469, 0xD05B, 0xB46A, 0xD05C, 0xB46B, 0xD05D, 0xB46C, 0xD05E, 0xB46D, 0xD05F, 0xB46E, 0xD061, + 0xB46F, 0xD062, 0xB470, 0xD063, 0xB471, 0xD064, 0xB472, 0xD065, 0xB473, 0xD066, 0xB474, 0xD067, 0xB475, 0xD068, 0xB476, 0xD069, + 0xB477, 0xD06A, 0xB478, 0xD06B, 0xB479, 0xD06E, 0xB47A, 0xD06F, 0xB481, 0xD071, 0xB482, 0xD072, 0xB483, 0xD073, 0xB484, 0xD075, + 0xB485, 0xD076, 0xB486, 0xD077, 0xB487, 0xD078, 0xB488, 0xD079, 0xB489, 0xD07A, 0xB48A, 0xD07B, 0xB48B, 0xD07E, 0xB48C, 0xD07F, + 0xB48D, 0xD080, 0xB48E, 0xD082, 0xB48F, 0xD083, 0xB490, 0xD084, 0xB491, 0xD085, 0xB492, 0xD086, 0xB493, 0xD087, 0xB494, 0xD088, + 0xB495, 0xD089, 0xB496, 0xD08A, 0xB497, 0xD08B, 0xB498, 0xD08C, 0xB499, 0xD08D, 0xB49A, 0xD08E, 0xB49B, 0xD08F, 0xB49C, 0xD090, + 0xB49D, 0xD091, 0xB49E, 0xD092, 0xB49F, 0xD093, 0xB4A0, 0xD094, 0xB4A1, 0xB1DF, 0xB4A2, 0xB1E8, 0xB4A3, 0xB1E9, 0xB4A4, 0xB1EC, + 0xB4A5, 0xB1F0, 0xB4A6, 0xB1F9, 0xB4A7, 0xB1FB, 0xB4A8, 0xB1FD, 0xB4A9, 0xB204, 0xB4AA, 0xB205, 0xB4AB, 0xB208, 0xB4AC, 0xB20B, + 0xB4AD, 0xB20C, 0xB4AE, 0xB214, 0xB4AF, 0xB215, 0xB4B0, 0xB217, 0xB4B1, 0xB219, 0xB4B2, 0xB220, 0xB4B3, 0xB234, 0xB4B4, 0xB23C, + 0xB4B5, 0xB258, 0xB4B6, 0xB25C, 0xB4B7, 0xB260, 0xB4B8, 0xB268, 0xB4B9, 0xB269, 0xB4BA, 0xB274, 0xB4BB, 0xB275, 0xB4BC, 0xB27C, + 0xB4BD, 0xB284, 0xB4BE, 0xB285, 0xB4BF, 0xB289, 0xB4C0, 0xB290, 0xB4C1, 0xB291, 0xB4C2, 0xB294, 0xB4C3, 0xB298, 0xB4C4, 0xB299, + 0xB4C5, 0xB29A, 0xB4C6, 0xB2A0, 0xB4C7, 0xB2A1, 0xB4C8, 0xB2A3, 0xB4C9, 0xB2A5, 0xB4CA, 0xB2A6, 0xB4CB, 0xB2AA, 0xB4CC, 0xB2AC, + 0xB4CD, 0xB2B0, 0xB4CE, 0xB2B4, 0xB4CF, 0xB2C8, 0xB4D0, 0xB2C9, 0xB4D1, 0xB2CC, 0xB4D2, 0xB2D0, 0xB4D3, 0xB2D2, 0xB4D4, 0xB2D8, + 0xB4D5, 0xB2D9, 0xB4D6, 0xB2DB, 0xB4D7, 0xB2DD, 0xB4D8, 0xB2E2, 0xB4D9, 0xB2E4, 0xB4DA, 0xB2E5, 0xB4DB, 0xB2E6, 0xB4DC, 0xB2E8, + 0xB4DD, 0xB2EB, 0xB4DE, 0xB2EC, 0xB4DF, 0xB2ED, 0xB4E0, 0xB2EE, 0xB4E1, 0xB2EF, 0xB4E2, 0xB2F3, 0xB4E3, 0xB2F4, 0xB4E4, 0xB2F5, + 0xB4E5, 0xB2F7, 0xB4E6, 0xB2F8, 0xB4E7, 0xB2F9, 0xB4E8, 0xB2FA, 0xB4E9, 0xB2FB, 0xB4EA, 0xB2FF, 0xB4EB, 0xB300, 0xB4EC, 0xB301, + 0xB4ED, 0xB304, 0xB4EE, 0xB308, 0xB4EF, 0xB310, 0xB4F0, 0xB311, 0xB4F1, 0xB313, 0xB4F2, 0xB314, 0xB4F3, 0xB315, 0xB4F4, 0xB31C, + 0xB4F5, 0xB354, 0xB4F6, 0xB355, 0xB4F7, 0xB356, 0xB4F8, 0xB358, 0xB4F9, 0xB35B, 0xB4FA, 0xB35C, 0xB4FB, 0xB35E, 0xB4FC, 0xB35F, + 0xB4FD, 0xB364, 0xB4FE, 0xB365, 0xB541, 0xD095, 0xB542, 0xD096, 0xB543, 0xD097, 0xB544, 0xD098, 0xB545, 0xD099, 0xB546, 0xD09A, + 0xB547, 0xD09B, 0xB548, 0xD09C, 0xB549, 0xD09D, 0xB54A, 0xD09E, 0xB54B, 0xD09F, 0xB54C, 0xD0A0, 0xB54D, 0xD0A1, 0xB54E, 0xD0A2, + 0xB54F, 0xD0A3, 0xB550, 0xD0A6, 0xB551, 0xD0A7, 0xB552, 0xD0A9, 0xB553, 0xD0AA, 0xB554, 0xD0AB, 0xB555, 0xD0AD, 0xB556, 0xD0AE, + 0xB557, 0xD0AF, 0xB558, 0xD0B0, 0xB559, 0xD0B1, 0xB55A, 0xD0B2, 0xB561, 0xD0B3, 0xB562, 0xD0B6, 0xB563, 0xD0B8, 0xB564, 0xD0BA, + 0xB565, 0xD0BB, 0xB566, 0xD0BC, 0xB567, 0xD0BD, 0xB568, 0xD0BE, 0xB569, 0xD0BF, 0xB56A, 0xD0C2, 0xB56B, 0xD0C3, 0xB56C, 0xD0C5, + 0xB56D, 0xD0C6, 0xB56E, 0xD0C7, 0xB56F, 0xD0CA, 0xB570, 0xD0CB, 0xB571, 0xD0CC, 0xB572, 0xD0CD, 0xB573, 0xD0CE, 0xB574, 0xD0CF, + 0xB575, 0xD0D2, 0xB576, 0xD0D6, 0xB577, 0xD0D7, 0xB578, 0xD0D8, 0xB579, 0xD0D9, 0xB57A, 0xD0DA, 0xB581, 0xD0DB, 0xB582, 0xD0DE, + 0xB583, 0xD0DF, 0xB584, 0xD0E1, 0xB585, 0xD0E2, 0xB586, 0xD0E3, 0xB587, 0xD0E5, 0xB588, 0xD0E6, 0xB589, 0xD0E7, 0xB58A, 0xD0E8, + 0xB58B, 0xD0E9, 0xB58C, 0xD0EA, 0xB58D, 0xD0EB, 0xB58E, 0xD0EE, 0xB58F, 0xD0F2, 0xB590, 0xD0F3, 0xB591, 0xD0F4, 0xB592, 0xD0F5, + 0xB593, 0xD0F6, 0xB594, 0xD0F7, 0xB595, 0xD0F9, 0xB596, 0xD0FA, 0xB597, 0xD0FB, 0xB598, 0xD0FC, 0xB599, 0xD0FD, 0xB59A, 0xD0FE, + 0xB59B, 0xD0FF, 0xB59C, 0xD100, 0xB59D, 0xD101, 0xB59E, 0xD102, 0xB59F, 0xD103, 0xB5A0, 0xD104, 0xB5A1, 0xB367, 0xB5A2, 0xB369, + 0xB5A3, 0xB36B, 0xB5A4, 0xB36E, 0xB5A5, 0xB370, 0xB5A6, 0xB371, 0xB5A7, 0xB374, 0xB5A8, 0xB378, 0xB5A9, 0xB380, 0xB5AA, 0xB381, + 0xB5AB, 0xB383, 0xB5AC, 0xB384, 0xB5AD, 0xB385, 0xB5AE, 0xB38C, 0xB5AF, 0xB390, 0xB5B0, 0xB394, 0xB5B1, 0xB3A0, 0xB5B2, 0xB3A1, + 0xB5B3, 0xB3A8, 0xB5B4, 0xB3AC, 0xB5B5, 0xB3C4, 0xB5B6, 0xB3C5, 0xB5B7, 0xB3C8, 0xB5B8, 0xB3CB, 0xB5B9, 0xB3CC, 0xB5BA, 0xB3CE, + 0xB5BB, 0xB3D0, 0xB5BC, 0xB3D4, 0xB5BD, 0xB3D5, 0xB5BE, 0xB3D7, 0xB5BF, 0xB3D9, 0xB5C0, 0xB3DB, 0xB5C1, 0xB3DD, 0xB5C2, 0xB3E0, + 0xB5C3, 0xB3E4, 0xB5C4, 0xB3E8, 0xB5C5, 0xB3FC, 0xB5C6, 0xB410, 0xB5C7, 0xB418, 0xB5C8, 0xB41C, 0xB5C9, 0xB420, 0xB5CA, 0xB428, + 0xB5CB, 0xB429, 0xB5CC, 0xB42B, 0xB5CD, 0xB434, 0xB5CE, 0xB450, 0xB5CF, 0xB451, 0xB5D0, 0xB454, 0xB5D1, 0xB458, 0xB5D2, 0xB460, + 0xB5D3, 0xB461, 0xB5D4, 0xB463, 0xB5D5, 0xB465, 0xB5D6, 0xB46C, 0xB5D7, 0xB480, 0xB5D8, 0xB488, 0xB5D9, 0xB49D, 0xB5DA, 0xB4A4, + 0xB5DB, 0xB4A8, 0xB5DC, 0xB4AC, 0xB5DD, 0xB4B5, 0xB5DE, 0xB4B7, 0xB5DF, 0xB4B9, 0xB5E0, 0xB4C0, 0xB5E1, 0xB4C4, 0xB5E2, 0xB4C8, + 0xB5E3, 0xB4D0, 0xB5E4, 0xB4D5, 0xB5E5, 0xB4DC, 0xB5E6, 0xB4DD, 0xB5E7, 0xB4E0, 0xB5E8, 0xB4E3, 0xB5E9, 0xB4E4, 0xB5EA, 0xB4E6, + 0xB5EB, 0xB4EC, 0xB5EC, 0xB4ED, 0xB5ED, 0xB4EF, 0xB5EE, 0xB4F1, 0xB5EF, 0xB4F8, 0xB5F0, 0xB514, 0xB5F1, 0xB515, 0xB5F2, 0xB518, + 0xB5F3, 0xB51B, 0xB5F4, 0xB51C, 0xB5F5, 0xB524, 0xB5F6, 0xB525, 0xB5F7, 0xB527, 0xB5F8, 0xB528, 0xB5F9, 0xB529, 0xB5FA, 0xB52A, + 0xB5FB, 0xB530, 0xB5FC, 0xB531, 0xB5FD, 0xB534, 0xB5FE, 0xB538, 0xB641, 0xD105, 0xB642, 0xD106, 0xB643, 0xD107, 0xB644, 0xD108, + 0xB645, 0xD109, 0xB646, 0xD10A, 0xB647, 0xD10B, 0xB648, 0xD10C, 0xB649, 0xD10E, 0xB64A, 0xD10F, 0xB64B, 0xD110, 0xB64C, 0xD111, + 0xB64D, 0xD112, 0xB64E, 0xD113, 0xB64F, 0xD114, 0xB650, 0xD115, 0xB651, 0xD116, 0xB652, 0xD117, 0xB653, 0xD118, 0xB654, 0xD119, + 0xB655, 0xD11A, 0xB656, 0xD11B, 0xB657, 0xD11C, 0xB658, 0xD11D, 0xB659, 0xD11E, 0xB65A, 0xD11F, 0xB661, 0xD120, 0xB662, 0xD121, + 0xB663, 0xD122, 0xB664, 0xD123, 0xB665, 0xD124, 0xB666, 0xD125, 0xB667, 0xD126, 0xB668, 0xD127, 0xB669, 0xD128, 0xB66A, 0xD129, + 0xB66B, 0xD12A, 0xB66C, 0xD12B, 0xB66D, 0xD12C, 0xB66E, 0xD12D, 0xB66F, 0xD12E, 0xB670, 0xD12F, 0xB671, 0xD132, 0xB672, 0xD133, + 0xB673, 0xD135, 0xB674, 0xD136, 0xB675, 0xD137, 0xB676, 0xD139, 0xB677, 0xD13B, 0xB678, 0xD13C, 0xB679, 0xD13D, 0xB67A, 0xD13E, + 0xB681, 0xD13F, 0xB682, 0xD142, 0xB683, 0xD146, 0xB684, 0xD147, 0xB685, 0xD148, 0xB686, 0xD149, 0xB687, 0xD14A, 0xB688, 0xD14B, + 0xB689, 0xD14E, 0xB68A, 0xD14F, 0xB68B, 0xD151, 0xB68C, 0xD152, 0xB68D, 0xD153, 0xB68E, 0xD155, 0xB68F, 0xD156, 0xB690, 0xD157, + 0xB691, 0xD158, 0xB692, 0xD159, 0xB693, 0xD15A, 0xB694, 0xD15B, 0xB695, 0xD15E, 0xB696, 0xD160, 0xB697, 0xD162, 0xB698, 0xD163, + 0xB699, 0xD164, 0xB69A, 0xD165, 0xB69B, 0xD166, 0xB69C, 0xD167, 0xB69D, 0xD169, 0xB69E, 0xD16A, 0xB69F, 0xD16B, 0xB6A0, 0xD16D, + 0xB6A1, 0xB540, 0xB6A2, 0xB541, 0xB6A3, 0xB543, 0xB6A4, 0xB544, 0xB6A5, 0xB545, 0xB6A6, 0xB54B, 0xB6A7, 0xB54C, 0xB6A8, 0xB54D, + 0xB6A9, 0xB550, 0xB6AA, 0xB554, 0xB6AB, 0xB55C, 0xB6AC, 0xB55D, 0xB6AD, 0xB55F, 0xB6AE, 0xB560, 0xB6AF, 0xB561, 0xB6B0, 0xB5A0, + 0xB6B1, 0xB5A1, 0xB6B2, 0xB5A4, 0xB6B3, 0xB5A8, 0xB6B4, 0xB5AA, 0xB6B5, 0xB5AB, 0xB6B6, 0xB5B0, 0xB6B7, 0xB5B1, 0xB6B8, 0xB5B3, + 0xB6B9, 0xB5B4, 0xB6BA, 0xB5B5, 0xB6BB, 0xB5BB, 0xB6BC, 0xB5BC, 0xB6BD, 0xB5BD, 0xB6BE, 0xB5C0, 0xB6BF, 0xB5C4, 0xB6C0, 0xB5CC, + 0xB6C1, 0xB5CD, 0xB6C2, 0xB5CF, 0xB6C3, 0xB5D0, 0xB6C4, 0xB5D1, 0xB6C5, 0xB5D8, 0xB6C6, 0xB5EC, 0xB6C7, 0xB610, 0xB6C8, 0xB611, + 0xB6C9, 0xB614, 0xB6CA, 0xB618, 0xB6CB, 0xB625, 0xB6CC, 0xB62C, 0xB6CD, 0xB634, 0xB6CE, 0xB648, 0xB6CF, 0xB664, 0xB6D0, 0xB668, + 0xB6D1, 0xB69C, 0xB6D2, 0xB69D, 0xB6D3, 0xB6A0, 0xB6D4, 0xB6A4, 0xB6D5, 0xB6AB, 0xB6D6, 0xB6AC, 0xB6D7, 0xB6B1, 0xB6D8, 0xB6D4, + 0xB6D9, 0xB6F0, 0xB6DA, 0xB6F4, 0xB6DB, 0xB6F8, 0xB6DC, 0xB700, 0xB6DD, 0xB701, 0xB6DE, 0xB705, 0xB6DF, 0xB728, 0xB6E0, 0xB729, + 0xB6E1, 0xB72C, 0xB6E2, 0xB72F, 0xB6E3, 0xB730, 0xB6E4, 0xB738, 0xB6E5, 0xB739, 0xB6E6, 0xB73B, 0xB6E7, 0xB744, 0xB6E8, 0xB748, + 0xB6E9, 0xB74C, 0xB6EA, 0xB754, 0xB6EB, 0xB755, 0xB6EC, 0xB760, 0xB6ED, 0xB764, 0xB6EE, 0xB768, 0xB6EF, 0xB770, 0xB6F0, 0xB771, + 0xB6F1, 0xB773, 0xB6F2, 0xB775, 0xB6F3, 0xB77C, 0xB6F4, 0xB77D, 0xB6F5, 0xB780, 0xB6F6, 0xB784, 0xB6F7, 0xB78C, 0xB6F8, 0xB78D, + 0xB6F9, 0xB78F, 0xB6FA, 0xB790, 0xB6FB, 0xB791, 0xB6FC, 0xB792, 0xB6FD, 0xB796, 0xB6FE, 0xB797, 0xB741, 0xD16E, 0xB742, 0xD16F, + 0xB743, 0xD170, 0xB744, 0xD171, 0xB745, 0xD172, 0xB746, 0xD173, 0xB747, 0xD174, 0xB748, 0xD175, 0xB749, 0xD176, 0xB74A, 0xD177, + 0xB74B, 0xD178, 0xB74C, 0xD179, 0xB74D, 0xD17A, 0xB74E, 0xD17B, 0xB74F, 0xD17D, 0xB750, 0xD17E, 0xB751, 0xD17F, 0xB752, 0xD180, + 0xB753, 0xD181, 0xB754, 0xD182, 0xB755, 0xD183, 0xB756, 0xD185, 0xB757, 0xD186, 0xB758, 0xD187, 0xB759, 0xD189, 0xB75A, 0xD18A, + 0xB761, 0xD18B, 0xB762, 0xD18C, 0xB763, 0xD18D, 0xB764, 0xD18E, 0xB765, 0xD18F, 0xB766, 0xD190, 0xB767, 0xD191, 0xB768, 0xD192, + 0xB769, 0xD193, 0xB76A, 0xD194, 0xB76B, 0xD195, 0xB76C, 0xD196, 0xB76D, 0xD197, 0xB76E, 0xD198, 0xB76F, 0xD199, 0xB770, 0xD19A, + 0xB771, 0xD19B, 0xB772, 0xD19C, 0xB773, 0xD19D, 0xB774, 0xD19E, 0xB775, 0xD19F, 0xB776, 0xD1A2, 0xB777, 0xD1A3, 0xB778, 0xD1A5, + 0xB779, 0xD1A6, 0xB77A, 0xD1A7, 0xB781, 0xD1A9, 0xB782, 0xD1AA, 0xB783, 0xD1AB, 0xB784, 0xD1AC, 0xB785, 0xD1AD, 0xB786, 0xD1AE, + 0xB787, 0xD1AF, 0xB788, 0xD1B2, 0xB789, 0xD1B4, 0xB78A, 0xD1B6, 0xB78B, 0xD1B7, 0xB78C, 0xD1B8, 0xB78D, 0xD1B9, 0xB78E, 0xD1BB, + 0xB78F, 0xD1BD, 0xB790, 0xD1BE, 0xB791, 0xD1BF, 0xB792, 0xD1C1, 0xB793, 0xD1C2, 0xB794, 0xD1C3, 0xB795, 0xD1C4, 0xB796, 0xD1C5, + 0xB797, 0xD1C6, 0xB798, 0xD1C7, 0xB799, 0xD1C8, 0xB79A, 0xD1C9, 0xB79B, 0xD1CA, 0xB79C, 0xD1CB, 0xB79D, 0xD1CC, 0xB79E, 0xD1CD, + 0xB79F, 0xD1CE, 0xB7A0, 0xD1CF, 0xB7A1, 0xB798, 0xB7A2, 0xB799, 0xB7A3, 0xB79C, 0xB7A4, 0xB7A0, 0xB7A5, 0xB7A8, 0xB7A6, 0xB7A9, + 0xB7A7, 0xB7AB, 0xB7A8, 0xB7AC, 0xB7A9, 0xB7AD, 0xB7AA, 0xB7B4, 0xB7AB, 0xB7B5, 0xB7AC, 0xB7B8, 0xB7AD, 0xB7C7, 0xB7AE, 0xB7C9, + 0xB7AF, 0xB7EC, 0xB7B0, 0xB7ED, 0xB7B1, 0xB7F0, 0xB7B2, 0xB7F4, 0xB7B3, 0xB7FC, 0xB7B4, 0xB7FD, 0xB7B5, 0xB7FF, 0xB7B6, 0xB800, + 0xB7B7, 0xB801, 0xB7B8, 0xB807, 0xB7B9, 0xB808, 0xB7BA, 0xB809, 0xB7BB, 0xB80C, 0xB7BC, 0xB810, 0xB7BD, 0xB818, 0xB7BE, 0xB819, + 0xB7BF, 0xB81B, 0xB7C0, 0xB81D, 0xB7C1, 0xB824, 0xB7C2, 0xB825, 0xB7C3, 0xB828, 0xB7C4, 0xB82C, 0xB7C5, 0xB834, 0xB7C6, 0xB835, + 0xB7C7, 0xB837, 0xB7C8, 0xB838, 0xB7C9, 0xB839, 0xB7CA, 0xB840, 0xB7CB, 0xB844, 0xB7CC, 0xB851, 0xB7CD, 0xB853, 0xB7CE, 0xB85C, + 0xB7CF, 0xB85D, 0xB7D0, 0xB860, 0xB7D1, 0xB864, 0xB7D2, 0xB86C, 0xB7D3, 0xB86D, 0xB7D4, 0xB86F, 0xB7D5, 0xB871, 0xB7D6, 0xB878, + 0xB7D7, 0xB87C, 0xB7D8, 0xB88D, 0xB7D9, 0xB8A8, 0xB7DA, 0xB8B0, 0xB7DB, 0xB8B4, 0xB7DC, 0xB8B8, 0xB7DD, 0xB8C0, 0xB7DE, 0xB8C1, + 0xB7DF, 0xB8C3, 0xB7E0, 0xB8C5, 0xB7E1, 0xB8CC, 0xB7E2, 0xB8D0, 0xB7E3, 0xB8D4, 0xB7E4, 0xB8DD, 0xB7E5, 0xB8DF, 0xB7E6, 0xB8E1, + 0xB7E7, 0xB8E8, 0xB7E8, 0xB8E9, 0xB7E9, 0xB8EC, 0xB7EA, 0xB8F0, 0xB7EB, 0xB8F8, 0xB7EC, 0xB8F9, 0xB7ED, 0xB8FB, 0xB7EE, 0xB8FD, + 0xB7EF, 0xB904, 0xB7F0, 0xB918, 0xB7F1, 0xB920, 0xB7F2, 0xB93C, 0xB7F3, 0xB93D, 0xB7F4, 0xB940, 0xB7F5, 0xB944, 0xB7F6, 0xB94C, + 0xB7F7, 0xB94F, 0xB7F8, 0xB951, 0xB7F9, 0xB958, 0xB7FA, 0xB959, 0xB7FB, 0xB95C, 0xB7FC, 0xB960, 0xB7FD, 0xB968, 0xB7FE, 0xB969, + 0xB841, 0xD1D0, 0xB842, 0xD1D1, 0xB843, 0xD1D2, 0xB844, 0xD1D3, 0xB845, 0xD1D4, 0xB846, 0xD1D5, 0xB847, 0xD1D6, 0xB848, 0xD1D7, + 0xB849, 0xD1D9, 0xB84A, 0xD1DA, 0xB84B, 0xD1DB, 0xB84C, 0xD1DC, 0xB84D, 0xD1DD, 0xB84E, 0xD1DE, 0xB84F, 0xD1DF, 0xB850, 0xD1E0, + 0xB851, 0xD1E1, 0xB852, 0xD1E2, 0xB853, 0xD1E3, 0xB854, 0xD1E4, 0xB855, 0xD1E5, 0xB856, 0xD1E6, 0xB857, 0xD1E7, 0xB858, 0xD1E8, + 0xB859, 0xD1E9, 0xB85A, 0xD1EA, 0xB861, 0xD1EB, 0xB862, 0xD1EC, 0xB863, 0xD1ED, 0xB864, 0xD1EE, 0xB865, 0xD1EF, 0xB866, 0xD1F0, + 0xB867, 0xD1F1, 0xB868, 0xD1F2, 0xB869, 0xD1F3, 0xB86A, 0xD1F5, 0xB86B, 0xD1F6, 0xB86C, 0xD1F7, 0xB86D, 0xD1F9, 0xB86E, 0xD1FA, + 0xB86F, 0xD1FB, 0xB870, 0xD1FC, 0xB871, 0xD1FD, 0xB872, 0xD1FE, 0xB873, 0xD1FF, 0xB874, 0xD200, 0xB875, 0xD201, 0xB876, 0xD202, + 0xB877, 0xD203, 0xB878, 0xD204, 0xB879, 0xD205, 0xB87A, 0xD206, 0xB881, 0xD208, 0xB882, 0xD20A, 0xB883, 0xD20B, 0xB884, 0xD20C, + 0xB885, 0xD20D, 0xB886, 0xD20E, 0xB887, 0xD20F, 0xB888, 0xD211, 0xB889, 0xD212, 0xB88A, 0xD213, 0xB88B, 0xD214, 0xB88C, 0xD215, + 0xB88D, 0xD216, 0xB88E, 0xD217, 0xB88F, 0xD218, 0xB890, 0xD219, 0xB891, 0xD21A, 0xB892, 0xD21B, 0xB893, 0xD21C, 0xB894, 0xD21D, + 0xB895, 0xD21E, 0xB896, 0xD21F, 0xB897, 0xD220, 0xB898, 0xD221, 0xB899, 0xD222, 0xB89A, 0xD223, 0xB89B, 0xD224, 0xB89C, 0xD225, + 0xB89D, 0xD226, 0xB89E, 0xD227, 0xB89F, 0xD228, 0xB8A0, 0xD229, 0xB8A1, 0xB96B, 0xB8A2, 0xB96D, 0xB8A3, 0xB974, 0xB8A4, 0xB975, + 0xB8A5, 0xB978, 0xB8A6, 0xB97C, 0xB8A7, 0xB984, 0xB8A8, 0xB985, 0xB8A9, 0xB987, 0xB8AA, 0xB989, 0xB8AB, 0xB98A, 0xB8AC, 0xB98D, + 0xB8AD, 0xB98E, 0xB8AE, 0xB9AC, 0xB8AF, 0xB9AD, 0xB8B0, 0xB9B0, 0xB8B1, 0xB9B4, 0xB8B2, 0xB9BC, 0xB8B3, 0xB9BD, 0xB8B4, 0xB9BF, + 0xB8B5, 0xB9C1, 0xB8B6, 0xB9C8, 0xB8B7, 0xB9C9, 0xB8B8, 0xB9CC, 0xB8B9, 0xB9CE, 0xB8BA, 0xB9CF, 0xB8BB, 0xB9D0, 0xB8BC, 0xB9D1, + 0xB8BD, 0xB9D2, 0xB8BE, 0xB9D8, 0xB8BF, 0xB9D9, 0xB8C0, 0xB9DB, 0xB8C1, 0xB9DD, 0xB8C2, 0xB9DE, 0xB8C3, 0xB9E1, 0xB8C4, 0xB9E3, + 0xB8C5, 0xB9E4, 0xB8C6, 0xB9E5, 0xB8C7, 0xB9E8, 0xB8C8, 0xB9EC, 0xB8C9, 0xB9F4, 0xB8CA, 0xB9F5, 0xB8CB, 0xB9F7, 0xB8CC, 0xB9F8, + 0xB8CD, 0xB9F9, 0xB8CE, 0xB9FA, 0xB8CF, 0xBA00, 0xB8D0, 0xBA01, 0xB8D1, 0xBA08, 0xB8D2, 0xBA15, 0xB8D3, 0xBA38, 0xB8D4, 0xBA39, + 0xB8D5, 0xBA3C, 0xB8D6, 0xBA40, 0xB8D7, 0xBA42, 0xB8D8, 0xBA48, 0xB8D9, 0xBA49, 0xB8DA, 0xBA4B, 0xB8DB, 0xBA4D, 0xB8DC, 0xBA4E, + 0xB8DD, 0xBA53, 0xB8DE, 0xBA54, 0xB8DF, 0xBA55, 0xB8E0, 0xBA58, 0xB8E1, 0xBA5C, 0xB8E2, 0xBA64, 0xB8E3, 0xBA65, 0xB8E4, 0xBA67, + 0xB8E5, 0xBA68, 0xB8E6, 0xBA69, 0xB8E7, 0xBA70, 0xB8E8, 0xBA71, 0xB8E9, 0xBA74, 0xB8EA, 0xBA78, 0xB8EB, 0xBA83, 0xB8EC, 0xBA84, + 0xB8ED, 0xBA85, 0xB8EE, 0xBA87, 0xB8EF, 0xBA8C, 0xB8F0, 0xBAA8, 0xB8F1, 0xBAA9, 0xB8F2, 0xBAAB, 0xB8F3, 0xBAAC, 0xB8F4, 0xBAB0, + 0xB8F5, 0xBAB2, 0xB8F6, 0xBAB8, 0xB8F7, 0xBAB9, 0xB8F8, 0xBABB, 0xB8F9, 0xBABD, 0xB8FA, 0xBAC4, 0xB8FB, 0xBAC8, 0xB8FC, 0xBAD8, + 0xB8FD, 0xBAD9, 0xB8FE, 0xBAFC, 0xB941, 0xD22A, 0xB942, 0xD22B, 0xB943, 0xD22E, 0xB944, 0xD22F, 0xB945, 0xD231, 0xB946, 0xD232, + 0xB947, 0xD233, 0xB948, 0xD235, 0xB949, 0xD236, 0xB94A, 0xD237, 0xB94B, 0xD238, 0xB94C, 0xD239, 0xB94D, 0xD23A, 0xB94E, 0xD23B, + 0xB94F, 0xD23E, 0xB950, 0xD240, 0xB951, 0xD242, 0xB952, 0xD243, 0xB953, 0xD244, 0xB954, 0xD245, 0xB955, 0xD246, 0xB956, 0xD247, + 0xB957, 0xD249, 0xB958, 0xD24A, 0xB959, 0xD24B, 0xB95A, 0xD24C, 0xB961, 0xD24D, 0xB962, 0xD24E, 0xB963, 0xD24F, 0xB964, 0xD250, + 0xB965, 0xD251, 0xB966, 0xD252, 0xB967, 0xD253, 0xB968, 0xD254, 0xB969, 0xD255, 0xB96A, 0xD256, 0xB96B, 0xD257, 0xB96C, 0xD258, + 0xB96D, 0xD259, 0xB96E, 0xD25A, 0xB96F, 0xD25B, 0xB970, 0xD25D, 0xB971, 0xD25E, 0xB972, 0xD25F, 0xB973, 0xD260, 0xB974, 0xD261, + 0xB975, 0xD262, 0xB976, 0xD263, 0xB977, 0xD265, 0xB978, 0xD266, 0xB979, 0xD267, 0xB97A, 0xD268, 0xB981, 0xD269, 0xB982, 0xD26A, + 0xB983, 0xD26B, 0xB984, 0xD26C, 0xB985, 0xD26D, 0xB986, 0xD26E, 0xB987, 0xD26F, 0xB988, 0xD270, 0xB989, 0xD271, 0xB98A, 0xD272, + 0xB98B, 0xD273, 0xB98C, 0xD274, 0xB98D, 0xD275, 0xB98E, 0xD276, 0xB98F, 0xD277, 0xB990, 0xD278, 0xB991, 0xD279, 0xB992, 0xD27A, + 0xB993, 0xD27B, 0xB994, 0xD27C, 0xB995, 0xD27D, 0xB996, 0xD27E, 0xB997, 0xD27F, 0xB998, 0xD282, 0xB999, 0xD283, 0xB99A, 0xD285, + 0xB99B, 0xD286, 0xB99C, 0xD287, 0xB99D, 0xD289, 0xB99E, 0xD28A, 0xB99F, 0xD28B, 0xB9A0, 0xD28C, 0xB9A1, 0xBB00, 0xB9A2, 0xBB04, + 0xB9A3, 0xBB0D, 0xB9A4, 0xBB0F, 0xB9A5, 0xBB11, 0xB9A6, 0xBB18, 0xB9A7, 0xBB1C, 0xB9A8, 0xBB20, 0xB9A9, 0xBB29, 0xB9AA, 0xBB2B, + 0xB9AB, 0xBB34, 0xB9AC, 0xBB35, 0xB9AD, 0xBB36, 0xB9AE, 0xBB38, 0xB9AF, 0xBB3B, 0xB9B0, 0xBB3C, 0xB9B1, 0xBB3D, 0xB9B2, 0xBB3E, + 0xB9B3, 0xBB44, 0xB9B4, 0xBB45, 0xB9B5, 0xBB47, 0xB9B6, 0xBB49, 0xB9B7, 0xBB4D, 0xB9B8, 0xBB4F, 0xB9B9, 0xBB50, 0xB9BA, 0xBB54, + 0xB9BB, 0xBB58, 0xB9BC, 0xBB61, 0xB9BD, 0xBB63, 0xB9BE, 0xBB6C, 0xB9BF, 0xBB88, 0xB9C0, 0xBB8C, 0xB9C1, 0xBB90, 0xB9C2, 0xBBA4, + 0xB9C3, 0xBBA8, 0xB9C4, 0xBBAC, 0xB9C5, 0xBBB4, 0xB9C6, 0xBBB7, 0xB9C7, 0xBBC0, 0xB9C8, 0xBBC4, 0xB9C9, 0xBBC8, 0xB9CA, 0xBBD0, + 0xB9CB, 0xBBD3, 0xB9CC, 0xBBF8, 0xB9CD, 0xBBF9, 0xB9CE, 0xBBFC, 0xB9CF, 0xBBFF, 0xB9D0, 0xBC00, 0xB9D1, 0xBC02, 0xB9D2, 0xBC08, + 0xB9D3, 0xBC09, 0xB9D4, 0xBC0B, 0xB9D5, 0xBC0C, 0xB9D6, 0xBC0D, 0xB9D7, 0xBC0F, 0xB9D8, 0xBC11, 0xB9D9, 0xBC14, 0xB9DA, 0xBC15, + 0xB9DB, 0xBC16, 0xB9DC, 0xBC17, 0xB9DD, 0xBC18, 0xB9DE, 0xBC1B, 0xB9DF, 0xBC1C, 0xB9E0, 0xBC1D, 0xB9E1, 0xBC1E, 0xB9E2, 0xBC1F, + 0xB9E3, 0xBC24, 0xB9E4, 0xBC25, 0xB9E5, 0xBC27, 0xB9E6, 0xBC29, 0xB9E7, 0xBC2D, 0xB9E8, 0xBC30, 0xB9E9, 0xBC31, 0xB9EA, 0xBC34, + 0xB9EB, 0xBC38, 0xB9EC, 0xBC40, 0xB9ED, 0xBC41, 0xB9EE, 0xBC43, 0xB9EF, 0xBC44, 0xB9F0, 0xBC45, 0xB9F1, 0xBC49, 0xB9F2, 0xBC4C, + 0xB9F3, 0xBC4D, 0xB9F4, 0xBC50, 0xB9F5, 0xBC5D, 0xB9F6, 0xBC84, 0xB9F7, 0xBC85, 0xB9F8, 0xBC88, 0xB9F9, 0xBC8B, 0xB9FA, 0xBC8C, + 0xB9FB, 0xBC8E, 0xB9FC, 0xBC94, 0xB9FD, 0xBC95, 0xB9FE, 0xBC97, 0xBA41, 0xD28D, 0xBA42, 0xD28E, 0xBA43, 0xD28F, 0xBA44, 0xD292, + 0xBA45, 0xD293, 0xBA46, 0xD294, 0xBA47, 0xD296, 0xBA48, 0xD297, 0xBA49, 0xD298, 0xBA4A, 0xD299, 0xBA4B, 0xD29A, 0xBA4C, 0xD29B, + 0xBA4D, 0xD29D, 0xBA4E, 0xD29E, 0xBA4F, 0xD29F, 0xBA50, 0xD2A1, 0xBA51, 0xD2A2, 0xBA52, 0xD2A3, 0xBA53, 0xD2A5, 0xBA54, 0xD2A6, + 0xBA55, 0xD2A7, 0xBA56, 0xD2A8, 0xBA57, 0xD2A9, 0xBA58, 0xD2AA, 0xBA59, 0xD2AB, 0xBA5A, 0xD2AD, 0xBA61, 0xD2AE, 0xBA62, 0xD2AF, + 0xBA63, 0xD2B0, 0xBA64, 0xD2B2, 0xBA65, 0xD2B3, 0xBA66, 0xD2B4, 0xBA67, 0xD2B5, 0xBA68, 0xD2B6, 0xBA69, 0xD2B7, 0xBA6A, 0xD2BA, + 0xBA6B, 0xD2BB, 0xBA6C, 0xD2BD, 0xBA6D, 0xD2BE, 0xBA6E, 0xD2C1, 0xBA6F, 0xD2C3, 0xBA70, 0xD2C4, 0xBA71, 0xD2C5, 0xBA72, 0xD2C6, + 0xBA73, 0xD2C7, 0xBA74, 0xD2CA, 0xBA75, 0xD2CC, 0xBA76, 0xD2CD, 0xBA77, 0xD2CE, 0xBA78, 0xD2CF, 0xBA79, 0xD2D0, 0xBA7A, 0xD2D1, + 0xBA81, 0xD2D2, 0xBA82, 0xD2D3, 0xBA83, 0xD2D5, 0xBA84, 0xD2D6, 0xBA85, 0xD2D7, 0xBA86, 0xD2D9, 0xBA87, 0xD2DA, 0xBA88, 0xD2DB, + 0xBA89, 0xD2DD, 0xBA8A, 0xD2DE, 0xBA8B, 0xD2DF, 0xBA8C, 0xD2E0, 0xBA8D, 0xD2E1, 0xBA8E, 0xD2E2, 0xBA8F, 0xD2E3, 0xBA90, 0xD2E6, + 0xBA91, 0xD2E7, 0xBA92, 0xD2E8, 0xBA93, 0xD2E9, 0xBA94, 0xD2EA, 0xBA95, 0xD2EB, 0xBA96, 0xD2EC, 0xBA97, 0xD2ED, 0xBA98, 0xD2EE, + 0xBA99, 0xD2EF, 0xBA9A, 0xD2F2, 0xBA9B, 0xD2F3, 0xBA9C, 0xD2F5, 0xBA9D, 0xD2F6, 0xBA9E, 0xD2F7, 0xBA9F, 0xD2F9, 0xBAA0, 0xD2FA, + 0xBAA1, 0xBC99, 0xBAA2, 0xBC9A, 0xBAA3, 0xBCA0, 0xBAA4, 0xBCA1, 0xBAA5, 0xBCA4, 0xBAA6, 0xBCA7, 0xBAA7, 0xBCA8, 0xBAA8, 0xBCB0, + 0xBAA9, 0xBCB1, 0xBAAA, 0xBCB3, 0xBAAB, 0xBCB4, 0xBAAC, 0xBCB5, 0xBAAD, 0xBCBC, 0xBAAE, 0xBCBD, 0xBAAF, 0xBCC0, 0xBAB0, 0xBCC4, + 0xBAB1, 0xBCCD, 0xBAB2, 0xBCCF, 0xBAB3, 0xBCD0, 0xBAB4, 0xBCD1, 0xBAB5, 0xBCD5, 0xBAB6, 0xBCD8, 0xBAB7, 0xBCDC, 0xBAB8, 0xBCF4, + 0xBAB9, 0xBCF5, 0xBABA, 0xBCF6, 0xBABB, 0xBCF8, 0xBABC, 0xBCFC, 0xBABD, 0xBD04, 0xBABE, 0xBD05, 0xBABF, 0xBD07, 0xBAC0, 0xBD09, + 0xBAC1, 0xBD10, 0xBAC2, 0xBD14, 0xBAC3, 0xBD24, 0xBAC4, 0xBD2C, 0xBAC5, 0xBD40, 0xBAC6, 0xBD48, 0xBAC7, 0xBD49, 0xBAC8, 0xBD4C, + 0xBAC9, 0xBD50, 0xBACA, 0xBD58, 0xBACB, 0xBD59, 0xBACC, 0xBD64, 0xBACD, 0xBD68, 0xBACE, 0xBD80, 0xBACF, 0xBD81, 0xBAD0, 0xBD84, + 0xBAD1, 0xBD87, 0xBAD2, 0xBD88, 0xBAD3, 0xBD89, 0xBAD4, 0xBD8A, 0xBAD5, 0xBD90, 0xBAD6, 0xBD91, 0xBAD7, 0xBD93, 0xBAD8, 0xBD95, + 0xBAD9, 0xBD99, 0xBADA, 0xBD9A, 0xBADB, 0xBD9C, 0xBADC, 0xBDA4, 0xBADD, 0xBDB0, 0xBADE, 0xBDB8, 0xBADF, 0xBDD4, 0xBAE0, 0xBDD5, + 0xBAE1, 0xBDD8, 0xBAE2, 0xBDDC, 0xBAE3, 0xBDE9, 0xBAE4, 0xBDF0, 0xBAE5, 0xBDF4, 0xBAE6, 0xBDF8, 0xBAE7, 0xBE00, 0xBAE8, 0xBE03, + 0xBAE9, 0xBE05, 0xBAEA, 0xBE0C, 0xBAEB, 0xBE0D, 0xBAEC, 0xBE10, 0xBAED, 0xBE14, 0xBAEE, 0xBE1C, 0xBAEF, 0xBE1D, 0xBAF0, 0xBE1F, + 0xBAF1, 0xBE44, 0xBAF2, 0xBE45, 0xBAF3, 0xBE48, 0xBAF4, 0xBE4C, 0xBAF5, 0xBE4E, 0xBAF6, 0xBE54, 0xBAF7, 0xBE55, 0xBAF8, 0xBE57, + 0xBAF9, 0xBE59, 0xBAFA, 0xBE5A, 0xBAFB, 0xBE5B, 0xBAFC, 0xBE60, 0xBAFD, 0xBE61, 0xBAFE, 0xBE64, 0xBB41, 0xD2FB, 0xBB42, 0xD2FC, + 0xBB43, 0xD2FD, 0xBB44, 0xD2FE, 0xBB45, 0xD2FF, 0xBB46, 0xD302, 0xBB47, 0xD304, 0xBB48, 0xD306, 0xBB49, 0xD307, 0xBB4A, 0xD308, + 0xBB4B, 0xD309, 0xBB4C, 0xD30A, 0xBB4D, 0xD30B, 0xBB4E, 0xD30F, 0xBB4F, 0xD311, 0xBB50, 0xD312, 0xBB51, 0xD313, 0xBB52, 0xD315, + 0xBB53, 0xD317, 0xBB54, 0xD318, 0xBB55, 0xD319, 0xBB56, 0xD31A, 0xBB57, 0xD31B, 0xBB58, 0xD31E, 0xBB59, 0xD322, 0xBB5A, 0xD323, + 0xBB61, 0xD324, 0xBB62, 0xD326, 0xBB63, 0xD327, 0xBB64, 0xD32A, 0xBB65, 0xD32B, 0xBB66, 0xD32D, 0xBB67, 0xD32E, 0xBB68, 0xD32F, + 0xBB69, 0xD331, 0xBB6A, 0xD332, 0xBB6B, 0xD333, 0xBB6C, 0xD334, 0xBB6D, 0xD335, 0xBB6E, 0xD336, 0xBB6F, 0xD337, 0xBB70, 0xD33A, + 0xBB71, 0xD33E, 0xBB72, 0xD33F, 0xBB73, 0xD340, 0xBB74, 0xD341, 0xBB75, 0xD342, 0xBB76, 0xD343, 0xBB77, 0xD346, 0xBB78, 0xD347, + 0xBB79, 0xD348, 0xBB7A, 0xD349, 0xBB81, 0xD34A, 0xBB82, 0xD34B, 0xBB83, 0xD34C, 0xBB84, 0xD34D, 0xBB85, 0xD34E, 0xBB86, 0xD34F, + 0xBB87, 0xD350, 0xBB88, 0xD351, 0xBB89, 0xD352, 0xBB8A, 0xD353, 0xBB8B, 0xD354, 0xBB8C, 0xD355, 0xBB8D, 0xD356, 0xBB8E, 0xD357, + 0xBB8F, 0xD358, 0xBB90, 0xD359, 0xBB91, 0xD35A, 0xBB92, 0xD35B, 0xBB93, 0xD35C, 0xBB94, 0xD35D, 0xBB95, 0xD35E, 0xBB96, 0xD35F, + 0xBB97, 0xD360, 0xBB98, 0xD361, 0xBB99, 0xD362, 0xBB9A, 0xD363, 0xBB9B, 0xD364, 0xBB9C, 0xD365, 0xBB9D, 0xD366, 0xBB9E, 0xD367, + 0xBB9F, 0xD368, 0xBBA0, 0xD369, 0xBBA1, 0xBE68, 0xBBA2, 0xBE6A, 0xBBA3, 0xBE70, 0xBBA4, 0xBE71, 0xBBA5, 0xBE73, 0xBBA6, 0xBE74, + 0xBBA7, 0xBE75, 0xBBA8, 0xBE7B, 0xBBA9, 0xBE7C, 0xBBAA, 0xBE7D, 0xBBAB, 0xBE80, 0xBBAC, 0xBE84, 0xBBAD, 0xBE8C, 0xBBAE, 0xBE8D, + 0xBBAF, 0xBE8F, 0xBBB0, 0xBE90, 0xBBB1, 0xBE91, 0xBBB2, 0xBE98, 0xBBB3, 0xBE99, 0xBBB4, 0xBEA8, 0xBBB5, 0xBED0, 0xBBB6, 0xBED1, + 0xBBB7, 0xBED4, 0xBBB8, 0xBED7, 0xBBB9, 0xBED8, 0xBBBA, 0xBEE0, 0xBBBB, 0xBEE3, 0xBBBC, 0xBEE4, 0xBBBD, 0xBEE5, 0xBBBE, 0xBEEC, + 0xBBBF, 0xBF01, 0xBBC0, 0xBF08, 0xBBC1, 0xBF09, 0xBBC2, 0xBF18, 0xBBC3, 0xBF19, 0xBBC4, 0xBF1B, 0xBBC5, 0xBF1C, 0xBBC6, 0xBF1D, + 0xBBC7, 0xBF40, 0xBBC8, 0xBF41, 0xBBC9, 0xBF44, 0xBBCA, 0xBF48, 0xBBCB, 0xBF50, 0xBBCC, 0xBF51, 0xBBCD, 0xBF55, 0xBBCE, 0xBF94, + 0xBBCF, 0xBFB0, 0xBBD0, 0xBFC5, 0xBBD1, 0xBFCC, 0xBBD2, 0xBFCD, 0xBBD3, 0xBFD0, 0xBBD4, 0xBFD4, 0xBBD5, 0xBFDC, 0xBBD6, 0xBFDF, + 0xBBD7, 0xBFE1, 0xBBD8, 0xC03C, 0xBBD9, 0xC051, 0xBBDA, 0xC058, 0xBBDB, 0xC05C, 0xBBDC, 0xC060, 0xBBDD, 0xC068, 0xBBDE, 0xC069, + 0xBBDF, 0xC090, 0xBBE0, 0xC091, 0xBBE1, 0xC094, 0xBBE2, 0xC098, 0xBBE3, 0xC0A0, 0xBBE4, 0xC0A1, 0xBBE5, 0xC0A3, 0xBBE6, 0xC0A5, + 0xBBE7, 0xC0AC, 0xBBE8, 0xC0AD, 0xBBE9, 0xC0AF, 0xBBEA, 0xC0B0, 0xBBEB, 0xC0B3, 0xBBEC, 0xC0B4, 0xBBED, 0xC0B5, 0xBBEE, 0xC0B6, + 0xBBEF, 0xC0BC, 0xBBF0, 0xC0BD, 0xBBF1, 0xC0BF, 0xBBF2, 0xC0C0, 0xBBF3, 0xC0C1, 0xBBF4, 0xC0C5, 0xBBF5, 0xC0C8, 0xBBF6, 0xC0C9, + 0xBBF7, 0xC0CC, 0xBBF8, 0xC0D0, 0xBBF9, 0xC0D8, 0xBBFA, 0xC0D9, 0xBBFB, 0xC0DB, 0xBBFC, 0xC0DC, 0xBBFD, 0xC0DD, 0xBBFE, 0xC0E4, + 0xBC41, 0xD36A, 0xBC42, 0xD36B, 0xBC43, 0xD36C, 0xBC44, 0xD36D, 0xBC45, 0xD36E, 0xBC46, 0xD36F, 0xBC47, 0xD370, 0xBC48, 0xD371, + 0xBC49, 0xD372, 0xBC4A, 0xD373, 0xBC4B, 0xD374, 0xBC4C, 0xD375, 0xBC4D, 0xD376, 0xBC4E, 0xD377, 0xBC4F, 0xD378, 0xBC50, 0xD379, + 0xBC51, 0xD37A, 0xBC52, 0xD37B, 0xBC53, 0xD37E, 0xBC54, 0xD37F, 0xBC55, 0xD381, 0xBC56, 0xD382, 0xBC57, 0xD383, 0xBC58, 0xD385, + 0xBC59, 0xD386, 0xBC5A, 0xD387, 0xBC61, 0xD388, 0xBC62, 0xD389, 0xBC63, 0xD38A, 0xBC64, 0xD38B, 0xBC65, 0xD38E, 0xBC66, 0xD392, + 0xBC67, 0xD393, 0xBC68, 0xD394, 0xBC69, 0xD395, 0xBC6A, 0xD396, 0xBC6B, 0xD397, 0xBC6C, 0xD39A, 0xBC6D, 0xD39B, 0xBC6E, 0xD39D, + 0xBC6F, 0xD39E, 0xBC70, 0xD39F, 0xBC71, 0xD3A1, 0xBC72, 0xD3A2, 0xBC73, 0xD3A3, 0xBC74, 0xD3A4, 0xBC75, 0xD3A5, 0xBC76, 0xD3A6, + 0xBC77, 0xD3A7, 0xBC78, 0xD3AA, 0xBC79, 0xD3AC, 0xBC7A, 0xD3AE, 0xBC81, 0xD3AF, 0xBC82, 0xD3B0, 0xBC83, 0xD3B1, 0xBC84, 0xD3B2, + 0xBC85, 0xD3B3, 0xBC86, 0xD3B5, 0xBC87, 0xD3B6, 0xBC88, 0xD3B7, 0xBC89, 0xD3B9, 0xBC8A, 0xD3BA, 0xBC8B, 0xD3BB, 0xBC8C, 0xD3BD, + 0xBC8D, 0xD3BE, 0xBC8E, 0xD3BF, 0xBC8F, 0xD3C0, 0xBC90, 0xD3C1, 0xBC91, 0xD3C2, 0xBC92, 0xD3C3, 0xBC93, 0xD3C6, 0xBC94, 0xD3C7, + 0xBC95, 0xD3CA, 0xBC96, 0xD3CB, 0xBC97, 0xD3CC, 0xBC98, 0xD3CD, 0xBC99, 0xD3CE, 0xBC9A, 0xD3CF, 0xBC9B, 0xD3D1, 0xBC9C, 0xD3D2, + 0xBC9D, 0xD3D3, 0xBC9E, 0xD3D4, 0xBC9F, 0xD3D5, 0xBCA0, 0xD3D6, 0xBCA1, 0xC0E5, 0xBCA2, 0xC0E8, 0xBCA3, 0xC0EC, 0xBCA4, 0xC0F4, + 0xBCA5, 0xC0F5, 0xBCA6, 0xC0F7, 0xBCA7, 0xC0F9, 0xBCA8, 0xC100, 0xBCA9, 0xC104, 0xBCAA, 0xC108, 0xBCAB, 0xC110, 0xBCAC, 0xC115, + 0xBCAD, 0xC11C, 0xBCAE, 0xC11D, 0xBCAF, 0xC11E, 0xBCB0, 0xC11F, 0xBCB1, 0xC120, 0xBCB2, 0xC123, 0xBCB3, 0xC124, 0xBCB4, 0xC126, + 0xBCB5, 0xC127, 0xBCB6, 0xC12C, 0xBCB7, 0xC12D, 0xBCB8, 0xC12F, 0xBCB9, 0xC130, 0xBCBA, 0xC131, 0xBCBB, 0xC136, 0xBCBC, 0xC138, + 0xBCBD, 0xC139, 0xBCBE, 0xC13C, 0xBCBF, 0xC140, 0xBCC0, 0xC148, 0xBCC1, 0xC149, 0xBCC2, 0xC14B, 0xBCC3, 0xC14C, 0xBCC4, 0xC14D, + 0xBCC5, 0xC154, 0xBCC6, 0xC155, 0xBCC7, 0xC158, 0xBCC8, 0xC15C, 0xBCC9, 0xC164, 0xBCCA, 0xC165, 0xBCCB, 0xC167, 0xBCCC, 0xC168, + 0xBCCD, 0xC169, 0xBCCE, 0xC170, 0xBCCF, 0xC174, 0xBCD0, 0xC178, 0xBCD1, 0xC185, 0xBCD2, 0xC18C, 0xBCD3, 0xC18D, 0xBCD4, 0xC18E, + 0xBCD5, 0xC190, 0xBCD6, 0xC194, 0xBCD7, 0xC196, 0xBCD8, 0xC19C, 0xBCD9, 0xC19D, 0xBCDA, 0xC19F, 0xBCDB, 0xC1A1, 0xBCDC, 0xC1A5, + 0xBCDD, 0xC1A8, 0xBCDE, 0xC1A9, 0xBCDF, 0xC1AC, 0xBCE0, 0xC1B0, 0xBCE1, 0xC1BD, 0xBCE2, 0xC1C4, 0xBCE3, 0xC1C8, 0xBCE4, 0xC1CC, + 0xBCE5, 0xC1D4, 0xBCE6, 0xC1D7, 0xBCE7, 0xC1D8, 0xBCE8, 0xC1E0, 0xBCE9, 0xC1E4, 0xBCEA, 0xC1E8, 0xBCEB, 0xC1F0, 0xBCEC, 0xC1F1, + 0xBCED, 0xC1F3, 0xBCEE, 0xC1FC, 0xBCEF, 0xC1FD, 0xBCF0, 0xC200, 0xBCF1, 0xC204, 0xBCF2, 0xC20C, 0xBCF3, 0xC20D, 0xBCF4, 0xC20F, + 0xBCF5, 0xC211, 0xBCF6, 0xC218, 0xBCF7, 0xC219, 0xBCF8, 0xC21C, 0xBCF9, 0xC21F, 0xBCFA, 0xC220, 0xBCFB, 0xC228, 0xBCFC, 0xC229, + 0xBCFD, 0xC22B, 0xBCFE, 0xC22D, 0xBD41, 0xD3D7, 0xBD42, 0xD3D9, 0xBD43, 0xD3DA, 0xBD44, 0xD3DB, 0xBD45, 0xD3DC, 0xBD46, 0xD3DD, + 0xBD47, 0xD3DE, 0xBD48, 0xD3DF, 0xBD49, 0xD3E0, 0xBD4A, 0xD3E2, 0xBD4B, 0xD3E4, 0xBD4C, 0xD3E5, 0xBD4D, 0xD3E6, 0xBD4E, 0xD3E7, + 0xBD4F, 0xD3E8, 0xBD50, 0xD3E9, 0xBD51, 0xD3EA, 0xBD52, 0xD3EB, 0xBD53, 0xD3EE, 0xBD54, 0xD3EF, 0xBD55, 0xD3F1, 0xBD56, 0xD3F2, + 0xBD57, 0xD3F3, 0xBD58, 0xD3F5, 0xBD59, 0xD3F6, 0xBD5A, 0xD3F7, 0xBD61, 0xD3F8, 0xBD62, 0xD3F9, 0xBD63, 0xD3FA, 0xBD64, 0xD3FB, + 0xBD65, 0xD3FE, 0xBD66, 0xD400, 0xBD67, 0xD402, 0xBD68, 0xD403, 0xBD69, 0xD404, 0xBD6A, 0xD405, 0xBD6B, 0xD406, 0xBD6C, 0xD407, + 0xBD6D, 0xD409, 0xBD6E, 0xD40A, 0xBD6F, 0xD40B, 0xBD70, 0xD40C, 0xBD71, 0xD40D, 0xBD72, 0xD40E, 0xBD73, 0xD40F, 0xBD74, 0xD410, + 0xBD75, 0xD411, 0xBD76, 0xD412, 0xBD77, 0xD413, 0xBD78, 0xD414, 0xBD79, 0xD415, 0xBD7A, 0xD416, 0xBD81, 0xD417, 0xBD82, 0xD418, + 0xBD83, 0xD419, 0xBD84, 0xD41A, 0xBD85, 0xD41B, 0xBD86, 0xD41C, 0xBD87, 0xD41E, 0xBD88, 0xD41F, 0xBD89, 0xD420, 0xBD8A, 0xD421, + 0xBD8B, 0xD422, 0xBD8C, 0xD423, 0xBD8D, 0xD424, 0xBD8E, 0xD425, 0xBD8F, 0xD426, 0xBD90, 0xD427, 0xBD91, 0xD428, 0xBD92, 0xD429, + 0xBD93, 0xD42A, 0xBD94, 0xD42B, 0xBD95, 0xD42C, 0xBD96, 0xD42D, 0xBD97, 0xD42E, 0xBD98, 0xD42F, 0xBD99, 0xD430, 0xBD9A, 0xD431, + 0xBD9B, 0xD432, 0xBD9C, 0xD433, 0xBD9D, 0xD434, 0xBD9E, 0xD435, 0xBD9F, 0xD436, 0xBDA0, 0xD437, 0xBDA1, 0xC22F, 0xBDA2, 0xC231, + 0xBDA3, 0xC232, 0xBDA4, 0xC234, 0xBDA5, 0xC248, 0xBDA6, 0xC250, 0xBDA7, 0xC251, 0xBDA8, 0xC254, 0xBDA9, 0xC258, 0xBDAA, 0xC260, + 0xBDAB, 0xC265, 0xBDAC, 0xC26C, 0xBDAD, 0xC26D, 0xBDAE, 0xC270, 0xBDAF, 0xC274, 0xBDB0, 0xC27C, 0xBDB1, 0xC27D, 0xBDB2, 0xC27F, + 0xBDB3, 0xC281, 0xBDB4, 0xC288, 0xBDB5, 0xC289, 0xBDB6, 0xC290, 0xBDB7, 0xC298, 0xBDB8, 0xC29B, 0xBDB9, 0xC29D, 0xBDBA, 0xC2A4, + 0xBDBB, 0xC2A5, 0xBDBC, 0xC2A8, 0xBDBD, 0xC2AC, 0xBDBE, 0xC2AD, 0xBDBF, 0xC2B4, 0xBDC0, 0xC2B5, 0xBDC1, 0xC2B7, 0xBDC2, 0xC2B9, + 0xBDC3, 0xC2DC, 0xBDC4, 0xC2DD, 0xBDC5, 0xC2E0, 0xBDC6, 0xC2E3, 0xBDC7, 0xC2E4, 0xBDC8, 0xC2EB, 0xBDC9, 0xC2EC, 0xBDCA, 0xC2ED, + 0xBDCB, 0xC2EF, 0xBDCC, 0xC2F1, 0xBDCD, 0xC2F6, 0xBDCE, 0xC2F8, 0xBDCF, 0xC2F9, 0xBDD0, 0xC2FB, 0xBDD1, 0xC2FC, 0xBDD2, 0xC300, + 0xBDD3, 0xC308, 0xBDD4, 0xC309, 0xBDD5, 0xC30C, 0xBDD6, 0xC30D, 0xBDD7, 0xC313, 0xBDD8, 0xC314, 0xBDD9, 0xC315, 0xBDDA, 0xC318, + 0xBDDB, 0xC31C, 0xBDDC, 0xC324, 0xBDDD, 0xC325, 0xBDDE, 0xC328, 0xBDDF, 0xC329, 0xBDE0, 0xC345, 0xBDE1, 0xC368, 0xBDE2, 0xC369, + 0xBDE3, 0xC36C, 0xBDE4, 0xC370, 0xBDE5, 0xC372, 0xBDE6, 0xC378, 0xBDE7, 0xC379, 0xBDE8, 0xC37C, 0xBDE9, 0xC37D, 0xBDEA, 0xC384, + 0xBDEB, 0xC388, 0xBDEC, 0xC38C, 0xBDED, 0xC3C0, 0xBDEE, 0xC3D8, 0xBDEF, 0xC3D9, 0xBDF0, 0xC3DC, 0xBDF1, 0xC3DF, 0xBDF2, 0xC3E0, + 0xBDF3, 0xC3E2, 0xBDF4, 0xC3E8, 0xBDF5, 0xC3E9, 0xBDF6, 0xC3ED, 0xBDF7, 0xC3F4, 0xBDF8, 0xC3F5, 0xBDF9, 0xC3F8, 0xBDFA, 0xC408, + 0xBDFB, 0xC410, 0xBDFC, 0xC424, 0xBDFD, 0xC42C, 0xBDFE, 0xC430, 0xBE41, 0xD438, 0xBE42, 0xD439, 0xBE43, 0xD43A, 0xBE44, 0xD43B, + 0xBE45, 0xD43C, 0xBE46, 0xD43D, 0xBE47, 0xD43E, 0xBE48, 0xD43F, 0xBE49, 0xD441, 0xBE4A, 0xD442, 0xBE4B, 0xD443, 0xBE4C, 0xD445, + 0xBE4D, 0xD446, 0xBE4E, 0xD447, 0xBE4F, 0xD448, 0xBE50, 0xD449, 0xBE51, 0xD44A, 0xBE52, 0xD44B, 0xBE53, 0xD44C, 0xBE54, 0xD44D, + 0xBE55, 0xD44E, 0xBE56, 0xD44F, 0xBE57, 0xD450, 0xBE58, 0xD451, 0xBE59, 0xD452, 0xBE5A, 0xD453, 0xBE61, 0xD454, 0xBE62, 0xD455, + 0xBE63, 0xD456, 0xBE64, 0xD457, 0xBE65, 0xD458, 0xBE66, 0xD459, 0xBE67, 0xD45A, 0xBE68, 0xD45B, 0xBE69, 0xD45D, 0xBE6A, 0xD45E, + 0xBE6B, 0xD45F, 0xBE6C, 0xD461, 0xBE6D, 0xD462, 0xBE6E, 0xD463, 0xBE6F, 0xD465, 0xBE70, 0xD466, 0xBE71, 0xD467, 0xBE72, 0xD468, + 0xBE73, 0xD469, 0xBE74, 0xD46A, 0xBE75, 0xD46B, 0xBE76, 0xD46C, 0xBE77, 0xD46E, 0xBE78, 0xD470, 0xBE79, 0xD471, 0xBE7A, 0xD472, + 0xBE81, 0xD473, 0xBE82, 0xD474, 0xBE83, 0xD475, 0xBE84, 0xD476, 0xBE85, 0xD477, 0xBE86, 0xD47A, 0xBE87, 0xD47B, 0xBE88, 0xD47D, + 0xBE89, 0xD47E, 0xBE8A, 0xD481, 0xBE8B, 0xD483, 0xBE8C, 0xD484, 0xBE8D, 0xD485, 0xBE8E, 0xD486, 0xBE8F, 0xD487, 0xBE90, 0xD48A, + 0xBE91, 0xD48C, 0xBE92, 0xD48E, 0xBE93, 0xD48F, 0xBE94, 0xD490, 0xBE95, 0xD491, 0xBE96, 0xD492, 0xBE97, 0xD493, 0xBE98, 0xD495, + 0xBE99, 0xD496, 0xBE9A, 0xD497, 0xBE9B, 0xD498, 0xBE9C, 0xD499, 0xBE9D, 0xD49A, 0xBE9E, 0xD49B, 0xBE9F, 0xD49C, 0xBEA0, 0xD49D, + 0xBEA1, 0xC434, 0xBEA2, 0xC43C, 0xBEA3, 0xC43D, 0xBEA4, 0xC448, 0xBEA5, 0xC464, 0xBEA6, 0xC465, 0xBEA7, 0xC468, 0xBEA8, 0xC46C, + 0xBEA9, 0xC474, 0xBEAA, 0xC475, 0xBEAB, 0xC479, 0xBEAC, 0xC480, 0xBEAD, 0xC494, 0xBEAE, 0xC49C, 0xBEAF, 0xC4B8, 0xBEB0, 0xC4BC, + 0xBEB1, 0xC4E9, 0xBEB2, 0xC4F0, 0xBEB3, 0xC4F1, 0xBEB4, 0xC4F4, 0xBEB5, 0xC4F8, 0xBEB6, 0xC4FA, 0xBEB7, 0xC4FF, 0xBEB8, 0xC500, + 0xBEB9, 0xC501, 0xBEBA, 0xC50C, 0xBEBB, 0xC510, 0xBEBC, 0xC514, 0xBEBD, 0xC51C, 0xBEBE, 0xC528, 0xBEBF, 0xC529, 0xBEC0, 0xC52C, + 0xBEC1, 0xC530, 0xBEC2, 0xC538, 0xBEC3, 0xC539, 0xBEC4, 0xC53B, 0xBEC5, 0xC53D, 0xBEC6, 0xC544, 0xBEC7, 0xC545, 0xBEC8, 0xC548, + 0xBEC9, 0xC549, 0xBECA, 0xC54A, 0xBECB, 0xC54C, 0xBECC, 0xC54D, 0xBECD, 0xC54E, 0xBECE, 0xC553, 0xBECF, 0xC554, 0xBED0, 0xC555, + 0xBED1, 0xC557, 0xBED2, 0xC558, 0xBED3, 0xC559, 0xBED4, 0xC55D, 0xBED5, 0xC55E, 0xBED6, 0xC560, 0xBED7, 0xC561, 0xBED8, 0xC564, + 0xBED9, 0xC568, 0xBEDA, 0xC570, 0xBEDB, 0xC571, 0xBEDC, 0xC573, 0xBEDD, 0xC574, 0xBEDE, 0xC575, 0xBEDF, 0xC57C, 0xBEE0, 0xC57D, + 0xBEE1, 0xC580, 0xBEE2, 0xC584, 0xBEE3, 0xC587, 0xBEE4, 0xC58C, 0xBEE5, 0xC58D, 0xBEE6, 0xC58F, 0xBEE7, 0xC591, 0xBEE8, 0xC595, + 0xBEE9, 0xC597, 0xBEEA, 0xC598, 0xBEEB, 0xC59C, 0xBEEC, 0xC5A0, 0xBEED, 0xC5A9, 0xBEEE, 0xC5B4, 0xBEEF, 0xC5B5, 0xBEF0, 0xC5B8, + 0xBEF1, 0xC5B9, 0xBEF2, 0xC5BB, 0xBEF3, 0xC5BC, 0xBEF4, 0xC5BD, 0xBEF5, 0xC5BE, 0xBEF6, 0xC5C4, 0xBEF7, 0xC5C5, 0xBEF8, 0xC5C6, + 0xBEF9, 0xC5C7, 0xBEFA, 0xC5C8, 0xBEFB, 0xC5C9, 0xBEFC, 0xC5CA, 0xBEFD, 0xC5CC, 0xBEFE, 0xC5CE, 0xBF41, 0xD49E, 0xBF42, 0xD49F, + 0xBF43, 0xD4A0, 0xBF44, 0xD4A1, 0xBF45, 0xD4A2, 0xBF46, 0xD4A3, 0xBF47, 0xD4A4, 0xBF48, 0xD4A5, 0xBF49, 0xD4A6, 0xBF4A, 0xD4A7, + 0xBF4B, 0xD4A8, 0xBF4C, 0xD4AA, 0xBF4D, 0xD4AB, 0xBF4E, 0xD4AC, 0xBF4F, 0xD4AD, 0xBF50, 0xD4AE, 0xBF51, 0xD4AF, 0xBF52, 0xD4B0, + 0xBF53, 0xD4B1, 0xBF54, 0xD4B2, 0xBF55, 0xD4B3, 0xBF56, 0xD4B4, 0xBF57, 0xD4B5, 0xBF58, 0xD4B6, 0xBF59, 0xD4B7, 0xBF5A, 0xD4B8, + 0xBF61, 0xD4B9, 0xBF62, 0xD4BA, 0xBF63, 0xD4BB, 0xBF64, 0xD4BC, 0xBF65, 0xD4BD, 0xBF66, 0xD4BE, 0xBF67, 0xD4BF, 0xBF68, 0xD4C0, + 0xBF69, 0xD4C1, 0xBF6A, 0xD4C2, 0xBF6B, 0xD4C3, 0xBF6C, 0xD4C4, 0xBF6D, 0xD4C5, 0xBF6E, 0xD4C6, 0xBF6F, 0xD4C7, 0xBF70, 0xD4C8, + 0xBF71, 0xD4C9, 0xBF72, 0xD4CA, 0xBF73, 0xD4CB, 0xBF74, 0xD4CD, 0xBF75, 0xD4CE, 0xBF76, 0xD4CF, 0xBF77, 0xD4D1, 0xBF78, 0xD4D2, + 0xBF79, 0xD4D3, 0xBF7A, 0xD4D5, 0xBF81, 0xD4D6, 0xBF82, 0xD4D7, 0xBF83, 0xD4D8, 0xBF84, 0xD4D9, 0xBF85, 0xD4DA, 0xBF86, 0xD4DB, + 0xBF87, 0xD4DD, 0xBF88, 0xD4DE, 0xBF89, 0xD4E0, 0xBF8A, 0xD4E1, 0xBF8B, 0xD4E2, 0xBF8C, 0xD4E3, 0xBF8D, 0xD4E4, 0xBF8E, 0xD4E5, + 0xBF8F, 0xD4E6, 0xBF90, 0xD4E7, 0xBF91, 0xD4E9, 0xBF92, 0xD4EA, 0xBF93, 0xD4EB, 0xBF94, 0xD4ED, 0xBF95, 0xD4EE, 0xBF96, 0xD4EF, + 0xBF97, 0xD4F1, 0xBF98, 0xD4F2, 0xBF99, 0xD4F3, 0xBF9A, 0xD4F4, 0xBF9B, 0xD4F5, 0xBF9C, 0xD4F6, 0xBF9D, 0xD4F7, 0xBF9E, 0xD4F9, + 0xBF9F, 0xD4FA, 0xBFA0, 0xD4FC, 0xBFA1, 0xC5D0, 0xBFA2, 0xC5D1, 0xBFA3, 0xC5D4, 0xBFA4, 0xC5D8, 0xBFA5, 0xC5E0, 0xBFA6, 0xC5E1, + 0xBFA7, 0xC5E3, 0xBFA8, 0xC5E5, 0xBFA9, 0xC5EC, 0xBFAA, 0xC5ED, 0xBFAB, 0xC5EE, 0xBFAC, 0xC5F0, 0xBFAD, 0xC5F4, 0xBFAE, 0xC5F6, + 0xBFAF, 0xC5F7, 0xBFB0, 0xC5FC, 0xBFB1, 0xC5FD, 0xBFB2, 0xC5FE, 0xBFB3, 0xC5FF, 0xBFB4, 0xC600, 0xBFB5, 0xC601, 0xBFB6, 0xC605, + 0xBFB7, 0xC606, 0xBFB8, 0xC607, 0xBFB9, 0xC608, 0xBFBA, 0xC60C, 0xBFBB, 0xC610, 0xBFBC, 0xC618, 0xBFBD, 0xC619, 0xBFBE, 0xC61B, + 0xBFBF, 0xC61C, 0xBFC0, 0xC624, 0xBFC1, 0xC625, 0xBFC2, 0xC628, 0xBFC3, 0xC62C, 0xBFC4, 0xC62D, 0xBFC5, 0xC62E, 0xBFC6, 0xC630, + 0xBFC7, 0xC633, 0xBFC8, 0xC634, 0xBFC9, 0xC635, 0xBFCA, 0xC637, 0xBFCB, 0xC639, 0xBFCC, 0xC63B, 0xBFCD, 0xC640, 0xBFCE, 0xC641, + 0xBFCF, 0xC644, 0xBFD0, 0xC648, 0xBFD1, 0xC650, 0xBFD2, 0xC651, 0xBFD3, 0xC653, 0xBFD4, 0xC654, 0xBFD5, 0xC655, 0xBFD6, 0xC65C, + 0xBFD7, 0xC65D, 0xBFD8, 0xC660, 0xBFD9, 0xC66C, 0xBFDA, 0xC66F, 0xBFDB, 0xC671, 0xBFDC, 0xC678, 0xBFDD, 0xC679, 0xBFDE, 0xC67C, + 0xBFDF, 0xC680, 0xBFE0, 0xC688, 0xBFE1, 0xC689, 0xBFE2, 0xC68B, 0xBFE3, 0xC68D, 0xBFE4, 0xC694, 0xBFE5, 0xC695, 0xBFE6, 0xC698, + 0xBFE7, 0xC69C, 0xBFE8, 0xC6A4, 0xBFE9, 0xC6A5, 0xBFEA, 0xC6A7, 0xBFEB, 0xC6A9, 0xBFEC, 0xC6B0, 0xBFED, 0xC6B1, 0xBFEE, 0xC6B4, + 0xBFEF, 0xC6B8, 0xBFF0, 0xC6B9, 0xBFF1, 0xC6BA, 0xBFF2, 0xC6C0, 0xBFF3, 0xC6C1, 0xBFF4, 0xC6C3, 0xBFF5, 0xC6C5, 0xBFF6, 0xC6CC, + 0xBFF7, 0xC6CD, 0xBFF8, 0xC6D0, 0xBFF9, 0xC6D4, 0xBFFA, 0xC6DC, 0xBFFB, 0xC6DD, 0xBFFC, 0xC6E0, 0xBFFD, 0xC6E1, 0xBFFE, 0xC6E8, + 0xC041, 0xD4FE, 0xC042, 0xD4FF, 0xC043, 0xD500, 0xC044, 0xD501, 0xC045, 0xD502, 0xC046, 0xD503, 0xC047, 0xD505, 0xC048, 0xD506, + 0xC049, 0xD507, 0xC04A, 0xD509, 0xC04B, 0xD50A, 0xC04C, 0xD50B, 0xC04D, 0xD50D, 0xC04E, 0xD50E, 0xC04F, 0xD50F, 0xC050, 0xD510, + 0xC051, 0xD511, 0xC052, 0xD512, 0xC053, 0xD513, 0xC054, 0xD516, 0xC055, 0xD518, 0xC056, 0xD519, 0xC057, 0xD51A, 0xC058, 0xD51B, + 0xC059, 0xD51C, 0xC05A, 0xD51D, 0xC061, 0xD51E, 0xC062, 0xD51F, 0xC063, 0xD520, 0xC064, 0xD521, 0xC065, 0xD522, 0xC066, 0xD523, + 0xC067, 0xD524, 0xC068, 0xD525, 0xC069, 0xD526, 0xC06A, 0xD527, 0xC06B, 0xD528, 0xC06C, 0xD529, 0xC06D, 0xD52A, 0xC06E, 0xD52B, + 0xC06F, 0xD52C, 0xC070, 0xD52D, 0xC071, 0xD52E, 0xC072, 0xD52F, 0xC073, 0xD530, 0xC074, 0xD531, 0xC075, 0xD532, 0xC076, 0xD533, + 0xC077, 0xD534, 0xC078, 0xD535, 0xC079, 0xD536, 0xC07A, 0xD537, 0xC081, 0xD538, 0xC082, 0xD539, 0xC083, 0xD53A, 0xC084, 0xD53B, + 0xC085, 0xD53E, 0xC086, 0xD53F, 0xC087, 0xD541, 0xC088, 0xD542, 0xC089, 0xD543, 0xC08A, 0xD545, 0xC08B, 0xD546, 0xC08C, 0xD547, + 0xC08D, 0xD548, 0xC08E, 0xD549, 0xC08F, 0xD54A, 0xC090, 0xD54B, 0xC091, 0xD54E, 0xC092, 0xD550, 0xC093, 0xD552, 0xC094, 0xD553, + 0xC095, 0xD554, 0xC096, 0xD555, 0xC097, 0xD556, 0xC098, 0xD557, 0xC099, 0xD55A, 0xC09A, 0xD55B, 0xC09B, 0xD55D, 0xC09C, 0xD55E, + 0xC09D, 0xD55F, 0xC09E, 0xD561, 0xC09F, 0xD562, 0xC0A0, 0xD563, 0xC0A1, 0xC6E9, 0xC0A2, 0xC6EC, 0xC0A3, 0xC6F0, 0xC0A4, 0xC6F8, + 0xC0A5, 0xC6F9, 0xC0A6, 0xC6FD, 0xC0A7, 0xC704, 0xC0A8, 0xC705, 0xC0A9, 0xC708, 0xC0AA, 0xC70C, 0xC0AB, 0xC714, 0xC0AC, 0xC715, + 0xC0AD, 0xC717, 0xC0AE, 0xC719, 0xC0AF, 0xC720, 0xC0B0, 0xC721, 0xC0B1, 0xC724, 0xC0B2, 0xC728, 0xC0B3, 0xC730, 0xC0B4, 0xC731, + 0xC0B5, 0xC733, 0xC0B6, 0xC735, 0xC0B7, 0xC737, 0xC0B8, 0xC73C, 0xC0B9, 0xC73D, 0xC0BA, 0xC740, 0xC0BB, 0xC744, 0xC0BC, 0xC74A, + 0xC0BD, 0xC74C, 0xC0BE, 0xC74D, 0xC0BF, 0xC74F, 0xC0C0, 0xC751, 0xC0C1, 0xC752, 0xC0C2, 0xC753, 0xC0C3, 0xC754, 0xC0C4, 0xC755, + 0xC0C5, 0xC756, 0xC0C6, 0xC757, 0xC0C7, 0xC758, 0xC0C8, 0xC75C, 0xC0C9, 0xC760, 0xC0CA, 0xC768, 0xC0CB, 0xC76B, 0xC0CC, 0xC774, + 0xC0CD, 0xC775, 0xC0CE, 0xC778, 0xC0CF, 0xC77C, 0xC0D0, 0xC77D, 0xC0D1, 0xC77E, 0xC0D2, 0xC783, 0xC0D3, 0xC784, 0xC0D4, 0xC785, + 0xC0D5, 0xC787, 0xC0D6, 0xC788, 0xC0D7, 0xC789, 0xC0D8, 0xC78A, 0xC0D9, 0xC78E, 0xC0DA, 0xC790, 0xC0DB, 0xC791, 0xC0DC, 0xC794, + 0xC0DD, 0xC796, 0xC0DE, 0xC797, 0xC0DF, 0xC798, 0xC0E0, 0xC79A, 0xC0E1, 0xC7A0, 0xC0E2, 0xC7A1, 0xC0E3, 0xC7A3, 0xC0E4, 0xC7A4, + 0xC0E5, 0xC7A5, 0xC0E6, 0xC7A6, 0xC0E7, 0xC7AC, 0xC0E8, 0xC7AD, 0xC0E9, 0xC7B0, 0xC0EA, 0xC7B4, 0xC0EB, 0xC7BC, 0xC0EC, 0xC7BD, + 0xC0ED, 0xC7BF, 0xC0EE, 0xC7C0, 0xC0EF, 0xC7C1, 0xC0F0, 0xC7C8, 0xC0F1, 0xC7C9, 0xC0F2, 0xC7CC, 0xC0F3, 0xC7CE, 0xC0F4, 0xC7D0, + 0xC0F5, 0xC7D8, 0xC0F6, 0xC7DD, 0xC0F7, 0xC7E4, 0xC0F8, 0xC7E8, 0xC0F9, 0xC7EC, 0xC0FA, 0xC800, 0xC0FB, 0xC801, 0xC0FC, 0xC804, + 0xC0FD, 0xC808, 0xC0FE, 0xC80A, 0xC141, 0xD564, 0xC142, 0xD566, 0xC143, 0xD567, 0xC144, 0xD56A, 0xC145, 0xD56C, 0xC146, 0xD56E, + 0xC147, 0xD56F, 0xC148, 0xD570, 0xC149, 0xD571, 0xC14A, 0xD572, 0xC14B, 0xD573, 0xC14C, 0xD576, 0xC14D, 0xD577, 0xC14E, 0xD579, + 0xC14F, 0xD57A, 0xC150, 0xD57B, 0xC151, 0xD57D, 0xC152, 0xD57E, 0xC153, 0xD57F, 0xC154, 0xD580, 0xC155, 0xD581, 0xC156, 0xD582, + 0xC157, 0xD583, 0xC158, 0xD586, 0xC159, 0xD58A, 0xC15A, 0xD58B, 0xC161, 0xD58C, 0xC162, 0xD58D, 0xC163, 0xD58E, 0xC164, 0xD58F, + 0xC165, 0xD591, 0xC166, 0xD592, 0xC167, 0xD593, 0xC168, 0xD594, 0xC169, 0xD595, 0xC16A, 0xD596, 0xC16B, 0xD597, 0xC16C, 0xD598, + 0xC16D, 0xD599, 0xC16E, 0xD59A, 0xC16F, 0xD59B, 0xC170, 0xD59C, 0xC171, 0xD59D, 0xC172, 0xD59E, 0xC173, 0xD59F, 0xC174, 0xD5A0, + 0xC175, 0xD5A1, 0xC176, 0xD5A2, 0xC177, 0xD5A3, 0xC178, 0xD5A4, 0xC179, 0xD5A6, 0xC17A, 0xD5A7, 0xC181, 0xD5A8, 0xC182, 0xD5A9, + 0xC183, 0xD5AA, 0xC184, 0xD5AB, 0xC185, 0xD5AC, 0xC186, 0xD5AD, 0xC187, 0xD5AE, 0xC188, 0xD5AF, 0xC189, 0xD5B0, 0xC18A, 0xD5B1, + 0xC18B, 0xD5B2, 0xC18C, 0xD5B3, 0xC18D, 0xD5B4, 0xC18E, 0xD5B5, 0xC18F, 0xD5B6, 0xC190, 0xD5B7, 0xC191, 0xD5B8, 0xC192, 0xD5B9, + 0xC193, 0xD5BA, 0xC194, 0xD5BB, 0xC195, 0xD5BC, 0xC196, 0xD5BD, 0xC197, 0xD5BE, 0xC198, 0xD5BF, 0xC199, 0xD5C0, 0xC19A, 0xD5C1, + 0xC19B, 0xD5C2, 0xC19C, 0xD5C3, 0xC19D, 0xD5C4, 0xC19E, 0xD5C5, 0xC19F, 0xD5C6, 0xC1A0, 0xD5C7, 0xC1A1, 0xC810, 0xC1A2, 0xC811, + 0xC1A3, 0xC813, 0xC1A4, 0xC815, 0xC1A5, 0xC816, 0xC1A6, 0xC81C, 0xC1A7, 0xC81D, 0xC1A8, 0xC820, 0xC1A9, 0xC824, 0xC1AA, 0xC82C, + 0xC1AB, 0xC82D, 0xC1AC, 0xC82F, 0xC1AD, 0xC831, 0xC1AE, 0xC838, 0xC1AF, 0xC83C, 0xC1B0, 0xC840, 0xC1B1, 0xC848, 0xC1B2, 0xC849, + 0xC1B3, 0xC84C, 0xC1B4, 0xC84D, 0xC1B5, 0xC854, 0xC1B6, 0xC870, 0xC1B7, 0xC871, 0xC1B8, 0xC874, 0xC1B9, 0xC878, 0xC1BA, 0xC87A, + 0xC1BB, 0xC880, 0xC1BC, 0xC881, 0xC1BD, 0xC883, 0xC1BE, 0xC885, 0xC1BF, 0xC886, 0xC1C0, 0xC887, 0xC1C1, 0xC88B, 0xC1C2, 0xC88C, + 0xC1C3, 0xC88D, 0xC1C4, 0xC894, 0xC1C5, 0xC89D, 0xC1C6, 0xC89F, 0xC1C7, 0xC8A1, 0xC1C8, 0xC8A8, 0xC1C9, 0xC8BC, 0xC1CA, 0xC8BD, + 0xC1CB, 0xC8C4, 0xC1CC, 0xC8C8, 0xC1CD, 0xC8CC, 0xC1CE, 0xC8D4, 0xC1CF, 0xC8D5, 0xC1D0, 0xC8D7, 0xC1D1, 0xC8D9, 0xC1D2, 0xC8E0, + 0xC1D3, 0xC8E1, 0xC1D4, 0xC8E4, 0xC1D5, 0xC8F5, 0xC1D6, 0xC8FC, 0xC1D7, 0xC8FD, 0xC1D8, 0xC900, 0xC1D9, 0xC904, 0xC1DA, 0xC905, + 0xC1DB, 0xC906, 0xC1DC, 0xC90C, 0xC1DD, 0xC90D, 0xC1DE, 0xC90F, 0xC1DF, 0xC911, 0xC1E0, 0xC918, 0xC1E1, 0xC92C, 0xC1E2, 0xC934, + 0xC1E3, 0xC950, 0xC1E4, 0xC951, 0xC1E5, 0xC954, 0xC1E6, 0xC958, 0xC1E7, 0xC960, 0xC1E8, 0xC961, 0xC1E9, 0xC963, 0xC1EA, 0xC96C, + 0xC1EB, 0xC970, 0xC1EC, 0xC974, 0xC1ED, 0xC97C, 0xC1EE, 0xC988, 0xC1EF, 0xC989, 0xC1F0, 0xC98C, 0xC1F1, 0xC990, 0xC1F2, 0xC998, + 0xC1F3, 0xC999, 0xC1F4, 0xC99B, 0xC1F5, 0xC99D, 0xC1F6, 0xC9C0, 0xC1F7, 0xC9C1, 0xC1F8, 0xC9C4, 0xC1F9, 0xC9C7, 0xC1FA, 0xC9C8, + 0xC1FB, 0xC9CA, 0xC1FC, 0xC9D0, 0xC1FD, 0xC9D1, 0xC1FE, 0xC9D3, 0xC241, 0xD5CA, 0xC242, 0xD5CB, 0xC243, 0xD5CD, 0xC244, 0xD5CE, + 0xC245, 0xD5CF, 0xC246, 0xD5D1, 0xC247, 0xD5D3, 0xC248, 0xD5D4, 0xC249, 0xD5D5, 0xC24A, 0xD5D6, 0xC24B, 0xD5D7, 0xC24C, 0xD5DA, + 0xC24D, 0xD5DC, 0xC24E, 0xD5DE, 0xC24F, 0xD5DF, 0xC250, 0xD5E0, 0xC251, 0xD5E1, 0xC252, 0xD5E2, 0xC253, 0xD5E3, 0xC254, 0xD5E6, + 0xC255, 0xD5E7, 0xC256, 0xD5E9, 0xC257, 0xD5EA, 0xC258, 0xD5EB, 0xC259, 0xD5ED, 0xC25A, 0xD5EE, 0xC261, 0xD5EF, 0xC262, 0xD5F0, + 0xC263, 0xD5F1, 0xC264, 0xD5F2, 0xC265, 0xD5F3, 0xC266, 0xD5F6, 0xC267, 0xD5F8, 0xC268, 0xD5FA, 0xC269, 0xD5FB, 0xC26A, 0xD5FC, + 0xC26B, 0xD5FD, 0xC26C, 0xD5FE, 0xC26D, 0xD5FF, 0xC26E, 0xD602, 0xC26F, 0xD603, 0xC270, 0xD605, 0xC271, 0xD606, 0xC272, 0xD607, + 0xC273, 0xD609, 0xC274, 0xD60A, 0xC275, 0xD60B, 0xC276, 0xD60C, 0xC277, 0xD60D, 0xC278, 0xD60E, 0xC279, 0xD60F, 0xC27A, 0xD612, + 0xC281, 0xD616, 0xC282, 0xD617, 0xC283, 0xD618, 0xC284, 0xD619, 0xC285, 0xD61A, 0xC286, 0xD61B, 0xC287, 0xD61D, 0xC288, 0xD61E, + 0xC289, 0xD61F, 0xC28A, 0xD621, 0xC28B, 0xD622, 0xC28C, 0xD623, 0xC28D, 0xD625, 0xC28E, 0xD626, 0xC28F, 0xD627, 0xC290, 0xD628, + 0xC291, 0xD629, 0xC292, 0xD62A, 0xC293, 0xD62B, 0xC294, 0xD62C, 0xC295, 0xD62E, 0xC296, 0xD62F, 0xC297, 0xD630, 0xC298, 0xD631, + 0xC299, 0xD632, 0xC29A, 0xD633, 0xC29B, 0xD634, 0xC29C, 0xD635, 0xC29D, 0xD636, 0xC29E, 0xD637, 0xC29F, 0xD63A, 0xC2A0, 0xD63B, + 0xC2A1, 0xC9D5, 0xC2A2, 0xC9D6, 0xC2A3, 0xC9D9, 0xC2A4, 0xC9DA, 0xC2A5, 0xC9DC, 0xC2A6, 0xC9DD, 0xC2A7, 0xC9E0, 0xC2A8, 0xC9E2, + 0xC2A9, 0xC9E4, 0xC2AA, 0xC9E7, 0xC2AB, 0xC9EC, 0xC2AC, 0xC9ED, 0xC2AD, 0xC9EF, 0xC2AE, 0xC9F0, 0xC2AF, 0xC9F1, 0xC2B0, 0xC9F8, + 0xC2B1, 0xC9F9, 0xC2B2, 0xC9FC, 0xC2B3, 0xCA00, 0xC2B4, 0xCA08, 0xC2B5, 0xCA09, 0xC2B6, 0xCA0B, 0xC2B7, 0xCA0C, 0xC2B8, 0xCA0D, + 0xC2B9, 0xCA14, 0xC2BA, 0xCA18, 0xC2BB, 0xCA29, 0xC2BC, 0xCA4C, 0xC2BD, 0xCA4D, 0xC2BE, 0xCA50, 0xC2BF, 0xCA54, 0xC2C0, 0xCA5C, + 0xC2C1, 0xCA5D, 0xC2C2, 0xCA5F, 0xC2C3, 0xCA60, 0xC2C4, 0xCA61, 0xC2C5, 0xCA68, 0xC2C6, 0xCA7D, 0xC2C7, 0xCA84, 0xC2C8, 0xCA98, + 0xC2C9, 0xCABC, 0xC2CA, 0xCABD, 0xC2CB, 0xCAC0, 0xC2CC, 0xCAC4, 0xC2CD, 0xCACC, 0xC2CE, 0xCACD, 0xC2CF, 0xCACF, 0xC2D0, 0xCAD1, + 0xC2D1, 0xCAD3, 0xC2D2, 0xCAD8, 0xC2D3, 0xCAD9, 0xC2D4, 0xCAE0, 0xC2D5, 0xCAEC, 0xC2D6, 0xCAF4, 0xC2D7, 0xCB08, 0xC2D8, 0xCB10, + 0xC2D9, 0xCB14, 0xC2DA, 0xCB18, 0xC2DB, 0xCB20, 0xC2DC, 0xCB21, 0xC2DD, 0xCB41, 0xC2DE, 0xCB48, 0xC2DF, 0xCB49, 0xC2E0, 0xCB4C, + 0xC2E1, 0xCB50, 0xC2E2, 0xCB58, 0xC2E3, 0xCB59, 0xC2E4, 0xCB5D, 0xC2E5, 0xCB64, 0xC2E6, 0xCB78, 0xC2E7, 0xCB79, 0xC2E8, 0xCB9C, + 0xC2E9, 0xCBB8, 0xC2EA, 0xCBD4, 0xC2EB, 0xCBE4, 0xC2EC, 0xCBE7, 0xC2ED, 0xCBE9, 0xC2EE, 0xCC0C, 0xC2EF, 0xCC0D, 0xC2F0, 0xCC10, + 0xC2F1, 0xCC14, 0xC2F2, 0xCC1C, 0xC2F3, 0xCC1D, 0xC2F4, 0xCC21, 0xC2F5, 0xCC22, 0xC2F6, 0xCC27, 0xC2F7, 0xCC28, 0xC2F8, 0xCC29, + 0xC2F9, 0xCC2C, 0xC2FA, 0xCC2E, 0xC2FB, 0xCC30, 0xC2FC, 0xCC38, 0xC2FD, 0xCC39, 0xC2FE, 0xCC3B, 0xC341, 0xD63D, 0xC342, 0xD63E, + 0xC343, 0xD63F, 0xC344, 0xD641, 0xC345, 0xD642, 0xC346, 0xD643, 0xC347, 0xD644, 0xC348, 0xD646, 0xC349, 0xD647, 0xC34A, 0xD64A, + 0xC34B, 0xD64C, 0xC34C, 0xD64E, 0xC34D, 0xD64F, 0xC34E, 0xD650, 0xC34F, 0xD652, 0xC350, 0xD653, 0xC351, 0xD656, 0xC352, 0xD657, + 0xC353, 0xD659, 0xC354, 0xD65A, 0xC355, 0xD65B, 0xC356, 0xD65D, 0xC357, 0xD65E, 0xC358, 0xD65F, 0xC359, 0xD660, 0xC35A, 0xD661, + 0xC361, 0xD662, 0xC362, 0xD663, 0xC363, 0xD664, 0xC364, 0xD665, 0xC365, 0xD666, 0xC366, 0xD668, 0xC367, 0xD66A, 0xC368, 0xD66B, + 0xC369, 0xD66C, 0xC36A, 0xD66D, 0xC36B, 0xD66E, 0xC36C, 0xD66F, 0xC36D, 0xD672, 0xC36E, 0xD673, 0xC36F, 0xD675, 0xC370, 0xD676, + 0xC371, 0xD677, 0xC372, 0xD678, 0xC373, 0xD679, 0xC374, 0xD67A, 0xC375, 0xD67B, 0xC376, 0xD67C, 0xC377, 0xD67D, 0xC378, 0xD67E, + 0xC379, 0xD67F, 0xC37A, 0xD680, 0xC381, 0xD681, 0xC382, 0xD682, 0xC383, 0xD684, 0xC384, 0xD686, 0xC385, 0xD687, 0xC386, 0xD688, + 0xC387, 0xD689, 0xC388, 0xD68A, 0xC389, 0xD68B, 0xC38A, 0xD68E, 0xC38B, 0xD68F, 0xC38C, 0xD691, 0xC38D, 0xD692, 0xC38E, 0xD693, + 0xC38F, 0xD695, 0xC390, 0xD696, 0xC391, 0xD697, 0xC392, 0xD698, 0xC393, 0xD699, 0xC394, 0xD69A, 0xC395, 0xD69B, 0xC396, 0xD69C, + 0xC397, 0xD69E, 0xC398, 0xD6A0, 0xC399, 0xD6A2, 0xC39A, 0xD6A3, 0xC39B, 0xD6A4, 0xC39C, 0xD6A5, 0xC39D, 0xD6A6, 0xC39E, 0xD6A7, + 0xC39F, 0xD6A9, 0xC3A0, 0xD6AA, 0xC3A1, 0xCC3C, 0xC3A2, 0xCC3D, 0xC3A3, 0xCC3E, 0xC3A4, 0xCC44, 0xC3A5, 0xCC45, 0xC3A6, 0xCC48, + 0xC3A7, 0xCC4C, 0xC3A8, 0xCC54, 0xC3A9, 0xCC55, 0xC3AA, 0xCC57, 0xC3AB, 0xCC58, 0xC3AC, 0xCC59, 0xC3AD, 0xCC60, 0xC3AE, 0xCC64, + 0xC3AF, 0xCC66, 0xC3B0, 0xCC68, 0xC3B1, 0xCC70, 0xC3B2, 0xCC75, 0xC3B3, 0xCC98, 0xC3B4, 0xCC99, 0xC3B5, 0xCC9C, 0xC3B6, 0xCCA0, + 0xC3B7, 0xCCA8, 0xC3B8, 0xCCA9, 0xC3B9, 0xCCAB, 0xC3BA, 0xCCAC, 0xC3BB, 0xCCAD, 0xC3BC, 0xCCB4, 0xC3BD, 0xCCB5, 0xC3BE, 0xCCB8, + 0xC3BF, 0xCCBC, 0xC3C0, 0xCCC4, 0xC3C1, 0xCCC5, 0xC3C2, 0xCCC7, 0xC3C3, 0xCCC9, 0xC3C4, 0xCCD0, 0xC3C5, 0xCCD4, 0xC3C6, 0xCCE4, + 0xC3C7, 0xCCEC, 0xC3C8, 0xCCF0, 0xC3C9, 0xCD01, 0xC3CA, 0xCD08, 0xC3CB, 0xCD09, 0xC3CC, 0xCD0C, 0xC3CD, 0xCD10, 0xC3CE, 0xCD18, + 0xC3CF, 0xCD19, 0xC3D0, 0xCD1B, 0xC3D1, 0xCD1D, 0xC3D2, 0xCD24, 0xC3D3, 0xCD28, 0xC3D4, 0xCD2C, 0xC3D5, 0xCD39, 0xC3D6, 0xCD5C, + 0xC3D7, 0xCD60, 0xC3D8, 0xCD64, 0xC3D9, 0xCD6C, 0xC3DA, 0xCD6D, 0xC3DB, 0xCD6F, 0xC3DC, 0xCD71, 0xC3DD, 0xCD78, 0xC3DE, 0xCD88, + 0xC3DF, 0xCD94, 0xC3E0, 0xCD95, 0xC3E1, 0xCD98, 0xC3E2, 0xCD9C, 0xC3E3, 0xCDA4, 0xC3E4, 0xCDA5, 0xC3E5, 0xCDA7, 0xC3E6, 0xCDA9, + 0xC3E7, 0xCDB0, 0xC3E8, 0xCDC4, 0xC3E9, 0xCDCC, 0xC3EA, 0xCDD0, 0xC3EB, 0xCDE8, 0xC3EC, 0xCDEC, 0xC3ED, 0xCDF0, 0xC3EE, 0xCDF8, + 0xC3EF, 0xCDF9, 0xC3F0, 0xCDFB, 0xC3F1, 0xCDFD, 0xC3F2, 0xCE04, 0xC3F3, 0xCE08, 0xC3F4, 0xCE0C, 0xC3F5, 0xCE14, 0xC3F6, 0xCE19, + 0xC3F7, 0xCE20, 0xC3F8, 0xCE21, 0xC3F9, 0xCE24, 0xC3FA, 0xCE28, 0xC3FB, 0xCE30, 0xC3FC, 0xCE31, 0xC3FD, 0xCE33, 0xC3FE, 0xCE35, + 0xC441, 0xD6AB, 0xC442, 0xD6AD, 0xC443, 0xD6AE, 0xC444, 0xD6AF, 0xC445, 0xD6B1, 0xC446, 0xD6B2, 0xC447, 0xD6B3, 0xC448, 0xD6B4, + 0xC449, 0xD6B5, 0xC44A, 0xD6B6, 0xC44B, 0xD6B7, 0xC44C, 0xD6B8, 0xC44D, 0xD6BA, 0xC44E, 0xD6BC, 0xC44F, 0xD6BD, 0xC450, 0xD6BE, + 0xC451, 0xD6BF, 0xC452, 0xD6C0, 0xC453, 0xD6C1, 0xC454, 0xD6C2, 0xC455, 0xD6C3, 0xC456, 0xD6C6, 0xC457, 0xD6C7, 0xC458, 0xD6C9, + 0xC459, 0xD6CA, 0xC45A, 0xD6CB, 0xC461, 0xD6CD, 0xC462, 0xD6CE, 0xC463, 0xD6CF, 0xC464, 0xD6D0, 0xC465, 0xD6D2, 0xC466, 0xD6D3, + 0xC467, 0xD6D5, 0xC468, 0xD6D6, 0xC469, 0xD6D8, 0xC46A, 0xD6DA, 0xC46B, 0xD6DB, 0xC46C, 0xD6DC, 0xC46D, 0xD6DD, 0xC46E, 0xD6DE, + 0xC46F, 0xD6DF, 0xC470, 0xD6E1, 0xC471, 0xD6E2, 0xC472, 0xD6E3, 0xC473, 0xD6E5, 0xC474, 0xD6E6, 0xC475, 0xD6E7, 0xC476, 0xD6E9, + 0xC477, 0xD6EA, 0xC478, 0xD6EB, 0xC479, 0xD6EC, 0xC47A, 0xD6ED, 0xC481, 0xD6EE, 0xC482, 0xD6EF, 0xC483, 0xD6F1, 0xC484, 0xD6F2, + 0xC485, 0xD6F3, 0xC486, 0xD6F4, 0xC487, 0xD6F6, 0xC488, 0xD6F7, 0xC489, 0xD6F8, 0xC48A, 0xD6F9, 0xC48B, 0xD6FA, 0xC48C, 0xD6FB, + 0xC48D, 0xD6FE, 0xC48E, 0xD6FF, 0xC48F, 0xD701, 0xC490, 0xD702, 0xC491, 0xD703, 0xC492, 0xD705, 0xC493, 0xD706, 0xC494, 0xD707, + 0xC495, 0xD708, 0xC496, 0xD709, 0xC497, 0xD70A, 0xC498, 0xD70B, 0xC499, 0xD70C, 0xC49A, 0xD70D, 0xC49B, 0xD70E, 0xC49C, 0xD70F, + 0xC49D, 0xD710, 0xC49E, 0xD712, 0xC49F, 0xD713, 0xC4A0, 0xD714, 0xC4A1, 0xCE58, 0xC4A2, 0xCE59, 0xC4A3, 0xCE5C, 0xC4A4, 0xCE5F, + 0xC4A5, 0xCE60, 0xC4A6, 0xCE61, 0xC4A7, 0xCE68, 0xC4A8, 0xCE69, 0xC4A9, 0xCE6B, 0xC4AA, 0xCE6D, 0xC4AB, 0xCE74, 0xC4AC, 0xCE75, + 0xC4AD, 0xCE78, 0xC4AE, 0xCE7C, 0xC4AF, 0xCE84, 0xC4B0, 0xCE85, 0xC4B1, 0xCE87, 0xC4B2, 0xCE89, 0xC4B3, 0xCE90, 0xC4B4, 0xCE91, + 0xC4B5, 0xCE94, 0xC4B6, 0xCE98, 0xC4B7, 0xCEA0, 0xC4B8, 0xCEA1, 0xC4B9, 0xCEA3, 0xC4BA, 0xCEA4, 0xC4BB, 0xCEA5, 0xC4BC, 0xCEAC, + 0xC4BD, 0xCEAD, 0xC4BE, 0xCEC1, 0xC4BF, 0xCEE4, 0xC4C0, 0xCEE5, 0xC4C1, 0xCEE8, 0xC4C2, 0xCEEB, 0xC4C3, 0xCEEC, 0xC4C4, 0xCEF4, + 0xC4C5, 0xCEF5, 0xC4C6, 0xCEF7, 0xC4C7, 0xCEF8, 0xC4C8, 0xCEF9, 0xC4C9, 0xCF00, 0xC4CA, 0xCF01, 0xC4CB, 0xCF04, 0xC4CC, 0xCF08, + 0xC4CD, 0xCF10, 0xC4CE, 0xCF11, 0xC4CF, 0xCF13, 0xC4D0, 0xCF15, 0xC4D1, 0xCF1C, 0xC4D2, 0xCF20, 0xC4D3, 0xCF24, 0xC4D4, 0xCF2C, + 0xC4D5, 0xCF2D, 0xC4D6, 0xCF2F, 0xC4D7, 0xCF30, 0xC4D8, 0xCF31, 0xC4D9, 0xCF38, 0xC4DA, 0xCF54, 0xC4DB, 0xCF55, 0xC4DC, 0xCF58, + 0xC4DD, 0xCF5C, 0xC4DE, 0xCF64, 0xC4DF, 0xCF65, 0xC4E0, 0xCF67, 0xC4E1, 0xCF69, 0xC4E2, 0xCF70, 0xC4E3, 0xCF71, 0xC4E4, 0xCF74, + 0xC4E5, 0xCF78, 0xC4E6, 0xCF80, 0xC4E7, 0xCF85, 0xC4E8, 0xCF8C, 0xC4E9, 0xCFA1, 0xC4EA, 0xCFA8, 0xC4EB, 0xCFB0, 0xC4EC, 0xCFC4, + 0xC4ED, 0xCFE0, 0xC4EE, 0xCFE1, 0xC4EF, 0xCFE4, 0xC4F0, 0xCFE8, 0xC4F1, 0xCFF0, 0xC4F2, 0xCFF1, 0xC4F3, 0xCFF3, 0xC4F4, 0xCFF5, + 0xC4F5, 0xCFFC, 0xC4F6, 0xD000, 0xC4F7, 0xD004, 0xC4F8, 0xD011, 0xC4F9, 0xD018, 0xC4FA, 0xD02D, 0xC4FB, 0xD034, 0xC4FC, 0xD035, + 0xC4FD, 0xD038, 0xC4FE, 0xD03C, 0xC541, 0xD715, 0xC542, 0xD716, 0xC543, 0xD717, 0xC544, 0xD71A, 0xC545, 0xD71B, 0xC546, 0xD71D, + 0xC547, 0xD71E, 0xC548, 0xD71F, 0xC549, 0xD721, 0xC54A, 0xD722, 0xC54B, 0xD723, 0xC54C, 0xD724, 0xC54D, 0xD725, 0xC54E, 0xD726, + 0xC54F, 0xD727, 0xC550, 0xD72A, 0xC551, 0xD72C, 0xC552, 0xD72E, 0xC553, 0xD72F, 0xC554, 0xD730, 0xC555, 0xD731, 0xC556, 0xD732, + 0xC557, 0xD733, 0xC558, 0xD736, 0xC559, 0xD737, 0xC55A, 0xD739, 0xC561, 0xD73A, 0xC562, 0xD73B, 0xC563, 0xD73D, 0xC564, 0xD73E, + 0xC565, 0xD73F, 0xC566, 0xD740, 0xC567, 0xD741, 0xC568, 0xD742, 0xC569, 0xD743, 0xC56A, 0xD745, 0xC56B, 0xD746, 0xC56C, 0xD748, + 0xC56D, 0xD74A, 0xC56E, 0xD74B, 0xC56F, 0xD74C, 0xC570, 0xD74D, 0xC571, 0xD74E, 0xC572, 0xD74F, 0xC573, 0xD752, 0xC574, 0xD753, + 0xC575, 0xD755, 0xC576, 0xD75A, 0xC577, 0xD75B, 0xC578, 0xD75C, 0xC579, 0xD75D, 0xC57A, 0xD75E, 0xC581, 0xD75F, 0xC582, 0xD762, + 0xC583, 0xD764, 0xC584, 0xD766, 0xC585, 0xD767, 0xC586, 0xD768, 0xC587, 0xD76A, 0xC588, 0xD76B, 0xC589, 0xD76D, 0xC58A, 0xD76E, + 0xC58B, 0xD76F, 0xC58C, 0xD771, 0xC58D, 0xD772, 0xC58E, 0xD773, 0xC58F, 0xD775, 0xC590, 0xD776, 0xC591, 0xD777, 0xC592, 0xD778, + 0xC593, 0xD779, 0xC594, 0xD77A, 0xC595, 0xD77B, 0xC596, 0xD77E, 0xC597, 0xD77F, 0xC598, 0xD780, 0xC599, 0xD782, 0xC59A, 0xD783, + 0xC59B, 0xD784, 0xC59C, 0xD785, 0xC59D, 0xD786, 0xC59E, 0xD787, 0xC59F, 0xD78A, 0xC5A0, 0xD78B, 0xC5A1, 0xD044, 0xC5A2, 0xD045, + 0xC5A3, 0xD047, 0xC5A4, 0xD049, 0xC5A5, 0xD050, 0xC5A6, 0xD054, 0xC5A7, 0xD058, 0xC5A8, 0xD060, 0xC5A9, 0xD06C, 0xC5AA, 0xD06D, + 0xC5AB, 0xD070, 0xC5AC, 0xD074, 0xC5AD, 0xD07C, 0xC5AE, 0xD07D, 0xC5AF, 0xD081, 0xC5B0, 0xD0A4, 0xC5B1, 0xD0A5, 0xC5B2, 0xD0A8, + 0xC5B3, 0xD0AC, 0xC5B4, 0xD0B4, 0xC5B5, 0xD0B5, 0xC5B6, 0xD0B7, 0xC5B7, 0xD0B9, 0xC5B8, 0xD0C0, 0xC5B9, 0xD0C1, 0xC5BA, 0xD0C4, + 0xC5BB, 0xD0C8, 0xC5BC, 0xD0C9, 0xC5BD, 0xD0D0, 0xC5BE, 0xD0D1, 0xC5BF, 0xD0D3, 0xC5C0, 0xD0D4, 0xC5C1, 0xD0D5, 0xC5C2, 0xD0DC, + 0xC5C3, 0xD0DD, 0xC5C4, 0xD0E0, 0xC5C5, 0xD0E4, 0xC5C6, 0xD0EC, 0xC5C7, 0xD0ED, 0xC5C8, 0xD0EF, 0xC5C9, 0xD0F0, 0xC5CA, 0xD0F1, + 0xC5CB, 0xD0F8, 0xC5CC, 0xD10D, 0xC5CD, 0xD130, 0xC5CE, 0xD131, 0xC5CF, 0xD134, 0xC5D0, 0xD138, 0xC5D1, 0xD13A, 0xC5D2, 0xD140, + 0xC5D3, 0xD141, 0xC5D4, 0xD143, 0xC5D5, 0xD144, 0xC5D6, 0xD145, 0xC5D7, 0xD14C, 0xC5D8, 0xD14D, 0xC5D9, 0xD150, 0xC5DA, 0xD154, + 0xC5DB, 0xD15C, 0xC5DC, 0xD15D, 0xC5DD, 0xD15F, 0xC5DE, 0xD161, 0xC5DF, 0xD168, 0xC5E0, 0xD16C, 0xC5E1, 0xD17C, 0xC5E2, 0xD184, + 0xC5E3, 0xD188, 0xC5E4, 0xD1A0, 0xC5E5, 0xD1A1, 0xC5E6, 0xD1A4, 0xC5E7, 0xD1A8, 0xC5E8, 0xD1B0, 0xC5E9, 0xD1B1, 0xC5EA, 0xD1B3, + 0xC5EB, 0xD1B5, 0xC5EC, 0xD1BA, 0xC5ED, 0xD1BC, 0xC5EE, 0xD1C0, 0xC5EF, 0xD1D8, 0xC5F0, 0xD1F4, 0xC5F1, 0xD1F8, 0xC5F2, 0xD207, + 0xC5F3, 0xD209, 0xC5F4, 0xD210, 0xC5F5, 0xD22C, 0xC5F6, 0xD22D, 0xC5F7, 0xD230, 0xC5F8, 0xD234, 0xC5F9, 0xD23C, 0xC5FA, 0xD23D, + 0xC5FB, 0xD23F, 0xC5FC, 0xD241, 0xC5FD, 0xD248, 0xC5FE, 0xD25C, 0xC641, 0xD78D, 0xC642, 0xD78E, 0xC643, 0xD78F, 0xC644, 0xD791, + 0xC645, 0xD792, 0xC646, 0xD793, 0xC647, 0xD794, 0xC648, 0xD795, 0xC649, 0xD796, 0xC64A, 0xD797, 0xC64B, 0xD79A, 0xC64C, 0xD79C, + 0xC64D, 0xD79E, 0xC64E, 0xD79F, 0xC64F, 0xD7A0, 0xC650, 0xD7A1, 0xC651, 0xD7A2, 0xC652, 0xD7A3, 0xC6A1, 0xD264, 0xC6A2, 0xD280, + 0xC6A3, 0xD281, 0xC6A4, 0xD284, 0xC6A5, 0xD288, 0xC6A6, 0xD290, 0xC6A7, 0xD291, 0xC6A8, 0xD295, 0xC6A9, 0xD29C, 0xC6AA, 0xD2A0, + 0xC6AB, 0xD2A4, 0xC6AC, 0xD2AC, 0xC6AD, 0xD2B1, 0xC6AE, 0xD2B8, 0xC6AF, 0xD2B9, 0xC6B0, 0xD2BC, 0xC6B1, 0xD2BF, 0xC6B2, 0xD2C0, + 0xC6B3, 0xD2C2, 0xC6B4, 0xD2C8, 0xC6B5, 0xD2C9, 0xC6B6, 0xD2CB, 0xC6B7, 0xD2D4, 0xC6B8, 0xD2D8, 0xC6B9, 0xD2DC, 0xC6BA, 0xD2E4, + 0xC6BB, 0xD2E5, 0xC6BC, 0xD2F0, 0xC6BD, 0xD2F1, 0xC6BE, 0xD2F4, 0xC6BF, 0xD2F8, 0xC6C0, 0xD300, 0xC6C1, 0xD301, 0xC6C2, 0xD303, + 0xC6C3, 0xD305, 0xC6C4, 0xD30C, 0xC6C5, 0xD30D, 0xC6C6, 0xD30E, 0xC6C7, 0xD310, 0xC6C8, 0xD314, 0xC6C9, 0xD316, 0xC6CA, 0xD31C, + 0xC6CB, 0xD31D, 0xC6CC, 0xD31F, 0xC6CD, 0xD320, 0xC6CE, 0xD321, 0xC6CF, 0xD325, 0xC6D0, 0xD328, 0xC6D1, 0xD329, 0xC6D2, 0xD32C, + 0xC6D3, 0xD330, 0xC6D4, 0xD338, 0xC6D5, 0xD339, 0xC6D6, 0xD33B, 0xC6D7, 0xD33C, 0xC6D8, 0xD33D, 0xC6D9, 0xD344, 0xC6DA, 0xD345, + 0xC6DB, 0xD37C, 0xC6DC, 0xD37D, 0xC6DD, 0xD380, 0xC6DE, 0xD384, 0xC6DF, 0xD38C, 0xC6E0, 0xD38D, 0xC6E1, 0xD38F, 0xC6E2, 0xD390, + 0xC6E3, 0xD391, 0xC6E4, 0xD398, 0xC6E5, 0xD399, 0xC6E6, 0xD39C, 0xC6E7, 0xD3A0, 0xC6E8, 0xD3A8, 0xC6E9, 0xD3A9, 0xC6EA, 0xD3AB, + 0xC6EB, 0xD3AD, 0xC6EC, 0xD3B4, 0xC6ED, 0xD3B8, 0xC6EE, 0xD3BC, 0xC6EF, 0xD3C4, 0xC6F0, 0xD3C5, 0xC6F1, 0xD3C8, 0xC6F2, 0xD3C9, + 0xC6F3, 0xD3D0, 0xC6F4, 0xD3D8, 0xC6F5, 0xD3E1, 0xC6F6, 0xD3E3, 0xC6F7, 0xD3EC, 0xC6F8, 0xD3ED, 0xC6F9, 0xD3F0, 0xC6FA, 0xD3F4, + 0xC6FB, 0xD3FC, 0xC6FC, 0xD3FD, 0xC6FD, 0xD3FF, 0xC6FE, 0xD401, 0xC7A1, 0xD408, 0xC7A2, 0xD41D, 0xC7A3, 0xD440, 0xC7A4, 0xD444, + 0xC7A5, 0xD45C, 0xC7A6, 0xD460, 0xC7A7, 0xD464, 0xC7A8, 0xD46D, 0xC7A9, 0xD46F, 0xC7AA, 0xD478, 0xC7AB, 0xD479, 0xC7AC, 0xD47C, + 0xC7AD, 0xD47F, 0xC7AE, 0xD480, 0xC7AF, 0xD482, 0xC7B0, 0xD488, 0xC7B1, 0xD489, 0xC7B2, 0xD48B, 0xC7B3, 0xD48D, 0xC7B4, 0xD494, + 0xC7B5, 0xD4A9, 0xC7B6, 0xD4CC, 0xC7B7, 0xD4D0, 0xC7B8, 0xD4D4, 0xC7B9, 0xD4DC, 0xC7BA, 0xD4DF, 0xC7BB, 0xD4E8, 0xC7BC, 0xD4EC, + 0xC7BD, 0xD4F0, 0xC7BE, 0xD4F8, 0xC7BF, 0xD4FB, 0xC7C0, 0xD4FD, 0xC7C1, 0xD504, 0xC7C2, 0xD508, 0xC7C3, 0xD50C, 0xC7C4, 0xD514, + 0xC7C5, 0xD515, 0xC7C6, 0xD517, 0xC7C7, 0xD53C, 0xC7C8, 0xD53D, 0xC7C9, 0xD540, 0xC7CA, 0xD544, 0xC7CB, 0xD54C, 0xC7CC, 0xD54D, + 0xC7CD, 0xD54F, 0xC7CE, 0xD551, 0xC7CF, 0xD558, 0xC7D0, 0xD559, 0xC7D1, 0xD55C, 0xC7D2, 0xD560, 0xC7D3, 0xD565, 0xC7D4, 0xD568, + 0xC7D5, 0xD569, 0xC7D6, 0xD56B, 0xC7D7, 0xD56D, 0xC7D8, 0xD574, 0xC7D9, 0xD575, 0xC7DA, 0xD578, 0xC7DB, 0xD57C, 0xC7DC, 0xD584, + 0xC7DD, 0xD585, 0xC7DE, 0xD587, 0xC7DF, 0xD588, 0xC7E0, 0xD589, 0xC7E1, 0xD590, 0xC7E2, 0xD5A5, 0xC7E3, 0xD5C8, 0xC7E4, 0xD5C9, + 0xC7E5, 0xD5CC, 0xC7E6, 0xD5D0, 0xC7E7, 0xD5D2, 0xC7E8, 0xD5D8, 0xC7E9, 0xD5D9, 0xC7EA, 0xD5DB, 0xC7EB, 0xD5DD, 0xC7EC, 0xD5E4, + 0xC7ED, 0xD5E5, 0xC7EE, 0xD5E8, 0xC7EF, 0xD5EC, 0xC7F0, 0xD5F4, 0xC7F1, 0xD5F5, 0xC7F2, 0xD5F7, 0xC7F3, 0xD5F9, 0xC7F4, 0xD600, + 0xC7F5, 0xD601, 0xC7F6, 0xD604, 0xC7F7, 0xD608, 0xC7F8, 0xD610, 0xC7F9, 0xD611, 0xC7FA, 0xD613, 0xC7FB, 0xD614, 0xC7FC, 0xD615, + 0xC7FD, 0xD61C, 0xC7FE, 0xD620, 0xC8A1, 0xD624, 0xC8A2, 0xD62D, 0xC8A3, 0xD638, 0xC8A4, 0xD639, 0xC8A5, 0xD63C, 0xC8A6, 0xD640, + 0xC8A7, 0xD645, 0xC8A8, 0xD648, 0xC8A9, 0xD649, 0xC8AA, 0xD64B, 0xC8AB, 0xD64D, 0xC8AC, 0xD651, 0xC8AD, 0xD654, 0xC8AE, 0xD655, + 0xC8AF, 0xD658, 0xC8B0, 0xD65C, 0xC8B1, 0xD667, 0xC8B2, 0xD669, 0xC8B3, 0xD670, 0xC8B4, 0xD671, 0xC8B5, 0xD674, 0xC8B6, 0xD683, + 0xC8B7, 0xD685, 0xC8B8, 0xD68C, 0xC8B9, 0xD68D, 0xC8BA, 0xD690, 0xC8BB, 0xD694, 0xC8BC, 0xD69D, 0xC8BD, 0xD69F, 0xC8BE, 0xD6A1, + 0xC8BF, 0xD6A8, 0xC8C0, 0xD6AC, 0xC8C1, 0xD6B0, 0xC8C2, 0xD6B9, 0xC8C3, 0xD6BB, 0xC8C4, 0xD6C4, 0xC8C5, 0xD6C5, 0xC8C6, 0xD6C8, + 0xC8C7, 0xD6CC, 0xC8C8, 0xD6D1, 0xC8C9, 0xD6D4, 0xC8CA, 0xD6D7, 0xC8CB, 0xD6D9, 0xC8CC, 0xD6E0, 0xC8CD, 0xD6E4, 0xC8CE, 0xD6E8, + 0xC8CF, 0xD6F0, 0xC8D0, 0xD6F5, 0xC8D1, 0xD6FC, 0xC8D2, 0xD6FD, 0xC8D3, 0xD700, 0xC8D4, 0xD704, 0xC8D5, 0xD711, 0xC8D6, 0xD718, + 0xC8D7, 0xD719, 0xC8D8, 0xD71C, 0xC8D9, 0xD720, 0xC8DA, 0xD728, 0xC8DB, 0xD729, 0xC8DC, 0xD72B, 0xC8DD, 0xD72D, 0xC8DE, 0xD734, + 0xC8DF, 0xD735, 0xC8E0, 0xD738, 0xC8E1, 0xD73C, 0xC8E2, 0xD744, 0xC8E3, 0xD747, 0xC8E4, 0xD749, 0xC8E5, 0xD750, 0xC8E6, 0xD751, + 0xC8E7, 0xD754, 0xC8E8, 0xD756, 0xC8E9, 0xD757, 0xC8EA, 0xD758, 0xC8EB, 0xD759, 0xC8EC, 0xD760, 0xC8ED, 0xD761, 0xC8EE, 0xD763, + 0xC8EF, 0xD765, 0xC8F0, 0xD769, 0xC8F1, 0xD76C, 0xC8F2, 0xD770, 0xC8F3, 0xD774, 0xC8F4, 0xD77C, 0xC8F5, 0xD77D, 0xC8F6, 0xD781, + 0xC8F7, 0xD788, 0xC8F8, 0xD789, 0xC8F9, 0xD78C, 0xC8FA, 0xD790, 0xC8FB, 0xD798, 0xC8FC, 0xD799, 0xC8FD, 0xD79B, 0xC8FE, 0xD79D, + 0xCAA1, 0x4F3D, 0xCAA2, 0x4F73, 0xCAA3, 0x5047, 0xCAA4, 0x50F9, 0xCAA5, 0x52A0, 0xCAA6, 0x53EF, 0xCAA7, 0x5475, 0xCAA8, 0x54E5, + 0xCAA9, 0x5609, 0xCAAA, 0x5AC1, 0xCAAB, 0x5BB6, 0xCAAC, 0x6687, 0xCAAD, 0x67B6, 0xCAAE, 0x67B7, 0xCAAF, 0x67EF, 0xCAB0, 0x6B4C, + 0xCAB1, 0x73C2, 0xCAB2, 0x75C2, 0xCAB3, 0x7A3C, 0xCAB4, 0x82DB, 0xCAB5, 0x8304, 0xCAB6, 0x8857, 0xCAB7, 0x8888, 0xCAB8, 0x8A36, + 0xCAB9, 0x8CC8, 0xCABA, 0x8DCF, 0xCABB, 0x8EFB, 0xCABC, 0x8FE6, 0xCABD, 0x99D5, 0xCABE, 0x523B, 0xCABF, 0x5374, 0xCAC0, 0x5404, + 0xCAC1, 0x606A, 0xCAC2, 0x6164, 0xCAC3, 0x6BBC, 0xCAC4, 0x73CF, 0xCAC5, 0x811A, 0xCAC6, 0x89BA, 0xCAC7, 0x89D2, 0xCAC8, 0x95A3, + 0xCAC9, 0x4F83, 0xCACA, 0x520A, 0xCACB, 0x58BE, 0xCACC, 0x5978, 0xCACD, 0x59E6, 0xCACE, 0x5E72, 0xCACF, 0x5E79, 0xCAD0, 0x61C7, + 0xCAD1, 0x63C0, 0xCAD2, 0x6746, 0xCAD3, 0x67EC, 0xCAD4, 0x687F, 0xCAD5, 0x6F97, 0xCAD6, 0x764E, 0xCAD7, 0x770B, 0xCAD8, 0x78F5, + 0xCAD9, 0x7A08, 0xCADA, 0x7AFF, 0xCADB, 0x7C21, 0xCADC, 0x809D, 0xCADD, 0x826E, 0xCADE, 0x8271, 0xCADF, 0x8AEB, 0xCAE0, 0x9593, + 0xCAE1, 0x4E6B, 0xCAE2, 0x559D, 0xCAE3, 0x66F7, 0xCAE4, 0x6E34, 0xCAE5, 0x78A3, 0xCAE6, 0x7AED, 0xCAE7, 0x845B, 0xCAE8, 0x8910, + 0xCAE9, 0x874E, 0xCAEA, 0x97A8, 0xCAEB, 0x52D8, 0xCAEC, 0x574E, 0xCAED, 0x582A, 0xCAEE, 0x5D4C, 0xCAEF, 0x611F, 0xCAF0, 0x61BE, + 0xCAF1, 0x6221, 0xCAF2, 0x6562, 0xCAF3, 0x67D1, 0xCAF4, 0x6A44, 0xCAF5, 0x6E1B, 0xCAF6, 0x7518, 0xCAF7, 0x75B3, 0xCAF8, 0x76E3, + 0xCAF9, 0x77B0, 0xCAFA, 0x7D3A, 0xCAFB, 0x90AF, 0xCAFC, 0x9451, 0xCAFD, 0x9452, 0xCAFE, 0x9F95, 0xCBA1, 0x5323, 0xCBA2, 0x5CAC, + 0xCBA3, 0x7532, 0xCBA4, 0x80DB, 0xCBA5, 0x9240, 0xCBA6, 0x9598, 0xCBA7, 0x525B, 0xCBA8, 0x5808, 0xCBA9, 0x59DC, 0xCBAA, 0x5CA1, + 0xCBAB, 0x5D17, 0xCBAC, 0x5EB7, 0xCBAD, 0x5F3A, 0xCBAE, 0x5F4A, 0xCBAF, 0x6177, 0xCBB0, 0x6C5F, 0xCBB1, 0x757A, 0xCBB2, 0x7586, + 0xCBB3, 0x7CE0, 0xCBB4, 0x7D73, 0xCBB5, 0x7DB1, 0xCBB6, 0x7F8C, 0xCBB7, 0x8154, 0xCBB8, 0x8221, 0xCBB9, 0x8591, 0xCBBA, 0x8941, + 0xCBBB, 0x8B1B, 0xCBBC, 0x92FC, 0xCBBD, 0x964D, 0xCBBE, 0x9C47, 0xCBBF, 0x4ECB, 0xCBC0, 0x4EF7, 0xCBC1, 0x500B, 0xCBC2, 0x51F1, + 0xCBC3, 0x584F, 0xCBC4, 0x6137, 0xCBC5, 0x613E, 0xCBC6, 0x6168, 0xCBC7, 0x6539, 0xCBC8, 0x69EA, 0xCBC9, 0x6F11, 0xCBCA, 0x75A5, + 0xCBCB, 0x7686, 0xCBCC, 0x76D6, 0xCBCD, 0x7B87, 0xCBCE, 0x82A5, 0xCBCF, 0x84CB, 0xCBD0, 0xF900, 0xCBD1, 0x93A7, 0xCBD2, 0x958B, + 0xCBD3, 0x5580, 0xCBD4, 0x5BA2, 0xCBD5, 0x5751, 0xCBD6, 0xF901, 0xCBD7, 0x7CB3, 0xCBD8, 0x7FB9, 0xCBD9, 0x91B5, 0xCBDA, 0x5028, + 0xCBDB, 0x53BB, 0xCBDC, 0x5C45, 0xCBDD, 0x5DE8, 0xCBDE, 0x62D2, 0xCBDF, 0x636E, 0xCBE0, 0x64DA, 0xCBE1, 0x64E7, 0xCBE2, 0x6E20, + 0xCBE3, 0x70AC, 0xCBE4, 0x795B, 0xCBE5, 0x8DDD, 0xCBE6, 0x8E1E, 0xCBE7, 0xF902, 0xCBE8, 0x907D, 0xCBE9, 0x9245, 0xCBEA, 0x92F8, + 0xCBEB, 0x4E7E, 0xCBEC, 0x4EF6, 0xCBED, 0x5065, 0xCBEE, 0x5DFE, 0xCBEF, 0x5EFA, 0xCBF0, 0x6106, 0xCBF1, 0x6957, 0xCBF2, 0x8171, + 0xCBF3, 0x8654, 0xCBF4, 0x8E47, 0xCBF5, 0x9375, 0xCBF6, 0x9A2B, 0xCBF7, 0x4E5E, 0xCBF8, 0x5091, 0xCBF9, 0x6770, 0xCBFA, 0x6840, + 0xCBFB, 0x5109, 0xCBFC, 0x528D, 0xCBFD, 0x5292, 0xCBFE, 0x6AA2, 0xCCA1, 0x77BC, 0xCCA2, 0x9210, 0xCCA3, 0x9ED4, 0xCCA4, 0x52AB, + 0xCCA5, 0x602F, 0xCCA6, 0x8FF2, 0xCCA7, 0x5048, 0xCCA8, 0x61A9, 0xCCA9, 0x63ED, 0xCCAA, 0x64CA, 0xCCAB, 0x683C, 0xCCAC, 0x6A84, + 0xCCAD, 0x6FC0, 0xCCAE, 0x8188, 0xCCAF, 0x89A1, 0xCCB0, 0x9694, 0xCCB1, 0x5805, 0xCCB2, 0x727D, 0xCCB3, 0x72AC, 0xCCB4, 0x7504, + 0xCCB5, 0x7D79, 0xCCB6, 0x7E6D, 0xCCB7, 0x80A9, 0xCCB8, 0x898B, 0xCCB9, 0x8B74, 0xCCBA, 0x9063, 0xCCBB, 0x9D51, 0xCCBC, 0x6289, + 0xCCBD, 0x6C7A, 0xCCBE, 0x6F54, 0xCCBF, 0x7D50, 0xCCC0, 0x7F3A, 0xCCC1, 0x8A23, 0xCCC2, 0x517C, 0xCCC3, 0x614A, 0xCCC4, 0x7B9D, + 0xCCC5, 0x8B19, 0xCCC6, 0x9257, 0xCCC7, 0x938C, 0xCCC8, 0x4EAC, 0xCCC9, 0x4FD3, 0xCCCA, 0x501E, 0xCCCB, 0x50BE, 0xCCCC, 0x5106, + 0xCCCD, 0x52C1, 0xCCCE, 0x52CD, 0xCCCF, 0x537F, 0xCCD0, 0x5770, 0xCCD1, 0x5883, 0xCCD2, 0x5E9A, 0xCCD3, 0x5F91, 0xCCD4, 0x6176, + 0xCCD5, 0x61AC, 0xCCD6, 0x64CE, 0xCCD7, 0x656C, 0xCCD8, 0x666F, 0xCCD9, 0x66BB, 0xCCDA, 0x66F4, 0xCCDB, 0x6897, 0xCCDC, 0x6D87, + 0xCCDD, 0x7085, 0xCCDE, 0x70F1, 0xCCDF, 0x749F, 0xCCE0, 0x74A5, 0xCCE1, 0x74CA, 0xCCE2, 0x75D9, 0xCCE3, 0x786C, 0xCCE4, 0x78EC, + 0xCCE5, 0x7ADF, 0xCCE6, 0x7AF6, 0xCCE7, 0x7D45, 0xCCE8, 0x7D93, 0xCCE9, 0x8015, 0xCCEA, 0x803F, 0xCCEB, 0x811B, 0xCCEC, 0x8396, + 0xCCED, 0x8B66, 0xCCEE, 0x8F15, 0xCCEF, 0x9015, 0xCCF0, 0x93E1, 0xCCF1, 0x9803, 0xCCF2, 0x9838, 0xCCF3, 0x9A5A, 0xCCF4, 0x9BE8, + 0xCCF5, 0x4FC2, 0xCCF6, 0x5553, 0xCCF7, 0x583A, 0xCCF8, 0x5951, 0xCCF9, 0x5B63, 0xCCFA, 0x5C46, 0xCCFB, 0x60B8, 0xCCFC, 0x6212, + 0xCCFD, 0x6842, 0xCCFE, 0x68B0, 0xCDA1, 0x68E8, 0xCDA2, 0x6EAA, 0xCDA3, 0x754C, 0xCDA4, 0x7678, 0xCDA5, 0x78CE, 0xCDA6, 0x7A3D, + 0xCDA7, 0x7CFB, 0xCDA8, 0x7E6B, 0xCDA9, 0x7E7C, 0xCDAA, 0x8A08, 0xCDAB, 0x8AA1, 0xCDAC, 0x8C3F, 0xCDAD, 0x968E, 0xCDAE, 0x9DC4, + 0xCDAF, 0x53E4, 0xCDB0, 0x53E9, 0xCDB1, 0x544A, 0xCDB2, 0x5471, 0xCDB3, 0x56FA, 0xCDB4, 0x59D1, 0xCDB5, 0x5B64, 0xCDB6, 0x5C3B, + 0xCDB7, 0x5EAB, 0xCDB8, 0x62F7, 0xCDB9, 0x6537, 0xCDBA, 0x6545, 0xCDBB, 0x6572, 0xCDBC, 0x66A0, 0xCDBD, 0x67AF, 0xCDBE, 0x69C1, + 0xCDBF, 0x6CBD, 0xCDC0, 0x75FC, 0xCDC1, 0x7690, 0xCDC2, 0x777E, 0xCDC3, 0x7A3F, 0xCDC4, 0x7F94, 0xCDC5, 0x8003, 0xCDC6, 0x80A1, + 0xCDC7, 0x818F, 0xCDC8, 0x82E6, 0xCDC9, 0x82FD, 0xCDCA, 0x83F0, 0xCDCB, 0x85C1, 0xCDCC, 0x8831, 0xCDCD, 0x88B4, 0xCDCE, 0x8AA5, + 0xCDCF, 0xF903, 0xCDD0, 0x8F9C, 0xCDD1, 0x932E, 0xCDD2, 0x96C7, 0xCDD3, 0x9867, 0xCDD4, 0x9AD8, 0xCDD5, 0x9F13, 0xCDD6, 0x54ED, + 0xCDD7, 0x659B, 0xCDD8, 0x66F2, 0xCDD9, 0x688F, 0xCDDA, 0x7A40, 0xCDDB, 0x8C37, 0xCDDC, 0x9D60, 0xCDDD, 0x56F0, 0xCDDE, 0x5764, + 0xCDDF, 0x5D11, 0xCDE0, 0x6606, 0xCDE1, 0x68B1, 0xCDE2, 0x68CD, 0xCDE3, 0x6EFE, 0xCDE4, 0x7428, 0xCDE5, 0x889E, 0xCDE6, 0x9BE4, + 0xCDE7, 0x6C68, 0xCDE8, 0xF904, 0xCDE9, 0x9AA8, 0xCDEA, 0x4F9B, 0xCDEB, 0x516C, 0xCDEC, 0x5171, 0xCDED, 0x529F, 0xCDEE, 0x5B54, + 0xCDEF, 0x5DE5, 0xCDF0, 0x6050, 0xCDF1, 0x606D, 0xCDF2, 0x62F1, 0xCDF3, 0x63A7, 0xCDF4, 0x653B, 0xCDF5, 0x73D9, 0xCDF6, 0x7A7A, + 0xCDF7, 0x86A3, 0xCDF8, 0x8CA2, 0xCDF9, 0x978F, 0xCDFA, 0x4E32, 0xCDFB, 0x5BE1, 0xCDFC, 0x6208, 0xCDFD, 0x679C, 0xCDFE, 0x74DC, + 0xCEA1, 0x79D1, 0xCEA2, 0x83D3, 0xCEA3, 0x8A87, 0xCEA4, 0x8AB2, 0xCEA5, 0x8DE8, 0xCEA6, 0x904E, 0xCEA7, 0x934B, 0xCEA8, 0x9846, + 0xCEA9, 0x5ED3, 0xCEAA, 0x69E8, 0xCEAB, 0x85FF, 0xCEAC, 0x90ED, 0xCEAD, 0xF905, 0xCEAE, 0x51A0, 0xCEAF, 0x5B98, 0xCEB0, 0x5BEC, + 0xCEB1, 0x6163, 0xCEB2, 0x68FA, 0xCEB3, 0x6B3E, 0xCEB4, 0x704C, 0xCEB5, 0x742F, 0xCEB6, 0x74D8, 0xCEB7, 0x7BA1, 0xCEB8, 0x7F50, + 0xCEB9, 0x83C5, 0xCEBA, 0x89C0, 0xCEBB, 0x8CAB, 0xCEBC, 0x95DC, 0xCEBD, 0x9928, 0xCEBE, 0x522E, 0xCEBF, 0x605D, 0xCEC0, 0x62EC, + 0xCEC1, 0x9002, 0xCEC2, 0x4F8A, 0xCEC3, 0x5149, 0xCEC4, 0x5321, 0xCEC5, 0x58D9, 0xCEC6, 0x5EE3, 0xCEC7, 0x66E0, 0xCEC8, 0x6D38, + 0xCEC9, 0x709A, 0xCECA, 0x72C2, 0xCECB, 0x73D6, 0xCECC, 0x7B50, 0xCECD, 0x80F1, 0xCECE, 0x945B, 0xCECF, 0x5366, 0xCED0, 0x639B, + 0xCED1, 0x7F6B, 0xCED2, 0x4E56, 0xCED3, 0x5080, 0xCED4, 0x584A, 0xCED5, 0x58DE, 0xCED6, 0x602A, 0xCED7, 0x6127, 0xCED8, 0x62D0, + 0xCED9, 0x69D0, 0xCEDA, 0x9B41, 0xCEDB, 0x5B8F, 0xCEDC, 0x7D18, 0xCEDD, 0x80B1, 0xCEDE, 0x8F5F, 0xCEDF, 0x4EA4, 0xCEE0, 0x50D1, + 0xCEE1, 0x54AC, 0xCEE2, 0x55AC, 0xCEE3, 0x5B0C, 0xCEE4, 0x5DA0, 0xCEE5, 0x5DE7, 0xCEE6, 0x652A, 0xCEE7, 0x654E, 0xCEE8, 0x6821, + 0xCEE9, 0x6A4B, 0xCEEA, 0x72E1, 0xCEEB, 0x768E, 0xCEEC, 0x77EF, 0xCEED, 0x7D5E, 0xCEEE, 0x7FF9, 0xCEEF, 0x81A0, 0xCEF0, 0x854E, + 0xCEF1, 0x86DF, 0xCEF2, 0x8F03, 0xCEF3, 0x8F4E, 0xCEF4, 0x90CA, 0xCEF5, 0x9903, 0xCEF6, 0x9A55, 0xCEF7, 0x9BAB, 0xCEF8, 0x4E18, + 0xCEF9, 0x4E45, 0xCEFA, 0x4E5D, 0xCEFB, 0x4EC7, 0xCEFC, 0x4FF1, 0xCEFD, 0x5177, 0xCEFE, 0x52FE, 0xCFA1, 0x5340, 0xCFA2, 0x53E3, + 0xCFA3, 0x53E5, 0xCFA4, 0x548E, 0xCFA5, 0x5614, 0xCFA6, 0x5775, 0xCFA7, 0x57A2, 0xCFA8, 0x5BC7, 0xCFA9, 0x5D87, 0xCFAA, 0x5ED0, + 0xCFAB, 0x61FC, 0xCFAC, 0x62D8, 0xCFAD, 0x6551, 0xCFAE, 0x67B8, 0xCFAF, 0x67E9, 0xCFB0, 0x69CB, 0xCFB1, 0x6B50, 0xCFB2, 0x6BC6, + 0xCFB3, 0x6BEC, 0xCFB4, 0x6C42, 0xCFB5, 0x6E9D, 0xCFB6, 0x7078, 0xCFB7, 0x72D7, 0xCFB8, 0x7396, 0xCFB9, 0x7403, 0xCFBA, 0x77BF, + 0xCFBB, 0x77E9, 0xCFBC, 0x7A76, 0xCFBD, 0x7D7F, 0xCFBE, 0x8009, 0xCFBF, 0x81FC, 0xCFC0, 0x8205, 0xCFC1, 0x820A, 0xCFC2, 0x82DF, + 0xCFC3, 0x8862, 0xCFC4, 0x8B33, 0xCFC5, 0x8CFC, 0xCFC6, 0x8EC0, 0xCFC7, 0x9011, 0xCFC8, 0x90B1, 0xCFC9, 0x9264, 0xCFCA, 0x92B6, + 0xCFCB, 0x99D2, 0xCFCC, 0x9A45, 0xCFCD, 0x9CE9, 0xCFCE, 0x9DD7, 0xCFCF, 0x9F9C, 0xCFD0, 0x570B, 0xCFD1, 0x5C40, 0xCFD2, 0x83CA, + 0xCFD3, 0x97A0, 0xCFD4, 0x97AB, 0xCFD5, 0x9EB4, 0xCFD6, 0x541B, 0xCFD7, 0x7A98, 0xCFD8, 0x7FA4, 0xCFD9, 0x88D9, 0xCFDA, 0x8ECD, + 0xCFDB, 0x90E1, 0xCFDC, 0x5800, 0xCFDD, 0x5C48, 0xCFDE, 0x6398, 0xCFDF, 0x7A9F, 0xCFE0, 0x5BAE, 0xCFE1, 0x5F13, 0xCFE2, 0x7A79, + 0xCFE3, 0x7AAE, 0xCFE4, 0x828E, 0xCFE5, 0x8EAC, 0xCFE6, 0x5026, 0xCFE7, 0x5238, 0xCFE8, 0x52F8, 0xCFE9, 0x5377, 0xCFEA, 0x5708, + 0xCFEB, 0x62F3, 0xCFEC, 0x6372, 0xCFED, 0x6B0A, 0xCFEE, 0x6DC3, 0xCFEF, 0x7737, 0xCFF0, 0x53A5, 0xCFF1, 0x7357, 0xCFF2, 0x8568, + 0xCFF3, 0x8E76, 0xCFF4, 0x95D5, 0xCFF5, 0x673A, 0xCFF6, 0x6AC3, 0xCFF7, 0x6F70, 0xCFF8, 0x8A6D, 0xCFF9, 0x8ECC, 0xCFFA, 0x994B, + 0xCFFB, 0xF906, 0xCFFC, 0x6677, 0xCFFD, 0x6B78, 0xCFFE, 0x8CB4, 0xD0A1, 0x9B3C, 0xD0A2, 0xF907, 0xD0A3, 0x53EB, 0xD0A4, 0x572D, + 0xD0A5, 0x594E, 0xD0A6, 0x63C6, 0xD0A7, 0x69FB, 0xD0A8, 0x73EA, 0xD0A9, 0x7845, 0xD0AA, 0x7ABA, 0xD0AB, 0x7AC5, 0xD0AC, 0x7CFE, + 0xD0AD, 0x8475, 0xD0AE, 0x898F, 0xD0AF, 0x8D73, 0xD0B0, 0x9035, 0xD0B1, 0x95A8, 0xD0B2, 0x52FB, 0xD0B3, 0x5747, 0xD0B4, 0x7547, + 0xD0B5, 0x7B60, 0xD0B6, 0x83CC, 0xD0B7, 0x921E, 0xD0B8, 0xF908, 0xD0B9, 0x6A58, 0xD0BA, 0x514B, 0xD0BB, 0x524B, 0xD0BC, 0x5287, + 0xD0BD, 0x621F, 0xD0BE, 0x68D8, 0xD0BF, 0x6975, 0xD0C0, 0x9699, 0xD0C1, 0x50C5, 0xD0C2, 0x52A4, 0xD0C3, 0x52E4, 0xD0C4, 0x61C3, + 0xD0C5, 0x65A4, 0xD0C6, 0x6839, 0xD0C7, 0x69FF, 0xD0C8, 0x747E, 0xD0C9, 0x7B4B, 0xD0CA, 0x82B9, 0xD0CB, 0x83EB, 0xD0CC, 0x89B2, + 0xD0CD, 0x8B39, 0xD0CE, 0x8FD1, 0xD0CF, 0x9949, 0xD0D0, 0xF909, 0xD0D1, 0x4ECA, 0xD0D2, 0x5997, 0xD0D3, 0x64D2, 0xD0D4, 0x6611, + 0xD0D5, 0x6A8E, 0xD0D6, 0x7434, 0xD0D7, 0x7981, 0xD0D8, 0x79BD, 0xD0D9, 0x82A9, 0xD0DA, 0x887E, 0xD0DB, 0x887F, 0xD0DC, 0x895F, + 0xD0DD, 0xF90A, 0xD0DE, 0x9326, 0xD0DF, 0x4F0B, 0xD0E0, 0x53CA, 0xD0E1, 0x6025, 0xD0E2, 0x6271, 0xD0E3, 0x6C72, 0xD0E4, 0x7D1A, + 0xD0E5, 0x7D66, 0xD0E6, 0x4E98, 0xD0E7, 0x5162, 0xD0E8, 0x77DC, 0xD0E9, 0x80AF, 0xD0EA, 0x4F01, 0xD0EB, 0x4F0E, 0xD0EC, 0x5176, + 0xD0ED, 0x5180, 0xD0EE, 0x55DC, 0xD0EF, 0x5668, 0xD0F0, 0x573B, 0xD0F1, 0x57FA, 0xD0F2, 0x57FC, 0xD0F3, 0x5914, 0xD0F4, 0x5947, + 0xD0F5, 0x5993, 0xD0F6, 0x5BC4, 0xD0F7, 0x5C90, 0xD0F8, 0x5D0E, 0xD0F9, 0x5DF1, 0xD0FA, 0x5E7E, 0xD0FB, 0x5FCC, 0xD0FC, 0x6280, + 0xD0FD, 0x65D7, 0xD0FE, 0x65E3, 0xD1A1, 0x671E, 0xD1A2, 0x671F, 0xD1A3, 0x675E, 0xD1A4, 0x68CB, 0xD1A5, 0x68C4, 0xD1A6, 0x6A5F, + 0xD1A7, 0x6B3A, 0xD1A8, 0x6C23, 0xD1A9, 0x6C7D, 0xD1AA, 0x6C82, 0xD1AB, 0x6DC7, 0xD1AC, 0x7398, 0xD1AD, 0x7426, 0xD1AE, 0x742A, + 0xD1AF, 0x7482, 0xD1B0, 0x74A3, 0xD1B1, 0x7578, 0xD1B2, 0x757F, 0xD1B3, 0x7881, 0xD1B4, 0x78EF, 0xD1B5, 0x7941, 0xD1B6, 0x7947, + 0xD1B7, 0x7948, 0xD1B8, 0x797A, 0xD1B9, 0x7B95, 0xD1BA, 0x7D00, 0xD1BB, 0x7DBA, 0xD1BC, 0x7F88, 0xD1BD, 0x8006, 0xD1BE, 0x802D, + 0xD1BF, 0x808C, 0xD1C0, 0x8A18, 0xD1C1, 0x8B4F, 0xD1C2, 0x8C48, 0xD1C3, 0x8D77, 0xD1C4, 0x9321, 0xD1C5, 0x9324, 0xD1C6, 0x98E2, + 0xD1C7, 0x9951, 0xD1C8, 0x9A0E, 0xD1C9, 0x9A0F, 0xD1CA, 0x9A65, 0xD1CB, 0x9E92, 0xD1CC, 0x7DCA, 0xD1CD, 0x4F76, 0xD1CE, 0x5409, + 0xD1CF, 0x62EE, 0xD1D0, 0x6854, 0xD1D1, 0x91D1, 0xD1D2, 0x55AB, 0xD1D3, 0x513A, 0xD1D4, 0xF90B, 0xD1D5, 0xF90C, 0xD1D6, 0x5A1C, + 0xD1D7, 0x61E6, 0xD1D8, 0xF90D, 0xD1D9, 0x62CF, 0xD1DA, 0x62FF, 0xD1DB, 0xF90E, 0xD1DC, 0xF90F, 0xD1DD, 0xF910, 0xD1DE, 0xF911, + 0xD1DF, 0xF912, 0xD1E0, 0xF913, 0xD1E1, 0x90A3, 0xD1E2, 0xF914, 0xD1E3, 0xF915, 0xD1E4, 0xF916, 0xD1E5, 0xF917, 0xD1E6, 0xF918, + 0xD1E7, 0x8AFE, 0xD1E8, 0xF919, 0xD1E9, 0xF91A, 0xD1EA, 0xF91B, 0xD1EB, 0xF91C, 0xD1EC, 0x6696, 0xD1ED, 0xF91D, 0xD1EE, 0x7156, + 0xD1EF, 0xF91E, 0xD1F0, 0xF91F, 0xD1F1, 0x96E3, 0xD1F2, 0xF920, 0xD1F3, 0x634F, 0xD1F4, 0x637A, 0xD1F5, 0x5357, 0xD1F6, 0xF921, + 0xD1F7, 0x678F, 0xD1F8, 0x6960, 0xD1F9, 0x6E73, 0xD1FA, 0xF922, 0xD1FB, 0x7537, 0xD1FC, 0xF923, 0xD1FD, 0xF924, 0xD1FE, 0xF925, + 0xD2A1, 0x7D0D, 0xD2A2, 0xF926, 0xD2A3, 0xF927, 0xD2A4, 0x8872, 0xD2A5, 0x56CA, 0xD2A6, 0x5A18, 0xD2A7, 0xF928, 0xD2A8, 0xF929, + 0xD2A9, 0xF92A, 0xD2AA, 0xF92B, 0xD2AB, 0xF92C, 0xD2AC, 0x4E43, 0xD2AD, 0xF92D, 0xD2AE, 0x5167, 0xD2AF, 0x5948, 0xD2B0, 0x67F0, + 0xD2B1, 0x8010, 0xD2B2, 0xF92E, 0xD2B3, 0x5973, 0xD2B4, 0x5E74, 0xD2B5, 0x649A, 0xD2B6, 0x79CA, 0xD2B7, 0x5FF5, 0xD2B8, 0x606C, + 0xD2B9, 0x62C8, 0xD2BA, 0x637B, 0xD2BB, 0x5BE7, 0xD2BC, 0x5BD7, 0xD2BD, 0x52AA, 0xD2BE, 0xF92F, 0xD2BF, 0x5974, 0xD2C0, 0x5F29, + 0xD2C1, 0x6012, 0xD2C2, 0xF930, 0xD2C3, 0xF931, 0xD2C4, 0xF932, 0xD2C5, 0x7459, 0xD2C6, 0xF933, 0xD2C7, 0xF934, 0xD2C8, 0xF935, + 0xD2C9, 0xF936, 0xD2CA, 0xF937, 0xD2CB, 0xF938, 0xD2CC, 0x99D1, 0xD2CD, 0xF939, 0xD2CE, 0xF93A, 0xD2CF, 0xF93B, 0xD2D0, 0xF93C, + 0xD2D1, 0xF93D, 0xD2D2, 0xF93E, 0xD2D3, 0xF93F, 0xD2D4, 0xF940, 0xD2D5, 0xF941, 0xD2D6, 0xF942, 0xD2D7, 0xF943, 0xD2D8, 0x6FC3, + 0xD2D9, 0xF944, 0xD2DA, 0xF945, 0xD2DB, 0x81BF, 0xD2DC, 0x8FB2, 0xD2DD, 0x60F1, 0xD2DE, 0xF946, 0xD2DF, 0xF947, 0xD2E0, 0x8166, + 0xD2E1, 0xF948, 0xD2E2, 0xF949, 0xD2E3, 0x5C3F, 0xD2E4, 0xF94A, 0xD2E5, 0xF94B, 0xD2E6, 0xF94C, 0xD2E7, 0xF94D, 0xD2E8, 0xF94E, + 0xD2E9, 0xF94F, 0xD2EA, 0xF950, 0xD2EB, 0xF951, 0xD2EC, 0x5AE9, 0xD2ED, 0x8A25, 0xD2EE, 0x677B, 0xD2EF, 0x7D10, 0xD2F0, 0xF952, + 0xD2F1, 0xF953, 0xD2F2, 0xF954, 0xD2F3, 0xF955, 0xD2F4, 0xF956, 0xD2F5, 0xF957, 0xD2F6, 0x80FD, 0xD2F7, 0xF958, 0xD2F8, 0xF959, + 0xD2F9, 0x5C3C, 0xD2FA, 0x6CE5, 0xD2FB, 0x533F, 0xD2FC, 0x6EBA, 0xD2FD, 0x591A, 0xD2FE, 0x8336, 0xD3A1, 0x4E39, 0xD3A2, 0x4EB6, + 0xD3A3, 0x4F46, 0xD3A4, 0x55AE, 0xD3A5, 0x5718, 0xD3A6, 0x58C7, 0xD3A7, 0x5F56, 0xD3A8, 0x65B7, 0xD3A9, 0x65E6, 0xD3AA, 0x6A80, + 0xD3AB, 0x6BB5, 0xD3AC, 0x6E4D, 0xD3AD, 0x77ED, 0xD3AE, 0x7AEF, 0xD3AF, 0x7C1E, 0xD3B0, 0x7DDE, 0xD3B1, 0x86CB, 0xD3B2, 0x8892, + 0xD3B3, 0x9132, 0xD3B4, 0x935B, 0xD3B5, 0x64BB, 0xD3B6, 0x6FBE, 0xD3B7, 0x737A, 0xD3B8, 0x75B8, 0xD3B9, 0x9054, 0xD3BA, 0x5556, + 0xD3BB, 0x574D, 0xD3BC, 0x61BA, 0xD3BD, 0x64D4, 0xD3BE, 0x66C7, 0xD3BF, 0x6DE1, 0xD3C0, 0x6E5B, 0xD3C1, 0x6F6D, 0xD3C2, 0x6FB9, + 0xD3C3, 0x75F0, 0xD3C4, 0x8043, 0xD3C5, 0x81BD, 0xD3C6, 0x8541, 0xD3C7, 0x8983, 0xD3C8, 0x8AC7, 0xD3C9, 0x8B5A, 0xD3CA, 0x931F, + 0xD3CB, 0x6C93, 0xD3CC, 0x7553, 0xD3CD, 0x7B54, 0xD3CE, 0x8E0F, 0xD3CF, 0x905D, 0xD3D0, 0x5510, 0xD3D1, 0x5802, 0xD3D2, 0x5858, + 0xD3D3, 0x5E62, 0xD3D4, 0x6207, 0xD3D5, 0x649E, 0xD3D6, 0x68E0, 0xD3D7, 0x7576, 0xD3D8, 0x7CD6, 0xD3D9, 0x87B3, 0xD3DA, 0x9EE8, + 0xD3DB, 0x4EE3, 0xD3DC, 0x5788, 0xD3DD, 0x576E, 0xD3DE, 0x5927, 0xD3DF, 0x5C0D, 0xD3E0, 0x5CB1, 0xD3E1, 0x5E36, 0xD3E2, 0x5F85, + 0xD3E3, 0x6234, 0xD3E4, 0x64E1, 0xD3E5, 0x73B3, 0xD3E6, 0x81FA, 0xD3E7, 0x888B, 0xD3E8, 0x8CB8, 0xD3E9, 0x968A, 0xD3EA, 0x9EDB, + 0xD3EB, 0x5B85, 0xD3EC, 0x5FB7, 0xD3ED, 0x60B3, 0xD3EE, 0x5012, 0xD3EF, 0x5200, 0xD3F0, 0x5230, 0xD3F1, 0x5716, 0xD3F2, 0x5835, + 0xD3F3, 0x5857, 0xD3F4, 0x5C0E, 0xD3F5, 0x5C60, 0xD3F6, 0x5CF6, 0xD3F7, 0x5D8B, 0xD3F8, 0x5EA6, 0xD3F9, 0x5F92, 0xD3FA, 0x60BC, + 0xD3FB, 0x6311, 0xD3FC, 0x6389, 0xD3FD, 0x6417, 0xD3FE, 0x6843, 0xD4A1, 0x68F9, 0xD4A2, 0x6AC2, 0xD4A3, 0x6DD8, 0xD4A4, 0x6E21, + 0xD4A5, 0x6ED4, 0xD4A6, 0x6FE4, 0xD4A7, 0x71FE, 0xD4A8, 0x76DC, 0xD4A9, 0x7779, 0xD4AA, 0x79B1, 0xD4AB, 0x7A3B, 0xD4AC, 0x8404, + 0xD4AD, 0x89A9, 0xD4AE, 0x8CED, 0xD4AF, 0x8DF3, 0xD4B0, 0x8E48, 0xD4B1, 0x9003, 0xD4B2, 0x9014, 0xD4B3, 0x9053, 0xD4B4, 0x90FD, + 0xD4B5, 0x934D, 0xD4B6, 0x9676, 0xD4B7, 0x97DC, 0xD4B8, 0x6BD2, 0xD4B9, 0x7006, 0xD4BA, 0x7258, 0xD4BB, 0x72A2, 0xD4BC, 0x7368, + 0xD4BD, 0x7763, 0xD4BE, 0x79BF, 0xD4BF, 0x7BE4, 0xD4C0, 0x7E9B, 0xD4C1, 0x8B80, 0xD4C2, 0x58A9, 0xD4C3, 0x60C7, 0xD4C4, 0x6566, + 0xD4C5, 0x65FD, 0xD4C6, 0x66BE, 0xD4C7, 0x6C8C, 0xD4C8, 0x711E, 0xD4C9, 0x71C9, 0xD4CA, 0x8C5A, 0xD4CB, 0x9813, 0xD4CC, 0x4E6D, + 0xD4CD, 0x7A81, 0xD4CE, 0x4EDD, 0xD4CF, 0x51AC, 0xD4D0, 0x51CD, 0xD4D1, 0x52D5, 0xD4D2, 0x540C, 0xD4D3, 0x61A7, 0xD4D4, 0x6771, + 0xD4D5, 0x6850, 0xD4D6, 0x68DF, 0xD4D7, 0x6D1E, 0xD4D8, 0x6F7C, 0xD4D9, 0x75BC, 0xD4DA, 0x77B3, 0xD4DB, 0x7AE5, 0xD4DC, 0x80F4, + 0xD4DD, 0x8463, 0xD4DE, 0x9285, 0xD4DF, 0x515C, 0xD4E0, 0x6597, 0xD4E1, 0x675C, 0xD4E2, 0x6793, 0xD4E3, 0x75D8, 0xD4E4, 0x7AC7, + 0xD4E5, 0x8373, 0xD4E6, 0xF95A, 0xD4E7, 0x8C46, 0xD4E8, 0x9017, 0xD4E9, 0x982D, 0xD4EA, 0x5C6F, 0xD4EB, 0x81C0, 0xD4EC, 0x829A, + 0xD4ED, 0x9041, 0xD4EE, 0x906F, 0xD4EF, 0x920D, 0xD4F0, 0x5F97, 0xD4F1, 0x5D9D, 0xD4F2, 0x6A59, 0xD4F3, 0x71C8, 0xD4F4, 0x767B, + 0xD4F5, 0x7B49, 0xD4F6, 0x85E4, 0xD4F7, 0x8B04, 0xD4F8, 0x9127, 0xD4F9, 0x9A30, 0xD4FA, 0x5587, 0xD4FB, 0x61F6, 0xD4FC, 0xF95B, + 0xD4FD, 0x7669, 0xD4FE, 0x7F85, 0xD5A1, 0x863F, 0xD5A2, 0x87BA, 0xD5A3, 0x88F8, 0xD5A4, 0x908F, 0xD5A5, 0xF95C, 0xD5A6, 0x6D1B, + 0xD5A7, 0x70D9, 0xD5A8, 0x73DE, 0xD5A9, 0x7D61, 0xD5AA, 0x843D, 0xD5AB, 0xF95D, 0xD5AC, 0x916A, 0xD5AD, 0x99F1, 0xD5AE, 0xF95E, + 0xD5AF, 0x4E82, 0xD5B0, 0x5375, 0xD5B1, 0x6B04, 0xD5B2, 0x6B12, 0xD5B3, 0x703E, 0xD5B4, 0x721B, 0xD5B5, 0x862D, 0xD5B6, 0x9E1E, + 0xD5B7, 0x524C, 0xD5B8, 0x8FA3, 0xD5B9, 0x5D50, 0xD5BA, 0x64E5, 0xD5BB, 0x652C, 0xD5BC, 0x6B16, 0xD5BD, 0x6FEB, 0xD5BE, 0x7C43, + 0xD5BF, 0x7E9C, 0xD5C0, 0x85CD, 0xD5C1, 0x8964, 0xD5C2, 0x89BD, 0xD5C3, 0x62C9, 0xD5C4, 0x81D8, 0xD5C5, 0x881F, 0xD5C6, 0x5ECA, + 0xD5C7, 0x6717, 0xD5C8, 0x6D6A, 0xD5C9, 0x72FC, 0xD5CA, 0x7405, 0xD5CB, 0x746F, 0xD5CC, 0x8782, 0xD5CD, 0x90DE, 0xD5CE, 0x4F86, + 0xD5CF, 0x5D0D, 0xD5D0, 0x5FA0, 0xD5D1, 0x840A, 0xD5D2, 0x51B7, 0xD5D3, 0x63A0, 0xD5D4, 0x7565, 0xD5D5, 0x4EAE, 0xD5D6, 0x5006, + 0xD5D7, 0x5169, 0xD5D8, 0x51C9, 0xD5D9, 0x6881, 0xD5DA, 0x6A11, 0xD5DB, 0x7CAE, 0xD5DC, 0x7CB1, 0xD5DD, 0x7CE7, 0xD5DE, 0x826F, + 0xD5DF, 0x8AD2, 0xD5E0, 0x8F1B, 0xD5E1, 0x91CF, 0xD5E2, 0x4FB6, 0xD5E3, 0x5137, 0xD5E4, 0x52F5, 0xD5E5, 0x5442, 0xD5E6, 0x5EEC, + 0xD5E7, 0x616E, 0xD5E8, 0x623E, 0xD5E9, 0x65C5, 0xD5EA, 0x6ADA, 0xD5EB, 0x6FFE, 0xD5EC, 0x792A, 0xD5ED, 0x85DC, 0xD5EE, 0x8823, + 0xD5EF, 0x95AD, 0xD5F0, 0x9A62, 0xD5F1, 0x9A6A, 0xD5F2, 0x9E97, 0xD5F3, 0x9ECE, 0xD5F4, 0x529B, 0xD5F5, 0x66C6, 0xD5F6, 0x6B77, + 0xD5F7, 0x701D, 0xD5F8, 0x792B, 0xD5F9, 0x8F62, 0xD5FA, 0x9742, 0xD5FB, 0x6190, 0xD5FC, 0x6200, 0xD5FD, 0x6523, 0xD5FE, 0x6F23, + 0xD6A1, 0x7149, 0xD6A2, 0x7489, 0xD6A3, 0x7DF4, 0xD6A4, 0x806F, 0xD6A5, 0x84EE, 0xD6A6, 0x8F26, 0xD6A7, 0x9023, 0xD6A8, 0x934A, + 0xD6A9, 0x51BD, 0xD6AA, 0x5217, 0xD6AB, 0x52A3, 0xD6AC, 0x6D0C, 0xD6AD, 0x70C8, 0xD6AE, 0x88C2, 0xD6AF, 0x5EC9, 0xD6B0, 0x6582, + 0xD6B1, 0x6BAE, 0xD6B2, 0x6FC2, 0xD6B3, 0x7C3E, 0xD6B4, 0x7375, 0xD6B5, 0x4EE4, 0xD6B6, 0x4F36, 0xD6B7, 0x56F9, 0xD6B8, 0xF95F, + 0xD6B9, 0x5CBA, 0xD6BA, 0x5DBA, 0xD6BB, 0x601C, 0xD6BC, 0x73B2, 0xD6BD, 0x7B2D, 0xD6BE, 0x7F9A, 0xD6BF, 0x7FCE, 0xD6C0, 0x8046, + 0xD6C1, 0x901E, 0xD6C2, 0x9234, 0xD6C3, 0x96F6, 0xD6C4, 0x9748, 0xD6C5, 0x9818, 0xD6C6, 0x9F61, 0xD6C7, 0x4F8B, 0xD6C8, 0x6FA7, + 0xD6C9, 0x79AE, 0xD6CA, 0x91B4, 0xD6CB, 0x96B7, 0xD6CC, 0x52DE, 0xD6CD, 0xF960, 0xD6CE, 0x6488, 0xD6CF, 0x64C4, 0xD6D0, 0x6AD3, + 0xD6D1, 0x6F5E, 0xD6D2, 0x7018, 0xD6D3, 0x7210, 0xD6D4, 0x76E7, 0xD6D5, 0x8001, 0xD6D6, 0x8606, 0xD6D7, 0x865C, 0xD6D8, 0x8DEF, + 0xD6D9, 0x8F05, 0xD6DA, 0x9732, 0xD6DB, 0x9B6F, 0xD6DC, 0x9DFA, 0xD6DD, 0x9E75, 0xD6DE, 0x788C, 0xD6DF, 0x797F, 0xD6E0, 0x7DA0, + 0xD6E1, 0x83C9, 0xD6E2, 0x9304, 0xD6E3, 0x9E7F, 0xD6E4, 0x9E93, 0xD6E5, 0x8AD6, 0xD6E6, 0x58DF, 0xD6E7, 0x5F04, 0xD6E8, 0x6727, + 0xD6E9, 0x7027, 0xD6EA, 0x74CF, 0xD6EB, 0x7C60, 0xD6EC, 0x807E, 0xD6ED, 0x5121, 0xD6EE, 0x7028, 0xD6EF, 0x7262, 0xD6F0, 0x78CA, + 0xD6F1, 0x8CC2, 0xD6F2, 0x8CDA, 0xD6F3, 0x8CF4, 0xD6F4, 0x96F7, 0xD6F5, 0x4E86, 0xD6F6, 0x50DA, 0xD6F7, 0x5BEE, 0xD6F8, 0x5ED6, + 0xD6F9, 0x6599, 0xD6FA, 0x71CE, 0xD6FB, 0x7642, 0xD6FC, 0x77AD, 0xD6FD, 0x804A, 0xD6FE, 0x84FC, 0xD7A1, 0x907C, 0xD7A2, 0x9B27, + 0xD7A3, 0x9F8D, 0xD7A4, 0x58D8, 0xD7A5, 0x5A41, 0xD7A6, 0x5C62, 0xD7A7, 0x6A13, 0xD7A8, 0x6DDA, 0xD7A9, 0x6F0F, 0xD7AA, 0x763B, + 0xD7AB, 0x7D2F, 0xD7AC, 0x7E37, 0xD7AD, 0x851E, 0xD7AE, 0x8938, 0xD7AF, 0x93E4, 0xD7B0, 0x964B, 0xD7B1, 0x5289, 0xD7B2, 0x65D2, + 0xD7B3, 0x67F3, 0xD7B4, 0x69B4, 0xD7B5, 0x6D41, 0xD7B6, 0x6E9C, 0xD7B7, 0x700F, 0xD7B8, 0x7409, 0xD7B9, 0x7460, 0xD7BA, 0x7559, + 0xD7BB, 0x7624, 0xD7BC, 0x786B, 0xD7BD, 0x8B2C, 0xD7BE, 0x985E, 0xD7BF, 0x516D, 0xD7C0, 0x622E, 0xD7C1, 0x9678, 0xD7C2, 0x4F96, + 0xD7C3, 0x502B, 0xD7C4, 0x5D19, 0xD7C5, 0x6DEA, 0xD7C6, 0x7DB8, 0xD7C7, 0x8F2A, 0xD7C8, 0x5F8B, 0xD7C9, 0x6144, 0xD7CA, 0x6817, + 0xD7CB, 0xF961, 0xD7CC, 0x9686, 0xD7CD, 0x52D2, 0xD7CE, 0x808B, 0xD7CF, 0x51DC, 0xD7D0, 0x51CC, 0xD7D1, 0x695E, 0xD7D2, 0x7A1C, + 0xD7D3, 0x7DBE, 0xD7D4, 0x83F1, 0xD7D5, 0x9675, 0xD7D6, 0x4FDA, 0xD7D7, 0x5229, 0xD7D8, 0x5398, 0xD7D9, 0x540F, 0xD7DA, 0x550E, + 0xD7DB, 0x5C65, 0xD7DC, 0x60A7, 0xD7DD, 0x674E, 0xD7DE, 0x68A8, 0xD7DF, 0x6D6C, 0xD7E0, 0x7281, 0xD7E1, 0x72F8, 0xD7E2, 0x7406, + 0xD7E3, 0x7483, 0xD7E4, 0xF962, 0xD7E5, 0x75E2, 0xD7E6, 0x7C6C, 0xD7E7, 0x7F79, 0xD7E8, 0x7FB8, 0xD7E9, 0x8389, 0xD7EA, 0x88CF, + 0xD7EB, 0x88E1, 0xD7EC, 0x91CC, 0xD7ED, 0x91D0, 0xD7EE, 0x96E2, 0xD7EF, 0x9BC9, 0xD7F0, 0x541D, 0xD7F1, 0x6F7E, 0xD7F2, 0x71D0, + 0xD7F3, 0x7498, 0xD7F4, 0x85FA, 0xD7F5, 0x8EAA, 0xD7F6, 0x96A3, 0xD7F7, 0x9C57, 0xD7F8, 0x9E9F, 0xD7F9, 0x6797, 0xD7FA, 0x6DCB, + 0xD7FB, 0x7433, 0xD7FC, 0x81E8, 0xD7FD, 0x9716, 0xD7FE, 0x782C, 0xD8A1, 0x7ACB, 0xD8A2, 0x7B20, 0xD8A3, 0x7C92, 0xD8A4, 0x6469, + 0xD8A5, 0x746A, 0xD8A6, 0x75F2, 0xD8A7, 0x78BC, 0xD8A8, 0x78E8, 0xD8A9, 0x99AC, 0xD8AA, 0x9B54, 0xD8AB, 0x9EBB, 0xD8AC, 0x5BDE, + 0xD8AD, 0x5E55, 0xD8AE, 0x6F20, 0xD8AF, 0x819C, 0xD8B0, 0x83AB, 0xD8B1, 0x9088, 0xD8B2, 0x4E07, 0xD8B3, 0x534D, 0xD8B4, 0x5A29, + 0xD8B5, 0x5DD2, 0xD8B6, 0x5F4E, 0xD8B7, 0x6162, 0xD8B8, 0x633D, 0xD8B9, 0x6669, 0xD8BA, 0x66FC, 0xD8BB, 0x6EFF, 0xD8BC, 0x6F2B, + 0xD8BD, 0x7063, 0xD8BE, 0x779E, 0xD8BF, 0x842C, 0xD8C0, 0x8513, 0xD8C1, 0x883B, 0xD8C2, 0x8F13, 0xD8C3, 0x9945, 0xD8C4, 0x9C3B, + 0xD8C5, 0x551C, 0xD8C6, 0x62B9, 0xD8C7, 0x672B, 0xD8C8, 0x6CAB, 0xD8C9, 0x8309, 0xD8CA, 0x896A, 0xD8CB, 0x977A, 0xD8CC, 0x4EA1, + 0xD8CD, 0x5984, 0xD8CE, 0x5FD8, 0xD8CF, 0x5FD9, 0xD8D0, 0x671B, 0xD8D1, 0x7DB2, 0xD8D2, 0x7F54, 0xD8D3, 0x8292, 0xD8D4, 0x832B, + 0xD8D5, 0x83BD, 0xD8D6, 0x8F1E, 0xD8D7, 0x9099, 0xD8D8, 0x57CB, 0xD8D9, 0x59B9, 0xD8DA, 0x5A92, 0xD8DB, 0x5BD0, 0xD8DC, 0x6627, + 0xD8DD, 0x679A, 0xD8DE, 0x6885, 0xD8DF, 0x6BCF, 0xD8E0, 0x7164, 0xD8E1, 0x7F75, 0xD8E2, 0x8CB7, 0xD8E3, 0x8CE3, 0xD8E4, 0x9081, + 0xD8E5, 0x9B45, 0xD8E6, 0x8108, 0xD8E7, 0x8C8A, 0xD8E8, 0x964C, 0xD8E9, 0x9A40, 0xD8EA, 0x9EA5, 0xD8EB, 0x5B5F, 0xD8EC, 0x6C13, + 0xD8ED, 0x731B, 0xD8EE, 0x76F2, 0xD8EF, 0x76DF, 0xD8F0, 0x840C, 0xD8F1, 0x51AA, 0xD8F2, 0x8993, 0xD8F3, 0x514D, 0xD8F4, 0x5195, + 0xD8F5, 0x52C9, 0xD8F6, 0x68C9, 0xD8F7, 0x6C94, 0xD8F8, 0x7704, 0xD8F9, 0x7720, 0xD8FA, 0x7DBF, 0xD8FB, 0x7DEC, 0xD8FC, 0x9762, + 0xD8FD, 0x9EB5, 0xD8FE, 0x6EC5, 0xD9A1, 0x8511, 0xD9A2, 0x51A5, 0xD9A3, 0x540D, 0xD9A4, 0x547D, 0xD9A5, 0x660E, 0xD9A6, 0x669D, + 0xD9A7, 0x6927, 0xD9A8, 0x6E9F, 0xD9A9, 0x76BF, 0xD9AA, 0x7791, 0xD9AB, 0x8317, 0xD9AC, 0x84C2, 0xD9AD, 0x879F, 0xD9AE, 0x9169, + 0xD9AF, 0x9298, 0xD9B0, 0x9CF4, 0xD9B1, 0x8882, 0xD9B2, 0x4FAE, 0xD9B3, 0x5192, 0xD9B4, 0x52DF, 0xD9B5, 0x59C6, 0xD9B6, 0x5E3D, + 0xD9B7, 0x6155, 0xD9B8, 0x6478, 0xD9B9, 0x6479, 0xD9BA, 0x66AE, 0xD9BB, 0x67D0, 0xD9BC, 0x6A21, 0xD9BD, 0x6BCD, 0xD9BE, 0x6BDB, + 0xD9BF, 0x725F, 0xD9C0, 0x7261, 0xD9C1, 0x7441, 0xD9C2, 0x7738, 0xD9C3, 0x77DB, 0xD9C4, 0x8017, 0xD9C5, 0x82BC, 0xD9C6, 0x8305, + 0xD9C7, 0x8B00, 0xD9C8, 0x8B28, 0xD9C9, 0x8C8C, 0xD9CA, 0x6728, 0xD9CB, 0x6C90, 0xD9CC, 0x7267, 0xD9CD, 0x76EE, 0xD9CE, 0x7766, + 0xD9CF, 0x7A46, 0xD9D0, 0x9DA9, 0xD9D1, 0x6B7F, 0xD9D2, 0x6C92, 0xD9D3, 0x5922, 0xD9D4, 0x6726, 0xD9D5, 0x8499, 0xD9D6, 0x536F, + 0xD9D7, 0x5893, 0xD9D8, 0x5999, 0xD9D9, 0x5EDF, 0xD9DA, 0x63CF, 0xD9DB, 0x6634, 0xD9DC, 0x6773, 0xD9DD, 0x6E3A, 0xD9DE, 0x732B, + 0xD9DF, 0x7AD7, 0xD9E0, 0x82D7, 0xD9E1, 0x9328, 0xD9E2, 0x52D9, 0xD9E3, 0x5DEB, 0xD9E4, 0x61AE, 0xD9E5, 0x61CB, 0xD9E6, 0x620A, + 0xD9E7, 0x62C7, 0xD9E8, 0x64AB, 0xD9E9, 0x65E0, 0xD9EA, 0x6959, 0xD9EB, 0x6B66, 0xD9EC, 0x6BCB, 0xD9ED, 0x7121, 0xD9EE, 0x73F7, + 0xD9EF, 0x755D, 0xD9F0, 0x7E46, 0xD9F1, 0x821E, 0xD9F2, 0x8302, 0xD9F3, 0x856A, 0xD9F4, 0x8AA3, 0xD9F5, 0x8CBF, 0xD9F6, 0x9727, + 0xD9F7, 0x9D61, 0xD9F8, 0x58A8, 0xD9F9, 0x9ED8, 0xD9FA, 0x5011, 0xD9FB, 0x520E, 0xD9FC, 0x543B, 0xD9FD, 0x554F, 0xD9FE, 0x6587, + 0xDAA1, 0x6C76, 0xDAA2, 0x7D0A, 0xDAA3, 0x7D0B, 0xDAA4, 0x805E, 0xDAA5, 0x868A, 0xDAA6, 0x9580, 0xDAA7, 0x96EF, 0xDAA8, 0x52FF, + 0xDAA9, 0x6C95, 0xDAAA, 0x7269, 0xDAAB, 0x5473, 0xDAAC, 0x5A9A, 0xDAAD, 0x5C3E, 0xDAAE, 0x5D4B, 0xDAAF, 0x5F4C, 0xDAB0, 0x5FAE, + 0xDAB1, 0x672A, 0xDAB2, 0x68B6, 0xDAB3, 0x6963, 0xDAB4, 0x6E3C, 0xDAB5, 0x6E44, 0xDAB6, 0x7709, 0xDAB7, 0x7C73, 0xDAB8, 0x7F8E, + 0xDAB9, 0x8587, 0xDABA, 0x8B0E, 0xDABB, 0x8FF7, 0xDABC, 0x9761, 0xDABD, 0x9EF4, 0xDABE, 0x5CB7, 0xDABF, 0x60B6, 0xDAC0, 0x610D, + 0xDAC1, 0x61AB, 0xDAC2, 0x654F, 0xDAC3, 0x65FB, 0xDAC4, 0x65FC, 0xDAC5, 0x6C11, 0xDAC6, 0x6CEF, 0xDAC7, 0x739F, 0xDAC8, 0x73C9, + 0xDAC9, 0x7DE1, 0xDACA, 0x9594, 0xDACB, 0x5BC6, 0xDACC, 0x871C, 0xDACD, 0x8B10, 0xDACE, 0x525D, 0xDACF, 0x535A, 0xDAD0, 0x62CD, + 0xDAD1, 0x640F, 0xDAD2, 0x64B2, 0xDAD3, 0x6734, 0xDAD4, 0x6A38, 0xDAD5, 0x6CCA, 0xDAD6, 0x73C0, 0xDAD7, 0x749E, 0xDAD8, 0x7B94, + 0xDAD9, 0x7C95, 0xDADA, 0x7E1B, 0xDADB, 0x818A, 0xDADC, 0x8236, 0xDADD, 0x8584, 0xDADE, 0x8FEB, 0xDADF, 0x96F9, 0xDAE0, 0x99C1, + 0xDAE1, 0x4F34, 0xDAE2, 0x534A, 0xDAE3, 0x53CD, 0xDAE4, 0x53DB, 0xDAE5, 0x62CC, 0xDAE6, 0x642C, 0xDAE7, 0x6500, 0xDAE8, 0x6591, + 0xDAE9, 0x69C3, 0xDAEA, 0x6CEE, 0xDAEB, 0x6F58, 0xDAEC, 0x73ED, 0xDAED, 0x7554, 0xDAEE, 0x7622, 0xDAEF, 0x76E4, 0xDAF0, 0x76FC, + 0xDAF1, 0x78D0, 0xDAF2, 0x78FB, 0xDAF3, 0x792C, 0xDAF4, 0x7D46, 0xDAF5, 0x822C, 0xDAF6, 0x87E0, 0xDAF7, 0x8FD4, 0xDAF8, 0x9812, + 0xDAF9, 0x98EF, 0xDAFA, 0x52C3, 0xDAFB, 0x62D4, 0xDAFC, 0x64A5, 0xDAFD, 0x6E24, 0xDAFE, 0x6F51, 0xDBA1, 0x767C, 0xDBA2, 0x8DCB, + 0xDBA3, 0x91B1, 0xDBA4, 0x9262, 0xDBA5, 0x9AEE, 0xDBA6, 0x9B43, 0xDBA7, 0x5023, 0xDBA8, 0x508D, 0xDBA9, 0x574A, 0xDBAA, 0x59A8, + 0xDBAB, 0x5C28, 0xDBAC, 0x5E47, 0xDBAD, 0x5F77, 0xDBAE, 0x623F, 0xDBAF, 0x653E, 0xDBB0, 0x65B9, 0xDBB1, 0x65C1, 0xDBB2, 0x6609, + 0xDBB3, 0x678B, 0xDBB4, 0x699C, 0xDBB5, 0x6EC2, 0xDBB6, 0x78C5, 0xDBB7, 0x7D21, 0xDBB8, 0x80AA, 0xDBB9, 0x8180, 0xDBBA, 0x822B, + 0xDBBB, 0x82B3, 0xDBBC, 0x84A1, 0xDBBD, 0x868C, 0xDBBE, 0x8A2A, 0xDBBF, 0x8B17, 0xDBC0, 0x90A6, 0xDBC1, 0x9632, 0xDBC2, 0x9F90, + 0xDBC3, 0x500D, 0xDBC4, 0x4FF3, 0xDBC5, 0xF963, 0xDBC6, 0x57F9, 0xDBC7, 0x5F98, 0xDBC8, 0x62DC, 0xDBC9, 0x6392, 0xDBCA, 0x676F, + 0xDBCB, 0x6E43, 0xDBCC, 0x7119, 0xDBCD, 0x76C3, 0xDBCE, 0x80CC, 0xDBCF, 0x80DA, 0xDBD0, 0x88F4, 0xDBD1, 0x88F5, 0xDBD2, 0x8919, + 0xDBD3, 0x8CE0, 0xDBD4, 0x8F29, 0xDBD5, 0x914D, 0xDBD6, 0x966A, 0xDBD7, 0x4F2F, 0xDBD8, 0x4F70, 0xDBD9, 0x5E1B, 0xDBDA, 0x67CF, + 0xDBDB, 0x6822, 0xDBDC, 0x767D, 0xDBDD, 0x767E, 0xDBDE, 0x9B44, 0xDBDF, 0x5E61, 0xDBE0, 0x6A0A, 0xDBE1, 0x7169, 0xDBE2, 0x71D4, + 0xDBE3, 0x756A, 0xDBE4, 0xF964, 0xDBE5, 0x7E41, 0xDBE6, 0x8543, 0xDBE7, 0x85E9, 0xDBE8, 0x98DC, 0xDBE9, 0x4F10, 0xDBEA, 0x7B4F, + 0xDBEB, 0x7F70, 0xDBEC, 0x95A5, 0xDBED, 0x51E1, 0xDBEE, 0x5E06, 0xDBEF, 0x68B5, 0xDBF0, 0x6C3E, 0xDBF1, 0x6C4E, 0xDBF2, 0x6CDB, + 0xDBF3, 0x72AF, 0xDBF4, 0x7BC4, 0xDBF5, 0x8303, 0xDBF6, 0x6CD5, 0xDBF7, 0x743A, 0xDBF8, 0x50FB, 0xDBF9, 0x5288, 0xDBFA, 0x58C1, + 0xDBFB, 0x64D8, 0xDBFC, 0x6A97, 0xDBFD, 0x74A7, 0xDBFE, 0x7656, 0xDCA1, 0x78A7, 0xDCA2, 0x8617, 0xDCA3, 0x95E2, 0xDCA4, 0x9739, + 0xDCA5, 0xF965, 0xDCA6, 0x535E, 0xDCA7, 0x5F01, 0xDCA8, 0x8B8A, 0xDCA9, 0x8FA8, 0xDCAA, 0x8FAF, 0xDCAB, 0x908A, 0xDCAC, 0x5225, + 0xDCAD, 0x77A5, 0xDCAE, 0x9C49, 0xDCAF, 0x9F08, 0xDCB0, 0x4E19, 0xDCB1, 0x5002, 0xDCB2, 0x5175, 0xDCB3, 0x5C5B, 0xDCB4, 0x5E77, + 0xDCB5, 0x661E, 0xDCB6, 0x663A, 0xDCB7, 0x67C4, 0xDCB8, 0x68C5, 0xDCB9, 0x70B3, 0xDCBA, 0x7501, 0xDCBB, 0x75C5, 0xDCBC, 0x79C9, + 0xDCBD, 0x7ADD, 0xDCBE, 0x8F27, 0xDCBF, 0x9920, 0xDCC0, 0x9A08, 0xDCC1, 0x4FDD, 0xDCC2, 0x5821, 0xDCC3, 0x5831, 0xDCC4, 0x5BF6, + 0xDCC5, 0x666E, 0xDCC6, 0x6B65, 0xDCC7, 0x6D11, 0xDCC8, 0x6E7A, 0xDCC9, 0x6F7D, 0xDCCA, 0x73E4, 0xDCCB, 0x752B, 0xDCCC, 0x83E9, + 0xDCCD, 0x88DC, 0xDCCE, 0x8913, 0xDCCF, 0x8B5C, 0xDCD0, 0x8F14, 0xDCD1, 0x4F0F, 0xDCD2, 0x50D5, 0xDCD3, 0x5310, 0xDCD4, 0x535C, + 0xDCD5, 0x5B93, 0xDCD6, 0x5FA9, 0xDCD7, 0x670D, 0xDCD8, 0x798F, 0xDCD9, 0x8179, 0xDCDA, 0x832F, 0xDCDB, 0x8514, 0xDCDC, 0x8907, + 0xDCDD, 0x8986, 0xDCDE, 0x8F39, 0xDCDF, 0x8F3B, 0xDCE0, 0x99A5, 0xDCE1, 0x9C12, 0xDCE2, 0x672C, 0xDCE3, 0x4E76, 0xDCE4, 0x4FF8, + 0xDCE5, 0x5949, 0xDCE6, 0x5C01, 0xDCE7, 0x5CEF, 0xDCE8, 0x5CF0, 0xDCE9, 0x6367, 0xDCEA, 0x68D2, 0xDCEB, 0x70FD, 0xDCEC, 0x71A2, + 0xDCED, 0x742B, 0xDCEE, 0x7E2B, 0xDCEF, 0x84EC, 0xDCF0, 0x8702, 0xDCF1, 0x9022, 0xDCF2, 0x92D2, 0xDCF3, 0x9CF3, 0xDCF4, 0x4E0D, + 0xDCF5, 0x4ED8, 0xDCF6, 0x4FEF, 0xDCF7, 0x5085, 0xDCF8, 0x5256, 0xDCF9, 0x526F, 0xDCFA, 0x5426, 0xDCFB, 0x5490, 0xDCFC, 0x57E0, + 0xDCFD, 0x592B, 0xDCFE, 0x5A66, 0xDDA1, 0x5B5A, 0xDDA2, 0x5B75, 0xDDA3, 0x5BCC, 0xDDA4, 0x5E9C, 0xDDA5, 0xF966, 0xDDA6, 0x6276, + 0xDDA7, 0x6577, 0xDDA8, 0x65A7, 0xDDA9, 0x6D6E, 0xDDAA, 0x6EA5, 0xDDAB, 0x7236, 0xDDAC, 0x7B26, 0xDDAD, 0x7C3F, 0xDDAE, 0x7F36, + 0xDDAF, 0x8150, 0xDDB0, 0x8151, 0xDDB1, 0x819A, 0xDDB2, 0x8240, 0xDDB3, 0x8299, 0xDDB4, 0x83A9, 0xDDB5, 0x8A03, 0xDDB6, 0x8CA0, + 0xDDB7, 0x8CE6, 0xDDB8, 0x8CFB, 0xDDB9, 0x8D74, 0xDDBA, 0x8DBA, 0xDDBB, 0x90E8, 0xDDBC, 0x91DC, 0xDDBD, 0x961C, 0xDDBE, 0x9644, + 0xDDBF, 0x99D9, 0xDDC0, 0x9CE7, 0xDDC1, 0x5317, 0xDDC2, 0x5206, 0xDDC3, 0x5429, 0xDDC4, 0x5674, 0xDDC5, 0x58B3, 0xDDC6, 0x5954, + 0xDDC7, 0x596E, 0xDDC8, 0x5FFF, 0xDDC9, 0x61A4, 0xDDCA, 0x626E, 0xDDCB, 0x6610, 0xDDCC, 0x6C7E, 0xDDCD, 0x711A, 0xDDCE, 0x76C6, + 0xDDCF, 0x7C89, 0xDDD0, 0x7CDE, 0xDDD1, 0x7D1B, 0xDDD2, 0x82AC, 0xDDD3, 0x8CC1, 0xDDD4, 0x96F0, 0xDDD5, 0xF967, 0xDDD6, 0x4F5B, + 0xDDD7, 0x5F17, 0xDDD8, 0x5F7F, 0xDDD9, 0x62C2, 0xDDDA, 0x5D29, 0xDDDB, 0x670B, 0xDDDC, 0x68DA, 0xDDDD, 0x787C, 0xDDDE, 0x7E43, + 0xDDDF, 0x9D6C, 0xDDE0, 0x4E15, 0xDDE1, 0x5099, 0xDDE2, 0x5315, 0xDDE3, 0x532A, 0xDDE4, 0x5351, 0xDDE5, 0x5983, 0xDDE6, 0x5A62, + 0xDDE7, 0x5E87, 0xDDE8, 0x60B2, 0xDDE9, 0x618A, 0xDDEA, 0x6249, 0xDDEB, 0x6279, 0xDDEC, 0x6590, 0xDDED, 0x6787, 0xDDEE, 0x69A7, + 0xDDEF, 0x6BD4, 0xDDF0, 0x6BD6, 0xDDF1, 0x6BD7, 0xDDF2, 0x6BD8, 0xDDF3, 0x6CB8, 0xDDF4, 0xF968, 0xDDF5, 0x7435, 0xDDF6, 0x75FA, + 0xDDF7, 0x7812, 0xDDF8, 0x7891, 0xDDF9, 0x79D5, 0xDDFA, 0x79D8, 0xDDFB, 0x7C83, 0xDDFC, 0x7DCB, 0xDDFD, 0x7FE1, 0xDDFE, 0x80A5, + 0xDEA1, 0x813E, 0xDEA2, 0x81C2, 0xDEA3, 0x83F2, 0xDEA4, 0x871A, 0xDEA5, 0x88E8, 0xDEA6, 0x8AB9, 0xDEA7, 0x8B6C, 0xDEA8, 0x8CBB, + 0xDEA9, 0x9119, 0xDEAA, 0x975E, 0xDEAB, 0x98DB, 0xDEAC, 0x9F3B, 0xDEAD, 0x56AC, 0xDEAE, 0x5B2A, 0xDEAF, 0x5F6C, 0xDEB0, 0x658C, + 0xDEB1, 0x6AB3, 0xDEB2, 0x6BAF, 0xDEB3, 0x6D5C, 0xDEB4, 0x6FF1, 0xDEB5, 0x7015, 0xDEB6, 0x725D, 0xDEB7, 0x73AD, 0xDEB8, 0x8CA7, + 0xDEB9, 0x8CD3, 0xDEBA, 0x983B, 0xDEBB, 0x6191, 0xDEBC, 0x6C37, 0xDEBD, 0x8058, 0xDEBE, 0x9A01, 0xDEBF, 0x4E4D, 0xDEC0, 0x4E8B, + 0xDEC1, 0x4E9B, 0xDEC2, 0x4ED5, 0xDEC3, 0x4F3A, 0xDEC4, 0x4F3C, 0xDEC5, 0x4F7F, 0xDEC6, 0x4FDF, 0xDEC7, 0x50FF, 0xDEC8, 0x53F2, + 0xDEC9, 0x53F8, 0xDECA, 0x5506, 0xDECB, 0x55E3, 0xDECC, 0x56DB, 0xDECD, 0x58EB, 0xDECE, 0x5962, 0xDECF, 0x5A11, 0xDED0, 0x5BEB, + 0xDED1, 0x5BFA, 0xDED2, 0x5C04, 0xDED3, 0x5DF3, 0xDED4, 0x5E2B, 0xDED5, 0x5F99, 0xDED6, 0x601D, 0xDED7, 0x6368, 0xDED8, 0x659C, + 0xDED9, 0x65AF, 0xDEDA, 0x67F6, 0xDEDB, 0x67FB, 0xDEDC, 0x68AD, 0xDEDD, 0x6B7B, 0xDEDE, 0x6C99, 0xDEDF, 0x6CD7, 0xDEE0, 0x6E23, + 0xDEE1, 0x7009, 0xDEE2, 0x7345, 0xDEE3, 0x7802, 0xDEE4, 0x793E, 0xDEE5, 0x7940, 0xDEE6, 0x7960, 0xDEE7, 0x79C1, 0xDEE8, 0x7BE9, + 0xDEE9, 0x7D17, 0xDEEA, 0x7D72, 0xDEEB, 0x8086, 0xDEEC, 0x820D, 0xDEED, 0x838E, 0xDEEE, 0x84D1, 0xDEEF, 0x86C7, 0xDEF0, 0x88DF, + 0xDEF1, 0x8A50, 0xDEF2, 0x8A5E, 0xDEF3, 0x8B1D, 0xDEF4, 0x8CDC, 0xDEF5, 0x8D66, 0xDEF6, 0x8FAD, 0xDEF7, 0x90AA, 0xDEF8, 0x98FC, + 0xDEF9, 0x99DF, 0xDEFA, 0x9E9D, 0xDEFB, 0x524A, 0xDEFC, 0xF969, 0xDEFD, 0x6714, 0xDEFE, 0xF96A, 0xDFA1, 0x5098, 0xDFA2, 0x522A, + 0xDFA3, 0x5C71, 0xDFA4, 0x6563, 0xDFA5, 0x6C55, 0xDFA6, 0x73CA, 0xDFA7, 0x7523, 0xDFA8, 0x759D, 0xDFA9, 0x7B97, 0xDFAA, 0x849C, + 0xDFAB, 0x9178, 0xDFAC, 0x9730, 0xDFAD, 0x4E77, 0xDFAE, 0x6492, 0xDFAF, 0x6BBA, 0xDFB0, 0x715E, 0xDFB1, 0x85A9, 0xDFB2, 0x4E09, + 0xDFB3, 0xF96B, 0xDFB4, 0x6749, 0xDFB5, 0x68EE, 0xDFB6, 0x6E17, 0xDFB7, 0x829F, 0xDFB8, 0x8518, 0xDFB9, 0x886B, 0xDFBA, 0x63F7, + 0xDFBB, 0x6F81, 0xDFBC, 0x9212, 0xDFBD, 0x98AF, 0xDFBE, 0x4E0A, 0xDFBF, 0x50B7, 0xDFC0, 0x50CF, 0xDFC1, 0x511F, 0xDFC2, 0x5546, + 0xDFC3, 0x55AA, 0xDFC4, 0x5617, 0xDFC5, 0x5B40, 0xDFC6, 0x5C19, 0xDFC7, 0x5CE0, 0xDFC8, 0x5E38, 0xDFC9, 0x5E8A, 0xDFCA, 0x5EA0, + 0xDFCB, 0x5EC2, 0xDFCC, 0x60F3, 0xDFCD, 0x6851, 0xDFCE, 0x6A61, 0xDFCF, 0x6E58, 0xDFD0, 0x723D, 0xDFD1, 0x7240, 0xDFD2, 0x72C0, + 0xDFD3, 0x76F8, 0xDFD4, 0x7965, 0xDFD5, 0x7BB1, 0xDFD6, 0x7FD4, 0xDFD7, 0x88F3, 0xDFD8, 0x89F4, 0xDFD9, 0x8A73, 0xDFDA, 0x8C61, + 0xDFDB, 0x8CDE, 0xDFDC, 0x971C, 0xDFDD, 0x585E, 0xDFDE, 0x74BD, 0xDFDF, 0x8CFD, 0xDFE0, 0x55C7, 0xDFE1, 0xF96C, 0xDFE2, 0x7A61, + 0xDFE3, 0x7D22, 0xDFE4, 0x8272, 0xDFE5, 0x7272, 0xDFE6, 0x751F, 0xDFE7, 0x7525, 0xDFE8, 0xF96D, 0xDFE9, 0x7B19, 0xDFEA, 0x5885, + 0xDFEB, 0x58FB, 0xDFEC, 0x5DBC, 0xDFED, 0x5E8F, 0xDFEE, 0x5EB6, 0xDFEF, 0x5F90, 0xDFF0, 0x6055, 0xDFF1, 0x6292, 0xDFF2, 0x637F, + 0xDFF3, 0x654D, 0xDFF4, 0x6691, 0xDFF5, 0x66D9, 0xDFF6, 0x66F8, 0xDFF7, 0x6816, 0xDFF8, 0x68F2, 0xDFF9, 0x7280, 0xDFFA, 0x745E, + 0xDFFB, 0x7B6E, 0xDFFC, 0x7D6E, 0xDFFD, 0x7DD6, 0xDFFE, 0x7F72, 0xE0A1, 0x80E5, 0xE0A2, 0x8212, 0xE0A3, 0x85AF, 0xE0A4, 0x897F, + 0xE0A5, 0x8A93, 0xE0A6, 0x901D, 0xE0A7, 0x92E4, 0xE0A8, 0x9ECD, 0xE0A9, 0x9F20, 0xE0AA, 0x5915, 0xE0AB, 0x596D, 0xE0AC, 0x5E2D, + 0xE0AD, 0x60DC, 0xE0AE, 0x6614, 0xE0AF, 0x6673, 0xE0B0, 0x6790, 0xE0B1, 0x6C50, 0xE0B2, 0x6DC5, 0xE0B3, 0x6F5F, 0xE0B4, 0x77F3, + 0xE0B5, 0x78A9, 0xE0B6, 0x84C6, 0xE0B7, 0x91CB, 0xE0B8, 0x932B, 0xE0B9, 0x4ED9, 0xE0BA, 0x50CA, 0xE0BB, 0x5148, 0xE0BC, 0x5584, + 0xE0BD, 0x5B0B, 0xE0BE, 0x5BA3, 0xE0BF, 0x6247, 0xE0C0, 0x657E, 0xE0C1, 0x65CB, 0xE0C2, 0x6E32, 0xE0C3, 0x717D, 0xE0C4, 0x7401, + 0xE0C5, 0x7444, 0xE0C6, 0x7487, 0xE0C7, 0x74BF, 0xE0C8, 0x766C, 0xE0C9, 0x79AA, 0xE0CA, 0x7DDA, 0xE0CB, 0x7E55, 0xE0CC, 0x7FA8, + 0xE0CD, 0x817A, 0xE0CE, 0x81B3, 0xE0CF, 0x8239, 0xE0D0, 0x861A, 0xE0D1, 0x87EC, 0xE0D2, 0x8A75, 0xE0D3, 0x8DE3, 0xE0D4, 0x9078, + 0xE0D5, 0x9291, 0xE0D6, 0x9425, 0xE0D7, 0x994D, 0xE0D8, 0x9BAE, 0xE0D9, 0x5368, 0xE0DA, 0x5C51, 0xE0DB, 0x6954, 0xE0DC, 0x6CC4, + 0xE0DD, 0x6D29, 0xE0DE, 0x6E2B, 0xE0DF, 0x820C, 0xE0E0, 0x859B, 0xE0E1, 0x893B, 0xE0E2, 0x8A2D, 0xE0E3, 0x8AAA, 0xE0E4, 0x96EA, + 0xE0E5, 0x9F67, 0xE0E6, 0x5261, 0xE0E7, 0x66B9, 0xE0E8, 0x6BB2, 0xE0E9, 0x7E96, 0xE0EA, 0x87FE, 0xE0EB, 0x8D0D, 0xE0EC, 0x9583, + 0xE0ED, 0x965D, 0xE0EE, 0x651D, 0xE0EF, 0x6D89, 0xE0F0, 0x71EE, 0xE0F1, 0xF96E, 0xE0F2, 0x57CE, 0xE0F3, 0x59D3, 0xE0F4, 0x5BAC, + 0xE0F5, 0x6027, 0xE0F6, 0x60FA, 0xE0F7, 0x6210, 0xE0F8, 0x661F, 0xE0F9, 0x665F, 0xE0FA, 0x7329, 0xE0FB, 0x73F9, 0xE0FC, 0x76DB, + 0xE0FD, 0x7701, 0xE0FE, 0x7B6C, 0xE1A1, 0x8056, 0xE1A2, 0x8072, 0xE1A3, 0x8165, 0xE1A4, 0x8AA0, 0xE1A5, 0x9192, 0xE1A6, 0x4E16, + 0xE1A7, 0x52E2, 0xE1A8, 0x6B72, 0xE1A9, 0x6D17, 0xE1AA, 0x7A05, 0xE1AB, 0x7B39, 0xE1AC, 0x7D30, 0xE1AD, 0xF96F, 0xE1AE, 0x8CB0, + 0xE1AF, 0x53EC, 0xE1B0, 0x562F, 0xE1B1, 0x5851, 0xE1B2, 0x5BB5, 0xE1B3, 0x5C0F, 0xE1B4, 0x5C11, 0xE1B5, 0x5DE2, 0xE1B6, 0x6240, + 0xE1B7, 0x6383, 0xE1B8, 0x6414, 0xE1B9, 0x662D, 0xE1BA, 0x68B3, 0xE1BB, 0x6CBC, 0xE1BC, 0x6D88, 0xE1BD, 0x6EAF, 0xE1BE, 0x701F, + 0xE1BF, 0x70A4, 0xE1C0, 0x71D2, 0xE1C1, 0x7526, 0xE1C2, 0x758F, 0xE1C3, 0x758E, 0xE1C4, 0x7619, 0xE1C5, 0x7B11, 0xE1C6, 0x7BE0, + 0xE1C7, 0x7C2B, 0xE1C8, 0x7D20, 0xE1C9, 0x7D39, 0xE1CA, 0x852C, 0xE1CB, 0x856D, 0xE1CC, 0x8607, 0xE1CD, 0x8A34, 0xE1CE, 0x900D, + 0xE1CF, 0x9061, 0xE1D0, 0x90B5, 0xE1D1, 0x92B7, 0xE1D2, 0x97F6, 0xE1D3, 0x9A37, 0xE1D4, 0x4FD7, 0xE1D5, 0x5C6C, 0xE1D6, 0x675F, + 0xE1D7, 0x6D91, 0xE1D8, 0x7C9F, 0xE1D9, 0x7E8C, 0xE1DA, 0x8B16, 0xE1DB, 0x8D16, 0xE1DC, 0x901F, 0xE1DD, 0x5B6B, 0xE1DE, 0x5DFD, + 0xE1DF, 0x640D, 0xE1E0, 0x84C0, 0xE1E1, 0x905C, 0xE1E2, 0x98E1, 0xE1E3, 0x7387, 0xE1E4, 0x5B8B, 0xE1E5, 0x609A, 0xE1E6, 0x677E, + 0xE1E7, 0x6DDE, 0xE1E8, 0x8A1F, 0xE1E9, 0x8AA6, 0xE1EA, 0x9001, 0xE1EB, 0x980C, 0xE1EC, 0x5237, 0xE1ED, 0xF970, 0xE1EE, 0x7051, + 0xE1EF, 0x788E, 0xE1F0, 0x9396, 0xE1F1, 0x8870, 0xE1F2, 0x91D7, 0xE1F3, 0x4FEE, 0xE1F4, 0x53D7, 0xE1F5, 0x55FD, 0xE1F6, 0x56DA, + 0xE1F7, 0x5782, 0xE1F8, 0x58FD, 0xE1F9, 0x5AC2, 0xE1FA, 0x5B88, 0xE1FB, 0x5CAB, 0xE1FC, 0x5CC0, 0xE1FD, 0x5E25, 0xE1FE, 0x6101, + 0xE2A1, 0x620D, 0xE2A2, 0x624B, 0xE2A3, 0x6388, 0xE2A4, 0x641C, 0xE2A5, 0x6536, 0xE2A6, 0x6578, 0xE2A7, 0x6A39, 0xE2A8, 0x6B8A, + 0xE2A9, 0x6C34, 0xE2AA, 0x6D19, 0xE2AB, 0x6F31, 0xE2AC, 0x71E7, 0xE2AD, 0x72E9, 0xE2AE, 0x7378, 0xE2AF, 0x7407, 0xE2B0, 0x74B2, + 0xE2B1, 0x7626, 0xE2B2, 0x7761, 0xE2B3, 0x79C0, 0xE2B4, 0x7A57, 0xE2B5, 0x7AEA, 0xE2B6, 0x7CB9, 0xE2B7, 0x7D8F, 0xE2B8, 0x7DAC, + 0xE2B9, 0x7E61, 0xE2BA, 0x7F9E, 0xE2BB, 0x8129, 0xE2BC, 0x8331, 0xE2BD, 0x8490, 0xE2BE, 0x84DA, 0xE2BF, 0x85EA, 0xE2C0, 0x8896, + 0xE2C1, 0x8AB0, 0xE2C2, 0x8B90, 0xE2C3, 0x8F38, 0xE2C4, 0x9042, 0xE2C5, 0x9083, 0xE2C6, 0x916C, 0xE2C7, 0x9296, 0xE2C8, 0x92B9, + 0xE2C9, 0x968B, 0xE2CA, 0x96A7, 0xE2CB, 0x96A8, 0xE2CC, 0x96D6, 0xE2CD, 0x9700, 0xE2CE, 0x9808, 0xE2CF, 0x9996, 0xE2D0, 0x9AD3, + 0xE2D1, 0x9B1A, 0xE2D2, 0x53D4, 0xE2D3, 0x587E, 0xE2D4, 0x5919, 0xE2D5, 0x5B70, 0xE2D6, 0x5BBF, 0xE2D7, 0x6DD1, 0xE2D8, 0x6F5A, + 0xE2D9, 0x719F, 0xE2DA, 0x7421, 0xE2DB, 0x74B9, 0xE2DC, 0x8085, 0xE2DD, 0x83FD, 0xE2DE, 0x5DE1, 0xE2DF, 0x5F87, 0xE2E0, 0x5FAA, + 0xE2E1, 0x6042, 0xE2E2, 0x65EC, 0xE2E3, 0x6812, 0xE2E4, 0x696F, 0xE2E5, 0x6A53, 0xE2E6, 0x6B89, 0xE2E7, 0x6D35, 0xE2E8, 0x6DF3, + 0xE2E9, 0x73E3, 0xE2EA, 0x76FE, 0xE2EB, 0x77AC, 0xE2EC, 0x7B4D, 0xE2ED, 0x7D14, 0xE2EE, 0x8123, 0xE2EF, 0x821C, 0xE2F0, 0x8340, + 0xE2F1, 0x84F4, 0xE2F2, 0x8563, 0xE2F3, 0x8A62, 0xE2F4, 0x8AC4, 0xE2F5, 0x9187, 0xE2F6, 0x931E, 0xE2F7, 0x9806, 0xE2F8, 0x99B4, + 0xE2F9, 0x620C, 0xE2FA, 0x8853, 0xE2FB, 0x8FF0, 0xE2FC, 0x9265, 0xE2FD, 0x5D07, 0xE2FE, 0x5D27, 0xE3A1, 0x5D69, 0xE3A2, 0x745F, + 0xE3A3, 0x819D, 0xE3A4, 0x8768, 0xE3A5, 0x6FD5, 0xE3A6, 0x62FE, 0xE3A7, 0x7FD2, 0xE3A8, 0x8936, 0xE3A9, 0x8972, 0xE3AA, 0x4E1E, + 0xE3AB, 0x4E58, 0xE3AC, 0x50E7, 0xE3AD, 0x52DD, 0xE3AE, 0x5347, 0xE3AF, 0x627F, 0xE3B0, 0x6607, 0xE3B1, 0x7E69, 0xE3B2, 0x8805, + 0xE3B3, 0x965E, 0xE3B4, 0x4F8D, 0xE3B5, 0x5319, 0xE3B6, 0x5636, 0xE3B7, 0x59CB, 0xE3B8, 0x5AA4, 0xE3B9, 0x5C38, 0xE3BA, 0x5C4E, + 0xE3BB, 0x5C4D, 0xE3BC, 0x5E02, 0xE3BD, 0x5F11, 0xE3BE, 0x6043, 0xE3BF, 0x65BD, 0xE3C0, 0x662F, 0xE3C1, 0x6642, 0xE3C2, 0x67BE, + 0xE3C3, 0x67F4, 0xE3C4, 0x731C, 0xE3C5, 0x77E2, 0xE3C6, 0x793A, 0xE3C7, 0x7FC5, 0xE3C8, 0x8494, 0xE3C9, 0x84CD, 0xE3CA, 0x8996, + 0xE3CB, 0x8A66, 0xE3CC, 0x8A69, 0xE3CD, 0x8AE1, 0xE3CE, 0x8C55, 0xE3CF, 0x8C7A, 0xE3D0, 0x57F4, 0xE3D1, 0x5BD4, 0xE3D2, 0x5F0F, + 0xE3D3, 0x606F, 0xE3D4, 0x62ED, 0xE3D5, 0x690D, 0xE3D6, 0x6B96, 0xE3D7, 0x6E5C, 0xE3D8, 0x7184, 0xE3D9, 0x7BD2, 0xE3DA, 0x8755, + 0xE3DB, 0x8B58, 0xE3DC, 0x8EFE, 0xE3DD, 0x98DF, 0xE3DE, 0x98FE, 0xE3DF, 0x4F38, 0xE3E0, 0x4F81, 0xE3E1, 0x4FE1, 0xE3E2, 0x547B, + 0xE3E3, 0x5A20, 0xE3E4, 0x5BB8, 0xE3E5, 0x613C, 0xE3E6, 0x65B0, 0xE3E7, 0x6668, 0xE3E8, 0x71FC, 0xE3E9, 0x7533, 0xE3EA, 0x795E, + 0xE3EB, 0x7D33, 0xE3EC, 0x814E, 0xE3ED, 0x81E3, 0xE3EE, 0x8398, 0xE3EF, 0x85AA, 0xE3F0, 0x85CE, 0xE3F1, 0x8703, 0xE3F2, 0x8A0A, + 0xE3F3, 0x8EAB, 0xE3F4, 0x8F9B, 0xE3F5, 0xF971, 0xE3F6, 0x8FC5, 0xE3F7, 0x5931, 0xE3F8, 0x5BA4, 0xE3F9, 0x5BE6, 0xE3FA, 0x6089, + 0xE3FB, 0x5BE9, 0xE3FC, 0x5C0B, 0xE3FD, 0x5FC3, 0xE3FE, 0x6C81, 0xE4A1, 0xF972, 0xE4A2, 0x6DF1, 0xE4A3, 0x700B, 0xE4A4, 0x751A, + 0xE4A5, 0x82AF, 0xE4A6, 0x8AF6, 0xE4A7, 0x4EC0, 0xE4A8, 0x5341, 0xE4A9, 0xF973, 0xE4AA, 0x96D9, 0xE4AB, 0x6C0F, 0xE4AC, 0x4E9E, + 0xE4AD, 0x4FC4, 0xE4AE, 0x5152, 0xE4AF, 0x555E, 0xE4B0, 0x5A25, 0xE4B1, 0x5CE8, 0xE4B2, 0x6211, 0xE4B3, 0x7259, 0xE4B4, 0x82BD, + 0xE4B5, 0x83AA, 0xE4B6, 0x86FE, 0xE4B7, 0x8859, 0xE4B8, 0x8A1D, 0xE4B9, 0x963F, 0xE4BA, 0x96C5, 0xE4BB, 0x9913, 0xE4BC, 0x9D09, + 0xE4BD, 0x9D5D, 0xE4BE, 0x580A, 0xE4BF, 0x5CB3, 0xE4C0, 0x5DBD, 0xE4C1, 0x5E44, 0xE4C2, 0x60E1, 0xE4C3, 0x6115, 0xE4C4, 0x63E1, + 0xE4C5, 0x6A02, 0xE4C6, 0x6E25, 0xE4C7, 0x9102, 0xE4C8, 0x9354, 0xE4C9, 0x984E, 0xE4CA, 0x9C10, 0xE4CB, 0x9F77, 0xE4CC, 0x5B89, + 0xE4CD, 0x5CB8, 0xE4CE, 0x6309, 0xE4CF, 0x664F, 0xE4D0, 0x6848, 0xE4D1, 0x773C, 0xE4D2, 0x96C1, 0xE4D3, 0x978D, 0xE4D4, 0x9854, + 0xE4D5, 0x9B9F, 0xE4D6, 0x65A1, 0xE4D7, 0x8B01, 0xE4D8, 0x8ECB, 0xE4D9, 0x95BC, 0xE4DA, 0x5535, 0xE4DB, 0x5CA9, 0xE4DC, 0x5DD6, + 0xE4DD, 0x5EB5, 0xE4DE, 0x6697, 0xE4DF, 0x764C, 0xE4E0, 0x83F4, 0xE4E1, 0x95C7, 0xE4E2, 0x58D3, 0xE4E3, 0x62BC, 0xE4E4, 0x72CE, + 0xE4E5, 0x9D28, 0xE4E6, 0x4EF0, 0xE4E7, 0x592E, 0xE4E8, 0x600F, 0xE4E9, 0x663B, 0xE4EA, 0x6B83, 0xE4EB, 0x79E7, 0xE4EC, 0x9D26, + 0xE4ED, 0x5393, 0xE4EE, 0x54C0, 0xE4EF, 0x57C3, 0xE4F0, 0x5D16, 0xE4F1, 0x611B, 0xE4F2, 0x66D6, 0xE4F3, 0x6DAF, 0xE4F4, 0x788D, + 0xE4F5, 0x827E, 0xE4F6, 0x9698, 0xE4F7, 0x9744, 0xE4F8, 0x5384, 0xE4F9, 0x627C, 0xE4FA, 0x6396, 0xE4FB, 0x6DB2, 0xE4FC, 0x7E0A, + 0xE4FD, 0x814B, 0xE4FE, 0x984D, 0xE5A1, 0x6AFB, 0xE5A2, 0x7F4C, 0xE5A3, 0x9DAF, 0xE5A4, 0x9E1A, 0xE5A5, 0x4E5F, 0xE5A6, 0x503B, + 0xE5A7, 0x51B6, 0xE5A8, 0x591C, 0xE5A9, 0x60F9, 0xE5AA, 0x63F6, 0xE5AB, 0x6930, 0xE5AC, 0x723A, 0xE5AD, 0x8036, 0xE5AE, 0xF974, + 0xE5AF, 0x91CE, 0xE5B0, 0x5F31, 0xE5B1, 0xF975, 0xE5B2, 0xF976, 0xE5B3, 0x7D04, 0xE5B4, 0x82E5, 0xE5B5, 0x846F, 0xE5B6, 0x84BB, + 0xE5B7, 0x85E5, 0xE5B8, 0x8E8D, 0xE5B9, 0xF977, 0xE5BA, 0x4F6F, 0xE5BB, 0xF978, 0xE5BC, 0xF979, 0xE5BD, 0x58E4, 0xE5BE, 0x5B43, + 0xE5BF, 0x6059, 0xE5C0, 0x63DA, 0xE5C1, 0x6518, 0xE5C2, 0x656D, 0xE5C3, 0x6698, 0xE5C4, 0xF97A, 0xE5C5, 0x694A, 0xE5C6, 0x6A23, + 0xE5C7, 0x6D0B, 0xE5C8, 0x7001, 0xE5C9, 0x716C, 0xE5CA, 0x75D2, 0xE5CB, 0x760D, 0xE5CC, 0x79B3, 0xE5CD, 0x7A70, 0xE5CE, 0xF97B, + 0xE5CF, 0x7F8A, 0xE5D0, 0xF97C, 0xE5D1, 0x8944, 0xE5D2, 0xF97D, 0xE5D3, 0x8B93, 0xE5D4, 0x91C0, 0xE5D5, 0x967D, 0xE5D6, 0xF97E, + 0xE5D7, 0x990A, 0xE5D8, 0x5704, 0xE5D9, 0x5FA1, 0xE5DA, 0x65BC, 0xE5DB, 0x6F01, 0xE5DC, 0x7600, 0xE5DD, 0x79A6, 0xE5DE, 0x8A9E, + 0xE5DF, 0x99AD, 0xE5E0, 0x9B5A, 0xE5E1, 0x9F6C, 0xE5E2, 0x5104, 0xE5E3, 0x61B6, 0xE5E4, 0x6291, 0xE5E5, 0x6A8D, 0xE5E6, 0x81C6, + 0xE5E7, 0x5043, 0xE5E8, 0x5830, 0xE5E9, 0x5F66, 0xE5EA, 0x7109, 0xE5EB, 0x8A00, 0xE5EC, 0x8AFA, 0xE5ED, 0x5B7C, 0xE5EE, 0x8616, + 0xE5EF, 0x4FFA, 0xE5F0, 0x513C, 0xE5F1, 0x56B4, 0xE5F2, 0x5944, 0xE5F3, 0x63A9, 0xE5F4, 0x6DF9, 0xE5F5, 0x5DAA, 0xE5F6, 0x696D, + 0xE5F7, 0x5186, 0xE5F8, 0x4E88, 0xE5F9, 0x4F59, 0xE5FA, 0xF97F, 0xE5FB, 0xF980, 0xE5FC, 0xF981, 0xE5FD, 0x5982, 0xE5FE, 0xF982, + 0xE6A1, 0xF983, 0xE6A2, 0x6B5F, 0xE6A3, 0x6C5D, 0xE6A4, 0xF984, 0xE6A5, 0x74B5, 0xE6A6, 0x7916, 0xE6A7, 0xF985, 0xE6A8, 0x8207, + 0xE6A9, 0x8245, 0xE6AA, 0x8339, 0xE6AB, 0x8F3F, 0xE6AC, 0x8F5D, 0xE6AD, 0xF986, 0xE6AE, 0x9918, 0xE6AF, 0xF987, 0xE6B0, 0xF988, + 0xE6B1, 0xF989, 0xE6B2, 0x4EA6, 0xE6B3, 0xF98A, 0xE6B4, 0x57DF, 0xE6B5, 0x5F79, 0xE6B6, 0x6613, 0xE6B7, 0xF98B, 0xE6B8, 0xF98C, + 0xE6B9, 0x75AB, 0xE6BA, 0x7E79, 0xE6BB, 0x8B6F, 0xE6BC, 0xF98D, 0xE6BD, 0x9006, 0xE6BE, 0x9A5B, 0xE6BF, 0x56A5, 0xE6C0, 0x5827, + 0xE6C1, 0x59F8, 0xE6C2, 0x5A1F, 0xE6C3, 0x5BB4, 0xE6C4, 0xF98E, 0xE6C5, 0x5EF6, 0xE6C6, 0xF98F, 0xE6C7, 0xF990, 0xE6C8, 0x6350, + 0xE6C9, 0x633B, 0xE6CA, 0xF991, 0xE6CB, 0x693D, 0xE6CC, 0x6C87, 0xE6CD, 0x6CBF, 0xE6CE, 0x6D8E, 0xE6CF, 0x6D93, 0xE6D0, 0x6DF5, + 0xE6D1, 0x6F14, 0xE6D2, 0xF992, 0xE6D3, 0x70DF, 0xE6D4, 0x7136, 0xE6D5, 0x7159, 0xE6D6, 0xF993, 0xE6D7, 0x71C3, 0xE6D8, 0x71D5, + 0xE6D9, 0xF994, 0xE6DA, 0x784F, 0xE6DB, 0x786F, 0xE6DC, 0xF995, 0xE6DD, 0x7B75, 0xE6DE, 0x7DE3, 0xE6DF, 0xF996, 0xE6E0, 0x7E2F, + 0xE6E1, 0xF997, 0xE6E2, 0x884D, 0xE6E3, 0x8EDF, 0xE6E4, 0xF998, 0xE6E5, 0xF999, 0xE6E6, 0xF99A, 0xE6E7, 0x925B, 0xE6E8, 0xF99B, + 0xE6E9, 0x9CF6, 0xE6EA, 0xF99C, 0xE6EB, 0xF99D, 0xE6EC, 0xF99E, 0xE6ED, 0x6085, 0xE6EE, 0x6D85, 0xE6EF, 0xF99F, 0xE6F0, 0x71B1, + 0xE6F1, 0xF9A0, 0xE6F2, 0xF9A1, 0xE6F3, 0x95B1, 0xE6F4, 0x53AD, 0xE6F5, 0xF9A2, 0xE6F6, 0xF9A3, 0xE6F7, 0xF9A4, 0xE6F8, 0x67D3, + 0xE6F9, 0xF9A5, 0xE6FA, 0x708E, 0xE6FB, 0x7130, 0xE6FC, 0x7430, 0xE6FD, 0x8276, 0xE6FE, 0x82D2, 0xE7A1, 0xF9A6, 0xE7A2, 0x95BB, + 0xE7A3, 0x9AE5, 0xE7A4, 0x9E7D, 0xE7A5, 0x66C4, 0xE7A6, 0xF9A7, 0xE7A7, 0x71C1, 0xE7A8, 0x8449, 0xE7A9, 0xF9A8, 0xE7AA, 0xF9A9, + 0xE7AB, 0x584B, 0xE7AC, 0xF9AA, 0xE7AD, 0xF9AB, 0xE7AE, 0x5DB8, 0xE7AF, 0x5F71, 0xE7B0, 0xF9AC, 0xE7B1, 0x6620, 0xE7B2, 0x668E, + 0xE7B3, 0x6979, 0xE7B4, 0x69AE, 0xE7B5, 0x6C38, 0xE7B6, 0x6CF3, 0xE7B7, 0x6E36, 0xE7B8, 0x6F41, 0xE7B9, 0x6FDA, 0xE7BA, 0x701B, + 0xE7BB, 0x702F, 0xE7BC, 0x7150, 0xE7BD, 0x71DF, 0xE7BE, 0x7370, 0xE7BF, 0xF9AD, 0xE7C0, 0x745B, 0xE7C1, 0xF9AE, 0xE7C2, 0x74D4, + 0xE7C3, 0x76C8, 0xE7C4, 0x7A4E, 0xE7C5, 0x7E93, 0xE7C6, 0xF9AF, 0xE7C7, 0xF9B0, 0xE7C8, 0x82F1, 0xE7C9, 0x8A60, 0xE7CA, 0x8FCE, + 0xE7CB, 0xF9B1, 0xE7CC, 0x9348, 0xE7CD, 0xF9B2, 0xE7CE, 0x9719, 0xE7CF, 0xF9B3, 0xE7D0, 0xF9B4, 0xE7D1, 0x4E42, 0xE7D2, 0x502A, + 0xE7D3, 0xF9B5, 0xE7D4, 0x5208, 0xE7D5, 0x53E1, 0xE7D6, 0x66F3, 0xE7D7, 0x6C6D, 0xE7D8, 0x6FCA, 0xE7D9, 0x730A, 0xE7DA, 0x777F, + 0xE7DB, 0x7A62, 0xE7DC, 0x82AE, 0xE7DD, 0x85DD, 0xE7DE, 0x8602, 0xE7DF, 0xF9B6, 0xE7E0, 0x88D4, 0xE7E1, 0x8A63, 0xE7E2, 0x8B7D, + 0xE7E3, 0x8C6B, 0xE7E4, 0xF9B7, 0xE7E5, 0x92B3, 0xE7E6, 0xF9B8, 0xE7E7, 0x9713, 0xE7E8, 0x9810, 0xE7E9, 0x4E94, 0xE7EA, 0x4F0D, + 0xE7EB, 0x4FC9, 0xE7EC, 0x50B2, 0xE7ED, 0x5348, 0xE7EE, 0x543E, 0xE7EF, 0x5433, 0xE7F0, 0x55DA, 0xE7F1, 0x5862, 0xE7F2, 0x58BA, + 0xE7F3, 0x5967, 0xE7F4, 0x5A1B, 0xE7F5, 0x5BE4, 0xE7F6, 0x609F, 0xE7F7, 0xF9B9, 0xE7F8, 0x61CA, 0xE7F9, 0x6556, 0xE7FA, 0x65FF, + 0xE7FB, 0x6664, 0xE7FC, 0x68A7, 0xE7FD, 0x6C5A, 0xE7FE, 0x6FB3, 0xE8A1, 0x70CF, 0xE8A2, 0x71AC, 0xE8A3, 0x7352, 0xE8A4, 0x7B7D, + 0xE8A5, 0x8708, 0xE8A6, 0x8AA4, 0xE8A7, 0x9C32, 0xE8A8, 0x9F07, 0xE8A9, 0x5C4B, 0xE8AA, 0x6C83, 0xE8AB, 0x7344, 0xE8AC, 0x7389, + 0xE8AD, 0x923A, 0xE8AE, 0x6EAB, 0xE8AF, 0x7465, 0xE8B0, 0x761F, 0xE8B1, 0x7A69, 0xE8B2, 0x7E15, 0xE8B3, 0x860A, 0xE8B4, 0x5140, + 0xE8B5, 0x58C5, 0xE8B6, 0x64C1, 0xE8B7, 0x74EE, 0xE8B8, 0x7515, 0xE8B9, 0x7670, 0xE8BA, 0x7FC1, 0xE8BB, 0x9095, 0xE8BC, 0x96CD, + 0xE8BD, 0x9954, 0xE8BE, 0x6E26, 0xE8BF, 0x74E6, 0xE8C0, 0x7AA9, 0xE8C1, 0x7AAA, 0xE8C2, 0x81E5, 0xE8C3, 0x86D9, 0xE8C4, 0x8778, + 0xE8C5, 0x8A1B, 0xE8C6, 0x5A49, 0xE8C7, 0x5B8C, 0xE8C8, 0x5B9B, 0xE8C9, 0x68A1, 0xE8CA, 0x6900, 0xE8CB, 0x6D63, 0xE8CC, 0x73A9, + 0xE8CD, 0x7413, 0xE8CE, 0x742C, 0xE8CF, 0x7897, 0xE8D0, 0x7DE9, 0xE8D1, 0x7FEB, 0xE8D2, 0x8118, 0xE8D3, 0x8155, 0xE8D4, 0x839E, + 0xE8D5, 0x8C4C, 0xE8D6, 0x962E, 0xE8D7, 0x9811, 0xE8D8, 0x66F0, 0xE8D9, 0x5F80, 0xE8DA, 0x65FA, 0xE8DB, 0x6789, 0xE8DC, 0x6C6A, + 0xE8DD, 0x738B, 0xE8DE, 0x502D, 0xE8DF, 0x5A03, 0xE8E0, 0x6B6A, 0xE8E1, 0x77EE, 0xE8E2, 0x5916, 0xE8E3, 0x5D6C, 0xE8E4, 0x5DCD, + 0xE8E5, 0x7325, 0xE8E6, 0x754F, 0xE8E7, 0xF9BA, 0xE8E8, 0xF9BB, 0xE8E9, 0x50E5, 0xE8EA, 0x51F9, 0xE8EB, 0x582F, 0xE8EC, 0x592D, + 0xE8ED, 0x5996, 0xE8EE, 0x59DA, 0xE8EF, 0x5BE5, 0xE8F0, 0xF9BC, 0xE8F1, 0xF9BD, 0xE8F2, 0x5DA2, 0xE8F3, 0x62D7, 0xE8F4, 0x6416, + 0xE8F5, 0x6493, 0xE8F6, 0x64FE, 0xE8F7, 0xF9BE, 0xE8F8, 0x66DC, 0xE8F9, 0xF9BF, 0xE8FA, 0x6A48, 0xE8FB, 0xF9C0, 0xE8FC, 0x71FF, + 0xE8FD, 0x7464, 0xE8FE, 0xF9C1, 0xE9A1, 0x7A88, 0xE9A2, 0x7AAF, 0xE9A3, 0x7E47, 0xE9A4, 0x7E5E, 0xE9A5, 0x8000, 0xE9A6, 0x8170, + 0xE9A7, 0xF9C2, 0xE9A8, 0x87EF, 0xE9A9, 0x8981, 0xE9AA, 0x8B20, 0xE9AB, 0x9059, 0xE9AC, 0xF9C3, 0xE9AD, 0x9080, 0xE9AE, 0x9952, + 0xE9AF, 0x617E, 0xE9B0, 0x6B32, 0xE9B1, 0x6D74, 0xE9B2, 0x7E1F, 0xE9B3, 0x8925, 0xE9B4, 0x8FB1, 0xE9B5, 0x4FD1, 0xE9B6, 0x50AD, + 0xE9B7, 0x5197, 0xE9B8, 0x52C7, 0xE9B9, 0x57C7, 0xE9BA, 0x5889, 0xE9BB, 0x5BB9, 0xE9BC, 0x5EB8, 0xE9BD, 0x6142, 0xE9BE, 0x6995, + 0xE9BF, 0x6D8C, 0xE9C0, 0x6E67, 0xE9C1, 0x6EB6, 0xE9C2, 0x7194, 0xE9C3, 0x7462, 0xE9C4, 0x7528, 0xE9C5, 0x752C, 0xE9C6, 0x8073, + 0xE9C7, 0x8338, 0xE9C8, 0x84C9, 0xE9C9, 0x8E0A, 0xE9CA, 0x9394, 0xE9CB, 0x93DE, 0xE9CC, 0xF9C4, 0xE9CD, 0x4E8E, 0xE9CE, 0x4F51, + 0xE9CF, 0x5076, 0xE9D0, 0x512A, 0xE9D1, 0x53C8, 0xE9D2, 0x53CB, 0xE9D3, 0x53F3, 0xE9D4, 0x5B87, 0xE9D5, 0x5BD3, 0xE9D6, 0x5C24, + 0xE9D7, 0x611A, 0xE9D8, 0x6182, 0xE9D9, 0x65F4, 0xE9DA, 0x725B, 0xE9DB, 0x7397, 0xE9DC, 0x7440, 0xE9DD, 0x76C2, 0xE9DE, 0x7950, + 0xE9DF, 0x7991, 0xE9E0, 0x79B9, 0xE9E1, 0x7D06, 0xE9E2, 0x7FBD, 0xE9E3, 0x828B, 0xE9E4, 0x85D5, 0xE9E5, 0x865E, 0xE9E6, 0x8FC2, + 0xE9E7, 0x9047, 0xE9E8, 0x90F5, 0xE9E9, 0x91EA, 0xE9EA, 0x9685, 0xE9EB, 0x96E8, 0xE9EC, 0x96E9, 0xE9ED, 0x52D6, 0xE9EE, 0x5F67, + 0xE9EF, 0x65ED, 0xE9F0, 0x6631, 0xE9F1, 0x682F, 0xE9F2, 0x715C, 0xE9F3, 0x7A36, 0xE9F4, 0x90C1, 0xE9F5, 0x980A, 0xE9F6, 0x4E91, + 0xE9F7, 0xF9C5, 0xE9F8, 0x6A52, 0xE9F9, 0x6B9E, 0xE9FA, 0x6F90, 0xE9FB, 0x7189, 0xE9FC, 0x8018, 0xE9FD, 0x82B8, 0xE9FE, 0x8553, + 0xEAA1, 0x904B, 0xEAA2, 0x9695, 0xEAA3, 0x96F2, 0xEAA4, 0x97FB, 0xEAA5, 0x851A, 0xEAA6, 0x9B31, 0xEAA7, 0x4E90, 0xEAA8, 0x718A, + 0xEAA9, 0x96C4, 0xEAAA, 0x5143, 0xEAAB, 0x539F, 0xEAAC, 0x54E1, 0xEAAD, 0x5713, 0xEAAE, 0x5712, 0xEAAF, 0x57A3, 0xEAB0, 0x5A9B, + 0xEAB1, 0x5AC4, 0xEAB2, 0x5BC3, 0xEAB3, 0x6028, 0xEAB4, 0x613F, 0xEAB5, 0x63F4, 0xEAB6, 0x6C85, 0xEAB7, 0x6D39, 0xEAB8, 0x6E72, + 0xEAB9, 0x6E90, 0xEABA, 0x7230, 0xEABB, 0x733F, 0xEABC, 0x7457, 0xEABD, 0x82D1, 0xEABE, 0x8881, 0xEABF, 0x8F45, 0xEAC0, 0x9060, + 0xEAC1, 0xF9C6, 0xEAC2, 0x9662, 0xEAC3, 0x9858, 0xEAC4, 0x9D1B, 0xEAC5, 0x6708, 0xEAC6, 0x8D8A, 0xEAC7, 0x925E, 0xEAC8, 0x4F4D, + 0xEAC9, 0x5049, 0xEACA, 0x50DE, 0xEACB, 0x5371, 0xEACC, 0x570D, 0xEACD, 0x59D4, 0xEACE, 0x5A01, 0xEACF, 0x5C09, 0xEAD0, 0x6170, + 0xEAD1, 0x6690, 0xEAD2, 0x6E2D, 0xEAD3, 0x7232, 0xEAD4, 0x744B, 0xEAD5, 0x7DEF, 0xEAD6, 0x80C3, 0xEAD7, 0x840E, 0xEAD8, 0x8466, + 0xEAD9, 0x853F, 0xEADA, 0x875F, 0xEADB, 0x885B, 0xEADC, 0x8918, 0xEADD, 0x8B02, 0xEADE, 0x9055, 0xEADF, 0x97CB, 0xEAE0, 0x9B4F, + 0xEAE1, 0x4E73, 0xEAE2, 0x4F91, 0xEAE3, 0x5112, 0xEAE4, 0x516A, 0xEAE5, 0xF9C7, 0xEAE6, 0x552F, 0xEAE7, 0x55A9, 0xEAE8, 0x5B7A, + 0xEAE9, 0x5BA5, 0xEAEA, 0x5E7C, 0xEAEB, 0x5E7D, 0xEAEC, 0x5EBE, 0xEAED, 0x60A0, 0xEAEE, 0x60DF, 0xEAEF, 0x6108, 0xEAF0, 0x6109, + 0xEAF1, 0x63C4, 0xEAF2, 0x6538, 0xEAF3, 0x6709, 0xEAF4, 0xF9C8, 0xEAF5, 0x67D4, 0xEAF6, 0x67DA, 0xEAF7, 0xF9C9, 0xEAF8, 0x6961, + 0xEAF9, 0x6962, 0xEAFA, 0x6CB9, 0xEAFB, 0x6D27, 0xEAFC, 0xF9CA, 0xEAFD, 0x6E38, 0xEAFE, 0xF9CB, 0xEBA1, 0x6FE1, 0xEBA2, 0x7336, + 0xEBA3, 0x7337, 0xEBA4, 0xF9CC, 0xEBA5, 0x745C, 0xEBA6, 0x7531, 0xEBA7, 0xF9CD, 0xEBA8, 0x7652, 0xEBA9, 0xF9CE, 0xEBAA, 0xF9CF, + 0xEBAB, 0x7DAD, 0xEBAC, 0x81FE, 0xEBAD, 0x8438, 0xEBAE, 0x88D5, 0xEBAF, 0x8A98, 0xEBB0, 0x8ADB, 0xEBB1, 0x8AED, 0xEBB2, 0x8E30, + 0xEBB3, 0x8E42, 0xEBB4, 0x904A, 0xEBB5, 0x903E, 0xEBB6, 0x907A, 0xEBB7, 0x9149, 0xEBB8, 0x91C9, 0xEBB9, 0x936E, 0xEBBA, 0xF9D0, + 0xEBBB, 0xF9D1, 0xEBBC, 0x5809, 0xEBBD, 0xF9D2, 0xEBBE, 0x6BD3, 0xEBBF, 0x8089, 0xEBC0, 0x80B2, 0xEBC1, 0xF9D3, 0xEBC2, 0xF9D4, + 0xEBC3, 0x5141, 0xEBC4, 0x596B, 0xEBC5, 0x5C39, 0xEBC6, 0xF9D5, 0xEBC7, 0xF9D6, 0xEBC8, 0x6F64, 0xEBC9, 0x73A7, 0xEBCA, 0x80E4, + 0xEBCB, 0x8D07, 0xEBCC, 0xF9D7, 0xEBCD, 0x9217, 0xEBCE, 0x958F, 0xEBCF, 0xF9D8, 0xEBD0, 0xF9D9, 0xEBD1, 0xF9DA, 0xEBD2, 0xF9DB, + 0xEBD3, 0x807F, 0xEBD4, 0x620E, 0xEBD5, 0x701C, 0xEBD6, 0x7D68, 0xEBD7, 0x878D, 0xEBD8, 0xF9DC, 0xEBD9, 0x57A0, 0xEBDA, 0x6069, + 0xEBDB, 0x6147, 0xEBDC, 0x6BB7, 0xEBDD, 0x8ABE, 0xEBDE, 0x9280, 0xEBDF, 0x96B1, 0xEBE0, 0x4E59, 0xEBE1, 0x541F, 0xEBE2, 0x6DEB, + 0xEBE3, 0x852D, 0xEBE4, 0x9670, 0xEBE5, 0x97F3, 0xEBE6, 0x98EE, 0xEBE7, 0x63D6, 0xEBE8, 0x6CE3, 0xEBE9, 0x9091, 0xEBEA, 0x51DD, + 0xEBEB, 0x61C9, 0xEBEC, 0x81BA, 0xEBED, 0x9DF9, 0xEBEE, 0x4F9D, 0xEBEF, 0x501A, 0xEBF0, 0x5100, 0xEBF1, 0x5B9C, 0xEBF2, 0x610F, + 0xEBF3, 0x61FF, 0xEBF4, 0x64EC, 0xEBF5, 0x6905, 0xEBF6, 0x6BC5, 0xEBF7, 0x7591, 0xEBF8, 0x77E3, 0xEBF9, 0x7FA9, 0xEBFA, 0x8264, + 0xEBFB, 0x858F, 0xEBFC, 0x87FB, 0xEBFD, 0x8863, 0xEBFE, 0x8ABC, 0xECA1, 0x8B70, 0xECA2, 0x91AB, 0xECA3, 0x4E8C, 0xECA4, 0x4EE5, + 0xECA5, 0x4F0A, 0xECA6, 0xF9DD, 0xECA7, 0xF9DE, 0xECA8, 0x5937, 0xECA9, 0x59E8, 0xECAA, 0xF9DF, 0xECAB, 0x5DF2, 0xECAC, 0x5F1B, + 0xECAD, 0x5F5B, 0xECAE, 0x6021, 0xECAF, 0xF9E0, 0xECB0, 0xF9E1, 0xECB1, 0xF9E2, 0xECB2, 0xF9E3, 0xECB3, 0x723E, 0xECB4, 0x73E5, + 0xECB5, 0xF9E4, 0xECB6, 0x7570, 0xECB7, 0x75CD, 0xECB8, 0xF9E5, 0xECB9, 0x79FB, 0xECBA, 0xF9E6, 0xECBB, 0x800C, 0xECBC, 0x8033, + 0xECBD, 0x8084, 0xECBE, 0x82E1, 0xECBF, 0x8351, 0xECC0, 0xF9E7, 0xECC1, 0xF9E8, 0xECC2, 0x8CBD, 0xECC3, 0x8CB3, 0xECC4, 0x9087, + 0xECC5, 0xF9E9, 0xECC6, 0xF9EA, 0xECC7, 0x98F4, 0xECC8, 0x990C, 0xECC9, 0xF9EB, 0xECCA, 0xF9EC, 0xECCB, 0x7037, 0xECCC, 0x76CA, + 0xECCD, 0x7FCA, 0xECCE, 0x7FCC, 0xECCF, 0x7FFC, 0xECD0, 0x8B1A, 0xECD1, 0x4EBA, 0xECD2, 0x4EC1, 0xECD3, 0x5203, 0xECD4, 0x5370, + 0xECD5, 0xF9ED, 0xECD6, 0x54BD, 0xECD7, 0x56E0, 0xECD8, 0x59FB, 0xECD9, 0x5BC5, 0xECDA, 0x5F15, 0xECDB, 0x5FCD, 0xECDC, 0x6E6E, + 0xECDD, 0xF9EE, 0xECDE, 0xF9EF, 0xECDF, 0x7D6A, 0xECE0, 0x8335, 0xECE1, 0xF9F0, 0xECE2, 0x8693, 0xECE3, 0x8A8D, 0xECE4, 0xF9F1, + 0xECE5, 0x976D, 0xECE6, 0x9777, 0xECE7, 0xF9F2, 0xECE8, 0xF9F3, 0xECE9, 0x4E00, 0xECEA, 0x4F5A, 0xECEB, 0x4F7E, 0xECEC, 0x58F9, + 0xECED, 0x65E5, 0xECEE, 0x6EA2, 0xECEF, 0x9038, 0xECF0, 0x93B0, 0xECF1, 0x99B9, 0xECF2, 0x4EFB, 0xECF3, 0x58EC, 0xECF4, 0x598A, + 0xECF5, 0x59D9, 0xECF6, 0x6041, 0xECF7, 0xF9F4, 0xECF8, 0xF9F5, 0xECF9, 0x7A14, 0xECFA, 0xF9F6, 0xECFB, 0x834F, 0xECFC, 0x8CC3, + 0xECFD, 0x5165, 0xECFE, 0x5344, 0xEDA1, 0xF9F7, 0xEDA2, 0xF9F8, 0xEDA3, 0xF9F9, 0xEDA4, 0x4ECD, 0xEDA5, 0x5269, 0xEDA6, 0x5B55, + 0xEDA7, 0x82BF, 0xEDA8, 0x4ED4, 0xEDA9, 0x523A, 0xEDAA, 0x54A8, 0xEDAB, 0x59C9, 0xEDAC, 0x59FF, 0xEDAD, 0x5B50, 0xEDAE, 0x5B57, + 0xEDAF, 0x5B5C, 0xEDB0, 0x6063, 0xEDB1, 0x6148, 0xEDB2, 0x6ECB, 0xEDB3, 0x7099, 0xEDB4, 0x716E, 0xEDB5, 0x7386, 0xEDB6, 0x74F7, + 0xEDB7, 0x75B5, 0xEDB8, 0x78C1, 0xEDB9, 0x7D2B, 0xEDBA, 0x8005, 0xEDBB, 0x81EA, 0xEDBC, 0x8328, 0xEDBD, 0x8517, 0xEDBE, 0x85C9, + 0xEDBF, 0x8AEE, 0xEDC0, 0x8CC7, 0xEDC1, 0x96CC, 0xEDC2, 0x4F5C, 0xEDC3, 0x52FA, 0xEDC4, 0x56BC, 0xEDC5, 0x65AB, 0xEDC6, 0x6628, + 0xEDC7, 0x707C, 0xEDC8, 0x70B8, 0xEDC9, 0x7235, 0xEDCA, 0x7DBD, 0xEDCB, 0x828D, 0xEDCC, 0x914C, 0xEDCD, 0x96C0, 0xEDCE, 0x9D72, + 0xEDCF, 0x5B71, 0xEDD0, 0x68E7, 0xEDD1, 0x6B98, 0xEDD2, 0x6F7A, 0xEDD3, 0x76DE, 0xEDD4, 0x5C91, 0xEDD5, 0x66AB, 0xEDD6, 0x6F5B, + 0xEDD7, 0x7BB4, 0xEDD8, 0x7C2A, 0xEDD9, 0x8836, 0xEDDA, 0x96DC, 0xEDDB, 0x4E08, 0xEDDC, 0x4ED7, 0xEDDD, 0x5320, 0xEDDE, 0x5834, + 0xEDDF, 0x58BB, 0xEDE0, 0x58EF, 0xEDE1, 0x596C, 0xEDE2, 0x5C07, 0xEDE3, 0x5E33, 0xEDE4, 0x5E84, 0xEDE5, 0x5F35, 0xEDE6, 0x638C, + 0xEDE7, 0x66B2, 0xEDE8, 0x6756, 0xEDE9, 0x6A1F, 0xEDEA, 0x6AA3, 0xEDEB, 0x6B0C, 0xEDEC, 0x6F3F, 0xEDED, 0x7246, 0xEDEE, 0xF9FA, + 0xEDEF, 0x7350, 0xEDF0, 0x748B, 0xEDF1, 0x7AE0, 0xEDF2, 0x7CA7, 0xEDF3, 0x8178, 0xEDF4, 0x81DF, 0xEDF5, 0x81E7, 0xEDF6, 0x838A, + 0xEDF7, 0x846C, 0xEDF8, 0x8523, 0xEDF9, 0x8594, 0xEDFA, 0x85CF, 0xEDFB, 0x88DD, 0xEDFC, 0x8D13, 0xEDFD, 0x91AC, 0xEDFE, 0x9577, + 0xEEA1, 0x969C, 0xEEA2, 0x518D, 0xEEA3, 0x54C9, 0xEEA4, 0x5728, 0xEEA5, 0x5BB0, 0xEEA6, 0x624D, 0xEEA7, 0x6750, 0xEEA8, 0x683D, + 0xEEA9, 0x6893, 0xEEAA, 0x6E3D, 0xEEAB, 0x6ED3, 0xEEAC, 0x707D, 0xEEAD, 0x7E21, 0xEEAE, 0x88C1, 0xEEAF, 0x8CA1, 0xEEB0, 0x8F09, + 0xEEB1, 0x9F4B, 0xEEB2, 0x9F4E, 0xEEB3, 0x722D, 0xEEB4, 0x7B8F, 0xEEB5, 0x8ACD, 0xEEB6, 0x931A, 0xEEB7, 0x4F47, 0xEEB8, 0x4F4E, + 0xEEB9, 0x5132, 0xEEBA, 0x5480, 0xEEBB, 0x59D0, 0xEEBC, 0x5E95, 0xEEBD, 0x62B5, 0xEEBE, 0x6775, 0xEEBF, 0x696E, 0xEEC0, 0x6A17, + 0xEEC1, 0x6CAE, 0xEEC2, 0x6E1A, 0xEEC3, 0x72D9, 0xEEC4, 0x732A, 0xEEC5, 0x75BD, 0xEEC6, 0x7BB8, 0xEEC7, 0x7D35, 0xEEC8, 0x82E7, + 0xEEC9, 0x83F9, 0xEECA, 0x8457, 0xEECB, 0x85F7, 0xEECC, 0x8A5B, 0xEECD, 0x8CAF, 0xEECE, 0x8E87, 0xEECF, 0x9019, 0xEED0, 0x90B8, + 0xEED1, 0x96CE, 0xEED2, 0x9F5F, 0xEED3, 0x52E3, 0xEED4, 0x540A, 0xEED5, 0x5AE1, 0xEED6, 0x5BC2, 0xEED7, 0x6458, 0xEED8, 0x6575, + 0xEED9, 0x6EF4, 0xEEDA, 0x72C4, 0xEEDB, 0xF9FB, 0xEEDC, 0x7684, 0xEEDD, 0x7A4D, 0xEEDE, 0x7B1B, 0xEEDF, 0x7C4D, 0xEEE0, 0x7E3E, + 0xEEE1, 0x7FDF, 0xEEE2, 0x837B, 0xEEE3, 0x8B2B, 0xEEE4, 0x8CCA, 0xEEE5, 0x8D64, 0xEEE6, 0x8DE1, 0xEEE7, 0x8E5F, 0xEEE8, 0x8FEA, + 0xEEE9, 0x8FF9, 0xEEEA, 0x9069, 0xEEEB, 0x93D1, 0xEEEC, 0x4F43, 0xEEED, 0x4F7A, 0xEEEE, 0x50B3, 0xEEEF, 0x5168, 0xEEF0, 0x5178, + 0xEEF1, 0x524D, 0xEEF2, 0x526A, 0xEEF3, 0x5861, 0xEEF4, 0x587C, 0xEEF5, 0x5960, 0xEEF6, 0x5C08, 0xEEF7, 0x5C55, 0xEEF8, 0x5EDB, + 0xEEF9, 0x609B, 0xEEFA, 0x6230, 0xEEFB, 0x6813, 0xEEFC, 0x6BBF, 0xEEFD, 0x6C08, 0xEEFE, 0x6FB1, 0xEFA1, 0x714E, 0xEFA2, 0x7420, + 0xEFA3, 0x7530, 0xEFA4, 0x7538, 0xEFA5, 0x7551, 0xEFA6, 0x7672, 0xEFA7, 0x7B4C, 0xEFA8, 0x7B8B, 0xEFA9, 0x7BAD, 0xEFAA, 0x7BC6, + 0xEFAB, 0x7E8F, 0xEFAC, 0x8A6E, 0xEFAD, 0x8F3E, 0xEFAE, 0x8F49, 0xEFAF, 0x923F, 0xEFB0, 0x9293, 0xEFB1, 0x9322, 0xEFB2, 0x942B, + 0xEFB3, 0x96FB, 0xEFB4, 0x985A, 0xEFB5, 0x986B, 0xEFB6, 0x991E, 0xEFB7, 0x5207, 0xEFB8, 0x622A, 0xEFB9, 0x6298, 0xEFBA, 0x6D59, + 0xEFBB, 0x7664, 0xEFBC, 0x7ACA, 0xEFBD, 0x7BC0, 0xEFBE, 0x7D76, 0xEFBF, 0x5360, 0xEFC0, 0x5CBE, 0xEFC1, 0x5E97, 0xEFC2, 0x6F38, + 0xEFC3, 0x70B9, 0xEFC4, 0x7C98, 0xEFC5, 0x9711, 0xEFC6, 0x9B8E, 0xEFC7, 0x9EDE, 0xEFC8, 0x63A5, 0xEFC9, 0x647A, 0xEFCA, 0x8776, + 0xEFCB, 0x4E01, 0xEFCC, 0x4E95, 0xEFCD, 0x4EAD, 0xEFCE, 0x505C, 0xEFCF, 0x5075, 0xEFD0, 0x5448, 0xEFD1, 0x59C3, 0xEFD2, 0x5B9A, + 0xEFD3, 0x5E40, 0xEFD4, 0x5EAD, 0xEFD5, 0x5EF7, 0xEFD6, 0x5F81, 0xEFD7, 0x60C5, 0xEFD8, 0x633A, 0xEFD9, 0x653F, 0xEFDA, 0x6574, + 0xEFDB, 0x65CC, 0xEFDC, 0x6676, 0xEFDD, 0x6678, 0xEFDE, 0x67FE, 0xEFDF, 0x6968, 0xEFE0, 0x6A89, 0xEFE1, 0x6B63, 0xEFE2, 0x6C40, + 0xEFE3, 0x6DC0, 0xEFE4, 0x6DE8, 0xEFE5, 0x6E1F, 0xEFE6, 0x6E5E, 0xEFE7, 0x701E, 0xEFE8, 0x70A1, 0xEFE9, 0x738E, 0xEFEA, 0x73FD, + 0xEFEB, 0x753A, 0xEFEC, 0x775B, 0xEFED, 0x7887, 0xEFEE, 0x798E, 0xEFEF, 0x7A0B, 0xEFF0, 0x7A7D, 0xEFF1, 0x7CBE, 0xEFF2, 0x7D8E, + 0xEFF3, 0x8247, 0xEFF4, 0x8A02, 0xEFF5, 0x8AEA, 0xEFF6, 0x8C9E, 0xEFF7, 0x912D, 0xEFF8, 0x914A, 0xEFF9, 0x91D8, 0xEFFA, 0x9266, + 0xEFFB, 0x92CC, 0xEFFC, 0x9320, 0xEFFD, 0x9706, 0xEFFE, 0x9756, 0xF0A1, 0x975C, 0xF0A2, 0x9802, 0xF0A3, 0x9F0E, 0xF0A4, 0x5236, + 0xF0A5, 0x5291, 0xF0A6, 0x557C, 0xF0A7, 0x5824, 0xF0A8, 0x5E1D, 0xF0A9, 0x5F1F, 0xF0AA, 0x608C, 0xF0AB, 0x63D0, 0xF0AC, 0x68AF, + 0xF0AD, 0x6FDF, 0xF0AE, 0x796D, 0xF0AF, 0x7B2C, 0xF0B0, 0x81CD, 0xF0B1, 0x85BA, 0xF0B2, 0x88FD, 0xF0B3, 0x8AF8, 0xF0B4, 0x8E44, + 0xF0B5, 0x918D, 0xF0B6, 0x9664, 0xF0B7, 0x969B, 0xF0B8, 0x973D, 0xF0B9, 0x984C, 0xF0BA, 0x9F4A, 0xF0BB, 0x4FCE, 0xF0BC, 0x5146, + 0xF0BD, 0x51CB, 0xF0BE, 0x52A9, 0xF0BF, 0x5632, 0xF0C0, 0x5F14, 0xF0C1, 0x5F6B, 0xF0C2, 0x63AA, 0xF0C3, 0x64CD, 0xF0C4, 0x65E9, + 0xF0C5, 0x6641, 0xF0C6, 0x66FA, 0xF0C7, 0x66F9, 0xF0C8, 0x671D, 0xF0C9, 0x689D, 0xF0CA, 0x68D7, 0xF0CB, 0x69FD, 0xF0CC, 0x6F15, + 0xF0CD, 0x6F6E, 0xF0CE, 0x7167, 0xF0CF, 0x71E5, 0xF0D0, 0x722A, 0xF0D1, 0x74AA, 0xF0D2, 0x773A, 0xF0D3, 0x7956, 0xF0D4, 0x795A, + 0xF0D5, 0x79DF, 0xF0D6, 0x7A20, 0xF0D7, 0x7A95, 0xF0D8, 0x7C97, 0xF0D9, 0x7CDF, 0xF0DA, 0x7D44, 0xF0DB, 0x7E70, 0xF0DC, 0x8087, + 0xF0DD, 0x85FB, 0xF0DE, 0x86A4, 0xF0DF, 0x8A54, 0xF0E0, 0x8ABF, 0xF0E1, 0x8D99, 0xF0E2, 0x8E81, 0xF0E3, 0x9020, 0xF0E4, 0x906D, + 0xF0E5, 0x91E3, 0xF0E6, 0x963B, 0xF0E7, 0x96D5, 0xF0E8, 0x9CE5, 0xF0E9, 0x65CF, 0xF0EA, 0x7C07, 0xF0EB, 0x8DB3, 0xF0EC, 0x93C3, + 0xF0ED, 0x5B58, 0xF0EE, 0x5C0A, 0xF0EF, 0x5352, 0xF0F0, 0x62D9, 0xF0F1, 0x731D, 0xF0F2, 0x5027, 0xF0F3, 0x5B97, 0xF0F4, 0x5F9E, + 0xF0F5, 0x60B0, 0xF0F6, 0x616B, 0xF0F7, 0x68D5, 0xF0F8, 0x6DD9, 0xF0F9, 0x742E, 0xF0FA, 0x7A2E, 0xF0FB, 0x7D42, 0xF0FC, 0x7D9C, + 0xF0FD, 0x7E31, 0xF0FE, 0x816B, 0xF1A1, 0x8E2A, 0xF1A2, 0x8E35, 0xF1A3, 0x937E, 0xF1A4, 0x9418, 0xF1A5, 0x4F50, 0xF1A6, 0x5750, + 0xF1A7, 0x5DE6, 0xF1A8, 0x5EA7, 0xF1A9, 0x632B, 0xF1AA, 0x7F6A, 0xF1AB, 0x4E3B, 0xF1AC, 0x4F4F, 0xF1AD, 0x4F8F, 0xF1AE, 0x505A, + 0xF1AF, 0x59DD, 0xF1B0, 0x80C4, 0xF1B1, 0x546A, 0xF1B2, 0x5468, 0xF1B3, 0x55FE, 0xF1B4, 0x594F, 0xF1B5, 0x5B99, 0xF1B6, 0x5DDE, + 0xF1B7, 0x5EDA, 0xF1B8, 0x665D, 0xF1B9, 0x6731, 0xF1BA, 0x67F1, 0xF1BB, 0x682A, 0xF1BC, 0x6CE8, 0xF1BD, 0x6D32, 0xF1BE, 0x6E4A, + 0xF1BF, 0x6F8D, 0xF1C0, 0x70B7, 0xF1C1, 0x73E0, 0xF1C2, 0x7587, 0xF1C3, 0x7C4C, 0xF1C4, 0x7D02, 0xF1C5, 0x7D2C, 0xF1C6, 0x7DA2, + 0xF1C7, 0x821F, 0xF1C8, 0x86DB, 0xF1C9, 0x8A3B, 0xF1CA, 0x8A85, 0xF1CB, 0x8D70, 0xF1CC, 0x8E8A, 0xF1CD, 0x8F33, 0xF1CE, 0x9031, + 0xF1CF, 0x914E, 0xF1D0, 0x9152, 0xF1D1, 0x9444, 0xF1D2, 0x99D0, 0xF1D3, 0x7AF9, 0xF1D4, 0x7CA5, 0xF1D5, 0x4FCA, 0xF1D6, 0x5101, + 0xF1D7, 0x51C6, 0xF1D8, 0x57C8, 0xF1D9, 0x5BEF, 0xF1DA, 0x5CFB, 0xF1DB, 0x6659, 0xF1DC, 0x6A3D, 0xF1DD, 0x6D5A, 0xF1DE, 0x6E96, + 0xF1DF, 0x6FEC, 0xF1E0, 0x710C, 0xF1E1, 0x756F, 0xF1E2, 0x7AE3, 0xF1E3, 0x8822, 0xF1E4, 0x9021, 0xF1E5, 0x9075, 0xF1E6, 0x96CB, + 0xF1E7, 0x99FF, 0xF1E8, 0x8301, 0xF1E9, 0x4E2D, 0xF1EA, 0x4EF2, 0xF1EB, 0x8846, 0xF1EC, 0x91CD, 0xF1ED, 0x537D, 0xF1EE, 0x6ADB, + 0xF1EF, 0x696B, 0xF1F0, 0x6C41, 0xF1F1, 0x847A, 0xF1F2, 0x589E, 0xF1F3, 0x618E, 0xF1F4, 0x66FE, 0xF1F5, 0x62EF, 0xF1F6, 0x70DD, + 0xF1F7, 0x7511, 0xF1F8, 0x75C7, 0xF1F9, 0x7E52, 0xF1FA, 0x84B8, 0xF1FB, 0x8B49, 0xF1FC, 0x8D08, 0xF1FD, 0x4E4B, 0xF1FE, 0x53EA, + 0xF2A1, 0x54AB, 0xF2A2, 0x5730, 0xF2A3, 0x5740, 0xF2A4, 0x5FD7, 0xF2A5, 0x6301, 0xF2A6, 0x6307, 0xF2A7, 0x646F, 0xF2A8, 0x652F, + 0xF2A9, 0x65E8, 0xF2AA, 0x667A, 0xF2AB, 0x679D, 0xF2AC, 0x67B3, 0xF2AD, 0x6B62, 0xF2AE, 0x6C60, 0xF2AF, 0x6C9A, 0xF2B0, 0x6F2C, + 0xF2B1, 0x77E5, 0xF2B2, 0x7825, 0xF2B3, 0x7949, 0xF2B4, 0x7957, 0xF2B5, 0x7D19, 0xF2B6, 0x80A2, 0xF2B7, 0x8102, 0xF2B8, 0x81F3, + 0xF2B9, 0x829D, 0xF2BA, 0x82B7, 0xF2BB, 0x8718, 0xF2BC, 0x8A8C, 0xF2BD, 0xF9FC, 0xF2BE, 0x8D04, 0xF2BF, 0x8DBE, 0xF2C0, 0x9072, + 0xF2C1, 0x76F4, 0xF2C2, 0x7A19, 0xF2C3, 0x7A37, 0xF2C4, 0x7E54, 0xF2C5, 0x8077, 0xF2C6, 0x5507, 0xF2C7, 0x55D4, 0xF2C8, 0x5875, + 0xF2C9, 0x632F, 0xF2CA, 0x6422, 0xF2CB, 0x6649, 0xF2CC, 0x664B, 0xF2CD, 0x686D, 0xF2CE, 0x699B, 0xF2CF, 0x6B84, 0xF2D0, 0x6D25, + 0xF2D1, 0x6EB1, 0xF2D2, 0x73CD, 0xF2D3, 0x7468, 0xF2D4, 0x74A1, 0xF2D5, 0x755B, 0xF2D6, 0x75B9, 0xF2D7, 0x76E1, 0xF2D8, 0x771E, + 0xF2D9, 0x778B, 0xF2DA, 0x79E6, 0xF2DB, 0x7E09, 0xF2DC, 0x7E1D, 0xF2DD, 0x81FB, 0xF2DE, 0x852F, 0xF2DF, 0x8897, 0xF2E0, 0x8A3A, + 0xF2E1, 0x8CD1, 0xF2E2, 0x8EEB, 0xF2E3, 0x8FB0, 0xF2E4, 0x9032, 0xF2E5, 0x93AD, 0xF2E6, 0x9663, 0xF2E7, 0x9673, 0xF2E8, 0x9707, + 0xF2E9, 0x4F84, 0xF2EA, 0x53F1, 0xF2EB, 0x59EA, 0xF2EC, 0x5AC9, 0xF2ED, 0x5E19, 0xF2EE, 0x684E, 0xF2EF, 0x74C6, 0xF2F0, 0x75BE, + 0xF2F1, 0x79E9, 0xF2F2, 0x7A92, 0xF2F3, 0x81A3, 0xF2F4, 0x86ED, 0xF2F5, 0x8CEA, 0xF2F6, 0x8DCC, 0xF2F7, 0x8FED, 0xF2F8, 0x659F, + 0xF2F9, 0x6715, 0xF2FA, 0xF9FD, 0xF2FB, 0x57F7, 0xF2FC, 0x6F57, 0xF2FD, 0x7DDD, 0xF2FE, 0x8F2F, 0xF3A1, 0x93F6, 0xF3A2, 0x96C6, + 0xF3A3, 0x5FB5, 0xF3A4, 0x61F2, 0xF3A5, 0x6F84, 0xF3A6, 0x4E14, 0xF3A7, 0x4F98, 0xF3A8, 0x501F, 0xF3A9, 0x53C9, 0xF3AA, 0x55DF, + 0xF3AB, 0x5D6F, 0xF3AC, 0x5DEE, 0xF3AD, 0x6B21, 0xF3AE, 0x6B64, 0xF3AF, 0x78CB, 0xF3B0, 0x7B9A, 0xF3B1, 0xF9FE, 0xF3B2, 0x8E49, + 0xF3B3, 0x8ECA, 0xF3B4, 0x906E, 0xF3B5, 0x6349, 0xF3B6, 0x643E, 0xF3B7, 0x7740, 0xF3B8, 0x7A84, 0xF3B9, 0x932F, 0xF3BA, 0x947F, + 0xF3BB, 0x9F6A, 0xF3BC, 0x64B0, 0xF3BD, 0x6FAF, 0xF3BE, 0x71E6, 0xF3BF, 0x74A8, 0xF3C0, 0x74DA, 0xF3C1, 0x7AC4, 0xF3C2, 0x7C12, + 0xF3C3, 0x7E82, 0xF3C4, 0x7CB2, 0xF3C5, 0x7E98, 0xF3C6, 0x8B9A, 0xF3C7, 0x8D0A, 0xF3C8, 0x947D, 0xF3C9, 0x9910, 0xF3CA, 0x994C, + 0xF3CB, 0x5239, 0xF3CC, 0x5BDF, 0xF3CD, 0x64E6, 0xF3CE, 0x672D, 0xF3CF, 0x7D2E, 0xF3D0, 0x50ED, 0xF3D1, 0x53C3, 0xF3D2, 0x5879, + 0xF3D3, 0x6158, 0xF3D4, 0x6159, 0xF3D5, 0x61FA, 0xF3D6, 0x65AC, 0xF3D7, 0x7AD9, 0xF3D8, 0x8B92, 0xF3D9, 0x8B96, 0xF3DA, 0x5009, + 0xF3DB, 0x5021, 0xF3DC, 0x5275, 0xF3DD, 0x5531, 0xF3DE, 0x5A3C, 0xF3DF, 0x5EE0, 0xF3E0, 0x5F70, 0xF3E1, 0x6134, 0xF3E2, 0x655E, + 0xF3E3, 0x660C, 0xF3E4, 0x6636, 0xF3E5, 0x66A2, 0xF3E6, 0x69CD, 0xF3E7, 0x6EC4, 0xF3E8, 0x6F32, 0xF3E9, 0x7316, 0xF3EA, 0x7621, + 0xF3EB, 0x7A93, 0xF3EC, 0x8139, 0xF3ED, 0x8259, 0xF3EE, 0x83D6, 0xF3EF, 0x84BC, 0xF3F0, 0x50B5, 0xF3F1, 0x57F0, 0xF3F2, 0x5BC0, + 0xF3F3, 0x5BE8, 0xF3F4, 0x5F69, 0xF3F5, 0x63A1, 0xF3F6, 0x7826, 0xF3F7, 0x7DB5, 0xF3F8, 0x83DC, 0xF3F9, 0x8521, 0xF3FA, 0x91C7, + 0xF3FB, 0x91F5, 0xF3FC, 0x518A, 0xF3FD, 0x67F5, 0xF3FE, 0x7B56, 0xF4A1, 0x8CAC, 0xF4A2, 0x51C4, 0xF4A3, 0x59BB, 0xF4A4, 0x60BD, + 0xF4A5, 0x8655, 0xF4A6, 0x501C, 0xF4A7, 0xF9FF, 0xF4A8, 0x5254, 0xF4A9, 0x5C3A, 0xF4AA, 0x617D, 0xF4AB, 0x621A, 0xF4AC, 0x62D3, + 0xF4AD, 0x64F2, 0xF4AE, 0x65A5, 0xF4AF, 0x6ECC, 0xF4B0, 0x7620, 0xF4B1, 0x810A, 0xF4B2, 0x8E60, 0xF4B3, 0x965F, 0xF4B4, 0x96BB, + 0xF4B5, 0x4EDF, 0xF4B6, 0x5343, 0xF4B7, 0x5598, 0xF4B8, 0x5929, 0xF4B9, 0x5DDD, 0xF4BA, 0x64C5, 0xF4BB, 0x6CC9, 0xF4BC, 0x6DFA, + 0xF4BD, 0x7394, 0xF4BE, 0x7A7F, 0xF4BF, 0x821B, 0xF4C0, 0x85A6, 0xF4C1, 0x8CE4, 0xF4C2, 0x8E10, 0xF4C3, 0x9077, 0xF4C4, 0x91E7, + 0xF4C5, 0x95E1, 0xF4C6, 0x9621, 0xF4C7, 0x97C6, 0xF4C8, 0x51F8, 0xF4C9, 0x54F2, 0xF4CA, 0x5586, 0xF4CB, 0x5FB9, 0xF4CC, 0x64A4, + 0xF4CD, 0x6F88, 0xF4CE, 0x7DB4, 0xF4CF, 0x8F1F, 0xF4D0, 0x8F4D, 0xF4D1, 0x9435, 0xF4D2, 0x50C9, 0xF4D3, 0x5C16, 0xF4D4, 0x6CBE, + 0xF4D5, 0x6DFB, 0xF4D6, 0x751B, 0xF4D7, 0x77BB, 0xF4D8, 0x7C3D, 0xF4D9, 0x7C64, 0xF4DA, 0x8A79, 0xF4DB, 0x8AC2, 0xF4DC, 0x581E, + 0xF4DD, 0x59BE, 0xF4DE, 0x5E16, 0xF4DF, 0x6377, 0xF4E0, 0x7252, 0xF4E1, 0x758A, 0xF4E2, 0x776B, 0xF4E3, 0x8ADC, 0xF4E4, 0x8CBC, + 0xF4E5, 0x8F12, 0xF4E6, 0x5EF3, 0xF4E7, 0x6674, 0xF4E8, 0x6DF8, 0xF4E9, 0x807D, 0xF4EA, 0x83C1, 0xF4EB, 0x8ACB, 0xF4EC, 0x9751, + 0xF4ED, 0x9BD6, 0xF4EE, 0xFA00, 0xF4EF, 0x5243, 0xF4F0, 0x66FF, 0xF4F1, 0x6D95, 0xF4F2, 0x6EEF, 0xF4F3, 0x7DE0, 0xF4F4, 0x8AE6, + 0xF4F5, 0x902E, 0xF4F6, 0x905E, 0xF4F7, 0x9AD4, 0xF4F8, 0x521D, 0xF4F9, 0x527F, 0xF4FA, 0x54E8, 0xF4FB, 0x6194, 0xF4FC, 0x6284, + 0xF4FD, 0x62DB, 0xF4FE, 0x68A2, 0xF5A1, 0x6912, 0xF5A2, 0x695A, 0xF5A3, 0x6A35, 0xF5A4, 0x7092, 0xF5A5, 0x7126, 0xF5A6, 0x785D, + 0xF5A7, 0x7901, 0xF5A8, 0x790E, 0xF5A9, 0x79D2, 0xF5AA, 0x7A0D, 0xF5AB, 0x8096, 0xF5AC, 0x8278, 0xF5AD, 0x82D5, 0xF5AE, 0x8349, + 0xF5AF, 0x8549, 0xF5B0, 0x8C82, 0xF5B1, 0x8D85, 0xF5B2, 0x9162, 0xF5B3, 0x918B, 0xF5B4, 0x91AE, 0xF5B5, 0x4FC3, 0xF5B6, 0x56D1, + 0xF5B7, 0x71ED, 0xF5B8, 0x77D7, 0xF5B9, 0x8700, 0xF5BA, 0x89F8, 0xF5BB, 0x5BF8, 0xF5BC, 0x5FD6, 0xF5BD, 0x6751, 0xF5BE, 0x90A8, + 0xF5BF, 0x53E2, 0xF5C0, 0x585A, 0xF5C1, 0x5BF5, 0xF5C2, 0x60A4, 0xF5C3, 0x6181, 0xF5C4, 0x6460, 0xF5C5, 0x7E3D, 0xF5C6, 0x8070, + 0xF5C7, 0x8525, 0xF5C8, 0x9283, 0xF5C9, 0x64AE, 0xF5CA, 0x50AC, 0xF5CB, 0x5D14, 0xF5CC, 0x6700, 0xF5CD, 0x589C, 0xF5CE, 0x62BD, + 0xF5CF, 0x63A8, 0xF5D0, 0x690E, 0xF5D1, 0x6978, 0xF5D2, 0x6A1E, 0xF5D3, 0x6E6B, 0xF5D4, 0x76BA, 0xF5D5, 0x79CB, 0xF5D6, 0x82BB, + 0xF5D7, 0x8429, 0xF5D8, 0x8ACF, 0xF5D9, 0x8DA8, 0xF5DA, 0x8FFD, 0xF5DB, 0x9112, 0xF5DC, 0x914B, 0xF5DD, 0x919C, 0xF5DE, 0x9310, + 0xF5DF, 0x9318, 0xF5E0, 0x939A, 0xF5E1, 0x96DB, 0xF5E2, 0x9A36, 0xF5E3, 0x9C0D, 0xF5E4, 0x4E11, 0xF5E5, 0x755C, 0xF5E6, 0x795D, + 0xF5E7, 0x7AFA, 0xF5E8, 0x7B51, 0xF5E9, 0x7BC9, 0xF5EA, 0x7E2E, 0xF5EB, 0x84C4, 0xF5EC, 0x8E59, 0xF5ED, 0x8E74, 0xF5EE, 0x8EF8, + 0xF5EF, 0x9010, 0xF5F0, 0x6625, 0xF5F1, 0x693F, 0xF5F2, 0x7443, 0xF5F3, 0x51FA, 0xF5F4, 0x672E, 0xF5F5, 0x9EDC, 0xF5F6, 0x5145, + 0xF5F7, 0x5FE0, 0xF5F8, 0x6C96, 0xF5F9, 0x87F2, 0xF5FA, 0x885D, 0xF5FB, 0x8877, 0xF5FC, 0x60B4, 0xF5FD, 0x81B5, 0xF5FE, 0x8403, + 0xF6A1, 0x8D05, 0xF6A2, 0x53D6, 0xF6A3, 0x5439, 0xF6A4, 0x5634, 0xF6A5, 0x5A36, 0xF6A6, 0x5C31, 0xF6A7, 0x708A, 0xF6A8, 0x7FE0, + 0xF6A9, 0x805A, 0xF6AA, 0x8106, 0xF6AB, 0x81ED, 0xF6AC, 0x8DA3, 0xF6AD, 0x9189, 0xF6AE, 0x9A5F, 0xF6AF, 0x9DF2, 0xF6B0, 0x5074, + 0xF6B1, 0x4EC4, 0xF6B2, 0x53A0, 0xF6B3, 0x60FB, 0xF6B4, 0x6E2C, 0xF6B5, 0x5C64, 0xF6B6, 0x4F88, 0xF6B7, 0x5024, 0xF6B8, 0x55E4, + 0xF6B9, 0x5CD9, 0xF6BA, 0x5E5F, 0xF6BB, 0x6065, 0xF6BC, 0x6894, 0xF6BD, 0x6CBB, 0xF6BE, 0x6DC4, 0xF6BF, 0x71BE, 0xF6C0, 0x75D4, + 0xF6C1, 0x75F4, 0xF6C2, 0x7661, 0xF6C3, 0x7A1A, 0xF6C4, 0x7A49, 0xF6C5, 0x7DC7, 0xF6C6, 0x7DFB, 0xF6C7, 0x7F6E, 0xF6C8, 0x81F4, + 0xF6C9, 0x86A9, 0xF6CA, 0x8F1C, 0xF6CB, 0x96C9, 0xF6CC, 0x99B3, 0xF6CD, 0x9F52, 0xF6CE, 0x5247, 0xF6CF, 0x52C5, 0xF6D0, 0x98ED, + 0xF6D1, 0x89AA, 0xF6D2, 0x4E03, 0xF6D3, 0x67D2, 0xF6D4, 0x6F06, 0xF6D5, 0x4FB5, 0xF6D6, 0x5BE2, 0xF6D7, 0x6795, 0xF6D8, 0x6C88, + 0xF6D9, 0x6D78, 0xF6DA, 0x741B, 0xF6DB, 0x7827, 0xF6DC, 0x91DD, 0xF6DD, 0x937C, 0xF6DE, 0x87C4, 0xF6DF, 0x79E4, 0xF6E0, 0x7A31, + 0xF6E1, 0x5FEB, 0xF6E2, 0x4ED6, 0xF6E3, 0x54A4, 0xF6E4, 0x553E, 0xF6E5, 0x58AE, 0xF6E6, 0x59A5, 0xF6E7, 0x60F0, 0xF6E8, 0x6253, + 0xF6E9, 0x62D6, 0xF6EA, 0x6736, 0xF6EB, 0x6955, 0xF6EC, 0x8235, 0xF6ED, 0x9640, 0xF6EE, 0x99B1, 0xF6EF, 0x99DD, 0xF6F0, 0x502C, + 0xF6F1, 0x5353, 0xF6F2, 0x5544, 0xF6F3, 0x577C, 0xF6F4, 0xFA01, 0xF6F5, 0x6258, 0xF6F6, 0xFA02, 0xF6F7, 0x64E2, 0xF6F8, 0x666B, + 0xF6F9, 0x67DD, 0xF6FA, 0x6FC1, 0xF6FB, 0x6FEF, 0xF6FC, 0x7422, 0xF6FD, 0x7438, 0xF6FE, 0x8A17, 0xF7A1, 0x9438, 0xF7A2, 0x5451, + 0xF7A3, 0x5606, 0xF7A4, 0x5766, 0xF7A5, 0x5F48, 0xF7A6, 0x619A, 0xF7A7, 0x6B4E, 0xF7A8, 0x7058, 0xF7A9, 0x70AD, 0xF7AA, 0x7DBB, + 0xF7AB, 0x8A95, 0xF7AC, 0x596A, 0xF7AD, 0x812B, 0xF7AE, 0x63A2, 0xF7AF, 0x7708, 0xF7B0, 0x803D, 0xF7B1, 0x8CAA, 0xF7B2, 0x5854, + 0xF7B3, 0x642D, 0xF7B4, 0x69BB, 0xF7B5, 0x5B95, 0xF7B6, 0x5E11, 0xF7B7, 0x6E6F, 0xF7B8, 0xFA03, 0xF7B9, 0x8569, 0xF7BA, 0x514C, + 0xF7BB, 0x53F0, 0xF7BC, 0x592A, 0xF7BD, 0x6020, 0xF7BE, 0x614B, 0xF7BF, 0x6B86, 0xF7C0, 0x6C70, 0xF7C1, 0x6CF0, 0xF7C2, 0x7B1E, + 0xF7C3, 0x80CE, 0xF7C4, 0x82D4, 0xF7C5, 0x8DC6, 0xF7C6, 0x90B0, 0xF7C7, 0x98B1, 0xF7C8, 0xFA04, 0xF7C9, 0x64C7, 0xF7CA, 0x6FA4, + 0xF7CB, 0x6491, 0xF7CC, 0x6504, 0xF7CD, 0x514E, 0xF7CE, 0x5410, 0xF7CF, 0x571F, 0xF7D0, 0x8A0E, 0xF7D1, 0x615F, 0xF7D2, 0x6876, + 0xF7D3, 0xFA05, 0xF7D4, 0x75DB, 0xF7D5, 0x7B52, 0xF7D6, 0x7D71, 0xF7D7, 0x901A, 0xF7D8, 0x5806, 0xF7D9, 0x69CC, 0xF7DA, 0x817F, + 0xF7DB, 0x892A, 0xF7DC, 0x9000, 0xF7DD, 0x9839, 0xF7DE, 0x5078, 0xF7DF, 0x5957, 0xF7E0, 0x59AC, 0xF7E1, 0x6295, 0xF7E2, 0x900F, + 0xF7E3, 0x9B2A, 0xF7E4, 0x615D, 0xF7E5, 0x7279, 0xF7E6, 0x95D6, 0xF7E7, 0x5761, 0xF7E8, 0x5A46, 0xF7E9, 0x5DF4, 0xF7EA, 0x628A, + 0xF7EB, 0x64AD, 0xF7EC, 0x64FA, 0xF7ED, 0x6777, 0xF7EE, 0x6CE2, 0xF7EF, 0x6D3E, 0xF7F0, 0x722C, 0xF7F1, 0x7436, 0xF7F2, 0x7834, + 0xF7F3, 0x7F77, 0xF7F4, 0x82AD, 0xF7F5, 0x8DDB, 0xF7F6, 0x9817, 0xF7F7, 0x5224, 0xF7F8, 0x5742, 0xF7F9, 0x677F, 0xF7FA, 0x7248, + 0xF7FB, 0x74E3, 0xF7FC, 0x8CA9, 0xF7FD, 0x8FA6, 0xF7FE, 0x9211, 0xF8A1, 0x962A, 0xF8A2, 0x516B, 0xF8A3, 0x53ED, 0xF8A4, 0x634C, + 0xF8A5, 0x4F69, 0xF8A6, 0x5504, 0xF8A7, 0x6096, 0xF8A8, 0x6557, 0xF8A9, 0x6C9B, 0xF8AA, 0x6D7F, 0xF8AB, 0x724C, 0xF8AC, 0x72FD, + 0xF8AD, 0x7A17, 0xF8AE, 0x8987, 0xF8AF, 0x8C9D, 0xF8B0, 0x5F6D, 0xF8B1, 0x6F8E, 0xF8B2, 0x70F9, 0xF8B3, 0x81A8, 0xF8B4, 0x610E, + 0xF8B5, 0x4FBF, 0xF8B6, 0x504F, 0xF8B7, 0x6241, 0xF8B8, 0x7247, 0xF8B9, 0x7BC7, 0xF8BA, 0x7DE8, 0xF8BB, 0x7FE9, 0xF8BC, 0x904D, + 0xF8BD, 0x97AD, 0xF8BE, 0x9A19, 0xF8BF, 0x8CB6, 0xF8C0, 0x576A, 0xF8C1, 0x5E73, 0xF8C2, 0x67B0, 0xF8C3, 0x840D, 0xF8C4, 0x8A55, + 0xF8C5, 0x5420, 0xF8C6, 0x5B16, 0xF8C7, 0x5E63, 0xF8C8, 0x5EE2, 0xF8C9, 0x5F0A, 0xF8CA, 0x6583, 0xF8CB, 0x80BA, 0xF8CC, 0x853D, + 0xF8CD, 0x9589, 0xF8CE, 0x965B, 0xF8CF, 0x4F48, 0xF8D0, 0x5305, 0xF8D1, 0x530D, 0xF8D2, 0x530F, 0xF8D3, 0x5486, 0xF8D4, 0x54FA, + 0xF8D5, 0x5703, 0xF8D6, 0x5E03, 0xF8D7, 0x6016, 0xF8D8, 0x629B, 0xF8D9, 0x62B1, 0xF8DA, 0x6355, 0xF8DB, 0xFA06, 0xF8DC, 0x6CE1, + 0xF8DD, 0x6D66, 0xF8DE, 0x75B1, 0xF8DF, 0x7832, 0xF8E0, 0x80DE, 0xF8E1, 0x812F, 0xF8E2, 0x82DE, 0xF8E3, 0x8461, 0xF8E4, 0x84B2, + 0xF8E5, 0x888D, 0xF8E6, 0x8912, 0xF8E7, 0x900B, 0xF8E8, 0x92EA, 0xF8E9, 0x98FD, 0xF8EA, 0x9B91, 0xF8EB, 0x5E45, 0xF8EC, 0x66B4, + 0xF8ED, 0x66DD, 0xF8EE, 0x7011, 0xF8EF, 0x7206, 0xF8F0, 0xFA07, 0xF8F1, 0x4FF5, 0xF8F2, 0x527D, 0xF8F3, 0x5F6A, 0xF8F4, 0x6153, + 0xF8F5, 0x6753, 0xF8F6, 0x6A19, 0xF8F7, 0x6F02, 0xF8F8, 0x74E2, 0xF8F9, 0x7968, 0xF8FA, 0x8868, 0xF8FB, 0x8C79, 0xF8FC, 0x98C7, + 0xF8FD, 0x98C4, 0xF8FE, 0x9A43, 0xF9A1, 0x54C1, 0xF9A2, 0x7A1F, 0xF9A3, 0x6953, 0xF9A4, 0x8AF7, 0xF9A5, 0x8C4A, 0xF9A6, 0x98A8, + 0xF9A7, 0x99AE, 0xF9A8, 0x5F7C, 0xF9A9, 0x62AB, 0xF9AA, 0x75B2, 0xF9AB, 0x76AE, 0xF9AC, 0x88AB, 0xF9AD, 0x907F, 0xF9AE, 0x9642, + 0xF9AF, 0x5339, 0xF9B0, 0x5F3C, 0xF9B1, 0x5FC5, 0xF9B2, 0x6CCC, 0xF9B3, 0x73CC, 0xF9B4, 0x7562, 0xF9B5, 0x758B, 0xF9B6, 0x7B46, + 0xF9B7, 0x82FE, 0xF9B8, 0x999D, 0xF9B9, 0x4E4F, 0xF9BA, 0x903C, 0xF9BB, 0x4E0B, 0xF9BC, 0x4F55, 0xF9BD, 0x53A6, 0xF9BE, 0x590F, + 0xF9BF, 0x5EC8, 0xF9C0, 0x6630, 0xF9C1, 0x6CB3, 0xF9C2, 0x7455, 0xF9C3, 0x8377, 0xF9C4, 0x8766, 0xF9C5, 0x8CC0, 0xF9C6, 0x9050, + 0xF9C7, 0x971E, 0xF9C8, 0x9C15, 0xF9C9, 0x58D1, 0xF9CA, 0x5B78, 0xF9CB, 0x8650, 0xF9CC, 0x8B14, 0xF9CD, 0x9DB4, 0xF9CE, 0x5BD2, + 0xF9CF, 0x6068, 0xF9D0, 0x608D, 0xF9D1, 0x65F1, 0xF9D2, 0x6C57, 0xF9D3, 0x6F22, 0xF9D4, 0x6FA3, 0xF9D5, 0x701A, 0xF9D6, 0x7F55, + 0xF9D7, 0x7FF0, 0xF9D8, 0x9591, 0xF9D9, 0x9592, 0xF9DA, 0x9650, 0xF9DB, 0x97D3, 0xF9DC, 0x5272, 0xF9DD, 0x8F44, 0xF9DE, 0x51FD, + 0xF9DF, 0x542B, 0xF9E0, 0x54B8, 0xF9E1, 0x5563, 0xF9E2, 0x558A, 0xF9E3, 0x6ABB, 0xF9E4, 0x6DB5, 0xF9E5, 0x7DD8, 0xF9E6, 0x8266, + 0xF9E7, 0x929C, 0xF9E8, 0x9677, 0xF9E9, 0x9E79, 0xF9EA, 0x5408, 0xF9EB, 0x54C8, 0xF9EC, 0x76D2, 0xF9ED, 0x86E4, 0xF9EE, 0x95A4, + 0xF9EF, 0x95D4, 0xF9F0, 0x965C, 0xF9F1, 0x4EA2, 0xF9F2, 0x4F09, 0xF9F3, 0x59EE, 0xF9F4, 0x5AE6, 0xF9F5, 0x5DF7, 0xF9F6, 0x6052, + 0xF9F7, 0x6297, 0xF9F8, 0x676D, 0xF9F9, 0x6841, 0xF9FA, 0x6C86, 0xF9FB, 0x6E2F, 0xF9FC, 0x7F38, 0xF9FD, 0x809B, 0xF9FE, 0x822A, + 0xFAA1, 0xFA08, 0xFAA2, 0xFA09, 0xFAA3, 0x9805, 0xFAA4, 0x4EA5, 0xFAA5, 0x5055, 0xFAA6, 0x54B3, 0xFAA7, 0x5793, 0xFAA8, 0x595A, + 0xFAA9, 0x5B69, 0xFAAA, 0x5BB3, 0xFAAB, 0x61C8, 0xFAAC, 0x6977, 0xFAAD, 0x6D77, 0xFAAE, 0x7023, 0xFAAF, 0x87F9, 0xFAB0, 0x89E3, + 0xFAB1, 0x8A72, 0xFAB2, 0x8AE7, 0xFAB3, 0x9082, 0xFAB4, 0x99ED, 0xFAB5, 0x9AB8, 0xFAB6, 0x52BE, 0xFAB7, 0x6838, 0xFAB8, 0x5016, + 0xFAB9, 0x5E78, 0xFABA, 0x674F, 0xFABB, 0x8347, 0xFABC, 0x884C, 0xFABD, 0x4EAB, 0xFABE, 0x5411, 0xFABF, 0x56AE, 0xFAC0, 0x73E6, + 0xFAC1, 0x9115, 0xFAC2, 0x97FF, 0xFAC3, 0x9909, 0xFAC4, 0x9957, 0xFAC5, 0x9999, 0xFAC6, 0x5653, 0xFAC7, 0x589F, 0xFAC8, 0x865B, + 0xFAC9, 0x8A31, 0xFACA, 0x61B2, 0xFACB, 0x6AF6, 0xFACC, 0x737B, 0xFACD, 0x8ED2, 0xFACE, 0x6B47, 0xFACF, 0x96AA, 0xFAD0, 0x9A57, + 0xFAD1, 0x5955, 0xFAD2, 0x7200, 0xFAD3, 0x8D6B, 0xFAD4, 0x9769, 0xFAD5, 0x4FD4, 0xFAD6, 0x5CF4, 0xFAD7, 0x5F26, 0xFAD8, 0x61F8, + 0xFAD9, 0x665B, 0xFADA, 0x6CEB, 0xFADB, 0x70AB, 0xFADC, 0x7384, 0xFADD, 0x73B9, 0xFADE, 0x73FE, 0xFADF, 0x7729, 0xFAE0, 0x774D, + 0xFAE1, 0x7D43, 0xFAE2, 0x7D62, 0xFAE3, 0x7E23, 0xFAE4, 0x8237, 0xFAE5, 0x8852, 0xFAE6, 0xFA0A, 0xFAE7, 0x8CE2, 0xFAE8, 0x9249, + 0xFAE9, 0x986F, 0xFAEA, 0x5B51, 0xFAEB, 0x7A74, 0xFAEC, 0x8840, 0xFAED, 0x9801, 0xFAEE, 0x5ACC, 0xFAEF, 0x4FE0, 0xFAF0, 0x5354, + 0xFAF1, 0x593E, 0xFAF2, 0x5CFD, 0xFAF3, 0x633E, 0xFAF4, 0x6D79, 0xFAF5, 0x72F9, 0xFAF6, 0x8105, 0xFAF7, 0x8107, 0xFAF8, 0x83A2, + 0xFAF9, 0x92CF, 0xFAFA, 0x9830, 0xFAFB, 0x4EA8, 0xFAFC, 0x5144, 0xFAFD, 0x5211, 0xFAFE, 0x578B, 0xFBA1, 0x5F62, 0xFBA2, 0x6CC2, + 0xFBA3, 0x6ECE, 0xFBA4, 0x7005, 0xFBA5, 0x7050, 0xFBA6, 0x70AF, 0xFBA7, 0x7192, 0xFBA8, 0x73E9, 0xFBA9, 0x7469, 0xFBAA, 0x834A, + 0xFBAB, 0x87A2, 0xFBAC, 0x8861, 0xFBAD, 0x9008, 0xFBAE, 0x90A2, 0xFBAF, 0x93A3, 0xFBB0, 0x99A8, 0xFBB1, 0x516E, 0xFBB2, 0x5F57, + 0xFBB3, 0x60E0, 0xFBB4, 0x6167, 0xFBB5, 0x66B3, 0xFBB6, 0x8559, 0xFBB7, 0x8E4A, 0xFBB8, 0x91AF, 0xFBB9, 0x978B, 0xFBBA, 0x4E4E, + 0xFBBB, 0x4E92, 0xFBBC, 0x547C, 0xFBBD, 0x58D5, 0xFBBE, 0x58FA, 0xFBBF, 0x597D, 0xFBC0, 0x5CB5, 0xFBC1, 0x5F27, 0xFBC2, 0x6236, + 0xFBC3, 0x6248, 0xFBC4, 0x660A, 0xFBC5, 0x6667, 0xFBC6, 0x6BEB, 0xFBC7, 0x6D69, 0xFBC8, 0x6DCF, 0xFBC9, 0x6E56, 0xFBCA, 0x6EF8, + 0xFBCB, 0x6F94, 0xFBCC, 0x6FE0, 0xFBCD, 0x6FE9, 0xFBCE, 0x705D, 0xFBCF, 0x72D0, 0xFBD0, 0x7425, 0xFBD1, 0x745A, 0xFBD2, 0x74E0, + 0xFBD3, 0x7693, 0xFBD4, 0x795C, 0xFBD5, 0x7CCA, 0xFBD6, 0x7E1E, 0xFBD7, 0x80E1, 0xFBD8, 0x82A6, 0xFBD9, 0x846B, 0xFBDA, 0x84BF, + 0xFBDB, 0x864E, 0xFBDC, 0x865F, 0xFBDD, 0x8774, 0xFBDE, 0x8B77, 0xFBDF, 0x8C6A, 0xFBE0, 0x93AC, 0xFBE1, 0x9800, 0xFBE2, 0x9865, + 0xFBE3, 0x60D1, 0xFBE4, 0x6216, 0xFBE5, 0x9177, 0xFBE6, 0x5A5A, 0xFBE7, 0x660F, 0xFBE8, 0x6DF7, 0xFBE9, 0x6E3E, 0xFBEA, 0x743F, + 0xFBEB, 0x9B42, 0xFBEC, 0x5FFD, 0xFBED, 0x60DA, 0xFBEE, 0x7B0F, 0xFBEF, 0x54C4, 0xFBF0, 0x5F18, 0xFBF1, 0x6C5E, 0xFBF2, 0x6CD3, + 0xFBF3, 0x6D2A, 0xFBF4, 0x70D8, 0xFBF5, 0x7D05, 0xFBF6, 0x8679, 0xFBF7, 0x8A0C, 0xFBF8, 0x9D3B, 0xFBF9, 0x5316, 0xFBFA, 0x548C, + 0xFBFB, 0x5B05, 0xFBFC, 0x6A3A, 0xFBFD, 0x706B, 0xFBFE, 0x7575, 0xFCA1, 0x798D, 0xFCA2, 0x79BE, 0xFCA3, 0x82B1, 0xFCA4, 0x83EF, + 0xFCA5, 0x8A71, 0xFCA6, 0x8B41, 0xFCA7, 0x8CA8, 0xFCA8, 0x9774, 0xFCA9, 0xFA0B, 0xFCAA, 0x64F4, 0xFCAB, 0x652B, 0xFCAC, 0x78BA, + 0xFCAD, 0x78BB, 0xFCAE, 0x7A6B, 0xFCAF, 0x4E38, 0xFCB0, 0x559A, 0xFCB1, 0x5950, 0xFCB2, 0x5BA6, 0xFCB3, 0x5E7B, 0xFCB4, 0x60A3, + 0xFCB5, 0x63DB, 0xFCB6, 0x6B61, 0xFCB7, 0x6665, 0xFCB8, 0x6853, 0xFCB9, 0x6E19, 0xFCBA, 0x7165, 0xFCBB, 0x74B0, 0xFCBC, 0x7D08, + 0xFCBD, 0x9084, 0xFCBE, 0x9A69, 0xFCBF, 0x9C25, 0xFCC0, 0x6D3B, 0xFCC1, 0x6ED1, 0xFCC2, 0x733E, 0xFCC3, 0x8C41, 0xFCC4, 0x95CA, + 0xFCC5, 0x51F0, 0xFCC6, 0x5E4C, 0xFCC7, 0x5FA8, 0xFCC8, 0x604D, 0xFCC9, 0x60F6, 0xFCCA, 0x6130, 0xFCCB, 0x614C, 0xFCCC, 0x6643, + 0xFCCD, 0x6644, 0xFCCE, 0x69A5, 0xFCCF, 0x6CC1, 0xFCD0, 0x6E5F, 0xFCD1, 0x6EC9, 0xFCD2, 0x6F62, 0xFCD3, 0x714C, 0xFCD4, 0x749C, + 0xFCD5, 0x7687, 0xFCD6, 0x7BC1, 0xFCD7, 0x7C27, 0xFCD8, 0x8352, 0xFCD9, 0x8757, 0xFCDA, 0x9051, 0xFCDB, 0x968D, 0xFCDC, 0x9EC3, + 0xFCDD, 0x532F, 0xFCDE, 0x56DE, 0xFCDF, 0x5EFB, 0xFCE0, 0x5F8A, 0xFCE1, 0x6062, 0xFCE2, 0x6094, 0xFCE3, 0x61F7, 0xFCE4, 0x6666, + 0xFCE5, 0x6703, 0xFCE6, 0x6A9C, 0xFCE7, 0x6DEE, 0xFCE8, 0x6FAE, 0xFCE9, 0x7070, 0xFCEA, 0x736A, 0xFCEB, 0x7E6A, 0xFCEC, 0x81BE, + 0xFCED, 0x8334, 0xFCEE, 0x86D4, 0xFCEF, 0x8AA8, 0xFCF0, 0x8CC4, 0xFCF1, 0x5283, 0xFCF2, 0x7372, 0xFCF3, 0x5B96, 0xFCF4, 0x6A6B, + 0xFCF5, 0x9404, 0xFCF6, 0x54EE, 0xFCF7, 0x5686, 0xFCF8, 0x5B5D, 0xFCF9, 0x6548, 0xFCFA, 0x6585, 0xFCFB, 0x66C9, 0xFCFC, 0x689F, + 0xFCFD, 0x6D8D, 0xFCFE, 0x6DC6, 0xFDA1, 0x723B, 0xFDA2, 0x80B4, 0xFDA3, 0x9175, 0xFDA4, 0x9A4D, 0xFDA5, 0x4FAF, 0xFDA6, 0x5019, + 0xFDA7, 0x539A, 0xFDA8, 0x540E, 0xFDA9, 0x543C, 0xFDAA, 0x5589, 0xFDAB, 0x55C5, 0xFDAC, 0x5E3F, 0xFDAD, 0x5F8C, 0xFDAE, 0x673D, + 0xFDAF, 0x7166, 0xFDB0, 0x73DD, 0xFDB1, 0x9005, 0xFDB2, 0x52DB, 0xFDB3, 0x52F3, 0xFDB4, 0x5864, 0xFDB5, 0x58CE, 0xFDB6, 0x7104, + 0xFDB7, 0x718F, 0xFDB8, 0x71FB, 0xFDB9, 0x85B0, 0xFDBA, 0x8A13, 0xFDBB, 0x6688, 0xFDBC, 0x85A8, 0xFDBD, 0x55A7, 0xFDBE, 0x6684, + 0xFDBF, 0x714A, 0xFDC0, 0x8431, 0xFDC1, 0x5349, 0xFDC2, 0x5599, 0xFDC3, 0x6BC1, 0xFDC4, 0x5F59, 0xFDC5, 0x5FBD, 0xFDC6, 0x63EE, + 0xFDC7, 0x6689, 0xFDC8, 0x7147, 0xFDC9, 0x8AF1, 0xFDCA, 0x8F1D, 0xFDCB, 0x9EBE, 0xFDCC, 0x4F11, 0xFDCD, 0x643A, 0xFDCE, 0x70CB, + 0xFDCF, 0x7566, 0xFDD0, 0x8667, 0xFDD1, 0x6064, 0xFDD2, 0x8B4E, 0xFDD3, 0x9DF8, 0xFDD4, 0x5147, 0xFDD5, 0x51F6, 0xFDD6, 0x5308, + 0xFDD7, 0x6D36, 0xFDD8, 0x80F8, 0xFDD9, 0x9ED1, 0xFDDA, 0x6615, 0xFDDB, 0x6B23, 0xFDDC, 0x7098, 0xFDDD, 0x75D5, 0xFDDE, 0x5403, + 0xFDDF, 0x5C79, 0xFDE0, 0x7D07, 0xFDE1, 0x8A16, 0xFDE2, 0x6B20, 0xFDE3, 0x6B3D, 0xFDE4, 0x6B46, 0xFDE5, 0x5438, 0xFDE6, 0x6070, + 0xFDE7, 0x6D3D, 0xFDE8, 0x7FD5, 0xFDE9, 0x8208, 0xFDEA, 0x50D6, 0xFDEB, 0x51DE, 0xFDEC, 0x559C, 0xFDED, 0x566B, 0xFDEE, 0x56CD, + 0xFDEF, 0x59EC, 0xFDF0, 0x5B09, 0xFDF1, 0x5E0C, 0xFDF2, 0x6199, 0xFDF3, 0x6198, 0xFDF4, 0x6231, 0xFDF5, 0x665E, 0xFDF6, 0x66E6, + 0xFDF7, 0x7199, 0xFDF8, 0x71B9, 0xFDF9, 0x71BA, 0xFDFA, 0x72A7, 0xFDFB, 0x79A7, 0xFDFC, 0x7A00, 0xFDFD, 0x7FB2, 0xFDFE, 0x8A70, + 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */ +static const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */ + 0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE, + 0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346, + 0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E, + 0x039C, 0xA34F, 0x039D, 0xA350, 0x039E, 0xA351, 0x039F, 0xA352, 0x03A0, 0xA353, 0x03A1, 0xA354, 0x03A3, 0xA355, 0x03A4, 0xA356, + 0x03A5, 0xA357, 0x03A6, 0xA358, 0x03A7, 0xA359, 0x03A8, 0xA35A, 0x03A9, 0xA35B, 0x03B1, 0xA35C, 0x03B2, 0xA35D, 0x03B3, 0xA35E, + 0x03B4, 0xA35F, 0x03B5, 0xA360, 0x03B6, 0xA361, 0x03B7, 0xA362, 0x03B8, 0xA363, 0x03B9, 0xA364, 0x03BA, 0xA365, 0x03BB, 0xA366, + 0x03BC, 0xA367, 0x03BD, 0xA368, 0x03BE, 0xA369, 0x03BF, 0xA36A, 0x03C0, 0xA36B, 0x03C1, 0xA36C, 0x03C3, 0xA36D, 0x03C4, 0xA36E, + 0x03C5, 0xA36F, 0x03C6, 0xA370, 0x03C7, 0xA371, 0x03C8, 0xA372, 0x03C9, 0xA373, 0x2013, 0xA156, 0x2014, 0xA158, 0x2018, 0xA1A5, + 0x2019, 0xA1A6, 0x201C, 0xA1A7, 0x201D, 0xA1A8, 0x2025, 0xA14C, 0x2026, 0xA14B, 0x2027, 0xA145, 0x2032, 0xA1AC, 0x2035, 0xA1AB, + 0x203B, 0xA1B0, 0x20AC, 0xA3E1, 0x2103, 0xA24A, 0x2105, 0xA1C1, 0x2109, 0xA24B, 0x2160, 0xA2B9, 0x2161, 0xA2BA, 0x2162, 0xA2BB, + 0x2163, 0xA2BC, 0x2164, 0xA2BD, 0x2165, 0xA2BE, 0x2166, 0xA2BF, 0x2167, 0xA2C0, 0x2168, 0xA2C1, 0x2169, 0xA2C2, 0x2190, 0xA1F6, + 0x2191, 0xA1F4, 0x2192, 0xA1F7, 0x2193, 0xA1F5, 0x2196, 0xA1F8, 0x2197, 0xA1F9, 0x2198, 0xA1FB, 0x2199, 0xA1FA, 0x2215, 0xA241, + 0x221A, 0xA1D4, 0x221E, 0xA1DB, 0x221F, 0xA1E8, 0x2220, 0xA1E7, 0x2223, 0xA1FD, 0x2225, 0xA1FC, 0x2229, 0xA1E4, 0x222A, 0xA1E5, + 0x222B, 0xA1EC, 0x222E, 0xA1ED, 0x2234, 0xA1EF, 0x2235, 0xA1EE, 0x2252, 0xA1DC, 0x2260, 0xA1DA, 0x2261, 0xA1DD, 0x2266, 0xA1D8, + 0x2267, 0xA1D9, 0x2295, 0xA1F2, 0x2299, 0xA1F3, 0x22A5, 0xA1E6, 0x22BF, 0xA1E9, 0x2500, 0xA277, 0x2502, 0xA278, 0x250C, 0xA27A, + 0x2510, 0xA27B, 0x2514, 0xA27C, 0x2518, 0xA27D, 0x251C, 0xA275, 0x2524, 0xA274, 0x252C, 0xA273, 0x2534, 0xA272, 0x253C, 0xA271, + 0x2550, 0xA2A4, 0x2550, 0xF9F9, 0x2551, 0xF9F8, 0x2552, 0xF9E6, 0x2553, 0xF9EF, 0x2554, 0xF9DD, 0x2555, 0xF9E8, 0x2556, 0xF9F1, + 0x2557, 0xF9DF, 0x2558, 0xF9EC, 0x2559, 0xF9F5, 0x255A, 0xF9E3, 0x255B, 0xF9EE, 0x255C, 0xF9F7, 0x255D, 0xF9E5, 0x255E, 0xA2A5, + 0x255E, 0xF9E9, 0x255F, 0xF9F2, 0x2560, 0xF9E0, 0x2561, 0xA2A7, 0x2561, 0xF9EB, 0x2562, 0xF9F4, 0x2563, 0xF9E2, 0x2564, 0xF9E7, + 0x2565, 0xF9F0, 0x2566, 0xF9DE, 0x2567, 0xF9ED, 0x2568, 0xF9F6, 0x2569, 0xF9E4, 0x256A, 0xA2A6, 0x256A, 0xF9EA, 0x256B, 0xF9F3, + 0x256C, 0xF9E1, 0x256D, 0xA27E, 0x256D, 0xF9FA, 0x256E, 0xA2A1, 0x256E, 0xF9FB, 0x256F, 0xA2A3, 0x256F, 0xF9FD, 0x2570, 0xA2A2, + 0x2570, 0xF9FC, 0x2571, 0xA2AC, 0x2572, 0xA2AD, 0x2573, 0xA2AE, 0x2574, 0xA15A, 0x2581, 0xA262, 0x2582, 0xA263, 0x2583, 0xA264, + 0x2584, 0xA265, 0x2585, 0xA266, 0x2586, 0xA267, 0x2587, 0xA268, 0x2588, 0xA269, 0x2589, 0xA270, 0x258A, 0xA26F, 0x258B, 0xA26E, + 0x258C, 0xA26D, 0x258D, 0xA26C, 0x258E, 0xA26B, 0x258F, 0xA26A, 0x2593, 0xF9FE, 0x2594, 0xA276, 0x2595, 0xA279, 0x25A0, 0xA1BD, + 0x25A1, 0xA1BC, 0x25B2, 0xA1B6, 0x25B3, 0xA1B5, 0x25BC, 0xA1BF, 0x25BD, 0xA1BE, 0x25C6, 0xA1BB, 0x25C7, 0xA1BA, 0x25CB, 0xA1B3, + 0x25CE, 0xA1B7, 0x25CF, 0xA1B4, 0x25E2, 0xA2A8, 0x25E3, 0xA2A9, 0x25E4, 0xA2AB, 0x25E5, 0xA2AA, 0x2605, 0xA1B9, 0x2606, 0xA1B8, + 0x2640, 0xA1F0, 0x2642, 0xA1F1, 0x3000, 0xA140, 0x3001, 0xA142, 0x3002, 0xA143, 0x3003, 0xA1B2, 0x3008, 0xA171, 0x3009, 0xA172, + 0x300A, 0xA16D, 0x300B, 0xA16E, 0x300C, 0xA175, 0x300D, 0xA176, 0x300E, 0xA179, 0x300F, 0xA17A, 0x3010, 0xA169, 0x3011, 0xA16A, + 0x3012, 0xA245, 0x3014, 0xA165, 0x3015, 0xA166, 0x301D, 0xA1A9, 0x301E, 0xA1AA, 0x3021, 0xA2C3, 0x3022, 0xA2C4, 0x3023, 0xA2C5, + 0x3024, 0xA2C6, 0x3025, 0xA2C7, 0x3026, 0xA2C8, 0x3027, 0xA2C9, 0x3028, 0xA2CA, 0x3029, 0xA2CB, 0x3105, 0xA374, 0x3106, 0xA375, + 0x3107, 0xA376, 0x3108, 0xA377, 0x3109, 0xA378, 0x310A, 0xA379, 0x310B, 0xA37A, 0x310C, 0xA37B, 0x310D, 0xA37C, 0x310E, 0xA37D, + 0x310F, 0xA37E, 0x3110, 0xA3A1, 0x3111, 0xA3A2, 0x3112, 0xA3A3, 0x3113, 0xA3A4, 0x3114, 0xA3A5, 0x3115, 0xA3A6, 0x3116, 0xA3A7, + 0x3117, 0xA3A8, 0x3118, 0xA3A9, 0x3119, 0xA3AA, 0x311A, 0xA3AB, 0x311B, 0xA3AC, 0x311C, 0xA3AD, 0x311D, 0xA3AE, 0x311E, 0xA3AF, + 0x311F, 0xA3B0, 0x3120, 0xA3B1, 0x3121, 0xA3B2, 0x3122, 0xA3B3, 0x3123, 0xA3B4, 0x3124, 0xA3B5, 0x3125, 0xA3B6, 0x3126, 0xA3B7, + 0x3127, 0xA3B8, 0x3128, 0xA3B9, 0x3129, 0xA3BA, 0x32A3, 0xA1C0, 0x338E, 0xA255, 0x338F, 0xA256, 0x339C, 0xA250, 0x339D, 0xA251, + 0x339E, 0xA252, 0x33A1, 0xA254, 0x33C4, 0xA257, 0x33CE, 0xA253, 0x33D1, 0xA1EB, 0x33D2, 0xA1EA, 0x33D5, 0xA24F, 0x4E00, 0xA440, + 0x4E01, 0xA442, 0x4E03, 0xA443, 0x4E07, 0xC945, 0x4E08, 0xA456, 0x4E09, 0xA454, 0x4E0A, 0xA457, 0x4E0B, 0xA455, 0x4E0C, 0xC946, + 0x4E0D, 0xA4A3, 0x4E0E, 0xC94F, 0x4E0F, 0xC94D, 0x4E10, 0xA4A2, 0x4E11, 0xA4A1, 0x4E14, 0xA542, 0x4E15, 0xA541, 0x4E16, 0xA540, + 0x4E18, 0xA543, 0x4E19, 0xA4FE, 0x4E1E, 0xA5E0, 0x4E1F, 0xA5E1, 0x4E26, 0xA8C3, 0x4E2B, 0xA458, 0x4E2D, 0xA4A4, 0x4E2E, 0xC950, + 0x4E30, 0xA4A5, 0x4E31, 0xC963, 0x4E32, 0xA6EA, 0x4E33, 0xCBB1, 0x4E38, 0xA459, 0x4E39, 0xA4A6, 0x4E3B, 0xA544, 0x4E3C, 0xC964, + 0x4E42, 0xC940, 0x4E43, 0xA444, 0x4E45, 0xA45B, 0x4E47, 0xC947, 0x4E48, 0xA45C, 0x4E4B, 0xA4A7, 0x4E4D, 0xA545, 0x4E4E, 0xA547, + 0x4E4F, 0xA546, 0x4E52, 0xA5E2, 0x4E53, 0xA5E3, 0x4E56, 0xA8C4, 0x4E58, 0xADBC, 0x4E59, 0xA441, 0x4E5C, 0xC941, 0x4E5D, 0xA445, + 0x4E5E, 0xA45E, 0x4E5F, 0xA45D, 0x4E69, 0xA5E4, 0x4E73, 0xA8C5, 0x4E7E, 0xB0AE, 0x4E7F, 0xD44B, 0x4E82, 0xB6C3, 0x4E83, 0xDCB1, + 0x4E84, 0xDCB2, 0x4E86, 0xA446, 0x4E88, 0xA4A9, 0x4E8B, 0xA8C6, 0x4E8C, 0xA447, 0x4E8D, 0xC948, 0x4E8E, 0xA45F, 0x4E91, 0xA4AA, + 0x4E92, 0xA4AC, 0x4E93, 0xC951, 0x4E94, 0xA4AD, 0x4E95, 0xA4AB, 0x4E99, 0xA5E5, 0x4E9B, 0xA8C7, 0x4E9E, 0xA8C8, 0x4E9F, 0xAB45, + 0x4EA1, 0xA460, 0x4EA2, 0xA4AE, 0x4EA4, 0xA5E6, 0x4EA5, 0xA5E8, 0x4EA6, 0xA5E7, 0x4EA8, 0xA6EB, 0x4EAB, 0xA8C9, 0x4EAC, 0xA8CA, + 0x4EAD, 0xAB46, 0x4EAE, 0xAB47, 0x4EB3, 0xADBD, 0x4EB6, 0xDCB3, 0x4EB9, 0xF6D6, 0x4EBA, 0xA448, 0x4EC0, 0xA4B0, 0x4EC1, 0xA4AF, + 0x4EC2, 0xC952, 0x4EC3, 0xA4B1, 0x4EC4, 0xA4B7, 0x4EC6, 0xA4B2, 0x4EC7, 0xA4B3, 0x4EC8, 0xC954, 0x4EC9, 0xC953, 0x4ECA, 0xA4B5, + 0x4ECB, 0xA4B6, 0x4ECD, 0xA4B4, 0x4ED4, 0xA54A, 0x4ED5, 0xA54B, 0x4ED6, 0xA54C, 0x4ED7, 0xA54D, 0x4ED8, 0xA549, 0x4ED9, 0xA550, + 0x4EDA, 0xC96A, 0x4EDC, 0xC966, 0x4EDD, 0xC969, 0x4EDE, 0xA551, 0x4EDF, 0xA561, 0x4EE1, 0xC968, 0x4EE3, 0xA54E, 0x4EE4, 0xA54F, + 0x4EE5, 0xA548, 0x4EE8, 0xC965, 0x4EE9, 0xC967, 0x4EF0, 0xA5F5, 0x4EF1, 0xC9B0, 0x4EF2, 0xA5F2, 0x4EF3, 0xA5F6, 0x4EF4, 0xC9BA, + 0x4EF5, 0xC9AE, 0x4EF6, 0xA5F3, 0x4EF7, 0xC9B2, 0x4EFB, 0xA5F4, 0x4EFD, 0xA5F7, 0x4EFF, 0xA5E9, 0x4F00, 0xC9B1, 0x4F01, 0xA5F8, + 0x4F02, 0xC9B5, 0x4F04, 0xC9B9, 0x4F05, 0xC9B6, 0x4F08, 0xC9B3, 0x4F09, 0xA5EA, 0x4F0A, 0xA5EC, 0x4F0B, 0xA5F9, 0x4F0D, 0xA5EE, + 0x4F0E, 0xC9AB, 0x4F0F, 0xA5F1, 0x4F10, 0xA5EF, 0x4F11, 0xA5F0, 0x4F12, 0xC9BB, 0x4F13, 0xC9B8, 0x4F14, 0xC9AF, 0x4F15, 0xA5ED, + 0x4F18, 0xC9AC, 0x4F19, 0xA5EB, 0x4F1D, 0xC9B4, 0x4F22, 0xC9B7, 0x4F2C, 0xC9AD, 0x4F2D, 0xCA66, 0x4F2F, 0xA742, 0x4F30, 0xA6F4, + 0x4F33, 0xCA67, 0x4F34, 0xA6F1, 0x4F36, 0xA744, 0x4F38, 0xA6F9, 0x4F3A, 0xA6F8, 0x4F3B, 0xCA5B, 0x4F3C, 0xA6FC, 0x4F3D, 0xA6F7, + 0x4F3E, 0xCA60, 0x4F3F, 0xCA68, 0x4F41, 0xCA64, 0x4F43, 0xA6FA, 0x4F46, 0xA6FD, 0x4F47, 0xA6EE, 0x4F48, 0xA747, 0x4F49, 0xCA5D, + 0x4F4C, 0xCBBD, 0x4F4D, 0xA6EC, 0x4F4E, 0xA743, 0x4F4F, 0xA6ED, 0x4F50, 0xA6F5, 0x4F51, 0xA6F6, 0x4F52, 0xCA62, 0x4F53, 0xCA5E, + 0x4F54, 0xA6FB, 0x4F55, 0xA6F3, 0x4F56, 0xCA5A, 0x4F57, 0xA6EF, 0x4F58, 0xCA65, 0x4F59, 0xA745, 0x4F5A, 0xA748, 0x4F5B, 0xA6F2, + 0x4F5C, 0xA740, 0x4F5D, 0xA746, 0x4F5E, 0xA6F0, 0x4F5F, 0xCA63, 0x4F60, 0xA741, 0x4F61, 0xCA69, 0x4F62, 0xCA5C, 0x4F63, 0xA6FE, + 0x4F64, 0xCA5F, 0x4F67, 0xCA61, 0x4F69, 0xA8D8, 0x4F6A, 0xCBBF, 0x4F6B, 0xCBCB, 0x4F6C, 0xA8D0, 0x4F6E, 0xCBCC, 0x4F6F, 0xA8CB, + 0x4F70, 0xA8D5, 0x4F73, 0xA8CE, 0x4F74, 0xCBB9, 0x4F75, 0xA8D6, 0x4F76, 0xCBB8, 0x4F77, 0xCBBC, 0x4F78, 0xCBC3, 0x4F79, 0xCBC1, + 0x4F7A, 0xA8DE, 0x4F7B, 0xA8D9, 0x4F7C, 0xCBB3, 0x4F7D, 0xCBB5, 0x4F7E, 0xA8DB, 0x4F7F, 0xA8CF, 0x4F80, 0xCBB6, 0x4F81, 0xCBC2, + 0x4F82, 0xCBC9, 0x4F83, 0xA8D4, 0x4F84, 0xCBBB, 0x4F85, 0xCBB4, 0x4F86, 0xA8D3, 0x4F87, 0xCBB7, 0x4F88, 0xA8D7, 0x4F89, 0xCBBA, + 0x4F8B, 0xA8D2, 0x4F8D, 0xA8CD, 0x4F8F, 0xA8DC, 0x4F90, 0xCBC4, 0x4F91, 0xA8DD, 0x4F92, 0xCBC8, 0x4F94, 0xCBC6, 0x4F95, 0xCBCA, + 0x4F96, 0xA8DA, 0x4F97, 0xCBBE, 0x4F98, 0xCBB2, 0x4F9A, 0xCBC0, 0x4F9B, 0xA8D1, 0x4F9C, 0xCBC5, 0x4F9D, 0xA8CC, 0x4F9E, 0xCBC7, + 0x4FAE, 0xAB56, 0x4FAF, 0xAB4A, 0x4FB2, 0xCDE0, 0x4FB3, 0xCDE8, 0x4FB5, 0xAB49, 0x4FB6, 0xAB51, 0x4FB7, 0xAB5D, 0x4FB9, 0xCDEE, + 0x4FBA, 0xCDEC, 0x4FBB, 0xCDE7, 0x4FBF, 0xAB4B, 0x4FC0, 0xCDED, 0x4FC1, 0xCDE3, 0x4FC2, 0xAB59, 0x4FC3, 0xAB50, 0x4FC4, 0xAB58, + 0x4FC5, 0xCDDE, 0x4FC7, 0xCDEA, 0x4FC9, 0xCDE1, 0x4FCA, 0xAB54, 0x4FCB, 0xCDE2, 0x4FCD, 0xCDDD, 0x4FCE, 0xAB5B, 0x4FCF, 0xAB4E, + 0x4FD0, 0xAB57, 0x4FD1, 0xAB4D, 0x4FD3, 0xCDDF, 0x4FD4, 0xCDE4, 0x4FD6, 0xCDEB, 0x4FD7, 0xAB55, 0x4FD8, 0xAB52, 0x4FD9, 0xCDE6, + 0x4FDA, 0xAB5A, 0x4FDB, 0xCDE9, 0x4FDC, 0xCDE5, 0x4FDD, 0xAB4F, 0x4FDE, 0xAB5C, 0x4FDF, 0xAB53, 0x4FE0, 0xAB4C, 0x4FE1, 0xAB48, + 0x4FEC, 0xCDEF, 0x4FEE, 0xADD7, 0x4FEF, 0xADC1, 0x4FF1, 0xADD1, 0x4FF3, 0xADD6, 0x4FF4, 0xD0D0, 0x4FF5, 0xD0CF, 0x4FF6, 0xD0D4, + 0x4FF7, 0xD0D5, 0x4FF8, 0xADC4, 0x4FFA, 0xADCD, 0x4FFE, 0xADDA, 0x5000, 0xADCE, 0x5005, 0xD0C9, 0x5006, 0xADC7, 0x5007, 0xD0CA, + 0x5009, 0xADDC, 0x500B, 0xADD3, 0x500C, 0xADBE, 0x500D, 0xADBF, 0x500E, 0xD0DD, 0x500F, 0xB0BF, 0x5011, 0xADCC, 0x5012, 0xADCB, + 0x5013, 0xD0CB, 0x5014, 0xADCF, 0x5015, 0xD45B, 0x5016, 0xADC6, 0x5017, 0xD0D6, 0x5018, 0xADD5, 0x5019, 0xADD4, 0x501A, 0xADCA, + 0x501B, 0xD0CE, 0x501C, 0xD0D7, 0x501E, 0xD0C8, 0x501F, 0xADC9, 0x5020, 0xD0D8, 0x5021, 0xADD2, 0x5022, 0xD0CC, 0x5023, 0xADC0, + 0x5025, 0xADC3, 0x5026, 0xADC2, 0x5027, 0xD0D9, 0x5028, 0xADD0, 0x5029, 0xADC5, 0x502A, 0xADD9, 0x502B, 0xADDB, 0x502C, 0xD0D3, + 0x502D, 0xADD8, 0x502F, 0xD0DB, 0x5030, 0xD0CD, 0x5031, 0xD0DC, 0x5033, 0xD0D1, 0x5035, 0xD0DA, 0x5037, 0xD0D2, 0x503C, 0xADC8, + 0x5040, 0xD463, 0x5041, 0xD457, 0x5043, 0xB0B3, 0x5045, 0xD45C, 0x5046, 0xD462, 0x5047, 0xB0B2, 0x5048, 0xD455, 0x5049, 0xB0B6, + 0x504A, 0xD459, 0x504B, 0xD452, 0x504C, 0xB0B4, 0x504D, 0xD456, 0x504E, 0xB0B9, 0x504F, 0xB0BE, 0x5051, 0xD467, 0x5053, 0xD451, + 0x5055, 0xB0BA, 0x5057, 0xD466, 0x505A, 0xB0B5, 0x505B, 0xD458, 0x505C, 0xB0B1, 0x505D, 0xD453, 0x505E, 0xD44F, 0x505F, 0xD45D, + 0x5060, 0xD450, 0x5061, 0xD44E, 0x5062, 0xD45A, 0x5063, 0xD460, 0x5064, 0xD461, 0x5065, 0xB0B7, 0x5068, 0xD85B, 0x5069, 0xD45E, + 0x506A, 0xD44D, 0x506B, 0xD45F, 0x506D, 0xB0C1, 0x506E, 0xD464, 0x506F, 0xB0C0, 0x5070, 0xD44C, 0x5072, 0xD454, 0x5073, 0xD465, + 0x5074, 0xB0BC, 0x5075, 0xB0BB, 0x5076, 0xB0B8, 0x5077, 0xB0BD, 0x507A, 0xB0AF, 0x507D, 0xB0B0, 0x5080, 0xB3C8, 0x5082, 0xD85E, + 0x5083, 0xD857, 0x5085, 0xB3C5, 0x5087, 0xD85F, 0x508B, 0xD855, 0x508C, 0xD858, 0x508D, 0xB3C4, 0x508E, 0xD859, 0x5091, 0xB3C7, + 0x5092, 0xD85D, 0x5094, 0xD853, 0x5095, 0xD852, 0x5096, 0xB3C9, 0x5098, 0xB3CA, 0x5099, 0xB3C6, 0x509A, 0xB3CB, 0x509B, 0xD851, + 0x509C, 0xD85C, 0x509D, 0xD85A, 0x509E, 0xD854, 0x50A2, 0xB3C3, 0x50A3, 0xD856, 0x50AC, 0xB6CA, 0x50AD, 0xB6C4, 0x50AE, 0xDCB7, + 0x50AF, 0xB6CD, 0x50B0, 0xDCBD, 0x50B1, 0xDCC0, 0x50B2, 0xB6C6, 0x50B3, 0xB6C7, 0x50B4, 0xDCBA, 0x50B5, 0xB6C5, 0x50B6, 0xDCC3, + 0x50B7, 0xB6CB, 0x50B8, 0xDCC4, 0x50BA, 0xDCBF, 0x50BB, 0xB6CC, 0x50BD, 0xDCB4, 0x50BE, 0xB6C9, 0x50BF, 0xDCB5, 0x50C1, 0xDCBE, + 0x50C2, 0xDCBC, 0x50C4, 0xDCB8, 0x50C5, 0xB6C8, 0x50C6, 0xDCB6, 0x50C7, 0xB6CE, 0x50C8, 0xDCBB, 0x50C9, 0xDCC2, 0x50CA, 0xDCB9, + 0x50CB, 0xDCC1, 0x50CE, 0xB9B6, 0x50CF, 0xB9B3, 0x50D1, 0xB9B4, 0x50D3, 0xE0F9, 0x50D4, 0xE0F1, 0x50D5, 0xB9B2, 0x50D6, 0xB9AF, + 0x50D7, 0xE0F2, 0x50DA, 0xB9B1, 0x50DB, 0xE0F5, 0x50DD, 0xE0F7, 0x50E0, 0xE0FE, 0x50E3, 0xE0FD, 0x50E4, 0xE0F8, 0x50E5, 0xB9AE, + 0x50E6, 0xE0F0, 0x50E7, 0xB9AC, 0x50E8, 0xE0F3, 0x50E9, 0xB9B7, 0x50EA, 0xE0F6, 0x50EC, 0xE0FA, 0x50ED, 0xB9B0, 0x50EE, 0xB9AD, + 0x50EF, 0xE0FC, 0x50F0, 0xE0FB, 0x50F1, 0xB9B5, 0x50F3, 0xE0F4, 0x50F5, 0xBBF8, 0x50F6, 0xE4EC, 0x50F8, 0xE4E9, 0x50F9, 0xBBF9, + 0x50FB, 0xBBF7, 0x50FD, 0xE4F0, 0x50FE, 0xE4ED, 0x50FF, 0xE4E6, 0x5100, 0xBBF6, 0x5102, 0xBBFA, 0x5103, 0xE4E7, 0x5104, 0xBBF5, + 0x5105, 0xBBFD, 0x5106, 0xE4EA, 0x5107, 0xE4EB, 0x5108, 0xBBFB, 0x5109, 0xBBFC, 0x510A, 0xE4F1, 0x510B, 0xE4EE, 0x510C, 0xE4EF, + 0x5110, 0xBEAA, 0x5111, 0xE8F8, 0x5112, 0xBEA7, 0x5113, 0xE8F5, 0x5114, 0xBEA9, 0x5115, 0xBEAB, 0x5117, 0xE8F6, 0x5118, 0xBEA8, + 0x511A, 0xE8F7, 0x511C, 0xE8F4, 0x511F, 0xC076, 0x5120, 0xECBD, 0x5121, 0xC077, 0x5122, 0xECBB, 0x5124, 0xECBC, 0x5125, 0xECBA, + 0x5126, 0xECB9, 0x5129, 0xECBE, 0x512A, 0xC075, 0x512D, 0xEFB8, 0x512E, 0xEFB9, 0x5130, 0xE4E8, 0x5131, 0xEFB7, 0x5132, 0xC078, + 0x5133, 0xC35F, 0x5134, 0xF1EB, 0x5135, 0xF1EC, 0x5137, 0xC4D7, 0x5138, 0xC4D8, 0x5139, 0xF5C1, 0x513A, 0xF5C0, 0x513B, 0xC56C, + 0x513C, 0xC56B, 0x513D, 0xF7D0, 0x513F, 0xA449, 0x5140, 0xA461, 0x5141, 0xA4B9, 0x5143, 0xA4B8, 0x5144, 0xA553, 0x5145, 0xA552, + 0x5146, 0xA5FC, 0x5147, 0xA5FB, 0x5148, 0xA5FD, 0x5149, 0xA5FA, 0x514B, 0xA74A, 0x514C, 0xA749, 0x514D, 0xA74B, 0x5152, 0xA8E0, + 0x5154, 0xA8DF, 0x5155, 0xA8E1, 0x5157, 0xAB5E, 0x5159, 0xA259, 0x515A, 0xD0DE, 0x515B, 0xA25A, 0x515C, 0xB0C2, 0x515D, 0xA25C, + 0x515E, 0xA25B, 0x515F, 0xD860, 0x5161, 0xA25D, 0x5162, 0xB9B8, 0x5163, 0xA25E, 0x5165, 0xA44A, 0x5167, 0xA4BA, 0x5168, 0xA5FE, + 0x5169, 0xA8E2, 0x516B, 0xA44B, 0x516C, 0xA4BD, 0x516D, 0xA4BB, 0x516E, 0xA4BC, 0x5171, 0xA640, 0x5175, 0xA74C, 0x5176, 0xA8E4, + 0x5177, 0xA8E3, 0x5178, 0xA8E5, 0x517C, 0xADDD, 0x5180, 0xBEAC, 0x5187, 0xC94E, 0x5189, 0xA554, 0x518A, 0xA555, 0x518D, 0xA641, + 0x518F, 0xCA6A, 0x5191, 0xAB60, 0x5192, 0xAB5F, 0x5193, 0xD0E0, 0x5194, 0xD0DF, 0x5195, 0xB0C3, 0x5197, 0xA4BE, 0x5198, 0xC955, + 0x519E, 0xCBCD, 0x51A0, 0xAB61, 0x51A2, 0xADE0, 0x51A4, 0xADDE, 0x51A5, 0xADDF, 0x51AA, 0xBEAD, 0x51AC, 0xA556, 0x51B0, 0xA642, + 0x51B1, 0xC9BC, 0x51B6, 0xA74D, 0x51B7, 0xA74E, 0x51B9, 0xCA6B, 0x51BC, 0xCBCE, 0x51BD, 0xA8E6, 0x51BE, 0xCBCF, 0x51C4, 0xD0E2, + 0x51C5, 0xD0E3, 0x51C6, 0xADE3, 0x51C8, 0xD0E4, 0x51CA, 0xD0E1, 0x51CB, 0xADE4, 0x51CC, 0xADE2, 0x51CD, 0xADE1, 0x51CE, 0xD0E5, + 0x51D0, 0xD468, 0x51D4, 0xD861, 0x51D7, 0xDCC5, 0x51D8, 0xE140, 0x51DC, 0xBBFE, 0x51DD, 0xBEAE, 0x51DE, 0xE8F9, 0x51E0, 0xA44C, + 0x51E1, 0xA45A, 0x51F0, 0xB0C4, 0x51F1, 0xB3CD, 0x51F3, 0xB9B9, 0x51F5, 0xC942, 0x51F6, 0xA4BF, 0x51F8, 0xA559, 0x51F9, 0xA557, + 0x51FA, 0xA558, 0x51FD, 0xA8E7, 0x5200, 0xA44D, 0x5201, 0xA44E, 0x5203, 0xA462, 0x5206, 0xA4C0, 0x5207, 0xA4C1, 0x5208, 0xA4C2, + 0x5209, 0xC9BE, 0x520A, 0xA55A, 0x520C, 0xC96B, 0x520E, 0xA646, 0x5210, 0xC9BF, 0x5211, 0xA644, 0x5212, 0xA645, 0x5213, 0xC9BD, + 0x5216, 0xA647, 0x5217, 0xA643, 0x521C, 0xCA6C, 0x521D, 0xAAEC, 0x521E, 0xCA6D, 0x5221, 0xCA6E, 0x5224, 0xA750, 0x5225, 0xA74F, + 0x5228, 0xA753, 0x5229, 0xA751, 0x522A, 0xA752, 0x522E, 0xA8ED, 0x5230, 0xA8EC, 0x5231, 0xCBD4, 0x5232, 0xCBD1, 0x5233, 0xCBD2, + 0x5235, 0xCBD0, 0x5236, 0xA8EE, 0x5237, 0xA8EA, 0x5238, 0xA8E9, 0x523A, 0xA8EB, 0x523B, 0xA8E8, 0x5241, 0xA8EF, 0x5243, 0xAB63, + 0x5244, 0xCDF0, 0x5246, 0xCBD3, 0x5247, 0xAB68, 0x5249, 0xCDF1, 0x524A, 0xAB64, 0x524B, 0xAB67, 0x524C, 0xAB66, 0x524D, 0xAB65, + 0x524E, 0xAB62, 0x5252, 0xD0E8, 0x5254, 0xADE7, 0x5255, 0xD0EB, 0x5256, 0xADE5, 0x525A, 0xD0E7, 0x525B, 0xADE8, 0x525C, 0xADE6, + 0x525D, 0xADE9, 0x525E, 0xD0E9, 0x525F, 0xD0EA, 0x5261, 0xD0E6, 0x5262, 0xD0EC, 0x5269, 0xB3D1, 0x526A, 0xB0C5, 0x526B, 0xD469, + 0x526C, 0xD46B, 0x526D, 0xD46A, 0x526E, 0xD46C, 0x526F, 0xB0C6, 0x5272, 0xB3CE, 0x5274, 0xB3CF, 0x5275, 0xB3D0, 0x5277, 0xB6D0, + 0x5278, 0xDCC7, 0x527A, 0xDCC6, 0x527B, 0xDCC8, 0x527C, 0xDCC9, 0x527D, 0xB6D1, 0x527F, 0xB6CF, 0x5280, 0xE141, 0x5281, 0xE142, + 0x5282, 0xB9BB, 0x5283, 0xB9BA, 0x5284, 0xE35A, 0x5287, 0xBC40, 0x5288, 0xBC41, 0x5289, 0xBC42, 0x528A, 0xBC44, 0x528B, 0xE4F2, + 0x528C, 0xE4F3, 0x528D, 0xBC43, 0x5291, 0xBEAF, 0x5293, 0xBEB0, 0x5296, 0xF1ED, 0x5297, 0xF5C3, 0x5298, 0xF5C2, 0x5299, 0xF7D1, + 0x529B, 0xA44F, 0x529F, 0xA55C, 0x52A0, 0xA55B, 0x52A3, 0xA648, 0x52A6, 0xC9C0, 0x52A9, 0xA755, 0x52AA, 0xA756, 0x52AB, 0xA754, + 0x52AC, 0xA757, 0x52AD, 0xCA6F, 0x52AE, 0xCA70, 0x52BB, 0xA8F1, 0x52BC, 0xCBD5, 0x52BE, 0xA8F0, 0x52C0, 0xCDF2, 0x52C1, 0xAB6C, + 0x52C2, 0xCDF3, 0x52C3, 0xAB6B, 0x52C7, 0xAB69, 0x52C9, 0xAB6A, 0x52CD, 0xD0ED, 0x52D2, 0xB0C7, 0x52D3, 0xD46E, 0x52D5, 0xB0CA, + 0x52D6, 0xD46D, 0x52D7, 0xB1E5, 0x52D8, 0xB0C9, 0x52D9, 0xB0C8, 0x52DB, 0xB3D4, 0x52DD, 0xB3D3, 0x52DE, 0xB3D2, 0x52DF, 0xB6D2, + 0x52E2, 0xB6D5, 0x52E3, 0xB6D6, 0x52E4, 0xB6D4, 0x52E6, 0xB6D3, 0x52E9, 0xE143, 0x52EB, 0xE144, 0x52EF, 0xE4F5, 0x52F0, 0xBC45, + 0x52F1, 0xE4F4, 0x52F3, 0xBEB1, 0x52F4, 0xECBF, 0x52F5, 0xC079, 0x52F7, 0xF1EE, 0x52F8, 0xC455, 0x52FA, 0xA463, 0x52FB, 0xA4C3, + 0x52FC, 0xC956, 0x52FE, 0xA4C4, 0x52FF, 0xA4C5, 0x5305, 0xA55D, 0x5306, 0xA55E, 0x5308, 0xA649, 0x5309, 0xCA71, 0x530A, 0xCBD6, + 0x530B, 0xCBD7, 0x530D, 0xAB6D, 0x530E, 0xD0EE, 0x530F, 0xB0CC, 0x5310, 0xB0CB, 0x5311, 0xD863, 0x5312, 0xD862, 0x5315, 0xA450, + 0x5316, 0xA4C6, 0x5317, 0xA55F, 0x5319, 0xB0CD, 0x531A, 0xC943, 0x531C, 0xC96C, 0x531D, 0xA560, 0x531F, 0xC9C2, 0x5320, 0xA64B, + 0x5321, 0xA64A, 0x5322, 0xC9C1, 0x5323, 0xA758, 0x532A, 0xADEA, 0x532D, 0xD46F, 0x532F, 0xB6D7, 0x5330, 0xE145, 0x5331, 0xB9BC, + 0x5334, 0xE8FA, 0x5337, 0xF3FD, 0x5339, 0xA4C7, 0x533C, 0xCBD8, 0x533D, 0xCDF4, 0x533E, 0xB0D0, 0x533F, 0xB0CE, 0x5340, 0xB0CF, + 0x5341, 0xA2CC, 0x5341, 0xA451, 0x5343, 0xA464, 0x5344, 0xA2CD, 0x5345, 0xA2CE, 0x5345, 0xA4CA, 0x5347, 0xA4C9, 0x5348, 0xA4C8, + 0x5349, 0xA563, 0x534A, 0xA562, 0x534C, 0xC96D, 0x534D, 0xC9C3, 0x5351, 0xA8F5, 0x5352, 0xA8F2, 0x5353, 0xA8F4, 0x5354, 0xA8F3, + 0x5357, 0xAB6E, 0x535A, 0xB3D5, 0x535C, 0xA452, 0x535E, 0xA4CB, 0x5360, 0xA565, 0x5361, 0xA564, 0x5363, 0xCA72, 0x5366, 0xA8F6, + 0x536C, 0xC957, 0x536E, 0xA567, 0x536F, 0xA566, 0x5370, 0xA64C, 0x5371, 0xA64D, 0x5372, 0xCA73, 0x5373, 0xA759, 0x5375, 0xA75A, + 0x5377, 0xA8F7, 0x5378, 0xA8F8, 0x5379, 0xA8F9, 0x537B, 0xAB6F, 0x537C, 0xCDF5, 0x537F, 0xADEB, 0x5382, 0xC944, 0x5384, 0xA4CC, + 0x538A, 0xC9C4, 0x538E, 0xCA74, 0x538F, 0xCA75, 0x5392, 0xCBD9, 0x5394, 0xCBDA, 0x5396, 0xCDF7, 0x5397, 0xCDF6, 0x5398, 0xCDF9, + 0x5399, 0xCDF8, 0x539A, 0xAB70, 0x539C, 0xD470, 0x539D, 0xADED, 0x539E, 0xD0EF, 0x539F, 0xADEC, 0x53A4, 0xD864, 0x53A5, 0xB3D6, + 0x53A7, 0xD865, 0x53AC, 0xE146, 0x53AD, 0xB9BD, 0x53B2, 0xBC46, 0x53B4, 0xF1EF, 0x53B9, 0xC958, 0x53BB, 0xA568, 0x53C3, 0xB0D1, + 0x53C8, 0xA453, 0x53C9, 0xA465, 0x53CA, 0xA4CE, 0x53CB, 0xA4CD, 0x53CD, 0xA4CF, 0x53D4, 0xA8FB, 0x53D6, 0xA8FA, 0x53D7, 0xA8FC, + 0x53DB, 0xAB71, 0x53DF, 0xADEE, 0x53E1, 0xE8FB, 0x53E2, 0xC24F, 0x53E3, 0xA466, 0x53E4, 0xA56A, 0x53E5, 0xA579, 0x53E6, 0xA574, + 0x53E8, 0xA56F, 0x53E9, 0xA56E, 0x53EA, 0xA575, 0x53EB, 0xA573, 0x53EC, 0xA56C, 0x53ED, 0xA57A, 0x53EE, 0xA56D, 0x53EF, 0xA569, + 0x53F0, 0xA578, 0x53F1, 0xA577, 0x53F2, 0xA576, 0x53F3, 0xA56B, 0x53F5, 0xA572, 0x53F8, 0xA571, 0x53FB, 0xA57B, 0x53FC, 0xA570, + 0x5401, 0xA653, 0x5403, 0xA659, 0x5404, 0xA655, 0x5406, 0xA65B, 0x5407, 0xC9C5, 0x5408, 0xA658, 0x5409, 0xA64E, 0x540A, 0xA651, + 0x540B, 0xA654, 0x540C, 0xA650, 0x540D, 0xA657, 0x540E, 0xA65A, 0x540F, 0xA64F, 0x5410, 0xA652, 0x5411, 0xA656, 0x5412, 0xA65C, + 0x5418, 0xCA7E, 0x5419, 0xCA7B, 0x541B, 0xA767, 0x541C, 0xCA7C, 0x541D, 0xA75B, 0x541E, 0xA75D, 0x541F, 0xA775, 0x5420, 0xA770, + 0x5424, 0xCAA5, 0x5425, 0xCA7D, 0x5426, 0xA75F, 0x5427, 0xA761, 0x5428, 0xCAA4, 0x5429, 0xA768, 0x542A, 0xCA78, 0x542B, 0xA774, + 0x542C, 0xA776, 0x542D, 0xA75C, 0x542E, 0xA76D, 0x5430, 0xCA76, 0x5431, 0xA773, 0x5433, 0xA764, 0x5435, 0xA76E, 0x5436, 0xA76F, + 0x5437, 0xCA77, 0x5438, 0xA76C, 0x5439, 0xA76A, 0x543B, 0xA76B, 0x543C, 0xA771, 0x543D, 0xCAA1, 0x543E, 0xA75E, 0x5440, 0xA772, + 0x5441, 0xCAA3, 0x5442, 0xA766, 0x5443, 0xA763, 0x5445, 0xCA7A, 0x5446, 0xA762, 0x5447, 0xCAA6, 0x5448, 0xA765, 0x544A, 0xA769, + 0x544E, 0xA760, 0x544F, 0xCAA2, 0x5454, 0xCA79, 0x5460, 0xCBEB, 0x5461, 0xCBEA, 0x5462, 0xA94F, 0x5463, 0xCBED, 0x5464, 0xCBEF, + 0x5465, 0xCBE4, 0x5466, 0xCBE7, 0x5467, 0xCBEE, 0x5468, 0xA950, 0x546B, 0xCBE1, 0x546C, 0xCBE5, 0x546F, 0xCBE9, 0x5470, 0xCE49, + 0x5471, 0xA94B, 0x5472, 0xCE4D, 0x5473, 0xA8FD, 0x5474, 0xCBE6, 0x5475, 0xA8FE, 0x5476, 0xA94C, 0x5477, 0xA945, 0x5478, 0xA941, + 0x547A, 0xCBE2, 0x547B, 0xA944, 0x547C, 0xA949, 0x547D, 0xA952, 0x547E, 0xCBE3, 0x547F, 0xCBDC, 0x5480, 0xA943, 0x5481, 0xCBDD, + 0x5482, 0xCBDF, 0x5484, 0xA946, 0x5486, 0xA948, 0x5487, 0xCBDB, 0x5488, 0xCBE0, 0x548B, 0xA951, 0x548C, 0xA94D, 0x548D, 0xCBE8, + 0x548E, 0xA953, 0x5490, 0xA94A, 0x5491, 0xCBDE, 0x5492, 0xA947, 0x5495, 0xA942, 0x5496, 0xA940, 0x5498, 0xCBEC, 0x549A, 0xA94E, + 0x54A0, 0xCE48, 0x54A1, 0xCDFB, 0x54A2, 0xCE4B, 0x54A5, 0xCDFD, 0x54A6, 0xAB78, 0x54A7, 0xABA8, 0x54A8, 0xAB74, 0x54A9, 0xABA7, + 0x54AA, 0xAB7D, 0x54AB, 0xABA4, 0x54AC, 0xAB72, 0x54AD, 0xCDFC, 0x54AE, 0xCE43, 0x54AF, 0xABA3, 0x54B0, 0xCE4F, 0x54B1, 0xABA5, + 0x54B3, 0xAB79, 0x54B6, 0xCE45, 0x54B7, 0xCE42, 0x54B8, 0xAB77, 0x54BA, 0xCDFA, 0x54BB, 0xABA6, 0x54BC, 0xCE4A, 0x54BD, 0xAB7C, + 0x54BE, 0xCE4C, 0x54BF, 0xABA9, 0x54C0, 0xAB73, 0x54C1, 0xAB7E, 0x54C2, 0xAB7B, 0x54C3, 0xCE40, 0x54C4, 0xABA1, 0x54C5, 0xCE46, + 0x54C6, 0xCE47, 0x54C7, 0xAB7A, 0x54C8, 0xABA2, 0x54C9, 0xAB76, 0x54CE, 0xAB75, 0x54CF, 0xCDFE, 0x54D6, 0xCE44, 0x54DE, 0xCE4E, + 0x54E0, 0xD144, 0x54E1, 0xADFB, 0x54E2, 0xD0F1, 0x54E4, 0xD0F6, 0x54E5, 0xADF4, 0x54E6, 0xAE40, 0x54E7, 0xD0F4, 0x54E8, 0xADEF, + 0x54E9, 0xADF9, 0x54EA, 0xADFE, 0x54EB, 0xD0FB, 0x54ED, 0xADFA, 0x54EE, 0xADFD, 0x54F1, 0xD0FE, 0x54F2, 0xADF5, 0x54F3, 0xD0F5, + 0x54F7, 0xD142, 0x54F8, 0xD143, 0x54FA, 0xADF7, 0x54FB, 0xD141, 0x54FC, 0xADF3, 0x54FD, 0xAE43, 0x54FF, 0xD0F8, 0x5501, 0xADF1, + 0x5503, 0xD146, 0x5504, 0xD0F9, 0x5505, 0xD0FD, 0x5506, 0xADF6, 0x5507, 0xAE42, 0x5508, 0xD0FA, 0x5509, 0xADFC, 0x550A, 0xD140, + 0x550B, 0xD147, 0x550C, 0xD4A1, 0x550E, 0xD145, 0x550F, 0xAE44, 0x5510, 0xADF0, 0x5511, 0xD0FC, 0x5512, 0xD0F3, 0x5514, 0xADF8, + 0x5517, 0xD0F2, 0x551A, 0xD0F7, 0x5526, 0xD0F0, 0x5527, 0xAE41, 0x552A, 0xD477, 0x552C, 0xB0E4, 0x552D, 0xD4A7, 0x552E, 0xB0E2, + 0x552F, 0xB0DF, 0x5530, 0xD47C, 0x5531, 0xB0DB, 0x5532, 0xD4A2, 0x5533, 0xB0E6, 0x5534, 0xD476, 0x5535, 0xD47B, 0x5536, 0xD47A, + 0x5537, 0xADF2, 0x5538, 0xB0E1, 0x5539, 0xD4A5, 0x553B, 0xD4A8, 0x553C, 0xD473, 0x553E, 0xB3E8, 0x5540, 0xD4A9, 0x5541, 0xB0E7, + 0x5543, 0xB0D9, 0x5544, 0xB0D6, 0x5545, 0xD47E, 0x5546, 0xB0D3, 0x5548, 0xD4A6, 0x554A, 0xB0DA, 0x554B, 0xD4AA, 0x554D, 0xD474, + 0x554E, 0xD4A4, 0x554F, 0xB0DD, 0x5550, 0xD475, 0x5551, 0xD478, 0x5552, 0xD47D, 0x5555, 0xB0DE, 0x5556, 0xB0DC, 0x5557, 0xB0E8, + 0x555C, 0xB0E3, 0x555E, 0xB0D7, 0x555F, 0xB1D2, 0x5561, 0xB0D8, 0x5562, 0xD479, 0x5563, 0xB0E5, 0x5564, 0xB0E0, 0x5565, 0xD4A3, + 0x5566, 0xB0D5, 0x556A, 0xB0D4, 0x5575, 0xD471, 0x5576, 0xD472, 0x5577, 0xD86A, 0x557B, 0xB3D7, 0x557C, 0xB3DA, 0x557D, 0xD875, + 0x557E, 0xB3EE, 0x557F, 0xD878, 0x5580, 0xB3D8, 0x5581, 0xD871, 0x5582, 0xB3DE, 0x5583, 0xB3E4, 0x5584, 0xB5BD, 0x5587, 0xB3E2, + 0x5588, 0xD86E, 0x5589, 0xB3EF, 0x558A, 0xB3DB, 0x558B, 0xB3E3, 0x558C, 0xD876, 0x558D, 0xDCD7, 0x558E, 0xD87B, 0x558F, 0xD86F, + 0x5591, 0xD866, 0x5592, 0xD873, 0x5593, 0xD86D, 0x5594, 0xB3E1, 0x5595, 0xD879, 0x5598, 0xB3DD, 0x5599, 0xB3F1, 0x559A, 0xB3EA, + 0x559C, 0xB3DF, 0x559D, 0xB3DC, 0x559F, 0xB3E7, 0x55A1, 0xD87A, 0x55A2, 0xD86C, 0x55A3, 0xD872, 0x55A4, 0xD874, 0x55A5, 0xD868, + 0x55A6, 0xD877, 0x55A7, 0xB3D9, 0x55A8, 0xD867, 0x55AA, 0xB3E0, 0x55AB, 0xB3F0, 0x55AC, 0xB3EC, 0x55AD, 0xD869, 0x55AE, 0xB3E6, + 0x55B1, 0xB3ED, 0x55B2, 0xB3E9, 0x55B3, 0xB3E5, 0x55B5, 0xD870, 0x55BB, 0xB3EB, 0x55BF, 0xDCD5, 0x55C0, 0xDCD1, 0x55C2, 0xDCE0, + 0x55C3, 0xDCCA, 0x55C4, 0xDCD3, 0x55C5, 0xB6E5, 0x55C6, 0xB6E6, 0x55C7, 0xB6DE, 0x55C8, 0xDCDC, 0x55C9, 0xB6E8, 0x55CA, 0xDCCF, + 0x55CB, 0xDCCE, 0x55CC, 0xDCCC, 0x55CD, 0xDCDE, 0x55CE, 0xB6DC, 0x55CF, 0xDCD8, 0x55D0, 0xDCCD, 0x55D1, 0xB6DF, 0x55D2, 0xDCD6, + 0x55D3, 0xB6DA, 0x55D4, 0xDCD2, 0x55D5, 0xDCD9, 0x55D6, 0xDCDB, 0x55D9, 0xDCDF, 0x55DA, 0xB6E3, 0x55DB, 0xDCCB, 0x55DC, 0xB6DD, + 0x55DD, 0xDCD0, 0x55DF, 0xB6D8, 0x55E1, 0xB6E4, 0x55E2, 0xDCDA, 0x55E3, 0xB6E0, 0x55E4, 0xB6E1, 0x55E5, 0xB6E7, 0x55E6, 0xB6DB, + 0x55E7, 0xA25F, 0x55E8, 0xB6D9, 0x55E9, 0xDCD4, 0x55EF, 0xB6E2, 0x55F2, 0xDCDD, 0x55F6, 0xB9CD, 0x55F7, 0xB9C8, 0x55F9, 0xE155, + 0x55FA, 0xE151, 0x55FC, 0xE14B, 0x55FD, 0xB9C2, 0x55FE, 0xB9BE, 0x55FF, 0xE154, 0x5600, 0xB9BF, 0x5601, 0xE14E, 0x5602, 0xE150, + 0x5604, 0xE153, 0x5606, 0xB9C4, 0x5608, 0xB9CB, 0x5609, 0xB9C5, 0x560C, 0xE149, 0x560D, 0xB9C6, 0x560E, 0xB9C7, 0x560F, 0xE14C, + 0x5610, 0xB9CC, 0x5612, 0xE14A, 0x5613, 0xE14F, 0x5614, 0xB9C3, 0x5615, 0xE148, 0x5616, 0xB9C9, 0x5617, 0xB9C1, 0x561B, 0xB9C0, + 0x561C, 0xE14D, 0x561D, 0xE152, 0x561F, 0xB9CA, 0x5627, 0xE147, 0x5629, 0xBC4D, 0x562A, 0xE547, 0x562C, 0xE544, 0x562E, 0xBC47, + 0x562F, 0xBC53, 0x5630, 0xBC54, 0x5632, 0xBC4A, 0x5633, 0xE542, 0x5634, 0xBC4C, 0x5635, 0xE4F9, 0x5636, 0xBC52, 0x5638, 0xE546, + 0x5639, 0xBC49, 0x563A, 0xE548, 0x563B, 0xBC48, 0x563D, 0xE543, 0x563E, 0xE545, 0x563F, 0xBC4B, 0x5640, 0xE541, 0x5641, 0xE4FA, + 0x5642, 0xE4F7, 0x5645, 0xD86B, 0x5646, 0xE4FD, 0x5648, 0xE4F6, 0x5649, 0xE4FC, 0x564A, 0xE4FB, 0x564C, 0xE4F8, 0x564E, 0xBC4F, + 0x5653, 0xBC4E, 0x5657, 0xBC50, 0x5658, 0xE4FE, 0x5659, 0xBEB2, 0x565A, 0xE540, 0x565E, 0xE945, 0x5660, 0xE8FD, 0x5662, 0xBEBE, + 0x5663, 0xE942, 0x5664, 0xBEB6, 0x5665, 0xBEBA, 0x5666, 0xE941, 0x5668, 0xBEB9, 0x5669, 0xBEB5, 0x566A, 0xBEB8, 0x566B, 0xBEB3, + 0x566C, 0xBEBD, 0x566D, 0xE943, 0x566E, 0xE8FE, 0x566F, 0xBEBC, 0x5670, 0xE8FC, 0x5671, 0xBEBB, 0x5672, 0xE944, 0x5673, 0xE940, + 0x5674, 0xBC51, 0x5676, 0xBEBF, 0x5677, 0xE946, 0x5678, 0xBEB7, 0x5679, 0xBEB4, 0x567E, 0xECC6, 0x567F, 0xECC8, 0x5680, 0xC07B, + 0x5681, 0xECC9, 0x5682, 0xECC7, 0x5683, 0xECC5, 0x5684, 0xECC4, 0x5685, 0xC07D, 0x5686, 0xECC3, 0x5687, 0xC07E, 0x568C, 0xECC1, + 0x568D, 0xECC2, 0x568E, 0xC07A, 0x568F, 0xC0A1, 0x5690, 0xC07C, 0x5693, 0xECC0, 0x5695, 0xC250, 0x5697, 0xEFBC, 0x5698, 0xEFBA, + 0x5699, 0xEFBF, 0x569A, 0xEFBD, 0x569C, 0xEFBB, 0x569D, 0xEFBE, 0x56A5, 0xC360, 0x56A6, 0xF1F2, 0x56A7, 0xF1F3, 0x56A8, 0xC456, + 0x56AA, 0xF1F4, 0x56AB, 0xF1F0, 0x56AC, 0xF1F5, 0x56AD, 0xF1F1, 0x56AE, 0xC251, 0x56B2, 0xF3FE, 0x56B3, 0xF441, 0x56B4, 0xC459, + 0x56B5, 0xF440, 0x56B6, 0xC458, 0x56B7, 0xC457, 0x56BC, 0xC45A, 0x56BD, 0xF5C5, 0x56BE, 0xF5C6, 0x56C0, 0xC4DA, 0x56C1, 0xC4D9, + 0x56C2, 0xC4DB, 0x56C3, 0xF5C4, 0x56C5, 0xF6D8, 0x56C6, 0xF6D7, 0x56C8, 0xC56D, 0x56C9, 0xC56F, 0x56CA, 0xC56E, 0x56CB, 0xF6D9, + 0x56CC, 0xC5C8, 0x56CD, 0xF8A6, 0x56D1, 0xC5F1, 0x56D3, 0xF8A5, 0x56D4, 0xF8EE, 0x56D7, 0xC949, 0x56DA, 0xA57D, 0x56DB, 0xA57C, + 0x56DD, 0xA65F, 0x56DE, 0xA65E, 0x56DF, 0xC9C7, 0x56E0, 0xA65D, 0x56E1, 0xC9C6, 0x56E4, 0xA779, 0x56E5, 0xCAA9, 0x56E7, 0xCAA8, + 0x56EA, 0xA777, 0x56EB, 0xA77A, 0x56EE, 0xCAA7, 0x56F0, 0xA778, 0x56F7, 0xCBF0, 0x56F9, 0xCBF1, 0x56FA, 0xA954, 0x56FF, 0xABAA, + 0x5701, 0xD148, 0x5702, 0xD149, 0x5703, 0xAE45, 0x5704, 0xAE46, 0x5707, 0xD4AC, 0x5708, 0xB0E9, 0x5709, 0xB0EB, 0x570A, 0xD4AB, + 0x570B, 0xB0EA, 0x570C, 0xD87C, 0x570D, 0xB3F2, 0x5712, 0xB6E9, 0x5713, 0xB6EA, 0x5714, 0xDCE1, 0x5716, 0xB9CF, 0x5718, 0xB9CE, + 0x571A, 0xE549, 0x571B, 0xE948, 0x571C, 0xE947, 0x571E, 0xF96B, 0x571F, 0xA467, 0x5720, 0xC959, 0x5722, 0xC96E, 0x5723, 0xC96F, + 0x5728, 0xA662, 0x5729, 0xA666, 0x572A, 0xC9C9, 0x572C, 0xA664, 0x572D, 0xA663, 0x572E, 0xC9C8, 0x572F, 0xA665, 0x5730, 0xA661, + 0x5733, 0xA660, 0x5734, 0xC9CA, 0x573B, 0xA7A6, 0x573E, 0xA7A3, 0x5740, 0xA77D, 0x5741, 0xCAAA, 0x5745, 0xCAAB, 0x5747, 0xA7A1, + 0x5749, 0xCAAD, 0x574A, 0xA77B, 0x574B, 0xCAAE, 0x574C, 0xCAAC, 0x574D, 0xA77E, 0x574E, 0xA7A2, 0x574F, 0xA7A5, 0x5750, 0xA7A4, + 0x5751, 0xA77C, 0x5752, 0xCAAF, 0x5761, 0xA959, 0x5762, 0xCBFE, 0x5764, 0xA95B, 0x5766, 0xA95A, 0x5768, 0xCC40, 0x5769, 0xA958, + 0x576A, 0xA957, 0x576B, 0xCBF5, 0x576D, 0xCBF4, 0x576F, 0xCBF2, 0x5770, 0xCBF7, 0x5771, 0xCBF6, 0x5772, 0xCBF3, 0x5773, 0xCBFC, + 0x5774, 0xCBFD, 0x5775, 0xCBFA, 0x5776, 0xCBF8, 0x5777, 0xA956, 0x577B, 0xCBFB, 0x577C, 0xA95C, 0x577D, 0xCC41, 0x5780, 0xCBF9, + 0x5782, 0xABAB, 0x5783, 0xA955, 0x578B, 0xABAC, 0x578C, 0xCE54, 0x578F, 0xCE5A, 0x5793, 0xABB2, 0x5794, 0xCE58, 0x5795, 0xCE5E, + 0x5797, 0xCE55, 0x5798, 0xCE59, 0x5799, 0xCE5B, 0x579A, 0xCE5D, 0x579B, 0xCE57, 0x579D, 0xCE56, 0x579E, 0xCE51, 0x579F, 0xCE52, + 0x57A0, 0xABAD, 0x57A2, 0xABAF, 0x57A3, 0xABAE, 0x57A4, 0xCE53, 0x57A5, 0xCE5C, 0x57AE, 0xABB1, 0x57B5, 0xCE50, 0x57B6, 0xD153, + 0x57B8, 0xD152, 0x57B9, 0xD157, 0x57BA, 0xD14E, 0x57BC, 0xD151, 0x57BD, 0xD150, 0x57BF, 0xD154, 0x57C1, 0xD158, 0x57C2, 0xAE47, + 0x57C3, 0xAE4A, 0x57C6, 0xD14F, 0x57C7, 0xD155, 0x57CB, 0xAE49, 0x57CC, 0xD14A, 0x57CE, 0xABB0, 0x57CF, 0xD4BA, 0x57D0, 0xD156, + 0x57D2, 0xD14D, 0x57D4, 0xAE48, 0x57D5, 0xD14C, 0x57DC, 0xD4B1, 0x57DF, 0xB0EC, 0x57E0, 0xB0F0, 0x57E1, 0xD4C1, 0x57E2, 0xD4AF, + 0x57E3, 0xD4BD, 0x57E4, 0xB0F1, 0x57E5, 0xD4BF, 0x57E7, 0xD4C5, 0x57E9, 0xD4C9, 0x57EC, 0xD4C0, 0x57ED, 0xD4B4, 0x57EE, 0xD4BC, + 0x57F0, 0xD4CA, 0x57F1, 0xD4C8, 0x57F2, 0xD4BE, 0x57F3, 0xD4B9, 0x57F4, 0xD4B2, 0x57F5, 0xD8A6, 0x57F6, 0xD4B0, 0x57F7, 0xB0F5, + 0x57F8, 0xD4B7, 0x57F9, 0xB0F6, 0x57FA, 0xB0F2, 0x57FB, 0xD4AD, 0x57FC, 0xD4C3, 0x57FD, 0xD4B5, 0x5800, 0xD4B3, 0x5801, 0xD4C6, + 0x5802, 0xB0F3, 0x5804, 0xD4CC, 0x5805, 0xB0ED, 0x5806, 0xB0EF, 0x5807, 0xD4BB, 0x5808, 0xD4B6, 0x5809, 0xAE4B, 0x580A, 0xB0EE, + 0x580B, 0xD4B8, 0x580C, 0xD4C7, 0x580D, 0xD4CB, 0x580E, 0xD4C2, 0x5810, 0xD4C4, 0x5814, 0xD4AE, 0x5819, 0xD8A1, 0x581B, 0xD8AA, + 0x581C, 0xD8A9, 0x581D, 0xB3FA, 0x581E, 0xD8A2, 0x5820, 0xB3FB, 0x5821, 0xB3F9, 0x5823, 0xD8A4, 0x5824, 0xB3F6, 0x5825, 0xD8A8, + 0x5827, 0xD8A3, 0x5828, 0xD8A5, 0x5829, 0xD87D, 0x582A, 0xB3F4, 0x582C, 0xD8B2, 0x582D, 0xD8B1, 0x582E, 0xD8AE, 0x582F, 0xB3F3, + 0x5830, 0xB3F7, 0x5831, 0xB3F8, 0x5832, 0xD14B, 0x5833, 0xD8AB, 0x5834, 0xB3F5, 0x5835, 0xB0F4, 0x5836, 0xD8AD, 0x5837, 0xD87E, + 0x5838, 0xD8B0, 0x5839, 0xD8AF, 0x583B, 0xD8B3, 0x583D, 0xDCEF, 0x583F, 0xD8AC, 0x5848, 0xD8A7, 0x5849, 0xDCE7, 0x584A, 0xB6F4, + 0x584B, 0xB6F7, 0x584C, 0xB6F2, 0x584D, 0xDCE6, 0x584E, 0xDCEA, 0x584F, 0xDCE5, 0x5851, 0xB6EC, 0x5852, 0xB6F6, 0x5853, 0xDCE2, + 0x5854, 0xB6F0, 0x5855, 0xDCE9, 0x5857, 0xB6EE, 0x5858, 0xB6ED, 0x5859, 0xDCEC, 0x585A, 0xB6EF, 0x585B, 0xDCEE, 0x585D, 0xDCEB, + 0x585E, 0xB6EB, 0x5862, 0xB6F5, 0x5863, 0xDCF0, 0x5864, 0xDCE4, 0x5865, 0xDCED, 0x5868, 0xDCE3, 0x586B, 0xB6F1, 0x586D, 0xB6F3, + 0x586F, 0xDCE8, 0x5871, 0xDCF1, 0x5874, 0xE15D, 0x5875, 0xB9D0, 0x5876, 0xE163, 0x5879, 0xB9D5, 0x587A, 0xE15F, 0x587B, 0xE166, + 0x587C, 0xE157, 0x587D, 0xB9D7, 0x587E, 0xB9D1, 0x587F, 0xE15C, 0x5880, 0xBC55, 0x5881, 0xE15B, 0x5882, 0xE164, 0x5883, 0xB9D2, + 0x5885, 0xB9D6, 0x5886, 0xE15A, 0x5887, 0xE160, 0x5888, 0xE165, 0x5889, 0xE156, 0x588A, 0xB9D4, 0x588B, 0xE15E, 0x588E, 0xE162, + 0x588F, 0xE168, 0x5890, 0xE158, 0x5891, 0xE161, 0x5893, 0xB9D3, 0x5894, 0xE167, 0x5898, 0xE159, 0x589C, 0xBC59, 0x589D, 0xE54B, + 0x589E, 0xBC57, 0x589F, 0xBC56, 0x58A0, 0xE54D, 0x58A1, 0xE552, 0x58A3, 0xE54E, 0x58A5, 0xE551, 0x58A6, 0xBC5C, 0x58A8, 0xBEA5, + 0x58A9, 0xBC5B, 0x58AB, 0xE54A, 0x58AC, 0xE550, 0x58AE, 0xBC5A, 0x58AF, 0xE54F, 0x58B1, 0xE54C, 0x58B3, 0xBC58, 0x58BA, 0xE94D, + 0x58BB, 0xF9D9, 0x58BC, 0xE94F, 0x58BD, 0xE94A, 0x58BE, 0xBEC1, 0x58BF, 0xE94C, 0x58C1, 0xBEC0, 0x58C2, 0xE94E, 0x58C5, 0xBEC3, + 0x58C6, 0xE950, 0x58C7, 0xBEC2, 0x58C8, 0xE949, 0x58C9, 0xE94B, 0x58CE, 0xC0A5, 0x58CF, 0xECCC, 0x58D1, 0xC0A4, 0x58D2, 0xECCD, + 0x58D3, 0xC0A3, 0x58D4, 0xECCB, 0x58D5, 0xC0A2, 0x58D6, 0xECCA, 0x58D8, 0xC253, 0x58D9, 0xC252, 0x58DA, 0xF1F6, 0x58DB, 0xF1F8, + 0x58DD, 0xF1F7, 0x58DE, 0xC361, 0x58DF, 0xC362, 0x58E2, 0xC363, 0x58E3, 0xF442, 0x58E4, 0xC45B, 0x58E7, 0xF7D3, 0x58E8, 0xF7D2, + 0x58E9, 0xC5F2, 0x58EB, 0xA468, 0x58EC, 0xA4D0, 0x58EF, 0xA7A7, 0x58F4, 0xCE5F, 0x58F9, 0xB3FC, 0x58FA, 0xB3FD, 0x58FC, 0xDCF2, + 0x58FD, 0xB9D8, 0x58FE, 0xE169, 0x58FF, 0xE553, 0x5903, 0xC95A, 0x5906, 0xCAB0, 0x590C, 0xCC42, 0x590D, 0xCE60, 0x590E, 0xD159, + 0x590F, 0xAE4C, 0x5912, 0xF1F9, 0x5914, 0xC4DC, 0x5915, 0xA469, 0x5916, 0xA57E, 0x5917, 0xC970, 0x5919, 0xA667, 0x591A, 0xA668, + 0x591C, 0xA95D, 0x5920, 0xB0F7, 0x5922, 0xB9DA, 0x5924, 0xB9DB, 0x5925, 0xB9D9, 0x5927, 0xA46A, 0x5929, 0xA4D1, 0x592A, 0xA4D3, + 0x592B, 0xA4D2, 0x592C, 0xC95B, 0x592D, 0xA4D4, 0x592E, 0xA5A1, 0x592F, 0xC971, 0x5931, 0xA5A2, 0x5937, 0xA669, 0x5938, 0xA66A, + 0x593C, 0xC9CB, 0x593E, 0xA7A8, 0x5940, 0xCAB1, 0x5944, 0xA961, 0x5945, 0xCC43, 0x5947, 0xA95F, 0x5948, 0xA960, 0x5949, 0xA95E, + 0x594A, 0xD15A, 0x594E, 0xABB6, 0x594F, 0xABB5, 0x5950, 0xABB7, 0x5951, 0xABB4, 0x5953, 0xCE61, 0x5954, 0xA962, 0x5955, 0xABB3, + 0x5957, 0xAE4D, 0x5958, 0xAE4E, 0x595A, 0xAE4F, 0x595C, 0xD4CD, 0x5960, 0xB3FE, 0x5961, 0xD8B4, 0x5962, 0xB0F8, 0x5967, 0xB6F8, + 0x5969, 0xB9DD, 0x596A, 0xB9DC, 0x596B, 0xE16A, 0x596D, 0xBC5D, 0x596E, 0xBEC4, 0x5970, 0xEFC0, 0x5971, 0xF6DA, 0x5972, 0xF7D4, + 0x5973, 0xA46B, 0x5974, 0xA5A3, 0x5976, 0xA5A4, 0x5977, 0xC9D1, 0x5978, 0xA66C, 0x5979, 0xA66F, 0x597B, 0xC9CF, 0x597C, 0xC9CD, + 0x597D, 0xA66E, 0x597E, 0xC9D0, 0x597F, 0xC9D2, 0x5980, 0xC9CC, 0x5981, 0xA671, 0x5982, 0xA670, 0x5983, 0xA66D, 0x5984, 0xA66B, + 0x5985, 0xC9CE, 0x598A, 0xA7B3, 0x598D, 0xA7B0, 0x598E, 0xCAB6, 0x598F, 0xCAB9, 0x5990, 0xCAB8, 0x5992, 0xA7AA, 0x5993, 0xA7B2, + 0x5996, 0xA7AF, 0x5997, 0xCAB5, 0x5998, 0xCAB3, 0x5999, 0xA7AE, 0x599D, 0xA7A9, 0x599E, 0xA7AC, 0x59A0, 0xCAB4, 0x59A1, 0xCABB, + 0x59A2, 0xCAB7, 0x59A3, 0xA7AD, 0x59A4, 0xA7B1, 0x59A5, 0xA7B4, 0x59A6, 0xCAB2, 0x59A7, 0xCABA, 0x59A8, 0xA7AB, 0x59AE, 0xA967, + 0x59AF, 0xA96F, 0x59B1, 0xCC4F, 0x59B2, 0xCC48, 0x59B3, 0xA970, 0x59B4, 0xCC53, 0x59B5, 0xCC44, 0x59B6, 0xCC4B, 0x59B9, 0xA966, + 0x59BA, 0xCC45, 0x59BB, 0xA964, 0x59BC, 0xCC4C, 0x59BD, 0xCC50, 0x59BE, 0xA963, 0x59C0, 0xCC51, 0x59C1, 0xCC4A, 0x59C3, 0xCC4D, + 0x59C5, 0xA972, 0x59C6, 0xA969, 0x59C7, 0xCC54, 0x59C8, 0xCC52, 0x59CA, 0xA96E, 0x59CB, 0xA96C, 0x59CC, 0xCC49, 0x59CD, 0xA96B, + 0x59CE, 0xCC47, 0x59CF, 0xCC46, 0x59D0, 0xA96A, 0x59D1, 0xA968, 0x59D2, 0xA971, 0x59D3, 0xA96D, 0x59D4, 0xA965, 0x59D6, 0xCC4E, + 0x59D8, 0xABB9, 0x59DA, 0xABC0, 0x59DB, 0xCE6F, 0x59DC, 0xABB8, 0x59DD, 0xCE67, 0x59DE, 0xCE63, 0x59E0, 0xCE73, 0x59E1, 0xCE62, + 0x59E3, 0xABBB, 0x59E4, 0xCE6C, 0x59E5, 0xABBE, 0x59E6, 0xABC1, 0x59E8, 0xABBC, 0x59E9, 0xCE70, 0x59EA, 0xABBF, 0x59EC, 0xAE56, + 0x59ED, 0xCE76, 0x59EE, 0xCE64, 0x59F1, 0xCE66, 0x59F2, 0xCE6D, 0x59F3, 0xCE71, 0x59F4, 0xCE75, 0x59F5, 0xCE72, 0x59F6, 0xCE6B, + 0x59F7, 0xCE6E, 0x59FA, 0xCE68, 0x59FB, 0xABC3, 0x59FC, 0xCE6A, 0x59FD, 0xCE69, 0x59FE, 0xCE74, 0x59FF, 0xABBA, 0x5A00, 0xCE65, + 0x5A01, 0xABC2, 0x5A03, 0xABBD, 0x5A09, 0xAE5C, 0x5A0A, 0xD162, 0x5A0C, 0xAE5B, 0x5A0F, 0xD160, 0x5A11, 0xAE50, 0x5A13, 0xAE55, + 0x5A15, 0xD15F, 0x5A16, 0xD15C, 0x5A17, 0xD161, 0x5A18, 0xAE51, 0x5A19, 0xD15B, 0x5A1B, 0xAE54, 0x5A1C, 0xAE52, 0x5A1E, 0xD163, + 0x5A1F, 0xAE53, 0x5A20, 0xAE57, 0x5A23, 0xAE58, 0x5A25, 0xAE5A, 0x5A29, 0xAE59, 0x5A2D, 0xD15D, 0x5A2E, 0xD15E, 0x5A33, 0xD164, + 0x5A35, 0xD4D4, 0x5A36, 0xB0F9, 0x5A37, 0xD8C2, 0x5A38, 0xD4D3, 0x5A39, 0xD4E6, 0x5A3C, 0xB140, 0x5A3E, 0xD4E4, 0x5A40, 0xB0FE, + 0x5A41, 0xB0FA, 0x5A42, 0xD4ED, 0x5A43, 0xD4DD, 0x5A44, 0xD4E0, 0x5A46, 0xB143, 0x5A47, 0xD4EA, 0x5A48, 0xD4E2, 0x5A49, 0xB0FB, + 0x5A4A, 0xB144, 0x5A4C, 0xD4E7, 0x5A4D, 0xD4E5, 0x5A50, 0xD4D6, 0x5A51, 0xD4EB, 0x5A52, 0xD4DF, 0x5A53, 0xD4DA, 0x5A55, 0xD4D0, + 0x5A56, 0xD4EC, 0x5A57, 0xD4DC, 0x5A58, 0xD4CF, 0x5A5A, 0xB142, 0x5A5B, 0xD4E1, 0x5A5C, 0xD4EE, 0x5A5D, 0xD4DE, 0x5A5E, 0xD4D2, + 0x5A5F, 0xD4D7, 0x5A60, 0xD4CE, 0x5A62, 0xB141, 0x5A64, 0xD4DB, 0x5A65, 0xD4D8, 0x5A66, 0xB0FC, 0x5A67, 0xD4D1, 0x5A69, 0xD4E9, + 0x5A6A, 0xB0FD, 0x5A6C, 0xD4D9, 0x5A6D, 0xD4D5, 0x5A70, 0xD4E8, 0x5A77, 0xB440, 0x5A78, 0xD8BB, 0x5A7A, 0xD8B8, 0x5A7B, 0xD8C9, + 0x5A7C, 0xD8BD, 0x5A7D, 0xD8CA, 0x5A7F, 0xB442, 0x5A83, 0xD8C6, 0x5A84, 0xD8C3, 0x5A8A, 0xD8C4, 0x5A8B, 0xD8C7, 0x5A8C, 0xD8CB, + 0x5A8E, 0xD4E3, 0x5A8F, 0xD8CD, 0x5A90, 0xDD47, 0x5A92, 0xB443, 0x5A93, 0xD8CE, 0x5A94, 0xD8B6, 0x5A95, 0xD8C0, 0x5A97, 0xD8C5, + 0x5A9A, 0xB441, 0x5A9B, 0xB444, 0x5A9C, 0xD8CC, 0x5A9D, 0xD8CF, 0x5A9E, 0xD8BA, 0x5A9F, 0xD8B7, 0x5AA2, 0xD8B9, 0x5AA5, 0xD8BE, + 0x5AA6, 0xD8BC, 0x5AA7, 0xB445, 0x5AA9, 0xD8C8, 0x5AAC, 0xD8BF, 0x5AAE, 0xD8C1, 0x5AAF, 0xD8B5, 0x5AB0, 0xDCFA, 0x5AB1, 0xDCF8, + 0x5AB2, 0xB742, 0x5AB3, 0xB740, 0x5AB4, 0xDD43, 0x5AB5, 0xDCF9, 0x5AB6, 0xDD44, 0x5AB7, 0xDD40, 0x5AB8, 0xDCF7, 0x5AB9, 0xDD46, + 0x5ABA, 0xDCF6, 0x5ABB, 0xDCFD, 0x5ABC, 0xB6FE, 0x5ABD, 0xB6FD, 0x5ABE, 0xB6FC, 0x5ABF, 0xDCFB, 0x5AC0, 0xDD41, 0x5AC1, 0xB6F9, + 0x5AC2, 0xB741, 0x5AC4, 0xDCF4, 0x5AC6, 0xDCFE, 0x5AC7, 0xDCF3, 0x5AC8, 0xDCFC, 0x5AC9, 0xB6FA, 0x5ACA, 0xDD42, 0x5ACB, 0xDCF5, + 0x5ACC, 0xB6FB, 0x5ACD, 0xDD45, 0x5AD5, 0xE16E, 0x5AD6, 0xB9E2, 0x5AD7, 0xB9E1, 0x5AD8, 0xB9E3, 0x5AD9, 0xE17A, 0x5ADA, 0xE170, + 0x5ADB, 0xE176, 0x5ADC, 0xE16B, 0x5ADD, 0xE179, 0x5ADE, 0xE178, 0x5ADF, 0xE17C, 0x5AE0, 0xE175, 0x5AE1, 0xB9DE, 0x5AE2, 0xE174, + 0x5AE3, 0xB9E4, 0x5AE5, 0xE16D, 0x5AE6, 0xB9DF, 0x5AE8, 0xE17B, 0x5AE9, 0xB9E0, 0x5AEA, 0xE16F, 0x5AEB, 0xE172, 0x5AEC, 0xE177, + 0x5AED, 0xE171, 0x5AEE, 0xE16C, 0x5AF3, 0xE173, 0x5AF4, 0xE555, 0x5AF5, 0xBC61, 0x5AF6, 0xE558, 0x5AF7, 0xE557, 0x5AF8, 0xE55A, + 0x5AF9, 0xE55C, 0x5AFA, 0xF9DC, 0x5AFB, 0xBC5F, 0x5AFD, 0xE556, 0x5AFF, 0xE554, 0x5B01, 0xE55D, 0x5B02, 0xE55B, 0x5B03, 0xE559, + 0x5B05, 0xE55F, 0x5B07, 0xE55E, 0x5B08, 0xBC63, 0x5B09, 0xBC5E, 0x5B0B, 0xBC60, 0x5B0C, 0xBC62, 0x5B0F, 0xE560, 0x5B10, 0xE957, + 0x5B13, 0xE956, 0x5B14, 0xE955, 0x5B16, 0xE958, 0x5B17, 0xE951, 0x5B19, 0xE952, 0x5B1A, 0xE95A, 0x5B1B, 0xE953, 0x5B1D, 0xBEC5, + 0x5B1E, 0xE95C, 0x5B20, 0xE95B, 0x5B21, 0xE954, 0x5B23, 0xECD1, 0x5B24, 0xC0A8, 0x5B25, 0xECCF, 0x5B26, 0xECD4, 0x5B27, 0xECD3, + 0x5B28, 0xE959, 0x5B2A, 0xC0A7, 0x5B2C, 0xECD2, 0x5B2D, 0xECCE, 0x5B2E, 0xECD6, 0x5B2F, 0xECD5, 0x5B30, 0xC0A6, 0x5B32, 0xECD0, + 0x5B34, 0xBEC6, 0x5B38, 0xC254, 0x5B3C, 0xEFC1, 0x5B3D, 0xF1FA, 0x5B3E, 0xF1FB, 0x5B3F, 0xF1FC, 0x5B40, 0xC45C, 0x5B43, 0xC45D, + 0x5B45, 0xF443, 0x5B47, 0xF5C8, 0x5B48, 0xF5C7, 0x5B4B, 0xF6DB, 0x5B4C, 0xF6DC, 0x5B4D, 0xF7D5, 0x5B4E, 0xF8A7, 0x5B50, 0xA46C, + 0x5B51, 0xA46D, 0x5B53, 0xA46E, 0x5B54, 0xA4D5, 0x5B55, 0xA5A5, 0x5B56, 0xC9D3, 0x5B57, 0xA672, 0x5B58, 0xA673, 0x5B5A, 0xA7B7, + 0x5B5B, 0xA7B8, 0x5B5C, 0xA7B6, 0x5B5D, 0xA7B5, 0x5B5F, 0xA973, 0x5B62, 0xCC55, 0x5B63, 0xA975, 0x5B64, 0xA974, 0x5B65, 0xCC56, + 0x5B69, 0xABC4, 0x5B6B, 0xAE5D, 0x5B6C, 0xD165, 0x5B6E, 0xD4F0, 0x5B70, 0xB145, 0x5B71, 0xB447, 0x5B72, 0xD4EF, 0x5B73, 0xB446, + 0x5B75, 0xB9E5, 0x5B77, 0xE17D, 0x5B78, 0xBEC7, 0x5B7A, 0xC0A9, 0x5B7B, 0xECD7, 0x5B7D, 0xC45E, 0x5B7F, 0xC570, 0x5B81, 0xC972, + 0x5B83, 0xA5A6, 0x5B84, 0xC973, 0x5B85, 0xA676, 0x5B87, 0xA674, 0x5B88, 0xA675, 0x5B89, 0xA677, 0x5B8B, 0xA7BA, 0x5B8C, 0xA7B9, + 0x5B8E, 0xCABC, 0x5B8F, 0xA7BB, 0x5B92, 0xCABD, 0x5B93, 0xCC57, 0x5B95, 0xCC58, 0x5B97, 0xA976, 0x5B98, 0xA978, 0x5B99, 0xA97A, + 0x5B9A, 0xA977, 0x5B9B, 0xA97B, 0x5B9C, 0xA979, 0x5BA2, 0xABC8, 0x5BA3, 0xABC5, 0x5BA4, 0xABC7, 0x5BA5, 0xABC9, 0x5BA6, 0xABC6, + 0x5BA7, 0xD166, 0x5BA8, 0xCE77, 0x5BAC, 0xD168, 0x5BAD, 0xD167, 0x5BAE, 0xAE63, 0x5BB0, 0xAE5F, 0x5BB3, 0xAE60, 0x5BB4, 0xAE62, + 0x5BB5, 0xAE64, 0x5BB6, 0xAE61, 0x5BB8, 0xAE66, 0x5BB9, 0xAE65, 0x5BBF, 0xB14A, 0x5BC0, 0xD4F2, 0x5BC1, 0xD4F1, 0x5BC2, 0xB149, + 0x5BC4, 0xB148, 0x5BC5, 0xB147, 0x5BC6, 0xB14B, 0x5BC7, 0xB146, 0x5BCA, 0xD8D5, 0x5BCB, 0xD8D2, 0x5BCC, 0xB449, 0x5BCD, 0xD8D1, + 0x5BCE, 0xD8D6, 0x5BD0, 0xB44B, 0x5BD1, 0xD8D4, 0x5BD2, 0xB448, 0x5BD3, 0xB44A, 0x5BD4, 0xD8D3, 0x5BD6, 0xDD48, 0x5BD8, 0xDD49, + 0x5BD9, 0xDD4A, 0x5BDE, 0xB9E6, 0x5BDF, 0xB9EE, 0x5BE0, 0xE17E, 0x5BE1, 0xB9E8, 0x5BE2, 0xB9EC, 0x5BE3, 0xE1A1, 0x5BE4, 0xB9ED, + 0x5BE5, 0xB9E9, 0x5BE6, 0xB9EA, 0x5BE7, 0xB9E7, 0x5BE8, 0xB9EB, 0x5BE9, 0xBC66, 0x5BEA, 0xD8D0, 0x5BEB, 0xBC67, 0x5BEC, 0xBC65, + 0x5BEE, 0xBC64, 0x5BEF, 0xE95D, 0x5BF0, 0xBEC8, 0x5BF1, 0xECD8, 0x5BF2, 0xECD9, 0x5BF5, 0xC364, 0x5BF6, 0xC45F, 0x5BF8, 0xA46F, + 0x5BFA, 0xA678, 0x5C01, 0xABCA, 0x5C03, 0xD169, 0x5C04, 0xAE67, 0x5C07, 0xB14E, 0x5C08, 0xB14D, 0x5C09, 0xB14C, 0x5C0A, 0xB44C, + 0x5C0B, 0xB44D, 0x5C0C, 0xD8D7, 0x5C0D, 0xB9EF, 0x5C0E, 0xBEC9, 0x5C0F, 0xA470, 0x5C10, 0xC95C, 0x5C11, 0xA4D6, 0x5C12, 0xC974, + 0x5C15, 0xC9D4, 0x5C16, 0xA679, 0x5C1A, 0xA97C, 0x5C1F, 0xDD4B, 0x5C22, 0xA471, 0x5C24, 0xA4D7, 0x5C25, 0xC9D5, 0x5C28, 0xCABE, + 0x5C2A, 0xCABF, 0x5C2C, 0xA7BC, 0x5C30, 0xD8D8, 0x5C31, 0xB44E, 0x5C33, 0xDD4C, 0x5C37, 0xC0AA, 0x5C38, 0xA472, 0x5C39, 0xA4A8, + 0x5C3A, 0xA4D8, 0x5C3B, 0xC975, 0x5C3C, 0xA5A7, 0x5C3E, 0xA7C0, 0x5C3F, 0xA7BF, 0x5C40, 0xA7BD, 0x5C41, 0xA7BE, 0x5C44, 0xCC59, + 0x5C45, 0xA97E, 0x5C46, 0xA9A1, 0x5C47, 0xCC5A, 0x5C48, 0xA97D, 0x5C4B, 0xABCE, 0x5C4C, 0xCE78, 0x5C4D, 0xABCD, 0x5C4E, 0xABCB, + 0x5C4F, 0xABCC, 0x5C50, 0xAE6A, 0x5C51, 0xAE68, 0x5C54, 0xD16B, 0x5C55, 0xAE69, 0x5C56, 0xD16A, 0x5C58, 0xAE5E, 0x5C59, 0xD4F3, + 0x5C5C, 0xB150, 0x5C5D, 0xB151, 0x5C60, 0xB14F, 0x5C62, 0xB9F0, 0x5C63, 0xE1A2, 0x5C64, 0xBC68, 0x5C65, 0xBC69, 0x5C67, 0xE561, + 0x5C68, 0xC0AB, 0x5C69, 0xEFC2, 0x5C6A, 0xEFC3, 0x5C6C, 0xC4DD, 0x5C6D, 0xF8A8, 0x5C6E, 0xC94B, 0x5C6F, 0xA4D9, 0x5C71, 0xA473, + 0x5C73, 0xC977, 0x5C74, 0xC976, 0x5C79, 0xA67A, 0x5C7A, 0xC9D7, 0x5C7B, 0xC9D8, 0x5C7C, 0xC9D6, 0x5C7E, 0xC9D9, 0x5C86, 0xCAC7, + 0x5C88, 0xCAC2, 0x5C89, 0xCAC4, 0x5C8A, 0xCAC6, 0x5C8B, 0xCAC3, 0x5C8C, 0xA7C4, 0x5C8D, 0xCAC0, 0x5C8F, 0xCAC1, 0x5C90, 0xA7C1, + 0x5C91, 0xA7C2, 0x5C92, 0xCAC5, 0x5C93, 0xCAC8, 0x5C94, 0xA7C3, 0x5C95, 0xCAC9, 0x5C9D, 0xCC68, 0x5C9F, 0xCC62, 0x5CA0, 0xCC5D, + 0x5CA1, 0xA9A3, 0x5CA2, 0xCC65, 0x5CA3, 0xCC63, 0x5CA4, 0xCC5C, 0x5CA5, 0xCC69, 0x5CA6, 0xCC6C, 0x5CA7, 0xCC67, 0x5CA8, 0xCC60, + 0x5CA9, 0xA9A5, 0x5CAA, 0xCC66, 0x5CAB, 0xA9A6, 0x5CAC, 0xCC61, 0x5CAD, 0xCC64, 0x5CAE, 0xCC5B, 0x5CAF, 0xCC5F, 0x5CB0, 0xCC6B, + 0x5CB1, 0xA9A7, 0x5CB3, 0xA9A8, 0x5CB5, 0xCC5E, 0x5CB6, 0xCC6A, 0x5CB7, 0xA9A2, 0x5CB8, 0xA9A4, 0x5CC6, 0xCEAB, 0x5CC7, 0xCEA4, + 0x5CC8, 0xCEAA, 0x5CC9, 0xCEA3, 0x5CCA, 0xCEA5, 0x5CCB, 0xCE7D, 0x5CCC, 0xCE7B, 0x5CCE, 0xCEAC, 0x5CCF, 0xCEA9, 0x5CD0, 0xCE79, + 0x5CD2, 0xABD0, 0x5CD3, 0xCEA7, 0x5CD4, 0xCEA8, 0x5CD6, 0xCEA6, 0x5CD7, 0xCE7C, 0x5CD8, 0xCE7A, 0x5CD9, 0xABCF, 0x5CDA, 0xCEA2, + 0x5CDB, 0xCE7E, 0x5CDE, 0xCEA1, 0x5CDF, 0xCEAD, 0x5CE8, 0xAE6F, 0x5CEA, 0xAE6E, 0x5CEC, 0xD16C, 0x5CED, 0xAE6B, 0x5CEE, 0xD16E, + 0x5CF0, 0xAE70, 0x5CF1, 0xD16F, 0x5CF4, 0xAE73, 0x5CF6, 0xAE71, 0x5CF7, 0xD170, 0x5CF8, 0xCEAE, 0x5CF9, 0xD172, 0x5CFB, 0xAE6D, + 0x5CFD, 0xAE6C, 0x5CFF, 0xD16D, 0x5D00, 0xD171, 0x5D01, 0xAE72, 0x5D06, 0xB153, 0x5D07, 0xB152, 0x5D0B, 0xD4F5, 0x5D0C, 0xD4F9, + 0x5D0D, 0xD4FB, 0x5D0E, 0xB154, 0x5D0F, 0xD4FE, 0x5D11, 0xB158, 0x5D12, 0xD541, 0x5D14, 0xB15A, 0x5D16, 0xB156, 0x5D17, 0xB15E, + 0x5D19, 0xB15B, 0x5D1A, 0xD4F7, 0x5D1B, 0xB155, 0x5D1D, 0xD4F6, 0x5D1E, 0xD4F4, 0x5D1F, 0xD543, 0x5D20, 0xD4F8, 0x5D22, 0xB157, + 0x5D23, 0xD542, 0x5D24, 0xB15C, 0x5D25, 0xD4FD, 0x5D26, 0xD4FC, 0x5D27, 0xB15D, 0x5D28, 0xD4FA, 0x5D29, 0xB159, 0x5D2E, 0xD544, + 0x5D30, 0xD540, 0x5D31, 0xD8E7, 0x5D32, 0xD8EE, 0x5D33, 0xD8E3, 0x5D34, 0xB451, 0x5D35, 0xD8DF, 0x5D36, 0xD8EF, 0x5D37, 0xD8D9, + 0x5D38, 0xD8EC, 0x5D39, 0xD8EA, 0x5D3A, 0xD8E4, 0x5D3C, 0xD8ED, 0x5D3D, 0xD8E6, 0x5D3F, 0xD8DE, 0x5D40, 0xD8F0, 0x5D41, 0xD8DC, + 0x5D42, 0xD8E9, 0x5D43, 0xD8DA, 0x5D45, 0xD8F1, 0x5D47, 0xB452, 0x5D49, 0xD8EB, 0x5D4A, 0xDD4F, 0x5D4B, 0xD8DD, 0x5D4C, 0xB44F, + 0x5D4E, 0xD8E1, 0x5D50, 0xB450, 0x5D51, 0xD8E0, 0x5D52, 0xD8E5, 0x5D55, 0xD8E2, 0x5D59, 0xD8E8, 0x5D5E, 0xDD53, 0x5D62, 0xDD56, + 0x5D63, 0xDD4E, 0x5D65, 0xDD50, 0x5D67, 0xDD55, 0x5D68, 0xDD54, 0x5D69, 0xB743, 0x5D6B, 0xD8DB, 0x5D6C, 0xDD52, 0x5D6F, 0xB744, + 0x5D71, 0xDD4D, 0x5D72, 0xDD51, 0x5D77, 0xE1A9, 0x5D79, 0xE1B0, 0x5D7A, 0xE1A7, 0x5D7C, 0xE1AE, 0x5D7D, 0xE1A5, 0x5D7E, 0xE1AD, + 0x5D7F, 0xE1B1, 0x5D80, 0xE1A4, 0x5D81, 0xE1A8, 0x5D82, 0xE1A3, 0x5D84, 0xB9F1, 0x5D86, 0xE1A6, 0x5D87, 0xB9F2, 0x5D88, 0xE1AC, + 0x5D89, 0xE1AB, 0x5D8A, 0xE1AA, 0x5D8D, 0xE1AF, 0x5D92, 0xE565, 0x5D93, 0xE567, 0x5D94, 0xBC6B, 0x5D95, 0xE568, 0x5D97, 0xE563, + 0x5D99, 0xE562, 0x5D9A, 0xE56C, 0x5D9C, 0xE56A, 0x5D9D, 0xBC6A, 0x5D9E, 0xE56D, 0x5D9F, 0xE564, 0x5DA0, 0xE569, 0x5DA1, 0xE56B, + 0x5DA2, 0xE566, 0x5DA7, 0xE961, 0x5DA8, 0xE966, 0x5DA9, 0xE960, 0x5DAA, 0xE965, 0x5DAC, 0xE95E, 0x5DAD, 0xE968, 0x5DAE, 0xE964, + 0x5DAF, 0xE969, 0x5DB0, 0xE963, 0x5DB1, 0xE95F, 0x5DB2, 0xE967, 0x5DB4, 0xE96A, 0x5DB5, 0xE962, 0x5DB7, 0xECDA, 0x5DB8, 0xC0AF, + 0x5DBA, 0xC0AD, 0x5DBC, 0xC0AC, 0x5DBD, 0xC0AE, 0x5DC0, 0xEFC4, 0x5DC2, 0xF172, 0x5DC3, 0xF1FD, 0x5DC6, 0xF444, 0x5DC7, 0xF445, + 0x5DC9, 0xC460, 0x5DCB, 0xF5C9, 0x5DCD, 0xC4DE, 0x5DCF, 0xF5CA, 0x5DD1, 0xF6DE, 0x5DD2, 0xC572, 0x5DD4, 0xC571, 0x5DD5, 0xF6DD, + 0x5DD6, 0xC5C9, 0x5DD8, 0xF7D6, 0x5DDD, 0xA474, 0x5DDE, 0xA67B, 0x5DDF, 0xC9DA, 0x5DE0, 0xCACA, 0x5DE1, 0xA8B5, 0x5DE2, 0xB15F, + 0x5DE5, 0xA475, 0x5DE6, 0xA5AA, 0x5DE7, 0xA5A9, 0x5DE8, 0xA5A8, 0x5DEB, 0xA7C5, 0x5DEE, 0xAE74, 0x5DF0, 0xDD57, 0x5DF1, 0xA476, + 0x5DF2, 0xA477, 0x5DF3, 0xA478, 0x5DF4, 0xA4DA, 0x5DF7, 0xABD1, 0x5DF9, 0xCEAF, 0x5DFD, 0xB453, 0x5DFE, 0xA479, 0x5DFF, 0xC95D, + 0x5E02, 0xA5AB, 0x5E03, 0xA5AC, 0x5E04, 0xC978, 0x5E06, 0xA67C, 0x5E0A, 0xCACB, 0x5E0C, 0xA7C6, 0x5E0E, 0xCACC, 0x5E11, 0xA9AE, + 0x5E14, 0xCC6E, 0x5E15, 0xA9AC, 0x5E16, 0xA9AB, 0x5E17, 0xCC6D, 0x5E18, 0xA9A9, 0x5E19, 0xCC6F, 0x5E1A, 0xA9AA, 0x5E1B, 0xA9AD, + 0x5E1D, 0xABD2, 0x5E1F, 0xABD4, 0x5E20, 0xCEB3, 0x5E21, 0xCEB0, 0x5E22, 0xCEB1, 0x5E23, 0xCEB2, 0x5E24, 0xCEB4, 0x5E25, 0xABD3, + 0x5E28, 0xD174, 0x5E29, 0xD173, 0x5E2B, 0xAE76, 0x5E2D, 0xAE75, 0x5E33, 0xB162, 0x5E34, 0xD546, 0x5E36, 0xB161, 0x5E37, 0xB163, + 0x5E38, 0xB160, 0x5E3D, 0xB455, 0x5E3E, 0xD545, 0x5E40, 0xB456, 0x5E41, 0xD8F3, 0x5E43, 0xB457, 0x5E44, 0xD8F2, 0x5E45, 0xB454, + 0x5E4A, 0xDD5A, 0x5E4B, 0xDD5C, 0x5E4C, 0xB745, 0x5E4D, 0xDD5B, 0x5E4E, 0xDD59, 0x5E4F, 0xDD58, 0x5E53, 0xE1B4, 0x5E54, 0xB9F7, + 0x5E55, 0xB9F5, 0x5E57, 0xB9F6, 0x5E58, 0xE1B2, 0x5E59, 0xE1B3, 0x5E5B, 0xB9F3, 0x5E5C, 0xE571, 0x5E5D, 0xE56F, 0x5E5F, 0xBC6D, + 0x5E60, 0xE570, 0x5E61, 0xBC6E, 0x5E62, 0xBC6C, 0x5E63, 0xB9F4, 0x5E66, 0xE96D, 0x5E67, 0xE96B, 0x5E68, 0xE96C, 0x5E69, 0xE56E, + 0x5E6A, 0xECDC, 0x5E6B, 0xC0B0, 0x5E6C, 0xECDB, 0x5E6D, 0xEFC5, 0x5E6E, 0xEFC6, 0x5E6F, 0xE96E, 0x5E70, 0xF1FE, 0x5E72, 0xA47A, + 0x5E73, 0xA5AD, 0x5E74, 0xA67E, 0x5E75, 0xC9DB, 0x5E76, 0xA67D, 0x5E78, 0xA9AF, 0x5E79, 0xB746, 0x5E7B, 0xA4DB, 0x5E7C, 0xA5AE, + 0x5E7D, 0xABD5, 0x5E7E, 0xB458, 0x5E80, 0xC979, 0x5E82, 0xC97A, 0x5E84, 0xC9DC, 0x5E87, 0xA7C8, 0x5E88, 0xCAD0, 0x5E89, 0xCACE, + 0x5E8A, 0xA7C9, 0x5E8B, 0xCACD, 0x5E8C, 0xCACF, 0x5E8D, 0xCAD1, 0x5E8F, 0xA7C7, 0x5E95, 0xA9B3, 0x5E96, 0xA9B4, 0x5E97, 0xA9B1, + 0x5E9A, 0xA9B0, 0x5E9B, 0xCEB8, 0x5E9C, 0xA9B2, 0x5EA0, 0xABD6, 0x5EA2, 0xCEB7, 0x5EA3, 0xCEB9, 0x5EA4, 0xCEB6, 0x5EA5, 0xCEBA, + 0x5EA6, 0xABD7, 0x5EA7, 0xAE79, 0x5EA8, 0xD175, 0x5EAA, 0xD177, 0x5EAB, 0xAE77, 0x5EAC, 0xD178, 0x5EAD, 0xAE78, 0x5EAE, 0xD176, + 0x5EB0, 0xCEB5, 0x5EB1, 0xD547, 0x5EB2, 0xD54A, 0x5EB3, 0xD54B, 0x5EB4, 0xD548, 0x5EB5, 0xB167, 0x5EB6, 0xB166, 0x5EB7, 0xB164, + 0x5EB8, 0xB165, 0x5EB9, 0xD549, 0x5EBE, 0xB168, 0x5EC1, 0xB45A, 0x5EC2, 0xB45B, 0x5EC4, 0xB45C, 0x5EC5, 0xDD5D, 0x5EC6, 0xDD5F, + 0x5EC7, 0xDD61, 0x5EC8, 0xB748, 0x5EC9, 0xB747, 0x5ECA, 0xB459, 0x5ECB, 0xDD60, 0x5ECC, 0xDD5E, 0x5ECE, 0xE1B8, 0x5ED1, 0xE1B6, + 0x5ED2, 0xE1BC, 0x5ED3, 0xB9F8, 0x5ED4, 0xE1BD, 0x5ED5, 0xE1BA, 0x5ED6, 0xB9F9, 0x5ED7, 0xE1B7, 0x5ED8, 0xE1B5, 0x5ED9, 0xE1BB, + 0x5EDA, 0xBC70, 0x5EDB, 0xE573, 0x5EDC, 0xE1B9, 0x5EDD, 0xBC72, 0x5EDE, 0xE574, 0x5EDF, 0xBC71, 0x5EE0, 0xBC74, 0x5EE1, 0xE575, + 0x5EE2, 0xBC6F, 0x5EE3, 0xBC73, 0x5EE5, 0xE973, 0x5EE6, 0xE971, 0x5EE7, 0xE970, 0x5EE8, 0xE972, 0x5EE9, 0xE96F, 0x5EEC, 0xC366, + 0x5EEE, 0xF446, 0x5EEF, 0xF447, 0x5EF1, 0xF5CB, 0x5EF2, 0xF6DF, 0x5EF3, 0xC655, 0x5EF6, 0xA9B5, 0x5EF7, 0xA7CA, 0x5EFA, 0xABD8, + 0x5EFE, 0xA47B, 0x5EFF, 0xA4DC, 0x5F01, 0xA5AF, 0x5F02, 0xC9DD, 0x5F04, 0xA7CB, 0x5F05, 0xCAD2, 0x5F07, 0xCEBB, 0x5F08, 0xABD9, + 0x5F0A, 0xB9FA, 0x5F0B, 0xA47C, 0x5F0F, 0xA6A1, 0x5F12, 0xB749, 0x5F13, 0xA47D, 0x5F14, 0xA4DD, 0x5F15, 0xA4DE, 0x5F17, 0xA5B1, + 0x5F18, 0xA5B0, 0x5F1A, 0xC9DE, 0x5F1B, 0xA6A2, 0x5F1D, 0xCAD3, 0x5F1F, 0xA7CC, 0x5F22, 0xCC71, 0x5F23, 0xCC72, 0x5F24, 0xCC73, + 0x5F26, 0xA9B6, 0x5F27, 0xA9B7, 0x5F28, 0xCC70, 0x5F29, 0xA9B8, 0x5F2D, 0xABDA, 0x5F2E, 0xCEBC, 0x5F30, 0xD17A, 0x5F31, 0xAE7A, + 0x5F33, 0xD179, 0x5F35, 0xB169, 0x5F36, 0xD54C, 0x5F37, 0xB16A, 0x5F38, 0xD54D, 0x5F3C, 0xB45D, 0x5F40, 0xDD62, 0x5F43, 0xE1BF, + 0x5F44, 0xE1BE, 0x5F46, 0xB9FB, 0x5F48, 0xBC75, 0x5F49, 0xE576, 0x5F4A, 0xBECA, 0x5F4B, 0xE974, 0x5F4C, 0xC0B1, 0x5F4E, 0xC573, + 0x5F4F, 0xF7D8, 0x5F54, 0xCC74, 0x5F56, 0xCEBD, 0x5F57, 0xB16B, 0x5F58, 0xD8F4, 0x5F59, 0xB74A, 0x5F5D, 0xC255, 0x5F62, 0xA7CE, + 0x5F64, 0xA7CD, 0x5F65, 0xABDB, 0x5F67, 0xD17B, 0x5F69, 0xB16D, 0x5F6A, 0xB343, 0x5F6B, 0xB16E, 0x5F6C, 0xB16C, 0x5F6D, 0xB45E, + 0x5F6F, 0xE1C0, 0x5F70, 0xB9FC, 0x5F71, 0xBC76, 0x5F73, 0xC94C, 0x5F74, 0xC9DF, 0x5F76, 0xCAD5, 0x5F77, 0xA7CF, 0x5F78, 0xCAD4, + 0x5F79, 0xA7D0, 0x5F7C, 0xA9BC, 0x5F7D, 0xCC77, 0x5F7E, 0xCC76, 0x5F7F, 0xA9BB, 0x5F80, 0xA9B9, 0x5F81, 0xA9BA, 0x5F82, 0xCC75, + 0x5F85, 0xABDD, 0x5F86, 0xCEBE, 0x5F87, 0xABE0, 0x5F88, 0xABDC, 0x5F89, 0xABE2, 0x5F8A, 0xABDE, 0x5F8B, 0xABDF, 0x5F8C, 0xABE1, + 0x5F90, 0xAE7D, 0x5F91, 0xAE7C, 0x5F92, 0xAE7B, 0x5F96, 0xD54F, 0x5F97, 0xB16F, 0x5F98, 0xB172, 0x5F99, 0xB170, 0x5F9B, 0xD54E, + 0x5F9C, 0xB175, 0x5F9E, 0xB171, 0x5F9F, 0xD550, 0x5FA0, 0xB174, 0x5FA1, 0xB173, 0x5FA5, 0xD8F6, 0x5FA6, 0xD8F5, 0x5FA8, 0xB461, + 0x5FA9, 0xB45F, 0x5FAA, 0xB460, 0x5FAB, 0xD8F7, 0x5FAC, 0xB74B, 0x5FAD, 0xDD64, 0x5FAE, 0xB74C, 0x5FAF, 0xDD63, 0x5FB2, 0xE577, + 0x5FB5, 0xBC78, 0x5FB6, 0xE1C1, 0x5FB7, 0xBC77, 0x5FB9, 0xB9FD, 0x5FBB, 0xECDE, 0x5FBC, 0xE975, 0x5FBD, 0xC0B2, 0x5FBE, 0xECDD, + 0x5FBF, 0xF240, 0x5FC0, 0xF448, 0x5FC1, 0xF449, 0x5FC3, 0xA4DF, 0x5FC5, 0xA5B2, 0x5FC9, 0xC97B, 0x5FCC, 0xA7D2, 0x5FCD, 0xA7D4, + 0x5FCF, 0xC9E2, 0x5FD0, 0xCAD8, 0x5FD1, 0xCAD7, 0x5FD2, 0xCAD6, 0x5FD4, 0xC9E1, 0x5FD5, 0xC9E0, 0x5FD6, 0xA6A4, 0x5FD7, 0xA7D3, + 0x5FD8, 0xA7D1, 0x5FD9, 0xA6A3, 0x5FDD, 0xA9BD, 0x5FDE, 0xCC78, 0x5FE0, 0xA9BE, 0x5FE1, 0xCADD, 0x5FE3, 0xCADF, 0x5FE4, 0xCADE, + 0x5FE5, 0xCC79, 0x5FE8, 0xCADA, 0x5FEA, 0xA7D8, 0x5FEB, 0xA7D6, 0x5FED, 0xCAD9, 0x5FEE, 0xCADB, 0x5FEF, 0xCAE1, 0x5FF1, 0xA7D5, + 0x5FF3, 0xCADC, 0x5FF4, 0xCAE5, 0x5FF5, 0xA9C0, 0x5FF7, 0xCAE2, 0x5FF8, 0xA7D7, 0x5FFA, 0xCAE0, 0x5FFB, 0xCAE3, 0x5FFD, 0xA9BF, + 0x5FFF, 0xA9C1, 0x6000, 0xCAE4, 0x6009, 0xCCAF, 0x600A, 0xCCA2, 0x600B, 0xCC7E, 0x600C, 0xCCAE, 0x600D, 0xCCA9, 0x600E, 0xABE7, + 0x600F, 0xA9C2, 0x6010, 0xCCAA, 0x6011, 0xCCAD, 0x6012, 0xABE3, 0x6013, 0xCCAC, 0x6014, 0xA9C3, 0x6015, 0xA9C8, 0x6016, 0xA9C6, + 0x6017, 0xCCA3, 0x6019, 0xCC7C, 0x601A, 0xCCA5, 0x601B, 0xA9CD, 0x601C, 0xCCB0, 0x601D, 0xABE4, 0x601E, 0xCCA6, 0x6020, 0xABE5, + 0x6021, 0xA9C9, 0x6022, 0xCCA8, 0x6024, 0xCECD, 0x6025, 0xABE6, 0x6026, 0xCC7B, 0x6027, 0xA9CA, 0x6028, 0xABE8, 0x6029, 0xA9CB, + 0x602A, 0xA9C7, 0x602B, 0xA9CC, 0x602C, 0xCCA7, 0x602D, 0xCC7A, 0x602E, 0xCCAB, 0x602F, 0xA9C4, 0x6032, 0xCC7D, 0x6033, 0xCCA4, + 0x6034, 0xCCA1, 0x6035, 0xA9C5, 0x6037, 0xCEBF, 0x6039, 0xCEC0, 0x6040, 0xCECA, 0x6041, 0xD1A1, 0x6042, 0xCECB, 0x6043, 0xABEE, + 0x6044, 0xCECE, 0x6045, 0xCEC4, 0x6046, 0xABED, 0x6047, 0xCEC6, 0x6049, 0xCEC7, 0x604C, 0xCEC9, 0x604D, 0xABE9, 0x6050, 0xAEA3, + 0x6052, 0xF9DA, 0x6053, 0xCEC5, 0x6054, 0xCEC1, 0x6055, 0xAEA4, 0x6058, 0xCECF, 0x6059, 0xAE7E, 0x605A, 0xD17D, 0x605B, 0xCEC8, + 0x605D, 0xD17C, 0x605E, 0xCEC3, 0x605F, 0xCECC, 0x6062, 0xABEC, 0x6063, 0xAEA1, 0x6064, 0xABF2, 0x6065, 0xAEA2, 0x6066, 0xCED0, + 0x6067, 0xD17E, 0x6068, 0xABEB, 0x6069, 0xAEA6, 0x606A, 0xABF1, 0x606B, 0xABF0, 0x606C, 0xABEF, 0x606D, 0xAEA5, 0x606E, 0xCED1, + 0x606F, 0xAEA7, 0x6070, 0xABEA, 0x6072, 0xCEC2, 0x607F, 0xB176, 0x6080, 0xD1A4, 0x6081, 0xD1A6, 0x6083, 0xD1A8, 0x6084, 0xAEA8, + 0x6085, 0xAEAE, 0x6086, 0xD553, 0x6087, 0xD1AC, 0x6088, 0xD1A3, 0x6089, 0xB178, 0x608A, 0xD551, 0x608C, 0xAEAD, 0x608D, 0xAEAB, + 0x608E, 0xD1AE, 0x6090, 0xD552, 0x6092, 0xD1A5, 0x6094, 0xAEAC, 0x6095, 0xD1A9, 0x6096, 0xAEAF, 0x6097, 0xD1AB, 0x609A, 0xAEAA, + 0x609B, 0xD1AA, 0x609C, 0xD1AD, 0x609D, 0xD1A7, 0x609F, 0xAEA9, 0x60A0, 0xB179, 0x60A2, 0xD1A2, 0x60A3, 0xB177, 0x60A8, 0xB17A, + 0x60B0, 0xD555, 0x60B1, 0xD55E, 0x60B2, 0xB464, 0x60B4, 0xB17C, 0x60B5, 0xB1A3, 0x60B6, 0xB465, 0x60B7, 0xD560, 0x60B8, 0xB1AA, + 0x60B9, 0xD8F9, 0x60BA, 0xD556, 0x60BB, 0xB1A2, 0x60BC, 0xB1A5, 0x60BD, 0xB17E, 0x60BE, 0xD554, 0x60BF, 0xD562, 0x60C0, 0xD565, + 0x60C1, 0xD949, 0x60C3, 0xD563, 0x60C4, 0xD8FD, 0x60C5, 0xB1A1, 0x60C6, 0xB1A8, 0x60C7, 0xB1AC, 0x60C8, 0xD55D, 0x60C9, 0xD8F8, + 0x60CA, 0xD561, 0x60CB, 0xB17B, 0x60CC, 0xD8FA, 0x60CD, 0xD564, 0x60CE, 0xD8FC, 0x60CF, 0xD559, 0x60D1, 0xB462, 0x60D3, 0xD557, + 0x60D4, 0xD558, 0x60D5, 0xB1A7, 0x60D8, 0xB1A6, 0x60D9, 0xD55B, 0x60DA, 0xB1AB, 0x60DB, 0xD55F, 0x60DC, 0xB1A4, 0x60DD, 0xD55C, + 0x60DF, 0xB1A9, 0x60E0, 0xB466, 0x60E1, 0xB463, 0x60E2, 0xD8FB, 0x60E4, 0xD55A, 0x60E6, 0xB17D, 0x60F0, 0xB46B, 0x60F1, 0xB46F, + 0x60F2, 0xD940, 0x60F3, 0xB751, 0x60F4, 0xB46D, 0x60F5, 0xD944, 0x60F6, 0xB471, 0x60F7, 0xDD65, 0x60F8, 0xD946, 0x60F9, 0xB753, + 0x60FA, 0xB469, 0x60FB, 0xB46C, 0x60FC, 0xD947, 0x60FE, 0xD948, 0x60FF, 0xD94E, 0x6100, 0xB473, 0x6101, 0xB754, 0x6103, 0xD94A, + 0x6104, 0xD94F, 0x6105, 0xD943, 0x6106, 0xB75E, 0x6108, 0xB755, 0x6109, 0xB472, 0x610A, 0xD941, 0x610B, 0xD950, 0x610D, 0xB75D, + 0x610E, 0xB470, 0x610F, 0xB74E, 0x6110, 0xD94D, 0x6112, 0xB474, 0x6113, 0xD945, 0x6114, 0xD8FE, 0x6115, 0xB46A, 0x6116, 0xD942, + 0x6118, 0xD94B, 0x611A, 0xB74D, 0x611B, 0xB752, 0x611C, 0xB467, 0x611D, 0xD94C, 0x611F, 0xB750, 0x6123, 0xB468, 0x6127, 0xB75C, + 0x6128, 0xE1C3, 0x6129, 0xDD70, 0x612B, 0xDD68, 0x612C, 0xE1C2, 0x612E, 0xDD6C, 0x612F, 0xDD6E, 0x6132, 0xDD6B, 0x6134, 0xB75B, + 0x6136, 0xDD6A, 0x6137, 0xB75F, 0x613B, 0xE1D2, 0x613E, 0xB75A, 0x613F, 0xBA40, 0x6140, 0xDD71, 0x6141, 0xE1C4, 0x6144, 0xB758, + 0x6145, 0xDD69, 0x6146, 0xDD6D, 0x6147, 0xB9FE, 0x6148, 0xB74F, 0x6149, 0xDD66, 0x614A, 0xDD67, 0x614B, 0xBA41, 0x614C, 0xB757, + 0x614D, 0xB759, 0x614E, 0xB756, 0x614F, 0xDD6F, 0x6152, 0xE1C8, 0x6153, 0xE1C9, 0x6154, 0xE1CE, 0x6155, 0xBC7D, 0x6156, 0xE1D5, + 0x6158, 0xBA47, 0x615A, 0xBA46, 0x615B, 0xE1D0, 0x615D, 0xBC7C, 0x615E, 0xE1C5, 0x615F, 0xBA45, 0x6161, 0xE1D4, 0x6162, 0xBA43, + 0x6163, 0xBA44, 0x6165, 0xE1D1, 0x6166, 0xE5AA, 0x6167, 0xBC7A, 0x6168, 0xB46E, 0x616A, 0xE1D3, 0x616B, 0xBCA3, 0x616C, 0xE1CB, + 0x616E, 0xBC7B, 0x6170, 0xBCA2, 0x6171, 0xE1C6, 0x6172, 0xE1CA, 0x6173, 0xE1C7, 0x6174, 0xE1CD, 0x6175, 0xBA48, 0x6176, 0xBC79, + 0x6177, 0xBA42, 0x6179, 0xE57A, 0x617A, 0xE1CF, 0x617C, 0xBCA1, 0x617E, 0xBCA4, 0x6180, 0xE1CC, 0x6182, 0xBC7E, 0x6183, 0xE579, + 0x6189, 0xE57E, 0x618A, 0xBECE, 0x618B, 0xE578, 0x618C, 0xE9A3, 0x618D, 0xE5A9, 0x618E, 0xBCA8, 0x6190, 0xBCA6, 0x6191, 0xBECC, + 0x6192, 0xE5A6, 0x6193, 0xE5A2, 0x6194, 0xBCAC, 0x6196, 0xE978, 0x619A, 0xBCAA, 0x619B, 0xE5A1, 0x619D, 0xE976, 0x619F, 0xE5A5, + 0x61A1, 0xE5A8, 0x61A2, 0xE57D, 0x61A4, 0xBCAB, 0x61A7, 0xBCA5, 0x61A8, 0xE977, 0x61A9, 0xBECD, 0x61AA, 0xE5A7, 0x61AB, 0xBCA7, + 0x61AC, 0xBCA9, 0x61AD, 0xE5A4, 0x61AE, 0xBCAD, 0x61AF, 0xE5A3, 0x61B0, 0xE57C, 0x61B1, 0xE57B, 0x61B2, 0xBECB, 0x61B3, 0xE5AB, + 0x61B4, 0xE97A, 0x61B5, 0xECE0, 0x61B6, 0xBED0, 0x61B8, 0xE9A2, 0x61BA, 0xE97E, 0x61BC, 0xECE1, 0x61BE, 0xBED1, 0x61BF, 0xE9A1, + 0x61C1, 0xE97C, 0x61C2, 0xC0B4, 0x61C3, 0xECDF, 0x61C5, 0xE979, 0x61C6, 0xE97B, 0x61C7, 0xC0B5, 0x61C8, 0xBED3, 0x61C9, 0xC0B3, + 0x61CA, 0xBED2, 0x61CB, 0xC0B7, 0x61CC, 0xE97D, 0x61CD, 0xBECF, 0x61D6, 0xEFCF, 0x61D8, 0xEFC7, 0x61DE, 0xECE7, 0x61DF, 0xEFC8, + 0x61E0, 0xECE3, 0x61E3, 0xC256, 0x61E4, 0xECE5, 0x61E5, 0xECE4, 0x61E6, 0xC0B6, 0x61E7, 0xECE2, 0x61E8, 0xECE6, 0x61E9, 0xEFD0, + 0x61EA, 0xEFCC, 0x61EB, 0xEFCE, 0x61ED, 0xEFC9, 0x61EE, 0xEFCA, 0x61F0, 0xEFCD, 0x61F1, 0xEFCB, 0x61F2, 0xC367, 0x61F5, 0xC36A, + 0x61F6, 0xC369, 0x61F7, 0xC368, 0x61F8, 0xC461, 0x61F9, 0xF44A, 0x61FA, 0xC462, 0x61FB, 0xF241, 0x61FC, 0xC4DF, 0x61FD, 0xF5CC, + 0x61FE, 0xC4E0, 0x61FF, 0xC574, 0x6200, 0xC5CA, 0x6201, 0xF7D9, 0x6203, 0xF7DA, 0x6204, 0xF7DB, 0x6207, 0xF9BA, 0x6208, 0xA4E0, + 0x6209, 0xC97C, 0x620A, 0xA5B3, 0x620C, 0xA6A6, 0x620D, 0xA6A7, 0x620E, 0xA6A5, 0x6210, 0xA6A8, 0x6211, 0xA7DA, 0x6212, 0xA7D9, + 0x6214, 0xCCB1, 0x6215, 0xA9CF, 0x6216, 0xA9CE, 0x6219, 0xD1AF, 0x621A, 0xB1AD, 0x621B, 0xB1AE, 0x621F, 0xB475, 0x6220, 0xDD72, + 0x6221, 0xB760, 0x6222, 0xB761, 0x6223, 0xDD74, 0x6224, 0xDD76, 0x6225, 0xDD75, 0x6227, 0xE1D7, 0x6229, 0xE1D6, 0x622A, 0xBA49, + 0x622B, 0xE1D8, 0x622D, 0xE5AC, 0x622E, 0xBCAE, 0x6230, 0xBED4, 0x6232, 0xC0B8, 0x6233, 0xC257, 0x6234, 0xC0B9, 0x6236, 0xA4E1, + 0x623A, 0xCAE6, 0x623D, 0xCCB2, 0x623E, 0xA9D1, 0x623F, 0xA9D0, 0x6240, 0xA9D2, 0x6241, 0xABF3, 0x6242, 0xCED2, 0x6243, 0xCED3, + 0x6246, 0xD1B0, 0x6247, 0xAEB0, 0x6248, 0xB1AF, 0x6249, 0xB476, 0x624A, 0xD951, 0x624B, 0xA4E2, 0x624D, 0xA47E, 0x624E, 0xA4E3, + 0x6250, 0xC97D, 0x6251, 0xA5B7, 0x6252, 0xA5B6, 0x6253, 0xA5B4, 0x6254, 0xA5B5, 0x6258, 0xA6AB, 0x6259, 0xC9E9, 0x625A, 0xC9EB, + 0x625B, 0xA6AA, 0x625C, 0xC9E3, 0x625E, 0xC9E4, 0x6260, 0xC9EA, 0x6261, 0xC9E6, 0x6262, 0xC9E8, 0x6263, 0xA6A9, 0x6264, 0xC9E5, + 0x6265, 0xC9EC, 0x6266, 0xC9E7, 0x626D, 0xA7E1, 0x626E, 0xA7EA, 0x626F, 0xA7E8, 0x6270, 0xCAF0, 0x6271, 0xCAED, 0x6272, 0xCAF5, + 0x6273, 0xA7E6, 0x6274, 0xCAF6, 0x6276, 0xA7DF, 0x6277, 0xCAF3, 0x6279, 0xA7E5, 0x627A, 0xCAEF, 0x627B, 0xCAEE, 0x627C, 0xA7E3, + 0x627D, 0xCAF4, 0x627E, 0xA7E4, 0x627F, 0xA9D3, 0x6280, 0xA7DE, 0x6281, 0xCAF1, 0x6283, 0xCAE7, 0x6284, 0xA7DB, 0x6286, 0xA7EE, + 0x6287, 0xCAEC, 0x6288, 0xCAF2, 0x6289, 0xA7E0, 0x628A, 0xA7E2, 0x628C, 0xCAE8, 0x628E, 0xCAE9, 0x628F, 0xCAEA, 0x6291, 0xA7ED, + 0x6292, 0xA7E7, 0x6293, 0xA7EC, 0x6294, 0xCAEB, 0x6295, 0xA7EB, 0x6296, 0xA7DD, 0x6297, 0xA7DC, 0x6298, 0xA7E9, 0x62A8, 0xA9E1, + 0x62A9, 0xCCBE, 0x62AA, 0xCCB7, 0x62AB, 0xA9DC, 0x62AC, 0xA9EF, 0x62AD, 0xCCB3, 0x62AE, 0xCCBA, 0x62AF, 0xCCBC, 0x62B0, 0xCCBF, + 0x62B1, 0xA9EA, 0x62B3, 0xCCBB, 0x62B4, 0xCCB4, 0x62B5, 0xA9E8, 0x62B6, 0xCCB8, 0x62B8, 0xCCC0, 0x62B9, 0xA9D9, 0x62BB, 0xCCBD, + 0x62BC, 0xA9E3, 0x62BD, 0xA9E2, 0x62BE, 0xCCB6, 0x62BF, 0xA9D7, 0x62C2, 0xA9D8, 0x62C4, 0xA9D6, 0x62C6, 0xA9EE, 0x62C7, 0xA9E6, + 0x62C8, 0xA9E0, 0x62C9, 0xA9D4, 0x62CA, 0xCCB9, 0x62CB, 0xA9DF, 0x62CC, 0xA9D5, 0x62CD, 0xA9E7, 0x62CE, 0xA9F0, 0x62CF, 0xCED4, + 0x62D0, 0xA9E4, 0x62D1, 0xCCB5, 0x62D2, 0xA9DA, 0x62D3, 0xA9DD, 0x62D4, 0xA9DE, 0x62D6, 0xA9EC, 0x62D7, 0xA9ED, 0x62D8, 0xA9EB, + 0x62D9, 0xA9E5, 0x62DA, 0xA9E9, 0x62DB, 0xA9DB, 0x62DC, 0xABF4, 0x62EB, 0xCEDA, 0x62EC, 0xAC41, 0x62ED, 0xABF8, 0x62EE, 0xABFA, + 0x62EF, 0xAC40, 0x62F0, 0xCEE6, 0x62F1, 0xABFD, 0x62F2, 0xD1B1, 0x62F3, 0xAEB1, 0x62F4, 0xAC43, 0x62F5, 0xCED7, 0x62F6, 0xCEDF, + 0x62F7, 0xABFE, 0x62F8, 0xCEDE, 0x62F9, 0xCEDB, 0x62FA, 0xCEE3, 0x62FB, 0xCEE5, 0x62FC, 0xABF7, 0x62FD, 0xABFB, 0x62FE, 0xAC42, + 0x62FF, 0xAEB3, 0x6300, 0xCEE0, 0x6301, 0xABF9, 0x6302, 0xAC45, 0x6303, 0xCED9, 0x6307, 0xABFC, 0x6308, 0xAEB2, 0x6309, 0xABF6, + 0x630B, 0xCED6, 0x630C, 0xCEDD, 0x630D, 0xCED5, 0x630E, 0xCED8, 0x630F, 0xCEDC, 0x6310, 0xD1B2, 0x6311, 0xAC44, 0x6313, 0xCEE1, + 0x6314, 0xCEE2, 0x6315, 0xCEE4, 0x6316, 0xABF5, 0x6328, 0xAEC1, 0x6329, 0xD1BE, 0x632A, 0xAEBF, 0x632B, 0xAEC0, 0x632C, 0xD1B4, + 0x632D, 0xD1C4, 0x632F, 0xAEB6, 0x6332, 0xD566, 0x6333, 0xD1C6, 0x6334, 0xD1C0, 0x6336, 0xD1B7, 0x6338, 0xD1C9, 0x6339, 0xD1BA, + 0x633A, 0xAEBC, 0x633B, 0xD57D, 0x633C, 0xD1BD, 0x633D, 0xAEBE, 0x633E, 0xAEB5, 0x6340, 0xD1CB, 0x6341, 0xD1BF, 0x6342, 0xAEB8, + 0x6343, 0xD1B8, 0x6344, 0xD1B5, 0x6345, 0xD1B6, 0x6346, 0xAEB9, 0x6347, 0xD1C5, 0x6348, 0xD1CC, 0x6349, 0xAEBB, 0x634A, 0xD1BC, + 0x634B, 0xD1BB, 0x634C, 0xAEC3, 0x634D, 0xAEC2, 0x634E, 0xAEB4, 0x634F, 0xAEBA, 0x6350, 0xAEBD, 0x6351, 0xD1C8, 0x6354, 0xD1C2, + 0x6355, 0xAEB7, 0x6356, 0xD1B3, 0x6357, 0xD1CA, 0x6358, 0xD1C1, 0x6359, 0xD1C3, 0x635A, 0xD1C7, 0x6365, 0xD567, 0x6367, 0xB1B7, + 0x6368, 0xB1CB, 0x6369, 0xB1CA, 0x636B, 0xB1BF, 0x636D, 0xD579, 0x636E, 0xD575, 0x636F, 0xD572, 0x6370, 0xD5A6, 0x6371, 0xB1BA, + 0x6372, 0xB1B2, 0x6375, 0xD577, 0x6376, 0xB4A8, 0x6377, 0xB1B6, 0x6378, 0xD5A1, 0x637A, 0xB1CC, 0x637B, 0xB1C9, 0x637C, 0xD57B, + 0x637D, 0xD56A, 0x6380, 0xB1C8, 0x6381, 0xD5A3, 0x6382, 0xD569, 0x6383, 0xB1BD, 0x6384, 0xB1C1, 0x6385, 0xD5A2, 0x6387, 0xD573, + 0x6388, 0xB1C2, 0x6389, 0xB1BC, 0x638A, 0xD568, 0x638C, 0xB478, 0x638D, 0xD5A5, 0x638E, 0xD571, 0x638F, 0xB1C7, 0x6390, 0xD574, + 0x6391, 0xD5A4, 0x6392, 0xB1C6, 0x6394, 0xD952, 0x6396, 0xB1B3, 0x6397, 0xD56F, 0x6398, 0xB1B8, 0x6399, 0xB1C3, 0x639B, 0xB1BE, + 0x639C, 0xD578, 0x639D, 0xD56E, 0x639E, 0xD56C, 0x639F, 0xD57E, 0x63A0, 0xB1B0, 0x63A1, 0xB1C4, 0x63A2, 0xB1B4, 0x63A3, 0xB477, + 0x63A4, 0xD57C, 0x63A5, 0xB1B5, 0x63A7, 0xB1B1, 0x63A8, 0xB1C0, 0x63A9, 0xB1BB, 0x63AA, 0xB1B9, 0x63AB, 0xD570, 0x63AC, 0xB1C5, + 0x63AD, 0xD56D, 0x63AE, 0xD57A, 0x63AF, 0xD576, 0x63B0, 0xD954, 0x63B1, 0xD953, 0x63BD, 0xD56B, 0x63BE, 0xD964, 0x63C0, 0xB47A, + 0x63C2, 0xD96A, 0x63C3, 0xD959, 0x63C4, 0xD967, 0x63C5, 0xDD77, 0x63C6, 0xB47D, 0x63C7, 0xD96B, 0x63C8, 0xD96E, 0x63C9, 0xB47C, + 0x63CA, 0xD95C, 0x63CB, 0xD96D, 0x63CC, 0xD96C, 0x63CD, 0xB47E, 0x63CE, 0xD955, 0x63CF, 0xB479, 0x63D0, 0xB4A3, 0x63D2, 0xB4A1, + 0x63D3, 0xD969, 0x63D5, 0xD95F, 0x63D6, 0xB4A5, 0x63D7, 0xD970, 0x63D8, 0xD968, 0x63D9, 0xD971, 0x63DA, 0xB4AD, 0x63DB, 0xB4AB, + 0x63DC, 0xD966, 0x63DD, 0xD965, 0x63DF, 0xD963, 0x63E0, 0xD95D, 0x63E1, 0xB4A4, 0x63E3, 0xB4A2, 0x63E4, 0xD1B9, 0x63E5, 0xD956, + 0x63E7, 0xDDB7, 0x63E8, 0xD957, 0x63E9, 0xB47B, 0x63EA, 0xB4AA, 0x63EB, 0xDD79, 0x63ED, 0xB4A6, 0x63EE, 0xB4A7, 0x63EF, 0xD958, + 0x63F0, 0xD96F, 0x63F1, 0xDD78, 0x63F2, 0xD960, 0x63F3, 0xD95B, 0x63F4, 0xB4A9, 0x63F5, 0xD961, 0x63F6, 0xD95E, 0x63F9, 0xB4AE, + 0x6406, 0xB770, 0x6409, 0xDD7C, 0x640A, 0xDDB1, 0x640B, 0xDDB6, 0x640C, 0xDDAA, 0x640D, 0xB76C, 0x640E, 0xDDBB, 0x640F, 0xB769, + 0x6410, 0xDD7A, 0x6412, 0xDD7B, 0x6413, 0xB762, 0x6414, 0xB76B, 0x6415, 0xDDA4, 0x6416, 0xB76E, 0x6417, 0xB76F, 0x6418, 0xDDA5, + 0x641A, 0xDDB2, 0x641B, 0xDDB8, 0x641C, 0xB76A, 0x641E, 0xB764, 0x641F, 0xDDA3, 0x6420, 0xDD7D, 0x6421, 0xDDBA, 0x6422, 0xDDA8, + 0x6423, 0xDDA9, 0x6424, 0xDD7E, 0x6425, 0xDDB4, 0x6426, 0xDDAB, 0x6427, 0xDDB5, 0x6428, 0xDDAD, 0x642A, 0xB765, 0x642B, 0xE1D9, + 0x642C, 0xB768, 0x642D, 0xB766, 0x642E, 0xDDB9, 0x642F, 0xDDB0, 0x6430, 0xDDAC, 0x6433, 0xDDA1, 0x6434, 0xBA53, 0x6435, 0xDDAF, + 0x6436, 0xB76D, 0x6437, 0xDDA7, 0x6439, 0xDDA6, 0x643D, 0xB767, 0x643E, 0xB763, 0x643F, 0xE1EE, 0x6440, 0xDDB3, 0x6441, 0xDDAE, + 0x6443, 0xDDA2, 0x644B, 0xE1E9, 0x644D, 0xE1DA, 0x644E, 0xE1E5, 0x6450, 0xE1EC, 0x6451, 0xBA51, 0x6452, 0xB4AC, 0x6453, 0xE1EA, + 0x6454, 0xBA4C, 0x6458, 0xBA4B, 0x6459, 0xE1F1, 0x645B, 0xE1DB, 0x645C, 0xE1E8, 0x645D, 0xE1DC, 0x645E, 0xE1E7, 0x645F, 0xBA4F, + 0x6460, 0xE1EB, 0x6461, 0xD962, 0x6465, 0xE1F2, 0x6466, 0xE1E3, 0x6467, 0xBA52, 0x6468, 0xE5BA, 0x6469, 0xBCAF, 0x646B, 0xE1F0, + 0x646C, 0xE1EF, 0x646D, 0xBA54, 0x646E, 0xE5AD, 0x646F, 0xBCB0, 0x6470, 0xE5AE, 0x6472, 0xE1DF, 0x6473, 0xE1E0, 0x6474, 0xE1DD, + 0x6475, 0xE1E2, 0x6476, 0xE1DE, 0x6477, 0xE1F3, 0x6478, 0xBA4E, 0x6479, 0xBCB1, 0x647A, 0xBA50, 0x647B, 0xBA55, 0x647D, 0xE1E1, + 0x647F, 0xE1ED, 0x6482, 0xE1E6, 0x6485, 0xE5B1, 0x6487, 0xBA4A, 0x6488, 0xBCB4, 0x6489, 0xE9AA, 0x648A, 0xE5B6, 0x648B, 0xE5B5, + 0x648C, 0xE5B7, 0x648F, 0xE5B4, 0x6490, 0xBCB5, 0x6492, 0xBCBB, 0x6493, 0xBCB8, 0x6495, 0xBCB9, 0x6496, 0xE5AF, 0x6497, 0xE5B2, + 0x6498, 0xE5BC, 0x6499, 0xBCC1, 0x649A, 0xBCBF, 0x649C, 0xE5B3, 0x649D, 0xD95A, 0x649E, 0xBCB2, 0x649F, 0xE5B9, 0x64A0, 0xE5B0, + 0x64A2, 0xBCC2, 0x64A3, 0xE5B8, 0x64A4, 0xBA4D, 0x64A5, 0xBCB7, 0x64A6, 0xE1E4, 0x64A9, 0xBCBA, 0x64AB, 0xBCBE, 0x64AC, 0xBCC0, + 0x64AD, 0xBCBD, 0x64AE, 0xBCBC, 0x64B0, 0xBCB6, 0x64B1, 0xE5BB, 0x64B2, 0xBCB3, 0x64B3, 0xBCC3, 0x64BB, 0xBED8, 0x64BC, 0xBED9, + 0x64BD, 0xE9A9, 0x64BE, 0xBEE2, 0x64BF, 0xBEDF, 0x64C1, 0xBED6, 0x64C2, 0xBEDD, 0x64C3, 0xE9AB, 0x64C4, 0xBEDB, 0x64C5, 0xBED5, + 0x64C7, 0xBEDC, 0x64C9, 0xE9A8, 0x64CA, 0xC0BB, 0x64CB, 0xBED7, 0x64CD, 0xBEDE, 0x64CE, 0xC0BA, 0x64CF, 0xE9A7, 0x64D0, 0xE9A6, + 0x64D2, 0xBEE0, 0x64D4, 0xBEE1, 0x64D6, 0xE9A5, 0x64D7, 0xE9A4, 0x64D8, 0xC0BC, 0x64D9, 0xE9AE, 0x64DA, 0xBEDA, 0x64DB, 0xE9AC, + 0x64E0, 0xC0BD, 0x64E2, 0xC0C2, 0x64E3, 0xECEA, 0x64E4, 0xECEC, 0x64E6, 0xC0BF, 0x64E8, 0xECED, 0x64E9, 0xECE9, 0x64EB, 0xECEB, + 0x64EC, 0xC0C0, 0x64ED, 0xC0C3, 0x64EF, 0xECE8, 0x64F0, 0xC0BE, 0x64F1, 0xC0C1, 0x64F2, 0xC259, 0x64F3, 0xE9AD, 0x64F4, 0xC258, + 0x64F7, 0xC25E, 0x64F8, 0xEFD4, 0x64FA, 0xC25C, 0x64FB, 0xC25D, 0x64FC, 0xEFD7, 0x64FD, 0xEFD3, 0x64FE, 0xC25A, 0x64FF, 0xEFD1, + 0x6500, 0xC36B, 0x6501, 0xEFD5, 0x6503, 0xEFD6, 0x6504, 0xEFD2, 0x6506, 0xC25B, 0x6507, 0xF242, 0x6509, 0xF245, 0x650C, 0xF246, + 0x650D, 0xF244, 0x650E, 0xF247, 0x650F, 0xC36C, 0x6510, 0xF243, 0x6513, 0xF44E, 0x6514, 0xC464, 0x6515, 0xF44D, 0x6516, 0xF44C, + 0x6517, 0xF44B, 0x6518, 0xC463, 0x6519, 0xC465, 0x651B, 0xF5CD, 0x651C, 0xC4E2, 0x651D, 0xC4E1, 0x6520, 0xF6E1, 0x6521, 0xF6E0, + 0x6522, 0xF6E3, 0x6523, 0xC5CB, 0x6524, 0xC575, 0x6525, 0xF7DD, 0x6526, 0xF6E2, 0x6529, 0xF7DC, 0x652A, 0xC5CD, 0x652B, 0xC5CC, + 0x652C, 0xC5F3, 0x652D, 0xF8A9, 0x652E, 0xF8EF, 0x652F, 0xA4E4, 0x6532, 0xD972, 0x6533, 0xE9AF, 0x6536, 0xA6AC, 0x6537, 0xCAF7, + 0x6538, 0xA7F1, 0x6539, 0xA7EF, 0x653B, 0xA7F0, 0x653D, 0xCCC1, 0x653E, 0xA9F1, 0x653F, 0xAC46, 0x6541, 0xCEE7, 0x6543, 0xCEE8, + 0x6545, 0xAC47, 0x6546, 0xD1CE, 0x6548, 0xAEC4, 0x6549, 0xAEC5, 0x654A, 0xD1CD, 0x654F, 0xB1D3, 0x6551, 0xB1CF, 0x6553, 0xD5A7, + 0x6554, 0xB1D6, 0x6555, 0xB1D5, 0x6556, 0xB1CE, 0x6557, 0xB1D1, 0x6558, 0xB1D4, 0x6559, 0xB1D0, 0x655C, 0xD976, 0x655D, 0xB1CD, + 0x655E, 0xB4AF, 0x6562, 0xB4B1, 0x6563, 0xB4B2, 0x6564, 0xD975, 0x6565, 0xD978, 0x6566, 0xB4B0, 0x6567, 0xD973, 0x6568, 0xD977, + 0x656A, 0xD974, 0x656C, 0xB771, 0x656F, 0xDDBC, 0x6572, 0xBA56, 0x6573, 0xE1F4, 0x6574, 0xBEE3, 0x6575, 0xBCC4, 0x6576, 0xE5BD, + 0x6577, 0xBCC5, 0x6578, 0xBCC6, 0x6579, 0xE5BF, 0x657A, 0xE5BE, 0x657B, 0xE5C0, 0x657C, 0xE9B1, 0x657F, 0xE9B0, 0x6580, 0xECEF, + 0x6581, 0xECEE, 0x6582, 0xC0C4, 0x6583, 0xC0C5, 0x6584, 0xF248, 0x6587, 0xA4E5, 0x658C, 0xD979, 0x6590, 0xB4B4, 0x6591, 0xB4B3, + 0x6592, 0xDDBD, 0x6594, 0xEFD8, 0x6595, 0xC4E3, 0x6596, 0xF7DE, 0x6597, 0xA4E6, 0x6599, 0xAEC6, 0x659B, 0xB1D8, 0x659C, 0xB1D7, + 0x659D, 0xD97A, 0x659E, 0xD97B, 0x659F, 0xB772, 0x65A0, 0xE1F5, 0x65A1, 0xBA57, 0x65A2, 0xE9B2, 0x65A4, 0xA4E7, 0x65A5, 0xA5B8, + 0x65A7, 0xA9F2, 0x65A8, 0xCCC2, 0x65AA, 0xCEE9, 0x65AB, 0xAC48, 0x65AC, 0xB1D9, 0x65AE, 0xD97C, 0x65AF, 0xB4B5, 0x65B0, 0xB773, + 0x65B2, 0xE5C1, 0x65B3, 0xE5C2, 0x65B6, 0xECF0, 0x65B7, 0xC25F, 0x65B8, 0xF8F0, 0x65B9, 0xA4E8, 0x65BB, 0xCCC3, 0x65BC, 0xA9F3, + 0x65BD, 0xAC49, 0x65BF, 0xCEEA, 0x65C1, 0xAEC7, 0x65C2, 0xD1D2, 0x65C3, 0xD1D0, 0x65C4, 0xD1D1, 0x65C5, 0xAEC8, 0x65C6, 0xD1CF, + 0x65CB, 0xB1DB, 0x65CC, 0xB1DC, 0x65CD, 0xD5A8, 0x65CE, 0xB1DD, 0x65CF, 0xB1DA, 0x65D0, 0xD97D, 0x65D2, 0xD97E, 0x65D3, 0xDDBE, + 0x65D6, 0xBA59, 0x65D7, 0xBA58, 0x65DA, 0xECF1, 0x65DB, 0xEFD9, 0x65DD, 0xF24A, 0x65DE, 0xF249, 0x65DF, 0xF44F, 0x65E1, 0xC95E, + 0x65E2, 0xAC4A, 0x65E5, 0xA4E9, 0x65E6, 0xA5B9, 0x65E8, 0xA6AE, 0x65E9, 0xA6AD, 0x65EC, 0xA6AF, 0x65ED, 0xA6B0, 0x65EE, 0xC9EE, + 0x65EF, 0xC9ED, 0x65F0, 0xCAF8, 0x65F1, 0xA7F2, 0x65F2, 0xCAFB, 0x65F3, 0xCAFA, 0x65F4, 0xCAF9, 0x65F5, 0xCAFC, 0x65FA, 0xA9F4, + 0x65FB, 0xCCC9, 0x65FC, 0xCCC5, 0x65FD, 0xCCCE, 0x6600, 0xA9FB, 0x6602, 0xA9F9, 0x6603, 0xCCCA, 0x6604, 0xCCC6, 0x6605, 0xCCCD, + 0x6606, 0xA9F8, 0x6607, 0xAA40, 0x6608, 0xCCC8, 0x6609, 0xCCC4, 0x660A, 0xA9FE, 0x660B, 0xCCCB, 0x660C, 0xA9F7, 0x660D, 0xCCCC, + 0x660E, 0xA9FA, 0x660F, 0xA9FC, 0x6610, 0xCCD0, 0x6611, 0xCCCF, 0x6612, 0xCCC7, 0x6613, 0xA9F6, 0x6614, 0xA9F5, 0x6615, 0xA9FD, + 0x661C, 0xCEEF, 0x661D, 0xCEF5, 0x661F, 0xAC50, 0x6620, 0xAC4D, 0x6621, 0xCEEC, 0x6622, 0xCEF1, 0x6624, 0xAC53, 0x6625, 0xAC4B, + 0x6626, 0xCEF0, 0x6627, 0xAC4E, 0x6628, 0xAC51, 0x662B, 0xCEF3, 0x662D, 0xAC4C, 0x662E, 0xCEF8, 0x662F, 0xAC4F, 0x6631, 0xAC52, + 0x6632, 0xCEED, 0x6633, 0xCEF2, 0x6634, 0xCEF6, 0x6635, 0xCEEE, 0x6636, 0xCEEB, 0x6639, 0xCEF7, 0x663A, 0xCEF4, 0x6641, 0xAED0, + 0x6642, 0xAEC9, 0x6643, 0xAECC, 0x6645, 0xAECF, 0x6647, 0xD1D5, 0x6649, 0xAECA, 0x664A, 0xD1D3, 0x664C, 0xAECE, 0x664F, 0xAECB, + 0x6651, 0xD1D6, 0x6652, 0xAECD, 0x6659, 0xD5AC, 0x665A, 0xB1DF, 0x665B, 0xD5AB, 0x665C, 0xD5AD, 0x665D, 0xB1DE, 0x665E, 0xB1E3, + 0x665F, 0xD1D4, 0x6661, 0xD5AA, 0x6662, 0xD5AE, 0x6664, 0xB1E0, 0x6665, 0xD5A9, 0x6666, 0xB1E2, 0x6668, 0xB1E1, 0x666A, 0xD9A7, + 0x666C, 0xD9A2, 0x666E, 0xB4B6, 0x666F, 0xB4BA, 0x6670, 0xB4B7, 0x6671, 0xD9A5, 0x6672, 0xD9A8, 0x6674, 0xB4B8, 0x6676, 0xB4B9, + 0x6677, 0xB4BE, 0x6678, 0xDDC7, 0x6679, 0xD9A6, 0x667A, 0xB4BC, 0x667B, 0xD9A3, 0x667C, 0xD9A1, 0x667E, 0xB4BD, 0x6680, 0xD9A4, + 0x6684, 0xB779, 0x6686, 0xDDBF, 0x6687, 0xB776, 0x6688, 0xB777, 0x6689, 0xB775, 0x668A, 0xDDC4, 0x668B, 0xDDC3, 0x668C, 0xDDC0, + 0x668D, 0xB77B, 0x6690, 0xDDC2, 0x6691, 0xB4BB, 0x6694, 0xDDC6, 0x6695, 0xDDC1, 0x6696, 0xB778, 0x6697, 0xB774, 0x6698, 0xB77A, + 0x6699, 0xDDC5, 0x669D, 0xBA5C, 0x669F, 0xE1F8, 0x66A0, 0xE1F7, 0x66A1, 0xE1F6, 0x66A2, 0xBA5A, 0x66A8, 0xBA5B, 0x66A9, 0xE5C5, + 0x66AA, 0xE5C8, 0x66AB, 0xBCC8, 0x66AE, 0xBCC7, 0x66AF, 0xE5C9, 0x66B0, 0xE5C4, 0x66B1, 0xBCCA, 0x66B2, 0xE5C6, 0x66B4, 0xBCC9, + 0x66B5, 0xE5C3, 0x66B7, 0xE5C7, 0x66B8, 0xBEE9, 0x66B9, 0xBEE6, 0x66BA, 0xE9BB, 0x66BB, 0xE9BA, 0x66BD, 0xE9B9, 0x66BE, 0xE9B4, + 0x66C0, 0xE9B5, 0x66C4, 0xBEE7, 0x66C6, 0xBEE4, 0x66C7, 0xBEE8, 0x66C8, 0xE9B3, 0x66C9, 0xBEE5, 0x66CA, 0xE9B6, 0x66CB, 0xE9B7, + 0x66CC, 0xE9BC, 0x66CF, 0xE9B8, 0x66D2, 0xECF2, 0x66D6, 0xC0C7, 0x66D8, 0xEFDC, 0x66D9, 0xC0C6, 0x66DA, 0xEFDA, 0x66DB, 0xEFDB, + 0x66DC, 0xC260, 0x66DD, 0xC36E, 0x66DE, 0xF24B, 0x66E0, 0xC36D, 0x66E3, 0xF451, 0x66E4, 0xF452, 0x66E6, 0xC466, 0x66E8, 0xF450, + 0x66E9, 0xC4E4, 0x66EB, 0xF7DF, 0x66EC, 0xC5CE, 0x66ED, 0xF8AA, 0x66EE, 0xF8AB, 0x66F0, 0xA4EA, 0x66F2, 0xA6B1, 0x66F3, 0xA6B2, + 0x66F4, 0xA7F3, 0x66F6, 0xCCD1, 0x66F7, 0xAC54, 0x66F8, 0xAED1, 0x66F9, 0xB1E4, 0x66FC, 0xB0D2, 0x66FE, 0xB4BF, 0x66FF, 0xB4C0, + 0x6700, 0xB3CC, 0x6701, 0xD9A9, 0x6703, 0xB77C, 0x6704, 0xE1FA, 0x6705, 0xE1F9, 0x6708, 0xA4EB, 0x6709, 0xA6B3, 0x670A, 0xCCD2, + 0x670B, 0xAA42, 0x670D, 0xAA41, 0x670F, 0xCEF9, 0x6710, 0xCEFA, 0x6712, 0xD1D7, 0x6713, 0xD1D8, 0x6714, 0xAED2, 0x6715, 0xAED3, + 0x6717, 0xAED4, 0x6718, 0xD5AF, 0x671B, 0xB1E6, 0x671D, 0xB4C2, 0x671F, 0xB4C1, 0x6720, 0xDDC8, 0x6721, 0xDF7A, 0x6722, 0xE1FB, + 0x6723, 0xE9BD, 0x6726, 0xC261, 0x6727, 0xC467, 0x6728, 0xA4EC, 0x672A, 0xA5BC, 0x672B, 0xA5BD, 0x672C, 0xA5BB, 0x672D, 0xA5BE, + 0x672E, 0xA5BA, 0x6731, 0xA6B6, 0x6733, 0xC9F6, 0x6734, 0xA6B5, 0x6735, 0xA6B7, 0x6738, 0xC9F1, 0x6739, 0xC9F0, 0x673A, 0xC9F3, + 0x673B, 0xC9F2, 0x673C, 0xC9F5, 0x673D, 0xA6B4, 0x673E, 0xC9EF, 0x673F, 0xC9F4, 0x6745, 0xCAFD, 0x6746, 0xA7FD, 0x6747, 0xCAFE, + 0x6748, 0xCB43, 0x6749, 0xA7FC, 0x674B, 0xCB47, 0x674C, 0xCB42, 0x674D, 0xCB45, 0x674E, 0xA7F5, 0x674F, 0xA7F6, 0x6750, 0xA7F7, + 0x6751, 0xA7F8, 0x6753, 0xA840, 0x6755, 0xCB41, 0x6756, 0xA7FA, 0x6757, 0xA841, 0x6759, 0xCB40, 0x675A, 0xCB46, 0x675C, 0xA7F9, + 0x675D, 0xCB44, 0x675E, 0xA7FB, 0x675F, 0xA7F4, 0x6760, 0xA7FE, 0x676A, 0xAA57, 0x676C, 0xCCD4, 0x676D, 0xAA43, 0x676F, 0xAA4D, + 0x6770, 0xAA4E, 0x6771, 0xAA46, 0x6772, 0xAA58, 0x6773, 0xAA48, 0x6774, 0xCCDC, 0x6775, 0xAA53, 0x6776, 0xCCD7, 0x6777, 0xAA49, + 0x6778, 0xCCE6, 0x6779, 0xCCE7, 0x677A, 0xCCDF, 0x677B, 0xCCD8, 0x677C, 0xAA56, 0x677D, 0xCCE4, 0x677E, 0xAA51, 0x677F, 0xAA4F, + 0x6781, 0xCCE5, 0x6783, 0xCCE3, 0x6784, 0xCCDB, 0x6785, 0xCCD3, 0x6786, 0xCCDA, 0x6787, 0xAA4A, 0x6789, 0xAA50, 0x678B, 0xAA44, + 0x678C, 0xCCDE, 0x678D, 0xCCDD, 0x678E, 0xCCD5, 0x6790, 0xAA52, 0x6791, 0xCCE1, 0x6792, 0xCCD6, 0x6793, 0xAA55, 0x6794, 0xCCE8, + 0x6795, 0xAA45, 0x6797, 0xAA4C, 0x6798, 0xCCD9, 0x6799, 0xCCE2, 0x679A, 0xAA54, 0x679C, 0xAA47, 0x679D, 0xAA4B, 0x679F, 0xCCE0, + 0x67AE, 0xCF5B, 0x67AF, 0xAC5C, 0x67B0, 0xAC69, 0x67B2, 0xCF56, 0x67B3, 0xCF4C, 0x67B4, 0xAC62, 0x67B5, 0xCF4A, 0x67B6, 0xAC5B, + 0x67B7, 0xCF45, 0x67B8, 0xAC65, 0x67B9, 0xCF52, 0x67BA, 0xCEFE, 0x67BB, 0xCF41, 0x67C0, 0xCF44, 0x67C1, 0xCEFB, 0x67C2, 0xCF51, + 0x67C3, 0xCF61, 0x67C4, 0xAC60, 0x67C5, 0xCF46, 0x67C6, 0xCF58, 0x67C8, 0xCEFD, 0x67C9, 0xCF5F, 0x67CA, 0xCF60, 0x67CB, 0xCF63, + 0x67CC, 0xCF5A, 0x67CD, 0xCF4B, 0x67CE, 0xCF53, 0x67CF, 0xAC66, 0x67D0, 0xAC59, 0x67D1, 0xAC61, 0x67D2, 0xAC6D, 0x67D3, 0xAC56, + 0x67D4, 0xAC58, 0x67D8, 0xCF43, 0x67D9, 0xAC6A, 0x67DA, 0xAC63, 0x67DB, 0xCF5D, 0x67DC, 0xCF40, 0x67DD, 0xAC6C, 0x67DE, 0xAC67, + 0x67DF, 0xCF49, 0x67E2, 0xAC6B, 0x67E3, 0xCF50, 0x67E4, 0xCF48, 0x67E5, 0xAC64, 0x67E6, 0xCF5C, 0x67E7, 0xCF54, 0x67E9, 0xAC5E, + 0x67EA, 0xCF62, 0x67EB, 0xCF47, 0x67EC, 0xAC5A, 0x67ED, 0xCF59, 0x67EE, 0xCF4F, 0x67EF, 0xAC5F, 0x67F0, 0xCF55, 0x67F1, 0xAC57, + 0x67F2, 0xCEFC, 0x67F3, 0xAC68, 0x67F4, 0xAEE3, 0x67F5, 0xAC5D, 0x67F6, 0xCF4E, 0x67F7, 0xCF4D, 0x67F8, 0xCF42, 0x67FA, 0xCF5E, + 0x67FC, 0xCF57, 0x67FF, 0xAC55, 0x6812, 0xD1EC, 0x6813, 0xAEEA, 0x6814, 0xD1ED, 0x6816, 0xD1E1, 0x6817, 0xAEDF, 0x6818, 0xAEEB, + 0x681A, 0xD1DA, 0x681C, 0xD1E3, 0x681D, 0xD1EB, 0x681F, 0xD1D9, 0x6820, 0xD1F4, 0x6821, 0xAED5, 0x6825, 0xD1F3, 0x6826, 0xD1EE, + 0x6828, 0xD1EF, 0x6829, 0xAEDD, 0x682A, 0xAEE8, 0x682B, 0xD1E5, 0x682D, 0xD1E6, 0x682E, 0xD1F0, 0x682F, 0xD1E7, 0x6831, 0xD1E2, + 0x6832, 0xD1DC, 0x6833, 0xD1DD, 0x6834, 0xD1EA, 0x6835, 0xD1E4, 0x6838, 0xAED6, 0x6839, 0xAEDA, 0x683A, 0xD1F2, 0x683B, 0xD1DE, + 0x683C, 0xAEE6, 0x683D, 0xAEE2, 0x6840, 0xAEE5, 0x6841, 0xAEEC, 0x6842, 0xAEDB, 0x6843, 0xAEE7, 0x6844, 0xD1E9, 0x6845, 0xAEE9, + 0x6846, 0xAED8, 0x6848, 0xAED7, 0x6849, 0xD1DB, 0x684B, 0xD1DF, 0x684C, 0xAEE0, 0x684D, 0xD1F1, 0x684E, 0xD1E8, 0x684F, 0xD1E0, + 0x6850, 0xAEE4, 0x6851, 0xAEE1, 0x6853, 0xAED9, 0x6854, 0xAEDC, 0x686B, 0xD5C4, 0x686D, 0xD5B4, 0x686E, 0xD5B5, 0x686F, 0xD5B9, + 0x6871, 0xD5C8, 0x6872, 0xD5C5, 0x6874, 0xD5BE, 0x6875, 0xD5BD, 0x6876, 0xB1ED, 0x6877, 0xD5C1, 0x6878, 0xD5D0, 0x6879, 0xD5B0, + 0x687B, 0xD5D1, 0x687C, 0xD5C3, 0x687D, 0xD5D5, 0x687E, 0xD5C9, 0x687F, 0xB1EC, 0x6880, 0xD5C7, 0x6881, 0xB1E7, 0x6882, 0xB1FC, + 0x6883, 0xB1F2, 0x6885, 0xB1F6, 0x6886, 0xB1F5, 0x6887, 0xD5B1, 0x6889, 0xD5CE, 0x688A, 0xD5D4, 0x688B, 0xD5CC, 0x688C, 0xD5D3, + 0x688F, 0xD5C0, 0x6890, 0xD5B2, 0x6891, 0xD5D2, 0x6892, 0xD5C2, 0x6893, 0xB1EA, 0x6894, 0xB1F7, 0x6896, 0xD5CB, 0x6897, 0xB1F0, + 0x689B, 0xD5CA, 0x689C, 0xD5B3, 0x689D, 0xB1F8, 0x689F, 0xB1FA, 0x68A0, 0xD5CD, 0x68A1, 0xB1FB, 0x68A2, 0xB1E9, 0x68A3, 0xD5BA, + 0x68A4, 0xD5CF, 0x68A7, 0xB1EF, 0x68A8, 0xB1F9, 0x68A9, 0xD5BC, 0x68AA, 0xD5C6, 0x68AB, 0xD5B7, 0x68AC, 0xD5BB, 0x68AD, 0xB1F4, + 0x68AE, 0xD5B6, 0x68AF, 0xB1E8, 0x68B0, 0xB1F1, 0x68B1, 0xB1EE, 0x68B2, 0xD5BF, 0x68B3, 0xAEDE, 0x68B4, 0xD9C0, 0x68B5, 0xB1EB, + 0x68C4, 0xB1F3, 0x68C6, 0xD9C3, 0x68C7, 0xD9D9, 0x68C8, 0xD9CE, 0x68C9, 0xB4D6, 0x68CB, 0xB4D1, 0x68CC, 0xD9BD, 0x68CD, 0xB4D2, + 0x68CE, 0xD9CD, 0x68D0, 0xD9C6, 0x68D1, 0xD9D3, 0x68D2, 0xB4CE, 0x68D3, 0xD9AB, 0x68D4, 0xD9D5, 0x68D5, 0xB4C4, 0x68D6, 0xD9B3, + 0x68D7, 0xB4C7, 0x68D8, 0xB4C6, 0x68DA, 0xB4D7, 0x68DC, 0xD9AD, 0x68DD, 0xD9CF, 0x68DE, 0xD9D0, 0x68DF, 0xB4C9, 0x68E0, 0xB4C5, + 0x68E1, 0xD9BB, 0x68E3, 0xB4D0, 0x68E4, 0xD9B6, 0x68E6, 0xD9D1, 0x68E7, 0xB4CC, 0x68E8, 0xD9C9, 0x68E9, 0xD9D6, 0x68EA, 0xD9B0, + 0x68EB, 0xD9B5, 0x68EC, 0xD9AF, 0x68EE, 0xB4CB, 0x68EF, 0xD9C2, 0x68F0, 0xDDDE, 0x68F1, 0xD9B1, 0x68F2, 0xB4CF, 0x68F3, 0xD9BA, + 0x68F4, 0xD9D2, 0x68F5, 0xB4CA, 0x68F6, 0xD9B7, 0x68F7, 0xD9B4, 0x68F8, 0xD9C5, 0x68F9, 0xB4CD, 0x68FA, 0xB4C3, 0x68FB, 0xB4D9, + 0x68FC, 0xD9C8, 0x68FD, 0xD9C7, 0x6904, 0xD9AC, 0x6905, 0xB4C8, 0x6906, 0xD9D4, 0x6907, 0xD9BC, 0x6908, 0xD9BE, 0x690A, 0xD9CB, + 0x690B, 0xD9CA, 0x690C, 0xD9AA, 0x690D, 0xB4D3, 0x690E, 0xB4D5, 0x690F, 0xD9B2, 0x6910, 0xD9B9, 0x6911, 0xD9C1, 0x6912, 0xB4D4, + 0x6913, 0xD9B8, 0x6914, 0xD9C4, 0x6915, 0xD9D7, 0x6917, 0xD9CC, 0x6925, 0xD9D8, 0x692A, 0xD9AE, 0x692F, 0xDDF2, 0x6930, 0xB7A6, + 0x6932, 0xDDF0, 0x6933, 0xDDDB, 0x6934, 0xDDE0, 0x6935, 0xDDD9, 0x6937, 0xDDEC, 0x6938, 0xDDCB, 0x6939, 0xDDD2, 0x693B, 0xDDEA, + 0x693C, 0xDDF4, 0x693D, 0xDDDC, 0x693F, 0xDDCF, 0x6940, 0xDDE2, 0x6941, 0xDDE7, 0x6942, 0xDDD3, 0x6944, 0xDDE4, 0x6945, 0xDDD0, + 0x6948, 0xDDD7, 0x6949, 0xDDD8, 0x694A, 0xB7A8, 0x694B, 0xDDEB, 0x694C, 0xDDE9, 0x694E, 0xDDCC, 0x694F, 0xDDEE, 0x6951, 0xDDEF, + 0x6952, 0xDDF1, 0x6953, 0xB7AC, 0x6954, 0xB7A4, 0x6956, 0xD5B8, 0x6957, 0xDDD4, 0x6958, 0xDDE6, 0x6959, 0xDDD5, 0x695A, 0xB7A1, + 0x695B, 0xB7B1, 0x695C, 0xDDED, 0x695D, 0xB7AF, 0x695E, 0xB7AB, 0x695F, 0xDDCA, 0x6960, 0xB7A3, 0x6962, 0xDDCD, 0x6963, 0xB7B0, + 0x6965, 0xDDDD, 0x6966, 0xDDC9, 0x6968, 0xB7A9, 0x6969, 0xDDE1, 0x696A, 0xDDD1, 0x696B, 0xB7AA, 0x696C, 0xDDDA, 0x696D, 0xB77E, + 0x696E, 0xB4D8, 0x696F, 0xDDE3, 0x6970, 0xD9BF, 0x6971, 0xDDCE, 0x6974, 0xDDE8, 0x6975, 0xB7A5, 0x6976, 0xDDE5, 0x6977, 0xB7A2, + 0x6978, 0xDDDF, 0x6979, 0xB7AD, 0x697A, 0xDDD6, 0x697B, 0xDDF3, 0x6982, 0xB7A7, 0x6983, 0xDEC6, 0x6986, 0xB7AE, 0x698D, 0xE24A, + 0x698E, 0xE248, 0x6990, 0xE25E, 0x6991, 0xE246, 0x6993, 0xE258, 0x6994, 0xB77D, 0x6995, 0xBA5F, 0x6996, 0xE242, 0x6997, 0xE25D, + 0x6999, 0xE247, 0x699A, 0xE255, 0x699B, 0xBA64, 0x699C, 0xBA5D, 0x699E, 0xE25B, 0x69A0, 0xE240, 0x69A1, 0xE25A, 0x69A3, 0xBA6F, + 0x69A4, 0xE251, 0x69A5, 0xE261, 0x69A6, 0xBA6D, 0x69A7, 0xE249, 0x69A8, 0xBA5E, 0x69A9, 0xE24B, 0x69AA, 0xE259, 0x69AB, 0xBA67, + 0x69AC, 0xE244, 0x69AD, 0xBA6B, 0x69AE, 0xBA61, 0x69AF, 0xE24D, 0x69B0, 0xE243, 0x69B1, 0xE1FC, 0x69B3, 0xE257, 0x69B4, 0xBA68, + 0x69B5, 0xE260, 0x69B6, 0xE1FD, 0x69B7, 0xBA65, 0x69B9, 0xE253, 0x69BB, 0xBA66, 0x69BC, 0xE245, 0x69BD, 0xE250, 0x69BE, 0xE24C, + 0x69BF, 0xE24E, 0x69C1, 0xBA60, 0x69C2, 0xE25F, 0x69C3, 0xBA6E, 0x69C4, 0xE24F, 0x69C6, 0xE262, 0x69C9, 0xE1FE, 0x69CA, 0xE254, + 0x69CB, 0xBA63, 0x69CC, 0xBA6C, 0x69CD, 0xBA6A, 0x69CE, 0xE241, 0x69CF, 0xE256, 0x69D0, 0xBA69, 0x69D3, 0xBA62, 0x69D4, 0xE252, + 0x69D9, 0xE25C, 0x69E2, 0xE5D5, 0x69E4, 0xE5D1, 0x69E5, 0xE5CD, 0x69E6, 0xE5E1, 0x69E7, 0xE5DE, 0x69E8, 0xBCCD, 0x69EB, 0xE5E5, + 0x69EC, 0xE5D4, 0x69ED, 0xBCD8, 0x69EE, 0xE5DB, 0x69F1, 0xE5D0, 0x69F2, 0xE5DA, 0x69F3, 0xBCD5, 0x69F4, 0xE5EE, 0x69F6, 0xE5EB, + 0x69F7, 0xE5DD, 0x69F8, 0xE5CE, 0x69FB, 0xE5E2, 0x69FC, 0xE5E4, 0x69FD, 0xBCD1, 0x69FE, 0xE5D8, 0x69FF, 0xE5D3, 0x6A00, 0xE5CA, + 0x6A01, 0xBCCE, 0x6A02, 0xBCD6, 0x6A04, 0xE5E7, 0x6A05, 0xBCD7, 0x6A06, 0xE5CB, 0x6A07, 0xE5ED, 0x6A08, 0xE5E0, 0x6A09, 0xE5E6, + 0x6A0A, 0xBCD4, 0x6A0D, 0xE5E3, 0x6A0F, 0xE5EA, 0x6A11, 0xBCD9, 0x6A13, 0xBCD3, 0x6A14, 0xE5DC, 0x6A15, 0xE5CF, 0x6A16, 0xE5EF, + 0x6A17, 0xE5CC, 0x6A18, 0xE5E8, 0x6A19, 0xBCD0, 0x6A1B, 0xE5D6, 0x6A1D, 0xE5D7, 0x6A1E, 0xBCCF, 0x6A1F, 0xBCCC, 0x6A20, 0xE5D2, + 0x6A21, 0xBCD2, 0x6A23, 0xBCCB, 0x6A25, 0xE5E9, 0x6A26, 0xE5EC, 0x6A27, 0xE5D9, 0x6A28, 0xE9CA, 0x6A32, 0xE9C2, 0x6A34, 0xE9BE, + 0x6A35, 0xBEF6, 0x6A38, 0xBEEB, 0x6A39, 0xBEF0, 0x6A3A, 0xBEEC, 0x6A3B, 0xE9CC, 0x6A3C, 0xE9D7, 0x6A3D, 0xBEEA, 0x6A3E, 0xE9C4, + 0x6A3F, 0xE9CD, 0x6A40, 0xE5DF, 0x6A41, 0xE9CE, 0x6A44, 0xBEF1, 0x6A46, 0xE9DD, 0x6A47, 0xBEF5, 0x6A48, 0xBEF8, 0x6A49, 0xE9C0, + 0x6A4B, 0xBEF4, 0x6A4D, 0xE9DB, 0x6A4E, 0xE9DC, 0x6A4F, 0xE9D2, 0x6A50, 0xE9D1, 0x6A51, 0xE9C9, 0x6A54, 0xE9D3, 0x6A55, 0xE9DA, + 0x6A56, 0xE9D9, 0x6A58, 0xBEEF, 0x6A59, 0xBEED, 0x6A5A, 0xE9CB, 0x6A5B, 0xE9C8, 0x6A5D, 0xE9C5, 0x6A5E, 0xE9D8, 0x6A5F, 0xBEF7, + 0x6A60, 0xE9D6, 0x6A61, 0xBEF3, 0x6A62, 0xBEF2, 0x6A64, 0xE9D0, 0x6A66, 0xE9BF, 0x6A67, 0xE9C1, 0x6A68, 0xE9C3, 0x6A69, 0xE9D5, + 0x6A6A, 0xE9CF, 0x6A6B, 0xBEEE, 0x6A6D, 0xE9C6, 0x6A6F, 0xE9D4, 0x6A76, 0xE9C7, 0x6A7E, 0xC0CF, 0x6A7F, 0xED45, 0x6A80, 0xC0C8, + 0x6A81, 0xECF5, 0x6A83, 0xED41, 0x6A84, 0xC0CA, 0x6A85, 0xED48, 0x6A87, 0xECFC, 0x6A89, 0xECF7, 0x6A8C, 0xED49, 0x6A8D, 0xECF3, + 0x6A8E, 0xECFE, 0x6A90, 0xC0D1, 0x6A91, 0xED44, 0x6A92, 0xED4A, 0x6A93, 0xECFD, 0x6A94, 0xC0C9, 0x6A95, 0xED40, 0x6A96, 0xECF4, + 0x6A97, 0xC0D0, 0x6A9A, 0xED47, 0x6A9B, 0xECF9, 0x6A9C, 0xC0CC, 0x6A9E, 0xECFB, 0x6A9F, 0xECF8, 0x6AA0, 0xC0D2, 0x6AA1, 0xECFA, + 0x6AA2, 0xC0CB, 0x6AA3, 0xC0CE, 0x6AA4, 0xED43, 0x6AA5, 0xECF6, 0x6AA6, 0xED46, 0x6AA8, 0xED42, 0x6AAC, 0xC263, 0x6AAD, 0xEFE7, + 0x6AAE, 0xC268, 0x6AAF, 0xC269, 0x6AB3, 0xC262, 0x6AB4, 0xEFE6, 0x6AB6, 0xEFE3, 0x6AB7, 0xEFE4, 0x6AB8, 0xC266, 0x6AB9, 0xEFDE, + 0x6ABA, 0xEFE2, 0x6ABB, 0xC265, 0x6ABD, 0xEFDF, 0x6AC2, 0xC267, 0x6AC3, 0xC264, 0x6AC5, 0xEFDD, 0x6AC6, 0xEFE1, 0x6AC7, 0xEFE5, + 0x6ACB, 0xF251, 0x6ACC, 0xF24E, 0x6ACD, 0xF257, 0x6ACF, 0xF256, 0x6AD0, 0xF254, 0x6AD1, 0xF24F, 0x6AD3, 0xC372, 0x6AD9, 0xF250, + 0x6ADA, 0xC371, 0x6ADB, 0xC0CD, 0x6ADC, 0xF253, 0x6ADD, 0xC370, 0x6ADE, 0xF258, 0x6ADF, 0xF252, 0x6AE0, 0xF24D, 0x6AE1, 0xEFE0, + 0x6AE5, 0xC36F, 0x6AE7, 0xF24C, 0x6AE8, 0xF456, 0x6AEA, 0xF455, 0x6AEB, 0xF255, 0x6AEC, 0xC468, 0x6AEE, 0xF459, 0x6AEF, 0xF45A, + 0x6AF0, 0xF454, 0x6AF1, 0xF458, 0x6AF3, 0xF453, 0x6AF8, 0xF5D1, 0x6AF9, 0xF457, 0x6AFA, 0xC4E7, 0x6AFB, 0xC4E5, 0x6AFC, 0xF5CF, + 0x6B00, 0xF5D2, 0x6B02, 0xF5CE, 0x6B03, 0xF5D0, 0x6B04, 0xC4E6, 0x6B08, 0xF6E5, 0x6B09, 0xF6E6, 0x6B0A, 0xC576, 0x6B0B, 0xF6E4, + 0x6B0F, 0xF7E2, 0x6B10, 0xC5CF, 0x6B11, 0xF7E0, 0x6B12, 0xF7E1, 0x6B13, 0xF8AC, 0x6B16, 0xC656, 0x6B17, 0xF8F3, 0x6B18, 0xF8F1, + 0x6B19, 0xF8F2, 0x6B1A, 0xF8F4, 0x6B1E, 0xF9BB, 0x6B20, 0xA4ED, 0x6B21, 0xA6B8, 0x6B23, 0xAA59, 0x6B25, 0xCCE9, 0x6B28, 0xCF64, + 0x6B2C, 0xD1F5, 0x6B2D, 0xD1F7, 0x6B2F, 0xD1F6, 0x6B31, 0xD1F8, 0x6B32, 0xB1FD, 0x6B33, 0xD5D7, 0x6B34, 0xD1F9, 0x6B36, 0xD5D6, + 0x6B37, 0xD5D8, 0x6B38, 0xD5D9, 0x6B39, 0xD9DA, 0x6B3A, 0xB4DB, 0x6B3B, 0xD9DB, 0x6B3C, 0xD9DD, 0x6B3D, 0xB4DC, 0x6B3E, 0xB4DA, + 0x6B3F, 0xD9DC, 0x6B41, 0xDDFA, 0x6B42, 0xDDF8, 0x6B43, 0xDDF7, 0x6B45, 0xDDF6, 0x6B46, 0xDDF5, 0x6B47, 0xB7B2, 0x6B48, 0xDDF9, + 0x6B49, 0xBA70, 0x6B4A, 0xE263, 0x6B4B, 0xE265, 0x6B4C, 0xBA71, 0x6B4D, 0xE264, 0x6B4E, 0xBCDB, 0x6B50, 0xBCDA, 0x6B51, 0xE5F0, + 0x6B54, 0xE9DF, 0x6B55, 0xE9DE, 0x6B56, 0xE9E0, 0x6B59, 0xBEF9, 0x6B5B, 0xED4B, 0x6B5C, 0xC0D3, 0x6B5E, 0xEFE8, 0x6B5F, 0xC26A, + 0x6B60, 0xF259, 0x6B61, 0xC577, 0x6B62, 0xA4EE, 0x6B63, 0xA5BF, 0x6B64, 0xA6B9, 0x6B65, 0xA842, 0x6B66, 0xAA5A, 0x6B67, 0xAA5B, + 0x6B6A, 0xAC6E, 0x6B6D, 0xD1FA, 0x6B72, 0xB7B3, 0x6B76, 0xE6D1, 0x6B77, 0xBEFA, 0x6B78, 0xC26B, 0x6B79, 0xA4EF, 0x6B7B, 0xA6BA, + 0x6B7E, 0xCCEB, 0x6B7F, 0xAA5C, 0x6B80, 0xCCEA, 0x6B82, 0xCF65, 0x6B83, 0xAC6F, 0x6B84, 0xCF66, 0x6B86, 0xAC70, 0x6B88, 0xD1FC, + 0x6B89, 0xAEEE, 0x6B8A, 0xAEED, 0x6B8C, 0xD5DE, 0x6B8D, 0xD5DC, 0x6B8E, 0xD5DD, 0x6B8F, 0xD5DB, 0x6B91, 0xD5DA, 0x6B94, 0xD9DE, + 0x6B95, 0xD9E1, 0x6B96, 0xB4DE, 0x6B97, 0xD9DF, 0x6B98, 0xB4DD, 0x6B99, 0xD9E0, 0x6B9B, 0xDDFB, 0x6B9E, 0xE266, 0x6B9F, 0xE267, + 0x6BA0, 0xE268, 0x6BA2, 0xE5F3, 0x6BA3, 0xE5F2, 0x6BA4, 0xBCDC, 0x6BA5, 0xE5F1, 0x6BA6, 0xE5F4, 0x6BA7, 0xE9E1, 0x6BAA, 0xE9E2, + 0x6BAB, 0xE9E3, 0x6BAD, 0xED4C, 0x6BAE, 0xC0D4, 0x6BAF, 0xC26C, 0x6BB0, 0xF25A, 0x6BB2, 0xC4E8, 0x6BB3, 0xC95F, 0x6BB5, 0xAC71, + 0x6BB6, 0xCF67, 0x6BB7, 0xAEEF, 0x6BBA, 0xB1FE, 0x6BBC, 0xB4DF, 0x6BBD, 0xD9E2, 0x6BBF, 0xB7B5, 0x6BC0, 0xB7B4, 0x6BC3, 0xE269, + 0x6BC4, 0xE26A, 0x6BC5, 0xBCDD, 0x6BC6, 0xBCDE, 0x6BC7, 0xE9E5, 0x6BC8, 0xE9E4, 0x6BC9, 0xEFE9, 0x6BCA, 0xF7E3, 0x6BCB, 0xA4F0, + 0x6BCC, 0xC960, 0x6BCD, 0xA5C0, 0x6BCF, 0xA843, 0x6BD0, 0xCB48, 0x6BD2, 0xAC72, 0x6BD3, 0xB7B6, 0x6BD4, 0xA4F1, 0x6BD6, 0xCF68, + 0x6BD7, 0xAC73, 0x6BD8, 0xCF69, 0x6BDA, 0xC0D5, 0x6BDB, 0xA4F2, 0x6BDE, 0xCCEC, 0x6BE0, 0xCF6A, 0x6BE2, 0xD242, 0x6BE3, 0xD241, + 0x6BE4, 0xD1FE, 0x6BE6, 0xD1FD, 0x6BE7, 0xD243, 0x6BE8, 0xD240, 0x6BEB, 0xB240, 0x6BEC, 0xB241, 0x6BEF, 0xB4E0, 0x6BF0, 0xD9E3, + 0x6BF2, 0xD9E4, 0x6BF3, 0xD9E5, 0x6BF7, 0xDE41, 0x6BF8, 0xDE42, 0x6BF9, 0xDE40, 0x6BFB, 0xDDFD, 0x6BFC, 0xDDFE, 0x6BFD, 0xB7B7, + 0x6BFE, 0xE26B, 0x6BFF, 0xE5F7, 0x6C00, 0xE5F6, 0x6C01, 0xE5F5, 0x6C02, 0xE5F8, 0x6C03, 0xE9E7, 0x6C04, 0xE9E6, 0x6C05, 0xBEFB, + 0x6C06, 0xE9E8, 0x6C08, 0xC0D6, 0x6C09, 0xED4D, 0x6C0B, 0xEFEA, 0x6C0C, 0xF25B, 0x6C0D, 0xF6E7, 0x6C0F, 0xA4F3, 0x6C10, 0xA5C2, + 0x6C11, 0xA5C1, 0x6C13, 0xAA5D, 0x6C14, 0xC961, 0x6C15, 0xC97E, 0x6C16, 0xA6BB, 0x6C18, 0xC9F7, 0x6C19, 0xCB49, 0x6C1A, 0xCB4A, + 0x6C1B, 0xAA5E, 0x6C1D, 0xCCED, 0x6C1F, 0xAC74, 0x6C20, 0xCF6B, 0x6C21, 0xCF6C, 0x6C23, 0xAEF0, 0x6C24, 0xAEF4, 0x6C25, 0xD244, + 0x6C26, 0xAEF3, 0x6C27, 0xAEF1, 0x6C28, 0xAEF2, 0x6C2A, 0xD5DF, 0x6C2B, 0xB242, 0x6C2C, 0xB4E3, 0x6C2E, 0xB4E1, 0x6C2F, 0xB4E2, + 0x6C30, 0xD9E6, 0x6C33, 0xBA72, 0x6C34, 0xA4F4, 0x6C36, 0xC9A1, 0x6C38, 0xA5C3, 0x6C3B, 0xC9A4, 0x6C3E, 0xA5C6, 0x6C3F, 0xC9A3, + 0x6C40, 0xA5C5, 0x6C41, 0xA5C4, 0x6C42, 0xA844, 0x6C43, 0xC9A2, 0x6C46, 0xC9F8, 0x6C4A, 0xC9FC, 0x6C4B, 0xC9FE, 0x6C4C, 0xCA40, + 0x6C4D, 0xA6C5, 0x6C4E, 0xA6C6, 0x6C4F, 0xC9FB, 0x6C50, 0xA6C1, 0x6C52, 0xC9F9, 0x6C54, 0xC9FD, 0x6C55, 0xA6C2, 0x6C57, 0xA6BD, + 0x6C59, 0xA6BE, 0x6C5B, 0xA6C4, 0x6C5C, 0xC9FA, 0x6C5D, 0xA6BC, 0x6C5E, 0xA845, 0x6C5F, 0xA6BF, 0x6C60, 0xA6C0, 0x6C61, 0xA6C3, + 0x6C65, 0xCB5B, 0x6C66, 0xCB59, 0x6C67, 0xCB4C, 0x6C68, 0xA851, 0x6C69, 0xCB53, 0x6C6A, 0xA84C, 0x6C6B, 0xCB4D, 0x6C6D, 0xCB55, + 0x6C6F, 0xCB52, 0x6C70, 0xA84F, 0x6C71, 0xCB51, 0x6C72, 0xA856, 0x6C73, 0xCB5A, 0x6C74, 0xA858, 0x6C76, 0xA85A, 0x6C78, 0xCB4B, + 0x6C7A, 0xA84D, 0x6C7B, 0xCB5C, 0x6C7D, 0xA854, 0x6C7E, 0xA857, 0x6C80, 0xCD45, 0x6C81, 0xA847, 0x6C82, 0xA85E, 0x6C83, 0xA855, + 0x6C84, 0xCB4E, 0x6C85, 0xA84A, 0x6C86, 0xA859, 0x6C87, 0xCB56, 0x6C88, 0xA848, 0x6C89, 0xA849, 0x6C8A, 0xCD43, 0x6C8B, 0xCB4F, + 0x6C8C, 0xA850, 0x6C8D, 0xA85B, 0x6C8E, 0xCB5D, 0x6C8F, 0xCB50, 0x6C90, 0xA84E, 0x6C92, 0xA853, 0x6C93, 0xCCEE, 0x6C94, 0xA85C, + 0x6C95, 0xCB57, 0x6C96, 0xA852, 0x6C98, 0xA85D, 0x6C99, 0xA846, 0x6C9A, 0xCB54, 0x6C9B, 0xA84B, 0x6C9C, 0xCB58, 0x6C9D, 0xCD44, + 0x6CAB, 0xAA6A, 0x6CAC, 0xAA7A, 0x6CAD, 0xCCF5, 0x6CAE, 0xAA71, 0x6CB0, 0xCD4B, 0x6CB1, 0xAA62, 0x6CB3, 0xAA65, 0x6CB4, 0xCD42, + 0x6CB6, 0xCCF3, 0x6CB7, 0xCCF7, 0x6CB8, 0xAA6D, 0x6CB9, 0xAA6F, 0x6CBA, 0xCCFA, 0x6CBB, 0xAA76, 0x6CBC, 0xAA68, 0x6CBD, 0xAA66, + 0x6CBE, 0xAA67, 0x6CBF, 0xAA75, 0x6CC0, 0xCD47, 0x6CC1, 0xAA70, 0x6CC2, 0xCCF9, 0x6CC3, 0xCCFB, 0x6CC4, 0xAA6E, 0x6CC5, 0xAA73, + 0x6CC6, 0xCCFC, 0x6CC7, 0xCD4A, 0x6CC9, 0xAC75, 0x6CCA, 0xAA79, 0x6CCC, 0xAA63, 0x6CCD, 0xCD49, 0x6CCF, 0xCD4D, 0x6CD0, 0xCCF8, + 0x6CD1, 0xCD4F, 0x6CD2, 0xCD40, 0x6CD3, 0xAA6C, 0x6CD4, 0xCCF4, 0x6CD5, 0xAA6B, 0x6CD6, 0xAA7D, 0x6CD7, 0xAA72, 0x6CD9, 0xCCF2, + 0x6CDA, 0xCF75, 0x6CDB, 0xAA78, 0x6CDC, 0xAA7C, 0x6CDD, 0xCD41, 0x6CDE, 0xCD46, 0x6CE0, 0xAA7E, 0x6CE1, 0xAA77, 0x6CE2, 0xAA69, + 0x6CE3, 0xAA5F, 0x6CE5, 0xAA64, 0x6CE7, 0xCCF6, 0x6CE8, 0xAA60, 0x6CE9, 0xCD4E, 0x6CEB, 0xCCF0, 0x6CEC, 0xCCEF, 0x6CED, 0xCCFD, + 0x6CEE, 0xCCF1, 0x6CEF, 0xAA7B, 0x6CF0, 0xAEF5, 0x6CF1, 0xAA74, 0x6CF2, 0xCCFE, 0x6CF3, 0xAA61, 0x6CF5, 0xACA6, 0x6CF9, 0xCD4C, + 0x6D00, 0xCF7C, 0x6D01, 0xCFA1, 0x6D03, 0xCFA4, 0x6D04, 0xCF77, 0x6D07, 0xCFA7, 0x6D08, 0xCFAA, 0x6D09, 0xCFAC, 0x6D0A, 0xCF74, + 0x6D0B, 0xAC76, 0x6D0C, 0xAC7B, 0x6D0D, 0xD249, 0x6D0E, 0xACAD, 0x6D0F, 0xCFA5, 0x6D10, 0xCFAD, 0x6D11, 0xCF7B, 0x6D12, 0xCF73, + 0x6D16, 0xD264, 0x6D17, 0xAC7E, 0x6D18, 0xCFA2, 0x6D19, 0xCF78, 0x6D1A, 0xCF7A, 0x6D1B, 0xACA5, 0x6D1D, 0xCF7D, 0x6D1E, 0xAC7D, + 0x6D1F, 0xCF70, 0x6D20, 0xCFA8, 0x6D22, 0xCFAB, 0x6D25, 0xAC7A, 0x6D27, 0xACA8, 0x6D28, 0xCF6D, 0x6D29, 0xACAA, 0x6D2A, 0xAC78, + 0x6D2B, 0xACAE, 0x6D2C, 0xCFA9, 0x6D2D, 0xCF6F, 0x6D2E, 0xACAB, 0x6D2F, 0xD25E, 0x6D30, 0xCD48, 0x6D31, 0xAC7C, 0x6D32, 0xAC77, + 0x6D33, 0xCF76, 0x6D34, 0xCF6E, 0x6D35, 0xACAC, 0x6D36, 0xACA4, 0x6D37, 0xCFA3, 0x6D38, 0xACA9, 0x6D39, 0xACA7, 0x6D3A, 0xCF79, + 0x6D3B, 0xACA1, 0x6D3C, 0xCF71, 0x6D3D, 0xACA2, 0x6D3E, 0xACA3, 0x6D3F, 0xCF72, 0x6D40, 0xCFA6, 0x6D41, 0xAC79, 0x6D42, 0xCF7E, + 0x6D58, 0xD24C, 0x6D59, 0xAEFD, 0x6D5A, 0xAF43, 0x6D5E, 0xD255, 0x6D5F, 0xD25B, 0x6D60, 0xD257, 0x6D61, 0xD24A, 0x6D62, 0xD24D, + 0x6D63, 0xD246, 0x6D64, 0xD247, 0x6D65, 0xAF4A, 0x6D66, 0xAEFA, 0x6D67, 0xD256, 0x6D68, 0xD25F, 0x6D69, 0xAF45, 0x6D6A, 0xAEF6, + 0x6D6C, 0xAF40, 0x6D6D, 0xD24E, 0x6D6E, 0xAF42, 0x6D6F, 0xD24F, 0x6D70, 0xD259, 0x6D74, 0xAF44, 0x6D75, 0xD268, 0x6D76, 0xD248, + 0x6D77, 0xAEFC, 0x6D78, 0xAEFB, 0x6D79, 0xAF48, 0x6D7A, 0xD245, 0x6D7B, 0xD266, 0x6D7C, 0xD25A, 0x6D7D, 0xD267, 0x6D7E, 0xD261, + 0x6D7F, 0xD253, 0x6D80, 0xD262, 0x6D82, 0xD25C, 0x6D83, 0xD265, 0x6D84, 0xD263, 0x6D85, 0xAF49, 0x6D86, 0xD254, 0x6D87, 0xAEF9, + 0x6D88, 0xAEF8, 0x6D89, 0xAF41, 0x6D8A, 0xAF47, 0x6D8B, 0xD260, 0x6D8C, 0xAF46, 0x6D8D, 0xD251, 0x6D8E, 0xB243, 0x6D90, 0xD269, + 0x6D91, 0xD250, 0x6D92, 0xD24B, 0x6D93, 0xAEFE, 0x6D94, 0xAF4B, 0x6D95, 0xAEF7, 0x6D97, 0xD258, 0x6D98, 0xD25D, 0x6DAA, 0xB265, + 0x6DAB, 0xD5E1, 0x6DAC, 0xD5E5, 0x6DAE, 0xB252, 0x6DAF, 0xB250, 0x6DB2, 0xB247, 0x6DB3, 0xD5E3, 0x6DB4, 0xD5E2, 0x6DB5, 0xB25B, + 0x6DB7, 0xD5E8, 0x6DB8, 0xB255, 0x6DBA, 0xD5FA, 0x6DBB, 0xD647, 0x6DBC, 0xB244, 0x6DBD, 0xD5F7, 0x6DBE, 0xD5F0, 0x6DBF, 0xB267, + 0x6DC0, 0xD5E0, 0x6DC2, 0xD5FC, 0x6DC4, 0xB264, 0x6DC5, 0xB258, 0x6DC6, 0xB263, 0x6DC7, 0xB24E, 0x6DC8, 0xD5EC, 0x6DC9, 0xD5FE, + 0x6DCA, 0xD5F6, 0x6DCB, 0xB24F, 0x6DCC, 0xB249, 0x6DCD, 0xD645, 0x6DCF, 0xD5FD, 0x6DD0, 0xD640, 0x6DD1, 0xB251, 0x6DD2, 0xB259, + 0x6DD3, 0xD642, 0x6DD4, 0xD5EA, 0x6DD5, 0xD5FB, 0x6DD6, 0xD5EF, 0x6DD7, 0xD644, 0x6DD8, 0xB25E, 0x6DD9, 0xB246, 0x6DDA, 0xB25C, + 0x6DDB, 0xD5F4, 0x6DDC, 0xD5F2, 0x6DDD, 0xD5F3, 0x6DDE, 0xB253, 0x6DDF, 0xD5EE, 0x6DE0, 0xD5ED, 0x6DE1, 0xB248, 0x6DE2, 0xD5E7, + 0x6DE3, 0xD646, 0x6DE4, 0xB24A, 0x6DE5, 0xD5F1, 0x6DE6, 0xB268, 0x6DE8, 0xB262, 0x6DE9, 0xD5E6, 0x6DEA, 0xB25F, 0x6DEB, 0xB25D, + 0x6DEC, 0xB266, 0x6DED, 0xD5F8, 0x6DEE, 0xB261, 0x6DEF, 0xD252, 0x6DF0, 0xD5F9, 0x6DF1, 0xB260, 0x6DF2, 0xD641, 0x6DF3, 0xB245, + 0x6DF4, 0xD5F5, 0x6DF5, 0xB257, 0x6DF6, 0xD5E9, 0x6DF7, 0xB256, 0x6DF9, 0xB254, 0x6DFA, 0xB24C, 0x6DFB, 0xB24B, 0x6DFC, 0xD9E7, + 0x6DFD, 0xD643, 0x6E00, 0xD5EB, 0x6E03, 0xD9FC, 0x6E05, 0xB24D, 0x6E19, 0xB541, 0x6E1A, 0xB25A, 0x6E1B, 0xB4EE, 0x6E1C, 0xD9F6, + 0x6E1D, 0xB4FC, 0x6E1F, 0xD9EA, 0x6E20, 0xB4EB, 0x6E21, 0xB4E7, 0x6E22, 0xDA49, 0x6E23, 0xB4ED, 0x6E24, 0xB4F1, 0x6E25, 0xB4EC, + 0x6E26, 0xB4F5, 0x6E27, 0xDA4D, 0x6E28, 0xDA44, 0x6E2B, 0xD9F1, 0x6E2C, 0xB4FA, 0x6E2D, 0xB4F4, 0x6E2E, 0xD9FD, 0x6E2F, 0xB4E4, + 0x6E30, 0xDA4A, 0x6E31, 0xDA43, 0x6E32, 0xB4E8, 0x6E33, 0xD9F7, 0x6E34, 0xB4F7, 0x6E35, 0xDA55, 0x6E36, 0xDA56, 0x6E38, 0xB4E5, + 0x6E39, 0xDA48, 0x6E3A, 0xB4F9, 0x6E3B, 0xD9FB, 0x6E3C, 0xD9ED, 0x6E3D, 0xD9EE, 0x6E3E, 0xB4FD, 0x6E3F, 0xD9F2, 0x6E40, 0xD9F9, + 0x6E41, 0xD9F3, 0x6E43, 0xB4FB, 0x6E44, 0xB544, 0x6E45, 0xD9EF, 0x6E46, 0xD9E8, 0x6E47, 0xD9E9, 0x6E49, 0xD9EB, 0x6E4A, 0xB4EA, + 0x6E4B, 0xD9F8, 0x6E4D, 0xB4F8, 0x6E4E, 0xB542, 0x6E51, 0xD9FA, 0x6E52, 0xDA53, 0x6E53, 0xDA4B, 0x6E54, 0xB4E6, 0x6E55, 0xDA51, + 0x6E56, 0xB4F2, 0x6E58, 0xB4F0, 0x6E5A, 0xDA57, 0x6E5B, 0xB4EF, 0x6E5C, 0xDA41, 0x6E5D, 0xD9F4, 0x6E5E, 0xD9FE, 0x6E5F, 0xB547, + 0x6E60, 0xDA45, 0x6E61, 0xDA42, 0x6E62, 0xD9F0, 0x6E63, 0xB543, 0x6E64, 0xDA4F, 0x6E65, 0xDA4C, 0x6E66, 0xDA54, 0x6E67, 0xB4E9, + 0x6E68, 0xDA40, 0x6E69, 0xB546, 0x6E6B, 0xDA47, 0x6E6E, 0xB4F3, 0x6E6F, 0xB4F6, 0x6E71, 0xDA46, 0x6E72, 0xB545, 0x6E73, 0xD9F5, + 0x6E74, 0xD5E4, 0x6E77, 0xDA50, 0x6E78, 0xDA4E, 0x6E79, 0xDA52, 0x6E88, 0xD9EC, 0x6E89, 0xB540, 0x6E8D, 0xDE61, 0x6E8E, 0xDE60, + 0x6E8F, 0xDE46, 0x6E90, 0xB7BD, 0x6E92, 0xDE5F, 0x6E93, 0xDE49, 0x6E94, 0xDE4A, 0x6E96, 0xB7C7, 0x6E97, 0xDE68, 0x6E98, 0xB7C2, + 0x6E99, 0xDE5E, 0x6E9B, 0xDE43, 0x6E9C, 0xB7C8, 0x6E9D, 0xB7BE, 0x6E9E, 0xDE52, 0x6E9F, 0xDE48, 0x6EA0, 0xDE4B, 0x6EA1, 0xDE63, + 0x6EA2, 0xB7B8, 0x6EA3, 0xDE6A, 0x6EA4, 0xDE62, 0x6EA5, 0xB7C1, 0x6EA6, 0xDE57, 0x6EA7, 0xB7CC, 0x6EAA, 0xB7CB, 0x6EAB, 0xB7C5, + 0x6EAE, 0xDE69, 0x6EAF, 0xB7B9, 0x6EB0, 0xDE55, 0x6EB1, 0xDE4C, 0x6EB2, 0xDE59, 0x6EB3, 0xDE65, 0x6EB4, 0xB7CD, 0x6EB6, 0xB7BB, + 0x6EB7, 0xDE54, 0x6EB9, 0xDE4D, 0x6EBA, 0xB7C4, 0x6EBC, 0xB7C3, 0x6EBD, 0xDE50, 0x6EBE, 0xDE5A, 0x6EBF, 0xDE64, 0x6EC0, 0xDE47, + 0x6EC1, 0xDE51, 0x6EC2, 0xB7BC, 0x6EC3, 0xDE5B, 0x6EC4, 0xB7C9, 0x6EC5, 0xB7C0, 0x6EC6, 0xDE4E, 0x6EC7, 0xB7BF, 0x6EC8, 0xDE45, + 0x6EC9, 0xDE53, 0x6ECA, 0xDE67, 0x6ECB, 0xB4FE, 0x6ECC, 0xBAB0, 0x6ECD, 0xDE56, 0x6ECE, 0xE26C, 0x6ECF, 0xDE58, 0x6ED0, 0xDE66, + 0x6ED1, 0xB7C6, 0x6ED2, 0xDE4F, 0x6ED3, 0xB7BA, 0x6ED4, 0xB7CA, 0x6ED5, 0xBCF0, 0x6ED6, 0xDE44, 0x6ED8, 0xDE5D, 0x6EDC, 0xDE5C, + 0x6EEB, 0xE2AA, 0x6EEC, 0xBAAD, 0x6EED, 0xE27D, 0x6EEE, 0xE2A4, 0x6EEF, 0xBAA2, 0x6EF1, 0xE26E, 0x6EF2, 0xBAAF, 0x6EF4, 0xBA77, + 0x6EF5, 0xE26D, 0x6EF6, 0xE2B0, 0x6EF7, 0xBAB1, 0x6EF8, 0xE271, 0x6EF9, 0xE2A3, 0x6EFB, 0xE273, 0x6EFC, 0xE2B3, 0x6EFD, 0xE2AF, + 0x6EFE, 0xBA75, 0x6EFF, 0xBAA1, 0x6F00, 0xE653, 0x6F01, 0xBAAE, 0x6F02, 0xBA7D, 0x6F03, 0xE26F, 0x6F05, 0xE2AE, 0x6F06, 0xBAA3, + 0x6F07, 0xE2AB, 0x6F08, 0xE2B8, 0x6F09, 0xE275, 0x6F0A, 0xE27E, 0x6F0D, 0xE2B6, 0x6F0E, 0xE2AC, 0x6F0F, 0xBA7C, 0x6F12, 0xE27C, + 0x6F13, 0xBA76, 0x6F14, 0xBA74, 0x6F15, 0xBAA8, 0x6F18, 0xE27A, 0x6F19, 0xE277, 0x6F1A, 0xE278, 0x6F1C, 0xE2B2, 0x6F1E, 0xE2B7, + 0x6F1F, 0xE2B5, 0x6F20, 0xBA7A, 0x6F21, 0xE2B9, 0x6F22, 0xBA7E, 0x6F23, 0xBAA7, 0x6F25, 0xE270, 0x6F26, 0xE5FA, 0x6F27, 0xE279, + 0x6F29, 0xBA78, 0x6F2A, 0xBAAC, 0x6F2B, 0xBAA9, 0x6F2C, 0xBA7B, 0x6F2D, 0xE2A5, 0x6F2E, 0xE274, 0x6F2F, 0xBAAA, 0x6F30, 0xE2A7, + 0x6F31, 0xBAA4, 0x6F32, 0xBAA6, 0x6F33, 0xBA73, 0x6F35, 0xE2A9, 0x6F36, 0xE2A1, 0x6F37, 0xE272, 0x6F38, 0xBAA5, 0x6F39, 0xE2B1, + 0x6F3A, 0xE2B4, 0x6F3B, 0xE27B, 0x6F3C, 0xE2A8, 0x6F3E, 0xBA79, 0x6F3F, 0xBCDF, 0x6F40, 0xE2A6, 0x6F41, 0xE5F9, 0x6F43, 0xE2AD, + 0x6F4E, 0xE276, 0x6F4F, 0xE644, 0x6F50, 0xE64E, 0x6F51, 0xBCE2, 0x6F52, 0xE64D, 0x6F53, 0xE659, 0x6F54, 0xBCE4, 0x6F55, 0xE64B, + 0x6F57, 0xE64F, 0x6F58, 0xBCEF, 0x6F5A, 0xE646, 0x6F5B, 0xBCE7, 0x6F5D, 0xE652, 0x6F5E, 0xE9F0, 0x6F5F, 0xBCF3, 0x6F60, 0xBCF2, + 0x6F61, 0xE654, 0x6F62, 0xE643, 0x6F63, 0xE65E, 0x6F64, 0xBCED, 0x6F66, 0xBCE3, 0x6F67, 0xE657, 0x6F69, 0xE65B, 0x6F6A, 0xE660, + 0x6F6B, 0xE655, 0x6F6C, 0xE649, 0x6F6D, 0xBCE6, 0x6F6E, 0xBCE9, 0x6F6F, 0xBCF1, 0x6F70, 0xBCEC, 0x6F72, 0xE64C, 0x6F73, 0xE2A2, + 0x6F76, 0xE648, 0x6F77, 0xE65F, 0x6F78, 0xBCE8, 0x6F7A, 0xBCEB, 0x6F7B, 0xE661, 0x6F7C, 0xBCE0, 0x6F7D, 0xE656, 0x6F7E, 0xE5FB, + 0x6F7F, 0xE65C, 0x6F80, 0xC0DF, 0x6F82, 0xE64A, 0x6F84, 0xBCE1, 0x6F85, 0xE645, 0x6F86, 0xBCE5, 0x6F87, 0xE5FC, 0x6F88, 0xBAAB, + 0x6F89, 0xE641, 0x6F8B, 0xE65A, 0x6F8C, 0xE642, 0x6F8D, 0xE640, 0x6F8E, 0xBCEA, 0x6F90, 0xE658, 0x6F92, 0xE5FE, 0x6F93, 0xE651, + 0x6F94, 0xE650, 0x6F95, 0xE65D, 0x6F96, 0xE647, 0x6F97, 0xBCEE, 0x6F9E, 0xE9F3, 0x6FA0, 0xBF49, 0x6FA1, 0xBEFE, 0x6FA2, 0xEA40, + 0x6FA3, 0xE9EB, 0x6FA4, 0xBF41, 0x6FA5, 0xE9F7, 0x6FA6, 0xBF48, 0x6FA7, 0xBF43, 0x6FA8, 0xE9F5, 0x6FA9, 0xED4F, 0x6FAA, 0xE9FB, + 0x6FAB, 0xEA42, 0x6FAC, 0xE9FA, 0x6FAD, 0xE9E9, 0x6FAE, 0xE9F8, 0x6FAF, 0xEA44, 0x6FB0, 0xEA46, 0x6FB1, 0xBEFD, 0x6FB2, 0xEA45, + 0x6FB3, 0xBF44, 0x6FB4, 0xBF4A, 0x6FB6, 0xBF47, 0x6FB8, 0xE9FE, 0x6FB9, 0xBF46, 0x6FBA, 0xE9F9, 0x6FBC, 0xE9ED, 0x6FBD, 0xE9F2, + 0x6FBF, 0xE9FD, 0x6FC0, 0xBF45, 0x6FC1, 0xBF42, 0x6FC2, 0xBEFC, 0x6FC3, 0xBF40, 0x6FC4, 0xE9F1, 0x6FC6, 0xE5FD, 0x6FC7, 0xE9EC, + 0x6FC8, 0xE9EF, 0x6FC9, 0xEA41, 0x6FCA, 0xE9F4, 0x6FCB, 0xE9EA, 0x6FCC, 0xED4E, 0x6FCD, 0xEA43, 0x6FCE, 0xE9EE, 0x6FCF, 0xE9FC, + 0x6FD4, 0xED51, 0x6FD5, 0xC0E3, 0x6FD8, 0xC0D7, 0x6FDB, 0xC0DB, 0x6FDC, 0xED53, 0x6FDD, 0xED59, 0x6FDE, 0xED57, 0x6FDF, 0xC0D9, + 0x6FE0, 0xC0DA, 0x6FE1, 0xC0E1, 0x6FE2, 0xED5A, 0x6FE3, 0xED52, 0x6FE4, 0xC0DC, 0x6FE6, 0xED56, 0x6FE7, 0xED55, 0x6FE8, 0xED5B, + 0x6FE9, 0xC0E2, 0x6FEB, 0xC0DD, 0x6FEC, 0xC0E0, 0x6FED, 0xED54, 0x6FEE, 0xC0E4, 0x6FEF, 0xC0DE, 0x6FF0, 0xC0E5, 0x6FF1, 0xC0D8, + 0x6FF2, 0xED58, 0x6FF4, 0xED50, 0x6FF7, 0xEFF7, 0x6FFA, 0xC271, 0x6FFB, 0xEFF4, 0x6FFC, 0xEFF6, 0x6FFE, 0xC26F, 0x6FFF, 0xEFF2, + 0x7000, 0xEFF3, 0x7001, 0xEFEE, 0x7004, 0xE9F6, 0x7005, 0xEFEF, 0x7006, 0xC270, 0x7007, 0xEFEB, 0x7009, 0xC26D, 0x700A, 0xEFF8, + 0x700B, 0xC26E, 0x700C, 0xEFEC, 0x700D, 0xEFED, 0x700E, 0xEFF1, 0x700F, 0xC273, 0x7011, 0xC272, 0x7014, 0xEFF0, 0x7015, 0xC378, + 0x7016, 0xF25F, 0x7017, 0xF265, 0x7018, 0xC379, 0x7019, 0xF25C, 0x701A, 0xC376, 0x701B, 0xC373, 0x701C, 0xF267, 0x701D, 0xC377, + 0x701F, 0xC374, 0x7020, 0xF25E, 0x7021, 0xF261, 0x7022, 0xF262, 0x7023, 0xF263, 0x7024, 0xF266, 0x7026, 0xEFF5, 0x7027, 0xF25D, + 0x7028, 0xC375, 0x7029, 0xF264, 0x702A, 0xF268, 0x702B, 0xF260, 0x702F, 0xF45D, 0x7030, 0xC46A, 0x7031, 0xF460, 0x7032, 0xC46B, + 0x7033, 0xF468, 0x7034, 0xF45F, 0x7035, 0xF45C, 0x7037, 0xF45E, 0x7038, 0xF462, 0x7039, 0xF465, 0x703A, 0xF464, 0x703B, 0xF467, + 0x703C, 0xF45B, 0x703E, 0xC469, 0x703F, 0xF463, 0x7040, 0xF466, 0x7041, 0xF469, 0x7042, 0xF461, 0x7043, 0xF5D3, 0x7044, 0xF5D4, + 0x7045, 0xF5D8, 0x7046, 0xF5D9, 0x7048, 0xF5D6, 0x7049, 0xF5D7, 0x704A, 0xF5D5, 0x704C, 0xC4E9, 0x7051, 0xC578, 0x7052, 0xF6EB, + 0x7055, 0xF6E8, 0x7056, 0xF6E9, 0x7057, 0xF6EA, 0x7058, 0xC579, 0x705A, 0xF7E5, 0x705B, 0xF7E4, 0x705D, 0xF8AF, 0x705E, 0xC5F4, + 0x705F, 0xF8AD, 0x7060, 0xF8B0, 0x7061, 0xF8AE, 0x7062, 0xF8F5, 0x7063, 0xC657, 0x7064, 0xC665, 0x7065, 0xF9A3, 0x7066, 0xF96C, + 0x7068, 0xF9A2, 0x7069, 0xF9D0, 0x706A, 0xF9D1, 0x706B, 0xA4F5, 0x7070, 0xA6C7, 0x7071, 0xCA41, 0x7074, 0xCB5E, 0x7076, 0xA85F, + 0x7078, 0xA862, 0x707A, 0xCB5F, 0x707C, 0xA860, 0x707D, 0xA861, 0x7082, 0xCD58, 0x7083, 0xCD5A, 0x7084, 0xCD55, 0x7085, 0xCD52, + 0x7086, 0xCD54, 0x708A, 0xAAA4, 0x708E, 0xAAA2, 0x7091, 0xCD56, 0x7092, 0xAAA3, 0x7093, 0xCD53, 0x7094, 0xCD50, 0x7095, 0xAAA1, + 0x7096, 0xCD57, 0x7098, 0xCD51, 0x7099, 0xAAA5, 0x709A, 0xCD59, 0x709F, 0xCFAF, 0x70A1, 0xCFB3, 0x70A4, 0xACB7, 0x70A9, 0xCFB6, + 0x70AB, 0xACAF, 0x70AC, 0xACB2, 0x70AD, 0xACB4, 0x70AE, 0xACB6, 0x70AF, 0xACB3, 0x70B0, 0xCFB2, 0x70B1, 0xCFB1, 0x70B3, 0xACB1, + 0x70B4, 0xCFB4, 0x70B5, 0xCFB5, 0x70B7, 0xCFAE, 0x70B8, 0xACB5, 0x70BA, 0xACB0, 0x70BE, 0xCFB0, 0x70C5, 0xD277, 0x70C6, 0xD278, + 0x70C7, 0xD279, 0x70C8, 0xAF50, 0x70CA, 0xAF4C, 0x70CB, 0xD26E, 0x70CD, 0xD276, 0x70CE, 0xD27B, 0x70CF, 0xAF51, 0x70D1, 0xD26C, + 0x70D2, 0xD272, 0x70D3, 0xD26B, 0x70D4, 0xD275, 0x70D7, 0xD271, 0x70D8, 0xAF4D, 0x70D9, 0xAF4F, 0x70DA, 0xD27A, 0x70DC, 0xD26A, + 0x70DD, 0xD26D, 0x70DE, 0xD273, 0x70E0, 0xD274, 0x70E1, 0xD27C, 0x70E2, 0xD270, 0x70E4, 0xAF4E, 0x70EF, 0xB26D, 0x70F0, 0xD64E, + 0x70F3, 0xD650, 0x70F4, 0xD64C, 0x70F6, 0xD658, 0x70F7, 0xD64A, 0x70F8, 0xD657, 0x70F9, 0xB269, 0x70FA, 0xD648, 0x70FB, 0xDA5B, + 0x70FC, 0xD652, 0x70FD, 0xB26C, 0x70FF, 0xD653, 0x7100, 0xD656, 0x7102, 0xD65A, 0x7104, 0xD64F, 0x7106, 0xD654, 0x7109, 0xB26A, + 0x710A, 0xB26B, 0x710B, 0xD659, 0x710C, 0xD64D, 0x710D, 0xD649, 0x710E, 0xD65B, 0x7110, 0xD651, 0x7113, 0xD655, 0x7117, 0xD64B, + 0x7119, 0xB548, 0x711A, 0xB549, 0x711B, 0xDA65, 0x711C, 0xB54F, 0x711E, 0xDA59, 0x711F, 0xDA62, 0x7120, 0xDA58, 0x7121, 0xB54C, + 0x7122, 0xDA60, 0x7123, 0xDA5E, 0x7125, 0xDA5F, 0x7126, 0xB54A, 0x7128, 0xDA63, 0x712E, 0xDA5C, 0x712F, 0xDA5A, 0x7130, 0xB54B, + 0x7131, 0xDA5D, 0x7132, 0xDA61, 0x7136, 0xB54D, 0x713A, 0xDA64, 0x7141, 0xDE70, 0x7142, 0xDE77, 0x7143, 0xDE79, 0x7144, 0xDEA1, + 0x7146, 0xB7DA, 0x7147, 0xDE6B, 0x7149, 0xB7D2, 0x714B, 0xDE7A, 0x714C, 0xB7D7, 0x714D, 0xDEA2, 0x714E, 0xB7CE, 0x7150, 0xDE7D, + 0x7152, 0xDE6D, 0x7153, 0xDE7E, 0x7154, 0xDE6C, 0x7156, 0xB7DC, 0x7158, 0xDE78, 0x7159, 0xB7CF, 0x715A, 0xDEA3, 0x715C, 0xB7D4, + 0x715D, 0xDE71, 0x715E, 0xB7D9, 0x715F, 0xDE7C, 0x7160, 0xDE6F, 0x7161, 0xDE76, 0x7162, 0xDE72, 0x7163, 0xDE6E, 0x7164, 0xB7D1, + 0x7165, 0xB7D8, 0x7166, 0xB7D6, 0x7167, 0xB7D3, 0x7168, 0xB7DB, 0x7169, 0xB7D0, 0x716A, 0xDE75, 0x716C, 0xB7D5, 0x716E, 0xB54E, + 0x7170, 0xDE7B, 0x7172, 0xDE73, 0x7178, 0xDE74, 0x717B, 0xE2C1, 0x717D, 0xBAB4, 0x7180, 0xE2BD, 0x7181, 0xE2C3, 0x7182, 0xE2BF, + 0x7184, 0xBAB6, 0x7185, 0xE2BE, 0x7186, 0xE2C2, 0x7187, 0xE2BA, 0x7189, 0xE2BC, 0x718A, 0xBAB5, 0x718F, 0xE2C0, 0x7190, 0xE2BB, + 0x7192, 0xBAB7, 0x7194, 0xBAB2, 0x7197, 0xE2C4, 0x7199, 0xBAB3, 0x719A, 0xE667, 0x719B, 0xE664, 0x719C, 0xE670, 0x719D, 0xE66A, + 0x719E, 0xE66C, 0x719F, 0xBCF4, 0x71A0, 0xE666, 0x71A1, 0xE66E, 0x71A4, 0xE66D, 0x71A5, 0xE66B, 0x71A7, 0xE671, 0x71A8, 0xBCF7, + 0x71A9, 0xE668, 0x71AA, 0xE66F, 0x71AC, 0xBCF5, 0x71AF, 0xE663, 0x71B0, 0xE665, 0x71B1, 0xBCF6, 0x71B2, 0xE662, 0x71B3, 0xE672, + 0x71B5, 0xE669, 0x71B8, 0xEA4A, 0x71B9, 0xBF51, 0x71BC, 0xEA55, 0x71BD, 0xEA53, 0x71BE, 0xBF4B, 0x71BF, 0xEA49, 0x71C0, 0xEA4C, + 0x71C1, 0xEA4D, 0x71C2, 0xEA48, 0x71C3, 0xBF55, 0x71C4, 0xBF56, 0x71C5, 0xEA47, 0x71C6, 0xEA56, 0x71C7, 0xEA51, 0x71C8, 0xBF4F, + 0x71C9, 0xBF4C, 0x71CA, 0xEA50, 0x71CB, 0xEA4E, 0x71CE, 0xBF52, 0x71CF, 0xEA52, 0x71D0, 0xBF4D, 0x71D2, 0xBF4E, 0x71D4, 0xEA4F, + 0x71D5, 0xBF50, 0x71D6, 0xEA4B, 0x71D8, 0xEA54, 0x71D9, 0xBF53, 0x71DA, 0xEA57, 0x71DB, 0xEA58, 0x71DC, 0xBF54, 0x71DF, 0xC0E7, + 0x71E0, 0xC0EE, 0x71E1, 0xED5C, 0x71E2, 0xED62, 0x71E4, 0xED60, 0x71E5, 0xC0EA, 0x71E6, 0xC0E9, 0x71E7, 0xC0E6, 0x71E8, 0xED5E, + 0x71EC, 0xC0EC, 0x71ED, 0xC0EB, 0x71EE, 0xC0E8, 0x71F0, 0xED61, 0x71F1, 0xED5D, 0x71F2, 0xED5F, 0x71F4, 0xC0ED, 0x71F8, 0xC277, + 0x71F9, 0xEFFB, 0x71FB, 0xC274, 0x71FC, 0xC275, 0x71FD, 0xEFFD, 0x71FE, 0xC276, 0x71FF, 0xEFFA, 0x7201, 0xEFF9, 0x7202, 0xF26C, + 0x7203, 0xEFFC, 0x7205, 0xF26D, 0x7206, 0xC37A, 0x7207, 0xF26B, 0x720A, 0xF26A, 0x720C, 0xF269, 0x720D, 0xC37B, 0x7210, 0xC46C, + 0x7213, 0xF46A, 0x7214, 0xF46B, 0x7219, 0xF5DC, 0x721A, 0xF5DB, 0x721B, 0xC4EA, 0x721D, 0xF5DA, 0x721E, 0xF6EC, 0x721F, 0xF6ED, + 0x7222, 0xF7E6, 0x7223, 0xF8B1, 0x7226, 0xF8F6, 0x7227, 0xF9BC, 0x7228, 0xC679, 0x7229, 0xF9C6, 0x722A, 0xA4F6, 0x722C, 0xAAA6, + 0x722D, 0xAAA7, 0x7230, 0xACB8, 0x7235, 0xC0EF, 0x7236, 0xA4F7, 0x7238, 0xAAA8, 0x7239, 0xAF52, 0x723A, 0xB7DD, 0x723B, 0xA4F8, + 0x723D, 0xB26E, 0x723E, 0xBAB8, 0x723F, 0xC962, 0x7241, 0xCFB7, 0x7242, 0xD27D, 0x7244, 0xE2C5, 0x7246, 0xC0F0, 0x7247, 0xA4F9, + 0x7248, 0xAAA9, 0x7249, 0xCFB8, 0x724A, 0xCFB9, 0x724B, 0xDA66, 0x724C, 0xB550, 0x724F, 0xDEA4, 0x7252, 0xB7DE, 0x7253, 0xE2C6, + 0x7256, 0xBCF8, 0x7258, 0xC37C, 0x7259, 0xA4FA, 0x725A, 0xDA67, 0x725B, 0xA4FB, 0x725D, 0xA6C9, 0x725E, 0xCA42, 0x725F, 0xA6C8, + 0x7260, 0xA865, 0x7261, 0xA864, 0x7262, 0xA863, 0x7263, 0xCB60, 0x7267, 0xAAAA, 0x7269, 0xAAAB, 0x726A, 0xCD5B, 0x726C, 0xCFBA, + 0x726E, 0xCFBD, 0x726F, 0xACBA, 0x7270, 0xCFBB, 0x7272, 0xACB9, 0x7273, 0xCFBC, 0x7274, 0xACBB, 0x7276, 0xD2A2, 0x7277, 0xD2A1, + 0x7278, 0xD27E, 0x7279, 0xAF53, 0x727B, 0xD65D, 0x727C, 0xD65E, 0x727D, 0xB26F, 0x727E, 0xD65C, 0x727F, 0xD65F, 0x7280, 0xB552, + 0x7281, 0xB270, 0x7284, 0xB551, 0x7285, 0xDA6B, 0x7286, 0xDA6A, 0x7288, 0xDA68, 0x7289, 0xDA69, 0x728B, 0xDA6C, 0x728C, 0xDEA6, + 0x728D, 0xDEA5, 0x728E, 0xDEA9, 0x7290, 0xDEA8, 0x7291, 0xDEA7, 0x7292, 0xBAB9, 0x7293, 0xE2C9, 0x7295, 0xE2C8, 0x7296, 0xBABA, + 0x7297, 0xE2C7, 0x7298, 0xE673, 0x729A, 0xE674, 0x729B, 0xBCF9, 0x729D, 0xEA59, 0x729E, 0xEA5A, 0x72A1, 0xF272, 0x72A2, 0xC37D, + 0x72A3, 0xF271, 0x72A4, 0xF270, 0x72A5, 0xF26E, 0x72A6, 0xF26F, 0x72A7, 0xC4EB, 0x72A8, 0xF46C, 0x72A9, 0xF6EE, 0x72AA, 0xF8F7, + 0x72AC, 0xA4FC, 0x72AE, 0xC9A5, 0x72AF, 0xA5C7, 0x72B0, 0xC9A6, 0x72B4, 0xCA43, 0x72B5, 0xCA44, 0x72BA, 0xCB66, 0x72BD, 0xCB62, + 0x72BF, 0xCB61, 0x72C0, 0xAAAC, 0x72C1, 0xCB65, 0x72C2, 0xA867, 0x72C3, 0xCB63, 0x72C4, 0xA866, 0x72C5, 0xCB67, 0x72C6, 0xCB64, + 0x72C9, 0xCD5F, 0x72CA, 0xCFBE, 0x72CB, 0xCD5D, 0x72CC, 0xCD64, 0x72CE, 0xAAAD, 0x72D0, 0xAAB0, 0x72D1, 0xCD65, 0x72D2, 0xCD61, + 0x72D4, 0xCD62, 0x72D6, 0xCD5C, 0x72D7, 0xAAAF, 0x72D8, 0xCD5E, 0x72D9, 0xAAAE, 0x72DA, 0xCD63, 0x72DC, 0xCD60, 0x72DF, 0xCFC2, + 0x72E0, 0xACBD, 0x72E1, 0xACBE, 0x72E3, 0xCFC5, 0x72E4, 0xCFBF, 0x72E6, 0xCFC4, 0x72E8, 0xCFC0, 0x72E9, 0xACBC, 0x72EA, 0xCFC3, + 0x72EB, 0xCFC1, 0x72F3, 0xD2A8, 0x72F4, 0xD2A5, 0x72F6, 0xD2A7, 0x72F7, 0xAF58, 0x72F8, 0xAF57, 0x72F9, 0xAF55, 0x72FA, 0xD2A4, + 0x72FB, 0xD2A9, 0x72FC, 0xAF54, 0x72FD, 0xAF56, 0x72FE, 0xD2A6, 0x72FF, 0xD667, 0x7300, 0xD2A3, 0x7301, 0xD2AA, 0x7307, 0xD662, + 0x7308, 0xD666, 0x730A, 0xD665, 0x730B, 0xDA6E, 0x730C, 0xDA79, 0x730F, 0xD668, 0x7311, 0xD663, 0x7312, 0xDA6D, 0x7313, 0xB274, + 0x7316, 0xB273, 0x7317, 0xD661, 0x7318, 0xD664, 0x7319, 0xB275, 0x731B, 0xB272, 0x731C, 0xB271, 0x731D, 0xD660, 0x731E, 0xD669, + 0x7322, 0xDA70, 0x7323, 0xDA77, 0x7325, 0xB554, 0x7326, 0xDA76, 0x7327, 0xDA73, 0x7329, 0xB556, 0x732D, 0xDA75, 0x7330, 0xDA6F, + 0x7331, 0xDA71, 0x7332, 0xDA74, 0x7333, 0xDA72, 0x7334, 0xB555, 0x7335, 0xDA78, 0x7336, 0xB553, 0x7337, 0xB7DF, 0x733A, 0xDEAD, + 0x733B, 0xDEAC, 0x733C, 0xDEAA, 0x733E, 0xB7E2, 0x733F, 0xB7E1, 0x7340, 0xDEAE, 0x7342, 0xDEAB, 0x7343, 0xE2CA, 0x7344, 0xBABB, + 0x7345, 0xB7E0, 0x7349, 0xDEB0, 0x734A, 0xDEAF, 0x734C, 0xE2CD, 0x734D, 0xE2CB, 0x734E, 0xBCFA, 0x7350, 0xBABC, 0x7351, 0xE2CC, + 0x7352, 0xE676, 0x7357, 0xBCFB, 0x7358, 0xE675, 0x7359, 0xE67E, 0x735A, 0xE67D, 0x735B, 0xE67B, 0x735D, 0xE67A, 0x735E, 0xE677, + 0x735F, 0xE678, 0x7360, 0xE679, 0x7361, 0xE67C, 0x7362, 0xE6A1, 0x7365, 0xEA5F, 0x7366, 0xEA5C, 0x7367, 0xEA5D, 0x7368, 0xBF57, + 0x7369, 0xEA5B, 0x736A, 0xEA61, 0x736B, 0xEA60, 0x736C, 0xEA5E, 0x736E, 0xED64, 0x736F, 0xED65, 0x7370, 0xC0F1, 0x7372, 0xC0F2, + 0x7373, 0xED63, 0x7375, 0xC279, 0x7376, 0xEFFE, 0x7377, 0xC278, 0x7378, 0xC37E, 0x737A, 0xC3A1, 0x737B, 0xC46D, 0x737C, 0xF46E, + 0x737D, 0xF46D, 0x737E, 0xF5DD, 0x737F, 0xF6EF, 0x7380, 0xC57A, 0x7381, 0xF7E8, 0x7382, 0xF7E7, 0x7383, 0xF7E9, 0x7384, 0xA5C8, + 0x7385, 0xCFC6, 0x7386, 0xAF59, 0x7387, 0xB276, 0x7388, 0xD66A, 0x7389, 0xA5C9, 0x738A, 0xC9A7, 0x738B, 0xA4FD, 0x738E, 0xCA45, + 0x7392, 0xCB6C, 0x7393, 0xCB6A, 0x7394, 0xCB6B, 0x7395, 0xCB68, 0x7396, 0xA868, 0x7397, 0xCB69, 0x739D, 0xCD6D, 0x739F, 0xAAB3, + 0x73A0, 0xCD6B, 0x73A1, 0xCD67, 0x73A2, 0xCD6A, 0x73A4, 0xCD66, 0x73A5, 0xAAB5, 0x73A6, 0xCD69, 0x73A8, 0xAAB2, 0x73A9, 0xAAB1, + 0x73AB, 0xAAB4, 0x73AC, 0xCD6C, 0x73AD, 0xCD68, 0x73B2, 0xACC2, 0x73B3, 0xACC5, 0x73B4, 0xCFCE, 0x73B5, 0xCFCD, 0x73B6, 0xCFCC, + 0x73B7, 0xACBF, 0x73B8, 0xCFD5, 0x73B9, 0xCFCB, 0x73BB, 0xACC1, 0x73BC, 0xD2AF, 0x73BE, 0xCFD2, 0x73BF, 0xCFD0, 0x73C0, 0xACC4, + 0x73C2, 0xCFC8, 0x73C3, 0xCFD3, 0x73C5, 0xCFCA, 0x73C6, 0xCFD4, 0x73C7, 0xCFD1, 0x73C8, 0xCFC9, 0x73CA, 0xACC0, 0x73CB, 0xCFD6, + 0x73CC, 0xCFC7, 0x73CD, 0xACC3, 0x73D2, 0xD2B4, 0x73D3, 0xD2AB, 0x73D4, 0xD2B6, 0x73D6, 0xD2AE, 0x73D7, 0xD2B9, 0x73D8, 0xD2BA, + 0x73D9, 0xD2AC, 0x73DA, 0xD2B8, 0x73DB, 0xD2B5, 0x73DC, 0xD2B3, 0x73DD, 0xD2B7, 0x73DE, 0xAF5F, 0x73E0, 0xAF5D, 0x73E3, 0xD2B1, + 0x73E5, 0xD2AD, 0x73E7, 0xD2B0, 0x73E8, 0xD2BB, 0x73E9, 0xD2B2, 0x73EA, 0xAF5E, 0x73EB, 0xCFCF, 0x73ED, 0xAF5A, 0x73EE, 0xAF5C, + 0x73F4, 0xD678, 0x73F5, 0xD66D, 0x73F6, 0xD66B, 0x73F8, 0xD66C, 0x73FA, 0xD673, 0x73FC, 0xD674, 0x73FD, 0xD670, 0x73FE, 0xB27B, + 0x73FF, 0xD675, 0x7400, 0xD672, 0x7401, 0xD66F, 0x7403, 0xB279, 0x7404, 0xD66E, 0x7405, 0xB277, 0x7406, 0xB27A, 0x7407, 0xD671, + 0x7408, 0xD679, 0x7409, 0xAF5B, 0x740A, 0xB278, 0x740B, 0xD677, 0x740C, 0xD676, 0x740D, 0xB27C, 0x7416, 0xDA7E, 0x741A, 0xDAA1, + 0x741B, 0xB560, 0x741D, 0xDAA7, 0x7420, 0xDAA9, 0x7421, 0xDAA2, 0x7422, 0xB55A, 0x7423, 0xDAA6, 0x7424, 0xDAA5, 0x7425, 0xB55B, + 0x7426, 0xB561, 0x7428, 0xB562, 0x7429, 0xDAA8, 0x742A, 0xB558, 0x742B, 0xDA7D, 0x742C, 0xDA7B, 0x742D, 0xDAA3, 0x742E, 0xDA7A, + 0x742F, 0xB55F, 0x7430, 0xDA7C, 0x7431, 0xDAA4, 0x7432, 0xDAAA, 0x7433, 0xB559, 0x7434, 0xB55E, 0x7435, 0xB55C, 0x7436, 0xB55D, + 0x743A, 0xB557, 0x743F, 0xB7E9, 0x7440, 0xDEB7, 0x7441, 0xB7E8, 0x7442, 0xDEBB, 0x7444, 0xDEB1, 0x7446, 0xDEBC, 0x744A, 0xDEB2, + 0x744B, 0xDEB3, 0x744D, 0xDEBD, 0x744E, 0xDEBA, 0x744F, 0xDEB8, 0x7450, 0xDEB9, 0x7451, 0xDEB5, 0x7452, 0xDEB4, 0x7454, 0xDEBE, + 0x7455, 0xB7E5, 0x7457, 0xDEB6, 0x7459, 0xB7EA, 0x745A, 0xB7E4, 0x745B, 0xB7EB, 0x745C, 0xB7EC, 0x745E, 0xB7E7, 0x745F, 0xB7E6, + 0x7462, 0xE2CE, 0x7463, 0xBABE, 0x7464, 0xBABD, 0x7467, 0xE2D3, 0x7469, 0xBCFC, 0x746A, 0xBABF, 0x746D, 0xBAC1, 0x746E, 0xE2D4, + 0x746F, 0xB7E3, 0x7470, 0xBAC0, 0x7471, 0xE2D0, 0x7472, 0xE2D2, 0x7473, 0xE2CF, 0x7475, 0xE2D1, 0x7479, 0xE6AB, 0x747C, 0xE6AA, + 0x747D, 0xE6A7, 0x747E, 0xBD40, 0x747F, 0xEA62, 0x7480, 0xBD41, 0x7481, 0xE6A6, 0x7483, 0xBCFE, 0x7485, 0xE6A8, 0x7486, 0xE6A5, + 0x7487, 0xE6A2, 0x7488, 0xE6A9, 0x7489, 0xE6A3, 0x748A, 0xE6A4, 0x748B, 0xBCFD, 0x7490, 0xED69, 0x7492, 0xEA66, 0x7494, 0xEA65, + 0x7495, 0xEA67, 0x7497, 0xED66, 0x7498, 0xBF5A, 0x749A, 0xEA63, 0x749C, 0xBF58, 0x749E, 0xBF5C, 0x749F, 0xBF5B, 0x74A0, 0xEA64, + 0x74A1, 0xEA68, 0x74A3, 0xBF59, 0x74A5, 0xED6D, 0x74A6, 0xC0F5, 0x74A7, 0xC27A, 0x74A8, 0xC0F6, 0x74A9, 0xC0F3, 0x74AA, 0xED6A, + 0x74AB, 0xED68, 0x74AD, 0xED6B, 0x74AF, 0xED6E, 0x74B0, 0xC0F4, 0x74B1, 0xED6C, 0x74B2, 0xED67, 0x74B5, 0xF042, 0x74B6, 0xF045, + 0x74B7, 0xF275, 0x74B8, 0xF040, 0x74BA, 0xF46F, 0x74BB, 0xF046, 0x74BD, 0xC3A2, 0x74BE, 0xF044, 0x74BF, 0xC27B, 0x74C0, 0xF041, + 0x74C1, 0xF043, 0x74C2, 0xF047, 0x74C3, 0xF276, 0x74C5, 0xF274, 0x74CA, 0xC3A3, 0x74CB, 0xF273, 0x74CF, 0xC46E, 0x74D4, 0xC4ED, + 0x74D5, 0xF6F1, 0x74D6, 0xC4EC, 0x74D7, 0xF6F3, 0x74D8, 0xF6F0, 0x74D9, 0xF6F2, 0x74DA, 0xC5D0, 0x74DB, 0xF8B2, 0x74DC, 0xA5CA, + 0x74DD, 0xCD6E, 0x74DE, 0xD2BC, 0x74DF, 0xD2BD, 0x74E0, 0xB27D, 0x74E1, 0xDEBF, 0x74E2, 0xBF5D, 0x74E3, 0xC3A4, 0x74E4, 0xC57B, + 0x74E5, 0xF8B3, 0x74E6, 0xA5CB, 0x74E8, 0xCD6F, 0x74E9, 0xA260, 0x74EC, 0xCFD7, 0x74EE, 0xCFD8, 0x74F4, 0xD2BE, 0x74F5, 0xD2BF, + 0x74F6, 0xB27E, 0x74F7, 0xB2A1, 0x74FB, 0xDAAB, 0x74FD, 0xDEC2, 0x74FE, 0xDEC1, 0x74FF, 0xDEC0, 0x7500, 0xE2D5, 0x7502, 0xE2D6, + 0x7503, 0xE2D7, 0x7504, 0xBAC2, 0x7507, 0xE6AD, 0x7508, 0xE6AC, 0x750B, 0xEA69, 0x750C, 0xBF5E, 0x750D, 0xBF5F, 0x750F, 0xED72, + 0x7510, 0xED6F, 0x7511, 0xED70, 0x7512, 0xED71, 0x7513, 0xF049, 0x7514, 0xF048, 0x7515, 0xC27C, 0x7516, 0xF277, 0x7517, 0xF5DE, + 0x7518, 0xA5CC, 0x751A, 0xACC6, 0x751C, 0xB2A2, 0x751D, 0xDEC3, 0x751F, 0xA5CD, 0x7521, 0xD2C0, 0x7522, 0xB2A3, 0x7525, 0xB563, + 0x7526, 0xB564, 0x7528, 0xA5CE, 0x7529, 0xA5CF, 0x752A, 0xCA46, 0x752B, 0xA86A, 0x752C, 0xA869, 0x752D, 0xACC7, 0x752E, 0xCFD9, + 0x752F, 0xDAAC, 0x7530, 0xA5D0, 0x7531, 0xA5D1, 0x7532, 0xA5D2, 0x7533, 0xA5D3, 0x7537, 0xA86B, 0x7538, 0xA86C, 0x7539, 0xCB6E, + 0x753A, 0xCB6D, 0x753D, 0xAAB6, 0x753E, 0xCD72, 0x753F, 0xCD70, 0x7540, 0xCD71, 0x7547, 0xCFDA, 0x7548, 0xCFDB, 0x754B, 0xACCB, + 0x754C, 0xACC9, 0x754E, 0xACCA, 0x754F, 0xACC8, 0x7554, 0xAF60, 0x7559, 0xAF64, 0x755A, 0xAF63, 0x755B, 0xD2C1, 0x755C, 0xAF62, + 0x755D, 0xAF61, 0x755F, 0xD2C2, 0x7562, 0xB2A6, 0x7563, 0xD67B, 0x7564, 0xD67A, 0x7565, 0xB2A4, 0x7566, 0xB2A5, 0x756A, 0xB566, + 0x756B, 0xB565, 0x756C, 0xDAAE, 0x756F, 0xDAAD, 0x7570, 0xB2A7, 0x7576, 0xB7ED, 0x7577, 0xDEC5, 0x7578, 0xB7EE, 0x7579, 0xDEC4, + 0x757D, 0xE2D8, 0x757E, 0xE6AE, 0x757F, 0xBD42, 0x7580, 0xEA6A, 0x7584, 0xED73, 0x7586, 0xC3A6, 0x7587, 0xC3A5, 0x758A, 0xC57C, + 0x758B, 0xA5D4, 0x758C, 0xCD73, 0x758F, 0xB2A8, 0x7590, 0xE2D9, 0x7591, 0xBAC3, 0x7594, 0xCB6F, 0x7595, 0xCB70, 0x7598, 0xCD74, + 0x7599, 0xAAB8, 0x759A, 0xAAB9, 0x759D, 0xAAB7, 0x75A2, 0xACCF, 0x75A3, 0xACD0, 0x75A4, 0xACCD, 0x75A5, 0xACCE, 0x75A7, 0xCFDC, + 0x75AA, 0xCFDD, 0x75AB, 0xACCC, 0x75B0, 0xD2C3, 0x75B2, 0xAF68, 0x75B3, 0xAF69, 0x75B5, 0xB2AB, 0x75B6, 0xD2C9, 0x75B8, 0xAF6E, + 0x75B9, 0xAF6C, 0x75BA, 0xD2CA, 0x75BB, 0xD2C5, 0x75BC, 0xAF6B, 0x75BD, 0xAF6A, 0x75BE, 0xAF65, 0x75BF, 0xD2C8, 0x75C0, 0xD2C7, + 0x75C1, 0xD2C4, 0x75C2, 0xAF6D, 0x75C4, 0xD2C6, 0x75C5, 0xAF66, 0x75C7, 0xAF67, 0x75CA, 0xB2AC, 0x75CB, 0xD6A1, 0x75CC, 0xD6A2, + 0x75CD, 0xB2AD, 0x75CE, 0xD67C, 0x75CF, 0xD67E, 0x75D0, 0xD6A4, 0x75D1, 0xD6A3, 0x75D2, 0xD67D, 0x75D4, 0xB2A9, 0x75D5, 0xB2AA, + 0x75D7, 0xDAB6, 0x75D8, 0xB56B, 0x75D9, 0xB56A, 0x75DA, 0xDAB0, 0x75DB, 0xB568, 0x75DD, 0xDAB3, 0x75DE, 0xB56C, 0x75DF, 0xDAB4, + 0x75E0, 0xB56D, 0x75E1, 0xDAB1, 0x75E2, 0xB567, 0x75E3, 0xB569, 0x75E4, 0xDAB5, 0x75E6, 0xDAB2, 0x75E7, 0xDAAF, 0x75ED, 0xDED2, + 0x75EF, 0xDEC7, 0x75F0, 0xB7F0, 0x75F1, 0xB7F3, 0x75F2, 0xB7F2, 0x75F3, 0xB7F7, 0x75F4, 0xB7F6, 0x75F5, 0xDED3, 0x75F6, 0xDED1, + 0x75F7, 0xDECA, 0x75F8, 0xDECE, 0x75F9, 0xDECD, 0x75FA, 0xB7F4, 0x75FB, 0xDED0, 0x75FC, 0xDECC, 0x75FD, 0xDED4, 0x75FE, 0xDECB, + 0x75FF, 0xB7F5, 0x7600, 0xB7EF, 0x7601, 0xB7F1, 0x7603, 0xDEC9, 0x7608, 0xE2DB, 0x7609, 0xBAC7, 0x760A, 0xE2DF, 0x760B, 0xBAC6, + 0x760C, 0xE2DC, 0x760D, 0xBAC5, 0x760F, 0xDEC8, 0x7610, 0xDECF, 0x7611, 0xE2DE, 0x7613, 0xBAC8, 0x7614, 0xE2E0, 0x7615, 0xE2DD, + 0x7616, 0xE2DA, 0x7619, 0xE6B1, 0x761A, 0xE6B5, 0x761B, 0xE6B7, 0x761C, 0xE6B3, 0x761D, 0xE6B2, 0x761E, 0xE6B0, 0x761F, 0xBD45, + 0x7620, 0xBD43, 0x7621, 0xBD48, 0x7622, 0xBD49, 0x7623, 0xE6B4, 0x7624, 0xBD46, 0x7625, 0xE6AF, 0x7626, 0xBD47, 0x7627, 0xBAC4, + 0x7628, 0xE6B6, 0x7629, 0xBD44, 0x762D, 0xEA6C, 0x762F, 0xEA6B, 0x7630, 0xEA73, 0x7631, 0xEA6D, 0x7632, 0xEA72, 0x7633, 0xEA6F, + 0x7634, 0xBF60, 0x7635, 0xEA71, 0x7638, 0xBF61, 0x763A, 0xBF62, 0x763C, 0xEA70, 0x763D, 0xEA6E, 0x7642, 0xC0F8, 0x7643, 0xED74, + 0x7646, 0xC0F7, 0x7647, 0xED77, 0x7648, 0xED75, 0x7649, 0xED76, 0x764C, 0xC0F9, 0x7650, 0xF04D, 0x7652, 0xC2A1, 0x7653, 0xF04E, + 0x7656, 0xC27D, 0x7657, 0xF04F, 0x7658, 0xC27E, 0x7659, 0xF04C, 0x765A, 0xF050, 0x765C, 0xF04A, 0x765F, 0xC3A7, 0x7660, 0xF278, + 0x7661, 0xC3A8, 0x7662, 0xC46F, 0x7664, 0xF04B, 0x7665, 0xC470, 0x7669, 0xC4EE, 0x766A, 0xF5DF, 0x766C, 0xC57E, 0x766D, 0xF6F4, + 0x766E, 0xC57D, 0x7670, 0xF7EA, 0x7671, 0xC5F5, 0x7672, 0xC5F6, 0x7675, 0xF9CC, 0x7678, 0xACD1, 0x7679, 0xCFDE, 0x767B, 0xB56E, + 0x767C, 0xB56F, 0x767D, 0xA5D5, 0x767E, 0xA6CA, 0x767F, 0xCA47, 0x7681, 0xCB71, 0x7682, 0xA86D, 0x7684, 0xAABA, 0x7686, 0xACD2, + 0x7687, 0xACD3, 0x7688, 0xACD4, 0x7689, 0xD6A6, 0x768A, 0xD2CB, 0x768B, 0xAF6F, 0x768E, 0xB2AE, 0x768F, 0xD6A5, 0x7692, 0xDAB8, + 0x7693, 0xB571, 0x7695, 0xDAB7, 0x7696, 0xB570, 0x7699, 0xDED5, 0x769A, 0xBD4A, 0x769B, 0xE6BB, 0x769C, 0xE6B8, 0x769D, 0xE6B9, + 0x769E, 0xE6BA, 0x76A4, 0xED78, 0x76A6, 0xF051, 0x76AA, 0xF471, 0x76AB, 0xF470, 0x76AD, 0xF6F5, 0x76AE, 0xA5D6, 0x76AF, 0xCD75, + 0x76B0, 0xAF70, 0x76B4, 0xB572, 0x76B5, 0xDED6, 0x76B8, 0xE2E1, 0x76BA, 0xBD4B, 0x76BB, 0xEA74, 0x76BD, 0xF052, 0x76BE, 0xF472, + 0x76BF, 0xA5D7, 0x76C2, 0xAABB, 0x76C3, 0xACD7, 0x76C4, 0xCFDF, 0x76C5, 0xACD8, 0x76C6, 0xACD6, 0x76C8, 0xACD5, 0x76C9, 0xD2CC, + 0x76CA, 0xAF71, 0x76CD, 0xAF72, 0x76CE, 0xAF73, 0x76D2, 0xB2B0, 0x76D3, 0xD6A7, 0x76D4, 0xB2AF, 0x76DA, 0xDAB9, 0x76DB, 0xB2B1, + 0x76DC, 0xB573, 0x76DD, 0xDED7, 0x76DE, 0xB7F8, 0x76DF, 0xB7F9, 0x76E1, 0xBAC9, 0x76E3, 0xBACA, 0x76E4, 0xBD4C, 0x76E5, 0xBF64, + 0x76E6, 0xEA75, 0x76E7, 0xBF63, 0x76E9, 0xED79, 0x76EA, 0xC0FA, 0x76EC, 0xF053, 0x76ED, 0xF473, 0x76EE, 0xA5D8, 0x76EF, 0xA86E, + 0x76F0, 0xCD78, 0x76F1, 0xCD77, 0x76F2, 0xAABC, 0x76F3, 0xCD76, 0x76F4, 0xAABD, 0x76F5, 0xCD79, 0x76F7, 0xCFE5, 0x76F8, 0xACDB, + 0x76F9, 0xACDA, 0x76FA, 0xCFE7, 0x76FB, 0xCFE6, 0x76FC, 0xACDF, 0x76FE, 0xACDE, 0x7701, 0xACD9, 0x7703, 0xCFE1, 0x7704, 0xCFE2, + 0x7705, 0xCFE3, 0x7707, 0xACE0, 0x7708, 0xCFE0, 0x7709, 0xACDC, 0x770A, 0xCFE4, 0x770B, 0xACDD, 0x7710, 0xD2CF, 0x7711, 0xD2D3, + 0x7712, 0xD2D1, 0x7713, 0xD2D0, 0x7715, 0xD2D4, 0x7719, 0xD2D5, 0x771A, 0xD2D6, 0x771B, 0xD2CE, 0x771D, 0xD2CD, 0x771F, 0xAF75, + 0x7720, 0xAF76, 0x7722, 0xD2D7, 0x7723, 0xD2D2, 0x7725, 0xD6B0, 0x7727, 0xD2D8, 0x7728, 0xAF77, 0x7729, 0xAF74, 0x772D, 0xD6AA, + 0x772F, 0xD6A9, 0x7731, 0xD6AB, 0x7732, 0xD6AC, 0x7733, 0xD6AE, 0x7734, 0xD6AD, 0x7735, 0xD6B2, 0x7736, 0xB2B5, 0x7737, 0xB2B2, + 0x7738, 0xB2B6, 0x7739, 0xD6A8, 0x773A, 0xB2B7, 0x773B, 0xD6B1, 0x773C, 0xB2B4, 0x773D, 0xD6AF, 0x773E, 0xB2B3, 0x7744, 0xDABC, + 0x7745, 0xDABE, 0x7746, 0xDABA, 0x7747, 0xDABB, 0x774A, 0xDABF, 0x774B, 0xDAC1, 0x774C, 0xDAC2, 0x774D, 0xDABD, 0x774E, 0xDAC0, + 0x774F, 0xB574, 0x7752, 0xDEDB, 0x7754, 0xDEE0, 0x7755, 0xDED8, 0x7756, 0xDEDC, 0x7759, 0xDEE1, 0x775A, 0xDEDD, 0x775B, 0xB7FA, + 0x775C, 0xB843, 0x775E, 0xB7FD, 0x775F, 0xDED9, 0x7760, 0xDEDA, 0x7761, 0xBACE, 0x7762, 0xB846, 0x7763, 0xB7FE, 0x7765, 0xB844, + 0x7766, 0xB7FC, 0x7767, 0xDEDF, 0x7768, 0xB845, 0x7769, 0xDEDE, 0x776A, 0xB841, 0x776B, 0xB7FB, 0x776C, 0xB842, 0x776D, 0xDEE2, + 0x776E, 0xE2E6, 0x776F, 0xE2E8, 0x7779, 0xB840, 0x777C, 0xE2E3, 0x777D, 0xBACC, 0x777E, 0xE2E9, 0x777F, 0xBACD, 0x7780, 0xE2E7, + 0x7781, 0xE2E2, 0x7782, 0xE2E5, 0x7783, 0xE2EA, 0x7784, 0xBACB, 0x7785, 0xE2E4, 0x7787, 0xBD4E, 0x7788, 0xE6BF, 0x7789, 0xE6BE, + 0x778B, 0xBD51, 0x778C, 0xBD4F, 0x778D, 0xE6BC, 0x778E, 0xBD4D, 0x778F, 0xE6BD, 0x7791, 0xBD50, 0x7795, 0xEA7D, 0x7797, 0xEAA1, + 0x7799, 0xEA7E, 0x779A, 0xEA76, 0x779B, 0xEA7A, 0x779C, 0xEA79, 0x779D, 0xEA77, 0x779E, 0xBF66, 0x779F, 0xBF67, 0x77A0, 0xBF65, + 0x77A1, 0xEA78, 0x77A2, 0xEA7B, 0x77A3, 0xEA7C, 0x77A5, 0xBF68, 0x77A7, 0xC140, 0x77A8, 0xEDA3, 0x77AA, 0xC0FC, 0x77AB, 0xED7B, + 0x77AC, 0xC0FE, 0x77AD, 0xC141, 0x77B0, 0xC0FD, 0x77B1, 0xEDA2, 0x77B2, 0xED7C, 0x77B3, 0xC0FB, 0x77B4, 0xEDA1, 0x77B5, 0xED7A, + 0x77B6, 0xED7E, 0x77B7, 0xED7D, 0x77BA, 0xF055, 0x77BB, 0xC2A4, 0x77BC, 0xC2A5, 0x77BD, 0xC2A2, 0x77BF, 0xC2A3, 0x77C2, 0xF054, + 0x77C4, 0xF27B, 0x77C7, 0xC3A9, 0x77C9, 0xF279, 0x77CA, 0xF27A, 0x77CC, 0xF474, 0x77CD, 0xF477, 0x77CE, 0xF475, 0x77CF, 0xF476, + 0x77D0, 0xF5E0, 0x77D3, 0xC4EF, 0x77D4, 0xF7EB, 0x77D5, 0xF8B4, 0x77D7, 0xC5F7, 0x77D8, 0xF8F8, 0x77D9, 0xF8F9, 0x77DA, 0xC666, + 0x77DB, 0xA5D9, 0x77DC, 0xACE1, 0x77DE, 0xDAC3, 0x77E0, 0xDEE3, 0x77E2, 0xA5DA, 0x77E3, 0xA86F, 0x77E5, 0xAABE, 0x77E7, 0xCFE8, + 0x77E8, 0xCFE9, 0x77E9, 0xAF78, 0x77EC, 0xDAC4, 0x77ED, 0xB575, 0x77EE, 0xB847, 0x77EF, 0xC142, 0x77F0, 0xEDA4, 0x77F1, 0xF27C, + 0x77F2, 0xF478, 0x77F3, 0xA5DB, 0x77F7, 0xCDA1, 0x77F8, 0xCD7A, 0x77F9, 0xCD7C, 0x77FA, 0xCD7E, 0x77FB, 0xCD7D, 0x77FC, 0xCD7B, + 0x77FD, 0xAABF, 0x7802, 0xACE2, 0x7803, 0xCFF2, 0x7805, 0xCFED, 0x7806, 0xCFEA, 0x7809, 0xCFF1, 0x780C, 0xACE4, 0x780D, 0xACE5, + 0x780E, 0xCFF0, 0x780F, 0xCFEF, 0x7810, 0xCFEE, 0x7811, 0xCFEB, 0x7812, 0xCFEC, 0x7813, 0xCFF3, 0x7814, 0xACE3, 0x781D, 0xAF7C, + 0x781F, 0xAFA4, 0x7820, 0xAFA3, 0x7821, 0xD2E1, 0x7822, 0xD2DB, 0x7823, 0xD2D9, 0x7825, 0xAFA1, 0x7826, 0xD6B9, 0x7827, 0xAF7A, + 0x7828, 0xD2DE, 0x7829, 0xD2E2, 0x782A, 0xD2E4, 0x782B, 0xD2E0, 0x782C, 0xD2DA, 0x782D, 0xAFA2, 0x782E, 0xD2DF, 0x782F, 0xD2DD, + 0x7830, 0xAF79, 0x7831, 0xD2E5, 0x7832, 0xAFA5, 0x7833, 0xD2E3, 0x7834, 0xAF7D, 0x7835, 0xD2DC, 0x7837, 0xAF7E, 0x7838, 0xAF7B, + 0x7843, 0xB2B9, 0x7845, 0xD6BA, 0x7848, 0xD6B3, 0x7849, 0xD6B5, 0x784A, 0xD6B7, 0x784C, 0xD6B8, 0x784D, 0xD6B6, 0x784E, 0xB2BA, + 0x7850, 0xD6BB, 0x7852, 0xD6B4, 0x785C, 0xDAC8, 0x785D, 0xB576, 0x785E, 0xDAD0, 0x7860, 0xDAC5, 0x7862, 0xDAD1, 0x7864, 0xDAC6, + 0x7865, 0xDAC7, 0x7868, 0xDACF, 0x7869, 0xDACE, 0x786A, 0xDACB, 0x786B, 0xB2B8, 0x786C, 0xB577, 0x786D, 0xDAC9, 0x786E, 0xDACC, + 0x786F, 0xB578, 0x7870, 0xDACD, 0x7871, 0xDACA, 0x7879, 0xDEEE, 0x787B, 0xDEF2, 0x787C, 0xB84E, 0x787E, 0xE2F0, 0x787F, 0xB851, + 0x7880, 0xDEF0, 0x7881, 0xF9D6, 0x7883, 0xDEED, 0x7884, 0xDEE8, 0x7885, 0xDEEA, 0x7886, 0xDEEB, 0x7887, 0xDEE4, 0x7889, 0xB84D, + 0x788C, 0xB84C, 0x788E, 0xB848, 0x788F, 0xDEE7, 0x7891, 0xB84F, 0x7893, 0xB850, 0x7894, 0xDEE6, 0x7895, 0xDEE9, 0x7896, 0xDEF1, + 0x7897, 0xB84A, 0x7898, 0xB84B, 0x7899, 0xDEEF, 0x789A, 0xDEE5, 0x789E, 0xE2F2, 0x789F, 0xBAD0, 0x78A0, 0xE2F4, 0x78A1, 0xDEEC, + 0x78A2, 0xE2F6, 0x78A3, 0xBAD4, 0x78A4, 0xE2F7, 0x78A5, 0xE2F3, 0x78A7, 0xBAD1, 0x78A8, 0xE2EF, 0x78A9, 0xBAD3, 0x78AA, 0xE2EC, + 0x78AB, 0xE2F1, 0x78AC, 0xE2F5, 0x78AD, 0xE2EE, 0x78B0, 0xB849, 0x78B2, 0xE2EB, 0x78B3, 0xBAD2, 0x78B4, 0xE2ED, 0x78BA, 0xBD54, + 0x78BB, 0xE6C1, 0x78BC, 0xBD58, 0x78BE, 0xBD56, 0x78C1, 0xBACF, 0x78C3, 0xE6C8, 0x78C4, 0xE6C9, 0x78C5, 0xBD53, 0x78C8, 0xE6C7, + 0x78C9, 0xE6CA, 0x78CA, 0xBD55, 0x78CB, 0xBD52, 0x78CC, 0xE6C3, 0x78CD, 0xE6C0, 0x78CE, 0xE6C5, 0x78CF, 0xE6C2, 0x78D0, 0xBD59, + 0x78D1, 0xE6C4, 0x78D4, 0xE6C6, 0x78D5, 0xBD57, 0x78DA, 0xBF6A, 0x78DB, 0xEAA8, 0x78DD, 0xEAA2, 0x78DE, 0xEAA6, 0x78DF, 0xEAAC, + 0x78E0, 0xEAAD, 0x78E1, 0xEAA9, 0x78E2, 0xEAAA, 0x78E3, 0xEAA7, 0x78E5, 0xEAA4, 0x78E7, 0xBF6C, 0x78E8, 0xBF69, 0x78E9, 0xEAA3, + 0x78EA, 0xEAA5, 0x78EC, 0xBF6B, 0x78ED, 0xEAAB, 0x78EF, 0xC146, 0x78F2, 0xEDAA, 0x78F3, 0xEDA5, 0x78F4, 0xC145, 0x78F7, 0xC143, + 0x78F9, 0xEDAC, 0x78FA, 0xC144, 0x78FB, 0xEDA8, 0x78FC, 0xEDA9, 0x78FD, 0xEDA6, 0x78FE, 0xEDAD, 0x78FF, 0xF056, 0x7901, 0xC147, + 0x7902, 0xEDA7, 0x7904, 0xEDAE, 0x7905, 0xEDAB, 0x7909, 0xF05A, 0x790C, 0xF057, 0x790E, 0xC2A6, 0x7910, 0xF05B, 0x7911, 0xF05D, + 0x7912, 0xF05C, 0x7913, 0xF058, 0x7914, 0xF059, 0x7917, 0xF2A3, 0x7919, 0xC3AA, 0x791B, 0xF27E, 0x791C, 0xF2A2, 0x791D, 0xF27D, + 0x791E, 0xF2A4, 0x7921, 0xF2A1, 0x7923, 0xF47A, 0x7924, 0xF47D, 0x7925, 0xF479, 0x7926, 0xC471, 0x7927, 0xF47B, 0x7928, 0xF47C, + 0x7929, 0xF47E, 0x792A, 0xC472, 0x792B, 0xC474, 0x792C, 0xC473, 0x792D, 0xF5E1, 0x792F, 0xF5E3, 0x7931, 0xF5E2, 0x7935, 0xF6F6, + 0x7938, 0xF8B5, 0x7939, 0xF8FA, 0x793A, 0xA5DC, 0x793D, 0xCB72, 0x793E, 0xAAC0, 0x793F, 0xCDA3, 0x7940, 0xAAC1, 0x7941, 0xAAC2, + 0x7942, 0xCDA2, 0x7944, 0xCFF8, 0x7945, 0xCFF7, 0x7946, 0xACE6, 0x7947, 0xACE9, 0x7948, 0xACE8, 0x7949, 0xACE7, 0x794A, 0xCFF4, + 0x794B, 0xCFF6, 0x794C, 0xCFF5, 0x794F, 0xD2E8, 0x7950, 0xAFA7, 0x7951, 0xD2EC, 0x7952, 0xD2EB, 0x7953, 0xD2EA, 0x7954, 0xD2E6, + 0x7955, 0xAFA6, 0x7956, 0xAFAA, 0x7957, 0xAFAD, 0x795A, 0xAFAE, 0x795B, 0xD2E7, 0x795C, 0xD2E9, 0x795D, 0xAFAC, 0x795E, 0xAFAB, + 0x795F, 0xAFA9, 0x7960, 0xAFA8, 0x7961, 0xD6C2, 0x7963, 0xD6C0, 0x7964, 0xD6BC, 0x7965, 0xB2BB, 0x7967, 0xD6BD, 0x7968, 0xB2BC, + 0x7969, 0xD6BE, 0x796A, 0xD6BF, 0x796B, 0xD6C1, 0x796D, 0xB2BD, 0x7970, 0xDAD5, 0x7972, 0xDAD4, 0x7973, 0xDAD3, 0x7974, 0xDAD2, + 0x7979, 0xDEF6, 0x797A, 0xB852, 0x797C, 0xDEF3, 0x797D, 0xDEF5, 0x797F, 0xB853, 0x7981, 0xB854, 0x7982, 0xDEF4, 0x7988, 0xE341, + 0x798A, 0xE2F9, 0x798B, 0xE2FA, 0x798D, 0xBAD7, 0x798E, 0xBAD5, 0x798F, 0xBAD6, 0x7990, 0xE343, 0x7992, 0xE342, 0x7993, 0xE2FE, + 0x7994, 0xE2FD, 0x7995, 0xE2FC, 0x7996, 0xE2FB, 0x7997, 0xE340, 0x7998, 0xE2F8, 0x799A, 0xE6CB, 0x799B, 0xE6D0, 0x799C, 0xE6CE, + 0x79A0, 0xE6CD, 0x79A1, 0xE6CC, 0x79A2, 0xE6CF, 0x79A4, 0xEAAE, 0x79A6, 0xBF6D, 0x79A7, 0xC148, 0x79A8, 0xEDB0, 0x79AA, 0xC149, + 0x79AB, 0xEDAF, 0x79AC, 0xF05F, 0x79AD, 0xF05E, 0x79AE, 0xC2A7, 0x79B0, 0xF2A5, 0x79B1, 0xC3AB, 0x79B2, 0xF4A1, 0x79B3, 0xC5A1, + 0x79B4, 0xF6F7, 0x79B6, 0xF8B7, 0x79B7, 0xF8B6, 0x79B8, 0xC9A8, 0x79B9, 0xACEA, 0x79BA, 0xACEB, 0x79BB, 0xD6C3, 0x79BD, 0xB856, + 0x79BE, 0xA5DD, 0x79BF, 0xA872, 0x79C0, 0xA871, 0x79C1, 0xA870, 0x79C5, 0xCDA4, 0x79C8, 0xAAC4, 0x79C9, 0xAAC3, 0x79CB, 0xACEE, + 0x79CD, 0xCFFA, 0x79CE, 0xCFFD, 0x79CF, 0xCFFB, 0x79D1, 0xACEC, 0x79D2, 0xACED, 0x79D5, 0xCFF9, 0x79D6, 0xCFFC, 0x79D8, 0xAFB5, + 0x79DC, 0xD2F3, 0x79DD, 0xD2F5, 0x79DE, 0xD2F4, 0x79DF, 0xAFB2, 0x79E0, 0xD2EF, 0x79E3, 0xAFB0, 0x79E4, 0xAFAF, 0x79E6, 0xAFB3, + 0x79E7, 0xAFB1, 0x79E9, 0xAFB4, 0x79EA, 0xD2F2, 0x79EB, 0xD2ED, 0x79EC, 0xD2EE, 0x79ED, 0xD2F1, 0x79EE, 0xD2F0, 0x79F6, 0xD6C6, + 0x79F7, 0xD6C7, 0x79F8, 0xD6C5, 0x79FA, 0xD6C4, 0x79FB, 0xB2BE, 0x7A00, 0xB57D, 0x7A02, 0xDAD6, 0x7A03, 0xDAD8, 0x7A04, 0xDADA, + 0x7A05, 0xB57C, 0x7A08, 0xB57A, 0x7A0A, 0xDAD7, 0x7A0B, 0xB57B, 0x7A0C, 0xDAD9, 0x7A0D, 0xB579, 0x7A10, 0xDF41, 0x7A11, 0xDEF7, + 0x7A12, 0xDEFA, 0x7A13, 0xDEFE, 0x7A14, 0xB85A, 0x7A15, 0xDEFC, 0x7A17, 0xDEFB, 0x7A18, 0xDEF8, 0x7A19, 0xDEF9, 0x7A1A, 0xB858, + 0x7A1B, 0xDF40, 0x7A1C, 0xB857, 0x7A1E, 0xB85C, 0x7A1F, 0xB85B, 0x7A20, 0xB859, 0x7A22, 0xDEFD, 0x7A26, 0xE349, 0x7A28, 0xE348, + 0x7A2B, 0xE344, 0x7A2E, 0xBAD8, 0x7A2F, 0xE347, 0x7A30, 0xE346, 0x7A31, 0xBAD9, 0x7A37, 0xBD5E, 0x7A39, 0xE6D2, 0x7A3B, 0xBD5F, + 0x7A3C, 0xBD5B, 0x7A3D, 0xBD5D, 0x7A3F, 0xBD5A, 0x7A40, 0xBD5C, 0x7A44, 0xEAAF, 0x7A46, 0xBF70, 0x7A47, 0xEAB1, 0x7A48, 0xEAB0, + 0x7A4A, 0xE345, 0x7A4B, 0xBF72, 0x7A4C, 0xBF71, 0x7A4D, 0xBF6E, 0x7A4E, 0xBF6F, 0x7A54, 0xEDB5, 0x7A56, 0xEDB3, 0x7A57, 0xC14A, + 0x7A58, 0xEDB4, 0x7A5A, 0xEDB6, 0x7A5B, 0xEDB2, 0x7A5C, 0xEDB1, 0x7A5F, 0xF060, 0x7A60, 0xC2AA, 0x7A61, 0xC2A8, 0x7A62, 0xC2A9, + 0x7A67, 0xF2A6, 0x7A68, 0xF2A7, 0x7A69, 0xC3AD, 0x7A6B, 0xC3AC, 0x7A6C, 0xF4A3, 0x7A6D, 0xF4A4, 0x7A6E, 0xF4A2, 0x7A70, 0xF6F8, + 0x7A71, 0xF6F9, 0x7A74, 0xA5DE, 0x7A75, 0xCA48, 0x7A76, 0xA873, 0x7A78, 0xCDA5, 0x7A79, 0xAAC6, 0x7A7A, 0xAAC5, 0x7A7B, 0xCDA6, + 0x7A7E, 0xD040, 0x7A7F, 0xACEF, 0x7A80, 0xCFFE, 0x7A81, 0xACF0, 0x7A84, 0xAFB6, 0x7A85, 0xD2F8, 0x7A86, 0xD2F6, 0x7A87, 0xD2FC, + 0x7A88, 0xAFB7, 0x7A89, 0xD2F7, 0x7A8A, 0xD2FB, 0x7A8B, 0xD2F9, 0x7A8C, 0xD2FA, 0x7A8F, 0xD6C8, 0x7A90, 0xD6CA, 0x7A92, 0xB2BF, + 0x7A94, 0xD6C9, 0x7A95, 0xB2C0, 0x7A96, 0xB5A2, 0x7A97, 0xB5A1, 0x7A98, 0xB57E, 0x7A99, 0xDADB, 0x7A9E, 0xDF44, 0x7A9F, 0xB85D, + 0x7AA0, 0xB85E, 0x7AA2, 0xDF43, 0x7AA3, 0xDF42, 0x7AA8, 0xE34A, 0x7AA9, 0xBADB, 0x7AAA, 0xBADA, 0x7AAB, 0xE34B, 0x7AAC, 0xE34C, + 0x7AAE, 0xBD61, 0x7AAF, 0xBD60, 0x7AB1, 0xEAB5, 0x7AB2, 0xE6D3, 0x7AB3, 0xE6D5, 0x7AB4, 0xE6D4, 0x7AB5, 0xEAB4, 0x7AB6, 0xEAB2, + 0x7AB7, 0xEAB6, 0x7AB8, 0xEAB3, 0x7ABA, 0xBF73, 0x7ABE, 0xEDB7, 0x7ABF, 0xC14B, 0x7AC0, 0xEDB8, 0x7AC1, 0xEDB9, 0x7AC4, 0xC2AB, + 0x7AC5, 0xC2AC, 0x7AC7, 0xC475, 0x7ACA, 0xC5D1, 0x7ACB, 0xA5DF, 0x7AD1, 0xD041, 0x7AD8, 0xD2FD, 0x7AD9, 0xAFB8, 0x7ADF, 0xB3BA, + 0x7AE0, 0xB3B9, 0x7AE3, 0xB5A4, 0x7AE4, 0xDADD, 0x7AE5, 0xB5A3, 0x7AE6, 0xDADC, 0x7AEB, 0xDF45, 0x7AED, 0xBADC, 0x7AEE, 0xE34D, + 0x7AEF, 0xBADD, 0x7AF6, 0xC476, 0x7AF7, 0xF4A5, 0x7AF9, 0xA6CB, 0x7AFA, 0xAAC7, 0x7AFB, 0xCDA7, 0x7AFD, 0xACF2, 0x7AFF, 0xACF1, + 0x7B00, 0xD042, 0x7B01, 0xD043, 0x7B04, 0xD340, 0x7B05, 0xD342, 0x7B06, 0xAFB9, 0x7B08, 0xD344, 0x7B09, 0xD347, 0x7B0A, 0xD345, + 0x7B0E, 0xD346, 0x7B0F, 0xD343, 0x7B10, 0xD2FE, 0x7B11, 0xAFBA, 0x7B12, 0xD348, 0x7B13, 0xD341, 0x7B18, 0xD6D3, 0x7B19, 0xB2C6, + 0x7B1A, 0xD6DC, 0x7B1B, 0xB2C3, 0x7B1D, 0xD6D5, 0x7B1E, 0xB2C7, 0x7B20, 0xB2C1, 0x7B22, 0xD6D0, 0x7B23, 0xD6DD, 0x7B24, 0xD6D1, + 0x7B25, 0xD6CE, 0x7B26, 0xB2C5, 0x7B28, 0xB2C2, 0x7B2A, 0xD6D4, 0x7B2B, 0xD6D7, 0x7B2C, 0xB2C4, 0x7B2D, 0xD6D8, 0x7B2E, 0xB2C8, + 0x7B2F, 0xD6D9, 0x7B30, 0xD6CF, 0x7B31, 0xD6D6, 0x7B32, 0xD6DA, 0x7B33, 0xD6D2, 0x7B34, 0xD6CD, 0x7B35, 0xD6CB, 0x7B38, 0xD6DB, + 0x7B3B, 0xDADF, 0x7B40, 0xDAE4, 0x7B44, 0xDAE0, 0x7B45, 0xDAE6, 0x7B46, 0xB5A7, 0x7B47, 0xD6CC, 0x7B48, 0xDAE1, 0x7B49, 0xB5A5, + 0x7B4A, 0xDADE, 0x7B4B, 0xB5AC, 0x7B4C, 0xDAE2, 0x7B4D, 0xB5AB, 0x7B4E, 0xDAE3, 0x7B4F, 0xB5AD, 0x7B50, 0xB5A8, 0x7B51, 0xB5AE, + 0x7B52, 0xB5A9, 0x7B54, 0xB5AA, 0x7B56, 0xB5A6, 0x7B58, 0xDAE5, 0x7B60, 0xB861, 0x7B61, 0xDF50, 0x7B63, 0xDF53, 0x7B64, 0xDF47, + 0x7B65, 0xDF4C, 0x7B66, 0xDF46, 0x7B67, 0xB863, 0x7B69, 0xDF4A, 0x7B6D, 0xDF48, 0x7B6E, 0xB862, 0x7B70, 0xDF4F, 0x7B71, 0xDF4E, + 0x7B72, 0xDF4B, 0x7B73, 0xDF4D, 0x7B74, 0xDF49, 0x7B75, 0xBAE1, 0x7B76, 0xDF52, 0x7B77, 0xB85F, 0x7B78, 0xDF51, 0x7B82, 0xE35D, + 0x7B84, 0xBAE8, 0x7B85, 0xE358, 0x7B87, 0xBAE7, 0x7B88, 0xE34E, 0x7B8A, 0xE350, 0x7B8B, 0xBAE0, 0x7B8C, 0xE355, 0x7B8D, 0xE354, + 0x7B8E, 0xE357, 0x7B8F, 0xBAE5, 0x7B90, 0xE352, 0x7B91, 0xE351, 0x7B94, 0xBAE4, 0x7B95, 0xBADF, 0x7B96, 0xE353, 0x7B97, 0xBAE2, + 0x7B98, 0xE359, 0x7B99, 0xE35B, 0x7B9B, 0xE356, 0x7B9C, 0xE34F, 0x7B9D, 0xBAE3, 0x7BA0, 0xBD69, 0x7BA1, 0xBADE, 0x7BA4, 0xE35C, + 0x7BAC, 0xE6D9, 0x7BAD, 0xBD62, 0x7BAF, 0xE6DB, 0x7BB1, 0xBD63, 0x7BB4, 0xBD65, 0x7BB5, 0xE6DE, 0x7BB7, 0xE6D6, 0x7BB8, 0xBAE6, + 0x7BB9, 0xE6DC, 0x7BBE, 0xE6D8, 0x7BC0, 0xB860, 0x7BC1, 0xBD68, 0x7BC4, 0xBD64, 0x7BC6, 0xBD66, 0x7BC7, 0xBD67, 0x7BC9, 0xBF76, + 0x7BCA, 0xE6DD, 0x7BCB, 0xE6D7, 0x7BCC, 0xBD6A, 0x7BCE, 0xE6DA, 0x7BD4, 0xEAC0, 0x7BD5, 0xEABB, 0x7BD8, 0xEAC5, 0x7BD9, 0xBF74, + 0x7BDA, 0xEABD, 0x7BDB, 0xBF78, 0x7BDC, 0xEAC3, 0x7BDD, 0xEABA, 0x7BDE, 0xEAB7, 0x7BDF, 0xEAC6, 0x7BE0, 0xC151, 0x7BE1, 0xBF79, + 0x7BE2, 0xEAC2, 0x7BE3, 0xEAB8, 0x7BE4, 0xBF77, 0x7BE5, 0xEABC, 0x7BE6, 0xBF7B, 0x7BE7, 0xEAB9, 0x7BE8, 0xEABE, 0x7BE9, 0xBF7A, + 0x7BEA, 0xEAC1, 0x7BEB, 0xEAC4, 0x7BF0, 0xEDCB, 0x7BF1, 0xEDCC, 0x7BF2, 0xEDBC, 0x7BF3, 0xEDC3, 0x7BF4, 0xEDC1, 0x7BF7, 0xC14F, + 0x7BF8, 0xEDC8, 0x7BF9, 0xEABF, 0x7BFB, 0xEDBF, 0x7BFD, 0xEDC9, 0x7BFE, 0xC14E, 0x7BFF, 0xEDBE, 0x7C00, 0xEDBD, 0x7C01, 0xEDC7, + 0x7C02, 0xEDC4, 0x7C03, 0xEDC6, 0x7C05, 0xEDBA, 0x7C06, 0xEDCA, 0x7C07, 0xC14C, 0x7C09, 0xEDC5, 0x7C0A, 0xEDCE, 0x7C0B, 0xEDC2, + 0x7C0C, 0xC150, 0x7C0D, 0xC14D, 0x7C0E, 0xEDC0, 0x7C0F, 0xEDBB, 0x7C10, 0xEDCD, 0x7C11, 0xBF75, 0x7C19, 0xF063, 0x7C1C, 0xF061, + 0x7C1D, 0xF067, 0x7C1E, 0xC2B0, 0x7C1F, 0xF065, 0x7C20, 0xF064, 0x7C21, 0xC2B2, 0x7C22, 0xF06A, 0x7C23, 0xC2B1, 0x7C25, 0xF06B, + 0x7C26, 0xF068, 0x7C27, 0xC2AE, 0x7C28, 0xF069, 0x7C29, 0xF062, 0x7C2A, 0xC2AF, 0x7C2B, 0xC2AD, 0x7C2C, 0xF2AB, 0x7C2D, 0xF066, + 0x7C30, 0xF06C, 0x7C33, 0xF2A8, 0x7C37, 0xC3B2, 0x7C38, 0xC3B0, 0x7C39, 0xF2AA, 0x7C3B, 0xF2AC, 0x7C3C, 0xF2A9, 0x7C3D, 0xC3B1, + 0x7C3E, 0xC3AE, 0x7C3F, 0xC3AF, 0x7C40, 0xC3B3, 0x7C43, 0xC478, 0x7C45, 0xF4AA, 0x7C47, 0xF4A9, 0x7C48, 0xF4A7, 0x7C49, 0xF4A6, + 0x7C4A, 0xF4A8, 0x7C4C, 0xC477, 0x7C4D, 0xC479, 0x7C50, 0xC4F0, 0x7C53, 0xF5E5, 0x7C54, 0xF5E4, 0x7C57, 0xF6FA, 0x7C59, 0xF6FC, + 0x7C5A, 0xF6FE, 0x7C5B, 0xF6FD, 0x7C5C, 0xF6FB, 0x7C5F, 0xC5A3, 0x7C60, 0xC5A2, 0x7C63, 0xC5D3, 0x7C64, 0xC5D2, 0x7C65, 0xC5D4, + 0x7C66, 0xF7ED, 0x7C67, 0xF7EC, 0x7C69, 0xF8FB, 0x7C6A, 0xF8B8, 0x7C6B, 0xF8FC, 0x7C6C, 0xC658, 0x7C6E, 0xC659, 0x7C6F, 0xF96D, + 0x7C72, 0xC67E, 0x7C73, 0xA6CC, 0x7C75, 0xCDA8, 0x7C78, 0xD045, 0x7C79, 0xD046, 0x7C7A, 0xD044, 0x7C7D, 0xACF3, 0x7C7F, 0xD047, + 0x7C80, 0xD048, 0x7C81, 0xD049, 0x7C84, 0xD349, 0x7C85, 0xD34F, 0x7C88, 0xD34D, 0x7C89, 0xAFBB, 0x7C8A, 0xD34B, 0x7C8C, 0xD34C, + 0x7C8D, 0xD34E, 0x7C91, 0xD34A, 0x7C92, 0xB2C9, 0x7C94, 0xD6DE, 0x7C95, 0xB2CB, 0x7C96, 0xD6E0, 0x7C97, 0xB2CA, 0x7C98, 0xD6DF, + 0x7C9E, 0xDAE8, 0x7C9F, 0xB5AF, 0x7CA1, 0xDAEA, 0x7CA2, 0xDAE7, 0x7CA3, 0xD6E1, 0x7CA5, 0xB5B0, 0x7CA7, 0xF9DB, 0x7CA8, 0xDAE9, + 0x7CAF, 0xDF56, 0x7CB1, 0xB864, 0x7CB2, 0xDF54, 0x7CB3, 0xB865, 0x7CB4, 0xDF55, 0x7CB5, 0xB866, 0x7CB9, 0xBAE9, 0x7CBA, 0xE361, + 0x7CBB, 0xE35E, 0x7CBC, 0xE360, 0x7CBD, 0xBAEA, 0x7CBE, 0xBAEB, 0x7CBF, 0xE35F, 0x7CC5, 0xE6DF, 0x7CC8, 0xE6E0, 0x7CCA, 0xBD6B, + 0x7CCB, 0xE6E2, 0x7CCC, 0xE6E1, 0x7CCE, 0xA261, 0x7CD0, 0xEACA, 0x7CD1, 0xEACB, 0x7CD2, 0xEAC7, 0x7CD4, 0xEAC8, 0x7CD5, 0xBF7C, + 0x7CD6, 0xBF7D, 0x7CD7, 0xEAC9, 0x7CD9, 0xC157, 0x7CDC, 0xC153, 0x7CDD, 0xC158, 0x7CDE, 0xC154, 0x7CDF, 0xC156, 0x7CE0, 0xC152, + 0x7CE2, 0xC155, 0x7CE7, 0xC2B3, 0x7CE8, 0xEDCF, 0x7CEA, 0xF2AE, 0x7CEC, 0xF2AD, 0x7CEE, 0xF4AB, 0x7CEF, 0xC47A, 0x7CF0, 0xC47B, + 0x7CF1, 0xF741, 0x7CF2, 0xF5E6, 0x7CF4, 0xF740, 0x7CF6, 0xF8FD, 0x7CF7, 0xF9A4, 0x7CF8, 0xA6CD, 0x7CFB, 0xA874, 0x7CFD, 0xCDA9, + 0x7CFE, 0xAAC8, 0x7D00, 0xACF6, 0x7D01, 0xD04C, 0x7D02, 0xACF4, 0x7D03, 0xD04A, 0x7D04, 0xACF9, 0x7D05, 0xACF5, 0x7D06, 0xACFA, + 0x7D07, 0xACF8, 0x7D08, 0xD04B, 0x7D09, 0xACF7, 0x7D0A, 0xAFBF, 0x7D0B, 0xAFBE, 0x7D0C, 0xD35A, 0x7D0D, 0xAFC7, 0x7D0E, 0xD353, + 0x7D0F, 0xD359, 0x7D10, 0xAFC3, 0x7D11, 0xD352, 0x7D12, 0xD358, 0x7D13, 0xD356, 0x7D14, 0xAFC2, 0x7D15, 0xAFC4, 0x7D16, 0xD355, + 0x7D17, 0xAFBD, 0x7D18, 0xD354, 0x7D19, 0xAFC8, 0x7D1A, 0xAFC5, 0x7D1B, 0xAFC9, 0x7D1C, 0xAFC6, 0x7D1D, 0xD351, 0x7D1E, 0xD350, + 0x7D1F, 0xD357, 0x7D20, 0xAFC0, 0x7D21, 0xAFBC, 0x7D22, 0xAFC1, 0x7D28, 0xD6F0, 0x7D29, 0xD6E9, 0x7D2B, 0xB5B5, 0x7D2C, 0xD6E8, + 0x7D2E, 0xB2CF, 0x7D2F, 0xB2D6, 0x7D30, 0xB2D3, 0x7D31, 0xB2D9, 0x7D32, 0xB2D8, 0x7D33, 0xB2D4, 0x7D35, 0xD6E2, 0x7D36, 0xD6E5, + 0x7D38, 0xD6E4, 0x7D39, 0xB2D0, 0x7D3A, 0xD6E6, 0x7D3B, 0xD6EF, 0x7D3C, 0xB2D1, 0x7D3D, 0xD6E3, 0x7D3E, 0xD6EC, 0x7D3F, 0xD6ED, + 0x7D40, 0xB2D2, 0x7D41, 0xD6EA, 0x7D42, 0xB2D7, 0x7D43, 0xB2CD, 0x7D44, 0xB2D5, 0x7D45, 0xD6E7, 0x7D46, 0xB2CC, 0x7D47, 0xD6EB, + 0x7D4A, 0xD6EE, 0x7D4E, 0xDAFB, 0x7D4F, 0xDAF2, 0x7D50, 0xB5B2, 0x7D51, 0xDAF9, 0x7D52, 0xDAF6, 0x7D53, 0xDAEE, 0x7D54, 0xDAF7, + 0x7D55, 0xB5B4, 0x7D56, 0xDAEF, 0x7D58, 0xDAEB, 0x7D5B, 0xB86C, 0x7D5C, 0xDAF4, 0x7D5E, 0xB5B1, 0x7D5F, 0xDAFA, 0x7D61, 0xB5B8, + 0x7D62, 0xB5BA, 0x7D63, 0xDAED, 0x7D66, 0xB5B9, 0x7D67, 0xDAF0, 0x7D68, 0xB5B3, 0x7D69, 0xDAF8, 0x7D6A, 0xDAF1, 0x7D6B, 0xDAF5, + 0x7D6D, 0xDAF3, 0x7D6E, 0xB5B6, 0x7D6F, 0xDAEC, 0x7D70, 0xB5BB, 0x7D71, 0xB2CE, 0x7D72, 0xB5B7, 0x7D73, 0xB5BC, 0x7D79, 0xB868, + 0x7D7A, 0xDF5D, 0x7D7B, 0xDF5F, 0x7D7C, 0xDF61, 0x7D7D, 0xDF65, 0x7D7F, 0xDF5B, 0x7D80, 0xDF59, 0x7D81, 0xB86A, 0x7D83, 0xDF60, + 0x7D84, 0xDF64, 0x7D85, 0xDF5C, 0x7D86, 0xDF58, 0x7D88, 0xDF57, 0x7D8C, 0xDF62, 0x7D8D, 0xDF5A, 0x7D8E, 0xDF5E, 0x7D8F, 0xB86B, + 0x7D91, 0xB869, 0x7D92, 0xDF66, 0x7D93, 0xB867, 0x7D94, 0xDF63, 0x7D96, 0xE372, 0x7D9C, 0xBAEE, 0x7D9D, 0xE36A, 0x7D9E, 0xBD78, + 0x7D9F, 0xE374, 0x7DA0, 0xBAF1, 0x7DA1, 0xE378, 0x7DA2, 0xBAF7, 0x7DA3, 0xE365, 0x7DA6, 0xE375, 0x7DA7, 0xE362, 0x7DA9, 0xE377, + 0x7DAA, 0xE366, 0x7DAC, 0xBAFE, 0x7DAD, 0xBAFB, 0x7DAE, 0xE376, 0x7DAF, 0xE370, 0x7DB0, 0xBAED, 0x7DB1, 0xBAF5, 0x7DB2, 0xBAF4, + 0x7DB4, 0xBAF3, 0x7DB5, 0xBAF9, 0x7DB7, 0xE363, 0x7DB8, 0xBAFA, 0x7DB9, 0xE371, 0x7DBA, 0xBAF6, 0x7DBB, 0xBAEC, 0x7DBC, 0xE373, + 0x7DBD, 0xBAEF, 0x7DBE, 0xBAF0, 0x7DBF, 0xBAF8, 0x7DC0, 0xE368, 0x7DC1, 0xE367, 0x7DC2, 0xE364, 0x7DC4, 0xE36C, 0x7DC5, 0xE369, + 0x7DC6, 0xE36D, 0x7DC7, 0xBAFD, 0x7DC9, 0xE379, 0x7DCA, 0xBAF2, 0x7DCB, 0xE36E, 0x7DCC, 0xE36F, 0x7DCE, 0xE36B, 0x7DD2, 0xBAFC, + 0x7DD7, 0xE6E7, 0x7DD8, 0xBD70, 0x7DD9, 0xBD79, 0x7DDA, 0xBD75, 0x7DDB, 0xE6E4, 0x7DDD, 0xBD72, 0x7DDE, 0xBD76, 0x7DDF, 0xE6F0, + 0x7DE0, 0xBD6C, 0x7DE1, 0xE6E8, 0x7DE3, 0xBD74, 0x7DE6, 0xE6EB, 0x7DE7, 0xE6E6, 0x7DE8, 0xBD73, 0x7DE9, 0xBD77, 0x7DEA, 0xE6E5, + 0x7DEC, 0xBD71, 0x7DEE, 0xE6EF, 0x7DEF, 0xBD6E, 0x7DF0, 0xE6EE, 0x7DF1, 0xE6ED, 0x7DF2, 0xBD7A, 0x7DF3, 0xE572, 0x7DF4, 0xBD6D, + 0x7DF6, 0xE6EC, 0x7DF7, 0xE6E3, 0x7DF9, 0xBD7B, 0x7DFA, 0xE6EA, 0x7DFB, 0xBD6F, 0x7E03, 0xE6E9, 0x7E08, 0xBFA2, 0x7E09, 0xBFA7, + 0x7E0A, 0xBF7E, 0x7E0B, 0xEAD8, 0x7E0C, 0xEACF, 0x7E0D, 0xEADB, 0x7E0E, 0xEAD3, 0x7E0F, 0xEAD9, 0x7E10, 0xBFA8, 0x7E11, 0xBFA1, + 0x7E12, 0xEACC, 0x7E13, 0xEAD2, 0x7E14, 0xEADC, 0x7E15, 0xEAD5, 0x7E16, 0xEADA, 0x7E17, 0xEACE, 0x7E1A, 0xEAD6, 0x7E1B, 0xBFA3, + 0x7E1C, 0xEAD4, 0x7E1D, 0xBFA6, 0x7E1E, 0xBFA5, 0x7E1F, 0xEAD0, 0x7E20, 0xEAD1, 0x7E21, 0xEACD, 0x7E22, 0xEAD7, 0x7E23, 0xBFA4, + 0x7E24, 0xEADE, 0x7E25, 0xEADD, 0x7E29, 0xEDDA, 0x7E2A, 0xEDD6, 0x7E2B, 0xC15F, 0x7E2D, 0xEDD0, 0x7E2E, 0xC159, 0x7E2F, 0xC169, + 0x7E30, 0xEDDC, 0x7E31, 0xC161, 0x7E32, 0xC15D, 0x7E33, 0xEDD3, 0x7E34, 0xC164, 0x7E35, 0xC167, 0x7E36, 0xEDDE, 0x7E37, 0xC15C, + 0x7E38, 0xEDD5, 0x7E39, 0xC165, 0x7E3A, 0xEDE0, 0x7E3B, 0xEDDD, 0x7E3C, 0xEDD1, 0x7E3D, 0xC160, 0x7E3E, 0xC15A, 0x7E3F, 0xC168, + 0x7E40, 0xEDD8, 0x7E41, 0xC163, 0x7E42, 0xEDD2, 0x7E43, 0xC15E, 0x7E44, 0xEDDF, 0x7E45, 0xC162, 0x7E46, 0xC15B, 0x7E47, 0xEDD9, + 0x7E48, 0xC166, 0x7E49, 0xEDD7, 0x7E4C, 0xEDDB, 0x7E50, 0xF06E, 0x7E51, 0xF074, 0x7E52, 0xC2B9, 0x7E53, 0xF077, 0x7E54, 0xC2B4, + 0x7E55, 0xC2B5, 0x7E56, 0xF06F, 0x7E57, 0xF076, 0x7E58, 0xF071, 0x7E59, 0xC2BA, 0x7E5A, 0xC2B7, 0x7E5C, 0xF06D, 0x7E5E, 0xC2B6, + 0x7E5F, 0xF073, 0x7E60, 0xF075, 0x7E61, 0xC2B8, 0x7E62, 0xF072, 0x7E63, 0xF070, 0x7E68, 0xF2B8, 0x7E69, 0xC3B7, 0x7E6A, 0xC3B8, + 0x7E6B, 0xC3B4, 0x7E6D, 0xC3B5, 0x7E6F, 0xF2B4, 0x7E70, 0xF2B2, 0x7E72, 0xF2B6, 0x7E73, 0xC3BA, 0x7E74, 0xF2B7, 0x7E75, 0xF2B0, + 0x7E76, 0xF2AF, 0x7E77, 0xF2B3, 0x7E78, 0xF2B1, 0x7E79, 0xC3B6, 0x7E7A, 0xF2B5, 0x7E7B, 0xF4AC, 0x7E7C, 0xC47E, 0x7E7D, 0xC47D, + 0x7E7E, 0xF4AD, 0x7E80, 0xF4AF, 0x7E81, 0xF4AE, 0x7E82, 0xC4A1, 0x7E86, 0xF5EB, 0x7E87, 0xF5E8, 0x7E88, 0xF5E9, 0x7E8A, 0xF5E7, + 0x7E8B, 0xF5EA, 0x7E8C, 0xC4F2, 0x7E8D, 0xF5EC, 0x7E8F, 0xC4F1, 0x7E91, 0xF742, 0x7E93, 0xC5D5, 0x7E94, 0xC5D7, 0x7E95, 0xF7EE, + 0x7E96, 0xC5D6, 0x7E97, 0xF8B9, 0x7E98, 0xF940, 0x7E99, 0xF942, 0x7E9A, 0xF8FE, 0x7E9B, 0xF941, 0x7E9C, 0xC66C, 0x7F36, 0xA6CE, + 0x7F38, 0xACFB, 0x7F39, 0xD26F, 0x7F3A, 0xAFCA, 0x7F3D, 0xB2DA, 0x7F3E, 0xDAFC, 0x7F3F, 0xDAFD, 0x7F43, 0xEADF, 0x7F44, 0xC16A, + 0x7F45, 0xEDE1, 0x7F48, 0xC2BB, 0x7F4A, 0xF2BA, 0x7F4B, 0xF2B9, 0x7F4C, 0xC4A2, 0x7F4D, 0xF5ED, 0x7F4F, 0xF743, 0x7F50, 0xC5F8, + 0x7F51, 0xCA49, 0x7F54, 0xAAC9, 0x7F55, 0xA875, 0x7F58, 0xD04D, 0x7F5B, 0xD360, 0x7F5C, 0xD35B, 0x7F5D, 0xD35F, 0x7F5E, 0xD35D, + 0x7F5F, 0xAFCB, 0x7F60, 0xD35E, 0x7F61, 0xD35C, 0x7F63, 0xD6F1, 0x7F65, 0xDAFE, 0x7F66, 0xDB40, 0x7F67, 0xDF69, 0x7F68, 0xDF6A, + 0x7F69, 0xB86E, 0x7F6A, 0xB86F, 0x7F6B, 0xDF68, 0x7F6C, 0xDF6B, 0x7F6D, 0xDF67, 0x7F6E, 0xB86D, 0x7F70, 0xBB40, 0x7F72, 0xB870, + 0x7F73, 0xE37A, 0x7F75, 0xBD7C, 0x7F76, 0xE6F1, 0x7F77, 0xBD7D, 0x7F79, 0xBFA9, 0x7F7A, 0xEAE2, 0x7F7B, 0xEAE0, 0x7F7C, 0xEAE1, + 0x7F7D, 0xEDE4, 0x7F7E, 0xEDE3, 0x7F7F, 0xEDE2, 0x7F83, 0xF2BB, 0x7F85, 0xC3B9, 0x7F86, 0xF2BC, 0x7F87, 0xF744, 0x7F88, 0xC5F9, + 0x7F89, 0xF8BA, 0x7F8A, 0xA6CF, 0x7F8B, 0xAACB, 0x7F8C, 0xAACA, 0x7F8D, 0xD04F, 0x7F8E, 0xACFC, 0x7F91, 0xD04E, 0x7F92, 0xD362, + 0x7F94, 0xAFCC, 0x7F95, 0xD6F2, 0x7F96, 0xD361, 0x7F9A, 0xB2DC, 0x7F9B, 0xD6F5, 0x7F9C, 0xD6F3, 0x7F9D, 0xD6F4, 0x7F9E, 0xB2DB, + 0x7FA0, 0xDB42, 0x7FA1, 0xDB43, 0x7FA2, 0xDB41, 0x7FA4, 0xB873, 0x7FA5, 0xDF6D, 0x7FA6, 0xDF6C, 0x7FA7, 0xDF6E, 0x7FA8, 0xB872, + 0x7FA9, 0xB871, 0x7FAC, 0xE6F2, 0x7FAD, 0xE6F4, 0x7FAF, 0xBD7E, 0x7FB0, 0xE6F3, 0x7FB1, 0xEAE3, 0x7FB2, 0xBFAA, 0x7FB3, 0xF079, + 0x7FB5, 0xF078, 0x7FB6, 0xC3BB, 0x7FB7, 0xF2BD, 0x7FB8, 0xC3BD, 0x7FB9, 0xC3BC, 0x7FBA, 0xF4B0, 0x7FBB, 0xF5EE, 0x7FBC, 0xC4F3, + 0x7FBD, 0xA6D0, 0x7FBE, 0xD050, 0x7FBF, 0xACFD, 0x7FC0, 0xD365, 0x7FC1, 0xAFCE, 0x7FC2, 0xD364, 0x7FC3, 0xD363, 0x7FC5, 0xAFCD, + 0x7FC7, 0xD6FB, 0x7FC9, 0xD6FD, 0x7FCA, 0xD6F6, 0x7FCB, 0xD6F7, 0x7FCC, 0xB2DD, 0x7FCD, 0xD6F8, 0x7FCE, 0xB2DE, 0x7FCF, 0xD6FC, + 0x7FD0, 0xD6F9, 0x7FD1, 0xD6FA, 0x7FD2, 0xB2DF, 0x7FD4, 0xB5BE, 0x7FD5, 0xB5BF, 0x7FD7, 0xDB44, 0x7FDB, 0xDF6F, 0x7FDC, 0xDF70, + 0x7FDE, 0xE37E, 0x7FDF, 0xBB43, 0x7FE0, 0xBB41, 0x7FE1, 0xBB42, 0x7FE2, 0xE37B, 0x7FE3, 0xE37C, 0x7FE5, 0xE37D, 0x7FE6, 0xE6F9, + 0x7FE8, 0xE6FA, 0x7FE9, 0xBDA1, 0x7FEA, 0xE6F7, 0x7FEB, 0xE6F6, 0x7FEC, 0xE6F8, 0x7FED, 0xE6F5, 0x7FEE, 0xBFAD, 0x7FEF, 0xEAE4, + 0x7FF0, 0xBFAB, 0x7FF1, 0xBFAC, 0x7FF2, 0xEDE6, 0x7FF3, 0xC16B, 0x7FF4, 0xEDE5, 0x7FF5, 0xEFA8, 0x7FF7, 0xF07A, 0x7FF8, 0xF07B, + 0x7FF9, 0xC2BC, 0x7FFB, 0xC2BD, 0x7FFC, 0xC16C, 0x7FFD, 0xF2BE, 0x7FFE, 0xF2BF, 0x7FFF, 0xF4B1, 0x8000, 0xC4A3, 0x8001, 0xA6D1, + 0x8003, 0xA6D2, 0x8004, 0xACFE, 0x8005, 0xAACC, 0x8006, 0xAFCF, 0x8007, 0xD051, 0x800B, 0xB5C0, 0x800C, 0xA6D3, 0x800D, 0xAD41, + 0x800E, 0xD052, 0x800F, 0xD053, 0x8010, 0xAD40, 0x8011, 0xAD42, 0x8012, 0xA6D4, 0x8014, 0xD054, 0x8015, 0xAFD1, 0x8016, 0xD366, + 0x8017, 0xAFD3, 0x8018, 0xAFD0, 0x8019, 0xAFD2, 0x801B, 0xD741, 0x801C, 0xB2E0, 0x801E, 0xD740, 0x801F, 0xD6FE, 0x8021, 0xDF71, + 0x8024, 0xE3A1, 0x8026, 0xBDA2, 0x8028, 0xBFAE, 0x8029, 0xEAE6, 0x802A, 0xEAE5, 0x802C, 0xEDE7, 0x8030, 0xF5EF, 0x8033, 0xA6D5, + 0x8034, 0xCB73, 0x8035, 0xCDAA, 0x8036, 0xAD43, 0x8037, 0xD055, 0x8039, 0xD368, 0x803D, 0xAFD4, 0x803E, 0xD367, 0x803F, 0xAFD5, + 0x8043, 0xD743, 0x8046, 0xB2E2, 0x8047, 0xD742, 0x8048, 0xD744, 0x804A, 0xB2E1, 0x804F, 0xDB46, 0x8050, 0xDB47, 0x8051, 0xDB45, + 0x8052, 0xB5C1, 0x8056, 0xB874, 0x8058, 0xB875, 0x805A, 0xBB45, 0x805C, 0xE3A3, 0x805D, 0xE3A2, 0x805E, 0xBB44, 0x8064, 0xE6FB, + 0x8067, 0xE6FC, 0x806C, 0xEAE7, 0x806F, 0xC170, 0x8070, 0xC16F, 0x8071, 0xC16D, 0x8072, 0xC16E, 0x8073, 0xC171, 0x8075, 0xF07C, + 0x8076, 0xC2BF, 0x8077, 0xC2BE, 0x8078, 0xF2C0, 0x8079, 0xF4B2, 0x807D, 0xC5A5, 0x807E, 0xC5A4, 0x807F, 0xA6D6, 0x8082, 0xD1FB, + 0x8084, 0xB877, 0x8085, 0xB5C2, 0x8086, 0xB876, 0x8087, 0xBB46, 0x8089, 0xA6D7, 0x808A, 0xC9A9, 0x808B, 0xA6D8, 0x808C, 0xA6D9, + 0x808F, 0xCDAB, 0x8090, 0xCB76, 0x8092, 0xCB77, 0x8093, 0xA877, 0x8095, 0xCB74, 0x8096, 0xA876, 0x8098, 0xA879, 0x8099, 0xCB75, + 0x809A, 0xA87B, 0x809B, 0xA87A, 0x809C, 0xCB78, 0x809D, 0xA878, 0x80A1, 0xAAD1, 0x80A2, 0xAACF, 0x80A3, 0xCDAD, 0x80A5, 0xAACE, + 0x80A9, 0xAAD3, 0x80AA, 0xAAD5, 0x80AB, 0xAAD2, 0x80AD, 0xCDB0, 0x80AE, 0xCDAC, 0x80AF, 0xAAD6, 0x80B1, 0xAAD0, 0x80B2, 0xA87C, + 0x80B4, 0xAAD4, 0x80B5, 0xCDAF, 0x80B8, 0xCDAE, 0x80BA, 0xAACD, 0x80C2, 0xD05B, 0x80C3, 0xAD47, 0x80C4, 0xAD48, 0x80C5, 0xD05D, + 0x80C7, 0xD057, 0x80C8, 0xD05A, 0x80C9, 0xD063, 0x80CA, 0xD061, 0x80CC, 0xAD49, 0x80CD, 0xD067, 0x80CE, 0xAD4C, 0x80CF, 0xD064, + 0x80D0, 0xD05C, 0x80D1, 0xD059, 0x80D4, 0xDB49, 0x80D5, 0xD062, 0x80D6, 0xAD44, 0x80D7, 0xD065, 0x80D8, 0xD056, 0x80D9, 0xD05F, + 0x80DA, 0xAD46, 0x80DB, 0xAD4B, 0x80DC, 0xD060, 0x80DD, 0xAD4F, 0x80DE, 0xAD4D, 0x80E0, 0xD058, 0x80E1, 0xAD4A, 0x80E3, 0xD05E, + 0x80E4, 0xAD4E, 0x80E5, 0xAD45, 0x80E6, 0xD066, 0x80ED, 0xAFDA, 0x80EF, 0xAFE3, 0x80F0, 0xAFD8, 0x80F1, 0xAFD6, 0x80F2, 0xD36A, + 0x80F3, 0xAFDE, 0x80F4, 0xAFDB, 0x80F5, 0xD36C, 0x80F8, 0xAFDD, 0x80F9, 0xD36B, 0x80FA, 0xD369, 0x80FB, 0xD36E, 0x80FC, 0xAFE2, + 0x80FD, 0xAFE0, 0x80FE, 0xDB48, 0x8100, 0xD36F, 0x8101, 0xD36D, 0x8102, 0xAFD7, 0x8105, 0xAFD9, 0x8106, 0xAFDC, 0x8108, 0xAFDF, + 0x810A, 0xAFE1, 0x8115, 0xD74E, 0x8116, 0xB2E4, 0x8118, 0xD745, 0x8119, 0xD747, 0x811B, 0xD748, 0x811D, 0xD750, 0x811E, 0xD74C, + 0x811F, 0xD74A, 0x8121, 0xD74D, 0x8122, 0xD751, 0x8123, 0xB2E5, 0x8124, 0xB2E9, 0x8125, 0xD746, 0x8127, 0xD74F, 0x8129, 0xB2E7, + 0x812B, 0xB2E6, 0x812C, 0xD74B, 0x812D, 0xD749, 0x812F, 0xB2E3, 0x8130, 0xB2E8, 0x8139, 0xB5C8, 0x813A, 0xDB51, 0x813D, 0xDB4F, + 0x813E, 0xB5CA, 0x8143, 0xDB4A, 0x8144, 0xDFA1, 0x8146, 0xB5C9, 0x8147, 0xDB4E, 0x814A, 0xDB4B, 0x814B, 0xB5C5, 0x814C, 0xB5CB, + 0x814D, 0xDB50, 0x814E, 0xB5C7, 0x814F, 0xDB4D, 0x8150, 0xBB47, 0x8151, 0xB5C6, 0x8152, 0xDB4C, 0x8153, 0xB5CC, 0x8154, 0xB5C4, + 0x8155, 0xB5C3, 0x815B, 0xDF77, 0x815C, 0xDF75, 0x815E, 0xDF7B, 0x8160, 0xDF73, 0x8161, 0xDFA2, 0x8162, 0xDF78, 0x8164, 0xDF72, + 0x8165, 0xB87B, 0x8166, 0xB8A3, 0x8167, 0xDF7D, 0x8169, 0xDF76, 0x816B, 0xB87E, 0x816E, 0xB87C, 0x816F, 0xDF7E, 0x8170, 0xB879, + 0x8171, 0xB878, 0x8172, 0xDF79, 0x8173, 0xB87D, 0x8174, 0xB5CD, 0x8176, 0xDF7C, 0x8177, 0xDF74, 0x8178, 0xB87A, 0x8179, 0xB8A1, + 0x817A, 0xB8A2, 0x817F, 0xBB4C, 0x8180, 0xBB48, 0x8182, 0xBB4D, 0x8183, 0xE3A6, 0x8186, 0xE3A5, 0x8187, 0xE3A7, 0x8188, 0xBB4A, + 0x8189, 0xE3A4, 0x818A, 0xBB4B, 0x818B, 0xE3AA, 0x818C, 0xE3A9, 0x818D, 0xE3A8, 0x818F, 0xBB49, 0x8195, 0xE741, 0x8197, 0xE744, + 0x8198, 0xBDA8, 0x8199, 0xE743, 0x819A, 0xBDA7, 0x819B, 0xBDA3, 0x819C, 0xBDA4, 0x819D, 0xBDA5, 0x819E, 0xE740, 0x819F, 0xE6FE, + 0x81A0, 0xBDA6, 0x81A2, 0xE742, 0x81A3, 0xE6FD, 0x81A6, 0xEAE9, 0x81A7, 0xEAF3, 0x81A8, 0xBFB1, 0x81A9, 0xBFB0, 0x81AB, 0xEAED, + 0x81AC, 0xEAEF, 0x81AE, 0xEAEA, 0x81B0, 0xEAEE, 0x81B1, 0xEAE8, 0x81B2, 0xEAF1, 0x81B3, 0xBFAF, 0x81B4, 0xEAF0, 0x81B5, 0xEAEC, + 0x81B7, 0xEAF2, 0x81B9, 0xEAEB, 0x81BA, 0xC174, 0x81BB, 0xEDE8, 0x81BC, 0xEDEE, 0x81BD, 0xC178, 0x81BE, 0xC17A, 0x81BF, 0xC177, + 0x81C0, 0xC176, 0x81C2, 0xC175, 0x81C3, 0xC173, 0x81C4, 0xEDE9, 0x81C5, 0xEDEC, 0x81C6, 0xC172, 0x81C7, 0xEDED, 0x81C9, 0xC179, + 0x81CA, 0xEDEB, 0x81CC, 0xEDEA, 0x81CD, 0xC2C0, 0x81CF, 0xC2C1, 0x81D0, 0xF0A1, 0x81D1, 0xF07D, 0x81D2, 0xF07E, 0x81D5, 0xF2C2, + 0x81D7, 0xF2C1, 0x81D8, 0xC3BE, 0x81D9, 0xF4B4, 0x81DA, 0xC4A4, 0x81DB, 0xF4B3, 0x81DD, 0xF5F0, 0x81DE, 0xF745, 0x81DF, 0xC5A6, + 0x81E0, 0xF943, 0x81E1, 0xF944, 0x81E2, 0xC5D8, 0x81E3, 0xA6DA, 0x81E5, 0xAAD7, 0x81E6, 0xDB52, 0x81E7, 0xBB4E, 0x81E8, 0xC17B, + 0x81E9, 0xEDEF, 0x81EA, 0xA6DB, 0x81EC, 0xAFE5, 0x81ED, 0xAFE4, 0x81EE, 0xDB53, 0x81F2, 0xEAF4, 0x81F3, 0xA6DC, 0x81F4, 0xAD50, + 0x81F7, 0xDB54, 0x81F8, 0xDB55, 0x81F9, 0xDB56, 0x81FA, 0xBB4F, 0x81FB, 0xBFB2, 0x81FC, 0xA6DD, 0x81FE, 0xAAD8, 0x81FF, 0xD068, + 0x8200, 0xAFE6, 0x8201, 0xD370, 0x8202, 0xB2EA, 0x8204, 0xDB57, 0x8205, 0xB8A4, 0x8207, 0xBB50, 0x8208, 0xBFB3, 0x8209, 0xC17C, + 0x820A, 0xC2C2, 0x820B, 0xF4B5, 0x820C, 0xA6DE, 0x820D, 0xAAD9, 0x8210, 0xAFE7, 0x8211, 0xD752, 0x8212, 0xB5CE, 0x8214, 0xBB51, + 0x8215, 0xE3AB, 0x8216, 0xE745, 0x821B, 0xA6DF, 0x821C, 0xB5CF, 0x821D, 0xDFA3, 0x821E, 0xBB52, 0x821F, 0xA6E0, 0x8220, 0xCDB1, + 0x8221, 0xD069, 0x8222, 0xAD51, 0x8225, 0xD372, 0x8228, 0xAFEA, 0x822A, 0xAFE8, 0x822B, 0xAFE9, 0x822C, 0xAFEB, 0x822F, 0xD371, + 0x8232, 0xD757, 0x8233, 0xD754, 0x8234, 0xD756, 0x8235, 0xB2EB, 0x8236, 0xB2ED, 0x8237, 0xB2EC, 0x8238, 0xD753, 0x8239, 0xB2EE, + 0x823A, 0xD755, 0x823C, 0xDB58, 0x823D, 0xDB59, 0x823F, 0xDB5A, 0x8240, 0xDFA6, 0x8242, 0xDFA7, 0x8244, 0xDFA5, 0x8245, 0xDFA8, + 0x8247, 0xB8A5, 0x8249, 0xDFA4, 0x824B, 0xBB53, 0x824E, 0xE74A, 0x824F, 0xE746, 0x8250, 0xE749, 0x8251, 0xE74B, 0x8252, 0xE748, + 0x8253, 0xE747, 0x8255, 0xEAF5, 0x8256, 0xEAF6, 0x8257, 0xEAF7, 0x8258, 0xBFB4, 0x8259, 0xBFB5, 0x825A, 0xEDF1, 0x825B, 0xEDF0, + 0x825C, 0xEDF2, 0x825E, 0xF0A3, 0x825F, 0xF0A2, 0x8261, 0xF2C4, 0x8263, 0xF2C5, 0x8264, 0xF2C3, 0x8266, 0xC4A5, 0x8268, 0xF4B6, + 0x8269, 0xF4B7, 0x826B, 0xF746, 0x826C, 0xF7EF, 0x826D, 0xF8BB, 0x826E, 0xA6E1, 0x826F, 0xA87D, 0x8271, 0xC17D, 0x8272, 0xA6E2, + 0x8274, 0xD758, 0x8275, 0xDB5B, 0x8277, 0xC641, 0x8278, 0xCA4A, 0x827C, 0xCA4B, 0x827D, 0xCA4D, 0x827E, 0xA6E3, 0x827F, 0xCA4E, + 0x8280, 0xCA4C, 0x8283, 0xCBA2, 0x8284, 0xCBA3, 0x8285, 0xCB7B, 0x828A, 0xCBA1, 0x828B, 0xA8A1, 0x828D, 0xA8A2, 0x828E, 0xCB7C, + 0x828F, 0xCB7A, 0x8290, 0xCB79, 0x8291, 0xCB7D, 0x8292, 0xA87E, 0x8293, 0xCB7E, 0x8294, 0xD06A, 0x8298, 0xCDB6, 0x8299, 0xAADC, + 0x829A, 0xCDB5, 0x829B, 0xCDB7, 0x829D, 0xAADB, 0x829E, 0xCDBC, 0x829F, 0xAADF, 0x82A0, 0xCDB2, 0x82A1, 0xCDC0, 0x82A2, 0xCDC6, + 0x82A3, 0xAAE6, 0x82A4, 0xCDC3, 0x82A5, 0xAAE3, 0x82A7, 0xCDB9, 0x82A8, 0xCDBF, 0x82A9, 0xCDC1, 0x82AB, 0xCDB4, 0x82AC, 0xAAE2, + 0x82AD, 0xAADD, 0x82AE, 0xCDBA, 0x82AF, 0xAAE4, 0x82B0, 0xAAE7, 0x82B1, 0xAAE1, 0x82B3, 0xAADA, 0x82B4, 0xCDBE, 0x82B5, 0xCDB8, + 0x82B6, 0xCDC5, 0x82B7, 0xAAE9, 0x82B8, 0xAAE5, 0x82B9, 0xAAE0, 0x82BA, 0xCDBD, 0x82BB, 0xAFEC, 0x82BC, 0xCDBB, 0x82BD, 0xAADE, + 0x82BE, 0xAAE8, 0x82C0, 0xCDB3, 0x82C2, 0xCDC2, 0x82C3, 0xCDC4, 0x82D1, 0xAD62, 0x82D2, 0xAD5C, 0x82D3, 0xAD64, 0x82D4, 0xAD61, + 0x82D5, 0xD071, 0x82D6, 0xD074, 0x82D7, 0xAD5D, 0x82D9, 0xD06B, 0x82DB, 0xAD56, 0x82DC, 0xAD60, 0x82DE, 0xAD63, 0x82DF, 0xAD65, + 0x82E0, 0xD0A2, 0x82E1, 0xD077, 0x82E3, 0xAD55, 0x82E4, 0xD0A1, 0x82E5, 0xAD59, 0x82E6, 0xAD57, 0x82E7, 0xAD52, 0x82E8, 0xD06F, + 0x82EA, 0xD07E, 0x82EB, 0xD073, 0x82EC, 0xD076, 0x82ED, 0xD0A5, 0x82EF, 0xAD66, 0x82F0, 0xD07D, 0x82F1, 0xAD5E, 0x82F2, 0xD078, + 0x82F3, 0xD0A4, 0x82F4, 0xD075, 0x82F5, 0xD079, 0x82F6, 0xD07C, 0x82F9, 0xD06D, 0x82FA, 0xD0A3, 0x82FB, 0xD07B, 0x82FE, 0xD06C, + 0x8300, 0xD070, 0x8301, 0xAD5F, 0x8302, 0xAD5A, 0x8303, 0xAD53, 0x8304, 0xAD58, 0x8305, 0xAD54, 0x8306, 0xAD67, 0x8307, 0xD06E, + 0x8308, 0xD3A5, 0x8309, 0xAD5B, 0x830C, 0xD07A, 0x830D, 0xCE41, 0x8316, 0xD3A8, 0x8317, 0xAFFA, 0x8319, 0xD376, 0x831B, 0xD3A3, + 0x831C, 0xD37D, 0x831E, 0xD3B2, 0x8320, 0xD3AA, 0x8322, 0xD37E, 0x8324, 0xD3A9, 0x8325, 0xD378, 0x8326, 0xD37C, 0x8327, 0xD3B5, + 0x8328, 0xAFFD, 0x8329, 0xD3AD, 0x832A, 0xD3A4, 0x832B, 0xAFED, 0x832C, 0xD3B3, 0x832D, 0xD374, 0x832F, 0xD3AC, 0x8331, 0xAFFC, + 0x8332, 0xAFF7, 0x8333, 0xD373, 0x8334, 0xAFF5, 0x8335, 0xAFF4, 0x8336, 0xAFF9, 0x8337, 0xD3AB, 0x8338, 0xAFF1, 0x8339, 0xAFF8, + 0x833A, 0xD072, 0x833B, 0xDB5C, 0x833C, 0xD3A6, 0x833F, 0xD37A, 0x8340, 0xAFFB, 0x8341, 0xD37B, 0x8342, 0xD3A1, 0x8343, 0xAFFE, + 0x8344, 0xD375, 0x8345, 0xD3AF, 0x8347, 0xD3AE, 0x8348, 0xD3B6, 0x8349, 0xAFF3, 0x834A, 0xAFF0, 0x834B, 0xD3B4, 0x834C, 0xD3B0, + 0x834D, 0xD3A7, 0x834E, 0xD3A2, 0x834F, 0xAFF6, 0x8350, 0xAFF2, 0x8351, 0xD377, 0x8352, 0xAFEE, 0x8353, 0xD3B1, 0x8354, 0xAFEF, + 0x8356, 0xD379, 0x8373, 0xD75E, 0x8374, 0xD760, 0x8375, 0xD765, 0x8376, 0xD779, 0x8377, 0xB2FC, 0x8378, 0xB2F2, 0x837A, 0xD75D, + 0x837B, 0xB2FD, 0x837C, 0xB2FE, 0x837D, 0xD768, 0x837E, 0xD76F, 0x837F, 0xD775, 0x8381, 0xD762, 0x8383, 0xD769, 0x8386, 0xB340, + 0x8387, 0xD777, 0x8388, 0xD772, 0x8389, 0xB2FA, 0x838A, 0xB2F8, 0x838B, 0xD76E, 0x838C, 0xD76A, 0x838D, 0xD75C, 0x838E, 0xB2EF, + 0x838F, 0xD761, 0x8390, 0xD759, 0x8392, 0xB2F7, 0x8393, 0xB2F9, 0x8394, 0xD766, 0x8395, 0xD763, 0x8396, 0xB2F4, 0x8397, 0xD773, + 0x8398, 0xB2F1, 0x8399, 0xD764, 0x839A, 0xD77A, 0x839B, 0xD76C, 0x839D, 0xD76B, 0x839E, 0xB2F0, 0x83A0, 0xB2FB, 0x83A2, 0xB2F3, + 0x83A3, 0xD75A, 0x83A4, 0xD75F, 0x83A5, 0xD770, 0x83A6, 0xD776, 0x83A7, 0xB341, 0x83A8, 0xD75B, 0x83A9, 0xD767, 0x83AA, 0xD76D, + 0x83AB, 0xB2F6, 0x83AE, 0xD778, 0x83AF, 0xD771, 0x83B0, 0xD774, 0x83BD, 0xB2F5, 0x83BF, 0xDB6C, 0x83C0, 0xDB60, 0x83C1, 0xB5D7, + 0x83C2, 0xDB7D, 0x83C3, 0xDBA7, 0x83C4, 0xDBAA, 0x83C5, 0xB5D5, 0x83C6, 0xDB68, 0x83C7, 0xDBA3, 0x83C8, 0xDB69, 0x83C9, 0xDB77, + 0x83CA, 0xB5E2, 0x83CB, 0xDB73, 0x83CC, 0xB5DF, 0x83CE, 0xDB74, 0x83CF, 0xDB5D, 0x83D1, 0xDBA4, 0x83D4, 0xB5E8, 0x83D5, 0xDBA1, + 0x83D6, 0xDB75, 0x83D7, 0xDBAC, 0x83D8, 0xDB70, 0x83D9, 0xDFC8, 0x83DB, 0xDBAF, 0x83DC, 0xB5E6, 0x83DD, 0xDB6E, 0x83DE, 0xDB7A, + 0x83DF, 0xB5E9, 0x83E0, 0xB5D4, 0x83E1, 0xDB72, 0x83E2, 0xDBAD, 0x83E3, 0xDB6B, 0x83E4, 0xDB64, 0x83E5, 0xDB6F, 0x83E7, 0xDB63, + 0x83E8, 0xDB61, 0x83E9, 0xB5D0, 0x83EA, 0xDBA5, 0x83EB, 0xDB6A, 0x83EC, 0xDBA8, 0x83EE, 0xDBA9, 0x83EF, 0xB5D8, 0x83F0, 0xB5DD, + 0x83F1, 0xB5D9, 0x83F2, 0xB5E1, 0x83F3, 0xDB7E, 0x83F4, 0xB5DA, 0x83F5, 0xDB76, 0x83F6, 0xDB66, 0x83F8, 0xB5D2, 0x83F9, 0xDB5E, + 0x83FA, 0xDBA2, 0x83FB, 0xDBAB, 0x83FC, 0xDB65, 0x83FD, 0xB5E0, 0x83FE, 0xDBB0, 0x83FF, 0xDB71, 0x8401, 0xDB6D, 0x8403, 0xB5D1, + 0x8404, 0xB5E5, 0x8406, 0xDB7C, 0x8407, 0xB5E7, 0x8409, 0xDB78, 0x840A, 0xB5DC, 0x840B, 0xB5D6, 0x840C, 0xB5DE, 0x840D, 0xB5D3, + 0x840E, 0xB5E4, 0x840F, 0xDB79, 0x8410, 0xDB67, 0x8411, 0xDB7B, 0x8412, 0xDB62, 0x8413, 0xDBA6, 0x841B, 0xDBAE, 0x8423, 0xDB5F, + 0x8429, 0xDFC7, 0x842B, 0xDFDD, 0x842C, 0xB855, 0x842D, 0xDFCC, 0x842F, 0xDFCA, 0x8430, 0xDFB5, 0x8431, 0xB8A9, 0x8432, 0xDFC5, + 0x8433, 0xDFD9, 0x8434, 0xDFC1, 0x8435, 0xB8B1, 0x8436, 0xDFD8, 0x8437, 0xDFBF, 0x8438, 0xB5E3, 0x8439, 0xDFCF, 0x843A, 0xDFC0, + 0x843B, 0xDFD6, 0x843C, 0xB8B0, 0x843D, 0xB8A8, 0x843F, 0xDFAA, 0x8440, 0xDFB2, 0x8442, 0xDFCB, 0x8443, 0xDFC3, 0x8444, 0xDFDC, + 0x8445, 0xDFC6, 0x8446, 0xB8B6, 0x8447, 0xDFD7, 0x8449, 0xB8AD, 0x844B, 0xDFC9, 0x844C, 0xDFD1, 0x844D, 0xDFB6, 0x844E, 0xDFD0, + 0x8450, 0xDFE1, 0x8451, 0xDFB1, 0x8452, 0xDFD2, 0x8454, 0xDFDF, 0x8456, 0xDFAB, 0x8457, 0xB5DB, 0x8459, 0xDFB9, 0x845A, 0xDFB8, + 0x845B, 0xB8AF, 0x845D, 0xDFBC, 0x845E, 0xDFBE, 0x845F, 0xDFCD, 0x8460, 0xDFDE, 0x8461, 0xB8B2, 0x8463, 0xB8B3, 0x8465, 0xDFB0, + 0x8466, 0xB8AB, 0x8467, 0xDFB4, 0x8468, 0xDFDA, 0x8469, 0xB8B4, 0x846B, 0xB8AC, 0x846C, 0xB8AE, 0x846D, 0xB8B5, 0x846E, 0xDFE0, + 0x846F, 0xDFD3, 0x8470, 0xDFCE, 0x8473, 0xDFBB, 0x8474, 0xDFBA, 0x8475, 0xB8AA, 0x8476, 0xDFAC, 0x8477, 0xB8A7, 0x8478, 0xDFC4, + 0x8479, 0xDFAD, 0x847A, 0xDFC2, 0x847D, 0xDFB7, 0x847E, 0xDFDB, 0x8482, 0xB8A6, 0x8486, 0xDFB3, 0x848D, 0xDFAF, 0x848E, 0xDFD5, + 0x848F, 0xDFAE, 0x8490, 0xBB60, 0x8491, 0xE3D3, 0x8494, 0xE3C2, 0x8497, 0xE3AC, 0x8498, 0xE3CA, 0x8499, 0xBB58, 0x849A, 0xE3BB, + 0x849B, 0xE3C5, 0x849C, 0xBB5B, 0x849D, 0xE3BE, 0x849E, 0xBB59, 0x849F, 0xE3AF, 0x84A0, 0xE3CD, 0x84A1, 0xE3AE, 0x84A2, 0xE3C1, + 0x84A4, 0xE3AD, 0x84A7, 0xE3BF, 0x84A8, 0xE3C8, 0x84A9, 0xE3C6, 0x84AA, 0xE3BA, 0x84AB, 0xE3B5, 0x84AC, 0xE3B3, 0x84AE, 0xE3B4, + 0x84AF, 0xE3C7, 0x84B0, 0xE3D2, 0x84B1, 0xE3BC, 0x84B2, 0xBB5A, 0x84B4, 0xE3B7, 0x84B6, 0xE3CB, 0x84B8, 0xBB5D, 0x84B9, 0xE3B6, + 0x84BA, 0xE3B0, 0x84BB, 0xE3C0, 0x84BC, 0xBB61, 0x84BF, 0xBB55, 0x84C0, 0xBB5E, 0x84C1, 0xE3B8, 0x84C2, 0xE3B2, 0x84C4, 0xBB57, + 0x84C5, 0xDFD4, 0x84C6, 0xBB56, 0x84C7, 0xE3C3, 0x84C9, 0xBB54, 0x84CA, 0xBB63, 0x84CB, 0xBB5C, 0x84CC, 0xE3C4, 0x84CD, 0xE3B9, + 0x84CE, 0xE3B1, 0x84CF, 0xE3CC, 0x84D0, 0xE3BD, 0x84D1, 0xBB62, 0x84D2, 0xE3D0, 0x84D3, 0xBB5F, 0x84D4, 0xE3CF, 0x84D6, 0xE3C9, + 0x84D7, 0xE3CE, 0x84DB, 0xE3D1, 0x84E7, 0xE773, 0x84E8, 0xE774, 0x84E9, 0xE767, 0x84EA, 0xE766, 0x84EB, 0xE762, 0x84EC, 0xBDB4, + 0x84EE, 0xBDAC, 0x84EF, 0xE776, 0x84F0, 0xE775, 0x84F1, 0xDFA9, 0x84F2, 0xE75F, 0x84F3, 0xE763, 0x84F4, 0xE75D, 0x84F6, 0xE770, + 0x84F7, 0xE761, 0x84F9, 0xE777, 0x84FA, 0xE75A, 0x84FB, 0xE758, 0x84FC, 0xE764, 0x84FD, 0xE76E, 0x84FE, 0xE769, 0x84FF, 0xBDB6, + 0x8500, 0xE74F, 0x8502, 0xE76D, 0x8506, 0xBDB7, 0x8507, 0xDFBD, 0x8508, 0xE75B, 0x8509, 0xE752, 0x850A, 0xE755, 0x850B, 0xE77B, + 0x850C, 0xE75C, 0x850D, 0xE753, 0x850E, 0xE751, 0x850F, 0xE74E, 0x8511, 0xBDB0, 0x8512, 0xE765, 0x8513, 0xBDAF, 0x8514, 0xBDB3, + 0x8515, 0xE760, 0x8516, 0xE768, 0x8517, 0xBDA9, 0x8518, 0xE778, 0x8519, 0xE77C, 0x851A, 0xBDAB, 0x851C, 0xE757, 0x851D, 0xE76B, + 0x851E, 0xE76F, 0x851F, 0xE754, 0x8520, 0xE779, 0x8521, 0xBDB2, 0x8523, 0xBDB1, 0x8524, 0xE74C, 0x8525, 0xBDB5, 0x8526, 0xE772, + 0x8527, 0xE756, 0x8528, 0xE76A, 0x8529, 0xE750, 0x852A, 0xE75E, 0x852B, 0xE759, 0x852C, 0xBDAD, 0x852D, 0xBDAE, 0x852E, 0xE76C, + 0x852F, 0xE77D, 0x8530, 0xE77A, 0x8531, 0xE771, 0x853B, 0xE74D, 0x853D, 0xBDAA, 0x853E, 0xEB49, 0x8540, 0xEB40, 0x8541, 0xEB43, + 0x8543, 0xBFBB, 0x8544, 0xEB45, 0x8545, 0xEAF9, 0x8546, 0xEB41, 0x8547, 0xEB47, 0x8548, 0xBFB8, 0x8549, 0xBFBC, 0x854A, 0xBFB6, + 0x854D, 0xEAFB, 0x854E, 0xEB4C, 0x8551, 0xEB46, 0x8553, 0xEAFC, 0x8554, 0xEB55, 0x8555, 0xEB4F, 0x8556, 0xEAF8, 0x8557, 0xEE46, + 0x8558, 0xEAFE, 0x8559, 0xBFB7, 0x855B, 0xEB4A, 0x855D, 0xEB54, 0x855E, 0xBFBF, 0x8560, 0xEB51, 0x8561, 0xEAFD, 0x8562, 0xEB44, + 0x8563, 0xEB48, 0x8564, 0xEB42, 0x8565, 0xEB56, 0x8566, 0xEB53, 0x8567, 0xEB50, 0x8568, 0xBFB9, 0x8569, 0xBFBA, 0x856A, 0xBFBE, + 0x856B, 0xEAFA, 0x856C, 0xEB57, 0x856D, 0xBFBD, 0x856E, 0xEB4D, 0x8571, 0xEB4B, 0x8575, 0xEB4E, 0x8576, 0xEE53, 0x8577, 0xEE40, + 0x8578, 0xEE45, 0x8579, 0xEE52, 0x857A, 0xEE44, 0x857B, 0xEDFB, 0x857C, 0xEE41, 0x857E, 0xC1A2, 0x8580, 0xEDF4, 0x8581, 0xEE4D, + 0x8582, 0xEE4F, 0x8583, 0xEDF3, 0x8584, 0xC1A1, 0x8585, 0xEE51, 0x8586, 0xEE49, 0x8587, 0xC1A8, 0x8588, 0xEE50, 0x8589, 0xEE42, + 0x858A, 0xC1AA, 0x858B, 0xEDF9, 0x858C, 0xEB52, 0x858D, 0xEE4A, 0x858E, 0xEE47, 0x858F, 0xEDF5, 0x8590, 0xEE55, 0x8591, 0xC1A4, + 0x8594, 0xC1A5, 0x8595, 0xEDF7, 0x8596, 0xEE48, 0x8598, 0xEE54, 0x8599, 0xEE4B, 0x859A, 0xEDFD, 0x859B, 0xC1A7, 0x859C, 0xC1A3, + 0x859D, 0xEE4C, 0x859E, 0xEDFE, 0x859F, 0xEE56, 0x85A0, 0xEDF8, 0x85A1, 0xEE43, 0x85A2, 0xEE4E, 0x85A3, 0xEDFA, 0x85A4, 0xEDFC, + 0x85A6, 0xC2CB, 0x85A7, 0xEDF6, 0x85A8, 0xC1A9, 0x85A9, 0xC2C4, 0x85AA, 0xC17E, 0x85AF, 0xC1A6, 0x85B0, 0xC2C8, 0x85B1, 0xF0B3, + 0x85B3, 0xF0A9, 0x85B4, 0xF0A4, 0x85B5, 0xF0AA, 0x85B6, 0xF0B4, 0x85B7, 0xF0B8, 0x85B8, 0xF0B7, 0x85B9, 0xC2CA, 0x85BA, 0xC2C9, + 0x85BD, 0xF0AB, 0x85BE, 0xF0B9, 0x85BF, 0xF0AE, 0x85C0, 0xF0A6, 0x85C2, 0xF0A8, 0x85C3, 0xF0A7, 0x85C4, 0xF0AD, 0x85C5, 0xF0B2, + 0x85C6, 0xF0A5, 0x85C7, 0xF0AC, 0x85C8, 0xF0B1, 0x85C9, 0xC2C7, 0x85CB, 0xF0AF, 0x85CD, 0xC2C5, 0x85CE, 0xF0B0, 0x85CF, 0xC2C3, + 0x85D0, 0xC2C6, 0x85D1, 0xF2D5, 0x85D2, 0xF0B5, 0x85D5, 0xC3C2, 0x85D7, 0xF2CD, 0x85D8, 0xF2D1, 0x85D9, 0xF2C9, 0x85DA, 0xF2CC, + 0x85DC, 0xF2D4, 0x85DD, 0xC3C0, 0x85DE, 0xF2D9, 0x85DF, 0xF2D2, 0x85E1, 0xF2CA, 0x85E2, 0xF2DA, 0x85E3, 0xF2D3, 0x85E4, 0xC3C3, + 0x85E5, 0xC3C4, 0x85E6, 0xF2D7, 0x85E8, 0xF2CB, 0x85E9, 0xC3BF, 0x85EA, 0xC3C1, 0x85EB, 0xF2C6, 0x85EC, 0xF2CE, 0x85ED, 0xF2C8, + 0x85EF, 0xF2D8, 0x85F0, 0xF2D6, 0x85F1, 0xF2C7, 0x85F2, 0xF2CF, 0x85F6, 0xF4BE, 0x85F7, 0xC3C5, 0x85F8, 0xF2D0, 0x85F9, 0xC4A7, + 0x85FA, 0xC4A9, 0x85FB, 0xC4A6, 0x85FD, 0xF4C3, 0x85FE, 0xF4BB, 0x85FF, 0xF4B9, 0x8600, 0xF4BD, 0x8601, 0xF4BA, 0x8604, 0xF4BF, + 0x8605, 0xF4C1, 0x8606, 0xC4AA, 0x8607, 0xC4AC, 0x8609, 0xF4C0, 0x860A, 0xC4AD, 0x860B, 0xC4AB, 0x860C, 0xF4C2, 0x8611, 0xC4A8, + 0x8617, 0xC4F4, 0x8618, 0xF5F1, 0x8619, 0xF5F7, 0x861A, 0xC4F6, 0x861B, 0xF4BC, 0x861C, 0xF5F6, 0x861E, 0xF5FD, 0x861F, 0xF5F4, + 0x8620, 0xF5FB, 0x8621, 0xF5FA, 0x8622, 0xF4B8, 0x8623, 0xF5F5, 0x8624, 0xF0B6, 0x8625, 0xF5FE, 0x8626, 0xF5F3, 0x8627, 0xF5F8, + 0x8629, 0xF5FC, 0x862A, 0xF5F2, 0x862C, 0xF74A, 0x862D, 0xC4F5, 0x862E, 0xF5F9, 0x8631, 0xF7F4, 0x8632, 0xF74B, 0x8633, 0xF749, + 0x8634, 0xF747, 0x8635, 0xF748, 0x8636, 0xF74C, 0x8638, 0xC5D9, 0x8639, 0xF7F2, 0x863A, 0xF7F0, 0x863B, 0xF7F5, 0x863C, 0xF7F3, + 0x863E, 0xF7F6, 0x863F, 0xC5DA, 0x8640, 0xF7F1, 0x8643, 0xF8BC, 0x8646, 0xF945, 0x8647, 0xF946, 0x8648, 0xF947, 0x864B, 0xF9C7, + 0x864C, 0xF9BD, 0x864D, 0xCA4F, 0x864E, 0xAAEA, 0x8650, 0xAD68, 0x8652, 0xD3B8, 0x8653, 0xD3B7, 0x8654, 0xB040, 0x8655, 0xB342, + 0x8656, 0xD77C, 0x8659, 0xD77B, 0x865B, 0xB5EA, 0x865C, 0xB8B8, 0x865E, 0xB8B7, 0x865F, 0xB8B9, 0x8661, 0xE3D4, 0x8662, 0xE77E, + 0x8663, 0xEB58, 0x8664, 0xEB5A, 0x8665, 0xEB59, 0x8667, 0xC1AB, 0x8668, 0xEE57, 0x8669, 0xF0BA, 0x866A, 0xF9A5, 0x866B, 0xA6E4, + 0x866D, 0xCDC9, 0x866E, 0xCDCA, 0x866F, 0xCDC8, 0x8670, 0xCDC7, 0x8671, 0xAAEB, 0x8673, 0xD0A9, 0x8674, 0xD0A7, 0x8677, 0xD0A6, + 0x8679, 0xAD69, 0x867A, 0xAD6B, 0x867B, 0xAD6A, 0x867C, 0xD0A8, 0x8685, 0xD3C4, 0x8686, 0xD3C1, 0x8687, 0xD3BF, 0x868A, 0xB041, + 0x868B, 0xD3C2, 0x868C, 0xB046, 0x868D, 0xD3BC, 0x868E, 0xD3CB, 0x8690, 0xD3CD, 0x8691, 0xD3BD, 0x8693, 0xB043, 0x8694, 0xD3CE, + 0x8695, 0xD3C9, 0x8696, 0xD3BB, 0x8697, 0xD3C0, 0x8698, 0xD3CA, 0x8699, 0xD3C6, 0x869A, 0xD3C3, 0x869C, 0xB048, 0x869D, 0xD3CC, + 0x869E, 0xD3BE, 0x86A1, 0xD3C7, 0x86A2, 0xD3B9, 0x86A3, 0xB047, 0x86A4, 0xB044, 0x86A5, 0xD3C5, 0x86A7, 0xD3C8, 0x86A8, 0xD3BA, + 0x86A9, 0xB045, 0x86AA, 0xB042, 0x86AF, 0xB34C, 0x86B0, 0xD7A5, 0x86B1, 0xB34B, 0x86B3, 0xD7A8, 0x86B4, 0xD7AB, 0x86B5, 0xB348, + 0x86B6, 0xB346, 0x86B7, 0xD77E, 0x86B8, 0xD7A9, 0x86B9, 0xD7A7, 0x86BA, 0xD7A4, 0x86BB, 0xD7AC, 0x86BC, 0xD7AD, 0x86BD, 0xD7AF, + 0x86BE, 0xD7B0, 0x86BF, 0xD77D, 0x86C0, 0xB345, 0x86C1, 0xD7A2, 0x86C2, 0xD7A1, 0x86C3, 0xD7AE, 0x86C4, 0xB347, 0x86C5, 0xD7A3, + 0x86C6, 0xB349, 0x86C7, 0xB344, 0x86C8, 0xD7A6, 0x86C9, 0xB34D, 0x86CB, 0xB34A, 0x86CC, 0xD7AA, 0x86D0, 0xB5F1, 0x86D1, 0xDBBF, + 0x86D3, 0xDBB4, 0x86D4, 0xB5EE, 0x86D6, 0xDFE7, 0x86D7, 0xDBBD, 0x86D8, 0xDBB1, 0x86D9, 0xB5EC, 0x86DA, 0xDBB6, 0x86DB, 0xB5EF, + 0x86DC, 0xDBBA, 0x86DD, 0xDBB8, 0x86DE, 0xB5F2, 0x86DF, 0xB5EB, 0x86E2, 0xDBB2, 0x86E3, 0xDBB5, 0x86E4, 0xB5F0, 0x86E6, 0xDBB3, + 0x86E8, 0xDBBE, 0x86E9, 0xDBBC, 0x86EA, 0xDBB7, 0x86EB, 0xDBB9, 0x86EC, 0xDBBB, 0x86ED, 0xB5ED, 0x86F5, 0xDFE8, 0x86F6, 0xDFEE, + 0x86F7, 0xDFE4, 0x86F8, 0xDFEA, 0x86F9, 0xB8BA, 0x86FA, 0xDFE6, 0x86FB, 0xB8C0, 0x86FE, 0xB8BF, 0x8700, 0xB8BE, 0x8701, 0xDFED, + 0x8702, 0xB8C1, 0x8703, 0xB8C2, 0x8704, 0xDFE3, 0x8705, 0xDFF0, 0x8706, 0xB8C3, 0x8707, 0xB8BD, 0x8708, 0xB8BC, 0x8709, 0xDFEC, + 0x870A, 0xB8C4, 0x870B, 0xDFE2, 0x870C, 0xDFE5, 0x870D, 0xDFEF, 0x870E, 0xDFEB, 0x8711, 0xE3F4, 0x8712, 0xE3E9, 0x8713, 0xB8BB, + 0x8718, 0xBB6A, 0x8719, 0xE3DD, 0x871A, 0xE3F2, 0x871B, 0xE3DE, 0x871C, 0xBB65, 0x871E, 0xE3DB, 0x8720, 0xE3E4, 0x8721, 0xE3DC, + 0x8722, 0xBB67, 0x8723, 0xE3D6, 0x8724, 0xE3F1, 0x8725, 0xBB68, 0x8726, 0xE3EE, 0x8727, 0xE3EF, 0x8728, 0xE3D7, 0x8729, 0xBB6D, + 0x872A, 0xE3E6, 0x872C, 0xE3E0, 0x872D, 0xE3E7, 0x872E, 0xE3DA, 0x8730, 0xE3F3, 0x8731, 0xE3EB, 0x8732, 0xE3E5, 0x8733, 0xE3D5, + 0x8734, 0xBB69, 0x8735, 0xE3EC, 0x8737, 0xBB6C, 0x8738, 0xE3F0, 0x873A, 0xE3EA, 0x873B, 0xBB66, 0x873C, 0xE3E8, 0x873E, 0xE3E2, + 0x873F, 0xBB64, 0x8740, 0xE3D9, 0x8741, 0xE3E1, 0x8742, 0xE3ED, 0x8743, 0xE3DF, 0x8746, 0xE3E3, 0x874C, 0xBDC1, 0x874D, 0xDFE9, + 0x874E, 0xE7B2, 0x874F, 0xE7BB, 0x8750, 0xE7B1, 0x8751, 0xE7AD, 0x8752, 0xE7AA, 0x8753, 0xBDC2, 0x8754, 0xE7A8, 0x8755, 0xBB6B, + 0x8756, 0xE7A1, 0x8757, 0xBDC0, 0x8758, 0xE7A7, 0x8759, 0xBDBF, 0x875A, 0xE7AC, 0x875B, 0xE7A9, 0x875C, 0xE7B9, 0x875D, 0xE7B4, + 0x875E, 0xE7AE, 0x875F, 0xE7B3, 0x8760, 0xBDBB, 0x8761, 0xE7AB, 0x8762, 0xE7BE, 0x8763, 0xE7A2, 0x8764, 0xE7A3, 0x8765, 0xE7BA, + 0x8766, 0xBDBC, 0x8767, 0xE7BF, 0x8768, 0xBDBE, 0x8769, 0xE7C0, 0x876A, 0xE7B0, 0x876B, 0xE3D8, 0x876C, 0xE7B6, 0x876D, 0xE7AF, + 0x876E, 0xE7B8, 0x876F, 0xE7B5, 0x8773, 0xE7A6, 0x8774, 0xBDB9, 0x8775, 0xE7BD, 0x8776, 0xBDBA, 0x8777, 0xE7A4, 0x8778, 0xBDBD, + 0x8779, 0xEB64, 0x877A, 0xE7B7, 0x877B, 0xE7BC, 0x8781, 0xEB61, 0x8782, 0xBDB8, 0x8783, 0xBFC0, 0x8784, 0xEB6B, 0x8785, 0xEB67, + 0x8787, 0xEB65, 0x8788, 0xEB60, 0x8789, 0xEB6F, 0x878D, 0xBFC4, 0x878F, 0xEB5C, 0x8790, 0xEB68, 0x8791, 0xEB69, 0x8792, 0xEB5F, + 0x8793, 0xEB5E, 0x8794, 0xEB6C, 0x8796, 0xEB62, 0x8797, 0xEB5D, 0x8798, 0xEB63, 0x879A, 0xEB6E, 0x879B, 0xEB5B, 0x879C, 0xEB6D, + 0x879D, 0xEB6A, 0x879E, 0xBFC2, 0x879F, 0xBFC1, 0x87A2, 0xBFC3, 0x87A3, 0xEB66, 0x87A4, 0xF0CB, 0x87AA, 0xEE59, 0x87AB, 0xC1B1, + 0x87AC, 0xEE5D, 0x87AD, 0xEE5A, 0x87AE, 0xEE61, 0x87AF, 0xEE67, 0x87B0, 0xEE5C, 0x87B2, 0xEE70, 0x87B3, 0xC1AE, 0x87B4, 0xEE6A, + 0x87B5, 0xEE5F, 0x87B6, 0xEE6B, 0x87B7, 0xEE66, 0x87B8, 0xEE6D, 0x87B9, 0xEE5E, 0x87BA, 0xC1B3, 0x87BB, 0xC1B2, 0x87BC, 0xEE60, + 0x87BD, 0xEE6E, 0x87BE, 0xEE58, 0x87BF, 0xEE6C, 0x87C0, 0xC1AC, 0x87C2, 0xEE64, 0x87C3, 0xEE63, 0x87C4, 0xEE68, 0x87C5, 0xEE5B, + 0x87C6, 0xC1B0, 0x87C8, 0xC1B4, 0x87C9, 0xEE62, 0x87CA, 0xEE69, 0x87CB, 0xC1B5, 0x87CC, 0xEE65, 0x87D1, 0xC1AD, 0x87D2, 0xC1AF, + 0x87D3, 0xF0C7, 0x87D4, 0xF0C5, 0x87D7, 0xF0CC, 0x87D8, 0xF0C9, 0x87D9, 0xF0CD, 0x87DB, 0xF0BE, 0x87DC, 0xF0C6, 0x87DD, 0xF0D1, + 0x87DE, 0xEE6F, 0x87DF, 0xF0C2, 0x87E0, 0xC2CF, 0x87E1, 0xE7A5, 0x87E2, 0xF0BD, 0x87E3, 0xF0CA, 0x87E4, 0xF0C4, 0x87E5, 0xF0C1, + 0x87E6, 0xF0BC, 0x87E7, 0xF0BB, 0x87E8, 0xF0D0, 0x87EA, 0xF0C0, 0x87EB, 0xF0BF, 0x87EC, 0xC2CD, 0x87ED, 0xF0C8, 0x87EF, 0xC2CC, + 0x87F2, 0xC2CE, 0x87F3, 0xF0C3, 0x87F4, 0xF0CF, 0x87F6, 0xF2DE, 0x87F7, 0xF2DF, 0x87F9, 0xC3C9, 0x87FA, 0xF2DC, 0x87FB, 0xC3C6, + 0x87FC, 0xF2E4, 0x87FE, 0xC3CA, 0x87FF, 0xF2E6, 0x8800, 0xF2DB, 0x8801, 0xF0CE, 0x8802, 0xF2E8, 0x8803, 0xF2DD, 0x8805, 0xC3C7, + 0x8806, 0xF2E3, 0x8808, 0xF2E5, 0x8809, 0xF2E0, 0x880A, 0xF2E7, 0x880B, 0xF2E2, 0x880C, 0xF2E1, 0x880D, 0xC3C8, 0x8810, 0xF4C5, + 0x8811, 0xF4C6, 0x8813, 0xF4C8, 0x8814, 0xC4AE, 0x8815, 0xC4AF, 0x8816, 0xF4C9, 0x8817, 0xF4C7, 0x8819, 0xF4C4, 0x881B, 0xF642, + 0x881C, 0xF645, 0x881D, 0xF641, 0x881F, 0xC4FA, 0x8820, 0xF643, 0x8821, 0xC4F9, 0x8822, 0xC4F8, 0x8823, 0xC4F7, 0x8824, 0xF644, + 0x8825, 0xF751, 0x8826, 0xF74F, 0x8828, 0xF74E, 0x8829, 0xF640, 0x882A, 0xF750, 0x882B, 0xF646, 0x882C, 0xF74D, 0x882E, 0xF7F9, + 0x882F, 0xF7D7, 0x8830, 0xF7F7, 0x8831, 0xC5DB, 0x8832, 0xF7F8, 0x8833, 0xF7FA, 0x8835, 0xF8BF, 0x8836, 0xC5FA, 0x8837, 0xF8BE, + 0x8838, 0xF8BD, 0x8839, 0xC5FB, 0x883B, 0xC65A, 0x883C, 0xF96E, 0x883D, 0xF9A7, 0x883E, 0xF9A6, 0x883F, 0xF9A8, 0x8840, 0xA6E5, + 0x8841, 0xD0AA, 0x8843, 0xD3CF, 0x8844, 0xD3D0, 0x8848, 0xDBC0, 0x884A, 0xF647, 0x884B, 0xF8C0, 0x884C, 0xA6E6, 0x884D, 0xAD6C, + 0x884E, 0xD0AB, 0x8852, 0xD7B1, 0x8853, 0xB34E, 0x8855, 0xDBC2, 0x8856, 0xDBC1, 0x8857, 0xB5F3, 0x8859, 0xB8C5, 0x885A, 0xE7C1, + 0x885B, 0xBDC3, 0x885D, 0xBDC4, 0x8861, 0xBFC5, 0x8862, 0xC5FC, 0x8863, 0xA6E7, 0x8867, 0xD0AC, 0x8868, 0xAAED, 0x8869, 0xD0AE, + 0x886A, 0xD0AD, 0x886B, 0xAD6D, 0x886D, 0xD3D1, 0x886F, 0xD3D8, 0x8870, 0xB049, 0x8871, 0xD3D6, 0x8872, 0xD3D4, 0x8874, 0xD3DB, + 0x8875, 0xD3D2, 0x8876, 0xD3D3, 0x8877, 0xB04A, 0x8879, 0xB04E, 0x887C, 0xD3DC, 0x887D, 0xB04D, 0x887E, 0xD3DA, 0x887F, 0xD3D7, + 0x8880, 0xD3D5, 0x8881, 0xB04B, 0x8882, 0xB04C, 0x8883, 0xD3D9, 0x8888, 0xB350, 0x8889, 0xD7B2, 0x888B, 0xB355, 0x888C, 0xD7C2, + 0x888D, 0xB354, 0x888E, 0xD7C4, 0x8891, 0xD7B8, 0x8892, 0xB352, 0x8893, 0xD7C3, 0x8895, 0xD7B3, 0x8896, 0xB353, 0x8897, 0xD7BF, + 0x8898, 0xD7BB, 0x8899, 0xD7BD, 0x889A, 0xD7B7, 0x889B, 0xD7BE, 0x889E, 0xB34F, 0x889F, 0xD7BA, 0x88A1, 0xD7B9, 0x88A2, 0xD7B5, + 0x88A4, 0xD7C0, 0x88A7, 0xD7BC, 0x88A8, 0xD7B4, 0x88AA, 0xD7B6, 0x88AB, 0xB351, 0x88AC, 0xD7C1, 0x88B1, 0xB5F6, 0x88B2, 0xDBCD, + 0x88B6, 0xDBC9, 0x88B7, 0xDBCB, 0x88B8, 0xDBC6, 0x88B9, 0xDBC5, 0x88BA, 0xDBC3, 0x88BC, 0xDBCA, 0x88BD, 0xDBCC, 0x88BE, 0xDBC8, + 0x88C0, 0xDBC7, 0x88C1, 0xB5F4, 0x88C2, 0xB5F5, 0x88C9, 0xDBCF, 0x88CA, 0xB8CD, 0x88CB, 0xDFF2, 0x88CC, 0xDFF8, 0x88CD, 0xDFF3, + 0x88CE, 0xDFF4, 0x88CF, 0xF9D8, 0x88D0, 0xDFF9, 0x88D2, 0xB8CF, 0x88D4, 0xB8C7, 0x88D5, 0xB8CE, 0x88D6, 0xDFF1, 0x88D7, 0xDBC4, + 0x88D8, 0xB8CA, 0x88D9, 0xB8C8, 0x88DA, 0xDFF7, 0x88DB, 0xDFF6, 0x88DC, 0xB8C9, 0x88DD, 0xB8CB, 0x88DE, 0xDFF5, 0x88DF, 0xB8C6, + 0x88E1, 0xB8CC, 0x88E7, 0xE3F6, 0x88E8, 0xBB74, 0x88EB, 0xE442, 0x88EC, 0xE441, 0x88EE, 0xE3FB, 0x88EF, 0xBB76, 0x88F0, 0xE440, + 0x88F1, 0xE3F7, 0x88F2, 0xE3F8, 0x88F3, 0xBB6E, 0x88F4, 0xBB70, 0x88F6, 0xE3FD, 0x88F7, 0xE3F5, 0x88F8, 0xBB72, 0x88F9, 0xBB71, + 0x88FA, 0xE3F9, 0x88FB, 0xE3FE, 0x88FC, 0xE3FC, 0x88FD, 0xBB73, 0x88FE, 0xE3FA, 0x8901, 0xDBCE, 0x8902, 0xBB6F, 0x8905, 0xE7C2, + 0x8906, 0xE7C9, 0x8907, 0xBDC6, 0x8909, 0xE7CD, 0x890A, 0xBDCA, 0x890B, 0xE7C5, 0x890C, 0xE7C3, 0x890E, 0xE7CC, 0x8910, 0xBDC5, + 0x8911, 0xE7CB, 0x8912, 0xBDC7, 0x8913, 0xBDC8, 0x8914, 0xE7C4, 0x8915, 0xBDC9, 0x8916, 0xE7CA, 0x8917, 0xE7C6, 0x8918, 0xE7C7, + 0x8919, 0xE7C8, 0x891A, 0xBB75, 0x891E, 0xEB70, 0x891F, 0xEB7C, 0x8921, 0xBFCA, 0x8922, 0xEB77, 0x8923, 0xEB79, 0x8925, 0xBFC8, + 0x8926, 0xEB71, 0x8927, 0xEB75, 0x8929, 0xEB78, 0x892A, 0xBFC6, 0x892B, 0xBFC9, 0x892C, 0xEB7B, 0x892D, 0xEB73, 0x892E, 0xEB74, + 0x892F, 0xEB7A, 0x8930, 0xEB72, 0x8931, 0xEB76, 0x8932, 0xBFC7, 0x8933, 0xEE72, 0x8935, 0xEE71, 0x8936, 0xC1B7, 0x8937, 0xEE77, + 0x8938, 0xC1B9, 0x893B, 0xC1B6, 0x893C, 0xEE73, 0x893D, 0xC1BA, 0x893E, 0xEE74, 0x8941, 0xEE75, 0x8942, 0xEE78, 0x8944, 0xC1B8, + 0x8946, 0xF0D6, 0x8949, 0xF0D9, 0x894B, 0xF0D3, 0x894C, 0xF0D5, 0x894F, 0xF0D4, 0x8950, 0xF0D7, 0x8951, 0xF0D8, 0x8952, 0xEE76, + 0x8953, 0xF0D2, 0x8956, 0xC3CD, 0x8957, 0xF2EC, 0x8958, 0xF2EF, 0x8959, 0xF2F1, 0x895A, 0xF2EA, 0x895B, 0xF2EB, 0x895C, 0xF2EE, + 0x895D, 0xF2F0, 0x895E, 0xC3CE, 0x895F, 0xC3CC, 0x8960, 0xC3CB, 0x8961, 0xF2ED, 0x8962, 0xF2E9, 0x8963, 0xF4CA, 0x8964, 0xC4B0, + 0x8966, 0xF4CB, 0x8969, 0xF649, 0x896A, 0xC4FB, 0x896B, 0xF64B, 0x896C, 0xC4FC, 0x896D, 0xF648, 0x896E, 0xF64A, 0x896F, 0xC5A8, + 0x8971, 0xF752, 0x8972, 0xC5A7, 0x8973, 0xF7FD, 0x8974, 0xF7FC, 0x8976, 0xF7FB, 0x8979, 0xF948, 0x897A, 0xF949, 0x897B, 0xF94B, + 0x897C, 0xF94A, 0x897E, 0xCA50, 0x897F, 0xA6E8, 0x8981, 0xAD6E, 0x8982, 0xD7C5, 0x8983, 0xB5F7, 0x8985, 0xDFFA, 0x8986, 0xC2D0, + 0x8988, 0xF2F2, 0x898B, 0xA8A3, 0x898F, 0xB357, 0x8993, 0xB356, 0x8995, 0xDBD0, 0x8996, 0xB5F8, 0x8997, 0xDBD2, 0x8998, 0xDBD1, + 0x899B, 0xDFFB, 0x899C, 0xB8D0, 0x899D, 0xE443, 0x899E, 0xE446, 0x899F, 0xE445, 0x89A1, 0xE444, 0x89A2, 0xE7CE, 0x89A3, 0xE7D0, + 0x89A4, 0xE7CF, 0x89A6, 0xBFCC, 0x89AA, 0xBFCB, 0x89AC, 0xC1BB, 0x89AD, 0xEE79, 0x89AE, 0xEE7B, 0x89AF, 0xEE7A, 0x89B2, 0xC2D1, + 0x89B6, 0xF2F4, 0x89B7, 0xF2F3, 0x89B9, 0xF4CC, 0x89BA, 0xC4B1, 0x89BD, 0xC4FD, 0x89BE, 0xF754, 0x89BF, 0xF753, 0x89C0, 0xC65B, + 0x89D2, 0xA8A4, 0x89D3, 0xD0AF, 0x89D4, 0xAD6F, 0x89D5, 0xD7C8, 0x89D6, 0xD7C6, 0x89D9, 0xD7C7, 0x89DA, 0xDBD4, 0x89DB, 0xDBD5, + 0x89DC, 0xE043, 0x89DD, 0xDBD3, 0x89DF, 0xDFFC, 0x89E0, 0xE041, 0x89E1, 0xE040, 0x89E2, 0xE042, 0x89E3, 0xB8D1, 0x89E4, 0xDFFE, + 0x89E5, 0xDFFD, 0x89E6, 0xE044, 0x89E8, 0xE449, 0x89E9, 0xE447, 0x89EB, 0xE448, 0x89EC, 0xE7D3, 0x89ED, 0xE7D1, 0x89F0, 0xE7D2, + 0x89F1, 0xEB7D, 0x89F2, 0xEE7C, 0x89F3, 0xEE7D, 0x89F4, 0xC2D2, 0x89F6, 0xF2F5, 0x89F7, 0xF4CD, 0x89F8, 0xC4B2, 0x89FA, 0xF64C, + 0x89FB, 0xF755, 0x89FC, 0xC5A9, 0x89FE, 0xF7FE, 0x89FF, 0xF94C, 0x8A00, 0xA8A5, 0x8A02, 0xAD71, 0x8A03, 0xAD72, 0x8A04, 0xD0B0, + 0x8A07, 0xD0B1, 0x8A08, 0xAD70, 0x8A0A, 0xB054, 0x8A0C, 0xB052, 0x8A0E, 0xB051, 0x8A0F, 0xB058, 0x8A10, 0xB050, 0x8A11, 0xB059, + 0x8A12, 0xD3DD, 0x8A13, 0xB056, 0x8A15, 0xB053, 0x8A16, 0xB057, 0x8A17, 0xB055, 0x8A18, 0xB04F, 0x8A1B, 0xB35F, 0x8A1D, 0xB359, + 0x8A1E, 0xD7CC, 0x8A1F, 0xB35E, 0x8A22, 0xB360, 0x8A23, 0xB35A, 0x8A25, 0xB35B, 0x8A27, 0xD7CA, 0x8A2A, 0xB358, 0x8A2C, 0xD7CB, + 0x8A2D, 0xB35D, 0x8A30, 0xD7C9, 0x8A31, 0xB35C, 0x8A34, 0xB644, 0x8A36, 0xB646, 0x8A39, 0xDBD8, 0x8A3A, 0xB645, 0x8A3B, 0xB5F9, + 0x8A3C, 0xB5FD, 0x8A3E, 0xB8E4, 0x8A3F, 0xE049, 0x8A40, 0xDBDA, 0x8A41, 0xB5FE, 0x8A44, 0xDBDD, 0x8A45, 0xDBDE, 0x8A46, 0xB643, + 0x8A48, 0xDBE0, 0x8A4A, 0xDBE2, 0x8A4C, 0xDBE3, 0x8A4D, 0xDBD7, 0x8A4E, 0xDBD6, 0x8A4F, 0xDBE4, 0x8A50, 0xB642, 0x8A51, 0xDBE1, + 0x8A52, 0xDBDF, 0x8A54, 0xB640, 0x8A55, 0xB5FB, 0x8A56, 0xB647, 0x8A57, 0xDBDB, 0x8A58, 0xDBDC, 0x8A59, 0xDBD9, 0x8A5B, 0xB641, + 0x8A5E, 0xB5FC, 0x8A60, 0xB5FA, 0x8A61, 0xE048, 0x8A62, 0xB8DF, 0x8A63, 0xB8DA, 0x8A66, 0xB8D5, 0x8A68, 0xB8E5, 0x8A69, 0xB8D6, + 0x8A6B, 0xB8D2, 0x8A6C, 0xB8E1, 0x8A6D, 0xB8DE, 0x8A6E, 0xB8E0, 0x8A70, 0xB8D7, 0x8A71, 0xB8DC, 0x8A72, 0xB8D3, 0x8A73, 0xB8D4, + 0x8A74, 0xE050, 0x8A75, 0xE04D, 0x8A76, 0xE045, 0x8A77, 0xE04A, 0x8A79, 0xB8E2, 0x8A7A, 0xE051, 0x8A7B, 0xB8E3, 0x8A7C, 0xB8D9, + 0x8A7F, 0xE047, 0x8A81, 0xE04F, 0x8A82, 0xE04B, 0x8A83, 0xE04E, 0x8A84, 0xE04C, 0x8A85, 0xB8DD, 0x8A86, 0xE046, 0x8A87, 0xB8D8, + 0x8A8B, 0xE44C, 0x8A8C, 0xBB78, 0x8A8D, 0xBB7B, 0x8A8F, 0xE44E, 0x8A91, 0xBBA5, 0x8A92, 0xE44D, 0x8A93, 0xBB7D, 0x8A95, 0xBDCF, + 0x8A96, 0xE44F, 0x8A98, 0xBBA4, 0x8A99, 0xE44B, 0x8A9A, 0xBBA6, 0x8A9E, 0xBB79, 0x8AA0, 0xB8DB, 0x8AA1, 0xBB7C, 0x8AA3, 0xBB7A, + 0x8AA4, 0xBB7E, 0x8AA5, 0xBBA2, 0x8AA6, 0xBB77, 0x8AA7, 0xBBA7, 0x8AA8, 0xBBA3, 0x8AAA, 0xBBA1, 0x8AAB, 0xE44A, 0x8AB0, 0xBDD6, + 0x8AB2, 0xBDD2, 0x8AB6, 0xBDD9, 0x8AB8, 0xE7D6, 0x8AB9, 0xBDDA, 0x8ABA, 0xE7E2, 0x8ABB, 0xE7DB, 0x8ABC, 0xBDCB, 0x8ABD, 0xE7E3, + 0x8ABE, 0xE7DD, 0x8ABF, 0xBDD5, 0x8AC0, 0xE7DE, 0x8AC2, 0xBDD4, 0x8AC3, 0xE7E1, 0x8AC4, 0xBDCE, 0x8AC5, 0xE7DF, 0x8AC6, 0xE7D5, + 0x8AC7, 0xBDCD, 0x8AC8, 0xEBAA, 0x8AC9, 0xBDD3, 0x8ACB, 0xBDD0, 0x8ACD, 0xBDD8, 0x8ACF, 0xE7D4, 0x8AD1, 0xE7D8, 0x8AD2, 0xBDCC, + 0x8AD3, 0xE7D7, 0x8AD4, 0xE7D9, 0x8AD5, 0xE7DA, 0x8AD6, 0xBDD7, 0x8AD7, 0xE7DC, 0x8AD8, 0xE7E0, 0x8AD9, 0xE7E4, 0x8ADB, 0xBDDB, + 0x8ADC, 0xBFD2, 0x8ADD, 0xEBA5, 0x8ADE, 0xEBAB, 0x8ADF, 0xEBA8, 0x8AE0, 0xEB7E, 0x8AE1, 0xEBAC, 0x8AE2, 0xEBA1, 0x8AE4, 0xEBA7, + 0x8AE6, 0xBFCD, 0x8AE7, 0xBFD3, 0x8AE8, 0xEBAD, 0x8AEB, 0xBFCF, 0x8AED, 0xBFD9, 0x8AEE, 0xBFD4, 0x8AEF, 0xEBAF, 0x8AF0, 0xEBA9, + 0x8AF1, 0xBFD0, 0x8AF2, 0xEBA2, 0x8AF3, 0xBFDA, 0x8AF4, 0xEBA3, 0x8AF5, 0xEBA4, 0x8AF6, 0xBFDB, 0x8AF7, 0xBFD8, 0x8AF8, 0xBDD1, + 0x8AFA, 0xBFCE, 0x8AFB, 0xEBB0, 0x8AFC, 0xBFDC, 0x8AFE, 0xBFD5, 0x8AFF, 0xEBAE, 0x8B00, 0xBFD1, 0x8B01, 0xBFD6, 0x8B02, 0xBFD7, + 0x8B04, 0xC1C3, 0x8B05, 0xEEA4, 0x8B06, 0xEEAD, 0x8B07, 0xEEAA, 0x8B08, 0xEEAC, 0x8B0A, 0xC1C0, 0x8B0B, 0xEEA5, 0x8B0D, 0xEEAB, + 0x8B0E, 0xC1BC, 0x8B0F, 0xEEA7, 0x8B10, 0xC1C4, 0x8B11, 0xEEA3, 0x8B12, 0xEEA8, 0x8B13, 0xEEAF, 0x8B14, 0xEBA6, 0x8B15, 0xEEA9, + 0x8B16, 0xEEA2, 0x8B17, 0xC1BD, 0x8B18, 0xEEA1, 0x8B19, 0xC1BE, 0x8B1A, 0xEEB0, 0x8B1B, 0xC1BF, 0x8B1C, 0xEEAE, 0x8B1D, 0xC1C2, + 0x8B1E, 0xEE7E, 0x8B20, 0xC1C1, 0x8B22, 0xEEA6, 0x8B23, 0xF0DC, 0x8B24, 0xF0EA, 0x8B25, 0xF0E5, 0x8B26, 0xF0E7, 0x8B27, 0xF0DB, + 0x8B28, 0xC2D3, 0x8B2A, 0xF0DA, 0x8B2B, 0xC2D6, 0x8B2C, 0xC2D5, 0x8B2E, 0xF0E9, 0x8B2F, 0xF0E1, 0x8B30, 0xF0DE, 0x8B31, 0xF0E4, + 0x8B33, 0xF0DD, 0x8B35, 0xF0DF, 0x8B36, 0xF0E8, 0x8B37, 0xF0E6, 0x8B39, 0xC2D4, 0x8B3A, 0xF0ED, 0x8B3B, 0xF0EB, 0x8B3C, 0xF0E2, + 0x8B3D, 0xF0EC, 0x8B3E, 0xF0E3, 0x8B40, 0xF2F9, 0x8B41, 0xC3CF, 0x8B42, 0xF341, 0x8B45, 0xF64F, 0x8B46, 0xC3D6, 0x8B47, 0xF0E0, + 0x8B48, 0xF2F7, 0x8B49, 0xC3D2, 0x8B4A, 0xF2F8, 0x8B4B, 0xF2FD, 0x8B4E, 0xC3D4, 0x8B4F, 0xC3D5, 0x8B50, 0xF2F6, 0x8B51, 0xF340, + 0x8B52, 0xF342, 0x8B53, 0xF2FA, 0x8B54, 0xF2FC, 0x8B55, 0xF2FE, 0x8B56, 0xF2FB, 0x8B57, 0xF343, 0x8B58, 0xC3D1, 0x8B59, 0xC3D7, + 0x8B5A, 0xC3D3, 0x8B5C, 0xC3D0, 0x8B5D, 0xF4D0, 0x8B5F, 0xC4B7, 0x8B60, 0xF4CE, 0x8B63, 0xF4D2, 0x8B65, 0xF4D3, 0x8B66, 0xC4B5, + 0x8B67, 0xF4D4, 0x8B68, 0xF4D1, 0x8B6A, 0xF4CF, 0x8B6B, 0xC4B8, 0x8B6C, 0xC4B4, 0x8B6D, 0xF4D5, 0x8B6F, 0xC4B6, 0x8B70, 0xC4B3, + 0x8B74, 0xC4FE, 0x8B77, 0xC540, 0x8B78, 0xF64E, 0x8B79, 0xF64D, 0x8B7A, 0xF650, 0x8B7B, 0xF651, 0x8B7D, 0xC541, 0x8B7E, 0xF756, + 0x8B7F, 0xF75B, 0x8B80, 0xC5AA, 0x8B82, 0xF758, 0x8B84, 0xF757, 0x8B85, 0xF75A, 0x8B86, 0xF759, 0x8B88, 0xF843, 0x8B8A, 0xC5DC, + 0x8B8B, 0xF842, 0x8B8C, 0xF840, 0x8B8E, 0xF841, 0x8B92, 0xC5FE, 0x8B93, 0xC5FD, 0x8B94, 0xF8C1, 0x8B95, 0xF8C2, 0x8B96, 0xC640, + 0x8B98, 0xF94D, 0x8B99, 0xF94E, 0x8B9A, 0xC667, 0x8B9C, 0xC66D, 0x8B9E, 0xF9A9, 0x8B9F, 0xF9C8, 0x8C37, 0xA8A6, 0x8C39, 0xD7CD, + 0x8C3B, 0xD7CE, 0x8C3C, 0xE052, 0x8C3D, 0xE450, 0x8C3E, 0xE7E5, 0x8C3F, 0xC1C6, 0x8C41, 0xC1C5, 0x8C42, 0xF0EE, 0x8C43, 0xF344, + 0x8C45, 0xF844, 0x8C46, 0xA8A7, 0x8C47, 0xD3DE, 0x8C48, 0xB05A, 0x8C49, 0xB361, 0x8C4A, 0xE054, 0x8C4B, 0xE053, 0x8C4C, 0xBDDC, + 0x8C4D, 0xE7E6, 0x8C4E, 0xBDDD, 0x8C4F, 0xEEB1, 0x8C50, 0xC2D7, 0x8C54, 0xC676, 0x8C55, 0xA8A8, 0x8C56, 0xCDCB, 0x8C57, 0xD3DF, + 0x8C5A, 0xB362, 0x8C5C, 0xD7CF, 0x8C5D, 0xD7D0, 0x8C5F, 0xDBE5, 0x8C61, 0xB648, 0x8C62, 0xB8E6, 0x8C64, 0xE056, 0x8C65, 0xE055, + 0x8C66, 0xE057, 0x8C68, 0xE451, 0x8C69, 0xE452, 0x8C6A, 0xBBA8, 0x8C6B, 0xBFDD, 0x8C6C, 0xBDDE, 0x8C6D, 0xBFDE, 0x8C6F, 0xEEB5, + 0x8C70, 0xEEB2, 0x8C71, 0xEEB4, 0x8C72, 0xEEB3, 0x8C73, 0xC1C7, 0x8C75, 0xF0EF, 0x8C76, 0xF346, 0x8C77, 0xF345, 0x8C78, 0xCBA4, + 0x8C79, 0xB05C, 0x8C7A, 0xB05B, 0x8C7B, 0xD3E0, 0x8C7D, 0xD7D1, 0x8C80, 0xDBE7, 0x8C81, 0xDBE6, 0x8C82, 0xB649, 0x8C84, 0xE059, + 0x8C85, 0xE05A, 0x8C86, 0xE058, 0x8C89, 0xB8E8, 0x8C8A, 0xB8E7, 0x8C8C, 0xBBAA, 0x8C8D, 0xBBA9, 0x8C8F, 0xE7E7, 0x8C90, 0xEBB3, + 0x8C91, 0xEBB1, 0x8C92, 0xEBB2, 0x8C93, 0xBFDF, 0x8C94, 0xEEB7, 0x8C95, 0xEEB6, 0x8C97, 0xF0F2, 0x8C98, 0xF0F1, 0x8C99, 0xF0F0, + 0x8C9A, 0xF347, 0x8C9C, 0xF9AA, 0x8C9D, 0xA8A9, 0x8C9E, 0xAD73, 0x8CA0, 0xAD74, 0x8CA1, 0xB05D, 0x8CA2, 0xB05E, 0x8CA3, 0xD3E2, + 0x8CA4, 0xD3E1, 0x8CA5, 0xD7D2, 0x8CA7, 0xB368, 0x8CA8, 0xB366, 0x8CA9, 0xB363, 0x8CAA, 0xB367, 0x8CAB, 0xB365, 0x8CAC, 0xB364, + 0x8CAF, 0xB64A, 0x8CB0, 0xDBEA, 0x8CB2, 0xB8ED, 0x8CB3, 0xB64C, 0x8CB4, 0xB651, 0x8CB5, 0xDBEC, 0x8CB6, 0xB653, 0x8CB7, 0xB652, + 0x8CB8, 0xB655, 0x8CB9, 0xDBEB, 0x8CBA, 0xDBE8, 0x8CBB, 0xB64F, 0x8CBC, 0xB64B, 0x8CBD, 0xB64D, 0x8CBE, 0xDBE9, 0x8CBF, 0xB654, + 0x8CC0, 0xB650, 0x8CC1, 0xB64E, 0x8CC2, 0xB8EF, 0x8CC3, 0xB8EE, 0x8CC4, 0xB8EC, 0x8CC5, 0xB8F0, 0x8CC7, 0xB8EA, 0x8CC8, 0xB8EB, + 0x8CCA, 0xB8E9, 0x8CCC, 0xE05B, 0x8CCF, 0xE454, 0x8CD1, 0xBBAC, 0x8CD2, 0xBBAD, 0x8CD3, 0xBBAB, 0x8CD5, 0xE453, 0x8CD7, 0xE455, + 0x8CD9, 0xE7EA, 0x8CDA, 0xE7EC, 0x8CDC, 0xBDE7, 0x8CDD, 0xE7ED, 0x8CDE, 0xBDE0, 0x8CDF, 0xE7E9, 0x8CE0, 0xBDDF, 0x8CE1, 0xBDE9, + 0x8CE2, 0xBDE5, 0x8CE3, 0xBDE6, 0x8CE4, 0xBDE2, 0x8CE5, 0xE7E8, 0x8CE6, 0xBDE1, 0x8CE7, 0xE7EE, 0x8CE8, 0xE7EB, 0x8CEA, 0xBDE8, + 0x8CEC, 0xBDE3, 0x8CED, 0xBDE4, 0x8CEE, 0xEBB5, 0x8CF0, 0xEBB7, 0x8CF1, 0xEBB6, 0x8CF3, 0xEBB8, 0x8CF4, 0xBFE0, 0x8CF5, 0xEBB4, + 0x8CF8, 0xC1CB, 0x8CF9, 0xEEB8, 0x8CFA, 0xC1C8, 0x8CFB, 0xC1CC, 0x8CFC, 0xC1CA, 0x8CFD, 0xC1C9, 0x8CFE, 0xF0F3, 0x8D00, 0xF0F6, + 0x8D02, 0xF0F5, 0x8D04, 0xF0F4, 0x8D05, 0xC2D8, 0x8D06, 0xF348, 0x8D07, 0xF349, 0x8D08, 0xC3D8, 0x8D09, 0xF34A, 0x8D0A, 0xC3D9, + 0x8D0D, 0xC4BA, 0x8D0F, 0xC4B9, 0x8D10, 0xF652, 0x8D13, 0xC542, 0x8D14, 0xF653, 0x8D15, 0xF75C, 0x8D16, 0xC5AB, 0x8D17, 0xC5AC, + 0x8D19, 0xF845, 0x8D1B, 0xC642, 0x8D64, 0xA8AA, 0x8D66, 0xB36A, 0x8D67, 0xB369, 0x8D68, 0xE05C, 0x8D69, 0xE05D, 0x8D6B, 0xBBAE, + 0x8D6C, 0xEBB9, 0x8D6D, 0xBDEA, 0x8D6E, 0xEBBA, 0x8D6F, 0xEEB9, 0x8D70, 0xA8AB, 0x8D72, 0xD0B2, 0x8D73, 0xAD76, 0x8D74, 0xAD75, + 0x8D76, 0xD3E3, 0x8D77, 0xB05F, 0x8D78, 0xD3E4, 0x8D79, 0xD7D5, 0x8D7B, 0xD7D4, 0x8D7D, 0xD7D3, 0x8D80, 0xDBEE, 0x8D81, 0xB658, + 0x8D84, 0xDBED, 0x8D85, 0xB657, 0x8D89, 0xDBEF, 0x8D8A, 0xB656, 0x8D8C, 0xE05F, 0x8D8D, 0xE062, 0x8D8E, 0xE060, 0x8D8F, 0xE061, + 0x8D90, 0xE065, 0x8D91, 0xE05E, 0x8D92, 0xE066, 0x8D93, 0xE063, 0x8D94, 0xE064, 0x8D95, 0xBBB0, 0x8D96, 0xE456, 0x8D99, 0xBBAF, + 0x8D9B, 0xE7F2, 0x8D9C, 0xE7F0, 0x8D9F, 0xBDEB, 0x8DA0, 0xE7EF, 0x8DA1, 0xE7F1, 0x8DA3, 0xBDEC, 0x8DA5, 0xEBBB, 0x8DA7, 0xEBBC, + 0x8DA8, 0xC1CD, 0x8DAA, 0xF34C, 0x8DAB, 0xF34E, 0x8DAC, 0xF34B, 0x8DAD, 0xF34D, 0x8DAE, 0xF4D6, 0x8DAF, 0xF654, 0x8DB2, 0xF96F, + 0x8DB3, 0xA8AC, 0x8DB4, 0xAD77, 0x8DB5, 0xD3E5, 0x8DB6, 0xD3E7, 0x8DB7, 0xD3E6, 0x8DB9, 0xD7D8, 0x8DBA, 0xB36C, 0x8DBC, 0xD7D6, + 0x8DBE, 0xB36B, 0x8DBF, 0xD7D9, 0x8DC1, 0xD7DA, 0x8DC2, 0xD7D7, 0x8DC5, 0xDBFB, 0x8DC6, 0xB660, 0x8DC7, 0xDBF3, 0x8DC8, 0xDBF9, + 0x8DCB, 0xB65B, 0x8DCC, 0xB65E, 0x8DCD, 0xDBF2, 0x8DCE, 0xB659, 0x8DCF, 0xDBF6, 0x8DD0, 0xE06C, 0x8DD1, 0xB65D, 0x8DD3, 0xDBF1, + 0x8DD5, 0xDBF7, 0x8DD6, 0xDBF4, 0x8DD7, 0xDBFA, 0x8DD8, 0xDBF0, 0x8DD9, 0xDBF8, 0x8DDA, 0xB65C, 0x8DDB, 0xB65F, 0x8DDC, 0xDBF5, + 0x8DDD, 0xB65A, 0x8DDF, 0xB8F2, 0x8DE0, 0xE068, 0x8DE1, 0xB8F1, 0x8DE2, 0xE06F, 0x8DE3, 0xE06E, 0x8DE4, 0xB8F8, 0x8DE6, 0xB8F9, + 0x8DE7, 0xE070, 0x8DE8, 0xB8F3, 0x8DE9, 0xE06D, 0x8DEA, 0xB8F7, 0x8DEB, 0xE072, 0x8DEC, 0xE069, 0x8DEE, 0xE06B, 0x8DEF, 0xB8F4, + 0x8DF0, 0xE067, 0x8DF1, 0xE06A, 0x8DF2, 0xE071, 0x8DF3, 0xB8F5, 0x8DF4, 0xE073, 0x8DFA, 0xB8F6, 0x8DFC, 0xBBB1, 0x8DFD, 0xE45B, + 0x8DFE, 0xE461, 0x8DFF, 0xE459, 0x8E00, 0xE462, 0x8E02, 0xE458, 0x8E03, 0xE45D, 0x8E04, 0xE463, 0x8E05, 0xE460, 0x8E06, 0xE45F, + 0x8E07, 0xE45E, 0x8E09, 0xE457, 0x8E0A, 0xE45C, 0x8E0D, 0xE45A, 0x8E0F, 0xBDF1, 0x8E10, 0xBDEE, 0x8E11, 0xE7FB, 0x8E12, 0xE841, + 0x8E13, 0xE843, 0x8E14, 0xE840, 0x8E15, 0xE7F8, 0x8E16, 0xE7FA, 0x8E17, 0xE845, 0x8E18, 0xE842, 0x8E19, 0xE7FC, 0x8E1A, 0xE846, + 0x8E1B, 0xE7F9, 0x8E1C, 0xE844, 0x8E1D, 0xBDEF, 0x8E1E, 0xBDF5, 0x8E1F, 0xBDF3, 0x8E20, 0xE7F3, 0x8E21, 0xBDF4, 0x8E22, 0xBDF0, + 0x8E23, 0xE7F4, 0x8E24, 0xE7F6, 0x8E25, 0xE7F5, 0x8E26, 0xE7FD, 0x8E27, 0xE7FE, 0x8E29, 0xBDF2, 0x8E2B, 0xBDED, 0x8E2E, 0xE7F7, + 0x8E30, 0xEBC6, 0x8E31, 0xBFE2, 0x8E33, 0xEBBD, 0x8E34, 0xBFE3, 0x8E35, 0xBFE6, 0x8E36, 0xEBC2, 0x8E38, 0xEBBF, 0x8E39, 0xBFE5, + 0x8E3C, 0xEBC3, 0x8E3D, 0xEBC4, 0x8E3E, 0xEBBE, 0x8E3F, 0xEBC7, 0x8E40, 0xEBC0, 0x8E41, 0xEBC5, 0x8E42, 0xBFE4, 0x8E44, 0xBFE1, + 0x8E45, 0xEBC1, 0x8E47, 0xEEBF, 0x8E48, 0xC1D0, 0x8E49, 0xC1CE, 0x8E4A, 0xC1D1, 0x8E4B, 0xC1CF, 0x8E4C, 0xEEBE, 0x8E4D, 0xEEBB, + 0x8E4E, 0xEEBA, 0x8E50, 0xEEBD, 0x8E53, 0xEEBC, 0x8E54, 0xF145, 0x8E55, 0xC2DE, 0x8E56, 0xF0FB, 0x8E57, 0xF0FA, 0x8E59, 0xC2D9, + 0x8E5A, 0xF141, 0x8E5B, 0xF140, 0x8E5C, 0xF0F7, 0x8E5D, 0xF143, 0x8E5E, 0xF0FC, 0x8E5F, 0xC2DD, 0x8E60, 0xF0F9, 0x8E61, 0xF142, + 0x8E62, 0xF0F8, 0x8E63, 0xC2DA, 0x8E64, 0xC2DC, 0x8E65, 0xF0FD, 0x8E66, 0xC2DB, 0x8E67, 0xF0FE, 0x8E69, 0xF144, 0x8E6A, 0xF352, + 0x8E6C, 0xC3DE, 0x8E6D, 0xF34F, 0x8E6F, 0xF353, 0x8E72, 0xC3DB, 0x8E73, 0xF351, 0x8E74, 0xC3E0, 0x8E76, 0xC3DD, 0x8E78, 0xF350, + 0x8E7A, 0xC3DF, 0x8E7B, 0xF354, 0x8E7C, 0xC3DA, 0x8E81, 0xC4BC, 0x8E82, 0xC4BE, 0x8E84, 0xF4D9, 0x8E85, 0xC4BD, 0x8E86, 0xF4D7, + 0x8E87, 0xC3DC, 0x8E88, 0xF4D8, 0x8E89, 0xC4BB, 0x8E8A, 0xC543, 0x8E8B, 0xC545, 0x8E8C, 0xF656, 0x8E8D, 0xC544, 0x8E8E, 0xF655, + 0x8E90, 0xF761, 0x8E91, 0xC5AD, 0x8E92, 0xF760, 0x8E93, 0xC5AE, 0x8E94, 0xF75E, 0x8E95, 0xF75D, 0x8E96, 0xF762, 0x8E97, 0xF763, + 0x8E98, 0xF846, 0x8E9A, 0xF75F, 0x8E9D, 0xF8C6, 0x8E9E, 0xF8C3, 0x8E9F, 0xF8C4, 0x8EA0, 0xF8C5, 0x8EA1, 0xC65C, 0x8EA3, 0xF951, + 0x8EA4, 0xF950, 0x8EA5, 0xF94F, 0x8EA6, 0xF970, 0x8EA8, 0xF9BE, 0x8EA9, 0xF9AB, 0x8EAA, 0xC66E, 0x8EAB, 0xA8AD, 0x8EAC, 0xB060, + 0x8EB2, 0xB8FA, 0x8EBA, 0xBDF6, 0x8EBD, 0xEBC8, 0x8EC0, 0xC2DF, 0x8EC2, 0xF355, 0x8EC9, 0xF9AC, 0x8ECA, 0xA8AE, 0x8ECB, 0xAAEE, + 0x8ECC, 0xAD79, 0x8ECD, 0xAD78, 0x8ECF, 0xB063, 0x8ED1, 0xD3E8, 0x8ED2, 0xB061, 0x8ED3, 0xD3E9, 0x8ED4, 0xB062, 0x8ED7, 0xD7DF, + 0x8ED8, 0xD7DB, 0x8EDB, 0xB36D, 0x8EDC, 0xD7DE, 0x8EDD, 0xD7DD, 0x8EDE, 0xD7DC, 0x8EDF, 0xB36E, 0x8EE0, 0xD7E0, 0x8EE1, 0xD7E1, + 0x8EE5, 0xDC43, 0x8EE6, 0xDC41, 0x8EE7, 0xDC45, 0x8EE8, 0xDC46, 0x8EE9, 0xDC4C, 0x8EEB, 0xDC48, 0x8EEC, 0xDC4A, 0x8EEE, 0xDC42, + 0x8EEF, 0xDBFC, 0x8EF1, 0xDC49, 0x8EF4, 0xDC4B, 0x8EF5, 0xDC44, 0x8EF6, 0xDC47, 0x8EF7, 0xDBFD, 0x8EF8, 0xB662, 0x8EF9, 0xDC40, + 0x8EFA, 0xDBFE, 0x8EFB, 0xB661, 0x8EFC, 0xB663, 0x8EFE, 0xB8FD, 0x8EFF, 0xE075, 0x8F00, 0xE077, 0x8F01, 0xE076, 0x8F02, 0xE07B, + 0x8F03, 0xB8FB, 0x8F05, 0xE078, 0x8F06, 0xE074, 0x8F07, 0xE079, 0x8F08, 0xE07A, 0x8F09, 0xB8FC, 0x8F0A, 0xB8FE, 0x8F0B, 0xE07C, + 0x8F0D, 0xE467, 0x8F0E, 0xE466, 0x8F10, 0xE464, 0x8F11, 0xE465, 0x8F12, 0xBBB3, 0x8F13, 0xBBB5, 0x8F14, 0xBBB2, 0x8F15, 0xBBB4, + 0x8F16, 0xE84D, 0x8F17, 0xE84E, 0x8F18, 0xE849, 0x8F1A, 0xE84A, 0x8F1B, 0xBDF8, 0x8F1C, 0xBDFD, 0x8F1D, 0xBDF7, 0x8F1E, 0xBDFE, + 0x8F1F, 0xBDF9, 0x8F20, 0xE84B, 0x8F23, 0xE84C, 0x8F24, 0xE848, 0x8F25, 0xBE40, 0x8F26, 0xBDFB, 0x8F29, 0xBDFA, 0x8F2A, 0xBDFC, + 0x8F2C, 0xE847, 0x8F2E, 0xEBCA, 0x8F2F, 0xBFE8, 0x8F32, 0xEBCC, 0x8F33, 0xBFEA, 0x8F34, 0xEBCF, 0x8F35, 0xEBCB, 0x8F36, 0xEBC9, + 0x8F37, 0xEBCE, 0x8F38, 0xBFE9, 0x8F39, 0xEBCD, 0x8F3B, 0xBFE7, 0x8F3E, 0xC1D3, 0x8F3F, 0xC1D6, 0x8F40, 0xEEC1, 0x8F42, 0xC1D4, + 0x8F43, 0xEEC0, 0x8F44, 0xC1D2, 0x8F45, 0xC1D5, 0x8F46, 0xF146, 0x8F47, 0xF147, 0x8F48, 0xF148, 0x8F49, 0xC2E0, 0x8F4B, 0xF149, + 0x8F4D, 0xC2E1, 0x8F4E, 0xC3E2, 0x8F4F, 0xF358, 0x8F50, 0xF359, 0x8F51, 0xF357, 0x8F52, 0xF356, 0x8F53, 0xF35A, 0x8F54, 0xC3E1, + 0x8F55, 0xF4DD, 0x8F56, 0xF4DB, 0x8F57, 0xF4DC, 0x8F58, 0xF4DE, 0x8F59, 0xF4DA, 0x8F5A, 0xF4DF, 0x8F5B, 0xF658, 0x8F5D, 0xF659, + 0x8F5E, 0xF657, 0x8F5F, 0xC546, 0x8F60, 0xF764, 0x8F61, 0xC5AF, 0x8F62, 0xF765, 0x8F63, 0xF848, 0x8F64, 0xF847, 0x8F9B, 0xA8AF, + 0x8F9C, 0xB664, 0x8F9F, 0xB940, 0x8FA3, 0xBBB6, 0x8FA6, 0xBFEC, 0x8FA8, 0xBFEB, 0x8FAD, 0xC3E3, 0x8FAE, 0xC47C, 0x8FAF, 0xC547, + 0x8FB0, 0xA8B0, 0x8FB1, 0xB064, 0x8FB2, 0xB941, 0x8FB4, 0xF35B, 0x8FBF, 0xCBA6, 0x8FC2, 0xA8B1, 0x8FC4, 0xA8B4, 0x8FC5, 0xA8B3, + 0x8FC6, 0xA8B2, 0x8FC9, 0xCBA5, 0x8FCB, 0xCDCD, 0x8FCD, 0xCDCF, 0x8FCE, 0xAAEF, 0x8FD1, 0xAAF1, 0x8FD2, 0xCDCC, 0x8FD3, 0xCDCE, + 0x8FD4, 0xAAF0, 0x8FD5, 0xCDD1, 0x8FD6, 0xCDD0, 0x8FD7, 0xCDD2, 0x8FE0, 0xD0B6, 0x8FE1, 0xD0B4, 0x8FE2, 0xAD7C, 0x8FE3, 0xD0B3, + 0x8FE4, 0xADA3, 0x8FE5, 0xAD7E, 0x8FE6, 0xAD7B, 0x8FE8, 0xADA4, 0x8FEA, 0xAD7D, 0x8FEB, 0xADA2, 0x8FED, 0xADA1, 0x8FEE, 0xD0B5, + 0x8FF0, 0xAD7A, 0x8FF4, 0xB06A, 0x8FF5, 0xD3EB, 0x8FF6, 0xD3F1, 0x8FF7, 0xB067, 0x8FF8, 0xB06E, 0x8FFA, 0xB069, 0x8FFB, 0xD3EE, + 0x8FFC, 0xD3F0, 0x8FFD, 0xB06C, 0x8FFE, 0xD3EA, 0x8FFF, 0xD3ED, 0x9000, 0xB068, 0x9001, 0xB065, 0x9002, 0xD3EC, 0x9003, 0xB06B, + 0x9004, 0xD3EF, 0x9005, 0xB06D, 0x9006, 0xB066, 0x900B, 0xD7E3, 0x900C, 0xD7E6, 0x900D, 0xB370, 0x900F, 0xB37A, 0x9010, 0xB376, + 0x9011, 0xD7E4, 0x9014, 0xB37E, 0x9015, 0xB377, 0x9016, 0xB37C, 0x9017, 0xB372, 0x9019, 0xB36F, 0x901A, 0xB371, 0x901B, 0xB37D, + 0x901C, 0xD7E5, 0x901D, 0xB375, 0x901E, 0xB378, 0x901F, 0xB374, 0x9020, 0xB379, 0x9021, 0xD7E7, 0x9022, 0xB37B, 0x9023, 0xB373, + 0x9024, 0xD7E2, 0x902D, 0xDC4D, 0x902E, 0xB665, 0x902F, 0xDC4F, 0x9031, 0xB667, 0x9032, 0xB669, 0x9034, 0xDC4E, 0x9035, 0xB666, + 0x9036, 0xB66A, 0x9038, 0xB668, 0x903C, 0xB947, 0x903D, 0xE0A3, 0x903E, 0xB94F, 0x903F, 0xE07E, 0x9041, 0xB950, 0x9042, 0xB945, + 0x9044, 0xE0A1, 0x9047, 0xB94A, 0x9049, 0xE0A2, 0x904A, 0xB943, 0x904B, 0xB942, 0x904D, 0xB94D, 0x904E, 0xB94C, 0x904F, 0xB94B, + 0x9050, 0xB949, 0x9051, 0xB94E, 0x9052, 0xE07D, 0x9053, 0xB944, 0x9054, 0xB946, 0x9055, 0xB948, 0x9058, 0xBBB8, 0x9059, 0xBBBB, + 0x905B, 0xBBBF, 0x905C, 0xBBB9, 0x905D, 0xBBBE, 0x905E, 0xBBBC, 0x9060, 0xBBB7, 0x9062, 0xBBBD, 0x9063, 0xBBBA, 0x9067, 0xE852, + 0x9068, 0xBE43, 0x9069, 0xBE41, 0x906B, 0xE853, 0x906D, 0xBE44, 0x906E, 0xBE42, 0x906F, 0xE851, 0x9070, 0xE850, 0x9072, 0xBFF0, + 0x9073, 0xE84F, 0x9074, 0xBFEE, 0x9075, 0xBFED, 0x9076, 0xEBD0, 0x9077, 0xBE45, 0x9078, 0xBFEF, 0x9079, 0xEBD1, 0x907A, 0xBFF2, + 0x907B, 0xEBD2, 0x907C, 0xBFF1, 0x907D, 0xC1D8, 0x907E, 0xEEC3, 0x907F, 0xC1D7, 0x9080, 0xC1DC, 0x9081, 0xC1DA, 0x9082, 0xC1DB, + 0x9083, 0xC2E3, 0x9084, 0xC1D9, 0x9085, 0xEEC2, 0x9086, 0xEBD3, 0x9087, 0xC2E2, 0x9088, 0xC2E4, 0x908A, 0xC3E4, 0x908B, 0xC3E5, + 0x908D, 0xF4E0, 0x908F, 0xC5DE, 0x9090, 0xC5DD, 0x9091, 0xA8B6, 0x9094, 0xCA55, 0x9095, 0xB06F, 0x9097, 0xCA52, 0x9098, 0xCA53, + 0x9099, 0xCA51, 0x909B, 0xCA54, 0x909E, 0xCBAA, 0x909F, 0xCBA7, 0x90A0, 0xCBAC, 0x90A1, 0xCBA8, 0x90A2, 0xA8B7, 0x90A3, 0xA8BA, + 0x90A5, 0xCBA9, 0x90A6, 0xA8B9, 0x90A7, 0xCBAB, 0x90AA, 0xA8B8, 0x90AF, 0xCDD5, 0x90B0, 0xCDD7, 0x90B1, 0xAAF4, 0x90B2, 0xCDD3, + 0x90B3, 0xCDD6, 0x90B4, 0xCDD4, 0x90B5, 0xAAF2, 0x90B6, 0xAAF5, 0x90B8, 0xAAF3, 0x90BD, 0xD0B8, 0x90BE, 0xD0BC, 0x90BF, 0xD0B9, + 0x90C1, 0xADA7, 0x90C3, 0xADA8, 0x90C5, 0xD0BB, 0x90C7, 0xD0BD, 0x90C8, 0xD0BF, 0x90CA, 0xADA5, 0x90CB, 0xD0BE, 0x90CE, 0xADA6, + 0x90D4, 0xD7EE, 0x90D5, 0xD0BA, 0x90D6, 0xD3F2, 0x90D7, 0xD3FB, 0x90D8, 0xD3F9, 0x90D9, 0xD3F4, 0x90DA, 0xD3F5, 0x90DB, 0xD3FA, + 0x90DC, 0xD3FC, 0x90DD, 0xB071, 0x90DF, 0xD3F7, 0x90E0, 0xD3F3, 0x90E1, 0xB070, 0x90E2, 0xB072, 0x90E3, 0xD3F6, 0x90E4, 0xD3FD, + 0x90E5, 0xD3F8, 0x90E8, 0xB3A1, 0x90E9, 0xD7F1, 0x90EA, 0xD7E9, 0x90EB, 0xD7EF, 0x90EC, 0xD7F0, 0x90ED, 0xB3A2, 0x90EF, 0xD7E8, + 0x90F0, 0xD7EA, 0x90F1, 0xD0B7, 0x90F2, 0xD7EC, 0x90F3, 0xD7ED, 0x90F4, 0xD7EB, 0x90F5, 0xB66C, 0x90F9, 0xDC56, 0x90FA, 0xEBD4, + 0x90FB, 0xDC57, 0x90FC, 0xDC54, 0x90FD, 0xB3A3, 0x90FE, 0xB66E, 0x90FF, 0xDC53, 0x9100, 0xDC59, 0x9101, 0xDC58, 0x9102, 0xB66B, + 0x9103, 0xDC5C, 0x9104, 0xDC52, 0x9105, 0xDC5B, 0x9106, 0xDC50, 0x9107, 0xDC5A, 0x9108, 0xDC55, 0x9109, 0xB66D, 0x910B, 0xE0AA, + 0x910D, 0xE0A5, 0x910E, 0xE0AB, 0x910F, 0xE0A6, 0x9110, 0xE0A4, 0x9111, 0xE0A7, 0x9112, 0xB951, 0x9114, 0xE0A9, 0x9116, 0xE0A8, + 0x9117, 0xB952, 0x9118, 0xBBC1, 0x9119, 0xBBC0, 0x911A, 0xE46E, 0x911B, 0xE471, 0x911C, 0xE469, 0x911D, 0xE46D, 0x911E, 0xBBC2, + 0x911F, 0xE46C, 0x9120, 0xE46A, 0x9121, 0xE470, 0x9122, 0xE46B, 0x9123, 0xE468, 0x9124, 0xE46F, 0x9126, 0xE859, 0x9127, 0xBE48, + 0x9128, 0xF14A, 0x9129, 0xE856, 0x912A, 0xE857, 0x912B, 0xE855, 0x912C, 0xDC51, 0x912D, 0xBE47, 0x912E, 0xE85A, 0x912F, 0xE854, + 0x9130, 0xBE46, 0x9131, 0xBE49, 0x9132, 0xE858, 0x9133, 0xEBD5, 0x9134, 0xBFF3, 0x9135, 0xEBD6, 0x9136, 0xEBD7, 0x9138, 0xEEC4, + 0x9139, 0xC1DD, 0x913A, 0xF14B, 0x913B, 0xF14C, 0x913E, 0xF14D, 0x913F, 0xF35D, 0x9140, 0xF35C, 0x9141, 0xF4E2, 0x9143, 0xF4E1, + 0x9144, 0xF65B, 0x9145, 0xF65C, 0x9146, 0xF65A, 0x9147, 0xF766, 0x9148, 0xC5B0, 0x9149, 0xA8BB, 0x914A, 0xADAA, 0x914B, 0xADA9, + 0x914C, 0xB075, 0x914D, 0xB074, 0x914E, 0xD440, 0x914F, 0xD441, 0x9150, 0xD3FE, 0x9152, 0xB073, 0x9153, 0xD7F5, 0x9155, 0xD7F6, + 0x9156, 0xD7F2, 0x9157, 0xB3A4, 0x9158, 0xD7F3, 0x915A, 0xD7F4, 0x915F, 0xDC5F, 0x9160, 0xDC61, 0x9161, 0xDC5D, 0x9162, 0xDC60, + 0x9163, 0xB66F, 0x9164, 0xDC5E, 0x9165, 0xB670, 0x9168, 0xDD73, 0x9169, 0xB955, 0x916A, 0xB954, 0x916C, 0xB953, 0x916E, 0xE0AC, + 0x916F, 0xE0AD, 0x9172, 0xE473, 0x9173, 0xE475, 0x9174, 0xBBC6, 0x9175, 0xBBC3, 0x9177, 0xBBC5, 0x9178, 0xBBC4, 0x9179, 0xE474, + 0x917A, 0xE472, 0x9180, 0xE861, 0x9181, 0xE85E, 0x9182, 0xE85F, 0x9183, 0xBE4D, 0x9184, 0xE860, 0x9185, 0xE85B, 0x9186, 0xE85C, + 0x9187, 0xBE4A, 0x9189, 0xBE4B, 0x918A, 0xE85D, 0x918B, 0xBE4C, 0x918D, 0xEBDB, 0x918F, 0xEBDC, 0x9190, 0xEBD9, 0x9191, 0xEBDA, + 0x9192, 0xBFF4, 0x9193, 0xEBD8, 0x9199, 0xEEC8, 0x919A, 0xEEC5, 0x919B, 0xEEC7, 0x919C, 0xC1E0, 0x919D, 0xEECB, 0x919E, 0xC1DF, + 0x919F, 0xEEC9, 0x91A0, 0xEECC, 0x91A1, 0xEECA, 0x91A2, 0xEEC6, 0x91A3, 0xC1DE, 0x91A5, 0xF14F, 0x91A7, 0xF150, 0x91A8, 0xF14E, + 0x91AA, 0xF152, 0x91AB, 0xC2E5, 0x91AC, 0xC2E6, 0x91AD, 0xF35F, 0x91AE, 0xC3E7, 0x91AF, 0xF151, 0x91B0, 0xF35E, 0x91B1, 0xC3E6, + 0x91B2, 0xF4E5, 0x91B3, 0xF4E6, 0x91B4, 0xC4BF, 0x91B5, 0xF4E4, 0x91B7, 0xF4E3, 0x91B9, 0xF65D, 0x91BA, 0xC548, 0x91BC, 0xF849, + 0x91BD, 0xF8C8, 0x91BE, 0xF8C7, 0x91C0, 0xC643, 0x91C1, 0xC65D, 0x91C2, 0xF8C9, 0x91C3, 0xF971, 0x91C5, 0xC66F, 0x91C6, 0xA8BC, + 0x91C7, 0xAAF6, 0x91C9, 0xB956, 0x91CB, 0xC4C0, 0x91CC, 0xA8BD, 0x91CD, 0xADAB, 0x91CE, 0xB3A5, 0x91CF, 0xB671, 0x91D0, 0xC2E7, + 0x91D1, 0xAAF7, 0x91D3, 0xD0C1, 0x91D4, 0xD0C0, 0x91D5, 0xD442, 0x91D7, 0xB078, 0x91D8, 0xB076, 0x91D9, 0xB07A, 0x91DA, 0xD444, + 0x91DC, 0xB079, 0x91DD, 0xB077, 0x91E2, 0xD443, 0x91E3, 0xB3A8, 0x91E4, 0xD7FC, 0x91E6, 0xB3A7, 0x91E7, 0xB3A9, 0x91E8, 0xD842, + 0x91E9, 0xB3AB, 0x91EA, 0xD7FE, 0x91EB, 0xD840, 0x91EC, 0xD7F7, 0x91ED, 0xB3AA, 0x91EE, 0xD843, 0x91F1, 0xD7F9, 0x91F3, 0xD7FA, + 0x91F4, 0xD7F8, 0x91F5, 0xB3A6, 0x91F7, 0xD841, 0x91F8, 0xD7FB, 0x91F9, 0xD7FD, 0x91FD, 0xDC6D, 0x91FF, 0xDC6C, 0x9200, 0xDC6A, + 0x9201, 0xDC62, 0x9202, 0xDC71, 0x9203, 0xDC65, 0x9204, 0xDC6F, 0x9205, 0xDC76, 0x9206, 0xDC6E, 0x9207, 0xB679, 0x9209, 0xB675, + 0x920A, 0xDC63, 0x920C, 0xDC69, 0x920D, 0xB677, 0x920F, 0xDC68, 0x9210, 0xB678, 0x9211, 0xB67A, 0x9212, 0xDC6B, 0x9214, 0xB672, + 0x9215, 0xB673, 0x9216, 0xDC77, 0x9217, 0xDC75, 0x9219, 0xDC74, 0x921A, 0xDC66, 0x921C, 0xDC72, 0x921E, 0xB676, 0x9223, 0xB674, + 0x9224, 0xDC73, 0x9225, 0xDC64, 0x9226, 0xDC67, 0x9227, 0xDC70, 0x922D, 0xE4BA, 0x922E, 0xE0B7, 0x9230, 0xE0B0, 0x9231, 0xE0C3, + 0x9232, 0xE0CC, 0x9233, 0xE0B3, 0x9234, 0xB961, 0x9236, 0xE0C0, 0x9237, 0xB957, 0x9238, 0xB959, 0x9239, 0xB965, 0x923A, 0xE0B1, + 0x923D, 0xB95A, 0x923E, 0xB95C, 0x923F, 0xB966, 0x9240, 0xB95B, 0x9245, 0xB964, 0x9246, 0xE0B9, 0x9248, 0xE0AE, 0x9249, 0xB962, + 0x924A, 0xE0B8, 0x924B, 0xB95E, 0x924C, 0xE0CA, 0x924D, 0xB963, 0x924E, 0xE0C8, 0x924F, 0xE0BC, 0x9250, 0xE0C6, 0x9251, 0xB960, + 0x9252, 0xE0AF, 0x9253, 0xE0C9, 0x9254, 0xE0C4, 0x9256, 0xE0CB, 0x9257, 0xB958, 0x925A, 0xB967, 0x925B, 0xB95D, 0x925E, 0xE0B5, + 0x9260, 0xE0BD, 0x9261, 0xE0C1, 0x9263, 0xE0C5, 0x9264, 0xB95F, 0x9265, 0xE0B4, 0x9266, 0xE0B2, 0x9267, 0xE0BE, 0x926C, 0xE0BB, + 0x926D, 0xE0BA, 0x926F, 0xE0BF, 0x9270, 0xE0C2, 0x9272, 0xE0C7, 0x9276, 0xE478, 0x9278, 0xBBC7, 0x9279, 0xE4A4, 0x927A, 0xE47A, + 0x927B, 0xBBCC, 0x927C, 0xBBD0, 0x927D, 0xE4AD, 0x927E, 0xE4B5, 0x927F, 0xE4A6, 0x9280, 0xBBC8, 0x9282, 0xE4AA, 0x9283, 0xE0B6, + 0x9285, 0xBBC9, 0x9286, 0xE4B1, 0x9287, 0xE4B6, 0x9288, 0xE4AE, 0x928A, 0xE4B0, 0x928B, 0xE4B9, 0x928C, 0xE4B2, 0x928D, 0xE47E, + 0x928E, 0xE4A9, 0x9291, 0xBBD1, 0x9293, 0xBBCD, 0x9294, 0xE47C, 0x9295, 0xE4AB, 0x9296, 0xBBCB, 0x9297, 0xE4A5, 0x9298, 0xBBCA, + 0x9299, 0xE4B3, 0x929A, 0xE4A2, 0x929B, 0xE479, 0x929C, 0xBBCE, 0x929D, 0xE4B8, 0x92A0, 0xE47B, 0x92A1, 0xE4AF, 0x92A2, 0xE4AC, + 0x92A3, 0xE4A7, 0x92A4, 0xE477, 0x92A5, 0xE476, 0x92A6, 0xE4A1, 0x92A7, 0xE4B4, 0x92A8, 0xBBCF, 0x92A9, 0xE4B7, 0x92AA, 0xE47D, + 0x92AB, 0xE4A3, 0x92AC, 0xBE52, 0x92B2, 0xBE5A, 0x92B3, 0xBE55, 0x92B4, 0xE8A4, 0x92B5, 0xE8A1, 0x92B6, 0xE867, 0x92B7, 0xBE50, + 0x92B9, 0xF9D7, 0x92BB, 0xBE4F, 0x92BC, 0xBE56, 0x92C0, 0xE865, 0x92C1, 0xBE54, 0x92C2, 0xE871, 0x92C3, 0xE863, 0x92C4, 0xE864, + 0x92C5, 0xBE4E, 0x92C6, 0xE8A3, 0x92C7, 0xBE58, 0x92C8, 0xE874, 0x92C9, 0xE879, 0x92CA, 0xE873, 0x92CB, 0xEBEE, 0x92CC, 0xE86F, + 0x92CD, 0xE877, 0x92CE, 0xE875, 0x92CF, 0xE868, 0x92D0, 0xE862, 0x92D1, 0xE87D, 0x92D2, 0xBE57, 0x92D3, 0xE87E, 0x92D5, 0xE878, + 0x92D7, 0xE86D, 0x92D8, 0xE86B, 0x92D9, 0xE866, 0x92DD, 0xE86E, 0x92DE, 0xE87B, 0x92DF, 0xE86A, 0x92E0, 0xE87A, 0x92E1, 0xE8A2, + 0x92E4, 0xBE53, 0x92E6, 0xE876, 0x92E7, 0xE87C, 0x92E8, 0xE872, 0x92E9, 0xE86C, 0x92EA, 0xBE51, 0x92EE, 0xE4A8, 0x92EF, 0xE870, + 0x92F0, 0xBE59, 0x92F1, 0xE869, 0x92F7, 0xEBF4, 0x92F8, 0xBFF7, 0x92F9, 0xEBF3, 0x92FA, 0xEBF0, 0x92FB, 0xEC44, 0x92FC, 0xBFFB, + 0x92FE, 0xEC41, 0x92FF, 0xEBF8, 0x9300, 0xEC43, 0x9301, 0xEBE9, 0x9302, 0xEBF6, 0x9304, 0xBFFD, 0x9306, 0xEBE1, 0x9308, 0xEBDF, + 0x9309, 0xEC42, 0x930B, 0xEC40, 0x930C, 0xEBFE, 0x930D, 0xEBED, 0x930E, 0xEBEC, 0x930F, 0xEBE2, 0x9310, 0xC040, 0x9312, 0xEBE8, + 0x9313, 0xEBF2, 0x9314, 0xEBFD, 0x9315, 0xC043, 0x9316, 0xEC45, 0x9318, 0xC1E8, 0x9319, 0xC045, 0x931A, 0xBFFE, 0x931B, 0xEBE6, + 0x931D, 0xEBEF, 0x931E, 0xEBDE, 0x931F, 0xEBE0, 0x9320, 0xBFF5, 0x9321, 0xC042, 0x9322, 0xBFFA, 0x9323, 0xEBE7, 0x9324, 0xEBF7, + 0x9325, 0xEBF1, 0x9326, 0xC041, 0x9327, 0xEBDD, 0x9328, 0xC1E3, 0x9329, 0xEBF9, 0x932A, 0xEBFC, 0x932B, 0xBFFC, 0x932D, 0xEBEB, + 0x932E, 0xC044, 0x932F, 0xBFF9, 0x9333, 0xBFF8, 0x9334, 0xEBF5, 0x9335, 0xEBFB, 0x9336, 0xBFF6, 0x9338, 0xEBE4, 0x9339, 0xEBFA, + 0x933C, 0xEBE5, 0x9346, 0xEBEA, 0x9347, 0xEED2, 0x9349, 0xEED7, 0x934A, 0xC1E5, 0x934B, 0xC1E7, 0x934C, 0xEEDD, 0x934D, 0xC1E1, + 0x934E, 0xEEEC, 0x934F, 0xEEE3, 0x9350, 0xEED8, 0x9351, 0xEED9, 0x9352, 0xEEE2, 0x9354, 0xC1EE, 0x9355, 0xEEE1, 0x9356, 0xEED1, + 0x9357, 0xEEE0, 0x9358, 0xEED4, 0x9359, 0xEEED, 0x935A, 0xC1ED, 0x935B, 0xC1EB, 0x935C, 0xEED5, 0x935E, 0xEEE8, 0x9360, 0xEEDA, + 0x9361, 0xEEE7, 0x9363, 0xEEE9, 0x9364, 0xEED0, 0x9365, 0xC1E6, 0x9367, 0xEEEA, 0x936A, 0xEEDE, 0x936C, 0xC1EA, 0x936D, 0xEEDB, + 0x9370, 0xC1EC, 0x9371, 0xEEE4, 0x9375, 0xC1E4, 0x9376, 0xEED6, 0x9377, 0xEEE5, 0x9379, 0xEEDF, 0x937A, 0xEBE3, 0x937B, 0xEEE6, + 0x937C, 0xEED3, 0x937E, 0xC1E9, 0x9380, 0xEEEB, 0x9382, 0xC1E2, 0x9383, 0xEECE, 0x9388, 0xF160, 0x9389, 0xF159, 0x938A, 0xC2E9, + 0x938C, 0xF154, 0x938D, 0xF163, 0x938E, 0xF15B, 0x938F, 0xEEDC, 0x9391, 0xF165, 0x9392, 0xF155, 0x9394, 0xC2E8, 0x9395, 0xF15F, + 0x9396, 0xC2EA, 0x9397, 0xC2F2, 0x9398, 0xC2F0, 0x9399, 0xF161, 0x939A, 0xC2F1, 0x939B, 0xF157, 0x939D, 0xF158, 0x939E, 0xF15D, + 0x939F, 0xF162, 0x93A1, 0xEECD, 0x93A2, 0xC2EB, 0x93A3, 0xF16A, 0x93A4, 0xF167, 0x93A5, 0xF16B, 0x93A6, 0xF15E, 0x93A7, 0xF15A, + 0x93A8, 0xF168, 0x93A9, 0xF36A, 0x93AA, 0xF15C, 0x93AC, 0xC2EE, 0x93AE, 0xC2ED, 0x93AF, 0xEECF, 0x93B0, 0xC2EF, 0x93B1, 0xF164, + 0x93B2, 0xF166, 0x93B3, 0xC2EC, 0x93B4, 0xF169, 0x93B5, 0xF153, 0x93B7, 0xF156, 0x93C0, 0xF373, 0x93C2, 0xF363, 0x93C3, 0xC3EB, + 0x93C4, 0xF371, 0x93C7, 0xF361, 0x93C8, 0xC3EC, 0x93CA, 0xF36C, 0x93CC, 0xF368, 0x93CD, 0xC3F1, 0x93CE, 0xF372, 0x93CF, 0xF362, + 0x93D0, 0xF365, 0x93D1, 0xC3E9, 0x93D2, 0xF374, 0x93D4, 0xF36D, 0x93D5, 0xF370, 0x93D6, 0xC3EF, 0x93D7, 0xC3F4, 0x93D8, 0xC3F2, + 0x93D9, 0xF369, 0x93DA, 0xF364, 0x93DC, 0xC3ED, 0x93DD, 0xC3EE, 0x93DE, 0xF360, 0x93DF, 0xC3EA, 0x93E1, 0xC3E8, 0x93E2, 0xC3F0, + 0x93E3, 0xF36F, 0x93E4, 0xC3F3, 0x93E6, 0xF36B, 0x93E7, 0xF375, 0x93E8, 0xC3F5, 0x93EC, 0xF367, 0x93EE, 0xF36E, 0x93F5, 0xF4F3, + 0x93F6, 0xF542, 0x93F7, 0xF4F5, 0x93F8, 0xF4FC, 0x93F9, 0xF366, 0x93FA, 0xF4FA, 0x93FB, 0xF4E9, 0x93FC, 0xF540, 0x93FD, 0xC4C3, + 0x93FE, 0xF4ED, 0x93FF, 0xF4FE, 0x9400, 0xF4F4, 0x9403, 0xC4C2, 0x9406, 0xF544, 0x9407, 0xF4F6, 0x9409, 0xF4FB, 0x940A, 0xF4FD, + 0x940B, 0xF4E7, 0x940C, 0xF541, 0x940D, 0xF4F2, 0x940E, 0xF4F7, 0x940F, 0xF4EB, 0x9410, 0xF4EF, 0x9411, 0xF543, 0x9412, 0xF4F9, + 0x9413, 0xF4E8, 0x9414, 0xF4EC, 0x9415, 0xF4EE, 0x9416, 0xF4F8, 0x9418, 0xC4C1, 0x9419, 0xF4F1, 0x9420, 0xF4EA, 0x9428, 0xF4F0, + 0x9429, 0xF661, 0x942A, 0xF666, 0x942B, 0xC54F, 0x942C, 0xF668, 0x942E, 0xC549, 0x9430, 0xF664, 0x9431, 0xF66A, 0x9432, 0xC54E, + 0x9433, 0xC54A, 0x9435, 0xC54B, 0x9436, 0xF660, 0x9437, 0xF667, 0x9438, 0xC54D, 0x9439, 0xF665, 0x943A, 0xC54C, 0x943B, 0xF65F, + 0x943C, 0xF663, 0x943D, 0xF662, 0x943F, 0xF65E, 0x9440, 0xF669, 0x9444, 0xC5B1, 0x9445, 0xF76D, 0x9446, 0xF770, 0x9447, 0xF76C, + 0x9448, 0xF76E, 0x9449, 0xF76F, 0x944A, 0xF769, 0x944B, 0xF76A, 0x944C, 0xF767, 0x944F, 0xF76B, 0x9450, 0xF768, 0x9451, 0xC5B2, + 0x9452, 0xC5B3, 0x9455, 0xF84B, 0x9457, 0xF84D, 0x945D, 0xF84C, 0x945E, 0xF84E, 0x9460, 0xC5E0, 0x9462, 0xF84A, 0x9463, 0xC5DF, + 0x9464, 0xC5E1, 0x9468, 0xF8CB, 0x9469, 0xF8CC, 0x946A, 0xC644, 0x946B, 0xF8CA, 0x946D, 0xF953, 0x946E, 0xF952, 0x946F, 0xF954, + 0x9470, 0xC65F, 0x9471, 0xF955, 0x9472, 0xC65E, 0x9473, 0xF956, 0x9474, 0xF972, 0x9475, 0xF975, 0x9476, 0xF974, 0x9477, 0xC668, + 0x9478, 0xF973, 0x947C, 0xC672, 0x947D, 0xC670, 0x947E, 0xC671, 0x947F, 0xC677, 0x9480, 0xF9C0, 0x9481, 0xF9C1, 0x9482, 0xF9BF, + 0x9483, 0xF9C9, 0x9577, 0xAAF8, 0x957A, 0xD844, 0x957B, 0xDC78, 0x957C, 0xE8A5, 0x957D, 0xF376, 0x9580, 0xAAF9, 0x9582, 0xADAC, + 0x9583, 0xB07B, 0x9586, 0xD845, 0x9588, 0xD846, 0x9589, 0xB3AC, 0x958B, 0xB67D, 0x958C, 0xDC7A, 0x958D, 0xDC79, 0x958E, 0xB6A3, + 0x958F, 0xB67C, 0x9590, 0xDC7B, 0x9591, 0xB67E, 0x9592, 0xB6A2, 0x9593, 0xB6A1, 0x9594, 0xB67B, 0x9598, 0xB968, 0x959B, 0xE0D0, + 0x959C, 0xE0CE, 0x959E, 0xE0CF, 0x959F, 0xE0CD, 0x95A1, 0xBBD2, 0x95A3, 0xBBD5, 0x95A4, 0xBBD7, 0x95A5, 0xBBD6, 0x95A8, 0xBBD3, + 0x95A9, 0xBBD4, 0x95AB, 0xE8A7, 0x95AC, 0xE8A6, 0x95AD, 0xBE5B, 0x95AE, 0xE8A8, 0x95B0, 0xE8A9, 0x95B1, 0xBE5C, 0x95B5, 0xEC4D, + 0x95B6, 0xEC4B, 0x95B7, 0xEEF3, 0x95B9, 0xEC49, 0x95BA, 0xEC4A, 0x95BB, 0xC046, 0x95BC, 0xEC46, 0x95BD, 0xEC4E, 0x95BE, 0xEC48, + 0x95BF, 0xEC4C, 0x95C0, 0xEEEF, 0x95C3, 0xEEF1, 0x95C5, 0xEEF2, 0x95C6, 0xC1F3, 0x95C7, 0xEEEE, 0x95C8, 0xC1F2, 0x95C9, 0xEEF0, + 0x95CA, 0xC1EF, 0x95CB, 0xC1F0, 0x95CC, 0xC1F1, 0x95CD, 0xEC47, 0x95D0, 0xC2F5, 0x95D1, 0xF16E, 0x95D2, 0xF16C, 0x95D3, 0xF16D, + 0x95D4, 0xC2F3, 0x95D5, 0xC2F6, 0x95D6, 0xC2F4, 0x95DA, 0xF377, 0x95DB, 0xF378, 0x95DC, 0xC3F6, 0x95DE, 0xF545, 0x95DF, 0xF547, + 0x95E0, 0xF546, 0x95E1, 0xC4C4, 0x95E2, 0xC550, 0x95E3, 0xF66D, 0x95E4, 0xF66C, 0x95E5, 0xF66B, 0x961C, 0xAAFA, 0x961E, 0xC9AA, + 0x9620, 0xCA58, 0x9621, 0xA6E9, 0x9622, 0xCA56, 0x9623, 0xCA59, 0x9624, 0xCA57, 0x9628, 0xCBAE, 0x962A, 0xA8C1, 0x962C, 0xA8C2, + 0x962D, 0xCBB0, 0x962E, 0xA8BF, 0x962F, 0xCBAF, 0x9630, 0xCBAD, 0x9631, 0xA8C0, 0x9632, 0xA8BE, 0x9639, 0xCDD8, 0x963A, 0xCDDB, + 0x963B, 0xAAFD, 0x963C, 0xCDDA, 0x963D, 0xCDD9, 0x963F, 0xAAFC, 0x9640, 0xAAFB, 0x9642, 0xAB40, 0x9643, 0xCDDC, 0x9644, 0xAAFE, + 0x964A, 0xD0C6, 0x964B, 0xADAE, 0x964C, 0xADAF, 0x964D, 0xADB0, 0x964E, 0xD0C7, 0x964F, 0xD0C3, 0x9650, 0xADAD, 0x9651, 0xD0C4, + 0x9653, 0xD0C5, 0x9654, 0xD0C2, 0x9658, 0xB0A4, 0x965B, 0xB0A1, 0x965C, 0xD445, 0x965D, 0xB0A2, 0x965E, 0xB0A5, 0x965F, 0xD446, + 0x9661, 0xB07E, 0x9662, 0xB07C, 0x9663, 0xB07D, 0x9664, 0xB0A3, 0x966A, 0xB3AD, 0x966B, 0xD849, 0x966C, 0xB3B5, 0x966D, 0xD848, + 0x966F, 0xD84B, 0x9670, 0xB3B1, 0x9671, 0xD84A, 0x9672, 0xB6AB, 0x9673, 0xB3AF, 0x9674, 0xB3B2, 0x9675, 0xB3AE, 0x9676, 0xB3B3, + 0x9677, 0xB3B4, 0x9678, 0xB3B0, 0x967C, 0xD847, 0x967D, 0xB6A7, 0x967E, 0xDC7D, 0x9680, 0xDCA3, 0x9683, 0xDCA2, 0x9684, 0xB6AC, + 0x9685, 0xB6A8, 0x9686, 0xB6A9, 0x9687, 0xDC7C, 0x9688, 0xDC7E, 0x9689, 0xDCA1, 0x968A, 0xB6A4, 0x968B, 0xB6A6, 0x968D, 0xB6AA, + 0x968E, 0xB6A5, 0x9691, 0xE0D3, 0x9692, 0xE0D1, 0x9693, 0xE0D2, 0x9694, 0xB96A, 0x9695, 0xB96B, 0x9697, 0xE0D4, 0x9698, 0xB969, + 0x9699, 0xBBD8, 0x969B, 0xBBDA, 0x969C, 0xBBD9, 0x969E, 0xE4BB, 0x96A1, 0xE4BC, 0x96A2, 0xE8AB, 0x96A4, 0xE8AA, 0x96A7, 0xC047, + 0x96A8, 0xC048, 0x96A9, 0xEC4F, 0x96AA, 0xC049, 0x96AC, 0xEEF6, 0x96AE, 0xEEF4, 0x96B0, 0xEEF5, 0x96B1, 0xC1F4, 0x96B3, 0xF16F, + 0x96B4, 0xC3F7, 0x96B8, 0xC1F5, 0x96B9, 0xAB41, 0x96BB, 0xB0A6, 0x96BC, 0xD447, 0x96BF, 0xD84C, 0x96C0, 0xB3B6, 0x96C1, 0xB6AD, + 0x96C2, 0xDCA4, 0x96C3, 0xDCA6, 0x96C4, 0xB6AF, 0x96C5, 0xB6AE, 0x96C6, 0xB6B0, 0x96C7, 0xB6B1, 0x96C8, 0xDCA5, 0x96C9, 0xB96E, + 0x96CA, 0xB96F, 0x96CB, 0xB96D, 0x96CC, 0xBBDB, 0x96CD, 0xB96C, 0x96CE, 0xE0D5, 0x96D2, 0xBBDC, 0x96D3, 0xE8AC, 0x96D4, 0xEC50, + 0x96D5, 0xC04A, 0x96D6, 0xC1F6, 0x96D7, 0xF170, 0x96D8, 0xF174, 0x96D9, 0xC2F9, 0x96DA, 0xF171, 0x96DB, 0xC2FA, 0x96DC, 0xC2F8, + 0x96DD, 0xF175, 0x96DE, 0xC2FB, 0x96DF, 0xF173, 0x96E1, 0xF379, 0x96E2, 0xC2F7, 0x96E3, 0xC3F8, 0x96E5, 0xF8CD, 0x96E8, 0xAB42, + 0x96E9, 0xB3B8, 0x96EA, 0xB3B7, 0x96EF, 0xB6B2, 0x96F0, 0xDCA8, 0x96F1, 0xDCA7, 0x96F2, 0xB6B3, 0x96F5, 0xE0D9, 0x96F6, 0xB973, + 0x96F7, 0xB970, 0x96F8, 0xE0D8, 0x96F9, 0xB972, 0x96FA, 0xE0D6, 0x96FB, 0xB971, 0x96FD, 0xE0D7, 0x96FF, 0xE4BD, 0x9700, 0xBBDD, + 0x9702, 0xE8AF, 0x9704, 0xBE5D, 0x9705, 0xE8AD, 0x9706, 0xBE5E, 0x9707, 0xBE5F, 0x9708, 0xE8AE, 0x9709, 0xBE60, 0x970B, 0xEC51, + 0x970D, 0xC04E, 0x970E, 0xC04B, 0x970F, 0xC050, 0x9710, 0xEC53, 0x9711, 0xC04C, 0x9712, 0xEC52, 0x9713, 0xC04F, 0x9716, 0xC04D, + 0x9718, 0xEEF9, 0x9719, 0xEEFB, 0x971C, 0xC1F7, 0x971D, 0xEEFA, 0x971E, 0xC1F8, 0x971F, 0xEEF8, 0x9720, 0xEEF7, 0x9722, 0xF177, + 0x9723, 0xF176, 0x9724, 0xC2FC, 0x9725, 0xF178, 0x9726, 0xF37E, 0x9727, 0xC3FA, 0x9728, 0xF37D, 0x9729, 0xF37A, 0x972A, 0xC3F9, + 0x972B, 0xF37B, 0x972C, 0xF37C, 0x972E, 0xF548, 0x972F, 0xF549, 0x9730, 0xC4C5, 0x9732, 0xC553, 0x9735, 0xF66E, 0x9738, 0xC551, + 0x9739, 0xC552, 0x973A, 0xF66F, 0x973D, 0xC5B4, 0x973E, 0xC5B5, 0x973F, 0xF771, 0x9742, 0xC645, 0x9743, 0xF8CF, 0x9744, 0xC647, + 0x9746, 0xF8CE, 0x9747, 0xF8D0, 0x9748, 0xC646, 0x9749, 0xF957, 0x974B, 0xF9AD, 0x9752, 0xAB43, 0x9756, 0xB974, 0x9758, 0xE4BE, + 0x975A, 0xE8B0, 0x975B, 0xC051, 0x975C, 0xC052, 0x975E, 0xAB44, 0x9760, 0xBE61, 0x9761, 0xC3FB, 0x9762, 0xADB1, 0x9766, 0xC053, + 0x9768, 0xC5E2, 0x9769, 0xADB2, 0x976A, 0xD84D, 0x976C, 0xDCA9, 0x976E, 0xDCAB, 0x9770, 0xDCAA, 0x9772, 0xE0DD, 0x9773, 0xE0DA, + 0x9774, 0xB975, 0x9776, 0xB976, 0x9777, 0xE0DB, 0x9778, 0xE0DC, 0x977A, 0xE4C0, 0x977B, 0xE4C5, 0x977C, 0xBBDE, 0x977D, 0xE4BF, + 0x977E, 0xE4C1, 0x977F, 0xE4C8, 0x9780, 0xE4C3, 0x9781, 0xE4C7, 0x9782, 0xE4C4, 0x9783, 0xE4C2, 0x9784, 0xE4C6, 0x9785, 0xBBDF, + 0x9788, 0xE8B3, 0x978A, 0xE8B1, 0x978B, 0xBE63, 0x978D, 0xBE62, 0x978E, 0xE8B2, 0x978F, 0xBE64, 0x9794, 0xEC56, 0x9797, 0xEC55, + 0x9798, 0xC054, 0x9799, 0xEC54, 0x979A, 0xEEFC, 0x979C, 0xEEFE, 0x979D, 0xEF41, 0x979E, 0xEF40, 0x97A0, 0xC1F9, 0x97A1, 0xEEFD, + 0x97A2, 0xF1A1, 0x97A3, 0xC2FD, 0x97A4, 0xF17D, 0x97A5, 0xF1A2, 0x97A6, 0xC2FE, 0x97A8, 0xF17B, 0x97AA, 0xF17E, 0x97AB, 0xF17C, + 0x97AC, 0xF179, 0x97AD, 0xC340, 0x97AE, 0xF17A, 0x97B3, 0xF3A1, 0x97B6, 0xF3A3, 0x97B7, 0xF3A2, 0x97B9, 0xF54A, 0x97BB, 0xF54B, + 0x97BF, 0xF670, 0x97C1, 0xC5B7, 0x97C3, 0xC5B6, 0x97C4, 0xF84F, 0x97C5, 0xF850, 0x97C6, 0xC648, 0x97C7, 0xF8D1, 0x97C9, 0xC669, + 0x97CB, 0xADB3, 0x97CC, 0xB6B4, 0x97CD, 0xE4CA, 0x97CE, 0xE4C9, 0x97CF, 0xE8B5, 0x97D0, 0xE8B4, 0x97D3, 0xC1FA, 0x97D4, 0xEF43, + 0x97D5, 0xEF42, 0x97D6, 0xF1A5, 0x97D7, 0xF1A3, 0x97D8, 0xF1A6, 0x97D9, 0xF1A4, 0x97DC, 0xC3FC, 0x97DD, 0xF3A4, 0x97DE, 0xF3A5, + 0x97DF, 0xF3A6, 0x97E1, 0xF671, 0x97E3, 0xF772, 0x97E5, 0xF8D2, 0x97ED, 0xADB4, 0x97F0, 0xEC57, 0x97F1, 0xEF44, 0x97F3, 0xADB5, + 0x97F6, 0xBBE0, 0x97F8, 0xEC58, 0x97F9, 0xC341, 0x97FA, 0xF1A7, 0x97FB, 0xC3FD, 0x97FD, 0xF54C, 0x97FE, 0xF54D, 0x97FF, 0xC554, + 0x9800, 0xF851, 0x9801, 0xADB6, 0x9802, 0xB3BB, 0x9803, 0xB3BC, 0x9804, 0xD84E, 0x9805, 0xB6B5, 0x9806, 0xB6B6, 0x9807, 0xDCAC, + 0x9808, 0xB6B7, 0x980A, 0xB97A, 0x980C, 0xB97C, 0x980D, 0xE0DF, 0x980E, 0xE0E0, 0x980F, 0xE0DE, 0x9810, 0xB977, 0x9811, 0xB978, + 0x9812, 0xB97B, 0x9813, 0xB979, 0x9816, 0xE4CB, 0x9817, 0xBBE1, 0x9818, 0xBBE2, 0x981B, 0xE8BC, 0x981C, 0xBE67, 0x981D, 0xE8B7, + 0x981E, 0xE8B6, 0x9820, 0xE8BB, 0x9821, 0xBE65, 0x9824, 0xC05B, 0x9826, 0xE8B8, 0x9827, 0xE8BD, 0x9828, 0xE8BA, 0x9829, 0xE8B9, + 0x982B, 0xBE66, 0x982D, 0xC059, 0x982F, 0xEC5A, 0x9830, 0xC055, 0x9832, 0xEC5B, 0x9835, 0xEC59, 0x9837, 0xC058, 0x9838, 0xC056, + 0x9839, 0xC05A, 0x983B, 0xC057, 0x9841, 0xEF45, 0x9843, 0xEF4A, 0x9844, 0xEF46, 0x9845, 0xEF49, 0x9846, 0xC1FB, 0x9848, 0xEDD4, + 0x9849, 0xEF48, 0x984A, 0xEF47, 0x984C, 0xC344, 0x984D, 0xC342, 0x984E, 0xC345, 0x984F, 0xC343, 0x9850, 0xF1A8, 0x9851, 0xF1A9, + 0x9852, 0xF1AA, 0x9853, 0xC346, 0x9857, 0xF3AA, 0x9858, 0xC440, 0x9859, 0xF3A8, 0x985B, 0xC441, 0x985C, 0xF3A7, 0x985D, 0xF3A9, + 0x985E, 0xC3FE, 0x985F, 0xF551, 0x9860, 0xF54E, 0x9862, 0xF54F, 0x9863, 0xF550, 0x9864, 0xF672, 0x9865, 0xC556, 0x9867, 0xC555, + 0x9869, 0xF774, 0x986A, 0xF773, 0x986B, 0xC5B8, 0x986F, 0xC5E3, 0x9870, 0xC649, 0x9871, 0xC660, 0x9872, 0xF958, 0x9873, 0xF9AE, + 0x9874, 0xF9AF, 0x98A8, 0xADB7, 0x98A9, 0xDCAD, 0x98AC, 0xE0E1, 0x98AD, 0xE4CC, 0x98AE, 0xE4CD, 0x98AF, 0xBBE3, 0x98B1, 0xBBE4, + 0x98B2, 0xE8BE, 0x98B3, 0xBE68, 0x98B6, 0xC1FC, 0x98B8, 0xF1AB, 0x98BA, 0xC347, 0x98BB, 0xF3AD, 0x98BC, 0xC442, 0x98BD, 0xF3AC, + 0x98BE, 0xF3AE, 0x98BF, 0xF3AB, 0x98C0, 0xF675, 0x98C1, 0xF552, 0x98C2, 0xF553, 0x98C4, 0xC4C6, 0x98C6, 0xF674, 0x98C9, 0xF673, + 0x98CB, 0xF775, 0x98CC, 0xF9B0, 0x98DB, 0xADB8, 0x98DF, 0xADB9, 0x98E2, 0xB0A7, 0x98E3, 0xD448, 0x98E5, 0xD84F, 0x98E7, 0xB6B8, + 0x98E9, 0xB6BB, 0x98EA, 0xB6B9, 0x98EB, 0xDCAE, 0x98ED, 0xB6BD, 0x98EF, 0xB6BA, 0x98F2, 0xB6BC, 0x98F4, 0xB97E, 0x98F6, 0xE0E2, + 0x98F9, 0xE0E3, 0x98FA, 0xE8C0, 0x98FC, 0xB97D, 0x98FD, 0xB9A1, 0x98FE, 0xB9A2, 0x9900, 0xE4CF, 0x9902, 0xE4CE, 0x9903, 0xBBE5, + 0x9905, 0xBBE6, 0x9907, 0xE4D0, 0x9908, 0xE8BF, 0x9909, 0xBBE8, 0x990A, 0xBE69, 0x990C, 0xBBE7, 0x9910, 0xC05C, 0x9911, 0xE8C1, + 0x9912, 0xBE6B, 0x9913, 0xBE6A, 0x9914, 0xE8C2, 0x9915, 0xE8C5, 0x9916, 0xE8C3, 0x9917, 0xE8C4, 0x9918, 0xBE6C, 0x991A, 0xC061, + 0x991B, 0xC05F, 0x991E, 0xC05E, 0x991F, 0xEC5D, 0x9921, 0xC060, 0x9924, 0xEC5C, 0x9925, 0xEF4B, 0x9927, 0xEC5E, 0x9928, 0xC05D, + 0x9929, 0xEC5F, 0x992A, 0xEF4E, 0x992B, 0xEF4C, 0x992C, 0xEF4D, 0x992D, 0xEF52, 0x992E, 0xC34B, 0x992F, 0xEF51, 0x9930, 0xEF54, + 0x9931, 0xEF53, 0x9932, 0xEF50, 0x9933, 0xEF4F, 0x9935, 0xC1FD, 0x993A, 0xF1AE, 0x993C, 0xF1AD, 0x993D, 0xC34A, 0x993E, 0xC348, + 0x993F, 0xC349, 0x9941, 0xF1AC, 0x9943, 0xF3B1, 0x9945, 0xC443, 0x9947, 0xF3B0, 0x9948, 0xF3AF, 0x9949, 0xC444, 0x994B, 0xF558, + 0x994C, 0xF557, 0x994E, 0xF555, 0x9950, 0xF554, 0x9951, 0xC4C8, 0x9952, 0xC4C7, 0x9953, 0xF559, 0x9954, 0xF776, 0x9955, 0xC5B9, + 0x9956, 0xF677, 0x9957, 0xC557, 0x9958, 0xF676, 0x9959, 0xF556, 0x995B, 0xF777, 0x995C, 0xC5E4, 0x995E, 0xC661, 0x995F, 0xF959, + 0x9961, 0xF9B1, 0x9996, 0xADBA, 0x9997, 0xD850, 0x9998, 0xEF55, 0x9999, 0xADBB, 0x999C, 0xE4D2, 0x999D, 0xE4D1, 0x999E, 0xEC60, + 0x99A1, 0xEF57, 0x99A3, 0xEF56, 0x99A5, 0xC34C, 0x99A6, 0xF3B2, 0x99A7, 0xF3B3, 0x99A8, 0xC4C9, 0x99AB, 0xF9B2, 0x99AC, 0xB0A8, + 0x99AD, 0xB6BF, 0x99AE, 0xB6BE, 0x99AF, 0xE0E4, 0x99B0, 0xE0E6, 0x99B1, 0xB9A4, 0x99B2, 0xE0E5, 0x99B3, 0xB9A3, 0x99B4, 0xB9A5, + 0x99B5, 0xE0E7, 0x99B9, 0xE4D4, 0x99BA, 0xE4D6, 0x99BB, 0xE4D5, 0x99BD, 0xE4D8, 0x99C1, 0xBBE9, 0x99C2, 0xE4D7, 0x99C3, 0xE4D3, + 0x99C7, 0xE4D9, 0x99C9, 0xE8CC, 0x99CB, 0xE8CF, 0x99CC, 0xE8D1, 0x99CD, 0xE8C7, 0x99CE, 0xE8CB, 0x99CF, 0xE8C8, 0x99D0, 0xBE6E, + 0x99D1, 0xBE71, 0x99D2, 0xBE73, 0x99D3, 0xE8C9, 0x99D4, 0xE8CA, 0x99D5, 0xBE72, 0x99D6, 0xE8CD, 0x99D7, 0xE8D0, 0x99D8, 0xE8CE, + 0x99D9, 0xBE74, 0x99DB, 0xBE70, 0x99DC, 0xE8C6, 0x99DD, 0xBE6D, 0x99DF, 0xBE6F, 0x99E2, 0xC063, 0x99E3, 0xEC66, 0x99E4, 0xEC64, + 0x99E5, 0xEC63, 0x99E7, 0xEC69, 0x99E9, 0xEC68, 0x99EA, 0xEC67, 0x99EC, 0xEC62, 0x99ED, 0xC062, 0x99EE, 0xEC61, 0x99F0, 0xEC65, + 0x99F1, 0xC064, 0x99F4, 0xEF5A, 0x99F6, 0xEF5E, 0x99F7, 0xEF5B, 0x99F8, 0xEF5D, 0x99F9, 0xEF5C, 0x99FA, 0xEF59, 0x99FB, 0xEF5F, + 0x99FC, 0xEF62, 0x99FD, 0xEF60, 0x99FE, 0xEF61, 0x99FF, 0xC240, 0x9A01, 0xC1FE, 0x9A02, 0xEF58, 0x9A03, 0xEF63, 0x9A04, 0xF1B3, + 0x9A05, 0xF1B6, 0x9A06, 0xF1B8, 0x9A07, 0xF1B7, 0x9A09, 0xF1B1, 0x9A0A, 0xF1B5, 0x9A0B, 0xF1B0, 0x9A0D, 0xF1B2, 0x9A0E, 0xC34D, + 0x9A0F, 0xF1AF, 0x9A11, 0xF1B4, 0x9A14, 0xF3C0, 0x9A15, 0xF3B5, 0x9A16, 0xC445, 0x9A19, 0xC446, 0x9A1A, 0xF3B4, 0x9A1B, 0xF3B9, + 0x9A1C, 0xF3BF, 0x9A1D, 0xF3B7, 0x9A1E, 0xF3BE, 0x9A20, 0xF3BB, 0x9A22, 0xF3BA, 0x9A23, 0xF3BD, 0x9A24, 0xF3B8, 0x9A25, 0xF3B6, + 0x9A27, 0xF3BC, 0x9A29, 0xF560, 0x9A2A, 0xF55E, 0x9A2B, 0xC4CA, 0x9A2C, 0xF55D, 0x9A2D, 0xF563, 0x9A2E, 0xF561, 0x9A30, 0xC4CB, + 0x9A31, 0xF55C, 0x9A32, 0xF55A, 0x9A34, 0xF55B, 0x9A35, 0xC4CD, 0x9A36, 0xF55F, 0x9A37, 0xC4CC, 0x9A38, 0xF562, 0x9A39, 0xF678, + 0x9A3A, 0xF67E, 0x9A3D, 0xF679, 0x9A3E, 0xC55B, 0x9A3F, 0xF6A1, 0x9A40, 0xC55A, 0x9A41, 0xF67D, 0x9A42, 0xF67C, 0x9A43, 0xC559, + 0x9A44, 0xF67B, 0x9A45, 0xC558, 0x9A46, 0xF67A, 0x9A48, 0xF77D, 0x9A49, 0xF7A1, 0x9A4A, 0xF77E, 0x9A4C, 0xF77B, 0x9A4D, 0xC5BB, + 0x9A4E, 0xF778, 0x9A4F, 0xF77C, 0x9A50, 0xF7A3, 0x9A52, 0xF7A2, 0x9A53, 0xF779, 0x9A54, 0xF77A, 0x9A55, 0xC5BA, 0x9A56, 0xF852, + 0x9A57, 0xC5E7, 0x9A59, 0xF853, 0x9A5A, 0xC5E5, 0x9A5B, 0xC5E6, 0x9A5E, 0xF8D3, 0x9A5F, 0xC64A, 0x9A60, 0xF976, 0x9A62, 0xC66A, + 0x9A64, 0xF9B3, 0x9A65, 0xC66B, 0x9A66, 0xF9B4, 0x9A67, 0xF9B5, 0x9A68, 0xF9C3, 0x9A69, 0xF9C2, 0x9A6A, 0xC67A, 0x9A6B, 0xF9CD, + 0x9AA8, 0xB0A9, 0x9AAB, 0xE0E9, 0x9AAD, 0xE0E8, 0x9AAF, 0xBBEA, 0x9AB0, 0xBBEB, 0x9AB1, 0xE4DA, 0x9AB3, 0xE8D2, 0x9AB4, 0xEC6C, + 0x9AB7, 0xBE75, 0x9AB8, 0xC065, 0x9AB9, 0xEC6A, 0x9ABB, 0xEC6D, 0x9ABC, 0xC066, 0x9ABE, 0xEF64, 0x9ABF, 0xEC6B, 0x9AC0, 0xF1B9, + 0x9AC1, 0xC34E, 0x9AC2, 0xF3C1, 0x9AC6, 0xF566, 0x9AC7, 0xF564, 0x9ACA, 0xF565, 0x9ACD, 0xF6A2, 0x9ACF, 0xC55C, 0x9AD0, 0xF7A4, + 0x9AD1, 0xC5EA, 0x9AD2, 0xC5BC, 0x9AD3, 0xC5E8, 0x9AD4, 0xC5E9, 0x9AD5, 0xF8D4, 0x9AD6, 0xC662, 0x9AD8, 0xB0AA, 0x9ADC, 0xF1BA, + 0x9ADF, 0xD449, 0x9AE1, 0xB9A6, 0x9AE3, 0xE4DB, 0x9AE6, 0xBBEC, 0x9AE7, 0xE4DC, 0x9AEB, 0xE8D4, 0x9AEC, 0xE8D3, 0x9AED, 0xC068, + 0x9AEE, 0xBE76, 0x9AEF, 0xBE77, 0x9AF1, 0xE8D7, 0x9AF2, 0xE8D6, 0x9AF3, 0xE8D5, 0x9AF6, 0xEC6E, 0x9AF7, 0xEC71, 0x9AF9, 0xEC70, + 0x9AFA, 0xEC6F, 0x9AFB, 0xC067, 0x9AFC, 0xEF68, 0x9AFD, 0xEF66, 0x9AFE, 0xEF65, 0x9B01, 0xEF67, 0x9B03, 0xC34F, 0x9B04, 0xF1BC, + 0x9B05, 0xF1BD, 0x9B06, 0xC350, 0x9B08, 0xF1BB, 0x9B0A, 0xF3C3, 0x9B0B, 0xF3C2, 0x9B0C, 0xF3C5, 0x9B0D, 0xC447, 0x9B0E, 0xF3C4, + 0x9B10, 0xF567, 0x9B11, 0xF569, 0x9B12, 0xF568, 0x9B15, 0xF6A3, 0x9B16, 0xF6A6, 0x9B17, 0xF6A4, 0x9B18, 0xF6A5, 0x9B19, 0xF7A5, + 0x9B1A, 0xC5BD, 0x9B1E, 0xF854, 0x9B1F, 0xF855, 0x9B20, 0xF856, 0x9B22, 0xC64B, 0x9B23, 0xC663, 0x9B24, 0xF9B6, 0x9B25, 0xB0AB, + 0x9B27, 0xBE78, 0x9B28, 0xC069, 0x9B29, 0xF1BE, 0x9B2B, 0xF7A6, 0x9B2E, 0xF9C4, 0x9B2F, 0xD44A, 0x9B31, 0xC67B, 0x9B32, 0xB0AC, + 0x9B33, 0xEC72, 0x9B35, 0xF1BF, 0x9B37, 0xF3C6, 0x9B3A, 0xF6A7, 0x9B3B, 0xF7A7, 0x9B3C, 0xB0AD, 0x9B3E, 0xE4DD, 0x9B3F, 0xE4DE, + 0x9B41, 0xBBED, 0x9B42, 0xBBEE, 0x9B43, 0xE8D9, 0x9B44, 0xBE7A, 0x9B45, 0xBE79, 0x9B46, 0xE8D8, 0x9B48, 0xEF69, 0x9B4A, 0xF1C0, + 0x9B4B, 0xF1C2, 0x9B4C, 0xF1C1, 0x9B4D, 0xC353, 0x9B4E, 0xC352, 0x9B4F, 0xC351, 0x9B51, 0xC55E, 0x9B52, 0xF6A8, 0x9B54, 0xC55D, + 0x9B55, 0xF7A9, 0x9B56, 0xF7A8, 0x9B58, 0xC64C, 0x9B59, 0xF8D5, 0x9B5A, 0xB3BD, 0x9B5B, 0xE0EA, 0x9B5F, 0xE4E1, 0x9B60, 0xE4DF, + 0x9B61, 0xE4E0, 0x9B64, 0xE8E2, 0x9B66, 0xE8DD, 0x9B67, 0xE8DA, 0x9B68, 0xE8E1, 0x9B6C, 0xE8E3, 0x9B6F, 0xBE7C, 0x9B70, 0xE8E0, + 0x9B71, 0xE8DC, 0x9B74, 0xE8DB, 0x9B75, 0xE8DF, 0x9B76, 0xE8DE, 0x9B77, 0xBE7B, 0x9B7A, 0xEC7D, 0x9B7B, 0xEC78, 0x9B7C, 0xEC76, + 0x9B7D, 0xECA1, 0x9B7E, 0xEC77, 0x9B80, 0xEC73, 0x9B82, 0xEC79, 0x9B85, 0xEC74, 0x9B86, 0xEF72, 0x9B87, 0xEC75, 0x9B88, 0xECA2, + 0x9B90, 0xEC7C, 0x9B91, 0xC06A, 0x9B92, 0xEC7B, 0x9B93, 0xEC7A, 0x9B95, 0xEC7E, 0x9B9A, 0xEF6A, 0x9B9B, 0xEF6D, 0x9B9E, 0xEF6C, + 0x9BA0, 0xEF74, 0x9BA1, 0xEF6F, 0x9BA2, 0xEF73, 0x9BA4, 0xEF71, 0x9BA5, 0xEF70, 0x9BA6, 0xEF6E, 0x9BA8, 0xEF6B, 0x9BAA, 0xC243, + 0x9BAB, 0xC242, 0x9BAD, 0xC244, 0x9BAE, 0xC241, 0x9BAF, 0xEF75, 0x9BB5, 0xF1C8, 0x9BB6, 0xF1CB, 0x9BB8, 0xF1C9, 0x9BB9, 0xF1CD, + 0x9BBD, 0xF1CE, 0x9BBF, 0xF1C6, 0x9BC0, 0xC358, 0x9BC1, 0xF1C7, 0x9BC3, 0xF1C5, 0x9BC4, 0xF1CC, 0x9BC6, 0xF1C4, 0x9BC7, 0xF1C3, + 0x9BC8, 0xC357, 0x9BC9, 0xC355, 0x9BCA, 0xC354, 0x9BD3, 0xF1CA, 0x9BD4, 0xF3CF, 0x9BD5, 0xF3D5, 0x9BD6, 0xC44A, 0x9BD7, 0xF3D0, + 0x9BD9, 0xF3D3, 0x9BDA, 0xF3D7, 0x9BDB, 0xC44B, 0x9BDC, 0xF3D2, 0x9BDE, 0xF3CA, 0x9BE0, 0xF3C9, 0x9BE1, 0xF3D6, 0x9BE2, 0xF3CD, + 0x9BE4, 0xF3CB, 0x9BE5, 0xF3D4, 0x9BE6, 0xF3CC, 0x9BE7, 0xC449, 0x9BE8, 0xC448, 0x9BEA, 0xF3C7, 0x9BEB, 0xF3C8, 0x9BEC, 0xF3D1, + 0x9BF0, 0xF3CE, 0x9BF7, 0xF56C, 0x9BF8, 0xF56F, 0x9BFD, 0xC356, 0x9C05, 0xF56D, 0x9C06, 0xF573, 0x9C07, 0xF571, 0x9C08, 0xF56B, + 0x9C09, 0xF576, 0x9C0B, 0xF56A, 0x9C0D, 0xC4CF, 0x9C0E, 0xF572, 0x9C12, 0xF56E, 0x9C13, 0xC4CE, 0x9C14, 0xF575, 0x9C17, 0xF574, + 0x9C1C, 0xF6AB, 0x9C1D, 0xF6AA, 0x9C21, 0xF6B1, 0x9C23, 0xF6AD, 0x9C24, 0xF6B0, 0x9C25, 0xC560, 0x9C28, 0xF6AE, 0x9C29, 0xF6AF, + 0x9C2B, 0xF6A9, 0x9C2C, 0xF6AC, 0x9C2D, 0xC55F, 0x9C31, 0xC5BF, 0x9C32, 0xF7B4, 0x9C33, 0xF7AF, 0x9C34, 0xF7B3, 0x9C36, 0xF7B6, + 0x9C37, 0xF7B2, 0x9C39, 0xF7AE, 0x9C3B, 0xC5C1, 0x9C3C, 0xF7B1, 0x9C3D, 0xF7B5, 0x9C3E, 0xC5C0, 0x9C3F, 0xF7AC, 0x9C40, 0xF570, + 0x9C41, 0xF7B0, 0x9C44, 0xF7AD, 0x9C46, 0xF7AA, 0x9C48, 0xF7AB, 0x9C49, 0xC5BE, 0x9C4A, 0xF85A, 0x9C4B, 0xF85C, 0x9C4C, 0xF85F, + 0x9C4D, 0xF85B, 0x9C4E, 0xF860, 0x9C50, 0xF859, 0x9C52, 0xF857, 0x9C54, 0xC5EB, 0x9C55, 0xF85D, 0x9C56, 0xC5ED, 0x9C57, 0xC5EC, + 0x9C58, 0xF858, 0x9C59, 0xF85E, 0x9C5E, 0xF8DA, 0x9C5F, 0xC64D, 0x9C60, 0xF8DB, 0x9C62, 0xF8D9, 0x9C63, 0xF8D6, 0x9C66, 0xF8D8, + 0x9C67, 0xF8D7, 0x9C68, 0xF95A, 0x9C6D, 0xF95C, 0x9C6E, 0xF95B, 0x9C71, 0xF979, 0x9C73, 0xF978, 0x9C74, 0xF977, 0x9C75, 0xF97A, + 0x9C77, 0xC673, 0x9C78, 0xC674, 0x9C79, 0xF9CA, 0x9C7A, 0xF9CE, 0x9CE5, 0xB3BE, 0x9CE6, 0xDCAF, 0x9CE7, 0xE0ED, 0x9CE9, 0xB9A7, + 0x9CEA, 0xE0EB, 0x9CED, 0xE0EC, 0x9CF1, 0xE4E2, 0x9CF2, 0xE4E3, 0x9CF3, 0xBBF1, 0x9CF4, 0xBBEF, 0x9CF5, 0xE4E4, 0x9CF6, 0xBBF0, + 0x9CF7, 0xE8E8, 0x9CF9, 0xE8EB, 0x9CFA, 0xE8E5, 0x9CFB, 0xE8EC, 0x9CFC, 0xE8E4, 0x9CFD, 0xE8E6, 0x9CFF, 0xE8E7, 0x9D00, 0xE8EA, + 0x9D03, 0xBEA1, 0x9D04, 0xE8EF, 0x9D05, 0xE8EE, 0x9D06, 0xBE7D, 0x9D07, 0xE8E9, 0x9D08, 0xE8ED, 0x9D09, 0xBE7E, 0x9D10, 0xECAC, + 0x9D12, 0xC06F, 0x9D14, 0xECA7, 0x9D15, 0xC06B, 0x9D17, 0xECA4, 0x9D18, 0xECAA, 0x9D19, 0xECAD, 0x9D1B, 0xC070, 0x9D1D, 0xECA9, + 0x9D1E, 0xECA6, 0x9D1F, 0xECAE, 0x9D20, 0xECA5, 0x9D22, 0xECAB, 0x9D23, 0xC06C, 0x9D25, 0xECA3, 0x9D26, 0xC06D, 0x9D28, 0xC06E, + 0x9D29, 0xECA8, 0x9D2D, 0xEFA9, 0x9D2E, 0xEF7A, 0x9D2F, 0xEF7B, 0x9D30, 0xEF7E, 0x9D31, 0xEF7C, 0x9D33, 0xEF76, 0x9D36, 0xEF79, + 0x9D37, 0xEFA5, 0x9D38, 0xEF7D, 0x9D3B, 0xC245, 0x9D3D, 0xEFA7, 0x9D3E, 0xEFA4, 0x9D3F, 0xC246, 0x9D40, 0xEFA6, 0x9D41, 0xEF77, + 0x9D42, 0xEFA2, 0x9D43, 0xEFA3, 0x9D45, 0xEFA1, 0x9D4A, 0xF1D2, 0x9D4B, 0xF1D4, 0x9D4C, 0xF1D7, 0x9D4F, 0xF1D1, 0x9D51, 0xC359, + 0x9D52, 0xF1D9, 0x9D53, 0xF1D0, 0x9D54, 0xF1DA, 0x9D56, 0xF1D6, 0x9D57, 0xF1D8, 0x9D58, 0xF1DC, 0x9D59, 0xF1D5, 0x9D5A, 0xF1DD, + 0x9D5B, 0xF1D3, 0x9D5C, 0xF1CF, 0x9D5D, 0xC35A, 0x9D5F, 0xF1DB, 0x9D60, 0xC35B, 0x9D61, 0xC44D, 0x9D67, 0xEF78, 0x9D68, 0xF3F1, + 0x9D69, 0xF3E8, 0x9D6A, 0xC44F, 0x9D6B, 0xF3E4, 0x9D6C, 0xC450, 0x9D6F, 0xF3ED, 0x9D70, 0xF3E7, 0x9D71, 0xF3DD, 0x9D72, 0xC44E, + 0x9D73, 0xF3EA, 0x9D74, 0xF3E5, 0x9D75, 0xF3E6, 0x9D77, 0xF3D8, 0x9D78, 0xF3DF, 0x9D79, 0xF3EE, 0x9D7B, 0xF3EB, 0x9D7D, 0xF3E3, + 0x9D7F, 0xF3EF, 0x9D80, 0xF3DE, 0x9D81, 0xF3D9, 0x9D82, 0xF3EC, 0x9D84, 0xF3DB, 0x9D85, 0xF3E9, 0x9D86, 0xF3E0, 0x9D87, 0xF3F0, + 0x9D88, 0xF3DC, 0x9D89, 0xC44C, 0x9D8A, 0xF3DA, 0x9D8B, 0xF3E1, 0x9D8C, 0xF3E2, 0x9D90, 0xF57D, 0x9D92, 0xF57B, 0x9D94, 0xF5A2, + 0x9D96, 0xF5AE, 0x9D97, 0xF5A5, 0x9D98, 0xF57C, 0x9D99, 0xF578, 0x9D9A, 0xF5A7, 0x9D9B, 0xF57E, 0x9D9C, 0xF5A3, 0x9D9D, 0xF57A, + 0x9D9E, 0xF5AA, 0x9D9F, 0xF577, 0x9DA0, 0xF5A1, 0x9DA1, 0xF5A6, 0x9DA2, 0xF5A8, 0x9DA3, 0xF5AB, 0x9DA4, 0xF579, 0x9DA6, 0xF5AF, + 0x9DA7, 0xF5B0, 0x9DA8, 0xF5A9, 0x9DA9, 0xF5AD, 0x9DAA, 0xF5A4, 0x9DAC, 0xF6C1, 0x9DAD, 0xF6C4, 0x9DAF, 0xC561, 0x9DB1, 0xF6C3, + 0x9DB2, 0xF6C8, 0x9DB3, 0xF6C6, 0x9DB4, 0xC562, 0x9DB5, 0xF6BD, 0x9DB6, 0xF6B3, 0x9DB7, 0xF6B2, 0x9DB8, 0xC564, 0x9DB9, 0xF6BF, + 0x9DBA, 0xF6C0, 0x9DBB, 0xF6BC, 0x9DBC, 0xF6B4, 0x9DBE, 0xF6B9, 0x9DBF, 0xF5AC, 0x9DC1, 0xF6B5, 0x9DC2, 0xC563, 0x9DC3, 0xF6BB, + 0x9DC5, 0xF6BA, 0x9DC7, 0xF6B6, 0x9DC8, 0xF6C2, 0x9DCA, 0xF6B7, 0x9DCB, 0xF7BB, 0x9DCC, 0xF6C5, 0x9DCD, 0xF6C7, 0x9DCE, 0xF6BE, + 0x9DCF, 0xF6B8, 0x9DD0, 0xF7BC, 0x9DD1, 0xF7BE, 0x9DD2, 0xF7B8, 0x9DD3, 0xC5C2, 0x9DD5, 0xF7C5, 0x9DD6, 0xF7C3, 0x9DD7, 0xC5C3, + 0x9DD8, 0xF7C2, 0x9DD9, 0xF7C1, 0x9DDA, 0xF7BA, 0x9DDB, 0xF7B7, 0x9DDC, 0xF7BD, 0x9DDD, 0xF7C6, 0x9DDE, 0xF7B9, 0x9DDF, 0xF7BF, + 0x9DE1, 0xF869, 0x9DE2, 0xF86E, 0x9DE3, 0xF864, 0x9DE4, 0xF867, 0x9DE5, 0xC5EE, 0x9DE6, 0xF86B, 0x9DE8, 0xF872, 0x9DE9, 0xF7C0, + 0x9DEB, 0xF865, 0x9DEC, 0xF86F, 0x9DED, 0xF873, 0x9DEE, 0xF86A, 0x9DEF, 0xF863, 0x9DF0, 0xF86D, 0x9DF2, 0xF86C, 0x9DF3, 0xF871, + 0x9DF4, 0xF870, 0x9DF5, 0xF7C4, 0x9DF6, 0xF868, 0x9DF7, 0xF862, 0x9DF8, 0xF866, 0x9DF9, 0xC64E, 0x9DFA, 0xC64F, 0x9DFB, 0xF861, + 0x9DFD, 0xF8E6, 0x9DFE, 0xF8DD, 0x9DFF, 0xF8E5, 0x9E00, 0xF8E2, 0x9E01, 0xF8E3, 0x9E02, 0xF8DC, 0x9E03, 0xF8DF, 0x9E04, 0xF8E7, + 0x9E05, 0xF8E1, 0x9E06, 0xF8E0, 0x9E07, 0xF8DE, 0x9E09, 0xF8E4, 0x9E0B, 0xF95D, 0x9E0D, 0xF95E, 0x9E0F, 0xF960, 0x9E10, 0xF95F, + 0x9E11, 0xF962, 0x9E12, 0xF961, 0x9E13, 0xF97C, 0x9E14, 0xF97B, 0x9E15, 0xF9B7, 0x9E17, 0xF9B8, 0x9E19, 0xF9C5, 0x9E1A, 0xC678, + 0x9E1B, 0xC67C, 0x9E1D, 0xF9CF, 0x9E1E, 0xC67D, 0x9E75, 0xB3BF, 0x9E79, 0xC4D0, 0x9E7A, 0xF6C9, 0x9E7C, 0xC650, 0x9E7D, 0xC651, + 0x9E7F, 0xB3C0, 0x9E80, 0xE0EE, 0x9E82, 0xB9A8, 0x9E83, 0xE8F0, 0x9E86, 0xECB0, 0x9E87, 0xECB1, 0x9E88, 0xECAF, 0x9E89, 0xEFAB, + 0x9E8A, 0xEFAA, 0x9E8B, 0xC247, 0x9E8C, 0xF1DF, 0x9E8D, 0xEFAC, 0x9E8E, 0xF1DE, 0x9E91, 0xF3F3, 0x9E92, 0xC451, 0x9E93, 0xC453, + 0x9E94, 0xF3F2, 0x9E97, 0xC452, 0x9E99, 0xF5B1, 0x9E9A, 0xF5B3, 0x9E9B, 0xF5B2, 0x9E9C, 0xF6CA, 0x9E9D, 0xC565, 0x9E9F, 0xC5EF, + 0x9EA0, 0xF8E8, 0x9EA1, 0xF963, 0x9EA4, 0xF9D2, 0x9EA5, 0xB3C1, 0x9EA7, 0xE4E5, 0x9EA9, 0xBEA2, 0x9EAD, 0xECB3, 0x9EAE, 0xECB2, + 0x9EB0, 0xEFAD, 0x9EB4, 0xC454, 0x9EB5, 0xC4D1, 0x9EB6, 0xF7C7, 0x9EB7, 0xF9CB, 0x9EBB, 0xB3C2, 0x9EBC, 0xBBF2, 0x9EBE, 0xBEA3, + 0x9EC0, 0xF3F4, 0x9EC2, 0xF874, 0x9EC3, 0xB6C0, 0x9EC8, 0xEFAE, 0x9ECC, 0xC664, 0x9ECD, 0xB6C1, 0x9ECE, 0xBEA4, 0x9ECF, 0xC248, + 0x9ED0, 0xF875, 0x9ED1, 0xB6C2, 0x9ED3, 0xE8F1, 0x9ED4, 0xC072, 0x9ED5, 0xECB4, 0x9ED6, 0xECB5, 0x9ED8, 0xC071, 0x9EDA, 0xEFAF, + 0x9EDB, 0xC24C, 0x9EDC, 0xC24A, 0x9EDD, 0xC24B, 0x9EDE, 0xC249, 0x9EDF, 0xF1E0, 0x9EE0, 0xC35C, 0x9EE4, 0xF5B5, 0x9EE5, 0xF5B4, + 0x9EE6, 0xF5B7, 0x9EE7, 0xF5B6, 0x9EE8, 0xC4D2, 0x9EEB, 0xF6CB, 0x9EED, 0xF6CD, 0x9EEE, 0xF6CC, 0x9EEF, 0xC566, 0x9EF0, 0xF7C8, + 0x9EF2, 0xF876, 0x9EF3, 0xF877, 0x9EF4, 0xC5F0, 0x9EF5, 0xF964, 0x9EF6, 0xF97D, 0x9EF7, 0xC675, 0x9EF9, 0xDCB0, 0x9EFA, 0xECB6, + 0x9EFB, 0xEFB0, 0x9EFC, 0xF3F5, 0x9EFD, 0xE0EF, 0x9EFF, 0xEFB1, 0x9F00, 0xF1E2, 0x9F01, 0xF1E1, 0x9F06, 0xF878, 0x9F07, 0xC652, + 0x9F09, 0xF965, 0x9F0A, 0xF97E, 0x9F0E, 0xB9A9, 0x9F0F, 0xE8F2, 0x9F10, 0xE8F3, 0x9F12, 0xECB7, 0x9F13, 0xB9AA, 0x9F15, 0xC35D, + 0x9F16, 0xF1E3, 0x9F18, 0xF6CF, 0x9F19, 0xC567, 0x9F1A, 0xF6D0, 0x9F1B, 0xF6CE, 0x9F1C, 0xF879, 0x9F1E, 0xF8E9, 0x9F20, 0xB9AB, + 0x9F22, 0xEFB4, 0x9F23, 0xEFB3, 0x9F24, 0xEFB2, 0x9F25, 0xF1E4, 0x9F28, 0xF1E8, 0x9F29, 0xF1E7, 0x9F2A, 0xF1E6, 0x9F2B, 0xF1E5, + 0x9F2C, 0xC35E, 0x9F2D, 0xF3F6, 0x9F2E, 0xF5B9, 0x9F2F, 0xC4D3, 0x9F30, 0xF5B8, 0x9F31, 0xF6D1, 0x9F32, 0xF7CB, 0x9F33, 0xF7CA, + 0x9F34, 0xC5C4, 0x9F35, 0xF7C9, 0x9F36, 0xF87C, 0x9F37, 0xF87B, 0x9F38, 0xF87A, 0x9F3B, 0xBBF3, 0x9F3D, 0xECB8, 0x9F3E, 0xC24D, + 0x9F40, 0xF3F7, 0x9F41, 0xF3F8, 0x9F42, 0xF7CC, 0x9F43, 0xF87D, 0x9F46, 0xF8EA, 0x9F47, 0xF966, 0x9F48, 0xF9B9, 0x9F49, 0xF9D4, + 0x9F4A, 0xBBF4, 0x9F4B, 0xC24E, 0x9F4C, 0xF1E9, 0x9F4D, 0xF3F9, 0x9F4E, 0xF6D2, 0x9F4F, 0xF87E, 0x9F52, 0xBEA6, 0x9F54, 0xEFB5, + 0x9F55, 0xF1EA, 0x9F56, 0xF3FA, 0x9F57, 0xF3FB, 0x9F58, 0xF3FC, 0x9F59, 0xF5BE, 0x9F5B, 0xF5BA, 0x9F5C, 0xC568, 0x9F5D, 0xF5BD, + 0x9F5E, 0xF5BC, 0x9F5F, 0xC4D4, 0x9F60, 0xF5BB, 0x9F61, 0xC4D6, 0x9F63, 0xC4D5, 0x9F64, 0xF6D4, 0x9F65, 0xF6D3, 0x9F66, 0xC569, + 0x9F67, 0xC56A, 0x9F6A, 0xC5C6, 0x9F6B, 0xF7CD, 0x9F6C, 0xC5C5, 0x9F6E, 0xF8A3, 0x9F6F, 0xF8A4, 0x9F70, 0xF8A2, 0x9F71, 0xF8A1, + 0x9F72, 0xC654, 0x9F74, 0xF8EB, 0x9F75, 0xF8EC, 0x9F76, 0xF8ED, 0x9F77, 0xC653, 0x9F78, 0xF967, 0x9F79, 0xF96A, 0x9F7A, 0xF969, + 0x9F7B, 0xF968, 0x9F7E, 0xF9D3, 0x9F8D, 0xC073, 0x9F90, 0xC365, 0x9F91, 0xF5BF, 0x9F92, 0xF6D5, 0x9F94, 0xC5C7, 0x9F95, 0xF7CE, + 0x9F98, 0xF9D5, 0x9F9C, 0xC074, 0x9FA0, 0xEFB6, 0x9FA2, 0xF7CF, 0x9FA4, 0xF9A1, 0xFA0C, 0xC94A, 0xFA0D, 0xDDFC, 0xFE30, 0xA14A, + 0xFE31, 0xA157, 0xFE33, 0xA159, 0xFE34, 0xA15B, 0xFE35, 0xA15F, 0xFE36, 0xA160, 0xFE37, 0xA163, 0xFE38, 0xA164, 0xFE39, 0xA167, + 0xFE3A, 0xA168, 0xFE3B, 0xA16B, 0xFE3C, 0xA16C, 0xFE3D, 0xA16F, 0xFE3E, 0xA170, 0xFE3F, 0xA173, 0xFE40, 0xA174, 0xFE41, 0xA177, + 0xFE42, 0xA178, 0xFE43, 0xA17B, 0xFE44, 0xA17C, 0xFE49, 0xA1C6, 0xFE4A, 0xA1C7, 0xFE4B, 0xA1CA, 0xFE4C, 0xA1CB, 0xFE4D, 0xA1C8, + 0xFE4E, 0xA1C9, 0xFE4F, 0xA15C, 0xFE50, 0xA14D, 0xFE51, 0xA14E, 0xFE52, 0xA14F, 0xFE54, 0xA151, 0xFE55, 0xA152, 0xFE56, 0xA153, + 0xFE57, 0xA154, 0xFE59, 0xA17D, 0xFE5A, 0xA17E, 0xFE5B, 0xA1A1, 0xFE5C, 0xA1A2, 0xFE5D, 0xA1A3, 0xFE5E, 0xA1A4, 0xFE5F, 0xA1CC, + 0xFE60, 0xA1CD, 0xFE61, 0xA1CE, 0xFE62, 0xA1DE, 0xFE63, 0xA1DF, 0xFE64, 0xA1E0, 0xFE65, 0xA1E1, 0xFE66, 0xA1E2, 0xFE68, 0xA242, + 0xFE69, 0xA24C, 0xFE6A, 0xA24D, 0xFE6B, 0xA24E, 0xFF01, 0xA149, 0xFF03, 0xA1AD, 0xFF04, 0xA243, 0xFF05, 0xA248, 0xFF06, 0xA1AE, + 0xFF08, 0xA15D, 0xFF09, 0xA15E, 0xFF0A, 0xA1AF, 0xFF0B, 0xA1CF, 0xFF0C, 0xA141, 0xFF0D, 0xA1D0, 0xFF0E, 0xA144, 0xFF0F, 0xA1FE, + 0xFF10, 0xA2AF, 0xFF11, 0xA2B0, 0xFF12, 0xA2B1, 0xFF13, 0xA2B2, 0xFF14, 0xA2B3, 0xFF15, 0xA2B4, 0xFF16, 0xA2B5, 0xFF17, 0xA2B6, + 0xFF18, 0xA2B7, 0xFF19, 0xA2B8, 0xFF1A, 0xA147, 0xFF1B, 0xA146, 0xFF1C, 0xA1D5, 0xFF1D, 0xA1D7, 0xFF1E, 0xA1D6, 0xFF1F, 0xA148, + 0xFF20, 0xA249, 0xFF21, 0xA2CF, 0xFF22, 0xA2D0, 0xFF23, 0xA2D1, 0xFF24, 0xA2D2, 0xFF25, 0xA2D3, 0xFF26, 0xA2D4, 0xFF27, 0xA2D5, + 0xFF28, 0xA2D6, 0xFF29, 0xA2D7, 0xFF2A, 0xA2D8, 0xFF2B, 0xA2D9, 0xFF2C, 0xA2DA, 0xFF2D, 0xA2DB, 0xFF2E, 0xA2DC, 0xFF2F, 0xA2DD, + 0xFF30, 0xA2DE, 0xFF31, 0xA2DF, 0xFF32, 0xA2E0, 0xFF33, 0xA2E1, 0xFF34, 0xA2E2, 0xFF35, 0xA2E3, 0xFF36, 0xA2E4, 0xFF37, 0xA2E5, + 0xFF38, 0xA2E6, 0xFF39, 0xA2E7, 0xFF3A, 0xA2E8, 0xFF3C, 0xA240, 0xFF3F, 0xA1C4, 0xFF41, 0xA2E9, 0xFF42, 0xA2EA, 0xFF43, 0xA2EB, + 0xFF44, 0xA2EC, 0xFF45, 0xA2ED, 0xFF46, 0xA2EE, 0xFF47, 0xA2EF, 0xFF48, 0xA2F0, 0xFF49, 0xA2F1, 0xFF4A, 0xA2F2, 0xFF4B, 0xA2F3, + 0xFF4C, 0xA2F4, 0xFF4D, 0xA2F5, 0xFF4E, 0xA2F6, 0xFF4F, 0xA2F7, 0xFF50, 0xA2F8, 0xFF51, 0xA2F9, 0xFF52, 0xA2FA, 0xFF53, 0xA2FB, + 0xFF54, 0xA2FC, 0xFF55, 0xA2FD, 0xFF56, 0xA2FE, 0xFF57, 0xA340, 0xFF58, 0xA341, 0xFF59, 0xA342, 0xFF5A, 0xA343, 0xFF5B, 0xA161, + 0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0 +}; + +static const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */ + 0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A, + 0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52, + 0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31, + 0xA158, 0x2014, 0xA159, 0xFE33, 0xA15A, 0x2574, 0xA15B, 0xFE34, 0xA15C, 0xFE4F, 0xA15D, 0xFF08, 0xA15E, 0xFF09, 0xA15F, 0xFE35, + 0xA160, 0xFE36, 0xA161, 0xFF5B, 0xA162, 0xFF5D, 0xA163, 0xFE37, 0xA164, 0xFE38, 0xA165, 0x3014, 0xA166, 0x3015, 0xA167, 0xFE39, + 0xA168, 0xFE3A, 0xA169, 0x3010, 0xA16A, 0x3011, 0xA16B, 0xFE3B, 0xA16C, 0xFE3C, 0xA16D, 0x300A, 0xA16E, 0x300B, 0xA16F, 0xFE3D, + 0xA170, 0xFE3E, 0xA171, 0x3008, 0xA172, 0x3009, 0xA173, 0xFE3F, 0xA174, 0xFE40, 0xA175, 0x300C, 0xA176, 0x300D, 0xA177, 0xFE41, + 0xA178, 0xFE42, 0xA179, 0x300E, 0xA17A, 0x300F, 0xA17B, 0xFE43, 0xA17C, 0xFE44, 0xA17D, 0xFE59, 0xA17E, 0xFE5A, 0xA1A1, 0xFE5B, + 0xA1A2, 0xFE5C, 0xA1A3, 0xFE5D, 0xA1A4, 0xFE5E, 0xA1A5, 0x2018, 0xA1A6, 0x2019, 0xA1A7, 0x201C, 0xA1A8, 0x201D, 0xA1A9, 0x301D, + 0xA1AA, 0x301E, 0xA1AB, 0x2035, 0xA1AC, 0x2032, 0xA1AD, 0xFF03, 0xA1AE, 0xFF06, 0xA1AF, 0xFF0A, 0xA1B0, 0x203B, 0xA1B1, 0x00A7, + 0xA1B2, 0x3003, 0xA1B3, 0x25CB, 0xA1B4, 0x25CF, 0xA1B5, 0x25B3, 0xA1B6, 0x25B2, 0xA1B7, 0x25CE, 0xA1B8, 0x2606, 0xA1B9, 0x2605, + 0xA1BA, 0x25C7, 0xA1BB, 0x25C6, 0xA1BC, 0x25A1, 0xA1BD, 0x25A0, 0xA1BE, 0x25BD, 0xA1BF, 0x25BC, 0xA1C0, 0x32A3, 0xA1C1, 0x2105, + 0xA1C2, 0x00AF, 0xA1C3, 0xFFE3, 0xA1C4, 0xFF3F, 0xA1C5, 0x02CD, 0xA1C6, 0xFE49, 0xA1C7, 0xFE4A, 0xA1C8, 0xFE4D, 0xA1C9, 0xFE4E, + 0xA1CA, 0xFE4B, 0xA1CB, 0xFE4C, 0xA1CC, 0xFE5F, 0xA1CD, 0xFE60, 0xA1CE, 0xFE61, 0xA1CF, 0xFF0B, 0xA1D0, 0xFF0D, 0xA1D1, 0x00D7, + 0xA1D2, 0x00F7, 0xA1D3, 0x00B1, 0xA1D4, 0x221A, 0xA1D5, 0xFF1C, 0xA1D6, 0xFF1E, 0xA1D7, 0xFF1D, 0xA1D8, 0x2266, 0xA1D9, 0x2267, + 0xA1DA, 0x2260, 0xA1DB, 0x221E, 0xA1DC, 0x2252, 0xA1DD, 0x2261, 0xA1DE, 0xFE62, 0xA1DF, 0xFE63, 0xA1E0, 0xFE64, 0xA1E1, 0xFE65, + 0xA1E2, 0xFE66, 0xA1E3, 0xFF5E, 0xA1E4, 0x2229, 0xA1E5, 0x222A, 0xA1E6, 0x22A5, 0xA1E7, 0x2220, 0xA1E8, 0x221F, 0xA1E9, 0x22BF, + 0xA1EA, 0x33D2, 0xA1EB, 0x33D1, 0xA1EC, 0x222B, 0xA1ED, 0x222E, 0xA1EE, 0x2235, 0xA1EF, 0x2234, 0xA1F0, 0x2640, 0xA1F1, 0x2642, + 0xA1F2, 0x2295, 0xA1F3, 0x2299, 0xA1F4, 0x2191, 0xA1F5, 0x2193, 0xA1F6, 0x2190, 0xA1F7, 0x2192, 0xA1F8, 0x2196, 0xA1F9, 0x2197, + 0xA1FA, 0x2199, 0xA1FB, 0x2198, 0xA1FC, 0x2225, 0xA1FD, 0x2223, 0xA1FE, 0xFF0F, 0xA240, 0xFF3C, 0xA241, 0x2215, 0xA242, 0xFE68, + 0xA243, 0xFF04, 0xA244, 0xFFE5, 0xA245, 0x3012, 0xA246, 0xFFE0, 0xA247, 0xFFE1, 0xA248, 0xFF05, 0xA249, 0xFF20, 0xA24A, 0x2103, + 0xA24B, 0x2109, 0xA24C, 0xFE69, 0xA24D, 0xFE6A, 0xA24E, 0xFE6B, 0xA24F, 0x33D5, 0xA250, 0x339C, 0xA251, 0x339D, 0xA252, 0x339E, + 0xA253, 0x33CE, 0xA254, 0x33A1, 0xA255, 0x338E, 0xA256, 0x338F, 0xA257, 0x33C4, 0xA258, 0x00B0, 0xA259, 0x5159, 0xA25A, 0x515B, + 0xA25B, 0x515E, 0xA25C, 0x515D, 0xA25D, 0x5161, 0xA25E, 0x5163, 0xA25F, 0x55E7, 0xA260, 0x74E9, 0xA261, 0x7CCE, 0xA262, 0x2581, + 0xA263, 0x2582, 0xA264, 0x2583, 0xA265, 0x2584, 0xA266, 0x2585, 0xA267, 0x2586, 0xA268, 0x2587, 0xA269, 0x2588, 0xA26A, 0x258F, + 0xA26B, 0x258E, 0xA26C, 0x258D, 0xA26D, 0x258C, 0xA26E, 0x258B, 0xA26F, 0x258A, 0xA270, 0x2589, 0xA271, 0x253C, 0xA272, 0x2534, + 0xA273, 0x252C, 0xA274, 0x2524, 0xA275, 0x251C, 0xA276, 0x2594, 0xA277, 0x2500, 0xA278, 0x2502, 0xA279, 0x2595, 0xA27A, 0x250C, + 0xA27B, 0x2510, 0xA27C, 0x2514, 0xA27D, 0x2518, 0xA27E, 0x256D, 0xA2A1, 0x256E, 0xA2A2, 0x2570, 0xA2A3, 0x256F, 0xA2A4, 0x2550, + 0xA2A5, 0x255E, 0xA2A6, 0x256A, 0xA2A7, 0x2561, 0xA2A8, 0x25E2, 0xA2A9, 0x25E3, 0xA2AA, 0x25E5, 0xA2AB, 0x25E4, 0xA2AC, 0x2571, + 0xA2AD, 0x2572, 0xA2AE, 0x2573, 0xA2AF, 0xFF10, 0xA2B0, 0xFF11, 0xA2B1, 0xFF12, 0xA2B2, 0xFF13, 0xA2B3, 0xFF14, 0xA2B4, 0xFF15, + 0xA2B5, 0xFF16, 0xA2B6, 0xFF17, 0xA2B7, 0xFF18, 0xA2B8, 0xFF19, 0xA2B9, 0x2160, 0xA2BA, 0x2161, 0xA2BB, 0x2162, 0xA2BC, 0x2163, + 0xA2BD, 0x2164, 0xA2BE, 0x2165, 0xA2BF, 0x2166, 0xA2C0, 0x2167, 0xA2C1, 0x2168, 0xA2C2, 0x2169, 0xA2C3, 0x3021, 0xA2C4, 0x3022, + 0xA2C5, 0x3023, 0xA2C6, 0x3024, 0xA2C7, 0x3025, 0xA2C8, 0x3026, 0xA2C9, 0x3027, 0xA2CA, 0x3028, 0xA2CB, 0x3029, 0xA2CC, 0x5341, + 0xA2CD, 0x5344, 0xA2CE, 0x5345, 0xA2CF, 0xFF21, 0xA2D0, 0xFF22, 0xA2D1, 0xFF23, 0xA2D2, 0xFF24, 0xA2D3, 0xFF25, 0xA2D4, 0xFF26, + 0xA2D5, 0xFF27, 0xA2D6, 0xFF28, 0xA2D7, 0xFF29, 0xA2D8, 0xFF2A, 0xA2D9, 0xFF2B, 0xA2DA, 0xFF2C, 0xA2DB, 0xFF2D, 0xA2DC, 0xFF2E, + 0xA2DD, 0xFF2F, 0xA2DE, 0xFF30, 0xA2DF, 0xFF31, 0xA2E0, 0xFF32, 0xA2E1, 0xFF33, 0xA2E2, 0xFF34, 0xA2E3, 0xFF35, 0xA2E4, 0xFF36, + 0xA2E5, 0xFF37, 0xA2E6, 0xFF38, 0xA2E7, 0xFF39, 0xA2E8, 0xFF3A, 0xA2E9, 0xFF41, 0xA2EA, 0xFF42, 0xA2EB, 0xFF43, 0xA2EC, 0xFF44, + 0xA2ED, 0xFF45, 0xA2EE, 0xFF46, 0xA2EF, 0xFF47, 0xA2F0, 0xFF48, 0xA2F1, 0xFF49, 0xA2F2, 0xFF4A, 0xA2F3, 0xFF4B, 0xA2F4, 0xFF4C, + 0xA2F5, 0xFF4D, 0xA2F6, 0xFF4E, 0xA2F7, 0xFF4F, 0xA2F8, 0xFF50, 0xA2F9, 0xFF51, 0xA2FA, 0xFF52, 0xA2FB, 0xFF53, 0xA2FC, 0xFF54, + 0xA2FD, 0xFF55, 0xA2FE, 0xFF56, 0xA340, 0xFF57, 0xA341, 0xFF58, 0xA342, 0xFF59, 0xA343, 0xFF5A, 0xA344, 0x0391, 0xA345, 0x0392, + 0xA346, 0x0393, 0xA347, 0x0394, 0xA348, 0x0395, 0xA349, 0x0396, 0xA34A, 0x0397, 0xA34B, 0x0398, 0xA34C, 0x0399, 0xA34D, 0x039A, + 0xA34E, 0x039B, 0xA34F, 0x039C, 0xA350, 0x039D, 0xA351, 0x039E, 0xA352, 0x039F, 0xA353, 0x03A0, 0xA354, 0x03A1, 0xA355, 0x03A3, + 0xA356, 0x03A4, 0xA357, 0x03A5, 0xA358, 0x03A6, 0xA359, 0x03A7, 0xA35A, 0x03A8, 0xA35B, 0x03A9, 0xA35C, 0x03B1, 0xA35D, 0x03B2, + 0xA35E, 0x03B3, 0xA35F, 0x03B4, 0xA360, 0x03B5, 0xA361, 0x03B6, 0xA362, 0x03B7, 0xA363, 0x03B8, 0xA364, 0x03B9, 0xA365, 0x03BA, + 0xA366, 0x03BB, 0xA367, 0x03BC, 0xA368, 0x03BD, 0xA369, 0x03BE, 0xA36A, 0x03BF, 0xA36B, 0x03C0, 0xA36C, 0x03C1, 0xA36D, 0x03C3, + 0xA36E, 0x03C4, 0xA36F, 0x03C5, 0xA370, 0x03C6, 0xA371, 0x03C7, 0xA372, 0x03C8, 0xA373, 0x03C9, 0xA374, 0x3105, 0xA375, 0x3106, + 0xA376, 0x3107, 0xA377, 0x3108, 0xA378, 0x3109, 0xA379, 0x310A, 0xA37A, 0x310B, 0xA37B, 0x310C, 0xA37C, 0x310D, 0xA37D, 0x310E, + 0xA37E, 0x310F, 0xA3A1, 0x3110, 0xA3A2, 0x3111, 0xA3A3, 0x3112, 0xA3A4, 0x3113, 0xA3A5, 0x3114, 0xA3A6, 0x3115, 0xA3A7, 0x3116, + 0xA3A8, 0x3117, 0xA3A9, 0x3118, 0xA3AA, 0x3119, 0xA3AB, 0x311A, 0xA3AC, 0x311B, 0xA3AD, 0x311C, 0xA3AE, 0x311D, 0xA3AF, 0x311E, + 0xA3B0, 0x311F, 0xA3B1, 0x3120, 0xA3B2, 0x3121, 0xA3B3, 0x3122, 0xA3B4, 0x3123, 0xA3B5, 0x3124, 0xA3B6, 0x3125, 0xA3B7, 0x3126, + 0xA3B8, 0x3127, 0xA3B9, 0x3128, 0xA3BA, 0x3129, 0xA3BB, 0x02D9, 0xA3BC, 0x02C9, 0xA3BD, 0x02CA, 0xA3BE, 0x02C7, 0xA3BF, 0x02CB, + 0xA3E1, 0x20AC, 0xA440, 0x4E00, 0xA441, 0x4E59, 0xA442, 0x4E01, 0xA443, 0x4E03, 0xA444, 0x4E43, 0xA445, 0x4E5D, 0xA446, 0x4E86, + 0xA447, 0x4E8C, 0xA448, 0x4EBA, 0xA449, 0x513F, 0xA44A, 0x5165, 0xA44B, 0x516B, 0xA44C, 0x51E0, 0xA44D, 0x5200, 0xA44E, 0x5201, + 0xA44F, 0x529B, 0xA450, 0x5315, 0xA451, 0x5341, 0xA452, 0x535C, 0xA453, 0x53C8, 0xA454, 0x4E09, 0xA455, 0x4E0B, 0xA456, 0x4E08, + 0xA457, 0x4E0A, 0xA458, 0x4E2B, 0xA459, 0x4E38, 0xA45A, 0x51E1, 0xA45B, 0x4E45, 0xA45C, 0x4E48, 0xA45D, 0x4E5F, 0xA45E, 0x4E5E, + 0xA45F, 0x4E8E, 0xA460, 0x4EA1, 0xA461, 0x5140, 0xA462, 0x5203, 0xA463, 0x52FA, 0xA464, 0x5343, 0xA465, 0x53C9, 0xA466, 0x53E3, + 0xA467, 0x571F, 0xA468, 0x58EB, 0xA469, 0x5915, 0xA46A, 0x5927, 0xA46B, 0x5973, 0xA46C, 0x5B50, 0xA46D, 0x5B51, 0xA46E, 0x5B53, + 0xA46F, 0x5BF8, 0xA470, 0x5C0F, 0xA471, 0x5C22, 0xA472, 0x5C38, 0xA473, 0x5C71, 0xA474, 0x5DDD, 0xA475, 0x5DE5, 0xA476, 0x5DF1, + 0xA477, 0x5DF2, 0xA478, 0x5DF3, 0xA479, 0x5DFE, 0xA47A, 0x5E72, 0xA47B, 0x5EFE, 0xA47C, 0x5F0B, 0xA47D, 0x5F13, 0xA47E, 0x624D, + 0xA4A1, 0x4E11, 0xA4A2, 0x4E10, 0xA4A3, 0x4E0D, 0xA4A4, 0x4E2D, 0xA4A5, 0x4E30, 0xA4A6, 0x4E39, 0xA4A7, 0x4E4B, 0xA4A8, 0x5C39, + 0xA4A9, 0x4E88, 0xA4AA, 0x4E91, 0xA4AB, 0x4E95, 0xA4AC, 0x4E92, 0xA4AD, 0x4E94, 0xA4AE, 0x4EA2, 0xA4AF, 0x4EC1, 0xA4B0, 0x4EC0, + 0xA4B1, 0x4EC3, 0xA4B2, 0x4EC6, 0xA4B3, 0x4EC7, 0xA4B4, 0x4ECD, 0xA4B5, 0x4ECA, 0xA4B6, 0x4ECB, 0xA4B7, 0x4EC4, 0xA4B8, 0x5143, + 0xA4B9, 0x5141, 0xA4BA, 0x5167, 0xA4BB, 0x516D, 0xA4BC, 0x516E, 0xA4BD, 0x516C, 0xA4BE, 0x5197, 0xA4BF, 0x51F6, 0xA4C0, 0x5206, + 0xA4C1, 0x5207, 0xA4C2, 0x5208, 0xA4C3, 0x52FB, 0xA4C4, 0x52FE, 0xA4C5, 0x52FF, 0xA4C6, 0x5316, 0xA4C7, 0x5339, 0xA4C8, 0x5348, + 0xA4C9, 0x5347, 0xA4CA, 0x5345, 0xA4CB, 0x535E, 0xA4CC, 0x5384, 0xA4CD, 0x53CB, 0xA4CE, 0x53CA, 0xA4CF, 0x53CD, 0xA4D0, 0x58EC, + 0xA4D1, 0x5929, 0xA4D2, 0x592B, 0xA4D3, 0x592A, 0xA4D4, 0x592D, 0xA4D5, 0x5B54, 0xA4D6, 0x5C11, 0xA4D7, 0x5C24, 0xA4D8, 0x5C3A, + 0xA4D9, 0x5C6F, 0xA4DA, 0x5DF4, 0xA4DB, 0x5E7B, 0xA4DC, 0x5EFF, 0xA4DD, 0x5F14, 0xA4DE, 0x5F15, 0xA4DF, 0x5FC3, 0xA4E0, 0x6208, + 0xA4E1, 0x6236, 0xA4E2, 0x624B, 0xA4E3, 0x624E, 0xA4E4, 0x652F, 0xA4E5, 0x6587, 0xA4E6, 0x6597, 0xA4E7, 0x65A4, 0xA4E8, 0x65B9, + 0xA4E9, 0x65E5, 0xA4EA, 0x66F0, 0xA4EB, 0x6708, 0xA4EC, 0x6728, 0xA4ED, 0x6B20, 0xA4EE, 0x6B62, 0xA4EF, 0x6B79, 0xA4F0, 0x6BCB, + 0xA4F1, 0x6BD4, 0xA4F2, 0x6BDB, 0xA4F3, 0x6C0F, 0xA4F4, 0x6C34, 0xA4F5, 0x706B, 0xA4F6, 0x722A, 0xA4F7, 0x7236, 0xA4F8, 0x723B, + 0xA4F9, 0x7247, 0xA4FA, 0x7259, 0xA4FB, 0x725B, 0xA4FC, 0x72AC, 0xA4FD, 0x738B, 0xA4FE, 0x4E19, 0xA540, 0x4E16, 0xA541, 0x4E15, + 0xA542, 0x4E14, 0xA543, 0x4E18, 0xA544, 0x4E3B, 0xA545, 0x4E4D, 0xA546, 0x4E4F, 0xA547, 0x4E4E, 0xA548, 0x4EE5, 0xA549, 0x4ED8, + 0xA54A, 0x4ED4, 0xA54B, 0x4ED5, 0xA54C, 0x4ED6, 0xA54D, 0x4ED7, 0xA54E, 0x4EE3, 0xA54F, 0x4EE4, 0xA550, 0x4ED9, 0xA551, 0x4EDE, + 0xA552, 0x5145, 0xA553, 0x5144, 0xA554, 0x5189, 0xA555, 0x518A, 0xA556, 0x51AC, 0xA557, 0x51F9, 0xA558, 0x51FA, 0xA559, 0x51F8, + 0xA55A, 0x520A, 0xA55B, 0x52A0, 0xA55C, 0x529F, 0xA55D, 0x5305, 0xA55E, 0x5306, 0xA55F, 0x5317, 0xA560, 0x531D, 0xA561, 0x4EDF, + 0xA562, 0x534A, 0xA563, 0x5349, 0xA564, 0x5361, 0xA565, 0x5360, 0xA566, 0x536F, 0xA567, 0x536E, 0xA568, 0x53BB, 0xA569, 0x53EF, + 0xA56A, 0x53E4, 0xA56B, 0x53F3, 0xA56C, 0x53EC, 0xA56D, 0x53EE, 0xA56E, 0x53E9, 0xA56F, 0x53E8, 0xA570, 0x53FC, 0xA571, 0x53F8, + 0xA572, 0x53F5, 0xA573, 0x53EB, 0xA574, 0x53E6, 0xA575, 0x53EA, 0xA576, 0x53F2, 0xA577, 0x53F1, 0xA578, 0x53F0, 0xA579, 0x53E5, + 0xA57A, 0x53ED, 0xA57B, 0x53FB, 0xA57C, 0x56DB, 0xA57D, 0x56DA, 0xA57E, 0x5916, 0xA5A1, 0x592E, 0xA5A2, 0x5931, 0xA5A3, 0x5974, + 0xA5A4, 0x5976, 0xA5A5, 0x5B55, 0xA5A6, 0x5B83, 0xA5A7, 0x5C3C, 0xA5A8, 0x5DE8, 0xA5A9, 0x5DE7, 0xA5AA, 0x5DE6, 0xA5AB, 0x5E02, + 0xA5AC, 0x5E03, 0xA5AD, 0x5E73, 0xA5AE, 0x5E7C, 0xA5AF, 0x5F01, 0xA5B0, 0x5F18, 0xA5B1, 0x5F17, 0xA5B2, 0x5FC5, 0xA5B3, 0x620A, + 0xA5B4, 0x6253, 0xA5B5, 0x6254, 0xA5B6, 0x6252, 0xA5B7, 0x6251, 0xA5B8, 0x65A5, 0xA5B9, 0x65E6, 0xA5BA, 0x672E, 0xA5BB, 0x672C, + 0xA5BC, 0x672A, 0xA5BD, 0x672B, 0xA5BE, 0x672D, 0xA5BF, 0x6B63, 0xA5C0, 0x6BCD, 0xA5C1, 0x6C11, 0xA5C2, 0x6C10, 0xA5C3, 0x6C38, + 0xA5C4, 0x6C41, 0xA5C5, 0x6C40, 0xA5C6, 0x6C3E, 0xA5C7, 0x72AF, 0xA5C8, 0x7384, 0xA5C9, 0x7389, 0xA5CA, 0x74DC, 0xA5CB, 0x74E6, + 0xA5CC, 0x7518, 0xA5CD, 0x751F, 0xA5CE, 0x7528, 0xA5CF, 0x7529, 0xA5D0, 0x7530, 0xA5D1, 0x7531, 0xA5D2, 0x7532, 0xA5D3, 0x7533, + 0xA5D4, 0x758B, 0xA5D5, 0x767D, 0xA5D6, 0x76AE, 0xA5D7, 0x76BF, 0xA5D8, 0x76EE, 0xA5D9, 0x77DB, 0xA5DA, 0x77E2, 0xA5DB, 0x77F3, + 0xA5DC, 0x793A, 0xA5DD, 0x79BE, 0xA5DE, 0x7A74, 0xA5DF, 0x7ACB, 0xA5E0, 0x4E1E, 0xA5E1, 0x4E1F, 0xA5E2, 0x4E52, 0xA5E3, 0x4E53, + 0xA5E4, 0x4E69, 0xA5E5, 0x4E99, 0xA5E6, 0x4EA4, 0xA5E7, 0x4EA6, 0xA5E8, 0x4EA5, 0xA5E9, 0x4EFF, 0xA5EA, 0x4F09, 0xA5EB, 0x4F19, + 0xA5EC, 0x4F0A, 0xA5ED, 0x4F15, 0xA5EE, 0x4F0D, 0xA5EF, 0x4F10, 0xA5F0, 0x4F11, 0xA5F1, 0x4F0F, 0xA5F2, 0x4EF2, 0xA5F3, 0x4EF6, + 0xA5F4, 0x4EFB, 0xA5F5, 0x4EF0, 0xA5F6, 0x4EF3, 0xA5F7, 0x4EFD, 0xA5F8, 0x4F01, 0xA5F9, 0x4F0B, 0xA5FA, 0x5149, 0xA5FB, 0x5147, + 0xA5FC, 0x5146, 0xA5FD, 0x5148, 0xA5FE, 0x5168, 0xA640, 0x5171, 0xA641, 0x518D, 0xA642, 0x51B0, 0xA643, 0x5217, 0xA644, 0x5211, + 0xA645, 0x5212, 0xA646, 0x520E, 0xA647, 0x5216, 0xA648, 0x52A3, 0xA649, 0x5308, 0xA64A, 0x5321, 0xA64B, 0x5320, 0xA64C, 0x5370, + 0xA64D, 0x5371, 0xA64E, 0x5409, 0xA64F, 0x540F, 0xA650, 0x540C, 0xA651, 0x540A, 0xA652, 0x5410, 0xA653, 0x5401, 0xA654, 0x540B, + 0xA655, 0x5404, 0xA656, 0x5411, 0xA657, 0x540D, 0xA658, 0x5408, 0xA659, 0x5403, 0xA65A, 0x540E, 0xA65B, 0x5406, 0xA65C, 0x5412, + 0xA65D, 0x56E0, 0xA65E, 0x56DE, 0xA65F, 0x56DD, 0xA660, 0x5733, 0xA661, 0x5730, 0xA662, 0x5728, 0xA663, 0x572D, 0xA664, 0x572C, + 0xA665, 0x572F, 0xA666, 0x5729, 0xA667, 0x5919, 0xA668, 0x591A, 0xA669, 0x5937, 0xA66A, 0x5938, 0xA66B, 0x5984, 0xA66C, 0x5978, + 0xA66D, 0x5983, 0xA66E, 0x597D, 0xA66F, 0x5979, 0xA670, 0x5982, 0xA671, 0x5981, 0xA672, 0x5B57, 0xA673, 0x5B58, 0xA674, 0x5B87, + 0xA675, 0x5B88, 0xA676, 0x5B85, 0xA677, 0x5B89, 0xA678, 0x5BFA, 0xA679, 0x5C16, 0xA67A, 0x5C79, 0xA67B, 0x5DDE, 0xA67C, 0x5E06, + 0xA67D, 0x5E76, 0xA67E, 0x5E74, 0xA6A1, 0x5F0F, 0xA6A2, 0x5F1B, 0xA6A3, 0x5FD9, 0xA6A4, 0x5FD6, 0xA6A5, 0x620E, 0xA6A6, 0x620C, + 0xA6A7, 0x620D, 0xA6A8, 0x6210, 0xA6A9, 0x6263, 0xA6AA, 0x625B, 0xA6AB, 0x6258, 0xA6AC, 0x6536, 0xA6AD, 0x65E9, 0xA6AE, 0x65E8, + 0xA6AF, 0x65EC, 0xA6B0, 0x65ED, 0xA6B1, 0x66F2, 0xA6B2, 0x66F3, 0xA6B3, 0x6709, 0xA6B4, 0x673D, 0xA6B5, 0x6734, 0xA6B6, 0x6731, + 0xA6B7, 0x6735, 0xA6B8, 0x6B21, 0xA6B9, 0x6B64, 0xA6BA, 0x6B7B, 0xA6BB, 0x6C16, 0xA6BC, 0x6C5D, 0xA6BD, 0x6C57, 0xA6BE, 0x6C59, + 0xA6BF, 0x6C5F, 0xA6C0, 0x6C60, 0xA6C1, 0x6C50, 0xA6C2, 0x6C55, 0xA6C3, 0x6C61, 0xA6C4, 0x6C5B, 0xA6C5, 0x6C4D, 0xA6C6, 0x6C4E, + 0xA6C7, 0x7070, 0xA6C8, 0x725F, 0xA6C9, 0x725D, 0xA6CA, 0x767E, 0xA6CB, 0x7AF9, 0xA6CC, 0x7C73, 0xA6CD, 0x7CF8, 0xA6CE, 0x7F36, + 0xA6CF, 0x7F8A, 0xA6D0, 0x7FBD, 0xA6D1, 0x8001, 0xA6D2, 0x8003, 0xA6D3, 0x800C, 0xA6D4, 0x8012, 0xA6D5, 0x8033, 0xA6D6, 0x807F, + 0xA6D7, 0x8089, 0xA6D8, 0x808B, 0xA6D9, 0x808C, 0xA6DA, 0x81E3, 0xA6DB, 0x81EA, 0xA6DC, 0x81F3, 0xA6DD, 0x81FC, 0xA6DE, 0x820C, + 0xA6DF, 0x821B, 0xA6E0, 0x821F, 0xA6E1, 0x826E, 0xA6E2, 0x8272, 0xA6E3, 0x827E, 0xA6E4, 0x866B, 0xA6E5, 0x8840, 0xA6E6, 0x884C, + 0xA6E7, 0x8863, 0xA6E8, 0x897F, 0xA6E9, 0x9621, 0xA6EA, 0x4E32, 0xA6EB, 0x4EA8, 0xA6EC, 0x4F4D, 0xA6ED, 0x4F4F, 0xA6EE, 0x4F47, + 0xA6EF, 0x4F57, 0xA6F0, 0x4F5E, 0xA6F1, 0x4F34, 0xA6F2, 0x4F5B, 0xA6F3, 0x4F55, 0xA6F4, 0x4F30, 0xA6F5, 0x4F50, 0xA6F6, 0x4F51, + 0xA6F7, 0x4F3D, 0xA6F8, 0x4F3A, 0xA6F9, 0x4F38, 0xA6FA, 0x4F43, 0xA6FB, 0x4F54, 0xA6FC, 0x4F3C, 0xA6FD, 0x4F46, 0xA6FE, 0x4F63, + 0xA740, 0x4F5C, 0xA741, 0x4F60, 0xA742, 0x4F2F, 0xA743, 0x4F4E, 0xA744, 0x4F36, 0xA745, 0x4F59, 0xA746, 0x4F5D, 0xA747, 0x4F48, + 0xA748, 0x4F5A, 0xA749, 0x514C, 0xA74A, 0x514B, 0xA74B, 0x514D, 0xA74C, 0x5175, 0xA74D, 0x51B6, 0xA74E, 0x51B7, 0xA74F, 0x5225, + 0xA750, 0x5224, 0xA751, 0x5229, 0xA752, 0x522A, 0xA753, 0x5228, 0xA754, 0x52AB, 0xA755, 0x52A9, 0xA756, 0x52AA, 0xA757, 0x52AC, + 0xA758, 0x5323, 0xA759, 0x5373, 0xA75A, 0x5375, 0xA75B, 0x541D, 0xA75C, 0x542D, 0xA75D, 0x541E, 0xA75E, 0x543E, 0xA75F, 0x5426, + 0xA760, 0x544E, 0xA761, 0x5427, 0xA762, 0x5446, 0xA763, 0x5443, 0xA764, 0x5433, 0xA765, 0x5448, 0xA766, 0x5442, 0xA767, 0x541B, + 0xA768, 0x5429, 0xA769, 0x544A, 0xA76A, 0x5439, 0xA76B, 0x543B, 0xA76C, 0x5438, 0xA76D, 0x542E, 0xA76E, 0x5435, 0xA76F, 0x5436, + 0xA770, 0x5420, 0xA771, 0x543C, 0xA772, 0x5440, 0xA773, 0x5431, 0xA774, 0x542B, 0xA775, 0x541F, 0xA776, 0x542C, 0xA777, 0x56EA, + 0xA778, 0x56F0, 0xA779, 0x56E4, 0xA77A, 0x56EB, 0xA77B, 0x574A, 0xA77C, 0x5751, 0xA77D, 0x5740, 0xA77E, 0x574D, 0xA7A1, 0x5747, + 0xA7A2, 0x574E, 0xA7A3, 0x573E, 0xA7A4, 0x5750, 0xA7A5, 0x574F, 0xA7A6, 0x573B, 0xA7A7, 0x58EF, 0xA7A8, 0x593E, 0xA7A9, 0x599D, + 0xA7AA, 0x5992, 0xA7AB, 0x59A8, 0xA7AC, 0x599E, 0xA7AD, 0x59A3, 0xA7AE, 0x5999, 0xA7AF, 0x5996, 0xA7B0, 0x598D, 0xA7B1, 0x59A4, + 0xA7B2, 0x5993, 0xA7B3, 0x598A, 0xA7B4, 0x59A5, 0xA7B5, 0x5B5D, 0xA7B6, 0x5B5C, 0xA7B7, 0x5B5A, 0xA7B8, 0x5B5B, 0xA7B9, 0x5B8C, + 0xA7BA, 0x5B8B, 0xA7BB, 0x5B8F, 0xA7BC, 0x5C2C, 0xA7BD, 0x5C40, 0xA7BE, 0x5C41, 0xA7BF, 0x5C3F, 0xA7C0, 0x5C3E, 0xA7C1, 0x5C90, + 0xA7C2, 0x5C91, 0xA7C3, 0x5C94, 0xA7C4, 0x5C8C, 0xA7C5, 0x5DEB, 0xA7C6, 0x5E0C, 0xA7C7, 0x5E8F, 0xA7C8, 0x5E87, 0xA7C9, 0x5E8A, + 0xA7CA, 0x5EF7, 0xA7CB, 0x5F04, 0xA7CC, 0x5F1F, 0xA7CD, 0x5F64, 0xA7CE, 0x5F62, 0xA7CF, 0x5F77, 0xA7D0, 0x5F79, 0xA7D1, 0x5FD8, + 0xA7D2, 0x5FCC, 0xA7D3, 0x5FD7, 0xA7D4, 0x5FCD, 0xA7D5, 0x5FF1, 0xA7D6, 0x5FEB, 0xA7D7, 0x5FF8, 0xA7D8, 0x5FEA, 0xA7D9, 0x6212, + 0xA7DA, 0x6211, 0xA7DB, 0x6284, 0xA7DC, 0x6297, 0xA7DD, 0x6296, 0xA7DE, 0x6280, 0xA7DF, 0x6276, 0xA7E0, 0x6289, 0xA7E1, 0x626D, + 0xA7E2, 0x628A, 0xA7E3, 0x627C, 0xA7E4, 0x627E, 0xA7E5, 0x6279, 0xA7E6, 0x6273, 0xA7E7, 0x6292, 0xA7E8, 0x626F, 0xA7E9, 0x6298, + 0xA7EA, 0x626E, 0xA7EB, 0x6295, 0xA7EC, 0x6293, 0xA7ED, 0x6291, 0xA7EE, 0x6286, 0xA7EF, 0x6539, 0xA7F0, 0x653B, 0xA7F1, 0x6538, + 0xA7F2, 0x65F1, 0xA7F3, 0x66F4, 0xA7F4, 0x675F, 0xA7F5, 0x674E, 0xA7F6, 0x674F, 0xA7F7, 0x6750, 0xA7F8, 0x6751, 0xA7F9, 0x675C, + 0xA7FA, 0x6756, 0xA7FB, 0x675E, 0xA7FC, 0x6749, 0xA7FD, 0x6746, 0xA7FE, 0x6760, 0xA840, 0x6753, 0xA841, 0x6757, 0xA842, 0x6B65, + 0xA843, 0x6BCF, 0xA844, 0x6C42, 0xA845, 0x6C5E, 0xA846, 0x6C99, 0xA847, 0x6C81, 0xA848, 0x6C88, 0xA849, 0x6C89, 0xA84A, 0x6C85, + 0xA84B, 0x6C9B, 0xA84C, 0x6C6A, 0xA84D, 0x6C7A, 0xA84E, 0x6C90, 0xA84F, 0x6C70, 0xA850, 0x6C8C, 0xA851, 0x6C68, 0xA852, 0x6C96, + 0xA853, 0x6C92, 0xA854, 0x6C7D, 0xA855, 0x6C83, 0xA856, 0x6C72, 0xA857, 0x6C7E, 0xA858, 0x6C74, 0xA859, 0x6C86, 0xA85A, 0x6C76, + 0xA85B, 0x6C8D, 0xA85C, 0x6C94, 0xA85D, 0x6C98, 0xA85E, 0x6C82, 0xA85F, 0x7076, 0xA860, 0x707C, 0xA861, 0x707D, 0xA862, 0x7078, + 0xA863, 0x7262, 0xA864, 0x7261, 0xA865, 0x7260, 0xA866, 0x72C4, 0xA867, 0x72C2, 0xA868, 0x7396, 0xA869, 0x752C, 0xA86A, 0x752B, + 0xA86B, 0x7537, 0xA86C, 0x7538, 0xA86D, 0x7682, 0xA86E, 0x76EF, 0xA86F, 0x77E3, 0xA870, 0x79C1, 0xA871, 0x79C0, 0xA872, 0x79BF, + 0xA873, 0x7A76, 0xA874, 0x7CFB, 0xA875, 0x7F55, 0xA876, 0x8096, 0xA877, 0x8093, 0xA878, 0x809D, 0xA879, 0x8098, 0xA87A, 0x809B, + 0xA87B, 0x809A, 0xA87C, 0x80B2, 0xA87D, 0x826F, 0xA87E, 0x8292, 0xA8A1, 0x828B, 0xA8A2, 0x828D, 0xA8A3, 0x898B, 0xA8A4, 0x89D2, + 0xA8A5, 0x8A00, 0xA8A6, 0x8C37, 0xA8A7, 0x8C46, 0xA8A8, 0x8C55, 0xA8A9, 0x8C9D, 0xA8AA, 0x8D64, 0xA8AB, 0x8D70, 0xA8AC, 0x8DB3, + 0xA8AD, 0x8EAB, 0xA8AE, 0x8ECA, 0xA8AF, 0x8F9B, 0xA8B0, 0x8FB0, 0xA8B1, 0x8FC2, 0xA8B2, 0x8FC6, 0xA8B3, 0x8FC5, 0xA8B4, 0x8FC4, + 0xA8B5, 0x5DE1, 0xA8B6, 0x9091, 0xA8B7, 0x90A2, 0xA8B8, 0x90AA, 0xA8B9, 0x90A6, 0xA8BA, 0x90A3, 0xA8BB, 0x9149, 0xA8BC, 0x91C6, + 0xA8BD, 0x91CC, 0xA8BE, 0x9632, 0xA8BF, 0x962E, 0xA8C0, 0x9631, 0xA8C1, 0x962A, 0xA8C2, 0x962C, 0xA8C3, 0x4E26, 0xA8C4, 0x4E56, + 0xA8C5, 0x4E73, 0xA8C6, 0x4E8B, 0xA8C7, 0x4E9B, 0xA8C8, 0x4E9E, 0xA8C9, 0x4EAB, 0xA8CA, 0x4EAC, 0xA8CB, 0x4F6F, 0xA8CC, 0x4F9D, + 0xA8CD, 0x4F8D, 0xA8CE, 0x4F73, 0xA8CF, 0x4F7F, 0xA8D0, 0x4F6C, 0xA8D1, 0x4F9B, 0xA8D2, 0x4F8B, 0xA8D3, 0x4F86, 0xA8D4, 0x4F83, + 0xA8D5, 0x4F70, 0xA8D6, 0x4F75, 0xA8D7, 0x4F88, 0xA8D8, 0x4F69, 0xA8D9, 0x4F7B, 0xA8DA, 0x4F96, 0xA8DB, 0x4F7E, 0xA8DC, 0x4F8F, + 0xA8DD, 0x4F91, 0xA8DE, 0x4F7A, 0xA8DF, 0x5154, 0xA8E0, 0x5152, 0xA8E1, 0x5155, 0xA8E2, 0x5169, 0xA8E3, 0x5177, 0xA8E4, 0x5176, + 0xA8E5, 0x5178, 0xA8E6, 0x51BD, 0xA8E7, 0x51FD, 0xA8E8, 0x523B, 0xA8E9, 0x5238, 0xA8EA, 0x5237, 0xA8EB, 0x523A, 0xA8EC, 0x5230, + 0xA8ED, 0x522E, 0xA8EE, 0x5236, 0xA8EF, 0x5241, 0xA8F0, 0x52BE, 0xA8F1, 0x52BB, 0xA8F2, 0x5352, 0xA8F3, 0x5354, 0xA8F4, 0x5353, + 0xA8F5, 0x5351, 0xA8F6, 0x5366, 0xA8F7, 0x5377, 0xA8F8, 0x5378, 0xA8F9, 0x5379, 0xA8FA, 0x53D6, 0xA8FB, 0x53D4, 0xA8FC, 0x53D7, + 0xA8FD, 0x5473, 0xA8FE, 0x5475, 0xA940, 0x5496, 0xA941, 0x5478, 0xA942, 0x5495, 0xA943, 0x5480, 0xA944, 0x547B, 0xA945, 0x5477, + 0xA946, 0x5484, 0xA947, 0x5492, 0xA948, 0x5486, 0xA949, 0x547C, 0xA94A, 0x5490, 0xA94B, 0x5471, 0xA94C, 0x5476, 0xA94D, 0x548C, + 0xA94E, 0x549A, 0xA94F, 0x5462, 0xA950, 0x5468, 0xA951, 0x548B, 0xA952, 0x547D, 0xA953, 0x548E, 0xA954, 0x56FA, 0xA955, 0x5783, + 0xA956, 0x5777, 0xA957, 0x576A, 0xA958, 0x5769, 0xA959, 0x5761, 0xA95A, 0x5766, 0xA95B, 0x5764, 0xA95C, 0x577C, 0xA95D, 0x591C, + 0xA95E, 0x5949, 0xA95F, 0x5947, 0xA960, 0x5948, 0xA961, 0x5944, 0xA962, 0x5954, 0xA963, 0x59BE, 0xA964, 0x59BB, 0xA965, 0x59D4, + 0xA966, 0x59B9, 0xA967, 0x59AE, 0xA968, 0x59D1, 0xA969, 0x59C6, 0xA96A, 0x59D0, 0xA96B, 0x59CD, 0xA96C, 0x59CB, 0xA96D, 0x59D3, + 0xA96E, 0x59CA, 0xA96F, 0x59AF, 0xA970, 0x59B3, 0xA971, 0x59D2, 0xA972, 0x59C5, 0xA973, 0x5B5F, 0xA974, 0x5B64, 0xA975, 0x5B63, + 0xA976, 0x5B97, 0xA977, 0x5B9A, 0xA978, 0x5B98, 0xA979, 0x5B9C, 0xA97A, 0x5B99, 0xA97B, 0x5B9B, 0xA97C, 0x5C1A, 0xA97D, 0x5C48, + 0xA97E, 0x5C45, 0xA9A1, 0x5C46, 0xA9A2, 0x5CB7, 0xA9A3, 0x5CA1, 0xA9A4, 0x5CB8, 0xA9A5, 0x5CA9, 0xA9A6, 0x5CAB, 0xA9A7, 0x5CB1, + 0xA9A8, 0x5CB3, 0xA9A9, 0x5E18, 0xA9AA, 0x5E1A, 0xA9AB, 0x5E16, 0xA9AC, 0x5E15, 0xA9AD, 0x5E1B, 0xA9AE, 0x5E11, 0xA9AF, 0x5E78, + 0xA9B0, 0x5E9A, 0xA9B1, 0x5E97, 0xA9B2, 0x5E9C, 0xA9B3, 0x5E95, 0xA9B4, 0x5E96, 0xA9B5, 0x5EF6, 0xA9B6, 0x5F26, 0xA9B7, 0x5F27, + 0xA9B8, 0x5F29, 0xA9B9, 0x5F80, 0xA9BA, 0x5F81, 0xA9BB, 0x5F7F, 0xA9BC, 0x5F7C, 0xA9BD, 0x5FDD, 0xA9BE, 0x5FE0, 0xA9BF, 0x5FFD, + 0xA9C0, 0x5FF5, 0xA9C1, 0x5FFF, 0xA9C2, 0x600F, 0xA9C3, 0x6014, 0xA9C4, 0x602F, 0xA9C5, 0x6035, 0xA9C6, 0x6016, 0xA9C7, 0x602A, + 0xA9C8, 0x6015, 0xA9C9, 0x6021, 0xA9CA, 0x6027, 0xA9CB, 0x6029, 0xA9CC, 0x602B, 0xA9CD, 0x601B, 0xA9CE, 0x6216, 0xA9CF, 0x6215, + 0xA9D0, 0x623F, 0xA9D1, 0x623E, 0xA9D2, 0x6240, 0xA9D3, 0x627F, 0xA9D4, 0x62C9, 0xA9D5, 0x62CC, 0xA9D6, 0x62C4, 0xA9D7, 0x62BF, + 0xA9D8, 0x62C2, 0xA9D9, 0x62B9, 0xA9DA, 0x62D2, 0xA9DB, 0x62DB, 0xA9DC, 0x62AB, 0xA9DD, 0x62D3, 0xA9DE, 0x62D4, 0xA9DF, 0x62CB, + 0xA9E0, 0x62C8, 0xA9E1, 0x62A8, 0xA9E2, 0x62BD, 0xA9E3, 0x62BC, 0xA9E4, 0x62D0, 0xA9E5, 0x62D9, 0xA9E6, 0x62C7, 0xA9E7, 0x62CD, + 0xA9E8, 0x62B5, 0xA9E9, 0x62DA, 0xA9EA, 0x62B1, 0xA9EB, 0x62D8, 0xA9EC, 0x62D6, 0xA9ED, 0x62D7, 0xA9EE, 0x62C6, 0xA9EF, 0x62AC, + 0xA9F0, 0x62CE, 0xA9F1, 0x653E, 0xA9F2, 0x65A7, 0xA9F3, 0x65BC, 0xA9F4, 0x65FA, 0xA9F5, 0x6614, 0xA9F6, 0x6613, 0xA9F7, 0x660C, + 0xA9F8, 0x6606, 0xA9F9, 0x6602, 0xA9FA, 0x660E, 0xA9FB, 0x6600, 0xA9FC, 0x660F, 0xA9FD, 0x6615, 0xA9FE, 0x660A, 0xAA40, 0x6607, + 0xAA41, 0x670D, 0xAA42, 0x670B, 0xAA43, 0x676D, 0xAA44, 0x678B, 0xAA45, 0x6795, 0xAA46, 0x6771, 0xAA47, 0x679C, 0xAA48, 0x6773, + 0xAA49, 0x6777, 0xAA4A, 0x6787, 0xAA4B, 0x679D, 0xAA4C, 0x6797, 0xAA4D, 0x676F, 0xAA4E, 0x6770, 0xAA4F, 0x677F, 0xAA50, 0x6789, + 0xAA51, 0x677E, 0xAA52, 0x6790, 0xAA53, 0x6775, 0xAA54, 0x679A, 0xAA55, 0x6793, 0xAA56, 0x677C, 0xAA57, 0x676A, 0xAA58, 0x6772, + 0xAA59, 0x6B23, 0xAA5A, 0x6B66, 0xAA5B, 0x6B67, 0xAA5C, 0x6B7F, 0xAA5D, 0x6C13, 0xAA5E, 0x6C1B, 0xAA5F, 0x6CE3, 0xAA60, 0x6CE8, + 0xAA61, 0x6CF3, 0xAA62, 0x6CB1, 0xAA63, 0x6CCC, 0xAA64, 0x6CE5, 0xAA65, 0x6CB3, 0xAA66, 0x6CBD, 0xAA67, 0x6CBE, 0xAA68, 0x6CBC, + 0xAA69, 0x6CE2, 0xAA6A, 0x6CAB, 0xAA6B, 0x6CD5, 0xAA6C, 0x6CD3, 0xAA6D, 0x6CB8, 0xAA6E, 0x6CC4, 0xAA6F, 0x6CB9, 0xAA70, 0x6CC1, + 0xAA71, 0x6CAE, 0xAA72, 0x6CD7, 0xAA73, 0x6CC5, 0xAA74, 0x6CF1, 0xAA75, 0x6CBF, 0xAA76, 0x6CBB, 0xAA77, 0x6CE1, 0xAA78, 0x6CDB, + 0xAA79, 0x6CCA, 0xAA7A, 0x6CAC, 0xAA7B, 0x6CEF, 0xAA7C, 0x6CDC, 0xAA7D, 0x6CD6, 0xAA7E, 0x6CE0, 0xAAA1, 0x7095, 0xAAA2, 0x708E, + 0xAAA3, 0x7092, 0xAAA4, 0x708A, 0xAAA5, 0x7099, 0xAAA6, 0x722C, 0xAAA7, 0x722D, 0xAAA8, 0x7238, 0xAAA9, 0x7248, 0xAAAA, 0x7267, + 0xAAAB, 0x7269, 0xAAAC, 0x72C0, 0xAAAD, 0x72CE, 0xAAAE, 0x72D9, 0xAAAF, 0x72D7, 0xAAB0, 0x72D0, 0xAAB1, 0x73A9, 0xAAB2, 0x73A8, + 0xAAB3, 0x739F, 0xAAB4, 0x73AB, 0xAAB5, 0x73A5, 0xAAB6, 0x753D, 0xAAB7, 0x759D, 0xAAB8, 0x7599, 0xAAB9, 0x759A, 0xAABA, 0x7684, + 0xAABB, 0x76C2, 0xAABC, 0x76F2, 0xAABD, 0x76F4, 0xAABE, 0x77E5, 0xAABF, 0x77FD, 0xAAC0, 0x793E, 0xAAC1, 0x7940, 0xAAC2, 0x7941, + 0xAAC3, 0x79C9, 0xAAC4, 0x79C8, 0xAAC5, 0x7A7A, 0xAAC6, 0x7A79, 0xAAC7, 0x7AFA, 0xAAC8, 0x7CFE, 0xAAC9, 0x7F54, 0xAACA, 0x7F8C, + 0xAACB, 0x7F8B, 0xAACC, 0x8005, 0xAACD, 0x80BA, 0xAACE, 0x80A5, 0xAACF, 0x80A2, 0xAAD0, 0x80B1, 0xAAD1, 0x80A1, 0xAAD2, 0x80AB, + 0xAAD3, 0x80A9, 0xAAD4, 0x80B4, 0xAAD5, 0x80AA, 0xAAD6, 0x80AF, 0xAAD7, 0x81E5, 0xAAD8, 0x81FE, 0xAAD9, 0x820D, 0xAADA, 0x82B3, + 0xAADB, 0x829D, 0xAADC, 0x8299, 0xAADD, 0x82AD, 0xAADE, 0x82BD, 0xAADF, 0x829F, 0xAAE0, 0x82B9, 0xAAE1, 0x82B1, 0xAAE2, 0x82AC, + 0xAAE3, 0x82A5, 0xAAE4, 0x82AF, 0xAAE5, 0x82B8, 0xAAE6, 0x82A3, 0xAAE7, 0x82B0, 0xAAE8, 0x82BE, 0xAAE9, 0x82B7, 0xAAEA, 0x864E, + 0xAAEB, 0x8671, 0xAAEC, 0x521D, 0xAAED, 0x8868, 0xAAEE, 0x8ECB, 0xAAEF, 0x8FCE, 0xAAF0, 0x8FD4, 0xAAF1, 0x8FD1, 0xAAF2, 0x90B5, + 0xAAF3, 0x90B8, 0xAAF4, 0x90B1, 0xAAF5, 0x90B6, 0xAAF6, 0x91C7, 0xAAF7, 0x91D1, 0xAAF8, 0x9577, 0xAAF9, 0x9580, 0xAAFA, 0x961C, + 0xAAFB, 0x9640, 0xAAFC, 0x963F, 0xAAFD, 0x963B, 0xAAFE, 0x9644, 0xAB40, 0x9642, 0xAB41, 0x96B9, 0xAB42, 0x96E8, 0xAB43, 0x9752, + 0xAB44, 0x975E, 0xAB45, 0x4E9F, 0xAB46, 0x4EAD, 0xAB47, 0x4EAE, 0xAB48, 0x4FE1, 0xAB49, 0x4FB5, 0xAB4A, 0x4FAF, 0xAB4B, 0x4FBF, + 0xAB4C, 0x4FE0, 0xAB4D, 0x4FD1, 0xAB4E, 0x4FCF, 0xAB4F, 0x4FDD, 0xAB50, 0x4FC3, 0xAB51, 0x4FB6, 0xAB52, 0x4FD8, 0xAB53, 0x4FDF, + 0xAB54, 0x4FCA, 0xAB55, 0x4FD7, 0xAB56, 0x4FAE, 0xAB57, 0x4FD0, 0xAB58, 0x4FC4, 0xAB59, 0x4FC2, 0xAB5A, 0x4FDA, 0xAB5B, 0x4FCE, + 0xAB5C, 0x4FDE, 0xAB5D, 0x4FB7, 0xAB5E, 0x5157, 0xAB5F, 0x5192, 0xAB60, 0x5191, 0xAB61, 0x51A0, 0xAB62, 0x524E, 0xAB63, 0x5243, + 0xAB64, 0x524A, 0xAB65, 0x524D, 0xAB66, 0x524C, 0xAB67, 0x524B, 0xAB68, 0x5247, 0xAB69, 0x52C7, 0xAB6A, 0x52C9, 0xAB6B, 0x52C3, + 0xAB6C, 0x52C1, 0xAB6D, 0x530D, 0xAB6E, 0x5357, 0xAB6F, 0x537B, 0xAB70, 0x539A, 0xAB71, 0x53DB, 0xAB72, 0x54AC, 0xAB73, 0x54C0, + 0xAB74, 0x54A8, 0xAB75, 0x54CE, 0xAB76, 0x54C9, 0xAB77, 0x54B8, 0xAB78, 0x54A6, 0xAB79, 0x54B3, 0xAB7A, 0x54C7, 0xAB7B, 0x54C2, + 0xAB7C, 0x54BD, 0xAB7D, 0x54AA, 0xAB7E, 0x54C1, 0xABA1, 0x54C4, 0xABA2, 0x54C8, 0xABA3, 0x54AF, 0xABA4, 0x54AB, 0xABA5, 0x54B1, + 0xABA6, 0x54BB, 0xABA7, 0x54A9, 0xABA8, 0x54A7, 0xABA9, 0x54BF, 0xABAA, 0x56FF, 0xABAB, 0x5782, 0xABAC, 0x578B, 0xABAD, 0x57A0, + 0xABAE, 0x57A3, 0xABAF, 0x57A2, 0xABB0, 0x57CE, 0xABB1, 0x57AE, 0xABB2, 0x5793, 0xABB3, 0x5955, 0xABB4, 0x5951, 0xABB5, 0x594F, + 0xABB6, 0x594E, 0xABB7, 0x5950, 0xABB8, 0x59DC, 0xABB9, 0x59D8, 0xABBA, 0x59FF, 0xABBB, 0x59E3, 0xABBC, 0x59E8, 0xABBD, 0x5A03, + 0xABBE, 0x59E5, 0xABBF, 0x59EA, 0xABC0, 0x59DA, 0xABC1, 0x59E6, 0xABC2, 0x5A01, 0xABC3, 0x59FB, 0xABC4, 0x5B69, 0xABC5, 0x5BA3, + 0xABC6, 0x5BA6, 0xABC7, 0x5BA4, 0xABC8, 0x5BA2, 0xABC9, 0x5BA5, 0xABCA, 0x5C01, 0xABCB, 0x5C4E, 0xABCC, 0x5C4F, 0xABCD, 0x5C4D, + 0xABCE, 0x5C4B, 0xABCF, 0x5CD9, 0xABD0, 0x5CD2, 0xABD1, 0x5DF7, 0xABD2, 0x5E1D, 0xABD3, 0x5E25, 0xABD4, 0x5E1F, 0xABD5, 0x5E7D, + 0xABD6, 0x5EA0, 0xABD7, 0x5EA6, 0xABD8, 0x5EFA, 0xABD9, 0x5F08, 0xABDA, 0x5F2D, 0xABDB, 0x5F65, 0xABDC, 0x5F88, 0xABDD, 0x5F85, + 0xABDE, 0x5F8A, 0xABDF, 0x5F8B, 0xABE0, 0x5F87, 0xABE1, 0x5F8C, 0xABE2, 0x5F89, 0xABE3, 0x6012, 0xABE4, 0x601D, 0xABE5, 0x6020, + 0xABE6, 0x6025, 0xABE7, 0x600E, 0xABE8, 0x6028, 0xABE9, 0x604D, 0xABEA, 0x6070, 0xABEB, 0x6068, 0xABEC, 0x6062, 0xABED, 0x6046, + 0xABEE, 0x6043, 0xABEF, 0x606C, 0xABF0, 0x606B, 0xABF1, 0x606A, 0xABF2, 0x6064, 0xABF3, 0x6241, 0xABF4, 0x62DC, 0xABF5, 0x6316, + 0xABF6, 0x6309, 0xABF7, 0x62FC, 0xABF8, 0x62ED, 0xABF9, 0x6301, 0xABFA, 0x62EE, 0xABFB, 0x62FD, 0xABFC, 0x6307, 0xABFD, 0x62F1, + 0xABFE, 0x62F7, 0xAC40, 0x62EF, 0xAC41, 0x62EC, 0xAC42, 0x62FE, 0xAC43, 0x62F4, 0xAC44, 0x6311, 0xAC45, 0x6302, 0xAC46, 0x653F, + 0xAC47, 0x6545, 0xAC48, 0x65AB, 0xAC49, 0x65BD, 0xAC4A, 0x65E2, 0xAC4B, 0x6625, 0xAC4C, 0x662D, 0xAC4D, 0x6620, 0xAC4E, 0x6627, + 0xAC4F, 0x662F, 0xAC50, 0x661F, 0xAC51, 0x6628, 0xAC52, 0x6631, 0xAC53, 0x6624, 0xAC54, 0x66F7, 0xAC55, 0x67FF, 0xAC56, 0x67D3, + 0xAC57, 0x67F1, 0xAC58, 0x67D4, 0xAC59, 0x67D0, 0xAC5A, 0x67EC, 0xAC5B, 0x67B6, 0xAC5C, 0x67AF, 0xAC5D, 0x67F5, 0xAC5E, 0x67E9, + 0xAC5F, 0x67EF, 0xAC60, 0x67C4, 0xAC61, 0x67D1, 0xAC62, 0x67B4, 0xAC63, 0x67DA, 0xAC64, 0x67E5, 0xAC65, 0x67B8, 0xAC66, 0x67CF, + 0xAC67, 0x67DE, 0xAC68, 0x67F3, 0xAC69, 0x67B0, 0xAC6A, 0x67D9, 0xAC6B, 0x67E2, 0xAC6C, 0x67DD, 0xAC6D, 0x67D2, 0xAC6E, 0x6B6A, + 0xAC6F, 0x6B83, 0xAC70, 0x6B86, 0xAC71, 0x6BB5, 0xAC72, 0x6BD2, 0xAC73, 0x6BD7, 0xAC74, 0x6C1F, 0xAC75, 0x6CC9, 0xAC76, 0x6D0B, + 0xAC77, 0x6D32, 0xAC78, 0x6D2A, 0xAC79, 0x6D41, 0xAC7A, 0x6D25, 0xAC7B, 0x6D0C, 0xAC7C, 0x6D31, 0xAC7D, 0x6D1E, 0xAC7E, 0x6D17, + 0xACA1, 0x6D3B, 0xACA2, 0x6D3D, 0xACA3, 0x6D3E, 0xACA4, 0x6D36, 0xACA5, 0x6D1B, 0xACA6, 0x6CF5, 0xACA7, 0x6D39, 0xACA8, 0x6D27, + 0xACA9, 0x6D38, 0xACAA, 0x6D29, 0xACAB, 0x6D2E, 0xACAC, 0x6D35, 0xACAD, 0x6D0E, 0xACAE, 0x6D2B, 0xACAF, 0x70AB, 0xACB0, 0x70BA, + 0xACB1, 0x70B3, 0xACB2, 0x70AC, 0xACB3, 0x70AF, 0xACB4, 0x70AD, 0xACB5, 0x70B8, 0xACB6, 0x70AE, 0xACB7, 0x70A4, 0xACB8, 0x7230, + 0xACB9, 0x7272, 0xACBA, 0x726F, 0xACBB, 0x7274, 0xACBC, 0x72E9, 0xACBD, 0x72E0, 0xACBE, 0x72E1, 0xACBF, 0x73B7, 0xACC0, 0x73CA, + 0xACC1, 0x73BB, 0xACC2, 0x73B2, 0xACC3, 0x73CD, 0xACC4, 0x73C0, 0xACC5, 0x73B3, 0xACC6, 0x751A, 0xACC7, 0x752D, 0xACC8, 0x754F, + 0xACC9, 0x754C, 0xACCA, 0x754E, 0xACCB, 0x754B, 0xACCC, 0x75AB, 0xACCD, 0x75A4, 0xACCE, 0x75A5, 0xACCF, 0x75A2, 0xACD0, 0x75A3, + 0xACD1, 0x7678, 0xACD2, 0x7686, 0xACD3, 0x7687, 0xACD4, 0x7688, 0xACD5, 0x76C8, 0xACD6, 0x76C6, 0xACD7, 0x76C3, 0xACD8, 0x76C5, + 0xACD9, 0x7701, 0xACDA, 0x76F9, 0xACDB, 0x76F8, 0xACDC, 0x7709, 0xACDD, 0x770B, 0xACDE, 0x76FE, 0xACDF, 0x76FC, 0xACE0, 0x7707, + 0xACE1, 0x77DC, 0xACE2, 0x7802, 0xACE3, 0x7814, 0xACE4, 0x780C, 0xACE5, 0x780D, 0xACE6, 0x7946, 0xACE7, 0x7949, 0xACE8, 0x7948, + 0xACE9, 0x7947, 0xACEA, 0x79B9, 0xACEB, 0x79BA, 0xACEC, 0x79D1, 0xACED, 0x79D2, 0xACEE, 0x79CB, 0xACEF, 0x7A7F, 0xACF0, 0x7A81, + 0xACF1, 0x7AFF, 0xACF2, 0x7AFD, 0xACF3, 0x7C7D, 0xACF4, 0x7D02, 0xACF5, 0x7D05, 0xACF6, 0x7D00, 0xACF7, 0x7D09, 0xACF8, 0x7D07, + 0xACF9, 0x7D04, 0xACFA, 0x7D06, 0xACFB, 0x7F38, 0xACFC, 0x7F8E, 0xACFD, 0x7FBF, 0xACFE, 0x8004, 0xAD40, 0x8010, 0xAD41, 0x800D, + 0xAD42, 0x8011, 0xAD43, 0x8036, 0xAD44, 0x80D6, 0xAD45, 0x80E5, 0xAD46, 0x80DA, 0xAD47, 0x80C3, 0xAD48, 0x80C4, 0xAD49, 0x80CC, + 0xAD4A, 0x80E1, 0xAD4B, 0x80DB, 0xAD4C, 0x80CE, 0xAD4D, 0x80DE, 0xAD4E, 0x80E4, 0xAD4F, 0x80DD, 0xAD50, 0x81F4, 0xAD51, 0x8222, + 0xAD52, 0x82E7, 0xAD53, 0x8303, 0xAD54, 0x8305, 0xAD55, 0x82E3, 0xAD56, 0x82DB, 0xAD57, 0x82E6, 0xAD58, 0x8304, 0xAD59, 0x82E5, + 0xAD5A, 0x8302, 0xAD5B, 0x8309, 0xAD5C, 0x82D2, 0xAD5D, 0x82D7, 0xAD5E, 0x82F1, 0xAD5F, 0x8301, 0xAD60, 0x82DC, 0xAD61, 0x82D4, + 0xAD62, 0x82D1, 0xAD63, 0x82DE, 0xAD64, 0x82D3, 0xAD65, 0x82DF, 0xAD66, 0x82EF, 0xAD67, 0x8306, 0xAD68, 0x8650, 0xAD69, 0x8679, + 0xAD6A, 0x867B, 0xAD6B, 0x867A, 0xAD6C, 0x884D, 0xAD6D, 0x886B, 0xAD6E, 0x8981, 0xAD6F, 0x89D4, 0xAD70, 0x8A08, 0xAD71, 0x8A02, + 0xAD72, 0x8A03, 0xAD73, 0x8C9E, 0xAD74, 0x8CA0, 0xAD75, 0x8D74, 0xAD76, 0x8D73, 0xAD77, 0x8DB4, 0xAD78, 0x8ECD, 0xAD79, 0x8ECC, + 0xAD7A, 0x8FF0, 0xAD7B, 0x8FE6, 0xAD7C, 0x8FE2, 0xAD7D, 0x8FEA, 0xAD7E, 0x8FE5, 0xADA1, 0x8FED, 0xADA2, 0x8FEB, 0xADA3, 0x8FE4, + 0xADA4, 0x8FE8, 0xADA5, 0x90CA, 0xADA6, 0x90CE, 0xADA7, 0x90C1, 0xADA8, 0x90C3, 0xADA9, 0x914B, 0xADAA, 0x914A, 0xADAB, 0x91CD, + 0xADAC, 0x9582, 0xADAD, 0x9650, 0xADAE, 0x964B, 0xADAF, 0x964C, 0xADB0, 0x964D, 0xADB1, 0x9762, 0xADB2, 0x9769, 0xADB3, 0x97CB, + 0xADB4, 0x97ED, 0xADB5, 0x97F3, 0xADB6, 0x9801, 0xADB7, 0x98A8, 0xADB8, 0x98DB, 0xADB9, 0x98DF, 0xADBA, 0x9996, 0xADBB, 0x9999, + 0xADBC, 0x4E58, 0xADBD, 0x4EB3, 0xADBE, 0x500C, 0xADBF, 0x500D, 0xADC0, 0x5023, 0xADC1, 0x4FEF, 0xADC2, 0x5026, 0xADC3, 0x5025, + 0xADC4, 0x4FF8, 0xADC5, 0x5029, 0xADC6, 0x5016, 0xADC7, 0x5006, 0xADC8, 0x503C, 0xADC9, 0x501F, 0xADCA, 0x501A, 0xADCB, 0x5012, + 0xADCC, 0x5011, 0xADCD, 0x4FFA, 0xADCE, 0x5000, 0xADCF, 0x5014, 0xADD0, 0x5028, 0xADD1, 0x4FF1, 0xADD2, 0x5021, 0xADD3, 0x500B, + 0xADD4, 0x5019, 0xADD5, 0x5018, 0xADD6, 0x4FF3, 0xADD7, 0x4FEE, 0xADD8, 0x502D, 0xADD9, 0x502A, 0xADDA, 0x4FFE, 0xADDB, 0x502B, + 0xADDC, 0x5009, 0xADDD, 0x517C, 0xADDE, 0x51A4, 0xADDF, 0x51A5, 0xADE0, 0x51A2, 0xADE1, 0x51CD, 0xADE2, 0x51CC, 0xADE3, 0x51C6, + 0xADE4, 0x51CB, 0xADE5, 0x5256, 0xADE6, 0x525C, 0xADE7, 0x5254, 0xADE8, 0x525B, 0xADE9, 0x525D, 0xADEA, 0x532A, 0xADEB, 0x537F, + 0xADEC, 0x539F, 0xADED, 0x539D, 0xADEE, 0x53DF, 0xADEF, 0x54E8, 0xADF0, 0x5510, 0xADF1, 0x5501, 0xADF2, 0x5537, 0xADF3, 0x54FC, + 0xADF4, 0x54E5, 0xADF5, 0x54F2, 0xADF6, 0x5506, 0xADF7, 0x54FA, 0xADF8, 0x5514, 0xADF9, 0x54E9, 0xADFA, 0x54ED, 0xADFB, 0x54E1, + 0xADFC, 0x5509, 0xADFD, 0x54EE, 0xADFE, 0x54EA, 0xAE40, 0x54E6, 0xAE41, 0x5527, 0xAE42, 0x5507, 0xAE43, 0x54FD, 0xAE44, 0x550F, + 0xAE45, 0x5703, 0xAE46, 0x5704, 0xAE47, 0x57C2, 0xAE48, 0x57D4, 0xAE49, 0x57CB, 0xAE4A, 0x57C3, 0xAE4B, 0x5809, 0xAE4C, 0x590F, + 0xAE4D, 0x5957, 0xAE4E, 0x5958, 0xAE4F, 0x595A, 0xAE50, 0x5A11, 0xAE51, 0x5A18, 0xAE52, 0x5A1C, 0xAE53, 0x5A1F, 0xAE54, 0x5A1B, + 0xAE55, 0x5A13, 0xAE56, 0x59EC, 0xAE57, 0x5A20, 0xAE58, 0x5A23, 0xAE59, 0x5A29, 0xAE5A, 0x5A25, 0xAE5B, 0x5A0C, 0xAE5C, 0x5A09, + 0xAE5D, 0x5B6B, 0xAE5E, 0x5C58, 0xAE5F, 0x5BB0, 0xAE60, 0x5BB3, 0xAE61, 0x5BB6, 0xAE62, 0x5BB4, 0xAE63, 0x5BAE, 0xAE64, 0x5BB5, + 0xAE65, 0x5BB9, 0xAE66, 0x5BB8, 0xAE67, 0x5C04, 0xAE68, 0x5C51, 0xAE69, 0x5C55, 0xAE6A, 0x5C50, 0xAE6B, 0x5CED, 0xAE6C, 0x5CFD, + 0xAE6D, 0x5CFB, 0xAE6E, 0x5CEA, 0xAE6F, 0x5CE8, 0xAE70, 0x5CF0, 0xAE71, 0x5CF6, 0xAE72, 0x5D01, 0xAE73, 0x5CF4, 0xAE74, 0x5DEE, + 0xAE75, 0x5E2D, 0xAE76, 0x5E2B, 0xAE77, 0x5EAB, 0xAE78, 0x5EAD, 0xAE79, 0x5EA7, 0xAE7A, 0x5F31, 0xAE7B, 0x5F92, 0xAE7C, 0x5F91, + 0xAE7D, 0x5F90, 0xAE7E, 0x6059, 0xAEA1, 0x6063, 0xAEA2, 0x6065, 0xAEA3, 0x6050, 0xAEA4, 0x6055, 0xAEA5, 0x606D, 0xAEA6, 0x6069, + 0xAEA7, 0x606F, 0xAEA8, 0x6084, 0xAEA9, 0x609F, 0xAEAA, 0x609A, 0xAEAB, 0x608D, 0xAEAC, 0x6094, 0xAEAD, 0x608C, 0xAEAE, 0x6085, + 0xAEAF, 0x6096, 0xAEB0, 0x6247, 0xAEB1, 0x62F3, 0xAEB2, 0x6308, 0xAEB3, 0x62FF, 0xAEB4, 0x634E, 0xAEB5, 0x633E, 0xAEB6, 0x632F, + 0xAEB7, 0x6355, 0xAEB8, 0x6342, 0xAEB9, 0x6346, 0xAEBA, 0x634F, 0xAEBB, 0x6349, 0xAEBC, 0x633A, 0xAEBD, 0x6350, 0xAEBE, 0x633D, + 0xAEBF, 0x632A, 0xAEC0, 0x632B, 0xAEC1, 0x6328, 0xAEC2, 0x634D, 0xAEC3, 0x634C, 0xAEC4, 0x6548, 0xAEC5, 0x6549, 0xAEC6, 0x6599, + 0xAEC7, 0x65C1, 0xAEC8, 0x65C5, 0xAEC9, 0x6642, 0xAECA, 0x6649, 0xAECB, 0x664F, 0xAECC, 0x6643, 0xAECD, 0x6652, 0xAECE, 0x664C, + 0xAECF, 0x6645, 0xAED0, 0x6641, 0xAED1, 0x66F8, 0xAED2, 0x6714, 0xAED3, 0x6715, 0xAED4, 0x6717, 0xAED5, 0x6821, 0xAED6, 0x6838, + 0xAED7, 0x6848, 0xAED8, 0x6846, 0xAED9, 0x6853, 0xAEDA, 0x6839, 0xAEDB, 0x6842, 0xAEDC, 0x6854, 0xAEDD, 0x6829, 0xAEDE, 0x68B3, + 0xAEDF, 0x6817, 0xAEE0, 0x684C, 0xAEE1, 0x6851, 0xAEE2, 0x683D, 0xAEE3, 0x67F4, 0xAEE4, 0x6850, 0xAEE5, 0x6840, 0xAEE6, 0x683C, + 0xAEE7, 0x6843, 0xAEE8, 0x682A, 0xAEE9, 0x6845, 0xAEEA, 0x6813, 0xAEEB, 0x6818, 0xAEEC, 0x6841, 0xAEED, 0x6B8A, 0xAEEE, 0x6B89, + 0xAEEF, 0x6BB7, 0xAEF0, 0x6C23, 0xAEF1, 0x6C27, 0xAEF2, 0x6C28, 0xAEF3, 0x6C26, 0xAEF4, 0x6C24, 0xAEF5, 0x6CF0, 0xAEF6, 0x6D6A, + 0xAEF7, 0x6D95, 0xAEF8, 0x6D88, 0xAEF9, 0x6D87, 0xAEFA, 0x6D66, 0xAEFB, 0x6D78, 0xAEFC, 0x6D77, 0xAEFD, 0x6D59, 0xAEFE, 0x6D93, + 0xAF40, 0x6D6C, 0xAF41, 0x6D89, 0xAF42, 0x6D6E, 0xAF43, 0x6D5A, 0xAF44, 0x6D74, 0xAF45, 0x6D69, 0xAF46, 0x6D8C, 0xAF47, 0x6D8A, + 0xAF48, 0x6D79, 0xAF49, 0x6D85, 0xAF4A, 0x6D65, 0xAF4B, 0x6D94, 0xAF4C, 0x70CA, 0xAF4D, 0x70D8, 0xAF4E, 0x70E4, 0xAF4F, 0x70D9, + 0xAF50, 0x70C8, 0xAF51, 0x70CF, 0xAF52, 0x7239, 0xAF53, 0x7279, 0xAF54, 0x72FC, 0xAF55, 0x72F9, 0xAF56, 0x72FD, 0xAF57, 0x72F8, + 0xAF58, 0x72F7, 0xAF59, 0x7386, 0xAF5A, 0x73ED, 0xAF5B, 0x7409, 0xAF5C, 0x73EE, 0xAF5D, 0x73E0, 0xAF5E, 0x73EA, 0xAF5F, 0x73DE, + 0xAF60, 0x7554, 0xAF61, 0x755D, 0xAF62, 0x755C, 0xAF63, 0x755A, 0xAF64, 0x7559, 0xAF65, 0x75BE, 0xAF66, 0x75C5, 0xAF67, 0x75C7, + 0xAF68, 0x75B2, 0xAF69, 0x75B3, 0xAF6A, 0x75BD, 0xAF6B, 0x75BC, 0xAF6C, 0x75B9, 0xAF6D, 0x75C2, 0xAF6E, 0x75B8, 0xAF6F, 0x768B, + 0xAF70, 0x76B0, 0xAF71, 0x76CA, 0xAF72, 0x76CD, 0xAF73, 0x76CE, 0xAF74, 0x7729, 0xAF75, 0x771F, 0xAF76, 0x7720, 0xAF77, 0x7728, + 0xAF78, 0x77E9, 0xAF79, 0x7830, 0xAF7A, 0x7827, 0xAF7B, 0x7838, 0xAF7C, 0x781D, 0xAF7D, 0x7834, 0xAF7E, 0x7837, 0xAFA1, 0x7825, + 0xAFA2, 0x782D, 0xAFA3, 0x7820, 0xAFA4, 0x781F, 0xAFA5, 0x7832, 0xAFA6, 0x7955, 0xAFA7, 0x7950, 0xAFA8, 0x7960, 0xAFA9, 0x795F, + 0xAFAA, 0x7956, 0xAFAB, 0x795E, 0xAFAC, 0x795D, 0xAFAD, 0x7957, 0xAFAE, 0x795A, 0xAFAF, 0x79E4, 0xAFB0, 0x79E3, 0xAFB1, 0x79E7, + 0xAFB2, 0x79DF, 0xAFB3, 0x79E6, 0xAFB4, 0x79E9, 0xAFB5, 0x79D8, 0xAFB6, 0x7A84, 0xAFB7, 0x7A88, 0xAFB8, 0x7AD9, 0xAFB9, 0x7B06, + 0xAFBA, 0x7B11, 0xAFBB, 0x7C89, 0xAFBC, 0x7D21, 0xAFBD, 0x7D17, 0xAFBE, 0x7D0B, 0xAFBF, 0x7D0A, 0xAFC0, 0x7D20, 0xAFC1, 0x7D22, + 0xAFC2, 0x7D14, 0xAFC3, 0x7D10, 0xAFC4, 0x7D15, 0xAFC5, 0x7D1A, 0xAFC6, 0x7D1C, 0xAFC7, 0x7D0D, 0xAFC8, 0x7D19, 0xAFC9, 0x7D1B, + 0xAFCA, 0x7F3A, 0xAFCB, 0x7F5F, 0xAFCC, 0x7F94, 0xAFCD, 0x7FC5, 0xAFCE, 0x7FC1, 0xAFCF, 0x8006, 0xAFD0, 0x8018, 0xAFD1, 0x8015, + 0xAFD2, 0x8019, 0xAFD3, 0x8017, 0xAFD4, 0x803D, 0xAFD5, 0x803F, 0xAFD6, 0x80F1, 0xAFD7, 0x8102, 0xAFD8, 0x80F0, 0xAFD9, 0x8105, + 0xAFDA, 0x80ED, 0xAFDB, 0x80F4, 0xAFDC, 0x8106, 0xAFDD, 0x80F8, 0xAFDE, 0x80F3, 0xAFDF, 0x8108, 0xAFE0, 0x80FD, 0xAFE1, 0x810A, + 0xAFE2, 0x80FC, 0xAFE3, 0x80EF, 0xAFE4, 0x81ED, 0xAFE5, 0x81EC, 0xAFE6, 0x8200, 0xAFE7, 0x8210, 0xAFE8, 0x822A, 0xAFE9, 0x822B, + 0xAFEA, 0x8228, 0xAFEB, 0x822C, 0xAFEC, 0x82BB, 0xAFED, 0x832B, 0xAFEE, 0x8352, 0xAFEF, 0x8354, 0xAFF0, 0x834A, 0xAFF1, 0x8338, + 0xAFF2, 0x8350, 0xAFF3, 0x8349, 0xAFF4, 0x8335, 0xAFF5, 0x8334, 0xAFF6, 0x834F, 0xAFF7, 0x8332, 0xAFF8, 0x8339, 0xAFF9, 0x8336, + 0xAFFA, 0x8317, 0xAFFB, 0x8340, 0xAFFC, 0x8331, 0xAFFD, 0x8328, 0xAFFE, 0x8343, 0xB040, 0x8654, 0xB041, 0x868A, 0xB042, 0x86AA, + 0xB043, 0x8693, 0xB044, 0x86A4, 0xB045, 0x86A9, 0xB046, 0x868C, 0xB047, 0x86A3, 0xB048, 0x869C, 0xB049, 0x8870, 0xB04A, 0x8877, + 0xB04B, 0x8881, 0xB04C, 0x8882, 0xB04D, 0x887D, 0xB04E, 0x8879, 0xB04F, 0x8A18, 0xB050, 0x8A10, 0xB051, 0x8A0E, 0xB052, 0x8A0C, + 0xB053, 0x8A15, 0xB054, 0x8A0A, 0xB055, 0x8A17, 0xB056, 0x8A13, 0xB057, 0x8A16, 0xB058, 0x8A0F, 0xB059, 0x8A11, 0xB05A, 0x8C48, + 0xB05B, 0x8C7A, 0xB05C, 0x8C79, 0xB05D, 0x8CA1, 0xB05E, 0x8CA2, 0xB05F, 0x8D77, 0xB060, 0x8EAC, 0xB061, 0x8ED2, 0xB062, 0x8ED4, + 0xB063, 0x8ECF, 0xB064, 0x8FB1, 0xB065, 0x9001, 0xB066, 0x9006, 0xB067, 0x8FF7, 0xB068, 0x9000, 0xB069, 0x8FFA, 0xB06A, 0x8FF4, + 0xB06B, 0x9003, 0xB06C, 0x8FFD, 0xB06D, 0x9005, 0xB06E, 0x8FF8, 0xB06F, 0x9095, 0xB070, 0x90E1, 0xB071, 0x90DD, 0xB072, 0x90E2, + 0xB073, 0x9152, 0xB074, 0x914D, 0xB075, 0x914C, 0xB076, 0x91D8, 0xB077, 0x91DD, 0xB078, 0x91D7, 0xB079, 0x91DC, 0xB07A, 0x91D9, + 0xB07B, 0x9583, 0xB07C, 0x9662, 0xB07D, 0x9663, 0xB07E, 0x9661, 0xB0A1, 0x965B, 0xB0A2, 0x965D, 0xB0A3, 0x9664, 0xB0A4, 0x9658, + 0xB0A5, 0x965E, 0xB0A6, 0x96BB, 0xB0A7, 0x98E2, 0xB0A8, 0x99AC, 0xB0A9, 0x9AA8, 0xB0AA, 0x9AD8, 0xB0AB, 0x9B25, 0xB0AC, 0x9B32, + 0xB0AD, 0x9B3C, 0xB0AE, 0x4E7E, 0xB0AF, 0x507A, 0xB0B0, 0x507D, 0xB0B1, 0x505C, 0xB0B2, 0x5047, 0xB0B3, 0x5043, 0xB0B4, 0x504C, + 0xB0B5, 0x505A, 0xB0B6, 0x5049, 0xB0B7, 0x5065, 0xB0B8, 0x5076, 0xB0B9, 0x504E, 0xB0BA, 0x5055, 0xB0BB, 0x5075, 0xB0BC, 0x5074, + 0xB0BD, 0x5077, 0xB0BE, 0x504F, 0xB0BF, 0x500F, 0xB0C0, 0x506F, 0xB0C1, 0x506D, 0xB0C2, 0x515C, 0xB0C3, 0x5195, 0xB0C4, 0x51F0, + 0xB0C5, 0x526A, 0xB0C6, 0x526F, 0xB0C7, 0x52D2, 0xB0C8, 0x52D9, 0xB0C9, 0x52D8, 0xB0CA, 0x52D5, 0xB0CB, 0x5310, 0xB0CC, 0x530F, + 0xB0CD, 0x5319, 0xB0CE, 0x533F, 0xB0CF, 0x5340, 0xB0D0, 0x533E, 0xB0D1, 0x53C3, 0xB0D2, 0x66FC, 0xB0D3, 0x5546, 0xB0D4, 0x556A, + 0xB0D5, 0x5566, 0xB0D6, 0x5544, 0xB0D7, 0x555E, 0xB0D8, 0x5561, 0xB0D9, 0x5543, 0xB0DA, 0x554A, 0xB0DB, 0x5531, 0xB0DC, 0x5556, + 0xB0DD, 0x554F, 0xB0DE, 0x5555, 0xB0DF, 0x552F, 0xB0E0, 0x5564, 0xB0E1, 0x5538, 0xB0E2, 0x552E, 0xB0E3, 0x555C, 0xB0E4, 0x552C, + 0xB0E5, 0x5563, 0xB0E6, 0x5533, 0xB0E7, 0x5541, 0xB0E8, 0x5557, 0xB0E9, 0x5708, 0xB0EA, 0x570B, 0xB0EB, 0x5709, 0xB0EC, 0x57DF, + 0xB0ED, 0x5805, 0xB0EE, 0x580A, 0xB0EF, 0x5806, 0xB0F0, 0x57E0, 0xB0F1, 0x57E4, 0xB0F2, 0x57FA, 0xB0F3, 0x5802, 0xB0F4, 0x5835, + 0xB0F5, 0x57F7, 0xB0F6, 0x57F9, 0xB0F7, 0x5920, 0xB0F8, 0x5962, 0xB0F9, 0x5A36, 0xB0FA, 0x5A41, 0xB0FB, 0x5A49, 0xB0FC, 0x5A66, + 0xB0FD, 0x5A6A, 0xB0FE, 0x5A40, 0xB140, 0x5A3C, 0xB141, 0x5A62, 0xB142, 0x5A5A, 0xB143, 0x5A46, 0xB144, 0x5A4A, 0xB145, 0x5B70, + 0xB146, 0x5BC7, 0xB147, 0x5BC5, 0xB148, 0x5BC4, 0xB149, 0x5BC2, 0xB14A, 0x5BBF, 0xB14B, 0x5BC6, 0xB14C, 0x5C09, 0xB14D, 0x5C08, + 0xB14E, 0x5C07, 0xB14F, 0x5C60, 0xB150, 0x5C5C, 0xB151, 0x5C5D, 0xB152, 0x5D07, 0xB153, 0x5D06, 0xB154, 0x5D0E, 0xB155, 0x5D1B, + 0xB156, 0x5D16, 0xB157, 0x5D22, 0xB158, 0x5D11, 0xB159, 0x5D29, 0xB15A, 0x5D14, 0xB15B, 0x5D19, 0xB15C, 0x5D24, 0xB15D, 0x5D27, + 0xB15E, 0x5D17, 0xB15F, 0x5DE2, 0xB160, 0x5E38, 0xB161, 0x5E36, 0xB162, 0x5E33, 0xB163, 0x5E37, 0xB164, 0x5EB7, 0xB165, 0x5EB8, + 0xB166, 0x5EB6, 0xB167, 0x5EB5, 0xB168, 0x5EBE, 0xB169, 0x5F35, 0xB16A, 0x5F37, 0xB16B, 0x5F57, 0xB16C, 0x5F6C, 0xB16D, 0x5F69, + 0xB16E, 0x5F6B, 0xB16F, 0x5F97, 0xB170, 0x5F99, 0xB171, 0x5F9E, 0xB172, 0x5F98, 0xB173, 0x5FA1, 0xB174, 0x5FA0, 0xB175, 0x5F9C, + 0xB176, 0x607F, 0xB177, 0x60A3, 0xB178, 0x6089, 0xB179, 0x60A0, 0xB17A, 0x60A8, 0xB17B, 0x60CB, 0xB17C, 0x60B4, 0xB17D, 0x60E6, + 0xB17E, 0x60BD, 0xB1A1, 0x60C5, 0xB1A2, 0x60BB, 0xB1A3, 0x60B5, 0xB1A4, 0x60DC, 0xB1A5, 0x60BC, 0xB1A6, 0x60D8, 0xB1A7, 0x60D5, + 0xB1A8, 0x60C6, 0xB1A9, 0x60DF, 0xB1AA, 0x60B8, 0xB1AB, 0x60DA, 0xB1AC, 0x60C7, 0xB1AD, 0x621A, 0xB1AE, 0x621B, 0xB1AF, 0x6248, + 0xB1B0, 0x63A0, 0xB1B1, 0x63A7, 0xB1B2, 0x6372, 0xB1B3, 0x6396, 0xB1B4, 0x63A2, 0xB1B5, 0x63A5, 0xB1B6, 0x6377, 0xB1B7, 0x6367, + 0xB1B8, 0x6398, 0xB1B9, 0x63AA, 0xB1BA, 0x6371, 0xB1BB, 0x63A9, 0xB1BC, 0x6389, 0xB1BD, 0x6383, 0xB1BE, 0x639B, 0xB1BF, 0x636B, + 0xB1C0, 0x63A8, 0xB1C1, 0x6384, 0xB1C2, 0x6388, 0xB1C3, 0x6399, 0xB1C4, 0x63A1, 0xB1C5, 0x63AC, 0xB1C6, 0x6392, 0xB1C7, 0x638F, + 0xB1C8, 0x6380, 0xB1C9, 0x637B, 0xB1CA, 0x6369, 0xB1CB, 0x6368, 0xB1CC, 0x637A, 0xB1CD, 0x655D, 0xB1CE, 0x6556, 0xB1CF, 0x6551, + 0xB1D0, 0x6559, 0xB1D1, 0x6557, 0xB1D2, 0x555F, 0xB1D3, 0x654F, 0xB1D4, 0x6558, 0xB1D5, 0x6555, 0xB1D6, 0x6554, 0xB1D7, 0x659C, + 0xB1D8, 0x659B, 0xB1D9, 0x65AC, 0xB1DA, 0x65CF, 0xB1DB, 0x65CB, 0xB1DC, 0x65CC, 0xB1DD, 0x65CE, 0xB1DE, 0x665D, 0xB1DF, 0x665A, + 0xB1E0, 0x6664, 0xB1E1, 0x6668, 0xB1E2, 0x6666, 0xB1E3, 0x665E, 0xB1E4, 0x66F9, 0xB1E5, 0x52D7, 0xB1E6, 0x671B, 0xB1E7, 0x6881, + 0xB1E8, 0x68AF, 0xB1E9, 0x68A2, 0xB1EA, 0x6893, 0xB1EB, 0x68B5, 0xB1EC, 0x687F, 0xB1ED, 0x6876, 0xB1EE, 0x68B1, 0xB1EF, 0x68A7, + 0xB1F0, 0x6897, 0xB1F1, 0x68B0, 0xB1F2, 0x6883, 0xB1F3, 0x68C4, 0xB1F4, 0x68AD, 0xB1F5, 0x6886, 0xB1F6, 0x6885, 0xB1F7, 0x6894, + 0xB1F8, 0x689D, 0xB1F9, 0x68A8, 0xB1FA, 0x689F, 0xB1FB, 0x68A1, 0xB1FC, 0x6882, 0xB1FD, 0x6B32, 0xB1FE, 0x6BBA, 0xB240, 0x6BEB, + 0xB241, 0x6BEC, 0xB242, 0x6C2B, 0xB243, 0x6D8E, 0xB244, 0x6DBC, 0xB245, 0x6DF3, 0xB246, 0x6DD9, 0xB247, 0x6DB2, 0xB248, 0x6DE1, + 0xB249, 0x6DCC, 0xB24A, 0x6DE4, 0xB24B, 0x6DFB, 0xB24C, 0x6DFA, 0xB24D, 0x6E05, 0xB24E, 0x6DC7, 0xB24F, 0x6DCB, 0xB250, 0x6DAF, + 0xB251, 0x6DD1, 0xB252, 0x6DAE, 0xB253, 0x6DDE, 0xB254, 0x6DF9, 0xB255, 0x6DB8, 0xB256, 0x6DF7, 0xB257, 0x6DF5, 0xB258, 0x6DC5, + 0xB259, 0x6DD2, 0xB25A, 0x6E1A, 0xB25B, 0x6DB5, 0xB25C, 0x6DDA, 0xB25D, 0x6DEB, 0xB25E, 0x6DD8, 0xB25F, 0x6DEA, 0xB260, 0x6DF1, + 0xB261, 0x6DEE, 0xB262, 0x6DE8, 0xB263, 0x6DC6, 0xB264, 0x6DC4, 0xB265, 0x6DAA, 0xB266, 0x6DEC, 0xB267, 0x6DBF, 0xB268, 0x6DE6, + 0xB269, 0x70F9, 0xB26A, 0x7109, 0xB26B, 0x710A, 0xB26C, 0x70FD, 0xB26D, 0x70EF, 0xB26E, 0x723D, 0xB26F, 0x727D, 0xB270, 0x7281, + 0xB271, 0x731C, 0xB272, 0x731B, 0xB273, 0x7316, 0xB274, 0x7313, 0xB275, 0x7319, 0xB276, 0x7387, 0xB277, 0x7405, 0xB278, 0x740A, + 0xB279, 0x7403, 0xB27A, 0x7406, 0xB27B, 0x73FE, 0xB27C, 0x740D, 0xB27D, 0x74E0, 0xB27E, 0x74F6, 0xB2A1, 0x74F7, 0xB2A2, 0x751C, + 0xB2A3, 0x7522, 0xB2A4, 0x7565, 0xB2A5, 0x7566, 0xB2A6, 0x7562, 0xB2A7, 0x7570, 0xB2A8, 0x758F, 0xB2A9, 0x75D4, 0xB2AA, 0x75D5, + 0xB2AB, 0x75B5, 0xB2AC, 0x75CA, 0xB2AD, 0x75CD, 0xB2AE, 0x768E, 0xB2AF, 0x76D4, 0xB2B0, 0x76D2, 0xB2B1, 0x76DB, 0xB2B2, 0x7737, + 0xB2B3, 0x773E, 0xB2B4, 0x773C, 0xB2B5, 0x7736, 0xB2B6, 0x7738, 0xB2B7, 0x773A, 0xB2B8, 0x786B, 0xB2B9, 0x7843, 0xB2BA, 0x784E, + 0xB2BB, 0x7965, 0xB2BC, 0x7968, 0xB2BD, 0x796D, 0xB2BE, 0x79FB, 0xB2BF, 0x7A92, 0xB2C0, 0x7A95, 0xB2C1, 0x7B20, 0xB2C2, 0x7B28, + 0xB2C3, 0x7B1B, 0xB2C4, 0x7B2C, 0xB2C5, 0x7B26, 0xB2C6, 0x7B19, 0xB2C7, 0x7B1E, 0xB2C8, 0x7B2E, 0xB2C9, 0x7C92, 0xB2CA, 0x7C97, + 0xB2CB, 0x7C95, 0xB2CC, 0x7D46, 0xB2CD, 0x7D43, 0xB2CE, 0x7D71, 0xB2CF, 0x7D2E, 0xB2D0, 0x7D39, 0xB2D1, 0x7D3C, 0xB2D2, 0x7D40, + 0xB2D3, 0x7D30, 0xB2D4, 0x7D33, 0xB2D5, 0x7D44, 0xB2D6, 0x7D2F, 0xB2D7, 0x7D42, 0xB2D8, 0x7D32, 0xB2D9, 0x7D31, 0xB2DA, 0x7F3D, + 0xB2DB, 0x7F9E, 0xB2DC, 0x7F9A, 0xB2DD, 0x7FCC, 0xB2DE, 0x7FCE, 0xB2DF, 0x7FD2, 0xB2E0, 0x801C, 0xB2E1, 0x804A, 0xB2E2, 0x8046, + 0xB2E3, 0x812F, 0xB2E4, 0x8116, 0xB2E5, 0x8123, 0xB2E6, 0x812B, 0xB2E7, 0x8129, 0xB2E8, 0x8130, 0xB2E9, 0x8124, 0xB2EA, 0x8202, + 0xB2EB, 0x8235, 0xB2EC, 0x8237, 0xB2ED, 0x8236, 0xB2EE, 0x8239, 0xB2EF, 0x838E, 0xB2F0, 0x839E, 0xB2F1, 0x8398, 0xB2F2, 0x8378, + 0xB2F3, 0x83A2, 0xB2F4, 0x8396, 0xB2F5, 0x83BD, 0xB2F6, 0x83AB, 0xB2F7, 0x8392, 0xB2F8, 0x838A, 0xB2F9, 0x8393, 0xB2FA, 0x8389, + 0xB2FB, 0x83A0, 0xB2FC, 0x8377, 0xB2FD, 0x837B, 0xB2FE, 0x837C, 0xB340, 0x8386, 0xB341, 0x83A7, 0xB342, 0x8655, 0xB343, 0x5F6A, + 0xB344, 0x86C7, 0xB345, 0x86C0, 0xB346, 0x86B6, 0xB347, 0x86C4, 0xB348, 0x86B5, 0xB349, 0x86C6, 0xB34A, 0x86CB, 0xB34B, 0x86B1, + 0xB34C, 0x86AF, 0xB34D, 0x86C9, 0xB34E, 0x8853, 0xB34F, 0x889E, 0xB350, 0x8888, 0xB351, 0x88AB, 0xB352, 0x8892, 0xB353, 0x8896, + 0xB354, 0x888D, 0xB355, 0x888B, 0xB356, 0x8993, 0xB357, 0x898F, 0xB358, 0x8A2A, 0xB359, 0x8A1D, 0xB35A, 0x8A23, 0xB35B, 0x8A25, + 0xB35C, 0x8A31, 0xB35D, 0x8A2D, 0xB35E, 0x8A1F, 0xB35F, 0x8A1B, 0xB360, 0x8A22, 0xB361, 0x8C49, 0xB362, 0x8C5A, 0xB363, 0x8CA9, + 0xB364, 0x8CAC, 0xB365, 0x8CAB, 0xB366, 0x8CA8, 0xB367, 0x8CAA, 0xB368, 0x8CA7, 0xB369, 0x8D67, 0xB36A, 0x8D66, 0xB36B, 0x8DBE, + 0xB36C, 0x8DBA, 0xB36D, 0x8EDB, 0xB36E, 0x8EDF, 0xB36F, 0x9019, 0xB370, 0x900D, 0xB371, 0x901A, 0xB372, 0x9017, 0xB373, 0x9023, + 0xB374, 0x901F, 0xB375, 0x901D, 0xB376, 0x9010, 0xB377, 0x9015, 0xB378, 0x901E, 0xB379, 0x9020, 0xB37A, 0x900F, 0xB37B, 0x9022, + 0xB37C, 0x9016, 0xB37D, 0x901B, 0xB37E, 0x9014, 0xB3A1, 0x90E8, 0xB3A2, 0x90ED, 0xB3A3, 0x90FD, 0xB3A4, 0x9157, 0xB3A5, 0x91CE, + 0xB3A6, 0x91F5, 0xB3A7, 0x91E6, 0xB3A8, 0x91E3, 0xB3A9, 0x91E7, 0xB3AA, 0x91ED, 0xB3AB, 0x91E9, 0xB3AC, 0x9589, 0xB3AD, 0x966A, + 0xB3AE, 0x9675, 0xB3AF, 0x9673, 0xB3B0, 0x9678, 0xB3B1, 0x9670, 0xB3B2, 0x9674, 0xB3B3, 0x9676, 0xB3B4, 0x9677, 0xB3B5, 0x966C, + 0xB3B6, 0x96C0, 0xB3B7, 0x96EA, 0xB3B8, 0x96E9, 0xB3B9, 0x7AE0, 0xB3BA, 0x7ADF, 0xB3BB, 0x9802, 0xB3BC, 0x9803, 0xB3BD, 0x9B5A, + 0xB3BE, 0x9CE5, 0xB3BF, 0x9E75, 0xB3C0, 0x9E7F, 0xB3C1, 0x9EA5, 0xB3C2, 0x9EBB, 0xB3C3, 0x50A2, 0xB3C4, 0x508D, 0xB3C5, 0x5085, + 0xB3C6, 0x5099, 0xB3C7, 0x5091, 0xB3C8, 0x5080, 0xB3C9, 0x5096, 0xB3CA, 0x5098, 0xB3CB, 0x509A, 0xB3CC, 0x6700, 0xB3CD, 0x51F1, + 0xB3CE, 0x5272, 0xB3CF, 0x5274, 0xB3D0, 0x5275, 0xB3D1, 0x5269, 0xB3D2, 0x52DE, 0xB3D3, 0x52DD, 0xB3D4, 0x52DB, 0xB3D5, 0x535A, + 0xB3D6, 0x53A5, 0xB3D7, 0x557B, 0xB3D8, 0x5580, 0xB3D9, 0x55A7, 0xB3DA, 0x557C, 0xB3DB, 0x558A, 0xB3DC, 0x559D, 0xB3DD, 0x5598, + 0xB3DE, 0x5582, 0xB3DF, 0x559C, 0xB3E0, 0x55AA, 0xB3E1, 0x5594, 0xB3E2, 0x5587, 0xB3E3, 0x558B, 0xB3E4, 0x5583, 0xB3E5, 0x55B3, + 0xB3E6, 0x55AE, 0xB3E7, 0x559F, 0xB3E8, 0x553E, 0xB3E9, 0x55B2, 0xB3EA, 0x559A, 0xB3EB, 0x55BB, 0xB3EC, 0x55AC, 0xB3ED, 0x55B1, + 0xB3EE, 0x557E, 0xB3EF, 0x5589, 0xB3F0, 0x55AB, 0xB3F1, 0x5599, 0xB3F2, 0x570D, 0xB3F3, 0x582F, 0xB3F4, 0x582A, 0xB3F5, 0x5834, + 0xB3F6, 0x5824, 0xB3F7, 0x5830, 0xB3F8, 0x5831, 0xB3F9, 0x5821, 0xB3FA, 0x581D, 0xB3FB, 0x5820, 0xB3FC, 0x58F9, 0xB3FD, 0x58FA, + 0xB3FE, 0x5960, 0xB440, 0x5A77, 0xB441, 0x5A9A, 0xB442, 0x5A7F, 0xB443, 0x5A92, 0xB444, 0x5A9B, 0xB445, 0x5AA7, 0xB446, 0x5B73, + 0xB447, 0x5B71, 0xB448, 0x5BD2, 0xB449, 0x5BCC, 0xB44A, 0x5BD3, 0xB44B, 0x5BD0, 0xB44C, 0x5C0A, 0xB44D, 0x5C0B, 0xB44E, 0x5C31, + 0xB44F, 0x5D4C, 0xB450, 0x5D50, 0xB451, 0x5D34, 0xB452, 0x5D47, 0xB453, 0x5DFD, 0xB454, 0x5E45, 0xB455, 0x5E3D, 0xB456, 0x5E40, + 0xB457, 0x5E43, 0xB458, 0x5E7E, 0xB459, 0x5ECA, 0xB45A, 0x5EC1, 0xB45B, 0x5EC2, 0xB45C, 0x5EC4, 0xB45D, 0x5F3C, 0xB45E, 0x5F6D, + 0xB45F, 0x5FA9, 0xB460, 0x5FAA, 0xB461, 0x5FA8, 0xB462, 0x60D1, 0xB463, 0x60E1, 0xB464, 0x60B2, 0xB465, 0x60B6, 0xB466, 0x60E0, + 0xB467, 0x611C, 0xB468, 0x6123, 0xB469, 0x60FA, 0xB46A, 0x6115, 0xB46B, 0x60F0, 0xB46C, 0x60FB, 0xB46D, 0x60F4, 0xB46E, 0x6168, + 0xB46F, 0x60F1, 0xB470, 0x610E, 0xB471, 0x60F6, 0xB472, 0x6109, 0xB473, 0x6100, 0xB474, 0x6112, 0xB475, 0x621F, 0xB476, 0x6249, + 0xB477, 0x63A3, 0xB478, 0x638C, 0xB479, 0x63CF, 0xB47A, 0x63C0, 0xB47B, 0x63E9, 0xB47C, 0x63C9, 0xB47D, 0x63C6, 0xB47E, 0x63CD, + 0xB4A1, 0x63D2, 0xB4A2, 0x63E3, 0xB4A3, 0x63D0, 0xB4A4, 0x63E1, 0xB4A5, 0x63D6, 0xB4A6, 0x63ED, 0xB4A7, 0x63EE, 0xB4A8, 0x6376, + 0xB4A9, 0x63F4, 0xB4AA, 0x63EA, 0xB4AB, 0x63DB, 0xB4AC, 0x6452, 0xB4AD, 0x63DA, 0xB4AE, 0x63F9, 0xB4AF, 0x655E, 0xB4B0, 0x6566, + 0xB4B1, 0x6562, 0xB4B2, 0x6563, 0xB4B3, 0x6591, 0xB4B4, 0x6590, 0xB4B5, 0x65AF, 0xB4B6, 0x666E, 0xB4B7, 0x6670, 0xB4B8, 0x6674, + 0xB4B9, 0x6676, 0xB4BA, 0x666F, 0xB4BB, 0x6691, 0xB4BC, 0x667A, 0xB4BD, 0x667E, 0xB4BE, 0x6677, 0xB4BF, 0x66FE, 0xB4C0, 0x66FF, + 0xB4C1, 0x671F, 0xB4C2, 0x671D, 0xB4C3, 0x68FA, 0xB4C4, 0x68D5, 0xB4C5, 0x68E0, 0xB4C6, 0x68D8, 0xB4C7, 0x68D7, 0xB4C8, 0x6905, + 0xB4C9, 0x68DF, 0xB4CA, 0x68F5, 0xB4CB, 0x68EE, 0xB4CC, 0x68E7, 0xB4CD, 0x68F9, 0xB4CE, 0x68D2, 0xB4CF, 0x68F2, 0xB4D0, 0x68E3, + 0xB4D1, 0x68CB, 0xB4D2, 0x68CD, 0xB4D3, 0x690D, 0xB4D4, 0x6912, 0xB4D5, 0x690E, 0xB4D6, 0x68C9, 0xB4D7, 0x68DA, 0xB4D8, 0x696E, + 0xB4D9, 0x68FB, 0xB4DA, 0x6B3E, 0xB4DB, 0x6B3A, 0xB4DC, 0x6B3D, 0xB4DD, 0x6B98, 0xB4DE, 0x6B96, 0xB4DF, 0x6BBC, 0xB4E0, 0x6BEF, + 0xB4E1, 0x6C2E, 0xB4E2, 0x6C2F, 0xB4E3, 0x6C2C, 0xB4E4, 0x6E2F, 0xB4E5, 0x6E38, 0xB4E6, 0x6E54, 0xB4E7, 0x6E21, 0xB4E8, 0x6E32, + 0xB4E9, 0x6E67, 0xB4EA, 0x6E4A, 0xB4EB, 0x6E20, 0xB4EC, 0x6E25, 0xB4ED, 0x6E23, 0xB4EE, 0x6E1B, 0xB4EF, 0x6E5B, 0xB4F0, 0x6E58, + 0xB4F1, 0x6E24, 0xB4F2, 0x6E56, 0xB4F3, 0x6E6E, 0xB4F4, 0x6E2D, 0xB4F5, 0x6E26, 0xB4F6, 0x6E6F, 0xB4F7, 0x6E34, 0xB4F8, 0x6E4D, + 0xB4F9, 0x6E3A, 0xB4FA, 0x6E2C, 0xB4FB, 0x6E43, 0xB4FC, 0x6E1D, 0xB4FD, 0x6E3E, 0xB4FE, 0x6ECB, 0xB540, 0x6E89, 0xB541, 0x6E19, + 0xB542, 0x6E4E, 0xB543, 0x6E63, 0xB544, 0x6E44, 0xB545, 0x6E72, 0xB546, 0x6E69, 0xB547, 0x6E5F, 0xB548, 0x7119, 0xB549, 0x711A, + 0xB54A, 0x7126, 0xB54B, 0x7130, 0xB54C, 0x7121, 0xB54D, 0x7136, 0xB54E, 0x716E, 0xB54F, 0x711C, 0xB550, 0x724C, 0xB551, 0x7284, + 0xB552, 0x7280, 0xB553, 0x7336, 0xB554, 0x7325, 0xB555, 0x7334, 0xB556, 0x7329, 0xB557, 0x743A, 0xB558, 0x742A, 0xB559, 0x7433, + 0xB55A, 0x7422, 0xB55B, 0x7425, 0xB55C, 0x7435, 0xB55D, 0x7436, 0xB55E, 0x7434, 0xB55F, 0x742F, 0xB560, 0x741B, 0xB561, 0x7426, + 0xB562, 0x7428, 0xB563, 0x7525, 0xB564, 0x7526, 0xB565, 0x756B, 0xB566, 0x756A, 0xB567, 0x75E2, 0xB568, 0x75DB, 0xB569, 0x75E3, + 0xB56A, 0x75D9, 0xB56B, 0x75D8, 0xB56C, 0x75DE, 0xB56D, 0x75E0, 0xB56E, 0x767B, 0xB56F, 0x767C, 0xB570, 0x7696, 0xB571, 0x7693, + 0xB572, 0x76B4, 0xB573, 0x76DC, 0xB574, 0x774F, 0xB575, 0x77ED, 0xB576, 0x785D, 0xB577, 0x786C, 0xB578, 0x786F, 0xB579, 0x7A0D, + 0xB57A, 0x7A08, 0xB57B, 0x7A0B, 0xB57C, 0x7A05, 0xB57D, 0x7A00, 0xB57E, 0x7A98, 0xB5A1, 0x7A97, 0xB5A2, 0x7A96, 0xB5A3, 0x7AE5, + 0xB5A4, 0x7AE3, 0xB5A5, 0x7B49, 0xB5A6, 0x7B56, 0xB5A7, 0x7B46, 0xB5A8, 0x7B50, 0xB5A9, 0x7B52, 0xB5AA, 0x7B54, 0xB5AB, 0x7B4D, + 0xB5AC, 0x7B4B, 0xB5AD, 0x7B4F, 0xB5AE, 0x7B51, 0xB5AF, 0x7C9F, 0xB5B0, 0x7CA5, 0xB5B1, 0x7D5E, 0xB5B2, 0x7D50, 0xB5B3, 0x7D68, + 0xB5B4, 0x7D55, 0xB5B5, 0x7D2B, 0xB5B6, 0x7D6E, 0xB5B7, 0x7D72, 0xB5B8, 0x7D61, 0xB5B9, 0x7D66, 0xB5BA, 0x7D62, 0xB5BB, 0x7D70, + 0xB5BC, 0x7D73, 0xB5BD, 0x5584, 0xB5BE, 0x7FD4, 0xB5BF, 0x7FD5, 0xB5C0, 0x800B, 0xB5C1, 0x8052, 0xB5C2, 0x8085, 0xB5C3, 0x8155, + 0xB5C4, 0x8154, 0xB5C5, 0x814B, 0xB5C6, 0x8151, 0xB5C7, 0x814E, 0xB5C8, 0x8139, 0xB5C9, 0x8146, 0xB5CA, 0x813E, 0xB5CB, 0x814C, + 0xB5CC, 0x8153, 0xB5CD, 0x8174, 0xB5CE, 0x8212, 0xB5CF, 0x821C, 0xB5D0, 0x83E9, 0xB5D1, 0x8403, 0xB5D2, 0x83F8, 0xB5D3, 0x840D, + 0xB5D4, 0x83E0, 0xB5D5, 0x83C5, 0xB5D6, 0x840B, 0xB5D7, 0x83C1, 0xB5D8, 0x83EF, 0xB5D9, 0x83F1, 0xB5DA, 0x83F4, 0xB5DB, 0x8457, + 0xB5DC, 0x840A, 0xB5DD, 0x83F0, 0xB5DE, 0x840C, 0xB5DF, 0x83CC, 0xB5E0, 0x83FD, 0xB5E1, 0x83F2, 0xB5E2, 0x83CA, 0xB5E3, 0x8438, + 0xB5E4, 0x840E, 0xB5E5, 0x8404, 0xB5E6, 0x83DC, 0xB5E7, 0x8407, 0xB5E8, 0x83D4, 0xB5E9, 0x83DF, 0xB5EA, 0x865B, 0xB5EB, 0x86DF, + 0xB5EC, 0x86D9, 0xB5ED, 0x86ED, 0xB5EE, 0x86D4, 0xB5EF, 0x86DB, 0xB5F0, 0x86E4, 0xB5F1, 0x86D0, 0xB5F2, 0x86DE, 0xB5F3, 0x8857, + 0xB5F4, 0x88C1, 0xB5F5, 0x88C2, 0xB5F6, 0x88B1, 0xB5F7, 0x8983, 0xB5F8, 0x8996, 0xB5F9, 0x8A3B, 0xB5FA, 0x8A60, 0xB5FB, 0x8A55, + 0xB5FC, 0x8A5E, 0xB5FD, 0x8A3C, 0xB5FE, 0x8A41, 0xB640, 0x8A54, 0xB641, 0x8A5B, 0xB642, 0x8A50, 0xB643, 0x8A46, 0xB644, 0x8A34, + 0xB645, 0x8A3A, 0xB646, 0x8A36, 0xB647, 0x8A56, 0xB648, 0x8C61, 0xB649, 0x8C82, 0xB64A, 0x8CAF, 0xB64B, 0x8CBC, 0xB64C, 0x8CB3, + 0xB64D, 0x8CBD, 0xB64E, 0x8CC1, 0xB64F, 0x8CBB, 0xB650, 0x8CC0, 0xB651, 0x8CB4, 0xB652, 0x8CB7, 0xB653, 0x8CB6, 0xB654, 0x8CBF, + 0xB655, 0x8CB8, 0xB656, 0x8D8A, 0xB657, 0x8D85, 0xB658, 0x8D81, 0xB659, 0x8DCE, 0xB65A, 0x8DDD, 0xB65B, 0x8DCB, 0xB65C, 0x8DDA, + 0xB65D, 0x8DD1, 0xB65E, 0x8DCC, 0xB65F, 0x8DDB, 0xB660, 0x8DC6, 0xB661, 0x8EFB, 0xB662, 0x8EF8, 0xB663, 0x8EFC, 0xB664, 0x8F9C, + 0xB665, 0x902E, 0xB666, 0x9035, 0xB667, 0x9031, 0xB668, 0x9038, 0xB669, 0x9032, 0xB66A, 0x9036, 0xB66B, 0x9102, 0xB66C, 0x90F5, + 0xB66D, 0x9109, 0xB66E, 0x90FE, 0xB66F, 0x9163, 0xB670, 0x9165, 0xB671, 0x91CF, 0xB672, 0x9214, 0xB673, 0x9215, 0xB674, 0x9223, + 0xB675, 0x9209, 0xB676, 0x921E, 0xB677, 0x920D, 0xB678, 0x9210, 0xB679, 0x9207, 0xB67A, 0x9211, 0xB67B, 0x9594, 0xB67C, 0x958F, + 0xB67D, 0x958B, 0xB67E, 0x9591, 0xB6A1, 0x9593, 0xB6A2, 0x9592, 0xB6A3, 0x958E, 0xB6A4, 0x968A, 0xB6A5, 0x968E, 0xB6A6, 0x968B, + 0xB6A7, 0x967D, 0xB6A8, 0x9685, 0xB6A9, 0x9686, 0xB6AA, 0x968D, 0xB6AB, 0x9672, 0xB6AC, 0x9684, 0xB6AD, 0x96C1, 0xB6AE, 0x96C5, + 0xB6AF, 0x96C4, 0xB6B0, 0x96C6, 0xB6B1, 0x96C7, 0xB6B2, 0x96EF, 0xB6B3, 0x96F2, 0xB6B4, 0x97CC, 0xB6B5, 0x9805, 0xB6B6, 0x9806, + 0xB6B7, 0x9808, 0xB6B8, 0x98E7, 0xB6B9, 0x98EA, 0xB6BA, 0x98EF, 0xB6BB, 0x98E9, 0xB6BC, 0x98F2, 0xB6BD, 0x98ED, 0xB6BE, 0x99AE, + 0xB6BF, 0x99AD, 0xB6C0, 0x9EC3, 0xB6C1, 0x9ECD, 0xB6C2, 0x9ED1, 0xB6C3, 0x4E82, 0xB6C4, 0x50AD, 0xB6C5, 0x50B5, 0xB6C6, 0x50B2, + 0xB6C7, 0x50B3, 0xB6C8, 0x50C5, 0xB6C9, 0x50BE, 0xB6CA, 0x50AC, 0xB6CB, 0x50B7, 0xB6CC, 0x50BB, 0xB6CD, 0x50AF, 0xB6CE, 0x50C7, + 0xB6CF, 0x527F, 0xB6D0, 0x5277, 0xB6D1, 0x527D, 0xB6D2, 0x52DF, 0xB6D3, 0x52E6, 0xB6D4, 0x52E4, 0xB6D5, 0x52E2, 0xB6D6, 0x52E3, + 0xB6D7, 0x532F, 0xB6D8, 0x55DF, 0xB6D9, 0x55E8, 0xB6DA, 0x55D3, 0xB6DB, 0x55E6, 0xB6DC, 0x55CE, 0xB6DD, 0x55DC, 0xB6DE, 0x55C7, + 0xB6DF, 0x55D1, 0xB6E0, 0x55E3, 0xB6E1, 0x55E4, 0xB6E2, 0x55EF, 0xB6E3, 0x55DA, 0xB6E4, 0x55E1, 0xB6E5, 0x55C5, 0xB6E6, 0x55C6, + 0xB6E7, 0x55E5, 0xB6E8, 0x55C9, 0xB6E9, 0x5712, 0xB6EA, 0x5713, 0xB6EB, 0x585E, 0xB6EC, 0x5851, 0xB6ED, 0x5858, 0xB6EE, 0x5857, + 0xB6EF, 0x585A, 0xB6F0, 0x5854, 0xB6F1, 0x586B, 0xB6F2, 0x584C, 0xB6F3, 0x586D, 0xB6F4, 0x584A, 0xB6F5, 0x5862, 0xB6F6, 0x5852, + 0xB6F7, 0x584B, 0xB6F8, 0x5967, 0xB6F9, 0x5AC1, 0xB6FA, 0x5AC9, 0xB6FB, 0x5ACC, 0xB6FC, 0x5ABE, 0xB6FD, 0x5ABD, 0xB6FE, 0x5ABC, + 0xB740, 0x5AB3, 0xB741, 0x5AC2, 0xB742, 0x5AB2, 0xB743, 0x5D69, 0xB744, 0x5D6F, 0xB745, 0x5E4C, 0xB746, 0x5E79, 0xB747, 0x5EC9, + 0xB748, 0x5EC8, 0xB749, 0x5F12, 0xB74A, 0x5F59, 0xB74B, 0x5FAC, 0xB74C, 0x5FAE, 0xB74D, 0x611A, 0xB74E, 0x610F, 0xB74F, 0x6148, + 0xB750, 0x611F, 0xB751, 0x60F3, 0xB752, 0x611B, 0xB753, 0x60F9, 0xB754, 0x6101, 0xB755, 0x6108, 0xB756, 0x614E, 0xB757, 0x614C, + 0xB758, 0x6144, 0xB759, 0x614D, 0xB75A, 0x613E, 0xB75B, 0x6134, 0xB75C, 0x6127, 0xB75D, 0x610D, 0xB75E, 0x6106, 0xB75F, 0x6137, + 0xB760, 0x6221, 0xB761, 0x6222, 0xB762, 0x6413, 0xB763, 0x643E, 0xB764, 0x641E, 0xB765, 0x642A, 0xB766, 0x642D, 0xB767, 0x643D, + 0xB768, 0x642C, 0xB769, 0x640F, 0xB76A, 0x641C, 0xB76B, 0x6414, 0xB76C, 0x640D, 0xB76D, 0x6436, 0xB76E, 0x6416, 0xB76F, 0x6417, + 0xB770, 0x6406, 0xB771, 0x656C, 0xB772, 0x659F, 0xB773, 0x65B0, 0xB774, 0x6697, 0xB775, 0x6689, 0xB776, 0x6687, 0xB777, 0x6688, + 0xB778, 0x6696, 0xB779, 0x6684, 0xB77A, 0x6698, 0xB77B, 0x668D, 0xB77C, 0x6703, 0xB77D, 0x6994, 0xB77E, 0x696D, 0xB7A1, 0x695A, + 0xB7A2, 0x6977, 0xB7A3, 0x6960, 0xB7A4, 0x6954, 0xB7A5, 0x6975, 0xB7A6, 0x6930, 0xB7A7, 0x6982, 0xB7A8, 0x694A, 0xB7A9, 0x6968, + 0xB7AA, 0x696B, 0xB7AB, 0x695E, 0xB7AC, 0x6953, 0xB7AD, 0x6979, 0xB7AE, 0x6986, 0xB7AF, 0x695D, 0xB7B0, 0x6963, 0xB7B1, 0x695B, + 0xB7B2, 0x6B47, 0xB7B3, 0x6B72, 0xB7B4, 0x6BC0, 0xB7B5, 0x6BBF, 0xB7B6, 0x6BD3, 0xB7B7, 0x6BFD, 0xB7B8, 0x6EA2, 0xB7B9, 0x6EAF, + 0xB7BA, 0x6ED3, 0xB7BB, 0x6EB6, 0xB7BC, 0x6EC2, 0xB7BD, 0x6E90, 0xB7BE, 0x6E9D, 0xB7BF, 0x6EC7, 0xB7C0, 0x6EC5, 0xB7C1, 0x6EA5, + 0xB7C2, 0x6E98, 0xB7C3, 0x6EBC, 0xB7C4, 0x6EBA, 0xB7C5, 0x6EAB, 0xB7C6, 0x6ED1, 0xB7C7, 0x6E96, 0xB7C8, 0x6E9C, 0xB7C9, 0x6EC4, + 0xB7CA, 0x6ED4, 0xB7CB, 0x6EAA, 0xB7CC, 0x6EA7, 0xB7CD, 0x6EB4, 0xB7CE, 0x714E, 0xB7CF, 0x7159, 0xB7D0, 0x7169, 0xB7D1, 0x7164, + 0xB7D2, 0x7149, 0xB7D3, 0x7167, 0xB7D4, 0x715C, 0xB7D5, 0x716C, 0xB7D6, 0x7166, 0xB7D7, 0x714C, 0xB7D8, 0x7165, 0xB7D9, 0x715E, + 0xB7DA, 0x7146, 0xB7DB, 0x7168, 0xB7DC, 0x7156, 0xB7DD, 0x723A, 0xB7DE, 0x7252, 0xB7DF, 0x7337, 0xB7E0, 0x7345, 0xB7E1, 0x733F, + 0xB7E2, 0x733E, 0xB7E3, 0x746F, 0xB7E4, 0x745A, 0xB7E5, 0x7455, 0xB7E6, 0x745F, 0xB7E7, 0x745E, 0xB7E8, 0x7441, 0xB7E9, 0x743F, + 0xB7EA, 0x7459, 0xB7EB, 0x745B, 0xB7EC, 0x745C, 0xB7ED, 0x7576, 0xB7EE, 0x7578, 0xB7EF, 0x7600, 0xB7F0, 0x75F0, 0xB7F1, 0x7601, + 0xB7F2, 0x75F2, 0xB7F3, 0x75F1, 0xB7F4, 0x75FA, 0xB7F5, 0x75FF, 0xB7F6, 0x75F4, 0xB7F7, 0x75F3, 0xB7F8, 0x76DE, 0xB7F9, 0x76DF, + 0xB7FA, 0x775B, 0xB7FB, 0x776B, 0xB7FC, 0x7766, 0xB7FD, 0x775E, 0xB7FE, 0x7763, 0xB840, 0x7779, 0xB841, 0x776A, 0xB842, 0x776C, + 0xB843, 0x775C, 0xB844, 0x7765, 0xB845, 0x7768, 0xB846, 0x7762, 0xB847, 0x77EE, 0xB848, 0x788E, 0xB849, 0x78B0, 0xB84A, 0x7897, + 0xB84B, 0x7898, 0xB84C, 0x788C, 0xB84D, 0x7889, 0xB84E, 0x787C, 0xB84F, 0x7891, 0xB850, 0x7893, 0xB851, 0x787F, 0xB852, 0x797A, + 0xB853, 0x797F, 0xB854, 0x7981, 0xB855, 0x842C, 0xB856, 0x79BD, 0xB857, 0x7A1C, 0xB858, 0x7A1A, 0xB859, 0x7A20, 0xB85A, 0x7A14, + 0xB85B, 0x7A1F, 0xB85C, 0x7A1E, 0xB85D, 0x7A9F, 0xB85E, 0x7AA0, 0xB85F, 0x7B77, 0xB860, 0x7BC0, 0xB861, 0x7B60, 0xB862, 0x7B6E, + 0xB863, 0x7B67, 0xB864, 0x7CB1, 0xB865, 0x7CB3, 0xB866, 0x7CB5, 0xB867, 0x7D93, 0xB868, 0x7D79, 0xB869, 0x7D91, 0xB86A, 0x7D81, + 0xB86B, 0x7D8F, 0xB86C, 0x7D5B, 0xB86D, 0x7F6E, 0xB86E, 0x7F69, 0xB86F, 0x7F6A, 0xB870, 0x7F72, 0xB871, 0x7FA9, 0xB872, 0x7FA8, + 0xB873, 0x7FA4, 0xB874, 0x8056, 0xB875, 0x8058, 0xB876, 0x8086, 0xB877, 0x8084, 0xB878, 0x8171, 0xB879, 0x8170, 0xB87A, 0x8178, + 0xB87B, 0x8165, 0xB87C, 0x816E, 0xB87D, 0x8173, 0xB87E, 0x816B, 0xB8A1, 0x8179, 0xB8A2, 0x817A, 0xB8A3, 0x8166, 0xB8A4, 0x8205, + 0xB8A5, 0x8247, 0xB8A6, 0x8482, 0xB8A7, 0x8477, 0xB8A8, 0x843D, 0xB8A9, 0x8431, 0xB8AA, 0x8475, 0xB8AB, 0x8466, 0xB8AC, 0x846B, + 0xB8AD, 0x8449, 0xB8AE, 0x846C, 0xB8AF, 0x845B, 0xB8B0, 0x843C, 0xB8B1, 0x8435, 0xB8B2, 0x8461, 0xB8B3, 0x8463, 0xB8B4, 0x8469, + 0xB8B5, 0x846D, 0xB8B6, 0x8446, 0xB8B7, 0x865E, 0xB8B8, 0x865C, 0xB8B9, 0x865F, 0xB8BA, 0x86F9, 0xB8BB, 0x8713, 0xB8BC, 0x8708, + 0xB8BD, 0x8707, 0xB8BE, 0x8700, 0xB8BF, 0x86FE, 0xB8C0, 0x86FB, 0xB8C1, 0x8702, 0xB8C2, 0x8703, 0xB8C3, 0x8706, 0xB8C4, 0x870A, + 0xB8C5, 0x8859, 0xB8C6, 0x88DF, 0xB8C7, 0x88D4, 0xB8C8, 0x88D9, 0xB8C9, 0x88DC, 0xB8CA, 0x88D8, 0xB8CB, 0x88DD, 0xB8CC, 0x88E1, + 0xB8CD, 0x88CA, 0xB8CE, 0x88D5, 0xB8CF, 0x88D2, 0xB8D0, 0x899C, 0xB8D1, 0x89E3, 0xB8D2, 0x8A6B, 0xB8D3, 0x8A72, 0xB8D4, 0x8A73, + 0xB8D5, 0x8A66, 0xB8D6, 0x8A69, 0xB8D7, 0x8A70, 0xB8D8, 0x8A87, 0xB8D9, 0x8A7C, 0xB8DA, 0x8A63, 0xB8DB, 0x8AA0, 0xB8DC, 0x8A71, + 0xB8DD, 0x8A85, 0xB8DE, 0x8A6D, 0xB8DF, 0x8A62, 0xB8E0, 0x8A6E, 0xB8E1, 0x8A6C, 0xB8E2, 0x8A79, 0xB8E3, 0x8A7B, 0xB8E4, 0x8A3E, + 0xB8E5, 0x8A68, 0xB8E6, 0x8C62, 0xB8E7, 0x8C8A, 0xB8E8, 0x8C89, 0xB8E9, 0x8CCA, 0xB8EA, 0x8CC7, 0xB8EB, 0x8CC8, 0xB8EC, 0x8CC4, + 0xB8ED, 0x8CB2, 0xB8EE, 0x8CC3, 0xB8EF, 0x8CC2, 0xB8F0, 0x8CC5, 0xB8F1, 0x8DE1, 0xB8F2, 0x8DDF, 0xB8F3, 0x8DE8, 0xB8F4, 0x8DEF, + 0xB8F5, 0x8DF3, 0xB8F6, 0x8DFA, 0xB8F7, 0x8DEA, 0xB8F8, 0x8DE4, 0xB8F9, 0x8DE6, 0xB8FA, 0x8EB2, 0xB8FB, 0x8F03, 0xB8FC, 0x8F09, + 0xB8FD, 0x8EFE, 0xB8FE, 0x8F0A, 0xB940, 0x8F9F, 0xB941, 0x8FB2, 0xB942, 0x904B, 0xB943, 0x904A, 0xB944, 0x9053, 0xB945, 0x9042, + 0xB946, 0x9054, 0xB947, 0x903C, 0xB948, 0x9055, 0xB949, 0x9050, 0xB94A, 0x9047, 0xB94B, 0x904F, 0xB94C, 0x904E, 0xB94D, 0x904D, + 0xB94E, 0x9051, 0xB94F, 0x903E, 0xB950, 0x9041, 0xB951, 0x9112, 0xB952, 0x9117, 0xB953, 0x916C, 0xB954, 0x916A, 0xB955, 0x9169, + 0xB956, 0x91C9, 0xB957, 0x9237, 0xB958, 0x9257, 0xB959, 0x9238, 0xB95A, 0x923D, 0xB95B, 0x9240, 0xB95C, 0x923E, 0xB95D, 0x925B, + 0xB95E, 0x924B, 0xB95F, 0x9264, 0xB960, 0x9251, 0xB961, 0x9234, 0xB962, 0x9249, 0xB963, 0x924D, 0xB964, 0x9245, 0xB965, 0x9239, + 0xB966, 0x923F, 0xB967, 0x925A, 0xB968, 0x9598, 0xB969, 0x9698, 0xB96A, 0x9694, 0xB96B, 0x9695, 0xB96C, 0x96CD, 0xB96D, 0x96CB, + 0xB96E, 0x96C9, 0xB96F, 0x96CA, 0xB970, 0x96F7, 0xB971, 0x96FB, 0xB972, 0x96F9, 0xB973, 0x96F6, 0xB974, 0x9756, 0xB975, 0x9774, + 0xB976, 0x9776, 0xB977, 0x9810, 0xB978, 0x9811, 0xB979, 0x9813, 0xB97A, 0x980A, 0xB97B, 0x9812, 0xB97C, 0x980C, 0xB97D, 0x98FC, + 0xB97E, 0x98F4, 0xB9A1, 0x98FD, 0xB9A2, 0x98FE, 0xB9A3, 0x99B3, 0xB9A4, 0x99B1, 0xB9A5, 0x99B4, 0xB9A6, 0x9AE1, 0xB9A7, 0x9CE9, + 0xB9A8, 0x9E82, 0xB9A9, 0x9F0E, 0xB9AA, 0x9F13, 0xB9AB, 0x9F20, 0xB9AC, 0x50E7, 0xB9AD, 0x50EE, 0xB9AE, 0x50E5, 0xB9AF, 0x50D6, + 0xB9B0, 0x50ED, 0xB9B1, 0x50DA, 0xB9B2, 0x50D5, 0xB9B3, 0x50CF, 0xB9B4, 0x50D1, 0xB9B5, 0x50F1, 0xB9B6, 0x50CE, 0xB9B7, 0x50E9, + 0xB9B8, 0x5162, 0xB9B9, 0x51F3, 0xB9BA, 0x5283, 0xB9BB, 0x5282, 0xB9BC, 0x5331, 0xB9BD, 0x53AD, 0xB9BE, 0x55FE, 0xB9BF, 0x5600, + 0xB9C0, 0x561B, 0xB9C1, 0x5617, 0xB9C2, 0x55FD, 0xB9C3, 0x5614, 0xB9C4, 0x5606, 0xB9C5, 0x5609, 0xB9C6, 0x560D, 0xB9C7, 0x560E, + 0xB9C8, 0x55F7, 0xB9C9, 0x5616, 0xB9CA, 0x561F, 0xB9CB, 0x5608, 0xB9CC, 0x5610, 0xB9CD, 0x55F6, 0xB9CE, 0x5718, 0xB9CF, 0x5716, + 0xB9D0, 0x5875, 0xB9D1, 0x587E, 0xB9D2, 0x5883, 0xB9D3, 0x5893, 0xB9D4, 0x588A, 0xB9D5, 0x5879, 0xB9D6, 0x5885, 0xB9D7, 0x587D, + 0xB9D8, 0x58FD, 0xB9D9, 0x5925, 0xB9DA, 0x5922, 0xB9DB, 0x5924, 0xB9DC, 0x596A, 0xB9DD, 0x5969, 0xB9DE, 0x5AE1, 0xB9DF, 0x5AE6, + 0xB9E0, 0x5AE9, 0xB9E1, 0x5AD7, 0xB9E2, 0x5AD6, 0xB9E3, 0x5AD8, 0xB9E4, 0x5AE3, 0xB9E5, 0x5B75, 0xB9E6, 0x5BDE, 0xB9E7, 0x5BE7, + 0xB9E8, 0x5BE1, 0xB9E9, 0x5BE5, 0xB9EA, 0x5BE6, 0xB9EB, 0x5BE8, 0xB9EC, 0x5BE2, 0xB9ED, 0x5BE4, 0xB9EE, 0x5BDF, 0xB9EF, 0x5C0D, + 0xB9F0, 0x5C62, 0xB9F1, 0x5D84, 0xB9F2, 0x5D87, 0xB9F3, 0x5E5B, 0xB9F4, 0x5E63, 0xB9F5, 0x5E55, 0xB9F6, 0x5E57, 0xB9F7, 0x5E54, + 0xB9F8, 0x5ED3, 0xB9F9, 0x5ED6, 0xB9FA, 0x5F0A, 0xB9FB, 0x5F46, 0xB9FC, 0x5F70, 0xB9FD, 0x5FB9, 0xB9FE, 0x6147, 0xBA40, 0x613F, + 0xBA41, 0x614B, 0xBA42, 0x6177, 0xBA43, 0x6162, 0xBA44, 0x6163, 0xBA45, 0x615F, 0xBA46, 0x615A, 0xBA47, 0x6158, 0xBA48, 0x6175, + 0xBA49, 0x622A, 0xBA4A, 0x6487, 0xBA4B, 0x6458, 0xBA4C, 0x6454, 0xBA4D, 0x64A4, 0xBA4E, 0x6478, 0xBA4F, 0x645F, 0xBA50, 0x647A, + 0xBA51, 0x6451, 0xBA52, 0x6467, 0xBA53, 0x6434, 0xBA54, 0x646D, 0xBA55, 0x647B, 0xBA56, 0x6572, 0xBA57, 0x65A1, 0xBA58, 0x65D7, + 0xBA59, 0x65D6, 0xBA5A, 0x66A2, 0xBA5B, 0x66A8, 0xBA5C, 0x669D, 0xBA5D, 0x699C, 0xBA5E, 0x69A8, 0xBA5F, 0x6995, 0xBA60, 0x69C1, + 0xBA61, 0x69AE, 0xBA62, 0x69D3, 0xBA63, 0x69CB, 0xBA64, 0x699B, 0xBA65, 0x69B7, 0xBA66, 0x69BB, 0xBA67, 0x69AB, 0xBA68, 0x69B4, + 0xBA69, 0x69D0, 0xBA6A, 0x69CD, 0xBA6B, 0x69AD, 0xBA6C, 0x69CC, 0xBA6D, 0x69A6, 0xBA6E, 0x69C3, 0xBA6F, 0x69A3, 0xBA70, 0x6B49, + 0xBA71, 0x6B4C, 0xBA72, 0x6C33, 0xBA73, 0x6F33, 0xBA74, 0x6F14, 0xBA75, 0x6EFE, 0xBA76, 0x6F13, 0xBA77, 0x6EF4, 0xBA78, 0x6F29, + 0xBA79, 0x6F3E, 0xBA7A, 0x6F20, 0xBA7B, 0x6F2C, 0xBA7C, 0x6F0F, 0xBA7D, 0x6F02, 0xBA7E, 0x6F22, 0xBAA1, 0x6EFF, 0xBAA2, 0x6EEF, + 0xBAA3, 0x6F06, 0xBAA4, 0x6F31, 0xBAA5, 0x6F38, 0xBAA6, 0x6F32, 0xBAA7, 0x6F23, 0xBAA8, 0x6F15, 0xBAA9, 0x6F2B, 0xBAAA, 0x6F2F, + 0xBAAB, 0x6F88, 0xBAAC, 0x6F2A, 0xBAAD, 0x6EEC, 0xBAAE, 0x6F01, 0xBAAF, 0x6EF2, 0xBAB0, 0x6ECC, 0xBAB1, 0x6EF7, 0xBAB2, 0x7194, + 0xBAB3, 0x7199, 0xBAB4, 0x717D, 0xBAB5, 0x718A, 0xBAB6, 0x7184, 0xBAB7, 0x7192, 0xBAB8, 0x723E, 0xBAB9, 0x7292, 0xBABA, 0x7296, + 0xBABB, 0x7344, 0xBABC, 0x7350, 0xBABD, 0x7464, 0xBABE, 0x7463, 0xBABF, 0x746A, 0xBAC0, 0x7470, 0xBAC1, 0x746D, 0xBAC2, 0x7504, + 0xBAC3, 0x7591, 0xBAC4, 0x7627, 0xBAC5, 0x760D, 0xBAC6, 0x760B, 0xBAC7, 0x7609, 0xBAC8, 0x7613, 0xBAC9, 0x76E1, 0xBACA, 0x76E3, + 0xBACB, 0x7784, 0xBACC, 0x777D, 0xBACD, 0x777F, 0xBACE, 0x7761, 0xBACF, 0x78C1, 0xBAD0, 0x789F, 0xBAD1, 0x78A7, 0xBAD2, 0x78B3, + 0xBAD3, 0x78A9, 0xBAD4, 0x78A3, 0xBAD5, 0x798E, 0xBAD6, 0x798F, 0xBAD7, 0x798D, 0xBAD8, 0x7A2E, 0xBAD9, 0x7A31, 0xBADA, 0x7AAA, + 0xBADB, 0x7AA9, 0xBADC, 0x7AED, 0xBADD, 0x7AEF, 0xBADE, 0x7BA1, 0xBADF, 0x7B95, 0xBAE0, 0x7B8B, 0xBAE1, 0x7B75, 0xBAE2, 0x7B97, + 0xBAE3, 0x7B9D, 0xBAE4, 0x7B94, 0xBAE5, 0x7B8F, 0xBAE6, 0x7BB8, 0xBAE7, 0x7B87, 0xBAE8, 0x7B84, 0xBAE9, 0x7CB9, 0xBAEA, 0x7CBD, + 0xBAEB, 0x7CBE, 0xBAEC, 0x7DBB, 0xBAED, 0x7DB0, 0xBAEE, 0x7D9C, 0xBAEF, 0x7DBD, 0xBAF0, 0x7DBE, 0xBAF1, 0x7DA0, 0xBAF2, 0x7DCA, + 0xBAF3, 0x7DB4, 0xBAF4, 0x7DB2, 0xBAF5, 0x7DB1, 0xBAF6, 0x7DBA, 0xBAF7, 0x7DA2, 0xBAF8, 0x7DBF, 0xBAF9, 0x7DB5, 0xBAFA, 0x7DB8, + 0xBAFB, 0x7DAD, 0xBAFC, 0x7DD2, 0xBAFD, 0x7DC7, 0xBAFE, 0x7DAC, 0xBB40, 0x7F70, 0xBB41, 0x7FE0, 0xBB42, 0x7FE1, 0xBB43, 0x7FDF, + 0xBB44, 0x805E, 0xBB45, 0x805A, 0xBB46, 0x8087, 0xBB47, 0x8150, 0xBB48, 0x8180, 0xBB49, 0x818F, 0xBB4A, 0x8188, 0xBB4B, 0x818A, + 0xBB4C, 0x817F, 0xBB4D, 0x8182, 0xBB4E, 0x81E7, 0xBB4F, 0x81FA, 0xBB50, 0x8207, 0xBB51, 0x8214, 0xBB52, 0x821E, 0xBB53, 0x824B, + 0xBB54, 0x84C9, 0xBB55, 0x84BF, 0xBB56, 0x84C6, 0xBB57, 0x84C4, 0xBB58, 0x8499, 0xBB59, 0x849E, 0xBB5A, 0x84B2, 0xBB5B, 0x849C, + 0xBB5C, 0x84CB, 0xBB5D, 0x84B8, 0xBB5E, 0x84C0, 0xBB5F, 0x84D3, 0xBB60, 0x8490, 0xBB61, 0x84BC, 0xBB62, 0x84D1, 0xBB63, 0x84CA, + 0xBB64, 0x873F, 0xBB65, 0x871C, 0xBB66, 0x873B, 0xBB67, 0x8722, 0xBB68, 0x8725, 0xBB69, 0x8734, 0xBB6A, 0x8718, 0xBB6B, 0x8755, + 0xBB6C, 0x8737, 0xBB6D, 0x8729, 0xBB6E, 0x88F3, 0xBB6F, 0x8902, 0xBB70, 0x88F4, 0xBB71, 0x88F9, 0xBB72, 0x88F8, 0xBB73, 0x88FD, + 0xBB74, 0x88E8, 0xBB75, 0x891A, 0xBB76, 0x88EF, 0xBB77, 0x8AA6, 0xBB78, 0x8A8C, 0xBB79, 0x8A9E, 0xBB7A, 0x8AA3, 0xBB7B, 0x8A8D, + 0xBB7C, 0x8AA1, 0xBB7D, 0x8A93, 0xBB7E, 0x8AA4, 0xBBA1, 0x8AAA, 0xBBA2, 0x8AA5, 0xBBA3, 0x8AA8, 0xBBA4, 0x8A98, 0xBBA5, 0x8A91, + 0xBBA6, 0x8A9A, 0xBBA7, 0x8AA7, 0xBBA8, 0x8C6A, 0xBBA9, 0x8C8D, 0xBBAA, 0x8C8C, 0xBBAB, 0x8CD3, 0xBBAC, 0x8CD1, 0xBBAD, 0x8CD2, + 0xBBAE, 0x8D6B, 0xBBAF, 0x8D99, 0xBBB0, 0x8D95, 0xBBB1, 0x8DFC, 0xBBB2, 0x8F14, 0xBBB3, 0x8F12, 0xBBB4, 0x8F15, 0xBBB5, 0x8F13, + 0xBBB6, 0x8FA3, 0xBBB7, 0x9060, 0xBBB8, 0x9058, 0xBBB9, 0x905C, 0xBBBA, 0x9063, 0xBBBB, 0x9059, 0xBBBC, 0x905E, 0xBBBD, 0x9062, + 0xBBBE, 0x905D, 0xBBBF, 0x905B, 0xBBC0, 0x9119, 0xBBC1, 0x9118, 0xBBC2, 0x911E, 0xBBC3, 0x9175, 0xBBC4, 0x9178, 0xBBC5, 0x9177, + 0xBBC6, 0x9174, 0xBBC7, 0x9278, 0xBBC8, 0x9280, 0xBBC9, 0x9285, 0xBBCA, 0x9298, 0xBBCB, 0x9296, 0xBBCC, 0x927B, 0xBBCD, 0x9293, + 0xBBCE, 0x929C, 0xBBCF, 0x92A8, 0xBBD0, 0x927C, 0xBBD1, 0x9291, 0xBBD2, 0x95A1, 0xBBD3, 0x95A8, 0xBBD4, 0x95A9, 0xBBD5, 0x95A3, + 0xBBD6, 0x95A5, 0xBBD7, 0x95A4, 0xBBD8, 0x9699, 0xBBD9, 0x969C, 0xBBDA, 0x969B, 0xBBDB, 0x96CC, 0xBBDC, 0x96D2, 0xBBDD, 0x9700, + 0xBBDE, 0x977C, 0xBBDF, 0x9785, 0xBBE0, 0x97F6, 0xBBE1, 0x9817, 0xBBE2, 0x9818, 0xBBE3, 0x98AF, 0xBBE4, 0x98B1, 0xBBE5, 0x9903, + 0xBBE6, 0x9905, 0xBBE7, 0x990C, 0xBBE8, 0x9909, 0xBBE9, 0x99C1, 0xBBEA, 0x9AAF, 0xBBEB, 0x9AB0, 0xBBEC, 0x9AE6, 0xBBED, 0x9B41, + 0xBBEE, 0x9B42, 0xBBEF, 0x9CF4, 0xBBF0, 0x9CF6, 0xBBF1, 0x9CF3, 0xBBF2, 0x9EBC, 0xBBF3, 0x9F3B, 0xBBF4, 0x9F4A, 0xBBF5, 0x5104, + 0xBBF6, 0x5100, 0xBBF7, 0x50FB, 0xBBF8, 0x50F5, 0xBBF9, 0x50F9, 0xBBFA, 0x5102, 0xBBFB, 0x5108, 0xBBFC, 0x5109, 0xBBFD, 0x5105, + 0xBBFE, 0x51DC, 0xBC40, 0x5287, 0xBC41, 0x5288, 0xBC42, 0x5289, 0xBC43, 0x528D, 0xBC44, 0x528A, 0xBC45, 0x52F0, 0xBC46, 0x53B2, + 0xBC47, 0x562E, 0xBC48, 0x563B, 0xBC49, 0x5639, 0xBC4A, 0x5632, 0xBC4B, 0x563F, 0xBC4C, 0x5634, 0xBC4D, 0x5629, 0xBC4E, 0x5653, + 0xBC4F, 0x564E, 0xBC50, 0x5657, 0xBC51, 0x5674, 0xBC52, 0x5636, 0xBC53, 0x562F, 0xBC54, 0x5630, 0xBC55, 0x5880, 0xBC56, 0x589F, + 0xBC57, 0x589E, 0xBC58, 0x58B3, 0xBC59, 0x589C, 0xBC5A, 0x58AE, 0xBC5B, 0x58A9, 0xBC5C, 0x58A6, 0xBC5D, 0x596D, 0xBC5E, 0x5B09, + 0xBC5F, 0x5AFB, 0xBC60, 0x5B0B, 0xBC61, 0x5AF5, 0xBC62, 0x5B0C, 0xBC63, 0x5B08, 0xBC64, 0x5BEE, 0xBC65, 0x5BEC, 0xBC66, 0x5BE9, + 0xBC67, 0x5BEB, 0xBC68, 0x5C64, 0xBC69, 0x5C65, 0xBC6A, 0x5D9D, 0xBC6B, 0x5D94, 0xBC6C, 0x5E62, 0xBC6D, 0x5E5F, 0xBC6E, 0x5E61, + 0xBC6F, 0x5EE2, 0xBC70, 0x5EDA, 0xBC71, 0x5EDF, 0xBC72, 0x5EDD, 0xBC73, 0x5EE3, 0xBC74, 0x5EE0, 0xBC75, 0x5F48, 0xBC76, 0x5F71, + 0xBC77, 0x5FB7, 0xBC78, 0x5FB5, 0xBC79, 0x6176, 0xBC7A, 0x6167, 0xBC7B, 0x616E, 0xBC7C, 0x615D, 0xBC7D, 0x6155, 0xBC7E, 0x6182, + 0xBCA1, 0x617C, 0xBCA2, 0x6170, 0xBCA3, 0x616B, 0xBCA4, 0x617E, 0xBCA5, 0x61A7, 0xBCA6, 0x6190, 0xBCA7, 0x61AB, 0xBCA8, 0x618E, + 0xBCA9, 0x61AC, 0xBCAA, 0x619A, 0xBCAB, 0x61A4, 0xBCAC, 0x6194, 0xBCAD, 0x61AE, 0xBCAE, 0x622E, 0xBCAF, 0x6469, 0xBCB0, 0x646F, + 0xBCB1, 0x6479, 0xBCB2, 0x649E, 0xBCB3, 0x64B2, 0xBCB4, 0x6488, 0xBCB5, 0x6490, 0xBCB6, 0x64B0, 0xBCB7, 0x64A5, 0xBCB8, 0x6493, + 0xBCB9, 0x6495, 0xBCBA, 0x64A9, 0xBCBB, 0x6492, 0xBCBC, 0x64AE, 0xBCBD, 0x64AD, 0xBCBE, 0x64AB, 0xBCBF, 0x649A, 0xBCC0, 0x64AC, + 0xBCC1, 0x6499, 0xBCC2, 0x64A2, 0xBCC3, 0x64B3, 0xBCC4, 0x6575, 0xBCC5, 0x6577, 0xBCC6, 0x6578, 0xBCC7, 0x66AE, 0xBCC8, 0x66AB, + 0xBCC9, 0x66B4, 0xBCCA, 0x66B1, 0xBCCB, 0x6A23, 0xBCCC, 0x6A1F, 0xBCCD, 0x69E8, 0xBCCE, 0x6A01, 0xBCCF, 0x6A1E, 0xBCD0, 0x6A19, + 0xBCD1, 0x69FD, 0xBCD2, 0x6A21, 0xBCD3, 0x6A13, 0xBCD4, 0x6A0A, 0xBCD5, 0x69F3, 0xBCD6, 0x6A02, 0xBCD7, 0x6A05, 0xBCD8, 0x69ED, + 0xBCD9, 0x6A11, 0xBCDA, 0x6B50, 0xBCDB, 0x6B4E, 0xBCDC, 0x6BA4, 0xBCDD, 0x6BC5, 0xBCDE, 0x6BC6, 0xBCDF, 0x6F3F, 0xBCE0, 0x6F7C, + 0xBCE1, 0x6F84, 0xBCE2, 0x6F51, 0xBCE3, 0x6F66, 0xBCE4, 0x6F54, 0xBCE5, 0x6F86, 0xBCE6, 0x6F6D, 0xBCE7, 0x6F5B, 0xBCE8, 0x6F78, + 0xBCE9, 0x6F6E, 0xBCEA, 0x6F8E, 0xBCEB, 0x6F7A, 0xBCEC, 0x6F70, 0xBCED, 0x6F64, 0xBCEE, 0x6F97, 0xBCEF, 0x6F58, 0xBCF0, 0x6ED5, + 0xBCF1, 0x6F6F, 0xBCF2, 0x6F60, 0xBCF3, 0x6F5F, 0xBCF4, 0x719F, 0xBCF5, 0x71AC, 0xBCF6, 0x71B1, 0xBCF7, 0x71A8, 0xBCF8, 0x7256, + 0xBCF9, 0x729B, 0xBCFA, 0x734E, 0xBCFB, 0x7357, 0xBCFC, 0x7469, 0xBCFD, 0x748B, 0xBCFE, 0x7483, 0xBD40, 0x747E, 0xBD41, 0x7480, + 0xBD42, 0x757F, 0xBD43, 0x7620, 0xBD44, 0x7629, 0xBD45, 0x761F, 0xBD46, 0x7624, 0xBD47, 0x7626, 0xBD48, 0x7621, 0xBD49, 0x7622, + 0xBD4A, 0x769A, 0xBD4B, 0x76BA, 0xBD4C, 0x76E4, 0xBD4D, 0x778E, 0xBD4E, 0x7787, 0xBD4F, 0x778C, 0xBD50, 0x7791, 0xBD51, 0x778B, + 0xBD52, 0x78CB, 0xBD53, 0x78C5, 0xBD54, 0x78BA, 0xBD55, 0x78CA, 0xBD56, 0x78BE, 0xBD57, 0x78D5, 0xBD58, 0x78BC, 0xBD59, 0x78D0, + 0xBD5A, 0x7A3F, 0xBD5B, 0x7A3C, 0xBD5C, 0x7A40, 0xBD5D, 0x7A3D, 0xBD5E, 0x7A37, 0xBD5F, 0x7A3B, 0xBD60, 0x7AAF, 0xBD61, 0x7AAE, + 0xBD62, 0x7BAD, 0xBD63, 0x7BB1, 0xBD64, 0x7BC4, 0xBD65, 0x7BB4, 0xBD66, 0x7BC6, 0xBD67, 0x7BC7, 0xBD68, 0x7BC1, 0xBD69, 0x7BA0, + 0xBD6A, 0x7BCC, 0xBD6B, 0x7CCA, 0xBD6C, 0x7DE0, 0xBD6D, 0x7DF4, 0xBD6E, 0x7DEF, 0xBD6F, 0x7DFB, 0xBD70, 0x7DD8, 0xBD71, 0x7DEC, + 0xBD72, 0x7DDD, 0xBD73, 0x7DE8, 0xBD74, 0x7DE3, 0xBD75, 0x7DDA, 0xBD76, 0x7DDE, 0xBD77, 0x7DE9, 0xBD78, 0x7D9E, 0xBD79, 0x7DD9, + 0xBD7A, 0x7DF2, 0xBD7B, 0x7DF9, 0xBD7C, 0x7F75, 0xBD7D, 0x7F77, 0xBD7E, 0x7FAF, 0xBDA1, 0x7FE9, 0xBDA2, 0x8026, 0xBDA3, 0x819B, + 0xBDA4, 0x819C, 0xBDA5, 0x819D, 0xBDA6, 0x81A0, 0xBDA7, 0x819A, 0xBDA8, 0x8198, 0xBDA9, 0x8517, 0xBDAA, 0x853D, 0xBDAB, 0x851A, + 0xBDAC, 0x84EE, 0xBDAD, 0x852C, 0xBDAE, 0x852D, 0xBDAF, 0x8513, 0xBDB0, 0x8511, 0xBDB1, 0x8523, 0xBDB2, 0x8521, 0xBDB3, 0x8514, + 0xBDB4, 0x84EC, 0xBDB5, 0x8525, 0xBDB6, 0x84FF, 0xBDB7, 0x8506, 0xBDB8, 0x8782, 0xBDB9, 0x8774, 0xBDBA, 0x8776, 0xBDBB, 0x8760, + 0xBDBC, 0x8766, 0xBDBD, 0x8778, 0xBDBE, 0x8768, 0xBDBF, 0x8759, 0xBDC0, 0x8757, 0xBDC1, 0x874C, 0xBDC2, 0x8753, 0xBDC3, 0x885B, + 0xBDC4, 0x885D, 0xBDC5, 0x8910, 0xBDC6, 0x8907, 0xBDC7, 0x8912, 0xBDC8, 0x8913, 0xBDC9, 0x8915, 0xBDCA, 0x890A, 0xBDCB, 0x8ABC, + 0xBDCC, 0x8AD2, 0xBDCD, 0x8AC7, 0xBDCE, 0x8AC4, 0xBDCF, 0x8A95, 0xBDD0, 0x8ACB, 0xBDD1, 0x8AF8, 0xBDD2, 0x8AB2, 0xBDD3, 0x8AC9, + 0xBDD4, 0x8AC2, 0xBDD5, 0x8ABF, 0xBDD6, 0x8AB0, 0xBDD7, 0x8AD6, 0xBDD8, 0x8ACD, 0xBDD9, 0x8AB6, 0xBDDA, 0x8AB9, 0xBDDB, 0x8ADB, + 0xBDDC, 0x8C4C, 0xBDDD, 0x8C4E, 0xBDDE, 0x8C6C, 0xBDDF, 0x8CE0, 0xBDE0, 0x8CDE, 0xBDE1, 0x8CE6, 0xBDE2, 0x8CE4, 0xBDE3, 0x8CEC, + 0xBDE4, 0x8CED, 0xBDE5, 0x8CE2, 0xBDE6, 0x8CE3, 0xBDE7, 0x8CDC, 0xBDE8, 0x8CEA, 0xBDE9, 0x8CE1, 0xBDEA, 0x8D6D, 0xBDEB, 0x8D9F, + 0xBDEC, 0x8DA3, 0xBDED, 0x8E2B, 0xBDEE, 0x8E10, 0xBDEF, 0x8E1D, 0xBDF0, 0x8E22, 0xBDF1, 0x8E0F, 0xBDF2, 0x8E29, 0xBDF3, 0x8E1F, + 0xBDF4, 0x8E21, 0xBDF5, 0x8E1E, 0xBDF6, 0x8EBA, 0xBDF7, 0x8F1D, 0xBDF8, 0x8F1B, 0xBDF9, 0x8F1F, 0xBDFA, 0x8F29, 0xBDFB, 0x8F26, + 0xBDFC, 0x8F2A, 0xBDFD, 0x8F1C, 0xBDFE, 0x8F1E, 0xBE40, 0x8F25, 0xBE41, 0x9069, 0xBE42, 0x906E, 0xBE43, 0x9068, 0xBE44, 0x906D, + 0xBE45, 0x9077, 0xBE46, 0x9130, 0xBE47, 0x912D, 0xBE48, 0x9127, 0xBE49, 0x9131, 0xBE4A, 0x9187, 0xBE4B, 0x9189, 0xBE4C, 0x918B, + 0xBE4D, 0x9183, 0xBE4E, 0x92C5, 0xBE4F, 0x92BB, 0xBE50, 0x92B7, 0xBE51, 0x92EA, 0xBE52, 0x92AC, 0xBE53, 0x92E4, 0xBE54, 0x92C1, + 0xBE55, 0x92B3, 0xBE56, 0x92BC, 0xBE57, 0x92D2, 0xBE58, 0x92C7, 0xBE59, 0x92F0, 0xBE5A, 0x92B2, 0xBE5B, 0x95AD, 0xBE5C, 0x95B1, + 0xBE5D, 0x9704, 0xBE5E, 0x9706, 0xBE5F, 0x9707, 0xBE60, 0x9709, 0xBE61, 0x9760, 0xBE62, 0x978D, 0xBE63, 0x978B, 0xBE64, 0x978F, + 0xBE65, 0x9821, 0xBE66, 0x982B, 0xBE67, 0x981C, 0xBE68, 0x98B3, 0xBE69, 0x990A, 0xBE6A, 0x9913, 0xBE6B, 0x9912, 0xBE6C, 0x9918, + 0xBE6D, 0x99DD, 0xBE6E, 0x99D0, 0xBE6F, 0x99DF, 0xBE70, 0x99DB, 0xBE71, 0x99D1, 0xBE72, 0x99D5, 0xBE73, 0x99D2, 0xBE74, 0x99D9, + 0xBE75, 0x9AB7, 0xBE76, 0x9AEE, 0xBE77, 0x9AEF, 0xBE78, 0x9B27, 0xBE79, 0x9B45, 0xBE7A, 0x9B44, 0xBE7B, 0x9B77, 0xBE7C, 0x9B6F, + 0xBE7D, 0x9D06, 0xBE7E, 0x9D09, 0xBEA1, 0x9D03, 0xBEA2, 0x9EA9, 0xBEA3, 0x9EBE, 0xBEA4, 0x9ECE, 0xBEA5, 0x58A8, 0xBEA6, 0x9F52, + 0xBEA7, 0x5112, 0xBEA8, 0x5118, 0xBEA9, 0x5114, 0xBEAA, 0x5110, 0xBEAB, 0x5115, 0xBEAC, 0x5180, 0xBEAD, 0x51AA, 0xBEAE, 0x51DD, + 0xBEAF, 0x5291, 0xBEB0, 0x5293, 0xBEB1, 0x52F3, 0xBEB2, 0x5659, 0xBEB3, 0x566B, 0xBEB4, 0x5679, 0xBEB5, 0x5669, 0xBEB6, 0x5664, + 0xBEB7, 0x5678, 0xBEB8, 0x566A, 0xBEB9, 0x5668, 0xBEBA, 0x5665, 0xBEBB, 0x5671, 0xBEBC, 0x566F, 0xBEBD, 0x566C, 0xBEBE, 0x5662, + 0xBEBF, 0x5676, 0xBEC0, 0x58C1, 0xBEC1, 0x58BE, 0xBEC2, 0x58C7, 0xBEC3, 0x58C5, 0xBEC4, 0x596E, 0xBEC5, 0x5B1D, 0xBEC6, 0x5B34, + 0xBEC7, 0x5B78, 0xBEC8, 0x5BF0, 0xBEC9, 0x5C0E, 0xBECA, 0x5F4A, 0xBECB, 0x61B2, 0xBECC, 0x6191, 0xBECD, 0x61A9, 0xBECE, 0x618A, + 0xBECF, 0x61CD, 0xBED0, 0x61B6, 0xBED1, 0x61BE, 0xBED2, 0x61CA, 0xBED3, 0x61C8, 0xBED4, 0x6230, 0xBED5, 0x64C5, 0xBED6, 0x64C1, + 0xBED7, 0x64CB, 0xBED8, 0x64BB, 0xBED9, 0x64BC, 0xBEDA, 0x64DA, 0xBEDB, 0x64C4, 0xBEDC, 0x64C7, 0xBEDD, 0x64C2, 0xBEDE, 0x64CD, + 0xBEDF, 0x64BF, 0xBEE0, 0x64D2, 0xBEE1, 0x64D4, 0xBEE2, 0x64BE, 0xBEE3, 0x6574, 0xBEE4, 0x66C6, 0xBEE5, 0x66C9, 0xBEE6, 0x66B9, + 0xBEE7, 0x66C4, 0xBEE8, 0x66C7, 0xBEE9, 0x66B8, 0xBEEA, 0x6A3D, 0xBEEB, 0x6A38, 0xBEEC, 0x6A3A, 0xBEED, 0x6A59, 0xBEEE, 0x6A6B, + 0xBEEF, 0x6A58, 0xBEF0, 0x6A39, 0xBEF1, 0x6A44, 0xBEF2, 0x6A62, 0xBEF3, 0x6A61, 0xBEF4, 0x6A4B, 0xBEF5, 0x6A47, 0xBEF6, 0x6A35, + 0xBEF7, 0x6A5F, 0xBEF8, 0x6A48, 0xBEF9, 0x6B59, 0xBEFA, 0x6B77, 0xBEFB, 0x6C05, 0xBEFC, 0x6FC2, 0xBEFD, 0x6FB1, 0xBEFE, 0x6FA1, + 0xBF40, 0x6FC3, 0xBF41, 0x6FA4, 0xBF42, 0x6FC1, 0xBF43, 0x6FA7, 0xBF44, 0x6FB3, 0xBF45, 0x6FC0, 0xBF46, 0x6FB9, 0xBF47, 0x6FB6, + 0xBF48, 0x6FA6, 0xBF49, 0x6FA0, 0xBF4A, 0x6FB4, 0xBF4B, 0x71BE, 0xBF4C, 0x71C9, 0xBF4D, 0x71D0, 0xBF4E, 0x71D2, 0xBF4F, 0x71C8, + 0xBF50, 0x71D5, 0xBF51, 0x71B9, 0xBF52, 0x71CE, 0xBF53, 0x71D9, 0xBF54, 0x71DC, 0xBF55, 0x71C3, 0xBF56, 0x71C4, 0xBF57, 0x7368, + 0xBF58, 0x749C, 0xBF59, 0x74A3, 0xBF5A, 0x7498, 0xBF5B, 0x749F, 0xBF5C, 0x749E, 0xBF5D, 0x74E2, 0xBF5E, 0x750C, 0xBF5F, 0x750D, + 0xBF60, 0x7634, 0xBF61, 0x7638, 0xBF62, 0x763A, 0xBF63, 0x76E7, 0xBF64, 0x76E5, 0xBF65, 0x77A0, 0xBF66, 0x779E, 0xBF67, 0x779F, + 0xBF68, 0x77A5, 0xBF69, 0x78E8, 0xBF6A, 0x78DA, 0xBF6B, 0x78EC, 0xBF6C, 0x78E7, 0xBF6D, 0x79A6, 0xBF6E, 0x7A4D, 0xBF6F, 0x7A4E, + 0xBF70, 0x7A46, 0xBF71, 0x7A4C, 0xBF72, 0x7A4B, 0xBF73, 0x7ABA, 0xBF74, 0x7BD9, 0xBF75, 0x7C11, 0xBF76, 0x7BC9, 0xBF77, 0x7BE4, + 0xBF78, 0x7BDB, 0xBF79, 0x7BE1, 0xBF7A, 0x7BE9, 0xBF7B, 0x7BE6, 0xBF7C, 0x7CD5, 0xBF7D, 0x7CD6, 0xBF7E, 0x7E0A, 0xBFA1, 0x7E11, + 0xBFA2, 0x7E08, 0xBFA3, 0x7E1B, 0xBFA4, 0x7E23, 0xBFA5, 0x7E1E, 0xBFA6, 0x7E1D, 0xBFA7, 0x7E09, 0xBFA8, 0x7E10, 0xBFA9, 0x7F79, + 0xBFAA, 0x7FB2, 0xBFAB, 0x7FF0, 0xBFAC, 0x7FF1, 0xBFAD, 0x7FEE, 0xBFAE, 0x8028, 0xBFAF, 0x81B3, 0xBFB0, 0x81A9, 0xBFB1, 0x81A8, + 0xBFB2, 0x81FB, 0xBFB3, 0x8208, 0xBFB4, 0x8258, 0xBFB5, 0x8259, 0xBFB6, 0x854A, 0xBFB7, 0x8559, 0xBFB8, 0x8548, 0xBFB9, 0x8568, + 0xBFBA, 0x8569, 0xBFBB, 0x8543, 0xBFBC, 0x8549, 0xBFBD, 0x856D, 0xBFBE, 0x856A, 0xBFBF, 0x855E, 0xBFC0, 0x8783, 0xBFC1, 0x879F, + 0xBFC2, 0x879E, 0xBFC3, 0x87A2, 0xBFC4, 0x878D, 0xBFC5, 0x8861, 0xBFC6, 0x892A, 0xBFC7, 0x8932, 0xBFC8, 0x8925, 0xBFC9, 0x892B, + 0xBFCA, 0x8921, 0xBFCB, 0x89AA, 0xBFCC, 0x89A6, 0xBFCD, 0x8AE6, 0xBFCE, 0x8AFA, 0xBFCF, 0x8AEB, 0xBFD0, 0x8AF1, 0xBFD1, 0x8B00, + 0xBFD2, 0x8ADC, 0xBFD3, 0x8AE7, 0xBFD4, 0x8AEE, 0xBFD5, 0x8AFE, 0xBFD6, 0x8B01, 0xBFD7, 0x8B02, 0xBFD8, 0x8AF7, 0xBFD9, 0x8AED, + 0xBFDA, 0x8AF3, 0xBFDB, 0x8AF6, 0xBFDC, 0x8AFC, 0xBFDD, 0x8C6B, 0xBFDE, 0x8C6D, 0xBFDF, 0x8C93, 0xBFE0, 0x8CF4, 0xBFE1, 0x8E44, + 0xBFE2, 0x8E31, 0xBFE3, 0x8E34, 0xBFE4, 0x8E42, 0xBFE5, 0x8E39, 0xBFE6, 0x8E35, 0xBFE7, 0x8F3B, 0xBFE8, 0x8F2F, 0xBFE9, 0x8F38, + 0xBFEA, 0x8F33, 0xBFEB, 0x8FA8, 0xBFEC, 0x8FA6, 0xBFED, 0x9075, 0xBFEE, 0x9074, 0xBFEF, 0x9078, 0xBFF0, 0x9072, 0xBFF1, 0x907C, + 0xBFF2, 0x907A, 0xBFF3, 0x9134, 0xBFF4, 0x9192, 0xBFF5, 0x9320, 0xBFF6, 0x9336, 0xBFF7, 0x92F8, 0xBFF8, 0x9333, 0xBFF9, 0x932F, + 0xBFFA, 0x9322, 0xBFFB, 0x92FC, 0xBFFC, 0x932B, 0xBFFD, 0x9304, 0xBFFE, 0x931A, 0xC040, 0x9310, 0xC041, 0x9326, 0xC042, 0x9321, + 0xC043, 0x9315, 0xC044, 0x932E, 0xC045, 0x9319, 0xC046, 0x95BB, 0xC047, 0x96A7, 0xC048, 0x96A8, 0xC049, 0x96AA, 0xC04A, 0x96D5, + 0xC04B, 0x970E, 0xC04C, 0x9711, 0xC04D, 0x9716, 0xC04E, 0x970D, 0xC04F, 0x9713, 0xC050, 0x970F, 0xC051, 0x975B, 0xC052, 0x975C, + 0xC053, 0x9766, 0xC054, 0x9798, 0xC055, 0x9830, 0xC056, 0x9838, 0xC057, 0x983B, 0xC058, 0x9837, 0xC059, 0x982D, 0xC05A, 0x9839, + 0xC05B, 0x9824, 0xC05C, 0x9910, 0xC05D, 0x9928, 0xC05E, 0x991E, 0xC05F, 0x991B, 0xC060, 0x9921, 0xC061, 0x991A, 0xC062, 0x99ED, + 0xC063, 0x99E2, 0xC064, 0x99F1, 0xC065, 0x9AB8, 0xC066, 0x9ABC, 0xC067, 0x9AFB, 0xC068, 0x9AED, 0xC069, 0x9B28, 0xC06A, 0x9B91, + 0xC06B, 0x9D15, 0xC06C, 0x9D23, 0xC06D, 0x9D26, 0xC06E, 0x9D28, 0xC06F, 0x9D12, 0xC070, 0x9D1B, 0xC071, 0x9ED8, 0xC072, 0x9ED4, + 0xC073, 0x9F8D, 0xC074, 0x9F9C, 0xC075, 0x512A, 0xC076, 0x511F, 0xC077, 0x5121, 0xC078, 0x5132, 0xC079, 0x52F5, 0xC07A, 0x568E, + 0xC07B, 0x5680, 0xC07C, 0x5690, 0xC07D, 0x5685, 0xC07E, 0x5687, 0xC0A1, 0x568F, 0xC0A2, 0x58D5, 0xC0A3, 0x58D3, 0xC0A4, 0x58D1, + 0xC0A5, 0x58CE, 0xC0A6, 0x5B30, 0xC0A7, 0x5B2A, 0xC0A8, 0x5B24, 0xC0A9, 0x5B7A, 0xC0AA, 0x5C37, 0xC0AB, 0x5C68, 0xC0AC, 0x5DBC, + 0xC0AD, 0x5DBA, 0xC0AE, 0x5DBD, 0xC0AF, 0x5DB8, 0xC0B0, 0x5E6B, 0xC0B1, 0x5F4C, 0xC0B2, 0x5FBD, 0xC0B3, 0x61C9, 0xC0B4, 0x61C2, + 0xC0B5, 0x61C7, 0xC0B6, 0x61E6, 0xC0B7, 0x61CB, 0xC0B8, 0x6232, 0xC0B9, 0x6234, 0xC0BA, 0x64CE, 0xC0BB, 0x64CA, 0xC0BC, 0x64D8, + 0xC0BD, 0x64E0, 0xC0BE, 0x64F0, 0xC0BF, 0x64E6, 0xC0C0, 0x64EC, 0xC0C1, 0x64F1, 0xC0C2, 0x64E2, 0xC0C3, 0x64ED, 0xC0C4, 0x6582, + 0xC0C5, 0x6583, 0xC0C6, 0x66D9, 0xC0C7, 0x66D6, 0xC0C8, 0x6A80, 0xC0C9, 0x6A94, 0xC0CA, 0x6A84, 0xC0CB, 0x6AA2, 0xC0CC, 0x6A9C, + 0xC0CD, 0x6ADB, 0xC0CE, 0x6AA3, 0xC0CF, 0x6A7E, 0xC0D0, 0x6A97, 0xC0D1, 0x6A90, 0xC0D2, 0x6AA0, 0xC0D3, 0x6B5C, 0xC0D4, 0x6BAE, + 0xC0D5, 0x6BDA, 0xC0D6, 0x6C08, 0xC0D7, 0x6FD8, 0xC0D8, 0x6FF1, 0xC0D9, 0x6FDF, 0xC0DA, 0x6FE0, 0xC0DB, 0x6FDB, 0xC0DC, 0x6FE4, + 0xC0DD, 0x6FEB, 0xC0DE, 0x6FEF, 0xC0DF, 0x6F80, 0xC0E0, 0x6FEC, 0xC0E1, 0x6FE1, 0xC0E2, 0x6FE9, 0xC0E3, 0x6FD5, 0xC0E4, 0x6FEE, + 0xC0E5, 0x6FF0, 0xC0E6, 0x71E7, 0xC0E7, 0x71DF, 0xC0E8, 0x71EE, 0xC0E9, 0x71E6, 0xC0EA, 0x71E5, 0xC0EB, 0x71ED, 0xC0EC, 0x71EC, + 0xC0ED, 0x71F4, 0xC0EE, 0x71E0, 0xC0EF, 0x7235, 0xC0F0, 0x7246, 0xC0F1, 0x7370, 0xC0F2, 0x7372, 0xC0F3, 0x74A9, 0xC0F4, 0x74B0, + 0xC0F5, 0x74A6, 0xC0F6, 0x74A8, 0xC0F7, 0x7646, 0xC0F8, 0x7642, 0xC0F9, 0x764C, 0xC0FA, 0x76EA, 0xC0FB, 0x77B3, 0xC0FC, 0x77AA, + 0xC0FD, 0x77B0, 0xC0FE, 0x77AC, 0xC140, 0x77A7, 0xC141, 0x77AD, 0xC142, 0x77EF, 0xC143, 0x78F7, 0xC144, 0x78FA, 0xC145, 0x78F4, + 0xC146, 0x78EF, 0xC147, 0x7901, 0xC148, 0x79A7, 0xC149, 0x79AA, 0xC14A, 0x7A57, 0xC14B, 0x7ABF, 0xC14C, 0x7C07, 0xC14D, 0x7C0D, + 0xC14E, 0x7BFE, 0xC14F, 0x7BF7, 0xC150, 0x7C0C, 0xC151, 0x7BE0, 0xC152, 0x7CE0, 0xC153, 0x7CDC, 0xC154, 0x7CDE, 0xC155, 0x7CE2, + 0xC156, 0x7CDF, 0xC157, 0x7CD9, 0xC158, 0x7CDD, 0xC159, 0x7E2E, 0xC15A, 0x7E3E, 0xC15B, 0x7E46, 0xC15C, 0x7E37, 0xC15D, 0x7E32, + 0xC15E, 0x7E43, 0xC15F, 0x7E2B, 0xC160, 0x7E3D, 0xC161, 0x7E31, 0xC162, 0x7E45, 0xC163, 0x7E41, 0xC164, 0x7E34, 0xC165, 0x7E39, + 0xC166, 0x7E48, 0xC167, 0x7E35, 0xC168, 0x7E3F, 0xC169, 0x7E2F, 0xC16A, 0x7F44, 0xC16B, 0x7FF3, 0xC16C, 0x7FFC, 0xC16D, 0x8071, + 0xC16E, 0x8072, 0xC16F, 0x8070, 0xC170, 0x806F, 0xC171, 0x8073, 0xC172, 0x81C6, 0xC173, 0x81C3, 0xC174, 0x81BA, 0xC175, 0x81C2, + 0xC176, 0x81C0, 0xC177, 0x81BF, 0xC178, 0x81BD, 0xC179, 0x81C9, 0xC17A, 0x81BE, 0xC17B, 0x81E8, 0xC17C, 0x8209, 0xC17D, 0x8271, + 0xC17E, 0x85AA, 0xC1A1, 0x8584, 0xC1A2, 0x857E, 0xC1A3, 0x859C, 0xC1A4, 0x8591, 0xC1A5, 0x8594, 0xC1A6, 0x85AF, 0xC1A7, 0x859B, + 0xC1A8, 0x8587, 0xC1A9, 0x85A8, 0xC1AA, 0x858A, 0xC1AB, 0x8667, 0xC1AC, 0x87C0, 0xC1AD, 0x87D1, 0xC1AE, 0x87B3, 0xC1AF, 0x87D2, + 0xC1B0, 0x87C6, 0xC1B1, 0x87AB, 0xC1B2, 0x87BB, 0xC1B3, 0x87BA, 0xC1B4, 0x87C8, 0xC1B5, 0x87CB, 0xC1B6, 0x893B, 0xC1B7, 0x8936, + 0xC1B8, 0x8944, 0xC1B9, 0x8938, 0xC1BA, 0x893D, 0xC1BB, 0x89AC, 0xC1BC, 0x8B0E, 0xC1BD, 0x8B17, 0xC1BE, 0x8B19, 0xC1BF, 0x8B1B, + 0xC1C0, 0x8B0A, 0xC1C1, 0x8B20, 0xC1C2, 0x8B1D, 0xC1C3, 0x8B04, 0xC1C4, 0x8B10, 0xC1C5, 0x8C41, 0xC1C6, 0x8C3F, 0xC1C7, 0x8C73, + 0xC1C8, 0x8CFA, 0xC1C9, 0x8CFD, 0xC1CA, 0x8CFC, 0xC1CB, 0x8CF8, 0xC1CC, 0x8CFB, 0xC1CD, 0x8DA8, 0xC1CE, 0x8E49, 0xC1CF, 0x8E4B, + 0xC1D0, 0x8E48, 0xC1D1, 0x8E4A, 0xC1D2, 0x8F44, 0xC1D3, 0x8F3E, 0xC1D4, 0x8F42, 0xC1D5, 0x8F45, 0xC1D6, 0x8F3F, 0xC1D7, 0x907F, + 0xC1D8, 0x907D, 0xC1D9, 0x9084, 0xC1DA, 0x9081, 0xC1DB, 0x9082, 0xC1DC, 0x9080, 0xC1DD, 0x9139, 0xC1DE, 0x91A3, 0xC1DF, 0x919E, + 0xC1E0, 0x919C, 0xC1E1, 0x934D, 0xC1E2, 0x9382, 0xC1E3, 0x9328, 0xC1E4, 0x9375, 0xC1E5, 0x934A, 0xC1E6, 0x9365, 0xC1E7, 0x934B, + 0xC1E8, 0x9318, 0xC1E9, 0x937E, 0xC1EA, 0x936C, 0xC1EB, 0x935B, 0xC1EC, 0x9370, 0xC1ED, 0x935A, 0xC1EE, 0x9354, 0xC1EF, 0x95CA, + 0xC1F0, 0x95CB, 0xC1F1, 0x95CC, 0xC1F2, 0x95C8, 0xC1F3, 0x95C6, 0xC1F4, 0x96B1, 0xC1F5, 0x96B8, 0xC1F6, 0x96D6, 0xC1F7, 0x971C, + 0xC1F8, 0x971E, 0xC1F9, 0x97A0, 0xC1FA, 0x97D3, 0xC1FB, 0x9846, 0xC1FC, 0x98B6, 0xC1FD, 0x9935, 0xC1FE, 0x9A01, 0xC240, 0x99FF, + 0xC241, 0x9BAE, 0xC242, 0x9BAB, 0xC243, 0x9BAA, 0xC244, 0x9BAD, 0xC245, 0x9D3B, 0xC246, 0x9D3F, 0xC247, 0x9E8B, 0xC248, 0x9ECF, + 0xC249, 0x9EDE, 0xC24A, 0x9EDC, 0xC24B, 0x9EDD, 0xC24C, 0x9EDB, 0xC24D, 0x9F3E, 0xC24E, 0x9F4B, 0xC24F, 0x53E2, 0xC250, 0x5695, + 0xC251, 0x56AE, 0xC252, 0x58D9, 0xC253, 0x58D8, 0xC254, 0x5B38, 0xC255, 0x5F5D, 0xC256, 0x61E3, 0xC257, 0x6233, 0xC258, 0x64F4, + 0xC259, 0x64F2, 0xC25A, 0x64FE, 0xC25B, 0x6506, 0xC25C, 0x64FA, 0xC25D, 0x64FB, 0xC25E, 0x64F7, 0xC25F, 0x65B7, 0xC260, 0x66DC, + 0xC261, 0x6726, 0xC262, 0x6AB3, 0xC263, 0x6AAC, 0xC264, 0x6AC3, 0xC265, 0x6ABB, 0xC266, 0x6AB8, 0xC267, 0x6AC2, 0xC268, 0x6AAE, + 0xC269, 0x6AAF, 0xC26A, 0x6B5F, 0xC26B, 0x6B78, 0xC26C, 0x6BAF, 0xC26D, 0x7009, 0xC26E, 0x700B, 0xC26F, 0x6FFE, 0xC270, 0x7006, + 0xC271, 0x6FFA, 0xC272, 0x7011, 0xC273, 0x700F, 0xC274, 0x71FB, 0xC275, 0x71FC, 0xC276, 0x71FE, 0xC277, 0x71F8, 0xC278, 0x7377, + 0xC279, 0x7375, 0xC27A, 0x74A7, 0xC27B, 0x74BF, 0xC27C, 0x7515, 0xC27D, 0x7656, 0xC27E, 0x7658, 0xC2A1, 0x7652, 0xC2A2, 0x77BD, + 0xC2A3, 0x77BF, 0xC2A4, 0x77BB, 0xC2A5, 0x77BC, 0xC2A6, 0x790E, 0xC2A7, 0x79AE, 0xC2A8, 0x7A61, 0xC2A9, 0x7A62, 0xC2AA, 0x7A60, + 0xC2AB, 0x7AC4, 0xC2AC, 0x7AC5, 0xC2AD, 0x7C2B, 0xC2AE, 0x7C27, 0xC2AF, 0x7C2A, 0xC2B0, 0x7C1E, 0xC2B1, 0x7C23, 0xC2B2, 0x7C21, + 0xC2B3, 0x7CE7, 0xC2B4, 0x7E54, 0xC2B5, 0x7E55, 0xC2B6, 0x7E5E, 0xC2B7, 0x7E5A, 0xC2B8, 0x7E61, 0xC2B9, 0x7E52, 0xC2BA, 0x7E59, + 0xC2BB, 0x7F48, 0xC2BC, 0x7FF9, 0xC2BD, 0x7FFB, 0xC2BE, 0x8077, 0xC2BF, 0x8076, 0xC2C0, 0x81CD, 0xC2C1, 0x81CF, 0xC2C2, 0x820A, + 0xC2C3, 0x85CF, 0xC2C4, 0x85A9, 0xC2C5, 0x85CD, 0xC2C6, 0x85D0, 0xC2C7, 0x85C9, 0xC2C8, 0x85B0, 0xC2C9, 0x85BA, 0xC2CA, 0x85B9, + 0xC2CB, 0x85A6, 0xC2CC, 0x87EF, 0xC2CD, 0x87EC, 0xC2CE, 0x87F2, 0xC2CF, 0x87E0, 0xC2D0, 0x8986, 0xC2D1, 0x89B2, 0xC2D2, 0x89F4, + 0xC2D3, 0x8B28, 0xC2D4, 0x8B39, 0xC2D5, 0x8B2C, 0xC2D6, 0x8B2B, 0xC2D7, 0x8C50, 0xC2D8, 0x8D05, 0xC2D9, 0x8E59, 0xC2DA, 0x8E63, + 0xC2DB, 0x8E66, 0xC2DC, 0x8E64, 0xC2DD, 0x8E5F, 0xC2DE, 0x8E55, 0xC2DF, 0x8EC0, 0xC2E0, 0x8F49, 0xC2E1, 0x8F4D, 0xC2E2, 0x9087, + 0xC2E3, 0x9083, 0xC2E4, 0x9088, 0xC2E5, 0x91AB, 0xC2E6, 0x91AC, 0xC2E7, 0x91D0, 0xC2E8, 0x9394, 0xC2E9, 0x938A, 0xC2EA, 0x9396, + 0xC2EB, 0x93A2, 0xC2EC, 0x93B3, 0xC2ED, 0x93AE, 0xC2EE, 0x93AC, 0xC2EF, 0x93B0, 0xC2F0, 0x9398, 0xC2F1, 0x939A, 0xC2F2, 0x9397, + 0xC2F3, 0x95D4, 0xC2F4, 0x95D6, 0xC2F5, 0x95D0, 0xC2F6, 0x95D5, 0xC2F7, 0x96E2, 0xC2F8, 0x96DC, 0xC2F9, 0x96D9, 0xC2FA, 0x96DB, + 0xC2FB, 0x96DE, 0xC2FC, 0x9724, 0xC2FD, 0x97A3, 0xC2FE, 0x97A6, 0xC340, 0x97AD, 0xC341, 0x97F9, 0xC342, 0x984D, 0xC343, 0x984F, + 0xC344, 0x984C, 0xC345, 0x984E, 0xC346, 0x9853, 0xC347, 0x98BA, 0xC348, 0x993E, 0xC349, 0x993F, 0xC34A, 0x993D, 0xC34B, 0x992E, + 0xC34C, 0x99A5, 0xC34D, 0x9A0E, 0xC34E, 0x9AC1, 0xC34F, 0x9B03, 0xC350, 0x9B06, 0xC351, 0x9B4F, 0xC352, 0x9B4E, 0xC353, 0x9B4D, + 0xC354, 0x9BCA, 0xC355, 0x9BC9, 0xC356, 0x9BFD, 0xC357, 0x9BC8, 0xC358, 0x9BC0, 0xC359, 0x9D51, 0xC35A, 0x9D5D, 0xC35B, 0x9D60, + 0xC35C, 0x9EE0, 0xC35D, 0x9F15, 0xC35E, 0x9F2C, 0xC35F, 0x5133, 0xC360, 0x56A5, 0xC361, 0x58DE, 0xC362, 0x58DF, 0xC363, 0x58E2, + 0xC364, 0x5BF5, 0xC365, 0x9F90, 0xC366, 0x5EEC, 0xC367, 0x61F2, 0xC368, 0x61F7, 0xC369, 0x61F6, 0xC36A, 0x61F5, 0xC36B, 0x6500, + 0xC36C, 0x650F, 0xC36D, 0x66E0, 0xC36E, 0x66DD, 0xC36F, 0x6AE5, 0xC370, 0x6ADD, 0xC371, 0x6ADA, 0xC372, 0x6AD3, 0xC373, 0x701B, + 0xC374, 0x701F, 0xC375, 0x7028, 0xC376, 0x701A, 0xC377, 0x701D, 0xC378, 0x7015, 0xC379, 0x7018, 0xC37A, 0x7206, 0xC37B, 0x720D, + 0xC37C, 0x7258, 0xC37D, 0x72A2, 0xC37E, 0x7378, 0xC3A1, 0x737A, 0xC3A2, 0x74BD, 0xC3A3, 0x74CA, 0xC3A4, 0x74E3, 0xC3A5, 0x7587, + 0xC3A6, 0x7586, 0xC3A7, 0x765F, 0xC3A8, 0x7661, 0xC3A9, 0x77C7, 0xC3AA, 0x7919, 0xC3AB, 0x79B1, 0xC3AC, 0x7A6B, 0xC3AD, 0x7A69, + 0xC3AE, 0x7C3E, 0xC3AF, 0x7C3F, 0xC3B0, 0x7C38, 0xC3B1, 0x7C3D, 0xC3B2, 0x7C37, 0xC3B3, 0x7C40, 0xC3B4, 0x7E6B, 0xC3B5, 0x7E6D, + 0xC3B6, 0x7E79, 0xC3B7, 0x7E69, 0xC3B8, 0x7E6A, 0xC3B9, 0x7F85, 0xC3BA, 0x7E73, 0xC3BB, 0x7FB6, 0xC3BC, 0x7FB9, 0xC3BD, 0x7FB8, + 0xC3BE, 0x81D8, 0xC3BF, 0x85E9, 0xC3C0, 0x85DD, 0xC3C1, 0x85EA, 0xC3C2, 0x85D5, 0xC3C3, 0x85E4, 0xC3C4, 0x85E5, 0xC3C5, 0x85F7, + 0xC3C6, 0x87FB, 0xC3C7, 0x8805, 0xC3C8, 0x880D, 0xC3C9, 0x87F9, 0xC3CA, 0x87FE, 0xC3CB, 0x8960, 0xC3CC, 0x895F, 0xC3CD, 0x8956, + 0xC3CE, 0x895E, 0xC3CF, 0x8B41, 0xC3D0, 0x8B5C, 0xC3D1, 0x8B58, 0xC3D2, 0x8B49, 0xC3D3, 0x8B5A, 0xC3D4, 0x8B4E, 0xC3D5, 0x8B4F, + 0xC3D6, 0x8B46, 0xC3D7, 0x8B59, 0xC3D8, 0x8D08, 0xC3D9, 0x8D0A, 0xC3DA, 0x8E7C, 0xC3DB, 0x8E72, 0xC3DC, 0x8E87, 0xC3DD, 0x8E76, + 0xC3DE, 0x8E6C, 0xC3DF, 0x8E7A, 0xC3E0, 0x8E74, 0xC3E1, 0x8F54, 0xC3E2, 0x8F4E, 0xC3E3, 0x8FAD, 0xC3E4, 0x908A, 0xC3E5, 0x908B, + 0xC3E6, 0x91B1, 0xC3E7, 0x91AE, 0xC3E8, 0x93E1, 0xC3E9, 0x93D1, 0xC3EA, 0x93DF, 0xC3EB, 0x93C3, 0xC3EC, 0x93C8, 0xC3ED, 0x93DC, + 0xC3EE, 0x93DD, 0xC3EF, 0x93D6, 0xC3F0, 0x93E2, 0xC3F1, 0x93CD, 0xC3F2, 0x93D8, 0xC3F3, 0x93E4, 0xC3F4, 0x93D7, 0xC3F5, 0x93E8, + 0xC3F6, 0x95DC, 0xC3F7, 0x96B4, 0xC3F8, 0x96E3, 0xC3F9, 0x972A, 0xC3FA, 0x9727, 0xC3FB, 0x9761, 0xC3FC, 0x97DC, 0xC3FD, 0x97FB, + 0xC3FE, 0x985E, 0xC440, 0x9858, 0xC441, 0x985B, 0xC442, 0x98BC, 0xC443, 0x9945, 0xC444, 0x9949, 0xC445, 0x9A16, 0xC446, 0x9A19, + 0xC447, 0x9B0D, 0xC448, 0x9BE8, 0xC449, 0x9BE7, 0xC44A, 0x9BD6, 0xC44B, 0x9BDB, 0xC44C, 0x9D89, 0xC44D, 0x9D61, 0xC44E, 0x9D72, + 0xC44F, 0x9D6A, 0xC450, 0x9D6C, 0xC451, 0x9E92, 0xC452, 0x9E97, 0xC453, 0x9E93, 0xC454, 0x9EB4, 0xC455, 0x52F8, 0xC456, 0x56A8, + 0xC457, 0x56B7, 0xC458, 0x56B6, 0xC459, 0x56B4, 0xC45A, 0x56BC, 0xC45B, 0x58E4, 0xC45C, 0x5B40, 0xC45D, 0x5B43, 0xC45E, 0x5B7D, + 0xC45F, 0x5BF6, 0xC460, 0x5DC9, 0xC461, 0x61F8, 0xC462, 0x61FA, 0xC463, 0x6518, 0xC464, 0x6514, 0xC465, 0x6519, 0xC466, 0x66E6, + 0xC467, 0x6727, 0xC468, 0x6AEC, 0xC469, 0x703E, 0xC46A, 0x7030, 0xC46B, 0x7032, 0xC46C, 0x7210, 0xC46D, 0x737B, 0xC46E, 0x74CF, + 0xC46F, 0x7662, 0xC470, 0x7665, 0xC471, 0x7926, 0xC472, 0x792A, 0xC473, 0x792C, 0xC474, 0x792B, 0xC475, 0x7AC7, 0xC476, 0x7AF6, + 0xC477, 0x7C4C, 0xC478, 0x7C43, 0xC479, 0x7C4D, 0xC47A, 0x7CEF, 0xC47B, 0x7CF0, 0xC47C, 0x8FAE, 0xC47D, 0x7E7D, 0xC47E, 0x7E7C, + 0xC4A1, 0x7E82, 0xC4A2, 0x7F4C, 0xC4A3, 0x8000, 0xC4A4, 0x81DA, 0xC4A5, 0x8266, 0xC4A6, 0x85FB, 0xC4A7, 0x85F9, 0xC4A8, 0x8611, + 0xC4A9, 0x85FA, 0xC4AA, 0x8606, 0xC4AB, 0x860B, 0xC4AC, 0x8607, 0xC4AD, 0x860A, 0xC4AE, 0x8814, 0xC4AF, 0x8815, 0xC4B0, 0x8964, + 0xC4B1, 0x89BA, 0xC4B2, 0x89F8, 0xC4B3, 0x8B70, 0xC4B4, 0x8B6C, 0xC4B5, 0x8B66, 0xC4B6, 0x8B6F, 0xC4B7, 0x8B5F, 0xC4B8, 0x8B6B, + 0xC4B9, 0x8D0F, 0xC4BA, 0x8D0D, 0xC4BB, 0x8E89, 0xC4BC, 0x8E81, 0xC4BD, 0x8E85, 0xC4BE, 0x8E82, 0xC4BF, 0x91B4, 0xC4C0, 0x91CB, + 0xC4C1, 0x9418, 0xC4C2, 0x9403, 0xC4C3, 0x93FD, 0xC4C4, 0x95E1, 0xC4C5, 0x9730, 0xC4C6, 0x98C4, 0xC4C7, 0x9952, 0xC4C8, 0x9951, + 0xC4C9, 0x99A8, 0xC4CA, 0x9A2B, 0xC4CB, 0x9A30, 0xC4CC, 0x9A37, 0xC4CD, 0x9A35, 0xC4CE, 0x9C13, 0xC4CF, 0x9C0D, 0xC4D0, 0x9E79, + 0xC4D1, 0x9EB5, 0xC4D2, 0x9EE8, 0xC4D3, 0x9F2F, 0xC4D4, 0x9F5F, 0xC4D5, 0x9F63, 0xC4D6, 0x9F61, 0xC4D7, 0x5137, 0xC4D8, 0x5138, + 0xC4D9, 0x56C1, 0xC4DA, 0x56C0, 0xC4DB, 0x56C2, 0xC4DC, 0x5914, 0xC4DD, 0x5C6C, 0xC4DE, 0x5DCD, 0xC4DF, 0x61FC, 0xC4E0, 0x61FE, + 0xC4E1, 0x651D, 0xC4E2, 0x651C, 0xC4E3, 0x6595, 0xC4E4, 0x66E9, 0xC4E5, 0x6AFB, 0xC4E6, 0x6B04, 0xC4E7, 0x6AFA, 0xC4E8, 0x6BB2, + 0xC4E9, 0x704C, 0xC4EA, 0x721B, 0xC4EB, 0x72A7, 0xC4EC, 0x74D6, 0xC4ED, 0x74D4, 0xC4EE, 0x7669, 0xC4EF, 0x77D3, 0xC4F0, 0x7C50, + 0xC4F1, 0x7E8F, 0xC4F2, 0x7E8C, 0xC4F3, 0x7FBC, 0xC4F4, 0x8617, 0xC4F5, 0x862D, 0xC4F6, 0x861A, 0xC4F7, 0x8823, 0xC4F8, 0x8822, + 0xC4F9, 0x8821, 0xC4FA, 0x881F, 0xC4FB, 0x896A, 0xC4FC, 0x896C, 0xC4FD, 0x89BD, 0xC4FE, 0x8B74, 0xC540, 0x8B77, 0xC541, 0x8B7D, + 0xC542, 0x8D13, 0xC543, 0x8E8A, 0xC544, 0x8E8D, 0xC545, 0x8E8B, 0xC546, 0x8F5F, 0xC547, 0x8FAF, 0xC548, 0x91BA, 0xC549, 0x942E, + 0xC54A, 0x9433, 0xC54B, 0x9435, 0xC54C, 0x943A, 0xC54D, 0x9438, 0xC54E, 0x9432, 0xC54F, 0x942B, 0xC550, 0x95E2, 0xC551, 0x9738, + 0xC552, 0x9739, 0xC553, 0x9732, 0xC554, 0x97FF, 0xC555, 0x9867, 0xC556, 0x9865, 0xC557, 0x9957, 0xC558, 0x9A45, 0xC559, 0x9A43, + 0xC55A, 0x9A40, 0xC55B, 0x9A3E, 0xC55C, 0x9ACF, 0xC55D, 0x9B54, 0xC55E, 0x9B51, 0xC55F, 0x9C2D, 0xC560, 0x9C25, 0xC561, 0x9DAF, + 0xC562, 0x9DB4, 0xC563, 0x9DC2, 0xC564, 0x9DB8, 0xC565, 0x9E9D, 0xC566, 0x9EEF, 0xC567, 0x9F19, 0xC568, 0x9F5C, 0xC569, 0x9F66, + 0xC56A, 0x9F67, 0xC56B, 0x513C, 0xC56C, 0x513B, 0xC56D, 0x56C8, 0xC56E, 0x56CA, 0xC56F, 0x56C9, 0xC570, 0x5B7F, 0xC571, 0x5DD4, + 0xC572, 0x5DD2, 0xC573, 0x5F4E, 0xC574, 0x61FF, 0xC575, 0x6524, 0xC576, 0x6B0A, 0xC577, 0x6B61, 0xC578, 0x7051, 0xC579, 0x7058, + 0xC57A, 0x7380, 0xC57B, 0x74E4, 0xC57C, 0x758A, 0xC57D, 0x766E, 0xC57E, 0x766C, 0xC5A1, 0x79B3, 0xC5A2, 0x7C60, 0xC5A3, 0x7C5F, + 0xC5A4, 0x807E, 0xC5A5, 0x807D, 0xC5A6, 0x81DF, 0xC5A7, 0x8972, 0xC5A8, 0x896F, 0xC5A9, 0x89FC, 0xC5AA, 0x8B80, 0xC5AB, 0x8D16, + 0xC5AC, 0x8D17, 0xC5AD, 0x8E91, 0xC5AE, 0x8E93, 0xC5AF, 0x8F61, 0xC5B0, 0x9148, 0xC5B1, 0x9444, 0xC5B2, 0x9451, 0xC5B3, 0x9452, + 0xC5B4, 0x973D, 0xC5B5, 0x973E, 0xC5B6, 0x97C3, 0xC5B7, 0x97C1, 0xC5B8, 0x986B, 0xC5B9, 0x9955, 0xC5BA, 0x9A55, 0xC5BB, 0x9A4D, + 0xC5BC, 0x9AD2, 0xC5BD, 0x9B1A, 0xC5BE, 0x9C49, 0xC5BF, 0x9C31, 0xC5C0, 0x9C3E, 0xC5C1, 0x9C3B, 0xC5C2, 0x9DD3, 0xC5C3, 0x9DD7, + 0xC5C4, 0x9F34, 0xC5C5, 0x9F6C, 0xC5C6, 0x9F6A, 0xC5C7, 0x9F94, 0xC5C8, 0x56CC, 0xC5C9, 0x5DD6, 0xC5CA, 0x6200, 0xC5CB, 0x6523, + 0xC5CC, 0x652B, 0xC5CD, 0x652A, 0xC5CE, 0x66EC, 0xC5CF, 0x6B10, 0xC5D0, 0x74DA, 0xC5D1, 0x7ACA, 0xC5D2, 0x7C64, 0xC5D3, 0x7C63, + 0xC5D4, 0x7C65, 0xC5D5, 0x7E93, 0xC5D6, 0x7E96, 0xC5D7, 0x7E94, 0xC5D8, 0x81E2, 0xC5D9, 0x8638, 0xC5DA, 0x863F, 0xC5DB, 0x8831, + 0xC5DC, 0x8B8A, 0xC5DD, 0x9090, 0xC5DE, 0x908F, 0xC5DF, 0x9463, 0xC5E0, 0x9460, 0xC5E1, 0x9464, 0xC5E2, 0x9768, 0xC5E3, 0x986F, + 0xC5E4, 0x995C, 0xC5E5, 0x9A5A, 0xC5E6, 0x9A5B, 0xC5E7, 0x9A57, 0xC5E8, 0x9AD3, 0xC5E9, 0x9AD4, 0xC5EA, 0x9AD1, 0xC5EB, 0x9C54, + 0xC5EC, 0x9C57, 0xC5ED, 0x9C56, 0xC5EE, 0x9DE5, 0xC5EF, 0x9E9F, 0xC5F0, 0x9EF4, 0xC5F1, 0x56D1, 0xC5F2, 0x58E9, 0xC5F3, 0x652C, + 0xC5F4, 0x705E, 0xC5F5, 0x7671, 0xC5F6, 0x7672, 0xC5F7, 0x77D7, 0xC5F8, 0x7F50, 0xC5F9, 0x7F88, 0xC5FA, 0x8836, 0xC5FB, 0x8839, + 0xC5FC, 0x8862, 0xC5FD, 0x8B93, 0xC5FE, 0x8B92, 0xC640, 0x8B96, 0xC641, 0x8277, 0xC642, 0x8D1B, 0xC643, 0x91C0, 0xC644, 0x946A, + 0xC645, 0x9742, 0xC646, 0x9748, 0xC647, 0x9744, 0xC648, 0x97C6, 0xC649, 0x9870, 0xC64A, 0x9A5F, 0xC64B, 0x9B22, 0xC64C, 0x9B58, + 0xC64D, 0x9C5F, 0xC64E, 0x9DF9, 0xC64F, 0x9DFA, 0xC650, 0x9E7C, 0xC651, 0x9E7D, 0xC652, 0x9F07, 0xC653, 0x9F77, 0xC654, 0x9F72, + 0xC655, 0x5EF3, 0xC656, 0x6B16, 0xC657, 0x7063, 0xC658, 0x7C6C, 0xC659, 0x7C6E, 0xC65A, 0x883B, 0xC65B, 0x89C0, 0xC65C, 0x8EA1, + 0xC65D, 0x91C1, 0xC65E, 0x9472, 0xC65F, 0x9470, 0xC660, 0x9871, 0xC661, 0x995E, 0xC662, 0x9AD6, 0xC663, 0x9B23, 0xC664, 0x9ECC, + 0xC665, 0x7064, 0xC666, 0x77DA, 0xC667, 0x8B9A, 0xC668, 0x9477, 0xC669, 0x97C9, 0xC66A, 0x9A62, 0xC66B, 0x9A65, 0xC66C, 0x7E9C, + 0xC66D, 0x8B9C, 0xC66E, 0x8EAA, 0xC66F, 0x91C5, 0xC670, 0x947D, 0xC671, 0x947E, 0xC672, 0x947C, 0xC673, 0x9C77, 0xC674, 0x9C78, + 0xC675, 0x9EF7, 0xC676, 0x8C54, 0xC677, 0x947F, 0xC678, 0x9E1A, 0xC679, 0x7228, 0xC67A, 0x9A6A, 0xC67B, 0x9B31, 0xC67C, 0x9E1B, + 0xC67D, 0x9E1E, 0xC67E, 0x7C72, 0xC940, 0x4E42, 0xC941, 0x4E5C, 0xC942, 0x51F5, 0xC943, 0x531A, 0xC944, 0x5382, 0xC945, 0x4E07, + 0xC946, 0x4E0C, 0xC947, 0x4E47, 0xC948, 0x4E8D, 0xC949, 0x56D7, 0xC94A, 0xFA0C, 0xC94B, 0x5C6E, 0xC94C, 0x5F73, 0xC94D, 0x4E0F, + 0xC94E, 0x5187, 0xC94F, 0x4E0E, 0xC950, 0x4E2E, 0xC951, 0x4E93, 0xC952, 0x4EC2, 0xC953, 0x4EC9, 0xC954, 0x4EC8, 0xC955, 0x5198, + 0xC956, 0x52FC, 0xC957, 0x536C, 0xC958, 0x53B9, 0xC959, 0x5720, 0xC95A, 0x5903, 0xC95B, 0x592C, 0xC95C, 0x5C10, 0xC95D, 0x5DFF, + 0xC95E, 0x65E1, 0xC95F, 0x6BB3, 0xC960, 0x6BCC, 0xC961, 0x6C14, 0xC962, 0x723F, 0xC963, 0x4E31, 0xC964, 0x4E3C, 0xC965, 0x4EE8, + 0xC966, 0x4EDC, 0xC967, 0x4EE9, 0xC968, 0x4EE1, 0xC969, 0x4EDD, 0xC96A, 0x4EDA, 0xC96B, 0x520C, 0xC96C, 0x531C, 0xC96D, 0x534C, + 0xC96E, 0x5722, 0xC96F, 0x5723, 0xC970, 0x5917, 0xC971, 0x592F, 0xC972, 0x5B81, 0xC973, 0x5B84, 0xC974, 0x5C12, 0xC975, 0x5C3B, + 0xC976, 0x5C74, 0xC977, 0x5C73, 0xC978, 0x5E04, 0xC979, 0x5E80, 0xC97A, 0x5E82, 0xC97B, 0x5FC9, 0xC97C, 0x6209, 0xC97D, 0x6250, + 0xC97E, 0x6C15, 0xC9A1, 0x6C36, 0xC9A2, 0x6C43, 0xC9A3, 0x6C3F, 0xC9A4, 0x6C3B, 0xC9A5, 0x72AE, 0xC9A6, 0x72B0, 0xC9A7, 0x738A, + 0xC9A8, 0x79B8, 0xC9A9, 0x808A, 0xC9AA, 0x961E, 0xC9AB, 0x4F0E, 0xC9AC, 0x4F18, 0xC9AD, 0x4F2C, 0xC9AE, 0x4EF5, 0xC9AF, 0x4F14, + 0xC9B0, 0x4EF1, 0xC9B1, 0x4F00, 0xC9B2, 0x4EF7, 0xC9B3, 0x4F08, 0xC9B4, 0x4F1D, 0xC9B5, 0x4F02, 0xC9B6, 0x4F05, 0xC9B7, 0x4F22, + 0xC9B8, 0x4F13, 0xC9B9, 0x4F04, 0xC9BA, 0x4EF4, 0xC9BB, 0x4F12, 0xC9BC, 0x51B1, 0xC9BD, 0x5213, 0xC9BE, 0x5209, 0xC9BF, 0x5210, + 0xC9C0, 0x52A6, 0xC9C1, 0x5322, 0xC9C2, 0x531F, 0xC9C3, 0x534D, 0xC9C4, 0x538A, 0xC9C5, 0x5407, 0xC9C6, 0x56E1, 0xC9C7, 0x56DF, + 0xC9C8, 0x572E, 0xC9C9, 0x572A, 0xC9CA, 0x5734, 0xC9CB, 0x593C, 0xC9CC, 0x5980, 0xC9CD, 0x597C, 0xC9CE, 0x5985, 0xC9CF, 0x597B, + 0xC9D0, 0x597E, 0xC9D1, 0x5977, 0xC9D2, 0x597F, 0xC9D3, 0x5B56, 0xC9D4, 0x5C15, 0xC9D5, 0x5C25, 0xC9D6, 0x5C7C, 0xC9D7, 0x5C7A, + 0xC9D8, 0x5C7B, 0xC9D9, 0x5C7E, 0xC9DA, 0x5DDF, 0xC9DB, 0x5E75, 0xC9DC, 0x5E84, 0xC9DD, 0x5F02, 0xC9DE, 0x5F1A, 0xC9DF, 0x5F74, + 0xC9E0, 0x5FD5, 0xC9E1, 0x5FD4, 0xC9E2, 0x5FCF, 0xC9E3, 0x625C, 0xC9E4, 0x625E, 0xC9E5, 0x6264, 0xC9E6, 0x6261, 0xC9E7, 0x6266, + 0xC9E8, 0x6262, 0xC9E9, 0x6259, 0xC9EA, 0x6260, 0xC9EB, 0x625A, 0xC9EC, 0x6265, 0xC9ED, 0x65EF, 0xC9EE, 0x65EE, 0xC9EF, 0x673E, + 0xC9F0, 0x6739, 0xC9F1, 0x6738, 0xC9F2, 0x673B, 0xC9F3, 0x673A, 0xC9F4, 0x673F, 0xC9F5, 0x673C, 0xC9F6, 0x6733, 0xC9F7, 0x6C18, + 0xC9F8, 0x6C46, 0xC9F9, 0x6C52, 0xC9FA, 0x6C5C, 0xC9FB, 0x6C4F, 0xC9FC, 0x6C4A, 0xC9FD, 0x6C54, 0xC9FE, 0x6C4B, 0xCA40, 0x6C4C, + 0xCA41, 0x7071, 0xCA42, 0x725E, 0xCA43, 0x72B4, 0xCA44, 0x72B5, 0xCA45, 0x738E, 0xCA46, 0x752A, 0xCA47, 0x767F, 0xCA48, 0x7A75, + 0xCA49, 0x7F51, 0xCA4A, 0x8278, 0xCA4B, 0x827C, 0xCA4C, 0x8280, 0xCA4D, 0x827D, 0xCA4E, 0x827F, 0xCA4F, 0x864D, 0xCA50, 0x897E, + 0xCA51, 0x9099, 0xCA52, 0x9097, 0xCA53, 0x9098, 0xCA54, 0x909B, 0xCA55, 0x9094, 0xCA56, 0x9622, 0xCA57, 0x9624, 0xCA58, 0x9620, + 0xCA59, 0x9623, 0xCA5A, 0x4F56, 0xCA5B, 0x4F3B, 0xCA5C, 0x4F62, 0xCA5D, 0x4F49, 0xCA5E, 0x4F53, 0xCA5F, 0x4F64, 0xCA60, 0x4F3E, + 0xCA61, 0x4F67, 0xCA62, 0x4F52, 0xCA63, 0x4F5F, 0xCA64, 0x4F41, 0xCA65, 0x4F58, 0xCA66, 0x4F2D, 0xCA67, 0x4F33, 0xCA68, 0x4F3F, + 0xCA69, 0x4F61, 0xCA6A, 0x518F, 0xCA6B, 0x51B9, 0xCA6C, 0x521C, 0xCA6D, 0x521E, 0xCA6E, 0x5221, 0xCA6F, 0x52AD, 0xCA70, 0x52AE, + 0xCA71, 0x5309, 0xCA72, 0x5363, 0xCA73, 0x5372, 0xCA74, 0x538E, 0xCA75, 0x538F, 0xCA76, 0x5430, 0xCA77, 0x5437, 0xCA78, 0x542A, + 0xCA79, 0x5454, 0xCA7A, 0x5445, 0xCA7B, 0x5419, 0xCA7C, 0x541C, 0xCA7D, 0x5425, 0xCA7E, 0x5418, 0xCAA1, 0x543D, 0xCAA2, 0x544F, + 0xCAA3, 0x5441, 0xCAA4, 0x5428, 0xCAA5, 0x5424, 0xCAA6, 0x5447, 0xCAA7, 0x56EE, 0xCAA8, 0x56E7, 0xCAA9, 0x56E5, 0xCAAA, 0x5741, + 0xCAAB, 0x5745, 0xCAAC, 0x574C, 0xCAAD, 0x5749, 0xCAAE, 0x574B, 0xCAAF, 0x5752, 0xCAB0, 0x5906, 0xCAB1, 0x5940, 0xCAB2, 0x59A6, + 0xCAB3, 0x5998, 0xCAB4, 0x59A0, 0xCAB5, 0x5997, 0xCAB6, 0x598E, 0xCAB7, 0x59A2, 0xCAB8, 0x5990, 0xCAB9, 0x598F, 0xCABA, 0x59A7, + 0xCABB, 0x59A1, 0xCABC, 0x5B8E, 0xCABD, 0x5B92, 0xCABE, 0x5C28, 0xCABF, 0x5C2A, 0xCAC0, 0x5C8D, 0xCAC1, 0x5C8F, 0xCAC2, 0x5C88, + 0xCAC3, 0x5C8B, 0xCAC4, 0x5C89, 0xCAC5, 0x5C92, 0xCAC6, 0x5C8A, 0xCAC7, 0x5C86, 0xCAC8, 0x5C93, 0xCAC9, 0x5C95, 0xCACA, 0x5DE0, + 0xCACB, 0x5E0A, 0xCACC, 0x5E0E, 0xCACD, 0x5E8B, 0xCACE, 0x5E89, 0xCACF, 0x5E8C, 0xCAD0, 0x5E88, 0xCAD1, 0x5E8D, 0xCAD2, 0x5F05, + 0xCAD3, 0x5F1D, 0xCAD4, 0x5F78, 0xCAD5, 0x5F76, 0xCAD6, 0x5FD2, 0xCAD7, 0x5FD1, 0xCAD8, 0x5FD0, 0xCAD9, 0x5FED, 0xCADA, 0x5FE8, + 0xCADB, 0x5FEE, 0xCADC, 0x5FF3, 0xCADD, 0x5FE1, 0xCADE, 0x5FE4, 0xCADF, 0x5FE3, 0xCAE0, 0x5FFA, 0xCAE1, 0x5FEF, 0xCAE2, 0x5FF7, + 0xCAE3, 0x5FFB, 0xCAE4, 0x6000, 0xCAE5, 0x5FF4, 0xCAE6, 0x623A, 0xCAE7, 0x6283, 0xCAE8, 0x628C, 0xCAE9, 0x628E, 0xCAEA, 0x628F, + 0xCAEB, 0x6294, 0xCAEC, 0x6287, 0xCAED, 0x6271, 0xCAEE, 0x627B, 0xCAEF, 0x627A, 0xCAF0, 0x6270, 0xCAF1, 0x6281, 0xCAF2, 0x6288, + 0xCAF3, 0x6277, 0xCAF4, 0x627D, 0xCAF5, 0x6272, 0xCAF6, 0x6274, 0xCAF7, 0x6537, 0xCAF8, 0x65F0, 0xCAF9, 0x65F4, 0xCAFA, 0x65F3, + 0xCAFB, 0x65F2, 0xCAFC, 0x65F5, 0xCAFD, 0x6745, 0xCAFE, 0x6747, 0xCB40, 0x6759, 0xCB41, 0x6755, 0xCB42, 0x674C, 0xCB43, 0x6748, + 0xCB44, 0x675D, 0xCB45, 0x674D, 0xCB46, 0x675A, 0xCB47, 0x674B, 0xCB48, 0x6BD0, 0xCB49, 0x6C19, 0xCB4A, 0x6C1A, 0xCB4B, 0x6C78, + 0xCB4C, 0x6C67, 0xCB4D, 0x6C6B, 0xCB4E, 0x6C84, 0xCB4F, 0x6C8B, 0xCB50, 0x6C8F, 0xCB51, 0x6C71, 0xCB52, 0x6C6F, 0xCB53, 0x6C69, + 0xCB54, 0x6C9A, 0xCB55, 0x6C6D, 0xCB56, 0x6C87, 0xCB57, 0x6C95, 0xCB58, 0x6C9C, 0xCB59, 0x6C66, 0xCB5A, 0x6C73, 0xCB5B, 0x6C65, + 0xCB5C, 0x6C7B, 0xCB5D, 0x6C8E, 0xCB5E, 0x7074, 0xCB5F, 0x707A, 0xCB60, 0x7263, 0xCB61, 0x72BF, 0xCB62, 0x72BD, 0xCB63, 0x72C3, + 0xCB64, 0x72C6, 0xCB65, 0x72C1, 0xCB66, 0x72BA, 0xCB67, 0x72C5, 0xCB68, 0x7395, 0xCB69, 0x7397, 0xCB6A, 0x7393, 0xCB6B, 0x7394, + 0xCB6C, 0x7392, 0xCB6D, 0x753A, 0xCB6E, 0x7539, 0xCB6F, 0x7594, 0xCB70, 0x7595, 0xCB71, 0x7681, 0xCB72, 0x793D, 0xCB73, 0x8034, + 0xCB74, 0x8095, 0xCB75, 0x8099, 0xCB76, 0x8090, 0xCB77, 0x8092, 0xCB78, 0x809C, 0xCB79, 0x8290, 0xCB7A, 0x828F, 0xCB7B, 0x8285, + 0xCB7C, 0x828E, 0xCB7D, 0x8291, 0xCB7E, 0x8293, 0xCBA1, 0x828A, 0xCBA2, 0x8283, 0xCBA3, 0x8284, 0xCBA4, 0x8C78, 0xCBA5, 0x8FC9, + 0xCBA6, 0x8FBF, 0xCBA7, 0x909F, 0xCBA8, 0x90A1, 0xCBA9, 0x90A5, 0xCBAA, 0x909E, 0xCBAB, 0x90A7, 0xCBAC, 0x90A0, 0xCBAD, 0x9630, + 0xCBAE, 0x9628, 0xCBAF, 0x962F, 0xCBB0, 0x962D, 0xCBB1, 0x4E33, 0xCBB2, 0x4F98, 0xCBB3, 0x4F7C, 0xCBB4, 0x4F85, 0xCBB5, 0x4F7D, + 0xCBB6, 0x4F80, 0xCBB7, 0x4F87, 0xCBB8, 0x4F76, 0xCBB9, 0x4F74, 0xCBBA, 0x4F89, 0xCBBB, 0x4F84, 0xCBBC, 0x4F77, 0xCBBD, 0x4F4C, + 0xCBBE, 0x4F97, 0xCBBF, 0x4F6A, 0xCBC0, 0x4F9A, 0xCBC1, 0x4F79, 0xCBC2, 0x4F81, 0xCBC3, 0x4F78, 0xCBC4, 0x4F90, 0xCBC5, 0x4F9C, + 0xCBC6, 0x4F94, 0xCBC7, 0x4F9E, 0xCBC8, 0x4F92, 0xCBC9, 0x4F82, 0xCBCA, 0x4F95, 0xCBCB, 0x4F6B, 0xCBCC, 0x4F6E, 0xCBCD, 0x519E, + 0xCBCE, 0x51BC, 0xCBCF, 0x51BE, 0xCBD0, 0x5235, 0xCBD1, 0x5232, 0xCBD2, 0x5233, 0xCBD3, 0x5246, 0xCBD4, 0x5231, 0xCBD5, 0x52BC, + 0xCBD6, 0x530A, 0xCBD7, 0x530B, 0xCBD8, 0x533C, 0xCBD9, 0x5392, 0xCBDA, 0x5394, 0xCBDB, 0x5487, 0xCBDC, 0x547F, 0xCBDD, 0x5481, + 0xCBDE, 0x5491, 0xCBDF, 0x5482, 0xCBE0, 0x5488, 0xCBE1, 0x546B, 0xCBE2, 0x547A, 0xCBE3, 0x547E, 0xCBE4, 0x5465, 0xCBE5, 0x546C, + 0xCBE6, 0x5474, 0xCBE7, 0x5466, 0xCBE8, 0x548D, 0xCBE9, 0x546F, 0xCBEA, 0x5461, 0xCBEB, 0x5460, 0xCBEC, 0x5498, 0xCBED, 0x5463, + 0xCBEE, 0x5467, 0xCBEF, 0x5464, 0xCBF0, 0x56F7, 0xCBF1, 0x56F9, 0xCBF2, 0x576F, 0xCBF3, 0x5772, 0xCBF4, 0x576D, 0xCBF5, 0x576B, + 0xCBF6, 0x5771, 0xCBF7, 0x5770, 0xCBF8, 0x5776, 0xCBF9, 0x5780, 0xCBFA, 0x5775, 0xCBFB, 0x577B, 0xCBFC, 0x5773, 0xCBFD, 0x5774, + 0xCBFE, 0x5762, 0xCC40, 0x5768, 0xCC41, 0x577D, 0xCC42, 0x590C, 0xCC43, 0x5945, 0xCC44, 0x59B5, 0xCC45, 0x59BA, 0xCC46, 0x59CF, + 0xCC47, 0x59CE, 0xCC48, 0x59B2, 0xCC49, 0x59CC, 0xCC4A, 0x59C1, 0xCC4B, 0x59B6, 0xCC4C, 0x59BC, 0xCC4D, 0x59C3, 0xCC4E, 0x59D6, + 0xCC4F, 0x59B1, 0xCC50, 0x59BD, 0xCC51, 0x59C0, 0xCC52, 0x59C8, 0xCC53, 0x59B4, 0xCC54, 0x59C7, 0xCC55, 0x5B62, 0xCC56, 0x5B65, + 0xCC57, 0x5B93, 0xCC58, 0x5B95, 0xCC59, 0x5C44, 0xCC5A, 0x5C47, 0xCC5B, 0x5CAE, 0xCC5C, 0x5CA4, 0xCC5D, 0x5CA0, 0xCC5E, 0x5CB5, + 0xCC5F, 0x5CAF, 0xCC60, 0x5CA8, 0xCC61, 0x5CAC, 0xCC62, 0x5C9F, 0xCC63, 0x5CA3, 0xCC64, 0x5CAD, 0xCC65, 0x5CA2, 0xCC66, 0x5CAA, + 0xCC67, 0x5CA7, 0xCC68, 0x5C9D, 0xCC69, 0x5CA5, 0xCC6A, 0x5CB6, 0xCC6B, 0x5CB0, 0xCC6C, 0x5CA6, 0xCC6D, 0x5E17, 0xCC6E, 0x5E14, + 0xCC6F, 0x5E19, 0xCC70, 0x5F28, 0xCC71, 0x5F22, 0xCC72, 0x5F23, 0xCC73, 0x5F24, 0xCC74, 0x5F54, 0xCC75, 0x5F82, 0xCC76, 0x5F7E, + 0xCC77, 0x5F7D, 0xCC78, 0x5FDE, 0xCC79, 0x5FE5, 0xCC7A, 0x602D, 0xCC7B, 0x6026, 0xCC7C, 0x6019, 0xCC7D, 0x6032, 0xCC7E, 0x600B, + 0xCCA1, 0x6034, 0xCCA2, 0x600A, 0xCCA3, 0x6017, 0xCCA4, 0x6033, 0xCCA5, 0x601A, 0xCCA6, 0x601E, 0xCCA7, 0x602C, 0xCCA8, 0x6022, + 0xCCA9, 0x600D, 0xCCAA, 0x6010, 0xCCAB, 0x602E, 0xCCAC, 0x6013, 0xCCAD, 0x6011, 0xCCAE, 0x600C, 0xCCAF, 0x6009, 0xCCB0, 0x601C, + 0xCCB1, 0x6214, 0xCCB2, 0x623D, 0xCCB3, 0x62AD, 0xCCB4, 0x62B4, 0xCCB5, 0x62D1, 0xCCB6, 0x62BE, 0xCCB7, 0x62AA, 0xCCB8, 0x62B6, + 0xCCB9, 0x62CA, 0xCCBA, 0x62AE, 0xCCBB, 0x62B3, 0xCCBC, 0x62AF, 0xCCBD, 0x62BB, 0xCCBE, 0x62A9, 0xCCBF, 0x62B0, 0xCCC0, 0x62B8, + 0xCCC1, 0x653D, 0xCCC2, 0x65A8, 0xCCC3, 0x65BB, 0xCCC4, 0x6609, 0xCCC5, 0x65FC, 0xCCC6, 0x6604, 0xCCC7, 0x6612, 0xCCC8, 0x6608, + 0xCCC9, 0x65FB, 0xCCCA, 0x6603, 0xCCCB, 0x660B, 0xCCCC, 0x660D, 0xCCCD, 0x6605, 0xCCCE, 0x65FD, 0xCCCF, 0x6611, 0xCCD0, 0x6610, + 0xCCD1, 0x66F6, 0xCCD2, 0x670A, 0xCCD3, 0x6785, 0xCCD4, 0x676C, 0xCCD5, 0x678E, 0xCCD6, 0x6792, 0xCCD7, 0x6776, 0xCCD8, 0x677B, + 0xCCD9, 0x6798, 0xCCDA, 0x6786, 0xCCDB, 0x6784, 0xCCDC, 0x6774, 0xCCDD, 0x678D, 0xCCDE, 0x678C, 0xCCDF, 0x677A, 0xCCE0, 0x679F, + 0xCCE1, 0x6791, 0xCCE2, 0x6799, 0xCCE3, 0x6783, 0xCCE4, 0x677D, 0xCCE5, 0x6781, 0xCCE6, 0x6778, 0xCCE7, 0x6779, 0xCCE8, 0x6794, + 0xCCE9, 0x6B25, 0xCCEA, 0x6B80, 0xCCEB, 0x6B7E, 0xCCEC, 0x6BDE, 0xCCED, 0x6C1D, 0xCCEE, 0x6C93, 0xCCEF, 0x6CEC, 0xCCF0, 0x6CEB, + 0xCCF1, 0x6CEE, 0xCCF2, 0x6CD9, 0xCCF3, 0x6CB6, 0xCCF4, 0x6CD4, 0xCCF5, 0x6CAD, 0xCCF6, 0x6CE7, 0xCCF7, 0x6CB7, 0xCCF8, 0x6CD0, + 0xCCF9, 0x6CC2, 0xCCFA, 0x6CBA, 0xCCFB, 0x6CC3, 0xCCFC, 0x6CC6, 0xCCFD, 0x6CED, 0xCCFE, 0x6CF2, 0xCD40, 0x6CD2, 0xCD41, 0x6CDD, + 0xCD42, 0x6CB4, 0xCD43, 0x6C8A, 0xCD44, 0x6C9D, 0xCD45, 0x6C80, 0xCD46, 0x6CDE, 0xCD47, 0x6CC0, 0xCD48, 0x6D30, 0xCD49, 0x6CCD, + 0xCD4A, 0x6CC7, 0xCD4B, 0x6CB0, 0xCD4C, 0x6CF9, 0xCD4D, 0x6CCF, 0xCD4E, 0x6CE9, 0xCD4F, 0x6CD1, 0xCD50, 0x7094, 0xCD51, 0x7098, + 0xCD52, 0x7085, 0xCD53, 0x7093, 0xCD54, 0x7086, 0xCD55, 0x7084, 0xCD56, 0x7091, 0xCD57, 0x7096, 0xCD58, 0x7082, 0xCD59, 0x709A, + 0xCD5A, 0x7083, 0xCD5B, 0x726A, 0xCD5C, 0x72D6, 0xCD5D, 0x72CB, 0xCD5E, 0x72D8, 0xCD5F, 0x72C9, 0xCD60, 0x72DC, 0xCD61, 0x72D2, + 0xCD62, 0x72D4, 0xCD63, 0x72DA, 0xCD64, 0x72CC, 0xCD65, 0x72D1, 0xCD66, 0x73A4, 0xCD67, 0x73A1, 0xCD68, 0x73AD, 0xCD69, 0x73A6, + 0xCD6A, 0x73A2, 0xCD6B, 0x73A0, 0xCD6C, 0x73AC, 0xCD6D, 0x739D, 0xCD6E, 0x74DD, 0xCD6F, 0x74E8, 0xCD70, 0x753F, 0xCD71, 0x7540, + 0xCD72, 0x753E, 0xCD73, 0x758C, 0xCD74, 0x7598, 0xCD75, 0x76AF, 0xCD76, 0x76F3, 0xCD77, 0x76F1, 0xCD78, 0x76F0, 0xCD79, 0x76F5, + 0xCD7A, 0x77F8, 0xCD7B, 0x77FC, 0xCD7C, 0x77F9, 0xCD7D, 0x77FB, 0xCD7E, 0x77FA, 0xCDA1, 0x77F7, 0xCDA2, 0x7942, 0xCDA3, 0x793F, + 0xCDA4, 0x79C5, 0xCDA5, 0x7A78, 0xCDA6, 0x7A7B, 0xCDA7, 0x7AFB, 0xCDA8, 0x7C75, 0xCDA9, 0x7CFD, 0xCDAA, 0x8035, 0xCDAB, 0x808F, + 0xCDAC, 0x80AE, 0xCDAD, 0x80A3, 0xCDAE, 0x80B8, 0xCDAF, 0x80B5, 0xCDB0, 0x80AD, 0xCDB1, 0x8220, 0xCDB2, 0x82A0, 0xCDB3, 0x82C0, + 0xCDB4, 0x82AB, 0xCDB5, 0x829A, 0xCDB6, 0x8298, 0xCDB7, 0x829B, 0xCDB8, 0x82B5, 0xCDB9, 0x82A7, 0xCDBA, 0x82AE, 0xCDBB, 0x82BC, + 0xCDBC, 0x829E, 0xCDBD, 0x82BA, 0xCDBE, 0x82B4, 0xCDBF, 0x82A8, 0xCDC0, 0x82A1, 0xCDC1, 0x82A9, 0xCDC2, 0x82C2, 0xCDC3, 0x82A4, + 0xCDC4, 0x82C3, 0xCDC5, 0x82B6, 0xCDC6, 0x82A2, 0xCDC7, 0x8670, 0xCDC8, 0x866F, 0xCDC9, 0x866D, 0xCDCA, 0x866E, 0xCDCB, 0x8C56, + 0xCDCC, 0x8FD2, 0xCDCD, 0x8FCB, 0xCDCE, 0x8FD3, 0xCDCF, 0x8FCD, 0xCDD0, 0x8FD6, 0xCDD1, 0x8FD5, 0xCDD2, 0x8FD7, 0xCDD3, 0x90B2, + 0xCDD4, 0x90B4, 0xCDD5, 0x90AF, 0xCDD6, 0x90B3, 0xCDD7, 0x90B0, 0xCDD8, 0x9639, 0xCDD9, 0x963D, 0xCDDA, 0x963C, 0xCDDB, 0x963A, + 0xCDDC, 0x9643, 0xCDDD, 0x4FCD, 0xCDDE, 0x4FC5, 0xCDDF, 0x4FD3, 0xCDE0, 0x4FB2, 0xCDE1, 0x4FC9, 0xCDE2, 0x4FCB, 0xCDE3, 0x4FC1, + 0xCDE4, 0x4FD4, 0xCDE5, 0x4FDC, 0xCDE6, 0x4FD9, 0xCDE7, 0x4FBB, 0xCDE8, 0x4FB3, 0xCDE9, 0x4FDB, 0xCDEA, 0x4FC7, 0xCDEB, 0x4FD6, + 0xCDEC, 0x4FBA, 0xCDED, 0x4FC0, 0xCDEE, 0x4FB9, 0xCDEF, 0x4FEC, 0xCDF0, 0x5244, 0xCDF1, 0x5249, 0xCDF2, 0x52C0, 0xCDF3, 0x52C2, + 0xCDF4, 0x533D, 0xCDF5, 0x537C, 0xCDF6, 0x5397, 0xCDF7, 0x5396, 0xCDF8, 0x5399, 0xCDF9, 0x5398, 0xCDFA, 0x54BA, 0xCDFB, 0x54A1, + 0xCDFC, 0x54AD, 0xCDFD, 0x54A5, 0xCDFE, 0x54CF, 0xCE40, 0x54C3, 0xCE41, 0x830D, 0xCE42, 0x54B7, 0xCE43, 0x54AE, 0xCE44, 0x54D6, + 0xCE45, 0x54B6, 0xCE46, 0x54C5, 0xCE47, 0x54C6, 0xCE48, 0x54A0, 0xCE49, 0x5470, 0xCE4A, 0x54BC, 0xCE4B, 0x54A2, 0xCE4C, 0x54BE, + 0xCE4D, 0x5472, 0xCE4E, 0x54DE, 0xCE4F, 0x54B0, 0xCE50, 0x57B5, 0xCE51, 0x579E, 0xCE52, 0x579F, 0xCE53, 0x57A4, 0xCE54, 0x578C, + 0xCE55, 0x5797, 0xCE56, 0x579D, 0xCE57, 0x579B, 0xCE58, 0x5794, 0xCE59, 0x5798, 0xCE5A, 0x578F, 0xCE5B, 0x5799, 0xCE5C, 0x57A5, + 0xCE5D, 0x579A, 0xCE5E, 0x5795, 0xCE5F, 0x58F4, 0xCE60, 0x590D, 0xCE61, 0x5953, 0xCE62, 0x59E1, 0xCE63, 0x59DE, 0xCE64, 0x59EE, + 0xCE65, 0x5A00, 0xCE66, 0x59F1, 0xCE67, 0x59DD, 0xCE68, 0x59FA, 0xCE69, 0x59FD, 0xCE6A, 0x59FC, 0xCE6B, 0x59F6, 0xCE6C, 0x59E4, + 0xCE6D, 0x59F2, 0xCE6E, 0x59F7, 0xCE6F, 0x59DB, 0xCE70, 0x59E9, 0xCE71, 0x59F3, 0xCE72, 0x59F5, 0xCE73, 0x59E0, 0xCE74, 0x59FE, + 0xCE75, 0x59F4, 0xCE76, 0x59ED, 0xCE77, 0x5BA8, 0xCE78, 0x5C4C, 0xCE79, 0x5CD0, 0xCE7A, 0x5CD8, 0xCE7B, 0x5CCC, 0xCE7C, 0x5CD7, + 0xCE7D, 0x5CCB, 0xCE7E, 0x5CDB, 0xCEA1, 0x5CDE, 0xCEA2, 0x5CDA, 0xCEA3, 0x5CC9, 0xCEA4, 0x5CC7, 0xCEA5, 0x5CCA, 0xCEA6, 0x5CD6, + 0xCEA7, 0x5CD3, 0xCEA8, 0x5CD4, 0xCEA9, 0x5CCF, 0xCEAA, 0x5CC8, 0xCEAB, 0x5CC6, 0xCEAC, 0x5CCE, 0xCEAD, 0x5CDF, 0xCEAE, 0x5CF8, + 0xCEAF, 0x5DF9, 0xCEB0, 0x5E21, 0xCEB1, 0x5E22, 0xCEB2, 0x5E23, 0xCEB3, 0x5E20, 0xCEB4, 0x5E24, 0xCEB5, 0x5EB0, 0xCEB6, 0x5EA4, + 0xCEB7, 0x5EA2, 0xCEB8, 0x5E9B, 0xCEB9, 0x5EA3, 0xCEBA, 0x5EA5, 0xCEBB, 0x5F07, 0xCEBC, 0x5F2E, 0xCEBD, 0x5F56, 0xCEBE, 0x5F86, + 0xCEBF, 0x6037, 0xCEC0, 0x6039, 0xCEC1, 0x6054, 0xCEC2, 0x6072, 0xCEC3, 0x605E, 0xCEC4, 0x6045, 0xCEC5, 0x6053, 0xCEC6, 0x6047, + 0xCEC7, 0x6049, 0xCEC8, 0x605B, 0xCEC9, 0x604C, 0xCECA, 0x6040, 0xCECB, 0x6042, 0xCECC, 0x605F, 0xCECD, 0x6024, 0xCECE, 0x6044, + 0xCECF, 0x6058, 0xCED0, 0x6066, 0xCED1, 0x606E, 0xCED2, 0x6242, 0xCED3, 0x6243, 0xCED4, 0x62CF, 0xCED5, 0x630D, 0xCED6, 0x630B, + 0xCED7, 0x62F5, 0xCED8, 0x630E, 0xCED9, 0x6303, 0xCEDA, 0x62EB, 0xCEDB, 0x62F9, 0xCEDC, 0x630F, 0xCEDD, 0x630C, 0xCEDE, 0x62F8, + 0xCEDF, 0x62F6, 0xCEE0, 0x6300, 0xCEE1, 0x6313, 0xCEE2, 0x6314, 0xCEE3, 0x62FA, 0xCEE4, 0x6315, 0xCEE5, 0x62FB, 0xCEE6, 0x62F0, + 0xCEE7, 0x6541, 0xCEE8, 0x6543, 0xCEE9, 0x65AA, 0xCEEA, 0x65BF, 0xCEEB, 0x6636, 0xCEEC, 0x6621, 0xCEED, 0x6632, 0xCEEE, 0x6635, + 0xCEEF, 0x661C, 0xCEF0, 0x6626, 0xCEF1, 0x6622, 0xCEF2, 0x6633, 0xCEF3, 0x662B, 0xCEF4, 0x663A, 0xCEF5, 0x661D, 0xCEF6, 0x6634, + 0xCEF7, 0x6639, 0xCEF8, 0x662E, 0xCEF9, 0x670F, 0xCEFA, 0x6710, 0xCEFB, 0x67C1, 0xCEFC, 0x67F2, 0xCEFD, 0x67C8, 0xCEFE, 0x67BA, + 0xCF40, 0x67DC, 0xCF41, 0x67BB, 0xCF42, 0x67F8, 0xCF43, 0x67D8, 0xCF44, 0x67C0, 0xCF45, 0x67B7, 0xCF46, 0x67C5, 0xCF47, 0x67EB, + 0xCF48, 0x67E4, 0xCF49, 0x67DF, 0xCF4A, 0x67B5, 0xCF4B, 0x67CD, 0xCF4C, 0x67B3, 0xCF4D, 0x67F7, 0xCF4E, 0x67F6, 0xCF4F, 0x67EE, + 0xCF50, 0x67E3, 0xCF51, 0x67C2, 0xCF52, 0x67B9, 0xCF53, 0x67CE, 0xCF54, 0x67E7, 0xCF55, 0x67F0, 0xCF56, 0x67B2, 0xCF57, 0x67FC, + 0xCF58, 0x67C6, 0xCF59, 0x67ED, 0xCF5A, 0x67CC, 0xCF5B, 0x67AE, 0xCF5C, 0x67E6, 0xCF5D, 0x67DB, 0xCF5E, 0x67FA, 0xCF5F, 0x67C9, + 0xCF60, 0x67CA, 0xCF61, 0x67C3, 0xCF62, 0x67EA, 0xCF63, 0x67CB, 0xCF64, 0x6B28, 0xCF65, 0x6B82, 0xCF66, 0x6B84, 0xCF67, 0x6BB6, + 0xCF68, 0x6BD6, 0xCF69, 0x6BD8, 0xCF6A, 0x6BE0, 0xCF6B, 0x6C20, 0xCF6C, 0x6C21, 0xCF6D, 0x6D28, 0xCF6E, 0x6D34, 0xCF6F, 0x6D2D, + 0xCF70, 0x6D1F, 0xCF71, 0x6D3C, 0xCF72, 0x6D3F, 0xCF73, 0x6D12, 0xCF74, 0x6D0A, 0xCF75, 0x6CDA, 0xCF76, 0x6D33, 0xCF77, 0x6D04, + 0xCF78, 0x6D19, 0xCF79, 0x6D3A, 0xCF7A, 0x6D1A, 0xCF7B, 0x6D11, 0xCF7C, 0x6D00, 0xCF7D, 0x6D1D, 0xCF7E, 0x6D42, 0xCFA1, 0x6D01, + 0xCFA2, 0x6D18, 0xCFA3, 0x6D37, 0xCFA4, 0x6D03, 0xCFA5, 0x6D0F, 0xCFA6, 0x6D40, 0xCFA7, 0x6D07, 0xCFA8, 0x6D20, 0xCFA9, 0x6D2C, + 0xCFAA, 0x6D08, 0xCFAB, 0x6D22, 0xCFAC, 0x6D09, 0xCFAD, 0x6D10, 0xCFAE, 0x70B7, 0xCFAF, 0x709F, 0xCFB0, 0x70BE, 0xCFB1, 0x70B1, + 0xCFB2, 0x70B0, 0xCFB3, 0x70A1, 0xCFB4, 0x70B4, 0xCFB5, 0x70B5, 0xCFB6, 0x70A9, 0xCFB7, 0x7241, 0xCFB8, 0x7249, 0xCFB9, 0x724A, + 0xCFBA, 0x726C, 0xCFBB, 0x7270, 0xCFBC, 0x7273, 0xCFBD, 0x726E, 0xCFBE, 0x72CA, 0xCFBF, 0x72E4, 0xCFC0, 0x72E8, 0xCFC1, 0x72EB, + 0xCFC2, 0x72DF, 0xCFC3, 0x72EA, 0xCFC4, 0x72E6, 0xCFC5, 0x72E3, 0xCFC6, 0x7385, 0xCFC7, 0x73CC, 0xCFC8, 0x73C2, 0xCFC9, 0x73C8, + 0xCFCA, 0x73C5, 0xCFCB, 0x73B9, 0xCFCC, 0x73B6, 0xCFCD, 0x73B5, 0xCFCE, 0x73B4, 0xCFCF, 0x73EB, 0xCFD0, 0x73BF, 0xCFD1, 0x73C7, + 0xCFD2, 0x73BE, 0xCFD3, 0x73C3, 0xCFD4, 0x73C6, 0xCFD5, 0x73B8, 0xCFD6, 0x73CB, 0xCFD7, 0x74EC, 0xCFD8, 0x74EE, 0xCFD9, 0x752E, + 0xCFDA, 0x7547, 0xCFDB, 0x7548, 0xCFDC, 0x75A7, 0xCFDD, 0x75AA, 0xCFDE, 0x7679, 0xCFDF, 0x76C4, 0xCFE0, 0x7708, 0xCFE1, 0x7703, + 0xCFE2, 0x7704, 0xCFE3, 0x7705, 0xCFE4, 0x770A, 0xCFE5, 0x76F7, 0xCFE6, 0x76FB, 0xCFE7, 0x76FA, 0xCFE8, 0x77E7, 0xCFE9, 0x77E8, + 0xCFEA, 0x7806, 0xCFEB, 0x7811, 0xCFEC, 0x7812, 0xCFED, 0x7805, 0xCFEE, 0x7810, 0xCFEF, 0x780F, 0xCFF0, 0x780E, 0xCFF1, 0x7809, + 0xCFF2, 0x7803, 0xCFF3, 0x7813, 0xCFF4, 0x794A, 0xCFF5, 0x794C, 0xCFF6, 0x794B, 0xCFF7, 0x7945, 0xCFF8, 0x7944, 0xCFF9, 0x79D5, + 0xCFFA, 0x79CD, 0xCFFB, 0x79CF, 0xCFFC, 0x79D6, 0xCFFD, 0x79CE, 0xCFFE, 0x7A80, 0xD040, 0x7A7E, 0xD041, 0x7AD1, 0xD042, 0x7B00, + 0xD043, 0x7B01, 0xD044, 0x7C7A, 0xD045, 0x7C78, 0xD046, 0x7C79, 0xD047, 0x7C7F, 0xD048, 0x7C80, 0xD049, 0x7C81, 0xD04A, 0x7D03, + 0xD04B, 0x7D08, 0xD04C, 0x7D01, 0xD04D, 0x7F58, 0xD04E, 0x7F91, 0xD04F, 0x7F8D, 0xD050, 0x7FBE, 0xD051, 0x8007, 0xD052, 0x800E, + 0xD053, 0x800F, 0xD054, 0x8014, 0xD055, 0x8037, 0xD056, 0x80D8, 0xD057, 0x80C7, 0xD058, 0x80E0, 0xD059, 0x80D1, 0xD05A, 0x80C8, + 0xD05B, 0x80C2, 0xD05C, 0x80D0, 0xD05D, 0x80C5, 0xD05E, 0x80E3, 0xD05F, 0x80D9, 0xD060, 0x80DC, 0xD061, 0x80CA, 0xD062, 0x80D5, + 0xD063, 0x80C9, 0xD064, 0x80CF, 0xD065, 0x80D7, 0xD066, 0x80E6, 0xD067, 0x80CD, 0xD068, 0x81FF, 0xD069, 0x8221, 0xD06A, 0x8294, + 0xD06B, 0x82D9, 0xD06C, 0x82FE, 0xD06D, 0x82F9, 0xD06E, 0x8307, 0xD06F, 0x82E8, 0xD070, 0x8300, 0xD071, 0x82D5, 0xD072, 0x833A, + 0xD073, 0x82EB, 0xD074, 0x82D6, 0xD075, 0x82F4, 0xD076, 0x82EC, 0xD077, 0x82E1, 0xD078, 0x82F2, 0xD079, 0x82F5, 0xD07A, 0x830C, + 0xD07B, 0x82FB, 0xD07C, 0x82F6, 0xD07D, 0x82F0, 0xD07E, 0x82EA, 0xD0A1, 0x82E4, 0xD0A2, 0x82E0, 0xD0A3, 0x82FA, 0xD0A4, 0x82F3, + 0xD0A5, 0x82ED, 0xD0A6, 0x8677, 0xD0A7, 0x8674, 0xD0A8, 0x867C, 0xD0A9, 0x8673, 0xD0AA, 0x8841, 0xD0AB, 0x884E, 0xD0AC, 0x8867, + 0xD0AD, 0x886A, 0xD0AE, 0x8869, 0xD0AF, 0x89D3, 0xD0B0, 0x8A04, 0xD0B1, 0x8A07, 0xD0B2, 0x8D72, 0xD0B3, 0x8FE3, 0xD0B4, 0x8FE1, + 0xD0B5, 0x8FEE, 0xD0B6, 0x8FE0, 0xD0B7, 0x90F1, 0xD0B8, 0x90BD, 0xD0B9, 0x90BF, 0xD0BA, 0x90D5, 0xD0BB, 0x90C5, 0xD0BC, 0x90BE, + 0xD0BD, 0x90C7, 0xD0BE, 0x90CB, 0xD0BF, 0x90C8, 0xD0C0, 0x91D4, 0xD0C1, 0x91D3, 0xD0C2, 0x9654, 0xD0C3, 0x964F, 0xD0C4, 0x9651, + 0xD0C5, 0x9653, 0xD0C6, 0x964A, 0xD0C7, 0x964E, 0xD0C8, 0x501E, 0xD0C9, 0x5005, 0xD0CA, 0x5007, 0xD0CB, 0x5013, 0xD0CC, 0x5022, + 0xD0CD, 0x5030, 0xD0CE, 0x501B, 0xD0CF, 0x4FF5, 0xD0D0, 0x4FF4, 0xD0D1, 0x5033, 0xD0D2, 0x5037, 0xD0D3, 0x502C, 0xD0D4, 0x4FF6, + 0xD0D5, 0x4FF7, 0xD0D6, 0x5017, 0xD0D7, 0x501C, 0xD0D8, 0x5020, 0xD0D9, 0x5027, 0xD0DA, 0x5035, 0xD0DB, 0x502F, 0xD0DC, 0x5031, + 0xD0DD, 0x500E, 0xD0DE, 0x515A, 0xD0DF, 0x5194, 0xD0E0, 0x5193, 0xD0E1, 0x51CA, 0xD0E2, 0x51C4, 0xD0E3, 0x51C5, 0xD0E4, 0x51C8, + 0xD0E5, 0x51CE, 0xD0E6, 0x5261, 0xD0E7, 0x525A, 0xD0E8, 0x5252, 0xD0E9, 0x525E, 0xD0EA, 0x525F, 0xD0EB, 0x5255, 0xD0EC, 0x5262, + 0xD0ED, 0x52CD, 0xD0EE, 0x530E, 0xD0EF, 0x539E, 0xD0F0, 0x5526, 0xD0F1, 0x54E2, 0xD0F2, 0x5517, 0xD0F3, 0x5512, 0xD0F4, 0x54E7, + 0xD0F5, 0x54F3, 0xD0F6, 0x54E4, 0xD0F7, 0x551A, 0xD0F8, 0x54FF, 0xD0F9, 0x5504, 0xD0FA, 0x5508, 0xD0FB, 0x54EB, 0xD0FC, 0x5511, + 0xD0FD, 0x5505, 0xD0FE, 0x54F1, 0xD140, 0x550A, 0xD141, 0x54FB, 0xD142, 0x54F7, 0xD143, 0x54F8, 0xD144, 0x54E0, 0xD145, 0x550E, + 0xD146, 0x5503, 0xD147, 0x550B, 0xD148, 0x5701, 0xD149, 0x5702, 0xD14A, 0x57CC, 0xD14B, 0x5832, 0xD14C, 0x57D5, 0xD14D, 0x57D2, + 0xD14E, 0x57BA, 0xD14F, 0x57C6, 0xD150, 0x57BD, 0xD151, 0x57BC, 0xD152, 0x57B8, 0xD153, 0x57B6, 0xD154, 0x57BF, 0xD155, 0x57C7, + 0xD156, 0x57D0, 0xD157, 0x57B9, 0xD158, 0x57C1, 0xD159, 0x590E, 0xD15A, 0x594A, 0xD15B, 0x5A19, 0xD15C, 0x5A16, 0xD15D, 0x5A2D, + 0xD15E, 0x5A2E, 0xD15F, 0x5A15, 0xD160, 0x5A0F, 0xD161, 0x5A17, 0xD162, 0x5A0A, 0xD163, 0x5A1E, 0xD164, 0x5A33, 0xD165, 0x5B6C, + 0xD166, 0x5BA7, 0xD167, 0x5BAD, 0xD168, 0x5BAC, 0xD169, 0x5C03, 0xD16A, 0x5C56, 0xD16B, 0x5C54, 0xD16C, 0x5CEC, 0xD16D, 0x5CFF, + 0xD16E, 0x5CEE, 0xD16F, 0x5CF1, 0xD170, 0x5CF7, 0xD171, 0x5D00, 0xD172, 0x5CF9, 0xD173, 0x5E29, 0xD174, 0x5E28, 0xD175, 0x5EA8, + 0xD176, 0x5EAE, 0xD177, 0x5EAA, 0xD178, 0x5EAC, 0xD179, 0x5F33, 0xD17A, 0x5F30, 0xD17B, 0x5F67, 0xD17C, 0x605D, 0xD17D, 0x605A, + 0xD17E, 0x6067, 0xD1A1, 0x6041, 0xD1A2, 0x60A2, 0xD1A3, 0x6088, 0xD1A4, 0x6080, 0xD1A5, 0x6092, 0xD1A6, 0x6081, 0xD1A7, 0x609D, + 0xD1A8, 0x6083, 0xD1A9, 0x6095, 0xD1AA, 0x609B, 0xD1AB, 0x6097, 0xD1AC, 0x6087, 0xD1AD, 0x609C, 0xD1AE, 0x608E, 0xD1AF, 0x6219, + 0xD1B0, 0x6246, 0xD1B1, 0x62F2, 0xD1B2, 0x6310, 0xD1B3, 0x6356, 0xD1B4, 0x632C, 0xD1B5, 0x6344, 0xD1B6, 0x6345, 0xD1B7, 0x6336, + 0xD1B8, 0x6343, 0xD1B9, 0x63E4, 0xD1BA, 0x6339, 0xD1BB, 0x634B, 0xD1BC, 0x634A, 0xD1BD, 0x633C, 0xD1BE, 0x6329, 0xD1BF, 0x6341, + 0xD1C0, 0x6334, 0xD1C1, 0x6358, 0xD1C2, 0x6354, 0xD1C3, 0x6359, 0xD1C4, 0x632D, 0xD1C5, 0x6347, 0xD1C6, 0x6333, 0xD1C7, 0x635A, + 0xD1C8, 0x6351, 0xD1C9, 0x6338, 0xD1CA, 0x6357, 0xD1CB, 0x6340, 0xD1CC, 0x6348, 0xD1CD, 0x654A, 0xD1CE, 0x6546, 0xD1CF, 0x65C6, + 0xD1D0, 0x65C3, 0xD1D1, 0x65C4, 0xD1D2, 0x65C2, 0xD1D3, 0x664A, 0xD1D4, 0x665F, 0xD1D5, 0x6647, 0xD1D6, 0x6651, 0xD1D7, 0x6712, + 0xD1D8, 0x6713, 0xD1D9, 0x681F, 0xD1DA, 0x681A, 0xD1DB, 0x6849, 0xD1DC, 0x6832, 0xD1DD, 0x6833, 0xD1DE, 0x683B, 0xD1DF, 0x684B, + 0xD1E0, 0x684F, 0xD1E1, 0x6816, 0xD1E2, 0x6831, 0xD1E3, 0x681C, 0xD1E4, 0x6835, 0xD1E5, 0x682B, 0xD1E6, 0x682D, 0xD1E7, 0x682F, + 0xD1E8, 0x684E, 0xD1E9, 0x6844, 0xD1EA, 0x6834, 0xD1EB, 0x681D, 0xD1EC, 0x6812, 0xD1ED, 0x6814, 0xD1EE, 0x6826, 0xD1EF, 0x6828, + 0xD1F0, 0x682E, 0xD1F1, 0x684D, 0xD1F2, 0x683A, 0xD1F3, 0x6825, 0xD1F4, 0x6820, 0xD1F5, 0x6B2C, 0xD1F6, 0x6B2F, 0xD1F7, 0x6B2D, + 0xD1F8, 0x6B31, 0xD1F9, 0x6B34, 0xD1FA, 0x6B6D, 0xD1FB, 0x8082, 0xD1FC, 0x6B88, 0xD1FD, 0x6BE6, 0xD1FE, 0x6BE4, 0xD240, 0x6BE8, + 0xD241, 0x6BE3, 0xD242, 0x6BE2, 0xD243, 0x6BE7, 0xD244, 0x6C25, 0xD245, 0x6D7A, 0xD246, 0x6D63, 0xD247, 0x6D64, 0xD248, 0x6D76, + 0xD249, 0x6D0D, 0xD24A, 0x6D61, 0xD24B, 0x6D92, 0xD24C, 0x6D58, 0xD24D, 0x6D62, 0xD24E, 0x6D6D, 0xD24F, 0x6D6F, 0xD250, 0x6D91, + 0xD251, 0x6D8D, 0xD252, 0x6DEF, 0xD253, 0x6D7F, 0xD254, 0x6D86, 0xD255, 0x6D5E, 0xD256, 0x6D67, 0xD257, 0x6D60, 0xD258, 0x6D97, + 0xD259, 0x6D70, 0xD25A, 0x6D7C, 0xD25B, 0x6D5F, 0xD25C, 0x6D82, 0xD25D, 0x6D98, 0xD25E, 0x6D2F, 0xD25F, 0x6D68, 0xD260, 0x6D8B, + 0xD261, 0x6D7E, 0xD262, 0x6D80, 0xD263, 0x6D84, 0xD264, 0x6D16, 0xD265, 0x6D83, 0xD266, 0x6D7B, 0xD267, 0x6D7D, 0xD268, 0x6D75, + 0xD269, 0x6D90, 0xD26A, 0x70DC, 0xD26B, 0x70D3, 0xD26C, 0x70D1, 0xD26D, 0x70DD, 0xD26E, 0x70CB, 0xD26F, 0x7F39, 0xD270, 0x70E2, + 0xD271, 0x70D7, 0xD272, 0x70D2, 0xD273, 0x70DE, 0xD274, 0x70E0, 0xD275, 0x70D4, 0xD276, 0x70CD, 0xD277, 0x70C5, 0xD278, 0x70C6, + 0xD279, 0x70C7, 0xD27A, 0x70DA, 0xD27B, 0x70CE, 0xD27C, 0x70E1, 0xD27D, 0x7242, 0xD27E, 0x7278, 0xD2A1, 0x7277, 0xD2A2, 0x7276, + 0xD2A3, 0x7300, 0xD2A4, 0x72FA, 0xD2A5, 0x72F4, 0xD2A6, 0x72FE, 0xD2A7, 0x72F6, 0xD2A8, 0x72F3, 0xD2A9, 0x72FB, 0xD2AA, 0x7301, + 0xD2AB, 0x73D3, 0xD2AC, 0x73D9, 0xD2AD, 0x73E5, 0xD2AE, 0x73D6, 0xD2AF, 0x73BC, 0xD2B0, 0x73E7, 0xD2B1, 0x73E3, 0xD2B2, 0x73E9, + 0xD2B3, 0x73DC, 0xD2B4, 0x73D2, 0xD2B5, 0x73DB, 0xD2B6, 0x73D4, 0xD2B7, 0x73DD, 0xD2B8, 0x73DA, 0xD2B9, 0x73D7, 0xD2BA, 0x73D8, + 0xD2BB, 0x73E8, 0xD2BC, 0x74DE, 0xD2BD, 0x74DF, 0xD2BE, 0x74F4, 0xD2BF, 0x74F5, 0xD2C0, 0x7521, 0xD2C1, 0x755B, 0xD2C2, 0x755F, + 0xD2C3, 0x75B0, 0xD2C4, 0x75C1, 0xD2C5, 0x75BB, 0xD2C6, 0x75C4, 0xD2C7, 0x75C0, 0xD2C8, 0x75BF, 0xD2C9, 0x75B6, 0xD2CA, 0x75BA, + 0xD2CB, 0x768A, 0xD2CC, 0x76C9, 0xD2CD, 0x771D, 0xD2CE, 0x771B, 0xD2CF, 0x7710, 0xD2D0, 0x7713, 0xD2D1, 0x7712, 0xD2D2, 0x7723, + 0xD2D3, 0x7711, 0xD2D4, 0x7715, 0xD2D5, 0x7719, 0xD2D6, 0x771A, 0xD2D7, 0x7722, 0xD2D8, 0x7727, 0xD2D9, 0x7823, 0xD2DA, 0x782C, + 0xD2DB, 0x7822, 0xD2DC, 0x7835, 0xD2DD, 0x782F, 0xD2DE, 0x7828, 0xD2DF, 0x782E, 0xD2E0, 0x782B, 0xD2E1, 0x7821, 0xD2E2, 0x7829, + 0xD2E3, 0x7833, 0xD2E4, 0x782A, 0xD2E5, 0x7831, 0xD2E6, 0x7954, 0xD2E7, 0x795B, 0xD2E8, 0x794F, 0xD2E9, 0x795C, 0xD2EA, 0x7953, + 0xD2EB, 0x7952, 0xD2EC, 0x7951, 0xD2ED, 0x79EB, 0xD2EE, 0x79EC, 0xD2EF, 0x79E0, 0xD2F0, 0x79EE, 0xD2F1, 0x79ED, 0xD2F2, 0x79EA, + 0xD2F3, 0x79DC, 0xD2F4, 0x79DE, 0xD2F5, 0x79DD, 0xD2F6, 0x7A86, 0xD2F7, 0x7A89, 0xD2F8, 0x7A85, 0xD2F9, 0x7A8B, 0xD2FA, 0x7A8C, + 0xD2FB, 0x7A8A, 0xD2FC, 0x7A87, 0xD2FD, 0x7AD8, 0xD2FE, 0x7B10, 0xD340, 0x7B04, 0xD341, 0x7B13, 0xD342, 0x7B05, 0xD343, 0x7B0F, + 0xD344, 0x7B08, 0xD345, 0x7B0A, 0xD346, 0x7B0E, 0xD347, 0x7B09, 0xD348, 0x7B12, 0xD349, 0x7C84, 0xD34A, 0x7C91, 0xD34B, 0x7C8A, + 0xD34C, 0x7C8C, 0xD34D, 0x7C88, 0xD34E, 0x7C8D, 0xD34F, 0x7C85, 0xD350, 0x7D1E, 0xD351, 0x7D1D, 0xD352, 0x7D11, 0xD353, 0x7D0E, + 0xD354, 0x7D18, 0xD355, 0x7D16, 0xD356, 0x7D13, 0xD357, 0x7D1F, 0xD358, 0x7D12, 0xD359, 0x7D0F, 0xD35A, 0x7D0C, 0xD35B, 0x7F5C, + 0xD35C, 0x7F61, 0xD35D, 0x7F5E, 0xD35E, 0x7F60, 0xD35F, 0x7F5D, 0xD360, 0x7F5B, 0xD361, 0x7F96, 0xD362, 0x7F92, 0xD363, 0x7FC3, + 0xD364, 0x7FC2, 0xD365, 0x7FC0, 0xD366, 0x8016, 0xD367, 0x803E, 0xD368, 0x8039, 0xD369, 0x80FA, 0xD36A, 0x80F2, 0xD36B, 0x80F9, + 0xD36C, 0x80F5, 0xD36D, 0x8101, 0xD36E, 0x80FB, 0xD36F, 0x8100, 0xD370, 0x8201, 0xD371, 0x822F, 0xD372, 0x8225, 0xD373, 0x8333, + 0xD374, 0x832D, 0xD375, 0x8344, 0xD376, 0x8319, 0xD377, 0x8351, 0xD378, 0x8325, 0xD379, 0x8356, 0xD37A, 0x833F, 0xD37B, 0x8341, + 0xD37C, 0x8326, 0xD37D, 0x831C, 0xD37E, 0x8322, 0xD3A1, 0x8342, 0xD3A2, 0x834E, 0xD3A3, 0x831B, 0xD3A4, 0x832A, 0xD3A5, 0x8308, + 0xD3A6, 0x833C, 0xD3A7, 0x834D, 0xD3A8, 0x8316, 0xD3A9, 0x8324, 0xD3AA, 0x8320, 0xD3AB, 0x8337, 0xD3AC, 0x832F, 0xD3AD, 0x8329, + 0xD3AE, 0x8347, 0xD3AF, 0x8345, 0xD3B0, 0x834C, 0xD3B1, 0x8353, 0xD3B2, 0x831E, 0xD3B3, 0x832C, 0xD3B4, 0x834B, 0xD3B5, 0x8327, + 0xD3B6, 0x8348, 0xD3B7, 0x8653, 0xD3B8, 0x8652, 0xD3B9, 0x86A2, 0xD3BA, 0x86A8, 0xD3BB, 0x8696, 0xD3BC, 0x868D, 0xD3BD, 0x8691, + 0xD3BE, 0x869E, 0xD3BF, 0x8687, 0xD3C0, 0x8697, 0xD3C1, 0x8686, 0xD3C2, 0x868B, 0xD3C3, 0x869A, 0xD3C4, 0x8685, 0xD3C5, 0x86A5, + 0xD3C6, 0x8699, 0xD3C7, 0x86A1, 0xD3C8, 0x86A7, 0xD3C9, 0x8695, 0xD3CA, 0x8698, 0xD3CB, 0x868E, 0xD3CC, 0x869D, 0xD3CD, 0x8690, + 0xD3CE, 0x8694, 0xD3CF, 0x8843, 0xD3D0, 0x8844, 0xD3D1, 0x886D, 0xD3D2, 0x8875, 0xD3D3, 0x8876, 0xD3D4, 0x8872, 0xD3D5, 0x8880, + 0xD3D6, 0x8871, 0xD3D7, 0x887F, 0xD3D8, 0x886F, 0xD3D9, 0x8883, 0xD3DA, 0x887E, 0xD3DB, 0x8874, 0xD3DC, 0x887C, 0xD3DD, 0x8A12, + 0xD3DE, 0x8C47, 0xD3DF, 0x8C57, 0xD3E0, 0x8C7B, 0xD3E1, 0x8CA4, 0xD3E2, 0x8CA3, 0xD3E3, 0x8D76, 0xD3E4, 0x8D78, 0xD3E5, 0x8DB5, + 0xD3E6, 0x8DB7, 0xD3E7, 0x8DB6, 0xD3E8, 0x8ED1, 0xD3E9, 0x8ED3, 0xD3EA, 0x8FFE, 0xD3EB, 0x8FF5, 0xD3EC, 0x9002, 0xD3ED, 0x8FFF, + 0xD3EE, 0x8FFB, 0xD3EF, 0x9004, 0xD3F0, 0x8FFC, 0xD3F1, 0x8FF6, 0xD3F2, 0x90D6, 0xD3F3, 0x90E0, 0xD3F4, 0x90D9, 0xD3F5, 0x90DA, + 0xD3F6, 0x90E3, 0xD3F7, 0x90DF, 0xD3F8, 0x90E5, 0xD3F9, 0x90D8, 0xD3FA, 0x90DB, 0xD3FB, 0x90D7, 0xD3FC, 0x90DC, 0xD3FD, 0x90E4, + 0xD3FE, 0x9150, 0xD440, 0x914E, 0xD441, 0x914F, 0xD442, 0x91D5, 0xD443, 0x91E2, 0xD444, 0x91DA, 0xD445, 0x965C, 0xD446, 0x965F, + 0xD447, 0x96BC, 0xD448, 0x98E3, 0xD449, 0x9ADF, 0xD44A, 0x9B2F, 0xD44B, 0x4E7F, 0xD44C, 0x5070, 0xD44D, 0x506A, 0xD44E, 0x5061, + 0xD44F, 0x505E, 0xD450, 0x5060, 0xD451, 0x5053, 0xD452, 0x504B, 0xD453, 0x505D, 0xD454, 0x5072, 0xD455, 0x5048, 0xD456, 0x504D, + 0xD457, 0x5041, 0xD458, 0x505B, 0xD459, 0x504A, 0xD45A, 0x5062, 0xD45B, 0x5015, 0xD45C, 0x5045, 0xD45D, 0x505F, 0xD45E, 0x5069, + 0xD45F, 0x506B, 0xD460, 0x5063, 0xD461, 0x5064, 0xD462, 0x5046, 0xD463, 0x5040, 0xD464, 0x506E, 0xD465, 0x5073, 0xD466, 0x5057, + 0xD467, 0x5051, 0xD468, 0x51D0, 0xD469, 0x526B, 0xD46A, 0x526D, 0xD46B, 0x526C, 0xD46C, 0x526E, 0xD46D, 0x52D6, 0xD46E, 0x52D3, + 0xD46F, 0x532D, 0xD470, 0x539C, 0xD471, 0x5575, 0xD472, 0x5576, 0xD473, 0x553C, 0xD474, 0x554D, 0xD475, 0x5550, 0xD476, 0x5534, + 0xD477, 0x552A, 0xD478, 0x5551, 0xD479, 0x5562, 0xD47A, 0x5536, 0xD47B, 0x5535, 0xD47C, 0x5530, 0xD47D, 0x5552, 0xD47E, 0x5545, + 0xD4A1, 0x550C, 0xD4A2, 0x5532, 0xD4A3, 0x5565, 0xD4A4, 0x554E, 0xD4A5, 0x5539, 0xD4A6, 0x5548, 0xD4A7, 0x552D, 0xD4A8, 0x553B, + 0xD4A9, 0x5540, 0xD4AA, 0x554B, 0xD4AB, 0x570A, 0xD4AC, 0x5707, 0xD4AD, 0x57FB, 0xD4AE, 0x5814, 0xD4AF, 0x57E2, 0xD4B0, 0x57F6, + 0xD4B1, 0x57DC, 0xD4B2, 0x57F4, 0xD4B3, 0x5800, 0xD4B4, 0x57ED, 0xD4B5, 0x57FD, 0xD4B6, 0x5808, 0xD4B7, 0x57F8, 0xD4B8, 0x580B, + 0xD4B9, 0x57F3, 0xD4BA, 0x57CF, 0xD4BB, 0x5807, 0xD4BC, 0x57EE, 0xD4BD, 0x57E3, 0xD4BE, 0x57F2, 0xD4BF, 0x57E5, 0xD4C0, 0x57EC, + 0xD4C1, 0x57E1, 0xD4C2, 0x580E, 0xD4C3, 0x57FC, 0xD4C4, 0x5810, 0xD4C5, 0x57E7, 0xD4C6, 0x5801, 0xD4C7, 0x580C, 0xD4C8, 0x57F1, + 0xD4C9, 0x57E9, 0xD4CA, 0x57F0, 0xD4CB, 0x580D, 0xD4CC, 0x5804, 0xD4CD, 0x595C, 0xD4CE, 0x5A60, 0xD4CF, 0x5A58, 0xD4D0, 0x5A55, + 0xD4D1, 0x5A67, 0xD4D2, 0x5A5E, 0xD4D3, 0x5A38, 0xD4D4, 0x5A35, 0xD4D5, 0x5A6D, 0xD4D6, 0x5A50, 0xD4D7, 0x5A5F, 0xD4D8, 0x5A65, + 0xD4D9, 0x5A6C, 0xD4DA, 0x5A53, 0xD4DB, 0x5A64, 0xD4DC, 0x5A57, 0xD4DD, 0x5A43, 0xD4DE, 0x5A5D, 0xD4DF, 0x5A52, 0xD4E0, 0x5A44, + 0xD4E1, 0x5A5B, 0xD4E2, 0x5A48, 0xD4E3, 0x5A8E, 0xD4E4, 0x5A3E, 0xD4E5, 0x5A4D, 0xD4E6, 0x5A39, 0xD4E7, 0x5A4C, 0xD4E8, 0x5A70, + 0xD4E9, 0x5A69, 0xD4EA, 0x5A47, 0xD4EB, 0x5A51, 0xD4EC, 0x5A56, 0xD4ED, 0x5A42, 0xD4EE, 0x5A5C, 0xD4EF, 0x5B72, 0xD4F0, 0x5B6E, + 0xD4F1, 0x5BC1, 0xD4F2, 0x5BC0, 0xD4F3, 0x5C59, 0xD4F4, 0x5D1E, 0xD4F5, 0x5D0B, 0xD4F6, 0x5D1D, 0xD4F7, 0x5D1A, 0xD4F8, 0x5D20, + 0xD4F9, 0x5D0C, 0xD4FA, 0x5D28, 0xD4FB, 0x5D0D, 0xD4FC, 0x5D26, 0xD4FD, 0x5D25, 0xD4FE, 0x5D0F, 0xD540, 0x5D30, 0xD541, 0x5D12, + 0xD542, 0x5D23, 0xD543, 0x5D1F, 0xD544, 0x5D2E, 0xD545, 0x5E3E, 0xD546, 0x5E34, 0xD547, 0x5EB1, 0xD548, 0x5EB4, 0xD549, 0x5EB9, + 0xD54A, 0x5EB2, 0xD54B, 0x5EB3, 0xD54C, 0x5F36, 0xD54D, 0x5F38, 0xD54E, 0x5F9B, 0xD54F, 0x5F96, 0xD550, 0x5F9F, 0xD551, 0x608A, + 0xD552, 0x6090, 0xD553, 0x6086, 0xD554, 0x60BE, 0xD555, 0x60B0, 0xD556, 0x60BA, 0xD557, 0x60D3, 0xD558, 0x60D4, 0xD559, 0x60CF, + 0xD55A, 0x60E4, 0xD55B, 0x60D9, 0xD55C, 0x60DD, 0xD55D, 0x60C8, 0xD55E, 0x60B1, 0xD55F, 0x60DB, 0xD560, 0x60B7, 0xD561, 0x60CA, + 0xD562, 0x60BF, 0xD563, 0x60C3, 0xD564, 0x60CD, 0xD565, 0x60C0, 0xD566, 0x6332, 0xD567, 0x6365, 0xD568, 0x638A, 0xD569, 0x6382, + 0xD56A, 0x637D, 0xD56B, 0x63BD, 0xD56C, 0x639E, 0xD56D, 0x63AD, 0xD56E, 0x639D, 0xD56F, 0x6397, 0xD570, 0x63AB, 0xD571, 0x638E, + 0xD572, 0x636F, 0xD573, 0x6387, 0xD574, 0x6390, 0xD575, 0x636E, 0xD576, 0x63AF, 0xD577, 0x6375, 0xD578, 0x639C, 0xD579, 0x636D, + 0xD57A, 0x63AE, 0xD57B, 0x637C, 0xD57C, 0x63A4, 0xD57D, 0x633B, 0xD57E, 0x639F, 0xD5A1, 0x6378, 0xD5A2, 0x6385, 0xD5A3, 0x6381, + 0xD5A4, 0x6391, 0xD5A5, 0x638D, 0xD5A6, 0x6370, 0xD5A7, 0x6553, 0xD5A8, 0x65CD, 0xD5A9, 0x6665, 0xD5AA, 0x6661, 0xD5AB, 0x665B, + 0xD5AC, 0x6659, 0xD5AD, 0x665C, 0xD5AE, 0x6662, 0xD5AF, 0x6718, 0xD5B0, 0x6879, 0xD5B1, 0x6887, 0xD5B2, 0x6890, 0xD5B3, 0x689C, + 0xD5B4, 0x686D, 0xD5B5, 0x686E, 0xD5B6, 0x68AE, 0xD5B7, 0x68AB, 0xD5B8, 0x6956, 0xD5B9, 0x686F, 0xD5BA, 0x68A3, 0xD5BB, 0x68AC, + 0xD5BC, 0x68A9, 0xD5BD, 0x6875, 0xD5BE, 0x6874, 0xD5BF, 0x68B2, 0xD5C0, 0x688F, 0xD5C1, 0x6877, 0xD5C2, 0x6892, 0xD5C3, 0x687C, + 0xD5C4, 0x686B, 0xD5C5, 0x6872, 0xD5C6, 0x68AA, 0xD5C7, 0x6880, 0xD5C8, 0x6871, 0xD5C9, 0x687E, 0xD5CA, 0x689B, 0xD5CB, 0x6896, + 0xD5CC, 0x688B, 0xD5CD, 0x68A0, 0xD5CE, 0x6889, 0xD5CF, 0x68A4, 0xD5D0, 0x6878, 0xD5D1, 0x687B, 0xD5D2, 0x6891, 0xD5D3, 0x688C, + 0xD5D4, 0x688A, 0xD5D5, 0x687D, 0xD5D6, 0x6B36, 0xD5D7, 0x6B33, 0xD5D8, 0x6B37, 0xD5D9, 0x6B38, 0xD5DA, 0x6B91, 0xD5DB, 0x6B8F, + 0xD5DC, 0x6B8D, 0xD5DD, 0x6B8E, 0xD5DE, 0x6B8C, 0xD5DF, 0x6C2A, 0xD5E0, 0x6DC0, 0xD5E1, 0x6DAB, 0xD5E2, 0x6DB4, 0xD5E3, 0x6DB3, + 0xD5E4, 0x6E74, 0xD5E5, 0x6DAC, 0xD5E6, 0x6DE9, 0xD5E7, 0x6DE2, 0xD5E8, 0x6DB7, 0xD5E9, 0x6DF6, 0xD5EA, 0x6DD4, 0xD5EB, 0x6E00, + 0xD5EC, 0x6DC8, 0xD5ED, 0x6DE0, 0xD5EE, 0x6DDF, 0xD5EF, 0x6DD6, 0xD5F0, 0x6DBE, 0xD5F1, 0x6DE5, 0xD5F2, 0x6DDC, 0xD5F3, 0x6DDD, + 0xD5F4, 0x6DDB, 0xD5F5, 0x6DF4, 0xD5F6, 0x6DCA, 0xD5F7, 0x6DBD, 0xD5F8, 0x6DED, 0xD5F9, 0x6DF0, 0xD5FA, 0x6DBA, 0xD5FB, 0x6DD5, + 0xD5FC, 0x6DC2, 0xD5FD, 0x6DCF, 0xD5FE, 0x6DC9, 0xD640, 0x6DD0, 0xD641, 0x6DF2, 0xD642, 0x6DD3, 0xD643, 0x6DFD, 0xD644, 0x6DD7, + 0xD645, 0x6DCD, 0xD646, 0x6DE3, 0xD647, 0x6DBB, 0xD648, 0x70FA, 0xD649, 0x710D, 0xD64A, 0x70F7, 0xD64B, 0x7117, 0xD64C, 0x70F4, + 0xD64D, 0x710C, 0xD64E, 0x70F0, 0xD64F, 0x7104, 0xD650, 0x70F3, 0xD651, 0x7110, 0xD652, 0x70FC, 0xD653, 0x70FF, 0xD654, 0x7106, + 0xD655, 0x7113, 0xD656, 0x7100, 0xD657, 0x70F8, 0xD658, 0x70F6, 0xD659, 0x710B, 0xD65A, 0x7102, 0xD65B, 0x710E, 0xD65C, 0x727E, + 0xD65D, 0x727B, 0xD65E, 0x727C, 0xD65F, 0x727F, 0xD660, 0x731D, 0xD661, 0x7317, 0xD662, 0x7307, 0xD663, 0x7311, 0xD664, 0x7318, + 0xD665, 0x730A, 0xD666, 0x7308, 0xD667, 0x72FF, 0xD668, 0x730F, 0xD669, 0x731E, 0xD66A, 0x7388, 0xD66B, 0x73F6, 0xD66C, 0x73F8, + 0xD66D, 0x73F5, 0xD66E, 0x7404, 0xD66F, 0x7401, 0xD670, 0x73FD, 0xD671, 0x7407, 0xD672, 0x7400, 0xD673, 0x73FA, 0xD674, 0x73FC, + 0xD675, 0x73FF, 0xD676, 0x740C, 0xD677, 0x740B, 0xD678, 0x73F4, 0xD679, 0x7408, 0xD67A, 0x7564, 0xD67B, 0x7563, 0xD67C, 0x75CE, + 0xD67D, 0x75D2, 0xD67E, 0x75CF, 0xD6A1, 0x75CB, 0xD6A2, 0x75CC, 0xD6A3, 0x75D1, 0xD6A4, 0x75D0, 0xD6A5, 0x768F, 0xD6A6, 0x7689, + 0xD6A7, 0x76D3, 0xD6A8, 0x7739, 0xD6A9, 0x772F, 0xD6AA, 0x772D, 0xD6AB, 0x7731, 0xD6AC, 0x7732, 0xD6AD, 0x7734, 0xD6AE, 0x7733, + 0xD6AF, 0x773D, 0xD6B0, 0x7725, 0xD6B1, 0x773B, 0xD6B2, 0x7735, 0xD6B3, 0x7848, 0xD6B4, 0x7852, 0xD6B5, 0x7849, 0xD6B6, 0x784D, + 0xD6B7, 0x784A, 0xD6B8, 0x784C, 0xD6B9, 0x7826, 0xD6BA, 0x7845, 0xD6BB, 0x7850, 0xD6BC, 0x7964, 0xD6BD, 0x7967, 0xD6BE, 0x7969, + 0xD6BF, 0x796A, 0xD6C0, 0x7963, 0xD6C1, 0x796B, 0xD6C2, 0x7961, 0xD6C3, 0x79BB, 0xD6C4, 0x79FA, 0xD6C5, 0x79F8, 0xD6C6, 0x79F6, + 0xD6C7, 0x79F7, 0xD6C8, 0x7A8F, 0xD6C9, 0x7A94, 0xD6CA, 0x7A90, 0xD6CB, 0x7B35, 0xD6CC, 0x7B47, 0xD6CD, 0x7B34, 0xD6CE, 0x7B25, + 0xD6CF, 0x7B30, 0xD6D0, 0x7B22, 0xD6D1, 0x7B24, 0xD6D2, 0x7B33, 0xD6D3, 0x7B18, 0xD6D4, 0x7B2A, 0xD6D5, 0x7B1D, 0xD6D6, 0x7B31, + 0xD6D7, 0x7B2B, 0xD6D8, 0x7B2D, 0xD6D9, 0x7B2F, 0xD6DA, 0x7B32, 0xD6DB, 0x7B38, 0xD6DC, 0x7B1A, 0xD6DD, 0x7B23, 0xD6DE, 0x7C94, + 0xD6DF, 0x7C98, 0xD6E0, 0x7C96, 0xD6E1, 0x7CA3, 0xD6E2, 0x7D35, 0xD6E3, 0x7D3D, 0xD6E4, 0x7D38, 0xD6E5, 0x7D36, 0xD6E6, 0x7D3A, + 0xD6E7, 0x7D45, 0xD6E8, 0x7D2C, 0xD6E9, 0x7D29, 0xD6EA, 0x7D41, 0xD6EB, 0x7D47, 0xD6EC, 0x7D3E, 0xD6ED, 0x7D3F, 0xD6EE, 0x7D4A, + 0xD6EF, 0x7D3B, 0xD6F0, 0x7D28, 0xD6F1, 0x7F63, 0xD6F2, 0x7F95, 0xD6F3, 0x7F9C, 0xD6F4, 0x7F9D, 0xD6F5, 0x7F9B, 0xD6F6, 0x7FCA, + 0xD6F7, 0x7FCB, 0xD6F8, 0x7FCD, 0xD6F9, 0x7FD0, 0xD6FA, 0x7FD1, 0xD6FB, 0x7FC7, 0xD6FC, 0x7FCF, 0xD6FD, 0x7FC9, 0xD6FE, 0x801F, + 0xD740, 0x801E, 0xD741, 0x801B, 0xD742, 0x8047, 0xD743, 0x8043, 0xD744, 0x8048, 0xD745, 0x8118, 0xD746, 0x8125, 0xD747, 0x8119, + 0xD748, 0x811B, 0xD749, 0x812D, 0xD74A, 0x811F, 0xD74B, 0x812C, 0xD74C, 0x811E, 0xD74D, 0x8121, 0xD74E, 0x8115, 0xD74F, 0x8127, + 0xD750, 0x811D, 0xD751, 0x8122, 0xD752, 0x8211, 0xD753, 0x8238, 0xD754, 0x8233, 0xD755, 0x823A, 0xD756, 0x8234, 0xD757, 0x8232, + 0xD758, 0x8274, 0xD759, 0x8390, 0xD75A, 0x83A3, 0xD75B, 0x83A8, 0xD75C, 0x838D, 0xD75D, 0x837A, 0xD75E, 0x8373, 0xD75F, 0x83A4, + 0xD760, 0x8374, 0xD761, 0x838F, 0xD762, 0x8381, 0xD763, 0x8395, 0xD764, 0x8399, 0xD765, 0x8375, 0xD766, 0x8394, 0xD767, 0x83A9, + 0xD768, 0x837D, 0xD769, 0x8383, 0xD76A, 0x838C, 0xD76B, 0x839D, 0xD76C, 0x839B, 0xD76D, 0x83AA, 0xD76E, 0x838B, 0xD76F, 0x837E, + 0xD770, 0x83A5, 0xD771, 0x83AF, 0xD772, 0x8388, 0xD773, 0x8397, 0xD774, 0x83B0, 0xD775, 0x837F, 0xD776, 0x83A6, 0xD777, 0x8387, + 0xD778, 0x83AE, 0xD779, 0x8376, 0xD77A, 0x839A, 0xD77B, 0x8659, 0xD77C, 0x8656, 0xD77D, 0x86BF, 0xD77E, 0x86B7, 0xD7A1, 0x86C2, + 0xD7A2, 0x86C1, 0xD7A3, 0x86C5, 0xD7A4, 0x86BA, 0xD7A5, 0x86B0, 0xD7A6, 0x86C8, 0xD7A7, 0x86B9, 0xD7A8, 0x86B3, 0xD7A9, 0x86B8, + 0xD7AA, 0x86CC, 0xD7AB, 0x86B4, 0xD7AC, 0x86BB, 0xD7AD, 0x86BC, 0xD7AE, 0x86C3, 0xD7AF, 0x86BD, 0xD7B0, 0x86BE, 0xD7B1, 0x8852, + 0xD7B2, 0x8889, 0xD7B3, 0x8895, 0xD7B4, 0x88A8, 0xD7B5, 0x88A2, 0xD7B6, 0x88AA, 0xD7B7, 0x889A, 0xD7B8, 0x8891, 0xD7B9, 0x88A1, + 0xD7BA, 0x889F, 0xD7BB, 0x8898, 0xD7BC, 0x88A7, 0xD7BD, 0x8899, 0xD7BE, 0x889B, 0xD7BF, 0x8897, 0xD7C0, 0x88A4, 0xD7C1, 0x88AC, + 0xD7C2, 0x888C, 0xD7C3, 0x8893, 0xD7C4, 0x888E, 0xD7C5, 0x8982, 0xD7C6, 0x89D6, 0xD7C7, 0x89D9, 0xD7C8, 0x89D5, 0xD7C9, 0x8A30, + 0xD7CA, 0x8A27, 0xD7CB, 0x8A2C, 0xD7CC, 0x8A1E, 0xD7CD, 0x8C39, 0xD7CE, 0x8C3B, 0xD7CF, 0x8C5C, 0xD7D0, 0x8C5D, 0xD7D1, 0x8C7D, + 0xD7D2, 0x8CA5, 0xD7D3, 0x8D7D, 0xD7D4, 0x8D7B, 0xD7D5, 0x8D79, 0xD7D6, 0x8DBC, 0xD7D7, 0x8DC2, 0xD7D8, 0x8DB9, 0xD7D9, 0x8DBF, + 0xD7DA, 0x8DC1, 0xD7DB, 0x8ED8, 0xD7DC, 0x8EDE, 0xD7DD, 0x8EDD, 0xD7DE, 0x8EDC, 0xD7DF, 0x8ED7, 0xD7E0, 0x8EE0, 0xD7E1, 0x8EE1, + 0xD7E2, 0x9024, 0xD7E3, 0x900B, 0xD7E4, 0x9011, 0xD7E5, 0x901C, 0xD7E6, 0x900C, 0xD7E7, 0x9021, 0xD7E8, 0x90EF, 0xD7E9, 0x90EA, + 0xD7EA, 0x90F0, 0xD7EB, 0x90F4, 0xD7EC, 0x90F2, 0xD7ED, 0x90F3, 0xD7EE, 0x90D4, 0xD7EF, 0x90EB, 0xD7F0, 0x90EC, 0xD7F1, 0x90E9, + 0xD7F2, 0x9156, 0xD7F3, 0x9158, 0xD7F4, 0x915A, 0xD7F5, 0x9153, 0xD7F6, 0x9155, 0xD7F7, 0x91EC, 0xD7F8, 0x91F4, 0xD7F9, 0x91F1, + 0xD7FA, 0x91F3, 0xD7FB, 0x91F8, 0xD7FC, 0x91E4, 0xD7FD, 0x91F9, 0xD7FE, 0x91EA, 0xD840, 0x91EB, 0xD841, 0x91F7, 0xD842, 0x91E8, + 0xD843, 0x91EE, 0xD844, 0x957A, 0xD845, 0x9586, 0xD846, 0x9588, 0xD847, 0x967C, 0xD848, 0x966D, 0xD849, 0x966B, 0xD84A, 0x9671, + 0xD84B, 0x966F, 0xD84C, 0x96BF, 0xD84D, 0x976A, 0xD84E, 0x9804, 0xD84F, 0x98E5, 0xD850, 0x9997, 0xD851, 0x509B, 0xD852, 0x5095, + 0xD853, 0x5094, 0xD854, 0x509E, 0xD855, 0x508B, 0xD856, 0x50A3, 0xD857, 0x5083, 0xD858, 0x508C, 0xD859, 0x508E, 0xD85A, 0x509D, + 0xD85B, 0x5068, 0xD85C, 0x509C, 0xD85D, 0x5092, 0xD85E, 0x5082, 0xD85F, 0x5087, 0xD860, 0x515F, 0xD861, 0x51D4, 0xD862, 0x5312, + 0xD863, 0x5311, 0xD864, 0x53A4, 0xD865, 0x53A7, 0xD866, 0x5591, 0xD867, 0x55A8, 0xD868, 0x55A5, 0xD869, 0x55AD, 0xD86A, 0x5577, + 0xD86B, 0x5645, 0xD86C, 0x55A2, 0xD86D, 0x5593, 0xD86E, 0x5588, 0xD86F, 0x558F, 0xD870, 0x55B5, 0xD871, 0x5581, 0xD872, 0x55A3, + 0xD873, 0x5592, 0xD874, 0x55A4, 0xD875, 0x557D, 0xD876, 0x558C, 0xD877, 0x55A6, 0xD878, 0x557F, 0xD879, 0x5595, 0xD87A, 0x55A1, + 0xD87B, 0x558E, 0xD87C, 0x570C, 0xD87D, 0x5829, 0xD87E, 0x5837, 0xD8A1, 0x5819, 0xD8A2, 0x581E, 0xD8A3, 0x5827, 0xD8A4, 0x5823, + 0xD8A5, 0x5828, 0xD8A6, 0x57F5, 0xD8A7, 0x5848, 0xD8A8, 0x5825, 0xD8A9, 0x581C, 0xD8AA, 0x581B, 0xD8AB, 0x5833, 0xD8AC, 0x583F, + 0xD8AD, 0x5836, 0xD8AE, 0x582E, 0xD8AF, 0x5839, 0xD8B0, 0x5838, 0xD8B1, 0x582D, 0xD8B2, 0x582C, 0xD8B3, 0x583B, 0xD8B4, 0x5961, + 0xD8B5, 0x5AAF, 0xD8B6, 0x5A94, 0xD8B7, 0x5A9F, 0xD8B8, 0x5A7A, 0xD8B9, 0x5AA2, 0xD8BA, 0x5A9E, 0xD8BB, 0x5A78, 0xD8BC, 0x5AA6, + 0xD8BD, 0x5A7C, 0xD8BE, 0x5AA5, 0xD8BF, 0x5AAC, 0xD8C0, 0x5A95, 0xD8C1, 0x5AAE, 0xD8C2, 0x5A37, 0xD8C3, 0x5A84, 0xD8C4, 0x5A8A, + 0xD8C5, 0x5A97, 0xD8C6, 0x5A83, 0xD8C7, 0x5A8B, 0xD8C8, 0x5AA9, 0xD8C9, 0x5A7B, 0xD8CA, 0x5A7D, 0xD8CB, 0x5A8C, 0xD8CC, 0x5A9C, + 0xD8CD, 0x5A8F, 0xD8CE, 0x5A93, 0xD8CF, 0x5A9D, 0xD8D0, 0x5BEA, 0xD8D1, 0x5BCD, 0xD8D2, 0x5BCB, 0xD8D3, 0x5BD4, 0xD8D4, 0x5BD1, + 0xD8D5, 0x5BCA, 0xD8D6, 0x5BCE, 0xD8D7, 0x5C0C, 0xD8D8, 0x5C30, 0xD8D9, 0x5D37, 0xD8DA, 0x5D43, 0xD8DB, 0x5D6B, 0xD8DC, 0x5D41, + 0xD8DD, 0x5D4B, 0xD8DE, 0x5D3F, 0xD8DF, 0x5D35, 0xD8E0, 0x5D51, 0xD8E1, 0x5D4E, 0xD8E2, 0x5D55, 0xD8E3, 0x5D33, 0xD8E4, 0x5D3A, + 0xD8E5, 0x5D52, 0xD8E6, 0x5D3D, 0xD8E7, 0x5D31, 0xD8E8, 0x5D59, 0xD8E9, 0x5D42, 0xD8EA, 0x5D39, 0xD8EB, 0x5D49, 0xD8EC, 0x5D38, + 0xD8ED, 0x5D3C, 0xD8EE, 0x5D32, 0xD8EF, 0x5D36, 0xD8F0, 0x5D40, 0xD8F1, 0x5D45, 0xD8F2, 0x5E44, 0xD8F3, 0x5E41, 0xD8F4, 0x5F58, + 0xD8F5, 0x5FA6, 0xD8F6, 0x5FA5, 0xD8F7, 0x5FAB, 0xD8F8, 0x60C9, 0xD8F9, 0x60B9, 0xD8FA, 0x60CC, 0xD8FB, 0x60E2, 0xD8FC, 0x60CE, + 0xD8FD, 0x60C4, 0xD8FE, 0x6114, 0xD940, 0x60F2, 0xD941, 0x610A, 0xD942, 0x6116, 0xD943, 0x6105, 0xD944, 0x60F5, 0xD945, 0x6113, + 0xD946, 0x60F8, 0xD947, 0x60FC, 0xD948, 0x60FE, 0xD949, 0x60C1, 0xD94A, 0x6103, 0xD94B, 0x6118, 0xD94C, 0x611D, 0xD94D, 0x6110, + 0xD94E, 0x60FF, 0xD94F, 0x6104, 0xD950, 0x610B, 0xD951, 0x624A, 0xD952, 0x6394, 0xD953, 0x63B1, 0xD954, 0x63B0, 0xD955, 0x63CE, + 0xD956, 0x63E5, 0xD957, 0x63E8, 0xD958, 0x63EF, 0xD959, 0x63C3, 0xD95A, 0x649D, 0xD95B, 0x63F3, 0xD95C, 0x63CA, 0xD95D, 0x63E0, + 0xD95E, 0x63F6, 0xD95F, 0x63D5, 0xD960, 0x63F2, 0xD961, 0x63F5, 0xD962, 0x6461, 0xD963, 0x63DF, 0xD964, 0x63BE, 0xD965, 0x63DD, + 0xD966, 0x63DC, 0xD967, 0x63C4, 0xD968, 0x63D8, 0xD969, 0x63D3, 0xD96A, 0x63C2, 0xD96B, 0x63C7, 0xD96C, 0x63CC, 0xD96D, 0x63CB, + 0xD96E, 0x63C8, 0xD96F, 0x63F0, 0xD970, 0x63D7, 0xD971, 0x63D9, 0xD972, 0x6532, 0xD973, 0x6567, 0xD974, 0x656A, 0xD975, 0x6564, + 0xD976, 0x655C, 0xD977, 0x6568, 0xD978, 0x6565, 0xD979, 0x658C, 0xD97A, 0x659D, 0xD97B, 0x659E, 0xD97C, 0x65AE, 0xD97D, 0x65D0, + 0xD97E, 0x65D2, 0xD9A1, 0x667C, 0xD9A2, 0x666C, 0xD9A3, 0x667B, 0xD9A4, 0x6680, 0xD9A5, 0x6671, 0xD9A6, 0x6679, 0xD9A7, 0x666A, + 0xD9A8, 0x6672, 0xD9A9, 0x6701, 0xD9AA, 0x690C, 0xD9AB, 0x68D3, 0xD9AC, 0x6904, 0xD9AD, 0x68DC, 0xD9AE, 0x692A, 0xD9AF, 0x68EC, + 0xD9B0, 0x68EA, 0xD9B1, 0x68F1, 0xD9B2, 0x690F, 0xD9B3, 0x68D6, 0xD9B4, 0x68F7, 0xD9B5, 0x68EB, 0xD9B6, 0x68E4, 0xD9B7, 0x68F6, + 0xD9B8, 0x6913, 0xD9B9, 0x6910, 0xD9BA, 0x68F3, 0xD9BB, 0x68E1, 0xD9BC, 0x6907, 0xD9BD, 0x68CC, 0xD9BE, 0x6908, 0xD9BF, 0x6970, + 0xD9C0, 0x68B4, 0xD9C1, 0x6911, 0xD9C2, 0x68EF, 0xD9C3, 0x68C6, 0xD9C4, 0x6914, 0xD9C5, 0x68F8, 0xD9C6, 0x68D0, 0xD9C7, 0x68FD, + 0xD9C8, 0x68FC, 0xD9C9, 0x68E8, 0xD9CA, 0x690B, 0xD9CB, 0x690A, 0xD9CC, 0x6917, 0xD9CD, 0x68CE, 0xD9CE, 0x68C8, 0xD9CF, 0x68DD, + 0xD9D0, 0x68DE, 0xD9D1, 0x68E6, 0xD9D2, 0x68F4, 0xD9D3, 0x68D1, 0xD9D4, 0x6906, 0xD9D5, 0x68D4, 0xD9D6, 0x68E9, 0xD9D7, 0x6915, + 0xD9D8, 0x6925, 0xD9D9, 0x68C7, 0xD9DA, 0x6B39, 0xD9DB, 0x6B3B, 0xD9DC, 0x6B3F, 0xD9DD, 0x6B3C, 0xD9DE, 0x6B94, 0xD9DF, 0x6B97, + 0xD9E0, 0x6B99, 0xD9E1, 0x6B95, 0xD9E2, 0x6BBD, 0xD9E3, 0x6BF0, 0xD9E4, 0x6BF2, 0xD9E5, 0x6BF3, 0xD9E6, 0x6C30, 0xD9E7, 0x6DFC, + 0xD9E8, 0x6E46, 0xD9E9, 0x6E47, 0xD9EA, 0x6E1F, 0xD9EB, 0x6E49, 0xD9EC, 0x6E88, 0xD9ED, 0x6E3C, 0xD9EE, 0x6E3D, 0xD9EF, 0x6E45, + 0xD9F0, 0x6E62, 0xD9F1, 0x6E2B, 0xD9F2, 0x6E3F, 0xD9F3, 0x6E41, 0xD9F4, 0x6E5D, 0xD9F5, 0x6E73, 0xD9F6, 0x6E1C, 0xD9F7, 0x6E33, + 0xD9F8, 0x6E4B, 0xD9F9, 0x6E40, 0xD9FA, 0x6E51, 0xD9FB, 0x6E3B, 0xD9FC, 0x6E03, 0xD9FD, 0x6E2E, 0xD9FE, 0x6E5E, 0xDA40, 0x6E68, + 0xDA41, 0x6E5C, 0xDA42, 0x6E61, 0xDA43, 0x6E31, 0xDA44, 0x6E28, 0xDA45, 0x6E60, 0xDA46, 0x6E71, 0xDA47, 0x6E6B, 0xDA48, 0x6E39, + 0xDA49, 0x6E22, 0xDA4A, 0x6E30, 0xDA4B, 0x6E53, 0xDA4C, 0x6E65, 0xDA4D, 0x6E27, 0xDA4E, 0x6E78, 0xDA4F, 0x6E64, 0xDA50, 0x6E77, + 0xDA51, 0x6E55, 0xDA52, 0x6E79, 0xDA53, 0x6E52, 0xDA54, 0x6E66, 0xDA55, 0x6E35, 0xDA56, 0x6E36, 0xDA57, 0x6E5A, 0xDA58, 0x7120, + 0xDA59, 0x711E, 0xDA5A, 0x712F, 0xDA5B, 0x70FB, 0xDA5C, 0x712E, 0xDA5D, 0x7131, 0xDA5E, 0x7123, 0xDA5F, 0x7125, 0xDA60, 0x7122, + 0xDA61, 0x7132, 0xDA62, 0x711F, 0xDA63, 0x7128, 0xDA64, 0x713A, 0xDA65, 0x711B, 0xDA66, 0x724B, 0xDA67, 0x725A, 0xDA68, 0x7288, + 0xDA69, 0x7289, 0xDA6A, 0x7286, 0xDA6B, 0x7285, 0xDA6C, 0x728B, 0xDA6D, 0x7312, 0xDA6E, 0x730B, 0xDA6F, 0x7330, 0xDA70, 0x7322, + 0xDA71, 0x7331, 0xDA72, 0x7333, 0xDA73, 0x7327, 0xDA74, 0x7332, 0xDA75, 0x732D, 0xDA76, 0x7326, 0xDA77, 0x7323, 0xDA78, 0x7335, + 0xDA79, 0x730C, 0xDA7A, 0x742E, 0xDA7B, 0x742C, 0xDA7C, 0x7430, 0xDA7D, 0x742B, 0xDA7E, 0x7416, 0xDAA1, 0x741A, 0xDAA2, 0x7421, + 0xDAA3, 0x742D, 0xDAA4, 0x7431, 0xDAA5, 0x7424, 0xDAA6, 0x7423, 0xDAA7, 0x741D, 0xDAA8, 0x7429, 0xDAA9, 0x7420, 0xDAAA, 0x7432, + 0xDAAB, 0x74FB, 0xDAAC, 0x752F, 0xDAAD, 0x756F, 0xDAAE, 0x756C, 0xDAAF, 0x75E7, 0xDAB0, 0x75DA, 0xDAB1, 0x75E1, 0xDAB2, 0x75E6, + 0xDAB3, 0x75DD, 0xDAB4, 0x75DF, 0xDAB5, 0x75E4, 0xDAB6, 0x75D7, 0xDAB7, 0x7695, 0xDAB8, 0x7692, 0xDAB9, 0x76DA, 0xDABA, 0x7746, + 0xDABB, 0x7747, 0xDABC, 0x7744, 0xDABD, 0x774D, 0xDABE, 0x7745, 0xDABF, 0x774A, 0xDAC0, 0x774E, 0xDAC1, 0x774B, 0xDAC2, 0x774C, + 0xDAC3, 0x77DE, 0xDAC4, 0x77EC, 0xDAC5, 0x7860, 0xDAC6, 0x7864, 0xDAC7, 0x7865, 0xDAC8, 0x785C, 0xDAC9, 0x786D, 0xDACA, 0x7871, + 0xDACB, 0x786A, 0xDACC, 0x786E, 0xDACD, 0x7870, 0xDACE, 0x7869, 0xDACF, 0x7868, 0xDAD0, 0x785E, 0xDAD1, 0x7862, 0xDAD2, 0x7974, + 0xDAD3, 0x7973, 0xDAD4, 0x7972, 0xDAD5, 0x7970, 0xDAD6, 0x7A02, 0xDAD7, 0x7A0A, 0xDAD8, 0x7A03, 0xDAD9, 0x7A0C, 0xDADA, 0x7A04, + 0xDADB, 0x7A99, 0xDADC, 0x7AE6, 0xDADD, 0x7AE4, 0xDADE, 0x7B4A, 0xDADF, 0x7B3B, 0xDAE0, 0x7B44, 0xDAE1, 0x7B48, 0xDAE2, 0x7B4C, + 0xDAE3, 0x7B4E, 0xDAE4, 0x7B40, 0xDAE5, 0x7B58, 0xDAE6, 0x7B45, 0xDAE7, 0x7CA2, 0xDAE8, 0x7C9E, 0xDAE9, 0x7CA8, 0xDAEA, 0x7CA1, + 0xDAEB, 0x7D58, 0xDAEC, 0x7D6F, 0xDAED, 0x7D63, 0xDAEE, 0x7D53, 0xDAEF, 0x7D56, 0xDAF0, 0x7D67, 0xDAF1, 0x7D6A, 0xDAF2, 0x7D4F, + 0xDAF3, 0x7D6D, 0xDAF4, 0x7D5C, 0xDAF5, 0x7D6B, 0xDAF6, 0x7D52, 0xDAF7, 0x7D54, 0xDAF8, 0x7D69, 0xDAF9, 0x7D51, 0xDAFA, 0x7D5F, + 0xDAFB, 0x7D4E, 0xDAFC, 0x7F3E, 0xDAFD, 0x7F3F, 0xDAFE, 0x7F65, 0xDB40, 0x7F66, 0xDB41, 0x7FA2, 0xDB42, 0x7FA0, 0xDB43, 0x7FA1, + 0xDB44, 0x7FD7, 0xDB45, 0x8051, 0xDB46, 0x804F, 0xDB47, 0x8050, 0xDB48, 0x80FE, 0xDB49, 0x80D4, 0xDB4A, 0x8143, 0xDB4B, 0x814A, + 0xDB4C, 0x8152, 0xDB4D, 0x814F, 0xDB4E, 0x8147, 0xDB4F, 0x813D, 0xDB50, 0x814D, 0xDB51, 0x813A, 0xDB52, 0x81E6, 0xDB53, 0x81EE, + 0xDB54, 0x81F7, 0xDB55, 0x81F8, 0xDB56, 0x81F9, 0xDB57, 0x8204, 0xDB58, 0x823C, 0xDB59, 0x823D, 0xDB5A, 0x823F, 0xDB5B, 0x8275, + 0xDB5C, 0x833B, 0xDB5D, 0x83CF, 0xDB5E, 0x83F9, 0xDB5F, 0x8423, 0xDB60, 0x83C0, 0xDB61, 0x83E8, 0xDB62, 0x8412, 0xDB63, 0x83E7, + 0xDB64, 0x83E4, 0xDB65, 0x83FC, 0xDB66, 0x83F6, 0xDB67, 0x8410, 0xDB68, 0x83C6, 0xDB69, 0x83C8, 0xDB6A, 0x83EB, 0xDB6B, 0x83E3, + 0xDB6C, 0x83BF, 0xDB6D, 0x8401, 0xDB6E, 0x83DD, 0xDB6F, 0x83E5, 0xDB70, 0x83D8, 0xDB71, 0x83FF, 0xDB72, 0x83E1, 0xDB73, 0x83CB, + 0xDB74, 0x83CE, 0xDB75, 0x83D6, 0xDB76, 0x83F5, 0xDB77, 0x83C9, 0xDB78, 0x8409, 0xDB79, 0x840F, 0xDB7A, 0x83DE, 0xDB7B, 0x8411, + 0xDB7C, 0x8406, 0xDB7D, 0x83C2, 0xDB7E, 0x83F3, 0xDBA1, 0x83D5, 0xDBA2, 0x83FA, 0xDBA3, 0x83C7, 0xDBA4, 0x83D1, 0xDBA5, 0x83EA, + 0xDBA6, 0x8413, 0xDBA7, 0x83C3, 0xDBA8, 0x83EC, 0xDBA9, 0x83EE, 0xDBAA, 0x83C4, 0xDBAB, 0x83FB, 0xDBAC, 0x83D7, 0xDBAD, 0x83E2, + 0xDBAE, 0x841B, 0xDBAF, 0x83DB, 0xDBB0, 0x83FE, 0xDBB1, 0x86D8, 0xDBB2, 0x86E2, 0xDBB3, 0x86E6, 0xDBB4, 0x86D3, 0xDBB5, 0x86E3, + 0xDBB6, 0x86DA, 0xDBB7, 0x86EA, 0xDBB8, 0x86DD, 0xDBB9, 0x86EB, 0xDBBA, 0x86DC, 0xDBBB, 0x86EC, 0xDBBC, 0x86E9, 0xDBBD, 0x86D7, + 0xDBBE, 0x86E8, 0xDBBF, 0x86D1, 0xDBC0, 0x8848, 0xDBC1, 0x8856, 0xDBC2, 0x8855, 0xDBC3, 0x88BA, 0xDBC4, 0x88D7, 0xDBC5, 0x88B9, + 0xDBC6, 0x88B8, 0xDBC7, 0x88C0, 0xDBC8, 0x88BE, 0xDBC9, 0x88B6, 0xDBCA, 0x88BC, 0xDBCB, 0x88B7, 0xDBCC, 0x88BD, 0xDBCD, 0x88B2, + 0xDBCE, 0x8901, 0xDBCF, 0x88C9, 0xDBD0, 0x8995, 0xDBD1, 0x8998, 0xDBD2, 0x8997, 0xDBD3, 0x89DD, 0xDBD4, 0x89DA, 0xDBD5, 0x89DB, + 0xDBD6, 0x8A4E, 0xDBD7, 0x8A4D, 0xDBD8, 0x8A39, 0xDBD9, 0x8A59, 0xDBDA, 0x8A40, 0xDBDB, 0x8A57, 0xDBDC, 0x8A58, 0xDBDD, 0x8A44, + 0xDBDE, 0x8A45, 0xDBDF, 0x8A52, 0xDBE0, 0x8A48, 0xDBE1, 0x8A51, 0xDBE2, 0x8A4A, 0xDBE3, 0x8A4C, 0xDBE4, 0x8A4F, 0xDBE5, 0x8C5F, + 0xDBE6, 0x8C81, 0xDBE7, 0x8C80, 0xDBE8, 0x8CBA, 0xDBE9, 0x8CBE, 0xDBEA, 0x8CB0, 0xDBEB, 0x8CB9, 0xDBEC, 0x8CB5, 0xDBED, 0x8D84, + 0xDBEE, 0x8D80, 0xDBEF, 0x8D89, 0xDBF0, 0x8DD8, 0xDBF1, 0x8DD3, 0xDBF2, 0x8DCD, 0xDBF3, 0x8DC7, 0xDBF4, 0x8DD6, 0xDBF5, 0x8DDC, + 0xDBF6, 0x8DCF, 0xDBF7, 0x8DD5, 0xDBF8, 0x8DD9, 0xDBF9, 0x8DC8, 0xDBFA, 0x8DD7, 0xDBFB, 0x8DC5, 0xDBFC, 0x8EEF, 0xDBFD, 0x8EF7, + 0xDBFE, 0x8EFA, 0xDC40, 0x8EF9, 0xDC41, 0x8EE6, 0xDC42, 0x8EEE, 0xDC43, 0x8EE5, 0xDC44, 0x8EF5, 0xDC45, 0x8EE7, 0xDC46, 0x8EE8, + 0xDC47, 0x8EF6, 0xDC48, 0x8EEB, 0xDC49, 0x8EF1, 0xDC4A, 0x8EEC, 0xDC4B, 0x8EF4, 0xDC4C, 0x8EE9, 0xDC4D, 0x902D, 0xDC4E, 0x9034, + 0xDC4F, 0x902F, 0xDC50, 0x9106, 0xDC51, 0x912C, 0xDC52, 0x9104, 0xDC53, 0x90FF, 0xDC54, 0x90FC, 0xDC55, 0x9108, 0xDC56, 0x90F9, + 0xDC57, 0x90FB, 0xDC58, 0x9101, 0xDC59, 0x9100, 0xDC5A, 0x9107, 0xDC5B, 0x9105, 0xDC5C, 0x9103, 0xDC5D, 0x9161, 0xDC5E, 0x9164, + 0xDC5F, 0x915F, 0xDC60, 0x9162, 0xDC61, 0x9160, 0xDC62, 0x9201, 0xDC63, 0x920A, 0xDC64, 0x9225, 0xDC65, 0x9203, 0xDC66, 0x921A, + 0xDC67, 0x9226, 0xDC68, 0x920F, 0xDC69, 0x920C, 0xDC6A, 0x9200, 0xDC6B, 0x9212, 0xDC6C, 0x91FF, 0xDC6D, 0x91FD, 0xDC6E, 0x9206, + 0xDC6F, 0x9204, 0xDC70, 0x9227, 0xDC71, 0x9202, 0xDC72, 0x921C, 0xDC73, 0x9224, 0xDC74, 0x9219, 0xDC75, 0x9217, 0xDC76, 0x9205, + 0xDC77, 0x9216, 0xDC78, 0x957B, 0xDC79, 0x958D, 0xDC7A, 0x958C, 0xDC7B, 0x9590, 0xDC7C, 0x9687, 0xDC7D, 0x967E, 0xDC7E, 0x9688, + 0xDCA1, 0x9689, 0xDCA2, 0x9683, 0xDCA3, 0x9680, 0xDCA4, 0x96C2, 0xDCA5, 0x96C8, 0xDCA6, 0x96C3, 0xDCA7, 0x96F1, 0xDCA8, 0x96F0, + 0xDCA9, 0x976C, 0xDCAA, 0x9770, 0xDCAB, 0x976E, 0xDCAC, 0x9807, 0xDCAD, 0x98A9, 0xDCAE, 0x98EB, 0xDCAF, 0x9CE6, 0xDCB0, 0x9EF9, + 0xDCB1, 0x4E83, 0xDCB2, 0x4E84, 0xDCB3, 0x4EB6, 0xDCB4, 0x50BD, 0xDCB5, 0x50BF, 0xDCB6, 0x50C6, 0xDCB7, 0x50AE, 0xDCB8, 0x50C4, + 0xDCB9, 0x50CA, 0xDCBA, 0x50B4, 0xDCBB, 0x50C8, 0xDCBC, 0x50C2, 0xDCBD, 0x50B0, 0xDCBE, 0x50C1, 0xDCBF, 0x50BA, 0xDCC0, 0x50B1, + 0xDCC1, 0x50CB, 0xDCC2, 0x50C9, 0xDCC3, 0x50B6, 0xDCC4, 0x50B8, 0xDCC5, 0x51D7, 0xDCC6, 0x527A, 0xDCC7, 0x5278, 0xDCC8, 0x527B, + 0xDCC9, 0x527C, 0xDCCA, 0x55C3, 0xDCCB, 0x55DB, 0xDCCC, 0x55CC, 0xDCCD, 0x55D0, 0xDCCE, 0x55CB, 0xDCCF, 0x55CA, 0xDCD0, 0x55DD, + 0xDCD1, 0x55C0, 0xDCD2, 0x55D4, 0xDCD3, 0x55C4, 0xDCD4, 0x55E9, 0xDCD5, 0x55BF, 0xDCD6, 0x55D2, 0xDCD7, 0x558D, 0xDCD8, 0x55CF, + 0xDCD9, 0x55D5, 0xDCDA, 0x55E2, 0xDCDB, 0x55D6, 0xDCDC, 0x55C8, 0xDCDD, 0x55F2, 0xDCDE, 0x55CD, 0xDCDF, 0x55D9, 0xDCE0, 0x55C2, + 0xDCE1, 0x5714, 0xDCE2, 0x5853, 0xDCE3, 0x5868, 0xDCE4, 0x5864, 0xDCE5, 0x584F, 0xDCE6, 0x584D, 0xDCE7, 0x5849, 0xDCE8, 0x586F, + 0xDCE9, 0x5855, 0xDCEA, 0x584E, 0xDCEB, 0x585D, 0xDCEC, 0x5859, 0xDCED, 0x5865, 0xDCEE, 0x585B, 0xDCEF, 0x583D, 0xDCF0, 0x5863, + 0xDCF1, 0x5871, 0xDCF2, 0x58FC, 0xDCF3, 0x5AC7, 0xDCF4, 0x5AC4, 0xDCF5, 0x5ACB, 0xDCF6, 0x5ABA, 0xDCF7, 0x5AB8, 0xDCF8, 0x5AB1, + 0xDCF9, 0x5AB5, 0xDCFA, 0x5AB0, 0xDCFB, 0x5ABF, 0xDCFC, 0x5AC8, 0xDCFD, 0x5ABB, 0xDCFE, 0x5AC6, 0xDD40, 0x5AB7, 0xDD41, 0x5AC0, + 0xDD42, 0x5ACA, 0xDD43, 0x5AB4, 0xDD44, 0x5AB6, 0xDD45, 0x5ACD, 0xDD46, 0x5AB9, 0xDD47, 0x5A90, 0xDD48, 0x5BD6, 0xDD49, 0x5BD8, + 0xDD4A, 0x5BD9, 0xDD4B, 0x5C1F, 0xDD4C, 0x5C33, 0xDD4D, 0x5D71, 0xDD4E, 0x5D63, 0xDD4F, 0x5D4A, 0xDD50, 0x5D65, 0xDD51, 0x5D72, + 0xDD52, 0x5D6C, 0xDD53, 0x5D5E, 0xDD54, 0x5D68, 0xDD55, 0x5D67, 0xDD56, 0x5D62, 0xDD57, 0x5DF0, 0xDD58, 0x5E4F, 0xDD59, 0x5E4E, + 0xDD5A, 0x5E4A, 0xDD5B, 0x5E4D, 0xDD5C, 0x5E4B, 0xDD5D, 0x5EC5, 0xDD5E, 0x5ECC, 0xDD5F, 0x5EC6, 0xDD60, 0x5ECB, 0xDD61, 0x5EC7, + 0xDD62, 0x5F40, 0xDD63, 0x5FAF, 0xDD64, 0x5FAD, 0xDD65, 0x60F7, 0xDD66, 0x6149, 0xDD67, 0x614A, 0xDD68, 0x612B, 0xDD69, 0x6145, + 0xDD6A, 0x6136, 0xDD6B, 0x6132, 0xDD6C, 0x612E, 0xDD6D, 0x6146, 0xDD6E, 0x612F, 0xDD6F, 0x614F, 0xDD70, 0x6129, 0xDD71, 0x6140, + 0xDD72, 0x6220, 0xDD73, 0x9168, 0xDD74, 0x6223, 0xDD75, 0x6225, 0xDD76, 0x6224, 0xDD77, 0x63C5, 0xDD78, 0x63F1, 0xDD79, 0x63EB, + 0xDD7A, 0x6410, 0xDD7B, 0x6412, 0xDD7C, 0x6409, 0xDD7D, 0x6420, 0xDD7E, 0x6424, 0xDDA1, 0x6433, 0xDDA2, 0x6443, 0xDDA3, 0x641F, + 0xDDA4, 0x6415, 0xDDA5, 0x6418, 0xDDA6, 0x6439, 0xDDA7, 0x6437, 0xDDA8, 0x6422, 0xDDA9, 0x6423, 0xDDAA, 0x640C, 0xDDAB, 0x6426, + 0xDDAC, 0x6430, 0xDDAD, 0x6428, 0xDDAE, 0x6441, 0xDDAF, 0x6435, 0xDDB0, 0x642F, 0xDDB1, 0x640A, 0xDDB2, 0x641A, 0xDDB3, 0x6440, + 0xDDB4, 0x6425, 0xDDB5, 0x6427, 0xDDB6, 0x640B, 0xDDB7, 0x63E7, 0xDDB8, 0x641B, 0xDDB9, 0x642E, 0xDDBA, 0x6421, 0xDDBB, 0x640E, + 0xDDBC, 0x656F, 0xDDBD, 0x6592, 0xDDBE, 0x65D3, 0xDDBF, 0x6686, 0xDDC0, 0x668C, 0xDDC1, 0x6695, 0xDDC2, 0x6690, 0xDDC3, 0x668B, + 0xDDC4, 0x668A, 0xDDC5, 0x6699, 0xDDC6, 0x6694, 0xDDC7, 0x6678, 0xDDC8, 0x6720, 0xDDC9, 0x6966, 0xDDCA, 0x695F, 0xDDCB, 0x6938, + 0xDDCC, 0x694E, 0xDDCD, 0x6962, 0xDDCE, 0x6971, 0xDDCF, 0x693F, 0xDDD0, 0x6945, 0xDDD1, 0x696A, 0xDDD2, 0x6939, 0xDDD3, 0x6942, + 0xDDD4, 0x6957, 0xDDD5, 0x6959, 0xDDD6, 0x697A, 0xDDD7, 0x6948, 0xDDD8, 0x6949, 0xDDD9, 0x6935, 0xDDDA, 0x696C, 0xDDDB, 0x6933, + 0xDDDC, 0x693D, 0xDDDD, 0x6965, 0xDDDE, 0x68F0, 0xDDDF, 0x6978, 0xDDE0, 0x6934, 0xDDE1, 0x6969, 0xDDE2, 0x6940, 0xDDE3, 0x696F, + 0xDDE4, 0x6944, 0xDDE5, 0x6976, 0xDDE6, 0x6958, 0xDDE7, 0x6941, 0xDDE8, 0x6974, 0xDDE9, 0x694C, 0xDDEA, 0x693B, 0xDDEB, 0x694B, + 0xDDEC, 0x6937, 0xDDED, 0x695C, 0xDDEE, 0x694F, 0xDDEF, 0x6951, 0xDDF0, 0x6932, 0xDDF1, 0x6952, 0xDDF2, 0x692F, 0xDDF3, 0x697B, + 0xDDF4, 0x693C, 0xDDF5, 0x6B46, 0xDDF6, 0x6B45, 0xDDF7, 0x6B43, 0xDDF8, 0x6B42, 0xDDF9, 0x6B48, 0xDDFA, 0x6B41, 0xDDFB, 0x6B9B, + 0xDDFC, 0xFA0D, 0xDDFD, 0x6BFB, 0xDDFE, 0x6BFC, 0xDE40, 0x6BF9, 0xDE41, 0x6BF7, 0xDE42, 0x6BF8, 0xDE43, 0x6E9B, 0xDE44, 0x6ED6, + 0xDE45, 0x6EC8, 0xDE46, 0x6E8F, 0xDE47, 0x6EC0, 0xDE48, 0x6E9F, 0xDE49, 0x6E93, 0xDE4A, 0x6E94, 0xDE4B, 0x6EA0, 0xDE4C, 0x6EB1, + 0xDE4D, 0x6EB9, 0xDE4E, 0x6EC6, 0xDE4F, 0x6ED2, 0xDE50, 0x6EBD, 0xDE51, 0x6EC1, 0xDE52, 0x6E9E, 0xDE53, 0x6EC9, 0xDE54, 0x6EB7, + 0xDE55, 0x6EB0, 0xDE56, 0x6ECD, 0xDE57, 0x6EA6, 0xDE58, 0x6ECF, 0xDE59, 0x6EB2, 0xDE5A, 0x6EBE, 0xDE5B, 0x6EC3, 0xDE5C, 0x6EDC, + 0xDE5D, 0x6ED8, 0xDE5E, 0x6E99, 0xDE5F, 0x6E92, 0xDE60, 0x6E8E, 0xDE61, 0x6E8D, 0xDE62, 0x6EA4, 0xDE63, 0x6EA1, 0xDE64, 0x6EBF, + 0xDE65, 0x6EB3, 0xDE66, 0x6ED0, 0xDE67, 0x6ECA, 0xDE68, 0x6E97, 0xDE69, 0x6EAE, 0xDE6A, 0x6EA3, 0xDE6B, 0x7147, 0xDE6C, 0x7154, + 0xDE6D, 0x7152, 0xDE6E, 0x7163, 0xDE6F, 0x7160, 0xDE70, 0x7141, 0xDE71, 0x715D, 0xDE72, 0x7162, 0xDE73, 0x7172, 0xDE74, 0x7178, + 0xDE75, 0x716A, 0xDE76, 0x7161, 0xDE77, 0x7142, 0xDE78, 0x7158, 0xDE79, 0x7143, 0xDE7A, 0x714B, 0xDE7B, 0x7170, 0xDE7C, 0x715F, + 0xDE7D, 0x7150, 0xDE7E, 0x7153, 0xDEA1, 0x7144, 0xDEA2, 0x714D, 0xDEA3, 0x715A, 0xDEA4, 0x724F, 0xDEA5, 0x728D, 0xDEA6, 0x728C, + 0xDEA7, 0x7291, 0xDEA8, 0x7290, 0xDEA9, 0x728E, 0xDEAA, 0x733C, 0xDEAB, 0x7342, 0xDEAC, 0x733B, 0xDEAD, 0x733A, 0xDEAE, 0x7340, + 0xDEAF, 0x734A, 0xDEB0, 0x7349, 0xDEB1, 0x7444, 0xDEB2, 0x744A, 0xDEB3, 0x744B, 0xDEB4, 0x7452, 0xDEB5, 0x7451, 0xDEB6, 0x7457, + 0xDEB7, 0x7440, 0xDEB8, 0x744F, 0xDEB9, 0x7450, 0xDEBA, 0x744E, 0xDEBB, 0x7442, 0xDEBC, 0x7446, 0xDEBD, 0x744D, 0xDEBE, 0x7454, + 0xDEBF, 0x74E1, 0xDEC0, 0x74FF, 0xDEC1, 0x74FE, 0xDEC2, 0x74FD, 0xDEC3, 0x751D, 0xDEC4, 0x7579, 0xDEC5, 0x7577, 0xDEC6, 0x6983, + 0xDEC7, 0x75EF, 0xDEC8, 0x760F, 0xDEC9, 0x7603, 0xDECA, 0x75F7, 0xDECB, 0x75FE, 0xDECC, 0x75FC, 0xDECD, 0x75F9, 0xDECE, 0x75F8, + 0xDECF, 0x7610, 0xDED0, 0x75FB, 0xDED1, 0x75F6, 0xDED2, 0x75ED, 0xDED3, 0x75F5, 0xDED4, 0x75FD, 0xDED5, 0x7699, 0xDED6, 0x76B5, + 0xDED7, 0x76DD, 0xDED8, 0x7755, 0xDED9, 0x775F, 0xDEDA, 0x7760, 0xDEDB, 0x7752, 0xDEDC, 0x7756, 0xDEDD, 0x775A, 0xDEDE, 0x7769, + 0xDEDF, 0x7767, 0xDEE0, 0x7754, 0xDEE1, 0x7759, 0xDEE2, 0x776D, 0xDEE3, 0x77E0, 0xDEE4, 0x7887, 0xDEE5, 0x789A, 0xDEE6, 0x7894, + 0xDEE7, 0x788F, 0xDEE8, 0x7884, 0xDEE9, 0x7895, 0xDEEA, 0x7885, 0xDEEB, 0x7886, 0xDEEC, 0x78A1, 0xDEED, 0x7883, 0xDEEE, 0x7879, + 0xDEEF, 0x7899, 0xDEF0, 0x7880, 0xDEF1, 0x7896, 0xDEF2, 0x787B, 0xDEF3, 0x797C, 0xDEF4, 0x7982, 0xDEF5, 0x797D, 0xDEF6, 0x7979, + 0xDEF7, 0x7A11, 0xDEF8, 0x7A18, 0xDEF9, 0x7A19, 0xDEFA, 0x7A12, 0xDEFB, 0x7A17, 0xDEFC, 0x7A15, 0xDEFD, 0x7A22, 0xDEFE, 0x7A13, + 0xDF40, 0x7A1B, 0xDF41, 0x7A10, 0xDF42, 0x7AA3, 0xDF43, 0x7AA2, 0xDF44, 0x7A9E, 0xDF45, 0x7AEB, 0xDF46, 0x7B66, 0xDF47, 0x7B64, + 0xDF48, 0x7B6D, 0xDF49, 0x7B74, 0xDF4A, 0x7B69, 0xDF4B, 0x7B72, 0xDF4C, 0x7B65, 0xDF4D, 0x7B73, 0xDF4E, 0x7B71, 0xDF4F, 0x7B70, + 0xDF50, 0x7B61, 0xDF51, 0x7B78, 0xDF52, 0x7B76, 0xDF53, 0x7B63, 0xDF54, 0x7CB2, 0xDF55, 0x7CB4, 0xDF56, 0x7CAF, 0xDF57, 0x7D88, + 0xDF58, 0x7D86, 0xDF59, 0x7D80, 0xDF5A, 0x7D8D, 0xDF5B, 0x7D7F, 0xDF5C, 0x7D85, 0xDF5D, 0x7D7A, 0xDF5E, 0x7D8E, 0xDF5F, 0x7D7B, + 0xDF60, 0x7D83, 0xDF61, 0x7D7C, 0xDF62, 0x7D8C, 0xDF63, 0x7D94, 0xDF64, 0x7D84, 0xDF65, 0x7D7D, 0xDF66, 0x7D92, 0xDF67, 0x7F6D, + 0xDF68, 0x7F6B, 0xDF69, 0x7F67, 0xDF6A, 0x7F68, 0xDF6B, 0x7F6C, 0xDF6C, 0x7FA6, 0xDF6D, 0x7FA5, 0xDF6E, 0x7FA7, 0xDF6F, 0x7FDB, + 0xDF70, 0x7FDC, 0xDF71, 0x8021, 0xDF72, 0x8164, 0xDF73, 0x8160, 0xDF74, 0x8177, 0xDF75, 0x815C, 0xDF76, 0x8169, 0xDF77, 0x815B, + 0xDF78, 0x8162, 0xDF79, 0x8172, 0xDF7A, 0x6721, 0xDF7B, 0x815E, 0xDF7C, 0x8176, 0xDF7D, 0x8167, 0xDF7E, 0x816F, 0xDFA1, 0x8144, + 0xDFA2, 0x8161, 0xDFA3, 0x821D, 0xDFA4, 0x8249, 0xDFA5, 0x8244, 0xDFA6, 0x8240, 0xDFA7, 0x8242, 0xDFA8, 0x8245, 0xDFA9, 0x84F1, + 0xDFAA, 0x843F, 0xDFAB, 0x8456, 0xDFAC, 0x8476, 0xDFAD, 0x8479, 0xDFAE, 0x848F, 0xDFAF, 0x848D, 0xDFB0, 0x8465, 0xDFB1, 0x8451, + 0xDFB2, 0x8440, 0xDFB3, 0x8486, 0xDFB4, 0x8467, 0xDFB5, 0x8430, 0xDFB6, 0x844D, 0xDFB7, 0x847D, 0xDFB8, 0x845A, 0xDFB9, 0x8459, + 0xDFBA, 0x8474, 0xDFBB, 0x8473, 0xDFBC, 0x845D, 0xDFBD, 0x8507, 0xDFBE, 0x845E, 0xDFBF, 0x8437, 0xDFC0, 0x843A, 0xDFC1, 0x8434, + 0xDFC2, 0x847A, 0xDFC3, 0x8443, 0xDFC4, 0x8478, 0xDFC5, 0x8432, 0xDFC6, 0x8445, 0xDFC7, 0x8429, 0xDFC8, 0x83D9, 0xDFC9, 0x844B, + 0xDFCA, 0x842F, 0xDFCB, 0x8442, 0xDFCC, 0x842D, 0xDFCD, 0x845F, 0xDFCE, 0x8470, 0xDFCF, 0x8439, 0xDFD0, 0x844E, 0xDFD1, 0x844C, + 0xDFD2, 0x8452, 0xDFD3, 0x846F, 0xDFD4, 0x84C5, 0xDFD5, 0x848E, 0xDFD6, 0x843B, 0xDFD7, 0x8447, 0xDFD8, 0x8436, 0xDFD9, 0x8433, + 0xDFDA, 0x8468, 0xDFDB, 0x847E, 0xDFDC, 0x8444, 0xDFDD, 0x842B, 0xDFDE, 0x8460, 0xDFDF, 0x8454, 0xDFE0, 0x846E, 0xDFE1, 0x8450, + 0xDFE2, 0x870B, 0xDFE3, 0x8704, 0xDFE4, 0x86F7, 0xDFE5, 0x870C, 0xDFE6, 0x86FA, 0xDFE7, 0x86D6, 0xDFE8, 0x86F5, 0xDFE9, 0x874D, + 0xDFEA, 0x86F8, 0xDFEB, 0x870E, 0xDFEC, 0x8709, 0xDFED, 0x8701, 0xDFEE, 0x86F6, 0xDFEF, 0x870D, 0xDFF0, 0x8705, 0xDFF1, 0x88D6, + 0xDFF2, 0x88CB, 0xDFF3, 0x88CD, 0xDFF4, 0x88CE, 0xDFF5, 0x88DE, 0xDFF6, 0x88DB, 0xDFF7, 0x88DA, 0xDFF8, 0x88CC, 0xDFF9, 0x88D0, + 0xDFFA, 0x8985, 0xDFFB, 0x899B, 0xDFFC, 0x89DF, 0xDFFD, 0x89E5, 0xDFFE, 0x89E4, 0xE040, 0x89E1, 0xE041, 0x89E0, 0xE042, 0x89E2, + 0xE043, 0x89DC, 0xE044, 0x89E6, 0xE045, 0x8A76, 0xE046, 0x8A86, 0xE047, 0x8A7F, 0xE048, 0x8A61, 0xE049, 0x8A3F, 0xE04A, 0x8A77, + 0xE04B, 0x8A82, 0xE04C, 0x8A84, 0xE04D, 0x8A75, 0xE04E, 0x8A83, 0xE04F, 0x8A81, 0xE050, 0x8A74, 0xE051, 0x8A7A, 0xE052, 0x8C3C, + 0xE053, 0x8C4B, 0xE054, 0x8C4A, 0xE055, 0x8C65, 0xE056, 0x8C64, 0xE057, 0x8C66, 0xE058, 0x8C86, 0xE059, 0x8C84, 0xE05A, 0x8C85, + 0xE05B, 0x8CCC, 0xE05C, 0x8D68, 0xE05D, 0x8D69, 0xE05E, 0x8D91, 0xE05F, 0x8D8C, 0xE060, 0x8D8E, 0xE061, 0x8D8F, 0xE062, 0x8D8D, + 0xE063, 0x8D93, 0xE064, 0x8D94, 0xE065, 0x8D90, 0xE066, 0x8D92, 0xE067, 0x8DF0, 0xE068, 0x8DE0, 0xE069, 0x8DEC, 0xE06A, 0x8DF1, + 0xE06B, 0x8DEE, 0xE06C, 0x8DD0, 0xE06D, 0x8DE9, 0xE06E, 0x8DE3, 0xE06F, 0x8DE2, 0xE070, 0x8DE7, 0xE071, 0x8DF2, 0xE072, 0x8DEB, + 0xE073, 0x8DF4, 0xE074, 0x8F06, 0xE075, 0x8EFF, 0xE076, 0x8F01, 0xE077, 0x8F00, 0xE078, 0x8F05, 0xE079, 0x8F07, 0xE07A, 0x8F08, + 0xE07B, 0x8F02, 0xE07C, 0x8F0B, 0xE07D, 0x9052, 0xE07E, 0x903F, 0xE0A1, 0x9044, 0xE0A2, 0x9049, 0xE0A3, 0x903D, 0xE0A4, 0x9110, + 0xE0A5, 0x910D, 0xE0A6, 0x910F, 0xE0A7, 0x9111, 0xE0A8, 0x9116, 0xE0A9, 0x9114, 0xE0AA, 0x910B, 0xE0AB, 0x910E, 0xE0AC, 0x916E, + 0xE0AD, 0x916F, 0xE0AE, 0x9248, 0xE0AF, 0x9252, 0xE0B0, 0x9230, 0xE0B1, 0x923A, 0xE0B2, 0x9266, 0xE0B3, 0x9233, 0xE0B4, 0x9265, + 0xE0B5, 0x925E, 0xE0B6, 0x9283, 0xE0B7, 0x922E, 0xE0B8, 0x924A, 0xE0B9, 0x9246, 0xE0BA, 0x926D, 0xE0BB, 0x926C, 0xE0BC, 0x924F, + 0xE0BD, 0x9260, 0xE0BE, 0x9267, 0xE0BF, 0x926F, 0xE0C0, 0x9236, 0xE0C1, 0x9261, 0xE0C2, 0x9270, 0xE0C3, 0x9231, 0xE0C4, 0x9254, + 0xE0C5, 0x9263, 0xE0C6, 0x9250, 0xE0C7, 0x9272, 0xE0C8, 0x924E, 0xE0C9, 0x9253, 0xE0CA, 0x924C, 0xE0CB, 0x9256, 0xE0CC, 0x9232, + 0xE0CD, 0x959F, 0xE0CE, 0x959C, 0xE0CF, 0x959E, 0xE0D0, 0x959B, 0xE0D1, 0x9692, 0xE0D2, 0x9693, 0xE0D3, 0x9691, 0xE0D4, 0x9697, + 0xE0D5, 0x96CE, 0xE0D6, 0x96FA, 0xE0D7, 0x96FD, 0xE0D8, 0x96F8, 0xE0D9, 0x96F5, 0xE0DA, 0x9773, 0xE0DB, 0x9777, 0xE0DC, 0x9778, + 0xE0DD, 0x9772, 0xE0DE, 0x980F, 0xE0DF, 0x980D, 0xE0E0, 0x980E, 0xE0E1, 0x98AC, 0xE0E2, 0x98F6, 0xE0E3, 0x98F9, 0xE0E4, 0x99AF, + 0xE0E5, 0x99B2, 0xE0E6, 0x99B0, 0xE0E7, 0x99B5, 0xE0E8, 0x9AAD, 0xE0E9, 0x9AAB, 0xE0EA, 0x9B5B, 0xE0EB, 0x9CEA, 0xE0EC, 0x9CED, + 0xE0ED, 0x9CE7, 0xE0EE, 0x9E80, 0xE0EF, 0x9EFD, 0xE0F0, 0x50E6, 0xE0F1, 0x50D4, 0xE0F2, 0x50D7, 0xE0F3, 0x50E8, 0xE0F4, 0x50F3, + 0xE0F5, 0x50DB, 0xE0F6, 0x50EA, 0xE0F7, 0x50DD, 0xE0F8, 0x50E4, 0xE0F9, 0x50D3, 0xE0FA, 0x50EC, 0xE0FB, 0x50F0, 0xE0FC, 0x50EF, + 0xE0FD, 0x50E3, 0xE0FE, 0x50E0, 0xE140, 0x51D8, 0xE141, 0x5280, 0xE142, 0x5281, 0xE143, 0x52E9, 0xE144, 0x52EB, 0xE145, 0x5330, + 0xE146, 0x53AC, 0xE147, 0x5627, 0xE148, 0x5615, 0xE149, 0x560C, 0xE14A, 0x5612, 0xE14B, 0x55FC, 0xE14C, 0x560F, 0xE14D, 0x561C, + 0xE14E, 0x5601, 0xE14F, 0x5613, 0xE150, 0x5602, 0xE151, 0x55FA, 0xE152, 0x561D, 0xE153, 0x5604, 0xE154, 0x55FF, 0xE155, 0x55F9, + 0xE156, 0x5889, 0xE157, 0x587C, 0xE158, 0x5890, 0xE159, 0x5898, 0xE15A, 0x5886, 0xE15B, 0x5881, 0xE15C, 0x587F, 0xE15D, 0x5874, + 0xE15E, 0x588B, 0xE15F, 0x587A, 0xE160, 0x5887, 0xE161, 0x5891, 0xE162, 0x588E, 0xE163, 0x5876, 0xE164, 0x5882, 0xE165, 0x5888, + 0xE166, 0x587B, 0xE167, 0x5894, 0xE168, 0x588F, 0xE169, 0x58FE, 0xE16A, 0x596B, 0xE16B, 0x5ADC, 0xE16C, 0x5AEE, 0xE16D, 0x5AE5, + 0xE16E, 0x5AD5, 0xE16F, 0x5AEA, 0xE170, 0x5ADA, 0xE171, 0x5AED, 0xE172, 0x5AEB, 0xE173, 0x5AF3, 0xE174, 0x5AE2, 0xE175, 0x5AE0, + 0xE176, 0x5ADB, 0xE177, 0x5AEC, 0xE178, 0x5ADE, 0xE179, 0x5ADD, 0xE17A, 0x5AD9, 0xE17B, 0x5AE8, 0xE17C, 0x5ADF, 0xE17D, 0x5B77, + 0xE17E, 0x5BE0, 0xE1A1, 0x5BE3, 0xE1A2, 0x5C63, 0xE1A3, 0x5D82, 0xE1A4, 0x5D80, 0xE1A5, 0x5D7D, 0xE1A6, 0x5D86, 0xE1A7, 0x5D7A, + 0xE1A8, 0x5D81, 0xE1A9, 0x5D77, 0xE1AA, 0x5D8A, 0xE1AB, 0x5D89, 0xE1AC, 0x5D88, 0xE1AD, 0x5D7E, 0xE1AE, 0x5D7C, 0xE1AF, 0x5D8D, + 0xE1B0, 0x5D79, 0xE1B1, 0x5D7F, 0xE1B2, 0x5E58, 0xE1B3, 0x5E59, 0xE1B4, 0x5E53, 0xE1B5, 0x5ED8, 0xE1B6, 0x5ED1, 0xE1B7, 0x5ED7, + 0xE1B8, 0x5ECE, 0xE1B9, 0x5EDC, 0xE1BA, 0x5ED5, 0xE1BB, 0x5ED9, 0xE1BC, 0x5ED2, 0xE1BD, 0x5ED4, 0xE1BE, 0x5F44, 0xE1BF, 0x5F43, + 0xE1C0, 0x5F6F, 0xE1C1, 0x5FB6, 0xE1C2, 0x612C, 0xE1C3, 0x6128, 0xE1C4, 0x6141, 0xE1C5, 0x615E, 0xE1C6, 0x6171, 0xE1C7, 0x6173, + 0xE1C8, 0x6152, 0xE1C9, 0x6153, 0xE1CA, 0x6172, 0xE1CB, 0x616C, 0xE1CC, 0x6180, 0xE1CD, 0x6174, 0xE1CE, 0x6154, 0xE1CF, 0x617A, + 0xE1D0, 0x615B, 0xE1D1, 0x6165, 0xE1D2, 0x613B, 0xE1D3, 0x616A, 0xE1D4, 0x6161, 0xE1D5, 0x6156, 0xE1D6, 0x6229, 0xE1D7, 0x6227, + 0xE1D8, 0x622B, 0xE1D9, 0x642B, 0xE1DA, 0x644D, 0xE1DB, 0x645B, 0xE1DC, 0x645D, 0xE1DD, 0x6474, 0xE1DE, 0x6476, 0xE1DF, 0x6472, + 0xE1E0, 0x6473, 0xE1E1, 0x647D, 0xE1E2, 0x6475, 0xE1E3, 0x6466, 0xE1E4, 0x64A6, 0xE1E5, 0x644E, 0xE1E6, 0x6482, 0xE1E7, 0x645E, + 0xE1E8, 0x645C, 0xE1E9, 0x644B, 0xE1EA, 0x6453, 0xE1EB, 0x6460, 0xE1EC, 0x6450, 0xE1ED, 0x647F, 0xE1EE, 0x643F, 0xE1EF, 0x646C, + 0xE1F0, 0x646B, 0xE1F1, 0x6459, 0xE1F2, 0x6465, 0xE1F3, 0x6477, 0xE1F4, 0x6573, 0xE1F5, 0x65A0, 0xE1F6, 0x66A1, 0xE1F7, 0x66A0, + 0xE1F8, 0x669F, 0xE1F9, 0x6705, 0xE1FA, 0x6704, 0xE1FB, 0x6722, 0xE1FC, 0x69B1, 0xE1FD, 0x69B6, 0xE1FE, 0x69C9, 0xE240, 0x69A0, + 0xE241, 0x69CE, 0xE242, 0x6996, 0xE243, 0x69B0, 0xE244, 0x69AC, 0xE245, 0x69BC, 0xE246, 0x6991, 0xE247, 0x6999, 0xE248, 0x698E, + 0xE249, 0x69A7, 0xE24A, 0x698D, 0xE24B, 0x69A9, 0xE24C, 0x69BE, 0xE24D, 0x69AF, 0xE24E, 0x69BF, 0xE24F, 0x69C4, 0xE250, 0x69BD, + 0xE251, 0x69A4, 0xE252, 0x69D4, 0xE253, 0x69B9, 0xE254, 0x69CA, 0xE255, 0x699A, 0xE256, 0x69CF, 0xE257, 0x69B3, 0xE258, 0x6993, + 0xE259, 0x69AA, 0xE25A, 0x69A1, 0xE25B, 0x699E, 0xE25C, 0x69D9, 0xE25D, 0x6997, 0xE25E, 0x6990, 0xE25F, 0x69C2, 0xE260, 0x69B5, + 0xE261, 0x69A5, 0xE262, 0x69C6, 0xE263, 0x6B4A, 0xE264, 0x6B4D, 0xE265, 0x6B4B, 0xE266, 0x6B9E, 0xE267, 0x6B9F, 0xE268, 0x6BA0, + 0xE269, 0x6BC3, 0xE26A, 0x6BC4, 0xE26B, 0x6BFE, 0xE26C, 0x6ECE, 0xE26D, 0x6EF5, 0xE26E, 0x6EF1, 0xE26F, 0x6F03, 0xE270, 0x6F25, + 0xE271, 0x6EF8, 0xE272, 0x6F37, 0xE273, 0x6EFB, 0xE274, 0x6F2E, 0xE275, 0x6F09, 0xE276, 0x6F4E, 0xE277, 0x6F19, 0xE278, 0x6F1A, + 0xE279, 0x6F27, 0xE27A, 0x6F18, 0xE27B, 0x6F3B, 0xE27C, 0x6F12, 0xE27D, 0x6EED, 0xE27E, 0x6F0A, 0xE2A1, 0x6F36, 0xE2A2, 0x6F73, + 0xE2A3, 0x6EF9, 0xE2A4, 0x6EEE, 0xE2A5, 0x6F2D, 0xE2A6, 0x6F40, 0xE2A7, 0x6F30, 0xE2A8, 0x6F3C, 0xE2A9, 0x6F35, 0xE2AA, 0x6EEB, + 0xE2AB, 0x6F07, 0xE2AC, 0x6F0E, 0xE2AD, 0x6F43, 0xE2AE, 0x6F05, 0xE2AF, 0x6EFD, 0xE2B0, 0x6EF6, 0xE2B1, 0x6F39, 0xE2B2, 0x6F1C, + 0xE2B3, 0x6EFC, 0xE2B4, 0x6F3A, 0xE2B5, 0x6F1F, 0xE2B6, 0x6F0D, 0xE2B7, 0x6F1E, 0xE2B8, 0x6F08, 0xE2B9, 0x6F21, 0xE2BA, 0x7187, + 0xE2BB, 0x7190, 0xE2BC, 0x7189, 0xE2BD, 0x7180, 0xE2BE, 0x7185, 0xE2BF, 0x7182, 0xE2C0, 0x718F, 0xE2C1, 0x717B, 0xE2C2, 0x7186, + 0xE2C3, 0x7181, 0xE2C4, 0x7197, 0xE2C5, 0x7244, 0xE2C6, 0x7253, 0xE2C7, 0x7297, 0xE2C8, 0x7295, 0xE2C9, 0x7293, 0xE2CA, 0x7343, + 0xE2CB, 0x734D, 0xE2CC, 0x7351, 0xE2CD, 0x734C, 0xE2CE, 0x7462, 0xE2CF, 0x7473, 0xE2D0, 0x7471, 0xE2D1, 0x7475, 0xE2D2, 0x7472, + 0xE2D3, 0x7467, 0xE2D4, 0x746E, 0xE2D5, 0x7500, 0xE2D6, 0x7502, 0xE2D7, 0x7503, 0xE2D8, 0x757D, 0xE2D9, 0x7590, 0xE2DA, 0x7616, + 0xE2DB, 0x7608, 0xE2DC, 0x760C, 0xE2DD, 0x7615, 0xE2DE, 0x7611, 0xE2DF, 0x760A, 0xE2E0, 0x7614, 0xE2E1, 0x76B8, 0xE2E2, 0x7781, + 0xE2E3, 0x777C, 0xE2E4, 0x7785, 0xE2E5, 0x7782, 0xE2E6, 0x776E, 0xE2E7, 0x7780, 0xE2E8, 0x776F, 0xE2E9, 0x777E, 0xE2EA, 0x7783, + 0xE2EB, 0x78B2, 0xE2EC, 0x78AA, 0xE2ED, 0x78B4, 0xE2EE, 0x78AD, 0xE2EF, 0x78A8, 0xE2F0, 0x787E, 0xE2F1, 0x78AB, 0xE2F2, 0x789E, + 0xE2F3, 0x78A5, 0xE2F4, 0x78A0, 0xE2F5, 0x78AC, 0xE2F6, 0x78A2, 0xE2F7, 0x78A4, 0xE2F8, 0x7998, 0xE2F9, 0x798A, 0xE2FA, 0x798B, + 0xE2FB, 0x7996, 0xE2FC, 0x7995, 0xE2FD, 0x7994, 0xE2FE, 0x7993, 0xE340, 0x7997, 0xE341, 0x7988, 0xE342, 0x7992, 0xE343, 0x7990, + 0xE344, 0x7A2B, 0xE345, 0x7A4A, 0xE346, 0x7A30, 0xE347, 0x7A2F, 0xE348, 0x7A28, 0xE349, 0x7A26, 0xE34A, 0x7AA8, 0xE34B, 0x7AAB, + 0xE34C, 0x7AAC, 0xE34D, 0x7AEE, 0xE34E, 0x7B88, 0xE34F, 0x7B9C, 0xE350, 0x7B8A, 0xE351, 0x7B91, 0xE352, 0x7B90, 0xE353, 0x7B96, + 0xE354, 0x7B8D, 0xE355, 0x7B8C, 0xE356, 0x7B9B, 0xE357, 0x7B8E, 0xE358, 0x7B85, 0xE359, 0x7B98, 0xE35A, 0x5284, 0xE35B, 0x7B99, + 0xE35C, 0x7BA4, 0xE35D, 0x7B82, 0xE35E, 0x7CBB, 0xE35F, 0x7CBF, 0xE360, 0x7CBC, 0xE361, 0x7CBA, 0xE362, 0x7DA7, 0xE363, 0x7DB7, + 0xE364, 0x7DC2, 0xE365, 0x7DA3, 0xE366, 0x7DAA, 0xE367, 0x7DC1, 0xE368, 0x7DC0, 0xE369, 0x7DC5, 0xE36A, 0x7D9D, 0xE36B, 0x7DCE, + 0xE36C, 0x7DC4, 0xE36D, 0x7DC6, 0xE36E, 0x7DCB, 0xE36F, 0x7DCC, 0xE370, 0x7DAF, 0xE371, 0x7DB9, 0xE372, 0x7D96, 0xE373, 0x7DBC, + 0xE374, 0x7D9F, 0xE375, 0x7DA6, 0xE376, 0x7DAE, 0xE377, 0x7DA9, 0xE378, 0x7DA1, 0xE379, 0x7DC9, 0xE37A, 0x7F73, 0xE37B, 0x7FE2, + 0xE37C, 0x7FE3, 0xE37D, 0x7FE5, 0xE37E, 0x7FDE, 0xE3A1, 0x8024, 0xE3A2, 0x805D, 0xE3A3, 0x805C, 0xE3A4, 0x8189, 0xE3A5, 0x8186, + 0xE3A6, 0x8183, 0xE3A7, 0x8187, 0xE3A8, 0x818D, 0xE3A9, 0x818C, 0xE3AA, 0x818B, 0xE3AB, 0x8215, 0xE3AC, 0x8497, 0xE3AD, 0x84A4, + 0xE3AE, 0x84A1, 0xE3AF, 0x849F, 0xE3B0, 0x84BA, 0xE3B1, 0x84CE, 0xE3B2, 0x84C2, 0xE3B3, 0x84AC, 0xE3B4, 0x84AE, 0xE3B5, 0x84AB, + 0xE3B6, 0x84B9, 0xE3B7, 0x84B4, 0xE3B8, 0x84C1, 0xE3B9, 0x84CD, 0xE3BA, 0x84AA, 0xE3BB, 0x849A, 0xE3BC, 0x84B1, 0xE3BD, 0x84D0, + 0xE3BE, 0x849D, 0xE3BF, 0x84A7, 0xE3C0, 0x84BB, 0xE3C1, 0x84A2, 0xE3C2, 0x8494, 0xE3C3, 0x84C7, 0xE3C4, 0x84CC, 0xE3C5, 0x849B, + 0xE3C6, 0x84A9, 0xE3C7, 0x84AF, 0xE3C8, 0x84A8, 0xE3C9, 0x84D6, 0xE3CA, 0x8498, 0xE3CB, 0x84B6, 0xE3CC, 0x84CF, 0xE3CD, 0x84A0, + 0xE3CE, 0x84D7, 0xE3CF, 0x84D4, 0xE3D0, 0x84D2, 0xE3D1, 0x84DB, 0xE3D2, 0x84B0, 0xE3D3, 0x8491, 0xE3D4, 0x8661, 0xE3D5, 0x8733, + 0xE3D6, 0x8723, 0xE3D7, 0x8728, 0xE3D8, 0x876B, 0xE3D9, 0x8740, 0xE3DA, 0x872E, 0xE3DB, 0x871E, 0xE3DC, 0x8721, 0xE3DD, 0x8719, + 0xE3DE, 0x871B, 0xE3DF, 0x8743, 0xE3E0, 0x872C, 0xE3E1, 0x8741, 0xE3E2, 0x873E, 0xE3E3, 0x8746, 0xE3E4, 0x8720, 0xE3E5, 0x8732, + 0xE3E6, 0x872A, 0xE3E7, 0x872D, 0xE3E8, 0x873C, 0xE3E9, 0x8712, 0xE3EA, 0x873A, 0xE3EB, 0x8731, 0xE3EC, 0x8735, 0xE3ED, 0x8742, + 0xE3EE, 0x8726, 0xE3EF, 0x8727, 0xE3F0, 0x8738, 0xE3F1, 0x8724, 0xE3F2, 0x871A, 0xE3F3, 0x8730, 0xE3F4, 0x8711, 0xE3F5, 0x88F7, + 0xE3F6, 0x88E7, 0xE3F7, 0x88F1, 0xE3F8, 0x88F2, 0xE3F9, 0x88FA, 0xE3FA, 0x88FE, 0xE3FB, 0x88EE, 0xE3FC, 0x88FC, 0xE3FD, 0x88F6, + 0xE3FE, 0x88FB, 0xE440, 0x88F0, 0xE441, 0x88EC, 0xE442, 0x88EB, 0xE443, 0x899D, 0xE444, 0x89A1, 0xE445, 0x899F, 0xE446, 0x899E, + 0xE447, 0x89E9, 0xE448, 0x89EB, 0xE449, 0x89E8, 0xE44A, 0x8AAB, 0xE44B, 0x8A99, 0xE44C, 0x8A8B, 0xE44D, 0x8A92, 0xE44E, 0x8A8F, + 0xE44F, 0x8A96, 0xE450, 0x8C3D, 0xE451, 0x8C68, 0xE452, 0x8C69, 0xE453, 0x8CD5, 0xE454, 0x8CCF, 0xE455, 0x8CD7, 0xE456, 0x8D96, + 0xE457, 0x8E09, 0xE458, 0x8E02, 0xE459, 0x8DFF, 0xE45A, 0x8E0D, 0xE45B, 0x8DFD, 0xE45C, 0x8E0A, 0xE45D, 0x8E03, 0xE45E, 0x8E07, + 0xE45F, 0x8E06, 0xE460, 0x8E05, 0xE461, 0x8DFE, 0xE462, 0x8E00, 0xE463, 0x8E04, 0xE464, 0x8F10, 0xE465, 0x8F11, 0xE466, 0x8F0E, + 0xE467, 0x8F0D, 0xE468, 0x9123, 0xE469, 0x911C, 0xE46A, 0x9120, 0xE46B, 0x9122, 0xE46C, 0x911F, 0xE46D, 0x911D, 0xE46E, 0x911A, + 0xE46F, 0x9124, 0xE470, 0x9121, 0xE471, 0x911B, 0xE472, 0x917A, 0xE473, 0x9172, 0xE474, 0x9179, 0xE475, 0x9173, 0xE476, 0x92A5, + 0xE477, 0x92A4, 0xE478, 0x9276, 0xE479, 0x929B, 0xE47A, 0x927A, 0xE47B, 0x92A0, 0xE47C, 0x9294, 0xE47D, 0x92AA, 0xE47E, 0x928D, + 0xE4A1, 0x92A6, 0xE4A2, 0x929A, 0xE4A3, 0x92AB, 0xE4A4, 0x9279, 0xE4A5, 0x9297, 0xE4A6, 0x927F, 0xE4A7, 0x92A3, 0xE4A8, 0x92EE, + 0xE4A9, 0x928E, 0xE4AA, 0x9282, 0xE4AB, 0x9295, 0xE4AC, 0x92A2, 0xE4AD, 0x927D, 0xE4AE, 0x9288, 0xE4AF, 0x92A1, 0xE4B0, 0x928A, + 0xE4B1, 0x9286, 0xE4B2, 0x928C, 0xE4B3, 0x9299, 0xE4B4, 0x92A7, 0xE4B5, 0x927E, 0xE4B6, 0x9287, 0xE4B7, 0x92A9, 0xE4B8, 0x929D, + 0xE4B9, 0x928B, 0xE4BA, 0x922D, 0xE4BB, 0x969E, 0xE4BC, 0x96A1, 0xE4BD, 0x96FF, 0xE4BE, 0x9758, 0xE4BF, 0x977D, 0xE4C0, 0x977A, + 0xE4C1, 0x977E, 0xE4C2, 0x9783, 0xE4C3, 0x9780, 0xE4C4, 0x9782, 0xE4C5, 0x977B, 0xE4C6, 0x9784, 0xE4C7, 0x9781, 0xE4C8, 0x977F, + 0xE4C9, 0x97CE, 0xE4CA, 0x97CD, 0xE4CB, 0x9816, 0xE4CC, 0x98AD, 0xE4CD, 0x98AE, 0xE4CE, 0x9902, 0xE4CF, 0x9900, 0xE4D0, 0x9907, + 0xE4D1, 0x999D, 0xE4D2, 0x999C, 0xE4D3, 0x99C3, 0xE4D4, 0x99B9, 0xE4D5, 0x99BB, 0xE4D6, 0x99BA, 0xE4D7, 0x99C2, 0xE4D8, 0x99BD, + 0xE4D9, 0x99C7, 0xE4DA, 0x9AB1, 0xE4DB, 0x9AE3, 0xE4DC, 0x9AE7, 0xE4DD, 0x9B3E, 0xE4DE, 0x9B3F, 0xE4DF, 0x9B60, 0xE4E0, 0x9B61, + 0xE4E1, 0x9B5F, 0xE4E2, 0x9CF1, 0xE4E3, 0x9CF2, 0xE4E4, 0x9CF5, 0xE4E5, 0x9EA7, 0xE4E6, 0x50FF, 0xE4E7, 0x5103, 0xE4E8, 0x5130, + 0xE4E9, 0x50F8, 0xE4EA, 0x5106, 0xE4EB, 0x5107, 0xE4EC, 0x50F6, 0xE4ED, 0x50FE, 0xE4EE, 0x510B, 0xE4EF, 0x510C, 0xE4F0, 0x50FD, + 0xE4F1, 0x510A, 0xE4F2, 0x528B, 0xE4F3, 0x528C, 0xE4F4, 0x52F1, 0xE4F5, 0x52EF, 0xE4F6, 0x5648, 0xE4F7, 0x5642, 0xE4F8, 0x564C, + 0xE4F9, 0x5635, 0xE4FA, 0x5641, 0xE4FB, 0x564A, 0xE4FC, 0x5649, 0xE4FD, 0x5646, 0xE4FE, 0x5658, 0xE540, 0x565A, 0xE541, 0x5640, + 0xE542, 0x5633, 0xE543, 0x563D, 0xE544, 0x562C, 0xE545, 0x563E, 0xE546, 0x5638, 0xE547, 0x562A, 0xE548, 0x563A, 0xE549, 0x571A, + 0xE54A, 0x58AB, 0xE54B, 0x589D, 0xE54C, 0x58B1, 0xE54D, 0x58A0, 0xE54E, 0x58A3, 0xE54F, 0x58AF, 0xE550, 0x58AC, 0xE551, 0x58A5, + 0xE552, 0x58A1, 0xE553, 0x58FF, 0xE554, 0x5AFF, 0xE555, 0x5AF4, 0xE556, 0x5AFD, 0xE557, 0x5AF7, 0xE558, 0x5AF6, 0xE559, 0x5B03, + 0xE55A, 0x5AF8, 0xE55B, 0x5B02, 0xE55C, 0x5AF9, 0xE55D, 0x5B01, 0xE55E, 0x5B07, 0xE55F, 0x5B05, 0xE560, 0x5B0F, 0xE561, 0x5C67, + 0xE562, 0x5D99, 0xE563, 0x5D97, 0xE564, 0x5D9F, 0xE565, 0x5D92, 0xE566, 0x5DA2, 0xE567, 0x5D93, 0xE568, 0x5D95, 0xE569, 0x5DA0, + 0xE56A, 0x5D9C, 0xE56B, 0x5DA1, 0xE56C, 0x5D9A, 0xE56D, 0x5D9E, 0xE56E, 0x5E69, 0xE56F, 0x5E5D, 0xE570, 0x5E60, 0xE571, 0x5E5C, + 0xE572, 0x7DF3, 0xE573, 0x5EDB, 0xE574, 0x5EDE, 0xE575, 0x5EE1, 0xE576, 0x5F49, 0xE577, 0x5FB2, 0xE578, 0x618B, 0xE579, 0x6183, + 0xE57A, 0x6179, 0xE57B, 0x61B1, 0xE57C, 0x61B0, 0xE57D, 0x61A2, 0xE57E, 0x6189, 0xE5A1, 0x619B, 0xE5A2, 0x6193, 0xE5A3, 0x61AF, + 0xE5A4, 0x61AD, 0xE5A5, 0x619F, 0xE5A6, 0x6192, 0xE5A7, 0x61AA, 0xE5A8, 0x61A1, 0xE5A9, 0x618D, 0xE5AA, 0x6166, 0xE5AB, 0x61B3, + 0xE5AC, 0x622D, 0xE5AD, 0x646E, 0xE5AE, 0x6470, 0xE5AF, 0x6496, 0xE5B0, 0x64A0, 0xE5B1, 0x6485, 0xE5B2, 0x6497, 0xE5B3, 0x649C, + 0xE5B4, 0x648F, 0xE5B5, 0x648B, 0xE5B6, 0x648A, 0xE5B7, 0x648C, 0xE5B8, 0x64A3, 0xE5B9, 0x649F, 0xE5BA, 0x6468, 0xE5BB, 0x64B1, + 0xE5BC, 0x6498, 0xE5BD, 0x6576, 0xE5BE, 0x657A, 0xE5BF, 0x6579, 0xE5C0, 0x657B, 0xE5C1, 0x65B2, 0xE5C2, 0x65B3, 0xE5C3, 0x66B5, + 0xE5C4, 0x66B0, 0xE5C5, 0x66A9, 0xE5C6, 0x66B2, 0xE5C7, 0x66B7, 0xE5C8, 0x66AA, 0xE5C9, 0x66AF, 0xE5CA, 0x6A00, 0xE5CB, 0x6A06, + 0xE5CC, 0x6A17, 0xE5CD, 0x69E5, 0xE5CE, 0x69F8, 0xE5CF, 0x6A15, 0xE5D0, 0x69F1, 0xE5D1, 0x69E4, 0xE5D2, 0x6A20, 0xE5D3, 0x69FF, + 0xE5D4, 0x69EC, 0xE5D5, 0x69E2, 0xE5D6, 0x6A1B, 0xE5D7, 0x6A1D, 0xE5D8, 0x69FE, 0xE5D9, 0x6A27, 0xE5DA, 0x69F2, 0xE5DB, 0x69EE, + 0xE5DC, 0x6A14, 0xE5DD, 0x69F7, 0xE5DE, 0x69E7, 0xE5DF, 0x6A40, 0xE5E0, 0x6A08, 0xE5E1, 0x69E6, 0xE5E2, 0x69FB, 0xE5E3, 0x6A0D, + 0xE5E4, 0x69FC, 0xE5E5, 0x69EB, 0xE5E6, 0x6A09, 0xE5E7, 0x6A04, 0xE5E8, 0x6A18, 0xE5E9, 0x6A25, 0xE5EA, 0x6A0F, 0xE5EB, 0x69F6, + 0xE5EC, 0x6A26, 0xE5ED, 0x6A07, 0xE5EE, 0x69F4, 0xE5EF, 0x6A16, 0xE5F0, 0x6B51, 0xE5F1, 0x6BA5, 0xE5F2, 0x6BA3, 0xE5F3, 0x6BA2, + 0xE5F4, 0x6BA6, 0xE5F5, 0x6C01, 0xE5F6, 0x6C00, 0xE5F7, 0x6BFF, 0xE5F8, 0x6C02, 0xE5F9, 0x6F41, 0xE5FA, 0x6F26, 0xE5FB, 0x6F7E, + 0xE5FC, 0x6F87, 0xE5FD, 0x6FC6, 0xE5FE, 0x6F92, 0xE640, 0x6F8D, 0xE641, 0x6F89, 0xE642, 0x6F8C, 0xE643, 0x6F62, 0xE644, 0x6F4F, + 0xE645, 0x6F85, 0xE646, 0x6F5A, 0xE647, 0x6F96, 0xE648, 0x6F76, 0xE649, 0x6F6C, 0xE64A, 0x6F82, 0xE64B, 0x6F55, 0xE64C, 0x6F72, + 0xE64D, 0x6F52, 0xE64E, 0x6F50, 0xE64F, 0x6F57, 0xE650, 0x6F94, 0xE651, 0x6F93, 0xE652, 0x6F5D, 0xE653, 0x6F00, 0xE654, 0x6F61, + 0xE655, 0x6F6B, 0xE656, 0x6F7D, 0xE657, 0x6F67, 0xE658, 0x6F90, 0xE659, 0x6F53, 0xE65A, 0x6F8B, 0xE65B, 0x6F69, 0xE65C, 0x6F7F, + 0xE65D, 0x6F95, 0xE65E, 0x6F63, 0xE65F, 0x6F77, 0xE660, 0x6F6A, 0xE661, 0x6F7B, 0xE662, 0x71B2, 0xE663, 0x71AF, 0xE664, 0x719B, + 0xE665, 0x71B0, 0xE666, 0x71A0, 0xE667, 0x719A, 0xE668, 0x71A9, 0xE669, 0x71B5, 0xE66A, 0x719D, 0xE66B, 0x71A5, 0xE66C, 0x719E, + 0xE66D, 0x71A4, 0xE66E, 0x71A1, 0xE66F, 0x71AA, 0xE670, 0x719C, 0xE671, 0x71A7, 0xE672, 0x71B3, 0xE673, 0x7298, 0xE674, 0x729A, + 0xE675, 0x7358, 0xE676, 0x7352, 0xE677, 0x735E, 0xE678, 0x735F, 0xE679, 0x7360, 0xE67A, 0x735D, 0xE67B, 0x735B, 0xE67C, 0x7361, + 0xE67D, 0x735A, 0xE67E, 0x7359, 0xE6A1, 0x7362, 0xE6A2, 0x7487, 0xE6A3, 0x7489, 0xE6A4, 0x748A, 0xE6A5, 0x7486, 0xE6A6, 0x7481, + 0xE6A7, 0x747D, 0xE6A8, 0x7485, 0xE6A9, 0x7488, 0xE6AA, 0x747C, 0xE6AB, 0x7479, 0xE6AC, 0x7508, 0xE6AD, 0x7507, 0xE6AE, 0x757E, + 0xE6AF, 0x7625, 0xE6B0, 0x761E, 0xE6B1, 0x7619, 0xE6B2, 0x761D, 0xE6B3, 0x761C, 0xE6B4, 0x7623, 0xE6B5, 0x761A, 0xE6B6, 0x7628, + 0xE6B7, 0x761B, 0xE6B8, 0x769C, 0xE6B9, 0x769D, 0xE6BA, 0x769E, 0xE6BB, 0x769B, 0xE6BC, 0x778D, 0xE6BD, 0x778F, 0xE6BE, 0x7789, + 0xE6BF, 0x7788, 0xE6C0, 0x78CD, 0xE6C1, 0x78BB, 0xE6C2, 0x78CF, 0xE6C3, 0x78CC, 0xE6C4, 0x78D1, 0xE6C5, 0x78CE, 0xE6C6, 0x78D4, + 0xE6C7, 0x78C8, 0xE6C8, 0x78C3, 0xE6C9, 0x78C4, 0xE6CA, 0x78C9, 0xE6CB, 0x799A, 0xE6CC, 0x79A1, 0xE6CD, 0x79A0, 0xE6CE, 0x799C, + 0xE6CF, 0x79A2, 0xE6D0, 0x799B, 0xE6D1, 0x6B76, 0xE6D2, 0x7A39, 0xE6D3, 0x7AB2, 0xE6D4, 0x7AB4, 0xE6D5, 0x7AB3, 0xE6D6, 0x7BB7, + 0xE6D7, 0x7BCB, 0xE6D8, 0x7BBE, 0xE6D9, 0x7BAC, 0xE6DA, 0x7BCE, 0xE6DB, 0x7BAF, 0xE6DC, 0x7BB9, 0xE6DD, 0x7BCA, 0xE6DE, 0x7BB5, + 0xE6DF, 0x7CC5, 0xE6E0, 0x7CC8, 0xE6E1, 0x7CCC, 0xE6E2, 0x7CCB, 0xE6E3, 0x7DF7, 0xE6E4, 0x7DDB, 0xE6E5, 0x7DEA, 0xE6E6, 0x7DE7, + 0xE6E7, 0x7DD7, 0xE6E8, 0x7DE1, 0xE6E9, 0x7E03, 0xE6EA, 0x7DFA, 0xE6EB, 0x7DE6, 0xE6EC, 0x7DF6, 0xE6ED, 0x7DF1, 0xE6EE, 0x7DF0, + 0xE6EF, 0x7DEE, 0xE6F0, 0x7DDF, 0xE6F1, 0x7F76, 0xE6F2, 0x7FAC, 0xE6F3, 0x7FB0, 0xE6F4, 0x7FAD, 0xE6F5, 0x7FED, 0xE6F6, 0x7FEB, + 0xE6F7, 0x7FEA, 0xE6F8, 0x7FEC, 0xE6F9, 0x7FE6, 0xE6FA, 0x7FE8, 0xE6FB, 0x8064, 0xE6FC, 0x8067, 0xE6FD, 0x81A3, 0xE6FE, 0x819F, + 0xE740, 0x819E, 0xE741, 0x8195, 0xE742, 0x81A2, 0xE743, 0x8199, 0xE744, 0x8197, 0xE745, 0x8216, 0xE746, 0x824F, 0xE747, 0x8253, + 0xE748, 0x8252, 0xE749, 0x8250, 0xE74A, 0x824E, 0xE74B, 0x8251, 0xE74C, 0x8524, 0xE74D, 0x853B, 0xE74E, 0x850F, 0xE74F, 0x8500, + 0xE750, 0x8529, 0xE751, 0x850E, 0xE752, 0x8509, 0xE753, 0x850D, 0xE754, 0x851F, 0xE755, 0x850A, 0xE756, 0x8527, 0xE757, 0x851C, + 0xE758, 0x84FB, 0xE759, 0x852B, 0xE75A, 0x84FA, 0xE75B, 0x8508, 0xE75C, 0x850C, 0xE75D, 0x84F4, 0xE75E, 0x852A, 0xE75F, 0x84F2, + 0xE760, 0x8515, 0xE761, 0x84F7, 0xE762, 0x84EB, 0xE763, 0x84F3, 0xE764, 0x84FC, 0xE765, 0x8512, 0xE766, 0x84EA, 0xE767, 0x84E9, + 0xE768, 0x8516, 0xE769, 0x84FE, 0xE76A, 0x8528, 0xE76B, 0x851D, 0xE76C, 0x852E, 0xE76D, 0x8502, 0xE76E, 0x84FD, 0xE76F, 0x851E, + 0xE770, 0x84F6, 0xE771, 0x8531, 0xE772, 0x8526, 0xE773, 0x84E7, 0xE774, 0x84E8, 0xE775, 0x84F0, 0xE776, 0x84EF, 0xE777, 0x84F9, + 0xE778, 0x8518, 0xE779, 0x8520, 0xE77A, 0x8530, 0xE77B, 0x850B, 0xE77C, 0x8519, 0xE77D, 0x852F, 0xE77E, 0x8662, 0xE7A1, 0x8756, + 0xE7A2, 0x8763, 0xE7A3, 0x8764, 0xE7A4, 0x8777, 0xE7A5, 0x87E1, 0xE7A6, 0x8773, 0xE7A7, 0x8758, 0xE7A8, 0x8754, 0xE7A9, 0x875B, + 0xE7AA, 0x8752, 0xE7AB, 0x8761, 0xE7AC, 0x875A, 0xE7AD, 0x8751, 0xE7AE, 0x875E, 0xE7AF, 0x876D, 0xE7B0, 0x876A, 0xE7B1, 0x8750, + 0xE7B2, 0x874E, 0xE7B3, 0x875F, 0xE7B4, 0x875D, 0xE7B5, 0x876F, 0xE7B6, 0x876C, 0xE7B7, 0x877A, 0xE7B8, 0x876E, 0xE7B9, 0x875C, + 0xE7BA, 0x8765, 0xE7BB, 0x874F, 0xE7BC, 0x877B, 0xE7BD, 0x8775, 0xE7BE, 0x8762, 0xE7BF, 0x8767, 0xE7C0, 0x8769, 0xE7C1, 0x885A, + 0xE7C2, 0x8905, 0xE7C3, 0x890C, 0xE7C4, 0x8914, 0xE7C5, 0x890B, 0xE7C6, 0x8917, 0xE7C7, 0x8918, 0xE7C8, 0x8919, 0xE7C9, 0x8906, + 0xE7CA, 0x8916, 0xE7CB, 0x8911, 0xE7CC, 0x890E, 0xE7CD, 0x8909, 0xE7CE, 0x89A2, 0xE7CF, 0x89A4, 0xE7D0, 0x89A3, 0xE7D1, 0x89ED, + 0xE7D2, 0x89F0, 0xE7D3, 0x89EC, 0xE7D4, 0x8ACF, 0xE7D5, 0x8AC6, 0xE7D6, 0x8AB8, 0xE7D7, 0x8AD3, 0xE7D8, 0x8AD1, 0xE7D9, 0x8AD4, + 0xE7DA, 0x8AD5, 0xE7DB, 0x8ABB, 0xE7DC, 0x8AD7, 0xE7DD, 0x8ABE, 0xE7DE, 0x8AC0, 0xE7DF, 0x8AC5, 0xE7E0, 0x8AD8, 0xE7E1, 0x8AC3, + 0xE7E2, 0x8ABA, 0xE7E3, 0x8ABD, 0xE7E4, 0x8AD9, 0xE7E5, 0x8C3E, 0xE7E6, 0x8C4D, 0xE7E7, 0x8C8F, 0xE7E8, 0x8CE5, 0xE7E9, 0x8CDF, + 0xE7EA, 0x8CD9, 0xE7EB, 0x8CE8, 0xE7EC, 0x8CDA, 0xE7ED, 0x8CDD, 0xE7EE, 0x8CE7, 0xE7EF, 0x8DA0, 0xE7F0, 0x8D9C, 0xE7F1, 0x8DA1, + 0xE7F2, 0x8D9B, 0xE7F3, 0x8E20, 0xE7F4, 0x8E23, 0xE7F5, 0x8E25, 0xE7F6, 0x8E24, 0xE7F7, 0x8E2E, 0xE7F8, 0x8E15, 0xE7F9, 0x8E1B, + 0xE7FA, 0x8E16, 0xE7FB, 0x8E11, 0xE7FC, 0x8E19, 0xE7FD, 0x8E26, 0xE7FE, 0x8E27, 0xE840, 0x8E14, 0xE841, 0x8E12, 0xE842, 0x8E18, + 0xE843, 0x8E13, 0xE844, 0x8E1C, 0xE845, 0x8E17, 0xE846, 0x8E1A, 0xE847, 0x8F2C, 0xE848, 0x8F24, 0xE849, 0x8F18, 0xE84A, 0x8F1A, + 0xE84B, 0x8F20, 0xE84C, 0x8F23, 0xE84D, 0x8F16, 0xE84E, 0x8F17, 0xE84F, 0x9073, 0xE850, 0x9070, 0xE851, 0x906F, 0xE852, 0x9067, + 0xE853, 0x906B, 0xE854, 0x912F, 0xE855, 0x912B, 0xE856, 0x9129, 0xE857, 0x912A, 0xE858, 0x9132, 0xE859, 0x9126, 0xE85A, 0x912E, + 0xE85B, 0x9185, 0xE85C, 0x9186, 0xE85D, 0x918A, 0xE85E, 0x9181, 0xE85F, 0x9182, 0xE860, 0x9184, 0xE861, 0x9180, 0xE862, 0x92D0, + 0xE863, 0x92C3, 0xE864, 0x92C4, 0xE865, 0x92C0, 0xE866, 0x92D9, 0xE867, 0x92B6, 0xE868, 0x92CF, 0xE869, 0x92F1, 0xE86A, 0x92DF, + 0xE86B, 0x92D8, 0xE86C, 0x92E9, 0xE86D, 0x92D7, 0xE86E, 0x92DD, 0xE86F, 0x92CC, 0xE870, 0x92EF, 0xE871, 0x92C2, 0xE872, 0x92E8, + 0xE873, 0x92CA, 0xE874, 0x92C8, 0xE875, 0x92CE, 0xE876, 0x92E6, 0xE877, 0x92CD, 0xE878, 0x92D5, 0xE879, 0x92C9, 0xE87A, 0x92E0, + 0xE87B, 0x92DE, 0xE87C, 0x92E7, 0xE87D, 0x92D1, 0xE87E, 0x92D3, 0xE8A1, 0x92B5, 0xE8A2, 0x92E1, 0xE8A3, 0x92C6, 0xE8A4, 0x92B4, + 0xE8A5, 0x957C, 0xE8A6, 0x95AC, 0xE8A7, 0x95AB, 0xE8A8, 0x95AE, 0xE8A9, 0x95B0, 0xE8AA, 0x96A4, 0xE8AB, 0x96A2, 0xE8AC, 0x96D3, + 0xE8AD, 0x9705, 0xE8AE, 0x9708, 0xE8AF, 0x9702, 0xE8B0, 0x975A, 0xE8B1, 0x978A, 0xE8B2, 0x978E, 0xE8B3, 0x9788, 0xE8B4, 0x97D0, + 0xE8B5, 0x97CF, 0xE8B6, 0x981E, 0xE8B7, 0x981D, 0xE8B8, 0x9826, 0xE8B9, 0x9829, 0xE8BA, 0x9828, 0xE8BB, 0x9820, 0xE8BC, 0x981B, + 0xE8BD, 0x9827, 0xE8BE, 0x98B2, 0xE8BF, 0x9908, 0xE8C0, 0x98FA, 0xE8C1, 0x9911, 0xE8C2, 0x9914, 0xE8C3, 0x9916, 0xE8C4, 0x9917, + 0xE8C5, 0x9915, 0xE8C6, 0x99DC, 0xE8C7, 0x99CD, 0xE8C8, 0x99CF, 0xE8C9, 0x99D3, 0xE8CA, 0x99D4, 0xE8CB, 0x99CE, 0xE8CC, 0x99C9, + 0xE8CD, 0x99D6, 0xE8CE, 0x99D8, 0xE8CF, 0x99CB, 0xE8D0, 0x99D7, 0xE8D1, 0x99CC, 0xE8D2, 0x9AB3, 0xE8D3, 0x9AEC, 0xE8D4, 0x9AEB, + 0xE8D5, 0x9AF3, 0xE8D6, 0x9AF2, 0xE8D7, 0x9AF1, 0xE8D8, 0x9B46, 0xE8D9, 0x9B43, 0xE8DA, 0x9B67, 0xE8DB, 0x9B74, 0xE8DC, 0x9B71, + 0xE8DD, 0x9B66, 0xE8DE, 0x9B76, 0xE8DF, 0x9B75, 0xE8E0, 0x9B70, 0xE8E1, 0x9B68, 0xE8E2, 0x9B64, 0xE8E3, 0x9B6C, 0xE8E4, 0x9CFC, + 0xE8E5, 0x9CFA, 0xE8E6, 0x9CFD, 0xE8E7, 0x9CFF, 0xE8E8, 0x9CF7, 0xE8E9, 0x9D07, 0xE8EA, 0x9D00, 0xE8EB, 0x9CF9, 0xE8EC, 0x9CFB, + 0xE8ED, 0x9D08, 0xE8EE, 0x9D05, 0xE8EF, 0x9D04, 0xE8F0, 0x9E83, 0xE8F1, 0x9ED3, 0xE8F2, 0x9F0F, 0xE8F3, 0x9F10, 0xE8F4, 0x511C, + 0xE8F5, 0x5113, 0xE8F6, 0x5117, 0xE8F7, 0x511A, 0xE8F8, 0x5111, 0xE8F9, 0x51DE, 0xE8FA, 0x5334, 0xE8FB, 0x53E1, 0xE8FC, 0x5670, + 0xE8FD, 0x5660, 0xE8FE, 0x566E, 0xE940, 0x5673, 0xE941, 0x5666, 0xE942, 0x5663, 0xE943, 0x566D, 0xE944, 0x5672, 0xE945, 0x565E, + 0xE946, 0x5677, 0xE947, 0x571C, 0xE948, 0x571B, 0xE949, 0x58C8, 0xE94A, 0x58BD, 0xE94B, 0x58C9, 0xE94C, 0x58BF, 0xE94D, 0x58BA, + 0xE94E, 0x58C2, 0xE94F, 0x58BC, 0xE950, 0x58C6, 0xE951, 0x5B17, 0xE952, 0x5B19, 0xE953, 0x5B1B, 0xE954, 0x5B21, 0xE955, 0x5B14, + 0xE956, 0x5B13, 0xE957, 0x5B10, 0xE958, 0x5B16, 0xE959, 0x5B28, 0xE95A, 0x5B1A, 0xE95B, 0x5B20, 0xE95C, 0x5B1E, 0xE95D, 0x5BEF, + 0xE95E, 0x5DAC, 0xE95F, 0x5DB1, 0xE960, 0x5DA9, 0xE961, 0x5DA7, 0xE962, 0x5DB5, 0xE963, 0x5DB0, 0xE964, 0x5DAE, 0xE965, 0x5DAA, + 0xE966, 0x5DA8, 0xE967, 0x5DB2, 0xE968, 0x5DAD, 0xE969, 0x5DAF, 0xE96A, 0x5DB4, 0xE96B, 0x5E67, 0xE96C, 0x5E68, 0xE96D, 0x5E66, + 0xE96E, 0x5E6F, 0xE96F, 0x5EE9, 0xE970, 0x5EE7, 0xE971, 0x5EE6, 0xE972, 0x5EE8, 0xE973, 0x5EE5, 0xE974, 0x5F4B, 0xE975, 0x5FBC, + 0xE976, 0x619D, 0xE977, 0x61A8, 0xE978, 0x6196, 0xE979, 0x61C5, 0xE97A, 0x61B4, 0xE97B, 0x61C6, 0xE97C, 0x61C1, 0xE97D, 0x61CC, + 0xE97E, 0x61BA, 0xE9A1, 0x61BF, 0xE9A2, 0x61B8, 0xE9A3, 0x618C, 0xE9A4, 0x64D7, 0xE9A5, 0x64D6, 0xE9A6, 0x64D0, 0xE9A7, 0x64CF, + 0xE9A8, 0x64C9, 0xE9A9, 0x64BD, 0xE9AA, 0x6489, 0xE9AB, 0x64C3, 0xE9AC, 0x64DB, 0xE9AD, 0x64F3, 0xE9AE, 0x64D9, 0xE9AF, 0x6533, + 0xE9B0, 0x657F, 0xE9B1, 0x657C, 0xE9B2, 0x65A2, 0xE9B3, 0x66C8, 0xE9B4, 0x66BE, 0xE9B5, 0x66C0, 0xE9B6, 0x66CA, 0xE9B7, 0x66CB, + 0xE9B8, 0x66CF, 0xE9B9, 0x66BD, 0xE9BA, 0x66BB, 0xE9BB, 0x66BA, 0xE9BC, 0x66CC, 0xE9BD, 0x6723, 0xE9BE, 0x6A34, 0xE9BF, 0x6A66, + 0xE9C0, 0x6A49, 0xE9C1, 0x6A67, 0xE9C2, 0x6A32, 0xE9C3, 0x6A68, 0xE9C4, 0x6A3E, 0xE9C5, 0x6A5D, 0xE9C6, 0x6A6D, 0xE9C7, 0x6A76, + 0xE9C8, 0x6A5B, 0xE9C9, 0x6A51, 0xE9CA, 0x6A28, 0xE9CB, 0x6A5A, 0xE9CC, 0x6A3B, 0xE9CD, 0x6A3F, 0xE9CE, 0x6A41, 0xE9CF, 0x6A6A, + 0xE9D0, 0x6A64, 0xE9D1, 0x6A50, 0xE9D2, 0x6A4F, 0xE9D3, 0x6A54, 0xE9D4, 0x6A6F, 0xE9D5, 0x6A69, 0xE9D6, 0x6A60, 0xE9D7, 0x6A3C, + 0xE9D8, 0x6A5E, 0xE9D9, 0x6A56, 0xE9DA, 0x6A55, 0xE9DB, 0x6A4D, 0xE9DC, 0x6A4E, 0xE9DD, 0x6A46, 0xE9DE, 0x6B55, 0xE9DF, 0x6B54, + 0xE9E0, 0x6B56, 0xE9E1, 0x6BA7, 0xE9E2, 0x6BAA, 0xE9E3, 0x6BAB, 0xE9E4, 0x6BC8, 0xE9E5, 0x6BC7, 0xE9E6, 0x6C04, 0xE9E7, 0x6C03, + 0xE9E8, 0x6C06, 0xE9E9, 0x6FAD, 0xE9EA, 0x6FCB, 0xE9EB, 0x6FA3, 0xE9EC, 0x6FC7, 0xE9ED, 0x6FBC, 0xE9EE, 0x6FCE, 0xE9EF, 0x6FC8, + 0xE9F0, 0x6F5E, 0xE9F1, 0x6FC4, 0xE9F2, 0x6FBD, 0xE9F3, 0x6F9E, 0xE9F4, 0x6FCA, 0xE9F5, 0x6FA8, 0xE9F6, 0x7004, 0xE9F7, 0x6FA5, + 0xE9F8, 0x6FAE, 0xE9F9, 0x6FBA, 0xE9FA, 0x6FAC, 0xE9FB, 0x6FAA, 0xE9FC, 0x6FCF, 0xE9FD, 0x6FBF, 0xE9FE, 0x6FB8, 0xEA40, 0x6FA2, + 0xEA41, 0x6FC9, 0xEA42, 0x6FAB, 0xEA43, 0x6FCD, 0xEA44, 0x6FAF, 0xEA45, 0x6FB2, 0xEA46, 0x6FB0, 0xEA47, 0x71C5, 0xEA48, 0x71C2, + 0xEA49, 0x71BF, 0xEA4A, 0x71B8, 0xEA4B, 0x71D6, 0xEA4C, 0x71C0, 0xEA4D, 0x71C1, 0xEA4E, 0x71CB, 0xEA4F, 0x71D4, 0xEA50, 0x71CA, + 0xEA51, 0x71C7, 0xEA52, 0x71CF, 0xEA53, 0x71BD, 0xEA54, 0x71D8, 0xEA55, 0x71BC, 0xEA56, 0x71C6, 0xEA57, 0x71DA, 0xEA58, 0x71DB, + 0xEA59, 0x729D, 0xEA5A, 0x729E, 0xEA5B, 0x7369, 0xEA5C, 0x7366, 0xEA5D, 0x7367, 0xEA5E, 0x736C, 0xEA5F, 0x7365, 0xEA60, 0x736B, + 0xEA61, 0x736A, 0xEA62, 0x747F, 0xEA63, 0x749A, 0xEA64, 0x74A0, 0xEA65, 0x7494, 0xEA66, 0x7492, 0xEA67, 0x7495, 0xEA68, 0x74A1, + 0xEA69, 0x750B, 0xEA6A, 0x7580, 0xEA6B, 0x762F, 0xEA6C, 0x762D, 0xEA6D, 0x7631, 0xEA6E, 0x763D, 0xEA6F, 0x7633, 0xEA70, 0x763C, + 0xEA71, 0x7635, 0xEA72, 0x7632, 0xEA73, 0x7630, 0xEA74, 0x76BB, 0xEA75, 0x76E6, 0xEA76, 0x779A, 0xEA77, 0x779D, 0xEA78, 0x77A1, + 0xEA79, 0x779C, 0xEA7A, 0x779B, 0xEA7B, 0x77A2, 0xEA7C, 0x77A3, 0xEA7D, 0x7795, 0xEA7E, 0x7799, 0xEAA1, 0x7797, 0xEAA2, 0x78DD, + 0xEAA3, 0x78E9, 0xEAA4, 0x78E5, 0xEAA5, 0x78EA, 0xEAA6, 0x78DE, 0xEAA7, 0x78E3, 0xEAA8, 0x78DB, 0xEAA9, 0x78E1, 0xEAAA, 0x78E2, + 0xEAAB, 0x78ED, 0xEAAC, 0x78DF, 0xEAAD, 0x78E0, 0xEAAE, 0x79A4, 0xEAAF, 0x7A44, 0xEAB0, 0x7A48, 0xEAB1, 0x7A47, 0xEAB2, 0x7AB6, + 0xEAB3, 0x7AB8, 0xEAB4, 0x7AB5, 0xEAB5, 0x7AB1, 0xEAB6, 0x7AB7, 0xEAB7, 0x7BDE, 0xEAB8, 0x7BE3, 0xEAB9, 0x7BE7, 0xEABA, 0x7BDD, + 0xEABB, 0x7BD5, 0xEABC, 0x7BE5, 0xEABD, 0x7BDA, 0xEABE, 0x7BE8, 0xEABF, 0x7BF9, 0xEAC0, 0x7BD4, 0xEAC1, 0x7BEA, 0xEAC2, 0x7BE2, + 0xEAC3, 0x7BDC, 0xEAC4, 0x7BEB, 0xEAC5, 0x7BD8, 0xEAC6, 0x7BDF, 0xEAC7, 0x7CD2, 0xEAC8, 0x7CD4, 0xEAC9, 0x7CD7, 0xEACA, 0x7CD0, + 0xEACB, 0x7CD1, 0xEACC, 0x7E12, 0xEACD, 0x7E21, 0xEACE, 0x7E17, 0xEACF, 0x7E0C, 0xEAD0, 0x7E1F, 0xEAD1, 0x7E20, 0xEAD2, 0x7E13, + 0xEAD3, 0x7E0E, 0xEAD4, 0x7E1C, 0xEAD5, 0x7E15, 0xEAD6, 0x7E1A, 0xEAD7, 0x7E22, 0xEAD8, 0x7E0B, 0xEAD9, 0x7E0F, 0xEADA, 0x7E16, + 0xEADB, 0x7E0D, 0xEADC, 0x7E14, 0xEADD, 0x7E25, 0xEADE, 0x7E24, 0xEADF, 0x7F43, 0xEAE0, 0x7F7B, 0xEAE1, 0x7F7C, 0xEAE2, 0x7F7A, + 0xEAE3, 0x7FB1, 0xEAE4, 0x7FEF, 0xEAE5, 0x802A, 0xEAE6, 0x8029, 0xEAE7, 0x806C, 0xEAE8, 0x81B1, 0xEAE9, 0x81A6, 0xEAEA, 0x81AE, + 0xEAEB, 0x81B9, 0xEAEC, 0x81B5, 0xEAED, 0x81AB, 0xEAEE, 0x81B0, 0xEAEF, 0x81AC, 0xEAF0, 0x81B4, 0xEAF1, 0x81B2, 0xEAF2, 0x81B7, + 0xEAF3, 0x81A7, 0xEAF4, 0x81F2, 0xEAF5, 0x8255, 0xEAF6, 0x8256, 0xEAF7, 0x8257, 0xEAF8, 0x8556, 0xEAF9, 0x8545, 0xEAFA, 0x856B, + 0xEAFB, 0x854D, 0xEAFC, 0x8553, 0xEAFD, 0x8561, 0xEAFE, 0x8558, 0xEB40, 0x8540, 0xEB41, 0x8546, 0xEB42, 0x8564, 0xEB43, 0x8541, + 0xEB44, 0x8562, 0xEB45, 0x8544, 0xEB46, 0x8551, 0xEB47, 0x8547, 0xEB48, 0x8563, 0xEB49, 0x853E, 0xEB4A, 0x855B, 0xEB4B, 0x8571, + 0xEB4C, 0x854E, 0xEB4D, 0x856E, 0xEB4E, 0x8575, 0xEB4F, 0x8555, 0xEB50, 0x8567, 0xEB51, 0x8560, 0xEB52, 0x858C, 0xEB53, 0x8566, + 0xEB54, 0x855D, 0xEB55, 0x8554, 0xEB56, 0x8565, 0xEB57, 0x856C, 0xEB58, 0x8663, 0xEB59, 0x8665, 0xEB5A, 0x8664, 0xEB5B, 0x879B, + 0xEB5C, 0x878F, 0xEB5D, 0x8797, 0xEB5E, 0x8793, 0xEB5F, 0x8792, 0xEB60, 0x8788, 0xEB61, 0x8781, 0xEB62, 0x8796, 0xEB63, 0x8798, + 0xEB64, 0x8779, 0xEB65, 0x8787, 0xEB66, 0x87A3, 0xEB67, 0x8785, 0xEB68, 0x8790, 0xEB69, 0x8791, 0xEB6A, 0x879D, 0xEB6B, 0x8784, + 0xEB6C, 0x8794, 0xEB6D, 0x879C, 0xEB6E, 0x879A, 0xEB6F, 0x8789, 0xEB70, 0x891E, 0xEB71, 0x8926, 0xEB72, 0x8930, 0xEB73, 0x892D, + 0xEB74, 0x892E, 0xEB75, 0x8927, 0xEB76, 0x8931, 0xEB77, 0x8922, 0xEB78, 0x8929, 0xEB79, 0x8923, 0xEB7A, 0x892F, 0xEB7B, 0x892C, + 0xEB7C, 0x891F, 0xEB7D, 0x89F1, 0xEB7E, 0x8AE0, 0xEBA1, 0x8AE2, 0xEBA2, 0x8AF2, 0xEBA3, 0x8AF4, 0xEBA4, 0x8AF5, 0xEBA5, 0x8ADD, + 0xEBA6, 0x8B14, 0xEBA7, 0x8AE4, 0xEBA8, 0x8ADF, 0xEBA9, 0x8AF0, 0xEBAA, 0x8AC8, 0xEBAB, 0x8ADE, 0xEBAC, 0x8AE1, 0xEBAD, 0x8AE8, + 0xEBAE, 0x8AFF, 0xEBAF, 0x8AEF, 0xEBB0, 0x8AFB, 0xEBB1, 0x8C91, 0xEBB2, 0x8C92, 0xEBB3, 0x8C90, 0xEBB4, 0x8CF5, 0xEBB5, 0x8CEE, + 0xEBB6, 0x8CF1, 0xEBB7, 0x8CF0, 0xEBB8, 0x8CF3, 0xEBB9, 0x8D6C, 0xEBBA, 0x8D6E, 0xEBBB, 0x8DA5, 0xEBBC, 0x8DA7, 0xEBBD, 0x8E33, + 0xEBBE, 0x8E3E, 0xEBBF, 0x8E38, 0xEBC0, 0x8E40, 0xEBC1, 0x8E45, 0xEBC2, 0x8E36, 0xEBC3, 0x8E3C, 0xEBC4, 0x8E3D, 0xEBC5, 0x8E41, + 0xEBC6, 0x8E30, 0xEBC7, 0x8E3F, 0xEBC8, 0x8EBD, 0xEBC9, 0x8F36, 0xEBCA, 0x8F2E, 0xEBCB, 0x8F35, 0xEBCC, 0x8F32, 0xEBCD, 0x8F39, + 0xEBCE, 0x8F37, 0xEBCF, 0x8F34, 0xEBD0, 0x9076, 0xEBD1, 0x9079, 0xEBD2, 0x907B, 0xEBD3, 0x9086, 0xEBD4, 0x90FA, 0xEBD5, 0x9133, + 0xEBD6, 0x9135, 0xEBD7, 0x9136, 0xEBD8, 0x9193, 0xEBD9, 0x9190, 0xEBDA, 0x9191, 0xEBDB, 0x918D, 0xEBDC, 0x918F, 0xEBDD, 0x9327, + 0xEBDE, 0x931E, 0xEBDF, 0x9308, 0xEBE0, 0x931F, 0xEBE1, 0x9306, 0xEBE2, 0x930F, 0xEBE3, 0x937A, 0xEBE4, 0x9338, 0xEBE5, 0x933C, + 0xEBE6, 0x931B, 0xEBE7, 0x9323, 0xEBE8, 0x9312, 0xEBE9, 0x9301, 0xEBEA, 0x9346, 0xEBEB, 0x932D, 0xEBEC, 0x930E, 0xEBED, 0x930D, + 0xEBEE, 0x92CB, 0xEBEF, 0x931D, 0xEBF0, 0x92FA, 0xEBF1, 0x9325, 0xEBF2, 0x9313, 0xEBF3, 0x92F9, 0xEBF4, 0x92F7, 0xEBF5, 0x9334, + 0xEBF6, 0x9302, 0xEBF7, 0x9324, 0xEBF8, 0x92FF, 0xEBF9, 0x9329, 0xEBFA, 0x9339, 0xEBFB, 0x9335, 0xEBFC, 0x932A, 0xEBFD, 0x9314, + 0xEBFE, 0x930C, 0xEC40, 0x930B, 0xEC41, 0x92FE, 0xEC42, 0x9309, 0xEC43, 0x9300, 0xEC44, 0x92FB, 0xEC45, 0x9316, 0xEC46, 0x95BC, + 0xEC47, 0x95CD, 0xEC48, 0x95BE, 0xEC49, 0x95B9, 0xEC4A, 0x95BA, 0xEC4B, 0x95B6, 0xEC4C, 0x95BF, 0xEC4D, 0x95B5, 0xEC4E, 0x95BD, + 0xEC4F, 0x96A9, 0xEC50, 0x96D4, 0xEC51, 0x970B, 0xEC52, 0x9712, 0xEC53, 0x9710, 0xEC54, 0x9799, 0xEC55, 0x9797, 0xEC56, 0x9794, + 0xEC57, 0x97F0, 0xEC58, 0x97F8, 0xEC59, 0x9835, 0xEC5A, 0x982F, 0xEC5B, 0x9832, 0xEC5C, 0x9924, 0xEC5D, 0x991F, 0xEC5E, 0x9927, + 0xEC5F, 0x9929, 0xEC60, 0x999E, 0xEC61, 0x99EE, 0xEC62, 0x99EC, 0xEC63, 0x99E5, 0xEC64, 0x99E4, 0xEC65, 0x99F0, 0xEC66, 0x99E3, + 0xEC67, 0x99EA, 0xEC68, 0x99E9, 0xEC69, 0x99E7, 0xEC6A, 0x9AB9, 0xEC6B, 0x9ABF, 0xEC6C, 0x9AB4, 0xEC6D, 0x9ABB, 0xEC6E, 0x9AF6, + 0xEC6F, 0x9AFA, 0xEC70, 0x9AF9, 0xEC71, 0x9AF7, 0xEC72, 0x9B33, 0xEC73, 0x9B80, 0xEC74, 0x9B85, 0xEC75, 0x9B87, 0xEC76, 0x9B7C, + 0xEC77, 0x9B7E, 0xEC78, 0x9B7B, 0xEC79, 0x9B82, 0xEC7A, 0x9B93, 0xEC7B, 0x9B92, 0xEC7C, 0x9B90, 0xEC7D, 0x9B7A, 0xEC7E, 0x9B95, + 0xECA1, 0x9B7D, 0xECA2, 0x9B88, 0xECA3, 0x9D25, 0xECA4, 0x9D17, 0xECA5, 0x9D20, 0xECA6, 0x9D1E, 0xECA7, 0x9D14, 0xECA8, 0x9D29, + 0xECA9, 0x9D1D, 0xECAA, 0x9D18, 0xECAB, 0x9D22, 0xECAC, 0x9D10, 0xECAD, 0x9D19, 0xECAE, 0x9D1F, 0xECAF, 0x9E88, 0xECB0, 0x9E86, + 0xECB1, 0x9E87, 0xECB2, 0x9EAE, 0xECB3, 0x9EAD, 0xECB4, 0x9ED5, 0xECB5, 0x9ED6, 0xECB6, 0x9EFA, 0xECB7, 0x9F12, 0xECB8, 0x9F3D, + 0xECB9, 0x5126, 0xECBA, 0x5125, 0xECBB, 0x5122, 0xECBC, 0x5124, 0xECBD, 0x5120, 0xECBE, 0x5129, 0xECBF, 0x52F4, 0xECC0, 0x5693, + 0xECC1, 0x568C, 0xECC2, 0x568D, 0xECC3, 0x5686, 0xECC4, 0x5684, 0xECC5, 0x5683, 0xECC6, 0x567E, 0xECC7, 0x5682, 0xECC8, 0x567F, + 0xECC9, 0x5681, 0xECCA, 0x58D6, 0xECCB, 0x58D4, 0xECCC, 0x58CF, 0xECCD, 0x58D2, 0xECCE, 0x5B2D, 0xECCF, 0x5B25, 0xECD0, 0x5B32, + 0xECD1, 0x5B23, 0xECD2, 0x5B2C, 0xECD3, 0x5B27, 0xECD4, 0x5B26, 0xECD5, 0x5B2F, 0xECD6, 0x5B2E, 0xECD7, 0x5B7B, 0xECD8, 0x5BF1, + 0xECD9, 0x5BF2, 0xECDA, 0x5DB7, 0xECDB, 0x5E6C, 0xECDC, 0x5E6A, 0xECDD, 0x5FBE, 0xECDE, 0x5FBB, 0xECDF, 0x61C3, 0xECE0, 0x61B5, + 0xECE1, 0x61BC, 0xECE2, 0x61E7, 0xECE3, 0x61E0, 0xECE4, 0x61E5, 0xECE5, 0x61E4, 0xECE6, 0x61E8, 0xECE7, 0x61DE, 0xECE8, 0x64EF, + 0xECE9, 0x64E9, 0xECEA, 0x64E3, 0xECEB, 0x64EB, 0xECEC, 0x64E4, 0xECED, 0x64E8, 0xECEE, 0x6581, 0xECEF, 0x6580, 0xECF0, 0x65B6, + 0xECF1, 0x65DA, 0xECF2, 0x66D2, 0xECF3, 0x6A8D, 0xECF4, 0x6A96, 0xECF5, 0x6A81, 0xECF6, 0x6AA5, 0xECF7, 0x6A89, 0xECF8, 0x6A9F, + 0xECF9, 0x6A9B, 0xECFA, 0x6AA1, 0xECFB, 0x6A9E, 0xECFC, 0x6A87, 0xECFD, 0x6A93, 0xECFE, 0x6A8E, 0xED40, 0x6A95, 0xED41, 0x6A83, + 0xED42, 0x6AA8, 0xED43, 0x6AA4, 0xED44, 0x6A91, 0xED45, 0x6A7F, 0xED46, 0x6AA6, 0xED47, 0x6A9A, 0xED48, 0x6A85, 0xED49, 0x6A8C, + 0xED4A, 0x6A92, 0xED4B, 0x6B5B, 0xED4C, 0x6BAD, 0xED4D, 0x6C09, 0xED4E, 0x6FCC, 0xED4F, 0x6FA9, 0xED50, 0x6FF4, 0xED51, 0x6FD4, + 0xED52, 0x6FE3, 0xED53, 0x6FDC, 0xED54, 0x6FED, 0xED55, 0x6FE7, 0xED56, 0x6FE6, 0xED57, 0x6FDE, 0xED58, 0x6FF2, 0xED59, 0x6FDD, + 0xED5A, 0x6FE2, 0xED5B, 0x6FE8, 0xED5C, 0x71E1, 0xED5D, 0x71F1, 0xED5E, 0x71E8, 0xED5F, 0x71F2, 0xED60, 0x71E4, 0xED61, 0x71F0, + 0xED62, 0x71E2, 0xED63, 0x7373, 0xED64, 0x736E, 0xED65, 0x736F, 0xED66, 0x7497, 0xED67, 0x74B2, 0xED68, 0x74AB, 0xED69, 0x7490, + 0xED6A, 0x74AA, 0xED6B, 0x74AD, 0xED6C, 0x74B1, 0xED6D, 0x74A5, 0xED6E, 0x74AF, 0xED6F, 0x7510, 0xED70, 0x7511, 0xED71, 0x7512, + 0xED72, 0x750F, 0xED73, 0x7584, 0xED74, 0x7643, 0xED75, 0x7648, 0xED76, 0x7649, 0xED77, 0x7647, 0xED78, 0x76A4, 0xED79, 0x76E9, + 0xED7A, 0x77B5, 0xED7B, 0x77AB, 0xED7C, 0x77B2, 0xED7D, 0x77B7, 0xED7E, 0x77B6, 0xEDA1, 0x77B4, 0xEDA2, 0x77B1, 0xEDA3, 0x77A8, + 0xEDA4, 0x77F0, 0xEDA5, 0x78F3, 0xEDA6, 0x78FD, 0xEDA7, 0x7902, 0xEDA8, 0x78FB, 0xEDA9, 0x78FC, 0xEDAA, 0x78F2, 0xEDAB, 0x7905, + 0xEDAC, 0x78F9, 0xEDAD, 0x78FE, 0xEDAE, 0x7904, 0xEDAF, 0x79AB, 0xEDB0, 0x79A8, 0xEDB1, 0x7A5C, 0xEDB2, 0x7A5B, 0xEDB3, 0x7A56, + 0xEDB4, 0x7A58, 0xEDB5, 0x7A54, 0xEDB6, 0x7A5A, 0xEDB7, 0x7ABE, 0xEDB8, 0x7AC0, 0xEDB9, 0x7AC1, 0xEDBA, 0x7C05, 0xEDBB, 0x7C0F, + 0xEDBC, 0x7BF2, 0xEDBD, 0x7C00, 0xEDBE, 0x7BFF, 0xEDBF, 0x7BFB, 0xEDC0, 0x7C0E, 0xEDC1, 0x7BF4, 0xEDC2, 0x7C0B, 0xEDC3, 0x7BF3, + 0xEDC4, 0x7C02, 0xEDC5, 0x7C09, 0xEDC6, 0x7C03, 0xEDC7, 0x7C01, 0xEDC8, 0x7BF8, 0xEDC9, 0x7BFD, 0xEDCA, 0x7C06, 0xEDCB, 0x7BF0, + 0xEDCC, 0x7BF1, 0xEDCD, 0x7C10, 0xEDCE, 0x7C0A, 0xEDCF, 0x7CE8, 0xEDD0, 0x7E2D, 0xEDD1, 0x7E3C, 0xEDD2, 0x7E42, 0xEDD3, 0x7E33, + 0xEDD4, 0x9848, 0xEDD5, 0x7E38, 0xEDD6, 0x7E2A, 0xEDD7, 0x7E49, 0xEDD8, 0x7E40, 0xEDD9, 0x7E47, 0xEDDA, 0x7E29, 0xEDDB, 0x7E4C, + 0xEDDC, 0x7E30, 0xEDDD, 0x7E3B, 0xEDDE, 0x7E36, 0xEDDF, 0x7E44, 0xEDE0, 0x7E3A, 0xEDE1, 0x7F45, 0xEDE2, 0x7F7F, 0xEDE3, 0x7F7E, + 0xEDE4, 0x7F7D, 0xEDE5, 0x7FF4, 0xEDE6, 0x7FF2, 0xEDE7, 0x802C, 0xEDE8, 0x81BB, 0xEDE9, 0x81C4, 0xEDEA, 0x81CC, 0xEDEB, 0x81CA, + 0xEDEC, 0x81C5, 0xEDED, 0x81C7, 0xEDEE, 0x81BC, 0xEDEF, 0x81E9, 0xEDF0, 0x825B, 0xEDF1, 0x825A, 0xEDF2, 0x825C, 0xEDF3, 0x8583, + 0xEDF4, 0x8580, 0xEDF5, 0x858F, 0xEDF6, 0x85A7, 0xEDF7, 0x8595, 0xEDF8, 0x85A0, 0xEDF9, 0x858B, 0xEDFA, 0x85A3, 0xEDFB, 0x857B, + 0xEDFC, 0x85A4, 0xEDFD, 0x859A, 0xEDFE, 0x859E, 0xEE40, 0x8577, 0xEE41, 0x857C, 0xEE42, 0x8589, 0xEE43, 0x85A1, 0xEE44, 0x857A, + 0xEE45, 0x8578, 0xEE46, 0x8557, 0xEE47, 0x858E, 0xEE48, 0x8596, 0xEE49, 0x8586, 0xEE4A, 0x858D, 0xEE4B, 0x8599, 0xEE4C, 0x859D, + 0xEE4D, 0x8581, 0xEE4E, 0x85A2, 0xEE4F, 0x8582, 0xEE50, 0x8588, 0xEE51, 0x8585, 0xEE52, 0x8579, 0xEE53, 0x8576, 0xEE54, 0x8598, + 0xEE55, 0x8590, 0xEE56, 0x859F, 0xEE57, 0x8668, 0xEE58, 0x87BE, 0xEE59, 0x87AA, 0xEE5A, 0x87AD, 0xEE5B, 0x87C5, 0xEE5C, 0x87B0, + 0xEE5D, 0x87AC, 0xEE5E, 0x87B9, 0xEE5F, 0x87B5, 0xEE60, 0x87BC, 0xEE61, 0x87AE, 0xEE62, 0x87C9, 0xEE63, 0x87C3, 0xEE64, 0x87C2, + 0xEE65, 0x87CC, 0xEE66, 0x87B7, 0xEE67, 0x87AF, 0xEE68, 0x87C4, 0xEE69, 0x87CA, 0xEE6A, 0x87B4, 0xEE6B, 0x87B6, 0xEE6C, 0x87BF, + 0xEE6D, 0x87B8, 0xEE6E, 0x87BD, 0xEE6F, 0x87DE, 0xEE70, 0x87B2, 0xEE71, 0x8935, 0xEE72, 0x8933, 0xEE73, 0x893C, 0xEE74, 0x893E, + 0xEE75, 0x8941, 0xEE76, 0x8952, 0xEE77, 0x8937, 0xEE78, 0x8942, 0xEE79, 0x89AD, 0xEE7A, 0x89AF, 0xEE7B, 0x89AE, 0xEE7C, 0x89F2, + 0xEE7D, 0x89F3, 0xEE7E, 0x8B1E, 0xEEA1, 0x8B18, 0xEEA2, 0x8B16, 0xEEA3, 0x8B11, 0xEEA4, 0x8B05, 0xEEA5, 0x8B0B, 0xEEA6, 0x8B22, + 0xEEA7, 0x8B0F, 0xEEA8, 0x8B12, 0xEEA9, 0x8B15, 0xEEAA, 0x8B07, 0xEEAB, 0x8B0D, 0xEEAC, 0x8B08, 0xEEAD, 0x8B06, 0xEEAE, 0x8B1C, + 0xEEAF, 0x8B13, 0xEEB0, 0x8B1A, 0xEEB1, 0x8C4F, 0xEEB2, 0x8C70, 0xEEB3, 0x8C72, 0xEEB4, 0x8C71, 0xEEB5, 0x8C6F, 0xEEB6, 0x8C95, + 0xEEB7, 0x8C94, 0xEEB8, 0x8CF9, 0xEEB9, 0x8D6F, 0xEEBA, 0x8E4E, 0xEEBB, 0x8E4D, 0xEEBC, 0x8E53, 0xEEBD, 0x8E50, 0xEEBE, 0x8E4C, + 0xEEBF, 0x8E47, 0xEEC0, 0x8F43, 0xEEC1, 0x8F40, 0xEEC2, 0x9085, 0xEEC3, 0x907E, 0xEEC4, 0x9138, 0xEEC5, 0x919A, 0xEEC6, 0x91A2, + 0xEEC7, 0x919B, 0xEEC8, 0x9199, 0xEEC9, 0x919F, 0xEECA, 0x91A1, 0xEECB, 0x919D, 0xEECC, 0x91A0, 0xEECD, 0x93A1, 0xEECE, 0x9383, + 0xEECF, 0x93AF, 0xEED0, 0x9364, 0xEED1, 0x9356, 0xEED2, 0x9347, 0xEED3, 0x937C, 0xEED4, 0x9358, 0xEED5, 0x935C, 0xEED6, 0x9376, + 0xEED7, 0x9349, 0xEED8, 0x9350, 0xEED9, 0x9351, 0xEEDA, 0x9360, 0xEEDB, 0x936D, 0xEEDC, 0x938F, 0xEEDD, 0x934C, 0xEEDE, 0x936A, + 0xEEDF, 0x9379, 0xEEE0, 0x9357, 0xEEE1, 0x9355, 0xEEE2, 0x9352, 0xEEE3, 0x934F, 0xEEE4, 0x9371, 0xEEE5, 0x9377, 0xEEE6, 0x937B, + 0xEEE7, 0x9361, 0xEEE8, 0x935E, 0xEEE9, 0x9363, 0xEEEA, 0x9367, 0xEEEB, 0x9380, 0xEEEC, 0x934E, 0xEEED, 0x9359, 0xEEEE, 0x95C7, + 0xEEEF, 0x95C0, 0xEEF0, 0x95C9, 0xEEF1, 0x95C3, 0xEEF2, 0x95C5, 0xEEF3, 0x95B7, 0xEEF4, 0x96AE, 0xEEF5, 0x96B0, 0xEEF6, 0x96AC, + 0xEEF7, 0x9720, 0xEEF8, 0x971F, 0xEEF9, 0x9718, 0xEEFA, 0x971D, 0xEEFB, 0x9719, 0xEEFC, 0x979A, 0xEEFD, 0x97A1, 0xEEFE, 0x979C, + 0xEF40, 0x979E, 0xEF41, 0x979D, 0xEF42, 0x97D5, 0xEF43, 0x97D4, 0xEF44, 0x97F1, 0xEF45, 0x9841, 0xEF46, 0x9844, 0xEF47, 0x984A, + 0xEF48, 0x9849, 0xEF49, 0x9845, 0xEF4A, 0x9843, 0xEF4B, 0x9925, 0xEF4C, 0x992B, 0xEF4D, 0x992C, 0xEF4E, 0x992A, 0xEF4F, 0x9933, + 0xEF50, 0x9932, 0xEF51, 0x992F, 0xEF52, 0x992D, 0xEF53, 0x9931, 0xEF54, 0x9930, 0xEF55, 0x9998, 0xEF56, 0x99A3, 0xEF57, 0x99A1, + 0xEF58, 0x9A02, 0xEF59, 0x99FA, 0xEF5A, 0x99F4, 0xEF5B, 0x99F7, 0xEF5C, 0x99F9, 0xEF5D, 0x99F8, 0xEF5E, 0x99F6, 0xEF5F, 0x99FB, + 0xEF60, 0x99FD, 0xEF61, 0x99FE, 0xEF62, 0x99FC, 0xEF63, 0x9A03, 0xEF64, 0x9ABE, 0xEF65, 0x9AFE, 0xEF66, 0x9AFD, 0xEF67, 0x9B01, + 0xEF68, 0x9AFC, 0xEF69, 0x9B48, 0xEF6A, 0x9B9A, 0xEF6B, 0x9BA8, 0xEF6C, 0x9B9E, 0xEF6D, 0x9B9B, 0xEF6E, 0x9BA6, 0xEF6F, 0x9BA1, + 0xEF70, 0x9BA5, 0xEF71, 0x9BA4, 0xEF72, 0x9B86, 0xEF73, 0x9BA2, 0xEF74, 0x9BA0, 0xEF75, 0x9BAF, 0xEF76, 0x9D33, 0xEF77, 0x9D41, + 0xEF78, 0x9D67, 0xEF79, 0x9D36, 0xEF7A, 0x9D2E, 0xEF7B, 0x9D2F, 0xEF7C, 0x9D31, 0xEF7D, 0x9D38, 0xEF7E, 0x9D30, 0xEFA1, 0x9D45, + 0xEFA2, 0x9D42, 0xEFA3, 0x9D43, 0xEFA4, 0x9D3E, 0xEFA5, 0x9D37, 0xEFA6, 0x9D40, 0xEFA7, 0x9D3D, 0xEFA8, 0x7FF5, 0xEFA9, 0x9D2D, + 0xEFAA, 0x9E8A, 0xEFAB, 0x9E89, 0xEFAC, 0x9E8D, 0xEFAD, 0x9EB0, 0xEFAE, 0x9EC8, 0xEFAF, 0x9EDA, 0xEFB0, 0x9EFB, 0xEFB1, 0x9EFF, + 0xEFB2, 0x9F24, 0xEFB3, 0x9F23, 0xEFB4, 0x9F22, 0xEFB5, 0x9F54, 0xEFB6, 0x9FA0, 0xEFB7, 0x5131, 0xEFB8, 0x512D, 0xEFB9, 0x512E, + 0xEFBA, 0x5698, 0xEFBB, 0x569C, 0xEFBC, 0x5697, 0xEFBD, 0x569A, 0xEFBE, 0x569D, 0xEFBF, 0x5699, 0xEFC0, 0x5970, 0xEFC1, 0x5B3C, + 0xEFC2, 0x5C69, 0xEFC3, 0x5C6A, 0xEFC4, 0x5DC0, 0xEFC5, 0x5E6D, 0xEFC6, 0x5E6E, 0xEFC7, 0x61D8, 0xEFC8, 0x61DF, 0xEFC9, 0x61ED, + 0xEFCA, 0x61EE, 0xEFCB, 0x61F1, 0xEFCC, 0x61EA, 0xEFCD, 0x61F0, 0xEFCE, 0x61EB, 0xEFCF, 0x61D6, 0xEFD0, 0x61E9, 0xEFD1, 0x64FF, + 0xEFD2, 0x6504, 0xEFD3, 0x64FD, 0xEFD4, 0x64F8, 0xEFD5, 0x6501, 0xEFD6, 0x6503, 0xEFD7, 0x64FC, 0xEFD8, 0x6594, 0xEFD9, 0x65DB, + 0xEFDA, 0x66DA, 0xEFDB, 0x66DB, 0xEFDC, 0x66D8, 0xEFDD, 0x6AC5, 0xEFDE, 0x6AB9, 0xEFDF, 0x6ABD, 0xEFE0, 0x6AE1, 0xEFE1, 0x6AC6, + 0xEFE2, 0x6ABA, 0xEFE3, 0x6AB6, 0xEFE4, 0x6AB7, 0xEFE5, 0x6AC7, 0xEFE6, 0x6AB4, 0xEFE7, 0x6AAD, 0xEFE8, 0x6B5E, 0xEFE9, 0x6BC9, + 0xEFEA, 0x6C0B, 0xEFEB, 0x7007, 0xEFEC, 0x700C, 0xEFED, 0x700D, 0xEFEE, 0x7001, 0xEFEF, 0x7005, 0xEFF0, 0x7014, 0xEFF1, 0x700E, + 0xEFF2, 0x6FFF, 0xEFF3, 0x7000, 0xEFF4, 0x6FFB, 0xEFF5, 0x7026, 0xEFF6, 0x6FFC, 0xEFF7, 0x6FF7, 0xEFF8, 0x700A, 0xEFF9, 0x7201, + 0xEFFA, 0x71FF, 0xEFFB, 0x71F9, 0xEFFC, 0x7203, 0xEFFD, 0x71FD, 0xEFFE, 0x7376, 0xF040, 0x74B8, 0xF041, 0x74C0, 0xF042, 0x74B5, + 0xF043, 0x74C1, 0xF044, 0x74BE, 0xF045, 0x74B6, 0xF046, 0x74BB, 0xF047, 0x74C2, 0xF048, 0x7514, 0xF049, 0x7513, 0xF04A, 0x765C, + 0xF04B, 0x7664, 0xF04C, 0x7659, 0xF04D, 0x7650, 0xF04E, 0x7653, 0xF04F, 0x7657, 0xF050, 0x765A, 0xF051, 0x76A6, 0xF052, 0x76BD, + 0xF053, 0x76EC, 0xF054, 0x77C2, 0xF055, 0x77BA, 0xF056, 0x78FF, 0xF057, 0x790C, 0xF058, 0x7913, 0xF059, 0x7914, 0xF05A, 0x7909, + 0xF05B, 0x7910, 0xF05C, 0x7912, 0xF05D, 0x7911, 0xF05E, 0x79AD, 0xF05F, 0x79AC, 0xF060, 0x7A5F, 0xF061, 0x7C1C, 0xF062, 0x7C29, + 0xF063, 0x7C19, 0xF064, 0x7C20, 0xF065, 0x7C1F, 0xF066, 0x7C2D, 0xF067, 0x7C1D, 0xF068, 0x7C26, 0xF069, 0x7C28, 0xF06A, 0x7C22, + 0xF06B, 0x7C25, 0xF06C, 0x7C30, 0xF06D, 0x7E5C, 0xF06E, 0x7E50, 0xF06F, 0x7E56, 0xF070, 0x7E63, 0xF071, 0x7E58, 0xF072, 0x7E62, + 0xF073, 0x7E5F, 0xF074, 0x7E51, 0xF075, 0x7E60, 0xF076, 0x7E57, 0xF077, 0x7E53, 0xF078, 0x7FB5, 0xF079, 0x7FB3, 0xF07A, 0x7FF7, + 0xF07B, 0x7FF8, 0xF07C, 0x8075, 0xF07D, 0x81D1, 0xF07E, 0x81D2, 0xF0A1, 0x81D0, 0xF0A2, 0x825F, 0xF0A3, 0x825E, 0xF0A4, 0x85B4, + 0xF0A5, 0x85C6, 0xF0A6, 0x85C0, 0xF0A7, 0x85C3, 0xF0A8, 0x85C2, 0xF0A9, 0x85B3, 0xF0AA, 0x85B5, 0xF0AB, 0x85BD, 0xF0AC, 0x85C7, + 0xF0AD, 0x85C4, 0xF0AE, 0x85BF, 0xF0AF, 0x85CB, 0xF0B0, 0x85CE, 0xF0B1, 0x85C8, 0xF0B2, 0x85C5, 0xF0B3, 0x85B1, 0xF0B4, 0x85B6, + 0xF0B5, 0x85D2, 0xF0B6, 0x8624, 0xF0B7, 0x85B8, 0xF0B8, 0x85B7, 0xF0B9, 0x85BE, 0xF0BA, 0x8669, 0xF0BB, 0x87E7, 0xF0BC, 0x87E6, + 0xF0BD, 0x87E2, 0xF0BE, 0x87DB, 0xF0BF, 0x87EB, 0xF0C0, 0x87EA, 0xF0C1, 0x87E5, 0xF0C2, 0x87DF, 0xF0C3, 0x87F3, 0xF0C4, 0x87E4, + 0xF0C5, 0x87D4, 0xF0C6, 0x87DC, 0xF0C7, 0x87D3, 0xF0C8, 0x87ED, 0xF0C9, 0x87D8, 0xF0CA, 0x87E3, 0xF0CB, 0x87A4, 0xF0CC, 0x87D7, + 0xF0CD, 0x87D9, 0xF0CE, 0x8801, 0xF0CF, 0x87F4, 0xF0D0, 0x87E8, 0xF0D1, 0x87DD, 0xF0D2, 0x8953, 0xF0D3, 0x894B, 0xF0D4, 0x894F, + 0xF0D5, 0x894C, 0xF0D6, 0x8946, 0xF0D7, 0x8950, 0xF0D8, 0x8951, 0xF0D9, 0x8949, 0xF0DA, 0x8B2A, 0xF0DB, 0x8B27, 0xF0DC, 0x8B23, + 0xF0DD, 0x8B33, 0xF0DE, 0x8B30, 0xF0DF, 0x8B35, 0xF0E0, 0x8B47, 0xF0E1, 0x8B2F, 0xF0E2, 0x8B3C, 0xF0E3, 0x8B3E, 0xF0E4, 0x8B31, + 0xF0E5, 0x8B25, 0xF0E6, 0x8B37, 0xF0E7, 0x8B26, 0xF0E8, 0x8B36, 0xF0E9, 0x8B2E, 0xF0EA, 0x8B24, 0xF0EB, 0x8B3B, 0xF0EC, 0x8B3D, + 0xF0ED, 0x8B3A, 0xF0EE, 0x8C42, 0xF0EF, 0x8C75, 0xF0F0, 0x8C99, 0xF0F1, 0x8C98, 0xF0F2, 0x8C97, 0xF0F3, 0x8CFE, 0xF0F4, 0x8D04, + 0xF0F5, 0x8D02, 0xF0F6, 0x8D00, 0xF0F7, 0x8E5C, 0xF0F8, 0x8E62, 0xF0F9, 0x8E60, 0xF0FA, 0x8E57, 0xF0FB, 0x8E56, 0xF0FC, 0x8E5E, + 0xF0FD, 0x8E65, 0xF0FE, 0x8E67, 0xF140, 0x8E5B, 0xF141, 0x8E5A, 0xF142, 0x8E61, 0xF143, 0x8E5D, 0xF144, 0x8E69, 0xF145, 0x8E54, + 0xF146, 0x8F46, 0xF147, 0x8F47, 0xF148, 0x8F48, 0xF149, 0x8F4B, 0xF14A, 0x9128, 0xF14B, 0x913A, 0xF14C, 0x913B, 0xF14D, 0x913E, + 0xF14E, 0x91A8, 0xF14F, 0x91A5, 0xF150, 0x91A7, 0xF151, 0x91AF, 0xF152, 0x91AA, 0xF153, 0x93B5, 0xF154, 0x938C, 0xF155, 0x9392, + 0xF156, 0x93B7, 0xF157, 0x939B, 0xF158, 0x939D, 0xF159, 0x9389, 0xF15A, 0x93A7, 0xF15B, 0x938E, 0xF15C, 0x93AA, 0xF15D, 0x939E, + 0xF15E, 0x93A6, 0xF15F, 0x9395, 0xF160, 0x9388, 0xF161, 0x9399, 0xF162, 0x939F, 0xF163, 0x938D, 0xF164, 0x93B1, 0xF165, 0x9391, + 0xF166, 0x93B2, 0xF167, 0x93A4, 0xF168, 0x93A8, 0xF169, 0x93B4, 0xF16A, 0x93A3, 0xF16B, 0x93A5, 0xF16C, 0x95D2, 0xF16D, 0x95D3, + 0xF16E, 0x95D1, 0xF16F, 0x96B3, 0xF170, 0x96D7, 0xF171, 0x96DA, 0xF172, 0x5DC2, 0xF173, 0x96DF, 0xF174, 0x96D8, 0xF175, 0x96DD, + 0xF176, 0x9723, 0xF177, 0x9722, 0xF178, 0x9725, 0xF179, 0x97AC, 0xF17A, 0x97AE, 0xF17B, 0x97A8, 0xF17C, 0x97AB, 0xF17D, 0x97A4, + 0xF17E, 0x97AA, 0xF1A1, 0x97A2, 0xF1A2, 0x97A5, 0xF1A3, 0x97D7, 0xF1A4, 0x97D9, 0xF1A5, 0x97D6, 0xF1A6, 0x97D8, 0xF1A7, 0x97FA, + 0xF1A8, 0x9850, 0xF1A9, 0x9851, 0xF1AA, 0x9852, 0xF1AB, 0x98B8, 0xF1AC, 0x9941, 0xF1AD, 0x993C, 0xF1AE, 0x993A, 0xF1AF, 0x9A0F, + 0xF1B0, 0x9A0B, 0xF1B1, 0x9A09, 0xF1B2, 0x9A0D, 0xF1B3, 0x9A04, 0xF1B4, 0x9A11, 0xF1B5, 0x9A0A, 0xF1B6, 0x9A05, 0xF1B7, 0x9A07, + 0xF1B8, 0x9A06, 0xF1B9, 0x9AC0, 0xF1BA, 0x9ADC, 0xF1BB, 0x9B08, 0xF1BC, 0x9B04, 0xF1BD, 0x9B05, 0xF1BE, 0x9B29, 0xF1BF, 0x9B35, + 0xF1C0, 0x9B4A, 0xF1C1, 0x9B4C, 0xF1C2, 0x9B4B, 0xF1C3, 0x9BC7, 0xF1C4, 0x9BC6, 0xF1C5, 0x9BC3, 0xF1C6, 0x9BBF, 0xF1C7, 0x9BC1, + 0xF1C8, 0x9BB5, 0xF1C9, 0x9BB8, 0xF1CA, 0x9BD3, 0xF1CB, 0x9BB6, 0xF1CC, 0x9BC4, 0xF1CD, 0x9BB9, 0xF1CE, 0x9BBD, 0xF1CF, 0x9D5C, + 0xF1D0, 0x9D53, 0xF1D1, 0x9D4F, 0xF1D2, 0x9D4A, 0xF1D3, 0x9D5B, 0xF1D4, 0x9D4B, 0xF1D5, 0x9D59, 0xF1D6, 0x9D56, 0xF1D7, 0x9D4C, + 0xF1D8, 0x9D57, 0xF1D9, 0x9D52, 0xF1DA, 0x9D54, 0xF1DB, 0x9D5F, 0xF1DC, 0x9D58, 0xF1DD, 0x9D5A, 0xF1DE, 0x9E8E, 0xF1DF, 0x9E8C, + 0xF1E0, 0x9EDF, 0xF1E1, 0x9F01, 0xF1E2, 0x9F00, 0xF1E3, 0x9F16, 0xF1E4, 0x9F25, 0xF1E5, 0x9F2B, 0xF1E6, 0x9F2A, 0xF1E7, 0x9F29, + 0xF1E8, 0x9F28, 0xF1E9, 0x9F4C, 0xF1EA, 0x9F55, 0xF1EB, 0x5134, 0xF1EC, 0x5135, 0xF1ED, 0x5296, 0xF1EE, 0x52F7, 0xF1EF, 0x53B4, + 0xF1F0, 0x56AB, 0xF1F1, 0x56AD, 0xF1F2, 0x56A6, 0xF1F3, 0x56A7, 0xF1F4, 0x56AA, 0xF1F5, 0x56AC, 0xF1F6, 0x58DA, 0xF1F7, 0x58DD, + 0xF1F8, 0x58DB, 0xF1F9, 0x5912, 0xF1FA, 0x5B3D, 0xF1FB, 0x5B3E, 0xF1FC, 0x5B3F, 0xF1FD, 0x5DC3, 0xF1FE, 0x5E70, 0xF240, 0x5FBF, + 0xF241, 0x61FB, 0xF242, 0x6507, 0xF243, 0x6510, 0xF244, 0x650D, 0xF245, 0x6509, 0xF246, 0x650C, 0xF247, 0x650E, 0xF248, 0x6584, + 0xF249, 0x65DE, 0xF24A, 0x65DD, 0xF24B, 0x66DE, 0xF24C, 0x6AE7, 0xF24D, 0x6AE0, 0xF24E, 0x6ACC, 0xF24F, 0x6AD1, 0xF250, 0x6AD9, + 0xF251, 0x6ACB, 0xF252, 0x6ADF, 0xF253, 0x6ADC, 0xF254, 0x6AD0, 0xF255, 0x6AEB, 0xF256, 0x6ACF, 0xF257, 0x6ACD, 0xF258, 0x6ADE, + 0xF259, 0x6B60, 0xF25A, 0x6BB0, 0xF25B, 0x6C0C, 0xF25C, 0x7019, 0xF25D, 0x7027, 0xF25E, 0x7020, 0xF25F, 0x7016, 0xF260, 0x702B, + 0xF261, 0x7021, 0xF262, 0x7022, 0xF263, 0x7023, 0xF264, 0x7029, 0xF265, 0x7017, 0xF266, 0x7024, 0xF267, 0x701C, 0xF268, 0x702A, + 0xF269, 0x720C, 0xF26A, 0x720A, 0xF26B, 0x7207, 0xF26C, 0x7202, 0xF26D, 0x7205, 0xF26E, 0x72A5, 0xF26F, 0x72A6, 0xF270, 0x72A4, + 0xF271, 0x72A3, 0xF272, 0x72A1, 0xF273, 0x74CB, 0xF274, 0x74C5, 0xF275, 0x74B7, 0xF276, 0x74C3, 0xF277, 0x7516, 0xF278, 0x7660, + 0xF279, 0x77C9, 0xF27A, 0x77CA, 0xF27B, 0x77C4, 0xF27C, 0x77F1, 0xF27D, 0x791D, 0xF27E, 0x791B, 0xF2A1, 0x7921, 0xF2A2, 0x791C, + 0xF2A3, 0x7917, 0xF2A4, 0x791E, 0xF2A5, 0x79B0, 0xF2A6, 0x7A67, 0xF2A7, 0x7A68, 0xF2A8, 0x7C33, 0xF2A9, 0x7C3C, 0xF2AA, 0x7C39, + 0xF2AB, 0x7C2C, 0xF2AC, 0x7C3B, 0xF2AD, 0x7CEC, 0xF2AE, 0x7CEA, 0xF2AF, 0x7E76, 0xF2B0, 0x7E75, 0xF2B1, 0x7E78, 0xF2B2, 0x7E70, + 0xF2B3, 0x7E77, 0xF2B4, 0x7E6F, 0xF2B5, 0x7E7A, 0xF2B6, 0x7E72, 0xF2B7, 0x7E74, 0xF2B8, 0x7E68, 0xF2B9, 0x7F4B, 0xF2BA, 0x7F4A, + 0xF2BB, 0x7F83, 0xF2BC, 0x7F86, 0xF2BD, 0x7FB7, 0xF2BE, 0x7FFD, 0xF2BF, 0x7FFE, 0xF2C0, 0x8078, 0xF2C1, 0x81D7, 0xF2C2, 0x81D5, + 0xF2C3, 0x8264, 0xF2C4, 0x8261, 0xF2C5, 0x8263, 0xF2C6, 0x85EB, 0xF2C7, 0x85F1, 0xF2C8, 0x85ED, 0xF2C9, 0x85D9, 0xF2CA, 0x85E1, + 0xF2CB, 0x85E8, 0xF2CC, 0x85DA, 0xF2CD, 0x85D7, 0xF2CE, 0x85EC, 0xF2CF, 0x85F2, 0xF2D0, 0x85F8, 0xF2D1, 0x85D8, 0xF2D2, 0x85DF, + 0xF2D3, 0x85E3, 0xF2D4, 0x85DC, 0xF2D5, 0x85D1, 0xF2D6, 0x85F0, 0xF2D7, 0x85E6, 0xF2D8, 0x85EF, 0xF2D9, 0x85DE, 0xF2DA, 0x85E2, + 0xF2DB, 0x8800, 0xF2DC, 0x87FA, 0xF2DD, 0x8803, 0xF2DE, 0x87F6, 0xF2DF, 0x87F7, 0xF2E0, 0x8809, 0xF2E1, 0x880C, 0xF2E2, 0x880B, + 0xF2E3, 0x8806, 0xF2E4, 0x87FC, 0xF2E5, 0x8808, 0xF2E6, 0x87FF, 0xF2E7, 0x880A, 0xF2E8, 0x8802, 0xF2E9, 0x8962, 0xF2EA, 0x895A, + 0xF2EB, 0x895B, 0xF2EC, 0x8957, 0xF2ED, 0x8961, 0xF2EE, 0x895C, 0xF2EF, 0x8958, 0xF2F0, 0x895D, 0xF2F1, 0x8959, 0xF2F2, 0x8988, + 0xF2F3, 0x89B7, 0xF2F4, 0x89B6, 0xF2F5, 0x89F6, 0xF2F6, 0x8B50, 0xF2F7, 0x8B48, 0xF2F8, 0x8B4A, 0xF2F9, 0x8B40, 0xF2FA, 0x8B53, + 0xF2FB, 0x8B56, 0xF2FC, 0x8B54, 0xF2FD, 0x8B4B, 0xF2FE, 0x8B55, 0xF340, 0x8B51, 0xF341, 0x8B42, 0xF342, 0x8B52, 0xF343, 0x8B57, + 0xF344, 0x8C43, 0xF345, 0x8C77, 0xF346, 0x8C76, 0xF347, 0x8C9A, 0xF348, 0x8D06, 0xF349, 0x8D07, 0xF34A, 0x8D09, 0xF34B, 0x8DAC, + 0xF34C, 0x8DAA, 0xF34D, 0x8DAD, 0xF34E, 0x8DAB, 0xF34F, 0x8E6D, 0xF350, 0x8E78, 0xF351, 0x8E73, 0xF352, 0x8E6A, 0xF353, 0x8E6F, + 0xF354, 0x8E7B, 0xF355, 0x8EC2, 0xF356, 0x8F52, 0xF357, 0x8F51, 0xF358, 0x8F4F, 0xF359, 0x8F50, 0xF35A, 0x8F53, 0xF35B, 0x8FB4, + 0xF35C, 0x9140, 0xF35D, 0x913F, 0xF35E, 0x91B0, 0xF35F, 0x91AD, 0xF360, 0x93DE, 0xF361, 0x93C7, 0xF362, 0x93CF, 0xF363, 0x93C2, + 0xF364, 0x93DA, 0xF365, 0x93D0, 0xF366, 0x93F9, 0xF367, 0x93EC, 0xF368, 0x93CC, 0xF369, 0x93D9, 0xF36A, 0x93A9, 0xF36B, 0x93E6, + 0xF36C, 0x93CA, 0xF36D, 0x93D4, 0xF36E, 0x93EE, 0xF36F, 0x93E3, 0xF370, 0x93D5, 0xF371, 0x93C4, 0xF372, 0x93CE, 0xF373, 0x93C0, + 0xF374, 0x93D2, 0xF375, 0x93E7, 0xF376, 0x957D, 0xF377, 0x95DA, 0xF378, 0x95DB, 0xF379, 0x96E1, 0xF37A, 0x9729, 0xF37B, 0x972B, + 0xF37C, 0x972C, 0xF37D, 0x9728, 0xF37E, 0x9726, 0xF3A1, 0x97B3, 0xF3A2, 0x97B7, 0xF3A3, 0x97B6, 0xF3A4, 0x97DD, 0xF3A5, 0x97DE, + 0xF3A6, 0x97DF, 0xF3A7, 0x985C, 0xF3A8, 0x9859, 0xF3A9, 0x985D, 0xF3AA, 0x9857, 0xF3AB, 0x98BF, 0xF3AC, 0x98BD, 0xF3AD, 0x98BB, + 0xF3AE, 0x98BE, 0xF3AF, 0x9948, 0xF3B0, 0x9947, 0xF3B1, 0x9943, 0xF3B2, 0x99A6, 0xF3B3, 0x99A7, 0xF3B4, 0x9A1A, 0xF3B5, 0x9A15, + 0xF3B6, 0x9A25, 0xF3B7, 0x9A1D, 0xF3B8, 0x9A24, 0xF3B9, 0x9A1B, 0xF3BA, 0x9A22, 0xF3BB, 0x9A20, 0xF3BC, 0x9A27, 0xF3BD, 0x9A23, + 0xF3BE, 0x9A1E, 0xF3BF, 0x9A1C, 0xF3C0, 0x9A14, 0xF3C1, 0x9AC2, 0xF3C2, 0x9B0B, 0xF3C3, 0x9B0A, 0xF3C4, 0x9B0E, 0xF3C5, 0x9B0C, + 0xF3C6, 0x9B37, 0xF3C7, 0x9BEA, 0xF3C8, 0x9BEB, 0xF3C9, 0x9BE0, 0xF3CA, 0x9BDE, 0xF3CB, 0x9BE4, 0xF3CC, 0x9BE6, 0xF3CD, 0x9BE2, + 0xF3CE, 0x9BF0, 0xF3CF, 0x9BD4, 0xF3D0, 0x9BD7, 0xF3D1, 0x9BEC, 0xF3D2, 0x9BDC, 0xF3D3, 0x9BD9, 0xF3D4, 0x9BE5, 0xF3D5, 0x9BD5, + 0xF3D6, 0x9BE1, 0xF3D7, 0x9BDA, 0xF3D8, 0x9D77, 0xF3D9, 0x9D81, 0xF3DA, 0x9D8A, 0xF3DB, 0x9D84, 0xF3DC, 0x9D88, 0xF3DD, 0x9D71, + 0xF3DE, 0x9D80, 0xF3DF, 0x9D78, 0xF3E0, 0x9D86, 0xF3E1, 0x9D8B, 0xF3E2, 0x9D8C, 0xF3E3, 0x9D7D, 0xF3E4, 0x9D6B, 0xF3E5, 0x9D74, + 0xF3E6, 0x9D75, 0xF3E7, 0x9D70, 0xF3E8, 0x9D69, 0xF3E9, 0x9D85, 0xF3EA, 0x9D73, 0xF3EB, 0x9D7B, 0xF3EC, 0x9D82, 0xF3ED, 0x9D6F, + 0xF3EE, 0x9D79, 0xF3EF, 0x9D7F, 0xF3F0, 0x9D87, 0xF3F1, 0x9D68, 0xF3F2, 0x9E94, 0xF3F3, 0x9E91, 0xF3F4, 0x9EC0, 0xF3F5, 0x9EFC, + 0xF3F6, 0x9F2D, 0xF3F7, 0x9F40, 0xF3F8, 0x9F41, 0xF3F9, 0x9F4D, 0xF3FA, 0x9F56, 0xF3FB, 0x9F57, 0xF3FC, 0x9F58, 0xF3FD, 0x5337, + 0xF3FE, 0x56B2, 0xF440, 0x56B5, 0xF441, 0x56B3, 0xF442, 0x58E3, 0xF443, 0x5B45, 0xF444, 0x5DC6, 0xF445, 0x5DC7, 0xF446, 0x5EEE, + 0xF447, 0x5EEF, 0xF448, 0x5FC0, 0xF449, 0x5FC1, 0xF44A, 0x61F9, 0xF44B, 0x6517, 0xF44C, 0x6516, 0xF44D, 0x6515, 0xF44E, 0x6513, + 0xF44F, 0x65DF, 0xF450, 0x66E8, 0xF451, 0x66E3, 0xF452, 0x66E4, 0xF453, 0x6AF3, 0xF454, 0x6AF0, 0xF455, 0x6AEA, 0xF456, 0x6AE8, + 0xF457, 0x6AF9, 0xF458, 0x6AF1, 0xF459, 0x6AEE, 0xF45A, 0x6AEF, 0xF45B, 0x703C, 0xF45C, 0x7035, 0xF45D, 0x702F, 0xF45E, 0x7037, + 0xF45F, 0x7034, 0xF460, 0x7031, 0xF461, 0x7042, 0xF462, 0x7038, 0xF463, 0x703F, 0xF464, 0x703A, 0xF465, 0x7039, 0xF466, 0x7040, + 0xF467, 0x703B, 0xF468, 0x7033, 0xF469, 0x7041, 0xF46A, 0x7213, 0xF46B, 0x7214, 0xF46C, 0x72A8, 0xF46D, 0x737D, 0xF46E, 0x737C, + 0xF46F, 0x74BA, 0xF470, 0x76AB, 0xF471, 0x76AA, 0xF472, 0x76BE, 0xF473, 0x76ED, 0xF474, 0x77CC, 0xF475, 0x77CE, 0xF476, 0x77CF, + 0xF477, 0x77CD, 0xF478, 0x77F2, 0xF479, 0x7925, 0xF47A, 0x7923, 0xF47B, 0x7927, 0xF47C, 0x7928, 0xF47D, 0x7924, 0xF47E, 0x7929, + 0xF4A1, 0x79B2, 0xF4A2, 0x7A6E, 0xF4A3, 0x7A6C, 0xF4A4, 0x7A6D, 0xF4A5, 0x7AF7, 0xF4A6, 0x7C49, 0xF4A7, 0x7C48, 0xF4A8, 0x7C4A, + 0xF4A9, 0x7C47, 0xF4AA, 0x7C45, 0xF4AB, 0x7CEE, 0xF4AC, 0x7E7B, 0xF4AD, 0x7E7E, 0xF4AE, 0x7E81, 0xF4AF, 0x7E80, 0xF4B0, 0x7FBA, + 0xF4B1, 0x7FFF, 0xF4B2, 0x8079, 0xF4B3, 0x81DB, 0xF4B4, 0x81D9, 0xF4B5, 0x820B, 0xF4B6, 0x8268, 0xF4B7, 0x8269, 0xF4B8, 0x8622, + 0xF4B9, 0x85FF, 0xF4BA, 0x8601, 0xF4BB, 0x85FE, 0xF4BC, 0x861B, 0xF4BD, 0x8600, 0xF4BE, 0x85F6, 0xF4BF, 0x8604, 0xF4C0, 0x8609, + 0xF4C1, 0x8605, 0xF4C2, 0x860C, 0xF4C3, 0x85FD, 0xF4C4, 0x8819, 0xF4C5, 0x8810, 0xF4C6, 0x8811, 0xF4C7, 0x8817, 0xF4C8, 0x8813, + 0xF4C9, 0x8816, 0xF4CA, 0x8963, 0xF4CB, 0x8966, 0xF4CC, 0x89B9, 0xF4CD, 0x89F7, 0xF4CE, 0x8B60, 0xF4CF, 0x8B6A, 0xF4D0, 0x8B5D, + 0xF4D1, 0x8B68, 0xF4D2, 0x8B63, 0xF4D3, 0x8B65, 0xF4D4, 0x8B67, 0xF4D5, 0x8B6D, 0xF4D6, 0x8DAE, 0xF4D7, 0x8E86, 0xF4D8, 0x8E88, + 0xF4D9, 0x8E84, 0xF4DA, 0x8F59, 0xF4DB, 0x8F56, 0xF4DC, 0x8F57, 0xF4DD, 0x8F55, 0xF4DE, 0x8F58, 0xF4DF, 0x8F5A, 0xF4E0, 0x908D, + 0xF4E1, 0x9143, 0xF4E2, 0x9141, 0xF4E3, 0x91B7, 0xF4E4, 0x91B5, 0xF4E5, 0x91B2, 0xF4E6, 0x91B3, 0xF4E7, 0x940B, 0xF4E8, 0x9413, + 0xF4E9, 0x93FB, 0xF4EA, 0x9420, 0xF4EB, 0x940F, 0xF4EC, 0x9414, 0xF4ED, 0x93FE, 0xF4EE, 0x9415, 0xF4EF, 0x9410, 0xF4F0, 0x9428, + 0xF4F1, 0x9419, 0xF4F2, 0x940D, 0xF4F3, 0x93F5, 0xF4F4, 0x9400, 0xF4F5, 0x93F7, 0xF4F6, 0x9407, 0xF4F7, 0x940E, 0xF4F8, 0x9416, + 0xF4F9, 0x9412, 0xF4FA, 0x93FA, 0xF4FB, 0x9409, 0xF4FC, 0x93F8, 0xF4FD, 0x940A, 0xF4FE, 0x93FF, 0xF540, 0x93FC, 0xF541, 0x940C, + 0xF542, 0x93F6, 0xF543, 0x9411, 0xF544, 0x9406, 0xF545, 0x95DE, 0xF546, 0x95E0, 0xF547, 0x95DF, 0xF548, 0x972E, 0xF549, 0x972F, + 0xF54A, 0x97B9, 0xF54B, 0x97BB, 0xF54C, 0x97FD, 0xF54D, 0x97FE, 0xF54E, 0x9860, 0xF54F, 0x9862, 0xF550, 0x9863, 0xF551, 0x985F, + 0xF552, 0x98C1, 0xF553, 0x98C2, 0xF554, 0x9950, 0xF555, 0x994E, 0xF556, 0x9959, 0xF557, 0x994C, 0xF558, 0x994B, 0xF559, 0x9953, + 0xF55A, 0x9A32, 0xF55B, 0x9A34, 0xF55C, 0x9A31, 0xF55D, 0x9A2C, 0xF55E, 0x9A2A, 0xF55F, 0x9A36, 0xF560, 0x9A29, 0xF561, 0x9A2E, + 0xF562, 0x9A38, 0xF563, 0x9A2D, 0xF564, 0x9AC7, 0xF565, 0x9ACA, 0xF566, 0x9AC6, 0xF567, 0x9B10, 0xF568, 0x9B12, 0xF569, 0x9B11, + 0xF56A, 0x9C0B, 0xF56B, 0x9C08, 0xF56C, 0x9BF7, 0xF56D, 0x9C05, 0xF56E, 0x9C12, 0xF56F, 0x9BF8, 0xF570, 0x9C40, 0xF571, 0x9C07, + 0xF572, 0x9C0E, 0xF573, 0x9C06, 0xF574, 0x9C17, 0xF575, 0x9C14, 0xF576, 0x9C09, 0xF577, 0x9D9F, 0xF578, 0x9D99, 0xF579, 0x9DA4, + 0xF57A, 0x9D9D, 0xF57B, 0x9D92, 0xF57C, 0x9D98, 0xF57D, 0x9D90, 0xF57E, 0x9D9B, 0xF5A1, 0x9DA0, 0xF5A2, 0x9D94, 0xF5A3, 0x9D9C, + 0xF5A4, 0x9DAA, 0xF5A5, 0x9D97, 0xF5A6, 0x9DA1, 0xF5A7, 0x9D9A, 0xF5A8, 0x9DA2, 0xF5A9, 0x9DA8, 0xF5AA, 0x9D9E, 0xF5AB, 0x9DA3, + 0xF5AC, 0x9DBF, 0xF5AD, 0x9DA9, 0xF5AE, 0x9D96, 0xF5AF, 0x9DA6, 0xF5B0, 0x9DA7, 0xF5B1, 0x9E99, 0xF5B2, 0x9E9B, 0xF5B3, 0x9E9A, + 0xF5B4, 0x9EE5, 0xF5B5, 0x9EE4, 0xF5B6, 0x9EE7, 0xF5B7, 0x9EE6, 0xF5B8, 0x9F30, 0xF5B9, 0x9F2E, 0xF5BA, 0x9F5B, 0xF5BB, 0x9F60, + 0xF5BC, 0x9F5E, 0xF5BD, 0x9F5D, 0xF5BE, 0x9F59, 0xF5BF, 0x9F91, 0xF5C0, 0x513A, 0xF5C1, 0x5139, 0xF5C2, 0x5298, 0xF5C3, 0x5297, + 0xF5C4, 0x56C3, 0xF5C5, 0x56BD, 0xF5C6, 0x56BE, 0xF5C7, 0x5B48, 0xF5C8, 0x5B47, 0xF5C9, 0x5DCB, 0xF5CA, 0x5DCF, 0xF5CB, 0x5EF1, + 0xF5CC, 0x61FD, 0xF5CD, 0x651B, 0xF5CE, 0x6B02, 0xF5CF, 0x6AFC, 0xF5D0, 0x6B03, 0xF5D1, 0x6AF8, 0xF5D2, 0x6B00, 0xF5D3, 0x7043, + 0xF5D4, 0x7044, 0xF5D5, 0x704A, 0xF5D6, 0x7048, 0xF5D7, 0x7049, 0xF5D8, 0x7045, 0xF5D9, 0x7046, 0xF5DA, 0x721D, 0xF5DB, 0x721A, + 0xF5DC, 0x7219, 0xF5DD, 0x737E, 0xF5DE, 0x7517, 0xF5DF, 0x766A, 0xF5E0, 0x77D0, 0xF5E1, 0x792D, 0xF5E2, 0x7931, 0xF5E3, 0x792F, + 0xF5E4, 0x7C54, 0xF5E5, 0x7C53, 0xF5E6, 0x7CF2, 0xF5E7, 0x7E8A, 0xF5E8, 0x7E87, 0xF5E9, 0x7E88, 0xF5EA, 0x7E8B, 0xF5EB, 0x7E86, + 0xF5EC, 0x7E8D, 0xF5ED, 0x7F4D, 0xF5EE, 0x7FBB, 0xF5EF, 0x8030, 0xF5F0, 0x81DD, 0xF5F1, 0x8618, 0xF5F2, 0x862A, 0xF5F3, 0x8626, + 0xF5F4, 0x861F, 0xF5F5, 0x8623, 0xF5F6, 0x861C, 0xF5F7, 0x8619, 0xF5F8, 0x8627, 0xF5F9, 0x862E, 0xF5FA, 0x8621, 0xF5FB, 0x8620, + 0xF5FC, 0x8629, 0xF5FD, 0x861E, 0xF5FE, 0x8625, 0xF640, 0x8829, 0xF641, 0x881D, 0xF642, 0x881B, 0xF643, 0x8820, 0xF644, 0x8824, + 0xF645, 0x881C, 0xF646, 0x882B, 0xF647, 0x884A, 0xF648, 0x896D, 0xF649, 0x8969, 0xF64A, 0x896E, 0xF64B, 0x896B, 0xF64C, 0x89FA, + 0xF64D, 0x8B79, 0xF64E, 0x8B78, 0xF64F, 0x8B45, 0xF650, 0x8B7A, 0xF651, 0x8B7B, 0xF652, 0x8D10, 0xF653, 0x8D14, 0xF654, 0x8DAF, + 0xF655, 0x8E8E, 0xF656, 0x8E8C, 0xF657, 0x8F5E, 0xF658, 0x8F5B, 0xF659, 0x8F5D, 0xF65A, 0x9146, 0xF65B, 0x9144, 0xF65C, 0x9145, + 0xF65D, 0x91B9, 0xF65E, 0x943F, 0xF65F, 0x943B, 0xF660, 0x9436, 0xF661, 0x9429, 0xF662, 0x943D, 0xF663, 0x943C, 0xF664, 0x9430, + 0xF665, 0x9439, 0xF666, 0x942A, 0xF667, 0x9437, 0xF668, 0x942C, 0xF669, 0x9440, 0xF66A, 0x9431, 0xF66B, 0x95E5, 0xF66C, 0x95E4, + 0xF66D, 0x95E3, 0xF66E, 0x9735, 0xF66F, 0x973A, 0xF670, 0x97BF, 0xF671, 0x97E1, 0xF672, 0x9864, 0xF673, 0x98C9, 0xF674, 0x98C6, + 0xF675, 0x98C0, 0xF676, 0x9958, 0xF677, 0x9956, 0xF678, 0x9A39, 0xF679, 0x9A3D, 0xF67A, 0x9A46, 0xF67B, 0x9A44, 0xF67C, 0x9A42, + 0xF67D, 0x9A41, 0xF67E, 0x9A3A, 0xF6A1, 0x9A3F, 0xF6A2, 0x9ACD, 0xF6A3, 0x9B15, 0xF6A4, 0x9B17, 0xF6A5, 0x9B18, 0xF6A6, 0x9B16, + 0xF6A7, 0x9B3A, 0xF6A8, 0x9B52, 0xF6A9, 0x9C2B, 0xF6AA, 0x9C1D, 0xF6AB, 0x9C1C, 0xF6AC, 0x9C2C, 0xF6AD, 0x9C23, 0xF6AE, 0x9C28, + 0xF6AF, 0x9C29, 0xF6B0, 0x9C24, 0xF6B1, 0x9C21, 0xF6B2, 0x9DB7, 0xF6B3, 0x9DB6, 0xF6B4, 0x9DBC, 0xF6B5, 0x9DC1, 0xF6B6, 0x9DC7, + 0xF6B7, 0x9DCA, 0xF6B8, 0x9DCF, 0xF6B9, 0x9DBE, 0xF6BA, 0x9DC5, 0xF6BB, 0x9DC3, 0xF6BC, 0x9DBB, 0xF6BD, 0x9DB5, 0xF6BE, 0x9DCE, + 0xF6BF, 0x9DB9, 0xF6C0, 0x9DBA, 0xF6C1, 0x9DAC, 0xF6C2, 0x9DC8, 0xF6C3, 0x9DB1, 0xF6C4, 0x9DAD, 0xF6C5, 0x9DCC, 0xF6C6, 0x9DB3, + 0xF6C7, 0x9DCD, 0xF6C8, 0x9DB2, 0xF6C9, 0x9E7A, 0xF6CA, 0x9E9C, 0xF6CB, 0x9EEB, 0xF6CC, 0x9EEE, 0xF6CD, 0x9EED, 0xF6CE, 0x9F1B, + 0xF6CF, 0x9F18, 0xF6D0, 0x9F1A, 0xF6D1, 0x9F31, 0xF6D2, 0x9F4E, 0xF6D3, 0x9F65, 0xF6D4, 0x9F64, 0xF6D5, 0x9F92, 0xF6D6, 0x4EB9, + 0xF6D7, 0x56C6, 0xF6D8, 0x56C5, 0xF6D9, 0x56CB, 0xF6DA, 0x5971, 0xF6DB, 0x5B4B, 0xF6DC, 0x5B4C, 0xF6DD, 0x5DD5, 0xF6DE, 0x5DD1, + 0xF6DF, 0x5EF2, 0xF6E0, 0x6521, 0xF6E1, 0x6520, 0xF6E2, 0x6526, 0xF6E3, 0x6522, 0xF6E4, 0x6B0B, 0xF6E5, 0x6B08, 0xF6E6, 0x6B09, + 0xF6E7, 0x6C0D, 0xF6E8, 0x7055, 0xF6E9, 0x7056, 0xF6EA, 0x7057, 0xF6EB, 0x7052, 0xF6EC, 0x721E, 0xF6ED, 0x721F, 0xF6EE, 0x72A9, + 0xF6EF, 0x737F, 0xF6F0, 0x74D8, 0xF6F1, 0x74D5, 0xF6F2, 0x74D9, 0xF6F3, 0x74D7, 0xF6F4, 0x766D, 0xF6F5, 0x76AD, 0xF6F6, 0x7935, + 0xF6F7, 0x79B4, 0xF6F8, 0x7A70, 0xF6F9, 0x7A71, 0xF6FA, 0x7C57, 0xF6FB, 0x7C5C, 0xF6FC, 0x7C59, 0xF6FD, 0x7C5B, 0xF6FE, 0x7C5A, + 0xF740, 0x7CF4, 0xF741, 0x7CF1, 0xF742, 0x7E91, 0xF743, 0x7F4F, 0xF744, 0x7F87, 0xF745, 0x81DE, 0xF746, 0x826B, 0xF747, 0x8634, + 0xF748, 0x8635, 0xF749, 0x8633, 0xF74A, 0x862C, 0xF74B, 0x8632, 0xF74C, 0x8636, 0xF74D, 0x882C, 0xF74E, 0x8828, 0xF74F, 0x8826, + 0xF750, 0x882A, 0xF751, 0x8825, 0xF752, 0x8971, 0xF753, 0x89BF, 0xF754, 0x89BE, 0xF755, 0x89FB, 0xF756, 0x8B7E, 0xF757, 0x8B84, + 0xF758, 0x8B82, 0xF759, 0x8B86, 0xF75A, 0x8B85, 0xF75B, 0x8B7F, 0xF75C, 0x8D15, 0xF75D, 0x8E95, 0xF75E, 0x8E94, 0xF75F, 0x8E9A, + 0xF760, 0x8E92, 0xF761, 0x8E90, 0xF762, 0x8E96, 0xF763, 0x8E97, 0xF764, 0x8F60, 0xF765, 0x8F62, 0xF766, 0x9147, 0xF767, 0x944C, + 0xF768, 0x9450, 0xF769, 0x944A, 0xF76A, 0x944B, 0xF76B, 0x944F, 0xF76C, 0x9447, 0xF76D, 0x9445, 0xF76E, 0x9448, 0xF76F, 0x9449, + 0xF770, 0x9446, 0xF771, 0x973F, 0xF772, 0x97E3, 0xF773, 0x986A, 0xF774, 0x9869, 0xF775, 0x98CB, 0xF776, 0x9954, 0xF777, 0x995B, + 0xF778, 0x9A4E, 0xF779, 0x9A53, 0xF77A, 0x9A54, 0xF77B, 0x9A4C, 0xF77C, 0x9A4F, 0xF77D, 0x9A48, 0xF77E, 0x9A4A, 0xF7A1, 0x9A49, + 0xF7A2, 0x9A52, 0xF7A3, 0x9A50, 0xF7A4, 0x9AD0, 0xF7A5, 0x9B19, 0xF7A6, 0x9B2B, 0xF7A7, 0x9B3B, 0xF7A8, 0x9B56, 0xF7A9, 0x9B55, + 0xF7AA, 0x9C46, 0xF7AB, 0x9C48, 0xF7AC, 0x9C3F, 0xF7AD, 0x9C44, 0xF7AE, 0x9C39, 0xF7AF, 0x9C33, 0xF7B0, 0x9C41, 0xF7B1, 0x9C3C, + 0xF7B2, 0x9C37, 0xF7B3, 0x9C34, 0xF7B4, 0x9C32, 0xF7B5, 0x9C3D, 0xF7B6, 0x9C36, 0xF7B7, 0x9DDB, 0xF7B8, 0x9DD2, 0xF7B9, 0x9DDE, + 0xF7BA, 0x9DDA, 0xF7BB, 0x9DCB, 0xF7BC, 0x9DD0, 0xF7BD, 0x9DDC, 0xF7BE, 0x9DD1, 0xF7BF, 0x9DDF, 0xF7C0, 0x9DE9, 0xF7C1, 0x9DD9, + 0xF7C2, 0x9DD8, 0xF7C3, 0x9DD6, 0xF7C4, 0x9DF5, 0xF7C5, 0x9DD5, 0xF7C6, 0x9DDD, 0xF7C7, 0x9EB6, 0xF7C8, 0x9EF0, 0xF7C9, 0x9F35, + 0xF7CA, 0x9F33, 0xF7CB, 0x9F32, 0xF7CC, 0x9F42, 0xF7CD, 0x9F6B, 0xF7CE, 0x9F95, 0xF7CF, 0x9FA2, 0xF7D0, 0x513D, 0xF7D1, 0x5299, + 0xF7D2, 0x58E8, 0xF7D3, 0x58E7, 0xF7D4, 0x5972, 0xF7D5, 0x5B4D, 0xF7D6, 0x5DD8, 0xF7D7, 0x882F, 0xF7D8, 0x5F4F, 0xF7D9, 0x6201, + 0xF7DA, 0x6203, 0xF7DB, 0x6204, 0xF7DC, 0x6529, 0xF7DD, 0x6525, 0xF7DE, 0x6596, 0xF7DF, 0x66EB, 0xF7E0, 0x6B11, 0xF7E1, 0x6B12, + 0xF7E2, 0x6B0F, 0xF7E3, 0x6BCA, 0xF7E4, 0x705B, 0xF7E5, 0x705A, 0xF7E6, 0x7222, 0xF7E7, 0x7382, 0xF7E8, 0x7381, 0xF7E9, 0x7383, + 0xF7EA, 0x7670, 0xF7EB, 0x77D4, 0xF7EC, 0x7C67, 0xF7ED, 0x7C66, 0xF7EE, 0x7E95, 0xF7EF, 0x826C, 0xF7F0, 0x863A, 0xF7F1, 0x8640, + 0xF7F2, 0x8639, 0xF7F3, 0x863C, 0xF7F4, 0x8631, 0xF7F5, 0x863B, 0xF7F6, 0x863E, 0xF7F7, 0x8830, 0xF7F8, 0x8832, 0xF7F9, 0x882E, + 0xF7FA, 0x8833, 0xF7FB, 0x8976, 0xF7FC, 0x8974, 0xF7FD, 0x8973, 0xF7FE, 0x89FE, 0xF840, 0x8B8C, 0xF841, 0x8B8E, 0xF842, 0x8B8B, + 0xF843, 0x8B88, 0xF844, 0x8C45, 0xF845, 0x8D19, 0xF846, 0x8E98, 0xF847, 0x8F64, 0xF848, 0x8F63, 0xF849, 0x91BC, 0xF84A, 0x9462, + 0xF84B, 0x9455, 0xF84C, 0x945D, 0xF84D, 0x9457, 0xF84E, 0x945E, 0xF84F, 0x97C4, 0xF850, 0x97C5, 0xF851, 0x9800, 0xF852, 0x9A56, + 0xF853, 0x9A59, 0xF854, 0x9B1E, 0xF855, 0x9B1F, 0xF856, 0x9B20, 0xF857, 0x9C52, 0xF858, 0x9C58, 0xF859, 0x9C50, 0xF85A, 0x9C4A, + 0xF85B, 0x9C4D, 0xF85C, 0x9C4B, 0xF85D, 0x9C55, 0xF85E, 0x9C59, 0xF85F, 0x9C4C, 0xF860, 0x9C4E, 0xF861, 0x9DFB, 0xF862, 0x9DF7, + 0xF863, 0x9DEF, 0xF864, 0x9DE3, 0xF865, 0x9DEB, 0xF866, 0x9DF8, 0xF867, 0x9DE4, 0xF868, 0x9DF6, 0xF869, 0x9DE1, 0xF86A, 0x9DEE, + 0xF86B, 0x9DE6, 0xF86C, 0x9DF2, 0xF86D, 0x9DF0, 0xF86E, 0x9DE2, 0xF86F, 0x9DEC, 0xF870, 0x9DF4, 0xF871, 0x9DF3, 0xF872, 0x9DE8, + 0xF873, 0x9DED, 0xF874, 0x9EC2, 0xF875, 0x9ED0, 0xF876, 0x9EF2, 0xF877, 0x9EF3, 0xF878, 0x9F06, 0xF879, 0x9F1C, 0xF87A, 0x9F38, + 0xF87B, 0x9F37, 0xF87C, 0x9F36, 0xF87D, 0x9F43, 0xF87E, 0x9F4F, 0xF8A1, 0x9F71, 0xF8A2, 0x9F70, 0xF8A3, 0x9F6E, 0xF8A4, 0x9F6F, + 0xF8A5, 0x56D3, 0xF8A6, 0x56CD, 0xF8A7, 0x5B4E, 0xF8A8, 0x5C6D, 0xF8A9, 0x652D, 0xF8AA, 0x66ED, 0xF8AB, 0x66EE, 0xF8AC, 0x6B13, + 0xF8AD, 0x705F, 0xF8AE, 0x7061, 0xF8AF, 0x705D, 0xF8B0, 0x7060, 0xF8B1, 0x7223, 0xF8B2, 0x74DB, 0xF8B3, 0x74E5, 0xF8B4, 0x77D5, + 0xF8B5, 0x7938, 0xF8B6, 0x79B7, 0xF8B7, 0x79B6, 0xF8B8, 0x7C6A, 0xF8B9, 0x7E97, 0xF8BA, 0x7F89, 0xF8BB, 0x826D, 0xF8BC, 0x8643, + 0xF8BD, 0x8838, 0xF8BE, 0x8837, 0xF8BF, 0x8835, 0xF8C0, 0x884B, 0xF8C1, 0x8B94, 0xF8C2, 0x8B95, 0xF8C3, 0x8E9E, 0xF8C4, 0x8E9F, + 0xF8C5, 0x8EA0, 0xF8C6, 0x8E9D, 0xF8C7, 0x91BE, 0xF8C8, 0x91BD, 0xF8C9, 0x91C2, 0xF8CA, 0x946B, 0xF8CB, 0x9468, 0xF8CC, 0x9469, + 0xF8CD, 0x96E5, 0xF8CE, 0x9746, 0xF8CF, 0x9743, 0xF8D0, 0x9747, 0xF8D1, 0x97C7, 0xF8D2, 0x97E5, 0xF8D3, 0x9A5E, 0xF8D4, 0x9AD5, + 0xF8D5, 0x9B59, 0xF8D6, 0x9C63, 0xF8D7, 0x9C67, 0xF8D8, 0x9C66, 0xF8D9, 0x9C62, 0xF8DA, 0x9C5E, 0xF8DB, 0x9C60, 0xF8DC, 0x9E02, + 0xF8DD, 0x9DFE, 0xF8DE, 0x9E07, 0xF8DF, 0x9E03, 0xF8E0, 0x9E06, 0xF8E1, 0x9E05, 0xF8E2, 0x9E00, 0xF8E3, 0x9E01, 0xF8E4, 0x9E09, + 0xF8E5, 0x9DFF, 0xF8E6, 0x9DFD, 0xF8E7, 0x9E04, 0xF8E8, 0x9EA0, 0xF8E9, 0x9F1E, 0xF8EA, 0x9F46, 0xF8EB, 0x9F74, 0xF8EC, 0x9F75, + 0xF8ED, 0x9F76, 0xF8EE, 0x56D4, 0xF8EF, 0x652E, 0xF8F0, 0x65B8, 0xF8F1, 0x6B18, 0xF8F2, 0x6B19, 0xF8F3, 0x6B17, 0xF8F4, 0x6B1A, + 0xF8F5, 0x7062, 0xF8F6, 0x7226, 0xF8F7, 0x72AA, 0xF8F8, 0x77D8, 0xF8F9, 0x77D9, 0xF8FA, 0x7939, 0xF8FB, 0x7C69, 0xF8FC, 0x7C6B, + 0xF8FD, 0x7CF6, 0xF8FE, 0x7E9A, 0xF940, 0x7E98, 0xF941, 0x7E9B, 0xF942, 0x7E99, 0xF943, 0x81E0, 0xF944, 0x81E1, 0xF945, 0x8646, + 0xF946, 0x8647, 0xF947, 0x8648, 0xF948, 0x8979, 0xF949, 0x897A, 0xF94A, 0x897C, 0xF94B, 0x897B, 0xF94C, 0x89FF, 0xF94D, 0x8B98, + 0xF94E, 0x8B99, 0xF94F, 0x8EA5, 0xF950, 0x8EA4, 0xF951, 0x8EA3, 0xF952, 0x946E, 0xF953, 0x946D, 0xF954, 0x946F, 0xF955, 0x9471, + 0xF956, 0x9473, 0xF957, 0x9749, 0xF958, 0x9872, 0xF959, 0x995F, 0xF95A, 0x9C68, 0xF95B, 0x9C6E, 0xF95C, 0x9C6D, 0xF95D, 0x9E0B, + 0xF95E, 0x9E0D, 0xF95F, 0x9E10, 0xF960, 0x9E0F, 0xF961, 0x9E12, 0xF962, 0x9E11, 0xF963, 0x9EA1, 0xF964, 0x9EF5, 0xF965, 0x9F09, + 0xF966, 0x9F47, 0xF967, 0x9F78, 0xF968, 0x9F7B, 0xF969, 0x9F7A, 0xF96A, 0x9F79, 0xF96B, 0x571E, 0xF96C, 0x7066, 0xF96D, 0x7C6F, + 0xF96E, 0x883C, 0xF96F, 0x8DB2, 0xF970, 0x8EA6, 0xF971, 0x91C3, 0xF972, 0x9474, 0xF973, 0x9478, 0xF974, 0x9476, 0xF975, 0x9475, + 0xF976, 0x9A60, 0xF977, 0x9C74, 0xF978, 0x9C73, 0xF979, 0x9C71, 0xF97A, 0x9C75, 0xF97B, 0x9E14, 0xF97C, 0x9E13, 0xF97D, 0x9EF6, + 0xF97E, 0x9F0A, 0xF9A1, 0x9FA4, 0xF9A2, 0x7068, 0xF9A3, 0x7065, 0xF9A4, 0x7CF7, 0xF9A5, 0x866A, 0xF9A6, 0x883E, 0xF9A7, 0x883D, + 0xF9A8, 0x883F, 0xF9A9, 0x8B9E, 0xF9AA, 0x8C9C, 0xF9AB, 0x8EA9, 0xF9AC, 0x8EC9, 0xF9AD, 0x974B, 0xF9AE, 0x9873, 0xF9AF, 0x9874, + 0xF9B0, 0x98CC, 0xF9B1, 0x9961, 0xF9B2, 0x99AB, 0xF9B3, 0x9A64, 0xF9B4, 0x9A66, 0xF9B5, 0x9A67, 0xF9B6, 0x9B24, 0xF9B7, 0x9E15, + 0xF9B8, 0x9E17, 0xF9B9, 0x9F48, 0xF9BA, 0x6207, 0xF9BB, 0x6B1E, 0xF9BC, 0x7227, 0xF9BD, 0x864C, 0xF9BE, 0x8EA8, 0xF9BF, 0x9482, + 0xF9C0, 0x9480, 0xF9C1, 0x9481, 0xF9C2, 0x9A69, 0xF9C3, 0x9A68, 0xF9C4, 0x9B2E, 0xF9C5, 0x9E19, 0xF9C6, 0x7229, 0xF9C7, 0x864B, + 0xF9C8, 0x8B9F, 0xF9C9, 0x9483, 0xF9CA, 0x9C79, 0xF9CB, 0x9EB7, 0xF9CC, 0x7675, 0xF9CD, 0x9A6B, 0xF9CE, 0x9C7A, 0xF9CF, 0x9E1D, + 0xF9D0, 0x7069, 0xF9D1, 0x706A, 0xF9D2, 0x9EA4, 0xF9D3, 0x9F7E, 0xF9D4, 0x9F49, 0xF9D5, 0x9F98, 0xF9D6, 0x7881, 0xF9D7, 0x92B9, + 0xF9D8, 0x88CF, 0xF9D9, 0x58BB, 0xF9DA, 0x6052, 0xF9DB, 0x7CA7, 0xF9DC, 0x5AFA, 0xF9DD, 0x2554, 0xF9DE, 0x2566, 0xF9DF, 0x2557, + 0xF9E0, 0x2560, 0xF9E1, 0x256C, 0xF9E2, 0x2563, 0xF9E3, 0x255A, 0xF9E4, 0x2569, 0xF9E5, 0x255D, 0xF9E6, 0x2552, 0xF9E7, 0x2564, + 0xF9E8, 0x2555, 0xF9E9, 0x255E, 0xF9EA, 0x256A, 0xF9EB, 0x2561, 0xF9EC, 0x2558, 0xF9ED, 0x2567, 0xF9EE, 0x255B, 0xF9EF, 0x2553, + 0xF9F0, 0x2565, 0xF9F1, 0x2556, 0xF9F2, 0x255F, 0xF9F3, 0x256B, 0xF9F4, 0x2562, 0xF9F5, 0x2559, 0xF9F6, 0x2568, 0xF9F7, 0x255C, + 0xF9F8, 0x2551, 0xF9F9, 0x2550, 0xF9FA, 0x256D, 0xF9FB, 0x256E, 0xF9FC, 0x2570, 0xF9FD, 0x256F, 0xF9FE, 0x2593, 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0 +static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0 +static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ + 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, + 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0 +static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, + 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, + 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, + 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0 +static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0 +static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ + 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, + 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, + 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, + 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0 +static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0 +static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, + 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, + 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0 +static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ + 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, + 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, + 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, + 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, + 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0 +static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0 +static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, + 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0 +static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0 +static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0 +static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, + 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, + 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0 +static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ + 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, + 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, + 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, + 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F, + 0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, + 0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9, + 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1, + 0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000 +}; +#endif +#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0 +static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0 +static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0 +static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ + 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, + 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, + 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3, + 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580, + 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384, + 0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0 +}; +#endif + + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for static code page configuration */ +/* SBCS fixed code page */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900 +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + WCHAR c = 0; + const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ + for (c = 0; c < 0x80 && uni != p[c]; c++) ; + c = (c + 0x80) & 0xFF; + } + } + + return c; +} + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + WCHAR c = 0; + const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + if (oem < 0x100) c = p[oem - 0x80]; + } + } + + return c; +} + +#endif + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for static code page configuration */ +/* DBCS fixed code page */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE >= 900 +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0, uc; + UINT i = 0, n, li, hi; + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ + uc = (WCHAR)uni; + p = CVTBL(uni2oem, FF_CODE_PAGE); + hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (uc == p[i * 2]) break; + if (uc > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + + return c; +} + + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i = 0, n, li, hi; + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + if (cp == FF_CODE_PAGE) { /* Is it valid code page? */ + p = CVTBL(oem2uni, FF_CODE_PAGE); + hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (oem == p[i * 2]) break; + if (oem > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + + return c; +} +#endif + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for dynamic code page configuration */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE == 0 + +static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0}; +static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; + + +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0, uc; + UINT i, n, li, hi; + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000) { /* Is it in BMP? */ + uc = (WCHAR)uni; + p = 0; + if (cp < 900) { /* SBCS */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */ + p = cp_table[i]; + if (p) { /* Is it valid code page ? */ + for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */ + c = (c + 0x80) & 0xFF; + } + } else { /* DBCS */ + switch (cp) { /* Get conversion table */ + case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break; + case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break; + case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break; + case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break; + } + if (p) { /* Is it valid code page? */ + li = 0; + for (n = 16; n; n--) { /* Find OEM code */ + i = li + (hi - li) / 2; + if (uc == p[i * 2]) break; + if (uc > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + } + } + + return c; +} + + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i, n, li, hi; + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + p = 0; + if (cp < 900) { /* SBCS */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ + p = cp_table[i]; + if (p) { /* Is it a valid CP ? */ + if (oem < 0x100) c = p[oem - 0x80]; + } + } else { /* DBCS */ + switch (cp) { + case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break; + case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break; + case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break; + case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break; + } + if (p) { + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (oem == p[i * 2]) break; + if (oem > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + } + + return c; +} +#endif + + + +/*------------------------------------------------------------------------*/ +/* Unicode up-case conversion */ +/*------------------------------------------------------------------------*/ + +DWORD ff_wtoupper ( /* Returns up-converted code point */ + DWORD uni /* Unicode code point to be up-converted */ +) +{ + const WORD *p; + WORD uc, bc, nc, cmd; + static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ + /* Basic Latin */ + 0x0061,0x031A, + /* Latin-1 Supplement */ + 0x00E0,0x0317, + 0x00F8,0x0307, + 0x00FF,0x0001,0x0178, + /* Latin Extended-A */ + 0x0100,0x0130, + 0x0132,0x0106, + 0x0139,0x0110, + 0x014A,0x012E, + 0x0179,0x0106, + /* Latin Extended-B */ + 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA, + 0x01CD,0x0110, + 0x01DD,0x0001,0x018E, + 0x01DE,0x0112, + 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, + 0x01F8,0x0128, + 0x0222,0x0112, + 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, + 0x0246,0x010A, + /* IPA Extensions */ + 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7, + /* Greek, Coptic */ + 0x037B,0x0003,0x03FD,0x03FE,0x03FF, + 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, + 0x03B1,0x0311, + 0x03C2,0x0002,0x03A3,0x03A3, + 0x03C4,0x0308, + 0x03CC,0x0003,0x038C,0x038E,0x038F, + 0x03D8,0x0118, + 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, + /* Cyrillic */ + 0x0430,0x0320, + 0x0450,0x0710, + 0x0460,0x0122, + 0x048A,0x0136, + 0x04C1,0x010E, + 0x04CF,0x0001,0x04C0, + 0x04D0,0x0144, + /* Armenian */ + 0x0561,0x0426, + + 0x0000 /* EOT */ + }; + static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */ + /* Phonetic Extensions */ + 0x1D7D,0x0001,0x2C63, + /* Latin Extended Additional */ + 0x1E00,0x0196, + 0x1EA0,0x015A, + /* Greek Extended */ + 0x1F00,0x0608, + 0x1F10,0x0606, + 0x1F20,0x0608, + 0x1F30,0x0608, + 0x1F40,0x0606, + 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, + 0x1F60,0x0608, + 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, + 0x1F80,0x0608, + 0x1F90,0x0608, + 0x1FA0,0x0608, + 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, + 0x1FCC,0x0001,0x1FC3, + 0x1FD0,0x0602, + 0x1FE0,0x0602, + 0x1FE5,0x0001,0x1FEC, + 0x1FF3,0x0001,0x1FFC, + /* Letterlike Symbols */ + 0x214E,0x0001,0x2132, + /* Number forms */ + 0x2170,0x0210, + 0x2184,0x0001,0x2183, + /* Enclosed Alphanumerics */ + 0x24D0,0x051A, + 0x2C30,0x042F, + /* Latin Extended-C */ + 0x2C60,0x0102, + 0x2C67,0x0106, 0x2C75,0x0102, + /* Coptic */ + 0x2C80,0x0164, + /* Georgian Supplement */ + 0x2D00,0x0826, + /* Full-width */ + 0xFF41,0x031A, + + 0x0000 /* EOT */ + }; + + + if (uni < 0x10000) { /* Is it in BMP? */ + uc = (WORD)uni; + p = uc < 0x1000 ? cvt1 : cvt2; + for (;;) { + bc = *p++; /* Get the block base */ + if (bc == 0 || uc < bc) break; /* Not matched? */ + nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ + if (uc < bc + nc) { /* In the block? */ + switch (cmd) { + case 0: uc = p[uc - bc]; break; /* Table conversion */ + case 1: uc -= (uc - bc) & 1; break; /* Case pairs */ + case 2: uc -= 16; break; /* Shift -16 */ + case 3: uc -= 32; break; /* Shift -32 */ + case 4: uc -= 48; break; /* Shift -48 */ + case 5: uc -= 26; break; /* Shift -26 */ + case 6: uc += 8; break; /* Shift +8 */ + case 7: uc -= 80; break; /* Shift -80 */ + case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */ + } + break; + } + if (cmd == 0) p += nc; /* Skip table if needed */ + } + uni = uc; + } + + return uni; +} + + +#endif /* #if FF_USE_LFN */ diff --git a/sept/sept-secondary/src/lib/fatfs/integer.h b/sept/sept-secondary/src/lib/fatfs/integer.h new file mode 100644 index 000000000..b3c70cab0 --- /dev/null +++ b/sept/sept-secondary/src/lib/fatfs/integer.h @@ -0,0 +1,36 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ + +#ifndef FF_INTEGER +#define FF_INTEGER + +#ifdef _WIN32 /* FatFs development platform */ + +#include <windows.h> +typedef unsigned __int64 QWORD; + +#else /* Embedded platform */ + +/* These types MUST be 16-bit or 32-bit */ +typedef int INT; +typedef unsigned int UINT; + +/* This type MUST be 8-bit */ +typedef unsigned char BYTE; + +/* These types MUST be 16-bit */ +typedef short SHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types MUST be 32-bit */ +typedef long LONG; +typedef unsigned long DWORD; + +/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */ +typedef unsigned long long QWORD; + +#endif + +#endif diff --git a/sept/sept-secondary/src/lib/ini.c b/sept/sept-secondary/src/lib/ini.c new file mode 100644 index 000000000..63626c72d --- /dev/null +++ b/sept/sept-secondary/src/lib/ini.c @@ -0,0 +1,269 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#include "ini.h" + +#if !INI_USE_STACK +#include <stdlib.h> +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to null at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + strncpy(dest, src, size - 1); + dest[size - 1] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; +#else + char* line; + int max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC + char* new_line; + int offset; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = realloc(line, max_line); + if (!new_line) { + free(line); + return -2; + } + line = new_line; + if (reader(line + offset, max_line - offset, stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; +#endif + value = lskip(value); + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ + error = lineno; + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/sept/sept-secondary/src/lib/ini.h b/sept/sept-secondary/src/lib/ini.h new file mode 100644 index 000000000..f45ba40ba --- /dev/null +++ b/sept/sept-secondary/src/lib/ini.h @@ -0,0 +1,130 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef __INI_H__ +#define __INI_H__ + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See http://code.google.com/p/inih/issues/detail?id=21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INI_H__ */ diff --git a/sept/sept-secondary/src/lib/log.c b/sept/sept-secondary/src/lib/log.c new file mode 100644 index 000000000..37006b166 --- /dev/null +++ b/sept/sept-secondary/src/lib/log.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "log.h" + +#include "../display/video_fb.h" +#include "vsprintf.h" + +/* default log level for screen output */ +ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_NONE; + +void log_set_log_level(ScreenLogLevel log_level) { + g_screen_log_level = log_level; +} + +ScreenLogLevel log_get_log_level() { + return g_screen_log_level; +} + +void log_to_uart(const char *message) { + /* TODO: add UART logging */ +} + +static void print_to_screen(ScreenLogLevel screen_log_level, char *message) { + /* don't print to screen if below log level */ + if(screen_log_level > g_screen_log_level) return; + + video_puts(message); +} + +/** + * vprintk - logs a message and prints it to screen based on its screen_log_level + * + * If the level is below g_screen_log_level it will not be shown but logged to UART + * This text will not be colored or prefixed + * UART is TODO + */ +void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args) +{ + char buf[PRINT_MESSAGE_MAX_LENGTH]; + vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args); + + /* we don't need that flag here, but if it gets used, strip it so we print correctly */ + screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX; + + /* log to UART */ + log_to_uart(buf); + + print_to_screen(screen_log_level, buf); +} + +static void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) { + char typebuf[] = "[%s] %s"; + + /* apply prefix and append message format */ + /* TODO: add coloring to the output */ + switch(screen_log_level) + { + case SCREEN_LOG_LEVEL_ERROR: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt); + break; + case SCREEN_LOG_LEVEL_WARNING: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt); + break; + case SCREEN_LOG_LEVEL_MANDATORY: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt); + break; + case SCREEN_LOG_LEVEL_INFO: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt); + break; + case SCREEN_LOG_LEVEL_DEBUG: + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt); + break; + default: + break; + } +} + +/** + * print - logs a message and prints it to screen based on its screen_log_level + * + * If the level is below g_screen_log_level it will not be shown but logged to UART + * Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added + * UART is TODO + */ +void print(ScreenLogLevel screen_log_level, const char * fmt, ...) +{ + char buf[PRINT_MESSAGE_MAX_LENGTH] = {}; + char message[PRINT_MESSAGE_MAX_LENGTH] = {}; + + /* TODO: make splash disappear if level > MANDATORY */ + + /* make prefix free messages with log_level possible */ + if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) { + /* remove the NO_PREFIX flag so the enum can be recognized later on */ + screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX; + + snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt); + } + else { + add_prefix(screen_log_level, fmt, buf); + } + + /* input arguments */ + va_list args; + va_start(args, fmt); + vsnprintf(message, PRINT_MESSAGE_MAX_LENGTH, buf, args); + va_end(args); + + /* log to UART */ + log_to_uart(message); + + print_to_screen(screen_log_level, message); +} \ No newline at end of file diff --git a/sept/sept-secondary/src/lib/log.h b/sept/sept-secondary/src/lib/log.h new file mode 100644 index 000000000..32703a318 --- /dev/null +++ b/sept/sept-secondary/src/lib/log.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_LOG_H +#define FUSEE_LOG_H + +#define PRINT_MESSAGE_MAX_LENGTH 512 + +#include <stdarg.h> + +typedef enum { + SCREEN_LOG_LEVEL_NONE = 0, + SCREEN_LOG_LEVEL_ERROR = 1, + SCREEN_LOG_LEVEL_WARNING = 2, + SCREEN_LOG_LEVEL_MANDATORY = 3, /* no log prefix */ + SCREEN_LOG_LEVEL_INFO = 4, + SCREEN_LOG_LEVEL_DEBUG = 5, + + SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */ +} ScreenLogLevel; + +extern ScreenLogLevel g_screen_log_level; + +void log_set_log_level(ScreenLogLevel screen_log_level); +ScreenLogLevel log_get_log_level(); +void log_to_uart(const char *message); +void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args); +void print(ScreenLogLevel screen_log_level, const char* fmt, ...); + +#endif \ No newline at end of file diff --git a/sept/sept-secondary/src/lib/lz.c b/sept/sept-secondary/src/lib/lz.c new file mode 100644 index 000000000..e62e02d15 --- /dev/null +++ b/sept/sept-secondary/src/lib/lz.c @@ -0,0 +1,377 @@ +/************************************************************************* +* Name: lz.c +* Author: Marcus Geelnard +* Description: LZ77 coder/decoder implementation. +* Reentrant: Yes +* +* The LZ77 compression scheme is a substitutional compression scheme +* proposed by Abraham Lempel and Jakob Ziv in 1977. It is very simple in +* its design, and uses no fancy bit level compression. +* +* This is my first attempt at an implementation of a LZ77 code/decoder. +* +* The principle of the LZ77 compression algorithm is to store repeated +* occurrences of strings as references to previous occurrences of the same +* string. The point is that the reference consumes less space than the +* string itself, provided that the string is long enough (in this +* implementation, the string has to be at least 4 bytes long, since the +* minimum coded reference is 3 bytes long). Also note that the term +* "string" refers to any kind of byte sequence (it does not have to be +* an ASCII string, for instance). +* +* The coder uses a brute force approach to finding string matches in the +* history buffer (or "sliding window", if you wish), which is very, very +* slow. I recon the complexity is somewhere between O(n^2) and O(n^3), +* depending on the input data. +* +* There is also a faster implementation that uses a large working buffer +* in which a "jump table" is stored, which is used to quickly find +* possible string matches (see the source code for LZ_CompressFast() for +* more information). The faster method is an order of magnitude faster, +* but still quite slow compared to other compression methods. +* +* The upside is that decompression is very fast, and the compression ratio +* is often very good. +* +* The reference to a string is coded as a (length,offset) pair, where the +* length indicates the length of the string, and the offset gives the +* offset from the current data position. To distinguish between string +* references and literal strings (uncompressed bytes), a string reference +* is preceded by a marker byte, which is chosen as the least common byte +* symbol in the input data stream (this marker byte is stored in the +* output stream as the first byte). +* +* Occurrences of the marker byte in the stream are encoded as the marker +* byte followed by a zero byte, which means that occurrences of the marker +* byte have to be coded with two bytes. +* +* The lengths and offsets are coded in a variable length fashion, allowing +* values of any magnitude (up to 4294967295 in this implementation). +* +* With this compression scheme, the worst case compression result is +* (257/256)*insize + 1. +* +*------------------------------------------------------------------------- +* Copyright (c) 2003-2006 Marcus Geelnard +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would +* be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not +* be misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source +* distribution. +* +* Marcus Geelnard +* marcus.geelnard at home.se +*************************************************************************/ + + +/************************************************************************* +* Constants used for LZ77 coding +*************************************************************************/ + +/* Maximum offset (can be any size < 2^31). Lower values give faster + compression, while higher values gives better compression. The default + value of 100000 is quite high. Experiment to see what works best for + you. */ +#define LZ_MAX_OFFSET 100000 + + + +/************************************************************************* +* INTERNAL FUNCTIONS * +*************************************************************************/ + + +/************************************************************************* +* _LZ_StringCompare() - Return maximum length string match. +*************************************************************************/ + +static unsigned int _LZ_StringCompare( const unsigned char * str1, + const unsigned char * str2, unsigned int minlen, unsigned int maxlen ) +{ + unsigned int len; + + for( len = minlen; (len < maxlen) && (str1[len] == str2[len]); ++ len ); + + return len; +} + + +/************************************************************************* +* _LZ_WriteVarSize() - Write unsigned integer with variable number of +* bytes depending on value. +*************************************************************************/ + +static int _LZ_WriteVarSize( unsigned int x, unsigned char * buf ) +{ + unsigned int y; + int num_bytes, i, b; + + /* Determine number of bytes needed to store the number x */ + y = x >> 3; + for( num_bytes = 5; num_bytes >= 2; -- num_bytes ) + { + if( y & 0xfe000000 ) break; + y <<= 7; + } + + /* Write all bytes, seven bits in each, with 8:th bit set for all */ + /* but the last byte. */ + for( i = num_bytes-1; i >= 0; -- i ) + { + b = (x >> (i*7)) & 0x0000007f; + if( i > 0 ) + { + b |= 0x00000080; + } + *buf ++ = (unsigned char) b; + } + + /* Return number of bytes written */ + return num_bytes; +} + + +/************************************************************************* +* _LZ_ReadVarSize() - Read unsigned integer with variable number of +* bytes depending on value. +*************************************************************************/ + +static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf ) +{ + unsigned int y, b, num_bytes; + + /* Read complete value (stop when byte contains zero in 8:th bit) */ + y = 0; + num_bytes = 0; + do + { + b = (unsigned int) (*buf ++); + y = (y << 7) | (b & 0x0000007f); + ++ num_bytes; + } + while( b & 0x00000080 ); + + /* Store value in x */ + *x = y; + + /* Return number of bytes read */ + return num_bytes; +} + + + +/************************************************************************* +* PUBLIC FUNCTIONS * +*************************************************************************/ + + +/************************************************************************* +* LZ_Compress() - Compress a block of data using an LZ77 coder. +* in - Input (uncompressed) buffer. +* out - Output (compressed) buffer. This buffer must be 0.4% larger +* than the input buffer, plus one byte. +* insize - Number of input bytes. +* The function returns the size of the compressed data. +*************************************************************************/ + +int LZ_Compress( const unsigned char *in, unsigned char *out, unsigned int insize ) +{ + unsigned char marker, symbol; + unsigned int inpos, outpos, bytesleft, i; + unsigned int maxoffset, offset, bestoffset; + unsigned int maxlength, length, bestlength; + unsigned int histogram[ 256 ]; + const unsigned char *ptr1, *ptr2; + + /* Do we have anything to compress? */ + if( insize < 1 ) + { + return 0; + } + + /* Create histogram */ + for( i = 0; i < 256; ++ i ) + { + histogram[ i ] = 0; + } + for( i = 0; i < insize; ++ i ) + { + ++ histogram[ in[ i ] ]; + } + + /* Find the least common byte, and use it as the marker symbol */ + marker = 0; + for( i = 1; i < 256; ++ i ) + { + if( histogram[ i ] < histogram[ marker ] ) + { + marker = (unsigned char) i; + } + } + + /* Remember the marker symbol for the decoder */ + out[ 0 ] = marker; + + /* Start of compression */ + inpos = 0; + outpos = 1; + + /* Main compression loop */ + bytesleft = insize; + do + { + /* Determine most distant position */ + if( inpos > LZ_MAX_OFFSET ) maxoffset = LZ_MAX_OFFSET; + else maxoffset = inpos; + + /* Get pointer to current position */ + ptr1 = &in[ inpos ]; + + /* Search history window for maximum length string match */ + bestlength = 3; + bestoffset = 0; + for( offset = 3; offset <= maxoffset; ++ offset ) + { + /* Get pointer to candidate string */ + ptr2 = &ptr1[ -(int)offset ]; + + /* Quickly determine if this is a candidate (for speed) */ + if( (ptr1[ 0 ] == ptr2[ 0 ]) && + (ptr1[ bestlength ] == ptr2[ bestlength ]) ) + { + /* Determine maximum length for this offset */ + maxlength = (bytesleft < offset ? bytesleft : offset); + + /* Count maximum length match at this offset */ + length = _LZ_StringCompare( ptr1, ptr2, 0, maxlength ); + + /* Better match than any previous match? */ + if( length > bestlength ) + { + bestlength = length; + bestoffset = offset; + } + } + } + + /* Was there a good enough match? */ + if( (bestlength >= 8) || + ((bestlength == 4) && (bestoffset <= 0x0000007f)) || + ((bestlength == 5) && (bestoffset <= 0x00003fff)) || + ((bestlength == 6) && (bestoffset <= 0x001fffff)) || + ((bestlength == 7) && (bestoffset <= 0x0fffffff)) ) + { + out[ outpos ++ ] = (unsigned char) marker; + outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] ); + outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] ); + inpos += bestlength; + bytesleft -= bestlength; + } + else + { + /* Output single byte (or two bytes if marker byte) */ + symbol = in[ inpos ++ ]; + out[ outpos ++ ] = symbol; + if( symbol == marker ) + { + out[ outpos ++ ] = 0; + } + -- bytesleft; + } + } + while( bytesleft > 3 ); + + /* Dump remaining bytes, if any */ + while( inpos < insize ) + { + if( in[ inpos ] == marker ) + { + out[ outpos ++ ] = marker; + out[ outpos ++ ] = 0; + } + else + { + out[ outpos ++ ] = in[ inpos ]; + } + ++ inpos; + } + + return outpos; +} + + +/************************************************************************* +* LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder. +* in - Input (compressed) buffer. +* out - Output (uncompressed) buffer. This buffer must be large +* enough to hold the uncompressed data. +* insize - Number of input bytes. +*************************************************************************/ + +int LZ_Uncompress( const unsigned char *in, unsigned char *out, unsigned int insize ) +{ + unsigned char marker, symbol; + unsigned int i, inpos, outpos, length, offset; + + /* Do we have anything to uncompress? */ + if( insize < 1 ) + { + return 0; + } + + /* Get marker symbol from input stream */ + marker = in[ 0 ]; + inpos = 1; + + /* Main decompression loop */ + outpos = 0; + do + { + symbol = in[ inpos ++ ]; + if( symbol == marker ) + { + /* We had a marker byte */ + if( in[ inpos ] == 0 ) + { + /* It was a single occurrence of the marker byte */ + out[ outpos ++ ] = marker; + ++ inpos; + } + else + { + /* Extract true length and offset */ + inpos += _LZ_ReadVarSize( &length, &in[ inpos ] ); + inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] ); + + /* Copy corresponding data from history window */ + for( i = 0; i < length; ++ i ) + { + out[ outpos ] = out[ outpos - offset ]; + ++ outpos; + } + } + } + else + { + /* No marker, plain copy */ + out[ outpos ++ ] = symbol; + } + } + while( inpos < insize ); + + return outpos; +} diff --git a/sept/sept-secondary/src/lib/lz.h b/sept/sept-secondary/src/lib/lz.h new file mode 100644 index 000000000..bc40b6c63 --- /dev/null +++ b/sept/sept-secondary/src/lib/lz.h @@ -0,0 +1,51 @@ +/************************************************************************* +* Name: lz.h +* Author: Marcus Geelnard +* Description: LZ77 coder/decoder interface. +* Reentrant: Yes +*------------------------------------------------------------------------- +* Copyright (c) 2003-2006 Marcus Geelnard +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would +* be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not +* be misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source +* distribution. +* +* Marcus Geelnard +* marcus.geelnard at home.se +*************************************************************************/ + +#ifndef _lz_h_ +#define _lz_h_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************* +* Function prototypes +*************************************************************************/ + +int LZ_Compress(const unsigned char *in, unsigned char *out, unsigned int insize); +int LZ_Uncompress(const unsigned char *in, unsigned char *out, unsigned int insize); + +#ifdef __cplusplus +} +#endif + +#endif /* _lz_h_ */ diff --git a/sept/sept-secondary/src/lib/vsprintf.c b/sept/sept-secondary/src/lib/vsprintf.c new file mode 100644 index 000000000..d934144c9 --- /dev/null +++ b/sept/sept-secondary/src/lib/vsprintf.c @@ -0,0 +1,1676 @@ +/* + * Copyright (C) 2011 Andrei Warkentin <andrey.warkentin@gmail.com> + * + * This program is free software ; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com> + * - changed to provide snprintf and vsnprintf functions + * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de> + * - scnprintf and vscnprintf + */ + +#include <string.h> +#include <ctype.h> +#include <inttypes.h> +#include <stdarg.h> +#include <stdbool.h> + +#include "vsprintf.h" + +#define USHRT_MAX ((uint16_t)(~0U)) +#define SHRT_MAX ((int16_t)(USHRT_MAX>>1)) +#define SHRT_MIN ((int16_t)(-SHRT_MAX - 1)) +#define INT_MAX ((int)(~0U>>1)) +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX (~0U) +#define LONG_MAX ((long)(~0UL>>1)) +#define LONG_MIN (-LONG_MAX - 1) +#define ULONG_MAX (~0UL) + +typedef _Bool bool_t; + +#define do_div(n,base) ({\ + uint32_t __base = (base);\ + uint32_t __rem;\ + __rem = ((uint64_t)(n)) % __base;\ + (n) = ((uint64_t)(n)) / __base;\ + __rem;\ + }) + +const char hex_asc[] = "0123456789abcdef"; +#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] +#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] + +static inline char *pack_hex_byte(char *buf, uint8_t byte) +{ + *buf++ = hex_asc_hi(byte); + *buf++ = hex_asc_lo(byte); + return buf; +} + +/** + * skip_spaces - Removes leading whitespace from @str. + * @str: The string to be stripped. + * + * Returns a pointer to the first non-whitespace character in @str. + */ +static char *skip_spaces(const char *str) +{ + while (isspace(*str)) + ++str; + return (char *)str; +} + + +/* Works only for digits and letters, but small and fast */ +#define TOLOWER(x) ((x) | 0x20) + +static unsigned int simple_guess_base(const char *cp) +{ + if (cp[0] == '0') { + if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2])) + return 16; + else + return 8; + } else { + return 10; + } +} + +/** + * simple_strtoull - convert a string to an unsigned long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) +{ + unsigned long long result = 0; + + if (!base) + base = simple_guess_base(cp); + + if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x') + cp += 2; + + while (isxdigit(*cp)) { + unsigned int value; + + value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10; + if (value >= base) + break; + result = result * base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + + return result; +} + +/** + * simple_strtoul - convert a string to an unsigned long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) +{ + return simple_strtoull(cp, endp, base); +} + +/** + * simple_strtol - convert a string to a signed long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +long simple_strtol(const char *cp, char **endp, unsigned int base) +{ + if (*cp == '-') + return -simple_strtoul(cp + 1, endp, base); + + return simple_strtoul(cp, endp, base); +} + +/** + * simple_strtoll - convert a string to a signed long long + * @cp: The start of the string + * @endp: A pointer to the end of the parsed string will be placed here + * @base: The number base to use + */ +long long simple_strtoll(const char *cp, char **endp, unsigned int base) +{ + if (*cp == '-') + return -simple_strtoull(cp + 1, endp, base); + + return simple_strtoull(cp, endp, base); +} + +static +int skip_atoi(const char **s) +{ + int i = 0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + + return i; +} + +/* Decimal conversion is by far the most typical, and is used + * for /proc and /sys data. This directly impacts e.g. top performance + * with many processes running. We optimize it for speed + * using code from + * http://www.cs.uiowa.edu/~jones/bcd/decimal.html + * (with permission from the author, Douglas W. Jones). */ + +/* Formats correctly any integer in [0,99999]. + * Outputs from one to five digits depending on input. + * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ +static +char *put_dec_trunc(char *buf, unsigned q) +{ + unsigned d3, d2, d1, d0; + d1 = (q>>4) & 0xf; + d2 = (q>>8) & 0xf; + d3 = (q>>12); + + d0 = 6*(d3 + d2 + d1) + (q & 0xf); + q = (d0 * 0xcd) >> 11; + d0 = d0 - 10*q; + *buf++ = d0 + '0'; /* least significant digit */ + d1 = q + 9*d3 + 5*d2 + d1; + if (d1 != 0) { + q = (d1 * 0xcd) >> 11; + d1 = d1 - 10*q; + *buf++ = d1 + '0'; /* next digit */ + + d2 = q + 2*d2; + if ((d2 != 0) || (d3 != 0)) { + q = (d2 * 0xd) >> 7; + d2 = d2 - 10*q; + *buf++ = d2 + '0'; /* next digit */ + + d3 = q + 4*d3; + if (d3 != 0) { + q = (d3 * 0xcd) >> 11; + d3 = d3 - 10*q; + *buf++ = d3 + '0'; /* next digit */ + if (q != 0) + *buf++ = q + '0'; /* most sign. digit */ + } + } + } + + return buf; +} +/* Same with if's removed. Always emits five digits */ +static +char *put_dec_full(char *buf, unsigned q) +{ + /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ + /* but anyway, gcc produces better code with full-sized ints */ + unsigned d3, d2, d1, d0; + d1 = (q>>4) & 0xf; + d2 = (q>>8) & 0xf; + d3 = (q>>12); + + /* + * Possible ways to approx. divide by 10 + * gcc -O2 replaces multiply with shifts and adds + * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386) + * (x * 0x67) >> 10: 1100111 + * (x * 0x34) >> 9: 110100 - same + * (x * 0x1a) >> 8: 11010 - same + * (x * 0x0d) >> 7: 1101 - same, shortest code (on i386) + */ + d0 = 6*(d3 + d2 + d1) + (q & 0xf); + q = (d0 * 0xcd) >> 11; + d0 = d0 - 10*q; + *buf++ = d0 + '0'; + d1 = q + 9*d3 + 5*d2 + d1; + q = (d1 * 0xcd) >> 11; + d1 = d1 - 10*q; + *buf++ = d1 + '0'; + + d2 = q + 2*d2; + q = (d2 * 0xd) >> 7; + d2 = d2 - 10*q; + *buf++ = d2 + '0'; + + d3 = q + 4*d3; + q = (d3 * 0xcd) >> 11; /* - shorter code */ + /* q = (d3 * 0x67) >> 10; - would also work */ + d3 = d3 - 10*q; + *buf++ = d3 + '0'; + *buf++ = q + '0'; + + return buf; +} +/* No inlining helps gcc to use registers better */ +static +char *put_dec(char *buf, unsigned long long num) +{ + while (1) { + unsigned rem; + if (num < 100000) + return put_dec_trunc(buf, num); + rem = do_div(num, 100000); + buf = put_dec_full(buf, rem); + } +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */ +#define SPECIAL 64 /* prefix hex with "0x", octal with "0" */ + +enum format_type { + FORMAT_TYPE_NONE, /* Just a string part */ + FORMAT_TYPE_WIDTH, + FORMAT_TYPE_PRECISION, + FORMAT_TYPE_CHAR, + FORMAT_TYPE_STR, + FORMAT_TYPE_PTR, + FORMAT_TYPE_PERCENT_CHAR, + FORMAT_TYPE_INVALID, + FORMAT_TYPE_LONG_LONG, + FORMAT_TYPE_ULONG, + FORMAT_TYPE_LONG, + FORMAT_TYPE_UBYTE, + FORMAT_TYPE_BYTE, + FORMAT_TYPE_USHORT, + FORMAT_TYPE_SHORT, + FORMAT_TYPE_UINT, + FORMAT_TYPE_INT, + FORMAT_TYPE_NRCHARS, + FORMAT_TYPE_SIZE_T, + FORMAT_TYPE_PTRDIFF +}; + +struct printf_spec { + uint8_t type; /* format_type enum */ + uint8_t flags; /* flags to number() */ + uint8_t base; /* number base, 8, 10 or 16 only */ + uint8_t qualifier; /* number qualifier, one of 'hHlLtzZ' */ + int16_t field_width; /* width of output field */ + int16_t precision; /* # of digits/chars */ +}; + +static +char *number(char *buf, char *end, unsigned long long num, + struct printf_spec spec) +{ + /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ + static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ + + char tmp[66]; + char sign; + char locase; + int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10); + int i; + + /* locase = 0 or 0x20. ORing digits or letters with 'locase' + * produces same digits or (maybe lowercased) letters */ + locase = (spec.flags & SMALL); + if (spec.flags & LEFT) + spec.flags &= ~ZEROPAD; + sign = 0; + if (spec.flags & SIGN) { + if ((signed long long)num < 0) { + sign = '-'; + num = -(signed long long)num; + spec.field_width--; + } else if (spec.flags & PLUS) { + sign = '+'; + spec.field_width--; + } else if (spec.flags & SPACE) { + sign = ' '; + spec.field_width--; + } + } + if (need_pfx) { + spec.field_width--; + if (spec.base == 16) + spec.field_width--; + } + + /* generate full string in tmp[], in reverse order */ + i = 0; + if (num == 0) + tmp[i++] = '0'; + /* Generic code, for any base: + else do { + tmp[i++] = (digits[do_div(num,base)] | locase); + } while (num != 0); + */ + else if (spec.base != 10) { /* 8 or 16 */ + int mask = spec.base - 1; + int shift = 3; + + if (spec.base == 16) + shift = 4; + do { + tmp[i++] = (digits[((unsigned char)num) & mask] | locase); + num >>= shift; + } while (num); + } else { /* base 10 */ + i = put_dec(tmp, num) - tmp; + } + + /* printing 100 using %2d gives "100", not "00" */ + if (i > spec.precision) + spec.precision = i; + /* leading space padding */ + spec.field_width -= spec.precision; + if (!(spec.flags & (ZEROPAD+LEFT))) { + while (--spec.field_width >= 0) { + if (buf < end) + *buf = ' '; + ++buf; + } + } + /* sign */ + if (sign) { + if (buf < end) + *buf = sign; + ++buf; + } + /* "0x" / "0" prefix */ + if (need_pfx) { + if (buf < end) + *buf = '0'; + ++buf; + if (spec.base == 16) { + if (buf < end) + *buf = ('X' | locase); + ++buf; + } + } + /* zero or space padding */ + if (!(spec.flags & LEFT)) { + char c = (spec.flags & ZEROPAD) ? '0' : ' '; + while (--spec.field_width >= 0) { + if (buf < end) + *buf = c; + ++buf; + } + } + /* hmm even more zero padding? */ + while (i <= --spec.precision) { + if (buf < end) + *buf = '0'; + ++buf; + } + /* actual digits of result */ + while (--i >= 0) { + if (buf < end) + *buf = tmp[i]; + ++buf; + } + /* trailing space padding */ + while (--spec.field_width >= 0) { + if (buf < end) + *buf = ' '; + ++buf; + } + + return buf; +} + +static +char *string(char *buf, char *end, const char *s, struct printf_spec spec) +{ + int len, i; + + if ((unsigned long)s == 0) + s = "(null)"; + + len = strnlen(s, spec.precision); + + if (!(spec.flags & LEFT)) { + while (len < spec.field_width--) { + if (buf < end) + *buf = ' '; + ++buf; + } + } + for (i = 0; i < len; ++i) { + if (buf < end) + *buf = *s; + ++buf; ++s; + } + while (len < spec.field_width--) { + if (buf < end) + *buf = ' '; + ++buf; + } + + return buf; +} + +static +char *uuid_string(char *buf, char *end, const uint8_t *addr, + struct printf_spec spec, const char *fmt) +{ + char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; + char *p = uuid; + int i; + static const uint8_t be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + static const uint8_t le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15}; + const uint8_t *index = be; + bool_t uc = false; + + switch (*(++fmt)) { + case 'L': + uc = true; /* fall-through */ + case 'l': + index = le; + break; + case 'B': + uc = true; + break; + } + + for (i = 0; i < 16; i++) { + p = pack_hex_byte(p, addr[index[i]]); + switch (i) { + case 3: + case 5: + case 7: + case 9: + *p++ = '-'; + break; + } + } + + *p = 0; + + if (uc) { + p = uuid; + do { + *p = toupper(*p); + } while (*(++p)); + } + + return string(buf, end, uuid, spec); +} + +int kptr_restrict = 1; + +/* + * Show a '%p' thing. A kernel extension is that the '%p' is followed + * by an extra set of alphanumeric characters that are extended format + * specifiers. + * + * Right now we handle: + * + * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form + * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + * Options for %pU are: + * b big endian lower case hex (default) + * B big endian UPPER case hex + * l little endian lower case hex + * L little endian UPPER case hex + * big endian output byte order is: + * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15] + * little endian output byte order is: + * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15] + * - 'V' For a struct va_format which contains a format string * and va_list *, + * call vsnprintf(->format, *->va_list). + * Implements a "recursive vsnprintf". + * Do not use this feature without some mechanism to verify the + * correctness of the format string and va_list arguments. + * + */ +static +char *pointer(const char *fmt, char *buf, char *end, void *ptr, + struct printf_spec spec) +{ + if (!ptr) { + /* + * Print (null) with the same width as a pointer so it makes + * tabular output look nice. + */ + if (spec.field_width == -1) + spec.field_width = 2 * sizeof(void *); + return string(buf, end, "(null)", spec); + } + + switch (*fmt) { + case 'U': + return uuid_string(buf, end, ptr, spec, fmt); + case 'V': + return buf + vsnprintf(buf, end - buf, + ((struct va_format *)ptr)->fmt, + *(((struct va_format *)ptr)->va)); + } + spec.flags |= SMALL; + if (spec.field_width == -1) { + spec.field_width = 2 * sizeof(void *); + spec.flags |= ZEROPAD; + } + spec.base = 16; + + return number(buf, end, (unsigned long) ptr, spec); +} + +/* + * Helper function to decode printf style format. + * Each call decode a token from the format and return the + * number of characters read (or likely the delta where it wants + * to go on the next call). + * The decoded token is returned through the parameters + * + * 'h', 'l', or 'L' for integer fields + * 'z' support added 23/7/1999 S.H. + * 'z' changed to 'Z' --davidm 1/25/99 + * 't' added for ptrdiff_t + * + * @fmt: the format string + * @type of the token returned + * @flags: various flags such as +, -, # tokens.. + * @field_width: overwritten width + * @base: base of the number (octal, hex, ...) + * @precision: precision of a number + * @qualifier: qualifier of a number (long, size_t, ...) + */ +static +int format_decode(const char *fmt, struct printf_spec *spec) +{ + const char *start = fmt; + + /* we finished early by reading the field width */ + if (spec->type == FORMAT_TYPE_WIDTH) { + if (spec->field_width < 0) { + spec->field_width = -spec->field_width; + spec->flags |= LEFT; + } + spec->type = FORMAT_TYPE_NONE; + goto precision; + } + + /* we finished early by reading the precision */ + if (spec->type == FORMAT_TYPE_PRECISION) { + if (spec->precision < 0) + spec->precision = 0; + + spec->type = FORMAT_TYPE_NONE; + goto qualifier; + } + + /* By default */ + spec->type = FORMAT_TYPE_NONE; + + for (; *fmt ; ++fmt) { + if (*fmt == '%') + break; + } + + /* Return the current non-format string */ + if (fmt != start || !*fmt) + return fmt - start; + + /* Process flags */ + spec->flags = 0; + + while (1) { /* this also skips first '%' */ + bool_t found = true; + + ++fmt; + + switch (*fmt) { + case '-': spec->flags |= LEFT; break; + case '+': spec->flags |= PLUS; break; + case ' ': spec->flags |= SPACE; break; + case '#': spec->flags |= SPECIAL; break; + case '0': spec->flags |= ZEROPAD; break; + default: found = false; + } + + if (!found) + break; + } + + /* get field width */ + spec->field_width = -1; + + if (isdigit(*fmt)) + spec->field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + spec->type = FORMAT_TYPE_WIDTH; + return ++fmt - start; + } + +precision: + /* get the precision */ + spec->precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) { + spec->precision = skip_atoi(&fmt); + if (spec->precision < 0) + spec->precision = 0; + } else if (*fmt == '*') { + /* it's the next argument */ + spec->type = FORMAT_TYPE_PRECISION; + return ++fmt - start; + } + } + +qualifier: + /* get the conversion qualifier */ + spec->qualifier = -1; + if (*fmt == 'h' || TOLOWER(*fmt) == 'l' || + TOLOWER(*fmt) == 'z' || *fmt == 't') { + spec->qualifier = *fmt++; + if (spec->qualifier == *fmt) { + if (spec->qualifier == 'l') { + spec->qualifier = 'L'; + ++fmt; + } else if (spec->qualifier == 'h') { + spec->qualifier = 'H'; + ++fmt; + } + } + } + + /* default base */ + spec->base = 10; + switch (*fmt) { + case 'c': + spec->type = FORMAT_TYPE_CHAR; + return ++fmt - start; + + case 's': + spec->type = FORMAT_TYPE_STR; + return ++fmt - start; + + case 'p': + spec->type = FORMAT_TYPE_PTR; + return fmt - start; + /* skip alnum */ + + case 'n': + spec->type = FORMAT_TYPE_NRCHARS; + return ++fmt - start; + + case '%': + spec->type = FORMAT_TYPE_PERCENT_CHAR; + return ++fmt - start; + + /* integer number formats - set up the flags and "break" */ + case 'o': + spec->base = 8; + break; + + case 'x': + spec->flags |= SMALL; + + case 'X': + spec->base = 16; + break; + + case 'd': + case 'i': + spec->flags |= SIGN; + case 'u': + break; + + default: + spec->type = FORMAT_TYPE_INVALID; + return fmt - start; + } + + if (spec->qualifier == 'L') + spec->type = FORMAT_TYPE_LONG_LONG; + else if (spec->qualifier == 'l') { + if (spec->flags & SIGN) + spec->type = FORMAT_TYPE_LONG; + else + spec->type = FORMAT_TYPE_ULONG; + } else if (TOLOWER(spec->qualifier) == 'z') { + spec->type = FORMAT_TYPE_SIZE_T; + } else if (spec->qualifier == 't') { + spec->type = FORMAT_TYPE_PTRDIFF; + } else if (spec->qualifier == 'H') { + if (spec->flags & SIGN) + spec->type = FORMAT_TYPE_BYTE; + else + spec->type = FORMAT_TYPE_UBYTE; + } else if (spec->qualifier == 'h') { + if (spec->flags & SIGN) + spec->type = FORMAT_TYPE_SHORT; + else + spec->type = FORMAT_TYPE_USHORT; + } else { + if (spec->flags & SIGN) + spec->type = FORMAT_TYPE_INT; + else + spec->type = FORMAT_TYPE_UINT; + } + + return ++fmt - start; +} + +/** + * vsnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @args: Arguments for the format string + * + * This function follows C99 vsnprintf, but has some extensions: + * %pS output the name of a text symbol with offset + * %ps output the name of a text symbol without offset + * %pF output the name of a function pointer with its offset + * %pf output the name of a function pointer without its offset + * %pB output the name of a backtrace symbol with its offset + * %pR output the address range in a struct resource with decoded flags + * %pr output the address range in a struct resource with raw flags + * %pM output a 6-byte MAC address with colons + * %pm output a 6-byte MAC address without colons + * %pI4 print an IPv4 address without leading zeros + * %pi4 print an IPv4 address with leading zeros + * %pI6 print an IPv6 address with colons + * %pi6 print an IPv6 address without colons + * %pI6c print an IPv6 address as specified by + * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00 + * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper + * case. + * %n is ignored + * + * The return value is the number of characters which would + * be generated for the given input, excluding the trailing + * '\0', as per ISO C99. If you want to have the exact + * number of characters written into @buf as return value + * (not including the trailing '\0'), use vscnprintf(). If the + * return is greater than or equal to @size, the resulting + * string is truncated. + * + * Call this function if you are already dealing with a va_list. + * You probably want snprintf() instead. + */ +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + unsigned long long num; + char *str, *end; + struct printf_spec spec = {0}; + + str = buf; + end = buf + size; + + /* Make sure end is always >= buf */ + if (end < buf) { + end = ((void *)-1); + size = end - buf; + } + + while (*fmt) { + const char *old_fmt = fmt; + int read = format_decode(fmt, &spec); + + fmt += read; + + switch (spec.type) { + case FORMAT_TYPE_NONE: { + int copy = read; + if (str < end) { + if (copy > end - str) + copy = end - str; + memcpy(str, old_fmt, copy); + } + str += read; + break; + } + + case FORMAT_TYPE_WIDTH: + spec.field_width = va_arg(args, int); + break; + + case FORMAT_TYPE_PRECISION: + spec.precision = va_arg(args, int); + break; + + case FORMAT_TYPE_CHAR: { + char c; + + if (!(spec.flags & LEFT)) { + while (--spec.field_width > 0) { + if (str < end) + *str = ' '; + ++str; + + } + } + c = (unsigned char) va_arg(args, int); + if (str < end) + *str = c; + ++str; + while (--spec.field_width > 0) { + if (str < end) + *str = ' '; + ++str; + } + break; + } + + case FORMAT_TYPE_STR: + str = string(str, end, va_arg(args, char *), spec); + break; + + case FORMAT_TYPE_PTR: + str = pointer(fmt+1, str, end, va_arg(args, void *), + spec); + while (isalnum(*fmt)) + fmt++; + break; + + case FORMAT_TYPE_PERCENT_CHAR: + if (str < end) + *str = '%'; + ++str; + break; + + case FORMAT_TYPE_INVALID: + if (str < end) + *str = '%'; + ++str; + break; + + case FORMAT_TYPE_NRCHARS: { + uint8_t qualifier = spec.qualifier; + + if (qualifier == 'l') { + long *ip = va_arg(args, long *); + *ip = (str - buf); + } else if (TOLOWER(qualifier) == 'z') { + size_t *ip = va_arg(args, size_t *); + *ip = (str - buf); + } else { + int *ip = va_arg(args, int *); + *ip = (str - buf); + } + break; + } + + default: + switch (spec.type) { + case FORMAT_TYPE_LONG_LONG: + num = va_arg(args, long long); + break; + case FORMAT_TYPE_ULONG: + num = va_arg(args, unsigned long); + break; + case FORMAT_TYPE_LONG: + num = va_arg(args, long); + break; + case FORMAT_TYPE_SIZE_T: + num = va_arg(args, size_t); + break; + case FORMAT_TYPE_PTRDIFF: + num = va_arg(args, ptrdiff_t); + break; + case FORMAT_TYPE_UBYTE: + num = (unsigned char) va_arg(args, int); + break; + case FORMAT_TYPE_BYTE: + num = (signed char) va_arg(args, int); + break; + case FORMAT_TYPE_USHORT: + num = (unsigned short) va_arg(args, int); + break; + case FORMAT_TYPE_SHORT: + num = (short) va_arg(args, int); + break; + case FORMAT_TYPE_INT: + num = (int) va_arg(args, int); + break; + default: + num = va_arg(args, unsigned int); + } + + str = number(str, end, num, spec); + } + } + + if (size > 0) { + if (str < end) + *str = '\0'; + else + end[-1] = '\0'; + } + + /* the trailing null byte doesn't count towards the total */ + return str-buf; + +} + +/** + * vscnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The return value is the number of characters which have been written into + * the @buf not including the trailing '\0'. If @size is == 0 the function + * returns 0. + * + * Call this function if you are already dealing with a va_list. + * You probably want scnprintf() instead. + * + * See the vsnprintf() documentation for format string extensions over C99. + */ +int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + int i; + + i = vsnprintf(buf, size, fmt, args); + + if (i < size) + return i; + if (size != 0) + return size - 1; + return 0; +} + +/** + * snprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The return value is the number of characters which would be + * generated for the given input, excluding the trailing null, + * as per ISO C99. If the return is greater than or equal to + * @size, the resulting string is truncated. + * + * See the vsnprintf() documentation for format string extensions over C99. + */ +int snprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, size, fmt, args); + va_end(args); + + return i; +} + +/** + * scnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The return value is the number of characters written into @buf not including + * the trailing '\0'. If @size is == 0 the function returns 0. + */ + +int scnprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vscnprintf(buf, size, fmt, args); + va_end(args); + + return i; +} + +/** + * vsprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The function returns the number of characters written + * into @buf. Use vsnprintf() or vscnprintf() in order to avoid + * buffer overflows. + * + * Call this function if you are already dealing with a va_list. + * You probably want sprintf() instead. + * + * See the vsnprintf() documentation for format string extensions over C99. + */ +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return vsnprintf(buf, INT_MAX, fmt, args); +} + +/** + * sprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The function returns the number of characters written + * into @buf. Use snprintf() or scnprintf() in order to avoid + * buffer overflows. + * + * See the vsnprintf() documentation for format string extensions over C99. + */ +int sprintf(char *buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, INT_MAX, fmt, args); + va_end(args); + + return i; +} + +#ifdef CONFIG_BINARY_PRINTF +/* + * bprintf service: + * vbin_printf() - VA arguments to binary data + * bstr_printf() - Binary data to text string + */ + +/** + * vbin_printf - Parse a format string and place args' binary value in a buffer + * @bin_buf: The buffer to place args' binary value + * @size: The size of the buffer(by words(32bits), not characters) + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The format follows C99 vsnprintf, except %n is ignored, and its argument + * is skiped. + * + * The return value is the number of words(32bits) which would be generated for + * the given input. + * + * NOTE: + * If the return value is greater than @size, the resulting bin_buf is NOT + * valid for bstr_printf(). + */ +int vbin_printf(uint32_t *bin_buf, size_t size, const char *fmt, va_list args) +{ + struct printf_spec spec = {0}; + char *str, *end; + + str = (char *)bin_buf; + end = (char *)(bin_buf + size); + +#define save_arg(type) \ +do { \ + if (sizeof(type) == 8) { \ + unsigned long long value; \ + str = PTR_ALIGN(str, sizeof(uint32_t)); \ + value = va_arg(args, unsigned long long); \ + if (str + sizeof(type) <= end) { \ + *(uint32_t *)str = *(uint32_t *)&value; \ + *(uint32_t *)(str + 4) = *((uint32_t *)&value + 1); \ + } \ + } else { \ + unsigned long value; \ + str = PTR_ALIGN(str, sizeof(type)); \ + value = va_arg(args, int); \ + if (str + sizeof(type) <= end) \ + *(typeof(type) *)str = (type)value; \ + } \ + str += sizeof(type); \ +} while (0) + + while (*fmt) { + int read = format_decode(fmt, &spec); + + fmt += read; + + switch (spec.type) { + case FORMAT_TYPE_NONE: + case FORMAT_TYPE_INVALID: + case FORMAT_TYPE_PERCENT_CHAR: + break; + + case FORMAT_TYPE_WIDTH: + case FORMAT_TYPE_PRECISION: + save_arg(int); + break; + + case FORMAT_TYPE_CHAR: + save_arg(char); + break; + + case FORMAT_TYPE_STR: { + const char *save_str = va_arg(args, char *); + size_t len; + + if ((unsigned long)save_str > (unsigned long)-PAGE_SIZE + || (unsigned long)save_str < PAGE_SIZE) + save_str = "(null)"; + len = strlen(save_str) + 1; + if (str + len < end) + memcpy(str, save_str, len); + str += len; + break; + } + + case FORMAT_TYPE_PTR: + save_arg(void *); + /* skip all alphanumeric pointer suffixes */ + while (isalnum(*fmt)) + fmt++; + break; + + case FORMAT_TYPE_NRCHARS: { + /* skip %n 's argument */ + uint8_t qualifier = spec.qualifier; + void *skip_arg; + if (qualifier == 'l') + skip_arg = va_arg(args, long *); + else if (TOLOWER(qualifier) == 'z') + skip_arg = va_arg(args, size_t *); + else + skip_arg = va_arg(args, int *); + break; + } + + default: + switch (spec.type) { + + case FORMAT_TYPE_LONG_LONG: + save_arg(long long); + break; + case FORMAT_TYPE_ULONG: + case FORMAT_TYPE_LONG: + save_arg(unsigned long); + break; + case FORMAT_TYPE_SIZE_T: + save_arg(size_t); + break; + case FORMAT_TYPE_PTRDIFF: + save_arg(ptrdiff_t); + break; + case FORMAT_TYPE_UBYTE: + case FORMAT_TYPE_BYTE: + save_arg(char); + break; + case FORMAT_TYPE_USHORT: + case FORMAT_TYPE_SHORT: + save_arg(short); + break; + default: + save_arg(int); + } + } + } + + return (uint32_t *)(PTR_ALIGN(str, sizeof(uint32_t))) - bin_buf; +#undef save_arg +} + +/** + * bstr_printf - Format a string from binary arguments and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @bin_buf: Binary arguments for the format string + * + * This function like C99 vsnprintf, but the difference is that vsnprintf gets + * arguments from stack, and bstr_printf gets arguments from @bin_buf which is + * a binary buffer that generated by vbin_printf. + * + * The format follows C99 vsnprintf, but has some extensions: + * see vsnprintf comment for details. + * + * The return value is the number of characters which would + * be generated for the given input, excluding the trailing + * '\0', as per ISO C99. If you want to have the exact + * number of characters written into @buf as return value + * (not including the trailing '\0'), use vscnprintf(). If the + * return is greater than or equal to @size, the resulting + * string is truncated. + */ +int bstr_printf(char *buf, size_t size, const char *fmt, const uint32_t *bin_buf) +{ + struct printf_spec spec = {0}; + char *str, *end; + const char *args = (const char *)bin_buf; + + if (WARN_ON_ONCE((int) size < 0)) + return 0; + + str = buf; + end = buf + size; + +#define get_arg(type) \ +({ \ + typeof(type) value; \ + if (sizeof(type) == 8) { \ + args = PTR_ALIGN(args, sizeof(uint32_t)); \ + *(uint32_t *)&value = *(uint32_t *)args; \ + *((uint32_t *)&value + 1) = *(uint32_t *)(args + 4); \ + } else { \ + args = PTR_ALIGN(args, sizeof(type)); \ + value = *(typeof(type) *)args; \ + } \ + args += sizeof(type); \ + value; \ +}) + + /* Make sure end is always >= buf */ + if (end < buf) { + end = ((void *)-1); + size = end - buf; + } + + while (*fmt) { + const char *old_fmt = fmt; + int read = format_decode(fmt, &spec); + + fmt += read; + + switch (spec.type) { + case FORMAT_TYPE_NONE: { + int copy = read; + if (str < end) { + if (copy > end - str) + copy = end - str; + memcpy(str, old_fmt, copy); + } + str += read; + break; + } + + case FORMAT_TYPE_WIDTH: + spec.field_width = get_arg(int); + break; + + case FORMAT_TYPE_PRECISION: + spec.precision = get_arg(int); + break; + + case FORMAT_TYPE_CHAR: { + char c; + + if (!(spec.flags & LEFT)) { + while (--spec.field_width > 0) { + if (str < end) + *str = ' '; + ++str; + } + } + c = (unsigned char) get_arg(char); + if (str < end) + *str = c; + ++str; + while (--spec.field_width > 0) { + if (str < end) + *str = ' '; + ++str; + } + break; + } + + case FORMAT_TYPE_STR: { + const char *str_arg = args; + args += strlen(str_arg) + 1; + str = string(str, end, (char *)str_arg, spec); + break; + } + + case FORMAT_TYPE_PTR: + str = pointer(fmt+1, str, end, get_arg(void *), spec); + while (isalnum(*fmt)) + fmt++; + break; + + case FORMAT_TYPE_PERCENT_CHAR: + case FORMAT_TYPE_INVALID: + if (str < end) + *str = '%'; + ++str; + break; + + case FORMAT_TYPE_NRCHARS: + /* skip */ + break; + + default: { + unsigned long long num; + + switch (spec.type) { + + case FORMAT_TYPE_LONG_LONG: + num = get_arg(long long); + break; + case FORMAT_TYPE_ULONG: + case FORMAT_TYPE_LONG: + num = get_arg(unsigned long); + break; + case FORMAT_TYPE_SIZE_T: + num = get_arg(size_t); + break; + case FORMAT_TYPE_PTRDIFF: + num = get_arg(ptrdiff_t); + break; + case FORMAT_TYPE_UBYTE: + num = get_arg(unsigned char); + break; + case FORMAT_TYPE_BYTE: + num = get_arg(signed char); + break; + case FORMAT_TYPE_USHORT: + num = get_arg(unsigned short); + break; + case FORMAT_TYPE_SHORT: + num = get_arg(short); + break; + case FORMAT_TYPE_UINT: + num = get_arg(unsigned int); + break; + default: + num = get_arg(int); + } + + str = number(str, end, num, spec); + } /* default: */ + } /* switch(spec.type) */ + } /* while(*fmt) */ + + if (size > 0) { + if (str < end) + *str = '\0'; + else + end[-1] = '\0'; + } + +#undef get_arg + + /* the trailing null byte doesn't count towards the total */ + return str - buf; +} + +/** + * bprintf - Parse a format string and place args' binary value in a buffer + * @bin_buf: The buffer to place args' binary value + * @size: The size of the buffer(by words(32bits), not characters) + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The function returns the number of words(uint32_t) written + * into @bin_buf. + */ +int bprintf(uint32_t *bin_buf, size_t size, const char *fmt, ...) +{ + va_list args; + int ret; + + va_start(args, fmt); + ret = vbin_printf(bin_buf, size, fmt, args); + va_end(args); + + return ret; +} + +#endif /* CONFIG_BINARY_PRINTF */ + +/** + * vsscanf - Unformat a buffer into a list of arguments + * @buf: input buffer + * @fmt: format of buffer + * @args: arguments + */ +int vsscanf(const char *buf, const char *fmt, va_list args) +{ + const char *str = buf; + char *next; + char digit; + int num = 0; + uint8_t qualifier; + uint8_t base; + int16_t field_width; + bool_t is_sign; + + while (*fmt && *str) { + /* skip any white space in format */ + /* white space in format matchs any amount of + * white space, including none, in the input. + */ + if (isspace(*fmt)) { + fmt = skip_spaces(++fmt); + str = skip_spaces(str); + } + + /* anything that is not a conversion must match exactly */ + if (*fmt != '%' && *fmt) { + if (*fmt++ != *str++) + break; + continue; + } + + if (!*fmt) + break; + ++fmt; + + /* skip this conversion. + * advance both strings to next white space + */ + if (*fmt == '*') { + while (!isspace(*fmt) && *fmt != '%' && *fmt) + fmt++; + while (!isspace(*str) && *str) + str++; + continue; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + + /* get conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || TOLOWER(*fmt) == 'l' || + TOLOWER(*fmt) == 'z') { + qualifier = *fmt++; + if (qualifier == *fmt) { + if (qualifier == 'h') { + qualifier = 'H'; + fmt++; + } else if (qualifier == 'l') { + qualifier = 'L'; + fmt++; + } + } + } + + if (!*fmt || !*str) + break; + + base = 10; + is_sign = 0; + + switch (*fmt++) { + case 'c': + { + char *s = (char *)va_arg(args, char*); + if (field_width == -1) + field_width = 1; + do { + *s++ = *str++; + } while (--field_width > 0 && *str); + num++; + } + continue; + case 's': + { + char *s = (char *)va_arg(args, char *); + if (field_width == -1) + field_width = SHRT_MAX; + /* first, skip leading white space in buffer */ + str = skip_spaces(str); + + /* now copy until next white space */ + while (*str && !isspace(*str) && field_width--) + *s++ = *str++; + *s = '\0'; + num++; + } + continue; + case 'n': + /* return number of characters read so far */ + { + int *i = (int *)va_arg(args, int*); + *i = str - buf; + } + continue; + case 'o': + base = 8; + break; + case 'x': + case 'X': + base = 16; + break; + case 'i': + base = 0; + case 'd': + is_sign = 1; + case 'u': + break; + case '%': + /* looking for '%' in str */ + if (*str++ != '%') + return num; + continue; + default: + /* invalid format; stop here */ + return num; + } + + /* have some sort of integer conversion. + * first, skip white space in buffer. + */ + str = skip_spaces(str); + + digit = *str; + if (is_sign && digit == '-') + digit = *(str + 1); + + if (!digit + || (base == 16 && !isxdigit(digit)) + || (base == 10 && !isdigit(digit)) + || (base == 8 && (!isdigit(digit) || digit > '7')) + || (base == 0 && !isdigit(digit))) + break; + + switch (qualifier) { + case 'H': /* that's 'hh' in format */ + if (is_sign) { + signed char *s = (signed char *)va_arg(args, signed char *); + *s = (signed char)simple_strtol(str, &next, base); + } else { + unsigned char *s = (unsigned char *)va_arg(args, unsigned char *); + *s = (unsigned char)simple_strtoul(str, &next, base); + } + break; + case 'h': + if (is_sign) { + short *s = (short *)va_arg(args, short *); + *s = (short)simple_strtol(str, &next, base); + } else { + unsigned short *s = (unsigned short *)va_arg(args, unsigned short *); + *s = (unsigned short)simple_strtoul(str, &next, base); + } + break; + case 'l': + if (is_sign) { + long *l = (long *)va_arg(args, long *); + *l = simple_strtol(str, &next, base); + } else { + unsigned long *l = (unsigned long *)va_arg(args, unsigned long *); + *l = simple_strtoul(str, &next, base); + } + break; + case 'L': + if (is_sign) { + long long *l = (long long *)va_arg(args, long long *); + *l = simple_strtoll(str, &next, base); + } else { + unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *); + *l = simple_strtoull(str, &next, base); + } + break; + case 'Z': + case 'z': + { + size_t *s = (size_t *)va_arg(args, size_t *); + *s = (size_t)simple_strtoul(str, &next, base); + } + break; + default: + if (is_sign) { + int *i = (int *)va_arg(args, int *); + *i = (int)simple_strtol(str, &next, base); + } else { + unsigned int *i = (unsigned int *)va_arg(args, unsigned int*); + *i = (unsigned int)simple_strtoul(str, &next, base); + } + break; + } + num++; + + if (!next) + break; + str = next; + } + + /* + * Now we've come all the way through so either the input string or the + * format ended. In the former case, there can be a %n at the current + * position in the format that needs to be filled. + */ + if (*fmt == '%' && *(fmt + 1) == 'n') { + int *p = (int *)va_arg(args, int *); + *p = str - buf; + } + + return num; +} + +/** + * sscanf - Unformat a buffer into a list of arguments + * @buf: input buffer + * @fmt: formatting of buffer + * @...: resulting arguments + */ +int sscanf(const char *buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsscanf(buf, fmt, args); + va_end(args); + + return i; +} diff --git a/sept/sept-secondary/src/lib/vsprintf.h b/sept/sept-secondary/src/lib/vsprintf.h new file mode 100644 index 000000000..7b7fea7aa --- /dev/null +++ b/sept/sept-secondary/src/lib/vsprintf.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011 Andrei Warkentin <andrey.warkentin@gmail.com> + * + * This program is free software ; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <stdarg.h> +#include <stdlib.h> + +#ifndef VSPRINTF_H +#define VSPRINTF_H + +struct va_format { + const char *fmt; + va_list *va; +}; + +unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base); + +int sprintf(char *buf, const char *fmt, ...); +int scnprintf(char *buf, size_t size, const char *fmt, ...); +int snprintf(char *buf, size_t size, const char *fmt, ...); +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); +int sscanf(const char *buf, const char *fmt, ...); + +#endif /* VSPRINTF_H */ diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c new file mode 100644 index 000000000..c5f6b2037 --- /dev/null +++ b/sept/sept-secondary/src/main.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils.h" +#include "exception_handlers.h" +#include "panic.h" +#include "hwinit.h" +#include "di.h" +#include "timers.h" +#include "fs_utils.h" +#include "stage2.h" +#include "chainloader.h" +#include "sdmmc/sdmmc.h" +#include "lib/fatfs/ff.h" +#include "lib/log.h" +#include "lib/vsprintf.h" +#include "lib/ini.h" +#include "display/video_fb.h" + +extern void (*__program_exit_callback)(int rc); + +static void *g_framebuffer; + +static void setup_env(void) { + g_framebuffer = (void *)0xC0000000; + + /* Initialize hardware. */ + nx_hwinit(); + + /* Check for panics. */ + check_and_display_panic(); + + /* Zero-fill the framebuffer and register it as printk provider. */ + video_init(g_framebuffer); + + /* Initialize the display. */ + display_init(); + + /* Set the framebuffer. */ + display_init_framebuffer(g_framebuffer); + + /* Turn on the backlight after initializing the lfb */ + /* to avoid flickering. */ + display_backlight(true); + + /* Set up the exception handlers. */ + setup_exception_handlers(); + + /* Mount the SD card. */ + mount_sd(); +} + +static void cleanup_env(void) { + /* Unmount the SD card. */ + unmount_sd(); + + display_backlight(false); + display_end(); +} + +static void exit_callback(int rc) { + (void)rc; + relocate_and_chainload(); +} + +int main(void) { + ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY; + + /* Override the global logging level. */ + log_set_log_level(log_level); + + /* Initialize the display, console, etc. */ + setup_env(); + + /* Say hello. */ + print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re sept-secondary!\n"); + while (true) { } + + /* TODO: Derive keys. */ + + /* TODO: Chainload to payload. */ + + /* Wait a while. */ + mdelay(1000); + + /* Deinitialize the display, console, etc. */ + cleanup_env(); + + /* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, jump to Stage2. */ + __program_exit_callback = exit_callback; + return 0; +} diff --git a/sept/sept-secondary/src/max77620.h b/sept/sept-secondary/src/max77620.h new file mode 100644 index 000000000..8e1e4627e --- /dev/null +++ b/sept/sept-secondary/src/max77620.h @@ -0,0 +1,357 @@ +/* + * Defining registers address and its bit definitions of MAX77620 and MAX20024 + * + * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#ifndef _MFD_MAX77620_H_ +#define _MFD_MAX77620_H_ + +/* RTC Registers */ +#define MAX77620_REG_RTCINT 0x00 +#define MAX77620_REG_RTCINTM 0x01 +#define MAX77620_REG_RTCCNTLM 0x02 +#define MAX77620_REG_RTCCNTL 0x03 +#define MAX77620_REG_RTCUPDATE0 0x04 +#define MAX77620_REG_RTCUPDATE1 0x05 +#define MAX77620_REG_RTCSMPL 0x06 +#define MAX77620_REG_RTCSEC 0x07 +#define MAX77620_REG_RTCMIN 0x08 +#define MAX77620_REG_RTCHOUR 0x09 +#define MAX77620_REG_RTCDOW 0x0A +#define MAX77620_REG_RTCMONTH 0x0B +#define MAX77620_REG_RTCYEAR 0x0C +#define MAX77620_REG_RTCDOM 0x0D +#define MAX77620_REG_RTCSECA1 0x0E +#define MAX77620_REG_RTCMINA1 0x0F +#define MAX77620_REG_RTCHOURA1 0x10 +#define MAX77620_REG_RTCDOWA1 0x11 +#define MAX77620_REG_RTCMONTHA1 0x12 +#define MAX77620_REG_RTCYEARA1 0x13 +#define MAX77620_REG_RTCDOMA1 0x14 +#define MAX77620_REG_RTCSECA2 0x15 +#define MAX77620_REG_RTCMINA2 0x16 +#define MAX77620_REG_RTCHOURA2 0x17 +#define MAX77620_REG_RTCDOWA2 0x18 +#define MAX77620_REG_RTCMONTHA2 0x19 +#define MAX77620_REG_RTCYEARA2 0x1A +#define MAX77620_REG_RTCDOMA2 0x1B + +/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ +#define MAX77620_REG_CNFGGLBL1 0x00 +#define MAX77620_REG_CNFGGLBL2 0x01 +#define MAX77620_REG_CNFGGLBL3 0x02 +#define MAX77620_REG_CNFG1_32K 0x03 +#define MAX77620_REG_CNFGBBC 0x04 +#define MAX77620_REG_IRQTOP 0x05 +#define MAX77620_REG_INTLBT 0x06 +#define MAX77620_REG_IRQSD 0x07 +#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 +#define MAX77620_REG_IRQ_LVL2_L8 0x09 +#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A +#define MAX77620_REG_ONOFFIRQ 0x0B +#define MAX77620_REG_NVERC 0x0C +#define MAX77620_REG_IRQTOPM 0x0D +#define MAX77620_REG_INTENLBT 0x0E +#define MAX77620_REG_IRQMASKSD 0x0F +#define MAX77620_REG_IRQ_MSK_L0_7 0x10 +#define MAX77620_REG_IRQ_MSK_L8 0x11 +#define MAX77620_REG_ONOFFIRQM 0x12 +#define MAX77620_REG_STATLBT 0x13 +#define MAX77620_REG_STATSD 0x14 +#define MAX77620_REG_ONOFFSTAT 0x15 + +/* SD and LDO Registers */ +#define MAX77620_REG_SD0 0x16 +#define MAX77620_REG_SD1 0x17 +#define MAX77620_REG_SD2 0x18 +#define MAX77620_REG_SD3 0x19 +#define MAX77620_REG_SD4 0x1A +#define MAX77620_REG_DVSSD0 0x1B +#define MAX77620_REG_DVSSD1 0x1C +#define MAX77620_REG_SD0_CFG 0x1D +#define MAX77620_REG_SD1_CFG 0x1E +#define MAX77620_REG_SD2_CFG 0x1F +#define MAX77620_REG_SD3_CFG 0x20 +#define MAX77620_REG_SD4_CFG 0x21 +#define MAX77620_REG_SD_CFG2 0x22 +#define MAX77620_REG_LDO0_CFG 0x23 +#define MAX77620_REG_LDO0_CFG2 0x24 +#define MAX77620_REG_LDO1_CFG 0x25 +#define MAX77620_REG_LDO1_CFG2 0x26 +#define MAX77620_REG_LDO2_CFG 0x27 +#define MAX77620_REG_LDO2_CFG2 0x28 +#define MAX77620_REG_LDO3_CFG 0x29 +#define MAX77620_REG_LDO3_CFG2 0x2A +#define MAX77620_REG_LDO4_CFG 0x2B +#define MAX77620_REG_LDO4_CFG2 0x2C +#define MAX77620_REG_LDO5_CFG 0x2D +#define MAX77620_REG_LDO5_CFG2 0x2E +#define MAX77620_REG_LDO6_CFG 0x2F +#define MAX77620_REG_LDO6_CFG2 0x30 +#define MAX77620_REG_LDO7_CFG 0x31 +#define MAX77620_REG_LDO7_CFG2 0x32 +#define MAX77620_REG_LDO8_CFG 0x33 +#define MAX77620_REG_LDO8_CFG2 0x34 +#define MAX77620_REG_LDO_CFG3 0x35 + +#define MAX77620_LDO_SLEW_RATE_MASK 0x1 + +/* LDO Configuration 3 */ +#define MAX77620_TRACK4_MASK (1 << 5) +#define MAX77620_TRACK4_SHIFT 5 + +/* Voltage */ +#define MAX77620_SDX_VOLT_MASK 0xFF +#define MAX77620_SD0_VOLT_MASK 0x3F +#define MAX77620_SD1_VOLT_MASK 0x7F +#define MAX77620_LDO_VOLT_MASK 0x3F + +#define MAX77620_REG_GPIO0 0x36 +#define MAX77620_REG_GPIO1 0x37 +#define MAX77620_REG_GPIO2 0x38 +#define MAX77620_REG_GPIO3 0x39 +#define MAX77620_REG_GPIO4 0x3A +#define MAX77620_REG_GPIO5 0x3B +#define MAX77620_REG_GPIO6 0x3C +#define MAX77620_REG_GPIO7 0x3D +#define MAX77620_REG_PUE_GPIO 0x3E +#define MAX77620_REG_PDE_GPIO 0x3F +#define MAX77620_REG_AME_GPIO 0x40 +#define MAX77620_REG_ONOFFCNFG1 0x41 +#define MAX77620_REG_ONOFFCNFG2 0x42 + +/* FPS Registers */ +#define MAX77620_REG_FPS_CFG0 0x43 +#define MAX77620_REG_FPS_CFG1 0x44 +#define MAX77620_REG_FPS_CFG2 0x45 +#define MAX77620_REG_FPS_LDO0 0x46 +#define MAX77620_REG_FPS_LDO1 0x47 +#define MAX77620_REG_FPS_LDO2 0x48 +#define MAX77620_REG_FPS_LDO3 0x49 +#define MAX77620_REG_FPS_LDO4 0x4A +#define MAX77620_REG_FPS_LDO5 0x4B +#define MAX77620_REG_FPS_LDO6 0x4C +#define MAX77620_REG_FPS_LDO7 0x4D +#define MAX77620_REG_FPS_LDO8 0x4E +#define MAX77620_REG_FPS_SD0 0x4F +#define MAX77620_REG_FPS_SD1 0x50 +#define MAX77620_REG_FPS_SD2 0x51 +#define MAX77620_REG_FPS_SD3 0x52 +#define MAX77620_REG_FPS_SD4 0x53 +#define MAX77620_REG_FPS_NONE 0 + +#define MAX77620_FPS_SRC_MASK 0xC0 +#define MAX77620_FPS_SRC_SHIFT 6 +#define MAX77620_FPS_PU_PERIOD_MASK 0x38 +#define MAX77620_FPS_PU_PERIOD_SHIFT 3 +#define MAX77620_FPS_PD_PERIOD_MASK 0x07 +#define MAX77620_FPS_PD_PERIOD_SHIFT 0 +#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 +#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 +#define MAX77620_FPS_EN_SRC_MASK 0x06 +#define MAX77620_FPS_EN_SRC_SHIFT 1 +#define MAX77620_FPS_ENFPS_SW_MASK 0x01 +#define MAX77620_FPS_ENFPS_SW 0x01 + +/* Minimum and maximum FPS period time (in microseconds) are + * different for MAX77620 and Max20024. + */ +#define MAX77620_FPS_PERIOD_MIN_US 40 +#define MAX20024_FPS_PERIOD_MIN_US 20 + +#define MAX77620_FPS_PERIOD_MAX_US 2560 +#define MAX20024_FPS_PERIOD_MAX_US 5120 + +#define MAX77620_REG_FPS_GPIO1 0x54 +#define MAX77620_REG_FPS_GPIO2 0x55 +#define MAX77620_REG_FPS_GPIO3 0x56 +#define MAX77620_REG_FPS_RSO 0x57 +#define MAX77620_REG_CID0 0x58 +#define MAX77620_REG_CID1 0x59 +#define MAX77620_REG_CID2 0x5A +#define MAX77620_REG_CID3 0x5B +#define MAX77620_REG_CID4 0x5C +#define MAX77620_REG_CID5 0x5D + +#define MAX77620_REG_DVSSD4 0x5E +#define MAX20024_REG_MAX_ADD 0x70 + +#define MAX77620_CID_DIDM_MASK 0xF0 +#define MAX77620_CID_DIDM_SHIFT 4 + +/* CNCG2SD */ +#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) +#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) + +/* Device Identification Metal */ +#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) +/* Device Indentification OTP */ +#define MAX77620_CID5_DIDO(n) ((n) & 0xF) + +/* SD CNFG1 */ +#define MAX77620_SD_SR_MASK 0xC0 +#define MAX77620_SD_SR_SHIFT 6 +#define MAX77620_SD_POWER_MODE_MASK 0x30 +#define MAX77620_SD_POWER_MODE_SHIFT 4 +#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) +#define MAX77620_SD_CFG1_ADE_DISABLE 0 +#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) +#define MAX77620_SD_FPWM_MASK 0x04 +#define MAX77620_SD_FPWM_SHIFT 2 +#define MAX77620_SD_FSRADE_MASK 0x01 +#define MAX77620_SD_FSRADE_SHIFT 0 +#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) +#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 +#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) +#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) +#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) +#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 +#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) + +/* LDO_CNFG2 */ +#define MAX77620_LDO_POWER_MODE_MASK 0xC0 +#define MAX77620_LDO_POWER_MODE_SHIFT 6 +#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) +#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) +#define MAX77620_LDO_CFG2_ADE_DISABLE 0 +#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) +#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) +#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) +#define MAX77620_LDO_CFG2_SS_SLOW 0 + +#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) +#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) +#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) +#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) +#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) +#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) +#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) + +#define MAX77620_IRQ_LBM_MASK (1 << 3) +#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) +#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) + +#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) +#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) +#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0 +#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) +#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) +#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0 +#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0 +#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) +#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) +#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) +#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) +#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) +#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) +#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) +#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) + +#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) +#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) +#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) +#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) +#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) +#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) +#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) +#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) + +#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) + +#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) +#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 +#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 +#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) +#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) +#define MAX20024_ONOFFCNFG1_CLRSE 0x18 + +#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) +#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) +#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) +#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) +#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) + +#define MAX77620_GLBLM_MASK (1 << 0) + +#define MAX77620_WDTC_MASK 0x3 +#define MAX77620_WDTOFFC (1 << 4) +#define MAX77620_WDTSLPC (1 << 3) +#define MAX77620_WDTEN (1 << 2) + +#define MAX77620_TWD_MASK 0x3 +#define MAX77620_TWD_2s 0x0 +#define MAX77620_TWD_16s 0x1 +#define MAX77620_TWD_64s 0x2 +#define MAX77620_TWD_128s 0x3 + +#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) +#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) +#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) +#define MAX77620_CNFGGLBL1_LBHYST_N (1 << 4) +#define MAX77620_CNFGGLBL1_LBDAC 0x0E +#define MAX77620_CNFGGLBL1_LBDAC_N (1 << 1) +#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) + +/* CNFG BBC registers */ +#define MAX77620_CNFGBBC_ENABLE (1 << 0) +#define MAX77620_CNFGBBC_CURRENT_MASK 0x06 +#define MAX77620_CNFGBBC_CURRENT_SHIFT 1 +#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 +#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 +#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) +#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 +#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 + +#define MAX77620_FPS_COUNT 3 + +/* Interrupts */ +enum { + MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ + MAX77620_IRQ_TOP_SD, /* SD power fail */ + MAX77620_IRQ_TOP_LDO, /* LDO power fail */ + MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ + MAX77620_IRQ_TOP_RTC, /* RTC */ + MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ + MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ + MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ + MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ + MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ +}; + +/* GPIOs */ +enum { + MAX77620_GPIO0, + MAX77620_GPIO1, + MAX77620_GPIO2, + MAX77620_GPIO3, + MAX77620_GPIO4, + MAX77620_GPIO5, + MAX77620_GPIO6, + MAX77620_GPIO7, + MAX77620_GPIO_NR, +}; + +/* FPS Source */ +enum max77620_fps_src { + MAX77620_FPS_SRC_0, + MAX77620_FPS_SRC_1, + MAX77620_FPS_SRC_2, + MAX77620_FPS_SRC_NONE, + MAX77620_FPS_SRC_DEF, +}; + +enum max77620_chip_id { + MAX77620, + MAX20024, +}; + +#endif /* _MFD_MAX77620_H_ */ diff --git a/sept/sept-secondary/src/max7762x.c b/sept/sept-secondary/src/max7762x.c new file mode 100644 index 000000000..2987917e5 --- /dev/null +++ b/sept/sept-secondary/src/max7762x.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> + +#include "max7762x.h" +#include "max77620.h" +#include "i2c.h" +#include "timers.h" + +#define REGULATOR_SD 0 +#define REGULATOR_LDO 1 + +typedef struct _max77620_regulator_t +{ + uint8_t type; + const char *name; + uint8_t reg_sd; + uint32_t mv_step; + uint32_t mv_min; + uint32_t mv_default; + uint32_t mv_max; + uint8_t volt_addr; + uint8_t cfg_addr; + uint8_t volt_mask; + uint8_t enable_mask; + uint8_t enable_shift; + uint8_t status_mask; + + uint8_t fps_addr; + uint8_t fps_src; + uint8_t pd_period; + uint8_t pu_period; +} max77620_regulator_t; + +static const max77620_regulator_t _pmic_regulators[] = { + { REGULATOR_SD, "sd0", 0x16, 12500, 600000, 625000, 1400000, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, 0x3F, 0x30, 4, 0x80, 0x4F, 1, 7, 1 }, + { REGULATOR_SD, "sd1", 0x17, 12500, 600000, 1125000, 1125000, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, 0x3F, 0x30, 4, 0x40, 0x50, 0, 1, 5 }, + { REGULATOR_SD, "sd2", 0x18, 12500, 600000, 1325000, 1350000, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, 0xFF, 0x30, 4, 0x20, 0x51, 1, 5, 2 }, + { REGULATOR_SD, "sd3", 0x19, 12500, 600000, 1800000, 1800000, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, 0xFF, 0x30, 4, 0x10, 0x52, 0, 3, 3 }, + { REGULATOR_LDO, "ldo0", 0x00, 25000, 800000, 1200000, 1200000, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, 0x3F, 0xC0, 6, 0x00, 0x46, 3, 7, 0 }, + { REGULATOR_LDO, "ldo1", 0x00, 25000, 800000, 1050000, 1050000, MAX77620_REG_LDO1_CFG, MAX77620_REG_LDO1_CFG2, 0x3F, 0xC0, 6, 0x00, 0x47, 3, 7, 0 }, + { REGULATOR_LDO, "ldo2", 0x00, 50000, 800000, 1800000, 3300000, MAX77620_REG_LDO2_CFG, MAX77620_REG_LDO2_CFG2, 0x3F, 0xC0, 6, 0x00, 0x48, 3, 7, 0 }, + { REGULATOR_LDO, "ldo3", 0x00, 50000, 800000, 3100000, 3100000, MAX77620_REG_LDO3_CFG, MAX77620_REG_LDO3_CFG2, 0x3F, 0xC0, 6, 0x00, 0x49, 3, 7, 0 }, + { REGULATOR_LDO, "ldo4", 0x00, 12500, 800000, 850000, 850000, MAX77620_REG_LDO4_CFG, MAX77620_REG_LDO4_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4A, 0, 7, 1 }, + { REGULATOR_LDO, "ldo5", 0x00, 50000, 800000, 1800000, 1800000, MAX77620_REG_LDO5_CFG, MAX77620_REG_LDO5_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4B, 3, 7, 0 }, + { REGULATOR_LDO, "ldo6", 0x00, 50000, 800000, 2900000, 2900000, MAX77620_REG_LDO6_CFG, MAX77620_REG_LDO6_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4C, 3, 7, 0 }, + { REGULATOR_LDO, "ldo7", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO7_CFG, MAX77620_REG_LDO7_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4D, 1, 4, 3 }, + { REGULATOR_LDO, "ldo8", 0x00, 50000, 800000, 1050000, 1050000, MAX77620_REG_LDO8_CFG, MAX77620_REG_LDO8_CFG2, 0x3F, 0xC0, 6, 0x00, 0x4E, 3, 7, 0 } +}; + +int max77620_regulator_get_status(uint32_t id) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + uint8_t val = 0; + + if (reg->type == REGULATOR_SD) { + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_STATSD, &val, 1)) + return (val & reg->status_mask) ? 0 : 1; + } + + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->cfg_addr, &val, 1)) + return (val & 8) ? 1 : 0; + + return 0; +} + +int max77620_regulator_config_fps(uint32_t id) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + uint8_t val = ((reg->fps_src << 6) | (reg->pu_period << 3) | (reg->pd_period)); + + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->fps_addr, &val, 1)) { + return 1; + } + + return 0; +} + +int max77620_regulator_set_voltage(uint32_t id, uint32_t mv) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + + if ((mv < reg->mv_default) || (mv > reg->mv_max)) + return 0; + + uint32_t mult = (mv + reg->mv_step - 1 - reg->mv_min) / reg->mv_step; + uint8_t val = 0; + + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) + { + val = ((val & ~reg->volt_mask) | (mult & reg->volt_mask)); + + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, reg->volt_addr, &val, 1)) + { + udelay(1000); + return 1; + } + } + + return 0; +} + +int max77620_regulator_enable(uint32_t id, int enable) +{ + if (id > REGULATOR_MAX) + return 0; + + const max77620_regulator_t *reg = &_pmic_regulators[id]; + + uint32_t addr = (reg->type == REGULATOR_SD) ? reg->cfg_addr : reg->volt_addr; + uint8_t val = 0; + + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) + { + if (enable) + val = ((val & ~reg->enable_mask) | ((3 << reg->enable_shift) & reg->enable_mask)); + else + val &= ~reg->enable_mask; + + if (i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, addr, &val, 1)) + { + udelay(1000); + return 1; + } + } + + return 0; +} + +void max77620_config_default() +{ + for (uint32_t i = 1; i <= REGULATOR_MAX; i++) + { + uint8_t val = 0; + if (i2c_query(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CID4, &val, 1)) + { + max77620_regulator_config_fps(i); + max77620_regulator_set_voltage(i, _pmic_regulators[i].mv_default); + + if (_pmic_regulators[i].fps_src != MAX77620_FPS_SRC_NONE) { + max77620_regulator_enable(i, 1); + } + } + } + + uint8_t val = 4; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1); +} + +void max77620_low_battery_monitor_config() +{ + uint8_t val = (MAX77620_CNFGGLBL1_LBDAC_EN | MAX77620_CNFGGLBL1_LBHYST_N | MAX77620_CNFGGLBL1_LBDAC_N); + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_CNFGGLBL1, &val, 1); +} diff --git a/sept/sept-secondary/src/max7762x.h b/sept/sept-secondary/src/max7762x.h new file mode 100644 index 000000000..8149c03f4 --- /dev/null +++ b/sept/sept-secondary/src/max7762x.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_MAX7762X_H_ +#define FUSEE_MAX7762X_H_ + +/* +* Switch Power domains (max77620): +* Name | Usage | uV step | uV min | uV default | uV max | Init +*-------+---------------+---------+--------+------------+---------+------------------ +* sd0 | core | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1) +* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1) +* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv) +* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 | +* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1) +* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv) +* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 | +* ldo3 | | 50000 | 800000 | 3100000 | 3100000 | +* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | +* ldo5 | | 50000 | 800000 | 1800000 | 1800000 | +* ldo6 | | 50000 | 800000 | 2900000 | 2900000 | +* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | +* ldo8 | XUSB, DC | 50000 | 800000 | 1050000 | 1050000 | +*/ + +/* +* MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode +* MAX77620_REG_GPIOx: 0x9 sets output and enable +*/ + +/*! MAX77620 partitions. */ +#define REGULATOR_SD0 0 +#define REGULATOR_SD1 1 +#define REGULATOR_SD2 2 +#define REGULATOR_SD3 3 +#define REGULATOR_LDO0 4 +#define REGULATOR_LDO1 5 +#define REGULATOR_LDO2 6 +#define REGULATOR_LDO3 7 +#define REGULATOR_LDO4 8 +#define REGULATOR_LDO5 9 +#define REGULATOR_LDO6 10 +#define REGULATOR_LDO7 11 +#define REGULATOR_LDO8 12 +#define REGULATOR_MAX 12 + +int max77620_regulator_get_status(uint32_t id); +int max77620_regulator_config_fps(uint32_t id); +int max77620_regulator_set_voltage(uint32_t id, uint32_t mv); +int max77620_regulator_enable(uint32_t id, int enable); +void max77620_config_default(); +void max77620_low_battery_monitor_config(); + +#endif diff --git a/sept/sept-secondary/src/mc.c b/sept/sept-secondary/src/mc.c new file mode 100644 index 000000000..e803d7a7c --- /dev/null +++ b/sept/sept-secondary/src/mc.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "mc.h" +#include "car.h" +#include "timers.h" + +void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock) +{ + MAKE_MC_REG(MC_SEC_CARVEOUT_BOM) = bom; + MAKE_MC_REG(MC_SEC_CARVEOUT_SIZE_MB) = size1mb; + + if (lock) + MAKE_MC_REG(MC_SEC_CARVEOUT_REG_CTRL) = 1; +} + +void mc_config_carveout() +{ + *(volatile uint32_t *)0x8005FFFC = 0xC0EDBBCC; + + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = 1; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = 0; + MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = 1; + + mc_config_tsec_carveout(0, 0, true); + + MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = 0; + MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = 1; + + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT1_CFG0) = 0x4000006; + + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT3_CFG0) = 0x4401E7E; + + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT4_CFG0) = 0x8F; + + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_SIZE_128KB) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT5_CFG0) = 0x8F; +} + +void mc_config_carveout_finalize() +{ + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_BOM) = 0x80020000; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_BOM_HI) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_SIZE_128KB) = 2; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = (BIT(CSR_GPUSRD) | BIT(CSW_GPUSWR)); + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = (BIT(CSR_GPUSRD2) | BIT(CSW_GPUSWR2)); + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0; + MAKE_MC_REG(MC_SECURITY_CARVEOUT2_CFG0) = 0x440167E; +} + +void mc_enable_ahb_redirect() +{ + volatile tegra_car_t *car = car_get_regs(); + car->lvl2_clk_gate_ovrd = ((car->lvl2_clk_gate_ovrd & 0xFFF7FFFF) | 0x80000); + + MAKE_MC_REG(MC_IRAM_BOM) = 0x40000000; + MAKE_MC_REG(MC_IRAM_TOM) = 0x4003F000; +} + +void mc_disable_ahb_redirect() +{ + volatile tegra_car_t *car = car_get_regs(); + + MAKE_MC_REG(MC_IRAM_BOM) = 0xFFFFF000; + MAKE_MC_REG(MC_IRAM_TOM) = 0; + + car->lvl2_clk_gate_ovrd &= 0xFFF7FFFF; +} + +void mc_enable() +{ + volatile tegra_car_t *car = car_get_regs(); + + /* Set EMC clock source. */ + car->clk_source_emc = ((car->clk_source_emc & 0x1FFFFFFF) | 0x40000000); + + /* Enable MIPI CAL clock. */ + car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFDFFFFFF) | 0x2000000); + + /* Enable MC clock. */ + car->clk_enb_h_set = ((car->clk_enb_h_set & 0xFFFFFFFE) | 1); + + /* Enable EMC DLL clock. */ + car->clk_enb_x_set = ((car->clk_enb_x_set & 0xFFFFBFFF) | 0x4000); + + /* Clear EMC and MC reset. */ + /* NOTE: [4.0.0+] This was changed to use the right register. */ + /* car->rst_dev_h_set = 0x2000001; */ + car->rst_dev_h_clr = 0x2000001; + udelay(5); + + mc_disable_ahb_redirect(); +} \ No newline at end of file diff --git a/sept/sept-secondary/src/mc.h b/sept/sept-secondary/src/mc.h new file mode 100644 index 000000000..dfba6052c --- /dev/null +++ b/sept/sept-secondary/src/mc.h @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2014, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_MC_H_ +#define FUSEE_MC_H_ + +#include <stdint.h> +#include <stdbool.h> + +#define MC_BASE 0x70019000 +#define MAKE_MC_REG(n) MAKE_REG32(MC_BASE + n) + +#define MC_INTSTATUS 0x0 +#define MC_INTMASK 0x4 +#define MC_ERR_STATUS 0x8 +#define MC_ERR_ADR 0xc +#define MC_SMMU_CONFIG 0x10 +#define MC_SMMU_TLB_CONFIG 0x14 +#define MC_SMMU_PTC_CONFIG 0x18 +#define MC_SMMU_PTB_ASID 0x1c +#define MC_SMMU_PTB_DATA 0x20 +#define MC_SMMU_TLB_FLUSH 0x30 +#define MC_SMMU_PTC_FLUSH 0x34 +#define MC_SMMU_ASID_SECURITY 0x38 +#define MC_SMMU_AFI_ASID 0x238 +#define MC_SMMU_AVPC_ASID 0x23c +#define MC_SMMU_TSEC_ASID 0x294 +#define MC_SMMU_PPCS1_ASID 0x298 +#define MC_SMMU_TRANSLATION_ENABLE_0 0x228 +#define MC_SMMU_TRANSLATION_ENABLE_1 0x22c +#define MC_SMMU_TRANSLATION_ENABLE_2 0x230 +#define MC_SMMU_TRANSLATION_ENABLE_3 0x234 +#define MC_SMMU_TRANSLATION_ENABLE_4 0xb98 +#define MC_PCFIFO_CLIENT_CONFIG0 0xdd0 +#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4 +#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8 +#define MC_PCFIFO_CLIENT_CONFIG3 0xddc +#define MC_PCFIFO_CLIENT_CONFIG4 0xde0 +#define MC_EMEM_CFG 0x50 +#define MC_EMEM_ADR_CFG 0x54 +#define MC_EMEM_ADR_CFG_DEV0 0x58 +#define MC_EMEM_ADR_CFG_DEV1 0x5c +#define MC_EMEM_ADR_CFG_CHANNEL_MASK 0x60 +#define MC_EMEM_ADR_CFG_BANK_MASK_0 0x64 +#define MC_EMEM_ADR_CFG_BANK_MASK_1 0x68 +#define MC_EMEM_ADR_CFG_BANK_MASK_2 0x6c +#define MC_SECURITY_CFG0 0x70 +#define MC_SECURITY_CFG1 0x74 +#define MC_SECURITY_CFG3 0x9bc +#define MC_SECURITY_RSV 0x7c +#define MC_EMEM_ARB_CFG 0x90 +#define MC_EMEM_ARB_OUTSTANDING_REQ 0x94 +#define MC_EMEM_ARB_TIMING_RCD 0x98 +#define MC_EMEM_ARB_TIMING_RP 0x9c +#define MC_EMEM_ARB_TIMING_RC 0xa0 +#define MC_EMEM_ARB_TIMING_RAS 0xa4 +#define MC_EMEM_ARB_TIMING_FAW 0xa8 +#define MC_EMEM_ARB_TIMING_RRD 0xac +#define MC_EMEM_ARB_TIMING_RAP2PRE 0xb0 +#define MC_EMEM_ARB_TIMING_WAP2PRE 0xb4 +#define MC_EMEM_ARB_TIMING_R2R 0xb8 +#define MC_EMEM_ARB_TIMING_W2W 0xbc +#define MC_EMEM_ARB_TIMING_R2W 0xc0 +#define MC_EMEM_ARB_TIMING_W2R 0xc4 +#define MC_EMEM_ARB_TIMING_RFCPB 0x6c0 +#define MC_EMEM_ARB_TIMING_CCDMW 0x6c4 +#define MC_EMEM_ARB_REFPB_HP_CTRL 0x6f0 +#define MC_EMEM_ARB_REFPB_BANK_CTRL 0x6f4 +#define MC_EMEM_ARB_DA_TURNS 0xd0 +#define MC_EMEM_ARB_DA_COVERS 0xd4 +#define MC_EMEM_ARB_MISC0 0xd8 +#define MC_EMEM_ARB_MISC1 0xdc +#define MC_EMEM_ARB_MISC2 0xc8 +#define MC_EMEM_ARB_RING1_THROTTLE 0xe0 +#define MC_EMEM_ARB_RING3_THROTTLE 0xe4 +#define MC_EMEM_ARB_NISO_THROTTLE 0x6b0 +#define MC_EMEM_ARB_OVERRIDE 0xe8 +#define MC_EMEM_ARB_RSV 0xec +#define MC_CLKEN_OVERRIDE 0xf4 +#define MC_TIMING_CONTROL_DBG 0xf8 +#define MC_TIMING_CONTROL 0xfc +#define MC_STAT_CONTROL 0x100 +#define MC_STAT_STATUS 0x104 +#define MC_STAT_EMC_CLOCK_LIMIT 0x108 +#define MC_STAT_EMC_CLOCK_LIMIT_MSBS 0x10c +#define MC_STAT_EMC_CLOCKS 0x110 +#define MC_STAT_EMC_CLOCKS_MSBS 0x114 +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_LO 0x118 +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_LO 0x158 +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_HI 0x11c +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_HI 0x15c +#define MC_STAT_EMC_FILTER_SET0_ADR_LIMIT_UPPER 0xa20 +#define MC_STAT_EMC_FILTER_SET1_ADR_LIMIT_UPPER 0xa24 +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_LO 0x198 +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_LO 0x1a8 +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_HI 0x19c +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_HI 0x1ac +#define MC_STAT_EMC_FILTER_SET0_VIRTUAL_ADR_LIMIT_UPPER 0xa28 +#define MC_STAT_EMC_FILTER_SET1_VIRTUAL_ADR_LIMIT_UPPER 0xa2c +#define MC_STAT_EMC_FILTER_SET0_ASID 0x1a0 +#define MC_STAT_EMC_FILTER_SET1_ASID 0x1b0 +#define MC_STAT_EMC_FILTER_SET0_SLACK_LIMIT 0x120 +#define MC_STAT_EMC_FILTER_SET1_SLACK_LIMIT 0x160 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_0 0x128 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_0 0x168 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_1 0x12c +#define MC_STAT_EMC_FILTER_SET1_CLIENT_1 0x16c +#define MC_STAT_EMC_FILTER_SET0_CLIENT_2 0x130 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_2 0x170 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_3 0x134 +#define MC_STAT_EMC_FILTER_SET0_CLIENT_4 0xb88 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_3 0x174 +#define MC_STAT_EMC_FILTER_SET1_CLIENT_4 0xb8c +#define MC_STAT_EMC_SET0_COUNT 0x138 +#define MC_STAT_EMC_SET0_COUNT_MSBS 0x13c +#define MC_STAT_EMC_SET1_COUNT 0x178 +#define MC_STAT_EMC_SET1_COUNT_MSBS 0x17c +#define MC_STAT_EMC_SET0_SLACK_ACCUM 0x140 +#define MC_STAT_EMC_SET0_SLACK_ACCUM_MSBS 0x144 +#define MC_STAT_EMC_SET1_SLACK_ACCUM 0x180 +#define MC_STAT_EMC_SET1_SLACK_ACCUM_MSBS 0x184 +#define MC_STAT_EMC_SET0_HISTO_COUNT 0x148 +#define MC_STAT_EMC_SET0_HISTO_COUNT_MSBS 0x14c +#define MC_STAT_EMC_SET1_HISTO_COUNT 0x188 +#define MC_STAT_EMC_SET1_HISTO_COUNT_MSBS 0x18c +#define MC_STAT_EMC_SET0_MINIMUM_SLACK_OBSERVED 0x150 +#define MC_STAT_EMC_SET1_MINIMUM_SLACK_OBSERVED 0x190 +#define MC_STAT_EMC_SET0_IDLE_CYCLE_COUNT 0x1b8 +#define MC_STAT_EMC_SET0_IDLE_CYCL_COUNT_MSBS 0x1bc +#define MC_STAT_EMC_SET1_IDLE_CYCLE_COUNT 0x1c8 +#define MC_STAT_EMC_SET1_IDLE_CYCL_COUNT_MSBS 0x1cc +#define MC_STAT_EMC_SET0_IDLE_CYCLE_PARTITION_SELECT 0x1c0 +#define MC_STAT_EMC_SET1_IDLE_CYCLE_PARTITION_SELECT 0x1d0 +#define MC_CLIENT_HOTRESET_CTRL 0x200 +#define MC_CLIENT_HOTRESET_CTRL_1 0x970 +#define MC_CLIENT_HOTRESET_STATUS 0x204 +#define MC_CLIENT_HOTRESET_STATUS_1 0x974 +#define MC_EMEM_ARB_ISOCHRONOUS_0 0x208 +#define MC_EMEM_ARB_ISOCHRONOUS_1 0x20c +#define MC_EMEM_ARB_ISOCHRONOUS_2 0x210 +#define MC_EMEM_ARB_ISOCHRONOUS_3 0x214 +#define MC_EMEM_ARB_ISOCHRONOUS_4 0xb94 +#define MC_EMEM_ARB_HYSTERESIS_0 0x218 +#define MC_EMEM_ARB_HYSTERESIS_1 0x21c +#define MC_EMEM_ARB_HYSTERESIS_2 0x220 +#define MC_EMEM_ARB_HYSTERESIS_3 0x224 +#define MC_EMEM_ARB_HYSTERESIS_4 0xb84 +#define MC_EMEM_ARB_DHYSTERESIS_0 0xbb0 +#define MC_EMEM_ARB_DHYSTERESIS_1 0xbb4 +#define MC_EMEM_ARB_DHYSTERESIS_2 0xbb8 +#define MC_EMEM_ARB_DHYSTERESIS_3 0xbbc +#define MC_EMEM_ARB_DHYSTERESIS_4 0xbc0 +#define MC_EMEM_ARB_DHYST_CTRL 0xbcc +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_0 0xbd0 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_1 0xbd4 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_2 0xbd8 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_3 0xbdc +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_4 0xbe0 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_5 0xbe4 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_6 0xbe8 +#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xbec +#define MC_RESERVED_RSV 0x3fc +#define MC_DISB_EXTRA_SNAP_LEVELS 0x408 +#define MC_APB_EXTRA_SNAP_LEVELS 0x2a4 +#define MC_AHB_EXTRA_SNAP_LEVELS 0x2a0 +#define MC_USBD_EXTRA_SNAP_LEVELS 0xa18 +#define MC_ISP_EXTRA_SNAP_LEVELS 0xa08 +#define MC_AUD_EXTRA_SNAP_LEVELS 0xa10 +#define MC_MSE_EXTRA_SNAP_LEVELS 0x40c +#define MC_GK2_EXTRA_SNAP_LEVELS 0xa40 +#define MC_A9AVPPC_EXTRA_SNAP_LEVELS 0x414 +#define MC_FTOP_EXTRA_SNAP_LEVELS 0x2bc +#define MC_JPG_EXTRA_SNAP_LEVELS 0xa3c +#define MC_HOST_EXTRA_SNAP_LEVELS 0xa14 +#define MC_SAX_EXTRA_SNAP_LEVELS 0x2c0 +#define MC_DIS_EXTRA_SNAP_LEVELS 0x2ac +#define MC_VICPC_EXTRA_SNAP_LEVELS 0xa1c +#define MC_HDAPC_EXTRA_SNAP_LEVELS 0xa48 +#define MC_AVP_EXTRA_SNAP_LEVELS 0x2a8 +#define MC_USBX_EXTRA_SNAP_LEVELS 0x404 +#define MC_PCX_EXTRA_SNAP_LEVELS 0x2b8 +#define MC_SD_EXTRA_SNAP_LEVELS 0xa04 +#define MC_DFD_EXTRA_SNAP_LEVELS 0xa4c +#define MC_VE_EXTRA_SNAP_LEVELS 0x2d8 +#define MC_GK_EXTRA_SNAP_LEVELS 0xa00 +#define MC_VE2_EXTRA_SNAP_LEVELS 0x410 +#define MC_SDM_EXTRA_SNAP_LEVELS 0xa44 +#define MC_VIDEO_PROTECT_BOM 0x648 +#define MC_VIDEO_PROTECT_SIZE_MB 0x64c +#define MC_VIDEO_PROTECT_BOM_ADR_HI 0x978 +#define MC_VIDEO_PROTECT_REG_CTRL 0x650 +#define MC_ERR_VPR_STATUS 0x654 +#define MC_ERR_VPR_ADR 0x658 +#define MC_VIDEO_PROTECT_VPR_OVERRIDE 0x418 +#define MC_VIDEO_PROTECT_VPR_OVERRIDE1 0x590 +#define MC_IRAM_BOM 0x65c +#define MC_IRAM_TOM 0x660 +#define MC_IRAM_ADR_HI 0x980 +#define MC_IRAM_REG_CTRL 0x964 +#define MC_EMEM_CFG_ACCESS_CTRL 0x664 +#define MC_TZ_SECURITY_CTRL 0x668 +#define MC_EMEM_ARB_OUTSTANDING_REQ_RING3 0x66c +#define MC_EMEM_ARB_OUTSTANDING_REQ_NISO 0x6b4 +#define MC_EMEM_ARB_RING0_THROTTLE_MASK 0x6bc +#define MC_EMEM_ARB_NISO_THROTTLE_MASK 0x6b8 +#define MC_EMEM_ARB_NISO_THROTTLE_MASK_1 0xb80 +#define MC_SEC_CARVEOUT_BOM 0x670 +#define MC_SEC_CARVEOUT_SIZE_MB 0x674 +#define MC_SEC_CARVEOUT_ADR_HI 0x9d4 +#define MC_SEC_CARVEOUT_REG_CTRL 0x678 +#define MC_ERR_SEC_STATUS 0x67c +#define MC_ERR_SEC_ADR 0x680 +#define MC_PC_IDLE_CLOCK_GATE_CONFIG 0x684 +#define MC_STUTTER_CONTROL 0x688 +#define MC_RESERVED_RSV_1 0x958 +#define MC_DVFS_PIPE_SELECT 0x95c +#define MC_AHB_PTSA_MIN 0x4e0 +#define MC_AUD_PTSA_MIN 0x54c +#define MC_MLL_MPCORER_PTSA_RATE 0x44c +#define MC_RING2_PTSA_RATE 0x440 +#define MC_USBD_PTSA_RATE 0x530 +#define MC_USBX_PTSA_MIN 0x528 +#define MC_USBD_PTSA_MIN 0x534 +#define MC_APB_PTSA_MAX 0x4f0 +#define MC_JPG_PTSA_RATE 0x584 +#define MC_DIS_PTSA_MIN 0x420 +#define MC_AVP_PTSA_MAX 0x4fc +#define MC_AVP_PTSA_RATE 0x4f4 +#define MC_RING1_PTSA_MIN 0x480 +#define MC_DIS_PTSA_MAX 0x424 +#define MC_SD_PTSA_MAX 0x4d8 +#define MC_MSE_PTSA_RATE 0x4c4 +#define MC_VICPC_PTSA_MIN 0x558 +#define MC_PCX_PTSA_MAX 0x4b4 +#define MC_ISP_PTSA_RATE 0x4a0 +#define MC_A9AVPPC_PTSA_MIN 0x48c +#define MC_RING2_PTSA_MAX 0x448 +#define MC_AUD_PTSA_RATE 0x548 +#define MC_HOST_PTSA_MIN 0x51c +#define MC_MLL_MPCORER_PTSA_MAX 0x454 +#define MC_SD_PTSA_MIN 0x4d4 +#define MC_RING1_PTSA_RATE 0x47c +#define MC_JPG_PTSA_MIN 0x588 +#define MC_HDAPC_PTSA_MIN 0x62c +#define MC_AVP_PTSA_MIN 0x4f8 +#define MC_JPG_PTSA_MAX 0x58c +#define MC_VE_PTSA_MAX 0x43c +#define MC_DFD_PTSA_MAX 0x63c +#define MC_VICPC_PTSA_RATE 0x554 +#define MC_GK_PTSA_MAX 0x544 +#define MC_VICPC_PTSA_MAX 0x55c +#define MC_SDM_PTSA_MAX 0x624 +#define MC_SAX_PTSA_RATE 0x4b8 +#define MC_PCX_PTSA_MIN 0x4b0 +#define MC_APB_PTSA_MIN 0x4ec +#define MC_GK2_PTSA_MIN 0x614 +#define MC_PCX_PTSA_RATE 0x4ac +#define MC_RING1_PTSA_MAX 0x484 +#define MC_HDAPC_PTSA_RATE 0x628 +#define MC_MLL_MPCORER_PTSA_MIN 0x450 +#define MC_GK2_PTSA_MAX 0x618 +#define MC_AUD_PTSA_MAX 0x550 +#define MC_GK2_PTSA_RATE 0x610 +#define MC_ISP_PTSA_MAX 0x4a8 +#define MC_DISB_PTSA_RATE 0x428 +#define MC_VE2_PTSA_MAX 0x49c +#define MC_DFD_PTSA_MIN 0x638 +#define MC_FTOP_PTSA_RATE 0x50c +#define MC_A9AVPPC_PTSA_RATE 0x488 +#define MC_VE2_PTSA_MIN 0x498 +#define MC_USBX_PTSA_MAX 0x52c +#define MC_DIS_PTSA_RATE 0x41c +#define MC_USBD_PTSA_MAX 0x538 +#define MC_A9AVPPC_PTSA_MAX 0x490 +#define MC_USBX_PTSA_RATE 0x524 +#define MC_FTOP_PTSA_MAX 0x514 +#define MC_HDAPC_PTSA_MAX 0x630 +#define MC_SD_PTSA_RATE 0x4d0 +#define MC_DFD_PTSA_RATE 0x634 +#define MC_FTOP_PTSA_MIN 0x510 +#define MC_SDM_PTSA_RATE 0x61c +#define MC_AHB_PTSA_RATE 0x4dc +#define MC_SMMU_SMMU_PTSA_MAX 0x460 +#define MC_RING2_PTSA_MIN 0x444 +#define MC_SDM_PTSA_MIN 0x620 +#define MC_APB_PTSA_RATE 0x4e8 +#define MC_MSE_PTSA_MIN 0x4c8 +#define MC_HOST_PTSA_RATE 0x518 +#define MC_VE_PTSA_RATE 0x434 +#define MC_AHB_PTSA_MAX 0x4e4 +#define MC_SAX_PTSA_MIN 0x4bc +#define MC_SMMU_SMMU_PTSA_MIN 0x45c +#define MC_ISP_PTSA_MIN 0x4a4 +#define MC_HOST_PTSA_MAX 0x520 +#define MC_SAX_PTSA_MAX 0x4c0 +#define MC_VE_PTSA_MIN 0x438 +#define MC_GK_PTSA_MIN 0x540 +#define MC_MSE_PTSA_MAX 0x4cc +#define MC_DISB_PTSA_MAX 0x430 +#define MC_DISB_PTSA_MIN 0x42c +#define MC_SMMU_SMMU_PTSA_RATE 0x458 +#define MC_VE2_PTSA_RATE 0x494 +#define MC_GK_PTSA_RATE 0x53c +#define MC_PTSA_GRANT_DECREMENT 0x960 +#define MC_LATENCY_ALLOWANCE_AVPC_0 0x2e4 +#define MC_LATENCY_ALLOWANCE_AXIAP_0 0x3a0 +#define MC_LATENCY_ALLOWANCE_XUSB_1 0x380 +#define MC_LATENCY_ALLOWANCE_ISP2B_0 0x384 +#define MC_LATENCY_ALLOWANCE_SDMMCAA_0 0x3bc +#define MC_LATENCY_ALLOWANCE_SDMMCA_0 0x3b8 +#define MC_LATENCY_ALLOWANCE_ISP2_0 0x370 +#define MC_LATENCY_ALLOWANCE_SE_0 0x3e0 +#define MC_LATENCY_ALLOWANCE_ISP2_1 0x374 +#define MC_LATENCY_ALLOWANCE_DC_0 0x2e8 +#define MC_LATENCY_ALLOWANCE_VIC_0 0x394 +#define MC_LATENCY_ALLOWANCE_DCB_1 0x2f8 +#define MC_LATENCY_ALLOWANCE_NVDEC_0 0x3d8 +#define MC_LATENCY_ALLOWANCE_DCB_2 0x2fc +#define MC_LATENCY_ALLOWANCE_TSEC_0 0x390 +#define MC_LATENCY_ALLOWANCE_DC_2 0x2f0 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0AB 0x694 +#define MC_LATENCY_ALLOWANCE_PPCS_1 0x348 +#define MC_LATENCY_ALLOWANCE_XUSB_0 0x37c +#define MC_LATENCY_ALLOWANCE_PPCS_0 0x344 +#define MC_LATENCY_ALLOWANCE_TSECB_0 0x3f0 +#define MC_LATENCY_ALLOWANCE_AFI_0 0x2e0 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0B 0x698 +#define MC_LATENCY_ALLOWANCE_DC_1 0x2ec +#define MC_LATENCY_ALLOWANCE_APE_0 0x3dc +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0C 0x6a0 +#define MC_LATENCY_ALLOWANCE_A9AVP_0 0x3a4 +#define MC_LATENCY_ALLOWANCE_GPU2_0 0x3e8 +#define MC_LATENCY_ALLOWANCE_DCB_0 0x2f4 +#define MC_LATENCY_ALLOWANCE_HC_1 0x314 +#define MC_LATENCY_ALLOWANCE_SDMMC_0 0x3c0 +#define MC_LATENCY_ALLOWANCE_NVJPG_0 0x3e4 +#define MC_LATENCY_ALLOWANCE_PTC_0 0x34c +#define MC_LATENCY_ALLOWANCE_ETR_0 0x3ec +#define MC_LATENCY_ALLOWANCE_MPCORE_0 0x320 +#define MC_LATENCY_ALLOWANCE_VI2_0 0x398 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0BB 0x69c +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0CB 0x6a4 +#define MC_LATENCY_ALLOWANCE_SATA_0 0x350 +#define MC_SCALED_LATENCY_ALLOWANCE_DISPLAY0A 0x690 +#define MC_LATENCY_ALLOWANCE_HC_0 0x310 +#define MC_LATENCY_ALLOWANCE_DC_3 0x3c8 +#define MC_LATENCY_ALLOWANCE_GPU_0 0x3ac +#define MC_LATENCY_ALLOWANCE_SDMMCAB_0 0x3c4 +#define MC_LATENCY_ALLOWANCE_ISP2B_1 0x388 +#define MC_LATENCY_ALLOWANCE_NVENC_0 0x328 +#define MC_LATENCY_ALLOWANCE_HDA_0 0x318 +#define MC_MIN_LENGTH_APE_0 0xb34 +#define MC_MIN_LENGTH_DCB_2 0x8a8 +#define MC_MIN_LENGTH_A9AVP_0 0x950 +#define MC_MIN_LENGTH_TSEC_0 0x93c +#define MC_MIN_LENGTH_DC_1 0x898 +#define MC_MIN_LENGTH_AXIAP_0 0x94c +#define MC_MIN_LENGTH_ISP2B_0 0x930 +#define MC_MIN_LENGTH_VI2_0 0x944 +#define MC_MIN_LENGTH_DCB_0 0x8a0 +#define MC_MIN_LENGTH_DCB_1 0x8a4 +#define MC_MIN_LENGTH_PPCS_1 0x8f4 +#define MC_MIN_LENGTH_NVJPG_0 0xb3c +#define MC_MIN_LENGTH_HDA_0 0x8c4 +#define MC_MIN_LENGTH_NVENC_0 0x8d4 +#define MC_MIN_LENGTH_SDMMC_0 0xb18 +#define MC_MIN_LENGTH_ISP2B_1 0x934 +#define MC_MIN_LENGTH_HC_1 0x8c0 +#define MC_MIN_LENGTH_DC_3 0xb20 +#define MC_MIN_LENGTH_AVPC_0 0x890 +#define MC_MIN_LENGTH_VIC_0 0x940 +#define MC_MIN_LENGTH_ISP2_0 0x91c +#define MC_MIN_LENGTH_HC_0 0x8bc +#define MC_MIN_LENGTH_SE_0 0xb38 +#define MC_MIN_LENGTH_NVDEC_0 0xb30 +#define MC_MIN_LENGTH_SATA_0 0x8fc +#define MC_MIN_LENGTH_DC_0 0x894 +#define MC_MIN_LENGTH_XUSB_1 0x92c +#define MC_MIN_LENGTH_DC_2 0x89c +#define MC_MIN_LENGTH_SDMMCAA_0 0xb14 +#define MC_MIN_LENGTH_GPU_0 0xb04 +#define MC_MIN_LENGTH_ETR_0 0xb44 +#define MC_MIN_LENGTH_AFI_0 0x88c +#define MC_MIN_LENGTH_PPCS_0 0x8f0 +#define MC_MIN_LENGTH_ISP2_1 0x920 +#define MC_MIN_LENGTH_XUSB_0 0x928 +#define MC_MIN_LENGTH_MPCORE_0 0x8cc +#define MC_MIN_LENGTH_TSECB_0 0xb48 +#define MC_MIN_LENGTH_SDMMCA_0 0xb10 +#define MC_MIN_LENGTH_GPU2_0 0xb40 +#define MC_MIN_LENGTH_SDMMCAB_0 0xb1c +#define MC_MIN_LENGTH_PTC_0 0x8f8 +#define MC_EMEM_ARB_OVERRIDE_1 0x968 +#define MC_VIDEO_PROTECT_GPU_OVERRIDE_0 0x984 +#define MC_VIDEO_PROTECT_GPU_OVERRIDE_1 0x988 +#define MC_EMEM_ARB_STATS_0 0x990 +#define MC_EMEM_ARB_STATS_1 0x994 +#define MC_MTS_CARVEOUT_BOM 0x9a0 +#define MC_MTS_CARVEOUT_SIZE_MB 0x9a4 +#define MC_MTS_CARVEOUT_ADR_HI 0x9a8 +#define MC_MTS_CARVEOUT_REG_CTRL 0x9ac +#define MC_ERR_MTS_STATUS 0x9b0 +#define MC_ERR_MTS_ADR 0x9b4 +#define MC_ERR_GENERALIZED_CARVEOUT_STATUS 0xc00 +#define MC_ERR_GENERALIZED_CARVEOUT_ADR 0xc04 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2 0xd74 +#define MC_SECURITY_CARVEOUT4_CFG0 0xcf8 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2 0xd10 +#define MC_SECURITY_CARVEOUT4_SIZE_128KB 0xd04 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4 0xc28 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1 0xc30 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4 0xc8c +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0 0xd1c +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1 0xd70 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0 0xc2c +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4 0xd7c +#define MC_SECURITY_CARVEOUT3_SIZE_128KB 0xcb4 +#define MC_SECURITY_CARVEOUT2_CFG0 0xc58 +#define MC_SECURITY_CARVEOUT1_CFG0 0xc08 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2 0xc84 +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0 0xc68 +#define MC_SECURITY_CARVEOUT3_BOM 0xcac +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2 0xc70 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3 0xd78 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0 0xc7c +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4 0xd18 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1 0xcbc +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3 0xc38 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2 0xc34 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2 0xcc0 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2 0xd60 +#define MC_SECURITY_CARVEOUT3_CFG0 0xca8 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0 0xcb8 +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3 0xc88 +#define MC_SECURITY_CARVEOUT2_SIZE_128KB 0xc64 +#define MC_SECURITY_CARVEOUT5_BOM_HI 0xd50 +#define MC_SECURITY_CARVEOUT1_SIZE_128KB 0xc14 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3 0xd14 +#define MC_SECURITY_CARVEOUT1_BOM 0xc0c +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4 0xd2c +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4 0xd68 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4 0xcc8 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0 0xd58 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2 0xd24 +#define MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3 0xcc4 +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4 0xc78 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1 0xc1c +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0 0xc18 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3 0xd28 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1 0xd5c +#define MC_SECURITY_CARVEOUT3_BOM_HI 0xcb0 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3 0xcd8 +#define MC_SECURITY_CARVEOUT2_BOM_HI 0xc60 +#define MC_SECURITY_CARVEOUT4_BOM_HI 0xd00 +#define MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3 0xd64 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4 0xcdc +#define MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1 0xc80 +#define MC_SECURITY_CARVEOUT5_SIZE_128KB 0xd54 +#define MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1 0xd20 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2 0xcd4 +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1 0xd0c +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3 0xc74 +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0 0xccc +#define MC_SECURITY_CARVEOUT4_BOM 0xcfc +#define MC_SECURITY_CARVEOUT5_CFG0 0xd48 +#define MC_SECURITY_CARVEOUT2_BOM 0xc5c +#define MC_SECURITY_CARVEOUT5_BOM 0xd4c +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3 0xc24 +#define MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0 0xd6c +#define MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1 0xcd0 +#define MC_SECURITY_CARVEOUT1_BOM_HI 0xc10 +#define MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2 0xc20 +#define MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4 0xc3c +#define MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1 0xc6c +#define MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0 0xd08 +#define MC_ERR_APB_ASID_UPDATE_STATUS 0x9d0 +#define MC_DA_CONFIG0 0x9dc + +/* Memory Controller clients */ +#define CLIENT_ACCESS_NUM_CLIENTS 32 +typedef enum { + /* _ACCESS0 */ + CSR_PTCR = (0 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0A = (1 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0AB = (2 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0B = (3 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0BB = (4 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0C = (5 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAY0CB = (6 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AFIR = (14 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_AVPCARM7R = (15 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHC = (16 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_DISPLAYHCB = (17 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HDAR = (21 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XDMAR = (22 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_HOST1XR = (23 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_NVENCSRD = (28 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBDMAR = (29 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_PPCSAHBSLVR = (30 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + CSR_SATAR = (31 - (CLIENT_ACCESS_NUM_CLIENTS * 0)), + + /* _ACCESS1 */ + CSR_VDEBSEVR = (34 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMBER = (35 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDEMCER = (36 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_VDETPER = (37 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORELPR = (38 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSR_MPCORER = (39 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_NVENCSWR = (43 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AFIW = (49 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_AVPCARM7W = (50 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HDAW = (53 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_HOST1XW = (54 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCORELPW = (56 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_MPCOREW = (57 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBDMAW = (59 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_PPCSAHBSLVW = (60 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_SATAW = (61 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEBSEVW = (62 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + CSW_VDEDBGW = (63 - (CLIENT_ACCESS_NUM_CLIENTS * 1)), + + /* _ACCESS2 */ + CSW_VDEMBEW = (64 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_VDETPMW = (65 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRA = (68 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWA = (70 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWB = (71 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_HOSTR = (74 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_HOSTW = (75 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_XUSB_DEVR = (76 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_XUSB_DEVW = (77 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_ISPRAB = (78 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWAB = (80 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_ISPWBB = (81 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_TSECSRD = (84 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_TSECSWR = (85 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_A9AVPSCR = (86 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_A9AVPSCW = (87 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_GPUSRD = (88 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSW_GPUSWR = (89 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + CSR_DISPLAYT = (90 - (CLIENT_ACCESS_NUM_CLIENTS * 2)), + + /* _ACCESS3 */ + CSR_SDMMCRA = (96 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAA = (97 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCR = (98 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_SDMMCRAB = (99 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWA = (100 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAA = (101 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCW = (102 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_SDMMCWAB = (103 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_VICSRD = (108 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VICSWR = (109 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_VIW = (114 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_DISPLAYD = (115 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVDECSRD = (120 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVDECSWR = (121 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_APER = (122 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_APEW = (123 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSR_NVJPGSRD = (126 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + CSW_NVJPGSWR = (127 - (CLIENT_ACCESS_NUM_CLIENTS * 3)), + + /* _ACCESS4 */ + CSR_SESRD = (128 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_SESWR = (129 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_AXIAPR = (130 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_AXIAPW = (131 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_ETRR = (132 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_ETRW = (133 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_TSECSRDB = (134 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_TSECSWRB = (135 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSR_GPUSRD2 = (136 - (CLIENT_ACCESS_NUM_CLIENTS * 4)), + CSW_GPUSWR2 = (137 - (CLIENT_ACCESS_NUM_CLIENTS * 4)) +} McClient; + +void mc_config_tsec_carveout(uint32_t bom, uint32_t size1mb, bool lock); +void mc_config_carveout(); +void mc_config_carveout_finalize(); +void mc_enable_ahb_redirect(); +void mc_disable_ahb_redirect(); +void mc_enable(); + +#endif \ No newline at end of file diff --git a/sept/sept-secondary/src/panic.c b/sept/sept-secondary/src/panic.c new file mode 100644 index 000000000..d8f298470 --- /dev/null +++ b/sept/sept-secondary/src/panic.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "panic.h" +#include "di.h" +#include "pmc.h" +#include "fuse.h" +#include "utils.h" + +static uint32_t g_panic_code = 0; + +void check_and_display_panic(void) { + /* We also handle our own panics. */ + /* In the case of our own panics, we assume that the display has already been initialized. */ + bool has_panic = APBDEV_PMC_RST_STATUS_0 != 0 || g_panic_code != 0; + uint32_t code = g_panic_code == 0 ? APBDEV_PMC_SCRATCH200_0 : g_panic_code; + + has_panic = has_panic && !(APBDEV_PMC_RST_STATUS_0 != 1 && code == PANIC_CODE_SAFEMODE); + + if (has_panic) { + uint32_t color; + + /* Check for predefined codes: */ + switch (code & MASK(20)) { + case 0x01: /* Package2 signature verification failed. */ + case 0x02: /* Package2 meta verification failed. */ + case 0x03: /* Package2 version check failed. */ + case 0x04: /* Package2 payload verification failed. */ + color = PANIC_COLOR_KERNEL; + break; + case 0x05: /* Unknown SMC. */ + case 0x06: /* Unknown Abort. */ + color = PANIC_COLOR_SECMON_GENERIC; + break; + case 0x07: /* Invalid CPU context. */ + case 0x08: /* Invalid SE state. */ + case 0x09: /* CPU is already awake (2.0.0+). */ + color = PANIC_COLOR_SECMON_DEEPSLEEP; + break; + case 0x10: /* Unknown exception. */ + color = PANIC_COLOR_SECMON_EXCEPTION; + break; + case 0x30: /* General bootloader error. */ + case 0x31: /* Invalid DRAM ID. */ + case 0x32: /* Invalid size. */ + case 0x33: /* Invalid arguement. */ + case 0x34: /* Bad GPT. */ + case 0x35: /* Failed to boot SafeMode. */ + case 0x36: /* Activity monitor fired (4.0.0+). */ + color = PANIC_COLOR_BOOTLOADER_GENERIC; + break; + case 0x40: /* Kernel panic. */ + color = PANIC_COLOR_KERNEL; + break; + default: + color = code >> 20; + color |= color << 4; + break; + } + + if (g_panic_code == 0) { + display_init(); + } + + display_color_screen(color); + wait_for_button_and_reboot(); + } else { + g_panic_code = 0; + APBDEV_PMC_SCRATCH200_0 = 0; + } +} + +__attribute__ ((noreturn)) void panic(uint32_t code) { + /* Set panic code. */ + if (g_panic_code == 0) { + g_panic_code = code; + APBDEV_PMC_SCRATCH200_0 = code; + } + + fuse_disable_programming(); + APBDEV_PMC_CRYPTO_OP_0 = 1; /* Disable all SE operations. */ + + check_and_display_panic(); + while(true); +} diff --git a/sept/sept-secondary/src/panic.h b/sept/sept-secondary/src/panic.h new file mode 100644 index 000000000..78ea67fb6 --- /dev/null +++ b/sept/sept-secondary/src/panic.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_PANIC_H +#define FUSEE_PANIC_H + +#include <stdint.h> + +#define PANIC_COLOR_KERNEL 0x0000FF +#define PANIC_COLOR_SECMON_EXCEPTION 0xFF7700 +#define PANIC_COLOR_SECMON_GENERIC 0x00FFFF +#define PANIC_COLOR_SECMON_DEEPSLEEP 0xFF77FF /* 4.0+ color */ +#define PANIC_COLOR_BOOTLOADER_GENERIC 0xAA00FF +#define PANIC_COLOR_BOOTLOADER_SAFEMODE 0xFFFFAA /* Removed */ + +#define PANIC_CODE_SAFEMODE 0x00000020 + +void check_and_display_panic(void); +__attribute__ ((noreturn)) void panic(uint32_t code); + +#endif diff --git a/sept/sept-secondary/src/panic_color.h b/sept/sept-secondary/src/panic_color.h new file mode 100644 index 000000000..68b00bf19 --- /dev/null +++ b/sept/sept-secondary/src/panic_color.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_PANIC_COLOR_H +#define FUSEE_PANIC_COLOR_H + +#define COLOR_0 0x00F00003 +#define COLOR_1 0x0F000003 +#define COLOR_2 0xF0000003 +#define COLOR_3 0x0FF00003 +#define COLOR_4 0xF0F00003 +#define COLOR_5 0xFF000003 +#define COLOR_6 0xFFF00003 +#define COLOR_7 0xAAF00003 +#define COLOR_8 0xAFA00003 +#define COLOR_9 0xFAA00003 +#define COLOR_A 0x33300003 +#define COLOR_B 0x06F00003 +#define COLOR_C 0x14800003 +#define COLOR_D 0x00300003 +#define COLOR_E 0x03000003 +#define COLOR_F 0xB6000003 + +#define PANIC_REBOOT 0x20 + +#endif \ No newline at end of file diff --git a/sept/sept-secondary/src/pinmux.h b/sept/sept-secondary/src/pinmux.h new file mode 100644 index 000000000..3912143eb --- /dev/null +++ b/sept/sept-secondary/src/pinmux.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_PINMUX_H +#define FUSEE_PINMUX_H + +#define PINMUX_BASE 0x70003000 +#define MAKE_PINMUX_REG(n) MAKE_REG32(PINMUX_BASE + n) + +#define PINMUX_TRISTATE (1 << 4) +#define PINMUX_PARKED (1 << 5) +#define PINMUX_INPUT (1 << 6) +#define PINMUX_PULL_NONE (0 << 2) +#define PINMUX_PULL_DOWN (1 << 2) +#define PINMUX_PULL_UP (2 << 2) +#define PINMUX_SELECT_FUNCTION0 0 +#define PINMUX_SELECT_FUNCTION1 1 +#define PINMUX_SELECT_FUNCTION2 2 +#define PINMUX_SELECT_FUNCTION3 3 +#define PINMUX_DRIVE_1X (0 << 13) +#define PINMUX_DRIVE_2X (1 << 13) +#define PINMUX_DRIVE_3X (2 << 13) +#define PINMUX_DRIVE_4X (3 << 13) + +typedef struct { + uint32_t sdmmc1_clk; + uint32_t sdmmc1_cmd; + uint32_t sdmmc1_dat3; + uint32_t sdmmc1_dat2; + uint32_t sdmmc1_dat1; + uint32_t sdmmc1_dat0; + uint32_t _r18; + uint32_t sdmmc3_clk; + uint32_t sdmmc3_cmd; + uint32_t sdmmc3_dat0; + uint32_t sdmmc3_dat1; + uint32_t sdmmc3_dat2; + uint32_t sdmmc3_dat3; + uint32_t _r34; + uint32_t pex_l0_rst_n; + uint32_t pex_l0_clkreq_n; + uint32_t pex_wake_n; + uint32_t pex_l1_rst_n; + uint32_t pex_l1_clkreq_n; + uint32_t sata_led_active; + uint32_t spi1_mosi; + uint32_t spi1_miso; + uint32_t spi1_sck; + uint32_t spi1_cs0; + uint32_t spi1_cs1; + uint32_t spi2_mosi; + uint32_t spi2_miso; + uint32_t spi2_sck; + uint32_t spi2_cs0; + uint32_t spi2_cs1; + uint32_t spi4_mosi; + uint32_t spi4_miso; + uint32_t spi4_sck; + uint32_t spi4_cs0; + uint32_t qspi_sck; + uint32_t qspi_cs_n; + uint32_t qspi_io0; + uint32_t qspi_io1; + uint32_t qspi_io2; + uint32_t qspi_io3; + uint32_t _ra0; + uint32_t dmic1_clk; + uint32_t dmic1_dat; + uint32_t dmic2_clk; + uint32_t dmic2_dat; + uint32_t dmic3_clk; + uint32_t dmic3_dat; + uint32_t gen1_i2c_scl; + uint32_t gen1_i2c_sda; + uint32_t gen2_i2c_scl; + uint32_t gen2_i2c_sda; + uint32_t gen3_i2c_scl; + uint32_t gen3_i2c_sda; + uint32_t cam_i2c_scl; + uint32_t cam_i2c_sda; + uint32_t pwr_i2c_scl; + uint32_t pwr_i2c_sda; + uint32_t uart1_tx; + uint32_t uart1_rx; + uint32_t uart1_rts; + uint32_t uart1_cts; + uint32_t uart2_tx; + uint32_t uart2_rx; + uint32_t uart2_rts; + uint32_t uart2_cts; + uint32_t uart3_tx; + uint32_t uart3_rx; + uint32_t uart3_rts; + uint32_t uart3_cts; + uint32_t uart4_tx; + uint32_t uart4_rx; + uint32_t uart4_rts; + uint32_t uart4_cts; + uint32_t dap1_fs; + uint32_t dap1_din; + uint32_t dap1_dout; + uint32_t dap1_sclk; + uint32_t dap2_fs; + uint32_t dap2_din; + uint32_t dap2_dout; + uint32_t dap2_sclk; + uint32_t dap4_fs; + uint32_t dap4_din; + uint32_t dap4_dout; + uint32_t dap4_sclk; + uint32_t cam1_mclk; + uint32_t cam2_mclk; + uint32_t jtag_rtck; + uint32_t clk_32k_in; + uint32_t clk_32k_out; + uint32_t batt_bcl; + uint32_t clk_req; + uint32_t cpu_pwr_req; + uint32_t pwr_int_n; + uint32_t shutdown; + uint32_t core_pwr_req; + uint32_t aud_mclk; + uint32_t dvfs_pwm; + uint32_t dvfs_clk; + uint32_t gpio_x1_aud; + uint32_t gpio_x3_aud; + uint32_t pcc7; + uint32_t hdmi_cec; + uint32_t hdmi_int_dp_hpd; + uint32_t spdif_out; + uint32_t spdif_in; + uint32_t usb_vbus_en0; + uint32_t usb_vbus_en1; + uint32_t dp_hpd0; + uint32_t wifi_en; + uint32_t wifi_rst; + uint32_t wifi_wake_ap; + uint32_t ap_wake_bt; + uint32_t bt_rst; + uint32_t bt_wake_ap; + uint32_t ap_wake_nfc; + uint32_t nfc_en; + uint32_t nfc_int; + uint32_t gps_en; + uint32_t gps_rst; + uint32_t cam_rst; + uint32_t cam_af_en; + uint32_t cam_flash_en; + uint32_t cam1_pwdn; + uint32_t cam2_pwdn; + uint32_t cam1_strobe; + uint32_t lcd_te; + uint32_t lcd_bl_pwm; + uint32_t lcd_bl_en; + uint32_t lcd_rst; + uint32_t lcd_gpio1; + uint32_t lcd_gpio2; + uint32_t ap_ready; + uint32_t touch_rst; + uint32_t touch_clk; + uint32_t modem_wake_ap; + uint32_t touch_int; + uint32_t motion_int; + uint32_t als_prox_int; + uint32_t temp_alert; + uint32_t button_power_on; + uint32_t button_vol_up; + uint32_t button_vol_down; + uint32_t button_slide_sw; + uint32_t button_home; + uint32_t pa6; + uint32_t pe6; + uint32_t pe7; + uint32_t ph6; + uint32_t pk0; + uint32_t pk1; + uint32_t pk2; + uint32_t pk3; + uint32_t pk4; + uint32_t pk5; + uint32_t pk6; + uint32_t pk7; + uint32_t pl0; + uint32_t pl1; + uint32_t pz0; + uint32_t pz1; + uint32_t pz2; + uint32_t pz3; + uint32_t pz4; + uint32_t pz5; +} tegra_pinmux_t; + +static inline volatile tegra_pinmux_t *pinmux_get_regs(void) +{ + return (volatile tegra_pinmux_t *)PINMUX_BASE; +} + +#endif diff --git a/sept/sept-secondary/src/pmc.h b/sept/sept-secondary/src/pmc.h new file mode 100644 index 000000000..80c36da7f --- /dev/null +++ b/sept/sept-secondary/src/pmc.h @@ -0,0 +1,626 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_PMC_H +#define FUSEE_PMC_H + +#include <stdint.h> + +#define PMC_BASE 0x7000E400 +#define MAKE_PMC_REG(n) MAKE_REG32(PMC_BASE + n) + +#define PMC_CONTROL_SDMMC1 (1 << 12) +#define PMC_CONTROL_SDMMC3 (1 << 13) +#define PMC_CONTROL_SDMMC4 (1 << 14) + +#define APBDEV_PMC_CONTROL MAKE_PMC_REG(0x00) +#define APBDEV_PM_0 MAKE_PMC_REG(0x14) +#define APBDEV_PMC_DPD_ENABLE_0 MAKE_PMC_REG(0x24) +#define APBDEV_PMC_PWRGATE_TOGGLE_0 MAKE_PMC_REG(0x30) +#define APBDEV_PMC_PWRGATE_STATUS_0 MAKE_PMC_REG(0x38) +#define APBDEV_PMC_NO_IOPOWER_0 MAKE_PMC_REG(0x44) +#define APBDEV_PMC_SCRATCH0_0 MAKE_PMC_REG(0x50) +#define APBDEV_PMC_SCRATCH1_0 MAKE_PMC_REG(0x54) +#define APBDEV_PMC_SCRATCH20_0 MAKE_PMC_REG(0xA0) +#define APBDEV_PMC_PWR_DET_VAL_0 MAKE_PMC_REG(0xE4) +#define APBDEV_PMC_DDR_PWR_0 MAKE_PMC_REG(0xE8) +#define APBDEV_PMC_CRYPTO_OP_0 MAKE_PMC_REG(0xF4) +#define APBDEV_PMC_WAKE2_STATUS_0 MAKE_PMC_REG(0x168) +#define APBDEV_PMC_OSC_EDPD_OVER_0 MAKE_PMC_REG(0x1A4) +#define APBDEV_PMC_RST_STATUS_0 MAKE_PMC_REG(0x1B4) +#define APBDEV_PMC_IO_DPD_REQ_0 MAKE_PMC_REG(0x1B8) +#define APBDEV_PMC_IO_DPD2_REQ_0 MAKE_PMC_REG(0x1C0) +#define APBDEV_PMC_VDDP_SEL_0 MAKE_PMC_REG(0x1CC) +#define APBDEV_PMC_SCRATCH49_0 MAKE_PMC_REG(0x244) +#define APBDEV_PMC_TSC_MULT_0 MAKE_PMC_REG(0x2B4) +#define APBDEV_PMC_REG_SHORT_0 MAKE_PMC_REG(0x2CC) +#define APBDEV_PMC_WEAK_BIAS_0 MAKE_PMC_REG(0x2C8) +#define APBDEV_PMC_SECURE_SCRATCH21_0 MAKE_PMC_REG(0x334) +#define APBDEV_PMC_SECURE_SCRATCH32_0 MAKE_PMC_REG(0x360) +#define APBDEV_PMC_SECURE_SCRATCH49_0 MAKE_PMC_REG(0x3A4) +#define APBDEV_PMC_CNTRL2_0 MAKE_PMC_REG(0x440) +#define APBDEV_PMC_IO_DPD4_REQ_0 MAKE_PMC_REG(0x464) +#define APBDEV_PMC_UTMIP_PAD_CFG1_0 MAKE_PMC_REG(0x4C4) +#define APBDEV_PMC_UTMIP_PAD_CFG3_0 MAKE_PMC_REG(0x4CC) +#define APBDEV_PMC_DDR_CNTRL_0 MAKE_PMC_REG(0x4E4) +#define APBDEV_PMC_SCRATCH43_0 MAKE_PMC_REG(0x22C) +#define APBDEV_PMC_SCRATCH188_0 MAKE_PMC_REG(0x810) +#define APBDEV_PMC_SCRATCH190_0 MAKE_PMC_REG(0x818) +#define APBDEV_PMC_SCRATCH200_0 MAKE_PMC_REG(0x840) + +#define APBDEV_PMC_SCRATCH45_0 MAKE_PMC_REG(0x234) +#define APBDEV_PMC_SCRATCH46_0 MAKE_PMC_REG(0x238) +#define APBDEV_PMC_SCRATCH33_0 MAKE_PMC_REG(0x120) +#define APBDEV_PMC_SCRATCH40_0 MAKE_PMC_REG(0x13C) + +typedef struct { + uint32_t cntrl; + uint32_t sec_disable; + uint32_t pmc_swrst; + uint32_t wake_mask; + uint32_t wake_lvl; + uint32_t wake_status; + uint32_t sw_wake_status; + uint32_t dpd_pads_oride; + uint32_t dpd_sample; + uint32_t dpd_enable; + uint32_t pwrgate_timer_off; + uint32_t clamp_status; + uint32_t pwrgate_toggle; + uint32_t remove_clamping; + uint32_t pwrgate_status; + uint32_t pwrgood_timer; + uint32_t blink_timer; + uint32_t no_iopower; + uint32_t pwr_det; + uint32_t pwr_det_latch; + uint32_t scratch0; + uint32_t scratch1; + uint32_t scratch2; + uint32_t scratch3; + uint32_t scratch4; + uint32_t scratch5; + uint32_t scratch6; + uint32_t scratch7; + uint32_t scratch8; + uint32_t scratch9; + uint32_t scratch10; + uint32_t scratch11; + uint32_t scratch12; + uint32_t scratch13; + uint32_t scratch14; + uint32_t scratch15; + uint32_t scratch16; + uint32_t scratch17; + uint32_t scratch18; + uint32_t scratch19; + uint32_t scratch20; + uint32_t scratch21; + uint32_t scratch22; + uint32_t scratch23; + uint32_t secure_scratch0; + uint32_t secure_scratch1; + uint32_t secure_scratch2; + uint32_t secure_scratch3; + uint32_t secure_scratch4; + uint32_t secure_scratch5; + uint32_t cpupwrgood_timer; + uint32_t cpupwroff_timer; + uint32_t pg_mask; + uint32_t pg_mask_1; + uint32_t auto_wake_lvl; + uint32_t auto_wake_lvl_mask; + uint32_t wake_delay; + uint32_t pwr_det_val; + uint32_t ddr_pwr; + uint32_t usb_debounce_del; + uint32_t usb_ao; + uint32_t crypto_op; + uint32_t pllp_wb0_override; + uint32_t scratch24; + uint32_t scratch25; + uint32_t scratch26; + uint32_t scratch27; + uint32_t scratch28; + uint32_t scratch29; + uint32_t scratch30; + uint32_t scratch31; + uint32_t scratch32; + uint32_t scratch33; + uint32_t scratch34; + uint32_t scratch35; + uint32_t scratch36; + uint32_t scratch37; + uint32_t scratch38; + uint32_t scratch39; + uint32_t scratch40; + uint32_t scratch41; + uint32_t scratch42; + uint32_t bo_mirror0; + uint32_t bo_mirror1; + uint32_t bo_mirror2; + uint32_t sys_33v_en; + uint32_t bo_mirror_access; + uint32_t gate; + uint32_t wake2_mask; + uint32_t wake2_lvl; + uint32_t wake2_stat; + uint32_t sw_wake2_stat; + uint32_t auto_wake2_lvl_mask; + uint32_t pg_mask2; + uint32_t pg_mask_ce1; + uint32_t pg_mask_ce2; + uint32_t pg_mask_ce3; + uint32_t pwrgate_timer_ce0; + uint32_t pwrgate_timer_ce1; + uint32_t pwrgate_timer_ce2; + uint32_t pwrgate_timer_ce3; + uint32_t pwrgate_timer_ce4; + uint32_t pwrgate_timer_ce5; + uint32_t pwrgate_timer_ce6; + uint32_t pcx_edpd_cntrl; + uint32_t osc_edpd_over; + uint32_t clk_out_cntrl; + uint32_t sata_pwrgate; + uint32_t sensor_ctrl; + uint32_t reset_status; + uint32_t io_dpd_req; + uint32_t io_dpd_stat; + uint32_t io_dpd2_req; + uint32_t io_dpd2_stat; + uint32_t sel_dpd_tim; + uint32_t vddp_sel; + uint32_t ddr_cfg; + uint32_t e_no_vttgen; + uint32_t _reserved0; + uint32_t pllm_wb0_ovrride_frq; + uint32_t test_pwrgate; + uint32_t pwrgate_timer_mult; + uint32_t dsi_sel_dpd; + uint32_t utmip_uhsic_triggers; + uint32_t utmip_uhsic_saved_st; + uint32_t utmip_pad_cfg; + uint32_t utmip_term_pad_cfg; + uint32_t utmip_uhsic_sleep_cfg; + uint32_t utmip_uhsic_sleepwalk_cfg; + uint32_t utmip_sleepwalk_p[3]; + uint32_t uhsic_sleepwalk_p0; + uint32_t utmip_uhsic_status; + uint32_t utmip_uhsic_fake; + uint32_t bo_mirror3[2]; + uint32_t secure_scratch6; + uint32_t secure_scratch7; + uint32_t scratch43; + uint32_t scratch44; + uint32_t scratch45; + uint32_t scratch46; + uint32_t scratch47; + uint32_t scratch48; + uint32_t scratch49; + uint32_t scratch50; + uint32_t scratch51; + uint32_t scratch52; + uint32_t scratch53; + uint32_t scratch54; + uint32_t scratch55; + uint32_t scratch0_eco; + uint32_t por_dpd_ctrl; + uint32_t scratch2_eco; + uint32_t utmip_uhsic_line_wakeup; + uint32_t utmip_bias_master_cntrl; + uint32_t utmip_master_config; + uint32_t td_pwrgate_inter_part_timer; + uint32_t utmip_uhsic2_triggers; + uint32_t utmip_uhsic2_saved_state; + uint32_t utmip_uhsic2_sleep_cfg; + uint32_t utmip_uhsic2_sleepwalk_cfg; + uint32_t uhsic2_sleepwalk_p1; + uint32_t utmip_uhsic2_status; + uint32_t utmip_uhsic2_fake; + uint32_t utmip_uhsic2_line_wakeup; + uint32_t utmip_master2_config; + uint32_t utmip_uhsic_rpd_cfg; + uint32_t pg_mask_ce0; + uint32_t pg_mask3[2]; + uint32_t pllm_wb0_override2; + uint32_t tsc_mult; + uint32_t cpu_vsense_override; + uint32_t glb_amap_cfg; + uint32_t sticky_bits; + uint32_t sec_disable2; + uint32_t weak_bias; + uint32_t reg_short; + uint32_t pg_mask_andor; + uint32_t _reserved1[11]; + uint32_t secure_scratch8; + uint32_t secure_scratch9; + uint32_t secure_scratch10; + uint32_t secure_scratch11; + uint32_t secure_scratch12; + uint32_t secure_scratch13; + uint32_t secure_scratch14; + uint32_t secure_scratch15; + uint32_t secure_scratch16; + uint32_t secure_scratch17; + uint32_t secure_scratch18; + uint32_t secure_scratch19; + uint32_t secure_scratch20; + uint32_t secure_scratch21; + uint32_t secure_scratch22; + uint32_t secure_scratch23; + uint32_t secure_scratch24; + uint32_t secure_scratch25; + uint32_t secure_scratch26; + uint32_t secure_scratch27; + uint32_t secure_scratch28; + uint32_t secure_scratch29; + uint32_t secure_scratch30; + uint32_t secure_scratch31; + uint32_t secure_scratch32; + uint32_t secure_scratch33; + uint32_t secure_scratch34; + uint32_t secure_scratch35; + uint32_t secure_scratch36; + uint32_t secure_scratch37; + uint32_t secure_scratch38; + uint32_t secure_scratch39; + uint32_t secure_scratch40; + uint32_t secure_scratch41; + uint32_t secure_scratch42; + uint32_t secure_scratch43; + uint32_t secure_scratch44; + uint32_t secure_scratch45; + uint32_t secure_scratch46; + uint32_t secure_scratch47; + uint32_t secure_scratch48; + uint32_t secure_scratch49; + uint32_t secure_scratch50; + uint32_t secure_scratch51; + uint32_t secure_scratch52; + uint32_t secure_scratch53; + uint32_t secure_scratch54; + uint32_t secure_scratch55; + uint32_t secure_scratch56; + uint32_t secure_scratch57; + uint32_t secure_scratch58; + uint32_t secure_scratch59; + uint32_t secure_scratch60; + uint32_t secure_scratch61; + uint32_t secure_scratch62; + uint32_t secure_scratch63; + uint32_t secure_scratch64; + uint32_t secure_scratch65; + uint32_t secure_scratch66; + uint32_t secure_scratch67; + uint32_t secure_scratch68; + uint32_t secure_scratch69; + uint32_t secure_scratch70; + uint32_t secure_scratch71; + uint32_t secure_scratch72; + uint32_t secure_scratch73; + uint32_t secure_scratch74; + uint32_t secure_scratch75; + uint32_t secure_scratch76; + uint32_t secure_scratch77; + uint32_t secure_scratch78; + uint32_t secure_scratch79; + uint32_t _reserved2[8]; + uint32_t cntrl2; + uint32_t _reserved3[2]; + uint32_t event_counter; + uint32_t fuse_control; + uint32_t scratch1_eco; + uint32_t _reserved4; + uint32_t io_dpd3_req; + uint32_t io_dpd3_status; + uint32_t io_dpd4_req; + uint32_t io_dpd4_status; + uint32_t _reserved5[30]; + uint32_t ddr_cntrl; + uint32_t _reserved6[70]; + uint32_t scratch56; + uint32_t scratch57; + uint32_t scratch58; + uint32_t scratch59; + uint32_t scratch60; + uint32_t scratch61; + uint32_t scratch62; + uint32_t scratch63; + uint32_t scratch64; + uint32_t scratch65; + uint32_t scratch66; + uint32_t scratch67; + uint32_t scratch68; + uint32_t scratch69; + uint32_t scratch70; + uint32_t scratch71; + uint32_t scratch72; + uint32_t scratch73; + uint32_t scratch74; + uint32_t scratch75; + uint32_t scratch76; + uint32_t scratch77; + uint32_t scratch78; + uint32_t scratch79; + uint32_t scratch80; + uint32_t scratch81; + uint32_t scratch82; + uint32_t scratch83; + uint32_t scratch84; + uint32_t scratch85; + uint32_t scratch86; + uint32_t scratch87; + uint32_t scratch88; + uint32_t scratch89; + uint32_t scratch90; + uint32_t scratch91; + uint32_t scratch92; + uint32_t scratch93; + uint32_t scratch94; + uint32_t scratch95; + uint32_t scratch96; + uint32_t scratch97; + uint32_t scratch98; + uint32_t scratch99; + uint32_t scratch100; + uint32_t scratch101; + uint32_t scratch102; + uint32_t scratch103; + uint32_t scratch104; + uint32_t scratch105; + uint32_t scratch106; + uint32_t scratch107; + uint32_t scratch108; + uint32_t scratch109; + uint32_t scratch110; + uint32_t scratch111; + uint32_t scratch112; + uint32_t scratch113; + uint32_t scratch114; + uint32_t scratch115; + uint32_t scratch116; + uint32_t scratch117; + uint32_t scratch118; + uint32_t scratch119; + uint32_t scratch120; + uint32_t scratch121; + uint32_t scratch122; + uint32_t scratch123; + uint32_t scratch124; + uint32_t scratch125; + uint32_t scratch126; + uint32_t scratch127; + uint32_t scratch128; + uint32_t scratch129; + uint32_t scratch130; + uint32_t scratch131; + uint32_t scratch132; + uint32_t scratch133; + uint32_t scratch134; + uint32_t scratch135; + uint32_t scratch136; + uint32_t scratch137; + uint32_t scratch138; + uint32_t scratch139; + uint32_t scratch140; + uint32_t scratch141; + uint32_t scratch142; + uint32_t scratch143; + uint32_t scratch144; + uint32_t scratch145; + uint32_t scratch146; + uint32_t scratch147; + uint32_t scratch148; + uint32_t scratch149; + uint32_t scratch150; + uint32_t scratch151; + uint32_t scratch152; + uint32_t scratch153; + uint32_t scratch154; + uint32_t scratch155; + uint32_t scratch156; + uint32_t scratch157; + uint32_t scratch158; + uint32_t scratch159; + uint32_t scratch160; + uint32_t scratch161; + uint32_t scratch162; + uint32_t scratch163; + uint32_t scratch164; + uint32_t scratch165; + uint32_t scratch166; + uint32_t scratch167; + uint32_t scratch168; + uint32_t scratch169; + uint32_t scratch170; + uint32_t scratch171; + uint32_t scratch172; + uint32_t scratch173; + uint32_t scratch174; + uint32_t scratch175; + uint32_t scratch176; + uint32_t scratch177; + uint32_t scratch178; + uint32_t scratch179; + uint32_t scratch180; + uint32_t scratch181; + uint32_t scratch182; + uint32_t scratch183; + uint32_t scratch184; + uint32_t scratch185; + uint32_t scratch186; + uint32_t scratch187; + uint32_t scratch188; + uint32_t scratch189; + uint32_t scratch190; + uint32_t scratch191; + uint32_t scratch192; + uint32_t scratch193; + uint32_t scratch194; + uint32_t scratch195; + uint32_t scratch196; + uint32_t scratch197; + uint32_t scratch198; + uint32_t scratch199; + uint32_t scratch200; + uint32_t scratch201; + uint32_t scratch202; + uint32_t scratch203; + uint32_t scratch204; + uint32_t scratch205; + uint32_t scratch206; + uint32_t scratch207; + uint32_t scratch208; + uint32_t scratch209; + uint32_t scratch210; + uint32_t scratch211; + uint32_t scratch212; + uint32_t scratch213; + uint32_t scratch214; + uint32_t scratch215; + uint32_t scratch216; + uint32_t scratch217; + uint32_t scratch218; + uint32_t scratch219; + uint32_t scratch220; + uint32_t scratch221; + uint32_t scratch222; + uint32_t scratch223; + uint32_t scratch224; + uint32_t scratch225; + uint32_t scratch226; + uint32_t scratch227; + uint32_t scratch228; + uint32_t scratch229; + uint32_t scratch230; + uint32_t scratch231; + uint32_t scratch232; + uint32_t scratch233; + uint32_t scratch234; + uint32_t scratch235; + uint32_t scratch236; + uint32_t scratch237; + uint32_t scratch238; + uint32_t scratch239; + uint32_t scratch240; + uint32_t scratch241; + uint32_t scratch242; + uint32_t scratch243; + uint32_t scratch244; + uint32_t scratch245; + uint32_t scratch246; + uint32_t scratch247; + uint32_t scratch248; + uint32_t scratch249; + uint32_t scratch250; + uint32_t scratch251; + uint32_t scratch252; + uint32_t scratch253; + uint32_t scratch254; + uint32_t scratch255; + uint32_t scratch256; + uint32_t scratch257; + uint32_t scratch258; + uint32_t scratch259; + uint32_t scratch260; + uint32_t scratch261; + uint32_t scratch262; + uint32_t scratch263; + uint32_t scratch264; + uint32_t scratch265; + uint32_t scratch266; + uint32_t scratch267; + uint32_t scratch268; + uint32_t scratch269; + uint32_t scratch270; + uint32_t scratch271; + uint32_t scratch272; + uint32_t scratch273; + uint32_t scratch274; + uint32_t scratch275; + uint32_t scratch276; + uint32_t scratch277; + uint32_t scratch278; + uint32_t scratch279; + uint32_t scratch280; + uint32_t scratch281; + uint32_t scratch282; + uint32_t scratch283; + uint32_t scratch284; + uint32_t scratch285; + uint32_t scratch286; + uint32_t scratch287; + uint32_t scratch288; + uint32_t scratch289; + uint32_t scratch290; + uint32_t scratch291; + uint32_t scratch292; + uint32_t scratch293; + uint32_t scratch294; + uint32_t scratch295; + uint32_t scratch296; + uint32_t scratch297; + uint32_t scratch298; + uint32_t scratch299; + uint32_t _reserved7[50]; + uint32_t secure_scratch80; + uint32_t secure_scratch81; + uint32_t secure_scratch82; + uint32_t secure_scratch83; + uint32_t secure_scratch84; + uint32_t secure_scratch85; + uint32_t secure_scratch86; + uint32_t secure_scratch87; + uint32_t secure_scratch88; + uint32_t secure_scratch89; + uint32_t secure_scratch90; + uint32_t secure_scratch91; + uint32_t secure_scratch92; + uint32_t secure_scratch93; + uint32_t secure_scratch94; + uint32_t secure_scratch95; + uint32_t secure_scratch96; + uint32_t secure_scratch97; + uint32_t secure_scratch98; + uint32_t secure_scratch99; + uint32_t secure_scratch100; + uint32_t secure_scratch101; + uint32_t secure_scratch102; + uint32_t secure_scratch103; + uint32_t secure_scratch104; + uint32_t secure_scratch105; + uint32_t secure_scratch106; + uint32_t secure_scratch107; + uint32_t secure_scratch108; + uint32_t secure_scratch109; + uint32_t secure_scratch110; + uint32_t secure_scratch111; + uint32_t secure_scratch112; + uint32_t secure_scratch113; + uint32_t secure_scratch114; + uint32_t secure_scratch115; + uint32_t secure_scratch116; + uint32_t secure_scratch117; + uint32_t secure_scratch118; + uint32_t secure_scratch119; +} tegra_pmc_t; + +static inline volatile tegra_pmc_t *pmc_get_regs(void) +{ + return (volatile tegra_pmc_t *)PMC_BASE; +} + +#endif diff --git a/sept/sept-secondary/src/preprocessor.h b/sept/sept-secondary/src/preprocessor.h new file mode 100644 index 000000000..2560cf456 --- /dev/null +++ b/sept/sept-secondary/src/preprocessor.h @@ -0,0 +1,207 @@ +/* TuxSH: I added INC/DEC_10 to INC/DEC_32; tuples */ + +#ifndef FUSEE_PREPROCESSOR_H +#define FUSEE_PREPROCESSOR_H + +/*============================================================================= + Copyright (c) 2015 Paul Fultz II + cloak.h + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +/*#ifndef CLOAK_GUARD_H +#define CLOAK_GUARD_H*/ + +#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) +#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ + +#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) +#define COMPL_0 1 +#define COMPL_1 0 + +#define BITAND(x) PRIMITIVE_CAT(BITAND_, x) +#define BITAND_0(y) 0 +#define BITAND_1(y) y + +#define INC(x) PRIMITIVE_CAT(INC_, x) +#define INC_0 1 +#define INC_1 2 +#define INC_2 3 +#define INC_3 4 +#define INC_4 5 +#define INC_5 6 +#define INC_6 7 +#define INC_7 8 +#define INC_8 9 +#define INC_9 10 +#define INC_10 11 +#define INC_11 12 +#define INC_12 13 +#define INC_13 14 +#define INC_14 15 +#define INC_15 16 +#define INC_16 17 +#define INC_17 18 +#define INC_18 19 +#define INC_19 20 +#define INC_20 21 +#define INC_21 22 +#define INC_22 23 +#define INC_23 24 +#define INC_24 25 +#define INC_25 26 +#define INC_26 27 +#define INC_27 28 +#define INC_28 29 +#define INC_29 30 +#define INC_30 31 +#define INC_31 32 +#define INC_32 32 +#define INC_33 33 + +#define DEC(x) PRIMITIVE_CAT(DEC_, x) +#define DEC_0 0 +#define DEC_1 0 +#define DEC_2 1 +#define DEC_3 2 +#define DEC_4 3 +#define DEC_5 4 +#define DEC_6 5 +#define DEC_7 6 +#define DEC_8 7 +#define DEC_9 8 +#define DEC_10 9 +#define DEC_11 10 +#define DEC_12 11 +#define DEC_13 12 +#define DEC_14 13 +#define DEC_15 14 +#define DEC_16 15 +#define DEC_17 16 +#define DEC_18 17 +#define DEC_19 18 +#define DEC_20 19 +#define DEC_21 20 +#define DEC_22 21 +#define DEC_23 22 +#define DEC_24 23 +#define DEC_25 24 +#define DEC_26 25 +#define DEC_27 26 +#define DEC_28 27 +#define DEC_29 28 +#define DEC_30 29 +#define DEC_31 30 +#define DEC_32 31 +#define DEC_33 32 + +#define CHECK_N(x, n, ...) n +#define CHECK(...) CHECK_N(__VA_ARGS__, 0,) +#define PROBE(x) x, 1, + +#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x) +#define IS_PAREN_PROBE(...) PROBE(~) + +#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x)) +#define NOT_0 PROBE(~) + +#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) +#define COMPL_0 1 +#define COMPL_1 0 + +#define BOOL(x) COMPL(NOT(x)) + +#define IIF(c) PRIMITIVE_CAT(IIF_, c) +#define IIF_0(t, ...) __VA_ARGS__ +#define IIF_1(t, ...) t + +#define IF(c) IIF(BOOL(c)) + +#define EAT(...) +#define EXPAND(...) __VA_ARGS__ +#define WHEN(c) IF(c)(EXPAND, EAT) + +#define EMPTY() +#define DEFER(id) id EMPTY() +#define OBSTRUCT(id) id DEFER(EMPTY)() + +#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) +#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) +#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) +#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) +#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__))) +#define EVAL5(...) __VA_ARGS__ + +#define REPEAT(count, macro, ...) \ + WHEN(count) \ + ( \ + OBSTRUCT(REPEAT_INDIRECT) () \ + ( \ + DEC(count), macro, __VA_ARGS__ \ + ) \ + OBSTRUCT(macro) \ + ( \ + DEC(count), __VA_ARGS__ \ + ) \ + ) +#define REPEAT_INDIRECT() REPEAT + +#define WHILE(pred, op, ...) \ + IF(pred(__VA_ARGS__)) \ + ( \ + OBSTRUCT(WHILE_INDIRECT) () \ + ( \ + pred, op, op(__VA_ARGS__) \ + ), \ + __VA_ARGS__ \ + ) +#define WHILE_INDIRECT() WHILE + +#define PRIMITIVE_COMPARE(x, y) IS_PAREN \ +( \ + COMPARE_ ## x ( COMPARE_ ## y) (()) \ +) + +#define IS_COMPARABLE(x) IS_PAREN( CAT(COMPARE_, x) (()) ) + +#define NOT_EQUAL(x, y) \ +IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y)) ) \ +( \ + PRIMITIVE_COMPARE, \ + 1 EAT \ +)(x, y) + +#define EQUAL(x, y) COMPL(NOT_EQUAL(x, y)) + +#define COMMA() , + +#define COMMA_IF(n) IF(n)(COMMA, EAT)() + +#define PLUS() + + +#define _TUPLE_ELEM_0(a, ...) a +#define _TUPLE_ELEM_1(a, b, ...) b +#define _TUPLE_ELEM_2(a, b, c, ...) c +#define _TUPLE_ELEM_3(a, b, c, d, ...) d +#define _TUPLE_ELEM_4(a, b, c, d, e, ...) e + +#define TUPLE_ELEM_0(T) EVAL(_TUPLE_ELEM_0 T) +#define TUPLE_ELEM_1(T) EVAL(_TUPLE_ELEM_1 T) +#define TUPLE_ELEM_2(T) EVAL(_TUPLE_ELEM_2 T) +#define TUPLE_ELEM_3(T) EVAL(_TUPLE_ELEM_3 T) +#define TUPLE_ELEM_4(T) EVAL(_TUPLE_ELEM_4 T) + +#define _TUPLE_FOLD_LEFT_0(i, T, op) (_TUPLE_ELEM_0 CAT(T,i)) op() +#define _TUPLE_FOLD_LEFT_1(i, T, op) (_TUPLE_ELEM_1 CAT(T,i)) op() +#define _TUPLE_FOLD_LEFT_2(i, T, op) (_TUPLE_ELEM_2 CAT(T,i)) op() +#define _TUPLE_FOLD_LEFT_3(i, T, op) (_TUPLE_ELEM_3 CAT(T,i)) op() +#define _TUPLE_FOLD_LEFT_4(i, T, op) (_TUPLE_ELEM_4 CAT(T,i)) op() + +#define TUPLE_FOLD_LEFT_0(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_0, T, op)) +#define TUPLE_FOLD_LEFT_1(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_1, T, op)) +#define TUPLE_FOLD_LEFT_2(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_2, T, op)) +#define TUPLE_FOLD_LEFT_3(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_3, T, op)) +#define TUPLE_FOLD_LEFT_4(len, T, op) EVAL(REPEAT(len, _TUPLE_FOLD_LEFT_4, T, op)) + +#endif diff --git a/sept/sept-secondary/src/sdmmc/mmc.h b/sept/sept-secondary/src/sdmmc/mmc.h new file mode 100644 index 000000000..6f7126c01 --- /dev/null +++ b/sept/sept-secondary/src/sdmmc/mmc.h @@ -0,0 +1,449 @@ +/* + * Header for MultiMediaCard (MMC) + * + * Copyright 2002 Hewlett-Packard Company + * Copyright (c) 2018 Atmosphère-NX + * + * Use consistent with the GNU GPL is permitted, + * provided that this copyright notice is + * preserved in its entirety in all copies and derived works. + * + * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, + * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS + * FITNESS FOR ANY PARTICULAR PURPOSE. + * + * Many thanks to Alessandro Rubini and Jonathan Corbet! + * + * Based strongly on code by: + * + * Author: Yong-iL Joh <tolkien@mizi.com> + * + * Author: Andrew Christian + * 15 May 2002 + */ + +#ifndef LINUX_MMC_MMC_H +#define LINUX_MMC_MMC_H + +/* Standard MMC commands (4.1) type argument response */ + /* class 1 */ +#define MMC_GO_IDLE_STATE 0 /* bc */ +#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ +#define MMC_ALL_SEND_CID 2 /* bcr R2 */ +#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ +#define MMC_SET_DSR 4 /* bc [31:16] RCA */ +#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */ +#define MMC_SWITCH 6 /* ac [31:0] See below R1b */ +#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ +#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ +#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ +#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ +#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ +#define MMC_STOP_TRANSMISSION 12 /* ac R1b */ +#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ +#define MMC_BUS_TEST_R 14 /* adtc R1 */ +#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ +#define MMC_BUS_TEST_W 19 /* adtc R1 */ +#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */ +#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */ + + /* class 2 */ +#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ +#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ +#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ +#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */ +#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */ + + /* class 3 */ +#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ + + /* class 4 */ +#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ +#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ +#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ +#define MMC_PROGRAM_CID 26 /* adtc R1 */ +#define MMC_PROGRAM_CSD 27 /* adtc R1 */ + + /* class 6 */ +#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ +#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ +#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ + + /* class 5 */ +#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ +#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ +#define MMC_ERASE 38 /* ac R1b */ + + /* class 9 */ +#define MMC_FAST_IO 39 /* ac <Complex> R4 */ +#define MMC_GO_IRQ_STATE 40 /* bcr R5 */ + + /* class 7 */ +#define MMC_LOCK_UNLOCK 42 /* adtc R1b */ + + /* class 8 */ +#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ +#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ + + /* class 11 */ +#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */ +#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */ +#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */ +#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */ +#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */ + +/* + * MMC_SWITCH argument format: + * + * [31:26] Always 0 + * [25:24] Access Mode + * [23:16] Location of target Byte in EXT_CSD + * [15:08] Value Byte + * [07:03] Always 0 + * [02:00] Command Set + */ + +/* + MMC status in R1, for native mode (SPI bits are different) + Type + e : error bit + s : status bit + r : detected and set for the actual command response + x : detected and set during command execution. the host must poll + the card by sending status command in order to read these bits. + Clear condition + a : according to the card state + b : always related to the previous command. Reception of + a valid command will clear it (with a delay of one command) + c : clear by read + */ + +#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ +#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ +#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ +#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ +#define R1_ERASE_PARAM (1 << 27) /* ex, c */ +#define R1_WP_VIOLATION (1 << 26) /* erx, c */ +#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ +#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ +#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ +#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ +#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ +#define R1_CC_ERROR (1 << 20) /* erx, c */ +#define R1_ERROR (1 << 19) /* erx, c */ +#define R1_UNDERRUN (1 << 18) /* ex, c */ +#define R1_OVERRUN (1 << 17) /* ex, c */ +#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ +#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ +#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ +#define R1_ERASE_RESET (1 << 13) /* sr, c */ +#define R1_STATUS(x) (x & 0xFFFFE000) +#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ +#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ +#define R1_SWITCH_ERROR (1 << 7) /* sx, c */ +#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */ +#define R1_APP_CMD (1 << 5) /* sr, c */ + +#define R1_STATE_IDLE 0 +#define R1_STATE_READY 1 +#define R1_STATE_IDENT 2 +#define R1_STATE_STBY 3 +#define R1_STATE_TRAN 4 +#define R1_STATE_DATA 5 +#define R1_STATE_RCV 6 +#define R1_STATE_PRG 7 +#define R1_STATE_DIS 8 + +/* + * MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS + * R1 is the low order byte; R2 is the next highest byte, when present. + */ +#define R1_SPI_IDLE (1 << 0) +#define R1_SPI_ERASE_RESET (1 << 1) +#define R1_SPI_ILLEGAL_COMMAND (1 << 2) +#define R1_SPI_COM_CRC (1 << 3) +#define R1_SPI_ERASE_SEQ (1 << 4) +#define R1_SPI_ADDRESS (1 << 5) +#define R1_SPI_PARAMETER (1 << 6) +/* R1 bit 7 is always zero */ +#define R2_SPI_CARD_LOCKED (1 << 8) +#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */ +#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP +#define R2_SPI_ERROR (1 << 10) +#define R2_SPI_CC_ERROR (1 << 11) +#define R2_SPI_CARD_ECC_ERROR (1 << 12) +#define R2_SPI_WP_VIOLATION (1 << 13) +#define R2_SPI_ERASE_PARAM (1 << 14) +#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */ +#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE + +/* + * OCR bits are mostly in host.h + */ +#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ +#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ +#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ +#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ +#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */ +#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */ +#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */ +#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */ +#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */ +#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */ +#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */ +#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */ +#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */ +#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */ +#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */ +#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */ +#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ +#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ + +/* + * Card Command Classes (CCC) + */ +#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */ + /* (CMD0,1,2,3,4,7,9,10,12,13,15) */ + /* (and for SPI, CMD58,59) */ +#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */ + /* (CMD11) */ +#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */ + /* (CMD16,17,18) */ +#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */ + /* (CMD20) */ +#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */ + /* (CMD16,24,25,26,27) */ +#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */ + /* (CMD32,33,34,35,36,37,38,39) */ +#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */ + /* (CMD28,29,30) */ +#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */ + /* (CMD16,CMD42) */ +#define CCC_APP_SPEC (1<<8) /* (8) Application specific */ + /* (CMD55,56,57,ACMD*) */ +#define CCC_IO_MODE (1<<9) /* (9) I/O mode */ + /* (CMD5,39,40,52,53) */ +#define CCC_SWITCH (1<<10) /* (10) High speed switch */ + /* (CMD6,34,35,36,37,50) */ + /* (11) Reserved */ + /* (CMD?) */ + +/* + * CSD field definitions + */ + +#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ +#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ +#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */ +#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */ + +#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ +#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ +#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ +#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */ +#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */ + +/* + * EXT_CSD fields + */ + +#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */ +#define EXT_CSD_FLUSH_CACHE 32 /* W */ +#define EXT_CSD_CACHE_CTRL 33 /* R/W */ +#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ +#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */ +#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */ +#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */ +#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */ +#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ +#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ +#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ +#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ +#define EXT_CSD_HPI_MGMT 161 /* R/W */ +#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ +#define EXT_CSD_BKOPS_EN 163 /* R/W */ +#define EXT_CSD_BKOPS_START 164 /* W */ +#define EXT_CSD_SANITIZE_START 165 /* W */ +#define EXT_CSD_WR_REL_PARAM 166 /* RO */ +#define EXT_CSD_RPMB_MULT 168 /* RO */ +#define EXT_CSD_FW_CONFIG 169 /* R/W */ +#define EXT_CSD_BOOT_WP 173 /* R/W */ +#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ +#define EXT_CSD_PART_CONFIG 179 /* R/W */ +#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ +#define EXT_CSD_BUS_WIDTH 183 /* R/W */ +#define EXT_CSD_STROBE_SUPPORT 184 /* RO */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_POWER_CLASS 187 /* R/W */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_STRUCTURE 194 /* RO */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */ +#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */ +#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */ +#define EXT_CSD_PWR_CL_52_195 200 /* RO */ +#define EXT_CSD_PWR_CL_26_195 201 /* RO */ +#define EXT_CSD_PWR_CL_52_360 202 /* RO */ +#define EXT_CSD_PWR_CL_26_360 203 /* RO */ +#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ +#define EXT_CSD_S_A_TIMEOUT 217 /* RO */ +#define EXT_CSD_REL_WR_SEC_C 222 /* RO */ +#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ +#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ +#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ +#define EXT_CSD_BOOT_MULT 226 /* RO */ +#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ +#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */ +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ +#define EXT_CSD_TRIM_MULT 232 /* RO */ +#define EXT_CSD_PWR_CL_200_195 236 /* RO */ +#define EXT_CSD_PWR_CL_200_360 237 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ +#define EXT_CSD_BKOPS_STATUS 246 /* RO */ +#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ +#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ +#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ +#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ +#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */ +#define EXT_CSD_PRE_EOL_INFO 267 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */ +#define EXT_CSD_CMDQ_DEPTH 307 /* RO */ +#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */ +#define EXT_CSD_SUPPORTED_MODE 493 /* RO */ +#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ +#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ +#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ +#define EXT_CSD_MAX_PACKED_READS 501 /* RO */ +#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ +#define EXT_CSD_HPI_FEATURES 503 /* RO */ + +/* + * EXT_CSD field definitions + */ + +#define EXT_CSD_WR_REL_PARAM_EN (1<<2) + +#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40) +#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10) +#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04) +#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01) + +#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7) +#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1) +#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3) +#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4) + +#define EXT_CSD_PART_SETTING_COMPLETED (0x1) +#define EXT_CSD_PART_SUPPORT_PART_EN (0x1) + +#define EXT_CSD_CMD_SET_NORMAL (1<<0) +#define EXT_CSD_CMD_SET_SECURE (1<<1) +#define EXT_CSD_CMD_SET_CPSECURE (1<<2) + +#define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */ +#define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */ +#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \ + EXT_CSD_CARD_TYPE_HS_52) +#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */ + /* DDR mode @1.8V or 3V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */ + /* DDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ + | EXT_CSD_CARD_TYPE_DDR_1_2V) +#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */ +#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */ + /* SDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \ + EXT_CSD_CARD_TYPE_HS200_1_2V) +#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */ +#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */ +#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \ + EXT_CSD_CARD_TYPE_HS400_1_2V) +#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */ + +#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ +#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ +#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ +#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ +#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */ +#define EXT_CSD_BUS_WIDTH_STROBE BIT(7) /* Enhanced strobe mode */ + +#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */ +#define EXT_CSD_TIMING_HS 1 /* High speed */ +#define EXT_CSD_TIMING_HS200 2 /* HS200 */ +#define EXT_CSD_TIMING_HS400 3 /* HS400 */ +#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */ + +#define EXT_CSD_SEC_ER_EN BIT(0) +#define EXT_CSD_SEC_BD_BLK_EN BIT(2) +#define EXT_CSD_SEC_GB_CL_EN BIT(4) +#define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */ + +#define EXT_CSD_RST_N_EN_MASK 0x3 +#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */ + +#define EXT_CSD_NO_POWER_NOTIFICATION 0 +#define EXT_CSD_POWER_ON 1 +#define EXT_CSD_POWER_OFF_SHORT 2 +#define EXT_CSD_POWER_OFF_LONG 3 + +#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */ +#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */ +#define EXT_CSD_PWR_CL_8BIT_SHIFT 4 +#define EXT_CSD_PWR_CL_4BIT_SHIFT 0 + +#define EXT_CSD_PACKED_EVENT_EN BIT(3) + +/* + * EXCEPTION_EVENT_STATUS field + */ +#define EXT_CSD_URGENT_BKOPS BIT(0) +#define EXT_CSD_DYNCAP_NEEDED BIT(1) +#define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2) +#define EXT_CSD_PACKED_FAILURE BIT(3) + +#define EXT_CSD_PACKED_GENERIC_ERROR BIT(0) +#define EXT_CSD_PACKED_INDEXED_ERROR BIT(1) + +/* + * BKOPS status level + */ +#define EXT_CSD_BKOPS_LEVEL_2 0x2 + +/* + * BKOPS modes + */ +#define EXT_CSD_MANUAL_BKOPS_MASK 0x01 +#define EXT_CSD_AUTO_BKOPS_MASK 0x02 + +/* + * Command Queue + */ +#define EXT_CSD_CMDQ_MODE_ENABLED BIT(0) +#define EXT_CSD_CMDQ_DEPTH_MASK GENMASK(4, 0) +#define EXT_CSD_CMDQ_SUPPORTED BIT(0) + +/* + * MMC_SWITCH access modes + */ +#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ +#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */ +#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ +#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ + +/* + * Erase/trim/discard + */ +#define MMC_ERASE_ARG 0x00000000 +#define MMC_SECURE_ERASE_ARG 0x80000000 +#define MMC_TRIM_ARG 0x00000001 +#define MMC_DISCARD_ARG 0x00000003 +#define MMC_SECURE_TRIM1_ARG 0x80000001 +#define MMC_SECURE_TRIM2_ARG 0x80008000 +#define MMC_SECURE_ARGS 0x80000000 +#define MMC_TRIM_ARGS 0x00008001 + +#endif /* LINUX_MMC_MMC_H */ diff --git a/sept/sept-secondary/src/sdmmc/sd.h b/sept/sept-secondary/src/sdmmc/sd.h new file mode 100644 index 000000000..c30e8647e --- /dev/null +++ b/sept/sept-secondary/src/sdmmc/sd.h @@ -0,0 +1,155 @@ +/* + * include/linux/mmc/sd.h + * + * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. + * Copyright (C) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#ifndef LINUX_MMC_SD_H +#define LINUX_MMC_SD_H + +/* SD commands type argument response */ +/* class 0 */ +/* This is basically the same command as for MMC with some quirks. */ +#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ +#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ +#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ + +/* class 10 */ +#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ + +/* class 5 */ +#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ +#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ + +/* Application commands */ +#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ +#define SD_APP_SD_STATUS 13 /* adtc R1 */ +#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ +#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ +#define SD_APP_SET_CLR_CARD_DETECT 42 /* ac [0] set cd R1 */ +#define SD_APP_SEND_SCR 51 /* adtc R1 */ + +/* OCR bit definitions */ +#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ +#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ +#define SD_OCR_XPC (1 << 28) /* SDXC power control */ +#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ +#define SD_OCR_VDD_LOW (1 << 7) /* SD: Reserved for Low Voltage Range */ +#define SD_OCR_VDD_20_21 (1 << 8) +#define SD_OCR_VDD_21_22 (1 << 9) +#define SD_OCR_VDD_22_23 (1 << 10) +#define SD_OCR_VDD_23_24 (1 << 11) +#define SD_OCR_VDD_24_25 (1 << 12) +#define SD_OCR_VDD_25_26 (1 << 13) +#define SD_OCR_VDD_26_27 (1 << 14) +#define SD_OCR_VDD_27_28 (1 << 15) +#define SD_OCR_VDD_28_29 (1 << 16) +#define SD_OCR_VDD_29_30 (1 << 17) +#define SD_OCR_VDD_30_31 (1 << 18) +#define SD_OCR_VDD_31_32 (1 << 19) +#define SD_OCR_VDD_32_33 (1 << 20) +#define SD_OCR_VDD_33_34 (1 << 21) +#define SD_OCR_VDD_34_35 (1 << 22) +#define SD_OCR_VDD_35_36 (1 << 23) + +/* + * SD_SWITCH argument format: + * + * [31] Check (0) or switch (1) + * [30:24] Reserved (0) + * [23:20] Function group 6 + * [19:16] Function group 5 + * [15:12] Function group 4 + * [11:8] Function group 3 + * [7:4] Function group 2 + * [3:0] Function group 1 + */ + +/* + * SD_SEND_IF_COND argument format: + * + * [31:12] Reserved (0) + * [11:8] Host Voltage Supply Flags + * [7:0] Check Pattern (0xAA) + */ + +/* + * SCR field definitions + */ + +#define SD_SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ +#define SD_SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ +#define SD_SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ +#define SD_SCR_BUS_WIDTH_1 1 +#define SD_SCR_BUS_WIDTH_4 4 +#define SD_SCR_CMD20_SUPPORT 1 +#define SD_SCR_CMD23_SUPPORT 2 + +/* + * SD bus widths + */ +#define SD_BUS_WIDTH_1 0 +#define SD_BUS_WIDTH_4 2 + +/* + * SD bus speed modes + */ +#define UHS_SDR12_BUS_SPEED 0 +#define HIGH_SPEED_BUS_SPEED 1 +#define UHS_SDR25_BUS_SPEED 1 +#define UHS_SDR50_BUS_SPEED 2 +#define UHS_SDR104_BUS_SPEED 3 +#define UHS_DDR50_BUS_SPEED 4 +#define SD_MODE_HIGH_SPEED (1 << HIGH_SPEED_BUS_SPEED) +#define SD_MODE_UHS_SDR12 (1 << UHS_SDR12_BUS_SPEED) +#define SD_MODE_UHS_SDR25 (1 << UHS_SDR25_BUS_SPEED) +#define SD_MODE_UHS_SDR50 (1 << UHS_SDR50_BUS_SPEED) +#define SD_MODE_UHS_SDR104 (1 << UHS_SDR104_BUS_SPEED) +#define SD_MODE_UHS_DDR50 (1 << UHS_DDR50_BUS_SPEED) + +/* + * SD bus driver types + */ +#define SD_DRIVER_TYPE_B 0x01 +#define SD_DRIVER_TYPE_A 0x02 +#define SD_DRIVER_TYPE_C 0x04 +#define SD_DRIVER_TYPE_D 0x08 + +/* + * SD bus current limits + */ +#define SD_SET_CURRENT_LIMIT_200 0 +#define SD_SET_CURRENT_LIMIT_400 1 +#define SD_SET_CURRENT_LIMIT_600 2 +#define SD_SET_CURRENT_LIMIT_800 3 +#define SD_SET_CURRENT_NO_CHANGE (-1) +#define SD_MAX_CURRENT_200 (1 << SD_SET_CURRENT_LIMIT_200) +#define SD_MAX_CURRENT_400 (1 << SD_SET_CURRENT_LIMIT_400) +#define SD_MAX_CURRENT_600 (1 << SD_SET_CURRENT_LIMIT_600) +#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) + +/* + * SD_SWITCH mode + */ +#define SD_SWITCH_CHECK 0 +#define SD_SWITCH_SET 1 + +/* + * SD_SWITCH function groups + */ +#define SD_SWITCH_GRP_ACCESS 0 + +/* + * SD_SWITCH access modes + */ +#define SD_SWITCH_ACCESS_DEF 0 +#define SD_SWITCH_ACCESS_HS 1 + +#endif /* LINUX_MMC_SD_H */ diff --git a/sept/sept-secondary/src/sdmmc/sdmmc.c b/sept/sept-secondary/src/sdmmc/sdmmc.c new file mode 100644 index 000000000..3aeb59f90 --- /dev/null +++ b/sept/sept-secondary/src/sdmmc/sdmmc.c @@ -0,0 +1,1543 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stdbool.h> +#include <stdint.h> +#include <errno.h> +#include <inttypes.h> + +#include "sdmmc.h" +#include "mmc.h" +#include "sd.h" +#include "../timers.h" + +#define UNSTUFF_BITS(resp,start,size) \ +({ \ + const int __size = size; \ + const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1; \ + const int __off = 3 - ((start) / 32); \ + const int __shft = (start) & 31; \ + uint32_t __res; \ + \ + __res = resp[__off] >> __shft; \ + if (__size + __shft > 32) \ + __res |= resp[__off-1] << ((32 - __shft) % 32); \ + __res & __mask; \ +}) + +static const unsigned int tran_exp[] = { + 10000, 100000, 1000000, 10000000, + 0, 0, 0, 0 +}; + +static const unsigned char tran_mant[] = { + 0, 10, 12, 13, 15, 20, 25, 30, + 35, 40, 45, 50, 55, 60, 70, 80, +}; + +static const unsigned int taac_exp[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, +}; + +static const unsigned int taac_mant[] = { + 0, 10, 12, 13, 15, 20, 25, 30, + 35, 40, 45, 50, 55, 60, 70, 80, +}; + +/* + Common SDMMC device functions. +*/ + +static bool is_sdmmc_device_r1_error(uint32_t status) +{ + return (status & (R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR + | R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION + | R1_LOCK_UNLOCK_FAILED | R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND + | R1_CARD_ECC_FAILED | R1_CC_ERROR | R1_ERROR | R1_CID_CSD_OVERWRITE + | R1_WP_ERASE_SKIP | R1_ERASE_RESET | R1_SWITCH_ERROR)); +} + +static int sdmmc_device_send_r1_cmd(sdmmc_device_t *device, uint32_t opcode, uint32_t arg, bool is_busy, uint32_t resp_mask, uint32_t resp_state) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = opcode; + cmd.arg = arg; + cmd.flags = (is_busy ? SDMMC_RSP_R1B : SDMMC_RSP_R1); + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Mask the response, if necessary. */ + if (resp_mask) + resp &= ~(resp_mask); + + /* We got an error state. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + + /* We need to check for the desired state. */ + if (resp_state != 0xFFFFFFFF) + { + /* We didn't get the expected state. */ + if (R1_CURRENT_STATE(resp) != resp_state) + return 0; + } + + return 1; +} + +static int sdmmc_device_go_idle(sdmmc_device_t *device) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = MMC_GO_IDLE_STATE; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_NONE; + + return sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0); +} + +static int sdmmc_device_send_cid(sdmmc_device_t *device, uint32_t *cid) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = MMC_ALL_SEND_CID; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R2; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + /* Try to load back the response. */ + return sdmmc_load_response(device->sdmmc, SDMMC_RSP_R2, cid); +} + +static int sdmmc_device_send_csd(sdmmc_device_t *device, uint32_t *csd) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = MMC_SEND_CSD; + cmd.arg = (device->rca << 16); + cmd.flags = SDMMC_RSP_R2; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + /* Try to load back the response. */ + return sdmmc_load_response(device->sdmmc, SDMMC_RSP_R2, csd); +} + +static int sdmmc_device_select_card(sdmmc_device_t *device) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SELECT_CARD, (device->rca << 16), true, 0, 0xFFFFFFFF); +} + +static int sdmmc_device_set_blocklen(sdmmc_device_t *device, uint32_t blocklen) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SET_BLOCKLEN, blocklen, false, 0, R1_STATE_TRAN); +} + +static int sdmmc_device_send_status(sdmmc_device_t *device) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SEND_STATUS, (device->rca << 16), false, 0, R1_STATE_TRAN); +} + +static int sdmmc_device_rw(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data, bool is_read) +{ + uint8_t *buf = (uint8_t *)data; + + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + while (num_sectors) + { + uint32_t num_blocks_out = 0; + uint32_t num_retries = 10; + + for (; num_retries > 0; num_retries--) + { + cmd.opcode = is_read ? MMC_READ_MULTIPLE_BLOCK : MMC_WRITE_MULTIPLE_BLOCK; + cmd.arg = sector; + cmd.flags = SDMMC_RSP_R1; + + req.data = buf; + req.blksz = 512; + req.num_blocks = num_sectors; + req.is_read = is_read; + req.is_multi_block = true; + req.is_auto_cmd12 = true; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, &req, &num_blocks_out)) + { + /* Abort the transmission. */ + sdmmc_abort(device->sdmmc, MMC_STOP_TRANSMISSION); + + /* Peek the SD card's status. */ + sdmmc_device_send_status(device); + + /* Wait for a while. */ + mdelay(100); + } + else + break; + } + + /* Failed to read/write on all attempts. */ + if (!num_retries) + return 0; + + /* Advance to next sector. */ + sector += num_blocks_out; + num_sectors -= num_blocks_out; + buf += (512 * num_blocks_out); + } + + return 1; +} + +int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data) +{ + return sdmmc_device_rw(device, sector, num_sectors, data, true); +} + +int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data) +{ + return sdmmc_device_rw(device, sector, num_sectors, data, false); +} + +int sdmmc_device_finish(sdmmc_device_t *device) +{ + /* Place the device in idle state. */ + if (!sdmmc_device_go_idle(device)) + return 0; + + /* Terminate the device. */ + sdmmc_finish(device->sdmmc); + return 1; +} + +/* + SD device functions. +*/ + +static void sdmmc_sd_decode_cid(sdmmc_device_t *device, uint32_t *cid) +{ + device->cid.manfid = UNSTUFF_BITS(cid, 120, 8); + device->cid.oemid = UNSTUFF_BITS(cid, 104, 16); + device->cid.prod_name[0] = UNSTUFF_BITS(cid, 96, 8); + device->cid.prod_name[1] = UNSTUFF_BITS(cid, 88, 8); + device->cid.prod_name[2] = UNSTUFF_BITS(cid, 80, 8); + device->cid.prod_name[3] = UNSTUFF_BITS(cid, 72, 8); + device->cid.prod_name[4] = UNSTUFF_BITS(cid, 64, 8); + device->cid.hwrev = UNSTUFF_BITS(cid, 60, 4); + device->cid.fwrev = UNSTUFF_BITS(cid, 56, 4); + device->cid.serial = UNSTUFF_BITS(cid, 24, 32); + device->cid.year = UNSTUFF_BITS(cid, 12, 8) + 2000; /* SD cards year offset */ + device->cid.month = UNSTUFF_BITS(cid, 8, 4); +} + +static int sdmmc_sd_decode_csd(sdmmc_device_t *device, uint32_t *csd) +{ + unsigned int e, m; + device->csd.structure = UNSTUFF_BITS(csd, 126, 2); + + switch (device->csd.structure) { + case 0: + m = UNSTUFF_BITS(csd, 115, 4); + e = UNSTUFF_BITS(csd, 112, 3); + device->csd.taac_ns = (taac_exp[e] * taac_mant[m] + 9) / 10; + device->csd.taac_clks = UNSTUFF_BITS(csd, 104, 8) * 100; + + m = UNSTUFF_BITS(csd, 99, 4); + e = UNSTUFF_BITS(csd, 96, 3); + device->csd.max_dtr = tran_exp[e] * tran_mant[m]; + device->csd.cmdclass = UNSTUFF_BITS(csd, 84, 12); + + e = UNSTUFF_BITS(csd, 47, 3); + m = UNSTUFF_BITS(csd, 62, 12); + device->csd.capacity = ((1 + m) << (e + 2)); + + device->csd.read_blkbits = UNSTUFF_BITS(csd, 80, 4); + device->csd.read_partial = UNSTUFF_BITS(csd, 79, 1); + device->csd.write_misalign = UNSTUFF_BITS(csd, 78, 1); + device->csd.read_misalign = UNSTUFF_BITS(csd, 77, 1); + device->csd.dsr_imp = UNSTUFF_BITS(csd, 76, 1); + device->csd.r2w_factor = UNSTUFF_BITS(csd, 26, 3); + device->csd.write_blkbits = UNSTUFF_BITS(csd, 22, 4); + device->csd.write_partial = UNSTUFF_BITS(csd, 21, 1); + + if (UNSTUFF_BITS(csd, 46, 1)) { + device->csd.erase_size = 1; + } else if (device->csd.write_blkbits >= 9) { + device->csd.erase_size = UNSTUFF_BITS(csd, 39, 7) + 1; + device->csd.erase_size <<= (device->csd.write_blkbits - 9); + } + break; + case 1: + device->csd.taac_ns = 0; /* Unused */ + device->csd.taac_clks = 0; /* Unused */ + + m = UNSTUFF_BITS(csd, 99, 4); + e = UNSTUFF_BITS(csd, 96, 3); + device->csd.max_dtr = tran_exp[e] * tran_mant[m]; + device->csd.cmdclass = UNSTUFF_BITS(csd, 84, 12); + device->csd.c_size = UNSTUFF_BITS(csd, 48, 22); + + m = UNSTUFF_BITS(csd, 48, 22); + device->csd.capacity = ((1 + m) << 10); + + device->csd.read_blkbits = 9; + device->csd.read_partial = 0; + device->csd.write_misalign = 0; + device->csd.read_misalign = 0; + device->csd.r2w_factor = 4; /* Unused */ + device->csd.write_blkbits = 9; + device->csd.write_partial = 0; + device->csd.erase_size = 1; + break; + default: + return 0; + } + + return 1; +} + +static int sdmmc_sd_decode_scr(sdmmc_device_t *device, uint8_t *scr) +{ + uint8_t tmp[8]; + uint32_t resp[4]; + + /* This must be swapped. */ + for (int i = 0; i < 8; i += 4) + { + tmp[i + 3] = scr[i]; + tmp[i + 2] = scr[i + 1]; + tmp[i + 1] = scr[i + 2]; + tmp[i] = scr[i + 3]; + } + + resp[3] = *(uint32_t *)&tmp[4]; + resp[2] = *(uint32_t *)&tmp[0]; + + device->scr.sda_vsn = UNSTUFF_BITS(resp, 56, 4); + device->scr.bus_widths = UNSTUFF_BITS(resp, 48, 4); + + /* Check if Physical Layer Spec v3.0 is supported. */ + if (device->scr.sda_vsn == SD_SCR_SPEC_VER_2) + device->scr.sda_spec3 = UNSTUFF_BITS(resp, 47, 1); + + if (device->scr.sda_spec3) + device->scr.cmds = UNSTUFF_BITS(resp, 32, 2); + + /* Unknown SCR structure version. */ + if (UNSTUFF_BITS(resp, 60, 4)) + return 0; + else + return 1; +} + +static void sdmmc_sd_decode_ssr(sdmmc_device_t *device, uint8_t *ssr) +{ + uint8_t tmp[64]; + uint32_t resp1[4]; + uint32_t resp2[4]; + + /* This must be swapped. */ + for (int i = 0; i < 64; i += 4) + { + tmp[i + 3] = ssr[i]; + tmp[i + 2] = ssr[i + 1]; + tmp[i + 1] = ssr[i + 2]; + tmp[i] = ssr[i + 3]; + } + + resp1[3] = *(uint32_t *)&tmp[12]; + resp1[2] = *(uint32_t *)&tmp[8]; + resp1[1] = *(uint32_t *)&tmp[4]; + resp1[0] = *(uint32_t *)&tmp[0]; + resp2[3] = *(uint32_t *)&tmp[28]; + resp2[2] = *(uint32_t *)&tmp[24]; + resp2[1] = *(uint32_t *)&tmp[20]; + resp2[0] = *(uint32_t *)&tmp[16]; + + device->ssr.dat_bus_width = ((UNSTUFF_BITS(resp1, 126, 2) & SD_BUS_WIDTH_4) ? 4 : 1); + device->ssr.speed_class = UNSTUFF_BITS(resp1, 56, 8); + + if (device->ssr.speed_class < 4) + device->ssr.speed_class <<= 1; + else if (device->ssr.speed_class == 4) + device->ssr.speed_class = 10; + + device->ssr.uhs_speed_grade = UNSTUFF_BITS(resp1, 12, 4); + device->ssr.video_speed_class = UNSTUFF_BITS(resp1, 0, 8); + device->ssr.app_perf_class = UNSTUFF_BITS(resp2, 80, 4); +} + +static int sdmmc_sd_send_app_cmd(sdmmc_device_t *device, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t resp_mask, uint32_t resp_state) +{ + /* Try to send the APP command. */ + if (!sdmmc_device_send_r1_cmd(device, MMC_APP_CMD, (device->rca << 16), false, resp_mask, resp_state)) + return 0; + + /* Send the actual command. */ + if (!sdmmc_send_cmd(device->sdmmc, cmd, req, 0)) + return 0; + + return 1; +} + +static int sdmmc_sd_send_if_cond(sdmmc_device_t *device, bool *is_sd_ver2) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = SD_SEND_IF_COND; + /* We set the bit if the host supports voltages between 2.7 and 3.6 V */ + cmd.arg = 0x1AA; + cmd.flags = SDMMC_RSP_R7; + + /* Command failed, this means SD Card is not version 2. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + { + *is_sd_ver2 = false; + return 1; + } + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R7, &resp)) + return 0; + + /* Check if we got a valid response. */ + if ((resp & 0xFF) == 0xAA) + { + *is_sd_ver2 = true; + return 1; + } + + return 0; +} + +static int sdmmc_sd_send_op_cond(sdmmc_device_t *device, bool is_sd_ver2, bool is_uhs_en) +{ + sdmmc_command_t cmd = {}; + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + while (!is_timeout) + { + /* Set this since most cards do not answer if some reserved bits in the OCR are set. */ + uint32_t arg = SD_OCR_VDD_32_33; + + /* Request support for SDXC power control and SDHC block mode cards. */ + if (is_sd_ver2) + { + arg |= SD_OCR_XPC; + arg |= SD_OCR_CCS; + } + + /* Request support 1.8V switching. */ + if (is_uhs_en) + arg |= SD_OCR_S18R; + + cmd.opcode = SD_APP_OP_COND; + cmd.arg = arg; + cmd.flags = SDMMC_RSP_R3; + + /* Try to send the command. */ + if (!sdmmc_sd_send_app_cmd(device, &cmd, 0, is_sd_ver2 ? 0 : 0x400000, 0xFFFFFFFF)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R3, &resp)) + return 0; + + /* Card Power up bit is set. */ + if (resp & MMC_CARD_BUSY) + { + /* We have a SDHC block mode card. */ + if (resp & SD_OCR_CCS) + device->is_block_sdhc = true; + + /* We asked for low voltage support and the card accepted. */ + if (is_uhs_en && (resp & SD_ROCR_S18A)) + { + /* Voltage switching is only valid for SDMMC1. */ + if (device->sdmmc->controller == SDMMC_1) + { + /* Failed to issue voltage switching command. */ + if (!sdmmc_device_send_r1_cmd(device, SD_SWITCH_VOLTAGE, 0, false, 0, R1_STATE_READY)) + return 0; + + /* Delay a bit before asking for the voltage switch. */ + mdelay(100); + + /* Tell the driver to switch the voltage. */ + if (!sdmmc_switch_voltage(device->sdmmc)) + return 0; + + /* We are now running at 1.8V. */ + device->is_180v = true; + } + } + + return 1; + } + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + + /* Delay for a minimum of 10 milliseconds. */ + mdelay(10); + } + + return 0; +} + +static int sdmmc_sd_send_relative_addr(sdmmc_device_t *device) +{ + sdmmc_command_t cmd = {}; + + cmd.opcode = SD_SEND_RELATIVE_ADDR; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R6; + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + while (!is_timeout) + { + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R6, &resp)) + return 0; + + /* Save the RCA. */ + if (resp >> 16) + { + device->rca = (resp >> 16); + return 1; + } + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + + /* Delay for an appropriate period. */ + udelay(1000); + } + + return 0; +} + +static int sdmmc_sd_send_scr(sdmmc_device_t *device, uint8_t *scr) +{ + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + cmd.opcode = SD_APP_SEND_SCR; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1; + + req.data = scr; + req.blksz = 8; + req.num_blocks = 1; + req.is_read = true; + req.is_multi_block = false; + req.is_auto_cmd12 = false; + + /* Try to send the APP command. */ + if (!sdmmc_sd_send_app_cmd(device, &cmd, &req, 0, R1_STATE_TRAN)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Evaluate the response. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + else + return 1; +} + +static int sdmmc_sd_set_clr_card_detect(sdmmc_device_t *device) +{ + /* Try to send the APP command. */ + if (!sdmmc_device_send_r1_cmd(device, MMC_APP_CMD, (device->rca << 16), false, 0, R1_STATE_TRAN)) + return 0; + + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, SD_APP_SET_CLR_CARD_DETECT, 0, false, 0, R1_STATE_TRAN); +} + +static int sdmmc_sd_set_bus_width(sdmmc_device_t *device) +{ + /* Try to send the APP command. */ + if (!sdmmc_device_send_r1_cmd(device, MMC_APP_CMD, (device->rca << 16), false, 0, R1_STATE_TRAN)) + return 0; + + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, false, 0, R1_STATE_TRAN); +} + +static int sdmmc_sd_switch(sdmmc_device_t *device, uint32_t mode, uint32_t group, uint8_t value, uint8_t *data) +{ + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + cmd.opcode = SD_SWITCH; + cmd.arg = ((mode << 31) | 0x00FFFFFF); + cmd.arg &= ~(0xF << (group * 4)); + cmd.arg |= (value << (group * 4)); + cmd.flags = SDMMC_RSP_R1; + + req.data = data; + req.blksz = 64; + req.num_blocks = 1; + req.is_read = true; + req.is_multi_block = false; + req.is_auto_cmd12 = false; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, &req, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Evaluate the response. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + else + return 1; +} + +static int sdmmc_sd_set_current_limit(sdmmc_device_t *device, uint8_t *status) +{ + /* Start with the highest possible limit. */ + int32_t current_limit = SD_SET_CURRENT_LIMIT_800; + + /* Try each limit. */ + while (current_limit > SD_SET_CURRENT_NO_CHANGE) + { + /* Switch the current limit. */ + if (!sdmmc_sd_switch(device, SD_SWITCH_SET, 3, current_limit, status)) + return 0; + + /* Current limit was set successfully. */ + if (((status[15] >> 4) & 0x0F) == current_limit) + break; + + current_limit--; + } + + return 1; +} + +static int sdmmc_sd_switch_hs(sdmmc_device_t *device, uint32_t type, uint8_t *status) +{ + /* Test if the card supports high-speed mode. */ + if (!sdmmc_sd_switch(device, 0, 0, type, status)) + return 0; + + uint32_t res_type = (status[16] & 0xF); + + /* This high-speed mode type is not supported. */ + if (res_type != type) + return 0; + + if ((((uint16_t)status[0] << 8) | status[1]) < 0x320) + { + /* Try to switch to high-speed mode. */ + if (!sdmmc_sd_switch(device, 1, 0, type, status)) + return 0; + + /* Something failed when switching to high-speed mode. */ + if ((status[16] & 0xF) != res_type) + return 0; + } + + return 1; +} + +static int sdmmc_sd_switch_hs_low(sdmmc_device_t *device, uint8_t *status) +{ + /* Adjust the current limit. */ + if (!sdmmc_sd_set_current_limit(device, status)) + return 0; + + /* Invalid bus width. */ + if (device->sdmmc->bus_width != SDMMC_BUS_WIDTH_4BIT) + return 0; + + /* Get the supported high-speed type. */ + if (!sdmmc_sd_switch(device, 0, 0, 0xF, status)) + return 0; + + /* High-speed SDR104 is supported. */ + if (status[13] & SD_MODE_UHS_SDR104) + { + /* Switch to high-speed. */ + if (!sdmmc_sd_switch_hs(device, UHS_SDR104_BUS_SPEED, status)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR104)) + return 0; + + /* Run tuning. */ + if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR104, MMC_SEND_TUNING_BLOCK)) + return 0; + } + else if (status[13] & SD_MODE_UHS_SDR50) /* High-speed SDR50 is supported. */ + { + /* Switch to high-speed. */ + if (!sdmmc_sd_switch_hs(device, UHS_SDR50_BUS_SPEED, status)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR50)) + return 0; + + /* Run tuning. */ + if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR50, MMC_SEND_TUNING_BLOCK)) + return 0; + } + else if (status[13] & SD_MODE_UHS_SDR12) /* High-speed SDR12 is supported. */ + { + /* Switch to high-speed. */ + if (!sdmmc_sd_switch_hs(device, UHS_SDR12_BUS_SPEED, status)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR12)) + return 0; + + /* Run tuning. */ + if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_SDR12, MMC_SEND_TUNING_BLOCK)) + return 0; + } + else + return 0; + + + /* Peek the SD card's status. */ + return sdmmc_device_send_status(device); +} + +static int sdmmc_sd_switch_hs_high(sdmmc_device_t *device, uint8_t *status) +{ + /* Get the supported high-speed type. */ + if (!sdmmc_sd_switch(device, 0, 0, 0xF, status)) + return 0; + + /* High-speed is supported. */ + if (status[13] & 2) + { + /* Switch to high-speed. */ + if (!sdmmc_sd_switch_hs(device, SDHCI_CTRL_UHS_SDR25, status)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_SDR25)) + return 0; + + /* Peek the SD card's status. */ + return sdmmc_device_send_status(device); + } + + /* Nothing to do. */ + return 1; +} + +static int sdmmc_sd_status(sdmmc_device_t *device, uint8_t *ssr) +{ + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + cmd.opcode = SD_APP_SD_STATUS; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1; + + req.data = ssr; + req.blksz = 64; + req.num_blocks = 1; + req.is_read = true; + req.is_multi_block = false; + req.is_auto_cmd12 = false; + + /* Try to send the APP command. */ + if (!sdmmc_sd_send_app_cmd(device, &cmd, &req, 0, R1_STATE_TRAN)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Evaluate the response. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + else + return 1; +} + +int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed) +{ + bool is_sd_ver2 = false; + uint32_t cid[4] = {0}; + uint32_t csd[4] = {0}; + uint8_t scr[8] = {0}; + uint8_t ssr[64] = {0}; + uint8_t switch_status[512] = {0}; + + /* Initialize our device's struct. */ + memset(device, 0, sizeof(sdmmc_device_t)); + + /* Try to initialize the driver. */ + if (!sdmmc_init(sdmmc, SDMMC_1, SDMMC_VOLTAGE_3V3, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_SDR)) + { + sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!"); + return 0; + } + + /* Bind the underlying driver. */ + device->sdmmc = sdmmc; + + sdmmc_info(sdmmc, "SDMMC driver was successfully initialized for SD!"); + + /* Apply at least 74 clock cycles. The card should be ready afterwards. */ + udelay((74000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + /* Instruct the SD card to go idle. */ + if (!sdmmc_device_go_idle(device)) + { + sdmmc_error(sdmmc, "Failed to go idle!"); + return 0; + } + + sdmmc_info(sdmmc, "SD card went idle!"); + + /* Get the SD card's interface operating condition. */ + if (!sdmmc_sd_send_if_cond(device, &is_sd_ver2)) + { + sdmmc_error(sdmmc, "Failed to send if cond!"); + return 0; + } + + sdmmc_info(sdmmc, "Sent if cond to SD card!"); + + /* Get the SD card's operating conditions. */ + if (!sdmmc_sd_send_op_cond(device, is_sd_ver2, (bus_width == SDMMC_BUS_WIDTH_4BIT) && (bus_speed == SDMMC_SPEED_SDR104))) + { + sdmmc_error(sdmmc, "Failed to send op cond!"); + return 0; + } + + sdmmc_info(sdmmc, "Sent op cond to SD card!"); + + /* Get the SD card's CID. */ + if (!sdmmc_device_send_cid(device, cid)) + { + sdmmc_error(sdmmc, "Failed to get CID!"); + return 0; + } + + sdmmc_info(sdmmc, "Got CID from SD card!"); + + /* Decode and save the CID. */ + sdmmc_sd_decode_cid(device, cid); + + /* Get the SD card's RCA. */ + if (!sdmmc_sd_send_relative_addr(device)) + { + sdmmc_error(sdmmc, "Failed to get RCA!"); + return 0; + } + + sdmmc_info(sdmmc, "Got RCA (0x%08x) from SD card!", device->rca); + + /* Get the SD card's CSD. */ + if (!sdmmc_device_send_csd(device, csd)) + { + sdmmc_error(sdmmc, "Failed to get CSD!"); + return 0; + } + + sdmmc_info(sdmmc, "Got CSD from SD card!"); + + /* Decode and save the CSD. */ + if (!sdmmc_sd_decode_csd(device, csd)) + sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure); + + /* If we never switched to 1.8V, change the bus speed mode. */ + if (!device->is_180v) + { + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_UNK6)) + { + sdmmc_error(sdmmc, "Failed to apply the correct bus speed!"); + return 0; + } + + sdmmc_info(sdmmc, "Speed mode has been adjusted!"); + } + + /* Select the SD card. */ + if (!sdmmc_device_select_card(device)) + { + sdmmc_error(sdmmc, "Failed to select SD card!"); + return 0; + } + + sdmmc_info(sdmmc, "SD card is now selected!"); + + /* Change the SD card's block length. */ + if (!sdmmc_device_set_blocklen(device, 512)) + { + sdmmc_error(sdmmc, "Failed to set SD card's block length!"); + return 0; + } + + sdmmc_info(sdmmc, "SD card's block length is now 512!"); + + /* It's a good practice to disconnect the pull-up resistor with ACMD42. */ + if (!sdmmc_sd_set_clr_card_detect(device)) + { + sdmmc_error(sdmmc, "Failed to disconnect the pull-up resistor!"); + return 0; + } + + sdmmc_info(sdmmc, "Pull-up resistor is now disconnected!"); + + /* Get the SD card's SCR. */ + if (!sdmmc_sd_send_scr(device, scr)) + { + sdmmc_error(sdmmc, "Failed to get SCR!"); + return 0; + } + + sdmmc_info(sdmmc, "Got SCR from SD card!"); + + /* Decode and save the SCR. */ + if (!sdmmc_sd_decode_scr(device, scr)) + { + sdmmc_error(sdmmc, "Got unknown SCR structure!"); + return 0; + } + + /* Switch to wider bus (if supported). */ + if ((bus_width == SDMMC_BUS_WIDTH_4BIT) + && (device->scr.bus_widths & SD_SCR_BUS_WIDTH_4) + && (device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2))) + { + if (!sdmmc_sd_set_bus_width(device)) + { + sdmmc_error(sdmmc, "Failed to switch to wider bus!"); + return 0; + } + + sdmmc_select_bus_width(device->sdmmc, SDMMC_BUS_WIDTH_4BIT); + sdmmc_info(sdmmc, "Switched to wider bus!"); + } + + if (device->is_180v) + { + /* Switch to high-speed from low voltage (if possible). */ + if (!sdmmc_sd_switch_hs_low(device, switch_status)) + { + sdmmc_error(sdmmc, "Failed to switch to high-speed from low voltage!"); + return 0; + } + + sdmmc_info(sdmmc, "Switched to high-speed from low voltage!"); + } + else if ((device->scr.sda_vsn & (SD_SCR_SPEC_VER_1 | SD_SCR_SPEC_VER_2)) && ((bus_speed != SDMMC_SPEED_UNK6))) + { + /* Switch to high-speed from high voltage (if possible). */ + if (!sdmmc_sd_switch_hs_high(device, switch_status)) + { + sdmmc_error(sdmmc, "Failed to switch to high-speed from high voltage!"); + return 0; + } + + sdmmc_info(sdmmc, "Switched to high-speed from high voltage!"); + } + + /* Correct any inconsistent states. */ + sdmmc_adjust_sd_clock(sdmmc); + + /* Get the SD card's SSR. */ + if (!sdmmc_sd_status(device, ssr)) + { + sdmmc_error(sdmmc, "Failed to get SSR!"); + return 0; + } + + sdmmc_info(sdmmc, "Got SSR from SD card!"); + + /* Decode and save the SSR. */ + sdmmc_sd_decode_ssr(device, scr); + + return 1; +} + +/* + MMC device functions. +*/ + +static void sdmmc_mmc_decode_cid(sdmmc_device_t *device, uint32_t *cid) +{ + switch (device->csd.mmca_vsn) + { + case 0: /* MMC v1.0 - v1.2 */ + case 1: /* MMC v1.4 */ + device->cid.prod_name[6] = UNSTUFF_BITS(cid, 48, 8); + device->cid.manfid = UNSTUFF_BITS(cid, 104, 24); + device->cid.hwrev = UNSTUFF_BITS(cid, 44, 4); + device->cid.fwrev = UNSTUFF_BITS(cid, 40, 4); + device->cid.serial = UNSTUFF_BITS(cid, 16, 24); + break; + case 2: /* MMC v2.0 - v2.2 */ + case 3: /* MMC v3.1 - v3.3 */ + case 4: /* MMC v4 */ + device->cid.manfid = UNSTUFF_BITS(cid, 120, 8); + device->cid.oemid = UNSTUFF_BITS(cid, 104, 8); + device->cid.prv = UNSTUFF_BITS(cid, 48, 8); + device->cid.serial = UNSTUFF_BITS(cid, 16, 32); + break; + default: + break; + } + + device->cid.prod_name[0] = UNSTUFF_BITS(cid, 96, 8); + device->cid.prod_name[1] = UNSTUFF_BITS(cid, 88, 8); + device->cid.prod_name[2] = UNSTUFF_BITS(cid, 80, 8); + device->cid.prod_name[3] = UNSTUFF_BITS(cid, 72, 8); + device->cid.prod_name[4] = UNSTUFF_BITS(cid, 64, 8); + device->cid.prod_name[5] = UNSTUFF_BITS(cid, 56, 8); + + device->cid.month = UNSTUFF_BITS(cid, 12, 4); + device->cid.year = (UNSTUFF_BITS(cid, 8, 4) + 1997); + + if ((device->ext_csd.rev >= 5) && (device->cid.year < 2010)) + device->cid.year += 16; +} + +static int sdmmc_mmc_decode_csd(sdmmc_device_t *device, uint32_t *csd) +{ + unsigned int e, m, a, b; + + device->csd.structure = UNSTUFF_BITS(csd, 126, 2); + + if (!device->csd.structure) { + return 0; + } + + device->csd.mmca_vsn = UNSTUFF_BITS(csd, 122, 4); + + m = UNSTUFF_BITS(csd, 115, 4); + e = UNSTUFF_BITS(csd, 112, 3); + device->csd.taac_ns = ((taac_exp[e] * taac_mant[m] + 9) / 10); + device->csd.taac_clks = (UNSTUFF_BITS(csd, 104, 8) * 100); + + m = UNSTUFF_BITS(csd, 99, 4); + e = UNSTUFF_BITS(csd, 96, 3); + device->csd.max_dtr = (tran_exp[e] * tran_mant[m]); + device->csd.cmdclass = UNSTUFF_BITS(csd, 84, 12); + + e = UNSTUFF_BITS(csd, 47, 3); + m = UNSTUFF_BITS(csd, 62, 12); + device->csd.capacity = ((1 + m) << (e + 2)); + + device->csd.read_blkbits = UNSTUFF_BITS(csd, 80, 4); + device->csd.read_partial = UNSTUFF_BITS(csd, 79, 1); + device->csd.write_misalign = UNSTUFF_BITS(csd, 78, 1); + device->csd.read_misalign = UNSTUFF_BITS(csd, 77, 1); + device->csd.dsr_imp = UNSTUFF_BITS(csd, 76, 1); + device->csd.r2w_factor = UNSTUFF_BITS(csd, 26, 3); + device->csd.write_blkbits = UNSTUFF_BITS(csd, 22, 4); + device->csd.write_partial = UNSTUFF_BITS(csd, 21, 1); + + if (device->csd.write_blkbits >= 9) + { + a = UNSTUFF_BITS(csd, 42, 5); + b = UNSTUFF_BITS(csd, 37, 5); + device->csd.erase_size = ((a + 1) * (b + 1)); + device->csd.erase_size <<= (device->csd.write_blkbits - 9); + } + + return 1; +} + +static void sdmmc_mmc_decode_ext_csd(sdmmc_device_t *device, uint8_t *ext_csd) +{ + device->ext_csd.rev = ext_csd[EXT_CSD_REV]; + device->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; + device->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE]; + device->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT]; + device->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0]; + device->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1]; + device->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2]; + device->ext_csd.raw_sectors[3] = ext_csd[EXT_CSD_SEC_CNT + 3]; + device->ext_csd.bkops = ext_csd[EXT_CSD_BKOPS_SUPPORT]; + device->ext_csd.man_bkops_en = ext_csd[EXT_CSD_BKOPS_EN]; + device->ext_csd.raw_bkops_status = ext_csd[EXT_CSD_BKOPS_STATUS]; +} + +static int sdmmc_mmc_send_op_cond(sdmmc_device_t *device, SdmmcBusVoltage bus_voltage) +{ + sdmmc_command_t cmd = {}; + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + while (!is_timeout) + { + /* Set high capacity bit. */ + uint32_t arg = SD_OCR_CCS; + + /* Set voltage bits. */ + if (bus_voltage == SDMMC_VOLTAGE_1V8) + arg |= MMC_VDD_165_195; + else if (bus_voltage == SDMMC_VOLTAGE_3V3) + arg |= (MMC_VDD_33_34 | MMC_VDD_32_33 | MMC_VDD_31_32 | MMC_VDD_30_31 | MMC_VDD_29_30 | MMC_VDD_28_29 | MMC_VDD_27_28); + else + return 0; + + cmd.opcode = MMC_SEND_OP_COND; + cmd.arg = arg; + cmd.flags = SDMMC_RSP_R3; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, 0, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R3, &resp)) + return 0; + + /* Card Power up bit is set. */ + if (resp & MMC_CARD_BUSY) + { + /* We have a SDHC block mode card. */ + if (resp & SD_OCR_CCS) + device->is_block_sdhc = true; + + return 1; + } + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + + /* Delay for a minimum of 10 milliseconds. */ + mdelay(10); + } + + return 0; +} + +static int sdmmc_mmc_send_ext_csd(sdmmc_device_t *device, uint8_t *ext_csd) +{ + sdmmc_command_t cmd = {}; + sdmmc_request_t req = {}; + + cmd.opcode = MMC_SEND_EXT_CSD; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1; + + req.data = ext_csd; + req.blksz = 512; + req.num_blocks = 1; + req.is_read = true; + req.is_multi_block = false; + req.is_auto_cmd12 = false; + + /* Try to send the command. */ + if (!sdmmc_send_cmd(device->sdmmc, &cmd, &req, 0)) + return 0; + + uint32_t resp = 0; + + /* Try to load back the response. */ + if (!sdmmc_load_response(device->sdmmc, SDMMC_RSP_R1, &resp)) + return 0; + + /* Evaluate the response. */ + if (is_sdmmc_device_r1_error(resp)) + return 0; + else + return 1; +} + +static int sdmmc_mmc_set_relative_addr(sdmmc_device_t *device) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SET_RELATIVE_ADDR, (device->rca << 16), false, 0, 0xFFFFFFFF); +} + +static int sdmmc_mmc_switch(sdmmc_device_t *device, uint32_t arg) +{ + /* Try to send the command. */ + return sdmmc_device_send_r1_cmd(device, MMC_SWITCH, arg, true, 0, 0xFFFFFFFF); +} + +static int sdmmc_mmc_select_bus_width(sdmmc_device_t *device, SdmmcBusWidth bus_width) +{ + uint32_t arg = 0; + + /* Choose the argument for the switch command. */ + switch (bus_width) + { + case SDMMC_BUS_WIDTH_1BIT: + return 1; + case SDMMC_BUS_WIDTH_4BIT: + arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_BUS_WIDTH) << 16) | ((EXT_CSD_BUS_WIDTH_4) << 8)); + break; + case SDMMC_BUS_WIDTH_8BIT: + arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_BUS_WIDTH) << 16) | ((EXT_CSD_BUS_WIDTH_8) << 8)); + break; + default: + return 0; + } + + /* Try to switch the bus width. */ + if (sdmmc_mmc_switch(device, arg) && sdmmc_device_send_status(device)) + { + sdmmc_select_bus_width(device->sdmmc, bus_width); + return 1; + } + + return 0; +} + +static int sdmmc_mmc_select_hs(sdmmc_device_t *device, bool ignore_status) +{ + uint32_t arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_HS_TIMING) << 16) | ((EXT_CSD_TIMING_HS) << 8)); + + /* Try to switch to HS. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Check the status if necessary. */ + if (!ignore_status && !sdmmc_device_send_status(device)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS52)) + return 0; + + /* Check the status if necessary. */ + if (!ignore_status && !sdmmc_device_send_status(device)) + return 0; + + return 1; +} + +static int sdmmc_mmc_select_hs200(sdmmc_device_t *device) +{ + uint32_t arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_HS_TIMING) << 16) | ((EXT_CSD_TIMING_HS200) << 8)); + + /* Try to switch to HS200. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS200)) + return 0; + + /* Execute tuning procedure. */ + if (!sdmmc_execute_tuning(device->sdmmc, SDMMC_SPEED_HS200, MMC_SEND_TUNING_BLOCK_HS200)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + +static int sdmmc_mmc_select_hs400(sdmmc_device_t *device) +{ + uint32_t arg = 0; + + /* Switch to HS200 first. */ + if (!sdmmc_mmc_select_hs200(device)) + return 0; + + /* Fetch and set the tuning tap value. */ + sdmmc_set_tuning_tap_val(device->sdmmc); + + /* Switch to HS. */ + if (!sdmmc_mmc_select_hs(device, true)) + return 0; + + arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_BUS_WIDTH) << 16) | ((EXT_CSD_DDR_BUS_WIDTH_8) << 8)); + + /* Try to switch to 8bit bus. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_HS_TIMING) << 16) | ((EXT_CSD_TIMING_HS400) << 8)); + + /* Try to switch to HS400. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS400)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + +static int sdmmc_mmc_select_timing(sdmmc_device_t *device, SdmmcBusSpeed bus_speed) +{ + if ((bus_speed == SDMMC_SPEED_HS400) && + (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) && + (device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)) + { + /* Switch to HS400. */ + return sdmmc_mmc_select_hs400(device); + } + else if (((bus_speed == SDMMC_SPEED_HS400) || (bus_speed == SDMMC_SPEED_HS200)) && + ((device->sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) || (device->sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT)) && + (device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)) + { + /* Switch to HS200. */ + return sdmmc_mmc_select_hs200(device); + } + else if (device->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_HS_52) + { + /* Switch to HS. */ + return sdmmc_mmc_select_hs(device, false); + } + + return 0; +} + +static int sdmmc_mmc_select_bkops(sdmmc_device_t *device) +{ + uint32_t arg = (((MMC_SWITCH_MODE_SET_BITS) << 24) | ((EXT_CSD_BKOPS_EN) << 16) | ((EXT_CSD_BKOPS_LEVEL_2) << 8)); + + /* Try to enable bkops. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + +int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition) +{ + uint32_t arg = (((MMC_SWITCH_MODE_WRITE_BYTE) << 24) | ((EXT_CSD_PART_CONFIG) << 16) | ((partition) << 8)); + + /* Try to change the active partition. */ + if (!sdmmc_mmc_switch(device, arg)) + return 0; + + /* Peek the current status. */ + return sdmmc_device_send_status(device); +} + +int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed) +{ + uint32_t cid[4] = {0}; + uint32_t csd[4] = {0}; + uint8_t ext_csd[512] = {0}; + + /* Initialize our device's struct. */ + memset(device, 0, sizeof(sdmmc_device_t)); + + /* Try to initialize the driver. */ + if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_VOLTAGE_1V8, SDMMC_BUS_WIDTH_1BIT, SDMMC_SPEED_INIT_HS)) + { + sdmmc_error(sdmmc, "Failed to initialize the SDMMC driver!"); + return 0; + } + + /* Bind the underlying driver. */ + device->sdmmc = sdmmc; + + /* Set RCA. */ + device->rca = 0x01; + + sdmmc_info(sdmmc, "SDMMC driver was successfully initialized for eMMC!"); + + /* Apply at least 74 clock cycles. eMMC should be ready afterwards. */ + udelay((74000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + /* Instruct the eMMC to go idle. */ + if (!sdmmc_device_go_idle(device)) + { + sdmmc_error(sdmmc, "Failed to go idle!"); + return 0; + } + + sdmmc_info(sdmmc, "eMMC went idle!"); + + /* Get the eMMC's operating conditions. */ + if (!sdmmc_mmc_send_op_cond(device, SDMMC_VOLTAGE_1V8)) + { + sdmmc_error(sdmmc, "Failed to send op cond!"); + return 0; + } + + sdmmc_info(sdmmc, "Sent op cond to eMMC!"); + + /* Get the eMMC's CID. */ + if (!sdmmc_device_send_cid(device, cid)) + { + sdmmc_error(sdmmc, "Failed to get CID!"); + return 0; + } + + sdmmc_info(sdmmc, "Got CID from eMMC!"); + + /* Set the eMMC's RCA. */ + if (!sdmmc_mmc_set_relative_addr(device)) + { + sdmmc_error(sdmmc, "Failed to set RCA!"); + return 0; + } + + sdmmc_info(sdmmc, "RCA is now set in eMMC!"); + + /* Get the eMMC card's CSD. */ + if (!sdmmc_device_send_csd(device, csd)) + { + sdmmc_error(sdmmc, "Failed to get CSD!"); + return 0; + } + + sdmmc_info(sdmmc, "Got CSD from eMMC!"); + + /* Decode and save the CSD. */ + if (!sdmmc_mmc_decode_csd(device, csd)) + sdmmc_warn(sdmmc, "Got unknown CSD structure (0x%08x)!", device->csd.structure); + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(device->sdmmc, SDMMC_SPEED_HS26)) + { + sdmmc_error(sdmmc, "Failed to apply the correct bus speed!"); + return 0; + } + + sdmmc_info(sdmmc, "Speed mode has been adjusted!"); + + /* Select the eMMC card. */ + if (!sdmmc_device_select_card(device)) + { + sdmmc_error(sdmmc, "Failed to select eMMC card!"); + return 0; + } + + sdmmc_info(sdmmc, "eMMC card is now selected!"); + + /* Change the eMMC's block length. */ + if (!sdmmc_device_set_blocklen(device, 512)) + { + sdmmc_error(sdmmc, "Failed to set eMMC's block length!"); + return 0; + } + + sdmmc_info(sdmmc, "eMMC's block length is now 512!"); + + /* Only specification version 4 and later support the next features. */ + if (device->csd.mmca_vsn < CSD_SPEC_VER_4) + return 1; + + /* Change the eMMC's bus width. */ + if (!sdmmc_mmc_select_bus_width(device, bus_width)) + { + sdmmc_error(sdmmc, "Failed to set eMMC's bus width!"); + return 0; + } + + sdmmc_info(sdmmc, "eMMC's bus width has been adjusted!"); + + /* Get the eMMC's extended CSD. */ + if (!sdmmc_mmc_send_ext_csd(device, ext_csd)) + { + sdmmc_error(sdmmc, "Failed to get EXT_CSD!"); + return 0; + } + + sdmmc_info(sdmmc, "Got EXT_CSD from eMMC!"); + + /* Decode and save the extended CSD. */ + sdmmc_mmc_decode_ext_csd(device, ext_csd); + + /* Decode and save the CID. */ + sdmmc_mmc_decode_cid(device, cid); + + /* TODO: Handle automatic BKOPS properly. Leave it disabled for now. */ + if (false && device->ext_csd.bkops && !(device->ext_csd.auto_bkops_en & EXT_CSD_AUTO_BKOPS_MASK)) + { + sdmmc_mmc_select_bkops(device); + sdmmc_info(sdmmc, "BKOPS is enabled!"); + } + else + sdmmc_info(sdmmc, "BKOPS is disabled!"); + + /* Switch to high speed mode. */ + if (!sdmmc_mmc_select_timing(device, bus_speed)) + { + sdmmc_error(sdmmc, "Failed to switch to high speed mode!"); + return 0; + } + + sdmmc_info(sdmmc, "Switched to high speed mode!"); + + /* Correct any inconsistent states. */ + sdmmc_adjust_sd_clock(sdmmc); + + return 1; +} \ No newline at end of file diff --git a/sept/sept-secondary/src/sdmmc/sdmmc.h b/sept/sept-secondary/src/sdmmc/sdmmc.h new file mode 100644 index 000000000..a40fe60d1 --- /dev/null +++ b/sept/sept-secondary/src/sdmmc/sdmmc.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SDMMC_H +#define FUSEE_SDMMC_H + +#include "sdmmc_core.h" + +/* Structure for storing the MMC CID (adapted from Linux headers) */ +typedef struct { + uint32_t manfid; + uint8_t prod_name[8]; + uint8_t prv; + uint32_t serial; + uint16_t oemid; + uint16_t year; + uint8_t hwrev; + uint8_t fwrev; + uint8_t month; +} mmc_cid_t; + +/* Structure for storing the MMC CSD (adapted from Linux headers) */ +typedef struct { + uint8_t structure; + uint8_t mmca_vsn; + uint16_t cmdclass; + uint16_t taac_clks; + uint32_t taac_ns; + uint32_t c_size; + uint32_t r2w_factor; + uint32_t max_dtr; + uint32_t erase_size; /* In sectors */ + uint32_t read_blkbits; + uint32_t write_blkbits; + uint32_t capacity; + uint32_t read_partial:1, + read_misalign:1, + write_partial:1, + write_misalign:1, + dsr_imp:1; +} mmc_csd_t; + +/* Structure for storing the MMC extended CSD (adapted from Linux headers) */ +typedef struct { + uint8_t rev; + uint8_t erase_group_def; + uint8_t sec_feature_support; + uint8_t rel_sectors; + uint8_t rel_param; + uint8_t part_config; + uint8_t cache_ctrl; + uint8_t rst_n_function; + uint8_t max_packed_writes; + uint8_t max_packed_reads; + uint8_t packed_event_en; + uint32_t part_time; /* Units: ms */ + uint32_t sa_timeout; /* Units: 100ns */ + uint32_t generic_cmd6_time; /* Units: 10ms */ + uint32_t power_off_longtime; /* Units: ms */ + uint8_t power_off_notification; /* state */ + uint32_t hs_max_dtr; + uint32_t hs200_max_dtr; + uint32_t sectors; + uint32_t hc_erase_size; /* In sectors */ + uint32_t hc_erase_timeout; /* In milliseconds */ + uint32_t sec_trim_mult; /* Secure trim multiplier */ + uint32_t sec_erase_mult; /* Secure erase multiplier */ + uint32_t trim_timeout; /* In milliseconds */ + uint32_t partition_setting_completed; /* enable bit */ + uint64_t enhanced_area_offset; /* Units: Byte */ + uint32_t enhanced_area_size; /* Units: KB */ + uint32_t cache_size; /* Units: KB */ + uint32_t hpi_en; /* HPI enablebit */ + uint32_t hpi; /* HPI support bit */ + uint32_t hpi_cmd; /* cmd used as HPI */ + uint32_t bkops; /* background support bit */ + uint32_t man_bkops_en; /* manual bkops enable bit */ + uint32_t auto_bkops_en; /* auto bkops enable bit */ + uint32_t data_sector_size; /* 512 bytes or 4KB */ + uint32_t data_tag_unit_size; /* DATA TAG UNIT size */ + uint32_t boot_ro_lock; /* ro lock support */ + uint32_t boot_ro_lockable; + uint32_t ffu_capable; /* Firmware upgrade support */ + uint32_t cmdq_en; /* Command Queue enabled */ + uint32_t cmdq_support; /* Command Queue supported */ + uint32_t cmdq_depth; /* Command Queue depth */ + uint8_t fwrev[8]; /* FW version */ + uint8_t raw_exception_status; /* 54 */ + uint8_t raw_partition_support; /* 160 */ + uint8_t raw_rpmb_size_mult; /* 168 */ + uint8_t raw_erased_mem_count; /* 181 */ + uint8_t strobe_support; /* 184 */ + uint8_t raw_ext_csd_structure; /* 194 */ + uint8_t raw_card_type; /* 196 */ + uint8_t raw_driver_strength; /* 197 */ + uint8_t out_of_int_time; /* 198 */ + uint8_t raw_pwr_cl_52_195; /* 200 */ + uint8_t raw_pwr_cl_26_195; /* 201 */ + uint8_t raw_pwr_cl_52_360; /* 202 */ + uint8_t raw_pwr_cl_26_360; /* 203 */ + uint8_t raw_s_a_timeout; /* 217 */ + uint8_t raw_hc_erase_gap_size; /* 221 */ + uint8_t raw_erase_timeout_mult; /* 223 */ + uint8_t raw_hc_erase_grp_size; /* 224 */ + uint8_t raw_sec_trim_mult; /* 229 */ + uint8_t raw_sec_erase_mult; /* 230 */ + uint8_t raw_sec_feature_support; /* 231 */ + uint8_t raw_trim_mult; /* 232 */ + uint8_t raw_pwr_cl_200_195; /* 236 */ + uint8_t raw_pwr_cl_200_360; /* 237 */ + uint8_t raw_pwr_cl_ddr_52_195; /* 238 */ + uint8_t raw_pwr_cl_ddr_52_360; /* 239 */ + uint8_t raw_pwr_cl_ddr_200_360; /* 253 */ + uint8_t raw_bkops_status; /* 246 */ + uint8_t raw_sectors[4]; /* 212 - 4 bytes */ + uint8_t pre_eol_info; /* 267 */ + uint8_t device_life_time_est_typ_a; /* 268 */ + uint8_t device_life_time_est_typ_b; /* 269 */ + uint32_t feature_support; +} mmc_ext_csd_t; + +/* Structure for storing the SD SCR (adapted from Linux headers) */ +typedef struct { + uint8_t sda_vsn; + uint8_t sda_spec3; + uint8_t bus_widths; + uint8_t cmds; +} sd_scr_t; + +/* Structure for storing the SD SSR (adapted from Linux headers) */ +typedef struct { + uint8_t dat_bus_width; + uint8_t secured_mode; + uint16_t sd_card_type; + uint8_t speed_class; + uint8_t uhs_speed_grade; + uint8_t uhs_au_size; + uint8_t video_speed_class; + uint8_t app_perf_class; +} sd_ssr_t; + +/* Structure describing a SDMMC device's context. */ +typedef struct { + /* Underlying driver context. */ + sdmmc_t *sdmmc; + + bool is_180v; + bool is_block_sdhc; + uint32_t rca; + mmc_cid_t cid; + mmc_csd_t csd; + mmc_ext_csd_t ext_csd; + sd_scr_t scr; + sd_ssr_t ssr; +} sdmmc_device_t; + +int sdmmc_device_sd_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed); +int sdmmc_device_mmc_init(sdmmc_device_t *device, sdmmc_t *sdmmc, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed); +int sdmmc_device_read(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data); +int sdmmc_device_write(sdmmc_device_t *device, uint32_t sector, uint32_t num_sectors, void *data); +int sdmmc_device_finish(sdmmc_device_t *device); +int sdmmc_mmc_select_partition(sdmmc_device_t *device, SdmmcPartitionNum partition); + +#endif \ No newline at end of file diff --git a/sept/sept-secondary/src/sdmmc/sdmmc_core.c b/sept/sept-secondary/src/sdmmc/sdmmc_core.c new file mode 100644 index 000000000..ded10a7ab --- /dev/null +++ b/sept/sept-secondary/src/sdmmc/sdmmc_core.c @@ -0,0 +1,1979 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> +#include <stdbool.h> +#include <stdint.h> +#include <errno.h> +#include <inttypes.h> + +#include "sdmmc_core.h" +#include "../car.h" +#include "../pinmux.h" +#include "../timers.h" +#include "../apb_misc.h" +#include "../gpio.h" +#include "../pmc.h" +#include "../max7762x.h" +#include "../lib/log.h" + +static void sdmmc_print(sdmmc_t *sdmmc, ScreenLogLevel screen_log_level, char *fmt, va_list list) +{ + if (screen_log_level > log_get_log_level()) + return; + + print(screen_log_level, "%s: ", sdmmc->name); + vprint(screen_log_level, fmt, list); + print(screen_log_level | SCREEN_LOG_LEVEL_NO_PREFIX, "\n"); +} + +void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_ERROR, fmt, list); + va_end(list); +} + +void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_WARNING, fmt, list); + va_end(list); +} + +void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_INFO, fmt, list); + va_end(list); +} + +void sdmmc_debug(sdmmc_t *sdmmc, char *fmt, ...) +{ + va_list list; + + va_start(list, fmt); + sdmmc_print(sdmmc, SCREEN_LOG_LEVEL_DEBUG, fmt, list); + va_end(list); +} + +void sdmmc_dump_regs(sdmmc_t *sdmmc) +{ + sdmmc_debug(sdmmc, "dma_address: 0x%08" PRIX32, sdmmc->regs->dma_address); + sdmmc_debug(sdmmc, "block_size: 0x%04" PRIX16, sdmmc->regs->block_size); + sdmmc_debug(sdmmc, "block_count: 0x%04" PRIX16, sdmmc->regs->block_count); + sdmmc_debug(sdmmc, "argument: 0x%08" PRIX32, sdmmc->regs->argument); + sdmmc_debug(sdmmc, "transfer_mode: 0x%04" PRIX16, sdmmc->regs->transfer_mode); + sdmmc_debug(sdmmc, "command: 0x%04" PRIX16, sdmmc->regs->command); + sdmmc_debug(sdmmc, "response[0]: 0x%08" PRIX32, sdmmc->regs->response[0]); + sdmmc_debug(sdmmc, "response[1]: 0x%08" PRIX32, sdmmc->regs->response[1]); + sdmmc_debug(sdmmc, "response[2]: 0x%08" PRIX32, sdmmc->regs->response[2]); + sdmmc_debug(sdmmc, "response[3]: 0x%08" PRIX32, sdmmc->regs->response[3]); + sdmmc_debug(sdmmc, "buffer: 0x%08" PRIX32, sdmmc->regs->buffer); + sdmmc_debug(sdmmc, "present_state: 0x%08" PRIX32, sdmmc->regs->present_state); + sdmmc_debug(sdmmc, "host_control: 0x%02" PRIX8, sdmmc->regs->host_control); + sdmmc_debug(sdmmc, "power_control: 0x%02" PRIX8, sdmmc->regs->power_control); + sdmmc_debug(sdmmc, "block_gap_control: 0x%02" PRIX8, sdmmc->regs->block_gap_control); + sdmmc_debug(sdmmc, "wake_up_control: 0x%02" PRIX8, sdmmc->regs->wake_up_control); + sdmmc_debug(sdmmc, "clock_control: 0x%04" PRIX16, sdmmc->regs->clock_control); + sdmmc_debug(sdmmc, "timeout_control: 0x%02" PRIX8, sdmmc->regs->timeout_control); + sdmmc_debug(sdmmc, "software_reset: 0x%02" PRIX8, sdmmc->regs->software_reset); + sdmmc_debug(sdmmc, "int_status: 0x%08" PRIX32, sdmmc->regs->int_status); + sdmmc_debug(sdmmc, "int_enable: 0x%08" PRIX32, sdmmc->regs->int_enable); + sdmmc_debug(sdmmc, "signal_enable: 0x%08" PRIX32, sdmmc->regs->signal_enable); + sdmmc_debug(sdmmc, "acmd12_err: 0x%04" PRIX16, sdmmc->regs->acmd12_err); + sdmmc_debug(sdmmc, "host_control2: 0x%04" PRIX16, sdmmc->regs->host_control2); + sdmmc_debug(sdmmc, "capabilities: 0x%08" PRIX32, sdmmc->regs->capabilities); + sdmmc_debug(sdmmc, "capabilities_1: 0x%08" PRIX32, sdmmc->regs->capabilities_1); + sdmmc_debug(sdmmc, "max_current: 0x%08" PRIX32, sdmmc->regs->max_current); + sdmmc_debug(sdmmc, "set_acmd12_error: 0x%04" PRIX16, sdmmc->regs->set_acmd12_error); + sdmmc_debug(sdmmc, "set_int_error: 0x%04" PRIX16, sdmmc->regs->set_int_error); + sdmmc_debug(sdmmc, "adma_error: 0x%02" PRIX8, sdmmc->regs->adma_error); + sdmmc_debug(sdmmc, "adma_address: 0x%08" PRIX32, sdmmc->regs->adma_address); + sdmmc_debug(sdmmc, "upper_adma_address: 0x%08" PRIX32, sdmmc->regs->upper_adma_address); + sdmmc_debug(sdmmc, "preset_for_init: 0x%04" PRIX16, sdmmc->regs->preset_for_init); + sdmmc_debug(sdmmc, "preset_for_default: 0x%04" PRIX16, sdmmc->regs->preset_for_default); + sdmmc_debug(sdmmc, "preset_for_high: 0x%04" PRIX16, sdmmc->regs->preset_for_high); + sdmmc_debug(sdmmc, "preset_for_sdr12: 0x%04" PRIX16, sdmmc->regs->preset_for_sdr12); + sdmmc_debug(sdmmc, "preset_for_sdr25: 0x%04" PRIX16, sdmmc->regs->preset_for_sdr25); + sdmmc_debug(sdmmc, "preset_for_sdr50: 0x%04" PRIX16, sdmmc->regs->preset_for_sdr50); + sdmmc_debug(sdmmc, "preset_for_sdr104: 0x%04" PRIX16, sdmmc->regs->preset_for_sdr104); + sdmmc_debug(sdmmc, "preset_for_ddr50: 0x%04" PRIX16, sdmmc->regs->preset_for_ddr50); + sdmmc_debug(sdmmc, "slot_int_status: 0x%04" PRIX16, sdmmc->regs->slot_int_status); + sdmmc_debug(sdmmc, "host_version: 0x%04" PRIX16, sdmmc->regs->host_version); + sdmmc_debug(sdmmc, "vendor_clock_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_clock_cntrl); + sdmmc_debug(sdmmc, "vendor_sys_sw_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_sys_sw_cntrl); + sdmmc_debug(sdmmc, "vendor_err_intr_status: 0x%08" PRIX32, sdmmc->regs->vendor_err_intr_status); + sdmmc_debug(sdmmc, "vendor_cap_overrides: 0x%08" PRIX32, sdmmc->regs->vendor_cap_overrides); + sdmmc_debug(sdmmc, "vendor_boot_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_boot_cntrl); + sdmmc_debug(sdmmc, "vendor_boot_ack_timeout: 0x%08" PRIX32, sdmmc->regs->vendor_boot_ack_timeout); + sdmmc_debug(sdmmc, "vendor_boot_dat_timeout: 0x%08" PRIX32, sdmmc->regs->vendor_boot_dat_timeout); + sdmmc_debug(sdmmc, "vendor_debounce_count: 0x%08" PRIX32, sdmmc->regs->vendor_debounce_count); + sdmmc_debug(sdmmc, "vendor_misc_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_misc_cntrl); + sdmmc_debug(sdmmc, "max_current_override: 0x%08" PRIX32, sdmmc->regs->max_current_override); + sdmmc_debug(sdmmc, "max_current_override_hi: 0x%08" PRIX32, sdmmc->regs->max_current_override_hi); + sdmmc_debug(sdmmc, "vendor_io_trim_cntrl: 0x%08" PRIX32, sdmmc->regs->vendor_io_trim_cntrl); + sdmmc_debug(sdmmc, "vendor_dllcal_cfg: 0x%08" PRIX32, sdmmc->regs->vendor_dllcal_cfg); + sdmmc_debug(sdmmc, "vendor_dll_ctrl0: 0x%08" PRIX32, sdmmc->regs->vendor_dll_ctrl0); + sdmmc_debug(sdmmc, "vendor_dll_ctrl1: 0x%08" PRIX32, sdmmc->regs->vendor_dll_ctrl1); + sdmmc_debug(sdmmc, "vendor_dllcal_cfg_sta: 0x%08" PRIX32, sdmmc->regs->vendor_dllcal_cfg_sta); + sdmmc_debug(sdmmc, "vendor_tuning_cntrl0: 0x%08" PRIX32, sdmmc->regs->vendor_tuning_cntrl0); + sdmmc_debug(sdmmc, "vendor_tuning_cntrl1: 0x%08" PRIX32, sdmmc->regs->vendor_tuning_cntrl1); + sdmmc_debug(sdmmc, "vendor_tuning_status0: 0x%08" PRIX32, sdmmc->regs->vendor_tuning_status0); + sdmmc_debug(sdmmc, "vendor_tuning_status1: 0x%08" PRIX32, sdmmc->regs->vendor_tuning_status1); + sdmmc_debug(sdmmc, "vendor_clk_gate_hysteresis_count: 0x%08" PRIX32, sdmmc->regs->vendor_clk_gate_hysteresis_count); + sdmmc_debug(sdmmc, "vendor_preset_val0: 0x%08" PRIX32, sdmmc->regs->vendor_preset_val0); + sdmmc_debug(sdmmc, "vendor_preset_val1: 0x%08" PRIX32, sdmmc->regs->vendor_preset_val1); + sdmmc_debug(sdmmc, "vendor_preset_val2: 0x%08" PRIX32, sdmmc->regs->vendor_preset_val2); + sdmmc_debug(sdmmc, "sdmemcomppadctrl: 0x%08" PRIX32, sdmmc->regs->sdmemcomppadctrl); + sdmmc_debug(sdmmc, "auto_cal_config: 0x%08" PRIX32, sdmmc->regs->auto_cal_config); + sdmmc_debug(sdmmc, "auto_cal_interval: 0x%08" PRIX32, sdmmc->regs->auto_cal_interval); + sdmmc_debug(sdmmc, "auto_cal_status: 0x%08" PRIX32, sdmmc->regs->auto_cal_status); + sdmmc_debug(sdmmc, "io_spare: 0x%08" PRIX32, sdmmc->regs->io_spare); + sdmmc_debug(sdmmc, "sdmmca_mccif_fifoctrl: 0x%08" PRIX32, sdmmc->regs->sdmmca_mccif_fifoctrl); + sdmmc_debug(sdmmc, "timeout_wcoal_sdmmca: 0x%08" PRIX32, sdmmc->regs->timeout_wcoal_sdmmca); +} + +typedef struct { + uint32_t clk_source_val; + uint32_t clk_div_val; +} sdmmc_clk_source_t; + +static sdmmc_clk_source_t sdmmc_clk_sources[4] = {0}; + +/* Check if the SDMMC device clock is held in reset. */ +static bool is_sdmmc_clk_rst(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + return (car->rst_dev_l & CLK_L_SDMMC1); + case SDMMC_2: + return (car->rst_dev_l & CLK_L_SDMMC2); + case SDMMC_3: + return (car->rst_dev_u & CLK_U_SDMMC3); + case SDMMC_4: + return (car->rst_dev_l & CLK_L_SDMMC4); + } + + return false; +} + +/* Put the SDMMC device clock in reset. */ +static void sdmmc_clk_set_rst(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + car->rst_dev_l_set = CLK_L_SDMMC1; + break; + case SDMMC_2: + car->rst_dev_l_set = CLK_L_SDMMC2; + break; + case SDMMC_3: + car->rst_dev_u_set = CLK_U_SDMMC3; + break; + case SDMMC_4: + car->rst_dev_l_set = CLK_L_SDMMC4; + break; + } +} + +/* Take the SDMMC device clock out of reset. */ +static void sdmmc_clk_clear_rst(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + car->rst_dev_l_clr = CLK_L_SDMMC1; + break; + case SDMMC_2: + car->rst_dev_l_clr = CLK_L_SDMMC2; + break; + case SDMMC_3: + car->rst_dev_u_clr = CLK_U_SDMMC3; + break; + case SDMMC_4: + car->rst_dev_l_clr = CLK_L_SDMMC4; + break; + } +} + +/* Check if the SDMMC device clock is enabled. */ +static bool is_sdmmc_clk_enb(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + return (car->clk_out_enb_l & CLK_L_SDMMC1); + case SDMMC_2: + return (car->clk_out_enb_l & CLK_L_SDMMC2); + case SDMMC_3: + return (car->clk_out_enb_u & CLK_U_SDMMC3); + case SDMMC_4: + return (car->clk_out_enb_l & CLK_L_SDMMC4); + } + + return false; +} + +/* Enable the SDMMC device clock. */ +static void sdmmc_clk_set_enb(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + car->clk_enb_l_set = CLK_L_SDMMC1; + break; + case SDMMC_2: + car->clk_enb_l_set = CLK_L_SDMMC2; + break; + case SDMMC_3: + car->clk_enb_u_set = CLK_U_SDMMC3; + break; + case SDMMC_4: + car->clk_enb_l_set = CLK_L_SDMMC4; + break; + } +} + +/* Disable the SDMMC device clock. */ +static void sdmmc_clk_clear_enb(SdmmcControllerNum controller) +{ + volatile tegra_car_t *car = car_get_regs(); + + switch (controller) { + case SDMMC_1: + car->clk_enb_l_clr = CLK_L_SDMMC1; + break; + case SDMMC_2: + car->clk_enb_l_clr = CLK_L_SDMMC2; + break; + case SDMMC_3: + car->clk_enb_u_clr = CLK_U_SDMMC3; + break; + case SDMMC_4: + car->clk_enb_l_clr = CLK_L_SDMMC4; + break; + } +} + +/* Get the appropriate SDMMC maximum frequency. */ +static int sdmmc_get_sdclk_freq(SdmmcBusSpeed bus_speed) +{ + switch (bus_speed) + { + case SDMMC_SPEED_INIT_HS: + case SDMMC_SPEED_HS26: + return 26000; + case SDMMC_SPEED_HS52: + return 52000; + case SDMMC_SPEED_HS200: + case SDMMC_SPEED_HS400: + case SDMMC_SPEED_SDR104: + return 200000; + case SDMMC_SPEED_INIT_SDR: + case SDMMC_SPEED_UNK6: + case SDMMC_SPEED_SDR12: + return 25000; + case SDMMC_SPEED_SDR25: + return 50000; + case SDMMC_SPEED_SDR50: + return 100000; + case SDMMC_SPEED_DDR50: + return 40800; + case SDMMC_SPEED_UNK14: + return 200000; + default: + return 0; + } +} + +/* Get the appropriate SDMMC divider for the SDCLK. */ +static int sdmmc_get_sdclk_div(SdmmcBusSpeed bus_speed) +{ + switch (bus_speed) + { + case SDMMC_SPEED_INIT_HS: + return 66; + case SDMMC_SPEED_INIT_SDR: + // TODO: TRM says return 64? + case SDMMC_SPEED_HS26: + case SDMMC_SPEED_HS52: + case SDMMC_SPEED_HS200: + case SDMMC_SPEED_HS400: + case SDMMC_SPEED_UNK6: + case SDMMC_SPEED_SDR25: + case SDMMC_SPEED_SDR12: + case SDMMC_SPEED_SDR50: + case SDMMC_SPEED_SDR104: + case SDMMC_SPEED_DDR50: + return 1; + case SDMMC_SPEED_UNK14: + return 2; + default: + return 0; + } +} + +/* Set the device clock source and CAR divider. */ +static int sdmmc_clk_set_source(SdmmcControllerNum controller, uint32_t clk_freq) +{ + volatile tegra_car_t *car = car_get_regs(); + + uint32_t car_div = 0; + uint32_t out_freq = 0; + + switch (clk_freq) + { + case 25000: + out_freq = 24728; + car_div = SDMMC_CAR_DIVIDER_SDR12; + break; + case 26000: + out_freq = 25500; + car_div = SDMMC_CAR_DIVIDER_HS26; + break; + case 40800: + out_freq = 40800; + car_div = SDMMC_CAR_DIVIDER_DDR50; + break; + case 50000: + out_freq = 48000; + car_div = SDMMC_CAR_DIVIDER_SDR25; + break; + case 52000: + out_freq = 51000; + car_div = SDMMC_CAR_DIVIDER_HS52; + break; + case 100000: + out_freq = 90667; + car_div = SDMMC_CAR_DIVIDER_SDR50; + break; + case 200000: + out_freq = 163200; + car_div = SDMMC_CAR_DIVIDER_HS200; + break; + case 208000: + out_freq = 204000; + car_div = SDMMC_CAR_DIVIDER_SDR104; + break; + default: + return 0; + } + + sdmmc_clk_sources[controller].clk_source_val = clk_freq; + sdmmc_clk_sources[controller].clk_div_val = out_freq; + + switch (controller) + { + case SDMMC_1: + car->clk_source_sdmmc1 = (CLK_SOURCE_FIRST | car_div); + break; + case SDMMC_2: + car->clk_source_sdmmc2 = (CLK_SOURCE_FIRST | car_div); + break; + case SDMMC_3: + car->clk_source_sdmmc3 = (CLK_SOURCE_FIRST | car_div); + break; + case SDMMC_4: + car->clk_source_sdmmc4 = (CLK_SOURCE_FIRST | car_div); + break; + } + + return out_freq; +} + +/* Adjust the device clock source value. */ +static int sdmmc_clk_adjust_source(SdmmcControllerNum controller, uint32_t clk_source_val) +{ + uint32_t out_val = 0; + + if (sdmmc_clk_sources[controller].clk_source_val == clk_source_val) + out_val = sdmmc_clk_sources[controller].clk_div_val; + else + { + bool was_sdmmc_clk_enb = is_sdmmc_clk_enb(controller); + + /* Clock was already enabled. Disable it. */ + if (was_sdmmc_clk_enb) + sdmmc_clk_clear_enb(controller); + + out_val = sdmmc_clk_set_source(controller, clk_source_val); + + /* Clock was already enabled. Enable it back. */ + if (was_sdmmc_clk_enb) + sdmmc_clk_set_enb(controller); + + /* Dummy read for value refreshing. */ + is_sdmmc_clk_rst(controller); + } + + return out_val; +} + +/* Enable the SD clock if possible. */ +static void sdmmc_enable_sd_clock(sdmmc_t *sdmmc) +{ + if ((sdmmc->has_sd) && !(sdmmc->regs->clock_control & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)) + sdmmc->regs->clock_control |= TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; + sdmmc->is_sd_clk_enabled = true; +} + +/* Disable the SD clock. */ +static void sdmmc_disable_sd_clock(sdmmc_t *sdmmc) +{ + sdmmc->is_sd_clk_enabled = false; + sdmmc->regs->clock_control &= ~TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE; +} + +/* Automatically enable or disable the SD clock. */ +void sdmmc_adjust_sd_clock(sdmmc_t *sdmmc) +{ + if (!(sdmmc->has_sd) && (sdmmc->regs->clock_control & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)) + sdmmc_disable_sd_clock(sdmmc); + else if (sdmmc->is_sd_clk_enabled && !(sdmmc->regs->clock_control & TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE)) + sdmmc_enable_sd_clock(sdmmc); +} + +/* Return the clock control value. Used for dummy reads. */ +static int sdmmc_get_sd_clock_control(sdmmc_t *sdmmc) +{ + return sdmmc->regs->clock_control; +} + +/* Start the SDMMC clock. */ +static void sdmmc_clk_start(SdmmcControllerNum controller, uint32_t clk_source_val) +{ + /* Clock was already enabled. Disable it. */ + if (is_sdmmc_clk_enb(controller)) + sdmmc_clk_clear_enb(controller); + + /* Put the device clock in reset. */ + sdmmc_clk_set_rst(controller); + + /* Configure the device clock source. */ + uint32_t clk_div = sdmmc_clk_set_source(controller, clk_source_val); + + /* Enable the device clock. */ + sdmmc_clk_set_enb(controller); + + /* Dummy read for value refreshing. */ + is_sdmmc_clk_rst(controller); + + /* Synchronize. */ + udelay((100000 + clk_div - 1) / clk_div); + + /* Take the device clock out of reset. */ + sdmmc_clk_clear_rst(controller); + + /* Dummy read for value refreshing. */ + is_sdmmc_clk_rst(controller); +} + +/* Stop the SDMMC clock. */ +static void sdmmc_clk_stop(SdmmcControllerNum controller) +{ + /* Put the device clock in reset. */ + sdmmc_clk_set_rst(controller); + + /* Disable the device clock. */ + sdmmc_clk_clear_enb(controller); + + /* Dummy read for value refreshing. */ + is_sdmmc_clk_rst(controller); +} + +/* Configure clock trimming. */ +static void sdmmc_vendor_clock_cntrl_config(sdmmc_t *sdmmc) +{ + /* Clear the I/O conditioning constants. */ + sdmmc->regs->vendor_clock_cntrl &= ~(SDMMC_CLOCK_TRIM_MASK | SDMMC_CLOCK_TAP_MASK); + + /* Per the TRM, set the PADPIPE clock enable */ + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_PADPIPE_CLKEN_OVERRIDE; + + /* Set the appropriate trim value. */ + switch (sdmmc->controller) { + case SDMMC_1: + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_TRIM_SDMMC1; + break; + case SDMMC_2: + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_TRIM_SDMMC2; + break; + case SDMMC_3: + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_TRIM_SDMMC3; + break; + case SDMMC_4: + sdmmc->regs->vendor_clock_cntrl |= SDMMC_CLOCK_TRIM_SDMMC4; + break; + } +} + +/* Configure automatic calibration. */ +static int sdmmc_autocal_config(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) +{ + switch (sdmmc->controller) { + case SDMMC_1: + case SDMMC_3: + switch (voltage) { + case SDMMC_VOLTAGE_1V8: + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); + sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_1V8; + break; + case SDMMC_VOLTAGE_3V3: + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); + sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC1_3V3; + break; + default: + sdmmc_error(sdmmc, "uSD does not support requested voltage!"); + return 0; + } + + break; + case SDMMC_2: + case SDMMC_4: + if (voltage != SDMMC_VOLTAGE_1V8) { + sdmmc_error(sdmmc, "eMMC can only run at 1V8!"); + return 0; + } + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_PDPU_CONFIG_MASK); + sdmmc->regs->auto_cal_config |= SDMMC_AUTOCAL_PDPU_SDMMC4_1V8; + break; + } + + return 1; +} + +/* Run automatic calibration. */ +static void sdmmc_autocal_run(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) +{ + volatile tegra_padctl_t *padctl = padctl_get_regs(); + bool restart_sd_clock = false; + + /* SD clock is enabled. Disable it and restart later. */ + if (sdmmc->is_sd_clk_enabled) + { + restart_sd_clock = true; + sdmmc_disable_sd_clock(sdmmc); + } + + /* Set PAD_E_INPUT_OR_E_PWRD */ + if (!(sdmmc->regs->sdmemcomppadctrl & 0x80000000)) + { + sdmmc->regs->sdmemcomppadctrl |= 0x80000000; + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Delay. */ + udelay(1); + } + + /* Start automatic calibration. */ + sdmmc->regs->auto_cal_config |= (SDMMC_AUTOCAL_START | SDMMC_AUTOCAL_ENABLE); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Delay. */ + udelay(1); + + /* Get current time. */ + uint32_t timebase = get_time(); + + /* Wait until the autocal is complete. */ + while ((sdmmc->regs->auto_cal_status & SDMMC_AUTOCAL_ACTIVE)) { + /* Ensure we haven't timed out. */ + if (get_time_since(timebase) > SDMMC_AUTOCAL_TIMEOUT) { + sdmmc_error(sdmmc, "Auto-calibration timed out!"); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Upon timeout, fall back to standard values. */ + if (sdmmc->controller == SDMMC_1) { + uint32_t drvup = (voltage == SDMMC_VOLTAGE_3V3) ? 0x12 : 0x11; + uint32_t drvdn = (voltage == SDMMC_VOLTAGE_3V3) ? 0x12 : 0x15; + uint32_t value = padctl->sdmmc1_pad_cfgpadctrl; + value &= ~(SDMMC1_PAD_CAL_DRVUP_MASK | SDMMC1_PAD_CAL_DRVDN_MASK); + value |= (drvup << SDMMC1_PAD_CAL_DRVUP_SHIFT); + value |= (drvdn << SDMMC1_PAD_CAL_DRVDN_SHIFT); + padctl->sdmmc1_pad_cfgpadctrl = value; + } else if (sdmmc->controller == SDMMC_4) { + uint32_t value = padctl->emmc4_pad_cfgpadctrl; + value &= ~(CFG2TMC_EMMC4_PAD_DRVUP_COMP_MASK | CFG2TMC_EMMC4_PAD_DRVDN_COMP_MASK); + value |= (0x10 << CFG2TMC_EMMC4_PAD_DRVUP_COMP_SHIFT); + value |= (0x10 << CFG2TMC_EMMC4_PAD_DRVDN_COMP_SHIFT); + padctl->emmc4_pad_cfgpadctrl = value; + } + + /* Manually clear the autocal enable bit. */ + sdmmc->regs->auto_cal_config &= ~(SDMMC_AUTOCAL_ENABLE); + break; + } + } + + /* Clear PAD_E_INPUT_OR_E_PWRD (relevant for eMMC only) */ + sdmmc->regs->sdmemcomppadctrl &= ~(0x80000000); + + /* If requested, enable the SD clock. */ + if (restart_sd_clock) + sdmmc_enable_sd_clock(sdmmc); +} + +static int sdmmc_int_clk_enable(sdmmc_t *sdmmc) +{ + /* Enable the internal clock. */ + sdmmc->regs->clock_control |= TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE; + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 2000ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait for the clock to stabilize. */ + while (!(sdmmc->regs->clock_control & TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + } + + /* Clock failed to stabilize. */ + if (is_timeout) { + sdmmc_error(sdmmc, "clock never stabilized!"); + return 0; + } + + /* Configure clock control and host control 2. */ + sdmmc->regs->host_control2 &= ~SDHCI_CTRL_PRESET_VAL_ENABLE; + sdmmc->regs->clock_control &= ~TEGRA_MMC_CLKCON_PROG_CLOCK_MODE; + sdmmc->regs->host_control2 |= SDHCI_HOST_VERSION_4_EN; + + /* Ensure 64bit addressing is supported. */ + if (!(sdmmc->regs->capabilities & SDHCI_CAN_64BIT)) { + sdmmc_error(sdmmc, "64bit addressing is unsupported!"); + return 0; + } + + /* Enable 64bit addressing. */ + sdmmc->regs->host_control2 |= SDHCI_ADDRESSING_64BIT_EN; + + /* Use SDMA by default. */ + sdmmc->regs->host_control &= ~SDHCI_CTRL_DMA_MASK; + + /* Change to ADMA if possible. */ + if (sdmmc->regs->capabilities & SDHCI_CAN_DO_ADMA2) + sdmmc->use_adma = true; + + /* Set the timeout to be the maximum value. */ + sdmmc->regs->timeout_control &= 0xF0; + sdmmc->regs->timeout_control |= 0x0E; + + return 1; +} + +void sdmmc_select_bus_width(sdmmc_t *sdmmc, SdmmcBusWidth width) +{ + if (width == SDMMC_BUS_WIDTH_1BIT) + { + sdmmc->regs->host_control &= ~(SDHCI_CTRL_4BITBUS | SDHCI_CTRL_8BITBUS); + sdmmc->bus_width = SDMMC_BUS_WIDTH_1BIT; + } + else if (width == SDMMC_BUS_WIDTH_4BIT) + { + sdmmc->regs->host_control |= SDHCI_CTRL_4BITBUS; + sdmmc->regs->host_control &= ~SDHCI_CTRL_8BITBUS; + sdmmc->bus_width = SDMMC_BUS_WIDTH_4BIT; + } + else if (width == SDMMC_BUS_WIDTH_8BIT) + { + sdmmc->regs->host_control |= SDHCI_CTRL_8BITBUS; + sdmmc->bus_width = SDMMC_BUS_WIDTH_8BIT; + } + else + sdmmc_error(sdmmc, "Invalid bus width specified!"); +} + +void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage) +{ + if (voltage == SDMMC_VOLTAGE_NONE) + { + sdmmc->regs->power_control &= ~TEGRA_MMC_PWRCTL_SD_BUS_POWER; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + } + else if (voltage == SDMMC_VOLTAGE_1V8) + { + sdmmc->regs->power_control |= TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8; + sdmmc->regs->power_control |= TEGRA_MMC_PWRCTL_SD_BUS_POWER; + sdmmc->bus_voltage = SDMMC_VOLTAGE_1V8; + } + else if (voltage == SDMMC_VOLTAGE_3V3) + { + sdmmc->regs->power_control |= TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3; + sdmmc->regs->power_control |= TEGRA_MMC_PWRCTL_SD_BUS_POWER; + sdmmc->bus_voltage = SDMMC_VOLTAGE_3V3; + } + else + sdmmc_error(sdmmc, "Invalid power state specified!"); +} + +static void sdmmc_tap_config(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed) +{ + if (bus_speed == SDMMC_SPEED_HS400) + { + /* Clear and set DQS_TRIM_VAL (used in HS400) */ + sdmmc->regs->vendor_cap_overrides &= ~(0x3F00); + sdmmc->regs->vendor_cap_overrides |= 0x2800; + } + + /* Clear TAP_VAL_UPDATED_BY_HW */ + sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x20000); + + if (bus_speed == SDMMC_SPEED_HS400) + { + /* We must have obtained the tap value from the tuning procedure here. */ + if (sdmmc->is_tuning_tap_val_set) + { + /* Clear and set the tap value. */ + sdmmc->regs->vendor_clock_cntrl &= ~(0xFF0000); + sdmmc->regs->vendor_clock_cntrl |= (sdmmc->tap_val << 16); + } + } + else + { + /* Use the recommended values. */ + switch (sdmmc->controller) + { + case SDMMC_1: + sdmmc->tap_val = 4; + break; + case SDMMC_2: + case SDMMC_4: + sdmmc->tap_val = 0; + break; + case SDMMC_3: + sdmmc->tap_val = 3; + break; + } + + /* Clear and set the tap value. */ + sdmmc->regs->vendor_clock_cntrl &= ~(0xFF0000); + sdmmc->regs->vendor_clock_cntrl |= (sdmmc->tap_val << 16); + } +} + +static int sdmmc_dllcal_run(sdmmc_t *sdmmc) +{ + bool shutdown_sd_clock = false; + + /* SD clock is disabled. Enable it. */ + if (!sdmmc->is_sd_clk_enabled) + { + shutdown_sd_clock = true; + sdmmc_enable_sd_clock(sdmmc); + } + + /* Set the CALIBRATE bit. */ + sdmmc->regs->vendor_dllcal_cfg |= 0x80000000; + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 5ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait for CALIBRATE to be cleared. */ + while ((sdmmc->regs->vendor_dllcal_cfg & 0x80000000) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 5000); + } + + /* Calibration failed. */ + if (is_timeout) { + sdmmc_error(sdmmc, "DLLCAL failed!"); + return 0; + } + + /* Program a timeout of 10ms. */ + timebase = get_time(); + is_timeout = false; + + /* Wait for DLL_CAL_ACTIVE to be cleared. */ + while ((sdmmc->regs->vendor_dllcal_cfg_sta & 0x80000000) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 10000); + } + + /* Calibration failed. */ + if (is_timeout) { + sdmmc_error(sdmmc, "DLLCAL failed!"); + return 0; + } + + /* If requested, disable the SD clock. */ + if (shutdown_sd_clock) + sdmmc_disable_sd_clock(sdmmc); + + return 1; +} + +int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed) +{ + bool restart_sd_clock = false; + + /* SD clock is enabled. Disable it and restart later. */ + if (sdmmc->is_sd_clk_enabled) + { + restart_sd_clock = true; + sdmmc_disable_sd_clock(sdmmc); + } + + /* Configure tap values as necessary. */ + sdmmc_tap_config(sdmmc, bus_speed); + + /* Set the appropriate host speed. */ + switch (bus_speed) { + /* 400kHz initialization mode and a few others. */ + case SDMMC_SPEED_INIT_HS: + case SDMMC_SPEED_HS26: + case SDMMC_SPEED_INIT_SDR: + case SDMMC_SPEED_UNK6: + sdmmc->regs->host_control &= ~(SDHCI_CTRL_HISPD); + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180); + break; + + /* 50MHz high speed (SD) and 52MHz high speed (MMC). */ + case SDMMC_SPEED_SDR25: + case SDMMC_SPEED_HS52: + sdmmc->regs->host_control |= SDHCI_CTRL_HISPD; + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_VDD_180); + break; + + /* 200MHz UHS-I (SD) and other modes due to errata. */ + case SDMMC_SPEED_HS200: + case SDMMC_SPEED_SDR104: + case SDMMC_SPEED_DDR50: + case SDMMC_SPEED_SDR50: + case SDMMC_SPEED_UNK14: + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR104; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; + break; + + /* 200MHz single-data rate (MMC). */ + case SDMMC_SPEED_HS400: + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_HS400; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; + break; + + /* 25MHz default speed (SD). */ + case SDMMC_SPEED_SDR12: + sdmmc->regs->host_control2 &= ~(SDHCI_CTRL_UHS_MASK); + sdmmc->regs->host_control2 |= SDHCI_CTRL_UHS_SDR12; + sdmmc->regs->host_control2 |= SDHCI_CTRL_VDD_180; + break; + + default: + sdmmc_error(sdmmc, "Switching to unsupported speed!"); + return 0; + } + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Get the clock's frequency and divider. */ + uint32_t freq_val = sdmmc_get_sdclk_freq(bus_speed); + uint32_t div_val = sdmmc_get_sdclk_div(bus_speed); + + /* Adjust the CAR side of the clock. */ + uint32_t out_freq_val = sdmmc_clk_adjust_source(sdmmc->controller, freq_val); + + /* Save the internal divider value. */ + sdmmc->internal_divider = ((out_freq_val + div_val - 1) / div_val); + + uint16_t div_val_lo = div_val >> 1; + uint16_t div_val_hi = 0; + + if (div_val_lo > 0xFF) + div_val_hi = (div_val_lo >> 8); + + /* Set the clock control divider values. */ + sdmmc->regs->clock_control &= ~((SDHCI_DIV_HI_MASK | SDHCI_DIV_MASK) << 6); + sdmmc->regs->clock_control |= ((div_val_hi << SDHCI_DIVIDER_HI_SHIFT) | (div_val_lo << SDHCI_DIVIDER_SHIFT)); + + /* If requested, enable the SD clock. */ + if (restart_sd_clock) + sdmmc_enable_sd_clock(sdmmc); + + /* Run DLLCAL for HS400 only */ + if (bus_speed == SDMMC_SPEED_HS400) + return sdmmc_dllcal_run(sdmmc); + + return 1; +} + +static int sdmmc1_config() +{ + volatile tegra_pinmux_t *pinmux = pinmux_get_regs(); + volatile tegra_padctl_t *padctl = padctl_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* Set up the card detect pin as a GPIO input */ + pinmux->pz1 = PINMUX_SELECT_FUNCTION1 | PINMUX_PULL_UP | PINMUX_INPUT; + padctl->vgpio_gpio_mux_sel = 0; + gpio_configure_mode(GPIO_MICROSD_CARD_DETECT, GPIO_MODE_GPIO); + gpio_configure_direction(GPIO_MICROSD_CARD_DETECT, GPIO_DIRECTION_INPUT); + udelay(100); + + /* Check the GPIO. */ + if (gpio_read(GPIO_MICROSD_CARD_DETECT)) + return 0; + + padctl->sdmmc1_clk_lpbk_control = 1; + + /* Set up the SDMMC1 pinmux. */ + pinmux->sdmmc1_clk = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT; + pinmux->sdmmc1_cmd = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + pinmux->sdmmc1_dat3 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + pinmux->sdmmc1_dat2 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + pinmux->sdmmc1_dat1 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + pinmux->sdmmc1_dat0 = PINMUX_DRIVE_2X | PINMUX_PARKED | PINMUX_SELECT_FUNCTION0 | PINMUX_INPUT | PINMUX_PULL_UP; + + /* Ensure the PMC is prepared for the SDMMC1 card to receive power. */ + pmc->no_iopower &= ~PMC_CONTROL_SDMMC1; + pmc->pwr_det_val |= PMC_CONTROL_SDMMC1; + + /* Configure the enable line for the SD card power. */ + pinmux->dmic3_clk = PINMUX_SELECT_FUNCTION1 | PINMUX_PULL_DOWN | PINMUX_INPUT; + gpio_configure_mode(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_MODE_GPIO); + gpio_write(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_LEVEL_HIGH); + gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_OUTPUT); + + udelay(1000); + + /* Set up SD card voltages. */ + max77620_regulator_set_voltage(REGULATOR_LDO2, 3300000); + max77620_regulator_enable(REGULATOR_LDO2, 1); + + udelay(1000); + + padctl->sdmmc1_pad_cfgpadctrl = 0x10000000; + + udelay(1000); + + return 1; +} + +static int sdmmc2_config() +{ + return 1; +} + +static int sdmmc3_config() +{ + return 1; +} + +static int sdmmc4_config() +{ + return 1; +} + +static int sdmmc_init_controller(sdmmc_t *sdmmc, SdmmcControllerNum controller) +{ + /* Sanitize input number for the controller. */ + if ((controller < SDMMC_1) || (controller > SDMMC_4)) + return 0; + + /* Clear up memory for our struct. */ + memset(sdmmc, 0, sizeof(sdmmc_t)); + + /* Bind the appropriate controller and it's register space to our struct. */ + sdmmc->controller = controller; + sdmmc->regs = sdmmc_get_regs(controller); + + /* Set up per-device pointers and properties. */ + switch (sdmmc->controller) { + case SDMMC_1: + /* Controller properties. */ + sdmmc->name = "uSD"; + sdmmc->has_sd = true; + sdmmc->is_clk_running = false; + sdmmc->is_sd_clk_enabled = false; + sdmmc->is_tuning_tap_val_set = false; + sdmmc->use_adma = false; + sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; + sdmmc->tap_val = 0; + sdmmc->internal_divider = 0; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + + /* Function pointers. */ + sdmmc->sdmmc_config = sdmmc1_config; + break; + + case SDMMC_2: + /* Controller properties. */ + sdmmc->name = "GC"; + sdmmc->has_sd = true; + sdmmc->is_clk_running = false; + sdmmc->is_sd_clk_enabled = false; + sdmmc->is_tuning_tap_val_set = false; + sdmmc->use_adma = false; + sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; + sdmmc->tap_val = 0; + sdmmc->internal_divider = 0; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + + /* Function pointers. */ + sdmmc->sdmmc_config = sdmmc2_config; + break; + + case SDMMC_3: + /* Controller properties. */ + sdmmc->name = "UNUSED"; + sdmmc->has_sd = true; + sdmmc->is_clk_running = false; + sdmmc->is_sd_clk_enabled = false; + sdmmc->is_tuning_tap_val_set = false; + sdmmc->use_adma = false; + sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; + sdmmc->tap_val = 0; + sdmmc->internal_divider = 0; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + + /* Function pointers. */ + sdmmc->sdmmc_config = sdmmc3_config; + break; + + case SDMMC_4: + /* Controller properties. */ + sdmmc->name = "eMMC"; + sdmmc->has_sd = true; + sdmmc->is_clk_running = false; + sdmmc->is_sd_clk_enabled = false; + sdmmc->is_tuning_tap_val_set = false; + sdmmc->use_adma = false; + sdmmc->dma_bounce_buf = (uint8_t*)SDMMC_BOUNCE_BUFFER_ADDRESS; + sdmmc->tap_val = 0; + sdmmc->internal_divider = 0; + sdmmc->bus_voltage = SDMMC_VOLTAGE_NONE; + + /* Function pointers. */ + sdmmc->sdmmc_config = sdmmc4_config; + break; + } + + return 1; +} + +int sdmmc_init(sdmmc_t *sdmmc, SdmmcControllerNum controller, SdmmcBusVoltage bus_voltage, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed) +{ + /* Initialize our controller structure. */ + if (!sdmmc_init_controller(sdmmc, controller)) { + sdmmc_error(sdmmc, "Failed to initialize SDMMC%d", controller + 1); + return 0; + } + + /* Perform initial configuration steps if necessary. */ + if (!sdmmc->sdmmc_config()) { + sdmmc_error(sdmmc, "Failed to configure controller!"); + return 0; + } + + /* Initialize the clock status. */ + sdmmc->is_clk_running = false; + + /* Clock is enabled and out of reset. Shouldn't happen. */ + if (!is_sdmmc_clk_rst(controller) && is_sdmmc_clk_enb(controller)) { + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + } + + /* Sort out the clock's frequency. */ + uint32_t clk_freq_val = sdmmc_get_sdclk_freq(bus_speed); + + /* Start the SDMMC clock. */ + sdmmc_clk_start(controller, clk_freq_val); + + /* Update the clock status. */ + sdmmc->is_clk_running = true; + + // Set IO_SPARE[19] (one cycle delay) + sdmmc->regs->io_spare |= 0x80000; + + // Clear SEL_VREG + sdmmc->regs->vendor_io_trim_cntrl &= ~(0x04); + + /* Configure vendor clocking. */ + sdmmc_vendor_clock_cntrl_config(sdmmc); + + // Set SDMMC2TMC_CFG_SDMEMCOMP_VREF_SEL to 0x07 + sdmmc->regs->sdmemcomppadctrl &= 0x0F; + sdmmc->regs->sdmemcomppadctrl |= 0x07; + + /* Configure autocal offsets. */ + if (!sdmmc_autocal_config(sdmmc, bus_voltage)) { + sdmmc_error(sdmmc, "Failed to configure automatic calibration!"); + return 0; + } + + /* Do autocal. */ + sdmmc_autocal_run(sdmmc, bus_voltage); + + /* Enable the internal clock. */ + if (!sdmmc_int_clk_enable(sdmmc)) { + sdmmc_error(sdmmc, "Failed to enable the internal clock!"); + return 0; + } + + /* Select the desired bus width. */ + sdmmc_select_bus_width(sdmmc, bus_width); + + /* Select the desired voltage. */ + sdmmc_select_voltage(sdmmc, bus_voltage); + + /* Enable the internal clock. */ + if (!sdmmc_select_speed(sdmmc, bus_speed)) { + sdmmc_error(sdmmc, "Failed to apply the correct bus speed!"); + return 0; + } + + /* Correct any inconsistent states. */ + sdmmc_adjust_sd_clock(sdmmc); + + /* Enable the SD clock. */ + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + return 1; +} + +void sdmmc_finish(sdmmc_t *sdmmc) +{ + /* Stop everything. */ + if (sdmmc->is_clk_running) + { + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + + /* Disable SDMMC power. */ + sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_NONE); + + /* Disable the SD card power. */ + if (sdmmc->controller == SDMMC_1) + { + /* Disable GPIO output. */ + gpio_configure_direction(GPIO_MICROSD_SUPPLY_ENABLE, GPIO_DIRECTION_INPUT); + + /* Power cycle for 100ms without power. */ + mdelay(100); + } + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Stop the SDMMC clock. */ + sdmmc_clk_stop(sdmmc->controller); + + /* Clock is no longer running by now. */ + sdmmc->is_clk_running = false; + } +} + +static void sdmmc_do_sw_reset(sdmmc_t *sdmmc) +{ + /* Assert a software reset. */ + sdmmc->regs->software_reset |= (TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE | TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 100ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait for the register to be cleared. */ + while ((sdmmc->regs->software_reset & (TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE | TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE)) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 100000); + } +} + +static int sdmmc_wait_for_inhibit(sdmmc_t *sdmmc, bool wait_for_dat) +{ + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 10ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait on CMD inhibit to be cleared. */ + while ((sdmmc->regs->present_state & TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 10000); + } + + /* Bit was never released. Reset. */ + if (is_timeout) + { + sdmmc_do_sw_reset(sdmmc); + return 0; + } + + if (wait_for_dat) + { + /* Program a timeout of 10ms. */ + timebase = get_time(); + is_timeout = false; + + /* Wait on DAT inhibit to be cleared. */ + while ((sdmmc->regs->present_state & TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 10000); + } + + /* Bit was never released, reset. */ + if (is_timeout) + { + sdmmc_do_sw_reset(sdmmc); + return 0; + } + } + + return 1; +} + +static int sdmmc_wait_busy(sdmmc_t *sdmmc) +{ + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a timeout of 10ms. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait on DAT0 level mask to be set. */ + while (!(sdmmc->regs->present_state & SDHCI_DATA_0_LVL_MASK) && !is_timeout) { + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 10000); + } + + /* Bit was never released. Reset. */ + if (is_timeout) + { + sdmmc_do_sw_reset(sdmmc); + return 0; + } + + return 1; +} + +static void sdmmc_intr_enable(sdmmc_t *sdmmc) +{ + /* Set all error bits and enable the relevant interrupts. */ + sdmmc->regs->int_enable |= 0x017F0000; + sdmmc->regs->int_enable |= (TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT); + + /* Refresh status. */ + sdmmc->regs->int_status = sdmmc->regs->int_status; +} + +static void sdmmc_intr_disable(sdmmc_t *sdmmc) +{ + /* Clear all error bits and the interrupts. */ + sdmmc->regs->int_enable &= ~(0x017F0000); + sdmmc->regs->int_enable &= ~(TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE | TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE | TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT); + + /* Refresh status. */ + sdmmc->regs->int_status = sdmmc->regs->int_status; +} + +static bool sdmmc_intr_check_status(sdmmc_t *sdmmc, uint16_t status_mask) +{ + bool is_masked = (sdmmc->regs->int_status & status_mask); + + /* Mask status. */ + if (is_masked) + sdmmc->regs->int_status &= status_mask; + + return is_masked; +} + +static bool sdmmc_intr_check_error(sdmmc_t *sdmmc) +{ + bool is_error = (sdmmc->regs->int_status & TEGRA_MMC_NORINTSTS_ERR_INTERRUPT); + + /* Refresh status. */ + if (is_error) + sdmmc->regs->int_status = sdmmc->regs->int_status; + + return is_error; +} + +static int sdmmc_dma_init(sdmmc_t *sdmmc, sdmmc_request_t *req) +{ + /* Invalid block count or size. */ + if (!req->blksz || !req->num_blocks) + return 0; + + uint32_t blkcnt = req->num_blocks; + + /* Truncate block count. Length can't be over 65536 bytes. */ + if (blkcnt >= 0xFFFF) + blkcnt = 0xFFFF; + + /* Use our bounce buffer for SDMA or the request data buffer for ADMA. */ + uint32_t dma_base_addr = sdmmc->use_adma ? (uint32_t)req->data : (uint32_t)sdmmc->dma_bounce_buf; + + /* DMA buffer address must be aligned to 4 bytes. */ + if ((4 - (dma_base_addr & 0x03)) & 0x03) + return 0; + + /* Write our address to the registers. */ + if (sdmmc->use_adma) + { + /* Set ADMA registers. */ + sdmmc->regs->adma_address = dma_base_addr; + sdmmc->regs->upper_adma_address = 0; + } + else + { + /* Set SDMA register. */ + sdmmc->regs->dma_address = dma_base_addr; + } + + /* Store the next DMA block address for updating. */ + sdmmc->next_dma_addr = ((dma_base_addr + 0x80000) & 0xFFF80000); + + /* Set the block size ORed with the DMA boundary mask. */ + sdmmc->regs->block_size = req->blksz | 0x7000; + + /* Set the block count. */ + sdmmc->regs->block_count = blkcnt; + + /* Select basic DMA transfer mode. */ + uint32_t transfer_mode = TEGRA_MMC_TRNMOD_DMA_ENABLE; + + /* Select multi block. */ + if (req->is_multi_block) + transfer_mode |= (TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT | TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE); + + /* Select read mode. */ + if (req->is_read) + transfer_mode |= TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ; + + /* Select AUTO_CMD12. */ + if (req->is_auto_cmd12) + { + transfer_mode &= ~(TEGRA_MMC_TRNMOD_AUTO_CMD12 & TEGRA_MMC_TRNMOD_AUTO_CMD23); + transfer_mode |= TEGRA_MMC_TRNMOD_AUTO_CMD12; + } + + /* Set the transfer mode in the register. */ + sdmmc->regs->transfer_mode = transfer_mode; + + return blkcnt; +} + +static int sdmmc_dma_update(sdmmc_t *sdmmc) +{ + uint16_t blkcnt = 0; + + /* Loop until all blocks have been consumed. */ + do + { + /* Update block count. */ + blkcnt = sdmmc->regs->block_count; + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Watch over the DMA transfer. */ + while (!is_timeout) + { + /* An error has been raised. Reset. */ + if (sdmmc_intr_check_error(sdmmc)) + { + sdmmc_do_sw_reset(sdmmc); + return 0; + } + + /* We have a DMA interrupt. Restart the transfer where it was interrupted. */ + if (sdmmc_intr_check_status(sdmmc, TEGRA_MMC_NORINTSTS_DMA_INTERRUPT)) + { + if (sdmmc->use_adma) + { + /* Update ADMA registers. */ + sdmmc->regs->adma_address = sdmmc->next_dma_addr; + sdmmc->regs->upper_adma_address = 0; + } + else + { + /* Update SDMA register. */ + sdmmc->regs->dma_address = sdmmc->next_dma_addr; + } + + sdmmc->next_dma_addr += 0x80000; + } + + /* Transfer is over. */ + if (sdmmc_intr_check_status(sdmmc, TEGRA_MMC_NORINTSTS_XFER_COMPLETE)) + return 1; + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + } + } while (sdmmc->regs->block_count < blkcnt); + + /* Should never get here. Reset. */ + sdmmc_do_sw_reset(sdmmc); + return 0; +} + +static void sdmmc_set_cmd_flags(sdmmc_t *sdmmc, sdmmc_command_t *cmd, bool is_dma) +{ + uint16_t cmd_reg_flags = 0; + + /* Select length flags based on response type. */ + if (!(cmd->flags & SDMMC_RSP_PRESENT)) + cmd_reg_flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE; + else if (cmd->flags & SDMMC_RSP_136) + cmd_reg_flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136; + else if (cmd->flags & SDMMC_RSP_BUSY) + cmd_reg_flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY; + else + cmd_reg_flags = TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48; + + /* Select CRC flag based on response type. */ + if (cmd->flags & SDMMC_RSP_CRC) + cmd_reg_flags |= TEGRA_MMC_TRNMOD_CMD_CRC_CHECK; + + /* Select opcode flag based on response type. */ + if (cmd->flags & SDMMC_RSP_OPCODE) + cmd_reg_flags |= TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK; + + /* Select data present flag. */ + if (is_dma) + cmd_reg_flags |= TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER; + + /* Set the CMD's argument, opcode and flags. */ + sdmmc->regs->argument = cmd->arg; + sdmmc->regs->command = ((cmd->opcode << 8) | cmd_reg_flags); +} + +static int sdmmc_wait_for_cmd(sdmmc_t *sdmmc) +{ + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a large timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Set this for error checking. */ + bool is_err = false; + + /* Wait for CMD to finish. */ + while (!is_err && !is_timeout) { + /* Command is done. */ + if (sdmmc_intr_check_status(sdmmc, TEGRA_MMC_NORINTSTS_CMD_COMPLETE)) + return 1; + + /* Check for any raised errors. */ + is_err = sdmmc_intr_check_error(sdmmc); + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 2000000); + } + + /* Should never get here. Reset. */ + sdmmc_do_sw_reset(sdmmc); + return 0; +} + +static int sdmmc_save_response(sdmmc_t *sdmmc, uint32_t flags) +{ + /* We have a valid response. */ + if (flags & SDMMC_RSP_PRESENT) + { + if (flags & SDMMC_RSP_136) + { + /* CRC is stripped so we need to do some shifting. */ + for (int i = 0; i < 4; i++) { + sdmmc->resp[i] = (sdmmc->regs->response[3 - i] << 0x08); + + if (i != 0) + sdmmc->resp[i - 1] |= ((sdmmc->regs->response[3 - i] >> 24) & 0xFF); + } + } + else + { + /* Card is still busy. */ + if (flags & SDMMC_RSP_BUSY) + { + /* Wait for DAT0 level mask. */ + if (!sdmmc_wait_busy(sdmmc)) + return 0; + } + + /* Save our response. */ + sdmmc->resp[0] = sdmmc->regs->response[0]; + } + + return 1; + } + + /* Invalid response. */ + return 0; +} + +int sdmmc_load_response(sdmmc_t *sdmmc, uint32_t flags, uint32_t *resp) +{ + /* Make sure our output buffer is valid. */ + if (!resp) + return 0; + + /* We have a valid response. */ + if (flags & SDMMC_RSP_PRESENT) + { + if (flags & SDMMC_RSP_136) + { + resp[0] = sdmmc->resp[0]; + resp[1] = sdmmc->resp[1]; + resp[2] = sdmmc->resp[2]; + resp[3] = sdmmc->resp[3]; + } + else + resp[0] = sdmmc->resp[0]; + + return 1; + } + + /* Invalid response. */ + return 0; +} + +int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t *num_blocks_out) +{ + uint32_t cmd_result = 0; + bool shutdown_sd_clock = false; + + /* Run automatic calibration on each command submission for SDMMC1. */ + if ((sdmmc->controller == SDMMC_1) && !(sdmmc->has_sd)) + sdmmc_autocal_run(sdmmc, sdmmc->bus_voltage); + + /* SD clock is disabled. Enable it. */ + if (!sdmmc->is_sd_clk_enabled) + { + shutdown_sd_clock = true; + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Provide 8 clock cycles after enabling the clock. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + } + + /* Determine if we should wait for data inhibit. */ + bool wait_for_dat = (req || (cmd->flags & SDMMC_RSP_BUSY)); + + /* Wait for CMD and DAT inhibit. */ + if (!sdmmc_wait_for_inhibit(sdmmc, wait_for_dat)) + return 0; + + uint32_t dma_blkcnt = 0; + bool is_dma = false; + + /* This is a data transfer. */ + if (req) + { + is_dma = true; + dma_blkcnt = sdmmc_dma_init(sdmmc, req); + + if (!dma_blkcnt) + { + sdmmc_error(sdmmc, "Failed to initialize the DMA transfer!"); + return 0; + } + + /* If this is a SDMA write operation, copy the data into our bounce buffer. */ + if (!sdmmc->use_adma && !req->is_read) + memcpy((void *)sdmmc->dma_bounce_buf, (void *)req->data, req->blksz * req->num_blocks); + } + + /* Enable interrupts. */ + sdmmc_intr_enable(sdmmc); + + /* Parse and set the CMD's flags. */ + sdmmc_set_cmd_flags(sdmmc, cmd, is_dma); + + /* Wait for the CMD to finish. */ + cmd_result = sdmmc_wait_for_cmd(sdmmc); + + sdmmc_debug(sdmmc, "CMD(%d): %08X, %08X, %08X, %08X", cmd_result, sdmmc->regs->response[0], sdmmc->regs->response[1], sdmmc->regs->response[2], sdmmc->regs->response[3]); + + if (cmd_result) + { + /* Save response, if necessary. */ + sdmmc_save_response(sdmmc, cmd->flags); + + /* Process the DMA request. */ + if (req) + { + if (!sdmmc_dma_update(sdmmc)) + { + sdmmc_error(sdmmc, "Failed to process the DMA transfer!"); + return 0; + } + + /* If this is a SDMA read operation, copy the data from our bounce buffer. */ + if (!sdmmc->use_adma && req->is_read) + { + uint32_t dma_data_size = (sdmmc->regs->dma_address - (uint32_t)sdmmc->dma_bounce_buf); + memcpy((void *)req->data, (void *)sdmmc->dma_bounce_buf, dma_data_size); + } + } + } + + /* Disable interrupts. */ + sdmmc_intr_disable(sdmmc); + + if (cmd_result) + { + if (req) + { + /* Save back the number of DMA blocks. */ + if (num_blocks_out) + *num_blocks_out = dma_blkcnt; + + /* Save the response for AUTO_CMD12. */ + if (req->is_auto_cmd12) + sdmmc->resp_auto_cmd12 = sdmmc->regs->response[3]; + } + + /* Wait for DAT0 to be 0. */ + if (req || (cmd->flags & SDMMC_RSP_BUSY)) + cmd_result = sdmmc_wait_busy(sdmmc); + } + + /* Provide 8 clock cycles before disabling the clock. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + if (shutdown_sd_clock) + sdmmc_disable_sd_clock(sdmmc); + + return cmd_result; +} + +int sdmmc_switch_voltage(sdmmc_t *sdmmc) +{ + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + + /* Reconfigure the internal clock. */ + if (!sdmmc_select_speed(sdmmc, SDMMC_SPEED_SDR12)) + { + sdmmc_error(sdmmc, "Failed to apply the correct bus speed for low voltage support!"); + return 0; + } + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Reconfigure the regulator. */ + max77620_regulator_set_voltage(REGULATOR_LDO2, 1800000); + pmc->pwr_det_val &= ~(PMC_CONTROL_SDMMC1); + + /* Reconfigure autocal offsets. */ + if (!sdmmc_autocal_config(sdmmc, SDMMC_VOLTAGE_1V8)) + { + sdmmc_error(sdmmc, "Failed to configure automatic calibration for low voltage support!"); + return 0; + } + + /* Do autocal again. */ + sdmmc_autocal_run(sdmmc, SDMMC_VOLTAGE_1V8); + + /* Change the desired voltage. */ + sdmmc_select_voltage(sdmmc, SDMMC_VOLTAGE_1V8); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Wait a while. */ + mdelay(5); + + /* Host control 2 flag should be set by now. */ + if (sdmmc->regs->host_control2 & SDHCI_CTRL_VDD_180) + { + /* Enable the SD clock. */ + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Wait a while. */ + mdelay(1); + + /* Data level is up. Voltage switching is done.*/ + if (sdmmc->regs->present_state & SDHCI_DATA_LVL_MASK) + return 1; + } + + return 0; +} + +static int sdmmc_send_tuning(sdmmc_t *sdmmc, uint32_t opcode) +{ + /* Nothing to do. */ + if (!sdmmc->has_sd) + return 0; + + /* Wait for CMD and DAT inhibit. */ + if (!sdmmc_wait_for_inhibit(sdmmc, true)) + return 0; + + /* Select the right size for sending the tuning block. */ + if (sdmmc->bus_width == SDMMC_BUS_WIDTH_4BIT) + sdmmc->regs->block_size = 0x40; + else if (sdmmc->bus_width == SDMMC_BUS_WIDTH_8BIT) + sdmmc->regs->block_size = 0x80; + else + return 0; + + /* Select the block count and transfer mode. */ + sdmmc->regs->block_count = 1; + sdmmc->regs->transfer_mode = TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ; + + /* Manually enable the Buffer Read Ready interrupt. */ + sdmmc->regs->int_enable |= TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY; + + /* Refresh status. */ + sdmmc->regs->int_status = sdmmc->regs->int_status; + + /* Disable the SD clock. */ + sdmmc_disable_sd_clock(sdmmc); + + /* Prepare the tuning command. */ + sdmmc_command_t cmd = {}; + cmd.opcode = opcode; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1; + + /* Parse and set the CMD's flags. */ + sdmmc_set_cmd_flags(sdmmc, &cmd, true); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Wait a while. */ + udelay(1); + + /* Reset. */ + sdmmc_do_sw_reset(sdmmc); + + /* Enable back the SD clock. */ + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Program a 50ms timeout. */ + uint32_t timebase = get_time(); + bool is_timeout = false; + + /* Wait for Buffer Read Ready interrupt. */ + while (!is_timeout) + { + /* Buffer Read Ready was asserted. */ + if (sdmmc_intr_check_status(sdmmc, TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY)) + { + /* Manually disable the Buffer Read Ready interrupt. */ + sdmmc->regs->int_enable &= ~(TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Provide 8 clock cycles. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + return 1; + } + + /* Keep checking if timeout expired. */ + is_timeout = (get_time_since(timebase) > 5000); + } + + /* Reset. */ + sdmmc_do_sw_reset(sdmmc); + + /* Manually disable the Buffer Read Ready interrupt. */ + sdmmc->regs->int_enable &= ~(TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Provide 8 clock cycles. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + return 0; +} + +void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc) +{ + sdmmc->tap_val = (sdmmc->regs->vendor_clock_cntrl >> 16); + sdmmc->is_tuning_tap_val_set = true; +} + +int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcode) +{ + uint32_t max_tuning_loop = 0; + uint32_t tuning_cntrl_flag = 0; + + sdmmc->regs->vendor_tuning_cntrl1 = 0; + + switch (bus_speed) + { + case SDMMC_SPEED_HS200: + case SDMMC_SPEED_HS400: + case SDMMC_SPEED_SDR104: + max_tuning_loop = 0x80; + tuning_cntrl_flag = 0x4000; + break; + case SDMMC_SPEED_SDR50: + case SDMMC_SPEED_DDR50: + case SDMMC_SPEED_UNK14: + max_tuning_loop = 0x100; + tuning_cntrl_flag = 0x8000; + break; + default: + return 0; + } + + sdmmc->regs->vendor_tuning_cntrl0 &= ~(0xE000); + sdmmc->regs->vendor_tuning_cntrl0 |= tuning_cntrl_flag; + + sdmmc->regs->vendor_tuning_cntrl0 &= ~(0x1FC0); + sdmmc->regs->vendor_tuning_cntrl0 |= 0x40; + + sdmmc->regs->vendor_tuning_cntrl0 |= 0x20000; + + /* Start tuning. */ + sdmmc->regs->host_control2 |= SDHCI_CTRL_EXEC_TUNING; + + /* Repeat until Execute Tuning is set to 0 or the number of loops reaches the maximum value. */ + for (uint32_t i = 0; i < max_tuning_loop; i++) + { + sdmmc_send_tuning(sdmmc, opcode); + + /* Tuning is done. */ + if (!(sdmmc->regs->host_control2 & SDHCI_CTRL_EXEC_TUNING)) + break; + } + + /* Success! */ + if (sdmmc->regs->host_control2 & SDHCI_CTRL_TUNED_CLK) + return 1; + + return 0; +} + +int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode) +{ + uint32_t result = 0; + uint32_t cmd_result = 0; + bool shutdown_sd_clock = false; + + /* SD clock is disabled. Enable it. */ + if (!sdmmc->is_sd_clk_enabled) + { + shutdown_sd_clock = true; + sdmmc_enable_sd_clock(sdmmc); + + /* Force a register read to refresh the clock control value. */ + sdmmc_get_sd_clock_control(sdmmc); + + /* Provide 8 clock cycles after enabling the clock. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + } + + /* Wait for CMD and DAT inhibit. */ + if (sdmmc_wait_for_inhibit(sdmmc, false)) + { + /* Enable interrupts. */ + sdmmc_intr_enable(sdmmc); + + /* Prepare the command. */ + sdmmc_command_t cmd = {}; + cmd.opcode = opcode; + cmd.arg = 0; + cmd.flags = SDMMC_RSP_R1B; + + /* Parse and set the CMD's flags. */ + sdmmc_set_cmd_flags(sdmmc, &cmd, false); + + /* Wait for the CMD to finish. */ + cmd_result = sdmmc_wait_for_cmd(sdmmc); + + /* Disable interrupts. */ + sdmmc_intr_disable(sdmmc); + + if (cmd_result) + { + /* Save response, if necessary. */ + sdmmc_save_response(sdmmc, cmd.flags); + + /* Wait for DAT0 to be 0. */ + result = sdmmc_wait_busy(sdmmc); + } + } + + /* Provide 8 clock cycles before disabling the clock. */ + udelay((8000 + sdmmc->internal_divider - 1) / sdmmc->internal_divider); + + /* Disable the SD clock if requested. */ + if (shutdown_sd_clock) + sdmmc_disable_sd_clock(sdmmc); + + return result; +} diff --git a/sept/sept-secondary/src/sdmmc/sdmmc_core.h b/sept/sept-secondary/src/sdmmc/sdmmc_core.h new file mode 100644 index 000000000..ccfab130b --- /dev/null +++ b/sept/sept-secondary/src/sdmmc/sdmmc_core.h @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SDMMC_CORE_H +#define FUSEE_SDMMC_CORE_H + +#include "sdmmc_tegra.h" + +/* Bounce buffer */ +#define SDMMC_BOUNCE_BUFFER_ADDRESS 0x90000000 + +/* Present state */ +#define SDHCI_CMD_INHIBIT 0x00000001 +#define SDHCI_DATA_INHIBIT 0x00000002 +#define SDHCI_DOING_WRITE 0x00000100 +#define SDHCI_DOING_READ 0x00000200 +#define SDHCI_SPACE_AVAILABLE 0x00000400 +#define SDHCI_DATA_AVAILABLE 0x00000800 +#define SDHCI_CARD_PRESENT 0x00010000 +#define SDHCI_WRITE_PROTECT 0x00080000 +#define SDHCI_DATA_LVL_MASK 0x00F00000 +#define SDHCI_DATA_LVL_SHIFT 20 +#define SDHCI_DATA_0_LVL_MASK 0x00100000 +#define SDHCI_CMD_LVL 0x01000000 + +/* SDHCI clock control */ +#define SDHCI_DIVIDER_SHIFT 8 +#define SDHCI_DIVIDER_HI_SHIFT 6 +#define SDHCI_DIV_MASK 0xFF +#define SDHCI_DIV_MASK_LEN 8 +#define SDHCI_DIV_HI_MASK 0x300 +#define SDHCI_PROG_CLOCK_MODE 0x0020 +#define SDHCI_CLOCK_CARD_EN 0x0004 +#define SDHCI_CLOCK_INT_STABLE 0x0002 +#define SDHCI_CLOCK_INT_EN 0x0001 + +/* SDHCI host control */ +#define SDHCI_CTRL_LED 0x01 +#define SDHCI_CTRL_4BITBUS 0x02 +#define SDHCI_CTRL_HISPD 0x04 +#define SDHCI_CTRL_DMA_MASK 0x18 +#define SDHCI_CTRL_SDMA 0x00 +#define SDHCI_CTRL_ADMA1 0x08 +#define SDHCI_CTRL_ADMA32 0x10 +#define SDHCI_CTRL_ADMA64 0x18 +#define SDHCI_CTRL_8BITBUS 0x20 +#define SDHCI_CTRL_CDTEST_INS 0x40 +#define SDHCI_CTRL_CDTEST_EN 0x80 + +/* SDHCI host control 2 */ +#define SDHCI_CTRL_UHS_MASK 0x0007 +#define SDHCI_CTRL_UHS_SDR12 0x0000 +#define SDHCI_CTRL_UHS_SDR25 0x0001 +#define SDHCI_CTRL_UHS_SDR50 0x0002 +#define SDHCI_CTRL_UHS_SDR104 0x0003 +#define SDHCI_CTRL_UHS_DDR50 0x0004 +#define SDHCI_CTRL_HS400 0x0005 +#define SDHCI_CTRL_VDD_180 0x0008 +#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 +#define SDHCI_CTRL_DRV_TYPE_B 0x0000 +#define SDHCI_CTRL_DRV_TYPE_A 0x0010 +#define SDHCI_CTRL_DRV_TYPE_C 0x0020 +#define SDHCI_CTRL_DRV_TYPE_D 0x0030 +#define SDHCI_CTRL_EXEC_TUNING 0x0040 +#define SDHCI_CTRL_TUNED_CLK 0x0080 +#define SDHCI_UHS2_IF_EN 0x0100 +#define SDHCI_HOST_VERSION_4_EN 0x1000 +#define SDHCI_ADDRESSING_64BIT_EN 0x2000 +#define SDHCI_ASYNC_INTR_EN 0x4000 +#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 + +/* SDHCI capabilities */ +#define SDHCI_CAN_DO_8BIT 0x00040000 +#define SDHCI_CAN_DO_ADMA2 0x00080000 +#define SDHCI_CAN_DO_ADMA1 0x00100000 +#define SDHCI_CAN_DO_HISPD 0x00200000 +#define SDHCI_CAN_DO_SDMA 0x00400000 +#define SDHCI_CAN_VDD_330 0x01000000 +#define SDHCI_CAN_VDD_300 0x02000000 +#define SDHCI_CAN_VDD_180 0x04000000 +#define SDHCI_CAN_64BIT 0x10000000 +#define SDHCI_ASYNC_INTR 0x20000000 + +/* Vendor clock control */ +#define SDMMC_CLOCK_TAP_MASK (0xFF << 16) +#define SDMMC_CLOCK_TAP_SDMMC1 (0x04 << 16) +#define SDMMC_CLOCK_TAP_SDMMC2 (0x00 << 16) +#define SDMMC_CLOCK_TAP_SDMMC3 (0x03 << 16) +#define SDMMC_CLOCK_TAP_SDMMC4 (0x00 << 16) +#define SDMMC_CLOCK_TRIM_MASK (0xFF << 24) +#define SDMMC_CLOCK_TRIM_SDMMC1 (0x02 << 24) +#define SDMMC_CLOCK_TRIM_SDMMC2 (0x08 << 24) +#define SDMMC_CLOCK_TRIM_SDMMC3 (0x03 << 24) +#define SDMMC_CLOCK_TRIM_SDMMC4 (0x08 << 24) +#define SDMMC_CLOCK_PADPIPE_CLKEN_OVERRIDE (1 << 3) + +/* Autocal configuration */ +#define SDMMC_AUTOCAL_PDPU_CONFIG_MASK 0x7F7F +#define SDMMC_AUTOCAL_PDPU_SDMMC1_1V8 0x7B7B +#define SDMMC_AUTOCAL_PDPU_SDMMC1_3V3 0x7D00 +#define SDMMC_AUTOCAL_PDPU_SDMMC4_1V8 0x0505 +#define SDMMC_AUTOCAL_START (1 << 31) +#define SDMMC_AUTOCAL_ENABLE (1 << 29) + +/* Autocal status */ +#define SDMMC_AUTOCAL_ACTIVE (1 << 31) + +/* Vendor tuning control 0*/ +#define SDMMC_VENDOR_TUNING_TRIES_MASK (0x7 << 13) +#define SDMMC_VENDOR_TUNING_TRIES_SHIFT 13 +#define SDMMC_VENDOR_TUNING_MULTIPLIER_MASK (0x7F << 6) +#define SDMMC_VENDOR_TUNING_MULTIPLIER_UNITY (1 << 6) +#define SDMMC_VENDOR_TUNING_DIVIDER_MASK (0x7 << 3) +#define SDMMC_VENDOR_TUNING_SET_BY_HW (1 << 17) + +/* Vendor tuning control 1*/ +#define SDMMC_VENDOR_TUNING_STEP_SIZE_SDR50_DEFAULT (0 << 0) +#define SDMMC_VENDOR_TUNING_STEP_SIZE_SDR104_DEFAULT (0 << 4) + +/* Vendor capability overrides */ +#define SDMMC_VENDOR_CAPABILITY_DQS_TRIM_MASK (0x3F << 8) +#define SDMMC_VENDOR_CAPABILITY_DQS_TRIM_HS400 (0x11 << 8) + +/* Timeouts */ +#define SDMMC_AUTOCAL_TIMEOUT (10 * 1000) +#define SDMMC_TUNING_TIMEOUT (150 * 1000) + +/* Command response flags */ +#define SDMMC_RSP_PRESENT (1 << 0) +#define SDMMC_RSP_136 (1 << 1) +#define SDMMC_RSP_CRC (1 << 2) +#define SDMMC_RSP_BUSY (1 << 3) +#define SDMMC_RSP_OPCODE (1 << 4) + +/* Command types */ +#define SDMMC_CMD_MASK (3 << 5) +#define SDMMC_CMD_AC (0 << 5) +#define SDMMC_CMD_ADTC (1 << 5) +#define SDMMC_CMD_BC (2 << 5) +#define SDMMC_CMD_BCR (3 << 5) + +/* SPI command response flags */ +#define SDMMC_RSP_SPI_S1 (1 << 7) +#define SDMMC_RSP_SPI_S2 (1 << 8) +#define SDMMC_RSP_SPI_B4 (1 << 9) +#define SDMMC_RSP_SPI_BUSY (1 << 10) + +/* Native response types for commands */ +#define SDMMC_RSP_NONE (0) +#define SDMMC_RSP_R1 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE) +#define SDMMC_RSP_R1B (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE|SDMMC_RSP_BUSY) +#define SDMMC_RSP_R2 (SDMMC_RSP_PRESENT|SDMMC_RSP_136|SDMMC_RSP_CRC) +#define SDMMC_RSP_R3 (SDMMC_RSP_PRESENT) +#define SDMMC_RSP_R4 (SDMMC_RSP_PRESENT) +#define SDMMC_RSP_R5 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE) +#define SDMMC_RSP_R6 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE) +#define SDMMC_RSP_R7 (SDMMC_RSP_PRESENT|SDMMC_RSP_CRC|SDMMC_RSP_OPCODE) +#define SDMMC_RSP_R1_NO_CRC (SDMMC_RSP_PRESENT|SDMMC_RSP_OPCODE) + +/* SPI response types for commands */ +#define SDMMC_RSP_SPI_R1 (SDMMC_RSP_SPI_S1) +#define SDMMC_RSP_SPI_R1B (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_BUSY) +#define SDMMC_RSP_SPI_R2 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2) +#define SDMMC_RSP_SPI_R3 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4) +#define SDMMC_RSP_SPI_R4 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4) +#define SDMMC_RSP_SPI_R5 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_S2) +#define SDMMC_RSP_SPI_R7 (SDMMC_RSP_SPI_S1|SDMMC_RSP_SPI_B4) + +/* SDMMC controllers */ +typedef enum { + SDMMC_1 = 0, + SDMMC_2 = 1, + SDMMC_3 = 2, + SDMMC_4 = 3 +} SdmmcControllerNum; + +typedef enum { + SDMMC_PARTITION_INVALID = -1, + SDMMC_PARTITION_USER = 0, + SDMMC_PARTITION_BOOT0 = 1, + SDMMC_PARTITION_BOOT1 = 2, + SDMMC_PARTITION_RPMB = 3 +} SdmmcPartitionNum; + +typedef enum { + SDMMC_VOLTAGE_NONE = 0, + SDMMC_VOLTAGE_1V8 = 1, + SDMMC_VOLTAGE_3V3 = 2 +} SdmmcBusVoltage; + +typedef enum { + SDMMC_BUS_WIDTH_1BIT = 0, + SDMMC_BUS_WIDTH_4BIT = 1, + SDMMC_BUS_WIDTH_8BIT = 2 +} SdmmcBusWidth; + +typedef enum { + SDMMC_SPEED_INIT_HS = 0, + SDMMC_SPEED_HS26 = 1, + SDMMC_SPEED_HS52 = 2, + SDMMC_SPEED_HS200 = 3, + SDMMC_SPEED_HS400 = 4, + SDMMC_SPEED_INIT_SDR = 5, + SDMMC_SPEED_UNK6 = 6, + SDMMC_SPEED_SDR25 = 7, + SDMMC_SPEED_SDR12 = 8, + SDMMC_SPEED_UNK9 = 9, + SDMMC_SPEED_SDR50 = 10, + SDMMC_SPEED_SDR104 = 11, + SDMMC_SPEED_UNK12 = 12, + SDMMC_SPEED_DDR50 = 13, + SDMMC_SPEED_UNK14 = 14, +} SdmmcBusSpeed; + +typedef enum { + SDMMC_CAR_DIVIDER_SDR12 = 31, // (16.5 * 2) - 2 + SDMMC_CAR_DIVIDER_SDR25 = 15, // (8.5 * 2) - 2 + SDMMC_CAR_DIVIDER_SDR50 = 7, // (4.5 * 2) - 2 + SDMMC_CAR_DIVIDER_SDR104 = 2, // (2 * 2) - 2 + SDMMC_CAR_DIVIDER_DDR50 = 18, // (5 * 2 * 2) - 2 + SDMMC_CAR_DIVIDER_HS26 = 30, // (16 * 2) - 2 + SDMMC_CAR_DIVIDER_HS52 = 14, // (8 * 2) - 2 + SDMMC_CAR_DIVIDER_HS200 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0) + SDMMC_CAR_DIVIDER_HS400 = 3, // (2.5 * 2) - 2 (for PLLP_OUT0) +} SdmmcCarDivider; + +/* Structure for describing a SDMMC device. */ +typedef struct { + /* Controller number */ + SdmmcControllerNum controller; + + /* Backing register space */ + volatile tegra_sdmmc_t *regs; + + /* Controller properties */ + const char *name; + bool has_sd; + bool is_clk_running; + bool is_sd_clk_enabled; + bool is_tuning_tap_val_set; + bool use_adma; + uint32_t tap_val; + uint32_t internal_divider; + uint32_t resp[4]; + uint32_t resp_auto_cmd12; + uint32_t next_dma_addr; + uint8_t* dma_bounce_buf; + SdmmcBusVoltage bus_voltage; + SdmmcBusWidth bus_width; + + /* Per-controller operations. */ + int (*sdmmc_config)(); +} sdmmc_t; + +/* Structure for describing a SDMMC command. */ +typedef struct { + uint32_t opcode; + uint32_t arg; + uint32_t resp[4]; + uint32_t flags; /* expected response type */ +} sdmmc_command_t; + +/* Structure for describing a SDMMC request. */ +typedef struct { + void* data; + uint32_t blksz; + uint32_t num_blocks; + bool is_multi_block; + bool is_read; + bool is_auto_cmd12; +} sdmmc_request_t; + +int sdmmc_init(sdmmc_t *sdmmc, SdmmcControllerNum controller, SdmmcBusVoltage bus_voltage, SdmmcBusWidth bus_width, SdmmcBusSpeed bus_speed); +void sdmmc_finish(sdmmc_t *sdmmc); +int sdmmc_select_speed(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed); +void sdmmc_select_bus_width(sdmmc_t *sdmmc, SdmmcBusWidth width); +void sdmmc_select_voltage(sdmmc_t *sdmmc, SdmmcBusVoltage voltage); +void sdmmc_adjust_sd_clock(sdmmc_t *sdmmc); +int sdmmc_switch_voltage(sdmmc_t *sdmmc); +void sdmmc_set_tuning_tap_val(sdmmc_t *sdmmc); +int sdmmc_execute_tuning(sdmmc_t *sdmmc, SdmmcBusSpeed bus_speed, uint32_t opcode); +int sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_command_t *cmd, sdmmc_request_t *req, uint32_t *num_blocks_out); +int sdmmc_load_response(sdmmc_t *sdmmc, uint32_t flags, uint32_t *resp); +int sdmmc_abort(sdmmc_t *sdmmc, uint32_t opcode); +void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...); +void sdmmc_warn(sdmmc_t *sdmmc, char *fmt, ...); +void sdmmc_info(sdmmc_t *sdmmc, char *fmt, ...); +void sdmmc_debug(sdmmc_t *sdmmc, char *fmt, ...); +void sdmmc_dump_regs(sdmmc_t *sdmmc); + +#endif diff --git a/sept/sept-secondary/src/sdmmc/sdmmc_tegra.h b/sept/sept-secondary/src/sdmmc/sdmmc_tegra.h new file mode 100644 index 000000000..3b6b4adb0 --- /dev/null +++ b/sept/sept-secondary/src/sdmmc/sdmmc_tegra.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SDMMC_TEGRA_H +#define FUSEE_SDMMC_TEGRA_H + +#include <stdbool.h> +#include <stdint.h> + +#define TEGRA_MMC_PWRCTL_SD_BUS_POWER (1 << 0) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 (5 << 1) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 (6 << 1) +#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 (7 << 1) + +#define TEGRA_MMC_HOSTCTL_DMASEL_MASK (3 << 3) +#define TEGRA_MMC_HOSTCTL_DMASEL_SDMA (0 << 3) +#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_32BIT (2 << 3) +#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_64BIT (3 << 3) + +#define TEGRA_MMC_TRNMOD_DMA_ENABLE (1 << 0) +#define TEGRA_MMC_TRNMOD_BLOCK_COUNT_ENABLE (1 << 1) +#define TEGRA_MMC_TRNMOD_AUTO_CMD12 (1 << 2) +#define TEGRA_MMC_TRNMOD_AUTO_CMD23 (1 << 3) +#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_WRITE (0 << 4) +#define TEGRA_MMC_TRNMOD_DATA_XFER_DIR_SEL_READ (1 << 4) +#define TEGRA_MMC_TRNMOD_MULTI_BLOCK_SELECT (1 << 5) + +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_MASK (3 << 0) +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_NO_RESPONSE (0 << 0) +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_136 (1 << 0) +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48 (2 << 0) +#define TEGRA_MMC_CMDREG_RESP_TYPE_SELECT_LENGTH_48_BUSY (3 << 0) + +#define TEGRA_MMC_TRNMOD_CMD_CRC_CHECK (1 << 3) +#define TEGRA_MMC_TRNMOD_CMD_INDEX_CHECK (1 << 4) +#define TEGRA_MMC_TRNMOD_DATA_PRESENT_SELECT_DATA_TRANSFER (1 << 5) + +#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_CMD (1 << 0) +#define TEGRA_MMC_PRNSTS_CMD_INHIBIT_DAT (1 << 1) + +#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_ENABLE (1 << 0) +#define TEGRA_MMC_CLKCON_INTERNAL_CLOCK_STABLE (1 << 1) +#define TEGRA_MMC_CLKCON_SD_CLOCK_ENABLE (1 << 2) +#define TEGRA_MMC_CLKCON_PROG_CLOCK_MODE (1 << 5) + +#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_SHIFT 8 +#define TEGRA_MMC_CLKCON_SDCLK_FREQ_SEL_MASK (0xff << 8) + +#define TEGRA_MMC_SWRST_SW_RESET_FOR_ALL (1 << 0) +#define TEGRA_MMC_SWRST_SW_RESET_FOR_CMD_LINE (1 << 1) +#define TEGRA_MMC_SWRST_SW_RESET_FOR_DAT_LINE (1 << 2) + +#define TEGRA_MMC_NORINTSTS_CMD_COMPLETE (1 << 0) +#define TEGRA_MMC_NORINTSTS_XFER_COMPLETE (1 << 1) +#define TEGRA_MMC_NORINTSTS_DMA_INTERRUPT (1 << 3) +#define TEGRA_MMC_NORINTSTS_ERR_INTERRUPT (1 << 15) +#define TEGRA_MMC_NORINTSTS_CMD_TIMEOUT (1 << 16) + +#define TEGRA_MMC_NORINTSTSEN_CMD_COMPLETE (1 << 0) +#define TEGRA_MMC_NORINTSTSEN_XFER_COMPLETE (1 << 1) +#define TEGRA_MMC_NORINTSTSEN_DMA_INTERRUPT (1 << 3) +#define TEGRA_MMC_NORINTSTSEN_BUFFER_WRITE_READY (1 << 4) +#define TEGRA_MMC_NORINTSTSEN_BUFFER_READ_READY (1 << 5) + +#define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE (1 << 1) + +typedef struct { + /* SDHCI standard registers */ + uint32_t dma_address; + uint16_t block_size; + uint16_t block_count; + uint32_t argument; + uint16_t transfer_mode; + uint16_t command; + uint32_t response[0x4]; + uint32_t buffer; + uint32_t present_state; + uint8_t host_control; + uint8_t power_control; + uint8_t block_gap_control; + uint8_t wake_up_control; + uint16_t clock_control; + uint8_t timeout_control; + uint8_t software_reset; + uint32_t int_status; + uint32_t int_enable; + uint32_t signal_enable; + uint16_t acmd12_err; + uint16_t host_control2; + uint32_t capabilities; + uint32_t capabilities_1; + uint32_t max_current; + uint32_t _0x4c; + uint16_t set_acmd12_error; + uint16_t set_int_error; + uint8_t adma_error; + uint8_t _0x56[0x3]; + uint32_t adma_address; + uint32_t upper_adma_address; + uint16_t preset_for_init; + uint16_t preset_for_default; + uint16_t preset_for_high; + uint16_t preset_for_sdr12; + uint16_t preset_for_sdr25; + uint16_t preset_for_sdr50; + uint16_t preset_for_sdr104; + uint16_t preset_for_ddr50; + uint32_t _0x70[0x23]; + uint16_t slot_int_status; + uint16_t host_version; + + /* Vendor specific registers */ + uint32_t vendor_clock_cntrl; + uint32_t vendor_sys_sw_cntrl; + uint32_t vendor_err_intr_status; + uint32_t vendor_cap_overrides; + uint32_t vendor_boot_cntrl; + uint32_t vendor_boot_ack_timeout; + uint32_t vendor_boot_dat_timeout; + uint32_t vendor_debounce_count; + uint32_t vendor_misc_cntrl; + uint32_t max_current_override; + uint32_t max_current_override_hi; + uint32_t _0x12c[0x20]; + uint32_t vendor_io_trim_cntrl; + + /* Start of sdmmc2/sdmmc4 only */ + uint32_t vendor_dllcal_cfg; + uint32_t vendor_dll_ctrl0; + uint32_t vendor_dll_ctrl1; + uint32_t vendor_dllcal_cfg_sta; + /* End of sdmmc2/sdmmc4 only */ + + uint32_t vendor_tuning_cntrl0; + uint32_t vendor_tuning_cntrl1; + uint32_t vendor_tuning_status0; + uint32_t vendor_tuning_status1; + uint32_t vendor_clk_gate_hysteresis_count; + uint32_t vendor_preset_val0; + uint32_t vendor_preset_val1; + uint32_t vendor_preset_val2; + uint32_t sdmemcomppadctrl; + uint32_t auto_cal_config; + uint32_t auto_cal_interval; + uint32_t auto_cal_status; + uint32_t io_spare; + uint32_t sdmmca_mccif_fifoctrl; + uint32_t timeout_wcoal_sdmmca; + uint32_t _0x1fc; +} tegra_sdmmc_t; + +static inline volatile tegra_sdmmc_t *sdmmc_get_regs(uint32_t idx) +{ + return (volatile tegra_sdmmc_t *)(0x700B0000 + (idx * 0x200)); +} + +#endif \ No newline at end of file diff --git a/sept/sept-secondary/src/sdram.c b/sept/sept-secondary/src/sdram.c new file mode 100644 index 000000000..c8e5b9502 --- /dev/null +++ b/sept/sept-secondary/src/sdram.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "i2c.h" +#include "mc.h" +#include "emc.h" +#include "pmc.h" +#include "timers.h" +#include "sysreg.h" +#include "fuse.h" +#include "max77620.h" +#include "sdram_param_t210.h" +#include "car.h" + +#define CONFIG_SDRAM_COMPRESS_CFG + +#ifdef CONFIG_SDRAM_COMPRESS_CFG +#include "lib/lz.h" +#include "sdram_lz.inl" +#else +#include "sdram.inl" +#endif + +static uint32_t _get_sdram_id() +{ + return ((fuse_get_reserved_odm(4) & 0x38) >> 3); +} + +static void _sdram_config(const sdram_params_t *params) +{ + volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + pmc->io_dpd3_req = (((4 * params->emc_pmc_scratch1 >> 2) + 0x80000000) ^ 0xFFFF) & 0xC000FFFF; + udelay(params->pmc_io_dpd3_req_wait); + + uint32_t req = (4 * params->emc_pmc_scratch2 >> 2) + 0x80000000; + pmc->io_dpd4_req = (req >> 16 << 16) ^ 0x3FFF0000; + + udelay(params->pmc_io_dpd4_req_wait); + pmc->io_dpd4_req = (req ^ 0xFFFF) & 0xC000FFFF; + udelay(params->pmc_io_dpd4_req_wait); + + pmc->weak_bias = 0; + udelay(1); + + car->pllm_misc1 = params->pllm_setup_control; + car->pllm_misc2 = 0; + car->pllm_base = ((params->pllm_feedback_divider << 8) | params->pllm_input_divider | 0x40000000 | ((params->pllm_post_divider & 0xFFFF) << 20)); + + bool timeout = false; + uint32_t wait_end = get_time_us() + 300; + + while (!(car->pllm_base & 0x8000000) && !timeout) + { + if (get_time_us() >= wait_end) + timeout = true; + } + + if (!timeout) { + udelay(10); + } + + car->clk_source_emc = (((params->mc_emem_arb_misc0 >> 11) & 0x10000) | (params->emc_clock_source & 0xFFFEFFFF)); + + if (params->emc_clock_source_dll) + car->clk_source_emc_dll = params->emc_clock_source_dll; + + if (params->clear_clock2_mc1) + car->clk_enb_w_clr = 0x40000000; + + car->clk_enb_h_set = 0x2000001; + car->clk_enb_x_set = 0x4000; + car->rst_dev_h_clr = 0x2000001; + + MAKE_EMC_REG(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0; + MAKE_EMC_REG(EMC_PMACRO_VTTGEN_CTRL_1) = params->emc_pmacro_vttgen_ctrl1; + MAKE_EMC_REG(EMC_PMACRO_VTTGEN_CTRL_2) = params->emc_pmacro_vttgen_ctrl2; + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + udelay(1); + + MAKE_EMC_REG(EMC_DBG) = (params->emc_dbg_write_mux << 1) | params->emc_dbg; + + if (params->emc_bct_spare2) + *(volatile uint32_t *)params->emc_bct_spare2 = params->emc_bct_spare3; + + MAKE_EMC_REG(EMC_FBIO_CFG7) = params->emc_fbio_cfg7; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD0_0) = params->emc_cmd_mapping_cmd0_0; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD0_1) = params->emc_cmd_mapping_cmd0_1; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD0_2) = params->emc_cmd_mapping_cmd0_2; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD1_0) = params->emc_cmd_mapping_cmd1_0; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD1_1) = params->emc_cmd_mapping_cmd1_1; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD1_2) = params->emc_cmd_mapping_cmd1_2; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD2_0) = params->emc_cmd_mapping_cmd2_0; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD2_1) = params->emc_cmd_mapping_cmd2_1; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD2_2) = params->emc_cmd_mapping_cmd2_2; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD3_0) = params->emc_cmd_mapping_cmd3_0; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD3_1) = params->emc_cmd_mapping_cmd3_1; + MAKE_EMC_REG(EMC_CMD_MAPPING_CMD3_2) = params->emc_cmd_mapping_cmd3_2; + MAKE_EMC_REG(EMC_CMD_MAPPING_BYTE) = params->emc_cmd_mapping_byte; + MAKE_EMC_REG(EMC_PMACRO_BRICK_MAPPING_0) = params->emc_pmacro_brick_mapping0; + MAKE_EMC_REG(EMC_PMACRO_BRICK_MAPPING_1) = params->emc_pmacro_brick_mapping1; + MAKE_EMC_REG(EMC_PMACRO_BRICK_MAPPING_2) = params->emc_pmacro_brick_mapping2; + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU1) = ((params->emc_pmacro_brick_ctrl_rfu1 & 0x1120112) | 0x1EED1EED); + MAKE_EMC_REG(EMC_CONFIG_SAMPLE_DELAY) = params->emc_config_sample_delay; + MAKE_EMC_REG(EMC_FBIO_CFG8) = params->emc_fbio_cfg8; + MAKE_EMC_REG(EMC_SWIZZLE_RANK0_BYTE0) = params->emc_swizzle_rank0_byte0; + MAKE_EMC_REG(EMC_SWIZZLE_RANK0_BYTE1) = params->emc_swizzle_rank0_byte1; + MAKE_EMC_REG(EMC_SWIZZLE_RANK0_BYTE2) = params->emc_swizzle_rank0_byte2; + MAKE_EMC_REG(EMC_SWIZZLE_RANK0_BYTE3) = params->emc_swizzle_rank0_byte3; + MAKE_EMC_REG(EMC_SWIZZLE_RANK1_BYTE0) = params->emc_swizzle_rank1_byte0; + MAKE_EMC_REG(EMC_SWIZZLE_RANK1_BYTE1) = params->emc_swizzle_rank1_byte1; + MAKE_EMC_REG(EMC_SWIZZLE_RANK1_BYTE2) = params->emc_swizzle_rank1_byte2; + MAKE_EMC_REG(EMC_SWIZZLE_RANK1_BYTE3) = params->emc_swizzle_rank1_byte3; + + if (params->emc_bct_spare6) + *(volatile uint32_t *)params->emc_bct_spare6 = params->emc_bct_spare7; + + MAKE_EMC_REG(EMC_XM2COMPPADCTRL) = params->emc_xm2_comp_pad_ctrl; + MAKE_EMC_REG(EMC_XM2COMPPADCTRL2) = params->emc_xm2_comp_pad_ctrl2; + MAKE_EMC_REG(EMC_XM2COMPPADCTRL3) = params->emc_xm2_comp_pad_ctrl3; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG2) = params->emc_auto_cal_config2; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG3) = params->emc_auto_cal_config3; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG4) = params->emc_auto_cal_config4; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG5) = params->emc_auto_cal_config5; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG6) = params->emc_auto_cal_config6; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG7) = params->emc_auto_cal_config7; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG8) = params->emc_auto_cal_config8; + MAKE_EMC_REG(EMC_PMACRO_RX_TERM) = params->emc_pmacro_rx_term; + MAKE_EMC_REG(EMC_PMACRO_DQ_TX_DRV) = params->emc_pmacro_dq_tx_drive; + MAKE_EMC_REG(EMC_PMACRO_CA_TX_DRV) = params->emc_pmacro_ca_tx_drive; + MAKE_EMC_REG(EMC_PMACRO_CMD_TX_DRV) = params->emc_pmacro_cmd_tx_drive; + MAKE_EMC_REG(EMC_PMACRO_AUTOCAL_CFG_COMMON) = params->emc_pmacro_auto_cal_common; + MAKE_EMC_REG(EMC_AUTO_CAL_CHANNEL) = params->emc_auto_cal_channel; + MAKE_EMC_REG(EMC_PMACRO_ZCTRL) = params->emc_pmacro_zcrtl; + MAKE_EMC_REG(EMC_DLL_CFG_0) = params->emc_dll_cfg0; + MAKE_EMC_REG(EMC_DLL_CFG_1) = params->emc_dll_cfg1; + MAKE_EMC_REG(EMC_CFG_DIG_DLL_1) = params->emc_cfg_dig_dll_1; + MAKE_EMC_REG(EMC_DATA_BRLSHFT_0) = params->emc_data_brlshft0; + MAKE_EMC_REG(EMC_DATA_BRLSHFT_1) = params->emc_data_brlshft1; + MAKE_EMC_REG(EMC_DQS_BRLSHFT_0) = params->emc_dqs_brlshft0; + MAKE_EMC_REG(EMC_DQS_BRLSHFT_1) = params->emc_dqs_brlshft1; + MAKE_EMC_REG(EMC_CMD_BRLSHFT_0) = params->emc_cmd_brlshft0; + MAKE_EMC_REG(EMC_CMD_BRLSHFT_1) = params->emc_cmd_brlshft1; + MAKE_EMC_REG(EMC_CMD_BRLSHFT_2) = params->emc_cmd_brlshft2; + MAKE_EMC_REG(EMC_CMD_BRLSHFT_3) = params->emc_cmd_brlshft3; + MAKE_EMC_REG(EMC_QUSE_BRLSHFT_0) = params->emc_quse_brlshft0; + MAKE_EMC_REG(EMC_QUSE_BRLSHFT_1) = params->emc_quse_brlshft1; + MAKE_EMC_REG(EMC_QUSE_BRLSHFT_2) = params->emc_quse_brlshft2; + MAKE_EMC_REG(EMC_QUSE_BRLSHFT_3) = params->emc_quse_brlshft3; + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU1) = ((params->emc_pmacro_brick_ctrl_rfu1 & 0x1BF01BF) | 0x1E401E40); + MAKE_EMC_REG(EMC_PMACRO_PAD_CFG_CTRL) = params->emc_pmacro_pad_cfg_ctrl; + MAKE_EMC_REG(EMC_PMACRO_CMD_BRICK_CTRL_FDPD) = params->emc_pmacro_cmd_brick_ctrl_fdpd; + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU2) = (params->emc_pmacro_brick_ctrl_rfu2 & 0xFF7FFF7F); + MAKE_EMC_REG(EMC_PMACRO_DATA_BRICK_CTRL_FDPD) = params->emc_pmacro_data_brick_ctrl_fdpd; + MAKE_EMC_REG(EMC_PMACRO_BG_BIAS_CTRL_0) = params->emc_pmacro_bg_bias_ctrl0; + MAKE_EMC_REG(EMC_PMACRO_DATA_PAD_RX_CTRL) = params->emc_pmacro_data_pad_rx_ctrl; + MAKE_EMC_REG(EMC_PMACRO_CMD_PAD_RX_CTRL) = params->emc_pmacro_cmd_pad_rx_ctrl; + MAKE_EMC_REG(EMC_PMACRO_DATA_PAD_TX_CTRL) = params->emc_pmacro_data_pad_tx_ctrl; + MAKE_EMC_REG(EMC_PMACRO_DATA_RX_TERM_MODE) = params->emc_pmacro_data_rx_term_mode; + MAKE_EMC_REG(EMC_PMACRO_CMD_RX_TERM_MODE) = params->emc_pmacro_cmd_rx_term_mode; + MAKE_EMC_REG(EMC_PMACRO_CMD_PAD_TX_CTRL) = params->emc_pmacro_cmd_pad_tx_ctrl; + MAKE_EMC_REG(EMC_CFG_3) = params->emc_cfg3; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_0) = params->emc_pmacro_tx_pwrd0; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_1) = params->emc_pmacro_tx_pwrd1; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_2) = params->emc_pmacro_tx_pwrd2; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_3) = params->emc_pmacro_tx_pwrd3; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_4) = params->emc_pmacro_tx_pwrd4; + MAKE_EMC_REG(EMC_PMACRO_TX_PWRD_5) = params->emc_pmacro_tx_pwrd5; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_0) = params->emc_pmacro_tx_sel_clk_src0; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_1) = params->emc_pmacro_tx_sel_clk_src1; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_2) = params->emc_pmacro_tx_sel_clk_src2; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_3) = params->emc_pmacro_tx_sel_clk_src3; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_4) = params->emc_pmacro_tx_sel_clk_src4; + MAKE_EMC_REG(EMC_PMACRO_TX_SEL_CLK_SRC_5) = params->emc_pmacro_tx_sel_clk_src5; + MAKE_EMC_REG(EMC_PMACRO_DDLL_BYPASS) = params->emc_pmacro_ddll_bypass; + MAKE_EMC_REG(EMC_PMACRO_DDLL_PWRD_0) = params->emc_pmacro_ddll_pwrd0; + MAKE_EMC_REG(EMC_PMACRO_DDLL_PWRD_1) = params->emc_pmacro_ddll_pwrd1; + MAKE_EMC_REG(EMC_PMACRO_DDLL_PWRD_2) = params->emc_pmacro_ddll_pwrd2; + MAKE_EMC_REG(EMC_PMACRO_CMD_CTRL_0) = params->emc_pmacro_cmd_ctrl0; + MAKE_EMC_REG(EMC_PMACRO_CMD_CTRL_1) = params->emc_pmacro_cmd_ctrl1; + MAKE_EMC_REG(EMC_PMACRO_CMD_CTRL_2) = params->emc_pmacro_cmd_ctrl2; + MAKE_EMC_REG(EMC_PMACRO_IB_VREF_DQ_0) = params->emc_pmacro_ib_vref_dq_0; + MAKE_EMC_REG(EMC_PMACRO_IB_VREF_DQ_1) = params->emc_pmacro_ib_vref_dq_1; + MAKE_EMC_REG(EMC_PMACRO_IB_VREF_DQS_0) = params->emc_pmacro_ib_vref_dqs_0; + MAKE_EMC_REG(EMC_PMACRO_IB_VREF_DQS_1) = params->emc_pmacro_ib_vref_dqs_1; + MAKE_EMC_REG(EMC_PMACRO_IB_RXRT) = params->emc_pmacro_ib_rxrt; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_0) = params->emc_pmacro_quse_ddll_rank0_0; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_1) = params->emc_pmacro_quse_ddll_rank0_1; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_2) = params->emc_pmacro_quse_ddll_rank0_2; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_3) = params->emc_pmacro_quse_ddll_rank0_3; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_4) = params->emc_pmacro_quse_ddll_rank0_4; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK0_5) = params->emc_pmacro_quse_ddll_rank0_5; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_0) = params->emc_pmacro_quse_ddll_rank1_0; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_1) = params->emc_pmacro_quse_ddll_rank1_1; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_2) = params->emc_pmacro_quse_ddll_rank1_2; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_3) = params->emc_pmacro_quse_ddll_rank1_3; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_4) = params->emc_pmacro_quse_ddll_rank1_4; + MAKE_EMC_REG(EMC_PMACRO_QUSE_DDLL_RANK1_5) = params->emc_pmacro_quse_ddll_rank1_5; + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU1) = params->emc_pmacro_brick_ctrl_rfu1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_0) = params->emc_pmacro_ob_ddll_long_dq_rank0_0; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_1) = params->emc_pmacro_ob_ddll_long_dq_rank0_1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_2) = params->emc_pmacro_ob_ddll_long_dq_rank0_2; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_3) = params->emc_pmacro_ob_ddll_long_dq_rank0_3; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_4) = params->emc_pmacro_ob_ddll_long_dq_rank0_4; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK0_5) = params->emc_pmacro_ob_ddll_long_dq_rank0_5; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_0) = params->emc_pmacro_ob_ddll_long_dq_rank1_0; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_1) = params->emc_pmacro_ob_ddll_long_dq_rank1_1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_2) = params->emc_pmacro_ob_ddll_long_dq_rank1_2; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_3) = params->emc_pmacro_ob_ddll_long_dq_rank1_3; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_4) = params->emc_pmacro_ob_ddll_long_dq_rank1_4; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQ_RANK1_5) = params->emc_pmacro_ob_ddll_long_dq_rank1_5; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ob_ddll_long_dqs_rank0_0; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ob_ddll_long_dqs_rank0_1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ob_ddll_long_dqs_rank0_2; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ob_ddll_long_dqs_rank0_3; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_4) = params->emc_pmacro_ob_ddll_long_dqs_rank0_4; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK0_5) = params->emc_pmacro_ob_ddll_long_dqs_rank0_5; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ob_ddll_long_dqs_rank1_0; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ob_ddll_long_dqs_rank1_1; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ob_ddll_long_dqs_rank1_2; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ob_ddll_long_dqs_rank1_3; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_4) = params->emc_pmacro_ob_ddll_long_dqs_rank1_4; + MAKE_EMC_REG(EMC_PMACRO_OB_DDLL_LONG_DQS_RANK1_5) = params->emc_pmacro_ob_ddll_long_dqs_rank1_5; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_0) = params->emc_pmacro_ib_ddll_long_dqs_rank0_0; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_1) = params->emc_pmacro_ib_ddll_long_dqs_rank0_1; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_2) = params->emc_pmacro_ib_ddll_long_dqs_rank0_2; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK0_3) = params->emc_pmacro_ib_ddll_long_dqs_rank0_3; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_0) = params->emc_pmacro_ib_ddll_long_dqs_rank1_0; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_1) = params->emc_pmacro_ib_ddll_long_dqs_rank1_1; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_2) = params->emc_pmacro_ib_ddll_long_dqs_rank1_2; + MAKE_EMC_REG(EMC_PMACRO_IB_DDLL_LONG_DQS_RANK1_3) = params->emc_pmacro_ib_ddll_long_dqs_rank1_3; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_0) = params->emc_pmacro_ddll_long_cmd_0; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_1) = params->emc_pmacro_ddll_long_cmd_1; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_2) = params->emc_pmacro_ddll_long_cmd_2; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_3) = params->emc_pmacro_ddll_long_cmd_3; + MAKE_EMC_REG(EMC_PMACRO_DDLL_LONG_CMD_4) = params->emc_pmacro_ddll_long_cmd_4; + MAKE_EMC_REG(EMC_PMACRO_DDLL_SHORT_CMD_0) = params->emc_pmacro_ddll_short_cmd_0; + MAKE_EMC_REG(EMC_PMACRO_DDLL_SHORT_CMD_1) = params->emc_pmacro_ddll_short_cmd_1; + MAKE_EMC_REG(EMC_PMACRO_DDLL_SHORT_CMD_2) = params->emc_pmacro_ddll_short_cmd_2; + MAKE_EMC_REG(EMC_PMACRO_COMMON_PAD_TX_CTRL) = ((params->emc_pmacro_common_pad_tx_ctrl & 1) | 0xE); + + if (params->emc_bct_spare4) + *(volatile uint32_t *)params->emc_bct_spare4 = params->emc_bct_spare5; + + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + + MAKE_MC_REG(MC_VIDEO_PROTECT_BOM) = params->mc_video_protect_bom; + MAKE_MC_REG(MC_VIDEO_PROTECT_BOM_ADR_HI) = params->mc_video_protect_bom_adr_hi; + MAKE_MC_REG(MC_VIDEO_PROTECT_SIZE_MB) = params->mc_video_protect_size_mb; + MAKE_MC_REG(MC_VIDEO_PROTECT_VPR_OVERRIDE) = params->mc_video_protect_vpr_override; + MAKE_MC_REG(MC_VIDEO_PROTECT_VPR_OVERRIDE1) = params->mc_video_protect_vpr_override1; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_0) = params->mc_video_protect_gpu_override0; + MAKE_MC_REG(MC_VIDEO_PROTECT_GPU_OVERRIDE_1) = params->mc_video_protect_gpu_override1; + MAKE_MC_REG(MC_EMEM_ADR_CFG) = params->mc_emem_adr_cfg; + MAKE_MC_REG(MC_EMEM_ADR_CFG_DEV0) = params->mc_emem_adr_cfg_dev0; + MAKE_MC_REG(MC_EMEM_ADR_CFG_DEV1) = params->mc_emem_adr_cfg_dev1; + MAKE_MC_REG(MC_EMEM_ADR_CFG_CHANNEL_MASK) = params->mc_emem_adr_cfg_channel_mask; + MAKE_MC_REG(MC_EMEM_ADR_CFG_BANK_MASK_0) = params->mc_emem_adr_cfg_bank_mask0; + MAKE_MC_REG(MC_EMEM_ADR_CFG_BANK_MASK_1) = params->mc_emem_adr_cfg_bank_mask1; + MAKE_MC_REG(MC_EMEM_ADR_CFG_BANK_MASK_2) = params->mc_emem_adr_cfg_bank_mask2; + MAKE_MC_REG(MC_EMEM_CFG) = params->mc_emem_cfg; + MAKE_MC_REG(MC_SEC_CARVEOUT_BOM) = params->mc_sec_carveout_bom; + MAKE_MC_REG(MC_SEC_CARVEOUT_ADR_HI) = params->mc_sec_carveout_adr_hi; + MAKE_MC_REG(MC_SEC_CARVEOUT_SIZE_MB) = params->mc_sec_carveout_size_mb; + MAKE_MC_REG(MC_MTS_CARVEOUT_BOM) = params->mc_mts_carveout_bom; + MAKE_MC_REG(MC_MTS_CARVEOUT_ADR_HI) = params->mc_mts_carveout_adr_hi; + MAKE_MC_REG(MC_MTS_CARVEOUT_SIZE_MB) = params->mc_mts_carveout_size_mb; + MAKE_MC_REG(MC_EMEM_ARB_CFG) = params->mc_emem_arb_cfg; + MAKE_MC_REG(MC_EMEM_ARB_OUTSTANDING_REQ) = params->mc_emem_arb_outstanding_req; + MAKE_MC_REG(MC_EMEM_ARB_REFPB_HP_CTRL) = params->emc_emem_arb_refpb_hp_ctrl; + MAKE_MC_REG(MC_EMEM_ARB_REFPB_BANK_CTRL) = params->emc_emem_arb_refpb_bank_ctrl; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RCD) = params->mc_emem_arb_timing_rcd; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RP) = params->mc_emem_arb_timing_rp; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RC) = params->mc_emem_arb_timing_rc; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RAS) = params->mc_emem_arb_timing_ras; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_FAW) = params->mc_emem_arb_timing_faw; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RRD) = params->mc_emem_arb_timing_rrd; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RAP2PRE) = params->mc_emem_arb_timing_rap2pre; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_WAP2PRE) = params->mc_emem_arb_timing_wap2pre; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_R2R) = params->mc_emem_arb_timing_r2r; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_W2W) = params->mc_emem_arb_timing_w2w; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_CCDMW) = params->mc_emem_arb_timing_ccdmw; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_R2W) = params->mc_emem_arb_timing_r2w; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_W2R) = params->mc_emem_arb_timing_w2r; + MAKE_MC_REG(MC_EMEM_ARB_TIMING_RFCPB) = params->mc_emem_arb_timing_rfcpb; + MAKE_MC_REG(MC_EMEM_ARB_DA_TURNS) = params->mc_emem_arb_da_turns; + MAKE_MC_REG(MC_EMEM_ARB_DA_COVERS) = params->mc_emem_arb_da_covers; + MAKE_MC_REG(MC_EMEM_ARB_MISC0) = params->mc_emem_arb_misc0; + MAKE_MC_REG(MC_EMEM_ARB_MISC1) = params->mc_emem_arb_misc1; + MAKE_MC_REG(MC_EMEM_ARB_MISC2) = params->mc_emem_arb_misc2; + MAKE_MC_REG(MC_EMEM_ARB_RING1_THROTTLE) = params->mc_emem_arb_ring1_throttle; + MAKE_MC_REG(MC_EMEM_ARB_OVERRIDE) = params->mc_emem_arb_override; + MAKE_MC_REG(MC_EMEM_ARB_OVERRIDE_1) = params->mc_emem_arb_override1; + MAKE_MC_REG(MC_EMEM_ARB_RSV) = params->mc_emem_arb_rsv; + MAKE_MC_REG(MC_DA_CONFIG0) = params->mc_da_cfg0; + MAKE_MC_REG(MC_TIMING_CONTROL) = 1; + MAKE_MC_REG(MC_CLKEN_OVERRIDE) = params->mc_clken_override; + MAKE_MC_REG(MC_STAT_CONTROL) = params->mc_stat_control; + + MAKE_EMC_REG(EMC_ADR_CFG) = params->emc_adr_cfg; + MAKE_EMC_REG(EMC_CLKEN_OVERRIDE) = params->emc_clken_override; + MAKE_EMC_REG(EMC_PMACRO_AUTOCAL_CFG_0) = params->emc_pmacro_auto_cal_cfg0; + MAKE_EMC_REG(EMC_PMACRO_AUTOCAL_CFG_1) = params->emc_pmacro_auto_cal_cfg1; + MAKE_EMC_REG(EMC_PMACRO_AUTOCAL_CFG_2) = params->emc_pmacro_auto_cal_cfg2; + MAKE_EMC_REG(EMC_AUTO_CAL_VREF_SEL_0) = params->emc_auto_cal_vref_sel0; + MAKE_EMC_REG(EMC_AUTO_CAL_VREF_SEL_1) = params->emc_auto_cal_vref_sel1; + MAKE_EMC_REG(EMC_AUTO_CAL_INTERVAL) = params->emc_auto_cal_interval; + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG) = params->emc_auto_cal_config; + udelay(params->emc_auto_cal_wait); + + if (params->emc_bct_spare8) + *(volatile uint32_t *)params->emc_bct_spare8 = params->emc_bct_spare9; + + MAKE_EMC_REG(EMC_CFG_2) = params->emc_cfg2; + MAKE_EMC_REG(EMC_CFG_PIPE) = params->emc_cfg_pipe; + MAKE_EMC_REG(EMC_CFG_PIPE_1) = params->emc_cfg_pipe1; + MAKE_EMC_REG(EMC_CFG_PIPE_2) = params->emc_cfg_pipe2; + MAKE_EMC_REG(EMC_CMDQ) = params->emc_cmd_q; + MAKE_EMC_REG(EMC_MC2EMCQ) = params->emc_mc2emc_q; + MAKE_EMC_REG(EMC_MRS_WAIT_CNT) = params->emc_mrs_wait_cnt; + MAKE_EMC_REG(EMC_MRS_WAIT_CNT2) = params->emc_mrs_wait_cnt2; + MAKE_EMC_REG(EMC_FBIO_CFG5) = params->emc_fbio_cfg5; + MAKE_EMC_REG(EMC_RC) = params->emc_rc; + MAKE_EMC_REG(EMC_RFC) = params->emc_rfc; + MAKE_EMC_REG(EMC_RFCPB) = params->emc_rfc_pb; + MAKE_EMC_REG(EMC_REFCTRL2) = params->emc_ref_ctrl2; + MAKE_EMC_REG(EMC_RFC_SLR) = params->emc_rfc_slr; + MAKE_EMC_REG(EMC_RAS) = params->emc_ras; + MAKE_EMC_REG(EMC_RP) = params->emc_rp; + MAKE_EMC_REG(EMC_TPPD) = params->emc_tppd; + MAKE_EMC_REG(EMC_R2R) = params->emc_r2r; + MAKE_EMC_REG(EMC_W2W) = params->emc_w2w; + MAKE_EMC_REG(EMC_R2W) = params->emc_r2w; + MAKE_EMC_REG(EMC_W2R) = params->emc_w2r; + MAKE_EMC_REG(EMC_R2P) = params->emc_r2p; + MAKE_EMC_REG(EMC_W2P) = params->emc_w2p; + MAKE_EMC_REG(EMC_CCDMW) = params->emc_ccdmw; + MAKE_EMC_REG(EMC_RD_RCD) = params->emc_rd_rcd; + MAKE_EMC_REG(EMC_WR_RCD) = params->emc_wr_rcd; + MAKE_EMC_REG(EMC_RRD) = params->emc_rrd; + MAKE_EMC_REG(EMC_REXT) = params->emc_rext; + MAKE_EMC_REG(EMC_WEXT) = params->emc_wext; + MAKE_EMC_REG(EMC_WDV) = params->emc_wdv; + MAKE_EMC_REG(EMC_WDV_CHK) = params->emc_wdv_chk; + MAKE_EMC_REG(EMC_WSV) = params->emc_wsv; + MAKE_EMC_REG(EMC_WEV) = params->emc_wev; + MAKE_EMC_REG(EMC_WDV_MASK) = params->emc_wdv_mask; + MAKE_EMC_REG(EMC_WS_DURATION) = params->emc_ws_duration; + MAKE_EMC_REG(EMC_WE_DURATION) = params->emc_we_duration; + MAKE_EMC_REG(EMC_QUSE) = params->emc_quse; + MAKE_EMC_REG(EMC_QUSE_WIDTH) = params->emc_quse_width; + MAKE_EMC_REG(EMC_IBDLY) = params->emc_ibdly; + MAKE_EMC_REG(EMC_OBDLY) = params->emc_obdly; + MAKE_EMC_REG(EMC_EINPUT) = params->emc_einput; + MAKE_EMC_REG(EMC_EINPUT_DURATION) = params->emc_einput_duration; + MAKE_EMC_REG(EMC_PUTERM_EXTRA) = params->emc_puterm_extra; + MAKE_EMC_REG(EMC_PUTERM_WIDTH) = params->emc_puterm_width; + MAKE_EMC_REG(EMC_PMACRO_COMMON_PAD_TX_CTRL) = params->emc_pmacro_common_pad_tx_ctrl; + MAKE_EMC_REG(EMC_DBG) = params->emc_dbg; + MAKE_EMC_REG(EMC_QRST) = params->emc_qrst; + MAKE_EMC_REG(EMC_ISSUE_QRST) = 0; + MAKE_EMC_REG(EMC_QSAFE) = params->emc_qsafe; + MAKE_EMC_REG(EMC_RDV) = params->emc_rdv; + MAKE_EMC_REG(EMC_RDV_MASK) = params->emc_rdv_mask; + MAKE_EMC_REG(EMC_RDV_EARLY) = params->emc_rdv_early; + MAKE_EMC_REG(EMC_RDV_EARLY_MASK) = params->emc_rdv_early_mask; + MAKE_EMC_REG(EMC_QPOP) = params->emc_qpop; + MAKE_EMC_REG(EMC_REFRESH) = params->emc_refresh; + MAKE_EMC_REG(EMC_BURST_REFRESH_NUM) = params->emc_burst_refresh_num; + MAKE_EMC_REG(EMC_PRE_REFRESH_REQ_CNT) = params->emc_prerefresh_req_cnt; + MAKE_EMC_REG(EMC_PDEX2WR) = params->emc_pdex2wr; + MAKE_EMC_REG(EMC_PDEX2RD) = params->emc_pdex2rd; + MAKE_EMC_REG(EMC_PCHG2PDEN) = params->emc_pchg2pden; + MAKE_EMC_REG(EMC_ACT2PDEN) = params->emc_act2pden; + MAKE_EMC_REG(EMC_AR2PDEN) = params->emc_ar2pden; + MAKE_EMC_REG(EMC_RW2PDEN) = params->emc_rw2pden; + MAKE_EMC_REG(EMC_CKE2PDEN) = params->emc_cke2pden; + MAKE_EMC_REG(EMC_PDEX2CKE) = params->emc_pdex2che; + MAKE_EMC_REG(EMC_PDEX2MRR) = params->emc_pdex2mrr; + MAKE_EMC_REG(EMC_TXSR) = params->emc_txsr; + MAKE_EMC_REG(EMC_TXSRDLL) = params->emc_txsr_dll; + MAKE_EMC_REG(EMC_TCKE) = params->emc_tcke; + MAKE_EMC_REG(EMC_TCKESR) = params->emc_tckesr; + MAKE_EMC_REG(EMC_TPD) = params->emc_tpd; + MAKE_EMC_REG(EMC_TFAW) = params->emc_tfaw; + MAKE_EMC_REG(EMC_TRPAB) = params->emc_trpab; + MAKE_EMC_REG(EMC_TCLKSTABLE) = params->emc_tclkstable; + MAKE_EMC_REG(EMC_TCLKSTOP) = params->emc_tclkstop; + MAKE_EMC_REG(EMC_TREFBW) = params->emc_trefbw; + MAKE_EMC_REG(EMC_ODT_WRITE) = params->emc_odt_write; + MAKE_EMC_REG(EMC_CFG_DIG_DLL) = params->emc_cfg_dig_dll; + MAKE_EMC_REG(EMC_CFG_DIG_DLL_PERIOD) = params->emc_cfg_dig_dll_period; + MAKE_EMC_REG(EMC_FBIO_SPARE) = params->emc_fbio_spare & 0xFFFFFFFD; + MAKE_EMC_REG(EMC_CFG_RSV) = params->emc_cfg_rsv; + MAKE_EMC_REG(EMC_PMC_SCRATCH1) = params->emc_pmc_scratch1; + MAKE_EMC_REG(EMC_PMC_SCRATCH2) = params->emc_pmc_scratch2; + MAKE_EMC_REG(EMC_PMC_SCRATCH3) = params->emc_pmc_scratch3; + MAKE_EMC_REG(EMC_ACPD_CONTROL) = params->emc_acpd_control; + MAKE_EMC_REG(EMC_TXDSRVTTGEN) = params->emc_txdsrvttgen; + MAKE_EMC_REG(EMC_CFG) = (params->emc_cfg & 0xE) | 0x3C00000; + + if (params->boot_rom_patch_control & 0x80000000) + { + *(volatile uint32_t *)(4 * (params->boot_rom_patch_control + 0x1C000000)) = params->boot_rom_patch_data; + MAKE_MC_REG(MC_TIMING_CONTROL) = 1; + } + + pmc->io_dpd3_req = (((4 * params->emc_pmc_scratch1 >> 2) + 0x40000000) & 0xCFFF0000); + udelay(params->pmc_io_dpd3_req_wait); + + if (!params->emc_auto_cal_interval) + MAKE_EMC_REG(EMC_AUTO_CAL_CONFIG) = (params->emc_auto_cal_config | 0x200); + + MAKE_EMC_REG(EMC_PMACRO_BRICK_CTRL_RFU2) = params->emc_pmacro_brick_ctrl_rfu2; + + if (params->emc_zcal_warm_cold_boot_enables & 1) + { + if (params->memory_type == 2) + MAKE_EMC_REG(EMC_ZCAL_WAIT_CNT) = (8 * params->emc_zcal_wait_cnt); + + if (params->memory_type == 3) + { + MAKE_EMC_REG(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; + MAKE_EMC_REG(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; + } + } + + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + udelay(params->emc_timing_control_wait); + + pmc->ddr_cntrl &= 0xFFF8007F; + udelay(params->pmc_ddr_ctrl_wait); + + if (params->memory_type == 2) + { + MAKE_EMC_REG(EMC_PIN) = ((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)); + udelay(params->emc_pin_extra_wait + 200); + MAKE_EMC_REG(EMC_PIN) = (((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 256); + udelay(params->emc_pin_extra_wait + 500); + } + + if (params->memory_type == 3) + { + MAKE_EMC_REG(EMC_PIN) = ((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)); + udelay(params->emc_pin_extra_wait + 200); + MAKE_EMC_REG(EMC_PIN) = (((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 256); + udelay(params->emc_pin_extra_wait + 2000); + } + + MAKE_EMC_REG(EMC_PIN) = (((params->emc_pin_gpio_enable << 16) | (params->emc_pin_gpio << 12)) + 0x101); + udelay(params->emc_pin_program_wait); + + if (params->memory_type != 3) + MAKE_EMC_REG(EMC_NOP) = ((params->emc_dev_select << 30) + 1); + + if (params->memory_type == 1) + udelay(params->emc_pin_extra_wait + 200); + + if (params->memory_type == 3) + { + if (params->emc_bct_spare10) + *(volatile uint32_t *)params->emc_bct_spare10 = params->emc_bct_spare11; + + MAKE_EMC_REG(EMC_MRW2) = params->emc_mrw2; + MAKE_EMC_REG(EMC_MRW) = params->emc_mrw1; + MAKE_EMC_REG(EMC_MRW3) = params->emc_mrw3; + MAKE_EMC_REG(EMC_MRW4) = params->emc_mrw4; + MAKE_EMC_REG(EMC_MRW6) = params->emc_mrw6; + MAKE_EMC_REG(EMC_MRW14) = params->emc_mrw14; + MAKE_EMC_REG(EMC_MRW8) = params->emc_mrw8; + MAKE_EMC_REG(EMC_MRW12) = params->emc_mrw12; + MAKE_EMC_REG(EMC_MRW9) = params->emc_mrw9; + MAKE_EMC_REG(EMC_MRW13) = params->emc_mrw13; + + if (params->emc_zcal_warm_cold_boot_enables & 1) + { + MAKE_EMC_REG(EMC_ZQ_CAL) = params->emc_zcal_init_dev0; + udelay(params->emc_zcal_init_wait); + MAKE_EMC_REG(EMC_ZQ_CAL) = (params->emc_zcal_init_dev0 ^ 3); + + if (!(params->emc_dev_select & 2)) + { + MAKE_EMC_REG(EMC_ZQ_CAL) = params->emc_zcal_init_dev1; + udelay(params->emc_zcal_init_wait); + MAKE_EMC_REG(EMC_ZQ_CAL) = (params->emc_zcal_init_dev1 ^ 3); + } + } + } + + pmc->ddr_cfg = params->pmc_ddr_cfg; + if ((params->memory_type - 1) <= 2) + { + MAKE_EMC_REG(EMC_ZCAL_INTERVAL) = params->emc_zcal_interval; + MAKE_EMC_REG(EMC_ZCAL_WAIT_CNT) = params->emc_zcal_wait_cnt; + MAKE_EMC_REG(EMC_ZCAL_MRW_CMD) = params->emc_zcal_mrw_cmd; + } + + if (params->emc_bct_spare12) + *(volatile uint32_t *)params->emc_bct_spare12 = params->emc_bct_spare13; + + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + + if (params->emc_extra_refresh_num) + MAKE_EMC_REG(EMC_REF) = (((1 << params->emc_extra_refresh_num << 8) - 0xFD) | (params->emc_pin_gpio << 30)); + + MAKE_EMC_REG(EMC_REFCTRL) = (params->emc_dev_select | 0x80000000); + MAKE_EMC_REG(EMC_DYN_SELF_REF_CONTROL) = params->emc_dyn_self_ref_control; + MAKE_EMC_REG(EMC_CFG_UPDATE) = params->emc_cfg_update; + MAKE_EMC_REG(EMC_CFG) = params->emc_cfg; + MAKE_EMC_REG(EMC_FDPD_CTRL_DQ) = params->emc_fdpd_ctrl_dq; + MAKE_EMC_REG(EMC_FDPD_CTRL_CMD) = params->emc_fdpd_ctrl_cmd; + MAKE_EMC_REG(EMC_SEL_DPD_CTRL) = params->emc_sel_dpd_ctrl; + MAKE_EMC_REG(EMC_FBIO_SPARE) = (params->emc_fbio_spare | 2); + MAKE_EMC_REG(EMC_TIMING_CONTROL) = 1; + MAKE_EMC_REG(EMC_CFG_PIPE_CLK) = params->emc_cfg_pipe_clk; + MAKE_EMC_REG(EMC_FDPD_CTRL_CMD_NO_RAMP) = params->emc_fdpd_ctrl_cmd_no_ramp; + + AHB_ARBITRATION_XBAR_CTRL_0 = ((AHB_ARBITRATION_XBAR_CTRL_0 & 0xFFFEFFFF) | ((params->ahb_arbitration_xbar_ctrl_meminit_done & 0xFFFF) << 16)); + + MAKE_MC_REG(MC_VIDEO_PROTECT_REG_CTRL) = params->mc_video_protect_write_access; + MAKE_MC_REG(MC_SEC_CARVEOUT_REG_CTRL) = params->mc_sec_carveout_protect_write_access; + MAKE_MC_REG(MC_MTS_CARVEOUT_REG_CTRL) = params->mc_mts_carveout_reg_ctrl; + MAKE_MC_REG(MC_EMEM_CFG_ACCESS_CTRL) = 1; /* Disable write access to a bunch of MC registers. */ +} + +const void *sdram_get_params() +{ + /* TODO: sdram_id should be in [0, 7]. */ + +#ifdef CONFIG_SDRAM_COMPRESS_CFG + uint8_t *buf = (uint8_t *)0x40030000; + LZ_Uncompress(_dram_cfg_lz, buf, sizeof(_dram_cfg_lz)); + return (const void *)&buf[sizeof(sdram_params_t) * _get_sdram_id()]; +#else + return _dram_cfgs[_get_sdram_id()]; +#endif +} + +void sdram_init() +{ + volatile tegra_pmc_t *pmc = pmc_get_regs(); + + /* TODO: sdram_id should be in [0,4]. */ + const sdram_params_t *params = (const sdram_params_t *)sdram_get_params(); + + uint8_t val = 5; + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD_CFG2, &val, 1); + val = 40; /* 40 = (1000 * 1100 - 600000) / 12500 -> 1.1V */ + i2c_send(I2C_5, MAX77620_PWR_I2C_ADDR, MAX77620_REG_SD1, &val, 1); + + pmc->vddp_sel = params->pmc_vddp_sel; + udelay(params->pmc_vddp_sel_wait); + + pmc->ddr_pwr = pmc->ddr_pwr; + pmc->no_iopower = params->pmc_no_io_power; + pmc->reg_short = params->pmc_reg_short; + pmc->ddr_cntrl = params->pmc_ddr_ctrl; + + if (params->emc_bct_spare0) + *(volatile uint32_t *)params->emc_bct_spare0 = params->emc_bct_spare1; + + _sdram_config(params); +} diff --git a/sept/sept-secondary/src/sdram.h b/sept/sept-secondary/src/sdram.h new file mode 100644 index 000000000..b63f14ba6 --- /dev/null +++ b/sept/sept-secondary/src/sdram.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SDRAM_H_ +#define FUSEE_SDRAM_H_ + +void sdram_init(); +const void *sdram_get_params(); +void sdram_lp0_save_params(const void *params); + +#endif diff --git a/sept/sept-secondary/src/sdram.inl b/sept/sept-secondary/src/sdram.inl new file mode 100644 index 000000000..845ad1161 --- /dev/null +++ b/sept/sept-secondary/src/sdram.inl @@ -0,0 +1,1152 @@ +/* + * Copyright (c) 2018 naehrwert + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +static const uint8_t _dram_cfg_0[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_1[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_2[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_3[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_4[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x10, 0x00, 0x14, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, 0x33, 0x00, 0x35, 0x00, + 0x30, 0x00, 0x32, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x0C, 0x00, + 0x02, 0x03, 0x0C, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x18, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_5[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, + 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, + 0x2F, 0x00, 0x33, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, + 0x2F, 0x00, 0x33, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x15, 0x00, 0x15, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, 0x16, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t _dram_cfg_6[1896] = { + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, 0x00, 0x04, 0xB4, 0x01, 0x70, + 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x1F, 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x77, 0x00, + 0xA6, 0xA6, 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, + 0xA1, 0x01, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x00, 0x00, + 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC1, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x00, 0x00, 0x0D, 0xA0, 0x60, 0x91, + 0xBF, 0x3B, 0x00, 0x00, 0x00, 0x00, 0xF3, 0x0C, 0x04, 0x05, 0x1B, 0x06, + 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, 0x08, 0x1D, 0x09, 0x0A, + 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, 0x02, 0x1B, 0x1C, 0x23, + 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, 0x0A, 0x0B, 0x1D, 0x0D, + 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, 0x24, 0x06, 0x07, 0x9A, + 0x12, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x0D, 0x08, + 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, 0x00, 0x0B, 0x08, + 0x72, 0x72, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0D, 0x0C, + 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x04, 0x00, 0x01, 0x08, + 0x00, 0x00, 0x11, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0xCC, 0x00, + 0x0A, 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, + 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x03, 0x00, 0x70, 0x00, 0x0C, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x2C, 0x00, 0x01, 0x37, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, + 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, 0x28, 0x28, + 0x28, 0x28, 0x28, 0x28, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0xBE, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, + 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, + 0x2F, 0x00, 0x33, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, 0x34, 0x00, 0x36, 0x00, + 0x2F, 0x00, 0x33, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, + 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x15, 0x00, 0x15, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x16, 0x00, 0x16, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, + 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x04, 0xFF, 0xFF, 0xAF, 0x4F, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x32, 0x54, 0x76, 0x10, 0x47, 0x32, 0x65, + 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, 0x64, 0x32, + 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, 0x32, 0x67, + 0x00, 0x00, 0x00, 0x00, 0x49, 0x92, 0x24, 0x00, 0x49, 0x92, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2F, 0x41, 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xAF, 0x4F, 0xFF, 0xFF, 0xFF, 0x7F, 0x0B, 0xD7, 0x06, 0x40, + 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, 0x00, 0x00, 0x5C, 0x01, 0x00, + 0x10, 0x10, 0x10, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x37, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x11, 0x01, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x81, 0x10, 0x09, 0x28, 0x93, 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xDC, 0xDC, 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, + 0x0A, 0x0A, 0x0A, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0x07, 0x00, + 0x02, 0x03, 0x07, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, + 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, 0x9C, 0x4B, 0x00, 0x10, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, 0x80, 0x20, 0x10, 0x0A, 0x00, + 0x28, 0x10, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, + 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0xA3, 0x72, 0x0F, 0x0F, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7E, 0x16, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x1E, 0x40, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x2C, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint32_t *_dram_cfgs[7] = { + (const uint32_t *)_dram_cfg_0, + (const uint32_t *)_dram_cfg_1, + (const uint32_t *)_dram_cfg_2, + (const uint32_t *)_dram_cfg_3, + (const uint32_t *)_dram_cfg_4, + (const uint32_t *)_dram_cfg_5, + (const uint32_t *)_dram_cfg_6 +}; diff --git a/sept/sept-secondary/src/sdram_lp0.c b/sept/sept-secondary/src/sdram_lp0.c new file mode 100644 index 000000000..12864e63c --- /dev/null +++ b/sept/sept-secondary/src/sdram_lp0.c @@ -0,0 +1,1125 @@ +/* + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "pmc.h" +#include "sdram_param_t210_lp0.h" + +/* + * This function reads SDRAM parameters from the common BCT format and + * writes them into PMC scratch registers (where the BootROM expects them + * on LP0 resume). + */ +void sdram_lp0_save_params(const void *params) +{ + struct sdram_params *sdram = (struct sdram_params *)params; + volatile tegra_pmc_t *pmc = pmc_get_regs(); + +#define pack(src, src_bits, dst, dst_bits) { \ + uint32_t mask = 0xffffffff >> (31 - ((1 ? src_bits) - (0 ? src_bits))); \ + dst &= ~(mask << (0 ? dst_bits)); \ + dst |= ((src >> (0 ? src_bits)) & mask) << (0 ? dst_bits); \ +} + +#define s(param, src_bits, pmcreg, dst_bits) \ + pack(sdram->param, src_bits, pmc->pmcreg, dst_bits) + +#define c(value, pmcreg, dst_bits) \ + pack(value, (1 ? dst_bits) - (0 ? dst_bits) : 0, pmc->pmcreg, dst_bits) + +/* 32 bits version of s macro */ +#define s32(param, pmcreg) pmc->pmcreg = sdram->param + +/* 32 bits version c macro */ +#define c32(value, pmcreg) pmc->pmcreg = value + + //TODO: pkg1.1 (1.X - 3.X) reads them from MC. + // Patch carveout parameters. + /*sdram->McGeneralizedCarveout1Bom = 0; + sdram->McGeneralizedCarveout1BomHi = 0; + sdram->McGeneralizedCarveout1Size128kb = 0; + sdram->McGeneralizedCarveout1Access0 = 0; + sdram->McGeneralizedCarveout1Access1 = 0; + sdram->McGeneralizedCarveout1Access2 = 0; + sdram->McGeneralizedCarveout1Access3 = 0; + sdram->McGeneralizedCarveout1Access4 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout1ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout1Cfg0 = 0; + sdram->McGeneralizedCarveout2Bom = 0x80020000; + sdram->McGeneralizedCarveout2BomHi = 0; + sdram->McGeneralizedCarveout2Size128kb = 2; + sdram->McGeneralizedCarveout2Access0 = 0; + sdram->McGeneralizedCarveout2Access1 = 0; + sdram->McGeneralizedCarveout2Access2 = 0x3000000; + sdram->McGeneralizedCarveout2Access3 = 0; + sdram->McGeneralizedCarveout2Access4 = 0x300; + sdram->McGeneralizedCarveout2ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout2ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout2ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout2ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout2ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout2Cfg0 = 0x440167E; + sdram->McGeneralizedCarveout3Bom = 0; + sdram->McGeneralizedCarveout3BomHi = 0; + sdram->McGeneralizedCarveout3Size128kb = 0; + sdram->McGeneralizedCarveout3Access0 = 0; + sdram->McGeneralizedCarveout3Access1 = 0; + sdram->McGeneralizedCarveout3Access2 = 0x3000000; + sdram->McGeneralizedCarveout3Access3 = 0; + sdram->McGeneralizedCarveout3Access4 = 0x300; + sdram->McGeneralizedCarveout3ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout3ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout3ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout3ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout3ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout3Cfg0 = 0x4401E7E; + sdram->McGeneralizedCarveout4Bom = 0; + sdram->McGeneralizedCarveout4BomHi = 0; + sdram->McGeneralizedCarveout4Size128kb = 0; + sdram->McGeneralizedCarveout4Access0 = 0; + sdram->McGeneralizedCarveout4Access1 = 0; + sdram->McGeneralizedCarveout4Access2 = 0; + sdram->McGeneralizedCarveout4Access3 = 0; + sdram->McGeneralizedCarveout4Access4 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout4ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout4Cfg0 = 0x8F; + sdram->McGeneralizedCarveout5Bom = 0; + sdram->McGeneralizedCarveout5BomHi = 0; + sdram->McGeneralizedCarveout5Size128kb = 0; + sdram->McGeneralizedCarveout5Access0 = 0; + sdram->McGeneralizedCarveout5Access1 = 0; + sdram->McGeneralizedCarveout5Access2 = 0; + sdram->McGeneralizedCarveout5Access3 = 0; + sdram->McGeneralizedCarveout5Access4 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess0 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess1 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess2 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess3 = 0; + sdram->McGeneralizedCarveout5ForceInternalAccess4 = 0; + sdram->McGeneralizedCarveout5Cfg0 = 0x8F;*/ + + //TODO: this is 4.X+ behaviour which seems to work fine for < 4.X. + // Patch carveout parameters. + sdram->McGeneralizedCarveout1Cfg0 = 0; + sdram->McGeneralizedCarveout2Cfg0 = 0; + sdram->McGeneralizedCarveout3Cfg0 = 0; + sdram->McGeneralizedCarveout4Cfg0 = 0; + sdram->McGeneralizedCarveout5Cfg0 = 0; + + // Patch SDRAM parameters. + uint32_t t0 = sdram->EmcSwizzleRank0Byte0 << 5 >> 29 > sdram->EmcSwizzleRank0Byte0 << 1 >> 29; + uint32_t t1 = (t0 & 0xFFFFFFEF) | ((sdram->EmcSwizzleRank1Byte0 << 5 >> 29 > sdram->EmcSwizzleRank1Byte0 << 1 >> 29) << 4); + uint32_t t2 = (t1 & 0xFFFFFFFD) | ((sdram->EmcSwizzleRank0Byte1 << 5 >> 29 > sdram->EmcSwizzleRank0Byte1 << 1 >> 29) << 1); + uint32_t t3 = (t2 & 0xFFFFFFDF) | ((sdram->EmcSwizzleRank1Byte1 << 5 >> 29 > sdram->EmcSwizzleRank1Byte1 << 1 >> 29) << 5); + uint32_t t4 = (t3 & 0xFFFFFFFB) | ((sdram->EmcSwizzleRank0Byte2 << 5 >> 29 > sdram->EmcSwizzleRank0Byte2 << 1 >> 29) << 2); + uint32_t t5 = (t4 & 0xFFFFFFBF) | ((sdram->EmcSwizzleRank1Byte2 << 5 >> 29 > sdram->EmcSwizzleRank1Byte2 << 1 >> 29) << 6); + uint32_t t6 = (t5 & 0xFFFFFFF7) | ((sdram->EmcSwizzleRank0Byte3 << 5 >> 29 > sdram->EmcSwizzleRank0Byte3 << 1 >> 29) << 3); + uint32_t t7 = (t6 & 0xFFFFFF7F) | ((sdram->EmcSwizzleRank1Byte3 << 5 >> 29 > sdram->EmcSwizzleRank1Byte3 << 1 >> 29) << 7); + sdram->SwizzleRankByteEncode = t7; + sdram->EmcBctSpare2 = 0x40000DD8; + sdram->EmcBctSpare3 = t7; + + s(EmcClockSource, 7:0, scratch6, 15:8); + s(EmcClockSourceDll, 7:0, scratch6, 23:16); + s(EmcClockSource, 31:29, scratch6, 26:24); + s(EmcClockSourceDll, 31:29, scratch6, 29:27); + s(EmcClockSourceDll, 11:10, scratch6, 31:30); + s(ClkRstControllerPllmMisc2Override, 9:8, scratch7, 1:0); + s(ClkRstControllerPllmMisc2Override, 2:1, scratch7, 3:2); + s(EmcZqCalLpDdr4WarmBoot, 31:30, scratch7, 5:4); + s(EmcClockSource, 15:15, scratch7, 6:6); + s(EmcClockSource, 26:26, scratch7, 7:7); + s(EmcClockSource, 20:20, scratch7, 8:8); + s(EmcClockSource, 19:19, scratch7, 9:9); + s(ClkRstControllerPllmMisc2Override, 13:13, scratch7, 10:10); + s(ClkRstControllerPllmMisc2Override, 12:12, scratch7, 11:11); + s(ClkRstControllerPllmMisc2Override, 11:11, scratch7, 12:12); + s(ClkRstControllerPllmMisc2Override, 10:10, scratch7, 13:13); + s(ClkRstControllerPllmMisc2Override, 5:5, scratch7, 14:14); + s(ClkRstControllerPllmMisc2Override, 4:4, scratch7, 15:15); + s(ClkRstControllerPllmMisc2Override, 3:3, scratch7, 16:16); + s(ClkRstControllerPllmMisc2Override, 0:0, scratch7, 17:17); + s(EmcZqCalLpDdr4WarmBoot, 1:0, scratch7, 19:18); + s(EmcZqCalLpDdr4WarmBoot, 4:4, scratch7, 20:20); + s(EmcOdtWrite, 5:0, scratch7, 26:21); + s(EmcOdtWrite, 11:8, scratch7, 30:27); + s(EmcOdtWrite, 31:31, scratch7, 31:31); + s(EmcFdpdCtrlCmdNoRamp, 0:0, scratch13, 30:30); + s(EmcCfgPipeClk, 0:0, scratch13, 31:31); + s(McEmemArbMisc2, 0:0, scratch14, 30:30); + s(McDaCfg0, 0:0, scratch14, 31:31); + s(EmcQRst, 6:0, scratch15, 26:20); + s(EmcQRst, 20:16, scratch15, 31:27); + s(EmcPmacroCmdTxDrv, 5:0, scratch16, 25:20); + s(EmcPmacroCmdTxDrv, 13:8, scratch16, 31:26); + s(EmcPmacroAutocalCfg0, 2:0, scratch17, 22:20); + s(EmcPmacroAutocalCfg0, 10:8, scratch17, 25:23); + s(EmcPmacroAutocalCfg0, 18:16, scratch17, 28:26); + s(EmcPmacroAutocalCfg0, 26:24, scratch17, 31:29); + s(EmcPmacroAutocalCfg1, 2:0, scratch18, 22:20); + s(EmcPmacroAutocalCfg1, 10:8, scratch18, 25:23); + s(EmcPmacroAutocalCfg1, 18:16, scratch18, 28:26); + s(EmcPmacroAutocalCfg1, 26:24, scratch18, 31:29); + s(EmcPmacroAutocalCfg2, 2:0, scratch19, 22:20); + s(EmcPmacroAutocalCfg2, 10:8, scratch19, 25:23); + s(EmcPmacroAutocalCfg2, 18:16, scratch19, 28:26); + s(EmcPmacroAutocalCfg2, 26:24, scratch19, 31:29); + s32(EmcCfgRsv,scratch22); + s32(EmcAutoCalConfig, scratch23); + s32(EmcAutoCalVrefSel0, scratch24); + s32(EmcPmacroBrickCtrlRfu1, scratch25); + s32(EmcPmacroBrickCtrlRfu2, scratch26); + s32(EmcPmcScratch1, scratch27); + s32(EmcPmcScratch2, scratch28); + s32(EmcPmcScratch3, scratch29); + s32(McEmemArbDaTurns, scratch30); + s(EmcFbioSpare, 31:24, scratch58, 7:0); + s(EmcFbioSpare, 23:16, scratch58, 15:8); + s(EmcFbioSpare, 15:8, scratch58, 23:16); + s(EmcFbioSpare, 7:2, scratch58, 29:24); + s(EmcFbioSpare, 0:0, scratch58, 30:30); + s(EmcDllCfg0, 29:0, scratch59, 29:0); + s(EmcPmacroDdllBypass, 11:0, scratch60, 11:0); + s(EmcPmacroDdllBypass, 27:13, scratch60, 26:12); + s(EmcPmacroDdllBypass, 31:29, scratch60, 29:27); + s(McEmemArbMisc0, 14:0, scratch61, 14:0); + s(McEmemArbMisc0, 30:16, scratch61, 29:15); + s(EmcFdpdCtrlCmd, 16:0, scratch62, 16:0); + s(EmcFdpdCtrlCmd, 31:20, scratch62, 28:17); + s(EmcAutoCalConfig2, 27:0, scratch63, 27:0); + s(EmcBurstRefreshNum, 3:0, scratch63, 31:28); + s(EmcPmacroZctrl, 27:0, scratch64, 27:0); + s(EmcTppd, 3:0, scratch64, 31:28); + s(EmcCfgDigDll, 10:0, scratch65, 10:0); + s(EmcCfgDigDll, 25:12, scratch65, 24:11); + s(EmcCfgDigDll, 27:27, scratch65, 25:25); + s(EmcCfgDigDll, 31:30, scratch65, 27:26); + s(EmcR2r, 3:0, scratch65, 31:28); + s(EmcFdpdCtrlDq, 16:0, scratch66, 16:0); + s(EmcFdpdCtrlDq, 28:20, scratch66, 25:17); + s(EmcFdpdCtrlDq, 31:30, scratch66, 27:26); + s(EmcW2w, 3:0, scratch66, 31:28); + s(EmcPmacroTxPwrd4, 13:0, scratch67, 13:0); + s(EmcPmacroTxPwrd4, 29:16, scratch67, 27:14); + s(EmcPmacroCommonPadTxCtrl, 3:0, scratch67, 31:28); + s(EmcPmacroTxPwrd5, 13:0, scratch68, 13:0); + s(EmcPmacroTxPwrd5, 29:16, scratch68, 27:14); + s(EmcPmacroDdllPwrd0, 4:0, scratch69, 4:0); + s(EmcPmacroDdllPwrd0, 12:6, scratch69, 11:5); + s(EmcPmacroDdllPwrd0, 20:14, scratch69, 18:12); + s(EmcPmacroDdllPwrd0, 28:22, scratch69, 25:19); + s(EmcPmacroDdllPwrd0, 31:30, scratch69, 27:26); + s(EmcCfg, 4:4, scratch69, 31:31); + s(EmcPmacroDdllPwrd1, 4:0, scratch70, 4:0); + s(EmcPmacroDdllPwrd1, 12:6, scratch70, 11:5); + s(EmcPmacroDdllPwrd1, 20:14, scratch70, 18:12); + s(EmcPmacroDdllPwrd1, 28:22, scratch70, 25:19); + s(EmcPmacroDdllPwrd1, 31:30, scratch70, 27:26); + s(EmcCfg, 5:5, scratch70, 31:31); + s(EmcPmacroDdllPwrd2, 4:0, scratch71, 4:0); + s(EmcPmacroDdllPwrd2, 12:6, scratch71, 11:5); + s(EmcPmacroDdllPwrd2, 20:14, scratch71, 18:12); + s(EmcPmacroDdllPwrd2, 28:22, scratch71, 25:19); + s(EmcPmacroDdllPwrd2, 31:30, scratch71, 27:26); + s(EmcFbioCfg5, 23:20, scratch71, 31:28); + s(EmcPmacroIbVrefDq_0, 6:0, scratch72, 6:0); + s(EmcPmacroIbVrefDq_0, 14:8, scratch72, 13:7); + s(EmcPmacroIbVrefDq_0, 22:16, scratch72, 20:14); + s(EmcPmacroIbVrefDq_0, 30:24, scratch72, 27:21); + s(EmcFbioCfg5, 15:13, scratch72, 30:28); + s(EmcCfg, 6:6, scratch72, 31:31); + s(EmcPmacroIbVrefDq_1, 6:0, scratch73, 6:0); + s(EmcPmacroIbVrefDq_1, 14:8, scratch73, 13:7); + s(EmcPmacroIbVrefDq_1, 22:16, scratch73, 20:14); + s(EmcPmacroIbVrefDq_1, 30:24, scratch73, 27:21); + s(EmcCfg2, 5:3, scratch73, 30:28); + s(EmcCfg, 7:7, scratch73, 31:31); + s(EmcPmacroIbVrefDqs_0, 6:0, scratch74, 6:0); + s(EmcPmacroIbVrefDqs_0, 14:8, scratch74, 13:7); + s(EmcPmacroIbVrefDqs_0, 22:16, scratch74, 20:14); + s(EmcPmacroIbVrefDqs_0, 30:24, scratch74, 27:21); + s(EmcCfg, 17:16, scratch74, 29:28); + s(EmcFbioCfg5, 1:0, scratch74, 31:30); + s(EmcPmacroIbVrefDqs_1, 6:0, scratch75, 6:0); + s(EmcPmacroIbVrefDqs_1, 14:8, scratch75, 13:7); + s(EmcPmacroIbVrefDqs_1, 22:16, scratch75, 20:14); + s(EmcPmacroIbVrefDqs_1, 30:24, scratch75, 27:21); + s(EmcFbioCfg5, 3:2, scratch75, 29:28); + s(EmcCfg2, 27:26, scratch75, 31:30); + s(EmcPmacroDdllShortCmd_0, 6:0, scratch76, 6:0); + s(EmcPmacroDdllShortCmd_0, 14:8, scratch76, 13:7); + s(EmcPmacroDdllShortCmd_0, 22:16, scratch76, 20:14); + s(EmcPmacroDdllShortCmd_0, 30:24, scratch76, 27:21); + s(EmcPmacroCmdPadTxCtrl, 3:2, scratch76, 29:28); + s(EmcPmacroCmdPadTxCtrl, 7:6, scratch76, 31:30); + s(EmcPmacroDdllShortCmd_1, 6:0, scratch77, 6:0); + s(EmcPmacroDdllShortCmd_1, 14:8, scratch77, 13:7); + s(EmcPmacroDdllShortCmd_1, 22:16, scratch77, 20:14); + s(EmcPmacroDdllShortCmd_1, 30:24, scratch77, 27:21); + s(EmcPmacroCmdPadTxCtrl, 11:10, scratch77, 29:28); + s(EmcPmacroCmdPadTxCtrl, 15:14, scratch77, 31:30); + s(EmcAutoCalChannel, 5:0, scratch78, 5:0); + s(EmcAutoCalChannel, 11:8, scratch78, 9:6); + s(EmcAutoCalChannel, 27:16, scratch78, 21:10); + s(EmcAutoCalChannel, 31:29, scratch78, 24:22); + s(EmcConfigSampleDelay, 6:0, scratch78, 31:25); + s(EmcPmacroRxTerm, 5:0, scratch79, 5:0); + s(EmcPmacroRxTerm, 13:8, scratch79, 11:6); + s(EmcPmacroRxTerm, 21:16, scratch79, 17:12); + s(EmcPmacroRxTerm, 29:24, scratch79, 23:18); + s(EmcRc, 7:0, scratch79, 31:24); + s(EmcPmacroDqTxDrv, 5:0, scratch80, 5:0); + s(EmcPmacroDqTxDrv, 13:8, scratch80, 11:6); + s(EmcPmacroDqTxDrv, 21:16, scratch80, 17:12); + s(EmcPmacroDqTxDrv, 29:24, scratch80, 23:18); + s(EmcSelDpdCtrl, 5:2, scratch80, 27:24); + s(EmcSelDpdCtrl, 8:8, scratch80, 28:28); + s(EmcSelDpdCtrl, 18:16, scratch80, 31:29); + s(EmcPmacroCaTxDrv, 5:0, scratch81, 5:0); + s(EmcPmacroCaTxDrv, 13:8, scratch81, 11:6); + s(EmcPmacroCaTxDrv, 21:16, scratch81, 17:12); + s(EmcPmacroCaTxDrv, 29:24, scratch81, 23:18); + s(EmcObdly, 5:0, scratch81, 29:24); + s(EmcObdly, 29:28, scratch81, 31:30); + s(EmcZcalInterval, 23:10, scratch82, 13:0); + s(EmcZcalInterval, 9:0, scratch82, 23:14); + s(EmcPmacroCmdRxTermMode, 1:0, scratch82, 25:24); + s(EmcPmacroCmdRxTermMode, 5:4, scratch82, 27:26); + s(EmcPmacroCmdRxTermMode, 9:8, scratch82, 29:28); + s(EmcPmacroCmdRxTermMode, 13:12, scratch82, 31:30); + s(EmcDataBrlshft0, 23:0, scratch83, 23:0); + s(EmcPmacroDataRxTermMode, 1:0, scratch83, 25:24); + s(EmcPmacroDataRxTermMode, 5:4, scratch83, 27:26); + s(EmcPmacroDataRxTermMode, 9:8, scratch83, 29:28); + s(EmcPmacroDataRxTermMode, 13:12, scratch83, 31:30); + s(EmcDataBrlshft1, 23:0, scratch84, 23:0); + s(McEmemArbTimingRc, 7:0, scratch84, 31:24); + s(EmcDqsBrlshft0, 23:0, scratch85, 23:0); + s(McEmemArbRsv, 7:0, scratch85, 31:24); + s(EmcDqsBrlshft1, 23:0, scratch86, 23:0); + s(EmcCfgPipe2, 11:0, scratch87, 11:0); + s(EmcCfgPipe2, 27:16, scratch87, 23:12); + s(EmcCfgPipe1, 11:0, scratch88, 11:0); + s(EmcCfgPipe1, 27:16, scratch88, 23:12); + s(EmcPmacroCmdCtrl0, 5:0, scratch89, 5:0); + s(EmcPmacroCmdCtrl0, 13:8, scratch89, 11:6); + s(EmcPmacroCmdCtrl0, 21:16, scratch89, 17:12); + s(EmcPmacroCmdCtrl0, 29:24, scratch89, 23:18); + s(EmcPmacroCmdCtrl1, 5:0, scratch90, 5:0); + s(EmcPmacroCmdCtrl1, 13:8, scratch90, 11:6); + s(EmcPmacroCmdCtrl1, 21:16, scratch90, 17:12); + s(EmcPmacroCmdCtrl1, 29:24, scratch90, 23:18); + s(EmcRas, 6:0, scratch90, 30:24); + s(EmcCfg, 8:8, scratch90, 31:31); + s(EmcPmacroVttgenCtrl2, 23:0, scratch91, 23:0); + s(EmcW2p, 6:0, scratch91, 30:24); + s(EmcCfg, 9:9, scratch91, 31:31); + s(EmcPmacroCmdPadRxCtrl, 2:0, scratch92, 2:0); + s(EmcPmacroCmdPadRxCtrl, 5:4, scratch92, 4:3); + s(EmcPmacroCmdPadRxCtrl, 10:8, scratch92, 7:5); + s(EmcPmacroCmdPadRxCtrl, 22:12, scratch92, 18:8); + s(EmcPmacroCmdPadRxCtrl, 28:24, scratch92, 23:19); + s(EmcQSafe, 6:0, scratch92, 30:24); + s(EmcCfg, 18:18, scratch92, 31:31); + s(EmcPmacroDataPadRxCtrl, 2:0, scratch93, 2:0); + s(EmcPmacroDataPadRxCtrl, 5:4, scratch93, 4:3); + s(EmcPmacroDataPadRxCtrl, 10:8, scratch93, 7:5); + s(EmcPmacroDataPadRxCtrl, 22:12, scratch93, 18:8); + s(EmcPmacroDataPadRxCtrl, 28:24, scratch93, 23:19); + s(EmcRdv, 6:0, scratch93, 30:24); + s(EmcCfg, 21:21, scratch93, 31:31); + s(McEmemArbDaCovers, 23:0, scratch94, 23:0); + s(EmcRw2Pden, 6:0, scratch94, 30:24); + s(EmcCfg, 22:22, scratch94, 31:31); + s(EmcPmacroCmdCtrl2, 5:0, scratch95, 5:0); + s(EmcPmacroCmdCtrl2, 13:9, scratch95, 10:6); + s(EmcPmacroCmdCtrl2, 21:16, scratch95, 16:11); + s(EmcPmacroCmdCtrl2, 29:24, scratch95, 22:17); + s(EmcRfcPb, 8:0, scratch95, 31:23); + s(EmcPmacroQuseDdllRank0_0, 10:0, scratch96, 10:0); + s(EmcPmacroQuseDdllRank0_0, 26:16, scratch96, 21:11); + s(EmcCfgUpdate, 2:0, scratch96, 24:22); + s(EmcCfgUpdate, 10:8, scratch96, 27:25); + s(EmcCfgUpdate, 31:28, scratch96, 31:28); + s(EmcPmacroQuseDdllRank0_1, 10:0, scratch97, 10:0); + s(EmcPmacroQuseDdllRank0_1, 26:16, scratch97, 21:11); + s(EmcRfc, 9:0, scratch97, 31:22); + s(EmcPmacroQuseDdllRank0_2, 10:0, scratch98, 10:0); + s(EmcPmacroQuseDdllRank0_2, 26:16, scratch98, 21:11); + s(EmcTxsr, 9:0, scratch98, 31:22); + s(EmcPmacroQuseDdllRank0_3, 10:0, scratch99, 10:0); + s(EmcPmacroQuseDdllRank0_3, 26:16, scratch99, 21:11); + s(EmcMc2EmcQ, 2:0, scratch99, 24:22); + s(EmcMc2EmcQ, 10:8, scratch99, 27:25); + s(EmcMc2EmcQ, 27:24, scratch99, 31:28); + s(EmcPmacroQuseDdllRank0_4, 10:0, scratch100, 10:0); + s(EmcPmacroQuseDdllRank0_4, 26:16, scratch100, 21:11); + s(McEmemArbRing1Throttle, 4:0, scratch100, 26:22); + s(McEmemArbRing1Throttle, 20:16, scratch100, 31:27); + s(EmcPmacroQuseDdllRank0_5, 10:0, scratch101, 10:0); + s(EmcPmacroQuseDdllRank0_5, 26:16, scratch101, 21:11); + s(EmcPmacroQuseDdllRank1_0, 10:0, scratch102, 10:0); + s(EmcPmacroQuseDdllRank1_0, 26:16, scratch102, 21:11); + s(EmcAr2Pden, 8:0, scratch102, 30:22); + s(EmcCfg, 23:23, scratch102, 31:31); + s(EmcPmacroQuseDdllRank1_1, 10:0, scratch103, 10:0); + s(EmcPmacroQuseDdllRank1_1, 26:16, scratch103, 21:11); + s(EmcRfcSlr, 8:0, scratch103, 30:22); + s(EmcCfg, 24:24, scratch103, 31:31); + s(EmcPmacroQuseDdllRank1_2, 10:0, scratch104, 10:0); + s(EmcPmacroQuseDdllRank1_2, 26:16, scratch104, 21:11); + s(EmcIbdly, 6:0, scratch104, 28:22); + s(EmcIbdly, 29:28, scratch104, 30:29); + s(EmcCfg, 25:25, scratch104, 31:31); + s(EmcPmacroQuseDdllRank1_3, 10:0, scratch105, 10:0); + s(EmcPmacroQuseDdllRank1_3, 26:16, scratch105, 21:11); + s(McEmemArbTimingRFCPB, 8:0, scratch105, 30:22); + s(EmcCfg, 26:26, scratch105, 31:31); + s(EmcPmacroQuseDdllRank1_4, 10:0, scratch106, 10:0); + s(EmcPmacroQuseDdllRank1_4, 26:16, scratch106, 21:11); + s(EmcTfaw, 6:0, scratch106, 28:22); + s(EmcPmacroDataPadTxCtrl, 3:2, scratch106, 30:29); + s(EmcCfg, 28:28, scratch106, 31:31); + s(EmcPmacroQuseDdllRank1_5, 10:0, scratch107, 10:0); + s(EmcPmacroQuseDdllRank1_5, 26:16, scratch107, 21:11); + s(EmcTClkStable, 6:0, scratch107, 28:22); + s(EmcPmacroDataPadTxCtrl, 7:6, scratch107, 30:29); + s(EmcCfg, 29:29, scratch107, 31:31); + s(EmcPmacroObDdllLongDqRank0_0, 10:0, scratch108, 10:0); + s(EmcPmacroObDdllLongDqRank0_0, 26:16, scratch108, 21:11); + s(EmcPdex2Mrr, 6:0, scratch108, 28:22); + s(EmcPmacroDataPadTxCtrl, 11:10, scratch108, 30:29); + s(EmcCfg, 30:30, scratch108, 31:31); + s(EmcPmacroObDdllLongDqRank0_1, 10:0, scratch109, 10:0); + s(EmcPmacroObDdllLongDqRank0_1, 26:16, scratch109, 21:11); + s(EmcRdvMask, 6:0, scratch109, 28:22); + s(EmcPmacroDataPadTxCtrl, 15:14, scratch109, 30:29); + s(EmcCfg, 31:31, scratch109, 31:31); + s(EmcPmacroObDdllLongDqRank0_2, 10:0, scratch110, 10:0); + s(EmcPmacroObDdllLongDqRank0_2, 26:16, scratch110, 21:11); + s(EmcRdvEarlyMask, 6:0, scratch110, 28:22); + s(EmcFbioCfg5, 4:4, scratch110, 29:29); + s(EmcFbioCfg5, 8:8, scratch110, 30:30); + s(EmcFbioCfg5, 10:10, scratch110, 31:31); + s(EmcPmacroObDdllLongDqRank0_3, 10:0, scratch111, 10:0); + s(EmcPmacroObDdllLongDqRank0_3, 26:16, scratch111, 21:11); + s(EmcRdvEarly, 6:0, scratch111, 28:22); + s(EmcFbioCfg5, 12:12, scratch111, 29:29); + s(EmcFbioCfg5, 25:24, scratch111, 31:30); + s(EmcPmacroObDdllLongDqRank0_4, 10:0, scratch112, 10:0); + s(EmcPmacroObDdllLongDqRank0_4, 26:16, scratch112, 21:11); + s(EmcPmacroDdllShortCmd_2, 6:0, scratch112, 28:22); + s(EmcFbioCfg5, 28:26, scratch112, 31:29); + s(EmcPmacroObDdllLongDqRank0_5, 10:0, scratch113, 10:0); + s(EmcPmacroObDdllLongDqRank0_5, 26:16, scratch113, 21:11); + s(McEmemArbTimingRp, 6:0, scratch113, 28:22); + s(EmcFbioCfg5, 31:30, scratch113, 30:29); + s(EmcCfg2, 0:0, scratch113, 31:31); + s(EmcPmacroObDdllLongDqRank1_0, 10:0, scratch114, 10:0); + s(EmcPmacroObDdllLongDqRank1_0, 26:16, scratch114, 21:11); + s(McEmemArbTimingRas, 6:0, scratch114, 28:22); + s(EmcCfg2, 2:1, scratch114, 30:29); + s(EmcCfg2, 7:7, scratch114, 31:31); + s(EmcPmacroObDdllLongDqRank1_1, 10:0, scratch115, 10:0); + s(EmcPmacroObDdllLongDqRank1_1, 26:16, scratch115, 21:11); + s(McEmemArbTimingFaw, 6:0, scratch115, 28:22); + s(EmcCfg2, 11:10, scratch115, 30:29); + s(EmcCfg2, 14:14, scratch115, 31:31); + s(EmcPmacroObDdllLongDqRank1_2, 10:0, scratch123, 10:0); + s(EmcPmacroObDdllLongDqRank1_2, 26:16, scratch123, 21:11); + s(McEmemArbTimingRap2Pre, 6:0, scratch123, 28:22); + s(EmcCfg2, 16:15, scratch123, 30:29); + s(EmcCfg2, 20:20, scratch123, 31:31); + s(EmcPmacroObDdllLongDqRank1_3, 10:0, scratch124, 10:0); + s(EmcPmacroObDdllLongDqRank1_3, 26:16, scratch124, 21:11); + s(McEmemArbTimingWap2Pre, 6:0, scratch124, 28:22); + s(EmcCfg2, 24:22, scratch124, 31:29); + s(EmcPmacroObDdllLongDqRank1_4, 10:0, scratch125, 10:0); + s(EmcPmacroObDdllLongDqRank1_4, 26:16, scratch125, 21:11); + s(McEmemArbTimingR2W, 6:0, scratch125, 28:22); + s(EmcCfg2, 25:25, scratch125, 29:29); + s(EmcCfg2, 29:28, scratch125, 31:30); + s(EmcPmacroObDdllLongDqRank1_5, 10:0, scratch126, 10:0); + s(EmcPmacroObDdllLongDqRank1_5, 26:16, scratch126, 21:11); + s(McEmemArbTimingW2R, 6:0, scratch126, 28:22); + s(EmcCfg2, 31:30, scratch126, 30:29); + s(EmcCfgPipe, 0:0, scratch126, 31:31); + s(EmcPmacroObDdllLongDqsRank0_0, 10:0, scratch127, 10:0); + s(EmcPmacroObDdllLongDqsRank0_0, 26:16, scratch127, 21:11); + s(EmcRp, 5:0, scratch127, 27:22); + s(EmcCfgPipe, 4:1, scratch127, 31:28); + s(EmcPmacroObDdllLongDqsRank0_1, 10:0, scratch128, 10:0); + s(EmcPmacroObDdllLongDqsRank0_1, 26:16, scratch128, 21:11); + s(EmcR2w, 5:0, scratch128, 27:22); + s(EmcCfgPipe, 8:5, scratch128, 31:28); + s(EmcPmacroObDdllLongDqsRank0_2, 10:0, scratch129, 10:0); + s(EmcPmacroObDdllLongDqsRank0_2, 26:16, scratch129, 21:11); + s(EmcW2r, 5:0, scratch129, 27:22); + s(EmcCfgPipe, 11:9, scratch129, 30:28); + s(EmcCfgPipe, 16:16, scratch129, 31:31); + s(EmcPmacroObDdllLongDqsRank0_3, 10:0, scratch130, 10:0); + s(EmcPmacroObDdllLongDqsRank0_3, 26:16, scratch130, 21:11); + s(EmcR2p, 5:0, scratch130, 27:22); + s(EmcCfgPipe, 20:17, scratch130, 31:28); + s(EmcPmacroObDdllLongDqsRank0_4, 10:0, scratch131, 10:0); + s(EmcPmacroObDdllLongDqsRank0_4, 26:16, scratch131, 21:11); + s(EmcCcdmw, 5:0, scratch131, 27:22); + s(EmcCfgPipe, 24:21, scratch131, 31:28); + s(EmcPmacroObDdllLongDqsRank0_5, 10:0, scratch132, 10:0); + s(EmcPmacroObDdllLongDqsRank0_5, 26:16, scratch132, 21:11); + s(EmcRdRcd, 5:0, scratch132, 27:22); + s(EmcCfgPipe, 27:25, scratch132, 30:28); + s(EmcPmacroTxPwrd0, 0:0, scratch132, 31:31); + s(EmcPmacroObDdllLongDqsRank1_0, 10:0, scratch133, 10:0); + s(EmcPmacroObDdllLongDqsRank1_0, 26:16, scratch133, 21:11); + s(EmcWrRcd, 5:0, scratch133, 27:22); + s(EmcPmacroTxPwrd0, 4:1, scratch133, 31:28); + s(EmcPmacroObDdllLongDqsRank1_1, 10:0, scratch134, 10:0); + s(EmcPmacroObDdllLongDqsRank1_1, 26:16, scratch134, 21:11); + s(EmcWdv, 5:0, scratch134, 27:22); + s(EmcPmacroTxPwrd0, 8:5, scratch134, 31:28); + s(EmcPmacroObDdllLongDqsRank1_2, 10:0, scratch135, 10:0); + s(EmcPmacroObDdllLongDqsRank1_2, 26:16, scratch135, 21:11); + s(EmcQUse, 5:0, scratch135, 27:22); + s(EmcPmacroTxPwrd0, 12:9, scratch135, 31:28); + s(EmcPmacroObDdllLongDqsRank1_3, 10:0, scratch136, 10:0); + s(EmcPmacroObDdllLongDqsRank1_3, 26:16, scratch136, 21:11); + s(EmcPdEx2Wr, 5:0, scratch136, 27:22); + s(EmcPmacroTxPwrd0, 13:13, scratch136, 28:28); + s(EmcPmacroTxPwrd0, 18:16, scratch136, 31:29); + s(EmcPmacroObDdllLongDqsRank1_4, 10:0, scratch137, 10:0); + s(EmcPmacroObDdllLongDqsRank1_4, 26:16, scratch137, 21:11); + s(EmcPdEx2Rd, 5:0, scratch137, 27:22); + s(EmcPmacroTxPwrd0, 22:19, scratch137, 31:28); + s(EmcPmacroObDdllLongDqsRank1_5, 10:0, scratch138, 10:0); + s(EmcPmacroObDdllLongDqsRank1_5, 26:16, scratch138, 21:11); + s(EmcPdex2Cke, 5:0, scratch138, 27:22); + s(EmcPmacroTxPwrd0, 26:23, scratch138, 31:28); + s(EmcPmacroIbDdllLongDqsRank0_0, 10:0, scratch139, 10:0); + s(EmcPmacroIbDdllLongDqsRank0_0, 26:16, scratch139, 21:11); + s(EmcPChg2Pden, 5:0, scratch139, 27:22); + s(EmcPmacroTxPwrd0, 29:27, scratch139, 30:28); + s(EmcPmacroTxPwrd1, 0:0, scratch139, 31:31); + s(EmcPmacroIbDdllLongDqsRank0_1, 10:0, scratch140, 10:0); + s(EmcPmacroIbDdllLongDqsRank0_1, 26:16, scratch140, 21:11); + s(EmcAct2Pden, 5:0, scratch140, 27:22); + s(EmcPmacroTxPwrd1, 4:1, scratch140, 31:28); + s(EmcPmacroIbDdllLongDqsRank0_2, 10:0, scratch141, 10:0); + s(EmcPmacroIbDdllLongDqsRank0_2, 26:16, scratch141, 21:11); + s(EmcCke2Pden, 5:0, scratch141, 27:22); + s(EmcPmacroTxPwrd1, 8:5, scratch141, 31:28); + s(EmcPmacroIbDdllLongDqsRank0_3, 10:0, scratch142, 10:0); + s(EmcPmacroIbDdllLongDqsRank0_3, 26:16, scratch142, 21:11); + s(EmcTcke, 5:0, scratch142, 27:22); + s(EmcPmacroTxPwrd1, 12:9, scratch142, 31:28); + s(EmcPmacroIbDdllLongDqsRank1_0, 10:0, scratch143, 10:0); + s(EmcPmacroIbDdllLongDqsRank1_0, 26:16, scratch143, 21:11); + s(EmcTrpab, 5:0, scratch143, 27:22); + s(EmcPmacroTxPwrd1, 13:13, scratch143, 28:28); + s(EmcPmacroTxPwrd1, 18:16, scratch143, 31:29); + s(EmcPmacroIbDdllLongDqsRank1_1, 10:0, scratch144, 10:0); + s(EmcPmacroIbDdllLongDqsRank1_1, 26:16, scratch144, 21:11); + s(EmcClkenOverride, 3:1, scratch144, 24:22); + s(EmcClkenOverride, 8:6, scratch144, 27:25); + s(EmcPmacroTxPwrd1, 22:19, scratch144, 31:28); + s(EmcPmacroIbDdllLongDqsRank1_2, 10:0, scratch145, 10:0); + s(EmcPmacroIbDdllLongDqsRank1_2, 26:16, scratch145, 21:11); + s(EmcEInput, 5:0, scratch145, 27:22); + s(EmcPmacroTxPwrd1, 26:23, scratch145, 31:28); + s(EmcPmacroIbDdllLongDqsRank1_3, 10:0, scratch146, 10:0); + s(EmcPmacroIbDdllLongDqsRank1_3, 26:16, scratch146, 21:11); + s(EmcEInputDuration, 5:0, scratch146, 27:22); + s(EmcPmacroTxPwrd1, 29:27, scratch146, 30:28); + s(EmcPmacroTxPwrd2, 0:0, scratch146, 31:31); + s(EmcPmacroDdllLongCmd_0, 10:0, scratch147, 10:0); + s(EmcPmacroDdllLongCmd_0, 26:16, scratch147, 21:11); + s(EmcPutermExtra, 5:0, scratch147, 27:22); + s(EmcPmacroTxPwrd2, 4:1, scratch147, 31:28); + s(EmcPmacroDdllLongCmd_1, 10:0, scratch148, 10:0); + s(EmcPmacroDdllLongCmd_1, 26:16, scratch148, 21:11); + s(EmcTckesr, 5:0, scratch148, 27:22); + s(EmcPmacroTxPwrd2, 8:5, scratch148, 31:28); + s(EmcPmacroDdllLongCmd_2, 10:0, scratch149, 10:0); + s(EmcPmacroDdllLongCmd_2, 26:16, scratch149, 21:11); + s(EmcTpd, 5:0, scratch149, 27:22); + s(EmcPmacroTxPwrd2, 12:9, scratch149, 31:28); + s(EmcPmacroDdllLongCmd_3, 10:0, scratch150, 10:0); + s(EmcPmacroDdllLongCmd_3, 26:16, scratch150, 21:11); + s(EmcWdvMask, 5:0, scratch150, 27:22); + s(EmcPmacroTxPwrd2, 13:13, scratch150, 28:28); + s(EmcPmacroTxPwrd2, 18:16, scratch150, 31:29); + s(McEmemArbCfg, 8:0, scratch151, 8:0); + s(McEmemArbCfg, 20:16, scratch151, 13:9); + s(McEmemArbCfg, 31:24, scratch151, 21:14); + s(EmcWdvChk, 5:0, scratch151, 27:22); + s(EmcPmacroTxPwrd2, 22:19, scratch151, 31:28); + s(McEmemArbMisc1, 12:0, scratch152, 12:0); + s(McEmemArbMisc1, 25:21, scratch152, 17:13); + s(McEmemArbMisc1, 31:28, scratch152, 21:18); + s(EmcCmdBrlshft0, 5:0, scratch152, 27:22); + s(EmcPmacroTxPwrd2, 26:23, scratch152, 31:28); + s(EmcMrsWaitCnt2, 9:0, scratch153, 9:0); + s(EmcMrsWaitCnt2, 26:16, scratch153, 20:10); + s(EmcPmacroIbRxrt, 10:0, scratch153, 31:21); + s(EmcMrsWaitCnt, 9:0, scratch154, 9:0); + s(EmcMrsWaitCnt, 26:16, scratch154, 20:10); + s(EmcPmacroDdllLongCmd_4, 10:0, scratch154, 31:21); + s(EmcAutoCalInterval, 20:0, scratch155, 20:0); + s(McEmemArbOutstandingReq, 8:0, scratch155, 29:21); + s(McEmemArbOutstandingReq, 31:30, scratch155, 31:30); + s(McEmemArbRefpbHpCtrl, 6:0, scratch156, 6:0); + s(McEmemArbRefpbHpCtrl, 14:8, scratch156, 13:7); + s(McEmemArbRefpbHpCtrl, 22:16, scratch156, 20:14); + s(EmcCmdBrlshft1, 5:0, scratch156, 26:21); + s(EmcRrd, 4:0, scratch156, 31:27); + s(EmcQuseBrlshft0, 19:0, scratch157, 19:0); + s(EmcFbioCfg8, 27:16, scratch157, 31:20); + s(EmcQuseBrlshft1, 19:0, scratch158, 19:0); + s(EmcTxsrDll, 11:0, scratch158, 31:20); + s(EmcQuseBrlshft2, 19:0, scratch159, 19:0); + s(EmcTxdsrvttgen, 11:0, scratch159, 31:20); + s(EmcQuseBrlshft3, 19:0, scratch160, 19:0); + s(EmcPmacroVttgenCtrl0, 3:0, scratch160, 23:20); + s(EmcPmacroVttgenCtrl0, 11:8, scratch160, 27:24); + s(EmcPmacroVttgenCtrl0, 19:16, scratch160, 31:28); + s(EmcPmacroVttgenCtrl1, 19:0, scratch161, 19:0); + s(EmcCmdBrlshft2, 5:0, scratch161, 25:20); + s(EmcCmdBrlshft3, 5:0, scratch161, 31:26); + s(EmcAutoCalConfig3, 5:0, scratch162, 5:0); + s(EmcAutoCalConfig3, 13:8, scratch162, 11:6); + s(EmcAutoCalConfig3, 18:16, scratch162, 14:12); + s(EmcAutoCalConfig3, 22:20, scratch162, 17:15); + s(EmcTRefBw, 13:0, scratch162, 31:18); + s(EmcAutoCalConfig4, 5:0, scratch163, 5:0); + s(EmcAutoCalConfig4, 13:8, scratch163, 11:6); + s(EmcAutoCalConfig4, 18:16, scratch163, 14:12); + s(EmcAutoCalConfig4, 22:20, scratch163, 17:15); + s(EmcQpop, 6:0, scratch163, 24:18); + s(EmcQpop, 22:16, scratch163, 31:25); + s(EmcAutoCalConfig5, 5:0, scratch164, 5:0); + s(EmcAutoCalConfig5, 13:8, scratch164, 11:6); + s(EmcAutoCalConfig5, 18:16, scratch164, 14:12); + s(EmcAutoCalConfig5, 22:20, scratch164, 17:15); + s(EmcPmacroAutocalCfgCommon, 5:0, scratch164, 23:18); + s(EmcPmacroAutocalCfgCommon, 13:8, scratch164, 29:24); + s(EmcPmacroAutocalCfgCommon, 16:16, scratch164, 30:30); + s(EmcPmacroTxPwrd2, 27:27, scratch164, 31:31); + s(EmcAutoCalConfig6, 5:0, scratch165, 5:0); + s(EmcAutoCalConfig6, 13:8, scratch165, 11:6); + s(EmcAutoCalConfig6, 18:16, scratch165, 14:12); + s(EmcAutoCalConfig6, 22:20, scratch165, 17:15); + s(EmcWev, 5:0, scratch165, 23:18); + s(EmcWsv, 5:0, scratch165, 29:24); + s(EmcPmacroTxPwrd2, 29:28, scratch165, 31:30); + s(EmcAutoCalConfig7, 5:0, scratch166, 5:0); + s(EmcAutoCalConfig7, 13:8, scratch166, 11:6); + s(EmcAutoCalConfig7, 18:16, scratch166, 14:12); + s(EmcAutoCalConfig7, 22:20, scratch166, 17:15); + s(EmcCfg3, 2:0, scratch166, 20:18); + s(EmcCfg3, 6:4, scratch166, 23:21); + s(EmcQuseWidth, 3:0, scratch166, 27:24); + s(EmcQuseWidth, 29:28, scratch166, 29:28); + s(EmcPmacroTxPwrd3, 1:0, scratch166, 31:30); + s(EmcAutoCalConfig8, 5:0, scratch167, 5:0); + s(EmcAutoCalConfig8, 13:8, scratch167, 11:6); + s(EmcAutoCalConfig8, 18:16, scratch167, 14:12); + s(EmcAutoCalConfig8, 22:20, scratch167, 17:15); + s(EmcPmacroBgBiasCtrl0, 2:0, scratch167, 20:18); + s(EmcPmacroBgBiasCtrl0, 6:4, scratch167, 23:21); + s(McEmemArbTimingRcd, 5:0, scratch167, 29:24); + s(EmcPmacroTxPwrd3, 3:2, scratch167, 31:30); + s(EmcXm2CompPadCtrl2, 17:0, scratch168, 17:0); + s(McEmemArbTimingCcdmw, 5:0, scratch168, 23:18); + s(McEmemArbOverride, 27:27, scratch168, 24:24); + s(McEmemArbOverride, 26:26, scratch168, 25:25); + s(McEmemArbOverride, 16:16, scratch168, 26:26); + s(McEmemArbOverride, 10:10, scratch168, 27:27); + s(McEmemArbOverride, 4:4, scratch168, 28:28); + s(McEmemArbOverride, 3:3, scratch168, 29:29); + s(EmcPmacroTxPwrd3, 5:4, scratch168, 31:30); + s(EmcXm2CompPadCtrl3, 17:0, scratch169, 17:0); + s(EmcRext, 4:0, scratch169, 22:18); + s(EmcTClkStop, 4:0, scratch169, 27:23); + s(EmcPmacroTxPwrd3, 9:6, scratch169, 31:28); + s(EmcZcalWaitCnt, 10:0, scratch170, 10:0); + s(EmcZcalWaitCnt, 21:16, scratch170, 16:11); + s(EmcZcalWaitCnt, 31:31, scratch170, 17:17); + s(EmcWext, 4:0, scratch170, 22:18); + s(EmcRefctrl2, 0:0, scratch170, 23:23); + s(EmcRefctrl2, 26:24, scratch170, 26:24); + s(EmcRefctrl2, 31:31, scratch170, 27:27); + s(EmcPmacroTxPwrd3, 13:10, scratch170, 31:28); + s(EmcZcalMrwCmd, 7:0, scratch171, 7:0); + s(EmcZcalMrwCmd, 23:16, scratch171, 15:8); + s(EmcZcalMrwCmd, 31:30, scratch171, 17:16); + s(EmcWeDuration, 4:0, scratch171, 22:18); + s(EmcWsDuration, 4:0, scratch171, 27:23); + s(EmcPmacroTxPwrd3, 19:16, scratch171, 31:28); + s(EmcSwizzleRank0Byte0, 2:0, scratch172, 2:0); + s(EmcSwizzleRank0Byte0, 6:4, scratch172, 5:3); + s(EmcSwizzleRank0Byte0, 10:8, scratch172, 8:6); + s(EmcSwizzleRank0Byte0, 14:12, scratch172, 11:9); + s(EmcSwizzleRank0Byte0, 18:16, scratch172, 14:12); + s(EmcSwizzleRank0Byte0, 22:20, scratch172, 17:15); + s(EmcPutermWidth, 31:31, scratch172, 18:18); + s(EmcPutermWidth, 3:0, scratch172, 22:19); + s(McEmemArbTimingRrd, 4:0, scratch172, 27:23); + s(EmcPmacroTxPwrd3, 23:20, scratch172, 31:28); + s(EmcSwizzleRank0Byte1, 2:0, scratch173, 2:0); + s(EmcSwizzleRank0Byte1, 6:4, scratch173, 5:3); + s(EmcSwizzleRank0Byte1, 10:8, scratch173, 8:6); + s(EmcSwizzleRank0Byte1, 14:12, scratch173, 11:9); + s(EmcSwizzleRank0Byte1, 18:16, scratch173, 14:12); + s(EmcSwizzleRank0Byte1, 22:20, scratch173, 17:15); + s(McEmemArbTimingR2R, 4:0, scratch173, 22:18); + s(McEmemArbTimingW2W, 4:0, scratch173, 27:23); + s(EmcPmacroTxPwrd3, 27:24, scratch173, 31:28); + s(EmcSwizzleRank0Byte2, 2:0, scratch174, 2:0); + s(EmcSwizzleRank0Byte2, 6:4, scratch174, 5:3); + s(EmcSwizzleRank0Byte2, 10:8, scratch174, 8:6); + s(EmcSwizzleRank0Byte2, 14:12, scratch174, 11:9); + s(EmcSwizzleRank0Byte2, 18:16, scratch174, 14:12); + s(EmcSwizzleRank0Byte2, 22:20, scratch174, 17:15); + s(EmcPmacroTxPwrd3, 29:28, scratch174, 19:18); + s(EmcPmacroTxSelClkSrc0, 11:0, scratch174, 31:20); + s(EmcSwizzleRank0Byte3, 2:0, scratch175, 2:0); + s(EmcSwizzleRank0Byte3, 6:4, scratch175, 5:3); + s(EmcSwizzleRank0Byte3, 10:8, scratch175, 8:6); + s(EmcSwizzleRank0Byte3, 14:12, scratch175, 11:9); + s(EmcSwizzleRank0Byte3, 18:16, scratch175, 14:12); + s(EmcSwizzleRank0Byte3, 22:20, scratch175, 17:15); + s(EmcPmacroTxSelClkSrc0, 27:16, scratch175, 29:18); + s(EmcPmacroTxSelClkSrc1, 1:0, scratch175, 31:30); + s(EmcSwizzleRank1Byte0, 2:0, scratch176, 2:0); + s(EmcSwizzleRank1Byte0, 6:4, scratch176, 5:3); + s(EmcSwizzleRank1Byte0, 10:8, scratch176, 8:6); + s(EmcSwizzleRank1Byte0, 14:12, scratch176, 11:9); + s(EmcSwizzleRank1Byte0, 18:16, scratch176, 14:12); + s(EmcSwizzleRank1Byte0, 22:20, scratch176, 17:15); + s(EmcPmacroTxSelClkSrc1, 11:2, scratch176, 27:18); + s(EmcPmacroTxSelClkSrc1, 19:16, scratch176, 31:28); + s(EmcSwizzleRank1Byte1, 2:0, scratch177, 2:0); + s(EmcSwizzleRank1Byte1, 6:4, scratch177, 5:3); + s(EmcSwizzleRank1Byte1, 10:8, scratch177, 8:6); + s(EmcSwizzleRank1Byte1, 14:12, scratch177, 11:9); + s(EmcSwizzleRank1Byte1, 18:16, scratch177, 14:12); + s(EmcSwizzleRank1Byte1, 22:20, scratch177, 17:15); + s(EmcPmacroTxSelClkSrc1, 27:20, scratch177, 25:18); + s(EmcPmacroTxSelClkSrc3, 5:0, scratch177, 31:26); + s(EmcSwizzleRank1Byte2, 2:0, scratch178, 2:0); + s(EmcSwizzleRank1Byte2, 6:4, scratch178, 5:3); + s(EmcSwizzleRank1Byte2, 10:8, scratch178, 8:6); + s(EmcSwizzleRank1Byte2, 14:12, scratch178, 11:9); + s(EmcSwizzleRank1Byte2, 18:16, scratch178, 14:12); + s(EmcSwizzleRank1Byte2, 22:20, scratch178, 17:15); + s(EmcPmacroTxSelClkSrc3, 11:6, scratch178, 23:18); + s(EmcPmacroTxSelClkSrc3, 23:16, scratch178, 31:24); + s(EmcSwizzleRank1Byte3, 2:0, scratch179, 2:0); + s(EmcSwizzleRank1Byte3, 6:4, scratch179, 5:3); + s(EmcSwizzleRank1Byte3, 10:8, scratch179, 8:6); + s(EmcSwizzleRank1Byte3, 14:12, scratch179, 11:9); + s(EmcSwizzleRank1Byte3, 18:16, scratch179, 14:12); + s(EmcSwizzleRank1Byte3, 22:20, scratch179, 17:15); + s(EmcPmacroTxSelClkSrc3, 27:24, scratch179, 21:18); + s(EmcPmacroTxSelClkSrc2, 9:0, scratch179, 31:22); + s(EmcPmacroCmdBrickCtrlFdpd, 17:0, scratch180, 17:0); + s(EmcPmacroTxSelClkSrc2, 11:10, scratch180, 19:18); + s(EmcPmacroTxSelClkSrc2, 27:16, scratch180, 31:20); + s(EmcPmacroDataBrickCtrlFdpd, 17:0, scratch181, 17:0); + s(EmcPmacroTxSelClkSrc4, 11:0, scratch181, 29:18); + s(EmcPmacroTxSelClkSrc4, 17:16, scratch181, 31:30); + s(EmcFbioCfg7, 16:0, scratch182, 16:0); + s(McEmemArbRefpbBankCtrl, 6:0, scratch182, 23:17); + s(McEmemArbRefpbBankCtrl, 14:8, scratch182, 30:24); + s(McEmemArbRefpbBankCtrl, 31:31, scratch182, 31:31); + s(EmcDynSelfRefControl, 15:0, scratch183, 15:0); + s(EmcDynSelfRefControl, 31:31, scratch183, 16:16); + s(EmcPmacroTxSelClkSrc4, 27:18, scratch183, 26:17); + s(EmcPmacroTxSelClkSrc5, 4:0, scratch183, 31:27); + s(EmcDllCfg1, 16:0, scratch184, 16:0); + s(EmcPmacroTxSelClkSrc5, 11:5, scratch184, 23:17); + s(EmcPmacroTxSelClkSrc5, 23:16, scratch184, 31:24); + s(EmcPmacroPadCfgCtrl, 1:0, scratch185, 1:0); + s(EmcPmacroPadCfgCtrl, 6:5, scratch185, 3:2); + s(EmcPmacroPadCfgCtrl, 11:9, scratch185, 6:4); + s(EmcPmacroPadCfgCtrl, 13:13, scratch185, 7:7); + s(EmcPmacroPadCfgCtrl, 17:16, scratch185, 9:8); + s(EmcPmacroPadCfgCtrl, 21:20, scratch185, 11:10); + s(EmcPmacroPadCfgCtrl, 25:24, scratch185, 13:12); + s(EmcPmacroPadCfgCtrl, 30:28, scratch185, 16:14); + s(EmcPmacroTxSelClkSrc5, 27:24, scratch185, 20:17); + s(EmcPmacroCmdPadTxCtrl, 1:0, scratch185, 22:21); + s(EmcPmacroCmdPadTxCtrl, 5:4, scratch185, 24:23); + s(EmcPmacroCmdPadTxCtrl, 9:8, scratch185, 26:25); + s(EmcPmacroCmdPadTxCtrl, 13:12, scratch185, 28:27); + s(EmcPmacroCmdPadTxCtrl, 16:16, scratch185, 29:29); + s(EmcPmacroCmdPadTxCtrl, 21:20, scratch185, 31:30); + s(EmcRefresh, 15:0, scratch186, 15:0); + s(EmcCmdQ, 4:0, scratch186, 20:16); + s(EmcCmdQ, 10:8, scratch186, 23:21); + s(EmcCmdQ, 14:12, scratch186, 26:24); + s(EmcCmdQ, 28:24, scratch186, 31:27); + s(EmcAcpdControl, 15:0, scratch187, 15:0); + s(EmcAutoCalVrefSel1, 15:0, scratch187, 31:16); + s(EmcXm2CompPadCtrl, 1:0, scratch188, 1:0); + s(EmcXm2CompPadCtrl, 6:3, scratch188, 5:2); + s(EmcXm2CompPadCtrl, 9:9, scratch188, 6:6); + s(EmcXm2CompPadCtrl, 19:11, scratch188, 15:7); + s(EmcCfgDigDllPeriod, 15:0, scratch188, 31:16); + s(EmcCfgDigDll_1, 15:0, scratch189, 15:0); + s(EmcPreRefreshReqCnt, 15:0, scratch189, 31:16); + s(EmcPmacroCmdPadTxCtrl, 27:24, scratch190, 19:16); + s(EmcPmacroDataPadTxCtrl, 1:0, scratch190, 21:20); + s(EmcPmacroDataPadTxCtrl, 5:4, scratch190, 23:22); + s(EmcPmacroDataPadTxCtrl, 9:8, scratch190, 25:24); + s(EmcPmacroDataPadTxCtrl, 13:12, scratch190, 27:26); + s(EmcPmacroDataPadTxCtrl, 16:16, scratch190, 28:28); + s(EmcPmacroDataPadTxCtrl, 21:20, scratch190, 30:29); + s(EmcPmacroDataPadTxCtrl, 24:24, scratch190, 31:31); + s(EmcPmacroDataPadTxCtrl, 27:25, scratch191, 2:0); + + s(EmcPinGpio, 1:0, scratch8, 31:30); + s(EmcPinGpioEn, 1:0, scratch9, 31:30); + s(EmcDevSelect, 1:0, scratch10, 31:30); + s(EmcZcalWarmColdBootEnables, 1:0, scratch11, 31:30); + s(EmcCfgDigDllPeriodWarmBoot, 1:0, scratch12, 31:30); + s32(EmcBctSpare13, scratch31); + s32(EmcBctSpare12, scratch32); + s32(EmcBctSpare7, scratch33); + s32(EmcBctSpare6, scratch40); + s32(EmcBctSpare5, scratch42); + s32(EmcBctSpare4, scratch44); + s32(EmcBctSpare3, scratch45); + s32(EmcBctSpare2, scratch46); + s32(EmcBctSpare1, scratch47); + s32(EmcBctSpare0, scratch48); + s32(EmcBctSpare9, scratch50); + s32(EmcBctSpare8, scratch51); + s32(BootRomPatchData, scratch56); + s32(BootRomPatchControl, scratch57); + s(McClkenOverrideAllWarmBoot, 0:0, scratch58, 31:31); + s(EmcClkenOverrideAllWarmBoot, 0:0, scratch59, 30:30); + s(EmcMrsWarmBootEnable, 0:0, scratch59, 31:31); + s(ClearClk2Mc1, 0:0, scratch60, 30:30); + s(EmcWarmBootExtraModeRegWriteEnable, 0:0, scratch60, 31:31); + s(ClkRstControllerPllmMisc2OverrideEnable, 0:0, scratch61, 30:30); + s(EmcDbgWriteMux, 0:0, scratch61, 31:31); + s(EmcExtraRefreshNum, 2:0, scratch62, 31:29); + s(PmcIoDpd3ReqWait, 2:0, scratch68, 30:28); + s(AhbArbitrationXbarCtrlMemInitDone, 0:0, scratch68, 31:31); + s(MemoryType, 2:0, scratch69, 30:28); + s(PmcIoDpd4ReqWait, 2:0, scratch70, 30:28); + s(EmcTimingControlWait, 7:0, scratch86, 31:24); + s(EmcZcalWarmBootWait, 7:0, scratch87, 31:24); + s(WarmBootWait, 7:0, scratch88, 31:24); + s(EmcPinProgramWait, 7:0, scratch89, 31:24); + s(EmcAutoCalWait, 9:0, scratch101, 31:22); + s(SwizzleRankByteEncode, 15:0, scratch190, 15:0); + + switch (sdram->MemoryType) + { + case NvBootMemoryType_LpDdr2: + case NvBootMemoryType_LpDdr4: + s(EmcMrwLpddr2ZcalWarmBoot, 23:16, scratch5, 7:0); + s(EmcMrwLpddr2ZcalWarmBoot, 7:0, scratch5, 15:8); + s(EmcWarmBootMrwExtra, 23:16, scratch5, 23:16); + s(EmcWarmBootMrwExtra, 7:0, scratch5, 31:24); + s(EmcMrwLpddr2ZcalWarmBoot, 31:30, scratch6, 1:0); + s(EmcWarmBootMrwExtra, 31:30, scratch6, 3:2); + s(EmcMrwLpddr2ZcalWarmBoot, 27:26, scratch6, 5:4); + s(EmcWarmBootMrwExtra, 27:26, scratch6, 7:6); + s(EmcMrw6, 27:0, scratch8, 27:0); + s(EmcMrw6, 31:30, scratch8, 29:28); + s(EmcMrw8, 27:0, scratch9, 27:0); + s(EmcMrw8, 31:30, scratch9, 29:28); + s(EmcMrw9, 27:0, scratch10, 27:0); + s(EmcMrw9, 31:30, scratch10, 29:28); + s(EmcMrw10, 27:0, scratch11, 27:0); + s(EmcMrw10, 31:30, scratch11, 29:28); + s(EmcMrw12, 27:0, scratch12, 27:0); + s(EmcMrw12, 31:30, scratch12, 29:28); + s(EmcMrw13, 27:0, scratch13, 27:0); + s(EmcMrw13, 31:30, scratch13, 29:28); + s(EmcMrw14, 27:0, scratch14, 27:0); + s(EmcMrw14, 31:30, scratch14, 29:28); + s(EmcMrw1, 7:0, scratch15, 7:0); + s(EmcMrw1, 23:16, scratch15, 15:8); + s(EmcMrw1, 27:26, scratch15, 17:16); + s(EmcMrw1, 31:30, scratch15, 19:18); + s(EmcWarmBootMrwExtra, 7:0, scratch16, 7:0); + s(EmcWarmBootMrwExtra, 23:16, scratch16, 15:8); + s(EmcWarmBootMrwExtra, 27:26, scratch16, 17:16); + s(EmcWarmBootMrwExtra, 31:30, scratch16, 19:18); + s(EmcMrw2, 7:0, scratch17, 7:0); + s(EmcMrw2, 23:16, scratch17, 15:8); + s(EmcMrw2, 27:26, scratch17, 17:16); + s(EmcMrw2, 31:30, scratch17, 19:18); + s(EmcMrw3, 7:0, scratch18, 7:0); + s(EmcMrw3, 23:16, scratch18, 15:8); + s(EmcMrw3, 27:26, scratch18, 17:16); + s(EmcMrw3, 31:30, scratch18, 19:18); + s(EmcMrw4, 7:0, scratch19, 7:0); + s(EmcMrw4, 23:16, scratch19, 15:8); + s(EmcMrw4, 27:26, scratch19, 17:16); + s(EmcMrw4, 31:30, scratch19, 19:18); + break; + case NvBootMemoryType_Ddr3: + s(EmcMrs, 13:0, scratch5, 13:0); + s(EmcEmrs, 13:0, scratch5, 27:14); + s(EmcMrs, 21:20, scratch5, 29:28); + s(EmcMrs, 31:30, scratch5, 31:30); + s(EmcEmrs2, 13:0, scratch8, 13:0); + s(EmcEmrs3, 13:0, scratch8, 27:14); + s(EmcEmrs, 21:20, scratch8, 29:28); + s(EmcWarmBootMrsExtra, 13:0, scratch9, 13:0); + s(EmcEmrs, 31:30, scratch9, 15:14); + s(EmcEmrs2, 21:20, scratch9, 17:16); + s(EmcEmrs2, 31:30, scratch9, 19:18); + s(EmcEmrs3, 21:20, scratch9, 21:20); + s(EmcEmrs3, 31:30, scratch9, 23:22); + s(EmcWarmBootMrsExtra, 31:30, scratch9, 25:24); + s(EmcWarmBootMrsExtra, 21:20, scratch9, 27:26); + s(EmcZqCalDdr3WarmBoot, 31:30, scratch9, 29:28); + s(EmcMrs, 27:26, scratch10, 1:0); + s(EmcEmrs, 27:26, scratch10, 3:2); + s(EmcEmrs2, 27:26, scratch10, 5:4); + s(EmcEmrs3, 27:26, scratch10, 7:6); + s(EmcWarmBootMrsExtra, 27:27, scratch10, 8:8); + s(EmcWarmBootMrsExtra, 26:26, scratch10, 9:9); + s(EmcZqCalDdr3WarmBoot, 0:0, scratch10, 10:10); + s(EmcZqCalDdr3WarmBoot, 4:4, scratch10, 11:11); + break; + } + + s32(EmcCmdMappingByte, secure_scratch8); + s32(EmcPmacroBrickMapping0, secure_scratch9); + s32(EmcPmacroBrickMapping1, secure_scratch10); + s32(EmcPmacroBrickMapping2, secure_scratch11); + s32(McVideoProtectGpuOverride0, secure_scratch12); + s(EmcCmdMappingCmd0_0, 6:0, secure_scratch13, 6:0); + s(EmcCmdMappingCmd0_0, 14:8, secure_scratch13, 13:7); + s(EmcCmdMappingCmd0_0, 22:16, secure_scratch13, 20:14); + s(EmcCmdMappingCmd0_0, 30:24, secure_scratch13, 27:21); + s(McVideoProtectBomAdrHi, 1:0, secure_scratch13, 29:28); + s(McVideoProtectWriteAccess, 1:0, secure_scratch13, 31:30); + s(EmcCmdMappingCmd0_1, 6:0, secure_scratch14, 6:0); + s(EmcCmdMappingCmd0_1, 14:8, secure_scratch14, 13:7); + s(EmcCmdMappingCmd0_1, 22:16, secure_scratch14, 20:14); + s(EmcCmdMappingCmd0_1, 30:24, secure_scratch14, 27:21); + s(McSecCarveoutAdrHi, 1:0, secure_scratch14, 29:28); + s(McMtsCarveoutAdrHi, 1:0, secure_scratch14, 31:30); + s(EmcCmdMappingCmd1_0, 6:0, secure_scratch15, 6:0); + s(EmcCmdMappingCmd1_0, 14:8, secure_scratch15, 13:7); + s(EmcCmdMappingCmd1_0, 22:16, secure_scratch15, 20:14); + s(EmcCmdMappingCmd1_0, 30:24, secure_scratch15, 27:21); + s(McGeneralizedCarveout5BomHi, 1:0, secure_scratch15, 29:28); + s(McGeneralizedCarveout3BomHi, 1:0, secure_scratch15, 31:30); + s(EmcCmdMappingCmd1_1, 6:0, secure_scratch16, 6:0); + s(EmcCmdMappingCmd1_1, 14:8, secure_scratch16, 13:7); + s(EmcCmdMappingCmd1_1, 22:16, secure_scratch16, 20:14); + s(EmcCmdMappingCmd1_1, 30:24, secure_scratch16, 27:21); + s(McGeneralizedCarveout2BomHi, 1:0, secure_scratch16, 29:28); + s(McGeneralizedCarveout4BomHi, 1:0, secure_scratch16, 31:30); + s(EmcCmdMappingCmd2_0, 6:0, secure_scratch17, 6:0); + s(EmcCmdMappingCmd2_0, 14:8, secure_scratch17, 13:7); + s(EmcCmdMappingCmd2_0, 22:16, secure_scratch17, 20:14); + s(EmcCmdMappingCmd2_0, 30:24, secure_scratch17, 27:21); + s(McGeneralizedCarveout1BomHi, 1:0, secure_scratch17, 29:28); + s(EmcAdrCfg, 0:0, secure_scratch17, 30:30); + s(EmcFbioSpare, 1:1, secure_scratch17, 31:31); + s(EmcCmdMappingCmd2_1, 6:0, secure_scratch18, 6:0); + s(EmcCmdMappingCmd2_1, 14:8, secure_scratch18, 13:7); + s(EmcCmdMappingCmd2_1, 22:16, secure_scratch18, 20:14); + s(EmcCmdMappingCmd2_1, 30:24, secure_scratch18, 27:21); + s(EmcFbioCfg8, 15:15, secure_scratch18, 28:28); + s(McEmemAdrCfg, 0:0, secure_scratch18, 29:29); + s(McSecCarveoutProtectWriteAccess, 0:0, secure_scratch18, 30:30); + s(McMtsCarveoutRegCtrl, 0:0, secure_scratch18, 31:31); + s(EmcCmdMappingCmd3_0, 6:0, secure_scratch19, 6:0); + s(EmcCmdMappingCmd3_0, 14:8, secure_scratch19, 13:7); + s(EmcCmdMappingCmd3_0, 22:16, secure_scratch19, 20:14); + s(EmcCmdMappingCmd3_0, 30:24, secure_scratch19, 27:21); + s(McGeneralizedCarveout2Cfg0, 6:3, secure_scratch19, 31:28); + s(EmcCmdMappingCmd3_1, 6:0, secure_scratch20, 6:0); + s(EmcCmdMappingCmd3_1, 14:8, secure_scratch20, 13:7); + s(EmcCmdMappingCmd3_1, 22:16, secure_scratch20, 20:14); + s(EmcCmdMappingCmd3_1, 30:24, secure_scratch20, 27:21); + s(McGeneralizedCarveout2Cfg0, 10:7, secure_scratch20, 31:28); + s(McGeneralizedCarveout4Cfg0, 26:0, secure_scratch39, 26:0); + s(McGeneralizedCarveout2Cfg0, 17:14, secure_scratch39, 30:27); + s(McVideoProtectVprOverride, 0:0, secure_scratch39, 31:31); + s(McGeneralizedCarveout5Cfg0, 26:0, secure_scratch40, 26:0); + s(McGeneralizedCarveout2Cfg0, 21:18, secure_scratch40, 30:27); + s(McVideoProtectVprOverride, 1:1, secure_scratch40, 31:31); + s(EmcCmdMappingCmd0_2, 6:0, secure_scratch41, 6:0); + s(EmcCmdMappingCmd0_2, 14:8, secure_scratch41, 13:7); + s(EmcCmdMappingCmd0_2, 22:16, secure_scratch41, 20:14); + s(EmcCmdMappingCmd0_2, 27:24, secure_scratch41, 24:21); + s(McGeneralizedCarveout1Cfg0, 6:3, secure_scratch41, 28:25); + s(McGeneralizedCarveout2Cfg0, 13:11, secure_scratch41, 31:29); + s(EmcCmdMappingCmd1_2, 6:0, secure_scratch42, 6:0); + s(EmcCmdMappingCmd1_2, 14:8, secure_scratch42, 13:7); + s(EmcCmdMappingCmd1_2, 22:16, secure_scratch42, 20:14); + s(EmcCmdMappingCmd1_2, 27:24, secure_scratch42, 24:21); + s(McGeneralizedCarveout1Cfg0, 13:7, secure_scratch42, 31:25); + s(EmcCmdMappingCmd2_2, 6:0, secure_scratch43, 6:0); + s(EmcCmdMappingCmd2_2, 14:8, secure_scratch43, 13:7); + s(EmcCmdMappingCmd2_2, 22:16, secure_scratch43, 20:14); + s(EmcCmdMappingCmd2_2, 27:24, secure_scratch43, 24:21); + s(McGeneralizedCarveout1Cfg0, 17:14, secure_scratch43, 28:25); + s(McGeneralizedCarveout3Cfg0, 13:11, secure_scratch43, 31:29); + s(EmcCmdMappingCmd3_2, 6:0, secure_scratch44, 6:0); + s(EmcCmdMappingCmd3_2, 14:8, secure_scratch44, 13:7); + s(EmcCmdMappingCmd3_2, 22:16, secure_scratch44, 20:14); + s(EmcCmdMappingCmd3_2, 27:24, secure_scratch44, 24:21); + s(McGeneralizedCarveout1Cfg0, 21:18, secure_scratch44, 28:25); + s(McVideoProtectVprOverride, 3:2, secure_scratch44, 30:29); + s(McVideoProtectVprOverride, 6:6, secure_scratch44, 31:31); + s(McEmemAdrCfgChannelMask, 31:9, secure_scratch45, 22:0); + s(McEmemAdrCfgDev0, 2:0, secure_scratch45, 25:23); + s(McEmemAdrCfgDev0, 9:8, secure_scratch45, 27:26); + s(McEmemAdrCfgDev0, 19:16, secure_scratch45, 31:28); + s(McEmemAdrCfgBankMask0, 31:10, secure_scratch46, 21:0); + s(McEmemAdrCfgDev1, 2:0, secure_scratch46, 24:22); + s(McEmemAdrCfgDev1, 9:8, secure_scratch46, 26:25); + s(McEmemAdrCfgDev1, 19:16, secure_scratch46, 30:27); + s(McVideoProtectVprOverride, 7:7, secure_scratch46, 31:31); + s(McEmemAdrCfgBankMask1, 31:10, secure_scratch47, 21:0); + s(McGeneralizedCarveout3Cfg0, 10:3, secure_scratch47, 29:22); + s(McVideoProtectVprOverride, 9:8, secure_scratch47, 31:30); + s(McEmemAdrCfgBankMask2, 31:10, secure_scratch48, 21:0); + s(McGeneralizedCarveout3Cfg0, 21:14, secure_scratch48, 29:22); + s(McVideoProtectVprOverride, 11:11, secure_scratch48, 30:30); + s(McVideoProtectVprOverride, 14:14, secure_scratch48, 31:31); + s(McVideoProtectGpuOverride1, 15:0, secure_scratch49, 15:0); + s(McEmemCfg, 13:0, secure_scratch49, 29:16); + s(McEmemCfg, 31:31, secure_scratch49, 30:30); + s(McVideoProtectVprOverride, 15:15, secure_scratch49, 31:31); + s(McGeneralizedCarveout3Bom, 31:17, secure_scratch50, 14:0); + s(McGeneralizedCarveout1Bom, 31:17, secure_scratch50, 29:15); + s(McVideoProtectVprOverride, 18:17, secure_scratch50, 31:30); + s(McGeneralizedCarveout4Bom, 31:17, secure_scratch51, 14:0); + s(McGeneralizedCarveout2Bom, 31:17, secure_scratch51, 29:15); + s(McVideoProtectVprOverride, 20:19, secure_scratch51, 31:30); + s(McGeneralizedCarveout5Bom, 31:17, secure_scratch52, 14:0); + s(McVideoProtectBom, 31:20, secure_scratch52, 26:15); + s(McVideoProtectVprOverride, 23:21, secure_scratch52, 29:27); + s(McVideoProtectVprOverride, 26:26, secure_scratch52, 30:30); + s(McVideoProtectVprOverride, 29:29, secure_scratch52, 31:31); + s(McVideoProtectSizeMb, 11:0, secure_scratch53, 11:0); + s(McSecCarveoutBom, 31:20, secure_scratch53, 23:12); + s(McVideoProtectVprOverride, 31:30, secure_scratch53, 25:24); + s(McVideoProtectVprOverride1, 1:0, secure_scratch53, 27:26); + s(McVideoProtectVprOverride1, 7:4, secure_scratch53, 31:28); + s(McSecCarveoutSizeMb, 11:0, secure_scratch54, 11:0); + s(McMtsCarveoutBom, 31:20, secure_scratch54, 23:12); + s(McVideoProtectVprOverride1, 15:8, secure_scratch54, 31:24); + s(McMtsCarveoutSizeMb, 11:0, secure_scratch55, 11:0); + s(McGeneralizedCarveout4Size128kb, 11:0, secure_scratch55, 23:12); + s(McVideoProtectVprOverride1, 16:16, secure_scratch55, 24:24); + s(McGeneralizedCarveout2Cfg0, 2:0, secure_scratch55, 27:25); + s(McGeneralizedCarveout2Cfg0, 25:22, secure_scratch55, 31:28); + s(McGeneralizedCarveout3Size128kb, 11:0, secure_scratch56, 11:0); + s(McGeneralizedCarveout2Size128kb, 11:0, secure_scratch56, 23:12); + s(McGeneralizedCarveout2Cfg0, 26:26, secure_scratch56, 24:24); + s(McGeneralizedCarveout1Cfg0, 2:0, secure_scratch56, 27:25); + s(McGeneralizedCarveout1Cfg0, 25:22, secure_scratch56, 31:28); + s(McGeneralizedCarveout1Size128kb, 11:0, secure_scratch57, 11:0); + s(McGeneralizedCarveout5Size128kb, 11:0, secure_scratch57, 23:12); + s(McGeneralizedCarveout1Cfg0, 26:26, secure_scratch57, 24:24); + s(McGeneralizedCarveout3Cfg0, 2:0, secure_scratch57, 27:25); + s(McGeneralizedCarveout3Cfg0, 25:22, secure_scratch57, 31:28); + s(McGeneralizedCarveout3Cfg0, 26:26, secure_scratch58, 0:0); + + s32(McGeneralizedCarveout1Access0, secure_scratch59); + s32(McGeneralizedCarveout1Access1, secure_scratch60); + s32(McGeneralizedCarveout1Access2, secure_scratch61); + s32(McGeneralizedCarveout1Access3, secure_scratch62); + s32(McGeneralizedCarveout1Access4, secure_scratch63); + s32(McGeneralizedCarveout2Access0, secure_scratch64); + s32(McGeneralizedCarveout2Access1, secure_scratch65); + s32(McGeneralizedCarveout2Access2, secure_scratch66); + s32(McGeneralizedCarveout2Access3, secure_scratch67); + s32(McGeneralizedCarveout2Access4, secure_scratch68); + s32(McGeneralizedCarveout3Access0, secure_scratch69); + s32(McGeneralizedCarveout3Access1, secure_scratch70); + s32(McGeneralizedCarveout3Access2, secure_scratch71); + s32(McGeneralizedCarveout3Access3, secure_scratch72); + s32(McGeneralizedCarveout3Access4, secure_scratch73); + s32(McGeneralizedCarveout4Access0, secure_scratch74); + s32(McGeneralizedCarveout4Access1, secure_scratch75); + s32(McGeneralizedCarveout4Access2, secure_scratch76); + s32(McGeneralizedCarveout4Access3, secure_scratch77); + s32(McGeneralizedCarveout4Access4, secure_scratch78); + s32(McGeneralizedCarveout5Access0, secure_scratch79); + s32(McGeneralizedCarveout5Access1, secure_scratch80); + s32(McGeneralizedCarveout5Access2, secure_scratch81); + s32(McGeneralizedCarveout5Access3, secure_scratch82); + s32(McGeneralizedCarveout1ForceInternalAccess0, secure_scratch84); + s32(McGeneralizedCarveout1ForceInternalAccess1, secure_scratch85); + s32(McGeneralizedCarveout1ForceInternalAccess2, secure_scratch86); + s32(McGeneralizedCarveout1ForceInternalAccess3, secure_scratch87); + s32(McGeneralizedCarveout1ForceInternalAccess4, secure_scratch88); + s32(McGeneralizedCarveout2ForceInternalAccess0, secure_scratch89); + s32(McGeneralizedCarveout2ForceInternalAccess1, secure_scratch90); + s32(McGeneralizedCarveout2ForceInternalAccess2, secure_scratch91); + s32(McGeneralizedCarveout2ForceInternalAccess3, secure_scratch92); + s32(McGeneralizedCarveout2ForceInternalAccess4, secure_scratch93); + s32(McGeneralizedCarveout3ForceInternalAccess0, secure_scratch94); + s32(McGeneralizedCarveout3ForceInternalAccess1, secure_scratch95); + s32(McGeneralizedCarveout3ForceInternalAccess2, secure_scratch96); + s32(McGeneralizedCarveout3ForceInternalAccess3, secure_scratch97); + s32(McGeneralizedCarveout3ForceInternalAccess4, secure_scratch98); + s32(McGeneralizedCarveout4ForceInternalAccess0, secure_scratch99); + s32(McGeneralizedCarveout4ForceInternalAccess1, secure_scratch100); + s32(McGeneralizedCarveout4ForceInternalAccess2, secure_scratch101); + s32(McGeneralizedCarveout4ForceInternalAccess3, secure_scratch102); + s32(McGeneralizedCarveout4ForceInternalAccess4, secure_scratch103); + s32(McGeneralizedCarveout5ForceInternalAccess0, secure_scratch104); + s32(McGeneralizedCarveout5ForceInternalAccess1, secure_scratch105); + s32(McGeneralizedCarveout5ForceInternalAccess2, secure_scratch106); + s32(McGeneralizedCarveout5ForceInternalAccess3, secure_scratch107); + + c32(0, scratch2); + s(PllMInputDivider, 7:0, scratch2, 7:0); + s(PllMFeedbackDivider, 7:0, scratch2, 15:8); + s(PllMPostDivider, 4:0, scratch2, 20:16); + s(PllMKVCO, 0:0, scratch2, 21:21); + s(PllMKCP, 1:0, scratch2, 23:22); + + c32(0, scratch35); + s(PllMSetupControl, 15:0, scratch35, 15:0); + + c32(0, scratch3); + s(PllMInputDivider, 7:0, scratch3, 7:0); + c(0x3e, scratch3, 15:8); + c(0, scratch3, 20:16); + s(PllMKVCO, 0:0, scratch3, 21:21); + s(PllMKCP, 1:0, scratch3, 23:22); + + c32(0, scratch36); + s(PllMSetupControl, 23:0, scratch36, 23:0); + + c32(0, scratch4); + s(PllMStableTime, 9:0, scratch4, 9:0); +} diff --git a/sept/sept-secondary/src/sdram_lz.inl b/sept/sept-secondary/src/sdram_lz.inl new file mode 100644 index 000000000..f8f46fbd4 --- /dev/null +++ b/sept/sept-secondary/src/sdram_lz.inl @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2018 naehrwert + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +static const uint8_t _dram_cfg_lz[1262] = { + 0x17, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x2C, 0x17, 0x04, 0x09, 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, + 0x17, 0x10, 0x10, 0x00, 0x00, 0x68, 0xBC, 0x01, 0x70, 0x0A, 0x00, 0x00, + 0x00, 0x04, 0xB4, 0x01, 0x70, 0x01, 0x32, 0x54, 0x76, 0xC8, 0xE6, 0x00, + 0x70, 0x17, 0x10, 0x24, 0x34, 0x00, 0x00, 0x00, 0x02, 0x80, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x17, 0x04, 0x04, 0x17, 0x09, 0x18, 0xFF, 0xFF, 0x1F, + 0x00, 0xD8, 0x51, 0x1A, 0xA0, 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x77, + 0x00, 0x17, 0x04, 0x04, 0x17, 0x08, 0x08, 0x17, 0x08, 0x08, 0xA6, 0xA6, + 0xAF, 0xB3, 0x3C, 0x9E, 0x00, 0x00, 0x03, 0x03, 0xE0, 0xC1, 0x04, 0x04, + 0x04, 0x04, 0x17, 0x04, 0x04, 0x17, 0x04, 0x3C, 0x1F, 0x1F, 0x1F, 0x1F, + 0x17, 0x04, 0x04, 0x17, 0x06, 0x06, 0x00, 0x00, 0x04, 0x08, 0x17, 0x06, + 0x46, 0xA1, 0x01, 0x00, 0x00, 0x32, 0x17, 0x0B, 0x64, 0x01, 0x17, 0x04, + 0x7C, 0x17, 0x07, 0x0C, 0x03, 0x17, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1E, + 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x13, + 0x17, 0x0B, 0x2C, 0x09, 0x00, 0x00, 0x00, 0x17, 0x05, 0x5D, 0x17, 0x07, + 0x10, 0x0B, 0x17, 0x07, 0x28, 0x08, 0x17, 0x07, 0x0C, 0x17, 0x04, 0x1C, + 0x20, 0x00, 0x00, 0x00, 0x06, 0x17, 0x04, 0x04, 0x17, 0x07, 0x08, 0x17, + 0x04, 0x50, 0x17, 0x04, 0x2C, 0x17, 0x04, 0x1C, 0x17, 0x04, 0x10, 0x17, + 0x08, 0x6C, 0x17, 0x04, 0x10, 0x17, 0x04, 0x38, 0x17, 0x04, 0x40, 0x05, + 0x17, 0x07, 0x1C, 0x17, 0x08, 0x58, 0x17, 0x04, 0x24, 0x17, 0x04, 0x18, + 0x17, 0x08, 0x64, 0x00, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x09, 0x0C, 0x17, 0x05, 0x82, + 0x58, 0x17, 0x07, 0x61, 0xC1, 0x17, 0x07, 0x50, 0x17, 0x04, 0x04, 0x17, + 0x08, 0x81, 0x48, 0x17, 0x04, 0x04, 0x17, 0x04, 0x28, 0x17, 0x04, 0x60, + 0x17, 0x08, 0x54, 0x27, 0x17, 0x04, 0x04, 0x17, 0x07, 0x14, 0x17, 0x04, + 0x04, 0x04, 0x17, 0x07, 0x81, 0x58, 0x17, 0x0C, 0x0C, 0x1C, 0x03, 0x00, + 0x00, 0x0D, 0xA0, 0x60, 0x91, 0xBF, 0x3B, 0x17, 0x04, 0x5A, 0xF3, 0x0C, + 0x04, 0x05, 0x1B, 0x06, 0x02, 0x03, 0x07, 0x1C, 0x23, 0x25, 0x25, 0x05, + 0x08, 0x1D, 0x09, 0x0A, 0x24, 0x0B, 0x1E, 0x0D, 0x0C, 0x26, 0x26, 0x03, + 0x02, 0x1B, 0x1C, 0x23, 0x03, 0x04, 0x07, 0x05, 0x06, 0x25, 0x25, 0x02, + 0x0A, 0x0B, 0x1D, 0x0D, 0x08, 0x0C, 0x09, 0x1E, 0x24, 0x26, 0x26, 0x08, + 0x24, 0x06, 0x07, 0x9A, 0x12, 0x17, 0x05, 0x83, 0x41, 0x00, 0xFF, 0x17, + 0x10, 0x83, 0x6C, 0x04, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, + 0x00, 0x0D, 0x08, 0x00, 0x00, 0x00, 0xC0, 0x71, 0x71, 0x03, 0x08, 0x00, + 0x00, 0x0B, 0x08, 0x72, 0x72, 0x0E, 0x0C, 0x17, 0x04, 0x20, 0x08, 0x08, + 0x0D, 0x0C, 0x00, 0x00, 0x0D, 0x0C, 0x14, 0x14, 0x16, 0x08, 0x17, 0x06, + 0x2C, 0x11, 0x08, 0x17, 0x10, 0x84, 0x67, 0x15, 0x00, 0xCC, 0x00, 0x0A, + 0x00, 0x33, 0x00, 0x00, 0x00, 0x20, 0xF3, 0x05, 0x08, 0x11, 0x00, 0xFF, + 0x0F, 0xFF, 0x0F, 0x17, 0x08, 0x83, 0x4C, 0x01, 0x03, 0x00, 0x70, 0x00, + 0x0C, 0x00, 0x01, 0x17, 0x04, 0x0C, 0x08, 0x44, 0x00, 0x10, 0x04, 0x04, + 0x00, 0x06, 0x13, 0x07, 0x00, 0x80, 0x17, 0x04, 0x10, 0xA0, 0x00, 0x2C, + 0x00, 0x01, 0x37, 0x00, 0x00, 0x00, 0x80, 0x17, 0x06, 0x48, 0x08, 0x00, + 0x04, 0x00, 0x1F, 0x22, 0x20, 0x80, 0x0F, 0xF4, 0x20, 0x02, 0x28, 0x28, + 0x28, 0x28, 0x17, 0x04, 0x04, 0x11, 0x11, 0x11, 0x11, 0x17, 0x04, 0x04, + 0xBE, 0x00, 0x00, 0x17, 0x05, 0x58, 0x17, 0x08, 0x5C, 0x17, 0x22, 0x85, + 0x6A, 0x17, 0x1A, 0x1A, 0x14, 0x00, 0x12, 0x00, 0x10, 0x17, 0x05, 0x83, + 0x0A, 0x17, 0x16, 0x18, 0x30, 0x00, 0x2E, 0x00, 0x33, 0x00, 0x30, 0x00, + 0x33, 0x00, 0x35, 0x00, 0x30, 0x00, 0x32, 0x17, 0x05, 0x83, 0x0C, 0x17, + 0x04, 0x20, 0x17, 0x18, 0x18, 0x28, 0x00, 0x28, 0x17, 0x04, 0x04, 0x17, + 0x08, 0x08, 0x17, 0x10, 0x10, 0x00, 0x14, 0x17, 0x05, 0x5A, 0x17, 0x04, + 0x5C, 0x17, 0x04, 0x5E, 0x17, 0x04, 0x0E, 0x17, 0x0E, 0x78, 0x17, 0x09, + 0x82, 0x50, 0x40, 0x06, 0x00, 0xCC, 0x00, 0x09, 0x00, 0x4F, 0x00, 0x51, + 0x17, 0x08, 0x18, 0x80, 0x01, 0x00, 0x00, 0x40, 0x17, 0x04, 0x20, 0x03, + 0x00, 0x00, 0x00, 0xAB, 0x00, 0x0A, 0x04, 0x11, 0x17, 0x08, 0x82, 0x58, + 0x17, 0x0C, 0x38, 0x17, 0x1B, 0x81, 0x6C, 0x17, 0x08, 0x85, 0x60, 0x17, + 0x08, 0x86, 0x50, 0x17, 0x08, 0x86, 0x60, 0x17, 0x06, 0x83, 0x21, 0x22, + 0x04, 0xFF, 0xFF, 0xAF, 0x4F, 0x17, 0x0C, 0x86, 0x74, 0x17, 0x08, 0x2C, + 0x8B, 0xFF, 0x07, 0x17, 0x06, 0x81, 0x04, 0x32, 0x54, 0x76, 0x10, 0x47, + 0x32, 0x65, 0x10, 0x34, 0x76, 0x25, 0x01, 0x34, 0x67, 0x25, 0x01, 0x75, + 0x64, 0x32, 0x01, 0x72, 0x56, 0x34, 0x10, 0x23, 0x74, 0x56, 0x01, 0x45, + 0x32, 0x67, 0x17, 0x04, 0x24, 0x49, 0x92, 0x24, 0x17, 0x04, 0x04, 0x17, + 0x11, 0x7C, 0x1B, 0x17, 0x04, 0x04, 0x17, 0x13, 0x81, 0x14, 0x2F, 0x41, + 0x13, 0x1F, 0x14, 0x00, 0x01, 0x00, 0x17, 0x04, 0x7C, 0xFF, 0xFF, 0xFF, + 0x7F, 0x0B, 0xD7, 0x06, 0x40, 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x03, + 0x00, 0x00, 0x5C, 0x01, 0x00, 0x10, 0x10, 0x10, 0x17, 0x06, 0x86, 0x59, + 0x17, 0x0F, 0x89, 0x14, 0x37, 0x17, 0x07, 0x82, 0x72, 0x10, 0x17, 0x06, + 0x83, 0x0D, 0x00, 0x11, 0x01, 0x17, 0x05, 0x85, 0x39, 0x17, 0x04, 0x0E, + 0x0A, 0x17, 0x07, 0x89, 0x29, 0x17, 0x04, 0x1B, 0x17, 0x08, 0x86, 0x77, + 0x17, 0x09, 0x12, 0x20, 0x00, 0x00, 0x00, 0x81, 0x10, 0x09, 0x28, 0x93, + 0x32, 0xA5, 0x44, 0x5B, 0x8A, 0x67, 0x76, 0x17, 0x18, 0x82, 0x2C, 0xFF, + 0xEF, 0xFF, 0xEF, 0xC0, 0xC0, 0xC0, 0xC0, 0x17, 0x04, 0x04, 0xDC, 0xDC, + 0xDC, 0xDC, 0x0A, 0x0A, 0x0A, 0x0A, 0x17, 0x04, 0x04, 0x17, 0x04, 0x04, + 0x17, 0x05, 0x82, 0x24, 0x03, 0x07, 0x17, 0x04, 0x04, 0x00, 0x00, 0x24, + 0xFF, 0xFF, 0x00, 0x44, 0x57, 0x6E, 0x00, 0x28, 0x72, 0x39, 0x00, 0x10, + 0x9C, 0x4B, 0x17, 0x04, 0x64, 0x01, 0x00, 0x00, 0x08, 0x4C, 0x00, 0x00, + 0x80, 0x20, 0x10, 0x0A, 0x00, 0x28, 0x10, 0x17, 0x06, 0x85, 0x60, 0x17, + 0x10, 0x82, 0x74, 0x17, 0x08, 0x08, 0x17, 0x08, 0x88, 0x00, 0x17, 0x04, + 0x10, 0x04, 0x17, 0x0B, 0x87, 0x6C, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, + 0x03, 0x00, 0x04, 0x05, 0xC3, 0x71, 0x0F, 0x0F, 0x17, 0x08, 0x8B, 0x18, + 0x1F, 0x17, 0x09, 0x81, 0x73, 0x00, 0xFF, 0x00, 0xFF, 0x17, 0x05, 0x86, + 0x48, 0x17, 0x04, 0x0C, 0x17, 0x07, 0x86, 0x34, 0x00, 0x00, 0xF0, 0x17, + 0x09, 0x87, 0x54, 0x43, 0xC3, 0xBA, 0xE4, 0xD3, 0x1E, 0x17, 0x0C, 0x81, + 0x52, 0x17, 0x0A, 0x1C, 0x17, 0x10, 0x81, 0x6C, 0x17, 0x0A, 0x82, 0x21, + 0x17, 0x07, 0x82, 0x4D, 0x17, 0x0A, 0x8A, 0x1B, 0x17, 0x11, 0x2C, 0x76, + 0x0C, 0x17, 0x0A, 0x8A, 0x67, 0x17, 0x0F, 0x84, 0x28, 0x17, 0x06, 0x34, + 0x17, 0x17, 0x3A, 0x7E, 0x16, 0x40, 0x17, 0x0C, 0x8B, 0x1F, 0x17, 0x2A, + 0x38, 0x1E, 0x17, 0x0A, 0x38, 0x17, 0x13, 0x81, 0x28, 0x00, 0xC0, 0x17, + 0x17, 0x55, 0x46, 0x24, 0x17, 0x0A, 0x81, 0x28, 0x17, 0x14, 0x38, 0x17, + 0x18, 0x81, 0x60, 0x46, 0x2C, 0x17, 0x06, 0x38, 0xEC, 0x17, 0x0D, 0x16, + 0x17, 0x0E, 0x82, 0x3C, 0x17, 0x82, 0x0C, 0x8E, 0x68, 0x17, 0x04, 0x24, + 0x17, 0x5C, 0x8E, 0x68, 0x17, 0x07, 0x82, 0x5F, 0x80, 0x17, 0x87, 0x01, + 0x8E, 0x68, 0x02, 0x17, 0x81, 0x4A, 0x8E, 0x68, 0x17, 0x0C, 0x87, 0x78, + 0x17, 0x85, 0x28, 0x8E, 0x68, 0x17, 0x8E, 0x68, 0x9D, 0x50, 0x17, 0x81, + 0x24, 0x8E, 0x68, 0x17, 0x04, 0x2C, 0x17, 0x28, 0x8E, 0x68, 0x17, 0x04, + 0x30, 0x17, 0x85, 0x3C, 0x8E, 0x68, 0x12, 0x17, 0x07, 0x85, 0x70, 0x17, + 0x88, 0x74, 0x8E, 0x68, 0x17, 0x87, 0x3E, 0x9D, 0x50, 0x0C, 0x17, 0x04, + 0x04, 0x17, 0x12, 0x8E, 0x68, 0x18, 0x17, 0x87, 0x12, 0xBB, 0x20, 0x17, + 0x83, 0x04, 0x9D, 0x50, 0x15, 0x17, 0x05, 0x8D, 0x76, 0x17, 0x0F, 0x8B, + 0x49, 0x17, 0x0B, 0x18, 0x32, 0x00, 0x2F, 0x00, 0x32, 0x00, 0x31, 0x00, + 0x34, 0x00, 0x36, 0x00, 0x2F, 0x00, 0x33, 0x17, 0x09, 0x84, 0x0C, 0x17, + 0x18, 0x18, 0x17, 0x20, 0x8E, 0x68, 0x15, 0x17, 0x07, 0x5A, 0x17, 0x06, + 0x5E, 0x16, 0x00, 0x15, 0x17, 0x82, 0x40, 0x9D, 0x50, 0x17, 0x86, 0x5F, + 0xBB, 0x20, 0x3A, 0x00, 0x00, 0x00, 0x1D, 0x17, 0x81, 0x4F, 0xAC, 0x38, + 0x3B, 0x17, 0x04, 0x04, 0x17, 0x86, 0x30, 0x8E, 0x68, 0x17, 0x81, 0x53, + 0xAC, 0x38, 0x07, 0x17, 0x0D, 0x8E, 0x68, 0xA3, 0x72, 0x17, 0x83, 0x10, + 0x8E, 0x68 +}; diff --git a/sept/sept-secondary/src/sdram_param_t210.h b/sept/sept-secondary/src/sdram_param_t210.h new file mode 100644 index 000000000..328ee5109 --- /dev/null +++ b/sept/sept-secondary/src/sdram_param_t210.h @@ -0,0 +1,933 @@ +/* + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * See file CREDITS for list of people who contributed to this + * project. + */ + +/** + * Defines the SDRAM parameter structure. + * + * Note that PLLM is used by EMC. + */ + +#ifndef _SDRAM_PARAM_T210_H_ +#define _SDRAM_PARAM_T210_H_ + +#include <stdint.h> + +#define MEMORY_TYPE_NONE 0 +#define MEMORY_TYPE_DDR 0 +#define MEMORY_TYPE_LPDDR 0 +#define MEMORY_TYPE_DDR2 0 +#define MEMORY_TYPE_LPDDR2 1 +#define MEMORY_TYPE_DDR3 2 +#define MEMORY_TYPE_LPDDR4 3 + +/** + * Defines the SDRAM parameter structure + */ +typedef struct _sdram_params +{ + /* Specifies the type of memory device */ + uint32_t memory_type; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + uint32_t pllm_input_divider; + /* Specifies the N value for PllM */ + uint32_t pllm_feedback_divider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + uint32_t pllm_stable_time; + /* Specifies misc. control bits */ + uint32_t pllm_setup_control; + /* Specifies the P value for PLLM */ + uint32_t pllm_post_divider; + /* Specifies value for Charge Pump Gain Control */ + uint32_t pllm_kcp; + /* Specifies VCO gain */ + uint32_t pllm_kvco; + /* Spare BCT param */ + uint32_t emc_bct_spare0; + /* Spare BCT param */ + uint32_t emc_bct_spare1; + /* Spare BCT param */ + uint32_t emc_bct_spare2; + /* Spare BCT param */ + uint32_t emc_bct_spare3; + /* Spare BCT param */ + uint32_t emc_bct_spare4; + /* Spare BCT param */ + uint32_t emc_bct_spare5; + /* Spare BCT param */ + uint32_t emc_bct_spare6; + /* Spare BCT param */ + uint32_t emc_bct_spare7; + /* Spare BCT param */ + uint32_t emc_bct_spare8; + /* Spare BCT param */ + uint32_t emc_bct_spare9; + /* Spare BCT param */ + uint32_t emc_bct_spare10; + /* Spare BCT param */ + uint32_t emc_bct_spare11; + /* Spare BCT param */ + uint32_t emc_bct_spare12; + /* Spare BCT param */ + uint32_t emc_bct_spare13; + + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + uint32_t emc_clock_source; + uint32_t emc_clock_source_dll; + + /* Defines possible override for PLLLM_MISC2 */ + uint32_t clk_rst_pllm_misc20_override; + /* enables override for PLLLM_MISC2 */ + uint32_t clk_rst_pllm_misc20_override_enable; + /* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */ + uint32_t clear_clock2_mc1; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + uint32_t emc_auto_cal_interval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + uint32_t emc_auto_cal_config; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + uint32_t emc_auto_cal_config2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + uint32_t emc_auto_cal_config3; + + uint32_t emc_auto_cal_config4; + uint32_t emc_auto_cal_config5; + uint32_t emc_auto_cal_config6; + uint32_t emc_auto_cal_config7; + uint32_t emc_auto_cal_config8; + /* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */ + uint32_t emc_auto_cal_vref_sel0; + uint32_t emc_auto_cal_vref_sel1; + + /* Specifies the value for EMC_AUTO_CAL_CHANNEL */ + uint32_t emc_auto_cal_channel; + + /* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */ + uint32_t emc_pmacro_auto_cal_cfg0; + uint32_t emc_pmacro_auto_cal_cfg1; + uint32_t emc_pmacro_auto_cal_cfg2; + + uint32_t emc_pmacro_rx_term; + uint32_t emc_pmacro_dq_tx_drive; + uint32_t emc_pmacro_ca_tx_drive; + uint32_t emc_pmacro_cmd_tx_drive; + uint32_t emc_pmacro_auto_cal_common; + uint32_t emc_pmacro_zcrtl; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + uint32_t emc_auto_cal_wait; + + uint32_t emc_xm2_comp_pad_ctrl; + uint32_t emc_xm2_comp_pad_ctrl2; + uint32_t emc_xm2_comp_pad_ctrl3; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + uint32_t emc_adr_cfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + uint32_t emc_pin_program_wait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + uint32_t emc_pin_extra_wait; + + uint32_t emc_pin_gpio_enable; + uint32_t emc_pin_gpio; + + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + uint32_t emc_timing_control_wait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + uint32_t emc_rc; + /* Specifies the value for EMC_RFC */ + uint32_t emc_rfc; + + uint32_t emc_rfc_pb; + uint32_t emc_ref_ctrl2; + + /* Specifies the value for EMC_RFC_SLR */ + uint32_t emc_rfc_slr; + /* Specifies the value for EMC_RAS */ + uint32_t emc_ras; + /* Specifies the value for EMC_RP */ + uint32_t emc_rp; + /* Specifies the value for EMC_R2R */ + uint32_t emc_r2r; + /* Specifies the value for EMC_W2W */ + uint32_t emc_w2w; + /* Specifies the value for EMC_R2W */ + uint32_t emc_r2w; + /* Specifies the value for EMC_W2R */ + uint32_t emc_w2r; + /* Specifies the value for EMC_R2P */ + uint32_t emc_r2p; + /* Specifies the value for EMC_W2P */ + uint32_t emc_w2p; + /* Specifies the value for EMC_RD_RCD */ + + uint32_t emc_tppd; + uint32_t emc_ccdmw; + + uint32_t emc_rd_rcd; + /* Specifies the value for EMC_WR_RCD */ + uint32_t emc_wr_rcd; + /* Specifies the value for EMC_RRD */ + uint32_t emc_rrd; + /* Specifies the value for EMC_REXT */ + uint32_t emc_rext; + /* Specifies the value for EMC_WEXT */ + uint32_t emc_wext; + /* Specifies the value for EMC_WDV */ + uint32_t emc_wdv; + + uint32_t emc_wdv_chk; + uint32_t emc_wsv; + uint32_t emc_wev; + + /* Specifies the value for EMC_WDV_MASK */ + uint32_t emc_wdv_mask; + + uint32_t emc_ws_duration; + uint32_t emc_we_duration; + + /* Specifies the value for EMC_QUSE */ + uint32_t emc_quse; + /* Specifies the value for EMC_QUSE_WIDTH */ + uint32_t emc_quse_width; + /* Specifies the value for EMC_IBDLY */ + uint32_t emc_ibdly; + + uint32_t emc_obdly; + + /* Specifies the value for EMC_EINPUT */ + uint32_t emc_einput; + /* Specifies the value for EMC_EINPUT_DURATION */ + uint32_t emc_einput_duration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + uint32_t emc_puterm_extra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + uint32_t emc_puterm_width; + + uint32_t emc_qrst; + uint32_t emc_qsafe; + uint32_t emc_rdv; + uint32_t emc_rdv_mask; + + uint32_t emc_rdv_early; + uint32_t emc_rdv_early_mask; + + /* Specifies the value for EMC_QPOP */ + uint32_t emc_qpop; + + /* Specifies the value for EMC_REFRESH */ + uint32_t emc_refresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + uint32_t emc_burst_refresh_num; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + uint32_t emc_prerefresh_req_cnt; + /* Specifies the value for EMC_PDEX2WR */ + uint32_t emc_pdex2wr; + /* Specifies the value for EMC_PDEX2RD */ + uint32_t emc_pdex2rd; + /* Specifies the value for EMC_PCHG2PDEN */ + uint32_t emc_pchg2pden; + /* Specifies the value for EMC_ACT2PDEN */ + uint32_t emc_act2pden; + /* Specifies the value for EMC_AR2PDEN */ + uint32_t emc_ar2pden; + /* Specifies the value for EMC_RW2PDEN */ + uint32_t emc_rw2pden; + + uint32_t emc_cke2pden; + uint32_t emc_pdex2che; + uint32_t emc_pdex2mrr; + + /* Specifies the value for EMC_TXSR */ + uint32_t emc_txsr; + /* Specifies the value for EMC_TXSRDLL */ + uint32_t emc_txsr_dll; + /* Specifies the value for EMC_TCKE */ + uint32_t emc_tcke; + /* Specifies the value for EMC_TCKESR */ + uint32_t emc_tckesr; + /* Specifies the value for EMC_TPD */ + uint32_t emc_tpd; + /* Specifies the value for EMC_TFAW */ + uint32_t emc_tfaw; + /* Specifies the value for EMC_TRPAB */ + uint32_t emc_trpab; + /* Specifies the value for EMC_TCLKSTABLE */ + uint32_t emc_tclkstable; + /* Specifies the value for EMC_TCLKSTOP */ + uint32_t emc_tclkstop; + /* Specifies the value for EMC_TREFBW */ + uint32_t emc_trefbw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + uint32_t emc_fbio_cfg5; + /* Specifies the value for EMC_FBIO_CFG7 */ + uint32_t emc_fbio_cfg7; + uint32_t emc_fbio_cfg8; + + /* Command mapping for CMD brick 0 */ + uint32_t emc_cmd_mapping_cmd0_0; + uint32_t emc_cmd_mapping_cmd0_1; + uint32_t emc_cmd_mapping_cmd0_2; + uint32_t emc_cmd_mapping_cmd1_0; + uint32_t emc_cmd_mapping_cmd1_1; + uint32_t emc_cmd_mapping_cmd1_2; + uint32_t emc_cmd_mapping_cmd2_0; + uint32_t emc_cmd_mapping_cmd2_1; + uint32_t emc_cmd_mapping_cmd2_2; + uint32_t emc_cmd_mapping_cmd3_0; + uint32_t emc_cmd_mapping_cmd3_1; + uint32_t emc_cmd_mapping_cmd3_2; + uint32_t emc_cmd_mapping_byte; + + /* Specifies the value for EMC_FBIO_SPARE */ + uint32_t emc_fbio_spare; + + /* Specifies the value for EMC_CFG_RSV */ + uint32_t emc_cfg_rsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + uint32_t emc_mrs; + /* Specifies the MP0 command to initialize mode registers */ + uint32_t emc_emrs; + /* Specifies the MP2 command to initialize mode registers */ + uint32_t emc_emrs2; + /* Specifies the MP3 command to initialize mode registers */ + uint32_t emc_emrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + uint32_t emc_mrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + uint32_t emc_mrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + uint32_t emc_mrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t emc_mrw4; + + /* Specifies the programming to LPDDR4 Mode Register 3 at cold boot */ + uint32_t emc_mrw6; + /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */ + uint32_t emc_mrw8; + /* Specifies the programming to LPDDR4 Mode Register 11 at cold boot */ + uint32_t emc_mrw9; + /* Specifies the programming to LPDDR4 Mode Register 12 at cold boot */ + uint32_t emc_mrw10; + /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */ + uint32_t emc_mrw12; + /* Specifies the programming to LPDDR4 Mode Register 14 at cold boot */ + uint32_t emc_mrw13; + /* Specifies the programming to LPDDR4 Mode Register 22 at cold boot */ + uint32_t emc_mrw14; + + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + uint32_t emc_mrw_extra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + uint32_t emc_warm_boot_mrw_extra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + uint32_t emc_warm_boot_extramode_reg_write_enable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + uint32_t emc_extramode_reg_write_enable; + + /* Specifies the EMC_MRW reset command value */ + uint32_t emc_mrw_reset_command; + /* Specifies the EMC Reset wait time (in microseconds) */ + uint32_t emc_mrw_reset_ninit_wait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + uint32_t emc_mrs_wait_cnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + uint32_t emc_mrs_wait_cnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + uint32_t emc_cfg; + /* Specifies the value for EMC_CFG_2 */ + uint32_t emc_cfg2; + /* Specifies the pipe bypass controls */ + uint32_t emc_cfg_pipe; + + uint32_t emc_cfg_pipe_clk; + uint32_t emc_fdpd_ctrl_cmd_no_ramp; + uint32_t emc_cfg_update; + + /* Specifies the value for EMC_DBG */ + uint32_t emc_dbg; + + uint32_t emc_dbg_write_mux; + + /* Specifies the value for EMC_CMDQ */ + uint32_t emc_cmd_q; + /* Specifies the value for EMC_MC2EMCQ */ + uint32_t emc_mc2emc_q; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + uint32_t emc_dyn_self_ref_control; + + /* Specifies the value for MEM_INIT_DONE */ + uint32_t ahb_arbitration_xbar_ctrl_meminit_done; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + uint32_t emc_cfg_dig_dll; + uint32_t emc_cfg_dig_dll_1; + + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + uint32_t emc_cfg_dig_dll_period; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + uint32_t emc_dev_select; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + uint32_t emc_sel_dpd_ctrl; + + /* Pads trimmer delays */ + uint32_t emc_fdpd_ctrl_dq; + uint32_t emc_fdpd_ctrl_cmd; + uint32_t emc_pmacro_ib_vref_dq_0; + uint32_t emc_pmacro_ib_vref_dq_1; + uint32_t emc_pmacro_ib_vref_dqs_0; + uint32_t emc_pmacro_ib_vref_dqs_1; + uint32_t emc_pmacro_ib_rxrt; + uint32_t emc_cfg_pipe1; + uint32_t emc_cfg_pipe2; + + /* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */ + uint32_t emc_pmacro_quse_ddll_rank0_0; + uint32_t emc_pmacro_quse_ddll_rank0_1; + uint32_t emc_pmacro_quse_ddll_rank0_2; + uint32_t emc_pmacro_quse_ddll_rank0_3; + uint32_t emc_pmacro_quse_ddll_rank0_4; + uint32_t emc_pmacro_quse_ddll_rank0_5; + uint32_t emc_pmacro_quse_ddll_rank1_0; + uint32_t emc_pmacro_quse_ddll_rank1_1; + uint32_t emc_pmacro_quse_ddll_rank1_2; + uint32_t emc_pmacro_quse_ddll_rank1_3; + uint32_t emc_pmacro_quse_ddll_rank1_4; + uint32_t emc_pmacro_quse_ddll_rank1_5; + + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_0; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_1; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_2; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_3; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_4; + uint32_t emc_pmacro_ob_ddll_long_dq_rank0_5; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_0; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_1; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_2; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_3; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_4; + uint32_t emc_pmacro_ob_ddll_long_dq_rank1_5; + + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_0; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_1; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_2; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_3; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_4; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank0_5; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_0; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_1; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_2; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_3; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_4; + uint32_t emc_pmacro_ob_ddll_long_dqs_rank1_5; + + uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_0; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_1; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_2; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank0_3; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_0; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_1; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_2; + uint32_t emc_pmacro_ib_ddll_long_dqs_rank1_3; + + uint32_t emc_pmacro_ddll_long_cmd_0; + uint32_t emc_pmacro_ddll_long_cmd_1; + uint32_t emc_pmacro_ddll_long_cmd_2; + uint32_t emc_pmacro_ddll_long_cmd_3; + uint32_t emc_pmacro_ddll_long_cmd_4; + uint32_t emc_pmacro_ddll_short_cmd_0; + uint32_t emc_pmacro_ddll_short_cmd_1; + uint32_t emc_pmacro_ddll_short_cmd_2; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + uint32_t warm_boot_wait; + + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t emc_odt_write; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + uint32_t emc_zcal_interval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + uint32_t emc_zcal_wait_cnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + uint32_t emc_zcal_mrw_cmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + uint32_t emc_mrs_reset_dll; + /* Specifies the command for ZQ initialization of device 0 */ + uint32_t emc_zcal_init_dev0; + /* Specifies the command for ZQ initialization of device 1 */ + uint32_t emc_zcal_init_dev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + uint32_t emc_zcal_init_wait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + uint32_t emc_zcal_warm_cold_boot_enables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + uint32_t emc_mrw_lpddr2zcal_warm_boot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + uint32_t emc_zqcal_ddr3_warm_boot; + + uint32_t emc_zqcal_lpddr4_warm_boot; + + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + uint32_t emc_zcal_warm_boot_wait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + uint32_t emc_mrs_warm_boot_enable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + uint32_t emc_mrs_reset_dll_wait; + /* Specifies the extra MRS command to initialize mode registers */ + uint32_t emc_mrs_extra; + /* Specifies the extra MRS command at warm boot */ + uint32_t emc_warm_boot_mrs_extra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + uint32_t emc_emrs_ddr2_dll_enable; + /* Specifies the MRS command to reset the DDR2 DLL */ + uint32_t emc_mrs_ddr2_dll_reset; + /* Specifies the EMRS command to set OCD calibration */ + uint32_t emc_emrs_ddr2_ocd_calib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + uint32_t emc_ddr2_wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + uint32_t emc_clken_override; + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + uint32_t emc_extra_refresh_num; + /* Specifies the master override for all EMC clocks */ + uint32_t emc_clken_override_allwarm_boot; + /* Specifies the master override for all MC clocks */ + uint32_t mc_clken_override_allwarm_boot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + uint32_t emc_cfg_dig_dll_period_warm_boot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + uint32_t pmc_vddp_sel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + uint32_t pmc_vddp_sel_wait; + /* Specifies the value for PMC_DDR_PWR */ + uint32_t pmc_ddr_pwr; + /* Specifies the value for PMC_DDR_CFG */ + uint32_t pmc_ddr_cfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + uint32_t pmc_io_dpd3_req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + uint32_t pmc_io_dpd3_req_wait; + + uint32_t pmc_io_dpd4_req_wait; + + /* Specifies the value for PMC_REG_SHORT */ + uint32_t pmc_reg_short; + /* Specifies the value for PMC_NO_IOPOWER */ + uint32_t pmc_no_io_power; + + uint32_t pmc_ddr_ctrl_wait; + uint32_t pmc_ddr_ctrl; + + /* Specifies the value for EMC_ACPD_CONTROL */ + uint32_t emc_acpd_control; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + uint32_t emc_swizzle_rank0_byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + uint32_t emc_swizzle_rank0_byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + uint32_t emc_swizzle_rank0_byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + uint32_t emc_swizzle_rank0_byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + uint32_t emc_swizzle_rank1_byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + uint32_t emc_swizzle_rank1_byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + uint32_t emc_swizzle_rank1_byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + uint32_t emc_swizzle_rank1_byte3; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + uint32_t emc_txdsrvttgen; + + /* Specifies the value for EMC_DATA_BRLSHFT_0 */ + uint32_t emc_data_brlshft0; + uint32_t emc_data_brlshft1; + + uint32_t emc_dqs_brlshft0; + uint32_t emc_dqs_brlshft1; + + uint32_t emc_cmd_brlshft0; + uint32_t emc_cmd_brlshft1; + uint32_t emc_cmd_brlshft2; + uint32_t emc_cmd_brlshft3; + + uint32_t emc_quse_brlshft0; + uint32_t emc_quse_brlshft1; + uint32_t emc_quse_brlshft2; + uint32_t emc_quse_brlshft3; + + uint32_t emc_dll_cfg0; + uint32_t emc_dll_cfg1; + + uint32_t emc_pmc_scratch1; + uint32_t emc_pmc_scratch2; + uint32_t emc_pmc_scratch3; + + uint32_t emc_pmacro_pad_cfg_ctrl; + + uint32_t emc_pmacro_vttgen_ctrl0; + uint32_t emc_pmacro_vttgen_ctrl1; + uint32_t emc_pmacro_vttgen_ctrl2; + + uint32_t emc_pmacro_brick_ctrl_rfu1; + uint32_t emc_pmacro_cmd_brick_ctrl_fdpd; + uint32_t emc_pmacro_brick_ctrl_rfu2; + uint32_t emc_pmacro_data_brick_ctrl_fdpd; + uint32_t emc_pmacro_bg_bias_ctrl0; + uint32_t emc_pmacro_data_pad_rx_ctrl; + uint32_t emc_pmacro_cmd_pad_rx_ctrl; + uint32_t emc_pmacro_data_rx_term_mode; + uint32_t emc_pmacro_cmd_rx_term_mode; + uint32_t emc_pmacro_data_pad_tx_ctrl; + uint32_t emc_pmacro_common_pad_tx_ctrl; + uint32_t emc_pmacro_cmd_pad_tx_ctrl; + uint32_t emc_cfg3; + + uint32_t emc_pmacro_tx_pwrd0; + uint32_t emc_pmacro_tx_pwrd1; + uint32_t emc_pmacro_tx_pwrd2; + uint32_t emc_pmacro_tx_pwrd3; + uint32_t emc_pmacro_tx_pwrd4; + uint32_t emc_pmacro_tx_pwrd5; + + uint32_t emc_config_sample_delay; + + uint32_t emc_pmacro_brick_mapping0; + uint32_t emc_pmacro_brick_mapping1; + uint32_t emc_pmacro_brick_mapping2; + + uint32_t emc_pmacro_tx_sel_clk_src0; + uint32_t emc_pmacro_tx_sel_clk_src1; + uint32_t emc_pmacro_tx_sel_clk_src2; + uint32_t emc_pmacro_tx_sel_clk_src3; + uint32_t emc_pmacro_tx_sel_clk_src4; + uint32_t emc_pmacro_tx_sel_clk_src5; + + uint32_t emc_pmacro_ddll_bypass; + + uint32_t emc_pmacro_ddll_pwrd0; + uint32_t emc_pmacro_ddll_pwrd1; + uint32_t emc_pmacro_ddll_pwrd2; + + uint32_t emc_pmacro_cmd_ctrl0; + uint32_t emc_pmacro_cmd_ctrl1; + uint32_t emc_pmacro_cmd_ctrl2; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + uint32_t mc_emem_adr_cfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + uint32_t mc_emem_adr_cfg_dev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + uint32_t mc_emem_adr_cfg_dev1; + + uint32_t mc_emem_adr_cfg_channel_mask; + + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG0 */ + uint32_t mc_emem_adr_cfg_bank_mask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + uint32_t mc_emem_adr_cfg_bank_mask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + uint32_t mc_emem_adr_cfg_bank_mask2; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + uint32_t mc_emem_cfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + uint32_t mc_emem_arb_cfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + uint32_t mc_emem_arb_outstanding_req; + + uint32_t emc_emem_arb_refpb_hp_ctrl; + uint32_t emc_emem_arb_refpb_bank_ctrl; + + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + uint32_t mc_emem_arb_timing_rcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + uint32_t mc_emem_arb_timing_rp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + uint32_t mc_emem_arb_timing_rc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + uint32_t mc_emem_arb_timing_ras; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + uint32_t mc_emem_arb_timing_faw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + uint32_t mc_emem_arb_timing_rrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + uint32_t mc_emem_arb_timing_rap2pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + uint32_t mc_emem_arb_timing_wap2pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + uint32_t mc_emem_arb_timing_r2r; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + uint32_t mc_emem_arb_timing_w2w; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + uint32_t mc_emem_arb_timing_r2w; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + uint32_t mc_emem_arb_timing_w2r; + + uint32_t mc_emem_arb_timing_rfcpb; + + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + uint32_t mc_emem_arb_da_turns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + uint32_t mc_emem_arb_da_covers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + uint32_t mc_emem_arb_misc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + uint32_t mc_emem_arb_misc1; + uint32_t mc_emem_arb_misc2; + + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + uint32_t mc_emem_arb_ring1_throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + uint32_t mc_emem_arb_override; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + uint32_t mc_emem_arb_override1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + uint32_t mc_emem_arb_rsv; + + uint32_t mc_da_cfg0; + uint32_t mc_emem_arb_timing_ccdmw; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + uint32_t mc_clken_override; + + /* Specifies the value for MC_STAT_CONTROL */ + uint32_t mc_stat_control; + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + uint32_t mc_video_protect_bom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + uint32_t mc_video_protect_bom_adr_hi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + uint32_t mc_video_protect_size_mb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + uint32_t mc_video_protect_vpr_override; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + uint32_t mc_video_protect_vpr_override1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + uint32_t mc_video_protect_gpu_override0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + uint32_t mc_video_protect_gpu_override1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + uint32_t mc_sec_carveout_bom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + uint32_t mc_sec_carveout_adr_hi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + uint32_t mc_sec_carveout_size_mb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL.VIDEO_PROTECT_WRITE_ACCESS */ + uint32_t mc_video_protect_write_access; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL.SEC_CARVEOUT_WRITE_ACCESS */ + uint32_t mc_sec_carveout_protect_write_access; + + uint32_t mc_generalized_carveout1_bom; + uint32_t mc_generalized_carveout1_bom_hi; + uint32_t mc_generalized_carveout1_size_128kb; + uint32_t mc_generalized_carveout1_access0; + uint32_t mc_generalized_carveout1_access1; + uint32_t mc_generalized_carveout1_access2; + uint32_t mc_generalized_carveout1_access3; + uint32_t mc_generalized_carveout1_access4; + uint32_t mc_generalized_carveout1_force_internal_access0; + uint32_t mc_generalized_carveout1_force_internal_access1; + uint32_t mc_generalized_carveout1_force_internal_access2; + uint32_t mc_generalized_carveout1_force_internal_access3; + uint32_t mc_generalized_carveout1_force_internal_access4; + uint32_t mc_generalized_carveout1_cfg0; + + uint32_t mc_generalized_carveout2_bom; + uint32_t mc_generalized_carveout2_bom_hi; + uint32_t mc_generalized_carveout2_size_128kb; + uint32_t mc_generalized_carveout2_access0; + uint32_t mc_generalized_carveout2_access1; + uint32_t mc_generalized_carveout2_access2; + uint32_t mc_generalized_carveout2_access3; + uint32_t mc_generalized_carveout2_access4; + uint32_t mc_generalized_carveout2_force_internal_access0; + uint32_t mc_generalized_carveout2_force_internal_access1; + uint32_t mc_generalized_carveout2_force_internal_access2; + uint32_t mc_generalized_carveout2_force_internal_access3; + uint32_t mc_generalized_carveout2_force_internal_access4; + uint32_t mc_generalized_carveout2_cfg0; + + uint32_t mc_generalized_carveout3_bom; + uint32_t mc_generalized_carveout3_bom_hi; + uint32_t mc_generalized_carveout3_size_128kb; + uint32_t mc_generalized_carveout3_access0; + uint32_t mc_generalized_carveout3_access1; + uint32_t mc_generalized_carveout3_access2; + uint32_t mc_generalized_carveout3_access3; + uint32_t mc_generalized_carveout3_access4; + uint32_t mc_generalized_carveout3_force_internal_access0; + uint32_t mc_generalized_carveout3_force_internal_access1; + uint32_t mc_generalized_carveout3_force_internal_access2; + uint32_t mc_generalized_carveout3_force_internal_access3; + uint32_t mc_generalized_carveout3_force_internal_access4; + uint32_t mc_generalized_carveout3_cfg0; + + uint32_t mc_generalized_carveout4_bom; + uint32_t mc_generalized_carveout4_bom_hi; + uint32_t mc_generalized_carveout4_size_128kb; + uint32_t mc_generalized_carveout4_access0; + uint32_t mc_generalized_carveout4_access1; + uint32_t mc_generalized_carveout4_access2; + uint32_t mc_generalized_carveout4_access3; + uint32_t mc_generalized_carveout4_access4; + uint32_t mc_generalized_carveout4_force_internal_access0; + uint32_t mc_generalized_carveout4_force_internal_access1; + uint32_t mc_generalized_carveout4_force_internal_access2; + uint32_t mc_generalized_carveout4_force_internal_access3; + uint32_t mc_generalized_carveout4_force_internal_access4; + uint32_t mc_generalized_carveout4_cfg0; + + uint32_t mc_generalized_carveout5_bom; + uint32_t mc_generalized_carveout5_bom_hi; + uint32_t mc_generalized_carveout5_size_128kb; + uint32_t mc_generalized_carveout5_access0; + uint32_t mc_generalized_carveout5_access1; + uint32_t mc_generalized_carveout5_access2; + uint32_t mc_generalized_carveout5_access3; + uint32_t mc_generalized_carveout5_access4; + uint32_t mc_generalized_carveout5_force_internal_access0; + uint32_t mc_generalized_carveout5_force_internal_access1; + uint32_t mc_generalized_carveout5_force_internal_access2; + uint32_t mc_generalized_carveout5_force_internal_access3; + uint32_t mc_generalized_carveout5_force_internal_access4; + uint32_t mc_generalized_carveout5_cfg0; + + /* Specifies enable for CA training */ + uint32_t emc_ca_training_enable; + /* Set if bit 6 select is greater than bit 7 select; uses aremc.spec packet SWIZZLE_BIT6_GT_BIT7 */ + uint32_t swizzle_rank_byte_encode; + /* Specifies enable and offset for patched boot rom write */ + uint32_t boot_rom_patch_control; + /* Specifies data for patched boot rom write */ + uint32_t boot_rom_patch_data; + + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + uint32_t mc_mts_carveout_bom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + uint32_t mc_mts_carveout_adr_hi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + uint32_t mc_mts_carveout_size_mb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + uint32_t mc_mts_carveout_reg_ctrl; +} sdram_params_t; + +#endif diff --git a/sept/sept-secondary/src/sdram_param_t210_lp0.h b/sept/sept-secondary/src/sdram_param_t210_lp0.h new file mode 100644 index 000000000..0a1d41840 --- /dev/null +++ b/sept/sept-secondary/src/sdram_param_t210_lp0.h @@ -0,0 +1,964 @@ +/* + * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved. + * Copyright 2014 Google Inc. + * Copyright (c) 2018 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/** + * Defines the SDRAM parameter structure. + * + * Note that PLLM is used by EMC. The field names are in camel case to ease + * directly converting BCT config files (*.cfg) into C structure. + */ + +#ifndef __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ +#define __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ + +#include <stdint.h> + +enum +{ + /* Specifies the memory type to be undefined */ + NvBootMemoryType_None = 0, + + /* Specifies the memory type to be DDR SDRAM */ + NvBootMemoryType_Ddr = 0, + + /* Specifies the memory type to be LPDDR SDRAM */ + NvBootMemoryType_LpDdr = 0, + + /* Specifies the memory type to be DDR2 SDRAM */ + NvBootMemoryType_Ddr2 = 0, + + /* Specifies the memory type to be LPDDR2 SDRAM */ + NvBootMemoryType_LpDdr2, + + /* Specifies the memory type to be DDR3 SDRAM */ + NvBootMemoryType_Ddr3, + + /* Specifies the memory type to be LPDDR4 SDRAM */ + NvBootMemoryType_LpDdr4, + + NvBootMemoryType_Num, + + /* Specifies an entry in the ram_code table that's not in use */ + NvBootMemoryType_Unused = 0X7FFFFFF, +}; + +/** + * Defines the SDRAM parameter structure + */ +struct sdram_params +{ + + /* Specifies the type of memory device */ + uint32_t MemoryType; + + /* MC/EMC clock source configuration */ + + /* Specifies the M value for PllM */ + uint32_t PllMInputDivider; + /* Specifies the N value for PllM */ + uint32_t PllMFeedbackDivider; + /* Specifies the time to wait for PLLM to lock (in microseconds) */ + uint32_t PllMStableTime; + /* Specifies misc. control bits */ + uint32_t PllMSetupControl; + /* Specifies the P value for PLLM */ + uint32_t PllMPostDivider; + /* Specifies value for Charge Pump Gain Control */ + uint32_t PllMKCP; + /* Specifies VCO gain */ + uint32_t PllMKVCO; + /* Spare BCT param */ + uint32_t EmcBctSpare0; + /* Spare BCT param */ + uint32_t EmcBctSpare1; + /* Spare BCT param */ + uint32_t EmcBctSpare2; + /* Spare BCT param */ + uint32_t EmcBctSpare3; + /* Spare BCT param */ + uint32_t EmcBctSpare4; + /* Spare BCT param */ + uint32_t EmcBctSpare5; + /* Spare BCT param */ + uint32_t EmcBctSpare6; + /* Spare BCT param */ + uint32_t EmcBctSpare7; + /* Spare BCT param */ + uint32_t EmcBctSpare8; + /* Spare BCT param */ + uint32_t EmcBctSpare9; + /* Spare BCT param */ + uint32_t EmcBctSpare10; + /* Spare BCT param */ + uint32_t EmcBctSpare11; + /* Spare BCT param */ + uint32_t EmcBctSpare12; + /* Spare BCT param */ + uint32_t EmcBctSpare13; + + /* Defines EMC_2X_CLK_SRC, EMC_2X_CLK_DIVISOR, EMC_INVERT_DCD */ + uint32_t EmcClockSource; + uint32_t EmcClockSourceDll; + + /* Defines possible override for PLLLM_MISC2 */ + uint32_t ClkRstControllerPllmMisc2Override; + /* enables override for PLLLM_MISC2 */ + uint32_t ClkRstControllerPllmMisc2OverrideEnable; + /* defines CLK_ENB_MC1 in register clk_rst_controller_clk_enb_w_clr */ + uint32_t ClearClk2Mc1; + + /* Auto-calibration of EMC pads */ + + /* Specifies the value for EMC_AUTO_CAL_INTERVAL */ + uint32_t EmcAutoCalInterval; + /* + * Specifies the value for EMC_AUTO_CAL_CONFIG + * Note: Trigger bits are set by the SDRAM code. + */ + uint32_t EmcAutoCalConfig; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG2 */ + uint32_t EmcAutoCalConfig2; + + /* Specifies the value for EMC_AUTO_CAL_CONFIG3 */ + uint32_t EmcAutoCalConfig3; + + /* Specifies the values for EMC_AUTO_CAL_CONFIG4-8 */ + uint32_t EmcAutoCalConfig4; + uint32_t EmcAutoCalConfig5; + uint32_t EmcAutoCalConfig6; + uint32_t EmcAutoCalConfig7; + uint32_t EmcAutoCalConfig8; + + /* Specifies the value for EMC_AUTO_CAL_VREF_SEL_0 */ + uint32_t EmcAutoCalVrefSel0; + uint32_t EmcAutoCalVrefSel1; + + /* Specifies the value for EMC_AUTO_CAL_CHANNEL */ + uint32_t EmcAutoCalChannel; + + /* Specifies the value for EMC_PMACRO_AUTOCAL_CFG_0 */ + uint32_t EmcPmacroAutocalCfg0; + uint32_t EmcPmacroAutocalCfg1; + uint32_t EmcPmacroAutocalCfg2; + uint32_t EmcPmacroRxTerm; + uint32_t EmcPmacroDqTxDrv; + uint32_t EmcPmacroCaTxDrv; + uint32_t EmcPmacroCmdTxDrv; + uint32_t EmcPmacroAutocalCfgCommon; + uint32_t EmcPmacroZctrl; + + /* + * Specifies the time for the calibration + * to stabilize (in microseconds) + */ + uint32_t EmcAutoCalWait; + + uint32_t EmcXm2CompPadCtrl; + uint32_t EmcXm2CompPadCtrl2; + uint32_t EmcXm2CompPadCtrl3; + + /* + * DRAM size information + * Specifies the value for EMC_ADR_CFG + */ + uint32_t EmcAdrCfg; + + /* + * Specifies the time to wait after asserting pin + * CKE (in microseconds) + */ + uint32_t EmcPinProgramWait; + /* Specifies the extra delay before/after pin RESET/CKE command */ + uint32_t EmcPinExtraWait; + + uint32_t EmcPinGpioEn; + uint32_t EmcPinGpio; + + /* + * Specifies the extra delay after the first writing + * of EMC_TIMING_CONTROL + */ + uint32_t EmcTimingControlWait; + + /* Timing parameters required for the SDRAM */ + + /* Specifies the value for EMC_RC */ + uint32_t EmcRc; + /* Specifies the value for EMC_RFC */ + uint32_t EmcRfc; + /* Specifies the value for EMC_RFC_PB */ + uint32_t EmcRfcPb; + /* Specifies the value for EMC_RFC_CTRL2 */ + uint32_t EmcRefctrl2; + /* Specifies the value for EMC_RFC_SLR */ + uint32_t EmcRfcSlr; + /* Specifies the value for EMC_RAS */ + uint32_t EmcRas; + /* Specifies the value for EMC_RP */ + uint32_t EmcRp; + /* Specifies the value for EMC_R2R */ + uint32_t EmcR2r; + /* Specifies the value for EMC_W2W */ + uint32_t EmcW2w; + /* Specifies the value for EMC_R2W */ + uint32_t EmcR2w; + /* Specifies the value for EMC_W2R */ + uint32_t EmcW2r; + /* Specifies the value for EMC_R2P */ + uint32_t EmcR2p; + /* Specifies the value for EMC_W2P */ + uint32_t EmcW2p; + + uint32_t EmcTppd; + uint32_t EmcCcdmw; + + /* Specifies the value for EMC_RD_RCD */ + uint32_t EmcRdRcd; + /* Specifies the value for EMC_WR_RCD */ + uint32_t EmcWrRcd; + /* Specifies the value for EMC_RRD */ + uint32_t EmcRrd; + /* Specifies the value for EMC_REXT */ + uint32_t EmcRext; + /* Specifies the value for EMC_WEXT */ + uint32_t EmcWext; + /* Specifies the value for EMC_WDV */ + uint32_t EmcWdv; + + uint32_t EmcWdvChk; + uint32_t EmcWsv; + uint32_t EmcWev; + + /* Specifies the value for EMC_WDV_MASK */ + uint32_t EmcWdvMask; + + uint32_t EmcWsDuration; + uint32_t EmcWeDuration; + + /* Specifies the value for EMC_QUSE */ + uint32_t EmcQUse; + /* Specifies the value for EMC_QUSE_WIDTH */ + uint32_t EmcQuseWidth; + /* Specifies the value for EMC_IBDLY */ + uint32_t EmcIbdly; + /* Specifies the value for EMC_OBDLY */ + uint32_t EmcObdly; + /* Specifies the value for EMC_EINPUT */ + uint32_t EmcEInput; + /* Specifies the value for EMC_EINPUT_DURATION */ + uint32_t EmcEInputDuration; + /* Specifies the value for EMC_PUTERM_EXTRA */ + uint32_t EmcPutermExtra; + /* Specifies the value for EMC_PUTERM_WIDTH */ + uint32_t EmcPutermWidth; + /* Specifies the value for EMC_PUTERM_ADJ */ + ////uint32_t EmcPutermAdj; + + /* Specifies the value for EMC_QRST */ + uint32_t EmcQRst; + /* Specifies the value for EMC_QSAFE */ + uint32_t EmcQSafe; + /* Specifies the value for EMC_RDV */ + uint32_t EmcRdv; + /* Specifies the value for EMC_RDV_MASK */ + uint32_t EmcRdvMask; + /* Specifies the value for EMC_RDV_EARLY */ + uint32_t EmcRdvEarly; + /* Specifies the value for EMC_RDV_EARLY_MASK */ + uint32_t EmcRdvEarlyMask; + /* Specifies the value for EMC_QPOP */ + uint32_t EmcQpop; + + /* Specifies the value for EMC_REFRESH */ + uint32_t EmcRefresh; + /* Specifies the value for EMC_BURST_REFRESH_NUM */ + uint32_t EmcBurstRefreshNum; + /* Specifies the value for EMC_PRE_REFRESH_REQ_CNT */ + uint32_t EmcPreRefreshReqCnt; + /* Specifies the value for EMC_PDEX2WR */ + uint32_t EmcPdEx2Wr; + /* Specifies the value for EMC_PDEX2RD */ + uint32_t EmcPdEx2Rd; + /* Specifies the value for EMC_PCHG2PDEN */ + uint32_t EmcPChg2Pden; + /* Specifies the value for EMC_ACT2PDEN */ + uint32_t EmcAct2Pden; + /* Specifies the value for EMC_AR2PDEN */ + uint32_t EmcAr2Pden; + /* Specifies the value for EMC_RW2PDEN */ + uint32_t EmcRw2Pden; + /* Specifies the value for EMC_CKE2PDEN */ + uint32_t EmcCke2Pden; + /* Specifies the value for EMC_PDEX2CKE */ + uint32_t EmcPdex2Cke; + /* Specifies the value for EMC_PDEX2MRR */ + uint32_t EmcPdex2Mrr; + /* Specifies the value for EMC_TXSR */ + uint32_t EmcTxsr; + /* Specifies the value for EMC_TXSRDLL */ + uint32_t EmcTxsrDll; + /* Specifies the value for EMC_TCKE */ + uint32_t EmcTcke; + /* Specifies the value for EMC_TCKESR */ + uint32_t EmcTckesr; + /* Specifies the value for EMC_TPD */ + uint32_t EmcTpd; + /* Specifies the value for EMC_TFAW */ + uint32_t EmcTfaw; + /* Specifies the value for EMC_TRPAB */ + uint32_t EmcTrpab; + /* Specifies the value for EMC_TCLKSTABLE */ + uint32_t EmcTClkStable; + /* Specifies the value for EMC_TCLKSTOP */ + uint32_t EmcTClkStop; + /* Specifies the value for EMC_TREFBW */ + uint32_t EmcTRefBw; + + /* FBIO configuration values */ + + /* Specifies the value for EMC_FBIO_CFG5 */ + uint32_t EmcFbioCfg5; + /* Specifies the value for EMC_FBIO_CFG7 */ + uint32_t EmcFbioCfg7; + /* Specifies the value for EMC_FBIO_CFG8 */ + uint32_t EmcFbioCfg8; + + /* Command mapping for CMD brick 0 */ + uint32_t EmcCmdMappingCmd0_0; + uint32_t EmcCmdMappingCmd0_1; + uint32_t EmcCmdMappingCmd0_2; + uint32_t EmcCmdMappingCmd1_0; + uint32_t EmcCmdMappingCmd1_1; + uint32_t EmcCmdMappingCmd1_2; + uint32_t EmcCmdMappingCmd2_0; + uint32_t EmcCmdMappingCmd2_1; + uint32_t EmcCmdMappingCmd2_2; + uint32_t EmcCmdMappingCmd3_0; + uint32_t EmcCmdMappingCmd3_1; + uint32_t EmcCmdMappingCmd3_2; + uint32_t EmcCmdMappingByte; + + /* Specifies the value for EMC_FBIO_SPARE */ + uint32_t EmcFbioSpare; + + /* Specifies the value for EMC_CFG_RSV */ + uint32_t EmcCfgRsv; + + /* MRS command values */ + + /* Specifies the value for EMC_MRS */ + uint32_t EmcMrs; + /* Specifies the MP0 command to initialize mode registers */ + uint32_t EmcEmrs; + /* Specifies the MP2 command to initialize mode registers */ + uint32_t EmcEmrs2; + /* Specifies the MP3 command to initialize mode registers */ + uint32_t EmcEmrs3; + /* Specifies the programming to LPDDR2 Mode Register 1 at cold boot */ + uint32_t EmcMrw1; + /* Specifies the programming to LPDDR2 Mode Register 2 at cold boot */ + uint32_t EmcMrw2; + /* Specifies the programming to LPDDR2 Mode Register 3 at cold boot */ + uint32_t EmcMrw3; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t EmcMrw4; + /* Specifies the programming to LPDDR2 Mode Register 3? at cold boot */ + uint32_t EmcMrw6; + /* Specifies the programming to LPDDR2 Mode Register 11 at cold boot */ + uint32_t EmcMrw8; + /* Specifies the programming to LPDDR2 Mode Register 11? at cold boot */ + uint32_t EmcMrw9; + /* Specifies the programming to LPDDR2 Mode Register 12 at cold boot */ + uint32_t EmcMrw10; + /* Specifies the programming to LPDDR2 Mode Register 14 at cold boot */ + uint32_t EmcMrw12; + /* Specifies the programming to LPDDR2 Mode Register 14? at cold boot */ + uint32_t EmcMrw13; + /* Specifies the programming to LPDDR2 Mode Register 22 at cold boot */ + uint32_t EmcMrw14; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at cold boot + */ + uint32_t EmcMrwExtra; + /* + * Specifies the programming to extra LPDDR2 Mode Register + * at warm boot + */ + uint32_t EmcWarmBootMrwExtra; + /* + * Specify the enable of extra Mode Register programming at + * warm boot + */ + uint32_t EmcWarmBootExtraModeRegWriteEnable; + /* + * Specify the enable of extra Mode Register programming at + * cold boot + */ + uint32_t EmcExtraModeRegWriteEnable; + + /* Specifies the EMC_MRW reset command value */ + uint32_t EmcMrwResetCommand; + /* Specifies the EMC Reset wait time (in microseconds) */ + uint32_t EmcMrwResetNInitWait; + /* Specifies the value for EMC_MRS_WAIT_CNT */ + uint32_t EmcMrsWaitCnt; + /* Specifies the value for EMC_MRS_WAIT_CNT2 */ + uint32_t EmcMrsWaitCnt2; + + /* EMC miscellaneous configurations */ + + /* Specifies the value for EMC_CFG */ + uint32_t EmcCfg; + /* Specifies the value for EMC_CFG_2 */ + uint32_t EmcCfg2; + /* Specifies the pipe bypass controls */ + uint32_t EmcCfgPipe; + uint32_t EmcCfgPipeClk; + uint32_t EmcFdpdCtrlCmdNoRamp; + uint32_t EmcCfgUpdate; + + /* Specifies the value for EMC_DBG */ + uint32_t EmcDbg; + uint32_t EmcDbgWriteMux; + + /* Specifies the value for EMC_CMDQ */ + uint32_t EmcCmdQ; + /* Specifies the value for EMC_MC2EMCQ */ + uint32_t EmcMc2EmcQ; + /* Specifies the value for EMC_DYN_SELF_REF_CONTROL */ + uint32_t EmcDynSelfRefControl; + + /* Specifies the value for MEM_INIT_DONE */ + uint32_t AhbArbitrationXbarCtrlMemInitDone; + + /* Specifies the value for EMC_CFG_DIG_DLL */ + uint32_t EmcCfgDigDll; + uint32_t EmcCfgDigDll_1; + /* Specifies the value for EMC_CFG_DIG_DLL_PERIOD */ + uint32_t EmcCfgDigDllPeriod; + /* Specifies the value of *DEV_SELECTN of various EMC registers */ + uint32_t EmcDevSelect; + + /* Specifies the value for EMC_SEL_DPD_CTRL */ + uint32_t EmcSelDpdCtrl; + + /* Pads trimmer delays */ + uint32_t EmcFdpdCtrlDq; + uint32_t EmcFdpdCtrlCmd; + uint32_t EmcPmacroIbVrefDq_0; + uint32_t EmcPmacroIbVrefDq_1; + uint32_t EmcPmacroIbVrefDqs_0; + uint32_t EmcPmacroIbVrefDqs_1; + uint32_t EmcPmacroIbRxrt; + uint32_t EmcCfgPipe1; + uint32_t EmcCfgPipe2; + + /* Specifies the value for EMC_PMACRO_QUSE_DDLL_RANK0_0 */ + uint32_t EmcPmacroQuseDdllRank0_0; + uint32_t EmcPmacroQuseDdllRank0_1; + uint32_t EmcPmacroQuseDdllRank0_2; + uint32_t EmcPmacroQuseDdllRank0_3; + uint32_t EmcPmacroQuseDdllRank0_4; + uint32_t EmcPmacroQuseDdllRank0_5; + uint32_t EmcPmacroQuseDdllRank1_0; + uint32_t EmcPmacroQuseDdllRank1_1; + uint32_t EmcPmacroQuseDdllRank1_2; + uint32_t EmcPmacroQuseDdllRank1_3; + uint32_t EmcPmacroQuseDdllRank1_4; + uint32_t EmcPmacroQuseDdllRank1_5; + + uint32_t EmcPmacroObDdllLongDqRank0_0; + uint32_t EmcPmacroObDdllLongDqRank0_1; + uint32_t EmcPmacroObDdllLongDqRank0_2; + uint32_t EmcPmacroObDdllLongDqRank0_3; + uint32_t EmcPmacroObDdllLongDqRank0_4; + uint32_t EmcPmacroObDdllLongDqRank0_5; + uint32_t EmcPmacroObDdllLongDqRank1_0; + uint32_t EmcPmacroObDdllLongDqRank1_1; + uint32_t EmcPmacroObDdllLongDqRank1_2; + uint32_t EmcPmacroObDdllLongDqRank1_3; + uint32_t EmcPmacroObDdllLongDqRank1_4; + uint32_t EmcPmacroObDdllLongDqRank1_5; + + uint32_t EmcPmacroObDdllLongDqsRank0_0; + uint32_t EmcPmacroObDdllLongDqsRank0_1; + uint32_t EmcPmacroObDdllLongDqsRank0_2; + uint32_t EmcPmacroObDdllLongDqsRank0_3; + uint32_t EmcPmacroObDdllLongDqsRank0_4; + uint32_t EmcPmacroObDdllLongDqsRank0_5; + uint32_t EmcPmacroObDdllLongDqsRank1_0; + uint32_t EmcPmacroObDdllLongDqsRank1_1; + uint32_t EmcPmacroObDdllLongDqsRank1_2; + uint32_t EmcPmacroObDdllLongDqsRank1_3; + uint32_t EmcPmacroObDdllLongDqsRank1_4; + uint32_t EmcPmacroObDdllLongDqsRank1_5; + + uint32_t EmcPmacroIbDdllLongDqsRank0_0; + uint32_t EmcPmacroIbDdllLongDqsRank0_1; + uint32_t EmcPmacroIbDdllLongDqsRank0_2; + uint32_t EmcPmacroIbDdllLongDqsRank0_3; + uint32_t EmcPmacroIbDdllLongDqsRank1_0; + uint32_t EmcPmacroIbDdllLongDqsRank1_1; + uint32_t EmcPmacroIbDdllLongDqsRank1_2; + uint32_t EmcPmacroIbDdllLongDqsRank1_3; + + uint32_t EmcPmacroDdllLongCmd_0; + uint32_t EmcPmacroDdllLongCmd_1; + uint32_t EmcPmacroDdllLongCmd_2; + uint32_t EmcPmacroDdllLongCmd_3; + uint32_t EmcPmacroDdllLongCmd_4; + uint32_t EmcPmacroDdllShortCmd_0; + uint32_t EmcPmacroDdllShortCmd_1; + uint32_t EmcPmacroDdllShortCmd_2; + + /* + * Specifies the delay after asserting CKE pin during a WarmBoot0 + * sequence (in microseconds) + */ + uint32_t WarmBootWait; + + /* Specifies the value for EMC_ODT_WRITE */ + uint32_t EmcOdtWrite; + + /* Periodic ZQ calibration */ + + /* + * Specifies the value for EMC_ZCAL_INTERVAL + * Value 0 disables ZQ calibration + */ + uint32_t EmcZcalInterval; + /* Specifies the value for EMC_ZCAL_WAIT_CNT */ + uint32_t EmcZcalWaitCnt; + /* Specifies the value for EMC_ZCAL_MRW_CMD */ + uint32_t EmcZcalMrwCmd; + + /* DRAM initialization sequence flow control */ + + /* Specifies the MRS command value for resetting DLL */ + uint32_t EmcMrsResetDll; + /* Specifies the command for ZQ initialization of device 0 */ + uint32_t EmcZcalInitDev0; + /* Specifies the command for ZQ initialization of device 1 */ + uint32_t EmcZcalInitDev1; + /* + * Specifies the wait time after programming a ZQ initialization + * command (in microseconds) + */ + uint32_t EmcZcalInitWait; + /* + * Specifies the enable for ZQ calibration at cold boot [bit 0] + * and warm boot [bit 1] + */ + uint32_t EmcZcalWarmColdBootEnables; + + /* + * Specifies the MRW command to LPDDR2 for ZQ calibration + * on warmboot + */ + /* Is issued to both devices separately */ + uint32_t EmcMrwLpddr2ZcalWarmBoot; + /* + * Specifies the ZQ command to DDR3 for ZQ calibration on warmboot + * Is issued to both devices separately + */ + uint32_t EmcZqCalDdr3WarmBoot; + uint32_t EmcZqCalLpDdr4WarmBoot; + /* + * Specifies the wait time for ZQ calibration on warmboot + * (in microseconds) + */ + uint32_t EmcZcalWarmBootWait; + /* + * Specifies the enable for DRAM Mode Register programming + * at warm boot + */ + uint32_t EmcMrsWarmBootEnable; + /* + * Specifies the wait time after sending an MRS DLL reset command + * in microseconds) + */ + uint32_t EmcMrsResetDllWait; + /* Specifies the extra MRS command to initialize mode registers */ + uint32_t EmcMrsExtra; + /* Specifies the extra MRS command at warm boot */ + uint32_t EmcWarmBootMrsExtra; + /* Specifies the EMRS command to enable the DDR2 DLL */ + uint32_t EmcEmrsDdr2DllEnable; + /* Specifies the MRS command to reset the DDR2 DLL */ + uint32_t EmcMrsDdr2DllReset; + /* Specifies the EMRS command to set OCD calibration */ + uint32_t EmcEmrsDdr2OcdCalib; + /* + * Specifies the wait between initializing DDR and setting OCD + * calibration (in microseconds) + */ + uint32_t EmcDdr2Wait; + /* Specifies the value for EMC_CLKEN_OVERRIDE */ + uint32_t EmcClkenOverride; + + /* + * Specifies LOG2 of the extra refresh numbers after booting + * Program 0 to disable + */ + uint32_t EmcExtraRefreshNum; + /* Specifies the master override for all EMC clocks */ + uint32_t EmcClkenOverrideAllWarmBoot; + /* Specifies the master override for all MC clocks */ + uint32_t McClkenOverrideAllWarmBoot; + /* Specifies digital dll period, choosing between 4 to 64 ms */ + uint32_t EmcCfgDigDllPeriodWarmBoot; + + /* Pad controls */ + + /* Specifies the value for PMC_VDDP_SEL */ + uint32_t PmcVddpSel; + /* Specifies the wait time after programming PMC_VDDP_SEL */ + uint32_t PmcVddpSelWait; + /* Specifies the value for PMC_DDR_PWR */ + uint32_t PmcDdrPwr; + /* Specifies the value for PMC_DDR_CFG */ + uint32_t PmcDdrCfg; + /* Specifies the value for PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3Req; + /* Specifies the wait time after programming PMC_IO_DPD3_REQ */ + uint32_t PmcIoDpd3ReqWait; + uint32_t PmcIoDpd4ReqWait; + + /* Specifies the value for PMC_REG_SHORT */ + uint32_t PmcRegShort; + /* Specifies the value for PMC_NO_IOPOWER */ + uint32_t PmcNoIoPower; + + uint32_t PmcDdrCntrlWait; + uint32_t PmcDdrCntrl; + + /* Specifies the value for EMC_ACPD_CONTROL */ + uint32_t EmcAcpdControl; + + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE_CFG */ + ////uint32_t EmcSwizzleRank0ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE0 */ + uint32_t EmcSwizzleRank0Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE1 */ + uint32_t EmcSwizzleRank0Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE2 */ + uint32_t EmcSwizzleRank0Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK0_BYTE3 */ + uint32_t EmcSwizzleRank0Byte3; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE_CFG */ + ////uint32_t EmcSwizzleRank1ByteCfg; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE0 */ + uint32_t EmcSwizzleRank1Byte0; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE1 */ + uint32_t EmcSwizzleRank1Byte1; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE2 */ + uint32_t EmcSwizzleRank1Byte2; + /* Specifies the value for EMC_SWIZZLE_RANK1_BYTE3 */ + uint32_t EmcSwizzleRank1Byte3; + + /* Specifies the value for EMC_TXDSRVTTGEN */ + uint32_t EmcTxdsrvttgen; + + /* Specifies the value for EMC_DATA_BRLSHFT_0 */ + uint32_t EmcDataBrlshft0; + uint32_t EmcDataBrlshft1; + + uint32_t EmcDqsBrlshft0; + uint32_t EmcDqsBrlshft1; + + uint32_t EmcCmdBrlshft0; + uint32_t EmcCmdBrlshft1; + uint32_t EmcCmdBrlshft2; + uint32_t EmcCmdBrlshft3; + + uint32_t EmcQuseBrlshft0; + uint32_t EmcQuseBrlshft1; + uint32_t EmcQuseBrlshft2; + uint32_t EmcQuseBrlshft3; + + uint32_t EmcDllCfg0; + uint32_t EmcDllCfg1; + + uint32_t EmcPmcScratch1; + uint32_t EmcPmcScratch2; + uint32_t EmcPmcScratch3; + + uint32_t EmcPmacroPadCfgCtrl; + + uint32_t EmcPmacroVttgenCtrl0; + uint32_t EmcPmacroVttgenCtrl1; + uint32_t EmcPmacroVttgenCtrl2; + + uint32_t EmcPmacroBrickCtrlRfu1; + uint32_t EmcPmacroCmdBrickCtrlFdpd; + uint32_t EmcPmacroBrickCtrlRfu2; + uint32_t EmcPmacroDataBrickCtrlFdpd; + uint32_t EmcPmacroBgBiasCtrl0; + uint32_t EmcPmacroDataPadRxCtrl; + uint32_t EmcPmacroCmdPadRxCtrl; + uint32_t EmcPmacroDataRxTermMode; + uint32_t EmcPmacroCmdRxTermMode; + uint32_t EmcPmacroDataPadTxCtrl; + uint32_t EmcPmacroCommonPadTxCtrl; + uint32_t EmcPmacroCmdPadTxCtrl; + uint32_t EmcCfg3; + + uint32_t EmcPmacroTxPwrd0; + uint32_t EmcPmacroTxPwrd1; + uint32_t EmcPmacroTxPwrd2; + uint32_t EmcPmacroTxPwrd3; + uint32_t EmcPmacroTxPwrd4; + uint32_t EmcPmacroTxPwrd5; + + uint32_t EmcConfigSampleDelay; + + uint32_t EmcPmacroBrickMapping0; + uint32_t EmcPmacroBrickMapping1; + uint32_t EmcPmacroBrickMapping2; + + uint32_t EmcPmacroTxSelClkSrc0; + uint32_t EmcPmacroTxSelClkSrc1; + uint32_t EmcPmacroTxSelClkSrc2; + uint32_t EmcPmacroTxSelClkSrc3; + uint32_t EmcPmacroTxSelClkSrc4; + uint32_t EmcPmacroTxSelClkSrc5; + + uint32_t EmcPmacroDdllBypass; + + uint32_t EmcPmacroDdllPwrd0; + uint32_t EmcPmacroDdllPwrd1; + uint32_t EmcPmacroDdllPwrd2; + + uint32_t EmcPmacroCmdCtrl0; + uint32_t EmcPmacroCmdCtrl1; + uint32_t EmcPmacroCmdCtrl2; + + /* DRAM size information */ + + /* Specifies the value for MC_EMEM_ADR_CFG */ + uint32_t McEmemAdrCfg; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV0 */ + uint32_t McEmemAdrCfgDev0; + /* Specifies the value for MC_EMEM_ADR_CFG_DEV1 */ + uint32_t McEmemAdrCfgDev1; + uint32_t McEmemAdrCfgChannelMask; + + /* Specifies the value for MC_EMEM_BANK_SWIZZLECfg0 */ + uint32_t McEmemAdrCfgBankMask0; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG1 */ + uint32_t McEmemAdrCfgBankMask1; + /* Specifies the value for MC_EMEM_BANK_SWIZZLE_CFG2 */ + uint32_t McEmemAdrCfgBankMask2; + + /* + * Specifies the value for MC_EMEM_CFG which holds the external memory + * size (in KBytes) + */ + uint32_t McEmemCfg; + + /* MC arbitration configuration */ + + /* Specifies the value for MC_EMEM_ARB_CFG */ + uint32_t McEmemArbCfg; + /* Specifies the value for MC_EMEM_ARB_OUTSTANDING_REQ */ + uint32_t McEmemArbOutstandingReq; + + uint32_t McEmemArbRefpbHpCtrl; + uint32_t McEmemArbRefpbBankCtrl; + + /* Specifies the value for MC_EMEM_ARB_TIMING_RCD */ + uint32_t McEmemArbTimingRcd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RP */ + uint32_t McEmemArbTimingRp; + /* Specifies the value for MC_EMEM_ARB_TIMING_RC */ + uint32_t McEmemArbTimingRc; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAS */ + uint32_t McEmemArbTimingRas; + /* Specifies the value for MC_EMEM_ARB_TIMING_FAW */ + uint32_t McEmemArbTimingFaw; + /* Specifies the value for MC_EMEM_ARB_TIMING_RRD */ + uint32_t McEmemArbTimingRrd; + /* Specifies the value for MC_EMEM_ARB_TIMING_RAP2PRE */ + uint32_t McEmemArbTimingRap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_WAP2PRE */ + uint32_t McEmemArbTimingWap2Pre; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2R */ + uint32_t McEmemArbTimingR2R; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2W */ + uint32_t McEmemArbTimingW2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_R2W */ + uint32_t McEmemArbTimingR2W; + /* Specifies the value for MC_EMEM_ARB_TIMING_W2R */ + uint32_t McEmemArbTimingW2R; + + uint32_t McEmemArbTimingRFCPB; + + /* Specifies the value for MC_EMEM_ARB_DA_TURNS */ + uint32_t McEmemArbDaTurns; + /* Specifies the value for MC_EMEM_ARB_DA_COVERS */ + uint32_t McEmemArbDaCovers; + /* Specifies the value for MC_EMEM_ARB_MISC0 */ + uint32_t McEmemArbMisc0; + /* Specifies the value for MC_EMEM_ARB_MISC1 */ + uint32_t McEmemArbMisc1; + uint32_t McEmemArbMisc2; + + /* Specifies the value for MC_EMEM_ARB_RING1_THROTTLE */ + uint32_t McEmemArbRing1Throttle; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE */ + uint32_t McEmemArbOverride; + /* Specifies the value for MC_EMEM_ARB_OVERRIDE_1 */ + uint32_t McEmemArbOverride1; + /* Specifies the value for MC_EMEM_ARB_RSV */ + uint32_t McEmemArbRsv; + + uint32_t McDaCfg0; + uint32_t McEmemArbTimingCcdmw; + + /* Specifies the value for MC_CLKEN_OVERRIDE */ + uint32_t McClkenOverride; + + /* Specifies the value for MC_STAT_CONTROL */ + uint32_t McStatControl; + + /* Specifies the value for MC_VIDEO_PROTECT_BOM */ + uint32_t McVideoProtectBom; + /* Specifies the value for MC_VIDEO_PROTECT_BOM_ADR_HI */ + uint32_t McVideoProtectBomAdrHi; + /* Specifies the value for MC_VIDEO_PROTECT_SIZE_MB */ + uint32_t McVideoProtectSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE */ + uint32_t McVideoProtectVprOverride; + /* Specifies the value for MC_VIDEO_PROTECT_VPR_OVERRIDE1 */ + uint32_t McVideoProtectVprOverride1; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_0 */ + uint32_t McVideoProtectGpuOverride0; + /* Specifies the value for MC_VIDEO_PROTECT_GPU_OVERRIDE_1 */ + uint32_t McVideoProtectGpuOverride1; + /* Specifies the value for MC_SEC_CARVEOUT_BOM */ + uint32_t McSecCarveoutBom; + /* Specifies the value for MC_SEC_CARVEOUT_ADR_HI */ + uint32_t McSecCarveoutAdrHi; + /* Specifies the value for MC_SEC_CARVEOUT_SIZE_MB */ + uint32_t McSecCarveoutSizeMb; + /* Specifies the value for MC_VIDEO_PROTECT_REG_CTRL. + VIDEO_PROTECT_WRITEAccess */ + uint32_t McVideoProtectWriteAccess; + /* Specifies the value for MC_SEC_CARVEOUT_REG_CTRL. + SEC_CARVEOUT_WRITEAccess */ + uint32_t McSecCarveoutProtectWriteAccess; + + /* Write-Protect Regions (WPR) */ + uint32_t McGeneralizedCarveout1Bom; + uint32_t McGeneralizedCarveout1BomHi; + uint32_t McGeneralizedCarveout1Size128kb; + uint32_t McGeneralizedCarveout1Access0; + uint32_t McGeneralizedCarveout1Access1; + uint32_t McGeneralizedCarveout1Access2; + uint32_t McGeneralizedCarveout1Access3; + uint32_t McGeneralizedCarveout1Access4; + uint32_t McGeneralizedCarveout1ForceInternalAccess0; + uint32_t McGeneralizedCarveout1ForceInternalAccess1; + uint32_t McGeneralizedCarveout1ForceInternalAccess2; + uint32_t McGeneralizedCarveout1ForceInternalAccess3; + uint32_t McGeneralizedCarveout1ForceInternalAccess4; + uint32_t McGeneralizedCarveout1Cfg0; + + uint32_t McGeneralizedCarveout2Bom; + uint32_t McGeneralizedCarveout2BomHi; + uint32_t McGeneralizedCarveout2Size128kb; + uint32_t McGeneralizedCarveout2Access0; + uint32_t McGeneralizedCarveout2Access1; + uint32_t McGeneralizedCarveout2Access2; + uint32_t McGeneralizedCarveout2Access3; + uint32_t McGeneralizedCarveout2Access4; + uint32_t McGeneralizedCarveout2ForceInternalAccess0; + uint32_t McGeneralizedCarveout2ForceInternalAccess1; + uint32_t McGeneralizedCarveout2ForceInternalAccess2; + uint32_t McGeneralizedCarveout2ForceInternalAccess3; + uint32_t McGeneralizedCarveout2ForceInternalAccess4; + uint32_t McGeneralizedCarveout2Cfg0; + + uint32_t McGeneralizedCarveout3Bom; + uint32_t McGeneralizedCarveout3BomHi; + uint32_t McGeneralizedCarveout3Size128kb; + uint32_t McGeneralizedCarveout3Access0; + uint32_t McGeneralizedCarveout3Access1; + uint32_t McGeneralizedCarveout3Access2; + uint32_t McGeneralizedCarveout3Access3; + uint32_t McGeneralizedCarveout3Access4; + uint32_t McGeneralizedCarveout3ForceInternalAccess0; + uint32_t McGeneralizedCarveout3ForceInternalAccess1; + uint32_t McGeneralizedCarveout3ForceInternalAccess2; + uint32_t McGeneralizedCarveout3ForceInternalAccess3; + uint32_t McGeneralizedCarveout3ForceInternalAccess4; + uint32_t McGeneralizedCarveout3Cfg0; + + uint32_t McGeneralizedCarveout4Bom; + uint32_t McGeneralizedCarveout4BomHi; + uint32_t McGeneralizedCarveout4Size128kb; + uint32_t McGeneralizedCarveout4Access0; + uint32_t McGeneralizedCarveout4Access1; + uint32_t McGeneralizedCarveout4Access2; + uint32_t McGeneralizedCarveout4Access3; + uint32_t McGeneralizedCarveout4Access4; + uint32_t McGeneralizedCarveout4ForceInternalAccess0; + uint32_t McGeneralizedCarveout4ForceInternalAccess1; + uint32_t McGeneralizedCarveout4ForceInternalAccess2; + uint32_t McGeneralizedCarveout4ForceInternalAccess3; + uint32_t McGeneralizedCarveout4ForceInternalAccess4; + uint32_t McGeneralizedCarveout4Cfg0; + + uint32_t McGeneralizedCarveout5Bom; + uint32_t McGeneralizedCarveout5BomHi; + uint32_t McGeneralizedCarveout5Size128kb; + uint32_t McGeneralizedCarveout5Access0; + uint32_t McGeneralizedCarveout5Access1; + uint32_t McGeneralizedCarveout5Access2; + uint32_t McGeneralizedCarveout5Access3; + uint32_t McGeneralizedCarveout5Access4; + uint32_t McGeneralizedCarveout5ForceInternalAccess0; + uint32_t McGeneralizedCarveout5ForceInternalAccess1; + uint32_t McGeneralizedCarveout5ForceInternalAccess2; + uint32_t McGeneralizedCarveout5ForceInternalAccess3; + uint32_t McGeneralizedCarveout5ForceInternalAccess4; + uint32_t McGeneralizedCarveout5Cfg0; + + /* Specifies enable for CA training */ + uint32_t EmcCaTrainingEnable; + + /* Set if bit 6 select is greater than bit 7 select; uses aremc. + spec packet SWIZZLE_BIT6_GT_BIT7 */ + uint32_t SwizzleRankByteEncode; + /* Specifies enable and offset for patched boot ROM write */ + uint32_t BootRomPatchControl; + /* Specifies data for patched boot ROM write */ + uint32_t BootRomPatchData; + + /* Specifies the value for MC_MTS_CARVEOUT_BOM */ + uint32_t McMtsCarveoutBom; + /* Specifies the value for MC_MTS_CARVEOUT_ADR_HI */ + uint32_t McMtsCarveoutAdrHi; + /* Specifies the value for MC_MTS_CARVEOUT_SIZE_MB */ + uint32_t McMtsCarveoutSizeMb; + /* Specifies the value for MC_MTS_CARVEOUT_REG_CTRL */ + uint32_t McMtsCarveoutRegCtrl; + + /* End */ +}; + +#endif /* __SOC_NVIDIA_TEGRA210_SDRAM_PARAM_H__ */ diff --git a/sept/sept-secondary/src/se.c b/sept/sept-secondary/src/se.c new file mode 100644 index 000000000..d4dbdc498 --- /dev/null +++ b/sept/sept-secondary/src/se.c @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> + +#include "utils.h" +#include "se.h" + +void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size); + +/* Globals for driver. */ +static unsigned int g_se_modulus_sizes[KEYSLOT_RSA_MAX]; +static unsigned int g_se_exp_sizes[KEYSLOT_RSA_MAX]; + +/* Initialize a SE linked list. */ +void NOINLINE ll_init(volatile se_ll_t *ll, void *buffer, size_t size) { + ll->num_entries = 0; /* 1 Entry. */ + + if (buffer != NULL) { + ll->addr_info.address = (uint32_t) get_physical_address(buffer); + ll->addr_info.size = (uint32_t) size; + } else { + ll->addr_info.address = 0; + ll->addr_info.size = 0; + } +} + +void se_check_error_status_reg(void) { + if (se_get_regs()->ERR_STATUS_REG) { + generic_panic(); + } +} + +void se_check_for_error(void) { + volatile tegra_se_t *se = se_get_regs(); + if (se->INT_STATUS_REG & 0x10000 || se->FLAGS_REG & 3 || se->ERR_STATUS_REG) { + generic_panic(); + } +} + +void se_verify_flags_cleared(void) { + if (se_get_regs()->FLAGS_REG & 3) { + generic_panic(); + } +} + +/* Set the flags for an AES keyslot. */ +void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* Misc flags. */ + if (flags & ~0x80) { + se->AES_KEYSLOT_FLAGS[keyslot] = ~flags; + } + + /* Disable keyslot reads. */ + if (flags & 0x80) { + se->AES_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + } +} + +/* Set the flags for an RSA keyslot. */ +void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_RSA_MAX) { + generic_panic(); + } + + /* Misc flags. */ + if (flags & ~0x80) { + /* TODO: Why are flags assigned this way? */ + se->RSA_KEYSLOT_FLAGS[keyslot] = (((flags >> 4) & 4) | (flags & 3)) ^ 7; + } + + /* Disable keyslot reads. */ + if (flags & 0x80) { + se->RSA_KEY_READ_DISABLE_REG &= ~(1 << keyslot); + } +} + +void clear_aes_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* Zero out the whole keyslot and IV. */ + for (unsigned int i = 0; i < 0x10; i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = 0; + } +} + +void clear_rsa_keyslot(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_RSA_MAX) { + generic_panic(); + } + + /* Zero out the whole keyslot. */ + for (unsigned int i = 0; i < 0x40; i++) { + /* Select Keyslot Modulus[i] */ + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i | 0x40; + se->RSA_KEYTABLE_DATA = 0; + } + for (unsigned int i = 0; i < 0x40; i++) { + /* Select Keyslot Expontent[i] */ + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = 0; + } +} + +void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || key_size > KEYSIZE_AES_MAX) { + generic_panic(); + } + + for (size_t i = 0; i < (key_size >> 2); i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | i; + se->AES_KEYTABLE_DATA = read32le(key, 4 * i); + } +} + +void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_RSA_MAX || modulus_size > KEYSIZE_RSA_MAX || exp_size > KEYSIZE_RSA_MAX) { + generic_panic(); + } + + for (size_t i = 0; i < (modulus_size >> 2); i++) { + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | 0x40 | i; + se->RSA_KEYTABLE_DATA = read32be(modulus, (4 * (modulus_size >> 2)) - (4 * i) - 4); + } + + for (size_t i = 0; i < (exp_size >> 2); i++) { + se->RSA_KEYTABLE_ADDR = (keyslot << 7) | i; + se->RSA_KEYTABLE_DATA = read32be(exponent, (4 * (exp_size >> 2)) - (4 * i) - 4); + } + + g_se_modulus_sizes[keyslot] = modulus_size; + g_se_exp_sizes[keyslot] = exp_size; +} + +void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || iv_size > 0x10) { + generic_panic(); + } + + for (size_t i = 0; i < (iv_size >> 2); i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = read32le(iv, 4 * i); + } +} + +void clear_aes_keyslot_iv(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + for (size_t i = 0; i < (0x10 >> 2); i++) { + se->AES_KEYTABLE_ADDR = (keyslot << 4) | 8 | i; + se->AES_KEYTABLE_DATA = 0; + } +} + +void set_se_ctr(const void *ctr) { + for (unsigned int i = 0; i < 4; i++) { + se_get_regs()->CRYPTO_CTR_REG[i] = read32le(ctr, i * 4); + } +} + +void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot_dst >= KEYSLOT_AES_MAX || keyslot_src >= KEYSLOT_AES_MAX || wrapped_key_size > KEYSIZE_AES_MAX) { + generic_panic(); + } + + se->CONFIG_REG = (ALG_AES_DEC | DST_KEYTAB); + se->CRYPTO_REG = keyslot_src << 24; + se->BLOCK_COUNT_REG = 0; + se->CRYPTO_KEYTABLE_DST_REG = keyslot_dst << 8; + + trigger_se_blocking_op(OP_START, NULL, 0, wrapped_key, wrapped_key_size); +} + +void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + uint8_t ALIGN(16) stack_buf[KEYSIZE_RSA_MAX]; + + if (keyslot >= KEYSLOT_RSA_MAX || src_size > KEYSIZE_RSA_MAX || dst_size > KEYSIZE_RSA_MAX) { + generic_panic(); + } + + /* Endian swap the input. */ + for (size_t i = 0; i < src_size; i++) { + stack_buf[i] = *((uint8_t *)src + src_size - i - 1); + } + + se->CONFIG_REG = (ALG_RSA | DST_RSAREG); + se->RSA_CONFIG = keyslot << 24; + se->RSA_KEY_SIZE_REG = (g_se_modulus_sizes[keyslot] >> 6) - 1; + se->RSA_EXP_SIZE_REG = g_se_exp_sizes[keyslot] >> 2; + + trigger_se_blocking_op(OP_START, NULL, 0, stack_buf, src_size); + se_get_exp_mod_output(dst, dst_size); +} + +void se_get_exp_mod_output(void *buf, size_t size) { + size_t num_dwords = (size >> 2); + + if (num_dwords < 1) { + return; + } + + uint32_t *p_out = ((uint32_t *)buf) + num_dwords - 1; + uint32_t offset = 0; + + /* Copy endian swapped output. */ + while (num_dwords) { + *p_out = read32be(se_get_regs()->RSA_OUTPUT, offset); + offset += 4; + p_out--; + num_dwords--; + } +} + +bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size) { + uint8_t message[RSA_2048_BYTES]; + uint8_t h_buf[0x24]; + + /* Hardcode RSA with keyslot 0. */ + const uint8_t public_exponent[4] = {0x00, 0x01, 0x00, 0x01}; + set_rsa_keyslot(0, modulus, modulus_size, public_exponent, sizeof(public_exponent)); + se_synchronous_exp_mod(0, message, sizeof(message), signature, signature_size); + + /* Validate sanity byte. */ + if (message[RSA_2048_BYTES - 1] != 0xBC) { + return false; + } + + /* Copy Salt into MGF1 Hash Buffer. */ + memset(h_buf, 0, sizeof(h_buf)); + memcpy(h_buf, message + RSA_2048_BYTES - 0x20 - 0x1, 0x20); + + /* Decrypt maskedDB (via inline MGF1). */ + uint8_t seed = 0; + uint8_t mgf1_buf[0x20]; + for (unsigned int ofs = 0; ofs < RSA_2048_BYTES - 0x20 - 1; ofs += 0x20) { + h_buf[sizeof(h_buf) - 1] = seed++; + se_calculate_sha256(mgf1_buf, h_buf, sizeof(h_buf)); + for (unsigned int i = ofs; i < ofs + 0x20 && i < RSA_2048_BYTES - 0x20 - 1; i++) { + message[i] ^= mgf1_buf[i - ofs]; + } + } + + /* Constant lmask for rsa-2048-pss. */ + message[0] &= 0x7F; + + /* Validate DB is of the form 0000...0001. */ + for (unsigned int i = 0; i < RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1; i++) { + if (message[i] != 0) { + return false; + } + } + if (message[RSA_2048_BYTES - 0x20 - 0x20 - 1 - 1] != 1) { + return false; + } + + /* Check hash correctness. */ + uint8_t validate_buf[8 + 0x20 + 0x20]; + uint8_t validate_hash[0x20]; + + memset(validate_buf, 0, sizeof(validate_buf)); + se_calculate_sha256(&validate_buf[8], data, data_size); + memcpy(&validate_buf[0x28], &message[RSA_2048_BYTES - 0x20 - 0x20 - 1], 0x20); + se_calculate_sha256(validate_hash, validate_buf, sizeof(validate_buf)); + return memcmp(h_buf, validate_hash, 0x20) == 0; +} + +void trigger_se_blocking_op(unsigned int op, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + se_ll_t in_ll; + se_ll_t out_ll; + + ll_init(&in_ll, (void *)src, src_size); + ll_init(&out_ll, dst, dst_size); + + /* Set the LLs. */ + se->IN_LL_ADDR_REG = (uint32_t) get_physical_address(&in_ll); + se->OUT_LL_ADDR_REG = (uint32_t) get_physical_address(&out_ll); + + /* Set registers for operation. */ + se->ERR_STATUS_REG = se->ERR_STATUS_REG; + se->INT_STATUS_REG = se->INT_STATUS_REG; + se->OPERATION_REG = op; + + while (!(se->INT_STATUS_REG & 0x10)) { /* Wait a while */ } + se_check_for_error(); +} + +/* Secure AES Functionality. */ +void se_perform_aes_block_operation(void *dst, size_t dst_size, const void *src, size_t src_size) { + uint8_t block[0x10] = {0}; + + if (src_size > sizeof(block) || dst_size > sizeof(block)) { + generic_panic(); + } + + /* Load src data into block. */ + if (src_size != 0) { + memcpy(block, src, src_size); + } + + /* Trigger AES operation. */ + se_get_regs()->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, block, sizeof(block), block, sizeof(block)); + + /* Copy output data into dst. */ + if (dst_size != 0) { + memcpy(dst, block, dst_size); + } +} + +void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || ctr_size != 0x10) { + generic_panic(); + } + unsigned int num_blocks = src_size >> 4; + + /* Unknown what this write does, but official code writes it for CTR mode. */ + se->SPARE_0 = 1; + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x91E; + set_se_ctr(ctr); + + /* Handle any aligned blocks. */ + size_t aligned_size = (size_t)num_blocks << 4; + if (aligned_size) { + se->BLOCK_COUNT_REG = num_blocks - 1; + trigger_se_blocking_op(OP_START, dst, dst_size, src, aligned_size); + } + + /* Handle final, unaligned block. */ + if (aligned_size < dst_size && aligned_size < src_size) { + size_t last_block_size = dst_size - aligned_size; + if (src_size < dst_size) { + last_block_size = src_size - aligned_size; + } + se_perform_aes_block_operation(dst + aligned_size, last_block_size, (uint8_t *)src + aligned_size, src_size - aligned_size); + } +} + +void se_aes_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { + generic_panic(); + } + + /* Set configuration high (256-bit vs 128-bit) based on parameter. */ + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (config_high << 16); + se->CRYPTO_REG = keyslot << 24 | 0x100; + se_perform_aes_block_operation(dst, 0x10, src, 0x10); +} + +void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0); +} + +void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + se_aes_ecb_encrypt_block(keyslot, dst, dst_size, src, src_size, 0x202); +} + +void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || dst_size != 0x10 || src_size != 0x10) { + generic_panic(); + } + + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot << 24; + se_perform_aes_block_operation(dst, 0x10, src, 0x10); +} + +void shift_left_xor_rb(uint8_t *key) { + uint8_t prev_high_bit = 0; + for (unsigned int i = 0; i < 0x10; i++) { + uint8_t cur_byte = key[0xF - i]; + key[0xF - i] = (cur_byte << 1) | (prev_high_bit); + prev_high_bit = cur_byte >> 7; + } + if (prev_high_bit) { + key[0xF] ^= 0x87; + } +} + +void shift_left_xor_rb_le(uint8_t *key) { + uint8_t prev_high_bit = 0; + for (unsigned int i = 0; i < 0x10; i++) { + uint8_t cur_byte = key[i]; + key[i] = (cur_byte << 1) | (prev_high_bit); + prev_high_bit = cur_byte >> 7; + } + if (prev_high_bit) { + key[0x0] ^= 0x87; + } +} + +void aes_128_xts_nintendo_get_tweak(uint8_t *tweak, size_t sector) { + for (int i = 0xF; i >= 0; i--) { /* Nintendo LE custom tweak... */ + tweak[i] = (unsigned char)(sector & 0xFF); + sector >>= 8; + } +} + +void aes_128_xts_nintendo_xor_with_tweak(unsigned int keyslot, size_t sector, uint8_t *dst, const uint8_t *src, size_t size) { + if ((size & 0xF) || size == 0) { + generic_panic(); + } + uint8_t tweak[0x10]; + aes_128_xts_nintendo_get_tweak(tweak, sector); + se_aes_128_ecb_encrypt_block(keyslot, tweak, sizeof(tweak), tweak, sizeof(tweak)); + + for (unsigned int block = 0; block < (size >> 4); block++) { + for (unsigned int i = 0; i < 0x10; i++) { + dst[(block << 4) | i] = src[(block << 4) | i] ^ tweak[i]; + } + shift_left_xor_rb_le(tweak); + } +} + +void aes_128_xts_nintendo_crypt_sector(unsigned int keyslot_1, unsigned int keyslot_2, size_t sector, bool encrypt, void *dst, const void *src, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + + if ((size & 0xF) || size == 0) { + generic_panic(); + } + + /* XOR. */ + aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, src, size); + + /* Encrypt/Decrypt. */ + if (encrypt) { + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CRYPTO_REG = keyslot_1 << 24 | 0x100; + } else { + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY); + se->CRYPTO_REG = keyslot_1 << 24; + } + se->BLOCK_COUNT_REG = (size >> 4) - 1; + trigger_se_blocking_op(OP_START, dst, size, src, size); + + /* XOR. */ + aes_128_xts_nintendo_xor_with_tweak(keyslot_2, sector, dst, dst, size); +} + +/* Encrypt with AES-XTS (Nintendo's custom tweak). */ +void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) { + if ((size & 0xF) || size == 0) { + generic_panic(); + } + size_t sector = base_sector; + for (size_t ofs = 0; ofs < size; ofs += sector_size) { + aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, true, dst + ofs, src + ofs, sector_size); + sector++; + } +} + +/* Decrypt with AES-XTS (Nintendo's custom tweak). */ +void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, size_t base_sector, void *dst, const void *src, size_t size, unsigned int sector_size) { + if ((size & 0xF) || size == 0) { + generic_panic(); + } + size_t sector = base_sector; + for (size_t ofs = 0; ofs < size; ofs += sector_size) { + aes_128_xts_nintendo_crypt_sector(keyslot_1, keyslot_2, sector, false, dst + ofs, src + ofs, sector_size); + sector++; + } +} + +void se_compute_aes_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size, unsigned int config_high) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* Generate the derived key, to be XOR'd with final output block. */ + uint8_t ALIGN(16) derived_key[0x10] = {0}; + se_aes_ecb_encrypt_block(keyslot, derived_key, sizeof(derived_key), derived_key, sizeof(derived_key), config_high); + shift_left_xor_rb(derived_key); + if (data_size & 0xF) { + shift_left_xor_rb(derived_key); + } + + se->CONFIG_REG = (ALG_AES_ENC | DST_HASHREG) | (config_high << 16); + se->CRYPTO_REG = (keyslot << 24) | (0x145); + clear_aes_keyslot_iv(keyslot); + + unsigned int num_blocks = (data_size + 0xF) >> 4; + /* Handle aligned blocks. */ + if (num_blocks > 1) { + se->BLOCK_COUNT_REG = num_blocks - 2; + trigger_se_blocking_op(OP_START, NULL, 0, data, data_size); + se->CRYPTO_REG |= 0x80; + } + + /* Create final block. */ + uint8_t ALIGN(16) last_block[0x10] = {0}; + if (data_size & 0xF) { + memcpy(last_block, data + (data_size & ~0xF), data_size & 0xF); + last_block[data_size & 0xF] = 0x80; /* Last block = data || 100...0 */ + } else if (data_size >= 0x10) { + memcpy(last_block, data + data_size - 0x10, 0x10); + } + + for (unsigned int i = 0; i < 0x10; i++) { + last_block[i] ^= derived_key[i]; + } + + /* Perform last operation. */ + se->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, NULL, 0, last_block, sizeof(last_block)); + + /* Copy output CMAC. */ + for (unsigned int i = 0; i < (cmac_size >> 2); i++) { + ((uint32_t *)cmac)[i] = read32le(se->HASH_RESULT_REG, i << 2); + } +} + +void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { + se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0); +} +void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size) { + se_compute_aes_cmac(keyslot, cmac, cmac_size, data, data_size, 0x202); +} + +void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { + generic_panic(); + } + + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY) | (0x202 << 16); + se->CRYPTO_REG = (keyslot << 24) | 0x144; + set_aes_keyslot_iv(keyslot, iv, 0x10); + se->BLOCK_COUNT_REG = (src_size >> 4) - 1; + trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); +} + +/* SHA256 Implementation. */ +void se_calculate_sha256(void *dst, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + + /* Setup config for SHA256, size = BITS(src_size) */ + se->CONFIG_REG = (ENCMODE_SHA256 | ALG_SHA | DST_HASHREG); + se->SHA_CONFIG_REG = 1; + se->SHA_MSG_LENGTH_REG = (uint32_t)(src_size << 3); + se->_0x208 = 0; + se->_0x20C = 0; + se->_0x210 = 0; + se->SHA_MSG_LEFT_REG = (uint32_t)(src_size << 3); + se->_0x218 = 0; + se->_0x21C = 0; + se->_0x220 = 0; + + /* Trigger the operation. */ + trigger_se_blocking_op(OP_START, NULL, 0, src, src_size); + + /* Copy output hash. */ + for (unsigned int i = 0; i < (0x20 >> 2); i++) { + ((uint32_t *)dst)[i] = read32be(se->HASH_RESULT_REG, i << 2); + } +} + +/* RNG API */ +void se_initialize_rng(unsigned int keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* To initialize the RNG, we'll perform an RNG operation into an output buffer. */ + /* This will be discarded, when done. */ + uint8_t ALIGN(16) output_buf[0x10]; + + se->RNG_SRC_CONFIG_REG = 3; /* Entropy enable + Entropy lock enable */ + se->RNG_RESEED_INTERVAL_REG = 70001; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 5; + se->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, output_buf, 0x10, NULL, 0); +} + +void se_generate_random(unsigned int keyslot, void *dst, size_t size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + uint32_t num_blocks = size >> 4; + size_t aligned_size = num_blocks << 4; + se->CONFIG_REG = (ALG_RNG | DST_MEMORY); + se->CRYPTO_REG = (keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 4; + + if (num_blocks >= 1) { + se->BLOCK_COUNT_REG = num_blocks - 1; + trigger_se_blocking_op(OP_START, dst, aligned_size, NULL, 0); + } + if (size > aligned_size) { + se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0); + } +} diff --git a/sept/sept-secondary/src/se.h b/sept/sept-secondary/src/se.h new file mode 100644 index 000000000..64998621a --- /dev/null +++ b/sept/sept-secondary/src/se.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SE_H +#define FUSEE_SE_H + +#define SE_BASE 0x70012000 +#define MAKE_SE_REG(n) MAKE_REG32(SE_BASE + n) + +#define KEYSLOT_SWITCH_LP0TZRAMKEY 0x2 +#define KEYSLOT_SWITCH_SRKGENKEY 0x8 +#define KEYSLOT_SWITCH_PACKAGE2KEY 0x8 +#define KEYSLOT_SWITCH_TEMPKEY 0x9 +#define KEYSLOT_SWITCH_SESSIONKEY 0xA +#define KEYSLOT_SWITCH_RNGKEY 0xB +#define KEYSLOT_SWITCH_MASTERKEY 0xC +#define KEYSLOT_SWITCH_DEVICEKEY 0xD + +/* This keyslot was added in 4.0.0. */ +#define KEYSLOT_SWITCH_4XNEWDEVICEKEYGENKEY 0xD +#define KEYSLOT_SWITCH_4XNEWCONSOLEKEYGENKEY 0xE +#define KEYSLOT_SWITCH_4XOLDDEVICEKEY 0xF + +/* This keyslot was added in 5.0.0. */ +#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA + +#define KEYSLOT_AES_MAX 0x10 +#define KEYSLOT_RSA_MAX 0x2 + +#define KEYSIZE_AES_MAX 0x20 +#define KEYSIZE_RSA_MAX 0x100 + +#define ALG_SHIFT (12) +#define ALG_DEC_SHIFT (8) +#define ALG_NOP (0 << ALG_SHIFT) +#define ALG_AES_ENC (1 << ALG_SHIFT) +#define ALG_AES_DEC ((1 << ALG_DEC_SHIFT) | ALG_NOP) +#define ALG_RNG (2 << ALG_SHIFT) +#define ALG_SHA (3 << ALG_SHIFT) +#define ALG_RSA (4 << ALG_SHIFT) + +#define DST_SHIFT (2) +#define DST_MEMORY (0 << DST_SHIFT) +#define DST_HASHREG (1 << DST_SHIFT) +#define DST_KEYTAB (2 << DST_SHIFT) +#define DST_SRK (3 << DST_SHIFT) +#define DST_RSAREG (4 << DST_SHIFT) + +#define ENCMODE_SHIFT (24) +#define DECMODE_SHIFT (16) +#define ENCMODE_SHA256 (5 << ENCMODE_SHIFT) + +#define HASH_DISABLE (0x0) +#define HASH_ENABLE (0x1) + +#define OP_ABORT 0 +#define OP_START 1 +#define OP_RESTART 2 +#define OP_CTX_SAVE 3 +#define OP_RESTART_IN 4 + +#define CTX_SAVE_SRC_SHIFT 29 +#define CTX_SAVE_SRC_STICKY_BITS (0 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_KEYTABLE_AES (2 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_KEYTABLE_RSA (1 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_MEM (4 << CTX_SAVE_SRC_SHIFT) +#define CTX_SAVE_SRC_SRK (6 << CTX_SAVE_SRC_SHIFT) + +#define CTX_SAVE_KEY_LOW_BITS 0 +#define CTX_SAVE_KEY_HIGH_BITS 1 +#define CTX_SAVE_KEY_ORIGINAL_IV 2 +#define CTX_SAVE_KEY_UPDATED_IV 3 + +#define CTX_SAVE_STICKY_BIT_INDEX_SHIFT 24 +#define CTX_SAVE_KEY_INDEX_SHIFT 8 +#define CTX_SAVE_RSA_KEY_INDEX_SHIFT 16 +#define CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT 12 + +#define RSA_2048_BYTES 0x100 + +typedef struct { + uint32_t _0x0; + uint32_t _0x4; + uint32_t OPERATION_REG; + uint32_t INT_ENABLE_REG; + uint32_t INT_STATUS_REG; + uint32_t CONFIG_REG; + uint32_t IN_LL_ADDR_REG; + uint32_t _0x1C; + uint32_t _0x20; + uint32_t OUT_LL_ADDR_REG; + uint32_t _0x28; + uint32_t _0x2C; + uint8_t HASH_RESULT_REG[0x20]; + uint8_t _0x50[0x20]; + uint32_t CONTEXT_SAVE_CONFIG_REG; + uint8_t _0x74[0x18C]; + uint32_t SHA_CONFIG_REG; + uint32_t SHA_MSG_LENGTH_REG; + uint32_t _0x208; + uint32_t _0x20C; + uint32_t _0x210; + uint32_t SHA_MSG_LEFT_REG; + uint32_t _0x218; + uint32_t _0x21C; + uint32_t _0x220; + uint32_t _0x224; + uint8_t _0x228[0x58]; + uint32_t AES_KEY_READ_DISABLE_REG; + uint32_t AES_KEYSLOT_FLAGS[0x10]; + uint8_t _0x2C4[0x3C]; + uint32_t _0x300; + uint32_t CRYPTO_REG; + uint32_t CRYPTO_CTR_REG[4]; + uint32_t BLOCK_COUNT_REG; + uint32_t AES_KEYTABLE_ADDR; + uint32_t AES_KEYTABLE_DATA; + uint32_t _0x324; + uint32_t _0x328; + uint32_t _0x32C; + uint32_t CRYPTO_KEYTABLE_DST_REG; + uint8_t _0x334[0xC]; + uint32_t RNG_CONFIG_REG; + uint32_t RNG_SRC_CONFIG_REG; + uint32_t RNG_RESEED_INTERVAL_REG; + uint8_t _0x34C[0xB4]; + uint32_t RSA_CONFIG; + uint32_t RSA_KEY_SIZE_REG; + uint32_t RSA_EXP_SIZE_REG; + uint32_t RSA_KEY_READ_DISABLE_REG; + uint32_t RSA_KEYSLOT_FLAGS[2]; + uint32_t _0x418; + uint32_t _0x41C; + uint32_t RSA_KEYTABLE_ADDR; + uint32_t RSA_KEYTABLE_DATA; + uint8_t RSA_OUTPUT[0x100]; + uint8_t _0x528[0x2D8]; + uint32_t FLAGS_REG; + uint32_t ERR_STATUS_REG; + uint32_t _0x808; + uint32_t SPARE_0; + uint32_t _0x810; + uint32_t _0x814; + uint32_t _0x818; + uint32_t _0x81C; + uint8_t _0x820[0x17E0]; +} tegra_se_t; + +typedef struct { + uint32_t address; + uint32_t size; +} se_addr_info_t; + +typedef struct { + uint32_t num_entries; /* Set to total entries - 1 */ + se_addr_info_t addr_info; /* This should really be an array...but for our use case it works. */ +} se_ll_t; + +static inline volatile tegra_se_t *se_get_regs(void) { + return (volatile tegra_se_t *)SE_BASE; +} + +void se_check_error_status_reg(void); +void se_check_for_error(void); +void se_trigger_interrupt(void); + +void se_validate_stored_vector(void); +void se_generate_stored_vector(void); + +void se_verify_flags_cleared(void); + +void set_aes_keyslot_flags(unsigned int keyslot, unsigned int flags); +void set_rsa_keyslot_flags(unsigned int keyslot, unsigned int flags); +void clear_aes_keyslot(unsigned int keyslot); +void clear_rsa_keyslot(unsigned int keyslot); + +void set_aes_keyslot(unsigned int keyslot, const void *key, size_t key_size); +void decrypt_data_into_keyslot(unsigned int keyslot_dst, unsigned int keyslot_src, const void *wrapped_key, size_t wrapped_key_size); +void set_rsa_keyslot(unsigned int keyslot, const void *modulus, size_t modulus_size, const void *exponent, size_t exp_size); +void set_aes_keyslot_iv(unsigned int keyslot, const void *iv, size_t iv_size); +void set_se_ctr(const void *ctr); + +/* Secure AES API */ +void se_aes_128_xts_nintendo_decrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size); +void se_aes_128_xts_nintendo_encrypt(unsigned int keyslot_1, unsigned int keyslot_2, unsigned int base_sector, void *dst, const void *src, size_t size, unsigned int sector_size); +void se_compute_aes_128_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); +void se_compute_aes_256_cmac(unsigned int keyslot, void *cmac, size_t cmac_size, const void *data, size_t data_size); +void se_aes_128_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); +void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); +void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size); +void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); +void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv); + +/* Hash API */ +void se_calculate_sha256(void *dst, const void *src, size_t src_size); + +/* RSA API */ +void se_get_exp_mod_output(void *buf, size_t size); +void se_synchronous_exp_mod(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); +bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const void *modulus, size_t modulus_size, const void *data, size_t data_size); + +/* RNG API */ +void se_initialize_rng(unsigned int keyslot); +void se_generate_random(unsigned int keyslot, void *dst, size_t size); + +#endif diff --git a/sept/sept-secondary/src/stage2.c b/sept/sept-secondary/src/stage2.c new file mode 100644 index 000000000..4d1e1d9da --- /dev/null +++ b/sept/sept-secondary/src/stage2.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "stage2.h" +#include "chainloader.h" +#include "fs_utils.h" +#include "utils.h" + +char g_stage2_path[0x100] = {0}; + +const char *stage2_get_program_path(void) { + return g_stage2_path; +} + +static int stage2_ini_handler(void *user, const char *section, const char *name, const char *value) { + stage2_config_t *config = (stage2_config_t *)user; + uintptr_t x = 0; + if (strcmp(section, "stage1") == 0) { + if (strcmp(name, STAGE2_NAME_KEY) == 0) { + strncpy(config->path, value, sizeof(config->path) - 1); + config->path[sizeof(config->path) - 1] = '\0'; + } else if (strcmp(name, STAGE2_ADDRESS_KEY) == 0) { + /* Read in load address as a hex string. */ + sscanf(value, "%x", &x); + config->load_address = x; + if (config->entrypoint == 0) { + config->entrypoint = config->load_address; + } + } else if (strcmp(name, STAGE2_ENTRYPOINT_KEY) == 0) { + /* Read in entrypoint as a hex string. */ + sscanf(value, "%x", &x); + config->entrypoint = x; + } else { + return 0; + } + } else { + return 0; + } + return 1; +} + +void load_stage2(const char *bct0) { + stage2_config_t config = {0}; + FILINFO info; + size_t size; + uintptr_t tmp_addr; + + if (ini_parse_string(bct0, stage2_ini_handler, &config) < 0) { + fatal_error("Failed to parse BCT.ini!\n"); + } + + if (config.load_address == 0 || config.path[0] == '\x00') { + fatal_error("Failed to determine where to load stage2!\n"); + } + + if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) { + print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n"); + } + + if (!check_32bit_address_loadable(config.entrypoint)) { + fatal_error("Stage2's entrypoint is invalid!\n"); + } + + if (!check_32bit_address_loadable(config.load_address)) { + fatal_error("Stage2's load address is invalid!\n"); + } + + print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n"); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Entrypoint: 0x%p\n", config.entrypoint); + + if (f_stat(config.path, &info) != FR_OK) { + fatal_error("Failed to stat stage2 (%s)!\n", config.path); + } + + size = (size_t)info.fsize; + + /* the LFB is located at 0xC0000000 atm */ + if (size > 0xC0000000u - 0x80000000u) { + fatal_error("Stage2 is way too big!\n"); + } + + if (!check_32bit_address_range_loadable(config.load_address, size)) { + fatal_error("Stage2 has an invalid load address & size combination (0x%08x 0x%08x)!\n", config.load_address, size); + } + + if (config.entrypoint < config.load_address || config.entrypoint >= config.load_address + size) { + fatal_error("Stage2's entrypoint is outside Stage2!\n"); + } + + if (check_32bit_address_range_in_program(config.load_address, size)) { + tmp_addr = 0x80000000u; + } else { + tmp_addr = config.load_address; + } + + if (read_from_file((void *)tmp_addr, size, config.path) != size) { + fatal_error("Failed to read stage2 (%s)!\n", config.path); + } + + g_chainloader_num_entries = 1; + g_chainloader_entries[0].load_address = config.load_address; + g_chainloader_entries[0].src_address = tmp_addr; + g_chainloader_entries[0].size = size; + g_chainloader_entries[0].num = 0; + g_chainloader_entrypoint = config.entrypoint; + + strncpy(g_stage2_path, config.path, sizeof(g_stage2_path) - 1); + g_stage2_path[sizeof(g_stage2_path) - 1] = '\0'; +} diff --git a/sept/sept-secondary/src/stage2.h b/sept/sept-secondary/src/stage2.h new file mode 100644 index 000000000..e453d159f --- /dev/null +++ b/sept/sept-secondary/src/stage2.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_STAGE2_H +#define FUSEE_STAGE2_H + +#include <stdbool.h> +#include <stdint.h> + +#include "display/video_fb.h" +#include "lib/log.h" +#include "lib/vsprintf.h" +#include "lib/ini.h" +#include "lib/fatfs/ff.h" + +/* TODO: Is there a more concise way to do this? */ +#define STAGE2_ARGV_PROGRAM_PATH 0 +#define STAGE2_ARGV_ARGUMENT_STRUCT 1 +#define STAGE2_ARGC 2 + +#define STAGE2_NAME_KEY "stage2_path" +#define STAGE2_ADDRESS_KEY "stage2_addr" +#define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint" +#define BCTO_MAX_SIZE 0x5800 + +typedef struct { + char path[0x100]; + uintptr_t load_address; + uintptr_t entrypoint; +} stage2_config_t; + +typedef struct { + uint32_t version; + ScreenLogLevel log_level; + bool display_initialized; + char bct0[BCTO_MAX_SIZE]; +} stage2_args_t; + +const char *stage2_get_program_path(void); +void load_stage2(const char *bct0); + +#endif diff --git a/sept/sept-secondary/src/start.s b/sept/sept-secondary/src/start.s new file mode 100644 index 000000000..4cfa68003 --- /dev/null +++ b/sept/sept-secondary/src/start.s @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +.macro CLEAR_GPR_REG_ITER + mov r\@, #0 +.endm + +.section .text.start, "ax", %progbits +.arm +.align 5 +.global _start +.type _start, %function +_start: + /* Switch to system mode, mask all interrupts, clear all flags */ + msr cpsr_cxsf, #0xDF + + /* Relocate ourselves if necessary */ + ldr r2, =__start__ + adr r3, _start + cmp r2, r3 + beq _relocation_loop_end + + ldr r4, =_relocation_loop_end + mov r4, #0x1000 + mov r1, #0x0 + _relocation_loop: + ldmia r3!, {r5-r12} + stmia r2!, {r5-r12} + add r1, r1, #0x20 + cmp r1, r4 + bne _relocation_loop + + ldr r12, =_second_relocation_start + bx r12 + + _second_relocation_start: + ldr r4, =__bss_start__ + sub r4, r4, r2 + mov r1, #0x0 + + _second_relocation_loop: + ldmia r3!, {r5-r12} + stmia r2!, {r5-r12} + add r1, r1, #0x20 + cmp r1, r4 + bne _second_relocation_loop + + ldr r12, =_relocation_loop_end + bx r12 + + _relocation_loop_end: + + /* Set the stack pointer */ + ldr sp, =__stack_top__ + mov fp, #0 + bl __program_init + + /* Set r0 to r12 to 0 (for debugging) & call main */ + .rept 13 + CLEAR_GPR_REG_ITER + .endr + ldr lr, =__program_exit + b main + +/* No need to include this in normal programs: */ +.section .chainloader.text.start, "ax", %progbits +.arm +.align 5 +.global relocate_and_chainload +.type relocate_and_chainload, %function +relocate_and_chainload: + ldr sp, =__stack_top__ + b relocate_and_chainload_main diff --git a/sept/sept-secondary/src/sysctr0.h b/sept/sept-secondary/src/sysctr0.h new file mode 100644 index 000000000..f622e70b1 --- /dev/null +++ b/sept/sept-secondary/src/sysctr0.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SYSCTR0_H +#define FUSEE_SYSCTR0_H + +#include <stdint.h> + +#define SYSCTR0_BASE 0x700F0000 +#define MAKE_SYSCTR0_REG(n) MAKE_REG32(SYSCTR0_BASE + n) + +#define SYSCTR0_CNTCR_0 MAKE_SYSCTR0_REG(0x00) +#define SYSCTR0_CNTSR_0 MAKE_SYSCTR0_REG(0x04) +#define SYSCTR0_CNTCV0_0 MAKE_SYSCTR0_REG(0x08) +#define SYSCTR0_CNTCV1_0 MAKE_SYSCTR0_REG(0x0C) +#define SYSCTR0_CNTFID0_0 MAKE_SYSCTR0_REG(0x20) +#define SYSCTR0_CNTFID1_0 MAKE_SYSCTR0_REG(0x24) +#define SYSCTR0_COUNTERID4_0 MAKE_SYSCTR0_REG(0xFD0) +#define SYSCTR0_COUNTERID5_0 MAKE_SYSCTR0_REG(0xFD4) +#define SYSCTR0_COUNTERID6_0 MAKE_SYSCTR0_REG(0xFD8) +#define SYSCTR0_COUNTERID7_0 MAKE_SYSCTR0_REG(0xFDC) +#define SYSCTR0_COUNTERID0_0 MAKE_SYSCTR0_REG(0xFE0) +#define SYSCTR0_COUNTERID1_0 MAKE_SYSCTR0_REG(0xFE4) +#define SYSCTR0_COUNTERID2_0 MAKE_SYSCTR0_REG(0xFE8) +#define SYSCTR0_COUNTERID3_0 MAKE_SYSCTR0_REG(0xFEC) +#define SYSCTR0_COUNTERID8_0 MAKE_SYSCTR0_REG(0xFF0) +#define SYSCTR0_COUNTERID9_0 MAKE_SYSCTR0_REG(0xFF4) +#define SYSCTR0_COUNTERID10_0 MAKE_SYSCTR0_REG(0xFF8) +#define SYSCTR0_COUNTERID11_0 MAKE_SYSCTR0_REG(0xFFC) + +#endif diff --git a/sept/sept-secondary/src/sysreg.h b/sept/sept-secondary/src/sysreg.h new file mode 100644 index 000000000..1bc1a8c43 --- /dev/null +++ b/sept/sept-secondary/src/sysreg.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_SYSREG_H +#define FUSEE_SYSREG_H + +#include <stdint.h> + +#define SYSREG_BASE 0x6000C000 +#define SB_BASE (SYSREG_BASE + 0x200) +#define EXCP_VEC_BASE 0x6000F000 + +#define MAKE_SYSREG(n) MAKE_REG32(SYSREG_BASE + n) +#define MAKE_SB_REG(n) MAKE_REG32(SB_BASE + n) +#define MAKE_EXCP_VEC_REG(n) MAKE_REG32(EXCP_VEC_BASE + n) + +#define AHB_ARBITRATION_DISABLE_0 MAKE_SYSREG(0x004) +#define AHB_ARBITRATION_XBAR_CTRL_0 MAKE_SYSREG(0x0E0) +#define AHB_AHB_SPARE_REG_0 MAKE_SYSREG(0x110) + +#define SB_CSR_0 MAKE_SB_REG(0x00) +#define SB_PIROM_START_0 MAKE_SB_REG(0x04) +#define SB_PFCFG_0 MAKE_SB_REG(0x08) +#define SB_SECURE_SPAREREG_0_0 MAKE_SB_REG(0x0C) +#define SB_SECURE_SPAREREG_1_0 MAKE_SB_REG(0x10) +#define SB_SECURE_SPAREREG_2_0 MAKE_SB_REG(0x14) +#define SB_SECURE_SPAREREG_3_0 MAKE_SB_REG(0x18) +#define SB_SECURE_SPAREREG_4_0 MAKE_SB_REG(0x1C) +#define SB_SECURE_SPAREREG_5_0 MAKE_SB_REG(0x20) +#define SB_SECURE_SPAREREG_6_0 MAKE_SB_REG(0x24) +#define SB_SECURE_SPAREREG_7_0 MAKE_SB_REG(0x28) +#define SB_AA64_RESET_LOW_0 MAKE_SB_REG(0x30) +#define SB_AA64_RESET_HIGH_0 MAKE_SB_REG(0x34) + +#endif diff --git a/sept/sept-secondary/src/timers.h b/sept/sept-secondary/src/timers.h new file mode 100644 index 000000000..1c2be85d7 --- /dev/null +++ b/sept/sept-secondary/src/timers.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_TIMERS_H +#define FUSEE_TIMERS_H + +#include "utils.h" + +#define TIMERS_BASE 0x60005000 +#define MAKE_TIMERS_REG(n) MAKE_REG32(TIMERS_BASE + n) + +#define TIMERUS_CNTR_1US_0 MAKE_TIMERS_REG(0x10) +#define TIMERUS_USEC_CFG_0 MAKE_TIMERS_REG(0x14) +#define SHARED_INTR_STATUS_0 MAKE_TIMERS_REG(0x1A0) +#define SHARED_TIMER_SECURE_CFG_0 MAKE_TIMERS_REG(0x1A4) + +#define RTC_BASE 0x7000E000 +#define MAKE_RTC_REG(n) MAKE_REG32(RTC_BASE + n) + +#define RTC_SECONDS MAKE_RTC_REG(0x08) +#define RTC_SHADOW_SECONDS MAKE_RTC_REG(0x0C) +#define RTC_MILLI_SECONDS MAKE_RTC_REG(0x10) + +typedef struct { + uint32_t CONFIG; + uint32_t STATUS; + uint32_t COMMAND; + uint32_t PATTERN; +} watchdog_timers_t; + +#define GET_WDT(n) ((volatile watchdog_timers_t *)(TIMERS_BASE + 0x100 + 0x20 * n)) +#define WDT_REBOOT_PATTERN 0xC45A +#define GET_WDT_REBOOT_CFG_REG(n) MAKE_REG32(TIMERS_BASE + 0x60 + 0x8 * n) + +void wait(uint32_t microseconds); + +static inline uint32_t get_time_s(void) { + return RTC_SECONDS; +} + +static inline uint32_t get_time_ms(void) { + return (RTC_MILLI_SECONDS | (RTC_SHADOW_SECONDS << 10)); +} + +static inline uint32_t get_time_us(void) { + return TIMERUS_CNTR_1US_0; +} + +/** + * Returns the time in microseconds. + */ +static inline uint32_t get_time(void) { + return get_time_us(); +} + +/** + * Returns the number of microseconds that have passed since a given get_time(). + */ +static inline uint32_t get_time_since(uint32_t base) { + return get_time_us() - base; +} + +/** + * Delays for a given number of microseconds. + */ +static inline void udelay(uint32_t usecs) { + uint32_t start = get_time_us(); + while (get_time_us() - start < usecs); +} + +/** + * Delays for a given number of milliseconds. + */ +static inline void mdelay(uint32_t msecs) { + uint32_t start = get_time_ms(); + while (get_time_ms() - start < msecs); +} + +__attribute__ ((noreturn)) void watchdog_reboot(void); + +#endif diff --git a/sept/sept-secondary/src/uart.c b/sept/sept-secondary/src/uart.c new file mode 100644 index 000000000..99d3dd848 --- /dev/null +++ b/sept/sept-secondary/src/uart.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "uart.h" +#include "timers.h" + +void uart_init(UartDevice dev, uint32_t baud) { + volatile tegra_uart_t *uart = uart_get_regs(dev); + + /* Set baud rate. */ + uint32_t rate = (8 * baud + 408000000) / (16 * baud); + uart->UART_LCR = UART_LCR_DLAB; /* Enable DLAB. */ + uart->UART_THR_DLAB = (uint8_t)rate; /* Divisor latch LSB. */ + uart->UART_IER_DLAB = (uint8_t)(rate >> 8); /* Divisor latch MSB. */ + uart->UART_LCR = 0; /* Diable DLAB. */ + + /* Setup UART in fifo mode. */ + uart->UART_IER_DLAB = 0; + uart->UART_IIR_FCR = UART_FCR_FCR_EN_FIFO | UART_FCR_RX_CLR | UART_FCR_TX_CLR; /* Enable and clear TX and RX FIFOs. */ + (void)uart->UART_LSR; + udelay(3 * ((baud + 999999) / baud)); + uart->UART_LCR = UART_LCR_WD_LENGTH_8; /* Set word length 8. */ + uart->UART_MCR = 0; + uart->UART_MSR = 0; + uart->UART_IRDA_CSR = 0; + uart->UART_RX_FIFO_CFG = 1; /* Set RX_FIFO trigger level */ + uart->UART_MIE = 0; + uart->UART_ASR = 0; +} + +/* This function blocks until the UART device (dev) is in the desired state (status). Make sure the desired state can be reached! */ +void uart_wait_idle(UartDevice dev, UartVendorStatus status) { + while (!(uart_get_regs(dev)->UART_VENDOR_STATUS & status)) { + /* Wait */ + } +} + +void uart_send(UartDevice dev, const void *buf, size_t len) { + volatile tegra_uart_t *uart = uart_get_regs(dev); + + for (size_t i = 0; i < len; i++) { + while (uart->UART_LSR & UART_LSR_TX_FIFO_FULL) { + /* Wait until the TX FIFO isn't full */ + } + uart->UART_THR_DLAB = *((const uint8_t *)buf + i); + } +} + +void uart_recv(UartDevice dev, void *buf, size_t len) { + volatile tegra_uart_t *uart = uart_get_regs(dev); + + for (size_t i = 0; i < len; i++) { + while (uart->UART_LSR & UART_LSR_RX_FIFO_EMPTY) { + /* Wait until the RX FIFO isn't empty */ + } + *((uint8_t *)buf + i) = uart->UART_THR_DLAB; + } +} diff --git a/sept/sept-secondary/src/uart.h b/sept/sept-secondary/src/uart.h new file mode 100644 index 000000000..a4402daf4 --- /dev/null +++ b/sept/sept-secondary/src/uart.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_UART_H +#define FUSEE_UART_H + +#include <string.h> + +#define UART_BASE 0x70006000 + +#define BAUD_115200 115200 + +/* UART devices */ +typedef enum { + UART_A = 0, + UART_B = 1, + UART_C = 2, + UART_D = 3, + UART_E = 4, +} UartDevice; + +/* 36.3.12 UART_VENDOR_STATUS_0_0 */ +typedef enum { + UART_VENDOR_STATE_TX_IDLE = 1 << 0, + UART_VENDOR_STATE_RX_IDLE = 1 << 1, + + /* This bit is set to 1 when a read is issued to an empty FIFO and gets cleared on register read (sticky bit until read) + 0 = NO_UNDERRUN + 1 = UNDERRUN + */ + UART_VENDOR_STATE_RX_UNDERRUN = 1 << 2, + + /* This bit is set to 1 when write data is issued to the TX FIFO when it is already full and gets cleared on register read (sticky bit until read) + 0 = NO_OVERRUN + 1 = OVERRUN + */ + UART_VENDOR_STATE_TX_OVERRUN = 1 << 3, + + UART_VENDOR_STATE_RX_FIFO_COUNTER = 0b111111 << 16, /* reflects number of current entries in RX FIFO */ + UART_VENDOR_STATE_TX_FIFO_COUNTER = 0b111111 << 24 /* reflects number of current entries in TX FIFO */ +} UartVendorStatus; + +/* 36.3.6 UART_LSR_0 */ +typedef enum { + UART_LSR_RDR = 1 << 0, /* Receiver Data Ready */ + UART_LSR_OVRF = 1 << 1, /* Receiver Overrun Error */ + UART_LSR_PERR = 1 << 2, /* Parity Error */ + UART_LSR_FERR = 1 << 3, /* Framing Error */ + UART_LSR_BRK = 1 << 4, /* BREAK condition detected on line */ + UART_LSR_THRE = 1 << 5, /* Transmit Holding Register is Empty -- OK to write data */ + UART_LSR_TMTY = 1 << 6, /* Transmit Shift Register empty status */ + UART_LSR_FIFOE = 1 << 7, /* Receive FIFO Error */ + UART_LSR_TX_FIFO_FULL = 1 << 8, /* Transmitter FIFO full status */ + UART_LSR_RX_FIFO_EMPTY = 1 << 9, /* Receiver FIFO empty status */ +} UartLineStatus; + +/* 36.3.4 UART_LCR_0 */ +typedef enum { + UART_LCR_WD_LENGTH_5 = 0, /* word length 5 */ + UART_LCR_WD_LENGTH_6 = 1, /* word length 6 */ + UART_LCR_WD_LENGTH_7 = 2, /* word length 7 */ + UART_LCR_WD_LENGTH_8 = 3, /* word length 8 */ + + /* STOP: + 0 = Transmit 1 stop bit + 1 = Transmit 2 stop bits (receiver always checks for 1 stop bit) + */ + UART_LCR_STOP = 1 << 2, + UART_LCR_PAR = 1 << 3, /* Parity enabled */ + UART_LCR_EVEN = 1 << 4, /* Even parity format. There will always be an even number of 1s in the binary representation (PAR = 1) */ + UART_LCR_SET_P = 1 << 5, /* Set (force) parity to value in LCR[4] */ + UART_LCR_SET_B = 1 << 6, /* Set BREAK condition -- Transmitter sends all zeroes to indicate BREAK */ + UART_LCR_DLAB = 1 << 7, /* Divisor Latch Access Bit (set to allow programming of the DLH, DLM Divisors) */ +} UartLineControl; + +/* 36.3.3 UART_IIR_FCR_0 */ +typedef enum { + UART_FCR_FCR_EN_FIFO = 1 << 0, /* Enable the transmit and receive FIFOs. This bit should be enabled */ + UART_FCR_RX_CLR = 1 << 1, /* Clears the contents of the receive FIFO and resets its counter logic to 0 (the receive shift register is not cleared or altered). This bit returns to 0 after clearing the FIFOs */ + UART_FCR_TX_CLR = 1 << 2, /* Clears the contents of the transmit FIFO and resets its counter logic to 0 (the transmit shift register is not cleared or altered). This bit returns to 0 after clearing the FIFOs */ + + /* DMA: + 0 = DMA_MODE_0 + 1 = DMA_MODE_1 + */ + UART_FCR_DMA = 1 << 3, + + /* TX_TRIG + 0 = FIFO_COUNT_GREATER_16 + 1 = FIFO_COUNT_GREATER_8 + 2 = FIFO_COUNT_GREATER_4 + 3 = FIFO_COUNT_GREATER_1 + */ + UART_FCR_TX_TRIG = 3 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_16 = 0 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_8 = 1 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_4 = 2 << 4, + UART_FCR_TX_TRIG_FIFO_COUNT_GREATER_1 = 3 << 4, + + /* RX_TRIG + 0 = FIFO_COUNT_GREATER_1 + 1 = FIFO_COUNT_GREATER_4 + 2 = FIFO_COUNT_GREATER_8 + 3 = FIFO_COUNT_GREATER_16 + */ + UART_FCR_RX_TRIG = 3 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_1 = 0 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_4 = 1 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_8 = 2 << 6, + UART_FCR_RX_TRIG_FIFO_COUNT_GREATER_16 = 3 << 6, +} UartFifoControl; + +/* 36.3.3 UART_IIR_FCR_0 */ +typedef enum { + UART_IIR_IS_STA = 1 << 0, /* Interrupt Pending if ZERO */ + UART_IIR_IS_PRI0 = 1 << 1, /* Encoded Interrupt ID Refer to IIR[3:0] table [36.3.3] */ + UART_IIR_IS_PRI1 = 1 << 2, /* Encoded Interrupt ID Refer to IIR[3:0] table */ + UART_IIR_IS_PRI2 = 1 << 3, /* Encoded Interrupt ID Refer to IIR[3:0] table */ + + /* FIFO Mode Status + 0 = 16450 mode (no FIFO) + 1 = 16550 mode (FIFO) + */ + UART_IIR_EN_FIFO = 3 << 6, + UART_IIR_MODE_16450 = 0 << 6, + UART_IIR_MODE_16550 = 1 << 6, +} UartInterruptIdentification; + +typedef struct { + uint32_t UART_THR_DLAB; + uint32_t UART_IER_DLAB; + uint32_t UART_IIR_FCR; + uint32_t UART_LCR; + uint32_t UART_MCR; + uint32_t UART_LSR; + uint32_t UART_MSR; + uint32_t UART_SPR; + uint32_t UART_IRDA_CSR; + uint32_t UART_RX_FIFO_CFG; + uint32_t UART_MIE; + uint32_t UART_VENDOR_STATUS; + uint8_t _0x30[0x0C]; + uint32_t UART_ASR; +} tegra_uart_t; + +void uart_init(UartDevice dev, uint32_t baud); +void uart_wait_idle(UartDevice dev, UartVendorStatus status); +void uart_send(UartDevice dev, const void *buf, size_t len); +void uart_recv(UartDevice dev, void *buf, size_t len); + +static inline volatile tegra_uart_t *uart_get_regs(UartDevice dev) { + static const size_t offsets[] = {0, 0x40, 0x200, 0x300, 0x400}; + return (volatile tegra_uart_t *)(UART_BASE + offsets[dev]); +} + +#endif diff --git a/sept/sept-secondary/src/utils.c b/sept/sept-secondary/src/utils.c new file mode 100644 index 000000000..ac3d7b61f --- /dev/null +++ b/sept/sept-secondary/src/utils.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stdarg.h> +#include "utils.h" +#include "se.h" +#include "fuse.h" +#include "pmc.h" +#include "timers.h" +#include "panic.h" +#include "car.h" +#include "btn.h" + +#include "lib/log.h" + +#include <inttypes.h> + +#define u8 uint8_t +#define u32 uint32_t +#include "rebootstub_bin.h" +#undef u8 +#undef u32 + +void wait(uint32_t microseconds) { + uint32_t old_time = TIMERUS_CNTR_1US_0; + while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { + /* Spin-lock. */ + } +} + +__attribute__((noreturn)) void watchdog_reboot(void) { + volatile watchdog_timers_t *wdt = GET_WDT(4); + wdt->PATTERN = WDT_REBOOT_PATTERN; + wdt->COMMAND = 2; /* Disable Counter. */ + GET_WDT_REBOOT_CFG_REG(4) = 0xC0000000; + wdt->CONFIG = 0x8019; /* Full System Reset after Fourth Counter expires, using TIMER(9). */ + wdt->COMMAND = 1; /* Enable Counter. */ + while (true) { + /* Wait for reboot. */ + } +} + +__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) { + APBDEV_PMC_SCRATCH0_0 = scratch0; + + /* Reset the processor. */ + APBDEV_PMC_CONTROL = BIT(4); + + while (true) { + /* Wait for reboot. */ + } +} + +__attribute__((noreturn)) void reboot_to_self(void) { + /* Patch SDRAM init to perform an SVC immediately after second write */ + APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF; + APBDEV_PMC_SCRATCH46_0 = 0x6001DC28; + /* Set SVC handler to jump to reboot stub in IRAM. */ + APBDEV_PMC_SCRATCH33_0 = 0x4003F000; + APBDEV_PMC_SCRATCH40_0 = 0x6000F208; + + /* Copy reboot stub into IRAM high. */ + for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) { + write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i)); + } + + /* Trigger warm reboot. */ + pmc_reboot(1 << 0); +} + +__attribute__((noreturn)) void wait_for_button_and_reboot(void) { + uint32_t button; + while (true) { + button = btn_read(); + if (button & BTN_POWER) { + reboot_to_self(); + } + } +} + +__attribute__ ((noreturn)) void generic_panic(void) { + panic(0xFF000006); +} + +__attribute__((noreturn)) void fatal_error(const char *fmt, ...) { + va_list args; + print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: "); + va_start(args, fmt); + vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args); + va_end(args); + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n"); + wait_for_button_and_reboot(); +} + +__attribute__((noinline)) bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be) +{ + if(as <= bs && bs <= ae) + return true; + if(bs <= as && as <= be) + return true; + return false; +} + +/* Adapted from https://gist.github.com/ccbrown/9722406 */ +void hexdump(const void* data, size_t size, uintptr_t addrbase) { + const uint8_t *d = (const uint8_t *)data; + char ascii[17]; + ascii[16] = '\0'; + + for (size_t i = 0; i < size; i++) { + if (i % 16 == 0) { + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i); + } + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%02X ", d[i]); + if (d[i] >= ' ' && d[i] <= '~') { + ascii[i % 16] = d[i]; + } else { + ascii[i % 16] = '.'; + } + if ((i+1) % 8 == 0 || i+1 == size) { + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); + if ((i+1) % 16 == 0) { + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii); + } else if (i+1 == size) { + ascii[(i+1) % 16] = '\0'; + if ((i+1) % 16 <= 8) { + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); + } + for (size_t j = (i+1) % 16; j < 16; j++) { + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " "); + } + print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii); + } + } + } +} diff --git a/sept/sept-secondary/src/utils.h b/sept/sept-secondary/src/utils.h new file mode 100644 index 000000000..58e53bffe --- /dev/null +++ b/sept/sept-secondary/src/utils.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef FUSEE_UTILS_H +#define FUSEE_UTILS_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#define BIT(n) (1u << (n)) +#define BITL(n) (1ull << (n)) +#define MASK(n) (BIT(n) - 1) +#define MASKL(n) (BITL(n) - 1) +#define MASK2(a,b) (MASK(a) & ~MASK(b)) +#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) + +#define MAKE_REG32(a) (*(volatile uint32_t *)(a)) + +#define ALIGN(m) __attribute__((aligned(m))) +#define PACKED __attribute__((packed)) + +#define ALINLINE __attribute__((always_inline)) +#define NOINLINE __attribute__((noinline)) + +#define SET_SYSREG(reg, val) do { temp_reg = (val); __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false) + +static inline uintptr_t get_physical_address(const void *addr) { + return (uintptr_t)addr; +} + +static inline uint32_t read32le(const volatile void *dword, size_t offset) { + uintptr_t addr = (uintptr_t)dword + offset; + volatile uint32_t *target = (uint32_t *)addr; + return *target; +} + +static inline uint32_t read32be(const volatile void *dword, size_t offset) { + return __builtin_bswap32(read32le(dword, offset)); +} + +static inline uint64_t read64le(const volatile void *qword, size_t offset) { + uintptr_t addr = (uintptr_t)qword + offset; + volatile uint64_t *target = (uint64_t *)addr; + return *target; +} + +static inline uint64_t read64be(const volatile void *qword, size_t offset) { + return __builtin_bswap64(read64le(qword, offset)); +} + +static inline void write32le(volatile void *dword, size_t offset, uint32_t value) { + uintptr_t addr = (uintptr_t)dword + offset; + volatile uint32_t *target = (uint32_t *)addr; + *target = value; +} + +static inline void write32be(volatile void *dword, size_t offset, uint32_t value) { + write32le(dword, offset, __builtin_bswap32(value)); +} + +static inline void write64le(volatile void *qword, size_t offset, uint64_t value) { + uintptr_t addr = (uintptr_t)qword + offset; + volatile uint64_t *target = (uint64_t *)addr; + *target = value; +} + +static inline void write64be(volatile void *qword, size_t offset, uint64_t value) { + write64le(qword, offset, __builtin_bswap64(value)); +} + +static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) { + return __builtin_add_overflow_p(a, b, (uint32_t)0); +} + +static inline bool check_32bit_address_loadable(uintptr_t addr) { + /* FWIW the bootROM forbids loading anything between 0x40000000 and 0x40010000, using it for itself... */ + return (addr >= 0x40010000u && addr < 0x40040000u) || addr >= 0x80000000u; +} + +static inline bool check_32bit_address_range_loadable(uintptr_t addr, size_t size) { + return + !__builtin_add_overflow_p(addr, size, (uintptr_t)0) && /* the range doesn't overflow */ + check_32bit_address_loadable(addr) && check_32bit_address_loadable(addr + size) && /* bounds are valid */ + !(addr >= 0x40010000u && addr < 0x40040000u && addr + size >= 0x40040000u) /* the range doesn't cross MMIO */ + ; +} + +bool overlaps(uint64_t as, uint64_t ae, uint64_t bs, uint64_t be); +static inline bool overlaps_a(const void *as, const void *ae, const void *bs, const void *be) { + return overlaps((uint64_t)(uintptr_t)as, (uint64_t)(uintptr_t)ae, (uint64_t)(uintptr_t)bs, (uint64_t)(uintptr_t)be); +} + +static inline bool check_32bit_address_range_in_program(uintptr_t addr, size_t size) { + extern uint8_t __chainloader_start__[], __chainloader_end__[]; + extern uint8_t __stack_bottom__[], __stack_top__[]; + extern uint8_t __start__[], __end__[]; + uint8_t *start = (uint8_t *)addr, *end = start + size; + + return overlaps_a(start, end, __chainloader_start__, __chainloader_end__) || + overlaps_a(start, end, __stack_bottom__, __stack_top__) || + overlaps_a(start, end, (void *)0xC0000000, (void *)0xC03C0000) || /* framebuffer */ + overlaps_a(start, end, __start__, __end__); +} + +void hexdump(const void* data, size_t size, uintptr_t addrbase); + +__attribute__((noreturn)) void watchdog_reboot(void); +__attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); +__attribute__((noreturn)) void reboot_to_self(void); +__attribute__((noreturn)) void wait_for_button_and_reboot(void); + +__attribute__((noreturn)) void generic_panic(void); + +__attribute__((noreturn)) void fatal_error(const char *fmt, ...); + +#endif From f58f7c8a169715dc1446d4217ee0d266e1aefe80 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 06:54:44 -0800 Subject: [PATCH 415/489] sept: implement cryptographic meme --- sept/sept-secondary/sept_sign.py | 33 ++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py index 91d966d11..f4903d142 100644 --- a/sept/sept-secondary/sept_sign.py +++ b/sept/sept-secondary/sept_sign.py @@ -5,7 +5,31 @@ from Crypto.Cipher import AES from Crypto.Hash import CMAC import KEYS -def sign_encrypt_code(code, sig_key, enc_key, iv): +def shift_left_xor_rb(s): + N = int(s.encode('hex'), 16) + if N & (1 << 127): + N = ((N << 1) ^ 0x87) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + else: + N = ((N << 1) ^ 0x00) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + return ('%032x' % N).decode('hex') + +def sxor(x, y): + return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(x, y)) + +def get_last_block_for_desired_mac(key, data, desired_mac): + assert len(desired_mac) == 0x10 + k1 = shift_left_xor_rb(AES.new(key, AES.MODE_ECB).encrypt('\x00'*0x10)) + if len(data) & 0xF: + k1 = shift_left_xor_rb(k1) + data += '\x80' + data += '\x00' * ((0x10 - (len(data) & 0xF)) & 0xF) + num_blocks = (len(data) + 0xF) >> 4 + last_block = sxor(AES.new(key, AES.MODE_ECB).decrypt(desired_mac), k1) + if len(data) > 0x0: + last_block = sxor(last_block, AES.new(key, AES.MODE_CBC, '\x00'*0x10).encrypt(data)[-0x10:]) + return last_block + +def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac): # Pad with 0x20 of zeroes. code += '\x00' * 0x20 code_len = len(code) @@ -14,11 +38,12 @@ def sign_encrypt_code(code, sig_key, enc_key, iv): code += '\x00' * (code_len - len(code)) # Add empty trustzone, warmboot segments. - code += '\x00'*0x1FE0 + code += '\x00'* (0x1FE0 - 0x10) pk11_hdr = 'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0) pk11 = pk11_hdr + code enc_pk11 = AES.new(enc_key, AES.MODE_CBC, iv).encrypt(pk11) - enc_pk11 = pk('<IIII', len(pk11), 0, 0, 0) + iv + enc_pk11 + enc_pk11 = pk('<IIII', len(pk11) + 0x10, 0, 0, 0) + iv + enc_pk11 + enc_pk11 += get_last_block_for_desired_mac(sig_key, enc_pk11, desired_mac) enc_pk11 += CMAC.new(sig_key, enc_pk11, AES).digest() return enc_pk11 @@ -31,7 +56,7 @@ def main(argc, argv): assert (len(code) & 0xF) == 0 # TODO: Support dev unit crypto with open(argv[2], 'wb') as f: - f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV)) + f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, 'THANKS_NVIDIA_<3')) return 0 if __name__ == '__main__': From c56561b234d79bc30ca7e4db023633ba1aea5fb2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 09:20:19 -0800 Subject: [PATCH 416/489] sept-secondary: reboot to clean state + grab keys from SE --- sept/sept-secondary/linker.ld | 1 + sept/sept-secondary/sept_sign.py | 3 +- sept/sept-secondary/src/di.c | 4 +- sept/sept-secondary/src/di.h | 5 + sept/sept-secondary/src/di.inl | 9 +- sept/sept-secondary/src/hwinit.c | 29 +++--- sept/sept-secondary/src/main.c | 81 +++++++++++++++++ sept/sept-secondary/src/se.c | 151 +++++++++++++++++++++++++++++++ sept/sept-secondary/src/se.h | 7 ++ sept/sept-secondary/src/start.s | 5 + 10 files changed, 272 insertions(+), 23 deletions(-) diff --git a/sept/sept-secondary/linker.ld b/sept/sept-secondary/linker.ld index b442fd3b6..27dba8fc7 100644 --- a/sept/sept-secondary/linker.ld +++ b/sept/sept-secondary/linker.ld @@ -148,6 +148,7 @@ SECTIONS . = ALIGN(32); PROVIDE (__bss_end__ = ABSOLUTE(.)); } >main :NONE + . = ALIGN(32); __end__ = ABSOLUTE(.) ; /* ================== diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py index f4903d142..c764a7598 100644 --- a/sept/sept-secondary/sept_sign.py +++ b/sept/sept-secondary/sept_sign.py @@ -53,7 +53,8 @@ def main(argc, argv): return 1 with open(argv[1], 'rb') as f: code = f.read() - assert (len(code) & 0xF) == 0 + if len(code) & 0xF: + code += '\x00'*(0x10 - (len(code) & 0xF)) # TODO: Support dev unit crypto with open(argv[2], 'wb') as f: f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, 'THANKS_NVIDIA_<3')) diff --git a/sept/sept-secondary/src/di.c b/sept/sept-secondary/src/di.c index b6f8116c9..f3f76209b 100644 --- a/sept/sept-secondary/src/di.c +++ b/sept/sept-secondary/src/di.c @@ -111,7 +111,7 @@ void display_init() exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4); exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94); - exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 60); + exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 61); udelay(10000); @@ -149,8 +149,8 @@ void display_init() udelay(20000); - exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21); exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3); + exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21); MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4; exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10); diff --git a/sept/sept-secondary/src/di.h b/sept/sept-secondary/src/di.h index 4aa4f944d..5d667ecd2 100644 --- a/sept/sept-secondary/src/di.h +++ b/sept/sept-secondary/src/di.h @@ -190,6 +190,7 @@ #define DC_WIN_WIN_OPTIONS 0x700 #define H_DIRECTION (1 << 0) #define V_DIRECTION (1 << 2) +#define SCAN_COLUMN (1 << 4) #define COLOR_EXPAND (1 << 6) #define CSC_ENABLE (1 << 18) #define WIN_ENABLE (1 << 30) @@ -237,6 +238,8 @@ #define V_DDA_INC(x) (((x) & 0xffff) << 16) #define DC_WIN_LINE_STRIDE 0x70A +#define LINE_STRIDE(x) (x) +#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16) #define DC_WIN_DV_CONTROL 0x70E /* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */ @@ -347,6 +350,8 @@ #define DSI_PAD_CONTROL_4 0x52 +#define DSI_INIT_SEQ_DATA_15 0x5F + typedef struct _cfg_op_t { uint32_t off; diff --git a/sept/sept-secondary/src/di.inl b/sept/sept-secondary/src/di.inl index e438ca5cb..f842bfddc 100644 --- a/sept/sept-secondary/src/di.inl +++ b/sept/sept-secondary/src/di.inl @@ -128,7 +128,7 @@ static const cfg_op_t _display_config_2[94] = { }; //DSI Init config. -static const cfg_op_t _display_config_3[60] = { +static const cfg_op_t _display_config_3[61] = { {DSI_WR_DATA, 0}, {DSI_INT_ENABLE, 0}, {DSI_INT_STATUS, 0}, @@ -137,6 +137,7 @@ static const cfg_op_t _display_config_3[60] = { {DSI_INIT_SEQ_DATA_1, 0}, {DSI_INIT_SEQ_DATA_2, 0}, {DSI_INIT_SEQ_DATA_3, 0}, + {DSI_INIT_SEQ_DATA_15, 0}, {DSI_DCS_CMDS, 0}, {DSI_PKT_SEQ_0_LO, 0}, {DSI_PKT_SEQ_1_LO, 0}, @@ -288,7 +289,7 @@ static const cfg_op_t _display_config_7[10] = { static const cfg_op_t _display_config_8[6] = { {0x18, 0}, {2, 0xF3F10000}, - {0x16, 1}, + {0x16, 0}, {0x18, 0}, {0x18, 0x10010}, {0x17, 0x300} @@ -474,10 +475,10 @@ static const cfg_op_t _display_config_13[16] = { {DSI_PAD_CONTROL_1, 0}, {DSI_PHY_TIMING_0, 0x6070601}, {DSI_PHY_TIMING_1, 0x40A0E05}, - {DSI_PHY_TIMING_2, 0x30109}, + {DSI_PHY_TIMING_2, 0x30118}, {DSI_BTA_TIMING, 0x190A14}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) }, - {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TO_TALLY, 0}, {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, diff --git a/sept/sept-secondary/src/hwinit.c b/sept/sept-secondary/src/hwinit.c index f959754de..655054791 100644 --- a/sept/sept-secondary/src/hwinit.c +++ b/sept/sept-secondary/src/hwinit.c @@ -186,25 +186,22 @@ void config_se_brom() void nx_hwinit() { volatile tegra_car_t *car = car_get_regs(); + volatile tegra_pmc_t *pmc = pmc_get_regs(); /* This stuff was handled by whatever loaded us. */ - /* - config_se_brom(); - - AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; - pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); - - mbist_workaround(); - - clkrst_reboot(CARDEVICE_SE); - - fuse_init(); - - mc_enable(); - - config_oscillators(); - */ + config_se_brom(); + AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; + pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); + + mbist_workaround(); + + clkrst_reboot(CARDEVICE_SE); + + fuse_init(); + + mc_enable(); + /* Disable pinmux tristate input clamping. */ APB_MISC_PP_PINMUX_GLOBAL_0 = 0; diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index c5f6b2037..66c690c2d 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -19,6 +19,8 @@ #include "panic.h" #include "hwinit.h" #include "di.h" +#include "se.h" +#include "pmc.h" #include "timers.h" #include "fs_utils.h" #include "stage2.h" @@ -34,6 +36,82 @@ extern void (*__program_exit_callback)(int rc); static void *g_framebuffer; +static uint32_t g_tsec_root_key[0x4] = {0}; +static uint32_t g_tsec_key[0x4] = {0}; + +static bool has_rebooted(void) { + return MAKE_REG32(0x4003FFFC) == 0xFAFAFAFA; +} + +static void set_has_rebooted(bool rebooted) { + MAKE_REG32(0x4003FFFC) = rebooted ? 0xFAFAFAFA : 0x00000000; +} + + +static void exfiltrate_keys_and_reboot_if_needed(void) { + volatile tegra_pmc_t *pmc = pmc_get_regs(); + uint8_t *enc_se_state = (uint8_t *)0x4003E000; + uint8_t *dec_se_state = (uint8_t *)0x4003F000; + + if (!has_rebooted()) { + + + /* Save the security engine context. */ + se_get_regs()->_0x4 = 0x0; + se_set_in_context_save_mode(true); + se_save_context(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY, enc_se_state); + se_set_in_context_save_mode(false); + + /* Decrypt the security engine context. */ + + /* Copy TSEC key from SOR1 registers. */ + MAKE_REG32(0x4003FFC0) = pmc->secure_scratch4; + MAKE_REG32(0x4003FFC4) = pmc->secure_scratch5; + MAKE_REG32(0x4003FFC8) = pmc->secure_scratch6; + MAKE_REG32(0x4003FFCC) = pmc->secure_scratch7; + + /* TODO: Master kek */ + MAKE_REG32(0x4003FFD0) = 0; + MAKE_REG32(0x4003FFD4) = 0; + MAKE_REG32(0x4003FFD8) = 0; + MAKE_REG32(0x4003FFDC) = 0; + + set_has_rebooted(true); + reboot_to_self(); + } else { + /* Decrypt the security engine state. */ + uint32_t ALIGN(16) context_key[4]; + context_key[0] = pmc->secure_scratch4; + context_key[1] = pmc->secure_scratch5; + context_key[2] = pmc->secure_scratch6; + context_key[3] = pmc->secure_scratch7; + set_aes_keyslot(0xC, context_key, sizeof(context_key)); + se_aes_128_cbc_decrypt(0xC, dec_se_state, 0x840, enc_se_state, 0x840); + + /* Copy out tsec key + tsec root key. */ + for (size_t i = 0; i < 0x10; i += 4) { + g_tsec_key[i/4] = MAKE_REG32((uintptr_t)(dec_se_state) + 0x1B0 + i); + g_tsec_root_key[i/4] = MAKE_REG32((uintptr_t)(dec_se_state) + 0x1D0 + i); + } + + /* Clear the security engine state. */ + for (size_t i = 0; i < 0x1000; i += 4) { + MAKE_REG32((uintptr_t)(enc_se_state) + i) = 0xCCCCCCCC; + MAKE_REG32((uintptr_t)(dec_se_state) + i) = 0xCCCCCCCC; + } + for (size_t i = 0; i < 4; i++) { + context_key[i] = 0xCCCCCCCC; + } + pmc->secure_scratch4 = 0xCCCCCCCC; + pmc->secure_scratch5 = 0xCCCCCCCC; + pmc->secure_scratch6 = 0xCCCCCCCC; + pmc->secure_scratch7 = 0xCCCCCCCC; + } + + + +} + static void setup_env(void) { g_framebuffer = (void *)0xC0000000; @@ -79,6 +157,9 @@ static void exit_callback(int rc) { int main(void) { ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY; + /* Extract keys from the security engine, which TSEC FW locked down. */ + exfiltrate_keys_and_reboot_if_needed(); + /* Override the global logging level. */ log_set_log_level(log_level); diff --git a/sept/sept-secondary/src/se.c b/sept/sept-secondary/src/se.c index d4dbdc498..09b46dbaa 100644 --- a/sept/sept-secondary/src/se.c +++ b/sept/sept-secondary/src/se.c @@ -580,6 +580,20 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); } +void se_aes_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size) { + volatile tegra_se_t *se = se_get_regs(); + + if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) { + generic_panic(); + } + + se->CONFIG_REG = (ALG_AES_DEC | DST_MEMORY) | (0x000 << 16); + se->CRYPTO_REG = (keyslot << 24) | 0x66; + clear_aes_keyslot_iv(keyslot); + se->BLOCK_COUNT_REG = (src_size >> 4) - 1; + trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size); +} + /* SHA256 Implementation. */ void se_calculate_sha256(void *dst, const void *src, size_t src_size) { volatile tegra_se_t *se = se_get_regs(); @@ -647,3 +661,140 @@ void se_generate_random(unsigned int keyslot, void *dst, size_t size) { se_perform_aes_block_operation(dst + aligned_size, size - aligned_size, NULL, 0); } } + +void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + if (dst_keyslot >= KEYSLOT_AES_MAX || rng_keyslot >= KEYSLOT_AES_MAX) { + generic_panic(); + } + + /* Setup Config. */ + se->CONFIG_REG = (ALG_RNG | DST_KEYTAB); + se->CRYPTO_REG = (rng_keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 4; + se->BLOCK_COUNT_REG = 0; + + /* Generate low part of key. */ + se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8); + trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); + /* Generate high part of key. */ + se->CRYPTO_KEYTABLE_DST_REG = (dst_keyslot << 8) | 1; + trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); +} + +/* SE context save API. */ +void se_set_in_context_save_mode(bool is_context_save_mode) { + volatile tegra_se_t *se = se_get_regs(); + + uint32_t val = se->_0x0; + if (is_context_save_mode) { + val |= 0x10000; + } else { + val &= 0xFFFEFFFF; + } + se->_0x0 = val; + /* Perform a useless read from flags reg. */ + (void)(se->FLAGS_REG); +} + +void se_generate_srk(unsigned int srkgen_keyslot) { + volatile tegra_se_t *se = se_get_regs(); + + se->CONFIG_REG = (ALG_RNG | DST_SRK); + se->CRYPTO_REG = (srkgen_keyslot << 24) | 0x108; + se->RNG_CONFIG_REG = 6; + se->BLOCK_COUNT_REG = 0; + trigger_se_blocking_op(OP_START, NULL, 0, NULL, 0); +} + +void se_encrypt_with_srk(void *dst, size_t dst_size, const void *src, size_t src_size) { + uint8_t output[0x80]; + uint8_t *aligned_out = (uint8_t *)(((uintptr_t)output + 0x7F) & ~0x3F); + if (dst_size > 0x10) { + generic_panic(); + } + + if (dst_size) { + trigger_se_blocking_op(OP_CTX_SAVE, aligned_out, dst_size, src, src_size); + memcpy(dst, aligned_out, dst_size); + } else { + trigger_se_blocking_op(OP_CTX_SAVE, aligned_out, 0, src, src_size); + } +} + +void se_save_context(unsigned int srkgen_keyslot, unsigned int rng_keyslot, void *dst) { + volatile tegra_se_t *se = se_get_regs(); + uint8_t _work_buf[0x80]; + uint8_t *work_buf = (uint8_t *)(((uintptr_t)_work_buf + 0x7F) & ~0x3F); + + /* Generate the SRK (context save encryption key). */ + se_generate_random_key(srkgen_keyslot, rng_keyslot); + se_generate_srk(srkgen_keyslot); + + se_generate_random(rng_keyslot, work_buf, 0x10); + + /* Save random initial block. */ + se->CONFIG_REG = (ALG_AES_ENC | DST_MEMORY); + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(dst, 0x10, work_buf, 0x10); + + /* Save Sticky Bits. */ + for (unsigned int i = 0; i < 0x2; i++) { + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_STICKY_BITS) | (i << CTX_SAVE_STICKY_BIT_INDEX_SHIFT); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(dst + 0x10 + (i * 0x10), 0x10, NULL, 0); + } + + /* Save AES Key Table. */ + for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_LOW_BITS); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(dst + 0x30 + (i * 0x20), 0x10, NULL, 0); + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_HIGH_BITS); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(dst + 0x40 + (i * 0x20), 0x10, NULL, 0); + } + + /* Save AES Original IVs. */ + for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_ORIGINAL_IV); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(dst + 0x230 + (i * 0x10), 0x10, NULL, 0); + } + + /* Save AES Updated IVs */ + for (unsigned int i = 0; i < KEYSLOT_AES_MAX; i++) { + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_AES) | (i << CTX_SAVE_KEY_INDEX_SHIFT) | (CTX_SAVE_KEY_UPDATED_IV); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(dst + 0x330 + (i * 0x10), 0x10, NULL, 0); + } + + /* Save RSA Keytable. */ + uint8_t *rsa_ctx_out = (uint8_t *)dst + 0x430; + for (unsigned int rsa_key = 0; rsa_key < KEYSLOT_RSA_MAX; rsa_key++) { + for (unsigned int mod_exp = 0; mod_exp < 2; mod_exp++) { + for (unsigned int sub_block = 0; sub_block < 0x10; sub_block++) { + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_KEYTABLE_RSA) | ((2 * rsa_key + (1 - mod_exp)) << CTX_SAVE_RSA_KEY_INDEX_SHIFT) | (sub_block << CTX_SAVE_RSA_KEY_BLOCK_INDEX_SHIFT); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(rsa_ctx_out, 0x10, NULL, 0); + rsa_ctx_out += 0x10; + } + } + } + + /* Save "Known Pattern. " */ + static const uint8_t context_save_known_pattern[0x10] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_MEM); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(dst + 0x830, 0x10, context_save_known_pattern, 0x10); + + /* Save SRK into PMC registers. */ + se->CONTEXT_SAVE_CONFIG_REG = (CTX_SAVE_SRC_SRK); + se->BLOCK_COUNT_REG = 0; + se_encrypt_with_srk(work_buf, 0, NULL, 0); + se->CONFIG_REG = 0; + se_encrypt_with_srk(work_buf, 0, NULL, 0); +} + diff --git a/sept/sept-secondary/src/se.h b/sept/sept-secondary/src/se.h index 64998621a..fa3dc0191 100644 --- a/sept/sept-secondary/src/se.h +++ b/sept/sept-secondary/src/se.h @@ -203,6 +203,7 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size); void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv); +void se_aes_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size); /* Hash API */ void se_calculate_sha256(void *dst, const void *src, size_t src_size); @@ -216,4 +217,10 @@ bool se_rsa2048_pss_verify(const void *signature, size_t signature_size, const v void se_initialize_rng(unsigned int keyslot); void se_generate_random(unsigned int keyslot, void *dst, size_t size); +/* SE context save API. */ +void se_generate_srk(unsigned int srkgen_keyslot); +void se_set_in_context_save_mode(bool is_context_save_mode); +void se_generate_random_key(unsigned int dst_keyslot, unsigned int rng_keyslot); +void se_save_context(unsigned int srk_keyslot, unsigned int rng_keyslot, void *dst); + #endif diff --git a/sept/sept-secondary/src/start.s b/sept/sept-secondary/src/start.s index 4cfa68003..b53b2aa44 100644 --- a/sept/sept-secondary/src/start.s +++ b/sept/sept-secondary/src/start.s @@ -32,6 +32,11 @@ _start: adr r3, _start cmp r2, r3 beq _relocation_loop_end + + /* If we are relocating, we are not rebooting to ourselves. Note that. */ + ldr r0, =0x4003FFFC + mov r1, #0x0 + str r1, [r0] ldr r4, =_relocation_loop_end mov r4, #0x1000 From fb2baa8c8d7b741202ee41a2ecefc83107e3b3ce Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 10:49:25 -0800 Subject: [PATCH 417/489] sept-s: remove a bunch of debug garbage --- sept/sept-secondary/src/main.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 66c690c2d..51a43f0e6 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -61,21 +61,7 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { se_set_in_context_save_mode(true); se_save_context(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY, enc_se_state); se_set_in_context_save_mode(false); - - /* Decrypt the security engine context. */ - - /* Copy TSEC key from SOR1 registers. */ - MAKE_REG32(0x4003FFC0) = pmc->secure_scratch4; - MAKE_REG32(0x4003FFC4) = pmc->secure_scratch5; - MAKE_REG32(0x4003FFC8) = pmc->secure_scratch6; - MAKE_REG32(0x4003FFCC) = pmc->secure_scratch7; - - /* TODO: Master kek */ - MAKE_REG32(0x4003FFD0) = 0; - MAKE_REG32(0x4003FFD4) = 0; - MAKE_REG32(0x4003FFD8) = 0; - MAKE_REG32(0x4003FFDC) = 0; - + set_has_rebooted(true); reboot_to_self(); } else { @@ -107,9 +93,6 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { pmc->secure_scratch6 = 0xCCCCCCCC; pmc->secure_scratch7 = 0xCCCCCCCC; } - - - } static void setup_env(void) { From f1068d6c3f8dc10d1fc0953eea1acdbff9de1796 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 11:31:36 -0800 Subject: [PATCH 418/489] sept-s: Implement key derivation --- fusee/fusee-secondary/src/nxboot.c | 29 ++++---- sept/sept-secondary/src/key_derivation.c | 85 ++++++++++++++++++++++++ sept/sept-secondary/src/key_derivation.h | 26 ++++++++ sept/sept-secondary/src/main.c | 17 ++++- 4 files changed, 141 insertions(+), 16 deletions(-) create mode 100644 sept/sept-secondary/src/key_derivation.c create mode 100644 sept/sept-secondary/src/key_derivation.h diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 71968dd16..5a11aa923 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -28,6 +28,7 @@ #include "mc.h" #include "se.h" #include "pmc.h" +#include "emc.h" #include "fuse.h" #include "i2c.h" #include "ips.h" @@ -308,6 +309,12 @@ static void nxboot_move_bootconfig() { free(bootconfig); } +static bool get_and_clear_has_run_sept(void) { + bool has_run_sept = (MAKE_EMC_REG(EMC_SCRATCH0) & 0x80000000) != 0; + MAKE_EMC_REG(EMC_SCRATCH0) &= ~0x80000000; + return has_run_sept; +} + /* This is the main function responsible for booting Horizon. */ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32]; uint32_t nxboot_main(void) { @@ -411,11 +418,6 @@ uint32_t nxboot_main(void) { tsec_fw_size = 0xF00; } } - - if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_700) { - /* TODO: Detect when we have been loaded by sept-secondary, and thus have keys provided for us. */ - reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size); - } print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); @@ -423,12 +425,9 @@ uint32_t nxboot_main(void) { uint8_t tsec_key[0x10] = {0}; uint8_t tsec_root_keys[0x20][0x10] = {0}; if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_700) { - /* TODO: what else to do here? */ - - /* Patch TSEC firmware to exit after generating TSEC key. */ - *((volatile uint16_t *)((uintptr_t)tsec_fw + 0x2DB5)) = 0x02F8; - if (tsec_get_key(tsec_key, 1, tsec_fw, tsec_fw_size) != 0) { - fatal_error("[NXBOOT]: Failed to get TSEC key!\n"); + /* Detect whether we need to run sept-secondary in order to derive keys. */ + if (!get_and_clear_has_run_sept()) { + reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size); } } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { uint8_t tsec_keys[0x20] = {0}; @@ -446,10 +445,12 @@ uint32_t nxboot_main(void) { } } - /* Derive keydata. */ + /* Derive keydata. If on 7.0.0+, sept has already derived keys for us. */ unsigned int keygen_type = 0; - if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) { - fatal_error("[NXBOOT]: Key derivation failed!\n"); + if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { + if (derive_nx_keydata(target_firmware, g_keyblobs, available_revision, tsec_key, tsec_root_keys, &keygen_type) != 0) { + fatal_error("[NXBOOT]: Key derivation failed!\n"); + } } /* Setup boot configuration for Exosphère. */ diff --git a/sept/sept-secondary/src/key_derivation.c b/sept/sept-secondary/src/key_derivation.c new file mode 100644 index 000000000..0567d510a --- /dev/null +++ b/sept/sept-secondary/src/key_derivation.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include "key_derivation.h" +#include "se.h" +#include "fuse.h" +#include "utils.h" + +#define AL16 ALIGN(16) + +static const uint8_t AL16 keyblob_seed_00[0x10] = { + 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 +}; + +static const uint8_t AL16 masterkey_seed[0x10] = { + 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C +}; + +static const uint8_t AL16 devicekey_seed[0x10] = { + 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 +}; + +static const uint8_t AL16 devicekey_4x_seed[0x10] = { + 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 +}; + +static const uint8_t AL16 masterkey_4x_seed[0x10] = { + 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 +}; + +static const uint8_t AL16 new_master_kek_seed_7x[0x10] = { + 0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C +}; + +void derive_7x_keys(const void *tsec_key, void *tsec_root_key) { + uint8_t AL16 work_buffer[0x10]; + uint8_t AL16 master_kek[0x10]; + + /* Set keyslot flags properly in preparation of derivation. */ + set_aes_keyslot_flags(0xE, 0x15); + set_aes_keyslot_flags(0xD, 0x15); + + /* Set the TSEC key. */ + set_aes_keyslot(0xD, tsec_key, 0x10); + + /* Derive keyblob key 0. */ + se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, keyblob_seed_00, 0x10); + decrypt_data_into_keyslot(0xF, 0xE, work_buffer, 0x10); + + /* Derive the master kek. */ + set_aes_keyslot(0xC, tsec_root_key, 0x10); + se_aes_ecb_decrypt_block(0xC, master_kek, 0x10, new_master_kek_seed_7x, 0x10); + + /* Clear the SBK. */ + clear_aes_keyslot(0xE); + + /* Set master kek. */ + set_aes_keyslot(0xC, master_kek, 0x10); + + /* Derive keys for exosphere. */ + decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); + decrypt_data_into_keyslot(0xF, 0xF, devicekey_seed, 0x10); + decrypt_data_into_keyslot(0xE, 0xC, masterkey_4x_seed, 0x10); + decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10); + + /* Clear master kek from memory. */ + for (size_t i = 0; i < sizeof(master_kek); i++) { + master_kek[i] = 0xCC; + work_buffer[i] = 0xCC; + } +} diff --git a/sept/sept-secondary/src/key_derivation.h b/sept/sept-secondary/src/key_derivation.h new file mode 100644 index 000000000..6c814171c --- /dev/null +++ b/sept/sept-secondary/src/key_derivation.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SEPT_KEYDERIVATION_H +#define SEPT_KEYDERIVATION_H + +#include <stddef.h> +#include <stdbool.h> +#include <stdint.h> + +void derive_7x_keys(const void *tsec_key, void *tsec_root_key); + +#endif diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 51a43f0e6..856578423 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -21,6 +21,8 @@ #include "di.h" #include "se.h" #include "pmc.h" +#include "emc.h" +#include "key_derivation.h" #include "timers.h" #include "fs_utils.h" #include "stage2.h" @@ -151,9 +153,20 @@ int main(void) { /* Say hello. */ print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re sept-secondary!\n"); - while (true) { } - /* TODO: Derive keys. */ + /* Derive keys. */ + derive_7x_keys(g_tsec_key, g_tsec_root_key); + + /* Cleanup keys in memory. */ + for (size_t i = 0; i < 0x10; i += 4) { + g_tsec_root_key[i/4] = 0xCCCCCCCC; + g_tsec_key[i/4] = 0xCCCCCCCC; + } + + /* Mark EMC scratch to say that sept has run. */ + MAKE_EMC_REG(EMC_SCRATCH0) |= 0x80000000; + + while (true) { } /* TODO: Chainload to payload. */ From ddc52222082b367062053c0b383dbf47f7144c36 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 13:12:15 -0800 Subject: [PATCH 419/489] sept-s: First functional version. --- fusee/fusee-primary/src/main.c | 2 +- fusee/fusee-secondary/src/main.c | 13 ++++-- fusee/fusee-secondary/src/nxboot.c | 17 ++++++- fusee/fusee-secondary/src/utils.c | 1 + sept/sept-secondary/src/di.c | 4 +- sept/sept-secondary/src/di.h | 5 -- sept/sept-secondary/src/di.inl | 9 ++-- sept/sept-secondary/src/hwinit.c | 13 ++++-- sept/sept-secondary/src/key_derivation.c | 15 ++---- sept/sept-secondary/src/main.c | 20 ++++++-- sept/sept-secondary/src/stage2.c | 58 ++++-------------------- sept/sept-secondary/src/stage2.h | 2 +- 12 files changed, 72 insertions(+), 87 deletions(-) diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 718130467..8299c70e8 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -149,7 +149,7 @@ int main(void) { /* Say hello. */ print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n"); - print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); + print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); /* Load the loader payload into DRAM. */ load_stage2(bct0); diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index bf2474fc3..f0ba2c261 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -98,6 +98,14 @@ int main(int argc, void **argv) { print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, u8"Welcome to Atmosphère Fusée Stage 2!\n"); print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 executing from: %s\n", (const char *)argv[STAGE2_ARGV_PROGRAM_PATH]); + + /* Load BCT0 from SD if needed. */ + if (strcmp(g_stage2_args->bct0, "") == 0) { + read_from_file(g_stage2_args->bct0, sizeof(g_stage2_args->bct0) - 1, "atmosphere/BCT.ini"); + if (!read_from_file(g_stage2_args->bct0, sizeof(g_stage2_args->bct0) - 1, "atmosphere/BCT.ini")) { + fatal_error("Failed to read BCT0 from SD!\n"); + } + } /* This will load all remaining binaries off of the SD. */ load_payload(g_stage2_args->bct0); @@ -106,10 +114,7 @@ int main(int argc, void **argv) { g_do_nxboot = loader_ctx->chainload_entrypoint == 0; if (g_do_nxboot) { - /* Display splash screen. */ - display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); - - print(SCREEN_LOG_LEVEL_MANDATORY, "Now performing nxboot.\n"); + print(SCREEN_LOG_LEVEL_INFO, "Now performing nxboot.\n"); uint32_t boot_memaddr = nxboot_main(); /* Wait for the splash screen to have been displayed as long as it should be. */ splash_screen_wait_delay(); diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index 5a11aa923..f9c50f77f 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -38,6 +38,7 @@ #include "flow.h" #include "timers.h" #include "key_derivation.h" +#include "masterkey.h" #include "package1.h" #include "package2.h" #include "smmu.h" @@ -47,6 +48,7 @@ #include "exocfg.h" #include "display/video_fb.h" #include "lib/ini.h" +#include "splash_screen.h" #define u8 uint8_t #define u32 uint32_t @@ -419,7 +421,7 @@ uint32_t nxboot_main(void) { } } - print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Loaded firmware from eMMC...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Loaded firmware from eMMC...\n"); /* Get the TSEC keys. */ uint8_t tsec_key[0x10] = {0}; @@ -428,7 +430,12 @@ uint32_t nxboot_main(void) { /* Detect whether we need to run sept-secondary in order to derive keys. */ if (!get_and_clear_has_run_sept()) { reboot_to_sept(tsec_fw, tsec_fw_size, sept_secondary_enc, sept_secondary_enc_size); + } else { + if (mkey_detect_revision(fuse_get_retail_type() != 0) != 0) { + fatal_error("[NXBOOT]: Sept derived incorrect keys!\n"); + } } + get_and_clear_has_run_sept(); } else if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_620) { uint8_t tsec_keys[0x20] = {0}; @@ -445,6 +452,10 @@ uint32_t nxboot_main(void) { } } + //fatal_error("Ran sept!"); + /* Display splash screen. */ + display_splash_screen_bmp(loader_ctx->custom_splash_path, (void *)0xC0000000); + /* Derive keydata. If on 7.0.0+, sept has already derived keys for us. */ unsigned int keygen_type = 0; if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_700) { @@ -528,11 +539,13 @@ uint32_t nxboot_main(void) { pmc->scratch1 = (uint32_t)warmboot_memaddr; } - print(SCREEN_LOG_LEVEL_MANDATORY, "[NXBOOT]: Rebuilding package2...\n"); + print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Rebuilding package2...\n"); /* Parse stratosphere config. */ nxboot_configure_stratosphere(MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); + print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT]: Configured Stratosphere...\n"); + /* Patch package2, adding Thermosphère + custom KIPs. */ package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware); diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index a847320a6..698cf7cd8 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -153,6 +153,7 @@ void wait_for_button(void) { } __attribute__ ((noreturn)) void generic_panic(void) { + print(SCREEN_LOG_LEVEL_ERROR, "generic panic from %p", __builtin_return_address(0)); panic(0xFF000006); } diff --git a/sept/sept-secondary/src/di.c b/sept/sept-secondary/src/di.c index f3f76209b..b6f8116c9 100644 --- a/sept/sept-secondary/src/di.c +++ b/sept/sept-secondary/src/di.c @@ -111,7 +111,7 @@ void display_init() exec_cfg((uint32_t *)CAR_BASE, _display_config_1, 4); exec_cfg((uint32_t *)DI_BASE, _display_config_2, 94); - exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 61); + exec_cfg((uint32_t *)DSI_BASE, _display_config_3, 60); udelay(10000); @@ -149,8 +149,8 @@ void display_init() udelay(20000); - exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3); exec_cfg((uint32_t *)DSI_BASE, _display_config_5, 21); + exec_cfg((uint32_t *)CAR_BASE, _display_config_6, 3); MAKE_DI_REG(DC_DISP_DISP_CLOCK_CONTROL) = 4; exec_cfg((uint32_t *)DSI_BASE, _display_config_7, 10); diff --git a/sept/sept-secondary/src/di.h b/sept/sept-secondary/src/di.h index 5d667ecd2..4aa4f944d 100644 --- a/sept/sept-secondary/src/di.h +++ b/sept/sept-secondary/src/di.h @@ -190,7 +190,6 @@ #define DC_WIN_WIN_OPTIONS 0x700 #define H_DIRECTION (1 << 0) #define V_DIRECTION (1 << 2) -#define SCAN_COLUMN (1 << 4) #define COLOR_EXPAND (1 << 6) #define CSC_ENABLE (1 << 18) #define WIN_ENABLE (1 << 30) @@ -238,8 +237,6 @@ #define V_DDA_INC(x) (((x) & 0xffff) << 16) #define DC_WIN_LINE_STRIDE 0x70A -#define LINE_STRIDE(x) (x) -#define UV_LINE_STRIDE(x) (((x) & 0xffff) << 16) #define DC_WIN_DV_CONTROL 0x70E /* The following registers are A/B/C shadows of the 0xBC0/0xDC0/0xFC0 registers (see DISPLAY_WINDOW_HEADER). */ @@ -350,8 +347,6 @@ #define DSI_PAD_CONTROL_4 0x52 -#define DSI_INIT_SEQ_DATA_15 0x5F - typedef struct _cfg_op_t { uint32_t off; diff --git a/sept/sept-secondary/src/di.inl b/sept/sept-secondary/src/di.inl index f842bfddc..e438ca5cb 100644 --- a/sept/sept-secondary/src/di.inl +++ b/sept/sept-secondary/src/di.inl @@ -128,7 +128,7 @@ static const cfg_op_t _display_config_2[94] = { }; //DSI Init config. -static const cfg_op_t _display_config_3[61] = { +static const cfg_op_t _display_config_3[60] = { {DSI_WR_DATA, 0}, {DSI_INT_ENABLE, 0}, {DSI_INT_STATUS, 0}, @@ -137,7 +137,6 @@ static const cfg_op_t _display_config_3[61] = { {DSI_INIT_SEQ_DATA_1, 0}, {DSI_INIT_SEQ_DATA_2, 0}, {DSI_INIT_SEQ_DATA_3, 0}, - {DSI_INIT_SEQ_DATA_15, 0}, {DSI_DCS_CMDS, 0}, {DSI_PKT_SEQ_0_LO, 0}, {DSI_PKT_SEQ_1_LO, 0}, @@ -289,7 +288,7 @@ static const cfg_op_t _display_config_7[10] = { static const cfg_op_t _display_config_8[6] = { {0x18, 0}, {2, 0xF3F10000}, - {0x16, 0}, + {0x16, 1}, {0x18, 0}, {0x18, 0x10010}, {0x17, 0x300} @@ -475,10 +474,10 @@ static const cfg_op_t _display_config_13[16] = { {DSI_PAD_CONTROL_1, 0}, {DSI_PHY_TIMING_0, 0x6070601}, {DSI_PHY_TIMING_1, 0x40A0E05}, - {DSI_PHY_TIMING_2, 0x30118}, + {DSI_PHY_TIMING_2, 0x30109}, {DSI_BTA_TIMING, 0x190A14}, {DSI_TIMEOUT_0, DSI_TIMEOUT_LRX(0x2000) | DSI_TIMEOUT_HTX(0xFFFF) }, - {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x1343) | DSI_TIMEOUT_TA(0x2000)}, + {DSI_TIMEOUT_1, DSI_TIMEOUT_PR(0x765) | DSI_TIMEOUT_TA(0x2000)}, {DSI_TO_TALLY, 0}, {DSI_HOST_CONTROL, DSI_HOST_CONTROL_CRC_RESET | DSI_HOST_CONTROL_TX_TRIG_HOST | DSI_HOST_CONTROL_CS | DSI_HOST_CONTROL_ECC}, {DSI_CONTROL, DSI_CONTROL_LANES(3) | DSI_CONTROL_HOST_ENABLE}, diff --git a/sept/sept-secondary/src/hwinit.c b/sept/sept-secondary/src/hwinit.c index 655054791..d3c7b82a2 100644 --- a/sept/sept-secondary/src/hwinit.c +++ b/sept/sept-secondary/src/hwinit.c @@ -185,23 +185,30 @@ void config_se_brom() void nx_hwinit() { - volatile tegra_car_t *car = car_get_regs(); volatile tegra_pmc_t *pmc = pmc_get_regs(); + volatile tegra_car_t *car = car_get_regs(); - /* This stuff was handled by whatever loaded us. */ + /* Bootrom stuff we skipped by going through RCM. */ config_se_brom(); AHB_AHB_SPARE_REG_0 &= 0xFFFFFF9F; pmc->scratch49 = (((pmc->scratch49 >> 1) << 1) & 0xFFFFFFFD); + /* Apply the memory built-in self test workaround. */ mbist_workaround(); + /* Reboot SE. */ clkrst_reboot(CARDEVICE_SE); + /* Initialize the fuse driver. */ fuse_init(); + /* Initialize the memory controller. */ mc_enable(); - + + /* Configure oscillators. */ + config_oscillators(); + /* Disable pinmux tristate input clamping. */ APB_MISC_PP_PINMUX_GLOBAL_0 = 0; diff --git a/sept/sept-secondary/src/key_derivation.c b/sept/sept-secondary/src/key_derivation.c index 0567d510a..5e05bed0a 100644 --- a/sept/sept-secondary/src/key_derivation.c +++ b/sept/sept-secondary/src/key_derivation.c @@ -48,7 +48,6 @@ static const uint8_t AL16 new_master_kek_seed_7x[0x10] = { void derive_7x_keys(const void *tsec_key, void *tsec_root_key) { uint8_t AL16 work_buffer[0x10]; - uint8_t AL16 master_kek[0x10]; /* Set keyslot flags properly in preparation of derivation. */ set_aes_keyslot_flags(0xE, 0x15); @@ -61,15 +60,12 @@ void derive_7x_keys(const void *tsec_key, void *tsec_root_key) { se_aes_ecb_decrypt_block(0xD, work_buffer, 0x10, keyblob_seed_00, 0x10); decrypt_data_into_keyslot(0xF, 0xE, work_buffer, 0x10); - /* Derive the master kek. */ - set_aes_keyslot(0xC, tsec_root_key, 0x10); - se_aes_ecb_decrypt_block(0xC, master_kek, 0x10, new_master_kek_seed_7x, 0x10); - /* Clear the SBK. */ clear_aes_keyslot(0xE); - - /* Set master kek. */ - set_aes_keyslot(0xC, master_kek, 0x10); + + /* Derive the master kek. */ + set_aes_keyslot(0xC, tsec_root_key, 0x10); + decrypt_data_into_keyslot(0xC, 0xC, new_master_kek_seed_7x, 0x10); /* Derive keys for exosphere. */ decrypt_data_into_keyslot(0xA, 0xF, devicekey_4x_seed, 0x10); @@ -78,8 +74,7 @@ void derive_7x_keys(const void *tsec_key, void *tsec_root_key) { decrypt_data_into_keyslot(0xC, 0xC, masterkey_seed, 0x10); /* Clear master kek from memory. */ - for (size_t i = 0; i < sizeof(master_kek); i++) { - master_kek[i] = 0xCC; + for (size_t i = 0; i < sizeof(work_buffer); i++) { work_buffer[i] = 0xCC; } } diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 856578423..a87efc830 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -83,7 +83,7 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { } /* Clear the security engine state. */ - for (size_t i = 0; i < 0x1000; i += 4) { + for (size_t i = 0; i < 0x840; i += 4) { MAKE_REG32((uintptr_t)(enc_se_state) + i) = 0xCCCCCCCC; MAKE_REG32((uintptr_t)(dec_se_state) + i) = 0xCCCCCCCC; } @@ -140,6 +140,9 @@ static void exit_callback(int rc) { } int main(void) { + const char *stage2_path; + stage2_args_t *stage2_args; + uint32_t stage2_version = 0; ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY; /* Extract keys from the security engine, which TSEC FW locked down. */ @@ -166,9 +169,18 @@ int main(void) { /* Mark EMC scratch to say that sept has run. */ MAKE_EMC_REG(EMC_SCRATCH0) |= 0x80000000; - while (true) { } - - /* TODO: Chainload to payload. */ + /* Load the loader payload into DRAM. */ + load_stage2(); + + /* Setup argument data. */ + stage2_path = stage2_get_program_path(); + strcpy(g_chainloader_arg_data, stage2_path); + stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */ + memcpy(&stage2_args->version, &stage2_version, 4); + memcpy(&stage2_args->log_level, &log_level, sizeof(log_level)); + stage2_args->display_initialized = false; + strcpy(stage2_args->bct0, ""); + g_chainloader_argc = 2; /* Wait a while. */ mdelay(1000); diff --git a/sept/sept-secondary/src/stage2.c b/sept/sept-secondary/src/stage2.c index 4d1e1d9da..1a6a05b04 100644 --- a/sept/sept-secondary/src/stage2.c +++ b/sept/sept-secondary/src/stage2.c @@ -25,59 +25,17 @@ const char *stage2_get_program_path(void) { return g_stage2_path; } -static int stage2_ini_handler(void *user, const char *section, const char *name, const char *value) { - stage2_config_t *config = (stage2_config_t *)user; - uintptr_t x = 0; - if (strcmp(section, "stage1") == 0) { - if (strcmp(name, STAGE2_NAME_KEY) == 0) { - strncpy(config->path, value, sizeof(config->path) - 1); - config->path[sizeof(config->path) - 1] = '\0'; - } else if (strcmp(name, STAGE2_ADDRESS_KEY) == 0) { - /* Read in load address as a hex string. */ - sscanf(value, "%x", &x); - config->load_address = x; - if (config->entrypoint == 0) { - config->entrypoint = config->load_address; - } - } else if (strcmp(name, STAGE2_ENTRYPOINT_KEY) == 0) { - /* Read in entrypoint as a hex string. */ - sscanf(value, "%x", &x); - config->entrypoint = x; - } else { - return 0; - } - } else { - return 0; - } - return 1; -} - -void load_stage2(const char *bct0) { - stage2_config_t config = {0}; +/* We get the luxury of assuming a constant filename/load address. */ +void load_stage2(void) { FILINFO info; size_t size; uintptr_t tmp_addr; - - if (ini_parse_string(bct0, stage2_ini_handler, &config) < 0) { - fatal_error("Failed to parse BCT.ini!\n"); - } - - if (config.load_address == 0 || config.path[0] == '\x00') { - fatal_error("Failed to determine where to load stage2!\n"); - } - - if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) { - print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n"); - } - - if (!check_32bit_address_loadable(config.entrypoint)) { - fatal_error("Stage2's entrypoint is invalid!\n"); - } - - if (!check_32bit_address_loadable(config.load_address)) { - fatal_error("Stage2's load address is invalid!\n"); - } - + stage2_config_t config = { + .path = "sept/payload.bin", + .load_address = 0xF0000000, + .entrypoint = 0xF0000000, + }; + print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n"); print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path); print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address); diff --git a/sept/sept-secondary/src/stage2.h b/sept/sept-secondary/src/stage2.h index e453d159f..3b2579d74 100644 --- a/sept/sept-secondary/src/stage2.h +++ b/sept/sept-secondary/src/stage2.h @@ -50,6 +50,6 @@ typedef struct { } stage2_args_t; const char *stage2_get_program_path(void); -void load_stage2(const char *bct0); +void load_stage2(void); #endif From d0ff791260978cfc7754922951dd790c9b71c7c1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 13:12:53 -0800 Subject: [PATCH 420/489] fusee: remove print in panic --- fusee/fusee-secondary/src/utils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fusee/fusee-secondary/src/utils.c b/fusee/fusee-secondary/src/utils.c index 698cf7cd8..a847320a6 100644 --- a/fusee/fusee-secondary/src/utils.c +++ b/fusee/fusee-secondary/src/utils.c @@ -153,7 +153,6 @@ void wait_for_button(void) { } __attribute__ ((noreturn)) void generic_panic(void) { - print(SCREEN_LOG_LEVEL_ERROR, "generic panic from %p", __builtin_return_address(0)); panic(0xFF000006); } From 7d170259d3331f92d0b719831a9cd552a2acb3cf Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 13:26:54 -0800 Subject: [PATCH 421/489] sept-s: fix building without keys (output won't work though) --- sept/sept-secondary/KEYS_template.py | 7 +++++++ sept/sept-secondary/Makefile | 2 +- sept/sept-secondary/sept_sign.py | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 sept/sept-secondary/KEYS_template.py diff --git a/sept/sept-secondary/KEYS_template.py b/sept/sept-secondary/KEYS_template.py new file mode 100644 index 000000000..a4a0ee971 --- /dev/null +++ b/sept/sept-secondary/KEYS_template.py @@ -0,0 +1,7 @@ +HOVI_ENC_KEY_PRD = '00000000000000000000000000000000'.decode('hex') +HOVI_ENC_KEY_DEV = '00000000000000000000000000000000'.decode('hex') +HOVI_SIG_KEY_PRD = '00000000000000000000000000000000'.decode('hex') +HOVI_SIG_KEY_DEV = '00000000000000000000000000000000'.decode('hex') +HOVI_KEK_KEY_PRD = '00000000000000000000000000000000'.decode('hex') +HOVI_KEK_KEY_DEV = '00000000000000000000000000000000'.decode('hex') +IV = '00000000000000000000000000000000'.decode('hex') \ No newline at end of file diff --git a/sept/sept-secondary/Makefile b/sept/sept-secondary/Makefile index 015822d91..b09d2359d 100644 --- a/sept/sept-secondary/Makefile +++ b/sept/sept-secondary/Makefile @@ -132,7 +132,7 @@ clean: #--------------------------------------------------------------------------------- else -.PHONY: all +.PHONY: all $(OUTPUT).enc DEPENDS := $(OFILES:.o=.d) diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py index c764a7598..ff49bea2d 100644 --- a/sept/sept-secondary/sept_sign.py +++ b/sept/sept-secondary/sept_sign.py @@ -3,7 +3,11 @@ import sys from struct import pack as pk, unpack as up from Crypto.Cipher import AES from Crypto.Hash import CMAC -import KEYS +try: + import KEYS +except ImportError: + import KEYS_template as KEYS + print('Warning: output will not work on 7.0.0+!') def shift_left_xor_rb(s): N = int(s.encode('hex'), 16) From 8cff208d3642db0d9cbe7493509fbdaf503f11b2 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 13:37:40 -0800 Subject: [PATCH 422/489] lightweight sept dox --- docs/components/fusee/sept.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/components/fusee/sept.md diff --git a/docs/components/fusee/sept.md b/docs/components/fusee/sept.md new file mode 100644 index 000000000..6d15be23e --- /dev/null +++ b/docs/components/fusee/sept.md @@ -0,0 +1,15 @@ +# sept +Sept is a payload that facilitates booting Atmosphère when targeting firmware version 7.0.0+. + +It consists of a primary and a secondary payload. + +## Sept-Primary +Sept-primary is essentially a stand-in for Nintendo's package1ldr, on 7.0.0+. To use it, the caller (normally Fusée-secondary) loads the sept-primary binary to `0x4003F000`, +loads the 7.0.0+ TSEC firmware to `0x40010F00`, and loads a signed, encrypted payload to `0x40016FE0`. + +This signed, encrypted payload is normally Sept-secondary. + +## Sept-Secondary +Sept-secondary is a payload that performs 7.0.0+ key derivation, and then chainloads to `sept/payload.bin`. + +It is normally stored encrypted/signed; if one wishes to build sept-secondary instead of using release builds, one must bring his/her own keys. From 9979cec045e012a356a4457b9971141bb5405091 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 13:42:05 -0800 Subject: [PATCH 423/489] update makefile for sept --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index cdc0d4dd0..83ce6f53c 100644 --- a/Makefile +++ b/Makefile @@ -44,12 +44,14 @@ dist: all rm -rf out mkdir atmosphere-$(AMSVER) mkdir atmosphere-$(AMSVER)/atmosphere + mkdir atmosphere-$(AMSVER)/sept mkdir atmosphere-$(AMSVER)/switch mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000036 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000034 mkdir -p atmosphere-$(AMSVER)/atmosphere/titles/0100000000000032 cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin + cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini cp common/defaults/system_settings.ini atmosphere-$(AMSVER)/atmosphere/system_settings.ini From 92d8829ee1c042ee66454984d10248ae308599ad Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 13:50:18 -0800 Subject: [PATCH 424/489] makefile: include sept binaries so people don't have to extract from embedded-in-fusee --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 83ce6f53c..9bf986357 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,10 @@ stratosphere: exosphere troposphere: stratosphere $(MAKE) -C troposphere all -fusee: exosphere stratosphere +sept: exosphere + $(MAKE) -C sept all + +fusee: exosphere stratosphere sept $(MAKE) -C $@ all clean: @@ -52,6 +55,9 @@ dist: all cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin + cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin + cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin + cp sept/sept-secondary/sept-secondary.enc atmosphere-$(AMSVER)/sept/sept-secondary.enc cp common/defaults/BCT.ini atmosphere-$(AMSVER)/atmosphere/BCT.ini cp common/defaults/loader.ini atmosphere-$(AMSVER)/atmosphere/loader.ini cp common/defaults/system_settings.ini atmosphere-$(AMSVER)/atmosphere/system_settings.ini From f00dd05f825521c052867f8f966a18b0b67b42fc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 14:17:51 -0800 Subject: [PATCH 425/489] Make stratosphere use new libnx HosVersion API --- stratosphere/ams_mitm/source/amsmitm_main.cpp | 2 ++ stratosphere/boot/source/boot_main.cpp | 2 ++ stratosphere/creport/source/creport_main.cpp | 2 ++ stratosphere/fatal/source/fatal_main.cpp | 2 ++ stratosphere/libstratosphere | 2 +- stratosphere/loader/source/ldr_main.cpp | 2 ++ stratosphere/pm/source/pm_main.cpp | 2 ++ stratosphere/sm/source/sm_main.cpp | 4 +++- 8 files changed, 16 insertions(+), 2 deletions(-) diff --git a/stratosphere/ams_mitm/source/amsmitm_main.cpp b/stratosphere/ams_mitm/source/amsmitm_main.cpp index 8f1a5f84b..54a0bf3d5 100644 --- a/stratosphere/ams_mitm/source/amsmitm_main.cpp +++ b/stratosphere/ams_mitm/source/amsmitm_main.cpp @@ -56,6 +56,8 @@ void __libnx_initheap(void) { void __appInit(void) { Result rc; + SetFirmwareVersionForLibnx(); + rc = smInitialize(); if (R_FAILED(rc)) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); diff --git a/stratosphere/boot/source/boot_main.cpp b/stratosphere/boot/source/boot_main.cpp index 1709654bf..55b8882eb 100644 --- a/stratosphere/boot/source/boot_main.cpp +++ b/stratosphere/boot/source/boot_main.cpp @@ -65,6 +65,8 @@ void __libnx_initheap(void) { void __appInit(void) { Result rc; + + SetFirmwareVersionForLibnx(); /* Initialize services we need (TODO: NCM) */ rc = smInitialize(); diff --git a/stratosphere/creport/source/creport_main.cpp b/stratosphere/creport/source/creport_main.cpp index d106268e8..8dd617769 100644 --- a/stratosphere/creport/source/creport_main.cpp +++ b/stratosphere/creport/source/creport_main.cpp @@ -54,6 +54,8 @@ void __libnx_initheap(void) { void __appInit(void) { Result rc; + + SetFirmwareVersionForLibnx(); rc = smInitialize(); if (R_FAILED(rc)) { diff --git a/stratosphere/fatal/source/fatal_main.cpp b/stratosphere/fatal/source/fatal_main.cpp index 3c26538c2..fc2865629 100644 --- a/stratosphere/fatal/source/fatal_main.cpp +++ b/stratosphere/fatal/source/fatal_main.cpp @@ -63,6 +63,8 @@ void __libnx_initheap(void) { void __appInit(void) { Result rc; + SetFirmwareVersionForLibnx(); + rc = smInitialize(); if (R_FAILED(rc)) { std::abort(); diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index a2c74f8cd..3de9d6c9d 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit a2c74f8cd5311f8050bcc5ea7d07b1ba4b697558 +Subproject commit 3de9d6c9d6ec91ac9f056c3683c19f50b6a7016d diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index f4118afc7..8060fdd55 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -58,6 +58,8 @@ void __libnx_initheap(void) { void __appInit(void) { Result rc; + + SetFirmwareVersionForLibnx(); /* Initialize services we need (TODO: SPL) */ rc = smInitialize(); diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 42f72fdd4..fae9dc3d1 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -85,6 +85,8 @@ void RegisterPrivilegedProcessesWithFs() { void __appInit(void) { Result rc; + + SetFirmwareVersionForLibnx(); rc = smInitialize(); if (R_FAILED(rc)) { diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index f97c34283..52c266f96 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -55,7 +55,9 @@ void __libnx_initheap(void) { } void __appInit(void) { - /* We must do no setup here, because we are sm. */ + SetFirmwareVersionForLibnx(); + + /* We must do no service setup here, because we are sm. */ } void __appExit(void) { From a0acbda9ce420bd8e11cb7d1bc1b0259e83d1bc5 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 14:23:38 -0800 Subject: [PATCH 426/489] creport: include firmware version header --- stratosphere/creport/source/creport_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stratosphere/creport/source/creport_main.cpp b/stratosphere/creport/source/creport_main.cpp index 8dd617769..3410a430a 100644 --- a/stratosphere/creport/source/creport_main.cpp +++ b/stratosphere/creport/source/creport_main.cpp @@ -21,6 +21,7 @@ #include <malloc.h> #include <switch.h> +#include <stratosphere/firmware_version.hpp> #include "creport_crash_report.hpp" From d20cd73523acdf05285641a14e930adf2be51186 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 14:28:31 -0800 Subject: [PATCH 427/489] sept-s: redefine a while. --- sept/sept-secondary/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index a87efc830..5b792f79b 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -183,7 +183,7 @@ int main(void) { g_chainloader_argc = 2; /* Wait a while. */ - mdelay(1000); + mdelay(1500); /* Deinitialize the display, console, etc. */ cleanup_env(); From 37eb3315b6354bf82e70a77d84537670b2766bd4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 15:05:25 -0800 Subject: [PATCH 428/489] sept-s: splash! (thanks @CtCaer, @balika011) --- sept/sept-secondary/src/main.c | 17 +++++++---- sept/sept-secondary/src/splash.c | 48 ++++++++++++++++++++++++++++++++ sept/sept-secondary/src/splash.h | 23 +++++++++++++++ 3 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 sept/sept-secondary/src/splash.c create mode 100644 sept/sept-secondary/src/splash.h diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 5b792f79b..d97ec791c 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -26,6 +26,7 @@ #include "timers.h" #include "fs_utils.h" #include "stage2.h" +#include "splash.h" #include "chainloader.h" #include "sdmmc/sdmmc.h" #include "lib/fatfs/ff.h" @@ -118,6 +119,14 @@ static void setup_env(void) { /* Turn on the backlight after initializing the lfb */ /* to avoid flickering. */ display_backlight(true); + + /* Set display background color. */ + for (size_t i = 0; i < 1280 * 768 * 4; i += 4) { + MAKE_REG32((uintptr_t)g_framebuffer + i) = 0xFF37394C; + } + + /* Draw splash. */ + draw_splash((volatile uint32_t *)g_framebuffer); /* Set up the exception handlers. */ setup_exception_handlers(); @@ -143,7 +152,7 @@ int main(void) { const char *stage2_path; stage2_args_t *stage2_args; uint32_t stage2_version = 0; - ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY; + ScreenLogLevel log_level = SCREEN_LOG_LEVEL_NONE; /* Extract keys from the security engine, which TSEC FW locked down. */ exfiltrate_keys_and_reboot_if_needed(); @@ -153,10 +162,7 @@ int main(void) { /* Initialize the display, console, etc. */ setup_env(); - - /* Say hello. */ - print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re sept-secondary!\n"); - + /* Derive keys. */ derive_7x_keys(g_tsec_key, g_tsec_root_key); @@ -173,6 +179,7 @@ int main(void) { load_stage2(); /* Setup argument data. */ + log_level = SCREEN_LOG_LEVEL_MANDATORY; stage2_path = stage2_get_program_path(); strcpy(g_chainloader_arg_data, stage2_path); stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */ diff --git a/sept/sept-secondary/src/splash.c b/sept/sept-secondary/src/splash.c new file mode 100644 index 000000000..33cf6f719 --- /dev/null +++ b/sept/sept-secondary/src/splash.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include "splash.h" +#include "lib/lz.h" + +static const uint8_t s_splash[] = {0x01, 0x37, 0x39, 0x4C, 0x37, 0x39, 0x4C, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x30, 0x30, 0x01, 0x60, 0x60, 0x01, 0x57, 0x57, 0x73, 0x74, 0x82, 0xB4, 0xB5, 0xBC, 0xC6, 0xC7, 0xCC, 0xD9, 0xD9, 0xDD, 0xEB, 0xEB, 0xED, 0xFB, 0xFB, 0xFC, 0x61, 0x62, 0x71, 0x01, 0x82, 0x17, 0x82, 0x2C, 0x01, 0x81, 0x4C, 0x81, 0x4C, 0x38, 0x3A, 0x4D, 0x7A, 0x7B, 0x88, 0xDA, 0xDB, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x04, 0x04, 0x01, 0x08, 0x08, 0xFF, 0xFF, 0x01, 0x0F, 0x84, 0x01, 0x3E, 0x3F, 0x52, 0x87, 0x88, 0x94, 0x01, 0x83, 0x4E, 0x83, 0x7E, 0x52, 0x54, 0x64, 0xDF, 0xDF, 0xE2, 0x01, 0x0F, 0x83, 0x78, 0xF9, 0xF9, 0xFA, 0x01, 0x12, 0x84, 0x01, 0x42, 0x44, 0x56, 0xCF, 0xD0, 0xD4, 0xFF, 0xFF, 0xFF, 0x96, 0x97, 0xA1, 0x01, 0x83, 0x48, 0x83, 0x7E, 0x4E, 0x50, 0x61, 0xE8, 0xE8, 0xEA, 0x01, 0x09, 0x83, 0x78, 0xB9, 0xBA, 0xC1, 0x78, 0x7A, 0x86, 0x4C, 0x4E, 0x5F, 0x95, 0x96, 0xA0, 0x01, 0x12, 0x84, 0x01, 0x67, 0x69, 0x77, 0xFE, 0xFE, 0xFE, 0x01, 0x06, 0x18, 0x65, 0x66, 0x75, 0x01, 0x83, 0x45, 0x84, 0x01, 0xC4, 0xC5, 0xCB, 0x01, 0x06, 0x83, 0x51, 0xEF, 0xEF, 0xF0, 0x76, 0x77, 0x84, 0x01, 0x09, 0x18, 0x01, 0x15, 0x84, 0x01, 0x37, 0x39, 0x4C, 0xAA, 0xAB, 0xB3, 0x01, 0x06, 0x18, 0xD3, 0xD3, 0xD7, 0x01, 0x83, 0x42, 0x83, 0x7E, 0x6C, 0x6D, 0x7B, 0x01, 0x06, 0x83, 0x4E, 0xFD, 0xFD, 0xFD, 0x5F, 0x60, 0x6F, 0x01, 0x0C, 0x1B, 0x01, 0x18, 0x84, 0x01, 0x3E, 0x40, 0x53, 0xE2, 0xE3, 0xE5, 0x01, 0x06, 0x1B, 0x69, 0x6A, 0x78, 0x01, 0x83, 0x3F, 0x84, 0x01, 0xB3, 0xB4, 0xBB, 0x01, 0x06, 0x83, 0x4B, 0xAB, 0xAB, 0xB3, 0x01, 0x0F, 0x1B, 0x01, 0x18, 0x84, 0x01, 0x37, 0x39, 0x4C, 0x83, 0x85, 0x90, 0x01, 0x06, 0x1B, 0xA6, 0xA7, 0xAF, 0x01, 0x83, 0x3F, 0x84, 0x01, 0xEE, 0xEE, 0xF0, 0x01, 0x06, 0x83, 0x4B, 0x46, 0x48, 0x5A, 0x01, 0x2A, 0x84, 0x01, 0x5D, 0x5F, 0x6E, 0x01, 0x06, 0x1B, 0xDE, 0xDF, 0xE2, 0x01, 0x83, 0x3C, 0x83, 0x7E, 0x44, 0x46, 0x57, 0x01, 0x06, 0x83, 0x48, 0xE9, 0xE9, 0xEB, 0x01, 0x12, 0x1E, 0x01, 0x1B, 0x84, 0x01, 0x3B, 0x3D, 0x50, 0xFB, 0xFB, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, 0xF8, 0xF8, 0x01, 0x83, 0x3C, 0x84, 0x01, 0x55, 0x57, 0x67, 0x01, 0x06, 0x83, 0x63, 0xC8, 0xC8, 0xCD, 0x01, 0x2D, 0x84, 0x01, 0x37, 0x39, 0x4C, 0x01, 0x09, 0xA0, 0x32, 0x41, 0x43, 0x55, 0x01, 0x83, 0x39, 0x84, 0x01, 0x5C, 0x5E, 0x6D, 0x01, 0x06, 0x83, 0x45, 0xB8, 0xB9, 0xBF, 0x01, 0x39, 0x84, 0x01, 0x49, 0x4B, 0x5C, 0x01, 0x83, 0x39, 0x84, 0x01, 0x4C, 0x4D, 0x5E, 0x01, 0x06, 0x83, 0x45, 0xD7, 0xD8, 0xDB, 0x01, 0x2D, 0x84, 0x01, 0x39, 0x3B, 0x4E, 0x01, 0x06, 0xA4, 0x27, 0xFE, 0xFE, 0xFE, 0x3A, 0x3C, 0x4E, 0x01, 0x83, 0x39, 0x84, 0x01, 0x3A, 0x3C, 0x4F, 0x01, 0x09, 0x8F, 0x4B, 0x38, 0x3A, 0x4D, 0x01, 0x2A, 0x84, 0x01, 0x54, 0x56, 0x66, 0x01, 0x06, 0x1B, 0xEC, 0xEC, 0xEE, 0x01, 0x83, 0x3F, 0x98, 0x06, 0xCC, 0xCC, 0xD1, 0x01, 0x06, 0x83, 0x4B, 0x6F, 0x70, 0x7E, 0x01, 0x2A, 0x84, 0x01, 0xA3, 0xA4, 0xAC, 0x01, 0x07, 0xA8, 0x37, 0xB9, 0xC0, 0x01, 0x83, 0x3F, 0x84, 0x01, 0x8E, 0x8F, 0x9A, 0x01, 0x06, 0x83, 0x4B, 0xE1, 0xE1, 0xE4, 0x3B, 0x3D, 0x50, 0x01, 0x24, 0x84, 0x01, 0x54, 0x55, 0x65, 0xFA, 0xFA, 0x01, 0x07, 0xB0, 0x27, 0x7C, 0x7D, 0x89, 0x01, 0x83, 0x3F, 0x84, 0x01, 0x3C, 0x3E, 0x50, 0xDE, 0x01, 0x08, 0xB4, 0x07, 0xA4, 0xA5, 0xAE, 0x01, 0x21, 0x84, 0x01, 0x45, 0x47, 0x59, 0xD1, 0xD1, 0xD6, 0x01, 0x06, 0x18, 0xD0, 0xD1, 0xD5, 0x01, 0x12, 0x8C, 0x39, 0x01, 0x83, 0x33, 0x84, 0x04, 0x62, 0x63, 0x72, 0xFD, 0xFD, 0xFD, 0x01, 0x06, 0x83, 0x54, 0xC4, 0xC4, 0xCA, 0x45, 0x46, 0x58, 0x01, 0x18, 0x84, 0x01, 0x5F, 0x61, 0x70, 0xE6, 0xE6, 0xE9, 0x01, 0x06, 0x15, 0xF8, 0xF8, 0xF9, 0x55, 0x57, 0x67, 0x01, 0x83, 0x48, 0xB8, 0x11, 0xA4, 0xA4, 0xAD, 0x01, 0x09, 0xB8, 0x0E, 0xEC, 0xED, 0xEE, 0xAC, 0xAD, 0xB5, 0x71, 0x73, 0x80, 0x9D, 0x9E, 0xA7, 0x01, 0x06, 0x12, 0x74, 0x75, 0x82, 0x85, 0x86, 0x92, 0xC3, 0xC3, 0xC9, 0x01, 0x09, 0x8B, 0x7A, 0xFF, 0xFF, 0xFF, 0x92, 0x93, 0x9E, 0x01, 0x83, 0x4B, 0xC0, 0x10, 0x3C, 0x3E, 0x50, 0xA5, 0xA6, 0xAE, 0xFC, 0xFC, 0xFC, 0x01, 0x12, 0xC4, 0x0E, 0x01, 0x12, 0x12, 0xFA, 0xFA, 0xFA, 0x9B, 0x9C, 0xA5, 0x39, 0x3B, 0x01, 0x83, 0x3A, 0x9B, 0x7E, 0x01, 0x18, 0x18, 0x5F, 0x61, 0x70, 0xDA, 0xDA, 0x01, 0x13, 0xC8, 0x12, 0x01, 0x0C, 0x0C, 0xD1, 0xD1, 0xD6, 0x57, 0x59, 0x69, 0x01, 0x83, 0x5A, 0xCC, 0x19, 0x3A, 0x3C, 0x4E, 0x8A, 0x8B, 0x96, 0xC8, 0xC9, 0xCE, 0xF8, 0xF8, 0xF9, 0x01, 0x0C, 0x83, 0x78, 0xF6, 0xF6, 0xF7, 0xC4, 0xC4, 0xCA, 0x82, 0x83, 0x8F, 0x01, 0x83, 0x45, 0x93, 0x76, 0x01, 0x27, 0xA4, 0x24, 0x4C, 0x4D, 0x5E, 0x5E, 0x5F, 0x6F, 0x5C, 0x5E, 0x6D, 0x4B, 0x4D, 0x5E, 0x01, 0x83, 0x3C, 0xA7, 0x6F, 0x01, 0x83, 0x66, 0x87, 0x31, 0x01, 0x87, 0x1F, 0x87, 0x1F, 0x01, 0x89, 0x1B, 0x89, 0x1B, 0x40, 0x42, 0x54, 0x5F, 0x61, 0x70, 0x5F, 0x61, 0x70, 0x5F, 0x61, 0x70, 0x01, 0x83, 0x75, 0x97, 0x68, 0x57, 0x59, 0x69, 0x01, 0x09, 0x9F, 0x6A, 0x01, 0x83, 0x5D, 0xA3, 0x5F, 0x01, 0x18, 0x18, 0x3E, 0x3F, 0x52, 0x01, 0x09, 0xE7, 0x67, 0x75, 0x01, 0x0B, 0xE4, 0x13, 0x01, 0x83, 0x6C, 0x84, 0x04, 0x01, 0x09, 0xF0, 0x13, 0x93, 0x94, 0x01, 0x83, 0x4C, 0xB3, 0x5D, 0x01, 0x2A, 0x2A, 0x8C, 0x8D, 0x98, 0x01, 0x09, 0xDF, 0x62, 0x3A, 0x3C, 0x4F, 0x01, 0x83, 0x75, 0x94, 0x08, 0xEC, 0xED, 0xEE, 0x01, 0x83, 0x54, 0xBB, 0x62, 0x01, 0x2D, 0xB8, 0x05, 0xF6, 0xF6, 0xF7, 0xFF, 0xFF, 0xFF, 0xF5, 0xF5, 0xF6, 0x6B, 0x6D, 0x7B, 0x01, 0x83, 0x75, 0x84, 0x04, 0x6A, 0x6C, 0x7A, 0xE9, 0xE9, 0xEB, 0x01, 0x06, 0xDB, 0x67, 0xA5, 0xA6, 0xAE, 0x01, 0x0F, 0xD0, 0x1D, 0x01, 0x83, 0x5D, 0x98, 0x06, 0x6C, 0x6D, 0x7B, 0x6C, 0x6D, 0x7B, 0x6C, 0x6D, 0x7B, 0x75, 0x77, 0x84, 0xD9, 0xD9, 0xDD, 0x01, 0x06, 0x8C, 0x0C, 0xF3, 0xF3, 0xF4, 0xC3, 0xC3, 0xC9, 0x91, 0x92, 0x9C, 0x6D, 0x6F, 0x7D, 0x01, 0x09, 0x21, 0x01, 0x09, 0x09, 0x01, 0x0F, 0x0F, 0x01, 0x83, 0x3C, 0x84, 0x01, 0x51, 0x53, 0x63, 0x01, 0x24, 0xC8, 0x03, 0x01, 0x1E, 0x1E, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x87, 0x3D, 0x88, 0x02, 0x01, 0x06, 0x81, 0x98, 0x1D, 0x38, 0x3A, 0x4D, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x12, 0x12, 0x01, 0x97, 0x59, 0xC8, 0x2A, 0x01, 0x8C, 0x0F, 0x8C, 0x0F, 0x01, 0x83, 0x72, 0xA3, 0x6E, 0x01, 0x9F, 0x67, 0x81, 0xC4, 0x31, 0x4B, 0x4D, 0x5E, 0x4C, 0x4E, 0x5F, 0x01, 0x83, 0x78, 0x81, 0xC4, 0x31, 0x58, 0x5A, 0x6A, 0xE8, 0xE8, 0xEA, 0x01, 0x09, 0x83, 0x51, 0x01, 0x83, 0x6F, 0x81, 0xC4, 0x31, 0x69, 0x6A, 0x78, 0xF2, 0xF2, 0xF3, 0x01, 0x0C, 0x83, 0x51, 0x01, 0x83, 0x6C, 0x81, 0xC4, 0x31, 0x7C, 0x7D, 0x89, 0x01, 0x06, 0x81, 0xAB, 0x69, 0xFC, 0xFC, 0xFC, 0x53, 0x54, 0x65, 0x01, 0x83, 0x6F, 0x81, 0xC4, 0x31, 0x92, 0x93, 0x9E, 0x01, 0x09, 0xA3, 0x3E, 0x90, 0x91, 0x9C, 0x01, 0x83, 0x6F, 0x81, 0xC4, 0x31, 0x77, 0x78, 0x85, 0x01, 0x0C, 0xA7, 0x66, 0x01, 0x83, 0x72, 0x81, 0xC4, 0x31, 0x42, 0x44, 0x56, 0xF4, 0xF4, 0xF5, 0xFF, 0xFF, 0xFF, 0xDB, 0xDC, 0xDF, 0x3E, 0x40, 0x53, 0x01, 0x83, 0x75, 0x81, 0xC4, 0x31, 0xA3, 0xA4, 0xAC, 0xF1, 0xF1, 0xF3, 0x52, 0x54, 0x64, 0x01, 0x83, 0x78, 0x81, 0xC4, 0x31, 0x4B, 0x4D, 0x5E, 0x01, 0x12, 0x8B, 0x62, 0x01, 0xAC, 0x0E, 0x81, 0xC4, 0x31, 0x01, 0x8C, 0x15, 0x8C, 0x15, 0x3E, 0x40, 0x53, 0x5D, 0x5F, 0x6E, 0x7C, 0x7E, 0x8A, 0x95, 0x96, 0xA0, 0x98, 0x99, 0xA3, 0x98, 0x99, 0xA3, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0F, 0x0F, 0x01, 0x83, 0x48, 0x83, 0x7B, 0x59, 0x5B, 0x6A, 0xCC, 0xCD, 0xD2, 0x01, 0x09, 0xCC, 0x3A, 0x01, 0x83, 0x69, 0x81, 0xA8, 0x2A, 0x01, 0x06, 0xD3, 0x62, 0xA4, 0xA5, 0xAE, 0xFB, 0xFB, 0x01, 0x25, 0xB8, 0x0B, 0x01, 0x83, 0x54, 0x84, 0x01, 0x91, 0x93, 0x9D, 0x01, 0x12, 0x83, 0x57, 0xEC, 0xED, 0xEE, 0xD6, 0xD6, 0xDA, 0xD5, 0xD5, 0xD9, 0xD5, 0xD5, 0xD9, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0C, 0x0C, 0x01, 0x83, 0x42, 0x81, 0x80, 0x1A, 0xF7, 0xF8, 0xF8, 0x01, 0x09, 0x83, 0x78, 0xE6, 0xE6, 0xE9, 0x78, 0x79, 0x86, 0x01, 0x09, 0xC8, 0x15, 0x01, 0x83, 0x63, 0x93, 0x76, 0xB9, 0xBA, 0xC1, 0x01, 0x09, 0x83, 0x7E, 0xC0, 0xC0, 0xC6, 0x3F, 0x41, 0x01, 0x10, 0xD4, 0x36, 0x01, 0x83, 0x60, 0x84, 0x01, 0xE1, 0xE2, 0x01, 0x07, 0xFB, 0x69, 0xF0, 0xF1, 0xF2, 0x47, 0x49, 0x01, 0x10, 0xF4, 0x20, 0x01, 0x83, 0x60, 0x83, 0x7E, 0x3D, 0x3F, 0x51, 0x01, 0x09, 0xD4, 0x0F, 0x94, 0x95, 0x9F, 0x01, 0x83, 0x72, 0x9F, 0x76, 0x01, 0x09, 0xF0, 0x1C, 0xFF, 0xFF, 0xFF, 0x01, 0x83, 0x75, 0x81, 0xD8, 0x30, 0x01, 0x09, 0xFF, 0x67, 0xFF, 0xFF, 0xFF, 0x4B, 0x4D, 0x5E, 0x01, 0x83, 0x72, 0x84, 0x01, 0x45, 0x47, 0x59, 0x01, 0x83, 0x7E, 0x84, 0x01, 0x37, 0x39, 0x4C, 0x01, 0x06, 0x81, 0xE4, 0x33, 0xFF, 0xFF, 0xFF, 0x72, 0x74, 0x81, 0x01, 0x83, 0x75, 0x84, 0x01, 0xB8, 0xB9, 0xBF, 0x01, 0x06, 0x84, 0x01, 0x9A, 0x9B, 0xA5, 0x01, 0x83, 0x78, 0x81, 0xE8, 0x34, 0x01, 0x06, 0x84, 0x01, 0xDC, 0xDC, 0xE0, 0x3C, 0x3E, 0x01, 0x81, 0x17, 0x81, 0xE8, 0x31, 0x6D, 0x6E, 0x79, 0xD9, 0xD9, 0xDB, 0xD9, 0xD9, 0xDB, 0x6D, 0x6E, 0x79, 0x01, 0x2D, 0x39, 0xAE, 0xAE, 0xB4, 0xCE, 0xCF, 0xD2, 0xC4, 0xC4, 0xC8, 0x01, 0x82, 0x1D, 0x84, 0x04, 0xC7, 0xC7, 0xCD, 0x01, 0x81, 0x1F, 0x81, 0x97, 0x73, 0x7C, 0x7D, 0x86, 0x01, 0x08, 0xF9, 0x0D, 0x86, 0x01, 0x2D, 0x39, 0xD9, 0xD9, 0xDB, 0x01, 0x08, 0x91, 0x62, 0x5D, 0x01, 0x82, 0x1A, 0x84, 0x01, 0x43, 0x45, 0x57, 0x01, 0x06, 0xA4, 0x0F, 0xFE, 0xFE, 0xFE, 0x82, 0x83, 0x8F, 0x01, 0x81, 0x4C, 0x84, 0x01, 0xB9, 0xB9, 0xBE, 0x01, 0x36, 0x39, 0x01, 0x81, 0x73, 0x82, 0xD0, 0x5D, 0xC1, 0xC2, 0xC8, 0x01, 0x06, 0x82, 0x2C, 0xCF, 0xCF, 0xD4, 0x5E, 0x5F, 0x01, 0x0D, 0x81, 0xA4, 0x32, 0x01, 0x81, 0x3A, 0x84, 0x01, 0xAE, 0xAE, 0xB4, 0x01, 0x06, 0x39, 0xAE, 0xAE, 0xB4, 0x01, 0x81, 0x79, 0x83, 0x5D, 0x46, 0x48, 0x5A, 0x95, 0x96, 0xA0, 0x95, 0x96, 0xA0, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0F, 0x0F, 0xD4, 0xD5, 0xD9, 0x01, 0x06, 0x82, 0x2F, 0xFE, 0xFE, 0xFE, 0xE7, 0xE7, 0xE9, 0xC8, 0xC9, 0xCE, 0xA9, 0xAA, 0xB2, 0x96, 0x97, 0xA1, 0x01, 0x1E, 0x36, 0x01, 0x83, 0x21, 0x84, 0x01, 0x01, 0x0C, 0x82, 0x94, 0x2A, 0x01, 0x42, 0x81, 0xEC, 0x29, 0x01, 0x75, 0xC0, 0x10, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x39, 0x84, 0x01, 0xE3, 0x01, 0x08, 0x81, 0xB1, 0x54, 0xA3, 0xA3, 0xA9, 0x01, 0x81, 0x79, 0x84, 0x01, 0x50, 0x52, 0x63, 0xD7, 0xD7, 0xDB, 0xD7, 0xD7, 0xDB, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x2D, 0x2D, 0x01, 0x81, 0x19, 0x84, 0x01, 0xC4, 0xC4, 0x01, 0x07, 0x91, 0x56, 0xFF, 0xFF, 0xFF, 0x01, 0x30, 0x9C, 0x40, 0x01, 0x83, 0x00, 0xA1, 0x1E, 0xAE, 0xAE, 0xB4, 0xAE, 0xAE, 0xB4, 0x01, 0x06, 0x06, 0xAE, 0xAE, 0xB4, 0x01, 0x09, 0x83, 0x4B, 0xC4, 0xC4, 0xC8, 0x01, 0x0F, 0x1B, 0x01, 0x0F, 0x0F, 0x01, 0x06, 0x06, 0xB9, 0xB9, 0xBE, 0xEC, 0xEC, 0x01, 0x07, 0x82, 0x92, 0x19, 0xFF, 0xFF, 0xFF, 0xD9, 0xD9, 0x01, 0x64, 0x85, 0x26, 0x01, 0x82, 0x4D, 0x84, 0x01, 0x01, 0x4B, 0x8D, 0x22, 0xF6, 0xF6, 0xF6, 0x01, 0x83, 0x30, 0x87, 0x7F, 0x01, 0x4B, 0x84, 0x01, 0xEC, 0xEC, 0xEE, 0x01, 0x81, 0x1F, 0x83, 0x7E, 0x77, 0x7B, 0x88, 0xC4, 0xC8, 0xD1, 0xDD, 0xE4, 0xEB, 0xCC, 0xD3, 0xDC, 0x98, 0x9E, 0xAA, 0x44, 0x47, 0x01, 0x82, 0x06, 0xC7, 0x14, 0x01, 0x06, 0xAB, 0x79, 0x01, 0x06, 0x06, 0xD9, 0xD9, 0xDB, 0x01, 0x09, 0x93, 0x4C, 0xE3, 0xE3, 0xE5, 0x01, 0x0F, 0x1B, 0x01, 0x0F, 0x0F, 0x01, 0x09, 0x09, 0xAE, 0xAE, 0xB4, 0x89, 0x8A, 0x93, 0x01, 0x81, 0x1F, 0x82, 0xFF, 0x5C, 0xBD, 0xC1, 0xC9, 0xEF, 0xF5, 0xF9, 0xED, 0xF4, 0xF8, 0xEB, 0xF2, 0xF8, 0xE8, 0xF0, 0xF6, 0xE6, 0xEF, 0xF6, 0xD6, 0xDF, 0xE6, 0x64, 0x69, 0x01, 0x82, 0x12, 0x89, 0x30, 0x01, 0x39, 0x98, 0x06, 0x01, 0x81, 0x19, 0x81, 0x52, 0x5A, 0x5C, 0x6C, 0xDC, 0xDF, 0xE4, 0xF2, 0xF7, 0xFA, 0xEF, 0xF5, 0xF9, 0xED, 0xF3, 0xF8, 0xEA, 0xF1, 0xF7, 0xE8, 0xF0, 0xF7, 0xE5, 0xEE, 0xF5, 0xE3, 0xED, 0xF5, 0xDE, 0xE9, 0xF1, 0x84, 0x8A, 0x99, 0x01, 0x83, 0x5D, 0x84, 0x01, 0x7D, 0x7F, 0x8C, 0xF0, 0xF4, 0xF6, 0xF5, 0xF9, 0xFB, 0xF2, 0xF6, 0x01, 0x05, 0x84, 0x01, 0x01, 0x0B, 0x88, 0x02, 0xE3, 0xED, 0xF4, 0xE1, 0xEC, 0xF4, 0xDE, 0xEA, 0xF3, 0xA5, 0xAE, 0xBB, 0x3F, 0x41, 0x54, 0x01, 0x83, 0x51, 0x84, 0x01, 0x3A, 0x3C, 0x4F, 0xA8, 0xA9, 0xB2, 0xF9, 0xFC, 0xFD, 0xF7, 0xFA, 0xFC, 0x01, 0x1E, 0x84, 0x01, 0xDB, 0xE8, 0xF1, 0xC0, 0xCA, 0xD6, 0x4F, 0x53, 0x01, 0x13, 0x81, 0xAB, 0x5D, 0x01, 0x83, 0x39, 0x84, 0x01, 0x49, 0x4B, 0x5C, 0xCF, 0xD0, 0xD4, 0xFB, 0xFC, 0xFD, 0xF9, 0xFB, 0xFD, 0xF6, 0xF9, 0xFC, 0xF4, 0xF8, 0xFB, 0xF2, 0xF7, 0xFA, 0xF0, 0xF5, 0xF9, 0xEC, 0x01, 0x07, 0x8C, 0x03, 0x01, 0x06, 0x84, 0x01, 0xF5, 0xE0, 0xEB, 0xF3, 0xDE, 0xEA, 0xF3, 0xDC, 0xE8, 0xF2, 0xD9, 0xE6, 0xF1, 0xCF, 0xDC, 0xE7, 0x67, 0x6E, 0x7F, 0x01, 0x83, 0x45, 0xC2, 0x78, 0x64, 0x66, 0x74, 0xEB, 0xEB, 0xED, 0xFE, 0xFF, 0xFF, 0xFC, 0xFD, 0xFE, 0x01, 0x27, 0x88, 0x02, 0xDA, 0xE7, 0xF1, 0xD7, 0xE5, 0xF0, 0xD4, 0xE3, 0xEF, 0x87, 0x90, 0xA0, 0x01, 0x83, 0x3F, 0x81, 0x9F, 0x1E, 0x8A, 0x8C, 0x97, 0x01, 0x06, 0x81, 0xC3, 0x18, 0xFF, 0xFF, 0xFF, 0x01, 0x2D, 0x88, 0x02, 0x01, 0x06, 0x84, 0x01, 0xD2, 0xE2, 0xEE, 0xA5, 0xB1, 0xC1, 0x42, 0x44, 0x57, 0x01, 0x6C, 0xAC, 0x3E, 0x83, 0x85, 0x90, 0x9B, 0x9C, 0xA5, 0xAC, 0xAD, 0xB5, 0xAB, 0xAC, 0xB4, 0x9B, 0x9C, 0xA5, 0x83, 0x84, 0x90, 0x50, 0x51, 0x62, 0x01, 0x82, 0x35, 0xE2, 0x7A, 0xB4, 0xB5, 0xBC, 0x01, 0x0C, 0xA1, 0x1B, 0x01, 0x36, 0x84, 0x01, 0xCF, 0xE0, 0xED, 0xBA, 0xC9, 0xD7, 0x53, 0x58, 0x6A, 0x01, 0x62, 0xCA, 0x7D, 0x7C, 0xDD, 0xDD, 0xE0, 0x01, 0x18, 0xA2, 0x58, 0xDA, 0xDB, 0xDE, 0x68, 0x69, 0x01, 0x82, 0x2A, 0x81, 0xE4, 0x2A, 0x50, 0x51, 0x62, 0xD8, 0xD8, 0xDC, 0x01, 0x0C, 0x82, 0x41, 0xFE, 0xFE, 0xFE, 0xFC, 0xFD, 0xFE, 0xFA, 0x01, 0x05, 0x8C, 0x03, 0x01, 0x08, 0x84, 0x01, 0xFA, 0xED, 0xF3, 0xF8, 0xEB, 0xF2, 0x01, 0x09, 0x84, 0x01, 0xF4, 0xE0, 0xEB, 0xF3, 0xDF, 0xEA, 0xF3, 0xDB, 0xE8, 0xF2, 0xD9, 0xE7, 0xF1, 0xD6, 0x01, 0x08, 0x84, 0x01, 0xD0, 0xE0, 0xED, 0xCC, 0xDE, 0xEC, 0xC5, 0xD8, 0xE5, 0x6B, 0x75, 0x01, 0x58, 0x92, 0x06, 0x4A, 0x4C, 0x5D, 0xBA, 0xBB, 0x01, 0x0A, 0xF0, 0x28, 0x01, 0x1B, 0xA6, 0x5F, 0xB6, 0xB6, 0xBD, 0x48, 0x4A, 0x5B, 0x01, 0x82, 0x20, 0x83, 0x7E, 0x6D, 0x6E, 0x7C, 0xF0, 0xF0, 0xF1, 0x01, 0x12, 0x82, 0x3E, 0x01, 0x39, 0x88, 0x02, 0xCD, 0xDE, 0xEC, 0xCB, 0xDD, 0xEC, 0xC8, 0xDC, 0xEA, 0x88, 0x95, 0xA6, 0x01, 0x51, 0x81, 0x2E, 0x66, 0x67, 0x76, 0x01, 0x06, 0x81, 0xC8, 0x56, 0x01, 0x0C, 0x81, 0x2B, 0xF3, 0xF3, 0xF4, 0xCF, 0xD0, 0xD4, 0xD6, 0xD6, 0xDA, 0xF7, 0xF7, 0x01, 0x07, 0xDC, 0x3B, 0x01, 0x09, 0x1B, 0xF2, 0xF2, 0xF3, 0x5B, 0x5C, 0x6C, 0x01, 0x82, 0x1A, 0x83, 0x7E, 0x95, 0x96, 0xA0, 0x01, 0x09, 0xEE, 0x74, 0x01, 0x4B, 0x88, 0x02, 0xCB, 0xDD, 0xEB, 0xC8, 0xDC, 0xEB, 0xC5, 0xDA, 0xE9, 0x7D, 0x89, 0x9A, 0x01, 0x4B, 0x81, 0x2E, 0x41, 0x43, 0x55, 0xE5, 0xE5, 0xE7, 0x01, 0x0C, 0x81, 0x80, 0x1A, 0x83, 0x85, 0x90, 0x4E, 0x50, 0x61, 0x01, 0x0C, 0x82, 0x80, 0x5B, 0x54, 0x55, 0x65, 0x93, 0x94, 0x9E, 0x01, 0x09, 0xE0, 0x45, 0x01, 0x06, 0x8C, 0x0F, 0x01, 0x82, 0x14, 0x82, 0xC0, 0x77, 0x41, 0x43, 0x55, 0xBF, 0xC0, 0xC6, 0x01, 0x18, 0x8A, 0x3D, 0x01, 0x48, 0x84, 0x01, 0xC3, 0xD8, 0xE9, 0x50, 0x56, 0x68, 0x01, 0x48, 0x81, 0x34, 0xB1, 0xB2, 0xB9, 0x01, 0x09, 0x81, 0x22, 0xAF, 0xB0, 0xB8, 0x44, 0x46, 0x01, 0x19, 0x94, 0x6E, 0x4F, 0x51, 0x61, 0xC4, 0xC4, 0xCA, 0x01, 0x09, 0x2D, 0xA1, 0xA2, 0xAB, 0x01, 0x7B, 0x82, 0x6B, 0x89, 0x8A, 0x93, 0xC4, 0xC4, 0xC8, 0x01, 0x09, 0xD7, 0x78, 0xF6, 0xF6, 0xF6, 0x01, 0x06, 0xB0, 0x03, 0x01, 0x7B, 0xB3, 0x7E, 0x56, 0x58, 0x68, 0x01, 0x12, 0x82, 0x83, 0x07, 0x01, 0x0D, 0x84, 0x01, 0x01, 0x06, 0x9C, 0x07, 0xFB, 0x01, 0x0F, 0x9C, 0x07, 0xF9, 0x01, 0x08, 0x84, 0x01, 0xF5, 0x01, 0x12, 0x9C, 0x07, 0xD5, 0xE4, 0x01, 0x08, 0x8C, 0x03, 0xDF, 0xED, 0xCA, 0xDD, 0xEB, 0xC8, 0xDB, 0xEA, 0xC6, 0xDA, 0xEA, 0xC3, 0xD8, 0xE9, 0x76, 0x83, 0x01, 0x0A, 0x81, 0xDB, 0x7E, 0x01, 0x3C, 0x81, 0x34, 0x6F, 0x70, 0x7E, 0x01, 0x09, 0x81, 0x1F, 0xB0, 0xB1, 0xB8, 0x01, 0x24, 0x82, 0x88, 0x69, 0xCF, 0xCF, 0xD4, 0x01, 0x0A, 0x81, 0xF8, 0x71, 0x61, 0x70, 0x01, 0x72, 0x82, 0x68, 0x96, 0x97, 0x9E, 0x01, 0x0C, 0xBF, 0x6F, 0x01, 0x12, 0x82, 0x68, 0x01, 0x33, 0xE0, 0x42, 0x01, 0x45, 0x81, 0xDB, 0x1E, 0x01, 0x12, 0x8E, 0x47, 0x01, 0x54, 0x88, 0x02, 0xBD, 0xD1, 0xE6, 0x8A, 0xA0, 0xD2, 0x6E, 0x7E, 0x01, 0x46, 0xC9, 0x64, 0xBD, 0xBE, 0xC4, 0x01, 0x06, 0x81, 0x1C, 0xE5, 0xE5, 0xE7, 0x01, 0x27, 0x81, 0xEC, 0x05, 0x51, 0x53, 0x63, 0xF5, 0xF5, 0xF6, 0x01, 0x06, 0x36, 0xA8, 0xA9, 0xB1, 0x01, 0x6E, 0x81, 0xD1, 0x7D, 0x5D, 0xCE, 0xCF, 0xD2, 0x01, 0x27, 0xBC, 0x0C, 0x96, 0x97, 0x01, 0x67, 0x81, 0xCD, 0x55, 0x38, 0x3A, 0x4D, 0xA1, 0xA2, 0xAB, 0x01, 0x24, 0x81, 0x13, 0x01, 0x42, 0x88, 0x02, 0xAA, 0xC0, 0xDF, 0x7C, 0x93, 0xCD, 0x7A, 0x8F, 0xCD, 0x55, 0x60, 0x87, 0x01, 0x45, 0xAD, 0x1B, 0x01, 0x09, 0x83, 0x4B, 0x01, 0x0C, 0x82, 0x84, 0x3B, 0x01, 0x21, 0x39, 0x99, 0x9A, 0xA3, 0x01, 0x06, 0x36, 0xE2, 0xE3, 0xE5, 0x01, 0x6C, 0x83, 0x7E, 0x01, 0x09, 0xBC, 0x18, 0x01, 0x06, 0x06, 0xCE, 0xCF, 0xD2, 0xA3, 0xA3, 0xA9, 0x7C, 0x7D, 0x86, 0x7C, 0x7D, 0x86, 0x7C, 0x7D, 0x86, 0xAE, 0xAE, 0xB4, 0x01, 0x0F, 0x21, 0xB9, 0xB9, 0xBE, 0x01, 0x63, 0xF6, 0x61, 0xC8, 0xC9, 0xCE, 0x01, 0x27, 0x85, 0x14, 0x01, 0x3C, 0x84, 0x01, 0xC5, 0xD8, 0xEA, 0x91, 0xA7, 0xD6, 0x7C, 0x93, 0xCE, 0x7B, 0x91, 0xCE, 0x77, 0x8C, 0xCA, 0x3D, 0x41, 0x01, 0x43, 0xA4, 0x18, 0x4E, 0x50, 0x61, 0x01, 0x09, 0x81, 0x1C, 0x01, 0x2D, 0x9B, 0x5A, 0x69, 0x6B, 0x79, 0x01, 0x06, 0x36, 0xFC, 0xFC, 0xFC, 0x01, 0x69, 0xA9, 0x26, 0x01, 0x0C, 0xCF, 0x64, 0xE3, 0xE3, 0xE5, 0x5D, 0x5E, 0x6B, 0x01, 0x18, 0xB0, 0x39, 0x01, 0x0C, 0x8C, 0x21, 0x01, 0x5D, 0x88, 0x08, 0x5E, 0x5F, 0x6F, 0x01, 0x09, 0x81, 0xDA, 0x47, 0x01, 0x25, 0x84, 0x01, 0xFE, 0xFF, 0x01, 0x06, 0x8C, 0x03, 0x01, 0x0C, 0x9C, 0x07, 0xED, 0xF3, 0xF8, 0xEA, 0xF2, 0xF7, 0xE8, 0xF1, 0x01, 0x07, 0xBC, 0x0F, 0x01, 0x05, 0x84, 0x01, 0xF2, 0x01, 0x05, 0x9C, 0x07, 0xF0, 0x01, 0x09, 0x9C, 0x07, 0xB2, 0xC6, 0xE3, 0x82, 0x9A, 0xCF, 0x7C, 0x95, 0xCE, 0x7C, 0x93, 0xCE, 0x7A, 0x90, 0xCE, 0x60, 0x6F, 0x9D, 0x01, 0x45, 0x81, 0x40, 0x61, 0x62, 0x71, 0x01, 0x07, 0x81, 0xFC, 0x3F, 0xEA, 0xEC, 0x01, 0x36, 0x83, 0xC1, 0x29, 0x01, 0x30, 0x84, 0x3A, 0x01, 0x3C, 0x93, 0x73, 0x01, 0x09, 0x72, 0x01, 0x21, 0xEF, 0x6C, 0x01, 0x0C, 0x88, 0x2C, 0xF6, 0xF6, 0xF6, 0x01, 0x57, 0xEC, 0x18, 0x81, 0x82, 0x8E, 0x01, 0x0F, 0x81, 0xCE, 0x59, 0x01, 0x54, 0x88, 0x02, 0xD3, 0xE2, 0xEE, 0x9E, 0xB5, 0xDB, 0x7E, 0x99, 0xD0, 0x7D, 0x96, 0xCF, 0x7C, 0x94, 0xCF, 0x7A, 0x91, 0xCD, 0x79, 0x8F, 0xCD, 0x44, 0x49, 0x01, 0x07, 0x81, 0xF3, 0x7E, 0x01, 0x40, 0x81, 0xD4, 0x26, 0x60, 0x6F, 0x01, 0x07, 0x81, 0xFC, 0x3F, 0xC9, 0xCE, 0x01, 0x30, 0x3C, 0x01, 0x09, 0x86, 0x66, 0x01, 0x66, 0x81, 0xFC, 0x3F, 0x01, 0x0C, 0xC8, 0x15, 0x01, 0x27, 0x8C, 0x30, 0x01, 0x09, 0x81, 0x22, 0x01, 0x51, 0xE0, 0x15, 0x3A, 0x3C, 0x4F, 0xAC, 0xAD, 0xB5, 0x01, 0x33, 0xCD, 0x23, 0x01, 0x30, 0x88, 0x02, 0xD2, 0xE1, 0xEE, 0x96, 0xAF, 0xD8, 0x80, 0x9A, 0xD1, 0x7E, 0x98, 0xD0, 0x7C, 0x95, 0xCE, 0x7B, 0x92, 0xCE, 0x7A, 0x90, 0xCE, 0x6A, 0x7A, 0xB0, 0x01, 0x4B, 0xE8, 0x35, 0x01, 0x07, 0x81, 0xEC, 0x38, 0xE2, 0x01, 0x2E, 0x8F, 0x4B, 0x3E, 0x40, 0x53, 0x01, 0x06, 0xA1, 0x69, 0xF3, 0xF3, 0xF4, 0x01, 0x66, 0xF8, 0x1E, 0x01, 0x09, 0x82, 0x44, 0x01, 0x18, 0x8B, 0x7A, 0x01, 0x15, 0x98, 0x2D, 0x01, 0x09, 0x88, 0x05, 0x01, 0x4E, 0x81, 0xE7, 0x06, 0xD2, 0xD2, 0x01, 0x07, 0x81, 0xEA, 0x3C, 0x01, 0x5D, 0x84, 0x01, 0xD0, 0xDE, 0xED, 0x91, 0xAA, 0xD7, 0x80, 0x9B, 0xD1, 0x7E, 0x99, 0xD0, 0x7E, 0x97, 0xD0, 0x7C, 0x94, 0xCE, 0x7B, 0x92, 0xCE, 0x79, 0x8E, 0xCD, 0x50, 0x59, 0x7D, 0x01, 0x4B, 0x81, 0x4F, 0x01, 0x06, 0x99, 0x3A, 0xFE, 0xFE, 0xFE, 0x01, 0x2D, 0x87, 0x49, 0x62, 0x64, 0x73, 0x01, 0x06, 0x81, 0x52, 0xD8, 0xD8, 0xDC, 0x01, 0x64, 0x81, 0xED, 0x7B, 0xA3, 0xA9, 0x01, 0x09, 0x93, 0x76, 0x01, 0x2F, 0x81, 0x85, 0x7F, 0x01, 0x07, 0x95, 0x63, 0x01, 0x48, 0xC0, 0x49, 0x66, 0x68, 0x76, 0x01, 0x1E, 0x9D, 0x02, 0x01, 0x21, 0x84, 0x04, 0x01, 0x06, 0xAC, 0x0B, 0x01, 0x06, 0x9C, 0x07, 0xF1, 0x01, 0x06, 0x8C, 0x03, 0xF3, 0x01, 0x0D, 0xBC, 0x0F, 0x01, 0x06, 0xAC, 0x0B, 0xCC, 0xDC, 0xEC, 0x8C, 0xA7, 0xD4, 0x81, 0x9D, 0xD1, 0x80, 0x9B, 0xD1, 0x7E, 0x98, 0xCF, 0x7D, 0x95, 0xCF, 0x01, 0x06, 0x8F, 0x7E, 0x78, 0x8B, 0xCB, 0x3B, 0x3F, 0x56, 0x01, 0x4B, 0x82, 0x5C, 0xB2, 0xB2, 0xBA, 0x01, 0x06, 0x81, 0x19, 0x01, 0x2D, 0xB3, 0x66, 0x8A, 0x8C, 0x97, 0x01, 0x06, 0x36, 0x01, 0x66, 0xF0, 0x1C, 0x01, 0x09, 0x93, 0x7F, 0x01, 0x30, 0xE7, 0x61, 0x01, 0x39, 0x39, 0x01, 0x17, 0x83, 0xBB, 0x1A, 0x99, 0x01, 0x39, 0x81, 0xAE, 0x51, 0x01, 0x2D, 0x88, 0x02, 0xC6, 0xD7, 0xEA, 0x87, 0xA5, 0xD3, 0x82, 0x9E, 0xD2, 0x81, 0x9C, 0xD1, 0x7F, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x07, 0x8F, 0x7E, 0x67, 0x77, 0x01, 0x4F, 0xA6, 0x7D, 0x60, 0x01, 0x08, 0x94, 0x08, 0xCF, 0xD0, 0xD4, 0x01, 0x27, 0x97, 0x50, 0x41, 0x43, 0x55, 0x01, 0x06, 0x82, 0xA4, 0x79, 0xFB, 0xFB, 0xFB, 0x01, 0x66, 0x82, 0x88, 0x3F, 0x01, 0x09, 0xA7, 0x6F, 0x01, 0x78, 0xF0, 0x1C, 0x3E, 0x3F, 0x52, 0xB7, 0xB8, 0x01, 0x07, 0x81, 0x8A, 0x4B, 0x01, 0x3F, 0xDD, 0x2A, 0x01, 0x21, 0x88, 0x02, 0xC1, 0xD2, 0xE8, 0x86, 0xA3, 0xD2, 0x83, 0xA0, 0xD2, 0x81, 0x9D, 0xD1, 0x7F, 0x9A, 0xD0, 0x7E, 0x97, 0x01, 0x07, 0x87, 0x7F, 0x7B, 0x91, 0xCE, 0x78, 0x8D, 0xCC, 0x51, 0x5A, 0x01, 0x52, 0x81, 0x8F, 0x4A, 0x01, 0x09, 0x81, 0x8C, 0x26, 0x91, 0x93, 0x01, 0x25, 0x98, 0x5D, 0xB2, 0xB3, 0x01, 0x07, 0x88, 0x35, 0x9D, 0x9E, 0xA7, 0x01, 0x69, 0xDC, 0x26, 0x01, 0x7B, 0x84, 0x01, 0x51, 0x53, 0x63, 0x01, 0x21, 0x81, 0xEA, 0x51, 0x01, 0x48, 0x84, 0x01, 0xCB, 0xDA, 0xEB, 0x87, 0xA5, 0xD3, 0x83, 0xA1, 0xD2, 0x81, 0x9E, 0xD1, 0x01, 0x0C, 0x87, 0x7F, 0x7B, 0x92, 0xCE, 0x79, 0x8F, 0xCD, 0x78, 0x8C, 0xCC, 0x3D, 0x40, 0x01, 0x52, 0x81, 0xAF, 0x46, 0x3E, 0x40, 0x53, 0x01, 0x06, 0x81, 0x61, 0xF9, 0xF9, 0xFA, 0x83, 0x85, 0x90, 0x01, 0x1E, 0x95, 0x7E, 0x99, 0x9A, 0xA4, 0x01, 0x09, 0x82, 0x94, 0x78, 0x01, 0x69, 0xA0, 0x02, 0x01, 0x09, 0x83, 0x48, 0x01, 0x39, 0x84, 0x01, 0x01, 0x39, 0xA0, 0x0E, 0x6F, 0x70, 0x7E, 0xF1, 0xF1, 0xF3, 0x01, 0x48, 0x83, 0x7E, 0x01, 0x06, 0x8C, 0x03, 0x01, 0x06, 0xBC, 0x0F, 0x01, 0x06, 0x9C, 0x07, 0x01, 0x06, 0xAC, 0x0B, 0xEA, 0x01, 0x05, 0x9C, 0x07, 0xD5, 0xE2, 0xF0, 0x8A, 0xA8, 0xD5, 0x84, 0xA2, 0x01, 0x05, 0x87, 0x7F, 0x9E, 0xD1, 0x80, 0x9B, 0xD0, 0x7E, 0x98, 0xCF, 0x7D, 0x96, 0xCF, 0x7B, 0x01, 0x05, 0x87, 0x7F, 0x79, 0x8E, 0xCD, 0x6B, 0x7B, 0x01, 0x10, 0x82, 0xA3, 0x6C, 0x01, 0x48, 0x82, 0x62, 0x47, 0x49, 0x5A, 0xC3, 0xC3, 0xC9, 0x01, 0x06, 0x81, 0x25, 0xCD, 0xCE, 0xD2, 0x57, 0x58, 0x01, 0x13, 0xB4, 0x6A, 0x66, 0x68, 0x76, 0xDE, 0xDE, 0xE1, 0x01, 0x06, 0x24, 0xB4, 0xB5, 0xBC, 0x40, 0x42, 0x01, 0x6A, 0xD9, 0x35, 0x01, 0x09, 0x97, 0x50, 0x01, 0x30, 0x87, 0x49, 0x01, 0x09, 0xAC, 0x38, 0x01, 0x36, 0xB0, 0x1B, 0x99, 0x9A, 0xA4, 0x01, 0x15, 0xBB, 0x56, 0x01, 0x54, 0x88, 0x02, 0xDD, 0xE8, 0xF2, 0x90, 0xAE, 0xD8, 0x85, 0xA4, 0xD3, 0x83, 0xA1, 0xD2, 0x82, 0x9F, 0xD2, 0x80, 0x9C, 0x01, 0x06, 0x8C, 0x00, 0x01, 0x07, 0x97, 0x7D, 0x7A, 0x01, 0x05, 0x87, 0x7F, 0x5B, 0x67, 0x01, 0x4F, 0x82, 0xBB, 0x45, 0x43, 0x45, 0x57, 0x01, 0x09, 0x81, 0x83, 0x68, 0x96, 0x97, 0xA1, 0xE1, 0xE1, 0xE4, 0x01, 0x0C, 0xEA, 0x55, 0xC8, 0xC8, 0xCD, 0xA4, 0xA5, 0xAE, 0xAB, 0xAB, 0xB3, 0xCE, 0xCE, 0xD3, 0x01, 0x0C, 0x86, 0x06, 0xD7, 0xD7, 0xDB, 0x01, 0x24, 0x81, 0x84, 0x6F, 0x01, 0x4B, 0x81, 0xB8, 0x73, 0x4B, 0x4D, 0x5D, 0x01, 0x2D, 0xA0, 0x05, 0x01, 0x0F, 0x36, 0x01, 0x33, 0x82, 0x91, 0x69, 0x41, 0x43, 0x55, 0x01, 0x09, 0x81, 0x8A, 0x33, 0x01, 0x4B, 0x83, 0x7E, 0x01, 0x18, 0x88, 0x02, 0xE4, 0xEE, 0xF5, 0x98, 0xB5, 0xDA, 0x86, 0xA5, 0xD4, 0x83, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x07, 0x97, 0x7D, 0x01, 0x05, 0xA3, 0x7D, 0x01, 0x08, 0x87, 0x7F, 0x78, 0x8C, 0xCC, 0x4C, 0x53, 0x01, 0x4F, 0x82, 0xB7, 0x3E, 0x01, 0x45, 0x82, 0xF0, 0x5C, 0x01, 0x18, 0x18, 0x54, 0x55, 0x01, 0x46, 0xA5, 0x2E, 0x01, 0x0F, 0x97, 0x50, 0x01, 0x2A, 0x8C, 0x06, 0x01, 0x39, 0x90, 0x01, 0x58, 0x5A, 0x6A, 0x01, 0x0C, 0x86, 0x0C, 0x01, 0x60, 0x84, 0x01, 0xEB, 0xF2, 0xF8, 0xA1, 0xBC, 0xDD, 0x86, 0xA6, 0xD4, 0x85, 0xA4, 0xD4, 0x01, 0x06, 0x87, 0x7F, 0x81, 0x01, 0x07, 0x87, 0x7F, 0xCF, 0x01, 0x07, 0x9F, 0x7C, 0x8F, 0xCD, 0x78, 0x8D, 0xCD, 0x77, 0x8A, 0xCB, 0x3D, 0x40, 0x01, 0x4F, 0xD4, 0x18, 0x01, 0x81, 0x2B, 0x84, 0x01, 0x4B, 0x4D, 0x5D, 0x01, 0x06, 0x9F, 0x55, 0x01, 0x27, 0xAB, 0x5B, 0x6D, 0x6E, 0x79, 0x01, 0x06, 0x30, 0x01, 0x30, 0x87, 0x7F, 0x79, 0x7B, 0x87, 0x01, 0x09, 0xB6, 0x21, 0x01, 0x52, 0x84, 0x01, 0xFF, 0xFF, 0xFB, 0xFD, 0xFD, 0xFA, 0xFC, 0xFD, 0xF7, 0x01, 0x0B, 0x9C, 0x07, 0xAD, 0xC4, 0xE1, 0x87, 0xA8, 0xD4, 0x85, 0xA5, 0xD3, 0x84, 0xA3, 0xD3, 0x83, 0xA0, 0xD2, 0x82, 0x9E, 0xD2, 0x01, 0x06, 0x8F, 0x7E, 0x7E, 0x01, 0x0E, 0x87, 0x7F, 0x71, 0x83, 0x01, 0x52, 0x82, 0x97, 0x30, 0x4C, 0x4D, 0x5E, 0x01, 0x5A, 0x81, 0x84, 0x39, 0x01, 0x0C, 0xC8, 0x54, 0x01, 0x4E, 0xA8, 0x10, 0x01, 0x1B, 0xB4, 0x0A, 0x01, 0x0F, 0x83, 0x7E, 0x01, 0x2D, 0xFC, 0x1C, 0x01, 0x06, 0x81, 0xCE, 0x3B, 0x01, 0x5D, 0x81, 0x8A, 0x4E, 0x01, 0x12, 0x88, 0x02, 0xCA, 0xDA, 0xED, 0x88, 0xAA, 0xD5, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x07, 0x8F, 0x7E, 0x81, 0x9D, 0x01, 0x05, 0x97, 0x7D, 0x98, 0xD0, 0x7D, 0x95, 0xCF, 0x01, 0x06, 0xAB, 0x7C, 0x79, 0x8D, 0xCD, 0x78, 0x8B, 0xCC, 0x64, 0x73, 0x01, 0x81, 0x7A, 0x81, 0x89, 0x65, 0x01, 0x15, 0x83, 0x5A, 0x01, 0x15, 0xA3, 0x5C, 0x4B, 0x4D, 0x5D, 0x01, 0x09, 0x8B, 0x7A, 0x01, 0x2D, 0xFC, 0x1C, 0x47, 0x49, 0x5A, 0xCB, 0xCB, 0xD0, 0x01, 0x5D, 0x83, 0x7E, 0x01, 0x12, 0x88, 0x02, 0xE7, 0xEF, 0xF6, 0x8E, 0xAF, 0xD6, 0x01, 0x06, 0x87, 0x7F, 0x85, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x06, 0x8F, 0x7E, 0x7F, 0x01, 0x0C, 0xB3, 0x7B, 0x8E, 0xCD, 0x77, 0x8C, 0xCC, 0x76, 0x89, 0xCB, 0x5A, 0x65, 0x01, 0x81, 0x7A, 0x82, 0xCF, 0x47, 0x4B, 0x4D, 0x5D, 0x01, 0x06, 0xBF, 0x72, 0x96, 0x97, 0x9E, 0x01, 0x0C, 0xBC, 0x15, 0xF6, 0xF6, 0xF6, 0xCE, 0xCF, 0xD2, 0x01, 0x09, 0x81, 0x88, 0x19, 0x01, 0x09, 0xA0, 0x2F, 0x01, 0x24, 0xFC, 0x4C, 0x01, 0x0C, 0xC0, 0x2B, 0x5C, 0x5E, 0x6D, 0x01, 0x0C, 0x82, 0xCA, 0x54, 0x01, 0x69, 0x84, 0x01, 0xA7, 0xC1, 0xE0, 0x87, 0xA9, 0xD4, 0x86, 0xA7, 0xD4, 0x84, 0xA4, 0xD3, 0x84, 0xA2, 0xD3, 0x01, 0x06, 0x97, 0x7D, 0x80, 0x9A, 0xD1, 0x01, 0x06, 0xA3, 0x7D, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x05, 0x84, 0x01, 0x8B, 0xCC, 0x75, 0x88, 0xCB, 0x50, 0x58, 0x80, 0x01, 0x82, 0x02, 0xF0, 0x1C, 0x01, 0x4B, 0x83, 0x0C, 0x01, 0x09, 0x81, 0x8C, 0x38, 0x5C, 0x5E, 0x6D, 0xF0, 0xF1, 0xF2, 0x01, 0x63, 0x83, 0x7E, 0x01, 0x0F, 0xBC, 0x0F, 0xCB, 0xDB, 0xED, 0x88, 0xAA, 0xD5, 0x87, 0xA9, 0xD5, 0x86, 0xA6, 0xD4, 0x84, 0xA3, 0x01, 0x07, 0xA3, 0x7D, 0x80, 0x01, 0x05, 0xA3, 0x7D, 0x01, 0x06, 0x87, 0x7F, 0x7B, 0x91, 0xCE, 0x7A, 0x8F, 0xCE, 0x78, 0x8C, 0xCC, 0x77, 0x89, 0xCC, 0x76, 0x87, 0xCB, 0x4A, 0x4F, 0x72, 0x01, 0x82, 0x53, 0x84, 0x01, 0x47, 0x49, 0x5A, 0x01, 0x09, 0x82, 0xC2, 0x52, 0x01, 0x6C, 0x88, 0x02, 0xEA, 0xF0, 0xF8, 0x8E, 0xAF, 0xD7, 0x88, 0xAA, 0xD5, 0x86, 0xA7, 0xD4, 0x85, 0x01, 0x07, 0x87, 0x7F, 0xD1, 0x01, 0x07, 0x9B, 0x7E, 0x01, 0x0B, 0x87, 0x7F, 0x78, 0x01, 0x05, 0x8F, 0x7E, 0x76, 0x88, 0xCB, 0x74, 0x86, 0xCA, 0x43, 0x48, 0x01, 0x4C, 0x96, 0x55, 0x01, 0x81, 0x2F, 0x81, 0xC5, 0x59, 0x5E, 0x6B, 0x01, 0x24, 0x81, 0x94, 0x1C, 0x01, 0x24, 0x24, 0x01, 0x09, 0x09, 0x01, 0x06, 0xA8, 0x1C, 0xB6, 0xB7, 0x01, 0x07, 0x81, 0xAC, 0x4C, 0x01, 0x6F, 0x88, 0x02, 0xA6, 0xC2, 0xE0, 0x88, 0xAA, 0xD5, 0x87, 0xA8, 0xD4, 0x01, 0x07, 0x93, 0x7F, 0x01, 0x08, 0x97, 0x7D, 0x01, 0x05, 0xAB, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x92, 0x01, 0x08, 0x87, 0x7F, 0x8A, 0xCC, 0x76, 0x87, 0xCB, 0x74, 0x85, 0xCA, 0x01, 0x54, 0xAC, 0x05, 0x01, 0x82, 0x00, 0x81, 0xAE, 0x21, 0x4E, 0x5F, 0x01, 0x51, 0xA7, 0x69, 0x01, 0x24, 0x84, 0x01, 0xCD, 0xDC, 0xED, 0x8A, 0xAD, 0xD6, 0x01, 0x06, 0x84, 0x01, 0x01, 0x05, 0x87, 0x7F, 0xD2, 0x82, 0x01, 0x06, 0x93, 0x7F, 0x9A, 0xD0, 0x7F, 0x98, 0xD0, 0x7C, 0x95, 0xCF, 0x7B, 0x93, 0x01, 0x05, 0x8F, 0x7E, 0x01, 0x0B, 0x87, 0x7F, 0x74, 0x84, 0xCA, 0x38, 0x3B, 0x01, 0x82, 0x51, 0x83, 0xB0, 0x09, 0x92, 0x93, 0x01, 0x07, 0xAC, 0x62, 0x01, 0x6A, 0x84, 0x01, 0xFE, 0xFE, 0xF7, 0xFA, 0xFC, 0x92, 0xB2, 0xD8, 0x88, 0xAB, 0xD5, 0x87, 0xA9, 0xD4, 0x01, 0x0D, 0x8F, 0x7E, 0x9B, 0xD0, 0x01, 0x12, 0xA3, 0x7D, 0x76, 0x8A, 0xCB, 0x76, 0x88, 0xCB, 0x74, 0x85, 0xCA, 0x72, 0x81, 0x01, 0x82, 0x1E, 0x81, 0xBD, 0x72, 0x01, 0x36, 0x36, 0x01, 0x27, 0xF2, 0x0C, 0x01, 0x4E, 0x88, 0x02, 0xC2, 0xD6, 0xEA, 0x89, 0x01, 0x05, 0x87, 0x7F, 0x86, 0xA7, 0x01, 0x07, 0xA3, 0x7D, 0x82, 0x01, 0x07, 0xB3, 0x7B, 0x01, 0x05, 0xAB, 0x7C, 0x95, 0xCF, 0x7C, 0x93, 0xCF, 0x7A, 0x90, 0x01, 0x05, 0xA3, 0x7D, 0x8B, 0xCC, 0x76, 0x89, 0xCC, 0x75, 0x86, 0xCB, 0x74, 0x84, 0xCA, 0x70, 0x7E, 0xC4, 0x01, 0x82, 0x53, 0x84, 0x01, 0xD3, 0xD4, 0xD8, 0x01, 0x6F, 0x84, 0x01, 0xF4, 0xF7, 0xFB, 0x8D, 0xAE, 0xD5, 0x88, 0xAB, 0xD5, 0x88, 0xA9, 0xD5, 0x86, 0xA7, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x07, 0xB3, 0x7B, 0x01, 0x05, 0x97, 0x7D, 0x7D, 0x95, 0xCF, 0x7B, 0x91, 0xCE, 0x79, 0x8F, 0xCD, 0x79, 0x01, 0x05, 0xAB, 0x7C, 0x75, 0x87, 0xCB, 0x74, 0x84, 0xCA, 0x72, 0x82, 0xC9, 0x6E, 0x7B, 0x01, 0x82, 0x54, 0x82, 0xBF, 0x37, 0xD0, 0xD1, 0xD5, 0x01, 0x6F, 0x84, 0x01, 0xBC, 0xD1, 0xE7, 0x01, 0x07, 0x8F, 0x7E, 0x01, 0x09, 0x87, 0x7F, 0x9F, 0xD1, 0x81, 0x9E, 0xD2, 0x7F, 0x9A, 0xD0, 0x01, 0x0B, 0xA3, 0x7D, 0xCE, 0x01, 0x06, 0x9F, 0x7C, 0x01, 0x09, 0x87, 0x7F, 0x72, 0x81, 0xC9, 0x6D, 0x7A, 0x01, 0x13, 0x82, 0xCF, 0x74, 0x01, 0x6F, 0x83, 0xA5, 0x13, 0x7F, 0x80, 0x8C, 0xA7, 0xA8, 0xB1, 0x96, 0x97, 0xA1, 0x67, 0x69, 0x77, 0x3D, 0x3F, 0x51, 0x01, 0x81, 0x43, 0x84, 0x01, 0xBD, 0xBD, 0x01, 0x07, 0xEA, 0x16, 0x01, 0x66, 0x83, 0x7E, 0xF7, 0xFA, 0xFD, 0x8C, 0xAF, 0xD5, 0x89, 0xAC, 0x01, 0x05, 0x8F, 0x7E, 0x01, 0x0A, 0xA3, 0x7D, 0x01, 0x0C, 0xC3, 0x79, 0x01, 0x07, 0x8F, 0x7E, 0x79, 0x8D, 0x01, 0x07, 0xA3, 0x7D, 0x74, 0x85, 0xCA, 0x73, 0x83, 0xCA, 0x71, 0x80, 0xC9, 0x6E, 0x7C, 0xC5, 0x01, 0x5A, 0x82, 0x08, 0x88, 0x89, 0x95, 0xA7, 0xA8, 0xB1, 0x4C, 0x01, 0x1A, 0x81, 0xDC, 0x37, 0x94, 0x95, 0x9F, 0x01, 0x0F, 0x96, 0x2E, 0xF1, 0xF1, 0xF3, 0x01, 0x81, 0x43, 0x82, 0xF0, 0x59, 0x91, 0x92, 0x9C, 0x01, 0x6C, 0x84, 0x01, 0xC5, 0xD7, 0xEA, 0x01, 0x05, 0x87, 0x7F, 0xD4, 0x87, 0xA8, 0xD5, 0x85, 0xA5, 0xD3, 0x01, 0x07, 0xC3, 0x79, 0x01, 0x17, 0xBB, 0x7A, 0x76, 0x89, 0x01, 0x08, 0x8C, 0x00, 0x81, 0xC9, 0x71, 0x7F, 0xC9, 0x6F, 0x7C, 0x01, 0x58, 0x94, 0x05, 0x3A, 0x3C, 0x4E, 0xE7, 0xE7, 0xE9, 0x01, 0x06, 0x82, 0xB8, 0x24, 0x58, 0x5A, 0x01, 0x13, 0x81, 0x89, 0x02, 0x01, 0x0C, 0x82, 0xBC, 0x6A, 0x01, 0x0D, 0x85, 0x50, 0xF8, 0xF8, 0x70, 0x71, 0x01, 0x81, 0x3E, 0x81, 0x95, 0x41, 0x4D, 0x4F, 0x60, 0x01, 0x27, 0x82, 0xBA, 0x41, 0x01, 0x43, 0xC4, 0x08, 0xFD, 0xFE, 0x8E, 0x01, 0x0B, 0x87, 0x7F, 0x01, 0x08, 0xA3, 0x7D, 0x01, 0x08, 0xC3, 0x79, 0x01, 0x06, 0x9B, 0x7E, 0x01, 0x09, 0x87, 0x7F, 0x8A, 0xCB, 0x76, 0x88, 0xCC, 0x01, 0x09, 0x87, 0x7F, 0x70, 0x7E, 0xC9, 0x6F, 0x7B, 0xC7, 0x39, 0x3B, 0x01, 0x55, 0x8A, 0x76, 0x7E, 0x7F, 0x8B, 0x01, 0x09, 0x81, 0xD8, 0x36, 0x01, 0x15, 0x81, 0xEC, 0x5C, 0x01, 0x09, 0x82, 0x23, 0xFE, 0xFE, 0xFE, 0xD7, 0xD8, 0xDB, 0xC1, 0xC1, 0xC7, 0xF3, 0xF3, 0xF4, 0x01, 0x09, 0xE8, 0x50, 0x01, 0x81, 0x40, 0x83, 0xCD, 0x26, 0x01, 0x09, 0xD2, 0x10, 0x01, 0x60, 0x84, 0x01, 0xD3, 0xE1, 0xF0, 0x89, 0xAD, 0xD5, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x14, 0x97, 0x7D, 0x01, 0x08, 0xAB, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x77, 0x8A, 0xCC, 0x75, 0x87, 0xCB, 0x73, 0x01, 0x0B, 0x87, 0x7F, 0x6E, 0x7A, 0xC7, 0x3C, 0x3E, 0x01, 0x55, 0x81, 0x94, 0x25, 0xCA, 0xCA, 0xCF, 0x01, 0x06, 0x81, 0x22, 0x81, 0x82, 0x8E, 0x01, 0x12, 0x1E, 0xC5, 0xC6, 0x01, 0x07, 0x82, 0xF8, 0x79, 0xFA, 0xFA, 0xFA, 0x66, 0x68, 0x76, 0x01, 0x07, 0xF2, 0x0F, 0x46, 0x58, 0x01, 0x09, 0x82, 0xE0, 0x55, 0x7D, 0x7E, 0x8B, 0x01, 0x81, 0x01, 0xB8, 0x20, 0x7C, 0x7D, 0x86, 0x01, 0x2A, 0xE4, 0x2E, 0x01, 0x12, 0xB8, 0x05, 0xED, 0xED, 0xEF, 0x01, 0x63, 0x84, 0x01, 0x9D, 0xB9, 0xD8, 0x89, 0xAC, 0xD6, 0x88, 0xA9, 0x01, 0x05, 0x93, 0x7F, 0xA4, 0xD3, 0x83, 0xA2, 0x01, 0x0D, 0xC3, 0x79, 0x01, 0x13, 0xAB, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x72, 0x80, 0xC9, 0x71, 0x01, 0x05, 0x87, 0x7F, 0x6E, 0x79, 0xC7, 0x42, 0x45, 0x01, 0x55, 0x81, 0xA4, 0x35, 0xE9, 0xEA, 0xEC, 0x01, 0x05, 0xDB, 0x61, 0xFC, 0x01, 0x12, 0x81, 0xE0, 0x35, 0x4B, 0x4D, 0x5E, 0x01, 0x09, 0x8F, 0x7B, 0x01, 0x0C, 0x82, 0xDD, 0x0D, 0x01, 0x0C, 0xF0, 0x55, 0xCB, 0xCB, 0xD0, 0x01, 0x75, 0x83, 0x78, 0x96, 0x97, 0x9E, 0x01, 0x0C, 0xFC, 0x28, 0x01, 0x12, 0xC7, 0x74, 0x01, 0x2A, 0x84, 0x13, 0x62, 0x63, 0x72, 0x01, 0x06, 0x82, 0xE6, 0x70, 0x01, 0x5A, 0x83, 0x7E, 0xEE, 0xF4, 0xF9, 0x8A, 0xAE, 0xD6, 0x88, 0xAB, 0x01, 0x07, 0xAB, 0x7C, 0x01, 0x05, 0x9B, 0x7E, 0xD3, 0x01, 0x09, 0xBB, 0x7A, 0x01, 0x07, 0x93, 0x7F, 0x01, 0x07, 0x87, 0x7F, 0xCD, 0x77, 0x8A, 0xCC, 0x75, 0x86, 0xCA, 0x74, 0x85, 0xCB, 0x72, 0x82, 0xCA, 0x71, 0x7F, 0xC9, 0x70, 0x7D, 0xC8, 0x6E, 0x7A, 0xC7, 0x6D, 0x78, 0xC7, 0x47, 0x4C, 0x01, 0x52, 0xB4, 0x0D, 0x01, 0x09, 0x83, 0xE0, 0x78, 0xE0, 0xE0, 0xE3, 0x01, 0x1B, 0x82, 0x8C, 0x5B, 0xF4, 0xF4, 0xF5, 0x01, 0x12, 0xD4, 0x03, 0xE4, 0xE4, 0xE7, 0x01, 0x18, 0x82, 0xF1, 0x15, 0x01, 0x60, 0x87, 0x73, 0x01, 0x0F, 0xFC, 0x04, 0x01, 0x12, 0x84, 0x01, 0x01, 0x06, 0xF4, 0x4A, 0x01, 0x2A, 0xFC, 0x1C, 0x01, 0x60, 0xBC, 0x0F, 0xBD, 0xD1, 0xE7, 0x89, 0xAC, 0xD5, 0x01, 0x05, 0xA3, 0x7D, 0xD3, 0x01, 0x0C, 0xC3, 0x79, 0x80, 0x01, 0x06, 0xA7, 0x7B, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x06, 0x9B, 0x7E, 0x88, 0xCB, 0x75, 0x86, 0xCB, 0x73, 0x83, 0xCA, 0x72, 0x81, 0xC9, 0x70, 0x7E, 0xC8, 0x6F, 0x7B, 0xC8, 0x6D, 0x79, 0xC7, 0x6C, 0x76, 0xC6, 0x4E, 0x53, 0x01, 0x52, 0xE0, 0x12, 0x59, 0x5B, 0x6A, 0x01, 0x09, 0x82, 0x88, 0x3C, 0x01, 0x12, 0x1E, 0x01, 0x09, 0x82, 0xD8, 0x3E, 0xAF, 0xB0, 0x01, 0x13, 0x81, 0x88, 0x3A, 0xC9, 0x01, 0x05, 0x8C, 0x3C, 0xFD, 0xFD, 0xFD, 0x01, 0x6C, 0x90, 0x07, 0x01, 0x09, 0xD8, 0x1F, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0xCC, 0x3D, 0x01, 0x24, 0xF8, 0x48, 0x01, 0x0C, 0xF2, 0x27, 0x01, 0x5A, 0xC4, 0x11, 0x91, 0xB0, 0xD5, 0x89, 0x01, 0x08, 0x87, 0x7F, 0x85, 0x01, 0x14, 0xBB, 0x7A, 0x7A, 0x91, 0xCD, 0x01, 0x06, 0xD7, 0x78, 0x76, 0x89, 0xCB, 0x76, 0x01, 0x05, 0x97, 0x7D, 0x73, 0x82, 0xCA, 0x71, 0x7F, 0xC8, 0x70, 0x7D, 0x01, 0x05, 0x84, 0x01, 0x78, 0xC7, 0x6B, 0x75, 0xC5, 0x54, 0x5A, 0x01, 0x52, 0x81, 0xE3, 0x53, 0x01, 0x09, 0x8B, 0x4A, 0xAB, 0xAC, 0x01, 0x10, 0x8A, 0x43, 0x48, 0x4A, 0x5B, 0x01, 0x09, 0x8C, 0x00, 0x01, 0x15, 0x82, 0xD9, 0x12, 0x01, 0x09, 0xD6, 0x35, 0x4A, 0x4C, 0x01, 0x67, 0x81, 0xE7, 0x15, 0x01, 0x0C, 0xFC, 0x22, 0xEC, 0xEC, 0xEE, 0x96, 0x97, 0x9E, 0x4B, 0x4D, 0x5D, 0x01, 0x06, 0xC4, 0x05, 0x01, 0x0F, 0x88, 0x02, 0x01, 0x09, 0xC8, 0x39, 0x01, 0x2D, 0xE0, 0x12, 0x01, 0x57, 0xCC, 0x13, 0xEA, 0xF1, 0xF8, 0x01, 0x08, 0x87, 0x7F, 0xD4, 0x85, 0x01, 0x05, 0xD7, 0x78, 0x01, 0x07, 0xCB, 0x78, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x05, 0x9B, 0x7E, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x06, 0xA3, 0x7D, 0x73, 0x83, 0xC9, 0x72, 0x81, 0xCA, 0x71, 0x7E, 0xC9, 0x70, 0x7C, 0x01, 0x07, 0x87, 0x7F, 0x6B, 0x74, 0xC6, 0x5C, 0x61, 0xA4, 0x01, 0x54, 0x81, 0xA0, 0x1C, 0x01, 0x07, 0x89, 0x24, 0xBD, 0x01, 0x10, 0xAC, 0x6B, 0x01, 0x09, 0x82, 0xE4, 0x71, 0xF4, 0xF4, 0xF5, 0x01, 0x15, 0x81, 0x98, 0x0E, 0x01, 0x06, 0x8C, 0x03, 0xFF, 0xFF, 0xFF, 0x3E, 0x3F, 0x52, 0x01, 0x66, 0xC8, 0x15, 0x01, 0x15, 0x87, 0x58, 0x01, 0x15, 0x84, 0x01, 0x01, 0x0C, 0xD0, 0x41, 0x01, 0x30, 0x81, 0x80, 0x20, 0x01, 0x51, 0xD4, 0x15, 0xC5, 0xD6, 0xEA, 0x01, 0x0E, 0x8F, 0x7E, 0x01, 0x07, 0x97, 0x7D, 0x01, 0x0C, 0x8F, 0x7E, 0x01, 0x0A, 0xBB, 0x7A, 0x88, 0x01, 0x0D, 0x87, 0x7F, 0x01, 0x06, 0x8F, 0x7E, 0x6B, 0x75, 0xC6, 0x6A, 0x73, 0xC5, 0x65, 0x6C, 0xBB, 0x01, 0x54, 0x82, 0x59, 0x01, 0x06, 0x82, 0xDC, 0x2A, 0xE7, 0xE7, 0xE9, 0x01, 0x0F, 0xE7, 0x67, 0x01, 0x09, 0x81, 0xA8, 0x30, 0xB2, 0xB3, 0xBA, 0x01, 0x15, 0x82, 0xE9, 0x2E, 0x01, 0x06, 0x90, 0x3D, 0xF4, 0xF4, 0xF5, 0x01, 0x6F, 0x81, 0x88, 0x1F, 0x01, 0x0F, 0x8F, 0x5A, 0x01, 0x18, 0x84, 0x01, 0x01, 0x3C, 0xDC, 0x17, 0x57, 0x59, 0x69, 0x01, 0x4B, 0xDC, 0x17, 0x98, 0xB4, 0xD7, 0x01, 0x06, 0xAB, 0x7C, 0x01, 0x06, 0xDF, 0x77, 0x01, 0x07, 0xBB, 0x7A, 0x01, 0x08, 0xC3, 0x79, 0x01, 0x07, 0xA3, 0x7D, 0x01, 0x08, 0x97, 0x7D, 0x75, 0x86, 0xCA, 0x01, 0x05, 0x9B, 0x7E, 0x01, 0x05, 0x93, 0x7F, 0x01, 0x05, 0x87, 0x7F, 0x6D, 0x77, 0xC6, 0x6B, 0x74, 0xC6, 0x6A, 0x72, 0xC5, 0x68, 0x6F, 0xC4, 0x3D, 0x3F, 0x01, 0x52, 0x81, 0xCC, 0x51, 0x01, 0x09, 0x9B, 0x69, 0x7F, 0x80, 0x8C, 0x01, 0x12, 0x82, 0xE8, 0x54, 0xFF, 0xFF, 0xFF, 0x69, 0x6B, 0x01, 0x13, 0xD2, 0x58, 0x67, 0x69, 0x77, 0x01, 0x06, 0x1E, 0xCC, 0xCD, 0x01, 0x2E, 0xFB, 0x30, 0x01, 0x3F, 0xE4, 0x19, 0x01, 0x12, 0x81, 0xD8, 0x00, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0x88, 0x35, 0x01, 0x7B, 0xE4, 0x19, 0xF6, 0xF9, 0xFC, 0x01, 0x08, 0xBB, 0x7A, 0x01, 0x05, 0xDB, 0x76, 0xA1, 0xD2, 0x82, 0x01, 0x07, 0xBB, 0x7A, 0x01, 0x07, 0x84, 0x01, 0x7A, 0x01, 0x05, 0xB3, 0x7B, 0x78, 0x8D, 0x01, 0x07, 0x9F, 0x7C, 0x01, 0x05, 0x97, 0x7D, 0xC9, 0x71, 0x80, 0x01, 0x05, 0x97, 0x7D, 0x7B, 0xC7, 0x6D, 0x78, 0xC7, 0x6C, 0x01, 0x05, 0x87, 0x7F, 0x6A, 0x71, 0xC5, 0x68, 0x6E, 0xC4, 0x46, 0x49, 0x01, 0x52, 0x83, 0xA7, 0x72, 0x6E, 0x70, 0x7D, 0x01, 0x07, 0xA5, 0x2B, 0xFB, 0xFB, 0xA5, 0xA6, 0xAE, 0x80, 0x81, 0x8D, 0xB7, 0xB8, 0xBF, 0x01, 0x09, 0xFA, 0x05, 0xCF, 0xD0, 0xD4, 0x01, 0x18, 0x82, 0xED, 0x2C, 0x01, 0x07, 0x85, 0x5F, 0x01, 0x65, 0x82, 0xB0, 0x4C, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x12, 0x81, 0xD0, 0x07, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x0C, 0x88, 0x38, 0x01, 0x38, 0xEC, 0x1B, 0xA3, 0x01, 0x3F, 0xC4, 0x32, 0xDA, 0xE5, 0xF2, 0x01, 0x05, 0xC3, 0x79, 0xD5, 0x85, 0xA4, 0x01, 0x09, 0xA3, 0x7D, 0xD2, 0x01, 0x06, 0xA7, 0x7B, 0x01, 0x05, 0x8F, 0x7E, 0x01, 0x07, 0xBB, 0x7A, 0x01, 0x05, 0x8F, 0x7E, 0xCB, 0x01, 0x0E, 0xA3, 0x7D, 0xC7, 0x6E, 0x7A, 0xC7, 0x6C, 0x77, 0xC6, 0x6C, 0x75, 0x01, 0x07, 0x87, 0x7F, 0x67, 0x6D, 0xC4, 0x51, 0x53, 0x8D, 0x01, 0x55, 0x84, 0xBD, 0x12, 0xCD, 0x01, 0x16, 0x81, 0x9A, 0x79, 0xFC, 0xFC, 0xFC, 0x5D, 0x5F, 0x6E, 0x01, 0x15, 0x84, 0xCD, 0x49, 0x01, 0x06, 0x8C, 0x39, 0xFD, 0xFD, 0xFD, 0x54, 0x56, 0x66, 0x01, 0x64, 0x82, 0xA1, 0x6D, 0xB9, 0xBE, 0x01, 0x18, 0x81, 0x87, 0x69, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x1B, 0x84, 0x3A, 0x01, 0x66, 0xF4, 0x1D, 0xBD, 0xD1, 0xE8, 0x88, 0x01, 0x05, 0xD3, 0x77, 0x01, 0x11, 0xEF, 0x75, 0x01, 0x07, 0xC3, 0x79, 0x7A, 0x90, 0xCE, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x07, 0xC3, 0x79, 0x82, 0xC9, 0x72, 0x80, 0x01, 0x06, 0x9B, 0x7E, 0x01, 0x05, 0x87, 0x7F, 0x76, 0xC6, 0x6B, 0x73, 0xC5, 0x69, 0x01, 0x05, 0x87, 0x7F, 0x66, 0x6B, 0xC3, 0x5D, 0x61, 0xAD, 0x01, 0x57, 0x83, 0xE9, 0x00, 0xC2, 0xC3, 0x01, 0x10, 0x89, 0x6F, 0xF2, 0xF2, 0xF3, 0x6E, 0x70, 0x01, 0x16, 0x81, 0x89, 0x0B, 0x01, 0x09, 0xA8, 0x3D, 0xBD, 0xBE, 0x01, 0x67, 0xC1, 0x26, 0x01, 0x06, 0x83, 0x66, 0x01, 0x15, 0x81, 0xE4, 0x00, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x09, 0xD4, 0x4E, 0x01, 0x78, 0xFC, 0x1F, 0x9C, 0xB8, 0xD9, 0x01, 0x0D, 0xC3, 0x79, 0x01, 0x06, 0x97, 0x7D, 0x01, 0x05, 0xF7, 0x74, 0x7C, 0x94, 0xCF, 0x01, 0x06, 0x97, 0x7D, 0x01, 0x07, 0xB3, 0x7B, 0x01, 0x06, 0x9F, 0x7C, 0x82, 0xCA, 0x70, 0x7E, 0xC8, 0x01, 0x05, 0xAB, 0x7C, 0xC8, 0x6C, 0x77, 0xC6, 0x6B, 0x74, 0x01, 0x05, 0x83, 0x7E, 0x01, 0x05, 0x87, 0x7F, 0x66, 0x6B, 0xC3, 0x64, 0x67, 0xC2, 0x3C, 0x3E, 0x01, 0x55, 0xD0, 0x1A, 0x39, 0x3B, 0x4E, 0x71, 0x73, 0x80, 0xA0, 0xA1, 0xAA, 0xCC, 0xCC, 0xD1, 0xBA, 0xBB, 0xC1, 0x91, 0x92, 0x9C, 0x50, 0x52, 0x63, 0x01, 0x18, 0x81, 0xC5, 0x7A, 0x01, 0x06, 0x93, 0x7F, 0xF6, 0xF6, 0xF7, 0x01, 0x69, 0x82, 0xF4, 0x5D, 0x01, 0x7E, 0x84, 0x01, 0x01, 0x39, 0x81, 0x84, 0x21, 0xFD, 0xFE, 0xFF, 0x89, 0x01, 0x08, 0xD7, 0x78, 0x01, 0x09, 0xEF, 0x75, 0x01, 0x05, 0xDF, 0x77, 0x01, 0x07, 0xFF, 0x73, 0x7A, 0x90, 0x01, 0x05, 0xAF, 0x7A, 0x8B, 0xCC, 0x75, 0x87, 0x01, 0x11, 0xA3, 0x7D, 0x78, 0xC6, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x06, 0x8F, 0x7E, 0x66, 0x6C, 0xC3, 0x65, 0x69, 0xC2, 0x64, 0x67, 0xC2, 0x47, 0x4A, 0x01, 0x81, 0x02, 0x81, 0xDC, 0x55, 0x5B, 0x5D, 0x6C, 0xC0, 0xC0, 0xC6, 0x7E, 0x7F, 0x01, 0x6A, 0xB0, 0x06, 0x01, 0x06, 0xAB, 0x76, 0x01, 0x15, 0xF8, 0x1B, 0x01, 0x27, 0x8C, 0x03, 0x01, 0x45, 0x81, 0x8C, 0x23, 0x8D, 0x8E, 0x01, 0x2E, 0x81, 0x8C, 0x23, 0xEA, 0xF0, 0xF8, 0x01, 0x0D, 0xE7, 0x76, 0x01, 0x06, 0x93, 0x7F, 0x01, 0x0E, 0x81, 0x9B, 0x71, 0x01, 0x06, 0xDF, 0x77, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x06, 0xB3, 0x7B, 0x6F, 0x7A, 0x01, 0x06, 0xA3, 0x7D, 0xC6, 0x6A, 0x72, 0xC5, 0x69, 0x70, 0xC4, 0x67, 0x6D, 0xC3, 0x66, 0x6B, 0xC3, 0x64, 0x68, 0xC2, 0x64, 0x66, 0xC2, 0x54, 0x56, 0x01, 0x46, 0x81, 0xB0, 0x23, 0x01, 0x81, 0x31, 0x81, 0xF0, 0x4B, 0x01, 0x18, 0x82, 0x8C, 0x0A, 0x01, 0x27, 0x94, 0x05, 0x01, 0x75, 0x81, 0x94, 0x25, 0xD6, 0xE2, 0xF1, 0x01, 0x07, 0x87, 0x7F, 0xA2, 0xD2, 0x01, 0x07, 0xDF, 0x77, 0x9A, 0xD1, 0x7D, 0x01, 0x08, 0xB3, 0x7B, 0x01, 0x0B, 0xBB, 0x7A, 0x01, 0x0A, 0xC3, 0x79, 0x01, 0x06, 0xBB, 0x7A, 0x6E, 0x01, 0x08, 0xA3, 0x7D, 0x01, 0x06, 0x87, 0x7F, 0x67, 0x6C, 0xC4, 0x65, 0x69, 0xC3, 0x63, 0x66, 0xC1, 0x63, 0x64, 0xC1, 0x60, 0x60, 0xBD, 0x3A, 0x3B, 0x01, 0x81, 0x71, 0x81, 0xDC, 0x4F, 0x01, 0x09, 0xA3, 0x56, 0x01, 0x12, 0xA7, 0x57, 0x01, 0x24, 0x9C, 0x07, 0x01, 0x4E, 0x81, 0xFD, 0x64, 0x4B, 0x4D, 0x5E, 0x01, 0x09, 0xAE, 0x25, 0x01, 0x1E, 0x84, 0x01, 0xC2, 0xD3, 0xEA, 0x01, 0x09, 0x8F, 0x7E, 0x01, 0x09, 0xDF, 0x77, 0x01, 0x0A, 0xCB, 0x78, 0x8F, 0xCD, 0x78, 0x8C, 0xCD, 0x01, 0x07, 0xC3, 0x79, 0x01, 0x06, 0x9B, 0x7E, 0x01, 0x11, 0x97, 0x7D, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x05, 0x8F, 0x7E, 0x68, 0xC2, 0x63, 0x66, 0xC2, 0x62, 0x63, 0xC1, 0x60, 0x60, 0xC0, 0x47, 0x48, 0x01, 0x81, 0x74, 0x81, 0xE8, 0x5B, 0x01, 0x06, 0x86, 0x78, 0xEC, 0xEC, 0xEE, 0x01, 0x0F, 0x88, 0x05, 0x01, 0x24, 0xA4, 0x09, 0x01, 0x30, 0x81, 0x9C, 0x5D, 0x01, 0x48, 0x81, 0xA4, 0x29, 0xAF, 0xC4, 0xE3, 0x01, 0x0A, 0xBB, 0x7A, 0x01, 0x0B, 0x81, 0x93, 0x72, 0x01, 0x0A, 0x97, 0x7D, 0x01, 0x05, 0xAB, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0xC9, 0x72, 0x81, 0x01, 0x0A, 0xBB, 0x7A, 0x01, 0x05, 0x93, 0x7F, 0xC6, 0x69, 0x71, 0xC4, 0x01, 0x08, 0x87, 0x7F, 0xC2, 0x64, 0x67, 0xC2, 0x62, 0x64, 0xC1, 0x61, 0x62, 0xC0, 0x60, 0x60, 0xC0, 0x55, 0x54, 0x01, 0x52, 0xAC, 0x14, 0x01, 0x81, 0x23, 0x83, 0x8E, 0x26, 0x01, 0x08, 0x81, 0xA0, 0x2B, 0x01, 0x0F, 0xB3, 0x60, 0x01, 0x18, 0x84, 0x01, 0x01, 0x0C, 0xEC, 0x4E, 0x01, 0x57, 0x81, 0xE0, 0x6E, 0x01, 0x21, 0x81, 0xAC, 0x2B, 0xA0, 0xB8, 0xDC, 0x01, 0x0D, 0xDF, 0x77, 0x01, 0x17, 0x87, 0x7F, 0x73, 0x01, 0x15, 0xAB, 0x7C, 0x72, 0xC5, 0x69, 0x70, 0xC5, 0x67, 0x6D, 0xC4, 0x67, 0x01, 0x09, 0x87, 0x7F, 0x64, 0xC1, 0x60, 0x60, 0xC0, 0x5F, 0x5E, 0xBF, 0x5D, 0x5B, 0xBE, 0x3D, 0x3E, 0x01, 0x07, 0x83, 0xAC, 0x2C, 0x01, 0x81, 0x6D, 0x84, 0x04, 0x01, 0x09, 0xBC, 0x06, 0xC4, 0xC4, 0xC8, 0x01, 0x09, 0x88, 0x08, 0x01, 0x15, 0x84, 0x01, 0x96, 0x97, 0x9E, 0x01, 0x09, 0x8B, 0x7D, 0x01, 0x51, 0x87, 0x7F, 0x01, 0x2A, 0x81, 0xB4, 0x2D, 0x90, 0xAC, 0xD5, 0x01, 0x0A, 0xF7, 0x74, 0x01, 0x0A, 0xDF, 0x77, 0x01, 0x10, 0xBB, 0x7A, 0x01, 0x07, 0x93, 0x7F, 0x01, 0x08, 0x87, 0x7F, 0x6D, 0x77, 0x01, 0x05, 0xA7, 0x7B, 0x01, 0x06, 0xA3, 0x7D, 0x6C, 0xC3, 0x66, 0x6A, 0xC3, 0x64, 0x67, 0xC2, 0x63, 0x65, 0xC2, 0x61, 0x62, 0xC0, 0x60, 0x5F, 0xC0, 0x5F, 0x5D, 0xBF, 0x5E, 0x5B, 0xBF, 0x4D, 0x4C, 0x91, 0x01, 0x81, 0x7C, 0x81, 0x80, 0x1D, 0x01, 0x1B, 0xB8, 0x0E, 0x89, 0x8A, 0x93, 0x01, 0x0C, 0xFC, 0x25, 0xE3, 0xE3, 0xE5, 0x01, 0x60, 0x82, 0xA0, 0x42, 0x01, 0x1B, 0x81, 0xBC, 0x2F, 0x01, 0x08, 0xEF, 0x75, 0x01, 0x07, 0xBB, 0x7A, 0x01, 0x0E, 0xC3, 0x79, 0x01, 0x0B, 0xCB, 0x78, 0x01, 0x05, 0x8F, 0x7E, 0x70, 0x7D, 0xC9, 0x6F, 0x7B, 0xC7, 0x6D, 0x01, 0x06, 0x8F, 0x7E, 0x73, 0xC5, 0x69, 0x70, 0xC4, 0x01, 0x06, 0xA3, 0x7D, 0x65, 0x68, 0xC2, 0x63, 0x66, 0xC1, 0x62, 0x63, 0xC1, 0x61, 0x61, 0xC0, 0x5F, 0x5E, 0xC0, 0x5D, 0x5B, 0xBE, 0x5C, 0x59, 0xBE, 0x59, 0x56, 0xB9, 0x3A, 0x3B, 0x01, 0x61, 0x81, 0xB3, 0x23, 0x43, 0x45, 0x57, 0x55, 0x57, 0x67, 0x52, 0x54, 0x64, 0x01, 0x6C, 0x81, 0x98, 0x11, 0x01, 0x2A, 0x84, 0x04, 0x01, 0x0F, 0x82, 0x80, 0x28, 0xD9, 0xD9, 0xDB, 0x01, 0x0F, 0x1B, 0x01, 0x69, 0x82, 0x80, 0x3D, 0x38, 0x3A, 0x4D, 0xA0, 0xA1, 0xAA, 0x01, 0x10, 0xD6, 0x35, 0xF9, 0xFC, 0x84, 0x01, 0x07, 0x97, 0x7D, 0x01, 0x08, 0xAB, 0x7C, 0x01, 0x06, 0xEF, 0x75, 0x01, 0x0A, 0xDF, 0x77, 0x01, 0x0E, 0x9F, 0x7C, 0x7C, 0xC8, 0x01, 0x0C, 0x97, 0x7D, 0x69, 0x01, 0x08, 0x87, 0x7F, 0x65, 0x68, 0xC2, 0x63, 0x65, 0x01, 0x07, 0x8F, 0x7E, 0x5F, 0x5E, 0xC0, 0x5D, 0x5A, 0xBE, 0x5C, 0x58, 0xBE, 0x5A, 0x55, 0xBD, 0x46, 0x44, 0x01, 0x19, 0x83, 0x98, 0x36, 0x01, 0x3F, 0x81, 0x4C, 0x7F, 0x81, 0x8D, 0xBF, 0xC0, 0xC6, 0x01, 0x0F, 0x81, 0xC9, 0x7E, 0xED, 0xED, 0xEF, 0xB6, 0xB6, 0xBD, 0x01, 0x81, 0x04, 0x82, 0xB4, 0x71, 0x5D, 0x5E, 0x6B, 0x01, 0x0F, 0x81, 0x84, 0x09, 0x01, 0x15, 0x86, 0x7E, 0xCE, 0xCF, 0xD2, 0x01, 0x6F, 0x82, 0xA8, 0x3E, 0x01, 0x0F, 0x81, 0xCC, 0x33, 0xF1, 0xF4, 0xFA, 0x01, 0x0C, 0xE7, 0x76, 0x01, 0x0F, 0x81, 0xA3, 0x70, 0x01, 0x08, 0xB3, 0x7B, 0x01, 0x08, 0x9B, 0x7E, 0x7D, 0x01, 0x0A, 0xAB, 0x7C, 0x01, 0x0D, 0x87, 0x7F, 0x01, 0x05, 0x9B, 0x7E, 0x62, 0x64, 0xC1, 0x61, 0x61, 0xC1, 0x5F, 0x5E, 0xBF, 0x5E, 0x5C, 0xBE, 0x5D, 0x5A, 0xBE, 0x5C, 0x57, 0xBE, 0x5A, 0x54, 0xBC, 0x4B, 0x48, 0x01, 0x52, 0xB0, 0x18, 0x54, 0x56, 0x66, 0x01, 0x06, 0x83, 0xD4, 0x51, 0x01, 0x1B, 0x82, 0x59, 0xBF, 0xC0, 0xC6, 0x01, 0x81, 0x04, 0x83, 0xB4, 0x5E, 0x96, 0x97, 0x9E, 0x01, 0x12, 0xCC, 0x19, 0x01, 0x09, 0x83, 0x7B, 0x01, 0x78, 0x81, 0xF4, 0x64, 0x01, 0x0C, 0x81, 0xD4, 0x35, 0xED, 0xF1, 0xF9, 0x01, 0x06, 0xFB, 0x75, 0x01, 0x0D, 0x87, 0x7F, 0x01, 0x0A, 0xC3, 0x79, 0x01, 0x0C, 0x8F, 0x7E, 0xC8, 0x01, 0x08, 0xBB, 0x7A, 0x01, 0x05, 0xB7, 0x7C, 0x01, 0x06, 0xAB, 0x7C, 0x01, 0x0F, 0x8F, 0x7E, 0x60, 0x01, 0x07, 0x8F, 0x7E, 0x5C, 0x58, 0xBD, 0x5B, 0x56, 0xBD, 0x5A, 0x53, 0xBD, 0x47, 0x45, 0x82, 0x01, 0x4E, 0x87, 0x79, 0x91, 0x93, 0x9D, 0x01, 0x27, 0x81, 0xC1, 0x7F, 0xF1, 0xF1, 0xF3, 0x01, 0x15, 0xD8, 0x43, 0x01, 0x78, 0x81, 0x8C, 0x3B, 0x01, 0x06, 0xFF, 0x70, 0x01, 0x06, 0x81, 0xCC, 0x3C, 0x01, 0x81, 0x01, 0x82, 0xB0, 0x34, 0x01, 0x09, 0x81, 0xDC, 0x37, 0xE8, 0xEE, 0xF7, 0x01, 0x07, 0xCB, 0x78, 0x01, 0x07, 0x81, 0xA3, 0x70, 0x01, 0x08, 0x87, 0x7F, 0x8D, 0xCD, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x07, 0xBB, 0x7A, 0x7E, 0xC9, 0x6E, 0x7A, 0xC7, 0x6E, 0x01, 0x08, 0xBB, 0x7A, 0x01, 0x06, 0xB3, 0x7B, 0x67, 0x6C, 0x01, 0x0B, 0x87, 0x7F, 0x62, 0xC1, 0x60, 0x5F, 0xC0, 0x5E, 0x5C, 0xBE, 0x5D, 0x59, 0x01, 0x05, 0x87, 0x7F, 0x55, 0xBD, 0x58, 0x52, 0xBC, 0x3D, 0x3D, 0x60, 0x01, 0x4E, 0x81, 0xE1, 0x69, 0x01, 0x0C, 0x83, 0x63, 0xD4, 0xD5, 0xD9, 0x9F, 0xA0, 0xA9, 0x7B, 0x7C, 0x89, 0x57, 0x59, 0x69, 0x5B, 0x5C, 0x6C, 0x7E, 0x7F, 0x8B, 0xA1, 0xA2, 0xAB, 0x01, 0x09, 0x84, 0x9D, 0x25, 0x01, 0x06, 0x06, 0x01, 0x6C, 0xAC, 0x0B, 0x01, 0x81, 0x34, 0x81, 0xE4, 0x39, 0xE2, 0xE8, 0xF3, 0x01, 0x0A, 0x81, 0xBB, 0x6D, 0x96, 0x01, 0x0A, 0x87, 0x7F, 0x01, 0x07, 0xC3, 0x79, 0x01, 0x07, 0x93, 0x7F, 0x01, 0x09, 0xB3, 0x7B, 0xC7, 0x6D, 0x77, 0xC7, 0x01, 0x09, 0xC3, 0x79, 0x67, 0x6D, 0xC4, 0x65, 0x6A, 0x01, 0x05, 0x9B, 0x7E, 0x65, 0x01, 0x07, 0xA3, 0x7D, 0x01, 0x06, 0x93, 0x7F, 0x5D, 0x59, 0xBE, 0x5A, 0x55, 0xBD, 0x59, 0x53, 0xBC, 0x4B, 0x47, 0x01, 0x4C, 0x8C, 0x00, 0x54, 0x56, 0x66, 0x01, 0x09, 0x87, 0x7C, 0xF2, 0xF2, 0xF3, 0x86, 0x87, 0x92, 0x01, 0x18, 0xB4, 0x31, 0x8E, 0x8F, 0x99, 0x01, 0x09, 0xCA, 0x2F, 0xF0, 0xF0, 0xF1, 0x01, 0x82, 0x1D, 0x82, 0xD9, 0x06, 0x70, 0x75, 0x87, 0x7D, 0x97, 0xCA, 0x01, 0x10, 0xA3, 0x7D, 0x01, 0x08, 0xB3, 0x7B, 0x01, 0x09, 0xDF, 0x77, 0x01, 0x08, 0xD3, 0x77, 0x01, 0x05, 0xB3, 0x7B, 0x74, 0xC6, 0x01, 0x08, 0x87, 0x7F, 0x01, 0x0C, 0xA3, 0x7D, 0xC1, 0x5F, 0x5F, 0xBF, 0x5E, 0x5C, 0xBF, 0x01, 0x07, 0x8F, 0x7E, 0x55, 0xBD, 0x4A, 0x47, 0x8C, 0x37, 0x39, 0x01, 0x4C, 0x81, 0xB3, 0x26, 0xCE, 0xCE, 0xD3, 0x01, 0x09, 0x82, 0xE4, 0x56, 0x01, 0x21, 0xD3, 0x62, 0x4F, 0x51, 0x61, 0x01, 0x09, 0x84, 0xB1, 0x3C, 0x01, 0x12, 0x83, 0xB9, 0x3C, 0x01, 0x82, 0x0F, 0x81, 0xE8, 0x46, 0x45, 0x5D, 0x70, 0x85, 0xB7, 0x01, 0x07, 0xC3, 0x79, 0x01, 0x08, 0xDF, 0x77, 0x01, 0x0E, 0xEF, 0x75, 0x01, 0x08, 0xA3, 0x7D, 0x77, 0x01, 0x07, 0xA3, 0x7D, 0x01, 0x0A, 0xBB, 0x7A, 0x01, 0x0D, 0x87, 0x7F, 0x01, 0x07, 0x8F, 0x7E, 0x59, 0x55, 0xB9, 0x43, 0x43, 0x01, 0x4F, 0xF3, 0x13, 0x01, 0x09, 0xEC, 0x1B, 0xFE, 0xFE, 0xFE, 0x01, 0x27, 0x82, 0xD8, 0x59, 0x74, 0x76, 0x83, 0x01, 0x09, 0x8C, 0x09, 0x6A, 0x6C, 0x7A, 0x01, 0x82, 0x1E, 0x82, 0xF3, 0x38, 0x3C, 0x50, 0x62, 0x72, 0x9E, 0x01, 0x0C, 0xC3, 0x79, 0x01, 0x0A, 0x87, 0x7F, 0x81, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x07, 0x9B, 0x7E, 0x01, 0x06, 0x97, 0x7D, 0x6F, 0x01, 0x06, 0x97, 0x7D, 0x01, 0x08, 0x87, 0x7F, 0x61, 0xC0, 0x01, 0x09, 0x87, 0x7F, 0x58, 0x54, 0xAF, 0x3D, 0x3E, 0x01, 0x4F, 0x81, 0xA6, 0x7C, 0x37, 0x39, 0x4C, 0xC0, 0x01, 0x08, 0x81, 0xED, 0x69, 0xAE, 0xAF, 0xB6, 0x01, 0x33, 0xEE, 0x53, 0xAC, 0xAD, 0xB5, 0x01, 0x82, 0x23, 0x81, 0x81, 0x09, 0x53, 0x5E, 0x83, 0x78, 0x8D, 0xCA, 0x01, 0x05, 0xC3, 0x79, 0x01, 0x05, 0x84, 0x01, 0x01, 0x0A, 0xA3, 0x7D, 0xC8, 0x6E, 0x79, 0x01, 0x05, 0xAB, 0x7C, 0x74, 0xC5, 0x6B, 0x73, 0xC6, 0x01, 0x0D, 0xA3, 0x7D, 0x65, 0xC1, 0x01, 0x06, 0x87, 0x7F, 0x60, 0x5E, 0xC0, 0x5E, 0x5B, 0xBF, 0x52, 0x50, 0x9F, 0x01, 0x54, 0xB8, 0x05, 0x38, 0x3A, 0x4D, 0x01, 0x09, 0x9D, 0x3B, 0x01, 0x09, 0xEF, 0x7B, 0x01, 0x24, 0x39, 0x71, 0x72, 0x7F, 0x01, 0x08, 0xA6, 0x6B, 0xE6, 0x01, 0x82, 0x26, 0x81, 0x85, 0x0D, 0x46, 0x4D, 0x69, 0x71, 0x83, 0xBF, 0x01, 0x08, 0xE7, 0x76, 0xC9, 0x01, 0x09, 0xA3, 0x7D, 0x01, 0x07, 0xDF, 0x77, 0x01, 0x08, 0xC3, 0x79, 0x01, 0x05, 0x97, 0x7D, 0xC2, 0x01, 0x05, 0x9B, 0x7E, 0x01, 0x05, 0xA3, 0x7D, 0x5F, 0xBF, 0x5F, 0x5D, 0xBF, 0x4B, 0x4A, 0x87, 0x01, 0x4E, 0x8F, 0x75, 0x01, 0x0C, 0xF2, 0x1B, 0x01, 0x09, 0x8C, 0x00, 0x01, 0x2D, 0x81, 0xD4, 0x35, 0x01, 0x09, 0xE0, 0x51, 0xFB, 0xFB, 0xFC, 0x01, 0x82, 0x2A, 0x82, 0x88, 0x4E, 0x40, 0x58, 0x67, 0x75, 0xAD, 0x01, 0x08, 0xB3, 0x7B, 0x01, 0x07, 0xF7, 0x74, 0x01, 0x0B, 0xBB, 0x7A, 0xC5, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x05, 0xBB, 0x7A, 0xC0, 0x61, 0x61, 0xC0, 0x5E, 0x5C, 0xBA, 0x43, 0x44, 0x01, 0x5B, 0x81, 0xF3, 0x1E, 0x01, 0x09, 0xEC, 0x1B, 0x01, 0x33, 0x87, 0x49, 0x01, 0x09, 0xF6, 0x55, 0x01, 0x12, 0x83, 0xE5, 0x32, 0x01, 0x82, 0x1C, 0x83, 0xFF, 0x64, 0x4E, 0x59, 0x64, 0x94, 0x01, 0x13, 0xAB, 0x7C, 0x01, 0x07, 0xB3, 0x7B, 0x01, 0x0A, 0x97, 0x7D, 0x62, 0x62, 0xC1, 0x5A, 0x59, 0xAD, 0x3D, 0x3F, 0x01, 0x5E, 0x82, 0xE3, 0x6D, 0x5A, 0x5B, 0x6B, 0x01, 0x36, 0x81, 0xE0, 0x38, 0x01, 0x0C, 0x81, 0xE4, 0x39, 0x01, 0x69, 0x9C, 0x0D, 0x01, 0x21, 0xA3, 0x65, 0x4B, 0x4D, 0x5D, 0xA3, 0xA3, 0xA9, 0x01, 0x09, 0x81, 0xB0, 0x0B, 0x01, 0x81, 0x19, 0x82, 0x9C, 0x74, 0x4C, 0x52, 0x79, 0x6E, 0x7B, 0xC3, 0x01, 0x06, 0xBB, 0x7A, 0x6C, 0x76, 0x01, 0x07, 0xC3, 0x79, 0x68, 0x6E, 0x01, 0x0D, 0xBB, 0x7A, 0x54, 0x54, 0x9A, 0x01, 0x57, 0x81, 0x84, 0x12, 0x01, 0x0F, 0xF0, 0x01, 0x01, 0x09, 0x8C, 0x03, 0x01, 0x2D, 0xB3, 0x72, 0x49, 0x4A, 0x5C, 0x01, 0x6F, 0x81, 0xF0, 0x3C, 0x01, 0x06, 0xC7, 0x5F, 0x01, 0x1B, 0xAF, 0x62, 0x89, 0x8A, 0x93, 0x01, 0x12, 0xB4, 0x28, 0xD9, 0xD9, 0xDB, 0x01, 0x81, 0x16, 0x82, 0xD8, 0x50, 0x41, 0x45, 0x62, 0x67, 0x72, 0xB7, 0x01, 0x08, 0x9F, 0x7C, 0x01, 0x05, 0x97, 0x7D, 0x01, 0x08, 0xAB, 0x7C, 0x62, 0x64, 0xC0, 0x4A, 0x4C, 0x01, 0x67, 0xB2, 0x74, 0x38, 0x3A, 0x4D, 0x01, 0x09, 0xA3, 0x59, 0x01, 0x2D, 0x81, 0x8F, 0x74, 0x01, 0x09, 0x82, 0x80, 0x76, 0xE5, 0xE5, 0xE7, 0x01, 0x67, 0x83, 0x82, 0x08, 0x01, 0x08, 0x82, 0xD8, 0x20, 0x01, 0x15, 0xD3, 0x5F, 0x01, 0x0C, 0x81, 0xE8, 0x5B, 0x01, 0x0F, 0x84, 0x04, 0x01, 0x2D, 0x81, 0xCC, 0x66, 0x01, 0x6C, 0x84, 0x04, 0x3B, 0x3D, 0x54, 0x5D, 0x64, 0xA4, 0x01, 0x06, 0xDF, 0x77, 0x67, 0x01, 0x08, 0x97, 0x7D, 0x61, 0x62, 0xB8, 0x42, 0x45, 0x01, 0x37, 0x81, 0x85, 0x6D, 0x01, 0x36, 0x36, 0x01, 0x09, 0xE0, 0x12, 0x01, 0x2D, 0x82, 0x80, 0x0A, 0x01, 0x09, 0x81, 0xDC, 0x3A, 0xAF, 0xAF, 0xB7, 0x01, 0x68, 0x82, 0xEE, 0x03, 0xF6, 0x01, 0x1B, 0x82, 0xC4, 0x1B, 0x01, 0x09, 0x8D, 0x10, 0x01, 0x06, 0x81, 0xC0, 0x48, 0x01, 0x06, 0x81, 0xBC, 0x59, 0x01, 0x5A, 0x81, 0xF0, 0x3C, 0x01, 0x4C, 0x8B, 0x05, 0x4D, 0x76, 0x5D, 0x62, 0xA9, 0x63, 0x6A, 0xBB, 0x5E, 0x62, 0xB0, 0x50, 0x53, 0x8E, 0x3A, 0x3C, 0x01, 0x4C, 0x81, 0xE8, 0x16, 0x01, 0x24, 0x24, 0x82, 0x83, 0x8F, 0x01, 0x09, 0x82, 0x88, 0x0F, 0x66, 0x67, 0x01, 0x25, 0x9C, 0x0A, 0x01, 0x0C, 0x82, 0x88, 0x75, 0x01, 0x18, 0xE4, 0x3D, 0x01, 0x57, 0xFC, 0x19, 0x01, 0x15, 0xE7, 0x61, 0x01, 0x0C, 0x81, 0xF0, 0x24, 0x01, 0x0C, 0x8B, 0x71, 0x01, 0x3C, 0xF0, 0x1C, 0x01, 0x81, 0x6D, 0x84, 0x94, 0x7C, 0xD3, 0xD3, 0xD7, 0x01, 0x09, 0x82, 0x84, 0x0E, 0x45, 0x47, 0x59, 0x01, 0x21, 0x82, 0xAE, 0x11, 0x01, 0x06, 0x81, 0x8C, 0x56, 0x01, 0x18, 0x81, 0x84, 0x57, 0x01, 0x5D, 0xDC, 0x17, 0x01, 0x1E, 0xCC, 0x2B, 0x01, 0x12, 0xD8, 0x34, 0x01, 0x09, 0xD0, 0x4A, 0x01, 0x82, 0x1D, 0x82, 0xC8, 0x55, 0x58, 0x5A, 0x6A, 0x01, 0x09, 0x83, 0xD8, 0x4F, 0xEE, 0xEE, 0xF0, 0x01, 0x1B, 0x81, 0x93, 0x78, 0x85, 0x86, 0x92, 0x01, 0x09, 0xEE, 0x29, 0xF2, 0xF2, 0xF3, 0x01, 0x69, 0x81, 0x84, 0x1B, 0x01, 0x1B, 0xE8, 0x1A, 0x5D, 0x5E, 0x01, 0x07, 0x99, 0x49, 0x01, 0x15, 0x87, 0x67, 0x01, 0x09, 0x90, 0x1C, 0x01, 0x81, 0x1F, 0x82, 0xC4, 0x5D, 0x01, 0x81, 0x01, 0x81, 0x01, 0x9B, 0x9C, 0xA5, 0x01, 0x0C, 0x92, 0x39, 0xCC, 0xCD, 0xD2, 0x96, 0x97, 0xA1, 0x72, 0x74, 0x81, 0x4F, 0x51, 0x61, 0x52, 0x54, 0x64, 0x75, 0x77, 0x84, 0x99, 0x9A, 0xA3, 0x01, 0x0F, 0x81, 0xFA, 0x34, 0x84, 0x85, 0x01, 0x6A, 0xD1, 0x18, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0x87, 0x64, 0x01, 0x18, 0x8F, 0x69, 0x01, 0x82, 0x02, 0x82, 0xE0, 0x58, 0x01, 0x27, 0x81, 0xA4, 0x2F, 0x9A, 0x9B, 0xA5, 0x01, 0x09, 0x82, 0xB1, 0x71, 0x01, 0x1E, 0xC4, 0x11, 0xF5, 0xF5, 0xF6, 0x8A, 0x8C, 0x97, 0x01, 0x6F, 0x82, 0xCC, 0x62, 0x01, 0x18, 0x84, 0x01, 0x01, 0x09, 0x8C, 0x00, 0x01, 0x18, 0x8B, 0x65, 0x01, 0x82, 0x26, 0x84, 0x01, 0x01, 0x07, 0xEF, 0x75, 0x5C, 0x6C, 0xD7, 0xD8, 0x01, 0x1F, 0xCE, 0x6F, 0xC8, 0xC8, 0xCD, 0x4F, 0x51, 0x01, 0x52, 0xB5, 0x14, 0x01, 0x27, 0x9C, 0x04, 0x01, 0x0F, 0x9F, 0x55, 0x01, 0x1E, 0x8C, 0x00, 0x01, 0x0C, 0x21, 0x01, 0x69, 0x82, 0x98, 0x52, 0x01, 0x81, 0x43, 0x88, 0x0B, 0x88, 0x89, 0x95, 0xC8, 0xC8, 0xCD, 0x01, 0x09, 0x84, 0xA5, 0x06, 0x01, 0x09, 0x81, 0x90, 0x2A, 0xBF, 0xC0, 0xC6, 0x7B, 0x7C, 0x01, 0x76, 0x83, 0xF4, 0x6B, 0x01, 0x18, 0xF3, 0x64, 0x01, 0x09, 0xD4, 0x1E, 0x01, 0x18, 0x87, 0x61, 0x01, 0x09, 0x98, 0x3F, 0x01, 0x82, 0x20, 0x82, 0xF8, 0x5E, 0x01, 0x16, 0x83, 0xDC, 0x77, 0x4E, 0x5F, 0x5E, 0x5F, 0x6F, 0x5B, 0x5D, 0x6C, 0x49, 0x4B, 0x5C, 0x01, 0x7E, 0x83, 0xE8, 0x68, 0x01, 0x0C, 0xEF, 0x66, 0x01, 0x06, 0x87, 0x4C, 0x5D, 0x5E, 0x6B, 0x01, 0x09, 0xF3, 0x79, 0xF6, 0xF6, 0xF6, 0x01, 0x18, 0x81, 0xA4, 0x17, 0x01, 0x09, 0x81, 0xA4, 0x4D, 0x01, 0x83, 0x42, 0x82, 0xC7, 0x12, 0x01, 0x09, 0x93, 0x6D, 0x01, 0x1E, 0x81, 0xA0, 0x25, 0x01, 0x15, 0x8C, 0x00, 0x01, 0x5D, 0xE8, 0x1D, 0x01, 0x82, 0x6C, 0x84, 0xAA, 0x32, 0x01, 0x0B, 0x81, 0xE4, 0x33, 0x01, 0x24, 0x82, 0x9C, 0x53, 0x01, 0x09, 0x87, 0x7F, 0x01, 0x82, 0x32, 0x8C, 0x00, 0x01, 0x81, 0x19, 0x81, 0x19, 0x89, 0x8A, 0x93, 0x01, 0x09, 0x83, 0x57, 0xD9, 0xD9, 0xDB, 0x01, 0x1B, 0x9F, 0x5E, 0x01, 0x09, 0x8C, 0x36, 0x01, 0x83, 0x33, 0x82, 0xF0, 0x59, 0x01, 0x4B, 0x90, 0x3A, 0xC4, 0xC4, 0xC8, 0x01, 0x39, 0x81, 0xB8, 0x49, 0x01, 0x91, 0x7A, 0x84, 0xD9, 0x01, 0x50, 0x51, 0x62, 0x6F, 0x70, 0x7E, 0x8E, 0x8F, 0x9A, 0xA7, 0xA8, 0xB0, 0xA9, 0xAA, 0xB2, 0xA9, 0xAA, 0xB2, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0F, 0x0F, 0x01, 0x83, 0x48, 0x83, 0x7E, 0x6B, 0x6D, 0x7B, 0x01, 0x09, 0x84, 0x9D, 0x10, 0x01, 0x83, 0x6F, 0x83, 0xD8, 0x76, 0x3E, 0x3F, 0x52, 0xBC, 0xBD, 0xC3, 0x01, 0x83, 0x78, 0x85, 0x89, 0x22, 0x01, 0x15, 0x81, 0xE0, 0x1A, 0xF8, 0xF8, 0xF9, 0xDB, 0xDC, 0xDF, 0xC4, 0xC5, 0xCB, 0xC4, 0xC4, 0xCA, 0xC4, 0xC4, 0xCA, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0C, 0x0C, 0x01, 0x83, 0x4B, 0x85, 0xE9, 0x37, 0x01, 0x06, 0x81, 0x80, 0x1A, 0x62, 0x63, 0x72, 0x01, 0x83, 0x6C, 0x84, 0xE9, 0x0B, 0x01, 0x09, 0x84, 0xD9, 0x13, 0xFF, 0xFF, 0xFF, 0xA7, 0xA8, 0xB1, 0x01, 0x83, 0x72, 0x85, 0x90, 0x74, 0x01, 0x06, 0x85, 0xA9, 0x21, 0x01, 0x06, 0x84, 0xB5, 0x0D, 0x01, 0x81, 0x46, 0x81, 0xF4, 0x13, 0x01, 0x82, 0x2C, 0x83, 0x7E, 0x43, 0x45, 0x01, 0x0A, 0x82, 0xD4, 0x1C, 0x01, 0x81, 0x07, 0x81, 0x8F, 0x77, 0x01, 0x82, 0x71, 0x90, 0x01, 0x01, 0x0A, 0x82, 0xCF, 0x2C, 0x01, 0x14, 0x81, 0xC8, 0x1D, 0x01, 0x83, 0x60, 0x84, 0x01, 0x01, 0x09, 0x84, 0xD5, 0x15, 0x01, 0x69, 0x81, 0xDB, 0x7E, 0x01, 0x83, 0x12, 0x83, 0xE8, 0x7A, 0x01, 0x09, 0x84, 0x80, 0x71, 0x01, 0x51, 0x82, 0xAF, 0x7B, 0x01, 0x83, 0x27, 0x84, 0x04, 0x01, 0x06, 0x82, 0x80, 0x3D, 0xFF, 0xFF, 0xFF, 0x79, 0x7B, 0x01, 0x43, 0x82, 0xED, 0x2C, 0x01, 0x83, 0x33, 0x84, 0x01, 0x9C, 0x9D, 0xA6, 0x01, 0x15, 0x84, 0xC9, 0x0F, 0x01, 0x83, 0x69, 0x84, 0x01, 0x49, 0x4B, 0x5C, 0x01, 0x06, 0xEC, 0x18, 0xF4, 0xF4, 0xF5, 0x01, 0x15, 0x84, 0xCD, 0x34, 0x01, 0x83, 0x63, 0x84, 0x04, 0x01, 0x09, 0x81, 0xF0, 0x27, 0xD7, 0xD7, 0xDB, 0x01, 0x83, 0x69, 0x85, 0xC9, 0x2C, 0x01, 0x0F, 0x0F, 0x01, 0x09, 0x84, 0xCC, 0x7E, 0xCC, 0xCD, 0xD2, 0x5C, 0x5E, 0x6D, 0x01, 0x83, 0x75, 0x84, 0x04, 0x75, 0x77, 0x84, 0x01, 0x06, 0x82, 0xD8, 0x35, 0xFD, 0xFD, 0xFD, 0xB5, 0xB6, 0xBD, 0x78, 0x7A, 0x86, 0x5B, 0x5C, 0x6C, 0x01, 0x83, 0x6F, 0x9C, 0x1C, 0x5A, 0x5B, 0x6B, 0xE3, 0xE3, 0xE6, 0x01, 0x0F, 0x82, 0xAD, 0x7C, 0xF3, 0xF3, 0xF4, 0xF3, 0xF3, 0xF4, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x09, 0x09, 0x01, 0x83, 0x48, 0x85, 0x91, 0x27, 0x01, 0x06, 0x82, 0x88, 0x12, 0x01, 0x83, 0x75, 0xC0, 0x10, 0x55, 0x57, 0x67, 0x01, 0x3C, 0x82, 0x8E, 0x42, 0x01, 0x83, 0x42, 0x84, 0xD0, 0x7C, 0xE5, 0xE6, 0xE8, 0x01, 0x0C, 0x83, 0x51, 0xE4, 0xE4, 0xE7, 0xB9, 0xB9, 0xC0, 0x99, 0x9A, 0xA4, 0x83, 0x84, 0x90, 0x82, 0x83, 0x8F, 0x82, 0x83, 0x8F, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0C, 0x0C, 0x01, 0x83, 0x3F, 0x84, 0x01, 0x85, 0x86, 0x92, 0x01, 0x0C, 0x84, 0xD8, 0x7B, 0x92, 0x93, 0x9E, 0x01, 0x83, 0x6F, 0x84, 0xD5, 0x00, 0x01, 0x09, 0x82, 0xF0, 0x2F, 0xFF, 0xFF, 0xFF, 0x73, 0x74, 0x01, 0x4C, 0x81, 0xCD, 0x07, 0x01, 0x83, 0x27, 0x8C, 0x00, 0x01, 0x09, 0x82, 0xAC, 0x2A, 0xBC, 0xBD, 0xC3, 0x01, 0x83, 0x72, 0x9F, 0x7C, 0x54, 0x55, 0x65, 0x01, 0x83, 0x7B, 0x87, 0x7F, 0x37, 0x39, 0x4C, 0x63, 0x65, 0x74, 0x01, 0x09, 0x84, 0x01, 0x01, 0x83, 0x75, 0xB0, 0x09, 0x01, 0x0C, 0x83, 0xA4, 0x69, 0x01, 0x83, 0x75, 0xB0, 0x06, 0x3A, 0x3C, 0x4E, 0x01, 0x09, 0x90, 0x04, 0x01, 0x83, 0x78, 0xB0, 0x03, 0x01, 0x09, 0x81, 0xA3, 0x7F, 0x01, 0x83, 0x51, 0x85, 0xC1, 0x03, 0x01, 0x30, 0x81, 0xB4, 0x2D, 0x01, 0x12, 0x82, 0xAC, 0x4E, 0x01, 0x83, 0x69, 0x86, 0x85, 0x44, 0x01, 0x09, 0xCC, 0x16, 0x78, 0x79, 0x01, 0x83, 0x49, 0x81, 0x92, 0x4D, 0x01, 0x30, 0x82, 0x98, 0x16, 0x01, 0x06, 0x81, 0xC4, 0x37, 0xF2, 0xF2, 0x01, 0x16, 0x85, 0x95, 0x49, 0x01, 0x83, 0x63, 0x84, 0x04, 0x6B, 0x6D, 0x7B, 0x01, 0x06, 0xE8, 0x23, 0xF6, 0xF6, 0xF7, 0x99, 0x9A, 0xA3, 0x01, 0x83, 0x69, 0xC0, 0x07, 0x3C, 0x3E, 0x50, 0x63, 0x65, 0x74, 0x63, 0x65, 0x74, 0x63, 0x65, 0x74, 0x6D, 0x6F, 0x7D, 0x01, 0x09, 0x82, 0x96, 0x1D, 0xE9, 0xEA, 0xEC, 0xB3, 0xB4, 0xBB, 0x95, 0x96, 0xA0, 0x76, 0x77, 0x84, 0x01, 0x09, 0x21, 0x01, 0x09, 0x09, 0x01, 0x0F, 0x0F, 0x01, 0x87, 0x3D, 0x86, 0x89, 0x42, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x09, 0x85, 0xED, 0x1A, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x12, 0x12, 0x01, 0xA3, 0x47, 0x85, 0x95, 0x16, 0x3A, 0x3C, 0x4E, 0x3E, 0x3F, 0x52, 0x3E, 0x3F, 0x52, 0x01, 0x30, 0xA3, 0x53, 0x47, 0x49, 0x5A, 0x01, 0x75, 0x84, 0x80, 0x7D, 0x01, 0x82, 0x59, 0x83, 0xA6, 0x6E, 0x01, 0x2A, 0xB7, 0x58, 0x3C, 0x3E, 0x50, 0xC5, 0xC6, 0xCB, 0xFB, 0xFB, 0xFC, 0xEC, 0xED, 0xEE, 0x01, 0x12, 0x85, 0xDA, 0x07, 0x01, 0x83, 0x31, 0x85, 0x91, 0x21, 0x01, 0x08, 0x83, 0x96, 0x6A, 0x01, 0x2D, 0xBB, 0x59, 0xC1, 0xC1, 0xC7, 0x01, 0x07, 0x82, 0xFE, 0x3A, 0x92, 0x01, 0x81, 0x74, 0x82, 0xD9, 0x66, 0x01, 0x81, 0x4C, 0x81, 0x4C, 0x90, 0x91, 0x01, 0x34, 0x84, 0x01, 0x01, 0x09, 0x82, 0xA0, 0x48, 0xD6, 0xD6, 0xDA, 0x01, 0x83, 0x48, 0x81, 0x90, 0x21, 0x01, 0x2D, 0x84, 0x01, 0x4C, 0x4E, 0x5F, 0x01, 0x09, 0x83, 0x9C, 0x6D, 0x01, 0x83, 0x3F, 0xB4, 0x10, 0x8E, 0x8F, 0x99, 0x01, 0x33, 0x84, 0x01, 0x01, 0x09, 0x82, 0xA4, 0x49, 0xFF, 0xFF, 0xFF, 0x01, 0x72, 0x81, 0xF8, 0x4D, 0x01, 0x82, 0x4D, 0x84, 0x01, 0x8C, 0x8D, 0x98, 0x01, 0x33, 0x84, 0x01, 0x84, 0x85, 0x91, 0x01, 0x09, 0x82, 0x9C, 0x47, 0x01, 0x81, 0x19, 0x84, 0xF9, 0x54, 0x01, 0x82, 0x1A, 0xF8, 0x12, 0x3A, 0x3C, 0x4F, 0x01, 0x06, 0x06, 0x3A, 0x3C, 0x4F, 0x01, 0x09, 0x88, 0x02, 0x67, 0x69, 0x77, 0x01, 0x0F, 0x1B, 0x01, 0x0F, 0x0F, 0x3A, 0x3C, 0x4F, 0x41, 0x43, 0x55, 0x57, 0x58, 0x68, 0x94, 0x95, 0x9F, 0x01, 0x09, 0x82, 0x9C, 0x7D, 0x01, 0x15, 0x83, 0x99, 0x1F, 0x01, 0x83, 0x24, 0x85, 0x81, 0x0E, 0x01, 0x48, 0x83, 0x8A, 0x40, 0x80, 0x81, 0x01, 0x55, 0x83, 0x81, 0x73, 0x01, 0x83, 0x27, 0x84, 0x01, 0x01, 0x15, 0x86, 0x89, 0x78, 0x01, 0x83, 0x63, 0x84, 0x01, 0xF7, 0xF8, 0xF8, 0xD6, 0xD6, 0xDA, 0x01, 0x83, 0x36, 0x81, 0x80, 0x50, 0x41, 0x43, 0x55, 0x61, 0x62, 0x71, 0x61, 0x62, 0x71, 0x01, 0x06, 0x06, 0x61, 0x62, 0x71, 0x01, 0x09, 0x81, 0xD8, 0x33, 0x84, 0x85, 0x91, 0x01, 0x0F, 0x1B, 0x01, 0x0F, 0x0F, 0x01, 0x06, 0x06, 0x01, 0x83, 0x51, 0x81, 0xBC, 0x56, 0x01, 0x09, 0x84, 0x90, 0x4E, 0x01, 0x83, 0x3F, 0xE3, 0x63, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x3C, 0x82, 0xA8, 0x47, 0x87, 0x88, 0x94, 0x87, 0x88, 0x94, 0x49, 0x4A, 0x01, 0x81, 0x02, 0x82, 0xE8, 0x30, 0x01, 0xA3, 0x6E, 0x85, 0xF2, 0x1F, 0x01, 0x83, 0x1B, 0xE0, 0x21, 0x7B, 0x7C, 0x89, 0xA0, 0xA1, 0xAA, 0xC5, 0xC6, 0xCB, 0xE3, 0xE3, 0xE6, 0xE6, 0xE6, 0xE9, 0xE7, 0xE7, 0xE9, 0xE8, 0xE8, 0xEA, 0xE8, 0xE8, 0xEA, 0xE9, 0xE9, 0xEB, 0xE9, 0xEA, 0xEC, 0xE9, 0xEA, 0xEC, 0xEA, 0xEA, 0xEC, 0xEB, 0xEB, 0xED, 0xEC, 0xEC, 0xEE, 0xEC, 0xEC, 0xEE, 0xEC, 0xED, 0xEE, 0xED, 0xED, 0xEF, 0xED, 0xED, 0xEF, 0x01, 0x83, 0x45, 0x83, 0x7E, 0x57, 0x59, 0x69, 0x01, 0x21, 0x82, 0xC8, 0x4C, 0x01, 0x83, 0x5A, 0x81, 0xD4, 0x35, 0x6D, 0x6F, 0x7D, 0x01, 0x30, 0x84, 0xD6, 0x5E, 0x01, 0x83, 0x4E, 0x81, 0xD4, 0x35, 0xE0, 0xE0, 0xE3, 0x01, 0x09, 0x83, 0x4E, 0xDC, 0xDC, 0xE0, 0xAB, 0xAB, 0xB3, 0x89, 0x8A, 0x95, 0x7F, 0x80, 0x8C, 0x01, 0x06, 0x84, 0xF9, 0x15, 0xD7, 0xD8, 0xDB, 0x76, 0x77, 0x84, 0x76, 0x77, 0x84, 0x8A, 0x8B, 0x96, 0x01, 0x0A, 0x85, 0xE9, 0x67, 0xF0, 0xF1, 0x79, 0x7B, 0x87, 0x6D, 0x6F, 0x7D, 0x6D, 0x6F, 0x01, 0x64, 0x82, 0xE4, 0x59, 0x01, 0x82, 0x65, 0xDC, 0x17, 0xFD, 0xFD, 0xFD, 0x99, 0x9A, 0xA3, 0x01, 0x0C, 0x82, 0xCC, 0x3B, 0x01, 0x06, 0x83, 0xEF, 0x12, 0xC4, 0xC5, 0xCB, 0x01, 0x0E, 0x83, 0x94, 0x68, 0x01, 0x07, 0xE0, 0x48, 0xD6, 0xD6, 0xDA, 0x42, 0x44, 0x01, 0x70, 0x82, 0xEA, 0x08, 0x01, 0x82, 0x53, 0x84, 0x01, 0x01, 0x09, 0x8F, 0x7B, 0xB1, 0xB2, 0xB9, 0x01, 0x0F, 0x1B, 0x01, 0x12, 0x84, 0x01, 0x01, 0x06, 0x06, 0x8F, 0x90, 0x9B, 0x01, 0x82, 0x2C, 0x83, 0x8C, 0x60, 0x01, 0x81, 0x1F, 0x81, 0x1F, 0x01, 0x06, 0x83, 0x8C, 0x63, 0xFB, 0xFB, 0xFB, 0x01, 0x12, 0x85, 0xE5, 0x39, 0x01, 0x18, 0x84, 0x01, 0x01, 0x09, 0x84, 0x8F, 0x3E, 0xFD, 0xFD, 0xFD, 0x5A, 0x5B, 0x01, 0x83, 0x3D, 0x82, 0xC3, 0x2F, 0x01, 0x09, 0x83, 0x80, 0x27, 0xDF, 0xDF, 0xE2, 0x01, 0x12, 0x1E, 0x01, 0x1B, 0x84, 0x01, 0x76, 0x77, 0x84, 0x01, 0x81, 0x04, 0x85, 0x81, 0x23, 0x01, 0x82, 0x4A, 0x81, 0xD4, 0x35, 0x01, 0x15, 0x82, 0xAC, 0x12, 0x01, 0x1B, 0x84, 0x01, 0x39, 0x3B, 0x4E, 0x01, 0x06, 0x82, 0x84, 0x77, 0xDE, 0xDE, 0xE1, 0x01, 0x83, 0x45, 0x85, 0xF5, 0x3D, 0xB9, 0xB9, 0x01, 0x13, 0x84, 0x9D, 0x67, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0x86, 0x81, 0x79, 0xFD, 0xFD, 0xFD, 0x01, 0x7E, 0x82, 0xE0, 0x73, 0x01, 0x82, 0x47, 0x81, 0xD8, 0x36, 0xDB, 0xDC, 0xDF, 0x01, 0x12, 0x1E, 0x01, 0x06, 0x84, 0xBB, 0x25, 0x01, 0x18, 0x84, 0x88, 0x64, 0x01, 0x09, 0x83, 0xC2, 0x66, 0x01, 0x83, 0x3C, 0xD0, 0x4D, 0x3B, 0x3D, 0x50, 0x01, 0x06, 0xA4, 0x03, 0x01, 0x15, 0x84, 0x8D, 0x03, 0x01, 0x06, 0x84, 0x90, 0x69, 0x01, 0x15, 0x84, 0x95, 0x1D, 0x37, 0x39, 0x4C, 0xD5, 0x01, 0x08, 0x85, 0xDD, 0x64, 0x01, 0x18, 0x83, 0xE5, 0x23, 0x01, 0x83, 0x27, 0x84, 0x04, 0x01, 0x09, 0x84, 0x86, 0x77, 0x5F, 0x60, 0x01, 0x10, 0x85, 0xE5, 0x2D, 0x01, 0x06, 0x83, 0xA9, 0x05, 0xF0, 0xF1, 0xF2, 0x01, 0x15, 0x39, 0x01, 0x06, 0x88, 0x20, 0xF8, 0xF8, 0xF9, 0x01, 0x83, 0x3C, 0x8C, 0x03, 0x01, 0x0C, 0x81, 0x8C, 0x23, 0xB2, 0xB2, 0x01, 0x10, 0x84, 0x80, 0x68, 0xA5, 0xA6, 0x01, 0x07, 0x84, 0x87, 0x0F, 0x67, 0x69, 0x77, 0x01, 0x0F, 0x1B, 0x73, 0x74, 0x82, 0x01, 0x07, 0x83, 0xF6, 0x5E, 0xDA, 0xDE, 0x01, 0x83, 0x3F, 0xA0, 0x08, 0x3F, 0x41, 0x53, 0x01, 0x06, 0x83, 0xA4, 0x33, 0xFC, 0xFC, 0xFC, 0x57, 0x59, 0x69, 0x01, 0x15, 0x83, 0xFD, 0x1A, 0xC6, 0xC7, 0xCC, 0x01, 0x0C, 0x81, 0xFC, 0x54, 0x48, 0x4A, 0x5B, 0x01, 0x09, 0x81, 0xF8, 0x74, 0xAD, 0xAE, 0x01, 0x83, 0x43, 0xA4, 0x0C, 0x8D, 0x8E, 0x01, 0x07, 0xAC, 0x0E, 0xC1, 0xC1, 0xC7, 0x01, 0x18, 0x8F, 0x69, 0xC8, 0xC9, 0xCE, 0x7B, 0x7C, 0x89, 0x65, 0x66, 0x75, 0x8D, 0x8E, 0x99, 0x01, 0x09, 0x82, 0x88, 0x6F, 0xF4, 0xF4, 0xF5, 0x01, 0x81, 0x04, 0x83, 0xCC, 0x7F, 0x01, 0x82, 0x44, 0x94, 0x0B, 0x01, 0x06, 0x83, 0xDE, 0x3D, 0xB9, 0xB9, 0xC0, 0x01, 0x0F, 0x82, 0x84, 0x3E, 0x6F, 0x70, 0x7E, 0x01, 0x1B, 0x84, 0x83, 0x02, 0x8C, 0x8D, 0x98, 0x01, 0x83, 0x48, 0xC4, 0x0E, 0x71, 0x72, 0x7F, 0x01, 0x18, 0x83, 0x9C, 0x64, 0x71, 0x73, 0x80, 0x01, 0x12, 0x85, 0xA3, 0x00, 0xF4, 0xF4, 0xF5, 0x7F, 0x01, 0x83, 0x2F, 0x81, 0x84, 0x1B, 0x01, 0x3F, 0x82, 0x80, 0x67, 0x99, 0x9A, 0xA3, 0xC4, 0xC4, 0xCA, 0xE0, 0xE0, 0xE3, 0xBF, 0xC0, 0xC6, 0x97, 0x98, 0xA2, 0x01, 0x81, 0x46, 0x85, 0xC1, 0x3C, 0x00}; +static bool g_has_uncompressed = false; + +static unsigned char *get_uncompressed_splash(void) { + unsigned char *splash = (unsigned char *)0xE0000000; + if (!g_has_uncompressed) { + LZ_Uncompress(s_splash, splash, sizeof(s_splash)); + g_has_uncompressed = true; + } + return splash; +} + +void draw_splash(volatile uint32_t *fb) { + unsigned char *splash = get_uncompressed_splash(); + + size_t pos = 0; + for (size_t y = 496; y < (496 + 287); y++) + { + for (size_t x = 293; x < (293 + 171); x++) + { + fb[x + y*768] = splash[pos + 2] | (splash[pos + 1] << 8) | (splash[pos] << 16); + pos += 3; + } + } +} \ No newline at end of file diff --git a/sept/sept-secondary/src/splash.h b/sept/sept-secondary/src/splash.h new file mode 100644 index 000000000..842ef0575 --- /dev/null +++ b/sept/sept-secondary/src/splash.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SEPT_SPLASH_H +#define SEPT_SPLASH_H + +void draw_splash(volatile uint32_t *fb); + +#endif From 656053582acd18e301494e476a47ee4dba91900c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 15:18:39 -0800 Subject: [PATCH 429/489] Fix copy/pasted copyright notice --- sept/sept-secondary/src/splash.c | 2 +- sept/sept-secondary/src/splash.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sept/sept-secondary/src/splash.c b/sept/sept-secondary/src/splash.c index 33cf6f719..1b8408605 100644 --- a/sept/sept-secondary/src/splash.c +++ b/sept/sept-secondary/src/splash.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CtCaer * Copyright (c) 2018 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it diff --git a/sept/sept-secondary/src/splash.h b/sept/sept-secondary/src/splash.h index 842ef0575..78cc8dc58 100644 --- a/sept/sept-secondary/src/splash.h +++ b/sept/sept-secondary/src/splash.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 naehrwert + * Copyright (c) 2018 CtCaer * Copyright (c) 2018 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it From f1ea368585a9b40bdf159426bcec22e9d6dc153c Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 15:24:11 -0800 Subject: [PATCH 430/489] sept-s: turn on backlight after drawing image. --- sept/sept-secondary/src/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index d97ec791c..9c1780a92 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -115,10 +115,6 @@ static void setup_env(void) { /* Set the framebuffer. */ display_init_framebuffer(g_framebuffer); - - /* Turn on the backlight after initializing the lfb */ - /* to avoid flickering. */ - display_backlight(true); /* Set display background color. */ for (size_t i = 0; i < 1280 * 768 * 4; i += 4) { @@ -128,6 +124,10 @@ static void setup_env(void) { /* Draw splash. */ draw_splash((volatile uint32_t *)g_framebuffer); + /* Turn on the backlight after initializing the lfb */ + /* to avoid flickering. */ + display_backlight(true); + /* Set up the exception handlers. */ setup_exception_handlers(); From 0df92148a4559f59be3d0ed84d724e3c677d7b92 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 21:26:35 -0800 Subject: [PATCH 431/489] sept: change splash to fancy one by @xamanthas --- sept/sept-secondary/src/main.c | 7 ------- sept/sept-secondary/src/splash.c | 12 ++++++++++-- sept/sept-secondary/src/splash.h | 3 ++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 9c1780a92..892072573 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -57,8 +57,6 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { uint8_t *dec_se_state = (uint8_t *)0x4003F000; if (!has_rebooted()) { - - /* Save the security engine context. */ se_get_regs()->_0x4 = 0x0; se_set_in_context_save_mode(true); @@ -116,11 +114,6 @@ static void setup_env(void) { /* Set the framebuffer. */ display_init_framebuffer(g_framebuffer); - /* Set display background color. */ - for (size_t i = 0; i < 1280 * 768 * 4; i += 4) { - MAKE_REG32((uintptr_t)g_framebuffer + i) = 0xFF37394C; - } - /* Draw splash. */ draw_splash((volatile uint32_t *)g_framebuffer); diff --git a/sept/sept-secondary/src/splash.c b/sept/sept-secondary/src/splash.c index 1b8408605..c5e292059 100644 --- a/sept/sept-secondary/src/splash.c +++ b/sept/sept-secondary/src/splash.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2018 CtCaer + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 xamanthas * Copyright (c) 2018 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it @@ -20,8 +21,9 @@ #include <stdbool.h> #include "splash.h" #include "lib/lz.h" +#include "utils.h" -static const uint8_t s_splash[] = {0x01, 0x37, 0x39, 0x4C, 0x37, 0x39, 0x4C, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x30, 0x30, 0x01, 0x60, 0x60, 0x01, 0x57, 0x57, 0x73, 0x74, 0x82, 0xB4, 0xB5, 0xBC, 0xC6, 0xC7, 0xCC, 0xD9, 0xD9, 0xDD, 0xEB, 0xEB, 0xED, 0xFB, 0xFB, 0xFC, 0x61, 0x62, 0x71, 0x01, 0x82, 0x17, 0x82, 0x2C, 0x01, 0x81, 0x4C, 0x81, 0x4C, 0x38, 0x3A, 0x4D, 0x7A, 0x7B, 0x88, 0xDA, 0xDB, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x04, 0x04, 0x01, 0x08, 0x08, 0xFF, 0xFF, 0x01, 0x0F, 0x84, 0x01, 0x3E, 0x3F, 0x52, 0x87, 0x88, 0x94, 0x01, 0x83, 0x4E, 0x83, 0x7E, 0x52, 0x54, 0x64, 0xDF, 0xDF, 0xE2, 0x01, 0x0F, 0x83, 0x78, 0xF9, 0xF9, 0xFA, 0x01, 0x12, 0x84, 0x01, 0x42, 0x44, 0x56, 0xCF, 0xD0, 0xD4, 0xFF, 0xFF, 0xFF, 0x96, 0x97, 0xA1, 0x01, 0x83, 0x48, 0x83, 0x7E, 0x4E, 0x50, 0x61, 0xE8, 0xE8, 0xEA, 0x01, 0x09, 0x83, 0x78, 0xB9, 0xBA, 0xC1, 0x78, 0x7A, 0x86, 0x4C, 0x4E, 0x5F, 0x95, 0x96, 0xA0, 0x01, 0x12, 0x84, 0x01, 0x67, 0x69, 0x77, 0xFE, 0xFE, 0xFE, 0x01, 0x06, 0x18, 0x65, 0x66, 0x75, 0x01, 0x83, 0x45, 0x84, 0x01, 0xC4, 0xC5, 0xCB, 0x01, 0x06, 0x83, 0x51, 0xEF, 0xEF, 0xF0, 0x76, 0x77, 0x84, 0x01, 0x09, 0x18, 0x01, 0x15, 0x84, 0x01, 0x37, 0x39, 0x4C, 0xAA, 0xAB, 0xB3, 0x01, 0x06, 0x18, 0xD3, 0xD3, 0xD7, 0x01, 0x83, 0x42, 0x83, 0x7E, 0x6C, 0x6D, 0x7B, 0x01, 0x06, 0x83, 0x4E, 0xFD, 0xFD, 0xFD, 0x5F, 0x60, 0x6F, 0x01, 0x0C, 0x1B, 0x01, 0x18, 0x84, 0x01, 0x3E, 0x40, 0x53, 0xE2, 0xE3, 0xE5, 0x01, 0x06, 0x1B, 0x69, 0x6A, 0x78, 0x01, 0x83, 0x3F, 0x84, 0x01, 0xB3, 0xB4, 0xBB, 0x01, 0x06, 0x83, 0x4B, 0xAB, 0xAB, 0xB3, 0x01, 0x0F, 0x1B, 0x01, 0x18, 0x84, 0x01, 0x37, 0x39, 0x4C, 0x83, 0x85, 0x90, 0x01, 0x06, 0x1B, 0xA6, 0xA7, 0xAF, 0x01, 0x83, 0x3F, 0x84, 0x01, 0xEE, 0xEE, 0xF0, 0x01, 0x06, 0x83, 0x4B, 0x46, 0x48, 0x5A, 0x01, 0x2A, 0x84, 0x01, 0x5D, 0x5F, 0x6E, 0x01, 0x06, 0x1B, 0xDE, 0xDF, 0xE2, 0x01, 0x83, 0x3C, 0x83, 0x7E, 0x44, 0x46, 0x57, 0x01, 0x06, 0x83, 0x48, 0xE9, 0xE9, 0xEB, 0x01, 0x12, 0x1E, 0x01, 0x1B, 0x84, 0x01, 0x3B, 0x3D, 0x50, 0xFB, 0xFB, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, 0xF8, 0xF8, 0x01, 0x83, 0x3C, 0x84, 0x01, 0x55, 0x57, 0x67, 0x01, 0x06, 0x83, 0x63, 0xC8, 0xC8, 0xCD, 0x01, 0x2D, 0x84, 0x01, 0x37, 0x39, 0x4C, 0x01, 0x09, 0xA0, 0x32, 0x41, 0x43, 0x55, 0x01, 0x83, 0x39, 0x84, 0x01, 0x5C, 0x5E, 0x6D, 0x01, 0x06, 0x83, 0x45, 0xB8, 0xB9, 0xBF, 0x01, 0x39, 0x84, 0x01, 0x49, 0x4B, 0x5C, 0x01, 0x83, 0x39, 0x84, 0x01, 0x4C, 0x4D, 0x5E, 0x01, 0x06, 0x83, 0x45, 0xD7, 0xD8, 0xDB, 0x01, 0x2D, 0x84, 0x01, 0x39, 0x3B, 0x4E, 0x01, 0x06, 0xA4, 0x27, 0xFE, 0xFE, 0xFE, 0x3A, 0x3C, 0x4E, 0x01, 0x83, 0x39, 0x84, 0x01, 0x3A, 0x3C, 0x4F, 0x01, 0x09, 0x8F, 0x4B, 0x38, 0x3A, 0x4D, 0x01, 0x2A, 0x84, 0x01, 0x54, 0x56, 0x66, 0x01, 0x06, 0x1B, 0xEC, 0xEC, 0xEE, 0x01, 0x83, 0x3F, 0x98, 0x06, 0xCC, 0xCC, 0xD1, 0x01, 0x06, 0x83, 0x4B, 0x6F, 0x70, 0x7E, 0x01, 0x2A, 0x84, 0x01, 0xA3, 0xA4, 0xAC, 0x01, 0x07, 0xA8, 0x37, 0xB9, 0xC0, 0x01, 0x83, 0x3F, 0x84, 0x01, 0x8E, 0x8F, 0x9A, 0x01, 0x06, 0x83, 0x4B, 0xE1, 0xE1, 0xE4, 0x3B, 0x3D, 0x50, 0x01, 0x24, 0x84, 0x01, 0x54, 0x55, 0x65, 0xFA, 0xFA, 0x01, 0x07, 0xB0, 0x27, 0x7C, 0x7D, 0x89, 0x01, 0x83, 0x3F, 0x84, 0x01, 0x3C, 0x3E, 0x50, 0xDE, 0x01, 0x08, 0xB4, 0x07, 0xA4, 0xA5, 0xAE, 0x01, 0x21, 0x84, 0x01, 0x45, 0x47, 0x59, 0xD1, 0xD1, 0xD6, 0x01, 0x06, 0x18, 0xD0, 0xD1, 0xD5, 0x01, 0x12, 0x8C, 0x39, 0x01, 0x83, 0x33, 0x84, 0x04, 0x62, 0x63, 0x72, 0xFD, 0xFD, 0xFD, 0x01, 0x06, 0x83, 0x54, 0xC4, 0xC4, 0xCA, 0x45, 0x46, 0x58, 0x01, 0x18, 0x84, 0x01, 0x5F, 0x61, 0x70, 0xE6, 0xE6, 0xE9, 0x01, 0x06, 0x15, 0xF8, 0xF8, 0xF9, 0x55, 0x57, 0x67, 0x01, 0x83, 0x48, 0xB8, 0x11, 0xA4, 0xA4, 0xAD, 0x01, 0x09, 0xB8, 0x0E, 0xEC, 0xED, 0xEE, 0xAC, 0xAD, 0xB5, 0x71, 0x73, 0x80, 0x9D, 0x9E, 0xA7, 0x01, 0x06, 0x12, 0x74, 0x75, 0x82, 0x85, 0x86, 0x92, 0xC3, 0xC3, 0xC9, 0x01, 0x09, 0x8B, 0x7A, 0xFF, 0xFF, 0xFF, 0x92, 0x93, 0x9E, 0x01, 0x83, 0x4B, 0xC0, 0x10, 0x3C, 0x3E, 0x50, 0xA5, 0xA6, 0xAE, 0xFC, 0xFC, 0xFC, 0x01, 0x12, 0xC4, 0x0E, 0x01, 0x12, 0x12, 0xFA, 0xFA, 0xFA, 0x9B, 0x9C, 0xA5, 0x39, 0x3B, 0x01, 0x83, 0x3A, 0x9B, 0x7E, 0x01, 0x18, 0x18, 0x5F, 0x61, 0x70, 0xDA, 0xDA, 0x01, 0x13, 0xC8, 0x12, 0x01, 0x0C, 0x0C, 0xD1, 0xD1, 0xD6, 0x57, 0x59, 0x69, 0x01, 0x83, 0x5A, 0xCC, 0x19, 0x3A, 0x3C, 0x4E, 0x8A, 0x8B, 0x96, 0xC8, 0xC9, 0xCE, 0xF8, 0xF8, 0xF9, 0x01, 0x0C, 0x83, 0x78, 0xF6, 0xF6, 0xF7, 0xC4, 0xC4, 0xCA, 0x82, 0x83, 0x8F, 0x01, 0x83, 0x45, 0x93, 0x76, 0x01, 0x27, 0xA4, 0x24, 0x4C, 0x4D, 0x5E, 0x5E, 0x5F, 0x6F, 0x5C, 0x5E, 0x6D, 0x4B, 0x4D, 0x5E, 0x01, 0x83, 0x3C, 0xA7, 0x6F, 0x01, 0x83, 0x66, 0x87, 0x31, 0x01, 0x87, 0x1F, 0x87, 0x1F, 0x01, 0x89, 0x1B, 0x89, 0x1B, 0x40, 0x42, 0x54, 0x5F, 0x61, 0x70, 0x5F, 0x61, 0x70, 0x5F, 0x61, 0x70, 0x01, 0x83, 0x75, 0x97, 0x68, 0x57, 0x59, 0x69, 0x01, 0x09, 0x9F, 0x6A, 0x01, 0x83, 0x5D, 0xA3, 0x5F, 0x01, 0x18, 0x18, 0x3E, 0x3F, 0x52, 0x01, 0x09, 0xE7, 0x67, 0x75, 0x01, 0x0B, 0xE4, 0x13, 0x01, 0x83, 0x6C, 0x84, 0x04, 0x01, 0x09, 0xF0, 0x13, 0x93, 0x94, 0x01, 0x83, 0x4C, 0xB3, 0x5D, 0x01, 0x2A, 0x2A, 0x8C, 0x8D, 0x98, 0x01, 0x09, 0xDF, 0x62, 0x3A, 0x3C, 0x4F, 0x01, 0x83, 0x75, 0x94, 0x08, 0xEC, 0xED, 0xEE, 0x01, 0x83, 0x54, 0xBB, 0x62, 0x01, 0x2D, 0xB8, 0x05, 0xF6, 0xF6, 0xF7, 0xFF, 0xFF, 0xFF, 0xF5, 0xF5, 0xF6, 0x6B, 0x6D, 0x7B, 0x01, 0x83, 0x75, 0x84, 0x04, 0x6A, 0x6C, 0x7A, 0xE9, 0xE9, 0xEB, 0x01, 0x06, 0xDB, 0x67, 0xA5, 0xA6, 0xAE, 0x01, 0x0F, 0xD0, 0x1D, 0x01, 0x83, 0x5D, 0x98, 0x06, 0x6C, 0x6D, 0x7B, 0x6C, 0x6D, 0x7B, 0x6C, 0x6D, 0x7B, 0x75, 0x77, 0x84, 0xD9, 0xD9, 0xDD, 0x01, 0x06, 0x8C, 0x0C, 0xF3, 0xF3, 0xF4, 0xC3, 0xC3, 0xC9, 0x91, 0x92, 0x9C, 0x6D, 0x6F, 0x7D, 0x01, 0x09, 0x21, 0x01, 0x09, 0x09, 0x01, 0x0F, 0x0F, 0x01, 0x83, 0x3C, 0x84, 0x01, 0x51, 0x53, 0x63, 0x01, 0x24, 0xC8, 0x03, 0x01, 0x1E, 0x1E, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x87, 0x3D, 0x88, 0x02, 0x01, 0x06, 0x81, 0x98, 0x1D, 0x38, 0x3A, 0x4D, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x12, 0x12, 0x01, 0x97, 0x59, 0xC8, 0x2A, 0x01, 0x8C, 0x0F, 0x8C, 0x0F, 0x01, 0x83, 0x72, 0xA3, 0x6E, 0x01, 0x9F, 0x67, 0x81, 0xC4, 0x31, 0x4B, 0x4D, 0x5E, 0x4C, 0x4E, 0x5F, 0x01, 0x83, 0x78, 0x81, 0xC4, 0x31, 0x58, 0x5A, 0x6A, 0xE8, 0xE8, 0xEA, 0x01, 0x09, 0x83, 0x51, 0x01, 0x83, 0x6F, 0x81, 0xC4, 0x31, 0x69, 0x6A, 0x78, 0xF2, 0xF2, 0xF3, 0x01, 0x0C, 0x83, 0x51, 0x01, 0x83, 0x6C, 0x81, 0xC4, 0x31, 0x7C, 0x7D, 0x89, 0x01, 0x06, 0x81, 0xAB, 0x69, 0xFC, 0xFC, 0xFC, 0x53, 0x54, 0x65, 0x01, 0x83, 0x6F, 0x81, 0xC4, 0x31, 0x92, 0x93, 0x9E, 0x01, 0x09, 0xA3, 0x3E, 0x90, 0x91, 0x9C, 0x01, 0x83, 0x6F, 0x81, 0xC4, 0x31, 0x77, 0x78, 0x85, 0x01, 0x0C, 0xA7, 0x66, 0x01, 0x83, 0x72, 0x81, 0xC4, 0x31, 0x42, 0x44, 0x56, 0xF4, 0xF4, 0xF5, 0xFF, 0xFF, 0xFF, 0xDB, 0xDC, 0xDF, 0x3E, 0x40, 0x53, 0x01, 0x83, 0x75, 0x81, 0xC4, 0x31, 0xA3, 0xA4, 0xAC, 0xF1, 0xF1, 0xF3, 0x52, 0x54, 0x64, 0x01, 0x83, 0x78, 0x81, 0xC4, 0x31, 0x4B, 0x4D, 0x5E, 0x01, 0x12, 0x8B, 0x62, 0x01, 0xAC, 0x0E, 0x81, 0xC4, 0x31, 0x01, 0x8C, 0x15, 0x8C, 0x15, 0x3E, 0x40, 0x53, 0x5D, 0x5F, 0x6E, 0x7C, 0x7E, 0x8A, 0x95, 0x96, 0xA0, 0x98, 0x99, 0xA3, 0x98, 0x99, 0xA3, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0F, 0x0F, 0x01, 0x83, 0x48, 0x83, 0x7B, 0x59, 0x5B, 0x6A, 0xCC, 0xCD, 0xD2, 0x01, 0x09, 0xCC, 0x3A, 0x01, 0x83, 0x69, 0x81, 0xA8, 0x2A, 0x01, 0x06, 0xD3, 0x62, 0xA4, 0xA5, 0xAE, 0xFB, 0xFB, 0x01, 0x25, 0xB8, 0x0B, 0x01, 0x83, 0x54, 0x84, 0x01, 0x91, 0x93, 0x9D, 0x01, 0x12, 0x83, 0x57, 0xEC, 0xED, 0xEE, 0xD6, 0xD6, 0xDA, 0xD5, 0xD5, 0xD9, 0xD5, 0xD5, 0xD9, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0C, 0x0C, 0x01, 0x83, 0x42, 0x81, 0x80, 0x1A, 0xF7, 0xF8, 0xF8, 0x01, 0x09, 0x83, 0x78, 0xE6, 0xE6, 0xE9, 0x78, 0x79, 0x86, 0x01, 0x09, 0xC8, 0x15, 0x01, 0x83, 0x63, 0x93, 0x76, 0xB9, 0xBA, 0xC1, 0x01, 0x09, 0x83, 0x7E, 0xC0, 0xC0, 0xC6, 0x3F, 0x41, 0x01, 0x10, 0xD4, 0x36, 0x01, 0x83, 0x60, 0x84, 0x01, 0xE1, 0xE2, 0x01, 0x07, 0xFB, 0x69, 0xF0, 0xF1, 0xF2, 0x47, 0x49, 0x01, 0x10, 0xF4, 0x20, 0x01, 0x83, 0x60, 0x83, 0x7E, 0x3D, 0x3F, 0x51, 0x01, 0x09, 0xD4, 0x0F, 0x94, 0x95, 0x9F, 0x01, 0x83, 0x72, 0x9F, 0x76, 0x01, 0x09, 0xF0, 0x1C, 0xFF, 0xFF, 0xFF, 0x01, 0x83, 0x75, 0x81, 0xD8, 0x30, 0x01, 0x09, 0xFF, 0x67, 0xFF, 0xFF, 0xFF, 0x4B, 0x4D, 0x5E, 0x01, 0x83, 0x72, 0x84, 0x01, 0x45, 0x47, 0x59, 0x01, 0x83, 0x7E, 0x84, 0x01, 0x37, 0x39, 0x4C, 0x01, 0x06, 0x81, 0xE4, 0x33, 0xFF, 0xFF, 0xFF, 0x72, 0x74, 0x81, 0x01, 0x83, 0x75, 0x84, 0x01, 0xB8, 0xB9, 0xBF, 0x01, 0x06, 0x84, 0x01, 0x9A, 0x9B, 0xA5, 0x01, 0x83, 0x78, 0x81, 0xE8, 0x34, 0x01, 0x06, 0x84, 0x01, 0xDC, 0xDC, 0xE0, 0x3C, 0x3E, 0x01, 0x81, 0x17, 0x81, 0xE8, 0x31, 0x6D, 0x6E, 0x79, 0xD9, 0xD9, 0xDB, 0xD9, 0xD9, 0xDB, 0x6D, 0x6E, 0x79, 0x01, 0x2D, 0x39, 0xAE, 0xAE, 0xB4, 0xCE, 0xCF, 0xD2, 0xC4, 0xC4, 0xC8, 0x01, 0x82, 0x1D, 0x84, 0x04, 0xC7, 0xC7, 0xCD, 0x01, 0x81, 0x1F, 0x81, 0x97, 0x73, 0x7C, 0x7D, 0x86, 0x01, 0x08, 0xF9, 0x0D, 0x86, 0x01, 0x2D, 0x39, 0xD9, 0xD9, 0xDB, 0x01, 0x08, 0x91, 0x62, 0x5D, 0x01, 0x82, 0x1A, 0x84, 0x01, 0x43, 0x45, 0x57, 0x01, 0x06, 0xA4, 0x0F, 0xFE, 0xFE, 0xFE, 0x82, 0x83, 0x8F, 0x01, 0x81, 0x4C, 0x84, 0x01, 0xB9, 0xB9, 0xBE, 0x01, 0x36, 0x39, 0x01, 0x81, 0x73, 0x82, 0xD0, 0x5D, 0xC1, 0xC2, 0xC8, 0x01, 0x06, 0x82, 0x2C, 0xCF, 0xCF, 0xD4, 0x5E, 0x5F, 0x01, 0x0D, 0x81, 0xA4, 0x32, 0x01, 0x81, 0x3A, 0x84, 0x01, 0xAE, 0xAE, 0xB4, 0x01, 0x06, 0x39, 0xAE, 0xAE, 0xB4, 0x01, 0x81, 0x79, 0x83, 0x5D, 0x46, 0x48, 0x5A, 0x95, 0x96, 0xA0, 0x95, 0x96, 0xA0, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0F, 0x0F, 0xD4, 0xD5, 0xD9, 0x01, 0x06, 0x82, 0x2F, 0xFE, 0xFE, 0xFE, 0xE7, 0xE7, 0xE9, 0xC8, 0xC9, 0xCE, 0xA9, 0xAA, 0xB2, 0x96, 0x97, 0xA1, 0x01, 0x1E, 0x36, 0x01, 0x83, 0x21, 0x84, 0x01, 0x01, 0x0C, 0x82, 0x94, 0x2A, 0x01, 0x42, 0x81, 0xEC, 0x29, 0x01, 0x75, 0xC0, 0x10, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x39, 0x84, 0x01, 0xE3, 0x01, 0x08, 0x81, 0xB1, 0x54, 0xA3, 0xA3, 0xA9, 0x01, 0x81, 0x79, 0x84, 0x01, 0x50, 0x52, 0x63, 0xD7, 0xD7, 0xDB, 0xD7, 0xD7, 0xDB, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x2D, 0x2D, 0x01, 0x81, 0x19, 0x84, 0x01, 0xC4, 0xC4, 0x01, 0x07, 0x91, 0x56, 0xFF, 0xFF, 0xFF, 0x01, 0x30, 0x9C, 0x40, 0x01, 0x83, 0x00, 0xA1, 0x1E, 0xAE, 0xAE, 0xB4, 0xAE, 0xAE, 0xB4, 0x01, 0x06, 0x06, 0xAE, 0xAE, 0xB4, 0x01, 0x09, 0x83, 0x4B, 0xC4, 0xC4, 0xC8, 0x01, 0x0F, 0x1B, 0x01, 0x0F, 0x0F, 0x01, 0x06, 0x06, 0xB9, 0xB9, 0xBE, 0xEC, 0xEC, 0x01, 0x07, 0x82, 0x92, 0x19, 0xFF, 0xFF, 0xFF, 0xD9, 0xD9, 0x01, 0x64, 0x85, 0x26, 0x01, 0x82, 0x4D, 0x84, 0x01, 0x01, 0x4B, 0x8D, 0x22, 0xF6, 0xF6, 0xF6, 0x01, 0x83, 0x30, 0x87, 0x7F, 0x01, 0x4B, 0x84, 0x01, 0xEC, 0xEC, 0xEE, 0x01, 0x81, 0x1F, 0x83, 0x7E, 0x77, 0x7B, 0x88, 0xC4, 0xC8, 0xD1, 0xDD, 0xE4, 0xEB, 0xCC, 0xD3, 0xDC, 0x98, 0x9E, 0xAA, 0x44, 0x47, 0x01, 0x82, 0x06, 0xC7, 0x14, 0x01, 0x06, 0xAB, 0x79, 0x01, 0x06, 0x06, 0xD9, 0xD9, 0xDB, 0x01, 0x09, 0x93, 0x4C, 0xE3, 0xE3, 0xE5, 0x01, 0x0F, 0x1B, 0x01, 0x0F, 0x0F, 0x01, 0x09, 0x09, 0xAE, 0xAE, 0xB4, 0x89, 0x8A, 0x93, 0x01, 0x81, 0x1F, 0x82, 0xFF, 0x5C, 0xBD, 0xC1, 0xC9, 0xEF, 0xF5, 0xF9, 0xED, 0xF4, 0xF8, 0xEB, 0xF2, 0xF8, 0xE8, 0xF0, 0xF6, 0xE6, 0xEF, 0xF6, 0xD6, 0xDF, 0xE6, 0x64, 0x69, 0x01, 0x82, 0x12, 0x89, 0x30, 0x01, 0x39, 0x98, 0x06, 0x01, 0x81, 0x19, 0x81, 0x52, 0x5A, 0x5C, 0x6C, 0xDC, 0xDF, 0xE4, 0xF2, 0xF7, 0xFA, 0xEF, 0xF5, 0xF9, 0xED, 0xF3, 0xF8, 0xEA, 0xF1, 0xF7, 0xE8, 0xF0, 0xF7, 0xE5, 0xEE, 0xF5, 0xE3, 0xED, 0xF5, 0xDE, 0xE9, 0xF1, 0x84, 0x8A, 0x99, 0x01, 0x83, 0x5D, 0x84, 0x01, 0x7D, 0x7F, 0x8C, 0xF0, 0xF4, 0xF6, 0xF5, 0xF9, 0xFB, 0xF2, 0xF6, 0x01, 0x05, 0x84, 0x01, 0x01, 0x0B, 0x88, 0x02, 0xE3, 0xED, 0xF4, 0xE1, 0xEC, 0xF4, 0xDE, 0xEA, 0xF3, 0xA5, 0xAE, 0xBB, 0x3F, 0x41, 0x54, 0x01, 0x83, 0x51, 0x84, 0x01, 0x3A, 0x3C, 0x4F, 0xA8, 0xA9, 0xB2, 0xF9, 0xFC, 0xFD, 0xF7, 0xFA, 0xFC, 0x01, 0x1E, 0x84, 0x01, 0xDB, 0xE8, 0xF1, 0xC0, 0xCA, 0xD6, 0x4F, 0x53, 0x01, 0x13, 0x81, 0xAB, 0x5D, 0x01, 0x83, 0x39, 0x84, 0x01, 0x49, 0x4B, 0x5C, 0xCF, 0xD0, 0xD4, 0xFB, 0xFC, 0xFD, 0xF9, 0xFB, 0xFD, 0xF6, 0xF9, 0xFC, 0xF4, 0xF8, 0xFB, 0xF2, 0xF7, 0xFA, 0xF0, 0xF5, 0xF9, 0xEC, 0x01, 0x07, 0x8C, 0x03, 0x01, 0x06, 0x84, 0x01, 0xF5, 0xE0, 0xEB, 0xF3, 0xDE, 0xEA, 0xF3, 0xDC, 0xE8, 0xF2, 0xD9, 0xE6, 0xF1, 0xCF, 0xDC, 0xE7, 0x67, 0x6E, 0x7F, 0x01, 0x83, 0x45, 0xC2, 0x78, 0x64, 0x66, 0x74, 0xEB, 0xEB, 0xED, 0xFE, 0xFF, 0xFF, 0xFC, 0xFD, 0xFE, 0x01, 0x27, 0x88, 0x02, 0xDA, 0xE7, 0xF1, 0xD7, 0xE5, 0xF0, 0xD4, 0xE3, 0xEF, 0x87, 0x90, 0xA0, 0x01, 0x83, 0x3F, 0x81, 0x9F, 0x1E, 0x8A, 0x8C, 0x97, 0x01, 0x06, 0x81, 0xC3, 0x18, 0xFF, 0xFF, 0xFF, 0x01, 0x2D, 0x88, 0x02, 0x01, 0x06, 0x84, 0x01, 0xD2, 0xE2, 0xEE, 0xA5, 0xB1, 0xC1, 0x42, 0x44, 0x57, 0x01, 0x6C, 0xAC, 0x3E, 0x83, 0x85, 0x90, 0x9B, 0x9C, 0xA5, 0xAC, 0xAD, 0xB5, 0xAB, 0xAC, 0xB4, 0x9B, 0x9C, 0xA5, 0x83, 0x84, 0x90, 0x50, 0x51, 0x62, 0x01, 0x82, 0x35, 0xE2, 0x7A, 0xB4, 0xB5, 0xBC, 0x01, 0x0C, 0xA1, 0x1B, 0x01, 0x36, 0x84, 0x01, 0xCF, 0xE0, 0xED, 0xBA, 0xC9, 0xD7, 0x53, 0x58, 0x6A, 0x01, 0x62, 0xCA, 0x7D, 0x7C, 0xDD, 0xDD, 0xE0, 0x01, 0x18, 0xA2, 0x58, 0xDA, 0xDB, 0xDE, 0x68, 0x69, 0x01, 0x82, 0x2A, 0x81, 0xE4, 0x2A, 0x50, 0x51, 0x62, 0xD8, 0xD8, 0xDC, 0x01, 0x0C, 0x82, 0x41, 0xFE, 0xFE, 0xFE, 0xFC, 0xFD, 0xFE, 0xFA, 0x01, 0x05, 0x8C, 0x03, 0x01, 0x08, 0x84, 0x01, 0xFA, 0xED, 0xF3, 0xF8, 0xEB, 0xF2, 0x01, 0x09, 0x84, 0x01, 0xF4, 0xE0, 0xEB, 0xF3, 0xDF, 0xEA, 0xF3, 0xDB, 0xE8, 0xF2, 0xD9, 0xE7, 0xF1, 0xD6, 0x01, 0x08, 0x84, 0x01, 0xD0, 0xE0, 0xED, 0xCC, 0xDE, 0xEC, 0xC5, 0xD8, 0xE5, 0x6B, 0x75, 0x01, 0x58, 0x92, 0x06, 0x4A, 0x4C, 0x5D, 0xBA, 0xBB, 0x01, 0x0A, 0xF0, 0x28, 0x01, 0x1B, 0xA6, 0x5F, 0xB6, 0xB6, 0xBD, 0x48, 0x4A, 0x5B, 0x01, 0x82, 0x20, 0x83, 0x7E, 0x6D, 0x6E, 0x7C, 0xF0, 0xF0, 0xF1, 0x01, 0x12, 0x82, 0x3E, 0x01, 0x39, 0x88, 0x02, 0xCD, 0xDE, 0xEC, 0xCB, 0xDD, 0xEC, 0xC8, 0xDC, 0xEA, 0x88, 0x95, 0xA6, 0x01, 0x51, 0x81, 0x2E, 0x66, 0x67, 0x76, 0x01, 0x06, 0x81, 0xC8, 0x56, 0x01, 0x0C, 0x81, 0x2B, 0xF3, 0xF3, 0xF4, 0xCF, 0xD0, 0xD4, 0xD6, 0xD6, 0xDA, 0xF7, 0xF7, 0x01, 0x07, 0xDC, 0x3B, 0x01, 0x09, 0x1B, 0xF2, 0xF2, 0xF3, 0x5B, 0x5C, 0x6C, 0x01, 0x82, 0x1A, 0x83, 0x7E, 0x95, 0x96, 0xA0, 0x01, 0x09, 0xEE, 0x74, 0x01, 0x4B, 0x88, 0x02, 0xCB, 0xDD, 0xEB, 0xC8, 0xDC, 0xEB, 0xC5, 0xDA, 0xE9, 0x7D, 0x89, 0x9A, 0x01, 0x4B, 0x81, 0x2E, 0x41, 0x43, 0x55, 0xE5, 0xE5, 0xE7, 0x01, 0x0C, 0x81, 0x80, 0x1A, 0x83, 0x85, 0x90, 0x4E, 0x50, 0x61, 0x01, 0x0C, 0x82, 0x80, 0x5B, 0x54, 0x55, 0x65, 0x93, 0x94, 0x9E, 0x01, 0x09, 0xE0, 0x45, 0x01, 0x06, 0x8C, 0x0F, 0x01, 0x82, 0x14, 0x82, 0xC0, 0x77, 0x41, 0x43, 0x55, 0xBF, 0xC0, 0xC6, 0x01, 0x18, 0x8A, 0x3D, 0x01, 0x48, 0x84, 0x01, 0xC3, 0xD8, 0xE9, 0x50, 0x56, 0x68, 0x01, 0x48, 0x81, 0x34, 0xB1, 0xB2, 0xB9, 0x01, 0x09, 0x81, 0x22, 0xAF, 0xB0, 0xB8, 0x44, 0x46, 0x01, 0x19, 0x94, 0x6E, 0x4F, 0x51, 0x61, 0xC4, 0xC4, 0xCA, 0x01, 0x09, 0x2D, 0xA1, 0xA2, 0xAB, 0x01, 0x7B, 0x82, 0x6B, 0x89, 0x8A, 0x93, 0xC4, 0xC4, 0xC8, 0x01, 0x09, 0xD7, 0x78, 0xF6, 0xF6, 0xF6, 0x01, 0x06, 0xB0, 0x03, 0x01, 0x7B, 0xB3, 0x7E, 0x56, 0x58, 0x68, 0x01, 0x12, 0x82, 0x83, 0x07, 0x01, 0x0D, 0x84, 0x01, 0x01, 0x06, 0x9C, 0x07, 0xFB, 0x01, 0x0F, 0x9C, 0x07, 0xF9, 0x01, 0x08, 0x84, 0x01, 0xF5, 0x01, 0x12, 0x9C, 0x07, 0xD5, 0xE4, 0x01, 0x08, 0x8C, 0x03, 0xDF, 0xED, 0xCA, 0xDD, 0xEB, 0xC8, 0xDB, 0xEA, 0xC6, 0xDA, 0xEA, 0xC3, 0xD8, 0xE9, 0x76, 0x83, 0x01, 0x0A, 0x81, 0xDB, 0x7E, 0x01, 0x3C, 0x81, 0x34, 0x6F, 0x70, 0x7E, 0x01, 0x09, 0x81, 0x1F, 0xB0, 0xB1, 0xB8, 0x01, 0x24, 0x82, 0x88, 0x69, 0xCF, 0xCF, 0xD4, 0x01, 0x0A, 0x81, 0xF8, 0x71, 0x61, 0x70, 0x01, 0x72, 0x82, 0x68, 0x96, 0x97, 0x9E, 0x01, 0x0C, 0xBF, 0x6F, 0x01, 0x12, 0x82, 0x68, 0x01, 0x33, 0xE0, 0x42, 0x01, 0x45, 0x81, 0xDB, 0x1E, 0x01, 0x12, 0x8E, 0x47, 0x01, 0x54, 0x88, 0x02, 0xBD, 0xD1, 0xE6, 0x8A, 0xA0, 0xD2, 0x6E, 0x7E, 0x01, 0x46, 0xC9, 0x64, 0xBD, 0xBE, 0xC4, 0x01, 0x06, 0x81, 0x1C, 0xE5, 0xE5, 0xE7, 0x01, 0x27, 0x81, 0xEC, 0x05, 0x51, 0x53, 0x63, 0xF5, 0xF5, 0xF6, 0x01, 0x06, 0x36, 0xA8, 0xA9, 0xB1, 0x01, 0x6E, 0x81, 0xD1, 0x7D, 0x5D, 0xCE, 0xCF, 0xD2, 0x01, 0x27, 0xBC, 0x0C, 0x96, 0x97, 0x01, 0x67, 0x81, 0xCD, 0x55, 0x38, 0x3A, 0x4D, 0xA1, 0xA2, 0xAB, 0x01, 0x24, 0x81, 0x13, 0x01, 0x42, 0x88, 0x02, 0xAA, 0xC0, 0xDF, 0x7C, 0x93, 0xCD, 0x7A, 0x8F, 0xCD, 0x55, 0x60, 0x87, 0x01, 0x45, 0xAD, 0x1B, 0x01, 0x09, 0x83, 0x4B, 0x01, 0x0C, 0x82, 0x84, 0x3B, 0x01, 0x21, 0x39, 0x99, 0x9A, 0xA3, 0x01, 0x06, 0x36, 0xE2, 0xE3, 0xE5, 0x01, 0x6C, 0x83, 0x7E, 0x01, 0x09, 0xBC, 0x18, 0x01, 0x06, 0x06, 0xCE, 0xCF, 0xD2, 0xA3, 0xA3, 0xA9, 0x7C, 0x7D, 0x86, 0x7C, 0x7D, 0x86, 0x7C, 0x7D, 0x86, 0xAE, 0xAE, 0xB4, 0x01, 0x0F, 0x21, 0xB9, 0xB9, 0xBE, 0x01, 0x63, 0xF6, 0x61, 0xC8, 0xC9, 0xCE, 0x01, 0x27, 0x85, 0x14, 0x01, 0x3C, 0x84, 0x01, 0xC5, 0xD8, 0xEA, 0x91, 0xA7, 0xD6, 0x7C, 0x93, 0xCE, 0x7B, 0x91, 0xCE, 0x77, 0x8C, 0xCA, 0x3D, 0x41, 0x01, 0x43, 0xA4, 0x18, 0x4E, 0x50, 0x61, 0x01, 0x09, 0x81, 0x1C, 0x01, 0x2D, 0x9B, 0x5A, 0x69, 0x6B, 0x79, 0x01, 0x06, 0x36, 0xFC, 0xFC, 0xFC, 0x01, 0x69, 0xA9, 0x26, 0x01, 0x0C, 0xCF, 0x64, 0xE3, 0xE3, 0xE5, 0x5D, 0x5E, 0x6B, 0x01, 0x18, 0xB0, 0x39, 0x01, 0x0C, 0x8C, 0x21, 0x01, 0x5D, 0x88, 0x08, 0x5E, 0x5F, 0x6F, 0x01, 0x09, 0x81, 0xDA, 0x47, 0x01, 0x25, 0x84, 0x01, 0xFE, 0xFF, 0x01, 0x06, 0x8C, 0x03, 0x01, 0x0C, 0x9C, 0x07, 0xED, 0xF3, 0xF8, 0xEA, 0xF2, 0xF7, 0xE8, 0xF1, 0x01, 0x07, 0xBC, 0x0F, 0x01, 0x05, 0x84, 0x01, 0xF2, 0x01, 0x05, 0x9C, 0x07, 0xF0, 0x01, 0x09, 0x9C, 0x07, 0xB2, 0xC6, 0xE3, 0x82, 0x9A, 0xCF, 0x7C, 0x95, 0xCE, 0x7C, 0x93, 0xCE, 0x7A, 0x90, 0xCE, 0x60, 0x6F, 0x9D, 0x01, 0x45, 0x81, 0x40, 0x61, 0x62, 0x71, 0x01, 0x07, 0x81, 0xFC, 0x3F, 0xEA, 0xEC, 0x01, 0x36, 0x83, 0xC1, 0x29, 0x01, 0x30, 0x84, 0x3A, 0x01, 0x3C, 0x93, 0x73, 0x01, 0x09, 0x72, 0x01, 0x21, 0xEF, 0x6C, 0x01, 0x0C, 0x88, 0x2C, 0xF6, 0xF6, 0xF6, 0x01, 0x57, 0xEC, 0x18, 0x81, 0x82, 0x8E, 0x01, 0x0F, 0x81, 0xCE, 0x59, 0x01, 0x54, 0x88, 0x02, 0xD3, 0xE2, 0xEE, 0x9E, 0xB5, 0xDB, 0x7E, 0x99, 0xD0, 0x7D, 0x96, 0xCF, 0x7C, 0x94, 0xCF, 0x7A, 0x91, 0xCD, 0x79, 0x8F, 0xCD, 0x44, 0x49, 0x01, 0x07, 0x81, 0xF3, 0x7E, 0x01, 0x40, 0x81, 0xD4, 0x26, 0x60, 0x6F, 0x01, 0x07, 0x81, 0xFC, 0x3F, 0xC9, 0xCE, 0x01, 0x30, 0x3C, 0x01, 0x09, 0x86, 0x66, 0x01, 0x66, 0x81, 0xFC, 0x3F, 0x01, 0x0C, 0xC8, 0x15, 0x01, 0x27, 0x8C, 0x30, 0x01, 0x09, 0x81, 0x22, 0x01, 0x51, 0xE0, 0x15, 0x3A, 0x3C, 0x4F, 0xAC, 0xAD, 0xB5, 0x01, 0x33, 0xCD, 0x23, 0x01, 0x30, 0x88, 0x02, 0xD2, 0xE1, 0xEE, 0x96, 0xAF, 0xD8, 0x80, 0x9A, 0xD1, 0x7E, 0x98, 0xD0, 0x7C, 0x95, 0xCE, 0x7B, 0x92, 0xCE, 0x7A, 0x90, 0xCE, 0x6A, 0x7A, 0xB0, 0x01, 0x4B, 0xE8, 0x35, 0x01, 0x07, 0x81, 0xEC, 0x38, 0xE2, 0x01, 0x2E, 0x8F, 0x4B, 0x3E, 0x40, 0x53, 0x01, 0x06, 0xA1, 0x69, 0xF3, 0xF3, 0xF4, 0x01, 0x66, 0xF8, 0x1E, 0x01, 0x09, 0x82, 0x44, 0x01, 0x18, 0x8B, 0x7A, 0x01, 0x15, 0x98, 0x2D, 0x01, 0x09, 0x88, 0x05, 0x01, 0x4E, 0x81, 0xE7, 0x06, 0xD2, 0xD2, 0x01, 0x07, 0x81, 0xEA, 0x3C, 0x01, 0x5D, 0x84, 0x01, 0xD0, 0xDE, 0xED, 0x91, 0xAA, 0xD7, 0x80, 0x9B, 0xD1, 0x7E, 0x99, 0xD0, 0x7E, 0x97, 0xD0, 0x7C, 0x94, 0xCE, 0x7B, 0x92, 0xCE, 0x79, 0x8E, 0xCD, 0x50, 0x59, 0x7D, 0x01, 0x4B, 0x81, 0x4F, 0x01, 0x06, 0x99, 0x3A, 0xFE, 0xFE, 0xFE, 0x01, 0x2D, 0x87, 0x49, 0x62, 0x64, 0x73, 0x01, 0x06, 0x81, 0x52, 0xD8, 0xD8, 0xDC, 0x01, 0x64, 0x81, 0xED, 0x7B, 0xA3, 0xA9, 0x01, 0x09, 0x93, 0x76, 0x01, 0x2F, 0x81, 0x85, 0x7F, 0x01, 0x07, 0x95, 0x63, 0x01, 0x48, 0xC0, 0x49, 0x66, 0x68, 0x76, 0x01, 0x1E, 0x9D, 0x02, 0x01, 0x21, 0x84, 0x04, 0x01, 0x06, 0xAC, 0x0B, 0x01, 0x06, 0x9C, 0x07, 0xF1, 0x01, 0x06, 0x8C, 0x03, 0xF3, 0x01, 0x0D, 0xBC, 0x0F, 0x01, 0x06, 0xAC, 0x0B, 0xCC, 0xDC, 0xEC, 0x8C, 0xA7, 0xD4, 0x81, 0x9D, 0xD1, 0x80, 0x9B, 0xD1, 0x7E, 0x98, 0xCF, 0x7D, 0x95, 0xCF, 0x01, 0x06, 0x8F, 0x7E, 0x78, 0x8B, 0xCB, 0x3B, 0x3F, 0x56, 0x01, 0x4B, 0x82, 0x5C, 0xB2, 0xB2, 0xBA, 0x01, 0x06, 0x81, 0x19, 0x01, 0x2D, 0xB3, 0x66, 0x8A, 0x8C, 0x97, 0x01, 0x06, 0x36, 0x01, 0x66, 0xF0, 0x1C, 0x01, 0x09, 0x93, 0x7F, 0x01, 0x30, 0xE7, 0x61, 0x01, 0x39, 0x39, 0x01, 0x17, 0x83, 0xBB, 0x1A, 0x99, 0x01, 0x39, 0x81, 0xAE, 0x51, 0x01, 0x2D, 0x88, 0x02, 0xC6, 0xD7, 0xEA, 0x87, 0xA5, 0xD3, 0x82, 0x9E, 0xD2, 0x81, 0x9C, 0xD1, 0x7F, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x07, 0x8F, 0x7E, 0x67, 0x77, 0x01, 0x4F, 0xA6, 0x7D, 0x60, 0x01, 0x08, 0x94, 0x08, 0xCF, 0xD0, 0xD4, 0x01, 0x27, 0x97, 0x50, 0x41, 0x43, 0x55, 0x01, 0x06, 0x82, 0xA4, 0x79, 0xFB, 0xFB, 0xFB, 0x01, 0x66, 0x82, 0x88, 0x3F, 0x01, 0x09, 0xA7, 0x6F, 0x01, 0x78, 0xF0, 0x1C, 0x3E, 0x3F, 0x52, 0xB7, 0xB8, 0x01, 0x07, 0x81, 0x8A, 0x4B, 0x01, 0x3F, 0xDD, 0x2A, 0x01, 0x21, 0x88, 0x02, 0xC1, 0xD2, 0xE8, 0x86, 0xA3, 0xD2, 0x83, 0xA0, 0xD2, 0x81, 0x9D, 0xD1, 0x7F, 0x9A, 0xD0, 0x7E, 0x97, 0x01, 0x07, 0x87, 0x7F, 0x7B, 0x91, 0xCE, 0x78, 0x8D, 0xCC, 0x51, 0x5A, 0x01, 0x52, 0x81, 0x8F, 0x4A, 0x01, 0x09, 0x81, 0x8C, 0x26, 0x91, 0x93, 0x01, 0x25, 0x98, 0x5D, 0xB2, 0xB3, 0x01, 0x07, 0x88, 0x35, 0x9D, 0x9E, 0xA7, 0x01, 0x69, 0xDC, 0x26, 0x01, 0x7B, 0x84, 0x01, 0x51, 0x53, 0x63, 0x01, 0x21, 0x81, 0xEA, 0x51, 0x01, 0x48, 0x84, 0x01, 0xCB, 0xDA, 0xEB, 0x87, 0xA5, 0xD3, 0x83, 0xA1, 0xD2, 0x81, 0x9E, 0xD1, 0x01, 0x0C, 0x87, 0x7F, 0x7B, 0x92, 0xCE, 0x79, 0x8F, 0xCD, 0x78, 0x8C, 0xCC, 0x3D, 0x40, 0x01, 0x52, 0x81, 0xAF, 0x46, 0x3E, 0x40, 0x53, 0x01, 0x06, 0x81, 0x61, 0xF9, 0xF9, 0xFA, 0x83, 0x85, 0x90, 0x01, 0x1E, 0x95, 0x7E, 0x99, 0x9A, 0xA4, 0x01, 0x09, 0x82, 0x94, 0x78, 0x01, 0x69, 0xA0, 0x02, 0x01, 0x09, 0x83, 0x48, 0x01, 0x39, 0x84, 0x01, 0x01, 0x39, 0xA0, 0x0E, 0x6F, 0x70, 0x7E, 0xF1, 0xF1, 0xF3, 0x01, 0x48, 0x83, 0x7E, 0x01, 0x06, 0x8C, 0x03, 0x01, 0x06, 0xBC, 0x0F, 0x01, 0x06, 0x9C, 0x07, 0x01, 0x06, 0xAC, 0x0B, 0xEA, 0x01, 0x05, 0x9C, 0x07, 0xD5, 0xE2, 0xF0, 0x8A, 0xA8, 0xD5, 0x84, 0xA2, 0x01, 0x05, 0x87, 0x7F, 0x9E, 0xD1, 0x80, 0x9B, 0xD0, 0x7E, 0x98, 0xCF, 0x7D, 0x96, 0xCF, 0x7B, 0x01, 0x05, 0x87, 0x7F, 0x79, 0x8E, 0xCD, 0x6B, 0x7B, 0x01, 0x10, 0x82, 0xA3, 0x6C, 0x01, 0x48, 0x82, 0x62, 0x47, 0x49, 0x5A, 0xC3, 0xC3, 0xC9, 0x01, 0x06, 0x81, 0x25, 0xCD, 0xCE, 0xD2, 0x57, 0x58, 0x01, 0x13, 0xB4, 0x6A, 0x66, 0x68, 0x76, 0xDE, 0xDE, 0xE1, 0x01, 0x06, 0x24, 0xB4, 0xB5, 0xBC, 0x40, 0x42, 0x01, 0x6A, 0xD9, 0x35, 0x01, 0x09, 0x97, 0x50, 0x01, 0x30, 0x87, 0x49, 0x01, 0x09, 0xAC, 0x38, 0x01, 0x36, 0xB0, 0x1B, 0x99, 0x9A, 0xA4, 0x01, 0x15, 0xBB, 0x56, 0x01, 0x54, 0x88, 0x02, 0xDD, 0xE8, 0xF2, 0x90, 0xAE, 0xD8, 0x85, 0xA4, 0xD3, 0x83, 0xA1, 0xD2, 0x82, 0x9F, 0xD2, 0x80, 0x9C, 0x01, 0x06, 0x8C, 0x00, 0x01, 0x07, 0x97, 0x7D, 0x7A, 0x01, 0x05, 0x87, 0x7F, 0x5B, 0x67, 0x01, 0x4F, 0x82, 0xBB, 0x45, 0x43, 0x45, 0x57, 0x01, 0x09, 0x81, 0x83, 0x68, 0x96, 0x97, 0xA1, 0xE1, 0xE1, 0xE4, 0x01, 0x0C, 0xEA, 0x55, 0xC8, 0xC8, 0xCD, 0xA4, 0xA5, 0xAE, 0xAB, 0xAB, 0xB3, 0xCE, 0xCE, 0xD3, 0x01, 0x0C, 0x86, 0x06, 0xD7, 0xD7, 0xDB, 0x01, 0x24, 0x81, 0x84, 0x6F, 0x01, 0x4B, 0x81, 0xB8, 0x73, 0x4B, 0x4D, 0x5D, 0x01, 0x2D, 0xA0, 0x05, 0x01, 0x0F, 0x36, 0x01, 0x33, 0x82, 0x91, 0x69, 0x41, 0x43, 0x55, 0x01, 0x09, 0x81, 0x8A, 0x33, 0x01, 0x4B, 0x83, 0x7E, 0x01, 0x18, 0x88, 0x02, 0xE4, 0xEE, 0xF5, 0x98, 0xB5, 0xDA, 0x86, 0xA5, 0xD4, 0x83, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x07, 0x97, 0x7D, 0x01, 0x05, 0xA3, 0x7D, 0x01, 0x08, 0x87, 0x7F, 0x78, 0x8C, 0xCC, 0x4C, 0x53, 0x01, 0x4F, 0x82, 0xB7, 0x3E, 0x01, 0x45, 0x82, 0xF0, 0x5C, 0x01, 0x18, 0x18, 0x54, 0x55, 0x01, 0x46, 0xA5, 0x2E, 0x01, 0x0F, 0x97, 0x50, 0x01, 0x2A, 0x8C, 0x06, 0x01, 0x39, 0x90, 0x01, 0x58, 0x5A, 0x6A, 0x01, 0x0C, 0x86, 0x0C, 0x01, 0x60, 0x84, 0x01, 0xEB, 0xF2, 0xF8, 0xA1, 0xBC, 0xDD, 0x86, 0xA6, 0xD4, 0x85, 0xA4, 0xD4, 0x01, 0x06, 0x87, 0x7F, 0x81, 0x01, 0x07, 0x87, 0x7F, 0xCF, 0x01, 0x07, 0x9F, 0x7C, 0x8F, 0xCD, 0x78, 0x8D, 0xCD, 0x77, 0x8A, 0xCB, 0x3D, 0x40, 0x01, 0x4F, 0xD4, 0x18, 0x01, 0x81, 0x2B, 0x84, 0x01, 0x4B, 0x4D, 0x5D, 0x01, 0x06, 0x9F, 0x55, 0x01, 0x27, 0xAB, 0x5B, 0x6D, 0x6E, 0x79, 0x01, 0x06, 0x30, 0x01, 0x30, 0x87, 0x7F, 0x79, 0x7B, 0x87, 0x01, 0x09, 0xB6, 0x21, 0x01, 0x52, 0x84, 0x01, 0xFF, 0xFF, 0xFB, 0xFD, 0xFD, 0xFA, 0xFC, 0xFD, 0xF7, 0x01, 0x0B, 0x9C, 0x07, 0xAD, 0xC4, 0xE1, 0x87, 0xA8, 0xD4, 0x85, 0xA5, 0xD3, 0x84, 0xA3, 0xD3, 0x83, 0xA0, 0xD2, 0x82, 0x9E, 0xD2, 0x01, 0x06, 0x8F, 0x7E, 0x7E, 0x01, 0x0E, 0x87, 0x7F, 0x71, 0x83, 0x01, 0x52, 0x82, 0x97, 0x30, 0x4C, 0x4D, 0x5E, 0x01, 0x5A, 0x81, 0x84, 0x39, 0x01, 0x0C, 0xC8, 0x54, 0x01, 0x4E, 0xA8, 0x10, 0x01, 0x1B, 0xB4, 0x0A, 0x01, 0x0F, 0x83, 0x7E, 0x01, 0x2D, 0xFC, 0x1C, 0x01, 0x06, 0x81, 0xCE, 0x3B, 0x01, 0x5D, 0x81, 0x8A, 0x4E, 0x01, 0x12, 0x88, 0x02, 0xCA, 0xDA, 0xED, 0x88, 0xAA, 0xD5, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x07, 0x8F, 0x7E, 0x81, 0x9D, 0x01, 0x05, 0x97, 0x7D, 0x98, 0xD0, 0x7D, 0x95, 0xCF, 0x01, 0x06, 0xAB, 0x7C, 0x79, 0x8D, 0xCD, 0x78, 0x8B, 0xCC, 0x64, 0x73, 0x01, 0x81, 0x7A, 0x81, 0x89, 0x65, 0x01, 0x15, 0x83, 0x5A, 0x01, 0x15, 0xA3, 0x5C, 0x4B, 0x4D, 0x5D, 0x01, 0x09, 0x8B, 0x7A, 0x01, 0x2D, 0xFC, 0x1C, 0x47, 0x49, 0x5A, 0xCB, 0xCB, 0xD0, 0x01, 0x5D, 0x83, 0x7E, 0x01, 0x12, 0x88, 0x02, 0xE7, 0xEF, 0xF6, 0x8E, 0xAF, 0xD6, 0x01, 0x06, 0x87, 0x7F, 0x85, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x06, 0x8F, 0x7E, 0x7F, 0x01, 0x0C, 0xB3, 0x7B, 0x8E, 0xCD, 0x77, 0x8C, 0xCC, 0x76, 0x89, 0xCB, 0x5A, 0x65, 0x01, 0x81, 0x7A, 0x82, 0xCF, 0x47, 0x4B, 0x4D, 0x5D, 0x01, 0x06, 0xBF, 0x72, 0x96, 0x97, 0x9E, 0x01, 0x0C, 0xBC, 0x15, 0xF6, 0xF6, 0xF6, 0xCE, 0xCF, 0xD2, 0x01, 0x09, 0x81, 0x88, 0x19, 0x01, 0x09, 0xA0, 0x2F, 0x01, 0x24, 0xFC, 0x4C, 0x01, 0x0C, 0xC0, 0x2B, 0x5C, 0x5E, 0x6D, 0x01, 0x0C, 0x82, 0xCA, 0x54, 0x01, 0x69, 0x84, 0x01, 0xA7, 0xC1, 0xE0, 0x87, 0xA9, 0xD4, 0x86, 0xA7, 0xD4, 0x84, 0xA4, 0xD3, 0x84, 0xA2, 0xD3, 0x01, 0x06, 0x97, 0x7D, 0x80, 0x9A, 0xD1, 0x01, 0x06, 0xA3, 0x7D, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x05, 0x84, 0x01, 0x8B, 0xCC, 0x75, 0x88, 0xCB, 0x50, 0x58, 0x80, 0x01, 0x82, 0x02, 0xF0, 0x1C, 0x01, 0x4B, 0x83, 0x0C, 0x01, 0x09, 0x81, 0x8C, 0x38, 0x5C, 0x5E, 0x6D, 0xF0, 0xF1, 0xF2, 0x01, 0x63, 0x83, 0x7E, 0x01, 0x0F, 0xBC, 0x0F, 0xCB, 0xDB, 0xED, 0x88, 0xAA, 0xD5, 0x87, 0xA9, 0xD5, 0x86, 0xA6, 0xD4, 0x84, 0xA3, 0x01, 0x07, 0xA3, 0x7D, 0x80, 0x01, 0x05, 0xA3, 0x7D, 0x01, 0x06, 0x87, 0x7F, 0x7B, 0x91, 0xCE, 0x7A, 0x8F, 0xCE, 0x78, 0x8C, 0xCC, 0x77, 0x89, 0xCC, 0x76, 0x87, 0xCB, 0x4A, 0x4F, 0x72, 0x01, 0x82, 0x53, 0x84, 0x01, 0x47, 0x49, 0x5A, 0x01, 0x09, 0x82, 0xC2, 0x52, 0x01, 0x6C, 0x88, 0x02, 0xEA, 0xF0, 0xF8, 0x8E, 0xAF, 0xD7, 0x88, 0xAA, 0xD5, 0x86, 0xA7, 0xD4, 0x85, 0x01, 0x07, 0x87, 0x7F, 0xD1, 0x01, 0x07, 0x9B, 0x7E, 0x01, 0x0B, 0x87, 0x7F, 0x78, 0x01, 0x05, 0x8F, 0x7E, 0x76, 0x88, 0xCB, 0x74, 0x86, 0xCA, 0x43, 0x48, 0x01, 0x4C, 0x96, 0x55, 0x01, 0x81, 0x2F, 0x81, 0xC5, 0x59, 0x5E, 0x6B, 0x01, 0x24, 0x81, 0x94, 0x1C, 0x01, 0x24, 0x24, 0x01, 0x09, 0x09, 0x01, 0x06, 0xA8, 0x1C, 0xB6, 0xB7, 0x01, 0x07, 0x81, 0xAC, 0x4C, 0x01, 0x6F, 0x88, 0x02, 0xA6, 0xC2, 0xE0, 0x88, 0xAA, 0xD5, 0x87, 0xA8, 0xD4, 0x01, 0x07, 0x93, 0x7F, 0x01, 0x08, 0x97, 0x7D, 0x01, 0x05, 0xAB, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x92, 0x01, 0x08, 0x87, 0x7F, 0x8A, 0xCC, 0x76, 0x87, 0xCB, 0x74, 0x85, 0xCA, 0x01, 0x54, 0xAC, 0x05, 0x01, 0x82, 0x00, 0x81, 0xAE, 0x21, 0x4E, 0x5F, 0x01, 0x51, 0xA7, 0x69, 0x01, 0x24, 0x84, 0x01, 0xCD, 0xDC, 0xED, 0x8A, 0xAD, 0xD6, 0x01, 0x06, 0x84, 0x01, 0x01, 0x05, 0x87, 0x7F, 0xD2, 0x82, 0x01, 0x06, 0x93, 0x7F, 0x9A, 0xD0, 0x7F, 0x98, 0xD0, 0x7C, 0x95, 0xCF, 0x7B, 0x93, 0x01, 0x05, 0x8F, 0x7E, 0x01, 0x0B, 0x87, 0x7F, 0x74, 0x84, 0xCA, 0x38, 0x3B, 0x01, 0x82, 0x51, 0x83, 0xB0, 0x09, 0x92, 0x93, 0x01, 0x07, 0xAC, 0x62, 0x01, 0x6A, 0x84, 0x01, 0xFE, 0xFE, 0xF7, 0xFA, 0xFC, 0x92, 0xB2, 0xD8, 0x88, 0xAB, 0xD5, 0x87, 0xA9, 0xD4, 0x01, 0x0D, 0x8F, 0x7E, 0x9B, 0xD0, 0x01, 0x12, 0xA3, 0x7D, 0x76, 0x8A, 0xCB, 0x76, 0x88, 0xCB, 0x74, 0x85, 0xCA, 0x72, 0x81, 0x01, 0x82, 0x1E, 0x81, 0xBD, 0x72, 0x01, 0x36, 0x36, 0x01, 0x27, 0xF2, 0x0C, 0x01, 0x4E, 0x88, 0x02, 0xC2, 0xD6, 0xEA, 0x89, 0x01, 0x05, 0x87, 0x7F, 0x86, 0xA7, 0x01, 0x07, 0xA3, 0x7D, 0x82, 0x01, 0x07, 0xB3, 0x7B, 0x01, 0x05, 0xAB, 0x7C, 0x95, 0xCF, 0x7C, 0x93, 0xCF, 0x7A, 0x90, 0x01, 0x05, 0xA3, 0x7D, 0x8B, 0xCC, 0x76, 0x89, 0xCC, 0x75, 0x86, 0xCB, 0x74, 0x84, 0xCA, 0x70, 0x7E, 0xC4, 0x01, 0x82, 0x53, 0x84, 0x01, 0xD3, 0xD4, 0xD8, 0x01, 0x6F, 0x84, 0x01, 0xF4, 0xF7, 0xFB, 0x8D, 0xAE, 0xD5, 0x88, 0xAB, 0xD5, 0x88, 0xA9, 0xD5, 0x86, 0xA7, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x07, 0xB3, 0x7B, 0x01, 0x05, 0x97, 0x7D, 0x7D, 0x95, 0xCF, 0x7B, 0x91, 0xCE, 0x79, 0x8F, 0xCD, 0x79, 0x01, 0x05, 0xAB, 0x7C, 0x75, 0x87, 0xCB, 0x74, 0x84, 0xCA, 0x72, 0x82, 0xC9, 0x6E, 0x7B, 0x01, 0x82, 0x54, 0x82, 0xBF, 0x37, 0xD0, 0xD1, 0xD5, 0x01, 0x6F, 0x84, 0x01, 0xBC, 0xD1, 0xE7, 0x01, 0x07, 0x8F, 0x7E, 0x01, 0x09, 0x87, 0x7F, 0x9F, 0xD1, 0x81, 0x9E, 0xD2, 0x7F, 0x9A, 0xD0, 0x01, 0x0B, 0xA3, 0x7D, 0xCE, 0x01, 0x06, 0x9F, 0x7C, 0x01, 0x09, 0x87, 0x7F, 0x72, 0x81, 0xC9, 0x6D, 0x7A, 0x01, 0x13, 0x82, 0xCF, 0x74, 0x01, 0x6F, 0x83, 0xA5, 0x13, 0x7F, 0x80, 0x8C, 0xA7, 0xA8, 0xB1, 0x96, 0x97, 0xA1, 0x67, 0x69, 0x77, 0x3D, 0x3F, 0x51, 0x01, 0x81, 0x43, 0x84, 0x01, 0xBD, 0xBD, 0x01, 0x07, 0xEA, 0x16, 0x01, 0x66, 0x83, 0x7E, 0xF7, 0xFA, 0xFD, 0x8C, 0xAF, 0xD5, 0x89, 0xAC, 0x01, 0x05, 0x8F, 0x7E, 0x01, 0x0A, 0xA3, 0x7D, 0x01, 0x0C, 0xC3, 0x79, 0x01, 0x07, 0x8F, 0x7E, 0x79, 0x8D, 0x01, 0x07, 0xA3, 0x7D, 0x74, 0x85, 0xCA, 0x73, 0x83, 0xCA, 0x71, 0x80, 0xC9, 0x6E, 0x7C, 0xC5, 0x01, 0x5A, 0x82, 0x08, 0x88, 0x89, 0x95, 0xA7, 0xA8, 0xB1, 0x4C, 0x01, 0x1A, 0x81, 0xDC, 0x37, 0x94, 0x95, 0x9F, 0x01, 0x0F, 0x96, 0x2E, 0xF1, 0xF1, 0xF3, 0x01, 0x81, 0x43, 0x82, 0xF0, 0x59, 0x91, 0x92, 0x9C, 0x01, 0x6C, 0x84, 0x01, 0xC5, 0xD7, 0xEA, 0x01, 0x05, 0x87, 0x7F, 0xD4, 0x87, 0xA8, 0xD5, 0x85, 0xA5, 0xD3, 0x01, 0x07, 0xC3, 0x79, 0x01, 0x17, 0xBB, 0x7A, 0x76, 0x89, 0x01, 0x08, 0x8C, 0x00, 0x81, 0xC9, 0x71, 0x7F, 0xC9, 0x6F, 0x7C, 0x01, 0x58, 0x94, 0x05, 0x3A, 0x3C, 0x4E, 0xE7, 0xE7, 0xE9, 0x01, 0x06, 0x82, 0xB8, 0x24, 0x58, 0x5A, 0x01, 0x13, 0x81, 0x89, 0x02, 0x01, 0x0C, 0x82, 0xBC, 0x6A, 0x01, 0x0D, 0x85, 0x50, 0xF8, 0xF8, 0x70, 0x71, 0x01, 0x81, 0x3E, 0x81, 0x95, 0x41, 0x4D, 0x4F, 0x60, 0x01, 0x27, 0x82, 0xBA, 0x41, 0x01, 0x43, 0xC4, 0x08, 0xFD, 0xFE, 0x8E, 0x01, 0x0B, 0x87, 0x7F, 0x01, 0x08, 0xA3, 0x7D, 0x01, 0x08, 0xC3, 0x79, 0x01, 0x06, 0x9B, 0x7E, 0x01, 0x09, 0x87, 0x7F, 0x8A, 0xCB, 0x76, 0x88, 0xCC, 0x01, 0x09, 0x87, 0x7F, 0x70, 0x7E, 0xC9, 0x6F, 0x7B, 0xC7, 0x39, 0x3B, 0x01, 0x55, 0x8A, 0x76, 0x7E, 0x7F, 0x8B, 0x01, 0x09, 0x81, 0xD8, 0x36, 0x01, 0x15, 0x81, 0xEC, 0x5C, 0x01, 0x09, 0x82, 0x23, 0xFE, 0xFE, 0xFE, 0xD7, 0xD8, 0xDB, 0xC1, 0xC1, 0xC7, 0xF3, 0xF3, 0xF4, 0x01, 0x09, 0xE8, 0x50, 0x01, 0x81, 0x40, 0x83, 0xCD, 0x26, 0x01, 0x09, 0xD2, 0x10, 0x01, 0x60, 0x84, 0x01, 0xD3, 0xE1, 0xF0, 0x89, 0xAD, 0xD5, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x14, 0x97, 0x7D, 0x01, 0x08, 0xAB, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x77, 0x8A, 0xCC, 0x75, 0x87, 0xCB, 0x73, 0x01, 0x0B, 0x87, 0x7F, 0x6E, 0x7A, 0xC7, 0x3C, 0x3E, 0x01, 0x55, 0x81, 0x94, 0x25, 0xCA, 0xCA, 0xCF, 0x01, 0x06, 0x81, 0x22, 0x81, 0x82, 0x8E, 0x01, 0x12, 0x1E, 0xC5, 0xC6, 0x01, 0x07, 0x82, 0xF8, 0x79, 0xFA, 0xFA, 0xFA, 0x66, 0x68, 0x76, 0x01, 0x07, 0xF2, 0x0F, 0x46, 0x58, 0x01, 0x09, 0x82, 0xE0, 0x55, 0x7D, 0x7E, 0x8B, 0x01, 0x81, 0x01, 0xB8, 0x20, 0x7C, 0x7D, 0x86, 0x01, 0x2A, 0xE4, 0x2E, 0x01, 0x12, 0xB8, 0x05, 0xED, 0xED, 0xEF, 0x01, 0x63, 0x84, 0x01, 0x9D, 0xB9, 0xD8, 0x89, 0xAC, 0xD6, 0x88, 0xA9, 0x01, 0x05, 0x93, 0x7F, 0xA4, 0xD3, 0x83, 0xA2, 0x01, 0x0D, 0xC3, 0x79, 0x01, 0x13, 0xAB, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x72, 0x80, 0xC9, 0x71, 0x01, 0x05, 0x87, 0x7F, 0x6E, 0x79, 0xC7, 0x42, 0x45, 0x01, 0x55, 0x81, 0xA4, 0x35, 0xE9, 0xEA, 0xEC, 0x01, 0x05, 0xDB, 0x61, 0xFC, 0x01, 0x12, 0x81, 0xE0, 0x35, 0x4B, 0x4D, 0x5E, 0x01, 0x09, 0x8F, 0x7B, 0x01, 0x0C, 0x82, 0xDD, 0x0D, 0x01, 0x0C, 0xF0, 0x55, 0xCB, 0xCB, 0xD0, 0x01, 0x75, 0x83, 0x78, 0x96, 0x97, 0x9E, 0x01, 0x0C, 0xFC, 0x28, 0x01, 0x12, 0xC7, 0x74, 0x01, 0x2A, 0x84, 0x13, 0x62, 0x63, 0x72, 0x01, 0x06, 0x82, 0xE6, 0x70, 0x01, 0x5A, 0x83, 0x7E, 0xEE, 0xF4, 0xF9, 0x8A, 0xAE, 0xD6, 0x88, 0xAB, 0x01, 0x07, 0xAB, 0x7C, 0x01, 0x05, 0x9B, 0x7E, 0xD3, 0x01, 0x09, 0xBB, 0x7A, 0x01, 0x07, 0x93, 0x7F, 0x01, 0x07, 0x87, 0x7F, 0xCD, 0x77, 0x8A, 0xCC, 0x75, 0x86, 0xCA, 0x74, 0x85, 0xCB, 0x72, 0x82, 0xCA, 0x71, 0x7F, 0xC9, 0x70, 0x7D, 0xC8, 0x6E, 0x7A, 0xC7, 0x6D, 0x78, 0xC7, 0x47, 0x4C, 0x01, 0x52, 0xB4, 0x0D, 0x01, 0x09, 0x83, 0xE0, 0x78, 0xE0, 0xE0, 0xE3, 0x01, 0x1B, 0x82, 0x8C, 0x5B, 0xF4, 0xF4, 0xF5, 0x01, 0x12, 0xD4, 0x03, 0xE4, 0xE4, 0xE7, 0x01, 0x18, 0x82, 0xF1, 0x15, 0x01, 0x60, 0x87, 0x73, 0x01, 0x0F, 0xFC, 0x04, 0x01, 0x12, 0x84, 0x01, 0x01, 0x06, 0xF4, 0x4A, 0x01, 0x2A, 0xFC, 0x1C, 0x01, 0x60, 0xBC, 0x0F, 0xBD, 0xD1, 0xE7, 0x89, 0xAC, 0xD5, 0x01, 0x05, 0xA3, 0x7D, 0xD3, 0x01, 0x0C, 0xC3, 0x79, 0x80, 0x01, 0x06, 0xA7, 0x7B, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x06, 0x9B, 0x7E, 0x88, 0xCB, 0x75, 0x86, 0xCB, 0x73, 0x83, 0xCA, 0x72, 0x81, 0xC9, 0x70, 0x7E, 0xC8, 0x6F, 0x7B, 0xC8, 0x6D, 0x79, 0xC7, 0x6C, 0x76, 0xC6, 0x4E, 0x53, 0x01, 0x52, 0xE0, 0x12, 0x59, 0x5B, 0x6A, 0x01, 0x09, 0x82, 0x88, 0x3C, 0x01, 0x12, 0x1E, 0x01, 0x09, 0x82, 0xD8, 0x3E, 0xAF, 0xB0, 0x01, 0x13, 0x81, 0x88, 0x3A, 0xC9, 0x01, 0x05, 0x8C, 0x3C, 0xFD, 0xFD, 0xFD, 0x01, 0x6C, 0x90, 0x07, 0x01, 0x09, 0xD8, 0x1F, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0xCC, 0x3D, 0x01, 0x24, 0xF8, 0x48, 0x01, 0x0C, 0xF2, 0x27, 0x01, 0x5A, 0xC4, 0x11, 0x91, 0xB0, 0xD5, 0x89, 0x01, 0x08, 0x87, 0x7F, 0x85, 0x01, 0x14, 0xBB, 0x7A, 0x7A, 0x91, 0xCD, 0x01, 0x06, 0xD7, 0x78, 0x76, 0x89, 0xCB, 0x76, 0x01, 0x05, 0x97, 0x7D, 0x73, 0x82, 0xCA, 0x71, 0x7F, 0xC8, 0x70, 0x7D, 0x01, 0x05, 0x84, 0x01, 0x78, 0xC7, 0x6B, 0x75, 0xC5, 0x54, 0x5A, 0x01, 0x52, 0x81, 0xE3, 0x53, 0x01, 0x09, 0x8B, 0x4A, 0xAB, 0xAC, 0x01, 0x10, 0x8A, 0x43, 0x48, 0x4A, 0x5B, 0x01, 0x09, 0x8C, 0x00, 0x01, 0x15, 0x82, 0xD9, 0x12, 0x01, 0x09, 0xD6, 0x35, 0x4A, 0x4C, 0x01, 0x67, 0x81, 0xE7, 0x15, 0x01, 0x0C, 0xFC, 0x22, 0xEC, 0xEC, 0xEE, 0x96, 0x97, 0x9E, 0x4B, 0x4D, 0x5D, 0x01, 0x06, 0xC4, 0x05, 0x01, 0x0F, 0x88, 0x02, 0x01, 0x09, 0xC8, 0x39, 0x01, 0x2D, 0xE0, 0x12, 0x01, 0x57, 0xCC, 0x13, 0xEA, 0xF1, 0xF8, 0x01, 0x08, 0x87, 0x7F, 0xD4, 0x85, 0x01, 0x05, 0xD7, 0x78, 0x01, 0x07, 0xCB, 0x78, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x05, 0x9B, 0x7E, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x06, 0xA3, 0x7D, 0x73, 0x83, 0xC9, 0x72, 0x81, 0xCA, 0x71, 0x7E, 0xC9, 0x70, 0x7C, 0x01, 0x07, 0x87, 0x7F, 0x6B, 0x74, 0xC6, 0x5C, 0x61, 0xA4, 0x01, 0x54, 0x81, 0xA0, 0x1C, 0x01, 0x07, 0x89, 0x24, 0xBD, 0x01, 0x10, 0xAC, 0x6B, 0x01, 0x09, 0x82, 0xE4, 0x71, 0xF4, 0xF4, 0xF5, 0x01, 0x15, 0x81, 0x98, 0x0E, 0x01, 0x06, 0x8C, 0x03, 0xFF, 0xFF, 0xFF, 0x3E, 0x3F, 0x52, 0x01, 0x66, 0xC8, 0x15, 0x01, 0x15, 0x87, 0x58, 0x01, 0x15, 0x84, 0x01, 0x01, 0x0C, 0xD0, 0x41, 0x01, 0x30, 0x81, 0x80, 0x20, 0x01, 0x51, 0xD4, 0x15, 0xC5, 0xD6, 0xEA, 0x01, 0x0E, 0x8F, 0x7E, 0x01, 0x07, 0x97, 0x7D, 0x01, 0x0C, 0x8F, 0x7E, 0x01, 0x0A, 0xBB, 0x7A, 0x88, 0x01, 0x0D, 0x87, 0x7F, 0x01, 0x06, 0x8F, 0x7E, 0x6B, 0x75, 0xC6, 0x6A, 0x73, 0xC5, 0x65, 0x6C, 0xBB, 0x01, 0x54, 0x82, 0x59, 0x01, 0x06, 0x82, 0xDC, 0x2A, 0xE7, 0xE7, 0xE9, 0x01, 0x0F, 0xE7, 0x67, 0x01, 0x09, 0x81, 0xA8, 0x30, 0xB2, 0xB3, 0xBA, 0x01, 0x15, 0x82, 0xE9, 0x2E, 0x01, 0x06, 0x90, 0x3D, 0xF4, 0xF4, 0xF5, 0x01, 0x6F, 0x81, 0x88, 0x1F, 0x01, 0x0F, 0x8F, 0x5A, 0x01, 0x18, 0x84, 0x01, 0x01, 0x3C, 0xDC, 0x17, 0x57, 0x59, 0x69, 0x01, 0x4B, 0xDC, 0x17, 0x98, 0xB4, 0xD7, 0x01, 0x06, 0xAB, 0x7C, 0x01, 0x06, 0xDF, 0x77, 0x01, 0x07, 0xBB, 0x7A, 0x01, 0x08, 0xC3, 0x79, 0x01, 0x07, 0xA3, 0x7D, 0x01, 0x08, 0x97, 0x7D, 0x75, 0x86, 0xCA, 0x01, 0x05, 0x9B, 0x7E, 0x01, 0x05, 0x93, 0x7F, 0x01, 0x05, 0x87, 0x7F, 0x6D, 0x77, 0xC6, 0x6B, 0x74, 0xC6, 0x6A, 0x72, 0xC5, 0x68, 0x6F, 0xC4, 0x3D, 0x3F, 0x01, 0x52, 0x81, 0xCC, 0x51, 0x01, 0x09, 0x9B, 0x69, 0x7F, 0x80, 0x8C, 0x01, 0x12, 0x82, 0xE8, 0x54, 0xFF, 0xFF, 0xFF, 0x69, 0x6B, 0x01, 0x13, 0xD2, 0x58, 0x67, 0x69, 0x77, 0x01, 0x06, 0x1E, 0xCC, 0xCD, 0x01, 0x2E, 0xFB, 0x30, 0x01, 0x3F, 0xE4, 0x19, 0x01, 0x12, 0x81, 0xD8, 0x00, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0x88, 0x35, 0x01, 0x7B, 0xE4, 0x19, 0xF6, 0xF9, 0xFC, 0x01, 0x08, 0xBB, 0x7A, 0x01, 0x05, 0xDB, 0x76, 0xA1, 0xD2, 0x82, 0x01, 0x07, 0xBB, 0x7A, 0x01, 0x07, 0x84, 0x01, 0x7A, 0x01, 0x05, 0xB3, 0x7B, 0x78, 0x8D, 0x01, 0x07, 0x9F, 0x7C, 0x01, 0x05, 0x97, 0x7D, 0xC9, 0x71, 0x80, 0x01, 0x05, 0x97, 0x7D, 0x7B, 0xC7, 0x6D, 0x78, 0xC7, 0x6C, 0x01, 0x05, 0x87, 0x7F, 0x6A, 0x71, 0xC5, 0x68, 0x6E, 0xC4, 0x46, 0x49, 0x01, 0x52, 0x83, 0xA7, 0x72, 0x6E, 0x70, 0x7D, 0x01, 0x07, 0xA5, 0x2B, 0xFB, 0xFB, 0xA5, 0xA6, 0xAE, 0x80, 0x81, 0x8D, 0xB7, 0xB8, 0xBF, 0x01, 0x09, 0xFA, 0x05, 0xCF, 0xD0, 0xD4, 0x01, 0x18, 0x82, 0xED, 0x2C, 0x01, 0x07, 0x85, 0x5F, 0x01, 0x65, 0x82, 0xB0, 0x4C, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x12, 0x81, 0xD0, 0x07, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x0C, 0x88, 0x38, 0x01, 0x38, 0xEC, 0x1B, 0xA3, 0x01, 0x3F, 0xC4, 0x32, 0xDA, 0xE5, 0xF2, 0x01, 0x05, 0xC3, 0x79, 0xD5, 0x85, 0xA4, 0x01, 0x09, 0xA3, 0x7D, 0xD2, 0x01, 0x06, 0xA7, 0x7B, 0x01, 0x05, 0x8F, 0x7E, 0x01, 0x07, 0xBB, 0x7A, 0x01, 0x05, 0x8F, 0x7E, 0xCB, 0x01, 0x0E, 0xA3, 0x7D, 0xC7, 0x6E, 0x7A, 0xC7, 0x6C, 0x77, 0xC6, 0x6C, 0x75, 0x01, 0x07, 0x87, 0x7F, 0x67, 0x6D, 0xC4, 0x51, 0x53, 0x8D, 0x01, 0x55, 0x84, 0xBD, 0x12, 0xCD, 0x01, 0x16, 0x81, 0x9A, 0x79, 0xFC, 0xFC, 0xFC, 0x5D, 0x5F, 0x6E, 0x01, 0x15, 0x84, 0xCD, 0x49, 0x01, 0x06, 0x8C, 0x39, 0xFD, 0xFD, 0xFD, 0x54, 0x56, 0x66, 0x01, 0x64, 0x82, 0xA1, 0x6D, 0xB9, 0xBE, 0x01, 0x18, 0x81, 0x87, 0x69, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x1B, 0x84, 0x3A, 0x01, 0x66, 0xF4, 0x1D, 0xBD, 0xD1, 0xE8, 0x88, 0x01, 0x05, 0xD3, 0x77, 0x01, 0x11, 0xEF, 0x75, 0x01, 0x07, 0xC3, 0x79, 0x7A, 0x90, 0xCE, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x07, 0xC3, 0x79, 0x82, 0xC9, 0x72, 0x80, 0x01, 0x06, 0x9B, 0x7E, 0x01, 0x05, 0x87, 0x7F, 0x76, 0xC6, 0x6B, 0x73, 0xC5, 0x69, 0x01, 0x05, 0x87, 0x7F, 0x66, 0x6B, 0xC3, 0x5D, 0x61, 0xAD, 0x01, 0x57, 0x83, 0xE9, 0x00, 0xC2, 0xC3, 0x01, 0x10, 0x89, 0x6F, 0xF2, 0xF2, 0xF3, 0x6E, 0x70, 0x01, 0x16, 0x81, 0x89, 0x0B, 0x01, 0x09, 0xA8, 0x3D, 0xBD, 0xBE, 0x01, 0x67, 0xC1, 0x26, 0x01, 0x06, 0x83, 0x66, 0x01, 0x15, 0x81, 0xE4, 0x00, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x09, 0xD4, 0x4E, 0x01, 0x78, 0xFC, 0x1F, 0x9C, 0xB8, 0xD9, 0x01, 0x0D, 0xC3, 0x79, 0x01, 0x06, 0x97, 0x7D, 0x01, 0x05, 0xF7, 0x74, 0x7C, 0x94, 0xCF, 0x01, 0x06, 0x97, 0x7D, 0x01, 0x07, 0xB3, 0x7B, 0x01, 0x06, 0x9F, 0x7C, 0x82, 0xCA, 0x70, 0x7E, 0xC8, 0x01, 0x05, 0xAB, 0x7C, 0xC8, 0x6C, 0x77, 0xC6, 0x6B, 0x74, 0x01, 0x05, 0x83, 0x7E, 0x01, 0x05, 0x87, 0x7F, 0x66, 0x6B, 0xC3, 0x64, 0x67, 0xC2, 0x3C, 0x3E, 0x01, 0x55, 0xD0, 0x1A, 0x39, 0x3B, 0x4E, 0x71, 0x73, 0x80, 0xA0, 0xA1, 0xAA, 0xCC, 0xCC, 0xD1, 0xBA, 0xBB, 0xC1, 0x91, 0x92, 0x9C, 0x50, 0x52, 0x63, 0x01, 0x18, 0x81, 0xC5, 0x7A, 0x01, 0x06, 0x93, 0x7F, 0xF6, 0xF6, 0xF7, 0x01, 0x69, 0x82, 0xF4, 0x5D, 0x01, 0x7E, 0x84, 0x01, 0x01, 0x39, 0x81, 0x84, 0x21, 0xFD, 0xFE, 0xFF, 0x89, 0x01, 0x08, 0xD7, 0x78, 0x01, 0x09, 0xEF, 0x75, 0x01, 0x05, 0xDF, 0x77, 0x01, 0x07, 0xFF, 0x73, 0x7A, 0x90, 0x01, 0x05, 0xAF, 0x7A, 0x8B, 0xCC, 0x75, 0x87, 0x01, 0x11, 0xA3, 0x7D, 0x78, 0xC6, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x06, 0x8F, 0x7E, 0x66, 0x6C, 0xC3, 0x65, 0x69, 0xC2, 0x64, 0x67, 0xC2, 0x47, 0x4A, 0x01, 0x81, 0x02, 0x81, 0xDC, 0x55, 0x5B, 0x5D, 0x6C, 0xC0, 0xC0, 0xC6, 0x7E, 0x7F, 0x01, 0x6A, 0xB0, 0x06, 0x01, 0x06, 0xAB, 0x76, 0x01, 0x15, 0xF8, 0x1B, 0x01, 0x27, 0x8C, 0x03, 0x01, 0x45, 0x81, 0x8C, 0x23, 0x8D, 0x8E, 0x01, 0x2E, 0x81, 0x8C, 0x23, 0xEA, 0xF0, 0xF8, 0x01, 0x0D, 0xE7, 0x76, 0x01, 0x06, 0x93, 0x7F, 0x01, 0x0E, 0x81, 0x9B, 0x71, 0x01, 0x06, 0xDF, 0x77, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x06, 0xB3, 0x7B, 0x6F, 0x7A, 0x01, 0x06, 0xA3, 0x7D, 0xC6, 0x6A, 0x72, 0xC5, 0x69, 0x70, 0xC4, 0x67, 0x6D, 0xC3, 0x66, 0x6B, 0xC3, 0x64, 0x68, 0xC2, 0x64, 0x66, 0xC2, 0x54, 0x56, 0x01, 0x46, 0x81, 0xB0, 0x23, 0x01, 0x81, 0x31, 0x81, 0xF0, 0x4B, 0x01, 0x18, 0x82, 0x8C, 0x0A, 0x01, 0x27, 0x94, 0x05, 0x01, 0x75, 0x81, 0x94, 0x25, 0xD6, 0xE2, 0xF1, 0x01, 0x07, 0x87, 0x7F, 0xA2, 0xD2, 0x01, 0x07, 0xDF, 0x77, 0x9A, 0xD1, 0x7D, 0x01, 0x08, 0xB3, 0x7B, 0x01, 0x0B, 0xBB, 0x7A, 0x01, 0x0A, 0xC3, 0x79, 0x01, 0x06, 0xBB, 0x7A, 0x6E, 0x01, 0x08, 0xA3, 0x7D, 0x01, 0x06, 0x87, 0x7F, 0x67, 0x6C, 0xC4, 0x65, 0x69, 0xC3, 0x63, 0x66, 0xC1, 0x63, 0x64, 0xC1, 0x60, 0x60, 0xBD, 0x3A, 0x3B, 0x01, 0x81, 0x71, 0x81, 0xDC, 0x4F, 0x01, 0x09, 0xA3, 0x56, 0x01, 0x12, 0xA7, 0x57, 0x01, 0x24, 0x9C, 0x07, 0x01, 0x4E, 0x81, 0xFD, 0x64, 0x4B, 0x4D, 0x5E, 0x01, 0x09, 0xAE, 0x25, 0x01, 0x1E, 0x84, 0x01, 0xC2, 0xD3, 0xEA, 0x01, 0x09, 0x8F, 0x7E, 0x01, 0x09, 0xDF, 0x77, 0x01, 0x0A, 0xCB, 0x78, 0x8F, 0xCD, 0x78, 0x8C, 0xCD, 0x01, 0x07, 0xC3, 0x79, 0x01, 0x06, 0x9B, 0x7E, 0x01, 0x11, 0x97, 0x7D, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x05, 0x8F, 0x7E, 0x68, 0xC2, 0x63, 0x66, 0xC2, 0x62, 0x63, 0xC1, 0x60, 0x60, 0xC0, 0x47, 0x48, 0x01, 0x81, 0x74, 0x81, 0xE8, 0x5B, 0x01, 0x06, 0x86, 0x78, 0xEC, 0xEC, 0xEE, 0x01, 0x0F, 0x88, 0x05, 0x01, 0x24, 0xA4, 0x09, 0x01, 0x30, 0x81, 0x9C, 0x5D, 0x01, 0x48, 0x81, 0xA4, 0x29, 0xAF, 0xC4, 0xE3, 0x01, 0x0A, 0xBB, 0x7A, 0x01, 0x0B, 0x81, 0x93, 0x72, 0x01, 0x0A, 0x97, 0x7D, 0x01, 0x05, 0xAB, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0xC9, 0x72, 0x81, 0x01, 0x0A, 0xBB, 0x7A, 0x01, 0x05, 0x93, 0x7F, 0xC6, 0x69, 0x71, 0xC4, 0x01, 0x08, 0x87, 0x7F, 0xC2, 0x64, 0x67, 0xC2, 0x62, 0x64, 0xC1, 0x61, 0x62, 0xC0, 0x60, 0x60, 0xC0, 0x55, 0x54, 0x01, 0x52, 0xAC, 0x14, 0x01, 0x81, 0x23, 0x83, 0x8E, 0x26, 0x01, 0x08, 0x81, 0xA0, 0x2B, 0x01, 0x0F, 0xB3, 0x60, 0x01, 0x18, 0x84, 0x01, 0x01, 0x0C, 0xEC, 0x4E, 0x01, 0x57, 0x81, 0xE0, 0x6E, 0x01, 0x21, 0x81, 0xAC, 0x2B, 0xA0, 0xB8, 0xDC, 0x01, 0x0D, 0xDF, 0x77, 0x01, 0x17, 0x87, 0x7F, 0x73, 0x01, 0x15, 0xAB, 0x7C, 0x72, 0xC5, 0x69, 0x70, 0xC5, 0x67, 0x6D, 0xC4, 0x67, 0x01, 0x09, 0x87, 0x7F, 0x64, 0xC1, 0x60, 0x60, 0xC0, 0x5F, 0x5E, 0xBF, 0x5D, 0x5B, 0xBE, 0x3D, 0x3E, 0x01, 0x07, 0x83, 0xAC, 0x2C, 0x01, 0x81, 0x6D, 0x84, 0x04, 0x01, 0x09, 0xBC, 0x06, 0xC4, 0xC4, 0xC8, 0x01, 0x09, 0x88, 0x08, 0x01, 0x15, 0x84, 0x01, 0x96, 0x97, 0x9E, 0x01, 0x09, 0x8B, 0x7D, 0x01, 0x51, 0x87, 0x7F, 0x01, 0x2A, 0x81, 0xB4, 0x2D, 0x90, 0xAC, 0xD5, 0x01, 0x0A, 0xF7, 0x74, 0x01, 0x0A, 0xDF, 0x77, 0x01, 0x10, 0xBB, 0x7A, 0x01, 0x07, 0x93, 0x7F, 0x01, 0x08, 0x87, 0x7F, 0x6D, 0x77, 0x01, 0x05, 0xA7, 0x7B, 0x01, 0x06, 0xA3, 0x7D, 0x6C, 0xC3, 0x66, 0x6A, 0xC3, 0x64, 0x67, 0xC2, 0x63, 0x65, 0xC2, 0x61, 0x62, 0xC0, 0x60, 0x5F, 0xC0, 0x5F, 0x5D, 0xBF, 0x5E, 0x5B, 0xBF, 0x4D, 0x4C, 0x91, 0x01, 0x81, 0x7C, 0x81, 0x80, 0x1D, 0x01, 0x1B, 0xB8, 0x0E, 0x89, 0x8A, 0x93, 0x01, 0x0C, 0xFC, 0x25, 0xE3, 0xE3, 0xE5, 0x01, 0x60, 0x82, 0xA0, 0x42, 0x01, 0x1B, 0x81, 0xBC, 0x2F, 0x01, 0x08, 0xEF, 0x75, 0x01, 0x07, 0xBB, 0x7A, 0x01, 0x0E, 0xC3, 0x79, 0x01, 0x0B, 0xCB, 0x78, 0x01, 0x05, 0x8F, 0x7E, 0x70, 0x7D, 0xC9, 0x6F, 0x7B, 0xC7, 0x6D, 0x01, 0x06, 0x8F, 0x7E, 0x73, 0xC5, 0x69, 0x70, 0xC4, 0x01, 0x06, 0xA3, 0x7D, 0x65, 0x68, 0xC2, 0x63, 0x66, 0xC1, 0x62, 0x63, 0xC1, 0x61, 0x61, 0xC0, 0x5F, 0x5E, 0xC0, 0x5D, 0x5B, 0xBE, 0x5C, 0x59, 0xBE, 0x59, 0x56, 0xB9, 0x3A, 0x3B, 0x01, 0x61, 0x81, 0xB3, 0x23, 0x43, 0x45, 0x57, 0x55, 0x57, 0x67, 0x52, 0x54, 0x64, 0x01, 0x6C, 0x81, 0x98, 0x11, 0x01, 0x2A, 0x84, 0x04, 0x01, 0x0F, 0x82, 0x80, 0x28, 0xD9, 0xD9, 0xDB, 0x01, 0x0F, 0x1B, 0x01, 0x69, 0x82, 0x80, 0x3D, 0x38, 0x3A, 0x4D, 0xA0, 0xA1, 0xAA, 0x01, 0x10, 0xD6, 0x35, 0xF9, 0xFC, 0x84, 0x01, 0x07, 0x97, 0x7D, 0x01, 0x08, 0xAB, 0x7C, 0x01, 0x06, 0xEF, 0x75, 0x01, 0x0A, 0xDF, 0x77, 0x01, 0x0E, 0x9F, 0x7C, 0x7C, 0xC8, 0x01, 0x0C, 0x97, 0x7D, 0x69, 0x01, 0x08, 0x87, 0x7F, 0x65, 0x68, 0xC2, 0x63, 0x65, 0x01, 0x07, 0x8F, 0x7E, 0x5F, 0x5E, 0xC0, 0x5D, 0x5A, 0xBE, 0x5C, 0x58, 0xBE, 0x5A, 0x55, 0xBD, 0x46, 0x44, 0x01, 0x19, 0x83, 0x98, 0x36, 0x01, 0x3F, 0x81, 0x4C, 0x7F, 0x81, 0x8D, 0xBF, 0xC0, 0xC6, 0x01, 0x0F, 0x81, 0xC9, 0x7E, 0xED, 0xED, 0xEF, 0xB6, 0xB6, 0xBD, 0x01, 0x81, 0x04, 0x82, 0xB4, 0x71, 0x5D, 0x5E, 0x6B, 0x01, 0x0F, 0x81, 0x84, 0x09, 0x01, 0x15, 0x86, 0x7E, 0xCE, 0xCF, 0xD2, 0x01, 0x6F, 0x82, 0xA8, 0x3E, 0x01, 0x0F, 0x81, 0xCC, 0x33, 0xF1, 0xF4, 0xFA, 0x01, 0x0C, 0xE7, 0x76, 0x01, 0x0F, 0x81, 0xA3, 0x70, 0x01, 0x08, 0xB3, 0x7B, 0x01, 0x08, 0x9B, 0x7E, 0x7D, 0x01, 0x0A, 0xAB, 0x7C, 0x01, 0x0D, 0x87, 0x7F, 0x01, 0x05, 0x9B, 0x7E, 0x62, 0x64, 0xC1, 0x61, 0x61, 0xC1, 0x5F, 0x5E, 0xBF, 0x5E, 0x5C, 0xBE, 0x5D, 0x5A, 0xBE, 0x5C, 0x57, 0xBE, 0x5A, 0x54, 0xBC, 0x4B, 0x48, 0x01, 0x52, 0xB0, 0x18, 0x54, 0x56, 0x66, 0x01, 0x06, 0x83, 0xD4, 0x51, 0x01, 0x1B, 0x82, 0x59, 0xBF, 0xC0, 0xC6, 0x01, 0x81, 0x04, 0x83, 0xB4, 0x5E, 0x96, 0x97, 0x9E, 0x01, 0x12, 0xCC, 0x19, 0x01, 0x09, 0x83, 0x7B, 0x01, 0x78, 0x81, 0xF4, 0x64, 0x01, 0x0C, 0x81, 0xD4, 0x35, 0xED, 0xF1, 0xF9, 0x01, 0x06, 0xFB, 0x75, 0x01, 0x0D, 0x87, 0x7F, 0x01, 0x0A, 0xC3, 0x79, 0x01, 0x0C, 0x8F, 0x7E, 0xC8, 0x01, 0x08, 0xBB, 0x7A, 0x01, 0x05, 0xB7, 0x7C, 0x01, 0x06, 0xAB, 0x7C, 0x01, 0x0F, 0x8F, 0x7E, 0x60, 0x01, 0x07, 0x8F, 0x7E, 0x5C, 0x58, 0xBD, 0x5B, 0x56, 0xBD, 0x5A, 0x53, 0xBD, 0x47, 0x45, 0x82, 0x01, 0x4E, 0x87, 0x79, 0x91, 0x93, 0x9D, 0x01, 0x27, 0x81, 0xC1, 0x7F, 0xF1, 0xF1, 0xF3, 0x01, 0x15, 0xD8, 0x43, 0x01, 0x78, 0x81, 0x8C, 0x3B, 0x01, 0x06, 0xFF, 0x70, 0x01, 0x06, 0x81, 0xCC, 0x3C, 0x01, 0x81, 0x01, 0x82, 0xB0, 0x34, 0x01, 0x09, 0x81, 0xDC, 0x37, 0xE8, 0xEE, 0xF7, 0x01, 0x07, 0xCB, 0x78, 0x01, 0x07, 0x81, 0xA3, 0x70, 0x01, 0x08, 0x87, 0x7F, 0x8D, 0xCD, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x07, 0xBB, 0x7A, 0x7E, 0xC9, 0x6E, 0x7A, 0xC7, 0x6E, 0x01, 0x08, 0xBB, 0x7A, 0x01, 0x06, 0xB3, 0x7B, 0x67, 0x6C, 0x01, 0x0B, 0x87, 0x7F, 0x62, 0xC1, 0x60, 0x5F, 0xC0, 0x5E, 0x5C, 0xBE, 0x5D, 0x59, 0x01, 0x05, 0x87, 0x7F, 0x55, 0xBD, 0x58, 0x52, 0xBC, 0x3D, 0x3D, 0x60, 0x01, 0x4E, 0x81, 0xE1, 0x69, 0x01, 0x0C, 0x83, 0x63, 0xD4, 0xD5, 0xD9, 0x9F, 0xA0, 0xA9, 0x7B, 0x7C, 0x89, 0x57, 0x59, 0x69, 0x5B, 0x5C, 0x6C, 0x7E, 0x7F, 0x8B, 0xA1, 0xA2, 0xAB, 0x01, 0x09, 0x84, 0x9D, 0x25, 0x01, 0x06, 0x06, 0x01, 0x6C, 0xAC, 0x0B, 0x01, 0x81, 0x34, 0x81, 0xE4, 0x39, 0xE2, 0xE8, 0xF3, 0x01, 0x0A, 0x81, 0xBB, 0x6D, 0x96, 0x01, 0x0A, 0x87, 0x7F, 0x01, 0x07, 0xC3, 0x79, 0x01, 0x07, 0x93, 0x7F, 0x01, 0x09, 0xB3, 0x7B, 0xC7, 0x6D, 0x77, 0xC7, 0x01, 0x09, 0xC3, 0x79, 0x67, 0x6D, 0xC4, 0x65, 0x6A, 0x01, 0x05, 0x9B, 0x7E, 0x65, 0x01, 0x07, 0xA3, 0x7D, 0x01, 0x06, 0x93, 0x7F, 0x5D, 0x59, 0xBE, 0x5A, 0x55, 0xBD, 0x59, 0x53, 0xBC, 0x4B, 0x47, 0x01, 0x4C, 0x8C, 0x00, 0x54, 0x56, 0x66, 0x01, 0x09, 0x87, 0x7C, 0xF2, 0xF2, 0xF3, 0x86, 0x87, 0x92, 0x01, 0x18, 0xB4, 0x31, 0x8E, 0x8F, 0x99, 0x01, 0x09, 0xCA, 0x2F, 0xF0, 0xF0, 0xF1, 0x01, 0x82, 0x1D, 0x82, 0xD9, 0x06, 0x70, 0x75, 0x87, 0x7D, 0x97, 0xCA, 0x01, 0x10, 0xA3, 0x7D, 0x01, 0x08, 0xB3, 0x7B, 0x01, 0x09, 0xDF, 0x77, 0x01, 0x08, 0xD3, 0x77, 0x01, 0x05, 0xB3, 0x7B, 0x74, 0xC6, 0x01, 0x08, 0x87, 0x7F, 0x01, 0x0C, 0xA3, 0x7D, 0xC1, 0x5F, 0x5F, 0xBF, 0x5E, 0x5C, 0xBF, 0x01, 0x07, 0x8F, 0x7E, 0x55, 0xBD, 0x4A, 0x47, 0x8C, 0x37, 0x39, 0x01, 0x4C, 0x81, 0xB3, 0x26, 0xCE, 0xCE, 0xD3, 0x01, 0x09, 0x82, 0xE4, 0x56, 0x01, 0x21, 0xD3, 0x62, 0x4F, 0x51, 0x61, 0x01, 0x09, 0x84, 0xB1, 0x3C, 0x01, 0x12, 0x83, 0xB9, 0x3C, 0x01, 0x82, 0x0F, 0x81, 0xE8, 0x46, 0x45, 0x5D, 0x70, 0x85, 0xB7, 0x01, 0x07, 0xC3, 0x79, 0x01, 0x08, 0xDF, 0x77, 0x01, 0x0E, 0xEF, 0x75, 0x01, 0x08, 0xA3, 0x7D, 0x77, 0x01, 0x07, 0xA3, 0x7D, 0x01, 0x0A, 0xBB, 0x7A, 0x01, 0x0D, 0x87, 0x7F, 0x01, 0x07, 0x8F, 0x7E, 0x59, 0x55, 0xB9, 0x43, 0x43, 0x01, 0x4F, 0xF3, 0x13, 0x01, 0x09, 0xEC, 0x1B, 0xFE, 0xFE, 0xFE, 0x01, 0x27, 0x82, 0xD8, 0x59, 0x74, 0x76, 0x83, 0x01, 0x09, 0x8C, 0x09, 0x6A, 0x6C, 0x7A, 0x01, 0x82, 0x1E, 0x82, 0xF3, 0x38, 0x3C, 0x50, 0x62, 0x72, 0x9E, 0x01, 0x0C, 0xC3, 0x79, 0x01, 0x0A, 0x87, 0x7F, 0x81, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x07, 0x9B, 0x7E, 0x01, 0x06, 0x97, 0x7D, 0x6F, 0x01, 0x06, 0x97, 0x7D, 0x01, 0x08, 0x87, 0x7F, 0x61, 0xC0, 0x01, 0x09, 0x87, 0x7F, 0x58, 0x54, 0xAF, 0x3D, 0x3E, 0x01, 0x4F, 0x81, 0xA6, 0x7C, 0x37, 0x39, 0x4C, 0xC0, 0x01, 0x08, 0x81, 0xED, 0x69, 0xAE, 0xAF, 0xB6, 0x01, 0x33, 0xEE, 0x53, 0xAC, 0xAD, 0xB5, 0x01, 0x82, 0x23, 0x81, 0x81, 0x09, 0x53, 0x5E, 0x83, 0x78, 0x8D, 0xCA, 0x01, 0x05, 0xC3, 0x79, 0x01, 0x05, 0x84, 0x01, 0x01, 0x0A, 0xA3, 0x7D, 0xC8, 0x6E, 0x79, 0x01, 0x05, 0xAB, 0x7C, 0x74, 0xC5, 0x6B, 0x73, 0xC6, 0x01, 0x0D, 0xA3, 0x7D, 0x65, 0xC1, 0x01, 0x06, 0x87, 0x7F, 0x60, 0x5E, 0xC0, 0x5E, 0x5B, 0xBF, 0x52, 0x50, 0x9F, 0x01, 0x54, 0xB8, 0x05, 0x38, 0x3A, 0x4D, 0x01, 0x09, 0x9D, 0x3B, 0x01, 0x09, 0xEF, 0x7B, 0x01, 0x24, 0x39, 0x71, 0x72, 0x7F, 0x01, 0x08, 0xA6, 0x6B, 0xE6, 0x01, 0x82, 0x26, 0x81, 0x85, 0x0D, 0x46, 0x4D, 0x69, 0x71, 0x83, 0xBF, 0x01, 0x08, 0xE7, 0x76, 0xC9, 0x01, 0x09, 0xA3, 0x7D, 0x01, 0x07, 0xDF, 0x77, 0x01, 0x08, 0xC3, 0x79, 0x01, 0x05, 0x97, 0x7D, 0xC2, 0x01, 0x05, 0x9B, 0x7E, 0x01, 0x05, 0xA3, 0x7D, 0x5F, 0xBF, 0x5F, 0x5D, 0xBF, 0x4B, 0x4A, 0x87, 0x01, 0x4E, 0x8F, 0x75, 0x01, 0x0C, 0xF2, 0x1B, 0x01, 0x09, 0x8C, 0x00, 0x01, 0x2D, 0x81, 0xD4, 0x35, 0x01, 0x09, 0xE0, 0x51, 0xFB, 0xFB, 0xFC, 0x01, 0x82, 0x2A, 0x82, 0x88, 0x4E, 0x40, 0x58, 0x67, 0x75, 0xAD, 0x01, 0x08, 0xB3, 0x7B, 0x01, 0x07, 0xF7, 0x74, 0x01, 0x0B, 0xBB, 0x7A, 0xC5, 0x01, 0x09, 0xC3, 0x79, 0x01, 0x05, 0xBB, 0x7A, 0xC0, 0x61, 0x61, 0xC0, 0x5E, 0x5C, 0xBA, 0x43, 0x44, 0x01, 0x5B, 0x81, 0xF3, 0x1E, 0x01, 0x09, 0xEC, 0x1B, 0x01, 0x33, 0x87, 0x49, 0x01, 0x09, 0xF6, 0x55, 0x01, 0x12, 0x83, 0xE5, 0x32, 0x01, 0x82, 0x1C, 0x83, 0xFF, 0x64, 0x4E, 0x59, 0x64, 0x94, 0x01, 0x13, 0xAB, 0x7C, 0x01, 0x07, 0xB3, 0x7B, 0x01, 0x0A, 0x97, 0x7D, 0x62, 0x62, 0xC1, 0x5A, 0x59, 0xAD, 0x3D, 0x3F, 0x01, 0x5E, 0x82, 0xE3, 0x6D, 0x5A, 0x5B, 0x6B, 0x01, 0x36, 0x81, 0xE0, 0x38, 0x01, 0x0C, 0x81, 0xE4, 0x39, 0x01, 0x69, 0x9C, 0x0D, 0x01, 0x21, 0xA3, 0x65, 0x4B, 0x4D, 0x5D, 0xA3, 0xA3, 0xA9, 0x01, 0x09, 0x81, 0xB0, 0x0B, 0x01, 0x81, 0x19, 0x82, 0x9C, 0x74, 0x4C, 0x52, 0x79, 0x6E, 0x7B, 0xC3, 0x01, 0x06, 0xBB, 0x7A, 0x6C, 0x76, 0x01, 0x07, 0xC3, 0x79, 0x68, 0x6E, 0x01, 0x0D, 0xBB, 0x7A, 0x54, 0x54, 0x9A, 0x01, 0x57, 0x81, 0x84, 0x12, 0x01, 0x0F, 0xF0, 0x01, 0x01, 0x09, 0x8C, 0x03, 0x01, 0x2D, 0xB3, 0x72, 0x49, 0x4A, 0x5C, 0x01, 0x6F, 0x81, 0xF0, 0x3C, 0x01, 0x06, 0xC7, 0x5F, 0x01, 0x1B, 0xAF, 0x62, 0x89, 0x8A, 0x93, 0x01, 0x12, 0xB4, 0x28, 0xD9, 0xD9, 0xDB, 0x01, 0x81, 0x16, 0x82, 0xD8, 0x50, 0x41, 0x45, 0x62, 0x67, 0x72, 0xB7, 0x01, 0x08, 0x9F, 0x7C, 0x01, 0x05, 0x97, 0x7D, 0x01, 0x08, 0xAB, 0x7C, 0x62, 0x64, 0xC0, 0x4A, 0x4C, 0x01, 0x67, 0xB2, 0x74, 0x38, 0x3A, 0x4D, 0x01, 0x09, 0xA3, 0x59, 0x01, 0x2D, 0x81, 0x8F, 0x74, 0x01, 0x09, 0x82, 0x80, 0x76, 0xE5, 0xE5, 0xE7, 0x01, 0x67, 0x83, 0x82, 0x08, 0x01, 0x08, 0x82, 0xD8, 0x20, 0x01, 0x15, 0xD3, 0x5F, 0x01, 0x0C, 0x81, 0xE8, 0x5B, 0x01, 0x0F, 0x84, 0x04, 0x01, 0x2D, 0x81, 0xCC, 0x66, 0x01, 0x6C, 0x84, 0x04, 0x3B, 0x3D, 0x54, 0x5D, 0x64, 0xA4, 0x01, 0x06, 0xDF, 0x77, 0x67, 0x01, 0x08, 0x97, 0x7D, 0x61, 0x62, 0xB8, 0x42, 0x45, 0x01, 0x37, 0x81, 0x85, 0x6D, 0x01, 0x36, 0x36, 0x01, 0x09, 0xE0, 0x12, 0x01, 0x2D, 0x82, 0x80, 0x0A, 0x01, 0x09, 0x81, 0xDC, 0x3A, 0xAF, 0xAF, 0xB7, 0x01, 0x68, 0x82, 0xEE, 0x03, 0xF6, 0x01, 0x1B, 0x82, 0xC4, 0x1B, 0x01, 0x09, 0x8D, 0x10, 0x01, 0x06, 0x81, 0xC0, 0x48, 0x01, 0x06, 0x81, 0xBC, 0x59, 0x01, 0x5A, 0x81, 0xF0, 0x3C, 0x01, 0x4C, 0x8B, 0x05, 0x4D, 0x76, 0x5D, 0x62, 0xA9, 0x63, 0x6A, 0xBB, 0x5E, 0x62, 0xB0, 0x50, 0x53, 0x8E, 0x3A, 0x3C, 0x01, 0x4C, 0x81, 0xE8, 0x16, 0x01, 0x24, 0x24, 0x82, 0x83, 0x8F, 0x01, 0x09, 0x82, 0x88, 0x0F, 0x66, 0x67, 0x01, 0x25, 0x9C, 0x0A, 0x01, 0x0C, 0x82, 0x88, 0x75, 0x01, 0x18, 0xE4, 0x3D, 0x01, 0x57, 0xFC, 0x19, 0x01, 0x15, 0xE7, 0x61, 0x01, 0x0C, 0x81, 0xF0, 0x24, 0x01, 0x0C, 0x8B, 0x71, 0x01, 0x3C, 0xF0, 0x1C, 0x01, 0x81, 0x6D, 0x84, 0x94, 0x7C, 0xD3, 0xD3, 0xD7, 0x01, 0x09, 0x82, 0x84, 0x0E, 0x45, 0x47, 0x59, 0x01, 0x21, 0x82, 0xAE, 0x11, 0x01, 0x06, 0x81, 0x8C, 0x56, 0x01, 0x18, 0x81, 0x84, 0x57, 0x01, 0x5D, 0xDC, 0x17, 0x01, 0x1E, 0xCC, 0x2B, 0x01, 0x12, 0xD8, 0x34, 0x01, 0x09, 0xD0, 0x4A, 0x01, 0x82, 0x1D, 0x82, 0xC8, 0x55, 0x58, 0x5A, 0x6A, 0x01, 0x09, 0x83, 0xD8, 0x4F, 0xEE, 0xEE, 0xF0, 0x01, 0x1B, 0x81, 0x93, 0x78, 0x85, 0x86, 0x92, 0x01, 0x09, 0xEE, 0x29, 0xF2, 0xF2, 0xF3, 0x01, 0x69, 0x81, 0x84, 0x1B, 0x01, 0x1B, 0xE8, 0x1A, 0x5D, 0x5E, 0x01, 0x07, 0x99, 0x49, 0x01, 0x15, 0x87, 0x67, 0x01, 0x09, 0x90, 0x1C, 0x01, 0x81, 0x1F, 0x82, 0xC4, 0x5D, 0x01, 0x81, 0x01, 0x81, 0x01, 0x9B, 0x9C, 0xA5, 0x01, 0x0C, 0x92, 0x39, 0xCC, 0xCD, 0xD2, 0x96, 0x97, 0xA1, 0x72, 0x74, 0x81, 0x4F, 0x51, 0x61, 0x52, 0x54, 0x64, 0x75, 0x77, 0x84, 0x99, 0x9A, 0xA3, 0x01, 0x0F, 0x81, 0xFA, 0x34, 0x84, 0x85, 0x01, 0x6A, 0xD1, 0x18, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0x87, 0x64, 0x01, 0x18, 0x8F, 0x69, 0x01, 0x82, 0x02, 0x82, 0xE0, 0x58, 0x01, 0x27, 0x81, 0xA4, 0x2F, 0x9A, 0x9B, 0xA5, 0x01, 0x09, 0x82, 0xB1, 0x71, 0x01, 0x1E, 0xC4, 0x11, 0xF5, 0xF5, 0xF6, 0x8A, 0x8C, 0x97, 0x01, 0x6F, 0x82, 0xCC, 0x62, 0x01, 0x18, 0x84, 0x01, 0x01, 0x09, 0x8C, 0x00, 0x01, 0x18, 0x8B, 0x65, 0x01, 0x82, 0x26, 0x84, 0x01, 0x01, 0x07, 0xEF, 0x75, 0x5C, 0x6C, 0xD7, 0xD8, 0x01, 0x1F, 0xCE, 0x6F, 0xC8, 0xC8, 0xCD, 0x4F, 0x51, 0x01, 0x52, 0xB5, 0x14, 0x01, 0x27, 0x9C, 0x04, 0x01, 0x0F, 0x9F, 0x55, 0x01, 0x1E, 0x8C, 0x00, 0x01, 0x0C, 0x21, 0x01, 0x69, 0x82, 0x98, 0x52, 0x01, 0x81, 0x43, 0x88, 0x0B, 0x88, 0x89, 0x95, 0xC8, 0xC8, 0xCD, 0x01, 0x09, 0x84, 0xA5, 0x06, 0x01, 0x09, 0x81, 0x90, 0x2A, 0xBF, 0xC0, 0xC6, 0x7B, 0x7C, 0x01, 0x76, 0x83, 0xF4, 0x6B, 0x01, 0x18, 0xF3, 0x64, 0x01, 0x09, 0xD4, 0x1E, 0x01, 0x18, 0x87, 0x61, 0x01, 0x09, 0x98, 0x3F, 0x01, 0x82, 0x20, 0x82, 0xF8, 0x5E, 0x01, 0x16, 0x83, 0xDC, 0x77, 0x4E, 0x5F, 0x5E, 0x5F, 0x6F, 0x5B, 0x5D, 0x6C, 0x49, 0x4B, 0x5C, 0x01, 0x7E, 0x83, 0xE8, 0x68, 0x01, 0x0C, 0xEF, 0x66, 0x01, 0x06, 0x87, 0x4C, 0x5D, 0x5E, 0x6B, 0x01, 0x09, 0xF3, 0x79, 0xF6, 0xF6, 0xF6, 0x01, 0x18, 0x81, 0xA4, 0x17, 0x01, 0x09, 0x81, 0xA4, 0x4D, 0x01, 0x83, 0x42, 0x82, 0xC7, 0x12, 0x01, 0x09, 0x93, 0x6D, 0x01, 0x1E, 0x81, 0xA0, 0x25, 0x01, 0x15, 0x8C, 0x00, 0x01, 0x5D, 0xE8, 0x1D, 0x01, 0x82, 0x6C, 0x84, 0xAA, 0x32, 0x01, 0x0B, 0x81, 0xE4, 0x33, 0x01, 0x24, 0x82, 0x9C, 0x53, 0x01, 0x09, 0x87, 0x7F, 0x01, 0x82, 0x32, 0x8C, 0x00, 0x01, 0x81, 0x19, 0x81, 0x19, 0x89, 0x8A, 0x93, 0x01, 0x09, 0x83, 0x57, 0xD9, 0xD9, 0xDB, 0x01, 0x1B, 0x9F, 0x5E, 0x01, 0x09, 0x8C, 0x36, 0x01, 0x83, 0x33, 0x82, 0xF0, 0x59, 0x01, 0x4B, 0x90, 0x3A, 0xC4, 0xC4, 0xC8, 0x01, 0x39, 0x81, 0xB8, 0x49, 0x01, 0x91, 0x7A, 0x84, 0xD9, 0x01, 0x50, 0x51, 0x62, 0x6F, 0x70, 0x7E, 0x8E, 0x8F, 0x9A, 0xA7, 0xA8, 0xB0, 0xA9, 0xAA, 0xB2, 0xA9, 0xAA, 0xB2, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0F, 0x0F, 0x01, 0x83, 0x48, 0x83, 0x7E, 0x6B, 0x6D, 0x7B, 0x01, 0x09, 0x84, 0x9D, 0x10, 0x01, 0x83, 0x6F, 0x83, 0xD8, 0x76, 0x3E, 0x3F, 0x52, 0xBC, 0xBD, 0xC3, 0x01, 0x83, 0x78, 0x85, 0x89, 0x22, 0x01, 0x15, 0x81, 0xE0, 0x1A, 0xF8, 0xF8, 0xF9, 0xDB, 0xDC, 0xDF, 0xC4, 0xC5, 0xCB, 0xC4, 0xC4, 0xCA, 0xC4, 0xC4, 0xCA, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0C, 0x0C, 0x01, 0x83, 0x4B, 0x85, 0xE9, 0x37, 0x01, 0x06, 0x81, 0x80, 0x1A, 0x62, 0x63, 0x72, 0x01, 0x83, 0x6C, 0x84, 0xE9, 0x0B, 0x01, 0x09, 0x84, 0xD9, 0x13, 0xFF, 0xFF, 0xFF, 0xA7, 0xA8, 0xB1, 0x01, 0x83, 0x72, 0x85, 0x90, 0x74, 0x01, 0x06, 0x85, 0xA9, 0x21, 0x01, 0x06, 0x84, 0xB5, 0x0D, 0x01, 0x81, 0x46, 0x81, 0xF4, 0x13, 0x01, 0x82, 0x2C, 0x83, 0x7E, 0x43, 0x45, 0x01, 0x0A, 0x82, 0xD4, 0x1C, 0x01, 0x81, 0x07, 0x81, 0x8F, 0x77, 0x01, 0x82, 0x71, 0x90, 0x01, 0x01, 0x0A, 0x82, 0xCF, 0x2C, 0x01, 0x14, 0x81, 0xC8, 0x1D, 0x01, 0x83, 0x60, 0x84, 0x01, 0x01, 0x09, 0x84, 0xD5, 0x15, 0x01, 0x69, 0x81, 0xDB, 0x7E, 0x01, 0x83, 0x12, 0x83, 0xE8, 0x7A, 0x01, 0x09, 0x84, 0x80, 0x71, 0x01, 0x51, 0x82, 0xAF, 0x7B, 0x01, 0x83, 0x27, 0x84, 0x04, 0x01, 0x06, 0x82, 0x80, 0x3D, 0xFF, 0xFF, 0xFF, 0x79, 0x7B, 0x01, 0x43, 0x82, 0xED, 0x2C, 0x01, 0x83, 0x33, 0x84, 0x01, 0x9C, 0x9D, 0xA6, 0x01, 0x15, 0x84, 0xC9, 0x0F, 0x01, 0x83, 0x69, 0x84, 0x01, 0x49, 0x4B, 0x5C, 0x01, 0x06, 0xEC, 0x18, 0xF4, 0xF4, 0xF5, 0x01, 0x15, 0x84, 0xCD, 0x34, 0x01, 0x83, 0x63, 0x84, 0x04, 0x01, 0x09, 0x81, 0xF0, 0x27, 0xD7, 0xD7, 0xDB, 0x01, 0x83, 0x69, 0x85, 0xC9, 0x2C, 0x01, 0x0F, 0x0F, 0x01, 0x09, 0x84, 0xCC, 0x7E, 0xCC, 0xCD, 0xD2, 0x5C, 0x5E, 0x6D, 0x01, 0x83, 0x75, 0x84, 0x04, 0x75, 0x77, 0x84, 0x01, 0x06, 0x82, 0xD8, 0x35, 0xFD, 0xFD, 0xFD, 0xB5, 0xB6, 0xBD, 0x78, 0x7A, 0x86, 0x5B, 0x5C, 0x6C, 0x01, 0x83, 0x6F, 0x9C, 0x1C, 0x5A, 0x5B, 0x6B, 0xE3, 0xE3, 0xE6, 0x01, 0x0F, 0x82, 0xAD, 0x7C, 0xF3, 0xF3, 0xF4, 0xF3, 0xF3, 0xF4, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x09, 0x09, 0x01, 0x83, 0x48, 0x85, 0x91, 0x27, 0x01, 0x06, 0x82, 0x88, 0x12, 0x01, 0x83, 0x75, 0xC0, 0x10, 0x55, 0x57, 0x67, 0x01, 0x3C, 0x82, 0x8E, 0x42, 0x01, 0x83, 0x42, 0x84, 0xD0, 0x7C, 0xE5, 0xE6, 0xE8, 0x01, 0x0C, 0x83, 0x51, 0xE4, 0xE4, 0xE7, 0xB9, 0xB9, 0xC0, 0x99, 0x9A, 0xA4, 0x83, 0x84, 0x90, 0x82, 0x83, 0x8F, 0x82, 0x83, 0x8F, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x0C, 0x0C, 0x01, 0x83, 0x3F, 0x84, 0x01, 0x85, 0x86, 0x92, 0x01, 0x0C, 0x84, 0xD8, 0x7B, 0x92, 0x93, 0x9E, 0x01, 0x83, 0x6F, 0x84, 0xD5, 0x00, 0x01, 0x09, 0x82, 0xF0, 0x2F, 0xFF, 0xFF, 0xFF, 0x73, 0x74, 0x01, 0x4C, 0x81, 0xCD, 0x07, 0x01, 0x83, 0x27, 0x8C, 0x00, 0x01, 0x09, 0x82, 0xAC, 0x2A, 0xBC, 0xBD, 0xC3, 0x01, 0x83, 0x72, 0x9F, 0x7C, 0x54, 0x55, 0x65, 0x01, 0x83, 0x7B, 0x87, 0x7F, 0x37, 0x39, 0x4C, 0x63, 0x65, 0x74, 0x01, 0x09, 0x84, 0x01, 0x01, 0x83, 0x75, 0xB0, 0x09, 0x01, 0x0C, 0x83, 0xA4, 0x69, 0x01, 0x83, 0x75, 0xB0, 0x06, 0x3A, 0x3C, 0x4E, 0x01, 0x09, 0x90, 0x04, 0x01, 0x83, 0x78, 0xB0, 0x03, 0x01, 0x09, 0x81, 0xA3, 0x7F, 0x01, 0x83, 0x51, 0x85, 0xC1, 0x03, 0x01, 0x30, 0x81, 0xB4, 0x2D, 0x01, 0x12, 0x82, 0xAC, 0x4E, 0x01, 0x83, 0x69, 0x86, 0x85, 0x44, 0x01, 0x09, 0xCC, 0x16, 0x78, 0x79, 0x01, 0x83, 0x49, 0x81, 0x92, 0x4D, 0x01, 0x30, 0x82, 0x98, 0x16, 0x01, 0x06, 0x81, 0xC4, 0x37, 0xF2, 0xF2, 0x01, 0x16, 0x85, 0x95, 0x49, 0x01, 0x83, 0x63, 0x84, 0x04, 0x6B, 0x6D, 0x7B, 0x01, 0x06, 0xE8, 0x23, 0xF6, 0xF6, 0xF7, 0x99, 0x9A, 0xA3, 0x01, 0x83, 0x69, 0xC0, 0x07, 0x3C, 0x3E, 0x50, 0x63, 0x65, 0x74, 0x63, 0x65, 0x74, 0x63, 0x65, 0x74, 0x6D, 0x6F, 0x7D, 0x01, 0x09, 0x82, 0x96, 0x1D, 0xE9, 0xEA, 0xEC, 0xB3, 0xB4, 0xBB, 0x95, 0x96, 0xA0, 0x76, 0x77, 0x84, 0x01, 0x09, 0x21, 0x01, 0x09, 0x09, 0x01, 0x0F, 0x0F, 0x01, 0x87, 0x3D, 0x86, 0x89, 0x42, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x09, 0x85, 0xED, 0x1A, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x12, 0x12, 0x01, 0xA3, 0x47, 0x85, 0x95, 0x16, 0x3A, 0x3C, 0x4E, 0x3E, 0x3F, 0x52, 0x3E, 0x3F, 0x52, 0x01, 0x30, 0xA3, 0x53, 0x47, 0x49, 0x5A, 0x01, 0x75, 0x84, 0x80, 0x7D, 0x01, 0x82, 0x59, 0x83, 0xA6, 0x6E, 0x01, 0x2A, 0xB7, 0x58, 0x3C, 0x3E, 0x50, 0xC5, 0xC6, 0xCB, 0xFB, 0xFB, 0xFC, 0xEC, 0xED, 0xEE, 0x01, 0x12, 0x85, 0xDA, 0x07, 0x01, 0x83, 0x31, 0x85, 0x91, 0x21, 0x01, 0x08, 0x83, 0x96, 0x6A, 0x01, 0x2D, 0xBB, 0x59, 0xC1, 0xC1, 0xC7, 0x01, 0x07, 0x82, 0xFE, 0x3A, 0x92, 0x01, 0x81, 0x74, 0x82, 0xD9, 0x66, 0x01, 0x81, 0x4C, 0x81, 0x4C, 0x90, 0x91, 0x01, 0x34, 0x84, 0x01, 0x01, 0x09, 0x82, 0xA0, 0x48, 0xD6, 0xD6, 0xDA, 0x01, 0x83, 0x48, 0x81, 0x90, 0x21, 0x01, 0x2D, 0x84, 0x01, 0x4C, 0x4E, 0x5F, 0x01, 0x09, 0x83, 0x9C, 0x6D, 0x01, 0x83, 0x3F, 0xB4, 0x10, 0x8E, 0x8F, 0x99, 0x01, 0x33, 0x84, 0x01, 0x01, 0x09, 0x82, 0xA4, 0x49, 0xFF, 0xFF, 0xFF, 0x01, 0x72, 0x81, 0xF8, 0x4D, 0x01, 0x82, 0x4D, 0x84, 0x01, 0x8C, 0x8D, 0x98, 0x01, 0x33, 0x84, 0x01, 0x84, 0x85, 0x91, 0x01, 0x09, 0x82, 0x9C, 0x47, 0x01, 0x81, 0x19, 0x84, 0xF9, 0x54, 0x01, 0x82, 0x1A, 0xF8, 0x12, 0x3A, 0x3C, 0x4F, 0x01, 0x06, 0x06, 0x3A, 0x3C, 0x4F, 0x01, 0x09, 0x88, 0x02, 0x67, 0x69, 0x77, 0x01, 0x0F, 0x1B, 0x01, 0x0F, 0x0F, 0x3A, 0x3C, 0x4F, 0x41, 0x43, 0x55, 0x57, 0x58, 0x68, 0x94, 0x95, 0x9F, 0x01, 0x09, 0x82, 0x9C, 0x7D, 0x01, 0x15, 0x83, 0x99, 0x1F, 0x01, 0x83, 0x24, 0x85, 0x81, 0x0E, 0x01, 0x48, 0x83, 0x8A, 0x40, 0x80, 0x81, 0x01, 0x55, 0x83, 0x81, 0x73, 0x01, 0x83, 0x27, 0x84, 0x01, 0x01, 0x15, 0x86, 0x89, 0x78, 0x01, 0x83, 0x63, 0x84, 0x01, 0xF7, 0xF8, 0xF8, 0xD6, 0xD6, 0xDA, 0x01, 0x83, 0x36, 0x81, 0x80, 0x50, 0x41, 0x43, 0x55, 0x61, 0x62, 0x71, 0x61, 0x62, 0x71, 0x01, 0x06, 0x06, 0x61, 0x62, 0x71, 0x01, 0x09, 0x81, 0xD8, 0x33, 0x84, 0x85, 0x91, 0x01, 0x0F, 0x1B, 0x01, 0x0F, 0x0F, 0x01, 0x06, 0x06, 0x01, 0x83, 0x51, 0x81, 0xBC, 0x56, 0x01, 0x09, 0x84, 0x90, 0x4E, 0x01, 0x83, 0x3F, 0xE3, 0x63, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x3C, 0x82, 0xA8, 0x47, 0x87, 0x88, 0x94, 0x87, 0x88, 0x94, 0x49, 0x4A, 0x01, 0x81, 0x02, 0x82, 0xE8, 0x30, 0x01, 0xA3, 0x6E, 0x85, 0xF2, 0x1F, 0x01, 0x83, 0x1B, 0xE0, 0x21, 0x7B, 0x7C, 0x89, 0xA0, 0xA1, 0xAA, 0xC5, 0xC6, 0xCB, 0xE3, 0xE3, 0xE6, 0xE6, 0xE6, 0xE9, 0xE7, 0xE7, 0xE9, 0xE8, 0xE8, 0xEA, 0xE8, 0xE8, 0xEA, 0xE9, 0xE9, 0xEB, 0xE9, 0xEA, 0xEC, 0xE9, 0xEA, 0xEC, 0xEA, 0xEA, 0xEC, 0xEB, 0xEB, 0xED, 0xEC, 0xEC, 0xEE, 0xEC, 0xEC, 0xEE, 0xEC, 0xED, 0xEE, 0xED, 0xED, 0xEF, 0xED, 0xED, 0xEF, 0x01, 0x83, 0x45, 0x83, 0x7E, 0x57, 0x59, 0x69, 0x01, 0x21, 0x82, 0xC8, 0x4C, 0x01, 0x83, 0x5A, 0x81, 0xD4, 0x35, 0x6D, 0x6F, 0x7D, 0x01, 0x30, 0x84, 0xD6, 0x5E, 0x01, 0x83, 0x4E, 0x81, 0xD4, 0x35, 0xE0, 0xE0, 0xE3, 0x01, 0x09, 0x83, 0x4E, 0xDC, 0xDC, 0xE0, 0xAB, 0xAB, 0xB3, 0x89, 0x8A, 0x95, 0x7F, 0x80, 0x8C, 0x01, 0x06, 0x84, 0xF9, 0x15, 0xD7, 0xD8, 0xDB, 0x76, 0x77, 0x84, 0x76, 0x77, 0x84, 0x8A, 0x8B, 0x96, 0x01, 0x0A, 0x85, 0xE9, 0x67, 0xF0, 0xF1, 0x79, 0x7B, 0x87, 0x6D, 0x6F, 0x7D, 0x6D, 0x6F, 0x01, 0x64, 0x82, 0xE4, 0x59, 0x01, 0x82, 0x65, 0xDC, 0x17, 0xFD, 0xFD, 0xFD, 0x99, 0x9A, 0xA3, 0x01, 0x0C, 0x82, 0xCC, 0x3B, 0x01, 0x06, 0x83, 0xEF, 0x12, 0xC4, 0xC5, 0xCB, 0x01, 0x0E, 0x83, 0x94, 0x68, 0x01, 0x07, 0xE0, 0x48, 0xD6, 0xD6, 0xDA, 0x42, 0x44, 0x01, 0x70, 0x82, 0xEA, 0x08, 0x01, 0x82, 0x53, 0x84, 0x01, 0x01, 0x09, 0x8F, 0x7B, 0xB1, 0xB2, 0xB9, 0x01, 0x0F, 0x1B, 0x01, 0x12, 0x84, 0x01, 0x01, 0x06, 0x06, 0x8F, 0x90, 0x9B, 0x01, 0x82, 0x2C, 0x83, 0x8C, 0x60, 0x01, 0x81, 0x1F, 0x81, 0x1F, 0x01, 0x06, 0x83, 0x8C, 0x63, 0xFB, 0xFB, 0xFB, 0x01, 0x12, 0x85, 0xE5, 0x39, 0x01, 0x18, 0x84, 0x01, 0x01, 0x09, 0x84, 0x8F, 0x3E, 0xFD, 0xFD, 0xFD, 0x5A, 0x5B, 0x01, 0x83, 0x3D, 0x82, 0xC3, 0x2F, 0x01, 0x09, 0x83, 0x80, 0x27, 0xDF, 0xDF, 0xE2, 0x01, 0x12, 0x1E, 0x01, 0x1B, 0x84, 0x01, 0x76, 0x77, 0x84, 0x01, 0x81, 0x04, 0x85, 0x81, 0x23, 0x01, 0x82, 0x4A, 0x81, 0xD4, 0x35, 0x01, 0x15, 0x82, 0xAC, 0x12, 0x01, 0x1B, 0x84, 0x01, 0x39, 0x3B, 0x4E, 0x01, 0x06, 0x82, 0x84, 0x77, 0xDE, 0xDE, 0xE1, 0x01, 0x83, 0x45, 0x85, 0xF5, 0x3D, 0xB9, 0xB9, 0x01, 0x13, 0x84, 0x9D, 0x67, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0x86, 0x81, 0x79, 0xFD, 0xFD, 0xFD, 0x01, 0x7E, 0x82, 0xE0, 0x73, 0x01, 0x82, 0x47, 0x81, 0xD8, 0x36, 0xDB, 0xDC, 0xDF, 0x01, 0x12, 0x1E, 0x01, 0x06, 0x84, 0xBB, 0x25, 0x01, 0x18, 0x84, 0x88, 0x64, 0x01, 0x09, 0x83, 0xC2, 0x66, 0x01, 0x83, 0x3C, 0xD0, 0x4D, 0x3B, 0x3D, 0x50, 0x01, 0x06, 0xA4, 0x03, 0x01, 0x15, 0x84, 0x8D, 0x03, 0x01, 0x06, 0x84, 0x90, 0x69, 0x01, 0x15, 0x84, 0x95, 0x1D, 0x37, 0x39, 0x4C, 0xD5, 0x01, 0x08, 0x85, 0xDD, 0x64, 0x01, 0x18, 0x83, 0xE5, 0x23, 0x01, 0x83, 0x27, 0x84, 0x04, 0x01, 0x09, 0x84, 0x86, 0x77, 0x5F, 0x60, 0x01, 0x10, 0x85, 0xE5, 0x2D, 0x01, 0x06, 0x83, 0xA9, 0x05, 0xF0, 0xF1, 0xF2, 0x01, 0x15, 0x39, 0x01, 0x06, 0x88, 0x20, 0xF8, 0xF8, 0xF9, 0x01, 0x83, 0x3C, 0x8C, 0x03, 0x01, 0x0C, 0x81, 0x8C, 0x23, 0xB2, 0xB2, 0x01, 0x10, 0x84, 0x80, 0x68, 0xA5, 0xA6, 0x01, 0x07, 0x84, 0x87, 0x0F, 0x67, 0x69, 0x77, 0x01, 0x0F, 0x1B, 0x73, 0x74, 0x82, 0x01, 0x07, 0x83, 0xF6, 0x5E, 0xDA, 0xDE, 0x01, 0x83, 0x3F, 0xA0, 0x08, 0x3F, 0x41, 0x53, 0x01, 0x06, 0x83, 0xA4, 0x33, 0xFC, 0xFC, 0xFC, 0x57, 0x59, 0x69, 0x01, 0x15, 0x83, 0xFD, 0x1A, 0xC6, 0xC7, 0xCC, 0x01, 0x0C, 0x81, 0xFC, 0x54, 0x48, 0x4A, 0x5B, 0x01, 0x09, 0x81, 0xF8, 0x74, 0xAD, 0xAE, 0x01, 0x83, 0x43, 0xA4, 0x0C, 0x8D, 0x8E, 0x01, 0x07, 0xAC, 0x0E, 0xC1, 0xC1, 0xC7, 0x01, 0x18, 0x8F, 0x69, 0xC8, 0xC9, 0xCE, 0x7B, 0x7C, 0x89, 0x65, 0x66, 0x75, 0x8D, 0x8E, 0x99, 0x01, 0x09, 0x82, 0x88, 0x6F, 0xF4, 0xF4, 0xF5, 0x01, 0x81, 0x04, 0x83, 0xCC, 0x7F, 0x01, 0x82, 0x44, 0x94, 0x0B, 0x01, 0x06, 0x83, 0xDE, 0x3D, 0xB9, 0xB9, 0xC0, 0x01, 0x0F, 0x82, 0x84, 0x3E, 0x6F, 0x70, 0x7E, 0x01, 0x1B, 0x84, 0x83, 0x02, 0x8C, 0x8D, 0x98, 0x01, 0x83, 0x48, 0xC4, 0x0E, 0x71, 0x72, 0x7F, 0x01, 0x18, 0x83, 0x9C, 0x64, 0x71, 0x73, 0x80, 0x01, 0x12, 0x85, 0xA3, 0x00, 0xF4, 0xF4, 0xF5, 0x7F, 0x01, 0x83, 0x2F, 0x81, 0x84, 0x1B, 0x01, 0x3F, 0x82, 0x80, 0x67, 0x99, 0x9A, 0xA3, 0xC4, 0xC4, 0xCA, 0xE0, 0xE0, 0xE3, 0xBF, 0xC0, 0xC6, 0x97, 0x98, 0xA2, 0x01, 0x81, 0x46, 0x85, 0xC1, 0x3C, 0x00}; +static const uint8_t s_splash[] = {0x01, 0x34, 0x36, 0x4B, 0x34, 0x36, 0x4B, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x30, 0x30, 0x01, 0x60, 0x60, 0x01, 0x81, 0x40, 0x81, 0x40, 0x01, 0x83, 0x00, 0x83, 0x00, 0x01, 0x86, 0x00, 0x86, 0x00, 0x01, 0x8C, 0x00, 0x8C, 0x00, 0x01, 0x98, 0x00, 0x98, 0x00, 0x01, 0xB0, 0x00, 0xB0, 0x00, 0x01, 0xD3, 0x44, 0xD3, 0x44, 0x67, 0x68, 0x78, 0x8D, 0x8E, 0x9A, 0x80, 0x82, 0x8F, 0x01, 0x83, 0x6F, 0x83, 0x78, 0x41, 0x43, 0x56, 0x9A, 0x9B, 0xA5, 0xF2, 0xF2, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xCD, 0xD2, 0x01, 0x0F, 0x84, 0x16, 0x01, 0x83, 0x60, 0x83, 0x7E, 0xD9, 0xD9, 0xDD, 0xF2, 0xF2, 0xF4, 0x9A, 0x9B, 0xA5, 0x5A, 0x5C, 0x6D, 0x9A, 0x9B, 0xA5, 0x01, 0x0C, 0x84, 0x01, 0x41, 0x43, 0x56, 0x01, 0x06, 0x1B, 0x01, 0x83, 0x5A, 0x84, 0x01, 0xD9, 0xD9, 0xDD, 0xD9, 0xD9, 0xDD, 0x4D, 0x4F, 0x62, 0x01, 0x06, 0x0F, 0x01, 0x0F, 0x84, 0x01, 0x34, 0x36, 0x4B, 0x74, 0x75, 0x83, 0xFF, 0xFF, 0xFF, 0x01, 0x09, 0x21, 0x01, 0x83, 0x4E, 0x83, 0x7E, 0x8D, 0x8E, 0x9A, 0xF2, 0xF2, 0xF4, 0x01, 0x0C, 0x83, 0x5D, 0x01, 0x12, 0x84, 0x01, 0x01, 0x06, 0x84, 0x25, 0xA6, 0xA7, 0xB0, 0x01, 0x83, 0x54, 0x84, 0x01, 0xE6, 0xE6, 0xE8, 0x01, 0x0F, 0x8B, 0x5F, 0x01, 0x15, 0x84, 0x01, 0x9A, 0x9B, 0xA5, 0xD9, 0xD9, 0xDD, 0x01, 0x83, 0x51, 0x83, 0x7E, 0x4D, 0x4F, 0x62, 0xFF, 0xFF, 0xFF, 0x5A, 0x5C, 0x6D, 0x01, 0x21, 0x84, 0x01, 0x67, 0x68, 0x78, 0xFF, 0xFF, 0xFF, 0x01, 0x83, 0x54, 0x9B, 0x75, 0x01, 0x12, 0x83, 0x57, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x83, 0x6C, 0x84, 0x01, 0x01, 0x2A, 0x8C, 0x03, 0xA6, 0xA7, 0xB0, 0x01, 0x12, 0x15, 0x01, 0x83, 0x6C, 0x94, 0x05, 0xE6, 0xE6, 0xE8, 0x01, 0x83, 0x57, 0x98, 0x06, 0x01, 0x06, 0xA8, 0x01, 0x41, 0x43, 0x56, 0x01, 0x1B, 0x84, 0x01, 0x8D, 0x8E, 0x9A, 0x01, 0x83, 0x5A, 0xA0, 0x08, 0x01, 0x09, 0xA4, 0x09, 0x01, 0x09, 0x84, 0x04, 0x01, 0x0F, 0x84, 0x01, 0x80, 0x82, 0x8F, 0xFF, 0xFF, 0xFF, 0x01, 0x83, 0x5D, 0xA8, 0x0A, 0x01, 0x0C, 0xAC, 0x0B, 0x4D, 0x4F, 0x62, 0x01, 0x09, 0x84, 0x01, 0x67, 0x68, 0x78, 0xB3, 0xB3, 0xBB, 0xFF, 0xFF, 0xFF, 0xB3, 0xB3, 0xBB, 0x01, 0x83, 0x63, 0xB4, 0x0D, 0xA6, 0xA7, 0xB0, 0x01, 0x06, 0xB4, 0x0A, 0x01, 0x06, 0x06, 0x01, 0x06, 0x06, 0xE6, 0xE6, 0xE8, 0x01, 0x83, 0x6C, 0xB8, 0x1A, 0x41, 0x43, 0x56, 0x74, 0x75, 0x83, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x01, 0x83, 0x60, 0xB8, 0x05, 0x01, 0x8C, 0x06, 0xCC, 0x01, 0x5A, 0x5C, 0x6D, 0xCC, 0xCD, 0xD2, 0x01, 0x0F, 0xA8, 0x0A, 0x01, 0x83, 0x6C, 0x84, 0x01, 0x01, 0x06, 0xAC, 0x0B, 0x01, 0x83, 0x7E, 0x88, 0x05, 0xE6, 0xE6, 0xE8, 0x74, 0x75, 0x83, 0x01, 0x83, 0x7B, 0x84, 0x01, 0x01, 0x15, 0xAF, 0x7A, 0x01, 0x83, 0x6F, 0x84, 0x04, 0x01, 0x83, 0x5A, 0xCB, 0x6F, 0x01, 0x2A, 0x2A, 0x01, 0x06, 0xBB, 0x6E, 0x74, 0x75, 0x83, 0x01, 0x0C, 0xB4, 0x16, 0x01, 0x83, 0x69, 0x98, 0x06, 0xCC, 0xCD, 0xD2, 0xCC, 0xCD, 0xD2, 0xD9, 0xD9, 0xDD, 0x01, 0x12, 0xAC, 0x0B, 0x01, 0x0F, 0x0F, 0x01, 0x83, 0x54, 0x98, 0x06, 0x01, 0x09, 0xAB, 0x79, 0x01, 0x09, 0x09, 0x01, 0x12, 0x12, 0x01, 0x09, 0x09, 0x01, 0x97, 0x6B, 0x81, 0x80, 0x23, 0x5A, 0x5C, 0x6D, 0x01, 0x83, 0x75, 0xB4, 0x1F, 0x67, 0x68, 0x78, 0xBF, 0xC0, 0xC7, 0x01, 0x15, 0x81, 0x80, 0x20, 0x01, 0x83, 0x63, 0xA4, 0x1E, 0x01, 0x06, 0xD3, 0x7D, 0xCC, 0xCD, 0xD2, 0x8D, 0x8E, 0x9A, 0xB3, 0xB3, 0xBB, 0x01, 0x12, 0x81, 0x80, 0x20, 0x01, 0x83, 0x5D, 0xB4, 0x31, 0xB3, 0xB3, 0xBB, 0x01, 0x0C, 0x83, 0x63, 0x01, 0x12, 0xB4, 0x1F, 0x01, 0x12, 0xE0, 0x3C, 0x01, 0x83, 0x4B, 0x83, 0x7E, 0x01, 0x06, 0x81, 0x83, 0x7D, 0x01, 0x0C, 0xD4, 0x00, 0x01, 0x18, 0xE8, 0x1A, 0x8D, 0x8E, 0x9A, 0x01, 0x83, 0x54, 0x84, 0x01, 0xCC, 0xCD, 0xD2, 0x01, 0x0F, 0xDF, 0x77, 0x01, 0x83, 0x66, 0xF0, 0x1C, 0x01, 0x06, 0xEB, 0x68, 0x41, 0x43, 0x56, 0x01, 0x0F, 0x87, 0x7F, 0x01, 0x18, 0x84, 0x01, 0x01, 0x06, 0x88, 0x29, 0x01, 0x83, 0x4B, 0x97, 0x71, 0x01, 0x06, 0xB3, 0x5A, 0x01, 0x83, 0x75, 0xFC, 0x1F, 0x01, 0x06, 0x97, 0x56, 0x01, 0x06, 0x87, 0x76, 0x01, 0x83, 0x75, 0x84, 0x01, 0x01, 0x0C, 0xC8, 0x00, 0x5A, 0x5C, 0x6D, 0x01, 0x12, 0xF7, 0x77, 0x01, 0x15, 0x84, 0x01, 0x8D, 0x8E, 0x9A, 0x01, 0x83, 0x45, 0x81, 0x90, 0x24, 0xA6, 0xA7, 0xB0, 0xE6, 0xE6, 0xE8, 0x01, 0x0C, 0x9B, 0x51, 0xF2, 0xF2, 0xF4, 0x01, 0x0F, 0xEF, 0x7E, 0x01, 0x18, 0x81, 0x98, 0x26, 0x01, 0x3C, 0xF4, 0x23, 0x5D, 0x5E, 0x6F, 0xE4, 0xE4, 0xE7, 0x5D, 0x5E, 0x6F, 0x78, 0x79, 0x87, 0x01, 0x83, 0x00, 0x97, 0x74, 0x01, 0x0F, 0x93, 0x73, 0xB3, 0xB3, 0xBB, 0xE6, 0xE6, 0xE8, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x06, 0x8C, 0x00, 0x01, 0x3C, 0xF0, 0x2B, 0xF1, 0xF2, 0xF3, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x94, 0x74, 0x01, 0x82, 0x2C, 0xF7, 0x2F, 0x01, 0x51, 0xA2, 0x7C, 0x01, 0x12, 0xA7, 0x51, 0x01, 0x06, 0x90, 0x13, 0x01, 0x0C, 0x87, 0x5E, 0x01, 0x0F, 0x84, 0x01, 0x5A, 0x5C, 0x6D, 0xF2, 0xF2, 0xF4, 0xBF, 0xC0, 0xC7, 0x01, 0x3C, 0x78, 0x01, 0x09, 0xCC, 0x52, 0x01, 0x81, 0x6A, 0x84, 0x01, 0x5A, 0x5C, 0x6D, 0x67, 0x68, 0x78, 0x01, 0x39, 0x83, 0x42, 0x01, 0x06, 0xAF, 0x17, 0x01, 0x66, 0xCB, 0x06, 0x01, 0x06, 0x83, 0x63, 0x01, 0x09, 0x88, 0x1D, 0x01, 0x0C, 0x84, 0x01, 0x80, 0x82, 0x8F, 0xF2, 0xF2, 0xF4, 0x01, 0x0C, 0x81, 0x84, 0x3F, 0x01, 0x3C, 0x88, 0x02, 0x93, 0x94, 0x9F, 0xE4, 0xE4, 0xE7, 0x01, 0x81, 0x6A, 0x8A, 0x6D, 0x01, 0x3C, 0x8A, 0x37, 0x01, 0x06, 0xE7, 0x34, 0xF2, 0xF2, 0xF4, 0x01, 0x69, 0x85, 0x2F, 0x01, 0x06, 0xD4, 0x15, 0xE6, 0xE6, 0xE8, 0xE6, 0xE6, 0xE8, 0x01, 0x06, 0x84, 0x10, 0x01, 0x06, 0x87, 0x37, 0xB3, 0xB3, 0xBB, 0x01, 0x42, 0x89, 0x09, 0x5D, 0x5E, 0x6F, 0xD6, 0xD7, 0xDB, 0xC9, 0xC9, 0xCF, 0x4F, 0x51, 0x63, 0x01, 0x82, 0x26, 0x84, 0x01, 0x01, 0x06, 0x92, 0x78, 0x01, 0x12, 0x81, 0x97, 0x43, 0x01, 0x60, 0xAC, 0x17, 0x01, 0x06, 0xA7, 0x72, 0x01, 0x06, 0xD8, 0x28, 0x01, 0x06, 0x81, 0x88, 0x31, 0x01, 0x82, 0x3B, 0x92, 0x6F, 0x01, 0x3F, 0x84, 0x01, 0x01, 0x06, 0x8C, 0x06, 0x01, 0x81, 0x46, 0x81, 0x83, 0x26, 0xA0, 0xA1, 0xAB, 0x4F, 0x51, 0x63, 0x4F, 0x51, 0x63, 0x93, 0x94, 0x9F, 0x01, 0x82, 0x29, 0x84, 0x01, 0x01, 0x06, 0xBB, 0x23, 0x01, 0x81, 0x46, 0xB3, 0x03, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x81, 0x6A, 0x94, 0x05, 0x01, 0x42, 0x84, 0x01, 0x01, 0x42, 0x42, 0x01, 0x83, 0x3C, 0x84, 0x01, 0x01, 0x06, 0x9E, 0x33, 0x01, 0x6F, 0x90, 0x04, 0x01, 0x5A, 0x5A, 0x85, 0x86, 0x93, 0x01, 0x06, 0x81, 0x4F, 0x85, 0x86, 0x93, 0x01, 0x82, 0x23, 0x84, 0x01, 0x41, 0x43, 0x56, 0x01, 0x06, 0x90, 0x01, 0x01, 0x0F, 0xA3, 0x23, 0x01, 0x81, 0x40, 0xA1, 0x5A, 0x01, 0x81, 0x61, 0xC4, 0x53, 0x67, 0x68, 0x78, 0x67, 0x68, 0x78, 0x01, 0x06, 0x06, 0x01, 0x06, 0x97, 0x44, 0x8D, 0x8E, 0x9A, 0x01, 0x0C, 0x15, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x8D, 0x8E, 0x9A, 0xE6, 0xE6, 0xE8, 0x01, 0x06, 0x86, 0x30, 0x01, 0x72, 0xCB, 0x09, 0x01, 0x1E, 0x81, 0x1C, 0x01, 0x82, 0x20, 0x97, 0x7A, 0x01, 0x21, 0xF2, 0x5D, 0x01, 0x21, 0x21, 0x01, 0x0C, 0x0C, 0x01, 0x6C, 0x81, 0xA3, 0x1F, 0x74, 0x75, 0x83, 0x01, 0x5D, 0xF4, 0x1D, 0x01, 0x81, 0x67, 0x8F, 0x7B, 0x01, 0x48, 0x83, 0x7B, 0xD9, 0xD9, 0xDD, 0x01, 0x6C, 0x87, 0x7C, 0x01, 0x06, 0x98, 0x6F, 0x01, 0x06, 0x81, 0xB4, 0x36, 0x74, 0x75, 0x83, 0x01, 0x54, 0x88, 0x02, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0xA8, 0x0D, 0xF1, 0xF2, 0xF3, 0x01, 0x82, 0x20, 0x8C, 0x03, 0x01, 0x75, 0xD0, 0x14, 0x01, 0x60, 0x81, 0x84, 0x21, 0x01, 0x06, 0xA0, 0x05, 0x01, 0x06, 0x06, 0x01, 0x82, 0x29, 0x9C, 0x07, 0x01, 0x69, 0xC0, 0x1F, 0x01, 0x3F, 0xB3, 0x69, 0x01, 0x82, 0x59, 0xA8, 0x0A, 0x01, 0x66, 0x97, 0x1A, 0x01, 0x66, 0x94, 0x6B, 0x01, 0x06, 0x8C, 0x00, 0x01, 0x81, 0x61, 0x8C, 0x03, 0x01, 0x81, 0x31, 0x84, 0x01, 0x01, 0x69, 0xCB, 0x69, 0x01, 0x06, 0x8B, 0x7D, 0x6A, 0x6C, 0x7B, 0x01, 0x81, 0x6A, 0x84, 0x01, 0x01, 0x06, 0xB2, 0x56, 0x01, 0x81, 0x1F, 0xA3, 0x47, 0x01, 0x72, 0xCF, 0x6A, 0x01, 0x83, 0x0F, 0xD0, 0x59, 0x01, 0x06, 0xD0, 0x14, 0x01, 0x63, 0xA3, 0x20, 0x01, 0x09, 0x98, 0x03, 0xC9, 0xC9, 0xCF, 0x01, 0x83, 0x75, 0x81, 0xA4, 0x29, 0x01, 0x81, 0x70, 0x98, 0x03, 0x01, 0x85, 0x2C, 0x81, 0xA4, 0x29, 0x01, 0x06, 0x81, 0xCC, 0x30, 0x01, 0x60, 0x81, 0xC8, 0x17, 0x4F, 0x51, 0x63, 0xC9, 0xC9, 0xCF, 0x01, 0x81, 0x6D, 0xC8, 0x12, 0x01, 0x81, 0x2E, 0x84, 0x04, 0xCC, 0xCD, 0xD2, 0x01, 0x54, 0xD5, 0x04, 0x01, 0x09, 0x09, 0xE4, 0xE4, 0xE7, 0x85, 0x86, 0x93, 0x85, 0x86, 0x93, 0x01, 0x51, 0xD0, 0x14, 0x4D, 0x4F, 0x62, 0x01, 0x06, 0x81, 0xC9, 0x66, 0x01, 0x06, 0xA6, 0x74, 0x01, 0x81, 0x2B, 0xEB, 0x1A, 0x01, 0x09, 0x81, 0x9E, 0x7D, 0x80, 0x82, 0x8F, 0x01, 0x66, 0x98, 0x2D, 0x01, 0x0C, 0x81, 0xA4, 0x17, 0x01, 0x09, 0x09, 0x01, 0x09, 0x09, 0x01, 0x09, 0xAD, 0x06, 0x01, 0x1B, 0x24, 0x01, 0x81, 0x0D, 0xC0, 0x10, 0x01, 0x06, 0x81, 0x4F, 0x01, 0x09, 0xAE, 0x40, 0xFD, 0xFE, 0xFE, 0xFB, 0xFD, 0xFE, 0xF9, 0xFB, 0xFD, 0xC6, 0xC9, 0xD0, 0x90, 0x99, 0xA8, 0x6F, 0x72, 0x82, 0x01, 0x81, 0x10, 0xB8, 0x7D, 0x4D, 0x4F, 0x62, 0x01, 0x06, 0xAE, 0x76, 0x01, 0x15, 0xB0, 0x00, 0x01, 0x06, 0xAF, 0x0B, 0x01, 0x5D, 0x81, 0x34, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x1B, 0x1B, 0x01, 0x42, 0x84, 0x01, 0x01, 0x51, 0x88, 0x02, 0x01, 0x06, 0xD9, 0x2F, 0x01, 0x0C, 0x82, 0x41, 0x01, 0x09, 0x84, 0x01, 0xF7, 0xFA, 0xFC, 0xF4, 0xF8, 0xFB, 0xF2, 0xF7, 0xFA, 0xF0, 0xF5, 0xF9, 0xCB, 0xD0, 0xD8, 0xA6, 0xAC, 0xB7, 0x78, 0x7C, 0x8B, 0x56, 0x59, 0x6B, 0x01, 0x81, 0x10, 0x81, 0xD7, 0x14, 0xE6, 0xE6, 0xE8, 0x01, 0x0C, 0x85, 0x41, 0x01, 0x06, 0x06, 0x01, 0x81, 0x58, 0x81, 0x87, 0x0C, 0x01, 0x4E, 0x90, 0x04, 0x01, 0x15, 0x81, 0xD9, 0x61, 0x01, 0x15, 0x84, 0x01, 0xEE, 0xF4, 0xF9, 0xEE, 0xF4, 0xF9, 0xE8, 0xF0, 0xF7, 0xE7, 0xEF, 0xF6, 0xDA, 0xE2, 0xEA, 0xAC, 0xB4, 0xBF, 0x8A, 0x90, 0x9F, 0x5E, 0x63, 0x75, 0x01, 0x72, 0x92, 0x66, 0x01, 0x0C, 0x87, 0x67, 0x01, 0x0F, 0x8B, 0x71, 0x01, 0x06, 0x81, 0xD7, 0x2C, 0x01, 0x0C, 0x88, 0x1D, 0x01, 0x82, 0x1A, 0x81, 0xB7, 0x3C, 0x01, 0x06, 0x91, 0x2F, 0x01, 0x15, 0x8A, 0x43, 0x01, 0x18, 0x84, 0x01, 0xEA, 0xF2, 0xF8, 0xEA, 0xF2, 0xF8, 0xE7, 0xEF, 0xF6, 0xE5, 0xEE, 0xF5, 0xE2, 0xED, 0xF4, 0xE0, 0xEB, 0xF3, 0xDE, 0xEA, 0xF3, 0xDB, 0xE8, 0xF2, 0xAC, 0xC7, 0xE1, 0x90, 0x99, 0xA8, 0x61, 0x6C, 0x83, 0x49, 0x4B, 0x5C, 0x01, 0x66, 0x83, 0x7E, 0x01, 0x21, 0xE3, 0x66, 0x01, 0x09, 0xDF, 0x1D, 0x01, 0x81, 0x58, 0x81, 0xE7, 0x2A, 0x01, 0x3F, 0x8D, 0x61, 0x5A, 0x5C, 0x6D, 0xE6, 0xE6, 0xE9, 0x01, 0x18, 0x8E, 0x44, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x06, 0x88, 0x02, 0x01, 0x0F, 0x84, 0x01, 0xD9, 0xE7, 0xF1, 0xD7, 0xE5, 0xF0, 0xD5, 0xE4, 0xEF, 0xD2, 0xE2, 0xEE, 0xBB, 0xD2, 0xE4, 0x94, 0xA0, 0xB0, 0x76, 0x7F, 0x91, 0x50, 0x55, 0x69, 0x01, 0x51, 0xAC, 0x11, 0x01, 0x06, 0x8B, 0x59, 0x01, 0x2A, 0x95, 0x21, 0x01, 0x09, 0x88, 0x0B, 0x01, 0x81, 0x46, 0xC7, 0x02, 0xBB, 0xBC, 0xC3, 0x85, 0x86, 0x93, 0x01, 0x06, 0xB4, 0x76, 0x01, 0x3C, 0xA8, 0x0A, 0x01, 0x12, 0x8F, 0x75, 0x01, 0x4B, 0x84, 0x01, 0xD0, 0xE1, 0xED, 0xCE, 0xDF, 0xED, 0xCC, 0xDE, 0xEC, 0xC9, 0xDC, 0xEB, 0xBB, 0xD2, 0xE4, 0x7D, 0x88, 0x01, 0x46, 0xDB, 0x0A, 0x01, 0x06, 0xAE, 0x6A, 0xFF, 0xFF, 0xFF, 0x01, 0x30, 0x9E, 0x66, 0x01, 0x06, 0x89, 0x66, 0x01, 0x81, 0x46, 0xD0, 0x11, 0x01, 0x06, 0x97, 0x77, 0xBB, 0xBC, 0xC3, 0xA0, 0xA1, 0xAB, 0x01, 0x39, 0x98, 0x06, 0x01, 0x15, 0x8F, 0x75, 0x01, 0x30, 0x90, 0x04, 0x01, 0x27, 0x84, 0x01, 0xC7, 0xDB, 0xEA, 0xC5, 0xDA, 0xE9, 0xA8, 0xBA, 0xCB, 0x3F, 0x41, 0x01, 0x40, 0x97, 0x11, 0x01, 0x06, 0xD3, 0x59, 0x01, 0x33, 0xCB, 0x5A, 0x4D, 0x4F, 0x62, 0x01, 0x06, 0x85, 0x6E, 0x01, 0x81, 0x43, 0x81, 0xEB, 0x37, 0xD6, 0xD7, 0xDB, 0x01, 0x09, 0xBC, 0x06, 0x93, 0x94, 0x9F, 0xD6, 0xD7, 0xDB, 0x01, 0x48, 0x8F, 0x75, 0x01, 0x3F, 0x90, 0x04, 0x01, 0x1E, 0x84, 0x01, 0xC3, 0xD8, 0xE8, 0x9D, 0xAF, 0xC1, 0x01, 0x42, 0xBE, 0x6B, 0x01, 0x39, 0x81, 0xFA, 0x76, 0x01, 0x06, 0x85, 0x74, 0x01, 0x6C, 0xC3, 0x2B, 0x4D, 0x4F, 0x62, 0xA6, 0xA7, 0xB0, 0x01, 0x0C, 0xD0, 0x1A, 0x01, 0x06, 0x81, 0xA0, 0x37, 0x01, 0x42, 0x9D, 0x1A, 0x01, 0x09, 0x42, 0x01, 0x30, 0x98, 0x03, 0x01, 0x1E, 0x8F, 0x75, 0x01, 0x57, 0x8C, 0x03, 0x01, 0x09, 0x84, 0x01, 0xC0, 0xD6, 0xE9, 0x61, 0x6C, 0x01, 0x3A, 0x9B, 0x12, 0x01, 0x06, 0x81, 0xFA, 0x76, 0x01, 0x39, 0x83, 0x42, 0x01, 0x06, 0xF4, 0x1D, 0x01, 0x69, 0xBA, 0x3D, 0x01, 0x09, 0x8E, 0x62, 0xBF, 0xC0, 0xC7, 0x01, 0x09, 0xA5, 0x22, 0x01, 0x09, 0xF4, 0x2F, 0x01, 0x75, 0xBD, 0x55, 0x01, 0x21, 0x8F, 0x75, 0x01, 0x5D, 0x84, 0x01, 0xBB, 0xD2, 0xE4, 0x94, 0xB3, 0xD9, 0x7A, 0x94, 0xC2, 0x01, 0x3F, 0x93, 0x7F, 0x01, 0x3C, 0xEB, 0x59, 0x01, 0x06, 0xDC, 0x1D, 0x01, 0x63, 0x94, 0x0B, 0x01, 0x09, 0x85, 0x2C, 0x01, 0x12, 0x89, 0x2D, 0x01, 0x06, 0xD1, 0x5D, 0xF2, 0xF2, 0xF4, 0x01, 0x6F, 0x84, 0x04, 0x01, 0x24, 0x8F, 0x75, 0x01, 0x5A, 0x90, 0x04, 0xAC, 0xC7, 0xE1, 0x88, 0xA9, 0xD5, 0x84, 0xA3, 0xD3, 0x83, 0xA0, 0xD2, 0x51, 0x5D, 0x7D, 0x01, 0x81, 0x5E, 0xEC, 0x1B, 0x01, 0x06, 0x88, 0x6B, 0x01, 0x1B, 0x91, 0x29, 0x01, 0x06, 0x9D, 0x4A, 0x01, 0x69, 0x95, 0x12, 0x01, 0x2A, 0x8F, 0x75, 0x01, 0x54, 0x90, 0x04, 0xC5, 0xD9, 0xEA, 0x9F, 0xBC, 0xDD, 0x86, 0xA7, 0xD4, 0x85, 0xA4, 0xD3, 0x83, 0xA1, 0xD2, 0x82, 0x9F, 0xD2, 0x6D, 0x83, 0xAF, 0x01, 0x78, 0x83, 0x3F, 0x01, 0x42, 0x88, 0x44, 0x01, 0x27, 0x9C, 0x76, 0x01, 0x21, 0x83, 0x5D, 0x01, 0x06, 0x84, 0x25, 0x01, 0x63, 0x95, 0x12, 0x01, 0x2D, 0x8F, 0x75, 0x01, 0x51, 0x8C, 0x03, 0xC4, 0xD8, 0xE9, 0x94, 0xB3, 0xD9, 0x87, 0xA8, 0xD4, 0x85, 0xA5, 0xD3, 0x84, 0xA2, 0xD3, 0x83, 0xA0, 0xD2, 0x81, 0x9D, 0xD1, 0x80, 0x9B, 0xD0, 0x4E, 0x55, 0x6F, 0x01, 0x7B, 0xF8, 0x1E, 0x01, 0x60, 0xAC, 0x1A, 0x01, 0x12, 0x81, 0x94, 0x25, 0x01, 0x18, 0x81, 0x0D, 0x01, 0x60, 0x95, 0x12, 0x01, 0x30, 0x8F, 0x75, 0x01, 0x4E, 0x84, 0x01, 0xC0, 0xD6, 0xE9, 0x8D, 0xAF, 0xD7, 0x87, 0xA9, 0xD5, 0x86, 0xA6, 0x01, 0x08, 0x87, 0x7F, 0x9E, 0xD1, 0x80, 0x9C, 0xD1, 0x7F, 0x99, 0xD0, 0x6A, 0x7C, 0xAD, 0x01, 0x39, 0x83, 0x3F, 0x01, 0x81, 0x1F, 0x8C, 0x03, 0x01, 0x15, 0x81, 0x9C, 0x27, 0x01, 0x1B, 0x83, 0x1E, 0x01, 0x3C, 0xF4, 0x1D, 0xE4, 0xE4, 0xE7, 0x01, 0x1B, 0xD8, 0x16, 0x01, 0x33, 0x8F, 0x75, 0x01, 0x4B, 0x90, 0x04, 0xB6, 0xD0, 0xE6, 0x88, 0xAB, 0xD5, 0x88, 0xAA, 0xD5, 0x87, 0xA7, 0x01, 0x07, 0x87, 0x7F, 0x82, 0x9F, 0xD2, 0x81, 0x9D, 0xD1, 0x7F, 0x9A, 0xD0, 0x7E, 0x96, 0xCF, 0x7D, 0x95, 0xCF, 0x46, 0x4E, 0x6C, 0x01, 0x33, 0x82, 0xB3, 0x25, 0x01, 0x45, 0x94, 0x05, 0x01, 0x5D, 0x81, 0x87, 0x24, 0x01, 0x2A, 0xD4, 0x15, 0x01, 0x3F, 0xD4, 0x3F, 0xFF, 0xFF, 0xFF, 0x6A, 0x6C, 0x7B, 0x01, 0x15, 0xCC, 0x16, 0x01, 0x39, 0x8F, 0x75, 0x01, 0x48, 0x90, 0x04, 0xB8, 0xCF, 0xE5, 0x8A, 0xAE, 0xD6, 0x89, 0xAB, 0xD5, 0x87, 0xA8, 0xD4, 0x86, 0xA6, 0xD4, 0x01, 0x06, 0x93, 0x7C, 0x81, 0x9E, 0xD1, 0x80, 0x9B, 0xD0, 0x7F, 0x98, 0xD0, 0x7D, 0x96, 0xCF, 0x7C, 0x93, 0xCE, 0x01, 0x33, 0x88, 0x05, 0x01, 0x06, 0x86, 0x5D, 0x01, 0x39, 0x8A, 0x37, 0x01, 0x06, 0x3F, 0x01, 0x60, 0x92, 0x7B, 0x01, 0x81, 0x04, 0x84, 0x01, 0x01, 0x24, 0xF1, 0x14, 0x01, 0x5A, 0x8C, 0x03, 0xA7, 0xC5, 0xE0, 0x8B, 0xAF, 0xD6, 0x89, 0xAC, 0xD5, 0x88, 0xAA, 0xD5, 0x01, 0x07, 0x93, 0x7C, 0xA2, 0xD2, 0x82, 0x9F, 0xD2, 0x81, 0x01, 0x05, 0x8B, 0x7D, 0x7E, 0x97, 0xCF, 0x7C, 0x94, 0xCF, 0x7B, 0x92, 0xCE, 0x79, 0x8E, 0xCD, 0x01, 0x33, 0x88, 0x05, 0x01, 0x06, 0x85, 0x59, 0x01, 0x36, 0x87, 0x43, 0x01, 0x06, 0x8C, 0x42, 0x01, 0x63, 0xB8, 0x17, 0x01, 0x27, 0x8C, 0x66, 0x01, 0x3F, 0x81, 0xA8, 0x2A, 0x01, 0x18, 0xE4, 0x19, 0x9A, 0x9B, 0xA5, 0x01, 0x48, 0xF2, 0x51, 0x01, 0x33, 0x84, 0x01, 0xA7, 0xC5, 0xE0, 0x8B, 0xB0, 0xD7, 0x8A, 0xAD, 0xD6, 0x88, 0x01, 0x05, 0x87, 0x7F, 0x85, 0xA5, 0xD3, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x05, 0x93, 0x7C, 0x7E, 0x98, 0xD0, 0x7D, 0x95, 0xCF, 0x7C, 0x93, 0xCE, 0x7A, 0x90, 0xCD, 0x79, 0x8D, 0xCD, 0x62, 0x70, 0xA4, 0x01, 0x36, 0x86, 0x60, 0x01, 0x33, 0x88, 0x05, 0x01, 0x09, 0xA4, 0x06, 0x01, 0x63, 0x81, 0x93, 0x24, 0xBF, 0xC0, 0xC7, 0x01, 0x24, 0x84, 0x67, 0x01, 0x57, 0x81, 0xF4, 0x61, 0x01, 0x39, 0x97, 0x74, 0x01, 0x42, 0x90, 0x04, 0xAF, 0xCA, 0xE3, 0x8C, 0xB0, 0xD7, 0x8A, 0xAE, 0xD6, 0x89, 0xAC, 0xD5, 0x01, 0x0D, 0x93, 0x7C, 0x9F, 0xD2, 0x01, 0x06, 0x93, 0x7C, 0x7E, 0x96, 0xCF, 0x7C, 0x94, 0xCF, 0x7A, 0x90, 0xCD, 0x79, 0x8E, 0xCD, 0x78, 0x8C, 0xCC, 0x76, 0x89, 0xCC, 0x3C, 0x40, 0x5B, 0x01, 0x36, 0x87, 0x49, 0x01, 0x2D, 0x9A, 0x41, 0x01, 0x09, 0xBC, 0x42, 0x01, 0x66, 0xC0, 0x16, 0x01, 0x15, 0x82, 0xB0, 0x4F, 0x01, 0x15, 0x94, 0x02, 0x01, 0x51, 0x85, 0x0E, 0x01, 0x06, 0x8D, 0x67, 0x01, 0x63, 0x88, 0x02, 0x01, 0x12, 0x90, 0x04, 0xC0, 0xD6, 0xE9, 0x8C, 0xB2, 0xD7, 0x01, 0x07, 0x87, 0x7F, 0xAA, 0x01, 0x08, 0x87, 0x7F, 0x01, 0x11, 0x93, 0x7C, 0x7B, 0x92, 0xCE, 0x7A, 0x90, 0xCD, 0x78, 0x8D, 0xCD, 0x77, 0x8A, 0xCC, 0x76, 0x88, 0xCB, 0x5D, 0x67, 0xA1, 0x01, 0x39, 0xC0, 0x10, 0x01, 0x27, 0x84, 0x04, 0x01, 0x09, 0x30, 0x01, 0x42, 0x81, 0xA3, 0x1C, 0x01, 0x2D, 0x9B, 0x00, 0xD9, 0xD9, 0xDD, 0x01, 0x18, 0x84, 0x04, 0x74, 0x75, 0x83, 0x01, 0x27, 0x9C, 0x2B, 0x01, 0x1B, 0x1B, 0x6A, 0x6C, 0x7B, 0x01, 0x12, 0x81, 0xB0, 0x2C, 0x01, 0x09, 0xBA, 0x2E, 0x01, 0x6F, 0x8C, 0x03, 0xC0, 0xD6, 0xE9, 0x8D, 0xB3, 0xD7, 0x8C, 0xB2, 0x01, 0x05, 0x87, 0x7F, 0xAB, 0xD5, 0x87, 0xA9, 0x01, 0x08, 0x93, 0x7C, 0x01, 0x05, 0x9B, 0x7B, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x06, 0x93, 0x7C, 0x7A, 0x91, 0xCE, 0x79, 0x8E, 0xCD, 0x78, 0x8B, 0xCC, 0x76, 0x88, 0xCB, 0x75, 0x86, 0xCB, 0x73, 0x83, 0xCA, 0x01, 0x33, 0x88, 0x05, 0x01, 0x09, 0x81, 0x8B, 0x70, 0x01, 0x21, 0xD6, 0x77, 0x67, 0x68, 0x78, 0x01, 0x06, 0x97, 0x7A, 0x01, 0x6C, 0x83, 0x7E, 0x01, 0x0C, 0xAB, 0x73, 0x01, 0x0F, 0x81, 0xA0, 0x19, 0x5A, 0x5C, 0x6D, 0x01, 0x33, 0x89, 0x42, 0x01, 0x2A, 0x81, 0xB0, 0x2C, 0x01, 0x75, 0x84, 0x01, 0xD1, 0xE1, 0xEF, 0x8E, 0xB4, 0xD8, 0x8C, 0xB2, 0xD7, 0x01, 0x05, 0x93, 0x7C, 0xD6, 0x01, 0x13, 0x93, 0x7C, 0x9A, 0x01, 0x0A, 0x93, 0x7C, 0x7A, 0x8F, 0x01, 0x07, 0x87, 0x7F, 0x75, 0x87, 0xCB, 0x74, 0x85, 0xCA, 0x72, 0x82, 0xC9, 0x5B, 0x65, 0x01, 0x37, 0x9B, 0x57, 0x01, 0x06, 0x8A, 0x46, 0x01, 0x06, 0x81, 0xAF, 0x16, 0x01, 0x0F, 0x81, 0xFF, 0x27, 0x4D, 0x4F, 0x62, 0x80, 0x82, 0x8F, 0x01, 0x09, 0x9A, 0x0B, 0xBF, 0xC0, 0xC7, 0x01, 0x69, 0x83, 0x7E, 0x01, 0x0F, 0xD4, 0x27, 0x01, 0x30, 0x82, 0x74, 0x01, 0x2A, 0xC9, 0x37, 0x01, 0x15, 0x81, 0xB0, 0x2C, 0x01, 0x66, 0x84, 0x01, 0x01, 0x0C, 0x90, 0x04, 0xDA, 0xE7, 0xF2, 0x94, 0xB3, 0xD9, 0x8D, 0xB3, 0x01, 0x05, 0x8B, 0x7D, 0xAE, 0x01, 0x07, 0x93, 0x7C, 0x01, 0x0A, 0x9B, 0x7B, 0x01, 0x05, 0x8B, 0x7D, 0x7F, 0x01, 0x0C, 0x93, 0x7C, 0x8E, 0xCD, 0x76, 0x89, 0xCC, 0x76, 0x88, 0xCB, 0x74, 0x01, 0x05, 0x87, 0x7F, 0x71, 0x7F, 0xC9, 0x70, 0x7E, 0xC8, 0x39, 0x3C, 0x5A, 0x01, 0x2A, 0x98, 0x03, 0x01, 0x4E, 0x81, 0x8C, 0x35, 0x01, 0x0F, 0x0F, 0x01, 0x42, 0xA4, 0x24, 0x01, 0x30, 0x81, 0xFC, 0x3F, 0x01, 0x0F, 0x0F, 0x01, 0x2A, 0x81, 0x01, 0xA0, 0xA1, 0xAB, 0x01, 0x12, 0x81, 0x98, 0x26, 0x01, 0x69, 0x88, 0x02, 0x01, 0x09, 0x90, 0x04, 0x9E, 0xC0, 0xDD, 0x8D, 0xB4, 0xD8, 0x8C, 0xB0, 0x01, 0x06, 0x87, 0x7F, 0xD5, 0x88, 0xA9, 0x01, 0x08, 0x87, 0x7F, 0x01, 0x0C, 0x93, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x7A, 0x91, 0x01, 0x05, 0x8F, 0x7E, 0x8C, 0xCC, 0x01, 0x0A, 0x87, 0x7F, 0x81, 0xC9, 0x71, 0x7F, 0xC9, 0x6F, 0x7B, 0xC8, 0x01, 0x27, 0x88, 0x05, 0x01, 0x81, 0x25, 0x84, 0x01, 0x01, 0x7E, 0xD0, 0x11, 0x01, 0x6F, 0x8C, 0x03, 0xB6, 0xCD, 0xE5, 0x8E, 0xB6, 0x01, 0x05, 0x8B, 0x7D, 0x01, 0x11, 0x93, 0x7C, 0x01, 0x0F, 0x9B, 0x7B, 0x01, 0x0F, 0x93, 0x7C, 0x74, 0x85, 0xCA, 0x73, 0x83, 0xCA, 0x71, 0x80, 0xC9, 0x70, 0x7D, 0xC8, 0x6F, 0x7B, 0xC8, 0x6D, 0x78, 0xC7, 0x38, 0x3A, 0x53, 0x01, 0x24, 0x8B, 0x74, 0x01, 0x3C, 0x86, 0x5D, 0x01, 0x24, 0x24, 0x01, 0x12, 0x97, 0x17, 0x8D, 0x8E, 0x9A, 0x01, 0x81, 0x2B, 0x81, 0xA0, 0x58, 0x01, 0x6C, 0x84, 0x01, 0xCB, 0xDD, 0xED, 0x94, 0xB3, 0xD9, 0x8D, 0x01, 0x05, 0x8F, 0x7E, 0x01, 0x15, 0x93, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x7D, 0x96, 0xCF, 0x7C, 0x94, 0xCE, 0x01, 0x06, 0xA3, 0x7A, 0x78, 0x8B, 0xCC, 0x76, 0x89, 0xCC, 0x75, 0x86, 0xCB, 0x73, 0x84, 0x01, 0x05, 0x87, 0x7F, 0x7E, 0xC8, 0x6F, 0x7B, 0xC8, 0x6E, 0x79, 0xC7, 0x6C, 0x76, 0xC6, 0x51, 0x57, 0x8B, 0x01, 0x81, 0x1C, 0x82, 0x88, 0x12, 0xBF, 0xC0, 0xC7, 0x01, 0x81, 0x10, 0xCC, 0x4C, 0x01, 0x09, 0x81, 0xB8, 0x2E, 0x5D, 0x5E, 0x01, 0x0A, 0xB6, 0x5A, 0x01, 0x69, 0x90, 0x04, 0xE1, 0xE9, 0xF4, 0x95, 0xBB, 0xDA, 0x01, 0x09, 0x93, 0x7C, 0x8A, 0xAE, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x12, 0xAF, 0x77, 0x97, 0xCF, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x0E, 0x93, 0x7C, 0x01, 0x07, 0x8F, 0x7E, 0x7D, 0xC8, 0x6E, 0x7A, 0xC7, 0x6D, 0x78, 0xC7, 0x6C, 0x75, 0xC6, 0x6A, 0x79, 0xB3, 0x37, 0x39, 0x52, 0x01, 0x81, 0x1C, 0x86, 0x5D, 0xBF, 0xC0, 0xC7, 0x01, 0x06, 0x82, 0xCC, 0x05, 0x01, 0x81, 0x07, 0xEA, 0x1F, 0xF1, 0xF2, 0xF3, 0x01, 0x06, 0xE8, 0x1A, 0x01, 0x0C, 0xA8, 0x0A, 0x01, 0x69, 0x88, 0x02, 0xA7, 0xC5, 0xE0, 0x8E, 0xB6, 0xD8, 0x8D, 0xB3, 0xD7, 0x01, 0x06, 0xA3, 0x7A, 0x01, 0x10, 0x93, 0x7C, 0x9E, 0x01, 0x08, 0x93, 0x7C, 0x01, 0x06, 0x9B, 0x7B, 0x8F, 0x01, 0x05, 0xA3, 0x7A, 0x01, 0x05, 0x9B, 0x7B, 0x01, 0x06, 0x93, 0x7C, 0x72, 0x81, 0xC9, 0x70, 0x01, 0x0B, 0x87, 0x7F, 0x6B, 0x74, 0xC6, 0x69, 0x70, 0xC4, 0x4E, 0x51, 0x88, 0x01, 0x81, 0x16, 0x88, 0x02, 0xA6, 0xA7, 0xB0, 0x01, 0x09, 0x88, 0x02, 0x4D, 0x4F, 0x62, 0x01, 0x81, 0x07, 0x81, 0xBB, 0x70, 0x01, 0x15, 0xF0, 0x1C, 0x01, 0x66, 0x84, 0x01, 0xCF, 0xE0, 0xEE, 0x8E, 0xB6, 0xD8, 0x01, 0x06, 0x8B, 0x7D, 0x01, 0x15, 0x93, 0x7C, 0x01, 0x0C, 0xAF, 0x77, 0x7A, 0x90, 0xCD, 0x01, 0x0C, 0x93, 0x7C, 0x73, 0x84, 0xCA, 0x72, 0x82, 0x01, 0x07, 0x93, 0x7C, 0x6E, 0x7A, 0xC7, 0x6D, 0x77, 0xC7, 0x6B, 0x74, 0xC6, 0x6A, 0x72, 0xC5, 0x69, 0x70, 0xC4, 0x64, 0x69, 0xBC, 0x01, 0x24, 0x90, 0x0A, 0x01, 0x72, 0x82, 0xEC, 0x28, 0x01, 0x33, 0x90, 0x04, 0x01, 0x15, 0x88, 0x26, 0x41, 0x43, 0x56, 0x01, 0x06, 0x81, 0xF4, 0x46, 0x01, 0x06, 0xD4, 0x1B, 0x01, 0x42, 0x84, 0x01, 0x78, 0x79, 0x87, 0x78, 0x79, 0x87, 0xFF, 0xFF, 0xFF, 0x01, 0x09, 0xB4, 0x10, 0x01, 0x63, 0x84, 0x01, 0xE8, 0xF0, 0xF7, 0x95, 0xBB, 0xDA, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x10, 0x93, 0x7C, 0x01, 0x1A, 0xAF, 0x77, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x11, 0x93, 0x7C, 0x6C, 0x76, 0xC6, 0x6A, 0x72, 0xC5, 0x6A, 0x71, 0xC5, 0x68, 0x6E, 0xC4, 0x66, 0x6B, 0xC3, 0x4A, 0x4B, 0x86, 0x01, 0x81, 0x49, 0x81, 0xDC, 0x49, 0x01, 0x12, 0xB1, 0x31, 0x01, 0x06, 0xA9, 0x11, 0x01, 0x09, 0xA0, 0x20, 0x01, 0x3F, 0x81, 0xA9, 0x37, 0x01, 0x09, 0xB4, 0x0D, 0x01, 0x06, 0x06, 0x6A, 0x6C, 0x7B, 0x01, 0x66, 0x84, 0x01, 0xB6, 0xD0, 0xE6, 0x8F, 0xB7, 0x01, 0x0B, 0x93, 0x7C, 0x01, 0x0E, 0xAF, 0x77, 0x81, 0x9D, 0x01, 0x14, 0x93, 0x7C, 0x01, 0x05, 0xAF, 0x77, 0x01, 0x06, 0xA7, 0x78, 0x01, 0x06, 0x9B, 0x7B, 0x70, 0x7D, 0xC8, 0x6E, 0x79, 0xC7, 0x6D, 0x77, 0xC6, 0x6B, 0x74, 0xC6, 0x01, 0x06, 0x83, 0x7E, 0x67, 0x6C, 0xC3, 0x64, 0x68, 0xC2, 0x5B, 0x5C, 0x01, 0x37, 0xCC, 0x2E, 0x01, 0x63, 0x96, 0x5E, 0x01, 0x30, 0xA5, 0x22, 0x01, 0x0F, 0x8C, 0x2A, 0x01, 0x06, 0xD4, 0x27, 0x01, 0x09, 0x48, 0x01, 0x12, 0x81, 0xF4, 0x61, 0x01, 0x81, 0x25, 0x98, 0x06, 0xE5, 0xEE, 0xF5, 0x8F, 0xB7, 0xD9, 0x01, 0x22, 0x93, 0x7C, 0x01, 0x09, 0x9B, 0x7B, 0x01, 0x12, 0x93, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x0A, 0x93, 0x7C, 0x01, 0x05, 0x8B, 0x7D, 0x67, 0x6D, 0xC4, 0x66, 0x6B, 0xC3, 0x64, 0x68, 0xC2, 0x63, 0x65, 0x01, 0x3D, 0xE0, 0x39, 0x01, 0x5A, 0xA7, 0x5A, 0x01, 0x06, 0x81, 0x8B, 0x76, 0x01, 0x27, 0x8F, 0x7E, 0x01, 0x15, 0xB7, 0x67, 0xBF, 0xC0, 0xC7, 0x01, 0x0F, 0xFC, 0x0D, 0xB3, 0xB3, 0xBB, 0x01, 0x3C, 0x88, 0x05, 0x01, 0x15, 0x81, 0xB8, 0x2B, 0x01, 0x60, 0x84, 0x01, 0xA8, 0xC8, 0xE1, 0x01, 0x0C, 0x93, 0x7C, 0x01, 0x0D, 0x9B, 0x7B, 0xA0, 0xD2, 0x82, 0x01, 0x0F, 0x93, 0x7C, 0x01, 0x08, 0xAF, 0x77, 0x77, 0x8A, 0x01, 0x0B, 0x87, 0x7F, 0x01, 0x11, 0x93, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x65, 0x69, 0xC3, 0x64, 0x66, 0xC2, 0x62, 0x64, 0x01, 0x31, 0x84, 0x01, 0x01, 0x09, 0x82, 0xCF, 0x35, 0x01, 0x06, 0x8A, 0x5B, 0x01, 0x51, 0xB7, 0x70, 0x01, 0x09, 0x81, 0x80, 0x62, 0x01, 0x06, 0x83, 0x88, 0x32, 0x01, 0x27, 0xE5, 0x3E, 0x01, 0x12, 0x87, 0x5B, 0xF2, 0xF2, 0xF4, 0x01, 0x0F, 0x8F, 0x78, 0x80, 0x82, 0x8F, 0x01, 0x36, 0xC5, 0x1E, 0x41, 0x43, 0x56, 0x01, 0x06, 0xCC, 0x0D, 0xFF, 0xFF, 0xFF, 0xE4, 0xE4, 0xE7, 0x01, 0x0C, 0xC4, 0x11, 0x01, 0x5D, 0x84, 0x01, 0xDA, 0xE7, 0xF2, 0x01, 0x0C, 0x87, 0x7F, 0x01, 0x16, 0xC3, 0x73, 0x01, 0x0F, 0xAF, 0x77, 0x8C, 0x01, 0x0D, 0xAF, 0x77, 0x01, 0x0A, 0x9B, 0x7B, 0x77, 0x01, 0x07, 0x8F, 0x7E, 0x01, 0x0F, 0x87, 0x7F, 0x62, 0x62, 0x01, 0x2B, 0x84, 0x01, 0x01, 0x06, 0x92, 0x54, 0x01, 0x0F, 0xD1, 0x75, 0x01, 0x18, 0x81, 0x82, 0x73, 0x01, 0x39, 0x9B, 0x3C, 0x01, 0x0C, 0x83, 0x75, 0x01, 0x24, 0x84, 0x01, 0x01, 0x15, 0xC7, 0x68, 0x01, 0x06, 0xBC, 0x21, 0x01, 0x0F, 0x84, 0x16, 0x01, 0x39, 0xC8, 0x12, 0xD6, 0xD7, 0xDB, 0x01, 0x09, 0xAB, 0x7F, 0x85, 0x86, 0x93, 0x01, 0x0C, 0xEC, 0x1B, 0x01, 0x5D, 0x84, 0x01, 0x01, 0x09, 0x87, 0x7F, 0x01, 0x0C, 0xC3, 0x73, 0x01, 0x0C, 0xAF, 0x77, 0x01, 0x13, 0x93, 0x7C, 0x8C, 0x01, 0x13, 0x9B, 0x7B, 0x01, 0x12, 0x93, 0x7C, 0x64, 0x68, 0xC2, 0x64, 0x66, 0xC2, 0x62, 0x62, 0xC1, 0x55, 0x54, 0xA3, 0x01, 0x2A, 0x81, 0xB3, 0x11, 0x01, 0x0C, 0x83, 0x7B, 0x01, 0x06, 0x87, 0x7C, 0x01, 0x18, 0x84, 0x01, 0x01, 0x06, 0x81, 0xDF, 0x46, 0x01, 0x30, 0xA3, 0x4A, 0x41, 0x43, 0x56, 0x01, 0x06, 0x81, 0x8C, 0x7A, 0xA6, 0xA7, 0xB0, 0x67, 0x68, 0x78, 0xA6, 0xA7, 0xB0, 0x01, 0x24, 0x97, 0x3B, 0x01, 0x15, 0x83, 0x57, 0x01, 0x15, 0x81, 0xFC, 0x2A, 0x01, 0x39, 0x84, 0x01, 0x01, 0x0F, 0x36, 0x01, 0x66, 0x9C, 0x07, 0xDB, 0xE8, 0xF2, 0x01, 0x09, 0x9B, 0x7B, 0x01, 0x0A, 0x93, 0x7C, 0x01, 0x09, 0x9B, 0x7B, 0x01, 0x08, 0xA7, 0x78, 0x01, 0x0C, 0xCB, 0x72, 0x01, 0x07, 0x93, 0x7C, 0x87, 0x01, 0x17, 0x93, 0x7C, 0x72, 0x01, 0x07, 0x93, 0x7C, 0x65, 0x69, 0xC3, 0x64, 0x68, 0xC2, 0x62, 0x64, 0xC1, 0x61, 0x61, 0xC0, 0x45, 0x47, 0x76, 0x01, 0x2A, 0xE6, 0x78, 0x01, 0x09, 0x82, 0xDF, 0x24, 0x01, 0x09, 0x87, 0x5E, 0x01, 0x18, 0x84, 0x01, 0x01, 0x06, 0xD4, 0x4E, 0x01, 0x30, 0xE7, 0x0D, 0x01, 0x12, 0xB3, 0x57, 0x01, 0x24, 0x84, 0x43, 0x01, 0x15, 0x81, 0xA4, 0x29, 0x01, 0x06, 0xF0, 0x22, 0x01, 0x81, 0x3D, 0x84, 0x01, 0xAC, 0xC7, 0xE1, 0x01, 0x0A, 0x93, 0x7C, 0x01, 0x14, 0xAF, 0x77, 0x01, 0x0D, 0x93, 0x7C, 0x01, 0x17, 0xAF, 0x77, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x06, 0x8B, 0x7D, 0x65, 0x69, 0xC3, 0x63, 0x65, 0xC1, 0x62, 0x64, 0xC1, 0x01, 0x27, 0x98, 0x03, 0x01, 0x09, 0x83, 0x7E, 0x01, 0x12, 0x81, 0xE2, 0x7F, 0x01, 0x1B, 0x8C, 0x03, 0x01, 0x09, 0x82, 0x93, 0x53, 0x01, 0x66, 0xA3, 0x23, 0x01, 0x0F, 0xE0, 0x7B, 0x01, 0x15, 0x81, 0xF4, 0x28, 0x01, 0x39, 0x83, 0x88, 0x62, 0xA0, 0xA1, 0xAB, 0xC9, 0xC9, 0xCF, 0x6A, 0x6C, 0x7B, 0x6A, 0x6C, 0x7B, 0xC9, 0xC9, 0xCF, 0x01, 0x06, 0xFC, 0x25, 0x01, 0x5D, 0x84, 0x01, 0xEA, 0xF2, 0xF8, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x12, 0x93, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x7F, 0x9A, 0xD0, 0x01, 0x13, 0xC3, 0x73, 0x01, 0x17, 0xAF, 0x77, 0x01, 0x0C, 0x9B, 0x7B, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x27, 0x87, 0x7F, 0x01, 0x09, 0xCF, 0x5B, 0x01, 0x15, 0x96, 0x40, 0x01, 0x1E, 0x90, 0x04, 0x01, 0x06, 0x8C, 0x33, 0x01, 0x63, 0xB7, 0x70, 0xB3, 0xB3, 0xBB, 0x01, 0x0C, 0xC5, 0x00, 0x01, 0x06, 0x83, 0x15, 0x01, 0x12, 0xE5, 0x0E, 0x01, 0x3C, 0x81, 0xF8, 0x3E, 0x01, 0x06, 0xFC, 0x16, 0xD6, 0xD7, 0xDB, 0x01, 0x0F, 0x81, 0xE0, 0x35, 0x01, 0x57, 0x84, 0x01, 0xB6, 0xD0, 0xE6, 0x01, 0x0F, 0xC3, 0x73, 0x87, 0x01, 0x05, 0x8B, 0x7D, 0x01, 0x07, 0x9B, 0x7B, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x14, 0x9B, 0x7B, 0x01, 0x0A, 0x8B, 0x7D, 0x01, 0x1D, 0x93, 0x7C, 0x5D, 0x5D, 0xB8, 0x01, 0x2A, 0xBC, 0x12, 0x01, 0x18, 0x83, 0x66, 0x01, 0x1E, 0x87, 0x64, 0x01, 0x06, 0xD6, 0x2F, 0x01, 0x63, 0x81, 0xCC, 0x36, 0x01, 0x06, 0x81, 0x81, 0x0C, 0x01, 0x06, 0x81, 0x91, 0x3D, 0xA6, 0xA7, 0xB0, 0x01, 0x06, 0x81, 0xF0, 0x2A, 0x01, 0x15, 0x85, 0x4A, 0x01, 0x51, 0xE9, 0x24, 0x01, 0x54, 0x84, 0x01, 0xF2, 0xF7, 0xFA, 0x95, 0xBB, 0xDA, 0x01, 0x19, 0xC3, 0x73, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x0F, 0x9B, 0x7B, 0x01, 0x14, 0x93, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x6A, 0x72, 0xC5, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x06, 0x8B, 0x7D, 0x01, 0x36, 0x87, 0x7F, 0x01, 0x18, 0x9F, 0x10, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x6C, 0x81, 0xF0, 0x3C, 0x01, 0x0C, 0x81, 0x9E, 0x71, 0xCC, 0xCD, 0xD2, 0x01, 0x12, 0x99, 0x04, 0x01, 0x06, 0xB4, 0x5B, 0x01, 0x81, 0x25, 0xBC, 0x0F, 0xD1, 0xE1, 0xEF, 0x01, 0x1B, 0xAF, 0x77, 0x01, 0x16, 0x93, 0x7C, 0x88, 0xCB, 0x01, 0x10, 0x93, 0x7C, 0x7A, 0x01, 0x16, 0x93, 0x7C, 0x01, 0x09, 0x87, 0x7F, 0x01, 0x24, 0xB8, 0x0B, 0x01, 0x21, 0x87, 0x43, 0x01, 0x21, 0x8F, 0x66, 0x01, 0x63, 0xE8, 0x1A, 0x01, 0x2D, 0x81, 0xCE, 0x0B, 0x01, 0x81, 0x25, 0x84, 0x01, 0xA7, 0xC5, 0xE0, 0x01, 0x24, 0xC3, 0x73, 0x01, 0x06, 0x9B, 0x7B, 0x01, 0x1B, 0xC3, 0x73, 0x01, 0x0C, 0xA3, 0x7A, 0x01, 0x0C, 0x93, 0x7C, 0x61, 0x61, 0xC0, 0x01, 0x27, 0xB0, 0x03, 0x01, 0x06, 0x86, 0x54, 0x01, 0x1B, 0x8A, 0x37, 0x01, 0x21, 0x84, 0x01, 0x01, 0x81, 0x4C, 0x81, 0xE8, 0x3A, 0x01, 0x66, 0x84, 0x01, 0xEA, 0xF2, 0xF8, 0x01, 0x0A, 0x93, 0x7C, 0x01, 0x0F, 0xDF, 0x6E, 0x01, 0x0E, 0xC3, 0x73, 0x01, 0x07, 0xBB, 0x74, 0x01, 0x08, 0xAF, 0x77, 0x75, 0x86, 0xCB, 0x01, 0x09, 0xCB, 0x72, 0x6E, 0x79, 0xC7, 0x6C, 0x01, 0x08, 0xAF, 0x77, 0x69, 0x70, 0x01, 0x0A, 0x93, 0x7C, 0x63, 0x65, 0xC1, 0x61, 0x61, 0xC0, 0x01, 0x27, 0x87, 0x7F, 0x01, 0x06, 0xA6, 0x4D, 0x01, 0x1E, 0x87, 0x40, 0x01, 0x21, 0x84, 0x01, 0x01, 0x66, 0xF8, 0x1E, 0x01, 0x81, 0x4C, 0x84, 0x01, 0xCB, 0xDD, 0xED, 0x01, 0x10, 0x93, 0x7C, 0x01, 0x18, 0xDF, 0x6E, 0x01, 0x1B, 0x93, 0x7C, 0x01, 0x17, 0xAF, 0x77, 0x62, 0x62, 0xC1, 0x60, 0x60, 0x01, 0x28, 0x87, 0x7F, 0x01, 0x0C, 0xD6, 0x08, 0x01, 0x39, 0x84, 0x01, 0x01, 0x66, 0x81, 0x80, 0x20, 0x01, 0x69, 0x81, 0xEC, 0x35, 0x01, 0x12, 0xEC, 0x1B, 0x01, 0x51, 0x84, 0x01, 0xAF, 0xCA, 0xE3, 0x01, 0x0A, 0xCB, 0x72, 0x01, 0x0E, 0x93, 0x7C, 0x81, 0x01, 0x12, 0x93, 0x7C, 0x01, 0x0B, 0xDF, 0x6E, 0x01, 0x18, 0x93, 0x7C, 0x01, 0x0F, 0x9B, 0x7B, 0x01, 0x2A, 0x87, 0x7F, 0x01, 0x45, 0x84, 0x01, 0x01, 0x75, 0x8C, 0x03, 0x01, 0x06, 0x82, 0x89, 0x79, 0x01, 0x06, 0x81, 0xB6, 0x7A, 0x01, 0x48, 0x90, 0x7F, 0x4F, 0x51, 0x63, 0x01, 0x0C, 0xC0, 0x10, 0x01, 0x12, 0x96, 0x28, 0x01, 0x45, 0x84, 0x01, 0xF7, 0xFA, 0xFC, 0x01, 0x27, 0xAF, 0x77, 0x01, 0x06, 0x8B, 0x7D, 0x01, 0x07, 0xC3, 0x73, 0x83, 0x01, 0x10, 0xAF, 0x77, 0x01, 0x0A, 0x93, 0x7C, 0x6D, 0xC4, 0x01, 0x0C, 0x93, 0x7C, 0x01, 0x2D, 0x87, 0x7F, 0x01, 0x45, 0x84, 0x01, 0x01, 0x06, 0xBF, 0x12, 0x01, 0x69, 0x84, 0x01, 0x01, 0x06, 0xB3, 0x6F, 0x01, 0x0F, 0x82, 0x56, 0x01, 0x12, 0x82, 0x94, 0x75, 0x01, 0x4E, 0x81, 0xB8, 0x2E, 0x01, 0x48, 0xF8, 0x1B, 0xFF, 0xFF, 0xFF, 0xDA, 0xE7, 0xF2, 0x01, 0x0D, 0xAF, 0x77, 0xA5, 0x01, 0x1C, 0xAF, 0x77, 0x01, 0x0D, 0x93, 0x7C, 0x01, 0x05, 0x83, 0x7E, 0x6D, 0x7B, 0xC1, 0x01, 0x09, 0x93, 0x7C, 0x68, 0x6E, 0x01, 0x07, 0x93, 0x7C, 0x66, 0x6B, 0x01, 0x0A, 0x87, 0x7F, 0x60, 0x60, 0xC0, 0x01, 0x4E, 0x81, 0x83, 0x5F, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x09, 0x81, 0x9C, 0x66, 0x01, 0x63, 0xCF, 0x55, 0x01, 0x06, 0xB5, 0x29, 0x01, 0x06, 0x81, 0x10, 0x80, 0x82, 0x8F, 0x01, 0x12, 0x81, 0xF1, 0x46, 0x01, 0x42, 0x81, 0xAD, 0x38, 0x01, 0x15, 0xD0, 0x14, 0x01, 0x09, 0xB0, 0x78, 0x01, 0x45, 0x84, 0x01, 0xBD, 0xD2, 0xE8, 0x01, 0x22, 0xF3, 0x6A, 0x01, 0x09, 0x9F, 0x79, 0x01, 0x05, 0xAF, 0x77, 0x01, 0x0C, 0xDF, 0x6E, 0x01, 0x0C, 0xC3, 0x73, 0x01, 0x06, 0x93, 0x7C, 0x01, 0x06, 0x83, 0x7E, 0x01, 0x06, 0x93, 0x7C, 0x60, 0x5F, 0xC0, 0x4F, 0x4E, 0x94, 0x01, 0x33, 0x81, 0x8F, 0x62, 0x01, 0x1B, 0xBB, 0x71, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x06, 0xAC, 0x44, 0x01, 0x66, 0x82, 0xA3, 0x3C, 0x01, 0x06, 0xB9, 0x27, 0x01, 0x18, 0xB0, 0x3C, 0x01, 0x06, 0x81, 0x49, 0x01, 0x3F, 0xD8, 0x67, 0x5D, 0x5E, 0x6F, 0xC9, 0xC9, 0xCF, 0xD6, 0xD7, 0xDB, 0x01, 0x0C, 0xD8, 0x16, 0x01, 0x0F, 0x81, 0xAE, 0x1B, 0x01, 0x3F, 0x84, 0x01, 0xA3, 0xBF, 0xDF, 0x01, 0x19, 0xF3, 0x6A, 0x01, 0x17, 0xAF, 0x77, 0x72, 0x81, 0xC9, 0x01, 0x1C, 0xC3, 0x73, 0x66, 0xC2, 0x64, 0x68, 0xC2, 0x62, 0x62, 0xC1, 0x61, 0x61, 0xC0, 0x5F, 0x5D, 0xBF, 0x01, 0x27, 0xE8, 0x11, 0x01, 0x0F, 0x91, 0x62, 0x01, 0x1B, 0x82, 0xBF, 0x07, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x06, 0x88, 0x41, 0x01, 0x63, 0x94, 0x02, 0x01, 0x18, 0xAB, 0x7C, 0x01, 0x0F, 0x84, 0x04, 0x01, 0x5D, 0x82, 0xC0, 0x50, 0x01, 0x42, 0x81, 0x8C, 0x20, 0xFF, 0xFF, 0xFF, 0x01, 0x1F, 0xDF, 0x6E, 0x01, 0x17, 0x93, 0x7C, 0x71, 0x7E, 0xC8, 0x01, 0x06, 0xB7, 0x76, 0x01, 0x13, 0xAF, 0x77, 0x01, 0x08, 0xB7, 0x76, 0x01, 0x33, 0x87, 0x7F, 0x01, 0x0C, 0xA3, 0x4A, 0x01, 0x18, 0x8A, 0x40, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0xB8, 0x11, 0x01, 0x63, 0x8C, 0x00, 0x01, 0x12, 0x82, 0xBC, 0x4F, 0x01, 0x27, 0x83, 0xA9, 0x11, 0x01, 0x4E, 0x81, 0xD8, 0x39, 0x01, 0x3F, 0x81, 0x94, 0x22, 0xE1, 0xE9, 0xF4, 0x01, 0x0C, 0xAF, 0x77, 0x01, 0x24, 0xF3, 0x6A, 0x01, 0x0D, 0xDF, 0x6E, 0x01, 0x1D, 0x93, 0x7C, 0x01, 0x33, 0x87, 0x7F, 0x01, 0x0F, 0x8D, 0x61, 0x01, 0x15, 0x90, 0x0A, 0x01, 0x1E, 0xC0, 0x10, 0x01, 0x69, 0x81, 0xBC, 0x32, 0x01, 0x27, 0xA0, 0x6B, 0x01, 0x3F, 0x82, 0xC0, 0x50, 0xC9, 0xC9, 0xCF, 0x01, 0x21, 0x81, 0xF8, 0x3E, 0x01, 0x3C, 0x81, 0x9C, 0x24, 0xC4, 0xD6, 0xEA, 0x01, 0x13, 0xAF, 0x77, 0x01, 0x0B, 0x81, 0x8F, 0x65, 0x01, 0x06, 0xF3, 0x6A, 0x01, 0x07, 0x8B, 0x7D, 0x01, 0x0B, 0xF3, 0x6A, 0x01, 0x12, 0xCB, 0x72, 0x01, 0x0F, 0xAF, 0x77, 0x01, 0x39, 0x87, 0x7F, 0x01, 0x0C, 0x8D, 0x61, 0x01, 0x15, 0x81, 0xC8, 0x08, 0x01, 0x15, 0x84, 0x01, 0x01, 0x09, 0x83, 0x7E, 0x01, 0x66, 0x8F, 0x7E, 0x01, 0x6C, 0x81, 0x90, 0x24, 0x01, 0x5D, 0x81, 0xA4, 0x26, 0xAF, 0xCA, 0xE3, 0x01, 0x1C, 0xF3, 0x6A, 0x8F, 0x01, 0x11, 0xDF, 0x6E, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x0B, 0xAF, 0x77, 0x01, 0x0F, 0x93, 0x7C, 0x01, 0x3F, 0x87, 0x7F, 0x01, 0x12, 0x81, 0xC4, 0x31, 0xB3, 0xB3, 0xBB, 0x01, 0x0C, 0x9E, 0x5A, 0x01, 0x0F, 0x84, 0x01, 0x01, 0x06, 0xCF, 0x46, 0x01, 0x09, 0x81, 0xD3, 0x3A, 0x01, 0x66, 0xE7, 0x52, 0x01, 0x81, 0x04, 0x81, 0x94, 0x25, 0x01, 0x45, 0x90, 0x13, 0xA3, 0xBF, 0xDF, 0x01, 0x33, 0xC3, 0x73, 0x01, 0x07, 0xAF, 0x77, 0x01, 0x17, 0xA7, 0x78, 0x01, 0x06, 0x93, 0x7C, 0x52, 0x53, 0x99, 0x01, 0x48, 0x9A, 0x65, 0x01, 0x09, 0x9E, 0x5A, 0x01, 0x06, 0xFA, 0x59, 0x01, 0x06, 0x83, 0x69, 0x01, 0x06, 0x9A, 0x6E, 0x01, 0x0C, 0xD0, 0x2F, 0x01, 0x6C, 0x81, 0x84, 0x1E, 0x01, 0x06, 0x81, 0x07, 0x01, 0x24, 0x6F, 0x01, 0x3F, 0x82, 0xC8, 0x52, 0x01, 0x30, 0x81, 0xF8, 0x3E, 0x01, 0x30, 0x90, 0x13, 0x01, 0x06, 0x9B, 0x7B, 0x01, 0x2D, 0xF3, 0x6A, 0x01, 0x07, 0x93, 0x7C, 0x01, 0x08, 0x9B, 0x7B, 0x67, 0x6D, 0x01, 0x0B, 0x93, 0x7C, 0x62, 0xC1, 0x62, 0x64, 0xC1, 0x60, 0x5F, 0xC0, 0x5F, 0x5D, 0xBF, 0x3E, 0x3F, 0x66, 0x01, 0x48, 0x82, 0x83, 0x28, 0x01, 0x12, 0xA2, 0x67, 0x01, 0x12, 0x81, 0xD4, 0x32, 0x01, 0x72, 0x81, 0xCC, 0x2A, 0x01, 0x66, 0x90, 0x04, 0x01, 0x60, 0x81, 0xAC, 0x37, 0x01, 0x15, 0xDF, 0x6E, 0x01, 0x28, 0xF3, 0x6A, 0x01, 0x08, 0x87, 0x7F, 0x01, 0x0A, 0x93, 0x7C, 0x64, 0x01, 0x07, 0x8B, 0x7D, 0x01, 0x2A, 0xD3, 0x77, 0x01, 0x2A, 0xA6, 0x6E, 0x01, 0x06, 0x81, 0xAF, 0x1C, 0x01, 0x12, 0xA6, 0x71, 0x01, 0x45, 0x81, 0xBF, 0x1A, 0x01, 0x36, 0xF4, 0x47, 0x01, 0x21, 0x83, 0x5A, 0x01, 0x06, 0xC9, 0x22, 0x01, 0x3F, 0x9D, 0x14, 0x01, 0x33, 0x81, 0xF0, 0x3F, 0x41, 0x43, 0x56, 0xC0, 0x01, 0x08, 0x82, 0xE5, 0x6C, 0x01, 0x1E, 0x98, 0x03, 0x01, 0x19, 0xF3, 0x6A, 0x01, 0x06, 0x81, 0x97, 0x64, 0x01, 0x0B, 0x9B, 0x7B, 0x01, 0x18, 0x93, 0x7C, 0x01, 0x0F, 0xAF, 0x77, 0x01, 0x06, 0x84, 0x01, 0x01, 0x48, 0x87, 0x7F, 0x01, 0x1B, 0xAE, 0x76, 0x01, 0x81, 0x07, 0xB7, 0x13, 0x01, 0x1E, 0xA3, 0x68, 0x01, 0x06, 0x8D, 0x22, 0x01, 0x3C, 0x85, 0x20, 0x01, 0x09, 0x81, 0xAC, 0x28, 0x01, 0x33, 0x8C, 0x48, 0x01, 0x21, 0x81, 0xA0, 0x4C, 0xE1, 0xE9, 0xF4, 0x01, 0x15, 0x81, 0xA3, 0x61, 0x01, 0x13, 0x81, 0x87, 0x66, 0x01, 0x17, 0xF3, 0x6A, 0x01, 0x09, 0xA3, 0x7A, 0x01, 0x0C, 0x93, 0x7C, 0x01, 0x3C, 0x97, 0x7D, 0x01, 0x81, 0x31, 0x82, 0x81, 0x6B, 0x01, 0x18, 0xA4, 0x75, 0x01, 0x09, 0x91, 0x41, 0x01, 0x3F, 0xBD, 0x16, 0x01, 0x09, 0x8F, 0x7E, 0x01, 0x36, 0x90, 0x49, 0x01, 0x0F, 0xDE, 0x58, 0x01, 0x10, 0x82, 0x96, 0x74, 0xE3, 0xF1, 0x01, 0x22, 0xDF, 0x6E, 0x01, 0x20, 0xF3, 0x6A, 0x64, 0x66, 0x01, 0x07, 0xDF, 0x6E, 0x01, 0x06, 0xB7, 0x76, 0x01, 0x81, 0x6A, 0x83, 0x7E, 0x01, 0x12, 0x82, 0x98, 0x49, 0x01, 0x06, 0xB0, 0x09, 0x01, 0x06, 0x82, 0xB8, 0x5A, 0x01, 0x48, 0x81, 0xD1, 0x3B, 0xC9, 0xC9, 0xCF, 0x93, 0x94, 0x9F, 0xFF, 0xFF, 0xFF, 0x01, 0x30, 0x81, 0xD0, 0x34, 0x01, 0x15, 0x81, 0xDE, 0x54, 0x01, 0x0F, 0x84, 0x01, 0xC1, 0xD0, 0xE9, 0x01, 0x19, 0x93, 0x7C, 0x01, 0x26, 0xF3, 0x6A, 0x01, 0x0C, 0xA7, 0x78, 0x52, 0x53, 0x99, 0x01, 0x5D, 0x8B, 0x7A, 0x01, 0x81, 0x1C, 0xC3, 0x1F, 0x01, 0x12, 0x9F, 0x04, 0x01, 0x0F, 0x9D, 0x3B, 0x01, 0x7E, 0x81, 0xE0, 0x38, 0x01, 0x18, 0x90, 0x13, 0xC1, 0xD0, 0xE9, 0x01, 0x0C, 0x81, 0x87, 0x66, 0x01, 0x27, 0xDF, 0x6E, 0x01, 0x09, 0x8B, 0x7D, 0x5D, 0x5D, 0xB8, 0x51, 0x57, 0x8B, 0x45, 0x47, 0x76, 0x01, 0x81, 0x76, 0x83, 0x78, 0x01, 0x15, 0xE8, 0x62, 0x01, 0x81, 0x1C, 0x82, 0xA8, 0x38, 0x01, 0x12, 0x90, 0x13, 0xC0, 0xCF, 0xE8, 0x82, 0x01, 0x0F, 0xA7, 0x78, 0x01, 0x0F, 0xDF, 0x6E, 0x01, 0x11, 0xF3, 0x6A, 0x61, 0x66, 0xB2, 0x01, 0x06, 0x83, 0x75, 0x01, 0x3C, 0xA3, 0x65, 0x01, 0x82, 0x7A, 0x81, 0xFD, 0x70, 0x6F, 0x72, 0x82, 0x01, 0x0C, 0x90, 0x13, 0xC0, 0xCF, 0xE8, 0x01, 0x1B, 0xF3, 0x6A, 0x75, 0x86, 0xCB, 0x72, 0x82, 0xC9, 0x6D, 0x7B, 0xC1, 0x5D, 0x67, 0xA1, 0x51, 0x5D, 0x7D, 0x42, 0x46, 0x6A, 0x01, 0x81, 0x16, 0x81, 0x8B, 0x5B, 0x8D, 0x8E, 0x9A, 0x01, 0x06, 0xEB, 0x53, 0x01, 0x82, 0x26, 0x82, 0xFB, 0x49, 0x01, 0x0C, 0x90, 0x13, 0xBF, 0xCD, 0xE8, 0x01, 0x10, 0x93, 0x7C, 0x01, 0x05, 0x8F, 0x7E, 0x6A, 0x79, 0xB3, 0x5B, 0x65, 0x9A, 0x4B, 0x52, 0x78, 0x40, 0x44, 0x01, 0x79, 0x82, 0x85, 0x36, 0x41, 0x43, 0x56, 0x01, 0x21, 0x9E, 0x3F, 0x01, 0x15, 0x81, 0xF8, 0x59, 0x01, 0x82, 0x23, 0x83, 0x87, 0x64, 0x01, 0x06, 0xAE, 0x3D, 0xE6, 0xE6, 0xE9, 0xBF, 0xCD, 0xE8, 0x01, 0x09, 0x9B, 0x7B, 0x6A, 0x7C, 0xAD, 0x57, 0x62, 0x8C, 0x4B, 0x52, 0x78, 0x01, 0x81, 0x07, 0x81, 0x8F, 0x41, 0x01, 0x06, 0x92, 0x57, 0x01, 0x1B, 0x81, 0xBC, 0x32, 0x01, 0x0C, 0x8D, 0x52, 0x01, 0x06, 0x81, 0xD7, 0x1D, 0x01, 0x09, 0xA8, 0x16, 0x01, 0x81, 0x4F, 0x84, 0x04, 0x01, 0x5A, 0xA5, 0x67, 0x3C, 0x40, 0x5B, 0x46, 0x4E, 0x6C, 0x01, 0x36, 0x81, 0xD3, 0x5B, 0x01, 0x63, 0x81, 0xDF, 0x10, 0x01, 0x1B, 0x81, 0xBA, 0x69, 0x01, 0x09, 0xD2, 0x16, 0x01, 0x0C, 0x84, 0x84, 0x00, 0x4D, 0x4F, 0x62, 0x01, 0x09, 0x81, 0xE3, 0x32, 0x01, 0x81, 0x49, 0x83, 0x7E, 0x01, 0x06, 0x81, 0xAC, 0x2B, 0x6A, 0x6C, 0x7B, 0xBB, 0xBC, 0xC3, 0x01, 0x81, 0x6D, 0x82, 0x9B, 0x22, 0x01, 0x1E, 0xC7, 0x56, 0x01, 0x09, 0x81, 0xF8, 0x5C, 0x01, 0x0F, 0x86, 0x1E, 0x41, 0x43, 0x56, 0x01, 0x06, 0x3C, 0x01, 0x69, 0x81, 0xA3, 0x70, 0x01, 0x06, 0x81, 0x9C, 0x60, 0xCC, 0xCD, 0xD2, 0x01, 0x1E, 0xB3, 0x03, 0x01, 0x82, 0x2F, 0x82, 0xE4, 0x59, 0x01, 0x21, 0x87, 0x46, 0x01, 0x1B, 0x84, 0x22, 0x01, 0x06, 0x88, 0x3E, 0x01, 0x66, 0xB3, 0x00, 0x01, 0x09, 0xB6, 0x7B, 0x01, 0x06, 0x81, 0x85, 0x3A, 0x01, 0x54, 0x83, 0xB0, 0x6C, 0x01, 0x81, 0x73, 0x84, 0x01, 0x01, 0x21, 0xD4, 0x15, 0x01, 0x24, 0xF4, 0x3E, 0x01, 0x63, 0x82, 0x2F, 0x01, 0x09, 0x81, 0xCD, 0x58, 0x01, 0x5D, 0xF1, 0x05, 0x01, 0x15, 0x81, 0xB8, 0x2E, 0x01, 0x81, 0x7F, 0x82, 0xB4, 0x4D, 0x01, 0x06, 0xBE, 0x62, 0x01, 0x1B, 0x88, 0x23, 0x01, 0x66, 0xE4, 0x19, 0x01, 0x06, 0x83, 0xBC, 0x69, 0x01, 0x81, 0x3D, 0x94, 0x05, 0x01, 0x81, 0x1C, 0x82, 0xC8, 0x5E, 0x01, 0x1B, 0x81, 0x76, 0x01, 0x21, 0xF8, 0x3F, 0x01, 0x63, 0x84, 0x01, 0x01, 0x69, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x79, 0x82, 0xD0, 0x60, 0x01, 0x21, 0x88, 0x23, 0x01, 0x1B, 0x8E, 0x59, 0x01, 0x42, 0x81, 0xE8, 0x7C, 0x01, 0x4B, 0xC8, 0x12, 0x01, 0x3F, 0x69, 0x01, 0x15, 0x81, 0xD0, 0x34, 0x01, 0x81, 0x7F, 0x84, 0x01, 0x01, 0x21, 0x81, 0x8C, 0x05, 0x01, 0x63, 0xF4, 0x1D, 0x01, 0x69, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x73, 0x83, 0x80, 0x60, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x09, 0x94, 0x02, 0x01, 0x1B, 0x86, 0x7E, 0x01, 0x69, 0x81, 0xF0, 0x3C, 0x01, 0x63, 0x88, 0x02, 0x01, 0x81, 0x73, 0x98, 0x06, 0x01, 0x1E, 0xF3, 0x5B, 0x01, 0x06, 0x9B, 0x66, 0x01, 0x1E, 0x9C, 0x25, 0x01, 0x66, 0x94, 0x05, 0x01, 0x66, 0x82, 0xA5, 0x3B, 0x01, 0x81, 0x73, 0x98, 0x06, 0x01, 0x1E, 0x82, 0xF4, 0x1B, 0x01, 0x24, 0x84, 0x83, 0x59, 0x01, 0x21, 0x81, 0x84, 0x63, 0x01, 0x81, 0x2E, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x70, 0x98, 0x06, 0x01, 0x1B, 0xF3, 0x5E, 0x01, 0x09, 0x81, 0x9C, 0x06, 0x01, 0x1B, 0xA7, 0x69, 0x01, 0x06, 0x8B, 0x1D, 0x01, 0x63, 0x81, 0x94, 0x25, 0x01, 0x06, 0xA8, 0x76, 0x01, 0x82, 0x53, 0x83, 0xAC, 0x47, 0x01, 0x09, 0x83, 0x66, 0x01, 0x12, 0x82, 0x5C, 0x01, 0x09, 0xB7, 0x7F, 0x01, 0x1B, 0x86, 0x15, 0x01, 0x06, 0xF0, 0x1F, 0x01, 0x66, 0x82, 0x98, 0x46, 0x01, 0x06, 0xBA, 0x5B, 0xBF, 0xC0, 0xC7, 0x01, 0x5A, 0xB4, 0x7F, 0x01, 0x81, 0x76, 0x82, 0xD0, 0x4B, 0x01, 0x09, 0xB7, 0x6A, 0x01, 0x0F, 0x81, 0xB7, 0x45, 0x01, 0x24, 0x82, 0xB0, 0x31, 0x01, 0x6F, 0xB0, 0x0C, 0x01, 0x09, 0x81, 0xE9, 0x5F, 0x01, 0x06, 0x83, 0x8C, 0x5D, 0x01, 0x54, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x64, 0x82, 0xE8, 0x5A, 0x01, 0x1B, 0x82, 0xAC, 0x18, 0x01, 0x12, 0x82, 0xEC, 0x3D, 0x01, 0x1B, 0x87, 0x7F, 0x01, 0x21, 0xFC, 0x5B, 0x01, 0x51, 0xB4, 0x0A, 0x01, 0x09, 0x82, 0xA9, 0x3C, 0x01, 0x57, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x73, 0x82, 0xE8, 0x5A, 0x01, 0x1B, 0xC3, 0x70, 0x01, 0x15, 0x81, 0xA3, 0x0D, 0x01, 0x12, 0x87, 0x7F, 0x01, 0x66, 0x81, 0xF8, 0x3E, 0x01, 0x06, 0x8D, 0x2B, 0x01, 0x06, 0xED, 0x25, 0x01, 0x82, 0x62, 0x84, 0x93, 0x5D, 0x01, 0x24, 0x81, 0xD3, 0x55, 0x01, 0x06, 0x8F, 0x12, 0x01, 0x69, 0x87, 0x7F, 0x01, 0x06, 0xE9, 0x2A, 0x01, 0x5A, 0x6C, 0x01, 0x09, 0x82, 0xB4, 0x3E, 0x01, 0x81, 0x6A, 0x83, 0x90, 0x5E, 0x01, 0x4B, 0x83, 0xBC, 0x0F, 0x01, 0x66, 0xA5, 0x31, 0x01, 0x5D, 0x90, 0x6A, 0x01, 0x81, 0x73, 0x83, 0x8C, 0x5D, 0x01, 0x81, 0x31, 0x81, 0xA3, 0x2B, 0x01, 0x5D, 0x88, 0x6B, 0x01, 0x0F, 0x8D, 0x7F, 0x01, 0x81, 0x70, 0x94, 0x05, 0x01, 0x81, 0x34, 0x84, 0xBD, 0x0F, 0x01, 0x5A, 0x82, 0xFC, 0x59, 0x01, 0x83, 0x12, 0x82, 0xE4, 0x5C, 0x01, 0x06, 0xA4, 0x6F, 0x01, 0x83, 0x7E, 0x83, 0xE4, 0x67, 0x01, 0x83, 0x60, 0x83, 0xDC, 0x53, 0x01, 0x24, 0xA5, 0x2E, 0x01, 0x83, 0x63, 0x84, 0xB4, 0x6C, 0x01, 0x81, 0x01, 0x82, 0xEC, 0x5B, 0x01, 0x83, 0x24, 0x84, 0x04, 0x01, 0x60, 0x82, 0xE5, 0x57, 0x01, 0x83, 0x21, 0x84, 0x8D, 0x03, 0x01, 0x09, 0x82, 0x99, 0x41, 0x01, 0x54, 0xAC, 0x0B, 0x01, 0x83, 0x24, 0x84, 0x95, 0x05, 0x01, 0x5D, 0x82, 0xEC, 0x5B, 0x01, 0x97, 0x4A, 0x84, 0x91, 0x19, 0x01, 0x83, 0x54, 0xA0, 0x26, 0x01, 0x06, 0xA0, 0x08, 0x01, 0x27, 0xE1, 0x67, 0x01, 0x83, 0x54, 0x84, 0xAD, 0x0B, 0x01, 0x2A, 0xBC, 0x0F, 0x01, 0x39, 0x82, 0x8C, 0x43, 0x01, 0x83, 0x48, 0x84, 0x01, 0x01, 0x83, 0x6C, 0x85, 0x81, 0x20, 0x01, 0x54, 0x81, 0xC0, 0x30, 0x01, 0x83, 0x42, 0x84, 0x01, 0xCC, 0xCD, 0xD2, 0x01, 0x82, 0x56, 0x83, 0xC1, 0x17, 0x01, 0x7B, 0xED, 0x3A, 0x01, 0x06, 0xC0, 0x0A, 0x01, 0x06, 0xE5, 0x38, 0x01, 0x1E, 0x82, 0xBD, 0x38, 0x01, 0x69, 0x82, 0xF9, 0x68, 0x01, 0x82, 0x6E, 0x84, 0x81, 0x09, 0x01, 0x2D, 0x83, 0xD2, 0x04, 0x01, 0x83, 0x57, 0x84, 0xF1, 0x28, 0x01, 0x83, 0x57, 0x93, 0x5B, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x84, 0x2B, 0x88, 0x02, 0x01, 0x94, 0x0E, 0xBF, 0x6F, 0x01, 0x0C, 0x82, 0xF1, 0x5D, 0x01, 0x83, 0x6C, 0x84, 0xED, 0x1B, 0x01, 0x0C, 0x83, 0xB2, 0x14, 0x01, 0x06, 0xBF, 0x72, 0x01, 0x06, 0x81, 0x9C, 0x36, 0x01, 0x06, 0x81, 0xE0, 0x41, 0x01, 0x09, 0xAC, 0x08, 0x01, 0x06, 0x81, 0xF1, 0x55, 0x01, 0x83, 0x57, 0x84, 0xED, 0x1B, 0x01, 0x06, 0x81, 0x95, 0x35, 0x01, 0x0C, 0xEC, 0x1B, 0x01, 0x12, 0x85, 0xD1, 0x34, 0x01, 0x3F, 0x82, 0xD0, 0x51, 0x01, 0x83, 0x21, 0x85, 0x89, 0x22, 0x01, 0x0F, 0x81, 0x91, 0x0D, 0x01, 0x18, 0x84, 0xB5, 0x0D, 0x01, 0x83, 0x54, 0xB0, 0x0F, 0x01, 0x2A, 0x85, 0xBD, 0x2F, 0x01, 0x06, 0x81, 0xF9, 0x78, 0x01, 0x83, 0x7B, 0x85, 0xC5, 0x31, 0x01, 0x06, 0x81, 0xA8, 0x51, 0x01, 0x83, 0x7B, 0x84, 0x01, 0x01, 0x83, 0x18, 0x81, 0x93, 0x66, 0x01, 0x54, 0x83, 0xAC, 0x6B, 0x01, 0x83, 0x6C, 0x84, 0x01, 0x01, 0x15, 0x83, 0xB4, 0x6D, 0x01, 0x06, 0x82, 0x8D, 0x6E, 0x01, 0x15, 0x82, 0xCC, 0x7A, 0x01, 0x83, 0x57, 0x84, 0xE9, 0x17, 0x01, 0x0F, 0x87, 0x70, 0x01, 0x18, 0x88, 0x17, 0x01, 0x83, 0x4E, 0xD0, 0x14, 0x01, 0x1E, 0x84, 0xCC, 0x6F, 0x01, 0x06, 0x81, 0xD8, 0x4B, 0x01, 0x0C, 0x82, 0xD8, 0x6B, 0x01, 0x2D, 0x83, 0xDE, 0x3A, 0x01, 0x83, 0x36, 0x84, 0xD5, 0x2A, 0x01, 0x15, 0x82, 0xA5, 0x50, 0x01, 0x09, 0x85, 0x99, 0x3E, 0x01, 0x83, 0x60, 0x81, 0x94, 0x49, 0x01, 0x12, 0xEF, 0x78, 0x01, 0x09, 0x81, 0xEC, 0x4D, 0xBF, 0xC0, 0xC7, 0x01, 0x83, 0x7E, 0x81, 0x9C, 0x48, 0x01, 0x98, 0x09, 0xCC, 0x31, 0x01, 0x9C, 0x04, 0x9C, 0x04, 0x01, 0xB8, 0x08, 0xB8, 0x08, 0x01, 0xD8, 0x73, 0xD8, 0x73, 0x00}; static bool g_has_uncompressed = false; static unsigned char *get_uncompressed_splash(void) { @@ -36,6 +38,12 @@ static unsigned char *get_uncompressed_splash(void) { void draw_splash(volatile uint32_t *fb) { unsigned char *splash = get_uncompressed_splash(); + /* Set display background color. */ + for (size_t i = 0; i < 1280 * 768; i++) { + fb[i] = 0x34364B; + } + + /* Draw actual splash. */ size_t pos = 0; for (size_t y = 496; y < (496 + 287); y++) { diff --git a/sept/sept-secondary/src/splash.h b/sept/sept-secondary/src/splash.h index 78cc8dc58..6db3f4b21 100644 --- a/sept/sept-secondary/src/splash.h +++ b/sept/sept-secondary/src/splash.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2018 CtCaer + * Copyright (c) 2018 CTCaer + * Copyright (c) 2018 xamanthas * Copyright (c) 2018 Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it From 4a60cee5fff782b2734fa679ecb22bcf530c4360 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 22:34:34 -0800 Subject: [PATCH 432/489] sept-s: revise splash (larger, square) --- sept/sept-secondary/src/main.c | 5 +++++ sept/sept-secondary/src/splash.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 892072573..048b3edc1 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -93,6 +93,11 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { pmc->secure_scratch5 = 0xCCCCCCCC; pmc->secure_scratch6 = 0xCCCCCCCC; pmc->secure_scratch7 = 0xCCCCCCCC; + + /* Clear all keyslots except for SBK/SSK. */ + for (size_t k = 0; k < 0xE; k++) { + clear_aes_keyslot(k); + } } } diff --git a/sept/sept-secondary/src/splash.c b/sept/sept-secondary/src/splash.c index c5e292059..100de11a8 100644 --- a/sept/sept-secondary/src/splash.c +++ b/sept/sept-secondary/src/splash.c @@ -23,7 +23,7 @@ #include "lib/lz.h" #include "utils.h" -static const uint8_t s_splash[] = {0x01, 0x34, 0x36, 0x4B, 0x34, 0x36, 0x4B, 0x01, 0x06, 0x06, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x01, 0x30, 0x30, 0x01, 0x60, 0x60, 0x01, 0x81, 0x40, 0x81, 0x40, 0x01, 0x83, 0x00, 0x83, 0x00, 0x01, 0x86, 0x00, 0x86, 0x00, 0x01, 0x8C, 0x00, 0x8C, 0x00, 0x01, 0x98, 0x00, 0x98, 0x00, 0x01, 0xB0, 0x00, 0xB0, 0x00, 0x01, 0xD3, 0x44, 0xD3, 0x44, 0x67, 0x68, 0x78, 0x8D, 0x8E, 0x9A, 0x80, 0x82, 0x8F, 0x01, 0x83, 0x6F, 0x83, 0x78, 0x41, 0x43, 0x56, 0x9A, 0x9B, 0xA5, 0xF2, 0xF2, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xCD, 0xD2, 0x01, 0x0F, 0x84, 0x16, 0x01, 0x83, 0x60, 0x83, 0x7E, 0xD9, 0xD9, 0xDD, 0xF2, 0xF2, 0xF4, 0x9A, 0x9B, 0xA5, 0x5A, 0x5C, 0x6D, 0x9A, 0x9B, 0xA5, 0x01, 0x0C, 0x84, 0x01, 0x41, 0x43, 0x56, 0x01, 0x06, 0x1B, 0x01, 0x83, 0x5A, 0x84, 0x01, 0xD9, 0xD9, 0xDD, 0xD9, 0xD9, 0xDD, 0x4D, 0x4F, 0x62, 0x01, 0x06, 0x0F, 0x01, 0x0F, 0x84, 0x01, 0x34, 0x36, 0x4B, 0x74, 0x75, 0x83, 0xFF, 0xFF, 0xFF, 0x01, 0x09, 0x21, 0x01, 0x83, 0x4E, 0x83, 0x7E, 0x8D, 0x8E, 0x9A, 0xF2, 0xF2, 0xF4, 0x01, 0x0C, 0x83, 0x5D, 0x01, 0x12, 0x84, 0x01, 0x01, 0x06, 0x84, 0x25, 0xA6, 0xA7, 0xB0, 0x01, 0x83, 0x54, 0x84, 0x01, 0xE6, 0xE6, 0xE8, 0x01, 0x0F, 0x8B, 0x5F, 0x01, 0x15, 0x84, 0x01, 0x9A, 0x9B, 0xA5, 0xD9, 0xD9, 0xDD, 0x01, 0x83, 0x51, 0x83, 0x7E, 0x4D, 0x4F, 0x62, 0xFF, 0xFF, 0xFF, 0x5A, 0x5C, 0x6D, 0x01, 0x21, 0x84, 0x01, 0x67, 0x68, 0x78, 0xFF, 0xFF, 0xFF, 0x01, 0x83, 0x54, 0x9B, 0x75, 0x01, 0x12, 0x83, 0x57, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x83, 0x6C, 0x84, 0x01, 0x01, 0x2A, 0x8C, 0x03, 0xA6, 0xA7, 0xB0, 0x01, 0x12, 0x15, 0x01, 0x83, 0x6C, 0x94, 0x05, 0xE6, 0xE6, 0xE8, 0x01, 0x83, 0x57, 0x98, 0x06, 0x01, 0x06, 0xA8, 0x01, 0x41, 0x43, 0x56, 0x01, 0x1B, 0x84, 0x01, 0x8D, 0x8E, 0x9A, 0x01, 0x83, 0x5A, 0xA0, 0x08, 0x01, 0x09, 0xA4, 0x09, 0x01, 0x09, 0x84, 0x04, 0x01, 0x0F, 0x84, 0x01, 0x80, 0x82, 0x8F, 0xFF, 0xFF, 0xFF, 0x01, 0x83, 0x5D, 0xA8, 0x0A, 0x01, 0x0C, 0xAC, 0x0B, 0x4D, 0x4F, 0x62, 0x01, 0x09, 0x84, 0x01, 0x67, 0x68, 0x78, 0xB3, 0xB3, 0xBB, 0xFF, 0xFF, 0xFF, 0xB3, 0xB3, 0xBB, 0x01, 0x83, 0x63, 0xB4, 0x0D, 0xA6, 0xA7, 0xB0, 0x01, 0x06, 0xB4, 0x0A, 0x01, 0x06, 0x06, 0x01, 0x06, 0x06, 0xE6, 0xE6, 0xE8, 0x01, 0x83, 0x6C, 0xB8, 0x1A, 0x41, 0x43, 0x56, 0x74, 0x75, 0x83, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x01, 0x83, 0x60, 0xB8, 0x05, 0x01, 0x8C, 0x06, 0xCC, 0x01, 0x5A, 0x5C, 0x6D, 0xCC, 0xCD, 0xD2, 0x01, 0x0F, 0xA8, 0x0A, 0x01, 0x83, 0x6C, 0x84, 0x01, 0x01, 0x06, 0xAC, 0x0B, 0x01, 0x83, 0x7E, 0x88, 0x05, 0xE6, 0xE6, 0xE8, 0x74, 0x75, 0x83, 0x01, 0x83, 0x7B, 0x84, 0x01, 0x01, 0x15, 0xAF, 0x7A, 0x01, 0x83, 0x6F, 0x84, 0x04, 0x01, 0x83, 0x5A, 0xCB, 0x6F, 0x01, 0x2A, 0x2A, 0x01, 0x06, 0xBB, 0x6E, 0x74, 0x75, 0x83, 0x01, 0x0C, 0xB4, 0x16, 0x01, 0x83, 0x69, 0x98, 0x06, 0xCC, 0xCD, 0xD2, 0xCC, 0xCD, 0xD2, 0xD9, 0xD9, 0xDD, 0x01, 0x12, 0xAC, 0x0B, 0x01, 0x0F, 0x0F, 0x01, 0x83, 0x54, 0x98, 0x06, 0x01, 0x09, 0xAB, 0x79, 0x01, 0x09, 0x09, 0x01, 0x12, 0x12, 0x01, 0x09, 0x09, 0x01, 0x97, 0x6B, 0x81, 0x80, 0x23, 0x5A, 0x5C, 0x6D, 0x01, 0x83, 0x75, 0xB4, 0x1F, 0x67, 0x68, 0x78, 0xBF, 0xC0, 0xC7, 0x01, 0x15, 0x81, 0x80, 0x20, 0x01, 0x83, 0x63, 0xA4, 0x1E, 0x01, 0x06, 0xD3, 0x7D, 0xCC, 0xCD, 0xD2, 0x8D, 0x8E, 0x9A, 0xB3, 0xB3, 0xBB, 0x01, 0x12, 0x81, 0x80, 0x20, 0x01, 0x83, 0x5D, 0xB4, 0x31, 0xB3, 0xB3, 0xBB, 0x01, 0x0C, 0x83, 0x63, 0x01, 0x12, 0xB4, 0x1F, 0x01, 0x12, 0xE0, 0x3C, 0x01, 0x83, 0x4B, 0x83, 0x7E, 0x01, 0x06, 0x81, 0x83, 0x7D, 0x01, 0x0C, 0xD4, 0x00, 0x01, 0x18, 0xE8, 0x1A, 0x8D, 0x8E, 0x9A, 0x01, 0x83, 0x54, 0x84, 0x01, 0xCC, 0xCD, 0xD2, 0x01, 0x0F, 0xDF, 0x77, 0x01, 0x83, 0x66, 0xF0, 0x1C, 0x01, 0x06, 0xEB, 0x68, 0x41, 0x43, 0x56, 0x01, 0x0F, 0x87, 0x7F, 0x01, 0x18, 0x84, 0x01, 0x01, 0x06, 0x88, 0x29, 0x01, 0x83, 0x4B, 0x97, 0x71, 0x01, 0x06, 0xB3, 0x5A, 0x01, 0x83, 0x75, 0xFC, 0x1F, 0x01, 0x06, 0x97, 0x56, 0x01, 0x06, 0x87, 0x76, 0x01, 0x83, 0x75, 0x84, 0x01, 0x01, 0x0C, 0xC8, 0x00, 0x5A, 0x5C, 0x6D, 0x01, 0x12, 0xF7, 0x77, 0x01, 0x15, 0x84, 0x01, 0x8D, 0x8E, 0x9A, 0x01, 0x83, 0x45, 0x81, 0x90, 0x24, 0xA6, 0xA7, 0xB0, 0xE6, 0xE6, 0xE8, 0x01, 0x0C, 0x9B, 0x51, 0xF2, 0xF2, 0xF4, 0x01, 0x0F, 0xEF, 0x7E, 0x01, 0x18, 0x81, 0x98, 0x26, 0x01, 0x3C, 0xF4, 0x23, 0x5D, 0x5E, 0x6F, 0xE4, 0xE4, 0xE7, 0x5D, 0x5E, 0x6F, 0x78, 0x79, 0x87, 0x01, 0x83, 0x00, 0x97, 0x74, 0x01, 0x0F, 0x93, 0x73, 0xB3, 0xB3, 0xBB, 0xE6, 0xE6, 0xE8, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x06, 0x8C, 0x00, 0x01, 0x3C, 0xF0, 0x2B, 0xF1, 0xF2, 0xF3, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0x94, 0x74, 0x01, 0x82, 0x2C, 0xF7, 0x2F, 0x01, 0x51, 0xA2, 0x7C, 0x01, 0x12, 0xA7, 0x51, 0x01, 0x06, 0x90, 0x13, 0x01, 0x0C, 0x87, 0x5E, 0x01, 0x0F, 0x84, 0x01, 0x5A, 0x5C, 0x6D, 0xF2, 0xF2, 0xF4, 0xBF, 0xC0, 0xC7, 0x01, 0x3C, 0x78, 0x01, 0x09, 0xCC, 0x52, 0x01, 0x81, 0x6A, 0x84, 0x01, 0x5A, 0x5C, 0x6D, 0x67, 0x68, 0x78, 0x01, 0x39, 0x83, 0x42, 0x01, 0x06, 0xAF, 0x17, 0x01, 0x66, 0xCB, 0x06, 0x01, 0x06, 0x83, 0x63, 0x01, 0x09, 0x88, 0x1D, 0x01, 0x0C, 0x84, 0x01, 0x80, 0x82, 0x8F, 0xF2, 0xF2, 0xF4, 0x01, 0x0C, 0x81, 0x84, 0x3F, 0x01, 0x3C, 0x88, 0x02, 0x93, 0x94, 0x9F, 0xE4, 0xE4, 0xE7, 0x01, 0x81, 0x6A, 0x8A, 0x6D, 0x01, 0x3C, 0x8A, 0x37, 0x01, 0x06, 0xE7, 0x34, 0xF2, 0xF2, 0xF4, 0x01, 0x69, 0x85, 0x2F, 0x01, 0x06, 0xD4, 0x15, 0xE6, 0xE6, 0xE8, 0xE6, 0xE6, 0xE8, 0x01, 0x06, 0x84, 0x10, 0x01, 0x06, 0x87, 0x37, 0xB3, 0xB3, 0xBB, 0x01, 0x42, 0x89, 0x09, 0x5D, 0x5E, 0x6F, 0xD6, 0xD7, 0xDB, 0xC9, 0xC9, 0xCF, 0x4F, 0x51, 0x63, 0x01, 0x82, 0x26, 0x84, 0x01, 0x01, 0x06, 0x92, 0x78, 0x01, 0x12, 0x81, 0x97, 0x43, 0x01, 0x60, 0xAC, 0x17, 0x01, 0x06, 0xA7, 0x72, 0x01, 0x06, 0xD8, 0x28, 0x01, 0x06, 0x81, 0x88, 0x31, 0x01, 0x82, 0x3B, 0x92, 0x6F, 0x01, 0x3F, 0x84, 0x01, 0x01, 0x06, 0x8C, 0x06, 0x01, 0x81, 0x46, 0x81, 0x83, 0x26, 0xA0, 0xA1, 0xAB, 0x4F, 0x51, 0x63, 0x4F, 0x51, 0x63, 0x93, 0x94, 0x9F, 0x01, 0x82, 0x29, 0x84, 0x01, 0x01, 0x06, 0xBB, 0x23, 0x01, 0x81, 0x46, 0xB3, 0x03, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x81, 0x6A, 0x94, 0x05, 0x01, 0x42, 0x84, 0x01, 0x01, 0x42, 0x42, 0x01, 0x83, 0x3C, 0x84, 0x01, 0x01, 0x06, 0x9E, 0x33, 0x01, 0x6F, 0x90, 0x04, 0x01, 0x5A, 0x5A, 0x85, 0x86, 0x93, 0x01, 0x06, 0x81, 0x4F, 0x85, 0x86, 0x93, 0x01, 0x82, 0x23, 0x84, 0x01, 0x41, 0x43, 0x56, 0x01, 0x06, 0x90, 0x01, 0x01, 0x0F, 0xA3, 0x23, 0x01, 0x81, 0x40, 0xA1, 0x5A, 0x01, 0x81, 0x61, 0xC4, 0x53, 0x67, 0x68, 0x78, 0x67, 0x68, 0x78, 0x01, 0x06, 0x06, 0x01, 0x06, 0x97, 0x44, 0x8D, 0x8E, 0x9A, 0x01, 0x0C, 0x15, 0x01, 0x0C, 0x0C, 0x01, 0x18, 0x18, 0x8D, 0x8E, 0x9A, 0xE6, 0xE6, 0xE8, 0x01, 0x06, 0x86, 0x30, 0x01, 0x72, 0xCB, 0x09, 0x01, 0x1E, 0x81, 0x1C, 0x01, 0x82, 0x20, 0x97, 0x7A, 0x01, 0x21, 0xF2, 0x5D, 0x01, 0x21, 0x21, 0x01, 0x0C, 0x0C, 0x01, 0x6C, 0x81, 0xA3, 0x1F, 0x74, 0x75, 0x83, 0x01, 0x5D, 0xF4, 0x1D, 0x01, 0x81, 0x67, 0x8F, 0x7B, 0x01, 0x48, 0x83, 0x7B, 0xD9, 0xD9, 0xDD, 0x01, 0x6C, 0x87, 0x7C, 0x01, 0x06, 0x98, 0x6F, 0x01, 0x06, 0x81, 0xB4, 0x36, 0x74, 0x75, 0x83, 0x01, 0x54, 0x88, 0x02, 0xFF, 0xFF, 0xFF, 0x01, 0x06, 0xA8, 0x0D, 0xF1, 0xF2, 0xF3, 0x01, 0x82, 0x20, 0x8C, 0x03, 0x01, 0x75, 0xD0, 0x14, 0x01, 0x60, 0x81, 0x84, 0x21, 0x01, 0x06, 0xA0, 0x05, 0x01, 0x06, 0x06, 0x01, 0x82, 0x29, 0x9C, 0x07, 0x01, 0x69, 0xC0, 0x1F, 0x01, 0x3F, 0xB3, 0x69, 0x01, 0x82, 0x59, 0xA8, 0x0A, 0x01, 0x66, 0x97, 0x1A, 0x01, 0x66, 0x94, 0x6B, 0x01, 0x06, 0x8C, 0x00, 0x01, 0x81, 0x61, 0x8C, 0x03, 0x01, 0x81, 0x31, 0x84, 0x01, 0x01, 0x69, 0xCB, 0x69, 0x01, 0x06, 0x8B, 0x7D, 0x6A, 0x6C, 0x7B, 0x01, 0x81, 0x6A, 0x84, 0x01, 0x01, 0x06, 0xB2, 0x56, 0x01, 0x81, 0x1F, 0xA3, 0x47, 0x01, 0x72, 0xCF, 0x6A, 0x01, 0x83, 0x0F, 0xD0, 0x59, 0x01, 0x06, 0xD0, 0x14, 0x01, 0x63, 0xA3, 0x20, 0x01, 0x09, 0x98, 0x03, 0xC9, 0xC9, 0xCF, 0x01, 0x83, 0x75, 0x81, 0xA4, 0x29, 0x01, 0x81, 0x70, 0x98, 0x03, 0x01, 0x85, 0x2C, 0x81, 0xA4, 0x29, 0x01, 0x06, 0x81, 0xCC, 0x30, 0x01, 0x60, 0x81, 0xC8, 0x17, 0x4F, 0x51, 0x63, 0xC9, 0xC9, 0xCF, 0x01, 0x81, 0x6D, 0xC8, 0x12, 0x01, 0x81, 0x2E, 0x84, 0x04, 0xCC, 0xCD, 0xD2, 0x01, 0x54, 0xD5, 0x04, 0x01, 0x09, 0x09, 0xE4, 0xE4, 0xE7, 0x85, 0x86, 0x93, 0x85, 0x86, 0x93, 0x01, 0x51, 0xD0, 0x14, 0x4D, 0x4F, 0x62, 0x01, 0x06, 0x81, 0xC9, 0x66, 0x01, 0x06, 0xA6, 0x74, 0x01, 0x81, 0x2B, 0xEB, 0x1A, 0x01, 0x09, 0x81, 0x9E, 0x7D, 0x80, 0x82, 0x8F, 0x01, 0x66, 0x98, 0x2D, 0x01, 0x0C, 0x81, 0xA4, 0x17, 0x01, 0x09, 0x09, 0x01, 0x09, 0x09, 0x01, 0x09, 0xAD, 0x06, 0x01, 0x1B, 0x24, 0x01, 0x81, 0x0D, 0xC0, 0x10, 0x01, 0x06, 0x81, 0x4F, 0x01, 0x09, 0xAE, 0x40, 0xFD, 0xFE, 0xFE, 0xFB, 0xFD, 0xFE, 0xF9, 0xFB, 0xFD, 0xC6, 0xC9, 0xD0, 0x90, 0x99, 0xA8, 0x6F, 0x72, 0x82, 0x01, 0x81, 0x10, 0xB8, 0x7D, 0x4D, 0x4F, 0x62, 0x01, 0x06, 0xAE, 0x76, 0x01, 0x15, 0xB0, 0x00, 0x01, 0x06, 0xAF, 0x0B, 0x01, 0x5D, 0x81, 0x34, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x1B, 0x1B, 0x01, 0x42, 0x84, 0x01, 0x01, 0x51, 0x88, 0x02, 0x01, 0x06, 0xD9, 0x2F, 0x01, 0x0C, 0x82, 0x41, 0x01, 0x09, 0x84, 0x01, 0xF7, 0xFA, 0xFC, 0xF4, 0xF8, 0xFB, 0xF2, 0xF7, 0xFA, 0xF0, 0xF5, 0xF9, 0xCB, 0xD0, 0xD8, 0xA6, 0xAC, 0xB7, 0x78, 0x7C, 0x8B, 0x56, 0x59, 0x6B, 0x01, 0x81, 0x10, 0x81, 0xD7, 0x14, 0xE6, 0xE6, 0xE8, 0x01, 0x0C, 0x85, 0x41, 0x01, 0x06, 0x06, 0x01, 0x81, 0x58, 0x81, 0x87, 0x0C, 0x01, 0x4E, 0x90, 0x04, 0x01, 0x15, 0x81, 0xD9, 0x61, 0x01, 0x15, 0x84, 0x01, 0xEE, 0xF4, 0xF9, 0xEE, 0xF4, 0xF9, 0xE8, 0xF0, 0xF7, 0xE7, 0xEF, 0xF6, 0xDA, 0xE2, 0xEA, 0xAC, 0xB4, 0xBF, 0x8A, 0x90, 0x9F, 0x5E, 0x63, 0x75, 0x01, 0x72, 0x92, 0x66, 0x01, 0x0C, 0x87, 0x67, 0x01, 0x0F, 0x8B, 0x71, 0x01, 0x06, 0x81, 0xD7, 0x2C, 0x01, 0x0C, 0x88, 0x1D, 0x01, 0x82, 0x1A, 0x81, 0xB7, 0x3C, 0x01, 0x06, 0x91, 0x2F, 0x01, 0x15, 0x8A, 0x43, 0x01, 0x18, 0x84, 0x01, 0xEA, 0xF2, 0xF8, 0xEA, 0xF2, 0xF8, 0xE7, 0xEF, 0xF6, 0xE5, 0xEE, 0xF5, 0xE2, 0xED, 0xF4, 0xE0, 0xEB, 0xF3, 0xDE, 0xEA, 0xF3, 0xDB, 0xE8, 0xF2, 0xAC, 0xC7, 0xE1, 0x90, 0x99, 0xA8, 0x61, 0x6C, 0x83, 0x49, 0x4B, 0x5C, 0x01, 0x66, 0x83, 0x7E, 0x01, 0x21, 0xE3, 0x66, 0x01, 0x09, 0xDF, 0x1D, 0x01, 0x81, 0x58, 0x81, 0xE7, 0x2A, 0x01, 0x3F, 0x8D, 0x61, 0x5A, 0x5C, 0x6D, 0xE6, 0xE6, 0xE9, 0x01, 0x18, 0x8E, 0x44, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x06, 0x88, 0x02, 0x01, 0x0F, 0x84, 0x01, 0xD9, 0xE7, 0xF1, 0xD7, 0xE5, 0xF0, 0xD5, 0xE4, 0xEF, 0xD2, 0xE2, 0xEE, 0xBB, 0xD2, 0xE4, 0x94, 0xA0, 0xB0, 0x76, 0x7F, 0x91, 0x50, 0x55, 0x69, 0x01, 0x51, 0xAC, 0x11, 0x01, 0x06, 0x8B, 0x59, 0x01, 0x2A, 0x95, 0x21, 0x01, 0x09, 0x88, 0x0B, 0x01, 0x81, 0x46, 0xC7, 0x02, 0xBB, 0xBC, 0xC3, 0x85, 0x86, 0x93, 0x01, 0x06, 0xB4, 0x76, 0x01, 0x3C, 0xA8, 0x0A, 0x01, 0x12, 0x8F, 0x75, 0x01, 0x4B, 0x84, 0x01, 0xD0, 0xE1, 0xED, 0xCE, 0xDF, 0xED, 0xCC, 0xDE, 0xEC, 0xC9, 0xDC, 0xEB, 0xBB, 0xD2, 0xE4, 0x7D, 0x88, 0x01, 0x46, 0xDB, 0x0A, 0x01, 0x06, 0xAE, 0x6A, 0xFF, 0xFF, 0xFF, 0x01, 0x30, 0x9E, 0x66, 0x01, 0x06, 0x89, 0x66, 0x01, 0x81, 0x46, 0xD0, 0x11, 0x01, 0x06, 0x97, 0x77, 0xBB, 0xBC, 0xC3, 0xA0, 0xA1, 0xAB, 0x01, 0x39, 0x98, 0x06, 0x01, 0x15, 0x8F, 0x75, 0x01, 0x30, 0x90, 0x04, 0x01, 0x27, 0x84, 0x01, 0xC7, 0xDB, 0xEA, 0xC5, 0xDA, 0xE9, 0xA8, 0xBA, 0xCB, 0x3F, 0x41, 0x01, 0x40, 0x97, 0x11, 0x01, 0x06, 0xD3, 0x59, 0x01, 0x33, 0xCB, 0x5A, 0x4D, 0x4F, 0x62, 0x01, 0x06, 0x85, 0x6E, 0x01, 0x81, 0x43, 0x81, 0xEB, 0x37, 0xD6, 0xD7, 0xDB, 0x01, 0x09, 0xBC, 0x06, 0x93, 0x94, 0x9F, 0xD6, 0xD7, 0xDB, 0x01, 0x48, 0x8F, 0x75, 0x01, 0x3F, 0x90, 0x04, 0x01, 0x1E, 0x84, 0x01, 0xC3, 0xD8, 0xE8, 0x9D, 0xAF, 0xC1, 0x01, 0x42, 0xBE, 0x6B, 0x01, 0x39, 0x81, 0xFA, 0x76, 0x01, 0x06, 0x85, 0x74, 0x01, 0x6C, 0xC3, 0x2B, 0x4D, 0x4F, 0x62, 0xA6, 0xA7, 0xB0, 0x01, 0x0C, 0xD0, 0x1A, 0x01, 0x06, 0x81, 0xA0, 0x37, 0x01, 0x42, 0x9D, 0x1A, 0x01, 0x09, 0x42, 0x01, 0x30, 0x98, 0x03, 0x01, 0x1E, 0x8F, 0x75, 0x01, 0x57, 0x8C, 0x03, 0x01, 0x09, 0x84, 0x01, 0xC0, 0xD6, 0xE9, 0x61, 0x6C, 0x01, 0x3A, 0x9B, 0x12, 0x01, 0x06, 0x81, 0xFA, 0x76, 0x01, 0x39, 0x83, 0x42, 0x01, 0x06, 0xF4, 0x1D, 0x01, 0x69, 0xBA, 0x3D, 0x01, 0x09, 0x8E, 0x62, 0xBF, 0xC0, 0xC7, 0x01, 0x09, 0xA5, 0x22, 0x01, 0x09, 0xF4, 0x2F, 0x01, 0x75, 0xBD, 0x55, 0x01, 0x21, 0x8F, 0x75, 0x01, 0x5D, 0x84, 0x01, 0xBB, 0xD2, 0xE4, 0x94, 0xB3, 0xD9, 0x7A, 0x94, 0xC2, 0x01, 0x3F, 0x93, 0x7F, 0x01, 0x3C, 0xEB, 0x59, 0x01, 0x06, 0xDC, 0x1D, 0x01, 0x63, 0x94, 0x0B, 0x01, 0x09, 0x85, 0x2C, 0x01, 0x12, 0x89, 0x2D, 0x01, 0x06, 0xD1, 0x5D, 0xF2, 0xF2, 0xF4, 0x01, 0x6F, 0x84, 0x04, 0x01, 0x24, 0x8F, 0x75, 0x01, 0x5A, 0x90, 0x04, 0xAC, 0xC7, 0xE1, 0x88, 0xA9, 0xD5, 0x84, 0xA3, 0xD3, 0x83, 0xA0, 0xD2, 0x51, 0x5D, 0x7D, 0x01, 0x81, 0x5E, 0xEC, 0x1B, 0x01, 0x06, 0x88, 0x6B, 0x01, 0x1B, 0x91, 0x29, 0x01, 0x06, 0x9D, 0x4A, 0x01, 0x69, 0x95, 0x12, 0x01, 0x2A, 0x8F, 0x75, 0x01, 0x54, 0x90, 0x04, 0xC5, 0xD9, 0xEA, 0x9F, 0xBC, 0xDD, 0x86, 0xA7, 0xD4, 0x85, 0xA4, 0xD3, 0x83, 0xA1, 0xD2, 0x82, 0x9F, 0xD2, 0x6D, 0x83, 0xAF, 0x01, 0x78, 0x83, 0x3F, 0x01, 0x42, 0x88, 0x44, 0x01, 0x27, 0x9C, 0x76, 0x01, 0x21, 0x83, 0x5D, 0x01, 0x06, 0x84, 0x25, 0x01, 0x63, 0x95, 0x12, 0x01, 0x2D, 0x8F, 0x75, 0x01, 0x51, 0x8C, 0x03, 0xC4, 0xD8, 0xE9, 0x94, 0xB3, 0xD9, 0x87, 0xA8, 0xD4, 0x85, 0xA5, 0xD3, 0x84, 0xA2, 0xD3, 0x83, 0xA0, 0xD2, 0x81, 0x9D, 0xD1, 0x80, 0x9B, 0xD0, 0x4E, 0x55, 0x6F, 0x01, 0x7B, 0xF8, 0x1E, 0x01, 0x60, 0xAC, 0x1A, 0x01, 0x12, 0x81, 0x94, 0x25, 0x01, 0x18, 0x81, 0x0D, 0x01, 0x60, 0x95, 0x12, 0x01, 0x30, 0x8F, 0x75, 0x01, 0x4E, 0x84, 0x01, 0xC0, 0xD6, 0xE9, 0x8D, 0xAF, 0xD7, 0x87, 0xA9, 0xD5, 0x86, 0xA6, 0x01, 0x08, 0x87, 0x7F, 0x9E, 0xD1, 0x80, 0x9C, 0xD1, 0x7F, 0x99, 0xD0, 0x6A, 0x7C, 0xAD, 0x01, 0x39, 0x83, 0x3F, 0x01, 0x81, 0x1F, 0x8C, 0x03, 0x01, 0x15, 0x81, 0x9C, 0x27, 0x01, 0x1B, 0x83, 0x1E, 0x01, 0x3C, 0xF4, 0x1D, 0xE4, 0xE4, 0xE7, 0x01, 0x1B, 0xD8, 0x16, 0x01, 0x33, 0x8F, 0x75, 0x01, 0x4B, 0x90, 0x04, 0xB6, 0xD0, 0xE6, 0x88, 0xAB, 0xD5, 0x88, 0xAA, 0xD5, 0x87, 0xA7, 0x01, 0x07, 0x87, 0x7F, 0x82, 0x9F, 0xD2, 0x81, 0x9D, 0xD1, 0x7F, 0x9A, 0xD0, 0x7E, 0x96, 0xCF, 0x7D, 0x95, 0xCF, 0x46, 0x4E, 0x6C, 0x01, 0x33, 0x82, 0xB3, 0x25, 0x01, 0x45, 0x94, 0x05, 0x01, 0x5D, 0x81, 0x87, 0x24, 0x01, 0x2A, 0xD4, 0x15, 0x01, 0x3F, 0xD4, 0x3F, 0xFF, 0xFF, 0xFF, 0x6A, 0x6C, 0x7B, 0x01, 0x15, 0xCC, 0x16, 0x01, 0x39, 0x8F, 0x75, 0x01, 0x48, 0x90, 0x04, 0xB8, 0xCF, 0xE5, 0x8A, 0xAE, 0xD6, 0x89, 0xAB, 0xD5, 0x87, 0xA8, 0xD4, 0x86, 0xA6, 0xD4, 0x01, 0x06, 0x93, 0x7C, 0x81, 0x9E, 0xD1, 0x80, 0x9B, 0xD0, 0x7F, 0x98, 0xD0, 0x7D, 0x96, 0xCF, 0x7C, 0x93, 0xCE, 0x01, 0x33, 0x88, 0x05, 0x01, 0x06, 0x86, 0x5D, 0x01, 0x39, 0x8A, 0x37, 0x01, 0x06, 0x3F, 0x01, 0x60, 0x92, 0x7B, 0x01, 0x81, 0x04, 0x84, 0x01, 0x01, 0x24, 0xF1, 0x14, 0x01, 0x5A, 0x8C, 0x03, 0xA7, 0xC5, 0xE0, 0x8B, 0xAF, 0xD6, 0x89, 0xAC, 0xD5, 0x88, 0xAA, 0xD5, 0x01, 0x07, 0x93, 0x7C, 0xA2, 0xD2, 0x82, 0x9F, 0xD2, 0x81, 0x01, 0x05, 0x8B, 0x7D, 0x7E, 0x97, 0xCF, 0x7C, 0x94, 0xCF, 0x7B, 0x92, 0xCE, 0x79, 0x8E, 0xCD, 0x01, 0x33, 0x88, 0x05, 0x01, 0x06, 0x85, 0x59, 0x01, 0x36, 0x87, 0x43, 0x01, 0x06, 0x8C, 0x42, 0x01, 0x63, 0xB8, 0x17, 0x01, 0x27, 0x8C, 0x66, 0x01, 0x3F, 0x81, 0xA8, 0x2A, 0x01, 0x18, 0xE4, 0x19, 0x9A, 0x9B, 0xA5, 0x01, 0x48, 0xF2, 0x51, 0x01, 0x33, 0x84, 0x01, 0xA7, 0xC5, 0xE0, 0x8B, 0xB0, 0xD7, 0x8A, 0xAD, 0xD6, 0x88, 0x01, 0x05, 0x87, 0x7F, 0x85, 0xA5, 0xD3, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x05, 0x93, 0x7C, 0x7E, 0x98, 0xD0, 0x7D, 0x95, 0xCF, 0x7C, 0x93, 0xCE, 0x7A, 0x90, 0xCD, 0x79, 0x8D, 0xCD, 0x62, 0x70, 0xA4, 0x01, 0x36, 0x86, 0x60, 0x01, 0x33, 0x88, 0x05, 0x01, 0x09, 0xA4, 0x06, 0x01, 0x63, 0x81, 0x93, 0x24, 0xBF, 0xC0, 0xC7, 0x01, 0x24, 0x84, 0x67, 0x01, 0x57, 0x81, 0xF4, 0x61, 0x01, 0x39, 0x97, 0x74, 0x01, 0x42, 0x90, 0x04, 0xAF, 0xCA, 0xE3, 0x8C, 0xB0, 0xD7, 0x8A, 0xAE, 0xD6, 0x89, 0xAC, 0xD5, 0x01, 0x0D, 0x93, 0x7C, 0x9F, 0xD2, 0x01, 0x06, 0x93, 0x7C, 0x7E, 0x96, 0xCF, 0x7C, 0x94, 0xCF, 0x7A, 0x90, 0xCD, 0x79, 0x8E, 0xCD, 0x78, 0x8C, 0xCC, 0x76, 0x89, 0xCC, 0x3C, 0x40, 0x5B, 0x01, 0x36, 0x87, 0x49, 0x01, 0x2D, 0x9A, 0x41, 0x01, 0x09, 0xBC, 0x42, 0x01, 0x66, 0xC0, 0x16, 0x01, 0x15, 0x82, 0xB0, 0x4F, 0x01, 0x15, 0x94, 0x02, 0x01, 0x51, 0x85, 0x0E, 0x01, 0x06, 0x8D, 0x67, 0x01, 0x63, 0x88, 0x02, 0x01, 0x12, 0x90, 0x04, 0xC0, 0xD6, 0xE9, 0x8C, 0xB2, 0xD7, 0x01, 0x07, 0x87, 0x7F, 0xAA, 0x01, 0x08, 0x87, 0x7F, 0x01, 0x11, 0x93, 0x7C, 0x7B, 0x92, 0xCE, 0x7A, 0x90, 0xCD, 0x78, 0x8D, 0xCD, 0x77, 0x8A, 0xCC, 0x76, 0x88, 0xCB, 0x5D, 0x67, 0xA1, 0x01, 0x39, 0xC0, 0x10, 0x01, 0x27, 0x84, 0x04, 0x01, 0x09, 0x30, 0x01, 0x42, 0x81, 0xA3, 0x1C, 0x01, 0x2D, 0x9B, 0x00, 0xD9, 0xD9, 0xDD, 0x01, 0x18, 0x84, 0x04, 0x74, 0x75, 0x83, 0x01, 0x27, 0x9C, 0x2B, 0x01, 0x1B, 0x1B, 0x6A, 0x6C, 0x7B, 0x01, 0x12, 0x81, 0xB0, 0x2C, 0x01, 0x09, 0xBA, 0x2E, 0x01, 0x6F, 0x8C, 0x03, 0xC0, 0xD6, 0xE9, 0x8D, 0xB3, 0xD7, 0x8C, 0xB2, 0x01, 0x05, 0x87, 0x7F, 0xAB, 0xD5, 0x87, 0xA9, 0x01, 0x08, 0x93, 0x7C, 0x01, 0x05, 0x9B, 0x7B, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x06, 0x93, 0x7C, 0x7A, 0x91, 0xCE, 0x79, 0x8E, 0xCD, 0x78, 0x8B, 0xCC, 0x76, 0x88, 0xCB, 0x75, 0x86, 0xCB, 0x73, 0x83, 0xCA, 0x01, 0x33, 0x88, 0x05, 0x01, 0x09, 0x81, 0x8B, 0x70, 0x01, 0x21, 0xD6, 0x77, 0x67, 0x68, 0x78, 0x01, 0x06, 0x97, 0x7A, 0x01, 0x6C, 0x83, 0x7E, 0x01, 0x0C, 0xAB, 0x73, 0x01, 0x0F, 0x81, 0xA0, 0x19, 0x5A, 0x5C, 0x6D, 0x01, 0x33, 0x89, 0x42, 0x01, 0x2A, 0x81, 0xB0, 0x2C, 0x01, 0x75, 0x84, 0x01, 0xD1, 0xE1, 0xEF, 0x8E, 0xB4, 0xD8, 0x8C, 0xB2, 0xD7, 0x01, 0x05, 0x93, 0x7C, 0xD6, 0x01, 0x13, 0x93, 0x7C, 0x9A, 0x01, 0x0A, 0x93, 0x7C, 0x7A, 0x8F, 0x01, 0x07, 0x87, 0x7F, 0x75, 0x87, 0xCB, 0x74, 0x85, 0xCA, 0x72, 0x82, 0xC9, 0x5B, 0x65, 0x01, 0x37, 0x9B, 0x57, 0x01, 0x06, 0x8A, 0x46, 0x01, 0x06, 0x81, 0xAF, 0x16, 0x01, 0x0F, 0x81, 0xFF, 0x27, 0x4D, 0x4F, 0x62, 0x80, 0x82, 0x8F, 0x01, 0x09, 0x9A, 0x0B, 0xBF, 0xC0, 0xC7, 0x01, 0x69, 0x83, 0x7E, 0x01, 0x0F, 0xD4, 0x27, 0x01, 0x30, 0x82, 0x74, 0x01, 0x2A, 0xC9, 0x37, 0x01, 0x15, 0x81, 0xB0, 0x2C, 0x01, 0x66, 0x84, 0x01, 0x01, 0x0C, 0x90, 0x04, 0xDA, 0xE7, 0xF2, 0x94, 0xB3, 0xD9, 0x8D, 0xB3, 0x01, 0x05, 0x8B, 0x7D, 0xAE, 0x01, 0x07, 0x93, 0x7C, 0x01, 0x0A, 0x9B, 0x7B, 0x01, 0x05, 0x8B, 0x7D, 0x7F, 0x01, 0x0C, 0x93, 0x7C, 0x8E, 0xCD, 0x76, 0x89, 0xCC, 0x76, 0x88, 0xCB, 0x74, 0x01, 0x05, 0x87, 0x7F, 0x71, 0x7F, 0xC9, 0x70, 0x7E, 0xC8, 0x39, 0x3C, 0x5A, 0x01, 0x2A, 0x98, 0x03, 0x01, 0x4E, 0x81, 0x8C, 0x35, 0x01, 0x0F, 0x0F, 0x01, 0x42, 0xA4, 0x24, 0x01, 0x30, 0x81, 0xFC, 0x3F, 0x01, 0x0F, 0x0F, 0x01, 0x2A, 0x81, 0x01, 0xA0, 0xA1, 0xAB, 0x01, 0x12, 0x81, 0x98, 0x26, 0x01, 0x69, 0x88, 0x02, 0x01, 0x09, 0x90, 0x04, 0x9E, 0xC0, 0xDD, 0x8D, 0xB4, 0xD8, 0x8C, 0xB0, 0x01, 0x06, 0x87, 0x7F, 0xD5, 0x88, 0xA9, 0x01, 0x08, 0x87, 0x7F, 0x01, 0x0C, 0x93, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x7A, 0x91, 0x01, 0x05, 0x8F, 0x7E, 0x8C, 0xCC, 0x01, 0x0A, 0x87, 0x7F, 0x81, 0xC9, 0x71, 0x7F, 0xC9, 0x6F, 0x7B, 0xC8, 0x01, 0x27, 0x88, 0x05, 0x01, 0x81, 0x25, 0x84, 0x01, 0x01, 0x7E, 0xD0, 0x11, 0x01, 0x6F, 0x8C, 0x03, 0xB6, 0xCD, 0xE5, 0x8E, 0xB6, 0x01, 0x05, 0x8B, 0x7D, 0x01, 0x11, 0x93, 0x7C, 0x01, 0x0F, 0x9B, 0x7B, 0x01, 0x0F, 0x93, 0x7C, 0x74, 0x85, 0xCA, 0x73, 0x83, 0xCA, 0x71, 0x80, 0xC9, 0x70, 0x7D, 0xC8, 0x6F, 0x7B, 0xC8, 0x6D, 0x78, 0xC7, 0x38, 0x3A, 0x53, 0x01, 0x24, 0x8B, 0x74, 0x01, 0x3C, 0x86, 0x5D, 0x01, 0x24, 0x24, 0x01, 0x12, 0x97, 0x17, 0x8D, 0x8E, 0x9A, 0x01, 0x81, 0x2B, 0x81, 0xA0, 0x58, 0x01, 0x6C, 0x84, 0x01, 0xCB, 0xDD, 0xED, 0x94, 0xB3, 0xD9, 0x8D, 0x01, 0x05, 0x8F, 0x7E, 0x01, 0x15, 0x93, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x7D, 0x96, 0xCF, 0x7C, 0x94, 0xCE, 0x01, 0x06, 0xA3, 0x7A, 0x78, 0x8B, 0xCC, 0x76, 0x89, 0xCC, 0x75, 0x86, 0xCB, 0x73, 0x84, 0x01, 0x05, 0x87, 0x7F, 0x7E, 0xC8, 0x6F, 0x7B, 0xC8, 0x6E, 0x79, 0xC7, 0x6C, 0x76, 0xC6, 0x51, 0x57, 0x8B, 0x01, 0x81, 0x1C, 0x82, 0x88, 0x12, 0xBF, 0xC0, 0xC7, 0x01, 0x81, 0x10, 0xCC, 0x4C, 0x01, 0x09, 0x81, 0xB8, 0x2E, 0x5D, 0x5E, 0x01, 0x0A, 0xB6, 0x5A, 0x01, 0x69, 0x90, 0x04, 0xE1, 0xE9, 0xF4, 0x95, 0xBB, 0xDA, 0x01, 0x09, 0x93, 0x7C, 0x8A, 0xAE, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x12, 0xAF, 0x77, 0x97, 0xCF, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x0E, 0x93, 0x7C, 0x01, 0x07, 0x8F, 0x7E, 0x7D, 0xC8, 0x6E, 0x7A, 0xC7, 0x6D, 0x78, 0xC7, 0x6C, 0x75, 0xC6, 0x6A, 0x79, 0xB3, 0x37, 0x39, 0x52, 0x01, 0x81, 0x1C, 0x86, 0x5D, 0xBF, 0xC0, 0xC7, 0x01, 0x06, 0x82, 0xCC, 0x05, 0x01, 0x81, 0x07, 0xEA, 0x1F, 0xF1, 0xF2, 0xF3, 0x01, 0x06, 0xE8, 0x1A, 0x01, 0x0C, 0xA8, 0x0A, 0x01, 0x69, 0x88, 0x02, 0xA7, 0xC5, 0xE0, 0x8E, 0xB6, 0xD8, 0x8D, 0xB3, 0xD7, 0x01, 0x06, 0xA3, 0x7A, 0x01, 0x10, 0x93, 0x7C, 0x9E, 0x01, 0x08, 0x93, 0x7C, 0x01, 0x06, 0x9B, 0x7B, 0x8F, 0x01, 0x05, 0xA3, 0x7A, 0x01, 0x05, 0x9B, 0x7B, 0x01, 0x06, 0x93, 0x7C, 0x72, 0x81, 0xC9, 0x70, 0x01, 0x0B, 0x87, 0x7F, 0x6B, 0x74, 0xC6, 0x69, 0x70, 0xC4, 0x4E, 0x51, 0x88, 0x01, 0x81, 0x16, 0x88, 0x02, 0xA6, 0xA7, 0xB0, 0x01, 0x09, 0x88, 0x02, 0x4D, 0x4F, 0x62, 0x01, 0x81, 0x07, 0x81, 0xBB, 0x70, 0x01, 0x15, 0xF0, 0x1C, 0x01, 0x66, 0x84, 0x01, 0xCF, 0xE0, 0xEE, 0x8E, 0xB6, 0xD8, 0x01, 0x06, 0x8B, 0x7D, 0x01, 0x15, 0x93, 0x7C, 0x01, 0x0C, 0xAF, 0x77, 0x7A, 0x90, 0xCD, 0x01, 0x0C, 0x93, 0x7C, 0x73, 0x84, 0xCA, 0x72, 0x82, 0x01, 0x07, 0x93, 0x7C, 0x6E, 0x7A, 0xC7, 0x6D, 0x77, 0xC7, 0x6B, 0x74, 0xC6, 0x6A, 0x72, 0xC5, 0x69, 0x70, 0xC4, 0x64, 0x69, 0xBC, 0x01, 0x24, 0x90, 0x0A, 0x01, 0x72, 0x82, 0xEC, 0x28, 0x01, 0x33, 0x90, 0x04, 0x01, 0x15, 0x88, 0x26, 0x41, 0x43, 0x56, 0x01, 0x06, 0x81, 0xF4, 0x46, 0x01, 0x06, 0xD4, 0x1B, 0x01, 0x42, 0x84, 0x01, 0x78, 0x79, 0x87, 0x78, 0x79, 0x87, 0xFF, 0xFF, 0xFF, 0x01, 0x09, 0xB4, 0x10, 0x01, 0x63, 0x84, 0x01, 0xE8, 0xF0, 0xF7, 0x95, 0xBB, 0xDA, 0x01, 0x06, 0x87, 0x7F, 0x01, 0x10, 0x93, 0x7C, 0x01, 0x1A, 0xAF, 0x77, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x11, 0x93, 0x7C, 0x6C, 0x76, 0xC6, 0x6A, 0x72, 0xC5, 0x6A, 0x71, 0xC5, 0x68, 0x6E, 0xC4, 0x66, 0x6B, 0xC3, 0x4A, 0x4B, 0x86, 0x01, 0x81, 0x49, 0x81, 0xDC, 0x49, 0x01, 0x12, 0xB1, 0x31, 0x01, 0x06, 0xA9, 0x11, 0x01, 0x09, 0xA0, 0x20, 0x01, 0x3F, 0x81, 0xA9, 0x37, 0x01, 0x09, 0xB4, 0x0D, 0x01, 0x06, 0x06, 0x6A, 0x6C, 0x7B, 0x01, 0x66, 0x84, 0x01, 0xB6, 0xD0, 0xE6, 0x8F, 0xB7, 0x01, 0x0B, 0x93, 0x7C, 0x01, 0x0E, 0xAF, 0x77, 0x81, 0x9D, 0x01, 0x14, 0x93, 0x7C, 0x01, 0x05, 0xAF, 0x77, 0x01, 0x06, 0xA7, 0x78, 0x01, 0x06, 0x9B, 0x7B, 0x70, 0x7D, 0xC8, 0x6E, 0x79, 0xC7, 0x6D, 0x77, 0xC6, 0x6B, 0x74, 0xC6, 0x01, 0x06, 0x83, 0x7E, 0x67, 0x6C, 0xC3, 0x64, 0x68, 0xC2, 0x5B, 0x5C, 0x01, 0x37, 0xCC, 0x2E, 0x01, 0x63, 0x96, 0x5E, 0x01, 0x30, 0xA5, 0x22, 0x01, 0x0F, 0x8C, 0x2A, 0x01, 0x06, 0xD4, 0x27, 0x01, 0x09, 0x48, 0x01, 0x12, 0x81, 0xF4, 0x61, 0x01, 0x81, 0x25, 0x98, 0x06, 0xE5, 0xEE, 0xF5, 0x8F, 0xB7, 0xD9, 0x01, 0x22, 0x93, 0x7C, 0x01, 0x09, 0x9B, 0x7B, 0x01, 0x12, 0x93, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x01, 0x0A, 0x93, 0x7C, 0x01, 0x05, 0x8B, 0x7D, 0x67, 0x6D, 0xC4, 0x66, 0x6B, 0xC3, 0x64, 0x68, 0xC2, 0x63, 0x65, 0x01, 0x3D, 0xE0, 0x39, 0x01, 0x5A, 0xA7, 0x5A, 0x01, 0x06, 0x81, 0x8B, 0x76, 0x01, 0x27, 0x8F, 0x7E, 0x01, 0x15, 0xB7, 0x67, 0xBF, 0xC0, 0xC7, 0x01, 0x0F, 0xFC, 0x0D, 0xB3, 0xB3, 0xBB, 0x01, 0x3C, 0x88, 0x05, 0x01, 0x15, 0x81, 0xB8, 0x2B, 0x01, 0x60, 0x84, 0x01, 0xA8, 0xC8, 0xE1, 0x01, 0x0C, 0x93, 0x7C, 0x01, 0x0D, 0x9B, 0x7B, 0xA0, 0xD2, 0x82, 0x01, 0x0F, 0x93, 0x7C, 0x01, 0x08, 0xAF, 0x77, 0x77, 0x8A, 0x01, 0x0B, 0x87, 0x7F, 0x01, 0x11, 0x93, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x65, 0x69, 0xC3, 0x64, 0x66, 0xC2, 0x62, 0x64, 0x01, 0x31, 0x84, 0x01, 0x01, 0x09, 0x82, 0xCF, 0x35, 0x01, 0x06, 0x8A, 0x5B, 0x01, 0x51, 0xB7, 0x70, 0x01, 0x09, 0x81, 0x80, 0x62, 0x01, 0x06, 0x83, 0x88, 0x32, 0x01, 0x27, 0xE5, 0x3E, 0x01, 0x12, 0x87, 0x5B, 0xF2, 0xF2, 0xF4, 0x01, 0x0F, 0x8F, 0x78, 0x80, 0x82, 0x8F, 0x01, 0x36, 0xC5, 0x1E, 0x41, 0x43, 0x56, 0x01, 0x06, 0xCC, 0x0D, 0xFF, 0xFF, 0xFF, 0xE4, 0xE4, 0xE7, 0x01, 0x0C, 0xC4, 0x11, 0x01, 0x5D, 0x84, 0x01, 0xDA, 0xE7, 0xF2, 0x01, 0x0C, 0x87, 0x7F, 0x01, 0x16, 0xC3, 0x73, 0x01, 0x0F, 0xAF, 0x77, 0x8C, 0x01, 0x0D, 0xAF, 0x77, 0x01, 0x0A, 0x9B, 0x7B, 0x77, 0x01, 0x07, 0x8F, 0x7E, 0x01, 0x0F, 0x87, 0x7F, 0x62, 0x62, 0x01, 0x2B, 0x84, 0x01, 0x01, 0x06, 0x92, 0x54, 0x01, 0x0F, 0xD1, 0x75, 0x01, 0x18, 0x81, 0x82, 0x73, 0x01, 0x39, 0x9B, 0x3C, 0x01, 0x0C, 0x83, 0x75, 0x01, 0x24, 0x84, 0x01, 0x01, 0x15, 0xC7, 0x68, 0x01, 0x06, 0xBC, 0x21, 0x01, 0x0F, 0x84, 0x16, 0x01, 0x39, 0xC8, 0x12, 0xD6, 0xD7, 0xDB, 0x01, 0x09, 0xAB, 0x7F, 0x85, 0x86, 0x93, 0x01, 0x0C, 0xEC, 0x1B, 0x01, 0x5D, 0x84, 0x01, 0x01, 0x09, 0x87, 0x7F, 0x01, 0x0C, 0xC3, 0x73, 0x01, 0x0C, 0xAF, 0x77, 0x01, 0x13, 0x93, 0x7C, 0x8C, 0x01, 0x13, 0x9B, 0x7B, 0x01, 0x12, 0x93, 0x7C, 0x64, 0x68, 0xC2, 0x64, 0x66, 0xC2, 0x62, 0x62, 0xC1, 0x55, 0x54, 0xA3, 0x01, 0x2A, 0x81, 0xB3, 0x11, 0x01, 0x0C, 0x83, 0x7B, 0x01, 0x06, 0x87, 0x7C, 0x01, 0x18, 0x84, 0x01, 0x01, 0x06, 0x81, 0xDF, 0x46, 0x01, 0x30, 0xA3, 0x4A, 0x41, 0x43, 0x56, 0x01, 0x06, 0x81, 0x8C, 0x7A, 0xA6, 0xA7, 0xB0, 0x67, 0x68, 0x78, 0xA6, 0xA7, 0xB0, 0x01, 0x24, 0x97, 0x3B, 0x01, 0x15, 0x83, 0x57, 0x01, 0x15, 0x81, 0xFC, 0x2A, 0x01, 0x39, 0x84, 0x01, 0x01, 0x0F, 0x36, 0x01, 0x66, 0x9C, 0x07, 0xDB, 0xE8, 0xF2, 0x01, 0x09, 0x9B, 0x7B, 0x01, 0x0A, 0x93, 0x7C, 0x01, 0x09, 0x9B, 0x7B, 0x01, 0x08, 0xA7, 0x78, 0x01, 0x0C, 0xCB, 0x72, 0x01, 0x07, 0x93, 0x7C, 0x87, 0x01, 0x17, 0x93, 0x7C, 0x72, 0x01, 0x07, 0x93, 0x7C, 0x65, 0x69, 0xC3, 0x64, 0x68, 0xC2, 0x62, 0x64, 0xC1, 0x61, 0x61, 0xC0, 0x45, 0x47, 0x76, 0x01, 0x2A, 0xE6, 0x78, 0x01, 0x09, 0x82, 0xDF, 0x24, 0x01, 0x09, 0x87, 0x5E, 0x01, 0x18, 0x84, 0x01, 0x01, 0x06, 0xD4, 0x4E, 0x01, 0x30, 0xE7, 0x0D, 0x01, 0x12, 0xB3, 0x57, 0x01, 0x24, 0x84, 0x43, 0x01, 0x15, 0x81, 0xA4, 0x29, 0x01, 0x06, 0xF0, 0x22, 0x01, 0x81, 0x3D, 0x84, 0x01, 0xAC, 0xC7, 0xE1, 0x01, 0x0A, 0x93, 0x7C, 0x01, 0x14, 0xAF, 0x77, 0x01, 0x0D, 0x93, 0x7C, 0x01, 0x17, 0xAF, 0x77, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x06, 0x8B, 0x7D, 0x65, 0x69, 0xC3, 0x63, 0x65, 0xC1, 0x62, 0x64, 0xC1, 0x01, 0x27, 0x98, 0x03, 0x01, 0x09, 0x83, 0x7E, 0x01, 0x12, 0x81, 0xE2, 0x7F, 0x01, 0x1B, 0x8C, 0x03, 0x01, 0x09, 0x82, 0x93, 0x53, 0x01, 0x66, 0xA3, 0x23, 0x01, 0x0F, 0xE0, 0x7B, 0x01, 0x15, 0x81, 0xF4, 0x28, 0x01, 0x39, 0x83, 0x88, 0x62, 0xA0, 0xA1, 0xAB, 0xC9, 0xC9, 0xCF, 0x6A, 0x6C, 0x7B, 0x6A, 0x6C, 0x7B, 0xC9, 0xC9, 0xCF, 0x01, 0x06, 0xFC, 0x25, 0x01, 0x5D, 0x84, 0x01, 0xEA, 0xF2, 0xF8, 0x01, 0x07, 0x87, 0x7F, 0x01, 0x12, 0x93, 0x7C, 0x01, 0x05, 0x87, 0x7F, 0x7F, 0x9A, 0xD0, 0x01, 0x13, 0xC3, 0x73, 0x01, 0x17, 0xAF, 0x77, 0x01, 0x0C, 0x9B, 0x7B, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x27, 0x87, 0x7F, 0x01, 0x09, 0xCF, 0x5B, 0x01, 0x15, 0x96, 0x40, 0x01, 0x1E, 0x90, 0x04, 0x01, 0x06, 0x8C, 0x33, 0x01, 0x63, 0xB7, 0x70, 0xB3, 0xB3, 0xBB, 0x01, 0x0C, 0xC5, 0x00, 0x01, 0x06, 0x83, 0x15, 0x01, 0x12, 0xE5, 0x0E, 0x01, 0x3C, 0x81, 0xF8, 0x3E, 0x01, 0x06, 0xFC, 0x16, 0xD6, 0xD7, 0xDB, 0x01, 0x0F, 0x81, 0xE0, 0x35, 0x01, 0x57, 0x84, 0x01, 0xB6, 0xD0, 0xE6, 0x01, 0x0F, 0xC3, 0x73, 0x87, 0x01, 0x05, 0x8B, 0x7D, 0x01, 0x07, 0x9B, 0x7B, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x14, 0x9B, 0x7B, 0x01, 0x0A, 0x8B, 0x7D, 0x01, 0x1D, 0x93, 0x7C, 0x5D, 0x5D, 0xB8, 0x01, 0x2A, 0xBC, 0x12, 0x01, 0x18, 0x83, 0x66, 0x01, 0x1E, 0x87, 0x64, 0x01, 0x06, 0xD6, 0x2F, 0x01, 0x63, 0x81, 0xCC, 0x36, 0x01, 0x06, 0x81, 0x81, 0x0C, 0x01, 0x06, 0x81, 0x91, 0x3D, 0xA6, 0xA7, 0xB0, 0x01, 0x06, 0x81, 0xF0, 0x2A, 0x01, 0x15, 0x85, 0x4A, 0x01, 0x51, 0xE9, 0x24, 0x01, 0x54, 0x84, 0x01, 0xF2, 0xF7, 0xFA, 0x95, 0xBB, 0xDA, 0x01, 0x19, 0xC3, 0x73, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x0F, 0x9B, 0x7B, 0x01, 0x14, 0x93, 0x7C, 0x01, 0x06, 0x87, 0x7F, 0x6A, 0x72, 0xC5, 0x01, 0x06, 0x8F, 0x7E, 0x01, 0x06, 0x8B, 0x7D, 0x01, 0x36, 0x87, 0x7F, 0x01, 0x18, 0x9F, 0x10, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x6C, 0x81, 0xF0, 0x3C, 0x01, 0x0C, 0x81, 0x9E, 0x71, 0xCC, 0xCD, 0xD2, 0x01, 0x12, 0x99, 0x04, 0x01, 0x06, 0xB4, 0x5B, 0x01, 0x81, 0x25, 0xBC, 0x0F, 0xD1, 0xE1, 0xEF, 0x01, 0x1B, 0xAF, 0x77, 0x01, 0x16, 0x93, 0x7C, 0x88, 0xCB, 0x01, 0x10, 0x93, 0x7C, 0x7A, 0x01, 0x16, 0x93, 0x7C, 0x01, 0x09, 0x87, 0x7F, 0x01, 0x24, 0xB8, 0x0B, 0x01, 0x21, 0x87, 0x43, 0x01, 0x21, 0x8F, 0x66, 0x01, 0x63, 0xE8, 0x1A, 0x01, 0x2D, 0x81, 0xCE, 0x0B, 0x01, 0x81, 0x25, 0x84, 0x01, 0xA7, 0xC5, 0xE0, 0x01, 0x24, 0xC3, 0x73, 0x01, 0x06, 0x9B, 0x7B, 0x01, 0x1B, 0xC3, 0x73, 0x01, 0x0C, 0xA3, 0x7A, 0x01, 0x0C, 0x93, 0x7C, 0x61, 0x61, 0xC0, 0x01, 0x27, 0xB0, 0x03, 0x01, 0x06, 0x86, 0x54, 0x01, 0x1B, 0x8A, 0x37, 0x01, 0x21, 0x84, 0x01, 0x01, 0x81, 0x4C, 0x81, 0xE8, 0x3A, 0x01, 0x66, 0x84, 0x01, 0xEA, 0xF2, 0xF8, 0x01, 0x0A, 0x93, 0x7C, 0x01, 0x0F, 0xDF, 0x6E, 0x01, 0x0E, 0xC3, 0x73, 0x01, 0x07, 0xBB, 0x74, 0x01, 0x08, 0xAF, 0x77, 0x75, 0x86, 0xCB, 0x01, 0x09, 0xCB, 0x72, 0x6E, 0x79, 0xC7, 0x6C, 0x01, 0x08, 0xAF, 0x77, 0x69, 0x70, 0x01, 0x0A, 0x93, 0x7C, 0x63, 0x65, 0xC1, 0x61, 0x61, 0xC0, 0x01, 0x27, 0x87, 0x7F, 0x01, 0x06, 0xA6, 0x4D, 0x01, 0x1E, 0x87, 0x40, 0x01, 0x21, 0x84, 0x01, 0x01, 0x66, 0xF8, 0x1E, 0x01, 0x81, 0x4C, 0x84, 0x01, 0xCB, 0xDD, 0xED, 0x01, 0x10, 0x93, 0x7C, 0x01, 0x18, 0xDF, 0x6E, 0x01, 0x1B, 0x93, 0x7C, 0x01, 0x17, 0xAF, 0x77, 0x62, 0x62, 0xC1, 0x60, 0x60, 0x01, 0x28, 0x87, 0x7F, 0x01, 0x0C, 0xD6, 0x08, 0x01, 0x39, 0x84, 0x01, 0x01, 0x66, 0x81, 0x80, 0x20, 0x01, 0x69, 0x81, 0xEC, 0x35, 0x01, 0x12, 0xEC, 0x1B, 0x01, 0x51, 0x84, 0x01, 0xAF, 0xCA, 0xE3, 0x01, 0x0A, 0xCB, 0x72, 0x01, 0x0E, 0x93, 0x7C, 0x81, 0x01, 0x12, 0x93, 0x7C, 0x01, 0x0B, 0xDF, 0x6E, 0x01, 0x18, 0x93, 0x7C, 0x01, 0x0F, 0x9B, 0x7B, 0x01, 0x2A, 0x87, 0x7F, 0x01, 0x45, 0x84, 0x01, 0x01, 0x75, 0x8C, 0x03, 0x01, 0x06, 0x82, 0x89, 0x79, 0x01, 0x06, 0x81, 0xB6, 0x7A, 0x01, 0x48, 0x90, 0x7F, 0x4F, 0x51, 0x63, 0x01, 0x0C, 0xC0, 0x10, 0x01, 0x12, 0x96, 0x28, 0x01, 0x45, 0x84, 0x01, 0xF7, 0xFA, 0xFC, 0x01, 0x27, 0xAF, 0x77, 0x01, 0x06, 0x8B, 0x7D, 0x01, 0x07, 0xC3, 0x73, 0x83, 0x01, 0x10, 0xAF, 0x77, 0x01, 0x0A, 0x93, 0x7C, 0x6D, 0xC4, 0x01, 0x0C, 0x93, 0x7C, 0x01, 0x2D, 0x87, 0x7F, 0x01, 0x45, 0x84, 0x01, 0x01, 0x06, 0xBF, 0x12, 0x01, 0x69, 0x84, 0x01, 0x01, 0x06, 0xB3, 0x6F, 0x01, 0x0F, 0x82, 0x56, 0x01, 0x12, 0x82, 0x94, 0x75, 0x01, 0x4E, 0x81, 0xB8, 0x2E, 0x01, 0x48, 0xF8, 0x1B, 0xFF, 0xFF, 0xFF, 0xDA, 0xE7, 0xF2, 0x01, 0x0D, 0xAF, 0x77, 0xA5, 0x01, 0x1C, 0xAF, 0x77, 0x01, 0x0D, 0x93, 0x7C, 0x01, 0x05, 0x83, 0x7E, 0x6D, 0x7B, 0xC1, 0x01, 0x09, 0x93, 0x7C, 0x68, 0x6E, 0x01, 0x07, 0x93, 0x7C, 0x66, 0x6B, 0x01, 0x0A, 0x87, 0x7F, 0x60, 0x60, 0xC0, 0x01, 0x4E, 0x81, 0x83, 0x5F, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x09, 0x81, 0x9C, 0x66, 0x01, 0x63, 0xCF, 0x55, 0x01, 0x06, 0xB5, 0x29, 0x01, 0x06, 0x81, 0x10, 0x80, 0x82, 0x8F, 0x01, 0x12, 0x81, 0xF1, 0x46, 0x01, 0x42, 0x81, 0xAD, 0x38, 0x01, 0x15, 0xD0, 0x14, 0x01, 0x09, 0xB0, 0x78, 0x01, 0x45, 0x84, 0x01, 0xBD, 0xD2, 0xE8, 0x01, 0x22, 0xF3, 0x6A, 0x01, 0x09, 0x9F, 0x79, 0x01, 0x05, 0xAF, 0x77, 0x01, 0x0C, 0xDF, 0x6E, 0x01, 0x0C, 0xC3, 0x73, 0x01, 0x06, 0x93, 0x7C, 0x01, 0x06, 0x83, 0x7E, 0x01, 0x06, 0x93, 0x7C, 0x60, 0x5F, 0xC0, 0x4F, 0x4E, 0x94, 0x01, 0x33, 0x81, 0x8F, 0x62, 0x01, 0x1B, 0xBB, 0x71, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x06, 0xAC, 0x44, 0x01, 0x66, 0x82, 0xA3, 0x3C, 0x01, 0x06, 0xB9, 0x27, 0x01, 0x18, 0xB0, 0x3C, 0x01, 0x06, 0x81, 0x49, 0x01, 0x3F, 0xD8, 0x67, 0x5D, 0x5E, 0x6F, 0xC9, 0xC9, 0xCF, 0xD6, 0xD7, 0xDB, 0x01, 0x0C, 0xD8, 0x16, 0x01, 0x0F, 0x81, 0xAE, 0x1B, 0x01, 0x3F, 0x84, 0x01, 0xA3, 0xBF, 0xDF, 0x01, 0x19, 0xF3, 0x6A, 0x01, 0x17, 0xAF, 0x77, 0x72, 0x81, 0xC9, 0x01, 0x1C, 0xC3, 0x73, 0x66, 0xC2, 0x64, 0x68, 0xC2, 0x62, 0x62, 0xC1, 0x61, 0x61, 0xC0, 0x5F, 0x5D, 0xBF, 0x01, 0x27, 0xE8, 0x11, 0x01, 0x0F, 0x91, 0x62, 0x01, 0x1B, 0x82, 0xBF, 0x07, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x06, 0x88, 0x41, 0x01, 0x63, 0x94, 0x02, 0x01, 0x18, 0xAB, 0x7C, 0x01, 0x0F, 0x84, 0x04, 0x01, 0x5D, 0x82, 0xC0, 0x50, 0x01, 0x42, 0x81, 0x8C, 0x20, 0xFF, 0xFF, 0xFF, 0x01, 0x1F, 0xDF, 0x6E, 0x01, 0x17, 0x93, 0x7C, 0x71, 0x7E, 0xC8, 0x01, 0x06, 0xB7, 0x76, 0x01, 0x13, 0xAF, 0x77, 0x01, 0x08, 0xB7, 0x76, 0x01, 0x33, 0x87, 0x7F, 0x01, 0x0C, 0xA3, 0x4A, 0x01, 0x18, 0x8A, 0x40, 0x01, 0x1B, 0x84, 0x01, 0x01, 0x09, 0xB8, 0x11, 0x01, 0x63, 0x8C, 0x00, 0x01, 0x12, 0x82, 0xBC, 0x4F, 0x01, 0x27, 0x83, 0xA9, 0x11, 0x01, 0x4E, 0x81, 0xD8, 0x39, 0x01, 0x3F, 0x81, 0x94, 0x22, 0xE1, 0xE9, 0xF4, 0x01, 0x0C, 0xAF, 0x77, 0x01, 0x24, 0xF3, 0x6A, 0x01, 0x0D, 0xDF, 0x6E, 0x01, 0x1D, 0x93, 0x7C, 0x01, 0x33, 0x87, 0x7F, 0x01, 0x0F, 0x8D, 0x61, 0x01, 0x15, 0x90, 0x0A, 0x01, 0x1E, 0xC0, 0x10, 0x01, 0x69, 0x81, 0xBC, 0x32, 0x01, 0x27, 0xA0, 0x6B, 0x01, 0x3F, 0x82, 0xC0, 0x50, 0xC9, 0xC9, 0xCF, 0x01, 0x21, 0x81, 0xF8, 0x3E, 0x01, 0x3C, 0x81, 0x9C, 0x24, 0xC4, 0xD6, 0xEA, 0x01, 0x13, 0xAF, 0x77, 0x01, 0x0B, 0x81, 0x8F, 0x65, 0x01, 0x06, 0xF3, 0x6A, 0x01, 0x07, 0x8B, 0x7D, 0x01, 0x0B, 0xF3, 0x6A, 0x01, 0x12, 0xCB, 0x72, 0x01, 0x0F, 0xAF, 0x77, 0x01, 0x39, 0x87, 0x7F, 0x01, 0x0C, 0x8D, 0x61, 0x01, 0x15, 0x81, 0xC8, 0x08, 0x01, 0x15, 0x84, 0x01, 0x01, 0x09, 0x83, 0x7E, 0x01, 0x66, 0x8F, 0x7E, 0x01, 0x6C, 0x81, 0x90, 0x24, 0x01, 0x5D, 0x81, 0xA4, 0x26, 0xAF, 0xCA, 0xE3, 0x01, 0x1C, 0xF3, 0x6A, 0x8F, 0x01, 0x11, 0xDF, 0x6E, 0x01, 0x09, 0x93, 0x7C, 0x01, 0x0B, 0xAF, 0x77, 0x01, 0x0F, 0x93, 0x7C, 0x01, 0x3F, 0x87, 0x7F, 0x01, 0x12, 0x81, 0xC4, 0x31, 0xB3, 0xB3, 0xBB, 0x01, 0x0C, 0x9E, 0x5A, 0x01, 0x0F, 0x84, 0x01, 0x01, 0x06, 0xCF, 0x46, 0x01, 0x09, 0x81, 0xD3, 0x3A, 0x01, 0x66, 0xE7, 0x52, 0x01, 0x81, 0x04, 0x81, 0x94, 0x25, 0x01, 0x45, 0x90, 0x13, 0xA3, 0xBF, 0xDF, 0x01, 0x33, 0xC3, 0x73, 0x01, 0x07, 0xAF, 0x77, 0x01, 0x17, 0xA7, 0x78, 0x01, 0x06, 0x93, 0x7C, 0x52, 0x53, 0x99, 0x01, 0x48, 0x9A, 0x65, 0x01, 0x09, 0x9E, 0x5A, 0x01, 0x06, 0xFA, 0x59, 0x01, 0x06, 0x83, 0x69, 0x01, 0x06, 0x9A, 0x6E, 0x01, 0x0C, 0xD0, 0x2F, 0x01, 0x6C, 0x81, 0x84, 0x1E, 0x01, 0x06, 0x81, 0x07, 0x01, 0x24, 0x6F, 0x01, 0x3F, 0x82, 0xC8, 0x52, 0x01, 0x30, 0x81, 0xF8, 0x3E, 0x01, 0x30, 0x90, 0x13, 0x01, 0x06, 0x9B, 0x7B, 0x01, 0x2D, 0xF3, 0x6A, 0x01, 0x07, 0x93, 0x7C, 0x01, 0x08, 0x9B, 0x7B, 0x67, 0x6D, 0x01, 0x0B, 0x93, 0x7C, 0x62, 0xC1, 0x62, 0x64, 0xC1, 0x60, 0x5F, 0xC0, 0x5F, 0x5D, 0xBF, 0x3E, 0x3F, 0x66, 0x01, 0x48, 0x82, 0x83, 0x28, 0x01, 0x12, 0xA2, 0x67, 0x01, 0x12, 0x81, 0xD4, 0x32, 0x01, 0x72, 0x81, 0xCC, 0x2A, 0x01, 0x66, 0x90, 0x04, 0x01, 0x60, 0x81, 0xAC, 0x37, 0x01, 0x15, 0xDF, 0x6E, 0x01, 0x28, 0xF3, 0x6A, 0x01, 0x08, 0x87, 0x7F, 0x01, 0x0A, 0x93, 0x7C, 0x64, 0x01, 0x07, 0x8B, 0x7D, 0x01, 0x2A, 0xD3, 0x77, 0x01, 0x2A, 0xA6, 0x6E, 0x01, 0x06, 0x81, 0xAF, 0x1C, 0x01, 0x12, 0xA6, 0x71, 0x01, 0x45, 0x81, 0xBF, 0x1A, 0x01, 0x36, 0xF4, 0x47, 0x01, 0x21, 0x83, 0x5A, 0x01, 0x06, 0xC9, 0x22, 0x01, 0x3F, 0x9D, 0x14, 0x01, 0x33, 0x81, 0xF0, 0x3F, 0x41, 0x43, 0x56, 0xC0, 0x01, 0x08, 0x82, 0xE5, 0x6C, 0x01, 0x1E, 0x98, 0x03, 0x01, 0x19, 0xF3, 0x6A, 0x01, 0x06, 0x81, 0x97, 0x64, 0x01, 0x0B, 0x9B, 0x7B, 0x01, 0x18, 0x93, 0x7C, 0x01, 0x0F, 0xAF, 0x77, 0x01, 0x06, 0x84, 0x01, 0x01, 0x48, 0x87, 0x7F, 0x01, 0x1B, 0xAE, 0x76, 0x01, 0x81, 0x07, 0xB7, 0x13, 0x01, 0x1E, 0xA3, 0x68, 0x01, 0x06, 0x8D, 0x22, 0x01, 0x3C, 0x85, 0x20, 0x01, 0x09, 0x81, 0xAC, 0x28, 0x01, 0x33, 0x8C, 0x48, 0x01, 0x21, 0x81, 0xA0, 0x4C, 0xE1, 0xE9, 0xF4, 0x01, 0x15, 0x81, 0xA3, 0x61, 0x01, 0x13, 0x81, 0x87, 0x66, 0x01, 0x17, 0xF3, 0x6A, 0x01, 0x09, 0xA3, 0x7A, 0x01, 0x0C, 0x93, 0x7C, 0x01, 0x3C, 0x97, 0x7D, 0x01, 0x81, 0x31, 0x82, 0x81, 0x6B, 0x01, 0x18, 0xA4, 0x75, 0x01, 0x09, 0x91, 0x41, 0x01, 0x3F, 0xBD, 0x16, 0x01, 0x09, 0x8F, 0x7E, 0x01, 0x36, 0x90, 0x49, 0x01, 0x0F, 0xDE, 0x58, 0x01, 0x10, 0x82, 0x96, 0x74, 0xE3, 0xF1, 0x01, 0x22, 0xDF, 0x6E, 0x01, 0x20, 0xF3, 0x6A, 0x64, 0x66, 0x01, 0x07, 0xDF, 0x6E, 0x01, 0x06, 0xB7, 0x76, 0x01, 0x81, 0x6A, 0x83, 0x7E, 0x01, 0x12, 0x82, 0x98, 0x49, 0x01, 0x06, 0xB0, 0x09, 0x01, 0x06, 0x82, 0xB8, 0x5A, 0x01, 0x48, 0x81, 0xD1, 0x3B, 0xC9, 0xC9, 0xCF, 0x93, 0x94, 0x9F, 0xFF, 0xFF, 0xFF, 0x01, 0x30, 0x81, 0xD0, 0x34, 0x01, 0x15, 0x81, 0xDE, 0x54, 0x01, 0x0F, 0x84, 0x01, 0xC1, 0xD0, 0xE9, 0x01, 0x19, 0x93, 0x7C, 0x01, 0x26, 0xF3, 0x6A, 0x01, 0x0C, 0xA7, 0x78, 0x52, 0x53, 0x99, 0x01, 0x5D, 0x8B, 0x7A, 0x01, 0x81, 0x1C, 0xC3, 0x1F, 0x01, 0x12, 0x9F, 0x04, 0x01, 0x0F, 0x9D, 0x3B, 0x01, 0x7E, 0x81, 0xE0, 0x38, 0x01, 0x18, 0x90, 0x13, 0xC1, 0xD0, 0xE9, 0x01, 0x0C, 0x81, 0x87, 0x66, 0x01, 0x27, 0xDF, 0x6E, 0x01, 0x09, 0x8B, 0x7D, 0x5D, 0x5D, 0xB8, 0x51, 0x57, 0x8B, 0x45, 0x47, 0x76, 0x01, 0x81, 0x76, 0x83, 0x78, 0x01, 0x15, 0xE8, 0x62, 0x01, 0x81, 0x1C, 0x82, 0xA8, 0x38, 0x01, 0x12, 0x90, 0x13, 0xC0, 0xCF, 0xE8, 0x82, 0x01, 0x0F, 0xA7, 0x78, 0x01, 0x0F, 0xDF, 0x6E, 0x01, 0x11, 0xF3, 0x6A, 0x61, 0x66, 0xB2, 0x01, 0x06, 0x83, 0x75, 0x01, 0x3C, 0xA3, 0x65, 0x01, 0x82, 0x7A, 0x81, 0xFD, 0x70, 0x6F, 0x72, 0x82, 0x01, 0x0C, 0x90, 0x13, 0xC0, 0xCF, 0xE8, 0x01, 0x1B, 0xF3, 0x6A, 0x75, 0x86, 0xCB, 0x72, 0x82, 0xC9, 0x6D, 0x7B, 0xC1, 0x5D, 0x67, 0xA1, 0x51, 0x5D, 0x7D, 0x42, 0x46, 0x6A, 0x01, 0x81, 0x16, 0x81, 0x8B, 0x5B, 0x8D, 0x8E, 0x9A, 0x01, 0x06, 0xEB, 0x53, 0x01, 0x82, 0x26, 0x82, 0xFB, 0x49, 0x01, 0x0C, 0x90, 0x13, 0xBF, 0xCD, 0xE8, 0x01, 0x10, 0x93, 0x7C, 0x01, 0x05, 0x8F, 0x7E, 0x6A, 0x79, 0xB3, 0x5B, 0x65, 0x9A, 0x4B, 0x52, 0x78, 0x40, 0x44, 0x01, 0x79, 0x82, 0x85, 0x36, 0x41, 0x43, 0x56, 0x01, 0x21, 0x9E, 0x3F, 0x01, 0x15, 0x81, 0xF8, 0x59, 0x01, 0x82, 0x23, 0x83, 0x87, 0x64, 0x01, 0x06, 0xAE, 0x3D, 0xE6, 0xE6, 0xE9, 0xBF, 0xCD, 0xE8, 0x01, 0x09, 0x9B, 0x7B, 0x6A, 0x7C, 0xAD, 0x57, 0x62, 0x8C, 0x4B, 0x52, 0x78, 0x01, 0x81, 0x07, 0x81, 0x8F, 0x41, 0x01, 0x06, 0x92, 0x57, 0x01, 0x1B, 0x81, 0xBC, 0x32, 0x01, 0x0C, 0x8D, 0x52, 0x01, 0x06, 0x81, 0xD7, 0x1D, 0x01, 0x09, 0xA8, 0x16, 0x01, 0x81, 0x4F, 0x84, 0x04, 0x01, 0x5A, 0xA5, 0x67, 0x3C, 0x40, 0x5B, 0x46, 0x4E, 0x6C, 0x01, 0x36, 0x81, 0xD3, 0x5B, 0x01, 0x63, 0x81, 0xDF, 0x10, 0x01, 0x1B, 0x81, 0xBA, 0x69, 0x01, 0x09, 0xD2, 0x16, 0x01, 0x0C, 0x84, 0x84, 0x00, 0x4D, 0x4F, 0x62, 0x01, 0x09, 0x81, 0xE3, 0x32, 0x01, 0x81, 0x49, 0x83, 0x7E, 0x01, 0x06, 0x81, 0xAC, 0x2B, 0x6A, 0x6C, 0x7B, 0xBB, 0xBC, 0xC3, 0x01, 0x81, 0x6D, 0x82, 0x9B, 0x22, 0x01, 0x1E, 0xC7, 0x56, 0x01, 0x09, 0x81, 0xF8, 0x5C, 0x01, 0x0F, 0x86, 0x1E, 0x41, 0x43, 0x56, 0x01, 0x06, 0x3C, 0x01, 0x69, 0x81, 0xA3, 0x70, 0x01, 0x06, 0x81, 0x9C, 0x60, 0xCC, 0xCD, 0xD2, 0x01, 0x1E, 0xB3, 0x03, 0x01, 0x82, 0x2F, 0x82, 0xE4, 0x59, 0x01, 0x21, 0x87, 0x46, 0x01, 0x1B, 0x84, 0x22, 0x01, 0x06, 0x88, 0x3E, 0x01, 0x66, 0xB3, 0x00, 0x01, 0x09, 0xB6, 0x7B, 0x01, 0x06, 0x81, 0x85, 0x3A, 0x01, 0x54, 0x83, 0xB0, 0x6C, 0x01, 0x81, 0x73, 0x84, 0x01, 0x01, 0x21, 0xD4, 0x15, 0x01, 0x24, 0xF4, 0x3E, 0x01, 0x63, 0x82, 0x2F, 0x01, 0x09, 0x81, 0xCD, 0x58, 0x01, 0x5D, 0xF1, 0x05, 0x01, 0x15, 0x81, 0xB8, 0x2E, 0x01, 0x81, 0x7F, 0x82, 0xB4, 0x4D, 0x01, 0x06, 0xBE, 0x62, 0x01, 0x1B, 0x88, 0x23, 0x01, 0x66, 0xE4, 0x19, 0x01, 0x06, 0x83, 0xBC, 0x69, 0x01, 0x81, 0x3D, 0x94, 0x05, 0x01, 0x81, 0x1C, 0x82, 0xC8, 0x5E, 0x01, 0x1B, 0x81, 0x76, 0x01, 0x21, 0xF8, 0x3F, 0x01, 0x63, 0x84, 0x01, 0x01, 0x69, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x79, 0x82, 0xD0, 0x60, 0x01, 0x21, 0x88, 0x23, 0x01, 0x1B, 0x8E, 0x59, 0x01, 0x42, 0x81, 0xE8, 0x7C, 0x01, 0x4B, 0xC8, 0x12, 0x01, 0x3F, 0x69, 0x01, 0x15, 0x81, 0xD0, 0x34, 0x01, 0x81, 0x7F, 0x84, 0x01, 0x01, 0x21, 0x81, 0x8C, 0x05, 0x01, 0x63, 0xF4, 0x1D, 0x01, 0x69, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x73, 0x83, 0x80, 0x60, 0x01, 0x1E, 0x84, 0x01, 0x01, 0x09, 0x94, 0x02, 0x01, 0x1B, 0x86, 0x7E, 0x01, 0x69, 0x81, 0xF0, 0x3C, 0x01, 0x63, 0x88, 0x02, 0x01, 0x81, 0x73, 0x98, 0x06, 0x01, 0x1E, 0xF3, 0x5B, 0x01, 0x06, 0x9B, 0x66, 0x01, 0x1E, 0x9C, 0x25, 0x01, 0x66, 0x94, 0x05, 0x01, 0x66, 0x82, 0xA5, 0x3B, 0x01, 0x81, 0x73, 0x98, 0x06, 0x01, 0x1E, 0x82, 0xF4, 0x1B, 0x01, 0x24, 0x84, 0x83, 0x59, 0x01, 0x21, 0x81, 0x84, 0x63, 0x01, 0x81, 0x2E, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x70, 0x98, 0x06, 0x01, 0x1B, 0xF3, 0x5E, 0x01, 0x09, 0x81, 0x9C, 0x06, 0x01, 0x1B, 0xA7, 0x69, 0x01, 0x06, 0x8B, 0x1D, 0x01, 0x63, 0x81, 0x94, 0x25, 0x01, 0x06, 0xA8, 0x76, 0x01, 0x82, 0x53, 0x83, 0xAC, 0x47, 0x01, 0x09, 0x83, 0x66, 0x01, 0x12, 0x82, 0x5C, 0x01, 0x09, 0xB7, 0x7F, 0x01, 0x1B, 0x86, 0x15, 0x01, 0x06, 0xF0, 0x1F, 0x01, 0x66, 0x82, 0x98, 0x46, 0x01, 0x06, 0xBA, 0x5B, 0xBF, 0xC0, 0xC7, 0x01, 0x5A, 0xB4, 0x7F, 0x01, 0x81, 0x76, 0x82, 0xD0, 0x4B, 0x01, 0x09, 0xB7, 0x6A, 0x01, 0x0F, 0x81, 0xB7, 0x45, 0x01, 0x24, 0x82, 0xB0, 0x31, 0x01, 0x6F, 0xB0, 0x0C, 0x01, 0x09, 0x81, 0xE9, 0x5F, 0x01, 0x06, 0x83, 0x8C, 0x5D, 0x01, 0x54, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x64, 0x82, 0xE8, 0x5A, 0x01, 0x1B, 0x82, 0xAC, 0x18, 0x01, 0x12, 0x82, 0xEC, 0x3D, 0x01, 0x1B, 0x87, 0x7F, 0x01, 0x21, 0xFC, 0x5B, 0x01, 0x51, 0xB4, 0x0A, 0x01, 0x09, 0x82, 0xA9, 0x3C, 0x01, 0x57, 0x82, 0xBC, 0x4F, 0x01, 0x81, 0x73, 0x82, 0xE8, 0x5A, 0x01, 0x1B, 0xC3, 0x70, 0x01, 0x15, 0x81, 0xA3, 0x0D, 0x01, 0x12, 0x87, 0x7F, 0x01, 0x66, 0x81, 0xF8, 0x3E, 0x01, 0x06, 0x8D, 0x2B, 0x01, 0x06, 0xED, 0x25, 0x01, 0x82, 0x62, 0x84, 0x93, 0x5D, 0x01, 0x24, 0x81, 0xD3, 0x55, 0x01, 0x06, 0x8F, 0x12, 0x01, 0x69, 0x87, 0x7F, 0x01, 0x06, 0xE9, 0x2A, 0x01, 0x5A, 0x6C, 0x01, 0x09, 0x82, 0xB4, 0x3E, 0x01, 0x81, 0x6A, 0x83, 0x90, 0x5E, 0x01, 0x4B, 0x83, 0xBC, 0x0F, 0x01, 0x66, 0xA5, 0x31, 0x01, 0x5D, 0x90, 0x6A, 0x01, 0x81, 0x73, 0x83, 0x8C, 0x5D, 0x01, 0x81, 0x31, 0x81, 0xA3, 0x2B, 0x01, 0x5D, 0x88, 0x6B, 0x01, 0x0F, 0x8D, 0x7F, 0x01, 0x81, 0x70, 0x94, 0x05, 0x01, 0x81, 0x34, 0x84, 0xBD, 0x0F, 0x01, 0x5A, 0x82, 0xFC, 0x59, 0x01, 0x83, 0x12, 0x82, 0xE4, 0x5C, 0x01, 0x06, 0xA4, 0x6F, 0x01, 0x83, 0x7E, 0x83, 0xE4, 0x67, 0x01, 0x83, 0x60, 0x83, 0xDC, 0x53, 0x01, 0x24, 0xA5, 0x2E, 0x01, 0x83, 0x63, 0x84, 0xB4, 0x6C, 0x01, 0x81, 0x01, 0x82, 0xEC, 0x5B, 0x01, 0x83, 0x24, 0x84, 0x04, 0x01, 0x60, 0x82, 0xE5, 0x57, 0x01, 0x83, 0x21, 0x84, 0x8D, 0x03, 0x01, 0x09, 0x82, 0x99, 0x41, 0x01, 0x54, 0xAC, 0x0B, 0x01, 0x83, 0x24, 0x84, 0x95, 0x05, 0x01, 0x5D, 0x82, 0xEC, 0x5B, 0x01, 0x97, 0x4A, 0x84, 0x91, 0x19, 0x01, 0x83, 0x54, 0xA0, 0x26, 0x01, 0x06, 0xA0, 0x08, 0x01, 0x27, 0xE1, 0x67, 0x01, 0x83, 0x54, 0x84, 0xAD, 0x0B, 0x01, 0x2A, 0xBC, 0x0F, 0x01, 0x39, 0x82, 0x8C, 0x43, 0x01, 0x83, 0x48, 0x84, 0x01, 0x01, 0x83, 0x6C, 0x85, 0x81, 0x20, 0x01, 0x54, 0x81, 0xC0, 0x30, 0x01, 0x83, 0x42, 0x84, 0x01, 0xCC, 0xCD, 0xD2, 0x01, 0x82, 0x56, 0x83, 0xC1, 0x17, 0x01, 0x7B, 0xED, 0x3A, 0x01, 0x06, 0xC0, 0x0A, 0x01, 0x06, 0xE5, 0x38, 0x01, 0x1E, 0x82, 0xBD, 0x38, 0x01, 0x69, 0x82, 0xF9, 0x68, 0x01, 0x82, 0x6E, 0x84, 0x81, 0x09, 0x01, 0x2D, 0x83, 0xD2, 0x04, 0x01, 0x83, 0x57, 0x84, 0xF1, 0x28, 0x01, 0x83, 0x57, 0x93, 0x5B, 0x01, 0x84, 0x01, 0x84, 0x01, 0x01, 0x84, 0x2B, 0x88, 0x02, 0x01, 0x94, 0x0E, 0xBF, 0x6F, 0x01, 0x0C, 0x82, 0xF1, 0x5D, 0x01, 0x83, 0x6C, 0x84, 0xED, 0x1B, 0x01, 0x0C, 0x83, 0xB2, 0x14, 0x01, 0x06, 0xBF, 0x72, 0x01, 0x06, 0x81, 0x9C, 0x36, 0x01, 0x06, 0x81, 0xE0, 0x41, 0x01, 0x09, 0xAC, 0x08, 0x01, 0x06, 0x81, 0xF1, 0x55, 0x01, 0x83, 0x57, 0x84, 0xED, 0x1B, 0x01, 0x06, 0x81, 0x95, 0x35, 0x01, 0x0C, 0xEC, 0x1B, 0x01, 0x12, 0x85, 0xD1, 0x34, 0x01, 0x3F, 0x82, 0xD0, 0x51, 0x01, 0x83, 0x21, 0x85, 0x89, 0x22, 0x01, 0x0F, 0x81, 0x91, 0x0D, 0x01, 0x18, 0x84, 0xB5, 0x0D, 0x01, 0x83, 0x54, 0xB0, 0x0F, 0x01, 0x2A, 0x85, 0xBD, 0x2F, 0x01, 0x06, 0x81, 0xF9, 0x78, 0x01, 0x83, 0x7B, 0x85, 0xC5, 0x31, 0x01, 0x06, 0x81, 0xA8, 0x51, 0x01, 0x83, 0x7B, 0x84, 0x01, 0x01, 0x83, 0x18, 0x81, 0x93, 0x66, 0x01, 0x54, 0x83, 0xAC, 0x6B, 0x01, 0x83, 0x6C, 0x84, 0x01, 0x01, 0x15, 0x83, 0xB4, 0x6D, 0x01, 0x06, 0x82, 0x8D, 0x6E, 0x01, 0x15, 0x82, 0xCC, 0x7A, 0x01, 0x83, 0x57, 0x84, 0xE9, 0x17, 0x01, 0x0F, 0x87, 0x70, 0x01, 0x18, 0x88, 0x17, 0x01, 0x83, 0x4E, 0xD0, 0x14, 0x01, 0x1E, 0x84, 0xCC, 0x6F, 0x01, 0x06, 0x81, 0xD8, 0x4B, 0x01, 0x0C, 0x82, 0xD8, 0x6B, 0x01, 0x2D, 0x83, 0xDE, 0x3A, 0x01, 0x83, 0x36, 0x84, 0xD5, 0x2A, 0x01, 0x15, 0x82, 0xA5, 0x50, 0x01, 0x09, 0x85, 0x99, 0x3E, 0x01, 0x83, 0x60, 0x81, 0x94, 0x49, 0x01, 0x12, 0xEF, 0x78, 0x01, 0x09, 0x81, 0xEC, 0x4D, 0xBF, 0xC0, 0xC7, 0x01, 0x83, 0x7E, 0x81, 0x9C, 0x48, 0x01, 0x98, 0x09, 0xCC, 0x31, 0x01, 0x9C, 0x04, 0x9C, 0x04, 0x01, 0xB8, 0x08, 0xB8, 0x08, 0x01, 0xD8, 0x73, 0xD8, 0x73, 0x00}; +static const uint8_t s_splash[] = {0x00, 0x34, 0x36, 0x4B, 0x34, 0x36, 0x4B, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x30, 0x30, 0x00, 0x60, 0x60, 0x00, 0x81, 0x40, 0x81, 0x40, 0x00, 0x83, 0x00, 0x83, 0x00, 0x00, 0x86, 0x00, 0x86, 0x00, 0x00, 0x8B, 0x0E, 0x8B, 0x0E, 0x5A, 0x5C, 0x6D, 0x00, 0x88, 0x0E, 0x88, 0x11, 0x73, 0x75, 0x83, 0xA6, 0xA7, 0xB0, 0xD9, 0xD9, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x04, 0x04, 0xFF, 0xCC, 0xCD, 0xD2, 0x00, 0x88, 0x05, 0x88, 0x1A, 0x9A, 0x9B, 0xA5, 0xE6, 0xE6, 0xE9, 0x00, 0x09, 0x88, 0x17, 0x00, 0x27, 0x88, 0x20, 0x41, 0x43, 0x56, 0x00, 0x87, 0x64, 0x98, 0x45, 0x00, 0x12, 0x88, 0x1A, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x15, 0x00, 0x1B, 0x88, 0x20, 0x80, 0x81, 0x8F, 0xF2, 0xF2, 0xF4, 0x00, 0x87, 0x5E, 0x99, 0x04, 0x80, 0x81, 0x8F, 0x00, 0x0C, 0x88, 0x17, 0xB3, 0xB4, 0xBC, 0x73, 0x75, 0x83, 0x00, 0x06, 0x90, 0x16, 0x9A, 0x9B, 0xA5, 0x00, 0x1B, 0x88, 0x20, 0x67, 0x68, 0x78, 0x00, 0x06, 0x33, 0xD9, 0xD9, 0xDD, 0x00, 0x87, 0x58, 0x90, 0x46, 0x00, 0x0C, 0x88, 0x1D, 0xCC, 0xCD, 0xD2, 0x4D, 0x4F, 0x62, 0x00, 0x0F, 0x98, 0x72, 0x00, 0x1E, 0x90, 0x40, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x3C, 0xC0, 0xC0, 0xC7, 0x00, 0x87, 0x52, 0x88, 0x1D, 0x00, 0x09, 0x90, 0x01, 0xFF, 0xFF, 0xFF, 0x8D, 0x8E, 0x9A, 0x00, 0x15, 0xA1, 0x12, 0x00, 0x21, 0xA1, 0x00, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x42, 0x67, 0x68, 0x78, 0x00, 0x87, 0x4C, 0x88, 0x1D, 0x41, 0x43, 0x56, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0x87, 0x5B, 0x80, 0x81, 0x8F, 0x00, 0x18, 0xA9, 0x32, 0x00, 0x21, 0x88, 0x20, 0x4D, 0x4F, 0x62, 0x00, 0x87, 0x55, 0xB1, 0x67, 0x00, 0x06, 0x87, 0x7C, 0xFF, 0xFF, 0xFF, 0xA6, 0xA7, 0xB0, 0x00, 0x1E, 0x24, 0x00, 0x21, 0x87, 0x79, 0x00, 0x09, 0x98, 0x66, 0x00, 0x0F, 0x99, 0x1F, 0x00, 0x87, 0x43, 0x90, 0x3D, 0xE6, 0xE6, 0xE9, 0x00, 0x21, 0x88, 0x44, 0x00, 0x21, 0x88, 0x20, 0x5A, 0x5C, 0x6D, 0x00, 0x06, 0x88, 0x20, 0x9A, 0x9B, 0xA5, 0x00, 0x87, 0x46, 0x88, 0x20, 0x8D, 0x8E, 0x9A, 0x00, 0x1E, 0x98, 0x5A, 0x00, 0x2D, 0x88, 0x20, 0x34, 0x36, 0x4B, 0x00, 0x21, 0xBA, 0x0A, 0x00, 0x87, 0x2E, 0x88, 0x20, 0x00, 0x06, 0xA8, 0x55, 0xF2, 0xF2, 0xF4, 0x00, 0x24, 0x99, 0x04, 0x00, 0x24, 0x87, 0x76, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x88, 0x71, 0x00, 0x87, 0x46, 0x88, 0x20, 0x00, 0x09, 0xC1, 0x6B, 0x00, 0x48, 0x88, 0x20, 0x00, 0x09, 0xA1, 0x4E, 0x00, 0x87, 0x43, 0xA1, 0x03, 0x00, 0x09, 0xA0, 0x2F, 0x00, 0x15, 0xB9, 0x54, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x87, 0x43, 0xB9, 0x66, 0x00, 0x09, 0xC1, 0x77, 0x00, 0x21, 0x87, 0x4C, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x2A, 0x54, 0x00, 0x87, 0x76, 0x88, 0x20, 0x00, 0x09, 0xA9, 0x71, 0x00, 0x88, 0x17, 0x88, 0x20, 0x00, 0x09, 0x98, 0x60, 0x00, 0x87, 0x43, 0xEB, 0x2C, 0x00, 0x09, 0x88, 0x20, 0x73, 0x75, 0x83, 0x00, 0x48, 0x88, 0x20, 0x00, 0x09, 0xCA, 0x23, 0x00, 0x87, 0x46, 0xCA, 0x1D, 0x00, 0x27, 0xC9, 0x4F, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x06, 0x81, 0x8C, 0x50, 0x00, 0x1E, 0xCA, 0x6E, 0x00, 0x87, 0x2B, 0x88, 0x23, 0x00, 0x27, 0xC9, 0x4F, 0x00, 0x27, 0x88, 0x20, 0x00, 0x09, 0xE3, 0x03, 0x00, 0x21, 0xBA, 0x31, 0x00, 0x87, 0x28, 0x88, 0x20, 0x00, 0x09, 0x98, 0x0F, 0x00, 0x1E, 0x81, 0x83, 0x38, 0x00, 0x27, 0x88, 0x20, 0x00, 0x09, 0xA0, 0x7D, 0x00, 0x1E, 0xD3, 0x0E, 0x00, 0x87, 0x2E, 0x81, 0xA4, 0x65, 0x00, 0x24, 0x98, 0x63, 0x00, 0x24, 0x88, 0x20, 0x00, 0x09, 0xE3, 0x4B, 0xF2, 0xF2, 0xF4, 0x00, 0x87, 0x4C, 0x81, 0x8C, 0x26, 0x00, 0x06, 0x98, 0x63, 0xF2, 0xF2, 0xF4, 0x00, 0x1B, 0xD1, 0x72, 0x00, 0x24, 0x88, 0x20, 0xA6, 0xA7, 0xB0, 0x00, 0x87, 0x4F, 0xEB, 0x1D, 0x00, 0x0F, 0x90, 0x43, 0xD9, 0xD9, 0xDD, 0x00, 0x39, 0x88, 0x20, 0x00, 0x09, 0x45, 0x00, 0x87, 0x4F, 0x90, 0x3D, 0x00, 0x0F, 0xEA, 0x55, 0x00, 0x18, 0xA8, 0x58, 0x00, 0x1E, 0x88, 0x20, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0x81, 0x8C, 0x62, 0x00, 0x21, 0xBA, 0x2B, 0x00, 0x87, 0x37, 0xB9, 0x69, 0x00, 0x09, 0x81, 0xC5, 0x68, 0xD9, 0xD9, 0xDD, 0x00, 0x12, 0x98, 0x69, 0x00, 0x1B, 0x88, 0x20, 0x00, 0x09, 0xD2, 0x31, 0x00, 0x87, 0x4C, 0xB1, 0x37, 0x00, 0x1E, 0x90, 0x04, 0xF2, 0xF2, 0xF4, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0x98, 0x27, 0x00, 0x15, 0x88, 0x20, 0x67, 0x68, 0x78, 0x00, 0x09, 0x81, 0xA4, 0x74, 0x00, 0x87, 0x5E, 0x88, 0x1D, 0x00, 0x12, 0x90, 0x46, 0x00, 0x09, 0x81, 0xB5, 0x0D, 0x9A, 0x9B, 0xA5, 0x67, 0x68, 0x78, 0x00, 0x06, 0xBA, 0x07, 0xD9, 0xD9, 0xDD, 0x67, 0x68, 0x78, 0x73, 0x75, 0x83, 0x9A, 0x9B, 0xA5, 0x00, 0x0F, 0x2A, 0x00, 0x87, 0x61, 0x88, 0x1D, 0x00, 0x0C, 0x90, 0x2B, 0x00, 0x09, 0x90, 0x49, 0x00, 0x12, 0x81, 0xD6, 0x43, 0x00, 0x12, 0x12, 0xE6, 0xE6, 0xE9, 0x00, 0x87, 0x55, 0xA0, 0x74, 0x00, 0x1E, 0xD2, 0x07, 0xA6, 0xA7, 0xB0, 0x00, 0x21, 0x88, 0x26, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x87, 0x64, 0x81, 0xDE, 0x57, 0x00, 0x1B, 0xEB, 0x41, 0x9A, 0x9B, 0xA5, 0xC0, 0xC0, 0xC7, 0xCC, 0xCD, 0xD2, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x06, 0xB3, 0xB4, 0xBC, 0x8D, 0x8E, 0x9A, 0x00, 0x88, 0x11, 0x81, 0xF7, 0x4F, 0x00, 0x97, 0x0E, 0x82, 0x96, 0x6E, 0x00, 0x9F, 0x1C, 0x9F, 0x1C, 0x00, 0x83, 0x0C, 0xE2, 0x74, 0x00, 0x06, 0xC1, 0x53, 0x00, 0x87, 0x49, 0x81, 0x93, 0x6F, 0x00, 0x57, 0x81, 0xB5, 0x40, 0x00, 0x87, 0x4F, 0x81, 0x8B, 0x52, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x51, 0x81, 0xEF, 0x20, 0x00, 0x87, 0x55, 0x82, 0xA8, 0x35, 0x00, 0x45, 0x45, 0x00, 0x87, 0x4F, 0x81, 0xC5, 0x2F, 0x00, 0x51, 0x51, 0x00, 0x09, 0x81, 0xAC, 0x55, 0x00, 0x88, 0x17, 0xEA, 0x70, 0x00, 0x87, 0x52, 0x81, 0xCD, 0x52, 0x00, 0x5A, 0x81, 0xAD, 0x1D, 0x00, 0x88, 0x1A, 0x90, 0x43, 0x00, 0x09, 0x82, 0xB1, 0x23, 0x00, 0x87, 0x7C, 0x81, 0x8B, 0x6D, 0x00, 0x27, 0x81, 0xC6, 0x03, 0x00, 0x87, 0x49, 0x82, 0xC1, 0x1B, 0x00, 0x51, 0x82, 0xE2, 0x60, 0x00, 0x09, 0x81, 0xDE, 0x1E, 0x00, 0x21, 0x82, 0xA0, 0x6F, 0x00, 0x87, 0x7C, 0xDA, 0x6F, 0x00, 0x09, 0x81, 0xA4, 0x5C, 0xA6, 0xA7, 0xB0, 0x67, 0x68, 0x78, 0x00, 0x87, 0x7F, 0x98, 0x72, 0x00, 0x0C, 0x81, 0xA4, 0x59, 0x00, 0x06, 0x06, 0x00, 0x15, 0x81, 0xAD, 0x17, 0xE6, 0xE6, 0xE9, 0x00, 0x12, 0x2A, 0x00, 0x12, 0x12, 0x00, 0x0C, 0x0C, 0x00, 0x87, 0x4C, 0xD2, 0x40, 0x00, 0x2A, 0x81, 0xBD, 0x4E, 0x00, 0x2A, 0x2A, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x87, 0x49, 0xEB, 0x23, 0x67, 0x68, 0x78, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x2A, 0x2A, 0x00, 0xC1, 0x41, 0x81, 0xBD, 0x7E, 0x00, 0xA1, 0x06, 0xA1, 0x06, 0x41, 0x43, 0x56, 0x00, 0x06, 0xE2, 0x50, 0x00, 0x88, 0x0E, 0x82, 0xA0, 0x54, 0x00, 0x06, 0x82, 0xB1, 0x23, 0x00, 0x0F, 0x82, 0xC1, 0x45, 0x00, 0x88, 0x05, 0x84, 0x98, 0x20, 0x4D, 0x4F, 0x62, 0x00, 0x0C, 0x82, 0xD1, 0x76, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x87, 0x64, 0xF3, 0x34, 0x00, 0x0C, 0x82, 0xE2, 0x2D, 0x00, 0x09, 0x81, 0xAD, 0x32, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x88, 0x32, 0x00, 0x21, 0x84, 0x87, 0x60, 0x00, 0x87, 0x5E, 0x82, 0xCA, 0x09, 0x00, 0x09, 0x83, 0x94, 0x2C, 0x00, 0x06, 0x81, 0x9C, 0x51, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x81, 0xA4, 0x7D, 0x00, 0x27, 0x84, 0x98, 0x20, 0x00, 0x87, 0x5B, 0x84, 0xA0, 0x43, 0x00, 0x0C, 0x88, 0x1D, 0x00, 0x12, 0x81, 0xF7, 0x4F, 0x00, 0x21, 0x83, 0x83, 0x60, 0x00, 0x09, 0x84, 0x98, 0x5F, 0x00, 0x1B, 0x83, 0x84, 0x25, 0x00, 0x87, 0x43, 0x98, 0x57, 0x00, 0x18, 0x90, 0x01, 0x00, 0x2D, 0x83, 0x94, 0x20, 0x00, 0x87, 0x4F, 0x82, 0x90, 0x6E, 0x00, 0x09, 0x81, 0xE7, 0x03, 0x00, 0x1B, 0x98, 0x1E, 0x00, 0x2D, 0x83, 0xA4, 0x60, 0x00, 0x87, 0x4F, 0x81, 0xF8, 0x0E, 0x00, 0x09, 0x98, 0x5A, 0x00, 0x1B, 0x8F, 0x78, 0x00, 0x30, 0x83, 0xB5, 0x20, 0x00, 0x87, 0x49, 0xB1, 0x4C, 0x00, 0x27, 0x84, 0xA8, 0x15, 0x00, 0x30, 0x83, 0xC5, 0x60, 0x00, 0x1B, 0x84, 0xA1, 0x0B, 0x00, 0x63, 0x81, 0xD8, 0x09, 0x00, 0x0F, 0xB2, 0x6E, 0x00, 0x06, 0xCB, 0x63, 0x00, 0x86, 0x3F, 0x82, 0x88, 0x00, 0x00, 0x1E, 0x86, 0x42, 0x00, 0x30, 0x83, 0xD6, 0x20, 0x00, 0x75, 0xA9, 0x26, 0x00, 0x0F, 0x83, 0x8D, 0x40, 0x00, 0x09, 0x81, 0x2E, 0x00, 0x06, 0x81, 0x64, 0x00, 0x86, 0x36, 0xBA, 0x7C, 0x00, 0x27, 0x82, 0x98, 0x40, 0x00, 0x81, 0x25, 0x83, 0xE6, 0x60, 0x00, 0x06, 0x90, 0x37, 0xA6, 0xA7, 0xB0, 0x4D, 0x4F, 0x62, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0x90, 0x40, 0xF2, 0xF2, 0xF4, 0x00, 0x86, 0x24, 0x83, 0xB6, 0x39, 0x00, 0x12, 0x90, 0x25, 0x00, 0x27, 0x98, 0x0F, 0x00, 0x81, 0x22, 0x83, 0xF7, 0x20, 0x00, 0x06, 0xC3, 0x04, 0x00, 0x09, 0xBB, 0x1A, 0x00, 0x0C, 0x88, 0x20, 0x00, 0x09, 0xBA, 0x7F, 0x00, 0x86, 0x1E, 0x81, 0xF0, 0x78, 0x00, 0x06, 0x83, 0xAC, 0x62, 0x00, 0x15, 0xC9, 0x58, 0x00, 0x21, 0xB9, 0x12, 0x00, 0x81, 0x22, 0x84, 0x87, 0x60, 0x00, 0x06, 0x81, 0x22, 0x00, 0x0C, 0xCB, 0x51, 0x00, 0x0F, 0x81, 0x2E, 0x00, 0x86, 0x1E, 0x82, 0xB3, 0x07, 0x00, 0x09, 0x9F, 0x1C, 0x00, 0x81, 0x58, 0x84, 0x98, 0x20, 0x00, 0x0F, 0x81, 0xF0, 0x15, 0x00, 0x15, 0x88, 0x20, 0x00, 0x86, 0x1B, 0xEC, 0x60, 0x00, 0x06, 0x82, 0xA0, 0x45, 0x00, 0x0F, 0xA0, 0x68, 0x00, 0x5D, 0x84, 0x90, 0x00, 0x00, 0x6F, 0x88, 0x20, 0xC0, 0xC0, 0xC7, 0x00, 0x0C, 0xAA, 0x15, 0x00, 0x86, 0x2D, 0x88, 0x20, 0x00, 0x18, 0x87, 0x34, 0x00, 0x5D, 0x88, 0x20, 0x00, 0x6F, 0x82, 0x99, 0x08, 0x00, 0x06, 0x78, 0x00, 0x09, 0x75, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x06, 0x82, 0x9A, 0x21, 0x00, 0x86, 0x15, 0xA1, 0x00, 0x00, 0x09, 0xE2, 0x1A, 0x00, 0x12, 0xE2, 0x56, 0x00, 0x54, 0xA1, 0x00, 0x00, 0x78, 0x84, 0xC9, 0x60, 0x00, 0x06, 0xC2, 0x7B, 0x00, 0x09, 0xA0, 0x62, 0x00, 0x0F, 0xB1, 0x40, 0x00, 0x06, 0x9A, 0x5C, 0x00, 0x86, 0x12, 0x82, 0xA2, 0x3B, 0x00, 0x09, 0x83, 0xD5, 0x76, 0x00, 0x18, 0x87, 0x5B, 0x00, 0x51, 0xB1, 0x40, 0x00, 0x06, 0x83, 0xF7, 0x6E, 0x00, 0x75, 0xC2, 0x00, 0x00, 0x06, 0xC1, 0x68, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x85, 0xA5, 0x7A, 0x00, 0x06, 0x81, 0x2E, 0x73, 0x75, 0x83, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x7B, 0xCB, 0x33, 0x00, 0x85, 0x1A, 0xA9, 0x14, 0x00, 0x21, 0x83, 0xFF, 0x1C, 0x00, 0x27, 0xC9, 0x4F, 0x00, 0x30, 0x84, 0xEA, 0x60, 0x00, 0x78, 0x87, 0x0D, 0x00, 0x0C, 0xF5, 0x06, 0x00, 0x86, 0x21, 0x83, 0xD7, 0x3F, 0x00, 0x09, 0x97, 0x6B, 0x00, 0x1B, 0xD0, 0x3B, 0x00, 0x09, 0xD2, 0x40, 0x00, 0x1E, 0x96, 0x7C, 0x00, 0x30, 0x84, 0xFB, 0x20, 0x00, 0x7B, 0xD1, 0x2D, 0x67, 0x68, 0x78, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x8A, 0x19, 0xE6, 0xE6, 0xE9, 0xB3, 0xB4, 0xBC, 0x00, 0x86, 0x18, 0xDA, 0x5D, 0x00, 0x06, 0xD0, 0x50, 0x00, 0x1E, 0x8E, 0x3B, 0x00, 0x09, 0x8F, 0x72, 0x00, 0x1E, 0x27, 0x00, 0x2D, 0x85, 0x8B, 0x60, 0x00, 0x87, 0x28, 0xF3, 0x40, 0xCC, 0xCD, 0xD2, 0x00, 0x24, 0x82, 0xD1, 0x73, 0x00, 0x24, 0x85, 0x9B, 0x58, 0x00, 0x2D, 0x85, 0x9C, 0x20, 0x00, 0x78, 0x81, 0x84, 0x00, 0x41, 0x43, 0x56, 0x00, 0x18, 0x81, 0x6D, 0x4D, 0x4F, 0x62, 0x00, 0x86, 0x12, 0xDA, 0x5D, 0xCC, 0xCD, 0xD2, 0x00, 0x24, 0xD9, 0x65, 0x00, 0x09, 0x90, 0x43, 0x00, 0x1B, 0xE1, 0x22, 0x00, 0x21, 0x88, 0x20, 0x00, 0x09, 0xB9, 0x57, 0x00, 0x7B, 0x81, 0x94, 0x40, 0x00, 0x06, 0x82, 0xBA, 0x7D, 0x00, 0x12, 0x81, 0x73, 0x00, 0x06, 0x81, 0x61, 0x00, 0x84, 0x4C, 0xD2, 0x3D, 0x9A, 0x9B, 0xA5, 0x00, 0x81, 0x43, 0x81, 0xA2, 0x48, 0x00, 0x2A, 0x9E, 0x78, 0x00, 0x0C, 0x87, 0x5E, 0x00, 0x15, 0xA1, 0x09, 0x00, 0x1E, 0x88, 0x20, 0x00, 0x0C, 0x81, 0xAD, 0x56, 0x00, 0x78, 0x82, 0x38, 0x00, 0x06, 0xBB, 0x2C, 0x00, 0x18, 0x9A, 0x26, 0x00, 0x06, 0xA2, 0x19, 0x00, 0x84, 0x43, 0x81, 0xA6, 0x1C, 0x67, 0x68, 0x78, 0x00, 0x09, 0xA5, 0x5B, 0x00, 0x81, 0x6D, 0x95, 0x12, 0x00, 0x09, 0xA9, 0x4D, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0xA8, 0x5E, 0x00, 0x18, 0x88, 0x20, 0x41, 0x43, 0x56, 0x00, 0x09, 0x39, 0x00, 0x7E, 0x81, 0x9C, 0x5A, 0x00, 0x06, 0xAA, 0x69, 0x00, 0x18, 0x88, 0x02, 0x00, 0x06, 0xA2, 0x1C, 0x00, 0x84, 0x40, 0xB9, 0x63, 0x00, 0x0C, 0x85, 0xB3, 0x0A, 0x00, 0x81, 0x70, 0x83, 0xA2, 0x76, 0x41, 0x43, 0x56, 0x00, 0x0C, 0x81, 0xC5, 0x77, 0x00, 0x06, 0xC0, 0x46, 0x00, 0x1B, 0x88, 0x20, 0x41, 0x43, 0x56, 0x00, 0x0F, 0x84, 0x88, 0x0A, 0x00, 0x7E, 0x81, 0xA4, 0x77, 0x00, 0x06, 0x81, 0x3D, 0x00, 0x1E, 0x82, 0xC3, 0x4A, 0x00, 0x83, 0x45, 0xDA, 0x60, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x00, 0x75, 0x84, 0x70, 0x00, 0x09, 0x82, 0xF1, 0x2A, 0x00, 0x81, 0x76, 0x84, 0xB6, 0x6B, 0x00, 0x09, 0xB9, 0x6F, 0x00, 0x09, 0x82, 0x02, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0xD1, 0x0C, 0x00, 0x06, 0x92, 0x54, 0x9A, 0x9B, 0xA5, 0x00, 0x06, 0xC8, 0x7B, 0x00, 0x0F, 0x27, 0x00, 0x81, 0x01, 0x81, 0xAD, 0x14, 0x00, 0x83, 0x69, 0x88, 0x20, 0x00, 0x81, 0x01, 0x81, 0xDB, 0x4E, 0x00, 0x0C, 0x85, 0x7D, 0x00, 0x81, 0x73, 0x81, 0xB3, 0x0B, 0x67, 0x68, 0x78, 0x00, 0x0F, 0x81, 0xDE, 0x57, 0x00, 0x1E, 0x82, 0xD2, 0x08, 0xC0, 0xC0, 0xC7, 0x00, 0x81, 0x04, 0xD9, 0x38, 0x00, 0x1E, 0xA0, 0x62, 0x00, 0x06, 0xA9, 0x23, 0x00, 0x83, 0x45, 0xCA, 0x26, 0x00, 0x81, 0x01, 0x88, 0x20, 0x00, 0x0C, 0x85, 0xDC, 0x2A, 0x00, 0x81, 0x79, 0xAD, 0x75, 0x73, 0x75, 0x83, 0x00, 0x0C, 0xA0, 0x59, 0x00, 0x12, 0x88, 0x17, 0xF2, 0xF2, 0xF4, 0xB3, 0xB4, 0xBC, 0x00, 0x81, 0x0A, 0xA7, 0x72, 0x00, 0x06, 0x93, 0x79, 0x00, 0x18, 0x83, 0x30, 0x00, 0x06, 0x81, 0x4C, 0x00, 0x83, 0x45, 0x81, 0x9C, 0x63, 0x00, 0x81, 0x01, 0x88, 0x20, 0x00, 0x09, 0x84, 0xF9, 0x36, 0x00, 0x24, 0x85, 0xB3, 0x19, 0x00, 0x81, 0x64, 0x90, 0x4F, 0x8D, 0x8E, 0x9A, 0x00, 0x09, 0x9B, 0x75, 0x00, 0x06, 0x9B, 0x78, 0x00, 0x81, 0x16, 0xB0, 0x09, 0x00, 0x15, 0xE2, 0x68, 0x41, 0x43, 0x56, 0x00, 0x09, 0x84, 0xB2, 0x3D, 0x00, 0x83, 0x4E, 0x82, 0xE8, 0x12, 0x00, 0x7B, 0x9C, 0x2E, 0x00, 0x0C, 0x98, 0x63, 0x00, 0x83, 0x2A, 0xEF, 0x75, 0x00, 0x09, 0xED, 0x0D, 0x00, 0x06, 0x83, 0x85, 0x1D, 0x9A, 0x9B, 0xA5, 0xB3, 0xB4, 0xBC, 0x00, 0x09, 0xE5, 0x02, 0x00, 0x83, 0x48, 0xB9, 0x5D, 0x00, 0x81, 0x10, 0x88, 0x20, 0x00, 0x83, 0x2D, 0xDF, 0x3E, 0x00, 0x15, 0x81, 0xF8, 0x7D, 0x00, 0x12, 0x85, 0xF8, 0x4F, 0x00, 0x84, 0x40, 0x88, 0x20, 0x00, 0x09, 0xC8, 0x30, 0x00, 0x83, 0x36, 0x81, 0xCB, 0x6B, 0x4D, 0x4F, 0x62, 0x80, 0x81, 0x8F, 0x9A, 0x9B, 0xA5, 0x8D, 0x8E, 0x9A, 0x00, 0x83, 0x51, 0x81, 0x83, 0x74, 0x00, 0x84, 0x43, 0x88, 0x20, 0x00, 0x83, 0x66, 0x83, 0x89, 0x12, 0x00, 0x84, 0x2E, 0x98, 0x60, 0x00, 0x21, 0xC2, 0x00, 0x00, 0x84, 0x4C, 0x88, 0x20, 0x00, 0x0C, 0xC0, 0x01, 0x00, 0x83, 0x27, 0x88, 0x20, 0x00, 0x06, 0xCB, 0x5A, 0x00, 0x83, 0x63, 0x81, 0x9C, 0x42, 0x00, 0x81, 0x0D, 0xB9, 0x60, 0x00, 0x83, 0x2A, 0xE7, 0x55, 0x00, 0x06, 0x83, 0xCF, 0x46, 0xD9, 0xD9, 0xDD, 0x00, 0x83, 0x60, 0xFB, 0x48, 0x00, 0x81, 0x0D, 0xCA, 0x20, 0x00, 0x83, 0x2A, 0x95, 0x33, 0x4D, 0x4F, 0x62, 0x00, 0x06, 0xF4, 0x47, 0x00, 0x06, 0xDC, 0x05, 0x00, 0x15, 0x83, 0x9D, 0x53, 0x00, 0x83, 0x45, 0x90, 0x5E, 0x00, 0x81, 0x01, 0x88, 0x20, 0x00, 0x06, 0xBE, 0x32, 0x00, 0x83, 0x30, 0x82, 0xB7, 0x32, 0x00, 0x0C, 0xAC, 0x53, 0x00, 0x18, 0xD3, 0x74, 0x00, 0x83, 0x45, 0x84, 0x91, 0x67, 0x00, 0x7E, 0x87, 0x1C, 0x00, 0x0F, 0x81, 0xA9, 0x61, 0x00, 0x83, 0x2A, 0x81, 0xC2, 0x32, 0x00, 0x06, 0x81, 0xFF, 0x57, 0x00, 0x1E, 0x83, 0xC6, 0x73, 0x00, 0x83, 0x45, 0x82, 0x99, 0x59, 0x00, 0x78, 0x88, 0x20, 0x00, 0x09, 0xD7, 0x09, 0x00, 0x81, 0x7C, 0xF3, 0x40, 0x00, 0x86, 0x15, 0xB9, 0x60, 0x00, 0x06, 0x81, 0xFC, 0x0F, 0x00, 0x12, 0x83, 0xD4, 0x18, 0x00, 0x81, 0x7C, 0x95, 0x0F, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0xE2, 0x77, 0x00, 0x06, 0x82, 0xC1, 0x60, 0x00, 0x84, 0x67, 0x83, 0xD6, 0x20, 0x00, 0x21, 0x94, 0x08, 0x00, 0x0F, 0x81, 0x80, 0x7D, 0x00, 0x33, 0x85, 0x1A, 0x00, 0x2D, 0x2D, 0x00, 0x18, 0x85, 0x89, 0x46, 0x00, 0x81, 0x76, 0xE7, 0x4F, 0x4D, 0x4F, 0x62, 0xB3, 0xB4, 0xBC, 0x00, 0x2D, 0x85, 0x94, 0x00, 0x00, 0x84, 0x4F, 0x83, 0xCE, 0x00, 0x00, 0x24, 0xA4, 0x48, 0x00, 0x5A, 0x83, 0xD3, 0x35, 0x00, 0x27, 0x27, 0x00, 0x81, 0x76, 0xB6, 0x27, 0x00, 0x4E, 0x83, 0x1B, 0x00, 0x84, 0x37, 0xA9, 0x20, 0x00, 0x81, 0x22, 0x88, 0x20, 0xCC, 0xCD, 0xD2, 0x00, 0x81, 0x73, 0x88, 0x1D, 0x00, 0x12, 0xA2, 0x7C, 0x00, 0x06, 0x85, 0xAC, 0x5D, 0x00, 0x18, 0xB8, 0x2C, 0x00, 0x81, 0x10, 0x83, 0xD6, 0x20, 0x00, 0x84, 0x64, 0x88, 0x20, 0x00, 0x06, 0x85, 0xA2, 0x11, 0x00, 0x81, 0x7F, 0x82, 0xD2, 0x1D, 0xD9, 0xD9, 0xDD, 0x00, 0x81, 0x4C, 0x81, 0x8A, 0x48, 0x41, 0x43, 0x56, 0x00, 0x06, 0x84, 0x89, 0x3B, 0x00, 0x83, 0x27, 0xB1, 0x3D, 0x00, 0x81, 0x13, 0x88, 0x20, 0x00, 0x06, 0x82, 0xE8, 0x63, 0x00, 0x81, 0x79, 0x81, 0x90, 0x5D, 0x00, 0x0C, 0x81, 0xA6, 0x73, 0x00, 0x81, 0x58, 0x81, 0xB3, 0x62, 0x00, 0x06, 0xCD, 0x74, 0x00, 0x83, 0x45, 0xEE, 0x6B, 0x00, 0x82, 0x71, 0xC9, 0x1C, 0x00, 0x09, 0xCC, 0x10, 0x00, 0x81, 0x5E, 0x81, 0xBB, 0x7F, 0x00, 0x84, 0x49, 0x81, 0xA5, 0x00, 0x00, 0x81, 0x76, 0x82, 0x88, 0x1E, 0x00, 0x81, 0x61, 0x82, 0x6E, 0x00, 0x84, 0x49, 0x81, 0xB5, 0x40, 0x00, 0x81, 0x76, 0x81, 0xF7, 0x64, 0x00, 0x81, 0x5E, 0x96, 0x7C, 0x00, 0x06, 0x81, 0xD6, 0x5E, 0x00, 0x83, 0x45, 0x81, 0xDE, 0x63, 0x00, 0x82, 0x6E, 0x88, 0x20, 0x00, 0x81, 0x64, 0x82, 0xEA, 0x32, 0x73, 0x75, 0x83, 0x00, 0x06, 0x81, 0x67, 0x00, 0x84, 0x3D, 0xDA, 0x60, 0x00, 0x83, 0x3F, 0x84, 0xDA, 0x1D, 0x00, 0x21, 0xAD, 0x78, 0x00, 0x83, 0x48, 0x82, 0x90, 0x23, 0x00, 0x82, 0x6B, 0x88, 0x20, 0x00, 0x81, 0x4C, 0x85, 0x83, 0x40, 0x00, 0x1B, 0x88, 0x20, 0x00, 0x83, 0x4E, 0x85, 0x95, 0x61, 0x00, 0x82, 0x74, 0x88, 0x20, 0x00, 0x85, 0x2C, 0x81, 0xA6, 0x64, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x84, 0x43, 0x88, 0x20, 0x00, 0x09, 0x81, 0xBD, 0x60, 0x73, 0x75, 0x83, 0x00, 0x83, 0x51, 0x81, 0xA5, 0x12, 0x00, 0x09, 0xDF, 0x41, 0x00, 0x82, 0x62, 0x81, 0xA3, 0x79, 0x00, 0x09, 0x82, 0x98, 0x3A, 0x00, 0x81, 0x49, 0xDC, 0x56, 0x00, 0x0F, 0x82, 0x89, 0x10, 0x00, 0x09, 0x81, 0xEA, 0x45, 0x00, 0x86, 0x39, 0x81, 0x87, 0x48, 0x00, 0x81, 0x4C, 0xD2, 0x3A, 0x00, 0x0C, 0x84, 0xFC, 0x69, 0x00, 0x06, 0x81, 0xDE, 0x60, 0xA6, 0xA7, 0xB0, 0x00, 0x21, 0x82, 0xC3, 0x62, 0x00, 0x86, 0x21, 0x82, 0xB1, 0x44, 0x00, 0x81, 0x49, 0x81, 0x85, 0x6D, 0x00, 0x06, 0x81, 0x4C, 0x00, 0x33, 0x83, 0xBE, 0x7D, 0x00, 0x86, 0x24, 0x83, 0xBD, 0x3A, 0x00, 0x81, 0x40, 0x8E, 0x5F, 0x00, 0x24, 0x81, 0xFF, 0x60, 0x00, 0x86, 0x33, 0x81, 0xDA, 0x0B, 0x00, 0x09, 0xCA, 0x23, 0x00, 0x81, 0x40, 0xC2, 0x03, 0x00, 0x1E, 0x82, 0xA9, 0x00, 0x00, 0x06, 0xA2, 0x6A, 0x00, 0x86, 0x12, 0x82, 0xE2, 0x63, 0x00, 0x2A, 0x81, 0x83, 0x7D, 0x00, 0x81, 0x40, 0x9F, 0x22, 0x00, 0x81, 0x3D, 0x82, 0xA0, 0x60, 0x00, 0x06, 0x81, 0x85, 0x25, 0xB3, 0xB4, 0xBC, 0x00, 0x09, 0x81, 0xDB, 0x39, 0xFE, 0xFF, 0xFF, 0xF0, 0xF1, 0xF3, 0xCA, 0xCB, 0xD1, 0x97, 0x99, 0xA4, 0x65, 0x67, 0x78, 0x40, 0x42, 0x00, 0x84, 0x7A, 0xAA, 0x60, 0x00, 0x09, 0xA7, 0x57, 0x00, 0x81, 0x3D, 0x81, 0x9E, 0x56, 0x00, 0x81, 0x37, 0x88, 0x20, 0x00, 0x06, 0x81, 0xA7, 0x71, 0x00, 0x12, 0xD3, 0x74, 0xFE, 0xFF, 0xFF, 0xFD, 0xFE, 0xFE, 0xFC, 0xFD, 0xFE, 0xFB, 0xFC, 0xFD, 0xFA, 0xFC, 0xFD, 0xF9, 0xFB, 0xFD, 0xD2, 0xD5, 0xDB, 0xAD, 0xB0, 0xBA, 0x7C, 0x7F, 0x8D, 0x4C, 0x4E, 0x61, 0x00, 0x84, 0x79, 0x83, 0x84, 0x04, 0x00, 0x81, 0x3A, 0x88, 0x23, 0x00, 0x24, 0x82, 0xC1, 0x60, 0x00, 0x81, 0x10, 0xE3, 0x03, 0x00, 0x12, 0x83, 0xFA, 0x0E, 0x00, 0x1B, 0x88, 0x20, 0xF7, 0xFA, 0xFC, 0xF6, 0xF9, 0xFC, 0xF5, 0xF9, 0xFB, 0xF4, 0xF8, 0xFB, 0xE7, 0xEB, 0xEF, 0xB6, 0xBA, 0xC3, 0x87, 0x8A, 0x97, 0x63, 0x66, 0x77, 0x00, 0x84, 0x73, 0x88, 0x23, 0x00, 0x81, 0x34, 0xA7, 0x48, 0x00, 0x1E, 0xFB, 0x42, 0x00, 0x81, 0x10, 0x82, 0xA9, 0x00, 0x00, 0x12, 0x81, 0xCA, 0x6D, 0x00, 0x2D, 0x88, 0x20, 0xF3, 0xF7, 0xFA, 0xF2, 0xF6, 0xFA, 0xF1, 0xF6, 0xFA, 0xF0, 0xF5, 0xF9, 0xEE, 0xF4, 0xF9, 0xBF, 0xC4, 0xCD, 0x9B, 0xA0, 0xAC, 0x6D, 0x71, 0x81, 0x3F, 0x00, 0x84, 0x5D, 0x99, 0x07, 0x00, 0x09, 0xFA, 0x08, 0x00, 0x06, 0x86, 0x69, 0x00, 0x81, 0x31, 0x81, 0x9E, 0x71, 0x00, 0x1E, 0xB9, 0x60, 0x00, 0x81, 0x0A, 0xBB, 0x44, 0x4D, 0x4F, 0x62, 0x00, 0x21, 0x82, 0xBC, 0x22, 0x00, 0x2D, 0x88, 0x20, 0xED, 0xF4, 0xF8, 0xEC, 0xF3, 0xF8, 0xEB, 0xF2, 0xF8, 0xEA, 0xF1, 0xF7, 0xD2, 0xD9, 0xE1, 0xA4, 0xAA, 0xB6, 0x82, 0x87, 0x96, 0x55, 0x59, 0x6B, 0x00, 0x84, 0x1F, 0x90, 0x10, 0x00, 0x0C, 0x82, 0xB0, 0x55, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x06, 0xC8, 0x51, 0x00, 0x0F, 0x81, 0xC5, 0x7D, 0x00, 0x06, 0x81, 0xC8, 0x26, 0x00, 0x06, 0xC8, 0x6F, 0x00, 0x2D, 0x4B, 0x00, 0x81, 0x10, 0xCA, 0x20, 0x00, 0x81, 0x07, 0xD7, 0x0F, 0x67, 0x68, 0x78, 0x00, 0x24, 0x81, 0xC8, 0x5F, 0x00, 0x39, 0x88, 0x20, 0xE9, 0xF1, 0xF7, 0xE8, 0xF0, 0xF6, 0xE7, 0xEF, 0xF6, 0xE5, 0xEE, 0xF5, 0xD9, 0xE2, 0xEA, 0xB7, 0xBF, 0xCA, 0x8B, 0x91, 0xA0, 0x5F, 0x63, 0x75, 0x00, 0x84, 0x16, 0xC9, 0x79, 0x00, 0x7B, 0x81, 0xAF, 0x76, 0x00, 0x81, 0x04, 0x82, 0xDC, 0x06, 0x00, 0x81, 0x10, 0x82, 0xA9, 0x00, 0x00, 0x1B, 0xA0, 0x71, 0x00, 0x54, 0x88, 0x20, 0xE4, 0xEE, 0xF5, 0xE3, 0xED, 0xF5, 0xE2, 0xEC, 0xF4, 0xE1, 0xEC, 0xF4, 0xE0, 0xEB, 0xF3, 0xBF, 0xC8, 0xD4, 0x93, 0x9B, 0xA9, 0x73, 0x79, 0x8A, 0x49, 0x4C, 0x60, 0x00, 0x81, 0x70, 0x82, 0xA4, 0x6D, 0x00, 0x06, 0x82, 0xD7, 0x55, 0x00, 0x1B, 0x85, 0xB2, 0x3C, 0xA6, 0xA7, 0xB0, 0x73, 0x75, 0x83, 0x00, 0x81, 0x6A, 0xDF, 0x08, 0x00, 0x81, 0x76, 0x88, 0x20, 0x00, 0x0F, 0xEB, 0x20, 0x80, 0x81, 0x8F, 0x00, 0x81, 0x07, 0x88, 0x1A, 0x00, 0x21, 0xA0, 0x71, 0x00, 0x63, 0x88, 0x20, 0xDF, 0xEA, 0xF3, 0xDD, 0xE9, 0xF2, 0xDC, 0xE9, 0xF2, 0xDB, 0xE8, 0xF2, 0xC5, 0xD1, 0xDC, 0xA5, 0xAF, 0xBD, 0x7C, 0x83, 0x93, 0x5D, 0x62, 0x74, 0x00, 0x81, 0x58, 0x82, 0xE8, 0x30, 0x80, 0x81, 0x8F, 0x00, 0x2D, 0x82, 0xD7, 0x6A, 0x00, 0x0C, 0x81, 0x88, 0x2E, 0x00, 0x81, 0x61, 0x88, 0x29, 0x00, 0x36, 0x98, 0x60, 0x00, 0x33, 0x33, 0x00, 0x81, 0x0A, 0x98, 0x60, 0x00, 0x81, 0x1C, 0x8D, 0x43, 0x00, 0x30, 0x85, 0x29, 0x00, 0x60, 0x88, 0x20, 0xDA, 0xE7, 0xF1, 0xD9, 0xE6, 0xF1, 0xD8, 0xE6, 0xF0, 0xD7, 0xE5, 0xF0, 0xD6, 0xE4, 0xEF, 0xAC, 0xB8, 0xC6, 0x84, 0x8C, 0x9D, 0x65, 0x6C, 0x7E, 0x3E, 0x41, 0x55, 0x00, 0x81, 0x43, 0x88, 0x1A, 0x00, 0x15, 0x81, 0xEE, 0x4F, 0x00, 0x2D, 0x83, 0x00, 0xF2, 0xF2, 0xF4, 0x9A, 0x9B, 0xA5, 0x00, 0x83, 0x48, 0xEF, 0x57, 0x00, 0x15, 0x83, 0x48, 0x00, 0x06, 0x82, 0x90, 0x32, 0x00, 0x06, 0xFB, 0x66, 0x00, 0x81, 0x22, 0xA0, 0x71, 0x00, 0x7E, 0x88, 0x20, 0xD4, 0xE4, 0xEF, 0xD3, 0xE3, 0xEF, 0xD2, 0xE2, 0xEE, 0xD1, 0xE1, 0xEE, 0xB3, 0xC1, 0xCF, 0x95, 0xA0, 0xB0, 0x6E, 0x75, 0x88, 0x51, 0x56, 0x69, 0x00, 0x81, 0x3A, 0x85, 0xDB, 0x47, 0x00, 0x45, 0x96, 0x04, 0x00, 0x15, 0x83, 0x81, 0x4C, 0x00, 0x83, 0x30, 0x83, 0xBF, 0x21, 0x00, 0x06, 0x84, 0xB2, 0x2B, 0x00, 0x1E, 0x84, 0x28, 0xE6, 0xE6, 0xE9, 0x00, 0x75, 0xA9, 0x20, 0x00, 0x2A, 0xA0, 0x71, 0x00, 0x81, 0x0A, 0x88, 0x20, 0xD0, 0xE1, 0xED, 0xCF, 0xE0, 0xED, 0xCE, 0xDF, 0xED, 0xCD, 0xDE, 0xEC, 0xC2, 0xD3, 0xE2, 0x9B, 0xA9, 0xB9, 0x7F, 0x89, 0x9B, 0x59, 0x5F, 0x73, 0x00, 0x81, 0x34, 0xFF, 0x5B, 0x00, 0x15, 0x98, 0x3F, 0x00, 0x18, 0x81, 0xF8, 0x11, 0x00, 0x1B, 0x82, 0xF0, 0x62, 0x00, 0x83, 0x36, 0x90, 0x49, 0x00, 0x09, 0xB1, 0x31, 0x00, 0x0F, 0x81, 0x85, 0x40, 0x00, 0x09, 0x81, 0x8D, 0x78, 0xB3, 0xB4, 0xBC, 0x00, 0x0C, 0x82, 0xFC, 0x7D, 0x00, 0x6C, 0x83, 0x66, 0x00, 0x30, 0xA0, 0x71, 0x00, 0x81, 0x16, 0x88, 0x20, 0xCB, 0xDE, 0xEC, 0xCA, 0xDD, 0xEB, 0xC9, 0xDC, 0xEB, 0xC8, 0xDC, 0xEA, 0xB4, 0xC6, 0xD6, 0x7D, 0x88, 0x9A, 0x3D, 0x40, 0x00, 0x81, 0x14, 0x99, 0x01, 0x00, 0x06, 0x8C, 0x27, 0x00, 0x1B, 0x82, 0xF0, 0x29, 0x00, 0x1E, 0x81, 0x90, 0x2A, 0x00, 0x06, 0xA5, 0x31, 0x00, 0x1B, 0x81, 0xFD, 0x3A, 0xD9, 0xD9, 0xDD, 0x00, 0x83, 0x33, 0x82, 0xDF, 0x00, 0x00, 0x06, 0x87, 0x01, 0x00, 0x12, 0x81, 0x8D, 0x5D, 0x00, 0x06, 0x84, 0x2B, 0x00, 0x0C, 0x90, 0x55, 0x00, 0x06, 0xC2, 0x03, 0x00, 0x69, 0x81, 0xAD, 0x26, 0x00, 0x33, 0xA0, 0x71, 0x00, 0x81, 0x22, 0x88, 0x20, 0xC7, 0xDB, 0xEA, 0xC6, 0xDA, 0xEA, 0xB3, 0xC5, 0xD5, 0x58, 0x00, 0x81, 0x0F, 0x90, 0x4C, 0x00, 0x09, 0x82, 0xE6, 0x58, 0x00, 0x45, 0x81, 0xB1, 0x18, 0x80, 0x81, 0x8F, 0x00, 0x15, 0x88, 0x6B, 0x00, 0x83, 0x33, 0x82, 0xE7, 0x23, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0x81, 0xC7, 0x3A, 0x00, 0x06, 0xD4, 0x09, 0x00, 0x0F, 0xDA, 0x4B, 0x00, 0x06, 0x82, 0xBD, 0x14, 0x00, 0x66, 0x81, 0xCE, 0x20, 0x00, 0x36, 0xA0, 0x71, 0x00, 0x81, 0x28, 0x88, 0x20, 0xC5, 0xD9, 0xE9, 0xC4, 0xD9, 0xE9, 0x72, 0x7D, 0x90, 0x00, 0x81, 0x1C, 0x88, 0x1D, 0xE6, 0xE6, 0xE9, 0x00, 0x3F, 0xA0, 0x38, 0x00, 0x15, 0xA1, 0x48, 0x00, 0x83, 0x30, 0x88, 0x23, 0x00, 0x15, 0xEA, 0x73, 0x00, 0x18, 0x83, 0xE6, 0x4B, 0x00, 0x66, 0xEB, 0x20, 0x00, 0x39, 0xA0, 0x71, 0x00, 0x81, 0x2E, 0x88, 0x20, 0xC2, 0xD8, 0xE8, 0x8C, 0x9B, 0xAD, 0x00, 0x81, 0x10, 0x83, 0xA3, 0x71, 0x00, 0x09, 0x9C, 0x55, 0x00, 0x45, 0x9C, 0x49, 0x00, 0x15, 0xA1, 0x51, 0x00, 0x81, 0x70, 0x83, 0xAC, 0x77, 0x00, 0x81, 0x4F, 0x88, 0x20, 0x00, 0x1B, 0xE3, 0x06, 0x00, 0x60, 0x88, 0x20, 0x00, 0x3F, 0xA0, 0x71, 0x00, 0x81, 0x31, 0x88, 0x20, 0xC1, 0xD7, 0xE8, 0x72, 0x7C, 0x00, 0x7F, 0x90, 0x46, 0x00, 0x12, 0xA8, 0x5E, 0x00, 0x51, 0x9C, 0x43, 0x00, 0x12, 0x81, 0xCA, 0x58, 0x00, 0x83, 0x2A, 0x81, 0xE3, 0x26, 0x00, 0x06, 0x8B, 0x5F, 0x00, 0x09, 0x93, 0x73, 0x00, 0x09, 0x83, 0xE8, 0x50, 0x00, 0x12, 0xEC, 0x60, 0x00, 0x06, 0x98, 0x75, 0x00, 0x5A, 0xC3, 0x16, 0x00, 0x42, 0xA0, 0x71, 0x00, 0x81, 0x34, 0x88, 0x20, 0xC0, 0xD6, 0xE7, 0x4E, 0x54, 0x68, 0x00, 0x81, 0x0A, 0xD5, 0x0D, 0x00, 0x57, 0xA4, 0x60, 0x00, 0x0F, 0x82, 0xD2, 0x11, 0x00, 0x83, 0x2A, 0x82, 0xC1, 0x57, 0x00, 0x06, 0x90, 0x2E, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0xE2, 0x6E, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x12, 0x81, 0x94, 0x25, 0x00, 0x09, 0x9D, 0x23, 0x00, 0x57, 0xD2, 0x4C, 0x00, 0x0C, 0xED, 0x58, 0x00, 0x81, 0x70, 0x88, 0x20, 0x9C, 0xAE, 0xC0, 0x00, 0x7E, 0xB5, 0x3B, 0x00, 0x66, 0x83, 0xAC, 0x0B, 0x00, 0x0F, 0x90, 0x46, 0x00, 0x83, 0x2A, 0x82, 0xC1, 0x5A, 0x00, 0x0F, 0x8B, 0x5C, 0x00, 0x12, 0xBD, 0x2B, 0x00, 0x2A, 0x84, 0x89, 0x44, 0x00, 0x81, 0x0D, 0x82, 0x95, 0x70, 0x00, 0x81, 0x28, 0x88, 0x20, 0xAD, 0xC6, 0xE1, 0x4C, 0x54, 0x6E, 0x00, 0x81, 0x01, 0x82, 0xA6, 0x0F, 0x00, 0x63, 0x81, 0x87, 0x5A, 0x00, 0x0F, 0xA1, 0x0C, 0x00, 0x83, 0x2A, 0x82, 0xD6, 0x6C, 0x00, 0x09, 0xD2, 0x28, 0x00, 0x18, 0xAC, 0x5C, 0x00, 0x57, 0x82, 0xA2, 0x32, 0x00, 0x27, 0xC7, 0x11, 0x00, 0x81, 0x58, 0x88, 0x20, 0xBE, 0xD4, 0xE7, 0x98, 0xB4, 0xD9, 0x84, 0xA3, 0xD3, 0x70, 0x87, 0xB1, 0x00, 0x78, 0x81, 0xAA, 0x35, 0x00, 0x6C, 0xA8, 0x34, 0x00, 0x0F, 0xAA, 0x0C, 0x00, 0x82, 0x0B, 0x90, 0x43, 0x4D, 0x4F, 0x62, 0x00, 0x82, 0x11, 0x82, 0xE9, 0x46, 0x5A, 0x5C, 0x6D, 0x00, 0x4E, 0xA0, 0x71, 0x00, 0x81, 0x2E, 0x88, 0x20, 0xB0, 0xC8, 0xE2, 0x89, 0xA8, 0xD4, 0x84, 0xA3, 0xD3, 0x84, 0xA2, 0xD3, 0x83, 0xA1, 0xD2, 0x48, 0x50, 0x00, 0x6D, 0xB7, 0x76, 0x00, 0x0F, 0x83, 0xCB, 0x06, 0x00, 0x69, 0x81, 0x91, 0x4F, 0x00, 0x0F, 0xA1, 0x72, 0x00, 0x81, 0x7C, 0xA1, 0x06, 0x00, 0x06, 0xED, 0x7F, 0x00, 0x1B, 0x8E, 0x20, 0xC0, 0xC0, 0xC7, 0x00, 0x81, 0x64, 0xED, 0x67, 0x00, 0x69, 0xA0, 0x71, 0x00, 0x81, 0x28, 0x88, 0x20, 0xC1, 0xD6, 0xE8, 0x9D, 0xBA, 0xDC, 0x86, 0xA6, 0xD4, 0x85, 0xA4, 0xD3, 0x84, 0xA3, 0xD3, 0x83, 0xA2, 0xD2, 0x83, 0xA0, 0xD2, 0x65, 0x78, 0x9F, 0x00, 0x72, 0x82, 0x8D, 0x35, 0x00, 0x75, 0x81, 0xE7, 0x06, 0x00, 0x0C, 0xCA, 0x3B, 0x00, 0x81, 0x76, 0x84, 0x85, 0x28, 0x00, 0x2D, 0xED, 0x7F, 0x00, 0x81, 0x73, 0xED, 0x67, 0x00, 0x66, 0x82, 0xB6, 0x61, 0x00, 0x81, 0x16, 0x88, 0x20, 0xBA, 0xD1, 0xE6, 0x8E, 0xAD, 0xD7, 0x86, 0xA6, 0xD4, 0x85, 0xA5, 0xD3, 0x00, 0x09, 0x90, 0x3D, 0x82, 0x9F, 0xD2, 0x82, 0x9E, 0xD1, 0x3E, 0x43, 0x5C, 0x00, 0x72, 0x82, 0xB6, 0x4F, 0x00, 0x72, 0x81, 0xA0, 0x34, 0x00, 0x0F, 0xA5, 0x70, 0x00, 0x81, 0x70, 0xCA, 0x2F, 0x00, 0x09, 0x83, 0xF0, 0x7F, 0x00, 0x12, 0x81, 0x86, 0x41, 0x00, 0x1B, 0x82, 0xDC, 0x72, 0xE6, 0xE6, 0xE9, 0x00, 0x81, 0x64, 0x81, 0xCC, 0x7B, 0x00, 0x5D, 0xA0, 0x71, 0x00, 0x81, 0x22, 0x88, 0x20, 0xAB, 0xC5, 0xE1, 0x87, 0xA8, 0xD4, 0x86, 0xA7, 0xD4, 0x85, 0xA5, 0xD3, 0x00, 0x07, 0x90, 0x3D, 0xA1, 0xD2, 0x83, 0xA0, 0xD2, 0x82, 0x9F, 0xD2, 0x81, 0x9D, 0xD1, 0x64, 0x76, 0x00, 0x67, 0x90, 0x43, 0x00, 0x0C, 0x98, 0x5D, 0x00, 0x72, 0x83, 0xCC, 0x7F, 0x00, 0x0F, 0x83, 0x94, 0x1D, 0x00, 0x81, 0x6D, 0x98, 0x63, 0x00, 0x0F, 0x8A, 0x1C, 0x00, 0x06, 0xDD, 0x3F, 0x00, 0x15, 0xA0, 0x6E, 0x00, 0x06, 0xA8, 0x13, 0x00, 0x0F, 0x88, 0x4A, 0x00, 0x81, 0x5E, 0x82, 0x8F, 0x04, 0x00, 0x60, 0xA0, 0x71, 0x00, 0x81, 0x1C, 0x88, 0x20, 0xC5, 0xD9, 0xEA, 0x9C, 0xB9, 0xDC, 0x87, 0xA9, 0xD4, 0x86, 0xA7, 0xD4, 0x00, 0x0F, 0x98, 0x5A, 0x82, 0x9F, 0xD2, 0x81, 0x9E, 0xD1, 0x81, 0x9C, 0xD1, 0x80, 0x9B, 0xD1, 0x3D, 0x00, 0x65, 0x90, 0x43, 0x00, 0x0C, 0x83, 0x06, 0x00, 0x75, 0x81, 0xB9, 0x11, 0x00, 0x0C, 0x8C, 0x24, 0x00, 0x81, 0x6A, 0xCA, 0x2C, 0x00, 0x0C, 0x88, 0x1D, 0x00, 0x2A, 0x90, 0x10, 0x73, 0x75, 0x83, 0x00, 0x0C, 0x88, 0x26, 0x00, 0x81, 0x58, 0x88, 0x23, 0x00, 0x63, 0xA0, 0x71, 0x00, 0x81, 0x19, 0x88, 0x20, 0xBE, 0xD4, 0xE7, 0x94, 0xB3, 0xD9, 0x87, 0xA9, 0xD5, 0x00, 0x16, 0x90, 0x3D, 0x9E, 0xD1, 0x81, 0x9D, 0xD1, 0x80, 0x9C, 0xD1, 0x7F, 0x9A, 0xD0, 0x63, 0x74, 0x9E, 0x00, 0x6C, 0x82, 0x88, 0x00, 0x00, 0x78, 0x81, 0xB9, 0x11, 0x00, 0x0C, 0xA9, 0x26, 0x00, 0x81, 0x67, 0x83, 0xDE, 0x40, 0x00, 0x09, 0x81, 0xFF, 0x69, 0x00, 0x33, 0xDD, 0x3F, 0x00, 0x0F, 0x81, 0xA3, 0x73, 0x00, 0x81, 0x52, 0x9B, 0x12, 0x00, 0x75, 0x82, 0xD7, 0x52, 0x00, 0x81, 0x07, 0x88, 0x20, 0xB7, 0xCE, 0xE5, 0x8C, 0xAE, 0xD6, 0x88, 0xAA, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x1B, 0x90, 0x3D, 0x7F, 0x9A, 0xD0, 0x7F, 0x98, 0xD0, 0x3D, 0x42, 0x00, 0x5E, 0x90, 0x43, 0x00, 0x0C, 0x85, 0x29, 0x00, 0x0C, 0x84, 0xEE, 0x4F, 0x00, 0x75, 0x82, 0x8E, 0x36, 0x00, 0x7B, 0x81, 0x04, 0x00, 0x75, 0x84, 0xC1, 0x67, 0x00, 0x3C, 0x93, 0x31, 0x00, 0x09, 0xC5, 0x30, 0x00, 0x81, 0x4C, 0x82, 0xFD, 0x78, 0x00, 0x6C, 0xA0, 0x71, 0x00, 0x81, 0x13, 0x88, 0x20, 0xAF, 0xC9, 0xE2, 0x89, 0xAB, 0xD5, 0x88, 0xAA, 0xD5, 0x87, 0xA9, 0xD4, 0x87, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x11, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x7F, 0x99, 0xD0, 0x7E, 0x98, 0xD0, 0x62, 0x72, 0x00, 0x5E, 0x90, 0x43, 0x00, 0x0C, 0x87, 0x1C, 0x00, 0x7B, 0x8F, 0x3C, 0x00, 0x75, 0xBA, 0x5E, 0x00, 0x81, 0x01, 0x8E, 0x20, 0x00, 0x3C, 0x87, 0x5B, 0x00, 0x0C, 0x85, 0x92, 0x7C, 0x00, 0x81, 0x01, 0x98, 0x66, 0x00, 0x18, 0x82, 0xF4, 0x33, 0x00, 0x2D, 0xC3, 0x3A, 0x00, 0x6F, 0xA0, 0x71, 0x00, 0x81, 0x10, 0x88, 0x20, 0xA3, 0xC0, 0xDF, 0x89, 0xAC, 0xD5, 0x88, 0x00, 0x06, 0x88, 0x20, 0x00, 0x1A, 0xA9, 0x17, 0x80, 0x9C, 0xD1, 0x80, 0x9B, 0x00, 0x07, 0x88, 0x1D, 0x7E, 0x97, 0xCF, 0x78, 0x8F, 0xC7, 0x39, 0x3C, 0x53, 0x00, 0x66, 0x97, 0x5C, 0x00, 0x7B, 0x81, 0xE2, 0x2E, 0x00, 0x0C, 0x9C, 0x6D, 0x00, 0x81, 0x61, 0x88, 0x20, 0x00, 0x09, 0x81, 0x6D, 0x00, 0x3F, 0xC9, 0x79, 0x00, 0x09, 0x93, 0x7C, 0x00, 0x78, 0xBC, 0x18, 0x00, 0x21, 0xF2, 0x42, 0x00, 0x2A, 0xD6, 0x14, 0x00, 0x72, 0xA0, 0x71, 0x00, 0x81, 0x0A, 0x88, 0x20, 0xCB, 0xDD, 0xEC, 0x97, 0xB7, 0xDA, 0x89, 0xAD, 0xD6, 0x00, 0x1E, 0x90, 0x3D, 0x00, 0x0F, 0x98, 0x5A, 0x7E, 0x97, 0xCF, 0x7D, 0x96, 0xCF, 0x7C, 0x95, 0xCF, 0x58, 0x65, 0x8D, 0x00, 0x66, 0x9B, 0x6C, 0x00, 0x82, 0x65, 0x83, 0xD6, 0x20, 0x00, 0x09, 0xA9, 0x17, 0x00, 0x45, 0xAC, 0x0B, 0x00, 0x7B, 0x84, 0xD2, 0x00, 0x00, 0x0C, 0x91, 0x41, 0x00, 0x3F, 0x83, 0xAD, 0x00, 0x00, 0x81, 0x04, 0x82, 0xF8, 0x43, 0x00, 0x78, 0x88, 0x20, 0xC8, 0xDB, 0xEB, 0x97, 0xB8, 0xDA, 0x8A, 0xAD, 0xD6, 0x89, 0xAC, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x28, 0x90, 0x3D, 0x7D, 0x96, 0xCF, 0x7D, 0x95, 0xCF, 0x7C, 0x94, 0xCE, 0x77, 0x8D, 0xC6, 0x38, 0x00, 0x59, 0x90, 0x43, 0x00, 0x82, 0x71, 0x88, 0x20, 0x00, 0x09, 0x9E, 0x60, 0x00, 0x45, 0xDA, 0x36, 0x00, 0x27, 0x84, 0xD2, 0x4E, 0x00, 0x5A, 0x94, 0x7A, 0x00, 0x3F, 0x81, 0xF0, 0x60, 0x00, 0x7B, 0xA0, 0x71, 0x00, 0x81, 0x04, 0x88, 0x20, 0xC5, 0xD9, 0xEA, 0x8F, 0xB2, 0xD8, 0x8A, 0xAE, 0x00, 0x05, 0x88, 0x1D, 0x00, 0x0B, 0x98, 0x5A, 0x00, 0x21, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x7C, 0x93, 0xCE, 0x7B, 0x92, 0xCE, 0x57, 0x63, 0x8C, 0x00, 0x83, 0x48, 0x88, 0x20, 0x00, 0x09, 0x81, 0xFF, 0x5A, 0x00, 0x4E, 0xD5, 0x01, 0x00, 0x72, 0x98, 0x63, 0x00, 0x06, 0x83, 0x33, 0x00, 0x3C, 0x89, 0x66, 0x00, 0x0F, 0x85, 0xB5, 0x3F, 0x00, 0x81, 0x70, 0x88, 0x20, 0xC6, 0xD9, 0xEA, 0x90, 0xB3, 0xD8, 0x8A, 0xAE, 0xD6, 0x00, 0x0B, 0x90, 0x3D, 0x00, 0x28, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x7B, 0x92, 0xCE, 0x7B, 0x91, 0xCE, 0x76, 0x8A, 0xC5, 0x00, 0x57, 0x90, 0x43, 0x00, 0x82, 0x6E, 0x88, 0x20, 0x00, 0x09, 0xCC, 0x0D, 0x00, 0x4B, 0x82, 0x96, 0x59, 0x00, 0x78, 0x85, 0xB5, 0x00, 0x00, 0x3F, 0x83, 0xEF, 0x00, 0x00, 0x81, 0x0D, 0x88, 0x1D, 0x00, 0x72, 0x88, 0x20, 0xC7, 0xDA, 0xEB, 0x90, 0xB3, 0xD8, 0x8B, 0xAF, 0xD6, 0x00, 0x25, 0x90, 0x3D, 0x00, 0x11, 0xA9, 0x17, 0x00, 0x05, 0x88, 0x1D, 0x00, 0x05, 0x90, 0x3D, 0x91, 0xCE, 0x7A, 0x90, 0xCD, 0x79, 0x8F, 0xCD, 0x56, 0x62, 0x00, 0x55, 0x90, 0x43, 0x00, 0x0C, 0xDA, 0x5D, 0x00, 0x7B, 0x88, 0x20, 0x00, 0x81, 0x67, 0xB1, 0x40, 0x00, 0x09, 0xB4, 0x2E, 0x00, 0x4B, 0xD4, 0x27, 0x00, 0x78, 0x85, 0xB5, 0x00, 0x00, 0x06, 0xD6, 0x77, 0x00, 0x48, 0xFF, 0x5E, 0x00, 0x81, 0x6D, 0x88, 0x20, 0xBF, 0xD4, 0xE8, 0x90, 0xB4, 0x00, 0x08, 0x88, 0x1D, 0x00, 0x20, 0xA9, 0x17, 0x00, 0x10, 0x90, 0x3D, 0x00, 0x0E, 0x98, 0x5A, 0x7A, 0x91, 0xCE, 0x7A, 0x8F, 0xCD, 0x79, 0x8E, 0xCD, 0x74, 0x87, 0xC5, 0x00, 0x63, 0xC0, 0x7C, 0x00, 0x81, 0x04, 0x88, 0x20, 0x00, 0x81, 0x5B, 0xF9, 0x4F, 0x00, 0x54, 0x82, 0xD2, 0x20, 0x00, 0x78, 0x85, 0xB5, 0x00, 0x00, 0x06, 0x81, 0x80, 0x14, 0x00, 0x36, 0x89, 0x69, 0x00, 0x0F, 0x84, 0x76, 0x00, 0x81, 0x6D, 0x88, 0x20, 0xBB, 0xD2, 0xE7, 0x8C, 0xB1, 0xD7, 0x8B, 0xB0, 0xD6, 0x00, 0x0E, 0x98, 0x5A, 0x00, 0x2B, 0xB9, 0x54, 0x00, 0x10, 0x90, 0x3D, 0x8E, 0xCD, 0x78, 0x8D, 0xCD, 0x78, 0x8C, 0xCC, 0x4D, 0x56, 0x7B, 0x00, 0x81, 0x55, 0x87, 0x1C, 0x00, 0x81, 0x07, 0xC3, 0x04, 0x00, 0x81, 0x37, 0x88, 0x20, 0x00, 0x7B, 0x82, 0xDB, 0x14, 0x00, 0x06, 0x81, 0xB9, 0x14, 0x8D, 0x8E, 0x9A, 0x00, 0x30, 0xA9, 0x23, 0x00, 0x81, 0x01, 0x81, 0xF1, 0x4C, 0x00, 0x78, 0x88, 0x20, 0xBC, 0xD3, 0xE7, 0x8C, 0xB2, 0xD7, 0x8C, 0xB1, 0xD7, 0x00, 0x10, 0x90, 0x3D, 0x00, 0x35, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x78, 0x8D, 0xCD, 0x78, 0x8B, 0xCC, 0x6E, 0x7F, 0x00, 0x55, 0xAD, 0x24, 0x00, 0x0C, 0xDF, 0x50, 0x00, 0x81, 0x01, 0xDA, 0x60, 0x00, 0x81, 0x5E, 0x82, 0xC6, 0x35, 0x00, 0x54, 0x87, 0x4C, 0x00, 0x78, 0x85, 0xB5, 0x00, 0x00, 0x39, 0x83, 0xBD, 0x40, 0x00, 0x0F, 0xD7, 0x33, 0x00, 0x81, 0x6A, 0x88, 0x20, 0xCB, 0xDD, 0xEC, 0x91, 0xB5, 0xD9, 0x00, 0x27, 0x90, 0x3D, 0x00, 0x24, 0xA9, 0x17, 0x00, 0x0C, 0x90, 0x3D, 0x77, 0x8A, 0xCC, 0x76, 0x89, 0xCC, 0x4D, 0x55, 0x00, 0x52, 0x90, 0x43, 0x00, 0x0C, 0xC5, 0x63, 0x00, 0x81, 0x01, 0xEB, 0x20, 0x00, 0x81, 0x5E, 0x81, 0x9C, 0x66, 0x00, 0x54, 0x82, 0xC1, 0x5D, 0x00, 0x09, 0x87, 0x28, 0x00, 0x6F, 0xDD, 0x18, 0x00, 0x39, 0x88, 0x20, 0x00, 0x0F, 0x81, 0x91, 0x0D, 0x00, 0x81, 0x67, 0x88, 0x20, 0xCB, 0xDD, 0xEC, 0x91, 0xB6, 0xD9, 0x8C, 0xB2, 0xD7, 0x8B, 0xB0, 0x00, 0x08, 0x90, 0x3D, 0x00, 0x2C, 0xB9, 0x54, 0x00, 0x18, 0xA9, 0x17, 0x79, 0x8E, 0x00, 0x05, 0x88, 0x1D, 0x8B, 0x00, 0x05, 0x88, 0x20, 0x88, 0xCB, 0x6D, 0x7D, 0xBB, 0x00, 0x60, 0x84, 0xE1, 0x42, 0x00, 0x82, 0x5F, 0x84, 0x8F, 0x7D, 0x00, 0x51, 0x8B, 0x08, 0x00, 0x06, 0x8A, 0x5E, 0x00, 0x81, 0x2B, 0x9B, 0x18, 0x00, 0x81, 0x0D, 0xB1, 0x37, 0x00, 0x66, 0x88, 0x20, 0xCD, 0xDE, 0xED, 0x92, 0xB7, 0xD9, 0x00, 0x16, 0x98, 0x5A, 0x00, 0x38, 0xB9, 0x54, 0x00, 0x0C, 0x98, 0x5A, 0x00, 0x05, 0x90, 0x3D, 0xCB, 0x75, 0x87, 0xCB, 0x75, 0x86, 0xCB, 0x4C, 0x54, 0x00, 0x52, 0x90, 0x43, 0x00, 0x7B, 0x84, 0xEF, 0x56, 0x00, 0x0C, 0x8D, 0x07, 0x00, 0x81, 0x64, 0x81, 0x94, 0x40, 0x00, 0x15, 0x85, 0xCD, 0x78, 0x00, 0x42, 0x83, 0x3C, 0x00, 0x81, 0x2B, 0xFE, 0x18, 0x00, 0x81, 0x16, 0x83, 0xD3, 0x0B, 0x00, 0x5A, 0x88, 0x20, 0xD3, 0xE2, 0xEF, 0x92, 0xB7, 0xDA, 0x8D, 0xB3, 0xD7, 0x00, 0x10, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x11, 0x90, 0x3D, 0x75, 0x87, 0xCB, 0x74, 0x85, 0xCA, 0x6C, 0x7A, 0xBA, 0x00, 0x5D, 0x81, 0x8C, 0x23, 0x00, 0x6C, 0x87, 0x25, 0x00, 0x0F, 0x81, 0xAD, 0x23, 0x00, 0x81, 0x64, 0x81, 0x8C, 0x1D, 0x00, 0x09, 0xDA, 0x60, 0x00, 0x45, 0xA0, 0x2F, 0x00, 0x09, 0x4E, 0x00, 0x7E, 0xEB, 0x23, 0x67, 0x68, 0x78, 0x00, 0x27, 0x84, 0xF7, 0x40, 0x00, 0x0F, 0x81, 0xB2, 0x0A, 0x00, 0x81, 0x61, 0x88, 0x20, 0xD8, 0xE6, 0xF1, 0x9C, 0xBE, 0xDD, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x21, 0x90, 0x3D, 0x00, 0x36, 0xA9, 0x17, 0x00, 0x0C, 0x90, 0x3D, 0x74, 0x85, 0xCA, 0x73, 0x84, 0xCA, 0x48, 0x4E, 0x00, 0x4F, 0x81, 0xEF, 0x50, 0x00, 0x0F, 0x83, 0x36, 0x00, 0x69, 0x84, 0x6D, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x81, 0x67, 0x81, 0xB5, 0x40, 0x00, 0x09, 0x8A, 0x13, 0x00, 0x45, 0xAB, 0x0A, 0x00, 0x06, 0x97, 0x2C, 0x00, 0x7B, 0x98, 0x5D, 0x00, 0x0C, 0x81, 0x8D, 0x30, 0x00, 0x09, 0x81, 0x52, 0x73, 0x75, 0x83, 0x00, 0x18, 0x83, 0xEA, 0x34, 0x00, 0x81, 0x13, 0xB9, 0x5A, 0x00, 0x5A, 0x88, 0x20, 0xDA, 0xE7, 0xF1, 0x9D, 0xBF, 0xDD, 0x8D, 0xB4, 0xD8, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x2F, 0xB9, 0x54, 0x00, 0x2A, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x74, 0x84, 0xCA, 0x73, 0x83, 0xCA, 0x63, 0x6E, 0xAA, 0x00, 0x60, 0x81, 0x9C, 0x66, 0x00, 0x63, 0x87, 0x2B, 0x00, 0x0F, 0x81, 0xCF, 0x12, 0x00, 0x81, 0x6A, 0x81, 0xC6, 0x00, 0x00, 0x09, 0x8A, 0x16, 0x00, 0x3F, 0xB4, 0x2E, 0x00, 0x09, 0xB3, 0x78, 0x00, 0x78, 0x82, 0x3B, 0x00, 0x06, 0x91, 0x3E, 0x00, 0x06, 0x82, 0x83, 0x70, 0x00, 0x0C, 0x84, 0x88, 0x64, 0x00, 0x06, 0x18, 0x00, 0x15, 0x99, 0x73, 0x00, 0x81, 0x6D, 0x88, 0x20, 0xAC, 0xC9, 0xE2, 0x8D, 0xB4, 0xD8, 0x00, 0x13, 0x98, 0x5A, 0x00, 0x3C, 0xB9, 0x54, 0x00, 0x18, 0x98, 0x5A, 0x86, 0xCB, 0x00, 0x06, 0x88, 0x1D, 0x72, 0x82, 0xC9, 0x72, 0x80, 0xC9, 0x43, 0x48, 0x00, 0x4F, 0x82, 0xC2, 0x6D, 0x00, 0x0F, 0x97, 0x6B, 0x00, 0x63, 0x9D, 0x50, 0x00, 0x0C, 0xA5, 0x28, 0x00, 0x81, 0x6D, 0x81, 0xB5, 0x3A, 0x00, 0x0C, 0x85, 0xCE, 0x07, 0x00, 0x39, 0xAB, 0x10, 0x00, 0x09, 0x81, 0xDD, 0x44, 0x00, 0x78, 0x81, 0x8C, 0x20, 0x00, 0x06, 0x84, 0x31, 0x00, 0x09, 0x85, 0xA6, 0x00, 0x00, 0x0F, 0x85, 0xE6, 0x40, 0x00, 0x18, 0x82, 0xFB, 0x40, 0x00, 0x81, 0x6A, 0x88, 0x20, 0xB7, 0xD0, 0xE6, 0x8E, 0xB5, 0xD8, 0x00, 0x0F, 0x90, 0x3D, 0x00, 0x43, 0xA9, 0x17, 0x00, 0x11, 0x90, 0x3D, 0x00, 0x0C, 0x98, 0x5A, 0x73, 0x82, 0xCA, 0x72, 0x81, 0xC9, 0x71, 0x80, 0xC9, 0x62, 0x6C, 0xA9, 0x00, 0x60, 0x81, 0xB5, 0x49, 0x00, 0x5D, 0xB9, 0x6C, 0x00, 0x0F, 0x81, 0x80, 0x38, 0x00, 0x81, 0x70, 0x83, 0x80, 0x09, 0x00, 0x09, 0xC0, 0x04, 0x00, 0x18, 0x85, 0xAC, 0x60, 0x00, 0x27, 0x88, 0x1D, 0x00, 0x7B, 0x82, 0x82, 0x21, 0x00, 0x06, 0x91, 0x3E, 0x00, 0x09, 0x83, 0x39, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x18, 0x85, 0xA4, 0x40, 0x00, 0x81, 0x67, 0x88, 0x20, 0xC2, 0xD8, 0xE9, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x28, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x0E, 0x90, 0x3D, 0x71, 0x7F, 0xC9, 0x70, 0x7D, 0xC8, 0x43, 0x48, 0x6A, 0x00, 0x81, 0x37, 0x84, 0xB0, 0x0E, 0x00, 0x0F, 0x66, 0x00, 0x81, 0x76, 0x81, 0xDE, 0x5A, 0x00, 0x09, 0xA8, 0x5B, 0xF2, 0xF2, 0xF4, 0x00, 0x2D, 0x8A, 0x1F, 0x00, 0x0C, 0x81, 0x8A, 0x4B, 0x00, 0x7B, 0x82, 0xAB, 0x4D, 0x00, 0x06, 0x84, 0xFB, 0x0B, 0x00, 0x30, 0x85, 0xFF, 0x20, 0x00, 0x81, 0x64, 0x88, 0x20, 0xD2, 0xE2, 0xEF, 0x94, 0xB9, 0xDA, 0x8E, 0xB5, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x31, 0xB9, 0x54, 0x00, 0x38, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x71, 0x7E, 0xC8, 0x70, 0x7D, 0xC8, 0x60, 0x6A, 0x00, 0x52, 0x90, 0x43, 0x00, 0x12, 0xD5, 0x7C, 0x00, 0x4E, 0x90, 0x46, 0x00, 0x12, 0x81, 0x90, 0x72, 0x00, 0x81, 0x7C, 0x83, 0xD2, 0x46, 0x00, 0x0C, 0x87, 0x6A, 0xB3, 0xB4, 0xBC, 0x00, 0x21, 0x90, 0x49, 0x4D, 0x4F, 0x62, 0x00, 0x0C, 0x85, 0xB5, 0x36, 0x00, 0x7E, 0xC4, 0x2C, 0x00, 0x0F, 0x84, 0xA9, 0x55, 0x00, 0x82, 0x08, 0x88, 0x20, 0xDE, 0xEA, 0xF3, 0x99, 0xBD, 0xDC, 0x00, 0x12, 0x98, 0x5A, 0x00, 0x3C, 0xE2, 0x6B, 0x00, 0x27, 0xA9, 0x17, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x05, 0x90, 0x3D, 0x6F, 0x7C, 0xC8, 0x6F, 0x7B, 0xC7, 0x43, 0x47, 0x00, 0x52, 0x90, 0x43, 0x00, 0x12, 0xF6, 0x79, 0x00, 0x36, 0x96, 0x04, 0x00, 0x24, 0x81, 0xA0, 0x61, 0x00, 0x82, 0x02, 0x83, 0xDA, 0x63, 0x00, 0x0F, 0x85, 0x82, 0x00, 0xD9, 0xD9, 0xDD, 0x8D, 0x8E, 0x9A, 0x00, 0x0C, 0x81, 0xA3, 0x3A, 0x00, 0x06, 0x81, 0xE7, 0x0C, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0x82, 0x3B, 0x00, 0x81, 0x04, 0x82, 0xB3, 0x61, 0x00, 0x06, 0x82, 0xE4, 0x1A, 0x00, 0x18, 0x88, 0x20, 0x00, 0x18, 0x82, 0xFB, 0x40, 0x00, 0x81, 0x61, 0x88, 0x20, 0xA9, 0xC8, 0xE1, 0x8E, 0xB6, 0xD8, 0x00, 0x13, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x12, 0x90, 0x3D, 0x00, 0x18, 0x98, 0x5A, 0x00, 0x05, 0x90, 0x3D, 0x6F, 0x7B, 0xC8, 0x6E, 0x7A, 0xC7, 0x58, 0x60, 0x99, 0x00, 0x66, 0x81, 0xB0, 0x47, 0x00, 0x3F, 0x81, 0xDB, 0x57, 0x00, 0x06, 0x81, 0xDC, 0x43, 0x00, 0x82, 0x05, 0x83, 0xE3, 0x00, 0x00, 0x7B, 0x86, 0x03, 0x00, 0x4E, 0xA3, 0x65, 0x00, 0x06, 0x9A, 0x20, 0x00, 0x09, 0xBE, 0x0B, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x06, 0x83, 0x6F, 0x00, 0x12, 0x99, 0x7F, 0x00, 0x81, 0x5E, 0x88, 0x20, 0xBF, 0xD6, 0xE9, 0x8F, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x23, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x16, 0x90, 0x3D, 0x00, 0x06, 0x88, 0x1D, 0x7C, 0xC8, 0x6E, 0x7A, 0xC7, 0x6E, 0x79, 0xC7, 0x6D, 0x78, 0xC7, 0x3B, 0x3E, 0x5A, 0x00, 0x69, 0xDE, 0x61, 0x00, 0x06, 0x88, 0x26, 0x00, 0x2D, 0x90, 0x4C, 0x4D, 0x4F, 0x62, 0x00, 0x12, 0x82, 0xF1, 0x03, 0x00, 0x81, 0x7C, 0x81, 0xEF, 0x0B, 0x00, 0x81, 0x49, 0x88, 0x20, 0x00, 0x06, 0xEF, 0x5A, 0x00, 0x09, 0xA2, 0x3D, 0x00, 0x0C, 0x88, 0x20, 0x00, 0x06, 0x88, 0x3B, 0x00, 0x15, 0xB5, 0x14, 0x00, 0x81, 0x5B, 0x88, 0x20, 0xD5, 0xE4, 0xF0, 0x8F, 0xB7, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x33, 0xB9, 0x54, 0x00, 0x46, 0xA9, 0x17, 0x00, 0x0B, 0x90, 0x3D, 0x6E, 0x79, 0xC7, 0x6D, 0x77, 0xC6, 0x57, 0x5E, 0x98, 0x00, 0x72, 0x81, 0xD9, 0x64, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x84, 0xAE, 0x27, 0x00, 0x18, 0x81, 0xDC, 0x0D, 0x00, 0x06, 0x86, 0x8B, 0x71, 0x00, 0x15, 0x3C, 0x00, 0x27, 0x85, 0xE4, 0x65, 0x00, 0x83, 0x24, 0x88, 0x20, 0x00, 0x0C, 0xBA, 0x64, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x84, 0xEA, 0x69, 0x00, 0x09, 0xCB, 0x33, 0x00, 0x15, 0x83, 0x66, 0x00, 0x81, 0x58, 0x88, 0x20, 0xE1, 0xEC, 0xF4, 0x9A, 0xBE, 0xDC, 0x00, 0x16, 0x98, 0x5A, 0x00, 0x39, 0xB9, 0x54, 0x00, 0x35, 0xA9, 0x17, 0x00, 0x0C, 0x90, 0x3D, 0x6C, 0x77, 0xC6, 0x6C, 0x75, 0xC6, 0x00, 0x3F, 0x90, 0x43, 0x00, 0x21, 0x84, 0xC9, 0x12, 0x00, 0x81, 0x22, 0x84, 0xC1, 0x7F, 0x00, 0x82, 0x7A, 0x84, 0xC7, 0x5E, 0x5A, 0x5C, 0x6D, 0x00, 0x15, 0x82, 0xFB, 0x40, 0x00, 0x18, 0x8C, 0x03, 0x00, 0x81, 0x58, 0x88, 0x20, 0xAB, 0xC9, 0xE2, 0x00, 0x12, 0x90, 0x3D, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x26, 0xA9, 0x17, 0x6E, 0x7A, 0xC7, 0x6D, 0x78, 0xC7, 0x6D, 0x77, 0xC6, 0x6C, 0x76, 0xC6, 0x6B, 0x74, 0xC6, 0x56, 0x5C, 0x97, 0x00, 0x81, 0x52, 0xE6, 0x30, 0x00, 0x69, 0x88, 0x20, 0x00, 0x82, 0x44, 0x82, 0xA1, 0x58, 0x5A, 0x5C, 0x6D, 0x00, 0x27, 0x82, 0xFB, 0x40, 0x00, 0x81, 0x55, 0x88, 0x20, 0xCC, 0xDE, 0xED, 0x8F, 0xB7, 0xD9, 0x00, 0x28, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x0E, 0x90, 0x3D, 0x00, 0x1A, 0x98, 0x5A, 0xC7, 0x6C, 0x76, 0xC6, 0x6B, 0x75, 0xC6, 0x6B, 0x73, 0xC5, 0x6A, 0x72, 0xC5, 0x3B, 0x3D, 0x00, 0x3A, 0x90, 0x43, 0x00, 0x81, 0x7F, 0x88, 0x20, 0x00, 0x06, 0xD8, 0x1F, 0x00, 0x82, 0x68, 0x83, 0xDB, 0x6D, 0x00, 0x81, 0x52, 0x88, 0x20, 0xDE, 0xEA, 0xF3, 0x95, 0xBB, 0xDB, 0x00, 0x2A, 0xA9, 0x17, 0x00, 0x4E, 0xE2, 0x6B, 0x00, 0x13, 0x90, 0x3D, 0x00, 0x0B, 0x98, 0x5A, 0x6B, 0x74, 0xC6, 0x6A, 0x73, 0xC5, 0x6A, 0x71, 0xC5, 0x55, 0x5A, 0x00, 0x3A, 0x90, 0x43, 0x00, 0x82, 0x02, 0x88, 0x20, 0x00, 0x82, 0x3E, 0x84, 0x8D, 0x36, 0x41, 0x43, 0x56, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0xE3, 0x03, 0xB3, 0xB4, 0xBC, 0x00, 0x1E, 0x81, 0x9C, 0x6F, 0x00, 0x81, 0x52, 0x88, 0x20, 0xA6, 0xC6, 0xE1, 0x00, 0x3C, 0xA9, 0x17, 0x00, 0x13, 0x90, 0x3D, 0x00, 0x43, 0xA9, 0x17, 0x00, 0x0D, 0x90, 0x3D, 0x69, 0x70, 0xC5, 0x65, 0x6C, 0xBC, 0x37, 0x3A, 0x00, 0x37, 0x81, 0xBE, 0x01, 0x00, 0x63, 0x84, 0xEA, 0x54, 0x00, 0x63, 0x63, 0x00, 0x48, 0x83, 0x8D, 0x58, 0x00, 0x06, 0xA6, 0x65, 0x00, 0x82, 0x29, 0x90, 0x4F, 0x00, 0x18, 0x82, 0xDE, 0x17, 0x00, 0x18, 0xB5, 0x20, 0x00, 0x81, 0x4F, 0x88, 0x20, 0xC3, 0xD8, 0xEA, 0x8F, 0xB8, 0xD9, 0x00, 0x10, 0x90, 0x3D, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x35, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x69, 0x70, 0xC4, 0x68, 0x6F, 0xC4, 0x4E, 0x52, 0x87, 0x00, 0x82, 0x41, 0x9E, 0x45, 0x00, 0x0C, 0x82, 0xF4, 0x51, 0xB3, 0xB4, 0xBC, 0x00, 0x82, 0x20, 0x83, 0xE4, 0x1F, 0x00, 0x0C, 0x81, 0xE0, 0x2C, 0x73, 0x75, 0x83, 0x67, 0x68, 0x78, 0x73, 0x75, 0x83, 0x00, 0x09, 0xD6, 0x20, 0x00, 0x15, 0x88, 0x23, 0x00, 0x81, 0x4C, 0x88, 0x20, 0xE5, 0xEE, 0xF6, 0x95, 0xBC, 0xDB, 0x00, 0x27, 0x90, 0x3D, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x20, 0xA9, 0x17, 0x6A, 0x00, 0x08, 0x90, 0x3D, 0x68, 0x6F, 0xC4, 0x68, 0x6E, 0xC4, 0x64, 0x69, 0xBC, 0x37, 0x39, 0x00, 0x5B, 0x81, 0xEF, 0x4A, 0x00, 0x81, 0x6D, 0x82, 0xB0, 0x28, 0x00, 0x0C, 0x90, 0x4F, 0x00, 0x81, 0x79, 0x82, 0xB0, 0x16, 0x00, 0x24, 0xF3, 0x40, 0x00, 0x15, 0xB9, 0x48, 0x00, 0x1B, 0x82, 0xD2, 0x20, 0x00, 0x81, 0x4C, 0x88, 0x20, 0xAC, 0xCB, 0xE3, 0x00, 0x2B, 0xA9, 0x17, 0x00, 0x26, 0x81, 0xEE, 0x6D, 0x00, 0x40, 0xB9, 0x54, 0x00, 0x0F, 0x98, 0x5A, 0x00, 0x06, 0x90, 0x3D, 0x6E, 0xC4, 0x67, 0x6D, 0xC4, 0x67, 0x6C, 0xC3, 0x4D, 0x50, 0x00, 0x82, 0x3F, 0x90, 0x43, 0x00, 0x18, 0xC3, 0x7C, 0x00, 0x82, 0x14, 0xA9, 0x44, 0x00, 0x06, 0xF3, 0x40, 0x00, 0x18, 0xA3, 0x32, 0x00, 0x06, 0x90, 0x5B, 0x00, 0x12, 0x90, 0x43, 0x00, 0x81, 0x49, 0x88, 0x20, 0xD5, 0xE4, 0xF0, 0x00, 0x13, 0x98, 0x5A, 0x00, 0x40, 0xE2, 0x6B, 0x00, 0x3B, 0xA9, 0x17, 0x00, 0x12, 0x90, 0x3D, 0x00, 0x08, 0x98, 0x5A, 0x00, 0x06, 0x88, 0x1D, 0x66, 0x6B, 0xC3, 0x62, 0x67, 0xBB, 0x37, 0x39, 0x52, 0x00, 0x82, 0x44, 0x90, 0x43, 0x00, 0x0C, 0x82, 0xA7, 0x6D, 0xCC, 0xCD, 0xD2, 0x00, 0x12, 0x81, 0x92, 0x23, 0x00, 0x82, 0x08, 0x83, 0xBF, 0x30, 0x00, 0x18, 0x92, 0x5A, 0x00, 0x06, 0x81, 0xB0, 0x77, 0x00, 0x81, 0x58, 0xEB, 0x20, 0xE7, 0xF0, 0xF6, 0x9B, 0xC0, 0xDD, 0x00, 0x0F, 0x90, 0x3D, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x0E, 0x90, 0x3D, 0x66, 0x6A, 0xC3, 0x65, 0x69, 0xC2, 0x49, 0x4C, 0x7F, 0x00, 0x82, 0x41, 0xA1, 0x03, 0x00, 0x0C, 0xE4, 0x22, 0x00, 0x09, 0x96, 0x3D, 0x00, 0x06, 0x81, 0x9A, 0x34, 0x00, 0x82, 0x0B, 0xCB, 0x09, 0x00, 0x36, 0x83, 0xEF, 0x00, 0x00, 0x81, 0x46, 0x88, 0x20, 0xBF, 0xD6, 0xE9, 0x00, 0x23, 0x90, 0x3D, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x33, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x65, 0x6A, 0xC3, 0x65, 0x68, 0xC2, 0x58, 0x5B, 0xA4, 0x00, 0x82, 0x44, 0xA0, 0x74, 0x00, 0x18, 0xED, 0x0D, 0x4D, 0x4F, 0x62, 0x00, 0x82, 0x08, 0xA1, 0x0C, 0x00, 0x06, 0xEF, 0x42, 0x00, 0x1E, 0x90, 0x40, 0x00, 0x81, 0x55, 0xF3, 0x40, 0xE2, 0xED, 0xF5, 0x96, 0x00, 0x29, 0xA9, 0x17, 0x00, 0x36, 0x81, 0xEE, 0x6D, 0x00, 0x2C, 0x90, 0x3D, 0x00, 0x1F, 0xA9, 0x17, 0x67, 0x6D, 0xC3, 0x66, 0x6B, 0x00, 0x07, 0x90, 0x3D, 0x64, 0x67, 0xC2, 0x64, 0x66, 0xC2, 0x00, 0x82, 0x32, 0x85, 0xDB, 0x68, 0x00, 0x81, 0x25, 0xC2, 0x03, 0x00, 0x06, 0xFB, 0x66, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x83, 0xAB, 0x64, 0x00, 0x81, 0x01, 0xE5, 0x44, 0x00, 0x0F, 0xF3, 0x40, 0x00, 0x15, 0x1E, 0x00, 0x81, 0x55, 0xF3, 0x40, 0xAD, 0x00, 0x3B, 0xA9, 0x17, 0x00, 0x27, 0x81, 0xEE, 0x6D, 0x00, 0x3D, 0xB9, 0x54, 0x00, 0x16, 0x98, 0x5A, 0xC3, 0x64, 0x68, 0xC2, 0x64, 0x67, 0xC2, 0x63, 0x65, 0xC1, 0x3D, 0x3F, 0x00, 0x82, 0x2D, 0x84, 0x81, 0x0F, 0x00, 0x12, 0x98, 0x4B, 0x00, 0x66, 0x99, 0x49, 0x00, 0x2A, 0x91, 0x08, 0x00, 0x15, 0x86, 0x86, 0x24, 0x00, 0x81, 0x04, 0x83, 0xDD, 0x27, 0xD9, 0xD9, 0xDD, 0x00, 0x1B, 0xB1, 0x40, 0x00, 0x15, 0x81, 0xA6, 0x19, 0x00, 0x81, 0x40, 0x88, 0x20, 0xD8, 0xE6, 0xF1, 0x90, 0xB8, 0xD9, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x40, 0xA9, 0x17, 0x00, 0x11, 0x90, 0x3D, 0x00, 0x06, 0x98, 0x5A, 0x64, 0x67, 0xC2, 0x63, 0x66, 0xC2, 0x63, 0x64, 0xC1, 0x40, 0x42, 0x00, 0x81, 0x32, 0x83, 0xC6, 0x46, 0x00, 0x7E, 0x81, 0xB4, 0x4E, 0x00, 0x6F, 0x86, 0x66, 0x00, 0x09, 0xB8, 0x1A, 0x00, 0x24, 0x91, 0x2C, 0x00, 0x15, 0x83, 0x9F, 0x52, 0x00, 0x81, 0x04, 0x83, 0xA7, 0x21, 0x00, 0x06, 0x83, 0xB9, 0x03, 0x00, 0x06, 0x81, 0x49, 0xA6, 0xA7, 0xB0, 0x00, 0x09, 0x82, 0xB1, 0x14, 0x00, 0x06, 0x93, 0x10, 0x00, 0x06, 0x83, 0xC9, 0x49, 0x00, 0x0C, 0x82, 0xB1, 0x2C, 0x00, 0x06, 0x81, 0x28, 0x00, 0x81, 0x40, 0x88, 0x20, 0xA8, 0xC8, 0xE1, 0x00, 0x22, 0x90, 0x3D, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x40, 0xA9, 0x17, 0x00, 0x0A, 0x90, 0x3D, 0x62, 0x64, 0xC1, 0x40, 0x41, 0x00, 0x82, 0x2D, 0x88, 0x20, 0x00, 0x7B, 0x81, 0xBD, 0x60, 0x00, 0x24, 0x81, 0xA6, 0x79, 0x00, 0x0C, 0x90, 0x3A, 0x00, 0x06, 0xD9, 0x3E, 0x00, 0x06, 0x83, 0xE9, 0x5D, 0x00, 0x09, 0x88, 0x35, 0x00, 0x78, 0x83, 0xA7, 0x21, 0x00, 0x30, 0x82, 0xA8, 0x35, 0x00, 0x06, 0xA9, 0x2C, 0x00, 0x81, 0x3D, 0x88, 0x20, 0xD3, 0xE3, 0x00, 0x37, 0xB9, 0x54, 0x00, 0x4C, 0x81, 0x8C, 0x02, 0x00, 0x08, 0x90, 0x3D, 0x00, 0x2D, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x62, 0x63, 0xC1, 0x3F, 0x41, 0x00, 0x79, 0x83, 0x9D, 0x02, 0x00, 0x82, 0x2C, 0x85, 0x9C, 0x20, 0x00, 0x24, 0x81, 0xC8, 0x65, 0x00, 0x09, 0x86, 0x4E, 0x00, 0x12, 0x90, 0x28, 0x00, 0x0C, 0x81, 0xA0, 0x07, 0x00, 0x75, 0x81, 0xAF, 0x61, 0x00, 0x24, 0x85, 0xDE, 0x20, 0x00, 0x0C, 0x0C, 0x00, 0x06, 0x81, 0xB5, 0x4C, 0x00, 0x81, 0x3D, 0x88, 0x20, 0x9C, 0xC0, 0xDD, 0x00, 0x45, 0xE2, 0x6B, 0x00, 0x4D, 0x81, 0x8C, 0x02, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x21, 0xA9, 0x17, 0x00, 0x06, 0x90, 0x3D, 0x62, 0x62, 0xC1, 0x3C, 0x3E, 0x00, 0x83, 0x1C, 0x84, 0xA2, 0x0F, 0x00, 0x09, 0x86, 0x21, 0x00, 0x24, 0x82, 0xA0, 0x63, 0x00, 0x09, 0x81, 0x9F, 0x66, 0x00, 0x15, 0xD9, 0x2C, 0x00, 0x0C, 0x81, 0xC6, 0x48, 0x00, 0x81, 0x28, 0xB2, 0x56, 0x00, 0x81, 0x3A, 0x88, 0x20, 0xCD, 0xDF, 0xEE, 0x00, 0x0A, 0x90, 0x3D, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x20, 0x81, 0xEE, 0x6D, 0x00, 0x3D, 0xB9, 0x54, 0x00, 0x11, 0x98, 0x5A, 0x62, 0x63, 0xC1, 0x61, 0x61, 0x00, 0x76, 0x83, 0xA5, 0x1F, 0x00, 0x82, 0x2C, 0xB2, 0x2F, 0x00, 0x2A, 0x82, 0x93, 0x0B, 0x00, 0x21, 0x81, 0xD0, 0x3D, 0x00, 0x09, 0x81, 0xC9, 0x33, 0x00, 0x81, 0x28, 0xF4, 0x7A, 0x00, 0x81, 0x3A, 0x88, 0x20, 0x00, 0x1F, 0x90, 0x3D, 0x00, 0x56, 0x81, 0xEE, 0x6D, 0x00, 0x3C, 0xA9, 0x17, 0x00, 0x12, 0x90, 0x3D, 0x61, 0x62, 0xC0, 0x56, 0x56, 0xA3, 0x00, 0x83, 0x24, 0x84, 0x90, 0x27, 0x00, 0x24, 0x81, 0xD8, 0x30, 0x00, 0x27, 0x82, 0xA9, 0x2D, 0x00, 0x7B, 0x81, 0xF7, 0x40, 0x5A, 0x5C, 0x6D, 0x9A, 0x9B, 0xA5, 0xC0, 0xC0, 0xC7, 0x00, 0x09, 0xFB, 0x5A, 0x00, 0x21, 0x89, 0x75, 0x00, 0x81, 0x37, 0x88, 0x20, 0xCE, 0xDF, 0xEE, 0x00, 0x30, 0xB9, 0x54, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x06, 0x90, 0x3D, 0x47, 0x49, 0x7E, 0x00, 0x82, 0x38, 0xDA, 0x54, 0x00, 0x09, 0x83, 0xEC, 0x39, 0x00, 0x06, 0xA6, 0x4D, 0x00, 0x57, 0x83, 0x93, 0x07, 0x00, 0x2A, 0x81, 0xB7, 0x3C, 0x00, 0x27, 0x82, 0xB0, 0x79, 0x00, 0x51, 0x82, 0x80, 0x31, 0x00, 0x39, 0x81, 0x9C, 0x57, 0x00, 0x24, 0x82, 0xF4, 0x6F, 0x00, 0x81, 0x37, 0x88, 0x20, 0x9C, 0xC0, 0xDD, 0x00, 0x48, 0xE2, 0x6B, 0x00, 0x43, 0x81, 0x8C, 0x02, 0x00, 0x23, 0xE2, 0x6B, 0x00, 0x12, 0xA9, 0x17, 0x61, 0x62, 0xC0, 0x5E, 0x5E, 0xB9, 0x00, 0x82, 0x35, 0xE3, 0x00, 0x00, 0x18, 0x82, 0xDF, 0x5D, 0x00, 0x51, 0xB8, 0x3E, 0x00, 0x2D, 0x82, 0x98, 0x40, 0x00, 0x09, 0x87, 0x01, 0x00, 0x27, 0x88, 0x47, 0x00, 0x72, 0xFB, 0x57, 0x00, 0x06, 0x85, 0xD9, 0x3F, 0x00, 0x0C, 0xB9, 0x5A, 0x00, 0x21, 0x81, 0xE8, 0x58, 0x00, 0x81, 0x34, 0x88, 0x20, 0xCE, 0xE0, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x78, 0x81, 0xEE, 0x6D, 0x00, 0x2D, 0xB9, 0x54, 0x00, 0x18, 0xA9, 0x17, 0x61, 0x61, 0xC0, 0x4A, 0x4B, 0x86, 0x00, 0x82, 0x35, 0xE2, 0x74, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x0C, 0xCA, 0x23, 0x00, 0x09, 0xE3, 0x09, 0x00, 0x4E, 0x84, 0xD9, 0x46, 0x00, 0x2D, 0x82, 0xA9, 0x00, 0x00, 0x27, 0x82, 0x80, 0x07, 0x00, 0x09, 0x81, 0xF7, 0x46, 0x00, 0x66, 0xC2, 0x09, 0x00, 0x09, 0x83, 0xCE, 0x03, 0x00, 0x18, 0xAA, 0x33, 0x00, 0x06, 0xA2, 0x61, 0x00, 0x18, 0xAA, 0x33, 0x00, 0x81, 0x34, 0x88, 0x20, 0xA8, 0xC8, 0xE1, 0x00, 0x19, 0x90, 0x3D, 0x00, 0x65, 0x81, 0xEE, 0x6D, 0x00, 0x36, 0xE2, 0x6B, 0x00, 0x0D, 0x90, 0x3D, 0x61, 0x00, 0x82, 0x39, 0x90, 0x3D, 0x00, 0x06, 0x97, 0x20, 0x00, 0x15, 0x85, 0x6E, 0x00, 0x06, 0x86, 0x7B, 0x00, 0x4B, 0x81, 0xCF, 0x48, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x09, 0x90, 0x6A, 0x00, 0x21, 0xB1, 0x67, 0x00, 0x6F, 0x82, 0xB9, 0x40, 0x00, 0x18, 0x83, 0xDE, 0x31, 0x00, 0x27, 0x82, 0x38, 0x00, 0x81, 0x31, 0x88, 0x20, 0xDB, 0xE8, 0xF3, 0x00, 0x31, 0xB9, 0x54, 0x00, 0x53, 0x81, 0xEE, 0x6D, 0x00, 0x3C, 0xA9, 0x17, 0x00, 0x82, 0x3B, 0x90, 0x3D, 0x00, 0x06, 0xE8, 0x47, 0x00, 0x1B, 0x81, 0xFE, 0x23, 0x00, 0x06, 0xC0, 0x64, 0x00, 0x48, 0xA1, 0x09, 0x00, 0x2A, 0x87, 0x4C, 0x00, 0x2A, 0x83, 0xD4, 0x66, 0x00, 0x6C, 0x88, 0x20, 0x00, 0x2A, 0x83, 0xE6, 0x36, 0x00, 0x18, 0x82, 0xE2, 0x7E, 0x00, 0x81, 0x31, 0x88, 0x20, 0xAF, 0xCC, 0xE3, 0x00, 0x43, 0xE2, 0x6B, 0x00, 0x4B, 0x81, 0x8C, 0x02, 0x78, 0x00, 0x34, 0xA9, 0x17, 0x00, 0x72, 0x90, 0x3D, 0x00, 0x09, 0x81, 0xE4, 0x18, 0x00, 0x81, 0x3D, 0x84, 0xAE, 0x03, 0x00, 0x06, 0x85, 0x2F, 0x00, 0x1B, 0x81, 0x3A, 0x00, 0x06, 0x9F, 0x5E, 0x00, 0x48, 0x86, 0x7B, 0x00, 0x2A, 0x87, 0x4C, 0x00, 0x2A, 0x82, 0xDA, 0x16, 0x00, 0x6C, 0x88, 0x20, 0x00, 0x1E, 0x81, 0x83, 0x74, 0x00, 0x12, 0xBA, 0x79, 0x00, 0x12, 0x82, 0x59, 0x00, 0x81, 0x2E, 0x88, 0x20, 0xE9, 0xF1, 0xF8, 0x00, 0x50, 0x81, 0x8C, 0x02, 0x00, 0x13, 0x82, 0xD1, 0x58, 0x00, 0x42, 0xE2, 0x6B, 0x00, 0x1E, 0xA9, 0x17, 0x61, 0x61, 0xC0, 0x50, 0x50, 0x94, 0x00, 0x6C, 0x83, 0xCB, 0x24, 0x00, 0x18, 0xE0, 0x12, 0x00, 0x82, 0x29, 0x88, 0x20, 0x00, 0x21, 0x81, 0xFF, 0x18, 0x00, 0x27, 0xA9, 0x1D, 0x00, 0x6F, 0x82, 0xDA, 0x40, 0x00, 0x18, 0xEA, 0x76, 0x00, 0x18, 0x93, 0x19, 0x00, 0x12, 0xBA, 0x76, 0x00, 0x81, 0x2E, 0x88, 0x20, 0xBC, 0xD4, 0xE8, 0x00, 0x81, 0x0A, 0x81, 0xEE, 0x6D, 0x00, 0x34, 0xB9, 0x54, 0x00, 0x05, 0x98, 0x5A, 0x60, 0x60, 0xC0, 0x3A, 0x3B, 0x00, 0x58, 0x81, 0xE7, 0x06, 0x00, 0x0C, 0x84, 0xF5, 0x56, 0x00, 0x21, 0x83, 0x8F, 0x42, 0x00, 0x81, 0x37, 0x98, 0x60, 0x00, 0x1B, 0xA0, 0x62, 0x00, 0x06, 0xA6, 0x6E, 0x00, 0x48, 0xA9, 0x23, 0x00, 0x09, 0x82, 0xC3, 0x4D, 0x00, 0x21, 0x92, 0x6C, 0x00, 0x2A, 0x82, 0xA9, 0x24, 0x00, 0x6C, 0xB1, 0x40, 0x00, 0x2D, 0x81, 0x96, 0x42, 0x00, 0x81, 0x43, 0x81, 0x8C, 0x20, 0x95, 0xBA, 0xDA, 0x00, 0x81, 0x0D, 0x81, 0xEE, 0x6D, 0x00, 0x31, 0xA9, 0x17, 0x00, 0x62, 0x90, 0x3D, 0x00, 0x18, 0x84, 0xFD, 0x70, 0x00, 0x42, 0x88, 0x20, 0x00, 0x81, 0x07, 0x81, 0xB4, 0x1E, 0x00, 0x06, 0x92, 0x0F, 0x00, 0x15, 0x96, 0x34, 0x00, 0x06, 0xF2, 0x3C, 0x00, 0x4E, 0x81, 0x9C, 0x54, 0x00, 0x06, 0xA7, 0x60, 0x00, 0x1E, 0xC9, 0x4F, 0x00, 0x36, 0xDB, 0x04, 0x00, 0x82, 0x50, 0x88, 0x20, 0xD0, 0xE1, 0xEF, 0x00, 0x3E, 0xE2, 0x6B, 0x00, 0x52, 0x81, 0xEE, 0x6D, 0x00, 0x33, 0xA9, 0x17, 0x00, 0x5D, 0x90, 0x3D, 0x8D, 0x8E, 0x9A, 0x00, 0x2D, 0x83, 0x9F, 0x76, 0x00, 0x30, 0xEF, 0x7E, 0x00, 0x81, 0x04, 0x81, 0xFF, 0x63, 0x00, 0x09, 0x81, 0x81, 0x2D, 0x00, 0x0F, 0x88, 0x23, 0x00, 0x06, 0xEA, 0x01, 0x00, 0x51, 0xC2, 0x03, 0x00, 0x09, 0x8A, 0x6D, 0x00, 0x1B, 0x9F, 0x46, 0x00, 0x09, 0xDB, 0x04, 0x00, 0x24, 0x82, 0x98, 0x1F, 0x00, 0x4B, 0x82, 0xBA, 0x0E, 0x00, 0x27, 0x81, 0x83, 0x71, 0x00, 0x2A, 0x82, 0xA2, 0x41, 0x00, 0x81, 0x3D, 0x82, 0xA0, 0x60, 0xA8, 0xC7, 0xE1, 0x00, 0x51, 0xE2, 0x6B, 0x00, 0x46, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x20, 0xA9, 0x17, 0x60, 0x60, 0x00, 0x58, 0x90, 0x3D, 0x00, 0x1B, 0x83, 0x97, 0x59, 0xF2, 0xF2, 0xF4, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x81, 0xF7, 0x40, 0x00, 0x06, 0xA9, 0x23, 0x00, 0x30, 0x88, 0x20, 0x00, 0x0C, 0x91, 0x11, 0x00, 0x72, 0xA9, 0x56, 0x00, 0x12, 0x84, 0xD9, 0x49, 0x00, 0x09, 0x82, 0xD9, 0x03, 0x00, 0x06, 0x81, 0x93, 0x1B, 0x00, 0x06, 0x81, 0x93, 0x27, 0x00, 0x09, 0xD9, 0x38, 0x00, 0x4E, 0x81, 0x22, 0x00, 0x09, 0xC8, 0x5D, 0x00, 0x18, 0x57, 0x00, 0x09, 0x81, 0x83, 0x71, 0x00, 0x24, 0x87, 0x0A, 0x00, 0x09, 0x82, 0xA9, 0x48, 0x00, 0x66, 0x85, 0xA3, 0x2A, 0x00, 0x06, 0x83, 0x39, 0x00, 0x24, 0x93, 0x79, 0x00, 0x18, 0x84, 0xB9, 0x20, 0x00, 0x81, 0x28, 0x88, 0x20, 0xEB, 0xF2, 0xF8, 0x00, 0x61, 0x81, 0xEE, 0x6D, 0x8B, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x0F, 0x98, 0x5A, 0x60, 0x5F, 0xC0, 0x39, 0x00, 0x53, 0x90, 0x3D, 0x00, 0x18, 0x83, 0x8F, 0x3C, 0xCC, 0xCD, 0xD2, 0x00, 0x12, 0x8D, 0x52, 0x00, 0x30, 0x88, 0x20, 0x00, 0x12, 0x84, 0x22, 0x00, 0x6F, 0x82, 0xA6, 0x45, 0x00, 0x33, 0x81, 0xF9, 0x12, 0x00, 0x57, 0x82, 0xF6, 0x11, 0x00, 0x15, 0xB9, 0x3C, 0x00, 0x09, 0x8B, 0x17, 0x00, 0x24, 0x92, 0x5D, 0x00, 0x2D, 0x90, 0x6A, 0x00, 0x48, 0xD4, 0x00, 0x00, 0x21, 0x83, 0xA4, 0x54, 0x00, 0x06, 0x82, 0xC5, 0x3A, 0x00, 0x15, 0x9B, 0x36, 0x00, 0x81, 0x28, 0x88, 0x20, 0xBD, 0xD4, 0xE8, 0x00, 0x72, 0x81, 0xEE, 0x6D, 0x73, 0x82, 0xCA, 0x00, 0x46, 0xA9, 0x17, 0x00, 0x08, 0x90, 0x3D, 0x4F, 0x00, 0x53, 0x90, 0x3D, 0x00, 0x15, 0x88, 0x1D, 0x00, 0x1B, 0x85, 0x91, 0x24, 0x00, 0x33, 0x90, 0x40, 0x00, 0x0F, 0x83, 0xE4, 0x58, 0x00, 0x6F, 0x85, 0xAA, 0x6A, 0x00, 0x33, 0x84, 0xEA, 0x09, 0x00, 0x5A, 0x82, 0xBC, 0x28, 0x00, 0x0C, 0xE3, 0x66, 0x00, 0x0C, 0x82, 0xA8, 0x5F, 0x00, 0x27, 0xAA, 0x15, 0x00, 0x2A, 0x90, 0x6A, 0x00, 0x4E, 0xF5, 0x00, 0x00, 0x1B, 0xE2, 0x65, 0x00, 0x09, 0x84, 0xA7, 0x7A, 0x00, 0x15, 0x89, 0x7E, 0x00, 0x81, 0x28, 0x88, 0x20, 0x9B, 0xBE, 0x00, 0x73, 0x82, 0xD1, 0x58, 0x00, 0x18, 0x90, 0x3D, 0x00, 0x36, 0xA9, 0x17, 0x60, 0x5F, 0xC0, 0x3F, 0x40, 0x00, 0x4F, 0x81, 0x8C, 0x0B, 0x00, 0x15, 0x88, 0x1D, 0x00, 0x1E, 0x86, 0x21, 0x00, 0x33, 0x88, 0x20, 0x00, 0x15, 0x84, 0x9D, 0x07, 0x00, 0x81, 0x73, 0x84, 0xD0, 0x49, 0x00, 0x1B, 0x85, 0x2F, 0x00, 0x24, 0x82, 0x9A, 0x60, 0x00, 0x09, 0x82, 0x44, 0x00, 0x6C, 0x85, 0xBC, 0x07, 0x00, 0x09, 0x84, 0x22, 0x00, 0x12, 0x84, 0xE2, 0x46, 0x00, 0x06, 0x81, 0xC8, 0x38, 0x00, 0x09, 0xDD, 0x2D, 0x00, 0x81, 0x3A, 0xE3, 0x00, 0xDF, 0xEA, 0xF4, 0x00, 0x4F, 0xE2, 0x6B, 0x00, 0x4B, 0x81, 0xEE, 0x6D, 0x71, 0x00, 0x28, 0xA9, 0x17, 0x55, 0x55, 0xA2, 0x00, 0x60, 0x84, 0x9F, 0x54, 0x00, 0x24, 0xA7, 0x1E, 0x00, 0x36, 0x88, 0x20, 0x00, 0x7B, 0x84, 0x90, 0x75, 0x00, 0x81, 0x10, 0x81, 0x84, 0x09, 0x00, 0x12, 0x85, 0x2C, 0x00, 0x24, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xA5, 0x18, 0x00, 0x72, 0x81, 0xA6, 0x40, 0x00, 0x0C, 0x82, 0xBA, 0x47, 0x00, 0x12, 0x82, 0x94, 0x48, 0x00, 0x1B, 0x81, 0x40, 0x00, 0x81, 0x25, 0x88, 0x20, 0xB6, 0xCF, 0xE6, 0x00, 0x5B, 0x81, 0xEE, 0x6D, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x44, 0x81, 0x8C, 0x02, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x0E, 0x98, 0x5A, 0x00, 0x54, 0x90, 0x3D, 0x00, 0x0F, 0x84, 0x97, 0x2E, 0x00, 0x27, 0xAF, 0x3B, 0x00, 0x39, 0x88, 0x20, 0x00, 0x0C, 0x83, 0xE4, 0x67, 0x00, 0x81, 0x76, 0x81, 0xD5, 0x1B, 0x67, 0x68, 0x78, 0x00, 0x0F, 0x8B, 0x11, 0xC0, 0xC0, 0xC7, 0x00, 0x27, 0x8A, 0x28, 0x00, 0x09, 0x91, 0x02, 0x00, 0x78, 0xB4, 0x04, 0x00, 0x12, 0x81, 0x3D, 0x00, 0x24, 0x81, 0xE1, 0x06, 0x00, 0x81, 0x25, 0x88, 0x20, 0x94, 0xB9, 0x00, 0x14, 0x82, 0xFA, 0x6F, 0x00, 0x81, 0x0C, 0x81, 0xEE, 0x6D, 0x00, 0x21, 0x90, 0x3D, 0x54, 0x54, 0x00, 0x4F, 0x90, 0x3D, 0x00, 0x0F, 0x82, 0xEA, 0x0E, 0x00, 0x2A, 0xB7, 0x58, 0x00, 0x39, 0x88, 0x20, 0x00, 0x12, 0x98, 0x66, 0x00, 0x82, 0x2C, 0x85, 0xDA, 0x4F, 0x00, 0x06, 0x81, 0xBD, 0x75, 0x00, 0x81, 0x04, 0x81, 0x9C, 0x5A, 0x5A, 0x5C, 0x6D, 0x00, 0x2A, 0x83, 0xE6, 0x4B, 0x00, 0x81, 0x22, 0x88, 0x20, 0xD8, 0xE6, 0xF1, 0x00, 0x81, 0x25, 0x81, 0xEE, 0x6D, 0x00, 0x1B, 0xA9, 0x17, 0x00, 0x54, 0x90, 0x3D, 0x00, 0x0F, 0x9E, 0x12, 0x00, 0x2A, 0x81, 0x99, 0x30, 0x00, 0x3C, 0x88, 0x20, 0x00, 0x0F, 0x83, 0xA5, 0x5E, 0x00, 0x82, 0x02, 0x82, 0xCA, 0x0F, 0x00, 0x81, 0x61, 0x82, 0xA2, 0x1D, 0x00, 0x81, 0x22, 0x88, 0x20, 0xB6, 0xCF, 0xE6, 0x00, 0x81, 0x14, 0x81, 0xEE, 0x6D, 0x72, 0x00, 0x2B, 0xA9, 0x17, 0x00, 0x54, 0x90, 0x3D, 0x00, 0x39, 0xA8, 0x2E, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x0C, 0x90, 0x43, 0x00, 0x81, 0x67, 0x84, 0x87, 0x5D, 0x00, 0x82, 0x05, 0x85, 0xE8, 0x3F, 0x00, 0x81, 0x19, 0x88, 0x20, 0x9B, 0xBC, 0xDC, 0x00, 0x81, 0x27, 0x81, 0xEE, 0x6D, 0xC3, 0x00, 0x15, 0x98, 0x5A, 0x5F, 0x5F, 0xBF, 0x41, 0x43, 0x6F, 0x00, 0x5A, 0x90, 0x3D, 0x00, 0x30, 0x95, 0x33, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x0F, 0x83, 0xA4, 0x60, 0x00, 0x83, 0x3F, 0x85, 0x94, 0x1E, 0x00, 0x81, 0x40, 0x83, 0x9C, 0x40, 0xE7, 0xEF, 0xF7, 0x00, 0x19, 0x90, 0x3D, 0x00, 0x81, 0x12, 0x81, 0xEE, 0x6D, 0x00, 0x15, 0x90, 0x3D, 0x5A, 0x59, 0x00, 0x4F, 0x84, 0xC9, 0x7E, 0x00, 0x0F, 0x81, 0xD3, 0x22, 0x00, 0x30, 0xBF, 0x6F, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x0F, 0xB2, 0x35, 0x00, 0x83, 0x63, 0x85, 0xF3, 0x32, 0x00, 0x81, 0x1C, 0x83, 0xAD, 0x00, 0xC4, 0xD8, 0xEB, 0x00, 0x7D, 0x81, 0xEE, 0x6D, 0xC8, 0x00, 0x3F, 0xA9, 0x17, 0x5F, 0x5F, 0xBF, 0x44, 0x45, 0x00, 0x4F, 0x85, 0xDF, 0x42, 0x00, 0x0F, 0x83, 0x83, 0x57, 0x00, 0x30, 0x9D, 0x53, 0x00, 0x42, 0x88, 0x20, 0x00, 0x81, 0x6A, 0x83, 0xC5, 0x60, 0x00, 0x82, 0x0E, 0x81, 0xBF, 0x62, 0x00, 0x81, 0x13, 0x88, 0x20, 0xA1, 0xC0, 0xDE, 0x00, 0x3F, 0xB9, 0x54, 0x00, 0x4F, 0x81, 0xEE, 0x6D, 0x73, 0x00, 0x2E, 0xA9, 0x17, 0x00, 0x51, 0x90, 0x3D, 0x00, 0x0F, 0x98, 0x5D, 0x00, 0x33, 0xC9, 0x28, 0x00, 0x42, 0x88, 0x20, 0x00, 0x81, 0x07, 0x83, 0xDF, 0x44, 0x00, 0x82, 0x6B, 0x82, 0xD2, 0x53, 0x00, 0x81, 0x16, 0x88, 0x20, 0xF6, 0xF9, 0xFC, 0x00, 0x81, 0x22, 0x81, 0xEE, 0x6D, 0x66, 0x00, 0x1A, 0x98, 0x5A, 0x5F, 0x5E, 0x00, 0x52, 0x90, 0x3D, 0x00, 0x0F, 0xB0, 0x42, 0x00, 0x33, 0x81, 0xCA, 0x67, 0x00, 0x42, 0x88, 0x20, 0x00, 0x81, 0x6A, 0x83, 0xE6, 0x60, 0x00, 0x83, 0x09, 0x85, 0xD8, 0x2C, 0x00, 0x15, 0x88, 0x20, 0xDA, 0xE6, 0xF2, 0x00, 0x81, 0x31, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x5F, 0x5F, 0xBF, 0x00, 0x54, 0x90, 0x3D, 0x00, 0x0F, 0xA8, 0x1F, 0x00, 0x33, 0x87, 0x1C, 0x00, 0x51, 0x88, 0x20, 0x00, 0x82, 0x2C, 0xC2, 0x06, 0x00, 0x82, 0x4A, 0x82, 0xD2, 0x26, 0xFE, 0xFF, 0xFF, 0xBD, 0xD3, 0xE8, 0x00, 0x81, 0x31, 0x81, 0xEE, 0x6D, 0x00, 0x60, 0x90, 0x3D, 0x00, 0x42, 0x83, 0xED, 0x7C, 0x00, 0x45, 0x88, 0x20, 0x00, 0x81, 0x6A, 0x84, 0x90, 0x00, 0x00, 0x21, 0x84, 0xF9, 0x78, 0xC0, 0xC0, 0xC7, 0x00, 0x12, 0x83, 0x8F, 0x00, 0x00, 0x81, 0x04, 0x84, 0xEA, 0x5D, 0x41, 0x43, 0x56, 0x00, 0x18, 0x84, 0xB0, 0x68, 0x00, 0x33, 0x84, 0xB1, 0x00, 0x00, 0x81, 0x13, 0x83, 0xFF, 0x40, 0x99, 0xBA, 0xDC, 0x00, 0x3A, 0xB9, 0x54, 0x00, 0x77, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x5C, 0x5B, 0xB8, 0x00, 0x81, 0x16, 0x84, 0x87, 0x60, 0x00, 0x82, 0x44, 0x88, 0x20, 0x5A, 0x5C, 0x6D, 0x00, 0x27, 0x86, 0x30, 0x00, 0x7B, 0x82, 0xBA, 0x47, 0x00, 0x33, 0x8F, 0x75, 0x00, 0x1B, 0xB6, 0x0C, 0x00, 0x81, 0x10, 0x84, 0x90, 0x00, 0xF7, 0xFA, 0xFC, 0x00, 0x81, 0x16, 0x82, 0xD1, 0x58, 0x00, 0x24, 0xA9, 0x17, 0x5F, 0x5E, 0xBF, 0x49, 0x49, 0x85, 0x00, 0x60, 0x82, 0x83, 0x46, 0x00, 0x36, 0xF2, 0x45, 0x00, 0x82, 0x3E, 0x88, 0x20, 0x00, 0x09, 0x81, 0xCC, 0x51, 0x00, 0x2D, 0x85, 0x4D, 0x00, 0x75, 0xBC, 0x06, 0x00, 0x06, 0x81, 0xDE, 0x54, 0x00, 0x0F, 0x81, 0xFF, 0x36, 0x00, 0x0C, 0x82, 0xA3, 0x1B, 0x00, 0x0C, 0xEB, 0x26, 0x00, 0x06, 0xEB, 0x38, 0x00, 0x1E, 0xA5, 0x4F, 0x00, 0x81, 0x0D, 0x88, 0x23, 0xDA, 0xE6, 0xF2, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x81, 0x22, 0x81, 0xEE, 0x6D, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x05, 0x88, 0x1D, 0x5C, 0x5B, 0xB8, 0x37, 0x38, 0x00, 0x55, 0x81, 0xBD, 0x3F, 0x00, 0x0C, 0x87, 0x5E, 0x00, 0x36, 0x81, 0x81, 0x69, 0x00, 0x82, 0x3B, 0x88, 0x20, 0x00, 0x12, 0x83, 0x8E, 0x5F, 0x00, 0x27, 0x83, 0xA4, 0x60, 0x00, 0x42, 0x84, 0xAF, 0x79, 0x00, 0x4B, 0x81, 0x96, 0x0C, 0x00, 0x0F, 0x81, 0x84, 0x0C, 0x00, 0x09, 0x83, 0xB0, 0x63, 0x00, 0x24, 0x84, 0x4F, 0x00, 0x15, 0x85, 0xFF, 0x5F, 0x00, 0x75, 0x88, 0x20, 0xBD, 0xD2, 0xE8, 0x00, 0x1F, 0x90, 0x3D, 0x00, 0x4D, 0x81, 0xEE, 0x6D, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x41, 0xA9, 0x17, 0x00, 0x5D, 0x90, 0x3D, 0x00, 0x81, 0x0A, 0x88, 0x20, 0x00, 0x0C, 0x85, 0x7D, 0x00, 0x81, 0x67, 0x88, 0x20, 0x00, 0x0F, 0x85, 0xC8, 0x28, 0x00, 0x30, 0x83, 0xB5, 0x20, 0x00, 0x81, 0x01, 0x88, 0x23, 0x00, 0x06, 0xDA, 0x2A, 0x00, 0x18, 0x94, 0x74, 0x00, 0x06, 0x81, 0x28, 0x00, 0x27, 0x9A, 0x0B, 0x00, 0x81, 0x04, 0x84, 0xC1, 0x40, 0xA7, 0xC2, 0xE0, 0x00, 0x81, 0x2E, 0x81, 0xEE, 0x6D, 0x00, 0x0A, 0x90, 0x3D, 0x5A, 0x00, 0x58, 0x90, 0x3D, 0x00, 0x0F, 0x83, 0x1B, 0x00, 0x36, 0x95, 0x36, 0x00, 0x82, 0x35, 0xB1, 0x40, 0x00, 0x0C, 0x96, 0x5B, 0x00, 0x3C, 0x83, 0xC5, 0x60, 0x00, 0x7B, 0x88, 0x23, 0x00, 0x06, 0x83, 0x78, 0x00, 0x18, 0x88, 0x02, 0x00, 0x18, 0x83, 0xCE, 0x00, 0x00, 0x81, 0x19, 0x84, 0xD2, 0x00, 0x00, 0x45, 0xE2, 0x6B, 0x00, 0x6C, 0x81, 0xEE, 0x6D, 0x00, 0x06, 0xA9, 0x17, 0x5F, 0x5D, 0x00, 0x5B, 0x90, 0x3D, 0x00, 0x45, 0xD1, 0x3C, 0x00, 0x42, 0x88, 0x20, 0x00, 0x42, 0xBA, 0x64, 0x00, 0x81, 0x3A, 0x84, 0xC9, 0x66, 0x00, 0x3F, 0x83, 0xD6, 0x20, 0x00, 0x7B, 0xDD, 0x12, 0x00, 0x36, 0x82, 0xD2, 0x20, 0x00, 0x81, 0x16, 0x84, 0xE2, 0x40, 0xE9, 0xF0, 0xF7, 0x00, 0x54, 0x81, 0xEE, 0x6D, 0x76, 0x88, 0x00, 0x58, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x98, 0x5A, 0x00, 0x5D, 0x90, 0x3D, 0x00, 0x0F, 0xAD, 0x15, 0x00, 0x78, 0x88, 0x20, 0x00, 0x81, 0x70, 0xD2, 0x40, 0x00, 0x1B, 0x82, 0xA8, 0x56, 0x00, 0x36, 0x88, 0x23, 0x00, 0x75, 0x82, 0xB9, 0x43, 0x00, 0x51, 0x88, 0x20, 0x00, 0x7B, 0x84, 0xD2, 0x0F, 0xD3, 0xE0, 0xF0, 0x00, 0x81, 0x2E, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x4C, 0x4B, 0x00, 0x58, 0x84, 0xD1, 0x7A, 0x00, 0x15, 0xD5, 0x6D, 0x00, 0x75, 0x88, 0x20, 0x00, 0x0C, 0x42, 0x00, 0x81, 0x4C, 0x84, 0xF8, 0x6E, 0x00, 0x21, 0xAB, 0x0D, 0x00, 0x48, 0x83, 0xF7, 0x20, 0x00, 0x75, 0xE5, 0x35, 0x00, 0x06, 0xB2, 0x77, 0x00, 0x18, 0x81, 0x43, 0x00, 0x06, 0xBE, 0x38, 0x00, 0x42, 0x9D, 0x32, 0x00, 0x66, 0x88, 0x20, 0xC4, 0xD6, 0xEA, 0x00, 0x79, 0x81, 0xEE, 0x6D, 0x77, 0x00, 0x3A, 0xA9, 0x17, 0x5E, 0x5C, 0xBF, 0x00, 0x54, 0x81, 0xBD, 0x3F, 0x00, 0x1B, 0x9F, 0x7C, 0x00, 0x33, 0x8D, 0x0A, 0x00, 0x42, 0x88, 0x20, 0x00, 0x0F, 0x82, 0xBF, 0x43, 0x00, 0x81, 0x67, 0xE0, 0x7E, 0x00, 0x4B, 0x84, 0x87, 0x60, 0x00, 0x75, 0x9B, 0x15, 0x00, 0x06, 0x92, 0x06, 0x00, 0x15, 0xA2, 0x01, 0x00, 0x09, 0xA2, 0x5E, 0x00, 0x39, 0x91, 0x59, 0x00, 0x6F, 0xA1, 0x0F, 0xA6, 0xC0, 0xE0, 0x00, 0x81, 0x0A, 0x81, 0xEE, 0x6D, 0x68, 0x6E, 0x00, 0x25, 0xA9, 0x17, 0x5F, 0x5D, 0xBF, 0x4E, 0x4E, 0x00, 0x64, 0x81, 0xEE, 0x76, 0x00, 0x0C, 0x87, 0x1F, 0x00, 0x33, 0x83, 0xCD, 0x17, 0x00, 0x4E, 0x81, 0x84, 0x00, 0x00, 0x81, 0x61, 0x83, 0xA3, 0x62, 0x00, 0x09, 0xC1, 0x6E, 0x00, 0x4E, 0x84, 0x98, 0x20, 0x00, 0x75, 0x83, 0xD0, 0x50, 0x00, 0x09, 0x82, 0xA1, 0x5B, 0x00, 0x09, 0xD3, 0x5C, 0x00, 0x06, 0x81, 0xF3, 0x42, 0x00, 0x06, 0xE7, 0x52, 0x00, 0x3F, 0x8B, 0x6B, 0x00, 0x6C, 0xA1, 0x0F, 0x90, 0xB0, 0xD8, 0x00, 0x51, 0xE2, 0x6B, 0x00, 0x5A, 0x81, 0xEE, 0x6D, 0x00, 0x06, 0x98, 0x5A, 0x00, 0x66, 0x90, 0x3D, 0x00, 0x42, 0x97, 0x5F, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x0F, 0x81, 0xAE, 0x15, 0x00, 0x81, 0x61, 0x82, 0xF1, 0x7E, 0x00, 0x09, 0x81, 0xBC, 0x1D, 0x00, 0x4E, 0x84, 0xA8, 0x60, 0x00, 0x75, 0x98, 0x63, 0x00, 0x1B, 0xA0, 0x2F, 0x00, 0x45, 0x94, 0x08, 0x00, 0x69, 0xA1, 0x0F, 0x00, 0x81, 0x2B, 0x81, 0xEE, 0x6D, 0x00, 0x6F, 0x90, 0x3D, 0x00, 0x12, 0xA1, 0x03, 0x00, 0x30, 0x8D, 0x58, 0x00, 0x4B, 0x81, 0xA5, 0x00, 0x00, 0x81, 0x64, 0x81, 0xC6, 0x06, 0x00, 0x57, 0x84, 0xB9, 0x20, 0x00, 0x7B, 0xAB, 0x58, 0x00, 0x06, 0x81, 0xB5, 0x49, 0x00, 0x09, 0x81, 0xCF, 0x2A, 0x00, 0x2A, 0x81, 0xB7, 0x03, 0x00, 0x81, 0x07, 0xA1, 0x0F, 0xE1, 0xEA, 0xF5, 0x00, 0x74, 0x81, 0xEE, 0x6D, 0x00, 0x05, 0x90, 0x3D, 0x00, 0x38, 0xA9, 0x17, 0x00, 0x69, 0x90, 0x3D, 0x00, 0x12, 0xC9, 0x1F, 0x00, 0x30, 0x87, 0x25, 0x00, 0x4B, 0x81, 0xB5, 0x40, 0x00, 0x81, 0x61, 0x98, 0x5D, 0x00, 0x09, 0xB1, 0x3A, 0x00, 0x54, 0x84, 0xC9, 0x60, 0x00, 0x81, 0x5B, 0xBC, 0x18, 0x00, 0x5D, 0xA1, 0x0F, 0xD2, 0xDF, 0xEF, 0x00, 0x81, 0x05, 0x81, 0xEE, 0x6D, 0x00, 0x29, 0xE2, 0x6B, 0x5E, 0x5C, 0xBF, 0x4E, 0x4D, 0x00, 0x67, 0x90, 0x3D, 0x00, 0x42, 0x81, 0xBC, 0x68, 0x00, 0x3C, 0x81, 0xC6, 0x00, 0x00, 0x0C, 0x83, 0x75, 0x00, 0x81, 0x64, 0x84, 0xA0, 0x43, 0x00, 0x81, 0x4C, 0x84, 0xDA, 0x20, 0x00, 0x81, 0x49, 0x85, 0xC5, 0x4F, 0xC3, 0xD4, 0xEA, 0x00, 0x81, 0x16, 0x81, 0xEE, 0x6D, 0x64, 0x00, 0x17, 0x98, 0x5A, 0x5E, 0x5C, 0xBF, 0x3C, 0x3D, 0x00, 0x70, 0x82, 0xE2, 0x24, 0x00, 0x0C, 0x97, 0x68, 0x00, 0x2D, 0xCF, 0x16, 0x00, 0x39, 0x88, 0x20, 0x00, 0x39, 0x81, 0xBE, 0x52, 0x00, 0x83, 0x09, 0x84, 0xEA, 0x60, 0x00, 0x06, 0xD2, 0x28, 0x00, 0x06, 0x82, 0xCC, 0x38, 0x00, 0x3C, 0x85, 0x9C, 0x20, 0x00, 0x7E, 0xA1, 0x0F, 0xB4, 0xC9, 0xE4, 0x00, 0x81, 0x25, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x53, 0x52, 0x00, 0x52, 0x81, 0xDE, 0x39, 0x00, 0x30, 0x90, 0x43, 0x00, 0x2A, 0x9E, 0x21, 0x00, 0x45, 0x81, 0xE7, 0x00, 0x00, 0x81, 0x67, 0x84, 0xB1, 0x00, 0x00, 0x81, 0x4C, 0x84, 0xFB, 0x20, 0x00, 0x12, 0x83, 0x45, 0x00, 0x3C, 0x85, 0xAC, 0x60, 0x00, 0x7B, 0xA1, 0x0F, 0xA5, 0xBD, 0xDF, 0x00, 0x81, 0x25, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x3E, 0x3F, 0x00, 0x76, 0x82, 0xFB, 0x01, 0x00, 0x0F, 0xEE, 0x4A, 0x00, 0x33, 0x85, 0xA8, 0x1D, 0x00, 0x39, 0x81, 0xA1, 0x02, 0x00, 0x81, 0x67, 0xEB, 0x14, 0x00, 0x81, 0x4C, 0x85, 0x8B, 0x60, 0x00, 0x0C, 0x82, 0x99, 0x65, 0x00, 0x45, 0x85, 0xBD, 0x20, 0x00, 0x78, 0xA1, 0x0F, 0x95, 0xB2, 0xD9, 0x00, 0x7B, 0x81, 0xEE, 0x6D, 0x00, 0x08, 0x90, 0x3D, 0x00, 0x28, 0xA9, 0x17, 0x00, 0x75, 0x90, 0x3D, 0x00, 0x15, 0xF0, 0x52, 0x00, 0x27, 0x85, 0x47, 0x00, 0x30, 0x88, 0x20, 0x00, 0x12, 0x66, 0x00, 0x81, 0x6A, 0x81, 0xBD, 0x54, 0x00, 0x81, 0x4C, 0x85, 0x9C, 0x20, 0x00, 0x06, 0x78, 0x00, 0x78, 0x84, 0x93, 0x48, 0x00, 0x4B, 0xA1, 0x0F, 0x00, 0x81, 0x25, 0x81, 0xEE, 0x6D, 0x00, 0x06, 0x98, 0x5A, 0x5E, 0x5B, 0x00, 0x73, 0xA0, 0x7A, 0x00, 0x1E, 0x94, 0x32, 0x00, 0x21, 0x85, 0xDB, 0x3E, 0x00, 0x2D, 0x88, 0x20, 0x00, 0x12, 0x60, 0x00, 0x81, 0x64, 0xDA, 0x51, 0x00, 0x12, 0xA3, 0x68, 0x00, 0x51, 0x85, 0xAC, 0x60, 0x00, 0x72, 0x82, 0x47, 0x00, 0x81, 0x01, 0x83, 0xBF, 0x4E, 0x00, 0x21, 0x85, 0xC6, 0x3E, 0x00, 0x27, 0x88, 0x20, 0x00, 0x81, 0x22, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x46, 0x46, 0x7D, 0x00, 0x81, 0x13, 0x81, 0xC1, 0x1F, 0x00, 0x1E, 0x85, 0xEB, 0x7E, 0x00, 0x27, 0x88, 0x20, 0x00, 0x0F, 0x81, 0x81, 0x3C, 0x00, 0x7E, 0x83, 0x99, 0x7C, 0x00, 0x81, 0x04, 0x82, 0x87, 0x7A, 0x00, 0x4E, 0x85, 0xBD, 0x20, 0x00, 0x72, 0x93, 0x04, 0x00, 0x06, 0x83, 0x4E, 0x00, 0x81, 0x07, 0x83, 0xD7, 0x27, 0x00, 0x39, 0x88, 0x1D, 0xE8, 0xEE, 0xF7, 0x00, 0x13, 0x90, 0x3D, 0x00, 0x81, 0x0F, 0x81, 0xEE, 0x6D, 0x00, 0x08, 0xB9, 0x54, 0x93, 0x00, 0x81, 0x1C, 0x82, 0x8D, 0x3E, 0xCC, 0xCD, 0xD2, 0x00, 0x15, 0x88, 0x26, 0x00, 0x21, 0x88, 0x20, 0x00, 0x06, 0x82, 0xFA, 0x1B, 0x00, 0x15, 0x83, 0xF3, 0x46, 0x00, 0x81, 0x73, 0x84, 0xA0, 0x49, 0x00, 0x09, 0x81, 0xA7, 0x71, 0x00, 0x4E, 0x85, 0xCD, 0x60, 0x00, 0x78, 0xA9, 0x1D, 0x00, 0x81, 0x04, 0xC2, 0x75, 0x67, 0x68, 0x78, 0x00, 0x39, 0xA1, 0x0F, 0xE1, 0xE8, 0xF4, 0x00, 0x81, 0x1F, 0x81, 0xEE, 0x6D, 0x00, 0x06, 0xA9, 0x17, 0x00, 0x5D, 0x81, 0x83, 0x65, 0x00, 0x4B, 0x8B, 0x17, 0x00, 0x06, 0x81, 0x9A, 0x01, 0x00, 0x0C, 0x84, 0x16, 0x00, 0x1B, 0x88, 0x20, 0x00, 0x0C, 0x83, 0xF3, 0x2E, 0x00, 0x12, 0x48, 0x00, 0x81, 0x79, 0x81, 0xC5, 0x68, 0x00, 0x09, 0xBC, 0x4B, 0x00, 0x3F, 0x8A, 0x1F, 0x00, 0x09, 0xA8, 0x22, 0x00, 0x78, 0xB3, 0x7E, 0xD9, 0xD9, 0xDD, 0x00, 0x18, 0x84, 0xF2, 0x68, 0x00, 0x72, 0xBA, 0x67, 0x00, 0x36, 0xA1, 0x0F, 0xE0, 0xE8, 0xF4, 0x00, 0x36, 0xB9, 0x54, 0x00, 0x69, 0x81, 0xEE, 0x6D, 0x5A, 0x59, 0xB1, 0x00, 0x51, 0x81, 0xFF, 0x2D, 0x00, 0x63, 0xAC, 0x26, 0x00, 0x06, 0x81, 0xA9, 0x01, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0xB1, 0x76, 0x00, 0x09, 0x82, 0xB7, 0x7D, 0x00, 0x1E, 0x81, 0xA0, 0x55, 0x00, 0x81, 0x04, 0x84, 0xC7, 0x1F, 0x00, 0x81, 0x04, 0xA3, 0x65, 0x00, 0x3C, 0x81, 0x93, 0x7E, 0x00, 0x81, 0x01, 0x85, 0xEE, 0x60, 0x00, 0x06, 0x83, 0x83, 0x51, 0x00, 0x06, 0x89, 0x1E, 0xA6, 0xA7, 0xB0, 0x00, 0x15, 0x82, 0xAB, 0x38, 0x00, 0x6C, 0x91, 0x56, 0x00, 0x36, 0xA1, 0x0F, 0xD1, 0xDD, 0xEF, 0x00, 0x49, 0xE2, 0x6B, 0x00, 0x50, 0x81, 0xEE, 0x6D, 0x5A, 0x5A, 0xB1, 0x4A, 0x4A, 0x85, 0x00, 0x5D, 0x81, 0x8B, 0x7F, 0x00, 0x81, 0x10, 0xC5, 0x12, 0x00, 0x1B, 0x84, 0x8C, 0x1A, 0x00, 0x81, 0x76, 0x81, 0xED, 0x24, 0x00, 0x36, 0x98, 0x66, 0x00, 0x0F, 0x85, 0xE5, 0x3C, 0x00, 0x81, 0x19, 0x86, 0x86, 0x66, 0x00, 0x72, 0x82, 0xC5, 0x3D, 0x00, 0x30, 0xA1, 0x0F, 0xC2, 0xD1, 0xE9, 0x00, 0x81, 0x0D, 0x81, 0xEE, 0x6D, 0x5F, 0x61, 0xBA, 0x53, 0x55, 0x9C, 0x4B, 0x4C, 0x86, 0x00, 0x81, 0x16, 0x90, 0x34, 0x00, 0x18, 0x8C, 0x2A, 0x00, 0x45, 0x81, 0xB0, 0x65, 0x00, 0x21, 0xB2, 0x0B, 0x00, 0x81, 0x73, 0x83, 0x8C, 0x75, 0x00, 0x06, 0x87, 0x61, 0x00, 0x2D, 0x82, 0x17, 0x00, 0x0F, 0x81, 0xA5, 0x3C, 0x00, 0x7B, 0x81, 0xC6, 0x0F, 0x00, 0x21, 0x82, 0xBB, 0x78, 0x00, 0x75, 0xC5, 0x57, 0x00, 0x2D, 0xA1, 0x0F, 0xC1, 0xD0, 0xE9, 0x00, 0x81, 0x01, 0x81, 0xEE, 0x6D, 0x5B, 0x5F, 0xAC, 0x52, 0x55, 0x95, 0x46, 0x48, 0x78, 0x3A, 0x3C, 0x00, 0x6A, 0xEA, 0x73, 0x00, 0x54, 0x82, 0x77, 0x00, 0x24, 0x82, 0xEB, 0x03, 0x00, 0x12, 0x12, 0x00, 0x82, 0x17, 0x84, 0x9F, 0x12, 0x00, 0x0F, 0x82, 0x92, 0x19, 0x00, 0x27, 0x98, 0x24, 0x00, 0x0F, 0x84, 0x9F, 0x30, 0x00, 0x82, 0x17, 0x81, 0xE1, 0x0C, 0x00, 0x2A, 0xA1, 0x0F, 0xC1, 0xD0, 0xE9, 0x00, 0x66, 0x84, 0xC0, 0x45, 0x00, 0x0F, 0x90, 0x3D, 0x5A, 0x5F, 0xA5, 0x4D, 0x51, 0x87, 0x44, 0x46, 0x71, 0x00, 0x81, 0x52, 0x84, 0x97, 0x34, 0x00, 0x06, 0x84, 0xD1, 0x5C, 0x00, 0x1E, 0x90, 0x52, 0x00, 0x06, 0xA1, 0x1E, 0x00, 0x81, 0x04, 0x83, 0xEC, 0x27, 0x00, 0x81, 0x28, 0x88, 0x23, 0x00, 0x09, 0x83, 0xA3, 0x2F, 0x00, 0x15, 0x82, 0x32, 0x5A, 0x5C, 0x6D, 0x00, 0x0C, 0x84, 0x88, 0x73, 0x00, 0x06, 0x82, 0x62, 0x00, 0x82, 0x1D, 0x82, 0x92, 0x4C, 0x00, 0x27, 0xA1, 0x0F, 0xC1, 0xCF, 0xE9, 0x00, 0x40, 0xE2, 0x6B, 0x00, 0x26, 0xA9, 0x17, 0x63, 0x6B, 0xB6, 0x59, 0x5E, 0x9F, 0x4B, 0x4F, 0x80, 0x3E, 0x41, 0x00, 0x81, 0x6B, 0x8E, 0x29, 0x00, 0x15, 0x81, 0xE3, 0x14, 0x00, 0x82, 0x2F, 0x81, 0xFD, 0x6D, 0x00, 0x0C, 0x87, 0x76, 0x00, 0x0C, 0xBC, 0x4E, 0x00, 0x1B, 0x84, 0xD5, 0x00, 0xD9, 0xD9, 0xDD, 0x00, 0x81, 0x0A, 0x8A, 0x79, 0x00, 0x06, 0x81, 0xCF, 0x42, 0x00, 0x6C, 0xDA, 0x60, 0x00, 0x4B, 0xA1, 0x0F, 0xC1, 0xCF, 0xE9, 0x00, 0x5A, 0x81, 0xEE, 0x6D, 0x62, 0x6B, 0xAF, 0x53, 0x5A, 0x90, 0x45, 0x4A, 0x71, 0x00, 0x5A, 0x84, 0xE9, 0x65, 0x00, 0x83, 0x60, 0x81, 0xF5, 0x4A, 0x00, 0x1B, 0xC4, 0x20, 0x00, 0x18, 0x93, 0x19, 0x00, 0x81, 0x0A, 0x83, 0x97, 0x08, 0x00, 0x1B, 0x83, 0xBD, 0x46, 0x00, 0x81, 0x0A, 0x85, 0x8F, 0x3A, 0x00, 0x1E, 0xA1, 0x0F, 0xB1, 0xC3, 0xE3, 0x00, 0x4B, 0x81, 0xEE, 0x6D, 0x6C, 0x78, 0xC0, 0x60, 0x6A, 0xA8, 0x51, 0x58, 0x89, 0x42, 0x00, 0x53, 0x85, 0x82, 0x39, 0x00, 0x84, 0x01, 0x88, 0x26, 0x00, 0x06, 0x83, 0x96, 0x7C, 0x00, 0x1B, 0x82, 0xF6, 0x14, 0x00, 0x81, 0x0D, 0xFE, 0x03, 0x00, 0x09, 0x81, 0x87, 0x3F, 0xE6, 0xE6, 0xE9, 0xCC, 0xCD, 0xD2, 0x00, 0x09, 0x84, 0xEA, 0x57, 0x00, 0x09, 0x0C, 0x00, 0x1E, 0xD6, 0x77, 0x00, 0x81, 0x07, 0xA1, 0x0F, 0xA1, 0xB6, 0xDD, 0x00, 0x3F, 0x81, 0xEE, 0x6D, 0x6A, 0x78, 0xB9, 0x5A, 0x64, 0x9A, 0x4B, 0x51, 0x7A, 0x3F, 0x43, 0x00, 0x83, 0x61, 0x82, 0x8D, 0x38, 0x00, 0x81, 0x16, 0x97, 0x32, 0x00, 0x81, 0x16, 0xAB, 0x5B, 0x00, 0x0F, 0x83, 0xB5, 0x05, 0x00, 0x06, 0x85, 0x9C, 0x2F, 0x00, 0x09, 0xB3, 0x09, 0x00, 0x06, 0x82, 0xE2, 0x69, 0x00, 0x81, 0x0A, 0x81, 0x3A, 0x00, 0x18, 0xA1, 0x0F, 0xA1, 0xB6, 0xDD, 0x00, 0x33, 0xB9, 0x54, 0x64, 0x72, 0xAB, 0x54, 0x5D, 0x8B, 0x48, 0x4E, 0x73, 0x38, 0x3B, 0x00, 0x82, 0x42, 0x84, 0xC0, 0x12, 0x00, 0x83, 0x57, 0x89, 0x45, 0x00, 0x0C, 0x84, 0xA0, 0x40, 0x00, 0x06, 0xF5, 0x18, 0x00, 0x0F, 0x91, 0x5F, 0x00, 0x81, 0x0D, 0x9A, 0x0B, 0x00, 0x18, 0xA1, 0x0F, 0xA0, 0xB5, 0xDD, 0x00, 0x24, 0xA9, 0x17, 0x73, 0x86, 0xC4, 0x62, 0x70, 0xA4, 0x51, 0x5A, 0x83, 0x44, 0x4A, 0x00, 0x4F, 0x85, 0xBB, 0x78, 0x00, 0x85, 0x59, 0x88, 0x20, 0x00, 0x0C, 0xF3, 0x40, 0x00, 0x06, 0xDB, 0x6A, 0x00, 0x0F, 0x98, 0x4E, 0x00, 0x3F, 0x84, 0xDD, 0x38, 0x00, 0x66, 0x83, 0xA2, 0x10, 0x00, 0x05, 0x88, 0x20, 0x00, 0x16, 0x98, 0x5A, 0x6D, 0x7F, 0xB5, 0x5B, 0x68, 0x94, 0x4E, 0x57, 0x7C, 0x3D, 0x41, 0x5B, 0x00, 0x86, 0x27, 0x88, 0x14, 0x00, 0x1E, 0x88, 0x20, 0x00, 0x0F, 0xBA, 0x70, 0x00, 0x06, 0xE3, 0x1E, 0x00, 0x81, 0x1F, 0xA3, 0x6E, 0x99, 0xA7, 0xC6, 0x00, 0x09, 0x90, 0x3D, 0x78, 0x90, 0xC7, 0x6A, 0x7D, 0xAE, 0x58, 0x65, 0x8D, 0x46, 0x4D, 0x6C, 0x38, 0x3C, 0x00, 0x86, 0x19, 0x98, 0x39, 0x00, 0x2D, 0xDA, 0x60, 0x00, 0x09, 0xBA, 0x67, 0x00, 0x0F, 0x81, 0xB9, 0x7A, 0x00, 0x06, 0xFC, 0x79, 0x00, 0x81, 0x76, 0x85, 0xC0, 0x7A, 0x00, 0x86, 0x06, 0x88, 0x20, 0x00, 0x06, 0x81, 0xFF, 0x42, 0x00, 0x09, 0x88, 0x02, 0x00, 0x06, 0x97, 0x35, 0x00, 0x06, 0x84, 0xED, 0x15, 0x00, 0x09, 0xD3, 0x65, 0x00, 0x83, 0x63, 0x82, 0xBD, 0x0B, 0x00, 0x84, 0x1F, 0x98, 0x63, 0x00, 0x09, 0x81, 0x8D, 0x18, 0x00, 0x12, 0x82, 0xA0, 0x2D, 0x00, 0x82, 0x35, 0x85, 0x86, 0x0D, 0x00, 0x85, 0x5C, 0x88, 0x2F, 0x00, 0x06, 0x83, 0x9C, 0x40, 0x00, 0x06, 0x84, 0x90, 0x0C, 0x00, 0x83, 0x63, 0x82, 0xC5, 0x25, 0x00, 0x88, 0x0E, 0x8B, 0x7D, 0x00, 0x88, 0x74, 0x88, 0x74, 0x00, 0x06, 0xB4, 0x46, 0x00, 0x09, 0x86, 0x83, 0x5D, 0x00, 0x06, 0xB5, 0x71, 0xC0, 0xC0, 0xC7, 0x00, 0x24, 0x84, 0xA5, 0x09, 0x00, 0x87, 0x61, 0x88, 0x1D, 0x00, 0x21, 0xE8, 0x74, 0x00, 0x82, 0x0B, 0x81, 0x8C, 0x2F, 0x00, 0x85, 0x26, 0x87, 0x52, 0x00, 0x06, 0xF8, 0x6C, 0x00, 0x42, 0xA4, 0x5A, 0x00, 0x2A, 0x82, 0xC5, 0x55, 0x00, 0x30, 0x82, 0xB7, 0x3B, 0x00, 0x81, 0x64, 0x85, 0xC4, 0x03, 0x00, 0x30, 0x83, 0xCF, 0x1C, 0x00, 0x81, 0x3A, 0x84, 0x8A, 0x5D, 0x00, 0x83, 0x39, 0x82, 0xF6, 0x56, 0xC0, 0xC0, 0xC7, 0x00, 0x3C, 0x98, 0x00, 0x00, 0x30, 0x81, 0x9D, 0x0D, 0x00, 0x81, 0x7C, 0xB6, 0x09, 0x00, 0x27, 0x84, 0x82, 0x19, 0x00, 0x83, 0x1B, 0x85, 0xD8, 0x02, 0x00, 0x81, 0x76, 0x82, 0xF6, 0x53, 0x00, 0x39, 0x82, 0x8F, 0x2B, 0x00, 0x33, 0x81, 0xEA, 0x3F, 0x00, 0x81, 0x76, 0x81, 0xC6, 0x09, 0x00, 0x51, 0x81, 0xEC, 0x6B, 0x00, 0x84, 0x67, 0x90, 0x3D, 0x00, 0x3C, 0x81, 0xA9, 0x76, 0x00, 0x12, 0x81, 0xEE, 0x79, 0x00, 0x06, 0x81, 0xB5, 0x31, 0x00, 0x0C, 0x4E, 0x5A, 0x5C, 0x6D, 0x00, 0x12, 0x85, 0xF7, 0x12, 0x00, 0x81, 0x70, 0x81, 0xD6, 0x49, 0x00, 0x12, 0x9B, 0x03, 0x00, 0x09, 0x81, 0x9F, 0x12, 0x00, 0x85, 0x14, 0x98, 0x60, 0x00, 0x0F, 0x83, 0xB8, 0x56, 0x00, 0x39, 0x84, 0x6D, 0x00, 0x0F, 0x85, 0x74, 0x00, 0x1B, 0x81, 0xC3, 0x60, 0x00, 0x12, 0x81, 0x87, 0x33, 0x00, 0x81, 0x6D, 0x85, 0x62, 0x00, 0x0F, 0x82, 0xE2, 0x27, 0x00, 0x81, 0x3D, 0x81, 0xA4, 0x4A, 0x00, 0x06, 0x84, 0xF3, 0x09, 0x00, 0x0C, 0x81, 0xBE, 0x6A, 0x00, 0x06, 0x81, 0xA0, 0x76, 0x00, 0x83, 0x57, 0x83, 0xA8, 0x13, 0x00, 0x39, 0x83, 0xD2, 0x73, 0x00, 0x0F, 0x90, 0x3D, 0x00, 0x21, 0x48, 0x00, 0x0F, 0xD7, 0x12, 0x00, 0x81, 0x2B, 0x84, 0xF0, 0x45, 0x00, 0x4B, 0x81, 0x81, 0x06, 0x00, 0x81, 0x3D, 0x8A, 0x16, 0x00, 0x0F, 0x83, 0x42, 0x00, 0x09, 0x88, 0x20, 0x00, 0x1E, 0x82, 0xCA, 0x1B, 0x00, 0x83, 0x33, 0x88, 0x20, 0x00, 0x45, 0x83, 0xD5, 0x25, 0x00, 0x0F, 0x81, 0xEF, 0x59, 0x00, 0x24, 0x84, 0x1F, 0x00, 0x0F, 0x83, 0xDF, 0x35, 0x00, 0x81, 0x64, 0x90, 0x43, 0x00, 0x0C, 0x82, 0xA2, 0x56, 0x00, 0x81, 0x40, 0x81, 0xD0, 0x2B, 0x00, 0x06, 0x90, 0x37, 0xA6, 0xA7, 0xB0, 0x00, 0x09, 0x82, 0x98, 0x46, 0x00, 0x0F, 0x85, 0x95, 0x61, 0x00, 0x83, 0x45, 0xBD, 0x40, 0x00, 0x0F, 0x98, 0x5D, 0x00, 0x39, 0xA8, 0x2B, 0x00, 0x36, 0x83, 0xEE, 0x4D, 0x00, 0x0C, 0xA7, 0x24, 0x00, 0x81, 0x64, 0x82, 0x98, 0x46, 0x00, 0x09, 0x81, 0xBD, 0x54, 0x00, 0x81, 0x40, 0x83, 0xBF, 0x2A, 0x00, 0x0F, 0x84, 0xBB, 0x5B, 0x00, 0x0C, 0x88, 0x20, 0x00, 0x1B, 0x85, 0xCD, 0x60, 0x00, 0x83, 0x33, 0x88, 0x20, 0x00, 0x0C, 0x95, 0x6F, 0x00, 0x39, 0x87, 0x22, 0x00, 0x0F, 0x98, 0x5D, 0x00, 0x2A, 0x94, 0x5C, 0x00, 0x0F, 0x82, 0xD2, 0x20, 0x00, 0x81, 0x61, 0xB1, 0x49, 0x00, 0x09, 0xA0, 0x7A, 0x00, 0x81, 0x40, 0x81, 0x6A, 0x00, 0x06, 0x8B, 0x59, 0x00, 0x09, 0x90, 0x22, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x12, 0x81, 0x84, 0x12, 0x00, 0x83, 0x39, 0x88, 0x20, 0x00, 0x0F, 0x85, 0xCB, 0x52, 0x00, 0x42, 0x88, 0x65, 0x00, 0x30, 0x83, 0xAD, 0x48, 0x00, 0x0C, 0xA7, 0x2D, 0x00, 0x81, 0x61, 0x8C, 0x72, 0x00, 0x81, 0x49, 0x82, 0x92, 0x16, 0x00, 0x0F, 0x81, 0x9C, 0x3F, 0x00, 0x15, 0x88, 0x20, 0x00, 0x83, 0x45, 0x83, 0xD1, 0x4E, 0x00, 0x0C, 0x98, 0x18, 0x00, 0x39, 0xA4, 0x54, 0x00, 0x0C, 0x87, 0x64, 0x00, 0x30, 0x8C, 0x36, 0x00, 0x0C, 0x88, 0x5C, 0x00, 0x81, 0x5E, 0x8C, 0x72, 0x00, 0x7B, 0x82, 0x8F, 0x4F, 0x00, 0x54, 0x92, 0x09, 0x00, 0x0C, 0x89, 0x66, 0x00, 0x83, 0x5A, 0x88, 0x20, 0x00, 0x45, 0x83, 0x8A, 0x7C, 0x00, 0x0C, 0x88, 0x65, 0x00, 0x30, 0x90, 0x04, 0x00, 0x0C, 0xCB, 0x1B, 0x00, 0x81, 0x5E, 0xA1, 0x03, 0x00, 0x54, 0x82, 0xB1, 0x20, 0x00, 0x7E, 0x98, 0x60, 0x00, 0x09, 0x84, 0x31, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x06, 0x82, 0x92, 0x07, 0x00, 0x83, 0x42, 0xA1, 0x00, 0x00, 0x42, 0x83, 0x83, 0x60, 0x00, 0x45, 0xA9, 0x62, 0x00, 0x81, 0x67, 0xD0, 0x08, 0x00, 0x7E, 0x82, 0xC9, 0x2C, 0x00, 0x5D, 0x83, 0xA4, 0x60, 0x00, 0x0F, 0xB1, 0x40, 0x00, 0x06, 0xB9, 0x78, 0x00, 0x83, 0x42, 0xF7, 0x26, 0x00, 0x42, 0x83, 0x94, 0x20, 0x00, 0x12, 0x83, 0xEF, 0x42, 0x00, 0x39, 0x82, 0xF0, 0x65, 0x00, 0x81, 0x61, 0xA9, 0x23, 0x00, 0x81, 0x4C, 0x88, 0x20, 0x00, 0x09, 0xBD, 0x52, 0x00, 0x06, 0x84, 0xC5, 0x56, 0x00, 0x06, 0x81, 0xF3, 0x33, 0x00, 0x06, 0x84, 0x0D, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x83, 0x45, 0x83, 0xFA, 0x6B, 0x00, 0x0C, 0x81, 0xF4, 0x43, 0x00, 0x39, 0x88, 0x20, 0x00, 0x0C, 0xB9, 0x24, 0x00, 0x36, 0x45, 0x00, 0x81, 0x67, 0x83, 0xBD, 0x40, 0x00, 0x2A, 0x84, 0xF3, 0x00, 0x00, 0x81, 0x40, 0x84, 0xBA, 0x69, 0x00, 0x82, 0x32, 0x84, 0x9B, 0x6B, 0x00, 0x81, 0x22, 0xE8, 0x23, 0x00, 0x39, 0x83, 0x54, 0x00, 0x42, 0x84, 0x87, 0x21, 0x00, 0x81, 0x67, 0x88, 0x20, 0x00, 0x2D, 0x85, 0xA4, 0x40, 0x00, 0x81, 0x2E, 0x84, 0xB2, 0x46, 0x00, 0x06, 0xA5, 0x01, 0xE6, 0xE6, 0xE9, 0x00, 0x83, 0x4E, 0x81, 0xA4, 0x7D, 0x00, 0x42, 0x83, 0xC5, 0x60, 0x00, 0x42, 0x83, 0xF7, 0x62, 0x00, 0x81, 0x6D, 0x83, 0xCE, 0x00, 0x00, 0x7B, 0x85, 0xBC, 0x4F, 0x00, 0x84, 0x3A, 0x81, 0xC9, 0x66, 0x00, 0x3C, 0x88, 0x20, 0x00, 0x0F, 0xC9, 0x61, 0x00, 0x36, 0x87, 0x5E, 0x00, 0x81, 0x6A, 0x88, 0x20, 0x00, 0x09, 0x84, 0xEB, 0x4C, 0x00, 0x81, 0x52, 0x9A, 0x3B, 0x00, 0x82, 0x1D, 0x82, 0x94, 0x0C, 0x00, 0x81, 0x79, 0x88, 0x20, 0x00, 0x45, 0x83, 0xBC, 0x7E, 0x00, 0x81, 0x6A, 0x88, 0x20, 0x00, 0x09, 0xA3, 0x71, 0x00, 0x81, 0x46, 0x81, 0x8E, 0x16, 0x00, 0x0C, 0x81, 0xE5, 0x4F, 0x00, 0x09, 0xA4, 0x7B, 0x00, 0x06, 0x85, 0xCD, 0x78, 0x00, 0x83, 0x51, 0x88, 0x20, 0x00, 0x42, 0x83, 0xC5, 0x60, 0x00, 0x39, 0xD0, 0x17, 0x00, 0x81, 0x6D, 0x83, 0xE6, 0x60, 0x00, 0x09, 0x82, 0x86, 0x37, 0x00, 0x81, 0x49, 0x82, 0xB2, 0x66, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x82, 0x88, 0x06, 0x00, 0x0C, 0x84, 0x13, 0x00, 0x83, 0x45, 0x88, 0x23, 0x00, 0x42, 0xB9, 0x60, 0x00, 0x0C, 0xA9, 0x1D, 0x00, 0x39, 0xA9, 0x62, 0x00, 0x81, 0x6D, 0x88, 0x20, 0x00, 0x09, 0xD4, 0x30, 0x00, 0x81, 0x40, 0x86, 0x42, 0xE6, 0xE6, 0xE9, 0x00, 0x09, 0x82, 0xAA, 0x07, 0x00, 0x0F, 0xCA, 0x20, 0x00, 0x83, 0x54, 0xC2, 0x00, 0x00, 0x36, 0x8F, 0x7E, 0x00, 0x0C, 0xC1, 0x3B, 0x00, 0x39, 0xCE, 0x30, 0x00, 0x81, 0x70, 0x82, 0xB7, 0x14, 0x00, 0x7E, 0x82, 0xD1, 0x5B, 0x00, 0x4B, 0x9A, 0x29, 0x00, 0x09, 0x81, 0x40, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x21, 0x85, 0xAF, 0x39, 0x00, 0x83, 0x2A, 0x81, 0xC5, 0x23, 0x00, 0x3C, 0xA0, 0x3E, 0x00, 0x3F, 0x83, 0xB5, 0x5C, 0x00, 0x81, 0x79, 0x84, 0xA8, 0x60, 0x00, 0x0C, 0x81, 0x85, 0x79, 0x00, 0x81, 0x37, 0xC8, 0x48, 0x00, 0x06, 0x81, 0xA0, 0x25, 0x00, 0x83, 0x63, 0xE3, 0x00, 0x00, 0x3C, 0x8F, 0x3C, 0x00, 0x0F, 0x82, 0x93, 0x11, 0x00, 0x82, 0x2C, 0x84, 0xB9, 0x20, 0x00, 0x0C, 0x82, 0xD2, 0x23, 0x00, 0x0C, 0x83, 0xCC, 0x43, 0x00, 0x85, 0x11, 0xF3, 0x40, 0x00, 0x0F, 0x82, 0xEA, 0x41, 0x00, 0x39, 0xA0, 0x7D, 0x00, 0x39, 0x84, 0x0D, 0x00, 0x0C, 0x88, 0x65, 0x00, 0x81, 0x6D, 0x83, 0x8C, 0x0F, 0x00, 0x12, 0x81, 0xAD, 0x26, 0x00, 0x09, 0x81, 0xAD, 0x23, 0x00, 0x30, 0x84, 0xA7, 0x4A, 0x00, 0x72, 0x9B, 0x15, 0x00, 0x06, 0x82, 0xA8, 0x71, 0x00, 0x18, 0x88, 0x20, 0x00, 0x18, 0x85, 0xC5, 0x40, 0x00, 0x83, 0x6C, 0x81, 0x8C, 0x20, 0x00, 0x0F, 0x99, 0x1C, 0x00, 0x39, 0x9C, 0x6D, 0x00, 0x45, 0x81, 0x85, 0x01, 0x00, 0x82, 0x02, 0x84, 0xD0, 0x10, 0x00, 0x75, 0x84, 0x37, 0x00, 0x09, 0x89, 0x18, 0x00, 0x15, 0x81, 0x94, 0x40, 0x00, 0x83, 0x45, 0x81, 0xFF, 0x63, 0x00, 0x0F, 0xF2, 0x7E, 0x00, 0x2A, 0x8D, 0x0A, 0x00, 0x0F, 0x81, 0xC3, 0x3F, 0x00, 0x39, 0xC6, 0x1F, 0x00, 0x45, 0xA9, 0x62, 0x00, 0x81, 0x37, 0xAC, 0x1D, 0x00, 0x4B, 0x83, 0xC3, 0x34, 0x00, 0x75, 0x81, 0xA6, 0x49, 0x00, 0x09, 0x81, 0xB9, 0x23, 0x00, 0x0C, 0x88, 0x20, 0x00, 0x06, 0x9A, 0x3B, 0x00, 0x83, 0x48, 0x81, 0xA5, 0x00, 0x00, 0x0F, 0x83, 0xD6, 0x20, 0x00, 0x27, 0x90, 0x43, 0x00, 0x48, 0x83, 0xCD, 0x3E, 0x00, 0x0F, 0xA9, 0x62, 0x00, 0x81, 0x6A, 0xCF, 0x04, 0x00, 0x12, 0x81, 0xCE, 0x1D, 0x00, 0x0C, 0x85, 0x9A, 0x6C, 0x00, 0x18, 0x83, 0xC4, 0x32, 0x00, 0x1B, 0x1B, 0x00, 0x78, 0xB1, 0x43, 0xF2, 0xF2, 0xF4, 0xA6, 0xA7, 0xB0, 0x00, 0x06, 0x81, 0x8C, 0x2F, 0x00, 0x06, 0x83, 0x83, 0x75, 0x00, 0x06, 0x84, 0x19, 0x00, 0x83, 0x4B, 0x82, 0x90, 0x20, 0x00, 0x33, 0x83, 0xC5, 0x5D, 0x00, 0x0F, 0x82, 0xCF, 0x4A, 0x00, 0x39, 0x98, 0x5D, 0x00, 0x0C, 0x96, 0x5E, 0x00, 0x81, 0x67, 0x83, 0xC5, 0x66, 0x00, 0x0F, 0x88, 0x1D, 0x00, 0x06, 0x86, 0x60, 0x00, 0x81, 0x37, 0x8A, 0x19, 0x00, 0x0F, 0x82, 0xF4, 0x30, 0x00, 0x30, 0x82, 0xF4, 0x6F, 0x00, 0x83, 0x36, 0x81, 0x9C, 0x66, 0x00, 0x21, 0x88, 0x23, 0x00, 0x0F, 0xF7, 0x56, 0x00, 0x3C, 0x94, 0x4A, 0x00, 0x0F, 0x84, 0xAF, 0x04, 0x00, 0x81, 0x73, 0xCD, 0x14, 0x00, 0x81, 0x40, 0x97, 0x05, 0x00, 0x06, 0x82, 0x98, 0x37, 0x00, 0x06, 0x82, 0x83, 0x46, 0xB3, 0xB4, 0xBC, 0x00, 0x81, 0x31, 0xB3, 0x09, 0x00, 0x82, 0x38, 0x84, 0xDD, 0x53, 0x00, 0x15, 0x85, 0xC5, 0x34, 0x00, 0x15, 0x83, 0xB4, 0x67, 0x00, 0x39, 0x90, 0x3D, 0x00, 0x0F, 0x91, 0x38, 0x00, 0x81, 0x67, 0x81, 0xCA, 0x52, 0x00, 0x09, 0x8B, 0x0B, 0x00, 0x81, 0x3D, 0x8A, 0x10, 0x00, 0x06, 0x85, 0xA4, 0x37, 0x00, 0x83, 0x78, 0xF3, 0x4C, 0x00, 0x15, 0x9E, 0x15, 0x00, 0x15, 0x82, 0xF8, 0x6A, 0x00, 0x3C, 0xB9, 0x12, 0x00, 0x0C, 0x51, 0x00, 0x81, 0x67, 0x98, 0x5D, 0x00, 0x09, 0x81, 0x96, 0x6C, 0x00, 0x81, 0x40, 0x81, 0xE8, 0x73, 0x00, 0x81, 0x01, 0x83, 0xC5, 0x60, 0x00, 0x83, 0x00, 0x81, 0xBD, 0x6C, 0x00, 0x27, 0x81, 0xF6, 0x7B, 0x00, 0x39, 0xD1, 0x6F, 0x00, 0x0F, 0x90, 0x3D, 0x00, 0x81, 0x67, 0xD7, 0x0C, 0x00, 0x09, 0x92, 0x7E, 0x00, 0x81, 0x40, 0x92, 0x2D, 0x00, 0x0F, 0xB9, 0x60, 0x00, 0x83, 0x69, 0x88, 0x23, 0x00, 0x2A, 0xBF, 0x0F, 0x00, 0x3C, 0x81, 0xFF, 0x18, 0x00, 0x0F, 0x85, 0xC5, 0x3D, 0x00, 0x81, 0x6A, 0xB6, 0x0C, 0x00, 0x81, 0x49, 0xF3, 0x3D, 0x00, 0x57, 0x85, 0xF9, 0x20, 0x00, 0x83, 0x24, 0x88, 0x23, 0x73, 0x75, 0x83, 0x00, 0x15, 0x98, 0x4B, 0x00, 0x0F, 0xCF, 0x6A, 0x00, 0x3C, 0xE2, 0x29, 0x00, 0x0F, 0x89, 0x06, 0x00, 0x81, 0x67, 0x90, 0x3D, 0x00, 0x09, 0xC4, 0x6B, 0x00, 0x81, 0x43, 0xAB, 0x0A, 0x00, 0x09, 0x83, 0xBD, 0x40, 0x00, 0x0C, 0xD3, 0x77, 0x00, 0x81, 0x04, 0x83, 0xAD, 0x00, 0x00, 0x82, 0x6B, 0xB9, 0x75, 0x00, 0x09, 0x84, 0x9C, 0x18, 0x00, 0x0C, 0xA0, 0x26, 0x00, 0x42, 0x81, 0xA0, 0x61, 0x00, 0x0F, 0xAA, 0x0C, 0x00, 0x81, 0x6A, 0x90, 0x3D, 0x00, 0x54, 0x84, 0x98, 0x20, 0x00, 0x81, 0x1C, 0x82, 0x91, 0x5D, 0x00, 0x83, 0x69, 0x82, 0x89, 0x16, 0x00, 0x51, 0x83, 0x89, 0x06, 0x00, 0x0C, 0xBE, 0x38, 0x00, 0x81, 0x6A, 0x81, 0xFC, 0x09, 0x00, 0x81, 0x4C, 0x81, 0xBD, 0x60, 0x00, 0x81, 0x19, 0x83, 0xBD, 0x40, 0x00, 0x83, 0x4E, 0x83, 0xA2, 0x58, 0x00, 0x81, 0x6D, 0xE2, 0x71, 0x00, 0x81, 0x4F, 0x81, 0xC6, 0x00, 0x00, 0x86, 0x51, 0x82, 0xBC, 0x22, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x81, 0x40, 0x81, 0xC6, 0x00, 0x00, 0x09, 0x81, 0xD6, 0x25, 0x00, 0x86, 0x5A, 0x88, 0x23, 0x00, 0x81, 0x3D, 0xB1, 0x40, 0x00, 0x15, 0xCA, 0x14, 0x00, 0x06, 0xA9, 0x29, 0x00, 0x86, 0x48, 0x92, 0x12, 0x00, 0x09, 0x84, 0xE0, 0x74, 0x00, 0x88, 0x17, 0x88, 0x20, 0x00, 0x09, 0xD4, 0x36, 0x00, 0x81, 0x34, 0x86, 0x51, 0x00, 0x86, 0x63, 0x88, 0x20, 0x00, 0x09, 0x81, 0x86, 0x38, 0x00, 0x81, 0x34, 0x9F, 0x49, 0x00, 0x86, 0x63, 0x88, 0x20, 0x00, 0x0C, 0xC8, 0x5A, 0x00, 0x81, 0x31, 0x81, 0x82, 0x25, 0x00, 0x86, 0x66, 0x88, 0x20, 0x00, 0x09, 0x81, 0x97, 0x31, 0x00, 0x81, 0x31, 0xE1, 0x3D, 0x00, 0x09, 0x82, 0xD2, 0x08, 0x00, 0x0C, 0x81, 0x95, 0x38, 0x00, 0x09, 0x84, 0xBA, 0x21, 0x00, 0x60, 0x84, 0xDA, 0x20, 0x00, 0x85, 0x74, 0x98, 0x66, 0x00, 0x81, 0x2E, 0x83, 0xFF, 0x07, 0x00, 0x30, 0x82, 0xF6, 0x7A, 0x00, 0x86, 0x3C, 0x83, 0xBD, 0x40, 0x00, 0x0C, 0x82, 0xE4, 0x62, 0x00, 0x3F, 0x82, 0xFE, 0x31, 0x00, 0x6F, 0x81, 0x8C, 0x14, 0x00, 0x45, 0x85, 0xE6, 0x40, 0x00, 0x86, 0x27, 0x90, 0x46, 0x00, 0x0F, 0x81, 0xF1, 0x5E, 0x00, 0x09, 0x81, 0xC5, 0x7A, 0x00, 0x87, 0x2E, 0x83, 0x96, 0x3A, 0x00, 0x57, 0x82, 0xBC, 0x2E, 0x00, 0x4E, 0x84, 0xF0, 0x48, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x8F, 0x66, 0x90, 0x40, 0x00, 0x94, 0x62, 0x83, 0xD4, 0x36, 0x00, 0x9C, 0x28, 0x9C, 0x28, 0x00, 0xAA, 0x24, 0xAA, 0x24, 0x00, 0x06, 0xFC, 0x22, 0x00, 0x83, 0x45, 0x83, 0xCC, 0x67, 0x00, 0x84, 0x5B, 0x81, 0xBE, 0x2E, 0x00, 0x81, 0x0D, 0x84, 0xF1, 0x6A, 0x00, 0x86, 0x45, 0xF3, 0x40, 0x00, 0x48, 0x81, 0x9A, 0x79, 0x00, 0x09, 0x81, 0xD7, 0x11, 0x00, 0x83, 0x45, 0x83, 0xAB, 0x6D, 0x00, 0x84, 0x52, 0x88, 0x20, 0x00, 0x81, 0x40, 0x81, 0xCE, 0x71, 0x00, 0x86, 0x63, 0x88, 0x20, 0x00, 0x09, 0x82, 0xDD, 0x7F, 0x00, 0x88, 0x17, 0x88, 0x20, 0x00, 0x87, 0x4F, 0x81, 0xF8, 0x14, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x51, 0x88, 0x20, 0x00, 0x09, 0x82, 0xC2, 0x31, 0x00, 0x88, 0x17, 0x88, 0x20, 0x00, 0x09, 0x82, 0xB0, 0x25, 0x00, 0x87, 0x46, 0x81, 0xBE, 0x13, 0x00, 0x4E, 0x88, 0x20, 0x00, 0x0C, 0x85, 0xBC, 0x25, 0x00, 0x88, 0x11, 0xA9, 0x20, 0x00, 0x0C, 0x85, 0xBA, 0x74, 0x00, 0x88, 0x0E, 0xC2, 0x00, 0x4D, 0x4F, 0x62, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x82, 0xCD, 0x24, 0x00, 0x87, 0x37, 0xD2, 0x40, 0x00, 0x45, 0x86, 0x81, 0x55, 0x00, 0x82, 0x20, 0x84, 0xE5, 0x01, 0x00, 0x86, 0x1E, 0x88, 0x20, 0x00, 0x83, 0x54, 0x83, 0x8A, 0x6A, 0x00, 0x84, 0x46, 0x88, 0x20, 0xCC, 0xCD, 0xD2, 0x8D, 0x8E, 0x9A, 0x00, 0x87, 0x52, 0x81, 0xEF, 0x47, 0x00, 0x86, 0x42, 0x82, 0x86, 0x19, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x90, 0x40, 0x90, 0x40, 0x00, 0x89, 0x7E, 0x90, 0x40, 0x00, 0x86, 0x3F, 0x82, 0xB7, 0x59, 0x00, 0xD4, 0x33, 0x81, 0xFF, 0x21, 0x80, 0x81, 0x8F, 0x00, 0x06, 0x84, 0x96, 0x5D, 0x00, 0x88, 0x11, 0x82, 0xE2, 0x60, 0x9A, 0x9B, 0xA5, 0x00, 0x45, 0x86, 0x87, 0x3A, 0x00, 0x87, 0x52, 0x88, 0x20, 0x00, 0x12, 0x84, 0xD1, 0x7A, 0x00, 0x88, 0x0E, 0x88, 0x20, 0x00, 0x0C, 0x88, 0x1D, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x0F, 0x81, 0xDE, 0x1E, 0x00, 0x06, 0x21, 0x00, 0x12, 0xFC, 0x07, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0x3C, 0x00, 0x87, 0x49, 0x81, 0xC5, 0x74, 0x00, 0x1B, 0x84, 0x86, 0x1A, 0x00, 0x18, 0x82, 0xA0, 0x1B, 0x00, 0x18, 0x88, 0x20, 0x00, 0x09, 0x81, 0xE6, 0x74, 0x00, 0x81, 0x3A, 0x83, 0xC6, 0x25, 0x00, 0x86, 0x27, 0x83, 0xB5, 0x1A, 0x00, 0x1E, 0x81, 0xC5, 0x38, 0x00, 0x1E, 0x88, 0x20, 0x00, 0x0C, 0x84, 0xF3, 0x3F, 0x00, 0x83, 0x48, 0x85, 0xBC, 0x0A, 0x00, 0x84, 0x07, 0x88, 0x20, 0x00, 0x09, 0x82, 0x8F, 0x4F, 0x00, 0x1E, 0x87, 0x58, 0x00, 0x21, 0x88, 0x20, 0x00, 0x0C, 0x81, 0xF7, 0x3A, 0x00, 0x81, 0x6A, 0x84, 0x92, 0x41, 0x00, 0x85, 0x6B, 0xA0, 0x7A, 0x00, 0x1E, 0x81, 0xDE, 0x12, 0x00, 0x24, 0x88, 0x20, 0x00, 0x09, 0x84, 0xBC, 0x50, 0x00, 0x87, 0x49, 0x81, 0xEF, 0x1D, 0x00, 0x09, 0x81, 0xA5, 0x00, 0x00, 0x21, 0xA0, 0x38, 0x00, 0x27, 0x88, 0x20, 0x00, 0x09, 0x82, 0xB1, 0x20, 0x00, 0x87, 0x46, 0x90, 0x43, 0x00, 0x2A, 0x84, 0x90, 0x00, 0x00, 0x27, 0x88, 0x20, 0x00, 0x09, 0x83, 0xDF, 0x0B, 0x00, 0x87, 0x46, 0xA1, 0x06, 0x00, 0x2A, 0x85, 0xE6, 0x40, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x06, 0xB2, 0x0E, 0x00, 0x87, 0x46, 0x98, 0x63, 0x00, 0x2A, 0x82, 0xA8, 0x2C, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x09, 0x54, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x83, 0x72, 0x84, 0xD9, 0x28, 0x00, 0x84, 0x2E, 0x88, 0x20, 0x00, 0x87, 0x43, 0x82, 0xB1, 0x20, 0x00, 0x09, 0x85, 0x9E, 0x0D, 0x00, 0x21, 0x81, 0xCE, 0x20, 0x00, 0x87, 0x76, 0x88, 0x20, 0x00, 0x2A, 0x81, 0xDE, 0x60, 0x00, 0x87, 0x79, 0x88, 0x20, 0x00, 0x06, 0x82, 0xA8, 0x35, 0x00, 0x21, 0xC2, 0x00, 0x00, 0x06, 0xC9, 0x79, 0x00, 0x24, 0x85, 0xC4, 0x00, 0x00, 0x09, 0x84, 0xB1, 0x51, 0x00, 0x87, 0x46, 0x82, 0x90, 0x2C, 0x00, 0x09, 0x82, 0xB8, 0x72, 0x00, 0x1E, 0x87, 0x4F, 0x00, 0x2A, 0xB9, 0x36, 0x00, 0x09, 0x82, 0xCA, 0x00, 0x00, 0x87, 0x46, 0xD2, 0x40, 0x00, 0x09, 0xE2, 0x35, 0x00, 0x1E, 0xA1, 0x03, 0x00, 0x09, 0x27, 0x00, 0x21, 0x82, 0xB9, 0x19, 0x00, 0x27, 0x91, 0x11, 0x00, 0x87, 0x2B, 0x88, 0x23, 0x00, 0x24, 0xFB, 0x1B, 0x00, 0x09, 0x85, 0xD8, 0x5C, 0x00, 0x1E, 0xA1, 0x03, 0x00, 0x09, 0x98, 0x5D, 0x00, 0x87, 0x4C, 0x83, 0x9C, 0x43, 0x00, 0x09, 0x98, 0x63, 0x00, 0x1E, 0xA8, 0x52, 0x00, 0x09, 0x85, 0xA4, 0x6A, 0x00, 0x18, 0xC1, 0x59, 0x00, 0x09, 0xFB, 0x63, 0x00, 0x83, 0x4B, 0x85, 0xD4, 0x6A, 0x00, 0x84, 0x0D, 0xE3, 0x06, 0x00, 0x1E, 0x85, 0xB7, 0x3B, 0x00, 0x09, 0xB1, 0x19, 0x00, 0x15, 0x84, 0xB9, 0x44, 0x67, 0x68, 0x78, 0x00, 0x09, 0x81, 0x84, 0x48, 0x00, 0x87, 0x52, 0x82, 0x90, 0x6E, 0x00, 0x09, 0xA8, 0x55, 0x00, 0x1E, 0x81, 0x9C, 0x24, 0x00, 0x0F, 0x85, 0xD8, 0x1D, 0xB3, 0xB4, 0xBC, 0x9A, 0x9B, 0xA5, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0x85, 0xA7, 0x5E, 0x00, 0x81, 0x6D, 0x85, 0xF9, 0x32, 0x00, 0x85, 0x6B, 0x81, 0x94, 0x46, 0x00, 0x06, 0x87, 0x64, 0x00, 0x27, 0x81, 0x83, 0x62, 0x00, 0x18, 0x81, 0xAD, 0x14, 0x00, 0x09, 0x85, 0xED, 0x5F, 0x00, 0x87, 0x52, 0x88, 0x23, 0x00, 0x2A, 0x85, 0xD4, 0x40, 0x00, 0x15, 0x85, 0xB8, 0x0F, 0xF2, 0xF2, 0xF4, 0x00, 0x88, 0x0E, 0x82, 0xA9, 0x45, 0x5A, 0x5C, 0x6D, 0x80, 0x81, 0x8F, 0x00, 0x84, 0x43, 0x85, 0xAB, 0x38, 0x00, 0x9D, 0x7A, 0x81, 0xF1, 0x0D}; static bool g_has_uncompressed = false; static unsigned char *get_uncompressed_splash(void) { @@ -44,10 +44,15 @@ void draw_splash(volatile uint32_t *fb) { } /* Draw actual splash. */ + const size_t x_res = 352; + const size_t y_res = 392; + const size_t x_start = (768 - x_res) / 2; + const size_t y_start = (1280 - y_res) / 2; + size_t pos = 0; - for (size_t y = 496; y < (496 + 287); y++) + for (size_t y = y_start; y < (y_start + y_res); y++) { - for (size_t x = 293; x < (293 + 171); x++) + for (size_t x = x_start; x < (x_start + x_res); x++) { fb[x + y*768] = splash[pos + 2] | (splash[pos + 1] << 8) | (splash[pos] << 16); pos += 3; From 1a63078c320512ccaeb752a245082f45f83bbbfd Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 23:16:39 -0800 Subject: [PATCH 433/489] README: add sept to component list --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 85f15e3de..9233e3471 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Components Atmosphère consists of multiple components, each of which replaces/modifies a different component of the system: * Fusée: First-stage Loader, responsible for loading and validating stage 2 (custom TrustZone) plus package2 (Kernel/FIRM sysmodules), and patching them as needed. This replaces all functionality normally in Package1loader/NX Bootloader. + * Sept: Payload used to enable support for runtime key derivation on 7.0.0 . * Exosphère: Customized TrustZone, to run a customized Secure Monitor * Thermosphère: EL2 EmuNAND support, i.e. backing up and using virtualized/redirected NAND images * Stratosphère: Custom Sysmodule(s), both Rosalina style to extend the kernel/provide new features, and of the loader reimplementation style to hook important system actions From 771039e6a7ce743e713343ea1c0f684fb18e6ccc Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 20 Feb 2019 23:25:31 -0800 Subject: [PATCH 434/489] Sept: improve edge case cleanup a little. --- sept/sept-secondary/src/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 048b3edc1..08500c300 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -63,6 +63,11 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { se_save_context(KEYSLOT_SWITCH_SRKGENKEY, KEYSLOT_SWITCH_RNGKEY, enc_se_state); se_set_in_context_save_mode(false); + /* Clear all keyslots. */ + for (size_t k = 0; k < 0x10; k++) { + clear_aes_keyslot(k); + } + set_has_rebooted(true); reboot_to_self(); } else { From 5b235a4b03c94752e9263853e688fdd8fcbfead7 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 00:52:33 -0800 Subject: [PATCH 435/489] sept-s: revise splash for roundedness one more time --- README.md | 2 +- sept/sept-secondary/src/splash.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9233e3471..4c4f5807e 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Components Atmosphère consists of multiple components, each of which replaces/modifies a different component of the system: * Fusée: First-stage Loader, responsible for loading and validating stage 2 (custom TrustZone) plus package2 (Kernel/FIRM sysmodules), and patching them as needed. This replaces all functionality normally in Package1loader/NX Bootloader. - * Sept: Payload used to enable support for runtime key derivation on 7.0.0 . + * Sept: Payload used to enable support for runtime key derivation on 7.0.0. * Exosphère: Customized TrustZone, to run a customized Secure Monitor * Thermosphère: EL2 EmuNAND support, i.e. backing up and using virtualized/redirected NAND images * Stratosphère: Custom Sysmodule(s), both Rosalina style to extend the kernel/provide new features, and of the loader reimplementation style to hook important system actions diff --git a/sept/sept-secondary/src/splash.c b/sept/sept-secondary/src/splash.c index 100de11a8..7feec1831 100644 --- a/sept/sept-secondary/src/splash.c +++ b/sept/sept-secondary/src/splash.c @@ -23,7 +23,7 @@ #include "lib/lz.h" #include "utils.h" -static const uint8_t s_splash[] = {0x00, 0x34, 0x36, 0x4B, 0x34, 0x36, 0x4B, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x30, 0x30, 0x00, 0x60, 0x60, 0x00, 0x81, 0x40, 0x81, 0x40, 0x00, 0x83, 0x00, 0x83, 0x00, 0x00, 0x86, 0x00, 0x86, 0x00, 0x00, 0x8B, 0x0E, 0x8B, 0x0E, 0x5A, 0x5C, 0x6D, 0x00, 0x88, 0x0E, 0x88, 0x11, 0x73, 0x75, 0x83, 0xA6, 0xA7, 0xB0, 0xD9, 0xD9, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x04, 0x04, 0xFF, 0xCC, 0xCD, 0xD2, 0x00, 0x88, 0x05, 0x88, 0x1A, 0x9A, 0x9B, 0xA5, 0xE6, 0xE6, 0xE9, 0x00, 0x09, 0x88, 0x17, 0x00, 0x27, 0x88, 0x20, 0x41, 0x43, 0x56, 0x00, 0x87, 0x64, 0x98, 0x45, 0x00, 0x12, 0x88, 0x1A, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x15, 0x00, 0x1B, 0x88, 0x20, 0x80, 0x81, 0x8F, 0xF2, 0xF2, 0xF4, 0x00, 0x87, 0x5E, 0x99, 0x04, 0x80, 0x81, 0x8F, 0x00, 0x0C, 0x88, 0x17, 0xB3, 0xB4, 0xBC, 0x73, 0x75, 0x83, 0x00, 0x06, 0x90, 0x16, 0x9A, 0x9B, 0xA5, 0x00, 0x1B, 0x88, 0x20, 0x67, 0x68, 0x78, 0x00, 0x06, 0x33, 0xD9, 0xD9, 0xDD, 0x00, 0x87, 0x58, 0x90, 0x46, 0x00, 0x0C, 0x88, 0x1D, 0xCC, 0xCD, 0xD2, 0x4D, 0x4F, 0x62, 0x00, 0x0F, 0x98, 0x72, 0x00, 0x1E, 0x90, 0x40, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x3C, 0xC0, 0xC0, 0xC7, 0x00, 0x87, 0x52, 0x88, 0x1D, 0x00, 0x09, 0x90, 0x01, 0xFF, 0xFF, 0xFF, 0x8D, 0x8E, 0x9A, 0x00, 0x15, 0xA1, 0x12, 0x00, 0x21, 0xA1, 0x00, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x42, 0x67, 0x68, 0x78, 0x00, 0x87, 0x4C, 0x88, 0x1D, 0x41, 0x43, 0x56, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0x87, 0x5B, 0x80, 0x81, 0x8F, 0x00, 0x18, 0xA9, 0x32, 0x00, 0x21, 0x88, 0x20, 0x4D, 0x4F, 0x62, 0x00, 0x87, 0x55, 0xB1, 0x67, 0x00, 0x06, 0x87, 0x7C, 0xFF, 0xFF, 0xFF, 0xA6, 0xA7, 0xB0, 0x00, 0x1E, 0x24, 0x00, 0x21, 0x87, 0x79, 0x00, 0x09, 0x98, 0x66, 0x00, 0x0F, 0x99, 0x1F, 0x00, 0x87, 0x43, 0x90, 0x3D, 0xE6, 0xE6, 0xE9, 0x00, 0x21, 0x88, 0x44, 0x00, 0x21, 0x88, 0x20, 0x5A, 0x5C, 0x6D, 0x00, 0x06, 0x88, 0x20, 0x9A, 0x9B, 0xA5, 0x00, 0x87, 0x46, 0x88, 0x20, 0x8D, 0x8E, 0x9A, 0x00, 0x1E, 0x98, 0x5A, 0x00, 0x2D, 0x88, 0x20, 0x34, 0x36, 0x4B, 0x00, 0x21, 0xBA, 0x0A, 0x00, 0x87, 0x2E, 0x88, 0x20, 0x00, 0x06, 0xA8, 0x55, 0xF2, 0xF2, 0xF4, 0x00, 0x24, 0x99, 0x04, 0x00, 0x24, 0x87, 0x76, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x88, 0x71, 0x00, 0x87, 0x46, 0x88, 0x20, 0x00, 0x09, 0xC1, 0x6B, 0x00, 0x48, 0x88, 0x20, 0x00, 0x09, 0xA1, 0x4E, 0x00, 0x87, 0x43, 0xA1, 0x03, 0x00, 0x09, 0xA0, 0x2F, 0x00, 0x15, 0xB9, 0x54, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x87, 0x43, 0xB9, 0x66, 0x00, 0x09, 0xC1, 0x77, 0x00, 0x21, 0x87, 0x4C, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x2A, 0x54, 0x00, 0x87, 0x76, 0x88, 0x20, 0x00, 0x09, 0xA9, 0x71, 0x00, 0x88, 0x17, 0x88, 0x20, 0x00, 0x09, 0x98, 0x60, 0x00, 0x87, 0x43, 0xEB, 0x2C, 0x00, 0x09, 0x88, 0x20, 0x73, 0x75, 0x83, 0x00, 0x48, 0x88, 0x20, 0x00, 0x09, 0xCA, 0x23, 0x00, 0x87, 0x46, 0xCA, 0x1D, 0x00, 0x27, 0xC9, 0x4F, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x06, 0x81, 0x8C, 0x50, 0x00, 0x1E, 0xCA, 0x6E, 0x00, 0x87, 0x2B, 0x88, 0x23, 0x00, 0x27, 0xC9, 0x4F, 0x00, 0x27, 0x88, 0x20, 0x00, 0x09, 0xE3, 0x03, 0x00, 0x21, 0xBA, 0x31, 0x00, 0x87, 0x28, 0x88, 0x20, 0x00, 0x09, 0x98, 0x0F, 0x00, 0x1E, 0x81, 0x83, 0x38, 0x00, 0x27, 0x88, 0x20, 0x00, 0x09, 0xA0, 0x7D, 0x00, 0x1E, 0xD3, 0x0E, 0x00, 0x87, 0x2E, 0x81, 0xA4, 0x65, 0x00, 0x24, 0x98, 0x63, 0x00, 0x24, 0x88, 0x20, 0x00, 0x09, 0xE3, 0x4B, 0xF2, 0xF2, 0xF4, 0x00, 0x87, 0x4C, 0x81, 0x8C, 0x26, 0x00, 0x06, 0x98, 0x63, 0xF2, 0xF2, 0xF4, 0x00, 0x1B, 0xD1, 0x72, 0x00, 0x24, 0x88, 0x20, 0xA6, 0xA7, 0xB0, 0x00, 0x87, 0x4F, 0xEB, 0x1D, 0x00, 0x0F, 0x90, 0x43, 0xD9, 0xD9, 0xDD, 0x00, 0x39, 0x88, 0x20, 0x00, 0x09, 0x45, 0x00, 0x87, 0x4F, 0x90, 0x3D, 0x00, 0x0F, 0xEA, 0x55, 0x00, 0x18, 0xA8, 0x58, 0x00, 0x1E, 0x88, 0x20, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0x81, 0x8C, 0x62, 0x00, 0x21, 0xBA, 0x2B, 0x00, 0x87, 0x37, 0xB9, 0x69, 0x00, 0x09, 0x81, 0xC5, 0x68, 0xD9, 0xD9, 0xDD, 0x00, 0x12, 0x98, 0x69, 0x00, 0x1B, 0x88, 0x20, 0x00, 0x09, 0xD2, 0x31, 0x00, 0x87, 0x4C, 0xB1, 0x37, 0x00, 0x1E, 0x90, 0x04, 0xF2, 0xF2, 0xF4, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0x98, 0x27, 0x00, 0x15, 0x88, 0x20, 0x67, 0x68, 0x78, 0x00, 0x09, 0x81, 0xA4, 0x74, 0x00, 0x87, 0x5E, 0x88, 0x1D, 0x00, 0x12, 0x90, 0x46, 0x00, 0x09, 0x81, 0xB5, 0x0D, 0x9A, 0x9B, 0xA5, 0x67, 0x68, 0x78, 0x00, 0x06, 0xBA, 0x07, 0xD9, 0xD9, 0xDD, 0x67, 0x68, 0x78, 0x73, 0x75, 0x83, 0x9A, 0x9B, 0xA5, 0x00, 0x0F, 0x2A, 0x00, 0x87, 0x61, 0x88, 0x1D, 0x00, 0x0C, 0x90, 0x2B, 0x00, 0x09, 0x90, 0x49, 0x00, 0x12, 0x81, 0xD6, 0x43, 0x00, 0x12, 0x12, 0xE6, 0xE6, 0xE9, 0x00, 0x87, 0x55, 0xA0, 0x74, 0x00, 0x1E, 0xD2, 0x07, 0xA6, 0xA7, 0xB0, 0x00, 0x21, 0x88, 0x26, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x87, 0x64, 0x81, 0xDE, 0x57, 0x00, 0x1B, 0xEB, 0x41, 0x9A, 0x9B, 0xA5, 0xC0, 0xC0, 0xC7, 0xCC, 0xCD, 0xD2, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x06, 0xB3, 0xB4, 0xBC, 0x8D, 0x8E, 0x9A, 0x00, 0x88, 0x11, 0x81, 0xF7, 0x4F, 0x00, 0x97, 0x0E, 0x82, 0x96, 0x6E, 0x00, 0x9F, 0x1C, 0x9F, 0x1C, 0x00, 0x83, 0x0C, 0xE2, 0x74, 0x00, 0x06, 0xC1, 0x53, 0x00, 0x87, 0x49, 0x81, 0x93, 0x6F, 0x00, 0x57, 0x81, 0xB5, 0x40, 0x00, 0x87, 0x4F, 0x81, 0x8B, 0x52, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x51, 0x81, 0xEF, 0x20, 0x00, 0x87, 0x55, 0x82, 0xA8, 0x35, 0x00, 0x45, 0x45, 0x00, 0x87, 0x4F, 0x81, 0xC5, 0x2F, 0x00, 0x51, 0x51, 0x00, 0x09, 0x81, 0xAC, 0x55, 0x00, 0x88, 0x17, 0xEA, 0x70, 0x00, 0x87, 0x52, 0x81, 0xCD, 0x52, 0x00, 0x5A, 0x81, 0xAD, 0x1D, 0x00, 0x88, 0x1A, 0x90, 0x43, 0x00, 0x09, 0x82, 0xB1, 0x23, 0x00, 0x87, 0x7C, 0x81, 0x8B, 0x6D, 0x00, 0x27, 0x81, 0xC6, 0x03, 0x00, 0x87, 0x49, 0x82, 0xC1, 0x1B, 0x00, 0x51, 0x82, 0xE2, 0x60, 0x00, 0x09, 0x81, 0xDE, 0x1E, 0x00, 0x21, 0x82, 0xA0, 0x6F, 0x00, 0x87, 0x7C, 0xDA, 0x6F, 0x00, 0x09, 0x81, 0xA4, 0x5C, 0xA6, 0xA7, 0xB0, 0x67, 0x68, 0x78, 0x00, 0x87, 0x7F, 0x98, 0x72, 0x00, 0x0C, 0x81, 0xA4, 0x59, 0x00, 0x06, 0x06, 0x00, 0x15, 0x81, 0xAD, 0x17, 0xE6, 0xE6, 0xE9, 0x00, 0x12, 0x2A, 0x00, 0x12, 0x12, 0x00, 0x0C, 0x0C, 0x00, 0x87, 0x4C, 0xD2, 0x40, 0x00, 0x2A, 0x81, 0xBD, 0x4E, 0x00, 0x2A, 0x2A, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x87, 0x49, 0xEB, 0x23, 0x67, 0x68, 0x78, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x2A, 0x2A, 0x00, 0xC1, 0x41, 0x81, 0xBD, 0x7E, 0x00, 0xA1, 0x06, 0xA1, 0x06, 0x41, 0x43, 0x56, 0x00, 0x06, 0xE2, 0x50, 0x00, 0x88, 0x0E, 0x82, 0xA0, 0x54, 0x00, 0x06, 0x82, 0xB1, 0x23, 0x00, 0x0F, 0x82, 0xC1, 0x45, 0x00, 0x88, 0x05, 0x84, 0x98, 0x20, 0x4D, 0x4F, 0x62, 0x00, 0x0C, 0x82, 0xD1, 0x76, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x87, 0x64, 0xF3, 0x34, 0x00, 0x0C, 0x82, 0xE2, 0x2D, 0x00, 0x09, 0x81, 0xAD, 0x32, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x88, 0x32, 0x00, 0x21, 0x84, 0x87, 0x60, 0x00, 0x87, 0x5E, 0x82, 0xCA, 0x09, 0x00, 0x09, 0x83, 0x94, 0x2C, 0x00, 0x06, 0x81, 0x9C, 0x51, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x81, 0xA4, 0x7D, 0x00, 0x27, 0x84, 0x98, 0x20, 0x00, 0x87, 0x5B, 0x84, 0xA0, 0x43, 0x00, 0x0C, 0x88, 0x1D, 0x00, 0x12, 0x81, 0xF7, 0x4F, 0x00, 0x21, 0x83, 0x83, 0x60, 0x00, 0x09, 0x84, 0x98, 0x5F, 0x00, 0x1B, 0x83, 0x84, 0x25, 0x00, 0x87, 0x43, 0x98, 0x57, 0x00, 0x18, 0x90, 0x01, 0x00, 0x2D, 0x83, 0x94, 0x20, 0x00, 0x87, 0x4F, 0x82, 0x90, 0x6E, 0x00, 0x09, 0x81, 0xE7, 0x03, 0x00, 0x1B, 0x98, 0x1E, 0x00, 0x2D, 0x83, 0xA4, 0x60, 0x00, 0x87, 0x4F, 0x81, 0xF8, 0x0E, 0x00, 0x09, 0x98, 0x5A, 0x00, 0x1B, 0x8F, 0x78, 0x00, 0x30, 0x83, 0xB5, 0x20, 0x00, 0x87, 0x49, 0xB1, 0x4C, 0x00, 0x27, 0x84, 0xA8, 0x15, 0x00, 0x30, 0x83, 0xC5, 0x60, 0x00, 0x1B, 0x84, 0xA1, 0x0B, 0x00, 0x63, 0x81, 0xD8, 0x09, 0x00, 0x0F, 0xB2, 0x6E, 0x00, 0x06, 0xCB, 0x63, 0x00, 0x86, 0x3F, 0x82, 0x88, 0x00, 0x00, 0x1E, 0x86, 0x42, 0x00, 0x30, 0x83, 0xD6, 0x20, 0x00, 0x75, 0xA9, 0x26, 0x00, 0x0F, 0x83, 0x8D, 0x40, 0x00, 0x09, 0x81, 0x2E, 0x00, 0x06, 0x81, 0x64, 0x00, 0x86, 0x36, 0xBA, 0x7C, 0x00, 0x27, 0x82, 0x98, 0x40, 0x00, 0x81, 0x25, 0x83, 0xE6, 0x60, 0x00, 0x06, 0x90, 0x37, 0xA6, 0xA7, 0xB0, 0x4D, 0x4F, 0x62, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0x90, 0x40, 0xF2, 0xF2, 0xF4, 0x00, 0x86, 0x24, 0x83, 0xB6, 0x39, 0x00, 0x12, 0x90, 0x25, 0x00, 0x27, 0x98, 0x0F, 0x00, 0x81, 0x22, 0x83, 0xF7, 0x20, 0x00, 0x06, 0xC3, 0x04, 0x00, 0x09, 0xBB, 0x1A, 0x00, 0x0C, 0x88, 0x20, 0x00, 0x09, 0xBA, 0x7F, 0x00, 0x86, 0x1E, 0x81, 0xF0, 0x78, 0x00, 0x06, 0x83, 0xAC, 0x62, 0x00, 0x15, 0xC9, 0x58, 0x00, 0x21, 0xB9, 0x12, 0x00, 0x81, 0x22, 0x84, 0x87, 0x60, 0x00, 0x06, 0x81, 0x22, 0x00, 0x0C, 0xCB, 0x51, 0x00, 0x0F, 0x81, 0x2E, 0x00, 0x86, 0x1E, 0x82, 0xB3, 0x07, 0x00, 0x09, 0x9F, 0x1C, 0x00, 0x81, 0x58, 0x84, 0x98, 0x20, 0x00, 0x0F, 0x81, 0xF0, 0x15, 0x00, 0x15, 0x88, 0x20, 0x00, 0x86, 0x1B, 0xEC, 0x60, 0x00, 0x06, 0x82, 0xA0, 0x45, 0x00, 0x0F, 0xA0, 0x68, 0x00, 0x5D, 0x84, 0x90, 0x00, 0x00, 0x6F, 0x88, 0x20, 0xC0, 0xC0, 0xC7, 0x00, 0x0C, 0xAA, 0x15, 0x00, 0x86, 0x2D, 0x88, 0x20, 0x00, 0x18, 0x87, 0x34, 0x00, 0x5D, 0x88, 0x20, 0x00, 0x6F, 0x82, 0x99, 0x08, 0x00, 0x06, 0x78, 0x00, 0x09, 0x75, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x06, 0x82, 0x9A, 0x21, 0x00, 0x86, 0x15, 0xA1, 0x00, 0x00, 0x09, 0xE2, 0x1A, 0x00, 0x12, 0xE2, 0x56, 0x00, 0x54, 0xA1, 0x00, 0x00, 0x78, 0x84, 0xC9, 0x60, 0x00, 0x06, 0xC2, 0x7B, 0x00, 0x09, 0xA0, 0x62, 0x00, 0x0F, 0xB1, 0x40, 0x00, 0x06, 0x9A, 0x5C, 0x00, 0x86, 0x12, 0x82, 0xA2, 0x3B, 0x00, 0x09, 0x83, 0xD5, 0x76, 0x00, 0x18, 0x87, 0x5B, 0x00, 0x51, 0xB1, 0x40, 0x00, 0x06, 0x83, 0xF7, 0x6E, 0x00, 0x75, 0xC2, 0x00, 0x00, 0x06, 0xC1, 0x68, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x85, 0xA5, 0x7A, 0x00, 0x06, 0x81, 0x2E, 0x73, 0x75, 0x83, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x7B, 0xCB, 0x33, 0x00, 0x85, 0x1A, 0xA9, 0x14, 0x00, 0x21, 0x83, 0xFF, 0x1C, 0x00, 0x27, 0xC9, 0x4F, 0x00, 0x30, 0x84, 0xEA, 0x60, 0x00, 0x78, 0x87, 0x0D, 0x00, 0x0C, 0xF5, 0x06, 0x00, 0x86, 0x21, 0x83, 0xD7, 0x3F, 0x00, 0x09, 0x97, 0x6B, 0x00, 0x1B, 0xD0, 0x3B, 0x00, 0x09, 0xD2, 0x40, 0x00, 0x1E, 0x96, 0x7C, 0x00, 0x30, 0x84, 0xFB, 0x20, 0x00, 0x7B, 0xD1, 0x2D, 0x67, 0x68, 0x78, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x8A, 0x19, 0xE6, 0xE6, 0xE9, 0xB3, 0xB4, 0xBC, 0x00, 0x86, 0x18, 0xDA, 0x5D, 0x00, 0x06, 0xD0, 0x50, 0x00, 0x1E, 0x8E, 0x3B, 0x00, 0x09, 0x8F, 0x72, 0x00, 0x1E, 0x27, 0x00, 0x2D, 0x85, 0x8B, 0x60, 0x00, 0x87, 0x28, 0xF3, 0x40, 0xCC, 0xCD, 0xD2, 0x00, 0x24, 0x82, 0xD1, 0x73, 0x00, 0x24, 0x85, 0x9B, 0x58, 0x00, 0x2D, 0x85, 0x9C, 0x20, 0x00, 0x78, 0x81, 0x84, 0x00, 0x41, 0x43, 0x56, 0x00, 0x18, 0x81, 0x6D, 0x4D, 0x4F, 0x62, 0x00, 0x86, 0x12, 0xDA, 0x5D, 0xCC, 0xCD, 0xD2, 0x00, 0x24, 0xD9, 0x65, 0x00, 0x09, 0x90, 0x43, 0x00, 0x1B, 0xE1, 0x22, 0x00, 0x21, 0x88, 0x20, 0x00, 0x09, 0xB9, 0x57, 0x00, 0x7B, 0x81, 0x94, 0x40, 0x00, 0x06, 0x82, 0xBA, 0x7D, 0x00, 0x12, 0x81, 0x73, 0x00, 0x06, 0x81, 0x61, 0x00, 0x84, 0x4C, 0xD2, 0x3D, 0x9A, 0x9B, 0xA5, 0x00, 0x81, 0x43, 0x81, 0xA2, 0x48, 0x00, 0x2A, 0x9E, 0x78, 0x00, 0x0C, 0x87, 0x5E, 0x00, 0x15, 0xA1, 0x09, 0x00, 0x1E, 0x88, 0x20, 0x00, 0x0C, 0x81, 0xAD, 0x56, 0x00, 0x78, 0x82, 0x38, 0x00, 0x06, 0xBB, 0x2C, 0x00, 0x18, 0x9A, 0x26, 0x00, 0x06, 0xA2, 0x19, 0x00, 0x84, 0x43, 0x81, 0xA6, 0x1C, 0x67, 0x68, 0x78, 0x00, 0x09, 0xA5, 0x5B, 0x00, 0x81, 0x6D, 0x95, 0x12, 0x00, 0x09, 0xA9, 0x4D, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0xA8, 0x5E, 0x00, 0x18, 0x88, 0x20, 0x41, 0x43, 0x56, 0x00, 0x09, 0x39, 0x00, 0x7E, 0x81, 0x9C, 0x5A, 0x00, 0x06, 0xAA, 0x69, 0x00, 0x18, 0x88, 0x02, 0x00, 0x06, 0xA2, 0x1C, 0x00, 0x84, 0x40, 0xB9, 0x63, 0x00, 0x0C, 0x85, 0xB3, 0x0A, 0x00, 0x81, 0x70, 0x83, 0xA2, 0x76, 0x41, 0x43, 0x56, 0x00, 0x0C, 0x81, 0xC5, 0x77, 0x00, 0x06, 0xC0, 0x46, 0x00, 0x1B, 0x88, 0x20, 0x41, 0x43, 0x56, 0x00, 0x0F, 0x84, 0x88, 0x0A, 0x00, 0x7E, 0x81, 0xA4, 0x77, 0x00, 0x06, 0x81, 0x3D, 0x00, 0x1E, 0x82, 0xC3, 0x4A, 0x00, 0x83, 0x45, 0xDA, 0x60, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x00, 0x75, 0x84, 0x70, 0x00, 0x09, 0x82, 0xF1, 0x2A, 0x00, 0x81, 0x76, 0x84, 0xB6, 0x6B, 0x00, 0x09, 0xB9, 0x6F, 0x00, 0x09, 0x82, 0x02, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0xD1, 0x0C, 0x00, 0x06, 0x92, 0x54, 0x9A, 0x9B, 0xA5, 0x00, 0x06, 0xC8, 0x7B, 0x00, 0x0F, 0x27, 0x00, 0x81, 0x01, 0x81, 0xAD, 0x14, 0x00, 0x83, 0x69, 0x88, 0x20, 0x00, 0x81, 0x01, 0x81, 0xDB, 0x4E, 0x00, 0x0C, 0x85, 0x7D, 0x00, 0x81, 0x73, 0x81, 0xB3, 0x0B, 0x67, 0x68, 0x78, 0x00, 0x0F, 0x81, 0xDE, 0x57, 0x00, 0x1E, 0x82, 0xD2, 0x08, 0xC0, 0xC0, 0xC7, 0x00, 0x81, 0x04, 0xD9, 0x38, 0x00, 0x1E, 0xA0, 0x62, 0x00, 0x06, 0xA9, 0x23, 0x00, 0x83, 0x45, 0xCA, 0x26, 0x00, 0x81, 0x01, 0x88, 0x20, 0x00, 0x0C, 0x85, 0xDC, 0x2A, 0x00, 0x81, 0x79, 0xAD, 0x75, 0x73, 0x75, 0x83, 0x00, 0x0C, 0xA0, 0x59, 0x00, 0x12, 0x88, 0x17, 0xF2, 0xF2, 0xF4, 0xB3, 0xB4, 0xBC, 0x00, 0x81, 0x0A, 0xA7, 0x72, 0x00, 0x06, 0x93, 0x79, 0x00, 0x18, 0x83, 0x30, 0x00, 0x06, 0x81, 0x4C, 0x00, 0x83, 0x45, 0x81, 0x9C, 0x63, 0x00, 0x81, 0x01, 0x88, 0x20, 0x00, 0x09, 0x84, 0xF9, 0x36, 0x00, 0x24, 0x85, 0xB3, 0x19, 0x00, 0x81, 0x64, 0x90, 0x4F, 0x8D, 0x8E, 0x9A, 0x00, 0x09, 0x9B, 0x75, 0x00, 0x06, 0x9B, 0x78, 0x00, 0x81, 0x16, 0xB0, 0x09, 0x00, 0x15, 0xE2, 0x68, 0x41, 0x43, 0x56, 0x00, 0x09, 0x84, 0xB2, 0x3D, 0x00, 0x83, 0x4E, 0x82, 0xE8, 0x12, 0x00, 0x7B, 0x9C, 0x2E, 0x00, 0x0C, 0x98, 0x63, 0x00, 0x83, 0x2A, 0xEF, 0x75, 0x00, 0x09, 0xED, 0x0D, 0x00, 0x06, 0x83, 0x85, 0x1D, 0x9A, 0x9B, 0xA5, 0xB3, 0xB4, 0xBC, 0x00, 0x09, 0xE5, 0x02, 0x00, 0x83, 0x48, 0xB9, 0x5D, 0x00, 0x81, 0x10, 0x88, 0x20, 0x00, 0x83, 0x2D, 0xDF, 0x3E, 0x00, 0x15, 0x81, 0xF8, 0x7D, 0x00, 0x12, 0x85, 0xF8, 0x4F, 0x00, 0x84, 0x40, 0x88, 0x20, 0x00, 0x09, 0xC8, 0x30, 0x00, 0x83, 0x36, 0x81, 0xCB, 0x6B, 0x4D, 0x4F, 0x62, 0x80, 0x81, 0x8F, 0x9A, 0x9B, 0xA5, 0x8D, 0x8E, 0x9A, 0x00, 0x83, 0x51, 0x81, 0x83, 0x74, 0x00, 0x84, 0x43, 0x88, 0x20, 0x00, 0x83, 0x66, 0x83, 0x89, 0x12, 0x00, 0x84, 0x2E, 0x98, 0x60, 0x00, 0x21, 0xC2, 0x00, 0x00, 0x84, 0x4C, 0x88, 0x20, 0x00, 0x0C, 0xC0, 0x01, 0x00, 0x83, 0x27, 0x88, 0x20, 0x00, 0x06, 0xCB, 0x5A, 0x00, 0x83, 0x63, 0x81, 0x9C, 0x42, 0x00, 0x81, 0x0D, 0xB9, 0x60, 0x00, 0x83, 0x2A, 0xE7, 0x55, 0x00, 0x06, 0x83, 0xCF, 0x46, 0xD9, 0xD9, 0xDD, 0x00, 0x83, 0x60, 0xFB, 0x48, 0x00, 0x81, 0x0D, 0xCA, 0x20, 0x00, 0x83, 0x2A, 0x95, 0x33, 0x4D, 0x4F, 0x62, 0x00, 0x06, 0xF4, 0x47, 0x00, 0x06, 0xDC, 0x05, 0x00, 0x15, 0x83, 0x9D, 0x53, 0x00, 0x83, 0x45, 0x90, 0x5E, 0x00, 0x81, 0x01, 0x88, 0x20, 0x00, 0x06, 0xBE, 0x32, 0x00, 0x83, 0x30, 0x82, 0xB7, 0x32, 0x00, 0x0C, 0xAC, 0x53, 0x00, 0x18, 0xD3, 0x74, 0x00, 0x83, 0x45, 0x84, 0x91, 0x67, 0x00, 0x7E, 0x87, 0x1C, 0x00, 0x0F, 0x81, 0xA9, 0x61, 0x00, 0x83, 0x2A, 0x81, 0xC2, 0x32, 0x00, 0x06, 0x81, 0xFF, 0x57, 0x00, 0x1E, 0x83, 0xC6, 0x73, 0x00, 0x83, 0x45, 0x82, 0x99, 0x59, 0x00, 0x78, 0x88, 0x20, 0x00, 0x09, 0xD7, 0x09, 0x00, 0x81, 0x7C, 0xF3, 0x40, 0x00, 0x86, 0x15, 0xB9, 0x60, 0x00, 0x06, 0x81, 0xFC, 0x0F, 0x00, 0x12, 0x83, 0xD4, 0x18, 0x00, 0x81, 0x7C, 0x95, 0x0F, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0xE2, 0x77, 0x00, 0x06, 0x82, 0xC1, 0x60, 0x00, 0x84, 0x67, 0x83, 0xD6, 0x20, 0x00, 0x21, 0x94, 0x08, 0x00, 0x0F, 0x81, 0x80, 0x7D, 0x00, 0x33, 0x85, 0x1A, 0x00, 0x2D, 0x2D, 0x00, 0x18, 0x85, 0x89, 0x46, 0x00, 0x81, 0x76, 0xE7, 0x4F, 0x4D, 0x4F, 0x62, 0xB3, 0xB4, 0xBC, 0x00, 0x2D, 0x85, 0x94, 0x00, 0x00, 0x84, 0x4F, 0x83, 0xCE, 0x00, 0x00, 0x24, 0xA4, 0x48, 0x00, 0x5A, 0x83, 0xD3, 0x35, 0x00, 0x27, 0x27, 0x00, 0x81, 0x76, 0xB6, 0x27, 0x00, 0x4E, 0x83, 0x1B, 0x00, 0x84, 0x37, 0xA9, 0x20, 0x00, 0x81, 0x22, 0x88, 0x20, 0xCC, 0xCD, 0xD2, 0x00, 0x81, 0x73, 0x88, 0x1D, 0x00, 0x12, 0xA2, 0x7C, 0x00, 0x06, 0x85, 0xAC, 0x5D, 0x00, 0x18, 0xB8, 0x2C, 0x00, 0x81, 0x10, 0x83, 0xD6, 0x20, 0x00, 0x84, 0x64, 0x88, 0x20, 0x00, 0x06, 0x85, 0xA2, 0x11, 0x00, 0x81, 0x7F, 0x82, 0xD2, 0x1D, 0xD9, 0xD9, 0xDD, 0x00, 0x81, 0x4C, 0x81, 0x8A, 0x48, 0x41, 0x43, 0x56, 0x00, 0x06, 0x84, 0x89, 0x3B, 0x00, 0x83, 0x27, 0xB1, 0x3D, 0x00, 0x81, 0x13, 0x88, 0x20, 0x00, 0x06, 0x82, 0xE8, 0x63, 0x00, 0x81, 0x79, 0x81, 0x90, 0x5D, 0x00, 0x0C, 0x81, 0xA6, 0x73, 0x00, 0x81, 0x58, 0x81, 0xB3, 0x62, 0x00, 0x06, 0xCD, 0x74, 0x00, 0x83, 0x45, 0xEE, 0x6B, 0x00, 0x82, 0x71, 0xC9, 0x1C, 0x00, 0x09, 0xCC, 0x10, 0x00, 0x81, 0x5E, 0x81, 0xBB, 0x7F, 0x00, 0x84, 0x49, 0x81, 0xA5, 0x00, 0x00, 0x81, 0x76, 0x82, 0x88, 0x1E, 0x00, 0x81, 0x61, 0x82, 0x6E, 0x00, 0x84, 0x49, 0x81, 0xB5, 0x40, 0x00, 0x81, 0x76, 0x81, 0xF7, 0x64, 0x00, 0x81, 0x5E, 0x96, 0x7C, 0x00, 0x06, 0x81, 0xD6, 0x5E, 0x00, 0x83, 0x45, 0x81, 0xDE, 0x63, 0x00, 0x82, 0x6E, 0x88, 0x20, 0x00, 0x81, 0x64, 0x82, 0xEA, 0x32, 0x73, 0x75, 0x83, 0x00, 0x06, 0x81, 0x67, 0x00, 0x84, 0x3D, 0xDA, 0x60, 0x00, 0x83, 0x3F, 0x84, 0xDA, 0x1D, 0x00, 0x21, 0xAD, 0x78, 0x00, 0x83, 0x48, 0x82, 0x90, 0x23, 0x00, 0x82, 0x6B, 0x88, 0x20, 0x00, 0x81, 0x4C, 0x85, 0x83, 0x40, 0x00, 0x1B, 0x88, 0x20, 0x00, 0x83, 0x4E, 0x85, 0x95, 0x61, 0x00, 0x82, 0x74, 0x88, 0x20, 0x00, 0x85, 0x2C, 0x81, 0xA6, 0x64, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x84, 0x43, 0x88, 0x20, 0x00, 0x09, 0x81, 0xBD, 0x60, 0x73, 0x75, 0x83, 0x00, 0x83, 0x51, 0x81, 0xA5, 0x12, 0x00, 0x09, 0xDF, 0x41, 0x00, 0x82, 0x62, 0x81, 0xA3, 0x79, 0x00, 0x09, 0x82, 0x98, 0x3A, 0x00, 0x81, 0x49, 0xDC, 0x56, 0x00, 0x0F, 0x82, 0x89, 0x10, 0x00, 0x09, 0x81, 0xEA, 0x45, 0x00, 0x86, 0x39, 0x81, 0x87, 0x48, 0x00, 0x81, 0x4C, 0xD2, 0x3A, 0x00, 0x0C, 0x84, 0xFC, 0x69, 0x00, 0x06, 0x81, 0xDE, 0x60, 0xA6, 0xA7, 0xB0, 0x00, 0x21, 0x82, 0xC3, 0x62, 0x00, 0x86, 0x21, 0x82, 0xB1, 0x44, 0x00, 0x81, 0x49, 0x81, 0x85, 0x6D, 0x00, 0x06, 0x81, 0x4C, 0x00, 0x33, 0x83, 0xBE, 0x7D, 0x00, 0x86, 0x24, 0x83, 0xBD, 0x3A, 0x00, 0x81, 0x40, 0x8E, 0x5F, 0x00, 0x24, 0x81, 0xFF, 0x60, 0x00, 0x86, 0x33, 0x81, 0xDA, 0x0B, 0x00, 0x09, 0xCA, 0x23, 0x00, 0x81, 0x40, 0xC2, 0x03, 0x00, 0x1E, 0x82, 0xA9, 0x00, 0x00, 0x06, 0xA2, 0x6A, 0x00, 0x86, 0x12, 0x82, 0xE2, 0x63, 0x00, 0x2A, 0x81, 0x83, 0x7D, 0x00, 0x81, 0x40, 0x9F, 0x22, 0x00, 0x81, 0x3D, 0x82, 0xA0, 0x60, 0x00, 0x06, 0x81, 0x85, 0x25, 0xB3, 0xB4, 0xBC, 0x00, 0x09, 0x81, 0xDB, 0x39, 0xFE, 0xFF, 0xFF, 0xF0, 0xF1, 0xF3, 0xCA, 0xCB, 0xD1, 0x97, 0x99, 0xA4, 0x65, 0x67, 0x78, 0x40, 0x42, 0x00, 0x84, 0x7A, 0xAA, 0x60, 0x00, 0x09, 0xA7, 0x57, 0x00, 0x81, 0x3D, 0x81, 0x9E, 0x56, 0x00, 0x81, 0x37, 0x88, 0x20, 0x00, 0x06, 0x81, 0xA7, 0x71, 0x00, 0x12, 0xD3, 0x74, 0xFE, 0xFF, 0xFF, 0xFD, 0xFE, 0xFE, 0xFC, 0xFD, 0xFE, 0xFB, 0xFC, 0xFD, 0xFA, 0xFC, 0xFD, 0xF9, 0xFB, 0xFD, 0xD2, 0xD5, 0xDB, 0xAD, 0xB0, 0xBA, 0x7C, 0x7F, 0x8D, 0x4C, 0x4E, 0x61, 0x00, 0x84, 0x79, 0x83, 0x84, 0x04, 0x00, 0x81, 0x3A, 0x88, 0x23, 0x00, 0x24, 0x82, 0xC1, 0x60, 0x00, 0x81, 0x10, 0xE3, 0x03, 0x00, 0x12, 0x83, 0xFA, 0x0E, 0x00, 0x1B, 0x88, 0x20, 0xF7, 0xFA, 0xFC, 0xF6, 0xF9, 0xFC, 0xF5, 0xF9, 0xFB, 0xF4, 0xF8, 0xFB, 0xE7, 0xEB, 0xEF, 0xB6, 0xBA, 0xC3, 0x87, 0x8A, 0x97, 0x63, 0x66, 0x77, 0x00, 0x84, 0x73, 0x88, 0x23, 0x00, 0x81, 0x34, 0xA7, 0x48, 0x00, 0x1E, 0xFB, 0x42, 0x00, 0x81, 0x10, 0x82, 0xA9, 0x00, 0x00, 0x12, 0x81, 0xCA, 0x6D, 0x00, 0x2D, 0x88, 0x20, 0xF3, 0xF7, 0xFA, 0xF2, 0xF6, 0xFA, 0xF1, 0xF6, 0xFA, 0xF0, 0xF5, 0xF9, 0xEE, 0xF4, 0xF9, 0xBF, 0xC4, 0xCD, 0x9B, 0xA0, 0xAC, 0x6D, 0x71, 0x81, 0x3F, 0x00, 0x84, 0x5D, 0x99, 0x07, 0x00, 0x09, 0xFA, 0x08, 0x00, 0x06, 0x86, 0x69, 0x00, 0x81, 0x31, 0x81, 0x9E, 0x71, 0x00, 0x1E, 0xB9, 0x60, 0x00, 0x81, 0x0A, 0xBB, 0x44, 0x4D, 0x4F, 0x62, 0x00, 0x21, 0x82, 0xBC, 0x22, 0x00, 0x2D, 0x88, 0x20, 0xED, 0xF4, 0xF8, 0xEC, 0xF3, 0xF8, 0xEB, 0xF2, 0xF8, 0xEA, 0xF1, 0xF7, 0xD2, 0xD9, 0xE1, 0xA4, 0xAA, 0xB6, 0x82, 0x87, 0x96, 0x55, 0x59, 0x6B, 0x00, 0x84, 0x1F, 0x90, 0x10, 0x00, 0x0C, 0x82, 0xB0, 0x55, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x06, 0xC8, 0x51, 0x00, 0x0F, 0x81, 0xC5, 0x7D, 0x00, 0x06, 0x81, 0xC8, 0x26, 0x00, 0x06, 0xC8, 0x6F, 0x00, 0x2D, 0x4B, 0x00, 0x81, 0x10, 0xCA, 0x20, 0x00, 0x81, 0x07, 0xD7, 0x0F, 0x67, 0x68, 0x78, 0x00, 0x24, 0x81, 0xC8, 0x5F, 0x00, 0x39, 0x88, 0x20, 0xE9, 0xF1, 0xF7, 0xE8, 0xF0, 0xF6, 0xE7, 0xEF, 0xF6, 0xE5, 0xEE, 0xF5, 0xD9, 0xE2, 0xEA, 0xB7, 0xBF, 0xCA, 0x8B, 0x91, 0xA0, 0x5F, 0x63, 0x75, 0x00, 0x84, 0x16, 0xC9, 0x79, 0x00, 0x7B, 0x81, 0xAF, 0x76, 0x00, 0x81, 0x04, 0x82, 0xDC, 0x06, 0x00, 0x81, 0x10, 0x82, 0xA9, 0x00, 0x00, 0x1B, 0xA0, 0x71, 0x00, 0x54, 0x88, 0x20, 0xE4, 0xEE, 0xF5, 0xE3, 0xED, 0xF5, 0xE2, 0xEC, 0xF4, 0xE1, 0xEC, 0xF4, 0xE0, 0xEB, 0xF3, 0xBF, 0xC8, 0xD4, 0x93, 0x9B, 0xA9, 0x73, 0x79, 0x8A, 0x49, 0x4C, 0x60, 0x00, 0x81, 0x70, 0x82, 0xA4, 0x6D, 0x00, 0x06, 0x82, 0xD7, 0x55, 0x00, 0x1B, 0x85, 0xB2, 0x3C, 0xA6, 0xA7, 0xB0, 0x73, 0x75, 0x83, 0x00, 0x81, 0x6A, 0xDF, 0x08, 0x00, 0x81, 0x76, 0x88, 0x20, 0x00, 0x0F, 0xEB, 0x20, 0x80, 0x81, 0x8F, 0x00, 0x81, 0x07, 0x88, 0x1A, 0x00, 0x21, 0xA0, 0x71, 0x00, 0x63, 0x88, 0x20, 0xDF, 0xEA, 0xF3, 0xDD, 0xE9, 0xF2, 0xDC, 0xE9, 0xF2, 0xDB, 0xE8, 0xF2, 0xC5, 0xD1, 0xDC, 0xA5, 0xAF, 0xBD, 0x7C, 0x83, 0x93, 0x5D, 0x62, 0x74, 0x00, 0x81, 0x58, 0x82, 0xE8, 0x30, 0x80, 0x81, 0x8F, 0x00, 0x2D, 0x82, 0xD7, 0x6A, 0x00, 0x0C, 0x81, 0x88, 0x2E, 0x00, 0x81, 0x61, 0x88, 0x29, 0x00, 0x36, 0x98, 0x60, 0x00, 0x33, 0x33, 0x00, 0x81, 0x0A, 0x98, 0x60, 0x00, 0x81, 0x1C, 0x8D, 0x43, 0x00, 0x30, 0x85, 0x29, 0x00, 0x60, 0x88, 0x20, 0xDA, 0xE7, 0xF1, 0xD9, 0xE6, 0xF1, 0xD8, 0xE6, 0xF0, 0xD7, 0xE5, 0xF0, 0xD6, 0xE4, 0xEF, 0xAC, 0xB8, 0xC6, 0x84, 0x8C, 0x9D, 0x65, 0x6C, 0x7E, 0x3E, 0x41, 0x55, 0x00, 0x81, 0x43, 0x88, 0x1A, 0x00, 0x15, 0x81, 0xEE, 0x4F, 0x00, 0x2D, 0x83, 0x00, 0xF2, 0xF2, 0xF4, 0x9A, 0x9B, 0xA5, 0x00, 0x83, 0x48, 0xEF, 0x57, 0x00, 0x15, 0x83, 0x48, 0x00, 0x06, 0x82, 0x90, 0x32, 0x00, 0x06, 0xFB, 0x66, 0x00, 0x81, 0x22, 0xA0, 0x71, 0x00, 0x7E, 0x88, 0x20, 0xD4, 0xE4, 0xEF, 0xD3, 0xE3, 0xEF, 0xD2, 0xE2, 0xEE, 0xD1, 0xE1, 0xEE, 0xB3, 0xC1, 0xCF, 0x95, 0xA0, 0xB0, 0x6E, 0x75, 0x88, 0x51, 0x56, 0x69, 0x00, 0x81, 0x3A, 0x85, 0xDB, 0x47, 0x00, 0x45, 0x96, 0x04, 0x00, 0x15, 0x83, 0x81, 0x4C, 0x00, 0x83, 0x30, 0x83, 0xBF, 0x21, 0x00, 0x06, 0x84, 0xB2, 0x2B, 0x00, 0x1E, 0x84, 0x28, 0xE6, 0xE6, 0xE9, 0x00, 0x75, 0xA9, 0x20, 0x00, 0x2A, 0xA0, 0x71, 0x00, 0x81, 0x0A, 0x88, 0x20, 0xD0, 0xE1, 0xED, 0xCF, 0xE0, 0xED, 0xCE, 0xDF, 0xED, 0xCD, 0xDE, 0xEC, 0xC2, 0xD3, 0xE2, 0x9B, 0xA9, 0xB9, 0x7F, 0x89, 0x9B, 0x59, 0x5F, 0x73, 0x00, 0x81, 0x34, 0xFF, 0x5B, 0x00, 0x15, 0x98, 0x3F, 0x00, 0x18, 0x81, 0xF8, 0x11, 0x00, 0x1B, 0x82, 0xF0, 0x62, 0x00, 0x83, 0x36, 0x90, 0x49, 0x00, 0x09, 0xB1, 0x31, 0x00, 0x0F, 0x81, 0x85, 0x40, 0x00, 0x09, 0x81, 0x8D, 0x78, 0xB3, 0xB4, 0xBC, 0x00, 0x0C, 0x82, 0xFC, 0x7D, 0x00, 0x6C, 0x83, 0x66, 0x00, 0x30, 0xA0, 0x71, 0x00, 0x81, 0x16, 0x88, 0x20, 0xCB, 0xDE, 0xEC, 0xCA, 0xDD, 0xEB, 0xC9, 0xDC, 0xEB, 0xC8, 0xDC, 0xEA, 0xB4, 0xC6, 0xD6, 0x7D, 0x88, 0x9A, 0x3D, 0x40, 0x00, 0x81, 0x14, 0x99, 0x01, 0x00, 0x06, 0x8C, 0x27, 0x00, 0x1B, 0x82, 0xF0, 0x29, 0x00, 0x1E, 0x81, 0x90, 0x2A, 0x00, 0x06, 0xA5, 0x31, 0x00, 0x1B, 0x81, 0xFD, 0x3A, 0xD9, 0xD9, 0xDD, 0x00, 0x83, 0x33, 0x82, 0xDF, 0x00, 0x00, 0x06, 0x87, 0x01, 0x00, 0x12, 0x81, 0x8D, 0x5D, 0x00, 0x06, 0x84, 0x2B, 0x00, 0x0C, 0x90, 0x55, 0x00, 0x06, 0xC2, 0x03, 0x00, 0x69, 0x81, 0xAD, 0x26, 0x00, 0x33, 0xA0, 0x71, 0x00, 0x81, 0x22, 0x88, 0x20, 0xC7, 0xDB, 0xEA, 0xC6, 0xDA, 0xEA, 0xB3, 0xC5, 0xD5, 0x58, 0x00, 0x81, 0x0F, 0x90, 0x4C, 0x00, 0x09, 0x82, 0xE6, 0x58, 0x00, 0x45, 0x81, 0xB1, 0x18, 0x80, 0x81, 0x8F, 0x00, 0x15, 0x88, 0x6B, 0x00, 0x83, 0x33, 0x82, 0xE7, 0x23, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0x81, 0xC7, 0x3A, 0x00, 0x06, 0xD4, 0x09, 0x00, 0x0F, 0xDA, 0x4B, 0x00, 0x06, 0x82, 0xBD, 0x14, 0x00, 0x66, 0x81, 0xCE, 0x20, 0x00, 0x36, 0xA0, 0x71, 0x00, 0x81, 0x28, 0x88, 0x20, 0xC5, 0xD9, 0xE9, 0xC4, 0xD9, 0xE9, 0x72, 0x7D, 0x90, 0x00, 0x81, 0x1C, 0x88, 0x1D, 0xE6, 0xE6, 0xE9, 0x00, 0x3F, 0xA0, 0x38, 0x00, 0x15, 0xA1, 0x48, 0x00, 0x83, 0x30, 0x88, 0x23, 0x00, 0x15, 0xEA, 0x73, 0x00, 0x18, 0x83, 0xE6, 0x4B, 0x00, 0x66, 0xEB, 0x20, 0x00, 0x39, 0xA0, 0x71, 0x00, 0x81, 0x2E, 0x88, 0x20, 0xC2, 0xD8, 0xE8, 0x8C, 0x9B, 0xAD, 0x00, 0x81, 0x10, 0x83, 0xA3, 0x71, 0x00, 0x09, 0x9C, 0x55, 0x00, 0x45, 0x9C, 0x49, 0x00, 0x15, 0xA1, 0x51, 0x00, 0x81, 0x70, 0x83, 0xAC, 0x77, 0x00, 0x81, 0x4F, 0x88, 0x20, 0x00, 0x1B, 0xE3, 0x06, 0x00, 0x60, 0x88, 0x20, 0x00, 0x3F, 0xA0, 0x71, 0x00, 0x81, 0x31, 0x88, 0x20, 0xC1, 0xD7, 0xE8, 0x72, 0x7C, 0x00, 0x7F, 0x90, 0x46, 0x00, 0x12, 0xA8, 0x5E, 0x00, 0x51, 0x9C, 0x43, 0x00, 0x12, 0x81, 0xCA, 0x58, 0x00, 0x83, 0x2A, 0x81, 0xE3, 0x26, 0x00, 0x06, 0x8B, 0x5F, 0x00, 0x09, 0x93, 0x73, 0x00, 0x09, 0x83, 0xE8, 0x50, 0x00, 0x12, 0xEC, 0x60, 0x00, 0x06, 0x98, 0x75, 0x00, 0x5A, 0xC3, 0x16, 0x00, 0x42, 0xA0, 0x71, 0x00, 0x81, 0x34, 0x88, 0x20, 0xC0, 0xD6, 0xE7, 0x4E, 0x54, 0x68, 0x00, 0x81, 0x0A, 0xD5, 0x0D, 0x00, 0x57, 0xA4, 0x60, 0x00, 0x0F, 0x82, 0xD2, 0x11, 0x00, 0x83, 0x2A, 0x82, 0xC1, 0x57, 0x00, 0x06, 0x90, 0x2E, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0xE2, 0x6E, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x12, 0x81, 0x94, 0x25, 0x00, 0x09, 0x9D, 0x23, 0x00, 0x57, 0xD2, 0x4C, 0x00, 0x0C, 0xED, 0x58, 0x00, 0x81, 0x70, 0x88, 0x20, 0x9C, 0xAE, 0xC0, 0x00, 0x7E, 0xB5, 0x3B, 0x00, 0x66, 0x83, 0xAC, 0x0B, 0x00, 0x0F, 0x90, 0x46, 0x00, 0x83, 0x2A, 0x82, 0xC1, 0x5A, 0x00, 0x0F, 0x8B, 0x5C, 0x00, 0x12, 0xBD, 0x2B, 0x00, 0x2A, 0x84, 0x89, 0x44, 0x00, 0x81, 0x0D, 0x82, 0x95, 0x70, 0x00, 0x81, 0x28, 0x88, 0x20, 0xAD, 0xC6, 0xE1, 0x4C, 0x54, 0x6E, 0x00, 0x81, 0x01, 0x82, 0xA6, 0x0F, 0x00, 0x63, 0x81, 0x87, 0x5A, 0x00, 0x0F, 0xA1, 0x0C, 0x00, 0x83, 0x2A, 0x82, 0xD6, 0x6C, 0x00, 0x09, 0xD2, 0x28, 0x00, 0x18, 0xAC, 0x5C, 0x00, 0x57, 0x82, 0xA2, 0x32, 0x00, 0x27, 0xC7, 0x11, 0x00, 0x81, 0x58, 0x88, 0x20, 0xBE, 0xD4, 0xE7, 0x98, 0xB4, 0xD9, 0x84, 0xA3, 0xD3, 0x70, 0x87, 0xB1, 0x00, 0x78, 0x81, 0xAA, 0x35, 0x00, 0x6C, 0xA8, 0x34, 0x00, 0x0F, 0xAA, 0x0C, 0x00, 0x82, 0x0B, 0x90, 0x43, 0x4D, 0x4F, 0x62, 0x00, 0x82, 0x11, 0x82, 0xE9, 0x46, 0x5A, 0x5C, 0x6D, 0x00, 0x4E, 0xA0, 0x71, 0x00, 0x81, 0x2E, 0x88, 0x20, 0xB0, 0xC8, 0xE2, 0x89, 0xA8, 0xD4, 0x84, 0xA3, 0xD3, 0x84, 0xA2, 0xD3, 0x83, 0xA1, 0xD2, 0x48, 0x50, 0x00, 0x6D, 0xB7, 0x76, 0x00, 0x0F, 0x83, 0xCB, 0x06, 0x00, 0x69, 0x81, 0x91, 0x4F, 0x00, 0x0F, 0xA1, 0x72, 0x00, 0x81, 0x7C, 0xA1, 0x06, 0x00, 0x06, 0xED, 0x7F, 0x00, 0x1B, 0x8E, 0x20, 0xC0, 0xC0, 0xC7, 0x00, 0x81, 0x64, 0xED, 0x67, 0x00, 0x69, 0xA0, 0x71, 0x00, 0x81, 0x28, 0x88, 0x20, 0xC1, 0xD6, 0xE8, 0x9D, 0xBA, 0xDC, 0x86, 0xA6, 0xD4, 0x85, 0xA4, 0xD3, 0x84, 0xA3, 0xD3, 0x83, 0xA2, 0xD2, 0x83, 0xA0, 0xD2, 0x65, 0x78, 0x9F, 0x00, 0x72, 0x82, 0x8D, 0x35, 0x00, 0x75, 0x81, 0xE7, 0x06, 0x00, 0x0C, 0xCA, 0x3B, 0x00, 0x81, 0x76, 0x84, 0x85, 0x28, 0x00, 0x2D, 0xED, 0x7F, 0x00, 0x81, 0x73, 0xED, 0x67, 0x00, 0x66, 0x82, 0xB6, 0x61, 0x00, 0x81, 0x16, 0x88, 0x20, 0xBA, 0xD1, 0xE6, 0x8E, 0xAD, 0xD7, 0x86, 0xA6, 0xD4, 0x85, 0xA5, 0xD3, 0x00, 0x09, 0x90, 0x3D, 0x82, 0x9F, 0xD2, 0x82, 0x9E, 0xD1, 0x3E, 0x43, 0x5C, 0x00, 0x72, 0x82, 0xB6, 0x4F, 0x00, 0x72, 0x81, 0xA0, 0x34, 0x00, 0x0F, 0xA5, 0x70, 0x00, 0x81, 0x70, 0xCA, 0x2F, 0x00, 0x09, 0x83, 0xF0, 0x7F, 0x00, 0x12, 0x81, 0x86, 0x41, 0x00, 0x1B, 0x82, 0xDC, 0x72, 0xE6, 0xE6, 0xE9, 0x00, 0x81, 0x64, 0x81, 0xCC, 0x7B, 0x00, 0x5D, 0xA0, 0x71, 0x00, 0x81, 0x22, 0x88, 0x20, 0xAB, 0xC5, 0xE1, 0x87, 0xA8, 0xD4, 0x86, 0xA7, 0xD4, 0x85, 0xA5, 0xD3, 0x00, 0x07, 0x90, 0x3D, 0xA1, 0xD2, 0x83, 0xA0, 0xD2, 0x82, 0x9F, 0xD2, 0x81, 0x9D, 0xD1, 0x64, 0x76, 0x00, 0x67, 0x90, 0x43, 0x00, 0x0C, 0x98, 0x5D, 0x00, 0x72, 0x83, 0xCC, 0x7F, 0x00, 0x0F, 0x83, 0x94, 0x1D, 0x00, 0x81, 0x6D, 0x98, 0x63, 0x00, 0x0F, 0x8A, 0x1C, 0x00, 0x06, 0xDD, 0x3F, 0x00, 0x15, 0xA0, 0x6E, 0x00, 0x06, 0xA8, 0x13, 0x00, 0x0F, 0x88, 0x4A, 0x00, 0x81, 0x5E, 0x82, 0x8F, 0x04, 0x00, 0x60, 0xA0, 0x71, 0x00, 0x81, 0x1C, 0x88, 0x20, 0xC5, 0xD9, 0xEA, 0x9C, 0xB9, 0xDC, 0x87, 0xA9, 0xD4, 0x86, 0xA7, 0xD4, 0x00, 0x0F, 0x98, 0x5A, 0x82, 0x9F, 0xD2, 0x81, 0x9E, 0xD1, 0x81, 0x9C, 0xD1, 0x80, 0x9B, 0xD1, 0x3D, 0x00, 0x65, 0x90, 0x43, 0x00, 0x0C, 0x83, 0x06, 0x00, 0x75, 0x81, 0xB9, 0x11, 0x00, 0x0C, 0x8C, 0x24, 0x00, 0x81, 0x6A, 0xCA, 0x2C, 0x00, 0x0C, 0x88, 0x1D, 0x00, 0x2A, 0x90, 0x10, 0x73, 0x75, 0x83, 0x00, 0x0C, 0x88, 0x26, 0x00, 0x81, 0x58, 0x88, 0x23, 0x00, 0x63, 0xA0, 0x71, 0x00, 0x81, 0x19, 0x88, 0x20, 0xBE, 0xD4, 0xE7, 0x94, 0xB3, 0xD9, 0x87, 0xA9, 0xD5, 0x00, 0x16, 0x90, 0x3D, 0x9E, 0xD1, 0x81, 0x9D, 0xD1, 0x80, 0x9C, 0xD1, 0x7F, 0x9A, 0xD0, 0x63, 0x74, 0x9E, 0x00, 0x6C, 0x82, 0x88, 0x00, 0x00, 0x78, 0x81, 0xB9, 0x11, 0x00, 0x0C, 0xA9, 0x26, 0x00, 0x81, 0x67, 0x83, 0xDE, 0x40, 0x00, 0x09, 0x81, 0xFF, 0x69, 0x00, 0x33, 0xDD, 0x3F, 0x00, 0x0F, 0x81, 0xA3, 0x73, 0x00, 0x81, 0x52, 0x9B, 0x12, 0x00, 0x75, 0x82, 0xD7, 0x52, 0x00, 0x81, 0x07, 0x88, 0x20, 0xB7, 0xCE, 0xE5, 0x8C, 0xAE, 0xD6, 0x88, 0xAA, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x1B, 0x90, 0x3D, 0x7F, 0x9A, 0xD0, 0x7F, 0x98, 0xD0, 0x3D, 0x42, 0x00, 0x5E, 0x90, 0x43, 0x00, 0x0C, 0x85, 0x29, 0x00, 0x0C, 0x84, 0xEE, 0x4F, 0x00, 0x75, 0x82, 0x8E, 0x36, 0x00, 0x7B, 0x81, 0x04, 0x00, 0x75, 0x84, 0xC1, 0x67, 0x00, 0x3C, 0x93, 0x31, 0x00, 0x09, 0xC5, 0x30, 0x00, 0x81, 0x4C, 0x82, 0xFD, 0x78, 0x00, 0x6C, 0xA0, 0x71, 0x00, 0x81, 0x13, 0x88, 0x20, 0xAF, 0xC9, 0xE2, 0x89, 0xAB, 0xD5, 0x88, 0xAA, 0xD5, 0x87, 0xA9, 0xD4, 0x87, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x11, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x7F, 0x99, 0xD0, 0x7E, 0x98, 0xD0, 0x62, 0x72, 0x00, 0x5E, 0x90, 0x43, 0x00, 0x0C, 0x87, 0x1C, 0x00, 0x7B, 0x8F, 0x3C, 0x00, 0x75, 0xBA, 0x5E, 0x00, 0x81, 0x01, 0x8E, 0x20, 0x00, 0x3C, 0x87, 0x5B, 0x00, 0x0C, 0x85, 0x92, 0x7C, 0x00, 0x81, 0x01, 0x98, 0x66, 0x00, 0x18, 0x82, 0xF4, 0x33, 0x00, 0x2D, 0xC3, 0x3A, 0x00, 0x6F, 0xA0, 0x71, 0x00, 0x81, 0x10, 0x88, 0x20, 0xA3, 0xC0, 0xDF, 0x89, 0xAC, 0xD5, 0x88, 0x00, 0x06, 0x88, 0x20, 0x00, 0x1A, 0xA9, 0x17, 0x80, 0x9C, 0xD1, 0x80, 0x9B, 0x00, 0x07, 0x88, 0x1D, 0x7E, 0x97, 0xCF, 0x78, 0x8F, 0xC7, 0x39, 0x3C, 0x53, 0x00, 0x66, 0x97, 0x5C, 0x00, 0x7B, 0x81, 0xE2, 0x2E, 0x00, 0x0C, 0x9C, 0x6D, 0x00, 0x81, 0x61, 0x88, 0x20, 0x00, 0x09, 0x81, 0x6D, 0x00, 0x3F, 0xC9, 0x79, 0x00, 0x09, 0x93, 0x7C, 0x00, 0x78, 0xBC, 0x18, 0x00, 0x21, 0xF2, 0x42, 0x00, 0x2A, 0xD6, 0x14, 0x00, 0x72, 0xA0, 0x71, 0x00, 0x81, 0x0A, 0x88, 0x20, 0xCB, 0xDD, 0xEC, 0x97, 0xB7, 0xDA, 0x89, 0xAD, 0xD6, 0x00, 0x1E, 0x90, 0x3D, 0x00, 0x0F, 0x98, 0x5A, 0x7E, 0x97, 0xCF, 0x7D, 0x96, 0xCF, 0x7C, 0x95, 0xCF, 0x58, 0x65, 0x8D, 0x00, 0x66, 0x9B, 0x6C, 0x00, 0x82, 0x65, 0x83, 0xD6, 0x20, 0x00, 0x09, 0xA9, 0x17, 0x00, 0x45, 0xAC, 0x0B, 0x00, 0x7B, 0x84, 0xD2, 0x00, 0x00, 0x0C, 0x91, 0x41, 0x00, 0x3F, 0x83, 0xAD, 0x00, 0x00, 0x81, 0x04, 0x82, 0xF8, 0x43, 0x00, 0x78, 0x88, 0x20, 0xC8, 0xDB, 0xEB, 0x97, 0xB8, 0xDA, 0x8A, 0xAD, 0xD6, 0x89, 0xAC, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x28, 0x90, 0x3D, 0x7D, 0x96, 0xCF, 0x7D, 0x95, 0xCF, 0x7C, 0x94, 0xCE, 0x77, 0x8D, 0xC6, 0x38, 0x00, 0x59, 0x90, 0x43, 0x00, 0x82, 0x71, 0x88, 0x20, 0x00, 0x09, 0x9E, 0x60, 0x00, 0x45, 0xDA, 0x36, 0x00, 0x27, 0x84, 0xD2, 0x4E, 0x00, 0x5A, 0x94, 0x7A, 0x00, 0x3F, 0x81, 0xF0, 0x60, 0x00, 0x7B, 0xA0, 0x71, 0x00, 0x81, 0x04, 0x88, 0x20, 0xC5, 0xD9, 0xEA, 0x8F, 0xB2, 0xD8, 0x8A, 0xAE, 0x00, 0x05, 0x88, 0x1D, 0x00, 0x0B, 0x98, 0x5A, 0x00, 0x21, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x7C, 0x93, 0xCE, 0x7B, 0x92, 0xCE, 0x57, 0x63, 0x8C, 0x00, 0x83, 0x48, 0x88, 0x20, 0x00, 0x09, 0x81, 0xFF, 0x5A, 0x00, 0x4E, 0xD5, 0x01, 0x00, 0x72, 0x98, 0x63, 0x00, 0x06, 0x83, 0x33, 0x00, 0x3C, 0x89, 0x66, 0x00, 0x0F, 0x85, 0xB5, 0x3F, 0x00, 0x81, 0x70, 0x88, 0x20, 0xC6, 0xD9, 0xEA, 0x90, 0xB3, 0xD8, 0x8A, 0xAE, 0xD6, 0x00, 0x0B, 0x90, 0x3D, 0x00, 0x28, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x7B, 0x92, 0xCE, 0x7B, 0x91, 0xCE, 0x76, 0x8A, 0xC5, 0x00, 0x57, 0x90, 0x43, 0x00, 0x82, 0x6E, 0x88, 0x20, 0x00, 0x09, 0xCC, 0x0D, 0x00, 0x4B, 0x82, 0x96, 0x59, 0x00, 0x78, 0x85, 0xB5, 0x00, 0x00, 0x3F, 0x83, 0xEF, 0x00, 0x00, 0x81, 0x0D, 0x88, 0x1D, 0x00, 0x72, 0x88, 0x20, 0xC7, 0xDA, 0xEB, 0x90, 0xB3, 0xD8, 0x8B, 0xAF, 0xD6, 0x00, 0x25, 0x90, 0x3D, 0x00, 0x11, 0xA9, 0x17, 0x00, 0x05, 0x88, 0x1D, 0x00, 0x05, 0x90, 0x3D, 0x91, 0xCE, 0x7A, 0x90, 0xCD, 0x79, 0x8F, 0xCD, 0x56, 0x62, 0x00, 0x55, 0x90, 0x43, 0x00, 0x0C, 0xDA, 0x5D, 0x00, 0x7B, 0x88, 0x20, 0x00, 0x81, 0x67, 0xB1, 0x40, 0x00, 0x09, 0xB4, 0x2E, 0x00, 0x4B, 0xD4, 0x27, 0x00, 0x78, 0x85, 0xB5, 0x00, 0x00, 0x06, 0xD6, 0x77, 0x00, 0x48, 0xFF, 0x5E, 0x00, 0x81, 0x6D, 0x88, 0x20, 0xBF, 0xD4, 0xE8, 0x90, 0xB4, 0x00, 0x08, 0x88, 0x1D, 0x00, 0x20, 0xA9, 0x17, 0x00, 0x10, 0x90, 0x3D, 0x00, 0x0E, 0x98, 0x5A, 0x7A, 0x91, 0xCE, 0x7A, 0x8F, 0xCD, 0x79, 0x8E, 0xCD, 0x74, 0x87, 0xC5, 0x00, 0x63, 0xC0, 0x7C, 0x00, 0x81, 0x04, 0x88, 0x20, 0x00, 0x81, 0x5B, 0xF9, 0x4F, 0x00, 0x54, 0x82, 0xD2, 0x20, 0x00, 0x78, 0x85, 0xB5, 0x00, 0x00, 0x06, 0x81, 0x80, 0x14, 0x00, 0x36, 0x89, 0x69, 0x00, 0x0F, 0x84, 0x76, 0x00, 0x81, 0x6D, 0x88, 0x20, 0xBB, 0xD2, 0xE7, 0x8C, 0xB1, 0xD7, 0x8B, 0xB0, 0xD6, 0x00, 0x0E, 0x98, 0x5A, 0x00, 0x2B, 0xB9, 0x54, 0x00, 0x10, 0x90, 0x3D, 0x8E, 0xCD, 0x78, 0x8D, 0xCD, 0x78, 0x8C, 0xCC, 0x4D, 0x56, 0x7B, 0x00, 0x81, 0x55, 0x87, 0x1C, 0x00, 0x81, 0x07, 0xC3, 0x04, 0x00, 0x81, 0x37, 0x88, 0x20, 0x00, 0x7B, 0x82, 0xDB, 0x14, 0x00, 0x06, 0x81, 0xB9, 0x14, 0x8D, 0x8E, 0x9A, 0x00, 0x30, 0xA9, 0x23, 0x00, 0x81, 0x01, 0x81, 0xF1, 0x4C, 0x00, 0x78, 0x88, 0x20, 0xBC, 0xD3, 0xE7, 0x8C, 0xB2, 0xD7, 0x8C, 0xB1, 0xD7, 0x00, 0x10, 0x90, 0x3D, 0x00, 0x35, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x78, 0x8D, 0xCD, 0x78, 0x8B, 0xCC, 0x6E, 0x7F, 0x00, 0x55, 0xAD, 0x24, 0x00, 0x0C, 0xDF, 0x50, 0x00, 0x81, 0x01, 0xDA, 0x60, 0x00, 0x81, 0x5E, 0x82, 0xC6, 0x35, 0x00, 0x54, 0x87, 0x4C, 0x00, 0x78, 0x85, 0xB5, 0x00, 0x00, 0x39, 0x83, 0xBD, 0x40, 0x00, 0x0F, 0xD7, 0x33, 0x00, 0x81, 0x6A, 0x88, 0x20, 0xCB, 0xDD, 0xEC, 0x91, 0xB5, 0xD9, 0x00, 0x27, 0x90, 0x3D, 0x00, 0x24, 0xA9, 0x17, 0x00, 0x0C, 0x90, 0x3D, 0x77, 0x8A, 0xCC, 0x76, 0x89, 0xCC, 0x4D, 0x55, 0x00, 0x52, 0x90, 0x43, 0x00, 0x0C, 0xC5, 0x63, 0x00, 0x81, 0x01, 0xEB, 0x20, 0x00, 0x81, 0x5E, 0x81, 0x9C, 0x66, 0x00, 0x54, 0x82, 0xC1, 0x5D, 0x00, 0x09, 0x87, 0x28, 0x00, 0x6F, 0xDD, 0x18, 0x00, 0x39, 0x88, 0x20, 0x00, 0x0F, 0x81, 0x91, 0x0D, 0x00, 0x81, 0x67, 0x88, 0x20, 0xCB, 0xDD, 0xEC, 0x91, 0xB6, 0xD9, 0x8C, 0xB2, 0xD7, 0x8B, 0xB0, 0x00, 0x08, 0x90, 0x3D, 0x00, 0x2C, 0xB9, 0x54, 0x00, 0x18, 0xA9, 0x17, 0x79, 0x8E, 0x00, 0x05, 0x88, 0x1D, 0x8B, 0x00, 0x05, 0x88, 0x20, 0x88, 0xCB, 0x6D, 0x7D, 0xBB, 0x00, 0x60, 0x84, 0xE1, 0x42, 0x00, 0x82, 0x5F, 0x84, 0x8F, 0x7D, 0x00, 0x51, 0x8B, 0x08, 0x00, 0x06, 0x8A, 0x5E, 0x00, 0x81, 0x2B, 0x9B, 0x18, 0x00, 0x81, 0x0D, 0xB1, 0x37, 0x00, 0x66, 0x88, 0x20, 0xCD, 0xDE, 0xED, 0x92, 0xB7, 0xD9, 0x00, 0x16, 0x98, 0x5A, 0x00, 0x38, 0xB9, 0x54, 0x00, 0x0C, 0x98, 0x5A, 0x00, 0x05, 0x90, 0x3D, 0xCB, 0x75, 0x87, 0xCB, 0x75, 0x86, 0xCB, 0x4C, 0x54, 0x00, 0x52, 0x90, 0x43, 0x00, 0x7B, 0x84, 0xEF, 0x56, 0x00, 0x0C, 0x8D, 0x07, 0x00, 0x81, 0x64, 0x81, 0x94, 0x40, 0x00, 0x15, 0x85, 0xCD, 0x78, 0x00, 0x42, 0x83, 0x3C, 0x00, 0x81, 0x2B, 0xFE, 0x18, 0x00, 0x81, 0x16, 0x83, 0xD3, 0x0B, 0x00, 0x5A, 0x88, 0x20, 0xD3, 0xE2, 0xEF, 0x92, 0xB7, 0xDA, 0x8D, 0xB3, 0xD7, 0x00, 0x10, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x11, 0x90, 0x3D, 0x75, 0x87, 0xCB, 0x74, 0x85, 0xCA, 0x6C, 0x7A, 0xBA, 0x00, 0x5D, 0x81, 0x8C, 0x23, 0x00, 0x6C, 0x87, 0x25, 0x00, 0x0F, 0x81, 0xAD, 0x23, 0x00, 0x81, 0x64, 0x81, 0x8C, 0x1D, 0x00, 0x09, 0xDA, 0x60, 0x00, 0x45, 0xA0, 0x2F, 0x00, 0x09, 0x4E, 0x00, 0x7E, 0xEB, 0x23, 0x67, 0x68, 0x78, 0x00, 0x27, 0x84, 0xF7, 0x40, 0x00, 0x0F, 0x81, 0xB2, 0x0A, 0x00, 0x81, 0x61, 0x88, 0x20, 0xD8, 0xE6, 0xF1, 0x9C, 0xBE, 0xDD, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x21, 0x90, 0x3D, 0x00, 0x36, 0xA9, 0x17, 0x00, 0x0C, 0x90, 0x3D, 0x74, 0x85, 0xCA, 0x73, 0x84, 0xCA, 0x48, 0x4E, 0x00, 0x4F, 0x81, 0xEF, 0x50, 0x00, 0x0F, 0x83, 0x36, 0x00, 0x69, 0x84, 0x6D, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x81, 0x67, 0x81, 0xB5, 0x40, 0x00, 0x09, 0x8A, 0x13, 0x00, 0x45, 0xAB, 0x0A, 0x00, 0x06, 0x97, 0x2C, 0x00, 0x7B, 0x98, 0x5D, 0x00, 0x0C, 0x81, 0x8D, 0x30, 0x00, 0x09, 0x81, 0x52, 0x73, 0x75, 0x83, 0x00, 0x18, 0x83, 0xEA, 0x34, 0x00, 0x81, 0x13, 0xB9, 0x5A, 0x00, 0x5A, 0x88, 0x20, 0xDA, 0xE7, 0xF1, 0x9D, 0xBF, 0xDD, 0x8D, 0xB4, 0xD8, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x2F, 0xB9, 0x54, 0x00, 0x2A, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x74, 0x84, 0xCA, 0x73, 0x83, 0xCA, 0x63, 0x6E, 0xAA, 0x00, 0x60, 0x81, 0x9C, 0x66, 0x00, 0x63, 0x87, 0x2B, 0x00, 0x0F, 0x81, 0xCF, 0x12, 0x00, 0x81, 0x6A, 0x81, 0xC6, 0x00, 0x00, 0x09, 0x8A, 0x16, 0x00, 0x3F, 0xB4, 0x2E, 0x00, 0x09, 0xB3, 0x78, 0x00, 0x78, 0x82, 0x3B, 0x00, 0x06, 0x91, 0x3E, 0x00, 0x06, 0x82, 0x83, 0x70, 0x00, 0x0C, 0x84, 0x88, 0x64, 0x00, 0x06, 0x18, 0x00, 0x15, 0x99, 0x73, 0x00, 0x81, 0x6D, 0x88, 0x20, 0xAC, 0xC9, 0xE2, 0x8D, 0xB4, 0xD8, 0x00, 0x13, 0x98, 0x5A, 0x00, 0x3C, 0xB9, 0x54, 0x00, 0x18, 0x98, 0x5A, 0x86, 0xCB, 0x00, 0x06, 0x88, 0x1D, 0x72, 0x82, 0xC9, 0x72, 0x80, 0xC9, 0x43, 0x48, 0x00, 0x4F, 0x82, 0xC2, 0x6D, 0x00, 0x0F, 0x97, 0x6B, 0x00, 0x63, 0x9D, 0x50, 0x00, 0x0C, 0xA5, 0x28, 0x00, 0x81, 0x6D, 0x81, 0xB5, 0x3A, 0x00, 0x0C, 0x85, 0xCE, 0x07, 0x00, 0x39, 0xAB, 0x10, 0x00, 0x09, 0x81, 0xDD, 0x44, 0x00, 0x78, 0x81, 0x8C, 0x20, 0x00, 0x06, 0x84, 0x31, 0x00, 0x09, 0x85, 0xA6, 0x00, 0x00, 0x0F, 0x85, 0xE6, 0x40, 0x00, 0x18, 0x82, 0xFB, 0x40, 0x00, 0x81, 0x6A, 0x88, 0x20, 0xB7, 0xD0, 0xE6, 0x8E, 0xB5, 0xD8, 0x00, 0x0F, 0x90, 0x3D, 0x00, 0x43, 0xA9, 0x17, 0x00, 0x11, 0x90, 0x3D, 0x00, 0x0C, 0x98, 0x5A, 0x73, 0x82, 0xCA, 0x72, 0x81, 0xC9, 0x71, 0x80, 0xC9, 0x62, 0x6C, 0xA9, 0x00, 0x60, 0x81, 0xB5, 0x49, 0x00, 0x5D, 0xB9, 0x6C, 0x00, 0x0F, 0x81, 0x80, 0x38, 0x00, 0x81, 0x70, 0x83, 0x80, 0x09, 0x00, 0x09, 0xC0, 0x04, 0x00, 0x18, 0x85, 0xAC, 0x60, 0x00, 0x27, 0x88, 0x1D, 0x00, 0x7B, 0x82, 0x82, 0x21, 0x00, 0x06, 0x91, 0x3E, 0x00, 0x09, 0x83, 0x39, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x18, 0x85, 0xA4, 0x40, 0x00, 0x81, 0x67, 0x88, 0x20, 0xC2, 0xD8, 0xE9, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x28, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x0E, 0x90, 0x3D, 0x71, 0x7F, 0xC9, 0x70, 0x7D, 0xC8, 0x43, 0x48, 0x6A, 0x00, 0x81, 0x37, 0x84, 0xB0, 0x0E, 0x00, 0x0F, 0x66, 0x00, 0x81, 0x76, 0x81, 0xDE, 0x5A, 0x00, 0x09, 0xA8, 0x5B, 0xF2, 0xF2, 0xF4, 0x00, 0x2D, 0x8A, 0x1F, 0x00, 0x0C, 0x81, 0x8A, 0x4B, 0x00, 0x7B, 0x82, 0xAB, 0x4D, 0x00, 0x06, 0x84, 0xFB, 0x0B, 0x00, 0x30, 0x85, 0xFF, 0x20, 0x00, 0x81, 0x64, 0x88, 0x20, 0xD2, 0xE2, 0xEF, 0x94, 0xB9, 0xDA, 0x8E, 0xB5, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x31, 0xB9, 0x54, 0x00, 0x38, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x71, 0x7E, 0xC8, 0x70, 0x7D, 0xC8, 0x60, 0x6A, 0x00, 0x52, 0x90, 0x43, 0x00, 0x12, 0xD5, 0x7C, 0x00, 0x4E, 0x90, 0x46, 0x00, 0x12, 0x81, 0x90, 0x72, 0x00, 0x81, 0x7C, 0x83, 0xD2, 0x46, 0x00, 0x0C, 0x87, 0x6A, 0xB3, 0xB4, 0xBC, 0x00, 0x21, 0x90, 0x49, 0x4D, 0x4F, 0x62, 0x00, 0x0C, 0x85, 0xB5, 0x36, 0x00, 0x7E, 0xC4, 0x2C, 0x00, 0x0F, 0x84, 0xA9, 0x55, 0x00, 0x82, 0x08, 0x88, 0x20, 0xDE, 0xEA, 0xF3, 0x99, 0xBD, 0xDC, 0x00, 0x12, 0x98, 0x5A, 0x00, 0x3C, 0xE2, 0x6B, 0x00, 0x27, 0xA9, 0x17, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x05, 0x90, 0x3D, 0x6F, 0x7C, 0xC8, 0x6F, 0x7B, 0xC7, 0x43, 0x47, 0x00, 0x52, 0x90, 0x43, 0x00, 0x12, 0xF6, 0x79, 0x00, 0x36, 0x96, 0x04, 0x00, 0x24, 0x81, 0xA0, 0x61, 0x00, 0x82, 0x02, 0x83, 0xDA, 0x63, 0x00, 0x0F, 0x85, 0x82, 0x00, 0xD9, 0xD9, 0xDD, 0x8D, 0x8E, 0x9A, 0x00, 0x0C, 0x81, 0xA3, 0x3A, 0x00, 0x06, 0x81, 0xE7, 0x0C, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0x82, 0x3B, 0x00, 0x81, 0x04, 0x82, 0xB3, 0x61, 0x00, 0x06, 0x82, 0xE4, 0x1A, 0x00, 0x18, 0x88, 0x20, 0x00, 0x18, 0x82, 0xFB, 0x40, 0x00, 0x81, 0x61, 0x88, 0x20, 0xA9, 0xC8, 0xE1, 0x8E, 0xB6, 0xD8, 0x00, 0x13, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x12, 0x90, 0x3D, 0x00, 0x18, 0x98, 0x5A, 0x00, 0x05, 0x90, 0x3D, 0x6F, 0x7B, 0xC8, 0x6E, 0x7A, 0xC7, 0x58, 0x60, 0x99, 0x00, 0x66, 0x81, 0xB0, 0x47, 0x00, 0x3F, 0x81, 0xDB, 0x57, 0x00, 0x06, 0x81, 0xDC, 0x43, 0x00, 0x82, 0x05, 0x83, 0xE3, 0x00, 0x00, 0x7B, 0x86, 0x03, 0x00, 0x4E, 0xA3, 0x65, 0x00, 0x06, 0x9A, 0x20, 0x00, 0x09, 0xBE, 0x0B, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x06, 0x83, 0x6F, 0x00, 0x12, 0x99, 0x7F, 0x00, 0x81, 0x5E, 0x88, 0x20, 0xBF, 0xD6, 0xE9, 0x8F, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x23, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x16, 0x90, 0x3D, 0x00, 0x06, 0x88, 0x1D, 0x7C, 0xC8, 0x6E, 0x7A, 0xC7, 0x6E, 0x79, 0xC7, 0x6D, 0x78, 0xC7, 0x3B, 0x3E, 0x5A, 0x00, 0x69, 0xDE, 0x61, 0x00, 0x06, 0x88, 0x26, 0x00, 0x2D, 0x90, 0x4C, 0x4D, 0x4F, 0x62, 0x00, 0x12, 0x82, 0xF1, 0x03, 0x00, 0x81, 0x7C, 0x81, 0xEF, 0x0B, 0x00, 0x81, 0x49, 0x88, 0x20, 0x00, 0x06, 0xEF, 0x5A, 0x00, 0x09, 0xA2, 0x3D, 0x00, 0x0C, 0x88, 0x20, 0x00, 0x06, 0x88, 0x3B, 0x00, 0x15, 0xB5, 0x14, 0x00, 0x81, 0x5B, 0x88, 0x20, 0xD5, 0xE4, 0xF0, 0x8F, 0xB7, 0x00, 0x07, 0x88, 0x1D, 0x00, 0x33, 0xB9, 0x54, 0x00, 0x46, 0xA9, 0x17, 0x00, 0x0B, 0x90, 0x3D, 0x6E, 0x79, 0xC7, 0x6D, 0x77, 0xC6, 0x57, 0x5E, 0x98, 0x00, 0x72, 0x81, 0xD9, 0x64, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x84, 0xAE, 0x27, 0x00, 0x18, 0x81, 0xDC, 0x0D, 0x00, 0x06, 0x86, 0x8B, 0x71, 0x00, 0x15, 0x3C, 0x00, 0x27, 0x85, 0xE4, 0x65, 0x00, 0x83, 0x24, 0x88, 0x20, 0x00, 0x0C, 0xBA, 0x64, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x84, 0xEA, 0x69, 0x00, 0x09, 0xCB, 0x33, 0x00, 0x15, 0x83, 0x66, 0x00, 0x81, 0x58, 0x88, 0x20, 0xE1, 0xEC, 0xF4, 0x9A, 0xBE, 0xDC, 0x00, 0x16, 0x98, 0x5A, 0x00, 0x39, 0xB9, 0x54, 0x00, 0x35, 0xA9, 0x17, 0x00, 0x0C, 0x90, 0x3D, 0x6C, 0x77, 0xC6, 0x6C, 0x75, 0xC6, 0x00, 0x3F, 0x90, 0x43, 0x00, 0x21, 0x84, 0xC9, 0x12, 0x00, 0x81, 0x22, 0x84, 0xC1, 0x7F, 0x00, 0x82, 0x7A, 0x84, 0xC7, 0x5E, 0x5A, 0x5C, 0x6D, 0x00, 0x15, 0x82, 0xFB, 0x40, 0x00, 0x18, 0x8C, 0x03, 0x00, 0x81, 0x58, 0x88, 0x20, 0xAB, 0xC9, 0xE2, 0x00, 0x12, 0x90, 0x3D, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x26, 0xA9, 0x17, 0x6E, 0x7A, 0xC7, 0x6D, 0x78, 0xC7, 0x6D, 0x77, 0xC6, 0x6C, 0x76, 0xC6, 0x6B, 0x74, 0xC6, 0x56, 0x5C, 0x97, 0x00, 0x81, 0x52, 0xE6, 0x30, 0x00, 0x69, 0x88, 0x20, 0x00, 0x82, 0x44, 0x82, 0xA1, 0x58, 0x5A, 0x5C, 0x6D, 0x00, 0x27, 0x82, 0xFB, 0x40, 0x00, 0x81, 0x55, 0x88, 0x20, 0xCC, 0xDE, 0xED, 0x8F, 0xB7, 0xD9, 0x00, 0x28, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x0E, 0x90, 0x3D, 0x00, 0x1A, 0x98, 0x5A, 0xC7, 0x6C, 0x76, 0xC6, 0x6B, 0x75, 0xC6, 0x6B, 0x73, 0xC5, 0x6A, 0x72, 0xC5, 0x3B, 0x3D, 0x00, 0x3A, 0x90, 0x43, 0x00, 0x81, 0x7F, 0x88, 0x20, 0x00, 0x06, 0xD8, 0x1F, 0x00, 0x82, 0x68, 0x83, 0xDB, 0x6D, 0x00, 0x81, 0x52, 0x88, 0x20, 0xDE, 0xEA, 0xF3, 0x95, 0xBB, 0xDB, 0x00, 0x2A, 0xA9, 0x17, 0x00, 0x4E, 0xE2, 0x6B, 0x00, 0x13, 0x90, 0x3D, 0x00, 0x0B, 0x98, 0x5A, 0x6B, 0x74, 0xC6, 0x6A, 0x73, 0xC5, 0x6A, 0x71, 0xC5, 0x55, 0x5A, 0x00, 0x3A, 0x90, 0x43, 0x00, 0x82, 0x02, 0x88, 0x20, 0x00, 0x82, 0x3E, 0x84, 0x8D, 0x36, 0x41, 0x43, 0x56, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0xE3, 0x03, 0xB3, 0xB4, 0xBC, 0x00, 0x1E, 0x81, 0x9C, 0x6F, 0x00, 0x81, 0x52, 0x88, 0x20, 0xA6, 0xC6, 0xE1, 0x00, 0x3C, 0xA9, 0x17, 0x00, 0x13, 0x90, 0x3D, 0x00, 0x43, 0xA9, 0x17, 0x00, 0x0D, 0x90, 0x3D, 0x69, 0x70, 0xC5, 0x65, 0x6C, 0xBC, 0x37, 0x3A, 0x00, 0x37, 0x81, 0xBE, 0x01, 0x00, 0x63, 0x84, 0xEA, 0x54, 0x00, 0x63, 0x63, 0x00, 0x48, 0x83, 0x8D, 0x58, 0x00, 0x06, 0xA6, 0x65, 0x00, 0x82, 0x29, 0x90, 0x4F, 0x00, 0x18, 0x82, 0xDE, 0x17, 0x00, 0x18, 0xB5, 0x20, 0x00, 0x81, 0x4F, 0x88, 0x20, 0xC3, 0xD8, 0xEA, 0x8F, 0xB8, 0xD9, 0x00, 0x10, 0x90, 0x3D, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x35, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x69, 0x70, 0xC4, 0x68, 0x6F, 0xC4, 0x4E, 0x52, 0x87, 0x00, 0x82, 0x41, 0x9E, 0x45, 0x00, 0x0C, 0x82, 0xF4, 0x51, 0xB3, 0xB4, 0xBC, 0x00, 0x82, 0x20, 0x83, 0xE4, 0x1F, 0x00, 0x0C, 0x81, 0xE0, 0x2C, 0x73, 0x75, 0x83, 0x67, 0x68, 0x78, 0x73, 0x75, 0x83, 0x00, 0x09, 0xD6, 0x20, 0x00, 0x15, 0x88, 0x23, 0x00, 0x81, 0x4C, 0x88, 0x20, 0xE5, 0xEE, 0xF6, 0x95, 0xBC, 0xDB, 0x00, 0x27, 0x90, 0x3D, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x20, 0xA9, 0x17, 0x6A, 0x00, 0x08, 0x90, 0x3D, 0x68, 0x6F, 0xC4, 0x68, 0x6E, 0xC4, 0x64, 0x69, 0xBC, 0x37, 0x39, 0x00, 0x5B, 0x81, 0xEF, 0x4A, 0x00, 0x81, 0x6D, 0x82, 0xB0, 0x28, 0x00, 0x0C, 0x90, 0x4F, 0x00, 0x81, 0x79, 0x82, 0xB0, 0x16, 0x00, 0x24, 0xF3, 0x40, 0x00, 0x15, 0xB9, 0x48, 0x00, 0x1B, 0x82, 0xD2, 0x20, 0x00, 0x81, 0x4C, 0x88, 0x20, 0xAC, 0xCB, 0xE3, 0x00, 0x2B, 0xA9, 0x17, 0x00, 0x26, 0x81, 0xEE, 0x6D, 0x00, 0x40, 0xB9, 0x54, 0x00, 0x0F, 0x98, 0x5A, 0x00, 0x06, 0x90, 0x3D, 0x6E, 0xC4, 0x67, 0x6D, 0xC4, 0x67, 0x6C, 0xC3, 0x4D, 0x50, 0x00, 0x82, 0x3F, 0x90, 0x43, 0x00, 0x18, 0xC3, 0x7C, 0x00, 0x82, 0x14, 0xA9, 0x44, 0x00, 0x06, 0xF3, 0x40, 0x00, 0x18, 0xA3, 0x32, 0x00, 0x06, 0x90, 0x5B, 0x00, 0x12, 0x90, 0x43, 0x00, 0x81, 0x49, 0x88, 0x20, 0xD5, 0xE4, 0xF0, 0x00, 0x13, 0x98, 0x5A, 0x00, 0x40, 0xE2, 0x6B, 0x00, 0x3B, 0xA9, 0x17, 0x00, 0x12, 0x90, 0x3D, 0x00, 0x08, 0x98, 0x5A, 0x00, 0x06, 0x88, 0x1D, 0x66, 0x6B, 0xC3, 0x62, 0x67, 0xBB, 0x37, 0x39, 0x52, 0x00, 0x82, 0x44, 0x90, 0x43, 0x00, 0x0C, 0x82, 0xA7, 0x6D, 0xCC, 0xCD, 0xD2, 0x00, 0x12, 0x81, 0x92, 0x23, 0x00, 0x82, 0x08, 0x83, 0xBF, 0x30, 0x00, 0x18, 0x92, 0x5A, 0x00, 0x06, 0x81, 0xB0, 0x77, 0x00, 0x81, 0x58, 0xEB, 0x20, 0xE7, 0xF0, 0xF6, 0x9B, 0xC0, 0xDD, 0x00, 0x0F, 0x90, 0x3D, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x0E, 0x90, 0x3D, 0x66, 0x6A, 0xC3, 0x65, 0x69, 0xC2, 0x49, 0x4C, 0x7F, 0x00, 0x82, 0x41, 0xA1, 0x03, 0x00, 0x0C, 0xE4, 0x22, 0x00, 0x09, 0x96, 0x3D, 0x00, 0x06, 0x81, 0x9A, 0x34, 0x00, 0x82, 0x0B, 0xCB, 0x09, 0x00, 0x36, 0x83, 0xEF, 0x00, 0x00, 0x81, 0x46, 0x88, 0x20, 0xBF, 0xD6, 0xE9, 0x00, 0x23, 0x90, 0x3D, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x33, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x65, 0x6A, 0xC3, 0x65, 0x68, 0xC2, 0x58, 0x5B, 0xA4, 0x00, 0x82, 0x44, 0xA0, 0x74, 0x00, 0x18, 0xED, 0x0D, 0x4D, 0x4F, 0x62, 0x00, 0x82, 0x08, 0xA1, 0x0C, 0x00, 0x06, 0xEF, 0x42, 0x00, 0x1E, 0x90, 0x40, 0x00, 0x81, 0x55, 0xF3, 0x40, 0xE2, 0xED, 0xF5, 0x96, 0x00, 0x29, 0xA9, 0x17, 0x00, 0x36, 0x81, 0xEE, 0x6D, 0x00, 0x2C, 0x90, 0x3D, 0x00, 0x1F, 0xA9, 0x17, 0x67, 0x6D, 0xC3, 0x66, 0x6B, 0x00, 0x07, 0x90, 0x3D, 0x64, 0x67, 0xC2, 0x64, 0x66, 0xC2, 0x00, 0x82, 0x32, 0x85, 0xDB, 0x68, 0x00, 0x81, 0x25, 0xC2, 0x03, 0x00, 0x06, 0xFB, 0x66, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x83, 0xAB, 0x64, 0x00, 0x81, 0x01, 0xE5, 0x44, 0x00, 0x0F, 0xF3, 0x40, 0x00, 0x15, 0x1E, 0x00, 0x81, 0x55, 0xF3, 0x40, 0xAD, 0x00, 0x3B, 0xA9, 0x17, 0x00, 0x27, 0x81, 0xEE, 0x6D, 0x00, 0x3D, 0xB9, 0x54, 0x00, 0x16, 0x98, 0x5A, 0xC3, 0x64, 0x68, 0xC2, 0x64, 0x67, 0xC2, 0x63, 0x65, 0xC1, 0x3D, 0x3F, 0x00, 0x82, 0x2D, 0x84, 0x81, 0x0F, 0x00, 0x12, 0x98, 0x4B, 0x00, 0x66, 0x99, 0x49, 0x00, 0x2A, 0x91, 0x08, 0x00, 0x15, 0x86, 0x86, 0x24, 0x00, 0x81, 0x04, 0x83, 0xDD, 0x27, 0xD9, 0xD9, 0xDD, 0x00, 0x1B, 0xB1, 0x40, 0x00, 0x15, 0x81, 0xA6, 0x19, 0x00, 0x81, 0x40, 0x88, 0x20, 0xD8, 0xE6, 0xF1, 0x90, 0xB8, 0xD9, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x40, 0xA9, 0x17, 0x00, 0x11, 0x90, 0x3D, 0x00, 0x06, 0x98, 0x5A, 0x64, 0x67, 0xC2, 0x63, 0x66, 0xC2, 0x63, 0x64, 0xC1, 0x40, 0x42, 0x00, 0x81, 0x32, 0x83, 0xC6, 0x46, 0x00, 0x7E, 0x81, 0xB4, 0x4E, 0x00, 0x6F, 0x86, 0x66, 0x00, 0x09, 0xB8, 0x1A, 0x00, 0x24, 0x91, 0x2C, 0x00, 0x15, 0x83, 0x9F, 0x52, 0x00, 0x81, 0x04, 0x83, 0xA7, 0x21, 0x00, 0x06, 0x83, 0xB9, 0x03, 0x00, 0x06, 0x81, 0x49, 0xA6, 0xA7, 0xB0, 0x00, 0x09, 0x82, 0xB1, 0x14, 0x00, 0x06, 0x93, 0x10, 0x00, 0x06, 0x83, 0xC9, 0x49, 0x00, 0x0C, 0x82, 0xB1, 0x2C, 0x00, 0x06, 0x81, 0x28, 0x00, 0x81, 0x40, 0x88, 0x20, 0xA8, 0xC8, 0xE1, 0x00, 0x22, 0x90, 0x3D, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x40, 0xA9, 0x17, 0x00, 0x0A, 0x90, 0x3D, 0x62, 0x64, 0xC1, 0x40, 0x41, 0x00, 0x82, 0x2D, 0x88, 0x20, 0x00, 0x7B, 0x81, 0xBD, 0x60, 0x00, 0x24, 0x81, 0xA6, 0x79, 0x00, 0x0C, 0x90, 0x3A, 0x00, 0x06, 0xD9, 0x3E, 0x00, 0x06, 0x83, 0xE9, 0x5D, 0x00, 0x09, 0x88, 0x35, 0x00, 0x78, 0x83, 0xA7, 0x21, 0x00, 0x30, 0x82, 0xA8, 0x35, 0x00, 0x06, 0xA9, 0x2C, 0x00, 0x81, 0x3D, 0x88, 0x20, 0xD3, 0xE3, 0x00, 0x37, 0xB9, 0x54, 0x00, 0x4C, 0x81, 0x8C, 0x02, 0x00, 0x08, 0x90, 0x3D, 0x00, 0x2D, 0xA9, 0x17, 0x00, 0x09, 0x90, 0x3D, 0x62, 0x63, 0xC1, 0x3F, 0x41, 0x00, 0x79, 0x83, 0x9D, 0x02, 0x00, 0x82, 0x2C, 0x85, 0x9C, 0x20, 0x00, 0x24, 0x81, 0xC8, 0x65, 0x00, 0x09, 0x86, 0x4E, 0x00, 0x12, 0x90, 0x28, 0x00, 0x0C, 0x81, 0xA0, 0x07, 0x00, 0x75, 0x81, 0xAF, 0x61, 0x00, 0x24, 0x85, 0xDE, 0x20, 0x00, 0x0C, 0x0C, 0x00, 0x06, 0x81, 0xB5, 0x4C, 0x00, 0x81, 0x3D, 0x88, 0x20, 0x9C, 0xC0, 0xDD, 0x00, 0x45, 0xE2, 0x6B, 0x00, 0x4D, 0x81, 0x8C, 0x02, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x21, 0xA9, 0x17, 0x00, 0x06, 0x90, 0x3D, 0x62, 0x62, 0xC1, 0x3C, 0x3E, 0x00, 0x83, 0x1C, 0x84, 0xA2, 0x0F, 0x00, 0x09, 0x86, 0x21, 0x00, 0x24, 0x82, 0xA0, 0x63, 0x00, 0x09, 0x81, 0x9F, 0x66, 0x00, 0x15, 0xD9, 0x2C, 0x00, 0x0C, 0x81, 0xC6, 0x48, 0x00, 0x81, 0x28, 0xB2, 0x56, 0x00, 0x81, 0x3A, 0x88, 0x20, 0xCD, 0xDF, 0xEE, 0x00, 0x0A, 0x90, 0x3D, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x20, 0x81, 0xEE, 0x6D, 0x00, 0x3D, 0xB9, 0x54, 0x00, 0x11, 0x98, 0x5A, 0x62, 0x63, 0xC1, 0x61, 0x61, 0x00, 0x76, 0x83, 0xA5, 0x1F, 0x00, 0x82, 0x2C, 0xB2, 0x2F, 0x00, 0x2A, 0x82, 0x93, 0x0B, 0x00, 0x21, 0x81, 0xD0, 0x3D, 0x00, 0x09, 0x81, 0xC9, 0x33, 0x00, 0x81, 0x28, 0xF4, 0x7A, 0x00, 0x81, 0x3A, 0x88, 0x20, 0x00, 0x1F, 0x90, 0x3D, 0x00, 0x56, 0x81, 0xEE, 0x6D, 0x00, 0x3C, 0xA9, 0x17, 0x00, 0x12, 0x90, 0x3D, 0x61, 0x62, 0xC0, 0x56, 0x56, 0xA3, 0x00, 0x83, 0x24, 0x84, 0x90, 0x27, 0x00, 0x24, 0x81, 0xD8, 0x30, 0x00, 0x27, 0x82, 0xA9, 0x2D, 0x00, 0x7B, 0x81, 0xF7, 0x40, 0x5A, 0x5C, 0x6D, 0x9A, 0x9B, 0xA5, 0xC0, 0xC0, 0xC7, 0x00, 0x09, 0xFB, 0x5A, 0x00, 0x21, 0x89, 0x75, 0x00, 0x81, 0x37, 0x88, 0x20, 0xCE, 0xDF, 0xEE, 0x00, 0x30, 0xB9, 0x54, 0x00, 0x48, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x3F, 0xA9, 0x17, 0x00, 0x06, 0x90, 0x3D, 0x47, 0x49, 0x7E, 0x00, 0x82, 0x38, 0xDA, 0x54, 0x00, 0x09, 0x83, 0xEC, 0x39, 0x00, 0x06, 0xA6, 0x4D, 0x00, 0x57, 0x83, 0x93, 0x07, 0x00, 0x2A, 0x81, 0xB7, 0x3C, 0x00, 0x27, 0x82, 0xB0, 0x79, 0x00, 0x51, 0x82, 0x80, 0x31, 0x00, 0x39, 0x81, 0x9C, 0x57, 0x00, 0x24, 0x82, 0xF4, 0x6F, 0x00, 0x81, 0x37, 0x88, 0x20, 0x9C, 0xC0, 0xDD, 0x00, 0x48, 0xE2, 0x6B, 0x00, 0x43, 0x81, 0x8C, 0x02, 0x00, 0x23, 0xE2, 0x6B, 0x00, 0x12, 0xA9, 0x17, 0x61, 0x62, 0xC0, 0x5E, 0x5E, 0xB9, 0x00, 0x82, 0x35, 0xE3, 0x00, 0x00, 0x18, 0x82, 0xDF, 0x5D, 0x00, 0x51, 0xB8, 0x3E, 0x00, 0x2D, 0x82, 0x98, 0x40, 0x00, 0x09, 0x87, 0x01, 0x00, 0x27, 0x88, 0x47, 0x00, 0x72, 0xFB, 0x57, 0x00, 0x06, 0x85, 0xD9, 0x3F, 0x00, 0x0C, 0xB9, 0x5A, 0x00, 0x21, 0x81, 0xE8, 0x58, 0x00, 0x81, 0x34, 0x88, 0x20, 0xCE, 0xE0, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x78, 0x81, 0xEE, 0x6D, 0x00, 0x2D, 0xB9, 0x54, 0x00, 0x18, 0xA9, 0x17, 0x61, 0x61, 0xC0, 0x4A, 0x4B, 0x86, 0x00, 0x82, 0x35, 0xE2, 0x74, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x0C, 0xCA, 0x23, 0x00, 0x09, 0xE3, 0x09, 0x00, 0x4E, 0x84, 0xD9, 0x46, 0x00, 0x2D, 0x82, 0xA9, 0x00, 0x00, 0x27, 0x82, 0x80, 0x07, 0x00, 0x09, 0x81, 0xF7, 0x46, 0x00, 0x66, 0xC2, 0x09, 0x00, 0x09, 0x83, 0xCE, 0x03, 0x00, 0x18, 0xAA, 0x33, 0x00, 0x06, 0xA2, 0x61, 0x00, 0x18, 0xAA, 0x33, 0x00, 0x81, 0x34, 0x88, 0x20, 0xA8, 0xC8, 0xE1, 0x00, 0x19, 0x90, 0x3D, 0x00, 0x65, 0x81, 0xEE, 0x6D, 0x00, 0x36, 0xE2, 0x6B, 0x00, 0x0D, 0x90, 0x3D, 0x61, 0x00, 0x82, 0x39, 0x90, 0x3D, 0x00, 0x06, 0x97, 0x20, 0x00, 0x15, 0x85, 0x6E, 0x00, 0x06, 0x86, 0x7B, 0x00, 0x4B, 0x81, 0xCF, 0x48, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x09, 0x90, 0x6A, 0x00, 0x21, 0xB1, 0x67, 0x00, 0x6F, 0x82, 0xB9, 0x40, 0x00, 0x18, 0x83, 0xDE, 0x31, 0x00, 0x27, 0x82, 0x38, 0x00, 0x81, 0x31, 0x88, 0x20, 0xDB, 0xE8, 0xF3, 0x00, 0x31, 0xB9, 0x54, 0x00, 0x53, 0x81, 0xEE, 0x6D, 0x00, 0x3C, 0xA9, 0x17, 0x00, 0x82, 0x3B, 0x90, 0x3D, 0x00, 0x06, 0xE8, 0x47, 0x00, 0x1B, 0x81, 0xFE, 0x23, 0x00, 0x06, 0xC0, 0x64, 0x00, 0x48, 0xA1, 0x09, 0x00, 0x2A, 0x87, 0x4C, 0x00, 0x2A, 0x83, 0xD4, 0x66, 0x00, 0x6C, 0x88, 0x20, 0x00, 0x2A, 0x83, 0xE6, 0x36, 0x00, 0x18, 0x82, 0xE2, 0x7E, 0x00, 0x81, 0x31, 0x88, 0x20, 0xAF, 0xCC, 0xE3, 0x00, 0x43, 0xE2, 0x6B, 0x00, 0x4B, 0x81, 0x8C, 0x02, 0x78, 0x00, 0x34, 0xA9, 0x17, 0x00, 0x72, 0x90, 0x3D, 0x00, 0x09, 0x81, 0xE4, 0x18, 0x00, 0x81, 0x3D, 0x84, 0xAE, 0x03, 0x00, 0x06, 0x85, 0x2F, 0x00, 0x1B, 0x81, 0x3A, 0x00, 0x06, 0x9F, 0x5E, 0x00, 0x48, 0x86, 0x7B, 0x00, 0x2A, 0x87, 0x4C, 0x00, 0x2A, 0x82, 0xDA, 0x16, 0x00, 0x6C, 0x88, 0x20, 0x00, 0x1E, 0x81, 0x83, 0x74, 0x00, 0x12, 0xBA, 0x79, 0x00, 0x12, 0x82, 0x59, 0x00, 0x81, 0x2E, 0x88, 0x20, 0xE9, 0xF1, 0xF8, 0x00, 0x50, 0x81, 0x8C, 0x02, 0x00, 0x13, 0x82, 0xD1, 0x58, 0x00, 0x42, 0xE2, 0x6B, 0x00, 0x1E, 0xA9, 0x17, 0x61, 0x61, 0xC0, 0x50, 0x50, 0x94, 0x00, 0x6C, 0x83, 0xCB, 0x24, 0x00, 0x18, 0xE0, 0x12, 0x00, 0x82, 0x29, 0x88, 0x20, 0x00, 0x21, 0x81, 0xFF, 0x18, 0x00, 0x27, 0xA9, 0x1D, 0x00, 0x6F, 0x82, 0xDA, 0x40, 0x00, 0x18, 0xEA, 0x76, 0x00, 0x18, 0x93, 0x19, 0x00, 0x12, 0xBA, 0x76, 0x00, 0x81, 0x2E, 0x88, 0x20, 0xBC, 0xD4, 0xE8, 0x00, 0x81, 0x0A, 0x81, 0xEE, 0x6D, 0x00, 0x34, 0xB9, 0x54, 0x00, 0x05, 0x98, 0x5A, 0x60, 0x60, 0xC0, 0x3A, 0x3B, 0x00, 0x58, 0x81, 0xE7, 0x06, 0x00, 0x0C, 0x84, 0xF5, 0x56, 0x00, 0x21, 0x83, 0x8F, 0x42, 0x00, 0x81, 0x37, 0x98, 0x60, 0x00, 0x1B, 0xA0, 0x62, 0x00, 0x06, 0xA6, 0x6E, 0x00, 0x48, 0xA9, 0x23, 0x00, 0x09, 0x82, 0xC3, 0x4D, 0x00, 0x21, 0x92, 0x6C, 0x00, 0x2A, 0x82, 0xA9, 0x24, 0x00, 0x6C, 0xB1, 0x40, 0x00, 0x2D, 0x81, 0x96, 0x42, 0x00, 0x81, 0x43, 0x81, 0x8C, 0x20, 0x95, 0xBA, 0xDA, 0x00, 0x81, 0x0D, 0x81, 0xEE, 0x6D, 0x00, 0x31, 0xA9, 0x17, 0x00, 0x62, 0x90, 0x3D, 0x00, 0x18, 0x84, 0xFD, 0x70, 0x00, 0x42, 0x88, 0x20, 0x00, 0x81, 0x07, 0x81, 0xB4, 0x1E, 0x00, 0x06, 0x92, 0x0F, 0x00, 0x15, 0x96, 0x34, 0x00, 0x06, 0xF2, 0x3C, 0x00, 0x4E, 0x81, 0x9C, 0x54, 0x00, 0x06, 0xA7, 0x60, 0x00, 0x1E, 0xC9, 0x4F, 0x00, 0x36, 0xDB, 0x04, 0x00, 0x82, 0x50, 0x88, 0x20, 0xD0, 0xE1, 0xEF, 0x00, 0x3E, 0xE2, 0x6B, 0x00, 0x52, 0x81, 0xEE, 0x6D, 0x00, 0x33, 0xA9, 0x17, 0x00, 0x5D, 0x90, 0x3D, 0x8D, 0x8E, 0x9A, 0x00, 0x2D, 0x83, 0x9F, 0x76, 0x00, 0x30, 0xEF, 0x7E, 0x00, 0x81, 0x04, 0x81, 0xFF, 0x63, 0x00, 0x09, 0x81, 0x81, 0x2D, 0x00, 0x0F, 0x88, 0x23, 0x00, 0x06, 0xEA, 0x01, 0x00, 0x51, 0xC2, 0x03, 0x00, 0x09, 0x8A, 0x6D, 0x00, 0x1B, 0x9F, 0x46, 0x00, 0x09, 0xDB, 0x04, 0x00, 0x24, 0x82, 0x98, 0x1F, 0x00, 0x4B, 0x82, 0xBA, 0x0E, 0x00, 0x27, 0x81, 0x83, 0x71, 0x00, 0x2A, 0x82, 0xA2, 0x41, 0x00, 0x81, 0x3D, 0x82, 0xA0, 0x60, 0xA8, 0xC7, 0xE1, 0x00, 0x51, 0xE2, 0x6B, 0x00, 0x46, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x20, 0xA9, 0x17, 0x60, 0x60, 0x00, 0x58, 0x90, 0x3D, 0x00, 0x1B, 0x83, 0x97, 0x59, 0xF2, 0xF2, 0xF4, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x81, 0xF7, 0x40, 0x00, 0x06, 0xA9, 0x23, 0x00, 0x30, 0x88, 0x20, 0x00, 0x0C, 0x91, 0x11, 0x00, 0x72, 0xA9, 0x56, 0x00, 0x12, 0x84, 0xD9, 0x49, 0x00, 0x09, 0x82, 0xD9, 0x03, 0x00, 0x06, 0x81, 0x93, 0x1B, 0x00, 0x06, 0x81, 0x93, 0x27, 0x00, 0x09, 0xD9, 0x38, 0x00, 0x4E, 0x81, 0x22, 0x00, 0x09, 0xC8, 0x5D, 0x00, 0x18, 0x57, 0x00, 0x09, 0x81, 0x83, 0x71, 0x00, 0x24, 0x87, 0x0A, 0x00, 0x09, 0x82, 0xA9, 0x48, 0x00, 0x66, 0x85, 0xA3, 0x2A, 0x00, 0x06, 0x83, 0x39, 0x00, 0x24, 0x93, 0x79, 0x00, 0x18, 0x84, 0xB9, 0x20, 0x00, 0x81, 0x28, 0x88, 0x20, 0xEB, 0xF2, 0xF8, 0x00, 0x61, 0x81, 0xEE, 0x6D, 0x8B, 0x00, 0x49, 0x81, 0x8C, 0x02, 0x00, 0x09, 0x90, 0x3D, 0x00, 0x0F, 0x98, 0x5A, 0x60, 0x5F, 0xC0, 0x39, 0x00, 0x53, 0x90, 0x3D, 0x00, 0x18, 0x83, 0x8F, 0x3C, 0xCC, 0xCD, 0xD2, 0x00, 0x12, 0x8D, 0x52, 0x00, 0x30, 0x88, 0x20, 0x00, 0x12, 0x84, 0x22, 0x00, 0x6F, 0x82, 0xA6, 0x45, 0x00, 0x33, 0x81, 0xF9, 0x12, 0x00, 0x57, 0x82, 0xF6, 0x11, 0x00, 0x15, 0xB9, 0x3C, 0x00, 0x09, 0x8B, 0x17, 0x00, 0x24, 0x92, 0x5D, 0x00, 0x2D, 0x90, 0x6A, 0x00, 0x48, 0xD4, 0x00, 0x00, 0x21, 0x83, 0xA4, 0x54, 0x00, 0x06, 0x82, 0xC5, 0x3A, 0x00, 0x15, 0x9B, 0x36, 0x00, 0x81, 0x28, 0x88, 0x20, 0xBD, 0xD4, 0xE8, 0x00, 0x72, 0x81, 0xEE, 0x6D, 0x73, 0x82, 0xCA, 0x00, 0x46, 0xA9, 0x17, 0x00, 0x08, 0x90, 0x3D, 0x4F, 0x00, 0x53, 0x90, 0x3D, 0x00, 0x15, 0x88, 0x1D, 0x00, 0x1B, 0x85, 0x91, 0x24, 0x00, 0x33, 0x90, 0x40, 0x00, 0x0F, 0x83, 0xE4, 0x58, 0x00, 0x6F, 0x85, 0xAA, 0x6A, 0x00, 0x33, 0x84, 0xEA, 0x09, 0x00, 0x5A, 0x82, 0xBC, 0x28, 0x00, 0x0C, 0xE3, 0x66, 0x00, 0x0C, 0x82, 0xA8, 0x5F, 0x00, 0x27, 0xAA, 0x15, 0x00, 0x2A, 0x90, 0x6A, 0x00, 0x4E, 0xF5, 0x00, 0x00, 0x1B, 0xE2, 0x65, 0x00, 0x09, 0x84, 0xA7, 0x7A, 0x00, 0x15, 0x89, 0x7E, 0x00, 0x81, 0x28, 0x88, 0x20, 0x9B, 0xBE, 0x00, 0x73, 0x82, 0xD1, 0x58, 0x00, 0x18, 0x90, 0x3D, 0x00, 0x36, 0xA9, 0x17, 0x60, 0x5F, 0xC0, 0x3F, 0x40, 0x00, 0x4F, 0x81, 0x8C, 0x0B, 0x00, 0x15, 0x88, 0x1D, 0x00, 0x1E, 0x86, 0x21, 0x00, 0x33, 0x88, 0x20, 0x00, 0x15, 0x84, 0x9D, 0x07, 0x00, 0x81, 0x73, 0x84, 0xD0, 0x49, 0x00, 0x1B, 0x85, 0x2F, 0x00, 0x24, 0x82, 0x9A, 0x60, 0x00, 0x09, 0x82, 0x44, 0x00, 0x6C, 0x85, 0xBC, 0x07, 0x00, 0x09, 0x84, 0x22, 0x00, 0x12, 0x84, 0xE2, 0x46, 0x00, 0x06, 0x81, 0xC8, 0x38, 0x00, 0x09, 0xDD, 0x2D, 0x00, 0x81, 0x3A, 0xE3, 0x00, 0xDF, 0xEA, 0xF4, 0x00, 0x4F, 0xE2, 0x6B, 0x00, 0x4B, 0x81, 0xEE, 0x6D, 0x71, 0x00, 0x28, 0xA9, 0x17, 0x55, 0x55, 0xA2, 0x00, 0x60, 0x84, 0x9F, 0x54, 0x00, 0x24, 0xA7, 0x1E, 0x00, 0x36, 0x88, 0x20, 0x00, 0x7B, 0x84, 0x90, 0x75, 0x00, 0x81, 0x10, 0x81, 0x84, 0x09, 0x00, 0x12, 0x85, 0x2C, 0x00, 0x24, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xA5, 0x18, 0x00, 0x72, 0x81, 0xA6, 0x40, 0x00, 0x0C, 0x82, 0xBA, 0x47, 0x00, 0x12, 0x82, 0x94, 0x48, 0x00, 0x1B, 0x81, 0x40, 0x00, 0x81, 0x25, 0x88, 0x20, 0xB6, 0xCF, 0xE6, 0x00, 0x5B, 0x81, 0xEE, 0x6D, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x44, 0x81, 0x8C, 0x02, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x0E, 0x98, 0x5A, 0x00, 0x54, 0x90, 0x3D, 0x00, 0x0F, 0x84, 0x97, 0x2E, 0x00, 0x27, 0xAF, 0x3B, 0x00, 0x39, 0x88, 0x20, 0x00, 0x0C, 0x83, 0xE4, 0x67, 0x00, 0x81, 0x76, 0x81, 0xD5, 0x1B, 0x67, 0x68, 0x78, 0x00, 0x0F, 0x8B, 0x11, 0xC0, 0xC0, 0xC7, 0x00, 0x27, 0x8A, 0x28, 0x00, 0x09, 0x91, 0x02, 0x00, 0x78, 0xB4, 0x04, 0x00, 0x12, 0x81, 0x3D, 0x00, 0x24, 0x81, 0xE1, 0x06, 0x00, 0x81, 0x25, 0x88, 0x20, 0x94, 0xB9, 0x00, 0x14, 0x82, 0xFA, 0x6F, 0x00, 0x81, 0x0C, 0x81, 0xEE, 0x6D, 0x00, 0x21, 0x90, 0x3D, 0x54, 0x54, 0x00, 0x4F, 0x90, 0x3D, 0x00, 0x0F, 0x82, 0xEA, 0x0E, 0x00, 0x2A, 0xB7, 0x58, 0x00, 0x39, 0x88, 0x20, 0x00, 0x12, 0x98, 0x66, 0x00, 0x82, 0x2C, 0x85, 0xDA, 0x4F, 0x00, 0x06, 0x81, 0xBD, 0x75, 0x00, 0x81, 0x04, 0x81, 0x9C, 0x5A, 0x5A, 0x5C, 0x6D, 0x00, 0x2A, 0x83, 0xE6, 0x4B, 0x00, 0x81, 0x22, 0x88, 0x20, 0xD8, 0xE6, 0xF1, 0x00, 0x81, 0x25, 0x81, 0xEE, 0x6D, 0x00, 0x1B, 0xA9, 0x17, 0x00, 0x54, 0x90, 0x3D, 0x00, 0x0F, 0x9E, 0x12, 0x00, 0x2A, 0x81, 0x99, 0x30, 0x00, 0x3C, 0x88, 0x20, 0x00, 0x0F, 0x83, 0xA5, 0x5E, 0x00, 0x82, 0x02, 0x82, 0xCA, 0x0F, 0x00, 0x81, 0x61, 0x82, 0xA2, 0x1D, 0x00, 0x81, 0x22, 0x88, 0x20, 0xB6, 0xCF, 0xE6, 0x00, 0x81, 0x14, 0x81, 0xEE, 0x6D, 0x72, 0x00, 0x2B, 0xA9, 0x17, 0x00, 0x54, 0x90, 0x3D, 0x00, 0x39, 0xA8, 0x2E, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x0C, 0x90, 0x43, 0x00, 0x81, 0x67, 0x84, 0x87, 0x5D, 0x00, 0x82, 0x05, 0x85, 0xE8, 0x3F, 0x00, 0x81, 0x19, 0x88, 0x20, 0x9B, 0xBC, 0xDC, 0x00, 0x81, 0x27, 0x81, 0xEE, 0x6D, 0xC3, 0x00, 0x15, 0x98, 0x5A, 0x5F, 0x5F, 0xBF, 0x41, 0x43, 0x6F, 0x00, 0x5A, 0x90, 0x3D, 0x00, 0x30, 0x95, 0x33, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x0F, 0x83, 0xA4, 0x60, 0x00, 0x83, 0x3F, 0x85, 0x94, 0x1E, 0x00, 0x81, 0x40, 0x83, 0x9C, 0x40, 0xE7, 0xEF, 0xF7, 0x00, 0x19, 0x90, 0x3D, 0x00, 0x81, 0x12, 0x81, 0xEE, 0x6D, 0x00, 0x15, 0x90, 0x3D, 0x5A, 0x59, 0x00, 0x4F, 0x84, 0xC9, 0x7E, 0x00, 0x0F, 0x81, 0xD3, 0x22, 0x00, 0x30, 0xBF, 0x6F, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x0F, 0xB2, 0x35, 0x00, 0x83, 0x63, 0x85, 0xF3, 0x32, 0x00, 0x81, 0x1C, 0x83, 0xAD, 0x00, 0xC4, 0xD8, 0xEB, 0x00, 0x7D, 0x81, 0xEE, 0x6D, 0xC8, 0x00, 0x3F, 0xA9, 0x17, 0x5F, 0x5F, 0xBF, 0x44, 0x45, 0x00, 0x4F, 0x85, 0xDF, 0x42, 0x00, 0x0F, 0x83, 0x83, 0x57, 0x00, 0x30, 0x9D, 0x53, 0x00, 0x42, 0x88, 0x20, 0x00, 0x81, 0x6A, 0x83, 0xC5, 0x60, 0x00, 0x82, 0x0E, 0x81, 0xBF, 0x62, 0x00, 0x81, 0x13, 0x88, 0x20, 0xA1, 0xC0, 0xDE, 0x00, 0x3F, 0xB9, 0x54, 0x00, 0x4F, 0x81, 0xEE, 0x6D, 0x73, 0x00, 0x2E, 0xA9, 0x17, 0x00, 0x51, 0x90, 0x3D, 0x00, 0x0F, 0x98, 0x5D, 0x00, 0x33, 0xC9, 0x28, 0x00, 0x42, 0x88, 0x20, 0x00, 0x81, 0x07, 0x83, 0xDF, 0x44, 0x00, 0x82, 0x6B, 0x82, 0xD2, 0x53, 0x00, 0x81, 0x16, 0x88, 0x20, 0xF6, 0xF9, 0xFC, 0x00, 0x81, 0x22, 0x81, 0xEE, 0x6D, 0x66, 0x00, 0x1A, 0x98, 0x5A, 0x5F, 0x5E, 0x00, 0x52, 0x90, 0x3D, 0x00, 0x0F, 0xB0, 0x42, 0x00, 0x33, 0x81, 0xCA, 0x67, 0x00, 0x42, 0x88, 0x20, 0x00, 0x81, 0x6A, 0x83, 0xE6, 0x60, 0x00, 0x83, 0x09, 0x85, 0xD8, 0x2C, 0x00, 0x15, 0x88, 0x20, 0xDA, 0xE6, 0xF2, 0x00, 0x81, 0x31, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x5F, 0x5F, 0xBF, 0x00, 0x54, 0x90, 0x3D, 0x00, 0x0F, 0xA8, 0x1F, 0x00, 0x33, 0x87, 0x1C, 0x00, 0x51, 0x88, 0x20, 0x00, 0x82, 0x2C, 0xC2, 0x06, 0x00, 0x82, 0x4A, 0x82, 0xD2, 0x26, 0xFE, 0xFF, 0xFF, 0xBD, 0xD3, 0xE8, 0x00, 0x81, 0x31, 0x81, 0xEE, 0x6D, 0x00, 0x60, 0x90, 0x3D, 0x00, 0x42, 0x83, 0xED, 0x7C, 0x00, 0x45, 0x88, 0x20, 0x00, 0x81, 0x6A, 0x84, 0x90, 0x00, 0x00, 0x21, 0x84, 0xF9, 0x78, 0xC0, 0xC0, 0xC7, 0x00, 0x12, 0x83, 0x8F, 0x00, 0x00, 0x81, 0x04, 0x84, 0xEA, 0x5D, 0x41, 0x43, 0x56, 0x00, 0x18, 0x84, 0xB0, 0x68, 0x00, 0x33, 0x84, 0xB1, 0x00, 0x00, 0x81, 0x13, 0x83, 0xFF, 0x40, 0x99, 0xBA, 0xDC, 0x00, 0x3A, 0xB9, 0x54, 0x00, 0x77, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x5C, 0x5B, 0xB8, 0x00, 0x81, 0x16, 0x84, 0x87, 0x60, 0x00, 0x82, 0x44, 0x88, 0x20, 0x5A, 0x5C, 0x6D, 0x00, 0x27, 0x86, 0x30, 0x00, 0x7B, 0x82, 0xBA, 0x47, 0x00, 0x33, 0x8F, 0x75, 0x00, 0x1B, 0xB6, 0x0C, 0x00, 0x81, 0x10, 0x84, 0x90, 0x00, 0xF7, 0xFA, 0xFC, 0x00, 0x81, 0x16, 0x82, 0xD1, 0x58, 0x00, 0x24, 0xA9, 0x17, 0x5F, 0x5E, 0xBF, 0x49, 0x49, 0x85, 0x00, 0x60, 0x82, 0x83, 0x46, 0x00, 0x36, 0xF2, 0x45, 0x00, 0x82, 0x3E, 0x88, 0x20, 0x00, 0x09, 0x81, 0xCC, 0x51, 0x00, 0x2D, 0x85, 0x4D, 0x00, 0x75, 0xBC, 0x06, 0x00, 0x06, 0x81, 0xDE, 0x54, 0x00, 0x0F, 0x81, 0xFF, 0x36, 0x00, 0x0C, 0x82, 0xA3, 0x1B, 0x00, 0x0C, 0xEB, 0x26, 0x00, 0x06, 0xEB, 0x38, 0x00, 0x1E, 0xA5, 0x4F, 0x00, 0x81, 0x0D, 0x88, 0x23, 0xDA, 0xE6, 0xF2, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x81, 0x22, 0x81, 0xEE, 0x6D, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x05, 0x88, 0x1D, 0x5C, 0x5B, 0xB8, 0x37, 0x38, 0x00, 0x55, 0x81, 0xBD, 0x3F, 0x00, 0x0C, 0x87, 0x5E, 0x00, 0x36, 0x81, 0x81, 0x69, 0x00, 0x82, 0x3B, 0x88, 0x20, 0x00, 0x12, 0x83, 0x8E, 0x5F, 0x00, 0x27, 0x83, 0xA4, 0x60, 0x00, 0x42, 0x84, 0xAF, 0x79, 0x00, 0x4B, 0x81, 0x96, 0x0C, 0x00, 0x0F, 0x81, 0x84, 0x0C, 0x00, 0x09, 0x83, 0xB0, 0x63, 0x00, 0x24, 0x84, 0x4F, 0x00, 0x15, 0x85, 0xFF, 0x5F, 0x00, 0x75, 0x88, 0x20, 0xBD, 0xD2, 0xE8, 0x00, 0x1F, 0x90, 0x3D, 0x00, 0x4D, 0x81, 0xEE, 0x6D, 0x00, 0x07, 0x90, 0x3D, 0x00, 0x41, 0xA9, 0x17, 0x00, 0x5D, 0x90, 0x3D, 0x00, 0x81, 0x0A, 0x88, 0x20, 0x00, 0x0C, 0x85, 0x7D, 0x00, 0x81, 0x67, 0x88, 0x20, 0x00, 0x0F, 0x85, 0xC8, 0x28, 0x00, 0x30, 0x83, 0xB5, 0x20, 0x00, 0x81, 0x01, 0x88, 0x23, 0x00, 0x06, 0xDA, 0x2A, 0x00, 0x18, 0x94, 0x74, 0x00, 0x06, 0x81, 0x28, 0x00, 0x27, 0x9A, 0x0B, 0x00, 0x81, 0x04, 0x84, 0xC1, 0x40, 0xA7, 0xC2, 0xE0, 0x00, 0x81, 0x2E, 0x81, 0xEE, 0x6D, 0x00, 0x0A, 0x90, 0x3D, 0x5A, 0x00, 0x58, 0x90, 0x3D, 0x00, 0x0F, 0x83, 0x1B, 0x00, 0x36, 0x95, 0x36, 0x00, 0x82, 0x35, 0xB1, 0x40, 0x00, 0x0C, 0x96, 0x5B, 0x00, 0x3C, 0x83, 0xC5, 0x60, 0x00, 0x7B, 0x88, 0x23, 0x00, 0x06, 0x83, 0x78, 0x00, 0x18, 0x88, 0x02, 0x00, 0x18, 0x83, 0xCE, 0x00, 0x00, 0x81, 0x19, 0x84, 0xD2, 0x00, 0x00, 0x45, 0xE2, 0x6B, 0x00, 0x6C, 0x81, 0xEE, 0x6D, 0x00, 0x06, 0xA9, 0x17, 0x5F, 0x5D, 0x00, 0x5B, 0x90, 0x3D, 0x00, 0x45, 0xD1, 0x3C, 0x00, 0x42, 0x88, 0x20, 0x00, 0x42, 0xBA, 0x64, 0x00, 0x81, 0x3A, 0x84, 0xC9, 0x66, 0x00, 0x3F, 0x83, 0xD6, 0x20, 0x00, 0x7B, 0xDD, 0x12, 0x00, 0x36, 0x82, 0xD2, 0x20, 0x00, 0x81, 0x16, 0x84, 0xE2, 0x40, 0xE9, 0xF0, 0xF7, 0x00, 0x54, 0x81, 0xEE, 0x6D, 0x76, 0x88, 0x00, 0x58, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x98, 0x5A, 0x00, 0x5D, 0x90, 0x3D, 0x00, 0x0F, 0xAD, 0x15, 0x00, 0x78, 0x88, 0x20, 0x00, 0x81, 0x70, 0xD2, 0x40, 0x00, 0x1B, 0x82, 0xA8, 0x56, 0x00, 0x36, 0x88, 0x23, 0x00, 0x75, 0x82, 0xB9, 0x43, 0x00, 0x51, 0x88, 0x20, 0x00, 0x7B, 0x84, 0xD2, 0x0F, 0xD3, 0xE0, 0xF0, 0x00, 0x81, 0x2E, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x4C, 0x4B, 0x00, 0x58, 0x84, 0xD1, 0x7A, 0x00, 0x15, 0xD5, 0x6D, 0x00, 0x75, 0x88, 0x20, 0x00, 0x0C, 0x42, 0x00, 0x81, 0x4C, 0x84, 0xF8, 0x6E, 0x00, 0x21, 0xAB, 0x0D, 0x00, 0x48, 0x83, 0xF7, 0x20, 0x00, 0x75, 0xE5, 0x35, 0x00, 0x06, 0xB2, 0x77, 0x00, 0x18, 0x81, 0x43, 0x00, 0x06, 0xBE, 0x38, 0x00, 0x42, 0x9D, 0x32, 0x00, 0x66, 0x88, 0x20, 0xC4, 0xD6, 0xEA, 0x00, 0x79, 0x81, 0xEE, 0x6D, 0x77, 0x00, 0x3A, 0xA9, 0x17, 0x5E, 0x5C, 0xBF, 0x00, 0x54, 0x81, 0xBD, 0x3F, 0x00, 0x1B, 0x9F, 0x7C, 0x00, 0x33, 0x8D, 0x0A, 0x00, 0x42, 0x88, 0x20, 0x00, 0x0F, 0x82, 0xBF, 0x43, 0x00, 0x81, 0x67, 0xE0, 0x7E, 0x00, 0x4B, 0x84, 0x87, 0x60, 0x00, 0x75, 0x9B, 0x15, 0x00, 0x06, 0x92, 0x06, 0x00, 0x15, 0xA2, 0x01, 0x00, 0x09, 0xA2, 0x5E, 0x00, 0x39, 0x91, 0x59, 0x00, 0x6F, 0xA1, 0x0F, 0xA6, 0xC0, 0xE0, 0x00, 0x81, 0x0A, 0x81, 0xEE, 0x6D, 0x68, 0x6E, 0x00, 0x25, 0xA9, 0x17, 0x5F, 0x5D, 0xBF, 0x4E, 0x4E, 0x00, 0x64, 0x81, 0xEE, 0x76, 0x00, 0x0C, 0x87, 0x1F, 0x00, 0x33, 0x83, 0xCD, 0x17, 0x00, 0x4E, 0x81, 0x84, 0x00, 0x00, 0x81, 0x61, 0x83, 0xA3, 0x62, 0x00, 0x09, 0xC1, 0x6E, 0x00, 0x4E, 0x84, 0x98, 0x20, 0x00, 0x75, 0x83, 0xD0, 0x50, 0x00, 0x09, 0x82, 0xA1, 0x5B, 0x00, 0x09, 0xD3, 0x5C, 0x00, 0x06, 0x81, 0xF3, 0x42, 0x00, 0x06, 0xE7, 0x52, 0x00, 0x3F, 0x8B, 0x6B, 0x00, 0x6C, 0xA1, 0x0F, 0x90, 0xB0, 0xD8, 0x00, 0x51, 0xE2, 0x6B, 0x00, 0x5A, 0x81, 0xEE, 0x6D, 0x00, 0x06, 0x98, 0x5A, 0x00, 0x66, 0x90, 0x3D, 0x00, 0x42, 0x97, 0x5F, 0x00, 0x3F, 0x88, 0x20, 0x00, 0x0F, 0x81, 0xAE, 0x15, 0x00, 0x81, 0x61, 0x82, 0xF1, 0x7E, 0x00, 0x09, 0x81, 0xBC, 0x1D, 0x00, 0x4E, 0x84, 0xA8, 0x60, 0x00, 0x75, 0x98, 0x63, 0x00, 0x1B, 0xA0, 0x2F, 0x00, 0x45, 0x94, 0x08, 0x00, 0x69, 0xA1, 0x0F, 0x00, 0x81, 0x2B, 0x81, 0xEE, 0x6D, 0x00, 0x6F, 0x90, 0x3D, 0x00, 0x12, 0xA1, 0x03, 0x00, 0x30, 0x8D, 0x58, 0x00, 0x4B, 0x81, 0xA5, 0x00, 0x00, 0x81, 0x64, 0x81, 0xC6, 0x06, 0x00, 0x57, 0x84, 0xB9, 0x20, 0x00, 0x7B, 0xAB, 0x58, 0x00, 0x06, 0x81, 0xB5, 0x49, 0x00, 0x09, 0x81, 0xCF, 0x2A, 0x00, 0x2A, 0x81, 0xB7, 0x03, 0x00, 0x81, 0x07, 0xA1, 0x0F, 0xE1, 0xEA, 0xF5, 0x00, 0x74, 0x81, 0xEE, 0x6D, 0x00, 0x05, 0x90, 0x3D, 0x00, 0x38, 0xA9, 0x17, 0x00, 0x69, 0x90, 0x3D, 0x00, 0x12, 0xC9, 0x1F, 0x00, 0x30, 0x87, 0x25, 0x00, 0x4B, 0x81, 0xB5, 0x40, 0x00, 0x81, 0x61, 0x98, 0x5D, 0x00, 0x09, 0xB1, 0x3A, 0x00, 0x54, 0x84, 0xC9, 0x60, 0x00, 0x81, 0x5B, 0xBC, 0x18, 0x00, 0x5D, 0xA1, 0x0F, 0xD2, 0xDF, 0xEF, 0x00, 0x81, 0x05, 0x81, 0xEE, 0x6D, 0x00, 0x29, 0xE2, 0x6B, 0x5E, 0x5C, 0xBF, 0x4E, 0x4D, 0x00, 0x67, 0x90, 0x3D, 0x00, 0x42, 0x81, 0xBC, 0x68, 0x00, 0x3C, 0x81, 0xC6, 0x00, 0x00, 0x0C, 0x83, 0x75, 0x00, 0x81, 0x64, 0x84, 0xA0, 0x43, 0x00, 0x81, 0x4C, 0x84, 0xDA, 0x20, 0x00, 0x81, 0x49, 0x85, 0xC5, 0x4F, 0xC3, 0xD4, 0xEA, 0x00, 0x81, 0x16, 0x81, 0xEE, 0x6D, 0x64, 0x00, 0x17, 0x98, 0x5A, 0x5E, 0x5C, 0xBF, 0x3C, 0x3D, 0x00, 0x70, 0x82, 0xE2, 0x24, 0x00, 0x0C, 0x97, 0x68, 0x00, 0x2D, 0xCF, 0x16, 0x00, 0x39, 0x88, 0x20, 0x00, 0x39, 0x81, 0xBE, 0x52, 0x00, 0x83, 0x09, 0x84, 0xEA, 0x60, 0x00, 0x06, 0xD2, 0x28, 0x00, 0x06, 0x82, 0xCC, 0x38, 0x00, 0x3C, 0x85, 0x9C, 0x20, 0x00, 0x7E, 0xA1, 0x0F, 0xB4, 0xC9, 0xE4, 0x00, 0x81, 0x25, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x53, 0x52, 0x00, 0x52, 0x81, 0xDE, 0x39, 0x00, 0x30, 0x90, 0x43, 0x00, 0x2A, 0x9E, 0x21, 0x00, 0x45, 0x81, 0xE7, 0x00, 0x00, 0x81, 0x67, 0x84, 0xB1, 0x00, 0x00, 0x81, 0x4C, 0x84, 0xFB, 0x20, 0x00, 0x12, 0x83, 0x45, 0x00, 0x3C, 0x85, 0xAC, 0x60, 0x00, 0x7B, 0xA1, 0x0F, 0xA5, 0xBD, 0xDF, 0x00, 0x81, 0x25, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x3E, 0x3F, 0x00, 0x76, 0x82, 0xFB, 0x01, 0x00, 0x0F, 0xEE, 0x4A, 0x00, 0x33, 0x85, 0xA8, 0x1D, 0x00, 0x39, 0x81, 0xA1, 0x02, 0x00, 0x81, 0x67, 0xEB, 0x14, 0x00, 0x81, 0x4C, 0x85, 0x8B, 0x60, 0x00, 0x0C, 0x82, 0x99, 0x65, 0x00, 0x45, 0x85, 0xBD, 0x20, 0x00, 0x78, 0xA1, 0x0F, 0x95, 0xB2, 0xD9, 0x00, 0x7B, 0x81, 0xEE, 0x6D, 0x00, 0x08, 0x90, 0x3D, 0x00, 0x28, 0xA9, 0x17, 0x00, 0x75, 0x90, 0x3D, 0x00, 0x15, 0xF0, 0x52, 0x00, 0x27, 0x85, 0x47, 0x00, 0x30, 0x88, 0x20, 0x00, 0x12, 0x66, 0x00, 0x81, 0x6A, 0x81, 0xBD, 0x54, 0x00, 0x81, 0x4C, 0x85, 0x9C, 0x20, 0x00, 0x06, 0x78, 0x00, 0x78, 0x84, 0x93, 0x48, 0x00, 0x4B, 0xA1, 0x0F, 0x00, 0x81, 0x25, 0x81, 0xEE, 0x6D, 0x00, 0x06, 0x98, 0x5A, 0x5E, 0x5B, 0x00, 0x73, 0xA0, 0x7A, 0x00, 0x1E, 0x94, 0x32, 0x00, 0x21, 0x85, 0xDB, 0x3E, 0x00, 0x2D, 0x88, 0x20, 0x00, 0x12, 0x60, 0x00, 0x81, 0x64, 0xDA, 0x51, 0x00, 0x12, 0xA3, 0x68, 0x00, 0x51, 0x85, 0xAC, 0x60, 0x00, 0x72, 0x82, 0x47, 0x00, 0x81, 0x01, 0x83, 0xBF, 0x4E, 0x00, 0x21, 0x85, 0xC6, 0x3E, 0x00, 0x27, 0x88, 0x20, 0x00, 0x81, 0x22, 0x81, 0xEE, 0x6D, 0x00, 0x09, 0x90, 0x3D, 0x46, 0x46, 0x7D, 0x00, 0x81, 0x13, 0x81, 0xC1, 0x1F, 0x00, 0x1E, 0x85, 0xEB, 0x7E, 0x00, 0x27, 0x88, 0x20, 0x00, 0x0F, 0x81, 0x81, 0x3C, 0x00, 0x7E, 0x83, 0x99, 0x7C, 0x00, 0x81, 0x04, 0x82, 0x87, 0x7A, 0x00, 0x4E, 0x85, 0xBD, 0x20, 0x00, 0x72, 0x93, 0x04, 0x00, 0x06, 0x83, 0x4E, 0x00, 0x81, 0x07, 0x83, 0xD7, 0x27, 0x00, 0x39, 0x88, 0x1D, 0xE8, 0xEE, 0xF7, 0x00, 0x13, 0x90, 0x3D, 0x00, 0x81, 0x0F, 0x81, 0xEE, 0x6D, 0x00, 0x08, 0xB9, 0x54, 0x93, 0x00, 0x81, 0x1C, 0x82, 0x8D, 0x3E, 0xCC, 0xCD, 0xD2, 0x00, 0x15, 0x88, 0x26, 0x00, 0x21, 0x88, 0x20, 0x00, 0x06, 0x82, 0xFA, 0x1B, 0x00, 0x15, 0x83, 0xF3, 0x46, 0x00, 0x81, 0x73, 0x84, 0xA0, 0x49, 0x00, 0x09, 0x81, 0xA7, 0x71, 0x00, 0x4E, 0x85, 0xCD, 0x60, 0x00, 0x78, 0xA9, 0x1D, 0x00, 0x81, 0x04, 0xC2, 0x75, 0x67, 0x68, 0x78, 0x00, 0x39, 0xA1, 0x0F, 0xE1, 0xE8, 0xF4, 0x00, 0x81, 0x1F, 0x81, 0xEE, 0x6D, 0x00, 0x06, 0xA9, 0x17, 0x00, 0x5D, 0x81, 0x83, 0x65, 0x00, 0x4B, 0x8B, 0x17, 0x00, 0x06, 0x81, 0x9A, 0x01, 0x00, 0x0C, 0x84, 0x16, 0x00, 0x1B, 0x88, 0x20, 0x00, 0x0C, 0x83, 0xF3, 0x2E, 0x00, 0x12, 0x48, 0x00, 0x81, 0x79, 0x81, 0xC5, 0x68, 0x00, 0x09, 0xBC, 0x4B, 0x00, 0x3F, 0x8A, 0x1F, 0x00, 0x09, 0xA8, 0x22, 0x00, 0x78, 0xB3, 0x7E, 0xD9, 0xD9, 0xDD, 0x00, 0x18, 0x84, 0xF2, 0x68, 0x00, 0x72, 0xBA, 0x67, 0x00, 0x36, 0xA1, 0x0F, 0xE0, 0xE8, 0xF4, 0x00, 0x36, 0xB9, 0x54, 0x00, 0x69, 0x81, 0xEE, 0x6D, 0x5A, 0x59, 0xB1, 0x00, 0x51, 0x81, 0xFF, 0x2D, 0x00, 0x63, 0xAC, 0x26, 0x00, 0x06, 0x81, 0xA9, 0x01, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0xB1, 0x76, 0x00, 0x09, 0x82, 0xB7, 0x7D, 0x00, 0x1E, 0x81, 0xA0, 0x55, 0x00, 0x81, 0x04, 0x84, 0xC7, 0x1F, 0x00, 0x81, 0x04, 0xA3, 0x65, 0x00, 0x3C, 0x81, 0x93, 0x7E, 0x00, 0x81, 0x01, 0x85, 0xEE, 0x60, 0x00, 0x06, 0x83, 0x83, 0x51, 0x00, 0x06, 0x89, 0x1E, 0xA6, 0xA7, 0xB0, 0x00, 0x15, 0x82, 0xAB, 0x38, 0x00, 0x6C, 0x91, 0x56, 0x00, 0x36, 0xA1, 0x0F, 0xD1, 0xDD, 0xEF, 0x00, 0x49, 0xE2, 0x6B, 0x00, 0x50, 0x81, 0xEE, 0x6D, 0x5A, 0x5A, 0xB1, 0x4A, 0x4A, 0x85, 0x00, 0x5D, 0x81, 0x8B, 0x7F, 0x00, 0x81, 0x10, 0xC5, 0x12, 0x00, 0x1B, 0x84, 0x8C, 0x1A, 0x00, 0x81, 0x76, 0x81, 0xED, 0x24, 0x00, 0x36, 0x98, 0x66, 0x00, 0x0F, 0x85, 0xE5, 0x3C, 0x00, 0x81, 0x19, 0x86, 0x86, 0x66, 0x00, 0x72, 0x82, 0xC5, 0x3D, 0x00, 0x30, 0xA1, 0x0F, 0xC2, 0xD1, 0xE9, 0x00, 0x81, 0x0D, 0x81, 0xEE, 0x6D, 0x5F, 0x61, 0xBA, 0x53, 0x55, 0x9C, 0x4B, 0x4C, 0x86, 0x00, 0x81, 0x16, 0x90, 0x34, 0x00, 0x18, 0x8C, 0x2A, 0x00, 0x45, 0x81, 0xB0, 0x65, 0x00, 0x21, 0xB2, 0x0B, 0x00, 0x81, 0x73, 0x83, 0x8C, 0x75, 0x00, 0x06, 0x87, 0x61, 0x00, 0x2D, 0x82, 0x17, 0x00, 0x0F, 0x81, 0xA5, 0x3C, 0x00, 0x7B, 0x81, 0xC6, 0x0F, 0x00, 0x21, 0x82, 0xBB, 0x78, 0x00, 0x75, 0xC5, 0x57, 0x00, 0x2D, 0xA1, 0x0F, 0xC1, 0xD0, 0xE9, 0x00, 0x81, 0x01, 0x81, 0xEE, 0x6D, 0x5B, 0x5F, 0xAC, 0x52, 0x55, 0x95, 0x46, 0x48, 0x78, 0x3A, 0x3C, 0x00, 0x6A, 0xEA, 0x73, 0x00, 0x54, 0x82, 0x77, 0x00, 0x24, 0x82, 0xEB, 0x03, 0x00, 0x12, 0x12, 0x00, 0x82, 0x17, 0x84, 0x9F, 0x12, 0x00, 0x0F, 0x82, 0x92, 0x19, 0x00, 0x27, 0x98, 0x24, 0x00, 0x0F, 0x84, 0x9F, 0x30, 0x00, 0x82, 0x17, 0x81, 0xE1, 0x0C, 0x00, 0x2A, 0xA1, 0x0F, 0xC1, 0xD0, 0xE9, 0x00, 0x66, 0x84, 0xC0, 0x45, 0x00, 0x0F, 0x90, 0x3D, 0x5A, 0x5F, 0xA5, 0x4D, 0x51, 0x87, 0x44, 0x46, 0x71, 0x00, 0x81, 0x52, 0x84, 0x97, 0x34, 0x00, 0x06, 0x84, 0xD1, 0x5C, 0x00, 0x1E, 0x90, 0x52, 0x00, 0x06, 0xA1, 0x1E, 0x00, 0x81, 0x04, 0x83, 0xEC, 0x27, 0x00, 0x81, 0x28, 0x88, 0x23, 0x00, 0x09, 0x83, 0xA3, 0x2F, 0x00, 0x15, 0x82, 0x32, 0x5A, 0x5C, 0x6D, 0x00, 0x0C, 0x84, 0x88, 0x73, 0x00, 0x06, 0x82, 0x62, 0x00, 0x82, 0x1D, 0x82, 0x92, 0x4C, 0x00, 0x27, 0xA1, 0x0F, 0xC1, 0xCF, 0xE9, 0x00, 0x40, 0xE2, 0x6B, 0x00, 0x26, 0xA9, 0x17, 0x63, 0x6B, 0xB6, 0x59, 0x5E, 0x9F, 0x4B, 0x4F, 0x80, 0x3E, 0x41, 0x00, 0x81, 0x6B, 0x8E, 0x29, 0x00, 0x15, 0x81, 0xE3, 0x14, 0x00, 0x82, 0x2F, 0x81, 0xFD, 0x6D, 0x00, 0x0C, 0x87, 0x76, 0x00, 0x0C, 0xBC, 0x4E, 0x00, 0x1B, 0x84, 0xD5, 0x00, 0xD9, 0xD9, 0xDD, 0x00, 0x81, 0x0A, 0x8A, 0x79, 0x00, 0x06, 0x81, 0xCF, 0x42, 0x00, 0x6C, 0xDA, 0x60, 0x00, 0x4B, 0xA1, 0x0F, 0xC1, 0xCF, 0xE9, 0x00, 0x5A, 0x81, 0xEE, 0x6D, 0x62, 0x6B, 0xAF, 0x53, 0x5A, 0x90, 0x45, 0x4A, 0x71, 0x00, 0x5A, 0x84, 0xE9, 0x65, 0x00, 0x83, 0x60, 0x81, 0xF5, 0x4A, 0x00, 0x1B, 0xC4, 0x20, 0x00, 0x18, 0x93, 0x19, 0x00, 0x81, 0x0A, 0x83, 0x97, 0x08, 0x00, 0x1B, 0x83, 0xBD, 0x46, 0x00, 0x81, 0x0A, 0x85, 0x8F, 0x3A, 0x00, 0x1E, 0xA1, 0x0F, 0xB1, 0xC3, 0xE3, 0x00, 0x4B, 0x81, 0xEE, 0x6D, 0x6C, 0x78, 0xC0, 0x60, 0x6A, 0xA8, 0x51, 0x58, 0x89, 0x42, 0x00, 0x53, 0x85, 0x82, 0x39, 0x00, 0x84, 0x01, 0x88, 0x26, 0x00, 0x06, 0x83, 0x96, 0x7C, 0x00, 0x1B, 0x82, 0xF6, 0x14, 0x00, 0x81, 0x0D, 0xFE, 0x03, 0x00, 0x09, 0x81, 0x87, 0x3F, 0xE6, 0xE6, 0xE9, 0xCC, 0xCD, 0xD2, 0x00, 0x09, 0x84, 0xEA, 0x57, 0x00, 0x09, 0x0C, 0x00, 0x1E, 0xD6, 0x77, 0x00, 0x81, 0x07, 0xA1, 0x0F, 0xA1, 0xB6, 0xDD, 0x00, 0x3F, 0x81, 0xEE, 0x6D, 0x6A, 0x78, 0xB9, 0x5A, 0x64, 0x9A, 0x4B, 0x51, 0x7A, 0x3F, 0x43, 0x00, 0x83, 0x61, 0x82, 0x8D, 0x38, 0x00, 0x81, 0x16, 0x97, 0x32, 0x00, 0x81, 0x16, 0xAB, 0x5B, 0x00, 0x0F, 0x83, 0xB5, 0x05, 0x00, 0x06, 0x85, 0x9C, 0x2F, 0x00, 0x09, 0xB3, 0x09, 0x00, 0x06, 0x82, 0xE2, 0x69, 0x00, 0x81, 0x0A, 0x81, 0x3A, 0x00, 0x18, 0xA1, 0x0F, 0xA1, 0xB6, 0xDD, 0x00, 0x33, 0xB9, 0x54, 0x64, 0x72, 0xAB, 0x54, 0x5D, 0x8B, 0x48, 0x4E, 0x73, 0x38, 0x3B, 0x00, 0x82, 0x42, 0x84, 0xC0, 0x12, 0x00, 0x83, 0x57, 0x89, 0x45, 0x00, 0x0C, 0x84, 0xA0, 0x40, 0x00, 0x06, 0xF5, 0x18, 0x00, 0x0F, 0x91, 0x5F, 0x00, 0x81, 0x0D, 0x9A, 0x0B, 0x00, 0x18, 0xA1, 0x0F, 0xA0, 0xB5, 0xDD, 0x00, 0x24, 0xA9, 0x17, 0x73, 0x86, 0xC4, 0x62, 0x70, 0xA4, 0x51, 0x5A, 0x83, 0x44, 0x4A, 0x00, 0x4F, 0x85, 0xBB, 0x78, 0x00, 0x85, 0x59, 0x88, 0x20, 0x00, 0x0C, 0xF3, 0x40, 0x00, 0x06, 0xDB, 0x6A, 0x00, 0x0F, 0x98, 0x4E, 0x00, 0x3F, 0x84, 0xDD, 0x38, 0x00, 0x66, 0x83, 0xA2, 0x10, 0x00, 0x05, 0x88, 0x20, 0x00, 0x16, 0x98, 0x5A, 0x6D, 0x7F, 0xB5, 0x5B, 0x68, 0x94, 0x4E, 0x57, 0x7C, 0x3D, 0x41, 0x5B, 0x00, 0x86, 0x27, 0x88, 0x14, 0x00, 0x1E, 0x88, 0x20, 0x00, 0x0F, 0xBA, 0x70, 0x00, 0x06, 0xE3, 0x1E, 0x00, 0x81, 0x1F, 0xA3, 0x6E, 0x99, 0xA7, 0xC6, 0x00, 0x09, 0x90, 0x3D, 0x78, 0x90, 0xC7, 0x6A, 0x7D, 0xAE, 0x58, 0x65, 0x8D, 0x46, 0x4D, 0x6C, 0x38, 0x3C, 0x00, 0x86, 0x19, 0x98, 0x39, 0x00, 0x2D, 0xDA, 0x60, 0x00, 0x09, 0xBA, 0x67, 0x00, 0x0F, 0x81, 0xB9, 0x7A, 0x00, 0x06, 0xFC, 0x79, 0x00, 0x81, 0x76, 0x85, 0xC0, 0x7A, 0x00, 0x86, 0x06, 0x88, 0x20, 0x00, 0x06, 0x81, 0xFF, 0x42, 0x00, 0x09, 0x88, 0x02, 0x00, 0x06, 0x97, 0x35, 0x00, 0x06, 0x84, 0xED, 0x15, 0x00, 0x09, 0xD3, 0x65, 0x00, 0x83, 0x63, 0x82, 0xBD, 0x0B, 0x00, 0x84, 0x1F, 0x98, 0x63, 0x00, 0x09, 0x81, 0x8D, 0x18, 0x00, 0x12, 0x82, 0xA0, 0x2D, 0x00, 0x82, 0x35, 0x85, 0x86, 0x0D, 0x00, 0x85, 0x5C, 0x88, 0x2F, 0x00, 0x06, 0x83, 0x9C, 0x40, 0x00, 0x06, 0x84, 0x90, 0x0C, 0x00, 0x83, 0x63, 0x82, 0xC5, 0x25, 0x00, 0x88, 0x0E, 0x8B, 0x7D, 0x00, 0x88, 0x74, 0x88, 0x74, 0x00, 0x06, 0xB4, 0x46, 0x00, 0x09, 0x86, 0x83, 0x5D, 0x00, 0x06, 0xB5, 0x71, 0xC0, 0xC0, 0xC7, 0x00, 0x24, 0x84, 0xA5, 0x09, 0x00, 0x87, 0x61, 0x88, 0x1D, 0x00, 0x21, 0xE8, 0x74, 0x00, 0x82, 0x0B, 0x81, 0x8C, 0x2F, 0x00, 0x85, 0x26, 0x87, 0x52, 0x00, 0x06, 0xF8, 0x6C, 0x00, 0x42, 0xA4, 0x5A, 0x00, 0x2A, 0x82, 0xC5, 0x55, 0x00, 0x30, 0x82, 0xB7, 0x3B, 0x00, 0x81, 0x64, 0x85, 0xC4, 0x03, 0x00, 0x30, 0x83, 0xCF, 0x1C, 0x00, 0x81, 0x3A, 0x84, 0x8A, 0x5D, 0x00, 0x83, 0x39, 0x82, 0xF6, 0x56, 0xC0, 0xC0, 0xC7, 0x00, 0x3C, 0x98, 0x00, 0x00, 0x30, 0x81, 0x9D, 0x0D, 0x00, 0x81, 0x7C, 0xB6, 0x09, 0x00, 0x27, 0x84, 0x82, 0x19, 0x00, 0x83, 0x1B, 0x85, 0xD8, 0x02, 0x00, 0x81, 0x76, 0x82, 0xF6, 0x53, 0x00, 0x39, 0x82, 0x8F, 0x2B, 0x00, 0x33, 0x81, 0xEA, 0x3F, 0x00, 0x81, 0x76, 0x81, 0xC6, 0x09, 0x00, 0x51, 0x81, 0xEC, 0x6B, 0x00, 0x84, 0x67, 0x90, 0x3D, 0x00, 0x3C, 0x81, 0xA9, 0x76, 0x00, 0x12, 0x81, 0xEE, 0x79, 0x00, 0x06, 0x81, 0xB5, 0x31, 0x00, 0x0C, 0x4E, 0x5A, 0x5C, 0x6D, 0x00, 0x12, 0x85, 0xF7, 0x12, 0x00, 0x81, 0x70, 0x81, 0xD6, 0x49, 0x00, 0x12, 0x9B, 0x03, 0x00, 0x09, 0x81, 0x9F, 0x12, 0x00, 0x85, 0x14, 0x98, 0x60, 0x00, 0x0F, 0x83, 0xB8, 0x56, 0x00, 0x39, 0x84, 0x6D, 0x00, 0x0F, 0x85, 0x74, 0x00, 0x1B, 0x81, 0xC3, 0x60, 0x00, 0x12, 0x81, 0x87, 0x33, 0x00, 0x81, 0x6D, 0x85, 0x62, 0x00, 0x0F, 0x82, 0xE2, 0x27, 0x00, 0x81, 0x3D, 0x81, 0xA4, 0x4A, 0x00, 0x06, 0x84, 0xF3, 0x09, 0x00, 0x0C, 0x81, 0xBE, 0x6A, 0x00, 0x06, 0x81, 0xA0, 0x76, 0x00, 0x83, 0x57, 0x83, 0xA8, 0x13, 0x00, 0x39, 0x83, 0xD2, 0x73, 0x00, 0x0F, 0x90, 0x3D, 0x00, 0x21, 0x48, 0x00, 0x0F, 0xD7, 0x12, 0x00, 0x81, 0x2B, 0x84, 0xF0, 0x45, 0x00, 0x4B, 0x81, 0x81, 0x06, 0x00, 0x81, 0x3D, 0x8A, 0x16, 0x00, 0x0F, 0x83, 0x42, 0x00, 0x09, 0x88, 0x20, 0x00, 0x1E, 0x82, 0xCA, 0x1B, 0x00, 0x83, 0x33, 0x88, 0x20, 0x00, 0x45, 0x83, 0xD5, 0x25, 0x00, 0x0F, 0x81, 0xEF, 0x59, 0x00, 0x24, 0x84, 0x1F, 0x00, 0x0F, 0x83, 0xDF, 0x35, 0x00, 0x81, 0x64, 0x90, 0x43, 0x00, 0x0C, 0x82, 0xA2, 0x56, 0x00, 0x81, 0x40, 0x81, 0xD0, 0x2B, 0x00, 0x06, 0x90, 0x37, 0xA6, 0xA7, 0xB0, 0x00, 0x09, 0x82, 0x98, 0x46, 0x00, 0x0F, 0x85, 0x95, 0x61, 0x00, 0x83, 0x45, 0xBD, 0x40, 0x00, 0x0F, 0x98, 0x5D, 0x00, 0x39, 0xA8, 0x2B, 0x00, 0x36, 0x83, 0xEE, 0x4D, 0x00, 0x0C, 0xA7, 0x24, 0x00, 0x81, 0x64, 0x82, 0x98, 0x46, 0x00, 0x09, 0x81, 0xBD, 0x54, 0x00, 0x81, 0x40, 0x83, 0xBF, 0x2A, 0x00, 0x0F, 0x84, 0xBB, 0x5B, 0x00, 0x0C, 0x88, 0x20, 0x00, 0x1B, 0x85, 0xCD, 0x60, 0x00, 0x83, 0x33, 0x88, 0x20, 0x00, 0x0C, 0x95, 0x6F, 0x00, 0x39, 0x87, 0x22, 0x00, 0x0F, 0x98, 0x5D, 0x00, 0x2A, 0x94, 0x5C, 0x00, 0x0F, 0x82, 0xD2, 0x20, 0x00, 0x81, 0x61, 0xB1, 0x49, 0x00, 0x09, 0xA0, 0x7A, 0x00, 0x81, 0x40, 0x81, 0x6A, 0x00, 0x06, 0x8B, 0x59, 0x00, 0x09, 0x90, 0x22, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x12, 0x81, 0x84, 0x12, 0x00, 0x83, 0x39, 0x88, 0x20, 0x00, 0x0F, 0x85, 0xCB, 0x52, 0x00, 0x42, 0x88, 0x65, 0x00, 0x30, 0x83, 0xAD, 0x48, 0x00, 0x0C, 0xA7, 0x2D, 0x00, 0x81, 0x61, 0x8C, 0x72, 0x00, 0x81, 0x49, 0x82, 0x92, 0x16, 0x00, 0x0F, 0x81, 0x9C, 0x3F, 0x00, 0x15, 0x88, 0x20, 0x00, 0x83, 0x45, 0x83, 0xD1, 0x4E, 0x00, 0x0C, 0x98, 0x18, 0x00, 0x39, 0xA4, 0x54, 0x00, 0x0C, 0x87, 0x64, 0x00, 0x30, 0x8C, 0x36, 0x00, 0x0C, 0x88, 0x5C, 0x00, 0x81, 0x5E, 0x8C, 0x72, 0x00, 0x7B, 0x82, 0x8F, 0x4F, 0x00, 0x54, 0x92, 0x09, 0x00, 0x0C, 0x89, 0x66, 0x00, 0x83, 0x5A, 0x88, 0x20, 0x00, 0x45, 0x83, 0x8A, 0x7C, 0x00, 0x0C, 0x88, 0x65, 0x00, 0x30, 0x90, 0x04, 0x00, 0x0C, 0xCB, 0x1B, 0x00, 0x81, 0x5E, 0xA1, 0x03, 0x00, 0x54, 0x82, 0xB1, 0x20, 0x00, 0x7E, 0x98, 0x60, 0x00, 0x09, 0x84, 0x31, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x06, 0x82, 0x92, 0x07, 0x00, 0x83, 0x42, 0xA1, 0x00, 0x00, 0x42, 0x83, 0x83, 0x60, 0x00, 0x45, 0xA9, 0x62, 0x00, 0x81, 0x67, 0xD0, 0x08, 0x00, 0x7E, 0x82, 0xC9, 0x2C, 0x00, 0x5D, 0x83, 0xA4, 0x60, 0x00, 0x0F, 0xB1, 0x40, 0x00, 0x06, 0xB9, 0x78, 0x00, 0x83, 0x42, 0xF7, 0x26, 0x00, 0x42, 0x83, 0x94, 0x20, 0x00, 0x12, 0x83, 0xEF, 0x42, 0x00, 0x39, 0x82, 0xF0, 0x65, 0x00, 0x81, 0x61, 0xA9, 0x23, 0x00, 0x81, 0x4C, 0x88, 0x20, 0x00, 0x09, 0xBD, 0x52, 0x00, 0x06, 0x84, 0xC5, 0x56, 0x00, 0x06, 0x81, 0xF3, 0x33, 0x00, 0x06, 0x84, 0x0D, 0x00, 0x06, 0x88, 0x1D, 0x00, 0x83, 0x45, 0x83, 0xFA, 0x6B, 0x00, 0x0C, 0x81, 0xF4, 0x43, 0x00, 0x39, 0x88, 0x20, 0x00, 0x0C, 0xB9, 0x24, 0x00, 0x36, 0x45, 0x00, 0x81, 0x67, 0x83, 0xBD, 0x40, 0x00, 0x2A, 0x84, 0xF3, 0x00, 0x00, 0x81, 0x40, 0x84, 0xBA, 0x69, 0x00, 0x82, 0x32, 0x84, 0x9B, 0x6B, 0x00, 0x81, 0x22, 0xE8, 0x23, 0x00, 0x39, 0x83, 0x54, 0x00, 0x42, 0x84, 0x87, 0x21, 0x00, 0x81, 0x67, 0x88, 0x20, 0x00, 0x2D, 0x85, 0xA4, 0x40, 0x00, 0x81, 0x2E, 0x84, 0xB2, 0x46, 0x00, 0x06, 0xA5, 0x01, 0xE6, 0xE6, 0xE9, 0x00, 0x83, 0x4E, 0x81, 0xA4, 0x7D, 0x00, 0x42, 0x83, 0xC5, 0x60, 0x00, 0x42, 0x83, 0xF7, 0x62, 0x00, 0x81, 0x6D, 0x83, 0xCE, 0x00, 0x00, 0x7B, 0x85, 0xBC, 0x4F, 0x00, 0x84, 0x3A, 0x81, 0xC9, 0x66, 0x00, 0x3C, 0x88, 0x20, 0x00, 0x0F, 0xC9, 0x61, 0x00, 0x36, 0x87, 0x5E, 0x00, 0x81, 0x6A, 0x88, 0x20, 0x00, 0x09, 0x84, 0xEB, 0x4C, 0x00, 0x81, 0x52, 0x9A, 0x3B, 0x00, 0x82, 0x1D, 0x82, 0x94, 0x0C, 0x00, 0x81, 0x79, 0x88, 0x20, 0x00, 0x45, 0x83, 0xBC, 0x7E, 0x00, 0x81, 0x6A, 0x88, 0x20, 0x00, 0x09, 0xA3, 0x71, 0x00, 0x81, 0x46, 0x81, 0x8E, 0x16, 0x00, 0x0C, 0x81, 0xE5, 0x4F, 0x00, 0x09, 0xA4, 0x7B, 0x00, 0x06, 0x85, 0xCD, 0x78, 0x00, 0x83, 0x51, 0x88, 0x20, 0x00, 0x42, 0x83, 0xC5, 0x60, 0x00, 0x39, 0xD0, 0x17, 0x00, 0x81, 0x6D, 0x83, 0xE6, 0x60, 0x00, 0x09, 0x82, 0x86, 0x37, 0x00, 0x81, 0x49, 0x82, 0xB2, 0x66, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x82, 0x88, 0x06, 0x00, 0x0C, 0x84, 0x13, 0x00, 0x83, 0x45, 0x88, 0x23, 0x00, 0x42, 0xB9, 0x60, 0x00, 0x0C, 0xA9, 0x1D, 0x00, 0x39, 0xA9, 0x62, 0x00, 0x81, 0x6D, 0x88, 0x20, 0x00, 0x09, 0xD4, 0x30, 0x00, 0x81, 0x40, 0x86, 0x42, 0xE6, 0xE6, 0xE9, 0x00, 0x09, 0x82, 0xAA, 0x07, 0x00, 0x0F, 0xCA, 0x20, 0x00, 0x83, 0x54, 0xC2, 0x00, 0x00, 0x36, 0x8F, 0x7E, 0x00, 0x0C, 0xC1, 0x3B, 0x00, 0x39, 0xCE, 0x30, 0x00, 0x81, 0x70, 0x82, 0xB7, 0x14, 0x00, 0x7E, 0x82, 0xD1, 0x5B, 0x00, 0x4B, 0x9A, 0x29, 0x00, 0x09, 0x81, 0x40, 0x00, 0x0F, 0x88, 0x20, 0x00, 0x21, 0x85, 0xAF, 0x39, 0x00, 0x83, 0x2A, 0x81, 0xC5, 0x23, 0x00, 0x3C, 0xA0, 0x3E, 0x00, 0x3F, 0x83, 0xB5, 0x5C, 0x00, 0x81, 0x79, 0x84, 0xA8, 0x60, 0x00, 0x0C, 0x81, 0x85, 0x79, 0x00, 0x81, 0x37, 0xC8, 0x48, 0x00, 0x06, 0x81, 0xA0, 0x25, 0x00, 0x83, 0x63, 0xE3, 0x00, 0x00, 0x3C, 0x8F, 0x3C, 0x00, 0x0F, 0x82, 0x93, 0x11, 0x00, 0x82, 0x2C, 0x84, 0xB9, 0x20, 0x00, 0x0C, 0x82, 0xD2, 0x23, 0x00, 0x0C, 0x83, 0xCC, 0x43, 0x00, 0x85, 0x11, 0xF3, 0x40, 0x00, 0x0F, 0x82, 0xEA, 0x41, 0x00, 0x39, 0xA0, 0x7D, 0x00, 0x39, 0x84, 0x0D, 0x00, 0x0C, 0x88, 0x65, 0x00, 0x81, 0x6D, 0x83, 0x8C, 0x0F, 0x00, 0x12, 0x81, 0xAD, 0x26, 0x00, 0x09, 0x81, 0xAD, 0x23, 0x00, 0x30, 0x84, 0xA7, 0x4A, 0x00, 0x72, 0x9B, 0x15, 0x00, 0x06, 0x82, 0xA8, 0x71, 0x00, 0x18, 0x88, 0x20, 0x00, 0x18, 0x85, 0xC5, 0x40, 0x00, 0x83, 0x6C, 0x81, 0x8C, 0x20, 0x00, 0x0F, 0x99, 0x1C, 0x00, 0x39, 0x9C, 0x6D, 0x00, 0x45, 0x81, 0x85, 0x01, 0x00, 0x82, 0x02, 0x84, 0xD0, 0x10, 0x00, 0x75, 0x84, 0x37, 0x00, 0x09, 0x89, 0x18, 0x00, 0x15, 0x81, 0x94, 0x40, 0x00, 0x83, 0x45, 0x81, 0xFF, 0x63, 0x00, 0x0F, 0xF2, 0x7E, 0x00, 0x2A, 0x8D, 0x0A, 0x00, 0x0F, 0x81, 0xC3, 0x3F, 0x00, 0x39, 0xC6, 0x1F, 0x00, 0x45, 0xA9, 0x62, 0x00, 0x81, 0x37, 0xAC, 0x1D, 0x00, 0x4B, 0x83, 0xC3, 0x34, 0x00, 0x75, 0x81, 0xA6, 0x49, 0x00, 0x09, 0x81, 0xB9, 0x23, 0x00, 0x0C, 0x88, 0x20, 0x00, 0x06, 0x9A, 0x3B, 0x00, 0x83, 0x48, 0x81, 0xA5, 0x00, 0x00, 0x0F, 0x83, 0xD6, 0x20, 0x00, 0x27, 0x90, 0x43, 0x00, 0x48, 0x83, 0xCD, 0x3E, 0x00, 0x0F, 0xA9, 0x62, 0x00, 0x81, 0x6A, 0xCF, 0x04, 0x00, 0x12, 0x81, 0xCE, 0x1D, 0x00, 0x0C, 0x85, 0x9A, 0x6C, 0x00, 0x18, 0x83, 0xC4, 0x32, 0x00, 0x1B, 0x1B, 0x00, 0x78, 0xB1, 0x43, 0xF2, 0xF2, 0xF4, 0xA6, 0xA7, 0xB0, 0x00, 0x06, 0x81, 0x8C, 0x2F, 0x00, 0x06, 0x83, 0x83, 0x75, 0x00, 0x06, 0x84, 0x19, 0x00, 0x83, 0x4B, 0x82, 0x90, 0x20, 0x00, 0x33, 0x83, 0xC5, 0x5D, 0x00, 0x0F, 0x82, 0xCF, 0x4A, 0x00, 0x39, 0x98, 0x5D, 0x00, 0x0C, 0x96, 0x5E, 0x00, 0x81, 0x67, 0x83, 0xC5, 0x66, 0x00, 0x0F, 0x88, 0x1D, 0x00, 0x06, 0x86, 0x60, 0x00, 0x81, 0x37, 0x8A, 0x19, 0x00, 0x0F, 0x82, 0xF4, 0x30, 0x00, 0x30, 0x82, 0xF4, 0x6F, 0x00, 0x83, 0x36, 0x81, 0x9C, 0x66, 0x00, 0x21, 0x88, 0x23, 0x00, 0x0F, 0xF7, 0x56, 0x00, 0x3C, 0x94, 0x4A, 0x00, 0x0F, 0x84, 0xAF, 0x04, 0x00, 0x81, 0x73, 0xCD, 0x14, 0x00, 0x81, 0x40, 0x97, 0x05, 0x00, 0x06, 0x82, 0x98, 0x37, 0x00, 0x06, 0x82, 0x83, 0x46, 0xB3, 0xB4, 0xBC, 0x00, 0x81, 0x31, 0xB3, 0x09, 0x00, 0x82, 0x38, 0x84, 0xDD, 0x53, 0x00, 0x15, 0x85, 0xC5, 0x34, 0x00, 0x15, 0x83, 0xB4, 0x67, 0x00, 0x39, 0x90, 0x3D, 0x00, 0x0F, 0x91, 0x38, 0x00, 0x81, 0x67, 0x81, 0xCA, 0x52, 0x00, 0x09, 0x8B, 0x0B, 0x00, 0x81, 0x3D, 0x8A, 0x10, 0x00, 0x06, 0x85, 0xA4, 0x37, 0x00, 0x83, 0x78, 0xF3, 0x4C, 0x00, 0x15, 0x9E, 0x15, 0x00, 0x15, 0x82, 0xF8, 0x6A, 0x00, 0x3C, 0xB9, 0x12, 0x00, 0x0C, 0x51, 0x00, 0x81, 0x67, 0x98, 0x5D, 0x00, 0x09, 0x81, 0x96, 0x6C, 0x00, 0x81, 0x40, 0x81, 0xE8, 0x73, 0x00, 0x81, 0x01, 0x83, 0xC5, 0x60, 0x00, 0x83, 0x00, 0x81, 0xBD, 0x6C, 0x00, 0x27, 0x81, 0xF6, 0x7B, 0x00, 0x39, 0xD1, 0x6F, 0x00, 0x0F, 0x90, 0x3D, 0x00, 0x81, 0x67, 0xD7, 0x0C, 0x00, 0x09, 0x92, 0x7E, 0x00, 0x81, 0x40, 0x92, 0x2D, 0x00, 0x0F, 0xB9, 0x60, 0x00, 0x83, 0x69, 0x88, 0x23, 0x00, 0x2A, 0xBF, 0x0F, 0x00, 0x3C, 0x81, 0xFF, 0x18, 0x00, 0x0F, 0x85, 0xC5, 0x3D, 0x00, 0x81, 0x6A, 0xB6, 0x0C, 0x00, 0x81, 0x49, 0xF3, 0x3D, 0x00, 0x57, 0x85, 0xF9, 0x20, 0x00, 0x83, 0x24, 0x88, 0x23, 0x73, 0x75, 0x83, 0x00, 0x15, 0x98, 0x4B, 0x00, 0x0F, 0xCF, 0x6A, 0x00, 0x3C, 0xE2, 0x29, 0x00, 0x0F, 0x89, 0x06, 0x00, 0x81, 0x67, 0x90, 0x3D, 0x00, 0x09, 0xC4, 0x6B, 0x00, 0x81, 0x43, 0xAB, 0x0A, 0x00, 0x09, 0x83, 0xBD, 0x40, 0x00, 0x0C, 0xD3, 0x77, 0x00, 0x81, 0x04, 0x83, 0xAD, 0x00, 0x00, 0x82, 0x6B, 0xB9, 0x75, 0x00, 0x09, 0x84, 0x9C, 0x18, 0x00, 0x0C, 0xA0, 0x26, 0x00, 0x42, 0x81, 0xA0, 0x61, 0x00, 0x0F, 0xAA, 0x0C, 0x00, 0x81, 0x6A, 0x90, 0x3D, 0x00, 0x54, 0x84, 0x98, 0x20, 0x00, 0x81, 0x1C, 0x82, 0x91, 0x5D, 0x00, 0x83, 0x69, 0x82, 0x89, 0x16, 0x00, 0x51, 0x83, 0x89, 0x06, 0x00, 0x0C, 0xBE, 0x38, 0x00, 0x81, 0x6A, 0x81, 0xFC, 0x09, 0x00, 0x81, 0x4C, 0x81, 0xBD, 0x60, 0x00, 0x81, 0x19, 0x83, 0xBD, 0x40, 0x00, 0x83, 0x4E, 0x83, 0xA2, 0x58, 0x00, 0x81, 0x6D, 0xE2, 0x71, 0x00, 0x81, 0x4F, 0x81, 0xC6, 0x00, 0x00, 0x86, 0x51, 0x82, 0xBC, 0x22, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x81, 0x40, 0x81, 0xC6, 0x00, 0x00, 0x09, 0x81, 0xD6, 0x25, 0x00, 0x86, 0x5A, 0x88, 0x23, 0x00, 0x81, 0x3D, 0xB1, 0x40, 0x00, 0x15, 0xCA, 0x14, 0x00, 0x06, 0xA9, 0x29, 0x00, 0x86, 0x48, 0x92, 0x12, 0x00, 0x09, 0x84, 0xE0, 0x74, 0x00, 0x88, 0x17, 0x88, 0x20, 0x00, 0x09, 0xD4, 0x36, 0x00, 0x81, 0x34, 0x86, 0x51, 0x00, 0x86, 0x63, 0x88, 0x20, 0x00, 0x09, 0x81, 0x86, 0x38, 0x00, 0x81, 0x34, 0x9F, 0x49, 0x00, 0x86, 0x63, 0x88, 0x20, 0x00, 0x0C, 0xC8, 0x5A, 0x00, 0x81, 0x31, 0x81, 0x82, 0x25, 0x00, 0x86, 0x66, 0x88, 0x20, 0x00, 0x09, 0x81, 0x97, 0x31, 0x00, 0x81, 0x31, 0xE1, 0x3D, 0x00, 0x09, 0x82, 0xD2, 0x08, 0x00, 0x0C, 0x81, 0x95, 0x38, 0x00, 0x09, 0x84, 0xBA, 0x21, 0x00, 0x60, 0x84, 0xDA, 0x20, 0x00, 0x85, 0x74, 0x98, 0x66, 0x00, 0x81, 0x2E, 0x83, 0xFF, 0x07, 0x00, 0x30, 0x82, 0xF6, 0x7A, 0x00, 0x86, 0x3C, 0x83, 0xBD, 0x40, 0x00, 0x0C, 0x82, 0xE4, 0x62, 0x00, 0x3F, 0x82, 0xFE, 0x31, 0x00, 0x6F, 0x81, 0x8C, 0x14, 0x00, 0x45, 0x85, 0xE6, 0x40, 0x00, 0x86, 0x27, 0x90, 0x46, 0x00, 0x0F, 0x81, 0xF1, 0x5E, 0x00, 0x09, 0x81, 0xC5, 0x7A, 0x00, 0x87, 0x2E, 0x83, 0x96, 0x3A, 0x00, 0x57, 0x82, 0xBC, 0x2E, 0x00, 0x4E, 0x84, 0xF0, 0x48, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x8F, 0x66, 0x90, 0x40, 0x00, 0x94, 0x62, 0x83, 0xD4, 0x36, 0x00, 0x9C, 0x28, 0x9C, 0x28, 0x00, 0xAA, 0x24, 0xAA, 0x24, 0x00, 0x06, 0xFC, 0x22, 0x00, 0x83, 0x45, 0x83, 0xCC, 0x67, 0x00, 0x84, 0x5B, 0x81, 0xBE, 0x2E, 0x00, 0x81, 0x0D, 0x84, 0xF1, 0x6A, 0x00, 0x86, 0x45, 0xF3, 0x40, 0x00, 0x48, 0x81, 0x9A, 0x79, 0x00, 0x09, 0x81, 0xD7, 0x11, 0x00, 0x83, 0x45, 0x83, 0xAB, 0x6D, 0x00, 0x84, 0x52, 0x88, 0x20, 0x00, 0x81, 0x40, 0x81, 0xCE, 0x71, 0x00, 0x86, 0x63, 0x88, 0x20, 0x00, 0x09, 0x82, 0xDD, 0x7F, 0x00, 0x88, 0x17, 0x88, 0x20, 0x00, 0x87, 0x4F, 0x81, 0xF8, 0x14, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x51, 0x88, 0x20, 0x00, 0x09, 0x82, 0xC2, 0x31, 0x00, 0x88, 0x17, 0x88, 0x20, 0x00, 0x09, 0x82, 0xB0, 0x25, 0x00, 0x87, 0x46, 0x81, 0xBE, 0x13, 0x00, 0x4E, 0x88, 0x20, 0x00, 0x0C, 0x85, 0xBC, 0x25, 0x00, 0x88, 0x11, 0xA9, 0x20, 0x00, 0x0C, 0x85, 0xBA, 0x74, 0x00, 0x88, 0x0E, 0xC2, 0x00, 0x4D, 0x4F, 0x62, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x82, 0xCD, 0x24, 0x00, 0x87, 0x37, 0xD2, 0x40, 0x00, 0x45, 0x86, 0x81, 0x55, 0x00, 0x82, 0x20, 0x84, 0xE5, 0x01, 0x00, 0x86, 0x1E, 0x88, 0x20, 0x00, 0x83, 0x54, 0x83, 0x8A, 0x6A, 0x00, 0x84, 0x46, 0x88, 0x20, 0xCC, 0xCD, 0xD2, 0x8D, 0x8E, 0x9A, 0x00, 0x87, 0x52, 0x81, 0xEF, 0x47, 0x00, 0x86, 0x42, 0x82, 0x86, 0x19, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x90, 0x40, 0x90, 0x40, 0x00, 0x89, 0x7E, 0x90, 0x40, 0x00, 0x86, 0x3F, 0x82, 0xB7, 0x59, 0x00, 0xD4, 0x33, 0x81, 0xFF, 0x21, 0x80, 0x81, 0x8F, 0x00, 0x06, 0x84, 0x96, 0x5D, 0x00, 0x88, 0x11, 0x82, 0xE2, 0x60, 0x9A, 0x9B, 0xA5, 0x00, 0x45, 0x86, 0x87, 0x3A, 0x00, 0x87, 0x52, 0x88, 0x20, 0x00, 0x12, 0x84, 0xD1, 0x7A, 0x00, 0x88, 0x0E, 0x88, 0x20, 0x00, 0x0C, 0x88, 0x1D, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x0F, 0x81, 0xDE, 0x1E, 0x00, 0x06, 0x21, 0x00, 0x12, 0xFC, 0x07, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0x3C, 0x00, 0x87, 0x49, 0x81, 0xC5, 0x74, 0x00, 0x1B, 0x84, 0x86, 0x1A, 0x00, 0x18, 0x82, 0xA0, 0x1B, 0x00, 0x18, 0x88, 0x20, 0x00, 0x09, 0x81, 0xE6, 0x74, 0x00, 0x81, 0x3A, 0x83, 0xC6, 0x25, 0x00, 0x86, 0x27, 0x83, 0xB5, 0x1A, 0x00, 0x1E, 0x81, 0xC5, 0x38, 0x00, 0x1E, 0x88, 0x20, 0x00, 0x0C, 0x84, 0xF3, 0x3F, 0x00, 0x83, 0x48, 0x85, 0xBC, 0x0A, 0x00, 0x84, 0x07, 0x88, 0x20, 0x00, 0x09, 0x82, 0x8F, 0x4F, 0x00, 0x1E, 0x87, 0x58, 0x00, 0x21, 0x88, 0x20, 0x00, 0x0C, 0x81, 0xF7, 0x3A, 0x00, 0x81, 0x6A, 0x84, 0x92, 0x41, 0x00, 0x85, 0x6B, 0xA0, 0x7A, 0x00, 0x1E, 0x81, 0xDE, 0x12, 0x00, 0x24, 0x88, 0x20, 0x00, 0x09, 0x84, 0xBC, 0x50, 0x00, 0x87, 0x49, 0x81, 0xEF, 0x1D, 0x00, 0x09, 0x81, 0xA5, 0x00, 0x00, 0x21, 0xA0, 0x38, 0x00, 0x27, 0x88, 0x20, 0x00, 0x09, 0x82, 0xB1, 0x20, 0x00, 0x87, 0x46, 0x90, 0x43, 0x00, 0x2A, 0x84, 0x90, 0x00, 0x00, 0x27, 0x88, 0x20, 0x00, 0x09, 0x83, 0xDF, 0x0B, 0x00, 0x87, 0x46, 0xA1, 0x06, 0x00, 0x2A, 0x85, 0xE6, 0x40, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x06, 0xB2, 0x0E, 0x00, 0x87, 0x46, 0x98, 0x63, 0x00, 0x2A, 0x82, 0xA8, 0x2C, 0x00, 0x2A, 0x88, 0x20, 0x00, 0x09, 0x54, 0x00, 0x88, 0x20, 0x88, 0x20, 0x00, 0x83, 0x72, 0x84, 0xD9, 0x28, 0x00, 0x84, 0x2E, 0x88, 0x20, 0x00, 0x87, 0x43, 0x82, 0xB1, 0x20, 0x00, 0x09, 0x85, 0x9E, 0x0D, 0x00, 0x21, 0x81, 0xCE, 0x20, 0x00, 0x87, 0x76, 0x88, 0x20, 0x00, 0x2A, 0x81, 0xDE, 0x60, 0x00, 0x87, 0x79, 0x88, 0x20, 0x00, 0x06, 0x82, 0xA8, 0x35, 0x00, 0x21, 0xC2, 0x00, 0x00, 0x06, 0xC9, 0x79, 0x00, 0x24, 0x85, 0xC4, 0x00, 0x00, 0x09, 0x84, 0xB1, 0x51, 0x00, 0x87, 0x46, 0x82, 0x90, 0x2C, 0x00, 0x09, 0x82, 0xB8, 0x72, 0x00, 0x1E, 0x87, 0x4F, 0x00, 0x2A, 0xB9, 0x36, 0x00, 0x09, 0x82, 0xCA, 0x00, 0x00, 0x87, 0x46, 0xD2, 0x40, 0x00, 0x09, 0xE2, 0x35, 0x00, 0x1E, 0xA1, 0x03, 0x00, 0x09, 0x27, 0x00, 0x21, 0x82, 0xB9, 0x19, 0x00, 0x27, 0x91, 0x11, 0x00, 0x87, 0x2B, 0x88, 0x23, 0x00, 0x24, 0xFB, 0x1B, 0x00, 0x09, 0x85, 0xD8, 0x5C, 0x00, 0x1E, 0xA1, 0x03, 0x00, 0x09, 0x98, 0x5D, 0x00, 0x87, 0x4C, 0x83, 0x9C, 0x43, 0x00, 0x09, 0x98, 0x63, 0x00, 0x1E, 0xA8, 0x52, 0x00, 0x09, 0x85, 0xA4, 0x6A, 0x00, 0x18, 0xC1, 0x59, 0x00, 0x09, 0xFB, 0x63, 0x00, 0x83, 0x4B, 0x85, 0xD4, 0x6A, 0x00, 0x84, 0x0D, 0xE3, 0x06, 0x00, 0x1E, 0x85, 0xB7, 0x3B, 0x00, 0x09, 0xB1, 0x19, 0x00, 0x15, 0x84, 0xB9, 0x44, 0x67, 0x68, 0x78, 0x00, 0x09, 0x81, 0x84, 0x48, 0x00, 0x87, 0x52, 0x82, 0x90, 0x6E, 0x00, 0x09, 0xA8, 0x55, 0x00, 0x1E, 0x81, 0x9C, 0x24, 0x00, 0x0F, 0x85, 0xD8, 0x1D, 0xB3, 0xB4, 0xBC, 0x9A, 0x9B, 0xA5, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0x85, 0xA7, 0x5E, 0x00, 0x81, 0x6D, 0x85, 0xF9, 0x32, 0x00, 0x85, 0x6B, 0x81, 0x94, 0x46, 0x00, 0x06, 0x87, 0x64, 0x00, 0x27, 0x81, 0x83, 0x62, 0x00, 0x18, 0x81, 0xAD, 0x14, 0x00, 0x09, 0x85, 0xED, 0x5F, 0x00, 0x87, 0x52, 0x88, 0x23, 0x00, 0x2A, 0x85, 0xD4, 0x40, 0x00, 0x15, 0x85, 0xB8, 0x0F, 0xF2, 0xF2, 0xF4, 0x00, 0x88, 0x0E, 0x82, 0xA9, 0x45, 0x5A, 0x5C, 0x6D, 0x80, 0x81, 0x8F, 0x00, 0x84, 0x43, 0x85, 0xAB, 0x38, 0x00, 0x9D, 0x7A, 0x81, 0xF1, 0x0D}; +static const uint8_t s_splash[] = {0x00, 0x34, 0x36, 0x4B, 0x34, 0x36, 0x4B, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x30, 0x30, 0x00, 0x60, 0x60, 0x00, 0x81, 0x40, 0x81, 0x40, 0x00, 0x83, 0x00, 0x83, 0x00, 0x00, 0x86, 0x00, 0x86, 0x00, 0x00, 0x8C, 0x00, 0x8C, 0x00, 0x00, 0x8D, 0x7F, 0x8D, 0x7F, 0x5A, 0x5C, 0x6D, 0x00, 0x87, 0x5E, 0x87, 0x61, 0x73, 0x75, 0x83, 0xA6, 0xA7, 0xB0, 0xD9, 0xD9, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x04, 0x04, 0xFF, 0xCC, 0xCD, 0xD2, 0x00, 0x87, 0x55, 0x87, 0x6A, 0x9A, 0x9B, 0xA5, 0xE6, 0xE6, 0xE9, 0x00, 0x09, 0x87, 0x67, 0x00, 0x27, 0x87, 0x70, 0x41, 0x43, 0x56, 0x00, 0x87, 0x34, 0x97, 0x35, 0x00, 0x12, 0x87, 0x6A, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x15, 0x00, 0x1B, 0x87, 0x70, 0x80, 0x81, 0x8F, 0xF2, 0xF2, 0xF4, 0x00, 0x87, 0x2E, 0x97, 0x74, 0x80, 0x81, 0x8F, 0x00, 0x0C, 0x87, 0x67, 0xB3, 0xB4, 0xBC, 0x73, 0x75, 0x83, 0x00, 0x06, 0x8F, 0x36, 0x9A, 0x9B, 0xA5, 0x00, 0x1B, 0x87, 0x70, 0x67, 0x68, 0x78, 0x00, 0x06, 0x33, 0xD9, 0xD9, 0xDD, 0x00, 0x87, 0x28, 0x8F, 0x66, 0x00, 0x0C, 0x87, 0x6D, 0xCC, 0xCD, 0xD2, 0x4D, 0x4F, 0x62, 0x00, 0x0F, 0x97, 0x62, 0x00, 0x1E, 0x8F, 0x60, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x3C, 0xC0, 0xC0, 0xC7, 0x00, 0x87, 0x22, 0x87, 0x6D, 0x00, 0x09, 0x8F, 0x21, 0xFF, 0xFF, 0xFF, 0x8D, 0x8E, 0x9A, 0x00, 0x15, 0x9F, 0x52, 0x00, 0x21, 0x9F, 0x40, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x42, 0x67, 0x68, 0x78, 0x00, 0x87, 0x1C, 0x87, 0x6D, 0x41, 0x43, 0x56, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0x87, 0x2B, 0x80, 0x81, 0x8F, 0x00, 0x18, 0xA7, 0x42, 0x00, 0x21, 0x87, 0x70, 0x4D, 0x4F, 0x62, 0x00, 0x87, 0x25, 0xAF, 0x47, 0x00, 0x06, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xA6, 0xA7, 0xB0, 0x00, 0x1E, 0x24, 0x00, 0x21, 0x87, 0x49, 0x00, 0x09, 0x97, 0x56, 0x00, 0x0F, 0x98, 0x0F, 0x00, 0x87, 0x13, 0x8F, 0x5D, 0xE6, 0xE6, 0xE9, 0x00, 0x21, 0x88, 0x14, 0x00, 0x21, 0x87, 0x70, 0x5A, 0x5C, 0x6D, 0x00, 0x06, 0x87, 0x70, 0x9A, 0x9B, 0xA5, 0x00, 0x87, 0x16, 0x87, 0x70, 0x8D, 0x8E, 0x9A, 0x00, 0x1E, 0x97, 0x4A, 0x00, 0x2D, 0x87, 0x70, 0x34, 0x36, 0x4B, 0x00, 0x21, 0xB7, 0x3A, 0x00, 0x86, 0x7E, 0x87, 0x70, 0x00, 0x06, 0xA6, 0x65, 0xF2, 0xF2, 0xF4, 0x00, 0x24, 0x97, 0x74, 0x00, 0x24, 0x87, 0x46, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x88, 0x41, 0x00, 0x87, 0x16, 0x87, 0x70, 0x00, 0x09, 0xBE, 0x6B, 0x00, 0x48, 0x87, 0x70, 0x00, 0x09, 0xA0, 0x0E, 0x00, 0x87, 0x13, 0x9F, 0x43, 0x00, 0x09, 0x9E, 0x6F, 0x00, 0x15, 0xB7, 0x04, 0x00, 0x3F, 0x87, 0x70, 0x00, 0x87, 0x13, 0xB7, 0x16, 0x00, 0x09, 0xBE, 0x77, 0x00, 0x21, 0x87, 0x1C, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x2A, 0x54, 0x00, 0x87, 0x46, 0x87, 0x70, 0x00, 0x09, 0xA8, 0x01, 0x00, 0x87, 0x67, 0x87, 0x70, 0x00, 0x09, 0x97, 0x50, 0x00, 0x87, 0x13, 0xE6, 0x3C, 0x00, 0x09, 0x87, 0x70, 0x73, 0x75, 0x83, 0x00, 0x48, 0x87, 0x70, 0x00, 0x09, 0xC6, 0x73, 0x00, 0x87, 0x16, 0xC6, 0x6D, 0x00, 0x27, 0xC6, 0x1F, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x06, 0x81, 0x86, 0x20, 0x00, 0x1E, 0xC7, 0x3E, 0x00, 0x86, 0x7B, 0x87, 0x73, 0x00, 0x27, 0xC6, 0x1F, 0x00, 0x27, 0x87, 0x70, 0x00, 0x09, 0xDE, 0x43, 0x00, 0x21, 0xB7, 0x61, 0x00, 0x86, 0x78, 0x87, 0x70, 0x00, 0x09, 0x96, 0x7F, 0x00, 0x1E, 0xFD, 0x38, 0x00, 0x27, 0x87, 0x70, 0x00, 0x09, 0x9F, 0x3D, 0x00, 0x1E, 0xCF, 0x2E, 0x00, 0x86, 0x7E, 0x81, 0x9D, 0x25, 0x00, 0x24, 0x97, 0x53, 0x00, 0x24, 0x87, 0x70, 0x00, 0x09, 0xDF, 0x0B, 0xF2, 0xF2, 0xF4, 0x00, 0x87, 0x1C, 0x81, 0x85, 0x76, 0x00, 0x06, 0x97, 0x53, 0xF2, 0xF2, 0xF4, 0x00, 0x1B, 0xCE, 0x12, 0x00, 0x24, 0x87, 0x70, 0xA6, 0xA7, 0xB0, 0x00, 0x87, 0x1F, 0xE6, 0x2D, 0x00, 0x0F, 0x8F, 0x63, 0xD9, 0xD9, 0xDD, 0x00, 0x39, 0x87, 0x70, 0x00, 0x09, 0x45, 0x00, 0x87, 0x1F, 0x8F, 0x5D, 0x00, 0x0F, 0xE5, 0x65, 0x00, 0x18, 0xA6, 0x68, 0x00, 0x1E, 0x87, 0x70, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0x81, 0x86, 0x32, 0x00, 0x21, 0xB7, 0x5B, 0x00, 0x87, 0x07, 0xB7, 0x19, 0x00, 0x09, 0x81, 0xBC, 0x68, 0xD9, 0xD9, 0xDD, 0x00, 0x12, 0x97, 0x59, 0x00, 0x1B, 0x87, 0x70, 0x00, 0x09, 0xCE, 0x51, 0x00, 0x87, 0x1C, 0xAF, 0x17, 0x00, 0x1E, 0x8F, 0x24, 0xF2, 0xF2, 0xF4, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0x97, 0x17, 0x00, 0x15, 0x87, 0x70, 0x67, 0x68, 0x78, 0x00, 0x09, 0x81, 0x9D, 0x34, 0x00, 0x87, 0x2E, 0x87, 0x6D, 0x00, 0x12, 0x8F, 0x66, 0x00, 0x09, 0x81, 0xAC, 0x6D, 0x9A, 0x9B, 0xA5, 0x67, 0x68, 0x78, 0x00, 0x06, 0xB7, 0x37, 0xD9, 0xD9, 0xDD, 0x67, 0x68, 0x78, 0x73, 0x75, 0x83, 0x9A, 0x9B, 0xA5, 0x00, 0x0F, 0x2A, 0x00, 0x87, 0x31, 0x87, 0x6D, 0x00, 0x0C, 0x8F, 0x4B, 0x00, 0x09, 0x8F, 0x69, 0x00, 0x12, 0x81, 0xCC, 0x63, 0x00, 0x12, 0x12, 0xE6, 0xE6, 0xE9, 0x00, 0x87, 0x25, 0x9F, 0x34, 0x00, 0x1E, 0xCE, 0x27, 0xA6, 0xA7, 0xB0, 0x00, 0x21, 0x87, 0x76, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x87, 0x34, 0x81, 0xD4, 0x47, 0x00, 0x1B, 0xE6, 0x51, 0x9A, 0x9B, 0xA5, 0xC0, 0xC0, 0xC7, 0xCC, 0xCD, 0xD2, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x06, 0xB3, 0xB4, 0xBC, 0x8D, 0x8E, 0x9A, 0x00, 0x87, 0x61, 0x81, 0xEC, 0x2F, 0x00, 0xA5, 0x7F, 0x82, 0x9A, 0x0F, 0x00, 0x90, 0x67, 0x82, 0xAA, 0x73, 0x00, 0x06, 0xBE, 0x53, 0x00, 0x87, 0x19, 0x81, 0x8D, 0x0F, 0x00, 0x57, 0x81, 0xAD, 0x20, 0x00, 0x87, 0x1F, 0x81, 0x85, 0x22, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x51, 0x81, 0xE4, 0x30, 0x00, 0x87, 0x25, 0x82, 0x9A, 0x75, 0x00, 0x45, 0x45, 0x00, 0x87, 0x1F, 0x81, 0xBC, 0x2F, 0x00, 0x51, 0x51, 0x00, 0x09, 0x81, 0xA4, 0x65, 0x00, 0x87, 0x67, 0xE6, 0x00, 0x00, 0x87, 0x22, 0x81, 0xC4, 0x22, 0x00, 0x5A, 0x81, 0xA5, 0x2D, 0x00, 0x87, 0x6A, 0x8F, 0x63, 0x00, 0x09, 0x82, 0xA3, 0x33, 0x00, 0x87, 0x4C, 0x81, 0x85, 0x3D, 0x00, 0x27, 0x81, 0xBD, 0x03, 0x00, 0x87, 0x19, 0x82, 0xB2, 0x4B, 0x00, 0x51, 0x82, 0xD2, 0x50, 0x00, 0x09, 0x81, 0xD4, 0x0E, 0x00, 0x21, 0x82, 0x93, 0x5F, 0x00, 0x87, 0x4C, 0xD6, 0x5F, 0x00, 0x09, 0x81, 0x9D, 0x1C, 0xA6, 0xA7, 0xB0, 0x67, 0x68, 0x78, 0x00, 0x87, 0x4F, 0x97, 0x62, 0x00, 0x0C, 0x81, 0x9D, 0x19, 0x00, 0x06, 0x06, 0x00, 0x15, 0x81, 0xA5, 0x27, 0xE6, 0xE6, 0xE9, 0x00, 0x12, 0x2A, 0x00, 0x12, 0x12, 0x00, 0x0C, 0x0C, 0x00, 0x87, 0x1C, 0xCE, 0x60, 0x00, 0x2A, 0x81, 0xB4, 0x7E, 0x00, 0x2A, 0x2A, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x87, 0x19, 0xE6, 0x33, 0x67, 0x68, 0x78, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x2A, 0x2A, 0x00, 0xBE, 0x41, 0x81, 0xB5, 0x2E, 0x00, 0x9F, 0x46, 0x9F, 0x46, 0x41, 0x43, 0x56, 0x00, 0x06, 0xDE, 0x10, 0x00, 0x87, 0x5E, 0x82, 0x93, 0x44, 0x00, 0x06, 0x82, 0xA3, 0x33, 0x00, 0x0F, 0x82, 0xB2, 0x75, 0x00, 0x87, 0x55, 0x83, 0xFF, 0x70, 0x4D, 0x4F, 0x62, 0x00, 0x0C, 0x82, 0xC2, 0x46, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x87, 0x34, 0xEE, 0x14, 0x00, 0x0C, 0x82, 0xD2, 0x1D, 0x00, 0x09, 0x81, 0xA5, 0x42, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x88, 0x02, 0x00, 0x21, 0x83, 0xF0, 0x10, 0x00, 0x87, 0x2E, 0x82, 0xBB, 0x09, 0x00, 0x09, 0x83, 0x81, 0x7C, 0x00, 0x06, 0x81, 0x95, 0x41, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x81, 0x9D, 0x3D, 0x00, 0x27, 0x83, 0xFF, 0x70, 0x00, 0x87, 0x2B, 0x84, 0x87, 0x63, 0x00, 0x0C, 0x87, 0x6D, 0x00, 0x12, 0x81, 0xEC, 0x2F, 0x00, 0x21, 0x82, 0xF2, 0x10, 0x00, 0x09, 0x84, 0x80, 0x2F, 0x00, 0x1B, 0x82, 0xF2, 0x55, 0x00, 0x87, 0x13, 0x97, 0x47, 0x00, 0x18, 0x8F, 0x21, 0x00, 0x2D, 0x83, 0x81, 0x70, 0x00, 0x87, 0x1F, 0x82, 0x84, 0x3E, 0x00, 0x09, 0x81, 0xDC, 0x43, 0x00, 0x1B, 0x97, 0x0E, 0x00, 0x2D, 0x83, 0x91, 0x50, 0x00, 0x87, 0x1F, 0x81, 0xEC, 0x6E, 0x00, 0x09, 0x97, 0x4A, 0x00, 0x1B, 0x8F, 0x18, 0x00, 0x30, 0x83, 0xA1, 0x30, 0x00, 0x87, 0x19, 0xAF, 0x2C, 0x00, 0x27, 0x84, 0x8F, 0x05, 0x00, 0x30, 0x83, 0xB1, 0x10, 0x00, 0x1B, 0x84, 0x88, 0x2B, 0x00, 0x87, 0x07, 0x81, 0xFC, 0x00, 0x00, 0x1E, 0x8F, 0x12, 0x00, 0x30, 0x83, 0xC0, 0x70, 0x00, 0x87, 0x19, 0xA7, 0x36, 0x00, 0x27, 0x82, 0x8B, 0x60, 0x00, 0x87, 0x37, 0x83, 0xD0, 0x50, 0x00, 0x12, 0x8F, 0x45, 0x00, 0x27, 0x96, 0x7F, 0x00, 0x87, 0x34, 0x83, 0xE0, 0x30, 0x00, 0x06, 0x83, 0x99, 0x22, 0x00, 0x15, 0xC6, 0x28, 0x00, 0x21, 0xB6, 0x42, 0x00, 0x87, 0x31, 0x83, 0xF0, 0x10, 0x00, 0x09, 0x83, 0x99, 0x1C, 0x00, 0x87, 0x67, 0x83, 0xFF, 0x70, 0x00, 0x06, 0x82, 0x93, 0x35, 0x00, 0x0F, 0x9F, 0x28, 0x00, 0x5D, 0x83, 0xF8, 0x00, 0x00, 0x86, 0x7B, 0x87, 0x70, 0x00, 0x18, 0x87, 0x04, 0x00, 0x5D, 0x87, 0x70, 0x00, 0x86, 0x78, 0x82, 0x8C, 0x28, 0x00, 0x09, 0xDD, 0x5A, 0x00, 0x12, 0xDE, 0x16, 0x00, 0x54, 0x9F, 0x40, 0x00, 0x63, 0x84, 0xAF, 0x10, 0x4D, 0x4F, 0x62, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x83, 0xD9, 0x77, 0x00, 0x09, 0x89, 0x2A, 0x00, 0x86, 0x06, 0xD7, 0x45, 0x00, 0x09, 0x83, 0xC0, 0x46, 0x00, 0x18, 0x87, 0x2B, 0x00, 0x51, 0xAF, 0x20, 0x00, 0x06, 0x87, 0x07, 0x00, 0x5A, 0xBF, 0x00, 0x00, 0x09, 0x81, 0x52, 0x00, 0x06, 0xA1, 0x0F, 0x00, 0x06, 0x87, 0x70, 0x00, 0x06, 0x89, 0x39, 0x00, 0x86, 0x00, 0xC7, 0x65, 0x41, 0x43, 0x56, 0x00, 0x21, 0x83, 0xE7, 0x7C, 0x00, 0x27, 0xC6, 0x1F, 0x00, 0x30, 0x84, 0xCE, 0x50, 0x00, 0x57, 0x86, 0x7B, 0x00, 0x06, 0xDF, 0x23, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0xB7, 0x6D, 0x00, 0x0C, 0x8F, 0x60, 0x00, 0x06, 0x81, 0x22, 0x00, 0x85, 0x7D, 0x98, 0x45, 0x00, 0x09, 0x96, 0x5B, 0x00, 0x1B, 0x81, 0x85, 0x07, 0x00, 0x09, 0xCE, 0x60, 0x00, 0x1E, 0x86, 0x2A, 0x00, 0x30, 0x84, 0xDE, 0x30, 0x00, 0x57, 0x81, 0x85, 0x79, 0x00, 0x06, 0x99, 0x1C, 0x00, 0x09, 0xBF, 0x5A, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x06, 0x84, 0x91, 0x1C, 0x00, 0x85, 0x7D, 0x82, 0xE3, 0x79, 0x00, 0x06, 0x81, 0x8D, 0x15, 0x00, 0x1E, 0x82, 0xCA, 0x39, 0x00, 0x09, 0x8F, 0x12, 0x00, 0x1E, 0x27, 0x00, 0x2D, 0x84, 0xEE, 0x10, 0x00, 0x5A, 0xEE, 0x20, 0xB3, 0xB4, 0xBC, 0x00, 0x0C, 0x91, 0x0B, 0x00, 0x0F, 0xA8, 0x6A, 0x00, 0x84, 0x46, 0x82, 0x9C, 0x38, 0x41, 0x43, 0x56, 0xA6, 0xA7, 0xB0, 0x00, 0x81, 0x34, 0x82, 0xA9, 0x27, 0xCC, 0xCD, 0xD2, 0x00, 0x24, 0x82, 0xC2, 0x43, 0x00, 0x24, 0x84, 0xFD, 0x28, 0x00, 0x2D, 0x84, 0xFD, 0x70, 0x00, 0x5A, 0xA6, 0x3B, 0x00, 0x0F, 0x87, 0x52, 0x00, 0x84, 0x52, 0x87, 0x70, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0xA4, 0x1E, 0x00, 0x81, 0x34, 0x82, 0xF0, 0x32, 0xCC, 0xCD, 0xD2, 0x00, 0x24, 0xD5, 0x55, 0x00, 0x09, 0x8F, 0x63, 0x00, 0x1B, 0x83, 0xFF, 0x2B, 0x00, 0x21, 0x87, 0x70, 0x00, 0x09, 0xB7, 0x07, 0x00, 0x5D, 0xE6, 0x2A, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x0F, 0x87, 0x70, 0xF2, 0xF2, 0xF4, 0x00, 0x84, 0x3D, 0xA7, 0x33, 0x00, 0x0C, 0x85, 0x8B, 0x66, 0x00, 0x81, 0x34, 0xC4, 0x41, 0x00, 0x2A, 0x81, 0x31, 0x00, 0x0C, 0x87, 0x2E, 0x00, 0x15, 0x9F, 0x49, 0x00, 0x1E, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xA5, 0x66, 0x00, 0x5D, 0xDE, 0x37, 0x00, 0x06, 0x82, 0xCC, 0x08, 0x00, 0x09, 0xA0, 0x1D, 0x00, 0x0C, 0x83, 0x15, 0x00, 0x06, 0x81, 0x04, 0x00, 0x83, 0x3F, 0xC7, 0x65, 0x4D, 0x4F, 0x62, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x00, 0x06, 0x83, 0xED, 0x16, 0x00, 0x7B, 0xF4, 0x2F, 0x00, 0x81, 0x61, 0x81, 0xBA, 0x7E, 0x00, 0x09, 0xA7, 0x5D, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0xA6, 0x6E, 0x00, 0x18, 0x87, 0x70, 0x41, 0x43, 0x56, 0x00, 0x09, 0x39, 0x00, 0x66, 0x81, 0x95, 0x4A, 0xD9, 0xD9, 0xDD, 0x00, 0x09, 0x81, 0x22, 0x00, 0x09, 0x87, 0x61, 0x00, 0x06, 0x93, 0x07, 0x00, 0x83, 0x42, 0x97, 0x4D, 0x00, 0x0C, 0x8E, 0x62, 0x00, 0x75, 0xAA, 0x7B, 0x00, 0x0C, 0x85, 0x93, 0x5C, 0x00, 0x81, 0x5E, 0xB3, 0x6F, 0x41, 0x43, 0x56, 0x00, 0x0C, 0x81, 0xBC, 0x77, 0xCC, 0xCD, 0xD2, 0x00, 0x0C, 0x87, 0x76, 0x00, 0x12, 0x87, 0x70, 0x41, 0x43, 0x56, 0x00, 0x0F, 0x83, 0xF0, 0x3A, 0x00, 0x66, 0xC5, 0x72, 0x4D, 0x4F, 0x62, 0x00, 0x06, 0xB8, 0x44, 0x00, 0x09, 0xBF, 0x06, 0x00, 0x09, 0x09, 0x00, 0x83, 0x42, 0x82, 0xCC, 0x0B, 0x00, 0x81, 0x01, 0x87, 0x70, 0x00, 0x0F, 0x81, 0xAB, 0x39, 0x00, 0x81, 0x61, 0x82, 0xD8, 0x59, 0x00, 0x0C, 0x91, 0x50, 0x00, 0x06, 0x86, 0x54, 0xCC, 0xCD, 0xD2, 0x9A, 0x9B, 0xA5, 0x00, 0x06, 0x88, 0x0B, 0xE6, 0xE6, 0xE9, 0x9A, 0x9B, 0xA5, 0xA6, 0xA7, 0xB0, 0x00, 0x0F, 0x81, 0xC5, 0x11, 0xF2, 0xF2, 0xF4, 0x00, 0x6C, 0xCD, 0x5F, 0x00, 0x06, 0x88, 0x6B, 0x00, 0x0C, 0x84, 0x91, 0x01, 0x00, 0x83, 0x48, 0x83, 0xF1, 0x17, 0x00, 0x81, 0x04, 0x87, 0x70, 0x00, 0x09, 0x82, 0xE8, 0x3C, 0x00, 0x81, 0x67, 0x83, 0x97, 0x68, 0x67, 0x68, 0x78, 0x00, 0x0F, 0x81, 0xD4, 0x47, 0x00, 0x1E, 0x82, 0xC2, 0x58, 0xC0, 0xC0, 0xC7, 0x00, 0x84, 0x49, 0xC5, 0x66, 0x00, 0x81, 0x04, 0x87, 0x70, 0x00, 0x0C, 0x82, 0xC9, 0x05, 0x00, 0x81, 0x6A, 0x81, 0xAA, 0x7A, 0x73, 0x75, 0x83, 0x00, 0x0C, 0x9F, 0x19, 0x00, 0x12, 0x87, 0x67, 0xF2, 0xF2, 0xF4, 0xB3, 0xB4, 0xBC, 0x00, 0x72, 0x81, 0x85, 0x55, 0x00, 0x18, 0x82, 0xC3, 0x4D, 0x73, 0x75, 0x83, 0x00, 0x83, 0x42, 0xEF, 0x12, 0x00, 0x81, 0x10, 0x87, 0x70, 0x00, 0x81, 0x73, 0x81, 0x93, 0x27, 0x00, 0x06, 0x81, 0xEC, 0x1A, 0x00, 0x09, 0xAA, 0x36, 0x9A, 0x9B, 0xA5, 0x80, 0x81, 0x8F, 0x00, 0x78, 0x81, 0x8D, 0x3C, 0x00, 0x06, 0xA2, 0x4F, 0xCC, 0xCD, 0xD2, 0x00, 0x0F, 0x97, 0x3E, 0x00, 0x06, 0xA0, 0x7D, 0x00, 0x83, 0x42, 0x84, 0xB7, 0x7B, 0x00, 0x81, 0x07, 0x87, 0x70, 0x00, 0x0C, 0x9D, 0x2F, 0x00, 0x83, 0x03, 0xEF, 0x6C, 0x00, 0x15, 0x88, 0x6E, 0x00, 0x06, 0xCF, 0x5E, 0x00, 0x83, 0x3F, 0xEE, 0x26, 0x00, 0x84, 0x10, 0x87, 0x70, 0xC0, 0xC0, 0xC7, 0x00, 0x1B, 0xC7, 0x50, 0x00, 0x06, 0x81, 0xE5, 0x5B, 0x00, 0x86, 0x3F, 0x97, 0x50, 0x00, 0x81, 0x13, 0x82, 0xFB, 0x2E, 0x00, 0x27, 0xD6, 0x6E, 0x00, 0x84, 0x37, 0x87, 0x70, 0x00, 0x09, 0x84, 0xFC, 0x15, 0x00, 0x83, 0x03, 0x87, 0x70, 0x00, 0x06, 0x81, 0x85, 0x67, 0x00, 0x1B, 0xFE, 0x7B, 0x00, 0x84, 0x43, 0x8F, 0x60, 0x00, 0x0C, 0xB7, 0x10, 0x00, 0x21, 0x85, 0xBB, 0x18, 0x00, 0x82, 0x65, 0x9F, 0x40, 0x00, 0x15, 0xAF, 0x08, 0x00, 0x06, 0x1B, 0x00, 0x84, 0x43, 0x9F, 0x40, 0x00, 0x0C, 0xC6, 0x70, 0x00, 0x83, 0x03, 0x94, 0x2F, 0xE6, 0xE6, 0xE9, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0x81, 0x9F, 0x09, 0xF2, 0xF2, 0xF4, 0x00, 0x83, 0x42, 0x81, 0xE5, 0x28, 0x00, 0x81, 0x01, 0x87, 0x70, 0x00, 0x09, 0xFB, 0x54, 0x00, 0x83, 0x09, 0x83, 0xE6, 0x48, 0x00, 0x0C, 0x81, 0x95, 0x50, 0x00, 0x06, 0xB8, 0x20, 0x00, 0x09, 0xD6, 0x5F, 0x00, 0x83, 0x42, 0x81, 0xC5, 0x62, 0x00, 0x7E, 0x87, 0x70, 0x00, 0x12, 0x84, 0xD4, 0x50, 0x00, 0x83, 0x06, 0x84, 0x52, 0x00, 0x06, 0x81, 0xA5, 0x30, 0x00, 0x0F, 0x84, 0xD7, 0x3E, 0x00, 0x83, 0x45, 0xCF, 0x64, 0x00, 0x7B, 0x87, 0x70, 0x00, 0x09, 0xE3, 0x18, 0x00, 0x83, 0x18, 0x82, 0xA9, 0x1E, 0x00, 0x09, 0x82, 0xB4, 0x29, 0x00, 0x83, 0x4B, 0x83, 0xB2, 0x32, 0x00, 0x75, 0x87, 0x70, 0x5A, 0x5C, 0x6D, 0x00, 0x0F, 0x8C, 0x3F, 0x00, 0x86, 0x4B, 0x81, 0xC2, 0x41, 0x00, 0x06, 0xEA, 0x6D, 0x00, 0x18, 0x83, 0xB5, 0x44, 0x00, 0x0C, 0x8E, 0x62, 0x00, 0x33, 0x83, 0xB6, 0x03, 0x00, 0x30, 0x30, 0x00, 0x18, 0x82, 0xB1, 0x08, 0x00, 0x83, 0x09, 0x81, 0xB1, 0x6C, 0x00, 0x06, 0x84, 0xD7, 0x4A, 0x00, 0x83, 0x42, 0x81, 0xA2, 0x54, 0x00, 0x5A, 0x83, 0xAE, 0x16, 0x00, 0x45, 0x45, 0x00, 0x81, 0x73, 0xBB, 0x56, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0xDE, 0x37, 0x00, 0x06, 0x82, 0xB3, 0x10, 0x00, 0x81, 0x04, 0x83, 0xC0, 0x70, 0x00, 0x06, 0xB6, 0x75, 0x00, 0x83, 0x3C, 0x9F, 0x2B, 0x00, 0x81, 0x22, 0x87, 0x70, 0x00, 0x81, 0x6D, 0x8F, 0x5A, 0x00, 0x06, 0xA6, 0x0B, 0x00, 0x2D, 0x84, 0xF6, 0x00, 0x00, 0x6F, 0x83, 0xB9, 0x00, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x84, 0xFE, 0x77, 0x00, 0x84, 0x52, 0x87, 0x70, 0x00, 0x81, 0x70, 0x84, 0x58, 0x00, 0x09, 0x81, 0x9D, 0x46, 0x00, 0x81, 0x19, 0x83, 0xC0, 0x70, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x9B, 0x63, 0x00, 0x15, 0x9B, 0x60, 0x00, 0x83, 0x21, 0xC6, 0x70, 0x00, 0x81, 0x13, 0x87, 0x70, 0xCC, 0xCD, 0xD2, 0xA6, 0xA7, 0xB0, 0x00, 0x81, 0x70, 0xB6, 0x7B, 0x00, 0x0F, 0xA9, 0x23, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0x85, 0x8D, 0x4D, 0x00, 0x06, 0x81, 0xA0, 0x3A, 0x00, 0x81, 0x07, 0x83, 0xC0, 0x70, 0x00, 0x21, 0x89, 0x12, 0x00, 0x83, 0x3F, 0x81, 0xC4, 0x70, 0x00, 0x81, 0x07, 0xE6, 0x30, 0x00, 0x81, 0x6D, 0x87, 0x6D, 0xD9, 0xD9, 0xDD, 0x00, 0x84, 0x79, 0x82, 0xD2, 0x17, 0x00, 0x82, 0x65, 0x87, 0x70, 0x00, 0x0C, 0xE0, 0x21, 0x00, 0x84, 0x7F, 0x81, 0xE2, 0x73, 0x00, 0x82, 0x65, 0x87, 0x70, 0x00, 0x06, 0x81, 0xE4, 0x54, 0x00, 0x85, 0x05, 0x81, 0xEA, 0x60, 0x00, 0x82, 0x62, 0x87, 0x70, 0x00, 0x09, 0x81, 0xFC, 0x1E, 0x00, 0x81, 0x25, 0xBD, 0x58, 0x00, 0x86, 0x42, 0x9F, 0x40, 0x00, 0x09, 0x81, 0xA5, 0x15, 0x00, 0x81, 0x25, 0xB1, 0x0A, 0x80, 0x81, 0x8F, 0x00, 0x15, 0xBF, 0x6C, 0x00, 0x09, 0xE6, 0x42, 0x00, 0x84, 0x46, 0x81, 0x95, 0x50, 0x00, 0x81, 0x5B, 0x82, 0x62, 0x00, 0x81, 0x46, 0x82, 0xD9, 0x72, 0x41, 0x43, 0x56, 0x00, 0x0F, 0x81, 0xEC, 0x3B, 0x00, 0x86, 0x15, 0x87, 0x70, 0x00, 0x81, 0x4C, 0x84, 0xBE, 0x6D, 0x00, 0x06, 0x81, 0xAD, 0x3B, 0x00, 0x86, 0x1E, 0x8F, 0x60, 0x00, 0x81, 0x4F, 0x84, 0xE6, 0x20, 0xCC, 0xCD, 0xD2, 0x00, 0x83, 0x3F, 0x84, 0xDF, 0x79, 0x00, 0x82, 0x68, 0x87, 0x70, 0x00, 0x81, 0x46, 0xD0, 0x47, 0x00, 0x06, 0xCE, 0x72, 0x00, 0x83, 0x45, 0x83, 0xAE, 0x0D, 0x67, 0x68, 0x78, 0x00, 0x82, 0x53, 0xE2, 0x26, 0x00, 0x81, 0x4C, 0x87, 0x70, 0x00, 0x06, 0xC8, 0x33, 0x00, 0x86, 0x1E, 0x84, 0xB8, 0x3A, 0x00, 0x81, 0x31, 0x87, 0x70, 0x00, 0x18, 0xAF, 0x20, 0x00, 0x09, 0x82, 0xAC, 0x15, 0x00, 0x86, 0x1E, 0x84, 0xB8, 0x2E, 0x00, 0x09, 0x82, 0x8B, 0x5A, 0x00, 0x81, 0x28, 0x8E, 0x17, 0x00, 0x18, 0xBF, 0x00, 0x00, 0x06, 0x84, 0xC0, 0x1E, 0x00, 0x86, 0x24, 0x84, 0xC0, 0x1B, 0x00, 0x87, 0x1F, 0x83, 0x81, 0x1F, 0x00, 0x57, 0xF1, 0x20, 0x00, 0x87, 0x25, 0x83, 0xA8, 0x55, 0x00, 0x4E, 0x83, 0xA9, 0x1A, 0x00, 0x81, 0x31, 0xAA, 0x0F, 0x00, 0x06, 0x86, 0x84, 0x67, 0x00, 0x78, 0x82, 0x97, 0x69, 0x00, 0x30, 0xC1, 0x68, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0x81, 0xDD, 0x7D, 0x00, 0x0F, 0xFA, 0x77, 0x80, 0x81, 0x8F, 0x00, 0x84, 0x6D, 0x82, 0xC4, 0x24, 0x00, 0x09, 0xC6, 0x73, 0x00, 0x81, 0x2B, 0xB9, 0x6F, 0x73, 0x75, 0x83, 0x00, 0x09, 0xE7, 0x64, 0x00, 0x81, 0x1F, 0x86, 0x84, 0x64, 0x73, 0x75, 0x83, 0x00, 0x24, 0x82, 0x86, 0x3D, 0xE6, 0xE6, 0xE9, 0xC0, 0xC0, 0xC7, 0x8D, 0x8E, 0x9A, 0x00, 0x84, 0x64, 0x81, 0xAA, 0x14, 0x00, 0x06, 0xB5, 0x4A, 0x00, 0x1B, 0x82, 0xD2, 0x74, 0x00, 0x81, 0x13, 0xE7, 0x61, 0x00, 0x06, 0x82, 0xB2, 0x7B, 0x00, 0x06, 0xBB, 0x29, 0x00, 0x09, 0x86, 0x85, 0x0B, 0x00, 0x81, 0x0D, 0x87, 0x73, 0x00, 0x0F, 0x82, 0x9E, 0x10, 0x00, 0x30, 0x81, 0x8A, 0x72, 0x9A, 0x9B, 0xA5, 0x73, 0x75, 0x83, 0x00, 0x84, 0x55, 0xA9, 0x02, 0x00, 0x09, 0x85, 0x85, 0x60, 0x00, 0x81, 0x22, 0xB5, 0x50, 0x00, 0x09, 0x82, 0xDA, 0x40, 0x00, 0x12, 0x82, 0x83, 0x70, 0x00, 0x06, 0x82, 0xA3, 0x39, 0x00, 0x81, 0x07, 0x81, 0x40, 0x00, 0x09, 0x81, 0xCE, 0x05, 0x00, 0x42, 0x81, 0x92, 0x6E, 0x00, 0x06, 0x81, 0xE6, 0x05, 0x00, 0x7B, 0x82, 0x86, 0x64, 0x00, 0x83, 0x5D, 0x82, 0xF2, 0x34, 0x00, 0x81, 0x1F, 0x87, 0x73, 0x00, 0x1B, 0x81, 0xE4, 0x30, 0x00, 0x06, 0xC0, 0x4C, 0x00, 0x81, 0x04, 0xDE, 0x40, 0x00, 0x09, 0x82, 0x4D, 0x00, 0x4E, 0x81, 0x9A, 0x67, 0xFE, 0xFE, 0xFF, 0xF0, 0xF1, 0xF3, 0xC9, 0xCB, 0xD1, 0x97, 0x99, 0xA4, 0x65, 0x67, 0x77, 0x00, 0x84, 0x4C, 0x87, 0x73, 0x00, 0x81, 0x19, 0x9C, 0x46, 0x00, 0x81, 0x1F, 0x81, 0xF4, 0x10, 0x00, 0x06, 0xEF, 0x27, 0x00, 0x57, 0x81, 0xA2, 0x57, 0xFE, 0xFE, 0xFF, 0xFD, 0xFE, 0xFE, 0xFB, 0xFD, 0xFE, 0xFA, 0xFC, 0xFD, 0xF9, 0xFB, 0xFD, 0xF7, 0xFA, 0xFC, 0xD1, 0xD4, 0xDA, 0xA0, 0xA3, 0xAE, 0x7C, 0x7E, 0x8D, 0x4C, 0x4E, 0x61, 0x00, 0x84, 0x37, 0x85, 0x95, 0x46, 0x00, 0x09, 0x95, 0x06, 0xC0, 0xC0, 0xC7, 0x00, 0x81, 0x13, 0xA6, 0x02, 0x00, 0x81, 0x1C, 0x82, 0x83, 0x70, 0x00, 0x12, 0x81, 0xD9, 0x01, 0x00, 0x60, 0x87, 0x70, 0xF6, 0xF9, 0xFC, 0xF4, 0xF8, 0xFB, 0xF3, 0xF7, 0xFA, 0xF1, 0xF6, 0xFA, 0xD8, 0xDD, 0xE3, 0xB4, 0xB9, 0xC3, 0x85, 0x89, 0x97, 0x62, 0x65, 0x76, 0x00, 0x81, 0x73, 0x81, 0xC2, 0x29, 0x00, 0x09, 0x83, 0xF5, 0x33, 0x00, 0x15, 0x81, 0xB4, 0x66, 0x00, 0x06, 0xA2, 0x10, 0x00, 0x81, 0x5E, 0xAA, 0x0C, 0x80, 0x81, 0x8F, 0x00, 0x0C, 0x82, 0xA2, 0x65, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x06, 0x82, 0xBA, 0x5C, 0x00, 0x0F, 0x9C, 0x79, 0x00, 0x06, 0x86, 0x45, 0xA6, 0xA7, 0xB0, 0x00, 0x30, 0x4B, 0x00, 0x75, 0x8F, 0x60, 0x00, 0x78, 0xEE, 0x20, 0x00, 0x06, 0x81, 0xF5, 0x11, 0x00, 0x5D, 0x81, 0xB2, 0x37, 0x00, 0x1E, 0x87, 0x70, 0xF0, 0xF5, 0xF9, 0xEF, 0xF4, 0xF9, 0xED, 0xF3, 0xF8, 0xEC, 0xF3, 0xF8, 0xEA, 0xF2, 0xF7, 0xBC, 0xC2, 0xCC, 0x8E, 0x93, 0xA1, 0x6C, 0x70, 0x80, 0x3F, 0x42, 0x00, 0x81, 0x56, 0xA7, 0x72, 0x00, 0x06, 0x82, 0xD2, 0x7A, 0x00, 0x0F, 0xB3, 0x27, 0x00, 0x27, 0x81, 0xCC, 0x3C, 0x00, 0x81, 0x55, 0x81, 0xAB, 0x0F, 0x00, 0x81, 0x01, 0x81, 0xB7, 0x69, 0x00, 0x75, 0x9F, 0x40, 0x00, 0x75, 0xD8, 0x19, 0x00, 0x4E, 0x81, 0xBF, 0x38, 0x00, 0x45, 0x87, 0x70, 0xE9, 0xF1, 0xF7, 0xE7, 0xF0, 0xF6, 0xE6, 0xEF, 0xF6, 0xE5, 0xEE, 0xF5, 0xCD, 0xD6, 0xDF, 0xA1, 0xA8, 0xB5, 0x7F, 0x85, 0x95, 0x54, 0x58, 0x6B, 0x00, 0x81, 0x55, 0x81, 0xF0, 0x1E, 0x00, 0x36, 0xAA, 0x06, 0x00, 0x81, 0x4F, 0x81, 0x82, 0x2B, 0x00, 0x81, 0x55, 0x87, 0x70, 0x00, 0x81, 0x10, 0xAF, 0x20, 0x00, 0x0F, 0x82, 0xDC, 0x3F, 0x00, 0x81, 0x16, 0x87, 0x70, 0xE3, 0xED, 0xF5, 0xE2, 0xEC, 0xF4, 0xE0, 0xEB, 0xF3, 0xDF, 0xEA, 0xF3, 0xD3, 0xDE, 0xE8, 0xB2, 0xBC, 0xC8, 0x87, 0x8F, 0x9E, 0x5D, 0x62, 0x75, 0x3E, 0x41, 0x55, 0x00, 0x81, 0x31, 0xF6, 0x2E, 0x00, 0x4E, 0x8A, 0x5B, 0x00, 0x09, 0x83, 0x8E, 0x29, 0x00, 0x81, 0x79, 0x97, 0x50, 0x00, 0x33, 0x33, 0x00, 0x6C, 0x97, 0x50, 0x00, 0x1E, 0xBF, 0x00, 0x00, 0x6F, 0x8B, 0x32, 0x5A, 0x5C, 0x6D, 0x00, 0x5D, 0x9F, 0x31, 0x00, 0x54, 0x87, 0x70, 0xDE, 0xE9, 0xF2, 0xDC, 0xE8, 0xF2, 0xDB, 0xE8, 0xF1, 0xD9, 0xE7, 0xF1, 0xD8, 0xE6, 0xF0, 0xB8, 0xC4, 0xD1, 0x8F, 0x98, 0xA7, 0x70, 0x77, 0x89, 0x48, 0x4C, 0x5F, 0x00, 0x81, 0x22, 0x9F, 0x28, 0x00, 0x21, 0x82, 0x6E, 0x00, 0x06, 0x82, 0xBF, 0x1C, 0x00, 0x18, 0x81, 0xEC, 0x71, 0x00, 0x83, 0x39, 0x81, 0xA9, 0x64, 0x00, 0x81, 0x04, 0xCE, 0x60, 0x00, 0x09, 0x85, 0xB7, 0x2F, 0x00, 0x81, 0x3D, 0x87, 0x70, 0xD7, 0xE5, 0xF0, 0xD5, 0xE4, 0xEF, 0xD4, 0xE3, 0xEF, 0xD2, 0xE2, 0xEE, 0xAA, 0xB7, 0xC5, 0x5B, 0x61, 0x74, 0x00, 0x81, 0x1F, 0x85, 0xBA, 0x1D, 0x00, 0x18, 0xF2, 0x1B, 0x00, 0x1E, 0x82, 0x80, 0x07, 0x00, 0x06, 0xA7, 0x54, 0x00, 0x1B, 0x93, 0x0A, 0xC0, 0xC0, 0xC7, 0x00, 0x83, 0x21, 0xC9, 0x5B, 0x00, 0x09, 0xDE, 0x40, 0x00, 0x72, 0xA2, 0x7F, 0x00, 0x0F, 0x82, 0xE4, 0x56, 0x00, 0x81, 0x46, 0x87, 0x70, 0xD1, 0xE1, 0xEE, 0xD0, 0xE0, 0xED, 0xA8, 0xB5, 0xC4, 0x00, 0x81, 0x10, 0x97, 0x68, 0x00, 0x18, 0xC1, 0x50, 0xB3, 0xB4, 0xBC, 0x00, 0x30, 0xAE, 0x73, 0x00, 0x12, 0x82, 0xEF, 0x55, 0x00, 0x0C, 0x97, 0x5C, 0x00, 0x84, 0x13, 0xD1, 0x4E, 0x00, 0x3C, 0xD6, 0x26, 0x00, 0x81, 0x22, 0x87, 0x70, 0xCB, 0xDD, 0xEC, 0xA4, 0xC0, 0xDF, 0x84, 0xA5, 0xCD, 0x44, 0x4C, 0x65, 0x00, 0x81, 0x1C, 0x87, 0x6D, 0x00, 0x27, 0x83, 0x8F, 0x39, 0x00, 0x30, 0xA0, 0x08, 0x00, 0x83, 0x0C, 0x87, 0x73, 0x4D, 0x4F, 0x62, 0x00, 0x12, 0x83, 0x63, 0x00, 0x06, 0x83, 0x9C, 0x5B, 0x00, 0x06, 0x81, 0xA5, 0x27, 0x00, 0x63, 0x8F, 0x66, 0x00, 0x4B, 0xD6, 0x26, 0x00, 0x81, 0x13, 0x87, 0x70, 0xB7, 0xCE, 0xE5, 0x8E, 0xB1, 0xD7, 0x89, 0xAD, 0xD6, 0x89, 0xAC, 0xD5, 0x83, 0xA3, 0xCC, 0x56, 0x61, 0x79, 0x00, 0x81, 0x10, 0x83, 0x90, 0x61, 0x00, 0x4E, 0x81, 0x8B, 0x1C, 0x00, 0x15, 0xA0, 0x11, 0x00, 0x83, 0x06, 0x81, 0xA9, 0x70, 0x00, 0x06, 0x86, 0x69, 0x00, 0x0F, 0x83, 0x0C, 0x00, 0x09, 0xDF, 0x77, 0x00, 0x66, 0x81, 0xDD, 0x7D, 0x00, 0x57, 0xD6, 0x26, 0x00, 0x81, 0x04, 0x87, 0x70, 0xCB, 0xDD, 0xEC, 0x9D, 0xBC, 0xDC, 0x8A, 0xAF, 0xD6, 0x8A, 0xAE, 0xD6, 0x89, 0xAC, 0xD5, 0x88, 0xAB, 0xD5, 0x88, 0xAA, 0xD5, 0x82, 0xA1, 0xCC, 0x43, 0x4B, 0x00, 0x7C, 0x8F, 0x66, 0x00, 0x0F, 0x83, 0x88, 0x6B, 0x00, 0x54, 0x82, 0xAF, 0x03, 0x00, 0x15, 0xB2, 0x5F, 0x00, 0x83, 0x03, 0x81, 0xA2, 0x03, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0x83, 0x6C, 0x00, 0x06, 0x8B, 0x1D, 0x00, 0x06, 0x83, 0x1E, 0x00, 0x09, 0xBB, 0x14, 0x00, 0x57, 0xCA, 0x44, 0x00, 0x5A, 0xD6, 0x26, 0x00, 0x81, 0x01, 0x87, 0x70, 0xBA, 0xD1, 0xE6, 0x90, 0xB3, 0xD8, 0x8B, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x88, 0xAA, 0xD5, 0x87, 0xA9, 0xD4, 0x87, 0xA7, 0xD4, 0x80, 0x9C, 0xC4, 0x00, 0x81, 0x04, 0x81, 0xD1, 0x7A, 0x00, 0x60, 0x84, 0xBB, 0x5B, 0x00, 0x12, 0x83, 0x5D, 0x00, 0x82, 0x7D, 0xE9, 0x1B, 0x00, 0x06, 0x81, 0xED, 0x3F, 0x00, 0x0F, 0xB6, 0x6C, 0x00, 0x06, 0x8E, 0x6E, 0x00, 0x0C, 0xB2, 0x4A, 0x00, 0x06, 0x8C, 0x0F, 0x00, 0x51, 0x8F, 0x63, 0x00, 0x60, 0xD6, 0x26, 0x00, 0x7B, 0x87, 0x70, 0xD3, 0xE3, 0xEF, 0xA3, 0xC2, 0xDF, 0x8C, 0xB1, 0xD7, 0x8B, 0xB0, 0xD6, 0x8A, 0xAE, 0xD6, 0x8A, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x87, 0xA8, 0xD4, 0x86, 0xA7, 0xD4, 0x86, 0xA6, 0xD4, 0x5D, 0x6D, 0x00, 0x76, 0xC5, 0x15, 0x00, 0x0C, 0x81, 0xF1, 0x34, 0x00, 0x63, 0x82, 0xBE, 0x5D, 0x00, 0x0F, 0xA3, 0x14, 0x00, 0x82, 0x7D, 0x81, 0xB9, 0x56, 0x00, 0x06, 0xA2, 0x5B, 0x00, 0x12, 0xD6, 0x3B, 0x00, 0x12, 0xD6, 0x59, 0x00, 0x51, 0xDE, 0x40, 0x00, 0x63, 0xD6, 0x26, 0x00, 0x78, 0x87, 0x70, 0xC6, 0xDA, 0xEB, 0x96, 0xB9, 0xDA, 0x00, 0x05, 0x87, 0x6D, 0xD7, 0x00, 0x0A, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x86, 0xA6, 0xD4, 0x85, 0xA5, 0xD3, 0x80, 0x9D, 0xCB, 0x00, 0x7E, 0x81, 0xF1, 0x34, 0x00, 0x66, 0x83, 0x9E, 0x1B, 0x00, 0x09, 0x83, 0xD6, 0x7A, 0x00, 0x83, 0x03, 0x82, 0xB3, 0x0D, 0x00, 0x06, 0x87, 0x70, 0x00, 0x0C, 0xAA, 0x39, 0x00, 0x12, 0x8F, 0x5D, 0x00, 0x54, 0x87, 0x70, 0x00, 0x12, 0x84, 0xD8, 0x4B, 0x00, 0x81, 0x49, 0x87, 0x70, 0xB4, 0xCE, 0xE5, 0x8D, 0xB3, 0xD7, 0x8C, 0xB2, 0xD7, 0x8C, 0xB1, 0x00, 0x07, 0x87, 0x6D, 0x00, 0x13, 0x8F, 0x5D, 0xA5, 0xD3, 0x85, 0xA4, 0xD3, 0x84, 0xA3, 0xD3, 0x52, 0x5F, 0x7E, 0x00, 0x7E, 0xAF, 0x14, 0x00, 0x66, 0xA6, 0x44, 0x00, 0x0F, 0xA8, 0x1C, 0x00, 0x82, 0x7A, 0x8F, 0x63, 0x00, 0x06, 0x81, 0xB6, 0x35, 0x00, 0x09, 0xA2, 0x46, 0x00, 0x06, 0x8B, 0x0B, 0x00, 0x12, 0xD6, 0x3B, 0x00, 0x06, 0x81, 0x97, 0x19, 0x00, 0x45, 0xCA, 0x2C, 0x00, 0x6C, 0xD6, 0x26, 0x00, 0x6F, 0x87, 0x70, 0xD9, 0xE6, 0xF1, 0xA6, 0xC5, 0xE0, 0x8D, 0xB4, 0xD8, 0x8D, 0xB3, 0x00, 0x05, 0x87, 0x6D, 0x00, 0x09, 0x8F, 0x5D, 0xAC, 0xD5, 0x00, 0x12, 0x8F, 0x5D, 0x84, 0xA3, 0xD3, 0x84, 0xA2, 0xD3, 0x79, 0x93, 0xC1, 0x00, 0x75, 0x84, 0xA4, 0x44, 0x00, 0x21, 0x83, 0xC6, 0x04, 0x00, 0x60, 0xA0, 0x32, 0x00, 0x82, 0x7A, 0x9F, 0x46, 0x00, 0x06, 0x84, 0x01, 0xB3, 0xB4, 0xBC, 0x00, 0x09, 0xEA, 0x13, 0x00, 0x0F, 0xB6, 0x7E, 0x00, 0x09, 0x82, 0xD5, 0x7A, 0x00, 0x42, 0x81, 0x97, 0x13, 0x00, 0x6F, 0xD6, 0x26, 0x00, 0x6C, 0x87, 0x70, 0xD0, 0xE0, 0xEE, 0x9D, 0xBF, 0xDD, 0x00, 0x07, 0x87, 0x6D, 0x00, 0x12, 0x8F, 0x5D, 0xAA, 0xD5, 0x87, 0xA9, 0x00, 0x10, 0x8F, 0x5D, 0x84, 0xA2, 0xD2, 0x83, 0xA0, 0xD2, 0x51, 0x5E, 0x00, 0x6A, 0x8F, 0x63, 0x00, 0x09, 0x81, 0xC2, 0x14, 0x00, 0x72, 0xD5, 0x6D, 0x00, 0x0F, 0x82, 0xE2, 0x2D, 0x00, 0x81, 0x79, 0x82, 0xF6, 0x5C, 0x4D, 0x4F, 0x62, 0x00, 0x0C, 0x82, 0xA3, 0x09, 0x00, 0x72, 0x81, 0x9D, 0x67, 0x00, 0x0C, 0xC5, 0x66, 0x00, 0x15, 0x86, 0x8C, 0x6F, 0x00, 0x06, 0x88, 0x05, 0x00, 0x42, 0x9B, 0x66, 0x00, 0x0C, 0x81, 0x80, 0x02, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xC7, 0xDB, 0xEB, 0x93, 0xB9, 0xDA, 0x8E, 0xB5, 0xD8, 0x00, 0x0B, 0x8F, 0x5D, 0xD6, 0x00, 0x09, 0xB7, 0x04, 0x00, 0x18, 0x8F, 0x5D, 0x83, 0xA1, 0xD2, 0x82, 0xA0, 0xD2, 0x78, 0x91, 0xC0, 0x00, 0x78, 0xD1, 0x3C, 0x00, 0x6F, 0xC6, 0x01, 0x00, 0x0C, 0xAF, 0x2C, 0x00, 0x81, 0x6D, 0x82, 0xF9, 0x7D, 0x41, 0x43, 0x56, 0x80, 0x81, 0x8F, 0x00, 0x1E, 0xD8, 0x73, 0x00, 0x0C, 0x84, 0xEE, 0x31, 0x00, 0x66, 0x8B, 0x7A, 0x00, 0x18, 0xDA, 0x27, 0x80, 0x81, 0x8F, 0x00, 0x42, 0xA2, 0x61, 0x00, 0x75, 0xD6, 0x26, 0x00, 0x66, 0x87, 0x70, 0xBE, 0xD5, 0xE8, 0x8F, 0xB6, 0xD8, 0x00, 0x0A, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x00, 0x0B, 0xB7, 0x04, 0x00, 0x10, 0x8F, 0x5D, 0x83, 0xA1, 0xD2, 0x83, 0xA0, 0xD2, 0x82, 0x9F, 0xD2, 0x81, 0x9E, 0xD1, 0x51, 0x5C, 0x7D, 0x00, 0x72, 0x97, 0x4D, 0x00, 0x72, 0xC5, 0x7E, 0x00, 0x0F, 0xB0, 0x18, 0x00, 0x81, 0x64, 0x97, 0x53, 0x00, 0x1B, 0xD8, 0x64, 0x00, 0x15, 0xE9, 0x12, 0x9A, 0x9B, 0xA5, 0x00, 0x81, 0x40, 0xD1, 0x06, 0x00, 0x7B, 0xD6, 0x26, 0x00, 0x63, 0x87, 0x70, 0xAF, 0xCC, 0xE3, 0x8F, 0xB7, 0xD8, 0x8E, 0x00, 0x06, 0x87, 0x70, 0x00, 0x09, 0x87, 0x6D, 0x00, 0x12, 0x8F, 0x5D, 0x00, 0x08, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x81, 0x9E, 0xD1, 0x81, 0x9D, 0xD1, 0x77, 0x8F, 0x00, 0x64, 0x8F, 0x63, 0x00, 0x0F, 0x83, 0x90, 0x4C, 0x00, 0x75, 0xFD, 0x23, 0x00, 0x0C, 0x85, 0x7A, 0x00, 0x81, 0x61, 0xC6, 0x7C, 0x67, 0x68, 0x78, 0x00, 0x12, 0x81, 0x88, 0x34, 0x00, 0x0F, 0x82, 0xC1, 0x5A, 0x00, 0x12, 0x88, 0x0B, 0xE6, 0xE6, 0xE9, 0x00, 0x81, 0x3A, 0xB1, 0x40, 0x5A, 0x5C, 0x6D, 0x00, 0x33, 0x81, 0x8A, 0x27, 0x00, 0x81, 0x25, 0x87, 0x70, 0xE0, 0xEB, 0xF4, 0xAA, 0xC9, 0xE2, 0x8F, 0xB7, 0xD9, 0x00, 0x2A, 0x8F, 0x5D, 0x85, 0x00, 0x14, 0x8F, 0x5D, 0x81, 0x9C, 0xD1, 0x80, 0x9B, 0xD0, 0x50, 0x5B, 0x00, 0x61, 0x8F, 0x63, 0x00, 0x0F, 0xAE, 0x25, 0x00, 0x75, 0x8C, 0x48, 0x00, 0x0C, 0x95, 0x54, 0x00, 0x81, 0x5E, 0xD6, 0x5F, 0x00, 0x0F, 0xB2, 0x08, 0x00, 0x06, 0x82, 0xC9, 0x2F, 0x00, 0x15, 0x9F, 0x2E, 0x00, 0x06, 0x81, 0xCA, 0x31, 0x00, 0x6F, 0xBA, 0x25, 0x00, 0x81, 0x55, 0xD6, 0x26, 0x00, 0x5A, 0x87, 0x70, 0xE2, 0xEC, 0xF4, 0xA0, 0xC3, 0xDE, 0x8F, 0xB8, 0xD9, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x0C, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x00, 0x0F, 0xC6, 0x61, 0x00, 0x0A, 0x8F, 0x5D, 0x00, 0x09, 0x87, 0x6D, 0x9D, 0xD1, 0x80, 0x9B, 0xD1, 0x7F, 0x9A, 0xD0, 0x75, 0x8C, 0xBF, 0x00, 0x6C, 0x85, 0x92, 0x4F, 0x00, 0x78, 0x81, 0xD9, 0x64, 0x00, 0x0C, 0xE6, 0x4B, 0x00, 0x81, 0x5B, 0x81, 0xDA, 0x68, 0x00, 0x0C, 0x85, 0x7A, 0x00, 0x2A, 0x8F, 0x30, 0x00, 0x0F, 0xFD, 0x0B, 0x00, 0x81, 0x2E, 0x87, 0x73, 0x00, 0x81, 0x04, 0xD6, 0x26, 0x00, 0x57, 0x87, 0x70, 0xE3, 0xED, 0xF5, 0xA0, 0xC3, 0xDE, 0x90, 0xB8, 0xD9, 0x00, 0x10, 0x8F, 0x5D, 0x00, 0x0F, 0xC6, 0x61, 0x00, 0x09, 0x8F, 0x5D, 0x00, 0x08, 0x87, 0x6D, 0x00, 0x10, 0x8F, 0x5D, 0x9D, 0xD1, 0x80, 0x00, 0x05, 0x8F, 0x5D, 0x7F, 0x99, 0xD0, 0x7E, 0x98, 0xD0, 0x46, 0x4E, 0x6C, 0x00, 0x69, 0x86, 0x6C, 0x00, 0x7B, 0x81, 0xA1, 0x0B, 0x00, 0x81, 0x61, 0x83, 0xA9, 0x20, 0x00, 0x0C, 0xB2, 0x05, 0xB3, 0xB4, 0xBC, 0x00, 0x2D, 0x92, 0x48, 0x00, 0x0F, 0x9D, 0x7D, 0x00, 0x81, 0x25, 0xA1, 0x63, 0x00, 0x81, 0x0A, 0xD6, 0x26, 0x00, 0x54, 0x87, 0x70, 0xE4, 0xEE, 0xF5, 0xA1, 0xC4, 0xDF, 0x90, 0xB9, 0xD9, 0x00, 0x19, 0x8F, 0x5D, 0x00, 0x17, 0xD6, 0x3E, 0x00, 0x0C, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x7F, 0x98, 0xD0, 0x7E, 0x97, 0xCF, 0x6B, 0x7E, 0xAE, 0x00, 0x69, 0x96, 0x4C, 0x00, 0x78, 0x81, 0x8C, 0x77, 0x00, 0x0F, 0xB8, 0x11, 0x00, 0x81, 0x5B, 0x84, 0xA7, 0x47, 0x00, 0x3C, 0xB8, 0x74, 0x00, 0x09, 0x8E, 0x2C, 0x00, 0x81, 0x22, 0x92, 0x03, 0x00, 0x81, 0x0D, 0xD6, 0x26, 0x00, 0x51, 0x87, 0x70, 0xE6, 0xEF, 0xF6, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x29, 0x8F, 0x5D, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x09, 0x8F, 0x5D, 0x82, 0xA0, 0xD2, 0x82, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x7E, 0x97, 0xCF, 0x7D, 0x95, 0xCF, 0x00, 0x5D, 0x8F, 0x63, 0x00, 0x0C, 0x8C, 0x39, 0x00, 0x82, 0x59, 0x83, 0xC0, 0x70, 0x00, 0x45, 0x84, 0x8F, 0x0B, 0x00, 0x0C, 0x83, 0x9B, 0x6C, 0x00, 0x81, 0x1C, 0x97, 0x56, 0x00, 0x81, 0x10, 0xD6, 0x26, 0x00, 0x4E, 0x87, 0x70, 0xE7, 0xF0, 0x00, 0x08, 0x87, 0x6D, 0x00, 0x18, 0x8F, 0x5D, 0x00, 0x20, 0xD6, 0x3E, 0x00, 0x0D, 0x8F, 0x5D, 0x9C, 0x00, 0x0D, 0x8F, 0x5D, 0x7D, 0x96, 0xCF, 0x7C, 0x95, 0xCF, 0x6A, 0x7C, 0xAD, 0x00, 0x83, 0x3F, 0x87, 0x70, 0x00, 0x09, 0x8D, 0x6D, 0x00, 0x3F, 0xC6, 0x49, 0x00, 0x09, 0x92, 0x09, 0x00, 0x63, 0x82, 0xBB, 0x4E, 0x00, 0x0F, 0xC8, 0x03, 0x00, 0x24, 0xC8, 0x0C, 0x00, 0x5D, 0x81, 0xCB, 0x7D, 0x00, 0x81, 0x04, 0x87, 0x70, 0xE9, 0xF1, 0xF7, 0x00, 0x09, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x00, 0x08, 0xB7, 0x04, 0x00, 0x26, 0xD6, 0x3E, 0x85, 0xA4, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x12, 0x8F, 0x5D, 0x7D, 0x96, 0xCF, 0x7D, 0x95, 0xCF, 0x7C, 0x94, 0xCE, 0x7B, 0x92, 0xCE, 0x46, 0x4D, 0x00, 0x58, 0x8F, 0x63, 0x00, 0x82, 0x62, 0x87, 0x70, 0x00, 0x09, 0xA7, 0x27, 0x00, 0x45, 0xD0, 0x3E, 0x00, 0x60, 0x84, 0xB7, 0x00, 0x00, 0x21, 0xD5, 0x70, 0x00, 0x18, 0x84, 0x25, 0x00, 0x12, 0x83, 0xAC, 0x6B, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xEA, 0xF1, 0xF7, 0xA2, 0x00, 0x09, 0x87, 0x6D, 0x00, 0x26, 0x8F, 0x5D, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x19, 0x8F, 0x5D, 0x94, 0xCF, 0x7C, 0x93, 0xCE, 0x7B, 0x92, 0xCE, 0x69, 0x7A, 0x00, 0x58, 0x8F, 0x63, 0x00, 0x82, 0x62, 0x87, 0x70, 0x00, 0x09, 0xA2, 0x22, 0x00, 0x45, 0xD6, 0x26, 0x00, 0x27, 0x84, 0xB7, 0x4E, 0x00, 0x42, 0x81, 0xED, 0x4B, 0x00, 0x06, 0xDE, 0x4C, 0x00, 0x12, 0x81, 0xB6, 0x05, 0x00, 0x15, 0xB0, 0x57, 0x00, 0x81, 0x43, 0x87, 0x6D, 0x00, 0x1E, 0x87, 0x70, 0xEB, 0xF2, 0xF8, 0x00, 0x16, 0x87, 0x6D, 0x00, 0x35, 0xD6, 0x3E, 0x00, 0x09, 0x8F, 0x5D, 0x7F, 0x9A, 0x00, 0x13, 0x8F, 0x5D, 0x7B, 0x91, 0xCE, 0x7A, 0x8F, 0xCD, 0x45, 0x4C, 0x00, 0x55, 0x8F, 0x63, 0x00, 0x0C, 0xD1, 0x63, 0x00, 0x78, 0x87, 0x70, 0x00, 0x81, 0x5E, 0xAF, 0x20, 0x00, 0x09, 0x81, 0xF4, 0x0A, 0x00, 0x4E, 0xF9, 0x3A, 0x00, 0x57, 0x97, 0x53, 0x00, 0x06, 0x84, 0x10, 0x00, 0x30, 0xA0, 0x20, 0x00, 0x81, 0x1F, 0xD6, 0x29, 0x00, 0x42, 0x87, 0x70, 0xAF, 0xCC, 0xE3, 0x00, 0x09, 0x87, 0x6D, 0x00, 0x0A, 0x87, 0x70, 0x00, 0x14, 0xC6, 0x61, 0x00, 0x1B, 0xE6, 0x1B, 0x00, 0x11, 0xC6, 0x61, 0x00, 0x0B, 0x8F, 0x5D, 0x95, 0x00, 0x0A, 0x8F, 0x5D, 0x7A, 0x90, 0xCE, 0x79, 0x8F, 0xCD, 0x68, 0x78, 0x00, 0x55, 0x8F, 0x63, 0x00, 0x0C, 0xB7, 0x10, 0x00, 0x78, 0xF5, 0x12, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x81, 0x4F, 0x83, 0xCD, 0x32, 0x00, 0x09, 0xD1, 0x3F, 0x00, 0x4B, 0x81, 0x8C, 0x17, 0x00, 0x5D, 0x85, 0x95, 0x40, 0x00, 0x06, 0x81, 0xC0, 0x42, 0x00, 0x42, 0x81, 0xA1, 0x74, 0x00, 0x81, 0x4C, 0x87, 0x70, 0xB5, 0xD0, 0xE5, 0x00, 0x13, 0x87, 0x6D, 0x00, 0x08, 0x8F, 0x5D, 0x00, 0x36, 0xD6, 0x3E, 0x00, 0x07, 0x87, 0x6D, 0x00, 0x11, 0x8F, 0x5D, 0x7A, 0x00, 0x05, 0x8F, 0x5D, 0x79, 0x8E, 0xCD, 0x78, 0x8D, 0xCD, 0x3D, 0x41, 0x5B, 0x00, 0x81, 0x55, 0x86, 0x6C, 0x00, 0x81, 0x04, 0xC0, 0x04, 0x00, 0x60, 0x89, 0x4B, 0x00, 0x4B, 0xD8, 0x28, 0x00, 0x5D, 0x85, 0x95, 0x40, 0x00, 0x06, 0x81, 0xE8, 0x07, 0x00, 0x81, 0x52, 0x83, 0xAE, 0x01, 0x00, 0x39, 0x87, 0x70, 0xC2, 0xD9, 0xEA, 0x00, 0x0C, 0x87, 0x6D, 0x00, 0x13, 0xB7, 0x04, 0x00, 0x32, 0xE6, 0x1B, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x0B, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x79, 0x8D, 0xCD, 0x78, 0x8C, 0xCC, 0x5E, 0x6B, 0x9C, 0x00, 0x60, 0xF5, 0x12, 0x00, 0x81, 0x01, 0xD6, 0x50, 0x00, 0x81, 0x4F, 0x81, 0xCC, 0x7B, 0x00, 0x54, 0x82, 0xC2, 0x70, 0x00, 0x5D, 0x85, 0x95, 0x40, 0x00, 0x06, 0x81, 0xC8, 0x68, 0x00, 0x2A, 0x84, 0x07, 0x00, 0x0F, 0xC2, 0x3C, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xD0, 0xE1, 0xEF, 0x00, 0x0D, 0x87, 0x6D, 0x00, 0x1B, 0xC6, 0x61, 0x00, 0x32, 0xD6, 0x3E, 0x00, 0x09, 0x8F, 0x5D, 0x7C, 0x95, 0x00, 0x08, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x78, 0x8B, 0xCC, 0x77, 0x8A, 0xCC, 0x3C, 0x40, 0x00, 0x52, 0x8F, 0x63, 0x00, 0x81, 0x01, 0xD3, 0x2F, 0x00, 0x0C, 0xC3, 0x1C, 0x00, 0x81, 0x4F, 0x81, 0x95, 0x56, 0x00, 0x54, 0x87, 0x70, 0x00, 0x60, 0x82, 0xCB, 0x34, 0xCC, 0xCD, 0xD2, 0x00, 0x2A, 0xD0, 0x02, 0x00, 0x81, 0x46, 0x9F, 0x3A, 0x00, 0x15, 0x87, 0x70, 0xE4, 0xEE, 0xF5, 0x96, 0xBD, 0xDB, 0x00, 0x1F, 0x8F, 0x5D, 0x00, 0x18, 0xD6, 0x3E, 0xA8, 0x00, 0x17, 0xD6, 0x3E, 0x9E, 0x00, 0x13, 0xC6, 0x61, 0x00, 0x07, 0x8F, 0x5D, 0x91, 0xCE, 0x7A, 0x90, 0xCD, 0x00, 0x09, 0x8F, 0x5D, 0x77, 0x8B, 0xCC, 0x76, 0x89, 0xCC, 0x5D, 0x69, 0x9B, 0x00, 0x5D, 0xA7, 0x33, 0x00, 0x7E, 0xF6, 0x10, 0x00, 0x81, 0x52, 0xFE, 0x00, 0x00, 0x54, 0x87, 0x1C, 0x00, 0x5D, 0x85, 0x95, 0x40, 0x00, 0x06, 0x82, 0xD2, 0x50, 0x00, 0x15, 0x81, 0xE0, 0x1A, 0x00, 0x15, 0x83, 0xB1, 0x10, 0x00, 0x81, 0x43, 0xAF, 0x17, 0x00, 0x15, 0x87, 0x70, 0xF2, 0xF7, 0xFA, 0x9D, 0xC1, 0xDD, 0x00, 0x2B, 0x8F, 0x5D, 0x00, 0x15, 0xD6, 0x3E, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x19, 0xD6, 0x3E, 0x00, 0x16, 0x8F, 0x5D, 0x00, 0x05, 0x87, 0x6D, 0x77, 0x8A, 0xCC, 0x76, 0x88, 0xCB, 0x75, 0x87, 0xCB, 0x00, 0x51, 0x8F, 0x63, 0x00, 0x0F, 0x93, 0x13, 0x00, 0x6F, 0x81, 0x8A, 0x5D, 0x00, 0x0C, 0x9B, 0x7E, 0x00, 0x81, 0x52, 0x81, 0x8D, 0x60, 0x00, 0x54, 0x82, 0xB3, 0x0D, 0x00, 0x09, 0x87, 0x70, 0x00, 0x54, 0x9A, 0x7D, 0x00, 0x30, 0x83, 0x91, 0x50, 0x00, 0x81, 0x49, 0x87, 0x6D, 0x00, 0x0F, 0x87, 0x70, 0xAA, 0xCA, 0xE2, 0x00, 0x0F, 0x87, 0x6D, 0x00, 0x3C, 0xD6, 0x3E, 0x83, 0x00, 0x1A, 0xD6, 0x3E, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x10, 0x8F, 0x5D, 0xCB, 0x75, 0x88, 0xCB, 0x75, 0x86, 0xCB, 0x5C, 0x67, 0x00, 0x52, 0xFC, 0x22, 0x00, 0x0C, 0x8B, 0x26, 0x00, 0x6C, 0x86, 0x75, 0x00, 0x0F, 0xAB, 0x5B, 0x00, 0x81, 0x55, 0x81, 0x85, 0x6D, 0x00, 0x51, 0x82, 0x56, 0x00, 0x06, 0xA1, 0x6F, 0x00, 0x81, 0x07, 0x92, 0x0C, 0x00, 0x81, 0x55, 0x87, 0x70, 0xC5, 0xDB, 0xEB, 0x00, 0x10, 0x87, 0x6D, 0x00, 0x45, 0xD6, 0x3E, 0x00, 0x1B, 0x8F, 0x5D, 0x00, 0x06, 0xA7, 0x27, 0x00, 0x11, 0x8F, 0x5D, 0x74, 0x85, 0xCA, 0x74, 0x84, 0xCA, 0x00, 0x51, 0x8F, 0x63, 0x00, 0x0F, 0xF9, 0x25, 0x00, 0x69, 0x8F, 0x63, 0x00, 0x0F, 0x84, 0xD4, 0x50, 0x00, 0x81, 0x6A, 0x85, 0xAD, 0x28, 0x00, 0x42, 0xA1, 0x6F, 0x00, 0x81, 0x07, 0xB1, 0x49, 0x00, 0x81, 0x52, 0x87, 0x70, 0xE1, 0xEC, 0xF5, 0x00, 0x12, 0x87, 0x6D, 0x00, 0x06, 0x8F, 0x5D, 0x00, 0x57, 0xD6, 0x3E, 0x00, 0x0D, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x08, 0x8F, 0x5D, 0x74, 0x85, 0xCA, 0x73, 0x84, 0xCA, 0x5B, 0x66, 0x00, 0x5E, 0x8F, 0x63, 0x00, 0x66, 0x86, 0x7B, 0x00, 0x0F, 0x81, 0x95, 0x4A, 0x00, 0x81, 0x58, 0x81, 0xBD, 0x00, 0x00, 0x09, 0x8A, 0x4C, 0x00, 0x45, 0x81, 0x61, 0x00, 0x09, 0x4E, 0x00, 0x60, 0xAA, 0x5A, 0x4D, 0x4F, 0x62, 0x00, 0x06, 0x82, 0x85, 0x51, 0x00, 0x1E, 0x8B, 0x7D, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xF6, 0xF9, 0xFC, 0x97, 0x00, 0x0F, 0xA7, 0x24, 0x00, 0x5C, 0xE6, 0x1B, 0x00, 0x24, 0x8F, 0x5D, 0x73, 0x83, 0xCA, 0x72, 0x81, 0xC9, 0x38, 0x3B, 0x53, 0x00, 0x5D, 0x96, 0x5B, 0x00, 0x60, 0x81, 0x94, 0x58, 0x00, 0x0F, 0x81, 0xE1, 0x0C, 0x00, 0x81, 0x5B, 0x81, 0xAD, 0x1A, 0x00, 0x09, 0x81, 0xDF, 0x16, 0x00, 0x45, 0x8A, 0x46, 0x00, 0x09, 0x84, 0x8E, 0x5B, 0x00, 0x69, 0x81, 0xA9, 0x43, 0x00, 0x06, 0x89, 0x27, 0x00, 0x06, 0x81, 0x95, 0x14, 0x00, 0x12, 0x9A, 0x71, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xAB, 0x00, 0x12, 0x9F, 0x37, 0x00, 0x19, 0xD6, 0x3E, 0xD7, 0x00, 0x4B, 0xD6, 0x3E, 0x00, 0x0C, 0xB7, 0x04, 0x00, 0x0D, 0x8F, 0x5D, 0x83, 0xCA, 0x72, 0x82, 0xC9, 0x72, 0x81, 0xC9, 0x53, 0x5B, 0x8A, 0x00, 0x60, 0x81, 0xAD, 0x29, 0x00, 0x5A, 0x8C, 0x42, 0x00, 0x0F, 0xDA, 0x6F, 0x00, 0x81, 0x61, 0x84, 0xCB, 0x26, 0x00, 0x09, 0xA6, 0x05, 0x00, 0x3F, 0xE5, 0x65, 0x00, 0x09, 0xBE, 0x7A, 0x00, 0x5D, 0xC1, 0x26, 0x00, 0x06, 0xCF, 0x40, 0x00, 0x06, 0x81, 0xF4, 0x01, 0x00, 0x09, 0x87, 0x70, 0x00, 0x06, 0x83, 0x33, 0x00, 0x12, 0x99, 0x16, 0x00, 0x81, 0x4C, 0x87, 0x70, 0xCE, 0xE0, 0xEE, 0x00, 0x13, 0x97, 0x4A, 0x00, 0x38, 0xD6, 0x3E, 0x00, 0x1C, 0x8F, 0x5D, 0x00, 0x12, 0xC6, 0x61, 0x00, 0x08, 0x8F, 0x5D, 0x76, 0x89, 0x00, 0x13, 0x8F, 0x5D, 0x71, 0x80, 0xC9, 0x6D, 0x7A, 0xC1, 0x38, 0x3A, 0x00, 0x4F, 0x8F, 0x63, 0x00, 0x12, 0x87, 0x07, 0x00, 0x54, 0x96, 0x64, 0x00, 0x12, 0xE2, 0x5C, 0x00, 0x81, 0x61, 0x81, 0xD4, 0x4A, 0x00, 0x0C, 0x85, 0xAD, 0x37, 0x00, 0x39, 0xA9, 0x14, 0x00, 0x0C, 0x84, 0x9E, 0x47, 0x00, 0x60, 0x81, 0x88, 0x7C, 0x00, 0x09, 0x88, 0x50, 0x00, 0x0C, 0x83, 0x1E, 0x00, 0x15, 0x82, 0xCA, 0x60, 0x00, 0x81, 0x49, 0x87, 0x6D, 0xEA, 0xF2, 0xF8, 0x00, 0x1C, 0x87, 0x6D, 0x00, 0x23, 0xE6, 0x1B, 0x00, 0x15, 0xD6, 0x3E, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x23, 0xD6, 0x3E, 0x00, 0x0A, 0x8F, 0x5D, 0x87, 0x00, 0x05, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x71, 0x7F, 0xC9, 0x70, 0x7E, 0xC8, 0x52, 0x59, 0x00, 0x52, 0x8F, 0x63, 0x00, 0x12, 0x81, 0xF4, 0x13, 0x00, 0x4E, 0x8F, 0x66, 0x00, 0x12, 0x81, 0x91, 0x67, 0x00, 0x81, 0x67, 0x83, 0xAD, 0x60, 0x00, 0x09, 0xB9, 0x75, 0x00, 0x18, 0x85, 0x8D, 0x50, 0x00, 0x27, 0x87, 0x6D, 0x00, 0x60, 0x81, 0xE7, 0x48, 0x00, 0x06, 0x81, 0xB6, 0x29, 0x00, 0x18, 0x85, 0x95, 0x40, 0x00, 0x12, 0x82, 0xCA, 0x60, 0x00, 0x81, 0x49, 0x87, 0x70, 0xA5, 0xC6, 0xE0, 0x00, 0x16, 0x87, 0x70, 0x00, 0x48, 0xD6, 0x3E, 0x9A, 0x00, 0x1F, 0xD6, 0x3E, 0x00, 0x13, 0x8F, 0x5D, 0x82, 0x00, 0x07, 0x8F, 0x5D, 0x71, 0x7E, 0xC8, 0x70, 0x7D, 0xC8, 0x6B, 0x77, 0xC0, 0x00, 0x51, 0x8F, 0x63, 0x00, 0x15, 0x82, 0x86, 0x64, 0x00, 0x30, 0x81, 0x9A, 0x70, 0x00, 0x2A, 0x81, 0xC8, 0x5C, 0x00, 0x81, 0x6D, 0x83, 0xB5, 0x4D, 0x00, 0x09, 0xA6, 0x6B, 0x00, 0x30, 0x92, 0x39, 0x00, 0x0C, 0x82, 0x38, 0x00, 0x60, 0x82, 0x8A, 0x65, 0x00, 0x30, 0x85, 0xA5, 0x20, 0x00, 0x81, 0x46, 0x87, 0x6D, 0xC8, 0xDC, 0xEC, 0x00, 0x22, 0x8F, 0x5D, 0x00, 0x30, 0x81, 0xBC, 0x59, 0x00, 0x32, 0xD6, 0x3E, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x13, 0x8F, 0x5D, 0x7D, 0xC8, 0x6F, 0x7C, 0xC8, 0x6F, 0x7B, 0xC7, 0x51, 0x58, 0x89, 0x00, 0x66, 0x81, 0x81, 0x72, 0x00, 0x3F, 0x82, 0xBA, 0x3E, 0x4D, 0x4F, 0x62, 0x00, 0x12, 0x81, 0xCA, 0x49, 0x00, 0x81, 0x73, 0x83, 0xBD, 0x3A, 0x00, 0x0C, 0x87, 0x3A, 0x00, 0x24, 0x84, 0xAD, 0x62, 0x00, 0x0C, 0x82, 0x38, 0x00, 0x66, 0x84, 0xB5, 0x7F, 0x00, 0x0F, 0x84, 0x97, 0x40, 0x00, 0x0F, 0x87, 0x70, 0xD9, 0xD9, 0xDD, 0x00, 0x0F, 0xB8, 0x08, 0x00, 0x81, 0x43, 0x87, 0x6D, 0xF1, 0xF6, 0xFA, 0x00, 0x15, 0x87, 0x6D, 0x00, 0x15, 0xE6, 0x1B, 0x00, 0x49, 0xD6, 0x3E, 0x92, 0x00, 0x13, 0xD6, 0x3E, 0x00, 0x09, 0x8F, 0x5D, 0x73, 0x00, 0x11, 0x8F, 0x5D, 0x6F, 0x7C, 0xC8, 0x6E, 0x7A, 0xC7, 0x6A, 0x75, 0xBF, 0x00, 0x54, 0x8F, 0x63, 0x00, 0x18, 0x81, 0xE7, 0x42, 0x00, 0x06, 0x87, 0x76, 0x00, 0x2D, 0x8F, 0x6C, 0x67, 0x68, 0x78, 0x00, 0x12, 0x81, 0x91, 0x64, 0x00, 0x57, 0xA0, 0x1A, 0x00, 0x81, 0x28, 0xCE, 0x72, 0x00, 0x0C, 0xC0, 0x76, 0x00, 0x06, 0x85, 0x8C, 0x2B, 0x00, 0x0C, 0x81, 0x94, 0x28, 0x00, 0x06, 0x81, 0x94, 0x49, 0x00, 0x0C, 0x85, 0x8C, 0x4F, 0x00, 0x6C, 0x82, 0xAD, 0x4F, 0x00, 0x06, 0xA8, 0x13, 0x00, 0x09, 0x6C, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x06, 0xD0, 0x2C, 0x00, 0x0F, 0xB3, 0x39, 0x00, 0x81, 0x43, 0x87, 0x70, 0xAC, 0xCB, 0x00, 0x0D, 0xFD, 0x5C, 0x00, 0x41, 0xE6, 0x1B, 0x00, 0x14, 0xC6, 0x61, 0x99, 0x00, 0x28, 0xD6, 0x3E, 0x00, 0x0A, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x6E, 0x79, 0xC7, 0x6D, 0x78, 0xC7, 0x50, 0x56, 0x00, 0x55, 0x8F, 0x63, 0x00, 0x1E, 0x81, 0xDF, 0x5E, 0x00, 0x09, 0x83, 0x84, 0x2B, 0x00, 0x15, 0x85, 0x05, 0x5A, 0x5C, 0x6D, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x85, 0xE0, 0x61, 0x00, 0x12, 0x82, 0xAB, 0x65, 0x00, 0x81, 0x6D, 0x82, 0xA3, 0x24, 0x00, 0x7B, 0x85, 0x4A, 0x00, 0x33, 0x8A, 0x55, 0x00, 0x06, 0x87, 0x55, 0x00, 0x09, 0x8F, 0x45, 0x00, 0x0C, 0xAF, 0x20, 0x00, 0x15, 0x84, 0xFD, 0x70, 0x00, 0x81, 0x40, 0x87, 0x6D, 0xD5, 0xE5, 0xF1, 0x00, 0x28, 0x8F, 0x5D, 0x00, 0x5E, 0xD6, 0x3E, 0xCC, 0x00, 0x0C, 0xC6, 0x61, 0x00, 0x10, 0x8F, 0x5D, 0x7B, 0xC8, 0x6E, 0x7A, 0xC7, 0x6D, 0x79, 0xC7, 0x6D, 0x77, 0xC6, 0x68, 0x72, 0xBE, 0x00, 0x3F, 0x97, 0x3B, 0x00, 0x1E, 0x84, 0xA4, 0x05, 0x00, 0x81, 0x25, 0xE2, 0x11, 0x00, 0x81, 0x1C, 0xCF, 0x1C, 0x00, 0x81, 0x2E, 0x87, 0x70, 0x00, 0x09, 0x8F, 0x63, 0x00, 0x06, 0x90, 0x79, 0x00, 0x06, 0x8F, 0x51, 0x00, 0x09, 0x81, 0xCD, 0x6A, 0x00, 0x12, 0x9B, 0x03, 0x00, 0x81, 0x3D, 0x87, 0x6D, 0xF8, 0xFB, 0xFD, 0x00, 0x15, 0xC6, 0x5E, 0x00, 0x31, 0xC6, 0x61, 0x00, 0x23, 0x81, 0xBC, 0x59, 0x00, 0x0F, 0x8F, 0x5D, 0x00, 0x15, 0xC6, 0x61, 0x00, 0x21, 0x8F, 0x5D, 0x6C, 0x76, 0xC6, 0x6B, 0x75, 0xC6, 0x49, 0x4D, 0x00, 0x3A, 0x82, 0xAB, 0x59, 0x00, 0x81, 0x46, 0x81, 0x89, 0x1D, 0x00, 0x2D, 0x87, 0x70, 0x00, 0x6F, 0x90, 0x5E, 0x00, 0x81, 0x31, 0x87, 0x70, 0x00, 0x15, 0x82, 0xC6, 0x6E, 0x00, 0x18, 0x83, 0xE0, 0x2A, 0x00, 0x81, 0x3D, 0x84, 0x37, 0xC1, 0xD8, 0x00, 0x0E, 0x81, 0x85, 0x4C, 0x00, 0x2A, 0x8F, 0x5D, 0x00, 0x15, 0xD6, 0x3E, 0x00, 0x1A, 0x81, 0xBC, 0x59, 0x00, 0x2D, 0xD6, 0x3E, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x05, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x6C, 0x76, 0xC6, 0x6B, 0x74, 0xC6, 0x64, 0x6B, 0xB6, 0x00, 0x82, 0x2C, 0x87, 0x70, 0x00, 0x06, 0x85, 0x9C, 0x08, 0x00, 0x82, 0x20, 0x83, 0xA5, 0x34, 0x41, 0x43, 0x56, 0x00, 0x24, 0x82, 0xCA, 0x60, 0x00, 0x81, 0x53, 0xA7, 0x27, 0x00, 0x81, 0x03, 0xD6, 0x3E, 0x00, 0x0C, 0x8F, 0x5D, 0x6E, 0x7A, 0x00, 0x0D, 0x8F, 0x5D, 0x6B, 0x74, 0xC5, 0x6A, 0x72, 0xC5, 0x48, 0x4C, 0x00, 0x37, 0x8F, 0x63, 0x00, 0x81, 0x76, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xE3, 0x2F, 0x00, 0x82, 0x44, 0x83, 0xC2, 0x4E, 0x00, 0x81, 0x56, 0xA7, 0x27, 0x00, 0x29, 0xE6, 0x1B, 0x00, 0x15, 0xD6, 0x3E, 0x00, 0x1C, 0x8F, 0x5D, 0x00, 0x20, 0xD6, 0x3E, 0x00, 0x10, 0x8F, 0x5D, 0x78, 0xC7, 0x6C, 0x77, 0xC6, 0x6C, 0x75, 0xC6, 0x6B, 0x74, 0xC6, 0x6A, 0x73, 0xC5, 0x6A, 0x71, 0xC5, 0x62, 0x69, 0xB5, 0x00, 0x57, 0x9F, 0x40, 0x00, 0x63, 0x84, 0xCE, 0x62, 0x00, 0x42, 0x42, 0x00, 0x2D, 0x81, 0xA4, 0x0E, 0x00, 0x06, 0x82, 0x82, 0x69, 0x00, 0x0C, 0x84, 0xB4, 0x66, 0x00, 0x21, 0xE4, 0x16, 0x00, 0x81, 0x76, 0x83, 0xD9, 0x7A, 0x00, 0x09, 0x84, 0xD3, 0x0A, 0x00, 0x06, 0x82, 0xDE, 0x2F, 0x00, 0x81, 0x4C, 0x87, 0x70, 0xE3, 0xEE, 0xF6, 0x00, 0x21, 0x8F, 0x5D, 0x00, 0x7B, 0xD6, 0x3E, 0x00, 0x0C, 0xB7, 0x04, 0x00, 0x0D, 0x8F, 0x5D, 0x73, 0xC5, 0x6A, 0x72, 0xC5, 0x69, 0x70, 0xC5, 0x68, 0x6F, 0xC4, 0x48, 0x4B, 0x00, 0x82, 0x30, 0x82, 0xA9, 0x60, 0x00, 0x06, 0x84, 0xDF, 0x37, 0x00, 0x0C, 0xBE, 0x11, 0x00, 0x82, 0x05, 0x82, 0xAC, 0x24, 0x00, 0x18, 0x82, 0xA2, 0x4D, 0x00, 0x12, 0x85, 0xAD, 0x25, 0x00, 0x81, 0x3A, 0x87, 0x70, 0x00, 0x19, 0xCE, 0x4E, 0x00, 0x45, 0x81, 0xBC, 0x59, 0x00, 0x2D, 0xD6, 0x3E, 0x00, 0x06, 0x8F, 0x5D, 0x00, 0x11, 0xD6, 0x3E, 0x00, 0x05, 0x8F, 0x5D, 0x00, 0x08, 0x87, 0x6D, 0x00, 0x0E, 0x8F, 0x5D, 0x69, 0x70, 0xC4, 0x68, 0x6E, 0xC4, 0x61, 0x66, 0x00, 0x37, 0x8F, 0x63, 0x00, 0x82, 0x02, 0x85, 0x5F, 0x00, 0x0F, 0x8F, 0x6F, 0x00, 0x6F, 0x82, 0x92, 0x46, 0x00, 0x81, 0x16, 0xFF, 0x31, 0xC0, 0xC0, 0xC7, 0x00, 0x09, 0xC7, 0x5F, 0x5A, 0x5C, 0x6D, 0x00, 0x06, 0x15, 0x00, 0x12, 0x9A, 0x38, 0x00, 0x81, 0x4D, 0xB7, 0x04, 0x00, 0x06, 0x87, 0x70, 0x00, 0x78, 0xD6, 0x3E, 0x00, 0x1E, 0x8F, 0x5D, 0x74, 0x00, 0x0D, 0x8F, 0x5D, 0x68, 0x6E, 0xC4, 0x67, 0x6C, 0xC3, 0x47, 0x4A, 0x00, 0x82, 0x3C, 0x82, 0xB9, 0x43, 0x00, 0x0C, 0xD0, 0x56, 0x00, 0x81, 0x79, 0xA7, 0x54, 0x00, 0x06, 0xA3, 0x50, 0x00, 0x15, 0xF9, 0x1F, 0x00, 0x15, 0x82, 0xD2, 0x50, 0x00, 0x81, 0x34, 0x87, 0x70, 0x9E, 0xC2, 0xDE, 0x00, 0x52, 0xD6, 0x3E, 0x00, 0x1B, 0x81, 0xBC, 0x59, 0x00, 0x38, 0xD6, 0x3E, 0x00, 0x10, 0x8F, 0x5D, 0x72, 0xC5, 0x69, 0x00, 0x08, 0x8F, 0x5D, 0x67, 0x6D, 0xC4, 0x66, 0x6B, 0xC3, 0x5F, 0x64, 0xB4, 0x00, 0x82, 0x38, 0x8F, 0x63, 0x00, 0x0C, 0x82, 0x8A, 0x4D, 0x00, 0x09, 0x83, 0xF5, 0x6F, 0x00, 0x81, 0x73, 0x82, 0xBC, 0x16, 0x00, 0x06, 0xFA, 0x14, 0x00, 0x15, 0x91, 0x5F, 0x00, 0x06, 0x81, 0xC6, 0x3C, 0x00, 0x81, 0x40, 0xE6, 0x30, 0x00, 0x2B, 0xC6, 0x61, 0x00, 0x38, 0x82, 0x93, 0x17, 0x00, 0x48, 0xD6, 0x3E, 0x00, 0x0C, 0xB7, 0x04, 0x00, 0x0C, 0x8F, 0x5D, 0x67, 0x6D, 0xC4, 0x67, 0x6C, 0xC3, 0x66, 0x6B, 0xC3, 0x65, 0x69, 0xC3, 0x40, 0x42, 0x69, 0x00, 0x82, 0x32, 0x9F, 0x43, 0x00, 0x0C, 0xCF, 0x7C, 0x00, 0x09, 0x95, 0x45, 0x73, 0x75, 0x83, 0x00, 0x06, 0xD5, 0x79, 0x00, 0x82, 0x1D, 0x85, 0xB5, 0x00, 0x00, 0x81, 0x53, 0x8F, 0x5D, 0x00, 0x45, 0xD6, 0x3E, 0x00, 0x1A, 0xE6, 0x1B, 0x00, 0x16, 0xC6, 0x61, 0x82, 0x00, 0x17, 0xC6, 0x61, 0x77, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x65, 0x6A, 0xC3, 0x65, 0x68, 0xC2, 0x56, 0x5B, 0x97, 0x00, 0x82, 0x35, 0x9F, 0x34, 0x00, 0x18, 0x82, 0xAA, 0x04, 0x4D, 0x4F, 0x62, 0x00, 0x81, 0x6D, 0x9F, 0x4C, 0x00, 0x1E, 0x84, 0xFD, 0x70, 0x00, 0x12, 0x84, 0x9F, 0x30, 0x00, 0x81, 0x6F, 0xD6, 0x3E, 0x00, 0x28, 0x82, 0x93, 0x17, 0x00, 0x09, 0x8F, 0x5D, 0x00, 0x3F, 0xD6, 0x3E, 0x00, 0x0E, 0x8F, 0x5D, 0xC4, 0x00, 0x0F, 0x8F, 0x5D, 0x64, 0x68, 0xC2, 0x5F, 0x64, 0x00, 0x5E, 0x82, 0x8C, 0x10, 0x00, 0x81, 0x46, 0x95, 0x33, 0x00, 0x82, 0x1A, 0xBF, 0x03, 0x00, 0x06, 0xD6, 0x44, 0x00, 0x18, 0x82, 0xA4, 0x43, 0x00, 0x81, 0x40, 0x81, 0x85, 0x70, 0x00, 0x31, 0x8F, 0x5D, 0x00, 0x81, 0x03, 0xD6, 0x3E, 0x00, 0x10, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x64, 0x67, 0xC2, 0x63, 0x66, 0x00, 0x70, 0x82, 0xD3, 0x0C, 0x00, 0x81, 0x3A, 0x81, 0xB4, 0x21, 0x00, 0x82, 0x14, 0x82, 0xD3, 0x3F, 0x00, 0x06, 0x81, 0x89, 0x71, 0x00, 0x15, 0xEF, 0x0F, 0xC0, 0xC0, 0xC7, 0xE6, 0xE6, 0xE9, 0x00, 0x81, 0x3A, 0xE6, 0x30, 0xDC, 0xE9, 0xF3, 0x00, 0x66, 0xD6, 0x3E, 0x00, 0x1C, 0xE6, 0x1B, 0x00, 0x32, 0xD6, 0x3E, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x0D, 0x8F, 0x5D, 0xC2, 0x64, 0x67, 0xC2, 0x64, 0x66, 0xC2, 0x63, 0x65, 0x00, 0x82, 0x21, 0x87, 0x70, 0x00, 0x81, 0x28, 0xC6, 0x5E, 0x00, 0x06, 0xF6, 0x16, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x81, 0xFB, 0x0B, 0x00, 0x66, 0x89, 0x1E, 0x00, 0x06, 0x82, 0xB4, 0x08, 0x00, 0x09, 0xB9, 0x18, 0x00, 0x06, 0x82, 0x8B, 0x54, 0x80, 0x81, 0x8F, 0x00, 0x06, 0xA9, 0x41, 0x00, 0x06, 0xF2, 0x15, 0x00, 0x0C, 0x84, 0xF7, 0x01, 0x00, 0x81, 0x59, 0xF5, 0x78, 0x00, 0x81, 0x0C, 0xD6, 0x3E, 0x69, 0x71, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x62, 0x64, 0x00, 0x82, 0x21, 0x87, 0x70, 0x00, 0x78, 0xA8, 0x19, 0x00, 0x2A, 0xA0, 0x08, 0x00, 0x0F, 0xFE, 0x24, 0x00, 0x0C, 0xC5, 0x72, 0x00, 0x60, 0x89, 0x2A, 0x00, 0x2D, 0x83, 0xBC, 0x6F, 0x00, 0x81, 0x2B, 0x87, 0x70, 0x00, 0x18, 0x81, 0x9D, 0x1F, 0x00, 0x33, 0x82, 0x93, 0x17, 0x00, 0x31, 0xD6, 0x3E, 0x8F, 0x00, 0x17, 0xD6, 0x3E, 0x84, 0x00, 0x17, 0xD6, 0x3E, 0x79, 0x00, 0x14, 0xC6, 0x61, 0x00, 0x05, 0x8F, 0x5D, 0x66, 0x6B, 0xC3, 0x66, 0x6A, 0x00, 0x0D, 0x8F, 0x5D, 0x62, 0x63, 0x00, 0x83, 0x13, 0x87, 0x70, 0x00, 0x06, 0x96, 0x25, 0x00, 0x27, 0x84, 0xCD, 0x0D, 0x00, 0x12, 0x81, 0xA0, 0x43, 0x00, 0x6C, 0x83, 0x85, 0x08, 0x00, 0x06, 0x90, 0x55, 0x00, 0x2A, 0x83, 0xC1, 0x71, 0x00, 0x81, 0x28, 0x87, 0x70, 0xBA, 0xD3, 0xE7, 0x00, 0x39, 0x8F, 0x5D, 0x00, 0x39, 0x82, 0x93, 0x17, 0x00, 0x40, 0xD6, 0x3E, 0x00, 0x06, 0x8F, 0x5D, 0x00, 0x0B, 0xC6, 0x61, 0x00, 0x0D, 0x8F, 0x5D, 0x65, 0xC1, 0x62, 0x64, 0xC1, 0x62, 0x62, 0x00, 0x83, 0x13, 0x87, 0x70, 0x00, 0x09, 0x8E, 0x35, 0x00, 0x24, 0x81, 0xB4, 0x48, 0x00, 0x0F, 0x81, 0xDE, 0x51, 0x8D, 0x8E, 0x9A, 0x80, 0x81, 0x8F, 0x00, 0x0C, 0xA8, 0x64, 0x00, 0x12, 0x9E, 0x45, 0x00, 0x82, 0x20, 0xE6, 0x30, 0xF8, 0xFB, 0xFD, 0x00, 0x72, 0xD6, 0x3E, 0x00, 0x1C, 0x81, 0xBC, 0x59, 0x00, 0x16, 0xD6, 0x3E, 0xC8, 0x00, 0x1B, 0xD6, 0x3E, 0x00, 0x18, 0x8F, 0x5D, 0x56, 0x57, 0xA3, 0x00, 0x83, 0x12, 0x87, 0x70, 0x00, 0x09, 0x81, 0xB5, 0x0D, 0x00, 0x21, 0x87, 0x28, 0x00, 0x09, 0xF1, 0x2F, 0x00, 0x12, 0x8F, 0x48, 0x00, 0x0C, 0x81, 0xB7, 0x48, 0x00, 0x81, 0x0A, 0x81, 0xFE, 0x26, 0x00, 0x81, 0x41, 0x81, 0xBC, 0x59, 0x00, 0x17, 0xC6, 0x61, 0x00, 0x48, 0x82, 0x93, 0x17, 0x00, 0x37, 0x8F, 0x5D, 0x00, 0x14, 0xD6, 0x3E, 0x00, 0x09, 0xB7, 0x04, 0x00, 0x0C, 0x8F, 0x5D, 0x4D, 0x4E, 0x8D, 0x00, 0x83, 0x18, 0x84, 0xC6, 0x63, 0x00, 0x24, 0xEF, 0x45, 0x00, 0x09, 0xE5, 0x29, 0x00, 0x15, 0x81, 0xCF, 0x60, 0x00, 0x0C, 0x81, 0xBD, 0x48, 0x00, 0x57, 0x8F, 0x63, 0x4D, 0x4F, 0x62, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0xC1, 0x1A, 0x00, 0x1E, 0xE8, 0x47, 0x00, 0x81, 0x3A, 0xB7, 0x07, 0x00, 0x58, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x1A, 0x81, 0xBC, 0x59, 0x00, 0x16, 0xD6, 0x3E, 0x73, 0x00, 0x10, 0xC6, 0x61, 0x00, 0x09, 0x8F, 0x5D, 0x63, 0x66, 0xC1, 0x63, 0x64, 0xC1, 0x62, 0x63, 0xC1, 0x61, 0x62, 0xC0, 0x3C, 0x3E, 0x00, 0x82, 0x27, 0x84, 0x81, 0x09, 0x00, 0x06, 0x82, 0xF1, 0x15, 0x00, 0x09, 0x96, 0x3D, 0x00, 0x06, 0x83, 0xF9, 0x31, 0x00, 0x54, 0x86, 0x45, 0x00, 0x09, 0x81, 0xCF, 0x36, 0x00, 0x24, 0xA6, 0x6B, 0x00, 0x21, 0x82, 0x96, 0x59, 0x00, 0x09, 0x81, 0xDE, 0x75, 0x00, 0x54, 0xC0, 0x37, 0x00, 0x09, 0x81, 0xCD, 0x40, 0x00, 0x09, 0x81, 0xFB, 0x7D, 0x00, 0x0C, 0x82, 0xCC, 0x17, 0x00, 0x15, 0x82, 0x1D, 0x00, 0x81, 0x38, 0xF5, 0x7B, 0x00, 0x6B, 0x82, 0x93, 0x17, 0x00, 0x4B, 0xD6, 0x3E, 0x00, 0x0F, 0x8F, 0x5D, 0x56, 0x56, 0x00, 0x82, 0x27, 0x97, 0x4D, 0x00, 0x18, 0x81, 0xA7, 0x08, 0x00, 0x54, 0xA6, 0x0E, 0x00, 0x06, 0x88, 0x53, 0x00, 0x24, 0x81, 0xEC, 0x20, 0x00, 0x27, 0x82, 0x9B, 0x6D, 0x00, 0x57, 0x81, 0xEC, 0x20, 0x00, 0x06, 0x89, 0x18, 0x00, 0x12, 0x85, 0xA6, 0x3C, 0x00, 0x09, 0xEE, 0x1D, 0x00, 0x15, 0x81, 0xCD, 0x58, 0x00, 0x81, 0x37, 0xA7, 0x2A, 0x00, 0x69, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x1D, 0xE6, 0x1B, 0x00, 0x13, 0xD6, 0x3E, 0x66, 0x00, 0x0B, 0xB7, 0x04, 0x00, 0x09, 0x8F, 0x5D, 0x3F, 0x41, 0x68, 0x00, 0x82, 0x2C, 0x85, 0xF1, 0x60, 0x00, 0x0C, 0xC6, 0x73, 0x00, 0x09, 0xDE, 0x49, 0x00, 0x51, 0x84, 0xAE, 0x36, 0x00, 0x2A, 0x81, 0xE6, 0x11, 0x00, 0x27, 0x82, 0xA3, 0x09, 0x00, 0x51, 0x81, 0xF4, 0x61, 0x00, 0x09, 0x88, 0x6B, 0x00, 0x1B, 0x81, 0xB5, 0x76, 0x00, 0x06, 0x81, 0x1C, 0x00, 0x12, 0xA0, 0x38, 0x00, 0x81, 0x35, 0xA7, 0x2A, 0x00, 0x42, 0xD6, 0x3E, 0x00, 0x2F, 0x82, 0x93, 0x17, 0x76, 0x00, 0x47, 0xD6, 0x3E, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x05, 0x87, 0x6D, 0x00, 0x82, 0x29, 0x8F, 0x5D, 0x00, 0x06, 0x86, 0x30, 0x00, 0x15, 0x8E, 0x44, 0x00, 0x06, 0x95, 0x51, 0x00, 0x4B, 0x81, 0xED, 0x2D, 0x00, 0x2D, 0x82, 0x8B, 0x60, 0x00, 0x09, 0x98, 0x5D, 0x00, 0x27, 0x88, 0x17, 0x00, 0x4E, 0xA8, 0x52, 0x00, 0x21, 0xAF, 0x77, 0x00, 0x06, 0x82, 0x38, 0x00, 0x0F, 0x8A, 0x0D, 0x00, 0x81, 0x34, 0xDE, 0x31, 0x00, 0x75, 0x82, 0x93, 0x17, 0x00, 0x37, 0xD6, 0x3E, 0x00, 0x0B, 0xE6, 0x1B, 0x00, 0x0F, 0x8F, 0x5D, 0x42, 0x43, 0x70, 0x00, 0x82, 0x26, 0x9F, 0x37, 0x00, 0x1E, 0x81, 0xE2, 0x73, 0x00, 0x06, 0xA5, 0x2B, 0x00, 0x48, 0x9F, 0x49, 0x00, 0x2D, 0x82, 0x9B, 0x40, 0x00, 0x27, 0x81, 0xF4, 0x37, 0x00, 0x09, 0x9E, 0x66, 0x00, 0x48, 0x98, 0x7B, 0x00, 0x15, 0x81, 0xC4, 0x49, 0x00, 0x18, 0x81, 0xDE, 0x03, 0x00, 0x81, 0x2E, 0xDE, 0x40, 0xB3, 0xCF, 0x00, 0x0D, 0x82, 0xBA, 0x3B, 0x00, 0x5A, 0x82, 0xE9, 0x55, 0x00, 0x21, 0x82, 0x93, 0x17, 0x00, 0x0F, 0x8F, 0x5D, 0x00, 0x2F, 0xD6, 0x3E, 0xC3, 0x00, 0x0C, 0xB7, 0x04, 0x61, 0x62, 0xC0, 0x5B, 0x5B, 0xB1, 0x00, 0x72, 0x96, 0x16, 0x00, 0x09, 0x81, 0xA9, 0x40, 0x00, 0x06, 0x06, 0x00, 0x81, 0x25, 0xE4, 0x79, 0x00, 0x06, 0x87, 0x01, 0x00, 0x1B, 0x8E, 0x6E, 0x00, 0x06, 0x8E, 0x3E, 0x00, 0x48, 0x81, 0x95, 0x59, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x09, 0x90, 0x0A, 0x00, 0x21, 0xAF, 0x47, 0x00, 0x51, 0x82, 0xA4, 0x04, 0x00, 0x2A, 0x85, 0xE4, 0x14, 0x00, 0x06, 0x83, 0xFB, 0x7B, 0x00, 0x81, 0x28, 0x87, 0x70, 0x00, 0x15, 0x81, 0xAD, 0x02, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x42, 0xD6, 0x3E, 0x63, 0x00, 0x05, 0xA7, 0x27, 0x61, 0x61, 0xC0, 0x45, 0x46, 0x00, 0x64, 0x84, 0xB8, 0x1F, 0x00, 0x06, 0xDA, 0x5D, 0x00, 0x18, 0x82, 0xBE, 0x60, 0x00, 0x81, 0x25, 0x81, 0x84, 0x1B, 0x00, 0x81, 0x19, 0x87, 0x70, 0x00, 0x09, 0x2A, 0x00, 0x21, 0x8A, 0x37, 0x00, 0x51, 0x87, 0x70, 0x00, 0x15, 0x83, 0xD0, 0x50, 0x00, 0x81, 0x43, 0xFE, 0x00, 0x00, 0x13, 0xBE, 0x77, 0x00, 0x65, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x1C, 0xE6, 0x1B, 0x00, 0x14, 0xD6, 0x3E, 0x67, 0x6C, 0x00, 0x13, 0xC6, 0x61, 0x00, 0x66, 0x8F, 0x5D, 0x67, 0x68, 0x78, 0x00, 0x21, 0x83, 0xC4, 0x11, 0x00, 0x81, 0x25, 0x87, 0x70, 0x00, 0x15, 0x81, 0x8B, 0x25, 0x00, 0x12, 0xAD, 0x27, 0x00, 0x48, 0xA7, 0x33, 0x00, 0x2A, 0x87, 0x1C, 0x00, 0x2A, 0x82, 0xCA, 0x36, 0x00, 0x82, 0x29, 0x87, 0x70, 0x00, 0x12, 0xE6, 0x21, 0x00, 0x55, 0xD6, 0x3E, 0x00, 0x4E, 0x8F, 0x5D, 0x00, 0x20, 0xD6, 0x3E, 0x00, 0x60, 0x8F, 0x5D, 0x67, 0x68, 0x78, 0x00, 0x27, 0x82, 0xCE, 0x31, 0x00, 0x30, 0x87, 0x70, 0x00, 0x78, 0x81, 0xAC, 0x0D, 0xC0, 0xC0, 0xC7, 0x00, 0x18, 0xC5, 0x30, 0x00, 0x06, 0xDD, 0x3C, 0x00, 0x4B, 0x89, 0x39, 0x00, 0x09, 0x87, 0x1C, 0x00, 0x21, 0x81, 0xF3, 0x48, 0x00, 0x27, 0xA7, 0x2D, 0x00, 0x54, 0x82, 0xCA, 0x60, 0x00, 0x06, 0x81, 0x25, 0x00, 0x21, 0x81, 0x22, 0x00, 0x06, 0x8A, 0x2B, 0x00, 0x81, 0x28, 0x82, 0xB3, 0x10, 0x00, 0x12, 0xAF, 0x1A, 0x00, 0x79, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x14, 0x81, 0xBC, 0x59, 0x00, 0x1E, 0xE6, 0x1B, 0x00, 0x5D, 0x8F, 0x5D, 0x00, 0x06, 0x84, 0x83, 0x5C, 0x00, 0x54, 0x81, 0xC3, 0x75, 0x00, 0x09, 0x81, 0xB1, 0x72, 0x00, 0x75, 0x9F, 0x73, 0x00, 0x06, 0xB7, 0x10, 0x00, 0x1B, 0x84, 0xAC, 0x73, 0x00, 0x4B, 0xBF, 0x03, 0x00, 0x09, 0x82, 0xE2, 0x30, 0x00, 0x21, 0xAF, 0x20, 0x00, 0x2A, 0x82, 0x9B, 0x64, 0x00, 0x54, 0xAF, 0x20, 0x00, 0x24, 0xB1, 0x16, 0x00, 0x15, 0x84, 0xB7, 0x1B, 0x00, 0x81, 0x2B, 0xAF, 0x1A, 0x00, 0x63, 0x82, 0xE9, 0x55, 0x00, 0x60, 0xD6, 0x3E, 0x00, 0x5A, 0x8F, 0x5D, 0x00, 0x1B, 0x82, 0xFD, 0x75, 0x00, 0x06, 0xD2, 0x64, 0x00, 0x06, 0xFA, 0x0B, 0x00, 0x06, 0x81, 0xC5, 0x2F, 0x00, 0x2D, 0x87, 0x70, 0x00, 0x0F, 0x82, 0x93, 0x50, 0x00, 0x63, 0x8F, 0x66, 0x00, 0x12, 0x84, 0xAE, 0x39, 0x00, 0x09, 0x82, 0xB9, 0x43, 0x00, 0x09, 0x82, 0xF7, 0x66, 0x00, 0x09, 0x81, 0xBD, 0x09, 0x00, 0x06, 0x85, 0xF3, 0x14, 0x00, 0x51, 0xDE, 0x3D, 0x00, 0x1E, 0xC6, 0x1F, 0x00, 0x36, 0xD6, 0x74, 0x00, 0x51, 0x82, 0x9B, 0x34, 0x00, 0x1B, 0x8F, 0x63, 0x00, 0x06, 0x82, 0xA6, 0x60, 0x00, 0x81, 0x2B, 0x82, 0x9B, 0x40, 0x00, 0x0F, 0xAF, 0x1A, 0x00, 0x81, 0x0A, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x1C, 0xE6, 0x1B, 0x00, 0x08, 0xB7, 0x04, 0x5E, 0x5E, 0xB9, 0x37, 0x39, 0x52, 0x00, 0x69, 0x84, 0x92, 0x47, 0x00, 0x15, 0x81, 0x8C, 0x14, 0x00, 0x30, 0x87, 0x70, 0x00, 0x0F, 0xFA, 0x62, 0x00, 0x63, 0x84, 0xF4, 0x16, 0x00, 0x33, 0x82, 0xE7, 0x41, 0x00, 0x54, 0x83, 0xAF, 0x14, 0x00, 0x1B, 0xB7, 0x64, 0x00, 0x09, 0x92, 0x48, 0x00, 0x24, 0x82, 0x8B, 0x3F, 0x00, 0x4B, 0x82, 0xAB, 0x6E, 0x00, 0x0F, 0xDF, 0x1A, 0x00, 0x18, 0xF7, 0x32, 0x00, 0x09, 0x83, 0xC0, 0x31, 0x00, 0x12, 0x8B, 0x1D, 0x00, 0x81, 0x19, 0x87, 0x70, 0x00, 0x0F, 0x81, 0xEB, 0x79, 0x00, 0x78, 0xD6, 0x3E, 0x00, 0x12, 0x82, 0x93, 0x17, 0x00, 0x0A, 0x8F, 0x5D, 0x00, 0x14, 0xD6, 0x3E, 0x00, 0x1E, 0x8F, 0x5D, 0x4A, 0x4B, 0x86, 0x00, 0x66, 0x87, 0x6D, 0xC0, 0xC0, 0xC7, 0x00, 0x18, 0x87, 0x16, 0x00, 0x30, 0x87, 0x70, 0x00, 0x12, 0x83, 0xB5, 0x17, 0x00, 0x60, 0x83, 0xA6, 0x71, 0x00, 0x33, 0x84, 0xBE, 0x19, 0x00, 0x54, 0x82, 0x93, 0x47, 0x00, 0x1B, 0x83, 0x90, 0x0A, 0x00, 0x09, 0x82, 0x9B, 0x1C, 0x00, 0x2A, 0x82, 0x9C, 0x08, 0x00, 0x51, 0x84, 0x86, 0x68, 0x00, 0x09, 0x87, 0x55, 0x00, 0x09, 0x82, 0x85, 0x03, 0x00, 0x06, 0x81, 0x8D, 0x5A, 0x00, 0x09, 0x90, 0x4F, 0x00, 0x81, 0x2B, 0x81, 0xEC, 0x20, 0x00, 0x0F, 0xDE, 0x34, 0x00, 0x21, 0xD6, 0x3E, 0x00, 0x6F, 0x82, 0x93, 0x17, 0x00, 0x36, 0xD6, 0x3E, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x12, 0x87, 0x6D, 0xF2, 0xF2, 0xF4, 0x00, 0x1E, 0x8C, 0x75, 0x00, 0x33, 0x87, 0x70, 0x00, 0x12, 0x87, 0x73, 0x00, 0x81, 0x5E, 0x83, 0xD0, 0x47, 0x00, 0x09, 0xE4, 0x76, 0x00, 0x15, 0x86, 0x33, 0x00, 0x09, 0x86, 0x51, 0x00, 0x24, 0xCF, 0x58, 0x00, 0x2D, 0x90, 0x0A, 0x00, 0x48, 0x84, 0xEC, 0x6E, 0x00, 0x1B, 0x84, 0xAB, 0x1E, 0x00, 0x81, 0x23, 0x81, 0xF3, 0x69, 0x00, 0x5D, 0x82, 0x93, 0x17, 0x00, 0x30, 0xD6, 0x3E, 0x00, 0x33, 0xE6, 0x1B, 0x00, 0x05, 0x87, 0x6D, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x12, 0x84, 0x86, 0x74, 0x00, 0x24, 0x84, 0xAE, 0x30, 0x00, 0x36, 0x87, 0x70, 0x00, 0x7B, 0x83, 0xF8, 0x75, 0x00, 0x7E, 0x84, 0x92, 0x2C, 0x00, 0x0C, 0xEF, 0x06, 0x00, 0x0F, 0x82, 0x9D, 0x57, 0x00, 0x24, 0x99, 0x58, 0x00, 0x2A, 0x90, 0x0A, 0x00, 0x48, 0x81, 0xF4, 0x0A, 0x00, 0x81, 0x34, 0x82, 0xCA, 0x60, 0x00, 0x0C, 0x81, 0xDC, 0x1F, 0x00, 0x4C, 0xD6, 0x3E, 0x00, 0x4A, 0x82, 0x93, 0x17, 0x00, 0x30, 0xD6, 0x3E, 0x5D, 0x5D, 0x00, 0x52, 0x8F, 0x5D, 0x00, 0x0F, 0xBE, 0x62, 0x00, 0x27, 0x84, 0xB6, 0x1D, 0x00, 0x39, 0x87, 0x70, 0x00, 0x7B, 0x83, 0xF8, 0x78, 0x00, 0x81, 0x13, 0x83, 0xCE, 0x5A, 0x00, 0x24, 0x91, 0x62, 0x00, 0x09, 0x98, 0x1B, 0x00, 0x81, 0x0A, 0x85, 0xB5, 0x4E, 0x00, 0x81, 0x20, 0xB7, 0x0A, 0x00, 0x77, 0x82, 0xE9, 0x55, 0x00, 0x27, 0xD6, 0x3E, 0x6B, 0x00, 0x18, 0xD6, 0x3E, 0x68, 0x00, 0x0D, 0xB7, 0x04, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x0F, 0x82, 0xD9, 0x4E, 0x00, 0x2A, 0x84, 0xBE, 0x0A, 0x00, 0x39, 0x87, 0x70, 0x00, 0x12, 0x83, 0xF7, 0x7D, 0x00, 0x81, 0x5E, 0x81, 0xC3, 0x5A, 0x00, 0x1B, 0xB9, 0x5D, 0x00, 0x24, 0x87, 0x40, 0x00, 0x0C, 0x81, 0x9D, 0x58, 0x00, 0x81, 0x0A, 0x81, 0xAE, 0x60, 0x00, 0x81, 0x1F, 0x81, 0xB4, 0x78, 0x00, 0x5E, 0xD6, 0x3E, 0x00, 0x5F, 0x81, 0xBC, 0x59, 0x00, 0x09, 0xD6, 0x3E, 0x60, 0x60, 0xC0, 0x3A, 0x3B, 0x5A, 0x00, 0x5A, 0x83, 0x89, 0x66, 0x00, 0x2D, 0xBD, 0x04, 0x00, 0x3C, 0x87, 0x70, 0x00, 0x0F, 0x83, 0x92, 0x4E, 0x00, 0x81, 0x61, 0x81, 0xC3, 0x7B, 0x00, 0x12, 0xD1, 0x27, 0xC0, 0xC0, 0xC7, 0x00, 0x27, 0xB9, 0x12, 0x00, 0x09, 0x8A, 0x1C, 0x00, 0x81, 0x0D, 0x82, 0xDC, 0x6C, 0x00, 0x81, 0x1D, 0x9F, 0x3D, 0x00, 0x1E, 0xD6, 0x3E, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x0E, 0x81, 0xBC, 0x59, 0x00, 0x09, 0x8F, 0x5D, 0x50, 0x50, 0x94, 0x00, 0x5D, 0x82, 0xF2, 0x10, 0x00, 0x2D, 0xA6, 0x3E, 0x00, 0x3C, 0x87, 0x70, 0x00, 0x0F, 0x8F, 0x63, 0x00, 0x82, 0x1D, 0x84, 0xC6, 0x6C, 0x00, 0x06, 0x81, 0xB5, 0x25, 0x00, 0x81, 0x10, 0x92, 0x06, 0x00, 0x81, 0x1C, 0xD6, 0x47, 0x00, 0x81, 0x23, 0x81, 0xBC, 0x59, 0x00, 0x23, 0xD6, 0x3E, 0x00, 0x60, 0x8F, 0x5D, 0x00, 0x39, 0x83, 0xA5, 0x1F, 0x00, 0x36, 0x87, 0x70, 0x00, 0x0F, 0x98, 0x48, 0x00, 0x82, 0x20, 0x84, 0xD6, 0x4F, 0x00, 0x81, 0x10, 0x82, 0x20, 0x00, 0x81, 0x13, 0x87, 0x70, 0x00, 0x4E, 0xD6, 0x3E, 0x00, 0x5D, 0x82, 0x93, 0x17, 0x00, 0x21, 0xD6, 0x3E, 0x60, 0x60, 0x00, 0x52, 0x8F, 0x5D, 0x00, 0x0F, 0x82, 0x9B, 0x43, 0x00, 0x30, 0xCD, 0x71, 0x00, 0x3F, 0x87, 0x70, 0x00, 0x0F, 0x83, 0xA1, 0x30, 0x00, 0x81, 0x55, 0x85, 0x8D, 0x7A, 0x00, 0x81, 0x61, 0x84, 0xA7, 0x59, 0x00, 0x81, 0x13, 0xBE, 0x7A, 0x00, 0x81, 0x28, 0x82, 0x93, 0x17, 0x00, 0x0C, 0x8F, 0x5D, 0x00, 0x12, 0xC6, 0x61, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x0C, 0xA4, 0x48, 0x00, 0x33, 0xC5, 0x7B, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x5B, 0x83, 0xB1, 0x10, 0x00, 0x81, 0x67, 0x81, 0xFC, 0x30, 0x00, 0x81, 0x10, 0xF6, 0x04, 0x00, 0x73, 0xD6, 0x3E, 0x00, 0x38, 0x82, 0x93, 0x17, 0x00, 0x1B, 0xD6, 0x3E, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x0F, 0x97, 0x4D, 0x00, 0x33, 0xC5, 0x78, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x04, 0x83, 0xC9, 0x64, 0x00, 0x82, 0x41, 0x85, 0xD6, 0x1E, 0x00, 0x81, 0x0D, 0x81, 0xA5, 0x1E, 0x00, 0x7C, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x32, 0xE6, 0x1B, 0x60, 0x5F, 0x00, 0x52, 0x81, 0xB4, 0x6F, 0x00, 0x0F, 0x83, 0x30, 0x00, 0x33, 0xB3, 0x69, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x5B, 0x83, 0xD0, 0x50, 0x00, 0x81, 0x52, 0x85, 0x9E, 0x79, 0x00, 0x12, 0x93, 0x01, 0x00, 0x81, 0x0D, 0x84, 0xC6, 0x2A, 0xA5, 0xC6, 0xE0, 0x00, 0x54, 0x82, 0xE9, 0x55, 0x00, 0x5D, 0x82, 0x93, 0x17, 0x00, 0x15, 0x81, 0xBC, 0x59, 0x60, 0x60, 0xC0, 0x55, 0x55, 0x00, 0x52, 0x81, 0xA5, 0x12, 0x00, 0x0C, 0xA6, 0x2F, 0x00, 0x36, 0x86, 0x6C, 0x00, 0x4E, 0x87, 0x70, 0x00, 0x81, 0x70, 0x82, 0x8A, 0x50, 0x00, 0x81, 0x07, 0x97, 0x14, 0x00, 0x0F, 0x82, 0xB5, 0x60, 0x00, 0x0F, 0x84, 0xA8, 0x36, 0x00, 0x0C, 0x82, 0x95, 0x5E, 0x00, 0x12, 0xBA, 0x34, 0x00, 0x81, 0x0D, 0x8F, 0x63, 0x00, 0x2E, 0xD6, 0x3E, 0x00, 0x81, 0x09, 0x82, 0x93, 0x17, 0x00, 0x0C, 0x8F, 0x5D, 0x00, 0x06, 0xB7, 0x04, 0x60, 0x5F, 0xC0, 0x3F, 0x40, 0x00, 0x52, 0x81, 0xB4, 0x6F, 0x00, 0x42, 0x83, 0xD7, 0x3C, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x61, 0x83, 0xFF, 0x70, 0x00, 0x81, 0x34, 0x82, 0x86, 0x10, 0x00, 0x0F, 0x9B, 0x5A, 0x00, 0x06, 0x82, 0xD2, 0x62, 0x00, 0x18, 0xBF, 0x7B, 0x00, 0x66, 0x85, 0xB4, 0x20, 0x00, 0x24, 0x81, 0xEC, 0x05, 0x00, 0x7F, 0x82, 0xE9, 0x55, 0x00, 0x38, 0x82, 0x93, 0x17, 0x00, 0x13, 0x8F, 0x5D, 0x54, 0xA2, 0x00, 0x81, 0x16, 0x83, 0xF0, 0x10, 0x00, 0x83, 0x4E, 0x87, 0x70, 0x00, 0x15, 0x81, 0xAD, 0x05, 0x00, 0x0C, 0x94, 0x0B, 0x00, 0x18, 0xB3, 0x3F, 0x00, 0x81, 0x04, 0x97, 0x56, 0xDC, 0xE9, 0xF3, 0x00, 0x3D, 0xD6, 0x3E, 0x00, 0x63, 0x82, 0x93, 0x17, 0x00, 0x26, 0xD6, 0x3E, 0x00, 0x57, 0x8F, 0x5D, 0x00, 0x0F, 0x9B, 0x3C, 0x00, 0x36, 0xED, 0x25, 0x00, 0x82, 0x3B, 0x87, 0x70, 0x00, 0x15, 0x86, 0x81, 0x16, 0x00, 0x06, 0xB2, 0x26, 0x00, 0x72, 0x84, 0xCE, 0x4D, 0x00, 0x09, 0x8C, 0x00, 0x00, 0x1E, 0x85, 0xCC, 0x50, 0x00, 0x18, 0xD7, 0x7B, 0x00, 0x81, 0x04, 0x84, 0x8F, 0x4D, 0xC7, 0xDB, 0xEC, 0x00, 0x81, 0x3A, 0x82, 0x93, 0x17, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x05, 0xB7, 0x04, 0x00, 0x57, 0x8F, 0x5D, 0x00, 0x0F, 0x87, 0x70, 0x00, 0x36, 0x81, 0x8C, 0x6B, 0x00, 0x82, 0x35, 0x87, 0x70, 0x00, 0x09, 0x81, 0xD3, 0x25, 0x00, 0x24, 0x85, 0xCF, 0x0E, 0x00, 0x6C, 0xDE, 0x2E, 0x00, 0x3F, 0x85, 0xDC, 0x30, 0x00, 0x7E, 0x97, 0x59, 0xB2, 0xCE, 0xE4, 0x00, 0x81, 0x3A, 0x82, 0x93, 0x17, 0x00, 0x0C, 0x8F, 0x5D, 0x41, 0x43, 0x6F, 0x00, 0x81, 0x5B, 0x87, 0x70, 0x00, 0x0F, 0x84, 0xCF, 0x54, 0x00, 0x81, 0x61, 0xCE, 0x21, 0x00, 0x33, 0xBD, 0x34, 0x00, 0x69, 0xEE, 0x11, 0x00, 0x06, 0xA7, 0x1E, 0x00, 0x3C, 0x85, 0xDC, 0x30, 0x00, 0x7B, 0x84, 0xAF, 0x0D, 0xAB, 0xC9, 0xE2, 0x00, 0x81, 0x3A, 0x82, 0x93, 0x17, 0x00, 0x09, 0xC6, 0x61, 0x5A, 0x59, 0x00, 0x5B, 0x81, 0xB4, 0x6F, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x36, 0xCD, 0x5C, 0x00, 0x82, 0x2C, 0xAF, 0x20, 0x00, 0x12, 0x81, 0xA0, 0x16, 0x00, 0x27, 0x83, 0x91, 0x50, 0x00, 0x69, 0x85, 0xAF, 0x3C, 0x00, 0x06, 0x81, 0xAD, 0x7D, 0x00, 0x3F, 0x85, 0xDC, 0x30, 0x00, 0x78, 0x84, 0xBE, 0x6D, 0x00, 0x81, 0x3D, 0x82, 0x93, 0x17, 0x00, 0x06, 0xA7, 0x27, 0x60, 0x5F, 0xC0, 0x44, 0x45, 0x00, 0x5B, 0x81, 0xB4, 0x6F, 0x00, 0x42, 0xCD, 0x5C, 0x00, 0x42, 0x87, 0x70, 0x00, 0x42, 0xB8, 0x14, 0x00, 0x81, 0x2E, 0x81, 0xE5, 0x28, 0x00, 0x36, 0x83, 0xA1, 0x30, 0x00, 0x66, 0x87, 0x73, 0x00, 0x09, 0x82, 0x94, 0x7B, 0x00, 0x0F, 0xF2, 0x21, 0x00, 0x06, 0x81, 0x3D, 0x00, 0x2A, 0xE7, 0x2E, 0x00, 0x72, 0x9F, 0x4F, 0xF8, 0xFA, 0xFD, 0x00, 0x1C, 0xD6, 0x3E, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x17, 0xD6, 0x3E, 0x00, 0x15, 0xE6, 0x1B, 0x00, 0x5D, 0x8F, 0x5D, 0x00, 0x0F, 0x9A, 0x71, 0x00, 0x78, 0x87, 0x70, 0x00, 0x81, 0x64, 0xCE, 0x60, 0x00, 0x0C, 0x81, 0xAF, 0x16, 0x00, 0x3C, 0x83, 0xB1, 0x10, 0x00, 0x63, 0x87, 0x73, 0x00, 0x09, 0xF2, 0x2D, 0x00, 0x06, 0x81, 0xFE, 0x14, 0x00, 0x09, 0x81, 0xAF, 0x4F, 0x00, 0x33, 0x94, 0x02, 0x00, 0x6C, 0x84, 0xDE, 0x2D, 0xE3, 0xED, 0xF5, 0x00, 0x81, 0x06, 0x82, 0xE9, 0x55, 0x00, 0x34, 0x82, 0x93, 0x17, 0x00, 0x66, 0x8F, 0x5D, 0x00, 0x0F, 0x84, 0xC2, 0x0E, 0x00, 0x36, 0x86, 0x6C, 0x00, 0x42, 0x87, 0x70, 0x00, 0x0C, 0x98, 0x54, 0x00, 0x81, 0x0A, 0x81, 0x8B, 0x3A, 0x00, 0x57, 0x92, 0x48, 0x00, 0x3F, 0x83, 0xC0, 0x70, 0x00, 0x66, 0x82, 0x23, 0x00, 0x12, 0x81, 0xC8, 0x65, 0x00, 0x39, 0x85, 0xC8, 0x61, 0x00, 0x69, 0x85, 0xC4, 0x33, 0xDC, 0xE8, 0xF3, 0x00, 0x42, 0xD6, 0x3E, 0x00, 0x7B, 0x81, 0xBC, 0x59, 0x60, 0x5F, 0x00, 0x61, 0x8F, 0x5D, 0x00, 0x0F, 0x9E, 0x3C, 0x00, 0x36, 0x81, 0x9A, 0x16, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x61, 0x81, 0x85, 0x73, 0x00, 0x1B, 0x82, 0x9B, 0x16, 0x00, 0x36, 0x86, 0x39, 0x00, 0x66, 0x82, 0xBB, 0x0C, 0x41, 0x43, 0x56, 0x00, 0x06, 0x81, 0xAD, 0x26, 0x00, 0x3F, 0x90, 0x52, 0x00, 0x66, 0x84, 0xB7, 0x1E, 0xC6, 0xDA, 0xEC, 0x00, 0x64, 0x82, 0x93, 0x17, 0x00, 0x30, 0xD6, 0x3E, 0x00, 0x26, 0x82, 0x93, 0x17, 0x00, 0x66, 0x8F, 0x5D, 0x00, 0x12, 0x86, 0x6F, 0x00, 0x33, 0x84, 0x49, 0x00, 0x4E, 0xFE, 0x00, 0x00, 0x81, 0x55, 0x82, 0xF1, 0x03, 0x00, 0x09, 0x82, 0x23, 0x00, 0x48, 0x83, 0xE0, 0x30, 0x00, 0x81, 0x34, 0x99, 0x76, 0x00, 0x60, 0xEE, 0x4A, 0xC6, 0xD9, 0xEB, 0x00, 0x53, 0x82, 0xE9, 0x55, 0x00, 0x61, 0x82, 0x93, 0x17, 0x00, 0x09, 0xB7, 0x04, 0x5C, 0x5B, 0xB8, 0x37, 0x38, 0x00, 0x52, 0x81, 0xC4, 0x4C, 0x00, 0x51, 0x96, 0x4F, 0x00, 0x3F, 0x87, 0x70, 0x00, 0x0F, 0xA5, 0x10, 0x00, 0x81, 0x5B, 0x83, 0xD8, 0x3A, 0x00, 0x4B, 0x83, 0xF0, 0x10, 0x00, 0x60, 0x8A, 0x19, 0x00, 0x06, 0x82, 0xE4, 0x50, 0x00, 0x2A, 0x84, 0xC6, 0x60, 0x00, 0x81, 0x04, 0x85, 0xF3, 0x53, 0xB1, 0xCB, 0xE4, 0x00, 0x72, 0x82, 0x93, 0x17, 0x00, 0x30, 0xD6, 0x3E, 0x00, 0x15, 0x81, 0xBC, 0x59, 0x00, 0x06, 0x8F, 0x5D, 0x4A, 0x4A, 0x85, 0x00, 0x72, 0x84, 0xE1, 0x51, 0x00, 0x33, 0x81, 0x92, 0x2F, 0x00, 0x4B, 0x81, 0x9D, 0x40, 0x00, 0x81, 0x55, 0x81, 0xBD, 0x06, 0x00, 0x09, 0x8D, 0x58, 0x00, 0x4E, 0x83, 0xFF, 0x70, 0x00, 0x5A, 0x82, 0x2C, 0x00, 0x1E, 0xA6, 0x65, 0x00, 0x3F, 0x81, 0x81, 0x21, 0x00, 0x5A, 0x85, 0x8D, 0x5C, 0xA9, 0xC6, 0xE1, 0x00, 0x60, 0x82, 0xE9, 0x55, 0x00, 0x54, 0x82, 0x93, 0x17, 0x00, 0x6F, 0x8F, 0x5D, 0x00, 0x12, 0xC5, 0x6F, 0x00, 0x30, 0x84, 0x49, 0x00, 0x48, 0x81, 0xAD, 0x20, 0x00, 0x81, 0x58, 0x97, 0x4D, 0x00, 0x06, 0x8F, 0x12, 0x00, 0x51, 0x84, 0x8F, 0x50, 0x00, 0x57, 0x97, 0x53, 0x00, 0x06, 0xA0, 0x6B, 0x00, 0x06, 0x81, 0xD4, 0x59, 0x00, 0x30, 0x84, 0xE6, 0x20, 0x00, 0x7E, 0x85, 0xBC, 0x6D, 0xA9, 0xC5, 0x00, 0x06, 0x87, 0x70, 0x00, 0x1A, 0xD6, 0x3E, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x05, 0x8F, 0x5D, 0x5F, 0x5E, 0xBF, 0x00, 0x69, 0x8F, 0x5D, 0x00, 0x42, 0x81, 0xB4, 0x18, 0x00, 0x39, 0x87, 0x70, 0x00, 0x0F, 0xC6, 0x67, 0x00, 0x81, 0x58, 0x84, 0x87, 0x63, 0x00, 0x57, 0x84, 0x9F, 0x30, 0x00, 0x57, 0xC9, 0x19, 0x00, 0x06, 0x84, 0x0A, 0x00, 0x63, 0xA8, 0x10, 0x00, 0x51, 0xD6, 0x7A, 0x93, 0xB6, 0xDA, 0x00, 0x58, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x41, 0x82, 0x93, 0x17, 0x00, 0x72, 0x8F, 0x5D, 0x00, 0x42, 0x85, 0xBB, 0x78, 0x00, 0x36, 0x87, 0x70, 0x00, 0x12, 0xAB, 0x34, 0x00, 0x81, 0x55, 0x8F, 0x5D, 0x00, 0x09, 0x89, 0x54, 0x00, 0x54, 0x84, 0xAF, 0x10, 0x00, 0x54, 0x82, 0x32, 0x00, 0x51, 0x85, 0xDC, 0x12, 0x00, 0x69, 0x85, 0xBC, 0x7C, 0x00, 0x81, 0x2B, 0x82, 0x93, 0x17, 0x00, 0x0C, 0xC6, 0x61, 0x00, 0x72, 0x8F, 0x5D, 0x00, 0x15, 0x96, 0x5B, 0x00, 0x2A, 0xB6, 0x18, 0x00, 0x45, 0x81, 0xDC, 0x40, 0x00, 0x81, 0x58, 0x8F, 0x5D, 0x00, 0x81, 0x31, 0x84, 0xBE, 0x70, 0x00, 0x06, 0x81, 0x85, 0x7C, 0x00, 0x81, 0x34, 0x85, 0x95, 0x67, 0x00, 0x69, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x30, 0x82, 0x93, 0x17, 0x00, 0x06, 0x8F, 0x5D, 0x5F, 0x5D, 0xBF, 0x39, 0x00, 0x50, 0x81, 0xA5, 0x12, 0x00, 0x33, 0x84, 0x87, 0x5A, 0x00, 0x2A, 0xBC, 0x2A, 0x00, 0x33, 0x87, 0x70, 0x00, 0x0F, 0x85, 0x89, 0x73, 0x00, 0x81, 0x5B, 0x81, 0xCC, 0x5A, 0x00, 0x81, 0x31, 0x84, 0xCE, 0x50, 0x00, 0x06, 0x5D, 0x00, 0x6C, 0x92, 0x6C, 0x00, 0x48, 0xD6, 0x7A, 0x00, 0x81, 0x31, 0x82, 0x93, 0x17, 0x00, 0x06, 0x8F, 0x5D, 0x55, 0x56, 0x96, 0x00, 0x81, 0x07, 0x85, 0xB0, 0x2B, 0x00, 0x27, 0xD3, 0x77, 0x00, 0x30, 0x87, 0x70, 0x00, 0x12, 0xAB, 0x7F, 0x00, 0x81, 0x5B, 0x81, 0xB5, 0x04, 0x00, 0x81, 0x31, 0x84, 0xDE, 0x30, 0x00, 0x06, 0x90, 0x40, 0xD9, 0xD9, 0xDD, 0x00, 0x6F, 0x82, 0x96, 0x6E, 0x00, 0x3F, 0x85, 0x95, 0x76, 0xF8, 0xFA, 0xFC, 0x00, 0x79, 0x82, 0x93, 0x17, 0x00, 0x3B, 0xD6, 0x3E, 0x63, 0x63, 0xBA, 0x00, 0x6F, 0x9F, 0x3A, 0x00, 0x21, 0x81, 0xE1, 0x57, 0x00, 0x21, 0xAF, 0x2F, 0x00, 0x2D, 0x87, 0x70, 0x00, 0x12, 0x60, 0x00, 0x81, 0x58, 0xD6, 0x41, 0x00, 0x81, 0x37, 0x84, 0xEE, 0x10, 0x00, 0x30, 0x84, 0xCE, 0x50, 0x00, 0x81, 0x07, 0x85, 0xA5, 0x56, 0xE2, 0xEB, 0xF5, 0x00, 0x81, 0x2E, 0x82, 0x93, 0x17, 0x60, 0x60, 0xC0, 0x66, 0x66, 0xC2, 0x3C, 0x3D, 0x00, 0x81, 0x02, 0x82, 0xE1, 0x6E, 0x00, 0x12, 0x9A, 0x50, 0x00, 0x1E, 0x83, 0x86, 0x57, 0x00, 0x27, 0x87, 0x70, 0x67, 0x68, 0x78, 0x00, 0x12, 0x5A, 0x00, 0x81, 0x61, 0x81, 0xD4, 0x41, 0x00, 0x81, 0x31, 0x84, 0xFD, 0x70, 0x00, 0x06, 0x84, 0xDE, 0x30, 0x00, 0x1B, 0x83, 0xDB, 0x2B, 0x00, 0x5D, 0xD9, 0x71, 0x00, 0x39, 0xD6, 0x7A, 0x00, 0x06, 0x87, 0x70, 0x00, 0x21, 0xD6, 0x3E, 0x00, 0x63, 0x82, 0x93, 0x17, 0x00, 0x27, 0xD6, 0x3E, 0x66, 0x67, 0xC2, 0x58, 0x5D, 0x7F, 0x00, 0x81, 0x10, 0xEB, 0x4A, 0x00, 0x24, 0x81, 0x8A, 0x69, 0x00, 0x21, 0x87, 0x70, 0x4D, 0x4F, 0x62, 0x00, 0x15, 0x9B, 0x21, 0x00, 0x66, 0xFB, 0x51, 0x00, 0x81, 0x07, 0x82, 0x83, 0x6D, 0x00, 0x51, 0x85, 0x8D, 0x50, 0x00, 0x81, 0x5B, 0x85, 0xC7, 0x09, 0x00, 0x33, 0x9F, 0x4F, 0xE2, 0xEB, 0xF5, 0x00, 0x75, 0x82, 0xE9, 0x55, 0x00, 0x36, 0x82, 0x93, 0x17, 0x64, 0x65, 0xBB, 0x00, 0x81, 0x0D, 0x82, 0xF1, 0x48, 0x00, 0x1B, 0xA2, 0x43, 0x00, 0x12, 0x81, 0x9A, 0x58, 0x00, 0x18, 0x87, 0x70, 0x00, 0x06, 0xD3, 0x14, 0x00, 0x18, 0x81, 0xB9, 0x5C, 0x00, 0x81, 0x6A, 0x84, 0x8F, 0x56, 0x00, 0x09, 0x82, 0x4A, 0x00, 0x4E, 0x85, 0x9D, 0x30, 0x00, 0x81, 0x5E, 0x9A, 0x08, 0x00, 0x30, 0xD6, 0x7A, 0xE2, 0xEB, 0xF5, 0x00, 0x51, 0x84, 0xFC, 0x6C, 0x00, 0x57, 0x82, 0x93, 0x17, 0x59, 0x5B, 0x9E, 0x00, 0x54, 0x82, 0xA2, 0x74, 0x00, 0x60, 0x9B, 0x4B, 0x00, 0x06, 0x81, 0xB9, 0x1D, 0x00, 0x09, 0x86, 0x80, 0x0F, 0x00, 0x09, 0x83, 0xBF, 0x36, 0x00, 0x06, 0xFA, 0x2F, 0x00, 0x1E, 0x93, 0x16, 0x00, 0x81, 0x6D, 0x81, 0xD4, 0x35, 0x00, 0x09, 0xE8, 0x11, 0x00, 0x4E, 0x85, 0xAD, 0x10, 0x00, 0x60, 0xA6, 0x50, 0x00, 0x06, 0x85, 0xF4, 0x0C, 0x00, 0x54, 0xCE, 0x60, 0x00, 0x54, 0xD6, 0x7A, 0xE2, 0xEA, 0x00, 0x05, 0x87, 0x70, 0x00, 0x69, 0x82, 0x93, 0x17, 0x00, 0x19, 0xD6, 0x3E, 0x00, 0x1C, 0x82, 0x93, 0x17, 0x50, 0x52, 0x94, 0x00, 0x81, 0x1F, 0x82, 0xF1, 0x42, 0x00, 0x51, 0x86, 0x86, 0x7B, 0x00, 0x81, 0x3D, 0x85, 0xE9, 0x58, 0x00, 0x42, 0x81, 0xD7, 0x32, 0x00, 0x3F, 0xA6, 0x62, 0x00, 0x09, 0xA7, 0x7E, 0x00, 0x5D, 0x81, 0x90, 0x06, 0x00, 0x0F, 0x85, 0xDD, 0x22, 0x00, 0x7B, 0x8B, 0x2C, 0x00, 0x2A, 0x85, 0xF4, 0x36, 0xE2, 0xEA, 0xF5, 0x00, 0x81, 0x13, 0x82, 0xE9, 0x55, 0x5F, 0x62, 0xB3, 0x55, 0x58, 0x9D, 0x49, 0x4B, 0x7F, 0x00, 0x81, 0x2E, 0x83, 0xD7, 0x66, 0x00, 0x09, 0x83, 0xB4, 0x7F, 0x00, 0x3C, 0x87, 0x6A, 0x00, 0x06, 0x85, 0xF9, 0x38, 0x00, 0x81, 0x76, 0x81, 0xBB, 0x55, 0x00, 0x09, 0xB9, 0x03, 0x00, 0x3C, 0xA1, 0x33, 0x00, 0x66, 0x85, 0xCC, 0x50, 0x00, 0x06, 0xD2, 0x6A, 0xF2, 0xF2, 0xF4, 0xA6, 0xA7, 0xB0, 0x00, 0x06, 0x93, 0x3D, 0x00, 0x06, 0x83, 0x39, 0x00, 0x06, 0x84, 0xC6, 0x78, 0xE6, 0xE6, 0xE9, 0x00, 0x72, 0xD2, 0x07, 0x00, 0x24, 0xD6, 0x7A, 0xE1, 0xEA, 0xF5, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x0C, 0xC6, 0x61, 0x5E, 0x63, 0xAD, 0x51, 0x54, 0x8F, 0x47, 0x4A, 0x78, 0x3A, 0x3C, 0x00, 0x73, 0xC6, 0x46, 0x00, 0x4E, 0x85, 0x35, 0x00, 0x36, 0xE1, 0x67, 0xD9, 0xD9, 0xDD, 0x00, 0x81, 0x7F, 0x83, 0xF6, 0x52, 0x00, 0x0C, 0xB1, 0x76, 0x00, 0x36, 0x97, 0x56, 0x00, 0x0C, 0x87, 0x6D, 0x00, 0x5D, 0xCE, 0x00, 0x00, 0x0C, 0x82, 0xE4, 0x2F, 0x00, 0x06, 0x87, 0x7C, 0x00, 0x0C, 0x83, 0x84, 0x13, 0x00, 0x78, 0xC2, 0x2D, 0x00, 0x21, 0xD6, 0x7A, 0x00, 0x07, 0x87, 0x70, 0x00, 0x4D, 0xD6, 0x3E, 0x00, 0x27, 0x8F, 0x5D, 0x68, 0x70, 0xBE, 0x59, 0x60, 0x9F, 0x4F, 0x53, 0x88, 0x41, 0x44, 0x00, 0x81, 0x53, 0x83, 0xE7, 0x2B, 0x00, 0x06, 0xA7, 0x06, 0xB3, 0xB4, 0xBC, 0x00, 0x1E, 0x97, 0x68, 0x00, 0x06, 0x81, 0xB1, 0x39, 0x8D, 0x8E, 0x9A, 0x00, 0x82, 0x08, 0x84, 0x8E, 0x28, 0x00, 0x0C, 0x81, 0x8D, 0x1E, 0x00, 0x15, 0x84, 0x86, 0x29, 0x00, 0x2A, 0x81, 0x9D, 0x7C, 0x00, 0x5D, 0x82, 0x53, 0x00, 0x0C, 0x85, 0xB5, 0x00, 0x00, 0x06, 0x83, 0xE2, 0x53, 0x00, 0x12, 0x85, 0x9D, 0x4B, 0x00, 0x81, 0x13, 0x9C, 0x5B, 0xE1, 0xEA, 0xF5, 0x00, 0x6C, 0x82, 0x93, 0x17, 0x63, 0x6C, 0xB0, 0x57, 0x5F, 0x98, 0x49, 0x4E, 0x79, 0x3E, 0x42, 0x00, 0x81, 0x6E, 0x85, 0x5F, 0x00, 0x12, 0x85, 0xD8, 0x56, 0x00, 0x82, 0x14, 0x83, 0xD7, 0x15, 0x00, 0x12, 0xD0, 0x59, 0x00, 0x27, 0x83, 0xC0, 0x7C, 0x00, 0x12, 0xAD, 0x2A, 0x00, 0x60, 0xA1, 0x7E, 0x00, 0x0C, 0xE6, 0x30, 0x00, 0x06, 0x83, 0xA3, 0x50, 0x00, 0x78, 0xE6, 0x4E, 0x00, 0x2D, 0xF6, 0x49, 0xE1, 0xEA, 0xF4, 0x00, 0x60, 0xD6, 0x3E, 0x61, 0x6B, 0xA9, 0x52, 0x59, 0x8A, 0x43, 0x47, 0x6A, 0x00, 0x57, 0x84, 0xCD, 0x52, 0x00, 0x83, 0x2D, 0x81, 0xFA, 0x07, 0x00, 0x36, 0xD9, 0x32, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x15, 0x8A, 0x22, 0x5A, 0x5C, 0x6D, 0x00, 0x0F, 0x86, 0x8B, 0x50, 0x00, 0x21, 0x82, 0xC5, 0x79, 0x00, 0x51, 0x81, 0xD4, 0x50, 0x00, 0x06, 0x81, 0x01, 0x00, 0x0F, 0x99, 0x16, 0x00, 0x81, 0x01, 0xCA, 0x23, 0x00, 0x15, 0xD6, 0x7A, 0xE9, 0xEF, 0xF7, 0x00, 0x51, 0x82, 0x93, 0x17, 0x6B, 0x7A, 0xBA, 0x5B, 0x66, 0x9A, 0x4F, 0x57, 0x82, 0x3F, 0x44, 0x63, 0x00, 0x84, 0x28, 0x87, 0x61, 0x00, 0x2A, 0xB4, 0x67, 0x00, 0x12, 0x81, 0xF3, 0x0F, 0x00, 0x0F, 0xA2, 0x04, 0x00, 0x66, 0x92, 0x39, 0x00, 0x0C, 0x83, 0x89, 0x6C, 0x00, 0x06, 0x9F, 0x31, 0x00, 0x09, 0xD8, 0x0A, 0x00, 0x06, 0x1B, 0x00, 0x81, 0x04, 0x81, 0x91, 0x04, 0x00, 0x15, 0xD6, 0x7A, 0x00, 0x45, 0x82, 0x93, 0x17, 0x65, 0x74, 0xAB, 0x59, 0x64, 0x93, 0x48, 0x4F, 0x73, 0x00, 0x51, 0x85, 0x8C, 0x40, 0x00, 0x83, 0x7B, 0x87, 0x73, 0x00, 0x06, 0x83, 0xB9, 0x7B, 0x00, 0x27, 0xC4, 0x50, 0x00, 0x6F, 0xB1, 0x58, 0x00, 0x06, 0xF2, 0x27, 0x00, 0x09, 0xC7, 0x4D, 0x00, 0x09, 0x83, 0xB1, 0x0A, 0x00, 0x06, 0x9E, 0x3C, 0x00, 0x81, 0x0A, 0xD2, 0x13, 0x00, 0x12, 0xF6, 0x49, 0x00, 0x36, 0xD6, 0x3E, 0x75, 0x89, 0xC5, 0x63, 0x72, 0xA4, 0x52, 0x5B, 0x83, 0x45, 0x4B, 0x6B, 0x00, 0x84, 0x49, 0x87, 0x61, 0x00, 0x1B, 0xA9, 0x7A, 0x00, 0x18, 0x9D, 0x11, 0x00, 0x06, 0x83, 0xF7, 0x05, 0x00, 0x75, 0x81, 0xB7, 0x1E, 0x00, 0x0C, 0xA0, 0x23, 0x00, 0x06, 0x81, 0xDD, 0x6E, 0x00, 0x09, 0x83, 0xB3, 0x3F, 0x00, 0x81, 0x10, 0xB2, 0x65, 0x00, 0x0C, 0x81, 0xAD, 0x74, 0x00, 0x2A, 0x82, 0x93, 0x17, 0x6E, 0x81, 0xB5, 0x5C, 0x6A, 0x95, 0x4E, 0x58, 0x7C, 0x00, 0x54, 0x85, 0xDB, 0x11, 0x00, 0x84, 0x25, 0x87, 0x7C, 0x00, 0x0F, 0xA9, 0x77, 0x00, 0x82, 0x20, 0x84, 0xCF, 0x6C, 0x00, 0x12, 0xE3, 0x1E, 0xF2, 0xF2, 0xF4, 0x00, 0x1B, 0x82, 0x93, 0x17, 0x7A, 0x92, 0xC8, 0x6C, 0x7F, 0xAE, 0x59, 0x66, 0x8D, 0x46, 0x4E, 0x00, 0x58, 0x86, 0x82, 0x38, 0x00, 0x84, 0x76, 0x88, 0x38, 0x00, 0x81, 0x7C, 0x81, 0x7C, 0x50, 0x57, 0x70, 0x5C, 0x6C, 0x8F, 0x6B, 0x80, 0xA8, 0x6F, 0x86, 0xB0, 0x6E, 0x84, 0xB0, 0x6E, 0x84, 0xB0, 0x64, 0x76, 0x9F, 0x51, 0x5C, 0x7D, 0x42, 0x49, 0x64, 0x00, 0x87, 0x49, 0x87, 0x64, 0x00, 0x87, 0x49, 0x87, 0x49, 0x00, 0x8F, 0x12, 0x8F, 0x12, 0x00, 0x8F, 0x30, 0x8F, 0x30, 0x00, 0x27, 0x85, 0xDC, 0x30, 0x00, 0x84, 0x10, 0x84, 0x34, 0x00, 0x06, 0x82, 0xB0, 0x70, 0x00, 0x06, 0xEA, 0x76, 0x00, 0x06, 0xD4, 0x2D, 0xB3, 0xB4, 0xBC, 0x00, 0x82, 0x02, 0xF6, 0x1F, 0x00, 0x81, 0x2B, 0x81, 0xF3, 0x3C, 0x00, 0x1E, 0x85, 0xDC, 0x30, 0x00, 0x84, 0x0A, 0xCC, 0x3D, 0x00, 0x1E, 0x81, 0xA0, 0x76, 0x00, 0x81, 0x7C, 0x81, 0x85, 0x7F, 0x00, 0x81, 0x25, 0x81, 0x9E, 0x71, 0x00, 0x27, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x3C, 0x87, 0x25, 0x00, 0x06, 0x83, 0xE7, 0x7C, 0x00, 0x42, 0x93, 0x40, 0x00, 0x2A, 0x81, 0x98, 0x7A, 0x00, 0x36, 0x82, 0x91, 0x5D, 0x00, 0x82, 0x62, 0x82, 0xCA, 0x60, 0x00, 0x2A, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x3C, 0x8F, 0x12, 0x00, 0x09, 0xE3, 0x42, 0x00, 0x3C, 0x84, 0x9D, 0x3A, 0x00, 0x1E, 0x84, 0xBC, 0x2F, 0x00, 0x72, 0x84, 0xBC, 0x41, 0x00, 0x82, 0x32, 0x84, 0xB8, 0x2B, 0x00, 0x2D, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x39, 0x87, 0x70, 0x00, 0x0F, 0x81, 0x98, 0x26, 0x00, 0x39, 0xF1, 0x77, 0x00, 0x33, 0x83, 0xCF, 0x3D, 0x00, 0x81, 0x67, 0x81, 0xBD, 0x09, 0x00, 0x15, 0x85, 0xC7, 0x06, 0x00, 0x30, 0x83, 0xC9, 0x79, 0x00, 0x57, 0x83, 0xCA, 0x05, 0x00, 0x39, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x42, 0x8F, 0x5D, 0x00, 0x3C, 0x81, 0xC1, 0x4C, 0x00, 0x12, 0x81, 0x81, 0x0C, 0x00, 0x12, 0x81, 0x9D, 0x3D, 0x73, 0x75, 0x83, 0x00, 0x12, 0x9F, 0x5B, 0x00, 0x81, 0x6A, 0x83, 0xA1, 0x2A, 0x00, 0x09, 0xE3, 0x60, 0x00, 0x42, 0x81, 0xAF, 0x6D, 0x00, 0x81, 0x04, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x45, 0x81, 0x8A, 0x78, 0x00, 0x36, 0x81, 0x92, 0x35, 0x00, 0x12, 0x97, 0x4A, 0x00, 0x1B, 0x93, 0x7C, 0x00, 0x12, 0x81, 0x81, 0x33, 0x00, 0x81, 0x64, 0x81, 0xB5, 0x28, 0x00, 0x4E, 0x82, 0x81, 0x65, 0x00, 0x81, 0x04, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x36, 0x87, 0x70, 0x00, 0x0C, 0x81, 0x80, 0x3B, 0x00, 0x39, 0x93, 0x31, 0x00, 0x0F, 0x8F, 0x5D, 0x00, 0x21, 0x48, 0x00, 0x0F, 0x82, 0xB7, 0x1A, 0x00, 0x81, 0x5E, 0x94, 0x29, 0x00, 0x12, 0x81, 0xBA, 0x4B, 0x00, 0x06, 0x84, 0x80, 0x59, 0x00, 0x81, 0x10, 0x97, 0x50, 0x00, 0x30, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x36, 0xBE, 0x26, 0x00, 0x45, 0x82, 0xBA, 0x02, 0x00, 0x0F, 0x83, 0xD8, 0x10, 0x00, 0x24, 0xAE, 0x79, 0x00, 0x0F, 0x82, 0xB3, 0x0D, 0x00, 0x81, 0x5B, 0x8F, 0x63, 0x00, 0x0F, 0x82, 0xAD, 0x07, 0x00, 0x81, 0x1C, 0x81, 0xF6, 0x03, 0x00, 0x2D, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x3F, 0x97, 0x4D, 0x00, 0x39, 0x83, 0xDD, 0x09, 0x00, 0x0F, 0x88, 0x35, 0x00, 0x2A, 0x8C, 0x7E, 0x00, 0x0F, 0x84, 0xE4, 0x0F, 0x00, 0x81, 0x5B, 0x85, 0x8C, 0x25, 0x00, 0x81, 0x2B, 0x81, 0xD6, 0x4C, 0x00, 0x2A, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x33, 0x87, 0x70, 0x00, 0x0C, 0x8C, 0x7B, 0x00, 0x39, 0x86, 0x72, 0x00, 0x0F, 0x97, 0x4D, 0x00, 0x2A, 0x93, 0x76, 0x00, 0x0C, 0x8F, 0x63, 0x00, 0x5D, 0x83, 0xE5, 0x77, 0x00, 0x81, 0x04, 0xAA, 0x0C, 0x00, 0x81, 0x2B, 0x9D, 0x7D, 0x00, 0x27, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x33, 0x87, 0x70, 0x00, 0x0C, 0xC6, 0x1C, 0x00, 0x39, 0x8B, 0x44, 0x00, 0x0C, 0x88, 0x35, 0x00, 0x30, 0xAB, 0x43, 0x00, 0x0C, 0x8C, 0x4B, 0x00, 0x81, 0x52, 0xBF, 0x0C, 0x00, 0x0C, 0x82, 0xE0, 0x7F, 0x00, 0x85, 0x05, 0xE2, 0x17, 0x00, 0x45, 0x83, 0xCF, 0x4F, 0x00, 0x0C, 0x87, 0x34, 0x00, 0x30, 0x8D, 0x46, 0x00, 0x0C, 0x88, 0x2C, 0x00, 0x81, 0x52, 0xAB, 0x7F, 0x00, 0x09, 0x81, 0x5E, 0x00, 0x81, 0x2E, 0x89, 0x4B, 0x00, 0x06, 0x81, 0xD0, 0x46, 0x00, 0x0C, 0x82, 0xE2, 0x27, 0x00, 0x83, 0x45, 0xE6, 0x39, 0x00, 0x45, 0x83, 0xB7, 0x7C, 0x00, 0x0F, 0x88, 0x35, 0x00, 0x30, 0x85, 0x59, 0x00, 0x0C, 0xB5, 0x26, 0x00, 0x81, 0x52, 0x9F, 0x43, 0x00, 0x81, 0x31, 0x82, 0xD4, 0x2B, 0x00, 0x15, 0x84, 0xA2, 0x51, 0x00, 0x83, 0x48, 0xD6, 0x4D, 0x00, 0x42, 0x82, 0xF2, 0x10, 0x00, 0x42, 0xA7, 0x72, 0x00, 0x0C, 0x88, 0x74, 0x00, 0x81, 0x4F, 0x95, 0x75, 0x00, 0x81, 0x34, 0x82, 0x83, 0x1F, 0x00, 0x06, 0x84, 0xB1, 0x15, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0x82, 0x95, 0x0D, 0x00, 0x09, 0xB2, 0x35, 0x00, 0x1B, 0x84, 0xB9, 0x38, 0x00, 0x83, 0x36, 0xD6, 0x47, 0x00, 0x39, 0xAC, 0x3B, 0x00, 0x0C, 0xF2, 0x3F, 0x00, 0x33, 0x87, 0x31, 0x00, 0x0C, 0x84, 0x87, 0x69, 0x00, 0x81, 0x4F, 0xA7, 0x33, 0x00, 0x54, 0x82, 0xA3, 0x30, 0x00, 0x63, 0x82, 0x85, 0x1E, 0x00, 0x09, 0xA7, 0x21, 0x00, 0x83, 0x51, 0xC6, 0x70, 0x00, 0x0C, 0xD5, 0x5B, 0x00, 0x39, 0x87, 0x70, 0x00, 0x0C, 0xB6, 0x54, 0x00, 0x36, 0x45, 0x00, 0x81, 0x58, 0x83, 0x99, 0x40, 0x00, 0x5D, 0x82, 0xBA, 0x2C, 0x00, 0x63, 0x83, 0xB1, 0x10, 0x00, 0x83, 0x51, 0xD6, 0x50, 0x00, 0x0C, 0x87, 0x2B, 0x00, 0x39, 0x9B, 0x1E, 0x00, 0x42, 0x83, 0xEF, 0x51, 0x00, 0x83, 0x09, 0x87, 0x70, 0x00, 0x83, 0x60, 0xE6, 0x30, 0x00, 0x42, 0x83, 0xB1, 0x10, 0x00, 0x42, 0x83, 0xE0, 0x72, 0x00, 0x81, 0x64, 0x87, 0x70, 0x00, 0x81, 0x28, 0xBD, 0x43, 0x00, 0x06, 0x81, 0xFF, 0x5A, 0x00, 0x83, 0x5A, 0xF6, 0x10, 0x00, 0x42, 0x87, 0x70, 0x00, 0x0F, 0xD6, 0x14, 0x00, 0x82, 0x0E, 0x83, 0xC0, 0x70, 0x00, 0x2D, 0x85, 0x85, 0x60, 0x00, 0x81, 0x0A, 0xC0, 0x2E, 0x00, 0x09, 0xB2, 0x62, 0x00, 0x83, 0x51, 0x81, 0x85, 0x70, 0x00, 0x42, 0x87, 0x70, 0x00, 0x45, 0x83, 0xA8, 0x5E, 0x00, 0x81, 0x5B, 0x83, 0xB9, 0x00, 0x00, 0x57, 0x85, 0x9C, 0x5F, 0x00, 0x5D, 0xD0, 0x0E, 0x00, 0x09, 0x81, 0x90, 0x78, 0x00, 0x0F, 0x81, 0x9D, 0x40, 0x00, 0x83, 0x42, 0x81, 0x95, 0x50, 0x00, 0x42, 0xA6, 0x6B, 0x00, 0x45, 0x83, 0xA8, 0x5E, 0x00, 0x81, 0x5B, 0x87, 0x70, 0x00, 0x09, 0x84, 0xDF, 0x1C, 0x00, 0x81, 0x2B, 0x99, 0x04, 0x00, 0x06, 0x83, 0xB8, 0x6B, 0x00, 0x06, 0x81, 0x3A, 0xB3, 0xB4, 0xBC, 0x00, 0x09, 0x81, 0x43, 0x00, 0x83, 0x42, 0x81, 0xA5, 0x30, 0x00, 0x42, 0xB7, 0x10, 0x00, 0x0C, 0xA7, 0x2D, 0x00, 0x39, 0x93, 0x6D, 0x00, 0x81, 0x5B, 0x87, 0x70, 0x00, 0x09, 0xC1, 0x1D, 0x00, 0x81, 0x2B, 0x96, 0x0A, 0x00, 0x0C, 0x84, 0xE9, 0x77, 0x00, 0x09, 0xDA, 0x24, 0x00, 0x83, 0x45, 0x81, 0xAD, 0x1D, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x33, 0x8F, 0x1E, 0x00, 0x0F, 0x84, 0xC6, 0x24, 0x00, 0x39, 0x83, 0xB5, 0x23, 0x00, 0x81, 0x5E, 0x83, 0xD0, 0x50, 0x00, 0x06, 0x8A, 0x13, 0x00, 0x81, 0x31, 0x96, 0x0D, 0x00, 0x48, 0x83, 0xB1, 0x10, 0x00, 0x83, 0x0C, 0x87, 0x70, 0x00, 0x0C, 0xA6, 0x6E, 0x00, 0x33, 0x9E, 0x7E, 0x00, 0x0F, 0xEE, 0x17, 0x00, 0x82, 0x17, 0x84, 0x8F, 0x50, 0x00, 0x09, 0x82, 0x26, 0x00, 0x81, 0x22, 0xA7, 0x36, 0xA6, 0xA7, 0xB0, 0x00, 0x81, 0x5E, 0x82, 0xD3, 0x2A, 0x00, 0x82, 0x05, 0x81, 0xB1, 0x00, 0x00, 0x39, 0x87, 0x31, 0x00, 0x0C, 0xE5, 0x6B, 0x00, 0x82, 0x1D, 0x83, 0xD0, 0x50, 0x00, 0x63, 0x82, 0xC2, 0x2B, 0x00, 0x48, 0x89, 0x1B, 0x00, 0x83, 0x45, 0x81, 0x8D, 0x45, 0x00, 0x27, 0x9E, 0x3C, 0x00, 0x30, 0xAF, 0x23, 0x00, 0x0C, 0x9F, 0x3D, 0x00, 0x39, 0x8D, 0x3D, 0x00, 0x0C, 0x88, 0x35, 0x00, 0x81, 0x58, 0x8C, 0x5D, 0x00, 0x06, 0x85, 0x84, 0x20, 0x00, 0x81, 0x22, 0x81, 0x64, 0x00, 0x06, 0xAF, 0x20, 0x00, 0x81, 0x6A, 0x82, 0xE5, 0x4E, 0x00, 0x82, 0x2C, 0x81, 0x85, 0x70, 0x00, 0x48, 0x81, 0x95, 0x0E, 0x00, 0x45, 0xFF, 0x01, 0x00, 0x81, 0x2E, 0x82, 0xC2, 0x73, 0x00, 0x06, 0x86, 0x8A, 0x2E, 0x00, 0x81, 0x13, 0x86, 0x54, 0x00, 0x09, 0x84, 0xD7, 0x62, 0x00, 0x0C, 0x85, 0x8F, 0x6D, 0x00, 0x48, 0x83, 0xC0, 0x70, 0x00, 0x83, 0x15, 0x81, 0x95, 0x50, 0x00, 0x2A, 0x85, 0x05, 0x00, 0x0C, 0xAB, 0x43, 0x00, 0x39, 0xB4, 0x70, 0x00, 0x45, 0xA7, 0x72, 0x00, 0x81, 0x3A, 0x81, 0xA5, 0x36, 0x00, 0x09, 0x81, 0xA5, 0x33, 0x00, 0x15, 0x82, 0xE9, 0x0D, 0x00, 0x15, 0x15, 0x00, 0x09, 0x09, 0x00, 0x75, 0x81, 0xAE, 0x42, 0x00, 0x83, 0x30, 0x84, 0xC2, 0x11, 0x00, 0x21, 0x83, 0xC0, 0x70, 0x00, 0x27, 0x8F, 0x63, 0x00, 0x48, 0x83, 0xB8, 0x3E, 0x00, 0x0F, 0x83, 0xC9, 0x5E, 0x00, 0x82, 0x2C, 0x84, 0xC5, 0x14, 0x00, 0x66, 0x82, 0xCE, 0x31, 0x00, 0x78, 0x82, 0xF2, 0x10, 0x00, 0x82, 0x68, 0xEE, 0x26, 0x00, 0x24, 0x96, 0x55, 0x00, 0x12, 0x85, 0x86, 0x0A, 0x00, 0x39, 0x8C, 0x6F, 0x00, 0x0C, 0x81, 0x82, 0x5B, 0x00, 0x81, 0x61, 0xDB, 0x1C, 0x00, 0x15, 0x83, 0x93, 0x55, 0x00, 0x81, 0x0D, 0x87, 0x70, 0x00, 0x83, 0x75, 0x81, 0x95, 0x56, 0x00, 0x1E, 0x87, 0x73, 0x00, 0x12, 0x83, 0x91, 0x71, 0x00, 0x39, 0xAE, 0x55, 0x00, 0x0F, 0x97, 0x4D, 0x00, 0x81, 0x5E, 0xDB, 0x1C, 0x00, 0x12, 0x96, 0x2B, 0x00, 0x09, 0x85, 0xFA, 0x57, 0x00, 0x1E, 0x83, 0x98, 0x33, 0x00, 0x18, 0x18, 0x00, 0x84, 0x3D, 0x81, 0x9D, 0x49, 0x00, 0x12, 0x85, 0x0E, 0x00, 0x15, 0x85, 0xA5, 0x14, 0x00, 0x15, 0x8D, 0x22, 0x00, 0x39, 0x8F, 0x5D, 0x00, 0x0F, 0x90, 0x58, 0x00, 0x81, 0x5B, 0xAC, 0x14, 0x00, 0x0C, 0x82, 0x5F, 0x00, 0x06, 0x82, 0xC9, 0x41, 0x00, 0x81, 0x0A, 0xA1, 0x2A, 0x00, 0x06, 0x9B, 0x1B, 0x00, 0x0F, 0x83, 0x45, 0x5A, 0x5C, 0x6D, 0x00, 0x83, 0x60, 0x81, 0xFB, 0x6E, 0x00, 0x15, 0x81, 0xE3, 0x6B, 0x00, 0x09, 0x84, 0xCA, 0x55, 0x00, 0x06, 0x81, 0xC8, 0x5F, 0x00, 0x4B, 0x84, 0xA4, 0x3B, 0x00, 0x3C, 0x83, 0xD1, 0x45, 0x00, 0x81, 0x3A, 0x81, 0xA0, 0x25, 0x00, 0x30, 0x82, 0xF2, 0x0D, 0x00, 0x78, 0x87, 0x70, 0x00, 0x83, 0x63, 0x90, 0x43, 0x00, 0x33, 0x83, 0xAC, 0x0E, 0x00, 0x3C, 0x81, 0xA3, 0x07, 0x00, 0x0F, 0x8F, 0x5D, 0x00, 0x81, 0x5B, 0xB3, 0x69, 0x00, 0x09, 0xA1, 0x6C, 0x00, 0x81, 0x16, 0x89, 0x54, 0x00, 0x83, 0x78, 0x87, 0x70, 0x00, 0x2D, 0x83, 0x94, 0x32, 0x00, 0x3F, 0x81, 0xF3, 0x48, 0x00, 0x0F, 0x9F, 0x3A, 0x00, 0x81, 0x5B, 0x84, 0x5B, 0x00, 0x09, 0xC1, 0x26, 0x00, 0x21, 0x86, 0x82, 0x41, 0x00, 0x84, 0x73, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xFF, 0x75, 0x00, 0x21, 0x84, 0xBC, 0x02, 0x00, 0x3C, 0x85, 0x3E, 0x00, 0x0F, 0x90, 0x49, 0x00, 0x81, 0x64, 0x81, 0xDC, 0x3A, 0x00, 0x81, 0x19, 0x81, 0x8D, 0x63, 0x00, 0x84, 0x01, 0x87, 0x70, 0x00, 0x06, 0x8F, 0x69, 0x00, 0x15, 0x85, 0xFB, 0x5B, 0xD9, 0xD9, 0xDD, 0xA6, 0xA7, 0xB0, 0x00, 0x3F, 0xBB, 0x05, 0x00, 0x0F, 0xA8, 0x1C, 0x00, 0x81, 0x5E, 0x84, 0x58, 0x00, 0x81, 0x22, 0xEE, 0x1D, 0x00, 0x06, 0x87, 0x70, 0x00, 0x0F, 0xCE, 0x4E, 0x00, 0x06, 0x81, 0x85, 0x5E, 0x00, 0x83, 0x54, 0xCE, 0x60, 0x00, 0x27, 0xF2, 0x18, 0x00, 0x4B, 0x95, 0x0C, 0x00, 0x06, 0x82, 0xF8, 0x01, 0x00, 0x69, 0x85, 0xDC, 0x30, 0x00, 0x81, 0x04, 0xB9, 0x69, 0x00, 0x81, 0x1C, 0xA9, 0x0E, 0x00, 0x0F, 0xCA, 0x3B, 0x00, 0x83, 0x60, 0xCE, 0x60, 0x00, 0x7B, 0x86, 0x0C, 0x00, 0x78, 0x82, 0xF7, 0x63, 0x00, 0x81, 0x3D, 0x83, 0xFF, 0x70, 0x00, 0x5A, 0xFD, 0x68, 0x00, 0x24, 0xD7, 0x45, 0x00, 0x84, 0x2B, 0x82, 0xBB, 0x0F, 0x00, 0x81, 0x7C, 0x81, 0xD7, 0x2F, 0x00, 0x83, 0x63, 0x96, 0x07, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x8B, 0x74, 0x8F, 0x60, 0x00, 0x81, 0x31, 0x81, 0xBD, 0x00, 0x00, 0x86, 0x42, 0x87, 0x73, 0x00, 0x81, 0x67, 0xEF, 0x7B, 0x00, 0x86, 0x09, 0x87, 0x70, 0x00, 0x06, 0xC6, 0x70, 0x00, 0x83, 0x4E, 0x82, 0xD8, 0x7A, 0x00, 0x84, 0x25, 0x83, 0xC8, 0x54, 0x00, 0x87, 0x67, 0x9F, 0x43, 0x00, 0x09, 0x82, 0xA3, 0x30, 0x00, 0x85, 0x05, 0x82, 0x9B, 0x40, 0x00, 0x82, 0x6E, 0x81, 0x80, 0x5C, 0x00, 0x83, 0x48, 0x82, 0xB1, 0x53, 0x00, 0x84, 0x22, 0x87, 0x73, 0x00, 0x06, 0xE8, 0x20, 0x00, 0x83, 0x45, 0x81, 0xDB, 0x03, 0x00, 0x84, 0x2E, 0x97, 0x56, 0x00, 0x66, 0x83, 0xE7, 0x67, 0x00, 0x87, 0x07, 0xBF, 0x0C, 0x00, 0x09, 0xF8, 0x06, 0x00, 0x15, 0x81, 0x98, 0x2C, 0x00, 0x87, 0x55, 0x8F, 0x66, 0x00, 0x0C, 0xF8, 0x0C, 0xD9, 0xD9, 0xDD, 0x00, 0x09, 0x81, 0xBC, 0x7A, 0x00, 0x83, 0x5D, 0x81, 0xD3, 0x43, 0x00, 0x83, 0x72, 0xC6, 0x70, 0x00, 0x54, 0x85, 0x83, 0x52, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x8F, 0x06, 0x8F, 0x60, 0x00, 0xAD, 0x54, 0x83, 0xED, 0x0D, 0x00, 0xA9, 0x4A, 0xA9, 0x4A, 0x00, 0x06, 0xF6, 0x52, 0x00, 0x83, 0x45, 0x83, 0xDF, 0x35, 0x00, 0x84, 0x2B, 0x81, 0xB5, 0x5E, 0x00, 0x81, 0x5E, 0x81, 0xEE, 0x55, 0x00, 0x85, 0x44, 0xEE, 0x20, 0x00, 0x48, 0x81, 0xCC, 0x60, 0x00, 0x09, 0x81, 0xCD, 0x31, 0x00, 0x83, 0x5D, 0x82, 0xE1, 0x56, 0x00, 0x84, 0x0A, 0x87, 0x70, 0x00, 0x87, 0x22, 0x81, 0xC5, 0x41, 0x00, 0x51, 0x87, 0x70, 0x00, 0x09, 0x82, 0xCD, 0x12, 0x00, 0x87, 0x67, 0x87, 0x70, 0x00, 0x87, 0x1F, 0x81, 0xEC, 0x74, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x51, 0x87, 0x70, 0x00, 0x09, 0x82, 0xB3, 0x61, 0x00, 0x87, 0x67, 0x87, 0x70, 0x00, 0x09, 0x82, 0xEA, 0x5F, 0x00, 0x87, 0x16, 0x81, 0xB5, 0x43, 0x00, 0x4E, 0x87, 0x70, 0x00, 0x09, 0x81, 0xCD, 0x28, 0x00, 0x87, 0x64, 0xAF, 0x20, 0x00, 0x0C, 0x84, 0xD9, 0x16, 0x00, 0x87, 0x5E, 0xBF, 0x00, 0x00, 0x06, 0x84, 0xED, 0x1E, 0x00, 0x09, 0x82, 0xDB, 0x08, 0x00, 0x87, 0x07, 0xCE, 0x60, 0x00, 0x33, 0x84, 0xD0, 0x4C, 0x00, 0x36, 0x81, 0xBC, 0x7A, 0x00, 0x87, 0x07, 0x81, 0xF4, 0x58, 0x00, 0x63, 0x87, 0x70, 0x00, 0x83, 0x4B, 0x84, 0xAE, 0x18, 0x00, 0x84, 0x1F, 0x87, 0x70, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x84, 0x8E, 0x64, 0x00, 0x87, 0x25, 0x81, 0xE4, 0x30, 0x00, 0x87, 0x70, 0x82, 0xB3, 0x10, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x8F, 0x60, 0x8F, 0x60, 0x00, 0x87, 0x6A, 0x87, 0x70, 0x00, 0x06, 0x83, 0x90, 0x19, 0x00, 0x87, 0x6A, 0x82, 0xB3, 0x0A, 0x00, 0xCE, 0x72, 0x81, 0xF3, 0x51, 0x00, 0x09, 0x85, 0xA3, 0x7B, 0x00, 0x87, 0x61, 0x82, 0xD2, 0x50, 0x00, 0x24, 0x83, 0xF2, 0x69, 0x00, 0x87, 0x46, 0x87, 0x70, 0x00, 0x2D, 0x84, 0x82, 0x49, 0x00, 0x87, 0x43, 0x87, 0x70, 0x00, 0x0C, 0x87, 0x6D, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x12, 0x83, 0xFE, 0x60, 0x00, 0x15, 0xF6, 0x37, 0x00, 0x0C, 0x84, 0xED, 0x1B, 0x00, 0x87, 0x19, 0x81, 0xBC, 0x74, 0x00, 0x1B, 0x84, 0x81, 0x60, 0x00, 0x18, 0x82, 0x93, 0x0B, 0x00, 0x18, 0x87, 0x70, 0x00, 0x09, 0x81, 0xDC, 0x34, 0x00, 0x87, 0x28, 0x83, 0xB1, 0x55, 0x00, 0x0C, 0x85, 0xDC, 0x30, 0x00, 0x1B, 0xFE, 0x06, 0x00, 0x1E, 0x87, 0x70, 0x00, 0x0C, 0x84, 0xD6, 0x7F, 0x00, 0x87, 0x1F, 0x83, 0xD1, 0x1B, 0x00, 0x09, 0x82, 0x83, 0x1F, 0x00, 0x1E, 0x87, 0x28, 0x00, 0x21, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xEC, 0x1A, 0x00, 0x87, 0x1C, 0x83, 0xA9, 0x62, 0x00, 0x09, 0x9E, 0x7E, 0x00, 0x1E, 0x81, 0xD4, 0x02, 0x00, 0x24, 0x87, 0x70, 0x00, 0x09, 0x84, 0xB1, 0x45, 0x00, 0x87, 0x1C, 0x83, 0xD9, 0x0E, 0x00, 0x27, 0x84, 0xA1, 0x14, 0x00, 0x27, 0x87, 0x70, 0x00, 0x09, 0x82, 0xA3, 0x30, 0x00, 0x87, 0x16, 0x8F, 0x63, 0x00, 0x2A, 0x83, 0xF8, 0x00, 0x00, 0x27, 0x87, 0x70, 0x00, 0x09, 0x83, 0xC9, 0x2B, 0x00, 0x87, 0x16, 0x9F, 0x46, 0x00, 0x2A, 0x85, 0xC4, 0x60, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x06, 0xAF, 0x6E, 0x00, 0x87, 0x16, 0x97, 0x53, 0x00, 0x2A, 0x82, 0x9A, 0x6C, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x09, 0x54, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x87, 0x13, 0x83, 0xE0, 0x7B, 0x00, 0x5D, 0x87, 0x70, 0x00, 0x87, 0x13, 0x82, 0xA3, 0x30, 0x00, 0x09, 0x84, 0xE0, 0x17, 0x00, 0x21, 0x81, 0xC4, 0x70, 0x00, 0x87, 0x46, 0x87, 0x70, 0x00, 0x2A, 0x81, 0xD4, 0x50, 0x00, 0x87, 0x49, 0x87, 0x70, 0x00, 0x06, 0x82, 0x9A, 0x75, 0x00, 0x21, 0xBF, 0x00, 0x00, 0x06, 0xC6, 0x49, 0x00, 0x24, 0x85, 0xE4, 0x47, 0x00, 0x09, 0x84, 0x98, 0x11, 0x00, 0x87, 0x16, 0x82, 0x83, 0x7C, 0x00, 0x09, 0x82, 0xAA, 0x52, 0x00, 0x1E, 0x87, 0x1F, 0x00, 0x2A, 0xB6, 0x66, 0x00, 0x09, 0x82, 0xBB, 0x00, 0x00, 0x87, 0x16, 0xCE, 0x60, 0x00, 0x09, 0xDD, 0x75, 0x00, 0x1E, 0x9F, 0x43, 0x00, 0x09, 0x27, 0x00, 0x21, 0x82, 0xAA, 0x79, 0x00, 0x27, 0x90, 0x31, 0x00, 0x86, 0x7B, 0x87, 0x73, 0x00, 0x24, 0xF5, 0x4B, 0x00, 0x09, 0x85, 0xB8, 0x06, 0x00, 0x1E, 0x9F, 0x43, 0x00, 0x09, 0x97, 0x4D, 0x00, 0x87, 0x1C, 0x83, 0x89, 0x63, 0x00, 0x09, 0x97, 0x53, 0x00, 0x1E, 0xA6, 0x62, 0x00, 0x09, 0x85, 0x86, 0x0A, 0x00, 0x18, 0xBE, 0x59, 0x00, 0x09, 0xF6, 0x13, 0x00, 0x83, 0x60, 0x85, 0xDB, 0x53, 0x00, 0x83, 0x48, 0xDE, 0x46, 0x00, 0x1E, 0x85, 0x9F, 0x5F, 0x00, 0x09, 0xAE, 0x79, 0x00, 0x15, 0x84, 0x9F, 0x54, 0x00, 0x06, 0x86, 0x82, 0x77, 0x00, 0x87, 0x28, 0x82, 0x84, 0x3E, 0x00, 0x09, 0xA6, 0x65, 0x00, 0x1E, 0x81, 0x95, 0x14, 0x00, 0x0C, 0x85, 0xCC, 0x6B, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x85, 0x8C, 0x64, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0x85, 0xC7, 0x4E, 0x00, 0x3C, 0x85, 0xA8, 0x14, 0x00, 0x86, 0x6C, 0x81, 0x8D, 0x66, 0x00, 0x06, 0x87, 0x34, 0x00, 0x27, 0xFD, 0x62, 0x00, 0x54, 0x85, 0xA8, 0x14, 0x00, 0x86, 0x72, 0xCE, 0x6C, 0x00, 0x27, 0xC6, 0x22, 0x73, 0x75, 0x83, 0x00, 0x0F, 0x85, 0xD7, 0x1F, 0x00, 0x06, 0x97, 0x65, 0x00, 0x87, 0x5E, 0x82, 0x9C, 0x05, 0x5A, 0x5C, 0x6D, 0x80, 0x81, 0x8F, 0x00, 0x83, 0x69, 0x85, 0xA4, 0x16, 0x00, 0x8D, 0x13, 0x81, 0xD6, 0x1C}; static bool g_has_uncompressed = false; static unsigned char *get_uncompressed_splash(void) { From fa6cf1ffb8df39715a624c1fee39c63e2776417f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 01:37:43 -0800 Subject: [PATCH 436/489] fix splash boundaries --- sept/sept-secondary/src/splash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sept/sept-secondary/src/splash.c b/sept/sept-secondary/src/splash.c index 7feec1831..019a28aa2 100644 --- a/sept/sept-secondary/src/splash.c +++ b/sept/sept-secondary/src/splash.c @@ -44,7 +44,7 @@ void draw_splash(volatile uint32_t *fb) { } /* Draw actual splash. */ - const size_t x_res = 352; + const size_t x_res = 336; const size_t y_res = 392; const size_t x_start = (768 - x_res) / 2; const size_t y_start = (1280 - y_res) / 2; From 0288986e14a44b49394011c187edd868fe8d6722 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 01:48:56 -0800 Subject: [PATCH 437/489] if you edit splash in a forest and nobody is around does it make a sound --- sept/sept-secondary/src/splash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sept/sept-secondary/src/splash.c b/sept/sept-secondary/src/splash.c index 019a28aa2..90be818a3 100644 --- a/sept/sept-secondary/src/splash.c +++ b/sept/sept-secondary/src/splash.c @@ -23,7 +23,7 @@ #include "lib/lz.h" #include "utils.h" -static const uint8_t s_splash[] = {0x00, 0x34, 0x36, 0x4B, 0x34, 0x36, 0x4B, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x30, 0x30, 0x00, 0x60, 0x60, 0x00, 0x81, 0x40, 0x81, 0x40, 0x00, 0x83, 0x00, 0x83, 0x00, 0x00, 0x86, 0x00, 0x86, 0x00, 0x00, 0x8C, 0x00, 0x8C, 0x00, 0x00, 0x8D, 0x7F, 0x8D, 0x7F, 0x5A, 0x5C, 0x6D, 0x00, 0x87, 0x5E, 0x87, 0x61, 0x73, 0x75, 0x83, 0xA6, 0xA7, 0xB0, 0xD9, 0xD9, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x04, 0x04, 0xFF, 0xCC, 0xCD, 0xD2, 0x00, 0x87, 0x55, 0x87, 0x6A, 0x9A, 0x9B, 0xA5, 0xE6, 0xE6, 0xE9, 0x00, 0x09, 0x87, 0x67, 0x00, 0x27, 0x87, 0x70, 0x41, 0x43, 0x56, 0x00, 0x87, 0x34, 0x97, 0x35, 0x00, 0x12, 0x87, 0x6A, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x15, 0x00, 0x1B, 0x87, 0x70, 0x80, 0x81, 0x8F, 0xF2, 0xF2, 0xF4, 0x00, 0x87, 0x2E, 0x97, 0x74, 0x80, 0x81, 0x8F, 0x00, 0x0C, 0x87, 0x67, 0xB3, 0xB4, 0xBC, 0x73, 0x75, 0x83, 0x00, 0x06, 0x8F, 0x36, 0x9A, 0x9B, 0xA5, 0x00, 0x1B, 0x87, 0x70, 0x67, 0x68, 0x78, 0x00, 0x06, 0x33, 0xD9, 0xD9, 0xDD, 0x00, 0x87, 0x28, 0x8F, 0x66, 0x00, 0x0C, 0x87, 0x6D, 0xCC, 0xCD, 0xD2, 0x4D, 0x4F, 0x62, 0x00, 0x0F, 0x97, 0x62, 0x00, 0x1E, 0x8F, 0x60, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x3C, 0xC0, 0xC0, 0xC7, 0x00, 0x87, 0x22, 0x87, 0x6D, 0x00, 0x09, 0x8F, 0x21, 0xFF, 0xFF, 0xFF, 0x8D, 0x8E, 0x9A, 0x00, 0x15, 0x9F, 0x52, 0x00, 0x21, 0x9F, 0x40, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x42, 0x67, 0x68, 0x78, 0x00, 0x87, 0x1C, 0x87, 0x6D, 0x41, 0x43, 0x56, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0x87, 0x2B, 0x80, 0x81, 0x8F, 0x00, 0x18, 0xA7, 0x42, 0x00, 0x21, 0x87, 0x70, 0x4D, 0x4F, 0x62, 0x00, 0x87, 0x25, 0xAF, 0x47, 0x00, 0x06, 0x87, 0x4C, 0xFF, 0xFF, 0xFF, 0xA6, 0xA7, 0xB0, 0x00, 0x1E, 0x24, 0x00, 0x21, 0x87, 0x49, 0x00, 0x09, 0x97, 0x56, 0x00, 0x0F, 0x98, 0x0F, 0x00, 0x87, 0x13, 0x8F, 0x5D, 0xE6, 0xE6, 0xE9, 0x00, 0x21, 0x88, 0x14, 0x00, 0x21, 0x87, 0x70, 0x5A, 0x5C, 0x6D, 0x00, 0x06, 0x87, 0x70, 0x9A, 0x9B, 0xA5, 0x00, 0x87, 0x16, 0x87, 0x70, 0x8D, 0x8E, 0x9A, 0x00, 0x1E, 0x97, 0x4A, 0x00, 0x2D, 0x87, 0x70, 0x34, 0x36, 0x4B, 0x00, 0x21, 0xB7, 0x3A, 0x00, 0x86, 0x7E, 0x87, 0x70, 0x00, 0x06, 0xA6, 0x65, 0xF2, 0xF2, 0xF4, 0x00, 0x24, 0x97, 0x74, 0x00, 0x24, 0x87, 0x46, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x88, 0x41, 0x00, 0x87, 0x16, 0x87, 0x70, 0x00, 0x09, 0xBE, 0x6B, 0x00, 0x48, 0x87, 0x70, 0x00, 0x09, 0xA0, 0x0E, 0x00, 0x87, 0x13, 0x9F, 0x43, 0x00, 0x09, 0x9E, 0x6F, 0x00, 0x15, 0xB7, 0x04, 0x00, 0x3F, 0x87, 0x70, 0x00, 0x87, 0x13, 0xB7, 0x16, 0x00, 0x09, 0xBE, 0x77, 0x00, 0x21, 0x87, 0x1C, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x2A, 0x54, 0x00, 0x87, 0x46, 0x87, 0x70, 0x00, 0x09, 0xA8, 0x01, 0x00, 0x87, 0x67, 0x87, 0x70, 0x00, 0x09, 0x97, 0x50, 0x00, 0x87, 0x13, 0xE6, 0x3C, 0x00, 0x09, 0x87, 0x70, 0x73, 0x75, 0x83, 0x00, 0x48, 0x87, 0x70, 0x00, 0x09, 0xC6, 0x73, 0x00, 0x87, 0x16, 0xC6, 0x6D, 0x00, 0x27, 0xC6, 0x1F, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x06, 0x81, 0x86, 0x20, 0x00, 0x1E, 0xC7, 0x3E, 0x00, 0x86, 0x7B, 0x87, 0x73, 0x00, 0x27, 0xC6, 0x1F, 0x00, 0x27, 0x87, 0x70, 0x00, 0x09, 0xDE, 0x43, 0x00, 0x21, 0xB7, 0x61, 0x00, 0x86, 0x78, 0x87, 0x70, 0x00, 0x09, 0x96, 0x7F, 0x00, 0x1E, 0xFD, 0x38, 0x00, 0x27, 0x87, 0x70, 0x00, 0x09, 0x9F, 0x3D, 0x00, 0x1E, 0xCF, 0x2E, 0x00, 0x86, 0x7E, 0x81, 0x9D, 0x25, 0x00, 0x24, 0x97, 0x53, 0x00, 0x24, 0x87, 0x70, 0x00, 0x09, 0xDF, 0x0B, 0xF2, 0xF2, 0xF4, 0x00, 0x87, 0x1C, 0x81, 0x85, 0x76, 0x00, 0x06, 0x97, 0x53, 0xF2, 0xF2, 0xF4, 0x00, 0x1B, 0xCE, 0x12, 0x00, 0x24, 0x87, 0x70, 0xA6, 0xA7, 0xB0, 0x00, 0x87, 0x1F, 0xE6, 0x2D, 0x00, 0x0F, 0x8F, 0x63, 0xD9, 0xD9, 0xDD, 0x00, 0x39, 0x87, 0x70, 0x00, 0x09, 0x45, 0x00, 0x87, 0x1F, 0x8F, 0x5D, 0x00, 0x0F, 0xE5, 0x65, 0x00, 0x18, 0xA6, 0x68, 0x00, 0x1E, 0x87, 0x70, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0x81, 0x86, 0x32, 0x00, 0x21, 0xB7, 0x5B, 0x00, 0x87, 0x07, 0xB7, 0x19, 0x00, 0x09, 0x81, 0xBC, 0x68, 0xD9, 0xD9, 0xDD, 0x00, 0x12, 0x97, 0x59, 0x00, 0x1B, 0x87, 0x70, 0x00, 0x09, 0xCE, 0x51, 0x00, 0x87, 0x1C, 0xAF, 0x17, 0x00, 0x1E, 0x8F, 0x24, 0xF2, 0xF2, 0xF4, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0x97, 0x17, 0x00, 0x15, 0x87, 0x70, 0x67, 0x68, 0x78, 0x00, 0x09, 0x81, 0x9D, 0x34, 0x00, 0x87, 0x2E, 0x87, 0x6D, 0x00, 0x12, 0x8F, 0x66, 0x00, 0x09, 0x81, 0xAC, 0x6D, 0x9A, 0x9B, 0xA5, 0x67, 0x68, 0x78, 0x00, 0x06, 0xB7, 0x37, 0xD9, 0xD9, 0xDD, 0x67, 0x68, 0x78, 0x73, 0x75, 0x83, 0x9A, 0x9B, 0xA5, 0x00, 0x0F, 0x2A, 0x00, 0x87, 0x31, 0x87, 0x6D, 0x00, 0x0C, 0x8F, 0x4B, 0x00, 0x09, 0x8F, 0x69, 0x00, 0x12, 0x81, 0xCC, 0x63, 0x00, 0x12, 0x12, 0xE6, 0xE6, 0xE9, 0x00, 0x87, 0x25, 0x9F, 0x34, 0x00, 0x1E, 0xCE, 0x27, 0xA6, 0xA7, 0xB0, 0x00, 0x21, 0x87, 0x76, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x87, 0x34, 0x81, 0xD4, 0x47, 0x00, 0x1B, 0xE6, 0x51, 0x9A, 0x9B, 0xA5, 0xC0, 0xC0, 0xC7, 0xCC, 0xCD, 0xD2, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x06, 0xB3, 0xB4, 0xBC, 0x8D, 0x8E, 0x9A, 0x00, 0x87, 0x61, 0x81, 0xEC, 0x2F, 0x00, 0xA5, 0x7F, 0x82, 0x9A, 0x0F, 0x00, 0x90, 0x67, 0x82, 0xAA, 0x73, 0x00, 0x06, 0xBE, 0x53, 0x00, 0x87, 0x19, 0x81, 0x8D, 0x0F, 0x00, 0x57, 0x81, 0xAD, 0x20, 0x00, 0x87, 0x1F, 0x81, 0x85, 0x22, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x51, 0x81, 0xE4, 0x30, 0x00, 0x87, 0x25, 0x82, 0x9A, 0x75, 0x00, 0x45, 0x45, 0x00, 0x87, 0x1F, 0x81, 0xBC, 0x2F, 0x00, 0x51, 0x51, 0x00, 0x09, 0x81, 0xA4, 0x65, 0x00, 0x87, 0x67, 0xE6, 0x00, 0x00, 0x87, 0x22, 0x81, 0xC4, 0x22, 0x00, 0x5A, 0x81, 0xA5, 0x2D, 0x00, 0x87, 0x6A, 0x8F, 0x63, 0x00, 0x09, 0x82, 0xA3, 0x33, 0x00, 0x87, 0x4C, 0x81, 0x85, 0x3D, 0x00, 0x27, 0x81, 0xBD, 0x03, 0x00, 0x87, 0x19, 0x82, 0xB2, 0x4B, 0x00, 0x51, 0x82, 0xD2, 0x50, 0x00, 0x09, 0x81, 0xD4, 0x0E, 0x00, 0x21, 0x82, 0x93, 0x5F, 0x00, 0x87, 0x4C, 0xD6, 0x5F, 0x00, 0x09, 0x81, 0x9D, 0x1C, 0xA6, 0xA7, 0xB0, 0x67, 0x68, 0x78, 0x00, 0x87, 0x4F, 0x97, 0x62, 0x00, 0x0C, 0x81, 0x9D, 0x19, 0x00, 0x06, 0x06, 0x00, 0x15, 0x81, 0xA5, 0x27, 0xE6, 0xE6, 0xE9, 0x00, 0x12, 0x2A, 0x00, 0x12, 0x12, 0x00, 0x0C, 0x0C, 0x00, 0x87, 0x1C, 0xCE, 0x60, 0x00, 0x2A, 0x81, 0xB4, 0x7E, 0x00, 0x2A, 0x2A, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x87, 0x19, 0xE6, 0x33, 0x67, 0x68, 0x78, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x2A, 0x2A, 0x00, 0xBE, 0x41, 0x81, 0xB5, 0x2E, 0x00, 0x9F, 0x46, 0x9F, 0x46, 0x41, 0x43, 0x56, 0x00, 0x06, 0xDE, 0x10, 0x00, 0x87, 0x5E, 0x82, 0x93, 0x44, 0x00, 0x06, 0x82, 0xA3, 0x33, 0x00, 0x0F, 0x82, 0xB2, 0x75, 0x00, 0x87, 0x55, 0x83, 0xFF, 0x70, 0x4D, 0x4F, 0x62, 0x00, 0x0C, 0x82, 0xC2, 0x46, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x87, 0x34, 0xEE, 0x14, 0x00, 0x0C, 0x82, 0xD2, 0x1D, 0x00, 0x09, 0x81, 0xA5, 0x42, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x88, 0x02, 0x00, 0x21, 0x83, 0xF0, 0x10, 0x00, 0x87, 0x2E, 0x82, 0xBB, 0x09, 0x00, 0x09, 0x83, 0x81, 0x7C, 0x00, 0x06, 0x81, 0x95, 0x41, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x81, 0x9D, 0x3D, 0x00, 0x27, 0x83, 0xFF, 0x70, 0x00, 0x87, 0x2B, 0x84, 0x87, 0x63, 0x00, 0x0C, 0x87, 0x6D, 0x00, 0x12, 0x81, 0xEC, 0x2F, 0x00, 0x21, 0x82, 0xF2, 0x10, 0x00, 0x09, 0x84, 0x80, 0x2F, 0x00, 0x1B, 0x82, 0xF2, 0x55, 0x00, 0x87, 0x13, 0x97, 0x47, 0x00, 0x18, 0x8F, 0x21, 0x00, 0x2D, 0x83, 0x81, 0x70, 0x00, 0x87, 0x1F, 0x82, 0x84, 0x3E, 0x00, 0x09, 0x81, 0xDC, 0x43, 0x00, 0x1B, 0x97, 0x0E, 0x00, 0x2D, 0x83, 0x91, 0x50, 0x00, 0x87, 0x1F, 0x81, 0xEC, 0x6E, 0x00, 0x09, 0x97, 0x4A, 0x00, 0x1B, 0x8F, 0x18, 0x00, 0x30, 0x83, 0xA1, 0x30, 0x00, 0x87, 0x19, 0xAF, 0x2C, 0x00, 0x27, 0x84, 0x8F, 0x05, 0x00, 0x30, 0x83, 0xB1, 0x10, 0x00, 0x1B, 0x84, 0x88, 0x2B, 0x00, 0x87, 0x07, 0x81, 0xFC, 0x00, 0x00, 0x1E, 0x8F, 0x12, 0x00, 0x30, 0x83, 0xC0, 0x70, 0x00, 0x87, 0x19, 0xA7, 0x36, 0x00, 0x27, 0x82, 0x8B, 0x60, 0x00, 0x87, 0x37, 0x83, 0xD0, 0x50, 0x00, 0x12, 0x8F, 0x45, 0x00, 0x27, 0x96, 0x7F, 0x00, 0x87, 0x34, 0x83, 0xE0, 0x30, 0x00, 0x06, 0x83, 0x99, 0x22, 0x00, 0x15, 0xC6, 0x28, 0x00, 0x21, 0xB6, 0x42, 0x00, 0x87, 0x31, 0x83, 0xF0, 0x10, 0x00, 0x09, 0x83, 0x99, 0x1C, 0x00, 0x87, 0x67, 0x83, 0xFF, 0x70, 0x00, 0x06, 0x82, 0x93, 0x35, 0x00, 0x0F, 0x9F, 0x28, 0x00, 0x5D, 0x83, 0xF8, 0x00, 0x00, 0x86, 0x7B, 0x87, 0x70, 0x00, 0x18, 0x87, 0x04, 0x00, 0x5D, 0x87, 0x70, 0x00, 0x86, 0x78, 0x82, 0x8C, 0x28, 0x00, 0x09, 0xDD, 0x5A, 0x00, 0x12, 0xDE, 0x16, 0x00, 0x54, 0x9F, 0x40, 0x00, 0x63, 0x84, 0xAF, 0x10, 0x4D, 0x4F, 0x62, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x83, 0xD9, 0x77, 0x00, 0x09, 0x89, 0x2A, 0x00, 0x86, 0x06, 0xD7, 0x45, 0x00, 0x09, 0x83, 0xC0, 0x46, 0x00, 0x18, 0x87, 0x2B, 0x00, 0x51, 0xAF, 0x20, 0x00, 0x06, 0x87, 0x07, 0x00, 0x5A, 0xBF, 0x00, 0x00, 0x09, 0x81, 0x52, 0x00, 0x06, 0xA1, 0x0F, 0x00, 0x06, 0x87, 0x70, 0x00, 0x06, 0x89, 0x39, 0x00, 0x86, 0x00, 0xC7, 0x65, 0x41, 0x43, 0x56, 0x00, 0x21, 0x83, 0xE7, 0x7C, 0x00, 0x27, 0xC6, 0x1F, 0x00, 0x30, 0x84, 0xCE, 0x50, 0x00, 0x57, 0x86, 0x7B, 0x00, 0x06, 0xDF, 0x23, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0xB7, 0x6D, 0x00, 0x0C, 0x8F, 0x60, 0x00, 0x06, 0x81, 0x22, 0x00, 0x85, 0x7D, 0x98, 0x45, 0x00, 0x09, 0x96, 0x5B, 0x00, 0x1B, 0x81, 0x85, 0x07, 0x00, 0x09, 0xCE, 0x60, 0x00, 0x1E, 0x86, 0x2A, 0x00, 0x30, 0x84, 0xDE, 0x30, 0x00, 0x57, 0x81, 0x85, 0x79, 0x00, 0x06, 0x99, 0x1C, 0x00, 0x09, 0xBF, 0x5A, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x06, 0x84, 0x91, 0x1C, 0x00, 0x85, 0x7D, 0x82, 0xE3, 0x79, 0x00, 0x06, 0x81, 0x8D, 0x15, 0x00, 0x1E, 0x82, 0xCA, 0x39, 0x00, 0x09, 0x8F, 0x12, 0x00, 0x1E, 0x27, 0x00, 0x2D, 0x84, 0xEE, 0x10, 0x00, 0x5A, 0xEE, 0x20, 0xB3, 0xB4, 0xBC, 0x00, 0x0C, 0x91, 0x0B, 0x00, 0x0F, 0xA8, 0x6A, 0x00, 0x84, 0x46, 0x82, 0x9C, 0x38, 0x41, 0x43, 0x56, 0xA6, 0xA7, 0xB0, 0x00, 0x81, 0x34, 0x82, 0xA9, 0x27, 0xCC, 0xCD, 0xD2, 0x00, 0x24, 0x82, 0xC2, 0x43, 0x00, 0x24, 0x84, 0xFD, 0x28, 0x00, 0x2D, 0x84, 0xFD, 0x70, 0x00, 0x5A, 0xA6, 0x3B, 0x00, 0x0F, 0x87, 0x52, 0x00, 0x84, 0x52, 0x87, 0x70, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0xA4, 0x1E, 0x00, 0x81, 0x34, 0x82, 0xF0, 0x32, 0xCC, 0xCD, 0xD2, 0x00, 0x24, 0xD5, 0x55, 0x00, 0x09, 0x8F, 0x63, 0x00, 0x1B, 0x83, 0xFF, 0x2B, 0x00, 0x21, 0x87, 0x70, 0x00, 0x09, 0xB7, 0x07, 0x00, 0x5D, 0xE6, 0x2A, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0x90, 0x3D, 0x00, 0x0F, 0x87, 0x70, 0xF2, 0xF2, 0xF4, 0x00, 0x84, 0x3D, 0xA7, 0x33, 0x00, 0x0C, 0x85, 0x8B, 0x66, 0x00, 0x81, 0x34, 0xC4, 0x41, 0x00, 0x2A, 0x81, 0x31, 0x00, 0x0C, 0x87, 0x2E, 0x00, 0x15, 0x9F, 0x49, 0x00, 0x1E, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xA5, 0x66, 0x00, 0x5D, 0xDE, 0x37, 0x00, 0x06, 0x82, 0xCC, 0x08, 0x00, 0x09, 0xA0, 0x1D, 0x00, 0x0C, 0x83, 0x15, 0x00, 0x06, 0x81, 0x04, 0x00, 0x83, 0x3F, 0xC7, 0x65, 0x4D, 0x4F, 0x62, 0x9A, 0x9B, 0xA5, 0x9A, 0x9B, 0xA5, 0x00, 0x06, 0x83, 0xED, 0x16, 0x00, 0x7B, 0xF4, 0x2F, 0x00, 0x81, 0x61, 0x81, 0xBA, 0x7E, 0x00, 0x09, 0xA7, 0x5D, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0xA6, 0x6E, 0x00, 0x18, 0x87, 0x70, 0x41, 0x43, 0x56, 0x00, 0x09, 0x39, 0x00, 0x66, 0x81, 0x95, 0x4A, 0xD9, 0xD9, 0xDD, 0x00, 0x09, 0x81, 0x22, 0x00, 0x09, 0x87, 0x61, 0x00, 0x06, 0x93, 0x07, 0x00, 0x83, 0x42, 0x97, 0x4D, 0x00, 0x0C, 0x8E, 0x62, 0x00, 0x75, 0xAA, 0x7B, 0x00, 0x0C, 0x85, 0x93, 0x5C, 0x00, 0x81, 0x5E, 0xB3, 0x6F, 0x41, 0x43, 0x56, 0x00, 0x0C, 0x81, 0xBC, 0x77, 0xCC, 0xCD, 0xD2, 0x00, 0x0C, 0x87, 0x76, 0x00, 0x12, 0x87, 0x70, 0x41, 0x43, 0x56, 0x00, 0x0F, 0x83, 0xF0, 0x3A, 0x00, 0x66, 0xC5, 0x72, 0x4D, 0x4F, 0x62, 0x00, 0x06, 0xB8, 0x44, 0x00, 0x09, 0xBF, 0x06, 0x00, 0x09, 0x09, 0x00, 0x83, 0x42, 0x82, 0xCC, 0x0B, 0x00, 0x81, 0x01, 0x87, 0x70, 0x00, 0x0F, 0x81, 0xAB, 0x39, 0x00, 0x81, 0x61, 0x82, 0xD8, 0x59, 0x00, 0x0C, 0x91, 0x50, 0x00, 0x06, 0x86, 0x54, 0xCC, 0xCD, 0xD2, 0x9A, 0x9B, 0xA5, 0x00, 0x06, 0x88, 0x0B, 0xE6, 0xE6, 0xE9, 0x9A, 0x9B, 0xA5, 0xA6, 0xA7, 0xB0, 0x00, 0x0F, 0x81, 0xC5, 0x11, 0xF2, 0xF2, 0xF4, 0x00, 0x6C, 0xCD, 0x5F, 0x00, 0x06, 0x88, 0x6B, 0x00, 0x0C, 0x84, 0x91, 0x01, 0x00, 0x83, 0x48, 0x83, 0xF1, 0x17, 0x00, 0x81, 0x04, 0x87, 0x70, 0x00, 0x09, 0x82, 0xE8, 0x3C, 0x00, 0x81, 0x67, 0x83, 0x97, 0x68, 0x67, 0x68, 0x78, 0x00, 0x0F, 0x81, 0xD4, 0x47, 0x00, 0x1E, 0x82, 0xC2, 0x58, 0xC0, 0xC0, 0xC7, 0x00, 0x84, 0x49, 0xC5, 0x66, 0x00, 0x81, 0x04, 0x87, 0x70, 0x00, 0x0C, 0x82, 0xC9, 0x05, 0x00, 0x81, 0x6A, 0x81, 0xAA, 0x7A, 0x73, 0x75, 0x83, 0x00, 0x0C, 0x9F, 0x19, 0x00, 0x12, 0x87, 0x67, 0xF2, 0xF2, 0xF4, 0xB3, 0xB4, 0xBC, 0x00, 0x72, 0x81, 0x85, 0x55, 0x00, 0x18, 0x82, 0xC3, 0x4D, 0x73, 0x75, 0x83, 0x00, 0x83, 0x42, 0xEF, 0x12, 0x00, 0x81, 0x10, 0x87, 0x70, 0x00, 0x81, 0x73, 0x81, 0x93, 0x27, 0x00, 0x06, 0x81, 0xEC, 0x1A, 0x00, 0x09, 0xAA, 0x36, 0x9A, 0x9B, 0xA5, 0x80, 0x81, 0x8F, 0x00, 0x78, 0x81, 0x8D, 0x3C, 0x00, 0x06, 0xA2, 0x4F, 0xCC, 0xCD, 0xD2, 0x00, 0x0F, 0x97, 0x3E, 0x00, 0x06, 0xA0, 0x7D, 0x00, 0x83, 0x42, 0x84, 0xB7, 0x7B, 0x00, 0x81, 0x07, 0x87, 0x70, 0x00, 0x0C, 0x9D, 0x2F, 0x00, 0x83, 0x03, 0xEF, 0x6C, 0x00, 0x15, 0x88, 0x6E, 0x00, 0x06, 0xCF, 0x5E, 0x00, 0x83, 0x3F, 0xEE, 0x26, 0x00, 0x84, 0x10, 0x87, 0x70, 0xC0, 0xC0, 0xC7, 0x00, 0x1B, 0xC7, 0x50, 0x00, 0x06, 0x81, 0xE5, 0x5B, 0x00, 0x86, 0x3F, 0x97, 0x50, 0x00, 0x81, 0x13, 0x82, 0xFB, 0x2E, 0x00, 0x27, 0xD6, 0x6E, 0x00, 0x84, 0x37, 0x87, 0x70, 0x00, 0x09, 0x84, 0xFC, 0x15, 0x00, 0x83, 0x03, 0x87, 0x70, 0x00, 0x06, 0x81, 0x85, 0x67, 0x00, 0x1B, 0xFE, 0x7B, 0x00, 0x84, 0x43, 0x8F, 0x60, 0x00, 0x0C, 0xB7, 0x10, 0x00, 0x21, 0x85, 0xBB, 0x18, 0x00, 0x82, 0x65, 0x9F, 0x40, 0x00, 0x15, 0xAF, 0x08, 0x00, 0x06, 0x1B, 0x00, 0x84, 0x43, 0x9F, 0x40, 0x00, 0x0C, 0xC6, 0x70, 0x00, 0x83, 0x03, 0x94, 0x2F, 0xE6, 0xE6, 0xE9, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0x81, 0x9F, 0x09, 0xF2, 0xF2, 0xF4, 0x00, 0x83, 0x42, 0x81, 0xE5, 0x28, 0x00, 0x81, 0x01, 0x87, 0x70, 0x00, 0x09, 0xFB, 0x54, 0x00, 0x83, 0x09, 0x83, 0xE6, 0x48, 0x00, 0x0C, 0x81, 0x95, 0x50, 0x00, 0x06, 0xB8, 0x20, 0x00, 0x09, 0xD6, 0x5F, 0x00, 0x83, 0x42, 0x81, 0xC5, 0x62, 0x00, 0x7E, 0x87, 0x70, 0x00, 0x12, 0x84, 0xD4, 0x50, 0x00, 0x83, 0x06, 0x84, 0x52, 0x00, 0x06, 0x81, 0xA5, 0x30, 0x00, 0x0F, 0x84, 0xD7, 0x3E, 0x00, 0x83, 0x45, 0xCF, 0x64, 0x00, 0x7B, 0x87, 0x70, 0x00, 0x09, 0xE3, 0x18, 0x00, 0x83, 0x18, 0x82, 0xA9, 0x1E, 0x00, 0x09, 0x82, 0xB4, 0x29, 0x00, 0x83, 0x4B, 0x83, 0xB2, 0x32, 0x00, 0x75, 0x87, 0x70, 0x5A, 0x5C, 0x6D, 0x00, 0x0F, 0x8C, 0x3F, 0x00, 0x86, 0x4B, 0x81, 0xC2, 0x41, 0x00, 0x06, 0xEA, 0x6D, 0x00, 0x18, 0x83, 0xB5, 0x44, 0x00, 0x0C, 0x8E, 0x62, 0x00, 0x33, 0x83, 0xB6, 0x03, 0x00, 0x30, 0x30, 0x00, 0x18, 0x82, 0xB1, 0x08, 0x00, 0x83, 0x09, 0x81, 0xB1, 0x6C, 0x00, 0x06, 0x84, 0xD7, 0x4A, 0x00, 0x83, 0x42, 0x81, 0xA2, 0x54, 0x00, 0x5A, 0x83, 0xAE, 0x16, 0x00, 0x45, 0x45, 0x00, 0x81, 0x73, 0xBB, 0x56, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0xDE, 0x37, 0x00, 0x06, 0x82, 0xB3, 0x10, 0x00, 0x81, 0x04, 0x83, 0xC0, 0x70, 0x00, 0x06, 0xB6, 0x75, 0x00, 0x83, 0x3C, 0x9F, 0x2B, 0x00, 0x81, 0x22, 0x87, 0x70, 0x00, 0x81, 0x6D, 0x8F, 0x5A, 0x00, 0x06, 0xA6, 0x0B, 0x00, 0x2D, 0x84, 0xF6, 0x00, 0x00, 0x6F, 0x83, 0xB9, 0x00, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x84, 0xFE, 0x77, 0x00, 0x84, 0x52, 0x87, 0x70, 0x00, 0x81, 0x70, 0x84, 0x58, 0x00, 0x09, 0x81, 0x9D, 0x46, 0x00, 0x81, 0x19, 0x83, 0xC0, 0x70, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x9B, 0x63, 0x00, 0x15, 0x9B, 0x60, 0x00, 0x83, 0x21, 0xC6, 0x70, 0x00, 0x81, 0x13, 0x87, 0x70, 0xCC, 0xCD, 0xD2, 0xA6, 0xA7, 0xB0, 0x00, 0x81, 0x70, 0xB6, 0x7B, 0x00, 0x0F, 0xA9, 0x23, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0x85, 0x8D, 0x4D, 0x00, 0x06, 0x81, 0xA0, 0x3A, 0x00, 0x81, 0x07, 0x83, 0xC0, 0x70, 0x00, 0x21, 0x89, 0x12, 0x00, 0x83, 0x3F, 0x81, 0xC4, 0x70, 0x00, 0x81, 0x07, 0xE6, 0x30, 0x00, 0x81, 0x6D, 0x87, 0x6D, 0xD9, 0xD9, 0xDD, 0x00, 0x84, 0x79, 0x82, 0xD2, 0x17, 0x00, 0x82, 0x65, 0x87, 0x70, 0x00, 0x0C, 0xE0, 0x21, 0x00, 0x84, 0x7F, 0x81, 0xE2, 0x73, 0x00, 0x82, 0x65, 0x87, 0x70, 0x00, 0x06, 0x81, 0xE4, 0x54, 0x00, 0x85, 0x05, 0x81, 0xEA, 0x60, 0x00, 0x82, 0x62, 0x87, 0x70, 0x00, 0x09, 0x81, 0xFC, 0x1E, 0x00, 0x81, 0x25, 0xBD, 0x58, 0x00, 0x86, 0x42, 0x9F, 0x40, 0x00, 0x09, 0x81, 0xA5, 0x15, 0x00, 0x81, 0x25, 0xB1, 0x0A, 0x80, 0x81, 0x8F, 0x00, 0x15, 0xBF, 0x6C, 0x00, 0x09, 0xE6, 0x42, 0x00, 0x84, 0x46, 0x81, 0x95, 0x50, 0x00, 0x81, 0x5B, 0x82, 0x62, 0x00, 0x81, 0x46, 0x82, 0xD9, 0x72, 0x41, 0x43, 0x56, 0x00, 0x0F, 0x81, 0xEC, 0x3B, 0x00, 0x86, 0x15, 0x87, 0x70, 0x00, 0x81, 0x4C, 0x84, 0xBE, 0x6D, 0x00, 0x06, 0x81, 0xAD, 0x3B, 0x00, 0x86, 0x1E, 0x8F, 0x60, 0x00, 0x81, 0x4F, 0x84, 0xE6, 0x20, 0xCC, 0xCD, 0xD2, 0x00, 0x83, 0x3F, 0x84, 0xDF, 0x79, 0x00, 0x82, 0x68, 0x87, 0x70, 0x00, 0x81, 0x46, 0xD0, 0x47, 0x00, 0x06, 0xCE, 0x72, 0x00, 0x83, 0x45, 0x83, 0xAE, 0x0D, 0x67, 0x68, 0x78, 0x00, 0x82, 0x53, 0xE2, 0x26, 0x00, 0x81, 0x4C, 0x87, 0x70, 0x00, 0x06, 0xC8, 0x33, 0x00, 0x86, 0x1E, 0x84, 0xB8, 0x3A, 0x00, 0x81, 0x31, 0x87, 0x70, 0x00, 0x18, 0xAF, 0x20, 0x00, 0x09, 0x82, 0xAC, 0x15, 0x00, 0x86, 0x1E, 0x84, 0xB8, 0x2E, 0x00, 0x09, 0x82, 0x8B, 0x5A, 0x00, 0x81, 0x28, 0x8E, 0x17, 0x00, 0x18, 0xBF, 0x00, 0x00, 0x06, 0x84, 0xC0, 0x1E, 0x00, 0x86, 0x24, 0x84, 0xC0, 0x1B, 0x00, 0x87, 0x1F, 0x83, 0x81, 0x1F, 0x00, 0x57, 0xF1, 0x20, 0x00, 0x87, 0x25, 0x83, 0xA8, 0x55, 0x00, 0x4E, 0x83, 0xA9, 0x1A, 0x00, 0x81, 0x31, 0xAA, 0x0F, 0x00, 0x06, 0x86, 0x84, 0x67, 0x00, 0x78, 0x82, 0x97, 0x69, 0x00, 0x30, 0xC1, 0x68, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0x81, 0xDD, 0x7D, 0x00, 0x0F, 0xFA, 0x77, 0x80, 0x81, 0x8F, 0x00, 0x84, 0x6D, 0x82, 0xC4, 0x24, 0x00, 0x09, 0xC6, 0x73, 0x00, 0x81, 0x2B, 0xB9, 0x6F, 0x73, 0x75, 0x83, 0x00, 0x09, 0xE7, 0x64, 0x00, 0x81, 0x1F, 0x86, 0x84, 0x64, 0x73, 0x75, 0x83, 0x00, 0x24, 0x82, 0x86, 0x3D, 0xE6, 0xE6, 0xE9, 0xC0, 0xC0, 0xC7, 0x8D, 0x8E, 0x9A, 0x00, 0x84, 0x64, 0x81, 0xAA, 0x14, 0x00, 0x06, 0xB5, 0x4A, 0x00, 0x1B, 0x82, 0xD2, 0x74, 0x00, 0x81, 0x13, 0xE7, 0x61, 0x00, 0x06, 0x82, 0xB2, 0x7B, 0x00, 0x06, 0xBB, 0x29, 0x00, 0x09, 0x86, 0x85, 0x0B, 0x00, 0x81, 0x0D, 0x87, 0x73, 0x00, 0x0F, 0x82, 0x9E, 0x10, 0x00, 0x30, 0x81, 0x8A, 0x72, 0x9A, 0x9B, 0xA5, 0x73, 0x75, 0x83, 0x00, 0x84, 0x55, 0xA9, 0x02, 0x00, 0x09, 0x85, 0x85, 0x60, 0x00, 0x81, 0x22, 0xB5, 0x50, 0x00, 0x09, 0x82, 0xDA, 0x40, 0x00, 0x12, 0x82, 0x83, 0x70, 0x00, 0x06, 0x82, 0xA3, 0x39, 0x00, 0x81, 0x07, 0x81, 0x40, 0x00, 0x09, 0x81, 0xCE, 0x05, 0x00, 0x42, 0x81, 0x92, 0x6E, 0x00, 0x06, 0x81, 0xE6, 0x05, 0x00, 0x7B, 0x82, 0x86, 0x64, 0x00, 0x83, 0x5D, 0x82, 0xF2, 0x34, 0x00, 0x81, 0x1F, 0x87, 0x73, 0x00, 0x1B, 0x81, 0xE4, 0x30, 0x00, 0x06, 0xC0, 0x4C, 0x00, 0x81, 0x04, 0xDE, 0x40, 0x00, 0x09, 0x82, 0x4D, 0x00, 0x4E, 0x81, 0x9A, 0x67, 0xFE, 0xFE, 0xFF, 0xF0, 0xF1, 0xF3, 0xC9, 0xCB, 0xD1, 0x97, 0x99, 0xA4, 0x65, 0x67, 0x77, 0x00, 0x84, 0x4C, 0x87, 0x73, 0x00, 0x81, 0x19, 0x9C, 0x46, 0x00, 0x81, 0x1F, 0x81, 0xF4, 0x10, 0x00, 0x06, 0xEF, 0x27, 0x00, 0x57, 0x81, 0xA2, 0x57, 0xFE, 0xFE, 0xFF, 0xFD, 0xFE, 0xFE, 0xFB, 0xFD, 0xFE, 0xFA, 0xFC, 0xFD, 0xF9, 0xFB, 0xFD, 0xF7, 0xFA, 0xFC, 0xD1, 0xD4, 0xDA, 0xA0, 0xA3, 0xAE, 0x7C, 0x7E, 0x8D, 0x4C, 0x4E, 0x61, 0x00, 0x84, 0x37, 0x85, 0x95, 0x46, 0x00, 0x09, 0x95, 0x06, 0xC0, 0xC0, 0xC7, 0x00, 0x81, 0x13, 0xA6, 0x02, 0x00, 0x81, 0x1C, 0x82, 0x83, 0x70, 0x00, 0x12, 0x81, 0xD9, 0x01, 0x00, 0x60, 0x87, 0x70, 0xF6, 0xF9, 0xFC, 0xF4, 0xF8, 0xFB, 0xF3, 0xF7, 0xFA, 0xF1, 0xF6, 0xFA, 0xD8, 0xDD, 0xE3, 0xB4, 0xB9, 0xC3, 0x85, 0x89, 0x97, 0x62, 0x65, 0x76, 0x00, 0x81, 0x73, 0x81, 0xC2, 0x29, 0x00, 0x09, 0x83, 0xF5, 0x33, 0x00, 0x15, 0x81, 0xB4, 0x66, 0x00, 0x06, 0xA2, 0x10, 0x00, 0x81, 0x5E, 0xAA, 0x0C, 0x80, 0x81, 0x8F, 0x00, 0x0C, 0x82, 0xA2, 0x65, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x06, 0x82, 0xBA, 0x5C, 0x00, 0x0F, 0x9C, 0x79, 0x00, 0x06, 0x86, 0x45, 0xA6, 0xA7, 0xB0, 0x00, 0x30, 0x4B, 0x00, 0x75, 0x8F, 0x60, 0x00, 0x78, 0xEE, 0x20, 0x00, 0x06, 0x81, 0xF5, 0x11, 0x00, 0x5D, 0x81, 0xB2, 0x37, 0x00, 0x1E, 0x87, 0x70, 0xF0, 0xF5, 0xF9, 0xEF, 0xF4, 0xF9, 0xED, 0xF3, 0xF8, 0xEC, 0xF3, 0xF8, 0xEA, 0xF2, 0xF7, 0xBC, 0xC2, 0xCC, 0x8E, 0x93, 0xA1, 0x6C, 0x70, 0x80, 0x3F, 0x42, 0x00, 0x81, 0x56, 0xA7, 0x72, 0x00, 0x06, 0x82, 0xD2, 0x7A, 0x00, 0x0F, 0xB3, 0x27, 0x00, 0x27, 0x81, 0xCC, 0x3C, 0x00, 0x81, 0x55, 0x81, 0xAB, 0x0F, 0x00, 0x81, 0x01, 0x81, 0xB7, 0x69, 0x00, 0x75, 0x9F, 0x40, 0x00, 0x75, 0xD8, 0x19, 0x00, 0x4E, 0x81, 0xBF, 0x38, 0x00, 0x45, 0x87, 0x70, 0xE9, 0xF1, 0xF7, 0xE7, 0xF0, 0xF6, 0xE6, 0xEF, 0xF6, 0xE5, 0xEE, 0xF5, 0xCD, 0xD6, 0xDF, 0xA1, 0xA8, 0xB5, 0x7F, 0x85, 0x95, 0x54, 0x58, 0x6B, 0x00, 0x81, 0x55, 0x81, 0xF0, 0x1E, 0x00, 0x36, 0xAA, 0x06, 0x00, 0x81, 0x4F, 0x81, 0x82, 0x2B, 0x00, 0x81, 0x55, 0x87, 0x70, 0x00, 0x81, 0x10, 0xAF, 0x20, 0x00, 0x0F, 0x82, 0xDC, 0x3F, 0x00, 0x81, 0x16, 0x87, 0x70, 0xE3, 0xED, 0xF5, 0xE2, 0xEC, 0xF4, 0xE0, 0xEB, 0xF3, 0xDF, 0xEA, 0xF3, 0xD3, 0xDE, 0xE8, 0xB2, 0xBC, 0xC8, 0x87, 0x8F, 0x9E, 0x5D, 0x62, 0x75, 0x3E, 0x41, 0x55, 0x00, 0x81, 0x31, 0xF6, 0x2E, 0x00, 0x4E, 0x8A, 0x5B, 0x00, 0x09, 0x83, 0x8E, 0x29, 0x00, 0x81, 0x79, 0x97, 0x50, 0x00, 0x33, 0x33, 0x00, 0x6C, 0x97, 0x50, 0x00, 0x1E, 0xBF, 0x00, 0x00, 0x6F, 0x8B, 0x32, 0x5A, 0x5C, 0x6D, 0x00, 0x5D, 0x9F, 0x31, 0x00, 0x54, 0x87, 0x70, 0xDE, 0xE9, 0xF2, 0xDC, 0xE8, 0xF2, 0xDB, 0xE8, 0xF1, 0xD9, 0xE7, 0xF1, 0xD8, 0xE6, 0xF0, 0xB8, 0xC4, 0xD1, 0x8F, 0x98, 0xA7, 0x70, 0x77, 0x89, 0x48, 0x4C, 0x5F, 0x00, 0x81, 0x22, 0x9F, 0x28, 0x00, 0x21, 0x82, 0x6E, 0x00, 0x06, 0x82, 0xBF, 0x1C, 0x00, 0x18, 0x81, 0xEC, 0x71, 0x00, 0x83, 0x39, 0x81, 0xA9, 0x64, 0x00, 0x81, 0x04, 0xCE, 0x60, 0x00, 0x09, 0x85, 0xB7, 0x2F, 0x00, 0x81, 0x3D, 0x87, 0x70, 0xD7, 0xE5, 0xF0, 0xD5, 0xE4, 0xEF, 0xD4, 0xE3, 0xEF, 0xD2, 0xE2, 0xEE, 0xAA, 0xB7, 0xC5, 0x5B, 0x61, 0x74, 0x00, 0x81, 0x1F, 0x85, 0xBA, 0x1D, 0x00, 0x18, 0xF2, 0x1B, 0x00, 0x1E, 0x82, 0x80, 0x07, 0x00, 0x06, 0xA7, 0x54, 0x00, 0x1B, 0x93, 0x0A, 0xC0, 0xC0, 0xC7, 0x00, 0x83, 0x21, 0xC9, 0x5B, 0x00, 0x09, 0xDE, 0x40, 0x00, 0x72, 0xA2, 0x7F, 0x00, 0x0F, 0x82, 0xE4, 0x56, 0x00, 0x81, 0x46, 0x87, 0x70, 0xD1, 0xE1, 0xEE, 0xD0, 0xE0, 0xED, 0xA8, 0xB5, 0xC4, 0x00, 0x81, 0x10, 0x97, 0x68, 0x00, 0x18, 0xC1, 0x50, 0xB3, 0xB4, 0xBC, 0x00, 0x30, 0xAE, 0x73, 0x00, 0x12, 0x82, 0xEF, 0x55, 0x00, 0x0C, 0x97, 0x5C, 0x00, 0x84, 0x13, 0xD1, 0x4E, 0x00, 0x3C, 0xD6, 0x26, 0x00, 0x81, 0x22, 0x87, 0x70, 0xCB, 0xDD, 0xEC, 0xA4, 0xC0, 0xDF, 0x84, 0xA5, 0xCD, 0x44, 0x4C, 0x65, 0x00, 0x81, 0x1C, 0x87, 0x6D, 0x00, 0x27, 0x83, 0x8F, 0x39, 0x00, 0x30, 0xA0, 0x08, 0x00, 0x83, 0x0C, 0x87, 0x73, 0x4D, 0x4F, 0x62, 0x00, 0x12, 0x83, 0x63, 0x00, 0x06, 0x83, 0x9C, 0x5B, 0x00, 0x06, 0x81, 0xA5, 0x27, 0x00, 0x63, 0x8F, 0x66, 0x00, 0x4B, 0xD6, 0x26, 0x00, 0x81, 0x13, 0x87, 0x70, 0xB7, 0xCE, 0xE5, 0x8E, 0xB1, 0xD7, 0x89, 0xAD, 0xD6, 0x89, 0xAC, 0xD5, 0x83, 0xA3, 0xCC, 0x56, 0x61, 0x79, 0x00, 0x81, 0x10, 0x83, 0x90, 0x61, 0x00, 0x4E, 0x81, 0x8B, 0x1C, 0x00, 0x15, 0xA0, 0x11, 0x00, 0x83, 0x06, 0x81, 0xA9, 0x70, 0x00, 0x06, 0x86, 0x69, 0x00, 0x0F, 0x83, 0x0C, 0x00, 0x09, 0xDF, 0x77, 0x00, 0x66, 0x81, 0xDD, 0x7D, 0x00, 0x57, 0xD6, 0x26, 0x00, 0x81, 0x04, 0x87, 0x70, 0xCB, 0xDD, 0xEC, 0x9D, 0xBC, 0xDC, 0x8A, 0xAF, 0xD6, 0x8A, 0xAE, 0xD6, 0x89, 0xAC, 0xD5, 0x88, 0xAB, 0xD5, 0x88, 0xAA, 0xD5, 0x82, 0xA1, 0xCC, 0x43, 0x4B, 0x00, 0x7C, 0x8F, 0x66, 0x00, 0x0F, 0x83, 0x88, 0x6B, 0x00, 0x54, 0x82, 0xAF, 0x03, 0x00, 0x15, 0xB2, 0x5F, 0x00, 0x83, 0x03, 0x81, 0xA2, 0x03, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0x83, 0x6C, 0x00, 0x06, 0x8B, 0x1D, 0x00, 0x06, 0x83, 0x1E, 0x00, 0x09, 0xBB, 0x14, 0x00, 0x57, 0xCA, 0x44, 0x00, 0x5A, 0xD6, 0x26, 0x00, 0x81, 0x01, 0x87, 0x70, 0xBA, 0xD1, 0xE6, 0x90, 0xB3, 0xD8, 0x8B, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x88, 0xAA, 0xD5, 0x87, 0xA9, 0xD4, 0x87, 0xA7, 0xD4, 0x80, 0x9C, 0xC4, 0x00, 0x81, 0x04, 0x81, 0xD1, 0x7A, 0x00, 0x60, 0x84, 0xBB, 0x5B, 0x00, 0x12, 0x83, 0x5D, 0x00, 0x82, 0x7D, 0xE9, 0x1B, 0x00, 0x06, 0x81, 0xED, 0x3F, 0x00, 0x0F, 0xB6, 0x6C, 0x00, 0x06, 0x8E, 0x6E, 0x00, 0x0C, 0xB2, 0x4A, 0x00, 0x06, 0x8C, 0x0F, 0x00, 0x51, 0x8F, 0x63, 0x00, 0x60, 0xD6, 0x26, 0x00, 0x7B, 0x87, 0x70, 0xD3, 0xE3, 0xEF, 0xA3, 0xC2, 0xDF, 0x8C, 0xB1, 0xD7, 0x8B, 0xB0, 0xD6, 0x8A, 0xAE, 0xD6, 0x8A, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x87, 0xA8, 0xD4, 0x86, 0xA7, 0xD4, 0x86, 0xA6, 0xD4, 0x5D, 0x6D, 0x00, 0x76, 0xC5, 0x15, 0x00, 0x0C, 0x81, 0xF1, 0x34, 0x00, 0x63, 0x82, 0xBE, 0x5D, 0x00, 0x0F, 0xA3, 0x14, 0x00, 0x82, 0x7D, 0x81, 0xB9, 0x56, 0x00, 0x06, 0xA2, 0x5B, 0x00, 0x12, 0xD6, 0x3B, 0x00, 0x12, 0xD6, 0x59, 0x00, 0x51, 0xDE, 0x40, 0x00, 0x63, 0xD6, 0x26, 0x00, 0x78, 0x87, 0x70, 0xC6, 0xDA, 0xEB, 0x96, 0xB9, 0xDA, 0x00, 0x05, 0x87, 0x6D, 0xD7, 0x00, 0x0A, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x86, 0xA6, 0xD4, 0x85, 0xA5, 0xD3, 0x80, 0x9D, 0xCB, 0x00, 0x7E, 0x81, 0xF1, 0x34, 0x00, 0x66, 0x83, 0x9E, 0x1B, 0x00, 0x09, 0x83, 0xD6, 0x7A, 0x00, 0x83, 0x03, 0x82, 0xB3, 0x0D, 0x00, 0x06, 0x87, 0x70, 0x00, 0x0C, 0xAA, 0x39, 0x00, 0x12, 0x8F, 0x5D, 0x00, 0x54, 0x87, 0x70, 0x00, 0x12, 0x84, 0xD8, 0x4B, 0x00, 0x81, 0x49, 0x87, 0x70, 0xB4, 0xCE, 0xE5, 0x8D, 0xB3, 0xD7, 0x8C, 0xB2, 0xD7, 0x8C, 0xB1, 0x00, 0x07, 0x87, 0x6D, 0x00, 0x13, 0x8F, 0x5D, 0xA5, 0xD3, 0x85, 0xA4, 0xD3, 0x84, 0xA3, 0xD3, 0x52, 0x5F, 0x7E, 0x00, 0x7E, 0xAF, 0x14, 0x00, 0x66, 0xA6, 0x44, 0x00, 0x0F, 0xA8, 0x1C, 0x00, 0x82, 0x7A, 0x8F, 0x63, 0x00, 0x06, 0x81, 0xB6, 0x35, 0x00, 0x09, 0xA2, 0x46, 0x00, 0x06, 0x8B, 0x0B, 0x00, 0x12, 0xD6, 0x3B, 0x00, 0x06, 0x81, 0x97, 0x19, 0x00, 0x45, 0xCA, 0x2C, 0x00, 0x6C, 0xD6, 0x26, 0x00, 0x6F, 0x87, 0x70, 0xD9, 0xE6, 0xF1, 0xA6, 0xC5, 0xE0, 0x8D, 0xB4, 0xD8, 0x8D, 0xB3, 0x00, 0x05, 0x87, 0x6D, 0x00, 0x09, 0x8F, 0x5D, 0xAC, 0xD5, 0x00, 0x12, 0x8F, 0x5D, 0x84, 0xA3, 0xD3, 0x84, 0xA2, 0xD3, 0x79, 0x93, 0xC1, 0x00, 0x75, 0x84, 0xA4, 0x44, 0x00, 0x21, 0x83, 0xC6, 0x04, 0x00, 0x60, 0xA0, 0x32, 0x00, 0x82, 0x7A, 0x9F, 0x46, 0x00, 0x06, 0x84, 0x01, 0xB3, 0xB4, 0xBC, 0x00, 0x09, 0xEA, 0x13, 0x00, 0x0F, 0xB6, 0x7E, 0x00, 0x09, 0x82, 0xD5, 0x7A, 0x00, 0x42, 0x81, 0x97, 0x13, 0x00, 0x6F, 0xD6, 0x26, 0x00, 0x6C, 0x87, 0x70, 0xD0, 0xE0, 0xEE, 0x9D, 0xBF, 0xDD, 0x00, 0x07, 0x87, 0x6D, 0x00, 0x12, 0x8F, 0x5D, 0xAA, 0xD5, 0x87, 0xA9, 0x00, 0x10, 0x8F, 0x5D, 0x84, 0xA2, 0xD2, 0x83, 0xA0, 0xD2, 0x51, 0x5E, 0x00, 0x6A, 0x8F, 0x63, 0x00, 0x09, 0x81, 0xC2, 0x14, 0x00, 0x72, 0xD5, 0x6D, 0x00, 0x0F, 0x82, 0xE2, 0x2D, 0x00, 0x81, 0x79, 0x82, 0xF6, 0x5C, 0x4D, 0x4F, 0x62, 0x00, 0x0C, 0x82, 0xA3, 0x09, 0x00, 0x72, 0x81, 0x9D, 0x67, 0x00, 0x0C, 0xC5, 0x66, 0x00, 0x15, 0x86, 0x8C, 0x6F, 0x00, 0x06, 0x88, 0x05, 0x00, 0x42, 0x9B, 0x66, 0x00, 0x0C, 0x81, 0x80, 0x02, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xC7, 0xDB, 0xEB, 0x93, 0xB9, 0xDA, 0x8E, 0xB5, 0xD8, 0x00, 0x0B, 0x8F, 0x5D, 0xD6, 0x00, 0x09, 0xB7, 0x04, 0x00, 0x18, 0x8F, 0x5D, 0x83, 0xA1, 0xD2, 0x82, 0xA0, 0xD2, 0x78, 0x91, 0xC0, 0x00, 0x78, 0xD1, 0x3C, 0x00, 0x6F, 0xC6, 0x01, 0x00, 0x0C, 0xAF, 0x2C, 0x00, 0x81, 0x6D, 0x82, 0xF9, 0x7D, 0x41, 0x43, 0x56, 0x80, 0x81, 0x8F, 0x00, 0x1E, 0xD8, 0x73, 0x00, 0x0C, 0x84, 0xEE, 0x31, 0x00, 0x66, 0x8B, 0x7A, 0x00, 0x18, 0xDA, 0x27, 0x80, 0x81, 0x8F, 0x00, 0x42, 0xA2, 0x61, 0x00, 0x75, 0xD6, 0x26, 0x00, 0x66, 0x87, 0x70, 0xBE, 0xD5, 0xE8, 0x8F, 0xB6, 0xD8, 0x00, 0x0A, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x00, 0x0B, 0xB7, 0x04, 0x00, 0x10, 0x8F, 0x5D, 0x83, 0xA1, 0xD2, 0x83, 0xA0, 0xD2, 0x82, 0x9F, 0xD2, 0x81, 0x9E, 0xD1, 0x51, 0x5C, 0x7D, 0x00, 0x72, 0x97, 0x4D, 0x00, 0x72, 0xC5, 0x7E, 0x00, 0x0F, 0xB0, 0x18, 0x00, 0x81, 0x64, 0x97, 0x53, 0x00, 0x1B, 0xD8, 0x64, 0x00, 0x15, 0xE9, 0x12, 0x9A, 0x9B, 0xA5, 0x00, 0x81, 0x40, 0xD1, 0x06, 0x00, 0x7B, 0xD6, 0x26, 0x00, 0x63, 0x87, 0x70, 0xAF, 0xCC, 0xE3, 0x8F, 0xB7, 0xD8, 0x8E, 0x00, 0x06, 0x87, 0x70, 0x00, 0x09, 0x87, 0x6D, 0x00, 0x12, 0x8F, 0x5D, 0x00, 0x08, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x81, 0x9E, 0xD1, 0x81, 0x9D, 0xD1, 0x77, 0x8F, 0x00, 0x64, 0x8F, 0x63, 0x00, 0x0F, 0x83, 0x90, 0x4C, 0x00, 0x75, 0xFD, 0x23, 0x00, 0x0C, 0x85, 0x7A, 0x00, 0x81, 0x61, 0xC6, 0x7C, 0x67, 0x68, 0x78, 0x00, 0x12, 0x81, 0x88, 0x34, 0x00, 0x0F, 0x82, 0xC1, 0x5A, 0x00, 0x12, 0x88, 0x0B, 0xE6, 0xE6, 0xE9, 0x00, 0x81, 0x3A, 0xB1, 0x40, 0x5A, 0x5C, 0x6D, 0x00, 0x33, 0x81, 0x8A, 0x27, 0x00, 0x81, 0x25, 0x87, 0x70, 0xE0, 0xEB, 0xF4, 0xAA, 0xC9, 0xE2, 0x8F, 0xB7, 0xD9, 0x00, 0x2A, 0x8F, 0x5D, 0x85, 0x00, 0x14, 0x8F, 0x5D, 0x81, 0x9C, 0xD1, 0x80, 0x9B, 0xD0, 0x50, 0x5B, 0x00, 0x61, 0x8F, 0x63, 0x00, 0x0F, 0xAE, 0x25, 0x00, 0x75, 0x8C, 0x48, 0x00, 0x0C, 0x95, 0x54, 0x00, 0x81, 0x5E, 0xD6, 0x5F, 0x00, 0x0F, 0xB2, 0x08, 0x00, 0x06, 0x82, 0xC9, 0x2F, 0x00, 0x15, 0x9F, 0x2E, 0x00, 0x06, 0x81, 0xCA, 0x31, 0x00, 0x6F, 0xBA, 0x25, 0x00, 0x81, 0x55, 0xD6, 0x26, 0x00, 0x5A, 0x87, 0x70, 0xE2, 0xEC, 0xF4, 0xA0, 0xC3, 0xDE, 0x8F, 0xB8, 0xD9, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x0C, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x00, 0x0F, 0xC6, 0x61, 0x00, 0x0A, 0x8F, 0x5D, 0x00, 0x09, 0x87, 0x6D, 0x9D, 0xD1, 0x80, 0x9B, 0xD1, 0x7F, 0x9A, 0xD0, 0x75, 0x8C, 0xBF, 0x00, 0x6C, 0x85, 0x92, 0x4F, 0x00, 0x78, 0x81, 0xD9, 0x64, 0x00, 0x0C, 0xE6, 0x4B, 0x00, 0x81, 0x5B, 0x81, 0xDA, 0x68, 0x00, 0x0C, 0x85, 0x7A, 0x00, 0x2A, 0x8F, 0x30, 0x00, 0x0F, 0xFD, 0x0B, 0x00, 0x81, 0x2E, 0x87, 0x73, 0x00, 0x81, 0x04, 0xD6, 0x26, 0x00, 0x57, 0x87, 0x70, 0xE3, 0xED, 0xF5, 0xA0, 0xC3, 0xDE, 0x90, 0xB8, 0xD9, 0x00, 0x10, 0x8F, 0x5D, 0x00, 0x0F, 0xC6, 0x61, 0x00, 0x09, 0x8F, 0x5D, 0x00, 0x08, 0x87, 0x6D, 0x00, 0x10, 0x8F, 0x5D, 0x9D, 0xD1, 0x80, 0x00, 0x05, 0x8F, 0x5D, 0x7F, 0x99, 0xD0, 0x7E, 0x98, 0xD0, 0x46, 0x4E, 0x6C, 0x00, 0x69, 0x86, 0x6C, 0x00, 0x7B, 0x81, 0xA1, 0x0B, 0x00, 0x81, 0x61, 0x83, 0xA9, 0x20, 0x00, 0x0C, 0xB2, 0x05, 0xB3, 0xB4, 0xBC, 0x00, 0x2D, 0x92, 0x48, 0x00, 0x0F, 0x9D, 0x7D, 0x00, 0x81, 0x25, 0xA1, 0x63, 0x00, 0x81, 0x0A, 0xD6, 0x26, 0x00, 0x54, 0x87, 0x70, 0xE4, 0xEE, 0xF5, 0xA1, 0xC4, 0xDF, 0x90, 0xB9, 0xD9, 0x00, 0x19, 0x8F, 0x5D, 0x00, 0x17, 0xD6, 0x3E, 0x00, 0x0C, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x7F, 0x98, 0xD0, 0x7E, 0x97, 0xCF, 0x6B, 0x7E, 0xAE, 0x00, 0x69, 0x96, 0x4C, 0x00, 0x78, 0x81, 0x8C, 0x77, 0x00, 0x0F, 0xB8, 0x11, 0x00, 0x81, 0x5B, 0x84, 0xA7, 0x47, 0x00, 0x3C, 0xB8, 0x74, 0x00, 0x09, 0x8E, 0x2C, 0x00, 0x81, 0x22, 0x92, 0x03, 0x00, 0x81, 0x0D, 0xD6, 0x26, 0x00, 0x51, 0x87, 0x70, 0xE6, 0xEF, 0xF6, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x29, 0x8F, 0x5D, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x09, 0x8F, 0x5D, 0x82, 0xA0, 0xD2, 0x82, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x7E, 0x97, 0xCF, 0x7D, 0x95, 0xCF, 0x00, 0x5D, 0x8F, 0x63, 0x00, 0x0C, 0x8C, 0x39, 0x00, 0x82, 0x59, 0x83, 0xC0, 0x70, 0x00, 0x45, 0x84, 0x8F, 0x0B, 0x00, 0x0C, 0x83, 0x9B, 0x6C, 0x00, 0x81, 0x1C, 0x97, 0x56, 0x00, 0x81, 0x10, 0xD6, 0x26, 0x00, 0x4E, 0x87, 0x70, 0xE7, 0xF0, 0x00, 0x08, 0x87, 0x6D, 0x00, 0x18, 0x8F, 0x5D, 0x00, 0x20, 0xD6, 0x3E, 0x00, 0x0D, 0x8F, 0x5D, 0x9C, 0x00, 0x0D, 0x8F, 0x5D, 0x7D, 0x96, 0xCF, 0x7C, 0x95, 0xCF, 0x6A, 0x7C, 0xAD, 0x00, 0x83, 0x3F, 0x87, 0x70, 0x00, 0x09, 0x8D, 0x6D, 0x00, 0x3F, 0xC6, 0x49, 0x00, 0x09, 0x92, 0x09, 0x00, 0x63, 0x82, 0xBB, 0x4E, 0x00, 0x0F, 0xC8, 0x03, 0x00, 0x24, 0xC8, 0x0C, 0x00, 0x5D, 0x81, 0xCB, 0x7D, 0x00, 0x81, 0x04, 0x87, 0x70, 0xE9, 0xF1, 0xF7, 0x00, 0x09, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x00, 0x08, 0xB7, 0x04, 0x00, 0x26, 0xD6, 0x3E, 0x85, 0xA4, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x12, 0x8F, 0x5D, 0x7D, 0x96, 0xCF, 0x7D, 0x95, 0xCF, 0x7C, 0x94, 0xCE, 0x7B, 0x92, 0xCE, 0x46, 0x4D, 0x00, 0x58, 0x8F, 0x63, 0x00, 0x82, 0x62, 0x87, 0x70, 0x00, 0x09, 0xA7, 0x27, 0x00, 0x45, 0xD0, 0x3E, 0x00, 0x60, 0x84, 0xB7, 0x00, 0x00, 0x21, 0xD5, 0x70, 0x00, 0x18, 0x84, 0x25, 0x00, 0x12, 0x83, 0xAC, 0x6B, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xEA, 0xF1, 0xF7, 0xA2, 0x00, 0x09, 0x87, 0x6D, 0x00, 0x26, 0x8F, 0x5D, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x19, 0x8F, 0x5D, 0x94, 0xCF, 0x7C, 0x93, 0xCE, 0x7B, 0x92, 0xCE, 0x69, 0x7A, 0x00, 0x58, 0x8F, 0x63, 0x00, 0x82, 0x62, 0x87, 0x70, 0x00, 0x09, 0xA2, 0x22, 0x00, 0x45, 0xD6, 0x26, 0x00, 0x27, 0x84, 0xB7, 0x4E, 0x00, 0x42, 0x81, 0xED, 0x4B, 0x00, 0x06, 0xDE, 0x4C, 0x00, 0x12, 0x81, 0xB6, 0x05, 0x00, 0x15, 0xB0, 0x57, 0x00, 0x81, 0x43, 0x87, 0x6D, 0x00, 0x1E, 0x87, 0x70, 0xEB, 0xF2, 0xF8, 0x00, 0x16, 0x87, 0x6D, 0x00, 0x35, 0xD6, 0x3E, 0x00, 0x09, 0x8F, 0x5D, 0x7F, 0x9A, 0x00, 0x13, 0x8F, 0x5D, 0x7B, 0x91, 0xCE, 0x7A, 0x8F, 0xCD, 0x45, 0x4C, 0x00, 0x55, 0x8F, 0x63, 0x00, 0x0C, 0xD1, 0x63, 0x00, 0x78, 0x87, 0x70, 0x00, 0x81, 0x5E, 0xAF, 0x20, 0x00, 0x09, 0x81, 0xF4, 0x0A, 0x00, 0x4E, 0xF9, 0x3A, 0x00, 0x57, 0x97, 0x53, 0x00, 0x06, 0x84, 0x10, 0x00, 0x30, 0xA0, 0x20, 0x00, 0x81, 0x1F, 0xD6, 0x29, 0x00, 0x42, 0x87, 0x70, 0xAF, 0xCC, 0xE3, 0x00, 0x09, 0x87, 0x6D, 0x00, 0x0A, 0x87, 0x70, 0x00, 0x14, 0xC6, 0x61, 0x00, 0x1B, 0xE6, 0x1B, 0x00, 0x11, 0xC6, 0x61, 0x00, 0x0B, 0x8F, 0x5D, 0x95, 0x00, 0x0A, 0x8F, 0x5D, 0x7A, 0x90, 0xCE, 0x79, 0x8F, 0xCD, 0x68, 0x78, 0x00, 0x55, 0x8F, 0x63, 0x00, 0x0C, 0xB7, 0x10, 0x00, 0x78, 0xF5, 0x12, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x81, 0x4F, 0x83, 0xCD, 0x32, 0x00, 0x09, 0xD1, 0x3F, 0x00, 0x4B, 0x81, 0x8C, 0x17, 0x00, 0x5D, 0x85, 0x95, 0x40, 0x00, 0x06, 0x81, 0xC0, 0x42, 0x00, 0x42, 0x81, 0xA1, 0x74, 0x00, 0x81, 0x4C, 0x87, 0x70, 0xB5, 0xD0, 0xE5, 0x00, 0x13, 0x87, 0x6D, 0x00, 0x08, 0x8F, 0x5D, 0x00, 0x36, 0xD6, 0x3E, 0x00, 0x07, 0x87, 0x6D, 0x00, 0x11, 0x8F, 0x5D, 0x7A, 0x00, 0x05, 0x8F, 0x5D, 0x79, 0x8E, 0xCD, 0x78, 0x8D, 0xCD, 0x3D, 0x41, 0x5B, 0x00, 0x81, 0x55, 0x86, 0x6C, 0x00, 0x81, 0x04, 0xC0, 0x04, 0x00, 0x60, 0x89, 0x4B, 0x00, 0x4B, 0xD8, 0x28, 0x00, 0x5D, 0x85, 0x95, 0x40, 0x00, 0x06, 0x81, 0xE8, 0x07, 0x00, 0x81, 0x52, 0x83, 0xAE, 0x01, 0x00, 0x39, 0x87, 0x70, 0xC2, 0xD9, 0xEA, 0x00, 0x0C, 0x87, 0x6D, 0x00, 0x13, 0xB7, 0x04, 0x00, 0x32, 0xE6, 0x1B, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x0B, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x79, 0x8D, 0xCD, 0x78, 0x8C, 0xCC, 0x5E, 0x6B, 0x9C, 0x00, 0x60, 0xF5, 0x12, 0x00, 0x81, 0x01, 0xD6, 0x50, 0x00, 0x81, 0x4F, 0x81, 0xCC, 0x7B, 0x00, 0x54, 0x82, 0xC2, 0x70, 0x00, 0x5D, 0x85, 0x95, 0x40, 0x00, 0x06, 0x81, 0xC8, 0x68, 0x00, 0x2A, 0x84, 0x07, 0x00, 0x0F, 0xC2, 0x3C, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xD0, 0xE1, 0xEF, 0x00, 0x0D, 0x87, 0x6D, 0x00, 0x1B, 0xC6, 0x61, 0x00, 0x32, 0xD6, 0x3E, 0x00, 0x09, 0x8F, 0x5D, 0x7C, 0x95, 0x00, 0x08, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x78, 0x8B, 0xCC, 0x77, 0x8A, 0xCC, 0x3C, 0x40, 0x00, 0x52, 0x8F, 0x63, 0x00, 0x81, 0x01, 0xD3, 0x2F, 0x00, 0x0C, 0xC3, 0x1C, 0x00, 0x81, 0x4F, 0x81, 0x95, 0x56, 0x00, 0x54, 0x87, 0x70, 0x00, 0x60, 0x82, 0xCB, 0x34, 0xCC, 0xCD, 0xD2, 0x00, 0x2A, 0xD0, 0x02, 0x00, 0x81, 0x46, 0x9F, 0x3A, 0x00, 0x15, 0x87, 0x70, 0xE4, 0xEE, 0xF5, 0x96, 0xBD, 0xDB, 0x00, 0x1F, 0x8F, 0x5D, 0x00, 0x18, 0xD6, 0x3E, 0xA8, 0x00, 0x17, 0xD6, 0x3E, 0x9E, 0x00, 0x13, 0xC6, 0x61, 0x00, 0x07, 0x8F, 0x5D, 0x91, 0xCE, 0x7A, 0x90, 0xCD, 0x00, 0x09, 0x8F, 0x5D, 0x77, 0x8B, 0xCC, 0x76, 0x89, 0xCC, 0x5D, 0x69, 0x9B, 0x00, 0x5D, 0xA7, 0x33, 0x00, 0x7E, 0xF6, 0x10, 0x00, 0x81, 0x52, 0xFE, 0x00, 0x00, 0x54, 0x87, 0x1C, 0x00, 0x5D, 0x85, 0x95, 0x40, 0x00, 0x06, 0x82, 0xD2, 0x50, 0x00, 0x15, 0x81, 0xE0, 0x1A, 0x00, 0x15, 0x83, 0xB1, 0x10, 0x00, 0x81, 0x43, 0xAF, 0x17, 0x00, 0x15, 0x87, 0x70, 0xF2, 0xF7, 0xFA, 0x9D, 0xC1, 0xDD, 0x00, 0x2B, 0x8F, 0x5D, 0x00, 0x15, 0xD6, 0x3E, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x19, 0xD6, 0x3E, 0x00, 0x16, 0x8F, 0x5D, 0x00, 0x05, 0x87, 0x6D, 0x77, 0x8A, 0xCC, 0x76, 0x88, 0xCB, 0x75, 0x87, 0xCB, 0x00, 0x51, 0x8F, 0x63, 0x00, 0x0F, 0x93, 0x13, 0x00, 0x6F, 0x81, 0x8A, 0x5D, 0x00, 0x0C, 0x9B, 0x7E, 0x00, 0x81, 0x52, 0x81, 0x8D, 0x60, 0x00, 0x54, 0x82, 0xB3, 0x0D, 0x00, 0x09, 0x87, 0x70, 0x00, 0x54, 0x9A, 0x7D, 0x00, 0x30, 0x83, 0x91, 0x50, 0x00, 0x81, 0x49, 0x87, 0x6D, 0x00, 0x0F, 0x87, 0x70, 0xAA, 0xCA, 0xE2, 0x00, 0x0F, 0x87, 0x6D, 0x00, 0x3C, 0xD6, 0x3E, 0x83, 0x00, 0x1A, 0xD6, 0x3E, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x10, 0x8F, 0x5D, 0xCB, 0x75, 0x88, 0xCB, 0x75, 0x86, 0xCB, 0x5C, 0x67, 0x00, 0x52, 0xFC, 0x22, 0x00, 0x0C, 0x8B, 0x26, 0x00, 0x6C, 0x86, 0x75, 0x00, 0x0F, 0xAB, 0x5B, 0x00, 0x81, 0x55, 0x81, 0x85, 0x6D, 0x00, 0x51, 0x82, 0x56, 0x00, 0x06, 0xA1, 0x6F, 0x00, 0x81, 0x07, 0x92, 0x0C, 0x00, 0x81, 0x55, 0x87, 0x70, 0xC5, 0xDB, 0xEB, 0x00, 0x10, 0x87, 0x6D, 0x00, 0x45, 0xD6, 0x3E, 0x00, 0x1B, 0x8F, 0x5D, 0x00, 0x06, 0xA7, 0x27, 0x00, 0x11, 0x8F, 0x5D, 0x74, 0x85, 0xCA, 0x74, 0x84, 0xCA, 0x00, 0x51, 0x8F, 0x63, 0x00, 0x0F, 0xF9, 0x25, 0x00, 0x69, 0x8F, 0x63, 0x00, 0x0F, 0x84, 0xD4, 0x50, 0x00, 0x81, 0x6A, 0x85, 0xAD, 0x28, 0x00, 0x42, 0xA1, 0x6F, 0x00, 0x81, 0x07, 0xB1, 0x49, 0x00, 0x81, 0x52, 0x87, 0x70, 0xE1, 0xEC, 0xF5, 0x00, 0x12, 0x87, 0x6D, 0x00, 0x06, 0x8F, 0x5D, 0x00, 0x57, 0xD6, 0x3E, 0x00, 0x0D, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x08, 0x8F, 0x5D, 0x74, 0x85, 0xCA, 0x73, 0x84, 0xCA, 0x5B, 0x66, 0x00, 0x5E, 0x8F, 0x63, 0x00, 0x66, 0x86, 0x7B, 0x00, 0x0F, 0x81, 0x95, 0x4A, 0x00, 0x81, 0x58, 0x81, 0xBD, 0x00, 0x00, 0x09, 0x8A, 0x4C, 0x00, 0x45, 0x81, 0x61, 0x00, 0x09, 0x4E, 0x00, 0x60, 0xAA, 0x5A, 0x4D, 0x4F, 0x62, 0x00, 0x06, 0x82, 0x85, 0x51, 0x00, 0x1E, 0x8B, 0x7D, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xF6, 0xF9, 0xFC, 0x97, 0x00, 0x0F, 0xA7, 0x24, 0x00, 0x5C, 0xE6, 0x1B, 0x00, 0x24, 0x8F, 0x5D, 0x73, 0x83, 0xCA, 0x72, 0x81, 0xC9, 0x38, 0x3B, 0x53, 0x00, 0x5D, 0x96, 0x5B, 0x00, 0x60, 0x81, 0x94, 0x58, 0x00, 0x0F, 0x81, 0xE1, 0x0C, 0x00, 0x81, 0x5B, 0x81, 0xAD, 0x1A, 0x00, 0x09, 0x81, 0xDF, 0x16, 0x00, 0x45, 0x8A, 0x46, 0x00, 0x09, 0x84, 0x8E, 0x5B, 0x00, 0x69, 0x81, 0xA9, 0x43, 0x00, 0x06, 0x89, 0x27, 0x00, 0x06, 0x81, 0x95, 0x14, 0x00, 0x12, 0x9A, 0x71, 0x00, 0x81, 0x4F, 0x87, 0x70, 0xAB, 0x00, 0x12, 0x9F, 0x37, 0x00, 0x19, 0xD6, 0x3E, 0xD7, 0x00, 0x4B, 0xD6, 0x3E, 0x00, 0x0C, 0xB7, 0x04, 0x00, 0x0D, 0x8F, 0x5D, 0x83, 0xCA, 0x72, 0x82, 0xC9, 0x72, 0x81, 0xC9, 0x53, 0x5B, 0x8A, 0x00, 0x60, 0x81, 0xAD, 0x29, 0x00, 0x5A, 0x8C, 0x42, 0x00, 0x0F, 0xDA, 0x6F, 0x00, 0x81, 0x61, 0x84, 0xCB, 0x26, 0x00, 0x09, 0xA6, 0x05, 0x00, 0x3F, 0xE5, 0x65, 0x00, 0x09, 0xBE, 0x7A, 0x00, 0x5D, 0xC1, 0x26, 0x00, 0x06, 0xCF, 0x40, 0x00, 0x06, 0x81, 0xF4, 0x01, 0x00, 0x09, 0x87, 0x70, 0x00, 0x06, 0x83, 0x33, 0x00, 0x12, 0x99, 0x16, 0x00, 0x81, 0x4C, 0x87, 0x70, 0xCE, 0xE0, 0xEE, 0x00, 0x13, 0x97, 0x4A, 0x00, 0x38, 0xD6, 0x3E, 0x00, 0x1C, 0x8F, 0x5D, 0x00, 0x12, 0xC6, 0x61, 0x00, 0x08, 0x8F, 0x5D, 0x76, 0x89, 0x00, 0x13, 0x8F, 0x5D, 0x71, 0x80, 0xC9, 0x6D, 0x7A, 0xC1, 0x38, 0x3A, 0x00, 0x4F, 0x8F, 0x63, 0x00, 0x12, 0x87, 0x07, 0x00, 0x54, 0x96, 0x64, 0x00, 0x12, 0xE2, 0x5C, 0x00, 0x81, 0x61, 0x81, 0xD4, 0x4A, 0x00, 0x0C, 0x85, 0xAD, 0x37, 0x00, 0x39, 0xA9, 0x14, 0x00, 0x0C, 0x84, 0x9E, 0x47, 0x00, 0x60, 0x81, 0x88, 0x7C, 0x00, 0x09, 0x88, 0x50, 0x00, 0x0C, 0x83, 0x1E, 0x00, 0x15, 0x82, 0xCA, 0x60, 0x00, 0x81, 0x49, 0x87, 0x6D, 0xEA, 0xF2, 0xF8, 0x00, 0x1C, 0x87, 0x6D, 0x00, 0x23, 0xE6, 0x1B, 0x00, 0x15, 0xD6, 0x3E, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x23, 0xD6, 0x3E, 0x00, 0x0A, 0x8F, 0x5D, 0x87, 0x00, 0x05, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x71, 0x7F, 0xC9, 0x70, 0x7E, 0xC8, 0x52, 0x59, 0x00, 0x52, 0x8F, 0x63, 0x00, 0x12, 0x81, 0xF4, 0x13, 0x00, 0x4E, 0x8F, 0x66, 0x00, 0x12, 0x81, 0x91, 0x67, 0x00, 0x81, 0x67, 0x83, 0xAD, 0x60, 0x00, 0x09, 0xB9, 0x75, 0x00, 0x18, 0x85, 0x8D, 0x50, 0x00, 0x27, 0x87, 0x6D, 0x00, 0x60, 0x81, 0xE7, 0x48, 0x00, 0x06, 0x81, 0xB6, 0x29, 0x00, 0x18, 0x85, 0x95, 0x40, 0x00, 0x12, 0x82, 0xCA, 0x60, 0x00, 0x81, 0x49, 0x87, 0x70, 0xA5, 0xC6, 0xE0, 0x00, 0x16, 0x87, 0x70, 0x00, 0x48, 0xD6, 0x3E, 0x9A, 0x00, 0x1F, 0xD6, 0x3E, 0x00, 0x13, 0x8F, 0x5D, 0x82, 0x00, 0x07, 0x8F, 0x5D, 0x71, 0x7E, 0xC8, 0x70, 0x7D, 0xC8, 0x6B, 0x77, 0xC0, 0x00, 0x51, 0x8F, 0x63, 0x00, 0x15, 0x82, 0x86, 0x64, 0x00, 0x30, 0x81, 0x9A, 0x70, 0x00, 0x2A, 0x81, 0xC8, 0x5C, 0x00, 0x81, 0x6D, 0x83, 0xB5, 0x4D, 0x00, 0x09, 0xA6, 0x6B, 0x00, 0x30, 0x92, 0x39, 0x00, 0x0C, 0x82, 0x38, 0x00, 0x60, 0x82, 0x8A, 0x65, 0x00, 0x30, 0x85, 0xA5, 0x20, 0x00, 0x81, 0x46, 0x87, 0x6D, 0xC8, 0xDC, 0xEC, 0x00, 0x22, 0x8F, 0x5D, 0x00, 0x30, 0x81, 0xBC, 0x59, 0x00, 0x32, 0xD6, 0x3E, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x13, 0x8F, 0x5D, 0x7D, 0xC8, 0x6F, 0x7C, 0xC8, 0x6F, 0x7B, 0xC7, 0x51, 0x58, 0x89, 0x00, 0x66, 0x81, 0x81, 0x72, 0x00, 0x3F, 0x82, 0xBA, 0x3E, 0x4D, 0x4F, 0x62, 0x00, 0x12, 0x81, 0xCA, 0x49, 0x00, 0x81, 0x73, 0x83, 0xBD, 0x3A, 0x00, 0x0C, 0x87, 0x3A, 0x00, 0x24, 0x84, 0xAD, 0x62, 0x00, 0x0C, 0x82, 0x38, 0x00, 0x66, 0x84, 0xB5, 0x7F, 0x00, 0x0F, 0x84, 0x97, 0x40, 0x00, 0x0F, 0x87, 0x70, 0xD9, 0xD9, 0xDD, 0x00, 0x0F, 0xB8, 0x08, 0x00, 0x81, 0x43, 0x87, 0x6D, 0xF1, 0xF6, 0xFA, 0x00, 0x15, 0x87, 0x6D, 0x00, 0x15, 0xE6, 0x1B, 0x00, 0x49, 0xD6, 0x3E, 0x92, 0x00, 0x13, 0xD6, 0x3E, 0x00, 0x09, 0x8F, 0x5D, 0x73, 0x00, 0x11, 0x8F, 0x5D, 0x6F, 0x7C, 0xC8, 0x6E, 0x7A, 0xC7, 0x6A, 0x75, 0xBF, 0x00, 0x54, 0x8F, 0x63, 0x00, 0x18, 0x81, 0xE7, 0x42, 0x00, 0x06, 0x87, 0x76, 0x00, 0x2D, 0x8F, 0x6C, 0x67, 0x68, 0x78, 0x00, 0x12, 0x81, 0x91, 0x64, 0x00, 0x57, 0xA0, 0x1A, 0x00, 0x81, 0x28, 0xCE, 0x72, 0x00, 0x0C, 0xC0, 0x76, 0x00, 0x06, 0x85, 0x8C, 0x2B, 0x00, 0x0C, 0x81, 0x94, 0x28, 0x00, 0x06, 0x81, 0x94, 0x49, 0x00, 0x0C, 0x85, 0x8C, 0x4F, 0x00, 0x6C, 0x82, 0xAD, 0x4F, 0x00, 0x06, 0xA8, 0x13, 0x00, 0x09, 0x6C, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x06, 0xD0, 0x2C, 0x00, 0x0F, 0xB3, 0x39, 0x00, 0x81, 0x43, 0x87, 0x70, 0xAC, 0xCB, 0x00, 0x0D, 0xFD, 0x5C, 0x00, 0x41, 0xE6, 0x1B, 0x00, 0x14, 0xC6, 0x61, 0x99, 0x00, 0x28, 0xD6, 0x3E, 0x00, 0x0A, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x0B, 0x8F, 0x5D, 0x6E, 0x79, 0xC7, 0x6D, 0x78, 0xC7, 0x50, 0x56, 0x00, 0x55, 0x8F, 0x63, 0x00, 0x1E, 0x81, 0xDF, 0x5E, 0x00, 0x09, 0x83, 0x84, 0x2B, 0x00, 0x15, 0x85, 0x05, 0x5A, 0x5C, 0x6D, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x85, 0xE0, 0x61, 0x00, 0x12, 0x82, 0xAB, 0x65, 0x00, 0x81, 0x6D, 0x82, 0xA3, 0x24, 0x00, 0x7B, 0x85, 0x4A, 0x00, 0x33, 0x8A, 0x55, 0x00, 0x06, 0x87, 0x55, 0x00, 0x09, 0x8F, 0x45, 0x00, 0x0C, 0xAF, 0x20, 0x00, 0x15, 0x84, 0xFD, 0x70, 0x00, 0x81, 0x40, 0x87, 0x6D, 0xD5, 0xE5, 0xF1, 0x00, 0x28, 0x8F, 0x5D, 0x00, 0x5E, 0xD6, 0x3E, 0xCC, 0x00, 0x0C, 0xC6, 0x61, 0x00, 0x10, 0x8F, 0x5D, 0x7B, 0xC8, 0x6E, 0x7A, 0xC7, 0x6D, 0x79, 0xC7, 0x6D, 0x77, 0xC6, 0x68, 0x72, 0xBE, 0x00, 0x3F, 0x97, 0x3B, 0x00, 0x1E, 0x84, 0xA4, 0x05, 0x00, 0x81, 0x25, 0xE2, 0x11, 0x00, 0x81, 0x1C, 0xCF, 0x1C, 0x00, 0x81, 0x2E, 0x87, 0x70, 0x00, 0x09, 0x8F, 0x63, 0x00, 0x06, 0x90, 0x79, 0x00, 0x06, 0x8F, 0x51, 0x00, 0x09, 0x81, 0xCD, 0x6A, 0x00, 0x12, 0x9B, 0x03, 0x00, 0x81, 0x3D, 0x87, 0x6D, 0xF8, 0xFB, 0xFD, 0x00, 0x15, 0xC6, 0x5E, 0x00, 0x31, 0xC6, 0x61, 0x00, 0x23, 0x81, 0xBC, 0x59, 0x00, 0x0F, 0x8F, 0x5D, 0x00, 0x15, 0xC6, 0x61, 0x00, 0x21, 0x8F, 0x5D, 0x6C, 0x76, 0xC6, 0x6B, 0x75, 0xC6, 0x49, 0x4D, 0x00, 0x3A, 0x82, 0xAB, 0x59, 0x00, 0x81, 0x46, 0x81, 0x89, 0x1D, 0x00, 0x2D, 0x87, 0x70, 0x00, 0x6F, 0x90, 0x5E, 0x00, 0x81, 0x31, 0x87, 0x70, 0x00, 0x15, 0x82, 0xC6, 0x6E, 0x00, 0x18, 0x83, 0xE0, 0x2A, 0x00, 0x81, 0x3D, 0x84, 0x37, 0xC1, 0xD8, 0x00, 0x0E, 0x81, 0x85, 0x4C, 0x00, 0x2A, 0x8F, 0x5D, 0x00, 0x15, 0xD6, 0x3E, 0x00, 0x1A, 0x81, 0xBC, 0x59, 0x00, 0x2D, 0xD6, 0x3E, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x05, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x6C, 0x76, 0xC6, 0x6B, 0x74, 0xC6, 0x64, 0x6B, 0xB6, 0x00, 0x82, 0x2C, 0x87, 0x70, 0x00, 0x06, 0x85, 0x9C, 0x08, 0x00, 0x82, 0x20, 0x83, 0xA5, 0x34, 0x41, 0x43, 0x56, 0x00, 0x24, 0x82, 0xCA, 0x60, 0x00, 0x81, 0x53, 0xA7, 0x27, 0x00, 0x81, 0x03, 0xD6, 0x3E, 0x00, 0x0C, 0x8F, 0x5D, 0x6E, 0x7A, 0x00, 0x0D, 0x8F, 0x5D, 0x6B, 0x74, 0xC5, 0x6A, 0x72, 0xC5, 0x48, 0x4C, 0x00, 0x37, 0x8F, 0x63, 0x00, 0x81, 0x76, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xE3, 0x2F, 0x00, 0x82, 0x44, 0x83, 0xC2, 0x4E, 0x00, 0x81, 0x56, 0xA7, 0x27, 0x00, 0x29, 0xE6, 0x1B, 0x00, 0x15, 0xD6, 0x3E, 0x00, 0x1C, 0x8F, 0x5D, 0x00, 0x20, 0xD6, 0x3E, 0x00, 0x10, 0x8F, 0x5D, 0x78, 0xC7, 0x6C, 0x77, 0xC6, 0x6C, 0x75, 0xC6, 0x6B, 0x74, 0xC6, 0x6A, 0x73, 0xC5, 0x6A, 0x71, 0xC5, 0x62, 0x69, 0xB5, 0x00, 0x57, 0x9F, 0x40, 0x00, 0x63, 0x84, 0xCE, 0x62, 0x00, 0x42, 0x42, 0x00, 0x2D, 0x81, 0xA4, 0x0E, 0x00, 0x06, 0x82, 0x82, 0x69, 0x00, 0x0C, 0x84, 0xB4, 0x66, 0x00, 0x21, 0xE4, 0x16, 0x00, 0x81, 0x76, 0x83, 0xD9, 0x7A, 0x00, 0x09, 0x84, 0xD3, 0x0A, 0x00, 0x06, 0x82, 0xDE, 0x2F, 0x00, 0x81, 0x4C, 0x87, 0x70, 0xE3, 0xEE, 0xF6, 0x00, 0x21, 0x8F, 0x5D, 0x00, 0x7B, 0xD6, 0x3E, 0x00, 0x0C, 0xB7, 0x04, 0x00, 0x0D, 0x8F, 0x5D, 0x73, 0xC5, 0x6A, 0x72, 0xC5, 0x69, 0x70, 0xC5, 0x68, 0x6F, 0xC4, 0x48, 0x4B, 0x00, 0x82, 0x30, 0x82, 0xA9, 0x60, 0x00, 0x06, 0x84, 0xDF, 0x37, 0x00, 0x0C, 0xBE, 0x11, 0x00, 0x82, 0x05, 0x82, 0xAC, 0x24, 0x00, 0x18, 0x82, 0xA2, 0x4D, 0x00, 0x12, 0x85, 0xAD, 0x25, 0x00, 0x81, 0x3A, 0x87, 0x70, 0x00, 0x19, 0xCE, 0x4E, 0x00, 0x45, 0x81, 0xBC, 0x59, 0x00, 0x2D, 0xD6, 0x3E, 0x00, 0x06, 0x8F, 0x5D, 0x00, 0x11, 0xD6, 0x3E, 0x00, 0x05, 0x8F, 0x5D, 0x00, 0x08, 0x87, 0x6D, 0x00, 0x0E, 0x8F, 0x5D, 0x69, 0x70, 0xC4, 0x68, 0x6E, 0xC4, 0x61, 0x66, 0x00, 0x37, 0x8F, 0x63, 0x00, 0x82, 0x02, 0x85, 0x5F, 0x00, 0x0F, 0x8F, 0x6F, 0x00, 0x6F, 0x82, 0x92, 0x46, 0x00, 0x81, 0x16, 0xFF, 0x31, 0xC0, 0xC0, 0xC7, 0x00, 0x09, 0xC7, 0x5F, 0x5A, 0x5C, 0x6D, 0x00, 0x06, 0x15, 0x00, 0x12, 0x9A, 0x38, 0x00, 0x81, 0x4D, 0xB7, 0x04, 0x00, 0x06, 0x87, 0x70, 0x00, 0x78, 0xD6, 0x3E, 0x00, 0x1E, 0x8F, 0x5D, 0x74, 0x00, 0x0D, 0x8F, 0x5D, 0x68, 0x6E, 0xC4, 0x67, 0x6C, 0xC3, 0x47, 0x4A, 0x00, 0x82, 0x3C, 0x82, 0xB9, 0x43, 0x00, 0x0C, 0xD0, 0x56, 0x00, 0x81, 0x79, 0xA7, 0x54, 0x00, 0x06, 0xA3, 0x50, 0x00, 0x15, 0xF9, 0x1F, 0x00, 0x15, 0x82, 0xD2, 0x50, 0x00, 0x81, 0x34, 0x87, 0x70, 0x9E, 0xC2, 0xDE, 0x00, 0x52, 0xD6, 0x3E, 0x00, 0x1B, 0x81, 0xBC, 0x59, 0x00, 0x38, 0xD6, 0x3E, 0x00, 0x10, 0x8F, 0x5D, 0x72, 0xC5, 0x69, 0x00, 0x08, 0x8F, 0x5D, 0x67, 0x6D, 0xC4, 0x66, 0x6B, 0xC3, 0x5F, 0x64, 0xB4, 0x00, 0x82, 0x38, 0x8F, 0x63, 0x00, 0x0C, 0x82, 0x8A, 0x4D, 0x00, 0x09, 0x83, 0xF5, 0x6F, 0x00, 0x81, 0x73, 0x82, 0xBC, 0x16, 0x00, 0x06, 0xFA, 0x14, 0x00, 0x15, 0x91, 0x5F, 0x00, 0x06, 0x81, 0xC6, 0x3C, 0x00, 0x81, 0x40, 0xE6, 0x30, 0x00, 0x2B, 0xC6, 0x61, 0x00, 0x38, 0x82, 0x93, 0x17, 0x00, 0x48, 0xD6, 0x3E, 0x00, 0x0C, 0xB7, 0x04, 0x00, 0x0C, 0x8F, 0x5D, 0x67, 0x6D, 0xC4, 0x67, 0x6C, 0xC3, 0x66, 0x6B, 0xC3, 0x65, 0x69, 0xC3, 0x40, 0x42, 0x69, 0x00, 0x82, 0x32, 0x9F, 0x43, 0x00, 0x0C, 0xCF, 0x7C, 0x00, 0x09, 0x95, 0x45, 0x73, 0x75, 0x83, 0x00, 0x06, 0xD5, 0x79, 0x00, 0x82, 0x1D, 0x85, 0xB5, 0x00, 0x00, 0x81, 0x53, 0x8F, 0x5D, 0x00, 0x45, 0xD6, 0x3E, 0x00, 0x1A, 0xE6, 0x1B, 0x00, 0x16, 0xC6, 0x61, 0x82, 0x00, 0x17, 0xC6, 0x61, 0x77, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x65, 0x6A, 0xC3, 0x65, 0x68, 0xC2, 0x56, 0x5B, 0x97, 0x00, 0x82, 0x35, 0x9F, 0x34, 0x00, 0x18, 0x82, 0xAA, 0x04, 0x4D, 0x4F, 0x62, 0x00, 0x81, 0x6D, 0x9F, 0x4C, 0x00, 0x1E, 0x84, 0xFD, 0x70, 0x00, 0x12, 0x84, 0x9F, 0x30, 0x00, 0x81, 0x6F, 0xD6, 0x3E, 0x00, 0x28, 0x82, 0x93, 0x17, 0x00, 0x09, 0x8F, 0x5D, 0x00, 0x3F, 0xD6, 0x3E, 0x00, 0x0E, 0x8F, 0x5D, 0xC4, 0x00, 0x0F, 0x8F, 0x5D, 0x64, 0x68, 0xC2, 0x5F, 0x64, 0x00, 0x5E, 0x82, 0x8C, 0x10, 0x00, 0x81, 0x46, 0x95, 0x33, 0x00, 0x82, 0x1A, 0xBF, 0x03, 0x00, 0x06, 0xD6, 0x44, 0x00, 0x18, 0x82, 0xA4, 0x43, 0x00, 0x81, 0x40, 0x81, 0x85, 0x70, 0x00, 0x31, 0x8F, 0x5D, 0x00, 0x81, 0x03, 0xD6, 0x3E, 0x00, 0x10, 0x8F, 0x5D, 0x00, 0x06, 0x87, 0x6D, 0x00, 0x05, 0x8F, 0x5D, 0x64, 0x67, 0xC2, 0x63, 0x66, 0x00, 0x70, 0x82, 0xD3, 0x0C, 0x00, 0x81, 0x3A, 0x81, 0xB4, 0x21, 0x00, 0x82, 0x14, 0x82, 0xD3, 0x3F, 0x00, 0x06, 0x81, 0x89, 0x71, 0x00, 0x15, 0xEF, 0x0F, 0xC0, 0xC0, 0xC7, 0xE6, 0xE6, 0xE9, 0x00, 0x81, 0x3A, 0xE6, 0x30, 0xDC, 0xE9, 0xF3, 0x00, 0x66, 0xD6, 0x3E, 0x00, 0x1C, 0xE6, 0x1B, 0x00, 0x32, 0xD6, 0x3E, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x0D, 0x8F, 0x5D, 0xC2, 0x64, 0x67, 0xC2, 0x64, 0x66, 0xC2, 0x63, 0x65, 0x00, 0x82, 0x21, 0x87, 0x70, 0x00, 0x81, 0x28, 0xC6, 0x5E, 0x00, 0x06, 0xF6, 0x16, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x81, 0xFB, 0x0B, 0x00, 0x66, 0x89, 0x1E, 0x00, 0x06, 0x82, 0xB4, 0x08, 0x00, 0x09, 0xB9, 0x18, 0x00, 0x06, 0x82, 0x8B, 0x54, 0x80, 0x81, 0x8F, 0x00, 0x06, 0xA9, 0x41, 0x00, 0x06, 0xF2, 0x15, 0x00, 0x0C, 0x84, 0xF7, 0x01, 0x00, 0x81, 0x59, 0xF5, 0x78, 0x00, 0x81, 0x0C, 0xD6, 0x3E, 0x69, 0x71, 0x00, 0x0A, 0xB7, 0x04, 0x00, 0x0F, 0x8F, 0x5D, 0x62, 0x64, 0x00, 0x82, 0x21, 0x87, 0x70, 0x00, 0x78, 0xA8, 0x19, 0x00, 0x2A, 0xA0, 0x08, 0x00, 0x0F, 0xFE, 0x24, 0x00, 0x0C, 0xC5, 0x72, 0x00, 0x60, 0x89, 0x2A, 0x00, 0x2D, 0x83, 0xBC, 0x6F, 0x00, 0x81, 0x2B, 0x87, 0x70, 0x00, 0x18, 0x81, 0x9D, 0x1F, 0x00, 0x33, 0x82, 0x93, 0x17, 0x00, 0x31, 0xD6, 0x3E, 0x8F, 0x00, 0x17, 0xD6, 0x3E, 0x84, 0x00, 0x17, 0xD6, 0x3E, 0x79, 0x00, 0x14, 0xC6, 0x61, 0x00, 0x05, 0x8F, 0x5D, 0x66, 0x6B, 0xC3, 0x66, 0x6A, 0x00, 0x0D, 0x8F, 0x5D, 0x62, 0x63, 0x00, 0x83, 0x13, 0x87, 0x70, 0x00, 0x06, 0x96, 0x25, 0x00, 0x27, 0x84, 0xCD, 0x0D, 0x00, 0x12, 0x81, 0xA0, 0x43, 0x00, 0x6C, 0x83, 0x85, 0x08, 0x00, 0x06, 0x90, 0x55, 0x00, 0x2A, 0x83, 0xC1, 0x71, 0x00, 0x81, 0x28, 0x87, 0x70, 0xBA, 0xD3, 0xE7, 0x00, 0x39, 0x8F, 0x5D, 0x00, 0x39, 0x82, 0x93, 0x17, 0x00, 0x40, 0xD6, 0x3E, 0x00, 0x06, 0x8F, 0x5D, 0x00, 0x0B, 0xC6, 0x61, 0x00, 0x0D, 0x8F, 0x5D, 0x65, 0xC1, 0x62, 0x64, 0xC1, 0x62, 0x62, 0x00, 0x83, 0x13, 0x87, 0x70, 0x00, 0x09, 0x8E, 0x35, 0x00, 0x24, 0x81, 0xB4, 0x48, 0x00, 0x0F, 0x81, 0xDE, 0x51, 0x8D, 0x8E, 0x9A, 0x80, 0x81, 0x8F, 0x00, 0x0C, 0xA8, 0x64, 0x00, 0x12, 0x9E, 0x45, 0x00, 0x82, 0x20, 0xE6, 0x30, 0xF8, 0xFB, 0xFD, 0x00, 0x72, 0xD6, 0x3E, 0x00, 0x1C, 0x81, 0xBC, 0x59, 0x00, 0x16, 0xD6, 0x3E, 0xC8, 0x00, 0x1B, 0xD6, 0x3E, 0x00, 0x18, 0x8F, 0x5D, 0x56, 0x57, 0xA3, 0x00, 0x83, 0x12, 0x87, 0x70, 0x00, 0x09, 0x81, 0xB5, 0x0D, 0x00, 0x21, 0x87, 0x28, 0x00, 0x09, 0xF1, 0x2F, 0x00, 0x12, 0x8F, 0x48, 0x00, 0x0C, 0x81, 0xB7, 0x48, 0x00, 0x81, 0x0A, 0x81, 0xFE, 0x26, 0x00, 0x81, 0x41, 0x81, 0xBC, 0x59, 0x00, 0x17, 0xC6, 0x61, 0x00, 0x48, 0x82, 0x93, 0x17, 0x00, 0x37, 0x8F, 0x5D, 0x00, 0x14, 0xD6, 0x3E, 0x00, 0x09, 0xB7, 0x04, 0x00, 0x0C, 0x8F, 0x5D, 0x4D, 0x4E, 0x8D, 0x00, 0x83, 0x18, 0x84, 0xC6, 0x63, 0x00, 0x24, 0xEF, 0x45, 0x00, 0x09, 0xE5, 0x29, 0x00, 0x15, 0x81, 0xCF, 0x60, 0x00, 0x0C, 0x81, 0xBD, 0x48, 0x00, 0x57, 0x8F, 0x63, 0x4D, 0x4F, 0x62, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0xC1, 0x1A, 0x00, 0x1E, 0xE8, 0x47, 0x00, 0x81, 0x3A, 0xB7, 0x07, 0x00, 0x58, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x1A, 0x81, 0xBC, 0x59, 0x00, 0x16, 0xD6, 0x3E, 0x73, 0x00, 0x10, 0xC6, 0x61, 0x00, 0x09, 0x8F, 0x5D, 0x63, 0x66, 0xC1, 0x63, 0x64, 0xC1, 0x62, 0x63, 0xC1, 0x61, 0x62, 0xC0, 0x3C, 0x3E, 0x00, 0x82, 0x27, 0x84, 0x81, 0x09, 0x00, 0x06, 0x82, 0xF1, 0x15, 0x00, 0x09, 0x96, 0x3D, 0x00, 0x06, 0x83, 0xF9, 0x31, 0x00, 0x54, 0x86, 0x45, 0x00, 0x09, 0x81, 0xCF, 0x36, 0x00, 0x24, 0xA6, 0x6B, 0x00, 0x21, 0x82, 0x96, 0x59, 0x00, 0x09, 0x81, 0xDE, 0x75, 0x00, 0x54, 0xC0, 0x37, 0x00, 0x09, 0x81, 0xCD, 0x40, 0x00, 0x09, 0x81, 0xFB, 0x7D, 0x00, 0x0C, 0x82, 0xCC, 0x17, 0x00, 0x15, 0x82, 0x1D, 0x00, 0x81, 0x38, 0xF5, 0x7B, 0x00, 0x6B, 0x82, 0x93, 0x17, 0x00, 0x4B, 0xD6, 0x3E, 0x00, 0x0F, 0x8F, 0x5D, 0x56, 0x56, 0x00, 0x82, 0x27, 0x97, 0x4D, 0x00, 0x18, 0x81, 0xA7, 0x08, 0x00, 0x54, 0xA6, 0x0E, 0x00, 0x06, 0x88, 0x53, 0x00, 0x24, 0x81, 0xEC, 0x20, 0x00, 0x27, 0x82, 0x9B, 0x6D, 0x00, 0x57, 0x81, 0xEC, 0x20, 0x00, 0x06, 0x89, 0x18, 0x00, 0x12, 0x85, 0xA6, 0x3C, 0x00, 0x09, 0xEE, 0x1D, 0x00, 0x15, 0x81, 0xCD, 0x58, 0x00, 0x81, 0x37, 0xA7, 0x2A, 0x00, 0x69, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x1D, 0xE6, 0x1B, 0x00, 0x13, 0xD6, 0x3E, 0x66, 0x00, 0x0B, 0xB7, 0x04, 0x00, 0x09, 0x8F, 0x5D, 0x3F, 0x41, 0x68, 0x00, 0x82, 0x2C, 0x85, 0xF1, 0x60, 0x00, 0x0C, 0xC6, 0x73, 0x00, 0x09, 0xDE, 0x49, 0x00, 0x51, 0x84, 0xAE, 0x36, 0x00, 0x2A, 0x81, 0xE6, 0x11, 0x00, 0x27, 0x82, 0xA3, 0x09, 0x00, 0x51, 0x81, 0xF4, 0x61, 0x00, 0x09, 0x88, 0x6B, 0x00, 0x1B, 0x81, 0xB5, 0x76, 0x00, 0x06, 0x81, 0x1C, 0x00, 0x12, 0xA0, 0x38, 0x00, 0x81, 0x35, 0xA7, 0x2A, 0x00, 0x42, 0xD6, 0x3E, 0x00, 0x2F, 0x82, 0x93, 0x17, 0x76, 0x00, 0x47, 0xD6, 0x3E, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x05, 0x87, 0x6D, 0x00, 0x82, 0x29, 0x8F, 0x5D, 0x00, 0x06, 0x86, 0x30, 0x00, 0x15, 0x8E, 0x44, 0x00, 0x06, 0x95, 0x51, 0x00, 0x4B, 0x81, 0xED, 0x2D, 0x00, 0x2D, 0x82, 0x8B, 0x60, 0x00, 0x09, 0x98, 0x5D, 0x00, 0x27, 0x88, 0x17, 0x00, 0x4E, 0xA8, 0x52, 0x00, 0x21, 0xAF, 0x77, 0x00, 0x06, 0x82, 0x38, 0x00, 0x0F, 0x8A, 0x0D, 0x00, 0x81, 0x34, 0xDE, 0x31, 0x00, 0x75, 0x82, 0x93, 0x17, 0x00, 0x37, 0xD6, 0x3E, 0x00, 0x0B, 0xE6, 0x1B, 0x00, 0x0F, 0x8F, 0x5D, 0x42, 0x43, 0x70, 0x00, 0x82, 0x26, 0x9F, 0x37, 0x00, 0x1E, 0x81, 0xE2, 0x73, 0x00, 0x06, 0xA5, 0x2B, 0x00, 0x48, 0x9F, 0x49, 0x00, 0x2D, 0x82, 0x9B, 0x40, 0x00, 0x27, 0x81, 0xF4, 0x37, 0x00, 0x09, 0x9E, 0x66, 0x00, 0x48, 0x98, 0x7B, 0x00, 0x15, 0x81, 0xC4, 0x49, 0x00, 0x18, 0x81, 0xDE, 0x03, 0x00, 0x81, 0x2E, 0xDE, 0x40, 0xB3, 0xCF, 0x00, 0x0D, 0x82, 0xBA, 0x3B, 0x00, 0x5A, 0x82, 0xE9, 0x55, 0x00, 0x21, 0x82, 0x93, 0x17, 0x00, 0x0F, 0x8F, 0x5D, 0x00, 0x2F, 0xD6, 0x3E, 0xC3, 0x00, 0x0C, 0xB7, 0x04, 0x61, 0x62, 0xC0, 0x5B, 0x5B, 0xB1, 0x00, 0x72, 0x96, 0x16, 0x00, 0x09, 0x81, 0xA9, 0x40, 0x00, 0x06, 0x06, 0x00, 0x81, 0x25, 0xE4, 0x79, 0x00, 0x06, 0x87, 0x01, 0x00, 0x1B, 0x8E, 0x6E, 0x00, 0x06, 0x8E, 0x3E, 0x00, 0x48, 0x81, 0x95, 0x59, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x09, 0x90, 0x0A, 0x00, 0x21, 0xAF, 0x47, 0x00, 0x51, 0x82, 0xA4, 0x04, 0x00, 0x2A, 0x85, 0xE4, 0x14, 0x00, 0x06, 0x83, 0xFB, 0x7B, 0x00, 0x81, 0x28, 0x87, 0x70, 0x00, 0x15, 0x81, 0xAD, 0x02, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x42, 0xD6, 0x3E, 0x63, 0x00, 0x05, 0xA7, 0x27, 0x61, 0x61, 0xC0, 0x45, 0x46, 0x00, 0x64, 0x84, 0xB8, 0x1F, 0x00, 0x06, 0xDA, 0x5D, 0x00, 0x18, 0x82, 0xBE, 0x60, 0x00, 0x81, 0x25, 0x81, 0x84, 0x1B, 0x00, 0x81, 0x19, 0x87, 0x70, 0x00, 0x09, 0x2A, 0x00, 0x21, 0x8A, 0x37, 0x00, 0x51, 0x87, 0x70, 0x00, 0x15, 0x83, 0xD0, 0x50, 0x00, 0x81, 0x43, 0xFE, 0x00, 0x00, 0x13, 0xBE, 0x77, 0x00, 0x65, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x1C, 0xE6, 0x1B, 0x00, 0x14, 0xD6, 0x3E, 0x67, 0x6C, 0x00, 0x13, 0xC6, 0x61, 0x00, 0x66, 0x8F, 0x5D, 0x67, 0x68, 0x78, 0x00, 0x21, 0x83, 0xC4, 0x11, 0x00, 0x81, 0x25, 0x87, 0x70, 0x00, 0x15, 0x81, 0x8B, 0x25, 0x00, 0x12, 0xAD, 0x27, 0x00, 0x48, 0xA7, 0x33, 0x00, 0x2A, 0x87, 0x1C, 0x00, 0x2A, 0x82, 0xCA, 0x36, 0x00, 0x82, 0x29, 0x87, 0x70, 0x00, 0x12, 0xE6, 0x21, 0x00, 0x55, 0xD6, 0x3E, 0x00, 0x4E, 0x8F, 0x5D, 0x00, 0x20, 0xD6, 0x3E, 0x00, 0x60, 0x8F, 0x5D, 0x67, 0x68, 0x78, 0x00, 0x27, 0x82, 0xCE, 0x31, 0x00, 0x30, 0x87, 0x70, 0x00, 0x78, 0x81, 0xAC, 0x0D, 0xC0, 0xC0, 0xC7, 0x00, 0x18, 0xC5, 0x30, 0x00, 0x06, 0xDD, 0x3C, 0x00, 0x4B, 0x89, 0x39, 0x00, 0x09, 0x87, 0x1C, 0x00, 0x21, 0x81, 0xF3, 0x48, 0x00, 0x27, 0xA7, 0x2D, 0x00, 0x54, 0x82, 0xCA, 0x60, 0x00, 0x06, 0x81, 0x25, 0x00, 0x21, 0x81, 0x22, 0x00, 0x06, 0x8A, 0x2B, 0x00, 0x81, 0x28, 0x82, 0xB3, 0x10, 0x00, 0x12, 0xAF, 0x1A, 0x00, 0x79, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x14, 0x81, 0xBC, 0x59, 0x00, 0x1E, 0xE6, 0x1B, 0x00, 0x5D, 0x8F, 0x5D, 0x00, 0x06, 0x84, 0x83, 0x5C, 0x00, 0x54, 0x81, 0xC3, 0x75, 0x00, 0x09, 0x81, 0xB1, 0x72, 0x00, 0x75, 0x9F, 0x73, 0x00, 0x06, 0xB7, 0x10, 0x00, 0x1B, 0x84, 0xAC, 0x73, 0x00, 0x4B, 0xBF, 0x03, 0x00, 0x09, 0x82, 0xE2, 0x30, 0x00, 0x21, 0xAF, 0x20, 0x00, 0x2A, 0x82, 0x9B, 0x64, 0x00, 0x54, 0xAF, 0x20, 0x00, 0x24, 0xB1, 0x16, 0x00, 0x15, 0x84, 0xB7, 0x1B, 0x00, 0x81, 0x2B, 0xAF, 0x1A, 0x00, 0x63, 0x82, 0xE9, 0x55, 0x00, 0x60, 0xD6, 0x3E, 0x00, 0x5A, 0x8F, 0x5D, 0x00, 0x1B, 0x82, 0xFD, 0x75, 0x00, 0x06, 0xD2, 0x64, 0x00, 0x06, 0xFA, 0x0B, 0x00, 0x06, 0x81, 0xC5, 0x2F, 0x00, 0x2D, 0x87, 0x70, 0x00, 0x0F, 0x82, 0x93, 0x50, 0x00, 0x63, 0x8F, 0x66, 0x00, 0x12, 0x84, 0xAE, 0x39, 0x00, 0x09, 0x82, 0xB9, 0x43, 0x00, 0x09, 0x82, 0xF7, 0x66, 0x00, 0x09, 0x81, 0xBD, 0x09, 0x00, 0x06, 0x85, 0xF3, 0x14, 0x00, 0x51, 0xDE, 0x3D, 0x00, 0x1E, 0xC6, 0x1F, 0x00, 0x36, 0xD6, 0x74, 0x00, 0x51, 0x82, 0x9B, 0x34, 0x00, 0x1B, 0x8F, 0x63, 0x00, 0x06, 0x82, 0xA6, 0x60, 0x00, 0x81, 0x2B, 0x82, 0x9B, 0x40, 0x00, 0x0F, 0xAF, 0x1A, 0x00, 0x81, 0x0A, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x1C, 0xE6, 0x1B, 0x00, 0x08, 0xB7, 0x04, 0x5E, 0x5E, 0xB9, 0x37, 0x39, 0x52, 0x00, 0x69, 0x84, 0x92, 0x47, 0x00, 0x15, 0x81, 0x8C, 0x14, 0x00, 0x30, 0x87, 0x70, 0x00, 0x0F, 0xFA, 0x62, 0x00, 0x63, 0x84, 0xF4, 0x16, 0x00, 0x33, 0x82, 0xE7, 0x41, 0x00, 0x54, 0x83, 0xAF, 0x14, 0x00, 0x1B, 0xB7, 0x64, 0x00, 0x09, 0x92, 0x48, 0x00, 0x24, 0x82, 0x8B, 0x3F, 0x00, 0x4B, 0x82, 0xAB, 0x6E, 0x00, 0x0F, 0xDF, 0x1A, 0x00, 0x18, 0xF7, 0x32, 0x00, 0x09, 0x83, 0xC0, 0x31, 0x00, 0x12, 0x8B, 0x1D, 0x00, 0x81, 0x19, 0x87, 0x70, 0x00, 0x0F, 0x81, 0xEB, 0x79, 0x00, 0x78, 0xD6, 0x3E, 0x00, 0x12, 0x82, 0x93, 0x17, 0x00, 0x0A, 0x8F, 0x5D, 0x00, 0x14, 0xD6, 0x3E, 0x00, 0x1E, 0x8F, 0x5D, 0x4A, 0x4B, 0x86, 0x00, 0x66, 0x87, 0x6D, 0xC0, 0xC0, 0xC7, 0x00, 0x18, 0x87, 0x16, 0x00, 0x30, 0x87, 0x70, 0x00, 0x12, 0x83, 0xB5, 0x17, 0x00, 0x60, 0x83, 0xA6, 0x71, 0x00, 0x33, 0x84, 0xBE, 0x19, 0x00, 0x54, 0x82, 0x93, 0x47, 0x00, 0x1B, 0x83, 0x90, 0x0A, 0x00, 0x09, 0x82, 0x9B, 0x1C, 0x00, 0x2A, 0x82, 0x9C, 0x08, 0x00, 0x51, 0x84, 0x86, 0x68, 0x00, 0x09, 0x87, 0x55, 0x00, 0x09, 0x82, 0x85, 0x03, 0x00, 0x06, 0x81, 0x8D, 0x5A, 0x00, 0x09, 0x90, 0x4F, 0x00, 0x81, 0x2B, 0x81, 0xEC, 0x20, 0x00, 0x0F, 0xDE, 0x34, 0x00, 0x21, 0xD6, 0x3E, 0x00, 0x6F, 0x82, 0x93, 0x17, 0x00, 0x36, 0xD6, 0x3E, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x12, 0x87, 0x6D, 0xF2, 0xF2, 0xF4, 0x00, 0x1E, 0x8C, 0x75, 0x00, 0x33, 0x87, 0x70, 0x00, 0x12, 0x87, 0x73, 0x00, 0x81, 0x5E, 0x83, 0xD0, 0x47, 0x00, 0x09, 0xE4, 0x76, 0x00, 0x15, 0x86, 0x33, 0x00, 0x09, 0x86, 0x51, 0x00, 0x24, 0xCF, 0x58, 0x00, 0x2D, 0x90, 0x0A, 0x00, 0x48, 0x84, 0xEC, 0x6E, 0x00, 0x1B, 0x84, 0xAB, 0x1E, 0x00, 0x81, 0x23, 0x81, 0xF3, 0x69, 0x00, 0x5D, 0x82, 0x93, 0x17, 0x00, 0x30, 0xD6, 0x3E, 0x00, 0x33, 0xE6, 0x1B, 0x00, 0x05, 0x87, 0x6D, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x12, 0x84, 0x86, 0x74, 0x00, 0x24, 0x84, 0xAE, 0x30, 0x00, 0x36, 0x87, 0x70, 0x00, 0x7B, 0x83, 0xF8, 0x75, 0x00, 0x7E, 0x84, 0x92, 0x2C, 0x00, 0x0C, 0xEF, 0x06, 0x00, 0x0F, 0x82, 0x9D, 0x57, 0x00, 0x24, 0x99, 0x58, 0x00, 0x2A, 0x90, 0x0A, 0x00, 0x48, 0x81, 0xF4, 0x0A, 0x00, 0x81, 0x34, 0x82, 0xCA, 0x60, 0x00, 0x0C, 0x81, 0xDC, 0x1F, 0x00, 0x4C, 0xD6, 0x3E, 0x00, 0x4A, 0x82, 0x93, 0x17, 0x00, 0x30, 0xD6, 0x3E, 0x5D, 0x5D, 0x00, 0x52, 0x8F, 0x5D, 0x00, 0x0F, 0xBE, 0x62, 0x00, 0x27, 0x84, 0xB6, 0x1D, 0x00, 0x39, 0x87, 0x70, 0x00, 0x7B, 0x83, 0xF8, 0x78, 0x00, 0x81, 0x13, 0x83, 0xCE, 0x5A, 0x00, 0x24, 0x91, 0x62, 0x00, 0x09, 0x98, 0x1B, 0x00, 0x81, 0x0A, 0x85, 0xB5, 0x4E, 0x00, 0x81, 0x20, 0xB7, 0x0A, 0x00, 0x77, 0x82, 0xE9, 0x55, 0x00, 0x27, 0xD6, 0x3E, 0x6B, 0x00, 0x18, 0xD6, 0x3E, 0x68, 0x00, 0x0D, 0xB7, 0x04, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x0F, 0x82, 0xD9, 0x4E, 0x00, 0x2A, 0x84, 0xBE, 0x0A, 0x00, 0x39, 0x87, 0x70, 0x00, 0x12, 0x83, 0xF7, 0x7D, 0x00, 0x81, 0x5E, 0x81, 0xC3, 0x5A, 0x00, 0x1B, 0xB9, 0x5D, 0x00, 0x24, 0x87, 0x40, 0x00, 0x0C, 0x81, 0x9D, 0x58, 0x00, 0x81, 0x0A, 0x81, 0xAE, 0x60, 0x00, 0x81, 0x1F, 0x81, 0xB4, 0x78, 0x00, 0x5E, 0xD6, 0x3E, 0x00, 0x5F, 0x81, 0xBC, 0x59, 0x00, 0x09, 0xD6, 0x3E, 0x60, 0x60, 0xC0, 0x3A, 0x3B, 0x5A, 0x00, 0x5A, 0x83, 0x89, 0x66, 0x00, 0x2D, 0xBD, 0x04, 0x00, 0x3C, 0x87, 0x70, 0x00, 0x0F, 0x83, 0x92, 0x4E, 0x00, 0x81, 0x61, 0x81, 0xC3, 0x7B, 0x00, 0x12, 0xD1, 0x27, 0xC0, 0xC0, 0xC7, 0x00, 0x27, 0xB9, 0x12, 0x00, 0x09, 0x8A, 0x1C, 0x00, 0x81, 0x0D, 0x82, 0xDC, 0x6C, 0x00, 0x81, 0x1D, 0x9F, 0x3D, 0x00, 0x1E, 0xD6, 0x3E, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x0E, 0x81, 0xBC, 0x59, 0x00, 0x09, 0x8F, 0x5D, 0x50, 0x50, 0x94, 0x00, 0x5D, 0x82, 0xF2, 0x10, 0x00, 0x2D, 0xA6, 0x3E, 0x00, 0x3C, 0x87, 0x70, 0x00, 0x0F, 0x8F, 0x63, 0x00, 0x82, 0x1D, 0x84, 0xC6, 0x6C, 0x00, 0x06, 0x81, 0xB5, 0x25, 0x00, 0x81, 0x10, 0x92, 0x06, 0x00, 0x81, 0x1C, 0xD6, 0x47, 0x00, 0x81, 0x23, 0x81, 0xBC, 0x59, 0x00, 0x23, 0xD6, 0x3E, 0x00, 0x60, 0x8F, 0x5D, 0x00, 0x39, 0x83, 0xA5, 0x1F, 0x00, 0x36, 0x87, 0x70, 0x00, 0x0F, 0x98, 0x48, 0x00, 0x82, 0x20, 0x84, 0xD6, 0x4F, 0x00, 0x81, 0x10, 0x82, 0x20, 0x00, 0x81, 0x13, 0x87, 0x70, 0x00, 0x4E, 0xD6, 0x3E, 0x00, 0x5D, 0x82, 0x93, 0x17, 0x00, 0x21, 0xD6, 0x3E, 0x60, 0x60, 0x00, 0x52, 0x8F, 0x5D, 0x00, 0x0F, 0x82, 0x9B, 0x43, 0x00, 0x30, 0xCD, 0x71, 0x00, 0x3F, 0x87, 0x70, 0x00, 0x0F, 0x83, 0xA1, 0x30, 0x00, 0x81, 0x55, 0x85, 0x8D, 0x7A, 0x00, 0x81, 0x61, 0x84, 0xA7, 0x59, 0x00, 0x81, 0x13, 0xBE, 0x7A, 0x00, 0x81, 0x28, 0x82, 0x93, 0x17, 0x00, 0x0C, 0x8F, 0x5D, 0x00, 0x12, 0xC6, 0x61, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x0C, 0xA4, 0x48, 0x00, 0x33, 0xC5, 0x7B, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x5B, 0x83, 0xB1, 0x10, 0x00, 0x81, 0x67, 0x81, 0xFC, 0x30, 0x00, 0x81, 0x10, 0xF6, 0x04, 0x00, 0x73, 0xD6, 0x3E, 0x00, 0x38, 0x82, 0x93, 0x17, 0x00, 0x1B, 0xD6, 0x3E, 0x00, 0x54, 0x8F, 0x5D, 0x00, 0x0F, 0x97, 0x4D, 0x00, 0x33, 0xC5, 0x78, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x04, 0x83, 0xC9, 0x64, 0x00, 0x82, 0x41, 0x85, 0xD6, 0x1E, 0x00, 0x81, 0x0D, 0x81, 0xA5, 0x1E, 0x00, 0x7C, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x32, 0xE6, 0x1B, 0x60, 0x5F, 0x00, 0x52, 0x81, 0xB4, 0x6F, 0x00, 0x0F, 0x83, 0x30, 0x00, 0x33, 0xB3, 0x69, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x5B, 0x83, 0xD0, 0x50, 0x00, 0x81, 0x52, 0x85, 0x9E, 0x79, 0x00, 0x12, 0x93, 0x01, 0x00, 0x81, 0x0D, 0x84, 0xC6, 0x2A, 0xA5, 0xC6, 0xE0, 0x00, 0x54, 0x82, 0xE9, 0x55, 0x00, 0x5D, 0x82, 0x93, 0x17, 0x00, 0x15, 0x81, 0xBC, 0x59, 0x60, 0x60, 0xC0, 0x55, 0x55, 0x00, 0x52, 0x81, 0xA5, 0x12, 0x00, 0x0C, 0xA6, 0x2F, 0x00, 0x36, 0x86, 0x6C, 0x00, 0x4E, 0x87, 0x70, 0x00, 0x81, 0x70, 0x82, 0x8A, 0x50, 0x00, 0x81, 0x07, 0x97, 0x14, 0x00, 0x0F, 0x82, 0xB5, 0x60, 0x00, 0x0F, 0x84, 0xA8, 0x36, 0x00, 0x0C, 0x82, 0x95, 0x5E, 0x00, 0x12, 0xBA, 0x34, 0x00, 0x81, 0x0D, 0x8F, 0x63, 0x00, 0x2E, 0xD6, 0x3E, 0x00, 0x81, 0x09, 0x82, 0x93, 0x17, 0x00, 0x0C, 0x8F, 0x5D, 0x00, 0x06, 0xB7, 0x04, 0x60, 0x5F, 0xC0, 0x3F, 0x40, 0x00, 0x52, 0x81, 0xB4, 0x6F, 0x00, 0x42, 0x83, 0xD7, 0x3C, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x61, 0x83, 0xFF, 0x70, 0x00, 0x81, 0x34, 0x82, 0x86, 0x10, 0x00, 0x0F, 0x9B, 0x5A, 0x00, 0x06, 0x82, 0xD2, 0x62, 0x00, 0x18, 0xBF, 0x7B, 0x00, 0x66, 0x85, 0xB4, 0x20, 0x00, 0x24, 0x81, 0xEC, 0x05, 0x00, 0x7F, 0x82, 0xE9, 0x55, 0x00, 0x38, 0x82, 0x93, 0x17, 0x00, 0x13, 0x8F, 0x5D, 0x54, 0xA2, 0x00, 0x81, 0x16, 0x83, 0xF0, 0x10, 0x00, 0x83, 0x4E, 0x87, 0x70, 0x00, 0x15, 0x81, 0xAD, 0x05, 0x00, 0x0C, 0x94, 0x0B, 0x00, 0x18, 0xB3, 0x3F, 0x00, 0x81, 0x04, 0x97, 0x56, 0xDC, 0xE9, 0xF3, 0x00, 0x3D, 0xD6, 0x3E, 0x00, 0x63, 0x82, 0x93, 0x17, 0x00, 0x26, 0xD6, 0x3E, 0x00, 0x57, 0x8F, 0x5D, 0x00, 0x0F, 0x9B, 0x3C, 0x00, 0x36, 0xED, 0x25, 0x00, 0x82, 0x3B, 0x87, 0x70, 0x00, 0x15, 0x86, 0x81, 0x16, 0x00, 0x06, 0xB2, 0x26, 0x00, 0x72, 0x84, 0xCE, 0x4D, 0x00, 0x09, 0x8C, 0x00, 0x00, 0x1E, 0x85, 0xCC, 0x50, 0x00, 0x18, 0xD7, 0x7B, 0x00, 0x81, 0x04, 0x84, 0x8F, 0x4D, 0xC7, 0xDB, 0xEC, 0x00, 0x81, 0x3A, 0x82, 0x93, 0x17, 0x00, 0x07, 0x8F, 0x5D, 0x00, 0x05, 0xB7, 0x04, 0x00, 0x57, 0x8F, 0x5D, 0x00, 0x0F, 0x87, 0x70, 0x00, 0x36, 0x81, 0x8C, 0x6B, 0x00, 0x82, 0x35, 0x87, 0x70, 0x00, 0x09, 0x81, 0xD3, 0x25, 0x00, 0x24, 0x85, 0xCF, 0x0E, 0x00, 0x6C, 0xDE, 0x2E, 0x00, 0x3F, 0x85, 0xDC, 0x30, 0x00, 0x7E, 0x97, 0x59, 0xB2, 0xCE, 0xE4, 0x00, 0x81, 0x3A, 0x82, 0x93, 0x17, 0x00, 0x0C, 0x8F, 0x5D, 0x41, 0x43, 0x6F, 0x00, 0x81, 0x5B, 0x87, 0x70, 0x00, 0x0F, 0x84, 0xCF, 0x54, 0x00, 0x81, 0x61, 0xCE, 0x21, 0x00, 0x33, 0xBD, 0x34, 0x00, 0x69, 0xEE, 0x11, 0x00, 0x06, 0xA7, 0x1E, 0x00, 0x3C, 0x85, 0xDC, 0x30, 0x00, 0x7B, 0x84, 0xAF, 0x0D, 0xAB, 0xC9, 0xE2, 0x00, 0x81, 0x3A, 0x82, 0x93, 0x17, 0x00, 0x09, 0xC6, 0x61, 0x5A, 0x59, 0x00, 0x5B, 0x81, 0xB4, 0x6F, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x36, 0xCD, 0x5C, 0x00, 0x82, 0x2C, 0xAF, 0x20, 0x00, 0x12, 0x81, 0xA0, 0x16, 0x00, 0x27, 0x83, 0x91, 0x50, 0x00, 0x69, 0x85, 0xAF, 0x3C, 0x00, 0x06, 0x81, 0xAD, 0x7D, 0x00, 0x3F, 0x85, 0xDC, 0x30, 0x00, 0x78, 0x84, 0xBE, 0x6D, 0x00, 0x81, 0x3D, 0x82, 0x93, 0x17, 0x00, 0x06, 0xA7, 0x27, 0x60, 0x5F, 0xC0, 0x44, 0x45, 0x00, 0x5B, 0x81, 0xB4, 0x6F, 0x00, 0x42, 0xCD, 0x5C, 0x00, 0x42, 0x87, 0x70, 0x00, 0x42, 0xB8, 0x14, 0x00, 0x81, 0x2E, 0x81, 0xE5, 0x28, 0x00, 0x36, 0x83, 0xA1, 0x30, 0x00, 0x66, 0x87, 0x73, 0x00, 0x09, 0x82, 0x94, 0x7B, 0x00, 0x0F, 0xF2, 0x21, 0x00, 0x06, 0x81, 0x3D, 0x00, 0x2A, 0xE7, 0x2E, 0x00, 0x72, 0x9F, 0x4F, 0xF8, 0xFA, 0xFD, 0x00, 0x1C, 0xD6, 0x3E, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x17, 0xD6, 0x3E, 0x00, 0x15, 0xE6, 0x1B, 0x00, 0x5D, 0x8F, 0x5D, 0x00, 0x0F, 0x9A, 0x71, 0x00, 0x78, 0x87, 0x70, 0x00, 0x81, 0x64, 0xCE, 0x60, 0x00, 0x0C, 0x81, 0xAF, 0x16, 0x00, 0x3C, 0x83, 0xB1, 0x10, 0x00, 0x63, 0x87, 0x73, 0x00, 0x09, 0xF2, 0x2D, 0x00, 0x06, 0x81, 0xFE, 0x14, 0x00, 0x09, 0x81, 0xAF, 0x4F, 0x00, 0x33, 0x94, 0x02, 0x00, 0x6C, 0x84, 0xDE, 0x2D, 0xE3, 0xED, 0xF5, 0x00, 0x81, 0x06, 0x82, 0xE9, 0x55, 0x00, 0x34, 0x82, 0x93, 0x17, 0x00, 0x66, 0x8F, 0x5D, 0x00, 0x0F, 0x84, 0xC2, 0x0E, 0x00, 0x36, 0x86, 0x6C, 0x00, 0x42, 0x87, 0x70, 0x00, 0x0C, 0x98, 0x54, 0x00, 0x81, 0x0A, 0x81, 0x8B, 0x3A, 0x00, 0x57, 0x92, 0x48, 0x00, 0x3F, 0x83, 0xC0, 0x70, 0x00, 0x66, 0x82, 0x23, 0x00, 0x12, 0x81, 0xC8, 0x65, 0x00, 0x39, 0x85, 0xC8, 0x61, 0x00, 0x69, 0x85, 0xC4, 0x33, 0xDC, 0xE8, 0xF3, 0x00, 0x42, 0xD6, 0x3E, 0x00, 0x7B, 0x81, 0xBC, 0x59, 0x60, 0x5F, 0x00, 0x61, 0x8F, 0x5D, 0x00, 0x0F, 0x9E, 0x3C, 0x00, 0x36, 0x81, 0x9A, 0x16, 0x00, 0x42, 0x87, 0x70, 0x00, 0x81, 0x61, 0x81, 0x85, 0x73, 0x00, 0x1B, 0x82, 0x9B, 0x16, 0x00, 0x36, 0x86, 0x39, 0x00, 0x66, 0x82, 0xBB, 0x0C, 0x41, 0x43, 0x56, 0x00, 0x06, 0x81, 0xAD, 0x26, 0x00, 0x3F, 0x90, 0x52, 0x00, 0x66, 0x84, 0xB7, 0x1E, 0xC6, 0xDA, 0xEC, 0x00, 0x64, 0x82, 0x93, 0x17, 0x00, 0x30, 0xD6, 0x3E, 0x00, 0x26, 0x82, 0x93, 0x17, 0x00, 0x66, 0x8F, 0x5D, 0x00, 0x12, 0x86, 0x6F, 0x00, 0x33, 0x84, 0x49, 0x00, 0x4E, 0xFE, 0x00, 0x00, 0x81, 0x55, 0x82, 0xF1, 0x03, 0x00, 0x09, 0x82, 0x23, 0x00, 0x48, 0x83, 0xE0, 0x30, 0x00, 0x81, 0x34, 0x99, 0x76, 0x00, 0x60, 0xEE, 0x4A, 0xC6, 0xD9, 0xEB, 0x00, 0x53, 0x82, 0xE9, 0x55, 0x00, 0x61, 0x82, 0x93, 0x17, 0x00, 0x09, 0xB7, 0x04, 0x5C, 0x5B, 0xB8, 0x37, 0x38, 0x00, 0x52, 0x81, 0xC4, 0x4C, 0x00, 0x51, 0x96, 0x4F, 0x00, 0x3F, 0x87, 0x70, 0x00, 0x0F, 0xA5, 0x10, 0x00, 0x81, 0x5B, 0x83, 0xD8, 0x3A, 0x00, 0x4B, 0x83, 0xF0, 0x10, 0x00, 0x60, 0x8A, 0x19, 0x00, 0x06, 0x82, 0xE4, 0x50, 0x00, 0x2A, 0x84, 0xC6, 0x60, 0x00, 0x81, 0x04, 0x85, 0xF3, 0x53, 0xB1, 0xCB, 0xE4, 0x00, 0x72, 0x82, 0x93, 0x17, 0x00, 0x30, 0xD6, 0x3E, 0x00, 0x15, 0x81, 0xBC, 0x59, 0x00, 0x06, 0x8F, 0x5D, 0x4A, 0x4A, 0x85, 0x00, 0x72, 0x84, 0xE1, 0x51, 0x00, 0x33, 0x81, 0x92, 0x2F, 0x00, 0x4B, 0x81, 0x9D, 0x40, 0x00, 0x81, 0x55, 0x81, 0xBD, 0x06, 0x00, 0x09, 0x8D, 0x58, 0x00, 0x4E, 0x83, 0xFF, 0x70, 0x00, 0x5A, 0x82, 0x2C, 0x00, 0x1E, 0xA6, 0x65, 0x00, 0x3F, 0x81, 0x81, 0x21, 0x00, 0x5A, 0x85, 0x8D, 0x5C, 0xA9, 0xC6, 0xE1, 0x00, 0x60, 0x82, 0xE9, 0x55, 0x00, 0x54, 0x82, 0x93, 0x17, 0x00, 0x6F, 0x8F, 0x5D, 0x00, 0x12, 0xC5, 0x6F, 0x00, 0x30, 0x84, 0x49, 0x00, 0x48, 0x81, 0xAD, 0x20, 0x00, 0x81, 0x58, 0x97, 0x4D, 0x00, 0x06, 0x8F, 0x12, 0x00, 0x51, 0x84, 0x8F, 0x50, 0x00, 0x57, 0x97, 0x53, 0x00, 0x06, 0xA0, 0x6B, 0x00, 0x06, 0x81, 0xD4, 0x59, 0x00, 0x30, 0x84, 0xE6, 0x20, 0x00, 0x7E, 0x85, 0xBC, 0x6D, 0xA9, 0xC5, 0x00, 0x06, 0x87, 0x70, 0x00, 0x1A, 0xD6, 0x3E, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x05, 0x8F, 0x5D, 0x5F, 0x5E, 0xBF, 0x00, 0x69, 0x8F, 0x5D, 0x00, 0x42, 0x81, 0xB4, 0x18, 0x00, 0x39, 0x87, 0x70, 0x00, 0x0F, 0xC6, 0x67, 0x00, 0x81, 0x58, 0x84, 0x87, 0x63, 0x00, 0x57, 0x84, 0x9F, 0x30, 0x00, 0x57, 0xC9, 0x19, 0x00, 0x06, 0x84, 0x0A, 0x00, 0x63, 0xA8, 0x10, 0x00, 0x51, 0xD6, 0x7A, 0x93, 0xB6, 0xDA, 0x00, 0x58, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x41, 0x82, 0x93, 0x17, 0x00, 0x72, 0x8F, 0x5D, 0x00, 0x42, 0x85, 0xBB, 0x78, 0x00, 0x36, 0x87, 0x70, 0x00, 0x12, 0xAB, 0x34, 0x00, 0x81, 0x55, 0x8F, 0x5D, 0x00, 0x09, 0x89, 0x54, 0x00, 0x54, 0x84, 0xAF, 0x10, 0x00, 0x54, 0x82, 0x32, 0x00, 0x51, 0x85, 0xDC, 0x12, 0x00, 0x69, 0x85, 0xBC, 0x7C, 0x00, 0x81, 0x2B, 0x82, 0x93, 0x17, 0x00, 0x0C, 0xC6, 0x61, 0x00, 0x72, 0x8F, 0x5D, 0x00, 0x15, 0x96, 0x5B, 0x00, 0x2A, 0xB6, 0x18, 0x00, 0x45, 0x81, 0xDC, 0x40, 0x00, 0x81, 0x58, 0x8F, 0x5D, 0x00, 0x81, 0x31, 0x84, 0xBE, 0x70, 0x00, 0x06, 0x81, 0x85, 0x7C, 0x00, 0x81, 0x34, 0x85, 0x95, 0x67, 0x00, 0x69, 0x82, 0x93, 0x17, 0x00, 0x18, 0xD6, 0x3E, 0x00, 0x30, 0x82, 0x93, 0x17, 0x00, 0x06, 0x8F, 0x5D, 0x5F, 0x5D, 0xBF, 0x39, 0x00, 0x50, 0x81, 0xA5, 0x12, 0x00, 0x33, 0x84, 0x87, 0x5A, 0x00, 0x2A, 0xBC, 0x2A, 0x00, 0x33, 0x87, 0x70, 0x00, 0x0F, 0x85, 0x89, 0x73, 0x00, 0x81, 0x5B, 0x81, 0xCC, 0x5A, 0x00, 0x81, 0x31, 0x84, 0xCE, 0x50, 0x00, 0x06, 0x5D, 0x00, 0x6C, 0x92, 0x6C, 0x00, 0x48, 0xD6, 0x7A, 0x00, 0x81, 0x31, 0x82, 0x93, 0x17, 0x00, 0x06, 0x8F, 0x5D, 0x55, 0x56, 0x96, 0x00, 0x81, 0x07, 0x85, 0xB0, 0x2B, 0x00, 0x27, 0xD3, 0x77, 0x00, 0x30, 0x87, 0x70, 0x00, 0x12, 0xAB, 0x7F, 0x00, 0x81, 0x5B, 0x81, 0xB5, 0x04, 0x00, 0x81, 0x31, 0x84, 0xDE, 0x30, 0x00, 0x06, 0x90, 0x40, 0xD9, 0xD9, 0xDD, 0x00, 0x6F, 0x82, 0x96, 0x6E, 0x00, 0x3F, 0x85, 0x95, 0x76, 0xF8, 0xFA, 0xFC, 0x00, 0x79, 0x82, 0x93, 0x17, 0x00, 0x3B, 0xD6, 0x3E, 0x63, 0x63, 0xBA, 0x00, 0x6F, 0x9F, 0x3A, 0x00, 0x21, 0x81, 0xE1, 0x57, 0x00, 0x21, 0xAF, 0x2F, 0x00, 0x2D, 0x87, 0x70, 0x00, 0x12, 0x60, 0x00, 0x81, 0x58, 0xD6, 0x41, 0x00, 0x81, 0x37, 0x84, 0xEE, 0x10, 0x00, 0x30, 0x84, 0xCE, 0x50, 0x00, 0x81, 0x07, 0x85, 0xA5, 0x56, 0xE2, 0xEB, 0xF5, 0x00, 0x81, 0x2E, 0x82, 0x93, 0x17, 0x60, 0x60, 0xC0, 0x66, 0x66, 0xC2, 0x3C, 0x3D, 0x00, 0x81, 0x02, 0x82, 0xE1, 0x6E, 0x00, 0x12, 0x9A, 0x50, 0x00, 0x1E, 0x83, 0x86, 0x57, 0x00, 0x27, 0x87, 0x70, 0x67, 0x68, 0x78, 0x00, 0x12, 0x5A, 0x00, 0x81, 0x61, 0x81, 0xD4, 0x41, 0x00, 0x81, 0x31, 0x84, 0xFD, 0x70, 0x00, 0x06, 0x84, 0xDE, 0x30, 0x00, 0x1B, 0x83, 0xDB, 0x2B, 0x00, 0x5D, 0xD9, 0x71, 0x00, 0x39, 0xD6, 0x7A, 0x00, 0x06, 0x87, 0x70, 0x00, 0x21, 0xD6, 0x3E, 0x00, 0x63, 0x82, 0x93, 0x17, 0x00, 0x27, 0xD6, 0x3E, 0x66, 0x67, 0xC2, 0x58, 0x5D, 0x7F, 0x00, 0x81, 0x10, 0xEB, 0x4A, 0x00, 0x24, 0x81, 0x8A, 0x69, 0x00, 0x21, 0x87, 0x70, 0x4D, 0x4F, 0x62, 0x00, 0x15, 0x9B, 0x21, 0x00, 0x66, 0xFB, 0x51, 0x00, 0x81, 0x07, 0x82, 0x83, 0x6D, 0x00, 0x51, 0x85, 0x8D, 0x50, 0x00, 0x81, 0x5B, 0x85, 0xC7, 0x09, 0x00, 0x33, 0x9F, 0x4F, 0xE2, 0xEB, 0xF5, 0x00, 0x75, 0x82, 0xE9, 0x55, 0x00, 0x36, 0x82, 0x93, 0x17, 0x64, 0x65, 0xBB, 0x00, 0x81, 0x0D, 0x82, 0xF1, 0x48, 0x00, 0x1B, 0xA2, 0x43, 0x00, 0x12, 0x81, 0x9A, 0x58, 0x00, 0x18, 0x87, 0x70, 0x00, 0x06, 0xD3, 0x14, 0x00, 0x18, 0x81, 0xB9, 0x5C, 0x00, 0x81, 0x6A, 0x84, 0x8F, 0x56, 0x00, 0x09, 0x82, 0x4A, 0x00, 0x4E, 0x85, 0x9D, 0x30, 0x00, 0x81, 0x5E, 0x9A, 0x08, 0x00, 0x30, 0xD6, 0x7A, 0xE2, 0xEB, 0xF5, 0x00, 0x51, 0x84, 0xFC, 0x6C, 0x00, 0x57, 0x82, 0x93, 0x17, 0x59, 0x5B, 0x9E, 0x00, 0x54, 0x82, 0xA2, 0x74, 0x00, 0x60, 0x9B, 0x4B, 0x00, 0x06, 0x81, 0xB9, 0x1D, 0x00, 0x09, 0x86, 0x80, 0x0F, 0x00, 0x09, 0x83, 0xBF, 0x36, 0x00, 0x06, 0xFA, 0x2F, 0x00, 0x1E, 0x93, 0x16, 0x00, 0x81, 0x6D, 0x81, 0xD4, 0x35, 0x00, 0x09, 0xE8, 0x11, 0x00, 0x4E, 0x85, 0xAD, 0x10, 0x00, 0x60, 0xA6, 0x50, 0x00, 0x06, 0x85, 0xF4, 0x0C, 0x00, 0x54, 0xCE, 0x60, 0x00, 0x54, 0xD6, 0x7A, 0xE2, 0xEA, 0x00, 0x05, 0x87, 0x70, 0x00, 0x69, 0x82, 0x93, 0x17, 0x00, 0x19, 0xD6, 0x3E, 0x00, 0x1C, 0x82, 0x93, 0x17, 0x50, 0x52, 0x94, 0x00, 0x81, 0x1F, 0x82, 0xF1, 0x42, 0x00, 0x51, 0x86, 0x86, 0x7B, 0x00, 0x81, 0x3D, 0x85, 0xE9, 0x58, 0x00, 0x42, 0x81, 0xD7, 0x32, 0x00, 0x3F, 0xA6, 0x62, 0x00, 0x09, 0xA7, 0x7E, 0x00, 0x5D, 0x81, 0x90, 0x06, 0x00, 0x0F, 0x85, 0xDD, 0x22, 0x00, 0x7B, 0x8B, 0x2C, 0x00, 0x2A, 0x85, 0xF4, 0x36, 0xE2, 0xEA, 0xF5, 0x00, 0x81, 0x13, 0x82, 0xE9, 0x55, 0x5F, 0x62, 0xB3, 0x55, 0x58, 0x9D, 0x49, 0x4B, 0x7F, 0x00, 0x81, 0x2E, 0x83, 0xD7, 0x66, 0x00, 0x09, 0x83, 0xB4, 0x7F, 0x00, 0x3C, 0x87, 0x6A, 0x00, 0x06, 0x85, 0xF9, 0x38, 0x00, 0x81, 0x76, 0x81, 0xBB, 0x55, 0x00, 0x09, 0xB9, 0x03, 0x00, 0x3C, 0xA1, 0x33, 0x00, 0x66, 0x85, 0xCC, 0x50, 0x00, 0x06, 0xD2, 0x6A, 0xF2, 0xF2, 0xF4, 0xA6, 0xA7, 0xB0, 0x00, 0x06, 0x93, 0x3D, 0x00, 0x06, 0x83, 0x39, 0x00, 0x06, 0x84, 0xC6, 0x78, 0xE6, 0xE6, 0xE9, 0x00, 0x72, 0xD2, 0x07, 0x00, 0x24, 0xD6, 0x7A, 0xE1, 0xEA, 0xF5, 0x00, 0x7B, 0x82, 0x93, 0x17, 0x00, 0x0C, 0xC6, 0x61, 0x5E, 0x63, 0xAD, 0x51, 0x54, 0x8F, 0x47, 0x4A, 0x78, 0x3A, 0x3C, 0x00, 0x73, 0xC6, 0x46, 0x00, 0x4E, 0x85, 0x35, 0x00, 0x36, 0xE1, 0x67, 0xD9, 0xD9, 0xDD, 0x00, 0x81, 0x7F, 0x83, 0xF6, 0x52, 0x00, 0x0C, 0xB1, 0x76, 0x00, 0x36, 0x97, 0x56, 0x00, 0x0C, 0x87, 0x6D, 0x00, 0x5D, 0xCE, 0x00, 0x00, 0x0C, 0x82, 0xE4, 0x2F, 0x00, 0x06, 0x87, 0x7C, 0x00, 0x0C, 0x83, 0x84, 0x13, 0x00, 0x78, 0xC2, 0x2D, 0x00, 0x21, 0xD6, 0x7A, 0x00, 0x07, 0x87, 0x70, 0x00, 0x4D, 0xD6, 0x3E, 0x00, 0x27, 0x8F, 0x5D, 0x68, 0x70, 0xBE, 0x59, 0x60, 0x9F, 0x4F, 0x53, 0x88, 0x41, 0x44, 0x00, 0x81, 0x53, 0x83, 0xE7, 0x2B, 0x00, 0x06, 0xA7, 0x06, 0xB3, 0xB4, 0xBC, 0x00, 0x1E, 0x97, 0x68, 0x00, 0x06, 0x81, 0xB1, 0x39, 0x8D, 0x8E, 0x9A, 0x00, 0x82, 0x08, 0x84, 0x8E, 0x28, 0x00, 0x0C, 0x81, 0x8D, 0x1E, 0x00, 0x15, 0x84, 0x86, 0x29, 0x00, 0x2A, 0x81, 0x9D, 0x7C, 0x00, 0x5D, 0x82, 0x53, 0x00, 0x0C, 0x85, 0xB5, 0x00, 0x00, 0x06, 0x83, 0xE2, 0x53, 0x00, 0x12, 0x85, 0x9D, 0x4B, 0x00, 0x81, 0x13, 0x9C, 0x5B, 0xE1, 0xEA, 0xF5, 0x00, 0x6C, 0x82, 0x93, 0x17, 0x63, 0x6C, 0xB0, 0x57, 0x5F, 0x98, 0x49, 0x4E, 0x79, 0x3E, 0x42, 0x00, 0x81, 0x6E, 0x85, 0x5F, 0x00, 0x12, 0x85, 0xD8, 0x56, 0x00, 0x82, 0x14, 0x83, 0xD7, 0x15, 0x00, 0x12, 0xD0, 0x59, 0x00, 0x27, 0x83, 0xC0, 0x7C, 0x00, 0x12, 0xAD, 0x2A, 0x00, 0x60, 0xA1, 0x7E, 0x00, 0x0C, 0xE6, 0x30, 0x00, 0x06, 0x83, 0xA3, 0x50, 0x00, 0x78, 0xE6, 0x4E, 0x00, 0x2D, 0xF6, 0x49, 0xE1, 0xEA, 0xF4, 0x00, 0x60, 0xD6, 0x3E, 0x61, 0x6B, 0xA9, 0x52, 0x59, 0x8A, 0x43, 0x47, 0x6A, 0x00, 0x57, 0x84, 0xCD, 0x52, 0x00, 0x83, 0x2D, 0x81, 0xFA, 0x07, 0x00, 0x36, 0xD9, 0x32, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x15, 0x8A, 0x22, 0x5A, 0x5C, 0x6D, 0x00, 0x0F, 0x86, 0x8B, 0x50, 0x00, 0x21, 0x82, 0xC5, 0x79, 0x00, 0x51, 0x81, 0xD4, 0x50, 0x00, 0x06, 0x81, 0x01, 0x00, 0x0F, 0x99, 0x16, 0x00, 0x81, 0x01, 0xCA, 0x23, 0x00, 0x15, 0xD6, 0x7A, 0xE9, 0xEF, 0xF7, 0x00, 0x51, 0x82, 0x93, 0x17, 0x6B, 0x7A, 0xBA, 0x5B, 0x66, 0x9A, 0x4F, 0x57, 0x82, 0x3F, 0x44, 0x63, 0x00, 0x84, 0x28, 0x87, 0x61, 0x00, 0x2A, 0xB4, 0x67, 0x00, 0x12, 0x81, 0xF3, 0x0F, 0x00, 0x0F, 0xA2, 0x04, 0x00, 0x66, 0x92, 0x39, 0x00, 0x0C, 0x83, 0x89, 0x6C, 0x00, 0x06, 0x9F, 0x31, 0x00, 0x09, 0xD8, 0x0A, 0x00, 0x06, 0x1B, 0x00, 0x81, 0x04, 0x81, 0x91, 0x04, 0x00, 0x15, 0xD6, 0x7A, 0x00, 0x45, 0x82, 0x93, 0x17, 0x65, 0x74, 0xAB, 0x59, 0x64, 0x93, 0x48, 0x4F, 0x73, 0x00, 0x51, 0x85, 0x8C, 0x40, 0x00, 0x83, 0x7B, 0x87, 0x73, 0x00, 0x06, 0x83, 0xB9, 0x7B, 0x00, 0x27, 0xC4, 0x50, 0x00, 0x6F, 0xB1, 0x58, 0x00, 0x06, 0xF2, 0x27, 0x00, 0x09, 0xC7, 0x4D, 0x00, 0x09, 0x83, 0xB1, 0x0A, 0x00, 0x06, 0x9E, 0x3C, 0x00, 0x81, 0x0A, 0xD2, 0x13, 0x00, 0x12, 0xF6, 0x49, 0x00, 0x36, 0xD6, 0x3E, 0x75, 0x89, 0xC5, 0x63, 0x72, 0xA4, 0x52, 0x5B, 0x83, 0x45, 0x4B, 0x6B, 0x00, 0x84, 0x49, 0x87, 0x61, 0x00, 0x1B, 0xA9, 0x7A, 0x00, 0x18, 0x9D, 0x11, 0x00, 0x06, 0x83, 0xF7, 0x05, 0x00, 0x75, 0x81, 0xB7, 0x1E, 0x00, 0x0C, 0xA0, 0x23, 0x00, 0x06, 0x81, 0xDD, 0x6E, 0x00, 0x09, 0x83, 0xB3, 0x3F, 0x00, 0x81, 0x10, 0xB2, 0x65, 0x00, 0x0C, 0x81, 0xAD, 0x74, 0x00, 0x2A, 0x82, 0x93, 0x17, 0x6E, 0x81, 0xB5, 0x5C, 0x6A, 0x95, 0x4E, 0x58, 0x7C, 0x00, 0x54, 0x85, 0xDB, 0x11, 0x00, 0x84, 0x25, 0x87, 0x7C, 0x00, 0x0F, 0xA9, 0x77, 0x00, 0x82, 0x20, 0x84, 0xCF, 0x6C, 0x00, 0x12, 0xE3, 0x1E, 0xF2, 0xF2, 0xF4, 0x00, 0x1B, 0x82, 0x93, 0x17, 0x7A, 0x92, 0xC8, 0x6C, 0x7F, 0xAE, 0x59, 0x66, 0x8D, 0x46, 0x4E, 0x00, 0x58, 0x86, 0x82, 0x38, 0x00, 0x84, 0x76, 0x88, 0x38, 0x00, 0x81, 0x7C, 0x81, 0x7C, 0x50, 0x57, 0x70, 0x5C, 0x6C, 0x8F, 0x6B, 0x80, 0xA8, 0x6F, 0x86, 0xB0, 0x6E, 0x84, 0xB0, 0x6E, 0x84, 0xB0, 0x64, 0x76, 0x9F, 0x51, 0x5C, 0x7D, 0x42, 0x49, 0x64, 0x00, 0x87, 0x49, 0x87, 0x64, 0x00, 0x87, 0x49, 0x87, 0x49, 0x00, 0x8F, 0x12, 0x8F, 0x12, 0x00, 0x8F, 0x30, 0x8F, 0x30, 0x00, 0x27, 0x85, 0xDC, 0x30, 0x00, 0x84, 0x10, 0x84, 0x34, 0x00, 0x06, 0x82, 0xB0, 0x70, 0x00, 0x06, 0xEA, 0x76, 0x00, 0x06, 0xD4, 0x2D, 0xB3, 0xB4, 0xBC, 0x00, 0x82, 0x02, 0xF6, 0x1F, 0x00, 0x81, 0x2B, 0x81, 0xF3, 0x3C, 0x00, 0x1E, 0x85, 0xDC, 0x30, 0x00, 0x84, 0x0A, 0xCC, 0x3D, 0x00, 0x1E, 0x81, 0xA0, 0x76, 0x00, 0x81, 0x7C, 0x81, 0x85, 0x7F, 0x00, 0x81, 0x25, 0x81, 0x9E, 0x71, 0x00, 0x27, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x3C, 0x87, 0x25, 0x00, 0x06, 0x83, 0xE7, 0x7C, 0x00, 0x42, 0x93, 0x40, 0x00, 0x2A, 0x81, 0x98, 0x7A, 0x00, 0x36, 0x82, 0x91, 0x5D, 0x00, 0x82, 0x62, 0x82, 0xCA, 0x60, 0x00, 0x2A, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x3C, 0x8F, 0x12, 0x00, 0x09, 0xE3, 0x42, 0x00, 0x3C, 0x84, 0x9D, 0x3A, 0x00, 0x1E, 0x84, 0xBC, 0x2F, 0x00, 0x72, 0x84, 0xBC, 0x41, 0x00, 0x82, 0x32, 0x84, 0xB8, 0x2B, 0x00, 0x2D, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x39, 0x87, 0x70, 0x00, 0x0F, 0x81, 0x98, 0x26, 0x00, 0x39, 0xF1, 0x77, 0x00, 0x33, 0x83, 0xCF, 0x3D, 0x00, 0x81, 0x67, 0x81, 0xBD, 0x09, 0x00, 0x15, 0x85, 0xC7, 0x06, 0x00, 0x30, 0x83, 0xC9, 0x79, 0x00, 0x57, 0x83, 0xCA, 0x05, 0x00, 0x39, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x42, 0x8F, 0x5D, 0x00, 0x3C, 0x81, 0xC1, 0x4C, 0x00, 0x12, 0x81, 0x81, 0x0C, 0x00, 0x12, 0x81, 0x9D, 0x3D, 0x73, 0x75, 0x83, 0x00, 0x12, 0x9F, 0x5B, 0x00, 0x81, 0x6A, 0x83, 0xA1, 0x2A, 0x00, 0x09, 0xE3, 0x60, 0x00, 0x42, 0x81, 0xAF, 0x6D, 0x00, 0x81, 0x04, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x45, 0x81, 0x8A, 0x78, 0x00, 0x36, 0x81, 0x92, 0x35, 0x00, 0x12, 0x97, 0x4A, 0x00, 0x1B, 0x93, 0x7C, 0x00, 0x12, 0x81, 0x81, 0x33, 0x00, 0x81, 0x64, 0x81, 0xB5, 0x28, 0x00, 0x4E, 0x82, 0x81, 0x65, 0x00, 0x81, 0x04, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x36, 0x87, 0x70, 0x00, 0x0C, 0x81, 0x80, 0x3B, 0x00, 0x39, 0x93, 0x31, 0x00, 0x0F, 0x8F, 0x5D, 0x00, 0x21, 0x48, 0x00, 0x0F, 0x82, 0xB7, 0x1A, 0x00, 0x81, 0x5E, 0x94, 0x29, 0x00, 0x12, 0x81, 0xBA, 0x4B, 0x00, 0x06, 0x84, 0x80, 0x59, 0x00, 0x81, 0x10, 0x97, 0x50, 0x00, 0x30, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x36, 0xBE, 0x26, 0x00, 0x45, 0x82, 0xBA, 0x02, 0x00, 0x0F, 0x83, 0xD8, 0x10, 0x00, 0x24, 0xAE, 0x79, 0x00, 0x0F, 0x82, 0xB3, 0x0D, 0x00, 0x81, 0x5B, 0x8F, 0x63, 0x00, 0x0F, 0x82, 0xAD, 0x07, 0x00, 0x81, 0x1C, 0x81, 0xF6, 0x03, 0x00, 0x2D, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x3F, 0x97, 0x4D, 0x00, 0x39, 0x83, 0xDD, 0x09, 0x00, 0x0F, 0x88, 0x35, 0x00, 0x2A, 0x8C, 0x7E, 0x00, 0x0F, 0x84, 0xE4, 0x0F, 0x00, 0x81, 0x5B, 0x85, 0x8C, 0x25, 0x00, 0x81, 0x2B, 0x81, 0xD6, 0x4C, 0x00, 0x2A, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x33, 0x87, 0x70, 0x00, 0x0C, 0x8C, 0x7B, 0x00, 0x39, 0x86, 0x72, 0x00, 0x0F, 0x97, 0x4D, 0x00, 0x2A, 0x93, 0x76, 0x00, 0x0C, 0x8F, 0x63, 0x00, 0x5D, 0x83, 0xE5, 0x77, 0x00, 0x81, 0x04, 0xAA, 0x0C, 0x00, 0x81, 0x2B, 0x9D, 0x7D, 0x00, 0x27, 0x85, 0xDC, 0x30, 0x00, 0x83, 0x33, 0x87, 0x70, 0x00, 0x0C, 0xC6, 0x1C, 0x00, 0x39, 0x8B, 0x44, 0x00, 0x0C, 0x88, 0x35, 0x00, 0x30, 0xAB, 0x43, 0x00, 0x0C, 0x8C, 0x4B, 0x00, 0x81, 0x52, 0xBF, 0x0C, 0x00, 0x0C, 0x82, 0xE0, 0x7F, 0x00, 0x85, 0x05, 0xE2, 0x17, 0x00, 0x45, 0x83, 0xCF, 0x4F, 0x00, 0x0C, 0x87, 0x34, 0x00, 0x30, 0x8D, 0x46, 0x00, 0x0C, 0x88, 0x2C, 0x00, 0x81, 0x52, 0xAB, 0x7F, 0x00, 0x09, 0x81, 0x5E, 0x00, 0x81, 0x2E, 0x89, 0x4B, 0x00, 0x06, 0x81, 0xD0, 0x46, 0x00, 0x0C, 0x82, 0xE2, 0x27, 0x00, 0x83, 0x45, 0xE6, 0x39, 0x00, 0x45, 0x83, 0xB7, 0x7C, 0x00, 0x0F, 0x88, 0x35, 0x00, 0x30, 0x85, 0x59, 0x00, 0x0C, 0xB5, 0x26, 0x00, 0x81, 0x52, 0x9F, 0x43, 0x00, 0x81, 0x31, 0x82, 0xD4, 0x2B, 0x00, 0x15, 0x84, 0xA2, 0x51, 0x00, 0x83, 0x48, 0xD6, 0x4D, 0x00, 0x42, 0x82, 0xF2, 0x10, 0x00, 0x42, 0xA7, 0x72, 0x00, 0x0C, 0x88, 0x74, 0x00, 0x81, 0x4F, 0x95, 0x75, 0x00, 0x81, 0x34, 0x82, 0x83, 0x1F, 0x00, 0x06, 0x84, 0xB1, 0x15, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0x82, 0x95, 0x0D, 0x00, 0x09, 0xB2, 0x35, 0x00, 0x1B, 0x84, 0xB9, 0x38, 0x00, 0x83, 0x36, 0xD6, 0x47, 0x00, 0x39, 0xAC, 0x3B, 0x00, 0x0C, 0xF2, 0x3F, 0x00, 0x33, 0x87, 0x31, 0x00, 0x0C, 0x84, 0x87, 0x69, 0x00, 0x81, 0x4F, 0xA7, 0x33, 0x00, 0x54, 0x82, 0xA3, 0x30, 0x00, 0x63, 0x82, 0x85, 0x1E, 0x00, 0x09, 0xA7, 0x21, 0x00, 0x83, 0x51, 0xC6, 0x70, 0x00, 0x0C, 0xD5, 0x5B, 0x00, 0x39, 0x87, 0x70, 0x00, 0x0C, 0xB6, 0x54, 0x00, 0x36, 0x45, 0x00, 0x81, 0x58, 0x83, 0x99, 0x40, 0x00, 0x5D, 0x82, 0xBA, 0x2C, 0x00, 0x63, 0x83, 0xB1, 0x10, 0x00, 0x83, 0x51, 0xD6, 0x50, 0x00, 0x0C, 0x87, 0x2B, 0x00, 0x39, 0x9B, 0x1E, 0x00, 0x42, 0x83, 0xEF, 0x51, 0x00, 0x83, 0x09, 0x87, 0x70, 0x00, 0x83, 0x60, 0xE6, 0x30, 0x00, 0x42, 0x83, 0xB1, 0x10, 0x00, 0x42, 0x83, 0xE0, 0x72, 0x00, 0x81, 0x64, 0x87, 0x70, 0x00, 0x81, 0x28, 0xBD, 0x43, 0x00, 0x06, 0x81, 0xFF, 0x5A, 0x00, 0x83, 0x5A, 0xF6, 0x10, 0x00, 0x42, 0x87, 0x70, 0x00, 0x0F, 0xD6, 0x14, 0x00, 0x82, 0x0E, 0x83, 0xC0, 0x70, 0x00, 0x2D, 0x85, 0x85, 0x60, 0x00, 0x81, 0x0A, 0xC0, 0x2E, 0x00, 0x09, 0xB2, 0x62, 0x00, 0x83, 0x51, 0x81, 0x85, 0x70, 0x00, 0x42, 0x87, 0x70, 0x00, 0x45, 0x83, 0xA8, 0x5E, 0x00, 0x81, 0x5B, 0x83, 0xB9, 0x00, 0x00, 0x57, 0x85, 0x9C, 0x5F, 0x00, 0x5D, 0xD0, 0x0E, 0x00, 0x09, 0x81, 0x90, 0x78, 0x00, 0x0F, 0x81, 0x9D, 0x40, 0x00, 0x83, 0x42, 0x81, 0x95, 0x50, 0x00, 0x42, 0xA6, 0x6B, 0x00, 0x45, 0x83, 0xA8, 0x5E, 0x00, 0x81, 0x5B, 0x87, 0x70, 0x00, 0x09, 0x84, 0xDF, 0x1C, 0x00, 0x81, 0x2B, 0x99, 0x04, 0x00, 0x06, 0x83, 0xB8, 0x6B, 0x00, 0x06, 0x81, 0x3A, 0xB3, 0xB4, 0xBC, 0x00, 0x09, 0x81, 0x43, 0x00, 0x83, 0x42, 0x81, 0xA5, 0x30, 0x00, 0x42, 0xB7, 0x10, 0x00, 0x0C, 0xA7, 0x2D, 0x00, 0x39, 0x93, 0x6D, 0x00, 0x81, 0x5B, 0x87, 0x70, 0x00, 0x09, 0xC1, 0x1D, 0x00, 0x81, 0x2B, 0x96, 0x0A, 0x00, 0x0C, 0x84, 0xE9, 0x77, 0x00, 0x09, 0xDA, 0x24, 0x00, 0x83, 0x45, 0x81, 0xAD, 0x1D, 0x00, 0x0C, 0x87, 0x70, 0x00, 0x33, 0x8F, 0x1E, 0x00, 0x0F, 0x84, 0xC6, 0x24, 0x00, 0x39, 0x83, 0xB5, 0x23, 0x00, 0x81, 0x5E, 0x83, 0xD0, 0x50, 0x00, 0x06, 0x8A, 0x13, 0x00, 0x81, 0x31, 0x96, 0x0D, 0x00, 0x48, 0x83, 0xB1, 0x10, 0x00, 0x83, 0x0C, 0x87, 0x70, 0x00, 0x0C, 0xA6, 0x6E, 0x00, 0x33, 0x9E, 0x7E, 0x00, 0x0F, 0xEE, 0x17, 0x00, 0x82, 0x17, 0x84, 0x8F, 0x50, 0x00, 0x09, 0x82, 0x26, 0x00, 0x81, 0x22, 0xA7, 0x36, 0xA6, 0xA7, 0xB0, 0x00, 0x81, 0x5E, 0x82, 0xD3, 0x2A, 0x00, 0x82, 0x05, 0x81, 0xB1, 0x00, 0x00, 0x39, 0x87, 0x31, 0x00, 0x0C, 0xE5, 0x6B, 0x00, 0x82, 0x1D, 0x83, 0xD0, 0x50, 0x00, 0x63, 0x82, 0xC2, 0x2B, 0x00, 0x48, 0x89, 0x1B, 0x00, 0x83, 0x45, 0x81, 0x8D, 0x45, 0x00, 0x27, 0x9E, 0x3C, 0x00, 0x30, 0xAF, 0x23, 0x00, 0x0C, 0x9F, 0x3D, 0x00, 0x39, 0x8D, 0x3D, 0x00, 0x0C, 0x88, 0x35, 0x00, 0x81, 0x58, 0x8C, 0x5D, 0x00, 0x06, 0x85, 0x84, 0x20, 0x00, 0x81, 0x22, 0x81, 0x64, 0x00, 0x06, 0xAF, 0x20, 0x00, 0x81, 0x6A, 0x82, 0xE5, 0x4E, 0x00, 0x82, 0x2C, 0x81, 0x85, 0x70, 0x00, 0x48, 0x81, 0x95, 0x0E, 0x00, 0x45, 0xFF, 0x01, 0x00, 0x81, 0x2E, 0x82, 0xC2, 0x73, 0x00, 0x06, 0x86, 0x8A, 0x2E, 0x00, 0x81, 0x13, 0x86, 0x54, 0x00, 0x09, 0x84, 0xD7, 0x62, 0x00, 0x0C, 0x85, 0x8F, 0x6D, 0x00, 0x48, 0x83, 0xC0, 0x70, 0x00, 0x83, 0x15, 0x81, 0x95, 0x50, 0x00, 0x2A, 0x85, 0x05, 0x00, 0x0C, 0xAB, 0x43, 0x00, 0x39, 0xB4, 0x70, 0x00, 0x45, 0xA7, 0x72, 0x00, 0x81, 0x3A, 0x81, 0xA5, 0x36, 0x00, 0x09, 0x81, 0xA5, 0x33, 0x00, 0x15, 0x82, 0xE9, 0x0D, 0x00, 0x15, 0x15, 0x00, 0x09, 0x09, 0x00, 0x75, 0x81, 0xAE, 0x42, 0x00, 0x83, 0x30, 0x84, 0xC2, 0x11, 0x00, 0x21, 0x83, 0xC0, 0x70, 0x00, 0x27, 0x8F, 0x63, 0x00, 0x48, 0x83, 0xB8, 0x3E, 0x00, 0x0F, 0x83, 0xC9, 0x5E, 0x00, 0x82, 0x2C, 0x84, 0xC5, 0x14, 0x00, 0x66, 0x82, 0xCE, 0x31, 0x00, 0x78, 0x82, 0xF2, 0x10, 0x00, 0x82, 0x68, 0xEE, 0x26, 0x00, 0x24, 0x96, 0x55, 0x00, 0x12, 0x85, 0x86, 0x0A, 0x00, 0x39, 0x8C, 0x6F, 0x00, 0x0C, 0x81, 0x82, 0x5B, 0x00, 0x81, 0x61, 0xDB, 0x1C, 0x00, 0x15, 0x83, 0x93, 0x55, 0x00, 0x81, 0x0D, 0x87, 0x70, 0x00, 0x83, 0x75, 0x81, 0x95, 0x56, 0x00, 0x1E, 0x87, 0x73, 0x00, 0x12, 0x83, 0x91, 0x71, 0x00, 0x39, 0xAE, 0x55, 0x00, 0x0F, 0x97, 0x4D, 0x00, 0x81, 0x5E, 0xDB, 0x1C, 0x00, 0x12, 0x96, 0x2B, 0x00, 0x09, 0x85, 0xFA, 0x57, 0x00, 0x1E, 0x83, 0x98, 0x33, 0x00, 0x18, 0x18, 0x00, 0x84, 0x3D, 0x81, 0x9D, 0x49, 0x00, 0x12, 0x85, 0x0E, 0x00, 0x15, 0x85, 0xA5, 0x14, 0x00, 0x15, 0x8D, 0x22, 0x00, 0x39, 0x8F, 0x5D, 0x00, 0x0F, 0x90, 0x58, 0x00, 0x81, 0x5B, 0xAC, 0x14, 0x00, 0x0C, 0x82, 0x5F, 0x00, 0x06, 0x82, 0xC9, 0x41, 0x00, 0x81, 0x0A, 0xA1, 0x2A, 0x00, 0x06, 0x9B, 0x1B, 0x00, 0x0F, 0x83, 0x45, 0x5A, 0x5C, 0x6D, 0x00, 0x83, 0x60, 0x81, 0xFB, 0x6E, 0x00, 0x15, 0x81, 0xE3, 0x6B, 0x00, 0x09, 0x84, 0xCA, 0x55, 0x00, 0x06, 0x81, 0xC8, 0x5F, 0x00, 0x4B, 0x84, 0xA4, 0x3B, 0x00, 0x3C, 0x83, 0xD1, 0x45, 0x00, 0x81, 0x3A, 0x81, 0xA0, 0x25, 0x00, 0x30, 0x82, 0xF2, 0x0D, 0x00, 0x78, 0x87, 0x70, 0x00, 0x83, 0x63, 0x90, 0x43, 0x00, 0x33, 0x83, 0xAC, 0x0E, 0x00, 0x3C, 0x81, 0xA3, 0x07, 0x00, 0x0F, 0x8F, 0x5D, 0x00, 0x81, 0x5B, 0xB3, 0x69, 0x00, 0x09, 0xA1, 0x6C, 0x00, 0x81, 0x16, 0x89, 0x54, 0x00, 0x83, 0x78, 0x87, 0x70, 0x00, 0x2D, 0x83, 0x94, 0x32, 0x00, 0x3F, 0x81, 0xF3, 0x48, 0x00, 0x0F, 0x9F, 0x3A, 0x00, 0x81, 0x5B, 0x84, 0x5B, 0x00, 0x09, 0xC1, 0x26, 0x00, 0x21, 0x86, 0x82, 0x41, 0x00, 0x84, 0x73, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xFF, 0x75, 0x00, 0x21, 0x84, 0xBC, 0x02, 0x00, 0x3C, 0x85, 0x3E, 0x00, 0x0F, 0x90, 0x49, 0x00, 0x81, 0x64, 0x81, 0xDC, 0x3A, 0x00, 0x81, 0x19, 0x81, 0x8D, 0x63, 0x00, 0x84, 0x01, 0x87, 0x70, 0x00, 0x06, 0x8F, 0x69, 0x00, 0x15, 0x85, 0xFB, 0x5B, 0xD9, 0xD9, 0xDD, 0xA6, 0xA7, 0xB0, 0x00, 0x3F, 0xBB, 0x05, 0x00, 0x0F, 0xA8, 0x1C, 0x00, 0x81, 0x5E, 0x84, 0x58, 0x00, 0x81, 0x22, 0xEE, 0x1D, 0x00, 0x06, 0x87, 0x70, 0x00, 0x0F, 0xCE, 0x4E, 0x00, 0x06, 0x81, 0x85, 0x5E, 0x00, 0x83, 0x54, 0xCE, 0x60, 0x00, 0x27, 0xF2, 0x18, 0x00, 0x4B, 0x95, 0x0C, 0x00, 0x06, 0x82, 0xF8, 0x01, 0x00, 0x69, 0x85, 0xDC, 0x30, 0x00, 0x81, 0x04, 0xB9, 0x69, 0x00, 0x81, 0x1C, 0xA9, 0x0E, 0x00, 0x0F, 0xCA, 0x3B, 0x00, 0x83, 0x60, 0xCE, 0x60, 0x00, 0x7B, 0x86, 0x0C, 0x00, 0x78, 0x82, 0xF7, 0x63, 0x00, 0x81, 0x3D, 0x83, 0xFF, 0x70, 0x00, 0x5A, 0xFD, 0x68, 0x00, 0x24, 0xD7, 0x45, 0x00, 0x84, 0x2B, 0x82, 0xBB, 0x0F, 0x00, 0x81, 0x7C, 0x81, 0xD7, 0x2F, 0x00, 0x83, 0x63, 0x96, 0x07, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x8B, 0x74, 0x8F, 0x60, 0x00, 0x81, 0x31, 0x81, 0xBD, 0x00, 0x00, 0x86, 0x42, 0x87, 0x73, 0x00, 0x81, 0x67, 0xEF, 0x7B, 0x00, 0x86, 0x09, 0x87, 0x70, 0x00, 0x06, 0xC6, 0x70, 0x00, 0x83, 0x4E, 0x82, 0xD8, 0x7A, 0x00, 0x84, 0x25, 0x83, 0xC8, 0x54, 0x00, 0x87, 0x67, 0x9F, 0x43, 0x00, 0x09, 0x82, 0xA3, 0x30, 0x00, 0x85, 0x05, 0x82, 0x9B, 0x40, 0x00, 0x82, 0x6E, 0x81, 0x80, 0x5C, 0x00, 0x83, 0x48, 0x82, 0xB1, 0x53, 0x00, 0x84, 0x22, 0x87, 0x73, 0x00, 0x06, 0xE8, 0x20, 0x00, 0x83, 0x45, 0x81, 0xDB, 0x03, 0x00, 0x84, 0x2E, 0x97, 0x56, 0x00, 0x66, 0x83, 0xE7, 0x67, 0x00, 0x87, 0x07, 0xBF, 0x0C, 0x00, 0x09, 0xF8, 0x06, 0x00, 0x15, 0x81, 0x98, 0x2C, 0x00, 0x87, 0x55, 0x8F, 0x66, 0x00, 0x0C, 0xF8, 0x0C, 0xD9, 0xD9, 0xDD, 0x00, 0x09, 0x81, 0xBC, 0x7A, 0x00, 0x83, 0x5D, 0x81, 0xD3, 0x43, 0x00, 0x83, 0x72, 0xC6, 0x70, 0x00, 0x54, 0x85, 0x83, 0x52, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x8F, 0x06, 0x8F, 0x60, 0x00, 0xAD, 0x54, 0x83, 0xED, 0x0D, 0x00, 0xA9, 0x4A, 0xA9, 0x4A, 0x00, 0x06, 0xF6, 0x52, 0x00, 0x83, 0x45, 0x83, 0xDF, 0x35, 0x00, 0x84, 0x2B, 0x81, 0xB5, 0x5E, 0x00, 0x81, 0x5E, 0x81, 0xEE, 0x55, 0x00, 0x85, 0x44, 0xEE, 0x20, 0x00, 0x48, 0x81, 0xCC, 0x60, 0x00, 0x09, 0x81, 0xCD, 0x31, 0x00, 0x83, 0x5D, 0x82, 0xE1, 0x56, 0x00, 0x84, 0x0A, 0x87, 0x70, 0x00, 0x87, 0x22, 0x81, 0xC5, 0x41, 0x00, 0x51, 0x87, 0x70, 0x00, 0x09, 0x82, 0xCD, 0x12, 0x00, 0x87, 0x67, 0x87, 0x70, 0x00, 0x87, 0x1F, 0x81, 0xEC, 0x74, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x51, 0x87, 0x70, 0x00, 0x09, 0x82, 0xB3, 0x61, 0x00, 0x87, 0x67, 0x87, 0x70, 0x00, 0x09, 0x82, 0xEA, 0x5F, 0x00, 0x87, 0x16, 0x81, 0xB5, 0x43, 0x00, 0x4E, 0x87, 0x70, 0x00, 0x09, 0x81, 0xCD, 0x28, 0x00, 0x87, 0x64, 0xAF, 0x20, 0x00, 0x0C, 0x84, 0xD9, 0x16, 0x00, 0x87, 0x5E, 0xBF, 0x00, 0x00, 0x06, 0x84, 0xED, 0x1E, 0x00, 0x09, 0x82, 0xDB, 0x08, 0x00, 0x87, 0x07, 0xCE, 0x60, 0x00, 0x33, 0x84, 0xD0, 0x4C, 0x00, 0x36, 0x81, 0xBC, 0x7A, 0x00, 0x87, 0x07, 0x81, 0xF4, 0x58, 0x00, 0x63, 0x87, 0x70, 0x00, 0x83, 0x4B, 0x84, 0xAE, 0x18, 0x00, 0x84, 0x1F, 0x87, 0x70, 0xCC, 0xCD, 0xD2, 0x00, 0x06, 0x84, 0x8E, 0x64, 0x00, 0x87, 0x25, 0x81, 0xE4, 0x30, 0x00, 0x87, 0x70, 0x82, 0xB3, 0x10, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x8F, 0x60, 0x8F, 0x60, 0x00, 0x87, 0x6A, 0x87, 0x70, 0x00, 0x06, 0x83, 0x90, 0x19, 0x00, 0x87, 0x6A, 0x82, 0xB3, 0x0A, 0x00, 0xCE, 0x72, 0x81, 0xF3, 0x51, 0x00, 0x09, 0x85, 0xA3, 0x7B, 0x00, 0x87, 0x61, 0x82, 0xD2, 0x50, 0x00, 0x24, 0x83, 0xF2, 0x69, 0x00, 0x87, 0x46, 0x87, 0x70, 0x00, 0x2D, 0x84, 0x82, 0x49, 0x00, 0x87, 0x43, 0x87, 0x70, 0x00, 0x0C, 0x87, 0x6D, 0xE6, 0xE6, 0xE9, 0x8D, 0x8E, 0x9A, 0x00, 0x12, 0x83, 0xFE, 0x60, 0x00, 0x15, 0xF6, 0x37, 0x00, 0x0C, 0x84, 0xED, 0x1B, 0x00, 0x87, 0x19, 0x81, 0xBC, 0x74, 0x00, 0x1B, 0x84, 0x81, 0x60, 0x00, 0x18, 0x82, 0x93, 0x0B, 0x00, 0x18, 0x87, 0x70, 0x00, 0x09, 0x81, 0xDC, 0x34, 0x00, 0x87, 0x28, 0x83, 0xB1, 0x55, 0x00, 0x0C, 0x85, 0xDC, 0x30, 0x00, 0x1B, 0xFE, 0x06, 0x00, 0x1E, 0x87, 0x70, 0x00, 0x0C, 0x84, 0xD6, 0x7F, 0x00, 0x87, 0x1F, 0x83, 0xD1, 0x1B, 0x00, 0x09, 0x82, 0x83, 0x1F, 0x00, 0x1E, 0x87, 0x28, 0x00, 0x21, 0x87, 0x70, 0x00, 0x0C, 0x81, 0xEC, 0x1A, 0x00, 0x87, 0x1C, 0x83, 0xA9, 0x62, 0x00, 0x09, 0x9E, 0x7E, 0x00, 0x1E, 0x81, 0xD4, 0x02, 0x00, 0x24, 0x87, 0x70, 0x00, 0x09, 0x84, 0xB1, 0x45, 0x00, 0x87, 0x1C, 0x83, 0xD9, 0x0E, 0x00, 0x27, 0x84, 0xA1, 0x14, 0x00, 0x27, 0x87, 0x70, 0x00, 0x09, 0x82, 0xA3, 0x30, 0x00, 0x87, 0x16, 0x8F, 0x63, 0x00, 0x2A, 0x83, 0xF8, 0x00, 0x00, 0x27, 0x87, 0x70, 0x00, 0x09, 0x83, 0xC9, 0x2B, 0x00, 0x87, 0x16, 0x9F, 0x46, 0x00, 0x2A, 0x85, 0xC4, 0x60, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x06, 0xAF, 0x6E, 0x00, 0x87, 0x16, 0x97, 0x53, 0x00, 0x2A, 0x82, 0x9A, 0x6C, 0x00, 0x2A, 0x87, 0x70, 0x00, 0x09, 0x54, 0x00, 0x87, 0x70, 0x87, 0x70, 0x00, 0x87, 0x13, 0x83, 0xE0, 0x7B, 0x00, 0x5D, 0x87, 0x70, 0x00, 0x87, 0x13, 0x82, 0xA3, 0x30, 0x00, 0x09, 0x84, 0xE0, 0x17, 0x00, 0x21, 0x81, 0xC4, 0x70, 0x00, 0x87, 0x46, 0x87, 0x70, 0x00, 0x2A, 0x81, 0xD4, 0x50, 0x00, 0x87, 0x49, 0x87, 0x70, 0x00, 0x06, 0x82, 0x9A, 0x75, 0x00, 0x21, 0xBF, 0x00, 0x00, 0x06, 0xC6, 0x49, 0x00, 0x24, 0x85, 0xE4, 0x47, 0x00, 0x09, 0x84, 0x98, 0x11, 0x00, 0x87, 0x16, 0x82, 0x83, 0x7C, 0x00, 0x09, 0x82, 0xAA, 0x52, 0x00, 0x1E, 0x87, 0x1F, 0x00, 0x2A, 0xB6, 0x66, 0x00, 0x09, 0x82, 0xBB, 0x00, 0x00, 0x87, 0x16, 0xCE, 0x60, 0x00, 0x09, 0xDD, 0x75, 0x00, 0x1E, 0x9F, 0x43, 0x00, 0x09, 0x27, 0x00, 0x21, 0x82, 0xAA, 0x79, 0x00, 0x27, 0x90, 0x31, 0x00, 0x86, 0x7B, 0x87, 0x73, 0x00, 0x24, 0xF5, 0x4B, 0x00, 0x09, 0x85, 0xB8, 0x06, 0x00, 0x1E, 0x9F, 0x43, 0x00, 0x09, 0x97, 0x4D, 0x00, 0x87, 0x1C, 0x83, 0x89, 0x63, 0x00, 0x09, 0x97, 0x53, 0x00, 0x1E, 0xA6, 0x62, 0x00, 0x09, 0x85, 0x86, 0x0A, 0x00, 0x18, 0xBE, 0x59, 0x00, 0x09, 0xF6, 0x13, 0x00, 0x83, 0x60, 0x85, 0xDB, 0x53, 0x00, 0x83, 0x48, 0xDE, 0x46, 0x00, 0x1E, 0x85, 0x9F, 0x5F, 0x00, 0x09, 0xAE, 0x79, 0x00, 0x15, 0x84, 0x9F, 0x54, 0x00, 0x06, 0x86, 0x82, 0x77, 0x00, 0x87, 0x28, 0x82, 0x84, 0x3E, 0x00, 0x09, 0xA6, 0x65, 0x00, 0x1E, 0x81, 0x95, 0x14, 0x00, 0x0C, 0x85, 0xCC, 0x6B, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x85, 0x8C, 0x64, 0xA6, 0xA7, 0xB0, 0x00, 0x0C, 0x85, 0xC7, 0x4E, 0x00, 0x3C, 0x85, 0xA8, 0x14, 0x00, 0x86, 0x6C, 0x81, 0x8D, 0x66, 0x00, 0x06, 0x87, 0x34, 0x00, 0x27, 0xFD, 0x62, 0x00, 0x54, 0x85, 0xA8, 0x14, 0x00, 0x86, 0x72, 0xCE, 0x6C, 0x00, 0x27, 0xC6, 0x22, 0x73, 0x75, 0x83, 0x00, 0x0F, 0x85, 0xD7, 0x1F, 0x00, 0x06, 0x97, 0x65, 0x00, 0x87, 0x5E, 0x82, 0x9C, 0x05, 0x5A, 0x5C, 0x6D, 0x80, 0x81, 0x8F, 0x00, 0x83, 0x69, 0x85, 0xA4, 0x16, 0x00, 0x8D, 0x13, 0x81, 0xD6, 0x1C}; +static const uint8_t s_splash[] = {0x00, 0x34, 0x36, 0x4B, 0x34, 0x36, 0x4B, 0x00, 0x06, 0x06, 0x00, 0x0C, 0x0C, 0x00, 0x18, 0x18, 0x00, 0x30, 0x30, 0x00, 0x60, 0x60, 0x00, 0x81, 0x40, 0x81, 0x40, 0x00, 0x83, 0x00, 0x83, 0x00, 0x00, 0x86, 0x00, 0x86, 0x00, 0x00, 0x8C, 0x00, 0x8C, 0x00, 0x00, 0x84, 0x46, 0x84, 0x46, 0x4D, 0x4F, 0x62, 0x8D, 0x8E, 0x9A, 0xB3, 0xB4, 0xBC, 0xCC, 0xCD, 0xD2, 0xA6, 0xA7, 0xB0, 0x00, 0x75, 0x81, 0x04, 0x67, 0x68, 0x78, 0xC0, 0xC0, 0xC7, 0xF2, 0xF2, 0xF4, 0xFF, 0xFF, 0xFF, 0x00, 0x09, 0x15, 0x73, 0x75, 0x83, 0x00, 0x86, 0x24, 0x87, 0x40, 0x5A, 0x5C, 0x6D, 0xCC, 0xCD, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, 0xCC, 0xCD, 0xD2, 0x00, 0x15, 0x27, 0x00, 0x5D, 0x81, 0x07, 0xB3, 0xB4, 0xBC, 0xF2, 0xF2, 0xF4, 0xA6, 0xA7, 0xB0, 0x67, 0x68, 0x78, 0x00, 0x0C, 0x87, 0x46, 0xB3, 0xB4, 0xBC, 0xB3, 0xB4, 0xBC, 0x00, 0x86, 0x1E, 0x87, 0x43, 0x80, 0x81, 0x8F, 0x00, 0x06, 0x87, 0x3A, 0x00, 0x06, 0x86, 0x42, 0x80, 0x81, 0x8F, 0xD9, 0xD9, 0xDD, 0x00, 0x12, 0x87, 0x46, 0x5A, 0x5C, 0x6D, 0xF2, 0xF2, 0xF4, 0x00, 0x5A, 0x86, 0x4E, 0x9A, 0x9B, 0xA5, 0xD9, 0xD9, 0xDD, 0x41, 0x43, 0x56, 0x00, 0x06, 0x0F, 0x00, 0x0C, 0x87, 0x46, 0x41, 0x43, 0x56, 0xD9, 0xD9, 0xDD, 0x67, 0x68, 0x78, 0x00, 0x86, 0x18, 0x87, 0x43, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0x87, 0x43, 0x9A, 0x9B, 0xA5, 0x00, 0x09, 0x15, 0xCC, 0xCD, 0xD2, 0x00, 0x12, 0x87, 0x46, 0x00, 0x06, 0x86, 0x4B, 0xFF, 0xFF, 0xFF, 0x8D, 0x8E, 0x9A, 0x00, 0x51, 0x81, 0x07, 0x41, 0x43, 0x56, 0xF2, 0xF2, 0xF4, 0x4D, 0x4F, 0x62, 0x00, 0x09, 0x12, 0x00, 0x0C, 0x87, 0x46, 0x00, 0x06, 0x88, 0x6B, 0xC0, 0xC0, 0xC7, 0x00, 0x86, 0x15, 0x87, 0x43, 0x00, 0x06, 0x95, 0x39, 0xF2, 0xF2, 0xF4, 0x00, 0x0F, 0x96, 0x2B, 0x00, 0x15, 0x87, 0x46, 0x00, 0x06, 0x9E, 0x39, 0xF2, 0xF2, 0xF4, 0xF2, 0xF2, 0xF4, 0x00, 0x09, 0x8E, 0x32, 0x00, 0x4E, 0x9E, 0x0F, 0x00, 0x0C, 0x12, 0x00, 0x0F, 0x87, 0x46, 0x41, 0x43, 0x56, 0xE6, 0xE6, 0xE9, 0x00, 0x86, 0x15, 0x87, 0x46, 0xE6, 0xE6, 0xE9, 0xFF, 0xFF, 0xFF, 0x00, 0x12, 0x95, 0x2A, 0x00, 0x18, 0x87, 0x46, 0x00, 0x06, 0x95, 0x78, 0xFF, 0xFF, 0xFF, 0x80, 0x81, 0x8F, 0x00, 0x51, 0x96, 0x4F, 0x00, 0x0C, 0x90, 0x0D, 0x00, 0x12, 0x87, 0x46, 0x00, 0x12, 0x12, 0x00, 0x86, 0x0C, 0x9E, 0x0F, 0x00, 0x15, 0x9D, 0x68, 0x00, 0x1B, 0x87, 0x46, 0x4D, 0x4F, 0x62, 0xFF, 0xFF, 0xFF, 0x00, 0x51, 0x95, 0x5D, 0x8D, 0x8E, 0x9A, 0x00, 0x0F, 0xAE, 0x16, 0x00, 0x86, 0x27, 0x8F, 0x0C, 0xC0, 0xC0, 0xC7, 0xFF, 0xFF, 0xFF, 0x00, 0x0C, 0x9D, 0x0B, 0x00, 0x24, 0x87, 0x46, 0x00, 0x06, 0x8F, 0x42, 0xF2, 0xF2, 0xF4, 0x00, 0x51, 0xAE, 0x25, 0x00, 0x0F, 0x87, 0x25, 0x00, 0x12, 0x9E, 0x18, 0x00, 0x86, 0x15, 0xAD, 0x27, 0xF2, 0xF2, 0xF4, 0x00, 0x18, 0x8D, 0x5E, 0x00, 0x1E, 0x87, 0x46, 0x00, 0x06, 0xB5, 0x14, 0x00, 0x51, 0x81, 0x10, 0xCC, 0xCD, 0xD2, 0x00, 0x0C, 0x97, 0x29, 0x00, 0x0F, 0xAD, 0x24, 0xE6, 0xE6, 0xE9, 0x00, 0x86, 0x15, 0xAD, 0x24, 0x00, 0x18, 0xBC, 0x15, 0x00, 0x21, 0x87, 0x46, 0xB3, 0xB4, 0xBC, 0xFF, 0xFF, 0xFF, 0x00, 0x51, 0xA5, 0x61, 0x00, 0x06, 0xB5, 0x4A, 0x00, 0x09, 0xAE, 0x01, 0x00, 0x09, 0x87, 0x46, 0x4D, 0x4F, 0x62, 0xCC, 0xCD, 0xD2, 0x00, 0x86, 0x15, 0x8F, 0x09, 0x5A, 0x5C, 0x6D, 0xFF, 0xFF, 0xFF, 0x00, 0x18, 0xCB, 0x21, 0x00, 0x1E, 0x87, 0x46, 0x00, 0x06, 0x97, 0x0B, 0x00, 0x57, 0x81, 0x16, 0xE6, 0xE6, 0xE9, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0x88, 0x29, 0x9A, 0x9B, 0xA5, 0x00, 0x06, 0xCB, 0x48, 0x00, 0x78, 0xCC, 0x49, 0x00, 0x85, 0x20, 0x87, 0x46, 0x41, 0x43, 0x56, 0x00, 0x1B, 0xA5, 0x25, 0x00, 0x75, 0x96, 0x52, 0x00, 0x0F, 0x9E, 0x03, 0x00, 0x06, 0x81, 0x04, 0x9A, 0x9B, 0xA5, 0x00, 0x15, 0x9F, 0x3A, 0x00, 0x86, 0x42, 0x96, 0x52, 0x00, 0x1B, 0x9E, 0x51, 0x00, 0x86, 0x72, 0xE1, 0x7C, 0x00, 0x06, 0xCB, 0x09, 0x00, 0x15, 0x9D, 0x5F, 0x00, 0x1B, 0x87, 0x46, 0x00, 0x06, 0xC4, 0x29, 0x00, 0x86, 0x21, 0xD9, 0x56, 0x00, 0x6F, 0xD2, 0x7C, 0x00, 0x15, 0xC3, 0x40, 0x00, 0x1B, 0x87, 0x46, 0x00, 0x06, 0x9E, 0x15, 0x00, 0x86, 0x27, 0xE8, 0x65, 0x00, 0x66, 0xF1, 0x08, 0x00, 0x18, 0xD2, 0x4F, 0x00, 0x18, 0x87, 0x46, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x57, 0x96, 0x4F, 0x41, 0x43, 0x56, 0xB3, 0xB4, 0xBC, 0x00, 0x15, 0x90, 0x1C, 0x8D, 0x8E, 0x9A, 0x00, 0x51, 0xCC, 0x2E, 0x00, 0x85, 0x4A, 0x87, 0x49, 0x00, 0x06, 0xD2, 0x4F, 0x00, 0x12, 0x87, 0x31, 0x00, 0x15, 0x87, 0x46, 0x00, 0x06, 0xB4, 0x0A, 0x00, 0x5A, 0x8F, 0x09, 0x00, 0x1B, 0xF0, 0x7F, 0x00, 0x06, 0x7B, 0x00, 0x86, 0x1B, 0xA5, 0x67, 0x00, 0x06, 0x9E, 0x1E, 0xD9, 0xD9, 0xDD, 0x00, 0x0C, 0x86, 0x24, 0x00, 0x12, 0x87, 0x46, 0x73, 0x75, 0x83, 0x00, 0x06, 0x87, 0x43, 0x00, 0x57, 0x9E, 0x12, 0x00, 0x06, 0xE9, 0x54, 0x00, 0x1B, 0xBD, 0x04, 0x9A, 0x9B, 0xA5, 0x00, 0x86, 0x18, 0xB4, 0x70, 0x00, 0x0C, 0xF0, 0x70, 0x00, 0x06, 0xF8, 0x3C, 0x00, 0x06, 0xCA, 0x20, 0x00, 0x09, 0x87, 0x46, 0x41, 0x43, 0x56, 0x80, 0x81, 0x8F, 0x00, 0x09, 0x81, 0x80, 0x41, 0x00, 0x5A, 0xA5, 0x55, 0x73, 0x75, 0x83, 0x00, 0x1E, 0xDB, 0x1C, 0x5A, 0x5C, 0x6D, 0xD9, 0xD9, 0xDD, 0x00, 0x86, 0x1E, 0x9E, 0x24, 0x00, 0x06, 0x96, 0x5B, 0x00, 0x0C, 0x81, 0x87, 0x6C, 0x00, 0x06, 0x8E, 0x7A, 0x00, 0x0C, 0x0F, 0x00, 0x54, 0xF8, 0x57, 0x00, 0x1B, 0xE9, 0x54, 0x00, 0x15, 0xB6, 0x1B, 0x00, 0x86, 0x24, 0xA5, 0x6D, 0x00, 0x06, 0x81, 0x86, 0x6E, 0x00, 0x0F, 0x87, 0x4F, 0xD9, 0xD9, 0xDD, 0x8D, 0x8E, 0x9A, 0x00, 0x51, 0xD2, 0x70, 0x00, 0x12, 0xC3, 0x6A, 0x00, 0x1E, 0x96, 0x31, 0x00, 0x86, 0x1B, 0xF8, 0x60, 0x00, 0x1B, 0x95, 0x3F, 0x67, 0x68, 0x78, 0x00, 0x60, 0x81, 0x96, 0x66, 0x00, 0x1E, 0xE9, 0x54, 0x00, 0x12, 0x87, 0x67, 0x00, 0x86, 0x18, 0x81, 0x87, 0x6C, 0x00, 0x81, 0x10, 0x81, 0x81, 0x33, 0x00, 0x18, 0xAD, 0x7E, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x86, 0x1B, 0xB4, 0x6D, 0x00, 0x81, 0x0D, 0x81, 0x90, 0x3F, 0xF2, 0xF2, 0xF4, 0x00, 0x12, 0x87, 0x49, 0x00, 0x06, 0xA7, 0x00, 0x00, 0x86, 0x21, 0xA5, 0x5B, 0x00, 0x81, 0x0D, 0x81, 0x88, 0x7F, 0xF2, 0xF2, 0xF4, 0x00, 0x06, 0xF8, 0x69, 0x67, 0x68, 0x78, 0x67, 0x68, 0x78, 0xA6, 0xA7, 0xB0, 0xF2, 0xF2, 0xF4, 0x00, 0x0C, 0x81, 0xA6, 0x1C, 0x00, 0x87, 0x28, 0x81, 0xBD, 0x5A, 0xA6, 0xA7, 0xB0, 0x00, 0x06, 0x81, 0x98, 0x11, 0x00, 0x06, 0xEA, 0x76, 0x00, 0x86, 0x1B, 0x96, 0x49, 0x00, 0x06, 0xAD, 0x12, 0x8D, 0x8E, 0x9A, 0x00, 0x86, 0x1E, 0xEF, 0x78, 0x00, 0x81, 0x25, 0xF1, 0x1A, 0x00, 0x87, 0x0A, 0xE9, 0x1B, 0x00, 0x54, 0xF8, 0x60, 0x00, 0x87, 0x2B, 0x87, 0x46, 0x00, 0x06, 0x81, 0x8E, 0x0D, 0x00, 0x81, 0x0A, 0x97, 0x62, 0x00, 0x6C, 0xBD, 0x1F, 0x00, 0x85, 0x50, 0x81, 0xB5, 0x10, 0x00, 0x81, 0x07, 0xF8, 0x2A, 0x8D, 0x8E, 0x9A, 0x00, 0x86, 0x39, 0x90, 0x19, 0x00, 0x81, 0x0A, 0xBB, 0x08, 0x00, 0x06, 0x81, 0xBD, 0x2D, 0x00, 0x86, 0x36, 0xA6, 0x6B, 0x00, 0x60, 0x81, 0xE2, 0x07, 0x00, 0x30, 0x90, 0x1C, 0x00, 0x0F, 0xF2, 0x21, 0x00, 0x84, 0x52, 0x94, 0x7D, 0x00, 0x81, 0x58, 0xC0, 0x76, 0x00, 0x06, 0xD9, 0x41, 0x00, 0x81, 0x01, 0x81, 0xE8, 0x58, 0x00, 0x06, 0xB5, 0x7A, 0x00, 0x06, 0xF2, 0x03, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0xE9, 0x63, 0x00, 0x06, 0x06, 0x00, 0x09, 0x09, 0x00, 0x84, 0x3A, 0xBC, 0x39, 0x00, 0x06, 0x81, 0xB9, 0x53, 0x00, 0x54, 0x81, 0xD1, 0x1A, 0x00, 0x81, 0x01, 0xF8, 0x57, 0x00, 0x06, 0xCA, 0x1D, 0x67, 0x68, 0x78, 0x73, 0x75, 0x83, 0x00, 0x06, 0x81, 0x64, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x86, 0x2D, 0x00, 0x09, 0x1B, 0x00, 0x09, 0x09, 0x00, 0x12, 0x12, 0x00, 0x54, 0x81, 0xFA, 0x07, 0x00, 0x06, 0xF9, 0x58, 0x00, 0x09, 0x09, 0x00, 0x0F, 0x0F, 0x00, 0x84, 0x37, 0x81, 0x80, 0x26, 0x00, 0x06, 0x81, 0x85, 0x01, 0x00, 0x09, 0xEF, 0x24, 0x00, 0x81, 0x4C, 0x81, 0xC8, 0x62, 0x00, 0x06, 0x81, 0x96, 0x42, 0x00, 0x0F, 0xF1, 0x05, 0x00, 0x12, 0x12, 0x00, 0x1B, 0x1B, 0x00, 0x84, 0x37, 0xC8, 0x69, 0x00, 0x06, 0x92, 0x57, 0x00, 0x6F, 0x86, 0x4B, 0x00, 0x09, 0x81, 0xF7, 0x25, 0x00, 0x81, 0x4F, 0xBA, 0x5E, 0x00, 0x24, 0x8D, 0x7C, 0x00, 0x1E, 0x1E, 0x00, 0x84, 0x37, 0x81, 0xF6, 0x2D, 0x00, 0x12, 0x81, 0xFD, 0x73, 0x00, 0x6C, 0x81, 0xEF, 0x65, 0x00, 0x06, 0x7E, 0x00, 0x86, 0x36, 0xB9, 0x54, 0x00, 0x81, 0x04, 0x87, 0x46, 0x00, 0x09, 0x82, 0x8D, 0x77, 0x00, 0x57, 0x82, 0x86, 0x0D, 0x00, 0x86, 0x66, 0x87, 0x46, 0x00, 0x06, 0x81, 0xD1, 0x53, 0x00, 0x81, 0x52, 0x96, 0x55, 0x00, 0x81, 0x19, 0xA6, 0x6E, 0x00, 0x18, 0xA6, 0x50, 0x00, 0x83, 0x3F, 0x92, 0x09, 0x00, 0x7E, 0x87, 0x46, 0x00, 0x0C, 0x96, 0x55, 0x00, 0x81, 0x0A, 0xD1, 0x33, 0x00, 0x81, 0x5B, 0x83, 0x63, 0x00, 0x18, 0xA6, 0x50, 0x00, 0x83, 0x3F, 0x9F, 0x0D, 0x00, 0x81, 0x01, 0x87, 0x46, 0x00, 0x0C, 0x82, 0xAC, 0x0C, 0x00, 0x82, 0x74, 0xC5, 0x1B, 0xC0, 0xC0, 0xC7, 0x00, 0x83, 0x42, 0xB4, 0x67, 0x00, 0x83, 0x7E, 0x87, 0x46, 0x00, 0x09, 0xE3, 0x3C, 0x00, 0x83, 0x3F, 0x81, 0xD4, 0x1D, 0x00, 0x84, 0x04, 0x87, 0x46, 0x00, 0x06, 0x8F, 0x12, 0x00, 0x87, 0x40, 0x87, 0x46, 0x00, 0x83, 0x42, 0x81, 0xBC, 0x56, 0x00, 0x81, 0x01, 0x87, 0x46, 0x00, 0x81, 0x6A, 0xC9, 0x34, 0x5A, 0x5C, 0x6D, 0x80, 0x81, 0x8F, 0x00, 0x81, 0x13, 0xD9, 0x35, 0x00, 0x06, 0x81, 0xE3, 0x62, 0x00, 0x84, 0x3A, 0x87, 0x46, 0x00, 0x06, 0x82, 0x8E, 0x03, 0x00, 0x06, 0x7E, 0x00, 0x81, 0x58, 0x81, 0xC1, 0x1F, 0x41, 0x43, 0x56, 0x9A, 0x9B, 0xA5, 0x00, 0x0C, 0xC5, 0x60, 0x00, 0x15, 0xAC, 0x11, 0x00, 0x7B, 0xE4, 0x13, 0x00, 0x06, 0x82, 0x8F, 0x64, 0x00, 0x84, 0x3A, 0x87, 0x46, 0x00, 0x06, 0x82, 0x94, 0x2A, 0x00, 0x09, 0x81, 0xA3, 0x13, 0x00, 0x81, 0x58, 0xE9, 0x57, 0x00, 0x09, 0x81, 0xCB, 0x50, 0xB3, 0xB4, 0xBC, 0xE6, 0xE6, 0xE9, 0x00, 0x18, 0x82, 0xCC, 0x08, 0x00, 0x72, 0x8F, 0x24, 0x00, 0x06, 0xD7, 0x00, 0x00, 0x83, 0x42, 0xCE, 0x39, 0x00, 0x7B, 0x87, 0x46, 0x00, 0x0C, 0x8F, 0x09, 0x00, 0x54, 0x82, 0xC2, 0x3A, 0x00, 0x81, 0x07, 0x81, 0xBB, 0x4C, 0x00, 0x06, 0x8E, 0x7D, 0x00, 0x09, 0x86, 0x27, 0x00, 0x1E, 0x81, 0xF1, 0x40, 0x00, 0x54, 0xDD, 0x4B, 0x00, 0x1E, 0xBC, 0x30, 0xE6, 0xE6, 0xE9, 0x00, 0x83, 0x42, 0xD5, 0x7C, 0x00, 0x78, 0x87, 0x46, 0x00, 0x09, 0x85, 0x38, 0x00, 0x09, 0xC3, 0x73, 0x00, 0x81, 0x4F, 0xF8, 0x66, 0x00, 0x06, 0x9C, 0x6D, 0x00, 0x12, 0xD4, 0x5A, 0x00, 0x72, 0x82, 0x80, 0x4C, 0x00, 0x1B, 0xCB, 0x3C, 0x00, 0x83, 0x48, 0x81, 0x80, 0x38, 0x00, 0x72, 0x87, 0x46, 0x00, 0x06, 0x9C, 0x28, 0x00, 0x0F, 0x81, 0xE7, 0x7E, 0x00, 0x75, 0xA6, 0x59, 0x00, 0x63, 0xAE, 0x7C, 0x00, 0x12, 0xDC, 0x1D, 0x00, 0x1B, 0xE9, 0x36, 0x00, 0x06, 0x98, 0x60, 0x00, 0x84, 0x16, 0x82, 0x8F, 0x58, 0x4D, 0x4F, 0x62, 0x00, 0x1B, 0xD6, 0x41, 0x00, 0x0C, 0xF0, 0x1F, 0x00, 0x06, 0x81, 0xF6, 0x2A, 0x00, 0x24, 0xFD, 0x47, 0x00, 0x27, 0x27, 0x00, 0x0F, 0x0F, 0x00, 0x09, 0x82, 0xB2, 0x2A, 0x00, 0x12, 0x93, 0x55, 0x00, 0x81, 0x4F, 0x8F, 0x09, 0x00, 0x06, 0x8A, 0x1C, 0x00, 0x15, 0x87, 0x2E, 0x00, 0x1B, 0x87, 0x46, 0x00, 0x06, 0x98, 0x63, 0x00, 0x84, 0x16, 0x81, 0xB5, 0x49, 0x00, 0x12, 0x81, 0xF6, 0x06, 0x00, 0x3F, 0xFD, 0x44, 0x00, 0x4E, 0x4E, 0x00, 0x12, 0x82, 0xE8, 0x42, 0x00, 0x81, 0x43, 0x82, 0x74, 0x00, 0x06, 0x8E, 0x56, 0x00, 0x15, 0x9D, 0x65, 0x00, 0x84, 0x37, 0x82, 0xAD, 0x70, 0x00, 0x81, 0x1C, 0x87, 0x46, 0x00, 0x81, 0x4C, 0x87, 0x43, 0x00, 0x0C, 0x9C, 0x64, 0x00, 0x1B, 0x82, 0xDA, 0x5B, 0x00, 0x7E, 0x82, 0xBC, 0x7C, 0x00, 0x0C, 0x93, 0x1C, 0x00, 0x84, 0x46, 0x87, 0x46, 0xCC, 0xCD, 0xD2, 0x00, 0x81, 0x49, 0xA2, 0x5E, 0x00, 0x06, 0x98, 0x30, 0x00, 0x42, 0x82, 0xBC, 0x7C, 0x00, 0x5A, 0x82, 0xCC, 0x08, 0x00, 0x06, 0x82, 0x8F, 0x61, 0x00, 0x0C, 0x82, 0x81, 0x50, 0x00, 0x06, 0x81, 0xA7, 0x23, 0x00, 0x83, 0x27, 0x81, 0xE2, 0x31, 0x00, 0x81, 0x10, 0x87, 0x46, 0x00, 0x06, 0x82, 0xD0, 0x51, 0x00, 0x81, 0x4C, 0x96, 0x46, 0x00, 0x06, 0x81, 0x98, 0x44, 0x00, 0x09, 0x87, 0x46, 0x00, 0x06, 0x81, 0xB4, 0x00, 0x00, 0x18, 0x9D, 0x5F, 0x00, 0x75, 0x82, 0xDB, 0x14, 0x00, 0x09, 0x83, 0x97, 0x44, 0x00, 0x0C, 0x82, 0xCB, 0x7C, 0x00, 0x06, 0x81, 0x9F, 0x5A, 0x00, 0x81, 0x55, 0x99, 0x52, 0x00, 0x82, 0x5C, 0xA5, 0x5E, 0x67, 0x68, 0x78, 0x00, 0x81, 0x55, 0x8B, 0x7A, 0xD9, 0xD9, 0xDD, 0x00, 0x0C, 0xB6, 0x2A, 0x00, 0x3C, 0x87, 0x46, 0x00, 0x57, 0x96, 0x52, 0x80, 0x81, 0x8F, 0xE6, 0xE6, 0xE9, 0x00, 0x15, 0x91, 0x7A, 0x00, 0x06, 0x82, 0x90, 0x71, 0x00, 0x84, 0x40, 0xF1, 0x1A, 0x00, 0x81, 0x46, 0xA5, 0x49, 0x00, 0x0F, 0xB4, 0x1F, 0x00, 0x39, 0x96, 0x52, 0x00, 0x54, 0x82, 0xF9, 0x2C, 0x00, 0x06, 0x57, 0x00, 0x1B, 0x9E, 0x09, 0x00, 0x0F, 0x82, 0xF2, 0x04, 0x00, 0x85, 0x71, 0x87, 0x46, 0x00, 0x06, 0x81, 0x98, 0x38, 0x00, 0x12, 0xD4, 0x3C, 0x00, 0x36, 0xA5, 0x5E, 0x00, 0x57, 0x83, 0x88, 0x38, 0x67, 0x68, 0x78, 0x00, 0x1E, 0x8E, 0x6E, 0x00, 0x06, 0x96, 0x5B, 0x00, 0x85, 0x7A, 0x87, 0x46, 0x00, 0x06, 0xB4, 0x19, 0x00, 0x12, 0x98, 0x27, 0xA6, 0xA7, 0xB0, 0x00, 0x18, 0xC3, 0x40, 0x00, 0x1B, 0x87, 0x46, 0x00, 0x06, 0x36, 0x00, 0x51, 0x8E, 0x17, 0x8D, 0x8E, 0x9A, 0x00, 0x21, 0x83, 0x5A, 0x00, 0x83, 0x3F, 0xB5, 0x5F, 0x00, 0x82, 0x3E, 0x87, 0x46, 0x00, 0x18, 0xBC, 0x15, 0x00, 0x06, 0xC3, 0x40, 0x00, 0x15, 0x8E, 0x02, 0x00, 0x1B, 0x83, 0xA6, 0x50, 0x00, 0x57, 0xD5, 0x0A, 0x00, 0x24, 0x87, 0x46, 0x00, 0x84, 0x40, 0xF8, 0x60, 0x00, 0x81, 0x3D, 0x82, 0x3E, 0x00, 0x1B, 0x81, 0x95, 0x32, 0x00, 0x06, 0x9E, 0x30, 0x00, 0x12, 0x21, 0x00, 0x1E, 0x83, 0xB5, 0x5C, 0x00, 0x54, 0x83, 0x03, 0x00, 0x12, 0x83, 0xAE, 0x16, 0x00, 0x15, 0x81, 0xBE, 0x07, 0x00, 0x85, 0x7A, 0x87, 0x46, 0x00, 0x1B, 0xBD, 0x70, 0x00, 0x09, 0x81, 0xCD, 0x43, 0x00, 0x0F, 0x87, 0x49, 0x00, 0x12, 0x87, 0x46, 0x4D, 0x4F, 0x62, 0x00, 0x09, 0x82, 0xD3, 0x78, 0x00, 0x5A, 0xB6, 0x09, 0x00, 0x1B, 0x81, 0x2B, 0xB3, 0xB4, 0xBC, 0x00, 0x83, 0x3F, 0x81, 0x9E, 0x41, 0x00, 0x82, 0x41, 0xAD, 0x24, 0x00, 0x24, 0xEB, 0x38, 0x00, 0x0C, 0xF8, 0x3C, 0x00, 0x0C, 0x87, 0x46, 0x00, 0x06, 0xF7, 0x5F, 0x00, 0x09, 0x24, 0x00, 0x5A, 0xB7, 0x07, 0x00, 0x06, 0x81, 0xE2, 0x34, 0x00, 0x1B, 0xF2, 0x3F, 0x00, 0x83, 0x3F, 0xE9, 0x5D, 0x00, 0x82, 0x5C, 0x87, 0x46, 0x00, 0x0C, 0x81, 0xE4, 0x18, 0x00, 0x09, 0xCD, 0x2F, 0x00, 0x06, 0xA6, 0x11, 0xCC, 0xCD, 0xD2, 0x00, 0x0C, 0xCA, 0x47, 0xC0, 0xC0, 0xC7, 0x00, 0x5D, 0xBE, 0x4A, 0x00, 0x09, 0x82, 0xB5, 0x1E, 0x00, 0x0C, 0x9F, 0x46, 0x00, 0x06, 0xEC, 0x5D, 0x00, 0x81, 0x55, 0xFB, 0x5A, 0x00, 0x81, 0x7C, 0x81, 0xC0, 0x39, 0x00, 0x82, 0x59, 0x8B, 0x11, 0x00, 0x0C, 0x82, 0xE2, 0x42, 0x00, 0x0F, 0xCD, 0x4A, 0xC0, 0xC0, 0xC7, 0x00, 0x66, 0xD9, 0x53, 0x00, 0x06, 0x82, 0xF9, 0x2F, 0x00, 0x06, 0xCE, 0x3C, 0x00, 0x06, 0x90, 0x10, 0x00, 0x06, 0x0C, 0x00, 0x86, 0x30, 0x83, 0x81, 0x61, 0x00, 0x06, 0x8A, 0x31, 0x00, 0x06, 0xAC, 0x32, 0x8D, 0x8E, 0x9A, 0x00, 0x75, 0xCD, 0x4A, 0x00, 0x06, 0x82, 0xEB, 0x15, 0x00, 0x06, 0x81, 0xE6, 0x23, 0x00, 0x86, 0x3C, 0x81, 0xDD, 0x5F, 0x00, 0x97, 0x41, 0x84, 0x91, 0x19, 0x00, 0x15, 0xA9, 0x32, 0x00, 0x06, 0x82, 0xD3, 0x57, 0xCC, 0xCD, 0xD2, 0x00, 0x83, 0x42, 0x81, 0xD3, 0x22, 0x00, 0x83, 0x66, 0x82, 0xE2, 0x4B, 0x00, 0x12, 0xAE, 0x01, 0x00, 0x06, 0xBD, 0x46, 0x00, 0x06, 0x83, 0xC4, 0x68, 0x00, 0x06, 0x82, 0xE2, 0x5D, 0x00, 0x81, 0x3D, 0x81, 0x97, 0x6A, 0x00, 0x09, 0xA8, 0x31, 0x00, 0x09, 0x82, 0xA0, 0x2D, 0x00, 0x85, 0x4A, 0x82, 0xAF, 0x5A, 0x00, 0x06, 0xCB, 0x30, 0x00, 0x15, 0x82, 0xF1, 0x57, 0xF2, 0xF2, 0xF4, 0x00, 0x0C, 0xBC, 0x21, 0x00, 0x81, 0x37, 0x82, 0xF9, 0x2C, 0x67, 0x68, 0x78, 0x00, 0x0C, 0x81, 0xC1, 0x13, 0x00, 0x12, 0x81, 0x94, 0x0A, 0x00, 0x06, 0x82, 0xA8, 0x14, 0x00, 0x85, 0x3E, 0x83, 0xE4, 0x58, 0x00, 0x06, 0x84, 0xA7, 0x62, 0x00, 0x27, 0x81, 0xCB, 0x4D, 0x00, 0x81, 0x2E, 0xF1, 0x1A, 0x41, 0x43, 0x56, 0x00, 0x18, 0xBE, 0x7D, 0x00, 0x18, 0x87, 0x55, 0xD9, 0xD9, 0xDD, 0xA6, 0xA7, 0xB0, 0x73, 0x75, 0x83, 0x00, 0x84, 0x40, 0x8F, 0x27, 0x00, 0x1E, 0x81, 0x8A, 0x72, 0x00, 0x51, 0x82, 0xAD, 0x70, 0x00, 0x15, 0x9D, 0x71, 0x00, 0x18, 0xDA, 0x51, 0x00, 0x06, 0x18, 0x00, 0x81, 0x2E, 0xD5, 0x55, 0x00, 0x3C, 0x81, 0x94, 0x31, 0xC0, 0xC0, 0xC7, 0x8D, 0x8E, 0x9A, 0x00, 0x84, 0x2B, 0xBE, 0x2F, 0x00, 0x12, 0x81, 0xDA, 0x6B, 0x00, 0x66, 0x82, 0xAD, 0x70, 0xCC, 0xCD, 0xD2, 0x00, 0x12, 0x88, 0x0E, 0x00, 0x1B, 0x81, 0xDA, 0x56, 0x00, 0x81, 0x25, 0xF1, 0x1A, 0x00, 0x0C, 0x81, 0x94, 0x5E, 0x00, 0x45, 0x81, 0x9C, 0x03, 0xFE, 0xFE, 0xFF, 0xCA, 0xCB, 0xD1, 0x98, 0x99, 0xA4, 0x72, 0x74, 0x83, 0x40, 0x42, 0x00, 0x81, 0x6E, 0x81, 0xA0, 0x46, 0x4D, 0x4F, 0x62, 0x00, 0x06, 0xC8, 0x00, 0xC0, 0xC0, 0xC7, 0x00, 0x15, 0x82, 0xB9, 0x46, 0x00, 0x06, 0xC9, 0x19, 0x00, 0x82, 0x08, 0x83, 0x8E, 0x74, 0x00, 0x0C, 0x93, 0x58, 0x00, 0x69, 0x82, 0xAD, 0x70, 0x00, 0x06, 0x83, 0x06, 0x00, 0x12, 0x8E, 0x71, 0x00, 0x18, 0xFA, 0x0E, 0x00, 0x81, 0x1F, 0x96, 0x52, 0x00, 0x09, 0xD4, 0x3F, 0x00, 0x51, 0x87, 0x46, 0xFD, 0xFD, 0xFE, 0xFB, 0xFC, 0xFD, 0xFA, 0xFC, 0xFD, 0xF8, 0xFB, 0xFC, 0xD2, 0xD5, 0xDB, 0xAD, 0xB0, 0xB9, 0x7C, 0x7F, 0x8D, 0x58, 0x5A, 0x6C, 0x00, 0x81, 0x5B, 0xE7, 0x22, 0x00, 0x0C, 0x83, 0x84, 0x76, 0x00, 0x24, 0x81, 0xB4, 0x6C, 0x00, 0x81, 0x7C, 0x83, 0x85, 0x1A, 0x00, 0x09, 0x81, 0xDC, 0x4C, 0x00, 0x06, 0xE9, 0x51, 0x00, 0x6F, 0xD2, 0x6D, 0x00, 0x06, 0x88, 0x41, 0x00, 0x0C, 0x75, 0xC0, 0xC0, 0xC7, 0x00, 0x18, 0x8F, 0x09, 0xB3, 0xB4, 0xBC, 0x00, 0x81, 0x1C, 0xE6, 0x09, 0x00, 0x09, 0xF3, 0x3A, 0x00, 0x60, 0x87, 0x46, 0xF7, 0xFA, 0xFC, 0xF5, 0xF9, 0xFB, 0xF3, 0xF7, 0xFB, 0xF2, 0xF6, 0xFA, 0xE5, 0xEA, 0xEF, 0xB4, 0xB9, 0xC3, 0x91, 0x95, 0xA2, 0x62, 0x65, 0x76, 0x00, 0x81, 0x49, 0x8C, 0x54, 0x00, 0x30, 0xA0, 0x50, 0x00, 0x0F, 0x87, 0x4F, 0x9A, 0x9B, 0xA5, 0x00, 0x81, 0x70, 0x81, 0xB1, 0x78, 0x00, 0x06, 0x89, 0x6F, 0x00, 0x7B, 0xB3, 0x45, 0x00, 0x09, 0x84, 0xC4, 0x7F, 0x00, 0x06, 0x97, 0x53, 0x00, 0x18, 0xF1, 0x7A, 0x00, 0x06, 0xF2, 0x1B, 0x00, 0x81, 0x19, 0x83, 0x1E, 0x00, 0x0F, 0x91, 0x50, 0x00, 0x69, 0x87, 0x46, 0xF1, 0xF6, 0xFA, 0xEF, 0xF5, 0xF9, 0xED, 0xF4, 0xF8, 0xEC, 0xF3, 0xF8, 0xEA, 0xF2, 0xF7, 0xC7, 0xCE, 0xD6, 0x99, 0x9E, 0xAB, 0x6C, 0x70, 0x80, 0x4A, 0x4D, 0x60, 0x00, 0x81, 0x40, 0xEE, 0x59, 0x00, 0x3F, 0x81, 0xC4, 0x07, 0x00, 0x81, 0x6A, 0x8F, 0x18, 0x00, 0x06, 0x81, 0x9E, 0x56, 0x00, 0x81, 0x01, 0x95, 0x27, 0x00, 0x06, 0x83, 0xB5, 0x35, 0xCC, 0xCD, 0xD2, 0x00, 0x18, 0x83, 0xBE, 0x08, 0xB3, 0xB4, 0xBC, 0xD9, 0xD9, 0xDD, 0x00, 0x81, 0x19, 0xA3, 0x68, 0x00, 0x60, 0x81, 0xBA, 0x4B, 0x00, 0x2A, 0x87, 0x46, 0xE9, 0xF1, 0xF7, 0xE7, 0xF0, 0xF6, 0xE6, 0xEF, 0xF6, 0xE4, 0xEE, 0xF5, 0xCD, 0xD6, 0xDF, 0xAB, 0xB3, 0xBF, 0x7F, 0x85, 0x95, 0x54, 0x58, 0x6A, 0x00, 0x81, 0x28, 0xC0, 0x37, 0x00, 0x21, 0xAF, 0x44, 0x00, 0x0C, 0x9B, 0x51, 0x00, 0x21, 0x30, 0xCC, 0xCD, 0xD2, 0x00, 0x81, 0x64, 0x8F, 0x15, 0x00, 0x06, 0x89, 0x7B, 0x00, 0x81, 0x22, 0xA0, 0x1D, 0x00, 0x81, 0x19, 0xB2, 0x7A, 0x41, 0x43, 0x56, 0x00, 0x06, 0x81, 0xC6, 0x27, 0x00, 0x81, 0x13, 0x87, 0x46, 0xE3, 0xED, 0xF4, 0xE1, 0xEC, 0xF4, 0xE0, 0xEB, 0xF3, 0xDE, 0xEA, 0xF3, 0xDC, 0xE9, 0xF2, 0xB1, 0xBB, 0xC8, 0x87, 0x8E, 0x9E, 0x67, 0x6D, 0x7F, 0x3E, 0x41, 0x55, 0x00, 0x81, 0x16, 0x81, 0xB2, 0x67, 0x00, 0x15, 0x8E, 0x53, 0xB3, 0xB4, 0xBC, 0x00, 0x1B, 0xC6, 0x22, 0x00, 0x06, 0xEF, 0x00, 0x00, 0x15, 0x83, 0xCA, 0x1D, 0x00, 0x81, 0x5B, 0x81, 0xDA, 0x5F, 0x00, 0x12, 0xAB, 0x73, 0x00, 0x82, 0x3B, 0x81, 0xA4, 0x56, 0x00, 0x06, 0x83, 0xDC, 0x4A, 0x00, 0x63, 0x81, 0xC9, 0x27, 0x00, 0x45, 0x87, 0x46, 0xDB, 0xE8, 0xF2, 0xDA, 0xE7, 0xF1, 0xD8, 0xE6, 0xF0, 0xD7, 0xE5, 0xF0, 0xB7, 0xC3, 0xD0, 0x98, 0xA2, 0xB1, 0x65, 0x6C, 0x7E, 0x00, 0x81, 0x19, 0x87, 0x43, 0x00, 0x33, 0x82, 0x85, 0x33, 0x5A, 0x5C, 0x6D, 0x00, 0x15, 0x4B, 0x00, 0x81, 0x61, 0x87, 0x49, 0x00, 0x82, 0x3B, 0x82, 0xBB, 0x4E, 0x00, 0x09, 0x83, 0xEC, 0x54, 0x00, 0x81, 0x34, 0x87, 0x46, 0xD5, 0xE4, 0xEF, 0xD3, 0xE3, 0xEF, 0xD2, 0xE2, 0xEE, 0xBD, 0xCC, 0xD9, 0x6E, 0x76, 0x88, 0x00, 0x81, 0x0D, 0x87, 0x43, 0x00, 0x3F, 0x9D, 0x53, 0x00, 0x15, 0x9E, 0x5D, 0x00, 0x81, 0x5B, 0x87, 0x49, 0x00, 0x1E, 0x81, 0xCB, 0x62, 0x00, 0x82, 0x20, 0x81, 0xA8, 0x54, 0x00, 0x6C, 0x81, 0xD8, 0x33, 0x00, 0x5A, 0x87, 0x46, 0xD1, 0xE1, 0xEE, 0xCB, 0xDD, 0xEC, 0x89, 0x9F, 0xBA, 0x39, 0x3D, 0x54, 0x00, 0x81, 0x04, 0x82, 0x47, 0x00, 0x48, 0x81, 0x94, 0x13, 0x00, 0x12, 0xBF, 0x33, 0x00, 0x81, 0x52, 0x82, 0x88, 0x06, 0x00, 0x82, 0x3B, 0x83, 0xAE, 0x16, 0x00, 0x33, 0xD2, 0x58, 0x00, 0x81, 0x1C, 0x87, 0x46, 0xBF, 0xD4, 0xE8, 0x93, 0xB4, 0xD9, 0x89, 0xAC, 0xD5, 0x8C, 0xAA, 0xCF, 0x44, 0x4C, 0x65, 0x00, 0x6F, 0x91, 0x4D, 0x00, 0x0F, 0x81, 0x67, 0x00, 0x4E, 0x81, 0xA9, 0x61, 0x00, 0x12, 0xCE, 0x3F, 0x00, 0x81, 0x58, 0x94, 0x77, 0x00, 0x82, 0x2F, 0x96, 0x52, 0x00, 0x0C, 0x82, 0xA1, 0x0A, 0x00, 0x81, 0x40, 0x87, 0x46, 0xCF, 0xE0, 0xED, 0xA5, 0xC2, 0xDF, 0x8A, 0xAE, 0xD6, 0x89, 0xAD, 0xD6, 0x89, 0xAC, 0xD5, 0x88, 0xAA, 0xD5, 0x86, 0xA5, 0xCD, 0x43, 0x47, 0x5E, 0x00, 0x75, 0x83, 0x80, 0x03, 0x00, 0x57, 0x82, 0xE9, 0x31, 0x00, 0x12, 0x87, 0x49, 0x00, 0x81, 0x55, 0x82, 0xEA, 0x17, 0x00, 0x06, 0xAF, 0x2F, 0x00, 0x82, 0x2C, 0xF2, 0x42, 0x00, 0x75, 0x81, 0xEF, 0x05, 0x00, 0x51, 0x87, 0x46, 0xC3, 0xD7, 0xE9, 0x90, 0xB3, 0xD8, 0x8A, 0xAF, 0xD6, 0x8A, 0xAE, 0x00, 0x05, 0x87, 0x43, 0xAB, 0xD5, 0x88, 0xAA, 0xD5, 0x87, 0xA8, 0xD4, 0x7B, 0x95, 0x00, 0x67, 0x93, 0x19, 0x00, 0x0F, 0x96, 0x4C, 0x00, 0x5A, 0x94, 0x11, 0x00, 0x0F, 0x82, 0xA6, 0x21, 0x00, 0x81, 0x55, 0x96, 0x58, 0x00, 0x06, 0xBC, 0x30, 0x00, 0x82, 0x23, 0xEE, 0x17, 0x00, 0x54, 0xD2, 0x58, 0x00, 0x75, 0x87, 0x46, 0xD3, 0xE3, 0xEF, 0xAD, 0xC8, 0xE2, 0x8C, 0xB1, 0xD7, 0x8B, 0x00, 0x06, 0x87, 0x43, 0x00, 0x08, 0x8F, 0x09, 0x87, 0xA9, 0xD4, 0x87, 0xA7, 0xD4, 0x86, 0xA6, 0xD4, 0x52, 0x60, 0x00, 0x61, 0xAD, 0x39, 0x00, 0x06, 0xA3, 0x11, 0x00, 0x0C, 0xAD, 0x0F, 0x00, 0x6C, 0xDD, 0x57, 0x00, 0x81, 0x52, 0x81, 0xB6, 0x08, 0x00, 0x06, 0xF7, 0x35, 0x00, 0x82, 0x1D, 0x96, 0x55, 0x00, 0x09, 0x81, 0xCD, 0x55, 0x00, 0x81, 0x43, 0x87, 0x46, 0xCB, 0xDD, 0xEC, 0x9B, 0xBC, 0xDC, 0x8C, 0xB1, 0xD7, 0x8B, 0xB0, 0xD6, 0x00, 0x0D, 0x8F, 0x09, 0xA9, 0xD5, 0x87, 0xA8, 0xD4, 0x86, 0xA7, 0xD4, 0x86, 0xA5, 0xD3, 0x7B, 0x96, 0xC2, 0x00, 0x6F, 0x8A, 0x13, 0x00, 0x63, 0xAC, 0x3E, 0x00, 0x0C, 0xA1, 0x4B, 0x00, 0x81, 0x55, 0x8F, 0x0F, 0x00, 0x06, 0x81, 0xBF, 0x2F, 0x00, 0x82, 0x17, 0x81, 0xBB, 0x31, 0x00, 0x42, 0xF0, 0x61, 0x00, 0x81, 0x0A, 0x87, 0x46, 0xBE, 0xD4, 0xE8, 0x92, 0xB6, 0xD9, 0x8C, 0xB2, 0xD7, 0x00, 0x0D, 0x8F, 0x09, 0x00, 0x06, 0x96, 0x4C, 0xA9, 0x00, 0x05, 0x87, 0x43, 0xA6, 0xD4, 0x85, 0xA5, 0xD3, 0x84, 0xA3, 0xD3, 0x52, 0x5F, 0x00, 0x5B, 0x8F, 0x0F, 0x00, 0x0F, 0x9E, 0x12, 0x00, 0x66, 0xAA, 0x5D, 0x00, 0x0F, 0x82, 0xBA, 0x11, 0x00, 0x81, 0x55, 0x85, 0x6E, 0x00, 0x06, 0x96, 0x58, 0x00, 0x82, 0x11, 0x83, 0x8A, 0x10, 0x00, 0x51, 0xF0, 0x61, 0x00, 0x78, 0x87, 0x46, 0xD9, 0xE6, 0xF1, 0xAB, 0xC8, 0xE2, 0x8D, 0xB4, 0xD8, 0x8D, 0xB3, 0x00, 0x05, 0x87, 0x43, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x06, 0x96, 0x4C, 0xAB, 0xD5, 0x87, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x05, 0x87, 0x43, 0x85, 0xA4, 0xD3, 0x84, 0xA2, 0xD3, 0x79, 0x94, 0xC1, 0x00, 0x66, 0x83, 0x8F, 0x03, 0x00, 0x6C, 0x83, 0xC1, 0x11, 0x00, 0x0C, 0x8F, 0x0F, 0x00, 0x81, 0x58, 0x82, 0x85, 0x15, 0x00, 0x06, 0xC9, 0x07, 0x00, 0x06, 0x81, 0xFF, 0x2D, 0x00, 0x82, 0x02, 0x82, 0x96, 0x08, 0x00, 0x57, 0xF0, 0x61, 0x00, 0x75, 0x87, 0x46, 0xD5, 0xE4, 0xF0, 0x9D, 0xBF, 0xDD, 0x8E, 0x00, 0x06, 0x87, 0x43, 0xB2, 0xD7, 0x8C, 0xB0, 0x00, 0x11, 0x8F, 0x09, 0x00, 0x06, 0x96, 0x4C, 0xA6, 0xD4, 0x85, 0xA4, 0xD3, 0x84, 0xA3, 0xD3, 0x84, 0xA2, 0xD2, 0x83, 0xA0, 0xD2, 0x51, 0x5D, 0x00, 0x58, 0x8F, 0x0F, 0x00, 0x0C, 0xD5, 0x31, 0x00, 0x6C, 0x82, 0xD2, 0x53, 0x00, 0x0F, 0x8F, 0x0F, 0x00, 0x81, 0x31, 0x85, 0x65, 0x00, 0x06, 0x81, 0xA4, 0x47, 0x00, 0x24, 0xF8, 0x30, 0x00, 0x0C, 0x81, 0x84, 0x69, 0x00, 0x81, 0x79, 0x83, 0xA6, 0x50, 0x00, 0x5A, 0xF0, 0x61, 0x00, 0x72, 0x87, 0x46, 0xD2, 0xE2, 0xEF, 0x94, 0xB9, 0xDA, 0x8E, 0xB5, 0xD8, 0x8D, 0xB4, 0xD8, 0x00, 0x07, 0x96, 0x4C, 0xB0, 0xD6, 0x8A, 0xAE, 0x00, 0x08, 0x8F, 0x09, 0xAA, 0x00, 0x13, 0x8F, 0x09, 0x83, 0xA1, 0xD2, 0x82, 0x9F, 0xD2, 0x78, 0x91, 0xC0, 0x00, 0x5A, 0x81, 0xFE, 0x11, 0x00, 0x09, 0x81, 0x58, 0x00, 0x6F, 0x81, 0xA9, 0x58, 0x00, 0x0C, 0xB8, 0x26, 0x00, 0x81, 0x31, 0x96, 0x55, 0x00, 0x5A, 0xC1, 0x26, 0x00, 0x57, 0xC0, 0x0D, 0x00, 0x1B, 0x81, 0x31, 0x00, 0x60, 0x88, 0x3B, 0x00, 0x5D, 0xF0, 0x61, 0x00, 0x6F, 0x87, 0x46, 0xC3, 0xD9, 0xEA, 0x8F, 0xB7, 0xD8, 0x8E, 0xB6, 0xD8, 0x00, 0x07, 0x96, 0x4C, 0xB2, 0xD7, 0x8B, 0x00, 0x09, 0x8F, 0x09, 0xAC, 0xD5, 0x00, 0x15, 0x8F, 0x09, 0x83, 0xA1, 0xD2, 0x83, 0xA0, 0xD2, 0x82, 0x9F, 0xD2, 0x81, 0x9D, 0xD1, 0x51, 0x5C, 0x7D, 0x00, 0x60, 0xB3, 0x78, 0x00, 0x7B, 0xB0, 0x69, 0x00, 0x81, 0x31, 0x81, 0xEE, 0x43, 0x00, 0x06, 0x84, 0xA6, 0x40, 0x00, 0x54, 0x82, 0xA1, 0x0A, 0x00, 0x57, 0xBB, 0x14, 0x00, 0x06, 0x85, 0xBD, 0x6B, 0x00, 0x72, 0x83, 0x9F, 0x0A, 0x00, 0x81, 0x0A, 0x9E, 0x09, 0x00, 0x42, 0x87, 0x46, 0xBA, 0xD3, 0xE7, 0x8F, 0xB7, 0xD9, 0x8E, 0xB6, 0xD8, 0x00, 0x0D, 0x8F, 0x09, 0x00, 0x05, 0x87, 0x43, 0x00, 0x0D, 0x8F, 0x09, 0x00, 0x0B, 0xA5, 0x55, 0x00, 0x09, 0x8F, 0x09, 0x81, 0x9E, 0xD1, 0x81, 0x9C, 0xD1, 0x7B, 0x92, 0x00, 0x52, 0xAD, 0x2D, 0x00, 0x0C, 0x9E, 0x15, 0x00, 0x72, 0x93, 0x4C, 0x00, 0x7E, 0x7E, 0x00, 0x81, 0x6A, 0x81, 0x92, 0x62, 0x00, 0x78, 0x82, 0xEA, 0x02, 0x00, 0x66, 0xF0, 0x61, 0x00, 0x69, 0x87, 0x46, 0xB0, 0xCD, 0xE4, 0x8F, 0xB8, 0xD9, 0x8F, 0xB7, 0x00, 0x07, 0x87, 0x43, 0x00, 0x08, 0xA5, 0x55, 0x00, 0x17, 0x8F, 0x09, 0x00, 0x06, 0x96, 0x4C, 0x00, 0x09, 0x8F, 0x09, 0x9E, 0xD1, 0x81, 0x9D, 0xD1, 0x80, 0x9C, 0xD1, 0x7F, 0x9A, 0xD0, 0x50, 0x59, 0x00, 0x4F, 0x81, 0x88, 0x40, 0x00, 0x0C, 0xFB, 0x09, 0x00, 0x72, 0x8E, 0x0E, 0x00, 0x0C, 0x90, 0x0A, 0x00, 0x82, 0x59, 0x82, 0xFD, 0x75, 0x00, 0x78, 0x84, 0xB5, 0x61, 0x00, 0x69, 0xF0, 0x61, 0x00, 0x66, 0x87, 0x46, 0xB1, 0xCE, 0xE4, 0x90, 0x00, 0x06, 0x87, 0x43, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x06, 0xA5, 0x55, 0x00, 0x13, 0x8F, 0x09, 0x00, 0x07, 0xC3, 0x67, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x06, 0x96, 0x4C, 0x00, 0x05, 0x8F, 0x09, 0x80, 0x9B, 0xD1, 0x7F, 0x99, 0xD0, 0x6C, 0x80, 0xAF, 0x00, 0x5A, 0xCB, 0x33, 0x00, 0x82, 0x5F, 0x83, 0x88, 0x38, 0x00, 0x7B, 0x81, 0x86, 0x32, 0x00, 0x72, 0x83, 0x5A, 0x00, 0x6C, 0xF0, 0x61, 0x00, 0x60, 0x87, 0x46, 0xE4, 0xEE, 0xF5, 0xA6, 0xC7, 0xE0, 0x90, 0xB9, 0xD9, 0x8F, 0xB8, 0xD9, 0x8F, 0x00, 0x08, 0x96, 0x4C, 0x00, 0x09, 0x8F, 0x09, 0x00, 0x12, 0xD2, 0x70, 0x00, 0x19, 0x8F, 0x09, 0x9B, 0xD1, 0x7F, 0x9A, 0xD0, 0x7F, 0x99, 0xD0, 0x7E, 0x97, 0xCF, 0x46, 0x4E, 0x00, 0x4C, 0x81, 0x9F, 0x21, 0x00, 0x0C, 0xA1, 0x72, 0x00, 0x75, 0xD0, 0x32, 0x00, 0x82, 0x62, 0x87, 0x46, 0x73, 0x75, 0x83, 0x00, 0x6F, 0xEA, 0x61, 0x00, 0x81, 0x1F, 0x82, 0xE0, 0x07, 0x00, 0x2D, 0x87, 0x46, 0xE6, 0xEF, 0xF6, 0xA1, 0xC4, 0xDF, 0x00, 0x07, 0x87, 0x43, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x09, 0xB4, 0x5E, 0x00, 0x1A, 0xD2, 0x70, 0x00, 0x08, 0x8F, 0x09, 0x00, 0x08, 0xA5, 0x55, 0x00, 0x0B, 0x8F, 0x09, 0x7E, 0x98, 0xD0, 0x7E, 0x96, 0xCF, 0x6B, 0x7D, 0xAE, 0x00, 0x84, 0x2E, 0x87, 0x46, 0x00, 0x06, 0xB0, 0x0C, 0x00, 0x66, 0xB7, 0x49, 0x00, 0x75, 0xF0, 0x61, 0x00, 0x5A, 0x87, 0x46, 0xE7, 0xF0, 0x00, 0x07, 0x87, 0x43, 0x00, 0x17, 0x8F, 0x09, 0x00, 0x0E, 0xD2, 0x70, 0x00, 0x14, 0x8F, 0x09, 0x82, 0x00, 0x0F, 0x8F, 0x09, 0x98, 0xD0, 0x7E, 0x97, 0xCF, 0x7D, 0x96, 0xCF, 0x7C, 0x94, 0xCF, 0x46, 0x4D, 0x00, 0x49, 0x8F, 0x0F, 0x00, 0x83, 0x66, 0x87, 0x46, 0x00, 0x06, 0x82, 0xDB, 0x0E, 0x00, 0x60, 0xC7, 0x50, 0x00, 0x78, 0xF0, 0x61, 0x00, 0x57, 0x87, 0x46, 0xE9, 0xF1, 0xF7, 0xA2, 0x00, 0x0C, 0x87, 0x43, 0x00, 0x1B, 0x8F, 0x09, 0x00, 0x08, 0xD2, 0x70, 0x00, 0x1D, 0x8F, 0x09, 0x00, 0x05, 0x96, 0x4C, 0x98, 0xD0, 0x7D, 0x96, 0xCF, 0x7D, 0x95, 0xCF, 0x7C, 0x93, 0xCE, 0x69, 0x7B, 0xAD, 0x00, 0x84, 0x2B, 0x87, 0x46, 0x00, 0x06, 0x81, 0xBC, 0x35, 0x00, 0x06, 0x86, 0x60, 0x00, 0x18, 0x81, 0xBD, 0x5A, 0x00, 0x42, 0xA9, 0x59, 0x00, 0x7B, 0xF0, 0x61, 0x00, 0x57, 0x87, 0x46, 0xAE, 0xCC, 0xE3, 0x00, 0x06, 0x87, 0x43, 0x90, 0xB9, 0xD9, 0x8F, 0xB7, 0x00, 0x17, 0x8F, 0x09, 0x00, 0x0F, 0xD2, 0x70, 0xA7, 0x00, 0x08, 0xC3, 0x67, 0x00, 0x1B, 0x8F, 0x09, 0x95, 0xCF, 0x7C, 0x94, 0xCF, 0x7C, 0x93, 0xCE, 0x7B, 0x91, 0xCE, 0x00, 0x48, 0x8F, 0x0F, 0x00, 0x0C, 0x99, 0x43, 0x00, 0x75, 0xC2, 0x78, 0x00, 0x82, 0x62, 0x87, 0x46, 0x00, 0x0C, 0x83, 0xF5, 0x6F, 0x00, 0x15, 0x84, 0x88, 0x5B, 0x00, 0x42, 0x83, 0xAF, 0x29, 0x00, 0x42, 0x83, 0xFB, 0x45, 0x00, 0x81, 0x10, 0x87, 0x46, 0xB4, 0xD0, 0xE5, 0x00, 0x0A, 0x87, 0x43, 0x00, 0x24, 0x8F, 0x09, 0x00, 0x14, 0xD2, 0x70, 0x00, 0x06, 0x8F, 0x09, 0x80, 0x00, 0x14, 0x8F, 0x09, 0x7B, 0x92, 0xCE, 0x7A, 0x90, 0xCE, 0x6C, 0x00, 0x47, 0x9E, 0x1E, 0x00, 0x0C, 0x87, 0x46, 0x00, 0x72, 0xA9, 0x4A, 0x00, 0x0C, 0xF2, 0x12, 0x00, 0x81, 0x5E, 0x81, 0xA4, 0x35, 0x00, 0x06, 0xA4, 0x63, 0x00, 0x0C, 0x94, 0x71, 0x00, 0x06, 0x81, 0xD7, 0x77, 0x00, 0x81, 0x43, 0xE4, 0x07, 0x00, 0x12, 0x81, 0x84, 0x60, 0x00, 0x81, 0x40, 0x87, 0x46, 0xB5, 0x00, 0x0B, 0x87, 0x43, 0x00, 0x05, 0xB4, 0x5E, 0x00, 0x0B, 0x8F, 0x09, 0x00, 0x09, 0xD2, 0x70, 0x00, 0x09, 0x8F, 0x09, 0x00, 0x18, 0xD2, 0x70, 0xA0, 0x00, 0x05, 0x96, 0x4C, 0x00, 0x14, 0x8F, 0x09, 0x7B, 0x92, 0xCE, 0x7B, 0x91, 0xCE, 0x7A, 0x90, 0xCD, 0x79, 0x8E, 0xCD, 0x45, 0x4B, 0x00, 0x43, 0x81, 0x8F, 0x50, 0x00, 0x0C, 0x8A, 0x46, 0x00, 0x72, 0xB8, 0x56, 0x00, 0x0C, 0x7E, 0x00, 0x81, 0x58, 0xC3, 0x76, 0x67, 0x68, 0x78, 0x00, 0x1E, 0x9C, 0x2E, 0x00, 0x81, 0x40, 0x82, 0xA5, 0x2F, 0x00, 0x6F, 0x81, 0x9D, 0x73, 0x00, 0x60, 0x87, 0x46, 0xC8, 0xDC, 0xEC, 0x00, 0x0A, 0x87, 0x43, 0x00, 0x0B, 0x8F, 0x09, 0x00, 0x2A, 0xD2, 0x70, 0x84, 0x00, 0x0B, 0xD2, 0x70, 0x00, 0x0F, 0x8F, 0x09, 0x7C, 0x00, 0x0B, 0x8F, 0x09, 0x79, 0x8F, 0xCD, 0x79, 0x8D, 0xCD, 0x5F, 0x6C, 0x9C, 0x00, 0x4E, 0x83, 0xF1, 0x0E, 0x00, 0x72, 0xC2, 0x78, 0x00, 0x7E, 0x90, 0x0A, 0x00, 0x6C, 0xCD, 0x1D, 0xE6, 0xE6, 0xE9, 0x00, 0x06, 0xD2, 0x01, 0x00, 0x06, 0xAC, 0x2C, 0x00, 0x06, 0x81, 0xB7, 0x36, 0x00, 0x0C, 0x81, 0xD5, 0x78, 0x00, 0x81, 0x37, 0x81, 0x9E, 0x6E, 0x00, 0x0C, 0x84, 0x40, 0x00, 0x81, 0x43, 0x87, 0x46, 0xCF, 0xE1, 0xEE, 0x00, 0x0C, 0x87, 0x43, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x10, 0xD2, 0x70, 0x00, 0x12, 0xE1, 0x79, 0x00, 0x18, 0xD2, 0x70, 0x00, 0x1B, 0x8F, 0x09, 0x8F, 0xCD, 0x79, 0x8E, 0xCD, 0x78, 0x8D, 0xCD, 0x77, 0x8B, 0xCC, 0x3C, 0x41, 0x5B, 0x00, 0x48, 0x85, 0x9C, 0x7D, 0x00, 0x75, 0x84, 0x87, 0x63, 0x00, 0x0C, 0x7B, 0x00, 0x81, 0x52, 0x81, 0x8D, 0x60, 0x00, 0x09, 0x87, 0x43, 0x00, 0x1E, 0x89, 0x21, 0x00, 0x09, 0xD8, 0x67, 0x00, 0x66, 0x87, 0x49, 0x00, 0x06, 0xDB, 0x7F, 0x00, 0x81, 0x61, 0xDA, 0x24, 0x00, 0x33, 0x87, 0x46, 0xE3, 0xEE, 0xF5, 0x96, 0xBD, 0xDB, 0x00, 0x13, 0x8F, 0x09, 0x00, 0x33, 0xD2, 0x70, 0x00, 0x08, 0x8F, 0x09, 0x00, 0x07, 0xC3, 0x67, 0x00, 0x17, 0x8F, 0x09, 0x78, 0x8C, 0xCC, 0x77, 0x8A, 0xCC, 0x5D, 0x6A, 0x9B, 0x00, 0x4E, 0x92, 0x12, 0x00, 0x6C, 0xD3, 0x05, 0x00, 0x0C, 0x9E, 0x15, 0x00, 0x81, 0x52, 0xD2, 0x7F, 0x00, 0x06, 0xD4, 0x5D, 0x00, 0x18, 0x81, 0xE8, 0x6D, 0x00, 0x6F, 0x85, 0xAE, 0x62, 0x00, 0x12, 0x83, 0xB1, 0x0D, 0x00, 0x0C, 0x83, 0x7E, 0x00, 0x3C, 0xBC, 0x4B, 0x00, 0x81, 0x2B, 0xBC, 0x1E, 0x00, 0x1E, 0x87, 0x46, 0xF2, 0xF6, 0xFA, 0x00, 0x0F, 0x87, 0x43, 0x00, 0x26, 0xD2, 0x70, 0x00, 0x11, 0x8F, 0x09, 0x00, 0x0F, 0xC3, 0x67, 0x9A, 0x00, 0x05, 0xC3, 0x67, 0x00, 0x07, 0x8F, 0x09, 0xCE, 0x00, 0x0D, 0x8F, 0x09, 0x8C, 0xCD, 0x77, 0x8B, 0xCC, 0x77, 0x8A, 0xCC, 0x76, 0x88, 0xCB, 0x3C, 0x40, 0x00, 0x40, 0x8F, 0x0F, 0x00, 0x78, 0xD9, 0x4D, 0x00, 0x0C, 0x88, 0x3E, 0x00, 0x81, 0x52, 0x81, 0xB3, 0x3E, 0x00, 0x06, 0x85, 0x5F, 0x00, 0x2A, 0xA5, 0x3D, 0x00, 0x06, 0x81, 0xB0, 0x47, 0x00, 0x5A, 0x85, 0xBD, 0x6E, 0x00, 0x06, 0xB4, 0x64, 0x00, 0x06, 0x88, 0x26, 0x00, 0x0C, 0x87, 0x46, 0x8D, 0x8E, 0x9A, 0x00, 0x3C, 0x81, 0x83, 0x23, 0x00, 0x81, 0x3A, 0x87, 0x43, 0x00, 0x0F, 0x87, 0x46, 0xA4, 0xC5, 0xE0, 0x00, 0x0D, 0x87, 0x43, 0x00, 0x17, 0x8F, 0x09, 0x00, 0x2B, 0xD2, 0x70, 0x00, 0x09, 0x8F, 0x09, 0x00, 0x06, 0xC3, 0x67, 0x00, 0x17, 0x8F, 0x09, 0x76, 0x89, 0xCB, 0x75, 0x88, 0xCB, 0x5D, 0x68, 0x00, 0x43, 0x8F, 0x0F, 0x00, 0x0C, 0x8A, 0x52, 0x00, 0x66, 0x81, 0x8C, 0x62, 0x00, 0x0F, 0xA9, 0x59, 0x00, 0x81, 0x4F, 0x82, 0x8A, 0x71, 0x00, 0x06, 0x8A, 0x19, 0x00, 0x30, 0xA7, 0x30, 0x00, 0x06, 0xE7, 0x7F, 0x00, 0x54, 0xAD, 0x36, 0x00, 0x0F, 0x85, 0xBD, 0x6E, 0x00, 0x0F, 0xB7, 0x55, 0x00, 0x3C, 0xAE, 0x2B, 0x00, 0x81, 0x46, 0x87, 0x46, 0xBE, 0xD6, 0xE9, 0x00, 0x16, 0x87, 0x43, 0x00, 0x45, 0xD2, 0x70, 0x00, 0x0B, 0x8F, 0x09, 0x7A, 0x00, 0x0A, 0x8F, 0x09, 0xCC, 0x77, 0x8B, 0xCC, 0x77, 0x89, 0xCC, 0x76, 0x88, 0xCB, 0x75, 0x87, 0xCB, 0x74, 0x85, 0xCA, 0x00, 0x42, 0x8F, 0x0F, 0x00, 0x0C, 0xAC, 0x2C, 0x00, 0x66, 0x81, 0x9D, 0x4C, 0x00, 0x0C, 0xF8, 0x5A, 0x00, 0x81, 0x52, 0xAD, 0x1E, 0x00, 0x1B, 0x83, 0x80, 0x72, 0x00, 0x21, 0x83, 0x06, 0x00, 0x51, 0xB0, 0x2A, 0x00, 0x06, 0x83, 0xCD, 0x38, 0x00, 0x0C, 0x83, 0x54, 0x00, 0x0F, 0x87, 0x46, 0x00, 0x3C, 0x82, 0x97, 0x1E, 0x00, 0x81, 0x43, 0x87, 0x46, 0xDA, 0xE7, 0xF2, 0x00, 0x0F, 0x87, 0x43, 0x00, 0x39, 0xE1, 0x79, 0x00, 0x10, 0xC3, 0x67, 0x00, 0x09, 0x8F, 0x09, 0x00, 0x06, 0xC3, 0x67, 0x92, 0x00, 0x05, 0xB4, 0x5E, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x06, 0x96, 0x4C, 0x89, 0xCB, 0x75, 0x87, 0xCB, 0x75, 0x86, 0xCB, 0x74, 0x84, 0xCA, 0x5B, 0x66, 0x00, 0x43, 0x8E, 0x3E, 0x00, 0x0C, 0x8F, 0x0F, 0x00, 0x60, 0xB4, 0x73, 0x00, 0x0F, 0xC0, 0x25, 0x00, 0x81, 0x52, 0x81, 0xD3, 0x31, 0x00, 0x39, 0x83, 0x9E, 0x51, 0x00, 0x06, 0x85, 0xD4, 0x76, 0x00, 0x60, 0xE2, 0x0E, 0x00, 0x12, 0x81, 0x1C, 0x00, 0x39, 0x75, 0x00, 0x81, 0x40, 0x87, 0x46, 0xEF, 0xF5, 0xF9, 0x97, 0x00, 0x0F, 0x9E, 0x0F, 0x00, 0x46, 0x8F, 0x09, 0x00, 0x0E, 0xC3, 0x67, 0x00, 0x14, 0x8F, 0x09, 0x76, 0x00, 0x06, 0x8F, 0x09, 0x86, 0xCB, 0x74, 0x85, 0xCA, 0x73, 0x84, 0xCA, 0x77, 0x87, 0xCB, 0x38, 0x3B, 0x53, 0x00, 0x81, 0x28, 0x83, 0xE2, 0x0E, 0x00, 0x0F, 0x96, 0x4C, 0x00, 0x81, 0x55, 0x82, 0xF6, 0x26, 0x00, 0x39, 0x90, 0x61, 0x00, 0x54, 0x83, 0xA6, 0x50, 0x00, 0x12, 0xF1, 0x1A, 0x00, 0x12, 0x63, 0x00, 0x39, 0x75, 0x00, 0x81, 0x40, 0x87, 0x46, 0xA4, 0xC6, 0x00, 0x10, 0x9E, 0x0F, 0x00, 0x4F, 0xD2, 0x70, 0x00, 0x09, 0x8F, 0x09, 0x00, 0x06, 0xC3, 0x67, 0x8F, 0xCD, 0x78, 0x00, 0x09, 0x8F, 0x09, 0x00, 0x05, 0x96, 0x4C, 0x00, 0x06, 0x8F, 0x09, 0x73, 0x83, 0xCA, 0x72, 0x81, 0xC9, 0x53, 0x5B, 0x8A, 0x00, 0x51, 0xEC, 0x51, 0x00, 0x54, 0xB3, 0x7B, 0x00, 0x0F, 0x81, 0xB8, 0x4C, 0x00, 0x81, 0x58, 0x85, 0x9C, 0x53, 0x00, 0x39, 0x87, 0x46, 0x00, 0x54, 0x83, 0xB5, 0x5C, 0x00, 0x06, 0x86, 0x81, 0x58, 0x00, 0x1B, 0x87, 0x34, 0x00, 0x06, 0x81, 0x9D, 0x58, 0x00, 0x81, 0x73, 0x87, 0x46, 0xC7, 0x00, 0x0E, 0xC3, 0x61, 0x00, 0x2D, 0xE1, 0x79, 0x00, 0x18, 0xD2, 0x70, 0x00, 0x15, 0xE1, 0x79, 0x00, 0x06, 0x8F, 0x09, 0x79, 0x00, 0x18, 0x8F, 0x09, 0x83, 0xCA, 0x72, 0x82, 0xC9, 0x72, 0x81, 0xC9, 0x6D, 0x7A, 0xC1, 0x00, 0x42, 0x8F, 0x0F, 0x00, 0x0F, 0x81, 0xA6, 0x10, 0x00, 0x15, 0x82, 0xB9, 0x3D, 0x00, 0x4B, 0x87, 0x43, 0x00, 0x81, 0x5B, 0x81, 0xE9, 0x7D, 0x00, 0x39, 0x87, 0x46, 0x00, 0x54, 0x83, 0xC4, 0x68, 0x00, 0x12, 0x84, 0x88, 0x3D, 0x00, 0x0F, 0x63, 0x00, 0x3C, 0x85, 0xDC, 0x06, 0x00, 0x81, 0x3A, 0x87, 0x43, 0xE3, 0xEE, 0xF6, 0x00, 0x12, 0x87, 0x43, 0x00, 0x10, 0xD2, 0x70, 0x00, 0x26, 0x81, 0xB4, 0x69, 0x00, 0x1E, 0xD2, 0x70, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x05, 0xC3, 0x67, 0x00, 0x0C, 0x8F, 0x09, 0x74, 0x85, 0xCA, 0x00, 0x09, 0x8F, 0x09, 0x71, 0x80, 0xC9, 0x71, 0x7E, 0xC8, 0x52, 0x59, 0x00, 0x43, 0x8F, 0x0F, 0x00, 0x12, 0x81, 0xC6, 0x78, 0x00, 0x48, 0xAD, 0x33, 0x00, 0x12, 0xED, 0x37, 0x00, 0x81, 0x5B, 0x81, 0xD1, 0x47, 0x00, 0x39, 0x81, 0xCB, 0x5F, 0x00, 0x57, 0x83, 0xBD, 0x22, 0x00, 0x1B, 0xAD, 0x24, 0x00, 0x06, 0x87, 0x64, 0x00, 0x39, 0xB0, 0x24, 0x00, 0x81, 0x37, 0x87, 0x43, 0xF8, 0xFB, 0xFD, 0x9E, 0xC2, 0xDE, 0x00, 0x24, 0x8F, 0x09, 0x00, 0x4C, 0xD2, 0x70, 0x00, 0x0B, 0x8F, 0x09, 0x75, 0x00, 0x0F, 0x8F, 0x09, 0x80, 0xC9, 0x71, 0x7F, 0xC9, 0x70, 0x7D, 0xC8, 0x6B, 0x78, 0xC0, 0x38, 0x3A, 0x00, 0x43, 0x8F, 0x0F, 0x00, 0x12, 0x87, 0x49, 0x00, 0x42, 0x83, 0xD3, 0x1D, 0x00, 0x0F, 0x97, 0x2C, 0x00, 0x51, 0x8F, 0x66, 0x00, 0x81, 0x16, 0x81, 0xD8, 0x45, 0x00, 0x36, 0xA5, 0x5E, 0x00, 0x54, 0x81, 0xBE, 0x61, 0x00, 0x06, 0x83, 0x54, 0xC0, 0xC0, 0xC7, 0x00, 0x06, 0x83, 0x48, 0x00, 0x09, 0x81, 0x1C, 0x00, 0x06, 0x81, 0x8E, 0x58, 0x00, 0x3C, 0xA2, 0x04, 0x00, 0x81, 0x37, 0x87, 0x46, 0xC1, 0xD8, 0xEA, 0x00, 0x18, 0x8F, 0x09, 0x00, 0x22, 0xD2, 0x70, 0x00, 0x14, 0x81, 0xB4, 0x69, 0x00, 0x24, 0xE1, 0x79, 0x00, 0x16, 0x8F, 0x09, 0x82, 0x00, 0x07, 0x8F, 0x09, 0x70, 0x7E, 0xC8, 0x70, 0x7D, 0xC8, 0x6F, 0x7B, 0xC8, 0x51, 0x58, 0x89, 0x00, 0x5A, 0x81, 0xDD, 0x4D, 0xB3, 0xB4, 0xBC, 0x00, 0x33, 0x87, 0x4C, 0x00, 0x06, 0x83, 0xC9, 0x28, 0x00, 0x81, 0x70, 0x84, 0x85, 0x4F, 0x00, 0x06, 0xC3, 0x43, 0x00, 0x30, 0x86, 0x1E, 0x00, 0x06, 0x36, 0x00, 0x57, 0xA7, 0x6F, 0x00, 0x0C, 0x83, 0x88, 0x38, 0x00, 0x0C, 0x83, 0x91, 0x08, 0x00, 0x3F, 0x8A, 0x4F, 0x00, 0x81, 0x4A, 0x96, 0x4C, 0x00, 0x12, 0xC3, 0x67, 0x00, 0x1B, 0x8F, 0x09, 0x00, 0x17, 0xD2, 0x70, 0x80, 0x00, 0x21, 0xD2, 0x70, 0x8B, 0x00, 0x07, 0xC3, 0x67, 0x00, 0x0A, 0xA5, 0x55, 0x82, 0x00, 0x05, 0x96, 0x4C, 0x00, 0x05, 0x8F, 0x09, 0x6F, 0x7C, 0xC8, 0x6E, 0x7A, 0xC7, 0x6A, 0x75, 0xBF, 0x00, 0x45, 0x8F, 0x0F, 0x00, 0x1B, 0x81, 0x9A, 0x01, 0x00, 0x06, 0xC0, 0x22, 0x00, 0x21, 0x87, 0x4F, 0x73, 0x75, 0x83, 0x00, 0x06, 0x82, 0xDF, 0x36, 0x00, 0x12, 0x88, 0x0B, 0x00, 0x81, 0x67, 0x81, 0xC9, 0x69, 0xE6, 0xE6, 0xE9, 0x00, 0x30, 0xCB, 0x09, 0x00, 0x06, 0x96, 0x4F, 0x00, 0x5D, 0xC6, 0x01, 0x00, 0x09, 0x82, 0xC0, 0x38, 0x00, 0x48, 0x82, 0xD9, 0x30, 0x00, 0x81, 0x34, 0x87, 0x46, 0xA5, 0x00, 0x14, 0xAD, 0x18, 0x00, 0x37, 0xD2, 0x70, 0x00, 0x0B, 0x81, 0xB4, 0x69, 0x00, 0x2A, 0xD2, 0x70, 0x00, 0x06, 0x8F, 0x09, 0x73, 0x00, 0x09, 0x8F, 0x09, 0x7F, 0x00, 0x09, 0x8F, 0x09, 0xC7, 0x6E, 0x79, 0xC7, 0x6D, 0x78, 0xC7, 0x50, 0x56, 0x00, 0x2E, 0x8F, 0x0F, 0x00, 0x1E, 0xFC, 0x43, 0x00, 0x15, 0x87, 0x0A, 0x00, 0x0C, 0x81, 0xC9, 0x2D, 0x00, 0x06, 0x82, 0xB9, 0x37, 0x00, 0x09, 0x30, 0x00, 0x0F, 0x83, 0x9C, 0x61, 0x00, 0x12, 0x81, 0xC1, 0x01, 0x00, 0x21, 0xFD, 0x2F, 0x00, 0x21, 0x21, 0x00, 0x0F, 0x0F, 0x00, 0x81, 0x1F, 0x81, 0xE2, 0x34, 0x00, 0x2A, 0x81, 0x22, 0x00, 0x06, 0xE0, 0x57, 0x00, 0x81, 0x31, 0xD5, 0x0A, 0x00, 0x81, 0x31, 0x87, 0x43, 0x00, 0x0F, 0xF0, 0x79, 0x00, 0x43, 0xE1, 0x79, 0x00, 0x10, 0xD2, 0x70, 0x00, 0x1C, 0xE1, 0x79, 0x00, 0x10, 0x8F, 0x09, 0x00, 0x07, 0xA5, 0x55, 0x00, 0x0A, 0x8F, 0x09, 0x6D, 0x79, 0xC7, 0x6D, 0x77, 0xC6, 0x6D, 0x77, 0x00, 0x2E, 0x81, 0xCC, 0x09, 0x00, 0x81, 0x37, 0x81, 0x83, 0x26, 0x00, 0x81, 0x25, 0x81, 0x88, 0x1F, 0x00, 0x2A, 0x81, 0xE2, 0x34, 0x00, 0x06, 0x2A, 0x00, 0x81, 0x34, 0xB6, 0x78, 0x00, 0x81, 0x2E, 0x84, 0x2E, 0xF1, 0xF6, 0xFA, 0x00, 0x12, 0xC3, 0x64, 0x00, 0x0D, 0x8F, 0x09, 0x00, 0x2B, 0xC3, 0x67, 0x00, 0x13, 0x81, 0xB4, 0x69, 0x00, 0x2A, 0xD2, 0x70, 0x00, 0x0F, 0x8F, 0x09, 0x6F, 0x7C, 0x00, 0x0A, 0x8F, 0x09, 0x6C, 0x76, 0xC6, 0x6B, 0x75, 0xC6, 0x49, 0x4D, 0x79, 0x00, 0x82, 0x1A, 0x87, 0x46, 0x00, 0x6F, 0x86, 0x27, 0x00, 0x06, 0x81, 0x95, 0x0E, 0x00, 0x09, 0xA4, 0x57, 0x00, 0x15, 0x92, 0x0C, 0x00, 0x06, 0xB4, 0x5E, 0x00, 0x81, 0x37, 0xA0, 0x2F, 0x00, 0x81, 0x2E, 0x84, 0x2E, 0xB3, 0xCF, 0x00, 0x0B, 0x81, 0x87, 0x45, 0x00, 0x64, 0xD2, 0x70, 0x00, 0x08, 0x8F, 0x09, 0x00, 0x11, 0xD2, 0x70, 0x00, 0x0C, 0xB4, 0x5E, 0x00, 0x06, 0xA5, 0x55, 0x00, 0x09, 0x8F, 0x09, 0x6C, 0x75, 0xC6, 0x6B, 0x74, 0xC6, 0x63, 0x6B, 0xB6, 0x00, 0x82, 0x1A, 0x87, 0x46, 0x00, 0x06, 0x82, 0xB6, 0x76, 0x00, 0x60, 0xE2, 0x7D, 0x00, 0x0C, 0x81, 0xD2, 0x03, 0x00, 0x09, 0xA7, 0x60, 0x00, 0x09, 0x82, 0xF6, 0x3E, 0x00, 0x0C, 0x84, 0x99, 0x78, 0x00, 0x0C, 0x81, 0x87, 0x6F, 0x00, 0x63, 0x84, 0xF1, 0x55, 0x00, 0x06, 0xC4, 0x02, 0x00, 0x06, 0x81, 0x9E, 0x32, 0x00, 0x0C, 0x83, 0xF9, 0x5E, 0x00, 0x81, 0x64, 0x87, 0x46, 0x00, 0x1F, 0xA5, 0x55, 0x00, 0x44, 0xE1, 0x79, 0x00, 0x2A, 0xD2, 0x70, 0x00, 0x1C, 0x8F, 0x09, 0x74, 0xC6, 0x6B, 0x73, 0xC5, 0x6A, 0x72, 0xC5, 0x48, 0x4C, 0x00, 0x28, 0x8F, 0x0F, 0x00, 0x81, 0x70, 0x87, 0x46, 0x00, 0x09, 0xAE, 0x31, 0x00, 0x5D, 0x83, 0xF0, 0x01, 0x00, 0x57, 0x84, 0x8B, 0x0D, 0x00, 0x42, 0xBF, 0x30, 0x00, 0x06, 0x84, 0x84, 0x15, 0x00, 0x09, 0xA1, 0x45, 0x00, 0x06, 0xAE, 0x13, 0x00, 0x3C, 0x91, 0x20, 0x00, 0x81, 0x41, 0xA5, 0x55, 0x00, 0x23, 0xD2, 0x70, 0x00, 0x0C, 0x82, 0x87, 0x59, 0x00, 0x30, 0xD2, 0x70, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x11, 0xD2, 0x70, 0x00, 0x10, 0x8F, 0x09, 0x78, 0xC7, 0x6C, 0x00, 0x08, 0x8F, 0x09, 0x6A, 0x72, 0xC5, 0x69, 0x71, 0xC5, 0x62, 0x68, 0xB5, 0x00, 0x82, 0x1D, 0x83, 0xC6, 0x5B, 0x00, 0x09, 0xB6, 0x48, 0xE6, 0xE6, 0xE9, 0x00, 0x45, 0x8D, 0x13, 0x00, 0x15, 0x83, 0xDB, 0x1F, 0x00, 0x3F, 0x85, 0x98, 0x16, 0x00, 0x4B, 0x81, 0xAC, 0x6D, 0x00, 0x06, 0x81, 0x81, 0x06, 0x00, 0x12, 0x9F, 0x22, 0x00, 0x06, 0x81, 0xD2, 0x4B, 0x00, 0x3C, 0xE5, 0x7D, 0x00, 0x81, 0x28, 0x87, 0x43, 0xD5, 0xE5, 0xF1, 0x00, 0x34, 0x8F, 0x09, 0x00, 0x14, 0x82, 0x87, 0x59, 0x00, 0x48, 0xD2, 0x70, 0x00, 0x09, 0xB4, 0x5E, 0x6F, 0x7A, 0x00, 0x11, 0x8F, 0x09, 0x71, 0xC5, 0x69, 0x70, 0xC4, 0x68, 0x6F, 0xC4, 0x47, 0x4B, 0x00, 0x82, 0x1E, 0x82, 0x9B, 0x61, 0x41, 0x43, 0x56, 0x8D, 0x8E, 0x9A, 0x00, 0x0C, 0x81, 0x95, 0x77, 0x00, 0x81, 0x5B, 0xCC, 0x4C, 0x00, 0x06, 0x82, 0xDB, 0x17, 0x00, 0x54, 0x86, 0x89, 0x2A, 0x00, 0x81, 0x28, 0x87, 0x46, 0x00, 0x15, 0xCB, 0x2A, 0x00, 0x2B, 0xE1, 0x79, 0x00, 0x44, 0xD2, 0x70, 0x75, 0x85, 0x00, 0x24, 0x8F, 0x09, 0xC5, 0x00, 0x06, 0x8F, 0x09, 0x68, 0x6F, 0xC4, 0x68, 0x6E, 0xC4, 0x60, 0x65, 0xB4, 0x00, 0x82, 0x29, 0x83, 0xD5, 0x76, 0x00, 0x0C, 0x8F, 0x1B, 0x00, 0x81, 0x52, 0x82, 0x87, 0x3B, 0x00, 0x06, 0x96, 0x4C, 0x00, 0x57, 0x81, 0xE2, 0x55, 0x00, 0x81, 0x50, 0x8F, 0x09, 0x00, 0x26, 0x82, 0x87, 0x59, 0x00, 0x21, 0x81, 0xB4, 0x69, 0x00, 0x27, 0xD2, 0x70, 0x00, 0x06, 0xB4, 0x5E, 0x6E, 0x79, 0xC7, 0x6D, 0x77, 0x00, 0x07, 0x8F, 0x09, 0x6A, 0x00, 0x09, 0x8F, 0x09, 0x6E, 0xC4, 0x67, 0x6D, 0xC4, 0x66, 0x6B, 0xC3, 0x47, 0x4A, 0x00, 0x82, 0x27, 0x83, 0x99, 0x07, 0x00, 0x0F, 0x82, 0xF3, 0x47, 0x00, 0x66, 0xA6, 0x02, 0x00, 0x6C, 0xAE, 0x28, 0x00, 0x1E, 0x97, 0x0E, 0x00, 0x06, 0x8F, 0x0F, 0x00, 0x81, 0x5B, 0x87, 0x46, 0x00, 0x16, 0x8F, 0x09, 0x00, 0x0E, 0xE1, 0x79, 0x00, 0x78, 0xD2, 0x70, 0x00, 0x07, 0x96, 0x4C, 0x77, 0xC6, 0x6B, 0x00, 0x09, 0x8F, 0x09, 0x70, 0x00, 0x05, 0x8F, 0x09, 0x6D, 0xC4, 0x67, 0x6C, 0xC3, 0x66, 0x6B, 0xC3, 0x5C, 0x5F, 0xAC, 0x00, 0x82, 0x2F, 0x96, 0x55, 0x5A, 0x5C, 0x6D, 0x00, 0x09, 0x82, 0x86, 0x3A, 0x00, 0x81, 0x49, 0x81, 0x89, 0x02, 0x00, 0x24, 0xC6, 0x1F, 0x00, 0x81, 0x5B, 0xF8, 0x60, 0x00, 0x21, 0x8F, 0x09, 0x00, 0x3A, 0xD2, 0x70, 0x00, 0x1D, 0x81, 0xB4, 0x69, 0x00, 0x27, 0xD2, 0x70, 0x00, 0x05, 0x8F, 0x09, 0xC6, 0x00, 0x18, 0x8F, 0x09, 0x65, 0x6A, 0xC3, 0x65, 0x68, 0xC2, 0x3A, 0x3C, 0x5A, 0x00, 0x82, 0x17, 0x81, 0xD1, 0x3B, 0x00, 0x0F, 0xA5, 0x61, 0x00, 0x0F, 0x96, 0x46, 0x4D, 0x4F, 0x62, 0x00, 0x81, 0x49, 0x82, 0xA5, 0x62, 0x73, 0x75, 0x83, 0x00, 0x21, 0x84, 0x81, 0x18, 0x00, 0x81, 0x5B, 0xF8, 0x60, 0x00, 0x1B, 0x8F, 0x09, 0x00, 0x3C, 0x82, 0x87, 0x59, 0x00, 0x1F, 0xD2, 0x70, 0x8D, 0x00, 0x10, 0xD2, 0x70, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x11, 0xD2, 0x70, 0x00, 0x06, 0xC3, 0x67, 0x00, 0x0C, 0x8F, 0x09, 0x67, 0x00, 0x06, 0x8F, 0x09, 0x6A, 0xC3, 0x65, 0x69, 0xC2, 0x64, 0x67, 0xC2, 0x4D, 0x51, 0x81, 0x00, 0x82, 0x11, 0x81, 0xFE, 0x59, 0x00, 0x09, 0xD4, 0x24, 0x00, 0x81, 0x67, 0x84, 0xA4, 0x6E, 0x00, 0x06, 0x81, 0xBB, 0x79, 0x00, 0x1E, 0x84, 0x81, 0x18, 0x00, 0x39, 0xD5, 0x4C, 0x00, 0x81, 0x3E, 0x8F, 0x09, 0x00, 0x42, 0xD2, 0x70, 0x00, 0x1D, 0x81, 0xB4, 0x69, 0x00, 0x16, 0xD2, 0x70, 0x00, 0x0B, 0x8F, 0x09, 0x00, 0x0C, 0xC3, 0x67, 0x00, 0x0D, 0x8F, 0x09, 0x00, 0x05, 0x96, 0x4C, 0x65, 0x6A, 0xC3, 0x64, 0x68, 0xC2, 0x64, 0x67, 0xC2, 0x4C, 0x4E, 0x86, 0x00, 0x82, 0x11, 0x84, 0x97, 0x1C, 0x00, 0x09, 0x96, 0x3D, 0x00, 0x81, 0x6D, 0x82, 0x80, 0x4F, 0x00, 0x18, 0xD3, 0x5F, 0x00, 0x06, 0xCC, 0x5E, 0x00, 0x39, 0xA7, 0x51, 0x00, 0x81, 0x39, 0x8F, 0x09, 0x00, 0x16, 0xE1, 0x79, 0x00, 0x4C, 0xD2, 0x70, 0x00, 0x1B, 0xE1, 0x79, 0x00, 0x11, 0xD2, 0x70, 0x00, 0x06, 0xC3, 0x67, 0x00, 0x15, 0x8F, 0x09, 0x63, 0x66, 0xC1, 0x60, 0x65, 0xA7, 0x00, 0x82, 0x11, 0x82, 0x86, 0x1F, 0x00, 0x81, 0x0D, 0xA5, 0x37, 0x00, 0x06, 0x81, 0xCB, 0x6B, 0x00, 0x66, 0xF9, 0x73, 0x00, 0x0F, 0xAF, 0x02, 0x00, 0x06, 0x98, 0x57, 0x00, 0x3F, 0x81, 0x8A, 0x72, 0x00, 0x81, 0x1C, 0x87, 0x43, 0xDC, 0xE9, 0xF3, 0x00, 0x64, 0xD2, 0x70, 0x00, 0x1B, 0x8F, 0x09, 0x00, 0x18, 0xC3, 0x67, 0x00, 0x12, 0x8F, 0x09, 0x00, 0x05, 0xB4, 0x5E, 0x00, 0x0D, 0x8F, 0x09, 0x69, 0x00, 0x07, 0x8F, 0x09, 0x63, 0x65, 0xC1, 0x57, 0x58, 0xA4, 0x00, 0x82, 0x7D, 0x83, 0xBD, 0x16, 0x00, 0x1B, 0x8D, 0x64, 0x00, 0x06, 0x84, 0xB5, 0x19, 0x00, 0x0C, 0xF3, 0x73, 0x00, 0x57, 0x88, 0x5F, 0x00, 0x33, 0xCF, 0x1F, 0x00, 0x81, 0x46, 0x87, 0x46, 0xAC, 0xCB, 0x00, 0x0A, 0x81, 0xF1, 0x01, 0x00, 0x55, 0x81, 0xB4, 0x69, 0x00, 0x21, 0xD2, 0x70, 0x00, 0x24, 0xE1, 0x79, 0x00, 0x08, 0xD2, 0x70, 0x00, 0x06, 0xC3, 0x67, 0x00, 0x06, 0xA5, 0x55, 0x00, 0x0C, 0x8F, 0x09, 0x63, 0x64, 0xC1, 0x5D, 0x62, 0xA0, 0x00, 0x82, 0x7A, 0x83, 0xBD, 0x1C, 0x00, 0x06, 0xD1, 0x72, 0x00, 0x15, 0x87, 0x49, 0x00, 0x0F, 0x81, 0xA8, 0x72, 0x00, 0x5D, 0x81, 0x99, 0x09, 0x00, 0x24, 0x85, 0xCC, 0x7A, 0x00, 0x39, 0x82, 0xAE, 0x71, 0x00, 0x81, 0x19, 0x87, 0x43, 0xEA, 0xF2, 0xF8, 0x00, 0x29, 0x8F, 0x09, 0x00, 0x3D, 0x82, 0x87, 0x59, 0x00, 0x21, 0x81, 0xB4, 0x69, 0x00, 0x18, 0xE1, 0x79, 0x00, 0x0F, 0xD2, 0x70, 0x69, 0x00, 0x05, 0xC3, 0x67, 0x00, 0x0D, 0x8F, 0x09, 0x66, 0xC2, 0x63, 0x65, 0xC1, 0x62, 0x63, 0xC1, 0x4B, 0x4C, 0x00, 0x82, 0x0F, 0x9E, 0x18, 0x00, 0x6F, 0x81, 0x8F, 0x35, 0x00, 0x18, 0xBB, 0x29, 0x00, 0x09, 0x83, 0xAE, 0x34, 0x00, 0x06, 0x8F, 0x00, 0x4D, 0x4F, 0x62, 0x00, 0x06, 0x30, 0x00, 0x81, 0x31, 0xB5, 0x5F, 0x00, 0x81, 0x19, 0x87, 0x46, 0xBA, 0xD3, 0xE7, 0x00, 0x6C, 0xD2, 0x70, 0x00, 0x1B, 0xE1, 0x79, 0x00, 0x2A, 0xD2, 0x70, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x06, 0x96, 0x4C, 0x66, 0xC1, 0x62, 0x64, 0xC1, 0x62, 0x62, 0xC1, 0x4A, 0x00, 0x2C, 0xF1, 0x26, 0x00, 0x82, 0x50, 0x82, 0xB4, 0x29, 0x00, 0x18, 0xC2, 0x4B, 0x00, 0x18, 0x81, 0xD3, 0x13, 0x00, 0x06, 0xE9, 0x63, 0x00, 0x81, 0x2E, 0x81, 0x99, 0x12, 0x00, 0x81, 0x19, 0x81, 0x9E, 0x1D, 0x00, 0x15, 0xF8, 0x48, 0x00, 0x31, 0x81, 0xB4, 0x69, 0x00, 0x08, 0xD2, 0x70, 0x00, 0x1E, 0x82, 0x87, 0x59, 0x00, 0x16, 0x81, 0xB4, 0x69, 0x00, 0x32, 0xD2, 0x70, 0x00, 0x15, 0x8F, 0x09, 0x61, 0x62, 0xC0, 0x3E, 0x42, 0x5C, 0x00, 0x82, 0x1D, 0x82, 0x8D, 0x71, 0x00, 0x57, 0x82, 0xC2, 0x3D, 0x00, 0x1E, 0x84, 0xCC, 0x1E, 0x00, 0x06, 0x8E, 0x77, 0x00, 0x12, 0x1E, 0x00, 0x81, 0x34, 0x85, 0x89, 0x04, 0x00, 0x81, 0x2B, 0xB4, 0x61, 0x00, 0x5A, 0x82, 0x87, 0x59, 0x00, 0x1F, 0xD2, 0x70, 0x00, 0x0B, 0x8F, 0x09, 0x00, 0x0F, 0xD2, 0x70, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x0E, 0xC3, 0x67, 0x00, 0x06, 0xA5, 0x55, 0x00, 0x06, 0x8F, 0x09, 0x53, 0x54, 0x00, 0x43, 0x81, 0xDB, 0x09, 0x00, 0x81, 0x58, 0xAD, 0x2A, 0x00, 0x0F, 0x85, 0xA0, 0x54, 0x00, 0x4E, 0x81, 0x8F, 0x7D, 0x00, 0x06, 0xA5, 0x37, 0x00, 0x18, 0xA5, 0x5B, 0x00, 0x1B, 0x1E, 0x00, 0x33, 0x81, 0x97, 0x2E, 0x00, 0x33, 0x82, 0xCD, 0x39, 0x00, 0x81, 0x61, 0x87, 0x46, 0x00, 0x13, 0xF1, 0x05, 0x00, 0x18, 0x82, 0x87, 0x59, 0x00, 0x65, 0xD2, 0x70, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x18, 0xD2, 0x70, 0x00, 0x0C, 0x8F, 0x09, 0x67, 0x00, 0x05, 0x8F, 0x09, 0x64, 0x00, 0x07, 0x8F, 0x09, 0x3F, 0x41, 0x68, 0x00, 0x82, 0x1A, 0x82, 0xFD, 0x69, 0x00, 0x09, 0xF6, 0x6A, 0x00, 0x09, 0x81, 0xFF, 0x51, 0x00, 0x4B, 0x81, 0xAC, 0x43, 0x00, 0x1E, 0x9D, 0x62, 0x00, 0x1B, 0x96, 0x6D, 0x00, 0x54, 0x81, 0xB5, 0x10, 0x00, 0x06, 0x9E, 0x75, 0x00, 0x0F, 0x81, 0x9A, 0x40, 0x00, 0x48, 0x84, 0xAF, 0x34, 0x00, 0x81, 0x28, 0xA5, 0x58, 0x00, 0x60, 0x82, 0x87, 0x59, 0x00, 0x10, 0x8F, 0x09, 0x00, 0x3B, 0xD2, 0x70, 0x00, 0x09, 0x8F, 0x09, 0x61, 0x62, 0xC0, 0x56, 0x56, 0xA3, 0x00, 0x82, 0x1A, 0x85, 0x83, 0x4C, 0x00, 0x12, 0x95, 0x36, 0x00, 0x06, 0x95, 0x66, 0x00, 0x45, 0x8F, 0x12, 0x00, 0x06, 0xCA, 0x2C, 0x00, 0x18, 0xD1, 0x75, 0x00, 0x06, 0xB3, 0x78, 0x00, 0x18, 0x96, 0x37, 0x00, 0x51, 0x81, 0xC4, 0x1C, 0x00, 0x06, 0x81, 0x9F, 0x15, 0x00, 0x06, 0x83, 0xF2, 0x1B, 0x00, 0x09, 0x8F, 0x7E, 0x00, 0x06, 0x82, 0x89, 0x0D, 0x00, 0x45, 0x81, 0xA9, 0x13, 0x00, 0x81, 0x26, 0x81, 0xB4, 0x6C, 0x00, 0x65, 0x82, 0x87, 0x59, 0x00, 0x20, 0xD2, 0x70, 0x00, 0x08, 0x8F, 0x09, 0x00, 0x18, 0xD2, 0x70, 0x6B, 0x00, 0x07, 0xB4, 0x5E, 0x00, 0x0A, 0x8F, 0x09, 0x61, 0x00, 0x82, 0x15, 0x8F, 0x09, 0x00, 0x06, 0x81, 0x8F, 0x32, 0x00, 0x1B, 0x84, 0xF9, 0x12, 0x00, 0x45, 0x81, 0xE1, 0x30, 0x00, 0x06, 0x87, 0x46, 0x00, 0x18, 0x88, 0x11, 0x00, 0x06, 0x86, 0x57, 0x00, 0x18, 0x1E, 0x00, 0x06, 0x88, 0x65, 0x00, 0x48, 0xF2, 0x1B, 0x00, 0x06, 0x81, 0xA9, 0x43, 0x00, 0x18, 0x8E, 0x74, 0x00, 0x06, 0x81, 0xD3, 0x1F, 0x00, 0x3F, 0x91, 0x02, 0x00, 0x81, 0x25, 0xCB, 0x30, 0x00, 0x66, 0x82, 0x87, 0x59, 0x00, 0x28, 0xD2, 0x70, 0x00, 0x12, 0x8F, 0x09, 0x6C, 0x00, 0x11, 0x8F, 0x09, 0x00, 0x05, 0x96, 0x4C, 0x00, 0x6C, 0x8F, 0x09, 0x00, 0x4E, 0x82, 0x8C, 0x28, 0x00, 0x7B, 0x83, 0x8F, 0x12, 0x00, 0x06, 0x81, 0xA5, 0x09, 0x00, 0x45, 0xA5, 0x6D, 0x00, 0x1B, 0x96, 0x52, 0x00, 0x1B, 0x85, 0xA7, 0x37, 0x00, 0x4E, 0x96, 0x52, 0x00, 0x06, 0x81, 0xB8, 0x4F, 0x00, 0x1E, 0x81, 0x4F, 0x00, 0x06, 0x98, 0x60, 0x00, 0x3C, 0x81, 0x88, 0x46, 0x00, 0x81, 0x23, 0x81, 0x96, 0x5D, 0x00, 0x61, 0x82, 0x87, 0x59, 0x00, 0x4F, 0xD2, 0x70, 0x00, 0x63, 0x8F, 0x09, 0x00, 0x06, 0x81, 0x9B, 0x77, 0x00, 0x09, 0x82, 0xB9, 0x4C, 0x00, 0x81, 0x2E, 0x81, 0xF8, 0x4A, 0x00, 0x06, 0x87, 0x46, 0x00, 0x18, 0x86, 0x42, 0x00, 0x1E, 0x1E, 0x00, 0x48, 0x87, 0x46, 0x00, 0x06, 0x82, 0x38, 0x00, 0x18, 0x8E, 0x6E, 0x00, 0x4B, 0x87, 0x46, 0x00, 0x06, 0xEB, 0x2C, 0x00, 0x27, 0x81, 0xED, 0x72, 0x00, 0x81, 0x49, 0x81, 0xD3, 0x28, 0x00, 0x12, 0xBC, 0x27, 0x00, 0x6A, 0x82, 0x87, 0x59, 0x00, 0x2A, 0xD2, 0x70, 0x73, 0x00, 0x1C, 0xD2, 0x70, 0x00, 0x06, 0x8F, 0x09, 0x58, 0x59, 0xAA, 0x00, 0x54, 0xBA, 0x01, 0x00, 0x12, 0xA2, 0x22, 0x00, 0x81, 0x31, 0x87, 0x46, 0x00, 0x06, 0x95, 0x6C, 0x00, 0x1E, 0x8F, 0x0C, 0x00, 0x45, 0x95, 0x4E, 0x00, 0x06, 0x87, 0x0D, 0x00, 0x12, 0x4B, 0x00, 0x06, 0xBC, 0x48, 0x00, 0x1B, 0x95, 0x45, 0x00, 0x48, 0x85, 0xB6, 0x28, 0x00, 0x06, 0x8F, 0x09, 0x00, 0x2A, 0x81, 0xE3, 0x29, 0x00, 0x81, 0x49, 0x81, 0xE2, 0x34, 0x00, 0x0F, 0x96, 0x4F, 0x00, 0x66, 0x82, 0x87, 0x59, 0x00, 0x2B, 0xD2, 0x70, 0x00, 0x11, 0x8F, 0x09, 0x00, 0x12, 0xD2, 0x70, 0x62, 0x62, 0xC1, 0x61, 0x61, 0xC0, 0x45, 0x46, 0x77, 0x00, 0x51, 0x82, 0xC8, 0x46, 0x00, 0x4E, 0x81, 0xA3, 0x22, 0x00, 0x7B, 0x81, 0x8E, 0x13, 0xC0, 0xC0, 0xC7, 0x00, 0x18, 0x86, 0x27, 0x00, 0x06, 0x82, 0x95, 0x40, 0x00, 0x4B, 0xA4, 0x54, 0x00, 0x12, 0x8E, 0x0B, 0x00, 0x1E, 0xCB, 0x51, 0x00, 0x06, 0x8E, 0x17, 0x00, 0x45, 0x82, 0x83, 0x49, 0xA6, 0xA7, 0xB0, 0x00, 0x2A, 0xBC, 0x78, 0x00, 0x06, 0xF3, 0x2E, 0x00, 0x81, 0x43, 0x87, 0x46, 0x00, 0x12, 0xAD, 0x1E, 0x00, 0x72, 0x82, 0x87, 0x59, 0x00, 0x28, 0xD2, 0x70, 0x00, 0x12, 0x8F, 0x09, 0x00, 0x0B, 0xC3, 0x67, 0x5B, 0x5B, 0xB1, 0x00, 0x4B, 0x8D, 0x3A, 0x00, 0x2A, 0x82, 0xB8, 0x57, 0x00, 0x2A, 0x86, 0x00, 0x00, 0x06, 0x81, 0xA3, 0x10, 0x00, 0x78, 0xF7, 0x59, 0x00, 0x06, 0x81, 0xE7, 0x69, 0x00, 0x0F, 0xE0, 0x7B, 0x00, 0x06, 0x81, 0xBB, 0x5B, 0x00, 0x4B, 0xD9, 0x47, 0x00, 0x09, 0x82, 0x82, 0x30, 0x00, 0x0C, 0x81, 0x67, 0x00, 0x09, 0x82, 0xAD, 0x7F, 0x00, 0x18, 0x95, 0x3F, 0x00, 0x4B, 0x85, 0x90, 0x4A, 0x00, 0x06, 0x81, 0xB4, 0x6F, 0x00, 0x2D, 0x98, 0x69, 0x00, 0x81, 0x43, 0x87, 0x46, 0x00, 0x0F, 0xAD, 0x1E, 0x00, 0x52, 0x82, 0xDA, 0x49, 0x00, 0x23, 0x81, 0xB4, 0x69, 0x00, 0x10, 0xD2, 0x70, 0x00, 0x12, 0xE1, 0x79, 0x00, 0x20, 0xD2, 0x70, 0x00, 0x4B, 0x8F, 0x09, 0x00, 0x1B, 0x82, 0xFC, 0x2F, 0x00, 0x09, 0x84, 0xBA, 0x06, 0x00, 0x06, 0x82, 0xA2, 0x65, 0x00, 0x2D, 0x87, 0x46, 0x00, 0x0C, 0x83, 0xB1, 0x55, 0x00, 0x66, 0xD0, 0x6B, 0x00, 0x06, 0x90, 0x4C, 0x00, 0x0C, 0x81, 0xAC, 0x13, 0x00, 0x0C, 0x81, 0xB5, 0x13, 0x00, 0x0C, 0x83, 0x9E, 0x2A, 0x00, 0x4E, 0x83, 0xBC, 0x54, 0x00, 0x09, 0x87, 0x34, 0x00, 0x06, 0x85, 0xF2, 0x4F, 0x00, 0x09, 0x66, 0x00, 0x1B, 0x95, 0x3C, 0x00, 0x06, 0x82, 0x1A, 0x00, 0x48, 0x97, 0x53, 0x00, 0x81, 0x73, 0x87, 0x46, 0x00, 0x10, 0x96, 0x4F, 0x00, 0x77, 0x82, 0x87, 0x59, 0x00, 0x3F, 0xD2, 0x70, 0x00, 0x48, 0x8F, 0x09, 0x00, 0x15, 0x82, 0xDE, 0x26, 0x00, 0x06, 0x83, 0x94, 0x05, 0x00, 0x0F, 0x8D, 0x2E, 0x00, 0x09, 0x85, 0x1D, 0x00, 0x24, 0x86, 0x00, 0x00, 0x09, 0x85, 0xE9, 0x25, 0x00, 0x6C, 0x82, 0x80, 0x4C, 0x00, 0x30, 0xEF, 0x18, 0x00, 0x5D, 0x83, 0xD1, 0x4E, 0x00, 0x1B, 0x95, 0x66, 0x00, 0x18, 0xBD, 0x49, 0x00, 0x39, 0x98, 0x39, 0x00, 0x2D, 0x87, 0x46, 0x00, 0x81, 0x43, 0x82, 0x97, 0x1E, 0xF1, 0xF6, 0xFA, 0x00, 0x4B, 0x82, 0x87, 0x59, 0x00, 0x19, 0xD2, 0x70, 0x00, 0x2C, 0x81, 0xB4, 0x69, 0x00, 0x07, 0xC3, 0x67, 0x00, 0x12, 0x8F, 0x09, 0x00, 0x08, 0xC3, 0x67, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x08, 0xD2, 0x70, 0x00, 0x48, 0x8F, 0x09, 0x00, 0x0F, 0x83, 0xB5, 0x6B, 0x00, 0x1E, 0x84, 0x97, 0x2B, 0x00, 0x2D, 0x87, 0x46, 0x00, 0x12, 0x5D, 0x00, 0x81, 0x61, 0x85, 0xBA, 0x68, 0x00, 0x09, 0x84, 0xF1, 0x22, 0x00, 0x21, 0x84, 0xB2, 0x73, 0x00, 0x06, 0x97, 0x53, 0x00, 0x48, 0xF8, 0x63, 0x00, 0x2D, 0x82, 0xB5, 0x0C, 0xA6, 0xA7, 0xB0, 0x00, 0x81, 0x43, 0x81, 0xAD, 0x4A, 0xCE, 0xE0, 0x00, 0x0B, 0x82, 0xCB, 0x43, 0x00, 0x21, 0x82, 0xDA, 0x49, 0x00, 0x5F, 0x82, 0x87, 0x59, 0x00, 0x19, 0x8F, 0x09, 0x00, 0x18, 0xD2, 0x70, 0x00, 0x4D, 0x8F, 0x09, 0x00, 0x12, 0x8D, 0x3A, 0x00, 0x1E, 0x82, 0x80, 0x49, 0x00, 0x30, 0x87, 0x46, 0x00, 0x12, 0x87, 0x49, 0x00, 0x82, 0x0B, 0x85, 0x89, 0x79, 0x00, 0x4B, 0x81, 0x80, 0x26, 0x00, 0x06, 0xAE, 0x0D, 0x00, 0x27, 0x51, 0x00, 0x81, 0x46, 0x81, 0xBC, 0x56, 0x00, 0x0C, 0x81, 0xDA, 0x4A, 0x00, 0x81, 0x01, 0x82, 0x87, 0x59, 0x00, 0x36, 0xD2, 0x70, 0x61, 0x61, 0xC0, 0x4A, 0x4B, 0x00, 0x40, 0xF8, 0x4B, 0x00, 0x0F, 0x95, 0x72, 0x00, 0x24, 0x93, 0x61, 0x00, 0x33, 0x87, 0x46, 0x00, 0x12, 0x82, 0xDF, 0x0C, 0x00, 0x82, 0x56, 0x84, 0xC7, 0x6A, 0x00, 0x06, 0x9F, 0x0D, 0x00, 0x24, 0x8F, 0x36, 0x00, 0x3C, 0xB5, 0x5C, 0x00, 0x81, 0x0A, 0x87, 0x46, 0x00, 0x0A, 0xF1, 0x0B, 0x00, 0x2F, 0x82, 0x87, 0x59, 0x00, 0x2B, 0xD2, 0x70, 0x00, 0x33, 0x81, 0xB4, 0x69, 0x00, 0x2A, 0xD2, 0x70, 0x62, 0xC0, 0x5D, 0x5D, 0xB9, 0x37, 0x39, 0x52, 0x00, 0x4B, 0x82, 0xDA, 0x22, 0x00, 0x27, 0xAA, 0x2D, 0x00, 0x36, 0x87, 0x46, 0x00, 0x06, 0x81, 0x86, 0x08, 0x00, 0x81, 0x5B, 0x82, 0xCC, 0x05, 0x00, 0x81, 0x0A, 0x81, 0x88, 0x6D, 0x00, 0x1E, 0x82, 0x5C, 0x00, 0x42, 0x83, 0xEB, 0x6E, 0x00, 0x81, 0x13, 0xB4, 0x64, 0x00, 0x81, 0x07, 0x82, 0x87, 0x59, 0x00, 0x19, 0xD2, 0x70, 0x00, 0x12, 0x8F, 0x09, 0x00, 0x05, 0x87, 0x43, 0x00, 0x45, 0x8F, 0x09, 0x00, 0x0F, 0x82, 0xDE, 0x23, 0x00, 0x27, 0x86, 0x5A, 0x00, 0x36, 0x87, 0x46, 0x00, 0x12, 0x84, 0x82, 0x04, 0x00, 0x82, 0x56, 0x85, 0xE8, 0x18, 0x00, 0x06, 0x81, 0xCB, 0x5C, 0xCC, 0xCD, 0xD2, 0x00, 0x12, 0x9F, 0x13, 0x00, 0x09, 0xB8, 0x47, 0x00, 0x3F, 0xB5, 0x59, 0x00, 0x81, 0x11, 0x9E, 0x15, 0x00, 0x6B, 0x82, 0xDA, 0x49, 0x00, 0x21, 0x82, 0x87, 0x59, 0x00, 0x2D, 0xD2, 0x70, 0x00, 0x42, 0x8F, 0x09, 0x00, 0x0F, 0x82, 0xBC, 0x10, 0x00, 0x2A, 0x87, 0x13, 0x00, 0x39, 0x87, 0x46, 0x00, 0x0F, 0x8F, 0x7B, 0x00, 0x82, 0x11, 0x83, 0xE1, 0x25, 0x00, 0x51, 0x82, 0x97, 0x15, 0x00, 0x06, 0xDA, 0x30, 0x00, 0x0C, 0x81, 0xE9, 0x74, 0x00, 0x15, 0x87, 0x5E, 0x00, 0x81, 0x37, 0x87, 0x46, 0x00, 0x09, 0x9E, 0x15, 0x00, 0x1E, 0xE1, 0x79, 0x00, 0x2C, 0xD2, 0x70, 0x00, 0x43, 0x82, 0x87, 0x59, 0x00, 0x19, 0xD2, 0x70, 0x00, 0x08, 0x81, 0xB4, 0x69, 0x00, 0x0A, 0x8F, 0x09, 0x60, 0x00, 0x43, 0x8F, 0x09, 0x00, 0x0C, 0x82, 0xA5, 0x4A, 0x00, 0x2D, 0xAA, 0x2A, 0x00, 0x3C, 0x87, 0x46, 0x00, 0x0C, 0xA5, 0x67, 0x00, 0x81, 0x64, 0x85, 0xE8, 0x15, 0x4D, 0x4F, 0x62, 0x73, 0x75, 0x83, 0x00, 0x09, 0x82, 0x91, 0x12, 0x00, 0x6C, 0x84, 0xE7, 0x7B, 0x00, 0x06, 0x81, 0xC5, 0x6B, 0x00, 0x09, 0x84, 0xD7, 0x4A, 0x00, 0x4B, 0x85, 0x9F, 0x53, 0x00, 0x81, 0x0E, 0x9E, 0x15, 0x00, 0x81, 0x12, 0x82, 0x87, 0x59, 0x00, 0x22, 0x8F, 0x09, 0x00, 0x05, 0xB4, 0x5E, 0x00, 0x45, 0x9E, 0x12, 0x00, 0x0C, 0x8F, 0x09, 0x00, 0x2D, 0xAC, 0x35, 0x00, 0x3C, 0x87, 0x46, 0x00, 0x0F, 0x82, 0xFD, 0x2D, 0x00, 0x81, 0x5B, 0xA5, 0x64, 0x00, 0x1B, 0x83, 0xDA, 0x36, 0x00, 0x09, 0x82, 0xE9, 0x34, 0x00, 0x81, 0x3A, 0xF3, 0x6A, 0x00, 0x81, 0x0A, 0xBC, 0x2A, 0x00, 0x81, 0x13, 0x82, 0x87, 0x59, 0x00, 0x1E, 0x81, 0xB4, 0x69, 0x00, 0x06, 0x8F, 0x09, 0x60, 0x60, 0xC0, 0x4F, 0x50, 0x94, 0x00, 0x4B, 0xBC, 0x21, 0x00, 0x30, 0x81, 0xC0, 0x27, 0x00, 0x3C, 0x87, 0x46, 0x00, 0x0F, 0x82, 0xC5, 0x31, 0x00, 0x81, 0x55, 0x81, 0xCA, 0x6D, 0x00, 0x0F, 0x83, 0xB3, 0x6C, 0x00, 0x0C, 0x83, 0xA5, 0x4F, 0x00, 0x0C, 0x98, 0x51, 0x00, 0x81, 0x3A, 0x84, 0xC7, 0x25, 0x00, 0x81, 0x04, 0x83, 0xF1, 0x5C, 0x00, 0x06, 0x81, 0xBC, 0x3E, 0x00, 0x75, 0x82, 0xDA, 0x49, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x18, 0xD2, 0x70, 0x00, 0x12, 0x81, 0xB4, 0x69, 0x00, 0x11, 0xD2, 0x70, 0x60, 0x5F, 0xC0, 0x39, 0x3B, 0x00, 0x40, 0x81, 0xDA, 0x50, 0x00, 0x0C, 0x86, 0x4B, 0x00, 0x30, 0xBB, 0x3E, 0x00, 0x3F, 0x87, 0x46, 0x00, 0x7E, 0x83, 0xD4, 0x72, 0x00, 0x69, 0x81, 0x90, 0x1E, 0x00, 0x0F, 0x86, 0x88, 0x23, 0x00, 0x0F, 0x82, 0xA9, 0x27, 0x00, 0x63, 0x85, 0xCC, 0x7A, 0x00, 0x69, 0x83, 0xFE, 0x0F, 0x00, 0x7B, 0x82, 0xA5, 0x7D, 0x00, 0x2A, 0x82, 0x87, 0x59, 0x00, 0x33, 0xD2, 0x70, 0x00, 0x3C, 0x82, 0x87, 0x59, 0x00, 0x1E, 0xD2, 0x70, 0x00, 0x45, 0x8F, 0x09, 0x00, 0x0F, 0x92, 0x15, 0x00, 0x30, 0x95, 0x57, 0x00, 0x3F, 0x87, 0x46, 0x00, 0x81, 0x5B, 0x83, 0x9F, 0x0A, 0x00, 0x09, 0x87, 0x43, 0x00, 0x21, 0x83, 0xBC, 0x1B, 0x00, 0x0C, 0x85, 0xDC, 0x06, 0x00, 0x81, 0x34, 0x87, 0x49, 0x00, 0x81, 0x01, 0x96, 0x55, 0xAC, 0xCA, 0xE3, 0x00, 0x81, 0x04, 0x82, 0x87, 0x59, 0x00, 0x19, 0xD2, 0x70, 0x00, 0x12, 0x8F, 0x09, 0x00, 0x0B, 0xD2, 0x70, 0x00, 0x45, 0x8F, 0x09, 0x00, 0x0C, 0x81, 0xC1, 0x25, 0x00, 0x33, 0xBF, 0x7E, 0x00, 0x3F, 0x87, 0x46, 0x00, 0x7E, 0x83, 0xA0, 0x08, 0x00, 0x63, 0x81, 0x97, 0x61, 0x00, 0x27, 0x87, 0x19, 0x00, 0x5D, 0x85, 0xEB, 0x12, 0x00, 0x81, 0x61, 0x84, 0x8F, 0x74, 0x97, 0xBD, 0xDB, 0x00, 0x7E, 0x82, 0xDA, 0x49, 0x00, 0x2B, 0xE1, 0x79, 0x00, 0x0E, 0xD2, 0x70, 0x60, 0x60, 0xC0, 0x4F, 0x4F, 0x00, 0x43, 0x8F, 0x09, 0x00, 0x0C, 0x92, 0x12, 0x00, 0x33, 0xC2, 0x7E, 0x00, 0x3F, 0x87, 0x46, 0x00, 0x81, 0x58, 0x83, 0xBD, 0x22, 0x00, 0x33, 0x85, 0xF9, 0x6B, 0x00, 0x09, 0xB7, 0x6D, 0x00, 0x81, 0x34, 0xA7, 0x66, 0x00, 0x7B, 0x83, 0xEA, 0x2E, 0xF8, 0xFB, 0xFD, 0x00, 0x1C, 0x82, 0x87, 0x59, 0x00, 0x18, 0xD2, 0x70, 0x00, 0x09, 0x8F, 0x09, 0x00, 0x11, 0xD2, 0x70, 0x00, 0x3E, 0x82, 0x87, 0x59, 0x00, 0x28, 0xD2, 0x70, 0x00, 0x4B, 0x8F, 0x09, 0x00, 0x0F, 0x9D, 0x1A, 0x00, 0x33, 0xBB, 0x35, 0x00, 0x82, 0x17, 0x87, 0x46, 0x00, 0x1E, 0x81, 0x9E, 0x23, 0x00, 0x1E, 0x83, 0x0C, 0x00, 0x81, 0x34, 0xBE, 0x3B, 0x00, 0x12, 0xD7, 0x3C, 0x00, 0x6A, 0x81, 0x96, 0x69, 0xED, 0xF6, 0x00, 0x81, 0x04, 0x82, 0xDA, 0x49, 0x00, 0x21, 0x82, 0x87, 0x59, 0x00, 0x12, 0x81, 0xB4, 0x69, 0x60, 0x60, 0xC0, 0x52, 0x52, 0x00, 0x46, 0x81, 0xBC, 0x32, 0x00, 0x0C, 0xD9, 0x53, 0x00, 0x33, 0xCF, 0x0A, 0x00, 0x42, 0x87, 0x46, 0x00, 0x0C, 0x8B, 0x47, 0x00, 0x81, 0x4F, 0x83, 0x88, 0x38, 0x00, 0x30, 0x9D, 0x65, 0x00, 0x06, 0x98, 0x60, 0x00, 0x81, 0x37, 0xA0, 0x20, 0x00, 0x78, 0x83, 0xF9, 0x40, 0xCE, 0xE0, 0xEE, 0x00, 0x81, 0x28, 0x82, 0x87, 0x59, 0x00, 0x0F, 0xD2, 0x70, 0x60, 0x5F, 0xC0, 0x3F, 0x40, 0x00, 0x46, 0x81, 0x9E, 0x20, 0x00, 0x3F, 0x83, 0xDB, 0x3A, 0x00, 0x82, 0x17, 0x8F, 0x0C, 0x00, 0x39, 0xC5, 0x48, 0x00, 0x06, 0x86, 0x09, 0x00, 0x82, 0x2C, 0x84, 0xA6, 0x55, 0xC0, 0xD6, 0xE9, 0x00, 0x5B, 0x82, 0xDA, 0x49, 0x00, 0x4D, 0x82, 0x87, 0x59, 0x00, 0x0C, 0x81, 0xB4, 0x69, 0x60, 0x60, 0xC0, 0x55, 0x54, 0xA2, 0x00, 0x81, 0x07, 0x83, 0xE3, 0x00, 0x00, 0x82, 0x1A, 0x87, 0x46, 0x00, 0x81, 0x0D, 0x82, 0xF9, 0x2C, 0x00, 0x81, 0x5B, 0xA5, 0x6D, 0xAB, 0xC9, 0xE2, 0x00, 0x81, 0x28, 0x82, 0x87, 0x59, 0x00, 0x57, 0x8F, 0x09, 0x00, 0x82, 0x56, 0x87, 0x46, 0x00, 0x30, 0x82, 0xE2, 0x54, 0x00, 0x5A, 0x81, 0xBC, 0x56, 0x00, 0x81, 0x55, 0x85, 0x97, 0x45, 0x00, 0x0F, 0x0F, 0xA3, 0xC4, 0xDF, 0x00, 0x78, 0x82, 0x87, 0x59, 0x00, 0x34, 0xD2, 0x70, 0x00, 0x08, 0x8F, 0x09, 0x54, 0x00, 0x4A, 0x8F, 0x09, 0x00, 0x0F, 0xC3, 0x73, 0x00, 0x72, 0x87, 0x46, 0x00, 0x81, 0x58, 0x83, 0xC4, 0x6B, 0x00, 0x81, 0x7C, 0x8F, 0x0C, 0x00, 0x6F, 0x84, 0xB5, 0x70, 0x00, 0x81, 0x2B, 0x82, 0x87, 0x59, 0x00, 0x09, 0xA5, 0x55, 0x00, 0x4E, 0x8F, 0x09, 0x00, 0x0F, 0xAD, 0x24, 0x00, 0x33, 0xD7, 0x51, 0x00, 0x82, 0x17, 0xC3, 0x76, 0x00, 0x81, 0x01, 0x9E, 0x18, 0x00, 0x09, 0x82, 0xF9, 0x11, 0x00, 0x27, 0x82, 0xF4, 0x2D, 0x00, 0x54, 0xD5, 0x7F, 0x00, 0x63, 0x9E, 0x27, 0xF8, 0xFA, 0xFD, 0x00, 0x81, 0x2B, 0x82, 0x87, 0x59, 0x00, 0x09, 0xB4, 0x5E, 0x57, 0x56, 0xA9, 0x00, 0x81, 0x0D, 0x83, 0xE2, 0x02, 0x00, 0x4B, 0xD3, 0x02, 0x00, 0x81, 0x4C, 0x81, 0x80, 0x2C, 0x00, 0x36, 0xAD, 0x24, 0x00, 0x06, 0x91, 0x1A, 0x00, 0x48, 0x85, 0xBD, 0x6E, 0x00, 0x0F, 0x81, 0xA7, 0x7A, 0x00, 0x09, 0x8E, 0x1A, 0x00, 0x09, 0xDB, 0x4C, 0x00, 0x06, 0x95, 0x75, 0x00, 0x06, 0x81, 0xA9, 0x52, 0x00, 0x5A, 0xD5, 0x7F, 0x00, 0x5D, 0x9E, 0x27, 0xE3, 0xEC, 0xF5, 0x00, 0x81, 0x2B, 0x82, 0x87, 0x59, 0x00, 0x09, 0x8F, 0x09, 0x44, 0x45, 0x00, 0x4C, 0x81, 0xBC, 0x32, 0x00, 0x42, 0x83, 0xF2, 0x0C, 0x00, 0x3F, 0x87, 0x46, 0x00, 0x72, 0x83, 0xCD, 0x26, 0x00, 0x81, 0x76, 0xBC, 0x30, 0x00, 0x0F, 0x83, 0x97, 0x44, 0x00, 0x0F, 0x81, 0xA7, 0x26, 0x00, 0x60, 0xE5, 0x08, 0x00, 0x5A, 0x9E, 0x27, 0xE3, 0xEC, 0xF5, 0x00, 0x67, 0xD2, 0x70, 0x00, 0x44, 0x82, 0x87, 0x59, 0x00, 0x06, 0x8F, 0x09, 0x5A, 0x59, 0x00, 0x49, 0x81, 0xBC, 0x32, 0x00, 0x48, 0xD2, 0x04, 0x00, 0x4B, 0xF1, 0x1A, 0x00, 0x81, 0x4C, 0x82, 0xAD, 0x01, 0x00, 0x06, 0x81, 0x5B, 0x00, 0x2D, 0xFB, 0x2A, 0x00, 0x06, 0xC2, 0x39, 0x00, 0x57, 0x83, 0xCF, 0x2B, 0x00, 0x1B, 0x81, 0xCB, 0x44, 0x00, 0x06, 0x81, 0xB8, 0x22, 0x00, 0x60, 0x81, 0xDE, 0x30, 0x00, 0x57, 0x84, 0xF2, 0x20, 0xC6, 0xD9, 0xEB, 0x00, 0x81, 0x2B, 0x82, 0x87, 0x59, 0x60, 0x60, 0xC0, 0x5F, 0x5E, 0xBF, 0x00, 0x51, 0x8F, 0x09, 0x00, 0x12, 0xC2, 0x78, 0x00, 0x30, 0x9E, 0x1B, 0x00, 0x3C, 0x87, 0x46, 0x00, 0x0C, 0x92, 0x6C, 0x00, 0x81, 0x52, 0x84, 0x88, 0x5B, 0x00, 0x81, 0x0A, 0xDA, 0x48, 0x4D, 0x4F, 0x62, 0x00, 0x5A, 0x82, 0xDB, 0x14, 0x00, 0x7E, 0xF1, 0x47, 0xC6, 0xD9, 0xEB, 0x00, 0x6A, 0x82, 0xDA, 0x49, 0x00, 0x3E, 0x82, 0x87, 0x59, 0x00, 0x5A, 0x8F, 0x09, 0x00, 0x12, 0x86, 0x4E, 0x00, 0x30, 0x83, 0x4E, 0x00, 0x3C, 0x87, 0x46, 0x00, 0x0C, 0x81, 0x9E, 0x41, 0x00, 0x81, 0x55, 0x83, 0xCC, 0x34, 0x00, 0x33, 0xE9, 0x54, 0x00, 0x57, 0xF0, 0x3D, 0x00, 0x1E, 0xA0, 0x74, 0x00, 0x21, 0x87, 0x67, 0x00, 0x81, 0x19, 0xF1, 0x4A, 0xC6, 0xD9, 0xEB, 0x00, 0x81, 0x28, 0x82, 0x87, 0x59, 0x00, 0x5D, 0x8F, 0x09, 0x00, 0x12, 0x85, 0x89, 0x01, 0x00, 0x2D, 0xDF, 0x0E, 0x00, 0x39, 0x87, 0x46, 0x00, 0x78, 0x84, 0xF3, 0x27, 0x00, 0x78, 0xF8, 0x60, 0xA6, 0xA7, 0xB0, 0x00, 0x78, 0xF8, 0x60, 0x00, 0x5D, 0x82, 0xDB, 0x14, 0x00, 0x7E, 0x85, 0x81, 0x3B, 0xA9, 0xC5, 0xE1, 0x00, 0x2D, 0x84, 0xE2, 0x22, 0x00, 0x78, 0x82, 0x87, 0x59, 0x00, 0x60, 0x8F, 0x09, 0x00, 0x12, 0xA4, 0x66, 0x00, 0x2D, 0x87, 0x10, 0x00, 0x45, 0x81, 0xAD, 0x4A, 0x00, 0x81, 0x5B, 0x84, 0xDB, 0x5A, 0x00, 0x0F, 0x84, 0xD9, 0x61, 0x00, 0x0C, 0x84, 0xF2, 0x32, 0x00, 0x0C, 0x82, 0x02, 0x00, 0x48, 0x85, 0xB1, 0x47, 0x00, 0x18, 0xA4, 0x5D, 0x00, 0x21, 0x82, 0xDB, 0x14, 0x00, 0x6F, 0x83, 0x03, 0x00, 0x48, 0x9E, 0x27, 0xA9, 0xC4, 0xE1, 0x00, 0x2B, 0x82, 0x87, 0x59, 0x00, 0x08, 0xD2, 0x70, 0x00, 0x0B, 0x8F, 0x09, 0x00, 0x33, 0xD2, 0x70, 0x00, 0x34, 0x82, 0x87, 0x59, 0x00, 0x06, 0x8F, 0x09, 0x49, 0x49, 0x85, 0x00, 0x6C, 0x81, 0xD1, 0x4D, 0x00, 0x2A, 0x9E, 0x1E, 0x00, 0x45, 0x81, 0xBC, 0x56, 0x00, 0x81, 0x61, 0x85, 0x9D, 0x7E, 0x00, 0x06, 0x86, 0x48, 0x00, 0x16, 0xD8, 0x07, 0x00, 0x47, 0x82, 0x96, 0x26, 0x00, 0x3F, 0x82, 0xDB, 0x14, 0x00, 0x75, 0x99, 0x52, 0x00, 0x42, 0x9E, 0x27, 0xA8, 0xC4, 0xE1, 0x00, 0x79, 0xD2, 0x70, 0x00, 0x1A, 0x82, 0x87, 0x59, 0x00, 0x15, 0xD2, 0x70, 0x5C, 0x5B, 0xB8, 0x37, 0x38, 0x00, 0x40, 0x81, 0x9E, 0x20, 0x00, 0x30, 0x85, 0x97, 0x21, 0x00, 0x27, 0xAC, 0x32, 0x00, 0x33, 0x87, 0x46, 0x00, 0x0F, 0x81, 0xB5, 0x0A, 0x00, 0x75, 0x84, 0xE0, 0x41, 0x00, 0x7B, 0x82, 0xD3, 0x39, 0x8D, 0x8E, 0x9A, 0x00, 0x06, 0x81, 0xD3, 0x37, 0x00, 0x09, 0x84, 0x9F, 0x3C, 0x00, 0x66, 0x83, 0xFA, 0x62, 0x00, 0x1E, 0x82, 0xDB, 0x14, 0x00, 0x78, 0x99, 0x52, 0x00, 0x3F, 0x84, 0xBD, 0x7E, 0xA8, 0xC3, 0xE0, 0x00, 0x30, 0x84, 0xE2, 0x22, 0x00, 0x72, 0x82, 0x87, 0x59, 0x00, 0x66, 0x8F, 0x09, 0x00, 0x15, 0xF4, 0x23, 0x00, 0x27, 0x9B, 0x27, 0x00, 0x30, 0x87, 0x46, 0x00, 0x0F, 0x9A, 0x14, 0x00, 0x7B, 0x84, 0x40, 0x00, 0x81, 0x73, 0x85, 0xC4, 0x12, 0x00, 0x06, 0x81, 0xD3, 0x10, 0x00, 0x09, 0x82, 0x71, 0x00, 0x06, 0x83, 0x8A, 0x31, 0x00, 0x81, 0x01, 0x83, 0xD7, 0x00, 0x00, 0x3C, 0x84, 0xCD, 0x0A, 0x92, 0xB4, 0xD9, 0x00, 0x33, 0x84, 0xE2, 0x22, 0x00, 0x6C, 0x82, 0x87, 0x59, 0x00, 0x06, 0xC3, 0x67, 0x5E, 0x5E, 0x00, 0x6A, 0x83, 0x80, 0x36, 0x00, 0x0F, 0xC6, 0x67, 0x00, 0x24, 0x84, 0xD0, 0x4C, 0x00, 0x2D, 0x87, 0x46, 0x00, 0x81, 0x67, 0x85, 0xBD, 0x6B, 0x00, 0x81, 0x1C, 0xB5, 0x7D, 0x00, 0x0F, 0x86, 0x30, 0xC0, 0xC0, 0xC7, 0x00, 0x81, 0x04, 0xBF, 0x27, 0x00, 0x39, 0x84, 0xDC, 0x16, 0x00, 0x79, 0xD2, 0x70, 0x00, 0x0A, 0x8F, 0x09, 0x00, 0x25, 0xD2, 0x70, 0x00, 0x63, 0x96, 0x4C, 0x00, 0x1B, 0x99, 0x2B, 0x00, 0x21, 0x8B, 0x29, 0x00, 0x2A, 0x87, 0x46, 0x00, 0x12, 0xCF, 0x0A, 0x00, 0x82, 0x56, 0x81, 0xD3, 0x1F, 0x00, 0x24, 0x92, 0x75, 0x00, 0x57, 0x85, 0x89, 0x6A, 0x00, 0x72, 0x84, 0xBE, 0x10, 0x00, 0x81, 0x02, 0xD2, 0x70, 0x00, 0x1D, 0x82, 0x87, 0x59, 0x60, 0x60, 0xC0, 0x57, 0x57, 0xAA, 0x00, 0x42, 0x81, 0xBC, 0x2F, 0x00, 0x45, 0xA8, 0x3D, 0x00, 0x1B, 0x83, 0x95, 0x51, 0x00, 0x24, 0x87, 0x46, 0x00, 0x15, 0x85, 0xE3, 0x4C, 0x00, 0x81, 0x64, 0x81, 0xC4, 0x0D, 0x00, 0x82, 0x35, 0x85, 0x82, 0x69, 0x00, 0x2D, 0x9E, 0x27, 0x00, 0x39, 0x84, 0xE2, 0x22, 0x00, 0x66, 0x82, 0x87, 0x59, 0x4D, 0x4D, 0x8D, 0x00, 0x78, 0x85, 0xFA, 0x33, 0x00, 0x15, 0x87, 0x49, 0x00, 0x18, 0x83, 0x9D, 0x1D, 0x00, 0x1E, 0x87, 0x46, 0x00, 0x09, 0x82, 0xE0, 0x31, 0x00, 0x12, 0x87, 0x43, 0x00, 0x82, 0x56, 0x81, 0xDA, 0x5F, 0x00, 0x81, 0x70, 0x85, 0xDC, 0x12, 0x00, 0x81, 0x19, 0x82, 0x87, 0x59, 0x5D, 0x5F, 0xA6, 0x46, 0x49, 0x6B, 0x00, 0x81, 0x19, 0x81, 0xBF, 0x74, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x83, 0xC9, 0x73, 0x00, 0x06, 0x87, 0x07, 0x00, 0x15, 0x87, 0x46, 0x00, 0x1E, 0x86, 0x81, 0x64, 0x00, 0x81, 0x6A, 0x83, 0xEA, 0x49, 0x00, 0x82, 0x3E, 0xA7, 0x0C, 0x00, 0x25, 0x87, 0x46, 0x00, 0x39, 0xD2, 0x70, 0x00, 0x4D, 0x82, 0x87, 0x59, 0x00, 0x06, 0xC3, 0x67, 0x5B, 0x5E, 0xAC, 0x4F, 0x51, 0x8E, 0x46, 0x47, 0x77, 0x00, 0x81, 0x0D, 0x83, 0x9E, 0x39, 0x00, 0x24, 0x91, 0x5F, 0x00, 0x09, 0x21, 0x00, 0x06, 0xED, 0x61, 0x00, 0x21, 0x30, 0x00, 0x82, 0x6E, 0xA5, 0x4F, 0x00, 0x81, 0x43, 0xDD, 0x09, 0x00, 0x1E, 0x84, 0x4F, 0x00, 0x33, 0x84, 0xE2, 0x22, 0x00, 0x3C, 0x81, 0xB4, 0x69, 0x00, 0x0F, 0xC3, 0x67, 0x64, 0x6A, 0xBC, 0x5A, 0x5F, 0xA5, 0x4D, 0x50, 0x87, 0x40, 0x43, 0x69, 0x00, 0x72, 0x9D, 0x7D, 0x00, 0x2D, 0xA2, 0x0A, 0x00, 0x48, 0x85, 0xA2, 0x5C, 0x00, 0x42, 0x84, 0x89, 0x23, 0x00, 0x82, 0x41, 0x85, 0x81, 0x41, 0x00, 0x7B, 0x85, 0xB6, 0x28, 0x00, 0x57, 0x85, 0x98, 0x55, 0x00, 0x57, 0x82, 0x87, 0x59, 0x00, 0x1B, 0xD2, 0x70, 0x64, 0x6B, 0xB6, 0x56, 0x5B, 0x97, 0x48, 0x4C, 0x79, 0x3E, 0x41, 0x00, 0x81, 0x2F, 0x85, 0x4D, 0x00, 0x1B, 0xC8, 0x7B, 0x00, 0x27, 0x87, 0x40, 0x00, 0x81, 0x7C, 0x85, 0xE9, 0x1C, 0x5A, 0x5C, 0x6D, 0x00, 0x06, 0xFF, 0x34, 0x00, 0x7B, 0x83, 0xF3, 0x61, 0x00, 0x7E, 0x85, 0xB6, 0x28, 0x00, 0x5A, 0x81, 0xAE, 0x21, 0x00, 0x37, 0x82, 0xDA, 0x49, 0x00, 0x08, 0x8F, 0x09, 0x00, 0x19, 0xD2, 0x70, 0x00, 0x0E, 0x81, 0xB4, 0x69, 0x5F, 0x68, 0xA8, 0x50, 0x56, 0x89, 0x45, 0x4A, 0x71, 0x37, 0x00, 0x4A, 0x84, 0x87, 0x75, 0x00, 0x7B, 0x8F, 0x18, 0x00, 0x0C, 0x82, 0xAD, 0x61, 0x00, 0x21, 0x85, 0x0B, 0x00, 0x06, 0x81, 0xF5, 0x77, 0x00, 0x81, 0x6D, 0x83, 0xA5, 0x37, 0x00, 0x48, 0x85, 0xB4, 0x26, 0x00, 0x81, 0x49, 0x85, 0xB6, 0x28, 0x00, 0x60, 0x82, 0x47, 0x00, 0x57, 0x82, 0x87, 0x59, 0x69, 0x76, 0xB9, 0x5D, 0x67, 0xA1, 0x4E, 0x55, 0x82, 0x3F, 0x43, 0x00, 0x81, 0x59, 0x94, 0x3E, 0x00, 0x06, 0xD0, 0x4A, 0x00, 0x09, 0x81, 0xFD, 0x16, 0x00, 0x0F, 0x83, 0xE0, 0x24, 0x00, 0x0C, 0xA5, 0x7C, 0x00, 0x82, 0x08, 0x85, 0xF0, 0x38, 0xB3, 0xB4, 0xBC, 0x80, 0x81, 0x8F, 0x00, 0x78, 0x82, 0x17, 0x00, 0x78, 0x85, 0xB6, 0x28, 0x00, 0x63, 0x9E, 0x27, 0x96, 0xB2, 0xD9, 0x00, 0x48, 0x82, 0x87, 0x59, 0x68, 0x75, 0xB2, 0x57, 0x61, 0x92, 0x47, 0x4D, 0x72, 0x3C, 0x3F, 0x00, 0x43, 0x84, 0xF1, 0x40, 0x00, 0x83, 0x48, 0xA3, 0x1D, 0x00, 0x06, 0x8C, 0x3F, 0xD9, 0xD9, 0xDD, 0x00, 0x81, 0x01, 0x8E, 0x05, 0x00, 0x81, 0x1F, 0x84, 0x92, 0x4D, 0x00, 0x3C, 0x9E, 0x27, 0xA4, 0xBD, 0xDF, 0x00, 0x39, 0x82, 0x87, 0x59, 0x73, 0x85, 0xC4, 0x61, 0x6F, 0xA3, 0x55, 0x5F, 0x8B, 0x44, 0x4A, 0x00, 0x81, 0x02, 0xB4, 0x13, 0x00, 0x83, 0x18, 0xB9, 0x75, 0x00, 0x81, 0x0A, 0x85, 0xFB, 0x76, 0x00, 0x72, 0x85, 0xB6, 0x28, 0x00, 0x69, 0x9E, 0x27, 0xA4, 0xBC, 0xDF, 0x00, 0x2D, 0x81, 0xB4, 0x69, 0x6D, 0x7F, 0xB5, 0x5F, 0x6D, 0x9C, 0x4E, 0x57, 0x7C, 0x3D, 0x00, 0x44, 0x85, 0x80, 0x31, 0x00, 0x83, 0x60, 0x87, 0x46, 0x00, 0x4B, 0x82, 0xD3, 0x18, 0x00, 0x81, 0x2E, 0x85, 0xB6, 0x28, 0x00, 0x66, 0x99, 0x2B, 0x00, 0x09, 0x96, 0x5E, 0xA4, 0xBC, 0xDE, 0x00, 0x1E, 0x81, 0xB4, 0x69, 0x79, 0x90, 0xC7, 0x6A, 0x7D, 0xAE, 0x58, 0x64, 0x8D, 0x46, 0x4D, 0x6C, 0x38, 0x3C, 0x00, 0x81, 0x41, 0xA5, 0x1C, 0x00, 0x82, 0x6E, 0x87, 0x46, 0x00, 0x81, 0x10, 0x81, 0xBC, 0x1D, 0x00, 0x66, 0x85, 0xB6, 0x28, 0x00, 0x72, 0x83, 0xE6, 0x3C, 0x88, 0x9A, 0xB9, 0x00, 0x12, 0xD2, 0x70, 0x76, 0x8E, 0xC0, 0x63, 0x74, 0x9E, 0x55, 0x61, 0x85, 0x42, 0x48, 0x64, 0x00, 0x84, 0x2E, 0x87, 0x37, 0x00, 0x48, 0x81, 0xC4, 0x1C, 0x00, 0x81, 0x3A, 0x85, 0xB6, 0x28, 0x00, 0x7B, 0x81, 0x61, 0x43, 0x4A, 0x64, 0x48, 0x50, 0x6D, 0x47, 0x50, 0x6D, 0x47, 0x50, 0x6D, 0x39, 0x00, 0x84, 0x30, 0x8E, 0x71, 0x00, 0x81, 0x28, 0x87, 0x46, 0x00, 0x63, 0x85, 0xB6, 0x28, 0x00, 0x84, 0x49, 0x86, 0x39, 0x00, 0x82, 0x1A, 0x87, 0x46, 0x00, 0x86, 0x12, 0x87, 0x1F, 0x00, 0x60, 0x84, 0xE3, 0x26, 0x00, 0x87, 0x0D, 0x87, 0x46, 0x00, 0x39, 0x84, 0xE3, 0x26, 0x00, 0x87, 0x0D, 0x87, 0x46, 0x00, 0x06, 0x81, 0xB6, 0x6E, 0x00, 0x81, 0x5E, 0x84, 0xEC, 0x50, 0x00, 0x85, 0x68, 0x96, 0x55, 0x00, 0x81, 0x10, 0x81, 0x89, 0x50, 0x00, 0x0C, 0x82, 0xCD, 0x06, 0x00, 0x86, 0x24, 0xA5, 0x5E, 0x00, 0x21, 0x83, 0xC4, 0x50, 0x00, 0x72, 0xB4, 0x6D, 0x00, 0x06, 0x81, 0xDB, 0x4B, 0x00, 0x0C, 0x81, 0xE9, 0x74, 0x00, 0x09, 0x0C, 0x00, 0x15, 0x84, 0xBD, 0x63, 0x00, 0x84, 0x0A, 0xD1, 0x06, 0x00, 0x0F, 0xE2, 0x2F, 0xC0, 0xC0, 0xC7, 0x8D, 0x8E, 0x9A, 0x00, 0x81, 0x6A, 0xF8, 0x66, 0x00, 0x06, 0x96, 0x58, 0x00, 0x5D, 0x81, 0xC3, 0x78, 0x00, 0x2A, 0x90, 0x19, 0x00, 0x09, 0xBC, 0x12, 0x00, 0x06, 0x81, 0xD3, 0x16, 0x00, 0x09, 0xDB, 0x5E, 0x00, 0x06, 0x0F, 0x00, 0x81, 0x7C, 0xF4, 0x3B, 0x00, 0x82, 0x1D, 0x85, 0xF7, 0x0F, 0x00, 0x1C, 0x82, 0xE5, 0x4E, 0x00, 0x81, 0x4B, 0x84, 0xB4, 0x60, 0x00, 0x24, 0xDF, 0x41, 0x00, 0x09, 0xF7, 0x5C, 0x00, 0x75, 0x87, 0x4F, 0x00, 0x06, 0x85, 0xE4, 0x4D, 0x00, 0x0C, 0x81, 0xA9, 0x0D, 0x00, 0x0F, 0xC3, 0x64, 0x00, 0x81, 0x46, 0xE9, 0x75, 0x00, 0x82, 0x0B, 0xD7, 0x7E, 0x00, 0x42, 0x84, 0x8D, 0x2A, 0x00, 0x27, 0x81, 0xA1, 0x47, 0x00, 0x81, 0x61, 0x85, 0x90, 0x4D, 0x00, 0x3C, 0x81, 0xB2, 0x6D, 0x00, 0x51, 0xE9, 0x54, 0x00, 0x0C, 0x87, 0x37, 0x00, 0x12, 0x81, 0x83, 0x35, 0x00, 0x06, 0x82, 0xBD, 0x77, 0x00, 0x83, 0x4B, 0x9B, 0x48, 0x00, 0x3F, 0x83, 0xF0, 0x19, 0x00, 0x15, 0x84, 0x8D, 0x7B, 0x00, 0x1B, 0x85, 0x2F, 0x00, 0x81, 0x61, 0xA2, 0x55, 0x73, 0x75, 0x83, 0x00, 0x33, 0x81, 0xC1, 0x79, 0x00, 0x5D, 0xF1, 0x1A, 0x00, 0x15, 0x81, 0x8A, 0x7B, 0x00, 0x83, 0x48, 0xB6, 0x18, 0x00, 0x0F, 0x81, 0xD3, 0x28, 0x00, 0x33, 0x93, 0x7C, 0x00, 0x18, 0x85, 0xFD, 0x6C, 0x00, 0x09, 0xD7, 0x3C, 0x00, 0x15, 0x85, 0x32, 0x00, 0x81, 0x5B, 0x81, 0x88, 0x0D, 0x00, 0x09, 0x81, 0xA8, 0x48, 0xB3, 0xB4, 0xBC, 0x73, 0x75, 0x83, 0x00, 0x78, 0x81, 0x6A, 0x00, 0x0F, 0x81, 0xE2, 0x34, 0xB3, 0xB4, 0xBC, 0x00, 0x0F, 0xA5, 0x4C, 0x00, 0x3C, 0x84, 0xBD, 0x48, 0x00, 0x83, 0x12, 0xF6, 0x10, 0x00, 0x3F, 0x8E, 0x23, 0x00, 0x12, 0x81, 0xC4, 0x58, 0x8D, 0x8E, 0x9A, 0x00, 0x0F, 0x88, 0x0E, 0x00, 0x06, 0xE6, 0x5D, 0x00, 0x0F, 0x85, 0x91, 0x12, 0x00, 0x81, 0x55, 0x81, 0x88, 0x19, 0x00, 0x09, 0x82, 0x80, 0x4C, 0x00, 0x81, 0x01, 0xA0, 0x02, 0x00, 0x06, 0x8A, 0x5E, 0x00, 0x09, 0x82, 0x65, 0x00, 0x06, 0x90, 0x1F, 0x00, 0x0C, 0x82, 0x74, 0x00, 0x2D, 0x83, 0xB6, 0x09, 0x00, 0x83, 0x21, 0xC8, 0x6C, 0x00, 0x3C, 0x82, 0x87, 0x1D, 0x00, 0x0F, 0x81, 0xF9, 0x4B, 0x00, 0x1E, 0x81, 0xE2, 0x76, 0x00, 0x0F, 0x87, 0x70, 0x00, 0x81, 0x52, 0x84, 0x43, 0x00, 0x33, 0x82, 0xDB, 0x14, 0x00, 0x60, 0x81, 0x88, 0x79, 0x00, 0x0F, 0x96, 0x55, 0xD9, 0xD9, 0xDD, 0x00, 0x06, 0x85, 0x82, 0x30, 0x00, 0x06, 0x83, 0xB6, 0x54, 0x00, 0x83, 0x45, 0x81, 0xB8, 0x22, 0x00, 0x0C, 0x96, 0x0A, 0x00, 0x45, 0x8F, 0x09, 0x00, 0x21, 0xB1, 0x3A, 0x00, 0x0C, 0x30, 0x00, 0x81, 0x52, 0x84, 0x46, 0x00, 0x81, 0x10, 0x81, 0x80, 0x26, 0x5A, 0x5C, 0x6D, 0x00, 0x0C, 0x82, 0x62, 0x00, 0x06, 0x83, 0x9F, 0x07, 0x00, 0x06, 0x83, 0x75, 0x00, 0x5A, 0x84, 0xB6, 0x7A, 0x00, 0x82, 0x77, 0xA5, 0x58, 0x00, 0x3C, 0x86, 0x51, 0x00, 0x0C, 0x88, 0x08, 0x00, 0x24, 0xC1, 0x6B, 0x00, 0x0F, 0x82, 0x80, 0x4F, 0x00, 0x81, 0x4F, 0xC0, 0x76, 0x00, 0x81, 0x49, 0x82, 0xBC, 0x43, 0x00, 0x83, 0x30, 0x81, 0x8C, 0x5F, 0x00, 0x3C, 0x81, 0xE1, 0x48, 0x00, 0x0F, 0x82, 0x81, 0x0B, 0x00, 0x27, 0x8B, 0x5C, 0x00, 0x81, 0x5B, 0x83, 0x9F, 0x0A, 0x00, 0x84, 0x73, 0xF1, 0x1A, 0x00, 0x3C, 0x82, 0xA6, 0x2A, 0x00, 0x12, 0x81, 0xA8, 0x66, 0x00, 0x2D, 0x85, 0x3E, 0x00, 0x0C, 0x8F, 0x42, 0x00, 0x81, 0x4C, 0x96, 0x55, 0x00, 0x84, 0x73, 0x87, 0x46, 0x00, 0x42, 0x83, 0xBC, 0x2A, 0x00, 0x39, 0x82, 0xBC, 0x43, 0x00, 0x0C, 0x9E, 0x1E, 0x00, 0x81, 0x4C, 0xC4, 0x05, 0x00, 0x84, 0x70, 0x87, 0x46, 0x00, 0x0C, 0x96, 0x0D, 0x00, 0x45, 0x83, 0xFD, 0x1D, 0x00, 0x2D, 0xBA, 0x16, 0x00, 0x0C, 0x96, 0x55, 0x00, 0x81, 0x4C, 0xAD, 0x2A, 0x00, 0x4B, 0x84, 0x81, 0x63, 0x00, 0x84, 0x2B, 0xF6, 0x0A, 0x00, 0x48, 0x9E, 0x15, 0x00, 0x30, 0xCF, 0x49, 0x00, 0x0C, 0xBD, 0x28, 0x00, 0x81, 0x4C, 0x85, 0x77, 0x00, 0x84, 0x70, 0x81, 0x80, 0x26, 0x00, 0x3F, 0x82, 0xDB, 0x14, 0x00, 0x3F, 0x82, 0xBD, 0x3B, 0x00, 0x0C, 0x8F, 0x48, 0x00, 0x81, 0x4C, 0xA5, 0x61, 0x00, 0x1E, 0x84, 0xA7, 0x5F, 0x00, 0x84, 0x5E, 0x87, 0x46, 0x00, 0x36, 0xED, 0x1F, 0x00, 0x0C, 0x9D, 0x5C, 0x00, 0x33, 0x88, 0x08, 0x00, 0x81, 0x55, 0x83, 0x80, 0x72, 0x00, 0x06, 0xA0, 0x2C, 0x00, 0x81, 0x52, 0x82, 0xCD, 0x5D, 0x00, 0x83, 0x24, 0xDA, 0x3F, 0x00, 0x36, 0x87, 0x46, 0x00, 0x0C, 0xAD, 0x63, 0x00, 0x33, 0x42, 0x00, 0x81, 0x55, 0x83, 0x97, 0x44, 0x00, 0x09, 0x82, 0xA8, 0x7A, 0x00, 0x82, 0x77, 0x82, 0x99, 0x02, 0x00, 0x82, 0x32, 0x87, 0x46, 0x00, 0x3F, 0xAD, 0x63, 0x00, 0x0C, 0x81, 0x01, 0x00, 0x81, 0x52, 0xDD, 0x1E, 0x00, 0x06, 0x84, 0xA0, 0x1C, 0x00, 0x84, 0x1F, 0x82, 0x8A, 0x02, 0x00, 0x81, 0x01, 0x87, 0x46, 0x00, 0x3F, 0x83, 0xBD, 0x61, 0x00, 0x81, 0x5E, 0x87, 0x46, 0x00, 0x09, 0x82, 0xFE, 0x76, 0x00, 0x06, 0x8F, 0x15, 0x00, 0x6C, 0x83, 0xE2, 0x71, 0x00, 0x84, 0x2E, 0x87, 0x46, 0x00, 0x0C, 0xAD, 0x63, 0x00, 0x42, 0x82, 0xF9, 0x2F, 0x00, 0x81, 0x55, 0xBF, 0x03, 0x00, 0x81, 0x10, 0x85, 0xF4, 0x2D, 0x00, 0x81, 0x2B, 0x84, 0xD0, 0x04, 0x00, 0x82, 0x68, 0x87, 0x46, 0x00, 0x0C, 0xD3, 0x3E, 0x00, 0x36, 0xAD, 0x63, 0x00, 0x82, 0x68, 0x87, 0x46, 0x00, 0x06, 0x81, 0xE0, 0x6B, 0x00, 0x09, 0xCE, 0x2D, 0x00, 0x0C, 0x83, 0x42, 0x00, 0x83, 0x42, 0x97, 0x71, 0x00, 0x3F, 0xAD, 0x24, 0x00, 0x0C, 0xA5, 0x1C, 0x00, 0x36, 0xB2, 0x59, 0x00, 0x0C, 0xD3, 0x05, 0x00, 0x82, 0x5C, 0x82, 0xA4, 0x7C, 0x00, 0x06, 0xC5, 0x09, 0x00, 0x06, 0xCE, 0x21, 0x00, 0x0C, 0x82, 0x6B, 0x00, 0x2D, 0x84, 0xA7, 0x20, 0x00, 0x83, 0x54, 0xBC, 0x30, 0x00, 0x45, 0x83, 0xF9, 0x13, 0x00, 0x81, 0x58, 0xB4, 0x6A, 0x00, 0x81, 0x10, 0xC5, 0x06, 0x00, 0x0C, 0xAE, 0x2E, 0x00, 0x0F, 0x82, 0x6B, 0xC0, 0xC0, 0xC7, 0x00, 0x83, 0x3F, 0xBD, 0x5B, 0x00, 0x0C, 0x82, 0xE1, 0x68, 0x00, 0x30, 0x81, 0xE5, 0x7F, 0x00, 0x0C, 0x3C, 0x00, 0x36, 0x81, 0x9A, 0x7F, 0x00, 0x0C, 0x81, 0x80, 0x5C, 0x00, 0x82, 0x59, 0x8C, 0x12, 0x00, 0x06, 0xB5, 0x74, 0x00, 0x0C, 0x96, 0x37, 0x00, 0x0F, 0x87, 0x46, 0x00, 0x06, 0x82, 0xA6, 0x45, 0x00, 0x83, 0x48, 0x81, 0x8F, 0x2C, 0x00, 0x30, 0x86, 0x48, 0x00, 0x0C, 0x9E, 0x15, 0x00, 0x36, 0x81, 0xAA, 0x0B, 0x00, 0x81, 0x5B, 0x83, 0xF2, 0x0C, 0x00, 0x81, 0x0D, 0x8B, 0x29, 0x00, 0x0F, 0xBD, 0x37, 0x00, 0x12, 0x91, 0x77, 0x00, 0x83, 0x42, 0x81, 0xA6, 0x04, 0x00, 0x39, 0x83, 0xF9, 0x52, 0x00, 0x42, 0xFF, 0x67, 0x00, 0x81, 0x5E, 0x84, 0x81, 0x18, 0x00, 0x81, 0x19, 0x85, 0xE3, 0x4C, 0x00, 0x12, 0x87, 0x46, 0x00, 0x83, 0x42, 0xDB, 0x76, 0x00, 0x0C, 0x82, 0xA8, 0x4D, 0x00, 0x2A, 0x87, 0x0D, 0x00, 0x0F, 0x81, 0x9E, 0x71, 0x00, 0x36, 0x81, 0xA3, 0x61, 0x00, 0x0C, 0xAD, 0x21, 0x00, 0x82, 0x59, 0x9B, 0x1B, 0x00, 0x12, 0x83, 0x97, 0x44, 0x00, 0x0F, 0x87, 0x34, 0x00, 0x06, 0x83, 0x98, 0x45, 0x00, 0x83, 0x4B, 0xE9, 0x57, 0x00, 0x2A, 0xC3, 0x3A, 0x00, 0x42, 0x81, 0x9E, 0x71, 0x00, 0x81, 0x5B, 0x83, 0xAE, 0x16, 0x00, 0x81, 0x13, 0x9E, 0x18, 0x00, 0x1B, 0x87, 0x46, 0x00, 0x0F, 0x81, 0xBC, 0x77, 0x00, 0x83, 0x39, 0x82, 0xD6, 0x03, 0x00, 0x30, 0x84, 0xA6, 0x76, 0x00, 0x0F, 0x8F, 0x09, 0x00, 0x36, 0x84, 0x04, 0x00, 0x0C, 0xA6, 0x1D, 0x00, 0x82, 0x5F, 0xE0, 0x39, 0x00, 0x1B, 0xAD, 0x24, 0x00, 0x06, 0x87, 0x64, 0x00, 0x83, 0x45, 0xCC, 0x55, 0x00, 0x0F, 0x82, 0xB7, 0x59, 0x00, 0x1E, 0x95, 0x5D, 0x00, 0x12, 0x82, 0xEA, 0x41, 0x00, 0x36, 0x84, 0x04, 0x00, 0x0C, 0x97, 0x4A, 0x00, 0x82, 0x05, 0xE0, 0x36, 0x00, 0x06, 0x81, 0xB4, 0x2A, 0x00, 0x54, 0x86, 0x51, 0x00, 0x0F, 0x83, 0xC4, 0x68, 0x00, 0x09, 0x87, 0x46, 0x00, 0x06, 0x81, 0xD4, 0x47, 0x00, 0x83, 0x48, 0xF2, 0x42, 0x00, 0x12, 0x81, 0xC3, 0x57, 0x00, 0x18, 0x9E, 0x21, 0x00, 0x12, 0x87, 0x43, 0x00, 0x42, 0x83, 0xE2, 0x7A, 0x00, 0x81, 0x52, 0x81, 0xF7, 0x31, 0x00, 0x36, 0x82, 0x9D, 0x36, 0x00, 0x5D, 0x81, 0xEA, 0x2D, 0x00, 0x09, 0x83, 0xDA, 0x48, 0x00, 0x06, 0xA9, 0x14, 0x00, 0x06, 0x81, 0xE9, 0x74, 0xE6, 0xE6, 0xE9, 0x00, 0x83, 0x4E, 0x81, 0xFA, 0x2B, 0x00, 0x12, 0x83, 0xB8, 0x3B, 0x00, 0x06, 0x86, 0x80, 0x03, 0x00, 0x09, 0x8C, 0x1B, 0x00, 0x06, 0x81, 0xE9, 0x4A, 0x00, 0x0F, 0x87, 0x6D, 0x00, 0x39, 0x93, 0x0D, 0x00, 0x0F, 0x84, 0xC6, 0x00, 0x00, 0x82, 0x08, 0x82, 0x97, 0x1E, 0xE6, 0xE6, 0xE9, 0x00, 0x5D, 0x82, 0x0E, 0x4D, 0x4F, 0x62, 0x00, 0x09, 0x83, 0xE3, 0x1B, 0x00, 0x83, 0x57, 0x81, 0xE9, 0x6E, 0x00, 0x33, 0x83, 0xA9, 0x26, 0x00, 0x36, 0x93, 0x0D, 0x00, 0x0F, 0x8F, 0x7B, 0x00, 0x81, 0x52, 0x96, 0x4F, 0x00, 0x3F, 0x84, 0xBF, 0x59, 0x00, 0x84, 0x46, 0x82, 0x94, 0x57, 0x00, 0x28, 0x84, 0xD6, 0x55, 0x00, 0x38, 0x86, 0x7E, 0x00, 0x0F, 0x9F, 0x07, 0x00, 0x81, 0x52, 0xA2, 0x5B, 0x00, 0x39, 0x87, 0x46, 0x00, 0x06, 0x83, 0x00, 0x00, 0x84, 0x43, 0xF9, 0x10, 0x00, 0x24, 0x82, 0xFB, 0x6A, 0x00, 0x3C, 0xC3, 0x25, 0x00, 0x0F, 0x9E, 0x12, 0x00, 0x81, 0x55, 0xA5, 0x58, 0x00, 0x82, 0x02, 0x84, 0x81, 0x18, 0x00, 0x83, 0x06, 0xD3, 0x17, 0x00, 0x1B, 0x82, 0xEF, 0x1F, 0x00, 0x3F, 0x82, 0xF8, 0x7C, 0x00, 0x45, 0xAD, 0x60, 0x00, 0x81, 0x55, 0x87, 0x46, 0x00, 0x1E, 0x85, 0xF3, 0x0E, 0x00, 0x48, 0x82, 0xCA, 0x3C, 0x00, 0x06, 0x84, 0xE3, 0x2C, 0x00, 0x54, 0x85, 0x89, 0x79, 0x00, 0x83, 0x18, 0xAD, 0x39, 0x00, 0x0F, 0x82, 0x9B, 0x16, 0x00, 0x0C, 0xA5, 0x6D, 0x00, 0x45, 0x81, 0xFE, 0x59, 0x00, 0x81, 0x58, 0xC0, 0x6D, 0x00, 0x33, 0x87, 0x46, 0x00, 0x09, 0x82, 0xE0, 0x34, 0x00, 0x57, 0x81, 0xB7, 0x18, 0x00, 0x06, 0x82, 0x83, 0x64, 0x00, 0x06, 0x83, 0x9B, 0x03, 0x00, 0x0C, 0x8F, 0x6F, 0x00, 0x06, 0xA9, 0x44, 0x00, 0x84, 0x34, 0x8F, 0x6C, 0x00, 0x06, 0xBA, 0x19, 0x00, 0x81, 0x4F, 0x83, 0xA6, 0x56, 0x00, 0x0C, 0x84, 0x87, 0x51, 0x00, 0x09, 0x83, 0x99, 0x55, 0x00, 0x15, 0x82, 0xD2, 0x3B, 0x00, 0x12, 0x12, 0x00, 0x0C, 0x84, 0x87, 0x7B, 0x00, 0x54, 0x82, 0x14, 0x00, 0x06, 0xBC, 0x18, 0x00, 0x09, 0x92, 0x42, 0x00, 0x83, 0x57, 0xC3, 0x76, 0x00, 0x75, 0x8F, 0x69, 0x00, 0x81, 0x4F, 0xA3, 0x44, 0x00, 0x36, 0x83, 0xC2, 0x2A, 0x00, 0x66, 0x83, 0xA8, 0x6A, 0x00, 0x0F, 0x82, 0x9E, 0x46, 0x00, 0x0F, 0x9E, 0x7B, 0x8D, 0x8E, 0x9A, 0x00, 0x84, 0x67, 0x81, 0xA7, 0x2C, 0x00, 0x81, 0x25, 0xBE, 0x71, 0x00, 0x09, 0x98, 0x7B, 0x00, 0x06, 0x9D, 0x5F, 0x00, 0x2A, 0x84, 0x9E, 0x2C, 0x67, 0x68, 0x78, 0x00, 0x5A, 0x8E, 0x0E, 0x67, 0x68, 0x78, 0x00, 0x0F, 0xE1, 0x6D, 0x00, 0x83, 0x54, 0xE2, 0x0E, 0x00, 0x83, 0x60, 0x82, 0xDB, 0x14, 0x00, 0x06, 0x83, 0xE3, 0x72, 0x00, 0x83, 0x60, 0xF1, 0x1A, 0x00, 0x83, 0x60, 0x87, 0x46, 0x00, 0x24, 0xF8, 0x60, 0x00, 0x83, 0x48, 0x82, 0xA6, 0x2A, 0x00, 0x83, 0x5A, 0x87, 0x46, 0x00, 0x21, 0x96, 0x52, 0x73, 0x75, 0x83, 0x00, 0x83, 0x4B, 0x82, 0xB5, 0x36, 0x00, 0x82, 0x4D, 0xC6, 0x3A, 0x00, 0x81, 0x0D, 0xB3, 0x3F, 0x00, 0x0C, 0x82, 0xC4, 0x33, 0x00, 0x12, 0x87, 0x46, 0x00, 0x84, 0x3A, 0xB4, 0x6D, 0x00, 0x82, 0x71, 0xB7, 0x5B, 0x00, 0x0C, 0x82, 0xA1, 0x76, 0x00, 0x0F, 0x81, 0xB5, 0x10, 0x00, 0x86, 0x15, 0xA5, 0x5B, 0x00, 0x81, 0x1C, 0xED, 0x34, 0x00, 0x06, 0x83, 0xB6, 0x66, 0x00, 0x06, 0x81, 0xB8, 0x7C, 0x00, 0x06, 0x81, 0xB5, 0x0A, 0x00, 0x84, 0x1C, 0x83, 0xE6, 0x0C, 0x00, 0x83, 0x15, 0x83, 0x15, 0x00, 0x06, 0x83, 0xED, 0x55, 0x00, 0x0C, 0x85, 0xF4, 0x57, 0x00, 0x87, 0x25, 0x96, 0x49, 0x00, 0x87, 0x40, 0x82, 0xFA, 0x2A, 0x00, 0x8E, 0x17, 0x8E, 0x17, 0x00, 0x12, 0xEC, 0x1B, 0x00, 0x21, 0xD3, 0x14, 0x00, 0x51, 0xB5, 0x77, 0x00, 0x86, 0x3C, 0x83, 0xA0, 0x17, 0x00, 0x39, 0x84, 0xF7, 0x79, 0x00, 0x54, 0x82, 0x81, 0x53, 0x00, 0x86, 0x36, 0xAD, 0x09, 0x00, 0x0C, 0x82, 0xCD, 0x69, 0xD9, 0xD9, 0xDD, 0xB3, 0xB4, 0xBC, 0x00, 0x06, 0x8E, 0x68, 0xE6, 0xE6, 0xE9, 0x00, 0x0F, 0xE2, 0x29, 0x00, 0x06, 0xEA, 0x0D, 0x00, 0x0C, 0x15, 0x00, 0x60, 0x81, 0xB5, 0x10, 0x00, 0x86, 0x2A, 0x87, 0x46, 0x00, 0x09, 0x84, 0xE2, 0x79, 0x00, 0x0F, 0x81, 0x8A, 0x18, 0x00, 0x06, 0xF8, 0x51, 0x00, 0x15, 0x82, 0xA8, 0x6E, 0x00, 0x5A, 0x81, 0xAD, 0x44, 0x67, 0x68, 0x78, 0x00, 0x06, 0x82, 0x9F, 0x74, 0x00, 0x06, 0x84, 0xC6, 0x06, 0x00, 0x81, 0x2B, 0x84, 0x81, 0x18, 0x00, 0x85, 0x02, 0xC2, 0x63, 0x00, 0x15, 0x82, 0xF3, 0x41, 0x00, 0x15, 0x87, 0x46, 0x00, 0x09, 0x33, 0x00, 0x54, 0x8F, 0x09, 0x00, 0x0F, 0x82, 0xD6, 0x6C, 0x00, 0x81, 0x2B, 0x84, 0x90, 0x24, 0x00, 0x84, 0x7F, 0x87, 0x46, 0x00, 0x06, 0x81, 0x99, 0x36, 0x00, 0x15, 0x81, 0xBB, 0x31, 0x00, 0x18, 0x87, 0x46, 0x00, 0x06, 0xD2, 0x0D, 0x00, 0x86, 0x39, 0x9D, 0x41, 0x00, 0x57, 0x81, 0xEC, 0x4D, 0x00, 0x18, 0xEF, 0x6C, 0x00, 0x1B, 0x87, 0x46, 0x00, 0x06, 0x81, 0xDC, 0x7F, 0x00, 0x84, 0x2B, 0x84, 0xA9, 0x19, 0x00, 0x82, 0x7A, 0xF1, 0x1A, 0x00, 0x1B, 0x87, 0x46, 0x00, 0x06, 0x1E, 0x00, 0x86, 0x15, 0xF0, 0x25, 0x00, 0x78, 0x83, 0x88, 0x35, 0x00, 0x18, 0xA5, 0x2B, 0x00, 0x1E, 0x87, 0x46, 0x00, 0x06, 0xAD, 0x45, 0x00, 0x87, 0x0A, 0x8F, 0x0C, 0x00, 0x39, 0x87, 0x46, 0x00, 0x45, 0xBC, 0x30, 0x4D, 0x4F, 0x62, 0x00, 0x84, 0x58, 0x82, 0xB6, 0x22, 0x00, 0x82, 0x23, 0x96, 0x52, 0x00, 0x48, 0x87, 0x46, 0x00, 0x18, 0xBC, 0x78, 0x00, 0x0F, 0x83, 0x90, 0x07, 0x00, 0x86, 0x21, 0x83, 0xDB, 0x37, 0x00, 0x18, 0x96, 0x19, 0x00, 0x0F, 0x81, 0xC3, 0x1B, 0x00, 0x6F, 0x87, 0x46, 0x00, 0x81, 0x7F, 0x84, 0xC0, 0x54, 0x00, 0x84, 0x34, 0x81, 0xDD, 0x35, 0x00, 0x15, 0x95, 0x54, 0x00, 0x1E, 0x87, 0x28, 0xC0, 0xC0, 0xC7, 0x00, 0x45, 0x81, 0x86, 0x7A, 0x00, 0x86, 0x45, 0x87, 0x46, 0x00, 0x1B, 0xC3, 0x43, 0x00, 0x09, 0x81, 0x86, 0x6B, 0x00, 0x18, 0xB4, 0x6A, 0x00, 0x45, 0xCB, 0x42, 0x00, 0x86, 0x45, 0x87, 0x46, 0x00, 0x09, 0xBC, 0x33, 0x00, 0x12, 0x9D, 0x05, 0x00, 0x1B, 0x86, 0x81, 0x49, 0x00, 0x06, 0x8F, 0x42, 0x00, 0x45, 0x81, 0xFF, 0x5D, 0x00, 0x86, 0x48, 0x87, 0x46, 0x00, 0x1B, 0xDA, 0x1B, 0x00, 0x06, 0x87, 0x2E, 0x00, 0x0C, 0x83, 0xB4, 0x55, 0x00, 0x09, 0xE9, 0x7E, 0x00, 0x48, 0x81, 0x9D, 0x49, 0x00, 0x86, 0x48, 0x87, 0x46, 0x00, 0x09, 0xE2, 0x11, 0x00, 0x12, 0x86, 0x36, 0x00, 0x0C, 0x82, 0x92, 0x1C, 0x00, 0x06, 0x81, 0x9D, 0x40, 0x00, 0x30, 0x85, 0xAA, 0x13, 0x00, 0x27, 0x85, 0x97, 0x7B, 0x00, 0x12, 0x81, 0xDB, 0x57, 0x00, 0x06, 0x81, 0xE2, 0x37, 0x00, 0x81, 0x4F, 0x84, 0xAE, 0x3C, 0x00, 0x84, 0x61, 0xF1, 0x1D, 0x00, 0x1B, 0x82, 0x99, 0x65, 0x00, 0x0F, 0xF8, 0x7B, 0x00, 0x4E, 0x84, 0xF4, 0x52, 0x00, 0x09, 0x84, 0xDF, 0x01, 0x00, 0x7B, 0x85, 0xF2, 0x58, 0x00, 0x85, 0x6B, 0x87, 0x67, 0x00, 0x06, 0xF0, 0x19, 0x00, 0x86, 0x42, 0xC3, 0x22, 0x00, 0x91, 0x44, 0x81, 0xA0, 0x16}; static bool g_has_uncompressed = false; static unsigned char *get_uncompressed_splash(void) { @@ -44,8 +44,8 @@ void draw_splash(volatile uint32_t *fb) { } /* Draw actual splash. */ - const size_t x_res = 336; - const size_t y_res = 392; + const size_t x_res = 322; + const size_t y_res = 276; const size_t x_start = (768 - x_res) / 2; const size_t y_start = (1280 - y_res) / 2; From a0e06cf7b2e0061ca594dad140508a2fa6fc5d79 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 07:05:58 -0800 Subject: [PATCH 438/489] exo/bpc.mitm: Add support for proper shutdown. --- exosphere/rebootstub/src/i2c.c | 169 ++++++++ exosphere/rebootstub/src/i2c.h | 51 +++ exosphere/rebootstub/src/max77620.h | 360 ++++++++++++++++++ exosphere/rebootstub/src/shutdown.c | 30 ++ exosphere/rebootstub/src/start.s | 13 +- exosphere/rebootstub/src/timer.h | 33 ++ exosphere/rebootstub/src/utils.h | 38 ++ exosphere/src/configitem.c | 32 ++ exosphere/src/configitem.h | 1 + .../source/bpc_mitm/bpc_mitm_service.cpp | 5 +- stratosphere/libstratosphere | 2 +- 11 files changed, 727 insertions(+), 7 deletions(-) create mode 100644 exosphere/rebootstub/src/i2c.c create mode 100644 exosphere/rebootstub/src/i2c.h create mode 100644 exosphere/rebootstub/src/max77620.h create mode 100644 exosphere/rebootstub/src/shutdown.c create mode 100644 exosphere/rebootstub/src/timer.h create mode 100644 exosphere/rebootstub/src/utils.h diff --git a/exosphere/rebootstub/src/i2c.c b/exosphere/rebootstub/src/i2c.c new file mode 100644 index 000000000..38fed9091 --- /dev/null +++ b/exosphere/rebootstub/src/i2c.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "max77620.h" +#include "i2c.h" +#include "timer.h" + +/* Prototypes for internal commands. */ +void i2c_load_config(void); +int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes); +int i2c_read(unsigned int device, void *dst, unsigned num_bytes); +int i2c_query(uint8_t device, uint8_t r, void *dst, size_t num_bytes); +int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b); + +/* Load hardware config for I2C4. */ +void i2c_load_config(void) { + /* Set MSTR_CONFIG_LOAD, TIMEOUT_CONFIG_LOAD, undocumented bit. */ + I2C_I2C_CONFIG_LOAD_0 = 0x25; + + /* Wait a bit for master config to be loaded. */ + for (unsigned int i = 0; i < 20; i++) { + timer_wait(1); + if (!(I2C_I2C_CONFIG_LOAD_0 & 1)) { + break; + } + } +} + +/* Initialize I2C4. */ +void i2c_init(void) { + /* Setup divisor, and clear the bus. */ + I2C_I2C_CLK_DIVISOR_REGISTER_0 = 0x50001; + I2C_I2C_BUS_CLEAR_CONFIG_0 = 0x90003; + + /* Load hardware configuration. */ + i2c_load_config(); + + /* Wait a while until BUS_CLEAR_DONE is set. */ + for (unsigned int i = 0; i < 10; i++) { + timer_wait(20000); + if (I2C_INTERRUPT_STATUS_REGISTER_0 & 0x800) { + break; + } + } + + /* Read the BUS_CLEAR_STATUS. Result doesn't matter. */ + I2C_I2C_BUS_CLEAR_STATUS_0; + + /* Read and set the Interrupt Status. */ + uint32_t int_status = I2C_INTERRUPT_STATUS_REGISTER_0; + I2C_INTERRUPT_STATUS_REGISTER_0 = int_status; +} + +/* Writes a value to an i2c device. */ +int i2c_write(unsigned int device, uint32_t val, unsigned int num_bytes) { + if (num_bytes > 4) { + return 0; + } + + /* Set device for 7-bit mode. */ + I2C_I2C_CMD_ADDR0_0 = device << 1; + + /* Load in data to write. */ + I2C_I2C_CMD_DATA1_0 = val; + + /* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2800; + + i2c_load_config(); + + /* Config |= SEND; */ + I2C_I2C_CNFG_0 |= 0x200; + + + while (I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Return CMD1_STAT == SL1_XFER_SUCCESSFUL. */ + return (I2C_I2C_STATUS_0 & 0xF) == 0; +} + +/* Reads a value from an i2c device. */ +int i2c_read(unsigned device, void *dst, unsigned num_bytes) { + if (num_bytes > 4) { + return 0; + } + + /* Set device for 7-bit read mode. */ + I2C_I2C_CMD_ADDR0_0 = (device << 1) | 1; + + /* Set config with LENGTH = num_bytes, NEW_MASTER_FSM, DEBOUNCE_CNT = 4T. */ + I2C_I2C_CNFG_0 = ((num_bytes << 1) - 2) | 0x2840; + + i2c_load_config(); + + /* Config |= SEND; */ + I2C_I2C_CNFG_0 |= 0x200; + + + while (I2C_I2C_STATUS_0 & 0x100) { + /* Wait until not busy. */ + } + + /* Ensure success. */ + if ((I2C_I2C_STATUS_0 & 0xF) != 0) { + return 0; + } + + uint32_t val = I2C_I2C_CMD_DATA1_0; + for (size_t i = 0; i < num_bytes; i++) { + ((uint8_t *)dst)[i] = ((uint8_t *)&val)[i]; + } + return 1; +} + +/* Queries the value of a register. */ +int i2c_query(uint8_t device, uint8_t r, void *dst, size_t num_bytes) { + /* Limit output size to 32-bits. */ + if (num_bytes > 4) { + return 0; + } + + /* Write single byte register ID to device. */ + if (!i2c_write(device, r, 1)) { + return 0; + } + + return i2c_read(device, dst, num_bytes); + +} + +/* Writes a byte val to reg for given device. */ +int i2c_send_byte_command(unsigned int device, unsigned char reg, unsigned char b) { + uint32_t val = (reg) | (b << 8); + /* Write 1 byte (reg) + 1 byte (value) */ + return i2c_write(device, val, 2); +} + +void i2c_stop_rtc_alarm(void) { + i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCUPDATE0, 0x10); + + uint8_t val = 0; + for (int i = 0; i < 14; i++) { + if (i2c_query(MAX77620_RTC_I2C_ADDR, 0x0E + i, &val, 1)) { + val &= 0x7F; + i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, 0x0E + i, val); + } + } + + i2c_send_byte_command(MAX77620_RTC_I2C_ADDR, MAX77620_REG_RTCUPDATE0, 0x01); +} + +void i2c_send_shutdown_cmd(void) { + i2c_send_byte_command(MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); +} diff --git a/exosphere/rebootstub/src/i2c.h b/exosphere/rebootstub/src/i2c.h new file mode 100644 index 000000000..2089404a0 --- /dev/null +++ b/exosphere/rebootstub/src/i2c.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_REBOOTSTUB_I2C_H +#define EXOSPHERE_REBOOTSTUB_I2C_H + +#include "utils.h" + +/* I2C_BASE = I2C4. */ +#define I2C_BASE (0x7000D000) + +#define MAKE_I2C_REG(ofs) (MAKE_REG32(I2C_BASE + ofs)) + +#define I2C_I2C_CNFG_0 MAKE_I2C_REG(0x000) + +#define I2C_I2C_CMD_ADDR0_0 MAKE_I2C_REG(0x004) + +#define I2C_I2C_CMD_DATA1_0 MAKE_I2C_REG(0x00C) + +#define I2C_I2C_STATUS_0 MAKE_I2C_REG(0x01C) + +#define I2C_INTERRUPT_STATUS_REGISTER_0 MAKE_I2C_REG(0x068) + +#define I2C_I2C_CLK_DIVISOR_REGISTER_0 MAKE_I2C_REG(0x06C) + +#define I2C_I2C_BUS_CLEAR_CONFIG_0 MAKE_I2C_REG(0x084) + +#define I2C_I2C_BUS_CLEAR_STATUS_0 MAKE_I2C_REG(0x088) + + +#define I2C_I2C_CONFIG_LOAD_0 MAKE_I2C_REG(0x08C) + +void i2c_init(void); + +void i2c_stop_rtc_alarm(void); +void i2c_send_shutdown_cmd(void); + +#endif diff --git a/exosphere/rebootstub/src/max77620.h b/exosphere/rebootstub/src/max77620.h new file mode 100644 index 000000000..dcab6c786 --- /dev/null +++ b/exosphere/rebootstub/src/max77620.h @@ -0,0 +1,360 @@ +/* + * Defining registers address and its bit definitions of MAX77620 and MAX20024 + * + * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#ifndef _MFD_MAX77620_H_ +#define _MFD_MAX77620_H_ + +#define MAX77620_I2C_ADDR 0x3C +#define MAX77620_RTC_I2C_ADDR 0x68 + +/* RTC Registers */ +#define MAX77620_REG_RTCINT 0x00 +#define MAX77620_REG_RTCINTM 0x01 +#define MAX77620_REG_RTCCNTLM 0x02 +#define MAX77620_REG_RTCCNTL 0x03 +#define MAX77620_REG_RTCUPDATE0 0x04 +#define MAX77620_REG_RTCUPDATE1 0x05 +#define MAX77620_REG_RTCSMPL 0x06 +#define MAX77620_REG_RTCSEC 0x07 +#define MAX77620_REG_RTCMIN 0x08 +#define MAX77620_REG_RTCHOUR 0x09 +#define MAX77620_REG_RTCDOW 0x0A +#define MAX77620_REG_RTCMONTH 0x0B +#define MAX77620_REG_RTCYEAR 0x0C +#define MAX77620_REG_RTCDOM 0x0D +#define MAX77620_REG_RTCSECA1 0x0E +#define MAX77620_REG_RTCMINA1 0x0F +#define MAX77620_REG_RTCHOURA1 0x10 +#define MAX77620_REG_RTCDOWA1 0x11 +#define MAX77620_REG_RTCMONTHA1 0x12 +#define MAX77620_REG_RTCYEARA1 0x13 +#define MAX77620_REG_RTCDOMA1 0x14 +#define MAX77620_REG_RTCSECA2 0x15 +#define MAX77620_REG_RTCMINA2 0x16 +#define MAX77620_REG_RTCHOURA2 0x17 +#define MAX77620_REG_RTCDOWA2 0x18 +#define MAX77620_REG_RTCMONTHA2 0x19 +#define MAX77620_REG_RTCYEARA2 0x1A +#define MAX77620_REG_RTCDOMA2 0x1B + +/* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ +#define MAX77620_REG_CNFGGLBL1 0x00 +#define MAX77620_REG_CNFGGLBL2 0x01 +#define MAX77620_REG_CNFGGLBL3 0x02 +#define MAX77620_REG_CNFG1_32K 0x03 +#define MAX77620_REG_CNFGBBC 0x04 +#define MAX77620_REG_IRQTOP 0x05 +#define MAX77620_REG_INTLBT 0x06 +#define MAX77620_REG_IRQSD 0x07 +#define MAX77620_REG_IRQ_LVL2_L0_7 0x08 +#define MAX77620_REG_IRQ_LVL2_L8 0x09 +#define MAX77620_REG_IRQ_LVL2_GPIO 0x0A +#define MAX77620_REG_ONOFFIRQ 0x0B +#define MAX77620_REG_NVERC 0x0C +#define MAX77620_REG_IRQTOPM 0x0D +#define MAX77620_REG_INTENLBT 0x0E +#define MAX77620_REG_IRQMASKSD 0x0F +#define MAX77620_REG_IRQ_MSK_L0_7 0x10 +#define MAX77620_REG_IRQ_MSK_L8 0x11 +#define MAX77620_REG_ONOFFIRQM 0x12 +#define MAX77620_REG_STATLBT 0x13 +#define MAX77620_REG_STATSD 0x14 +#define MAX77620_REG_ONOFFSTAT 0x15 + +/* SD and LDO Registers */ +#define MAX77620_REG_SD0 0x16 +#define MAX77620_REG_SD1 0x17 +#define MAX77620_REG_SD2 0x18 +#define MAX77620_REG_SD3 0x19 +#define MAX77620_REG_SD4 0x1A +#define MAX77620_REG_DVSSD0 0x1B +#define MAX77620_REG_DVSSD1 0x1C +#define MAX77620_REG_SD0_CFG 0x1D +#define MAX77620_REG_SD1_CFG 0x1E +#define MAX77620_REG_SD2_CFG 0x1F +#define MAX77620_REG_SD3_CFG 0x20 +#define MAX77620_REG_SD4_CFG 0x21 +#define MAX77620_REG_SD_CFG2 0x22 +#define MAX77620_REG_LDO0_CFG 0x23 +#define MAX77620_REG_LDO0_CFG2 0x24 +#define MAX77620_REG_LDO1_CFG 0x25 +#define MAX77620_REG_LDO1_CFG2 0x26 +#define MAX77620_REG_LDO2_CFG 0x27 +#define MAX77620_REG_LDO2_CFG2 0x28 +#define MAX77620_REG_LDO3_CFG 0x29 +#define MAX77620_REG_LDO3_CFG2 0x2A +#define MAX77620_REG_LDO4_CFG 0x2B +#define MAX77620_REG_LDO4_CFG2 0x2C +#define MAX77620_REG_LDO5_CFG 0x2D +#define MAX77620_REG_LDO5_CFG2 0x2E +#define MAX77620_REG_LDO6_CFG 0x2F +#define MAX77620_REG_LDO6_CFG2 0x30 +#define MAX77620_REG_LDO7_CFG 0x31 +#define MAX77620_REG_LDO7_CFG2 0x32 +#define MAX77620_REG_LDO8_CFG 0x33 +#define MAX77620_REG_LDO8_CFG2 0x34 +#define MAX77620_REG_LDO_CFG3 0x35 + +#define MAX77620_LDO_SLEW_RATE_MASK 0x1 + +/* LDO Configuration 3 */ +#define MAX77620_TRACK4_MASK (1 << 5) +#define MAX77620_TRACK4_SHIFT 5 + +/* Voltage */ +#define MAX77620_SDX_VOLT_MASK 0xFF +#define MAX77620_SD0_VOLT_MASK 0x3F +#define MAX77620_SD1_VOLT_MASK 0x7F +#define MAX77620_LDO_VOLT_MASK 0x3F + +#define MAX77620_REG_GPIO0 0x36 +#define MAX77620_REG_GPIO1 0x37 +#define MAX77620_REG_GPIO2 0x38 +#define MAX77620_REG_GPIO3 0x39 +#define MAX77620_REG_GPIO4 0x3A +#define MAX77620_REG_GPIO5 0x3B +#define MAX77620_REG_GPIO6 0x3C +#define MAX77620_REG_GPIO7 0x3D +#define MAX77620_REG_PUE_GPIO 0x3E +#define MAX77620_REG_PDE_GPIO 0x3F +#define MAX77620_REG_AME_GPIO 0x40 +#define MAX77620_REG_ONOFFCNFG1 0x41 +#define MAX77620_REG_ONOFFCNFG2 0x42 + +/* FPS Registers */ +#define MAX77620_REG_FPS_CFG0 0x43 +#define MAX77620_REG_FPS_CFG1 0x44 +#define MAX77620_REG_FPS_CFG2 0x45 +#define MAX77620_REG_FPS_LDO0 0x46 +#define MAX77620_REG_FPS_LDO1 0x47 +#define MAX77620_REG_FPS_LDO2 0x48 +#define MAX77620_REG_FPS_LDO3 0x49 +#define MAX77620_REG_FPS_LDO4 0x4A +#define MAX77620_REG_FPS_LDO5 0x4B +#define MAX77620_REG_FPS_LDO6 0x4C +#define MAX77620_REG_FPS_LDO7 0x4D +#define MAX77620_REG_FPS_LDO8 0x4E +#define MAX77620_REG_FPS_SD0 0x4F +#define MAX77620_REG_FPS_SD1 0x50 +#define MAX77620_REG_FPS_SD2 0x51 +#define MAX77620_REG_FPS_SD3 0x52 +#define MAX77620_REG_FPS_SD4 0x53 +#define MAX77620_REG_FPS_NONE 0 + +#define MAX77620_FPS_SRC_MASK 0xC0 +#define MAX77620_FPS_SRC_SHIFT 6 +#define MAX77620_FPS_PU_PERIOD_MASK 0x38 +#define MAX77620_FPS_PU_PERIOD_SHIFT 3 +#define MAX77620_FPS_PD_PERIOD_MASK 0x07 +#define MAX77620_FPS_PD_PERIOD_SHIFT 0 +#define MAX77620_FPS_TIME_PERIOD_MASK 0x38 +#define MAX77620_FPS_TIME_PERIOD_SHIFT 3 +#define MAX77620_FPS_EN_SRC_MASK 0x06 +#define MAX77620_FPS_EN_SRC_SHIFT 1 +#define MAX77620_FPS_ENFPS_SW_MASK 0x01 +#define MAX77620_FPS_ENFPS_SW 0x01 + +/* Minimum and maximum FPS period time (in microseconds) are + * different for MAX77620 and Max20024. + */ +#define MAX77620_FPS_PERIOD_MIN_US 40 +#define MAX20024_FPS_PERIOD_MIN_US 20 + +#define MAX77620_FPS_PERIOD_MAX_US 2560 +#define MAX20024_FPS_PERIOD_MAX_US 5120 + +#define MAX77620_REG_FPS_GPIO1 0x54 +#define MAX77620_REG_FPS_GPIO2 0x55 +#define MAX77620_REG_FPS_GPIO3 0x56 +#define MAX77620_REG_FPS_RSO 0x57 +#define MAX77620_REG_CID0 0x58 +#define MAX77620_REG_CID1 0x59 +#define MAX77620_REG_CID2 0x5A +#define MAX77620_REG_CID3 0x5B +#define MAX77620_REG_CID4 0x5C +#define MAX77620_REG_CID5 0x5D + +#define MAX77620_REG_DVSSD4 0x5E +#define MAX20024_REG_MAX_ADD 0x70 + +#define MAX77620_CID_DIDM_MASK 0xF0 +#define MAX77620_CID_DIDM_SHIFT 4 + +/* CNCG2SD */ +#define MAX77620_SD_CNF2_ROVS_EN_SD1 (1 << 1) +#define MAX77620_SD_CNF2_ROVS_EN_SD0 (1 << 2) + +/* Device Identification Metal */ +#define MAX77620_CID5_DIDM(n) (((n) >> 4) & 0xF) +/* Device Indentification OTP */ +#define MAX77620_CID5_DIDO(n) ((n) & 0xF) + +/* SD CNFG1 */ +#define MAX77620_SD_SR_MASK 0xC0 +#define MAX77620_SD_SR_SHIFT 6 +#define MAX77620_SD_POWER_MODE_MASK 0x30 +#define MAX77620_SD_POWER_MODE_SHIFT 4 +#define MAX77620_SD_CFG1_ADE_MASK (1 << 3) +#define MAX77620_SD_CFG1_ADE_DISABLE 0 +#define MAX77620_SD_CFG1_ADE_ENABLE (1 << 3) +#define MAX77620_SD_FPWM_MASK 0x04 +#define MAX77620_SD_FPWM_SHIFT 2 +#define MAX77620_SD_FSRADE_MASK 0x01 +#define MAX77620_SD_FSRADE_SHIFT 0 +#define MAX77620_SD_CFG1_FPWM_SD_MASK (1 << 2) +#define MAX77620_SD_CFG1_FPWM_SD_SKIP 0 +#define MAX77620_SD_CFG1_FPWM_SD_FPWM (1 << 2) +#define MAX20024_SD_CFG1_MPOK_MASK (1 << 1) +#define MAX77620_SD_CFG1_FSRADE_SD_MASK (1 << 0) +#define MAX77620_SD_CFG1_FSRADE_SD_DISABLE 0 +#define MAX77620_SD_CFG1_FSRADE_SD_ENABLE (1 << 0) + +/* LDO_CNFG2 */ +#define MAX77620_LDO_POWER_MODE_MASK 0xC0 +#define MAX77620_LDO_POWER_MODE_SHIFT 6 +#define MAX20024_LDO_CFG2_MPOK_MASK (1 << 2) +#define MAX77620_LDO_CFG2_ADE_MASK (1 << 1) +#define MAX77620_LDO_CFG2_ADE_DISABLE 0 +#define MAX77620_LDO_CFG2_ADE_ENABLE (1 << 1) +#define MAX77620_LDO_CFG2_SS_MASK (1 << 0) +#define MAX77620_LDO_CFG2_SS_FAST (1 << 0) +#define MAX77620_LDO_CFG2_SS_SLOW 0 + +#define MAX77620_IRQ_TOP_GLBL_MASK (1 << 7) +#define MAX77620_IRQ_TOP_SD_MASK (1 << 6) +#define MAX77620_IRQ_TOP_LDO_MASK (1 << 5) +#define MAX77620_IRQ_TOP_GPIO_MASK (1 << 4) +#define MAX77620_IRQ_TOP_RTC_MASK (1 << 3) +#define MAX77620_IRQ_TOP_32K_MASK (1 << 2) +#define MAX77620_IRQ_TOP_ONOFF_MASK (1 << 1) + +#define MAX77620_IRQ_LBM_MASK (1 << 3) +#define MAX77620_IRQ_TJALRM1_MASK (1 << 2) +#define MAX77620_IRQ_TJALRM2_MASK (1 << 1) + +#define MAX77620_CNFG_GPIO_DRV_MASK (1 << 0) +#define MAX77620_CNFG_GPIO_DRV_PUSHPULL (1 << 0) +#define MAX77620_CNFG_GPIO_DRV_OPENDRAIN 0 +#define MAX77620_CNFG_GPIO_DIR_MASK (1 << 1) +#define MAX77620_CNFG_GPIO_DIR_INPUT (1 << 1) +#define MAX77620_CNFG_GPIO_DIR_OUTPUT 0 +#define MAX77620_CNFG_GPIO_INPUT_VAL_MASK (1 << 2) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_MASK (1 << 3) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH (1 << 3) +#define MAX77620_CNFG_GPIO_OUTPUT_VAL_LOW 0 +#define MAX77620_CNFG_GPIO_INT_MASK (0x3 << 4) +#define MAX77620_CNFG_GPIO_INT_FALLING (1 << 4) +#define MAX77620_CNFG_GPIO_INT_RISING (1 << 5) +#define MAX77620_CNFG_GPIO_DBNC_MASK (0x3 << 6) +#define MAX77620_CNFG_GPIO_DBNC_None (0x0 << 6) +#define MAX77620_CNFG_GPIO_DBNC_8ms (0x1 << 6) +#define MAX77620_CNFG_GPIO_DBNC_16ms (0x2 << 6) +#define MAX77620_CNFG_GPIO_DBNC_32ms (0x3 << 6) + +#define MAX77620_IRQ_LVL2_GPIO_EDGE0 (1 << 0) +#define MAX77620_IRQ_LVL2_GPIO_EDGE1 (1 << 1) +#define MAX77620_IRQ_LVL2_GPIO_EDGE2 (1 << 2) +#define MAX77620_IRQ_LVL2_GPIO_EDGE3 (1 << 3) +#define MAX77620_IRQ_LVL2_GPIO_EDGE4 (1 << 4) +#define MAX77620_IRQ_LVL2_GPIO_EDGE5 (1 << 5) +#define MAX77620_IRQ_LVL2_GPIO_EDGE6 (1 << 6) +#define MAX77620_IRQ_LVL2_GPIO_EDGE7 (1 << 7) + +#define MAX77620_CNFG1_32K_OUT0_EN (1 << 2) + +#define MAX77620_ONOFFCNFG1_SFT_RST (1 << 7) +#define MAX77620_ONOFFCNFG1_MRT_MASK 0x38 +#define MAX77620_ONOFFCNFG1_MRT_SHIFT 0x3 +#define MAX77620_ONOFFCNFG1_SLPEN (1 << 2) +#define MAX77620_ONOFFCNFG1_PWR_OFF (1 << 1) +#define MAX20024_ONOFFCNFG1_CLRSE 0x18 + +#define MAX77620_ONOFFCNFG2_SFT_RST_WK (1 << 7) +#define MAX77620_ONOFFCNFG2_WD_RST_WK (1 << 6) +#define MAX77620_ONOFFCNFG2_SLP_LPM_MSK (1 << 5) +#define MAX77620_ONOFFCNFG2_WK_ALARM1 (1 << 2) +#define MAX77620_ONOFFCNFG2_WK_EN0 (1 << 0) + +#define MAX77620_GLBLM_MASK (1 << 0) + +#define MAX77620_WDTC_MASK 0x3 +#define MAX77620_WDTOFFC (1 << 4) +#define MAX77620_WDTSLPC (1 << 3) +#define MAX77620_WDTEN (1 << 2) + +#define MAX77620_TWD_MASK 0x3 +#define MAX77620_TWD_2s 0x0 +#define MAX77620_TWD_16s 0x1 +#define MAX77620_TWD_64s 0x2 +#define MAX77620_TWD_128s 0x3 + +#define MAX77620_CNFGGLBL1_LBDAC_EN (1 << 7) +#define MAX77620_CNFGGLBL1_MPPLD (1 << 6) +#define MAX77620_CNFGGLBL1_LBHYST ((1 << 5) | (1 << 4)) +#define MAX77620_CNFGGLBL1_LBHYST_N (1 << 4) +#define MAX77620_CNFGGLBL1_LBDAC 0x0E +#define MAX77620_CNFGGLBL1_LBDAC_N (1 << 1) +#define MAX77620_CNFGGLBL1_LBRSTEN (1 << 0) + +/* CNFG BBC registers */ +#define MAX77620_CNFGBBC_ENABLE (1 << 0) +#define MAX77620_CNFGBBC_CURRENT_MASK 0x06 +#define MAX77620_CNFGBBC_CURRENT_SHIFT 1 +#define MAX77620_CNFGBBC_VOLTAGE_MASK 0x18 +#define MAX77620_CNFGBBC_VOLTAGE_SHIFT 3 +#define MAX77620_CNFGBBC_LOW_CURRENT_DISABLE (1 << 5) +#define MAX77620_CNFGBBC_RESISTOR_MASK 0xC0 +#define MAX77620_CNFGBBC_RESISTOR_SHIFT 6 + +#define MAX77620_FPS_COUNT 3 + +/* Interrupts */ +enum { + MAX77620_IRQ_TOP_GLBL, /* Low-Battery */ + MAX77620_IRQ_TOP_SD, /* SD power fail */ + MAX77620_IRQ_TOP_LDO, /* LDO power fail */ + MAX77620_IRQ_TOP_GPIO, /* TOP GPIO internal int to MAX77620 */ + MAX77620_IRQ_TOP_RTC, /* RTC */ + MAX77620_IRQ_TOP_32K, /* 32kHz oscillator */ + MAX77620_IRQ_TOP_ONOFF, /* ON/OFF oscillator */ + MAX77620_IRQ_LBT_MBATLOW, /* Thermal alarm status, > 120C */ + MAX77620_IRQ_LBT_TJALRM1, /* Thermal alarm status, > 120C */ + MAX77620_IRQ_LBT_TJALRM2, /* Thermal alarm status, > 140C */ +}; + +/* GPIOs */ +enum { + MAX77620_GPIO0, + MAX77620_GPIO1, + MAX77620_GPIO2, + MAX77620_GPIO3, + MAX77620_GPIO4, + MAX77620_GPIO5, + MAX77620_GPIO6, + MAX77620_GPIO7, + MAX77620_GPIO_NR, +}; + +/* FPS Source */ +enum max77620_fps_src { + MAX77620_FPS_SRC_0, + MAX77620_FPS_SRC_1, + MAX77620_FPS_SRC_2, + MAX77620_FPS_SRC_NONE, + MAX77620_FPS_SRC_DEF, +}; + +enum max77620_chip_id { + MAX77620, + MAX20024, +}; + +#endif /* _MFD_MAX77620_H_ */ diff --git a/exosphere/rebootstub/src/shutdown.c b/exosphere/rebootstub/src/shutdown.c new file mode 100644 index 000000000..e7596e882 --- /dev/null +++ b/exosphere/rebootstub/src/shutdown.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils.h" +#include "i2c.h" +#include "timer.h" + +void do_shutdown(void) { + /* Initialize i2c. */ + i2c_init(); + + /* Stop alarm, shutdown. */ + i2c_stop_rtc_alarm(); + i2c_send_shutdown_cmd(); + + while (true) { } +} \ No newline at end of file diff --git a/exosphere/rebootstub/src/start.s b/exosphere/rebootstub/src/start.s index 155ab382a..461ba2099 100644 --- a/exosphere/rebootstub/src/start.s +++ b/exosphere/rebootstub/src/start.s @@ -18,11 +18,16 @@ .align 4 .global _start _start: - b crt0 + adr r0, reboot_type + cmp r0, #0x0 + beq do_shutdown + b jump_to_reboot_payload +reboot_type: +.word 0x00000001 -.global crt0 -.type crt0, %function -crt0: +.global jump_to_reboot_payload +.type jump_to_reboot_payload, %function +jump_to_reboot_payload: @ clear all registers ldr r0, =0x52425430 @ RBT0 mov r1, #0x0 diff --git a/exosphere/rebootstub/src/timer.h b/exosphere/rebootstub/src/timer.h new file mode 100644 index 000000000..939930bde --- /dev/null +++ b/exosphere/rebootstub/src/timer.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_REBOOTSTUB_TIMER_H +#define EXOSPHERE_REBOOTSTUB_TIMER_H + +#include "utils.h" + +#define TIMERUS_CNTR_1US_0 MAKE_REG32(0x60005010) + +static inline void timer_wait(uint32_t microseconds) { + uint32_t old_time = TIMERUS_CNTR_1US_0; + while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) { + /* Spin-lock. */ + } +} + +void spinlock_wait(uint32_t count); + +#endif diff --git a/exosphere/rebootstub/src/utils.h b/exosphere/rebootstub/src/utils.h new file mode 100644 index 000000000..531de9fb6 --- /dev/null +++ b/exosphere/rebootstub/src/utils.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef EXOSPHERE_REBOOTSTUB_UTILS_H +#define EXOSPHERE_REBOOTSTUB_UTILS_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define BIT(n) (1u << (n)) +#define BITL(n) (1ull << (n)) +#define MASK(n) (BIT(n) - 1) +#define MASKL(n) (BITL(n) - 1) +#define MASK2(a,b) (MASK(a) & ~MASK(b)) +#define MASK2L(a,b) (MASKL(a) & ~MASKL(b)) + +#define MAKE_REG32(a) (*(volatile uint32_t *)(a)) + +#define ALIGN(m) __attribute__((aligned(m))) +#define PACKED __attribute__((packed)) + +#define ALINLINE __attribute__((always_inline)) + +#endif diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index e332311c8..7029297d3 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -80,6 +80,34 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { while (1) { } } break; + case CONFIGITEM_NEEDS_SHUTDOWN: + /* Force a shutdown, if requested. */ + { + if (value == 0) { + return 0; + } + /* Set reboot kind = warmboot. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1; + /* Patch SDRAM init to perform an SVC immediately after second write */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x2E38DFFF; + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x6001DC28; + /* Set SVC handler to jump to reboot stub in IRAM. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x520ull) = 0x4003F000; + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x53Cull) = 0x6000F208; + + /* Copy reboot stub payload. */ + ams_map_irampage(0x4003F000); + for (unsigned int i = 0; i < rebootstub_bin_size; i += 4) { + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + i) = read32le(rebootstub_bin, i); + } + /* Tell rebootstub to shut down. */ + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + 0x10) = 0x0; + ams_unmap_irampage(); + + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; + while (1) { } + } + break; default: return 2; } @@ -228,6 +256,10 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue) /* UNOFFICIAL: The fact that we are executing means we aren't in the process of rebooting. */ *p_outvalue = 0; break; + case CONFIGITEM_NEEDS_SHUTDOWN: + /* UNOFFICIAL: The fact that we are executing means we aren't in the process of shutting down. */ + *p_outvalue = 0; + break; default: result = 2; break; diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h index 26b54c67f..4bf6f30c1 100644 --- a/exosphere/src/configitem.h +++ b/exosphere/src/configitem.h @@ -42,6 +42,7 @@ typedef enum { /* These are unofficial, for usage by Exosphere. */ CONFIGITEM_EXOSPHERE_VERSION = 65000, CONFIGITEM_NEEDS_REBOOT = 65001, + CONFIGITEM_NEEDS_SHUTDOWN = 65002, } ConfigItem; #define REBOOT_KIND_NO_REBOOT 0 diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp index 4860301e4..2bad23b3d 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_mitm_service.cpp @@ -25,8 +25,9 @@ void BpcMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ct } Result BpcMitmService::ShutdownSystem() { - /* TODO: Use exosphere + reboot to perform real shutdown, instead of fake shutdown. */ - return RESULT_FORWARD_TO_SESSION; + /* Use exosphere + reboot to perform real shutdown, instead of fake shutdown. */ + PerformShutdownSmc(); + return 0; } Result BpcMitmService::RebootSystem() { diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 3de9d6c9d..9ce1dce44 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 3de9d6c9d6ec91ac9f056c3683c19f50b6a7016d +Subproject commit 9ce1dce4400461311a17712628febd99b25ff335 From f5695145ef14e000b31f2e5f6cef783d16502f72 Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Thu, 21 Feb 2019 15:25:08 +0000 Subject: [PATCH 439/489] sept-secondary: Better meme compliance --- sept/sept-secondary/KEYS_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sept/sept-secondary/KEYS_template.py b/sept/sept-secondary/KEYS_template.py index a4a0ee971..be51e754f 100644 --- a/sept/sept-secondary/KEYS_template.py +++ b/sept/sept-secondary/KEYS_template.py @@ -1,7 +1,7 @@ HOVI_ENC_KEY_PRD = '00000000000000000000000000000000'.decode('hex') HOVI_ENC_KEY_DEV = '00000000000000000000000000000000'.decode('hex') +HOVI_ENC_KEY_IV1 = '00000000000000000000000000000000'.decode('hex') HOVI_SIG_KEY_PRD = '00000000000000000000000000000000'.decode('hex') HOVI_SIG_KEY_DEV = '00000000000000000000000000000000'.decode('hex') HOVI_KEK_KEY_PRD = '00000000000000000000000000000000'.decode('hex') HOVI_KEK_KEY_DEV = '00000000000000000000000000000000'.decode('hex') -IV = '00000000000000000000000000000000'.decode('hex') \ No newline at end of file From 4adf297c8055028fe6bdaffefa2af71e1465965c Mon Sep 17 00:00:00 2001 From: hexkyz <mike.hexkyz@gmail.com> Date: Thu, 21 Feb 2019 15:25:42 +0000 Subject: [PATCH 440/489] sept-secondary: Better meme compliance --- sept/sept-secondary/sept_sign.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py index ff49bea2d..64e97b220 100644 --- a/sept/sept-secondary/sept_sign.py +++ b/sept/sept-secondary/sept_sign.py @@ -61,8 +61,8 @@ def main(argc, argv): code += '\x00'*(0x10 - (len(code) & 0xF)) # TODO: Support dev unit crypto with open(argv[2], 'wb') as f: - f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, 'THANKS_NVIDIA_<3')) + f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.HOVI_ENC_KEY_IV1, 'THANKS_NVIDIA_<3')) return 0 if __name__ == '__main__': - sys.exit(main(len(sys.argv), sys.argv)) \ No newline at end of file + sys.exit(main(len(sys.argv), sys.argv)) From 83f21d7d2a5b01568dbf00a9b8ff572a76e5f1ac Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 07:40:04 -0800 Subject: [PATCH 441/489] exo: don't forget to dereference your pointers kids --- exosphere/rebootstub/src/start.s | 4 ++++ exosphere/src/configitem.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/exosphere/rebootstub/src/start.s b/exosphere/rebootstub/src/start.s index 461ba2099..e29bd0acc 100644 --- a/exosphere/rebootstub/src/start.s +++ b/exosphere/rebootstub/src/start.s @@ -19,9 +19,13 @@ .global _start _start: adr r0, reboot_type + ldr r0, [r0] cmp r0, #0x0 beq do_shutdown b jump_to_reboot_payload + nop + nop + nop reboot_type: .word 0x00000001 diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index 7029297d3..c0f1a262d 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -101,7 +101,7 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + i) = read32le(rebootstub_bin, i); } /* Tell rebootstub to shut down. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + 0x10) = 0x0; + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + 0x20) = 0x0; ams_unmap_irampage(); MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; From e9e3f29d746c7c8501f08fc608c67157ea88f362 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 07:41:58 -0800 Subject: [PATCH 442/489] sept-sign: uncorrect misguided meme correction --- sept/sept-secondary/KEYS_template.py | 2 +- sept/sept-secondary/sept_sign.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sept/sept-secondary/KEYS_template.py b/sept/sept-secondary/KEYS_template.py index be51e754f..0b3a4ad9a 100644 --- a/sept/sept-secondary/KEYS_template.py +++ b/sept/sept-secondary/KEYS_template.py @@ -1,7 +1,7 @@ HOVI_ENC_KEY_PRD = '00000000000000000000000000000000'.decode('hex') HOVI_ENC_KEY_DEV = '00000000000000000000000000000000'.decode('hex') -HOVI_ENC_KEY_IV1 = '00000000000000000000000000000000'.decode('hex') HOVI_SIG_KEY_PRD = '00000000000000000000000000000000'.decode('hex') HOVI_SIG_KEY_DEV = '00000000000000000000000000000000'.decode('hex') HOVI_KEK_KEY_PRD = '00000000000000000000000000000000'.decode('hex') HOVI_KEK_KEY_DEV = '00000000000000000000000000000000'.decode('hex') +IV = '00000000000000000000000000000000'.decode('hex') diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py index 64e97b220..17d515433 100644 --- a/sept/sept-secondary/sept_sign.py +++ b/sept/sept-secondary/sept_sign.py @@ -61,7 +61,7 @@ def main(argc, argv): code += '\x00'*(0x10 - (len(code) & 0xF)) # TODO: Support dev unit crypto with open(argv[2], 'wb') as f: - f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.HOVI_ENC_KEY_IV1, 'THANKS_NVIDIA_<3')) + f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, 'THANKS_NVIDIA_<3')) return 0 if __name__ == '__main__': From cfc9576eafe49bf2fa1dfc5e26097ca79143233e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 07:47:49 -0800 Subject: [PATCH 443/489] rebootstub: pc-relative load (thanks fincs) --- exosphere/rebootstub/src/start.s | 6 +----- exosphere/src/configitem.c | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/exosphere/rebootstub/src/start.s b/exosphere/rebootstub/src/start.s index e29bd0acc..3fce7d9f2 100644 --- a/exosphere/rebootstub/src/start.s +++ b/exosphere/rebootstub/src/start.s @@ -18,14 +18,10 @@ .align 4 .global _start _start: - adr r0, reboot_type - ldr r0, [r0] + ldr r0, reboot_type cmp r0, #0x0 beq do_shutdown b jump_to_reboot_payload - nop - nop - nop reboot_type: .word 0x00000001 diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c index c0f1a262d..7029297d3 100644 --- a/exosphere/src/configitem.c +++ b/exosphere/src/configitem.c @@ -101,7 +101,7 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) { MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + i) = read32le(rebootstub_bin, i); } /* Tell rebootstub to shut down. */ - MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + 0x20) = 0x0; + MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + 0x10) = 0x0; ams_unmap_irampage(); MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x400ull) = 0x10; From 2388a3f4fdcd807ff3857c962f828232c22a6f16 Mon Sep 17 00:00:00 2001 From: David Buchanan <d@vidbuchanan.co.uk> Date: Thu, 21 Feb 2019 15:52:42 +0000 Subject: [PATCH 444/489] sept_sign: Python 3 compat (#356) --- sept/sept-secondary/KEYS_template.py | 14 ++++----- sept/sept-secondary/sept_sign.py | 46 +++++++++++++++++----------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/sept/sept-secondary/KEYS_template.py b/sept/sept-secondary/KEYS_template.py index 0b3a4ad9a..38cdcb0c4 100644 --- a/sept/sept-secondary/KEYS_template.py +++ b/sept/sept-secondary/KEYS_template.py @@ -1,7 +1,7 @@ -HOVI_ENC_KEY_PRD = '00000000000000000000000000000000'.decode('hex') -HOVI_ENC_KEY_DEV = '00000000000000000000000000000000'.decode('hex') -HOVI_SIG_KEY_PRD = '00000000000000000000000000000000'.decode('hex') -HOVI_SIG_KEY_DEV = '00000000000000000000000000000000'.decode('hex') -HOVI_KEK_KEY_PRD = '00000000000000000000000000000000'.decode('hex') -HOVI_KEK_KEY_DEV = '00000000000000000000000000000000'.decode('hex') -IV = '00000000000000000000000000000000'.decode('hex') +HOVI_ENC_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') +HOVI_ENC_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000') +HOVI_SIG_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') +HOVI_SIG_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000') +HOVI_KEK_KEY_PRD = bytearray.fromhex('00000000000000000000000000000000') +HOVI_KEK_KEY_DEV = bytearray.fromhex('00000000000000000000000000000000') +IV = bytearray.fromhex('00000000000000000000000000000000') diff --git a/sept/sept-secondary/sept_sign.py b/sept/sept-secondary/sept_sign.py index 17d515433..a4dd83a87 100644 --- a/sept/sept-secondary/sept_sign.py +++ b/sept/sept-secondary/sept_sign.py @@ -9,48 +9,57 @@ except ImportError: import KEYS_template as KEYS print('Warning: output will not work on 7.0.0+!') + def shift_left_xor_rb(s): - N = int(s.encode('hex'), 16) + if hasattr(int, "from_bytes"): + N = int.from_bytes(s, byteorder="big") + else: + N = int(s.encode('hex'), 16) + if N & (1 << 127): N = ((N << 1) ^ 0x87) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF else: N = ((N << 1) ^ 0x00) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - return ('%032x' % N).decode('hex') + return bytearray.fromhex('%032x' % N) + def sxor(x, y): - return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(x, y)) - + return bytearray(a^b for a,b in zip(x, y)) + + def get_last_block_for_desired_mac(key, data, desired_mac): assert len(desired_mac) == 0x10 - k1 = shift_left_xor_rb(AES.new(key, AES.MODE_ECB).encrypt('\x00'*0x10)) + k1 = shift_left_xor_rb(AES.new(key, AES.MODE_ECB).encrypt(bytearray(0x10))) if len(data) & 0xF: k1 = shift_left_xor_rb(k1) - data += '\x80' - data += '\x00' * ((0x10 - (len(data) & 0xF)) & 0xF) + data += b'\x80' + data += bytearray((0x10 - (len(data) & 0xF)) & 0xF) num_blocks = (len(data) + 0xF) >> 4 - last_block = sxor(AES.new(key, AES.MODE_ECB).decrypt(desired_mac), k1) + last_block = sxor(bytearray(AES.new(key, AES.MODE_ECB).decrypt(desired_mac)), bytearray(k1)) if len(data) > 0x0: - last_block = sxor(last_block, AES.new(key, AES.MODE_CBC, '\x00'*0x10).encrypt(data)[-0x10:]) + last_block = sxor(last_block, bytearray(AES.new(key, AES.MODE_CBC, bytearray(0x10)).encrypt(data)[-0x10:])) return last_block + def sign_encrypt_code(code, sig_key, enc_key, iv, desired_mac): # Pad with 0x20 of zeroes. - code += '\x00' * 0x20 + code += bytearray(0x20) code_len = len(code) code_len += 0xFFF code_len &= ~0xFFF - code += '\x00' * (code_len - len(code)) - + code += bytearray(code_len - len(code)) + # Add empty trustzone, warmboot segments. - code += '\x00'* (0x1FE0 - 0x10) - pk11_hdr = 'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0) + code += bytearray(0x1FE0 - 0x10) + pk11_hdr = b'PK11' + pk('<IIIIIII', 0x1000, 0, 0, code_len - 0x20, 0, 0x1000, 0) pk11 = pk11_hdr + code enc_pk11 = AES.new(enc_key, AES.MODE_CBC, iv).encrypt(pk11) enc_pk11 = pk('<IIII', len(pk11) + 0x10, 0, 0, 0) + iv + enc_pk11 enc_pk11 += get_last_block_for_desired_mac(sig_key, enc_pk11, desired_mac) enc_pk11 += CMAC.new(sig_key, enc_pk11, AES).digest() return enc_pk11 - + + def main(argc, argv): if argc != 3: print('Usage: %s input output' % argv[0]) @@ -58,11 +67,12 @@ def main(argc, argv): with open(argv[1], 'rb') as f: code = f.read() if len(code) & 0xF: - code += '\x00'*(0x10 - (len(code) & 0xF)) + code += bytearray(0x10 - (len(code) & 0xF)) # TODO: Support dev unit crypto with open(argv[2], 'wb') as f: - f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, 'THANKS_NVIDIA_<3')) + f.write(sign_encrypt_code(code, KEYS.HOVI_SIG_KEY_PRD, KEYS.HOVI_ENC_KEY_PRD, KEYS.IV, b'THANKS_NVIDIA_<3')) return 0 - + + if __name__ == '__main__': sys.exit(main(len(sys.argv), sys.argv)) From 61b057c37d3642ba46661f9f262e428a051fa584 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 08:03:37 -0800 Subject: [PATCH 445/489] ams: write changelog for 0.8.4 a while before actual release. --- docs/changelog.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index cd4548e51..9373bfbc7 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,4 +1,17 @@ # Changelog +## 0.8.4 ++ Support for 7.0.0/7.0.1 was added. + + This is facilitated through a new payload, `sept`, which can be signed, encrypted, and then loaded by Nintendo's TSEC firmware. + + `sept` will derive the keys needed to boot new firmware, and then load `sept/payload.bin` off the SD card and jump to it. ++ Recognition of applications for override/mitm has been improved. + + Nintendo's official Title ID range (`0x0100000000000000`-`0x01FFFFFFFFFFFFFF`) is now enforced. ++ A deadlock condition was fixed involving libstratosphere mitm sysmodules. ++ `set.mitm` and `fs.mitm` were merged into a single `ams_mitm` sysmodule. + + This saves a process ID, allowing users to run one additional process up to the 0x40 process limit. ++ A `bpc.mitm` component was added, performing custom behavior on shutdown/reboot requests from `am` or applications. + + Performing a reboot from the reboot menu now reboots to atmosphere. This can be configured via `system_settings.ini`. + + Performing a shutdown from the reboot menu now works properly with AutoRCM, and does a real shutdown. ++ General system stability improvements to enhance the user's experience. ## 0.8.3 + A custom warmboot firmware was implemented, which does not perform anti-downgrade fuse checks. + This fixes sleep mode when using a downgraded NAND. From b63061a505b6abf58dc16fa50627564cb030f8ac Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 08:23:33 -0800 Subject: [PATCH 446/489] sept: prepare for reboot immediately --- sept/sept-secondary/src/main.c | 7 +++++-- sept/sept-secondary/src/utils.c | 7 ++++++- sept/sept-secondary/src/utils.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/sept/sept-secondary/src/main.c b/sept/sept-secondary/src/main.c index 08500c300..211ab3987 100644 --- a/sept/sept-secondary/src/main.c +++ b/sept/sept-secondary/src/main.c @@ -57,6 +57,10 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { uint8_t *dec_se_state = (uint8_t *)0x4003F000; if (!has_rebooted()) { + /* Prepare for a reboot before doing anything else. */ + prepare_for_reboot_to_self(); + set_has_rebooted(true); + /* Save the security engine context. */ se_get_regs()->_0x4 = 0x0; se_set_in_context_save_mode(true); @@ -67,8 +71,7 @@ static void exfiltrate_keys_and_reboot_if_needed(void) { for (size_t k = 0; k < 0x10; k++) { clear_aes_keyslot(k); } - - set_has_rebooted(true); + reboot_to_self(); } else { /* Decrypt the security engine state. */ diff --git a/sept/sept-secondary/src/utils.c b/sept/sept-secondary/src/utils.c index ac3d7b61f..4b95bf289 100644 --- a/sept/sept-secondary/src/utils.c +++ b/sept/sept-secondary/src/utils.c @@ -65,7 +65,7 @@ __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0) { } } -__attribute__((noreturn)) void reboot_to_self(void) { +void prepare_for_reboot_to_self(void) { /* Patch SDRAM init to perform an SVC immediately after second write */ APBDEV_PMC_SCRATCH45_0 = 0x2E38DFFF; APBDEV_PMC_SCRATCH46_0 = 0x6001DC28; @@ -77,6 +77,11 @@ __attribute__((noreturn)) void reboot_to_self(void) { for (size_t i = 0; i < rebootstub_bin_size; i += sizeof(uint32_t)) { write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i)); } +} + +__attribute__((noreturn)) void reboot_to_self(void) { + /* Prep IRAM for reboot. */ + prepare_for_reboot_to_self(); /* Trigger warm reboot. */ pmc_reboot(1 << 0); diff --git a/sept/sept-secondary/src/utils.h b/sept/sept-secondary/src/utils.h index 58e53bffe..ee16c6e40 100644 --- a/sept/sept-secondary/src/utils.h +++ b/sept/sept-secondary/src/utils.h @@ -121,6 +121,7 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase); __attribute__((noreturn)) void watchdog_reboot(void); __attribute__((noreturn)) void pmc_reboot(uint32_t scratch0); +void prepare_for_reboot_to_self(void); __attribute__((noreturn)) void reboot_to_self(void); __attribute__((noreturn)) void wait_for_button_and_reboot(void); From d646023bbd7b07a4586b6a2300995825cc4902a8 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 09:22:28 -0800 Subject: [PATCH 447/489] changelog: mention kernel patches --- docs/changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index 9373bfbc7..82466cd77 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -6,6 +6,8 @@ + Recognition of applications for override/mitm has been improved. + Nintendo's official Title ID range (`0x0100000000000000`-`0x01FFFFFFFFFFFFFF`) is now enforced. + A deadlock condition was fixed involving libstratosphere mitm sysmodules. ++ Kernel patches for JIT support were added (Thanks, @m4xw!). + + These loosen restrictions on caller process in svcControlCodeMemory. + `set.mitm` and `fs.mitm` were merged into a single `ams_mitm` sysmodule. + This saves a process ID, allowing users to run one additional process up to the 0x40 process limit. + A `bpc.mitm` component was added, performing custom behavior on shutdown/reboot requests from `am` or applications. From 37161c5d11931c73cf2e28a2788ee41c183fd9e3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Thu, 21 Feb 2019 11:54:07 -0800 Subject: [PATCH 448/489] ams: bump version to 0.8.4 --- common/include/atmosphere/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 2396eb595..6cc2ca10d 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -19,6 +19,6 @@ #define ATMOSPHERE_RELEASE_VERSION_MAJOR 0 #define ATMOSPHERE_RELEASE_VERSION_MINOR 8 -#define ATMOSPHERE_RELEASE_VERSION_MICRO 3 +#define ATMOSPHERE_RELEASE_VERSION_MICRO 4 #endif \ No newline at end of file From 1970a52fc9c82bb37b41e36af236f950a3579872 Mon Sep 17 00:00:00 2001 From: thedax <thedax@users.noreply.github.com> Date: Thu, 21 Feb 2019 21:26:41 -0500 Subject: [PATCH 449/489] Allow the user to build with a prebuilt sept-secondary blob via a SEPT_ENC_PATH variable. (#365) --- sept/sept-secondary/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sept/sept-secondary/Makefile b/sept/sept-secondary/Makefile index b09d2359d..e5361512d 100644 --- a/sept/sept-secondary/Makefile +++ b/sept/sept-secondary/Makefile @@ -120,8 +120,12 @@ check_rebootstub: @$(MAKE) -C $(AMS)/exosphere/rebootstub all $(BUILD): +ifeq ($(strip $(SEPT_ENC_PATH)),) @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile +else + @cp $(SEPT_ENC_PATH) $(TOPDIR)/sept-secondary.enc +endif #--------------------------------------------------------------------------------- clean: From dcf44e406e34bad30c3768d8c2732aea7af4437e Mon Sep 17 00:00:00 2001 From: Pedro Diaz <igoticecream@gmail.com> Date: Sat, 23 Feb 2019 03:57:27 +0100 Subject: [PATCH 450/489] Fix sept-secondary build when using prebuild sept-secondary.enc (#371) --- sept/sept-secondary/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/sept/sept-secondary/Makefile b/sept/sept-secondary/Makefile index e5361512d..5c04ee70c 100644 --- a/sept/sept-secondary/Makefile +++ b/sept/sept-secondary/Makefile @@ -124,6 +124,7 @@ ifeq ($(strip $(SEPT_ENC_PATH)),) @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile else + @touch $(TOPDIR)/sept-secondary.bin @cp $(SEPT_ENC_PATH) $(TOPDIR)/sept-secondary.enc endif From eefee8c7a8e6177b84cb015e4088a469d7d8efb9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 23 Feb 2019 07:17:33 -0800 Subject: [PATCH 451/489] loader: add support for title-specific override keys --- common/defaults/loader.ini | 9 +- .../loader/source/ldr_content_management.cpp | 212 ++++++++++++------ .../loader/source/ldr_content_management.hpp | 10 +- stratosphere/loader/source/ldr_npdm.cpp | 18 +- stratosphere/loader/source/ldr_nso.cpp | 13 +- 5 files changed, 181 insertions(+), 81 deletions(-) diff --git a/common/defaults/loader.ini b/common/defaults/loader.ini index 1049ef9dd..ac56e2b9b 100644 --- a/common/defaults/loader.ini +++ b/common/defaults/loader.ini @@ -1,4 +1,7 @@ -[config] -hbl_tid=010000000000100D -hbl_path=atmosphere/hbl.nsp +[hbl_config] +title_id=010000000000100D +path=atmosphere/hbl.nsp +override_key=!R + +[default_config] override_key=!R \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index b5fbbb491..346846714 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -38,10 +38,26 @@ static bool g_has_initialized_fs_dev = false; /* Default to Key R, hold disables override, HBL at atmosphere/hbl.nsp. */ static bool g_mounted_hbl_nsp = false; static char g_hbl_sd_path[FS_MAX_PATH+1] = "@Sdcard:/atmosphere/hbl.nsp\x00"; -static u64 g_override_key_combination = KEY_R; -static bool g_override_by_default = true; -static u64 g_override_hbl_tid = 0x010000000000100D; -static bool g_override_any_app = false; + +static OverrideKey g_default_override_key = { + .key_combination = KEY_R, + .override_by_default = true +}; + +struct HblOverrideConfig { + OverrideKey override_key; + u64 title_id; + bool override_any_app; +}; + +static HblOverrideConfig g_hbl_override_config = { + .override_key = { + .key_combination = KEY_R, + .override_by_default = true + }, + .title_id = 0x010000000000100D, + .override_any_app = false +}; /* Static buffer for loader.ini contents at runtime. */ static char g_config_ini_data[0x800]; @@ -62,7 +78,7 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { RefreshConfigurationData(); } - if (ShouldOverrideContents(tid) && R_SUCCEEDED(MountCodeNspOnSd(tid))) { + if (ShouldOverrideContentsWithSD(tid) && R_SUCCEEDED(MountCodeNspOnSd(tid))) { return 0x0; } @@ -204,72 +220,100 @@ void ContentManagement::SetCreatedTitle(u64 tid) { } } +static OverrideKey ParseOverrideKey(const char *value) { + OverrideKey cfg; + + /* Parse on by default. */ + if (value[0] == '!') { + cfg.override_by_default = true; + value++; + } else { + cfg.override_by_default = false; + } + + /* Parse key combination. */ + if (strcasecmp(value, "A") == 0) { + cfg.key_combination = KEY_A; + } else if (strcasecmp(value, "B") == 0) { + cfg.key_combination = KEY_B; + } else if (strcasecmp(value, "X") == 0) { + cfg.key_combination = KEY_X; + } else if (strcasecmp(value, "Y") == 0) { + cfg.key_combination = KEY_Y; + } else if (strcasecmp(value, "LS") == 0) { + cfg.key_combination = KEY_LSTICK; + } else if (strcasecmp(value, "RS") == 0) { + cfg.key_combination = KEY_RSTICK; + } else if (strcasecmp(value, "L") == 0) { + cfg.key_combination = KEY_L; + } else if (strcasecmp(value, "R") == 0) { + cfg.key_combination = KEY_R; + } else if (strcasecmp(value, "ZL") == 0) { + cfg.key_combination = KEY_ZL; + } else if (strcasecmp(value, "ZR") == 0) { + cfg.key_combination = KEY_ZR; + } else if (strcasecmp(value, "PLUS") == 0) { + cfg.key_combination = KEY_PLUS; + } else if (strcasecmp(value, "MINUS") == 0) { + cfg.key_combination = KEY_MINUS; + } else if (strcasecmp(value, "DLEFT") == 0) { + cfg.key_combination = KEY_DLEFT; + } else if (strcasecmp(value, "DUP") == 0) { + cfg.key_combination = KEY_DUP; + } else if (strcasecmp(value, "DRIGHT") == 0) { + cfg.key_combination = KEY_DRIGHT; + } else if (strcasecmp(value, "DDOWN") == 0) { + cfg.key_combination = KEY_DDOWN; + } else if (strcasecmp(value, "SL") == 0) { + cfg.key_combination = KEY_SL; + } else if (strcasecmp(value, "SR") == 0) { + cfg.key_combination = KEY_SR; + } else { + cfg.key_combination = 0; + } + + return cfg; +} + static int LoaderIniHandler(void *user, const char *section, const char *name, const char *value) { /* Taken and modified, with love, from Rajkosto's implementation. */ - if (strcasecmp(section, "config") == 0) { - if (strcasecmp(name, "hbl_tid") == 0) { + if (strcasecmp(section, "hbl_config") == 0) { + if (strcasecmp(name, "title_id") == 0) { if (strcasecmp(value, "app") == 0) { - g_override_any_app = true; + g_hbl_override_config.override_any_app = true; } else { u64 override_tid = strtoul(value, NULL, 16); if (override_tid != 0) { - g_override_hbl_tid = override_tid; + g_hbl_override_config.title_id = override_tid; } } - } else if (strcasecmp(name, "hbl_path") == 0) { + } else if (strcasecmp(name, "path") == 0) { while (*value == '/' || *value == '\\') { value++; } snprintf(g_hbl_sd_path, FS_MAX_PATH, "@Sdcard:/%s", value); g_hbl_sd_path[FS_MAX_PATH] = 0; } else if (strcasecmp(name, "override_key") == 0) { - if (value[0] == '!') { - g_override_by_default = true; - value++; - } else { - g_override_by_default = false; - } - - if (strcasecmp(value, "A") == 0) { - g_override_key_combination = KEY_A; - } else if (strcasecmp(value, "B") == 0) { - g_override_key_combination = KEY_B; - } else if (strcasecmp(value, "X") == 0) { - g_override_key_combination = KEY_X; - } else if (strcasecmp(value, "Y") == 0) { - g_override_key_combination = KEY_Y; - } else if (strcasecmp(value, "LS") == 0) { - g_override_key_combination = KEY_LSTICK; - } else if (strcasecmp(value, "RS") == 0) { - g_override_key_combination = KEY_RSTICK; - } else if (strcasecmp(value, "L") == 0) { - g_override_key_combination = KEY_L; - } else if (strcasecmp(value, "R") == 0) { - g_override_key_combination = KEY_R; - } else if (strcasecmp(value, "ZL") == 0) { - g_override_key_combination = KEY_ZL; - } else if (strcasecmp(value, "ZR") == 0) { - g_override_key_combination = KEY_ZR; - } else if (strcasecmp(value, "PLUS") == 0) { - g_override_key_combination = KEY_PLUS; - } else if (strcasecmp(value, "MINUS") == 0) { - g_override_key_combination = KEY_MINUS; - } else if (strcasecmp(value, "DLEFT") == 0) { - g_override_key_combination = KEY_DLEFT; - } else if (strcasecmp(value, "DUP") == 0) { - g_override_key_combination = KEY_DUP; - } else if (strcasecmp(value, "DRIGHT") == 0) { - g_override_key_combination = KEY_DRIGHT; - } else if (strcasecmp(value, "DDOWN") == 0) { - g_override_key_combination = KEY_DDOWN; - } else if (strcasecmp(value, "SL") == 0) { - g_override_key_combination = KEY_SL; - } else if (strcasecmp(value, "SR") == 0) { - g_override_key_combination = KEY_SR; - } else { - g_override_key_combination = 0; - } + g_hbl_override_config.override_key = ParseOverrideKey(value); + } + } else if (strcasecmp(section, "default_config") == 0) { + if (strcasecmp(name, "override_key") == 0) { + g_default_override_key = ParseOverrideKey(value); + } + } else { + return 0; + } + return 1; +} + +static int LoaderTitleSpecificIniHandler(void *user, const char *section, const char *name, const char *value) { + /* We'll output an override key when relevant. */ + OverrideKey *user_cfg = reinterpret_cast<OverrideKey *>(user); + + if (strcasecmp(section, "override_config") == 0) { + if (strcasecmp(name, "override_key") == 0) { + *user_cfg = ParseOverrideKey(value); } } else { return 0; @@ -309,18 +353,56 @@ void ContentManagement::TryMountSdCard() { } } -bool ContentManagement::ShouldReplaceWithHBL(u64 tid) { - return g_mounted_hbl_nsp && ((g_override_any_app && IsApplicationTid(tid)) || (!g_override_any_app && tid == g_override_hbl_tid)); +static bool IsHBLTitleId(u64 tid) { + return ((g_hbl_override_config.override_any_app && IsApplicationTid(tid)) || (!g_hbl_override_config.override_any_app && tid == g_hbl_override_config.title_id)); } -bool ContentManagement::ShouldOverrideContents(u64 tid) { - if (tid >= 0x0100000000001000 && HasCreatedTitle(0x0100000000001000)) { - u64 kDown = 0; - bool keys_triggered = (R_SUCCEEDED(HidManagement::GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0)); - return g_has_initialized_fs_dev && (g_override_by_default ^ keys_triggered); +OverrideKey ContentManagement::GetTitleOverrideKey(u64 tid) { + OverrideKey cfg = g_default_override_key; + char path[FS_MAX_PATH+1] = {0}; + snprintf(path, FS_MAX_PATH, "sdmc:/atmosphere/titles/%016lx/config.ini", tid); + + + FILE *config = fopen(path, "r"); + if (config != NULL) { + ON_SCOPE_EXIT { fclose(config); }; + + /* Parse current title ini. */ + ini_parse_file(config, LoaderTitleSpecificIniHandler, &cfg); + } + + return cfg; +} + +static bool ShouldOverrideContents(OverrideKey *cfg) { + u64 kDown = 0; + bool keys_triggered = (R_SUCCEEDED(HidManagement::GetKeysDown(&kDown)) && ((kDown & cfg->key_combination) != 0)); + return g_has_initialized_fs_dev && (cfg->override_by_default ^ keys_triggered); +} + +bool ContentManagement::ShouldOverrideContentsWithHBL(u64 tid) { + if (g_mounted_hbl_nsp && tid >= 0x0100000000001000 && HasCreatedTitle(0x0100000000001000)) { + /* Return whether we should override contents with HBL. */ + return IsHBLTitleId(tid) && ShouldOverrideContents(&g_hbl_override_config.override_key); } else { - /* Always redirect before qlaunch. */ - return g_has_initialized_fs_dev; + /* Don't override if we failed to mount HBL or haven't launched qlaunch. */ + return false; + } +} + +bool ContentManagement::ShouldOverrideContentsWithSD(u64 tid) { + if (g_has_initialized_fs_dev) { + if (tid >= 0x0100000000001000 && HasCreatedTitle(0x0100000000001000)) { + /* Check whether we should override with non-HBL. */ + OverrideKey title_cfg = GetTitleOverrideKey(tid); + return ShouldOverrideContents(&title_cfg); + } else { + /* Always redirect before qlaunch. */ + return true; + } + } else { + /* Never redirect before we can do so. */ + return false; } } diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index a9974530a..60b01d7e2 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -19,6 +19,11 @@ #include "ldr_registration.hpp" +struct OverrideKey { + u64 key_combination; + bool override_by_default; +}; + class ContentManagement { public: static Result MountCode(u64 tid, FsStorageId sid); @@ -37,8 +42,9 @@ class ContentManagement { static void RefreshConfigurationData(); static void TryMountSdCard(); - static bool ShouldReplaceWithHBL(u64 tid); - static bool ShouldOverrideContents(u64 tid); + static OverrideKey GetTitleOverrideKey(u64 tid); + static bool ShouldOverrideContentsWithSD(u64 tid); + static bool ShouldOverrideContentsWithHBL(u64 tid); /* SetExternalContentSource extension */ class ExternalContentSource { diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index 7eb114cfc..d7ec3a517 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -63,16 +63,21 @@ FILE *NpdmUtils::OpenNpdm(u64 title_id) { if ((ecs = ContentManagement::GetExternalContentSource(title_id)) != nullptr) { return OpenNpdmFromECS(ecs); } - - if (ContentManagement::ShouldOverrideContents(title_id)) { - if (ContentManagement::ShouldReplaceWithHBL(title_id)) { - return OpenNpdmFromHBL(); - } + + /* First, check HBL. */ + if (ContentManagement::ShouldOverrideContentsWithHBL(title_id)) { + return OpenNpdmFromHBL(); + } + + /* Next, check other override. */ + if (ContentManagement::ShouldOverrideContentsWithSD(title_id)) { FILE *f_out = OpenNpdmFromSdCard(title_id); if (f_out != NULL) { return f_out; } } + + /* Last resort: real exefs. */ return OpenNpdmFromExeFS(); } @@ -193,8 +198,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { info->acid->title_id_range_max = tid; info->aci0->title_id = tid; - if (ContentManagement::ShouldOverrideContents(tid) && ContentManagement::ShouldReplaceWithHBL(tid) - && R_SUCCEEDED(LoadNpdmInternal(OpenNpdmFromExeFS(), &g_original_npdm_cache))) { + if (ContentManagement::ShouldOverrideContentsWithHBL(tid) && R_SUCCEEDED(LoadNpdmInternal(OpenNpdmFromExeFS(), &g_original_npdm_cache))) { NpdmInfo *original_info = &g_original_npdm_cache.info; /* Fix pool partition. */ if (kernelAbove500()) { diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index bdc65eb3d..61502a7b2 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -71,11 +71,14 @@ FILE *NsoUtils::OpenNso(unsigned int index, u64 title_id) { if ((ecs = ContentManagement::GetExternalContentSource(title_id)) != nullptr) { return OpenNsoFromECS(index, ecs); } + + /* First, check HBL. */ + if (ContentManagement::ShouldOverrideContentsWithHBL(title_id)) { + return OpenNsoFromHBL(index); + } - if (ContentManagement::ShouldOverrideContents(title_id)) { - if (ContentManagement::ShouldReplaceWithHBL(title_id)) { - return OpenNsoFromHBL(index); - } + /* Next, check secondary override. */ + if (ContentManagement::ShouldOverrideContentsWithSD(title_id)) { FILE *f_out = OpenNsoFromSdCard(index, title_id); if (f_out != NULL) { return f_out; @@ -83,6 +86,8 @@ FILE *NsoUtils::OpenNso(unsigned int index, u64 title_id) { return NULL; } } + + /* Finally, default to exefs. */ return OpenNsoFromExeFS(index); } From 6cc69fb3fc06726afca45888b3c82b1784f89669 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 23 Feb 2019 07:39:40 -0800 Subject: [PATCH 452/489] fs.mitm: Add title-specific override key support. --- stratosphere/ams_mitm/source/utils.cpp | 200 +++++++++++++++++-------- stratosphere/ams_mitm/source/utils.hpp | 7 + 2 files changed, 147 insertions(+), 60 deletions(-) diff --git a/stratosphere/ams_mitm/source/utils.cpp b/stratosphere/ams_mitm/source/utils.cpp index 637113fdc..e25b09408 100644 --- a/stratosphere/ams_mitm/source/utils.cpp +++ b/stratosphere/ams_mitm/source/utils.cpp @@ -35,10 +35,26 @@ static std::vector<u64> g_disable_mitm_flagged_tids; static std::atomic_bool g_has_initialized = false; static std::atomic_bool g_has_hid_session = false; -static u64 g_override_key_combination = KEY_R; -static u64 g_override_hbl_tid = 0x010000000000100DULL; -static bool g_override_any_app = false; -static bool g_override_by_default = true; +/* Content override support variables/types */ +static OverrideKey g_default_override_key = { + .key_combination = KEY_R, + .override_by_default = true +}; + +struct HblOverrideConfig { + OverrideKey override_key; + u64 title_id; + bool override_any_app; +}; + +static HblOverrideConfig g_hbl_override_config = { + .override_key = { + .key_combination = KEY_R, + .override_by_default = true + }, + .title_id = 0x010000000000100D, + .override_any_app = false +}; /* Static buffer for loader.ini contents at runtime. */ static char g_config_ini_data[0x800]; @@ -368,7 +384,7 @@ Result Utils::SaveSdFileForAtmosphere(u64 title_id, const char *fn, void *data, } bool Utils::IsHblTid(u64 tid) { - return (g_override_any_app && IsApplicationTid(tid)) || (!g_override_any_app && tid == g_override_hbl_tid); + return (g_hbl_override_config.override_any_app && IsApplicationTid(tid)) || (!g_hbl_override_config.override_any_app && tid == g_hbl_override_config.title_id); } bool Utils::HasTitleFlag(u64 tid, const char *flag) { @@ -446,6 +462,13 @@ Result Utils::GetKeysDown(u64 *keys) { return 0x0; } +static bool HasOverrideKey(OverrideKey *cfg) { + u64 kDown = 0; + bool keys_triggered = (R_SUCCEEDED(Utils::GetKeysDown(&kDown)) && ((kDown & cfg->key_combination) != 0)); + return Utils::IsSdInitialized() && (cfg->override_by_default ^ keys_triggered); +} + + bool Utils::HasOverrideButton(u64 tid) { if ((!IsApplicationTid(tid)) || (!IsSdInitialized())) { /* Disable button override disable for non-applications. */ @@ -455,71 +478,88 @@ bool Utils::HasOverrideButton(u64 tid) { /* Unconditionally refresh loader.ini contents. */ RefreshConfiguration(); - u64 kDown = 0; - bool keys_triggered = (R_SUCCEEDED(GetKeysDown(&kDown)) && ((kDown & g_override_key_combination) != 0)); - return IsSdInitialized() && (g_override_by_default ^ keys_triggered); + if (IsHblTid(tid) && HasOverrideKey(&g_hbl_override_config.override_key)) { + return true; + } + + OverrideKey title_cfg = GetTitleOverrideKey(tid); + return HasOverrideKey(&title_cfg); } -static int FsMitMIniHandler(void *user, const char *section, const char *name, const char *value) { +static OverrideKey ParseOverrideKey(const char *value) { + OverrideKey cfg; + + /* Parse on by default. */ + if (value[0] == '!') { + cfg.override_by_default = true; + value++; + } else { + cfg.override_by_default = false; + } + + /* Parse key combination. */ + if (strcasecmp(value, "A") == 0) { + cfg.key_combination = KEY_A; + } else if (strcasecmp(value, "B") == 0) { + cfg.key_combination = KEY_B; + } else if (strcasecmp(value, "X") == 0) { + cfg.key_combination = KEY_X; + } else if (strcasecmp(value, "Y") == 0) { + cfg.key_combination = KEY_Y; + } else if (strcasecmp(value, "LS") == 0) { + cfg.key_combination = KEY_LSTICK; + } else if (strcasecmp(value, "RS") == 0) { + cfg.key_combination = KEY_RSTICK; + } else if (strcasecmp(value, "L") == 0) { + cfg.key_combination = KEY_L; + } else if (strcasecmp(value, "R") == 0) { + cfg.key_combination = KEY_R; + } else if (strcasecmp(value, "ZL") == 0) { + cfg.key_combination = KEY_ZL; + } else if (strcasecmp(value, "ZR") == 0) { + cfg.key_combination = KEY_ZR; + } else if (strcasecmp(value, "PLUS") == 0) { + cfg.key_combination = KEY_PLUS; + } else if (strcasecmp(value, "MINUS") == 0) { + cfg.key_combination = KEY_MINUS; + } else if (strcasecmp(value, "DLEFT") == 0) { + cfg.key_combination = KEY_DLEFT; + } else if (strcasecmp(value, "DUP") == 0) { + cfg.key_combination = KEY_DUP; + } else if (strcasecmp(value, "DRIGHT") == 0) { + cfg.key_combination = KEY_DRIGHT; + } else if (strcasecmp(value, "DDOWN") == 0) { + cfg.key_combination = KEY_DDOWN; + } else if (strcasecmp(value, "SL") == 0) { + cfg.key_combination = KEY_SL; + } else if (strcasecmp(value, "SR") == 0) { + cfg.key_combination = KEY_SR; + } else { + cfg.key_combination = 0; + } + + return cfg; +} + +static int FsMitmIniHandler(void *user, const char *section, const char *name, const char *value) { /* Taken and modified, with love, from Rajkosto's implementation. */ - if (strcasecmp(section, "config") == 0) { - if (strcasecmp(name, "hbl_tid") == 0) { + if (strcasecmp(section, "hbl_config") == 0) { + if (strcasecmp(name, "title_id") == 0) { if (strcasecmp(value, "app") == 0) { - g_override_any_app = true; + g_hbl_override_config.override_any_app = true; } else { u64 override_tid = strtoul(value, NULL, 16); if (override_tid != 0) { - g_override_hbl_tid = override_tid; + g_hbl_override_config.title_id = override_tid; } } } else if (strcasecmp(name, "override_key") == 0) { - if (value[0] == '!') { - g_override_by_default = true; - value++; - } else { - g_override_by_default = false; - } - - if (strcasecmp(value, "A") == 0) { - g_override_key_combination = KEY_A; - } else if (strcasecmp(value, "B") == 0) { - g_override_key_combination = KEY_B; - } else if (strcasecmp(value, "X") == 0) { - g_override_key_combination = KEY_X; - } else if (strcasecmp(value, "Y") == 0) { - g_override_key_combination = KEY_Y; - } else if (strcasecmp(value, "LS") == 0) { - g_override_key_combination = KEY_LSTICK; - } else if (strcasecmp(value, "RS") == 0) { - g_override_key_combination = KEY_RSTICK; - } else if (strcasecmp(value, "L") == 0) { - g_override_key_combination = KEY_L; - } else if (strcasecmp(value, "R") == 0) { - g_override_key_combination = KEY_R; - } else if (strcasecmp(value, "ZL") == 0) { - g_override_key_combination = KEY_ZL; - } else if (strcasecmp(value, "ZR") == 0) { - g_override_key_combination = KEY_ZR; - } else if (strcasecmp(value, "PLUS") == 0) { - g_override_key_combination = KEY_PLUS; - } else if (strcasecmp(value, "MINUS") == 0) { - g_override_key_combination = KEY_MINUS; - } else if (strcasecmp(value, "DLEFT") == 0) { - g_override_key_combination = KEY_DLEFT; - } else if (strcasecmp(value, "DUP") == 0) { - g_override_key_combination = KEY_DUP; - } else if (strcasecmp(value, "DRIGHT") == 0) { - g_override_key_combination = KEY_DRIGHT; - } else if (strcasecmp(value, "DDOWN") == 0) { - g_override_key_combination = KEY_DDOWN; - } else if (strcasecmp(value, "SL") == 0) { - g_override_key_combination = KEY_SL; - } else if (strcasecmp(value, "SR") == 0) { - g_override_key_combination = KEY_SR; - } else { - g_override_key_combination = 0; - } + g_hbl_override_config.override_key = ParseOverrideKey(value); + } + } else if (strcasecmp(section, "default_config") == 0) { + if (strcasecmp(name, "override_key") == 0) { + g_default_override_key = ParseOverrideKey(value); } } else { return 0; @@ -527,6 +567,46 @@ static int FsMitMIniHandler(void *user, const char *section, const char *name, c return 1; } +static int FsMitmTitleSpecificIniHandler(void *user, const char *section, const char *name, const char *value) { + /* We'll output an override key when relevant. */ + OverrideKey *user_cfg = reinterpret_cast<OverrideKey *>(user); + + if (strcasecmp(section, "override_config") == 0) { + if (strcasecmp(name, "override_key") == 0) { + *user_cfg = ParseOverrideKey(value); + } + } else { + return 0; + } + return 1; +} + +OverrideKey Utils::GetTitleOverrideKey(u64 tid) { + OverrideKey cfg = g_default_override_key; + char path[FS_MAX_PATH+1] = {0}; + snprintf(path, FS_MAX_PATH, "/atmosphere/titles/%016lx/config.ini", tid); + FsFile cfg_file; + + if (fsFsOpenFile(&g_sd_filesystem, path, FS_OPEN_READ, &cfg_file)) { + ON_SCOPE_EXIT { fsFileClose(&cfg_file); }; + + size_t config_file_size = 0x20000; + fsFileGetSize(&cfg_file, &config_file_size); + + char *config_buf = reinterpret_cast<char *>(calloc(1, config_file_size)); + if (config_buf != NULL) { + ON_SCOPE_EXIT { free(config_buf); }; + + /* Read title ini contents. */ + fsFileRead(&cfg_file, 0, config_buf, config_file_size, &config_file_size); + + /* Parse title ini. */ + ini_parse_string(config_buf, FsMitmTitleSpecificIniHandler, &cfg); + } + } + + return cfg; +} void Utils::RefreshConfiguration() { FsFile config_file; @@ -547,7 +627,7 @@ void Utils::RefreshConfiguration() { fsFileRead(&config_file, 0, g_config_ini_data, size, &r_s); fsFileClose(&config_file); - ini_parse_string(g_config_ini_data, FsMitMIniHandler, NULL); + ini_parse_string(g_config_ini_data, FsMitmIniHandler, NULL); } Result Utils::GetSettingsItemValueSize(const char *name, const char *key, u64 *out_size) { diff --git a/stratosphere/ams_mitm/source/utils.hpp b/stratosphere/ams_mitm/source/utils.hpp index 2c15ec13e..db9e84f6a 100644 --- a/stratosphere/ams_mitm/source/utils.hpp +++ b/stratosphere/ams_mitm/source/utils.hpp @@ -37,6 +37,11 @@ enum BisStorageId : u32 { BisStorageId_SystemProperPartition = 33, }; +struct OverrideKey { + u64 key_combination; + bool override_by_default; +}; + class Utils { public: static bool IsSdInitialized(); @@ -72,6 +77,8 @@ class Utils { static bool IsHidAvailable(); static Result GetKeysDown(u64 *keys); + + static OverrideKey GetTitleOverrideKey(u64 tid); static bool HasOverrideButton(u64 tid); /* Settings! */ From 26731184786d48872876e8b77ec0db8abf1ebc82 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 23 Feb 2019 07:43:12 -0800 Subject: [PATCH 453/489] update loader doc --- docs/modules/loader.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/modules/loader.md b/docs/modules/loader.md index ca388178c..666ad86b5 100644 --- a/docs/modules/loader.md +++ b/docs/modules/loader.md @@ -55,7 +55,7 @@ When authoring patches, [hactool](https://github.com/SciresM/hactool) can be use Atmosphère can use the loader module in order to turn any game on your Switch's home menu into a launchpoint for the Homebrew Menu, rather than launching it through the album applet. This allows one to launch the Homebrew Menu with access to the ~3.2GB of RAM that the Switch reserves for games and applications, as opposed to the 442MB of RAM we are limited to when launching the Homebrew Menu from the album. This also means that it is no longer necessary to install homebrew as `.nsp` files on your Switch so long as you are using this method, as the only reason to do so is to allow the homebrew to access all of the Switch's available memory. -In order to setup this method you will need the latest release of [hbmenu](https://github.com/switchbrew/nx-hbmenu/releases), and the latest release of [hbloader](https://github.com/switchbrew/nx-hbloader/releases). Place `hbmenu.nro` on the root of your Switch's SD Card, and place `hbl.nsp` in the atmosphere folder. From there, simply configure `loader.ini` in the atmosphere folder by replacing the Title ID in the ini (hbl_tid) (it is the Title ID for the album by default) with the Title ID of whatever game you wish to use to launch the Homebrew Menu. A list of Title IDs for Switch Games can be found [here](https://switchbrew.org/wiki/Title_list/Games). Afterwards you may reinsert your SD Card into your Switch and boot into Atmosphère as you normally would. You should now be able to boot into the Homebrew Menu by launching your designated game of choice. +In order to setup this method you will need the latest release of [hbmenu](https://github.com/switchbrew/nx-hbmenu/releases), and the latest release of [hbloader](https://github.com/switchbrew/nx-hbloader/releases). Place `hbmenu.nro` on the root of your Switch's SD Card, and place `hbl.nsp` in the atmosphere folder. From there, simply configure `loader.ini` in the atmosphere folder by replacing the Title ID in the ini (title_id in the [hbl_config] section) (it is the Title ID for the album by default) with the Title ID of whatever game you wish to use to launch the Homebrew Menu. A list of Title IDs for Switch Games can be found [here](https://switchbrew.org/wiki/Title_list/Games). Afterwards you may reinsert your SD Card into your Switch and boot into Atmosphère as you normally would. You should now be able to boot into the Homebrew Menu by launching your designated game of choice. ### Button Overrides From 618de9546a1eb94d9f313504a44a87053c12734f Mon Sep 17 00:00:00 2001 From: thedax <thedax@users.noreply.github.com> Date: Sat, 23 Feb 2019 20:16:37 -0500 Subject: [PATCH 454/489] Makefile tweaks. (#376) -Have fusee-secondary clean sept-secondary as required. -Use $(TARGET) variable for sept-secondary, and clean the encrypted output as required. --- fusee/fusee-secondary/Makefile | 1 + sept/sept-secondary/Makefile | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 7273cc10d..7552e8e42 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -159,6 +159,7 @@ clean: @$(MAKE) -C $(AMS)/exosphere clean @$(MAKE) -C $(AMS)/thermosphere clean @$(MAKE) -C $(AMS)/stratosphere clean + @$(MAKE) -C $(AMS)/sept clean @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf #--------------------------------------------------------------------------------- diff --git a/sept/sept-secondary/Makefile b/sept/sept-secondary/Makefile index 5c04ee70c..1628eb4f7 100644 --- a/sept/sept-secondary/Makefile +++ b/sept/sept-secondary/Makefile @@ -124,15 +124,15 @@ ifeq ($(strip $(SEPT_ENC_PATH)),) @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile else - @touch $(TOPDIR)/sept-secondary.bin - @cp $(SEPT_ENC_PATH) $(TOPDIR)/sept-secondary.enc + @touch $(TOPDIR)/$(TARGET).bin + @cp $(SEPT_ENC_PATH) $(TOPDIR)/$(TARGET).enc endif #--------------------------------------------------------------------------------- clean: @echo clean ... @$(MAKE) -C $(AMS)/exosphere/rebootstub clean - @rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf + @rm -fr $(BUILD) $(TARGET).bin $(TARGET).enc $(TARGET).elf #--------------------------------------------------------------------------------- From a8d929a343c9173ef7ee56c1b19d38aca15a6f1b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 23 Feb 2019 22:11:38 -0800 Subject: [PATCH 455/489] fs.mitm: fix inverted conditional --- stratosphere/ams_mitm/source/utils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stratosphere/ams_mitm/source/utils.cpp b/stratosphere/ams_mitm/source/utils.cpp index e25b09408..916bf9bf1 100644 --- a/stratosphere/ams_mitm/source/utils.cpp +++ b/stratosphere/ams_mitm/source/utils.cpp @@ -587,13 +587,13 @@ OverrideKey Utils::GetTitleOverrideKey(u64 tid) { snprintf(path, FS_MAX_PATH, "/atmosphere/titles/%016lx/config.ini", tid); FsFile cfg_file; - if (fsFsOpenFile(&g_sd_filesystem, path, FS_OPEN_READ, &cfg_file)) { + if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, path, FS_OPEN_READ, &cfg_file))) { ON_SCOPE_EXIT { fsFileClose(&cfg_file); }; size_t config_file_size = 0x20000; fsFileGetSize(&cfg_file, &config_file_size); - char *config_buf = reinterpret_cast<char *>(calloc(1, config_file_size)); + char *config_buf = reinterpret_cast<char *>(calloc(1, config_file_size + 1)); if (config_buf != NULL) { ON_SCOPE_EXIT { free(config_buf); }; From c8e002887465ac09b3d69723f9016542291d0fdb Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sat, 23 Feb 2019 22:14:38 -0800 Subject: [PATCH 456/489] Make default override key !L --- common/defaults/loader.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/defaults/loader.ini b/common/defaults/loader.ini index ac56e2b9b..a1df9025b 100644 --- a/common/defaults/loader.ini +++ b/common/defaults/loader.ini @@ -4,4 +4,4 @@ path=atmosphere/hbl.nsp override_key=!R [default_config] -override_key=!R \ No newline at end of file +override_key=!L \ No newline at end of file From 3149b8a6fec69c440b0037ad9e136ec1eceda644 Mon Sep 17 00:00:00 2001 From: Dylan Nguyen <47096930+TTTechnoPro@users.noreply.github.com> Date: Sun, 24 Feb 2019 12:51:45 -0800 Subject: [PATCH 457/489] Update readme.md reswitched website (#339) Should be reswitched.team, the other one (reswitched.tech) is not availble --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c4f5807e..0e55cc854 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ In no particular order, we credit the following for their invaluable contributio * __switchbrew__ for the [libnx](https://github.com/switchbrew/libnx) project and the extensive [documentation, research and tool development](http://switchbrew.org) pertaining to the Nintendo Switch. * __devkitPro__ for the [devkitA64](https://devkitpro.org/) toolchain and libnx support. -* __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.tech/) pertaining to the Nintendo Switch. +* __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.team/) pertaining to the Nintendo Switch. * __ChaN__ for the [FatFs](http://elm-chan.org/fsw/ff/00index_e.html) module. * __Marcus Geelnard__ for the [bcl-1.2.0](https://sourceforge.net/projects/bcl/files/bcl/bcl-1.2.0) library. * __naehrwert__ and __st4rk__ for the original [hekate](https://github.com/nwert/hekate) project and its hwinit code base. From be772b40e1f12680597c4ad27548c9c08d7d877a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 24 Feb 2019 20:22:38 -0800 Subject: [PATCH 458/489] fusee-secondary: add content metadata --- Makefile | 3 +- fusee/fusee-secondary/Makefile | 7 +- fusee/fusee-secondary/linker.ld | 35 ++++++++ fusee/fusee-secondary/src/start.s | 136 +++++++++++++++++++++++++++++- 4 files changed, 174 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 9bf986357..c7cb1e5b9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ TOPTARGETS := all clean dist AMSBRANCH := $(shell git symbolic-ref --short HEAD) -AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) +AMSHASH := $(shell git rev-parse --short HEAD) +AMSREV := $(AMSBRANCH)-$(AMSHASH) ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) AMSREV := $(AMSREV)-dirty diff --git a/fusee/fusee-secondary/Makefile b/fusee/fusee-secondary/Makefile index 7552e8e42..d4a0c2c91 100644 --- a/fusee/fusee-secondary/Makefile +++ b/fusee/fusee-secondary/Makefile @@ -13,7 +13,8 @@ AMS := $(TOPDIR)/../../ include $(DEVKITARM)/base_rules AMSBRANCH := $(shell git symbolic-ref --short HEAD) -AMSREV := $(AMSBRANCH)-$(shell git rev-parse --short HEAD) +AMSHASH := $(shell git rev-parse --short HEAD) +AMSREV := $(AMSBRANCH)-$(AMSHASH) ifneq (, $(strip $(shell git status --porcelain 2>/dev/null))) AMSREV := $(AMSREV)-dirty @@ -43,7 +44,7 @@ INCLUDES := include ../../common/include # options for code generation #--------------------------------------------------------------------------------- ARCH := -march=armv4t -mtune=arm7tdmi -marm -DEFINES := -D__BPMP__ -DFUSEE_STAGE2_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" +DEFINES := -D__BPMP__ -DFUSEE_STAGE2_SRC -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" -DATMOSPHERE_GIT_HASH=$(AMSHASH) CFLAGS := \ -g \ @@ -61,7 +62,7 @@ CFLAGS += $(INCLUDE) CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 -ASFLAGS := -g $(ARCH) +ASFLAGS := -g $(ARCH) $(INCLUDE) $(DEFINES) LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) LIBS := diff --git a/fusee/fusee-secondary/linker.ld b/fusee/fusee-secondary/linker.ld index 68d127842..a6328675a 100644 --- a/fusee/fusee-secondary/linker.ld +++ b/fusee/fusee-secondary/linker.ld @@ -157,6 +157,9 @@ SECTIONS CONSTRUCTORS . = ALIGN(32); } >main + + __data_end__ = ABSOLUTE(.); + PROVIDE (__total_size__ = (__data_end__ - __start__)); .bss (NOLOAD) : { @@ -211,4 +214,36 @@ SECTIONS .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } + + /* ======================= + ==== Embedded Data ==== + ======================= */ + PROVIDE(__ams_mitm_kip_start__ = ams_mitm_kip - __start__); + PROVIDE(__ams_mitm_kip_size__ = ams_mitm_kip_end - ams_mitm_kip); + PROVIDE(__boot_100_kip_start__ = boot_100_kip - __start__); + PROVIDE(__boot_100_kip_size__ = boot_100_kip_end - boot_100_kip); + PROVIDE(__boot_200_kip_start__ = boot_200_kip - __start__); + PROVIDE(__boot_200_kip_size__ = boot_200_kip_end - boot_200_kip); + PROVIDE(__exosphere_bin_start__ = exosphere_bin - __start__); + PROVIDE(__exosphere_bin_size__ = exosphere_bin_end - exosphere_bin); + PROVIDE(__fusee_primary_bin_start__ = fusee_primary_bin - __start__); + PROVIDE(__fusee_primary_bin_size__ = fusee_primary_bin_end - fusee_primary_bin); + PROVIDE(__loader_kip_start__ = loader_kip - __start__); + PROVIDE(__loader_kip_size__ = loader_kip_end - loader_kip); + PROVIDE(__lp0fw_bin_start__ = lp0fw_bin - __start__); + PROVIDE(__lp0fw_bin_size__ = lp0fw_bin_end - lp0fw_bin); + PROVIDE(__pm_kip_start__ = pm_kip - __start__); + PROVIDE(__pm_kip_size__ = pm_kip_end - pm_kip); + PROVIDE(__rebootstub_bin_start__ = rebootstub_bin - __start__); + PROVIDE(__rebootstub_bin_size__ = rebootstub_bin_end - rebootstub_bin); + PROVIDE(__sept_primary_bin_start__ = sept_primary_bin - __start__); + PROVIDE(__sept_primary_bin_size__ = sept_primary_bin_end - sept_primary_bin); + PROVIDE(__sept_secondary_enc_start__ = sept_secondary_enc - __start__); + PROVIDE(__sept_secondary_enc_size__ = sept_secondary_enc_end - sept_secondary_enc); + PROVIDE(__sm_kip_start__ = sm_kip - __start__); + PROVIDE(__sm_kip_size__ = sm_kip_end - sm_kip); + PROVIDE(__splash_screen_bmp_start__ = splash_screen_bmp - __start__); + PROVIDE(__splash_screen_bmp_size__ = splash_screen_bmp_end - splash_screen_bmp); + PROVIDE(__thermosphere_bin_start__ = thermosphere_bin - __start__); + PROVIDE(__thermosphere_bin_size__ = thermosphere_bin_end - thermosphere_bin); } diff --git a/fusee/fusee-secondary/src/start.s b/fusee/fusee-secondary/src/start.s index fcad0f23d..67d6c5c51 100644 --- a/fusee/fusee-secondary/src/start.s +++ b/fusee/fusee-secondary/src/start.s @@ -13,6 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <atmosphere/version.h> .macro CLEAR_GPR_REG_ITER mov r\@, #0 @@ -20,21 +21,27 @@ .section .text.start, "ax", %progbits .arm + .align 5 .global _start .type _start, %function _start: + b _crt0 + +.word (_metadata - _start) + +_crt0: /* Switch to system mode, mask all interrupts, clear all flags */ msr cpsr_cxsf, #0xDF /* Relocate ourselves if necessary */ - ldr r2, =__start__ + ldr r2, =_start adr r3, _start cmp r2, r3 - bne _relocation_loop_end + beq _relocation_loop_end ldr r4, =__bss_start__ - sub r4, r4, r2 /* size >= 32, obviously, and we've declared 32-byte-alignment */ + sub r4, r4, r2 /* size >= 32, obviously, and weve declared 32-byte-alignment */ _relocation_loop: ldmia r3!, {r5-r12} stmia r2!, {r5-r12} @@ -60,6 +67,129 @@ _start: ldr r0, [r0] ldr r1, [r1] b main + +/* Fusee-secondary header. */ +.align 5 +_metadata: +.ascii "FSS0" +.word __total_size__ +.word (_crt0 - _start) +.word (_content_headers - _start) +.word (_content_headers_end - _content_headers) / 0x20 /* Number of content headers */ +.word 0x00010007 /* Maximum known supported HOS version: 7.0.1 */ +.word ((ATMOSPHERE_RELEASE_VERSION_MAJOR << 24) | (ATMOSPHERE_RELEASE_VERSION_MINOR << 16) | (ATMOSPHERE_RELEASE_VERSION_MICRO << 8) | (0x0)) +#define TO_WORD(x) TO_WORD_(x) +#define TO_WORD_(x) 0x##x +#define AMS_GIT_REV_WORD TO_WORD(ATMOSPHERE_GIT_HASH) +.word AMS_GIT_REV_WORD +#undef TO_WORD_ +#undef TO_WORD + +_content_headers: +/* ams_mitm content header */ +.word __ams_mitm_kip_start__ +.word __ams_mitm_kip_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "ams_mitm" +.align 5 + +/* boot_100 content header */ +.word __boot_100_kip_start__ +.word __boot_100_kip_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "boot_100" +.align 5 + +/* boot_200 content header */ +.word __boot_200_kip_start__ +.word __boot_200_kip_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "boot_200" +.align 5 + +/* exosphere content header */ +.word __exosphere_bin_start__ +.word __exosphere_bin_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "exosphere" +.align 5 + +/* fusee_primary content header */ +.word __fusee_primary_bin_start__ +.word __fusee_primary_bin_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "fusee_primary" +.align 5 + +/* loader content header */ +.word __loader_kip_start__ +.word __loader_kip_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "loader" +.align 5 + +/* lp0fw content header */ +.word __lp0fw_bin_start__ +.word __lp0fw_bin_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "lp0fw" +.align 5 + +/* pm content header */ +.word __pm_kip_start__ +.word __pm_kip_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "pm" +.align 5 + +/* rebootstub content header */ +.word __rebootstub_bin_start__ +.word __rebootstub_bin_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "rebootstub" +.align 5 + +/* sept_primary content header */ +.word __sept_primary_bin_start__ +.word __sept_primary_bin_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "sept_primary" +.align 5 + +/* sept_secondary content header */ +.word __sept_secondary_enc_start__ +.word __sept_secondary_enc_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "sept_secondary" +.align 5 + +/* sm content header */ +.word __sm_kip_start__ +.word __sm_kip_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "sm" +.align 5 + +/* splash_screen content header */ +.word __splash_screen_bmp_start__ +.word __splash_screen_bmp_size__ +.word 0xCCCCCCCC +.word 0xCCCCCCCC +.asciz "splash_screen" +.align 5 +_content_headers_end: /* No need to include this in normal programs: */ .section .chainloader.text.start, "ax", %progbits From aaabb4bfc43143df6b128db19cdebf2dbb8dcc4e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 24 Feb 2019 20:28:06 -0800 Subject: [PATCH 459/489] atmosphere: add define for supported hos version --- common/include/atmosphere/version.h | 4 ++++ fusee/fusee-secondary/src/start.s | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/common/include/atmosphere/version.h b/common/include/atmosphere/version.h index 6cc2ca10d..24c6f40dd 100644 --- a/common/include/atmosphere/version.h +++ b/common/include/atmosphere/version.h @@ -21,4 +21,8 @@ #define ATMOSPHERE_RELEASE_VERSION_MINOR 8 #define ATMOSPHERE_RELEASE_VERSION_MICRO 4 +#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 7 +#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 0 +#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 1 + #endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/start.s b/fusee/fusee-secondary/src/start.s index 67d6c5c51..1e639f371 100644 --- a/fusee/fusee-secondary/src/start.s +++ b/fusee/fusee-secondary/src/start.s @@ -76,7 +76,7 @@ _metadata: .word (_crt0 - _start) .word (_content_headers - _start) .word (_content_headers_end - _content_headers) / 0x20 /* Number of content headers */ -.word 0x00010007 /* Maximum known supported HOS version: 7.0.1 */ +.word ((ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR << 24) | (ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR << 16) | (ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO << 8) | (0x0)) .word ((ATMOSPHERE_RELEASE_VERSION_MAJOR << 24) | (ATMOSPHERE_RELEASE_VERSION_MINOR << 16) | (ATMOSPHERE_RELEASE_VERSION_MICRO << 8) | (0x0)) #define TO_WORD(x) TO_WORD_(x) #define TO_WORD_(x) 0x##x From 434f600f9560cb1229e3c2df66dda055c94cf97a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 02:50:53 -0800 Subject: [PATCH 460/489] dmnt: Skeleton cheat service API. --- stratosphere/dmnt/dmnt.json | 3 +- .../dmnt/source/dmnt_cheat_service.cpp | 101 ++++++++++++++++++ .../dmnt/source/dmnt_cheat_service.hpp | 93 ++++++++++++++++ stratosphere/dmnt/source/dmnt_cheat_types.hpp | 39 +++++++ stratosphere/dmnt/source/dmnt_main.cpp | 6 +- 5 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 stratosphere/dmnt/source/dmnt_cheat_service.cpp create mode 100644 stratosphere/dmnt/source/dmnt_cheat_service.hpp create mode 100644 stratosphere/dmnt/source/dmnt_cheat_types.hpp diff --git a/stratosphere/dmnt/dmnt.json b/stratosphere/dmnt/dmnt.json index 0be7e94ed..cbf0e4e6c 100644 --- a/stratosphere/dmnt/dmnt.json +++ b/stratosphere/dmnt/dmnt.json @@ -30,7 +30,8 @@ "fatal:u" ], "service_host": [ - "dmnt:-" + "dmnt:-", + "dmnt:cht" ], "kernel_capabilities": [{ "type": "kernel_flags", diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp new file mode 100644 index 000000000..9b154ced4 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "dmnt_cheat_service.hpp" + +void DmntCheatService::HasCheatProcess(Out<bool> out) { + /* TODO */ + std::abort(); +} + +void DmntCheatService::GetCheatProcessEvent(Out<CopiedHandle> out_event) { + /* TODO */ + std::abort(); +} + +Result DmntCheatService::GetCheatProcessMetadata(Out<CheatProcessMetadata> out_metadata) { + /* TODO */ + return 0xF601; +} + + +Result DmntCheatService::GetCheatProcessMappingCount(Out<u64> out_count) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::GetCheatProcessMappings(OutBuffer<MemoryInfo> mappings, Out<u64> out_count, u64 offset) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::ReadCheatProcessMemory(OutBuffer<u8> buffer, u64 address, u64 out_size) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::WriteCheatProcessMemory(InBuffer<u8> buffer, u64 address, u64 in_size) { + /* TODO */ + return 0xF601; +} + + +Result DmntCheatService::GetCheatCount(Out<u64> out_count) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::GetCheats(OutBuffer<CheatEntry> cheats, Out<u64> out_count, u64 offset) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::GetCheatById(OutBuffer<CheatEntry> cheat, u32 cheat_id) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::ToggleCheat(u32 cheat_id) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::AddCheat(InBuffer<CheatEntry> cheat) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::RemoveCheat(u32 cheat_id) { + /* TODO */ + return 0xF601; +} + + +Result DmntCheatService::GetFrozenAddressCount(Out<u64> out_count) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::GetFrozenAddresses(OutBuffer<uintptr_t> addresses, Out<u64> out_count, u64 offset) { + /* TODO */ + return 0xF601; +} + +Result DmntCheatService::ToggleAddressFrozen(uintptr_t address) { + /* TODO */ + return 0xF601; +} diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.hpp b/stratosphere/dmnt/source/dmnt_cheat_service.hpp new file mode 100644 index 000000000..7ceb91032 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_cheat_service.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "dmnt_cheat_types.hpp" + +enum DmntCheatCmd { + /* Meta */ + DmntCheat_Cmd_HasCheatProcess = 65000, + DmntCheat_Cmd_GetCheatProcessEvent = 65001, + DmntCheat_Cmd_GetCheatProcessMetadata = 65002, + + /* Interact with Memory */ + DmntCheat_Cmd_GetCheatProcessMappingCount = 65100, + DmntCheat_Cmd_GetCheatProcessMappings = 65101, + DmntCheat_Cmd_ReadCheatProcessMemory = 65102, + DmntCheat_Cmd_WriteCheatProcessMemory = 65103, + + /* Interact with Cheats */ + DmntCheat_Cmd_GetCheatCount = 65200, + DmntCheat_Cmd_GetCheats = 65201, + DmntCheat_Cmd_GetCheatById = 65202, + DmntCheat_Cmd_ToggleCheat = 65203, + DmntCheat_Cmd_AddCheat = 65204, + DmntCheat_Cmd_RemoveCheat = 65205, + + /* Interact with Frozen Addresses */ + DmntCheat_Cmd_GetFrozenAddressCount = 65300, + DmntCheat_Cmd_GetFrozenAddresses = 65301, + DmntCheat_Cmd_ToggleAddressFrozen = 65302, +}; + +class DmntCheatService final : public IServiceObject { + private: + void HasCheatProcess(Out<bool> out); + void GetCheatProcessEvent(Out<CopiedHandle> out_event); + Result GetCheatProcessMetadata(Out<CheatProcessMetadata> out_metadata); + + Result GetCheatProcessMappingCount(Out<u64> out_count); + Result GetCheatProcessMappings(OutBuffer<MemoryInfo> mappings, Out<u64> out_count, u64 offset); + Result ReadCheatProcessMemory(OutBuffer<u8> buffer, u64 address, u64 out_size); + Result WriteCheatProcessMemory(InBuffer<u8> buffer, u64 address, u64 in_size); + + Result GetCheatCount(Out<u64> out_count); + Result GetCheats(OutBuffer<CheatEntry> cheats, Out<u64> out_count, u64 offset); + Result GetCheatById(OutBuffer<CheatEntry> cheat, u32 cheat_id); + Result ToggleCheat(u32 cheat_id); + Result AddCheat(InBuffer<CheatEntry> cheat); + Result RemoveCheat(u32 cheat_id); + + Result GetFrozenAddressCount(Out<u64> out_count); + Result GetFrozenAddresses(OutBuffer<uintptr_t> addresses, Out<u64> out_count, u64 offset); + Result ToggleAddressFrozen(uintptr_t address); + + public: + DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta<DmntCheat_Cmd_HasCheatProcess, &DmntCheatService::HasCheatProcess>(), + MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessEvent, &DmntCheatService::GetCheatProcessEvent>(), + MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessMetadata, &DmntCheatService::GetCheatProcessMetadata>(), + + MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessMappingCount, &DmntCheatService::GetCheatProcessMappingCount>(), + MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessMappings, &DmntCheatService::GetCheatProcessMappings>(), + MakeServiceCommandMeta<DmntCheat_Cmd_ReadCheatProcessMemory, &DmntCheatService::ReadCheatProcessMemory>(), + MakeServiceCommandMeta<DmntCheat_Cmd_WriteCheatProcessMemory, &DmntCheatService::WriteCheatProcessMemory>(), + + MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatCount, &DmntCheatService::GetCheatCount>(), + MakeServiceCommandMeta<DmntCheat_Cmd_GetCheats, &DmntCheatService::GetCheats>(), + MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatById, &DmntCheatService::GetCheatById>(), + MakeServiceCommandMeta<DmntCheat_Cmd_ToggleCheat, &DmntCheatService::ToggleCheat>(), + MakeServiceCommandMeta<DmntCheat_Cmd_AddCheat, &DmntCheatService::AddCheat>(), + MakeServiceCommandMeta<DmntCheat_Cmd_RemoveCheat, &DmntCheatService::RemoveCheat>(), + + MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddressCount, &DmntCheatService::GetFrozenAddressCount>(), + MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddresses, &DmntCheatService::GetFrozenAddresses>(), + MakeServiceCommandMeta<DmntCheat_Cmd_ToggleAddressFrozen, &DmntCheatService::ToggleAddressFrozen>(), + }; +}; diff --git a/stratosphere/dmnt/source/dmnt_cheat_types.hpp b/stratosphere/dmnt/source/dmnt_cheat_types.hpp new file mode 100644 index 000000000..b077d1e09 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_cheat_types.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +struct MemoryRegionExtents { + u64 base; + u64 size; +}; + +struct CheatProcessMetadata { + MemoryRegionExtents main_nso_extents; + MemoryRegionExtents heap_extents; + MemoryRegionExtents alias_extents; + MemoryRegionExtents address_space_extents; + u64 main_nso_build_id[4]; +}; + +struct CheatEntry { + bool enabled; + uint32_t cheat_id; + char readable_name[0x20]; + uint32_t opcodes[0x100]; +}; \ No newline at end of file diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index fc4917faa..bf56137b7 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -24,6 +24,7 @@ #include <stratosphere.hpp> #include "dmnt_service.hpp" +#include "dmnt_cheat_service.hpp" extern "C" { extern u32 __start__; @@ -124,11 +125,12 @@ int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); - /* Nintendo uses four threads. */ - auto server_manager = new WaitableManager(4); + /* Nintendo uses four threads. Add a fifth for our cheat service. */ + auto server_manager = new WaitableManager(5); /* Create services. */ server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("dmnt:-", 4)); + server_manager->AddWaitable(new ServiceServer<DmntCheatService>("dmnt:cht", 1)); /* Loop forever, servicing our services. */ server_manager->Process(); From 66d5c9fe26399cc461e5bfe0d47b028754e021f1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 03:30:08 -0800 Subject: [PATCH 461/489] dmnt-cheat: Skeleton cheat manager --- .../dmnt/source/dmnt_cheat_manager.cpp | 75 +++++++++++++++++++ .../dmnt/source/dmnt_cheat_manager.hpp | 31 ++++++++ stratosphere/dmnt/source/dmnt_main.cpp | 4 + 3 files changed, 110 insertions(+) create mode 100644 stratosphere/dmnt/source/dmnt_cheat_manager.cpp create mode 100644 stratosphere/dmnt/source/dmnt_cheat_manager.hpp diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp new file mode 100644 index 000000000..65c98d7cd --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "dmnt_cheat_manager.hpp" + +static HosMutex g_cheat_lock; +static HosThread g_detect_thread, g_vm_thread; + +Handle DmntCheatManager::PrepareDebugNextApplication() { + Result rc; + Handle event_h; + if (R_FAILED((rc = pmdmntEnableDebugForApplication(&event_h)))) { + fatalSimple(rc); + } + + return event_h; +} + +void DmntCheatManager::OnNewApplicationLaunch() { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + /* TODO: load information about the new process. */ +} + +void DmntCheatManager::DetectThread(void *arg) { + auto waiter = new WaitableManager(1); + waiter->AddWaitable(LoadReadOnlySystemEvent(PrepareDebugNextApplication(), [](u64 timeout) { + /* Process stuff for new application. */ + DmntCheatManager::OnNewApplicationLaunch(); + + /* Setup detection for the next application, and close the duplicate handle. */ + svcCloseHandle(PrepareDebugNextApplication()); + + return 0x0; + }, true)); + + waiter->Process(); + delete waiter; +} + +void DmntCheatManager::VmThread(void *arg) { + while (true) { + /* TODO */ + svcSleepThread(0x5000000ul); + } +} + +void DmntCheatManager::InitializeCheatManager() { + /* Spawn application detection thread, spawn cheat vm thread. */ + if (R_FAILED(g_detect_thread.Initialize(&DmntCheatManager::DetectThread, nullptr, 0x4000, 28))) { + std::abort(); + } + if (R_FAILED(g_vm_thread.Initialize(&DmntCheatManager::VmThread, nullptr, 0x4000, 28))) { + std::abort(); + } + + /* Start threads. */ + if (R_FAILED(g_detect_thread.Start()) || R_FAILED(g_vm_thread.Start())) { + std::abort(); + } +} diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp new file mode 100644 index 000000000..a0ad6d3c7 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "dmnt_cheat_types.hpp" + +class DmntCheatManager { + private: + static Handle PrepareDebugNextApplication(); + static void OnNewApplicationLaunch(); + static void DetectThread(void *arg); + static void VmThread(void *arg); + public: + static void InitializeCheatManager(); +}; diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index bf56137b7..e4321328f 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -25,6 +25,7 @@ #include "dmnt_service.hpp" #include "dmnt_cheat_service.hpp" +#include "dmnt_cheat_manager.hpp" extern "C" { extern u32 __start__; @@ -125,6 +126,9 @@ int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); + /* Start cheat manager. */ + DmntCheatManager::InitializeCheatManager(); + /* Nintendo uses four threads. Add a fifth for our cheat service. */ auto server_manager = new WaitableManager(5); From b57ec74ca3fc7e3ed083bdeaf189828d7831738d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 03:33:42 -0800 Subject: [PATCH 462/489] pm: remove duplicate definitions --- stratosphere/pm/source/pm_boot2.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index 6541ae62f..fc739c88e 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -27,20 +27,6 @@ #include "pm_registration.hpp" #include "pm_boot_mode.hpp" -static std::vector<Boot2KnownTitleId> g_boot2_titles; - -static void ClearLaunchedTitles() { - g_boot2_titles.clear(); -} - -static void SetLaunchedTitle(Boot2KnownTitleId title_id) { - g_boot2_titles.push_back(title_id); -} - -static bool HasLaunchedTitle(Boot2KnownTitleId title_id) { - return std::find(g_boot2_titles.begin(), g_boot2_titles.end(), title_id) != g_boot2_titles.end(); -} - static std::vector<Boot2KnownTitleId> g_launched_titles; static bool IsHexadecimal(const char *str) { From 964a69887543c8a384dd1d12552f6f2cb6fa39ee Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 04:09:14 -0800 Subject: [PATCH 463/489] dmnt-cheat: flesh out new process logic --- .../dmnt/source/dmnt_cheat_manager.cpp | 79 ++++++++++++++++++- stratosphere/dmnt/source/dmnt_cheat_types.hpp | 3 +- stratosphere/dmnt/source/pm_shim.c | 58 ++++++++++++++ stratosphere/dmnt/source/pm_shim.h | 19 +++++ 4 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 stratosphere/dmnt/source/pm_shim.c create mode 100644 stratosphere/dmnt/source/pm_shim.h diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 65c98d7cd..0c849f49d 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -16,10 +16,15 @@ #include <switch.h> #include "dmnt_cheat_manager.hpp" +#include "pm_shim.h" static HosMutex g_cheat_lock; static HosThread g_detect_thread, g_vm_thread; +static bool g_has_cheat_process; +static CheatProcessMetadata g_cheat_process_metadata = {0}; +static Handle g_cheat_process_debug_hnd = 0; + Handle DmntCheatManager::PrepareDebugNextApplication() { Result rc; Handle event_h; @@ -30,10 +35,82 @@ Handle DmntCheatManager::PrepareDebugNextApplication() { return event_h; } +static void PopulateMemoryExtents(MemoryRegionExtents *extents, Handle p_h, u64 id_base, u64 id_size) { + Result rc; + /* Get base extent. */ + if (R_FAILED((rc = svcGetInfo(&extents->base, id_base, p_h, 0)))) { + fatalSimple(rc); + } + + /* Get size extent. */ + if (R_FAILED((rc = svcGetInfo(&extents->size, id_size, p_h, 0)))) { + fatalSimple(rc); + } +} + void DmntCheatManager::OnNewApplicationLaunch() { std::scoped_lock<HosMutex> lk(g_cheat_lock); + Result rc; - /* TODO: load information about the new process. */ + /* Close the current application, if it's open. */ + if (g_cheat_process_debug_hnd != 0) { + svcCloseHandle(g_cheat_process_debug_hnd); + g_cheat_process_debug_hnd = 0; + g_cheat_process_metadata = (CheatProcessMetadata){0}; + } + + /* Get the new application's process ID. */ + if (R_FAILED((rc = pmdmntGetApplicationPid(&g_cheat_process_metadata.process_id)))) { + fatalSimple(rc); + } + + /* Get process handle, use it to learn memory extents. */ + { + Handle proc_h = 0; + ON_SCOPE_EXIT { if (proc_h != 0) { svcCloseHandle(proc_h); } }; + + if (R_FAILED((rc = pmdmntAtmosphereGetProcessHandle(&proc_h, g_cheat_process_metadata.process_id)))) { + fatalSimple(rc); + } + + /* Get memory extents. */ + PopulateMemoryExtents(&g_cheat_process_metadata.heap_extents, proc_h, 4, 5); + PopulateMemoryExtents(&g_cheat_process_metadata.alias_extents, proc_h, 2, 3); + if (kernelAbove200()) { + PopulateMemoryExtents(&g_cheat_process_metadata.address_space_extents, proc_h, 12, 13); + } else { + g_cheat_process_metadata.address_space_extents.base = 0x08000000UL; + g_cheat_process_metadata.address_space_extents.size = 0x78000000UL; + } + } + + /* Get module information from Loader. */ + { + LoaderModuleInfo proc_modules[2]; + u32 num_modules; + if (R_FAILED((rc = ldrDmntGetModuleInfos(g_cheat_process_metadata.process_id, &proc_modules, 2, &num_modules)))) { + fatalSimple(rc); + } + + /* All applications must have two modules. */ + /* If we only have one, we must be e.g. mitming HBL. */ + /* We don't want to fuck with HBL. */ + if (num_modules != 2) { + g_cheat_process_metadata.process_id = 0; + return; + } + + g_cheat_process_metadata.main_nso_extents.base = proc_modules[1].base_address; + g_cheat_process_metadata.main_nso_extents.size = proc_modules[1].size; + g_cheat_process_metadata.main_nso_build_id = proc_modules[1].build_id; + } + + /* Open a debug handle. */ + if (R_FAILED((rc = svcDebugActiveProcess(&g_cheat_process_debug_hnd, g_cheat_process_metadata.process_id)))) { + fatalSimple(rc); + } + + /* TODO: Continue debug events, etc. */ } void DmntCheatManager::DetectThread(void *arg) { diff --git a/stratosphere/dmnt/source/dmnt_cheat_types.hpp b/stratosphere/dmnt/source/dmnt_cheat_types.hpp index b077d1e09..7b2069dd2 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_types.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_types.hpp @@ -24,11 +24,12 @@ struct MemoryRegionExtents { }; struct CheatProcessMetadata { + u64 process_id; MemoryRegionExtents main_nso_extents; MemoryRegionExtents heap_extents; MemoryRegionExtents alias_extents; MemoryRegionExtents address_space_extents; - u64 main_nso_build_id[4]; + u8 main_nso_build_id[0x20]; }; struct CheatEntry { diff --git a/stratosphere/dmnt/source/pm_shim.c b/stratosphere/dmnt/source/pm_shim.c new file mode 100644 index 000000000..027265817 --- /dev/null +++ b/stratosphere/dmnt/source/pm_shim.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "pm_shim.h" + +/* Atmosphere extension commands. */ +Result pmdmntAtmosphereGetProcessHandle(Handle* out, u64 pid) { + IpcCommand c; + ipcInitialize(&c); + Service *s = pmdmntGetServiceSession(); + + struct { + u64 magic; + u64 cmd_id; + u64 pid; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65000; + raw->pid = pid; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *out = r.Handles[0]; + } + } + + return rc; +} diff --git a/stratosphere/dmnt/source/pm_shim.h b/stratosphere/dmnt/source/pm_shim.h new file mode 100644 index 000000000..ae2ca9403 --- /dev/null +++ b/stratosphere/dmnt/source/pm_shim.h @@ -0,0 +1,19 @@ +/** + * @file pm_shim.h + * @brief Process Management (pm) IPC wrapper. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include <switch.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Atmosphere extension commands. */ +Result pmdmntAtmosphereGetProcessHandle(Handle* out, u64 pid); + +#ifdef __cplusplus +} +#endif \ No newline at end of file From c80eb26135cb01b0711651bc1be321cf0f8cb955 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 04:27:49 -0800 Subject: [PATCH 464/489] dmnt-cheat: continue fleshing out cheat manager code --- .../dmnt/source/dmnt_cheat_manager.cpp | 82 ++++++++++++++++--- .../dmnt/source/dmnt_cheat_manager.hpp | 8 +- 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 0c849f49d..6d29e3d7d 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -21,10 +21,57 @@ static HosMutex g_cheat_lock; static HosThread g_detect_thread, g_vm_thread; -static bool g_has_cheat_process; static CheatProcessMetadata g_cheat_process_metadata = {0}; static Handle g_cheat_process_debug_hnd = 0; +void DmntCheatManager::CloseActiveCheatProcess() { + if (g_cheat_process_debug_hnd != 0) { + svcCloseHandle(g_cheat_process_debug_hnd); + g_cheat_process_debug_hnd = 0; + g_cheat_process_metadata = (CheatProcessMetadata){0}; + } +} + +bool DmntCheatManager::HasActiveCheatProcess() { + u64 tmp; + bool has_cheat_process = g_cheat_process_debug_hnd != 0; + + if (has_cheat_process) { + has_cheat_process &= R_SUCCEEDED(svcGetProcessId(&tmp, g_cheat_process_debug_hnd)); + } + + if (has_cheat_process) { + has_cheat_process &= R_SUCCEEDED(pmdmntGetApplicationPid(&tmp)); + } + + if (has_cheat_process) { + has_cheat_process &= tmp == g_cheat_process_metadata.process_id; + } + + if (!has_cheat_process) { + CloseActiveCheatProcess(); + } + + return has_cheat_process; +} + +void DmntCheatManager::ContinueCheatProcess() { + if (HasActiveCheatProcess()) { + /* Loop getting debug events. */ + u8 tmp; + while (R_SUCCEEDED(svcGetDebugEvent(&tmp, g_cheat_process_debug_hnd))) { + /* ... */ + } + + /* Continue the process. */ + if (kernelAbove300()) { + svcContinueDebugEvent(g_cheat_process_debug_hnd, 5, nullptr, 0); + } else { + svcLegacyContinueDebugEvent(g_cheat_process_debug_hnd, 5, 0); + } + } +} + Handle DmntCheatManager::PrepareDebugNextApplication() { Result rc; Handle event_h; @@ -53,11 +100,7 @@ void DmntCheatManager::OnNewApplicationLaunch() { Result rc; /* Close the current application, if it's open. */ - if (g_cheat_process_debug_hnd != 0) { - svcCloseHandle(g_cheat_process_debug_hnd); - g_cheat_process_debug_hnd = 0; - g_cheat_process_metadata = (CheatProcessMetadata){0}; - } + CloseActiveCheatProcess(); /* Get the new application's process ID. */ if (R_FAILED((rc = pmdmntGetApplicationPid(&g_cheat_process_metadata.process_id)))) { @@ -88,7 +131,7 @@ void DmntCheatManager::OnNewApplicationLaunch() { { LoaderModuleInfo proc_modules[2]; u32 num_modules; - if (R_FAILED((rc = ldrDmntGetModuleInfos(g_cheat_process_metadata.process_id, &proc_modules, 2, &num_modules)))) { + if (R_FAILED((rc = ldrDmntGetModuleInfos(g_cheat_process_metadata.process_id, proc_modules, 2, &num_modules)))) { fatalSimple(rc); } @@ -102,15 +145,18 @@ void DmntCheatManager::OnNewApplicationLaunch() { g_cheat_process_metadata.main_nso_extents.base = proc_modules[1].base_address; g_cheat_process_metadata.main_nso_extents.size = proc_modules[1].size; - g_cheat_process_metadata.main_nso_build_id = proc_modules[1].build_id; + memcpy(g_cheat_process_metadata.main_nso_build_id, proc_modules[1].build_id, sizeof(g_cheat_process_metadata.main_nso_build_id)); } + /* TODO: Read cheats off the SD. */ + /* Open a debug handle. */ if (R_FAILED((rc = svcDebugActiveProcess(&g_cheat_process_debug_hnd, g_cheat_process_metadata.process_id)))) { fatalSimple(rc); } - /* TODO: Continue debug events, etc. */ + /* Continue debug events, etc. */ + ContinueCheatProcess(); } void DmntCheatManager::DetectThread(void *arg) { @@ -131,11 +177,27 @@ void DmntCheatManager::DetectThread(void *arg) { void DmntCheatManager::VmThread(void *arg) { while (true) { - /* TODO */ + /* Execute Cheat VM. */ + { + /* Acquire lock. */ + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (HasActiveCheatProcess()) { + ContinueCheatProcess(); + + /* TODO: Execute VM. */ + } + } svcSleepThread(0x5000000ul); } } +bool DmntCheatManager::GetHasActiveCheatProcess() { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + return HasActiveCheatProcess(); +} + void DmntCheatManager::InitializeCheatManager() { /* Spawn application detection thread, spawn cheat vm thread. */ if (R_FAILED(g_detect_thread.Initialize(&DmntCheatManager::DetectThread, nullptr, 0x4000, 28))) { diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index a0ad6d3c7..afbd63715 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -26,6 +26,12 @@ class DmntCheatManager { static void OnNewApplicationLaunch(); static void DetectThread(void *arg); static void VmThread(void *arg); - public: + + static bool HasActiveCheatProcess(); + static void CloseActiveCheatProcess(); + static void ContinueCheatProcess(); + public:; + static bool GetHasActiveCheatProcess(); + static void InitializeCheatManager(); }; From e4cc39c29b56940089a0ca2ed55b71e0acab52c9 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 04:37:02 -0800 Subject: [PATCH 465/489] dmnt-cheat: Implement all meta commands. --- .../dmnt/source/dmnt_cheat_manager.cpp | 25 +++++++++++++++++++ .../dmnt/source/dmnt_cheat_manager.hpp | 2 ++ .../dmnt/source/dmnt_cheat_service.cpp | 10 +++----- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 6d29e3d7d..2653fc25f 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -21,6 +21,8 @@ static HosMutex g_cheat_lock; static HosThread g_detect_thread, g_vm_thread; +static IEvent *g_cheat_process_event; + static CheatProcessMetadata g_cheat_process_metadata = {0}; static Handle g_cheat_process_debug_hnd = 0; @@ -29,6 +31,7 @@ void DmntCheatManager::CloseActiveCheatProcess() { svcCloseHandle(g_cheat_process_debug_hnd); g_cheat_process_debug_hnd = 0; g_cheat_process_metadata = (CheatProcessMetadata){0}; + g_cheat_process_event->Signal(); } } @@ -157,6 +160,9 @@ void DmntCheatManager::OnNewApplicationLaunch() { /* Continue debug events, etc. */ ContinueCheatProcess(); + + /* Signal to our fans. */ + g_cheat_process_event->Signal(); } void DmntCheatManager::DetectThread(void *arg) { @@ -198,7 +204,26 @@ bool DmntCheatManager::GetHasActiveCheatProcess() { return HasActiveCheatProcess(); } +Handle DmntCheatManager::GetCheatProcessEventHandle() { + return g_cheat_process_event->GetHandle(); +} + +Result DmntCheatManager::GetCheatProcessMetadata(CheatProcessMetadata *out) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (HasActiveCheatProcess()) { + *out = g_cheat_process_metadata; + return 0; + } + + /* TODO: Decide on a set of return values... */ + return 0x20F; +} + void DmntCheatManager::InitializeCheatManager() { + /* Create cheat process detection event. */ + g_cheat_process_event = CreateWriteOnlySystemEvent(); + /* Spawn application detection thread, spawn cheat vm thread. */ if (R_FAILED(g_detect_thread.Initialize(&DmntCheatManager::DetectThread, nullptr, 0x4000, 28))) { std::abort(); diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index afbd63715..e454c30a0 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -32,6 +32,8 @@ class DmntCheatManager { static void ContinueCheatProcess(); public:; static bool GetHasActiveCheatProcess(); + static Handle GetCheatProcessEventHandle(); + static Result GetCheatProcessMetadata(CheatProcessMetadata *out); static void InitializeCheatManager(); }; diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp index 9b154ced4..f2088acf7 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -16,20 +16,18 @@ #include <switch.h> #include "dmnt_cheat_service.hpp" +#include "dmnt_cheat_manager.hpp" void DmntCheatService::HasCheatProcess(Out<bool> out) { - /* TODO */ - std::abort(); + out.SetValue(DmntCheatManager::GetHasActiveCheatProcess()); } void DmntCheatService::GetCheatProcessEvent(Out<CopiedHandle> out_event) { - /* TODO */ - std::abort(); + out_event.SetValue(DmntCheatManager::GetCheatProcessEventHandle()); } Result DmntCheatService::GetCheatProcessMetadata(Out<CheatProcessMetadata> out_metadata) { - /* TODO */ - return 0xF601; + return DmntCheatManager::GetCheatProcessMetadata(out_metadata.GetPointer()); } From f5ac89506275ff571c6c034eab99cd3b6ad3e28a Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 04:47:43 -0800 Subject: [PATCH 466/489] dmnt-cheat: revise cheatentry definition --- stratosphere/dmnt/source/dmnt_cheat_service.hpp | 2 +- stratosphere/dmnt/source/dmnt_cheat_types.hpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.hpp b/stratosphere/dmnt/source/dmnt_cheat_service.hpp index 7ceb91032..02aca63d5 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.hpp @@ -61,7 +61,7 @@ class DmntCheatService final : public IServiceObject { Result GetCheats(OutBuffer<CheatEntry> cheats, Out<u64> out_count, u64 offset); Result GetCheatById(OutBuffer<CheatEntry> cheat, u32 cheat_id); Result ToggleCheat(u32 cheat_id); - Result AddCheat(InBuffer<CheatEntry> cheat); + Result AddCheat(InBuffer<CheatDefinition> cheat, Out<u32> out_cheat_id, bool enabled); Result RemoveCheat(u32 cheat_id); Result GetFrozenAddressCount(Out<u64> out_count); diff --git a/stratosphere/dmnt/source/dmnt_cheat_types.hpp b/stratosphere/dmnt/source/dmnt_cheat_types.hpp index 7b2069dd2..4e7a4602e 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_types.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_types.hpp @@ -32,9 +32,14 @@ struct CheatProcessMetadata { u8 main_nso_build_id[0x20]; }; +struct CheatDefinition { + char readable_name[0x40]; + uint32_t num_opcodes; + uint32_t opcodes[0x100]; +}; + struct CheatEntry { bool enabled; uint32_t cheat_id; - char readable_name[0x20]; - uint32_t opcodes[0x100]; + CheatDefinition definition; }; \ No newline at end of file From 2552c0327cd9803c4b2a9b16aadf05ccf3208427 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 18:33:07 -0800 Subject: [PATCH 467/489] dmnt-cheat: Begin implementing Cheat VM. --- .../dmnt/source/dmnt_cheat_manager.cpp | 11 +- .../dmnt/source/dmnt_cheat_service.cpp | 2 +- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 109 ++++++++++++ stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 157 ++++++++++++++++++ 4 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 stratosphere/dmnt/source/dmnt_cheat_vm.cpp create mode 100644 stratosphere/dmnt/source/dmnt_cheat_vm.hpp diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 2653fc25f..bb24343f6 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -16,12 +16,14 @@ #include <switch.h> #include "dmnt_cheat_manager.hpp" +#include "dmnt_cheat_vm.hpp" #include "pm_shim.h" static HosMutex g_cheat_lock; static HosThread g_detect_thread, g_vm_thread; static IEvent *g_cheat_process_event; +static DmntCheatVm *g_cheat_vm; static CheatProcessMetadata g_cheat_process_metadata = {0}; static Handle g_cheat_process_debug_hnd = 0; @@ -189,9 +191,13 @@ void DmntCheatManager::VmThread(void *arg) { std::scoped_lock<HosMutex> lk(g_cheat_lock); if (HasActiveCheatProcess()) { + /* Handle any pending debug events. */ ContinueCheatProcess(); - /* TODO: Execute VM. */ + /* Execute VM. */ + if (g_cheat_vm->GetProgramSize() != 0) { + g_cheat_vm->Execute(&g_cheat_process_metadata); + } } } svcSleepThread(0x5000000ul); @@ -224,6 +230,9 @@ void DmntCheatManager::InitializeCheatManager() { /* Create cheat process detection event. */ g_cheat_process_event = CreateWriteOnlySystemEvent(); + /* Create cheat vm. */ + g_cheat_vm = new DmntCheatVm(); + /* Spawn application detection thread, spawn cheat vm thread. */ if (R_FAILED(g_detect_thread.Initialize(&DmntCheatManager::DetectThread, nullptr, 0x4000, 28))) { std::abort(); diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp index f2088acf7..b67422344 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -72,7 +72,7 @@ Result DmntCheatService::ToggleCheat(u32 cheat_id) { return 0xF601; } -Result DmntCheatService::AddCheat(InBuffer<CheatEntry> cheat) { +Result DmntCheatService::AddCheat(InBuffer<CheatDefinition> cheat, Out<u32> out_cheat_id, bool enabled) { /* TODO */ return 0xF601; } diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp new file mode 100644 index 000000000..1264562df --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include "dmnt_cheat_types.hpp" +#include "dmnt_cheat_vm.hpp" + +bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { + /* TODO: Parse opcodes */ + return false; +} + +void DmntCheatVm::SkipConditionalBlock() { + CheatVmOpcode skip_opcode; + while (this->DecodeNextOpcode(&skip_opcode)) { + /* Decode instructions until we see end of conditional block. */ + /* NOTE: This is broken in gateway's implementation. */ + /* Gateway currently checks for "0x2" instead of "0x20000000" */ + /* In addition, they do a linear scan instead of correctly decoding opcodes. */ + /* This causes issues if "0x2" appears as an immediate in the conditional block... */ + if (skip_opcode.opcode == CheatVmOpcodeType_EndConditionalBlock) { + break; + } + } +} + +void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { + CheatVmOpcode cur_opcode; + u64 kDown = 0; + + /* TODO: Get Keys down. */ + + /* Clear VM state. */ + for (size_t i = 0; i < DmntCheatVm::NumRegisters; i++) { + this->registers[i] = 0; + this->loop_tops[i] = 0; + } + + /* Loop until program finishes. */ + while (this->DecodeNextOpcode(&cur_opcode)) { + switch (cur_opcode.opcode) { + case CheatVmOpcodeType_StoreStatic: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_BeginConditionalBlock: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_EndConditionalBlock: + /* There is nothing to do here. Just move on to the next instruction. */ + break; + case CheatVmOpcodeType_ControlLoop: + if (cur_opcode.ctrl_loop.start_loop) { + /* Start a loop. */ + this->registers[cur_opcode.ctrl_loop.register_index] = cur_opcode.ctrl_loop.num_iters; + this->loop_tops[cur_opcode.ctrl_loop.register_index] = this->instruction_ptr; + } else { + /* End a loop. */ + this->registers[cur_opcode.ctrl_loop.register_index]--; + if (this->registers[cur_opcode.ctrl_loop.register_index] != 0) { + this->instruction_ptr = this->loop_tops[cur_opcode.ctrl_loop.register_index]; + } + } + break; + case CheatVmOpcodeType_LoadRegisterStatic: + /* Set a register to a static value. */ + this->registers[cur_opcode.ldr_static.register_index] = cur_opcode.ldr_static.value; + break; + case CheatVmOpcodeType_LoadRegisterMemory: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_StoreToRegisterAddress: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_PerformArithmetic: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_BeginKeypressConditionalBlock: + /* Check for keypress. */ + if ((cur_opcode.begin_keypress_cond.key_mask & kDown) != cur_opcode.begin_keypress_cond.key_mask) { + /* Keys not pressed. Skip conditional block. */ + this->SkipConditionalBlock(); + } + break; + } + } +} \ No newline at end of file diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp new file mode 100644 index 000000000..869097040 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +#include "dmnt_cheat_types.hpp" + +enum CheatVmOpcodeType : u32 { + CheatVmOpcodeType_StoreStatic = 0, + CheatVmOpcodeType_BeginConditionalBlock = 1, + CheatVmOpcodeType_EndConditionalBlock = 2, + CheatVmOpcodeType_ControlLoop = 3, + CheatVmOpcodeType_LoadRegisterStatic = 4, + CheatVmOpcodeType_LoadRegisterMemory = 5, + CheatVmOpcodeType_StoreToRegisterAddress = 6, + CheatVmOpcodeType_PerformArithmetic = 7, + CheatVmOpcodeType_BeginKeypressConditionalBlock = 8, +}; + +enum MemoryAccessType : u32 { + MemoryAccessType_MainNso = 0, + MemoryAccessType_Heap = 1, +}; + +enum ConditionalComparisonType : u32 { + ConditionalComparisonType_GT = 1, + ConditionalComparisonType_GE = 2, + ConditionalComparisonType_LT = 3, + ConditionalComparisonType_LE = 4, + ConditionalComparisonType_EQ = 5, + ConditionalComparisonType_NE = 6, +}; + +enum RegisterArithmeticType : u32 { + RegisterArithmeticType_Addition = 0, + RegisterArithmeticType_Subtraction = 1, + RegisterArithmeticType_Multiplication = 2, + RegisterArithmeticType_LeftShift = 3, + RegisterArithmeticType_RightShift = 4, +}; + +union VmInt { + u8 bit8; + u16 bit16; + u32 bit32; + u64 bit64; +}; + +struct StoreStaticOpcode { + u32 bit_width; + MemoryAccessType mem_type; + u32 offset_register; + u64 relative_address; + VmInt value; +}; + +struct BeginConditionalOpcode { + u32 bit_width; + MemoryAccessType mem_type; + ConditionalComparisonType cond_type; + u64 relative_address; + VmInt value; +}; + +struct EndConditionalOpcode {}; + +struct ControlLoopOpcode { + bool start_loop; + u32 register_index; + u32 num_iters; +}; + +struct LoadRegisterStaticOpcode { + u32 register_index; + u64 value; +}; + +struct LoadRegisterMemoryOpcode { + u32 bit_width; + MemoryAccessType mem_type; + u32 reg_index; + bool load_from_reg; + u64 relative_address; +}; + +struct StoreToRegisterAddressOpcode { + u32 bit_width; + u32 reg_index; + bool increment_reg; + bool add_offset_reg; + u32 offset_reg_index; + u64 value; +}; + +struct PerformArithmeticOpcode { + u32 bit_width; + u32 reg_index; + RegisterArithmeticType math_type; + VmInt value; +}; + +struct BeginKeypressConditionalOpcode { + u32 key_mask; +}; + +struct CheatVmOpcode { + CheatVmOpcodeType opcode; + union { + StoreStaticOpcode store_static; + BeginConditionalOpcode begin_cond; + EndConditionalOpcode end_cond; + ControlLoopOpcode ctrl_loop; + LoadRegisterStaticOpcode ldr_static; + LoadRegisterMemoryOpcode ldr_memory; + StoreToRegisterAddressOpcode str_regaddr; + PerformArithmeticOpcode perform_math; + BeginKeypressConditionalOpcode begin_keypress_cond; + }; +}; + +class DmntCheatVm { + public: + constexpr static size_t MaximumProgramOpcodeCount = 0x400; + constexpr static size_t NumRegisters = 0x10; + private: + size_t num_opcodes = 0; + size_t instruction_ptr = 0; + u32 program[MaximumProgramOpcodeCount] = {0}; + u64 registers[NumRegisters] = {0}; + size_t loop_tops[NumRegisters] = {0}; + private: + bool DecodeNextOpcode(CheatVmOpcode *out); + void SkipConditionalBlock(); + public: + DmntCheatVm() { } + + size_t GetProgramSize() { + return this->num_opcodes; + } + + void Execute(const CheatProcessMetadata *metadata); +}; From 68af2c1c2a106b263eac88d399a597c2a8c56de1 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 18:46:53 -0800 Subject: [PATCH 468/489] dmnt-cheat: Implement static math opcode. --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 48 ++++++++++++++++++---- stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 12 +++--- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index 1264562df..afa19505b 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -68,19 +68,19 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { case CheatVmOpcodeType_ControlLoop: if (cur_opcode.ctrl_loop.start_loop) { /* Start a loop. */ - this->registers[cur_opcode.ctrl_loop.register_index] = cur_opcode.ctrl_loop.num_iters; - this->loop_tops[cur_opcode.ctrl_loop.register_index] = this->instruction_ptr; + this->registers[cur_opcode.ctrl_loop.reg_index] = cur_opcode.ctrl_loop.num_iters; + this->loop_tops[cur_opcode.ctrl_loop.reg_index] = this->instruction_ptr; } else { /* End a loop. */ - this->registers[cur_opcode.ctrl_loop.register_index]--; - if (this->registers[cur_opcode.ctrl_loop.register_index] != 0) { - this->instruction_ptr = this->loop_tops[cur_opcode.ctrl_loop.register_index]; + this->registers[cur_opcode.ctrl_loop.reg_index]--; + if (this->registers[cur_opcode.ctrl_loop.reg_index] != 0) { + this->instruction_ptr = this->loop_tops[cur_opcode.ctrl_loop.reg_index]; } } break; case CheatVmOpcodeType_LoadRegisterStatic: /* Set a register to a static value. */ - this->registers[cur_opcode.ldr_static.register_index] = cur_opcode.ldr_static.value; + this->registers[cur_opcode.ldr_static.reg_index] = cur_opcode.ldr_static.value; break; case CheatVmOpcodeType_LoadRegisterMemory: { @@ -92,9 +92,41 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { /* TODO */ } break; - case CheatVmOpcodeType_PerformArithmetic: + case CheatVmOpcodeType_PerformArithmeticStatic: { - /* TODO */ + /* Do requested math. */ + switch (cur_opcode.perform_math_static.math_type) { + case RegisterArithmeticType_Addition: + this->registers[cur_opcode.perform_math_static.reg_index] += (u64)cur_opcode.perform_math_static.value; + break; + case RegisterArithmeticType_Subtraction: + this->registers[cur_opcode.perform_math_static.reg_index] -= (u64)cur_opcode.perform_math_static.value; + break; + case RegisterArithmeticType_Multiplication: + this->registers[cur_opcode.perform_math_static.reg_index] *= (u64)cur_opcode.perform_math_static.value; + break; + case RegisterArithmeticType_LeftShift: + this->registers[cur_opcode.perform_math_static.reg_index] <<= (u64)cur_opcode.perform_math_static.value; + break; + case RegisterArithmeticType_RightShift: + this->registers[cur_opcode.perform_math_static.reg_index] >>= (u64)cur_opcode.perform_math_static.value; + break; + } + /* Apply bit width. */ + switch (cur_opcode.perform_math_static.bit_width) { + case 1: + this->registers[cur_opcode.perform_math_static.reg_index] = static_cast<u8>(this->registers[cur_opcode.perform_math_static.reg_index]); + break; + case 2: + this->registers[cur_opcode.perform_math_static.reg_index] = static_cast<u16>(this->registers[cur_opcode.perform_math_static.reg_index]); + break; + case 4: + this->registers[cur_opcode.perform_math_static.reg_index] = static_cast<u32>(this->registers[cur_opcode.perform_math_static.reg_index]); + break; + case 8: + this->registers[cur_opcode.perform_math_static.reg_index] = static_cast<u64>(this->registers[cur_opcode.perform_math_static.reg_index]); + break; + } } break; case CheatVmOpcodeType_BeginKeypressConditionalBlock: diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 869097040..55e4cffce 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -28,7 +28,7 @@ enum CheatVmOpcodeType : u32 { CheatVmOpcodeType_LoadRegisterStatic = 4, CheatVmOpcodeType_LoadRegisterMemory = 5, CheatVmOpcodeType_StoreToRegisterAddress = 6, - CheatVmOpcodeType_PerformArithmetic = 7, + CheatVmOpcodeType_PerformArithmeticStatic = 7, CheatVmOpcodeType_BeginKeypressConditionalBlock = 8, }; @@ -81,12 +81,12 @@ struct EndConditionalOpcode {}; struct ControlLoopOpcode { bool start_loop; - u32 register_index; + u32 reg_index; u32 num_iters; }; struct LoadRegisterStaticOpcode { - u32 register_index; + u32 reg_index; u64 value; }; @@ -107,11 +107,11 @@ struct StoreToRegisterAddressOpcode { u64 value; }; -struct PerformArithmeticOpcode { +struct PerformArithmeticStaticOpcode { u32 bit_width; u32 reg_index; RegisterArithmeticType math_type; - VmInt value; + u32 value; }; struct BeginKeypressConditionalOpcode { @@ -128,7 +128,7 @@ struct CheatVmOpcode { LoadRegisterStaticOpcode ldr_static; LoadRegisterMemoryOpcode ldr_memory; StoreToRegisterAddressOpcode str_regaddr; - PerformArithmeticOpcode perform_math; + PerformArithmeticStaticOpcode perform_math_static; BeginKeypressConditionalOpcode begin_keypress_cond; }; }; From a3fc2c95b8bbf16345db8cc5c4eb1c46f61bef3b Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Wed, 27 Feb 2019 19:30:29 -0800 Subject: [PATCH 469/489] dmnt-cheat: Add new, better math instruction to vm --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 82 ++++++++++++++++++++++ stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 24 +++++++ 2 files changed, 106 insertions(+) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index afa19505b..627c94d06 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -37,6 +37,22 @@ void DmntCheatVm::SkipConditionalBlock() { } } +u64 DmntCheatVm::GetVmInt(VmInt value, u32 bit_width) { + switch (bit_width) { + case 1: + return value.bit8; + case 2: + return value.bit16; + case 4: + return value.bit32; + case 8: + return value.bit64; + default: + /* Invalid bit width -> return 0. */ + return 0; + } +} + void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { CheatVmOpcode cur_opcode; u64 kDown = 0; @@ -111,6 +127,9 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { case RegisterArithmeticType_RightShift: this->registers[cur_opcode.perform_math_static.reg_index] >>= (u64)cur_opcode.perform_math_static.value; break; + default: + /* Do not handle extensions here. */ + break; } /* Apply bit width. */ switch (cur_opcode.perform_math_static.bit_width) { @@ -136,6 +155,69 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { this->SkipConditionalBlock(); } break; + case CheatVmOpcodeType_PerformArithmeticRegister: + { + const u64 operand_1_value = this->registers[cur_opcode.perform_math_reg.src_reg_1_index]; + const u64 operand_2_value = cur_opcode.perform_math_reg.has_immediate ? + GetVmInt(cur_opcode.perform_math_reg.value, cur_opcode.perform_math_reg.bit_width) : + this->registers[cur_opcode.perform_math_reg.src_reg_2_index]; + + u64 res_val = 0; + /* Do requested math. */ + switch (cur_opcode.perform_math_reg.math_type) { + case RegisterArithmeticType_Addition: + res_val = operand_1_value + operand_2_value; + break; + case RegisterArithmeticType_Subtraction: + res_val = operand_1_value - operand_2_value; + break; + case RegisterArithmeticType_Multiplication: + res_val = operand_1_value * operand_2_value; + break; + case RegisterArithmeticType_LeftShift: + res_val = operand_1_value << operand_2_value; + break; + case RegisterArithmeticType_RightShift: + res_val = operand_1_value >> operand_2_value; + break; + case RegisterArithmeticType_LogicalAnd: + res_val = operand_1_value & operand_2_value; + break; + case RegisterArithmeticType_LogicalOr: + res_val = operand_1_value | operand_2_value; + break; + case RegisterArithmeticType_LogicalNot: + res_val = ~operand_1_value; + break; + case RegisterArithmeticType_LogicalXor: + res_val = operand_1_value ^ operand_2_value; + break; + case RegisterArithmeticType_None: + res_val = operand_1_value; + break; + } + + + /* Apply bit width. */ + switch (cur_opcode.perform_math_reg.bit_width) { + case 1: + res_val = static_cast<u8>(res_val); + break; + case 2: + res_val = static_cast<u16>(res_val); + break; + case 4: + res_val = static_cast<u32>(res_val); + break; + case 8: + res_val = static_cast<u64>(res_val); + break; + } + + /* Save to register. */ + this->registers[cur_opcode.perform_math_reg.dst_reg_index] = res_val; + } + break; } } } \ No newline at end of file diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 55e4cffce..51499690a 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -30,6 +30,9 @@ enum CheatVmOpcodeType : u32 { CheatVmOpcodeType_StoreToRegisterAddress = 6, CheatVmOpcodeType_PerformArithmeticStatic = 7, CheatVmOpcodeType_BeginKeypressConditionalBlock = 8, + + /* These are not implemented by Gateway's VM. */ + CheatVmOpcodeType_PerformArithmeticRegister = 9, }; enum MemoryAccessType : u32 { @@ -52,6 +55,14 @@ enum RegisterArithmeticType : u32 { RegisterArithmeticType_Multiplication = 2, RegisterArithmeticType_LeftShift = 3, RegisterArithmeticType_RightShift = 4, + + /* These are not supported by Gateway's VM. */ + RegisterArithmeticType_LogicalAnd = 5, + RegisterArithmeticType_LogicalOr = 6, + RegisterArithmeticType_LogicalNot = 7, + RegisterArithmeticType_LogicalXor = 8, + + RegisterArithmeticType_None = 9, }; union VmInt { @@ -118,6 +129,16 @@ struct BeginKeypressConditionalOpcode { u32 key_mask; }; +struct PerformArithmeticRegisterOpcode { + u32 bit_width; + RegisterArithmeticType math_type; + u32 dst_reg_index; + u32 src_reg_1_index; + u32 src_reg_2_index; + bool has_immediate; + VmInt value; +}; + struct CheatVmOpcode { CheatVmOpcodeType opcode; union { @@ -130,6 +151,7 @@ struct CheatVmOpcode { StoreToRegisterAddressOpcode str_regaddr; PerformArithmeticStaticOpcode perform_math_static; BeginKeypressConditionalOpcode begin_keypress_cond; + PerformArithmeticRegisterOpcode perform_math_reg; }; }; @@ -146,6 +168,8 @@ class DmntCheatVm { private: bool DecodeNextOpcode(CheatVmOpcode *out); void SkipConditionalBlock(); + + static u64 GetVmInt(VmInt value, u32 bit_width); public: DmntCheatVm() { } From bc6ad530181ea67556f5c793f8dd90bcd2026ff6 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 3 Mar 2019 06:29:48 -0800 Subject: [PATCH 470/489] dmnt-cheat: Implement remaining VM opcodes --- .../dmnt/source/dmnt_cheat_manager.cpp | 30 ++++++ .../dmnt/source/dmnt_cheat_manager.hpp | 7 +- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 99 ++++++++++++++++++- stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 7 +- 4 files changed, 135 insertions(+), 8 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index bb24343f6..cdd2e15ff 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -77,6 +77,36 @@ void DmntCheatManager::ContinueCheatProcess() { } } +Result DmntCheatManager::ReadCheatProcessMemoryForVm(u64 proc_addr, void *out_data, size_t size) { + if (HasActiveCheatProcess()) { + return svcReadDebugProcessMemory(out_data, g_cheat_process_debug_hnd, proc_addr, size); + } + + /* TODO: Return value... */ + return 0x20F; +} + +Result DmntCheatManager::WriteCheatProcessMemoryForVm(u64 proc_addr, const void *data, size_t size) { + if (HasActiveCheatProcess()) { + return svcWriteDebugProcessMemory(g_cheat_process_debug_hnd, data, proc_addr, size); + } + + /* TODO: Return value... */ + return 0x20F; +} + +Result DmntCheatManager::ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + return ReadCheatProcessMemoryForVm(proc_addr, out_data, size); +} + +Result DmntCheatManager::WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + return WriteCheatProcessMemoryForVm(proc_addr, data, size); +} + Handle DmntCheatManager::PrepareDebugNextApplication() { Result rc; Handle event_h; diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index e454c30a0..5d7518ae6 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -30,10 +30,15 @@ class DmntCheatManager { static bool HasActiveCheatProcess(); static void CloseActiveCheatProcess(); static void ContinueCheatProcess(); - public:; + public: static bool GetHasActiveCheatProcess(); static Handle GetCheatProcessEventHandle(); static Result GetCheatProcessMetadata(CheatProcessMetadata *out); + static Result ReadCheatProcessMemoryForVm(u64 proc_addr, void *out_data, size_t size); + static Result WriteCheatProcessMemoryForVm(u64 proc_addr, const void *data, size_t size); + static Result ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size); + static Result WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size); + static void InitializeCheatManager(); }; diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index 627c94d06..c3766de8d 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -17,6 +17,7 @@ #include <switch.h> #include "dmnt_cheat_types.hpp" #include "dmnt_cheat_vm.hpp" +#include "dmnt_cheat_manager.hpp" bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { /* TODO: Parse opcodes */ @@ -53,6 +54,16 @@ u64 DmntCheatVm::GetVmInt(VmInt value, u32 bit_width) { } } +u64 DmntCheatVm::GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address) { + switch (mem_type) { + case MemoryAccessType_MainNso: + default: + return metadata->main_nso_extents.base + rel_address; + case MemoryAccessType_Heap: + return metadata->heap_extents.base + rel_address; + } +} + void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { CheatVmOpcode cur_opcode; u64 kDown = 0; @@ -70,12 +81,59 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { switch (cur_opcode.opcode) { case CheatVmOpcodeType_StoreStatic: { - /* TODO */ + /* Calculate address, write value to memory. */ + u64 dst_address = GetCheatProcessAddress(metadata, cur_opcode.store_static.mem_type, cur_opcode.store_static.rel_address + this->registers[cur_opcode.store_static.offset_register]); + u64 dst_value = GetVmInt(cur_opcode.store_static.value, cur_opcode.store_static.bit_width); + switch (cur_opcode.store_static.bit_width) { + case 1: + case 2: + case 4: + case 8: + DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.store_static.bit_width); + break; + } } break; case CheatVmOpcodeType_BeginConditionalBlock: { - /* TODO */ + /* Read value from memory. */ + u64 src_address = GetCheatProcessAddress(metadata, cur_opcode.begin_cond.mem_type, cur_opcode.begin_cond.rel_address); + u64 src_value = 0; + switch (cur_opcode.store_static.bit_width) { + case 1: + case 2: + case 4: + case 8: + DmntCheatManager::ReadCheatProcessMemoryForVm(src_address, &src_value, cur_opcode.begin_cond.bit_width); + break; + } + /* Check against condition. */ + u64 cond_value = GetVmInt(cur_opcode.begin_cond.value, cur_opcode.begin_cond.bit_width); + bool cond_met = false; + switch (cur_opcode.begin_cond.cond_type) { + case ConditionalComparisonType_GT: + cond_met = src_value > cond_value; + break; + case ConditionalComparisonType_GE: + cond_met = src_value >= cond_value; + break; + case ConditionalComparisonType_LT: + cond_met = src_value < cond_value; + break; + case ConditionalComparisonType_LE: + cond_met = src_value <= cond_value; + break; + case ConditionalComparisonType_EQ: + cond_met = src_value == cond_value; + break; + case ConditionalComparisonType_NE: + cond_met = src_value != cond_value; + break; + } + /* Skip conditional block if condition not met. */ + if (!cond_met) { + this->SkipConditionalBlock(); + } } break; case CheatVmOpcodeType_EndConditionalBlock: @@ -100,12 +158,45 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { break; case CheatVmOpcodeType_LoadRegisterMemory: { - /* TODO */ + /* Choose source address. */ + u64 src_address; + if (cur_opcode.ldr_memory.load_from_reg) { + src_address = this->registers[cur_opcode.ldr_memory.reg_index] + cur_opcode.ldr_memory.rel_address; + } else { + src_address = GetCheatProcessAddress(metadata, cur_opcode.ldr_memory.mem_type, cur_opcode.ldr_memory.rel_address); + } + /* Read into register. Gateway only reads on valid bitwidth. */ + switch (cur_opcode.ldr_memory.bit_width) { + case 1: + case 2: + case 4: + case 8: + DmntCheatManager::ReadCheatProcessMemoryForVm(src_address, &this->registers[cur_opcode.ldr_memory.reg_index], cur_opcode.ldr_memory.bit_width); + break; + } } break; case CheatVmOpcodeType_StoreToRegisterAddress: { - /* TODO */ + /* Calculate address. */ + u64 dst_address = this->registers[cur_opcode.str_regaddr.reg_index]; + u64 dst_value = cur_opcode.str_regaddr.value; + if (cur_opcode.str_regaddr.add_offset_reg) { + dst_address += this->registers[cur_opcode.str_regaddr.offset_reg_index]; + } + /* Write value to memory. Gateway only writes on valid bitwidth. */ + switch (cur_opcode.str_regaddr.bit_width) { + case 1: + case 2: + case 4: + case 8: + DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.str_regaddr.bit_width); + break; + } + /* Increment register if relevant. */ + if (cur_opcode.str_regaddr.increment_reg) { + this->registers[cur_opcode.str_regaddr.reg_index] += cur_opcode.str_regaddr.bit_width; + } } break; case CheatVmOpcodeType_PerformArithmeticStatic: diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 51499690a..705f26a4a 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -76,7 +76,7 @@ struct StoreStaticOpcode { u32 bit_width; MemoryAccessType mem_type; u32 offset_register; - u64 relative_address; + u64 rel_address; VmInt value; }; @@ -84,7 +84,7 @@ struct BeginConditionalOpcode { u32 bit_width; MemoryAccessType mem_type; ConditionalComparisonType cond_type; - u64 relative_address; + u64 rel_address; VmInt value; }; @@ -106,7 +106,7 @@ struct LoadRegisterMemoryOpcode { MemoryAccessType mem_type; u32 reg_index; bool load_from_reg; - u64 relative_address; + u64 rel_address; }; struct StoreToRegisterAddressOpcode { @@ -170,6 +170,7 @@ class DmntCheatVm { void SkipConditionalBlock(); static u64 GetVmInt(VmInt value, u32 bit_width); + static u64 GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address); public: DmntCheatVm() { } From af70a4a3a3791b4253170be19971ed647f03606d Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 3 Mar 2019 06:44:21 -0800 Subject: [PATCH 471/489] dmnt-cheat: skeleton decode, fix missing libnx call --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 100 +++++++++++++++++++-- stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 2 + stratosphere/dmnt/source/dmnt_main.cpp | 8 +- 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index c3766de8d..979c61f2e 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -20,8 +20,90 @@ #include "dmnt_cheat_manager.hpp" bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { - /* TODO: Parse opcodes */ - return false; + /* If we've ever seen a decode failure, return true. */ + bool valid = this->decode_success; + CheatVmOpcode opcode = {}; + ON_SCOPE_EXIT { + this->decode_success &= valid; + if (valid) { + *out = opcode; + } + }; + + /* If we have ever seen a decode failure, don't decode any more. */ + if (!valid) { + return valid; + } + + /* Validate instruction pointer. */ + if (this->instruction_ptr >= this->num_opcodes) { + valid = false; + return valid; + } + + /* Read opcode. */ + const u32 first_dword = this->program[this->instruction_ptr++]; + opcode.opcode = (CheatVmOpcodeType)(((first_dword >> 28) & 0xF)); + + switch (opcode.opcode) { + case CheatVmOpcodeType_StoreStatic: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_BeginConditionalBlock: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_EndConditionalBlock: + { + /* There's actually nothing left to process here! */ + } + break; + case CheatVmOpcodeType_ControlLoop: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_LoadRegisterStatic: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_LoadRegisterMemory: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_StoreToRegisterAddress: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_PerformArithmeticStatic: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_BeginKeypressConditionalBlock: + { + /* TODO */ + } + break; + case CheatVmOpcodeType_PerformArithmeticRegister: + { + /* TODO */ + } + break; + default: + /* Unrecognized instruction cannot be decoded. */ + valid = false; + break; + } + + /* End decoding. */ + return valid; } void DmntCheatVm::SkipConditionalBlock() { @@ -64,6 +146,15 @@ u64 DmntCheatVm::GetCheatProcessAddress(const CheatProcessMetadata* metadata, Me } } +void DmntCheatVm::ResetState() { + for (size_t i = 0; i < DmntCheatVm::NumRegisters; i++) { + this->registers[i] = 0; + this->loop_tops[i] = 0; + } + this->instruction_ptr = 0; + this->decode_success = true; +} + void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { CheatVmOpcode cur_opcode; u64 kDown = 0; @@ -71,10 +162,7 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { /* TODO: Get Keys down. */ /* Clear VM state. */ - for (size_t i = 0; i < DmntCheatVm::NumRegisters; i++) { - this->registers[i] = 0; - this->loop_tops[i] = 0; - } + this->ResetState(); /* Loop until program finishes. */ while (this->DecodeNextOpcode(&cur_opcode)) { diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 705f26a4a..089870e58 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -162,12 +162,14 @@ class DmntCheatVm { private: size_t num_opcodes = 0; size_t instruction_ptr = 0; + bool decode_success = false; u32 program[MaximumProgramOpcodeCount] = {0}; u64 registers[NumRegisters] = {0}; size_t loop_tops[NumRegisters] = {0}; private: bool DecodeNextOpcode(CheatVmOpcode *out); void SkipConditionalBlock(); + void ResetState(); static u64 GetVmInt(VmInt value, u32 bit_width); static u64 GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address); diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index e4321328f..bea0dfffb 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -57,6 +57,8 @@ void __libnx_initheap(void) { void __appInit(void) { Result rc; + SetFirmwareVersionForLibnx(); + rc = smInitialize(); if (R_FAILED(rc)) { fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM)); @@ -133,7 +135,11 @@ int main(int argc, char **argv) auto server_manager = new WaitableManager(5); /* Create services. */ - server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("dmnt:-", 4)); + + /* TODO: Implement rest of dmnt:- in ams.tma development branch. */ + /* server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("dmnt:-", 4)); */ + + server_manager->AddWaitable(new ServiceServer<DmntCheatService>("dmnt:cht", 1)); /* Loop forever, servicing our services. */ From afae7eaa113b41cbbdacad61b2b70bbf0f565042 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 3 Mar 2019 09:09:21 -0800 Subject: [PATCH 472/489] dmnt-cheat: finish vm instruction decoder --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 122 +++++++++++++++++---- 1 file changed, 103 insertions(+), 19 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index 979c61f2e..c73b7b7ba 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -20,7 +20,7 @@ #include "dmnt_cheat_manager.hpp" bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { - /* If we've ever seen a decode failure, return true. */ + /* If we've ever seen a decode failure, return false. */ bool valid = this->decode_success; CheatVmOpcode opcode = {}; ON_SCOPE_EXIT { @@ -30,70 +30,154 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { } }; - /* If we have ever seen a decode failure, don't decode any more. */ + /* Helper function for getting instruction dwords. */ + auto GetNextDword = [&]() { + if (this->instruction_ptr >= this->num_opcodes) { + valid = false; + return static_cast<u32>(0); + } + return this->program[this->instruction_ptr++]; + }; + + /* Helper function for parsing a VmInt. */ + auto GetNextVmInt = [&](const u32 bit_width) { + VmInt val = {0}; + + const u32 first_dword = GetNextDword(); + switch (bit_width) { + case 1: + val.bit8 = (u8)first_dword; + break; + case 2: + val.bit16 = (u16)first_dword; + break; + case 4: + val.bit32 = first_dword; + break; + case 8: + val.bit64 = (((u64)first_dword) << 32ul) | ((u64)GetNextDword()); + break; + } + + return val; + }; + + /* Read opcode. */ + const u32 first_dword = GetNextDword(); if (!valid) { return valid; } - /* Validate instruction pointer. */ - if (this->instruction_ptr >= this->num_opcodes) { - valid = false; - return valid; - } - - /* Read opcode. */ - const u32 first_dword = this->program[this->instruction_ptr++]; opcode.opcode = (CheatVmOpcodeType)(((first_dword >> 28) & 0xF)); switch (opcode.opcode) { case CheatVmOpcodeType_StoreStatic: { - /* TODO */ + /* 0TMR00AA AAAAAAAA YYYYYYYY (YYYYYYYY) */ + /* Read additional words. */ + const u32 second_dword = GetNextDword(); + opcode.store_static.bit_width = (first_dword >> 24) & 0xF; + opcode.store_static.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF); + opcode.store_static.offset_register = ((first_dword >> 16) & 0xF); + opcode.store_static.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword); + opcode.store_static.value = GetNextVmInt(opcode.store_static.bit_width); } break; case CheatVmOpcodeType_BeginConditionalBlock: { - /* TODO */ + /* 1TMC00AA AAAAAAAA YYYYYYYY (YYYYYYYY) */ + /* Read additional words. */ + const u32 second_dword = GetNextDword(); + opcode.begin_cond.bit_width = (first_dword >> 24) & 0xF; + opcode.begin_cond.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF); + opcode.begin_cond.cond_type = (ConditionalComparisonType)((first_dword >> 16) & 0xF); + opcode.begin_cond.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword); + opcode.begin_cond.value = GetNextVmInt(opcode.store_static.bit_width); } break; case CheatVmOpcodeType_EndConditionalBlock: { + /* 20000000 */ /* There's actually nothing left to process here! */ } break; case CheatVmOpcodeType_ControlLoop: { - /* TODO */ + /* 300R0000 VVVVVVVV */ + /* 310R0000 */ + /* Parse register, whether loop start or loop end. */ + opcode.ctrl_loop.start_loop = ((first_dword >> 24) & 0xF) == 0; + opcode.ctrl_loop.reg_index = ((first_dword >> 20) & 0xF); + + /* Read number of iters if loop start. */ + if (opcode.ctrl_loop.start_loop) { + opcode.ctrl_loop.num_iters = GetNextDword(); + } } break; case CheatVmOpcodeType_LoadRegisterStatic: { - /* TODO */ + /* 400R0000 VVVVVVVV VVVVVVVV */ + /* Read additional words. */ + opcode.ldr_static.reg_index = ((first_dword >> 20) & 0xF); + opcode.ldr_static.value = (((u64)GetNextDword()) << 32ul) | ((u64)GetNextDword()); } break; case CheatVmOpcodeType_LoadRegisterMemory: { - /* TODO */ + /* 5TMRI0AA AAAAAAAA */ + /* Read additional words. */ + const u32 second_dword = GetNextDword(); + opcode.ldr_memory.bit_width = (first_dword >> 24) & 0xF; + opcode.ldr_memory.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF); + opcode.ldr_memory.reg_index = ((first_dword >> 16) & 0xF); + opcode.ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF) == 0; + opcode.ldr_memory.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword); } break; case CheatVmOpcodeType_StoreToRegisterAddress: { - /* TODO */ + /* 6T0RIor0 VVVVVVVV VVVVVVVV */ + /* Read additional words. */ + opcode.str_regaddr.bit_width = (first_dword >> 24) & 0xF; + opcode.str_regaddr.reg_index = ((first_dword >> 16) & 0xF); + opcode.str_regaddr.increment_reg = ((first_dword >> 12) & 0xF) == 0; + opcode.str_regaddr.add_offset_reg = ((first_dword >> 8) & 0xF) == 0; + opcode.str_regaddr.offset_reg_index = ((first_dword >> 4) & 0xF); + opcode.str_regaddr.value = (((u64)GetNextDword()) << 32ul) | ((u64)GetNextDword()); } break; case CheatVmOpcodeType_PerformArithmeticStatic: { - /* TODO */ + /* 7T0RC000 VVVVVVVV */ + /* Read additional words. */ + opcode.perform_math_static.bit_width = (first_dword >> 24) & 0xF; + opcode.perform_math_static.reg_index = ((first_dword >> 16) & 0xF); + opcode.perform_math_static.math_type = (RegisterArithmeticType)((first_dword >> 12) & 0xF); + opcode.perform_math_static.value = GetNextDword(); } break; case CheatVmOpcodeType_BeginKeypressConditionalBlock: { - /* TODO */ + /* 8kkkkkkk */ + /* Just parse the mask. */ + opcode.begin_keypress_cond.key_mask = first_dword & 0x0FFFFFFF; } break; case CheatVmOpcodeType_PerformArithmeticRegister: { - /* TODO */ + /* 9TCRSIs0 (VVVVVVVV (VVVVVVVV)) */ + opcode.perform_math_reg.bit_width = (first_dword >> 24) & 0xF; + opcode.perform_math_reg.math_type = (RegisterArithmeticType)((first_dword >> 20) & 0xF); + opcode.perform_math_reg.dst_reg_index = ((first_dword >> 16) & 0xF); + opcode.perform_math_reg.src_reg_1_index = ((first_dword >> 12) & 0xF); + opcode.perform_math_reg.has_immediate = ((first_dword >> 8) & 0xF) == 0; + if (opcode.perform_math_reg.has_immediate) { + opcode.perform_math_reg.src_reg_2_index = 0; + opcode.perform_math_reg.value = GetNextVmInt(opcode.perform_math_reg.bit_width); + } else { + opcode.perform_math_reg.src_reg_2_index = ((first_dword >> 4) & 0xF); + } } break; default: From 8d140d835a3cbbd6b23abbe0fca19bcadd462aac Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 3 Mar 2019 23:42:52 -0800 Subject: [PATCH 473/489] dmnt-cheat: fix compat --- stratosphere/dmnt/dmnt.json | 3 ++- .../dmnt/source/dmnt_cheat_manager.cpp | 20 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/stratosphere/dmnt/dmnt.json b/stratosphere/dmnt/dmnt.json index cbf0e4e6c..a0aeb6355 100644 --- a/stratosphere/dmnt/dmnt.json +++ b/stratosphere/dmnt/dmnt.json @@ -106,7 +106,8 @@ "svcReadDebugProcessMemory": "0x6a", "svcWriteDebugProcessMemory": "0x6b", "svcSetHardwareBreakPoint": "0x6c", - "svcGetDebugThreadParam": "0x6d" + "svcGetDebugThreadParam": "0x6d", + "svcCallSecureMonitor": "0x7f" } }, { "type": "min_kernel_version", diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index cdd2e15ff..7272c4448 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -63,8 +63,8 @@ bool DmntCheatManager::HasActiveCheatProcess() { void DmntCheatManager::ContinueCheatProcess() { if (HasActiveCheatProcess()) { /* Loop getting debug events. */ - u8 tmp; - while (R_SUCCEEDED(svcGetDebugEvent(&tmp, g_cheat_process_debug_hnd))) { + u64 debug_event_buf[0x50]; + while (R_SUCCEEDED(svcGetDebugEvent((u8 *)debug_event_buf, g_cheat_process_debug_hnd))) { /* ... */ } @@ -130,6 +130,13 @@ static void PopulateMemoryExtents(MemoryRegionExtents *extents, Handle p_h, u64 } } +static void StartDebugProcess(u64 pid) { + Result rc = pmdmntStartProcess(pid); + if (R_FAILED(rc)) { + fatalSimple(rc); + } +} + void DmntCheatManager::OnNewApplicationLaunch() { std::scoped_lock<HosMutex> lk(g_cheat_lock); Result rc; @@ -166,7 +173,7 @@ void DmntCheatManager::OnNewApplicationLaunch() { { LoaderModuleInfo proc_modules[2]; u32 num_modules; - if (R_FAILED((rc = ldrDmntGetModuleInfos(g_cheat_process_metadata.process_id, proc_modules, 2, &num_modules)))) { + if (R_FAILED((rc = ldrDmntGetModuleInfos(g_cheat_process_metadata.process_id, proc_modules, sizeof(proc_modules), &num_modules)))) { fatalSimple(rc); } @@ -174,6 +181,7 @@ void DmntCheatManager::OnNewApplicationLaunch() { /* If we only have one, we must be e.g. mitming HBL. */ /* We don't want to fuck with HBL. */ if (num_modules != 2) { + StartDebugProcess(g_cheat_process_metadata.process_id); g_cheat_process_metadata.process_id = 0; return; } @@ -182,14 +190,18 @@ void DmntCheatManager::OnNewApplicationLaunch() { g_cheat_process_metadata.main_nso_extents.size = proc_modules[1].size; memcpy(g_cheat_process_metadata.main_nso_build_id, proc_modules[1].build_id, sizeof(g_cheat_process_metadata.main_nso_build_id)); } - + /* TODO: Read cheats off the SD. */ + /* Open a debug handle. */ if (R_FAILED((rc = svcDebugActiveProcess(&g_cheat_process_debug_hnd, g_cheat_process_metadata.process_id)))) { fatalSimple(rc); } + /* Start the process. */ + StartDebugProcess(g_cheat_process_metadata.process_id); + /* Continue debug events, etc. */ ContinueCheatProcess(); From f2f25dd5ed21ff1881048e6eebbee2c189ceff72 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Sun, 3 Mar 2019 23:53:53 -0800 Subject: [PATCH 474/489] atmosphere: launch tma (fixes home button) --- stratosphere/pm/source/pm_boot2.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stratosphere/pm/source/pm_boot2.cpp b/stratosphere/pm/source/pm_boot2.cpp index fc739c88e..a7cdd8e3a 100644 --- a/stratosphere/pm/source/pm_boot2.cpp +++ b/stratosphere/pm/source/pm_boot2.cpp @@ -235,6 +235,9 @@ void EmbeddedBoot2::Main() { /* Launch usb. */ LaunchTitle(Boot2KnownTitleId::usb, FsStorageId_NandSystem, 0, NULL); + + /* Launch tma. */ + LaunchTitle(Boot2KnownTitleId::tma, FsStorageId_NandSystem, 0, NULL); /* Launch Atmosphere dmnt, using FsStorageId_None to force SD card boot. */ LaunchTitle(Boot2KnownTitleId::dmnt, FsStorageId_None, 0, NULL); From e8a5aa81f41c63136e213c5128e7efff75e74f58 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 01:41:01 -0800 Subject: [PATCH 475/489] dmnt-cheat: fix decode error, add debug logging --- .../dmnt/source/dmnt_cheat_manager.cpp | 1 - stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 136 +++++++++++++++++- stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 11 ++ 3 files changed, 143 insertions(+), 5 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 7272c4448..ddb743561 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -193,7 +193,6 @@ void DmntCheatManager::OnNewApplicationLaunch() { /* TODO: Read cheats off the SD. */ - /* Open a debug handle. */ if (R_FAILED((rc = svcDebugActiveProcess(&g_cheat_process_debug_hnd, g_cheat_process_metadata.process_id)))) { fatalSimple(rc); diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index c73b7b7ba..9f056f562 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -19,6 +19,119 @@ #include "dmnt_cheat_vm.hpp" #include "dmnt_cheat_manager.hpp" + +void DmntCheatVm::OpenDebugLogFile() { + #ifdef DMNT_CHEAT_VM_DEBUG_LOG + CloseDebugLogFile(); + this->debug_log_file = fopen("cheat_vm_log.txt", "wb"); + #endif +} + +void DmntCheatVm::CloseDebugLogFile() { + #ifdef DMNT_CHEAT_VM_DEBUG_LOG + if (this->debug_log_file != NULL) { + fclose(this->debug_log_file); + this->debug_log_file = NULL; + } + #endif +} + +void DmntCheatVm::LogToDebugFile(const char *format, ...) { + #ifdef DMNT_CHEAT_VM_DEBUG_LOG + if (this->debug_log_file != NULL) { + va_list arglist; + va_start(arglist, format); + vfprintf(this->debug_log_file, format, arglist); + va_end(arglist); + } + #endif +} + +void DmntCheatVm::LogOpcode(const CheatVmOpcode *opcode) { + #ifndef DMNT_CHEAT_VM_DEBUG_LOG + return; + #endif + switch (opcode->opcode) { + case CheatVmOpcodeType_StoreStatic: + this->LogToDebugFile("Opcode: Store Static\n"); + this->LogToDebugFile("Bit Width: %x\n", opcode->store_static.bit_width); + this->LogToDebugFile("Mem Type: %x\n", opcode->store_static.mem_type); + this->LogToDebugFile("Reg Idx: %x\n", opcode->store_static.offset_register); + this->LogToDebugFile("Rel Addr: %lx\n", opcode->store_static.rel_address); + this->LogToDebugFile("Value: %lx\n", opcode->store_static.value.bit64); + break; + case CheatVmOpcodeType_BeginConditionalBlock: + this->LogToDebugFile("Opcode: Begin Conditional\n"); + this->LogToDebugFile("Bit Width: %x\n", opcode->begin_cond.bit_width); + this->LogToDebugFile("Mem Type: %x\n", opcode->begin_cond.mem_type); + this->LogToDebugFile("Cond Type: %x\n", opcode->begin_cond.cond_type); + this->LogToDebugFile("Rel Addr: %lx\n", opcode->begin_cond.rel_address); + this->LogToDebugFile("Value: %lx\n", opcode->begin_cond.value.bit64); + break; + case CheatVmOpcodeType_EndConditionalBlock: + this->LogToDebugFile("Opcode: End Conditional\n"); + break; + case CheatVmOpcodeType_ControlLoop: + if (opcode->ctrl_loop.start_loop) { + this->LogToDebugFile("Opcode: Start Loop\n"); + this->LogToDebugFile("Reg Idx: %x\n", opcode->ctrl_loop.reg_index); + this->LogToDebugFile("Num Iters: %x\n", opcode->ctrl_loop.num_iters); + } else { + this->LogToDebugFile("Opcode: End Loop\n"); + this->LogToDebugFile("Reg Idx: %x\n", opcode->ctrl_loop.reg_index); + } + break; + case CheatVmOpcodeType_LoadRegisterStatic: + this->LogToDebugFile("Opcode: Load Register Static\n"); + this->LogToDebugFile("Reg Idx: %x\n", opcode->ldr_static.reg_index); + this->LogToDebugFile("Value: %lx\n", opcode->ldr_static.value); + break; + case CheatVmOpcodeType_LoadRegisterMemory: + this->LogToDebugFile("Opcode: Load Register Memory\n"); + this->LogToDebugFile("Bit Width: %x\n", opcode->ldr_memory.bit_width); + this->LogToDebugFile("Reg Idx: %x\n", opcode->ldr_memory.reg_index); + this->LogToDebugFile("Mem Type: %x\n", opcode->ldr_memory.mem_type); + this->LogToDebugFile("From Reg: %d\n", opcode->ldr_memory.load_from_reg); + this->LogToDebugFile("Rel Addr: %lx\n", opcode->ldr_memory.rel_address); + break; + case CheatVmOpcodeType_StoreToRegisterAddress: + this->LogToDebugFile("Opcode: Store Static to Register Address\n"); + this->LogToDebugFile("Bit Width: %x\n", opcode->str_regaddr.bit_width); + this->LogToDebugFile("Reg Idx: %x\n", opcode->str_regaddr.reg_index); + if (opcode->str_regaddr.add_offset_reg) { + this->LogToDebugFile("O Reg Idx: %x\n", opcode->str_regaddr.offset_reg_index); + } + this->LogToDebugFile("Incr Reg: %d\n", opcode->str_regaddr.increment_reg); + this->LogToDebugFile("Value: %lx\n", opcode->str_regaddr.value); + break; + case CheatVmOpcodeType_PerformArithmeticStatic: + this->LogToDebugFile("Opcode: Perform Static Arithmetic\n"); + this->LogToDebugFile("Bit Width: %x\n", opcode->perform_math_static.bit_width); + this->LogToDebugFile("Reg Idx: %x\n", opcode->perform_math_static.reg_index); + this->LogToDebugFile("Math Type: %x\n", opcode->perform_math_static.math_type); + this->LogToDebugFile("Value: %lx\n", opcode->perform_math_static.value); + break; + case CheatVmOpcodeType_BeginKeypressConditionalBlock: + this->LogToDebugFile("Opcode: Begin Keypress Conditional\n"); + this->LogToDebugFile("Key Mask: %x\n", opcode->begin_keypress_cond.key_mask); + break; + case CheatVmOpcodeType_PerformArithmeticRegister: + this->LogToDebugFile("Opcode: Perform Register Arithmetic\n"); + this->LogToDebugFile("Bit Width: %x\n", opcode->perform_math_reg.bit_width); + this->LogToDebugFile("Dst Idx: %x\n", opcode->perform_math_reg.dst_reg_index); + this->LogToDebugFile("Src1 Idx: %x\n", opcode->perform_math_reg.src_reg_1_index); + if (opcode->perform_math_reg.has_immediate) { + this->LogToDebugFile("Value: %lx\n", opcode->perform_math_reg.value.bit64); + } else { + this->LogToDebugFile("Src2 Idx: %x\n", opcode->perform_math_reg.src_reg_2_index); + } + break; + default: + this->LogToDebugFile("Unknown opcode: %x\n", opcode->opcode); + break; + } +} + bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { /* If we've ever seen a decode failure, return false. */ bool valid = this->decode_success; @@ -131,7 +244,7 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { opcode.ldr_memory.bit_width = (first_dword >> 24) & 0xF; opcode.ldr_memory.mem_type = (MemoryAccessType)((first_dword >> 20) & 0xF); opcode.ldr_memory.reg_index = ((first_dword >> 16) & 0xF); - opcode.ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF) == 0; + opcode.ldr_memory.load_from_reg = ((first_dword >> 12) & 0xF) != 0; opcode.ldr_memory.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword); } break; @@ -141,8 +254,8 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { /* Read additional words. */ opcode.str_regaddr.bit_width = (first_dword >> 24) & 0xF; opcode.str_regaddr.reg_index = ((first_dword >> 16) & 0xF); - opcode.str_regaddr.increment_reg = ((first_dword >> 12) & 0xF) == 0; - opcode.str_regaddr.add_offset_reg = ((first_dword >> 8) & 0xF) == 0; + opcode.str_regaddr.increment_reg = ((first_dword >> 12) & 0xF) != 0; + opcode.str_regaddr.add_offset_reg = ((first_dword >> 8) & 0xF) != 0; opcode.str_regaddr.offset_reg_index = ((first_dword >> 4) & 0xF); opcode.str_regaddr.value = (((u64)GetNextDword()) << 32ul) | ((u64)GetNextDword()); } @@ -171,7 +284,7 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { opcode.perform_math_reg.math_type = (RegisterArithmeticType)((first_dword >> 20) & 0xF); opcode.perform_math_reg.dst_reg_index = ((first_dword >> 16) & 0xF); opcode.perform_math_reg.src_reg_1_index = ((first_dword >> 12) & 0xF); - opcode.perform_math_reg.has_immediate = ((first_dword >> 8) & 0xF) == 0; + opcode.perform_math_reg.has_immediate = ((first_dword >> 8) & 0xF) != 0; if (opcode.perform_math_reg.has_immediate) { opcode.perform_math_reg.src_reg_2_index = 0; opcode.perform_math_reg.value = GetNextVmInt(opcode.perform_math_reg.bit_width); @@ -245,11 +358,26 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { /* TODO: Get Keys down. */ + + this->OpenDebugLogFile(); + ON_SCOPE_EXIT { this->CloseDebugLogFile(); }; + + this->LogToDebugFile("Started VM execution.\n"); + this->LogToDebugFile("Main NSO: %012lx\n", metadata->main_nso_extents.base); + this->LogToDebugFile("Heap: %012lx\n", metadata->main_nso_extents.base); + /* Clear VM state. */ this->ResetState(); /* Loop until program finishes. */ while (this->DecodeNextOpcode(&cur_opcode)) { + this->LogToDebugFile("Instruction Ptr: %04x\n", (u32)this->instruction_ptr); + + for (size_t i = 0; i < NumRegisters; i++) { + this->LogToDebugFile("Registers[%02x]: %016lx\n", i, this->registers[i]); + } + this->LogOpcode(&cur_opcode); + switch (cur_opcode.opcode) { case CheatVmOpcodeType_StoreStatic: { diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 089870e58..2dbc4cbc4 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -16,6 +16,7 @@ #pragma once #include <switch.h> +#include <stdarg.h> #include <stratosphere.hpp> #include "dmnt_cheat_types.hpp" @@ -171,6 +172,12 @@ class DmntCheatVm { void SkipConditionalBlock(); void ResetState(); + /* For debugging. These will be IFDEF'd out normally. */ + void OpenDebugLogFile(); + void CloseDebugLogFile(); + void LogToDebugFile(const char *format, ...); + void LogOpcode(const CheatVmOpcode *opcode); + static u64 GetVmInt(VmInt value, u32 bit_width); static u64 GetCheatProcessAddress(const CheatProcessMetadata* metadata, MemoryAccessType mem_type, u64 rel_address); public: @@ -181,4 +188,8 @@ class DmntCheatVm { } void Execute(const CheatProcessMetadata *metadata); +#ifdef DMNT_CHEAT_VM_DEBUG_LOG + private: + FILE *debug_log_file = NULL; +#endif }; From ef68881e5c2327f12d91083dac6ba68cb12fcdec Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 05:56:44 -0800 Subject: [PATCH 476/489] dmnt-cheat: Implement memory service cmds --- .../dmnt/source/dmnt_cheat_manager.cpp | 80 +++++++++++++++++-- .../dmnt/source/dmnt_cheat_manager.hpp | 4 + .../dmnt/source/dmnt_cheat_service.cpp | 38 +++++++-- .../dmnt/source/dmnt_cheat_service.hpp | 3 + stratosphere/dmnt/source/dmnt_cheat_types.hpp | 2 + stratosphere/dmnt/source/dmnt_results.hpp | 27 +++++++ 6 files changed, 140 insertions(+), 14 deletions(-) create mode 100644 stratosphere/dmnt/source/dmnt_results.hpp diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index ddb743561..40be7a440 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -82,8 +82,7 @@ Result DmntCheatManager::ReadCheatProcessMemoryForVm(u64 proc_addr, void *out_da return svcReadDebugProcessMemory(out_data, g_cheat_process_debug_hnd, proc_addr, size); } - /* TODO: Return value... */ - return 0x20F; + return ResultDmntCheatNotAttached; } Result DmntCheatManager::WriteCheatProcessMemoryForVm(u64 proc_addr, const void *data, size_t size) { @@ -91,8 +90,67 @@ Result DmntCheatManager::WriteCheatProcessMemoryForVm(u64 proc_addr, const void return svcWriteDebugProcessMemory(g_cheat_process_debug_hnd, data, proc_addr, size); } - /* TODO: Return value... */ - return 0x20F; + return ResultDmntCheatNotAttached; +} + + +Result DmntCheatManager::GetCheatProcessMappingCount(u64 *out_count) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + MemoryInfo mem_info; + + u64 address = 0; + *out_count = 0; + do { + mem_info.perm = 0; + u32 tmp; + if (R_FAILED(svcQueryDebugProcessMemory(&mem_info, &tmp, g_cheat_process_debug_hnd, address))) { + break; + } + + if (mem_info.perm != 0) { + *out_count += 1; + } + + address = mem_info.addr + mem_info.size; + } while (address != 0); + + return 0; +} + +Result DmntCheatManager::GetCheatProcessMappings(MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + MemoryInfo mem_info; + u64 address = 0; + u64 count = 0; + *out_count = 0; + do { + mem_info.perm = 0; + u32 tmp; + if (R_FAILED(svcQueryDebugProcessMemory(&mem_info, &tmp, g_cheat_process_debug_hnd, address))) { + break; + } + + if (mem_info.perm != 0) { + count++; + if (count > offset) { + mappings[(*out_count)++] = mem_info; + } + } + + address = mem_info.addr + mem_info.size; + } while (address != 0 && *out_count < max_count); + + return 0; } Result DmntCheatManager::ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size) { @@ -107,6 +165,17 @@ Result DmntCheatManager::WriteCheatProcessMemory(u64 proc_addr, const void *data return WriteCheatProcessMemoryForVm(proc_addr, data, size); } +Result DmntCheatManager::QueryCheatProcessMemory(MemoryInfo *mapping, u64 address) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (HasActiveCheatProcess()) { + u32 tmp; + return svcQueryDebugProcessMemory(mapping, &tmp, g_cheat_process_debug_hnd, address); + } + + return ResultDmntCheatNotAttached; +} + Handle DmntCheatManager::PrepareDebugNextApplication() { Result rc; Handle event_h; @@ -263,8 +332,7 @@ Result DmntCheatManager::GetCheatProcessMetadata(CheatProcessMetadata *out) { return 0; } - /* TODO: Decide on a set of return values... */ - return 0x20F; + return ResultDmntCheatNotAttached; } void DmntCheatManager::InitializeCheatManager() { diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index 5d7518ae6..c46a5f86b 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -37,8 +37,12 @@ class DmntCheatManager { static Result ReadCheatProcessMemoryForVm(u64 proc_addr, void *out_data, size_t size); static Result WriteCheatProcessMemoryForVm(u64 proc_addr, const void *data, size_t size); + + static Result GetCheatProcessMappingCount(u64 *out_count); + static Result GetCheatProcessMappings(MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset); static Result ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size); static Result WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size); + static Result QueryCheatProcessMemory(MemoryInfo *mapping, u64 address); static void InitializeCheatManager(); }; diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp index b67422344..af41d8041 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -32,23 +32,45 @@ Result DmntCheatService::GetCheatProcessMetadata(Out<CheatProcessMetadata> out_m Result DmntCheatService::GetCheatProcessMappingCount(Out<u64> out_count) { - /* TODO */ - return 0xF601; + return DmntCheatManager::GetCheatProcessMappingCount(out_count.GetPointer()); } Result DmntCheatService::GetCheatProcessMappings(OutBuffer<MemoryInfo> mappings, Out<u64> out_count, u64 offset) { - /* TODO */ - return 0xF601; + if (mappings.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + return DmntCheatManager::GetCheatProcessMappings(mappings.buffer, mappings.num_elements, out_count.GetPointer(), offset); } Result DmntCheatService::ReadCheatProcessMemory(OutBuffer<u8> buffer, u64 address, u64 out_size) { - /* TODO */ - return 0xF601; + if (buffer.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + u64 sz = out_size; + if (buffer.num_elements < sz) { + sz = buffer.num_elements; + } + + return DmntCheatManager::ReadCheatProcessMemory(address, buffer.buffer, sz); } Result DmntCheatService::WriteCheatProcessMemory(InBuffer<u8> buffer, u64 address, u64 in_size) { - /* TODO */ - return 0xF601; + if (buffer.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + u64 sz = in_size; + if (buffer.num_elements < sz) { + sz = buffer.num_elements; + } + + return DmntCheatManager::WriteCheatProcessMemory(address, buffer.buffer, sz); +} + +Result DmntCheatService::QueryCheatProcessMemory(Out<MemoryInfo> mapping, u64 address) { + return DmntCheatManager::QueryCheatProcessMemory(mapping.GetPointer(), address); } diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.hpp b/stratosphere/dmnt/source/dmnt_cheat_service.hpp index 02aca63d5..6a95dc0e9 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.hpp @@ -31,6 +31,7 @@ enum DmntCheatCmd { DmntCheat_Cmd_GetCheatProcessMappings = 65101, DmntCheat_Cmd_ReadCheatProcessMemory = 65102, DmntCheat_Cmd_WriteCheatProcessMemory = 65103, + DmntCheat_Cmd_QueryCheatProcessMemory = 65104, /* Interact with Cheats */ DmntCheat_Cmd_GetCheatCount = 65200, @@ -56,6 +57,7 @@ class DmntCheatService final : public IServiceObject { Result GetCheatProcessMappings(OutBuffer<MemoryInfo> mappings, Out<u64> out_count, u64 offset); Result ReadCheatProcessMemory(OutBuffer<u8> buffer, u64 address, u64 out_size); Result WriteCheatProcessMemory(InBuffer<u8> buffer, u64 address, u64 in_size); + Result QueryCheatProcessMemory(Out<MemoryInfo> mapping, u64 address); Result GetCheatCount(Out<u64> out_count); Result GetCheats(OutBuffer<CheatEntry> cheats, Out<u64> out_count, u64 offset); @@ -78,6 +80,7 @@ class DmntCheatService final : public IServiceObject { MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessMappings, &DmntCheatService::GetCheatProcessMappings>(), MakeServiceCommandMeta<DmntCheat_Cmd_ReadCheatProcessMemory, &DmntCheatService::ReadCheatProcessMemory>(), MakeServiceCommandMeta<DmntCheat_Cmd_WriteCheatProcessMemory, &DmntCheatService::WriteCheatProcessMemory>(), + MakeServiceCommandMeta<DmntCheat_Cmd_QueryCheatProcessMemory, &DmntCheatService::QueryCheatProcessMemory>(), MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatCount, &DmntCheatService::GetCheatCount>(), MakeServiceCommandMeta<DmntCheat_Cmd_GetCheats, &DmntCheatService::GetCheats>(), diff --git a/stratosphere/dmnt/source/dmnt_cheat_types.hpp b/stratosphere/dmnt/source/dmnt_cheat_types.hpp index 4e7a4602e..73979badf 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_types.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_types.hpp @@ -18,6 +18,8 @@ #include <switch.h> #include <stratosphere.hpp> +#include "dmnt_results.hpp" + struct MemoryRegionExtents { u64 base; u64 size; diff --git a/stratosphere/dmnt/source/dmnt_results.hpp b/stratosphere/dmnt/source/dmnt_results.hpp new file mode 100644 index 000000000..5be79a674 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_results.hpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> +#include <stratosphere.hpp> + +static constexpr u32 Module_Dmnt = 13; + +static constexpr Result ResultDmntUnknown = MAKERESULT(Module_Dmnt, 1); +static constexpr Result ResultDmntDebuggingDisabled = MAKERESULT(Module_Dmnt, 2); + +static constexpr Result ResultDmntCheatNotAttached = MAKERESULT(Module_Dmnt, 6500); +static constexpr Result ResultDmntCheatNullBuffer = MAKERESULT(Module_Dmnt, 6501); \ No newline at end of file From 37d35770283fff3568d01422983823338c38d047 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 06:55:37 -0800 Subject: [PATCH 477/489] dmnt: allow disabling cheats via title-specific button combo --- common/defaults/loader.ini | 3 +- docs/modules/pm.md | 2 +- stratosphere/ams_mitm/source/utils.cpp | 2 +- .../dmnt/source/dmnt_cheat_manager.cpp | 86 +++++- .../dmnt/source/dmnt_cheat_manager.hpp | 1 + .../dmnt/source/dmnt_cheat_service.cpp | 10 + .../dmnt/source/dmnt_cheat_service.hpp | 3 + stratosphere/dmnt/source/dmnt_cheat_types.hpp | 1 + stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 10 +- stratosphere/dmnt/source/dmnt_config.cpp | 157 ++++++++++ stratosphere/dmnt/source/dmnt_config.hpp | 31 ++ stratosphere/dmnt/source/dmnt_hid.cpp | 32 +++ stratosphere/dmnt/source/dmnt_hid.hpp | 23 ++ stratosphere/dmnt/source/dmnt_main.cpp | 4 + stratosphere/dmnt/source/ini.c | 269 ++++++++++++++++++ stratosphere/dmnt/source/ini.h | 130 +++++++++ stratosphere/dmnt/source/pm_shim.c | 12 +- stratosphere/dmnt/source/pm_shim.h | 2 +- .../loader/source/ldr_content_management.cpp | 4 +- stratosphere/pm/source/pm_debug_monitor.cpp | 5 +- stratosphere/pm/source/pm_debug_monitor.hpp | 6 +- 21 files changed, 775 insertions(+), 18 deletions(-) create mode 100644 stratosphere/dmnt/source/dmnt_config.cpp create mode 100644 stratosphere/dmnt/source/dmnt_config.hpp create mode 100644 stratosphere/dmnt/source/dmnt_hid.cpp create mode 100644 stratosphere/dmnt/source/dmnt_hid.hpp create mode 100644 stratosphere/dmnt/source/ini.c create mode 100644 stratosphere/dmnt/source/ini.h diff --git a/common/defaults/loader.ini b/common/defaults/loader.ini index a1df9025b..d488f21b4 100644 --- a/common/defaults/loader.ini +++ b/common/defaults/loader.ini @@ -4,4 +4,5 @@ path=atmosphere/hbl.nsp override_key=!R [default_config] -override_key=!L \ No newline at end of file +override_key=!L +cheat_enable_key=!L \ No newline at end of file diff --git a/docs/modules/pm.md b/docs/modules/pm.md index fe00ee18a..288fdf355 100644 --- a/docs/modules/pm.md +++ b/docs/modules/pm.md @@ -14,7 +14,7 @@ The SwIPC definition for this command follows. ``` interface nn::pm::detail::IDebugMonitorInterface is pm:dmnt { ... - [65000] AtmosphereGetProcessHandle(u64 pid) -> handle<copy, process> process_handle; + [65000] AtmosphereGetProcessInfo(u64 pid) -> handle<copy, process> process_handle, u64 title_id, u64 storage_id; } ``` diff --git a/stratosphere/ams_mitm/source/utils.cpp b/stratosphere/ams_mitm/source/utils.cpp index 916bf9bf1..fef0957e8 100644 --- a/stratosphere/ams_mitm/source/utils.cpp +++ b/stratosphere/ams_mitm/source/utils.cpp @@ -49,7 +49,7 @@ struct HblOverrideConfig { static HblOverrideConfig g_hbl_override_config = { .override_key = { - .key_combination = KEY_R, + .key_combination = KEY_L, .override_by_default = true }, .title_id = 0x010000000000100D, diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 40be7a440..52556dbee 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -17,6 +17,7 @@ #include <switch.h> #include "dmnt_cheat_manager.hpp" #include "dmnt_cheat_vm.hpp" +#include "dmnt_config.hpp" #include "pm_shim.h" static HosMutex g_cheat_lock; @@ -206,6 +207,82 @@ static void StartDebugProcess(u64 pid) { } } +Result DmntCheatManager::ForceOpenCheatProcess() { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + Result rc; + + if (HasActiveCheatProcess()) { + return 0; + } + + /* Get the current application process ID. */ + if (R_FAILED((rc = pmdmntGetApplicationPid(&g_cheat_process_metadata.process_id)))) { + return rc; + } + ON_SCOPE_EXIT { if (R_FAILED(rc)) { g_cheat_process_metadata.process_id = 0; } }; + + /* Get process handle, use it to learn memory extents. */ + { + Handle proc_h = 0; + ON_SCOPE_EXIT { if (proc_h != 0) { svcCloseHandle(proc_h); } }; + + if (R_FAILED((rc = pmdmntAtmosphereGetProcessInfo(&proc_h, &g_cheat_process_metadata.title_id, nullptr, g_cheat_process_metadata.process_id)))) { + return rc; + } + + /* Get memory extents. */ + PopulateMemoryExtents(&g_cheat_process_metadata.heap_extents, proc_h, 4, 5); + PopulateMemoryExtents(&g_cheat_process_metadata.alias_extents, proc_h, 2, 3); + if (kernelAbove200()) { + PopulateMemoryExtents(&g_cheat_process_metadata.address_space_extents, proc_h, 12, 13); + } else { + g_cheat_process_metadata.address_space_extents.base = 0x08000000UL; + g_cheat_process_metadata.address_space_extents.size = 0x78000000UL; + } + } + + /* Get module information from Loader. */ + { + LoaderModuleInfo proc_modules[2]; + u32 num_modules; + if (R_FAILED((rc = ldrDmntGetModuleInfos(g_cheat_process_metadata.process_id, proc_modules, sizeof(proc_modules), &num_modules)))) { + return rc; + } + + /* All applications must have two modules. */ + /* However, this is a force-open, so we will accept one module. */ + /* Poor HBL, I guess... */ + LoaderModuleInfo *proc_module; + if (num_modules == 2) { + proc_module = &proc_modules[1]; + } else if (num_modules == 1) { + proc_module = &proc_modules[0]; + } else { + rc = ResultDmntCheatNotAttached; + return rc; + } + + g_cheat_process_metadata.main_nso_extents.base = proc_module->base_address; + g_cheat_process_metadata.main_nso_extents.size = proc_module->size; + memcpy(g_cheat_process_metadata.main_nso_build_id, proc_module->build_id, sizeof(g_cheat_process_metadata.main_nso_build_id)); + } + + /* TODO: Read cheats off the SD. */ + + /* Open a debug handle. */ + if (R_FAILED((rc = svcDebugActiveProcess(&g_cheat_process_debug_hnd, g_cheat_process_metadata.process_id)))) { + return rc; + } + + /* Continue debug events, etc. */ + ContinueCheatProcess(); + + /* Signal to our fans. */ + g_cheat_process_event->Signal(); + + return rc; +} + void DmntCheatManager::OnNewApplicationLaunch() { std::scoped_lock<HosMutex> lk(g_cheat_lock); Result rc; @@ -223,7 +300,7 @@ void DmntCheatManager::OnNewApplicationLaunch() { Handle proc_h = 0; ON_SCOPE_EXIT { if (proc_h != 0) { svcCloseHandle(proc_h); } }; - if (R_FAILED((rc = pmdmntAtmosphereGetProcessHandle(&proc_h, g_cheat_process_metadata.process_id)))) { + if (R_FAILED((rc = pmdmntAtmosphereGetProcessInfo(&proc_h, &g_cheat_process_metadata.title_id, nullptr, g_cheat_process_metadata.process_id)))) { fatalSimple(rc); } @@ -238,6 +315,13 @@ void DmntCheatManager::OnNewApplicationLaunch() { } } + /* Check if we should skip based on keys down. */ + if (!DmntConfigManager::HasCheatEnableButton(g_cheat_process_metadata.title_id)) { + StartDebugProcess(g_cheat_process_metadata.process_id); + g_cheat_process_metadata.process_id = 0; + return; + } + /* Get module information from Loader. */ { LoaderModuleInfo proc_modules[2]; diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index c46a5f86b..47408b9b9 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -34,6 +34,7 @@ class DmntCheatManager { static bool GetHasActiveCheatProcess(); static Handle GetCheatProcessEventHandle(); static Result GetCheatProcessMetadata(CheatProcessMetadata *out); + static Result ForceOpenCheatProcess(); static Result ReadCheatProcessMemoryForVm(u64 proc_addr, void *out_data, size_t size); static Result WriteCheatProcessMemoryForVm(u64 proc_addr, const void *data, size_t size); diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp index af41d8041..521a12c85 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -30,6 +30,16 @@ Result DmntCheatService::GetCheatProcessMetadata(Out<CheatProcessMetadata> out_m return DmntCheatManager::GetCheatProcessMetadata(out_metadata.GetPointer()); } +Result DmntCheatService::ForceOpenCheatProcess() { + Result rc = DmntCheatManager::ForceOpenCheatProcess(); + + if (R_FAILED(rc)) { + rc = ResultDmntCheatNotAttached; + } + + return rc; +} + Result DmntCheatService::GetCheatProcessMappingCount(Out<u64> out_count) { return DmntCheatManager::GetCheatProcessMappingCount(out_count.GetPointer()); diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.hpp b/stratosphere/dmnt/source/dmnt_cheat_service.hpp index 6a95dc0e9..a921465a0 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.hpp @@ -25,6 +25,7 @@ enum DmntCheatCmd { DmntCheat_Cmd_HasCheatProcess = 65000, DmntCheat_Cmd_GetCheatProcessEvent = 65001, DmntCheat_Cmd_GetCheatProcessMetadata = 65002, + DmntCheat_Cmd_ForceOpenCheatProcess = 65003, /* Interact with Memory */ DmntCheat_Cmd_GetCheatProcessMappingCount = 65100, @@ -52,6 +53,7 @@ class DmntCheatService final : public IServiceObject { void HasCheatProcess(Out<bool> out); void GetCheatProcessEvent(Out<CopiedHandle> out_event); Result GetCheatProcessMetadata(Out<CheatProcessMetadata> out_metadata); + Result ForceOpenCheatProcess(); Result GetCheatProcessMappingCount(Out<u64> out_count); Result GetCheatProcessMappings(OutBuffer<MemoryInfo> mappings, Out<u64> out_count, u64 offset); @@ -75,6 +77,7 @@ class DmntCheatService final : public IServiceObject { MakeServiceCommandMeta<DmntCheat_Cmd_HasCheatProcess, &DmntCheatService::HasCheatProcess>(), MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessEvent, &DmntCheatService::GetCheatProcessEvent>(), MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessMetadata, &DmntCheatService::GetCheatProcessMetadata>(), + MakeServiceCommandMeta<DmntCheat_Cmd_ForceOpenCheatProcess, &DmntCheatService::ForceOpenCheatProcess>(), MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessMappingCount, &DmntCheatService::GetCheatProcessMappingCount>(), MakeServiceCommandMeta<DmntCheat_Cmd_GetCheatProcessMappings, &DmntCheatService::GetCheatProcessMappings>(), diff --git a/stratosphere/dmnt/source/dmnt_cheat_types.hpp b/stratosphere/dmnt/source/dmnt_cheat_types.hpp index 73979badf..133baf425 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_types.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_types.hpp @@ -27,6 +27,7 @@ struct MemoryRegionExtents { struct CheatProcessMetadata { u64 process_id; + u64 title_id; MemoryRegionExtents main_nso_extents; MemoryRegionExtents heap_extents; MemoryRegionExtents alias_extents; diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index 9f056f562..821ae75e4 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -18,6 +18,7 @@ #include "dmnt_cheat_types.hpp" #include "dmnt_cheat_vm.hpp" #include "dmnt_cheat_manager.hpp" +#include "dmnt_hid.hpp" void DmntCheatVm::OpenDebugLogFile() { @@ -356,15 +357,16 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { CheatVmOpcode cur_opcode; u64 kDown = 0; - /* TODO: Get Keys down. */ - + /* Get Keys down. */ + HidManagement::GetKeysDown(&kDown); this->OpenDebugLogFile(); ON_SCOPE_EXIT { this->CloseDebugLogFile(); }; this->LogToDebugFile("Started VM execution.\n"); - this->LogToDebugFile("Main NSO: %012lx\n", metadata->main_nso_extents.base); - this->LogToDebugFile("Heap: %012lx\n", metadata->main_nso_extents.base); + this->LogToDebugFile("Main NSO: %012lx\n", metadata->main_nso_extents.base); + this->LogToDebugFile("Heap: %012lx\n", metadata->main_nso_extents.base); + this->LogToDebugFile("Keys Down: %08x\n", (u32)(kDown & 0x0FFFFFFF)); /* Clear VM state. */ this->ResetState(); diff --git a/stratosphere/dmnt/source/dmnt_config.cpp b/stratosphere/dmnt/source/dmnt_config.cpp new file mode 100644 index 000000000..cd4026a50 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_config.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <string.h> +#include <stratosphere.hpp> + +#include "dmnt_hid.hpp" +#include "dmnt_config.hpp" +#include "ini.h" + +/* Support variables. */ +static OverrideKey g_default_cheat_enable_key = { + .key_combination = KEY_L, + .override_by_default = true +}; + +/* Static buffer for loader.ini contents at runtime. */ +static char g_config_ini_data[0x800]; + +static OverrideKey ParseOverrideKey(const char *value) { + OverrideKey cfg; + + /* Parse on by default. */ + if (value[0] == '!') { + cfg.override_by_default = true; + value++; + } else { + cfg.override_by_default = false; + } + + /* Parse key combination. */ + if (strcasecmp(value, "A") == 0) { + cfg.key_combination = KEY_A; + } else if (strcasecmp(value, "B") == 0) { + cfg.key_combination = KEY_B; + } else if (strcasecmp(value, "X") == 0) { + cfg.key_combination = KEY_X; + } else if (strcasecmp(value, "Y") == 0) { + cfg.key_combination = KEY_Y; + } else if (strcasecmp(value, "LS") == 0) { + cfg.key_combination = KEY_LSTICK; + } else if (strcasecmp(value, "RS") == 0) { + cfg.key_combination = KEY_RSTICK; + } else if (strcasecmp(value, "L") == 0) { + cfg.key_combination = KEY_L; + } else if (strcasecmp(value, "R") == 0) { + cfg.key_combination = KEY_R; + } else if (strcasecmp(value, "ZL") == 0) { + cfg.key_combination = KEY_ZL; + } else if (strcasecmp(value, "ZR") == 0) { + cfg.key_combination = KEY_ZR; + } else if (strcasecmp(value, "PLUS") == 0) { + cfg.key_combination = KEY_PLUS; + } else if (strcasecmp(value, "MINUS") == 0) { + cfg.key_combination = KEY_MINUS; + } else if (strcasecmp(value, "DLEFT") == 0) { + cfg.key_combination = KEY_DLEFT; + } else if (strcasecmp(value, "DUP") == 0) { + cfg.key_combination = KEY_DUP; + } else if (strcasecmp(value, "DRIGHT") == 0) { + cfg.key_combination = KEY_DRIGHT; + } else if (strcasecmp(value, "DDOWN") == 0) { + cfg.key_combination = KEY_DDOWN; + } else if (strcasecmp(value, "SL") == 0) { + cfg.key_combination = KEY_SL; + } else if (strcasecmp(value, "SR") == 0) { + cfg.key_combination = KEY_SR; + } else { + cfg.key_combination = 0; + } + + return cfg; +} + +static int DmntIniHandler(void *user, const char *section, const char *name, const char *value) { + /* Taken and modified, with love, from Rajkosto's implementation. */ + if (strcasecmp(section, "default_config") == 0) { + if (strcasecmp(name, "cheat_enable_key") == 0) { + g_default_cheat_enable_key = ParseOverrideKey(value); + } + } else { + return 0; + } + return 1; +} + +static int DmntTitleSpecificIniHandler(void *user, const char *section, const char *name, const char *value) { + /* We'll output an override key when relevant. */ + OverrideKey *user_cfg = reinterpret_cast<OverrideKey *>(user); + + if (strcasecmp(section, "override_config") == 0) { + if (strcasecmp(name, "cheat_enable_key") == 0) { + *user_cfg = ParseOverrideKey(value); + } + } else { + return 0; + } + return 1; +} + +void DmntConfigManager::RefreshConfiguration() { + FILE *config = fopen("sdmc:/atmosphere/loader.ini", "r"); + if (config == NULL) { + return; + } + + memset(g_config_ini_data, 0, sizeof(g_config_ini_data)); + fread(g_config_ini_data, 1, sizeof(g_config_ini_data) - 1, config); + fclose(config); + + ini_parse_string(g_config_ini_data, DmntIniHandler, NULL); +} + +OverrideKey DmntConfigManager::GetTitleCheatEnableKey(u64 tid) { + OverrideKey cfg = g_default_cheat_enable_key; + char path[FS_MAX_PATH+1] = {0}; + snprintf(path, FS_MAX_PATH, "sdmc:/atmosphere/titles/%016lx/config.ini", tid); + + + FILE *config = fopen(path, "r"); + if (config != NULL) { + ON_SCOPE_EXIT { fclose(config); }; + + /* Parse current title ini. */ + ini_parse_file(config, DmntTitleSpecificIniHandler, &cfg); + } + + return cfg; +} + +static bool HasOverrideKey(OverrideKey *cfg) { + u64 kDown = 0; + bool keys_triggered = (R_SUCCEEDED(HidManagement::GetKeysDown(&kDown)) && ((kDown & cfg->key_combination) != 0)); + return (cfg->override_by_default ^ keys_triggered); +} + +bool DmntConfigManager::HasCheatEnableButton(u64 tid) { + /* Unconditionally refresh loader.ini contents. */ + RefreshConfiguration(); + + OverrideKey title_cfg = GetTitleCheatEnableKey(tid); + return HasOverrideKey(&title_cfg); +} diff --git a/stratosphere/dmnt/source/dmnt_config.hpp b/stratosphere/dmnt/source/dmnt_config.hpp new file mode 100644 index 000000000..b1ebed733 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_config.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> + +struct OverrideKey { + u64 key_combination; + bool override_by_default; +}; + +class DmntConfigManager { + public: + static void RefreshConfiguration(); + + static OverrideKey GetTitleCheatEnableKey(u64 tid); + static bool HasCheatEnableButton(u64 tid); +}; diff --git a/stratosphere/dmnt/source/dmnt_hid.cpp b/stratosphere/dmnt/source/dmnt_hid.cpp new file mode 100644 index 000000000..46c9eee24 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_hid.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <switch.h> +#include <string.h> + +#include "dmnt_hid.hpp" + +Result HidManagement::GetKeysDown(u64 *keys) { + if (R_FAILED(hidInitialize())) { + return MAKERESULT(Module_Libnx, LibnxError_InitFail_HID); + } + + hidScanInput(); + *keys = hidKeysDown(CONTROLLER_P1_AUTO); + + hidExit(); + return 0x0; +} \ No newline at end of file diff --git a/stratosphere/dmnt/source/dmnt_hid.hpp b/stratosphere/dmnt/source/dmnt_hid.hpp new file mode 100644 index 000000000..b5529fd20 --- /dev/null +++ b/stratosphere/dmnt/source/dmnt_hid.hpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once +#include <switch.h> + +class HidManagement { + public: + static Result GetKeysDown(u64 *keys); +}; diff --git a/stratosphere/dmnt/source/dmnt_main.cpp b/stratosphere/dmnt/source/dmnt_main.cpp index bea0dfffb..2eaf1dbb5 100644 --- a/stratosphere/dmnt/source/dmnt_main.cpp +++ b/stratosphere/dmnt/source/dmnt_main.cpp @@ -26,6 +26,7 @@ #include "dmnt_service.hpp" #include "dmnt_cheat_service.hpp" #include "dmnt_cheat_manager.hpp" +#include "dmnt_config.hpp" extern "C" { extern u32 __start__; @@ -128,6 +129,9 @@ int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); + /* Initialize configuration manager. */ + DmntConfigManager::RefreshConfiguration(); + /* Start cheat manager. */ DmntCheatManager::InitializeCheatManager(); diff --git a/stratosphere/dmnt/source/ini.c b/stratosphere/dmnt/source/ini.c new file mode 100644 index 000000000..63626c72d --- /dev/null +++ b/stratosphere/dmnt/source/ini.c @@ -0,0 +1,269 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +#include "ini.h" + +#if !INI_USE_STACK +#include <stdlib.h> +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to null at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + strncpy(dest, src, size - 1); + dest[size - 1] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; +#else + char* line; + int max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC + char* new_line; + int offset; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = realloc(line, max_line); + if (!new_line) { + free(line); + return -2; + } + line = new_line; + if (reader(line + offset, max_line - offset, stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; +#endif + value = lskip(value); + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ + error = lineno; + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/stratosphere/dmnt/source/ini.h b/stratosphere/dmnt/source/ini.h new file mode 100644 index 000000000..f45ba40ba --- /dev/null +++ b/stratosphere/dmnt/source/ini.h @@ -0,0 +1,130 @@ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef __INI_H__ +#define __INI_H__ + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See http://code.google.com/p/inih/issues/detail?id=21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INI_H__ */ diff --git a/stratosphere/dmnt/source/pm_shim.c b/stratosphere/dmnt/source/pm_shim.c index 027265817..9b4b5ff87 100644 --- a/stratosphere/dmnt/source/pm_shim.c +++ b/stratosphere/dmnt/source/pm_shim.c @@ -18,7 +18,7 @@ #include "pm_shim.h" /* Atmosphere extension commands. */ -Result pmdmntAtmosphereGetProcessHandle(Handle* out, u64 pid) { +Result pmdmntAtmosphereGetProcessInfo(Handle* out, u64 *tid_out, FsStorageId *sid_out, u64 pid) { IpcCommand c; ipcInitialize(&c); Service *s = pmdmntGetServiceSession(); @@ -42,6 +42,8 @@ Result pmdmntAtmosphereGetProcessHandle(Handle* out, u64 pid) { struct { u64 magic; u64 result; + u64 title_id; + FsStorageId storage_id; } *resp; serviceIpcParse(s, &r, sizeof(*resp)); @@ -50,7 +52,13 @@ Result pmdmntAtmosphereGetProcessHandle(Handle* out, u64 pid) { rc = resp->result; if (R_SUCCEEDED(rc)) { - *out = r.Handles[0]; + if (out) { + *out = r.Handles[0]; + } else { + svcCloseHandle(r.Handles[0]); + } + if (tid_out) *tid_out = resp->title_id; + if (sid_out) *sid_out = resp->storage_id; } } diff --git a/stratosphere/dmnt/source/pm_shim.h b/stratosphere/dmnt/source/pm_shim.h index ae2ca9403..76d4e68b9 100644 --- a/stratosphere/dmnt/source/pm_shim.h +++ b/stratosphere/dmnt/source/pm_shim.h @@ -12,7 +12,7 @@ extern "C" { #endif /* Atmosphere extension commands. */ -Result pmdmntAtmosphereGetProcessHandle(Handle* out, u64 pid); +Result pmdmntAtmosphereGetProcessInfo(Handle* out, u64 *tid_out, FsStorageId *sid_out, u64 pid); #ifdef __cplusplus } diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 346846714..4b121c948 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -40,7 +40,7 @@ static bool g_mounted_hbl_nsp = false; static char g_hbl_sd_path[FS_MAX_PATH+1] = "@Sdcard:/atmosphere/hbl.nsp\x00"; static OverrideKey g_default_override_key = { - .key_combination = KEY_R, + .key_combination = KEY_L, .override_by_default = true }; @@ -321,7 +321,7 @@ static int LoaderTitleSpecificIniHandler(void *user, const char *section, const return 1; } -void ContentManagement::RefreshConfigurationData() { +void ContentManagement::RefreshConfigurationData() { FILE *config = fopen("sdmc:/atmosphere/loader.ini", "r"); if (config == NULL) { return; diff --git a/stratosphere/pm/source/pm_debug_monitor.cpp b/stratosphere/pm/source/pm_debug_monitor.cpp index a9d4312d2..69f9eaab9 100644 --- a/stratosphere/pm/source/pm_debug_monitor.cpp +++ b/stratosphere/pm/source/pm_debug_monitor.cpp @@ -76,10 +76,11 @@ Result DebugMonitorService::DisableDebug(u32 which) { return Registration::DisableDebug(which); } -Result DebugMonitorService::AtmosphereGetProcessHandle(Out<CopiedHandle> proc_hand, u64 pid) { +Result DebugMonitorService::AtmosphereGetProcessInfo(Out<CopiedHandle> proc_hand, Out<Registration::TidSid> tid_sid, u64 pid) { auto proc = Registration::GetProcess(pid); - if(proc != nullptr) { + if (proc != nullptr) { proc_hand.SetValue(proc->handle); + tid_sid.SetValue(proc->tid_sid); return 0; } return 0x20F; diff --git a/stratosphere/pm/source/pm_debug_monitor.hpp b/stratosphere/pm/source/pm_debug_monitor.hpp index 88445bc60..22f6d02af 100644 --- a/stratosphere/pm/source/pm_debug_monitor.hpp +++ b/stratosphere/pm/source/pm_debug_monitor.hpp @@ -38,7 +38,7 @@ enum DmntCmd { Dmnt_Cmd_6X_DisableDebug = 6, - Dmnt_Cmd_AtmosphereGetProcessHandle = 65000, + Dmnt_Cmd_AtmosphereGetProcessInfo = 65000, Dmnt_Cmd_AtmosphereGetCurrentLimitInfo = 65001, }; @@ -55,7 +55,7 @@ class DebugMonitorService final : public IServiceObject { Result DisableDebug(u32 which); /* Atmosphere commands. */ - Result AtmosphereGetProcessHandle(Out<CopiedHandle> proc_hand, u64 pid); + Result AtmosphereGetProcessInfo(Out<CopiedHandle> proc_hand, Out<Registration::TidSid> tid_sid, u64 pid); Result AtmosphereGetCurrentLimitInfo(Out<u64> cur_val, Out<u64> lim_val, u32 category, u32 resource); public: DEFINE_SERVICE_DISPATCH_TABLE { @@ -80,7 +80,7 @@ class DebugMonitorService final : public IServiceObject { MakeServiceCommandMeta<Dmnt_Cmd_6X_DisableDebug, &DebugMonitorService::DisableDebug, FirmwareVersion_600>(), /* Atmosphere extensions. */ - MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetProcessHandle, &DebugMonitorService::AtmosphereGetProcessHandle>(), + MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetProcessInfo, &DebugMonitorService::AtmosphereGetProcessInfo>(), MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetCurrentLimitInfo, &DebugMonitorService::AtmosphereGetCurrentLimitInfo>(), }; }; From 5ef3ca9364bfcb5311a1d7df466ab28613d99835 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 19:05:52 -0800 Subject: [PATCH 478/489] fs.mitm: make prodinfo backups actually work --- stratosphere/ams_mitm/source/utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/ams_mitm/source/utils.cpp b/stratosphere/ams_mitm/source/utils.cpp index fef0957e8..27ea93f49 100644 --- a/stratosphere/ams_mitm/source/utils.cpp +++ b/stratosphere/ams_mitm/source/utils.cpp @@ -137,7 +137,7 @@ void Utils::InitializeThreadFunc(void *args) { if (!has_auto_backup) { fsFileSetSize(&g_cal0_file, ProdinfoSize); - fsFileWrite(&g_cal0_file, 0, g_cal0_backup, ProdinfoSize); + fsFileWrite(&g_cal0_file, 0, g_cal0_storage_backup, ProdinfoSize); fsFileFlush(&g_cal0_file); } From 34af93b72fd0efaf8d9f14d3f92110005a42e4ac Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 20:13:52 -0800 Subject: [PATCH 479/489] dmnt-cheat: implement cheat loading from SD --- .../dmnt/source/dmnt_cheat_manager.cpp | 187 +++++++++++++++++- .../dmnt/source/dmnt_cheat_manager.hpp | 8 + stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 20 ++ stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 1 + 4 files changed, 212 insertions(+), 4 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 52556dbee..63d329d65 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -29,11 +29,20 @@ static DmntCheatVm *g_cheat_vm; static CheatProcessMetadata g_cheat_process_metadata = {0}; static Handle g_cheat_process_debug_hnd = 0; +/* Global cheat entry storage. */ +static CheatEntry g_cheat_entries[DmntCheatManager::MaxCheatCount]; + void DmntCheatManager::CloseActiveCheatProcess() { if (g_cheat_process_debug_hnd != 0) { + /* Close process resources. */ svcCloseHandle(g_cheat_process_debug_hnd); g_cheat_process_debug_hnd = 0; g_cheat_process_metadata = (CheatProcessMetadata){0}; + + /* Clear cheat list. */ + ResetAllCheatEntries(); + + /* Signal to our fans. */ g_cheat_process_event->Signal(); } } @@ -177,6 +186,166 @@ Result DmntCheatManager::QueryCheatProcessMemory(MemoryInfo *mapping, u64 addres return ResultDmntCheatNotAttached; } +void DmntCheatManager::ResetCheatEntry(size_t i) { + if (i < DmntCheatManager::MaxCheatCount) { + g_cheat_entries[i].enabled = false; + g_cheat_entries[i].cheat_id = i; + g_cheat_entries[i].definition = {0}; + } +} + +void DmntCheatManager::ResetAllCheatEntries() { + for (size_t i = 0; i < DmntCheatManager::MaxCheatCount; i++) { + ResetCheatEntry(i); + } +} + +CheatEntry *DmntCheatManager::GetFreeCheatEntry() { + /* Check all non-master cheats for availability. */ + for (size_t i = 1; i < DmntCheatManager::MaxCheatCount; i++) { + if (g_cheat_entries[i].definition.num_opcodes == 0) { + return &g_cheat_entries[i]; + } + } + + return nullptr; +} + +bool DmntCheatManager::ParseCheats(const char *s, size_t len) { + size_t i = 0; + CheatEntry *cur_entry = NULL; + + while (i < len) { + if (isspace(s[i])) { + /* Just ignore space. */ + i++; + } else if (s[i] == '[') { + /* Parse a readable cheat name. */ + cur_entry = GetFreeCheatEntry(); + if (cur_entry == NULL) { + return false; + } + + /* Extract name bounds. */ + size_t j = i + 1; + while (s[j] != ']') { + j++; + if (j >= len || (j - i - 1) >= sizeof(cur_entry->definition.readable_name)) { + return false; + } + } + + /* s[i+1:j] is cheat name. */ + const size_t cheat_name_len = (j - i - 1); + memcpy(cur_entry->definition.readable_name, &s[i+1], cheat_name_len); + cur_entry->definition.readable_name[cheat_name_len] = 0; + + /* Skip onwards. */ + i = j + 1; + } else if (s[i] == '{') { + /* We're parsing a master cheat. */ + cur_entry = &g_cheat_entries[0]; + + /* There can only be one master cheat. */ + if (cur_entry->definition.num_opcodes > 0) { + return false; + } + + /* Extract name bounds */ + size_t j = i + 1; + while (s[j] != '}') { + j++; + if (j >= len || (j - i - 1) >= sizeof(cur_entry->definition.readable_name)) { + return false; + } + } + + /* s[i+1:j] is cheat name. */ + const size_t cheat_name_len = (j - i - 1); + memcpy(cur_entry->definition.readable_name, &s[i+1], cheat_name_len); + cur_entry->definition.readable_name[cheat_name_len] = 0; + + /* Skip onwards. */ + i = j + 1; + } else if (isxdigit(s[i])) { + /* Make sure that we have a cheat open. */ + if (cur_entry == NULL) { + return false; + } + + /* We're parsing an instruction, so validate it's 8 hex digits. */ + for (size_t j = 1; j < 8; j++) { + /* Validate 8 hex chars. */ + if (i + j >= len || !isxdigit(s[i+j])) { + return false; + } + } + + /* Parse the new opcode. */ + char hex_str[9] = {0}; + memcpy(hex_str, &s[i], 8); + cur_entry->definition.opcodes[cur_entry->definition.num_opcodes++] = strtoul(hex_str, NULL, 16); + + /* Skip onwards. */ + i += 8; + } else { + /* Unexpected character encountered. */ + return false; + } + } + + /* Enable all entries we parsed. */ + for (size_t i = 0; i < DmntCheatManager::MaxCheatCount; i++) { + if (g_cheat_entries[i].definition.num_opcodes > 0) { + g_cheat_entries[i].enabled = true; + } + } + + return true; +} + +bool DmntCheatManager::LoadCheats(u64 title_id, const u8 *build_id) { + /* Reset existing entries. */ + ResetAllCheatEntries(); + + FILE *f_cht = NULL; + /* Open the file for title/build_id. */ + { + char path[FS_MAX_PATH+1] = {0}; + snprintf(path, FS_MAX_PATH, "sdmc:/atmosphere/titles/%016lx/cheats/%02x%02x%02x%02x%02x%02x%02x%02x.txt", title_id, + build_id[0], build_id[1], build_id[2], build_id[3], build_id[4], build_id[5], build_id[6], build_id[7]); + + f_cht = fopen(path, "rb"); + } + + /* Check for NULL */ + if (f_cht == NULL) { + return false; + } + ON_SCOPE_EXIT { fclose(f_cht); }; + + /* Get file size. */ + fseek(f_cht, 0L, SEEK_END); + const size_t cht_sz = ftell(f_cht); + fseek(f_cht, 0L, SEEK_SET); + + /* Allocate cheat txt buffer. */ + char *cht_txt = (char *)malloc(cht_sz + 1); + if (cht_txt == NULL) { + return false; + } + ON_SCOPE_EXIT { free(cht_txt); }; + + /* Read cheats into buffer. */ + if (fread(cht_txt, 1, cht_sz, f_cht) != cht_sz) { + return false; + } + cht_txt[cht_sz] = 0; + + /* Parse cheat buffer. */ + return ParseCheats(cht_txt, strlen(cht_txt)); +} + Handle DmntCheatManager::PrepareDebugNextApplication() { Result rc; Handle event_h; @@ -267,7 +436,9 @@ Result DmntCheatManager::ForceOpenCheatProcess() { memcpy(g_cheat_process_metadata.main_nso_build_id, proc_module->build_id, sizeof(g_cheat_process_metadata.main_nso_build_id)); } - /* TODO: Read cheats off the SD. */ + /* Read cheats off the SD. */ + /* This is allowed to fail. We may not have any cheats. */ + LoadCheats(g_cheat_process_metadata.title_id, g_cheat_process_metadata.main_nso_build_id); /* Open a debug handle. */ if (R_FAILED((rc = svcDebugActiveProcess(&g_cheat_process_debug_hnd, g_cheat_process_metadata.process_id)))) { @@ -344,7 +515,13 @@ void DmntCheatManager::OnNewApplicationLaunch() { memcpy(g_cheat_process_metadata.main_nso_build_id, proc_modules[1].build_id, sizeof(g_cheat_process_metadata.main_nso_build_id)); } - /* TODO: Read cheats off the SD. */ + /* Read cheats off the SD. */ + if (!LoadCheats(g_cheat_process_metadata.title_id, g_cheat_process_metadata.main_nso_build_id)) { + /* If we don't have cheats, or cheats are malformed, don't attach. */ + StartDebugProcess(g_cheat_process_metadata.process_id); + g_cheat_process_metadata.process_id = 0; + return; + } /* Open a debug handle. */ if (R_FAILED((rc = svcDebugActiveProcess(&g_cheat_process_debug_hnd, g_cheat_process_metadata.process_id)))) { @@ -389,8 +566,10 @@ void DmntCheatManager::VmThread(void *arg) { ContinueCheatProcess(); /* Execute VM. */ - if (g_cheat_vm->GetProgramSize() != 0) { - g_cheat_vm->Execute(&g_cheat_process_metadata); + if (g_cheat_vm->LoadProgram(g_cheat_entries, DmntCheatManager::MaxCheatCount)) { + if (g_cheat_vm->GetProgramSize() != 0) { + g_cheat_vm->Execute(&g_cheat_process_metadata); + } } } } diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index 47408b9b9..99ae85b43 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -21,6 +21,8 @@ #include "dmnt_cheat_types.hpp" class DmntCheatManager { + public: + static constexpr size_t MaxCheatCount = 0x80; private: static Handle PrepareDebugNextApplication(); static void OnNewApplicationLaunch(); @@ -30,6 +32,12 @@ class DmntCheatManager { static bool HasActiveCheatProcess(); static void CloseActiveCheatProcess(); static void ContinueCheatProcess(); + + static void ResetCheatEntry(size_t i); + static void ResetAllCheatEntries(); + static CheatEntry *GetFreeCheatEntry(); + static bool ParseCheats(const char *cht_txt, size_t len); + static bool LoadCheats(u64 title_id, const u8 *build_id); public: static bool GetHasActiveCheatProcess(); static Handle GetCheatProcessEventHandle(); diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index 821ae75e4..9afc9edc3 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -353,6 +353,26 @@ void DmntCheatVm::ResetState() { this->decode_success = true; } +bool DmntCheatVm::LoadProgram(const CheatEntry *cheats, size_t num_cheats) { + /* Reset opcode count. */ + this->num_opcodes = 0; + + for (size_t i = 0; i < num_cheats; i++) { + if (cheats[i].enabled) { + /* Bounds check. */ + if (cheats[i].definition.num_opcodes + this->num_opcodes > MaximumProgramOpcodeCount) { + return false; + } + + for (size_t n = 0; n < cheats[i].definition.num_opcodes; n++) { + this->program[this->num_opcodes++] = cheats[i].definition.opcodes[n]; + } + } + } + + return true; +} + void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { CheatVmOpcode cur_opcode; u64 kDown = 0; diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 2dbc4cbc4..2236dd9a4 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -187,6 +187,7 @@ class DmntCheatVm { return this->num_opcodes; } + bool LoadProgram(const CheatEntry *cheats, size_t num_cheats); void Execute(const CheatProcessMetadata *metadata); #ifdef DMNT_CHEAT_VM_DEBUG_LOG private: From 862aa7378308fbab0d8b7078b90f230ef5598f6e Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 20:24:49 -0800 Subject: [PATCH 480/489] Add maximum instruction opcode bounds check (thanks hthh) --- stratosphere/dmnt/source/dmnt_cheat_manager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 63d329d65..1a152a7a5 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -273,6 +273,11 @@ bool DmntCheatManager::ParseCheats(const char *s, size_t len) { return false; } + /* Bounds check the opcode count. */ + if (cur_entry->definition.num_opcodes >= sizeof(cur_entry->definition.opcodes)/sizeof(cur_entry->definition.opcodes[0])) { + return false; + } + /* We're parsing an instruction, so validate it's 8 hex digits. */ for (size_t j = 1; j < 8; j++) { /* Validate 8 hex chars. */ @@ -286,6 +291,7 @@ bool DmntCheatManager::ParseCheats(const char *s, size_t len) { memcpy(hex_str, &s[i], 8); cur_entry->definition.opcodes[cur_entry->definition.num_opcodes++] = strtoul(hex_str, NULL, 16); + /* Skip onwards. */ i += 8; } else { From 7ddb0da5f6c926eae9bf1b655d62bfef78d01621 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 21:11:12 -0800 Subject: [PATCH 481/489] dmnt-cheat: Implement cheat management service commands --- .../dmnt/source/dmnt_cheat_manager.cpp | 114 ++++++++++++++++++ .../dmnt/source/dmnt_cheat_manager.hpp | 8 ++ .../dmnt/source/dmnt_cheat_service.cpp | 51 ++++++-- stratosphere/dmnt/source/dmnt_results.hpp | 8 +- 4 files changed, 167 insertions(+), 14 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 1a152a7a5..7f42b2369 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -211,6 +211,14 @@ CheatEntry *DmntCheatManager::GetFreeCheatEntry() { return nullptr; } +CheatEntry *DmntCheatManager::GetCheatEntryById(size_t i) { + if (i < DmntCheatManager::MaxCheatCount) { + return &g_cheat_entries[i]; + } + + return nullptr; +} + bool DmntCheatManager::ParseCheats(const char *s, size_t len) { size_t i = 0; CheatEntry *cur_entry = NULL; @@ -352,6 +360,112 @@ bool DmntCheatManager::LoadCheats(u64 title_id, const u8 *build_id) { return ParseCheats(cht_txt, strlen(cht_txt)); } +Result DmntCheatManager::GetCheatCount(u64 *out_count) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + *out_count = 0; + for (size_t i = 0; i < DmntCheatManager::MaxCheatCount; i++) { + if (g_cheat_entries[i].definition.num_opcodes > 0) { + *out_count += 1; + } + } + + return 0; +} + +Result DmntCheatManager::GetCheats(CheatEntry *cheats, size_t max_count, u64 *out_count, u64 offset) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + u64 count = 0; + *out_count = 0; + for (size_t i = 0; i < DmntCheatManager::MaxCheatCount && (*out_count) < max_count; i++) { + if (g_cheat_entries[i].definition.num_opcodes > 0) { + count++; + if (count > offset) { + cheats[(*out_count)++] = g_cheat_entries[i]; + } + } + } + + return 0; +} + +Result DmntCheatManager::GetCheatById(CheatEntry *out_cheat, u32 cheat_id) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + const CheatEntry *entry = GetCheatEntryById(cheat_id); + if (entry == nullptr || entry->definition.num_opcodes == 0) { + return ResultDmntCheatUnknownChtId; + } + + *out_cheat = *entry; + return 0; +} + +Result DmntCheatManager::ToggleCheat(u32 cheat_id) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + CheatEntry *entry = GetCheatEntryById(cheat_id); + if (entry == nullptr || entry->definition.num_opcodes == 0) { + return ResultDmntCheatUnknownChtId; + } + + entry->enabled = !entry->enabled; + return 0; +} + +Result DmntCheatManager::AddCheat(u32 *out_id, CheatDefinition *def, bool enabled) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + if (def->num_opcodes == 0 || def->num_opcodes > sizeof(def->opcodes)/sizeof(def->opcodes[0])) { + return ResultDmntCheatInvalidCheat; + } + + CheatEntry *new_entry = GetFreeCheatEntry(); + if (new_entry == nullptr) { + return ResultDmntCheatOutOfCheats; + } + + new_entry->enabled = enabled; + new_entry->definition = *def; + return 0; +} + +Result DmntCheatManager::RemoveCheat(u32 cheat_id) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + if (cheat_id >= DmntCheatManager::MaxCheatCount) { + return ResultDmntCheatUnknownChtId; + } + + ResetCheatEntry(cheat_id); + return 0; +} + Handle DmntCheatManager::PrepareDebugNextApplication() { Result rc; Handle event_h; diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index 99ae85b43..2b8a11dcb 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -36,6 +36,7 @@ class DmntCheatManager { static void ResetCheatEntry(size_t i); static void ResetAllCheatEntries(); static CheatEntry *GetFreeCheatEntry(); + static CheatEntry *GetCheatEntryById(size_t i); static bool ParseCheats(const char *cht_txt, size_t len); static bool LoadCheats(u64 title_id, const u8 *build_id); public: @@ -53,5 +54,12 @@ class DmntCheatManager { static Result WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size); static Result QueryCheatProcessMemory(MemoryInfo *mapping, u64 address); + static Result GetCheatCount(u64 *out_count); + static Result GetCheats(CheatEntry *cheats, size_t max_count, u64 *out_count, u64 offset); + static Result GetCheatById(CheatEntry *out_cheat, u32 cheat_id); + static Result ToggleCheat(u32 cheat_id); + static Result AddCheat(u32 *out_id, CheatDefinition *def, bool enabled); + static Result RemoveCheat(u32 cheat_id); + static void InitializeCheatManager(); }; diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp index 521a12c85..69abea9c8 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -18,6 +18,10 @@ #include "dmnt_cheat_service.hpp" #include "dmnt_cheat_manager.hpp" +/* ========================================================================================= */ +/* ==================================== Meta Commands ==================================== */ +/* ========================================================================================= */ + void DmntCheatService::HasCheatProcess(Out<bool> out) { out.SetValue(DmntCheatManager::GetHasActiveCheatProcess()); } @@ -40,6 +44,9 @@ Result DmntCheatService::ForceOpenCheatProcess() { return rc; } +/* ========================================================================================= */ +/* =================================== Memory Commands =================================== */ +/* ========================================================================================= */ Result DmntCheatService::GetCheatProcessMappingCount(Out<u64> out_count) { return DmntCheatManager::GetCheatProcessMappingCount(out_count.GetPointer()); @@ -83,37 +90,57 @@ Result DmntCheatService::QueryCheatProcessMemory(Out<MemoryInfo> mapping, u64 ad return DmntCheatManager::QueryCheatProcessMemory(mapping.GetPointer(), address); } +/* ========================================================================================= */ +/* =================================== Cheat Commands ==================================== */ +/* ========================================================================================= */ Result DmntCheatService::GetCheatCount(Out<u64> out_count) { - /* TODO */ - return 0xF601; + return DmntCheatManager::GetCheatCount(out_count.GetPointer()); } Result DmntCheatService::GetCheats(OutBuffer<CheatEntry> cheats, Out<u64> out_count, u64 offset) { - /* TODO */ - return 0xF601; + if (cheats.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + return DmntCheatManager::GetCheats(cheats.buffer, cheats.num_elements, out_count.GetPointer(), offset); } Result DmntCheatService::GetCheatById(OutBuffer<CheatEntry> cheat, u32 cheat_id) { - /* TODO */ - return 0xF601; + if (cheat.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + if (cheat.num_elements < 1) { + return ResultDmntCheatInvalidBuffer; + } + + return DmntCheatManager::GetCheatById(cheat.buffer, cheat_id); } Result DmntCheatService::ToggleCheat(u32 cheat_id) { - /* TODO */ - return 0xF601; + return DmntCheatManager::ToggleCheat(cheat_id); } Result DmntCheatService::AddCheat(InBuffer<CheatDefinition> cheat, Out<u32> out_cheat_id, bool enabled) { - /* TODO */ - return 0xF601; + if (cheat.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + if (cheat.num_elements < 1) { + return ResultDmntCheatInvalidBuffer; + } + + return DmntCheatManager::AddCheat(out_cheat_id.GetPointer(), cheat.buffer, enabled); } Result DmntCheatService::RemoveCheat(u32 cheat_id) { - /* TODO */ - return 0xF601; + return DmntCheatManager::RemoveCheat(cheat_id); } +/* ========================================================================================= */ +/* =================================== Address Commands ================================== */ +/* ========================================================================================= */ Result DmntCheatService::GetFrozenAddressCount(Out<u64> out_count) { /* TODO */ diff --git a/stratosphere/dmnt/source/dmnt_results.hpp b/stratosphere/dmnt/source/dmnt_results.hpp index 5be79a674..752e9de07 100644 --- a/stratosphere/dmnt/source/dmnt_results.hpp +++ b/stratosphere/dmnt/source/dmnt_results.hpp @@ -23,5 +23,9 @@ static constexpr u32 Module_Dmnt = 13; static constexpr Result ResultDmntUnknown = MAKERESULT(Module_Dmnt, 1); static constexpr Result ResultDmntDebuggingDisabled = MAKERESULT(Module_Dmnt, 2); -static constexpr Result ResultDmntCheatNotAttached = MAKERESULT(Module_Dmnt, 6500); -static constexpr Result ResultDmntCheatNullBuffer = MAKERESULT(Module_Dmnt, 6501); \ No newline at end of file +static constexpr Result ResultDmntCheatNotAttached = MAKERESULT(Module_Dmnt, 6500); +static constexpr Result ResultDmntCheatNullBuffer = MAKERESULT(Module_Dmnt, 6501); +static constexpr Result ResultDmntCheatInvalidBuffer = MAKERESULT(Module_Dmnt, 6502); +static constexpr Result ResultDmntCheatUnknownChtId = MAKERESULT(Module_Dmnt, 6503); +static constexpr Result ResultDmntCheatOutOfCheats = MAKERESULT(Module_Dmnt, 6504); +static constexpr Result ResultDmntCheatInvalidCheat = MAKERESULT(Module_Dmnt, 6505); \ No newline at end of file From e734a5412a79a1a36df074fa8175adbe3cdccce7 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 22:13:43 -0800 Subject: [PATCH 482/489] dmnt-cheat: Implement frozen addresses --- .../dmnt/source/dmnt_cheat_manager.cpp | 113 ++++++++++++++++++ .../dmnt/source/dmnt_cheat_manager.hpp | 9 ++ .../dmnt/source/dmnt_cheat_service.cpp | 35 ++++-- .../dmnt/source/dmnt_cheat_service.hpp | 14 ++- stratosphere/dmnt/source/dmnt_cheat_types.hpp | 10 ++ stratosphere/dmnt/source/dmnt_results.hpp | 7 +- 6 files changed, 175 insertions(+), 13 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 7f42b2369..274fc973d 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -14,6 +14,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <map> #include <switch.h> #include "dmnt_cheat_manager.hpp" #include "dmnt_cheat_vm.hpp" @@ -32,6 +33,9 @@ static Handle g_cheat_process_debug_hnd = 0; /* Global cheat entry storage. */ static CheatEntry g_cheat_entries[DmntCheatManager::MaxCheatCount]; +/* Global frozen address storage. */ +static std::map<u64, FrozenAddressValue> g_frozen_addresses_map; + void DmntCheatManager::CloseActiveCheatProcess() { if (g_cheat_process_debug_hnd != 0) { /* Close process resources. */ @@ -42,6 +46,9 @@ void DmntCheatManager::CloseActiveCheatProcess() { /* Clear cheat list. */ ResetAllCheatEntries(); + /* Clear frozen addresses. */ + ResetFrozenAddresses(); + /* Signal to our fans. */ g_cheat_process_event->Signal(); } @@ -186,6 +193,11 @@ Result DmntCheatManager::QueryCheatProcessMemory(MemoryInfo *mapping, u64 addres return ResultDmntCheatNotAttached; } +void DmntCheatManager::ResetFrozenAddresses() { + /* Just clear the map. */ + g_frozen_addresses_map.clear(); +} + void DmntCheatManager::ResetCheatEntry(size_t i) { if (i < DmntCheatManager::MaxCheatCount) { g_cheat_entries[i].enabled = false; @@ -466,6 +478,102 @@ Result DmntCheatManager::RemoveCheat(u32 cheat_id) { return 0; } +Result DmntCheatManager::GetFrozenAddressCount(u64 *out_count) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + *out_count = g_frozen_addresses_map.size(); + return 0; +} + +Result DmntCheatManager::GetFrozenAddresses(FrozenAddressEntry *frz_addrs, size_t max_count, u64 *out_count, u64 offset) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + u64 count = 0; + *out_count = 0; + for (auto const& [address, value] : g_frozen_addresses_map) { + if ((*out_count) >= max_count) { + break; + } + + count++; + if (count > offset) { + const u64 cur_ind = (*out_count)++; + frz_addrs[cur_ind].address = address; + frz_addrs[cur_ind].value = value; + } + } + + return 0; +} + +Result DmntCheatManager::GetFrozenAddress(FrozenAddressEntry *frz_addr, u64 address) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + const auto it = g_frozen_addresses_map.find(address); + if (it == g_frozen_addresses_map.end()) { + return ResultDmntCheatAddressNotFrozen; + } + + frz_addr->address = it->first; + frz_addr->value = it->second; + return 0; +} + +Result DmntCheatManager::EnableFrozenAddress(u64 address, u64 width) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + if (g_frozen_addresses_map.size() >= DmntCheatManager::MaxFrozenAddressCount) { + return ResultDmntCheatTooManyFrozenAddresses; + } + + const auto it = g_frozen_addresses_map.find(address); + if (it != g_frozen_addresses_map.end()) { + return ResultDmntCheatAddressAlreadyFrozen; + } + + Result rc; + FrozenAddressValue value = {0}; + value.width = width; + if (R_FAILED((rc = ReadCheatProcessMemoryForVm(address, &value.value, width)))) { + return rc; + } + + g_frozen_addresses_map[address] = value; + return 0; +} + +Result DmntCheatManager::DisableFrozenAddress(u64 address) { + std::scoped_lock<HosMutex> lk(g_cheat_lock); + + if (!HasActiveCheatProcess()) { + return ResultDmntCheatNotAttached; + } + + const auto it = g_frozen_addresses_map.find(address); + if (it == g_frozen_addresses_map.end()) { + return ResultDmntCheatAddressNotFrozen; + } + + g_frozen_addresses_map.erase(address); + return 0; +} + Handle DmntCheatManager::PrepareDebugNextApplication() { Result rc; Handle event_h; @@ -691,6 +799,11 @@ void DmntCheatManager::VmThread(void *arg) { g_cheat_vm->Execute(&g_cheat_process_metadata); } } + + /* Apply frozen addresses. */ + for (auto const& [address, value] : g_frozen_addresses_map) { + WriteCheatProcessMemoryForVm(address, &value.value, value.width); + } } } svcSleepThread(0x5000000ul); diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index 2b8a11dcb..37525adb4 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -23,6 +23,7 @@ class DmntCheatManager { public: static constexpr size_t MaxCheatCount = 0x80; + static constexpr size_t MaxFrozenAddressCount = 0x80; private: static Handle PrepareDebugNextApplication(); static void OnNewApplicationLaunch(); @@ -39,6 +40,8 @@ class DmntCheatManager { static CheatEntry *GetCheatEntryById(size_t i); static bool ParseCheats(const char *cht_txt, size_t len); static bool LoadCheats(u64 title_id, const u8 *build_id); + + static void ResetFrozenAddresses(); public: static bool GetHasActiveCheatProcess(); static Handle GetCheatProcessEventHandle(); @@ -61,5 +64,11 @@ class DmntCheatManager { static Result AddCheat(u32 *out_id, CheatDefinition *def, bool enabled); static Result RemoveCheat(u32 cheat_id); + static Result GetFrozenAddressCount(u64 *out_count); + static Result GetFrozenAddresses(FrozenAddressEntry *frz_addrs, size_t max_count, u64 *out_count, u64 offset); + static Result GetFrozenAddress(FrozenAddressEntry *frz_addr, u64 address); + static Result EnableFrozenAddress(u64 address, u64 width); + static Result DisableFrozenAddress(u64 address); + static void InitializeCheatManager(); }; diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp index 69abea9c8..8ccd6266c 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -143,16 +143,35 @@ Result DmntCheatService::RemoveCheat(u32 cheat_id) { /* ========================================================================================= */ Result DmntCheatService::GetFrozenAddressCount(Out<u64> out_count) { - /* TODO */ - return 0xF601; + return DmntCheatManager::GetFrozenAddressCount(out_count.GetPointer()); } -Result DmntCheatService::GetFrozenAddresses(OutBuffer<uintptr_t> addresses, Out<u64> out_count, u64 offset) { - /* TODO */ - return 0xF601; +Result DmntCheatService::GetFrozenAddresses(OutBuffer<FrozenAddressEntry> frz_addrs, Out<u64> out_count, u64 offset) { + if (frz_addrs.buffer == nullptr) { + return ResultDmntCheatNullBuffer; + } + + return DmntCheatManager::GetFrozenAddresses(frz_addrs.buffer, frz_addrs.num_elements, out_count.GetPointer(), offset); } -Result DmntCheatService::ToggleAddressFrozen(uintptr_t address) { - /* TODO */ - return 0xF601; +Result DmntCheatService::GetFrozenAddress(Out<FrozenAddressEntry> entry, u64 address) { + return DmntCheatManager::GetFrozenAddress(entry.GetPointer(), address); +} + +Result DmntCheatService::EnableFrozenAddress(u64 address, u64 width) { + switch (width) { + case 1: + case 2: + case 4: + case 8: + break; + default: + return ResultDmntCheatInvalidFreezeWidth; + } + + return DmntCheatManager::EnableFrozenAddress(address, width); +} + +Result DmntCheatService::DisableFrozenAddress(u64 address) { + return DmntCheatManager::DisableFrozenAddress(address); } diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.hpp b/stratosphere/dmnt/source/dmnt_cheat_service.hpp index a921465a0..abb43d523 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.hpp @@ -45,7 +45,9 @@ enum DmntCheatCmd { /* Interact with Frozen Addresses */ DmntCheat_Cmd_GetFrozenAddressCount = 65300, DmntCheat_Cmd_GetFrozenAddresses = 65301, - DmntCheat_Cmd_ToggleAddressFrozen = 65302, + DmntCheat_Cmd_GetFrozenAddress = 65302, + DmntCheat_Cmd_EnableFrozenAddress = 65303, + DmntCheat_Cmd_DisableFrozenAddress = 65304, }; class DmntCheatService final : public IServiceObject { @@ -69,8 +71,10 @@ class DmntCheatService final : public IServiceObject { Result RemoveCheat(u32 cheat_id); Result GetFrozenAddressCount(Out<u64> out_count); - Result GetFrozenAddresses(OutBuffer<uintptr_t> addresses, Out<u64> out_count, u64 offset); - Result ToggleAddressFrozen(uintptr_t address); + Result GetFrozenAddresses(OutBuffer<FrozenAddressEntry> addresses, Out<u64> out_count, u64 offset); + Result GetFrozenAddress(Out<FrozenAddressEntry> entry, u64 address); + Result EnableFrozenAddress(u64 address, u64 width); + Result DisableFrozenAddress(u64 address); public: DEFINE_SERVICE_DISPATCH_TABLE { @@ -94,6 +98,8 @@ class DmntCheatService final : public IServiceObject { MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddressCount, &DmntCheatService::GetFrozenAddressCount>(), MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddresses, &DmntCheatService::GetFrozenAddresses>(), - MakeServiceCommandMeta<DmntCheat_Cmd_ToggleAddressFrozen, &DmntCheatService::ToggleAddressFrozen>(), + MakeServiceCommandMeta<DmntCheat_Cmd_GetFrozenAddress, &DmntCheatService::GetFrozenAddress>(), + MakeServiceCommandMeta<DmntCheat_Cmd_EnableFrozenAddress, &DmntCheatService::EnableFrozenAddress>(), + MakeServiceCommandMeta<DmntCheat_Cmd_DisableFrozenAddress, &DmntCheatService::DisableFrozenAddress>(), }; }; diff --git a/stratosphere/dmnt/source/dmnt_cheat_types.hpp b/stratosphere/dmnt/source/dmnt_cheat_types.hpp index 133baf425..830777c86 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_types.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_types.hpp @@ -45,4 +45,14 @@ struct CheatEntry { bool enabled; uint32_t cheat_id; CheatDefinition definition; +}; + +struct FrozenAddressValue { + u64 value; + u8 width; +}; + +struct FrozenAddressEntry { + u64 address; + FrozenAddressValue value; }; \ No newline at end of file diff --git a/stratosphere/dmnt/source/dmnt_results.hpp b/stratosphere/dmnt/source/dmnt_results.hpp index 752e9de07..f4e908a12 100644 --- a/stratosphere/dmnt/source/dmnt_results.hpp +++ b/stratosphere/dmnt/source/dmnt_results.hpp @@ -28,4 +28,9 @@ static constexpr Result ResultDmntCheatNullBuffer = MAKERESULT(Module_Dmnt, 6 static constexpr Result ResultDmntCheatInvalidBuffer = MAKERESULT(Module_Dmnt, 6502); static constexpr Result ResultDmntCheatUnknownChtId = MAKERESULT(Module_Dmnt, 6503); static constexpr Result ResultDmntCheatOutOfCheats = MAKERESULT(Module_Dmnt, 6504); -static constexpr Result ResultDmntCheatInvalidCheat = MAKERESULT(Module_Dmnt, 6505); \ No newline at end of file +static constexpr Result ResultDmntCheatInvalidCheat = MAKERESULT(Module_Dmnt, 6505); + +static constexpr Result ResultDmntCheatInvalidFreezeWidth = MAKERESULT(Module_Dmnt, 6600); +static constexpr Result ResultDmntCheatAddressAlreadyFrozen = MAKERESULT(Module_Dmnt, 6601); +static constexpr Result ResultDmntCheatAddressNotFrozen = MAKERESULT(Module_Dmnt, 6602); +static constexpr Result ResultDmntCheatTooManyFrozenAddresses = MAKERESULT(Module_Dmnt, 6603); \ No newline at end of file From eddbd7c072c3b94aca918049fdf45f67054ab5b4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 22:17:18 -0800 Subject: [PATCH 483/489] dmnt-cheat: output value on EnableFrozenAddress --- stratosphere/dmnt/source/dmnt_cheat_manager.cpp | 3 ++- stratosphere/dmnt/source/dmnt_cheat_manager.hpp | 2 +- stratosphere/dmnt/source/dmnt_cheat_service.cpp | 4 ++-- stratosphere/dmnt/source/dmnt_cheat_service.hpp | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp index 274fc973d..98d8453ad 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.cpp @@ -531,7 +531,7 @@ Result DmntCheatManager::GetFrozenAddress(FrozenAddressEntry *frz_addr, u64 add return 0; } -Result DmntCheatManager::EnableFrozenAddress(u64 address, u64 width) { +Result DmntCheatManager::EnableFrozenAddress(u64 *out_value, u64 address, u64 width) { std::scoped_lock<HosMutex> lk(g_cheat_lock); if (!HasActiveCheatProcess()) { @@ -555,6 +555,7 @@ Result DmntCheatManager::EnableFrozenAddress(u64 address, u64 width) { } g_frozen_addresses_map[address] = value; + *out_value = value.value; return 0; } diff --git a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp index 37525adb4..d1deb8ba6 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_manager.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_manager.hpp @@ -67,7 +67,7 @@ class DmntCheatManager { static Result GetFrozenAddressCount(u64 *out_count); static Result GetFrozenAddresses(FrozenAddressEntry *frz_addrs, size_t max_count, u64 *out_count, u64 offset); static Result GetFrozenAddress(FrozenAddressEntry *frz_addr, u64 address); - static Result EnableFrozenAddress(u64 address, u64 width); + static Result EnableFrozenAddress(u64 *out_value, u64 address, u64 width); static Result DisableFrozenAddress(u64 address); static void InitializeCheatManager(); diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.cpp b/stratosphere/dmnt/source/dmnt_cheat_service.cpp index 8ccd6266c..966c0702d 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.cpp @@ -158,7 +158,7 @@ Result DmntCheatService::GetFrozenAddress(Out<FrozenAddressEntry> entry, u64 add return DmntCheatManager::GetFrozenAddress(entry.GetPointer(), address); } -Result DmntCheatService::EnableFrozenAddress(u64 address, u64 width) { +Result DmntCheatService::EnableFrozenAddress(Out<u64> out_value, u64 address, u64 width) { switch (width) { case 1: case 2: @@ -169,7 +169,7 @@ Result DmntCheatService::EnableFrozenAddress(u64 address, u64 width) { return ResultDmntCheatInvalidFreezeWidth; } - return DmntCheatManager::EnableFrozenAddress(address, width); + return DmntCheatManager::EnableFrozenAddress(out_value.GetPointer(), address, width); } Result DmntCheatService::DisableFrozenAddress(u64 address) { diff --git a/stratosphere/dmnt/source/dmnt_cheat_service.hpp b/stratosphere/dmnt/source/dmnt_cheat_service.hpp index abb43d523..422e8cff6 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_service.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_service.hpp @@ -73,7 +73,7 @@ class DmntCheatService final : public IServiceObject { Result GetFrozenAddressCount(Out<u64> out_count); Result GetFrozenAddresses(OutBuffer<FrozenAddressEntry> addresses, Out<u64> out_count, u64 offset); Result GetFrozenAddress(Out<FrozenAddressEntry> entry, u64 address); - Result EnableFrozenAddress(u64 address, u64 width); + Result EnableFrozenAddress(Out<u64> out_value, u64 address, u64 width); Result DisableFrozenAddress(u64 address); public: From 7e93ca0977e55b2de71c69bd17cf5f688db8bd6f Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Mon, 4 Mar 2019 22:40:35 -0800 Subject: [PATCH 484/489] dmnt: give hid access --- stratosphere/dmnt/dmnt.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stratosphere/dmnt/dmnt.json b/stratosphere/dmnt/dmnt.json index a0aeb6355..375e5d664 100644 --- a/stratosphere/dmnt/dmnt.json +++ b/stratosphere/dmnt/dmnt.json @@ -27,7 +27,8 @@ "bsdcfg", "set", "fsp-srv", - "fatal:u" + "fatal:u", + "hid" ], "service_host": [ "dmnt:-", From 7d2dd628ba0196acf962ae373c468c57337a4cd4 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 5 Mar 2019 00:53:45 -0800 Subject: [PATCH 485/489] dmnt-cheat: multi-nybble opcodes, update libstrat --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 7 +++++++ stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 4 ++++ stratosphere/libstratosphere | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index 9afc9edc3..3a7b95625 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -183,6 +183,9 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { } opcode.opcode = (CheatVmOpcodeType)(((first_dword >> 28) & 0xF)); + if (opcode.opcode >= CheatVmOpcodeType_ExtendedWidth) { + opcode.opcode = (CheatVmOpcodeType)((((u32)opcode.opcode) << 4) | ((first_dword >> 24) & 0xF)); + } switch (opcode.opcode) { case CheatVmOpcodeType_StoreStatic: @@ -294,6 +297,7 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { } } break; + case CheatVmOpcodeType_ExtendedWidth: default: /* Unrecognized instruction cannot be decoded. */ valid = false; @@ -631,6 +635,9 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { this->registers[cur_opcode.perform_math_reg.dst_reg_index] = res_val; } break; + default: + /* By default, we do a no-op. */ + break; } } } \ No newline at end of file diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index 2236dd9a4..d892479bc 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -34,6 +34,10 @@ enum CheatVmOpcodeType : u32 { /* These are not implemented by Gateway's VM. */ CheatVmOpcodeType_PerformArithmeticRegister = 9, + + /* This is a meta entry, and not a real opcode. */ + /* This is to facilitate multi-nybble instruction decoding in the future. */ + CheatVmOpcodeType_ExtendedWidth = 12, }; enum MemoryAccessType : u32 { diff --git a/stratosphere/libstratosphere b/stratosphere/libstratosphere index 9ce1dce44..82c67a62d 160000 --- a/stratosphere/libstratosphere +++ b/stratosphere/libstratosphere @@ -1 +1 @@ -Subproject commit 9ce1dce4400461311a17712628febd99b25ff335 +Subproject commit 82c67a62d69f04f656da495c696f264eea6fa63a From 88a6ef4cd7ebbbe3b2b2d3d40ef770fad35ad5cf Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 5 Mar 2019 00:56:17 -0800 Subject: [PATCH 486/489] ams: default USB 3.0 off (some users see issues) --- common/defaults/system_settings.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/defaults/system_settings.ini b/common/defaults/system_settings.ini index 91c7f7cfb..2d4d14d1f 100644 --- a/common/defaults/system_settings.ini +++ b/common/defaults/system_settings.ini @@ -3,7 +3,7 @@ upload_enabled = u8!0x0 ; Enable USB 3.0 superspeed for homebrew [usb] -usb30_force_enabled = u8!0x1 +usb30_force_enabled = u8!0x0 ; Atmosphere custom settings [atmosphere] ; Make the power menu's "reboot" button reboot to payload. From 8c86074da238db6ac2c79170a61a35ffe7ea9252 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 5 Mar 2019 01:20:18 -0800 Subject: [PATCH 487/489] dmnt-cheat: Add opcode to store register to memory --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 129 +++++++++++++++++---- stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 25 +++- 2 files changed, 127 insertions(+), 27 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index 3a7b95625..269b4a437 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -95,15 +95,15 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode *opcode) { this->LogToDebugFile("From Reg: %d\n", opcode->ldr_memory.load_from_reg); this->LogToDebugFile("Rel Addr: %lx\n", opcode->ldr_memory.rel_address); break; - case CheatVmOpcodeType_StoreToRegisterAddress: - this->LogToDebugFile("Opcode: Store Static to Register Address\n"); - this->LogToDebugFile("Bit Width: %x\n", opcode->str_regaddr.bit_width); - this->LogToDebugFile("Reg Idx: %x\n", opcode->str_regaddr.reg_index); - if (opcode->str_regaddr.add_offset_reg) { - this->LogToDebugFile("O Reg Idx: %x\n", opcode->str_regaddr.offset_reg_index); + case CheatVmOpcodeType_StoreStaticToAddress: + this->LogToDebugFile("Opcode: Store Static to Address\n"); + this->LogToDebugFile("Bit Width: %x\n", opcode->str_static.bit_width); + this->LogToDebugFile("Reg Idx: %x\n", opcode->str_static.reg_index); + if (opcode->str_static.add_offset_reg) { + this->LogToDebugFile("O Reg Idx: %x\n", opcode->str_static.offset_reg_index); } - this->LogToDebugFile("Incr Reg: %d\n", opcode->str_regaddr.increment_reg); - this->LogToDebugFile("Value: %lx\n", opcode->str_regaddr.value); + this->LogToDebugFile("Incr Reg: %d\n", opcode->str_static.increment_reg); + this->LogToDebugFile("Value: %lx\n", opcode->str_static.value); break; case CheatVmOpcodeType_PerformArithmeticStatic: this->LogToDebugFile("Opcode: Perform Static Arithmetic\n"); @@ -127,6 +127,23 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode *opcode) { this->LogToDebugFile("Src2 Idx: %x\n", opcode->perform_math_reg.src_reg_2_index); } break; + case CheatVmOpcodeType_StoreRegisterToAddress: + this->LogToDebugFile("Opcode: Store Register to Address\n"); + this->LogToDebugFile("Bit Width: %x\n", opcode->str_register.bit_width); + this->LogToDebugFile("S Reg Idx: %x\n", opcode->str_register.str_reg_index); + this->LogToDebugFile("A Reg Idx: %x\n", opcode->str_register.addr_reg_index); + this->LogToDebugFile("Incr Reg: %d\n", opcode->str_register.increment_reg); + switch (opcode->str_register.ofs_type) { + case StoreRegisterOffsetType_None: + break; + case StoreRegisterOffsetType_Reg: + this->LogToDebugFile("O Reg Idx: %x\n", opcode->str_register.ofs_reg_index); + break; + case StoreRegisterOffsetType_Imm: + this->LogToDebugFile("Rel Addr: %lx\n", opcode->str_register.rel_address); + break; + } + break; default: this->LogToDebugFile("Unknown opcode: %x\n", opcode->opcode); break; @@ -252,16 +269,16 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { opcode.ldr_memory.rel_address = ((u64)(first_dword & 0xFF) << 32ul) | ((u64)second_dword); } break; - case CheatVmOpcodeType_StoreToRegisterAddress: + case CheatVmOpcodeType_StoreStaticToAddress: { /* 6T0RIor0 VVVVVVVV VVVVVVVV */ /* Read additional words. */ - opcode.str_regaddr.bit_width = (first_dword >> 24) & 0xF; - opcode.str_regaddr.reg_index = ((first_dword >> 16) & 0xF); - opcode.str_regaddr.increment_reg = ((first_dword >> 12) & 0xF) != 0; - opcode.str_regaddr.add_offset_reg = ((first_dword >> 8) & 0xF) != 0; - opcode.str_regaddr.offset_reg_index = ((first_dword >> 4) & 0xF); - opcode.str_regaddr.value = (((u64)GetNextDword()) << 32ul) | ((u64)GetNextDword()); + opcode.str_static.bit_width = (first_dword >> 24) & 0xF; + opcode.str_static.reg_index = ((first_dword >> 16) & 0xF); + opcode.str_static.increment_reg = ((first_dword >> 12) & 0xF) != 0; + opcode.str_static.add_offset_reg = ((first_dword >> 8) & 0xF) != 0; + opcode.str_static.offset_reg_index = ((first_dword >> 4) & 0xF); + opcode.str_static.value = (((u64)GetNextDword()) << 32ul) | ((u64)GetNextDword()); } break; case CheatVmOpcodeType_PerformArithmeticStatic: @@ -297,6 +314,37 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { } } break; + case CheatVmOpcodeType_StoreRegisterToAddress: + { + /* ATSRIOra (aaaaaaaa) */ + /* A = opcode 10 */ + /* T = bit width */ + /* S = src register index */ + /* R = address register index */ + /* I = 1 if increment address register, 0 if not increment address register */ + /* O = offset type, 0 = None, 1 = Register, 2 = Immediate */ + /* r = offset register (for offset type 1) */ + /* a = relative address (for offset type 2) */ + opcode.str_register.bit_width = (first_dword >> 24) & 0xF; + opcode.str_register.str_reg_index = ((first_dword >> 20) & 0xF); + opcode.str_register.addr_reg_index = ((first_dword >> 16) & 0xF); + opcode.str_register.increment_reg = ((first_dword >> 12) & 0xF) != 0; + opcode.str_register.ofs_type = (StoreRegisterOffsetType)(((first_dword >> 8) & 0xF)); + opcode.str_register.ofs_reg_index = ((first_dword >> 4) & 0xF); + switch (opcode.str_register.ofs_type) { + case StoreRegisterOffsetType_None: + case StoreRegisterOffsetType_Reg: + /* Nothing more to do */ + break; + case StoreRegisterOffsetType_Imm: + opcode.str_register.rel_address = (((u64)(first_dword & 0xF) << 32ul) | ((u64)GetNextDword())); + break; + default: + opcode.str_register.ofs_type = StoreRegisterOffsetType_None; + break; + } + } + break; case CheatVmOpcodeType_ExtendedWidth: default: /* Unrecognized instruction cannot be decoded. */ @@ -502,26 +550,26 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { } } break; - case CheatVmOpcodeType_StoreToRegisterAddress: + case CheatVmOpcodeType_StoreStaticToAddress: { /* Calculate address. */ - u64 dst_address = this->registers[cur_opcode.str_regaddr.reg_index]; - u64 dst_value = cur_opcode.str_regaddr.value; - if (cur_opcode.str_regaddr.add_offset_reg) { - dst_address += this->registers[cur_opcode.str_regaddr.offset_reg_index]; + u64 dst_address = this->registers[cur_opcode.str_static.reg_index]; + u64 dst_value = cur_opcode.str_static.value; + if (cur_opcode.str_static.add_offset_reg) { + dst_address += this->registers[cur_opcode.str_static.offset_reg_index]; } /* Write value to memory. Gateway only writes on valid bitwidth. */ - switch (cur_opcode.str_regaddr.bit_width) { + switch (cur_opcode.str_static.bit_width) { case 1: case 2: case 4: case 8: - DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.str_regaddr.bit_width); + DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.str_static.bit_width); break; } /* Increment register if relevant. */ - if (cur_opcode.str_regaddr.increment_reg) { - this->registers[cur_opcode.str_regaddr.reg_index] += cur_opcode.str_regaddr.bit_width; + if (cur_opcode.str_static.increment_reg) { + this->registers[cur_opcode.str_static.reg_index] += cur_opcode.str_static.bit_width; } } break; @@ -635,6 +683,39 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { this->registers[cur_opcode.perform_math_reg.dst_reg_index] = res_val; } break; + case CheatVmOpcodeType_StoreRegisterToAddress: + { + /* Calculate address. */ + u64 dst_value = this->registers[cur_opcode.str_register.str_reg_index]; + u64 dst_address = this->registers[cur_opcode.str_register.addr_reg_index]; + switch (cur_opcode.str_register.ofs_type) { + case StoreRegisterOffsetType_None: + /* Nothing more to do */ + break; + case StoreRegisterOffsetType_Reg: + dst_address += this->registers[cur_opcode.str_register.ofs_reg_index]; + break; + case StoreRegisterOffsetType_Imm: + dst_address += cur_opcode.str_register.rel_address; + break; + } + + /* Write value to memory. Write only on valid bitwidth. */ + switch (cur_opcode.str_register.bit_width) { + case 1: + case 2: + case 4: + case 8: + DmntCheatManager::WriteCheatProcessMemoryForVm(dst_address, &dst_value, cur_opcode.str_register.bit_width); + break; + } + + /* Increment register if relevant. */ + if (cur_opcode.str_register.increment_reg) { + this->registers[cur_opcode.str_register.addr_reg_index] += cur_opcode.str_register.bit_width; + } + } + break; default: /* By default, we do a no-op. */ break; diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index d892479bc..e9cffa8bc 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -28,12 +28,13 @@ enum CheatVmOpcodeType : u32 { CheatVmOpcodeType_ControlLoop = 3, CheatVmOpcodeType_LoadRegisterStatic = 4, CheatVmOpcodeType_LoadRegisterMemory = 5, - CheatVmOpcodeType_StoreToRegisterAddress = 6, + CheatVmOpcodeType_StoreStaticToAddress = 6, CheatVmOpcodeType_PerformArithmeticStatic = 7, CheatVmOpcodeType_BeginKeypressConditionalBlock = 8, /* These are not implemented by Gateway's VM. */ CheatVmOpcodeType_PerformArithmeticRegister = 9, + CheatVmOpcodeType_StoreRegisterToAddress = 10, /* This is a meta entry, and not a real opcode. */ /* This is to facilitate multi-nybble instruction decoding in the future. */ @@ -70,6 +71,12 @@ enum RegisterArithmeticType : u32 { RegisterArithmeticType_None = 9, }; +enum StoreRegisterOffsetType : u32 { + StoreRegisterOffsetType_None = 0, + StoreRegisterOffsetType_Reg = 1, + StoreRegisterOffsetType_Imm = 2, +}; + union VmInt { u8 bit8; u16 bit16; @@ -114,7 +121,7 @@ struct LoadRegisterMemoryOpcode { u64 rel_address; }; -struct StoreToRegisterAddressOpcode { +struct StoreStaticToAddressOpcode { u32 bit_width; u32 reg_index; bool increment_reg; @@ -144,6 +151,17 @@ struct PerformArithmeticRegisterOpcode { VmInt value; }; +struct StoreRegisterToAddressOpcode { + u32 bit_width; + u32 str_reg_index; + u32 addr_reg_index; + bool increment_reg; + StoreRegisterOffsetType ofs_type; + u32 ofs_reg_index; + u64 rel_address; +}; + + struct CheatVmOpcode { CheatVmOpcodeType opcode; union { @@ -153,10 +171,11 @@ struct CheatVmOpcode { ControlLoopOpcode ctrl_loop; LoadRegisterStaticOpcode ldr_static; LoadRegisterMemoryOpcode ldr_memory; - StoreToRegisterAddressOpcode str_regaddr; + StoreStaticToAddressOpcode str_static; PerformArithmeticStaticOpcode perform_math_static; BeginKeypressConditionalOpcode begin_keypress_cond; PerformArithmeticRegisterOpcode perform_math_reg; + StoreRegisterToAddressOpcode str_register; }; }; From 853a57e4d4496727415964a35c4c8377e63959c3 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 5 Mar 2019 01:39:20 -0800 Subject: [PATCH 488/489] dmnt-cheat: Support nested conditionals in VM --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 57 ++++++++++++++++++---- stratosphere/dmnt/source/dmnt_cheat_vm.hpp | 2 + stratosphere/dmnt/source/dmnt_results.hpp | 4 +- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index 269b4a437..eded284cf 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -204,6 +204,17 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { opcode.opcode = (CheatVmOpcodeType)((((u32)opcode.opcode) << 4) | ((first_dword >> 24) & 0xF)); } + /* detect condition start. */ + switch (opcode.opcode) { + case CheatVmOpcodeType_BeginConditionalBlock: + case CheatVmOpcodeType_BeginKeypressConditionalBlock: + opcode.begin_conditional_block = true; + break; + default: + opcode.begin_conditional_block = false; + break; + } + switch (opcode.opcode) { case CheatVmOpcodeType_StoreStatic: { @@ -357,16 +368,32 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { } void DmntCheatVm::SkipConditionalBlock() { - CheatVmOpcode skip_opcode; - while (this->DecodeNextOpcode(&skip_opcode)) { - /* Decode instructions until we see end of conditional block. */ - /* NOTE: This is broken in gateway's implementation. */ - /* Gateway currently checks for "0x2" instead of "0x20000000" */ - /* In addition, they do a linear scan instead of correctly decoding opcodes. */ - /* This causes issues if "0x2" appears as an immediate in the conditional block... */ - if (skip_opcode.opcode == CheatVmOpcodeType_EndConditionalBlock) { - break; + if (this->condition_depth > 0) { + /* We want to continue until we're out of the current block. */ + size_t desired_depth = this->condition_depth - 1; + + CheatVmOpcode skip_opcode; + while (this->DecodeNextOpcode(&skip_opcode) && this->condition_depth > desired_depth) { + /* Decode instructions until we see end of the current conditional block. */ + /* NOTE: This is broken in gateway's implementation. */ + /* Gateway currently checks for "0x2" instead of "0x20000000" */ + /* In addition, they do a linear scan instead of correctly decoding opcodes. */ + /* This causes issues if "0x2" appears as an immediate in the conditional block... */ + + /* We also support nesting of conditional blocks, and Gateway does not. */ + if (skip_opcode.begin_conditional_block) { + this->condition_depth++; + } else if (skip_opcode.opcode == CheatVmOpcodeType_EndConditionalBlock) { + this->condition_depth--; + } } + } else { + /* Skipping, but this->condition_depth = 0. */ + /* This is an error condition. */ + /* However, I don't actually believe it is possible for this to happen. */ + /* I guess we'll throw a fatal error here, so as to encourage me to fix the VM */ + /* in the event that someone triggers it? I don't know how you'd do that. */ + fatalSimple(ResultDmntCheatVmInvalidCondDepth); } } @@ -402,6 +429,7 @@ void DmntCheatVm::ResetState() { this->loop_tops[i] = 0; } this->instruction_ptr = 0; + this->condition_depth = 0; this->decode_success = true; } @@ -452,6 +480,11 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { } this->LogOpcode(&cur_opcode); + /* Increment conditional depth, if relevant. */ + if (cur_opcode.begin_conditional_block) { + this->condition_depth++; + } + switch (cur_opcode.opcode) { case CheatVmOpcodeType_StoreStatic: { @@ -511,7 +544,11 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) { } break; case CheatVmOpcodeType_EndConditionalBlock: - /* There is nothing to do here. Just move on to the next instruction. */ + /* Decrement the condition depth. */ + /* We will assume, graciously, that mismatched conditional block ends are a nop. */ + if (this->condition_depth > 0) { + this->condition_depth--; + } break; case CheatVmOpcodeType_ControlLoop: if (cur_opcode.ctrl_loop.start_loop) { diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp index e9cffa8bc..469e36699 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.hpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.hpp @@ -164,6 +164,7 @@ struct StoreRegisterToAddressOpcode { struct CheatVmOpcode { CheatVmOpcodeType opcode; + bool begin_conditional_block; union { StoreStaticOpcode store_static; BeginConditionalOpcode begin_cond; @@ -186,6 +187,7 @@ class DmntCheatVm { private: size_t num_opcodes = 0; size_t instruction_ptr = 0; + size_t condition_depth = 0; bool decode_success = false; u32 program[MaximumProgramOpcodeCount] = {0}; u64 registers[NumRegisters] = {0}; diff --git a/stratosphere/dmnt/source/dmnt_results.hpp b/stratosphere/dmnt/source/dmnt_results.hpp index f4e908a12..42b43df89 100644 --- a/stratosphere/dmnt/source/dmnt_results.hpp +++ b/stratosphere/dmnt/source/dmnt_results.hpp @@ -33,4 +33,6 @@ static constexpr Result ResultDmntCheatInvalidCheat = MAKERESULT(Module_Dmnt, 6 static constexpr Result ResultDmntCheatInvalidFreezeWidth = MAKERESULT(Module_Dmnt, 6600); static constexpr Result ResultDmntCheatAddressAlreadyFrozen = MAKERESULT(Module_Dmnt, 6601); static constexpr Result ResultDmntCheatAddressNotFrozen = MAKERESULT(Module_Dmnt, 6602); -static constexpr Result ResultDmntCheatTooManyFrozenAddresses = MAKERESULT(Module_Dmnt, 6603); \ No newline at end of file +static constexpr Result ResultDmntCheatTooManyFrozenAddresses = MAKERESULT(Module_Dmnt, 6603); + +static constexpr Result ResultDmntCheatVmInvalidCondDepth = MAKERESULT(Module_Dmnt, 6700); \ No newline at end of file From 4e95397ed567dbb0e955d67b3f915b67ff58d275 Mon Sep 17 00:00:00 2001 From: Michael Scire <SciresM@gmail.com> Date: Tue, 5 Mar 2019 01:40:49 -0800 Subject: [PATCH 489/489] dmnt-cheat: const correctness --- stratosphere/dmnt/source/dmnt_cheat_vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp index eded284cf..e77b1f2d1 100644 --- a/stratosphere/dmnt/source/dmnt_cheat_vm.cpp +++ b/stratosphere/dmnt/source/dmnt_cheat_vm.cpp @@ -370,7 +370,7 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) { void DmntCheatVm::SkipConditionalBlock() { if (this->condition_depth > 0) { /* We want to continue until we're out of the current block. */ - size_t desired_depth = this->condition_depth - 1; + const size_t desired_depth = this->condition_depth - 1; CheatVmOpcode skip_opcode; while (this->DecodeNextOpcode(&skip_opcode) && this->condition_depth > desired_depth) {